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:
Greg Kroah-Hartman
2025-03-11 17:09:07 +00:00
117 changed files with 1347 additions and 599 deletions

View File

@@ -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.

View File

@@ -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);

View File

@@ -1,7 +1,7 @@
# SPDX-License-Identifier: GPL-2.0
VERSION = 6
PATCHLEVEL = 1
SUBLEVEL = 129
SUBLEVEL = 130
EXTRAVERSION =
NAME = Curry Ramen

View File

@@ -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);

View File

@@ -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..
*

View File

@@ -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();

View File

@@ -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"

View File

@@ -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)

View File

@@ -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:

View File

@@ -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 */

View File

@@ -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)

View File

@@ -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,

View File

@@ -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,

View File

@@ -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)

View File

@@ -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);
}
}

View File

@@ -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;
}
/*

View File

@@ -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);
/*

View File

@@ -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)

View File

@@ -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);
}

View File

@@ -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)

View File

@@ -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))

View File

@@ -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,

View File

@@ -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);

View File

@@ -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(&notifier->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(&notifier->notifier);

View File

@@ -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);

View File

@@ -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)

View File

@@ -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);

View File

@@ -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];

View File

@@ -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)

View File

@@ -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;
}

View File

@@ -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;
}

View File

@@ -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) {

View File

@@ -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;

View File

@@ -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);

View File

@@ -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))

View File

@@ -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;

View File

@@ -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);

View File

@@ -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

View File

@@ -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),
};

View File

@@ -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;
}

View File

@@ -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;

View File

@@ -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);

View File

@@ -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

View File

@@ -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 = {

View File

@@ -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;
}

View File

@@ -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");

View File

@@ -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;

View File

@@ -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) {

View File

@@ -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;

View File

@@ -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)

View File

@@ -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);

View File

@@ -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;

View File

@@ -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);

View File

@@ -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

View File

@@ -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);

View File

@@ -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);
}

View File

@@ -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) {

View File

@@ -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:

View File

@@ -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)

View File

@@ -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);
}

View File

@@ -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;

View File

@@ -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); \

View File

@@ -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. */

View File

@@ -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);

View File

@@ -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;

View File

@@ -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.

View File

@@ -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 *,

View File

@@ -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;

View File

@@ -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);

View File

@@ -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))

View File

@@ -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);

View File

@@ -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

View 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>

View File

@@ -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,

View File

@@ -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

View File

@@ -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 = &current->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(&current->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);
}
/**

View File

@@ -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();
}

View File

@@ -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);

View File

@@ -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;

View File

@@ -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;
}

View File

@@ -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);

View File

@@ -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;

View File

@@ -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);

View File

@@ -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)

View File

@@ -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)

View File

@@ -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;
}

View File

@@ -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 */

View File

@@ -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)

View File

@@ -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

View File

@@ -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);

View File

@@ -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)) {

View File

@@ -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);
}

View File

@@ -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;
}

View File

@@ -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",

View File

@@ -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);

View File

@@ -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);

View File

@@ -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;

View File

@@ -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;

View File

@@ -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);

View File

@@ -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