Merge 6.1.132 into android14-6.1-lts

Changes in 6.1.132
	clockevents/drivers/i8253: Fix stop sequence for timer 0
	sched/isolation: Prevent boot crash when the boot CPU is nohz_full
	hrtimer: Use and report correct timerslack values for realtime tasks
	fs/ntfs3: Fix shift-out-of-bounds in ntfs_fill_super
	fbdev: hyperv_fb: iounmap() the correct memory when removing a device
	pinctrl: bcm281xx: Fix incorrect regmap max_registers value
	netfilter: nft_ct: Use __refcount_inc() for per-CPU nft_ct_pcpu_template.
	ice: fix memory leak in aRFS after reset
	netfilter: nf_conncount: garbage collection is not skipped when jiffies wrap around
	sched: address a potential NULL pointer dereference in the GRED scheduler.
	wifi: cfg80211: cancel wiphy_work before freeing wiphy
	Bluetooth: hci_event: Fix enabling passive scanning
	Revert "Bluetooth: hci_core: Fix sleeping function called from invalid context"
	net: dsa: mv88e6xxx: Verify after ATU Load ops
	net: mctp i2c: Copy headers if cloned
	netpoll: hold rcu read lock in __netpoll_send_skb()
	drm/hyperv: Fix address space leak when Hyper-V DRM device is removed
	Drivers: hv: vmbus: Don't release fb_mmio resource in vmbus_free_mmio()
	net/mlx5: handle errors in mlx5_chains_create_table()
	eth: bnxt: do not update checksum in bnxt_xdp_build_skb()
	net: switchdev: Convert blocking notification chain to a raw one
	bonding: fix incorrect MAC address setting to receive NS messages
	netfilter: nf_conncount: Fully initialize struct nf_conncount_tuple in insert_tree()
	ipvs: prevent integer overflow in do_ip_vs_get_ctl()
	net_sched: Prevent creation of classes with TC_H_ROOT
	netfilter: nft_exthdr: fix offset with ipv4_find_option()
	gre: Fix IPv6 link-local address generation.
	net: openvswitch: remove misbehaving actions length check
	net/mlx5: Bridge, fix the crash caused by LAG state check
	net/mlx5e: Prevent bridge link show failure for non-eswitch-allowed devices
	nvme-fc: go straight to connecting state when initializing
	hrtimers: Mark is_migration_base() with __always_inline
	powercap: call put_device() on an error path in powercap_register_control_type()
	iscsi_ibft: Fix UBSAN shift-out-of-bounds warning in ibft_attr_show_nic()
	scsi: core: Use GFP_NOIO to avoid circular locking dependency
	scsi: qla1280: Fix kernel oops when debug level > 2
	ACPI: resource: IRQ override for Eluktronics MECH-17
	smb: client: fix noisy when tree connecting to DFS interlink targets
	alpha/elf: Fix misc/setarch test of util-linux by removing 32bit support
	vboxsf: fix building with GCC 15
	HID: intel-ish-hid: fix the length of MNG_SYNC_FW_CLOCK in doorbell
	HID: intel-ish-hid: Send clock sync message immediately after reset
	HID: ignore non-functional sensor in HP 5MP Camera
	HID: hid-apple: Apple Magic Keyboard a3203 USB-C support
	HID: apple: fix up the F6 key on the Omoton KB066 keyboard
	sched: Clarify wake_up_q()'s write to task->wake_q.next
	platform/x86: thinkpad_acpi: Fix invalid fan speed on ThinkPad X120e
	platform/x86: thinkpad_acpi: Support for V9 DYTC platform profiles
	s390/cio: Fix CHPID "configure" attribute caching
	thermal/cpufreq_cooling: Remove structure member documentation
	Xen/swiotlb: mark xen_swiotlb_fixup() __init
	ALSA: hda/realtek: Limit mic boost on Positivo ARN50
	ASoC: rsnd: don't indicate warning on rsnd_kctrl_accept_runtime()
	ASoC: rsnd: adjust convert rate limitation
	ASoC: arizona/madera: use fsleep() in up/down DAPM event delays.
	ASoC: SOF: Intel: hda: add softdep pre to snd-hda-codec-hdmi module
	net: wwan: mhi_wwan_mbim: Silence sequence number glitch errors
	nvme-pci: quirk Acer FA100 for non-uniqueue identifiers
	nvme-tcp: add basic support for the C2HTermReq PDU
	nvmet-rdma: recheck queue state is LIVE in state lock in recv done
	sctp: Fix undefined behavior in left shift operation
	nvme: only allow entering LIVE from CONNECTING state
	ASoC: tas2770: Fix volume scale
	ASoC: tas2764: Fix power control mask
	ASoC: tas2764: Set the SDOUT polarity correctly
	fuse: don't truncate cached, mutated symlink
	perf/x86/intel: Use better start period for frequency mode
	x86/irq: Define trace events conditionally
	mptcp: safety check before fallback
	drm/nouveau: Do not override forced connector status
	block: fix 'kmem_cache of name 'bio-108' already exists'
	io_uring: return error pointer from io_mem_alloc()
	io_uring: add ring freeing helper
	mm: add nommu variant of vm_insert_pages()
	io_uring: get rid of remap_pfn_range() for mapping rings/sqes
	io_uring: don't attempt to mmap larger than what the user asks for
	io_uring: fix corner case forgetting to vunmap
	xfs: pass refcount intent directly through the log intent code
	xfs: pass xfs_extent_free_item directly through the log intent code
	xfs: fix confusing xfs_extent_item variable names
	xfs: pass the xfs_bmbt_irec directly through the log intent code
	xfs: pass per-ag references to xfs_free_extent
	xfs: validate block number being freed before adding to xefi
	xfs: fix bounds check in xfs_defer_agfl_block()
	xfs: use deferred frees for btree block freeing
	xfs: reserve less log space when recovering log intent items
	xfs: move the xfs_rtbitmap.c declarations to xfs_rtbitmap.h
	xfs: convert rt bitmap extent lengths to xfs_rtbxlen_t
	xfs: consider minlen sized extents in xfs_rtallocate_extent_block
	xfs: don't leak recovered attri intent items
	xfs: make rextslog computation consistent with mkfs
	xfs: fix 32-bit truncation in xfs_compute_rextslog
	xfs: don't allow overly small or large realtime volumes
	xfs: remove unused fields from struct xbtree_ifakeroot
	xfs: recompute growfsrtfree transaction reservation while growing rt volume
	xfs: force all buffers to be written during btree bulk load
	xfs: initialise di_crc in xfs_log_dinode
	xfs: add lock protection when remove perag from radix tree
	xfs: fix perag leak when growfs fails
	xfs: ensure logflagsp is initialized in xfs_bmap_del_extent_real
	xfs: update dir3 leaf block metadata after swap
	xfs: reset XFS_ATTR_INCOMPLETE filter on node removal
	xfs: remove conditional building of rt geometry validator functions
	Input: i8042 - swap old quirk combination with new quirk for NHxxRZQ
	Input: i8042 - add required quirks for missing old boardnames
	Input: i8042 - swap old quirk combination with new quirk for several devices
	Input: i8042 - swap old quirk combination with new quirk for more devices
	USB: serial: ftdi_sio: add support for Altera USB Blaster 3
	USB: serial: option: add Telit Cinterion FE990B compositions
	USB: serial: option: fix Telit Cinterion FE990A name
	USB: serial: option: match on interface class for Telit FN990B
	x86/microcode/AMD: Fix out-of-bounds on systems with CPU-less NUMA nodes
	drm/atomic: Filter out redundant DPMS calls
	drm/dp_mst: Fix locking when skipping CSN before topology probing
	drm/amd/display: Restore correct backlight brightness after a GPU reset
	drm/amd/display: Assign normalized_pix_clk when color depth = 14
	drm/amd/display: Fix slab-use-after-free on hdcp_work
	clk: samsung: update PLL locktime for PLL142XX used on FSD platform
	ASoC: amd: yc: Support mic on another Lenovo ThinkPad E16 Gen 2 model
	qlcnic: fix memory leak issues in qlcnic_sriov_common.c
	rust: Disallow BTF generation with Rust + LTO
	lib/buildid: Handle memfd_secret() files in build_id_parse()
	tcp: fix races in tcp_abort()
	tcp: fix forever orphan socket caused by tcp_abort
	leds: mlxreg: Use devm_mutex_init() for mutex initialization
	ASoC: ops: Consistently treat platform_max as control value
	drm/gma500: Add NULL check for pci_gfx_root in mid_get_vbt_data()
	ASoC: codecs: wm0010: Fix error handling path in wm0010_spi_probe()
	scripts: generate_rust_analyzer: Handle sub-modules with no Makefile
	scripts: `make rust-analyzer` for out-of-tree modules
	scripts: generate_rust_analyzer: provide `cfg`s for `core` and `alloc`
	scripts: generate_rust_analyzer: add missing macros deps
	cifs: Fix integer overflow while processing acregmax mount option
	cifs: Fix integer overflow while processing acdirmax mount option
	cifs: Fix integer overflow while processing actimeo mount option
	cifs: Fix integer overflow while processing closetimeo mount option
	i2c: ali1535: Fix an error handling path in ali1535_probe()
	i2c: ali15x3: Fix an error handling path in ali15x3_probe()
	i2c: sis630: Fix an error handling path in sis630_probe()
	arm64: mm: Populate vmemmap at the page level if not section aligned
	smb3: add support for IAKerb
	smb: client: Fix match_session bug preventing session reuse
	HID: apple: disable Fn key handling on the Omoton KB066
	nvme-tcp: Fix a C2HTermReq error message
	smb: client: fix potential UAF in cifs_dump_full_key()
	firmware: imx-scu: fix OF node leak in .probe()
	arm64: dts: freescale: tqma8mpql: Fix vqmmc-supply
	xfrm_output: Force software GSO only in tunnel mode
	soc: imx8m: Remove global soc_uid
	soc: imx8m: Use devm_* to simplify probe failure handling
	soc: imx8m: Unregister cpufreq and soc dev in cleanup path
	ARM: dts: bcm2711: PL011 UARTs are actually r1p5
	RDMA/bnxt_re: Add missing paranthesis in map_qp_id_to_tbl_indx
	ARM: OMAP1: select CONFIG_GENERIC_IRQ_CHIP
	ARM: dts: bcm2711: Don't mark timer regs unconfigured
	RDMA/bnxt_re: Avoid clearing VLAN_ID mask in modify qp path
	RDMA/hns: Fix soft lockup during bt pages loop
	RDMA/hns: Fix unmatched condition in error path of alloc_user_qp_db()
	RDMA/hns: Fix a missing rollback in error path of hns_roce_create_qp_common()
	RDMA/hns: Fix wrong value of max_sge_rd
	Bluetooth: Fix error code in chan_alloc_skb_cb()
	ipv6: Fix memleak of nhc_pcpu_rth_output in fib_check_nh_v6_gw().
	ipv6: Set errno after ip_fib_metrics_init() in ip6_route_info_create().
	net: atm: fix use after free in lec_send()
	net: lwtunnel: fix recursion loops
	net/neighbor: add missing policy for NDTPA_QUEUE_LENBYTES
	Revert "gre: Fix IPv6 link-local address generation."
	i2c: omap: fix IRQ storms
	can: rcar_canfd: Fix page entries in the AFL list
	can: flexcan: only change CAN state when link up in system PM
	can: flexcan: disable transceiver during system PM
	drm/v3d: Don't run jobs that have errors flagged in its fence
	regulator: check that dummy regulator has been probed before using it
	arm64: dts: freescale: imx8mm-verdin-dahlia: add Microphone Jack to sound card
	mmc: sdhci-brcmstb: add cqhci suspend/resume to PM ops
	mmc: atmel-mci: Add missing clk_disable_unprepare()
	proc: fix UAF in proc_get_inode()
	ARM: shmobile: smp: Enforce shmobile_smp_* alignment
	efi/libstub: Avoid physical address 0x0 when doing random allocation
	xsk: fix an integer overflow in xp_create_and_assign_umem()
	batman-adv: Ignore own maximum aggregation size during RX
	soc: qcom: pdr: Fix the potential deadlock
	drm/radeon: fix uninitialized size issue in radeon_vce_cs_parse()
	drm/amdgpu: Fix JPEG video caps max size for navi1x and raven
	ksmbd: fix incorrect validation for num_aces field of smb_acl
	drm/amd/display: Use HW lock mgr for PSR1 when only one eDP
	mptcp: Fix data stream corruption in the address announcement
	netfilter: nft_counter: Use u64_stats_t for statistic.
	drm/mediatek: Fix coverity issue with unintentional integer overflow
	media: mediatek: vcodec: Fix VP8 stateless decoder smatch warning
	arm64: dts: rockchip: fix u2phy1_host status for NanoPi R4S
	drm/amdgpu: fix use-after-free bug
	fs/ntfs3: Change new sparse cluster processing
	wifi: iwlwifi: mvm: ensure offloading TID queue exists
	mm/migrate: fix shmem xarray update during migration
	block, bfq: fix re-introduced UAF in bic_set_bfqq()
	xfs: give xfs_extfree_intent its own perag reference
	Linux 6.1.132

Change-Id: If8f5c0975337904552609e4542f88d5516d3d64d
Signed-off-by: Greg Kroah-Hartman <gregkh@google.com>
This commit is contained in:
Greg Kroah-Hartman
2025-03-30 12:32:45 +00:00
78 changed files with 799 additions and 524 deletions

View File

@@ -1,7 +1,7 @@
# SPDX-License-Identifier: GPL-2.0
VERSION = 6
PATCHLEVEL = 1
SUBLEVEL = 131
SUBLEVEL = 132
EXTRAVERSION =
NAME = Curry Ramen
@@ -1892,11 +1892,6 @@ rustfmt:
rustfmtcheck: rustfmt_flags = --check
rustfmtcheck: rustfmt
# IDE support targets
PHONY += rust-analyzer
rust-analyzer:
$(Q)$(MAKE) $(build)=rust $@
# Misc
# ---------------------------------------------------------------------------
@@ -1951,6 +1946,7 @@ help:
@echo ' headers_install - Install sanitised kernel headers to INSTALL_HDR_PATH'
@echo ' (default: $(abspath $(INSTALL_HDR_PATH)))'
@echo ' clean - remove generated files in module directory only'
@echo ' rust-analyzer - generate rust-project.json rust-analyzer support file'
@echo ''
endif # KBUILD_EXTMOD
@@ -2089,6 +2085,11 @@ quiet_cmd_tags = GEN $@
tags TAGS cscope gtags: FORCE
$(call cmd,tags)
# IDE support targets
PHONY += rust-analyzer
rust-analyzer:
$(Q)$(MAKE) $(build)=rust $@
# Script to generate missing namespace dependencies
# ---------------------------------------------------------------------------

View File

@@ -134,7 +134,7 @@
clocks = <&clocks BCM2835_CLOCK_UART>,
<&clocks BCM2835_CLOCK_VPU>;
clock-names = "uartclk", "apb_pclk";
arm,primecell-periphid = <0x00241011>;
arm,primecell-periphid = <0x00341011>;
status = "disabled";
};
@@ -145,7 +145,7 @@
clocks = <&clocks BCM2835_CLOCK_UART>,
<&clocks BCM2835_CLOCK_VPU>;
clock-names = "uartclk", "apb_pclk";
arm,primecell-periphid = <0x00241011>;
arm,primecell-periphid = <0x00341011>;
status = "disabled";
};
@@ -156,7 +156,7 @@
clocks = <&clocks BCM2835_CLOCK_UART>,
<&clocks BCM2835_CLOCK_VPU>;
clock-names = "uartclk", "apb_pclk";
arm,primecell-periphid = <0x00241011>;
arm,primecell-periphid = <0x00341011>;
status = "disabled";
};
@@ -167,7 +167,7 @@
clocks = <&clocks BCM2835_CLOCK_UART>,
<&clocks BCM2835_CLOCK_VPU>;
clock-names = "uartclk", "apb_pclk";
arm,primecell-periphid = <0x00241011>;
arm,primecell-periphid = <0x00341011>;
status = "disabled";
};
@@ -451,8 +451,6 @@
IRQ_TYPE_LEVEL_LOW)>,
<GIC_PPI 10 (GIC_CPU_MASK_SIMPLE(4) |
IRQ_TYPE_LEVEL_LOW)>;
/* This only applies to the ARMv7 stub */
arm,cpu-registers-not-fw-configured;
};
cpus: cpus {
@@ -1154,6 +1152,7 @@
};
&uart0 {
arm,primecell-periphid = <0x00341011>;
interrupts = <GIC_SPI 121 IRQ_TYPE_LEVEL_HIGH>;
};

