Merge 0264d6b73e ("can: ems_pci: move ASIX AX99100 ids to pci_ids.h") into android14-6.1-lts

Steps on the way to 6.1.129

Resolves merge conflicts in:
	drivers/i3c/master/i3c-master-cdns.c
	include/linux/iommu.h
	net/ipv4/icmp.c

Change-Id: I27a81ad93ee7a865b5eb17d7866220fd3cf0bb11
Signed-off-by: Greg Kroah-Hartman <gregkh@google.com>
This commit is contained in:
Greg Kroah-Hartman
2025-03-07 15:05:13 +00:00
65 changed files with 545 additions and 232 deletions

View File

@@ -42,6 +42,8 @@ struct pt_regs {
unsigned long trap_a0; unsigned long trap_a0;
unsigned long trap_a1; unsigned long trap_a1;
unsigned long trap_a2; unsigned long trap_a2;
/* This makes the stack 16-byte aligned as GCC expects */
unsigned long __pad0;
/* These are saved by PAL-code: */ /* These are saved by PAL-code: */
unsigned long ps; unsigned long ps;
unsigned long pc; unsigned long pc;

View File

@@ -32,7 +32,9 @@ void foo(void)
DEFINE(CRED_EGID, offsetof(struct cred, egid)); DEFINE(CRED_EGID, offsetof(struct cred, egid));
BLANK(); BLANK();
DEFINE(SP_OFF, offsetof(struct pt_regs, ps));
DEFINE(SIZEOF_PT_REGS, sizeof(struct pt_regs)); DEFINE(SIZEOF_PT_REGS, sizeof(struct pt_regs));
DEFINE(SWITCH_STACK_SIZE, sizeof(struct switch_stack));
DEFINE(PT_PTRACED, PT_PTRACED); DEFINE(PT_PTRACED, PT_PTRACED);
DEFINE(CLONE_VM, CLONE_VM); DEFINE(CLONE_VM, CLONE_VM);
DEFINE(CLONE_UNTRACED, CLONE_UNTRACED); DEFINE(CLONE_UNTRACED, CLONE_UNTRACED);

View File

@@ -15,10 +15,6 @@
.set noat .set noat
.cfi_sections .debug_frame .cfi_sections .debug_frame
/* Stack offsets. */
#define SP_OFF 184
#define SWITCH_STACK_SIZE 320
.macro CFI_START_OSF_FRAME func .macro CFI_START_OSF_FRAME func
.align 4 .align 4
.globl \func .globl \func
@@ -199,8 +195,8 @@ CFI_END_OSF_FRAME entArith
CFI_START_OSF_FRAME entMM CFI_START_OSF_FRAME entMM
SAVE_ALL SAVE_ALL
/* save $9 - $15 so the inline exception code can manipulate them. */ /* save $9 - $15 so the inline exception code can manipulate them. */
subq $sp, 56, $sp subq $sp, 64, $sp
.cfi_adjust_cfa_offset 56 .cfi_adjust_cfa_offset 64
stq $9, 0($sp) stq $9, 0($sp)
stq $10, 8($sp) stq $10, 8($sp)
stq $11, 16($sp) stq $11, 16($sp)
@@ -215,7 +211,7 @@ CFI_START_OSF_FRAME entMM
.cfi_rel_offset $13, 32 .cfi_rel_offset $13, 32
.cfi_rel_offset $14, 40 .cfi_rel_offset $14, 40
.cfi_rel_offset $15, 48 .cfi_rel_offset $15, 48
addq $sp, 56, $19 addq $sp, 64, $19
/* handle the fault */ /* handle the fault */
lda $8, 0x3fff lda $8, 0x3fff
bic $sp, $8, $8 bic $sp, $8, $8
@@ -228,7 +224,7 @@ CFI_START_OSF_FRAME entMM
ldq $13, 32($sp) ldq $13, 32($sp)
ldq $14, 40($sp) ldq $14, 40($sp)
ldq $15, 48($sp) ldq $15, 48($sp)
addq $sp, 56, $sp addq $sp, 64, $sp
.cfi_restore $9 .cfi_restore $9
.cfi_restore $10 .cfi_restore $10
.cfi_restore $11 .cfi_restore $11
@@ -236,7 +232,7 @@ CFI_START_OSF_FRAME entMM
.cfi_restore $13 .cfi_restore $13
.cfi_restore $14 .cfi_restore $14
.cfi_restore $15 .cfi_restore $15
.cfi_adjust_cfa_offset -56 .cfi_adjust_cfa_offset -64
/* finish up the syscall as normal. */ /* finish up the syscall as normal. */
br ret_from_sys_call br ret_from_sys_call
CFI_END_OSF_FRAME entMM CFI_END_OSF_FRAME entMM
@@ -383,8 +379,8 @@ entUnaUser:
.cfi_restore $0 .cfi_restore $0
.cfi_adjust_cfa_offset -256 .cfi_adjust_cfa_offset -256
SAVE_ALL /* setup normal kernel stack */ SAVE_ALL /* setup normal kernel stack */
lda $sp, -56($sp) lda $sp, -64($sp)
.cfi_adjust_cfa_offset 56 .cfi_adjust_cfa_offset 64
stq $9, 0($sp) stq $9, 0($sp)
stq $10, 8($sp) stq $10, 8($sp)
stq $11, 16($sp) stq $11, 16($sp)
@@ -400,7 +396,7 @@ entUnaUser:
.cfi_rel_offset $14, 40 .cfi_rel_offset $14, 40
.cfi_rel_offset $15, 48 .cfi_rel_offset $15, 48
lda $8, 0x3fff lda $8, 0x3fff
addq $sp, 56, $19 addq $sp, 64, $19
bic $sp, $8, $8 bic $sp, $8, $8
jsr $26, do_entUnaUser jsr $26, do_entUnaUser
ldq $9, 0($sp) ldq $9, 0($sp)
@@ -410,7 +406,7 @@ entUnaUser:
ldq $13, 32($sp) ldq $13, 32($sp)
ldq $14, 40($sp) ldq $14, 40($sp)
ldq $15, 48($sp) ldq $15, 48($sp)
lda $sp, 56($sp) lda $sp, 64($sp)
.cfi_restore $9 .cfi_restore $9
.cfi_restore $10 .cfi_restore $10
.cfi_restore $11 .cfi_restore $11
@@ -418,7 +414,7 @@ entUnaUser:
.cfi_restore $13 .cfi_restore $13
.cfi_restore $14 .cfi_restore $14
.cfi_restore $15 .cfi_restore $15
.cfi_adjust_cfa_offset -56 .cfi_adjust_cfa_offset -64
br ret_from_sys_call br ret_from_sys_call
CFI_END_OSF_FRAME entUna CFI_END_OSF_FRAME entUna

View File

@@ -707,7 +707,7 @@ s_reg_to_mem (unsigned long s_reg)
static int unauser_reg_offsets[32] = { static int unauser_reg_offsets[32] = {
R(r0), R(r1), R(r2), R(r3), R(r4), R(r5), R(r6), R(r7), R(r8), R(r0), R(r1), R(r2), R(r3), R(r4), R(r5), R(r6), R(r7), R(r8),
/* r9 ... r15 are stored in front of regs. */ /* r9 ... r15 are stored in front of regs. */
-56, -48, -40, -32, -24, -16, -8, -64, -56, -48, -40, -32, -24, -16, /* padding at -8 */
R(r16), R(r17), R(r18), R(r16), R(r17), R(r18),
R(r19), R(r20), R(r21), R(r22), R(r23), R(r24), R(r25), R(r26), R(r19), R(r20), R(r21), R(r22), R(r23), R(r24), R(r25), R(r26),
R(r27), R(r28), R(gp), R(r27), R(r28), R(gp),

View File

@@ -78,8 +78,8 @@ __load_new_mm_context(struct mm_struct *next_mm)
/* Macro for exception fixup code to access integer registers. */ /* Macro for exception fixup code to access integer registers. */
#define dpf_reg(r) \ #define dpf_reg(r) \
(((unsigned long *)regs)[(r) <= 8 ? (r) : (r) <= 15 ? (r)-16 : \ (((unsigned long *)regs)[(r) <= 8 ? (r) : (r) <= 15 ? (r)-17 : \
(r) <= 18 ? (r)+10 : (r)-10]) (r) <= 18 ? (r)+11 : (r)-10])
asmlinkage void asmlinkage void
do_page_fault(unsigned long address, unsigned long mmcsr, do_page_fault(unsigned long address, unsigned long mmcsr,

View File

@@ -1558,7 +1558,7 @@
}; };
dce-fabric@de00000 { dce-fabric@de00000 {
compatible = "nvidia,tegra234-sce-fabric"; compatible = "nvidia,tegra234-dce-fabric";
reg = <0xde00000 0x40000>; reg = <0xde00000 0x40000>;
interrupts = <GIC_SPI 381 IRQ_TYPE_LEVEL_HIGH>; interrupts = <GIC_SPI 381 IRQ_TYPE_LEVEL_HIGH>;
status = "okay"; status = "okay";

View File

@@ -38,6 +38,7 @@ SECTIONS
*/ */
/DISCARD/ : { /DISCARD/ : {
*(.note.GNU-stack .note.gnu.property) *(.note.GNU-stack .note.gnu.property)
*(.ARM.attributes)
} }
.note : { *(.note.*) } :text :note .note : { *(.note.*) } :text :note

View File

@@ -182,6 +182,7 @@ SECTIONS
/DISCARD/ : { /DISCARD/ : {
*(.interp .dynamic) *(.interp .dynamic)
*(.dynsym .dynstr .hash .gnu.hash) *(.dynsym .dynstr .hash .gnu.hash)
*(.ARM.attributes)
} }
. = KIMAGE_VADDR; . = KIMAGE_VADDR;

View File

@@ -173,7 +173,6 @@ EXPORT_SYMBOL_GPL(arch_static_call_transform);
noinstr void __static_call_update_early(void *tramp, void *func) noinstr void __static_call_update_early(void *tramp, void *func)
{ {
BUG_ON(system_state != SYSTEM_BOOTING); BUG_ON(system_state != SYSTEM_BOOTING);
BUG_ON(!early_boot_irqs_disabled);
BUG_ON(static_call_initialized); BUG_ON(static_call_initialized);
__text_gen_insn(tramp, JMP32_INSN_OPCODE, tramp, func, JMP32_INSN_SIZE); __text_gen_insn(tramp, JMP32_INSN_OPCODE, tramp, func, JMP32_INSN_SIZE);
sync_core(); sync_core();

View File

@@ -51,13 +51,25 @@ int mac_partition(struct parsed_partitions *state)
} }
secsize = be16_to_cpu(md->block_size); secsize = be16_to_cpu(md->block_size);
put_dev_sector(sect); put_dev_sector(sect);
/*
* If the "block size" is not a power of 2, things get weird - we might
* end up with a partition straddling a sector boundary, so we wouldn't
* be able to read a partition entry with read_part_sector().
* Real block sizes are probably (?) powers of two, so just require
* that.
*/
if (!is_power_of_2(secsize))
return -1;
datasize = round_down(secsize, 512); datasize = round_down(secsize, 512);
data = read_part_sector(state, datasize / 512, &sect); data = read_part_sector(state, datasize / 512, &sect);
if (!data) if (!data)
return -1; return -1;
partoffset = secsize % 512; partoffset = secsize % 512;
if (partoffset + sizeof(*part) > datasize) if (partoffset + sizeof(*part) > datasize) {
put_dev_sector(sect);
return -1; return -1;
}
part = (struct mac_partition *) (data + partoffset); part = (struct mac_partition *) (data + partoffset);
if (be16_to_cpu(part->signature) != MAC_PARTITION_MAGIC) { if (be16_to_cpu(part->signature) != MAC_PARTITION_MAGIC) {
put_dev_sector(sect); put_dev_sector(sect);
@@ -110,8 +122,8 @@ int mac_partition(struct parsed_partitions *state)
int i, l; int i, l;
goodness++; goodness++;
l = strlen(part->name); l = strnlen(part->name, sizeof(part->name));
if (strcmp(part->name, "/") == 0) if (strncmp(part->name, "/", sizeof(part->name)) == 0)
goodness++; goodness++;
for (i = 0; i <= l - 4; ++i) { for (i = 0; i <= l - 4; ++i) {
if (strncasecmp(part->name + i, "root", if (strncasecmp(part->name + i, "root",

View File

@@ -1059,6 +1059,7 @@ err_alloc:
kfree(d->wake_buf); kfree(d->wake_buf);
kfree(d->mask_buf_def); kfree(d->mask_buf_def);
kfree(d->mask_buf); kfree(d->mask_buf);
kfree(d->main_status_buf);
kfree(d->status_buf); kfree(d->status_buf);
kfree(d->status_reg_buf); kfree(d->status_reg_buf);
if (d->virt_buf) { if (d->virt_buf) {
@@ -1139,6 +1140,7 @@ void regmap_del_irq_chip(int irq, struct regmap_irq_chip_data *d)
kfree(d->wake_buf); kfree(d->wake_buf);
kfree(d->mask_buf_def); kfree(d->mask_buf_def);
kfree(d->mask_buf); kfree(d->mask_buf);
kfree(d->main_status_buf);
kfree(d->status_reg_buf); kfree(d->status_reg_buf);
kfree(d->status_buf); kfree(d->status_buf);
if (d->config_buf) { if (d->config_buf) {

View File

@@ -835,13 +835,15 @@ char * __init efi_md_typeattr_format(char *buf, size_t size,
EFI_MEMORY_WB | EFI_MEMORY_UCE | EFI_MEMORY_RO | EFI_MEMORY_WB | EFI_MEMORY_UCE | EFI_MEMORY_RO |
EFI_MEMORY_WP | EFI_MEMORY_RP | EFI_MEMORY_XP | EFI_MEMORY_WP | EFI_MEMORY_RP | EFI_MEMORY_XP |
EFI_MEMORY_NV | EFI_MEMORY_SP | EFI_MEMORY_CPU_CRYPTO | EFI_MEMORY_NV | EFI_MEMORY_SP | EFI_MEMORY_CPU_CRYPTO |
EFI_MEMORY_RUNTIME | EFI_MEMORY_MORE_RELIABLE)) EFI_MEMORY_MORE_RELIABLE | EFI_MEMORY_HOT_PLUGGABLE |
EFI_MEMORY_RUNTIME))
snprintf(pos, size, "|attr=0x%016llx]", snprintf(pos, size, "|attr=0x%016llx]",
(unsigned long long)attr); (unsigned long long)attr);
else else
snprintf(pos, size, snprintf(pos, size,
"|%3s|%2s|%2s|%2s|%2s|%2s|%2s|%2s|%2s|%3s|%2s|%2s|%2s|%2s]", "|%3s|%2s|%2s|%2s|%2s|%2s|%2s|%2s|%2s|%2s|%3s|%2s|%2s|%2s|%2s]",
attr & EFI_MEMORY_RUNTIME ? "RUN" : "", attr & EFI_MEMORY_RUNTIME ? "RUN" : "",
attr & EFI_MEMORY_HOT_PLUGGABLE ? "HP" : "",
attr & EFI_MEMORY_MORE_RELIABLE ? "MR" : "", attr & EFI_MEMORY_MORE_RELIABLE ? "MR" : "",
attr & EFI_MEMORY_CPU_CRYPTO ? "CC" : "", attr & EFI_MEMORY_CPU_CRYPTO ? "CC" : "",
attr & EFI_MEMORY_SP ? "SP" : "", attr & EFI_MEMORY_SP ? "SP" : "",

View File

@@ -25,6 +25,9 @@ static unsigned long get_entry_num_slots(efi_memory_desc_t *md,
if (md->type != EFI_CONVENTIONAL_MEMORY) if (md->type != EFI_CONVENTIONAL_MEMORY)
return 0; return 0;
if (md->attribute & EFI_MEMORY_HOT_PLUGGABLE)
return 0;
if (efi_soft_reserve_enabled() && if (efi_soft_reserve_enabled() &&
(md->attribute & EFI_MEMORY_SP)) (md->attribute & EFI_MEMORY_SP))
return 0; return 0;

View File

@@ -53,6 +53,9 @@ efi_status_t efi_low_alloc_above(unsigned long size, unsigned long align,
if (desc->type != EFI_CONVENTIONAL_MEMORY) if (desc->type != EFI_CONVENTIONAL_MEMORY)
continue; continue;
if (desc->attribute & EFI_MEMORY_HOT_PLUGGABLE)
continue;
if (efi_soft_reserve_enabled() && if (efi_soft_reserve_enabled() &&
(desc->attribute & EFI_MEMORY_SP)) (desc->attribute & EFI_MEMORY_SP))
continue; continue;

View File

@@ -191,7 +191,7 @@ static void stmpe_gpio_irq_sync_unlock(struct irq_data *d)
[REG_IE][CSB] = STMPE_IDX_IEGPIOR_CSB, [REG_IE][CSB] = STMPE_IDX_IEGPIOR_CSB,
[REG_IE][MSB] = STMPE_IDX_IEGPIOR_MSB, [REG_IE][MSB] = STMPE_IDX_IEGPIOR_MSB,
}; };
int i, j; int ret, i, j;
/* /*
* STMPE1600: to be able to get IRQ from pins, * STMPE1600: to be able to get IRQ from pins,
@@ -199,8 +199,16 @@ static void stmpe_gpio_irq_sync_unlock(struct irq_data *d)
* GPSR or GPCR registers * GPSR or GPCR registers
*/ */
if (stmpe->partnum == STMPE1600) { if (stmpe->partnum == STMPE1600) {
stmpe_reg_read(stmpe, stmpe->regs[STMPE_IDX_GPMR_LSB]); ret = stmpe_reg_read(stmpe, stmpe->regs[STMPE_IDX_GPMR_LSB]);
stmpe_reg_read(stmpe, stmpe->regs[STMPE_IDX_GPMR_CSB]); if (ret < 0) {
dev_err(stmpe->dev, "Failed to read GPMR_LSB: %d\n", ret);
goto err;
}
ret = stmpe_reg_read(stmpe, stmpe->regs[STMPE_IDX_GPMR_CSB]);
if (ret < 0) {
dev_err(stmpe->dev, "Failed to read GPMR_CSB: %d\n", ret);
goto err;
}
} }
for (i = 0; i < CACHE_NR_REGS; i++) { for (i = 0; i < CACHE_NR_REGS; i++) {
@@ -222,6 +230,7 @@ static void stmpe_gpio_irq_sync_unlock(struct irq_data *d)
} }
} }
err:
mutex_unlock(&stmpe_gpio->irq_lock); mutex_unlock(&stmpe_gpio->irq_lock);
} }

View File

@@ -1640,6 +1640,20 @@ static const struct dmi_system_id gpiolib_acpi_quirks[] __initconst = {
.ignore_wake = "PNP0C50:00@8", .ignore_wake = "PNP0C50:00@8",
}, },
}, },
{
/*
* Spurious wakeups from GPIO 11
* Found in BIOS 1.04
* https://gitlab.freedesktop.org/drm/amd/-/issues/3954
*/
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
DMI_MATCH(DMI_PRODUCT_FAMILY, "Acer Nitro V 14"),
},
.driver_data = &(struct acpi_gpiolib_dmi_quirk) {
.ignore_interrupt = "AMDI0030:00@11",
},
},
{} /* Terminating entry */ {} /* Terminating entry */
}; };

View File

@@ -599,7 +599,7 @@ void dispc_k2g_set_irqenable(struct dispc_device *dispc, dispc_irq_t mask)
{ {
dispc_irq_t old_mask = dispc_k2g_read_irqenable(dispc); dispc_irq_t old_mask = dispc_k2g_read_irqenable(dispc);
/* clear the irqstatus for newly enabled irqs */ /* clear the irqstatus for irqs that will be enabled */
dispc_k2g_clear_irqstatus(dispc, (mask ^ old_mask) & mask); dispc_k2g_clear_irqstatus(dispc, (mask ^ old_mask) & mask);
dispc_k2g_vp_set_irqenable(dispc, 0, mask); dispc_k2g_vp_set_irqenable(dispc, 0, mask);
@@ -607,6 +607,9 @@ void dispc_k2g_set_irqenable(struct dispc_device *dispc, dispc_irq_t mask)
dispc_write(dispc, DISPC_IRQENABLE_SET, (1 << 0) | (1 << 7)); dispc_write(dispc, DISPC_IRQENABLE_SET, (1 << 0) | (1 << 7));
/* clear the irqstatus for irqs that were disabled */
dispc_k2g_clear_irqstatus(dispc, (mask ^ old_mask) & old_mask);
/* flush posted write */ /* flush posted write */
dispc_k2g_read_irqenable(dispc); dispc_k2g_read_irqenable(dispc);
} }
@@ -679,24 +682,20 @@ static
void dispc_k3_clear_irqstatus(struct dispc_device *dispc, dispc_irq_t clearmask) void dispc_k3_clear_irqstatus(struct dispc_device *dispc, dispc_irq_t clearmask)
{ {
unsigned int i; unsigned int i;
u32 top_clear = 0;
for (i = 0; i < dispc->feat->num_vps; ++i) { for (i = 0; i < dispc->feat->num_vps; ++i) {
if (clearmask & DSS_IRQ_VP_MASK(i)) { if (clearmask & DSS_IRQ_VP_MASK(i))
dispc_k3_vp_write_irqstatus(dispc, i, clearmask); dispc_k3_vp_write_irqstatus(dispc, i, clearmask);
top_clear |= BIT(i);
}
} }
for (i = 0; i < dispc->feat->num_planes; ++i) { for (i = 0; i < dispc->feat->num_planes; ++i) {
if (clearmask & DSS_IRQ_PLANE_MASK(i)) { if (clearmask & DSS_IRQ_PLANE_MASK(i))
dispc_k3_vid_write_irqstatus(dispc, i, clearmask); dispc_k3_vid_write_irqstatus(dispc, i, clearmask);
top_clear |= BIT(4 + i);
}
} }
if (dispc->feat->subrev == DISPC_K2G) if (dispc->feat->subrev == DISPC_K2G)
return; return;
dispc_write(dispc, DISPC_IRQSTATUS, top_clear); /* always clear the top level irqstatus */
dispc_write(dispc, DISPC_IRQSTATUS, dispc_read(dispc, DISPC_IRQSTATUS));
/* Flush posted writes */ /* Flush posted writes */
dispc_read(dispc, DISPC_IRQSTATUS); dispc_read(dispc, DISPC_IRQSTATUS);
@@ -742,7 +741,7 @@ static void dispc_k3_set_irqenable(struct dispc_device *dispc,
old_mask = dispc_k3_read_irqenable(dispc); old_mask = dispc_k3_read_irqenable(dispc);
/* clear the irqstatus for newly enabled irqs */ /* clear the irqstatus for irqs that will be enabled */
dispc_k3_clear_irqstatus(dispc, (old_mask ^ mask) & mask); dispc_k3_clear_irqstatus(dispc, (old_mask ^ mask) & mask);
for (i = 0; i < dispc->feat->num_vps; ++i) { for (i = 0; i < dispc->feat->num_vps; ++i) {
@@ -767,6 +766,9 @@ static void dispc_k3_set_irqenable(struct dispc_device *dispc,
if (main_disable) if (main_disable)
dispc_write(dispc, DISPC_IRQENABLE_CLR, main_disable); dispc_write(dispc, DISPC_IRQENABLE_CLR, main_disable);
/* clear the irqstatus for irqs that were disabled */
dispc_k3_clear_irqstatus(dispc, (old_mask ^ mask) & old_mask);
/* Flush posted writes */ /* Flush posted writes */
dispc_read(dispc, DISPC_IRQENABLE_SET); dispc_read(dispc, DISPC_IRQENABLE_SET);
} }

View File

@@ -175,6 +175,7 @@ int v3d_perfmon_destroy_ioctl(struct drm_device *dev, void *data,
{ {
struct v3d_file_priv *v3d_priv = file_priv->driver_priv; struct v3d_file_priv *v3d_priv = file_priv->driver_priv;
struct drm_v3d_perfmon_destroy *req = data; struct drm_v3d_perfmon_destroy *req = data;
struct v3d_dev *v3d = v3d_priv->v3d;
struct v3d_perfmon *perfmon; struct v3d_perfmon *perfmon;
mutex_lock(&v3d_priv->perfmon.lock); mutex_lock(&v3d_priv->perfmon.lock);
@@ -184,6 +185,10 @@ int v3d_perfmon_destroy_ioctl(struct drm_device *dev, void *data,
if (!perfmon) if (!perfmon)
return -EINVAL; return -EINVAL;
/* If the active perfmon is being destroyed, stop it first */
if (perfmon == v3d->active_perfmon)
v3d_perfmon_stop(v3d, perfmon, false);
v3d_perfmon_put(perfmon); v3d_perfmon_put(perfmon);
return 0; return 0;

View File

@@ -262,6 +262,7 @@
#define MSDC_PAD_TUNE_CMD_SEL BIT(21) /* RW */ #define MSDC_PAD_TUNE_CMD_SEL BIT(21) /* RW */
#define PAD_DS_TUNE_DLY_SEL BIT(0) /* RW */ #define PAD_DS_TUNE_DLY_SEL BIT(0) /* RW */
#define PAD_DS_TUNE_DLY2_SEL BIT(1) /* RW */
#define PAD_DS_TUNE_DLY1 GENMASK(6, 2) /* RW */ #define PAD_DS_TUNE_DLY1 GENMASK(6, 2) /* RW */
#define PAD_DS_TUNE_DLY2 GENMASK(11, 7) /* RW */ #define PAD_DS_TUNE_DLY2 GENMASK(11, 7) /* RW */
#define PAD_DS_TUNE_DLY3 GENMASK(16, 12) /* RW */ #define PAD_DS_TUNE_DLY3 GENMASK(16, 12) /* RW */
@@ -307,6 +308,7 @@
/* EMMC50_PAD_DS_TUNE mask */ /* EMMC50_PAD_DS_TUNE mask */
#define PAD_DS_DLY_SEL BIT(16) /* RW */ #define PAD_DS_DLY_SEL BIT(16) /* RW */
#define PAD_DS_DLY2_SEL BIT(15) /* RW */
#define PAD_DS_DLY1 GENMASK(14, 10) /* RW */ #define PAD_DS_DLY1 GENMASK(14, 10) /* RW */
#define PAD_DS_DLY3 GENMASK(4, 0) /* RW */ #define PAD_DS_DLY3 GENMASK(4, 0) /* RW */
@@ -2293,13 +2295,23 @@ tune_done:
static int msdc_prepare_hs400_tuning(struct mmc_host *mmc, struct mmc_ios *ios) static int msdc_prepare_hs400_tuning(struct mmc_host *mmc, struct mmc_ios *ios)
{ {
struct msdc_host *host = mmc_priv(mmc); struct msdc_host *host = mmc_priv(mmc);
host->hs400_mode = true; host->hs400_mode = true;
if (host->top_base) if (host->top_base) {
writel(host->hs400_ds_delay, if (host->hs400_ds_dly3)
host->top_base + EMMC50_PAD_DS_TUNE); sdr_set_field(host->top_base + EMMC50_PAD_DS_TUNE,
else PAD_DS_DLY3, host->hs400_ds_dly3);
writel(host->hs400_ds_delay, host->base + PAD_DS_TUNE); if (host->hs400_ds_delay)
writel(host->hs400_ds_delay,
host->top_base + EMMC50_PAD_DS_TUNE);
} else {
if (host->hs400_ds_dly3)
sdr_set_field(host->base + PAD_DS_TUNE,
PAD_DS_TUNE_DLY3, host->hs400_ds_dly3);
if (host->hs400_ds_delay)
writel(host->hs400_ds_delay, host->base + PAD_DS_TUNE);
}
/* hs400 mode must set it to 0 */ /* hs400 mode must set it to 0 */
sdr_clr_bits(host->base + MSDC_PATCH_BIT2, MSDC_PATCH_BIT2_CFGCRCSTS); sdr_clr_bits(host->base + MSDC_PATCH_BIT2, MSDC_PATCH_BIT2_CFGCRCSTS);
/* to improve read performance, set outstanding to 2 */ /* to improve read performance, set outstanding to 2 */
@@ -2319,14 +2331,11 @@ static int msdc_execute_hs400_tuning(struct mmc_host *mmc, struct mmc_card *card
if (host->top_base) { if (host->top_base) {
sdr_set_bits(host->top_base + EMMC50_PAD_DS_TUNE, sdr_set_bits(host->top_base + EMMC50_PAD_DS_TUNE,
PAD_DS_DLY_SEL); PAD_DS_DLY_SEL);
if (host->hs400_ds_dly3) sdr_clr_bits(host->top_base + EMMC50_PAD_DS_TUNE,
sdr_set_field(host->top_base + EMMC50_PAD_DS_TUNE, PAD_DS_DLY2_SEL);
PAD_DS_DLY3, host->hs400_ds_dly3);
} else { } else {
sdr_set_bits(host->base + PAD_DS_TUNE, PAD_DS_TUNE_DLY_SEL); sdr_set_bits(host->base + PAD_DS_TUNE, PAD_DS_TUNE_DLY_SEL);
if (host->hs400_ds_dly3) sdr_clr_bits(host->base + PAD_DS_TUNE, PAD_DS_TUNE_DLY2_SEL);
sdr_set_field(host->base + PAD_DS_TUNE,
PAD_DS_TUNE_DLY3, host->hs400_ds_dly3);
} }
host->hs400_tuning = true; host->hs400_tuning = true;

View File

@@ -395,15 +395,16 @@ static int c_can_plat_probe(struct platform_device *pdev)
if (ret) { if (ret) {
dev_err(&pdev->dev, "registering %s failed (err=%d)\n", dev_err(&pdev->dev, "registering %s failed (err=%d)\n",
KBUILD_MODNAME, ret); KBUILD_MODNAME, ret);
goto exit_free_device; goto exit_pm_runtime;
} }
dev_info(&pdev->dev, "%s device registered (regs=%p, irq=%d)\n", dev_info(&pdev->dev, "%s device registered (regs=%p, irq=%d)\n",
KBUILD_MODNAME, priv->base, dev->irq); KBUILD_MODNAME, priv->base, dev->irq);
return 0; return 0;
exit_free_device: exit_pm_runtime:
pm_runtime_disable(priv->device); pm_runtime_disable(priv->device);
exit_free_device:
free_c_can_dev(dev); free_c_can_dev(dev);
exit: exit:
dev_err(&pdev->dev, "probe failed\n"); dev_err(&pdev->dev, "probe failed\n");

View File

@@ -867,10 +867,12 @@ static void ctucan_err_interrupt(struct net_device *ndev, u32 isr)
} }
break; break;
case CAN_STATE_ERROR_ACTIVE: case CAN_STATE_ERROR_ACTIVE:
cf->can_id |= CAN_ERR_CNT; if (skb) {
cf->data[1] = CAN_ERR_CRTL_ACTIVE; cf->can_id |= CAN_ERR_CNT;
cf->data[6] = bec.txerr; cf->data[1] = CAN_ERR_CRTL_ACTIVE;
cf->data[7] = bec.rxerr; cf->data[6] = bec.txerr;
cf->data[7] = bec.rxerr;
}
break; break;
default: default:
netdev_warn(ndev, "unhandled error state (%d:%s)!\n", netdev_warn(ndev, "unhandled error state (%d:%s)!\n",

View File

@@ -768,7 +768,9 @@ static void __mlxsw_sp_port_get_stats(struct net_device *dev,
err = mlxsw_sp_get_hw_stats_by_group(&hw_stats, &len, grp); err = mlxsw_sp_get_hw_stats_by_group(&hw_stats, &len, grp);
if (err) if (err)
return; return;
mlxsw_sp_port_get_stats_raw(dev, grp, prio, ppcnt_pl); err = mlxsw_sp_port_get_stats_raw(dev, grp, prio, ppcnt_pl);
if (err)
return;
for (i = 0; i < len; i++) { for (i = 0; i < len; i++) {
data[data_index + i] = hw_stats[i].getter(ppcnt_pl); data[data_index + i] = hw_stats[i].getter(ppcnt_pl);
if (!hw_stats[i].cells_bytes) if (!hw_stats[i].cells_bytes)

View File

@@ -345,6 +345,7 @@ static inline int is_omap1510_8250(struct uart_8250_port *pt)
#ifdef CONFIG_SERIAL_8250_DMA #ifdef CONFIG_SERIAL_8250_DMA
extern int serial8250_tx_dma(struct uart_8250_port *); extern int serial8250_tx_dma(struct uart_8250_port *);
extern void serial8250_tx_dma_flush(struct uart_8250_port *);
extern int serial8250_rx_dma(struct uart_8250_port *); extern int serial8250_rx_dma(struct uart_8250_port *);
extern void serial8250_rx_dma_flush(struct uart_8250_port *); extern void serial8250_rx_dma_flush(struct uart_8250_port *);
extern int serial8250_request_dma(struct uart_8250_port *); extern int serial8250_request_dma(struct uart_8250_port *);
@@ -377,6 +378,7 @@ static inline int serial8250_tx_dma(struct uart_8250_port *p)
{ {
return -1; return -1;
} }
static inline void serial8250_tx_dma_flush(struct uart_8250_port *p) { }
static inline int serial8250_rx_dma(struct uart_8250_port *p) static inline int serial8250_rx_dma(struct uart_8250_port *p)
{ {
return -1; return -1;

View File

@@ -133,6 +133,22 @@ err:
return ret; return ret;
} }
void serial8250_tx_dma_flush(struct uart_8250_port *p)
{
struct uart_8250_dma *dma = p->dma;
if (!dma->tx_running)
return;
/*
* kfifo_reset() has been called by the serial core, avoid
* advancing and underflowing in __dma_tx_complete().
*/
dma->tx_size = 0;
dmaengine_terminate_async(dma->rxchan);
}
int serial8250_rx_dma(struct uart_8250_port *p) int serial8250_rx_dma(struct uart_8250_port *p)
{ {
struct uart_8250_dma *dma = p->dma; struct uart_8250_dma *dma = p->dma;

View File

@@ -1975,7 +1975,6 @@ pci_moxa_setup(struct serial_private *priv,
#define PCI_DEVICE_ID_WCH_CH355_4S 0x7173 #define PCI_DEVICE_ID_WCH_CH355_4S 0x7173
#define PCI_VENDOR_ID_AGESTAR 0x5372 #define PCI_VENDOR_ID_AGESTAR 0x5372
#define PCI_DEVICE_ID_AGESTAR_9375 0x6872 #define PCI_DEVICE_ID_AGESTAR_9375 0x6872
#define PCI_VENDOR_ID_ASIX 0x9710
#define PCI_DEVICE_ID_BROADCOM_TRUMANAGE 0x160a #define PCI_DEVICE_ID_BROADCOM_TRUMANAGE 0x160a
#define PCI_DEVICE_ID_AMCC_ADDIDATA_APCI7800 0x818e #define PCI_DEVICE_ID_AMCC_ADDIDATA_APCI7800 0x818e

View File

@@ -2558,6 +2558,14 @@ static unsigned int npcm_get_divisor(struct uart_8250_port *up,
return DIV_ROUND_CLOSEST(port->uartclk, 16 * baud + 2) - 2; return DIV_ROUND_CLOSEST(port->uartclk, 16 * baud + 2) - 2;
} }
static void serial8250_flush_buffer(struct uart_port *port)
{
struct uart_8250_port *up = up_to_u8250p(port);
if (up->dma)
serial8250_tx_dma_flush(up);
}
static unsigned int serial8250_do_get_divisor(struct uart_port *port, static unsigned int serial8250_do_get_divisor(struct uart_port *port,
unsigned int baud, unsigned int baud,
unsigned int *frac) unsigned int *frac)
@@ -3273,6 +3281,7 @@ static const struct uart_ops serial8250_pops = {
.break_ctl = serial8250_break_ctl, .break_ctl = serial8250_break_ctl,
.startup = serial8250_startup, .startup = serial8250_startup,
.shutdown = serial8250_shutdown, .shutdown = serial8250_shutdown,
.flush_buffer = serial8250_flush_buffer,
.set_termios = serial8250_set_termios, .set_termios = serial8250_set_termios,
.set_ldisc = serial8250_set_ldisc, .set_ldisc = serial8250_set_ldisc,
.pm = serial8250_pm, .pm = serial8250_pm,

View File

@@ -360,7 +360,7 @@ static void acm_process_notification(struct acm *acm, unsigned char *buf)
static void acm_ctrl_irq(struct urb *urb) static void acm_ctrl_irq(struct urb *urb)
{ {
struct acm *acm = urb->context; struct acm *acm = urb->context;
struct usb_cdc_notification *dr = urb->transfer_buffer; struct usb_cdc_notification *dr;
unsigned int current_size = urb->actual_length; unsigned int current_size = urb->actual_length;
unsigned int expected_size, copy_size, alloc_size; unsigned int expected_size, copy_size, alloc_size;
int retval; int retval;
@@ -387,14 +387,25 @@ static void acm_ctrl_irq(struct urb *urb)
usb_mark_last_busy(acm->dev); usb_mark_last_busy(acm->dev);
if (acm->nb_index) if (acm->nb_index == 0) {
/*
* The first chunk of a message must contain at least the
* notification header with the length field, otherwise we
* can't get an expected_size.
*/
if (current_size < sizeof(struct usb_cdc_notification)) {
dev_dbg(&acm->control->dev, "urb too short\n");
goto exit;
}
dr = urb->transfer_buffer;
} else {
dr = (struct usb_cdc_notification *)acm->notification_buffer; dr = (struct usb_cdc_notification *)acm->notification_buffer;
}
/* size = notification-header + (optional) data */ /* size = notification-header + (optional) data */
expected_size = sizeof(struct usb_cdc_notification) + expected_size = sizeof(struct usb_cdc_notification) +
le16_to_cpu(dr->wLength); le16_to_cpu(dr->wLength);
if (current_size < expected_size) { if (acm->nb_index != 0 || current_size < expected_size) {
/* notification is transmitted fragmented, reassemble */ /* notification is transmitted fragmented, reassemble */
if (acm->nb_size < expected_size) { if (acm->nb_size < expected_size) {
u8 *new_buffer; u8 *new_buffer;
@@ -1703,13 +1714,16 @@ static const struct usb_device_id acm_ids[] = {
{ USB_DEVICE(0x0870, 0x0001), /* Metricom GS Modem */ { USB_DEVICE(0x0870, 0x0001), /* Metricom GS Modem */
.driver_info = NO_UNION_NORMAL, /* has no union descriptor */ .driver_info = NO_UNION_NORMAL, /* has no union descriptor */
}, },
{ USB_DEVICE(0x045b, 0x023c), /* Renesas USB Download mode */ { USB_DEVICE(0x045b, 0x023c), /* Renesas R-Car H3 USB Download mode */
.driver_info = DISABLE_ECHO, /* Don't echo banner */ .driver_info = DISABLE_ECHO, /* Don't echo banner */
}, },
{ USB_DEVICE(0x045b, 0x0248), /* Renesas USB Download mode */ { USB_DEVICE(0x045b, 0x0247), /* Renesas R-Car D3 USB Download mode */
.driver_info = DISABLE_ECHO, /* Don't echo banner */ .driver_info = DISABLE_ECHO, /* Don't echo banner */
}, },
{ USB_DEVICE(0x045b, 0x024D), /* Renesas USB Download mode */ { USB_DEVICE(0x045b, 0x0248), /* Renesas R-Car M3-N USB Download mode */
.driver_info = DISABLE_ECHO, /* Don't echo banner */
},
{ USB_DEVICE(0x045b, 0x024D), /* Renesas R-Car E3 USB Download mode */
.driver_info = DISABLE_ECHO, /* Don't echo banner */ .driver_info = DISABLE_ECHO, /* Don't echo banner */
}, },
{ USB_DEVICE(0x0e8d, 0x0003), /* FIREFLY, MediaTek Inc; andrey.arapov@gmail.com */ { USB_DEVICE(0x0e8d, 0x0003), /* FIREFLY, MediaTek Inc; andrey.arapov@gmail.com */

View File

@@ -1818,6 +1818,17 @@ static int hub_probe(struct usb_interface *intf, const struct usb_device_id *id)
desc = intf->cur_altsetting; desc = intf->cur_altsetting;
hdev = interface_to_usbdev(intf); hdev = interface_to_usbdev(intf);
/*
* The USB 2.0 spec prohibits hubs from having more than one
* configuration or interface, and we rely on this prohibition.
* Refuse to accept a device that violates it.
*/
if (hdev->descriptor.bNumConfigurations > 1 ||
hdev->actconfig->desc.bNumInterfaces > 1) {
dev_err(&intf->dev, "Invalid hub with more than one config or interface\n");
return -EINVAL;
}
/* /*
* Set default autosuspend delay as 0 to speedup bus suspend, * Set default autosuspend delay as 0 to speedup bus suspend,
* based on the below considerations: * based on the below considerations:
@@ -4718,7 +4729,6 @@ void usb_ep0_reinit(struct usb_device *udev)
EXPORT_SYMBOL_GPL(usb_ep0_reinit); EXPORT_SYMBOL_GPL(usb_ep0_reinit);
#define usb_sndaddr0pipe() (PIPE_CONTROL << 30) #define usb_sndaddr0pipe() (PIPE_CONTROL << 30)
#define usb_rcvaddr0pipe() ((PIPE_CONTROL << 30) | USB_DIR_IN)
static int hub_set_address(struct usb_device *udev, int devnum) static int hub_set_address(struct usb_device *udev, int devnum)
{ {
@@ -4824,7 +4834,7 @@ static int get_bMaxPacketSize0(struct usb_device *udev,
for (i = 0; i < GET_MAXPACKET0_TRIES; ++i) { for (i = 0; i < GET_MAXPACKET0_TRIES; ++i) {
/* Start with invalid values in case the transfer fails */ /* Start with invalid values in case the transfer fails */
buf->bDescriptorType = buf->bMaxPacketSize0 = 0; buf->bDescriptorType = buf->bMaxPacketSize0 = 0;
rc = usb_control_msg(udev, usb_rcvaddr0pipe(), rc = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0),
USB_REQ_GET_DESCRIPTOR, USB_DIR_IN, USB_REQ_GET_DESCRIPTOR, USB_DIR_IN,
USB_DT_DEVICE << 8, 0, USB_DT_DEVICE << 8, 0,
buf, size, buf, size,

View File

@@ -432,6 +432,9 @@ static const struct usb_device_id usb_quirk_list[] = {
{ USB_DEVICE(0x0c45, 0x7056), .driver_info = { USB_DEVICE(0x0c45, 0x7056), .driver_info =
USB_QUIRK_IGNORE_REMOTE_WAKEUP }, USB_QUIRK_IGNORE_REMOTE_WAKEUP },
/* Sony Xperia XZ1 Compact (lilac) smartphone in fastboot mode */
{ USB_DEVICE(0x0fce, 0x0dde), .driver_info = USB_QUIRK_NO_LPM },
/* Action Semiconductor flash disk */ /* Action Semiconductor flash disk */
{ USB_DEVICE(0x10d6, 0x2200), .driver_info = { USB_DEVICE(0x10d6, 0x2200), .driver_info =
USB_QUIRK_STRING_FETCH_255 }, USB_QUIRK_STRING_FETCH_255 },
@@ -522,6 +525,9 @@ static const struct usb_device_id usb_quirk_list[] = {
/* Blackmagic Design UltraStudio SDI */ /* Blackmagic Design UltraStudio SDI */
{ USB_DEVICE(0x1edb, 0xbd4f), .driver_info = USB_QUIRK_NO_LPM }, { USB_DEVICE(0x1edb, 0xbd4f), .driver_info = USB_QUIRK_NO_LPM },
/* Teclast disk */
{ USB_DEVICE(0x1f75, 0x0917), .driver_info = USB_QUIRK_NO_LPM },
/* Hauppauge HVR-950q */ /* Hauppauge HVR-950q */
{ USB_DEVICE(0x2040, 0x7200), .driver_info = { USB_DEVICE(0x2040, 0x7200), .driver_info =
USB_QUIRK_CONFIG_INTF_STRINGS }, USB_QUIRK_CONFIG_INTF_STRINGS },

View File

@@ -4613,6 +4613,7 @@ static int dwc2_hsotg_udc_stop(struct usb_gadget *gadget)
spin_lock_irqsave(&hsotg->lock, flags); spin_lock_irqsave(&hsotg->lock, flags);
hsotg->driver = NULL; hsotg->driver = NULL;
hsotg->gadget.dev.of_node = NULL;
hsotg->gadget.speed = USB_SPEED_UNKNOWN; hsotg->gadget.speed = USB_SPEED_UNKNOWN;
hsotg->enabled = 0; hsotg->enabled = 0;

View File

@@ -999,11 +999,11 @@ static int f_midi_bind(struct usb_configuration *c, struct usb_function *f)
} }
/* configure the endpoint descriptors ... */ /* configure the endpoint descriptors ... */
ms_out_desc.bLength = USB_DT_MS_ENDPOINT_SIZE(midi->in_ports); ms_out_desc.bLength = USB_DT_MS_ENDPOINT_SIZE(midi->out_ports);
ms_out_desc.bNumEmbMIDIJack = midi->in_ports; ms_out_desc.bNumEmbMIDIJack = midi->out_ports;
ms_in_desc.bLength = USB_DT_MS_ENDPOINT_SIZE(midi->out_ports); ms_in_desc.bLength = USB_DT_MS_ENDPOINT_SIZE(midi->in_ports);
ms_in_desc.bNumEmbMIDIJack = midi->out_ports; ms_in_desc.bNumEmbMIDIJack = midi->in_ports;
/* ... and add them to the list */ /* ... and add them to the list */
endpoint_descriptor_index = i; endpoint_descriptor_index = i;

View File

@@ -309,7 +309,7 @@ struct renesas_usb3_request {
struct list_head queue; struct list_head queue;
}; };
#define USB3_EP_NAME_SIZE 8 #define USB3_EP_NAME_SIZE 16
struct renesas_usb3_ep { struct renesas_usb3_ep {
struct usb_ep ep; struct usb_ep ep;
struct renesas_usb3 *usb3; struct renesas_usb3 *usb3;

View File

@@ -946,6 +946,15 @@ static void quirk_usb_disable_ehci(struct pci_dev *pdev)
* booting from USB disk or using a usb keyboard * booting from USB disk or using a usb keyboard
*/ */
hcc_params = readl(base + EHCI_HCC_PARAMS); hcc_params = readl(base + EHCI_HCC_PARAMS);
/* LS7A EHCI controller doesn't have extended capabilities, the
* EECP (EHCI Extended Capabilities Pointer) field of HCCPARAMS
* register should be 0x0 but it reads as 0xa0. So clear it to
* avoid error messages on boot.
*/
if (pdev->vendor == PCI_VENDOR_ID_LOONGSON && pdev->device == 0x7a14)
hcc_params &= ~(0xffL << 8);
offset = (hcc_params >> 8) & 0xff; offset = (hcc_params >> 8) & 0xff;
while (offset && --count) { while (offset && --count) {
pci_read_config_dword(pdev, offset, &cap); pci_read_config_dword(pdev, offset, &cap);

View File

@@ -619,15 +619,6 @@ static void option_instat_callback(struct urb *urb);
/* Luat Air72*U series based on UNISOC UIS8910 uses UNISOC's vendor ID */ /* Luat Air72*U series based on UNISOC UIS8910 uses UNISOC's vendor ID */
#define LUAT_PRODUCT_AIR720U 0x4e00 #define LUAT_PRODUCT_AIR720U 0x4e00
/* MeiG Smart Technology products */
#define MEIGSMART_VENDOR_ID 0x2dee
/* MeiG Smart SRM815/SRM825L based on Qualcomm 315 */
#define MEIGSMART_PRODUCT_SRM825L 0x4d22
/* MeiG Smart SLM320 based on UNISOC UIS8910 */
#define MEIGSMART_PRODUCT_SLM320 0x4d41
/* MeiG Smart SLM770A based on ASR1803 */
#define MEIGSMART_PRODUCT_SLM770A 0x4d57
/* Device flags */ /* Device flags */
/* Highest interface number which can be used with NCTRL() and RSVD() */ /* Highest interface number which can be used with NCTRL() and RSVD() */
@@ -1367,15 +1358,15 @@ static const struct usb_device_id option_ids[] = {
.driver_info = NCTRL(2) | RSVD(3) }, .driver_info = NCTRL(2) | RSVD(3) },
{ USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x1063, 0xff), /* Telit LN920 (ECM) */ { USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x1063, 0xff), /* Telit LN920 (ECM) */
.driver_info = NCTRL(0) | RSVD(1) }, .driver_info = NCTRL(0) | RSVD(1) },
{ USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x1070, 0xff), /* Telit FN990 (rmnet) */ { USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x1070, 0xff), /* Telit FN990A (rmnet) */
.driver_info = NCTRL(0) | RSVD(1) | RSVD(2) }, .driver_info = NCTRL(0) | RSVD(1) | RSVD(2) },
{ USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x1071, 0xff), /* Telit FN990 (MBIM) */ { USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x1071, 0xff), /* Telit FN990A (MBIM) */
.driver_info = NCTRL(0) | RSVD(1) }, .driver_info = NCTRL(0) | RSVD(1) },
{ USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x1072, 0xff), /* Telit FN990 (RNDIS) */ { USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x1072, 0xff), /* Telit FN990A (RNDIS) */
.driver_info = NCTRL(2) | RSVD(3) }, .driver_info = NCTRL(2) | RSVD(3) },
{ USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x1073, 0xff), /* Telit FN990 (ECM) */ { USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x1073, 0xff), /* Telit FN990A (ECM) */
.driver_info = NCTRL(0) | RSVD(1) }, .driver_info = NCTRL(0) | RSVD(1) },
{ USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x1075, 0xff), /* Telit FN990 (PCIe) */ { USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x1075, 0xff), /* Telit FN990A (PCIe) */
.driver_info = RSVD(0) }, .driver_info = RSVD(0) },
{ USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x1080, 0xff), /* Telit FE990 (rmnet) */ { USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x1080, 0xff), /* Telit FE990 (rmnet) */
.driver_info = NCTRL(0) | RSVD(1) | RSVD(2) }, .driver_info = NCTRL(0) | RSVD(1) | RSVD(2) },
@@ -1403,6 +1394,22 @@ static const struct usb_device_id option_ids[] = {
.driver_info = RSVD(0) | NCTRL(3) }, .driver_info = RSVD(0) | NCTRL(3) },
{ USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x10c8, 0xff), /* Telit FE910C04 (rmnet) */ { USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x10c8, 0xff), /* Telit FE910C04 (rmnet) */
.driver_info = RSVD(0) | NCTRL(2) | RSVD(3) | RSVD(4) }, .driver_info = RSVD(0) | NCTRL(2) | RSVD(3) | RSVD(4) },
{ USB_DEVICE_INTERFACE_PROTOCOL(TELIT_VENDOR_ID, 0x10d0, 0x60) }, /* Telit FN990B (rmnet) */
{ USB_DEVICE_INTERFACE_PROTOCOL(TELIT_VENDOR_ID, 0x10d0, 0x40) },
{ USB_DEVICE_INTERFACE_PROTOCOL(TELIT_VENDOR_ID, 0x10d0, 0x30),
.driver_info = NCTRL(5) },
{ USB_DEVICE_INTERFACE_PROTOCOL(TELIT_VENDOR_ID, 0x10d1, 0x60) }, /* Telit FN990B (MBIM) */
{ USB_DEVICE_INTERFACE_PROTOCOL(TELIT_VENDOR_ID, 0x10d1, 0x40) },
{ USB_DEVICE_INTERFACE_PROTOCOL(TELIT_VENDOR_ID, 0x10d1, 0x30),
.driver_info = NCTRL(6) },
{ USB_DEVICE_INTERFACE_PROTOCOL(TELIT_VENDOR_ID, 0x10d2, 0x60) }, /* Telit FN990B (RNDIS) */
{ USB_DEVICE_INTERFACE_PROTOCOL(TELIT_VENDOR_ID, 0x10d2, 0x40) },
{ USB_DEVICE_INTERFACE_PROTOCOL(TELIT_VENDOR_ID, 0x10d2, 0x30),
.driver_info = NCTRL(6) },
{ USB_DEVICE_INTERFACE_PROTOCOL(TELIT_VENDOR_ID, 0x10d3, 0x60) }, /* Telit FN990B (ECM) */
{ USB_DEVICE_INTERFACE_PROTOCOL(TELIT_VENDOR_ID, 0x10d3, 0x40) },
{ USB_DEVICE_INTERFACE_PROTOCOL(TELIT_VENDOR_ID, 0x10d3, 0x30),
.driver_info = NCTRL(6) },
{ USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_ME910), { USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_ME910),
.driver_info = NCTRL(0) | RSVD(1) | RSVD(3) }, .driver_info = NCTRL(0) | RSVD(1) | RSVD(3) },
{ USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_ME910_DUAL_MODEM), { USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_ME910_DUAL_MODEM),
@@ -2347,6 +2354,14 @@ static const struct usb_device_id option_ids[] = {
{ USB_DEVICE_INTERFACE_CLASS(0x2cb7, 0x0a05, 0xff) }, /* Fibocom FM650-CN (NCM mode) */ { USB_DEVICE_INTERFACE_CLASS(0x2cb7, 0x0a05, 0xff) }, /* Fibocom FM650-CN (NCM mode) */
{ USB_DEVICE_INTERFACE_CLASS(0x2cb7, 0x0a06, 0xff) }, /* Fibocom FM650-CN (RNDIS mode) */ { USB_DEVICE_INTERFACE_CLASS(0x2cb7, 0x0a06, 0xff) }, /* Fibocom FM650-CN (RNDIS mode) */
{ USB_DEVICE_INTERFACE_CLASS(0x2cb7, 0x0a07, 0xff) }, /* Fibocom FM650-CN (MBIM mode) */ { USB_DEVICE_INTERFACE_CLASS(0x2cb7, 0x0a07, 0xff) }, /* Fibocom FM650-CN (MBIM mode) */
{ USB_DEVICE_AND_INTERFACE_INFO(0x2dee, 0x4d41, 0xff, 0, 0) }, /* MeiG Smart SLM320 */
{ USB_DEVICE_AND_INTERFACE_INFO(0x2dee, 0x4d57, 0xff, 0, 0) }, /* MeiG Smart SLM770A */
{ USB_DEVICE_AND_INTERFACE_INFO(0x2dee, 0x4d22, 0xff, 0, 0) }, /* MeiG Smart SRM815 */
{ USB_DEVICE_AND_INTERFACE_INFO(0x2dee, 0x4d22, 0xff, 0x10, 0x02) }, /* MeiG Smart SLM828 */
{ USB_DEVICE_AND_INTERFACE_INFO(0x2dee, 0x4d22, 0xff, 0x10, 0x03) }, /* MeiG Smart SLM828 */
{ USB_DEVICE_AND_INTERFACE_INFO(0x2dee, 0x4d22, 0xff, 0xff, 0x30) }, /* MeiG Smart SRM815 and SRM825L */
{ USB_DEVICE_AND_INTERFACE_INFO(0x2dee, 0x4d22, 0xff, 0xff, 0x40) }, /* MeiG Smart SRM825L */
{ USB_DEVICE_AND_INTERFACE_INFO(0x2dee, 0x4d22, 0xff, 0xff, 0x60) }, /* MeiG Smart SRM825L */
{ USB_DEVICE_INTERFACE_CLASS(0x2df3, 0x9d03, 0xff) }, /* LongSung M5710 */ { USB_DEVICE_INTERFACE_CLASS(0x2df3, 0x9d03, 0xff) }, /* LongSung M5710 */
{ USB_DEVICE_INTERFACE_CLASS(0x305a, 0x1404, 0xff) }, /* GosunCn GM500 RNDIS */ { USB_DEVICE_INTERFACE_CLASS(0x305a, 0x1404, 0xff) }, /* GosunCn GM500 RNDIS */
{ USB_DEVICE_INTERFACE_CLASS(0x305a, 0x1405, 0xff) }, /* GosunCn GM500 MBIM */ { USB_DEVICE_INTERFACE_CLASS(0x305a, 0x1405, 0xff) }, /* GosunCn GM500 MBIM */
@@ -2403,12 +2418,6 @@ static const struct usb_device_id option_ids[] = {
{ USB_DEVICE_AND_INTERFACE_INFO(SIERRA_VENDOR_ID, SIERRA_PRODUCT_EM9191, 0xff, 0, 0) }, { USB_DEVICE_AND_INTERFACE_INFO(SIERRA_VENDOR_ID, SIERRA_PRODUCT_EM9191, 0xff, 0, 0) },
{ USB_DEVICE_AND_INTERFACE_INFO(UNISOC_VENDOR_ID, TOZED_PRODUCT_LT70C, 0xff, 0, 0) }, { USB_DEVICE_AND_INTERFACE_INFO(UNISOC_VENDOR_ID, TOZED_PRODUCT_LT70C, 0xff, 0, 0) },
{ USB_DEVICE_AND_INTERFACE_INFO(UNISOC_VENDOR_ID, LUAT_PRODUCT_AIR720U, 0xff, 0, 0) }, { USB_DEVICE_AND_INTERFACE_INFO(UNISOC_VENDOR_ID, LUAT_PRODUCT_AIR720U, 0xff, 0, 0) },
{ USB_DEVICE_AND_INTERFACE_INFO(MEIGSMART_VENDOR_ID, MEIGSMART_PRODUCT_SLM320, 0xff, 0, 0) },
{ USB_DEVICE_AND_INTERFACE_INFO(MEIGSMART_VENDOR_ID, MEIGSMART_PRODUCT_SLM770A, 0xff, 0, 0) },
{ USB_DEVICE_AND_INTERFACE_INFO(MEIGSMART_VENDOR_ID, MEIGSMART_PRODUCT_SRM825L, 0xff, 0, 0) },
{ USB_DEVICE_AND_INTERFACE_INFO(MEIGSMART_VENDOR_ID, MEIGSMART_PRODUCT_SRM825L, 0xff, 0xff, 0x30) },
{ USB_DEVICE_AND_INTERFACE_INFO(MEIGSMART_VENDOR_ID, MEIGSMART_PRODUCT_SRM825L, 0xff, 0xff, 0x40) },
{ USB_DEVICE_AND_INTERFACE_INFO(MEIGSMART_VENDOR_ID, MEIGSMART_PRODUCT_SRM825L, 0xff, 0xff, 0x60) },
{ USB_DEVICE_INTERFACE_CLASS(0x1bbb, 0x0530, 0xff), /* TCL IK512 MBIM */ { USB_DEVICE_INTERFACE_CLASS(0x1bbb, 0x0530, 0xff), /* TCL IK512 MBIM */
.driver_info = NCTRL(1) }, .driver_info = NCTRL(1) },
{ USB_DEVICE_INTERFACE_CLASS(0x1bbb, 0x0640, 0xff), /* TCL IK512 ECM */ { USB_DEVICE_INTERFACE_CLASS(0x1bbb, 0x0640, 0xff), /* TCL IK512 ECM */

View File

@@ -1122,7 +1122,6 @@ static int btrfs_write_check(struct kiocb *iocb, struct iov_iter *from,
loff_t pos = iocb->ki_pos; loff_t pos = iocb->ki_pos;
int ret; int ret;
loff_t oldsize; loff_t oldsize;
loff_t start_pos;
/* /*
* Quickly bail out on NOWAIT writes if we don't have the nodatacow or * Quickly bail out on NOWAIT writes if we don't have the nodatacow or
@@ -1147,9 +1146,8 @@ static int btrfs_write_check(struct kiocb *iocb, struct iov_iter *from,
*/ */
update_time_for_write(inode); update_time_for_write(inode);
start_pos = round_down(pos, fs_info->sectorsize);
oldsize = i_size_read(inode); oldsize = i_size_read(inode);
if (start_pos > oldsize) { if (pos > oldsize) {
/* Expand hole size to cover write data, preventing empty gap */ /* Expand hole size to cover write data, preventing empty gap */
loff_t end_pos = round_up(pos + count, fs_info->sectorsize); loff_t end_pos = round_up(pos + count, fs_info->sectorsize);

View File

@@ -162,7 +162,7 @@ static int nilfs_writepages(struct address_space *mapping,
int err = 0; int err = 0;
if (sb_rdonly(inode->i_sb)) { if (sb_rdonly(inode->i_sb)) {
nilfs_clear_dirty_pages(mapping, false); nilfs_clear_dirty_pages(mapping);
return -EROFS; return -EROFS;
} }
@@ -185,7 +185,7 @@ static int nilfs_writepage(struct page *page, struct writeback_control *wbc)
* have dirty pages that try to be flushed in background. * have dirty pages that try to be flushed in background.
* So, here we simply discard this dirty page. * So, here we simply discard this dirty page.
*/ */
nilfs_clear_dirty_page(page, false); nilfs_clear_dirty_page(page);
unlock_page(page); unlock_page(page);
return -EROFS; return -EROFS;
} }

View File

@@ -411,7 +411,7 @@ nilfs_mdt_write_page(struct page *page, struct writeback_control *wbc)
* have dirty pages that try to be flushed in background. * have dirty pages that try to be flushed in background.
* So, here we simply discard this dirty page. * So, here we simply discard this dirty page.
*/ */
nilfs_clear_dirty_page(page, false); nilfs_clear_dirty_page(page);
unlock_page(page); unlock_page(page);
return -EROFS; return -EROFS;
} }
@@ -634,10 +634,10 @@ void nilfs_mdt_restore_from_shadow_map(struct inode *inode)
if (mi->mi_palloc_cache) if (mi->mi_palloc_cache)
nilfs_palloc_clear_cache(inode); nilfs_palloc_clear_cache(inode);
nilfs_clear_dirty_pages(inode->i_mapping, true); nilfs_clear_dirty_pages(inode->i_mapping);
nilfs_copy_back_pages(inode->i_mapping, shadow->inode->i_mapping); nilfs_copy_back_pages(inode->i_mapping, shadow->inode->i_mapping);
nilfs_clear_dirty_pages(ii->i_assoc_inode->i_mapping, true); nilfs_clear_dirty_pages(ii->i_assoc_inode->i_mapping);
nilfs_copy_back_pages(ii->i_assoc_inode->i_mapping, nilfs_copy_back_pages(ii->i_assoc_inode->i_mapping,
NILFS_I(shadow->inode)->i_assoc_inode->i_mapping); NILFS_I(shadow->inode)->i_assoc_inode->i_mapping);

View File

@@ -354,9 +354,8 @@ repeat:
/** /**
* nilfs_clear_dirty_pages - discard dirty pages in address space * nilfs_clear_dirty_pages - discard dirty pages in address space
* @mapping: address space with dirty pages for discarding * @mapping: address space with dirty pages for discarding
* @silent: suppress [true] or print [false] warning messages
*/ */
void nilfs_clear_dirty_pages(struct address_space *mapping, bool silent) void nilfs_clear_dirty_pages(struct address_space *mapping)
{ {
struct pagevec pvec; struct pagevec pvec;
unsigned int i; unsigned int i;
@@ -377,7 +376,7 @@ void nilfs_clear_dirty_pages(struct address_space *mapping, bool silent)
* was acquired. Skip processing in that case. * was acquired. Skip processing in that case.
*/ */
if (likely(page->mapping == mapping)) if (likely(page->mapping == mapping))
nilfs_clear_dirty_page(page, silent); nilfs_clear_dirty_page(page);
unlock_page(page); unlock_page(page);
} }
@@ -389,44 +388,54 @@ void nilfs_clear_dirty_pages(struct address_space *mapping, bool silent)
/** /**
* nilfs_clear_dirty_page - discard dirty page * nilfs_clear_dirty_page - discard dirty page
* @page: dirty page that will be discarded * @page: dirty page that will be discarded
* @silent: suppress [true] or print [false] warning messages *
* nilfs_clear_dirty_page() clears working states including dirty state for
* the page and its buffers. If the page has buffers, clear only if it is
* confirmed that none of the buffer heads are busy (none have valid
* references and none are locked).
*/ */
void nilfs_clear_dirty_page(struct page *page, bool silent) void nilfs_clear_dirty_page(struct page *page)
{ {
struct inode *inode = page->mapping->host;
struct super_block *sb = inode->i_sb;
BUG_ON(!PageLocked(page)); BUG_ON(!PageLocked(page));
if (!silent)
nilfs_warn(sb, "discard dirty page: offset=%lld, ino=%lu",
page_offset(page), inode->i_ino);
ClearPageUptodate(page);
ClearPageMappedToDisk(page);
ClearPageChecked(page);
if (page_has_buffers(page)) { if (page_has_buffers(page)) {
struct buffer_head *bh, *head; struct buffer_head *bh, *head = page_buffers(page);
const unsigned long clear_bits = const unsigned long clear_bits =
(BIT(BH_Uptodate) | BIT(BH_Dirty) | BIT(BH_Mapped) | (BIT(BH_Uptodate) | BIT(BH_Dirty) | BIT(BH_Mapped) |
BIT(BH_Async_Write) | BIT(BH_NILFS_Volatile) | BIT(BH_Async_Write) | BIT(BH_NILFS_Volatile) |
BIT(BH_NILFS_Checked) | BIT(BH_NILFS_Redirected) | BIT(BH_NILFS_Checked) | BIT(BH_NILFS_Redirected) |
BIT(BH_Delay)); BIT(BH_Delay));
bool busy, invalidated = false;
bh = head = page_buffers(page); recheck_buffers:
busy = false;
bh = head;
do {
if (atomic_read(&bh->b_count) | buffer_locked(bh)) {
busy = true;
break;
}
} while (bh = bh->b_this_page, bh != head);
if (busy) {
if (invalidated)
return;
invalidate_bh_lrus();
invalidated = true;
goto recheck_buffers;
}
bh = head;
do { do {
lock_buffer(bh); lock_buffer(bh);
if (!silent)
nilfs_warn(sb,
"discard dirty block: blocknr=%llu, size=%zu",
(u64)bh->b_blocknr, bh->b_size);
set_mask_bits(&bh->b_state, clear_bits, 0); set_mask_bits(&bh->b_state, clear_bits, 0);
unlock_buffer(bh); unlock_buffer(bh);
} while (bh = bh->b_this_page, bh != head); } while (bh = bh->b_this_page, bh != head);
} }
ClearPageUptodate(page);
ClearPageMappedToDisk(page);
ClearPageChecked(page);
__nilfs_clear_page_dirty(page); __nilfs_clear_page_dirty(page);
} }

View File

@@ -41,8 +41,8 @@ void nilfs_page_bug(struct page *);
int nilfs_copy_dirty_pages(struct address_space *, struct address_space *); int nilfs_copy_dirty_pages(struct address_space *, struct address_space *);
void nilfs_copy_back_pages(struct address_space *, struct address_space *); void nilfs_copy_back_pages(struct address_space *, struct address_space *);
void nilfs_clear_dirty_page(struct page *, bool); void nilfs_clear_dirty_page(struct page *page);
void nilfs_clear_dirty_pages(struct address_space *, bool); void nilfs_clear_dirty_pages(struct address_space *mapping);
unsigned int nilfs_page_count_clean_buffers(struct page *, unsigned int, unsigned int nilfs_page_count_clean_buffers(struct page *, unsigned int,
unsigned int); unsigned int);
unsigned long nilfs_find_uncommitted_extent(struct inode *inode, unsigned long nilfs_find_uncommitted_extent(struct inode *inode,

View File

@@ -732,7 +732,6 @@ static size_t nilfs_lookup_dirty_data_buffers(struct inode *inode,
} }
if (!page_has_buffers(page)) if (!page_has_buffers(page))
create_empty_buffers(page, i_blocksize(inode), 0); create_empty_buffers(page, i_blocksize(inode), 0);
unlock_page(page);
bh = head = page_buffers(page); bh = head = page_buffers(page);
do { do {
@@ -742,11 +741,14 @@ static size_t nilfs_lookup_dirty_data_buffers(struct inode *inode,
list_add_tail(&bh->b_assoc_buffers, listp); list_add_tail(&bh->b_assoc_buffers, listp);
ndirties++; ndirties++;
if (unlikely(ndirties >= nlimit)) { if (unlikely(ndirties >= nlimit)) {
unlock_page(page);
pagevec_release(&pvec); pagevec_release(&pvec);
cond_resched(); cond_resched();
return ndirties; return ndirties;
} }
} while (bh = bh->b_this_page, bh != head); } while (bh = bh->b_this_page, bh != head);
unlock_page(page);
} }
pagevec_release(&pvec); pagevec_release(&pvec);
cond_resched(); cond_resched();

View File

@@ -71,9 +71,6 @@ enum {
/* Cgroup is frozen. */ /* Cgroup is frozen. */
CGRP_FROZEN, CGRP_FROZEN,
/* Control group has to be killed. */
CGRP_KILL,
}; };
/* cgroup_root->flags */ /* cgroup_root->flags */
@@ -424,6 +421,9 @@ struct cgroup {
int nr_threaded_children; /* # of live threaded child cgroups */ int nr_threaded_children; /* # of live threaded child cgroups */
/* sequence number for cgroup.kill, serialized by css_set_lock. */
unsigned int kill_seq;
struct kernfs_node *kn; /* cgroup kernfs entry */ struct kernfs_node *kn; /* cgroup kernfs entry */
struct cgroup_file procs_file; /* handle for "cgroup.procs" */ struct cgroup_file procs_file; /* handle for "cgroup.procs" */
struct cgroup_file events_file; /* handle for "cgroup.events" */ struct cgroup_file events_file; /* handle for "cgroup.events" */

View File

@@ -125,6 +125,7 @@ typedef struct {
#define EFI_MEMORY_RO ((u64)0x0000000000020000ULL) /* read-only */ #define EFI_MEMORY_RO ((u64)0x0000000000020000ULL) /* read-only */
#define EFI_MEMORY_SP ((u64)0x0000000000040000ULL) /* soft reserved */ #define EFI_MEMORY_SP ((u64)0x0000000000040000ULL) /* soft reserved */
#define EFI_MEMORY_CPU_CRYPTO ((u64)0x0000000000080000ULL) /* supports encryption */ #define EFI_MEMORY_CPU_CRYPTO ((u64)0x0000000000080000ULL) /* supports encryption */
#define EFI_MEMORY_HOT_PLUGGABLE BIT_ULL(20) /* supports unplugging at runtime */
#define EFI_MEMORY_RUNTIME ((u64)0x8000000000000000ULL) /* range requires runtime mapping */ #define EFI_MEMORY_RUNTIME ((u64)0x8000000000000000ULL) /* range requires runtime mapping */
#define EFI_MEMORY_DESCRIPTOR_VERSION 1 #define EFI_MEMORY_DESCRIPTOR_VERSION 1

View File

@@ -1153,7 +1153,7 @@ u32 iommu_sva_get_pasid(struct iommu_sva *handle);
static inline struct iommu_sva * static inline struct iommu_sva *
iommu_sva_bind_device(struct device *dev, struct mm_struct *mm) iommu_sva_bind_device(struct device *dev, struct mm_struct *mm)
{ {
return NULL; return ERR_PTR(-ENODEV);
} }
static inline void iommu_sva_unbind_device(struct iommu_sva *handle) static inline void iommu_sva_unbind_device(struct iommu_sva *handle)

View File

@@ -2576,6 +2576,12 @@ struct net *dev_net(const struct net_device *dev)
return read_pnet(&dev->nd_net); return read_pnet(&dev->nd_net);
} }
static inline
struct net *dev_net_rcu(const struct net_device *dev)
{
return read_pnet_rcu(&dev->nd_net);
}
static inline static inline
void dev_net_set(struct net_device *dev, struct net *net) void dev_net_set(struct net_device *dev, struct net *net)
{ {

View File

@@ -1754,6 +1754,10 @@
#define PCI_SUBDEVICE_ID_AT_2700FX 0x2701 #define PCI_SUBDEVICE_ID_AT_2700FX 0x2701
#define PCI_SUBDEVICE_ID_AT_2701FX 0x2703 #define PCI_SUBDEVICE_ID_AT_2701FX 0x2703
#define PCI_VENDOR_ID_ASIX 0x125b
#define PCI_DEVICE_ID_ASIX_AX99100 0x9100
#define PCI_DEVICE_ID_ASIX_AX99100_LB 0x9110
#define PCI_VENDOR_ID_ESS 0x125d #define PCI_VENDOR_ID_ESS 0x125d
#define PCI_DEVICE_ID_ESS_ESS1968 0x1968 #define PCI_DEVICE_ID_ESS_ESS1968 0x1968
#define PCI_DEVICE_ID_ESS_ESS1978 0x1978 #define PCI_DEVICE_ID_ESS_ESS1978 0x1978

View File

@@ -38,6 +38,7 @@ struct kernel_clone_args {
void *fn_arg; void *fn_arg;
struct cgroup *cgrp; struct cgroup *cgrp;
struct css_set *cset; struct css_set *cset;
unsigned int kill_seq;
}; };
/* /*

View File

@@ -382,21 +382,30 @@ static inline void put_net_track(struct net *net, netns_tracker *tracker)
typedef struct { typedef struct {
#ifdef CONFIG_NET_NS #ifdef CONFIG_NET_NS
struct net *net; struct net __rcu *net;
#endif #endif
} possible_net_t; } possible_net_t;
static inline void write_pnet(possible_net_t *pnet, struct net *net) static inline void write_pnet(possible_net_t *pnet, struct net *net)
{ {
#ifdef CONFIG_NET_NS #ifdef CONFIG_NET_NS
pnet->net = net; rcu_assign_pointer(pnet->net, net);
#endif #endif
} }
static inline struct net *read_pnet(const possible_net_t *pnet) static inline struct net *read_pnet(const possible_net_t *pnet)
{ {
#ifdef CONFIG_NET_NS #ifdef CONFIG_NET_NS
return pnet->net; return rcu_dereference_protected(pnet->net, true);
#else
return &init_net;
#endif
}
static inline struct net *read_pnet_rcu(const possible_net_t *pnet)
{
#ifdef CONFIG_NET_NS
return rcu_dereference(pnet->net);
#else #else
return &init_net; return &init_net;
#endif #endif

View File

@@ -362,10 +362,15 @@ static inline int inet_iif(const struct sk_buff *skb)
static inline int ip4_dst_hoplimit(const struct dst_entry *dst) static inline int ip4_dst_hoplimit(const struct dst_entry *dst)
{ {
int hoplimit = dst_metric_raw(dst, RTAX_HOPLIMIT); int hoplimit = dst_metric_raw(dst, RTAX_HOPLIMIT);
struct net *net = dev_net(dst->dev);
if (hoplimit == 0) if (hoplimit == 0) {
const struct net *net;
rcu_read_lock();
net = dev_net_rcu(dst->dev);
hoplimit = READ_ONCE(net->ipv4.sysctl_ip_default_ttl); hoplimit = READ_ONCE(net->ipv4.sysctl_ip_default_ttl);
rcu_read_unlock();
}
return hoplimit; return hoplimit;
} }

View File

@@ -3961,7 +3961,7 @@ static void __cgroup_kill(struct cgroup *cgrp)
lockdep_assert_held(&cgroup_mutex); lockdep_assert_held(&cgroup_mutex);
spin_lock_irq(&css_set_lock); spin_lock_irq(&css_set_lock);
set_bit(CGRP_KILL, &cgrp->flags); cgrp->kill_seq++;
spin_unlock_irq(&css_set_lock); spin_unlock_irq(&css_set_lock);
css_task_iter_start(&cgrp->self, CSS_TASK_ITER_PROCS | CSS_TASK_ITER_THREADED, &it); css_task_iter_start(&cgrp->self, CSS_TASK_ITER_PROCS | CSS_TASK_ITER_THREADED, &it);
@@ -3977,10 +3977,6 @@ static void __cgroup_kill(struct cgroup *cgrp)
send_sig(SIGKILL, task, 0); send_sig(SIGKILL, task, 0);
} }
css_task_iter_end(&it); css_task_iter_end(&it);
spin_lock_irq(&css_set_lock);
clear_bit(CGRP_KILL, &cgrp->flags);
spin_unlock_irq(&css_set_lock);
} }
static void cgroup_kill(struct cgroup *cgrp) static void cgroup_kill(struct cgroup *cgrp)
@@ -6425,6 +6421,10 @@ static int cgroup_css_set_fork(struct kernel_clone_args *kargs)
spin_lock_irq(&css_set_lock); spin_lock_irq(&css_set_lock);
cset = task_css_set(current); cset = task_css_set(current);
get_css_set(cset); get_css_set(cset);
if (kargs->cgrp)
kargs->kill_seq = kargs->cgrp->kill_seq;
else
kargs->kill_seq = cset->dfl_cgrp->kill_seq;
spin_unlock_irq(&css_set_lock); spin_unlock_irq(&css_set_lock);
if (!(kargs->flags & CLONE_INTO_CGROUP)) { if (!(kargs->flags & CLONE_INTO_CGROUP)) {
@@ -6608,6 +6608,7 @@ void cgroup_post_fork(struct task_struct *child,
struct kernel_clone_args *kargs) struct kernel_clone_args *kargs)
__releases(&cgroup_threadgroup_rwsem) __releases(&cgroup_mutex) __releases(&cgroup_threadgroup_rwsem) __releases(&cgroup_mutex)
{ {
unsigned int cgrp_kill_seq = 0;
unsigned long cgrp_flags = 0; unsigned long cgrp_flags = 0;
bool kill = false; bool kill = false;
struct cgroup_subsys *ss; struct cgroup_subsys *ss;
@@ -6621,10 +6622,13 @@ void cgroup_post_fork(struct task_struct *child,
/* init tasks are special, only link regular threads */ /* init tasks are special, only link regular threads */
if (likely(child->pid)) { if (likely(child->pid)) {
if (kargs->cgrp) if (kargs->cgrp) {
cgrp_flags = kargs->cgrp->flags; cgrp_flags = kargs->cgrp->flags;
else cgrp_kill_seq = kargs->cgrp->kill_seq;
} else {
cgrp_flags = cset->dfl_cgrp->flags; cgrp_flags = cset->dfl_cgrp->flags;
cgrp_kill_seq = cset->dfl_cgrp->kill_seq;
}
WARN_ON_ONCE(!list_empty(&child->cg_list)); WARN_ON_ONCE(!list_empty(&child->cg_list));
cset->nr_tasks++; cset->nr_tasks++;
@@ -6659,7 +6663,7 @@ void cgroup_post_fork(struct task_struct *child,
* child down right after we finished preparing it for * child down right after we finished preparing it for
* userspace. * userspace.
*/ */
kill = test_bit(CGRP_KILL, &cgrp_flags); kill = kargs->kill_seq != cgrp_kill_seq;
} }
spin_unlock_irq(&css_set_lock); spin_unlock_irq(&css_set_lock);

View File

@@ -576,6 +576,8 @@ static void kdb_msg_write(const char *msg, int msg_len)
continue; continue;
if (c == dbg_io_ops->cons) if (c == dbg_io_ops->cons)
continue; continue;
if (!c->write)
continue;
/* /*
* Set oops_in_progress to encourage the console drivers to * Set oops_in_progress to encourage the console drivers to
* disregard their internal spin locks: in the current calling * disregard their internal spin locks: in the current calling

View File

@@ -348,16 +348,18 @@ void clocksource_verify_percpu(struct clocksource *cs)
cpumask_clear(&cpus_ahead); cpumask_clear(&cpus_ahead);
cpumask_clear(&cpus_behind); cpumask_clear(&cpus_behind);
cpus_read_lock(); cpus_read_lock();
preempt_disable(); migrate_disable();
clocksource_verify_choose_cpus(); clocksource_verify_choose_cpus();
if (cpumask_empty(&cpus_chosen)) { if (cpumask_empty(&cpus_chosen)) {
preempt_enable(); migrate_enable();
cpus_read_unlock(); cpus_read_unlock();
pr_warn("Not enough CPUs to check clocksource '%s'.\n", cs->name); pr_warn("Not enough CPUs to check clocksource '%s'.\n", cs->name);
return; return;
} }
testcpu = smp_processor_id(); testcpu = smp_processor_id();
pr_warn("Checking clocksource %s synchronization from CPU %d to CPUs %*pbl.\n", cs->name, testcpu, cpumask_pr_args(&cpus_chosen)); pr_info("Checking clocksource %s synchronization from CPU %d to CPUs %*pbl.\n",
cs->name, testcpu, cpumask_pr_args(&cpus_chosen));
preempt_disable();
for_each_cpu(cpu, &cpus_chosen) { for_each_cpu(cpu, &cpus_chosen) {
if (cpu == testcpu) if (cpu == testcpu)
continue; continue;
@@ -377,6 +379,7 @@ void clocksource_verify_percpu(struct clocksource *cs)
cs_nsec_min = cs_nsec; cs_nsec_min = cs_nsec;
} }
preempt_enable(); preempt_enable();
migrate_enable();
cpus_read_unlock(); cpus_read_unlock();
if (!cpumask_empty(&cpus_ahead)) if (!cpumask_empty(&cpus_ahead))
pr_warn(" CPUs %*pbl ahead of CPU %d for clocksource %s.\n", pr_warn(" CPUs %*pbl ahead of CPU %d for clocksource %s.\n",

View File

@@ -1944,14 +1944,14 @@ struct page *get_dump_page(unsigned long addr)
/* /*
* Returns the number of collected pages. Return value is always >= 0. * Returns the number of collected pages. Return value is always >= 0.
*/ */
static unsigned long collect_longterm_unpinnable_pages( static void collect_longterm_unpinnable_pages(
struct list_head *movable_page_list, struct list_head *movable_page_list,
unsigned long nr_pages, unsigned long nr_pages,
struct page **pages) struct page **pages)
{ {
unsigned long i, collected = 0;
struct folio *prev_folio = NULL; struct folio *prev_folio = NULL;
bool drain_allow = true; bool drain_allow = true;
unsigned long i;
for (i = 0; i < nr_pages; i++) { for (i = 0; i < nr_pages; i++) {
struct folio *folio = page_folio(pages[i]); struct folio *folio = page_folio(pages[i]);
@@ -1963,8 +1963,6 @@ static unsigned long collect_longterm_unpinnable_pages(
if (folio_is_longterm_pinnable(folio)) if (folio_is_longterm_pinnable(folio))
continue; continue;
collected++;
if (folio_is_device_coherent(folio)) if (folio_is_device_coherent(folio))
continue; continue;
@@ -1986,8 +1984,6 @@ static unsigned long collect_longterm_unpinnable_pages(
NR_ISOLATED_ANON + folio_is_file_lru(folio), NR_ISOLATED_ANON + folio_is_file_lru(folio),
folio_nr_pages(folio)); folio_nr_pages(folio));
} }
return collected;
} }
/* /*
@@ -2080,12 +2076,10 @@ err:
static long check_and_migrate_movable_pages(unsigned long nr_pages, static long check_and_migrate_movable_pages(unsigned long nr_pages,
struct page **pages) struct page **pages)
{ {
unsigned long collected;
LIST_HEAD(movable_page_list); LIST_HEAD(movable_page_list);
collected = collect_longterm_unpinnable_pages(&movable_page_list, collect_longterm_unpinnable_pages(&movable_page_list, nr_pages, pages);
nr_pages, pages); if (list_empty(&movable_page_list))
if (!collected)
return 0; return 0;
return migrate_longterm_unpinnable_pages(&movable_page_list, nr_pages, return migrate_longterm_unpinnable_pages(&movable_page_list, nr_pages,

View File

@@ -1132,7 +1132,7 @@ static int j1939_sk_send_loop(struct j1939_priv *priv, struct sock *sk,
todo_size = size; todo_size = size;
while (todo_size) { do {
struct j1939_sk_buff_cb *skcb; struct j1939_sk_buff_cb *skcb;
segment_size = min_t(size_t, J1939_MAX_TP_PACKET_SIZE, segment_size = min_t(size_t, J1939_MAX_TP_PACKET_SIZE,
@@ -1177,7 +1177,7 @@ static int j1939_sk_send_loop(struct j1939_priv *priv, struct sock *sk,
todo_size -= segment_size; todo_size -= segment_size;
session->total_queued_size += segment_size; session->total_queued_size += segment_size;
} } while (todo_size);
switch (ret) { switch (ret) {
case 0: /* OK */ case 0: /* OK */

View File

@@ -382,8 +382,9 @@ sk_buff *j1939_session_skb_get_by_offset(struct j1939_session *session,
skb_queue_walk(&session->skb_queue, do_skb) { skb_queue_walk(&session->skb_queue, do_skb) {
do_skcb = j1939_skb_to_cb(do_skb); do_skcb = j1939_skb_to_cb(do_skb);
if (offset_start >= do_skcb->offset && if ((offset_start >= do_skcb->offset &&
offset_start < (do_skcb->offset + do_skb->len)) { offset_start < (do_skcb->offset + do_skb->len)) ||
(offset_start == 0 && do_skcb->offset == 0 && do_skb->len == 0)) {
skb = do_skb; skb = do_skb;
} }
} }

View File

@@ -1004,10 +1004,12 @@ bool __skb_flow_dissect(const struct net *net,
FLOW_DISSECTOR_KEY_BASIC, FLOW_DISSECTOR_KEY_BASIC,
target_container); target_container);
rcu_read_lock();
if (skb) { if (skb) {
if (!net) { if (!net) {
if (skb->dev) if (skb->dev)
net = dev_net(skb->dev); net = dev_net_rcu(skb->dev);
else if (skb->sk) else if (skb->sk)
net = sock_net(skb->sk); net = sock_net(skb->sk);
} }
@@ -1018,7 +1020,6 @@ bool __skb_flow_dissect(const struct net *net,
enum netns_bpf_attach_type type = NETNS_BPF_FLOW_DISSECTOR; enum netns_bpf_attach_type type = NETNS_BPF_FLOW_DISSECTOR;
struct bpf_prog_array *run_array; struct bpf_prog_array *run_array;
rcu_read_lock();
run_array = rcu_dereference(init_net.bpf.run_array[type]); run_array = rcu_dereference(init_net.bpf.run_array[type]);
if (!run_array) if (!run_array)
run_array = rcu_dereference(net->bpf.run_array[type]); run_array = rcu_dereference(net->bpf.run_array[type]);
@@ -1046,17 +1047,17 @@ bool __skb_flow_dissect(const struct net *net,
prog = READ_ONCE(run_array->items[0].prog); prog = READ_ONCE(run_array->items[0].prog);
result = bpf_flow_dissect(prog, &ctx, n_proto, nhoff, result = bpf_flow_dissect(prog, &ctx, n_proto, nhoff,
hlen, flags); hlen, flags);
if (result == BPF_FLOW_DISSECTOR_CONTINUE) if (result != BPF_FLOW_DISSECTOR_CONTINUE) {
goto dissect_continue; __skb_flow_bpf_to_target(&flow_keys, flow_dissector,
__skb_flow_bpf_to_target(&flow_keys, flow_dissector, target_container);
target_container); rcu_read_unlock();
rcu_read_unlock(); return result == BPF_OK;
return result == BPF_OK; }
} }
dissect_continue:
rcu_read_unlock();
} }
rcu_read_unlock();
if (dissector_uses_key(flow_dissector, if (dissector_uses_key(flow_dissector,
FLOW_DISSECTOR_KEY_ETH_ADDRS)) { FLOW_DISSECTOR_KEY_ETH_ADDRS)) {
struct ethhdr *eth = eth_hdr(skb); struct ethhdr *eth = eth_hdr(skb);

View File

@@ -3498,10 +3498,12 @@ static const struct seq_operations neigh_stat_seq_ops = {
static void __neigh_notify(struct neighbour *n, int type, int flags, static void __neigh_notify(struct neighbour *n, int type, int flags,
u32 pid) u32 pid)
{ {
struct net *net = dev_net(n->dev);
struct sk_buff *skb; struct sk_buff *skb;
int err = -ENOBUFS; int err = -ENOBUFS;
struct net *net;
rcu_read_lock();
net = dev_net_rcu(n->dev);
skb = nlmsg_new(neigh_nlmsg_size(), GFP_ATOMIC); skb = nlmsg_new(neigh_nlmsg_size(), GFP_ATOMIC);
if (skb == NULL) if (skb == NULL)
goto errout; goto errout;
@@ -3514,10 +3516,11 @@ static void __neigh_notify(struct neighbour *n, int type, int flags,
goto errout; goto errout;
} }
rtnl_notify(skb, net, 0, RTNLGRP_NEIGH, NULL, GFP_ATOMIC); rtnl_notify(skb, net, 0, RTNLGRP_NEIGH, NULL, GFP_ATOMIC);
return; goto out;
errout: errout:
if (err < 0) rtnl_set_sk_err(net, RTNLGRP_NEIGH, err);
rtnl_set_sk_err(net, RTNLGRP_NEIGH, err); out:
rcu_read_unlock();
} }
void neigh_app_ns(struct neighbour *n) void neigh_app_ns(struct neighbour *n)

View File

@@ -658,10 +658,12 @@ static int arp_xmit_finish(struct net *net, struct sock *sk, struct sk_buff *skb
*/ */
void arp_xmit(struct sk_buff *skb) void arp_xmit(struct sk_buff *skb)
{ {
rcu_read_lock();
/* Send it off, maybe filter it using firewalling first. */ /* Send it off, maybe filter it using firewalling first. */
NF_HOOK(NFPROTO_ARP, NF_ARP_OUT, NF_HOOK(NFPROTO_ARP, NF_ARP_OUT,
dev_net(skb->dev), NULL, skb, NULL, skb->dev, dev_net_rcu(skb->dev), NULL, skb, NULL, skb->dev,
arp_xmit_finish); arp_xmit_finish);
rcu_read_unlock();
} }
EXPORT_SYMBOL(arp_xmit); EXPORT_SYMBOL(arp_xmit);

View File

@@ -1320,10 +1320,11 @@ __be32 inet_select_addr(const struct net_device *dev, __be32 dst, int scope)
__be32 addr = 0; __be32 addr = 0;
unsigned char localnet_scope = RT_SCOPE_HOST; unsigned char localnet_scope = RT_SCOPE_HOST;
struct in_device *in_dev; struct in_device *in_dev;
struct net *net = dev_net(dev); struct net *net;
int master_idx; int master_idx;
rcu_read_lock(); rcu_read_lock();
net = dev_net_rcu(dev);
in_dev = __in_dev_get_rcu(dev); in_dev = __in_dev_get_rcu(dev);
if (!in_dev) if (!in_dev)
goto no_in_dev; goto no_in_dev;

View File

@@ -393,9 +393,9 @@ static void icmp_push_reply(struct sock *sk,
static void icmp_reply(struct icmp_bxm *icmp_param, struct sk_buff *skb) static void icmp_reply(struct icmp_bxm *icmp_param, struct sk_buff *skb)
{ {
struct ipcm_cookie ipc;
struct rtable *rt = skb_rtable(skb); struct rtable *rt = skb_rtable(skb);
struct net *net = dev_net(rt->dst.dev); struct net *net = dev_net_rcu(rt->dst.dev);
struct ipcm_cookie ipc;
struct flowi4 fl4; struct flowi4 fl4;
struct sock *sk; struct sock *sk;
struct inet_sock *inet; struct inet_sock *inet;
@@ -597,12 +597,14 @@ void __icmp_send(struct sk_buff *skb_in, int type, int code, __be32 info,
struct sock *sk; struct sock *sk;
if (!rt) if (!rt)
goto out; return;
rcu_read_lock();
if (rt->dst.dev) if (rt->dst.dev)
net = dev_net(rt->dst.dev); net = dev_net_rcu(rt->dst.dev);
else if (skb_in->dev) else if (skb_in->dev)
net = dev_net(skb_in->dev); net = dev_net_rcu(skb_in->dev);
else else
goto out; goto out;
@@ -771,7 +773,8 @@ out_unlock:
icmp_xmit_unlock(sk); icmp_xmit_unlock(sk);
out_bh_enable: out_bh_enable:
local_bh_enable(); local_bh_enable();
out:; out:
rcu_read_unlock();
} }
EXPORT_SYMBOL(__icmp_send); EXPORT_SYMBOL(__icmp_send);
@@ -820,7 +823,7 @@ static void icmp_socket_deliver(struct sk_buff *skb, u32 info)
* avoid additional coding at protocol handlers. * avoid additional coding at protocol handlers.
*/ */
if (!pskb_may_pull(skb, iph->ihl * 4 + 8)) { if (!pskb_may_pull(skb, iph->ihl * 4 + 8)) {
__ICMP_INC_STATS(dev_net(skb->dev), ICMP_MIB_INERRORS); __ICMP_INC_STATS(dev_net_rcu(skb->dev), ICMP_MIB_INERRORS);
return; return;
} }
@@ -854,7 +857,7 @@ static enum skb_drop_reason icmp_unreach(struct sk_buff *skb)
struct net *net; struct net *net;
u32 info = 0; u32 info = 0;
net = dev_net(skb_dst(skb)->dev); net = dev_net_rcu(skb_dst(skb)->dev);
/* /*
* Incomplete header ? * Incomplete header ?
@@ -965,7 +968,7 @@ out_err:
static enum skb_drop_reason icmp_redirect(struct sk_buff *skb) static enum skb_drop_reason icmp_redirect(struct sk_buff *skb)
{ {
if (skb->len < sizeof(struct iphdr)) { if (skb->len < sizeof(struct iphdr)) {
__ICMP_INC_STATS(dev_net(skb->dev), ICMP_MIB_INERRORS); __ICMP_INC_STATS(dev_net_rcu(skb->dev), ICMP_MIB_INERRORS);
return SKB_DROP_REASON_PKT_TOO_SMALL; return SKB_DROP_REASON_PKT_TOO_SMALL;
} }
@@ -997,7 +1000,7 @@ static enum skb_drop_reason icmp_echo(struct sk_buff *skb)
struct icmp_bxm icmp_param; struct icmp_bxm icmp_param;
struct net *net; struct net *net;
net = dev_net(skb_dst(skb)->dev); net = dev_net_rcu(skb_dst(skb)->dev);
/* should there be an ICMP stat for ignored echos? */ /* should there be an ICMP stat for ignored echos? */
if (READ_ONCE(net->ipv4.sysctl_icmp_echo_ignore_all)) if (READ_ONCE(net->ipv4.sysctl_icmp_echo_ignore_all))
return SKB_NOT_DROPPED_YET; return SKB_NOT_DROPPED_YET;
@@ -1026,9 +1029,9 @@ static enum skb_drop_reason icmp_echo(struct sk_buff *skb)
bool icmp_build_probe(struct sk_buff *skb, struct icmphdr *icmphdr) bool icmp_build_probe(struct sk_buff *skb, struct icmphdr *icmphdr)
{ {
struct net *net = dev_net_rcu(skb->dev);
struct icmp_ext_hdr *ext_hdr, _ext_hdr; struct icmp_ext_hdr *ext_hdr, _ext_hdr;
struct icmp_ext_echo_iio *iio, _iio; struct icmp_ext_echo_iio *iio, _iio;
struct net *net = dev_net(skb->dev);
struct inet6_dev *in6_dev; struct inet6_dev *in6_dev;
struct in_device *in_dev; struct in_device *in_dev;
struct net_device *dev; struct net_device *dev;
@@ -1167,7 +1170,7 @@ static enum skb_drop_reason icmp_timestamp(struct sk_buff *skb)
return SKB_NOT_DROPPED_YET; return SKB_NOT_DROPPED_YET;
out_err: out_err:
__ICMP_INC_STATS(dev_net(skb_dst(skb)->dev), ICMP_MIB_INERRORS); __ICMP_INC_STATS(dev_net_rcu(skb_dst(skb)->dev), ICMP_MIB_INERRORS);
return SKB_DROP_REASON_PKT_TOO_SMALL; return SKB_DROP_REASON_PKT_TOO_SMALL;
} }
@@ -1184,7 +1187,7 @@ int icmp_rcv(struct sk_buff *skb)
{ {
enum skb_drop_reason reason = SKB_DROP_REASON_NOT_SPECIFIED; enum skb_drop_reason reason = SKB_DROP_REASON_NOT_SPECIFIED;
struct rtable *rt = skb_rtable(skb); struct rtable *rt = skb_rtable(skb);
struct net *net = dev_net(rt->dst.dev); struct net *net = dev_net_rcu(rt->dst.dev);
struct icmphdr *icmph; struct icmphdr *icmph;
if (!xfrm4_policy_check(NULL, XFRM_POLICY_IN, skb)) { if (!xfrm4_policy_check(NULL, XFRM_POLICY_IN, skb)) {
@@ -1357,9 +1360,9 @@ int icmp_err(struct sk_buff *skb, u32 info)
struct iphdr *iph = (struct iphdr *)skb->data; struct iphdr *iph = (struct iphdr *)skb->data;
int offset = iph->ihl<<2; int offset = iph->ihl<<2;
struct icmphdr *icmph = (struct icmphdr *)(skb->data + offset); struct icmphdr *icmph = (struct icmphdr *)(skb->data + offset);
struct net *net = dev_net_rcu(skb->dev);
int type = icmp_hdr(skb)->type; int type = icmp_hdr(skb)->type;
int code = icmp_hdr(skb)->code; int code = icmp_hdr(skb)->code;
struct net *net = dev_net(skb->dev);
/* /*
* Use ping_err to handle all icmp errors except those * Use ping_err to handle all icmp errors except those

View File

@@ -393,7 +393,13 @@ static inline int ip_rt_proc_init(void)
static inline bool rt_is_expired(const struct rtable *rth) static inline bool rt_is_expired(const struct rtable *rth)
{ {
return rth->rt_genid != rt_genid_ipv4(dev_net(rth->dst.dev)); bool res;
rcu_read_lock();
res = rth->rt_genid != rt_genid_ipv4(dev_net_rcu(rth->dst.dev));
rcu_read_unlock();
return res;
} }
void rt_cache_flush(struct net *net) void rt_cache_flush(struct net *net)
@@ -1014,9 +1020,9 @@ out: kfree_skb_reason(skb, reason);
static void __ip_rt_update_pmtu(struct rtable *rt, struct flowi4 *fl4, u32 mtu) static void __ip_rt_update_pmtu(struct rtable *rt, struct flowi4 *fl4, u32 mtu)
{ {
struct dst_entry *dst = &rt->dst; struct dst_entry *dst = &rt->dst;
struct net *net = dev_net(dst->dev);
struct fib_result res; struct fib_result res;
bool lock = false; bool lock = false;
struct net *net;
u32 old_mtu; u32 old_mtu;
if (ip_mtu_locked(dst)) if (ip_mtu_locked(dst))
@@ -1026,6 +1032,8 @@ static void __ip_rt_update_pmtu(struct rtable *rt, struct flowi4 *fl4, u32 mtu)
if (old_mtu < mtu) if (old_mtu < mtu)
return; return;
rcu_read_lock();
net = dev_net_rcu(dst->dev);
if (mtu < net->ipv4.ip_rt_min_pmtu) { if (mtu < net->ipv4.ip_rt_min_pmtu) {
lock = true; lock = true;
mtu = min(old_mtu, net->ipv4.ip_rt_min_pmtu); mtu = min(old_mtu, net->ipv4.ip_rt_min_pmtu);
@@ -1033,17 +1041,29 @@ static void __ip_rt_update_pmtu(struct rtable *rt, struct flowi4 *fl4, u32 mtu)
if (rt->rt_pmtu == mtu && !lock && if (rt->rt_pmtu == mtu && !lock &&
time_before(jiffies, dst->expires - net->ipv4.ip_rt_mtu_expires / 2)) time_before(jiffies, dst->expires - net->ipv4.ip_rt_mtu_expires / 2))
return; goto out;
rcu_read_lock();
if (fib_lookup(net, fl4, &res, 0) == 0) { if (fib_lookup(net, fl4, &res, 0) == 0) {
struct fib_nh_common *nhc; struct fib_nh_common *nhc;
fib_select_path(net, &res, fl4, NULL); fib_select_path(net, &res, fl4, NULL);
#ifdef CONFIG_IP_ROUTE_MULTIPATH
if (fib_info_num_path(res.fi) > 1) {
int nhsel;
for (nhsel = 0; nhsel < fib_info_num_path(res.fi); nhsel++) {
nhc = fib_info_nhc(res.fi, nhsel);
update_or_create_fnhe(nhc, fl4->daddr, 0, mtu, lock,
jiffies + net->ipv4.ip_rt_mtu_expires);
}
goto out;
}
#endif /* CONFIG_IP_ROUTE_MULTIPATH */
nhc = FIB_RES_NHC(res); nhc = FIB_RES_NHC(res);
update_or_create_fnhe(nhc, fl4->daddr, 0, mtu, lock, update_or_create_fnhe(nhc, fl4->daddr, 0, mtu, lock,
jiffies + net->ipv4.ip_rt_mtu_expires); jiffies + net->ipv4.ip_rt_mtu_expires);
} }
out:
rcu_read_unlock(); rcu_read_unlock();
} }
@@ -1306,10 +1326,15 @@ static void set_class_tag(struct rtable *rt, u32 tag)
static unsigned int ipv4_default_advmss(const struct dst_entry *dst) static unsigned int ipv4_default_advmss(const struct dst_entry *dst)
{ {
struct net *net = dev_net(dst->dev);
unsigned int header_size = sizeof(struct tcphdr) + sizeof(struct iphdr); unsigned int header_size = sizeof(struct tcphdr) + sizeof(struct iphdr);
unsigned int advmss = max_t(unsigned int, ipv4_mtu(dst) - header_size, unsigned int advmss;
net->ipv4.ip_rt_min_advmss); struct net *net;
rcu_read_lock();
net = dev_net_rcu(dst->dev);
advmss = max_t(unsigned int, ipv4_mtu(dst) - header_size,
net->ipv4.ip_rt_min_advmss);
rcu_read_unlock();
return min(advmss, IPV4_MAX_PMTU - header_size); return min(advmss, IPV4_MAX_PMTU - header_size);
} }

View File

@@ -1731,21 +1731,19 @@ static struct sk_buff *mld_newpack(struct inet6_dev *idev, unsigned int mtu)
struct net_device *dev = idev->dev; struct net_device *dev = idev->dev;
int hlen = LL_RESERVED_SPACE(dev); int hlen = LL_RESERVED_SPACE(dev);
int tlen = dev->needed_tailroom; int tlen = dev->needed_tailroom;
struct net *net = dev_net(dev);
const struct in6_addr *saddr; const struct in6_addr *saddr;
struct in6_addr addr_buf; struct in6_addr addr_buf;
struct mld2_report *pmr; struct mld2_report *pmr;
struct sk_buff *skb; struct sk_buff *skb;
unsigned int size; unsigned int size;
struct sock *sk; struct sock *sk;
int err; struct net *net;
sk = net->ipv6.igmp_sk;
/* we assume size > sizeof(ra) here /* we assume size > sizeof(ra) here
* Also try to not allocate high-order pages for big MTU * Also try to not allocate high-order pages for big MTU
*/ */
size = min_t(int, mtu, PAGE_SIZE / 2) + hlen + tlen; size = min_t(int, mtu, PAGE_SIZE / 2) + hlen + tlen;
skb = sock_alloc_send_skb(sk, size, 1, &err); skb = alloc_skb(size, GFP_KERNEL);
if (!skb) if (!skb)
return NULL; return NULL;
@@ -1753,6 +1751,12 @@ static struct sk_buff *mld_newpack(struct inet6_dev *idev, unsigned int mtu)
skb_reserve(skb, hlen); skb_reserve(skb, hlen);
skb_tailroom_reserve(skb, mtu, tlen); skb_tailroom_reserve(skb, mtu, tlen);
rcu_read_lock();
net = dev_net_rcu(dev);
sk = net->ipv6.igmp_sk;
skb_set_owner_w(skb, sk);
if (ipv6_get_lladdr(dev, &addr_buf, IFA_F_TENTATIVE)) { if (ipv6_get_lladdr(dev, &addr_buf, IFA_F_TENTATIVE)) {
/* <draft-ietf-magma-mld-source-05.txt>: /* <draft-ietf-magma-mld-source-05.txt>:
* use unspecified address as the source address * use unspecified address as the source address
@@ -1764,6 +1768,8 @@ static struct sk_buff *mld_newpack(struct inet6_dev *idev, unsigned int mtu)
ip6_mc_hdr(sk, skb, dev, saddr, &mld2_all_mcr, NEXTHDR_HOP, 0); ip6_mc_hdr(sk, skb, dev, saddr, &mld2_all_mcr, NEXTHDR_HOP, 0);
rcu_read_unlock();
skb_put_data(skb, ra, sizeof(ra)); skb_put_data(skb, ra, sizeof(ra));
skb_set_transport_header(skb, skb_tail_pointer(skb) - skb->data); skb_set_transport_header(skb, skb_tail_pointer(skb) - skb->data);

View File

@@ -418,15 +418,11 @@ static struct sk_buff *ndisc_alloc_skb(struct net_device *dev,
{ {
int hlen = LL_RESERVED_SPACE(dev); int hlen = LL_RESERVED_SPACE(dev);
int tlen = dev->needed_tailroom; int tlen = dev->needed_tailroom;
struct sock *sk = dev_net(dev)->ipv6.ndisc_sk;
struct sk_buff *skb; struct sk_buff *skb;
skb = alloc_skb(hlen + sizeof(struct ipv6hdr) + len + tlen, GFP_ATOMIC); skb = alloc_skb(hlen + sizeof(struct ipv6hdr) + len + tlen, GFP_ATOMIC);
if (!skb) { if (!skb)
ND_PRINTK(0, err, "ndisc: %s failed to allocate an skb\n",
__func__);
return NULL; return NULL;
}
skb->protocol = htons(ETH_P_IPV6); skb->protocol = htons(ETH_P_IPV6);
skb->dev = dev; skb->dev = dev;
@@ -437,7 +433,9 @@ static struct sk_buff *ndisc_alloc_skb(struct net_device *dev,
/* Manually assign socket ownership as we avoid calling /* Manually assign socket ownership as we avoid calling
* sock_alloc_send_pskb() to bypass wmem buffer limits * sock_alloc_send_pskb() to bypass wmem buffer limits
*/ */
skb_set_owner_w(skb, sk); rcu_read_lock();
skb_set_owner_w(skb, dev_net_rcu(dev)->ipv6.ndisc_sk);
rcu_read_unlock();
return skb; return skb;
} }
@@ -473,16 +471,20 @@ static void ip6_nd_hdr(struct sk_buff *skb,
void ndisc_send_skb(struct sk_buff *skb, const struct in6_addr *daddr, void ndisc_send_skb(struct sk_buff *skb, const struct in6_addr *daddr,
const struct in6_addr *saddr) const struct in6_addr *saddr)
{ {
struct dst_entry *dst = skb_dst(skb);
struct net *net = dev_net(skb->dev);
struct sock *sk = net->ipv6.ndisc_sk;
struct inet6_dev *idev;
int err;
struct icmp6hdr *icmp6h = icmp6_hdr(skb); struct icmp6hdr *icmp6h = icmp6_hdr(skb);
struct dst_entry *dst = skb_dst(skb);
struct inet6_dev *idev;
struct net *net;
struct sock *sk;
int err;
u8 type; u8 type;
type = icmp6h->icmp6_type; type = icmp6h->icmp6_type;
rcu_read_lock();
net = dev_net_rcu(skb->dev);
sk = net->ipv6.ndisc_sk;
if (!dst) { if (!dst) {
struct flowi6 fl6; struct flowi6 fl6;
int oif = skb->dev->ifindex; int oif = skb->dev->ifindex;
@@ -490,6 +492,7 @@ void ndisc_send_skb(struct sk_buff *skb, const struct in6_addr *daddr,
icmpv6_flow_init(sk, &fl6, type, saddr, daddr, oif); icmpv6_flow_init(sk, &fl6, type, saddr, daddr, oif);
dst = icmp6_dst_alloc(skb->dev, &fl6); dst = icmp6_dst_alloc(skb->dev, &fl6);
if (IS_ERR(dst)) { if (IS_ERR(dst)) {
rcu_read_unlock();
kfree_skb(skb); kfree_skb(skb);
return; return;
} }
@@ -504,7 +507,6 @@ void ndisc_send_skb(struct sk_buff *skb, const struct in6_addr *daddr,
ip6_nd_hdr(skb, saddr, daddr, inet6_sk(sk)->hop_limit, skb->len); ip6_nd_hdr(skb, saddr, daddr, inet6_sk(sk)->hop_limit, skb->len);
rcu_read_lock();
idev = __in6_dev_get(dst->dev); idev = __in6_dev_get(dst->dev);
IP6_UPD_PO_STATS(net, idev, IPSTATS_MIB_OUT, skb->len); IP6_UPD_PO_STATS(net, idev, IPSTATS_MIB_OUT, skb->len);

View File

@@ -3190,13 +3190,18 @@ static unsigned int ip6_default_advmss(const struct dst_entry *dst)
{ {
struct net_device *dev = dst->dev; struct net_device *dev = dst->dev;
unsigned int mtu = dst_mtu(dst); unsigned int mtu = dst_mtu(dst);
struct net *net = dev_net(dev); struct net *net;
mtu -= sizeof(struct ipv6hdr) + sizeof(struct tcphdr); mtu -= sizeof(struct ipv6hdr) + sizeof(struct tcphdr);
rcu_read_lock();
net = dev_net_rcu(dev);
if (mtu < net->ipv6.sysctl.ip6_rt_min_advmss) if (mtu < net->ipv6.sysctl.ip6_rt_min_advmss)
mtu = net->ipv6.sysctl.ip6_rt_min_advmss; mtu = net->ipv6.sysctl.ip6_rt_min_advmss;
rcu_read_unlock();
/* /*
* Maximal non-jumbo IPv6 payload is IPV6_MAXPLEN and * Maximal non-jumbo IPv6 payload is IPV6_MAXPLEN and
* corresponding MSS is IPV6_MAXPLEN - tcp_header_size. * corresponding MSS is IPV6_MAXPLEN - tcp_header_size.

View File

@@ -2076,6 +2076,7 @@ static int ovs_vport_cmd_fill_info(struct vport *vport, struct sk_buff *skb,
{ {
struct ovs_header *ovs_header; struct ovs_header *ovs_header;
struct ovs_vport_stats vport_stats; struct ovs_vport_stats vport_stats;
struct net *net_vport;
int err; int err;
ovs_header = genlmsg_put(skb, portid, seq, &dp_vport_genl_family, ovs_header = genlmsg_put(skb, portid, seq, &dp_vport_genl_family,
@@ -2092,12 +2093,15 @@ static int ovs_vport_cmd_fill_info(struct vport *vport, struct sk_buff *skb,
nla_put_u32(skb, OVS_VPORT_ATTR_IFINDEX, vport->dev->ifindex)) nla_put_u32(skb, OVS_VPORT_ATTR_IFINDEX, vport->dev->ifindex))
goto nla_put_failure; goto nla_put_failure;
if (!net_eq(net, dev_net(vport->dev))) { rcu_read_lock();
int id = peernet2id_alloc(net, dev_net(vport->dev), gfp); net_vport = dev_net_rcu(vport->dev);
if (!net_eq(net, net_vport)) {
int id = peernet2id_alloc(net, net_vport, GFP_ATOMIC);
if (nla_put_s32(skb, OVS_VPORT_ATTR_NETNSID, id)) if (nla_put_s32(skb, OVS_VPORT_ATTR_NETNSID, id))
goto nla_put_failure; goto nla_put_failure_unlock;
} }
rcu_read_unlock();
ovs_vport_get_stats(vport, &vport_stats); ovs_vport_get_stats(vport, &vport_stats);
if (nla_put_64bit(skb, OVS_VPORT_ATTR_STATS, if (nla_put_64bit(skb, OVS_VPORT_ATTR_STATS,
@@ -2115,6 +2119,8 @@ static int ovs_vport_cmd_fill_info(struct vport *vport, struct sk_buff *skb,
genlmsg_end(skb, ovs_header); genlmsg_end(skb, ovs_header);
return 0; return 0;
nla_put_failure_unlock:
rcu_read_unlock();
nla_put_failure: nla_put_failure:
err = -EMSGSIZE; err = -EMSGSIZE;
error: error:

View File

@@ -197,6 +197,12 @@
# #
# - pmtu_ipv6_route_change # - pmtu_ipv6_route_change
# Same as above but with IPv6 # Same as above but with IPv6
#
# - pmtu_ipv4_mp_exceptions
# Use the same topology as in pmtu_ipv4, but add routeable addresses
# on host A and B on lo reachable via both routers. Host A and B
# addresses have multipath routes to each other, b_r1 mtu = 1500.
# Check that PMTU exceptions are created for both paths.
# Kselftest framework requirement - SKIP code is 4. # Kselftest framework requirement - SKIP code is 4.
ksft_skip=4 ksft_skip=4
@@ -266,7 +272,8 @@ tests="
list_flush_ipv4_exception ipv4: list and flush cached exceptions 1 list_flush_ipv4_exception ipv4: list and flush cached exceptions 1
list_flush_ipv6_exception ipv6: list and flush cached exceptions 1 list_flush_ipv6_exception ipv6: list and flush cached exceptions 1
pmtu_ipv4_route_change ipv4: PMTU exception w/route replace 1 pmtu_ipv4_route_change ipv4: PMTU exception w/route replace 1
pmtu_ipv6_route_change ipv6: PMTU exception w/route replace 1" pmtu_ipv6_route_change ipv6: PMTU exception w/route replace 1
pmtu_ipv4_mp_exceptions ipv4: PMTU multipath nh exceptions 1"
NS_A="ns-A" NS_A="ns-A"
NS_B="ns-B" NS_B="ns-B"
@@ -353,6 +360,9 @@ tunnel6_a_addr="fd00:2::a"
tunnel6_b_addr="fd00:2::b" tunnel6_b_addr="fd00:2::b"
tunnel6_mask="64" tunnel6_mask="64"
host4_a_addr="192.168.99.99"
host4_b_addr="192.168.88.88"
dummy6_0_prefix="fc00:1000::" dummy6_0_prefix="fc00:1000::"
dummy6_1_prefix="fc00:1001::" dummy6_1_prefix="fc00:1001::"
dummy6_mask="64" dummy6_mask="64"
@@ -907,6 +917,52 @@ setup_ovs_bridge() {
run_cmd ip route add ${prefix6}:${b_r1}::1 via ${prefix6}:${a_r1}::2 run_cmd ip route add ${prefix6}:${b_r1}::1 via ${prefix6}:${a_r1}::2
} }
setup_multipath_new() {
# Set up host A with multipath routes to host B host4_b_addr
run_cmd ${ns_a} ip addr add ${host4_a_addr} dev lo
run_cmd ${ns_a} ip nexthop add id 401 via ${prefix4}.${a_r1}.2 dev veth_A-R1
run_cmd ${ns_a} ip nexthop add id 402 via ${prefix4}.${a_r2}.2 dev veth_A-R2
run_cmd ${ns_a} ip nexthop add id 403 group 401/402
run_cmd ${ns_a} ip route add ${host4_b_addr} src ${host4_a_addr} nhid 403
# Set up host B with multipath routes to host A host4_a_addr
run_cmd ${ns_b} ip addr add ${host4_b_addr} dev lo
run_cmd ${ns_b} ip nexthop add id 401 via ${prefix4}.${b_r1}.2 dev veth_B-R1
run_cmd ${ns_b} ip nexthop add id 402 via ${prefix4}.${b_r2}.2 dev veth_B-R2
run_cmd ${ns_b} ip nexthop add id 403 group 401/402
run_cmd ${ns_b} ip route add ${host4_a_addr} src ${host4_b_addr} nhid 403
}
setup_multipath_old() {
# Set up host A with multipath routes to host B host4_b_addr
run_cmd ${ns_a} ip addr add ${host4_a_addr} dev lo
run_cmd ${ns_a} ip route add ${host4_b_addr} \
src ${host4_a_addr} \
nexthop via ${prefix4}.${a_r1}.2 weight 1 \
nexthop via ${prefix4}.${a_r2}.2 weight 1
# Set up host B with multipath routes to host A host4_a_addr
run_cmd ${ns_b} ip addr add ${host4_b_addr} dev lo
run_cmd ${ns_b} ip route add ${host4_a_addr} \
src ${host4_b_addr} \
nexthop via ${prefix4}.${b_r1}.2 weight 1 \
nexthop via ${prefix4}.${b_r2}.2 weight 1
}
setup_multipath() {
if [ "$USE_NH" = "yes" ]; then
setup_multipath_new
else
setup_multipath_old
fi
# Set up routers with routes to dummies
run_cmd ${ns_r1} ip route add ${host4_a_addr} via ${prefix4}.${a_r1}.1
run_cmd ${ns_r2} ip route add ${host4_a_addr} via ${prefix4}.${a_r2}.1
run_cmd ${ns_r1} ip route add ${host4_b_addr} via ${prefix4}.${b_r1}.1
run_cmd ${ns_r2} ip route add ${host4_b_addr} via ${prefix4}.${b_r2}.1
}
setup() { setup() {
[ "$(id -u)" -ne 0 ] && echo " need to run as root" && return $ksft_skip [ "$(id -u)" -ne 0 ] && echo " need to run as root" && return $ksft_skip
@@ -988,23 +1044,15 @@ link_get_mtu() {
} }
route_get_dst_exception() { route_get_dst_exception() {
ns_cmd="${1}" ns_cmd="${1}"; shift
dst="${2}"
dsfield="${3}"
if [ -z "${dsfield}" ]; then ${ns_cmd} ip route get "$@"
dsfield=0
fi
${ns_cmd} ip route get "${dst}" dsfield "${dsfield}"
} }
route_get_dst_pmtu_from_exception() { route_get_dst_pmtu_from_exception() {
ns_cmd="${1}" ns_cmd="${1}"; shift
dst="${2}"
dsfield="${3}"
mtu_parse "$(route_get_dst_exception "${ns_cmd}" "${dst}" "${dsfield}")" mtu_parse "$(route_get_dst_exception "${ns_cmd}" "$@")"
} }
check_pmtu_value() { check_pmtu_value() {
@@ -1147,10 +1195,10 @@ test_pmtu_ipv4_dscp_icmp_exception() {
run_cmd "${ns_a}" ping -q -M want -Q "${dsfield}" -c 1 -w 1 -s "${len}" "${dst2}" run_cmd "${ns_a}" ping -q -M want -Q "${dsfield}" -c 1 -w 1 -s "${len}" "${dst2}"
# Check that exceptions have been created with the correct PMTU # Check that exceptions have been created with the correct PMTU
pmtu_1="$(route_get_dst_pmtu_from_exception "${ns_a}" "${dst1}" "${policy_mark}")" pmtu_1="$(route_get_dst_pmtu_from_exception "${ns_a}" "${dst1}" dsfield "${policy_mark}")"
check_pmtu_value "1400" "${pmtu_1}" "exceeding MTU" || return 1 check_pmtu_value "1400" "${pmtu_1}" "exceeding MTU" || return 1
pmtu_2="$(route_get_dst_pmtu_from_exception "${ns_a}" "${dst2}" "${policy_mark}")" pmtu_2="$(route_get_dst_pmtu_from_exception "${ns_a}" "${dst2}" dsfield "${policy_mark}")"
check_pmtu_value "1500" "${pmtu_2}" "exceeding MTU" || return 1 check_pmtu_value "1500" "${pmtu_2}" "exceeding MTU" || return 1
} }
@@ -1197,9 +1245,9 @@ test_pmtu_ipv4_dscp_udp_exception() {
UDP:"${dst2}":50000,tos="${dsfield}" UDP:"${dst2}":50000,tos="${dsfield}"
# Check that exceptions have been created with the correct PMTU # Check that exceptions have been created with the correct PMTU
pmtu_1="$(route_get_dst_pmtu_from_exception "${ns_a}" "${dst1}" "${policy_mark}")" pmtu_1="$(route_get_dst_pmtu_from_exception "${ns_a}" "${dst1}" dsfield "${policy_mark}")"
check_pmtu_value "1400" "${pmtu_1}" "exceeding MTU" || return 1 check_pmtu_value "1400" "${pmtu_1}" "exceeding MTU" || return 1
pmtu_2="$(route_get_dst_pmtu_from_exception "${ns_a}" "${dst2}" "${policy_mark}")" pmtu_2="$(route_get_dst_pmtu_from_exception "${ns_a}" "${dst2}" dsfield "${policy_mark}")"
check_pmtu_value "1500" "${pmtu_2}" "exceeding MTU" || return 1 check_pmtu_value "1500" "${pmtu_2}" "exceeding MTU" || return 1
} }
@@ -2205,6 +2253,36 @@ test_pmtu_ipv6_route_change() {
test_pmtu_ipvX_route_change 6 test_pmtu_ipvX_route_change 6
} }
test_pmtu_ipv4_mp_exceptions() {
setup namespaces routing multipath || return $ksft_skip
trace "${ns_a}" veth_A-R1 "${ns_r1}" veth_R1-A \
"${ns_r1}" veth_R1-B "${ns_b}" veth_B-R1 \
"${ns_a}" veth_A-R2 "${ns_r2}" veth_R2-A \
"${ns_r2}" veth_R2-B "${ns_b}" veth_B-R2
# Set up initial MTU values
mtu "${ns_a}" veth_A-R1 2000
mtu "${ns_r1}" veth_R1-A 2000
mtu "${ns_r1}" veth_R1-B 1500
mtu "${ns_b}" veth_B-R1 1500
mtu "${ns_a}" veth_A-R2 2000
mtu "${ns_r2}" veth_R2-A 2000
mtu "${ns_r2}" veth_R2-B 1500
mtu "${ns_b}" veth_B-R2 1500
# Ping and expect two nexthop exceptions for two routes
run_cmd ${ns_a} ping -q -M want -i 0.1 -c 1 -s 1800 "${host4_b_addr}"
# Check that exceptions have been created with the correct PMTU
pmtu_a_R1="$(route_get_dst_pmtu_from_exception "${ns_a}" "${host4_b_addr}" oif veth_A-R1)"
pmtu_a_R2="$(route_get_dst_pmtu_from_exception "${ns_a}" "${host4_b_addr}" oif veth_A-R2)"
check_pmtu_value "1500" "${pmtu_a_R1}" "exceeding MTU (veth_A-R1)" || return 1
check_pmtu_value "1500" "${pmtu_a_R2}" "exceeding MTU (veth_A-R2)" || return 1
}
usage() { usage() {
echo echo
echo "$0 [OPTIONS] [TEST]..." echo "$0 [OPTIONS] [TEST]..."