mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-05 02:21:52 +09:00
Merge 6.1.130 into android14-6.1-lts
Changes in 6.1.130 arm64: mte: Do not allow PROT_MTE on MAP_HUGETLB user mappings md/md-bitmap: replace md_bitmap_status() with a new helper md_bitmap_get_stats() md/md-cluster: fix spares warnings for __le64 md/md-bitmap: add 'sync_size' into struct md_bitmap_stats md/md-bitmap: Synchronize bitmap_get_stats() with bitmap lifetime mm: update mark_victim tracepoints fields memcg: fix soft lockup in the OOM process spi: atmel-quadspi: Add support for configuring CS timing spi: atmel-quadspi: switch to use modern name spi: atmel-quadspi: Create `atmel_qspi_ops` to support newer SoC families spi: atmel-qspi: Memory barriers after memory-mapped I/O Bluetooth: qca: Support downloading board id specific NVM for WCN7850 Bluetooth: qca: Update firmware-name to support board specific nvm Bluetooth: qca: Fix poor RF performance for WCN6855 clk: mediatek: clk-mtk: Add dummy clock ops clk: mediatek: mt2701-vdec: fix conversion to mtk_clk_simple_probe clk: mediatek: mt2701-bdp: add missing dummy clk clk: mediatek: mt2701-img: add missing dummy clk ASoC: renesas: rz-ssi: Add a check for negative sample_space scsi: core: Handle depopulation and restoration in progress scsi: core: Do not retry I/Os during depopulation arm64: dts: mediatek: mt8183: Disable DSI display output by default arm64: dts: qcom: trim addresses to 8 digits arm64: dts: qcom: sm8450: Fix CDSP memory length tpm: Use managed allocation for bios event log tpm: Change to kvalloc() in eventlog/acpi.c soc: mediatek: mtk-devapc: Switch to devm_clk_get_enabled() soc: mediatek: mtk-devapc: Fix leaking IO map on error paths soc/mediatek: mtk-devapc: Convert to platform remove callback returning void soc: mediatek: mtk-devapc: Fix leaking IO map on driver remove media: Switch to use dev_err_probe() helper media: uvcvideo: Fix crash during unbind if gpio unit is in use media: uvcvideo: Refactor iterators media: uvcvideo: Only save async fh if success media: uvcvideo: Remove dangling pointers USB: gadget: core: create sysfs link between udc and gadget usb: gadget: core: flush gadget workqueue after device removal USB: gadget: f_midi: f_midi_complete to call queue_work ASoC: rockchip: i2s-tdm: fix shift config for SND_SOC_DAIFMT_DSP_[AB] powerpc/64s/mm: Move __real_pte stubs into hash-4k.h powerpc/64s: Rewrite __real_pte() and __rpte_to_hidx() as static inline ALSA: hda/realtek: Fixup ALC225 depop procedure powerpc/code-patching: Fix KASAN hit by not flagging text patching area as VM_ALLOC geneve: Fix use-after-free in geneve_find_dev(). ALSA: hda/cirrus: Correct the full scale volume set logic ibmvnic: Return error code on TX scrq flush fail ibmvnic: Introduce send sub-crq direct ibmvnic: Add stat for tx direct vs tx batched ibmvnic: Don't reference skb after sending to VIOS gtp: Suppress list corruption splat in gtp_net_exit_batch_rtnl(). geneve: Suppress list corruption splat in geneve_destroy_tunnels(). flow_dissector: Fix handling of mixed port and port-range keys flow_dissector: Fix port range key handling in BPF conversion net: Add non-RCU dev_getbyhwaddr() helper arp: switch to dev_getbyhwaddr() in arp_req_set_public() net: axienet: Set mac_managed_pm tcp: drop secpath at the same time as we currently drop dst drm/tidss: Add simple K2G manual reset drm/tidss: Fix race condition while handling interrupt registers drm/rcar-du: dsi: Fix PHY lock bit check bpf, test_run: Fix use-after-free issue in eth_skb_pkt_type() strparser: Add read_sock callback bpf: Fix wrong copied_seq calculation power: supply: da9150-fg: fix potential overflow nouveau/svm: fix missing folio unlock + put after make_device_exclusive_range() drm/msm/dpu: Don't leak bits_per_component into random DSC_ENC fields nvme/ioctl: add missing space in err message bpf: skip non exist keys in generic_map_lookup_batch drm/msm/dpu: Disable dither in phys encoder cleanup drm/i915: Make sure all planes in use by the joiner have their crtc included tee: optee: Fix supplicant wait loop drop_monitor: fix incorrect initialization order nfp: bpf: Add check for nfp_app_ctrl_msg_alloc() ASoC: fsl_micfil: Enable default case in micfil_set_quality() ALSA: hda: Add error check for snd_ctl_rename_id() in snd_hda_create_dig_out_ctls() ALSA: hda/conexant: Add quirk for HP ProBook 450 G4 mute LED acct: perform last write from workqueue acct: block access to kernel internal filesystems mm,madvise,hugetlb: check for 0-length range after end address adjustment mtd: rawnand: cadence: fix error code in cadence_nand_init() mtd: rawnand: cadence: use dma_map_resource for sdma address mtd: rawnand: cadence: fix incorrect device in dma_unmap_single smb: client: Add check for next_buffer in receive_encrypted_standard() EDAC/qcom: Correct interrupt enable register configuration ftrace: Correct preemption accounting for function tracing. ftrace: Do not add duplicate entries in subops manager ops x86/cpu/kvm: SRSO: Fix possible missing IBPB on VM-Exit block, bfq: split sync bfq_queues on a per-actuator basis block, bfq: fix bfqq uaf in bfq_limit_depth() media: mediatek: vcodec: Fix H264 multi stateless decoder smatch warning spi: atmel-quadspi: Avoid overwriting delay register settings spi: atmel-quadspi: Fix wrong register value written to MR netfilter: allow exp not to be removed in nf_ct_find_expectation IB/mlx5: Set and get correct qp_num for a DCT QP ovl: fix UAF in ovl_dentry_update_reval by moving dput() in ovl_link_up SUNRPC: convert RPC_TASK_* constants to enum SUNRPC: Prevent looping due to rpc_signal_task() races scsi: core: Clear driver private data when retrying request RDMA/mlx5: Fix bind QP error cleanup flow sunrpc: suppress warnings for unused procfs functions ALSA: usb-audio: Avoid dropping MIDI events at closing multiple ports Bluetooth: L2CAP: Fix L2CAP_ECRED_CONN_RSP response afs: remove variable nr_servers afs: Make it possible to find the volumes that are using a server afs: Fix the server_list to unuse a displaced server rather than putting it net: loopback: Avoid sending IP packets without an Ethernet header net: set the minimum for net_hotdata.netdev_budget_usecs net/ipv4: add tracepoint for icmp_send ipv4: icmp: Pass full DS field to ip_route_input() ipv4: icmp: Unmask upper DSCP bits in icmp_route_lookup() ipvlan: Unmask upper DSCP bits in ipvlan_process_v4_outbound() ipv4: Convert icmp_route_lookup() to dscp_t. ipv4: Convert ip_route_input() to dscp_t. ipvlan: Prepare ipvlan_process_v4_outbound() to future .flowi4_tos conversion. ipvlan: ensure network headers are in skb linear part net: cadence: macb: Synchronize stats calculations ASoC: es8328: fix route from DAC to output ipvs: Always clear ipvs_property flag in skb_scrub_packet() tcp: Defer ts_recent changes until req is owned net: Clear old fragment checksum value in napi_reuse_skb net: mvpp2: cls: Fixed Non IP flow, with vlan tag flow defination. net/mlx5: IRQ, Fix null string in debug print include: net: add static inline dst_dev_overhead() to dst.h net: ipv6: seg6_iptunnel: mitigate 2-realloc issue net: ipv6: fix dst ref loop on input in seg6 lwt net: ipv6: rpl_iptunnel: mitigate 2-realloc issue net: ipv6: fix dst ref loop on input in rpl lwt mm: Don't pin ZERO_PAGE in pin_user_pages() uprobes: Reject the shared zeropage in uprobe_write_opcode() io_uring/net: save msg_control for compat x86/CPU: Fix warm boot hang regression on AMD SC1100 SoC systems phy: rockchip: naneng-combphy: compatible reset with old DT tracing: Fix bad hist from corrupting named_triggers list ftrace: Avoid potential division by zero in function_stat_show() ALSA: usb-audio: Re-add sample rate quirk for Pioneer DJM-900NXS2 perf/x86: Fix low freqency setting issue perf/core: Fix low freq setting via IOC_PERIOD drm/amd/display: Disable PSR-SU on eDP panels drm/amd/display: Fix HPD after gpu reset i2c: npcm: disable interrupt enable bit before devm_request_irq usbnet: gl620a: fix endpoint checking in genelink_bind() net: enetc: fix the off-by-one issue in enetc_map_tx_buffs() net: enetc: keep track of correct Tx BD count in enetc_map_tx_tso_buffs() net: enetc: update UDP checksum when updating originTimestamp field net: enetc: correct the xdp_tx statistics net: enetc: fix the off-by-one issue in enetc_map_tx_tso_buffs() phy: tegra: xusb: reset VBUS & ID OVERRIDE phy: exynos5-usbdrd: fix MPLL_MULTIPLIER and SSC_REFCLKSEL masks in refclk mptcp: always handle address removal under msk socket lock mptcp: reset when MPTCP opts are dropped after join vmlinux.lds: Ensure that const vars with relocations are mapped R/O sched/core: Prevent rescheduling when interrupts are disabled riscv/futex: sign extend compare value in atomic cmpxchg drm/amd/display: fixed integer types and null check locations amdgpu/pm/legacy: fix suspend/resume issues intel_idle: Handle older CPUs, which stop the TSC in deeper C states, correctly ptrace: Introduce exception_ip arch hook mm/memory: Use exception ip to search exception tables Squashfs: check the inode number is not the invalid value of zero pfifo_tail_enqueue: Drop new packet when sch->limit == 0 media: mtk-vcodec: potential null pointer deference in SCP Linux 6.1.130 Change-Id: Ida62c0b803cfd88c5a0afc42fe7cd192e694feeb Signed-off-by: Greg Kroah-Hartman <gregkh@google.com>
This commit is contained in:
@@ -113,6 +113,12 @@ pages:
|
||||
This also leads to limitations: there are only 31-10==21 bits available for a
|
||||
counter that increments 10 bits at a time.
|
||||
|
||||
* Because of that limitation, special handling is applied to the zero pages
|
||||
when using FOLL_PIN. We only pretend to pin a zero page - we don't alter its
|
||||
refcount or pincount at all (it is permanent, so there's no need). The
|
||||
unpinning functions also don't do anything to a zero page. This is
|
||||
transparent to the caller.
|
||||
|
||||
* Callers must specifically request "dma-pinned tracking of pages". In other
|
||||
words, just calling get_user_pages() will not suffice; a new set of functions,
|
||||
pin_user_page() and related, must be used.
|
||||
|
||||
@@ -112,7 +112,7 @@ Functions
|
||||
Callbacks
|
||||
=========
|
||||
|
||||
There are six callbacks:
|
||||
There are seven callbacks:
|
||||
|
||||
::
|
||||
|
||||
@@ -182,6 +182,13 @@ There are six callbacks:
|
||||
the length of the message. skb->len - offset may be greater
|
||||
then full_len since strparser does not trim the skb.
|
||||
|
||||
::
|
||||
|
||||
int (*read_sock)(struct strparser *strp, read_descriptor_t *desc,
|
||||
sk_read_actor_t recv_actor);
|
||||
|
||||
The read_sock callback is used by strparser instead of
|
||||
sock->ops->read_sock, if provided.
|
||||
::
|
||||
|
||||
int (*read_sock_done)(struct strparser *strp, int err);
|
||||
|
||||
2
Makefile
2
Makefile
@@ -1,7 +1,7 @@
|
||||
# SPDX-License-Identifier: GPL-2.0
|
||||
VERSION = 6
|
||||
PATCHLEVEL = 1
|
||||
SUBLEVEL = 129
|
||||
SUBLEVEL = 130
|
||||
EXTRAVERSION =
|
||||
NAME = Curry Ramen
|
||||
|
||||
|
||||
@@ -155,6 +155,8 @@ static inline long regs_return_value(struct pt_regs *regs)
|
||||
}
|
||||
|
||||
#define instruction_pointer(regs) ((regs)->cp0_epc)
|
||||
extern unsigned long exception_ip(struct pt_regs *regs);
|
||||
#define exception_ip(regs) exception_ip(regs)
|
||||
#define profile_pc(regs) instruction_pointer(regs)
|
||||
|
||||
extern asmlinkage long syscall_trace_enter(struct pt_regs *regs);
|
||||
|
||||
@@ -31,6 +31,7 @@
|
||||
#include <linux/seccomp.h>
|
||||
#include <linux/ftrace.h>
|
||||
|
||||
#include <asm/branch.h>
|
||||
#include <asm/byteorder.h>
|
||||
#include <asm/cpu.h>
|
||||
#include <asm/cpu-info.h>
|
||||
@@ -48,6 +49,12 @@
|
||||
#define CREATE_TRACE_POINTS
|
||||
#include <trace/events/syscalls.h>
|
||||
|
||||
unsigned long exception_ip(struct pt_regs *regs)
|
||||
{
|
||||
return exception_epc(regs);
|
||||
}
|
||||
EXPORT_SYMBOL(exception_ip);
|
||||
|
||||
/*
|
||||
* Called by kernel/ptrace.c when detaching..
|
||||
*
|
||||
|
||||
@@ -93,7 +93,7 @@ futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr,
|
||||
_ASM_EXTABLE_UACCESS_ERR(1b, 3b, %[r]) \
|
||||
_ASM_EXTABLE_UACCESS_ERR(2b, 3b, %[r]) \
|
||||
: [r] "+r" (ret), [v] "=&r" (val), [u] "+m" (*uaddr), [t] "=&r" (tmp)
|
||||
: [ov] "Jr" (oldval), [nv] "Jr" (newval)
|
||||
: [ov] "Jr" ((long)(int)oldval), [nv] "Jr" (newval)
|
||||
: "memory");
|
||||
__disable_user_access();
|
||||
|
||||
|
||||
@@ -2507,7 +2507,8 @@ config CPU_IBPB_ENTRY
|
||||
depends on CPU_SUP_AMD && X86_64
|
||||
default y
|
||||
help
|
||||
Compile the kernel with support for the retbleed=ibpb mitigation.
|
||||
Compile the kernel with support for the retbleed=ibpb and
|
||||
spec_rstack_overflow={ibpb,ibpb-vmexit} mitigations.
|
||||
|
||||
config CPU_IBRS_ENTRY
|
||||
bool "Enable IBRS on kernel entry"
|
||||
|
||||
@@ -621,7 +621,7 @@ int x86_pmu_hw_config(struct perf_event *event)
|
||||
if (event->attr.type == event->pmu->type)
|
||||
event->hw.config |= event->attr.config & X86_RAW_EVENT_MASK;
|
||||
|
||||
if (event->attr.sample_period && x86_pmu.limit_period) {
|
||||
if (!event->attr.freq && x86_pmu.limit_period) {
|
||||
s64 left = event->attr.sample_period;
|
||||
x86_pmu.limit_period(event, &left);
|
||||
if (left > event->attr.sample_period)
|
||||
|
||||
@@ -1092,6 +1092,8 @@ do_cmd_auto:
|
||||
|
||||
case RETBLEED_MITIGATION_IBPB:
|
||||
setup_force_cpu_cap(X86_FEATURE_ENTRY_IBPB);
|
||||
setup_force_cpu_cap(X86_FEATURE_IBPB_ON_VMEXIT);
|
||||
mitigate_smt = true;
|
||||
|
||||
/*
|
||||
* IBPB on entry already obviates the need for
|
||||
@@ -1101,8 +1103,6 @@ do_cmd_auto:
|
||||
setup_clear_cpu_cap(X86_FEATURE_UNRET);
|
||||
setup_clear_cpu_cap(X86_FEATURE_RETHUNK);
|
||||
|
||||
mitigate_smt = true;
|
||||
|
||||
/*
|
||||
* There is no need for RSB filling: entry_ibpb() ensures
|
||||
* all predictions, including the RSB, are invalidated,
|
||||
@@ -2607,6 +2607,7 @@ static void __init srso_select_mitigation(void)
|
||||
if (IS_ENABLED(CONFIG_CPU_IBPB_ENTRY)) {
|
||||
if (has_microcode) {
|
||||
setup_force_cpu_cap(X86_FEATURE_ENTRY_IBPB);
|
||||
setup_force_cpu_cap(X86_FEATURE_IBPB_ON_VMEXIT);
|
||||
srso_mitigation = SRSO_MITIGATION_IBPB;
|
||||
|
||||
/*
|
||||
@@ -2616,6 +2617,13 @@ static void __init srso_select_mitigation(void)
|
||||
*/
|
||||
setup_clear_cpu_cap(X86_FEATURE_UNRET);
|
||||
setup_clear_cpu_cap(X86_FEATURE_RETHUNK);
|
||||
|
||||
/*
|
||||
* There is no need for RSB filling: entry_ibpb() ensures
|
||||
* all predictions, including the RSB, are invalidated,
|
||||
* regardless of IBPB implementation.
|
||||
*/
|
||||
setup_clear_cpu_cap(X86_FEATURE_RSB_VMEXIT);
|
||||
}
|
||||
} else {
|
||||
pr_err("WARNING: kernel not compiled with CPU_IBPB_ENTRY.\n");
|
||||
@@ -2624,8 +2632,8 @@ static void __init srso_select_mitigation(void)
|
||||
break;
|
||||
|
||||
case SRSO_CMD_IBPB_ON_VMEXIT:
|
||||
if (IS_ENABLED(CONFIG_CPU_SRSO)) {
|
||||
if (!boot_cpu_has(X86_FEATURE_ENTRY_IBPB) && has_microcode) {
|
||||
if (IS_ENABLED(CONFIG_CPU_IBPB_ENTRY)) {
|
||||
if (has_microcode) {
|
||||
setup_force_cpu_cap(X86_FEATURE_IBPB_ON_VMEXIT);
|
||||
srso_mitigation = SRSO_MITIGATION_IBPB_ON_VMEXIT;
|
||||
|
||||
@@ -2637,9 +2645,9 @@ static void __init srso_select_mitigation(void)
|
||||
setup_clear_cpu_cap(X86_FEATURE_RSB_VMEXIT);
|
||||
}
|
||||
} else {
|
||||
pr_err("WARNING: kernel not compiled with CPU_SRSO.\n");
|
||||
pr_err("WARNING: kernel not compiled with CPU_IBPB_ENTRY.\n");
|
||||
goto pred_cmd;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
|
||||
@@ -153,8 +153,8 @@ static void geode_configure(void)
|
||||
u8 ccr3;
|
||||
local_irq_save(flags);
|
||||
|
||||
/* Suspend on halt power saving and enable #SUSP pin */
|
||||
setCx86(CX86_CCR2, getCx86(CX86_CCR2) | 0x88);
|
||||
/* Suspend on halt power saving */
|
||||
setCx86(CX86_CCR2, getCx86(CX86_CCR2) | 0x08);
|
||||
|
||||
ccr3 = getCx86(CX86_CCR3);
|
||||
setCx86(CX86_CCR3, (ccr3 & 0x0f) | 0x10); /* enable MAPEN */
|
||||
|
||||
@@ -704,6 +704,46 @@ void bfq_bfqq_move(struct bfq_data *bfqd, struct bfq_queue *bfqq,
|
||||
bfq_put_queue(bfqq);
|
||||
}
|
||||
|
||||
static void bfq_sync_bfqq_move(struct bfq_data *bfqd,
|
||||
struct bfq_queue *sync_bfqq,
|
||||
struct bfq_io_cq *bic,
|
||||
struct bfq_group *bfqg,
|
||||
unsigned int act_idx)
|
||||
{
|
||||
struct bfq_queue *bfqq;
|
||||
|
||||
if (!sync_bfqq->new_bfqq && !bfq_bfqq_coop(sync_bfqq)) {
|
||||
/* We are the only user of this bfqq, just move it */
|
||||
if (sync_bfqq->entity.sched_data != &bfqg->sched_data)
|
||||
bfq_bfqq_move(bfqd, sync_bfqq, bfqg);
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* The queue was merged to a different queue. Check
|
||||
* that the merge chain still belongs to the same
|
||||
* cgroup.
|
||||
*/
|
||||
for (bfqq = sync_bfqq; bfqq; bfqq = bfqq->new_bfqq)
|
||||
if (bfqq->entity.sched_data != &bfqg->sched_data)
|
||||
break;
|
||||
if (bfqq) {
|
||||
/*
|
||||
* Some queue changed cgroup so the merge is not valid
|
||||
* anymore. We cannot easily just cancel the merge (by
|
||||
* clearing new_bfqq) as there may be other processes
|
||||
* using this queue and holding refs to all queues
|
||||
* below sync_bfqq->new_bfqq. Similarly if the merge
|
||||
* already happened, we need to detach from bfqq now
|
||||
* so that we cannot merge bio to a request from the
|
||||
* old cgroup.
|
||||
*/
|
||||
bfq_put_cooperator(sync_bfqq);
|
||||
bfq_release_process_ref(bfqd, sync_bfqq);
|
||||
bic_set_bfqq(bic, NULL, true, act_idx);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* __bfq_bic_change_cgroup - move @bic to @bfqg.
|
||||
* @bfqd: the queue descriptor.
|
||||
@@ -714,60 +754,25 @@ void bfq_bfqq_move(struct bfq_data *bfqd, struct bfq_queue *bfqq,
|
||||
* sure that the reference to cgroup is valid across the call (see
|
||||
* comments in bfq_bic_update_cgroup on this issue)
|
||||
*/
|
||||
static void *__bfq_bic_change_cgroup(struct bfq_data *bfqd,
|
||||
static void __bfq_bic_change_cgroup(struct bfq_data *bfqd,
|
||||
struct bfq_io_cq *bic,
|
||||
struct bfq_group *bfqg)
|
||||
{
|
||||
struct bfq_queue *async_bfqq = bic_to_bfqq(bic, false);
|
||||
struct bfq_queue *sync_bfqq = bic_to_bfqq(bic, true);
|
||||
struct bfq_entity *entity;
|
||||
unsigned int act_idx;
|
||||
|
||||
if (async_bfqq) {
|
||||
entity = &async_bfqq->entity;
|
||||
for (act_idx = 0; act_idx < bfqd->num_actuators; act_idx++) {
|
||||
struct bfq_queue *async_bfqq = bic_to_bfqq(bic, false, act_idx);
|
||||
struct bfq_queue *sync_bfqq = bic_to_bfqq(bic, true, act_idx);
|
||||
|
||||
if (entity->sched_data != &bfqg->sched_data) {
|
||||
bic_set_bfqq(bic, NULL, false);
|
||||
if (async_bfqq &&
|
||||
async_bfqq->entity.sched_data != &bfqg->sched_data) {
|
||||
bic_set_bfqq(bic, NULL, false, act_idx);
|
||||
bfq_release_process_ref(bfqd, async_bfqq);
|
||||
}
|
||||
|
||||
if (sync_bfqq)
|
||||
bfq_sync_bfqq_move(bfqd, sync_bfqq, bic, bfqg, act_idx);
|
||||
}
|
||||
|
||||
if (sync_bfqq) {
|
||||
if (!sync_bfqq->new_bfqq && !bfq_bfqq_coop(sync_bfqq)) {
|
||||
/* We are the only user of this bfqq, just move it */
|
||||
if (sync_bfqq->entity.sched_data != &bfqg->sched_data)
|
||||
bfq_bfqq_move(bfqd, sync_bfqq, bfqg);
|
||||
} else {
|
||||
struct bfq_queue *bfqq;
|
||||
|
||||
/*
|
||||
* The queue was merged to a different queue. Check
|
||||
* that the merge chain still belongs to the same
|
||||
* cgroup.
|
||||
*/
|
||||
for (bfqq = sync_bfqq; bfqq; bfqq = bfqq->new_bfqq)
|
||||
if (bfqq->entity.sched_data !=
|
||||
&bfqg->sched_data)
|
||||
break;
|
||||
if (bfqq) {
|
||||
/*
|
||||
* Some queue changed cgroup so the merge is
|
||||
* not valid anymore. We cannot easily just
|
||||
* cancel the merge (by clearing new_bfqq) as
|
||||
* there may be other processes using this
|
||||
* queue and holding refs to all queues below
|
||||
* sync_bfqq->new_bfqq. Similarly if the merge
|
||||
* already happened, we need to detach from
|
||||
* bfqq now so that we cannot merge bio to a
|
||||
* request from the old cgroup.
|
||||
*/
|
||||
bfq_put_cooperator(sync_bfqq);
|
||||
bic_set_bfqq(bic, NULL, true);
|
||||
bfq_release_process_ref(bfqd, sync_bfqq);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return bfqg;
|
||||
}
|
||||
|
||||
void bfq_bic_update_cgroup(struct bfq_io_cq *bic, struct bio *bio)
|
||||
|
||||
@@ -377,16 +377,23 @@ static const unsigned long bfq_late_stable_merging = 600;
|
||||
#define RQ_BIC(rq) ((struct bfq_io_cq *)((rq)->elv.priv[0]))
|
||||
#define RQ_BFQQ(rq) ((rq)->elv.priv[1])
|
||||
|
||||
struct bfq_queue *bic_to_bfqq(struct bfq_io_cq *bic, bool is_sync)
|
||||
struct bfq_queue *bic_to_bfqq(struct bfq_io_cq *bic, bool is_sync,
|
||||
unsigned int actuator_idx)
|
||||
{
|
||||
return bic->bfqq[is_sync];
|
||||
if (is_sync)
|
||||
return bic->bfqq[1][actuator_idx];
|
||||
|
||||
return bic->bfqq[0][actuator_idx];
|
||||
}
|
||||
|
||||
static void bfq_put_stable_ref(struct bfq_queue *bfqq);
|
||||
|
||||
void bic_set_bfqq(struct bfq_io_cq *bic, struct bfq_queue *bfqq, bool is_sync)
|
||||
void bic_set_bfqq(struct bfq_io_cq *bic,
|
||||
struct bfq_queue *bfqq,
|
||||
bool is_sync,
|
||||
unsigned int actuator_idx)
|
||||
{
|
||||
struct bfq_queue *old_bfqq = bic->bfqq[is_sync];
|
||||
struct bfq_queue *old_bfqq = bic->bfqq[is_sync][actuator_idx];
|
||||
|
||||
/* Clear bic pointer if bfqq is detached from this bic */
|
||||
if (old_bfqq && old_bfqq->bic == bic)
|
||||
@@ -405,7 +412,10 @@ void bic_set_bfqq(struct bfq_io_cq *bic, struct bfq_queue *bfqq, bool is_sync)
|
||||
* we cancel the stable merge if
|
||||
* bic->stable_merge_bfqq == bfqq.
|
||||
*/
|
||||
bic->bfqq[is_sync] = bfqq;
|
||||
if (is_sync)
|
||||
bic->bfqq[1][actuator_idx] = bfqq;
|
||||
else
|
||||
bic->bfqq[0][actuator_idx] = bfqq;
|
||||
|
||||
if (bfqq && bic->stable_merge_bfqq == bfqq) {
|
||||
/*
|
||||
@@ -571,23 +581,31 @@ static struct request *bfq_choose_req(struct bfq_data *bfqd,
|
||||
#define BFQ_LIMIT_INLINE_DEPTH 16
|
||||
|
||||
#ifdef CONFIG_BFQ_GROUP_IOSCHED
|
||||
static bool bfqq_request_over_limit(struct bfq_queue *bfqq, int limit)
|
||||
static bool bfqq_request_over_limit(struct bfq_data *bfqd,
|
||||
struct bfq_io_cq *bic, blk_opf_t opf,
|
||||
unsigned int act_idx, int limit)
|
||||
{
|
||||
struct bfq_data *bfqd = bfqq->bfqd;
|
||||
struct bfq_entity *entity = &bfqq->entity;
|
||||
struct bfq_entity *inline_entities[BFQ_LIMIT_INLINE_DEPTH];
|
||||
struct bfq_entity **entities = inline_entities;
|
||||
int depth, level, alloc_depth = BFQ_LIMIT_INLINE_DEPTH;
|
||||
int class_idx = bfqq->ioprio_class - 1;
|
||||
int alloc_depth = BFQ_LIMIT_INLINE_DEPTH;
|
||||
struct bfq_sched_data *sched_data;
|
||||
struct bfq_entity *entity;
|
||||
struct bfq_queue *bfqq;
|
||||
unsigned long wsum;
|
||||
bool ret = false;
|
||||
|
||||
if (!entity->on_st_or_in_serv)
|
||||
return false;
|
||||
int depth;
|
||||
int level;
|
||||
|
||||
retry:
|
||||
spin_lock_irq(&bfqd->lock);
|
||||
bfqq = bic_to_bfqq(bic, op_is_sync(opf), act_idx);
|
||||
if (!bfqq)
|
||||
goto out;
|
||||
|
||||
entity = &bfqq->entity;
|
||||
if (!entity->on_st_or_in_serv)
|
||||
goto out;
|
||||
|
||||
/* +1 for bfqq entity, root cgroup not included */
|
||||
depth = bfqg_to_blkg(bfqq_group(bfqq))->blkcg->css.cgroup->level + 1;
|
||||
if (depth > alloc_depth) {
|
||||
@@ -632,7 +650,7 @@ retry:
|
||||
* class.
|
||||
*/
|
||||
wsum = 0;
|
||||
for (i = 0; i <= class_idx; i++) {
|
||||
for (i = 0; i <= bfqq->ioprio_class - 1; i++) {
|
||||
wsum = wsum * IOPRIO_BE_NR +
|
||||
sched_data->service_tree[i].wsum;
|
||||
}
|
||||
@@ -655,7 +673,9 @@ out:
|
||||
return ret;
|
||||
}
|
||||
#else
|
||||
static bool bfqq_request_over_limit(struct bfq_queue *bfqq, int limit)
|
||||
static bool bfqq_request_over_limit(struct bfq_data *bfqd,
|
||||
struct bfq_io_cq *bic, blk_opf_t opf,
|
||||
unsigned int act_idx, int limit)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
@@ -680,9 +700,9 @@ static void bfq_limit_depth(blk_opf_t opf, struct blk_mq_alloc_data *data)
|
||||
{
|
||||
struct bfq_data *bfqd = data->q->elevator->elevator_data;
|
||||
struct bfq_io_cq *bic = bfq_bic_lookup(data->q);
|
||||
struct bfq_queue *bfqq = bic ? bic_to_bfqq(bic, op_is_sync(opf)) : NULL;
|
||||
int depth;
|
||||
unsigned limit = data->q->nr_requests;
|
||||
unsigned int act_idx;
|
||||
|
||||
/* Sync reads have full depth available */
|
||||
if (op_is_sync(opf) && !op_is_write(opf)) {
|
||||
@@ -692,14 +712,22 @@ static void bfq_limit_depth(blk_opf_t opf, struct blk_mq_alloc_data *data)
|
||||
limit = (limit * depth) >> bfqd->full_depth_shift;
|
||||
}
|
||||
|
||||
/*
|
||||
* Does queue (or any parent entity) exceed number of requests that
|
||||
* should be available to it? Heavily limit depth so that it cannot
|
||||
* consume more available requests and thus starve other entities.
|
||||
*/
|
||||
if (bfqq && bfqq_request_over_limit(bfqq, limit))
|
||||
depth = 1;
|
||||
for (act_idx = 0; bic && act_idx < bfqd->num_actuators; act_idx++) {
|
||||
/* Fast path to check if bfqq is already allocated. */
|
||||
if (!bic_to_bfqq(bic, op_is_sync(opf), act_idx))
|
||||
continue;
|
||||
|
||||
/*
|
||||
* Does queue (or any parent entity) exceed number of
|
||||
* requests that should be available to it? Heavily
|
||||
* limit depth so that it cannot consume more
|
||||
* available requests and thus starve other entities.
|
||||
*/
|
||||
if (bfqq_request_over_limit(bfqd, bic, opf, act_idx, limit)) {
|
||||
depth = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
bfq_log(bfqd, "[%s] wr_busy %d sync %d depth %u",
|
||||
__func__, bfqd->wr_busy_queues, op_is_sync(opf), depth);
|
||||
if (depth)
|
||||
@@ -1820,6 +1848,18 @@ static bool bfq_bfqq_higher_class_or_weight(struct bfq_queue *bfqq,
|
||||
return bfqq_weight > in_serv_weight;
|
||||
}
|
||||
|
||||
/*
|
||||
* Get the index of the actuator that will serve bio.
|
||||
*/
|
||||
static unsigned int bfq_actuator_index(struct bfq_data *bfqd, struct bio *bio)
|
||||
{
|
||||
/*
|
||||
* Multi-actuator support not complete yet, so always return 0
|
||||
* for the moment (to keep incomplete mechanisms off).
|
||||
*/
|
||||
return 0;
|
||||
}
|
||||
|
||||
static bool bfq_better_to_idle(struct bfq_queue *bfqq);
|
||||
|
||||
static void bfq_bfqq_handle_idle_busy_switch(struct bfq_data *bfqd,
|
||||
@@ -2150,7 +2190,7 @@ static void bfq_check_waker(struct bfq_data *bfqd, struct bfq_queue *bfqq,
|
||||
* We reset waker detection logic also if too much time has passed
|
||||
* since the first detection. If wakeups are rare, pointless idling
|
||||
* doesn't hurt throughput that much. The condition below makes sure
|
||||
* we do not uselessly idle blocking waker in more than 1/64 cases.
|
||||
* we do not uselessly idle blocking waker in more than 1/64 cases.
|
||||
*/
|
||||
if (bfqd->last_completed_rq_bfqq !=
|
||||
bfqq->tentative_waker_bfqq ||
|
||||
@@ -2486,7 +2526,8 @@ static bool bfq_bio_merge(struct request_queue *q, struct bio *bio,
|
||||
*/
|
||||
bfq_bic_update_cgroup(bic, bio);
|
||||
|
||||
bfqd->bio_bfqq = bic_to_bfqq(bic, op_is_sync(bio->bi_opf));
|
||||
bfqd->bio_bfqq = bic_to_bfqq(bic, op_is_sync(bio->bi_opf),
|
||||
bfq_actuator_index(bfqd, bio));
|
||||
} else {
|
||||
bfqd->bio_bfqq = NULL;
|
||||
}
|
||||
@@ -3188,7 +3229,7 @@ static struct bfq_queue *bfq_merge_bfqqs(struct bfq_data *bfqd,
|
||||
/*
|
||||
* Merge queues (that is, let bic redirect its requests to new_bfqq)
|
||||
*/
|
||||
bic_set_bfqq(bic, new_bfqq, true);
|
||||
bic_set_bfqq(bic, new_bfqq, true, bfqq->actuator_idx);
|
||||
bfq_mark_bfqq_coop(new_bfqq);
|
||||
/*
|
||||
* new_bfqq now belongs to at least two bics (it is a shared queue):
|
||||
@@ -4818,11 +4859,8 @@ check_queue:
|
||||
*/
|
||||
if (bfq_bfqq_wait_request(bfqq) ||
|
||||
(bfqq->dispatched != 0 && bfq_better_to_idle(bfqq))) {
|
||||
struct bfq_queue *async_bfqq =
|
||||
bfqq->bic && bfqq->bic->bfqq[0] &&
|
||||
bfq_bfqq_busy(bfqq->bic->bfqq[0]) &&
|
||||
bfqq->bic->bfqq[0]->next_rq ?
|
||||
bfqq->bic->bfqq[0] : NULL;
|
||||
unsigned int act_idx = bfqq->actuator_idx;
|
||||
struct bfq_queue *async_bfqq = NULL;
|
||||
struct bfq_queue *blocked_bfqq =
|
||||
!hlist_empty(&bfqq->woken_list) ?
|
||||
container_of(bfqq->woken_list.first,
|
||||
@@ -4830,6 +4868,10 @@ check_queue:
|
||||
woken_list_node)
|
||||
: NULL;
|
||||
|
||||
if (bfqq->bic && bfqq->bic->bfqq[0][act_idx] &&
|
||||
bfq_bfqq_busy(bfqq->bic->bfqq[0][act_idx]) &&
|
||||
bfqq->bic->bfqq[0][act_idx]->next_rq)
|
||||
async_bfqq = bfqq->bic->bfqq[0][act_idx];
|
||||
/*
|
||||
* The next four mutually-exclusive ifs decide
|
||||
* whether to try injection, and choose the queue to
|
||||
@@ -4914,7 +4956,7 @@ check_queue:
|
||||
icq_to_bic(async_bfqq->next_rq->elv.icq) == bfqq->bic &&
|
||||
bfq_serv_to_charge(async_bfqq->next_rq, async_bfqq) <=
|
||||
bfq_bfqq_budget_left(async_bfqq))
|
||||
bfqq = bfqq->bic->bfqq[0];
|
||||
bfqq = bfqq->bic->bfqq[0][act_idx];
|
||||
else if (bfqq->waker_bfqq &&
|
||||
bfq_bfqq_busy(bfqq->waker_bfqq) &&
|
||||
bfqq->waker_bfqq->next_rq &&
|
||||
@@ -5375,48 +5417,54 @@ static void bfq_exit_bfqq(struct bfq_data *bfqd, struct bfq_queue *bfqq)
|
||||
bfq_release_process_ref(bfqd, bfqq);
|
||||
}
|
||||
|
||||
static void bfq_exit_icq_bfqq(struct bfq_io_cq *bic, bool is_sync)
|
||||
static void bfq_exit_icq_bfqq(struct bfq_io_cq *bic, bool is_sync,
|
||||
unsigned int actuator_idx)
|
||||
{
|
||||
struct bfq_queue *bfqq = bic_to_bfqq(bic, is_sync);
|
||||
struct bfq_queue *bfqq = bic_to_bfqq(bic, is_sync, actuator_idx);
|
||||
struct bfq_data *bfqd;
|
||||
|
||||
if (bfqq)
|
||||
bfqd = bfqq->bfqd; /* NULL if scheduler already exited */
|
||||
|
||||
if (bfqq && bfqd) {
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&bfqd->lock, flags);
|
||||
bic_set_bfqq(bic, NULL, is_sync);
|
||||
bic_set_bfqq(bic, NULL, is_sync, actuator_idx);
|
||||
bfq_exit_bfqq(bfqd, bfqq);
|
||||
spin_unlock_irqrestore(&bfqd->lock, flags);
|
||||
}
|
||||
}
|
||||
|
||||
static void bfq_exit_icq(struct io_cq *icq)
|
||||
{
|
||||
struct bfq_io_cq *bic = icq_to_bic(icq);
|
||||
struct bfq_data *bfqd = bic_to_bfqd(bic);
|
||||
unsigned long flags;
|
||||
unsigned int act_idx;
|
||||
/*
|
||||
* If bfqd and thus bfqd->num_actuators is not available any
|
||||
* longer, then cycle over all possible per-actuator bfqqs in
|
||||
* next loop. We rely on bic being zeroed on creation, and
|
||||
* therefore on its unused per-actuator fields being NULL.
|
||||
*/
|
||||
unsigned int num_actuators = BFQ_MAX_ACTUATORS;
|
||||
|
||||
if (bic->stable_merge_bfqq) {
|
||||
struct bfq_data *bfqd = bic->stable_merge_bfqq->bfqd;
|
||||
|
||||
/*
|
||||
* bfqd is NULL if scheduler already exited, and in
|
||||
* that case this is the last time bfqq is accessed.
|
||||
*/
|
||||
if (bfqd) {
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&bfqd->lock, flags);
|
||||
bfq_put_stable_ref(bic->stable_merge_bfqq);
|
||||
spin_unlock_irqrestore(&bfqd->lock, flags);
|
||||
} else {
|
||||
bfq_put_stable_ref(bic->stable_merge_bfqq);
|
||||
}
|
||||
/*
|
||||
* bfqd is NULL if scheduler already exited, and in that case
|
||||
* this is the last time these queues are accessed.
|
||||
*/
|
||||
if (bfqd) {
|
||||
spin_lock_irqsave(&bfqd->lock, flags);
|
||||
num_actuators = bfqd->num_actuators;
|
||||
}
|
||||
|
||||
bfq_exit_icq_bfqq(bic, true);
|
||||
bfq_exit_icq_bfqq(bic, false);
|
||||
if (bic->stable_merge_bfqq)
|
||||
bfq_put_stable_ref(bic->stable_merge_bfqq);
|
||||
|
||||
for (act_idx = 0; act_idx < num_actuators; act_idx++) {
|
||||
bfq_exit_icq_bfqq(bic, true, act_idx);
|
||||
bfq_exit_icq_bfqq(bic, false, act_idx);
|
||||
}
|
||||
|
||||
if (bfqd)
|
||||
spin_unlock_irqrestore(&bfqd->lock, flags);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -5493,25 +5541,27 @@ static void bfq_check_ioprio_change(struct bfq_io_cq *bic, struct bio *bio)
|
||||
|
||||
bic->ioprio = ioprio;
|
||||
|
||||
bfqq = bic_to_bfqq(bic, false);
|
||||
bfqq = bic_to_bfqq(bic, false, bfq_actuator_index(bfqd, bio));
|
||||
if (bfqq) {
|
||||
struct bfq_queue *old_bfqq = bfqq;
|
||||
|
||||
bfqq = bfq_get_queue(bfqd, bio, false, bic, true);
|
||||
bic_set_bfqq(bic, bfqq, false);
|
||||
bic_set_bfqq(bic, bfqq, false, bfq_actuator_index(bfqd, bio));
|
||||
bfq_release_process_ref(bfqd, old_bfqq);
|
||||
}
|
||||
|
||||
bfqq = bic_to_bfqq(bic, true);
|
||||
bfqq = bic_to_bfqq(bic, true, bfq_actuator_index(bfqd, bio));
|
||||
if (bfqq)
|
||||
bfq_set_next_ioprio_data(bfqq, bic);
|
||||
}
|
||||
|
||||
static void bfq_init_bfqq(struct bfq_data *bfqd, struct bfq_queue *bfqq,
|
||||
struct bfq_io_cq *bic, pid_t pid, int is_sync)
|
||||
struct bfq_io_cq *bic, pid_t pid, int is_sync,
|
||||
unsigned int act_idx)
|
||||
{
|
||||
u64 now_ns = ktime_get_ns();
|
||||
|
||||
bfqq->actuator_idx = act_idx;
|
||||
RB_CLEAR_NODE(&bfqq->entity.rb_node);
|
||||
INIT_LIST_HEAD(&bfqq->fifo);
|
||||
INIT_HLIST_NODE(&bfqq->burst_list_node);
|
||||
@@ -5762,7 +5812,7 @@ static struct bfq_queue *bfq_get_queue(struct bfq_data *bfqd,
|
||||
|
||||
if (bfqq) {
|
||||
bfq_init_bfqq(bfqd, bfqq, bic, current->pid,
|
||||
is_sync);
|
||||
is_sync, bfq_actuator_index(bfqd, bio));
|
||||
bfq_init_entity(&bfqq->entity, bfqg);
|
||||
bfq_log_bfqq(bfqd, bfqq, "allocated");
|
||||
} else {
|
||||
@@ -6078,7 +6128,8 @@ static bool __bfq_insert_request(struct bfq_data *bfqd, struct request *rq)
|
||||
* then complete the merge and redirect it to
|
||||
* new_bfqq.
|
||||
*/
|
||||
if (bic_to_bfqq(RQ_BIC(rq), 1) == bfqq) {
|
||||
if (bic_to_bfqq(RQ_BIC(rq), true,
|
||||
bfq_actuator_index(bfqd, rq->bio)) == bfqq) {
|
||||
while (bfqq != new_bfqq)
|
||||
bfqq = bfq_merge_bfqqs(bfqd, RQ_BIC(rq), bfqq);
|
||||
}
|
||||
@@ -6632,7 +6683,7 @@ bfq_split_bfqq(struct bfq_io_cq *bic, struct bfq_queue *bfqq)
|
||||
return bfqq;
|
||||
}
|
||||
|
||||
bic_set_bfqq(bic, NULL, true);
|
||||
bic_set_bfqq(bic, NULL, true, bfqq->actuator_idx);
|
||||
|
||||
bfq_put_cooperator(bfqq);
|
||||
|
||||
@@ -6646,7 +6697,8 @@ static struct bfq_queue *bfq_get_bfqq_handle_split(struct bfq_data *bfqd,
|
||||
bool split, bool is_sync,
|
||||
bool *new_queue)
|
||||
{
|
||||
struct bfq_queue *bfqq = bic_to_bfqq(bic, is_sync);
|
||||
unsigned int act_idx = bfq_actuator_index(bfqd, bio);
|
||||
struct bfq_queue *bfqq = bic_to_bfqq(bic, is_sync, act_idx);
|
||||
|
||||
if (likely(bfqq && bfqq != &bfqd->oom_bfqq))
|
||||
return bfqq;
|
||||
@@ -6658,7 +6710,7 @@ static struct bfq_queue *bfq_get_bfqq_handle_split(struct bfq_data *bfqd,
|
||||
bfq_put_queue(bfqq);
|
||||
bfqq = bfq_get_queue(bfqd, bio, is_sync, bic, split);
|
||||
|
||||
bic_set_bfqq(bic, bfqq, is_sync);
|
||||
bic_set_bfqq(bic, bfqq, is_sync, act_idx);
|
||||
if (split && is_sync) {
|
||||
if ((bic->was_in_burst_list && bfqd->large_burst) ||
|
||||
bic->saved_in_large_burst)
|
||||
@@ -7139,8 +7191,10 @@ static int bfq_init_queue(struct request_queue *q, struct elevator_type *e)
|
||||
* Our fallback bfqq if bfq_find_alloc_queue() runs into OOM issues.
|
||||
* Grab a permanent reference to it, so that the normal code flow
|
||||
* will not attempt to free it.
|
||||
* Set zero as actuator index: we will pretend that
|
||||
* all I/O requests are for the same actuator.
|
||||
*/
|
||||
bfq_init_bfqq(bfqd, &bfqd->oom_bfqq, NULL, 1, 0);
|
||||
bfq_init_bfqq(bfqd, &bfqd->oom_bfqq, NULL, 1, 0, 0);
|
||||
bfqd->oom_bfqq.ref++;
|
||||
bfqd->oom_bfqq.new_ioprio = BFQ_DEFAULT_QUEUE_IOPRIO;
|
||||
bfqd->oom_bfqq.new_ioprio_class = IOPRIO_CLASS_BE;
|
||||
@@ -7159,6 +7213,13 @@ static int bfq_init_queue(struct request_queue *q, struct elevator_type *e)
|
||||
|
||||
bfqd->queue = q;
|
||||
|
||||
/*
|
||||
* Multi-actuator support not complete yet, unconditionally
|
||||
* set to only one actuator for the moment (to keep incomplete
|
||||
* mechanisms off).
|
||||
*/
|
||||
bfqd->num_actuators = 1;
|
||||
|
||||
INIT_LIST_HEAD(&bfqd->dispatch);
|
||||
|
||||
hrtimer_init(&bfqd->idle_slice_timer, CLOCK_MONOTONIC,
|
||||
|
||||
@@ -33,6 +33,14 @@
|
||||
*/
|
||||
#define BFQ_SOFTRT_WEIGHT_FACTOR 100
|
||||
|
||||
/*
|
||||
* Maximum number of actuators supported. This constant is used simply
|
||||
* to define the size of the static array that will contain
|
||||
* per-actuator data. The current value is hopefully a good upper
|
||||
* bound to the possible number of actuators of any actual drive.
|
||||
*/
|
||||
#define BFQ_MAX_ACTUATORS 8
|
||||
|
||||
struct bfq_entity;
|
||||
|
||||
/**
|
||||
@@ -225,12 +233,14 @@ struct bfq_ttime {
|
||||
* struct bfq_queue - leaf schedulable entity.
|
||||
*
|
||||
* A bfq_queue is a leaf request queue; it can be associated with an
|
||||
* io_context or more, if it is async or shared between cooperating
|
||||
* processes. @cgroup holds a reference to the cgroup, to be sure that it
|
||||
* does not disappear while a bfqq still references it (mostly to avoid
|
||||
* races between request issuing and task migration followed by cgroup
|
||||
* destruction).
|
||||
* All the fields are protected by the queue lock of the containing bfqd.
|
||||
* io_context or more, if it is async or shared between cooperating
|
||||
* processes. Besides, it contains I/O requests for only one actuator
|
||||
* (an io_context is associated with a different bfq_queue for each
|
||||
* actuator it generates I/O for). @cgroup holds a reference to the
|
||||
* cgroup, to be sure that it does not disappear while a bfqq still
|
||||
* references it (mostly to avoid races between request issuing and
|
||||
* task migration followed by cgroup destruction). All the fields are
|
||||
* protected by the queue lock of the containing bfqd.
|
||||
*/
|
||||
struct bfq_queue {
|
||||
/* reference counter */
|
||||
@@ -395,6 +405,9 @@ struct bfq_queue {
|
||||
* the woken queues when this queue exits.
|
||||
*/
|
||||
struct hlist_head woken_list;
|
||||
|
||||
/* index of the actuator this queue is associated with */
|
||||
unsigned int actuator_idx;
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -403,8 +416,17 @@ struct bfq_queue {
|
||||
struct bfq_io_cq {
|
||||
/* associated io_cq structure */
|
||||
struct io_cq icq; /* must be the first member */
|
||||
/* array of two process queues, the sync and the async */
|
||||
struct bfq_queue *bfqq[2];
|
||||
/*
|
||||
* Matrix of associated process queues: first row for async
|
||||
* queues, second row sync queues. Each row contains one
|
||||
* column for each actuator. An I/O request generated by the
|
||||
* process is inserted into the queue pointed by bfqq[i][j] if
|
||||
* the request is to be served by the j-th actuator of the
|
||||
* drive, where i==0 or i==1, depending on whether the request
|
||||
* is async or sync. So there is a distinct queue for each
|
||||
* actuator.
|
||||
*/
|
||||
struct bfq_queue *bfqq[2][BFQ_MAX_ACTUATORS];
|
||||
/* per (request_queue, blkcg) ioprio */
|
||||
int ioprio;
|
||||
#ifdef CONFIG_BFQ_GROUP_IOSCHED
|
||||
@@ -768,6 +790,13 @@ struct bfq_data {
|
||||
*/
|
||||
unsigned int word_depths[2][2];
|
||||
unsigned int full_depth_shift;
|
||||
|
||||
/*
|
||||
* Number of independent actuators. This is equal to 1 in
|
||||
* case of single-actuator drives.
|
||||
*/
|
||||
unsigned int num_actuators;
|
||||
|
||||
};
|
||||
|
||||
enum bfqq_state_flags {
|
||||
@@ -964,8 +993,10 @@ struct bfq_group {
|
||||
|
||||
extern const int bfq_timeout;
|
||||
|
||||
struct bfq_queue *bic_to_bfqq(struct bfq_io_cq *bic, bool is_sync);
|
||||
void bic_set_bfqq(struct bfq_io_cq *bic, struct bfq_queue *bfqq, bool is_sync);
|
||||
struct bfq_queue *bic_to_bfqq(struct bfq_io_cq *bic, bool is_sync,
|
||||
unsigned int actuator_idx);
|
||||
void bic_set_bfqq(struct bfq_io_cq *bic, struct bfq_queue *bfqq, bool is_sync,
|
||||
unsigned int actuator_idx);
|
||||
struct bfq_data *bic_to_bfqd(struct bfq_io_cq *bic);
|
||||
void bfq_pos_tree_add_move(struct bfq_data *bfqd, struct bfq_queue *bfqq);
|
||||
void bfq_weights_tree_add(struct bfq_data *bfqd, struct bfq_queue *bfqq,
|
||||
|
||||
@@ -95,7 +95,7 @@ static int qcom_llcc_core_setup(struct llcc_drv_data *drv, struct regmap *llcc_b
|
||||
* Configure interrupt enable registers such that Tag, Data RAM related
|
||||
* interrupts are propagated to interrupt controller for servicing
|
||||
*/
|
||||
ret = regmap_update_bits(llcc_bcast_regmap, drv->edac_reg_offset->cmn_interrupt_2_enable,
|
||||
ret = regmap_update_bits(llcc_bcast_regmap, drv->edac_reg_offset->cmn_interrupt_0_enable,
|
||||
TRP0_INTERRUPT_ENABLE,
|
||||
TRP0_INTERRUPT_ENABLE);
|
||||
if (ret)
|
||||
@@ -113,7 +113,7 @@ static int qcom_llcc_core_setup(struct llcc_drv_data *drv, struct regmap *llcc_b
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = regmap_update_bits(llcc_bcast_regmap, drv->edac_reg_offset->cmn_interrupt_2_enable,
|
||||
ret = regmap_update_bits(llcc_bcast_regmap, drv->edac_reg_offset->cmn_interrupt_0_enable,
|
||||
DRP0_INTERRUPT_ENABLE,
|
||||
DRP0_INTERRUPT_ENABLE);
|
||||
if (ret)
|
||||
|
||||
@@ -885,6 +885,7 @@ void amdgpu_dm_hpd_init(struct amdgpu_device *adev)
|
||||
struct drm_device *dev = adev_to_drm(adev);
|
||||
struct drm_connector *connector;
|
||||
struct drm_connector_list_iter iter;
|
||||
int i;
|
||||
|
||||
drm_connector_list_iter_begin(dev, &iter);
|
||||
drm_for_each_connector_iter(connector, &iter) {
|
||||
@@ -906,6 +907,12 @@ void amdgpu_dm_hpd_init(struct amdgpu_device *adev)
|
||||
}
|
||||
}
|
||||
drm_connector_list_iter_end(&iter);
|
||||
|
||||
/* Update reference counts for HPDs */
|
||||
for (i = DC_IRQ_SOURCE_HPD1; i <= adev->mode_info.num_hpd; i++) {
|
||||
if (amdgpu_irq_get(adev, &adev->hpd_irq, i - DC_IRQ_SOURCE_HPD1))
|
||||
drm_err(dev, "DM_IRQ: Failed get HPD for source=%d)!\n", i);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -921,6 +928,7 @@ void amdgpu_dm_hpd_fini(struct amdgpu_device *adev)
|
||||
struct drm_device *dev = adev_to_drm(adev);
|
||||
struct drm_connector *connector;
|
||||
struct drm_connector_list_iter iter;
|
||||
int i;
|
||||
|
||||
drm_connector_list_iter_begin(dev, &iter);
|
||||
drm_for_each_connector_iter(connector, &iter) {
|
||||
@@ -941,4 +949,10 @@ void amdgpu_dm_hpd_fini(struct amdgpu_device *adev)
|
||||
}
|
||||
}
|
||||
drm_connector_list_iter_end(&iter);
|
||||
|
||||
/* Update reference counts for HPDs */
|
||||
for (i = DC_IRQ_SOURCE_HPD1; i <= adev->mode_info.num_hpd; i++) {
|
||||
if (amdgpu_irq_put(adev, &adev->hpd_irq, i - DC_IRQ_SOURCE_HPD1))
|
||||
drm_err(dev, "DM_IRQ: Failed put HPD for source=%d!\n", i);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -51,7 +51,8 @@ static bool link_supports_psrsu(struct dc_link *link)
|
||||
!link->dpcd_caps.psr_info.psr2_su_y_granularity_cap)
|
||||
return false;
|
||||
|
||||
return dc_dmub_check_min_version(dc->ctx->dmub_srv->dmub);
|
||||
/* Temporarily disable PSR-SU to avoid glitches */
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@@ -1862,19 +1862,21 @@ static enum bp_result get_firmware_info_v3_2(
|
||||
/* Vega12 */
|
||||
smu_info_v3_2 = GET_IMAGE(struct atom_smu_info_v3_2,
|
||||
DATA_TABLES(smu_info));
|
||||
DC_LOG_BIOS("gpuclk_ss_percentage (unit of 0.001 percent): %d\n", smu_info_v3_2->gpuclk_ss_percentage);
|
||||
if (!smu_info_v3_2)
|
||||
return BP_RESULT_BADBIOSTABLE;
|
||||
|
||||
DC_LOG_BIOS("gpuclk_ss_percentage (unit of 0.001 percent): %d\n", smu_info_v3_2->gpuclk_ss_percentage);
|
||||
|
||||
info->default_engine_clk = smu_info_v3_2->bootup_dcefclk_10khz * 10;
|
||||
} else if (revision.minor == 3) {
|
||||
/* Vega20 */
|
||||
smu_info_v3_3 = GET_IMAGE(struct atom_smu_info_v3_3,
|
||||
DATA_TABLES(smu_info));
|
||||
DC_LOG_BIOS("gpuclk_ss_percentage (unit of 0.001 percent): %d\n", smu_info_v3_3->gpuclk_ss_percentage);
|
||||
if (!smu_info_v3_3)
|
||||
return BP_RESULT_BADBIOSTABLE;
|
||||
|
||||
DC_LOG_BIOS("gpuclk_ss_percentage (unit of 0.001 percent): %d\n", smu_info_v3_3->gpuclk_ss_percentage);
|
||||
|
||||
info->default_engine_clk = smu_info_v3_3->bootup_dcefclk_10khz * 10;
|
||||
}
|
||||
|
||||
@@ -2439,10 +2441,11 @@ static enum bp_result get_integrated_info_v11(
|
||||
info_v11 = GET_IMAGE(struct atom_integrated_system_info_v1_11,
|
||||
DATA_TABLES(integratedsysteminfo));
|
||||
|
||||
DC_LOG_BIOS("gpuclk_ss_percentage (unit of 0.001 percent): %d\n", info_v11->gpuclk_ss_percentage);
|
||||
if (info_v11 == NULL)
|
||||
return BP_RESULT_BADBIOSTABLE;
|
||||
|
||||
DC_LOG_BIOS("gpuclk_ss_percentage (unit of 0.001 percent): %d\n", info_v11->gpuclk_ss_percentage);
|
||||
|
||||
info->gpu_cap_info =
|
||||
le32_to_cpu(info_v11->gpucapinfo);
|
||||
/*
|
||||
@@ -2654,11 +2657,12 @@ static enum bp_result get_integrated_info_v2_1(
|
||||
|
||||
info_v2_1 = GET_IMAGE(struct atom_integrated_system_info_v2_1,
|
||||
DATA_TABLES(integratedsysteminfo));
|
||||
DC_LOG_BIOS("gpuclk_ss_percentage (unit of 0.001 percent): %d\n", info_v2_1->gpuclk_ss_percentage);
|
||||
|
||||
if (info_v2_1 == NULL)
|
||||
return BP_RESULT_BADBIOSTABLE;
|
||||
|
||||
DC_LOG_BIOS("gpuclk_ss_percentage (unit of 0.001 percent): %d\n", info_v2_1->gpuclk_ss_percentage);
|
||||
|
||||
info->gpu_cap_info =
|
||||
le32_to_cpu(info_v2_1->gpucapinfo);
|
||||
/*
|
||||
@@ -2816,11 +2820,11 @@ static enum bp_result get_integrated_info_v2_2(
|
||||
info_v2_2 = GET_IMAGE(struct atom_integrated_system_info_v2_2,
|
||||
DATA_TABLES(integratedsysteminfo));
|
||||
|
||||
DC_LOG_BIOS("gpuclk_ss_percentage (unit of 0.001 percent): %d\n", info_v2_2->gpuclk_ss_percentage);
|
||||
|
||||
if (info_v2_2 == NULL)
|
||||
return BP_RESULT_BADBIOSTABLE;
|
||||
|
||||
DC_LOG_BIOS("gpuclk_ss_percentage (unit of 0.001 percent): %d\n", info_v2_2->gpuclk_ss_percentage);
|
||||
|
||||
info->gpu_cap_info =
|
||||
le32_to_cpu(info_v2_2->gpucapinfo);
|
||||
/*
|
||||
|
||||
@@ -3056,6 +3056,7 @@ static int kv_dpm_hw_init(void *handle)
|
||||
if (!amdgpu_dpm)
|
||||
return 0;
|
||||
|
||||
mutex_lock(&adev->pm.mutex);
|
||||
kv_dpm_setup_asic(adev);
|
||||
ret = kv_dpm_enable(adev);
|
||||
if (ret)
|
||||
@@ -3063,6 +3064,8 @@ static int kv_dpm_hw_init(void *handle)
|
||||
else
|
||||
adev->pm.dpm_enabled = true;
|
||||
amdgpu_legacy_dpm_compute_clocks(adev);
|
||||
mutex_unlock(&adev->pm.mutex);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -3080,32 +3083,42 @@ static int kv_dpm_suspend(void *handle)
|
||||
{
|
||||
struct amdgpu_device *adev = (struct amdgpu_device *)handle;
|
||||
|
||||
cancel_work_sync(&adev->pm.dpm.thermal.work);
|
||||
|
||||
if (adev->pm.dpm_enabled) {
|
||||
mutex_lock(&adev->pm.mutex);
|
||||
adev->pm.dpm_enabled = false;
|
||||
/* disable dpm */
|
||||
kv_dpm_disable(adev);
|
||||
/* reset the power state */
|
||||
adev->pm.dpm.current_ps = adev->pm.dpm.requested_ps = adev->pm.dpm.boot_ps;
|
||||
mutex_unlock(&adev->pm.mutex);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int kv_dpm_resume(void *handle)
|
||||
{
|
||||
int ret;
|
||||
int ret = 0;
|
||||
struct amdgpu_device *adev = (struct amdgpu_device *)handle;
|
||||
|
||||
if (adev->pm.dpm_enabled) {
|
||||
if (!amdgpu_dpm)
|
||||
return 0;
|
||||
|
||||
if (!adev->pm.dpm_enabled) {
|
||||
mutex_lock(&adev->pm.mutex);
|
||||
/* asic init will reset to the boot state */
|
||||
kv_dpm_setup_asic(adev);
|
||||
ret = kv_dpm_enable(adev);
|
||||
if (ret)
|
||||
if (ret) {
|
||||
adev->pm.dpm_enabled = false;
|
||||
else
|
||||
} else {
|
||||
adev->pm.dpm_enabled = true;
|
||||
if (adev->pm.dpm_enabled)
|
||||
amdgpu_legacy_dpm_compute_clocks(adev);
|
||||
}
|
||||
mutex_unlock(&adev->pm.mutex);
|
||||
}
|
||||
return 0;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static bool kv_dpm_is_idle(void *handle)
|
||||
|
||||
@@ -1018,9 +1018,12 @@ void amdgpu_dpm_thermal_work_handler(struct work_struct *work)
|
||||
enum amd_pm_state_type dpm_state = POWER_STATE_TYPE_INTERNAL_THERMAL;
|
||||
int temp, size = sizeof(temp);
|
||||
|
||||
if (!adev->pm.dpm_enabled)
|
||||
return;
|
||||
mutex_lock(&adev->pm.mutex);
|
||||
|
||||
if (!adev->pm.dpm_enabled) {
|
||||
mutex_unlock(&adev->pm.mutex);
|
||||
return;
|
||||
}
|
||||
if (!pp_funcs->read_sensor(adev->powerplay.pp_handle,
|
||||
AMDGPU_PP_SENSOR_GPU_TEMP,
|
||||
(void *)&temp,
|
||||
@@ -1042,4 +1045,5 @@ void amdgpu_dpm_thermal_work_handler(struct work_struct *work)
|
||||
adev->pm.dpm.state = dpm_state;
|
||||
|
||||
amdgpu_legacy_dpm_compute_clocks(adev->powerplay.pp_handle);
|
||||
mutex_unlock(&adev->pm.mutex);
|
||||
}
|
||||
|
||||
@@ -7796,6 +7796,7 @@ static int si_dpm_hw_init(void *handle)
|
||||
if (!amdgpu_dpm)
|
||||
return 0;
|
||||
|
||||
mutex_lock(&adev->pm.mutex);
|
||||
si_dpm_setup_asic(adev);
|
||||
ret = si_dpm_enable(adev);
|
||||
if (ret)
|
||||
@@ -7803,6 +7804,7 @@ static int si_dpm_hw_init(void *handle)
|
||||
else
|
||||
adev->pm.dpm_enabled = true;
|
||||
amdgpu_legacy_dpm_compute_clocks(adev);
|
||||
mutex_unlock(&adev->pm.mutex);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -7820,32 +7822,44 @@ static int si_dpm_suspend(void *handle)
|
||||
{
|
||||
struct amdgpu_device *adev = (struct amdgpu_device *)handle;
|
||||
|
||||
cancel_work_sync(&adev->pm.dpm.thermal.work);
|
||||
|
||||
if (adev->pm.dpm_enabled) {
|
||||
mutex_lock(&adev->pm.mutex);
|
||||
adev->pm.dpm_enabled = false;
|
||||
/* disable dpm */
|
||||
si_dpm_disable(adev);
|
||||
/* reset the power state */
|
||||
adev->pm.dpm.current_ps = adev->pm.dpm.requested_ps = adev->pm.dpm.boot_ps;
|
||||
mutex_unlock(&adev->pm.mutex);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int si_dpm_resume(void *handle)
|
||||
{
|
||||
int ret;
|
||||
int ret = 0;
|
||||
struct amdgpu_device *adev = (struct amdgpu_device *)handle;
|
||||
|
||||
if (adev->pm.dpm_enabled) {
|
||||
if (!amdgpu_dpm)
|
||||
return 0;
|
||||
|
||||
if (!adev->pm.dpm_enabled) {
|
||||
/* asic init will reset to the boot state */
|
||||
mutex_lock(&adev->pm.mutex);
|
||||
si_dpm_setup_asic(adev);
|
||||
ret = si_dpm_enable(adev);
|
||||
if (ret)
|
||||
if (ret) {
|
||||
adev->pm.dpm_enabled = false;
|
||||
else
|
||||
} else {
|
||||
adev->pm.dpm_enabled = true;
|
||||
if (adev->pm.dpm_enabled)
|
||||
amdgpu_legacy_dpm_compute_clocks(adev);
|
||||
}
|
||||
mutex_unlock(&adev->pm.mutex);
|
||||
}
|
||||
return 0;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static bool si_dpm_is_idle(void *handle)
|
||||
|
||||
@@ -6691,12 +6691,30 @@ static int intel_async_flip_check_hw(struct intel_atomic_state *state, struct in
|
||||
static int intel_bigjoiner_add_affected_crtcs(struct intel_atomic_state *state)
|
||||
{
|
||||
struct drm_i915_private *i915 = to_i915(state->base.dev);
|
||||
const struct intel_plane_state *plane_state;
|
||||
struct intel_crtc_state *crtc_state;
|
||||
struct intel_plane *plane;
|
||||
struct intel_crtc *crtc;
|
||||
u8 affected_pipes = 0;
|
||||
u8 modeset_pipes = 0;
|
||||
int i;
|
||||
|
||||
/*
|
||||
* Any plane which is in use by the joiner needs its crtc.
|
||||
* Pull those in first as this will not have happened yet
|
||||
* if the plane remains disabled according to uapi.
|
||||
*/
|
||||
for_each_new_intel_plane_in_state(state, plane, plane_state, i) {
|
||||
crtc = to_intel_crtc(plane_state->hw.crtc);
|
||||
if (!crtc)
|
||||
continue;
|
||||
|
||||
crtc_state = intel_atomic_get_crtc_state(&state->base, crtc);
|
||||
if (IS_ERR(crtc_state))
|
||||
return PTR_ERR(crtc_state);
|
||||
}
|
||||
|
||||
/* Now pull in all joined crtcs */
|
||||
for_each_new_intel_crtc_in_state(state, crtc, crtc_state, i) {
|
||||
affected_pipes |= crtc_state->bigjoiner_pipes;
|
||||
if (intel_crtc_needs_modeset(crtc_state))
|
||||
|
||||
@@ -2059,6 +2059,9 @@ void dpu_encoder_helper_phys_cleanup(struct dpu_encoder_phys *phys_enc)
|
||||
}
|
||||
}
|
||||
|
||||
if (phys_enc->hw_pp && phys_enc->hw_pp->ops.setup_dither)
|
||||
phys_enc->hw_pp->ops.setup_dither(phys_enc->hw_pp, NULL);
|
||||
|
||||
/* reset the merge 3D HW block */
|
||||
if (phys_enc->hw_pp && phys_enc->hw_pp->merge_3d) {
|
||||
phys_enc->hw_pp->merge_3d->ops.setup_3d_mode(phys_enc->hw_pp->merge_3d,
|
||||
|
||||
@@ -46,6 +46,7 @@ static void dpu_hw_dsc_config(struct dpu_hw_dsc *hw_dsc,
|
||||
u32 slice_last_group_size;
|
||||
u32 det_thresh_flatness;
|
||||
bool is_cmd_mode = !(mode & DSC_MODE_VIDEO);
|
||||
bool input_10_bits = dsc->bits_per_component == 10;
|
||||
|
||||
DPU_REG_WRITE(c, DSC_COMMON_MODE, mode);
|
||||
|
||||
@@ -62,7 +63,7 @@ static void dpu_hw_dsc_config(struct dpu_hw_dsc *hw_dsc,
|
||||
data |= (dsc->line_buf_depth << 3);
|
||||
data |= (dsc->simple_422 << 2);
|
||||
data |= (dsc->convert_rgb << 1);
|
||||
data |= dsc->bits_per_component;
|
||||
data |= input_10_bits;
|
||||
|
||||
DPU_REG_WRITE(c, DSC_ENC, data);
|
||||
|
||||
|
||||
@@ -592,6 +592,7 @@ static int nouveau_atomic_range_fault(struct nouveau_svmm *svmm,
|
||||
unsigned long timeout =
|
||||
jiffies + msecs_to_jiffies(HMM_RANGE_DEFAULT_TIMEOUT);
|
||||
struct mm_struct *mm = svmm->notifier.mm;
|
||||
struct folio *folio;
|
||||
struct page *page;
|
||||
unsigned long start = args->p.addr;
|
||||
unsigned long notifier_seq;
|
||||
@@ -618,12 +619,16 @@ static int nouveau_atomic_range_fault(struct nouveau_svmm *svmm,
|
||||
ret = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
folio = page_folio(page);
|
||||
|
||||
mutex_lock(&svmm->mutex);
|
||||
if (!mmu_interval_read_retry(¬ifier->notifier,
|
||||
notifier_seq))
|
||||
break;
|
||||
mutex_unlock(&svmm->mutex);
|
||||
|
||||
folio_unlock(folio);
|
||||
folio_put(folio);
|
||||
}
|
||||
|
||||
/* Map the page on the GPU. */
|
||||
@@ -639,8 +644,8 @@ static int nouveau_atomic_range_fault(struct nouveau_svmm *svmm,
|
||||
ret = nvif_object_ioctl(&svmm->vmm->vmm.object, args, size, NULL);
|
||||
mutex_unlock(&svmm->mutex);
|
||||
|
||||
unlock_page(page);
|
||||
put_page(page);
|
||||
folio_unlock(folio);
|
||||
folio_put(folio);
|
||||
|
||||
out:
|
||||
mmu_interval_notifier_remove(¬ifier->notifier);
|
||||
|
||||
@@ -396,7 +396,7 @@ static int rcar_mipi_dsi_startup(struct rcar_mipi_dsi *dsi,
|
||||
for (timeout = 10; timeout > 0; --timeout) {
|
||||
if ((rcar_mipi_dsi_read(dsi, PPICLSR) & PPICLSR_STPST) &&
|
||||
(rcar_mipi_dsi_read(dsi, PPIDLSR) & PPIDLSR_STPST) &&
|
||||
(rcar_mipi_dsi_read(dsi, CLOCKSET1) & CLOCKSET1_LOCK))
|
||||
(rcar_mipi_dsi_read(dsi, CLOCKSET1) & CLOCKSET1_LOCK_PHY))
|
||||
break;
|
||||
|
||||
usleep_range(1000, 2000);
|
||||
|
||||
@@ -141,7 +141,6 @@
|
||||
|
||||
#define CLOCKSET1 0x101c
|
||||
#define CLOCKSET1_LOCK_PHY (1 << 17)
|
||||
#define CLOCKSET1_LOCK (1 << 16)
|
||||
#define CLOCKSET1_CLKSEL (1 << 8)
|
||||
#define CLOCKSET1_CLKINSEL_EXTAL (0 << 2)
|
||||
#define CLOCKSET1_CLKINSEL_DIG (1 << 2)
|
||||
|
||||
@@ -2655,14 +2655,32 @@ static void dispc_init_errata(struct dispc_device *dispc)
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* K2G display controller does not support soft reset, so we do a basic manual
|
||||
* reset here: make sure the IRQs are masked and VPs are disabled.
|
||||
*/
|
||||
static void dispc_softreset_k2g(struct dispc_device *dispc)
|
||||
{
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&dispc->tidss->wait_lock, flags);
|
||||
dispc_set_irqenable(dispc, 0);
|
||||
dispc_read_and_clear_irqstatus(dispc);
|
||||
spin_unlock_irqrestore(&dispc->tidss->wait_lock, flags);
|
||||
|
||||
for (unsigned int vp_idx = 0; vp_idx < dispc->feat->num_vps; ++vp_idx)
|
||||
VP_REG_FLD_MOD(dispc, vp_idx, DISPC_VP_CONTROL, 0, 0, 0);
|
||||
}
|
||||
|
||||
static int dispc_softreset(struct dispc_device *dispc)
|
||||
{
|
||||
u32 val;
|
||||
int ret = 0;
|
||||
|
||||
/* K2G display controller does not support soft reset */
|
||||
if (dispc->feat->subrev == DISPC_K2G)
|
||||
if (dispc->feat->subrev == DISPC_K2G) {
|
||||
dispc_softreset_k2g(dispc);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Soft reset */
|
||||
REG_FLD_MOD(dispc, DSS_SYSCONFIG, 1, 1, 1);
|
||||
|
||||
@@ -60,7 +60,9 @@ static irqreturn_t tidss_irq_handler(int irq, void *arg)
|
||||
unsigned int id;
|
||||
dispc_irq_t irqstatus;
|
||||
|
||||
spin_lock(&tidss->wait_lock);
|
||||
irqstatus = dispc_read_and_clear_irqstatus(tidss->dispc);
|
||||
spin_unlock(&tidss->wait_lock);
|
||||
|
||||
for (id = 0; id < tidss->num_crtcs; id++) {
|
||||
struct drm_crtc *crtc = tidss->crtcs[id];
|
||||
|
||||
@@ -2335,6 +2335,13 @@ static int npcm_i2c_probe_bus(struct platform_device *pdev)
|
||||
if (irq < 0)
|
||||
return irq;
|
||||
|
||||
/*
|
||||
* Disable the interrupt to avoid the interrupt handler being triggered
|
||||
* incorrectly by the asynchronous interrupt status since the machine
|
||||
* might do a warm reset during the last smbus/i2c transfer session.
|
||||
*/
|
||||
npcm_i2c_int_enable(bus, false);
|
||||
|
||||
ret = devm_request_irq(bus->dev, irq, npcm_i2c_bus_irq, 0,
|
||||
dev_name(bus->dev), bus);
|
||||
if (ret)
|
||||
|
||||
@@ -56,6 +56,7 @@
|
||||
#include <asm/nospec-branch.h>
|
||||
#include <asm/mwait.h>
|
||||
#include <asm/msr.h>
|
||||
#include <asm/tsc.h>
|
||||
#include <asm/fpu/api.h>
|
||||
|
||||
#define INTEL_IDLE_VERSION "0.5.1"
|
||||
@@ -1583,6 +1584,9 @@ static void __init intel_idle_init_cstates_acpi(struct cpuidle_driver *drv)
|
||||
if (intel_idle_state_needs_timer_stop(state))
|
||||
state->flags |= CPUIDLE_FLAG_TIMER_STOP;
|
||||
|
||||
if (cx->type > ACPI_STATE_C1 && !boot_cpu_has(X86_FEATURE_NONSTOP_TSC))
|
||||
mark_tsc_unstable("TSC halts in idle");
|
||||
|
||||
state->enter = intel_idle;
|
||||
state->enter_s2idle = intel_idle_s2idle;
|
||||
}
|
||||
|
||||
@@ -444,6 +444,7 @@ static int mlx5_ib_counter_bind_qp(struct rdma_counter *counter,
|
||||
struct ib_qp *qp)
|
||||
{
|
||||
struct mlx5_ib_dev *dev = to_mdev(qp->device);
|
||||
bool new = false;
|
||||
int err;
|
||||
|
||||
if (!counter->id) {
|
||||
@@ -458,6 +459,7 @@ static int mlx5_ib_counter_bind_qp(struct rdma_counter *counter,
|
||||
return err;
|
||||
counter->id =
|
||||
MLX5_GET(alloc_q_counter_out, out, counter_set_id);
|
||||
new = true;
|
||||
}
|
||||
|
||||
err = mlx5_ib_qp_set_counter(qp, counter);
|
||||
@@ -467,8 +469,10 @@ static int mlx5_ib_counter_bind_qp(struct rdma_counter *counter,
|
||||
return 0;
|
||||
|
||||
fail_set_counter:
|
||||
mlx5_ib_counter_dealloc(counter);
|
||||
counter->id = 0;
|
||||
if (new) {
|
||||
mlx5_ib_counter_dealloc(counter);
|
||||
counter->id = 0;
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
@@ -4466,6 +4466,8 @@ static int mlx5_ib_modify_dct(struct ib_qp *ibqp, struct ib_qp_attr *attr,
|
||||
|
||||
set_id = mlx5_ib_get_counters_id(dev, attr->port_num - 1);
|
||||
MLX5_SET(dctc, dctc, counter_set_id, set_id);
|
||||
|
||||
qp->port = attr->port_num;
|
||||
} else if (cur_state == IB_QPS_INIT && new_state == IB_QPS_RTR) {
|
||||
struct mlx5_ib_modify_qp_resp resp = {};
|
||||
u32 out[MLX5_ST_SZ_DW(create_dct_out)] = {};
|
||||
@@ -4955,7 +4957,7 @@ static int mlx5_ib_dct_query_qp(struct mlx5_ib_dev *dev, struct mlx5_ib_qp *mqp,
|
||||
}
|
||||
|
||||
if (qp_attr_mask & IB_QP_PORT)
|
||||
qp_attr->port_num = MLX5_GET(dctc, dctc, port);
|
||||
qp_attr->port_num = mqp->port;
|
||||
if (qp_attr_mask & IB_QP_MIN_RNR_TIMER)
|
||||
qp_attr->min_rnr_timer = MLX5_GET(dctc, dctc, min_rnr_nak);
|
||||
if (qp_attr_mask & IB_QP_AV) {
|
||||
|
||||
@@ -65,6 +65,8 @@ struct mtk_vcodec_fw *mtk_vcodec_fw_scp_init(struct mtk_vcodec_dev *dev)
|
||||
}
|
||||
|
||||
fw = devm_kzalloc(&dev->plat_dev->dev, sizeof(*fw), GFP_KERNEL);
|
||||
if (!fw)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
fw->type = SCP;
|
||||
fw->ops = &mtk_vcodec_rproc_msg;
|
||||
fw->scp = scp;
|
||||
|
||||
@@ -729,11 +729,16 @@ static int vdec_h264_slice_single_decode(void *h_vdec, struct mtk_vcodec_mem *bs
|
||||
return vpu_dec_reset(vpu);
|
||||
|
||||
fb = inst->ctx->dev->vdec_pdata->get_cap_buffer(inst->ctx);
|
||||
if (!fb) {
|
||||
mtk_vcodec_err(inst, "fb buffer is NULL");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
src_buf_info = container_of(bs, struct mtk_video_dec_buf, bs_buffer);
|
||||
dst_buf_info = container_of(fb, struct mtk_video_dec_buf, frame_buffer);
|
||||
|
||||
y_fb_dma = fb ? (u64)fb->base_y.dma_addr : 0;
|
||||
c_fb_dma = fb ? (u64)fb->base_c.dma_addr : 0;
|
||||
y_fb_dma = fb->base_y.dma_addr;
|
||||
c_fb_dma = fb->base_c.dma_addr;
|
||||
mtk_vcodec_debug(inst, "[h264-dec] [%d] y_dma=%llx c_dma=%llx",
|
||||
inst->ctx->decoded_frame_cnt, y_fb_dma, c_fb_dma);
|
||||
|
||||
|
||||
@@ -469,6 +469,8 @@ struct cdns_nand_ctrl {
|
||||
struct {
|
||||
void __iomem *virt;
|
||||
dma_addr_t dma;
|
||||
dma_addr_t iova_dma;
|
||||
u32 size;
|
||||
} io;
|
||||
|
||||
int irq;
|
||||
@@ -1830,11 +1832,11 @@ static int cadence_nand_slave_dma_transfer(struct cdns_nand_ctrl *cdns_ctrl,
|
||||
}
|
||||
|
||||
if (dir == DMA_FROM_DEVICE) {
|
||||
src_dma = cdns_ctrl->io.dma;
|
||||
src_dma = cdns_ctrl->io.iova_dma;
|
||||
dst_dma = buf_dma;
|
||||
} else {
|
||||
src_dma = buf_dma;
|
||||
dst_dma = cdns_ctrl->io.dma;
|
||||
dst_dma = cdns_ctrl->io.iova_dma;
|
||||
}
|
||||
|
||||
tx = dmaengine_prep_dma_memcpy(cdns_ctrl->dmac, dst_dma, src_dma, len,
|
||||
@@ -1856,12 +1858,12 @@ static int cadence_nand_slave_dma_transfer(struct cdns_nand_ctrl *cdns_ctrl,
|
||||
dma_async_issue_pending(cdns_ctrl->dmac);
|
||||
wait_for_completion(&finished);
|
||||
|
||||
dma_unmap_single(cdns_ctrl->dev, buf_dma, len, dir);
|
||||
dma_unmap_single(dma_dev->dev, buf_dma, len, dir);
|
||||
|
||||
return 0;
|
||||
|
||||
err_unmap:
|
||||
dma_unmap_single(cdns_ctrl->dev, buf_dma, len, dir);
|
||||
dma_unmap_single(dma_dev->dev, buf_dma, len, dir);
|
||||
|
||||
err:
|
||||
dev_dbg(cdns_ctrl->dev, "Fall back to CPU I/O\n");
|
||||
@@ -2828,6 +2830,7 @@ cadence_nand_irq_cleanup(int irqnum, struct cdns_nand_ctrl *cdns_ctrl)
|
||||
static int cadence_nand_init(struct cdns_nand_ctrl *cdns_ctrl)
|
||||
{
|
||||
dma_cap_mask_t mask;
|
||||
struct dma_device *dma_dev = cdns_ctrl->dmac->device;
|
||||
int ret;
|
||||
|
||||
cdns_ctrl->cdma_desc = dma_alloc_coherent(cdns_ctrl->dev,
|
||||
@@ -2863,15 +2866,24 @@ static int cadence_nand_init(struct cdns_nand_ctrl *cdns_ctrl)
|
||||
dma_cap_set(DMA_MEMCPY, mask);
|
||||
|
||||
if (cdns_ctrl->caps1->has_dma) {
|
||||
cdns_ctrl->dmac = dma_request_channel(mask, NULL, NULL);
|
||||
if (!cdns_ctrl->dmac) {
|
||||
dev_err(cdns_ctrl->dev,
|
||||
"Unable to get a DMA channel\n");
|
||||
ret = -EBUSY;
|
||||
cdns_ctrl->dmac = dma_request_chan_by_mask(&mask);
|
||||
if (IS_ERR(cdns_ctrl->dmac)) {
|
||||
ret = dev_err_probe(cdns_ctrl->dev, PTR_ERR(cdns_ctrl->dmac),
|
||||
"%d: Failed to get a DMA channel\n", ret);
|
||||
goto disable_irq;
|
||||
}
|
||||
}
|
||||
|
||||
cdns_ctrl->io.iova_dma = dma_map_resource(dma_dev->dev, cdns_ctrl->io.dma,
|
||||
cdns_ctrl->io.size,
|
||||
DMA_BIDIRECTIONAL, 0);
|
||||
|
||||
ret = dma_mapping_error(dma_dev->dev, cdns_ctrl->io.iova_dma);
|
||||
if (ret) {
|
||||
dev_err(cdns_ctrl->dev, "Failed to map I/O resource to DMA\n");
|
||||
goto dma_release_chnl;
|
||||
}
|
||||
|
||||
nand_controller_init(&cdns_ctrl->controller);
|
||||
INIT_LIST_HEAD(&cdns_ctrl->chips);
|
||||
|
||||
@@ -2882,18 +2894,22 @@ static int cadence_nand_init(struct cdns_nand_ctrl *cdns_ctrl)
|
||||
if (ret) {
|
||||
dev_err(cdns_ctrl->dev, "Failed to register MTD: %d\n",
|
||||
ret);
|
||||
goto dma_release_chnl;
|
||||
goto unmap_dma_resource;
|
||||
}
|
||||
|
||||
kfree(cdns_ctrl->buf);
|
||||
cdns_ctrl->buf = kzalloc(cdns_ctrl->buf_size, GFP_KERNEL);
|
||||
if (!cdns_ctrl->buf) {
|
||||
ret = -ENOMEM;
|
||||
goto dma_release_chnl;
|
||||
goto unmap_dma_resource;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
unmap_dma_resource:
|
||||
dma_unmap_resource(dma_dev->dev, cdns_ctrl->io.iova_dma,
|
||||
cdns_ctrl->io.size, DMA_BIDIRECTIONAL, 0);
|
||||
|
||||
dma_release_chnl:
|
||||
if (cdns_ctrl->dmac)
|
||||
dma_release_channel(cdns_ctrl->dmac);
|
||||
@@ -2915,6 +2931,8 @@ free_buf_desc:
|
||||
static void cadence_nand_remove(struct cdns_nand_ctrl *cdns_ctrl)
|
||||
{
|
||||
cadence_nand_chips_cleanup(cdns_ctrl);
|
||||
dma_unmap_resource(cdns_ctrl->dmac->device->dev, cdns_ctrl->io.iova_dma,
|
||||
cdns_ctrl->io.size, DMA_BIDIRECTIONAL, 0);
|
||||
cadence_nand_irq_cleanup(cdns_ctrl->irq, cdns_ctrl);
|
||||
kfree(cdns_ctrl->buf);
|
||||
dma_free_coherent(cdns_ctrl->dev, sizeof(struct cadence_nand_cdma_desc),
|
||||
@@ -2983,7 +3001,9 @@ static int cadence_nand_dt_probe(struct platform_device *ofdev)
|
||||
cdns_ctrl->io.virt = devm_platform_get_and_ioremap_resource(ofdev, 1, &res);
|
||||
if (IS_ERR(cdns_ctrl->io.virt))
|
||||
return PTR_ERR(cdns_ctrl->io.virt);
|
||||
|
||||
cdns_ctrl->io.dma = res->start;
|
||||
cdns_ctrl->io.size = resource_size(res);
|
||||
|
||||
dt->clk = devm_clk_get(cdns_ctrl->dev, "nf_clk");
|
||||
if (IS_ERR(dt->clk))
|
||||
|
||||
@@ -1271,6 +1271,8 @@ struct macb {
|
||||
struct clk *rx_clk;
|
||||
struct clk *tsu_clk;
|
||||
struct net_device *dev;
|
||||
/* Protects hw_stats and ethtool_stats */
|
||||
spinlock_t stats_lock;
|
||||
union {
|
||||
struct macb_stats macb;
|
||||
struct gem_stats gem;
|
||||
|
||||
@@ -1936,10 +1936,12 @@ static irqreturn_t macb_interrupt(int irq, void *dev_id)
|
||||
|
||||
if (status & MACB_BIT(ISR_ROVR)) {
|
||||
/* We missed at least one packet */
|
||||
spin_lock(&bp->stats_lock);
|
||||
if (macb_is_gem(bp))
|
||||
bp->hw_stats.gem.rx_overruns++;
|
||||
else
|
||||
bp->hw_stats.macb.rx_overruns++;
|
||||
spin_unlock(&bp->stats_lock);
|
||||
|
||||
if (bp->caps & MACB_CAPS_ISR_CLEAR_ON_WRITE)
|
||||
queue_writel(queue, ISR, MACB_BIT(ISR_ROVR));
|
||||
@@ -2999,6 +3001,7 @@ static struct net_device_stats *gem_get_stats(struct macb *bp)
|
||||
if (!netif_running(bp->dev))
|
||||
return nstat;
|
||||
|
||||
spin_lock_irq(&bp->stats_lock);
|
||||
gem_update_stats(bp);
|
||||
|
||||
nstat->rx_errors = (hwstat->rx_frame_check_sequence_errors +
|
||||
@@ -3028,6 +3031,7 @@ static struct net_device_stats *gem_get_stats(struct macb *bp)
|
||||
nstat->tx_aborted_errors = hwstat->tx_excessive_collisions;
|
||||
nstat->tx_carrier_errors = hwstat->tx_carrier_sense_errors;
|
||||
nstat->tx_fifo_errors = hwstat->tx_underrun;
|
||||
spin_unlock_irq(&bp->stats_lock);
|
||||
|
||||
return nstat;
|
||||
}
|
||||
@@ -3035,12 +3039,13 @@ static struct net_device_stats *gem_get_stats(struct macb *bp)
|
||||
static void gem_get_ethtool_stats(struct net_device *dev,
|
||||
struct ethtool_stats *stats, u64 *data)
|
||||
{
|
||||
struct macb *bp;
|
||||
struct macb *bp = netdev_priv(dev);
|
||||
|
||||
bp = netdev_priv(dev);
|
||||
spin_lock_irq(&bp->stats_lock);
|
||||
gem_update_stats(bp);
|
||||
memcpy(data, &bp->ethtool_stats, sizeof(u64)
|
||||
* (GEM_STATS_LEN + QUEUE_STATS_LEN * MACB_MAX_QUEUES));
|
||||
spin_unlock_irq(&bp->stats_lock);
|
||||
}
|
||||
|
||||
static int gem_get_sset_count(struct net_device *dev, int sset)
|
||||
@@ -3090,6 +3095,7 @@ static struct net_device_stats *macb_get_stats(struct net_device *dev)
|
||||
return gem_get_stats(bp);
|
||||
|
||||
/* read stats from hardware */
|
||||
spin_lock_irq(&bp->stats_lock);
|
||||
macb_update_stats(bp);
|
||||
|
||||
/* Convert HW stats into netdevice stats */
|
||||
@@ -3123,6 +3129,7 @@ static struct net_device_stats *macb_get_stats(struct net_device *dev)
|
||||
nstat->tx_carrier_errors = hwstat->tx_carrier_errors;
|
||||
nstat->tx_fifo_errors = hwstat->tx_underruns;
|
||||
/* Don't know about heartbeat or window errors... */
|
||||
spin_unlock_irq(&bp->stats_lock);
|
||||
|
||||
return nstat;
|
||||
}
|
||||
@@ -4949,6 +4956,7 @@ static int macb_probe(struct platform_device *pdev)
|
||||
bp->usrio = macb_config->usrio;
|
||||
|
||||
spin_lock_init(&bp->lock);
|
||||
spin_lock_init(&bp->stats_lock);
|
||||
|
||||
/* setup capabilities */
|
||||
macb_configure_caps(bp, macb_config);
|
||||
|
||||
@@ -123,6 +123,24 @@ static int enetc_ptp_parse(struct sk_buff *skb, u8 *udp,
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* enetc_unwind_tx_frame() - Unwind the DMA mappings of a multi-buffer Tx frame
|
||||
* @tx_ring: Pointer to the Tx ring on which the buffer descriptors are located
|
||||
* @count: Number of Tx buffer descriptors which need to be unmapped
|
||||
* @i: Index of the last successfully mapped Tx buffer descriptor
|
||||
*/
|
||||
static void enetc_unwind_tx_frame(struct enetc_bdr *tx_ring, int count, int i)
|
||||
{
|
||||
while (count--) {
|
||||
struct enetc_tx_swbd *tx_swbd = &tx_ring->tx_swbd[i];
|
||||
|
||||
enetc_free_tx_frame(tx_ring, tx_swbd);
|
||||
if (i == 0)
|
||||
i = tx_ring->bd_count;
|
||||
i--;
|
||||
}
|
||||
}
|
||||
|
||||
static int enetc_map_tx_buffs(struct enetc_bdr *tx_ring, struct sk_buff *skb)
|
||||
{
|
||||
bool do_vlan, do_onestep_tstamp = false, do_twostep_tstamp = false;
|
||||
@@ -213,9 +231,11 @@ static int enetc_map_tx_buffs(struct enetc_bdr *tx_ring, struct sk_buff *skb)
|
||||
}
|
||||
|
||||
if (do_onestep_tstamp) {
|
||||
u32 lo, hi, val;
|
||||
u64 sec, nsec;
|
||||
__be32 new_sec_l, new_nsec;
|
||||
u32 lo, hi, nsec, val;
|
||||
__be16 new_sec_h;
|
||||
u8 *data;
|
||||
u64 sec;
|
||||
|
||||
lo = enetc_rd_hot(hw, ENETC_SICTR0);
|
||||
hi = enetc_rd_hot(hw, ENETC_SICTR1);
|
||||
@@ -229,13 +249,38 @@ static int enetc_map_tx_buffs(struct enetc_bdr *tx_ring, struct sk_buff *skb)
|
||||
/* Update originTimestamp field of Sync packet
|
||||
* - 48 bits seconds field
|
||||
* - 32 bits nanseconds field
|
||||
*
|
||||
* In addition, the UDP checksum needs to be updated
|
||||
* by software after updating originTimestamp field,
|
||||
* otherwise the hardware will calculate the wrong
|
||||
* checksum when updating the correction field and
|
||||
* update it to the packet.
|
||||
*/
|
||||
data = skb_mac_header(skb);
|
||||
*(__be16 *)(data + offset2) =
|
||||
htons((sec >> 32) & 0xffff);
|
||||
*(__be32 *)(data + offset2 + 2) =
|
||||
htonl(sec & 0xffffffff);
|
||||
*(__be32 *)(data + offset2 + 6) = htonl(nsec);
|
||||
new_sec_h = htons((sec >> 32) & 0xffff);
|
||||
new_sec_l = htonl(sec & 0xffffffff);
|
||||
new_nsec = htonl(nsec);
|
||||
if (udp) {
|
||||
struct udphdr *uh = udp_hdr(skb);
|
||||
__be32 old_sec_l, old_nsec;
|
||||
__be16 old_sec_h;
|
||||
|
||||
old_sec_h = *(__be16 *)(data + offset2);
|
||||
inet_proto_csum_replace2(&uh->check, skb, old_sec_h,
|
||||
new_sec_h, false);
|
||||
|
||||
old_sec_l = *(__be32 *)(data + offset2 + 2);
|
||||
inet_proto_csum_replace4(&uh->check, skb, old_sec_l,
|
||||
new_sec_l, false);
|
||||
|
||||
old_nsec = *(__be32 *)(data + offset2 + 6);
|
||||
inet_proto_csum_replace4(&uh->check, skb, old_nsec,
|
||||
new_nsec, false);
|
||||
}
|
||||
|
||||
*(__be16 *)(data + offset2) = new_sec_h;
|
||||
*(__be32 *)(data + offset2 + 2) = new_sec_l;
|
||||
*(__be32 *)(data + offset2 + 6) = new_nsec;
|
||||
|
||||
/* Configure single-step register */
|
||||
val = ENETC_PM0_SINGLE_STEP_EN;
|
||||
@@ -306,25 +351,20 @@ static int enetc_map_tx_buffs(struct enetc_bdr *tx_ring, struct sk_buff *skb)
|
||||
dma_err:
|
||||
dev_err(tx_ring->dev, "DMA map error");
|
||||
|
||||
do {
|
||||
tx_swbd = &tx_ring->tx_swbd[i];
|
||||
enetc_free_tx_frame(tx_ring, tx_swbd);
|
||||
if (i == 0)
|
||||
i = tx_ring->bd_count;
|
||||
i--;
|
||||
} while (count--);
|
||||
enetc_unwind_tx_frame(tx_ring, count, i);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void enetc_map_tx_tso_hdr(struct enetc_bdr *tx_ring, struct sk_buff *skb,
|
||||
struct enetc_tx_swbd *tx_swbd,
|
||||
union enetc_tx_bd *txbd, int *i, int hdr_len,
|
||||
int data_len)
|
||||
static int enetc_map_tx_tso_hdr(struct enetc_bdr *tx_ring, struct sk_buff *skb,
|
||||
struct enetc_tx_swbd *tx_swbd,
|
||||
union enetc_tx_bd *txbd, int *i, int hdr_len,
|
||||
int data_len)
|
||||
{
|
||||
union enetc_tx_bd txbd_tmp;
|
||||
u8 flags = 0, e_flags = 0;
|
||||
dma_addr_t addr;
|
||||
int count = 1;
|
||||
|
||||
enetc_clear_tx_bd(&txbd_tmp);
|
||||
addr = tx_ring->tso_headers_dma + *i * TSO_HEADER_SIZE;
|
||||
@@ -367,7 +407,10 @@ static void enetc_map_tx_tso_hdr(struct enetc_bdr *tx_ring, struct sk_buff *skb,
|
||||
/* Write the BD */
|
||||
txbd_tmp.ext.e_flags = e_flags;
|
||||
*txbd = txbd_tmp;
|
||||
count++;
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
static int enetc_map_tx_tso_data(struct enetc_bdr *tx_ring, struct sk_buff *skb,
|
||||
@@ -499,9 +542,9 @@ static int enetc_map_tx_tso_buffs(struct enetc_bdr *tx_ring, struct sk_buff *skb
|
||||
|
||||
/* compute the csum over the L4 header */
|
||||
csum = enetc_tso_hdr_csum(&tso, skb, hdr, hdr_len, &pos);
|
||||
enetc_map_tx_tso_hdr(tx_ring, skb, tx_swbd, txbd, &i, hdr_len, data_len);
|
||||
count += enetc_map_tx_tso_hdr(tx_ring, skb, tx_swbd, txbd,
|
||||
&i, hdr_len, data_len);
|
||||
bd_data_num = 0;
|
||||
count++;
|
||||
|
||||
while (data_len > 0) {
|
||||
int size;
|
||||
@@ -525,8 +568,13 @@ static int enetc_map_tx_tso_buffs(struct enetc_bdr *tx_ring, struct sk_buff *skb
|
||||
err = enetc_map_tx_tso_data(tx_ring, skb, tx_swbd, txbd,
|
||||
tso.data, size,
|
||||
size == data_len);
|
||||
if (err)
|
||||
if (err) {
|
||||
if (i == 0)
|
||||
i = tx_ring->bd_count;
|
||||
i--;
|
||||
|
||||
goto err_map_data;
|
||||
}
|
||||
|
||||
data_len -= size;
|
||||
count++;
|
||||
@@ -555,13 +603,7 @@ err_map_data:
|
||||
dev_err(tx_ring->dev, "DMA map error");
|
||||
|
||||
err_chained_bd:
|
||||
do {
|
||||
tx_swbd = &tx_ring->tx_swbd[i];
|
||||
enetc_free_tx_frame(tx_ring, tx_swbd);
|
||||
if (i == 0)
|
||||
i = tx_ring->bd_count;
|
||||
i--;
|
||||
} while (count--);
|
||||
enetc_unwind_tx_frame(tx_ring, count, i);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -1581,7 +1623,7 @@ static int enetc_clean_rx_ring_xdp(struct enetc_bdr *rx_ring,
|
||||
enetc_xdp_drop(rx_ring, orig_i, i);
|
||||
tx_ring->stats.xdp_tx_drops++;
|
||||
} else {
|
||||
tx_ring->stats.xdp_tx += xdp_tx_bd_cnt;
|
||||
tx_ring->stats.xdp_tx++;
|
||||
rx_ring->xdp.xdp_tx_in_flight += xdp_tx_bd_cnt;
|
||||
xdp_tx_frm_cnt++;
|
||||
/* The XDP_TX enqueue was successful, so we
|
||||
|
||||
@@ -324,7 +324,7 @@ static const struct mvpp2_cls_flow cls_flows[MVPP2_N_PRS_FLOWS] = {
|
||||
MVPP2_PRS_RI_VLAN_MASK),
|
||||
/* Non IP flow, with vlan tag */
|
||||
MVPP2_DEF_FLOW(MVPP22_FLOW_ETHERNET, MVPP2_FL_NON_IP_TAG,
|
||||
MVPP22_CLS_HEK_OPT_VLAN,
|
||||
MVPP22_CLS_HEK_TAGGED,
|
||||
0, 0),
|
||||
};
|
||||
|
||||
|
||||
@@ -513,7 +513,7 @@ irq_pool_alloc(struct mlx5_core_dev *dev, int start, int size, char *name,
|
||||
pool->min_threshold = min_threshold * MLX5_EQ_REFS_PER_IRQ;
|
||||
pool->max_threshold = max_threshold * MLX5_EQ_REFS_PER_IRQ;
|
||||
mlx5_core_dbg(dev, "pool->name = %s, pool->size = %d, pool->start = %d",
|
||||
name, size, start);
|
||||
name ? name : "mlx5_pcif_pool", size, start);
|
||||
return pool;
|
||||
}
|
||||
|
||||
|
||||
@@ -20,6 +20,8 @@ nfp_bpf_cmsg_alloc(struct nfp_app_bpf *bpf, unsigned int size)
|
||||
struct sk_buff *skb;
|
||||
|
||||
skb = nfp_app_ctrl_msg_alloc(bpf->app, size, GFP_KERNEL);
|
||||
if (!skb)
|
||||
return NULL;
|
||||
skb_put(skb, size);
|
||||
|
||||
return skb;
|
||||
|
||||
@@ -2,6 +2,9 @@
|
||||
/* Copyright (c) 2014 Mahesh Bandewar <maheshb@google.com>
|
||||
*/
|
||||
|
||||
#include <net/inet_dscp.h>
|
||||
#include <net/ip.h>
|
||||
|
||||
#include "ipvlan.h"
|
||||
|
||||
static u32 ipvlan_jhash_secret __read_mostly;
|
||||
@@ -413,20 +416,25 @@ struct ipvl_addr *ipvlan_addr_lookup(struct ipvl_port *port, void *lyr3h,
|
||||
|
||||
static noinline_for_stack int ipvlan_process_v4_outbound(struct sk_buff *skb)
|
||||
{
|
||||
const struct iphdr *ip4h = ip_hdr(skb);
|
||||
struct net_device *dev = skb->dev;
|
||||
struct net *net = dev_net(dev);
|
||||
struct rtable *rt;
|
||||
int err, ret = NET_XMIT_DROP;
|
||||
const struct iphdr *ip4h;
|
||||
struct rtable *rt;
|
||||
struct flowi4 fl4 = {
|
||||
.flowi4_oif = dev->ifindex,
|
||||
.flowi4_tos = RT_TOS(ip4h->tos),
|
||||
.flowi4_flags = FLOWI_FLAG_ANYSRC,
|
||||
.flowi4_mark = skb->mark,
|
||||
.daddr = ip4h->daddr,
|
||||
.saddr = ip4h->saddr,
|
||||
};
|
||||
|
||||
if (!pskb_network_may_pull(skb, sizeof(struct iphdr)))
|
||||
goto err;
|
||||
|
||||
ip4h = ip_hdr(skb);
|
||||
fl4.daddr = ip4h->daddr;
|
||||
fl4.saddr = ip4h->saddr;
|
||||
fl4.flowi4_tos = inet_dscp_to_dsfield(ip4h_dscp(ip4h));
|
||||
|
||||
rt = ip_route_output_flow(net, &fl4, NULL);
|
||||
if (IS_ERR(rt))
|
||||
goto err;
|
||||
@@ -485,6 +493,12 @@ static int ipvlan_process_v6_outbound(struct sk_buff *skb)
|
||||
struct net_device *dev = skb->dev;
|
||||
int err, ret = NET_XMIT_DROP;
|
||||
|
||||
if (!pskb_network_may_pull(skb, sizeof(struct ipv6hdr))) {
|
||||
DEV_STATS_INC(dev, tx_errors);
|
||||
kfree_skb(skb);
|
||||
return ret;
|
||||
}
|
||||
|
||||
err = ipvlan_route_v6_outbound(dev, skb);
|
||||
if (unlikely(err)) {
|
||||
DEV_STATS_INC(dev, tx_errors);
|
||||
|
||||
@@ -246,8 +246,22 @@ static netdev_tx_t blackhole_netdev_xmit(struct sk_buff *skb,
|
||||
return NETDEV_TX_OK;
|
||||
}
|
||||
|
||||
static int blackhole_neigh_output(struct neighbour *n, struct sk_buff *skb)
|
||||
{
|
||||
kfree_skb(skb);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int blackhole_neigh_construct(struct net_device *dev,
|
||||
struct neighbour *n)
|
||||
{
|
||||
n->output = blackhole_neigh_output;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct net_device_ops blackhole_netdev_ops = {
|
||||
.ndo_start_xmit = blackhole_netdev_xmit,
|
||||
.ndo_neigh_construct = blackhole_neigh_construct,
|
||||
};
|
||||
|
||||
/* This is a dst-dummy device used specifically for invalidated
|
||||
|
||||
@@ -179,9 +179,7 @@ static int genelink_bind(struct usbnet *dev, struct usb_interface *intf)
|
||||
{
|
||||
dev->hard_mtu = GL_RCV_BUF_SIZE;
|
||||
dev->net->hard_header_len += 4;
|
||||
dev->in = usb_rcvbulkpipe(dev->udev, dev->driver_info->in);
|
||||
dev->out = usb_sndbulkpipe(dev->udev, dev->driver_info->out);
|
||||
return 0;
|
||||
return usbnet_get_endpoints(dev, intf);
|
||||
}
|
||||
|
||||
static const struct driver_info genelink_info = {
|
||||
|
||||
@@ -262,8 +262,7 @@ static bool nvme_validate_passthru_nsid(struct nvme_ctrl *ctrl,
|
||||
{
|
||||
if (ns && nsid != ns->head->ns_id) {
|
||||
dev_err(ctrl->device,
|
||||
"%s: nsid (%u) in cmd does not match nsid (%u)"
|
||||
"of namespace\n",
|
||||
"%s: nsid (%u) in cmd does not match nsid (%u) of namespace\n",
|
||||
current->comm, nsid, ns->head->ns_id);
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -299,7 +299,10 @@ static int rockchip_combphy_parse_dt(struct device *dev, struct rockchip_combphy
|
||||
|
||||
priv->ext_refclk = device_property_present(dev, "rockchip,ext-refclk");
|
||||
|
||||
priv->phy_rst = devm_reset_control_get(dev, "phy");
|
||||
priv->phy_rst = devm_reset_control_get_exclusive(dev, "phy");
|
||||
/* fallback to old behaviour */
|
||||
if (PTR_ERR(priv->phy_rst) == -ENOENT)
|
||||
priv->phy_rst = devm_reset_control_array_get_exclusive(dev);
|
||||
if (IS_ERR(priv->phy_rst))
|
||||
return dev_err_probe(dev, PTR_ERR(priv->phy_rst), "failed to get phy reset\n");
|
||||
|
||||
|
||||
@@ -288,9 +288,9 @@ exynos5_usbdrd_pipe3_set_refclk(struct phy_usb_instance *inst)
|
||||
reg |= PHYCLKRST_REFCLKSEL_EXT_REFCLK;
|
||||
|
||||
/* FSEL settings corresponding to reference clock */
|
||||
reg &= ~PHYCLKRST_FSEL_PIPE_MASK |
|
||||
PHYCLKRST_MPLL_MULTIPLIER_MASK |
|
||||
PHYCLKRST_SSC_REFCLKSEL_MASK;
|
||||
reg &= ~(PHYCLKRST_FSEL_PIPE_MASK |
|
||||
PHYCLKRST_MPLL_MULTIPLIER_MASK |
|
||||
PHYCLKRST_SSC_REFCLKSEL_MASK);
|
||||
switch (phy_drd->extrefclk) {
|
||||
case EXYNOS5_FSEL_50MHZ:
|
||||
reg |= (PHYCLKRST_MPLL_MULTIPLIER_50M_REF |
|
||||
@@ -332,9 +332,9 @@ exynos5_usbdrd_utmi_set_refclk(struct phy_usb_instance *inst)
|
||||
reg &= ~PHYCLKRST_REFCLKSEL_MASK;
|
||||
reg |= PHYCLKRST_REFCLKSEL_EXT_REFCLK;
|
||||
|
||||
reg &= ~PHYCLKRST_FSEL_UTMI_MASK |
|
||||
PHYCLKRST_MPLL_MULTIPLIER_MASK |
|
||||
PHYCLKRST_SSC_REFCLKSEL_MASK;
|
||||
reg &= ~(PHYCLKRST_FSEL_UTMI_MASK |
|
||||
PHYCLKRST_MPLL_MULTIPLIER_MASK |
|
||||
PHYCLKRST_SSC_REFCLKSEL_MASK);
|
||||
reg |= PHYCLKRST_FSEL(phy_drd->extrefclk);
|
||||
|
||||
return reg;
|
||||
|
||||
@@ -900,6 +900,7 @@ static int tegra186_utmi_phy_exit(struct phy *phy)
|
||||
unsigned int index = lane->index;
|
||||
struct device *dev = padctl->dev;
|
||||
int err;
|
||||
u32 reg;
|
||||
|
||||
port = tegra_xusb_find_usb2_port(padctl, index);
|
||||
if (!port) {
|
||||
@@ -907,6 +908,16 @@ static int tegra186_utmi_phy_exit(struct phy *phy)
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
if (port->mode == USB_DR_MODE_OTG ||
|
||||
port->mode == USB_DR_MODE_PERIPHERAL) {
|
||||
/* reset VBUS&ID OVERRIDE */
|
||||
reg = padctl_readl(padctl, USB2_VBUS_ID);
|
||||
reg &= ~VBUS_OVERRIDE;
|
||||
reg &= ~ID_OVERRIDE(~0);
|
||||
reg |= ID_OVERRIDE_FLOATING;
|
||||
padctl_writel(padctl, reg, USB2_VBUS_ID);
|
||||
}
|
||||
|
||||
if (port->supply && port->mode == USB_DR_MODE_HOST) {
|
||||
err = regulator_disable(port->supply);
|
||||
if (err) {
|
||||
|
||||
@@ -248,9 +248,9 @@ static int da9150_fg_current_avg(struct da9150_fg *fg,
|
||||
DA9150_QIF_SD_GAIN_SIZE);
|
||||
da9150_fg_read_sync_end(fg);
|
||||
|
||||
div = (u64) (sd_gain * shunt_val * 65536ULL);
|
||||
div = 65536ULL * sd_gain * shunt_val;
|
||||
do_div(div, 1000000);
|
||||
res = (u64) (iavg * 1000000ULL);
|
||||
res = 1000000ULL * iavg;
|
||||
do_div(res, div);
|
||||
|
||||
val->intval = (int) res;
|
||||
|
||||
@@ -1575,13 +1575,6 @@ static blk_status_t scsi_prepare_cmd(struct request *req)
|
||||
if (in_flight)
|
||||
__set_bit(SCMD_STATE_INFLIGHT, &cmd->state);
|
||||
|
||||
/*
|
||||
* Only clear the driver-private command data if the LLD does not supply
|
||||
* a function to initialize that data.
|
||||
*/
|
||||
if (!shost->hostt->init_cmd_priv)
|
||||
memset(cmd + 1, 0, shost->hostt->cmd_size);
|
||||
|
||||
cmd->prot_op = SCSI_PROT_NORMAL;
|
||||
if (blk_rq_bytes(req))
|
||||
cmd->sc_data_direction = rq_dma_dir(req);
|
||||
@@ -1748,6 +1741,13 @@ static blk_status_t scsi_queue_rq(struct blk_mq_hw_ctx *hctx,
|
||||
if (!scsi_host_queue_ready(q, shost, sdev, cmd))
|
||||
goto out_dec_target_busy;
|
||||
|
||||
/*
|
||||
* Only clear the driver-private command data if the LLD does not supply
|
||||
* a function to initialize that data.
|
||||
*/
|
||||
if (shost->hostt->cmd_size && !shost->hostt->init_cmd_priv)
|
||||
memset(cmd + 1, 0, shost->hostt->cmd_size);
|
||||
|
||||
if (!(req->rq_flags & RQF_DONTPREP)) {
|
||||
ret = scsi_prepare_cmd(req);
|
||||
if (ret != BLK_STS_OK)
|
||||
|
||||
@@ -388,9 +388,9 @@ static int atmel_qspi_set_cfg(struct atmel_qspi *aq,
|
||||
* If the QSPI controller is set in regular SPI mode, set it in
|
||||
* Serial Memory Mode (SMM).
|
||||
*/
|
||||
if (aq->mr != QSPI_MR_SMM) {
|
||||
atmel_qspi_write(QSPI_MR_SMM, aq, QSPI_MR);
|
||||
aq->mr = QSPI_MR_SMM;
|
||||
if (!(aq->mr & QSPI_MR_SMM)) {
|
||||
aq->mr |= QSPI_MR_SMM;
|
||||
atmel_qspi_write(aq->mr, aq, QSPI_MR);
|
||||
}
|
||||
|
||||
/* Clear pending interrupts */
|
||||
@@ -545,7 +545,8 @@ static int atmel_qspi_setup(struct spi_device *spi)
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
aq->scr = QSPI_SCR_SCBR(scbr);
|
||||
aq->scr &= ~QSPI_SCR_SCBR_MASK;
|
||||
aq->scr |= QSPI_SCR_SCBR(scbr);
|
||||
atmel_qspi_write(aq->scr, aq, QSPI_SCR);
|
||||
|
||||
pm_runtime_mark_last_busy(ctrl->dev.parent);
|
||||
@@ -578,6 +579,7 @@ static int atmel_qspi_set_cs_timing(struct spi_device *spi)
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
aq->scr &= ~QSPI_SCR_DLYBS_MASK;
|
||||
aq->scr |= QSPI_SCR_DLYBS(cs_setup);
|
||||
atmel_qspi_write(aq->scr, aq, QSPI_SCR);
|
||||
|
||||
@@ -593,8 +595,8 @@ static void atmel_qspi_init(struct atmel_qspi *aq)
|
||||
atmel_qspi_write(QSPI_CR_SWRST, aq, QSPI_CR);
|
||||
|
||||
/* Set the QSPI controller by default in Serial Memory Mode */
|
||||
atmel_qspi_write(QSPI_MR_SMM, aq, QSPI_MR);
|
||||
aq->mr = QSPI_MR_SMM;
|
||||
aq->mr |= QSPI_MR_SMM;
|
||||
atmel_qspi_write(aq->mr, aq, QSPI_MR);
|
||||
|
||||
/* Enable the QSPI controller */
|
||||
atmel_qspi_write(QSPI_CR_QSPIEN, aq, QSPI_CR);
|
||||
|
||||
@@ -80,7 +80,6 @@ u32 optee_supp_thrd_req(struct tee_context *ctx, u32 func, size_t num_params,
|
||||
struct optee *optee = tee_get_drvdata(ctx->teedev);
|
||||
struct optee_supp *supp = &optee->supp;
|
||||
struct optee_supp_req *req;
|
||||
bool interruptable;
|
||||
u32 ret;
|
||||
|
||||
/*
|
||||
@@ -111,36 +110,18 @@ u32 optee_supp_thrd_req(struct tee_context *ctx, u32 func, size_t num_params,
|
||||
/*
|
||||
* Wait for supplicant to process and return result, once we've
|
||||
* returned from wait_for_completion(&req->c) successfully we have
|
||||
* exclusive access again.
|
||||
* exclusive access again. Allow the wait to be killable such that
|
||||
* the wait doesn't turn into an indefinite state if the supplicant
|
||||
* gets hung for some reason.
|
||||
*/
|
||||
while (wait_for_completion_interruptible(&req->c)) {
|
||||
if (wait_for_completion_killable(&req->c)) {
|
||||
mutex_lock(&supp->mutex);
|
||||
interruptable = !supp->ctx;
|
||||
if (interruptable) {
|
||||
/*
|
||||
* There's no supplicant available and since the
|
||||
* supp->mutex currently is held none can
|
||||
* become available until the mutex released
|
||||
* again.
|
||||
*
|
||||
* Interrupting an RPC to supplicant is only
|
||||
* allowed as a way of slightly improving the user
|
||||
* experience in case the supplicant hasn't been
|
||||
* started yet. During normal operation the supplicant
|
||||
* will serve all requests in a timely manner and
|
||||
* interrupting then wouldn't make sense.
|
||||
*/
|
||||
if (req->in_queue) {
|
||||
list_del(&req->link);
|
||||
req->in_queue = false;
|
||||
}
|
||||
if (req->in_queue) {
|
||||
list_del(&req->link);
|
||||
req->in_queue = false;
|
||||
}
|
||||
mutex_unlock(&supp->mutex);
|
||||
|
||||
if (interruptable) {
|
||||
req->ret = TEEC_ERROR_COMMUNICATION;
|
||||
break;
|
||||
}
|
||||
req->ret = TEEC_ERROR_COMMUNICATION;
|
||||
}
|
||||
|
||||
ret = req->ret;
|
||||
|
||||
@@ -161,6 +161,7 @@ static struct afs_cell *afs_alloc_cell(struct afs_net *net,
|
||||
refcount_set(&cell->ref, 1);
|
||||
atomic_set(&cell->active, 0);
|
||||
INIT_WORK(&cell->manager, afs_manage_cell_work);
|
||||
spin_lock_init(&cell->vs_lock);
|
||||
cell->volumes = RB_ROOT;
|
||||
INIT_HLIST_HEAD(&cell->proc_volumes);
|
||||
seqlock_init(&cell->volume_lock);
|
||||
|
||||
@@ -378,6 +378,7 @@ struct afs_cell {
|
||||
unsigned int debug_id;
|
||||
|
||||
/* The volumes belonging to this cell */
|
||||
spinlock_t vs_lock; /* Lock for server->volumes */
|
||||
struct rb_root volumes; /* Tree of volumes on this server */
|
||||
struct hlist_head proc_volumes; /* procfs volume list */
|
||||
seqlock_t volume_lock; /* For volumes */
|
||||
@@ -501,6 +502,7 @@ struct afs_server {
|
||||
struct hlist_node addr4_link; /* Link in net->fs_addresses4 */
|
||||
struct hlist_node addr6_link; /* Link in net->fs_addresses6 */
|
||||
struct hlist_node proc_link; /* Link in net->fs_proc */
|
||||
struct list_head volumes; /* RCU list of afs_server_entry objects */
|
||||
struct work_struct initcb_work; /* Work for CB.InitCallBackState* */
|
||||
struct afs_server *gc_next; /* Next server in manager's list */
|
||||
time64_t unuse_time; /* Time at which last unused */
|
||||
@@ -549,12 +551,14 @@ struct afs_server {
|
||||
*/
|
||||
struct afs_server_entry {
|
||||
struct afs_server *server;
|
||||
struct afs_volume *volume;
|
||||
struct list_head slink; /* Link in server->volumes */
|
||||
};
|
||||
|
||||
struct afs_server_list {
|
||||
struct rcu_head rcu;
|
||||
afs_volid_t vids[AFS_MAXTYPES]; /* Volume IDs */
|
||||
refcount_t usage;
|
||||
bool attached; /* T if attached to servers */
|
||||
unsigned char nr_servers;
|
||||
unsigned char preferred; /* Preferred server */
|
||||
unsigned short vnovol_mask; /* Servers to be skipped due to VNOVOL */
|
||||
@@ -567,10 +571,9 @@ struct afs_server_list {
|
||||
* Live AFS volume management.
|
||||
*/
|
||||
struct afs_volume {
|
||||
union {
|
||||
struct rcu_head rcu;
|
||||
afs_volid_t vid; /* volume ID */
|
||||
};
|
||||
struct rcu_head rcu;
|
||||
afs_volid_t vid; /* The volume ID of this volume */
|
||||
afs_volid_t vids[AFS_MAXTYPES]; /* All associated volume IDs */
|
||||
refcount_t ref;
|
||||
time64_t update_at; /* Time at which to next update */
|
||||
struct afs_cell *cell; /* Cell to which belongs (pins ref) */
|
||||
@@ -1450,10 +1453,14 @@ static inline struct afs_server_list *afs_get_serverlist(struct afs_server_list
|
||||
}
|
||||
|
||||
extern void afs_put_serverlist(struct afs_net *, struct afs_server_list *);
|
||||
extern struct afs_server_list *afs_alloc_server_list(struct afs_cell *, struct key *,
|
||||
struct afs_vldb_entry *,
|
||||
u8);
|
||||
struct afs_server_list *afs_alloc_server_list(struct afs_volume *volume,
|
||||
struct key *key,
|
||||
struct afs_vldb_entry *vldb);
|
||||
extern bool afs_annotate_server_list(struct afs_server_list *, struct afs_server_list *);
|
||||
void afs_attach_volume_to_servers(struct afs_volume *volume, struct afs_server_list *slist);
|
||||
void afs_reattach_volume_to_servers(struct afs_volume *volume, struct afs_server_list *slist,
|
||||
struct afs_server_list *old);
|
||||
void afs_detach_volume_from_servers(struct afs_volume *volume, struct afs_server_list *slist);
|
||||
|
||||
/*
|
||||
* super.c
|
||||
|
||||
@@ -236,6 +236,7 @@ static struct afs_server *afs_alloc_server(struct afs_cell *cell,
|
||||
server->addr_version = alist->version;
|
||||
server->uuid = *uuid;
|
||||
rwlock_init(&server->fs_lock);
|
||||
INIT_LIST_HEAD(&server->volumes);
|
||||
INIT_WORK(&server->initcb_work, afs_server_init_callback_work);
|
||||
init_waitqueue_head(&server->probe_wq);
|
||||
INIT_LIST_HEAD(&server->probe_link);
|
||||
|
||||
@@ -24,13 +24,13 @@ void afs_put_serverlist(struct afs_net *net, struct afs_server_list *slist)
|
||||
/*
|
||||
* Build a server list from a VLDB record.
|
||||
*/
|
||||
struct afs_server_list *afs_alloc_server_list(struct afs_cell *cell,
|
||||
struct afs_server_list *afs_alloc_server_list(struct afs_volume *volume,
|
||||
struct key *key,
|
||||
struct afs_vldb_entry *vldb,
|
||||
u8 type_mask)
|
||||
struct afs_vldb_entry *vldb)
|
||||
{
|
||||
struct afs_server_list *slist;
|
||||
struct afs_server *server;
|
||||
unsigned int type_mask = 1 << volume->type;
|
||||
int ret = -ENOMEM, nr_servers = 0, i, j;
|
||||
|
||||
for (i = 0; i < vldb->nr_servers; i++)
|
||||
@@ -44,15 +44,12 @@ struct afs_server_list *afs_alloc_server_list(struct afs_cell *cell,
|
||||
refcount_set(&slist->usage, 1);
|
||||
rwlock_init(&slist->lock);
|
||||
|
||||
for (i = 0; i < AFS_MAXTYPES; i++)
|
||||
slist->vids[i] = vldb->vid[i];
|
||||
|
||||
/* Make sure a records exists for each server in the list. */
|
||||
for (i = 0; i < vldb->nr_servers; i++) {
|
||||
if (!(vldb->fs_mask[i] & type_mask))
|
||||
continue;
|
||||
|
||||
server = afs_lookup_server(cell, key, &vldb->fs_server[i],
|
||||
server = afs_lookup_server(volume->cell, key, &vldb->fs_server[i],
|
||||
vldb->addr_version[i]);
|
||||
if (IS_ERR(server)) {
|
||||
ret = PTR_ERR(server);
|
||||
@@ -70,8 +67,8 @@ struct afs_server_list *afs_alloc_server_list(struct afs_cell *cell,
|
||||
break;
|
||||
if (j < slist->nr_servers) {
|
||||
if (slist->servers[j].server == server) {
|
||||
afs_put_server(cell->net, server,
|
||||
afs_server_trace_put_slist_isort);
|
||||
afs_unuse_server(volume->cell->net, server,
|
||||
afs_server_trace_put_slist_isort);
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -81,6 +78,7 @@ struct afs_server_list *afs_alloc_server_list(struct afs_cell *cell,
|
||||
}
|
||||
|
||||
slist->servers[j].server = server;
|
||||
slist->servers[j].volume = volume;
|
||||
slist->nr_servers++;
|
||||
}
|
||||
|
||||
@@ -92,7 +90,7 @@ struct afs_server_list *afs_alloc_server_list(struct afs_cell *cell,
|
||||
return slist;
|
||||
|
||||
error_2:
|
||||
afs_put_serverlist(cell->net, slist);
|
||||
afs_put_serverlist(volume->cell->net, slist);
|
||||
error:
|
||||
return ERR_PTR(ret);
|
||||
}
|
||||
@@ -127,3 +125,99 @@ changed:
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* Attach a volume to the servers it is going to use.
|
||||
*/
|
||||
void afs_attach_volume_to_servers(struct afs_volume *volume, struct afs_server_list *slist)
|
||||
{
|
||||
struct afs_server_entry *se, *pe;
|
||||
struct afs_server *server;
|
||||
struct list_head *p;
|
||||
unsigned int i;
|
||||
|
||||
spin_lock(&volume->cell->vs_lock);
|
||||
|
||||
for (i = 0; i < slist->nr_servers; i++) {
|
||||
se = &slist->servers[i];
|
||||
server = se->server;
|
||||
|
||||
list_for_each(p, &server->volumes) {
|
||||
pe = list_entry(p, struct afs_server_entry, slink);
|
||||
if (volume->vid <= pe->volume->vid)
|
||||
break;
|
||||
}
|
||||
list_add_tail_rcu(&se->slink, p);
|
||||
}
|
||||
|
||||
slist->attached = true;
|
||||
spin_unlock(&volume->cell->vs_lock);
|
||||
}
|
||||
|
||||
/*
|
||||
* Reattach a volume to the servers it is going to use when server list is
|
||||
* replaced. We try to switch the attachment points to avoid rewalking the
|
||||
* lists.
|
||||
*/
|
||||
void afs_reattach_volume_to_servers(struct afs_volume *volume, struct afs_server_list *new,
|
||||
struct afs_server_list *old)
|
||||
{
|
||||
unsigned int n = 0, o = 0;
|
||||
|
||||
spin_lock(&volume->cell->vs_lock);
|
||||
|
||||
while (n < new->nr_servers || o < old->nr_servers) {
|
||||
struct afs_server_entry *pn = n < new->nr_servers ? &new->servers[n] : NULL;
|
||||
struct afs_server_entry *po = o < old->nr_servers ? &old->servers[o] : NULL;
|
||||
struct afs_server_entry *s;
|
||||
struct list_head *p;
|
||||
int diff;
|
||||
|
||||
if (pn && po && pn->server == po->server) {
|
||||
list_replace_rcu(&po->slink, &pn->slink);
|
||||
n++;
|
||||
o++;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (pn && po)
|
||||
diff = memcmp(&pn->server->uuid, &po->server->uuid,
|
||||
sizeof(pn->server->uuid));
|
||||
else
|
||||
diff = pn ? -1 : 1;
|
||||
|
||||
if (diff < 0) {
|
||||
list_for_each(p, &pn->server->volumes) {
|
||||
s = list_entry(p, struct afs_server_entry, slink);
|
||||
if (volume->vid <= s->volume->vid)
|
||||
break;
|
||||
}
|
||||
list_add_tail_rcu(&pn->slink, p);
|
||||
n++;
|
||||
} else {
|
||||
list_del_rcu(&po->slink);
|
||||
o++;
|
||||
}
|
||||
}
|
||||
|
||||
spin_unlock(&volume->cell->vs_lock);
|
||||
}
|
||||
|
||||
/*
|
||||
* Detach a volume from the servers it has been using.
|
||||
*/
|
||||
void afs_detach_volume_from_servers(struct afs_volume *volume, struct afs_server_list *slist)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
if (!slist->attached)
|
||||
return;
|
||||
|
||||
spin_lock(&volume->cell->vs_lock);
|
||||
|
||||
for (i = 0; i < slist->nr_servers; i++)
|
||||
list_del_rcu(&slist->servers[i].slink);
|
||||
|
||||
slist->attached = false;
|
||||
spin_unlock(&volume->cell->vs_lock);
|
||||
}
|
||||
|
||||
@@ -126,7 +126,7 @@ static int afs_compare_volume_slists(const struct afs_volume *vol_a,
|
||||
lb = rcu_dereference(vol_b->servers);
|
||||
|
||||
for (i = 0; i < AFS_MAXTYPES; i++)
|
||||
if (la->vids[i] != lb->vids[i])
|
||||
if (vol_a->vids[i] != vol_b->vids[i])
|
||||
return 0;
|
||||
|
||||
while (a < la->nr_servers && b < lb->nr_servers) {
|
||||
|
||||
@@ -72,15 +72,11 @@ static void afs_remove_volume_from_cell(struct afs_volume *volume)
|
||||
*/
|
||||
static struct afs_volume *afs_alloc_volume(struct afs_fs_context *params,
|
||||
struct afs_vldb_entry *vldb,
|
||||
unsigned long type_mask)
|
||||
struct afs_server_list **_slist)
|
||||
{
|
||||
struct afs_server_list *slist;
|
||||
struct afs_volume *volume;
|
||||
int ret = -ENOMEM, nr_servers = 0, i;
|
||||
|
||||
for (i = 0; i < vldb->nr_servers; i++)
|
||||
if (vldb->fs_mask[i] & type_mask)
|
||||
nr_servers++;
|
||||
int ret = -ENOMEM, i;
|
||||
|
||||
volume = kzalloc(sizeof(struct afs_volume), GFP_KERNEL);
|
||||
if (!volume)
|
||||
@@ -99,13 +95,16 @@ static struct afs_volume *afs_alloc_volume(struct afs_fs_context *params,
|
||||
rwlock_init(&volume->cb_v_break_lock);
|
||||
memcpy(volume->name, vldb->name, vldb->name_len + 1);
|
||||
|
||||
slist = afs_alloc_server_list(params->cell, params->key, vldb, type_mask);
|
||||
for (i = 0; i < AFS_MAXTYPES; i++)
|
||||
volume->vids[i] = vldb->vid[i];
|
||||
|
||||
slist = afs_alloc_server_list(volume, params->key, vldb);
|
||||
if (IS_ERR(slist)) {
|
||||
ret = PTR_ERR(slist);
|
||||
goto error_1;
|
||||
}
|
||||
|
||||
refcount_set(&slist->usage, 1);
|
||||
*_slist = slist;
|
||||
rcu_assign_pointer(volume->servers, slist);
|
||||
trace_afs_volume(volume->vid, 1, afs_volume_trace_alloc);
|
||||
return volume;
|
||||
@@ -121,17 +120,19 @@ error_0:
|
||||
* Look up or allocate a volume record.
|
||||
*/
|
||||
static struct afs_volume *afs_lookup_volume(struct afs_fs_context *params,
|
||||
struct afs_vldb_entry *vldb,
|
||||
unsigned long type_mask)
|
||||
struct afs_vldb_entry *vldb)
|
||||
{
|
||||
struct afs_server_list *slist;
|
||||
struct afs_volume *candidate, *volume;
|
||||
|
||||
candidate = afs_alloc_volume(params, vldb, type_mask);
|
||||
candidate = afs_alloc_volume(params, vldb, &slist);
|
||||
if (IS_ERR(candidate))
|
||||
return candidate;
|
||||
|
||||
volume = afs_insert_volume_into_cell(params->cell, candidate);
|
||||
if (volume != candidate)
|
||||
if (volume == candidate)
|
||||
afs_attach_volume_to_servers(volume, slist);
|
||||
else
|
||||
afs_put_volume(params->net, candidate, afs_volume_trace_put_cell_dup);
|
||||
return volume;
|
||||
}
|
||||
@@ -212,8 +213,7 @@ struct afs_volume *afs_create_volume(struct afs_fs_context *params)
|
||||
goto error;
|
||||
}
|
||||
|
||||
type_mask = 1UL << params->type;
|
||||
volume = afs_lookup_volume(params, vldb, type_mask);
|
||||
volume = afs_lookup_volume(params, vldb);
|
||||
|
||||
error:
|
||||
kfree(vldb);
|
||||
@@ -225,14 +225,17 @@ error:
|
||||
*/
|
||||
static void afs_destroy_volume(struct afs_net *net, struct afs_volume *volume)
|
||||
{
|
||||
struct afs_server_list *slist = rcu_access_pointer(volume->servers);
|
||||
|
||||
_enter("%p", volume);
|
||||
|
||||
#ifdef CONFIG_AFS_FSCACHE
|
||||
ASSERTCMP(volume->cache, ==, NULL);
|
||||
#endif
|
||||
|
||||
afs_detach_volume_from_servers(volume, slist);
|
||||
afs_remove_volume_from_cell(volume);
|
||||
afs_put_serverlist(net, rcu_access_pointer(volume->servers));
|
||||
afs_put_serverlist(net, slist);
|
||||
afs_put_cell(volume->cell, afs_cell_trace_put_vol);
|
||||
trace_afs_volume(volume->vid, refcount_read(&volume->ref),
|
||||
afs_volume_trace_free);
|
||||
@@ -366,8 +369,7 @@ static int afs_update_volume_status(struct afs_volume *volume, struct key *key)
|
||||
}
|
||||
|
||||
/* See if the volume's server list got updated. */
|
||||
new = afs_alloc_server_list(volume->cell, key,
|
||||
vldb, (1 << volume->type));
|
||||
new = afs_alloc_server_list(volume, key, vldb);
|
||||
if (IS_ERR(new)) {
|
||||
ret = PTR_ERR(new);
|
||||
goto error_vldb;
|
||||
@@ -388,9 +390,11 @@ static int afs_update_volume_status(struct afs_volume *volume, struct key *key)
|
||||
|
||||
volume->update_at = ktime_get_real_seconds() + afs_volume_record_life;
|
||||
write_unlock(&volume->servers_lock);
|
||||
ret = 0;
|
||||
|
||||
if (discard == old)
|
||||
afs_reattach_volume_to_servers(volume, new, old);
|
||||
afs_put_serverlist(volume->cell->net, discard);
|
||||
ret = 0;
|
||||
error_vldb:
|
||||
kfree(vldb);
|
||||
error:
|
||||
|
||||
@@ -532,7 +532,6 @@ static int ovl_link_up(struct ovl_copy_up_ctx *c)
|
||||
err = PTR_ERR(upper);
|
||||
if (!IS_ERR(upper)) {
|
||||
err = ovl_do_link(ofs, ovl_dentry_upper(c->dentry), udir, upper);
|
||||
dput(upper);
|
||||
|
||||
if (!err) {
|
||||
/* Restore timestamps on parent (best effort) */
|
||||
@@ -540,6 +539,7 @@ static int ovl_link_up(struct ovl_copy_up_ctx *c)
|
||||
ovl_dentry_set_upper_alias(c->dentry);
|
||||
ovl_dentry_update_reval(c->dentry, upper);
|
||||
}
|
||||
dput(upper);
|
||||
}
|
||||
inode_unlock(udir);
|
||||
if (err)
|
||||
|
||||
@@ -5158,6 +5158,10 @@ one_more:
|
||||
next_buffer = (char *)cifs_buf_get();
|
||||
else
|
||||
next_buffer = (char *)cifs_small_buf_get();
|
||||
if (!next_buffer) {
|
||||
cifs_server_dbg(VFS, "No memory for (large) SMB response\n");
|
||||
return -1;
|
||||
}
|
||||
memcpy(next_buffer, buf + next_cmd, pdu_length - next_cmd);
|
||||
}
|
||||
|
||||
|
||||
@@ -48,6 +48,10 @@ static int squashfs_new_inode(struct super_block *sb, struct inode *inode,
|
||||
gid_t i_gid;
|
||||
int err;
|
||||
|
||||
inode->i_ino = le32_to_cpu(sqsh_ino->inode_number);
|
||||
if (inode->i_ino == 0)
|
||||
return -EINVAL;
|
||||
|
||||
err = squashfs_get_id(sb, le16_to_cpu(sqsh_ino->uid), &i_uid);
|
||||
if (err)
|
||||
return err;
|
||||
@@ -58,7 +62,6 @@ static int squashfs_new_inode(struct super_block *sb, struct inode *inode,
|
||||
|
||||
i_uid_write(inode, i_uid);
|
||||
i_gid_write(inode, i_gid);
|
||||
inode->i_ino = le32_to_cpu(sqsh_ino->inode_number);
|
||||
inode->i_mtime.tv_sec = le32_to_cpu(sqsh_ino->mtime);
|
||||
inode->i_atime.tv_sec = inode->i_mtime.tv_sec;
|
||||
inode->i_ctime.tv_sec = inode->i_mtime.tv_sec;
|
||||
|
||||
@@ -461,7 +461,7 @@
|
||||
. = ALIGN((align)); \
|
||||
.rodata : AT(ADDR(.rodata) - LOAD_OFFSET) { \
|
||||
__start_rodata = .; \
|
||||
*(.rodata) *(.rodata.*) \
|
||||
*(.rodata) *(.rodata.*) *(.data.rel.ro*) \
|
||||
SCHED_DATA \
|
||||
RO_AFTER_INIT_DATA /* Read only after init */ \
|
||||
. = ALIGN(8); \
|
||||
|
||||
@@ -1870,6 +1870,28 @@ static inline bool page_needs_cow_for_dma(struct vm_area_struct *vma,
|
||||
return page_maybe_dma_pinned(page);
|
||||
}
|
||||
|
||||
/**
|
||||
* is_zero_page - Query if a page is a zero page
|
||||
* @page: The page to query
|
||||
*
|
||||
* This returns true if @page is one of the permanent zero pages.
|
||||
*/
|
||||
static inline bool is_zero_page(const struct page *page)
|
||||
{
|
||||
return is_zero_pfn(page_to_pfn(page));
|
||||
}
|
||||
|
||||
/**
|
||||
* is_zero_folio - Query if a folio is a zero page
|
||||
* @folio: The folio to query
|
||||
*
|
||||
* This returns true if @folio is one of the permanent zero pages.
|
||||
*/
|
||||
static inline bool is_zero_folio(const struct folio *folio)
|
||||
{
|
||||
return is_zero_page(&folio->page);
|
||||
}
|
||||
|
||||
/* MIGRATE_CMA and ZONE_MOVABLE do not allow pin pages */
|
||||
#ifdef CONFIG_MIGRATION
|
||||
static inline bool is_longterm_pinnable_page(struct page *page)
|
||||
@@ -1880,8 +1902,8 @@ static inline bool is_longterm_pinnable_page(struct page *page)
|
||||
if (mt == MIGRATE_CMA || mt == MIGRATE_ISOLATE)
|
||||
return false;
|
||||
#endif
|
||||
/* The zero page may always be pinned */
|
||||
if (is_zero_pfn(page_to_pfn(page)))
|
||||
/* The zero page can be "pinned" but gets special handling. */
|
||||
if (is_zero_page(page))
|
||||
return true;
|
||||
|
||||
/* Coherent device memory must always allow eviction. */
|
||||
|
||||
@@ -402,6 +402,10 @@ static inline void user_single_step_report(struct pt_regs *regs)
|
||||
#define current_user_stack_pointer() user_stack_pointer(current_pt_regs())
|
||||
#endif
|
||||
|
||||
#ifndef exception_ip
|
||||
#define exception_ip(x) instruction_pointer(x)
|
||||
#endif
|
||||
|
||||
extern int task_current_syscall(struct task_struct *target, struct syscall_info *info);
|
||||
|
||||
extern void sigaction_compat_abi(struct k_sigaction *act, struct k_sigaction *oact);
|
||||
|
||||
@@ -87,6 +87,8 @@ struct sk_psock {
|
||||
struct sk_psock_progs progs;
|
||||
#if IS_ENABLED(CONFIG_BPF_STREAM_PARSER)
|
||||
struct strparser strp;
|
||||
u32 copied_seq;
|
||||
u32 ingress_bytes;
|
||||
#endif
|
||||
struct sk_buff_head ingress_skb;
|
||||
struct list_head ingress_msg;
|
||||
|
||||
@@ -140,13 +140,14 @@ struct rpc_task_setup {
|
||||
#define RPC_WAS_SENT(t) ((t)->tk_flags & RPC_TASK_SENT)
|
||||
#define RPC_IS_MOVEABLE(t) ((t)->tk_flags & RPC_TASK_MOVEABLE)
|
||||
|
||||
#define RPC_TASK_RUNNING 0
|
||||
#define RPC_TASK_QUEUED 1
|
||||
#define RPC_TASK_ACTIVE 2
|
||||
#define RPC_TASK_NEED_XMIT 3
|
||||
#define RPC_TASK_NEED_RECV 4
|
||||
#define RPC_TASK_MSG_PIN_WAIT 5
|
||||
#define RPC_TASK_SIGNALLED 6
|
||||
enum {
|
||||
RPC_TASK_RUNNING,
|
||||
RPC_TASK_QUEUED,
|
||||
RPC_TASK_ACTIVE,
|
||||
RPC_TASK_NEED_XMIT,
|
||||
RPC_TASK_NEED_RECV,
|
||||
RPC_TASK_MSG_PIN_WAIT,
|
||||
};
|
||||
|
||||
#define rpc_test_and_set_running(t) \
|
||||
test_and_set_bit(RPC_TASK_RUNNING, &(t)->tk_runstate)
|
||||
@@ -158,7 +159,7 @@ struct rpc_task_setup {
|
||||
|
||||
#define RPC_IS_ACTIVATED(t) test_bit(RPC_TASK_ACTIVE, &(t)->tk_runstate)
|
||||
|
||||
#define RPC_SIGNALLED(t) test_bit(RPC_TASK_SIGNALLED, &(t)->tk_runstate)
|
||||
#define RPC_SIGNALLED(t) (READ_ONCE(task->tk_rpc_status) == -ERESTARTSYS)
|
||||
|
||||
/*
|
||||
* Task priorities.
|
||||
|
||||
@@ -434,6 +434,15 @@ static inline void dst_set_expires(struct dst_entry *dst, int timeout)
|
||||
dst->expires = expires;
|
||||
}
|
||||
|
||||
static inline unsigned int dst_dev_overhead(struct dst_entry *dst,
|
||||
struct sk_buff *skb)
|
||||
{
|
||||
if (likely(dst))
|
||||
return LL_RESERVED_SPACE(dst->dev);
|
||||
|
||||
return skb->mac_len;
|
||||
}
|
||||
|
||||
INDIRECT_CALLABLE_DECLARE(int ip6_output(struct net *, struct sock *,
|
||||
struct sk_buff *));
|
||||
INDIRECT_CALLABLE_DECLARE(int ip_output(struct net *, struct sock *,
|
||||
|
||||
@@ -411,6 +411,11 @@ int ip_decrease_ttl(struct iphdr *iph)
|
||||
return --iph->ttl;
|
||||
}
|
||||
|
||||
static inline dscp_t ip4h_dscp(const struct iphdr *ip4h)
|
||||
{
|
||||
return inet_dsfield_to_dscp(ip4h->tos);
|
||||
}
|
||||
|
||||
static inline int ip_mtu_locked(const struct dst_entry *dst)
|
||||
{
|
||||
const struct rtable *rt = (const struct rtable *)dst;
|
||||
|
||||
@@ -100,7 +100,7 @@ nf_ct_expect_find_get(struct net *net,
|
||||
struct nf_conntrack_expect *
|
||||
nf_ct_find_expectation(struct net *net,
|
||||
const struct nf_conntrack_zone *zone,
|
||||
const struct nf_conntrack_tuple *tuple);
|
||||
const struct nf_conntrack_tuple *tuple, bool unlink);
|
||||
|
||||
void nf_ct_unlink_expect_report(struct nf_conntrack_expect *exp,
|
||||
u32 portid, int report);
|
||||
|
||||
@@ -203,12 +203,13 @@ int ip_route_use_hint(struct sk_buff *skb, __be32 dst, __be32 src,
|
||||
const struct sk_buff *hint);
|
||||
|
||||
static inline int ip_route_input(struct sk_buff *skb, __be32 dst, __be32 src,
|
||||
u8 tos, struct net_device *devin)
|
||||
dscp_t dscp, struct net_device *devin)
|
||||
{
|
||||
int err;
|
||||
|
||||
rcu_read_lock();
|
||||
err = ip_route_input_noref(skb, dst, src, tos, devin);
|
||||
err = ip_route_input_noref(skb, dst, src, inet_dscp_to_dsfield(dscp),
|
||||
devin);
|
||||
if (!err) {
|
||||
skb_dst_force(skb);
|
||||
if (!skb_dst(skb))
|
||||
|
||||
@@ -43,6 +43,8 @@ struct strparser;
|
||||
struct strp_callbacks {
|
||||
int (*parse_msg)(struct strparser *strp, struct sk_buff *skb);
|
||||
void (*rcv_msg)(struct strparser *strp, struct sk_buff *skb);
|
||||
int (*read_sock)(struct strparser *strp, read_descriptor_t *desc,
|
||||
sk_read_actor_t recv_actor);
|
||||
int (*read_sock_done)(struct strparser *strp, int err);
|
||||
void (*abort_parser)(struct strparser *strp, int err);
|
||||
void (*lock)(struct strparser *strp);
|
||||
|
||||
@@ -701,6 +701,9 @@ void tcp_get_info(struct sock *, struct tcp_info *);
|
||||
/* Read 'sendfile()'-style from a TCP socket */
|
||||
int tcp_read_sock(struct sock *sk, read_descriptor_t *desc,
|
||||
sk_read_actor_t recv_actor);
|
||||
int tcp_read_sock_noack(struct sock *sk, read_descriptor_t *desc,
|
||||
sk_read_actor_t recv_actor, bool noack,
|
||||
u32 *copied_seq);
|
||||
int tcp_read_skb(struct sock *sk, skb_read_actor_t recv_actor);
|
||||
struct sk_buff *tcp_recv_skb(struct sock *sk, u32 seq, u32 *off);
|
||||
void tcp_read_done(struct sock *sk, size_t len);
|
||||
@@ -2352,6 +2355,11 @@ struct sk_psock;
|
||||
struct proto *tcp_bpf_get_proto(struct sock *sk, struct sk_psock *psock);
|
||||
int tcp_bpf_update_proto(struct sock *sk, struct sk_psock *psock, bool restore);
|
||||
void tcp_bpf_clone(const struct sock *sk, struct sock *newsk);
|
||||
#ifdef CONFIG_BPF_STREAM_PARSER
|
||||
struct strparser;
|
||||
int tcp_bpf_strp_read_sock(struct strparser *strp, read_descriptor_t *desc,
|
||||
sk_read_actor_t recv_actor);
|
||||
#endif /* CONFIG_BPF_STREAM_PARSER */
|
||||
#endif /* CONFIG_BPF_SYSCALL */
|
||||
|
||||
#ifdef CONFIG_INET
|
||||
|
||||
67
include/trace/events/icmp.h
Normal file
67
include/trace/events/icmp.h
Normal file
@@ -0,0 +1,67 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
#undef TRACE_SYSTEM
|
||||
#define TRACE_SYSTEM icmp
|
||||
|
||||
#if !defined(_TRACE_ICMP_H) || defined(TRACE_HEADER_MULTI_READ)
|
||||
#define _TRACE_ICMP_H
|
||||
|
||||
#include <linux/icmp.h>
|
||||
#include <linux/tracepoint.h>
|
||||
|
||||
TRACE_EVENT(icmp_send,
|
||||
|
||||
TP_PROTO(const struct sk_buff *skb, int type, int code),
|
||||
|
||||
TP_ARGS(skb, type, code),
|
||||
|
||||
TP_STRUCT__entry(
|
||||
__field(const void *, skbaddr)
|
||||
__field(int, type)
|
||||
__field(int, code)
|
||||
__array(__u8, saddr, 4)
|
||||
__array(__u8, daddr, 4)
|
||||
__field(__u16, sport)
|
||||
__field(__u16, dport)
|
||||
__field(unsigned short, ulen)
|
||||
),
|
||||
|
||||
TP_fast_assign(
|
||||
struct iphdr *iph = ip_hdr(skb);
|
||||
struct udphdr *uh = udp_hdr(skb);
|
||||
int proto_4 = iph->protocol;
|
||||
__be32 *p32;
|
||||
|
||||
__entry->skbaddr = skb;
|
||||
__entry->type = type;
|
||||
__entry->code = code;
|
||||
|
||||
if (proto_4 != IPPROTO_UDP || (u8 *)uh < skb->head ||
|
||||
(u8 *)uh + sizeof(struct udphdr)
|
||||
> skb_tail_pointer(skb)) {
|
||||
__entry->sport = 0;
|
||||
__entry->dport = 0;
|
||||
__entry->ulen = 0;
|
||||
} else {
|
||||
__entry->sport = ntohs(uh->source);
|
||||
__entry->dport = ntohs(uh->dest);
|
||||
__entry->ulen = ntohs(uh->len);
|
||||
}
|
||||
|
||||
p32 = (__be32 *) __entry->saddr;
|
||||
*p32 = iph->saddr;
|
||||
|
||||
p32 = (__be32 *) __entry->daddr;
|
||||
*p32 = iph->daddr;
|
||||
),
|
||||
|
||||
TP_printk("icmp_send: type=%d, code=%d. From %pI4:%u to %pI4:%u ulen=%d skbaddr=%p",
|
||||
__entry->type, __entry->code,
|
||||
__entry->saddr, __entry->sport, __entry->daddr,
|
||||
__entry->dport, __entry->ulen, __entry->skbaddr)
|
||||
);
|
||||
|
||||
#endif /* _TRACE_ICMP_H */
|
||||
|
||||
/* This part must be outside protection */
|
||||
#include <trace/define_trace.h>
|
||||
|
||||
@@ -328,8 +328,7 @@ TRACE_EVENT(rpc_request,
|
||||
{ (1UL << RPC_TASK_ACTIVE), "ACTIVE" }, \
|
||||
{ (1UL << RPC_TASK_NEED_XMIT), "NEED_XMIT" }, \
|
||||
{ (1UL << RPC_TASK_NEED_RECV), "NEED_RECV" }, \
|
||||
{ (1UL << RPC_TASK_MSG_PIN_WAIT), "MSG_PIN_WAIT" }, \
|
||||
{ (1UL << RPC_TASK_SIGNALLED), "SIGNALLED" })
|
||||
{ (1UL << RPC_TASK_MSG_PIN_WAIT), "MSG_PIN_WAIT" })
|
||||
|
||||
DECLARE_EVENT_CLASS(rpc_task_running,
|
||||
|
||||
|
||||
@@ -282,7 +282,9 @@ static int io_sendmsg_copy_hdr(struct io_kiocb *req,
|
||||
if (unlikely(ret))
|
||||
return ret;
|
||||
|
||||
return __get_compat_msghdr(&iomsg->msg, &cmsg, NULL);
|
||||
ret = __get_compat_msghdr(&iomsg->msg, &cmsg, NULL);
|
||||
sr->msg_control = iomsg->msg.msg_control_user;
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
134
kernel/acct.c
134
kernel/acct.c
@@ -104,48 +104,50 @@ struct bsd_acct_struct {
|
||||
atomic_long_t count;
|
||||
struct rcu_head rcu;
|
||||
struct mutex lock;
|
||||
int active;
|
||||
bool active;
|
||||
bool check_space;
|
||||
unsigned long needcheck;
|
||||
struct file *file;
|
||||
struct pid_namespace *ns;
|
||||
struct work_struct work;
|
||||
struct completion done;
|
||||
acct_t ac;
|
||||
};
|
||||
|
||||
static void do_acct_process(struct bsd_acct_struct *acct);
|
||||
static void fill_ac(struct bsd_acct_struct *acct);
|
||||
static void acct_write_process(struct bsd_acct_struct *acct);
|
||||
|
||||
/*
|
||||
* Check the amount of free space and suspend/resume accordingly.
|
||||
*/
|
||||
static int check_free_space(struct bsd_acct_struct *acct)
|
||||
static bool check_free_space(struct bsd_acct_struct *acct)
|
||||
{
|
||||
struct kstatfs sbuf;
|
||||
|
||||
if (time_is_after_jiffies(acct->needcheck))
|
||||
goto out;
|
||||
if (!acct->check_space)
|
||||
return acct->active;
|
||||
|
||||
/* May block */
|
||||
if (vfs_statfs(&acct->file->f_path, &sbuf))
|
||||
goto out;
|
||||
return acct->active;
|
||||
|
||||
if (acct->active) {
|
||||
u64 suspend = sbuf.f_blocks * SUSPEND;
|
||||
do_div(suspend, 100);
|
||||
if (sbuf.f_bavail <= suspend) {
|
||||
acct->active = 0;
|
||||
acct->active = false;
|
||||
pr_info("Process accounting paused\n");
|
||||
}
|
||||
} else {
|
||||
u64 resume = sbuf.f_blocks * RESUME;
|
||||
do_div(resume, 100);
|
||||
if (sbuf.f_bavail >= resume) {
|
||||
acct->active = 1;
|
||||
acct->active = true;
|
||||
pr_info("Process accounting resumed\n");
|
||||
}
|
||||
}
|
||||
|
||||
acct->needcheck = jiffies + ACCT_TIMEOUT*HZ;
|
||||
out:
|
||||
return acct->active;
|
||||
}
|
||||
|
||||
@@ -190,7 +192,11 @@ static void acct_pin_kill(struct fs_pin *pin)
|
||||
{
|
||||
struct bsd_acct_struct *acct = to_acct(pin);
|
||||
mutex_lock(&acct->lock);
|
||||
do_acct_process(acct);
|
||||
/*
|
||||
* Fill the accounting struct with the exiting task's info
|
||||
* before punting to the workqueue.
|
||||
*/
|
||||
fill_ac(acct);
|
||||
schedule_work(&acct->work);
|
||||
wait_for_completion(&acct->done);
|
||||
cmpxchg(&acct->ns->bacct, pin, NULL);
|
||||
@@ -203,6 +209,9 @@ static void close_work(struct work_struct *work)
|
||||
{
|
||||
struct bsd_acct_struct *acct = container_of(work, struct bsd_acct_struct, work);
|
||||
struct file *file = acct->file;
|
||||
|
||||
/* We were fired by acct_pin_kill() which holds acct->lock. */
|
||||
acct_write_process(acct);
|
||||
if (file->f_op->flush)
|
||||
file->f_op->flush(file, NULL);
|
||||
__fput_sync(file);
|
||||
@@ -235,6 +244,20 @@ static int acct_on(struct filename *pathname)
|
||||
return -EACCES;
|
||||
}
|
||||
|
||||
/* Exclude kernel kernel internal filesystems. */
|
||||
if (file_inode(file)->i_sb->s_flags & (SB_NOUSER | SB_KERNMOUNT)) {
|
||||
kfree(acct);
|
||||
filp_close(file, NULL);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* Exclude procfs and sysfs. */
|
||||
if (file_inode(file)->i_sb->s_iflags & SB_I_USERNS_VISIBLE) {
|
||||
kfree(acct);
|
||||
filp_close(file, NULL);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (!(file->f_mode & FMODE_CAN_WRITE)) {
|
||||
kfree(acct);
|
||||
filp_close(file, NULL);
|
||||
@@ -431,13 +454,27 @@ static u32 encode_float(u64 value)
|
||||
* do_exit() or when switching to a different output file.
|
||||
*/
|
||||
|
||||
static void fill_ac(acct_t *ac)
|
||||
static void fill_ac(struct bsd_acct_struct *acct)
|
||||
{
|
||||
struct pacct_struct *pacct = ¤t->signal->pacct;
|
||||
struct file *file = acct->file;
|
||||
acct_t *ac = &acct->ac;
|
||||
u64 elapsed, run_time;
|
||||
time64_t btime;
|
||||
struct tty_struct *tty;
|
||||
|
||||
lockdep_assert_held(&acct->lock);
|
||||
|
||||
if (time_is_after_jiffies(acct->needcheck)) {
|
||||
acct->check_space = false;
|
||||
|
||||
/* Don't fill in @ac if nothing will be written. */
|
||||
if (!acct->active)
|
||||
return;
|
||||
} else {
|
||||
acct->check_space = true;
|
||||
}
|
||||
|
||||
/*
|
||||
* Fill the accounting struct with the needed info as recorded
|
||||
* by the different kernel functions.
|
||||
@@ -485,64 +522,61 @@ static void fill_ac(acct_t *ac)
|
||||
ac->ac_majflt = encode_comp_t(pacct->ac_majflt);
|
||||
ac->ac_exitcode = pacct->ac_exitcode;
|
||||
spin_unlock_irq(¤t->sighand->siglock);
|
||||
}
|
||||
/*
|
||||
* do_acct_process does all actual work. Caller holds the reference to file.
|
||||
*/
|
||||
static void do_acct_process(struct bsd_acct_struct *acct)
|
||||
{
|
||||
acct_t ac;
|
||||
unsigned long flim;
|
||||
const struct cred *orig_cred;
|
||||
struct file *file = acct->file;
|
||||
|
||||
/*
|
||||
* Accounting records are not subject to resource limits.
|
||||
*/
|
||||
flim = rlimit(RLIMIT_FSIZE);
|
||||
current->signal->rlim[RLIMIT_FSIZE].rlim_cur = RLIM_INFINITY;
|
||||
/* Perform file operations on behalf of whoever enabled accounting */
|
||||
orig_cred = override_creds(file->f_cred);
|
||||
|
||||
/*
|
||||
* First check to see if there is enough free_space to continue
|
||||
* the process accounting system.
|
||||
*/
|
||||
if (!check_free_space(acct))
|
||||
goto out;
|
||||
|
||||
fill_ac(&ac);
|
||||
/* we really need to bite the bullet and change layout */
|
||||
ac.ac_uid = from_kuid_munged(file->f_cred->user_ns, orig_cred->uid);
|
||||
ac.ac_gid = from_kgid_munged(file->f_cred->user_ns, orig_cred->gid);
|
||||
ac->ac_uid = from_kuid_munged(file->f_cred->user_ns, current_uid());
|
||||
ac->ac_gid = from_kgid_munged(file->f_cred->user_ns, current_gid());
|
||||
#if ACCT_VERSION == 1 || ACCT_VERSION == 2
|
||||
/* backward-compatible 16 bit fields */
|
||||
ac.ac_uid16 = ac.ac_uid;
|
||||
ac.ac_gid16 = ac.ac_gid;
|
||||
ac->ac_uid16 = ac->ac_uid;
|
||||
ac->ac_gid16 = ac->ac_gid;
|
||||
#elif ACCT_VERSION == 3
|
||||
{
|
||||
struct pid_namespace *ns = acct->ns;
|
||||
|
||||
ac.ac_pid = task_tgid_nr_ns(current, ns);
|
||||
ac->ac_pid = task_tgid_nr_ns(current, ns);
|
||||
rcu_read_lock();
|
||||
ac.ac_ppid = task_tgid_nr_ns(rcu_dereference(current->real_parent),
|
||||
ns);
|
||||
ac->ac_ppid = task_tgid_nr_ns(rcu_dereference(current->real_parent), ns);
|
||||
rcu_read_unlock();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
static void acct_write_process(struct bsd_acct_struct *acct)
|
||||
{
|
||||
struct file *file = acct->file;
|
||||
const struct cred *cred;
|
||||
acct_t *ac = &acct->ac;
|
||||
|
||||
/* Perform file operations on behalf of whoever enabled accounting */
|
||||
cred = override_creds(file->f_cred);
|
||||
|
||||
/*
|
||||
* Get freeze protection. If the fs is frozen, just skip the write
|
||||
* as we could deadlock the system otherwise.
|
||||
* First check to see if there is enough free_space to continue
|
||||
* the process accounting system. Then get freeze protection. If
|
||||
* the fs is frozen, just skip the write as we could deadlock
|
||||
* the system otherwise.
|
||||
*/
|
||||
if (file_start_write_trylock(file)) {
|
||||
if (check_free_space(acct) && file_start_write_trylock(file)) {
|
||||
/* it's been opened O_APPEND, so position is irrelevant */
|
||||
loff_t pos = 0;
|
||||
__kernel_write(file, &ac, sizeof(acct_t), &pos);
|
||||
__kernel_write(file, ac, sizeof(acct_t), &pos);
|
||||
file_end_write(file);
|
||||
}
|
||||
out:
|
||||
|
||||
revert_creds(cred);
|
||||
}
|
||||
|
||||
static void do_acct_process(struct bsd_acct_struct *acct)
|
||||
{
|
||||
unsigned long flim;
|
||||
|
||||
/* Accounting records are not subject to resource limits. */
|
||||
flim = rlimit(RLIMIT_FSIZE);
|
||||
current->signal->rlim[RLIMIT_FSIZE].rlim_cur = RLIM_INFINITY;
|
||||
fill_ac(acct);
|
||||
acct_write_process(acct);
|
||||
current->signal->rlim[RLIMIT_FSIZE].rlim_cur = flim;
|
||||
revert_creds(orig_cred);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -1693,8 +1693,6 @@ int generic_map_update_batch(struct bpf_map *map,
|
||||
return err;
|
||||
}
|
||||
|
||||
#define MAP_LOOKUP_RETRIES 3
|
||||
|
||||
int generic_map_lookup_batch(struct bpf_map *map,
|
||||
const union bpf_attr *attr,
|
||||
union bpf_attr __user *uattr)
|
||||
@@ -1704,8 +1702,8 @@ int generic_map_lookup_batch(struct bpf_map *map,
|
||||
void __user *values = u64_to_user_ptr(attr->batch.values);
|
||||
void __user *keys = u64_to_user_ptr(attr->batch.keys);
|
||||
void *buf, *buf_prevkey, *prev_key, *key, *value;
|
||||
int err, retry = MAP_LOOKUP_RETRIES;
|
||||
u32 value_size, cp, max_count;
|
||||
int err;
|
||||
|
||||
if (attr->batch.elem_flags & ~BPF_F_LOCK)
|
||||
return -EINVAL;
|
||||
@@ -1751,14 +1749,8 @@ int generic_map_lookup_batch(struct bpf_map *map,
|
||||
err = bpf_map_copy_value(map, key, value,
|
||||
attr->batch.elem_flags);
|
||||
|
||||
if (err == -ENOENT) {
|
||||
if (retry) {
|
||||
retry--;
|
||||
continue;
|
||||
}
|
||||
err = -EINTR;
|
||||
break;
|
||||
}
|
||||
if (err == -ENOENT)
|
||||
goto next_key;
|
||||
|
||||
if (err)
|
||||
goto free_buf;
|
||||
@@ -1773,12 +1765,12 @@ int generic_map_lookup_batch(struct bpf_map *map,
|
||||
goto free_buf;
|
||||
}
|
||||
|
||||
cp++;
|
||||
next_key:
|
||||
if (!prev_key)
|
||||
prev_key = buf_prevkey;
|
||||
|
||||
swap(prev_key, key);
|
||||
retry = MAP_LOOKUP_RETRIES;
|
||||
cp++;
|
||||
cond_resched();
|
||||
}
|
||||
|
||||
|
||||
@@ -5654,14 +5654,15 @@ static int _perf_event_period(struct perf_event *event, u64 value)
|
||||
if (!value)
|
||||
return -EINVAL;
|
||||
|
||||
if (event->attr.freq && value > sysctl_perf_event_sample_rate)
|
||||
return -EINVAL;
|
||||
|
||||
if (perf_event_check_period(event, value))
|
||||
return -EINVAL;
|
||||
|
||||
if (!event->attr.freq && (value & (1ULL << 63)))
|
||||
return -EINVAL;
|
||||
if (event->attr.freq) {
|
||||
if (value > sysctl_perf_event_sample_rate)
|
||||
return -EINVAL;
|
||||
} else {
|
||||
if (perf_event_check_period(event, value))
|
||||
return -EINVAL;
|
||||
if (value & (1ULL << 63))
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
event_function_call(event, __perf_event_period, &value);
|
||||
|
||||
|
||||
@@ -488,6 +488,11 @@ retry:
|
||||
if (ret <= 0)
|
||||
goto put_old;
|
||||
|
||||
if (is_zero_page(old_page)) {
|
||||
ret = -EINVAL;
|
||||
goto put_old;
|
||||
}
|
||||
|
||||
if (WARN(!is_register && PageCompound(old_page),
|
||||
"uprobe unregister should never work on compound page\n")) {
|
||||
ret = -EINVAL;
|
||||
|
||||
@@ -8593,7 +8593,7 @@ SYSCALL_DEFINE0(sched_yield)
|
||||
#if !defined(CONFIG_PREEMPTION) || defined(CONFIG_PREEMPT_DYNAMIC)
|
||||
int __sched __cond_resched(void)
|
||||
{
|
||||
if (should_resched(0)) {
|
||||
if (should_resched(0) && !irqs_disabled()) {
|
||||
preempt_schedule_common();
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -507,6 +507,7 @@ static int function_stat_show(struct seq_file *m, void *v)
|
||||
static struct trace_seq s;
|
||||
unsigned long long avg;
|
||||
unsigned long long stddev;
|
||||
unsigned long long stddev_denom;
|
||||
#endif
|
||||
mutex_lock(&ftrace_profile_lock);
|
||||
|
||||
@@ -528,23 +529,19 @@ static int function_stat_show(struct seq_file *m, void *v)
|
||||
#ifdef CONFIG_FUNCTION_GRAPH_TRACER
|
||||
seq_puts(m, " ");
|
||||
|
||||
/* Sample standard deviation (s^2) */
|
||||
if (rec->counter <= 1)
|
||||
stddev = 0;
|
||||
else {
|
||||
/*
|
||||
* Apply Welford's method:
|
||||
* s^2 = 1 / (n * (n-1)) * (n * \Sum (x_i)^2 - (\Sum x_i)^2)
|
||||
*/
|
||||
/*
|
||||
* Variance formula:
|
||||
* s^2 = 1 / (n * (n-1)) * (n * \Sum (x_i)^2 - (\Sum x_i)^2)
|
||||
* Maybe Welford's method is better here?
|
||||
* Divide only by 1000 for ns^2 -> us^2 conversion.
|
||||
* trace_print_graph_duration will divide by 1000 again.
|
||||
*/
|
||||
stddev = 0;
|
||||
stddev_denom = rec->counter * (rec->counter - 1) * 1000;
|
||||
if (stddev_denom) {
|
||||
stddev = rec->counter * rec->time_squared -
|
||||
rec->time * rec->time;
|
||||
|
||||
/*
|
||||
* Divide only 1000 for ns^2 -> us^2 conversion.
|
||||
* trace_print_graph_duration will divide 1000 again.
|
||||
*/
|
||||
stddev = div64_ul(stddev,
|
||||
rec->counter * (rec->counter - 1) * 1000);
|
||||
stddev = div64_ul(stddev, stddev_denom);
|
||||
}
|
||||
|
||||
trace_seq_init(&s);
|
||||
@@ -5108,6 +5105,9 @@ __ftrace_match_addr(struct ftrace_hash *hash, unsigned long ip, int remove)
|
||||
return -ENOENT;
|
||||
free_hash_entry(hash, entry);
|
||||
return 0;
|
||||
} else if (__ftrace_lookup_ip(hash, ip) != NULL) {
|
||||
/* Already exists */
|
||||
return 0;
|
||||
}
|
||||
|
||||
return add_hash_entry(hash, ip);
|
||||
|
||||
@@ -6551,27 +6551,27 @@ static int event_hist_trigger_parse(struct event_command *cmd_ops,
|
||||
if (existing_hist_update_only(glob, trigger_data, file))
|
||||
goto out_free;
|
||||
|
||||
if (!get_named_trigger_data(trigger_data)) {
|
||||
|
||||
ret = create_actions(hist_data);
|
||||
if (ret)
|
||||
goto out_free;
|
||||
|
||||
if (has_hist_vars(hist_data) || hist_data->n_var_refs) {
|
||||
ret = save_hist_vars(hist_data);
|
||||
if (ret)
|
||||
goto out_free;
|
||||
}
|
||||
|
||||
ret = tracing_map_init(hist_data->map);
|
||||
if (ret)
|
||||
goto out_free;
|
||||
}
|
||||
|
||||
ret = event_trigger_register(cmd_ops, file, glob, trigger_data);
|
||||
if (ret < 0)
|
||||
goto out_free;
|
||||
|
||||
if (get_named_trigger_data(trigger_data))
|
||||
goto enable;
|
||||
|
||||
ret = create_actions(hist_data);
|
||||
if (ret)
|
||||
goto out_unreg;
|
||||
|
||||
if (has_hist_vars(hist_data) || hist_data->n_var_refs) {
|
||||
ret = save_hist_vars(hist_data);
|
||||
if (ret)
|
||||
goto out_unreg;
|
||||
}
|
||||
|
||||
ret = tracing_map_init(hist_data->map);
|
||||
if (ret)
|
||||
goto out_unreg;
|
||||
enable:
|
||||
ret = hist_trigger_enable(trigger_data, file);
|
||||
if (ret)
|
||||
goto out_unreg;
|
||||
|
||||
@@ -185,7 +185,7 @@ function_trace_call(unsigned long ip, unsigned long parent_ip,
|
||||
if (bit < 0)
|
||||
return;
|
||||
|
||||
trace_ctx = tracing_gen_ctx();
|
||||
trace_ctx = tracing_gen_ctx_dec();
|
||||
|
||||
cpu = smp_processor_id();
|
||||
data = per_cpu_ptr(tr->array_buffer.data, cpu);
|
||||
@@ -285,7 +285,6 @@ function_no_repeats_trace_call(unsigned long ip, unsigned long parent_ip,
|
||||
struct trace_array *tr = op->private;
|
||||
struct trace_array_cpu *data;
|
||||
unsigned int trace_ctx;
|
||||
unsigned long flags;
|
||||
int bit;
|
||||
int cpu;
|
||||
|
||||
@@ -312,8 +311,7 @@ function_no_repeats_trace_call(unsigned long ip, unsigned long parent_ip,
|
||||
if (is_repeat_check(tr, last_info, ip, parent_ip))
|
||||
goto out;
|
||||
|
||||
local_save_flags(flags);
|
||||
trace_ctx = tracing_gen_ctx_flags(flags);
|
||||
trace_ctx = tracing_gen_ctx_dec();
|
||||
process_repeats(tr, ip, parent_ip, last_info, trace_ctx);
|
||||
|
||||
trace_function(tr, ip, parent_ip, trace_ctx);
|
||||
|
||||
31
mm/gup.c
31
mm/gup.c
@@ -51,7 +51,8 @@ static inline void sanity_check_pinned_pages(struct page **pages,
|
||||
struct page *page = *pages;
|
||||
struct folio *folio = page_folio(page);
|
||||
|
||||
if (!folio_test_anon(folio))
|
||||
if (is_zero_page(page) ||
|
||||
!folio_test_anon(folio))
|
||||
continue;
|
||||
if (!folio_test_large(folio) || folio_test_hugetlb(folio))
|
||||
VM_BUG_ON_PAGE(!PageAnonExclusive(&folio->page), page);
|
||||
@@ -128,6 +129,13 @@ struct folio *try_grab_folio(struct page *page, int refs, unsigned int flags)
|
||||
else if (flags & FOLL_PIN) {
|
||||
struct folio *folio;
|
||||
|
||||
/*
|
||||
* Don't take a pin on the zero page - it's not going anywhere
|
||||
* and it is used in a *lot* of places.
|
||||
*/
|
||||
if (is_zero_page(page))
|
||||
return page_folio(page);
|
||||
|
||||
/*
|
||||
* Can't do FOLL_LONGTERM + FOLL_PIN gup fast path if not in a
|
||||
* right zone, so fail and let the caller fall back to the slow
|
||||
@@ -177,6 +185,8 @@ struct folio *try_grab_folio(struct page *page, int refs, unsigned int flags)
|
||||
static void gup_put_folio(struct folio *folio, int refs, unsigned int flags)
|
||||
{
|
||||
if (flags & FOLL_PIN) {
|
||||
if (is_zero_folio(folio))
|
||||
return;
|
||||
node_stat_mod_folio(folio, NR_FOLL_PIN_RELEASED, refs);
|
||||
if (folio_test_large(folio))
|
||||
atomic_sub(refs, folio_pincount_ptr(folio));
|
||||
@@ -217,6 +227,13 @@ bool __must_check try_grab_page(struct page *page, unsigned int flags)
|
||||
if (flags & FOLL_GET)
|
||||
folio_ref_inc(folio);
|
||||
else if (flags & FOLL_PIN) {
|
||||
/*
|
||||
* Don't take a pin on the zero page - it's not going anywhere
|
||||
* and it is used in a *lot* of places.
|
||||
*/
|
||||
if (is_zero_page(page))
|
||||
return 0;
|
||||
|
||||
/*
|
||||
* Similar to try_grab_folio(): be sure to *also*
|
||||
* increment the normal page refcount field at least once,
|
||||
@@ -3149,6 +3166,9 @@ EXPORT_SYMBOL_GPL(get_user_pages_fast);
|
||||
*
|
||||
* FOLL_PIN means that the pages must be released via unpin_user_page(). Please
|
||||
* see Documentation/core-api/pin_user_pages.rst for further details.
|
||||
*
|
||||
* Note that if a zero_page is amongst the returned pages, it will not have
|
||||
* pins in it and unpin_user_page() will not remove pins from it.
|
||||
*/
|
||||
int pin_user_pages_fast(unsigned long start, int nr_pages,
|
||||
unsigned int gup_flags, struct page **pages)
|
||||
@@ -3225,6 +3245,9 @@ EXPORT_SYMBOL_GPL(pin_user_pages_fast_only);
|
||||
*
|
||||
* FOLL_PIN means that the pages must be released via unpin_user_page(). Please
|
||||
* see Documentation/core-api/pin_user_pages.rst for details.
|
||||
*
|
||||
* Note that if a zero_page is amongst the returned pages, it will not have
|
||||
* pins in it and unpin_user_page*() will not remove pins from it.
|
||||
*/
|
||||
long pin_user_pages_remote(struct mm_struct *mm,
|
||||
unsigned long start, unsigned long nr_pages,
|
||||
@@ -3260,6 +3283,9 @@ EXPORT_SYMBOL(pin_user_pages_remote);
|
||||
*
|
||||
* FOLL_PIN means that the pages must be released via unpin_user_page(). Please
|
||||
* see Documentation/core-api/pin_user_pages.rst for details.
|
||||
*
|
||||
* Note that if a zero_page is amongst the returned pages, it will not have
|
||||
* pins in it and unpin_user_page*() will not remove pins from it.
|
||||
*/
|
||||
long pin_user_pages(unsigned long start, unsigned long nr_pages,
|
||||
unsigned int gup_flags, struct page **pages,
|
||||
@@ -3282,6 +3308,9 @@ EXPORT_SYMBOL(pin_user_pages);
|
||||
* pin_user_pages_unlocked() is the FOLL_PIN variant of
|
||||
* get_user_pages_unlocked(). Behavior is the same, except that this one sets
|
||||
* FOLL_PIN and rejects FOLL_GET.
|
||||
*
|
||||
* Note that if a zero_page is amongst the returned pages, it will not have
|
||||
* pins in it and unpin_user_page*() will not remove pins from it.
|
||||
*/
|
||||
long pin_user_pages_unlocked(unsigned long start, unsigned long nr_pages,
|
||||
struct page **pages, unsigned int gup_flags)
|
||||
|
||||
11
mm/madvise.c
11
mm/madvise.c
@@ -928,7 +928,16 @@ static long madvise_dontneed_free(struct vm_area_struct *vma,
|
||||
*/
|
||||
end = vma->vm_end;
|
||||
}
|
||||
VM_WARN_ON(start >= end);
|
||||
/*
|
||||
* If the memory region between start and end was
|
||||
* originally backed by 4kB pages and then remapped to
|
||||
* be backed by hugepages while mmap_lock was dropped,
|
||||
* the adjustment for hugetlb vma above may have rounded
|
||||
* end down to the start address.
|
||||
*/
|
||||
if (start == end)
|
||||
return 0;
|
||||
VM_WARN_ON(start > end);
|
||||
}
|
||||
|
||||
if (behavior == MADV_DONTNEED || behavior == MADV_DONTNEED_LOCKED)
|
||||
|
||||
@@ -5470,7 +5470,7 @@ static inline bool get_mmap_lock_carefully(struct mm_struct *mm, struct pt_regs
|
||||
}
|
||||
|
||||
if (regs && !user_mode(regs)) {
|
||||
unsigned long ip = instruction_pointer(regs);
|
||||
unsigned long ip = exception_ip(regs);
|
||||
if (!search_exception_tables(ip))
|
||||
return false;
|
||||
}
|
||||
@@ -5495,7 +5495,7 @@ static inline bool upgrade_mmap_lock_carefully(struct mm_struct *mm, struct pt_r
|
||||
{
|
||||
mmap_read_unlock(mm);
|
||||
if (regs && !user_mode(regs)) {
|
||||
unsigned long ip = instruction_pointer(regs);
|
||||
unsigned long ip = exception_ip(regs);
|
||||
if (!search_exception_tables(ip))
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -632,7 +632,8 @@ void __l2cap_chan_add(struct l2cap_conn *conn, struct l2cap_chan *chan)
|
||||
test_bit(FLAG_HOLD_HCI_CONN, &chan->flags))
|
||||
hci_conn_hold(conn->hcon);
|
||||
|
||||
list_add(&chan->list, &conn->chan_l);
|
||||
/* Append to the list since the order matters for ECRED */
|
||||
list_add_tail(&chan->list, &conn->chan_l);
|
||||
}
|
||||
|
||||
void l2cap_chan_add(struct l2cap_conn *conn, struct l2cap_chan *chan)
|
||||
@@ -3971,7 +3972,11 @@ static void l2cap_ecred_rsp_defer(struct l2cap_chan *chan, void *data)
|
||||
{
|
||||
struct l2cap_ecred_rsp_data *rsp = data;
|
||||
|
||||
if (test_bit(FLAG_ECRED_CONN_REQ_SENT, &chan->flags))
|
||||
/* Check if channel for outgoing connection or if it wasn't deferred
|
||||
* since in those cases it must be skipped.
|
||||
*/
|
||||
if (test_bit(FLAG_ECRED_CONN_REQ_SENT, &chan->flags) ||
|
||||
!test_and_clear_bit(FLAG_DEFER_SETUP, &chan->flags))
|
||||
return;
|
||||
|
||||
/* Reset ident so only one response is sent */
|
||||
|
||||
@@ -768,12 +768,9 @@ static void *bpf_test_init(const union bpf_attr *kattr, u32 user_size,
|
||||
void __user *data_in = u64_to_user_ptr(kattr->test.data_in);
|
||||
void *data;
|
||||
|
||||
if (size < ETH_HLEN || size > PAGE_SIZE - headroom - tailroom)
|
||||
if (user_size < ETH_HLEN || user_size > PAGE_SIZE - headroom - tailroom)
|
||||
return ERR_PTR(-EINVAL);
|
||||
|
||||
if (user_size > size)
|
||||
return ERR_PTR(-EMSGSIZE);
|
||||
|
||||
size = SKB_DATA_ALIGN(size);
|
||||
data = kzalloc(size + headroom + tailroom, GFP_USER);
|
||||
if (!data)
|
||||
|
||||
@@ -366,9 +366,9 @@ br_nf_ipv4_daddr_was_changed(const struct sk_buff *skb,
|
||||
*/
|
||||
static int br_nf_pre_routing_finish(struct net *net, struct sock *sk, struct sk_buff *skb)
|
||||
{
|
||||
struct net_device *dev = skb->dev, *br_indev;
|
||||
struct iphdr *iph = ip_hdr(skb);
|
||||
struct nf_bridge_info *nf_bridge = nf_bridge_info_get(skb);
|
||||
struct net_device *dev = skb->dev, *br_indev;
|
||||
const struct iphdr *iph = ip_hdr(skb);
|
||||
struct rtable *rt;
|
||||
int err;
|
||||
|
||||
@@ -386,7 +386,9 @@ static int br_nf_pre_routing_finish(struct net *net, struct sock *sk, struct sk_
|
||||
}
|
||||
nf_bridge->in_prerouting = 0;
|
||||
if (br_nf_ipv4_daddr_was_changed(skb, nf_bridge)) {
|
||||
if ((err = ip_route_input(skb, iph->daddr, iph->saddr, iph->tos, dev))) {
|
||||
err = ip_route_input(skb, iph->daddr, iph->saddr,
|
||||
ip4h_dscp(iph), dev);
|
||||
if (err) {
|
||||
struct in_device *in_dev = __in_dev_get_rcu(dev);
|
||||
|
||||
/* If err equals -EHOSTUNREACH the error is due to a
|
||||
|
||||
@@ -1714,30 +1714,30 @@ static int __init init_net_drop_monitor(void)
|
||||
return -ENOSPC;
|
||||
}
|
||||
|
||||
rc = genl_register_family(&net_drop_monitor_family);
|
||||
if (rc) {
|
||||
pr_err("Could not create drop monitor netlink family\n");
|
||||
return rc;
|
||||
}
|
||||
WARN_ON(net_drop_monitor_family.mcgrp_offset != NET_DM_GRP_ALERT);
|
||||
|
||||
rc = register_netdevice_notifier(&dropmon_net_notifier);
|
||||
if (rc < 0) {
|
||||
pr_crit("Failed to register netdevice notifier\n");
|
||||
goto out_unreg;
|
||||
}
|
||||
|
||||
rc = 0;
|
||||
|
||||
for_each_possible_cpu(cpu) {
|
||||
net_dm_cpu_data_init(cpu);
|
||||
net_dm_hw_cpu_data_init(cpu);
|
||||
}
|
||||
|
||||
rc = register_netdevice_notifier(&dropmon_net_notifier);
|
||||
if (rc < 0) {
|
||||
pr_crit("Failed to register netdevice notifier\n");
|
||||
return rc;
|
||||
}
|
||||
|
||||
rc = genl_register_family(&net_drop_monitor_family);
|
||||
if (rc) {
|
||||
pr_err("Could not create drop monitor netlink family\n");
|
||||
goto out_unreg;
|
||||
}
|
||||
WARN_ON(net_drop_monitor_family.mcgrp_offset != NET_DM_GRP_ALERT);
|
||||
|
||||
rc = 0;
|
||||
|
||||
goto out;
|
||||
|
||||
out_unreg:
|
||||
genl_unregister_family(&net_drop_monitor_family);
|
||||
WARN_ON(unregister_netdevice_notifier(&dropmon_net_notifier));
|
||||
out:
|
||||
return rc;
|
||||
}
|
||||
@@ -1746,19 +1746,18 @@ static void exit_net_drop_monitor(void)
|
||||
{
|
||||
int cpu;
|
||||
|
||||
BUG_ON(unregister_netdevice_notifier(&dropmon_net_notifier));
|
||||
|
||||
/*
|
||||
* Because of the module_get/put we do in the trace state change path
|
||||
* we are guaranteed not to have any current users when we get here
|
||||
*/
|
||||
BUG_ON(genl_unregister_family(&net_drop_monitor_family));
|
||||
|
||||
BUG_ON(unregister_netdevice_notifier(&dropmon_net_notifier));
|
||||
|
||||
for_each_possible_cpu(cpu) {
|
||||
net_dm_hw_cpu_data_fini(cpu);
|
||||
net_dm_cpu_data_fini(cpu);
|
||||
}
|
||||
|
||||
BUG_ON(genl_unregister_family(&net_drop_monitor_family));
|
||||
}
|
||||
|
||||
module_init(init_net_drop_monitor);
|
||||
|
||||
@@ -679,6 +679,7 @@ static void napi_reuse_skb(struct napi_struct *napi, struct sk_buff *skb)
|
||||
skb->pkt_type = PACKET_HOST;
|
||||
|
||||
skb->encapsulation = 0;
|
||||
skb->ip_summed = CHECKSUM_NONE;
|
||||
skb_shinfo(skb)->gso_type = 0;
|
||||
skb_shinfo(skb)->gso_size = 0;
|
||||
if (unlikely(skb->slow_gro)) {
|
||||
|
||||
@@ -5556,11 +5556,11 @@ void skb_scrub_packet(struct sk_buff *skb, bool xnet)
|
||||
skb->offload_fwd_mark = 0;
|
||||
skb->offload_l3_fwd_mark = 0;
|
||||
#endif
|
||||
ipvs_reset(skb);
|
||||
|
||||
if (!xnet)
|
||||
return;
|
||||
|
||||
ipvs_reset(skb);
|
||||
skb->mark = 0;
|
||||
skb_clear_tstamp(skb);
|
||||
}
|
||||
|
||||
@@ -547,6 +547,9 @@ static int sk_psock_skb_ingress_enqueue(struct sk_buff *skb,
|
||||
return num_sge;
|
||||
}
|
||||
|
||||
#if IS_ENABLED(CONFIG_BPF_STREAM_PARSER)
|
||||
psock->ingress_bytes += len;
|
||||
#endif
|
||||
copied = len;
|
||||
msg->sg.start = 0;
|
||||
msg->sg.size = copied;
|
||||
@@ -1138,6 +1141,10 @@ int sk_psock_init_strp(struct sock *sk, struct sk_psock *psock)
|
||||
if (!ret)
|
||||
sk_psock_set_state(psock, SK_PSOCK_RX_STRP_ENABLED);
|
||||
|
||||
if (sk_is_tcp(sk)) {
|
||||
psock->strp.cb.read_sock = tcp_bpf_strp_read_sock;
|
||||
psock->copied_seq = tcp_sk(sk)->copied_seq;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
@@ -30,6 +30,7 @@ static int min_sndbuf = SOCK_MIN_SNDBUF;
|
||||
static int min_rcvbuf = SOCK_MIN_RCVBUF;
|
||||
static int max_skb_frags = MAX_SKB_FRAGS;
|
||||
static int min_mem_pcpu_rsv = SK_MEMORY_PCPU_RESERVE;
|
||||
static int netdev_budget_usecs_min = 2 * USEC_PER_SEC / HZ;
|
||||
|
||||
static int net_msg_warn; /* Unused, but still a sysctl */
|
||||
|
||||
@@ -554,7 +555,7 @@ static struct ctl_table net_core_table[] = {
|
||||
.maxlen = sizeof(unsigned int),
|
||||
.mode = 0644,
|
||||
.proc_handler = proc_dointvec_minmax,
|
||||
.extra1 = SYSCTL_ZERO,
|
||||
.extra1 = &netdev_budget_usecs_min,
|
||||
},
|
||||
{
|
||||
.procname = "fb_tunnels_only_for_init_net",
|
||||
|
||||
@@ -93,6 +93,9 @@
|
||||
#include <net/ip_fib.h>
|
||||
#include <net/l3mdev.h>
|
||||
#include <net/addrconf.h>
|
||||
#include <net/inet_dscp.h>
|
||||
#define CREATE_TRACE_POINTS
|
||||
#include <trace/events/icmp.h>
|
||||
|
||||
/*
|
||||
* Build xmit assembly blocks
|
||||
@@ -470,13 +473,11 @@ static struct net_device *icmp_get_route_lookup_dev(struct sk_buff *skb)
|
||||
return route_lookup_dev;
|
||||
}
|
||||
|
||||
static struct rtable *icmp_route_lookup(struct net *net,
|
||||
struct flowi4 *fl4,
|
||||
static struct rtable *icmp_route_lookup(struct net *net, struct flowi4 *fl4,
|
||||
struct sk_buff *skb_in,
|
||||
const struct iphdr *iph,
|
||||
__be32 saddr, u8 tos, u32 mark,
|
||||
int type, int code,
|
||||
struct icmp_bxm *param)
|
||||
const struct iphdr *iph, __be32 saddr,
|
||||
dscp_t dscp, u32 mark, int type,
|
||||
int code, struct icmp_bxm *param)
|
||||
{
|
||||
struct net_device *route_lookup_dev;
|
||||
struct rtable *rt, *rt2;
|
||||
@@ -489,7 +490,7 @@ static struct rtable *icmp_route_lookup(struct net *net,
|
||||
fl4->saddr = saddr;
|
||||
fl4->flowi4_mark = mark;
|
||||
fl4->flowi4_uid = sock_net_uid(net, NULL);
|
||||
fl4->flowi4_tos = RT_TOS(tos);
|
||||
fl4->flowi4_tos = inet_dscp_to_dsfield(dscp);
|
||||
fl4->flowi4_proto = IPPROTO_ICMP;
|
||||
fl4->fl4_icmp_type = type;
|
||||
fl4->fl4_icmp_code = code;
|
||||
@@ -537,7 +538,7 @@ static struct rtable *icmp_route_lookup(struct net *net,
|
||||
orefdst = skb_in->_skb_refdst; /* save old refdst */
|
||||
skb_dst_set(skb_in, NULL);
|
||||
err = ip_route_input(skb_in, fl4_dec.daddr, fl4_dec.saddr,
|
||||
RT_TOS(tos), rt2->dst.dev);
|
||||
dscp, rt2->dst.dev);
|
||||
|
||||
dst_release(&rt2->dst);
|
||||
rt2 = skb_rtable(skb_in);
|
||||
@@ -732,8 +733,9 @@ void __icmp_send(struct sk_buff *skb_in, int type, int code, __be32 info,
|
||||
ipc.opt = &icmp_param.replyopts.opt;
|
||||
ipc.sockc.mark = mark;
|
||||
|
||||
rt = icmp_route_lookup(net, &fl4, skb_in, iph, saddr, tos, mark,
|
||||
type, code, &icmp_param);
|
||||
rt = icmp_route_lookup(net, &fl4, skb_in, iph, saddr,
|
||||
inet_dsfield_to_dscp(tos), mark, type, code,
|
||||
&icmp_param);
|
||||
if (IS_ERR(rt))
|
||||
goto out_unlock;
|
||||
|
||||
@@ -766,6 +768,8 @@ void __icmp_send(struct sk_buff *skb_in, int type, int code, __be32 info,
|
||||
if (!fl4.saddr)
|
||||
fl4.saddr = htonl(INADDR_DUMMY);
|
||||
|
||||
trace_icmp_send(skb_in, type, code);
|
||||
|
||||
icmp_push_reply(sk, &icmp_param, &fl4, &ipc, &rt);
|
||||
ende:
|
||||
ip_rt_put(rt);
|
||||
|
||||
@@ -617,7 +617,8 @@ int ip_options_rcv_srr(struct sk_buff *skb, struct net_device *dev)
|
||||
|
||||
orefdst = skb->_skb_refdst;
|
||||
skb_dst_set(skb, NULL);
|
||||
err = ip_route_input(skb, nexthop, iph->saddr, iph->tos, dev);
|
||||
err = ip_route_input(skb, nexthop, iph->saddr, ip4h_dscp(iph),
|
||||
dev);
|
||||
rt2 = skb_rtable(skb);
|
||||
if (err || (rt2->rt_type != RTN_UNICAST && rt2->rt_type != RTN_LOCAL)) {
|
||||
skb_dst_drop(skb);
|
||||
|
||||
@@ -1681,12 +1681,13 @@ EXPORT_SYMBOL(tcp_recv_skb);
|
||||
* or for 'peeking' the socket using this routine
|
||||
* (although both would be easy to implement).
|
||||
*/
|
||||
int tcp_read_sock(struct sock *sk, read_descriptor_t *desc,
|
||||
sk_read_actor_t recv_actor)
|
||||
static int __tcp_read_sock(struct sock *sk, read_descriptor_t *desc,
|
||||
sk_read_actor_t recv_actor, bool noack,
|
||||
u32 *copied_seq)
|
||||
{
|
||||
struct sk_buff *skb;
|
||||
struct tcp_sock *tp = tcp_sk(sk);
|
||||
u32 seq = tp->copied_seq;
|
||||
u32 seq = *copied_seq;
|
||||
u32 offset;
|
||||
int copied = 0;
|
||||
|
||||
@@ -1740,9 +1741,12 @@ int tcp_read_sock(struct sock *sk, read_descriptor_t *desc,
|
||||
tcp_eat_recv_skb(sk, skb);
|
||||
if (!desc->count)
|
||||
break;
|
||||
WRITE_ONCE(tp->copied_seq, seq);
|
||||
WRITE_ONCE(*copied_seq, seq);
|
||||
}
|
||||
WRITE_ONCE(tp->copied_seq, seq);
|
||||
WRITE_ONCE(*copied_seq, seq);
|
||||
|
||||
if (noack)
|
||||
goto out;
|
||||
|
||||
tcp_rcv_space_adjust(sk);
|
||||
|
||||
@@ -1751,10 +1755,25 @@ int tcp_read_sock(struct sock *sk, read_descriptor_t *desc,
|
||||
tcp_recv_skb(sk, seq, &offset);
|
||||
tcp_cleanup_rbuf(sk, copied);
|
||||
}
|
||||
out:
|
||||
return copied;
|
||||
}
|
||||
|
||||
int tcp_read_sock(struct sock *sk, read_descriptor_t *desc,
|
||||
sk_read_actor_t recv_actor)
|
||||
{
|
||||
return __tcp_read_sock(sk, desc, recv_actor, false,
|
||||
&tcp_sk(sk)->copied_seq);
|
||||
}
|
||||
EXPORT_SYMBOL(tcp_read_sock);
|
||||
|
||||
int tcp_read_sock_noack(struct sock *sk, read_descriptor_t *desc,
|
||||
sk_read_actor_t recv_actor, bool noack,
|
||||
u32 *copied_seq)
|
||||
{
|
||||
return __tcp_read_sock(sk, desc, recv_actor, noack, copied_seq);
|
||||
}
|
||||
|
||||
int tcp_read_skb(struct sock *sk, skb_read_actor_t recv_actor)
|
||||
{
|
||||
struct sk_buff *skb;
|
||||
|
||||
@@ -679,6 +679,42 @@ static int tcp_bpf_assert_proto_ops(struct proto *ops)
|
||||
ops->sendpage == tcp_sendpage ? 0 : -ENOTSUPP;
|
||||
}
|
||||
|
||||
#if IS_ENABLED(CONFIG_BPF_STREAM_PARSER)
|
||||
int tcp_bpf_strp_read_sock(struct strparser *strp, read_descriptor_t *desc,
|
||||
sk_read_actor_t recv_actor)
|
||||
{
|
||||
struct sock *sk = strp->sk;
|
||||
struct sk_psock *psock;
|
||||
struct tcp_sock *tp;
|
||||
int copied = 0;
|
||||
|
||||
tp = tcp_sk(sk);
|
||||
rcu_read_lock();
|
||||
psock = sk_psock(sk);
|
||||
if (WARN_ON_ONCE(!psock)) {
|
||||
desc->error = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
psock->ingress_bytes = 0;
|
||||
copied = tcp_read_sock_noack(sk, desc, recv_actor, true,
|
||||
&psock->copied_seq);
|
||||
if (copied < 0)
|
||||
goto out;
|
||||
/* recv_actor may redirect skb to another socket (SK_REDIRECT) or
|
||||
* just put skb into ingress queue of current socket (SK_PASS).
|
||||
* For SK_REDIRECT, we need to ack the frame immediately but for
|
||||
* SK_PASS, we want to delay the ack until tcp_bpf_recvmsg_parser().
|
||||
*/
|
||||
tp->copied_seq = psock->copied_seq - psock->ingress_bytes;
|
||||
tcp_rcv_space_adjust(sk);
|
||||
__tcp_cleanup_rbuf(sk, copied - psock->ingress_bytes);
|
||||
out:
|
||||
rcu_read_unlock();
|
||||
return copied;
|
||||
}
|
||||
#endif /* CONFIG_BPF_STREAM_PARSER */
|
||||
|
||||
int tcp_bpf_update_proto(struct sock *sk, struct sk_psock *psock, bool restore)
|
||||
{
|
||||
int family = sk->sk_family == AF_INET6 ? TCP_BPF_IPV6 : TCP_BPF_IPV4;
|
||||
|
||||
@@ -735,12 +735,6 @@ struct sock *tcp_check_req(struct sock *sk, struct sk_buff *skb,
|
||||
|
||||
/* In sequence, PAWS is OK. */
|
||||
|
||||
/* TODO: We probably should defer ts_recent change once
|
||||
* we take ownership of @req.
|
||||
*/
|
||||
if (tmp_opt.saw_tstamp && !after(TCP_SKB_CB(skb)->seq, tcp_rsk(req)->rcv_nxt))
|
||||
WRITE_ONCE(req->ts_recent, tmp_opt.rcv_tsval);
|
||||
|
||||
if (TCP_SKB_CB(skb)->seq == tcp_rsk(req)->rcv_isn) {
|
||||
/* Truncate SYN, it is out of window starting
|
||||
at tcp_rsk(req)->rcv_isn + 1. */
|
||||
@@ -789,6 +783,10 @@ struct sock *tcp_check_req(struct sock *sk, struct sk_buff *skb,
|
||||
if (!child)
|
||||
goto listen_overflow;
|
||||
|
||||
if (own_req && tmp_opt.saw_tstamp &&
|
||||
!after(TCP_SKB_CB(skb)->seq, tcp_rsk(req)->rcv_nxt))
|
||||
tcp_sk(child)->rx_opt.ts_recent = tmp_opt.rcv_tsval;
|
||||
|
||||
if (own_req && rsk_drop_req(req)) {
|
||||
reqsk_queue_removed(&inet_csk(req->rsk_listener)->icsk_accept_queue, req);
|
||||
inet_csk_reqsk_queue_drop_and_put(req->rsk_listener, req);
|
||||
|
||||
@@ -628,8 +628,8 @@ ip4ip6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
|
||||
}
|
||||
skb_dst_set(skb2, &rt->dst);
|
||||
} else {
|
||||
if (ip_route_input(skb2, eiph->daddr, eiph->saddr, eiph->tos,
|
||||
skb2->dev) ||
|
||||
if (ip_route_input(skb2, eiph->daddr, eiph->saddr,
|
||||
ip4h_dscp(eiph), skb2->dev) ||
|
||||
skb_dst(skb2)->dev->type != ARPHRD_TUNNEL6)
|
||||
goto out;
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user