View File

@@ -9,6 +9,7 @@ menuconfig ARCH_OMAP1
select ARCH_OMAP
select CLKSRC_MMIO
select FORCE_PCI if PCCARD
select GENERIC_IRQ_CHIP
select GPIOLIB
help
Support for older TI OMAP1 (omap7xx, omap15xx or omap16xx)

View File

@@ -136,6 +136,7 @@ ENDPROC(shmobile_smp_sleep)
.long shmobile_smp_arg - 1b
.bss
.align 2
.globl shmobile_smp_mpidr
shmobile_smp_mpidr:
.space NR_CPUS * 4

View File

@@ -16,10 +16,10 @@
"Headphone Jack", "HPOUTR",
"IN2L", "Line In Jack",
"IN2R", "Line In Jack",
"Headphone Jack", "MICBIAS",
"IN1L", "Headphone Jack";
"Microphone Jack", "MICBIAS",
"IN1L", "Microphone Jack";
simple-audio-card,widgets =
"Microphone", "Headphone Jack",
"Microphone", "Microphone Jack",
"Headphone", "Headphone Jack",
"Line", "Line In Jack";

View File

@@ -1,7 +1,8 @@
// SPDX-License-Identifier: GPL-2.0-or-later OR MIT
/*
* Copyright 2021-2022 TQ-Systems GmbH
* Author: Alexander Stein <alexander.stein@tq-group.com>
* Copyright 2021-2025 TQ-Systems GmbH <linux@ew.tq-group.com>,
* D-82229 Seefeld, Germany.
* Author: Alexander Stein
*/
#include "imx8mp.dtsi"
@@ -23,15 +24,6 @@
regulator-max-microvolt = <3300000>;
regulator-always-on;
};
/* e-MMC IO, needed for HS modes */
reg_vcc1v8: regulator-vcc1v8 {
compatible = "regulator-fixed";
regulator-name = "VCC1V8";
regulator-min-microvolt = <1800000>;
regulator-max-microvolt = <1800000>;
regulator-always-on;
};
};
&A53_0 {
@@ -194,7 +186,7 @@
no-sd;
no-sdio;
vmmc-supply = <&reg_vcc3v3>;
vqmmc-supply = <&reg_vcc1v8>;
vqmmc-supply = <&buck5_reg>;
status = "okay";
};

View File

