mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-05 02:21:52 +09:00
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:
13
Makefile
13
Makefile
@@ -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
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
|
||||
@@ -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>;
|
||||
};
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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";
|
||||
|
||||
|
||||
@@ -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 = <®_vcc3v3>;
|
||||
vqmmc-supply = <®_vcc1v8>;
|
||||
vqmmc-supply = <&buck5_reg>;
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
|
||||
@@ -117,7 +117,7 @@
|
||||
};
|
||||
|
||||
&u2phy1_host {
|
||||
status = "disabled";
|
||||
phy-supply = <&vdd_5v>;
|
||||
};
|
||||
|
||||
&uart0 {
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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++) {
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -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)},
|
||||
};
|
||||
|
||||
|
||||
@@ -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)},
|
||||
};
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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))
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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__ */
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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",
|
||||
};
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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 = {
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
151
fs/ntfs3/file.c
151
fs/ntfs3/file.c
@@ -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;
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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];
|
||||
|
||||
|
||||
@@ -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");
|
||||
|
||||
@@ -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";
|
||||
}
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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) ||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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));
|
||||
|
||||
@@ -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 {
|
||||
|
||||
16
mm/migrate.c
16
mm/migrate.c
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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 },
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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),
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user