commit: 2ff50bda111e1adfbafd70658521dcaf0e8537ef Author: Mike Pagano <mpagano <AT> gentoo <DOT> org> AuthorDate: Mon Jun 5 11:48:34 2023 +0000 Commit: Mike Pagano <mpagano <AT> gentoo <DOT> org> CommitDate: Mon Jun 5 11:48:34 2023 +0000 URL: https://gitweb.gentoo.org/proj/linux-patches.git/commit/?id=2ff50bda
Linux patch 6.1.32 Signed-off-by: Mike Pagano <mpagano <AT> gentoo.org> 0000_README | 4 + 1031_linux-6.1.32.patch | 2421 +++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 2425 insertions(+) diff --git a/0000_README b/0000_README index f6e14669..a242f865 100644 --- a/0000_README +++ b/0000_README @@ -163,6 +163,10 @@ Patch: 1030_linux-6.1.31.patch From: https://www.kernel.org Desc: Linux 6.1.31 +Patch: 1031_linux-6.1.32.patch +From: https://www.kernel.org +Desc: Linux 6.1.32 + Patch: 1500_XATTR_USER_PREFIX.patch From: https://bugs.gentoo.org/show_bug.cgi?id=470644 Desc: Support for namespace user.pax.* on tmpfs. diff --git a/1031_linux-6.1.32.patch b/1031_linux-6.1.32.patch new file mode 100644 index 00000000..f4ef09a2 --- /dev/null +++ b/1031_linux-6.1.32.patch @@ -0,0 +1,2421 @@ +diff --git a/Makefile b/Makefile +index 902a6b598c73b..a0c3d8809e93a 100644 +--- a/Makefile ++++ b/Makefile +@@ -1,7 +1,7 @@ + # SPDX-License-Identifier: GPL-2.0 + VERSION = 6 + PATCHLEVEL = 1 +-SUBLEVEL = 31 ++SUBLEVEL = 32 + EXTRAVERSION = + NAME = Curry Ramen + +diff --git a/block/blk-map.c b/block/blk-map.c +index 34735626b00f3..66da9e2b19abf 100644 +--- a/block/blk-map.c ++++ b/block/blk-map.c +@@ -246,7 +246,7 @@ static struct bio *blk_rq_map_bio_alloc(struct request *rq, + { + struct bio *bio; + +- if (rq->cmd_flags & REQ_POLLED) { ++ if (rq->cmd_flags & REQ_POLLED && (nr_vecs <= BIO_INLINE_VECS)) { + blk_opf_t opf = rq->cmd_flags | REQ_ALLOC_CACHE; + + bio = bio_alloc_bioset(NULL, nr_vecs, opf, gfp_mask, +diff --git a/block/blk-mq-tag.c b/block/blk-mq-tag.c +index 9eb968e14d31f..a80d7c62bdfe6 100644 +--- a/block/blk-mq-tag.c ++++ b/block/blk-mq-tag.c +@@ -41,16 +41,20 @@ void __blk_mq_tag_busy(struct blk_mq_hw_ctx *hctx) + { + unsigned int users; + ++ /* ++ * calling test_bit() prior to test_and_set_bit() is intentional, ++ * it avoids dirtying the cacheline if the queue is already active. ++ */ + if (blk_mq_is_shared_tags(hctx->flags)) { + struct request_queue *q = hctx->queue; + +- if (test_bit(QUEUE_FLAG_HCTX_ACTIVE, &q->queue_flags)) ++ if (test_bit(QUEUE_FLAG_HCTX_ACTIVE, &q->queue_flags) || ++ test_and_set_bit(QUEUE_FLAG_HCTX_ACTIVE, &q->queue_flags)) + return; +- set_bit(QUEUE_FLAG_HCTX_ACTIVE, &q->queue_flags); + } else { +- if (test_bit(BLK_MQ_S_TAG_ACTIVE, &hctx->state)) ++ if (test_bit(BLK_MQ_S_TAG_ACTIVE, &hctx->state) || ++ test_and_set_bit(BLK_MQ_S_TAG_ACTIVE, &hctx->state)) + return; +- set_bit(BLK_MQ_S_TAG_ACTIVE, &hctx->state); + } + + users = atomic_inc_return(&hctx->tags->active_queues); +diff --git a/drivers/cpufreq/amd-pstate.c b/drivers/cpufreq/amd-pstate.c +index c17bd845f5fcb..f8d2bba9173d8 100644 +--- a/drivers/cpufreq/amd-pstate.c ++++ b/drivers/cpufreq/amd-pstate.c +@@ -249,9 +249,8 @@ static int amd_pstate_verify(struct cpufreq_policy_data *policy) + return 0; + } + +-static int amd_pstate_target(struct cpufreq_policy *policy, +- unsigned int target_freq, +- unsigned int relation) ++static int amd_pstate_update_freq(struct cpufreq_policy *policy, ++ unsigned int target_freq, bool fast_switch) + { + struct cpufreq_freqs freqs; + struct amd_cpudata *cpudata = policy->driver_data; +@@ -270,26 +269,50 @@ static int amd_pstate_target(struct cpufreq_policy *policy, + des_perf = DIV_ROUND_CLOSEST(target_freq * cap_perf, + cpudata->max_freq); + +- cpufreq_freq_transition_begin(policy, &freqs); +- amd_pstate_update(cpudata, min_perf, des_perf, +- max_perf, false); +- cpufreq_freq_transition_end(policy, &freqs, false); ++ WARN_ON(fast_switch && !policy->fast_switch_enabled); ++ /* ++ * If fast_switch is desired, then there aren't any registered ++ * transition notifiers. See comment for ++ * cpufreq_enable_fast_switch(). ++ */ ++ if (!fast_switch) ++ cpufreq_freq_transition_begin(policy, &freqs); ++ ++ amd_pstate_update(cpudata, min_perf, des_perf, max_perf, fast_switch); ++ ++ if (!fast_switch) ++ cpufreq_freq_transition_end(policy, &freqs, false); + + return 0; + } + ++static int amd_pstate_target(struct cpufreq_policy *policy, ++ unsigned int target_freq, ++ unsigned int relation) ++{ ++ return amd_pstate_update_freq(policy, target_freq, false); ++} ++ ++static unsigned int amd_pstate_fast_switch(struct cpufreq_policy *policy, ++ unsigned int target_freq) ++{ ++ return amd_pstate_update_freq(policy, target_freq, true); ++} ++ + static void amd_pstate_adjust_perf(unsigned int cpu, + unsigned long _min_perf, + unsigned long target_perf, + unsigned long capacity) + { + unsigned long max_perf, min_perf, des_perf, +- cap_perf, lowest_nonlinear_perf; ++ cap_perf, lowest_nonlinear_perf, max_freq; + struct cpufreq_policy *policy = cpufreq_cpu_get(cpu); + struct amd_cpudata *cpudata = policy->driver_data; ++ unsigned int target_freq; + + cap_perf = READ_ONCE(cpudata->highest_perf); + lowest_nonlinear_perf = READ_ONCE(cpudata->lowest_nonlinear_perf); ++ max_freq = READ_ONCE(cpudata->max_freq); + + des_perf = cap_perf; + if (target_perf < capacity) +@@ -306,6 +329,10 @@ static void amd_pstate_adjust_perf(unsigned int cpu, + if (max_perf < min_perf) + max_perf = min_perf; + ++ des_perf = clamp_t(unsigned long, des_perf, min_perf, max_perf); ++ target_freq = div_u64(des_perf * max_freq, max_perf); ++ policy->cur = target_freq; ++ + amd_pstate_update(cpudata, min_perf, des_perf, max_perf, true); + cpufreq_cpu_put(policy); + } +@@ -517,6 +544,7 @@ static int amd_pstate_cpu_exit(struct cpufreq_policy *policy) + + freq_qos_remove_request(&cpudata->req[1]); + freq_qos_remove_request(&cpudata->req[0]); ++ policy->fast_switch_possible = false; + kfree(cpudata); + + return 0; +@@ -608,6 +636,7 @@ static struct cpufreq_driver amd_pstate_driver = { + .flags = CPUFREQ_CONST_LOOPS | CPUFREQ_NEED_UPDATE_LIMITS, + .verify = amd_pstate_verify, + .target = amd_pstate_target, ++ .fast_switch = amd_pstate_fast_switch, + .init = amd_pstate_cpu_init, + .exit = amd_pstate_cpu_exit, + .suspend = amd_pstate_cpu_suspend, +diff --git a/drivers/firmware/arm_ffa/driver.c b/drivers/firmware/arm_ffa/driver.c +index 737f36e7a9035..5904a679d3512 100644 +--- a/drivers/firmware/arm_ffa/driver.c ++++ b/drivers/firmware/arm_ffa/driver.c +@@ -274,7 +274,8 @@ __ffa_partition_info_get(u32 uuid0, u32 uuid1, u32 uuid2, u32 uuid3, + int idx, count, flags = 0, sz, buf_sz; + ffa_value_t partition_info; + +- if (!buffer || !num_partitions) /* Just get the count for now */ ++ if (drv_info->version > FFA_VERSION_1_0 && ++ (!buffer || !num_partitions)) /* Just get the count for now */ + flags = PARTITION_INFO_GET_RETURN_COUNT_ONLY; + + mutex_lock(&drv_info->rx_lock); +diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig +index e3af86f06c630..3e8e5f4ffa59f 100644 +--- a/drivers/gpio/Kconfig ++++ b/drivers/gpio/Kconfig +@@ -882,7 +882,7 @@ config GPIO_F7188X + help + This option enables support for GPIOs found on Fintek Super-I/O + chips F71869, F71869A, F71882FG, F71889F and F81866. +- As well as Nuvoton Super-I/O chip NCT6116D. ++ As well as Nuvoton Super-I/O chip NCT6126D. + + To compile this driver as a module, choose M here: the module will + be called f7188x-gpio. +diff --git a/drivers/gpio/gpio-f7188x.c b/drivers/gpio/gpio-f7188x.c +index 9effa7769bef5..f54ca5a1775ea 100644 +--- a/drivers/gpio/gpio-f7188x.c ++++ b/drivers/gpio/gpio-f7188x.c +@@ -48,7 +48,7 @@ + /* + * Nuvoton devices. + */ +-#define SIO_NCT6116D_ID 0xD283 /* NCT6116D chipset ID */ ++#define SIO_NCT6126D_ID 0xD283 /* NCT6126D chipset ID */ + + #define SIO_LD_GPIO_NUVOTON 0x07 /* GPIO logical device */ + +@@ -62,7 +62,7 @@ enum chips { + f81866, + f81804, + f81865, +- nct6116d, ++ nct6126d, + }; + + static const char * const f7188x_names[] = { +@@ -74,7 +74,7 @@ static const char * const f7188x_names[] = { + "f81866", + "f81804", + "f81865", +- "nct6116d", ++ "nct6126d", + }; + + struct f7188x_sio { +@@ -187,8 +187,8 @@ static int f7188x_gpio_set_config(struct gpio_chip *chip, unsigned offset, + /* Output mode register (0:open drain 1:push-pull). */ + #define f7188x_gpio_out_mode(base) ((base) + 3) + +-#define f7188x_gpio_dir_invert(type) ((type) == nct6116d) +-#define f7188x_gpio_data_single(type) ((type) == nct6116d) ++#define f7188x_gpio_dir_invert(type) ((type) == nct6126d) ++#define f7188x_gpio_data_single(type) ((type) == nct6126d) + + static struct f7188x_gpio_bank f71869_gpio_bank[] = { + F7188X_GPIO_BANK(0, 6, 0xF0, DRVNAME "-0"), +@@ -274,7 +274,7 @@ static struct f7188x_gpio_bank f81865_gpio_bank[] = { + F7188X_GPIO_BANK(60, 5, 0x90, DRVNAME "-6"), + }; + +-static struct f7188x_gpio_bank nct6116d_gpio_bank[] = { ++static struct f7188x_gpio_bank nct6126d_gpio_bank[] = { + F7188X_GPIO_BANK(0, 8, 0xE0, DRVNAME "-0"), + F7188X_GPIO_BANK(10, 8, 0xE4, DRVNAME "-1"), + F7188X_GPIO_BANK(20, 8, 0xE8, DRVNAME "-2"), +@@ -282,7 +282,7 @@ static struct f7188x_gpio_bank nct6116d_gpio_bank[] = { + F7188X_GPIO_BANK(40, 8, 0xF0, DRVNAME "-4"), + F7188X_GPIO_BANK(50, 8, 0xF4, DRVNAME "-5"), + F7188X_GPIO_BANK(60, 8, 0xF8, DRVNAME "-6"), +- F7188X_GPIO_BANK(70, 1, 0xFC, DRVNAME "-7"), ++ F7188X_GPIO_BANK(70, 8, 0xFC, DRVNAME "-7"), + }; + + static int f7188x_gpio_get_direction(struct gpio_chip *chip, unsigned offset) +@@ -490,9 +490,9 @@ static int f7188x_gpio_probe(struct platform_device *pdev) + data->nr_bank = ARRAY_SIZE(f81865_gpio_bank); + data->bank = f81865_gpio_bank; + break; +- case nct6116d: +- data->nr_bank = ARRAY_SIZE(nct6116d_gpio_bank); +- data->bank = nct6116d_gpio_bank; ++ case nct6126d: ++ data->nr_bank = ARRAY_SIZE(nct6126d_gpio_bank); ++ data->bank = nct6126d_gpio_bank; + break; + default: + return -ENODEV; +@@ -559,9 +559,9 @@ static int __init f7188x_find(int addr, struct f7188x_sio *sio) + case SIO_F81865_ID: + sio->type = f81865; + break; +- case SIO_NCT6116D_ID: ++ case SIO_NCT6126D_ID: + sio->device = SIO_LD_GPIO_NUVOTON; +- sio->type = nct6116d; ++ sio->type = nct6126d; + break; + default: + pr_info("Unsupported Fintek device 0x%04x\n", devid); +@@ -569,7 +569,7 @@ static int __init f7188x_find(int addr, struct f7188x_sio *sio) + } + + /* double check manufacturer where possible */ +- if (sio->type != nct6116d) { ++ if (sio->type != nct6126d) { + manid = superio_inw(addr, SIO_FINTEK_MANID); + if (manid != SIO_FINTEK_ID) { + pr_debug("Not a Fintek device at 0x%08x\n", addr); +@@ -581,7 +581,7 @@ static int __init f7188x_find(int addr, struct f7188x_sio *sio) + err = 0; + + pr_info("Found %s at %#x\n", f7188x_names[sio->type], (unsigned int)addr); +- if (sio->type != nct6116d) ++ if (sio->type != nct6126d) + pr_info(" revision %d\n", superio_inb(addr, SIO_FINTEK_DEVREV)); + + err: +diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_acpi.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_acpi.c +index a78e80f9f65cd..e32bd990800de 100644 +--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_acpi.c ++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_acpi.c +@@ -1083,6 +1083,9 @@ bool amdgpu_acpi_is_s0ix_active(struct amdgpu_device *adev) + (pm_suspend_target_state != PM_SUSPEND_TO_IDLE)) + return false; + ++ if (adev->asic_type < CHIP_RAVEN) ++ return false; ++ + /* + * If ACPI_FADT_LOW_POWER_S0 is not set in the FADT, it is generally + * risky to do any special firmware-related preparations for entering +diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c +index 871f481f84328..88a9ece7f4647 100644 +--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c ++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c +@@ -2402,8 +2402,10 @@ static int amdgpu_pmops_suspend(struct device *dev) + + if (amdgpu_acpi_is_s0ix_active(adev)) + adev->in_s0ix = true; +- else ++ else if (amdgpu_acpi_is_s3_active(adev)) + adev->in_s3 = true; ++ if (!adev->in_s0ix && !adev->in_s3) ++ return 0; + return amdgpu_device_suspend(drm_dev, true); + } + +@@ -2424,6 +2426,9 @@ static int amdgpu_pmops_resume(struct device *dev) + struct amdgpu_device *adev = drm_to_adev(drm_dev); + int r; + ++ if (!adev->in_s0ix && !adev->in_s3) ++ return 0; ++ + /* Avoids registers access if device is physically gone */ + if (!pci_device_is_present(adev->pdev)) + adev->no_hw_access = true; +diff --git a/drivers/infiniband/sw/rxe/rxe_qp.c b/drivers/infiniband/sw/rxe/rxe_qp.c +index e459fb542b83a..1f6e006c51c4a 100644 +--- a/drivers/infiniband/sw/rxe/rxe_qp.c ++++ b/drivers/infiniband/sw/rxe/rxe_qp.c +@@ -792,8 +792,11 @@ static void rxe_qp_do_cleanup(struct work_struct *work) + del_timer_sync(&qp->rnr_nak_timer); + } + +- rxe_cleanup_task(&qp->req.task); +- rxe_cleanup_task(&qp->comp.task); ++ if (qp->req.task.func) ++ rxe_cleanup_task(&qp->req.task); ++ ++ if (qp->comp.task.func) ++ rxe_cleanup_task(&qp->comp.task); + + /* flush out any receive wr's or pending requests */ + if (qp->req.task.func) +diff --git a/drivers/net/ethernet/marvell/octeontx2/af/cgx.c b/drivers/net/ethernet/marvell/octeontx2/af/cgx.c +index 8fdd3afe59981..afdddfced7e69 100644 +--- a/drivers/net/ethernet/marvell/octeontx2/af/cgx.c ++++ b/drivers/net/ethernet/marvell/octeontx2/af/cgx.c +@@ -1225,6 +1225,14 @@ static inline void link_status_user_format(u64 lstat, + linfo->an = FIELD_GET(RESP_LINKSTAT_AN, lstat); + linfo->fec = FIELD_GET(RESP_LINKSTAT_FEC, lstat); + linfo->lmac_type_id = cgx_get_lmac_type(cgx, lmac_id); ++ ++ if (linfo->lmac_type_id >= LMAC_MODE_MAX) { ++ dev_err(&cgx->pdev->dev, "Unknown lmac_type_id %d reported by firmware on cgx port%d:%d", ++ linfo->lmac_type_id, cgx->cgx_id, lmac_id); ++ strncpy(linfo->lmac_type, "Unknown", LMACTYPE_STR_LEN - 1); ++ return; ++ } ++ + lmac_string = cgx_lmactype_string[linfo->lmac_type_id]; + strncpy(linfo->lmac_type, lmac_string, LMACTYPE_STR_LEN - 1); + } +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/eswitch.h b/drivers/net/ethernet/mellanox/mlx5/core/eswitch.h +index 821c78bab3732..a3daca44f74b1 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/eswitch.h ++++ b/drivers/net/ethernet/mellanox/mlx5/core/eswitch.h +@@ -340,6 +340,7 @@ struct mlx5_eswitch { + } params; + struct blocking_notifier_head n_head; + struct dentry *dbgfs; ++ bool paired[MLX5_MAX_PORTS]; + }; + + void esw_offloads_disable(struct mlx5_eswitch *esw); +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c b/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c +index 5235b5a7b9637..433cdd0a2cf34 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c +@@ -2827,6 +2827,9 @@ static int mlx5_esw_offloads_devcom_event(int event, + mlx5_eswitch_vport_match_metadata_enabled(peer_esw)) + break; + ++ if (esw->paired[mlx5_get_dev_index(peer_esw->dev)]) ++ break; ++ + err = mlx5_esw_offloads_set_ns_peer(esw, peer_esw, true); + if (err) + goto err_out; +@@ -2838,14 +2841,18 @@ static int mlx5_esw_offloads_devcom_event(int event, + if (err) + goto err_pair; + ++ esw->paired[mlx5_get_dev_index(peer_esw->dev)] = true; ++ peer_esw->paired[mlx5_get_dev_index(esw->dev)] = true; + mlx5_devcom_set_paired(devcom, MLX5_DEVCOM_ESW_OFFLOADS, true); + break; + + case ESW_OFFLOADS_DEVCOM_UNPAIR: +- if (!mlx5_devcom_is_paired(devcom, MLX5_DEVCOM_ESW_OFFLOADS)) ++ if (!esw->paired[mlx5_get_dev_index(peer_esw->dev)]) + break; + + mlx5_devcom_set_paired(devcom, MLX5_DEVCOM_ESW_OFFLOADS, false); ++ esw->paired[mlx5_get_dev_index(peer_esw->dev)] = false; ++ peer_esw->paired[mlx5_get_dev_index(esw->dev)] = false; + mlx5_esw_offloads_unpair(peer_esw); + mlx5_esw_offloads_unpair(esw); + mlx5_esw_offloads_set_ns_peer(esw, peer_esw, false); +diff --git a/drivers/net/ethernet/mellanox/mlxsw/core_thermal.c b/drivers/net/ethernet/mellanox/mlxsw/core_thermal.c +index 09ed6e5fa6c34..ef5e61708df39 100644 +--- a/drivers/net/ethernet/mellanox/mlxsw/core_thermal.c ++++ b/drivers/net/ethernet/mellanox/mlxsw/core_thermal.c +@@ -36,39 +36,33 @@ enum mlxsw_thermal_trips { + MLXSW_THERMAL_TEMP_TRIP_HOT, + }; + +-struct mlxsw_cooling_states { ++struct mlxsw_thermal_trip { ++ int type; ++ int temp; ++ int hyst; + int min_state; + int max_state; + }; + +-static const struct thermal_trip default_thermal_trips[] = { ++static const struct mlxsw_thermal_trip default_thermal_trips[] = { + { /* In range - 0-40% PWM */ + .type = THERMAL_TRIP_ACTIVE, +- .temperature = MLXSW_THERMAL_ASIC_TEMP_NORM, +- .hysteresis = MLXSW_THERMAL_HYSTERESIS_TEMP, +- }, +- { +- /* In range - 40-100% PWM */ +- .type = THERMAL_TRIP_ACTIVE, +- .temperature = MLXSW_THERMAL_ASIC_TEMP_HIGH, +- .hysteresis = MLXSW_THERMAL_HYSTERESIS_TEMP, +- }, +- { /* Warning */ +- .type = THERMAL_TRIP_HOT, +- .temperature = MLXSW_THERMAL_ASIC_TEMP_HOT, +- }, +-}; +- +-static const struct mlxsw_cooling_states default_cooling_states[] = { +- { ++ .temp = MLXSW_THERMAL_ASIC_TEMP_NORM, ++ .hyst = MLXSW_THERMAL_HYSTERESIS_TEMP, + .min_state = 0, + .max_state = (4 * MLXSW_THERMAL_MAX_STATE) / 10, + }, + { ++ /* In range - 40-100% PWM */ ++ .type = THERMAL_TRIP_ACTIVE, ++ .temp = MLXSW_THERMAL_ASIC_TEMP_HIGH, ++ .hyst = MLXSW_THERMAL_HYSTERESIS_TEMP, + .min_state = (4 * MLXSW_THERMAL_MAX_STATE) / 10, + .max_state = MLXSW_THERMAL_MAX_STATE, + }, +- { ++ { /* Warning */ ++ .type = THERMAL_TRIP_HOT, ++ .temp = MLXSW_THERMAL_ASIC_TEMP_HOT, + .min_state = MLXSW_THERMAL_MAX_STATE, + .max_state = MLXSW_THERMAL_MAX_STATE, + }, +@@ -84,8 +78,7 @@ struct mlxsw_thermal; + struct mlxsw_thermal_module { + struct mlxsw_thermal *parent; + struct thermal_zone_device *tzdev; +- struct thermal_trip trips[MLXSW_THERMAL_NUM_TRIPS]; +- struct mlxsw_cooling_states cooling_states[MLXSW_THERMAL_NUM_TRIPS]; ++ struct mlxsw_thermal_trip trips[MLXSW_THERMAL_NUM_TRIPS]; + int module; /* Module or gearbox number */ + u8 slot_index; + }; +@@ -105,8 +98,7 @@ struct mlxsw_thermal { + struct thermal_zone_device *tzdev; + int polling_delay; + struct thermal_cooling_device *cdevs[MLXSW_MFCR_PWMS_MAX]; +- struct thermal_trip trips[MLXSW_THERMAL_NUM_TRIPS]; +- struct mlxsw_cooling_states cooling_states[MLXSW_THERMAL_NUM_TRIPS]; ++ struct mlxsw_thermal_trip trips[MLXSW_THERMAL_NUM_TRIPS]; + struct mlxsw_thermal_area line_cards[]; + }; + +@@ -143,9 +135,9 @@ static int mlxsw_get_cooling_device_idx(struct mlxsw_thermal *thermal, + static void + mlxsw_thermal_module_trips_reset(struct mlxsw_thermal_module *tz) + { +- tz->trips[MLXSW_THERMAL_TEMP_TRIP_NORM].temperature = 0; +- tz->trips[MLXSW_THERMAL_TEMP_TRIP_HIGH].temperature = 0; +- tz->trips[MLXSW_THERMAL_TEMP_TRIP_HOT].temperature = 0; ++ tz->trips[MLXSW_THERMAL_TEMP_TRIP_NORM].temp = 0; ++ tz->trips[MLXSW_THERMAL_TEMP_TRIP_HIGH].temp = 0; ++ tz->trips[MLXSW_THERMAL_TEMP_TRIP_HOT].temp = 0; + } + + static int +@@ -187,12 +179,12 @@ mlxsw_thermal_module_trips_update(struct device *dev, struct mlxsw_core *core, + * by subtracting double hysteresis value. + */ + if (crit_temp >= MLXSW_THERMAL_MODULE_TEMP_SHIFT) +- tz->trips[MLXSW_THERMAL_TEMP_TRIP_NORM].temperature = crit_temp - ++ tz->trips[MLXSW_THERMAL_TEMP_TRIP_NORM].temp = crit_temp - + MLXSW_THERMAL_MODULE_TEMP_SHIFT; + else +- tz->trips[MLXSW_THERMAL_TEMP_TRIP_NORM].temperature = crit_temp; +- tz->trips[MLXSW_THERMAL_TEMP_TRIP_HIGH].temperature = crit_temp; +- tz->trips[MLXSW_THERMAL_TEMP_TRIP_HOT].temperature = emerg_temp; ++ tz->trips[MLXSW_THERMAL_TEMP_TRIP_NORM].temp = crit_temp; ++ tz->trips[MLXSW_THERMAL_TEMP_TRIP_HIGH].temp = crit_temp; ++ tz->trips[MLXSW_THERMAL_TEMP_TRIP_HOT].temp = emerg_temp; + + return 0; + } +@@ -209,11 +201,11 @@ static int mlxsw_thermal_bind(struct thermal_zone_device *tzdev, + return 0; + + for (i = 0; i < MLXSW_THERMAL_NUM_TRIPS; i++) { +- const struct mlxsw_cooling_states *state = &thermal->cooling_states[i]; ++ const struct mlxsw_thermal_trip *trip = &thermal->trips[i]; + + err = thermal_zone_bind_cooling_device(tzdev, i, cdev, +- state->max_state, +- state->min_state, ++ trip->max_state, ++ trip->min_state, + THERMAL_WEIGHT_DEFAULT); + if (err < 0) { + dev_err(dev, "Failed to bind cooling device to trip %d\n", i); +@@ -267,6 +259,61 @@ static int mlxsw_thermal_get_temp(struct thermal_zone_device *tzdev, + return 0; + } + ++static int mlxsw_thermal_get_trip_type(struct thermal_zone_device *tzdev, ++ int trip, ++ enum thermal_trip_type *p_type) ++{ ++ struct mlxsw_thermal *thermal = tzdev->devdata; ++ ++ if (trip < 0 || trip >= MLXSW_THERMAL_NUM_TRIPS) ++ return -EINVAL; ++ ++ *p_type = thermal->trips[trip].type; ++ return 0; ++} ++ ++static int mlxsw_thermal_get_trip_temp(struct thermal_zone_device *tzdev, ++ int trip, int *p_temp) ++{ ++ struct mlxsw_thermal *thermal = tzdev->devdata; ++ ++ if (trip < 0 || trip >= MLXSW_THERMAL_NUM_TRIPS) ++ return -EINVAL; ++ ++ *p_temp = thermal->trips[trip].temp; ++ return 0; ++} ++ ++static int mlxsw_thermal_set_trip_temp(struct thermal_zone_device *tzdev, ++ int trip, int temp) ++{ ++ struct mlxsw_thermal *thermal = tzdev->devdata; ++ ++ if (trip < 0 || trip >= MLXSW_THERMAL_NUM_TRIPS) ++ return -EINVAL; ++ ++ thermal->trips[trip].temp = temp; ++ return 0; ++} ++ ++static int mlxsw_thermal_get_trip_hyst(struct thermal_zone_device *tzdev, ++ int trip, int *p_hyst) ++{ ++ struct mlxsw_thermal *thermal = tzdev->devdata; ++ ++ *p_hyst = thermal->trips[trip].hyst; ++ return 0; ++} ++ ++static int mlxsw_thermal_set_trip_hyst(struct thermal_zone_device *tzdev, ++ int trip, int hyst) ++{ ++ struct mlxsw_thermal *thermal = tzdev->devdata; ++ ++ thermal->trips[trip].hyst = hyst; ++ return 0; ++} ++ + static struct thermal_zone_params mlxsw_thermal_params = { + .no_hwmon = true, + }; +@@ -275,6 +322,11 @@ static struct thermal_zone_device_ops mlxsw_thermal_ops = { + .bind = mlxsw_thermal_bind, + .unbind = mlxsw_thermal_unbind, + .get_temp = mlxsw_thermal_get_temp, ++ .get_trip_type = mlxsw_thermal_get_trip_type, ++ .get_trip_temp = mlxsw_thermal_get_trip_temp, ++ .set_trip_temp = mlxsw_thermal_set_trip_temp, ++ .get_trip_hyst = mlxsw_thermal_get_trip_hyst, ++ .set_trip_hyst = mlxsw_thermal_set_trip_hyst, + }; + + static int mlxsw_thermal_module_bind(struct thermal_zone_device *tzdev, +@@ -289,11 +341,11 @@ static int mlxsw_thermal_module_bind(struct thermal_zone_device *tzdev, + return 0; + + for (i = 0; i < MLXSW_THERMAL_NUM_TRIPS; i++) { +- const struct mlxsw_cooling_states *state = &tz->cooling_states[i]; ++ const struct mlxsw_thermal_trip *trip = &tz->trips[i]; + + err = thermal_zone_bind_cooling_device(tzdev, i, cdev, +- state->max_state, +- state->min_state, ++ trip->max_state, ++ trip->min_state, + THERMAL_WEIGHT_DEFAULT); + if (err < 0) + goto err_thermal_zone_bind_cooling_device; +@@ -381,10 +433,74 @@ static int mlxsw_thermal_module_temp_get(struct thermal_zone_device *tzdev, + return 0; + } + ++static int ++mlxsw_thermal_module_trip_type_get(struct thermal_zone_device *tzdev, int trip, ++ enum thermal_trip_type *p_type) ++{ ++ struct mlxsw_thermal_module *tz = tzdev->devdata; ++ ++ if (trip < 0 || trip >= MLXSW_THERMAL_NUM_TRIPS) ++ return -EINVAL; ++ ++ *p_type = tz->trips[trip].type; ++ return 0; ++} ++ ++static int ++mlxsw_thermal_module_trip_temp_get(struct thermal_zone_device *tzdev, ++ int trip, int *p_temp) ++{ ++ struct mlxsw_thermal_module *tz = tzdev->devdata; ++ ++ if (trip < 0 || trip >= MLXSW_THERMAL_NUM_TRIPS) ++ return -EINVAL; ++ ++ *p_temp = tz->trips[trip].temp; ++ return 0; ++} ++ ++static int ++mlxsw_thermal_module_trip_temp_set(struct thermal_zone_device *tzdev, ++ int trip, int temp) ++{ ++ struct mlxsw_thermal_module *tz = tzdev->devdata; ++ ++ if (trip < 0 || trip >= MLXSW_THERMAL_NUM_TRIPS) ++ return -EINVAL; ++ ++ tz->trips[trip].temp = temp; ++ return 0; ++} ++ ++static int ++mlxsw_thermal_module_trip_hyst_get(struct thermal_zone_device *tzdev, int trip, ++ int *p_hyst) ++{ ++ struct mlxsw_thermal_module *tz = tzdev->devdata; ++ ++ *p_hyst = tz->trips[trip].hyst; ++ return 0; ++} ++ ++static int ++mlxsw_thermal_module_trip_hyst_set(struct thermal_zone_device *tzdev, int trip, ++ int hyst) ++{ ++ struct mlxsw_thermal_module *tz = tzdev->devdata; ++ ++ tz->trips[trip].hyst = hyst; ++ return 0; ++} ++ + static struct thermal_zone_device_ops mlxsw_thermal_module_ops = { + .bind = mlxsw_thermal_module_bind, + .unbind = mlxsw_thermal_module_unbind, + .get_temp = mlxsw_thermal_module_temp_get, ++ .get_trip_type = mlxsw_thermal_module_trip_type_get, ++ .get_trip_temp = mlxsw_thermal_module_trip_temp_get, ++ .set_trip_temp = mlxsw_thermal_module_trip_temp_set, ++ .get_trip_hyst = mlxsw_thermal_module_trip_hyst_get, ++ .set_trip_hyst = mlxsw_thermal_module_trip_hyst_set, + }; + + static int mlxsw_thermal_gearbox_temp_get(struct thermal_zone_device *tzdev, +@@ -414,6 +530,11 @@ static struct thermal_zone_device_ops mlxsw_thermal_gearbox_ops = { + .bind = mlxsw_thermal_module_bind, + .unbind = mlxsw_thermal_module_unbind, + .get_temp = mlxsw_thermal_gearbox_temp_get, ++ .get_trip_type = mlxsw_thermal_module_trip_type_get, ++ .get_trip_temp = mlxsw_thermal_module_trip_temp_get, ++ .set_trip_temp = mlxsw_thermal_module_trip_temp_set, ++ .get_trip_hyst = mlxsw_thermal_module_trip_hyst_get, ++ .set_trip_hyst = mlxsw_thermal_module_trip_hyst_set, + }; + + static int mlxsw_thermal_get_max_state(struct thermal_cooling_device *cdev, +@@ -495,8 +616,7 @@ mlxsw_thermal_module_tz_init(struct mlxsw_thermal_module *module_tz) + else + snprintf(tz_name, sizeof(tz_name), "mlxsw-module%d", + module_tz->module + 1); +- module_tz->tzdev = thermal_zone_device_register_with_trips(tz_name, +- module_tz->trips, ++ module_tz->tzdev = thermal_zone_device_register(tz_name, + MLXSW_THERMAL_NUM_TRIPS, + MLXSW_THERMAL_TRIP_MASK, + module_tz, +@@ -540,8 +660,6 @@ mlxsw_thermal_module_init(struct device *dev, struct mlxsw_core *core, + module_tz->parent = thermal; + memcpy(module_tz->trips, default_thermal_trips, + sizeof(thermal->trips)); +- memcpy(module_tz->cooling_states, default_cooling_states, +- sizeof(thermal->cooling_states)); + /* Initialize all trip point. */ + mlxsw_thermal_module_trips_reset(module_tz); + /* Read module temperature and thresholds. */ +@@ -637,8 +755,7 @@ mlxsw_thermal_gearbox_tz_init(struct mlxsw_thermal_module *gearbox_tz) + else + snprintf(tz_name, sizeof(tz_name), "mlxsw-gearbox%d", + gearbox_tz->module + 1); +- gearbox_tz->tzdev = thermal_zone_device_register_with_trips(tz_name, +- gearbox_tz->trips, ++ gearbox_tz->tzdev = thermal_zone_device_register(tz_name, + MLXSW_THERMAL_NUM_TRIPS, + MLXSW_THERMAL_TRIP_MASK, + gearbox_tz, +@@ -695,8 +812,6 @@ mlxsw_thermal_gearboxes_init(struct device *dev, struct mlxsw_core *core, + gearbox_tz = &area->tz_gearbox_arr[i]; + memcpy(gearbox_tz->trips, default_thermal_trips, + sizeof(thermal->trips)); +- memcpy(gearbox_tz->cooling_states, default_cooling_states, +- sizeof(thermal->cooling_states)); + gearbox_tz->module = i; + gearbox_tz->parent = thermal; + gearbox_tz->slot_index = area->slot_index; +@@ -812,7 +927,6 @@ int mlxsw_thermal_init(struct mlxsw_core *core, + thermal->core = core; + thermal->bus_info = bus_info; + memcpy(thermal->trips, default_thermal_trips, sizeof(thermal->trips)); +- memcpy(thermal->cooling_states, default_cooling_states, sizeof(thermal->cooling_states)); + thermal->line_cards[0].slot_index = 0; + + err = mlxsw_reg_query(thermal->core, MLXSW_REG(mfcr), mfcr_pl); +@@ -862,8 +976,7 @@ int mlxsw_thermal_init(struct mlxsw_core *core, + MLXSW_THERMAL_SLOW_POLL_INT : + MLXSW_THERMAL_POLL_INT; + +- thermal->tzdev = thermal_zone_device_register_with_trips("mlxsw", +- thermal->trips, ++ thermal->tzdev = thermal_zone_device_register("mlxsw", + MLXSW_THERMAL_NUM_TRIPS, + MLXSW_THERMAL_TRIP_MASK, + thermal, +diff --git a/drivers/net/phy/mscc/mscc.h b/drivers/net/phy/mscc/mscc.h +index a50235fdf7d99..055e4ca5b3b5c 100644 +--- a/drivers/net/phy/mscc/mscc.h ++++ b/drivers/net/phy/mscc/mscc.h +@@ -179,6 +179,7 @@ enum rgmii_clock_delay { + #define VSC8502_RGMII_CNTL 20 + #define VSC8502_RGMII_RX_DELAY_MASK 0x0070 + #define VSC8502_RGMII_TX_DELAY_MASK 0x0007 ++#define VSC8502_RGMII_RX_CLK_DISABLE 0x0800 + + #define MSCC_PHY_WOL_LOWER_MAC_ADDR 21 + #define MSCC_PHY_WOL_MID_MAC_ADDR 22 +diff --git a/drivers/net/phy/mscc/mscc_main.c b/drivers/net/phy/mscc/mscc_main.c +index f778e4f8b5080..7bd940baec595 100644 +--- a/drivers/net/phy/mscc/mscc_main.c ++++ b/drivers/net/phy/mscc/mscc_main.c +@@ -527,14 +527,27 @@ out_unlock: + * * 2.0 ns (which causes the data to be sampled at exactly half way between + * clock transitions at 1000 Mbps) if delays should be enabled + */ +-static int vsc85xx_rgmii_set_skews(struct phy_device *phydev, u32 rgmii_cntl, +- u16 rgmii_rx_delay_mask, +- u16 rgmii_tx_delay_mask) ++static int vsc85xx_update_rgmii_cntl(struct phy_device *phydev, u32 rgmii_cntl, ++ u16 rgmii_rx_delay_mask, ++ u16 rgmii_tx_delay_mask) + { + u16 rgmii_rx_delay_pos = ffs(rgmii_rx_delay_mask) - 1; + u16 rgmii_tx_delay_pos = ffs(rgmii_tx_delay_mask) - 1; + u16 reg_val = 0; +- int rc; ++ u16 mask = 0; ++ int rc = 0; ++ ++ /* For traffic to pass, the VSC8502 family needs the RX_CLK disable bit ++ * to be unset for all PHY modes, so do that as part of the paged ++ * register modification. ++ * For some family members (like VSC8530/31/40/41) this bit is reserved ++ * and read-only, and the RX clock is enabled by default. ++ */ ++ if (rgmii_cntl == VSC8502_RGMII_CNTL) ++ mask |= VSC8502_RGMII_RX_CLK_DISABLE; ++ ++ if (phy_interface_is_rgmii(phydev)) ++ mask |= rgmii_rx_delay_mask | rgmii_tx_delay_mask; + + mutex_lock(&phydev->lock); + +@@ -545,10 +558,9 @@ static int vsc85xx_rgmii_set_skews(struct phy_device *phydev, u32 rgmii_cntl, + phydev->interface == PHY_INTERFACE_MODE_RGMII_ID) + reg_val |= RGMII_CLK_DELAY_2_0_NS << rgmii_tx_delay_pos; + +- rc = phy_modify_paged(phydev, MSCC_PHY_PAGE_EXTENDED_2, +- rgmii_cntl, +- rgmii_rx_delay_mask | rgmii_tx_delay_mask, +- reg_val); ++ if (mask) ++ rc = phy_modify_paged(phydev, MSCC_PHY_PAGE_EXTENDED_2, ++ rgmii_cntl, mask, reg_val); + + mutex_unlock(&phydev->lock); + +@@ -557,19 +569,11 @@ static int vsc85xx_rgmii_set_skews(struct phy_device *phydev, u32 rgmii_cntl, + + static int vsc85xx_default_config(struct phy_device *phydev) + { +- int rc; +- + phydev->mdix_ctrl = ETH_TP_MDI_AUTO; + +- if (phy_interface_mode_is_rgmii(phydev->interface)) { +- rc = vsc85xx_rgmii_set_skews(phydev, VSC8502_RGMII_CNTL, +- VSC8502_RGMII_RX_DELAY_MASK, +- VSC8502_RGMII_TX_DELAY_MASK); +- if (rc) +- return rc; +- } +- +- return 0; ++ return vsc85xx_update_rgmii_cntl(phydev, VSC8502_RGMII_CNTL, ++ VSC8502_RGMII_RX_DELAY_MASK, ++ VSC8502_RGMII_TX_DELAY_MASK); + } + + static int vsc85xx_get_tunable(struct phy_device *phydev, +@@ -1766,13 +1770,11 @@ static int vsc8584_config_init(struct phy_device *phydev) + if (ret) + return ret; + +- if (phy_interface_is_rgmii(phydev)) { +- ret = vsc85xx_rgmii_set_skews(phydev, VSC8572_RGMII_CNTL, +- VSC8572_RGMII_RX_DELAY_MASK, +- VSC8572_RGMII_TX_DELAY_MASK); +- if (ret) +- return ret; +- } ++ ret = vsc85xx_update_rgmii_cntl(phydev, VSC8572_RGMII_CNTL, ++ VSC8572_RGMII_RX_DELAY_MASK, ++ VSC8572_RGMII_TX_DELAY_MASK); ++ if (ret) ++ return ret; + + ret = genphy_soft_reset(phydev); + if (ret) +diff --git a/drivers/net/wireless/intel/iwlwifi/fw/api/d3.h b/drivers/net/wireless/intel/iwlwifi/fw/api/d3.h +index df0833890e55a..8a613e150a024 100644 +--- a/drivers/net/wireless/intel/iwlwifi/fw/api/d3.h ++++ b/drivers/net/wireless/intel/iwlwifi/fw/api/d3.h +@@ -767,7 +767,7 @@ struct iwl_wowlan_status_v12 { + } __packed; /* WOWLAN_STATUSES_RSP_API_S_VER_12 */ + + /** +- * struct iwl_wowlan_info_notif - WoWLAN information notification ++ * struct iwl_wowlan_info_notif_v1 - WoWLAN information notification + * @gtk: GTK data + * @igtk: IGTK data + * @replay_ctr: GTK rekey replay counter +@@ -785,7 +785,7 @@ struct iwl_wowlan_status_v12 { + * @station_id: station id + * @reserved2: reserved + */ +-struct iwl_wowlan_info_notif { ++struct iwl_wowlan_info_notif_v1 { + struct iwl_wowlan_gtk_status_v3 gtk[WOWLAN_GTK_KEYS_NUM]; + struct iwl_wowlan_igtk_status igtk[WOWLAN_IGTK_KEYS_NUM]; + __le64 replay_ctr; +@@ -803,6 +803,39 @@ struct iwl_wowlan_info_notif { + u8 reserved2[2]; + } __packed; /* WOWLAN_INFO_NTFY_API_S_VER_1 */ + ++/** ++ * struct iwl_wowlan_info_notif - WoWLAN information notification ++ * @gtk: GTK data ++ * @igtk: IGTK data ++ * @replay_ctr: GTK rekey replay counter ++ * @pattern_number: number of the matched patterns ++ * @reserved1: reserved ++ * @qos_seq_ctr: QoS sequence counters to use next ++ * @wakeup_reasons: wakeup reasons, see &enum iwl_wowlan_wakeup_reason ++ * @num_of_gtk_rekeys: number of GTK rekeys ++ * @transmitted_ndps: number of transmitted neighbor discovery packets ++ * @received_beacons: number of received beacons ++ * @tid_tear_down: bit mask of tids whose BA sessions were closed ++ * in suspend state ++ * @station_id: station id ++ * @reserved2: reserved ++ */ ++struct iwl_wowlan_info_notif { ++ struct iwl_wowlan_gtk_status_v3 gtk[WOWLAN_GTK_KEYS_NUM]; ++ struct iwl_wowlan_igtk_status igtk[WOWLAN_IGTK_KEYS_NUM]; ++ __le64 replay_ctr; ++ __le16 pattern_number; ++ __le16 reserved1; ++ __le16 qos_seq_ctr[8]; ++ __le32 wakeup_reasons; ++ __le32 num_of_gtk_rekeys; ++ __le32 transmitted_ndps; ++ __le32 received_beacons; ++ u8 tid_tear_down; ++ u8 station_id; ++ u8 reserved2[2]; ++} __packed; /* WOWLAN_INFO_NTFY_API_S_VER_2 */ ++ + /** + * struct iwl_wowlan_wake_pkt_notif - WoWLAN wake packet notification + * @wake_packet_length: wakeup packet length +diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/d3.c b/drivers/net/wireless/intel/iwlwifi/mvm/d3.c +index bbdda3e1ff3fc..c876e81437fee 100644 +--- a/drivers/net/wireless/intel/iwlwifi/mvm/d3.c ++++ b/drivers/net/wireless/intel/iwlwifi/mvm/d3.c +@@ -2011,6 +2011,12 @@ static void iwl_mvm_parse_wowlan_info_notif(struct iwl_mvm *mvm, + { + u32 i; + ++ if (!data) { ++ IWL_ERR(mvm, "iwl_wowlan_info_notif data is NULL\n"); ++ status = NULL; ++ return; ++ } ++ + if (len < sizeof(*data)) { + IWL_ERR(mvm, "Invalid WoWLAN info notification!\n"); + status = NULL; +@@ -2698,10 +2704,15 @@ static bool iwl_mvm_wait_d3_notif(struct iwl_notif_wait_data *notif_wait, + struct iwl_d3_data *d3_data = data; + u32 len; + int ret; ++ int wowlan_info_ver = iwl_fw_lookup_notif_ver(mvm->fw, ++ PROT_OFFLOAD_GROUP, ++ WOWLAN_INFO_NOTIFICATION, ++ IWL_FW_CMD_VER_UNKNOWN); ++ + + switch (WIDE_ID(pkt->hdr.group_id, pkt->hdr.cmd)) { + case WIDE_ID(PROT_OFFLOAD_GROUP, WOWLAN_INFO_NOTIFICATION): { +- struct iwl_wowlan_info_notif *notif = (void *)pkt->data; ++ struct iwl_wowlan_info_notif *notif; + + if (d3_data->notif_received & IWL_D3_NOTIF_WOWLAN_INFO) { + /* We might get two notifications due to dual bss */ +@@ -2710,10 +2721,32 @@ static bool iwl_mvm_wait_d3_notif(struct iwl_notif_wait_data *notif_wait, + break; + } + ++ if (wowlan_info_ver < 2) { ++ struct iwl_wowlan_info_notif_v1 *notif_v1 = (void *)pkt->data; ++ ++ notif = kmemdup(notif_v1, ++ offsetofend(struct iwl_wowlan_info_notif, ++ received_beacons), ++ GFP_ATOMIC); ++ ++ if (!notif) ++ return false; ++ ++ notif->tid_tear_down = notif_v1->tid_tear_down; ++ notif->station_id = notif_v1->station_id; ++ ++ } else { ++ notif = (void *)pkt->data; ++ } ++ + d3_data->notif_received |= IWL_D3_NOTIF_WOWLAN_INFO; + len = iwl_rx_packet_payload_len(pkt); + iwl_mvm_parse_wowlan_info_notif(mvm, notif, d3_data->status, + len); ++ ++ if (wowlan_info_ver < 2) ++ kfree(notif); ++ + if (d3_data->status && + d3_data->status->wakeup_reasons & IWL_WOWLAN_WAKEUP_REASON_HAS_WAKEUP_PKT) + /* We are supposed to get also wake packet notif */ +diff --git a/drivers/net/wireless/realtek/rtw89/rtw8852c.c b/drivers/net/wireless/realtek/rtw89/rtw8852c.c +index 67653b3e1a356..3109114cec6ff 100644 +--- a/drivers/net/wireless/realtek/rtw89/rtw8852c.c ++++ b/drivers/net/wireless/realtek/rtw89/rtw8852c.c +@@ -1484,18 +1484,19 @@ static void rtw8852c_5m_mask(struct rtw89_dev *rtwdev, + const struct rtw89_chan *chan, + enum rtw89_phy_idx phy_idx) + { +- u8 pri_ch = chan->primary_channel; ++ u8 pri_ch = chan->pri_ch_idx; + bool mask_5m_low; + bool mask_5m_en; + + switch (chan->band_width) { + case RTW89_CHANNEL_WIDTH_40: + mask_5m_en = true; +- mask_5m_low = pri_ch == 2; ++ mask_5m_low = pri_ch == RTW89_SC_20_LOWER; + break; + case RTW89_CHANNEL_WIDTH_80: +- mask_5m_en = ((pri_ch == 3) || (pri_ch == 4)); +- mask_5m_low = pri_ch == 4; ++ mask_5m_en = pri_ch == RTW89_SC_20_UPMOST || ++ pri_ch == RTW89_SC_20_LOWEST; ++ mask_5m_low = pri_ch == RTW89_SC_20_LOWEST; + break; + default: + mask_5m_en = false; +diff --git a/drivers/platform/x86/amd/pmf/core.c b/drivers/platform/x86/amd/pmf/core.c +index 0acc0b6221290..dc9803e1a4b9b 100644 +--- a/drivers/platform/x86/amd/pmf/core.c ++++ b/drivers/platform/x86/amd/pmf/core.c +@@ -245,24 +245,29 @@ static const struct pci_device_id pmf_pci_ids[] = { + { } + }; + +-int amd_pmf_init_metrics_table(struct amd_pmf_dev *dev) ++static void amd_pmf_set_dram_addr(struct amd_pmf_dev *dev) + { + u64 phys_addr; + u32 hi, low; + +- INIT_DELAYED_WORK(&dev->work_buffer, amd_pmf_get_metrics); ++ phys_addr = virt_to_phys(dev->buf); ++ hi = phys_addr >> 32; ++ low = phys_addr & GENMASK(31, 0); ++ ++ amd_pmf_send_cmd(dev, SET_DRAM_ADDR_HIGH, 0, hi, NULL); ++ amd_pmf_send_cmd(dev, SET_DRAM_ADDR_LOW, 0, low, NULL); ++} + ++int amd_pmf_init_metrics_table(struct amd_pmf_dev *dev) ++{ + /* Get Metrics Table Address */ + dev->buf = kzalloc(sizeof(dev->m_table), GFP_KERNEL); + if (!dev->buf) + return -ENOMEM; + +- phys_addr = virt_to_phys(dev->buf); +- hi = phys_addr >> 32; +- low = phys_addr & GENMASK(31, 0); ++ INIT_DELAYED_WORK(&dev->work_buffer, amd_pmf_get_metrics); + +- amd_pmf_send_cmd(dev, SET_DRAM_ADDR_HIGH, 0, hi, NULL); +- amd_pmf_send_cmd(dev, SET_DRAM_ADDR_LOW, 0, low, NULL); ++ amd_pmf_set_dram_addr(dev); + + /* + * Start collecting the metrics data after a small delay +@@ -273,6 +278,18 @@ int amd_pmf_init_metrics_table(struct amd_pmf_dev *dev) + return 0; + } + ++static int amd_pmf_resume_handler(struct device *dev) ++{ ++ struct amd_pmf_dev *pdev = dev_get_drvdata(dev); ++ ++ if (pdev->buf) ++ amd_pmf_set_dram_addr(pdev); ++ ++ return 0; ++} ++ ++static DEFINE_SIMPLE_DEV_PM_OPS(amd_pmf_pm, NULL, amd_pmf_resume_handler); ++ + static void amd_pmf_init_features(struct amd_pmf_dev *dev) + { + int ret; +@@ -414,6 +431,7 @@ static struct platform_driver amd_pmf_driver = { + .name = "amd-pmf", + .acpi_match_table = amd_pmf_acpi_ids, + .dev_groups = amd_pmf_driver_groups, ++ .pm = pm_sleep_ptr(&amd_pmf_pm), + }, + .probe = amd_pmf_probe, + .remove = amd_pmf_remove, +diff --git a/drivers/vfio/vfio_iommu_type1.c b/drivers/vfio/vfio_iommu_type1.c +index 7fa68dc4e938a..009ba186652ac 100644 +--- a/drivers/vfio/vfio_iommu_type1.c ++++ b/drivers/vfio/vfio_iommu_type1.c +@@ -936,6 +936,11 @@ again: + if (ret) + goto pin_unwind; + ++ if (!pfn_valid(phys_pfn)) { ++ ret = -EINVAL; ++ goto pin_unwind; ++ } ++ + ret = vfio_add_to_pfn_list(dma, iova, phys_pfn); + if (ret) { + if (put_pfn(phys_pfn, dma->prot) && do_accounting) +diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h +index 20ca1613f2e3e..cc5ed2cf25f65 100644 +--- a/include/linux/skbuff.h ++++ b/include/linux/skbuff.h +@@ -1567,6 +1567,16 @@ static inline void skb_copy_hash(struct sk_buff *to, const struct sk_buff *from) + to->l4_hash = from->l4_hash; + }; + ++static inline int skb_cmp_decrypted(const struct sk_buff *skb1, ++ const struct sk_buff *skb2) ++{ ++#ifdef CONFIG_TLS_DEVICE ++ return skb2->decrypted - skb1->decrypted; ++#else ++ return 0; ++#endif ++} ++ + static inline void skb_copy_decrypted(struct sk_buff *to, + const struct sk_buff *from) + { +diff --git a/include/linux/skmsg.h b/include/linux/skmsg.h +index 84f787416a54d..054d7911bfc9f 100644 +--- a/include/linux/skmsg.h ++++ b/include/linux/skmsg.h +@@ -71,7 +71,6 @@ struct sk_psock_link { + }; + + struct sk_psock_work_state { +- struct sk_buff *skb; + u32 len; + u32 off; + }; +@@ -105,7 +104,7 @@ struct sk_psock { + struct proto *sk_proto; + struct mutex work_mutex; + struct sk_psock_work_state work_state; +- struct work_struct work; ++ struct delayed_work work; + struct rcu_work rwork; + }; + +diff --git a/include/net/inet_sock.h b/include/net/inet_sock.h +index bf5654ce711ef..51857117ac099 100644 +--- a/include/net/inet_sock.h ++++ b/include/net/inet_sock.h +@@ -249,6 +249,10 @@ struct inet_sock { + __be32 mc_addr; + struct ip_mc_socklist __rcu *mc_list; + struct inet_cork_full cork; ++ struct { ++ __u16 lo; ++ __u16 hi; ++ } local_port_range; + }; + + #define IPCORK_OPT 1 /* ip-options has been held in ipcork.opt */ +diff --git a/include/net/ip.h b/include/net/ip.h +index 144bdfbb25afe..acec504c469a0 100644 +--- a/include/net/ip.h ++++ b/include/net/ip.h +@@ -76,6 +76,7 @@ struct ipcm_cookie { + __be32 addr; + int oif; + struct ip_options_rcu *opt; ++ __u8 protocol; + __u8 ttl; + __s16 tos; + char priority; +@@ -96,6 +97,7 @@ static inline void ipcm_init_sk(struct ipcm_cookie *ipcm, + ipcm->sockc.tsflags = inet->sk.sk_tsflags; + ipcm->oif = READ_ONCE(inet->sk.sk_bound_dev_if); + ipcm->addr = inet->inet_saddr; ++ ipcm->protocol = inet->inet_num; + } + + #define IPCB(skb) ((struct inet_skb_parm*)((skb)->cb)) +@@ -340,7 +342,8 @@ static inline u64 snmp_fold_field64(void __percpu *mib, int offt, size_t syncp_o + } \ + } + +-void inet_get_local_port_range(struct net *net, int *low, int *high); ++void inet_get_local_port_range(const struct net *net, int *low, int *high); ++void inet_sk_get_local_port_range(const struct sock *sk, int *low, int *high); + + #ifdef CONFIG_SYSCTL + static inline bool inet_is_local_reserved_port(struct net *net, unsigned short port) +diff --git a/include/net/page_pool.h b/include/net/page_pool.h +index 813c93499f201..ad0bafc877d48 100644 +--- a/include/net/page_pool.h ++++ b/include/net/page_pool.h +@@ -383,22 +383,4 @@ static inline void page_pool_nid_changed(struct page_pool *pool, int new_nid) + page_pool_update_nid(pool, new_nid); + } + +-static inline void page_pool_ring_lock(struct page_pool *pool) +- __acquires(&pool->ring.producer_lock) +-{ +- if (in_serving_softirq()) +- spin_lock(&pool->ring.producer_lock); +- else +- spin_lock_bh(&pool->ring.producer_lock); +-} +- +-static inline void page_pool_ring_unlock(struct page_pool *pool) +- __releases(&pool->ring.producer_lock) +-{ +- if (in_serving_softirq()) +- spin_unlock(&pool->ring.producer_lock); +- else +- spin_unlock_bh(&pool->ring.producer_lock); +-} +- + #endif /* _NET_PAGE_POOL_H */ +diff --git a/include/net/tcp.h b/include/net/tcp.h +index 5b70b241ce71b..0744717f5caa7 100644 +--- a/include/net/tcp.h ++++ b/include/net/tcp.h +@@ -1467,6 +1467,8 @@ static inline void tcp_adjust_rcv_ssthresh(struct sock *sk) + } + + void tcp_cleanup_rbuf(struct sock *sk, int copied); ++void __tcp_cleanup_rbuf(struct sock *sk, int copied); ++ + + /* We provision sk_rcvbuf around 200% of sk_rcvlowat. + * If 87.5 % (7/8) of the space has been consumed, we want to override +@@ -2291,6 +2293,14 @@ int tcp_bpf_update_proto(struct sock *sk, struct sk_psock *psock, bool restore); + void tcp_bpf_clone(const struct sock *sk, struct sock *newsk); + #endif /* CONFIG_BPF_SYSCALL */ + ++#ifdef CONFIG_INET ++void tcp_eat_skb(struct sock *sk, struct sk_buff *skb); ++#else ++static inline void tcp_eat_skb(struct sock *sk, struct sk_buff *skb) ++{ ++} ++#endif ++ + int tcp_bpf_sendmsg_redir(struct sock *sk, bool ingress, + struct sk_msg *msg, u32 bytes, int flags); + #endif /* CONFIG_NET_SOCK_MSG */ +diff --git a/include/net/tls.h b/include/net/tls.h +index 154949c7b0c88..c36bf4c50027e 100644 +--- a/include/net/tls.h ++++ b/include/net/tls.h +@@ -124,6 +124,7 @@ struct tls_strparser { + u32 mark : 8; + u32 stopped : 1; + u32 copy_mode : 1; ++ u32 mixed_decrypted : 1; + u32 msg_ready : 1; + + struct strp_msg stm; +diff --git a/include/uapi/linux/in.h b/include/uapi/linux/in.h +index 07a4cb149305b..e682ab628dfa6 100644 +--- a/include/uapi/linux/in.h ++++ b/include/uapi/linux/in.h +@@ -162,6 +162,8 @@ struct in_addr { + #define MCAST_MSFILTER 48 + #define IP_MULTICAST_ALL 49 + #define IP_UNICAST_IF 50 ++#define IP_LOCAL_PORT_RANGE 51 ++#define IP_PROTOCOL 52 + + #define MCAST_EXCLUDE 0 + #define MCAST_INCLUDE 1 +diff --git a/net/bluetooth/hci_sock.c b/net/bluetooth/hci_sock.c +index f597fe0db9f8f..1d249d839819d 100644 +--- a/net/bluetooth/hci_sock.c ++++ b/net/bluetooth/hci_sock.c +@@ -987,6 +987,34 @@ static int hci_sock_ioctl(struct socket *sock, unsigned int cmd, + + BT_DBG("cmd %x arg %lx", cmd, arg); + ++ /* Make sure the cmd is valid before doing anything */ ++ switch (cmd) { ++ case HCIGETDEVLIST: ++ case HCIGETDEVINFO: ++ case HCIGETCONNLIST: ++ case HCIDEVUP: ++ case HCIDEVDOWN: ++ case HCIDEVRESET: ++ case HCIDEVRESTAT: ++ case HCISETSCAN: ++ case HCISETAUTH: ++ case HCISETENCRYPT: ++ case HCISETPTYPE: ++ case HCISETLINKPOL: ++ case HCISETLINKMODE: ++ case HCISETACLMTU: ++ case HCISETSCOMTU: ++ case HCIINQUIRY: ++ case HCISETRAW: ++ case HCIGETCONNINFO: ++ case HCIGETAUTHINFO: ++ case HCIBLOCKADDR: ++ case HCIUNBLOCKADDR: ++ break; ++ default: ++ return -ENOIOCTLCMD; ++ } ++ + lock_sock(sk); + + if (hci_pi(sk)->channel != HCI_CHANNEL_RAW) { +diff --git a/net/core/page_pool.c b/net/core/page_pool.c +index 9b203d8660e47..2396c99bedeaa 100644 +--- a/net/core/page_pool.c ++++ b/net/core/page_pool.c +@@ -133,6 +133,29 @@ EXPORT_SYMBOL(page_pool_ethtool_stats_get); + #define recycle_stat_add(pool, __stat, val) + #endif + ++static bool page_pool_producer_lock(struct page_pool *pool) ++ __acquires(&pool->ring.producer_lock) ++{ ++ bool in_softirq = in_softirq(); ++ ++ if (in_softirq) ++ spin_lock(&pool->ring.producer_lock); ++ else ++ spin_lock_bh(&pool->ring.producer_lock); ++ ++ return in_softirq; ++} ++ ++static void page_pool_producer_unlock(struct page_pool *pool, ++ bool in_softirq) ++ __releases(&pool->ring.producer_lock) ++{ ++ if (in_softirq) ++ spin_unlock(&pool->ring.producer_lock); ++ else ++ spin_unlock_bh(&pool->ring.producer_lock); ++} ++ + static int page_pool_init(struct page_pool *pool, + const struct page_pool_params *params) + { +@@ -511,8 +534,8 @@ static void page_pool_return_page(struct page_pool *pool, struct page *page) + static bool page_pool_recycle_in_ring(struct page_pool *pool, struct page *page) + { + int ret; +- /* BH protection not needed if current is serving softirq */ +- if (in_serving_softirq()) ++ /* BH protection not needed if current is softirq */ ++ if (in_softirq()) + ret = ptr_ring_produce(&pool->ring, page); + else + ret = ptr_ring_produce_bh(&pool->ring, page); +@@ -570,7 +593,7 @@ __page_pool_put_page(struct page_pool *pool, struct page *page, + page_pool_dma_sync_for_device(pool, page, + dma_sync_size); + +- if (allow_direct && in_serving_softirq() && ++ if (allow_direct && in_softirq() && + page_pool_recycle_in_cache(page, pool)) + return NULL; + +@@ -615,6 +638,7 @@ void page_pool_put_page_bulk(struct page_pool *pool, void **data, + int count) + { + int i, bulk_len = 0; ++ bool in_softirq; + + for (i = 0; i < count; i++) { + struct page *page = virt_to_head_page(data[i]); +@@ -633,7 +657,7 @@ void page_pool_put_page_bulk(struct page_pool *pool, void **data, + return; + + /* Bulk producer into ptr_ring page_pool cache */ +- page_pool_ring_lock(pool); ++ in_softirq = page_pool_producer_lock(pool); + for (i = 0; i < bulk_len; i++) { + if (__ptr_ring_produce(&pool->ring, data[i])) { + /* ring full */ +@@ -642,7 +666,7 @@ void page_pool_put_page_bulk(struct page_pool *pool, void **data, + } + } + recycle_stat_add(pool, ring, i); +- page_pool_ring_unlock(pool); ++ page_pool_producer_unlock(pool, in_softirq); + + /* Hopefully all pages was return into ptr_ring */ + if (likely(i == bulk_len)) +diff --git a/net/core/skmsg.c b/net/core/skmsg.c +index 53d0251788aa2..9e0f694515636 100644 +--- a/net/core/skmsg.c ++++ b/net/core/skmsg.c +@@ -480,8 +480,6 @@ int sk_msg_recvmsg(struct sock *sk, struct sk_psock *psock, struct msghdr *msg, + msg_rx = sk_psock_peek_msg(psock); + } + out: +- if (psock->work_state.skb && copied > 0) +- schedule_work(&psock->work); + return copied; + } + EXPORT_SYMBOL_GPL(sk_msg_recvmsg); +@@ -623,42 +621,33 @@ static int sk_psock_handle_skb(struct sk_psock *psock, struct sk_buff *skb, + + static void sk_psock_skb_state(struct sk_psock *psock, + struct sk_psock_work_state *state, +- struct sk_buff *skb, + int len, int off) + { + spin_lock_bh(&psock->ingress_lock); + if (sk_psock_test_state(psock, SK_PSOCK_TX_ENABLED)) { +- state->skb = skb; + state->len = len; + state->off = off; +- } else { +- sock_drop(psock->sk, skb); + } + spin_unlock_bh(&psock->ingress_lock); + } + + static void sk_psock_backlog(struct work_struct *work) + { +- struct sk_psock *psock = container_of(work, struct sk_psock, work); ++ struct delayed_work *dwork = to_delayed_work(work); ++ struct sk_psock *psock = container_of(dwork, struct sk_psock, work); + struct sk_psock_work_state *state = &psock->work_state; + struct sk_buff *skb = NULL; ++ u32 len = 0, off = 0; + bool ingress; +- u32 len, off; + int ret; + + mutex_lock(&psock->work_mutex); +- if (unlikely(state->skb)) { +- spin_lock_bh(&psock->ingress_lock); +- skb = state->skb; ++ if (unlikely(state->len)) { + len = state->len; + off = state->off; +- state->skb = NULL; +- spin_unlock_bh(&psock->ingress_lock); + } +- if (skb) +- goto start; + +- while ((skb = skb_dequeue(&psock->ingress_skb))) { ++ while ((skb = skb_peek(&psock->ingress_skb))) { + len = skb->len; + off = 0; + if (skb_bpf_strparser(skb)) { +@@ -667,7 +656,6 @@ static void sk_psock_backlog(struct work_struct *work) + off = stm->offset; + len = stm->full_len; + } +-start: + ingress = skb_bpf_ingress(skb); + skb_bpf_redirect_clear(skb); + do { +@@ -677,22 +665,28 @@ start: + len, ingress); + if (ret <= 0) { + if (ret == -EAGAIN) { +- sk_psock_skb_state(psock, state, skb, +- len, off); ++ sk_psock_skb_state(psock, state, len, off); ++ ++ /* Delay slightly to prioritize any ++ * other work that might be here. ++ */ ++ if (sk_psock_test_state(psock, SK_PSOCK_TX_ENABLED)) ++ schedule_delayed_work(&psock->work, 1); + goto end; + } + /* Hard errors break pipe and stop xmit. */ + sk_psock_report_error(psock, ret ? -ret : EPIPE); + sk_psock_clear_state(psock, SK_PSOCK_TX_ENABLED); +- sock_drop(psock->sk, skb); + goto end; + } + off += ret; + len -= ret; + } while (len); + +- if (!ingress) ++ skb = skb_dequeue(&psock->ingress_skb); ++ if (!ingress) { + kfree_skb(skb); ++ } + } + end: + mutex_unlock(&psock->work_mutex); +@@ -733,7 +727,7 @@ struct sk_psock *sk_psock_init(struct sock *sk, int node) + INIT_LIST_HEAD(&psock->link); + spin_lock_init(&psock->link_lock); + +- INIT_WORK(&psock->work, sk_psock_backlog); ++ INIT_DELAYED_WORK(&psock->work, sk_psock_backlog); + mutex_init(&psock->work_mutex); + INIT_LIST_HEAD(&psock->ingress_msg); + spin_lock_init(&psock->ingress_lock); +@@ -785,11 +779,6 @@ static void __sk_psock_zap_ingress(struct sk_psock *psock) + skb_bpf_redirect_clear(skb); + sock_drop(psock->sk, skb); + } +- kfree_skb(psock->work_state.skb); +- /* We null the skb here to ensure that calls to sk_psock_backlog +- * do not pick up the free'd skb. +- */ +- psock->work_state.skb = NULL; + __sk_psock_purge_ingress_msg(psock); + } + +@@ -808,7 +797,6 @@ void sk_psock_stop(struct sk_psock *psock) + spin_lock_bh(&psock->ingress_lock); + sk_psock_clear_state(psock, SK_PSOCK_TX_ENABLED); + sk_psock_cork_free(psock); +- __sk_psock_zap_ingress(psock); + spin_unlock_bh(&psock->ingress_lock); + } + +@@ -822,7 +810,8 @@ static void sk_psock_destroy(struct work_struct *work) + + sk_psock_done_strp(psock); + +- cancel_work_sync(&psock->work); ++ cancel_delayed_work_sync(&psock->work); ++ __sk_psock_zap_ingress(psock); + mutex_destroy(&psock->work_mutex); + + psock_progs_drop(&psock->progs); +@@ -937,7 +926,7 @@ static int sk_psock_skb_redirect(struct sk_psock *from, struct sk_buff *skb) + } + + skb_queue_tail(&psock_other->ingress_skb, skb); +- schedule_work(&psock_other->work); ++ schedule_delayed_work(&psock_other->work, 0); + spin_unlock_bh(&psock_other->ingress_lock); + return 0; + } +@@ -989,10 +978,8 @@ static int sk_psock_verdict_apply(struct sk_psock *psock, struct sk_buff *skb, + err = -EIO; + sk_other = psock->sk; + if (sock_flag(sk_other, SOCK_DEAD) || +- !sk_psock_test_state(psock, SK_PSOCK_TX_ENABLED)) { +- skb_bpf_redirect_clear(skb); ++ !sk_psock_test_state(psock, SK_PSOCK_TX_ENABLED)) + goto out_free; +- } + + skb_bpf_set_ingress(skb); + +@@ -1017,22 +1004,23 @@ static int sk_psock_verdict_apply(struct sk_psock *psock, struct sk_buff *skb, + spin_lock_bh(&psock->ingress_lock); + if (sk_psock_test_state(psock, SK_PSOCK_TX_ENABLED)) { + skb_queue_tail(&psock->ingress_skb, skb); +- schedule_work(&psock->work); ++ schedule_delayed_work(&psock->work, 0); + err = 0; + } + spin_unlock_bh(&psock->ingress_lock); +- if (err < 0) { +- skb_bpf_redirect_clear(skb); ++ if (err < 0) + goto out_free; +- } + } + break; + case __SK_REDIRECT: ++ tcp_eat_skb(psock->sk, skb); + err = sk_psock_skb_redirect(psock, skb); + break; + case __SK_DROP: + default: + out_free: ++ skb_bpf_redirect_clear(skb); ++ tcp_eat_skb(psock->sk, skb); + sock_drop(psock->sk, skb); + } + +@@ -1048,7 +1036,7 @@ static void sk_psock_write_space(struct sock *sk) + psock = sk_psock(sk); + if (likely(psock)) { + if (sk_psock_test_state(psock, SK_PSOCK_TX_ENABLED)) +- schedule_work(&psock->work); ++ schedule_delayed_work(&psock->work, 0); + write_space = psock->saved_write_space; + } + rcu_read_unlock(); +@@ -1077,8 +1065,7 @@ static void sk_psock_strp_read(struct strparser *strp, struct sk_buff *skb) + skb_dst_drop(skb); + skb_bpf_redirect_clear(skb); + ret = bpf_prog_run_pin_on_cpu(prog, skb); +- if (ret == SK_PASS) +- skb_bpf_set_strparser(skb); ++ skb_bpf_set_strparser(skb); + ret = sk_psock_map_verd(ret, skb_bpf_redirect_fetch(skb)); + skb->sk = NULL; + } +@@ -1180,12 +1167,11 @@ static int sk_psock_verdict_recv(struct sock *sk, struct sk_buff *skb) + int ret = __SK_DROP; + int len = skb->len; + +- skb_get(skb); +- + rcu_read_lock(); + psock = sk_psock(sk); + if (unlikely(!psock)) { + len = 0; ++ tcp_eat_skb(sk, skb); + sock_drop(sk, skb); + goto out; + } +@@ -1209,10 +1195,19 @@ out: + static void sk_psock_verdict_data_ready(struct sock *sk) + { + struct socket *sock = sk->sk_socket; ++ int copied; + + if (unlikely(!sock || !sock->ops || !sock->ops->read_skb)) + return; +- sock->ops->read_skb(sk, sk_psock_verdict_recv); ++ copied = sock->ops->read_skb(sk, sk_psock_verdict_recv); ++ if (copied >= 0) { ++ struct sk_psock *psock; ++ ++ rcu_read_lock(); ++ psock = sk_psock(sk); ++ psock->saved_data_ready(sk); ++ rcu_read_unlock(); ++ } + } + + void sk_psock_start_verdict(struct sock *sk, struct sk_psock *psock) +diff --git a/net/core/sock_map.c b/net/core/sock_map.c +index a68a7290a3b2b..d382672018928 100644 +--- a/net/core/sock_map.c ++++ b/net/core/sock_map.c +@@ -1624,9 +1624,10 @@ void sock_map_close(struct sock *sk, long timeout) + rcu_read_unlock(); + sk_psock_stop(psock); + release_sock(sk); +- cancel_work_sync(&psock->work); ++ cancel_delayed_work_sync(&psock->work); + sk_psock_put(sk, psock); + } ++ + /* Make sure we do not recurse. This is a bug. + * Leak the socket instead of crashing on a stack overflow. + */ +diff --git a/net/ipv4/inet_connection_sock.c b/net/ipv4/inet_connection_sock.c +index 7152ede18f115..916075e00d066 100644 +--- a/net/ipv4/inet_connection_sock.c ++++ b/net/ipv4/inet_connection_sock.c +@@ -117,7 +117,7 @@ bool inet_rcv_saddr_any(const struct sock *sk) + return !sk->sk_rcv_saddr; + } + +-void inet_get_local_port_range(struct net *net, int *low, int *high) ++void inet_get_local_port_range(const struct net *net, int *low, int *high) + { + unsigned int seq; + +@@ -130,6 +130,27 @@ void inet_get_local_port_range(struct net *net, int *low, int *high) + } + EXPORT_SYMBOL(inet_get_local_port_range); + ++void inet_sk_get_local_port_range(const struct sock *sk, int *low, int *high) ++{ ++ const struct inet_sock *inet = inet_sk(sk); ++ const struct net *net = sock_net(sk); ++ int lo, hi, sk_lo, sk_hi; ++ ++ inet_get_local_port_range(net, &lo, &hi); ++ ++ sk_lo = inet->local_port_range.lo; ++ sk_hi = inet->local_port_range.hi; ++ ++ if (unlikely(lo <= sk_lo && sk_lo <= hi)) ++ lo = sk_lo; ++ if (unlikely(lo <= sk_hi && sk_hi <= hi)) ++ hi = sk_hi; ++ ++ *low = lo; ++ *high = hi; ++} ++EXPORT_SYMBOL(inet_sk_get_local_port_range); ++ + static bool inet_use_bhash2_on_bind(const struct sock *sk) + { + #if IS_ENABLED(CONFIG_IPV6) +@@ -316,7 +337,7 @@ inet_csk_find_open_port(const struct sock *sk, struct inet_bind_bucket **tb_ret, + ports_exhausted: + attempt_half = (sk->sk_reuse == SK_CAN_REUSE) ? 1 : 0; + other_half_scan: +- inet_get_local_port_range(net, &low, &high); ++ inet_sk_get_local_port_range(sk, &low, &high); + high++; /* [32768, 60999] -> [32768, 61000[ */ + if (high - low < 4) + attempt_half = 0; +diff --git a/net/ipv4/inet_hashtables.c b/net/ipv4/inet_hashtables.c +index f0750c06d5ffc..e8734ffca85a8 100644 +--- a/net/ipv4/inet_hashtables.c ++++ b/net/ipv4/inet_hashtables.c +@@ -1022,7 +1022,7 @@ int __inet_hash_connect(struct inet_timewait_death_row *death_row, + + l3mdev = inet_sk_bound_l3mdev(sk); + +- inet_get_local_port_range(net, &low, &high); ++ inet_sk_get_local_port_range(sk, &low, &high); + high++; /* [32768, 60999] -> [32768, 61000[ */ + remaining = high - low; + if (likely(remaining > 1)) +diff --git a/net/ipv4/ip_sockglue.c b/net/ipv4/ip_sockglue.c +index 6e19cad154f5c..a7fd035b5b4f9 100644 +--- a/net/ipv4/ip_sockglue.c ++++ b/net/ipv4/ip_sockglue.c +@@ -317,7 +317,14 @@ int ip_cmsg_send(struct sock *sk, struct msghdr *msg, struct ipcm_cookie *ipc, + ipc->tos = val; + ipc->priority = rt_tos2priority(ipc->tos); + break; +- ++ case IP_PROTOCOL: ++ if (cmsg->cmsg_len != CMSG_LEN(sizeof(int))) ++ return -EINVAL; ++ val = *(int *)CMSG_DATA(cmsg); ++ if (val < 1 || val > 255) ++ return -EINVAL; ++ ipc->protocol = val; ++ break; + default: + return -EINVAL; + } +@@ -922,6 +929,7 @@ int do_ip_setsockopt(struct sock *sk, int level, int optname, + case IP_CHECKSUM: + case IP_RECVFRAGSIZE: + case IP_RECVERR_RFC4884: ++ case IP_LOCAL_PORT_RANGE: + if (optlen >= sizeof(int)) { + if (copy_from_sockptr(&val, optval, sizeof(val))) + return -EFAULT; +@@ -1364,6 +1372,20 @@ int do_ip_setsockopt(struct sock *sk, int level, int optname, + WRITE_ONCE(inet->min_ttl, val); + break; + ++ case IP_LOCAL_PORT_RANGE: ++ { ++ const __u16 lo = val; ++ const __u16 hi = val >> 16; ++ ++ if (optlen != sizeof(__u32)) ++ goto e_inval; ++ if (lo != 0 && hi != 0 && lo > hi) ++ goto e_inval; ++ ++ inet->local_port_range.lo = lo; ++ inet->local_port_range.hi = hi; ++ break; ++ } + default: + err = -ENOPROTOOPT; + break; +@@ -1742,6 +1764,12 @@ int do_ip_getsockopt(struct sock *sk, int level, int optname, + case IP_MINTTL: + val = inet->min_ttl; + break; ++ case IP_LOCAL_PORT_RANGE: ++ val = inet->local_port_range.hi << 16 | inet->local_port_range.lo; ++ break; ++ case IP_PROTOCOL: ++ val = inet_sk(sk)->inet_num; ++ break; + default: + sockopt_release_sock(sk); + return -ENOPROTOOPT; +diff --git a/net/ipv4/raw.c b/net/ipv4/raw.c +index af03aa8a8e513..86197634dcf5d 100644 +--- a/net/ipv4/raw.c ++++ b/net/ipv4/raw.c +@@ -530,6 +530,9 @@ static int raw_sendmsg(struct sock *sk, struct msghdr *msg, size_t len) + } + + ipcm_init_sk(&ipc, inet); ++ /* Keep backward compat */ ++ if (hdrincl) ++ ipc.protocol = IPPROTO_RAW; + + if (msg->msg_controllen) { + err = ip_cmsg_send(sk, msg, &ipc, false); +@@ -597,7 +600,7 @@ static int raw_sendmsg(struct sock *sk, struct msghdr *msg, size_t len) + + flowi4_init_output(&fl4, ipc.oif, ipc.sockc.mark, tos, + RT_SCOPE_UNIVERSE, +- hdrincl ? IPPROTO_RAW : sk->sk_protocol, ++ hdrincl ? ipc.protocol : sk->sk_protocol, + inet_sk_flowi_flags(sk) | + (hdrincl ? FLOWI_FLAG_KNOWN_NH : 0), + daddr, saddr, 0, 0, sk->sk_uid); +diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c +index 1fb67f819de49..021a8bf6a1898 100644 +--- a/net/ipv4/tcp.c ++++ b/net/ipv4/tcp.c +@@ -1570,7 +1570,7 @@ static int tcp_peek_sndq(struct sock *sk, struct msghdr *msg, int len) + * calculation of whether or not we must ACK for the sake of + * a window update. + */ +-static void __tcp_cleanup_rbuf(struct sock *sk, int copied) ++void __tcp_cleanup_rbuf(struct sock *sk, int copied) + { + struct tcp_sock *tp = tcp_sk(sk); + bool time_to_ack = false; +@@ -1772,7 +1772,6 @@ int tcp_read_skb(struct sock *sk, skb_read_actor_t recv_actor) + WARN_ON_ONCE(!skb_set_owner_sk_safe(skb, sk)); + tcp_flags = TCP_SKB_CB(skb)->tcp_flags; + used = recv_actor(sk, skb); +- consume_skb(skb); + if (used < 0) { + if (!copied) + copied = used; +@@ -1786,14 +1785,6 @@ int tcp_read_skb(struct sock *sk, skb_read_actor_t recv_actor) + break; + } + } +- WRITE_ONCE(tp->copied_seq, seq); +- +- tcp_rcv_space_adjust(sk); +- +- /* Clean up data we have read: This will do ACK frames. */ +- if (copied > 0) +- __tcp_cleanup_rbuf(sk, copied); +- + return copied; + } + EXPORT_SYMBOL(tcp_read_skb); +diff --git a/net/ipv4/tcp_bpf.c b/net/ipv4/tcp_bpf.c +index 2e9547467edbe..5f93918c063c7 100644 +--- a/net/ipv4/tcp_bpf.c ++++ b/net/ipv4/tcp_bpf.c +@@ -11,6 +11,24 @@ + #include <net/inet_common.h> + #include <net/tls.h> + ++void tcp_eat_skb(struct sock *sk, struct sk_buff *skb) ++{ ++ struct tcp_sock *tcp; ++ int copied; ++ ++ if (!skb || !skb->len || !sk_is_tcp(sk)) ++ return; ++ ++ if (skb_bpf_strparser(skb)) ++ return; ++ ++ tcp = tcp_sk(sk); ++ copied = tcp->copied_seq + skb->len; ++ WRITE_ONCE(tcp->copied_seq, copied); ++ tcp_rcv_space_adjust(sk); ++ __tcp_cleanup_rbuf(sk, skb->len); ++} ++ + static int bpf_tcp_ingress(struct sock *sk, struct sk_psock *psock, + struct sk_msg *msg, u32 apply_bytes, int flags) + { +@@ -174,14 +192,34 @@ static int tcp_msg_wait_data(struct sock *sk, struct sk_psock *psock, + return ret; + } + ++static bool is_next_msg_fin(struct sk_psock *psock) ++{ ++ struct scatterlist *sge; ++ struct sk_msg *msg_rx; ++ int i; ++ ++ msg_rx = sk_psock_peek_msg(psock); ++ i = msg_rx->sg.start; ++ sge = sk_msg_elem(msg_rx, i); ++ if (!sge->length) { ++ struct sk_buff *skb = msg_rx->skb; ++ ++ if (skb && TCP_SKB_CB(skb)->tcp_flags & TCPHDR_FIN) ++ return true; ++ } ++ return false; ++} ++ + static int tcp_bpf_recvmsg_parser(struct sock *sk, + struct msghdr *msg, + size_t len, + int flags, + int *addr_len) + { ++ struct tcp_sock *tcp = tcp_sk(sk); ++ u32 seq = tcp->copied_seq; + struct sk_psock *psock; +- int copied; ++ int copied = 0; + + if (unlikely(flags & MSG_ERRQUEUE)) + return inet_recv_error(sk, msg, len, addr_len); +@@ -194,8 +232,43 @@ static int tcp_bpf_recvmsg_parser(struct sock *sk, + return tcp_recvmsg(sk, msg, len, flags, addr_len); + + lock_sock(sk); ++ ++ /* We may have received data on the sk_receive_queue pre-accept and ++ * then we can not use read_skb in this context because we haven't ++ * assigned a sk_socket yet so have no link to the ops. The work-around ++ * is to check the sk_receive_queue and in these cases read skbs off ++ * queue again. The read_skb hook is not running at this point because ++ * of lock_sock so we avoid having multiple runners in read_skb. ++ */ ++ if (unlikely(!skb_queue_empty(&sk->sk_receive_queue))) { ++ tcp_data_ready(sk); ++ /* This handles the ENOMEM errors if we both receive data ++ * pre accept and are already under memory pressure. At least ++ * let user know to retry. ++ */ ++ if (unlikely(!skb_queue_empty(&sk->sk_receive_queue))) { ++ copied = -EAGAIN; ++ goto out; ++ } ++ } ++ + msg_bytes_ready: + copied = sk_msg_recvmsg(sk, psock, msg, len, flags); ++ /* The typical case for EFAULT is the socket was gracefully ++ * shutdown with a FIN pkt. So check here the other case is ++ * some error on copy_page_to_iter which would be unexpected. ++ * On fin return correct return code to zero. ++ */ ++ if (copied == -EFAULT) { ++ bool is_fin = is_next_msg_fin(psock); ++ ++ if (is_fin) { ++ copied = 0; ++ seq++; ++ goto out; ++ } ++ } ++ seq += copied; + if (!copied) { + long timeo; + int data; +@@ -233,6 +306,10 @@ msg_bytes_ready: + copied = -EAGAIN; + } + out: ++ WRITE_ONCE(tcp->copied_seq, seq); ++ tcp_rcv_space_adjust(sk); ++ if (copied > 0) ++ __tcp_cleanup_rbuf(sk, copied); + release_sock(sk); + sk_psock_put(sk, psock); + return copied; +diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c +index 2eaf47e23b221..956d6797c76f3 100644 +--- a/net/ipv4/udp.c ++++ b/net/ipv4/udp.c +@@ -243,7 +243,7 @@ int udp_lib_get_port(struct sock *sk, unsigned short snum, + int low, high, remaining; + unsigned int rand; + +- inet_get_local_port_range(net, &low, &high); ++ inet_sk_get_local_port_range(sk, &low, &high); + remaining = (high - low) + 1; + + rand = get_random_u32(); +@@ -1806,7 +1806,7 @@ EXPORT_SYMBOL(__skb_recv_udp); + int udp_read_skb(struct sock *sk, skb_read_actor_t recv_actor) + { + struct sk_buff *skb; +- int err, copied; ++ int err; + + try_again: + skb = skb_recv_udp(sk, MSG_DONTWAIT, &err); +@@ -1825,10 +1825,7 @@ try_again: + } + + WARN_ON_ONCE(!skb_set_owner_sk_safe(skb, sk)); +- copied = recv_actor(sk, skb); +- kfree_skb(skb); +- +- return copied; ++ return recv_actor(sk, skb); + } + EXPORT_SYMBOL(udp_read_skb); + +diff --git a/net/ipv6/raw.c b/net/ipv6/raw.c +index f44b99f7ecdcc..33852fc38ad91 100644 +--- a/net/ipv6/raw.c ++++ b/net/ipv6/raw.c +@@ -791,7 +791,8 @@ static int rawv6_sendmsg(struct sock *sk, struct msghdr *msg, size_t len) + + if (!proto) + proto = inet->inet_num; +- else if (proto != inet->inet_num) ++ else if (proto != inet->inet_num && ++ inet->inet_num != IPPROTO_RAW) + return -EINVAL; + + if (proto > 255) +diff --git a/net/netfilter/nf_conntrack_netlink.c b/net/netfilter/nf_conntrack_netlink.c +index cb4325b8ebb11..857cddd9d82e5 100644 +--- a/net/netfilter/nf_conntrack_netlink.c ++++ b/net/netfilter/nf_conntrack_netlink.c +@@ -1559,9 +1559,6 @@ static const struct nla_policy ct_nla_policy[CTA_MAX+1] = { + + static int ctnetlink_flush_iterate(struct nf_conn *ct, void *data) + { +- if (test_bit(IPS_OFFLOAD_BIT, &ct->status)) +- return 0; +- + return ctnetlink_filter_match(ct, data); + } + +@@ -1631,11 +1628,6 @@ static int ctnetlink_del_conntrack(struct sk_buff *skb, + + ct = nf_ct_tuplehash_to_ctrack(h); + +- if (test_bit(IPS_OFFLOAD_BIT, &ct->status)) { +- nf_ct_put(ct); +- return -EBUSY; +- } +- + if (cda[CTA_ID]) { + __be32 id = nla_get_be32(cda[CTA_ID]); + +diff --git a/net/sctp/socket.c b/net/sctp/socket.c +index 17185200079d5..bc3d08bd7cef3 100644 +--- a/net/sctp/socket.c ++++ b/net/sctp/socket.c +@@ -8325,7 +8325,7 @@ static int sctp_get_port_local(struct sock *sk, union sctp_addr *addr) + int low, high, remaining, index; + unsigned int rover; + +- inet_get_local_port_range(net, &low, &high); ++ inet_sk_get_local_port_range(sk, &low, &high); + remaining = (high - low) + 1; + rover = prandom_u32_max(remaining) + low; + +diff --git a/net/tls/tls.h b/net/tls/tls.h +index 0e840a0c3437b..17737a65c643a 100644 +--- a/net/tls/tls.h ++++ b/net/tls/tls.h +@@ -165,6 +165,11 @@ static inline bool tls_strp_msg_ready(struct tls_sw_context_rx *ctx) + return ctx->strp.msg_ready; + } + ++static inline bool tls_strp_msg_mixed_decrypted(struct tls_sw_context_rx *ctx) ++{ ++ return ctx->strp.mixed_decrypted; ++} ++ + #ifdef CONFIG_TLS_DEVICE + int tls_device_init(void); + void tls_device_cleanup(void); +diff --git a/net/tls/tls_device.c b/net/tls/tls_device.c +index a7cc4f9faac28..bf69c9d6d06c0 100644 +--- a/net/tls/tls_device.c ++++ b/net/tls/tls_device.c +@@ -1007,20 +1007,14 @@ int tls_device_decrypted(struct sock *sk, struct tls_context *tls_ctx) + struct tls_sw_context_rx *sw_ctx = tls_sw_ctx_rx(tls_ctx); + struct sk_buff *skb = tls_strp_msg(sw_ctx); + struct strp_msg *rxm = strp_msg(skb); +- int is_decrypted = skb->decrypted; +- int is_encrypted = !is_decrypted; +- struct sk_buff *skb_iter; +- int left; +- +- left = rxm->full_len - skb->len; +- /* Check if all the data is decrypted already */ +- skb_iter = skb_shinfo(skb)->frag_list; +- while (skb_iter && left > 0) { +- is_decrypted &= skb_iter->decrypted; +- is_encrypted &= !skb_iter->decrypted; +- +- left -= skb_iter->len; +- skb_iter = skb_iter->next; ++ int is_decrypted, is_encrypted; ++ ++ if (!tls_strp_msg_mixed_decrypted(sw_ctx)) { ++ is_decrypted = skb->decrypted; ++ is_encrypted = !is_decrypted; ++ } else { ++ is_decrypted = 0; ++ is_encrypted = 0; + } + + trace_tls_device_decrypted(sk, tcp_sk(sk)->copied_seq - rxm->full_len, +diff --git a/net/tls/tls_strp.c b/net/tls/tls_strp.c +index 955ac3e0bf4d3..da95abbb7ea32 100644 +--- a/net/tls/tls_strp.c ++++ b/net/tls/tls_strp.c +@@ -29,34 +29,50 @@ static void tls_strp_anchor_free(struct tls_strparser *strp) + struct skb_shared_info *shinfo = skb_shinfo(strp->anchor); + + DEBUG_NET_WARN_ON_ONCE(atomic_read(&shinfo->dataref) != 1); +- shinfo->frag_list = NULL; ++ if (!strp->copy_mode) ++ shinfo->frag_list = NULL; + consume_skb(strp->anchor); + strp->anchor = NULL; + } + +-/* Create a new skb with the contents of input copied to its page frags */ +-static struct sk_buff *tls_strp_msg_make_copy(struct tls_strparser *strp) ++static struct sk_buff * ++tls_strp_skb_copy(struct tls_strparser *strp, struct sk_buff *in_skb, ++ int offset, int len) + { +- struct strp_msg *rxm; + struct sk_buff *skb; +- int i, err, offset; ++ int i, err; + +- skb = alloc_skb_with_frags(0, strp->stm.full_len, TLS_PAGE_ORDER, ++ skb = alloc_skb_with_frags(0, len, TLS_PAGE_ORDER, + &err, strp->sk->sk_allocation); + if (!skb) + return NULL; + +- offset = strp->stm.offset; + for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) { + skb_frag_t *frag = &skb_shinfo(skb)->frags[i]; + +- WARN_ON_ONCE(skb_copy_bits(strp->anchor, offset, ++ WARN_ON_ONCE(skb_copy_bits(in_skb, offset, + skb_frag_address(frag), + skb_frag_size(frag))); + offset += skb_frag_size(frag); + } + +- skb_copy_header(skb, strp->anchor); ++ skb->len = len; ++ skb->data_len = len; ++ skb_copy_header(skb, in_skb); ++ return skb; ++} ++ ++/* Create a new skb with the contents of input copied to its page frags */ ++static struct sk_buff *tls_strp_msg_make_copy(struct tls_strparser *strp) ++{ ++ struct strp_msg *rxm; ++ struct sk_buff *skb; ++ ++ skb = tls_strp_skb_copy(strp, strp->anchor, strp->stm.offset, ++ strp->stm.full_len); ++ if (!skb) ++ return NULL; ++ + rxm = strp_msg(skb); + rxm->offset = 0; + return skb; +@@ -180,22 +196,22 @@ static void tls_strp_flush_anchor_copy(struct tls_strparser *strp) + for (i = 0; i < shinfo->nr_frags; i++) + __skb_frag_unref(&shinfo->frags[i], false); + shinfo->nr_frags = 0; ++ if (strp->copy_mode) { ++ kfree_skb_list(shinfo->frag_list); ++ shinfo->frag_list = NULL; ++ } + strp->copy_mode = 0; ++ strp->mixed_decrypted = 0; + } + +-static int tls_strp_copyin(read_descriptor_t *desc, struct sk_buff *in_skb, +- unsigned int offset, size_t in_len) ++static int tls_strp_copyin_frag(struct tls_strparser *strp, struct sk_buff *skb, ++ struct sk_buff *in_skb, unsigned int offset, ++ size_t in_len) + { +- struct tls_strparser *strp = (struct tls_strparser *)desc->arg.data; +- struct sk_buff *skb; +- skb_frag_t *frag; + size_t len, chunk; ++ skb_frag_t *frag; + int sz; + +- if (strp->msg_ready) +- return 0; +- +- skb = strp->anchor; + frag = &skb_shinfo(skb)->frags[skb->len / PAGE_SIZE]; + + len = in_len; +@@ -208,19 +224,26 @@ static int tls_strp_copyin(read_descriptor_t *desc, struct sk_buff *in_skb, + skb_frag_size(frag), + chunk)); + +- sz = tls_rx_msg_size(strp, strp->anchor); +- if (sz < 0) { +- desc->error = sz; +- return 0; +- } +- +- /* We may have over-read, sz == 0 is guaranteed under-read */ +- if (sz > 0) +- chunk = min_t(size_t, chunk, sz - skb->len); +- + skb->len += chunk; + skb->data_len += chunk; + skb_frag_size_add(frag, chunk); ++ ++ sz = tls_rx_msg_size(strp, skb); ++ if (sz < 0) ++ return sz; ++ ++ /* We may have over-read, sz == 0 is guaranteed under-read */ ++ if (unlikely(sz && sz < skb->len)) { ++ int over = skb->len - sz; ++ ++ WARN_ON_ONCE(over > chunk); ++ skb->len -= over; ++ skb->data_len -= over; ++ skb_frag_size_add(frag, -over); ++ ++ chunk -= over; ++ } ++ + frag++; + len -= chunk; + offset += chunk; +@@ -247,15 +270,99 @@ static int tls_strp_copyin(read_descriptor_t *desc, struct sk_buff *in_skb, + offset += chunk; + } + +- if (strp->stm.full_len == skb->len) { ++read_done: ++ return in_len - len; ++} ++ ++static int tls_strp_copyin_skb(struct tls_strparser *strp, struct sk_buff *skb, ++ struct sk_buff *in_skb, unsigned int offset, ++ size_t in_len) ++{ ++ struct sk_buff *nskb, *first, *last; ++ struct skb_shared_info *shinfo; ++ size_t chunk; ++ int sz; ++ ++ if (strp->stm.full_len) ++ chunk = strp->stm.full_len - skb->len; ++ else ++ chunk = TLS_MAX_PAYLOAD_SIZE + PAGE_SIZE; ++ chunk = min(chunk, in_len); ++ ++ nskb = tls_strp_skb_copy(strp, in_skb, offset, chunk); ++ if (!nskb) ++ return -ENOMEM; ++ ++ shinfo = skb_shinfo(skb); ++ if (!shinfo->frag_list) { ++ shinfo->frag_list = nskb; ++ nskb->prev = nskb; ++ } else { ++ first = shinfo->frag_list; ++ last = first->prev; ++ last->next = nskb; ++ first->prev = nskb; ++ } ++ ++ skb->len += chunk; ++ skb->data_len += chunk; ++ ++ if (!strp->stm.full_len) { ++ sz = tls_rx_msg_size(strp, skb); ++ if (sz < 0) ++ return sz; ++ ++ /* We may have over-read, sz == 0 is guaranteed under-read */ ++ if (unlikely(sz && sz < skb->len)) { ++ int over = skb->len - sz; ++ ++ WARN_ON_ONCE(over > chunk); ++ skb->len -= over; ++ skb->data_len -= over; ++ __pskb_trim(nskb, nskb->len - over); ++ ++ chunk -= over; ++ } ++ ++ strp->stm.full_len = sz; ++ } ++ ++ return chunk; ++} ++ ++static int tls_strp_copyin(read_descriptor_t *desc, struct sk_buff *in_skb, ++ unsigned int offset, size_t in_len) ++{ ++ struct tls_strparser *strp = (struct tls_strparser *)desc->arg.data; ++ struct sk_buff *skb; ++ int ret; ++ ++ if (strp->msg_ready) ++ return 0; ++ ++ skb = strp->anchor; ++ if (!skb->len) ++ skb_copy_decrypted(skb, in_skb); ++ else ++ strp->mixed_decrypted |= !!skb_cmp_decrypted(skb, in_skb); ++ ++ if (IS_ENABLED(CONFIG_TLS_DEVICE) && strp->mixed_decrypted) ++ ret = tls_strp_copyin_skb(strp, skb, in_skb, offset, in_len); ++ else ++ ret = tls_strp_copyin_frag(strp, skb, in_skb, offset, in_len); ++ if (ret < 0) { ++ desc->error = ret; ++ ret = 0; ++ } ++ ++ if (strp->stm.full_len && strp->stm.full_len == skb->len) { + desc->count = 0; + + strp->msg_ready = 1; + tls_rx_msg_ready(strp); + } + +-read_done: +- return in_len - len; ++ return ret; + } + + static int tls_strp_read_copyin(struct tls_strparser *strp) +@@ -315,15 +422,19 @@ static int tls_strp_read_copy(struct tls_strparser *strp, bool qshort) + return 0; + } + +-static bool tls_strp_check_no_dup(struct tls_strparser *strp) ++static bool tls_strp_check_queue_ok(struct tls_strparser *strp) + { + unsigned int len = strp->stm.offset + strp->stm.full_len; +- struct sk_buff *skb; ++ struct sk_buff *first, *skb; + u32 seq; + +- skb = skb_shinfo(strp->anchor)->frag_list; +- seq = TCP_SKB_CB(skb)->seq; ++ first = skb_shinfo(strp->anchor)->frag_list; ++ skb = first; ++ seq = TCP_SKB_CB(first)->seq; + ++ /* Make sure there's no duplicate data in the queue, ++ * and the decrypted status matches. ++ */ + while (skb->len < len) { + seq += skb->len; + len -= skb->len; +@@ -331,6 +442,8 @@ static bool tls_strp_check_no_dup(struct tls_strparser *strp) + + if (TCP_SKB_CB(skb)->seq != seq) + return false; ++ if (skb_cmp_decrypted(first, skb)) ++ return false; + } + + return true; +@@ -411,7 +524,7 @@ static int tls_strp_read_sock(struct tls_strparser *strp) + return tls_strp_read_copy(strp, true); + } + +- if (!tls_strp_check_no_dup(strp)) ++ if (!tls_strp_check_queue_ok(strp)) + return tls_strp_read_copy(strp, false); + + strp->msg_ready = 1; +diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c +index 70eb3bc67126d..5b19b6c53a2cb 100644 +--- a/net/unix/af_unix.c ++++ b/net/unix/af_unix.c +@@ -2552,7 +2552,7 @@ static int unix_read_skb(struct sock *sk, skb_read_actor_t recv_actor) + { + struct unix_sock *u = unix_sk(sk); + struct sk_buff *skb; +- int err, copied; ++ int err; + + mutex_lock(&u->iolock); + skb = skb_recv_datagram(sk, MSG_DONTWAIT, &err); +@@ -2560,10 +2560,7 @@ static int unix_read_skb(struct sock *sk, skb_read_actor_t recv_actor) + if (!skb) + return err; + +- copied = recv_actor(sk, skb); +- kfree_skb(skb); +- +- return copied; ++ return recv_actor(sk, skb); + } + + /* +diff --git a/tools/include/uapi/linux/in.h b/tools/include/uapi/linux/in.h +index 07a4cb149305b..4b7f2df66b995 100644 +--- a/tools/include/uapi/linux/in.h ++++ b/tools/include/uapi/linux/in.h +@@ -162,6 +162,7 @@ struct in_addr { + #define MCAST_MSFILTER 48 + #define IP_MULTICAST_ALL 49 + #define IP_UNICAST_IF 50 ++#define IP_LOCAL_PORT_RANGE 51 + + #define MCAST_EXCLUDE 0 + #define MCAST_INCLUDE 1 +diff --git a/tools/testing/selftests/bpf/Makefile b/tools/testing/selftests/bpf/Makefile +index 687249d99b5f1..0465ddc81f352 100644 +--- a/tools/testing/selftests/bpf/Makefile ++++ b/tools/testing/selftests/bpf/Makefile +@@ -193,7 +193,7 @@ $(OUTPUT)/urandom_read: urandom_read.c urandom_read_aux.c $(OUTPUT)/liburandom_r + + $(OUTPUT)/sign-file: ../../../../scripts/sign-file.c + $(call msg,SIGN-FILE,,$@) +- $(Q)$(CC) $(shell $(HOSTPKG_CONFIG)--cflags libcrypto 2> /dev/null) \ ++ $(Q)$(CC) $(shell $(HOSTPKG_CONFIG) --cflags libcrypto 2> /dev/null) \ + $< -o $@ \ + $(shell $(HOSTPKG_CONFIG) --libs libcrypto 2> /dev/null || echo -lcrypto) +