@@ -117,7 +117,7 @@
};
&u2phy1_host {
status = "disabled";
phy-supply = <&vdd_5v>;
};
&uart0 {

View File

@@ -1209,8 +1209,11 @@ int __meminit vmemmap_populate(unsigned long start, unsigned long end, int node,
pmd_t *pmdp;
WARN_ON((start < VMEMMAP_START) || (end > VMEMMAP_END));
/* [start, end] should be within one section */
WARN_ON_ONCE(end - start > PAGES_PER_SECTION * sizeof(struct page));
if (!ARM64_KERNEL_USES_PMD_MAPS)
if (!ARM64_KERNEL_USES_PMD_MAPS ||
(end - start < PAGES_PER_SECTION * sizeof(struct page)))
return vmemmap_populate_basepages(start, end, node, altmap);
do {

View File

@@ -739,8 +739,8 @@ static void bfq_sync_bfqq_move(struct bfq_data *bfqd,
* old cgroup.
*/
bfq_put_cooperator(sync_bfqq);
bfq_release_process_ref(bfqd, sync_bfqq);
bic_set_bfqq(bic, NULL, true, act_idx);
bfq_release_process_ref(bfqd, sync_bfqq);
}
}

View File

@@ -75,6 +75,10 @@ efi_status_t efi_random_alloc(unsigned long size,
if (align < EFI_ALLOC_ALIGN)
align = EFI_ALLOC_ALIGN;
/* Avoid address 0x0, as it can be mistaken for NULL */
if (alloc_min == 0)
alloc_min = align;
size = round_up(size, EFI_ALLOC_ALIGN);
/* count the suitable slots in each memory map entry */

View File

@@ -279,6 +279,7 @@ static int imx_scu_probe(struct platform_device *pdev)
return ret;
sc_ipc->fast_ipc = of_device_is_compatible(args.np, "fsl,imx8-mu-scu");
of_node_put(args.np);
num_channel = sc_ipc->fast_ipc ? 2 : SCU_MU_CHAN_NUM;
for (i = 0; i < num_channel; i++) {

View File

@@ -132,13 +132,25 @@ static const struct mmu_interval_notifier_ops amdgpu_mn_hsa_ops = {
*/
int amdgpu_mn_register(struct amdgpu_bo *bo, unsigned long addr)
{
int r;
if (bo->kfd_bo)
return mmu_interval_notifier_insert(&bo->notifier, current->mm,
r = mmu_interval_notifier_insert(&bo->notifier, current->mm,
addr, amdgpu_bo_size(bo),
&amdgpu_mn_hsa_ops);
return mmu_interval_notifier_insert(&bo->notifier, current->mm, addr,
amdgpu_bo_size(bo),
&amdgpu_mn_gfx_ops);
else
r = mmu_interval_notifier_insert(&bo->notifier, current->mm, addr,
amdgpu_bo_size(bo),
&amdgpu_mn_gfx_ops);
if (r)
/*
* Make sure amdgpu_hmm_unregister() doesn't call
* mmu_interval_notifier_remove() when the notifier isn't properly
* initialized.
*/
bo->notifier.mm = NULL;
return r;
}
/**

View File

@@ -87,7 +87,7 @@ static const struct amdgpu_video_codec_info nv_video_codecs_decode_array[] =
{codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_MPEG4_AVC, 4096, 4096, 52)},
{codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_VC1, 4096, 4096, 4)},
{codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_HEVC, 8192, 4352, 186)},
{codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_JPEG, 4096, 4096, 0)},
{codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_JPEG, 8192, 8192, 0)},
{codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_VP9, 8192, 4352, 0)},
};

View File

@@ -125,7 +125,7 @@ static const struct amdgpu_video_codec_info rv_video_codecs_decode_array[] =
{codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_MPEG4_AVC, 4096, 4096, 52)},
{codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_VC1, 4096, 4096, 4)},
{codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_HEVC, 4096, 4096, 186)},
{codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_JPEG, 4096, 4096, 0)},
{codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_JPEG, 8192, 8192, 0)},
{codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_VP9, 4096, 4096, 0)},
};

View File

@@ -67,5 +67,17 @@ bool should_use_dmub_lock(struct dc_link *link)
{
if (link->psr_settings.psr_version == DC_PSR_VERSION_SU_1)
return true;
/* only use HW lock for PSR1 on single eDP */
if (link->psr_settings.psr_version == DC_PSR_VERSION_1) {
struct dc_link *edp_links[MAX_NUM_EDP];
int edp_num;
get_edp_links(link->dc, edp_links, &edp_num);
if (edp_num == 1)
return true;
}
return false;
}

View File

@@ -119,7 +119,14 @@ int mtk_drm_gem_dumb_create(struct drm_file *file_priv, struct drm_device *dev,
int ret;
args->pitch = DIV_ROUND_UP(args->width * args->bpp, 8);
args->size = args->pitch * args->height;
/*
* Multiply 2 variables of different types,
* for example: args->size = args->spacing * args->height;
* may cause coverity issue with unintentional overflow.
*/
args->size = args->pitch;
args->size *= args->height;
mtk_gem = mtk_drm_gem_create(dev, args->size, false);
if (IS_ERR(mtk_gem))

View File

@@ -120,6 +120,7 @@ static void mtk_plane_update_new_state(struct drm_plane_state *new_state,
struct mtk_drm_gem_obj *mtk_gem;
unsigned int pitch, format;
dma_addr_t addr;
int offset;
gem = fb->obj[0];
mtk_gem = to_mtk_gem_obj(gem);
@@ -127,8 +128,16 @@ static void mtk_plane_update_new_state(struct drm_plane_state *new_state,
pitch = fb->pitches[0];
format = fb->format->format;
addr += (new_state->src.x1 >> 16) * fb->format->cpp[0];
addr += (new_state->src.y1 >> 16) * pitch;
/*
* Using dma_addr_t variable to calculate with multiplier of different types,
* for example: addr += (new_state->src.x1 >> 16) * fb->format->cpp[0];
* may cause coverity issue with unintentional overflow.
*/
offset = (new_state->src.x1 >> 16) * fb->format->cpp[0];
addr += offset;
offset = (new_state->src.y1 >> 16) * pitch;
addr += offset;
mtk_plane_state->pending.enable = true;
mtk_plane_state->pending.pitch = pitch;

View File

@@ -557,7 +557,7 @@ int radeon_vce_cs_parse(struct radeon_cs_parser *p)
{
int session_idx = -1;
bool destroyed = false, created = false, allocated = false;
uint32_t tmp, handle = 0;
uint32_t tmp = 0, handle = 0;
uint32_t *size = &tmp;
int i, r = 0;

View File

@@ -179,11 +179,15 @@ v3d_tfu_job_run(struct drm_sched_job *sched_job)
struct drm_device *dev = &v3d->drm;
struct dma_fence *fence;
if (unlikely(job->base.base.s_fence->finished.error))
return NULL;
v3d->tfu_job = job;
fence = v3d_fence_create(v3d, V3D_TFU);
if (IS_ERR(fence))
return NULL;
v3d->tfu_job = job;
if (job->base.irq_fence)
dma_fence_put(job->base.irq_fence);
job->base.irq_fence = dma_fence_get(fence);
@@ -217,6 +221,9 @@ v3d_csd_job_run(struct drm_sched_job *sched_job)
struct dma_fence *fence;
int i;
if (unlikely(job->base.base.s_fence->finished.error))
return NULL;
v3d->csd_job = job;
v3d_invalidate_caches(v3d);

View File

@@ -339,6 +339,12 @@ static bool apple_is_non_apple_keyboard(struct hid_device *hdev)
return false;
}
static bool apple_is_omoton_kb066(struct hid_device *hdev)
{
return hdev->product == USB_DEVICE_ID_APPLE_ALU_WIRELESS_ANSI &&
strcmp(hdev->name, "Bluetooth Keyboard") == 0;
}
static inline void apple_setup_key_translation(struct input_dev *input,
const struct apple_key_translation *table)
{
@@ -497,9 +503,6 @@ static int hidinput_apple_event(struct hid_device *hid, struct input_dev *input,
}
}
if (usage->hid == 0xc0301) /* Omoton KB066 quirk */
code = KEY_F6;
if (usage->code != code) {
input_event_with_scancode(input, usage->type, code, usage->hid, value);
@@ -679,7 +682,7 @@ static int apple_input_configured(struct hid_device *hdev,
{
struct apple_sc *asc = hid_get_drvdata(hdev);
if ((asc->quirks & APPLE_HAS_FN) && !asc->fn_found) {
if (((asc->quirks & APPLE_HAS_FN) && !asc->fn_found) || apple_is_omoton_kb066(hdev)) {
hid_info(hdev, "Fn key not found (Apple Wireless Keyboard clone?), disabling Fn key handling\n");
asc->quirks &= ~APPLE_HAS_FN;
}

View File

@@ -490,6 +490,8 @@ MODULE_DEVICE_TABLE(pci, ali1535_ids);
static int ali1535_probe(struct pci_dev *dev, const struct pci_device_id *id)
{
int ret;
if (ali1535_setup(dev)) {
dev_warn(&dev->dev,
"ALI1535 not detected, module not inserted.\n");
@@ -501,7 +503,15 @@ static int ali1535_probe(struct pci_dev *dev, const struct pci_device_id *id)
snprintf(ali1535_adapter.name, sizeof(ali1535_adapter.name),
"SMBus ALI1535 adapter at %04x", ali1535_offset);
return i2c_add_adapter(&ali1535_adapter);
ret = i2c_add_adapter(&ali1535_adapter);
if (ret)
goto release_region;
return 0;
release_region:
release_region(ali1535_smba, ALI1535_SMB_IOSIZE);
return ret;
}
static void ali1535_remove(struct pci_dev *dev)

View File

@@ -473,6 +473,8 @@ MODULE_DEVICE_TABLE (pci, ali15x3_ids);
static int ali15x3_probe(struct pci_dev *dev, const struct pci_device_id *id)
{
int ret;
if (ali15x3_setup(dev)) {
dev_err(&dev->dev,
"ALI15X3 not detected, module not inserted.\n");
@@ -484,7 +486,15 @@ static int ali15x3_probe(struct pci_dev *dev, const struct pci_device_id *id)
snprintf(ali15x3_adapter.name, sizeof(ali15x3_adapter.name),
"SMBus ALI15X3 adapter at %04x", ali15x3_smba);
return i2c_add_adapter(&ali15x3_adapter);
ret = i2c_add_adapter(&ali15x3_adapter);
if (ret)
goto release_region;
return 0;
release_region:
release_region(ali15x3_smba, ALI15X3_SMB_IOSIZE);
return ret;
}
static void ali15x3_remove(struct pci_dev *dev)

View File

@@ -1049,23 +1049,6 @@ static int omap_i2c_transmit_data(struct omap_i2c_dev *omap, u8 num_bytes,
return 0;
}
static irqreturn_t
omap_i2c_isr(int irq, void *dev_id)
{
struct omap_i2c_dev *omap = dev_id;
irqreturn_t ret = IRQ_HANDLED;
u16 mask;
u16 stat;
stat = omap_i2c_read_reg(omap, OMAP_I2C_STAT_REG);
mask = omap_i2c_read_reg(omap, OMAP_I2C_IE_REG) & ~OMAP_I2C_STAT_NACK;
if (stat & mask)
ret = IRQ_WAKE_THREAD;
return ret;
}
static int omap_i2c_xfer_data(struct omap_i2c_dev *omap)
{
u16 bits;
@@ -1096,8 +1079,13 @@ static int omap_i2c_xfer_data(struct omap_i2c_dev *omap)
}
if (stat & OMAP_I2C_STAT_NACK) {
err |= OMAP_I2C_STAT_NACK;
omap->cmd_err |= OMAP_I2C_STAT_NACK;
omap_i2c_ack_stat(omap, OMAP_I2C_STAT_NACK);
if (!(stat & ~OMAP_I2C_STAT_NACK)) {
err = -EAGAIN;
break;
}
}
if (stat & OMAP_I2C_STAT_AL) {
@@ -1475,7 +1463,7 @@ omap_i2c_probe(struct platform_device *pdev)
IRQF_NO_SUSPEND, pdev->name, omap);
else
r = devm_request_threaded_irq(&pdev->dev, omap->irq,
omap_i2c_isr, omap_i2c_isr_thread,
NULL, omap_i2c_isr_thread,
IRQF_NO_SUSPEND | IRQF_ONESHOT,
pdev->name, omap);

View File

@@ -509,6 +509,8 @@ MODULE_DEVICE_TABLE(pci, sis630_ids);
static int sis630_probe(struct pci_dev *dev, const struct pci_device_id *id)
{
int ret;
if (sis630_setup(dev)) {
dev_err(&dev->dev,
"SIS630 compatible bus not detected, "
@@ -522,7 +524,15 @@ static int sis630_probe(struct pci_dev *dev, const struct pci_device_id *id)
snprintf(sis630_adapter.name, sizeof(sis630_adapter.name),
"SMBus SIS630 adapter at %04x", smbus_base + SMB_STS);
return i2c_add_adapter(&sis630_adapter);
ret = i2c_add_adapter(&sis630_adapter);
if (ret)
goto release_region;
return 0;
release_region:
release_region(smbus_base + SMB_STS, SIS630_SMB_IOREGION);
return ret;
}
static void sis630_remove(struct pci_dev *dev)

View File

@@ -1186,8 +1186,6 @@ static void __modify_flags_from_init_state(struct bnxt_qplib_qp *qp)
qp->path_mtu =
CMDQ_MODIFY_QP_PATH_MTU_MTU_2048;
}
qp->modify_flags &=
~CMDQ_MODIFY_QP_MODIFY_MASK_VLAN_ID;
/* Bono FW require the max_dest_rd_atomic to be >= 1 */
if (qp->max_dest_rd_atomic < 1)
qp->max_dest_rd_atomic = 1;

View File

@@ -220,9 +220,10 @@ int bnxt_qplib_deinit_rcfw(struct bnxt_qplib_rcfw *rcfw);
int bnxt_qplib_init_rcfw(struct bnxt_qplib_rcfw *rcfw,
struct bnxt_qplib_ctx *ctx, int is_virtfn);
void bnxt_qplib_mark_qp_error(void *qp_handle);
static inline u32 map_qp_id_to_tbl_indx(u32 qid, struct bnxt_qplib_rcfw *rcfw)
{
/* Last index of the qp_tbl is for QP1 ie. qp_tbl_size - 1*/
return (qid == 1) ? rcfw->qp_tbl_size - 1 : qid % rcfw->qp_tbl_size - 2;
return (qid == 1) ? rcfw->qp_tbl_size - 1 : (qid % (rcfw->qp_tbl_size - 2));
}
#endif /* __BNXT_QPLIB_RCFW_H__ */

View File

@@ -1416,6 +1416,11 @@ static int hem_list_alloc_root_bt(struct hns_roce_dev *hr_dev,
return ret;
}
/* This is the bottom bt pages number of a 100G MR on 4K OS, assuming
* the bt page size is not expanded by cal_best_bt_pg_sz()
*/
#define RESCHED_LOOP_CNT_THRESHOLD_ON_4K 12800
/* construct the base address table and link them by address hop config */
int hns_roce_hem_list_request(struct hns_roce_dev *hr_dev,
struct hns_roce_hem_list *hem_list,
@@ -1424,6 +1429,7 @@ int hns_roce_hem_list_request(struct hns_roce_dev *hr_dev,
{
const struct hns_roce_buf_region *r;
int ofs, end;
int loop;
int unit;
int ret;
int i;
@@ -1441,7 +1447,10 @@ int hns_roce_hem_list_request(struct hns_roce_dev *hr_dev,
continue;
end = r->offset + r->count;
for (ofs = r->offset; ofs < end; ofs += unit) {
for (ofs = r->offset, loop = 1; ofs < end; ofs += unit, loop++) {
if (!(loop % RESCHED_LOOP_CNT_THRESHOLD_ON_4K))
cond_resched();
ret = hem_list_alloc_mid_bt(hr_dev, r, unit, ofs,
hem_list->mid_bt[i],
&hem_list->btm_bt);
@@ -1498,9 +1507,14 @@ void *hns_roce_hem_list_find_mtt(struct hns_roce_dev *hr_dev,
struct list_head *head = &hem_list->btm_bt;
struct hns_roce_hem_item *hem, *temp_hem;
void *cpu_base = NULL;
int loop = 1;
int nr = 0;
list_for_each_entry_safe(hem, temp_hem, head, sibling) {
if (!(loop % RESCHED_LOOP_CNT_THRESHOLD_ON_4K))
cond_resched();
loop++;
if (hem_list_page_is_in_range(hem, offset)) {
nr = offset - hem->start;
cpu_base = hem->addr + nr * BA_BYTE_LEN;

View File

@@ -182,7 +182,7 @@ static int hns_roce_query_device(struct ib_device *ib_dev,
IB_DEVICE_RC_RNR_NAK_GEN;
props->max_send_sge = hr_dev->caps.max_sq_sg;
props->max_recv_sge = hr_dev->caps.max_rq_sg;
props->max_sge_rd = 1;
props->max_sge_rd = hr_dev->caps.max_sq_sg;
props->max_cq = hr_dev->caps.num_cqs;
props->max_cqe = hr_dev->caps.max_cqes;
props->max_mr = hr_dev->caps.num_mtpts;

View File

@@ -924,12 +924,14 @@ static int alloc_user_qp_db(struct hns_roce_dev *hr_dev,
struct hns_roce_ib_create_qp *ucmd,
struct hns_roce_ib_create_qp_resp *resp)
{
bool has_sdb = user_qp_has_sdb(hr_dev, init_attr, udata, resp, ucmd);
struct hns_roce_ucontext *uctx = rdma_udata_to_drv_context(udata,
struct hns_roce_ucontext, ibucontext);
bool has_rdb = user_qp_has_rdb(hr_dev, init_attr, udata, resp);
struct ib_device *ibdev = &hr_dev->ib_dev;
int ret;
if (user_qp_has_sdb(hr_dev, init_attr, udata, resp, ucmd)) {
if (has_sdb) {
ret = hns_roce_db_map_user(uctx, ucmd->sdb_addr, &hr_qp->sdb);
if (ret) {
ibdev_err(ibdev,
@@ -940,7 +942,7 @@ static int alloc_user_qp_db(struct hns_roce_dev *hr_dev,
hr_qp->en_flags |= HNS_ROCE_QP_CAP_SQ_RECORD_DB;
}
if (user_qp_has_rdb(hr_dev, init_attr, udata, resp)) {
if (has_rdb) {
ret = hns_roce_db_map_user(uctx, ucmd->db_addr, &hr_qp->rdb);
if (ret) {
ibdev_err(ibdev,
@@ -954,7 +956,7 @@ static int alloc_user_qp_db(struct hns_roce_dev *hr_dev,
return 0;
err_sdb:
if (hr_qp->en_flags & HNS_ROCE_QP_CAP_SQ_RECORD_DB)
if (has_sdb)
hns_roce_db_unmap_user(uctx, &hr_qp->sdb);
err_out:
return ret;
@@ -1211,7 +1213,7 @@ static int hns_roce_create_qp_common(struct hns_roce_dev *hr_dev,
min(udata->outlen, sizeof(resp)));
if (ret) {
ibdev_err(ibdev, "copy qp resp failed!\n");
goto err_store;
goto err_flow_ctrl;
}
}

View File

@@ -336,14 +336,18 @@ static int vdec_vp8_slice_decode(void *h_vdec, struct mtk_vcodec_mem *bs,
src_buf_info = container_of(bs, struct mtk_video_dec_buf, bs_buffer);
fb = inst->ctx->dev->vdec_pdata->get_cap_buffer(inst->ctx);
dst_buf_info = container_of(fb, struct mtk_video_dec_buf, frame_buffer);
if (!fb) {
mtk_vcodec_err(inst, "fb buffer is NULL");
return -ENOMEM;
}
y_fb_dma = fb ? (u64)fb->base_y.dma_addr : 0;
dst_buf_info = container_of(fb, struct mtk_video_dec_buf, frame_buffer);
y_fb_dma = fb->base_y.dma_addr;
if (inst->ctx->q_data[MTK_Q_DATA_DST].fmt->num_planes == 1)
c_fb_dma = y_fb_dma +
inst->ctx->picinfo.buf_w * inst->ctx->picinfo.buf_h;
else
c_fb_dma = fb ? (u64)fb->base_c.dma_addr : 0;
c_fb_dma = fb->base_c.dma_addr;
inst->vsi->dec.bs_dma = (u64)bs->dma_addr;
inst->vsi->dec.bs_sz = bs->size;

View File

@@ -2506,8 +2506,10 @@ static int atmci_probe(struct platform_device *pdev)
/* Get MCI capabilities and set operations according to it */
atmci_get_cap(host);
ret = atmci_configure_dma(host);
if (ret == -EPROBE_DEFER)
if (ret == -EPROBE_DEFER) {
clk_disable_unprepare(host->mck);
goto err_dma_probe_defer;
}
if (ret == 0) {
host->prepare_data = &atmci_prepare_data_dma;
host->submit_data = &atmci_submit_data_dma;

View File

@@ -396,8 +396,15 @@ static int sdhci_brcmstb_suspend(struct device *dev)
struct sdhci_host *host = dev_get_drvdata(dev);
struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
struct sdhci_brcmstb_priv *priv = sdhci_pltfm_priv(pltfm_host);
int ret;
clk_disable_unprepare(priv->base_clk);
if (host->mmc->caps2 & MMC_CAP2_CQE) {
ret = cqhci_suspend(host->mmc);
if (ret)
return ret;
}
return sdhci_pltfm_suspend(dev);
}
@@ -422,6 +429,9 @@ static int sdhci_brcmstb_resume(struct device *dev)
ret = clk_set_rate(priv->base_clk, priv->base_freq_hz);
}
if (host->mmc->caps2 & MMC_CAP2_CQE)
ret = cqhci_resume(host->mmc);
return ret;
}
#endif

View File

@@ -2230,14 +2230,19 @@ static int __maybe_unused flexcan_suspend(struct device *device)
flexcan_chip_interrupts_disable(dev);
err = flexcan_transceiver_disable(priv);
if (err)
return err;
err = pinctrl_pm_select_sleep_state(device);
if (err)
return err;
}
netif_stop_queue(dev);
netif_device_detach(dev);
priv->can.state = CAN_STATE_SLEEPING;
}
priv->can.state = CAN_STATE_SLEEPING;
return 0;
}
@@ -2248,7 +2253,6 @@ static int __maybe_unused flexcan_resume(struct device *device)
struct flexcan_priv *priv = netdev_priv(dev);
int err;
priv->can.state = CAN_STATE_ERROR_ACTIVE;
if (netif_running(dev)) {
netif_device_attach(dev);
netif_start_queue(dev);
@@ -2262,12 +2266,20 @@ static int __maybe_unused flexcan_resume(struct device *device)
if (err)
return err;
err = flexcan_chip_start(dev);
err = flexcan_transceiver_enable(priv);
if (err)
return err;
err = flexcan_chip_start(dev);
if (err) {
flexcan_transceiver_disable(priv);
return err;
}
flexcan_chip_interrupts_enable(dev);
}
priv->can.state = CAN_STATE_ERROR_ACTIVE;
}
return 0;

View File

@@ -772,22 +772,14 @@ static void rcar_canfd_configure_controller(struct rcar_canfd_global *gpriv)
}
static void rcar_canfd_configure_afl_rules(struct rcar_canfd_global *gpriv,
u32 ch)
u32 ch, u32 rule_entry)
{
u32 cfg;
int offset, start, page, num_rules = RCANFD_CHANNEL_NUMRULES;
int offset, page, num_rules = RCANFD_CHANNEL_NUMRULES;
u32 rule_entry_index = rule_entry % 16;
u32 ridx = ch + RCANFD_RFFIFO_IDX;
if (ch == 0) {
start = 0; /* Channel 0 always starts from 0th rule */
} else {
/* Get number of Channel 0 rules and adjust */
cfg = rcar_canfd_read(gpriv->base, RCANFD_GAFLCFG(ch));
start = RCANFD_GAFLCFG_GETRNC(gpriv, 0, cfg);
}
/* Enable write access to entry */
page = RCANFD_GAFL_PAGENUM(start);
page = RCANFD_GAFL_PAGENUM(rule_entry);
rcar_canfd_set_bit(gpriv->base, RCANFD_GAFLECTR,
(RCANFD_GAFLECTR_AFLPN(gpriv, page) |
RCANFD_GAFLECTR_AFLDAE));
@@ -803,13 +795,13 @@ static void rcar_canfd_configure_afl_rules(struct rcar_canfd_global *gpriv,
offset = RCANFD_C_GAFL_OFFSET;
/* Accept all IDs */
rcar_canfd_write(gpriv->base, RCANFD_GAFLID(offset, start), 0);
rcar_canfd_write(gpriv->base, RCANFD_GAFLID(offset, rule_entry_index), 0);
/* IDE or RTR is not considered for matching */
rcar_canfd_write(gpriv->base, RCANFD_GAFLM(offset, start), 0);
rcar_canfd_write(gpriv->base, RCANFD_GAFLM(offset, rule_entry_index), 0);
/* Any data length accepted */
rcar_canfd_write(gpriv->base, RCANFD_GAFLP0(offset, start), 0);
rcar_canfd_write(gpriv->base, RCANFD_GAFLP0(offset, rule_entry_index), 0);
/* Place the msg in corresponding Rx FIFO entry */
rcar_canfd_set_bit(gpriv->base, RCANFD_GAFLP1(offset, start),
rcar_canfd_set_bit(gpriv->base, RCANFD_GAFLP1(offset, rule_entry_index),
RCANFD_GAFLP1_GAFLFDP(ridx));
/* Disable write access to page */
@@ -1825,6 +1817,7 @@ static int rcar_canfd_probe(struct platform_device *pdev)
unsigned long channels_mask = 0;
int err, ch_irq, g_irq;
int g_err_irq, g_recc_irq;
u32 rule_entry = 0;
bool fdmode = true; /* CAN FD only mode - default */
enum rcanfd_chip_id chip_id;
int max_channels;
@@ -2003,7 +1996,8 @@ static int rcar_canfd_probe(struct platform_device *pdev)
rcar_canfd_configure_tx(gpriv, ch);
/* Configure receive rules */
rcar_canfd_configure_afl_rules(gpriv, ch);
rcar_canfd_configure_afl_rules(gpriv, ch, rule_entry);
rule_entry += RCANFD_CHANNEL_NUMRULES;
}
/* Configure common interrupts */

View File

@@ -1286,7 +1286,9 @@ static int __iwl_mvm_suspend(struct ieee80211_hw *hw,
mvm->net_detect = true;
} else {
struct iwl_wowlan_config_cmd wowlan_config_cmd = {};
struct iwl_wowlan_config_cmd wowlan_config_cmd = {
.offloading_tid = 0,
};
wowlan_config_cmd.sta_id = mvmvif->ap_sta_id;
@@ -1298,6 +1300,11 @@ static int __iwl_mvm_suspend(struct ieee80211_hw *hw,
goto out_noreset;
}
ret = iwl_mvm_sta_ensure_queue(
mvm, ap_sta->txq[wowlan_config_cmd.offloading_tid]);
if (ret)
goto out_noreset;
ret = iwl_mvm_get_wowlan_config(mvm, wowlan, &wowlan_config_cmd,
vif, mvmvif, ap_sta);
if (ret)

View File

@@ -1419,6 +1419,34 @@ out_err:
return ret;
}
int iwl_mvm_sta_ensure_queue(struct iwl_mvm *mvm,
struct ieee80211_txq *txq)
{
struct iwl_mvm_txq *mvmtxq = iwl_mvm_txq_from_mac80211(txq);
int ret = -EINVAL;
lockdep_assert_held(&mvm->mutex);
if (likely(test_bit(IWL_MVM_TXQ_STATE_READY, &mvmtxq->state)) ||
!txq->sta) {
return 0;
}
if (!iwl_mvm_sta_alloc_queue(mvm, txq->sta, txq->ac, txq->tid)) {
set_bit(IWL_MVM_TXQ_STATE_READY, &mvmtxq->state);
ret = 0;
}
local_bh_disable();
spin_lock(&mvm->add_stream_lock);
if (!list_empty(&mvmtxq->list))
list_del_init(&mvmtxq->list);
spin_unlock(&mvm->add_stream_lock);
local_bh_enable();
return ret;
}
void iwl_mvm_add_new_dqa_stream_wk(struct work_struct *wk)
{
struct iwl_mvm *mvm = container_of(wk, struct iwl_mvm,

View File

@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
/*
* Copyright (C) 2012-2014, 2018-2021 Intel Corporation
* Copyright (C) 2012-2014, 2018-2024 Intel Corporation
* Copyright (C) 2013-2014 Intel Mobile Communications GmbH
* Copyright (C) 2015-2016 Intel Deutschland GmbH
*/
@@ -544,6 +544,7 @@ void iwl_mvm_modify_all_sta_disable_tx(struct iwl_mvm *mvm,
struct iwl_mvm_vif *mvmvif,
bool disable);
void iwl_mvm_csa_client_absent(struct iwl_mvm *mvm, struct ieee80211_vif *vif);
int iwl_mvm_sta_ensure_queue(struct iwl_mvm *mvm, struct ieee80211_txq *txq);
void iwl_mvm_add_new_dqa_stream_wk(struct work_struct *wk);
int iwl_mvm_add_pasn_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
struct iwl_mvm_int_sta *sta, u8 *addr, u32 cipher,

View File

@@ -706,7 +706,7 @@ static void nvme_tcp_handle_c2h_term(struct nvme_tcp_queue *queue,
[NVME_TCP_FES_PDU_SEQ_ERR] = "PDU Sequence Error",
[NVME_TCP_FES_HDR_DIGEST_ERR] = "Header Digest Error",
[NVME_TCP_FES_DATA_OUT_OF_RANGE] = "Data Transfer Out Of Range",
[NVME_TCP_FES_R2T_LIMIT_EXCEEDED] = "R2T Limit Exceeded",
[NVME_TCP_FES_DATA_LIMIT_EXCEEDED] = "Data Transfer Limit Exceeded",
[NVME_TCP_FES_UNSUPPORTED_PARAM] = "Unsupported Parameter",
};

View File

@@ -2091,6 +2091,10 @@ static int regulator_resolve_supply(struct regulator_dev *rdev)
if (have_full_constraints()) {
r = dummy_regulator_rdev;
if (!r) {
ret = -EPROBE_DEFER;
goto out;
}
get_device(&r->dev);
} else {
dev_err(dev, "Failed to resolve %s-supply for %s\n",
@@ -2108,6 +2112,10 @@ static int regulator_resolve_supply(struct regulator_dev *rdev)
goto out;
}
r = dummy_regulator_rdev;
if (!r) {
ret = -EPROBE_DEFER;
goto out;
}
get_device(&r->dev);
}
@@ -2216,8 +2224,10 @@ struct regulator *_regulator_get(struct device *dev, const char *id,
* enabled, even if it isn't hooked up, and just
* provide a dummy.
*/
dev_warn(dev, "supply %s not found, using dummy regulator\n", id);
rdev = dummy_regulator_rdev;
if (!rdev)
return ERR_PTR(-EPROBE_DEFER);
dev_warn(dev, "supply %s not found, using dummy regulator\n", id);
get_device(&rdev->dev);
break;

View File

@@ -30,11 +30,9 @@
struct imx8_soc_data {
char *name;
int (*soc_revision)(u32 *socrev);
int (*soc_revision)(u32 *socrev, u64 *socuid);
};
static u64 soc_uid;
#ifdef CONFIG_HAVE_ARM_SMCCC
static u32 imx8mq_soc_revision_from_atf(void)
{
@@ -51,24 +49,22 @@ static u32 imx8mq_soc_revision_from_atf(void)
static inline u32 imx8mq_soc_revision_from_atf(void) { return 0; };
#endif
static int imx8mq_soc_revision(u32 *socrev)
static int imx8mq_soc_revision(u32 *socrev, u64 *socuid)
{
struct device_node *np;
struct device_node *np __free(device_node) =
of_find_compatible_node(NULL, NULL, "fsl,imx8mq-ocotp");
void __iomem *ocotp_base;
u32 magic;
u32 rev;
struct clk *clk;
int ret;
np = of_find_compatible_node(NULL, NULL, "fsl,imx8mq-ocotp");
if (!np)
return -EINVAL;
ocotp_base = of_iomap(np, 0);
if (!ocotp_base) {
ret = -EINVAL;
goto err_iomap;
}
if (!ocotp_base)
return -EINVAL;
clk = of_clk_get_by_name(np, NULL);
if (IS_ERR(clk)) {
@@ -89,44 +85,39 @@ static int imx8mq_soc_revision(u32 *socrev)
rev = REV_B1;
}
soc_uid = readl_relaxed(ocotp_base + OCOTP_UID_HIGH);
soc_uid <<= 32;
soc_uid |= readl_relaxed(ocotp_base + OCOTP_UID_LOW);
*socuid = readl_relaxed(ocotp_base + OCOTP_UID_HIGH);
*socuid <<= 32;
*socuid |= readl_relaxed(ocotp_base + OCOTP_UID_LOW);
*socrev = rev;
clk_disable_unprepare(clk);
clk_put(clk);
iounmap(ocotp_base);
of_node_put(np);
return 0;
err_clk:
iounmap(ocotp_base);
err_iomap:
of_node_put(np);
return ret;
}
static int imx8mm_soc_uid(void)
static int imx8mm_soc_uid(u64 *socuid)
{
struct device_node *np __free(device_node) =
of_find_compatible_node(NULL, NULL, "fsl,imx8mm-ocotp");
void __iomem *ocotp_base;
struct device_node *np;
struct clk *clk;
int ret = 0;
u32 offset = of_machine_is_compatible("fsl,imx8mp") ?
IMX8MP_OCOTP_UID_OFFSET : 0;
np = of_find_compatible_node(NULL, NULL, "fsl,imx8mm-ocotp");
if (!np)
return -EINVAL;
ocotp_base = of_iomap(np, 0);
if (!ocotp_base) {
ret = -EINVAL;
goto err_iomap;
}
if (!ocotp_base)
return -EINVAL;
clk = of_clk_get_by_name(np, NULL);
if (IS_ERR(clk)) {
@@ -136,47 +127,36 @@ static int imx8mm_soc_uid(void)
clk_prepare_enable(clk);
soc_uid = readl_relaxed(ocotp_base + OCOTP_UID_HIGH + offset);
soc_uid <<= 32;
soc_uid |= readl_relaxed(ocotp_base + OCOTP_UID_LOW + offset);
*socuid = readl_relaxed(ocotp_base + OCOTP_UID_HIGH + offset);
*socuid <<= 32;
*socuid |= readl_relaxed(ocotp_base + OCOTP_UID_LOW + offset);
clk_disable_unprepare(clk);
clk_put(clk);
err_clk:
iounmap(ocotp_base);
err_iomap:
of_node_put(np);
return ret;
}
static int imx8mm_soc_revision(u32 *socrev)
static int imx8mm_soc_revision(u32 *socrev, u64 *socuid)
{
struct device_node *np;
struct device_node *np __free(device_node) =
of_find_compatible_node(NULL, NULL, "fsl,imx8mm-anatop");
void __iomem *anatop_base;
int ret;
np = of_find_compatible_node(NULL, NULL, "fsl,imx8mm-anatop");
if (!np)
return -EINVAL;
anatop_base = of_iomap(np, 0);
if (!anatop_base) {
ret = -EINVAL;
goto err_iomap;
}
if (!anatop_base)
return -EINVAL;
*socrev = readl_relaxed(anatop_base + ANADIG_DIGPROG_IMX8MM);
iounmap(anatop_base);
of_node_put(np);
return imx8mm_soc_uid();
err_iomap:
of_node_put(np);
return ret;
return imx8mm_soc_uid(socuid);
}
static const struct imx8_soc_data imx8mq_soc_data = {
@@ -207,21 +187,34 @@ static __maybe_unused const struct of_device_id imx8_soc_match[] = {
{ }
};
#define imx8_revision(soc_rev) \
soc_rev ? \
kasprintf(GFP_KERNEL, "%d.%d", (soc_rev >> 4) & 0xf, soc_rev & 0xf) : \
#define imx8_revision(dev, soc_rev) \
(soc_rev) ? \
devm_kasprintf((dev), GFP_KERNEL, "%d.%d", ((soc_rev) >> 4) & 0xf, (soc_rev) & 0xf) : \
"unknown"
static void imx8m_unregister_soc(void *data)
{
soc_device_unregister(data);
}
static void imx8m_unregister_cpufreq(void *data)
{
platform_device_unregister(data);
}
static int imx8m_soc_probe(struct platform_device *pdev)
{
struct soc_device_attribute *soc_dev_attr;
struct soc_device *soc_dev;
const struct of_device_id *id;
u32 soc_rev = 0;
struct platform_device *cpufreq_dev;
const struct imx8_soc_data *data;
struct device *dev = &pdev->dev;
const struct of_device_id *id;
struct soc_device *soc_dev;
u32 soc_rev = 0;
u64 soc_uid = 0;
int ret;
soc_dev_attr = kzalloc(sizeof(*soc_dev_attr), GFP_KERNEL);
soc_dev_attr = devm_kzalloc(dev, sizeof(*soc_dev_attr), GFP_KERNEL);
if (!soc_dev_attr)
return -ENOMEM;
@@ -229,58 +222,52 @@ static int imx8m_soc_probe(struct platform_device *pdev)
ret = of_property_read_string(of_root, "model", &soc_dev_attr->machine);
if (ret)
goto free_soc;
return ret;
id = of_match_node(imx8_soc_match, of_root);
if (!id) {
ret = -ENODEV;
goto free_soc;
}
if (!id)
return -ENODEV;
data = id->data;
if (data) {
soc_dev_attr->soc_id = data->name;
if (data->soc_revision) {
ret = data->soc_revision(&soc_rev);
ret = data->soc_revision(&soc_rev, &soc_uid);
if (ret)
goto free_soc;
return ret;
}
}
soc_dev_attr->revision = imx8_revision(soc_rev);
if (!soc_dev_attr->revision) {
ret = -ENOMEM;
goto free_soc;
}
soc_dev_attr->revision = imx8_revision(dev, soc_rev);
if (!soc_dev_attr->revision)
return -ENOMEM;
soc_dev_attr->serial_number = kasprintf(GFP_KERNEL, "%016llX", soc_uid);
if (!soc_dev_attr->serial_number) {
ret = -ENOMEM;
goto free_rev;
}
soc_dev_attr->serial_number = devm_kasprintf(dev, GFP_KERNEL, "%016llX", soc_uid);
if (!soc_dev_attr->serial_number)
return -ENOMEM;
soc_dev = soc_device_register(soc_dev_attr);
if (IS_ERR(soc_dev)) {
ret = PTR_ERR(soc_dev);
goto free_serial_number;
}
if (IS_ERR(soc_dev))
return PTR_ERR(soc_dev);
ret = devm_add_action(dev, imx8m_unregister_soc, soc_dev);
if (ret)
return ret;
pr_info("SoC: %s revision %s\n", soc_dev_attr->soc_id,
soc_dev_attr->revision);
if (IS_ENABLED(CONFIG_ARM_IMX_CPUFREQ_DT))
platform_device_register_simple("imx-cpufreq-dt", -1, NULL, 0);
if (IS_ENABLED(CONFIG_ARM_IMX_CPUFREQ_DT)) {
cpufreq_dev = platform_device_register_simple("imx-cpufreq-dt", -1, NULL, 0);
if (IS_ERR(cpufreq_dev))
return dev_err_probe(dev, PTR_ERR(cpufreq_dev),
"Failed to register imx-cpufreq-dev device\n");
ret = devm_add_action(dev, imx8m_unregister_cpufreq, cpufreq_dev);
if (ret)
return ret;
}
return 0;
free_serial_number:
kfree(soc_dev_attr->serial_number);
free_rev:
if (strcmp(soc_dev_attr->revision, "unknown"))
kfree(soc_dev_attr->revision);
free_soc:
kfree(soc_dev_attr);
return ret;
}
static struct platform_driver imx8m_soc_driver = {

View File

@@ -74,7 +74,6 @@ static int pdr_locator_new_server(struct qmi_handle *qmi,
{
struct pdr_handle *pdr = container_of(qmi, struct pdr_handle,
locator_hdl);
struct pdr_service *pds;
mutex_lock(&pdr->lock);
/* Create a local client port for QMI communication */
@@ -86,12 +85,7 @@ static int pdr_locator_new_server(struct qmi_handle *qmi,
mutex_unlock(&pdr->lock);
/* Service pending lookup requests */
mutex_lock(&pdr->list_lock);
list_for_each_entry(pds, &pdr->lookups, node) {
if (pds->need_locator_lookup)
schedule_work(&pdr->locator_work);
}
mutex_unlock(&pdr->list_lock);
schedule_work(&pdr->locator_work);
return 0;
}

View File

@@ -176,7 +176,7 @@ out:
int attr_allocate_clusters(struct ntfs_sb_info *sbi, struct runs_tree *run,
CLST vcn, CLST lcn, CLST len, CLST *pre_alloc,
enum ALLOCATE_OPT opt, CLST *alen, const size_t fr,
CLST *new_lcn)
CLST *new_lcn, CLST *new_len)
{
int err;
CLST flen, vcn0 = vcn, pre = pre_alloc ? *pre_alloc : 0;
@@ -196,20 +196,36 @@ int attr_allocate_clusters(struct ntfs_sb_info *sbi, struct runs_tree *run,
if (err)
goto out;
if (new_lcn && vcn == vcn0)
*new_lcn = lcn;
if (vcn == vcn0) {
/* Return the first fragment. */
if (new_lcn)
*new_lcn = lcn;
if (new_len)
*new_len = flen;
}
/* Add new fragment into run storage. */
if (!run_add_entry(run, vcn, lcn, flen, opt == ALLOCATE_MFT)) {
if (!run_add_entry(run, vcn, lcn, flen, opt & ALLOCATE_MFT)) {
/* Undo last 'ntfs_look_for_free_space' */
mark_as_free_ex(sbi, lcn, len, false);
err = -ENOMEM;
goto out;
}
if (opt & ALLOCATE_ZERO) {
u8 shift = sbi->cluster_bits - SECTOR_SHIFT;
err = blkdev_issue_zeroout(sbi->sb->s_bdev,
(sector_t)lcn << shift,
(sector_t)flen << shift,
GFP_NOFS, 0);
if (err)
goto out;
}
vcn += flen;
if (flen >= len || opt == ALLOCATE_MFT ||
if (flen >= len || (opt & ALLOCATE_MFT) ||
(fr && run->count - cnt >= fr)) {
*alen = vcn - vcn0;
return 0;
@@ -287,7 +303,8 @@ int attr_make_nonresident(struct ntfs_inode *ni, struct ATTRIB *attr,
const char *data = resident_data(attr);
err = attr_allocate_clusters(sbi, run, 0, 0, len, NULL,
ALLOCATE_DEF, &alen, 0, NULL);
ALLOCATE_DEF, &alen, 0, NULL,
NULL);
if (err)
goto out1;
@@ -582,13 +599,13 @@ add_alloc_in_same_attr_seg:
/* ~3 bytes per fragment. */
err = attr_allocate_clusters(
sbi, run, vcn, lcn, to_allocate, &pre_alloc,
is_mft ? ALLOCATE_MFT : 0, &alen,
is_mft ? ALLOCATE_MFT : ALLOCATE_DEF, &alen,
is_mft ? 0
: (sbi->record_size -
le32_to_cpu(rec->used) + 8) /
3 +
1,
NULL);
NULL, NULL);
if (err)
goto out;
}
@@ -886,8 +903,19 @@ bad_inode:
return err;
}
/*
* attr_data_get_block - Returns 'lcn' and 'len' for given 'vcn'.
*
* @new == NULL means just to get current mapping for 'vcn'
* @new != NULL means allocate real cluster if 'vcn' maps to hole
* @zero - zeroout new allocated clusters
*
* NOTE:
* - @new != NULL is called only for sparsed or compressed attributes.
* - new allocated clusters are zeroed via blkdev_issue_zeroout.
*/
int attr_data_get_block(struct ntfs_inode *ni, CLST vcn, CLST clen, CLST *lcn,
CLST *len, bool *new)
CLST *len, bool *new, bool zero)
{
int err = 0;
struct runs_tree *run = &ni->file.run;
@@ -896,29 +924,27 @@ int attr_data_get_block(struct ntfs_inode *ni, CLST vcn, CLST clen, CLST *lcn,
struct ATTRIB *attr = NULL, *attr_b;
struct ATTR_LIST_ENTRY *le, *le_b;
struct mft_inode *mi, *mi_b;
CLST hint, svcn, to_alloc, evcn1, next_svcn, asize, end;
CLST hint, svcn, to_alloc, evcn1, next_svcn, asize, end, vcn0, alen;
unsigned int fr;
u64 total_size;
u32 clst_per_frame;
bool ok;
if (new)
*new = false;
/* Try to find in cache. */
down_read(&ni->file.run_lock);
ok = run_lookup_entry(run, vcn, lcn, len, NULL);
if (!run_lookup_entry(run, vcn, lcn, len, NULL))
*len = 0;
up_read(&ni->file.run_lock);
if (ok && (*lcn != SPARSE_LCN || !new)) {
/* Normal way. */
return 0;
if (*len) {
if (*lcn != SPARSE_LCN || !new)
return 0; /* Fast normal way without allocation. */
else if (clen > *len)
clen = *len;
}
if (!clen)
clen = 1;
if (ok && clen > *len)
clen = *len;
/* No cluster in cache or we need to allocate cluster in hole. */
sbi = ni->mi.sbi;
cluster_bits = sbi->cluster_bits;
@@ -944,12 +970,6 @@ int attr_data_get_block(struct ntfs_inode *ni, CLST vcn, CLST clen, CLST *lcn,
goto out;
}
clst_per_frame = 1u << attr_b->nres.c_unit;
to_alloc = (clen + clst_per_frame - 1) & ~(clst_per_frame - 1);
if (vcn + to_alloc > asize)
to_alloc = asize - vcn;
svcn = le64_to_cpu(attr_b->nres.svcn);
evcn1 = le64_to_cpu(attr_b->nres.evcn) + 1;
@@ -968,36 +988,68 @@ int attr_data_get_block(struct ntfs_inode *ni, CLST vcn, CLST clen, CLST *lcn,
evcn1 = le64_to_cpu(attr->nres.evcn) + 1;
}
/* Load in cache actual information. */
err = attr_load_runs(attr, ni, run, NULL);
if (err)
goto out;
if (!ok) {
ok = run_lookup_entry(run, vcn, lcn, len, NULL);
if (ok && (*lcn != SPARSE_LCN || !new)) {
/* Normal way. */
err = 0;
goto ok;
}
if (!*len) {
if (run_lookup_entry(run, vcn, lcn, len, NULL)) {
if (*lcn != SPARSE_LCN || !new)
goto ok; /* Slow normal way without allocation. */
if (!ok && !new) {
*len = 0;
err = 0;
if (clen > *len)
clen = *len;
} else if (!new) {
/* Here we may return -ENOENT.
* In any case caller gets zero length. */
goto ok;
}
if (ok && clen > *len) {
clen = *len;
to_alloc = (clen + clst_per_frame - 1) &
~(clst_per_frame - 1);
}
}
if (!is_attr_ext(attr_b)) {
/* The code below only for sparsed or compressed attributes. */
err = -EINVAL;
goto out;
}
vcn0 = vcn;
to_alloc = clen;
fr = (sbi->record_size - le32_to_cpu(mi->mrec->used) + 8) / 3 + 1;
/* Allocate frame aligned clusters.
* ntfs.sys usually uses 16 clusters per frame for sparsed or compressed.
* ntfs3 uses 1 cluster per frame for new created sparsed files. */
if (attr_b->nres.c_unit) {
CLST clst_per_frame = 1u << attr_b->nres.c_unit;
CLST cmask = ~(clst_per_frame - 1);
/* Get frame aligned vcn and to_alloc. */
vcn = vcn0 & cmask;
to_alloc = ((vcn0 + clen + clst_per_frame - 1) & cmask) - vcn;
if (fr < clst_per_frame)
fr = clst_per_frame;
zero = true;
/* Check if 'vcn' and 'vcn0' in different attribute segments. */
if (vcn < svcn || evcn1 <= vcn) {
/* Load attribute for truncated vcn. */
attr = ni_find_attr(ni, attr_b, &le, ATTR_DATA, NULL, 0,
&vcn, &mi);
if (!attr) {
err = -EINVAL;
goto out;
}
svcn = le64_to_cpu(attr->nres.svcn);
evcn1 = le64_to_cpu(attr->nres.evcn) + 1;
err = attr_load_runs(attr, ni, run, NULL);
if (err)
goto out;
}
}
if (vcn + to_alloc > asize)
to_alloc = asize - vcn;
/* Get the last LCN to allocate from. */
hint = 0;
@@ -1011,18 +1063,33 @@ int attr_data_get_block(struct ntfs_inode *ni, CLST vcn, CLST clen, CLST *lcn,
hint = -1;
}
err = attr_allocate_clusters(
sbi, run, vcn, hint + 1, to_alloc, NULL, 0, len,
(sbi->record_size - le32_to_cpu(mi->mrec->used) + 8) / 3 + 1,
lcn);
/* Allocate and zeroout new clusters. */
err = attr_allocate_clusters(sbi, run, vcn, hint + 1, to_alloc, NULL,
zero ? ALLOCATE_ZERO : ALLOCATE_DEF, &alen,
fr, lcn, len);
if (err)
goto out;
*new = true;
end = vcn + *len;
end = vcn + alen;
total_size = le64_to_cpu(attr_b->nres.total_size) +
((u64)*len << cluster_bits);
((u64)alen << cluster_bits);
if (vcn != vcn0) {
if (!run_lookup_entry(run, vcn0, lcn, len, NULL)) {
err = -EINVAL;
goto out;
}
if (*lcn == SPARSE_LCN) {
/* Internal error. Should not happened. */
WARN_ON(1);
err = -EINVAL;
goto out;
}
/* Check case when vcn0 + len overlaps new allocated clusters. */
if (vcn0 + *len > end)
*len = end - vcn0;
}
repack:
err = mi_pack_runs(mi, attr, run, max(end, evcn1) - svcn);
@@ -1547,7 +1614,7 @@ int attr_allocate_frame(struct ntfs_inode *ni, CLST frame, size_t compr_size,
struct ATTRIB *attr = NULL, *attr_b;
struct ATTR_LIST_ENTRY *le, *le_b;
struct mft_inode *mi, *mi_b;
CLST svcn, evcn1, next_svcn, lcn, len;
CLST svcn, evcn1, next_svcn, len;
CLST vcn, end, clst_data;
u64 total_size, valid_size, data_size;
@@ -1623,8 +1690,9 @@ int attr_allocate_frame(struct ntfs_inode *ni, CLST frame, size_t compr_size,
}
err = attr_allocate_clusters(sbi, run, vcn + clst_data,
hint + 1, len - clst_data, NULL, 0,
&alen, 0, &lcn);
hint + 1, len - clst_data, NULL,
ALLOCATE_DEF, &alen, 0, NULL,
NULL);
if (err)
goto out;

View File

@@ -122,8 +122,8 @@ static int ntfs_extend_initialized_size(struct file *file,
bits = sbi->cluster_bits;
vcn = pos >> bits;
err = attr_data_get_block(ni, vcn, 0, &lcn, &clen,
NULL);
err = attr_data_get_block(ni, vcn, 1, &lcn, &clen, NULL,
false);
if (err)
goto out;
@@ -196,18 +196,18 @@ static int ntfs_zero_range(struct inode *inode, u64 vbo, u64 vbo_to)
struct address_space *mapping = inode->i_mapping;
u32 blocksize = 1 << inode->i_blkbits;
pgoff_t idx = vbo >> PAGE_SHIFT;
u32 z_start = vbo & (PAGE_SIZE - 1);
u32 from = vbo & (PAGE_SIZE - 1);
pgoff_t idx_end = (vbo_to + PAGE_SIZE - 1) >> PAGE_SHIFT;
loff_t page_off;
struct buffer_head *head, *bh;
u32 bh_next, bh_off, z_end;
u32 bh_next, bh_off, to;
sector_t iblock;
struct page *page;
for (; idx < idx_end; idx += 1, z_start = 0) {
for (; idx < idx_end; idx += 1, from = 0) {
page_off = (loff_t)idx << PAGE_SHIFT;
z_end = (page_off + PAGE_SIZE) > vbo_to ? (vbo_to - page_off)
: PAGE_SIZE;
to = (page_off + PAGE_SIZE) > vbo_to ? (vbo_to - page_off)
: PAGE_SIZE;
iblock = page_off >> inode->i_blkbits;
page = find_or_create_page(mapping, idx,
@@ -224,7 +224,7 @@ static int ntfs_zero_range(struct inode *inode, u64 vbo, u64 vbo_to)
do {
bh_next = bh_off + blocksize;
if (bh_next <= z_start || bh_off >= z_end)
if (bh_next <= from || bh_off >= to)
continue;
if (!buffer_mapped(bh)) {
@@ -258,7 +258,7 @@ static int ntfs_zero_range(struct inode *inode, u64 vbo, u64 vbo_to)
} while (bh_off = bh_next, iblock += 1,
head != (bh = bh->b_this_page));
zero_user_segment(page, z_start, z_end);
zero_user_segment(page, from, to);
unlock_page(page);
put_page(page);
@@ -269,81 +269,6 @@ out:
return err;
}
/*
* ntfs_sparse_cluster - Helper function to zero a new allocated clusters.
*
* NOTE: 512 <= cluster size <= 2M
*/
void ntfs_sparse_cluster(struct inode *inode, struct page *page0, CLST vcn,
CLST len)
{
struct address_space *mapping = inode->i_mapping;
struct ntfs_sb_info *sbi = inode->i_sb->s_fs_info;
u64 vbo = (u64)vcn << sbi->cluster_bits;
u64 bytes = (u64)len << sbi->cluster_bits;
u32 blocksize = 1 << inode->i_blkbits;
pgoff_t idx0 = page0 ? page0->index : -1;
loff_t vbo_clst = vbo & sbi->cluster_mask_inv;
loff_t end = ntfs_up_cluster(sbi, vbo + bytes);
pgoff_t idx = vbo_clst >> PAGE_SHIFT;
u32 from = vbo_clst & (PAGE_SIZE - 1);
pgoff_t idx_end = (end + PAGE_SIZE - 1) >> PAGE_SHIFT;
loff_t page_off;
u32 to;
bool partial;
struct page *page;
for (; idx < idx_end; idx += 1, from = 0) {
page = idx == idx0 ? page0 : grab_cache_page(mapping, idx);
if (!page)
continue;
page_off = (loff_t)idx << PAGE_SHIFT;
to = (page_off + PAGE_SIZE) > end ? (end - page_off)
: PAGE_SIZE;
partial = false;
if ((from || PAGE_SIZE != to) &&
likely(!page_has_buffers(page))) {
create_empty_buffers(page, blocksize, 0);
}
if (page_has_buffers(page)) {
struct buffer_head *head, *bh;
u32 bh_off = 0;
bh = head = page_buffers(page);
do {
u32 bh_next = bh_off + blocksize;
if (from <= bh_off && bh_next <= to) {
set_buffer_uptodate(bh);
mark_buffer_dirty(bh);
} else if (!buffer_uptodate(bh)) {
partial = true;
}
bh_off = bh_next;
} while (head != (bh = bh->b_this_page));
}
zero_user_segment(page, from, to);
if (!partial) {
if (!PageUptodate(page))
SetPageUptodate(page);
set_page_dirty(page);
}
if (idx != idx0) {
unlock_page(page);
put_page(page);
}
cond_resched();
}
mark_inode_dirty(inode);
}
/*
* ntfs_file_mmap - file_operations::mmap
*/
@@ -385,13 +310,9 @@ static int ntfs_file_mmap(struct file *file, struct vm_area_struct *vma)
for (; vcn < end; vcn += len) {
err = attr_data_get_block(ni, vcn, 1, &lcn,
&len, &new);
&len, &new, true);
if (err)
goto out;
if (!new)
continue;
ntfs_sparse_cluster(inode, NULL, vcn, 1);
}
}
@@ -532,7 +453,8 @@ static long ntfs_fallocate(struct file *file, int mode, loff_t vbo, loff_t len)
struct ntfs_sb_info *sbi = sb->s_fs_info;
struct ntfs_inode *ni = ntfs_i(inode);
loff_t end = vbo + len;
loff_t vbo_down = round_down(vbo, PAGE_SIZE);
loff_t vbo_down = round_down(vbo, max_t(unsigned long,
sbi->cluster_size, PAGE_SIZE));
bool is_supported_holes = is_sparsed(ni) || is_compressed(ni);
loff_t i_size, new_size;
bool map_locked;
@@ -585,11 +507,8 @@ static long ntfs_fallocate(struct file *file, int mode, loff_t vbo, loff_t len)
u32 frame_size;
loff_t mask, vbo_a, end_a, tmp;
err = filemap_write_and_wait_range(mapping, vbo, end - 1);
if (err)
goto out;
err = filemap_write_and_wait_range(mapping, end, LLONG_MAX);
err = filemap_write_and_wait_range(mapping, vbo_down,
LLONG_MAX);
if (err)
goto out;
@@ -692,39 +611,35 @@ static long ntfs_fallocate(struct file *file, int mode, loff_t vbo, loff_t len)
goto out;
if (is_supported_holes) {
CLST vcn_v = ni->i_valid >> sbi->cluster_bits;
CLST vcn = vbo >> sbi->cluster_bits;
CLST cend = bytes_to_cluster(sbi, end);
CLST cend_v = bytes_to_cluster(sbi, ni->i_valid);
CLST lcn, clen;
bool new;
if (cend_v > cend)
cend_v = cend;
/*
* Allocate but do not zero new clusters. (see below comments)
* This breaks security: One can read unused on-disk areas.
* Allocate and zero new clusters.
* Zeroing these clusters may be too long.
* Maybe we should check here for root rights?
*/
for (; vcn < cend_v; vcn += clen) {
err = attr_data_get_block(ni, vcn, cend_v - vcn,
&lcn, &clen, &new,
true);
if (err)
goto out;
}
/*
* Allocate but not zero new clusters.
*/
for (; vcn < cend; vcn += clen) {
err = attr_data_get_block(ni, vcn, cend - vcn,
&lcn, &clen, &new);
&lcn, &clen, &new,
false);
if (err)
goto out;
if (!new || vcn >= vcn_v)
continue;
/*
* Unwritten area.
* NTFS is not able to store several unwritten areas.
* Activate 'ntfs_sparse_cluster' to zero new allocated clusters.
*
* Dangerous in case:
* 1G of sparsed clusters + 1 cluster of data =>
* valid_size == 1G + 1 cluster
* fallocate(1G) will zero 1G and this can be very long
* xfstest 016/086 will fail without 'ntfs_sparse_cluster'.
*/
ntfs_sparse_cluster(inode, NULL, vcn,
min(vcn_v - vcn, clen));
}
}
@@ -945,8 +860,8 @@ static ssize_t ntfs_compress_write(struct kiocb *iocb, struct iov_iter *from)
frame_vbo = valid & ~(frame_size - 1);
off = valid & (frame_size - 1);
err = attr_data_get_block(ni, frame << NTFS_LZNT_CUNIT, 0, &lcn,
&clen, NULL);
err = attr_data_get_block(ni, frame << NTFS_LZNT_CUNIT, 1, &lcn,
&clen, NULL, false);
if (err)
goto out;

View File

@@ -2297,7 +2297,7 @@ int ni_decompress_file(struct ntfs_inode *ni)
for (vcn = vbo >> sbi->cluster_bits; vcn < end; vcn += clen) {
err = attr_data_get_block(ni, vcn, cend - vcn, &lcn,
&clen, &new);
&clen, &new, false);
if (err)
goto out;
}

View File

@@ -1442,8 +1442,8 @@ static int indx_create_allocate(struct ntfs_index *indx, struct ntfs_inode *ni,
run_init(&run);
err = attr_allocate_clusters(sbi, &run, 0, 0, len, NULL, 0, &alen, 0,
NULL);
err = attr_allocate_clusters(sbi, &run, 0, 0, len, NULL, ALLOCATE_DEF,
&alen, 0, NULL, NULL);
if (err)
goto out;

View File

@@ -592,7 +592,8 @@ static noinline int ntfs_get_block_vbo(struct inode *inode, u64 vbo,
off = vbo & sbi->cluster_mask;
new = false;
err = attr_data_get_block(ni, vcn, 1, &lcn, &len, create ? &new : NULL);
err = attr_data_get_block(ni, vcn, 1, &lcn, &len, create ? &new : NULL,
create && sbi->cluster_size > PAGE_SIZE);
if (err)
goto out;
@@ -610,11 +611,8 @@ static noinline int ntfs_get_block_vbo(struct inode *inode, u64 vbo,
WARN_ON(1);
}
if (new) {
if (new)
set_buffer_new(bh);
if ((len << cluster_bits) > block_size)
ntfs_sparse_cluster(inode, page, vcn, len);
}
lbo = ((u64)lcn << cluster_bits) + off;
@@ -1533,8 +1531,8 @@ struct inode *ntfs_create_inode(struct user_namespace *mnt_userns,
cpu_to_le64(ntfs_up_cluster(sbi, nsize));
err = attr_allocate_clusters(sbi, &ni->file.run, 0, 0,
clst, NULL, 0, &alen, 0,
NULL);
clst, NULL, ALLOCATE_DEF,
&alen, 0, NULL, NULL);
if (err)
goto out5;

View File

@@ -129,6 +129,7 @@ struct ntfs_buffers {
enum ALLOCATE_OPT {
ALLOCATE_DEF = 0, // Allocate all clusters.
ALLOCATE_MFT = 1, // Allocate for MFT.
ALLOCATE_ZERO = 2, // Zeroout new allocated clusters
};
enum bitmap_mutex_classes {
@@ -419,7 +420,7 @@ enum REPARSE_SIGN {
int attr_allocate_clusters(struct ntfs_sb_info *sbi, struct runs_tree *run,
CLST vcn, CLST lcn, CLST len, CLST *pre_alloc,
enum ALLOCATE_OPT opt, CLST *alen, const size_t fr,
CLST *new_lcn);
CLST *new_lcn, CLST *new_len);
int attr_make_nonresident(struct ntfs_inode *ni, struct ATTRIB *attr,
struct ATTR_LIST_ENTRY *le, struct mft_inode *mi,
u64 new_size, struct runs_tree *run,
@@ -429,7 +430,7 @@ int attr_set_size(struct ntfs_inode *ni, enum ATTR_TYPE type,
u64 new_size, const u64 *new_valid, bool keep_prealloc,
struct ATTRIB **ret);
int attr_data_get_block(struct ntfs_inode *ni, CLST vcn, CLST clen, CLST *lcn,
CLST *len, bool *new);
CLST *len, bool *new, bool zero);
int attr_data_read_resident(struct ntfs_inode *ni, struct page *page);
int attr_data_write_resident(struct ntfs_inode *ni, struct page *page);
int attr_load_runs_vcn(struct ntfs_inode *ni, enum ATTR_TYPE type,
@@ -494,8 +495,6 @@ extern const struct file_operations ntfs_dir_operations;
/* Globals from file.c */
int ntfs_getattr(struct user_namespace *mnt_userns, const struct path *path,
struct kstat *stat, u32 request_mask, u32 flags);
void ntfs_sparse_cluster(struct inode *inode, struct page *page0, CLST vcn,
CLST len);
int ntfs3_setattr(struct user_namespace *mnt_userns, struct dentry *dentry,
struct iattr *attr);
int ntfs_file_open(struct inode *inode, struct file *file);

View File

@@ -558,10 +558,16 @@ struct proc_dir_entry *proc_create_reg(const char *name, umode_t mode,
return p;
}
static inline void pde_set_flags(struct proc_dir_entry *pde)
static void pde_set_flags(struct proc_dir_entry *pde)
{
if (pde->proc_ops->proc_flags & PROC_ENTRY_PERMANENT)
pde->flags |= PROC_ENTRY_PERMANENT;
if (pde->proc_ops->proc_read_iter)
pde->flags |= PROC_ENTRY_proc_read_iter;
#ifdef CONFIG_COMPAT
if (pde->proc_ops->proc_compat_ioctl)
pde->flags |= PROC_ENTRY_proc_compat_ioctl;
#endif
}
struct proc_dir_entry *proc_create_data(const char *name, umode_t mode,
@@ -625,6 +631,7 @@ struct proc_dir_entry *proc_create_seq_private(const char *name, umode_t mode,
p->proc_ops = &proc_seq_ops;
p->seq_ops = ops;
p->state_size = state_size;
pde_set_flags(p);
return proc_register(parent, p);
}
EXPORT_SYMBOL(proc_create_seq_private);
@@ -655,6 +662,7 @@ struct proc_dir_entry *proc_create_single_data(const char *name, umode_t mode,
return NULL;
p->proc_ops = &proc_single_ops;
p->single_show = show;
pde_set_flags(p);
return proc_register(parent, p);
}
EXPORT_SYMBOL(proc_create_single_data);

View File

@@ -679,13 +679,13 @@ struct inode *proc_get_inode(struct super_block *sb, struct proc_dir_entry *de)
if (S_ISREG(inode->i_mode)) {
inode->i_op = de->proc_iops;
if (de->proc_ops->proc_read_iter)
if (pde_has_proc_read_iter(de))
inode->i_fop = &proc_iter_file_ops;
else
inode->i_fop = &proc_reg_file_ops;
#ifdef CONFIG_COMPAT
if (de->proc_ops->proc_compat_ioctl) {
if (de->proc_ops->proc_read_iter)
if (pde_has_proc_compat_ioctl(de)) {
if (pde_has_proc_read_iter(de))
inode->i_fop = &proc_iter_file_ops_compat;
else
inode->i_fop = &proc_reg_file_ops_compat;

View File

@@ -84,6 +84,20 @@ static inline void pde_make_permanent(struct proc_dir_entry *pde)
pde->flags |= PROC_ENTRY_PERMANENT;
}
static inline bool pde_has_proc_read_iter(const struct proc_dir_entry *pde)
{
return pde->flags & PROC_ENTRY_proc_read_iter;
}
static inline bool pde_has_proc_compat_ioctl(const struct proc_dir_entry *pde)
{
#ifdef CONFIG_COMPAT
return pde->flags & PROC_ENTRY_proc_compat_ioctl;
#else
return false;
#endif
}
extern struct kmem_cache *proc_dir_entry_cache;
void pde_free(struct proc_dir_entry *pde);

View File

@@ -52,6 +52,8 @@ int cifs_neg_token_init_mech_type(void *context, size_t hdrlen,
server->sec_kerberos = true;
else if (oid == OID_ntlmssp)
server->sec_ntlmssp = true;
else if (oid == OID_IAKerb)
server->sec_iakerb = true;
else {
char buf[50];

View File

@@ -130,11 +130,13 @@ cifs_get_spnego_key(struct cifs_ses *sesInfo,
dp = description + strlen(description);
/* for now, only sec=krb5 and sec=mskrb5 are valid */
/* for now, only sec=krb5 and sec=mskrb5 and iakerb are valid */
if (server->sec_kerberos)
sprintf(dp, ";sec=krb5");
else if (server->sec_mskerberos)
sprintf(dp, ";sec=mskrb5");
else if (server->sec_iakerb)
sprintf(dp, ";sec=iakerb");
else {
cifs_dbg(VFS, "unknown or missing server auth type, use krb5\n");
sprintf(dp, ";sec=krb5");

View File

@@ -148,6 +148,7 @@ enum securityEnum {
NTLMv2, /* Legacy NTLM auth with NTLMv2 hash */
RawNTLMSSP, /* NTLMSSP without SPNEGO, NTLMv2 hash */
Kerberos, /* Kerberos via SPNEGO */
IAKerb, /* Kerberos proxy */
};
struct session_key {
@@ -685,6 +686,7 @@ struct TCP_Server_Info {
bool sec_kerberosu2u; /* supports U2U Kerberos */
bool sec_kerberos; /* supports plain Kerberos */
bool sec_mskerberos; /* supports legacy MS Kerberos */
bool sec_iakerb; /* supports pass-through auth for Kerberos (krb5 proxy) */
bool large_buf; /* is current buffer large? */
/* use SMBD connection instead of socket */
bool rdma;
@@ -2049,6 +2051,8 @@ static inline char *get_security_type_str(enum securityEnum sectype)
return "Kerberos";
case NTLMv2:
return "NTLMv2";
case IAKerb:
return "IAKerb";
default:
return "Unknown";
}

View File

@@ -1881,9 +1881,8 @@ out_err:
/* this function must be called with ses_lock and chan_lock held */
static int match_session(struct cifs_ses *ses, struct smb3_fs_context *ctx)
{
if (ctx->sectype != Unspecified &&
ctx->sectype != ses->sectype)
return 0;
struct TCP_Server_Info *server = ses->server;
enum securityEnum ctx_sec, ses_sec;
/*
* If an existing session is limited to less channels than
@@ -1892,11 +1891,20 @@ static int match_session(struct cifs_ses *ses, struct smb3_fs_context *ctx)
if (ses->chan_max < ctx->max_channels)
return 0;
switch (ses->sectype) {
ctx_sec = server->ops->select_sectype(server, ctx->sectype);
ses_sec = server->ops->select_sectype(server, ses->sectype);
if (ctx_sec != ses_sec)
return 0;
switch (ctx_sec) {
case IAKerb:
case Kerberos:
if (!uid_eq(ctx->cred_uid, ses->cred_uid))
return 0;
break;
case NTLMv2:
case RawNTLMSSP:
default:
/* NULL username means anonymous session */
if (ses->user_name == NULL) {

View File

@@ -1078,21 +1078,21 @@ static int smb3_fs_context_parse_param(struct fs_context *fc,
ctx->got_wsize = true;
break;
case Opt_acregmax:
ctx->acregmax = HZ * result.uint_32;
if (ctx->acregmax > CIFS_MAX_ACTIMEO) {
if (result.uint_32 > CIFS_MAX_ACTIMEO / HZ) {
cifs_errorf(fc, "acregmax too large\n");
goto cifs_parse_mount_err;
}
ctx->acregmax = HZ * result.uint_32;
break;
case Opt_acdirmax:
ctx->acdirmax = HZ * result.uint_32;
if (ctx->acdirmax > CIFS_MAX_ACTIMEO) {
if (result.uint_32 > CIFS_MAX_ACTIMEO / HZ) {
cifs_errorf(fc, "acdirmax too large\n");
goto cifs_parse_mount_err;
}
ctx->acdirmax = HZ * result.uint_32;
break;
case Opt_actimeo:
if (HZ * result.uint_32 > CIFS_MAX_ACTIMEO) {
if (result.uint_32 > CIFS_MAX_ACTIMEO / HZ) {
cifs_errorf(fc, "timeout too large\n");
goto cifs_parse_mount_err;
}
@@ -1104,11 +1104,11 @@ static int smb3_fs_context_parse_param(struct fs_context *fc,
ctx->acdirmax = ctx->acregmax = HZ * result.uint_32;
break;
case Opt_closetimeo:
ctx->closetimeo = HZ * result.uint_32;
if (ctx->closetimeo > SMB3_MAX_DCLOSETIMEO) {
if (result.uint_32 > SMB3_MAX_DCLOSETIMEO / HZ) {
cifs_errorf(fc, "closetimeo too large\n");
goto cifs_parse_mount_err;
}
ctx->closetimeo = HZ * result.uint_32;
break;
case Opt_echo_interval:
ctx->echo_interval = result.uint_32;

View File

@@ -246,7 +246,9 @@ static int cifs_dump_full_key(struct cifs_tcon *tcon, struct smb3_full_key_debug
spin_lock(&cifs_tcp_ses_lock);
list_for_each_entry(server_it, &cifs_tcp_ses_list, tcp_ses_list) {
list_for_each_entry(ses_it, &server_it->smb_ses_list, smb_ses_list) {
if (ses_it->Suid == out.session_id) {
spin_lock(&ses_it->ses_lock);
if (ses_it->ses_status != SES_EXITING &&
ses_it->Suid == out.session_id) {
ses = ses_it;
/*
* since we are using the session outside the crit
@@ -254,9 +256,11 @@ static int cifs_dump_full_key(struct cifs_tcon *tcon, struct smb3_full_key_debug
* so increment its refcount
*/
ses->ses_count++;
spin_unlock(&ses_it->ses_lock);
found = true;
goto search_end;
}
spin_unlock(&ses_it->ses_lock);
}
}
search_end:

View File

@@ -1209,12 +1209,13 @@ cifs_select_sectype(struct TCP_Server_Info *server, enum securityEnum requested)
switch (requested) {
case Kerberos:
case RawNTLMSSP:
case IAKerb:
return requested;
case Unspecified:
if (server->sec_ntlmssp &&
(global_secflags & CIFSSEC_MAY_NTLMSSP))
return RawNTLMSSP;
if ((server->sec_kerberos || server->sec_mskerberos) &&
if ((server->sec_kerberos || server->sec_mskerberos || server->sec_iakerb) &&
(global_secflags & CIFSSEC_MAY_KRB5))
return Kerberos;
fallthrough;

View File

@@ -1270,7 +1270,7 @@ smb2_select_sectype(struct TCP_Server_Info *server, enum securityEnum requested)
if (server->sec_ntlmssp &&
(global_secflags & CIFSSEC_MAY_NTLMSSP))
return RawNTLMSSP;
if ((server->sec_kerberos || server->sec_mskerberos) &&
if ((server->sec_kerberos || server->sec_mskerberos || server->sec_iakerb) &&
(global_secflags & CIFSSEC_MAY_KRB5))
return Kerberos;
fallthrough;

View File

@@ -398,7 +398,9 @@ static void parse_dacl(struct user_namespace *user_ns,
if (num_aces <= 0)
return;
if (num_aces > ULONG_MAX / sizeof(struct smb_ace *))
if (num_aces > (le16_to_cpu(pdacl->size) - sizeof(struct smb_acl)) /
(offsetof(struct smb_ace, sid) +
offsetof(struct smb_sid, sub_auth) + sizeof(__le16)))
return;
ret = init_acl_state(&acl_state, num_aces);
@@ -432,6 +434,7 @@ static void parse_dacl(struct user_namespace *user_ns,
offsetof(struct smb_sid, sub_auth);
if (end_of_acl - acl_base < acl_size ||
ppace[i]->sid.num_subauth == 0 ||
ppace[i]->sid.num_subauth > SID_MAX_SUB_AUTHORITIES ||
(end_of_acl - acl_base <
acl_size + sizeof(__le32) * ppace[i]->sid.num_subauth) ||

View File

@@ -2511,6 +2511,7 @@ xfs_defer_agfl_block(
trace_xfs_agfl_free_defer(mp, agno, 0, agbno, 1);
xfs_extent_free_get_group(mp, xefi);
xfs_defer_add(tp, XFS_DEFER_OPS_TYPE_AGFL_FREE, &xefi->xefi_list);
return 0;
}
@@ -2529,8 +2530,8 @@ __xfs_free_extent_later(
bool skip_discard)
{
struct xfs_extent_free_item *xefi;
#ifdef DEBUG
struct xfs_mount *mp = tp->t_mountp;
#ifdef DEBUG
xfs_agnumber_t agno;
xfs_agblock_t agbno;
@@ -2569,9 +2570,11 @@ __xfs_free_extent_later(
} else {
xefi->xefi_owner = XFS_RMAP_OWN_NULL;
}
trace_xfs_bmap_free_defer(tp->t_mountp,
trace_xfs_bmap_free_defer(mp,
XFS_FSB_TO_AGNO(tp->t_mountp, bno), 0,
XFS_FSB_TO_AGBNO(tp->t_mountp, bno), len);
xfs_extent_free_get_group(mp, xefi);
xfs_defer_add(tp, XFS_DEFER_OPS_TYPE_FREE, &xefi->xefi_list);
return 0;
}

View File

@@ -226,10 +226,14 @@ struct xfs_extent_free_item {
uint64_t xefi_owner;
xfs_fsblock_t xefi_startblock;/* starting fs block number */
xfs_extlen_t xefi_blockcount;/* number of blocks in extent */
struct xfs_perag *xefi_pag;
unsigned int xefi_flags;
enum xfs_ag_resv_type xefi_agresv;
};
void xfs_extent_free_get_group(struct xfs_mount *mp,
struct xfs_extent_free_item *xefi);
#define XFS_EFI_SKIP_DISCARD (1U << 0) /* don't issue discard */
#define XFS_EFI_ATTR_FORK (1U << 1) /* freeing attr fork block */
#define XFS_EFI_BMBT_BLOCK (1U << 2) /* freeing bmap btree block */

View File

@@ -350,10 +350,7 @@ xfs_trans_free_extent(
struct xfs_owner_info oinfo = { };
struct xfs_mount *mp = tp->t_mountp;
struct xfs_extent *extp;
struct xfs_perag *pag;
uint next_extent;
xfs_agnumber_t agno = XFS_FSB_TO_AGNO(mp,
xefi->xefi_startblock);
xfs_agblock_t agbno = XFS_FSB_TO_AGBNO(mp,
xefi->xefi_startblock);
int error;
@@ -364,14 +361,12 @@ xfs_trans_free_extent(
if (xefi->xefi_flags & XFS_EFI_BMBT_BLOCK)
oinfo.oi_flags |= XFS_OWNER_INFO_BMBT_BLOCK;
trace_xfs_bmap_free_deferred(tp->t_mountp, agno, 0, agbno,
xefi->xefi_blockcount);
trace_xfs_bmap_free_deferred(tp->t_mountp, xefi->xefi_pag->pag_agno, 0,
agbno, xefi->xefi_blockcount);
pag = xfs_perag_get(mp, agno);
error = __xfs_free_extent(tp, pag, agbno, xefi->xefi_blockcount,
&oinfo, xefi->xefi_agresv,
error = __xfs_free_extent(tp, xefi->xefi_pag, agbno,
xefi->xefi_blockcount, &oinfo, xefi->xefi_agresv,
xefi->xefi_flags & XFS_EFI_SKIP_DISCARD);
xfs_perag_put(pag);
/*
* Mark the transaction dirty, even on error. This ensures the
@@ -400,14 +395,13 @@ xfs_extent_free_diff_items(
const struct list_head *a,
const struct list_head *b)
{
struct xfs_mount *mp = priv;
struct xfs_extent_free_item *ra;
struct xfs_extent_free_item *rb;
ra = container_of(a, struct xfs_extent_free_item, xefi_list);
rb = container_of(b, struct xfs_extent_free_item, xefi_list);
return XFS_FSB_TO_AGNO(mp, ra->xefi_startblock) -
XFS_FSB_TO_AGNO(mp, rb->xefi_startblock);
return ra->xefi_pag->pag_agno - rb->xefi_pag->pag_agno;
}
/* Log a free extent to the intent item. */
@@ -466,6 +460,26 @@ xfs_extent_free_create_done(
return &xfs_trans_get_efd(tp, EFI_ITEM(intent), count)->efd_item;
}
/* Take a passive ref to the AG containing the space we're freeing. */
void
xfs_extent_free_get_group(
struct xfs_mount *mp,
struct xfs_extent_free_item *xefi)
{
xfs_agnumber_t agno;
agno = XFS_FSB_TO_AGNO(mp, xefi->xefi_startblock);
xefi->xefi_pag = xfs_perag_get(mp, agno);
}
/* Release a passive AG ref after some freeing work. */
static inline void
xfs_extent_free_put_group(
struct xfs_extent_free_item *xefi)
{
xfs_perag_put(xefi->xefi_pag);
}
/* Process a free extent. */
STATIC int
xfs_extent_free_finish_item(
@@ -480,6 +494,8 @@ xfs_extent_free_finish_item(
xefi = container_of(item, struct xfs_extent_free_item, xefi_list);
error = xfs_trans_free_extent(tp, EFD_ITEM(done), xefi);
xfs_extent_free_put_group(xefi);
kmem_cache_free(xfs_extfree_item_cache, xefi);
return error;
}
@@ -500,6 +516,8 @@ xfs_extent_free_cancel_item(
struct xfs_extent_free_item *xefi;
xefi = container_of(item, struct xfs_extent_free_item, xefi_list);
xfs_extent_free_put_group(xefi);
kmem_cache_free(xfs_extfree_item_cache, xefi);
}
@@ -530,24 +548,21 @@ xfs_agfl_free_finish_item(
struct xfs_extent *extp;
struct xfs_buf *agbp;
int error;
xfs_agnumber_t agno;
xfs_agblock_t agbno;
uint next_extent;
struct xfs_perag *pag;
xefi = container_of(item, struct xfs_extent_free_item, xefi_list);
ASSERT(xefi->xefi_blockcount == 1);
agno = XFS_FSB_TO_AGNO(mp, xefi->xefi_startblock);
agbno = XFS_FSB_TO_AGBNO(mp, xefi->xefi_startblock);
oinfo.oi_owner = xefi->xefi_owner;
trace_xfs_agfl_free_deferred(mp, agno, 0, agbno, xefi->xefi_blockcount);
trace_xfs_agfl_free_deferred(mp, xefi->xefi_pag->pag_agno, 0, agbno,
xefi->xefi_blockcount);
pag = xfs_perag_get(mp, agno);
error = xfs_alloc_read_agf(pag, tp, 0, &agbp);
error = xfs_alloc_read_agf(xefi->xefi_pag, tp, 0, &agbp);
if (!error)
error = xfs_free_agfl_block(tp, agno, agbno, agbp, &oinfo);
xfs_perag_put(pag);
error = xfs_free_agfl_block(tp, xefi->xefi_pag->pag_agno,
agbno, agbp, &oinfo);
/*
* Mark the transaction dirty, even on error. This ensures the
@@ -566,6 +581,7 @@ xfs_agfl_free_finish_item(
extp->ext_len = xefi->xefi_blockcount;
efdp->efd_next_extent++;
xfs_extent_free_put_group(xefi);
kmem_cache_free(xfs_extfree_item_cache, xefi);
return error;
}
@@ -639,7 +655,9 @@ xfs_efi_item_recover(
fake.xefi_startblock = extp->ext_start;
fake.xefi_blockcount = extp->ext_len;
xfs_extent_free_get_group(mp, &fake);
error = xfs_trans_free_extent(tp, efdp, &fake);
xfs_extent_free_put_group(&fake);
if (error == -EFSCORRUPTED)
XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_LOW, mp,
extp, sizeof(*extp));

View File

@@ -20,10 +20,13 @@ enum {
* If in doubt, ignore this flag.
*/
#ifdef MODULE
PROC_ENTRY_PERMANENT = 0U,
PROC_ENTRY_PERMANENT = 0U,
#else
PROC_ENTRY_PERMANENT = 1U << 0,
PROC_ENTRY_PERMANENT = 1U << 0,
#endif
PROC_ENTRY_proc_read_iter = 1U << 1,
PROC_ENTRY_proc_compat_ioctl = 1U << 2,
};
struct proc_ops {

View File

@@ -425,19 +425,17 @@ int folio_migrate_mapping(struct address_space *mapping,
newfolio->index = folio->index;
newfolio->mapping = folio->mapping;
folio_ref_add(newfolio, nr); /* add cache reference */
if (folio_test_swapbacked(folio)) {
if (folio_test_swapbacked(folio))
__folio_set_swapbacked(newfolio);
if (folio_test_swapcache(folio)) {
int i;
if (folio_test_swapcache(folio)) {
int i;
folio_set_swapcache(newfolio);
for (i = 0; i < nr; i++)
set_page_private(folio_page(newfolio, i),
page_private(folio_page(folio, i)));
}
folio_set_swapcache(newfolio);
for (i = 0; i < nr; i++)
set_page_private(folio_page(newfolio, i),
page_private(folio_page(folio, i)));
entries = nr;
} else {
VM_BUG_ON_FOLIO(folio_test_swapcache(folio), folio);
entries = 1;
}

View File

@@ -181,6 +181,7 @@ static void
lec_send(struct atm_vcc *vcc, struct sk_buff *skb)
{
struct net_device *dev = skb->dev;
unsigned int len = skb->len;
ATM_SKB(skb)->vcc = vcc;
atm_account_tx(vcc, skb);
@@ -191,7 +192,7 @@ lec_send(struct atm_vcc *vcc, struct sk_buff *skb)
}
dev->stats.tx_packets++;
dev->stats.tx_bytes += skb->len;
dev->stats.tx_bytes += len;
}
static void lec_tx_timeout(struct net_device *dev, unsigned int txqueue)

View File

@@ -325,8 +325,7 @@ batadv_iv_ogm_aggr_packet(int buff_pos, int packet_len,
/* check if there is enough space for the optional TVLV */
next_buff_pos += ntohs(ogm_packet->tvlv_len);
return (next_buff_pos <= packet_len) &&
(next_buff_pos <= BATADV_MAX_AGGREGATION_BYTES);
return next_buff_pos <= packet_len;
}
/* send a batman ogm to a given interface */

View File

@@ -840,8 +840,7 @@ batadv_v_ogm_aggr_packet(int buff_pos, int packet_len,
/* check if there is enough space for the optional TVLV */
next_buff_pos += ntohs(ogm2_packet->tvlv_len);
return (next_buff_pos <= packet_len) &&
(next_buff_pos <= BATADV_MAX_AGGREGATION_BYTES);
return next_buff_pos <= packet_len;
}
/**

View File

@@ -825,11 +825,16 @@ static struct sk_buff *chan_alloc_skb_cb(struct l2cap_chan *chan,
unsigned long hdr_len,
unsigned long len, int nb)
{
struct sk_buff *skb;
/* Note that we must allocate using GFP_ATOMIC here as
* this function is called originally from netdev hard xmit
* function in atomic context.
*/
return bt_skb_alloc(hdr_len + len, GFP_ATOMIC);
skb = bt_skb_alloc(hdr_len + len, GFP_ATOMIC);
if (!skb)
return ERR_PTR(-ENOMEM);
return skb;
}
static void chan_suspend_cb(struct l2cap_chan *chan)

View File

@@ -23,6 +23,8 @@
#include <net/ip6_fib.h>
#include <net/rtnh.h>
#include "dev.h"
DEFINE_STATIC_KEY_FALSE(nf_hooks_lwtunnel_enabled);
EXPORT_SYMBOL_GPL(nf_hooks_lwtunnel_enabled);
@@ -325,13 +327,23 @@ EXPORT_SYMBOL_GPL(lwtunnel_cmp_encap);
int lwtunnel_output(struct net *net, struct sock *sk, struct sk_buff *skb)
{
struct dst_entry *dst = skb_dst(skb);
const struct lwtunnel_encap_ops *ops;
struct lwtunnel_state *lwtstate;
int ret = -EINVAL;
struct dst_entry *dst;
int ret;
if (!dst)
if (dev_xmit_recursion()) {
net_crit_ratelimited("%s(): recursion limit reached on datapath\n",
__func__);
ret = -ENETDOWN;
goto drop;
}
dst = skb_dst(skb);
if (!dst) {
ret = -EINVAL;
goto drop;
}
lwtstate = dst->lwtstate;
if (lwtstate->type == LWTUNNEL_ENCAP_NONE ||
@@ -341,8 +353,11 @@ int lwtunnel_output(struct net *net, struct sock *sk, struct sk_buff *skb)
ret = -EOPNOTSUPP;
rcu_read_lock();
ops = rcu_dereference(lwtun_encaps[lwtstate->type]);
if (likely(ops && ops->output))
if (likely(ops && ops->output)) {
dev_xmit_recursion_inc();
ret = ops->output(net, sk, skb);
dev_xmit_recursion_dec();
}
rcu_read_unlock();
if (ret == -EOPNOTSUPP)
@@ -359,13 +374,23 @@ EXPORT_SYMBOL_GPL(lwtunnel_output);
int lwtunnel_xmit(struct sk_buff *skb)
{
struct dst_entry *dst = skb_dst(skb);
const struct lwtunnel_encap_ops *ops;
struct lwtunnel_state *lwtstate;
int ret = -EINVAL;
struct dst_entry *dst;
int ret;
if (!dst)
if (dev_xmit_recursion()) {
net_crit_ratelimited("%s(): recursion limit reached on datapath\n",
__func__);
ret = -ENETDOWN;
goto drop;
}
dst = skb_dst(skb);
if (!dst) {
ret = -EINVAL;
goto drop;
}
lwtstate = dst->lwtstate;
@@ -376,8 +401,11 @@ int lwtunnel_xmit(struct sk_buff *skb)
ret = -EOPNOTSUPP;
rcu_read_lock();
ops = rcu_dereference(lwtun_encaps[lwtstate->type]);
if (likely(ops && ops->xmit))
if (likely(ops && ops->xmit)) {
dev_xmit_recursion_inc();
ret = ops->xmit(skb);
dev_xmit_recursion_dec();
}
rcu_read_unlock();
if (ret == -EOPNOTSUPP)
@@ -394,13 +422,23 @@ EXPORT_SYMBOL_GPL(lwtunnel_xmit);
int lwtunnel_input(struct sk_buff *skb)
{
struct dst_entry *dst = skb_dst(skb);
const struct lwtunnel_encap_ops *ops;
struct lwtunnel_state *lwtstate;
int ret = -EINVAL;
struct dst_entry *dst;
int ret;
if (!dst)
if (dev_xmit_recursion()) {
net_crit_ratelimited("%s(): recursion limit reached on datapath\n",
__func__);
ret = -ENETDOWN;
goto drop;
}
dst = skb_dst(skb);
if (!dst) {
ret = -EINVAL;
goto drop;
}
lwtstate = dst->lwtstate;
if (lwtstate->type == LWTUNNEL_ENCAP_NONE ||
@@ -410,8 +448,11 @@ int lwtunnel_input(struct sk_buff *skb)
ret = -EOPNOTSUPP;
rcu_read_lock();
ops = rcu_dereference(lwtun_encaps[lwtstate->type]);
if (likely(ops && ops->input))
if (likely(ops && ops->input)) {
dev_xmit_recursion_inc();
ret = ops->input(skb);
dev_xmit_recursion_dec();
}
rcu_read_unlock();
if (ret == -EOPNOTSUPP)

View File

@@ -2283,6 +2283,7 @@ static const struct nla_policy nl_neightbl_policy[NDTA_MAX+1] = {
static const struct nla_policy nl_ntbl_parm_policy[NDTPA_MAX+1] = {
[NDTPA_IFINDEX] = { .type = NLA_U32 },
[NDTPA_QUEUE_LEN] = { .type = NLA_U32 },
[NDTPA_QUEUE_LENBYTES] = { .type = NLA_U32 },
[NDTPA_PROXY_QLEN] = { .type = NLA_U32 },
[NDTPA_APP_PROBES] = { .type = NLA_U32 },
[NDTPA_UCAST_PROBES] = { .type = NLA_U32 },

View File

@@ -3184,13 +3184,16 @@ static void add_v4_addrs(struct inet6_dev *idev)
struct in6_addr addr;
struct net_device *dev;
struct net *net = dev_net(idev->dev);
int scope, plen;
int scope, plen, offset = 0;
u32 pflags = 0;
ASSERT_RTNL();
memset(&addr, 0, sizeof(struct in6_addr));
memcpy(&addr.s6_addr32[3], idev->dev->dev_addr, 4);
/* in case of IP6GRE the dev_addr is an IPv6 and therefore we use only the last 4 bytes */
if (idev->dev->addr_len == sizeof(struct in6_addr))
offset = sizeof(struct in6_addr) - 4;
memcpy(&addr.s6_addr32[3], idev->dev->dev_addr + offset, 4);
if (!(idev->dev->flags & IFF_POINTOPOINT) && idev->dev->type == ARPHRD_SIT) {
scope = IPV6_ADDR_COMPATv4;
@@ -3500,13 +3503,7 @@ static void addrconf_gre_config(struct net_device *dev)
return;
}
/* Generate the IPv6 link-local address using addrconf_addr_gen(),
* unless we have an IPv4 GRE device not bound to an IP address and
* which is in EUI64 mode (as __ipv6_isatap_ifid() would fail in this
* case). Such devices fall back to add_v4_addrs() instead.
*/
if (!(dev->type == ARPHRD_IPGRE && *(__be32 *)dev->dev_addr == 0 &&
idev->cnf.addr_gen_mode == IN6_ADDR_GEN_MODE_EUI64)) {
if (dev->type == ARPHRD_ETHER) {
addrconf_addr_gen(idev, true);
return;
}

View File

@@ -3640,7 +3640,8 @@ out:
in6_dev_put(idev);
if (err) {
lwtstate_put(fib6_nh->fib_nh_lws);
fib_nh_common_release(&fib6_nh->nh_common);
fib6_nh->nh_common.nhc_pcpu_rth_output = NULL;
fib6_nh->fib_nh_lws = NULL;
dev_put(dev);
}
@@ -3800,10 +3801,12 @@ static struct fib6_info *ip6_route_info_create(struct fib6_config *cfg,
if (nh) {
if (rt->fib6_src.plen) {
NL_SET_ERR_MSG(extack, "Nexthops can not be used with source routing");
err = -EINVAL;
goto out_free;
}
if (!nexthop_get(nh)) {
NL_SET_ERR_MSG(extack, "Nexthop has been deleted");
err = -ENOENT;
goto out_free;
}
rt->nh = nh;

View File

@@ -649,6 +649,7 @@ static bool mptcp_established_options_add_addr(struct sock *sk, struct sk_buff *
struct mptcp_sock *msk = mptcp_sk(subflow->conn);
bool drop_other_suboptions = false;
unsigned int opt_size = *size;
struct mptcp_addr_info addr;
bool echo;
int len;
@@ -657,7 +658,7 @@ static bool mptcp_established_options_add_addr(struct sock *sk, struct sk_buff *
*/
if (!mptcp_pm_should_add_signal(msk) ||
(opts->suboptions & (OPTION_MPTCP_MPJ_ACK | OPTION_MPTCP_MPC_ACK)) ||
!mptcp_pm_add_addr_signal(msk, skb, opt_size, remaining, &opts->addr,
!mptcp_pm_add_addr_signal(msk, skb, opt_size, remaining, &addr,
&echo, &drop_other_suboptions))
return false;
@@ -670,7 +671,7 @@ static bool mptcp_established_options_add_addr(struct sock *sk, struct sk_buff *
else if (opts->suboptions & OPTION_MPTCP_DSS)
return false;
len = mptcp_add_addr_len(opts->addr.family, echo, !!opts->addr.port);
len = mptcp_add_addr_len(addr.family, echo, !!addr.port);
if (remaining < len)
return false;
@@ -687,6 +688,7 @@ static bool mptcp_established_options_add_addr(struct sock *sk, struct sk_buff *
opts->ahmac = 0;
*size -= opt_size;
}
opts->addr = addr;
opts->suboptions |= OPTION_MPTCP_ADD_ADDR;
if (!echo) {
opts->ahmac = add_addr_generate_hmac(msk->local_key,

View File

@@ -8,7 +8,7 @@
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/module.h>
#include <linux/seqlock.h>
#include <linux/u64_stats_sync.h>
#include <linux/netlink.h>
#include <linux/netfilter.h>
#include <linux/netfilter/nf_tables.h>
@@ -17,6 +17,11 @@
#include <net/netfilter/nf_tables_offload.h>
struct nft_counter {
u64_stats_t bytes;
u64_stats_t packets;
};
struct nft_counter_tot {
s64 bytes;
s64 packets;
};
@@ -25,25 +30,24 @@ struct nft_counter_percpu_priv {
struct nft_counter __percpu *counter;
};
static DEFINE_PER_CPU(seqcount_t, nft_counter_seq);
static DEFINE_PER_CPU(struct u64_stats_sync, nft_counter_sync);
static inline void nft_counter_do_eval(struct nft_counter_percpu_priv *priv,
struct nft_regs *regs,
const struct nft_pktinfo *pkt)
{
struct u64_stats_sync *nft_sync;
struct nft_counter *this_cpu;
seqcount_t *myseq;
local_bh_disable();
this_cpu = this_cpu_ptr(priv->counter);
myseq = this_cpu_ptr(&nft_counter_seq);
nft_sync = this_cpu_ptr(&nft_counter_sync);
write_seqcount_begin(myseq);
u64_stats_update_begin(nft_sync);
u64_stats_add(&this_cpu->bytes, pkt->skb->len);
u64_stats_inc(&this_cpu->packets);
u64_stats_update_end(nft_sync);
this_cpu->bytes += pkt->skb->len;
this_cpu->packets++;
write_seqcount_end(myseq);
local_bh_enable();
}
@@ -66,17 +70,16 @@ static int nft_counter_do_init(const struct nlattr * const tb[],
if (cpu_stats == NULL)
return -ENOMEM;
preempt_disable();
this_cpu = this_cpu_ptr(cpu_stats);
this_cpu = raw_cpu_ptr(cpu_stats);
if (tb[NFTA_COUNTER_PACKETS]) {
this_cpu->packets =
be64_to_cpu(nla_get_be64(tb[NFTA_COUNTER_PACKETS]));
u64_stats_set(&this_cpu->packets,
be64_to_cpu(nla_get_be64(tb[NFTA_COUNTER_PACKETS])));
}
if (tb[NFTA_COUNTER_BYTES]) {
this_cpu->bytes =
be64_to_cpu(nla_get_be64(tb[NFTA_COUNTER_BYTES]));
u64_stats_set(&this_cpu->bytes,
be64_to_cpu(nla_get_be64(tb[NFTA_COUNTER_BYTES])));
}
preempt_enable();
priv->counter = cpu_stats;
return 0;
}
@@ -104,40 +107,41 @@ static void nft_counter_obj_destroy(const struct nft_ctx *ctx,
}
static void nft_counter_reset(struct nft_counter_percpu_priv *priv,
struct nft_counter *total)
struct nft_counter_tot *total)
{
struct u64_stats_sync *nft_sync;
struct nft_counter *this_cpu;
seqcount_t *myseq;
local_bh_disable();
this_cpu = this_cpu_ptr(priv->counter);
myseq = this_cpu_ptr(&nft_counter_seq);
nft_sync = this_cpu_ptr(&nft_counter_sync);
u64_stats_update_begin(nft_sync);
u64_stats_add(&this_cpu->packets, -total->packets);
u64_stats_add(&this_cpu->bytes, -total->bytes);
u64_stats_update_end(nft_sync);
write_seqcount_begin(myseq);
this_cpu->packets -= total->packets;
this_cpu->bytes -= total->bytes;
write_seqcount_end(myseq);
local_bh_enable();
}
static void nft_counter_fetch(struct nft_counter_percpu_priv *priv,
struct nft_counter *total)
struct nft_counter_tot *total)
{
struct nft_counter *this_cpu;
const seqcount_t *myseq;
u64 bytes, packets;
unsigned int seq;
int cpu;
memset(total, 0, sizeof(*total));
for_each_possible_cpu(cpu) {
myseq = per_cpu_ptr(&nft_counter_seq, cpu);
struct u64_stats_sync *nft_sync = per_cpu_ptr(&nft_counter_sync, cpu);
this_cpu = per_cpu_ptr(priv->counter, cpu);
do {
seq = read_seqcount_begin(myseq);
bytes = this_cpu->bytes;
packets = this_cpu->packets;
} while (read_seqcount_retry(myseq, seq));
seq = u64_stats_fetch_begin(nft_sync);
bytes = u64_stats_read(&this_cpu->bytes);
packets = u64_stats_read(&this_cpu->packets);
} while (u64_stats_fetch_retry(nft_sync, seq));
total->bytes += bytes;
total->packets += packets;
@@ -148,7 +152,7 @@ static int nft_counter_do_dump(struct sk_buff *skb,
struct nft_counter_percpu_priv *priv,
bool reset)
{
struct nft_counter total;
struct nft_counter_tot total;
nft_counter_fetch(priv, &total);
@@ -236,7 +240,7 @@ static int nft_counter_clone(struct nft_expr *dst, const struct nft_expr *src, g
struct nft_counter_percpu_priv *priv_clone = nft_expr_priv(dst);
struct nft_counter __percpu *cpu_stats;
struct nft_counter *this_cpu;
struct nft_counter total;
struct nft_counter_tot total;
nft_counter_fetch(priv, &total);
@@ -244,11 +248,9 @@ static int nft_counter_clone(struct nft_expr *dst, const struct nft_expr *src, g
if (cpu_stats == NULL)
return -ENOMEM;
preempt_disable();
this_cpu = this_cpu_ptr(cpu_stats);
this_cpu->packets = total.packets;
this_cpu->bytes = total.bytes;
preempt_enable();
this_cpu = raw_cpu_ptr(cpu_stats);
u64_stats_set(&this_cpu->packets, total.packets);
u64_stats_set(&this_cpu->bytes, total.bytes);
priv_clone->counter = cpu_stats;
return 0;
@@ -266,17 +268,17 @@ static void nft_counter_offload_stats(struct nft_expr *expr,
const struct flow_stats *stats)
{
struct nft_counter_percpu_priv *priv = nft_expr_priv(expr);
struct u64_stats_sync *nft_sync;
struct nft_counter *this_cpu;
seqcount_t *myseq;
local_bh_disable();
this_cpu = this_cpu_ptr(priv->counter);
myseq = this_cpu_ptr(&nft_counter_seq);
nft_sync = this_cpu_ptr(&nft_counter_sync);
write_seqcount_begin(myseq);
this_cpu->packets += stats->pkts;
this_cpu->bytes += stats->bytes;
write_seqcount_end(myseq);
u64_stats_update_begin(nft_sync);
u64_stats_add(&this_cpu->packets, stats->pkts);
u64_stats_add(&this_cpu->bytes, stats->bytes);
u64_stats_update_end(nft_sync);
local_bh_enable();
}
@@ -285,7 +287,7 @@ void nft_counter_init_seqcount(void)
int cpu;
for_each_possible_cpu(cpu)
seqcount_init(per_cpu_ptr(&nft_counter_seq, cpu));
u64_stats_init(per_cpu_ptr(&nft_counter_sync, cpu));
}
struct nft_expr_type nft_counter_type;

View File

@@ -102,7 +102,7 @@ struct xsk_buff_pool *xp_create_and_assign_umem(struct xdp_sock *xs,
if (pool->unaligned)
pool->free_heads[i] = xskb;
else
xp_init_xskb_addr(xskb, pool, i * pool->chunk_size);
xp_init_xskb_addr(xskb, pool, (u64)i * pool->chunk_size);
}
return pool;

View File

@@ -736,7 +736,7 @@ int xfrm_output(struct sock *sk, struct sk_buff *skb)
skb->encapsulation = 1;
if (skb_is_gso(skb)) {
if (skb->inner_protocol)
if (skb->inner_protocol && x->props.mode == XFRM_MODE_TUNNEL)
return xfrm_output_gso(net, sk, skb);
skb_shinfo(skb)->gso_type |= SKB_GSO_ESP;

View File

@@ -344,8 +344,11 @@ quiet_cmd_rustc_library = $(if $(skip_clippy),RUSTC,$(RUSTC_OR_CLIPPY_QUIET)) L
$(if $(rustc_objcopy),;$(OBJCOPY) $(rustc_objcopy) $@)
rust-analyzer:
$(Q)$(srctree)/scripts/generate_rust_analyzer.py $(srctree) $(objtree) \
$(RUST_LIB_SRC) > $(objtree)/rust-project.json
$(Q)$(srctree)/scripts/generate_rust_analyzer.py \
--cfgs='core=$(core-cfgs)' --cfgs='alloc=$(alloc-cfgs)' \
$(abs_srctree) $(abs_objtree) \
$(RUST_LIB_SRC) $(KBUILD_EXTMOD) > \
$(if $(KBUILD_EXTMOD),$(extmod_prefix),$(objtree))/rust-project.json
$(obj)/core.o: private skip_clippy = 1
$(obj)/core.o: private skip_flags = -Dunreachable_pub

View File

@@ -6,10 +6,19 @@
import argparse
import json
import logging
import os
import pathlib
import sys
def generate_crates(srctree, objtree, sysroot_src):
def args_crates_cfgs(cfgs):
crates_cfgs = {}
for cfg in cfgs:
crate, vals = cfg.split("=", 1)
crates_cfgs[crate] = vals.replace("--cfg", "").split()
return crates_cfgs
def generate_crates(srctree, objtree, sysroot_src, external_src, cfgs):
# Generate the configuration list.
cfg = []
with open(objtree / "include" / "generated" / "rustc_cfg") as fd:
@@ -23,6 +32,7 @@ def generate_crates(srctree, objtree, sysroot_src):
# Avoid O(n^2) iterations by keeping a map of indexes.
crates = []
crates_indexes = {}
crates_cfgs = args_crates_cfgs(cfgs)
def append_crate(display_name, root_module, deps, cfg=[], is_workspace_member=True, is_proc_macro=False):
crates_indexes[display_name] = len(crates)
@@ -39,13 +49,26 @@ def generate_crates(srctree, objtree, sysroot_src):
}
})
# First, the ones in `rust/` since they are a bit special.
append_crate(
"core",
sysroot_src / "core" / "src" / "lib.rs",
[],
is_workspace_member=False,
)
def append_sysroot_crate(
display_name,
deps,
cfg=[],
):
append_crate(
display_name,
sysroot_src / display_name / "src" / "lib.rs",
deps,
cfg,
is_workspace_member=False,
)
# NB: sysroot crates reexport items from one another so setting up our transitive dependencies
# here is important for ensuring that rust-analyzer can resolve symbols. The sources of truth
# for this dependency graph are `(sysroot_src / crate / "Cargo.toml" for crate in crates)`.
append_sysroot_crate("core", [], cfg=crates_cfgs.get("core", []))
append_sysroot_crate("alloc", ["core"])
append_sysroot_crate("std", ["alloc", "core"])
append_sysroot_crate("proc_macro", ["core", "std"])
append_crate(
"compiler_builtins",
@@ -57,15 +80,16 @@ def generate_crates(srctree, objtree, sysroot_src):
"alloc",
srctree / "rust" / "alloc" / "lib.rs",
["core", "compiler_builtins"],
cfg=crates_cfgs.get("alloc", []),
)
append_crate(
"macros",
srctree / "rust" / "macros" / "lib.rs",
[],
["std", "proc_macro"],
is_proc_macro=True,
)
crates[-1]["proc_macro_dylib_path"] = "rust/libmacros.so"
crates[-1]["proc_macro_dylib_path"] = f"{objtree}/rust/libmacros.so"
append_crate(
"bindings",
@@ -89,16 +113,26 @@ def generate_crates(srctree, objtree, sysroot_src):
"exclude_dirs": [],
}
def is_root_crate(build_file, target):
try:
return f"{target}.o" in open(build_file).read()
except FileNotFoundError:
return False
# Then, the rest outside of `rust/`.
#
# We explicitly mention the top-level folders we want to cover.
for folder in ("samples", "drivers"):
for path in (srctree / folder).rglob("*.rs"):
extra_dirs = map(lambda dir: srctree / dir, ("samples", "drivers"))
if external_src is not None:
extra_dirs = [external_src]
for folder in extra_dirs:
for path in folder.rglob("*.rs"):
logging.info("Checking %s", path)
name = path.name.replace(".rs", "")
# Skip those that are not crate roots.
if f"{name}.o" not in open(path.parent / "Makefile").read():
if not is_root_crate(path.parent / "Makefile", name) and \
not is_root_crate(path.parent / "Kbuild", name):
continue
logging.info("Adding %s", name)
@@ -114,9 +148,11 @@ def generate_crates(srctree, objtree, sysroot_src):
def main():
parser = argparse.ArgumentParser()
parser.add_argument('--verbose', '-v', action='store_true')
parser.add_argument('--cfgs', action='append', default=[])
parser.add_argument("srctree", type=pathlib.Path)
parser.add_argument("objtree", type=pathlib.Path)
parser.add_argument("sysroot_src", type=pathlib.Path)
parser.add_argument("exttree", type=pathlib.Path, nargs="?")
args = parser.parse_args()
logging.basicConfig(
@@ -125,7 +161,7 @@ def main():
)
rust_project = {
"crates": generate_crates(args.srctree, args.objtree, args.sysroot_src),
"crates": generate_crates(args.srctree, args.objtree, args.sysroot_src, args.exttree, args.cfgs),
"sysroot_src": str(args.sysroot_src),
}