Import of kernel-6.12.0-124.27.1.el10_1

This commit is contained in:
almalinux-bot-kernel 2026-01-15 04:20:26 +00:00
parent d0ce8b55b0
commit 85c1100e1e
77 changed files with 1982 additions and 150 deletions

View File

@ -49,3 +49,17 @@ The ``zl3073x`` driver reports the following versions
- running
- 1.3.0.1
- Device configuration version customized by OEM
Flash Update
============
The ``zl3073x`` driver implements support for flash update using the
``devlink-flash`` interface. It supports updating the device flash using a
combined flash image ("bundle") that contains multiple components (firmware
parts and configurations).
During the flash procedure, the standard firmware interface is not available,
so the driver unregisters all DPLLs and associated pins, and re-registers them
once the flash procedure is complete.
The driver does not support any overwrite mask flags.

View File

@ -12,7 +12,7 @@ RHEL_MINOR = 1
#
# Use this spot to avoid future merge conflicts.
# Do not trim this comment.
RHEL_RELEASE = 124.21.1
RHEL_RELEASE = 124.27.1
#
# RHEL_REBASE_NUM

View File

@ -75,6 +75,7 @@
#define ARM_CPU_PART_CORTEX_A76 0xD0B
#define ARM_CPU_PART_NEOVERSE_N1 0xD0C
#define ARM_CPU_PART_CORTEX_A77 0xD0D
#define ARM_CPU_PART_CORTEX_A76AE 0xD0E
#define ARM_CPU_PART_NEOVERSE_V1 0xD40
#define ARM_CPU_PART_CORTEX_A78 0xD41
#define ARM_CPU_PART_CORTEX_A78AE 0xD42
@ -95,6 +96,7 @@
#define ARM_CPU_PART_NEOVERSE_V3 0xD84
#define ARM_CPU_PART_CORTEX_X925 0xD85
#define ARM_CPU_PART_CORTEX_A725 0xD87
#define ARM_CPU_PART_CORTEX_A720AE 0xD89
#define ARM_CPU_PART_NEOVERSE_N3 0xD8E
#define APM_CPU_PART_XGENE 0x000
@ -131,6 +133,7 @@
#define FUJITSU_CPU_PART_A64FX 0x001
#define HISI_CPU_PART_TSV110 0xD01
#define HISI_CPU_PART_HIP09 0xD02
#define APPLE_CPU_PART_M1_ICESTORM 0x022
#define APPLE_CPU_PART_M1_FIRESTORM 0x023
@ -160,6 +163,7 @@
#define MIDR_CORTEX_A76 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_A76)
#define MIDR_NEOVERSE_N1 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_NEOVERSE_N1)
#define MIDR_CORTEX_A77 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_A77)
#define MIDR_CORTEX_A76AE MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_A76AE)
#define MIDR_NEOVERSE_V1 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_NEOVERSE_V1)
#define MIDR_CORTEX_A78 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_A78)
#define MIDR_CORTEX_A78AE MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_A78AE)
@ -180,6 +184,7 @@
#define MIDR_NEOVERSE_V3 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_NEOVERSE_V3)
#define MIDR_CORTEX_X925 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_X925)
#define MIDR_CORTEX_A725 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_A725)
#define MIDR_CORTEX_A720AE MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_A720AE)
#define MIDR_NEOVERSE_N3 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_NEOVERSE_N3)
#define MIDR_THUNDERX MIDR_CPU_MODEL(ARM_CPU_IMP_CAVIUM, CAVIUM_CPU_PART_THUNDERX)
#define MIDR_THUNDERX_81XX MIDR_CPU_MODEL(ARM_CPU_IMP_CAVIUM, CAVIUM_CPU_PART_THUNDERX_81XX)
@ -206,6 +211,7 @@
#define MIDR_NVIDIA_CARMEL MIDR_CPU_MODEL(ARM_CPU_IMP_NVIDIA, NVIDIA_CPU_PART_CARMEL)
#define MIDR_FUJITSU_A64FX MIDR_CPU_MODEL(ARM_CPU_IMP_FUJITSU, FUJITSU_CPU_PART_A64FX)
#define MIDR_HISI_TSV110 MIDR_CPU_MODEL(ARM_CPU_IMP_HISI, HISI_CPU_PART_TSV110)
#define MIDR_HISI_HIP09 MIDR_CPU_MODEL(ARM_CPU_IMP_HISI, HISI_CPU_PART_HIP09)
#define MIDR_APPLE_M1_ICESTORM MIDR_CPU_MODEL(ARM_CPU_IMP_APPLE, APPLE_CPU_PART_M1_ICESTORM)
#define MIDR_APPLE_M1_FIRESTORM MIDR_CPU_MODEL(ARM_CPU_IMP_APPLE, APPLE_CPU_PART_M1_FIRESTORM)
#define MIDR_APPLE_M1_ICESTORM_PRO MIDR_CPU_MODEL(ARM_CPU_IMP_APPLE, APPLE_CPU_PART_M1_ICESTORM_PRO)

View File

@ -494,6 +494,7 @@ static const struct midr_range erratum_spec_ssbs_list[] = {
MIDR_ALL_VERSIONS(MIDR_CORTEX_A710),
MIDR_ALL_VERSIONS(MIDR_CORTEX_A715),
MIDR_ALL_VERSIONS(MIDR_CORTEX_A720),
MIDR_ALL_VERSIONS(MIDR_CORTEX_A720AE),
MIDR_ALL_VERSIONS(MIDR_CORTEX_A725),
MIDR_ALL_VERSIONS(MIDR_CORTEX_X1),
MIDR_ALL_VERSIONS(MIDR_CORTEX_X1C),

View File

@ -854,6 +854,9 @@ static bool is_spectre_bhb_safe(int scope)
MIDR_ALL_VERSIONS(MIDR_CORTEX_A510),
MIDR_ALL_VERSIONS(MIDR_CORTEX_A520),
MIDR_ALL_VERSIONS(MIDR_BRAHMA_B53),
MIDR_ALL_VERSIONS(MIDR_QCOM_KRYO_2XX_SILVER),
MIDR_ALL_VERSIONS(MIDR_QCOM_KRYO_3XX_SILVER),
MIDR_ALL_VERSIONS(MIDR_QCOM_KRYO_4XX_SILVER),
{},
};
static bool all_safe = true;
@ -873,6 +876,17 @@ static u8 spectre_bhb_loop_affected(void)
{
u8 k = 0;
static const struct midr_range spectre_bhb_k132_list[] = {
MIDR_ALL_VERSIONS(MIDR_CORTEX_X3),
MIDR_ALL_VERSIONS(MIDR_NEOVERSE_V2),
{},
};
static const struct midr_range spectre_bhb_k38_list[] = {
MIDR_ALL_VERSIONS(MIDR_CORTEX_A715),
MIDR_ALL_VERSIONS(MIDR_CORTEX_A720),
MIDR_ALL_VERSIONS(MIDR_CORTEX_A720AE),
{},
};
static const struct midr_range spectre_bhb_k32_list[] = {
MIDR_ALL_VERSIONS(MIDR_CORTEX_A78),
MIDR_ALL_VERSIONS(MIDR_CORTEX_A78AE),
@ -887,9 +901,11 @@ static u8 spectre_bhb_loop_affected(void)
};
static const struct midr_range spectre_bhb_k24_list[] = {
MIDR_ALL_VERSIONS(MIDR_CORTEX_A76),
MIDR_ALL_VERSIONS(MIDR_CORTEX_A76AE),
MIDR_ALL_VERSIONS(MIDR_CORTEX_A77),
MIDR_ALL_VERSIONS(MIDR_NEOVERSE_N1),
MIDR_ALL_VERSIONS(MIDR_QCOM_KRYO_4XX_GOLD),
MIDR_ALL_VERSIONS(MIDR_HISI_HIP09),
{},
};
static const struct midr_range spectre_bhb_k11_list[] = {
@ -902,7 +918,11 @@ static u8 spectre_bhb_loop_affected(void)
{},
};
if (is_midr_in_range_list(spectre_bhb_k32_list))
if (is_midr_in_range_list(spectre_bhb_k132_list))
k = 132;
else if (is_midr_in_range_list(spectre_bhb_k38_list))
k = 38;
else if (is_midr_in_range_list(spectre_bhb_k32_list))
k = 32;
else if (is_midr_in_range_list(spectre_bhb_k24_list))
k = 24;

View File

@ -500,6 +500,9 @@ CONFIG_PPC_TRANSACTIONAL_MEM=y
CONFIG_PPC_UV=y
# CONFIG_LD_HEAD_STUB_CATCH is not set
CONFIG_MPROFILE_KERNEL=y
CONFIG_ARCH_USING_PATCHABLE_FUNCTION_ENTRY=y
CONFIG_PPC_FTRACE_OUT_OF_LINE=y
CONFIG_PPC_FTRACE_OUT_OF_LINE_NUM_RESERVE=32768
CONFIG_HOTPLUG_CPU=y
CONFIG_INTERRUPT_SANITIZE_REGISTERS=y
CONFIG_PPC_QUEUED_SPINLOCKS=y
@ -722,6 +725,7 @@ CONFIG_FUNCTION_ALIGNMENT_4B=y
CONFIG_FUNCTION_ALIGNMENT=4
CONFIG_CC_HAS_MIN_FUNCTION_ALIGNMENT=y
CONFIG_CC_HAS_SANE_FUNCTION_ALIGNMENT=y
CONFIG_ARCH_WANTS_PRE_LINK_VMLINUX=y
# end of General architecture-dependent options
CONFIG_RT_MUTEXES=y
@ -5026,6 +5030,7 @@ CONFIG_HID_KUNIT_TEST=m
#
# HID-BPF support
#
CONFIG_HID_BPF=y
# end of HID-BPF support
CONFIG_I2C_HID=y
@ -7127,6 +7132,8 @@ CONFIG_HAVE_FUNCTION_TRACER=y
CONFIG_HAVE_FUNCTION_GRAPH_TRACER=y
CONFIG_HAVE_DYNAMIC_FTRACE=y
CONFIG_HAVE_DYNAMIC_FTRACE_WITH_REGS=y
CONFIG_HAVE_DYNAMIC_FTRACE_WITH_DIRECT_CALLS=y
CONFIG_HAVE_DYNAMIC_FTRACE_WITH_CALL_OPS=y
CONFIG_HAVE_DYNAMIC_FTRACE_WITH_ARGS=y
CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
CONFIG_HAVE_SYSCALL_TRACEPOINTS=y
@ -7147,6 +7154,8 @@ CONFIG_FUNCTION_TRACER=y
CONFIG_FUNCTION_GRAPH_TRACER=y
CONFIG_DYNAMIC_FTRACE=y
CONFIG_DYNAMIC_FTRACE_WITH_REGS=y
CONFIG_DYNAMIC_FTRACE_WITH_DIRECT_CALLS=y
CONFIG_DYNAMIC_FTRACE_WITH_CALL_OPS=y
CONFIG_DYNAMIC_FTRACE_WITH_ARGS=y
CONFIG_FPROBE=y
CONFIG_FUNCTION_PROFILER=y
@ -7171,7 +7180,7 @@ CONFIG_BPF_EVENTS=y
CONFIG_DYNAMIC_EVENTS=y
CONFIG_PROBE_EVENTS=y
CONFIG_FTRACE_MCOUNT_RECORD=y
CONFIG_FTRACE_MCOUNT_USE_CC=y
CONFIG_FTRACE_MCOUNT_USE_PATCHABLE_FUNCTION_ENTRY=y
CONFIG_TRACING_MAP=y
CONFIG_SYNTH_EVENTS=y
# CONFIG_USER_EVENTS is not set
@ -7197,6 +7206,8 @@ CONFIG_RV_REACTORS=y
CONFIG_RV_REACT_PRINTK=y
CONFIG_RV_REACT_PANIC=y
# CONFIG_SAMPLES is not set
CONFIG_HAVE_SAMPLE_FTRACE_DIRECT=y
CONFIG_HAVE_SAMPLE_FTRACE_DIRECT_MULTI=y
CONFIG_ARCH_HAS_DEVMEM_IS_ALLOWED=y
CONFIG_STRICT_DEVMEM=y
# CONFIG_IO_STRICT_DEVMEM is not set

View File

@ -1,7 +1,7 @@
# SPDX-License-Identifier: GPL-2.0
obj-$(CONFIG_ZL3073X) += zl3073x.o
zl3073x-objs := core.o devlink.o dpll.o prop.o
zl3073x-objs := core.o devlink.o dpll.o flash.o fw.o prop.o
obj-$(CONFIG_ZL3073X_I2C) += zl3073x_i2c.o
zl3073x_i2c-objs := i2c.o

View File

@ -95,9 +95,9 @@ EXPORT_SYMBOL_NS_GPL(zl30735_chip_info, "ZL3073X");
#define ZL_RANGE_OFFSET 0x80
#define ZL_PAGE_SIZE 0x80
#define ZL_NUM_PAGES 15
#define ZL_NUM_PAGES 256
#define ZL_PAGE_SEL 0x7F
#define ZL_PAGE_SEL_MASK GENMASK(3, 0)
#define ZL_PAGE_SEL_MASK GENMASK(7, 0)
#define ZL_NUM_REGS (ZL_NUM_PAGES * ZL_PAGE_SIZE)
/* Regmap range configuration */
@ -174,9 +174,10 @@ static bool
zl3073x_check_reg(struct zl3073x_dev *zldev, unsigned int reg, size_t size)
{
/* Check that multiop lock is held when accessing registers
* from page 10 and above.
* from page 10 and above except the page 255 that does not
* need this protection.
*/
if (ZL_REG_PAGE(reg) >= 10)
if (ZL_REG_PAGE(reg) >= 10 && ZL_REG_PAGE(reg) < 255)
lockdep_assert_held(&zldev->multiop_lock);
/* Check the index is in valid range for indexed register */
@ -446,6 +447,152 @@ int zl3073x_mb_op(struct zl3073x_dev *zldev, unsigned int op_reg, u8 op_val,
return zl3073x_poll_zero_u8(zldev, op_reg, op_val);
}
/**
* zl3073x_do_hwreg_op - Perform HW register read/write operation
* @zldev: zl3073x device pointer
* @op: operation to perform
*
* Performs requested operation and waits for its completion.
*
* Return: 0 on success, <0 on error
*/
static int
zl3073x_do_hwreg_op(struct zl3073x_dev *zldev, u8 op)
{
int rc;
/* Set requested operation and set pending bit */
rc = zl3073x_write_u8(zldev, ZL_REG_HWREG_OP, op | ZL_HWREG_OP_PENDING);
if (rc)
return rc;
/* Poll for completion - pending bit cleared */
return zl3073x_poll_zero_u8(zldev, ZL_REG_HWREG_OP,
ZL_HWREG_OP_PENDING);
}
/**
* zl3073x_read_hwreg - Read HW register
* @zldev: zl3073x device pointer
* @addr: HW register address
* @value: Value of the HW register
*
* Reads HW register value and stores it into @value.
*
* Return: 0 on success, <0 on error
*/
int zl3073x_read_hwreg(struct zl3073x_dev *zldev, u32 addr, u32 *value)
{
int rc;
/* Set address to read data from */
rc = zl3073x_write_u32(zldev, ZL_REG_HWREG_ADDR, addr);
if (rc)
return rc;
/* Perform the read operation */
rc = zl3073x_do_hwreg_op(zldev, ZL_HWREG_OP_READ);
if (rc)
return rc;
/* Read the received data */
return zl3073x_read_u32(zldev, ZL_REG_HWREG_READ_DATA, value);
}
/**
* zl3073x_write_hwreg - Write value to HW register
* @zldev: zl3073x device pointer
* @addr: HW registers address
* @value: Value to be written to HW register
*
* Stores the requested value into HW register.
*
* Return: 0 on success, <0 on error
*/
int zl3073x_write_hwreg(struct zl3073x_dev *zldev, u32 addr, u32 value)
{
int rc;
/* Set address to write data to */
rc = zl3073x_write_u32(zldev, ZL_REG_HWREG_ADDR, addr);
if (rc)
return rc;
/* Set data to be written */
rc = zl3073x_write_u32(zldev, ZL_REG_HWREG_WRITE_DATA, value);
if (rc)
return rc;
/* Perform the write operation */
return zl3073x_do_hwreg_op(zldev, ZL_HWREG_OP_WRITE);
}
/**
* zl3073x_update_hwreg - Update certain bits in HW register
* @zldev: zl3073x device pointer
* @addr: HW register address
* @value: Value to be written into HW register
* @mask: Bitmask indicating bits to be updated
*
* Reads given HW register, updates requested bits specified by value and
* mask and writes result back to HW register.
*
* Return: 0 on success, <0 on error
*/
int zl3073x_update_hwreg(struct zl3073x_dev *zldev, u32 addr, u32 value,
u32 mask)
{
u32 tmp;
int rc;
rc = zl3073x_read_hwreg(zldev, addr, &tmp);
if (rc)
return rc;
tmp &= ~mask;
tmp |= value & mask;
return zl3073x_write_hwreg(zldev, addr, tmp);
}
/**
* zl3073x_write_hwreg_seq - Write HW registers sequence
* @zldev: pointer to device structure
* @seq: pointer to first sequence item
* @num_items: number of items in sequence
*
* Writes given HW registers sequence.
*
* Return: 0 on success, <0 on error
*/
int zl3073x_write_hwreg_seq(struct zl3073x_dev *zldev,
const struct zl3073x_hwreg_seq_item *seq,
size_t num_items)
{
int i, rc = 0;
for (i = 0; i < num_items; i++) {
dev_dbg(zldev->dev, "Write 0x%0x [0x%0x] to 0x%0x",
seq[i].value, seq[i].mask, seq[i].addr);
if (seq[i].mask == U32_MAX)
/* Write value directly */
rc = zl3073x_write_hwreg(zldev, seq[i].addr,
seq[i].value);
else
/* Update only bits specified by the mask */
rc = zl3073x_update_hwreg(zldev, seq[i].addr,
seq[i].value, seq[i].mask);
if (rc)
return rc;
if (seq->wait)
msleep(seq->wait);
}
return rc;
}
/**
* zl3073x_ref_state_fetch - get input reference state
* @zldev: pointer to zl3073x_dev structure

View File

@ -3,6 +3,7 @@
#ifndef _ZL3073X_CORE_H
#define _ZL3073X_CORE_H
#include <linux/bitfield.h>
#include <linux/kthread.h>
#include <linux/list.h>
#include <linux/mutex.h>
@ -118,6 +119,28 @@ void zl3073x_dev_stop(struct zl3073x_dev *zldev);
* Registers operations
**********************/
/**
* struct zl3073x_hwreg_seq_item - HW register write sequence item
* @addr: HW register to be written
* @value: value to be written to HW register
* @mask: bitmask indicating bits to be updated
* @wait: number of ms to wait after register write
*/
struct zl3073x_hwreg_seq_item {
u32 addr;
u32 value;
u32 mask;
u32 wait;
};
#define HWREG_SEQ_ITEM(_addr, _value, _mask, _wait) \
{ \
.addr = _addr, \
.value = FIELD_PREP_CONST(_mask, _value), \
.mask = _mask, \
.wait = _wait, \
}
int zl3073x_mb_op(struct zl3073x_dev *zldev, unsigned int op_reg, u8 op_val,
unsigned int mask_reg, u16 mask_val);
int zl3073x_poll_zero_u8(struct zl3073x_dev *zldev, unsigned int reg, u8 mask);
@ -129,6 +152,13 @@ int zl3073x_write_u8(struct zl3073x_dev *zldev, unsigned int reg, u8 val);
int zl3073x_write_u16(struct zl3073x_dev *zldev, unsigned int reg, u16 val);
int zl3073x_write_u32(struct zl3073x_dev *zldev, unsigned int reg, u32 val);
int zl3073x_write_u48(struct zl3073x_dev *zldev, unsigned int reg, u64 val);
int zl3073x_read_hwreg(struct zl3073x_dev *zldev, u32 addr, u32 *value);
int zl3073x_write_hwreg(struct zl3073x_dev *zldev, u32 addr, u32 value);
int zl3073x_update_hwreg(struct zl3073x_dev *zldev, u32 addr, u32 value,
u32 mask);
int zl3073x_write_hwreg_seq(struct zl3073x_dev *zldev,
const struct zl3073x_hwreg_seq_item *seq,
size_t num_items);
/*****************
* Misc operations

View File

@ -9,6 +9,8 @@
#include "core.h"
#include "devlink.h"
#include "dpll.h"
#include "flash.h"
#include "fw.h"
#include "regs.h"
/**
@ -132,11 +134,146 @@ zl3073x_devlink_reload_up(struct devlink *devlink,
return 0;
}
void zl3073x_devlink_flash_notify(struct zl3073x_dev *zldev, const char *msg,
const char *component, u32 done, u32 total)
{
struct devlink *devlink = priv_to_devlink(zldev);
devlink_flash_update_status_notify(devlink, msg, component, done,
total);
}
/**
* zl3073x_devlink_flash_prepare - Prepare and enter flash mode
* @zldev: zl3073x device pointer
* @zlfw: pointer to loaded firmware
* @extack: netlink extack pointer to report errors
*
* The function stops normal operation and switches the device to flash mode.
* If an error occurs the normal operation is resumed.
*
* Return: 0 on success, <0 on error
*/
static int
zl3073x_devlink_flash_prepare(struct zl3073x_dev *zldev,
struct zl3073x_fw *zlfw,
struct netlink_ext_ack *extack)
{
struct zl3073x_fw_component *util;
int rc;
util = zlfw->component[ZL_FW_COMPONENT_UTIL];
if (!util) {
zl3073x_devlink_flash_notify(zldev,
"Utility is missing in firmware",
NULL, 0, 0);
return -ENOEXEC;
}
/* Stop normal operation prior entering flash mode */
zl3073x_dev_stop(zldev);
rc = zl3073x_flash_mode_enter(zldev, util->data, util->size, extack);
if (rc) {
zl3073x_devlink_flash_notify(zldev,
"Failed to enter flash mode",
NULL, 0, 0);
/* Resume normal operation */
zl3073x_dev_start(zldev, true);
return rc;
}
return 0;
}
/**
* zl3073x_devlink_flash_finish - Leave flash mode and resume normal operation
* @zldev: zl3073x device pointer
* @extack: netlink extack pointer to report errors
*
* The function switches the device back to standard mode and resumes normal
* operation.
*
* Return: 0 on success, <0 on error
*/
static int
zl3073x_devlink_flash_finish(struct zl3073x_dev *zldev,
struct netlink_ext_ack *extack)
{
int rc;
/* Reset device CPU to normal mode */
zl3073x_flash_mode_leave(zldev, extack);
/* Resume normal operation */
rc = zl3073x_dev_start(zldev, true);
if (rc)
zl3073x_devlink_flash_notify(zldev,
"Failed to start normal operation",
NULL, 0, 0);
return rc;
}
/**
* zl3073x_devlink_flash_update - Devlink flash update callback
* @devlink: devlink structure pointer
* @params: flashing parameters pointer
* @extack: netlink extack pointer to report errors
*
* Return: 0 on success, <0 on error
*/
static int
zl3073x_devlink_flash_update(struct devlink *devlink,
struct devlink_flash_update_params *params,
struct netlink_ext_ack *extack)
{
struct zl3073x_dev *zldev = devlink_priv(devlink);
struct zl3073x_fw *zlfw;
int rc = 0;
zlfw = zl3073x_fw_load(zldev, params->fw->data, params->fw->size,
extack);
if (IS_ERR(zlfw)) {
zl3073x_devlink_flash_notify(zldev, "Failed to load firmware",
NULL, 0, 0);
rc = PTR_ERR(zlfw);
goto finish;
}
/* Stop normal operation and enter flash mode */
rc = zl3073x_devlink_flash_prepare(zldev, zlfw, extack);
if (rc)
goto finish;
rc = zl3073x_fw_flash(zldev, zlfw, extack);
if (rc) {
zl3073x_devlink_flash_finish(zldev, extack);
goto finish;
}
/* Resume normal mode */
rc = zl3073x_devlink_flash_finish(zldev, extack);
finish:
if (!IS_ERR(zlfw))
zl3073x_fw_free(zlfw);
zl3073x_devlink_flash_notify(zldev,
rc ? "Flashing failed" : "Flashing done",
NULL, 0, 0);
return rc;
}
static const struct devlink_ops zl3073x_devlink_ops = {
.info_get = zl3073x_devlink_info_get,
.reload_actions = BIT(DEVLINK_RELOAD_ACTION_DRIVER_REINIT),
.reload_down = zl3073x_devlink_reload_down,
.reload_up = zl3073x_devlink_reload_up,
.flash_update = zl3073x_devlink_flash_update,
};
static void

View File

@ -9,4 +9,7 @@ struct zl3073x_dev *zl3073x_devm_alloc(struct device *dev);
int zl3073x_devlink_register(struct zl3073x_dev *zldev);
void zl3073x_devlink_flash_notify(struct zl3073x_dev *zldev, const char *msg,
const char *component, u32 done, u32 total);
#endif /* _ZL3073X_DEVLINK_H */

View File

@ -0,0 +1,666 @@
// SPDX-License-Identifier: GPL-2.0-or-later
#include <linux/array_size.h>
#include <linux/bitfield.h>
#include <linux/bits.h>
#include <linux/delay.h>
#include <linux/dev_printk.h>
#include <linux/errno.h>
#include <linux/jiffies.h>
#include <linux/minmax.h>
#include <linux/netlink.h>
#include <linux/sched/signal.h>
#include <linux/sizes.h>
#include <linux/sprintf.h>
#include <linux/string.h>
#include <linux/types.h>
#include <linux/unaligned.h>
#include <net/devlink.h>
#include "core.h"
#include "devlink.h"
#include "flash.h"
#define ZL_FLASH_ERR_PFX "FW update failed: "
#define ZL_FLASH_ERR_MSG(_extack, _msg, ...) \
NL_SET_ERR_MSG_FMT_MOD((_extack), ZL_FLASH_ERR_PFX _msg, \
## __VA_ARGS__)
/**
* zl3073x_flash_download - Download image block to device memory
* @zldev: zl3073x device structure
* @component: name of the component to be downloaded
* @addr: device memory target address
* @data: pointer to data to download
* @size: size of data to download
* @extack: netlink extack pointer to report errors
*
* Return: 0 on success, <0 on error
*/
static int
zl3073x_flash_download(struct zl3073x_dev *zldev, const char *component,
u32 addr, const void *data, size_t size,
struct netlink_ext_ack *extack)
{
#define ZL_CHECK_DELAY 5000 /* Check for interrupt each 5 seconds */
unsigned long check_time;
const void *ptr, *end;
int rc = 0;
dev_dbg(zldev->dev, "Downloading %zu bytes to device memory at 0x%0x\n",
size, addr);
check_time = jiffies + msecs_to_jiffies(ZL_CHECK_DELAY);
for (ptr = data, end = data + size; ptr < end; ptr += 4, addr += 4) {
/* Write current word to HW memory */
rc = zl3073x_write_hwreg(zldev, addr,
get_unaligned((u32 *)ptr));
if (rc) {
ZL_FLASH_ERR_MSG(extack,
"failed to write to memory at 0x%0x",
addr);
return rc;
}
if (time_is_before_jiffies(check_time)) {
if (signal_pending(current)) {
ZL_FLASH_ERR_MSG(extack,
"Flashing interrupted");
return -EINTR;
}
check_time = jiffies + msecs_to_jiffies(ZL_CHECK_DELAY);
}
/* Report status each 1 kB block */
if ((ptr - data) % 1024 == 0)
zl3073x_devlink_flash_notify(zldev, "Downloading image",
component, ptr - data,
size);
}
zl3073x_devlink_flash_notify(zldev, "Downloading image", component,
ptr - data, size);
dev_dbg(zldev->dev, "%zu bytes downloaded to device memory\n", size);
return rc;
}
/**
* zl3073x_flash_error_check - Check for flash utility errors
* @zldev: zl3073x device structure
* @extack: netlink extack pointer to report errors
*
* The function checks for errors detected by the flash utility and
* reports them if any were found.
*
* Return: 0 on success, -EIO when errors are detected
*/
static int
zl3073x_flash_error_check(struct zl3073x_dev *zldev,
struct netlink_ext_ack *extack)
{
u32 count, cause;
int rc;
rc = zl3073x_read_u32(zldev, ZL_REG_ERROR_COUNT, &count);
if (rc)
return rc;
else if (!count)
return 0; /* No error */
rc = zl3073x_read_u32(zldev, ZL_REG_ERROR_CAUSE, &cause);
if (rc)
return rc;
/* Report errors */
ZL_FLASH_ERR_MSG(extack,
"utility error occurred: count=%u cause=0x%x", count,
cause);
return -EIO;
}
/**
* zl3073x_flash_wait_ready - Check or wait for utility to be ready to flash
* @zldev: zl3073x device structure
* @timeout_ms: timeout for the waiting
*
* Return: 0 on success, <0 on error
*/
static int
zl3073x_flash_wait_ready(struct zl3073x_dev *zldev, unsigned int timeout_ms)
{
#define ZL_FLASH_POLL_DELAY_MS 100
unsigned long timeout;
int rc, i;
dev_dbg(zldev->dev, "Waiting for flashing to be ready\n");
timeout = jiffies + msecs_to_jiffies(timeout_ms);
for (i = 0; time_is_after_jiffies(timeout); i++) {
u8 value;
/* Check for interrupt each 1s */
if (i > 9) {
if (signal_pending(current))
return -EINTR;
i = 0;
}
rc = zl3073x_read_u8(zldev, ZL_REG_WRITE_FLASH, &value);
if (rc)
return rc;
value = FIELD_GET(ZL_WRITE_FLASH_OP, value);
if (value == ZL_WRITE_FLASH_OP_DONE)
return 0; /* Successfully done */
msleep(ZL_FLASH_POLL_DELAY_MS);
}
return -ETIMEDOUT;
}
/**
* zl3073x_flash_cmd_wait - Perform flash operation and wait for finish
* @zldev: zl3073x device structure
* @operation: operation to perform
* @extack: netlink extack pointer to report errors
*
* Return: 0 on success, <0 on error
*/
static int
zl3073x_flash_cmd_wait(struct zl3073x_dev *zldev, u32 operation,
struct netlink_ext_ack *extack)
{
#define ZL_FLASH_PHASE1_TIMEOUT_MS 60000 /* up to 1 minute */
#define ZL_FLASH_PHASE2_TIMEOUT_MS 120000 /* up to 2 minutes */
u8 value;
int rc;
dev_dbg(zldev->dev, "Sending flash command: 0x%x\n", operation);
rc = zl3073x_flash_wait_ready(zldev, ZL_FLASH_PHASE1_TIMEOUT_MS);
if (rc)
return rc;
/* Issue the requested operation */
rc = zl3073x_read_u8(zldev, ZL_REG_WRITE_FLASH, &value);
if (rc)
return rc;
value &= ~ZL_WRITE_FLASH_OP;
value |= FIELD_PREP(ZL_WRITE_FLASH_OP, operation);
rc = zl3073x_write_u8(zldev, ZL_REG_WRITE_FLASH, value);
if (rc)
return rc;
/* Wait for command completion */
rc = zl3073x_flash_wait_ready(zldev, ZL_FLASH_PHASE2_TIMEOUT_MS);
if (rc)
return rc;
return zl3073x_flash_error_check(zldev, extack);
}
/**
* zl3073x_flash_get_sector_size - Get flash sector size
* @zldev: zl3073x device structure
* @sector_size: sector size returned by the function
*
* The function reads the flash sector size detected by flash utility and
* stores it into @sector_size.
*
* Return: 0 on success, <0 on error
*/
static int
zl3073x_flash_get_sector_size(struct zl3073x_dev *zldev, size_t *sector_size)
{
u8 flash_info;
int rc;
rc = zl3073x_read_u8(zldev, ZL_REG_FLASH_INFO, &flash_info);
if (rc)
return rc;
switch (FIELD_GET(ZL_FLASH_INFO_SECTOR_SIZE, flash_info)) {
case ZL_FLASH_INFO_SECTOR_4K:
*sector_size = SZ_4K;
break;
case ZL_FLASH_INFO_SECTOR_64K:
*sector_size = SZ_64K;
break;
default:
rc = -EINVAL;
break;
}
return rc;
}
/**
* zl3073x_flash_block - Download and flash memory block
* @zldev: zl3073x device structure
* @component: component name
* @operation: flash operation to perform
* @page: destination flash page
* @addr: device memory address to load data
* @data: pointer to data to be flashed
* @size: size of data
* @extack: netlink extack pointer to report errors
*
* The function downloads the memory block given by the @data pointer and
* the size @size and flashes it into internal memory on flash page @page.
* The internal flash operation performed by the firmware is specified by
* the @operation parameter.
*
* Return: 0 on success, <0 on error
*/
static int
zl3073x_flash_block(struct zl3073x_dev *zldev, const char *component,
u32 operation, u32 page, u32 addr, const void *data,
size_t size, struct netlink_ext_ack *extack)
{
int rc;
/* Download block to device memory */
rc = zl3073x_flash_download(zldev, component, addr, data, size, extack);
if (rc)
return rc;
/* Set address to flash from */
rc = zl3073x_write_u32(zldev, ZL_REG_IMAGE_START_ADDR, addr);
if (rc)
return rc;
/* Set size of block to flash */
rc = zl3073x_write_u32(zldev, ZL_REG_IMAGE_SIZE, size);
if (rc)
return rc;
/* Set destination page to flash */
rc = zl3073x_write_u32(zldev, ZL_REG_FLASH_INDEX_WRITE, page);
if (rc)
return rc;
/* Set filling pattern */
rc = zl3073x_write_u32(zldev, ZL_REG_FILL_PATTERN, U32_MAX);
if (rc)
return rc;
zl3073x_devlink_flash_notify(zldev, "Flashing image", component, 0,
size);
dev_dbg(zldev->dev, "Flashing %zu bytes to page %u\n", size, page);
/* Execute sectors flash operation */
rc = zl3073x_flash_cmd_wait(zldev, operation, extack);
if (rc)
return rc;
zl3073x_devlink_flash_notify(zldev, "Flashing image", component, size,
size);
return 0;
}
/**
* zl3073x_flash_sectors - Flash sectors
* @zldev: zl3073x device structure
* @component: component name
* @page: destination flash page
* @addr: device memory address to load data
* @data: pointer to data to be flashed
* @size: size of data
* @extack: netlink extack pointer to report errors
*
* The function flashes given @data with size of @size to the internal flash
* memory block starting from page @page. The function uses sector flash
* method and has to take into account the flash sector size reported by
* flashing utility. Input data are spliced into blocks according this
* sector size and each block is flashed separately.
*
* Return: 0 on success, <0 on error
*/
int zl3073x_flash_sectors(struct zl3073x_dev *zldev, const char *component,
u32 page, u32 addr, const void *data, size_t size,
struct netlink_ext_ack *extack)
{
#define ZL_FLASH_MAX_BLOCK_SIZE 0x0001E000
#define ZL_FLASH_PAGE_SIZE 256
size_t max_block_size, block_size, sector_size;
const void *ptr, *end;
int rc;
/* Get flash sector size */
rc = zl3073x_flash_get_sector_size(zldev, &sector_size);
if (rc) {
ZL_FLASH_ERR_MSG(extack, "Failed to get flash sector size");
return rc;
}
/* Determine max block size depending on sector size */
max_block_size = ALIGN_DOWN(ZL_FLASH_MAX_BLOCK_SIZE, sector_size);
for (ptr = data, end = data + size; ptr < end; ptr += block_size) {
char comp_str[32];
block_size = min_t(size_t, max_block_size, end - ptr);
/* Add suffix '-partN' if the requested component size is
* greater than max_block_size.
*/
if (max_block_size < size)
snprintf(comp_str, sizeof(comp_str), "%s-part%zu",
component, (ptr - data) / max_block_size + 1);
else
strscpy(comp_str, component);
/* Flash the memory block */
rc = zl3073x_flash_block(zldev, comp_str,
ZL_WRITE_FLASH_OP_SECTORS, page, addr,
ptr, block_size, extack);
if (rc)
goto finish;
/* Move to next page */
page += block_size / ZL_FLASH_PAGE_SIZE;
}
finish:
zl3073x_devlink_flash_notify(zldev,
rc ? "Flashing failed" : "Flashing done",
component, 0, 0);
return rc;
}
/**
* zl3073x_flash_page - Flash page
* @zldev: zl3073x device structure
* @component: component name
* @page: destination flash page
* @addr: device memory address to load data
* @data: pointer to data to be flashed
* @size: size of data
* @extack: netlink extack pointer to report errors
*
* The function flashes given @data with size of @size to the internal flash
* memory block starting with page @page.
*
* Return: 0 on success, <0 on error
*/
int zl3073x_flash_page(struct zl3073x_dev *zldev, const char *component,
u32 page, u32 addr, const void *data, size_t size,
struct netlink_ext_ack *extack)
{
int rc;
/* Flash the memory block */
rc = zl3073x_flash_block(zldev, component, ZL_WRITE_FLASH_OP_PAGE, page,
addr, data, size, extack);
zl3073x_devlink_flash_notify(zldev,
rc ? "Flashing failed" : "Flashing done",
component, 0, 0);
return rc;
}
/**
* zl3073x_flash_page_copy - Copy flash page
* @zldev: zl3073x device structure
* @component: component name
* @src_page: source page to copy
* @dst_page: destination page
* @extack: netlink extack pointer to report errors
*
* The function copies one flash page specified by @src_page into the flash
* page specified by @dst_page.
*
* Return: 0 on success, <0 on error
*/
int zl3073x_flash_page_copy(struct zl3073x_dev *zldev, const char *component,
u32 src_page, u32 dst_page,
struct netlink_ext_ack *extack)
{
int rc;
/* Set source page to be copied */
rc = zl3073x_write_u32(zldev, ZL_REG_FLASH_INDEX_READ, src_page);
if (rc)
return rc;
/* Set destination page for the copy */
rc = zl3073x_write_u32(zldev, ZL_REG_FLASH_INDEX_WRITE, dst_page);
if (rc)
return rc;
/* Perform copy operation */
rc = zl3073x_flash_cmd_wait(zldev, ZL_WRITE_FLASH_OP_COPY_PAGE, extack);
if (rc)
ZL_FLASH_ERR_MSG(extack, "Failed to copy page %u to page %u",
src_page, dst_page);
return rc;
}
/**
* zl3073x_flash_mode_verify - Check flash utility
* @zldev: zl3073x device structure
*
* Return: 0 if the flash utility is ready, <0 on error
*/
static int
zl3073x_flash_mode_verify(struct zl3073x_dev *zldev)
{
u8 family, release;
u32 hash;
int rc;
rc = zl3073x_read_u32(zldev, ZL_REG_FLASH_HASH, &hash);
if (rc)
return rc;
rc = zl3073x_read_u8(zldev, ZL_REG_FLASH_FAMILY, &family);
if (rc)
return rc;
rc = zl3073x_read_u8(zldev, ZL_REG_FLASH_RELEASE, &release);
if (rc)
return rc;
dev_dbg(zldev->dev,
"Flash utility check: hash 0x%08x, fam 0x%02x, rel 0x%02x\n",
hash, family, release);
/* Return success for correct family */
return (family == 0x21) ? 0 : -ENODEV;
}
static int
zl3073x_flash_host_ctrl_enable(struct zl3073x_dev *zldev)
{
u8 host_ctrl;
int rc;
/* Enable host control */
rc = zl3073x_read_u8(zldev, ZL_REG_HOST_CONTROL, &host_ctrl);
if (rc)
return rc;
host_ctrl |= ZL_HOST_CONTROL_ENABLE;
return zl3073x_write_u8(zldev, ZL_REG_HOST_CONTROL, host_ctrl);
}
/**
* zl3073x_flash_mode_enter - Switch the device to flash mode
* @zldev: zl3073x device structure
* @util_ptr: buffer with flash utility
* @util_size: size of buffer with flash utility
* @extack: netlink extack pointer to report errors
*
* The function prepares and switches the device into flash mode.
*
* The procedure:
* 1) Stop device CPU by specific HW register sequence
* 2) Download flash utility to device memory
* 3) Resume device CPU by specific HW register sequence
* 4) Check communication with flash utility
* 5) Enable host control necessary to access flash API
* 6) Check for potential error detected by the utility
*
* The API provided by normal firmware is not available in flash mode
* so the caller has to ensure that this API is not used in this mode.
*
* After performing flash operation the caller should call
* @zl3073x_flash_mode_leave to return back to normal operation.
*
* Return: 0 on success, <0 on error.
*/
int zl3073x_flash_mode_enter(struct zl3073x_dev *zldev, const void *util_ptr,
size_t util_size, struct netlink_ext_ack *extack)
{
/* Sequence to be written prior utility download */
static const struct zl3073x_hwreg_seq_item pre_seq[] = {
HWREG_SEQ_ITEM(0x80000400, 1, BIT(0), 0),
HWREG_SEQ_ITEM(0x80206340, 1, BIT(4), 0),
HWREG_SEQ_ITEM(0x10000000, 1, BIT(2), 0),
HWREG_SEQ_ITEM(0x10000024, 0x00000001, U32_MAX, 0),
HWREG_SEQ_ITEM(0x10000020, 0x00000001, U32_MAX, 0),
HWREG_SEQ_ITEM(0x10000000, 1, BIT(10), 1000),
};
/* Sequence to be written after utility download */
static const struct zl3073x_hwreg_seq_item post_seq[] = {
HWREG_SEQ_ITEM(0x10400004, 0x000000C0, U32_MAX, 0),
HWREG_SEQ_ITEM(0x10400008, 0x00000000, U32_MAX, 0),
HWREG_SEQ_ITEM(0x10400010, 0x20000000, U32_MAX, 0),
HWREG_SEQ_ITEM(0x10400014, 0x20000004, U32_MAX, 0),
HWREG_SEQ_ITEM(0x10000000, 1, GENMASK(10, 9), 0),
HWREG_SEQ_ITEM(0x10000020, 0x00000000, U32_MAX, 0),
HWREG_SEQ_ITEM(0x10000000, 0, BIT(0), 1000),
};
int rc;
zl3073x_devlink_flash_notify(zldev, "Prepare flash mode", "utility",
0, 0);
/* Execure pre-load sequence */
rc = zl3073x_write_hwreg_seq(zldev, pre_seq, ARRAY_SIZE(pre_seq));
if (rc) {
ZL_FLASH_ERR_MSG(extack, "cannot execute pre-load sequence");
goto error;
}
/* Download utility image to device memory */
rc = zl3073x_flash_download(zldev, "utility", 0x20000000, util_ptr,
util_size, extack);
if (rc) {
ZL_FLASH_ERR_MSG(extack, "cannot download flash utility");
goto error;
}
/* Execute post-load sequence */
rc = zl3073x_write_hwreg_seq(zldev, post_seq, ARRAY_SIZE(post_seq));
if (rc) {
ZL_FLASH_ERR_MSG(extack, "cannot execute post-load sequence");
goto error;
}
/* Check that utility identifies itself correctly */
rc = zl3073x_flash_mode_verify(zldev);
if (rc) {
ZL_FLASH_ERR_MSG(extack, "flash utility check failed");
goto error;
}
/* Enable host control */
rc = zl3073x_flash_host_ctrl_enable(zldev);
if (rc) {
ZL_FLASH_ERR_MSG(extack, "cannot enable host control");
goto error;
}
zl3073x_devlink_flash_notify(zldev, "Flash mode enabled", "utility",
0, 0);
return 0;
error:
zl3073x_flash_mode_leave(zldev, extack);
return rc;
}
/**
* zl3073x_flash_mode_leave - Leave flash mode
* @zldev: zl3073x device structure
* @extack: netlink extack pointer to report errors
*
* The function instructs the device to leave the flash mode and
* to return back to normal operation.
*
* The procedure:
* 1) Set reset flag
* 2) Reset the device CPU by specific HW register sequence
* 3) Wait for the device to be ready
* 4) Check the reset flag was cleared
*
* Return: 0 on success, <0 on error
*/
int zl3073x_flash_mode_leave(struct zl3073x_dev *zldev,
struct netlink_ext_ack *extack)
{
/* Sequence to be written after flash */
static const struct zl3073x_hwreg_seq_item fw_reset_seq[] = {
HWREG_SEQ_ITEM(0x80000404, 1, BIT(0), 0),
HWREG_SEQ_ITEM(0x80000410, 1, BIT(0), 0),
};
u8 reset_status;
int rc;
zl3073x_devlink_flash_notify(zldev, "Leaving flash mode", "utility",
0, 0);
/* Read reset status register */
rc = zl3073x_read_u8(zldev, ZL_REG_RESET_STATUS, &reset_status);
if (rc)
return rc;
/* Set reset bit */
reset_status |= ZL_REG_RESET_STATUS_RESET;
/* Update reset status register */
rc = zl3073x_write_u8(zldev, ZL_REG_RESET_STATUS, reset_status);
if (rc)
return rc;
/* We do not check the return value here as the sequence resets
* the device CPU and the last write always return an error.
*/
zl3073x_write_hwreg_seq(zldev, fw_reset_seq, ARRAY_SIZE(fw_reset_seq));
/* Wait for the device to be ready */
msleep(500);
/* Read again the reset status register */
rc = zl3073x_read_u8(zldev, ZL_REG_RESET_STATUS, &reset_status);
if (rc)
return rc;
/* Check the reset bit was cleared */
if (reset_status & ZL_REG_RESET_STATUS_RESET) {
dev_err(zldev->dev,
"Reset not confirmed after switch to normal mode\n");
return -EINVAL;
}
return 0;
}

View File

@ -0,0 +1,29 @@
/* SPDX-License-Identifier: GPL-2.0+ */
#ifndef __ZL3073X_FLASH_H
#define __ZL3073X_FLASH_H
#include <linux/types.h>
struct netlink_ext_ack;
struct zl3073x_dev;
int zl3073x_flash_mode_enter(struct zl3073x_dev *zldev, const void *util_ptr,
size_t util_size, struct netlink_ext_ack *extack);
int zl3073x_flash_mode_leave(struct zl3073x_dev *zldev,
struct netlink_ext_ack *extack);
int zl3073x_flash_page(struct zl3073x_dev *zldev, const char *component,
u32 page, u32 addr, const void *data, size_t size,
struct netlink_ext_ack *extack);
int zl3073x_flash_page_copy(struct zl3073x_dev *zldev, const char *component,
u32 src_page, u32 dst_page,
struct netlink_ext_ack *extack);
int zl3073x_flash_sectors(struct zl3073x_dev *zldev, const char *component,
u32 page, u32 addr, const void *data, size_t size,
struct netlink_ext_ack *extack);
#endif /* __ZL3073X_FLASH_H */

419
drivers/dpll/zl3073x/fw.c Normal file
View File

@ -0,0 +1,419 @@
// SPDX-License-Identifier: GPL-2.0-or-later
#include <linux/array_size.h>
#include <linux/build_bug.h>
#include <linux/dev_printk.h>
#include <linux/err.h>
#include <linux/errno.h>
#include <linux/netlink.h>
#include <linux/slab.h>
#include <linux/string.h>
#include "core.h"
#include "flash.h"
#include "fw.h"
#define ZL3073X_FW_ERR_PFX "FW load failed: "
#define ZL3073X_FW_ERR_MSG(_extack, _msg, ...) \
NL_SET_ERR_MSG_FMT_MOD((_extack), ZL3073X_FW_ERR_PFX _msg, \
## __VA_ARGS__)
enum zl3073x_flash_type {
ZL3073X_FLASH_TYPE_NONE = 0,
ZL3073X_FLASH_TYPE_SECTORS,
ZL3073X_FLASH_TYPE_PAGE,
ZL3073X_FLASH_TYPE_PAGE_AND_COPY,
};
struct zl3073x_fw_component_info {
const char *name;
size_t max_size;
enum zl3073x_flash_type flash_type;
u32 load_addr;
u32 dest_page;
u32 copy_page;
};
static const struct zl3073x_fw_component_info component_info[] = {
[ZL_FW_COMPONENT_UTIL] = {
.name = "utility",
.max_size = 0x4000,
.load_addr = 0x20000000,
.flash_type = ZL3073X_FLASH_TYPE_NONE,
},
[ZL_FW_COMPONENT_FW1] = {
.name = "firmware1",
.max_size = 0x35000,
.load_addr = 0x20002000,
.flash_type = ZL3073X_FLASH_TYPE_SECTORS,
.dest_page = 0x020,
},
[ZL_FW_COMPONENT_FW2] = {
.name = "firmware2",
.max_size = 0x0040,
.load_addr = 0x20000000,
.flash_type = ZL3073X_FLASH_TYPE_PAGE_AND_COPY,
.dest_page = 0x3e0,
.copy_page = 0x000,
},
[ZL_FW_COMPONENT_FW3] = {
.name = "firmware3",
.max_size = 0x0248,
.load_addr = 0x20000400,
.flash_type = ZL3073X_FLASH_TYPE_PAGE_AND_COPY,
.dest_page = 0x3e4,
.copy_page = 0x004,
},
[ZL_FW_COMPONENT_CFG0] = {
.name = "config0",
.max_size = 0x1000,
.load_addr = 0x20000000,
.flash_type = ZL3073X_FLASH_TYPE_PAGE,
.dest_page = 0x3d0,
},
[ZL_FW_COMPONENT_CFG1] = {
.name = "config1",
.max_size = 0x1000,
.load_addr = 0x20000000,
.flash_type = ZL3073X_FLASH_TYPE_PAGE,
.dest_page = 0x3c0,
},
[ZL_FW_COMPONENT_CFG2] = {
.name = "config2",
.max_size = 0x1000,
.load_addr = 0x20000000,
.flash_type = ZL3073X_FLASH_TYPE_PAGE,
.dest_page = 0x3b0,
},
[ZL_FW_COMPONENT_CFG3] = {
.name = "config3",
.max_size = 0x1000,
.load_addr = 0x20000000,
.flash_type = ZL3073X_FLASH_TYPE_PAGE,
.dest_page = 0x3a0,
},
[ZL_FW_COMPONENT_CFG4] = {
.name = "config4",
.max_size = 0x1000,
.load_addr = 0x20000000,
.flash_type = ZL3073X_FLASH_TYPE_PAGE,
.dest_page = 0x390,
},
[ZL_FW_COMPONENT_CFG5] = {
.name = "config5",
.max_size = 0x1000,
.load_addr = 0x20000000,
.flash_type = ZL3073X_FLASH_TYPE_PAGE,
.dest_page = 0x380,
},
[ZL_FW_COMPONENT_CFG6] = {
.name = "config6",
.max_size = 0x1000,
.load_addr = 0x20000000,
.flash_type = ZL3073X_FLASH_TYPE_PAGE,
.dest_page = 0x370,
},
};
/* Sanity check */
static_assert(ARRAY_SIZE(component_info) == ZL_FW_NUM_COMPONENTS);
/**
* zl3073x_fw_component_alloc - Alloc structure to hold firmware component
* @size: size of buffer to store data
*
* Return: pointer to allocated component structure or NULL on error.
*/
static struct zl3073x_fw_component *
zl3073x_fw_component_alloc(size_t size)
{
struct zl3073x_fw_component *comp;
comp = kzalloc(sizeof(*comp), GFP_KERNEL);
if (!comp)
return NULL;
comp->size = size;
comp->data = kzalloc(size, GFP_KERNEL);
if (!comp->data) {
kfree(comp);
return NULL;
}
return comp;
}
/**
* zl3073x_fw_component_free - Free allocated component structure
* @comp: pointer to allocated component
*/
static void
zl3073x_fw_component_free(struct zl3073x_fw_component *comp)
{
if (comp)
kfree(comp->data);
kfree(comp);
}
/**
* zl3073x_fw_component_id_get - Get ID for firmware component name
* @name: input firmware component name
*
* Return:
* - ZL3073X_FW_COMPONENT_* ID for known component name
* - ZL3073X_FW_COMPONENT_INVALID if the given name is unknown
*/
static enum zl3073x_fw_component_id
zl3073x_fw_component_id_get(const char *name)
{
enum zl3073x_fw_component_id id;
for (id = 0; id < ZL_FW_NUM_COMPONENTS; id++)
if (!strcasecmp(name, component_info[id].name))
return id;
return ZL_FW_COMPONENT_INVALID;
}
/**
* zl3073x_fw_component_load - Load component from firmware source
* @zldev: zl3073x device structure
* @pcomp: pointer to loaded component
* @psrc: data pointer to load component from
* @psize: remaining bytes in buffer
* @extack: netlink extack pointer to report errors
*
* The function allocates single firmware component and loads the data from
* the buffer specified by @psrc and @psize. Pointer to allocated component
* is stored in output @pcomp. Source data pointer @psrc and remaining bytes
* @psize are updated accordingly.
*
* Return:
* * 1 when component was allocated and loaded
* * 0 when there is no component to load
* * <0 on error
*/
static ssize_t
zl3073x_fw_component_load(struct zl3073x_dev *zldev,
struct zl3073x_fw_component **pcomp,
const char **psrc, size_t *psize,
struct netlink_ext_ack *extack)
{
const struct zl3073x_fw_component_info *info;
struct zl3073x_fw_component *comp = NULL;
struct device *dev = zldev->dev;
enum zl3073x_fw_component_id id;
char buf[32], name[16];
u32 count, size, *dest;
int pos, rc;
/* Fetch image name and size from input */
strscpy(buf, *psrc, min(sizeof(buf), *psize));
rc = sscanf(buf, "%15s %u %n", name, &count, &pos);
if (!rc) {
/* No more data */
return 0;
} else if (rc == 1 || count > U32_MAX / sizeof(u32)) {
ZL3073X_FW_ERR_MSG(extack, "invalid component size");
return -EINVAL;
}
*psrc += pos;
*psize -= pos;
dev_dbg(dev, "Firmware component '%s' found\n", name);
id = zl3073x_fw_component_id_get(name);
if (id == ZL_FW_COMPONENT_INVALID) {
ZL3073X_FW_ERR_MSG(extack, "unknown component type '%s'", name);
return -EINVAL;
}
info = &component_info[id];
size = count * sizeof(u32); /* get size in bytes */
/* Check image size validity */
if (size > component_info[id].max_size) {
ZL3073X_FW_ERR_MSG(extack,
"[%s] component is too big (%u bytes)\n",
info->name, size);
return -EINVAL;
}
dev_dbg(dev, "Indicated component image size: %u bytes\n", size);
/* Alloc component */
comp = zl3073x_fw_component_alloc(size);
if (!comp) {
ZL3073X_FW_ERR_MSG(extack, "failed to alloc memory");
return -ENOMEM;
}
comp->id = id;
/* Load component data from firmware source */
for (dest = comp->data; count; count--, dest++) {
strscpy(buf, *psrc, min(sizeof(buf), *psize));
rc = sscanf(buf, "%x %n", dest, &pos);
if (!rc)
goto err_data;
*psrc += pos;
*psize -= pos;
}
*pcomp = comp;
return 1;
err_data:
ZL3073X_FW_ERR_MSG(extack, "[%s] invalid or missing data", info->name);
zl3073x_fw_component_free(comp);
return -ENODATA;
}
/**
* zl3073x_fw_free - Free allocated firmware
* @fw: firmware pointer
*
* The function frees existing firmware allocated by @zl3073x_fw_load.
*/
void zl3073x_fw_free(struct zl3073x_fw *fw)
{
size_t i;
if (!fw)
return;
for (i = 0; i < ZL_FW_NUM_COMPONENTS; i++)
zl3073x_fw_component_free(fw->component[i]);
kfree(fw);
}
/**
* zl3073x_fw_load - Load all components from source
* @zldev: zl3073x device structure
* @data: source buffer pointer
* @size: size of source buffer
* @extack: netlink extack pointer to report errors
*
* The functions allocate firmware structure and loads all components from
* the given buffer specified by @data and @size.
*
* Return: pointer to firmware on success, error pointer on error
*/
struct zl3073x_fw *zl3073x_fw_load(struct zl3073x_dev *zldev, const char *data,
size_t size, struct netlink_ext_ack *extack)
{
struct zl3073x_fw_component *comp;
enum zl3073x_fw_component_id id;
struct zl3073x_fw *fw;
ssize_t rc;
/* Allocate firmware structure */
fw = kzalloc(sizeof(*fw), GFP_KERNEL);
if (!fw)
return ERR_PTR(-ENOMEM);
do {
/* Load single component */
rc = zl3073x_fw_component_load(zldev, &comp, &data, &size,
extack);
if (rc <= 0)
/* Everything was read or error occurred */
break;
id = comp->id;
/* Report error if the given component is present twice
* or more.
*/
if (fw->component[id]) {
ZL3073X_FW_ERR_MSG(extack,
"duplicate component '%s' detected",
component_info[id].name);
zl3073x_fw_component_free(comp);
rc = -EINVAL;
break;
}
fw->component[id] = comp;
} while (true);
if (rc) {
/* Free allocated firmware in case of error */
zl3073x_fw_free(fw);
return ERR_PTR(rc);
}
return fw;
}
/**
* zl3073x_flash_bundle_flash - Flash all components
* @zldev: zl3073x device structure
* @components: pointer to components array
* @extack: netlink extack pointer to report errors
*
* Returns 0 in case of success or negative number otherwise.
*/
static int
zl3073x_fw_component_flash(struct zl3073x_dev *zldev,
struct zl3073x_fw_component *comp,
struct netlink_ext_ack *extack)
{
const struct zl3073x_fw_component_info *info;
int rc;
info = &component_info[comp->id];
switch (info->flash_type) {
case ZL3073X_FLASH_TYPE_NONE:
/* Non-flashable component - used for utility */
return 0;
case ZL3073X_FLASH_TYPE_SECTORS:
rc = zl3073x_flash_sectors(zldev, info->name, info->dest_page,
info->load_addr, comp->data,
comp->size, extack);
break;
case ZL3073X_FLASH_TYPE_PAGE:
rc = zl3073x_flash_page(zldev, info->name, info->dest_page,
info->load_addr, comp->data, comp->size,
extack);
break;
case ZL3073X_FLASH_TYPE_PAGE_AND_COPY:
rc = zl3073x_flash_page(zldev, info->name, info->dest_page,
info->load_addr, comp->data, comp->size,
extack);
if (!rc)
rc = zl3073x_flash_page_copy(zldev, info->name,
info->dest_page,
info->copy_page, extack);
break;
}
if (rc)
ZL3073X_FW_ERR_MSG(extack, "Failed to flash component '%s'",
info->name);
return rc;
}
int zl3073x_fw_flash(struct zl3073x_dev *zldev, struct zl3073x_fw *zlfw,
struct netlink_ext_ack *extack)
{
int i, rc = 0;
for (i = 0; i < ZL_FW_NUM_COMPONENTS; i++) {
if (!zlfw->component[i])
continue; /* Component is not present */
rc = zl3073x_fw_component_flash(zldev, zlfw->component[i],
extack);
if (rc)
break;
}
return rc;
}

52
drivers/dpll/zl3073x/fw.h Normal file
View File

@ -0,0 +1,52 @@
/* SPDX-License-Identifier: GPL-2.0-only */
#ifndef _ZL3073X_FW_H
#define _ZL3073X_FW_H
/*
* enum zl3073x_fw_component_id - Identifiers for possible flash components
*/
enum zl3073x_fw_component_id {
ZL_FW_COMPONENT_INVALID = -1,
ZL_FW_COMPONENT_UTIL = 0,
ZL_FW_COMPONENT_FW1,
ZL_FW_COMPONENT_FW2,
ZL_FW_COMPONENT_FW3,
ZL_FW_COMPONENT_CFG0,
ZL_FW_COMPONENT_CFG1,
ZL_FW_COMPONENT_CFG2,
ZL_FW_COMPONENT_CFG3,
ZL_FW_COMPONENT_CFG4,
ZL_FW_COMPONENT_CFG5,
ZL_FW_COMPONENT_CFG6,
ZL_FW_NUM_COMPONENTS
};
/**
* struct zl3073x_fw_component - Firmware component
* @id: Flash component ID
* @size: Size of the buffer
* @data: Pointer to buffer with component data
*/
struct zl3073x_fw_component {
enum zl3073x_fw_component_id id;
size_t size;
void *data;
};
/**
* struct zl3073x_fw - Firmware bundle
* @component: firmware components array
*/
struct zl3073x_fw {
struct zl3073x_fw_component *component[ZL_FW_NUM_COMPONENTS];
};
struct zl3073x_fw *zl3073x_fw_load(struct zl3073x_dev *zldev, const char *data,
size_t size, struct netlink_ext_ack *extack);
void zl3073x_fw_free(struct zl3073x_fw *fw);
int zl3073x_fw_flash(struct zl3073x_dev *zldev, struct zl3073x_fw *zlfw,
struct netlink_ext_ack *extack);
#endif /* _ZL3073X_FW_H */

View File

@ -75,6 +75,9 @@
#define ZL_REG_FW_VER ZL_REG(0, 0x05, 2)
#define ZL_REG_CUSTOM_CONFIG_VER ZL_REG(0, 0x07, 4)
#define ZL_REG_RESET_STATUS ZL_REG(0, 0x18, 1)
#define ZL_REG_RESET_STATUS_RESET BIT(0)
/*************************
* Register Page 2, Status
*************************/
@ -263,4 +266,52 @@
#define ZL_REG_OUTPUT_ESYNC_WIDTH ZL_REG(14, 0x18, 4)
#define ZL_REG_OUTPUT_PHASE_COMP ZL_REG(14, 0x20, 4)
/*
* Register Page 255 - HW registers access
*/
#define ZL_REG_HWREG_OP ZL_REG(0xff, 0x00, 1)
#define ZL_HWREG_OP_WRITE 0x28
#define ZL_HWREG_OP_READ 0x29
#define ZL_HWREG_OP_PENDING BIT(1)
#define ZL_REG_HWREG_ADDR ZL_REG(0xff, 0x04, 4)
#define ZL_REG_HWREG_WRITE_DATA ZL_REG(0xff, 0x08, 4)
#define ZL_REG_HWREG_READ_DATA ZL_REG(0xff, 0x0c, 4)
/*
* Registers available in flash mode
*/
#define ZL_REG_FLASH_HASH ZL_REG(0, 0x78, 4)
#define ZL_REG_FLASH_FAMILY ZL_REG(0, 0x7c, 1)
#define ZL_REG_FLASH_RELEASE ZL_REG(0, 0x7d, 1)
#define ZL_REG_HOST_CONTROL ZL_REG(1, 0x02, 1)
#define ZL_HOST_CONTROL_ENABLE BIT(0)
#define ZL_REG_IMAGE_START_ADDR ZL_REG(1, 0x04, 4)
#define ZL_REG_IMAGE_SIZE ZL_REG(1, 0x08, 4)
#define ZL_REG_FLASH_INDEX_READ ZL_REG(1, 0x0c, 4)
#define ZL_REG_FLASH_INDEX_WRITE ZL_REG(1, 0x10, 4)
#define ZL_REG_FILL_PATTERN ZL_REG(1, 0x14, 4)
#define ZL_REG_WRITE_FLASH ZL_REG(1, 0x18, 1)
#define ZL_WRITE_FLASH_OP GENMASK(2, 0)
#define ZL_WRITE_FLASH_OP_DONE 0x0
#define ZL_WRITE_FLASH_OP_SECTORS 0x2
#define ZL_WRITE_FLASH_OP_PAGE 0x3
#define ZL_WRITE_FLASH_OP_COPY_PAGE 0x4
#define ZL_REG_FLASH_INFO ZL_REG(2, 0x00, 1)
#define ZL_FLASH_INFO_SECTOR_SIZE GENMASK(3, 0)
#define ZL_FLASH_INFO_SECTOR_4K 0
#define ZL_FLASH_INFO_SECTOR_64K 1
#define ZL_REG_ERROR_COUNT ZL_REG(2, 0x04, 4)
#define ZL_REG_ERROR_CAUSE ZL_REG(2, 0x08, 4)
#define ZL_REG_OP_STATE ZL_REG(2, 0x14, 1)
#define ZL_OP_STATE_NO_COMMAND 0
#define ZL_OP_STATE_PENDING 1
#define ZL_OP_STATE_DONE 2
#endif /* _ZL3073X_REGS_H */

View File

@ -3679,6 +3679,11 @@ static int vmw_cmd_check(struct vmw_private *dev_priv,
cmd_id = header->id;
if (header->size > SVGA_CMD_MAX_DATASIZE) {
VMW_DEBUG_USER("SVGA3D command: %d is too big.\n",
cmd_id + SVGA_3D_CMD_BASE);
return -E2BIG;
}
*size = header->size + sizeof(SVGA3dCmdHeader);
cmd_id -= SVGA_3D_CMD_BASE;

View File

@ -1461,6 +1461,14 @@ static const __u8 *mt_report_fixup(struct hid_device *hdev, __u8 *rdesc,
if (hdev->vendor == I2C_VENDOR_ID_GOODIX &&
(hdev->product == I2C_DEVICE_ID_GOODIX_01E8 ||
hdev->product == I2C_DEVICE_ID_GOODIX_01E9)) {
if (*size < 608) {
dev_info(
&hdev->dev,
"GT7868Q fixup: report descriptor is only %u bytes, skipping\n",
*size);
return rdesc;
}
if (rdesc[607] == 0x15) {
rdesc[607] = 0x25;
dev_info(

View File

@ -76,6 +76,13 @@ static int i2c_hid_acpi_get_descriptor(struct i2c_hid_acpi *ihid_acpi)
return hid_descriptor_address;
}
static void i2c_hid_acpi_restore_sequence(struct i2chid_ops *ops)
{
struct i2c_hid_acpi *ihid_acpi = container_of(ops, struct i2c_hid_acpi, ops);
i2c_hid_acpi_get_descriptor(ihid_acpi);
}
static void i2c_hid_acpi_shutdown_tail(struct i2chid_ops *ops)
{
struct i2c_hid_acpi *ihid_acpi = container_of(ops, struct i2c_hid_acpi, ops);
@ -96,6 +103,7 @@ static int i2c_hid_acpi_probe(struct i2c_client *client)
ihid_acpi->adev = ACPI_COMPANION(dev);
ihid_acpi->ops.shutdown_tail = i2c_hid_acpi_shutdown_tail;
ihid_acpi->ops.restore_sequence = i2c_hid_acpi_restore_sequence;
ret = i2c_hid_acpi_get_descriptor(ihid_acpi);
if (ret < 0)

View File

@ -961,6 +961,14 @@ static void i2c_hid_core_shutdown_tail(struct i2c_hid *ihid)
ihid->ops->shutdown_tail(ihid->ops);
}
static void i2c_hid_core_restore_sequence(struct i2c_hid *ihid)
{
if (!ihid->ops->restore_sequence)
return;
ihid->ops->restore_sequence(ihid->ops);
}
static int i2c_hid_core_suspend(struct i2c_hid *ihid, bool force_poweroff)
{
struct i2c_client *client = ihid->client;
@ -1360,8 +1368,26 @@ static int i2c_hid_core_pm_resume(struct device *dev)
return i2c_hid_core_resume(ihid);
}
static int i2c_hid_core_pm_restore(struct device *dev)
{
struct i2c_client *client = to_i2c_client(dev);
struct i2c_hid *ihid = i2c_get_clientdata(client);
if (ihid->is_panel_follower)
return 0;
i2c_hid_core_restore_sequence(ihid);
return i2c_hid_core_resume(ihid);
}
const struct dev_pm_ops i2c_hid_core_pm = {
SYSTEM_SLEEP_PM_OPS(i2c_hid_core_pm_suspend, i2c_hid_core_pm_resume)
.suspend = pm_sleep_ptr(i2c_hid_core_pm_suspend),
.resume = pm_sleep_ptr(i2c_hid_core_pm_resume),
.freeze = pm_sleep_ptr(i2c_hid_core_pm_suspend),
.thaw = pm_sleep_ptr(i2c_hid_core_pm_resume),
.poweroff = pm_sleep_ptr(i2c_hid_core_pm_suspend),
.restore = pm_sleep_ptr(i2c_hid_core_pm_restore),
};
EXPORT_SYMBOL_GPL(i2c_hid_core_pm);

View File

@ -27,11 +27,13 @@ static inline u32 i2c_hid_get_dmi_quirks(const u16 vendor, const u16 product)
* @power_up: do sequencing to power up the device.
* @power_down: do sequencing to power down the device.
* @shutdown_tail: called at the end of shutdown.
* @restore_sequence: hibernation restore sequence.
*/
struct i2chid_ops {
int (*power_up)(struct i2chid_ops *ops);
void (*power_down)(struct i2chid_ops *ops);
void (*shutdown_tail)(struct i2chid_ops *ops);
void (*restore_sequence)(struct i2chid_ops *ops);
};
int i2c_hid_core_probe(struct i2c_client *client, struct i2chid_ops *ops,

View File

@ -439,12 +439,12 @@ static int iommufd_eventq_init(struct iommufd_eventq *eventq, char *name,
const struct file_operations *fops)
{
struct file *filep;
int fdno;
spin_lock_init(&eventq->lock);
INIT_LIST_HEAD(&eventq->deliver);
init_waitqueue_head(&eventq->wait_queue);
/* The filep is fput() by the core code during failure */
filep = anon_inode_getfile(name, fops, eventq, O_RDWR);
if (IS_ERR(filep))
return PTR_ERR(filep);
@ -454,10 +454,7 @@ static int iommufd_eventq_init(struct iommufd_eventq *eventq, char *name,
eventq->filep = filep;
refcount_inc(&eventq->obj.users);
fdno = get_unused_fd_flags(O_CLOEXEC);
if (fdno < 0)
fput(filep);
return fdno;
return get_unused_fd_flags(O_CLOEXEC);
}
static const struct file_operations iommufd_fault_fops =
@ -501,7 +498,6 @@ int iommufd_fault_alloc(struct iommufd_ucmd *ucmd)
return 0;
out_put_fdno:
put_unused_fd(fdno);
fput(fault->common.filep);
out_abort:
iommufd_object_abort_and_destroy(ucmd->ictx, &fault->common.obj);
@ -588,7 +584,6 @@ int iommufd_veventq_alloc(struct iommufd_ucmd *ucmd)
out_put_fdno:
put_unused_fd(fdno);
fput(veventq->common.filep);
out_abort:
iommufd_object_abort_and_destroy(ucmd->ictx, &veventq->common.obj);
out_unlock_veventqs:

View File

@ -23,6 +23,7 @@
#include "iommufd_test.h"
struct iommufd_object_ops {
size_t file_offset;
void (*destroy)(struct iommufd_object *obj);
void (*abort)(struct iommufd_object *obj);
};
@ -71,10 +72,30 @@ void iommufd_object_abort(struct iommufd_ctx *ictx, struct iommufd_object *obj)
void iommufd_object_abort_and_destroy(struct iommufd_ctx *ictx,
struct iommufd_object *obj)
{
if (iommufd_object_ops[obj->type].abort)
iommufd_object_ops[obj->type].abort(obj);
const struct iommufd_object_ops *ops = &iommufd_object_ops[obj->type];
if (ops->file_offset) {
struct file **filep = ((void *)obj) + ops->file_offset;
/*
* A file should hold a users refcount while the file is open
* and put it back in its release. The file should hold a
* pointer to obj in their private data. Normal fput() is
* deferred to a workqueue and can get out of order with the
* following kfree(obj). Using the sync version ensures the
* release happens immediately. During abort we require the file
* refcount is one at this point - meaning the object alloc
* function cannot do anything to allow another thread to take a
* refcount prior to a guaranteed success.
*/
if (*filep)
__fput_sync(*filep);
}
if (ops->abort)
ops->abort(obj);
else
iommufd_object_ops[obj->type].destroy(obj);
ops->destroy(obj);
iommufd_object_abort(ictx, obj);
}
@ -493,6 +514,12 @@ void iommufd_ctx_put(struct iommufd_ctx *ictx)
}
EXPORT_SYMBOL_NS_GPL(iommufd_ctx_put, "IOMMUFD");
#define IOMMUFD_FILE_OFFSET(_struct, _filep, _obj) \
.file_offset = (offsetof(_struct, _filep) + \
BUILD_BUG_ON_ZERO(!__same_type( \
struct file *, ((_struct *)NULL)->_filep)) + \
BUILD_BUG_ON_ZERO(offsetof(_struct, _obj)))
static const struct iommufd_object_ops iommufd_object_ops[] = {
[IOMMUFD_OBJ_ACCESS] = {
.destroy = iommufd_access_destroy_object,
@ -502,6 +529,7 @@ static const struct iommufd_object_ops iommufd_object_ops[] = {
},
[IOMMUFD_OBJ_FAULT] = {
.destroy = iommufd_fault_destroy,
IOMMUFD_FILE_OFFSET(struct iommufd_fault, common.filep, common.obj),
},
[IOMMUFD_OBJ_HWPT_PAGING] = {
.destroy = iommufd_hwpt_paging_destroy,
@ -520,6 +548,7 @@ static const struct iommufd_object_ops iommufd_object_ops[] = {
[IOMMUFD_OBJ_VEVENTQ] = {
.destroy = iommufd_veventq_destroy,
.abort = iommufd_veventq_abort,
IOMMUFD_FILE_OFFSET(struct iommufd_veventq, common.filep, common.obj),
},
[IOMMUFD_OBJ_VIOMMU] = {
.destroy = iommufd_viommu_destroy,

View File

@ -67,6 +67,8 @@ struct phylink {
struct timer_list link_poll;
struct mutex state_mutex;
/* Serialize updates to pl->phydev with phylink_resolve() */
struct mutex phydev_mutex;
struct phylink_link_state phy_state;
unsigned int phy_ib_mode;
struct work_struct resolve;
@ -1588,8 +1590,11 @@ static void phylink_resolve(struct work_struct *w)
struct phylink_link_state link_state;
bool mac_config = false;
bool retrigger = false;
struct phy_device *phy;
bool cur_link_state;
mutex_lock(&pl->phydev_mutex);
phy = pl->phydev;
mutex_lock(&pl->state_mutex);
cur_link_state = phylink_link_is_up(pl);
@ -1623,11 +1628,11 @@ static void phylink_resolve(struct work_struct *w)
/* If we have a phy, the "up" state is the union of both the
* PHY and the MAC
*/
if (pl->phydev)
if (phy)
link_state.link &= pl->phy_state.link;
/* Only update if the PHY link is up */
if (pl->phydev && pl->phy_state.link) {
if (phy && pl->phy_state.link) {
/* If the interface has changed, force a link down
* event if the link isn't already down, and re-resolve.
*/
@ -1691,6 +1696,7 @@ static void phylink_resolve(struct work_struct *w)
queue_work(system_power_efficient_wq, &pl->resolve);
}
mutex_unlock(&pl->state_mutex);
mutex_unlock(&pl->phydev_mutex);
}
static void phylink_run_resolve(struct phylink *pl)
@ -1826,6 +1832,7 @@ struct phylink *phylink_create(struct phylink_config *config,
if (!pl)
return ERR_PTR(-ENOMEM);
mutex_init(&pl->phydev_mutex);
mutex_init(&pl->state_mutex);
INIT_WORK(&pl->resolve, phylink_resolve);
@ -2086,6 +2093,7 @@ static int phylink_bringup_phy(struct phylink *pl, struct phy_device *phy,
dev_name(&phy->mdio.dev), phy->drv->name, irq_str);
kfree(irq_str);
mutex_lock(&pl->phydev_mutex);
mutex_lock(&phy->lock);
mutex_lock(&pl->state_mutex);
pl->phydev = phy;
@ -2131,6 +2139,7 @@ static int phylink_bringup_phy(struct phylink *pl, struct phy_device *phy,
mutex_unlock(&pl->state_mutex);
mutex_unlock(&phy->lock);
mutex_unlock(&pl->phydev_mutex);
phylink_dbg(pl,
"phy: %s setting supported %*pb advertising %*pb\n",
@ -2309,6 +2318,7 @@ void phylink_disconnect_phy(struct phylink *pl)
ASSERT_RTNL();
mutex_lock(&pl->phydev_mutex);
phy = pl->phydev;
if (phy) {
mutex_lock(&phy->lock);
@ -2318,8 +2328,11 @@ void phylink_disconnect_phy(struct phylink *pl)
pl->mac_tx_clk_stop = false;
mutex_unlock(&pl->state_mutex);
mutex_unlock(&phy->lock);
flush_work(&pl->resolve);
}
mutex_unlock(&pl->phydev_mutex);
if (phy) {
flush_work(&pl->resolve);
phy_disconnect(phy);
}
}

View File

@ -94,6 +94,7 @@ static int __dwc3_gadget_ep0_queue(struct dwc3_ep *dep,
req->request.actual = 0;
req->request.status = -EINPROGRESS;
req->epnum = dep->number;
req->status = DWC3_REQUEST_STATUS_QUEUED;
list_add_tail(&req->list, &dep->pending_list);

View File

@ -228,6 +228,13 @@ void dwc3_gadget_giveback(struct dwc3_ep *dep, struct dwc3_request *req,
{
struct dwc3 *dwc = dep->dwc;
/*
* The request might have been processed and completed while the
* spinlock was released. Skip processing if already completed.
*/
if (req->status == DWC3_REQUEST_STATUS_COMPLETED)
return;
dwc3_gadget_del_and_unmap_request(dep, req, status);
req->status = DWC3_REQUEST_STATUS_COMPLETED;

View File

@ -615,6 +615,8 @@ extern int E_md4hash(const unsigned char *passwd, unsigned char *p16,
extern struct TCP_Server_Info *
cifs_find_tcp_session(struct smb3_fs_context *ctx);
struct cifs_tcon *cifs_setup_ipc(struct cifs_ses *ses, bool seal);
void __cifs_put_smb_ses(struct cifs_ses *ses);
extern struct cifs_ses *

View File

@ -2015,39 +2015,31 @@ static int match_session(struct cifs_ses *ses,
/**
* cifs_setup_ipc - helper to setup the IPC tcon for the session
* @ses: smb session to issue the request on
* @ctx: the superblock configuration context to use for building the
* new tree connection for the IPC (interprocess communication RPC)
* @seal: if encryption is requested
*
* A new IPC connection is made and stored in the session
* tcon_ipc. The IPC tcon has the same lifetime as the session.
*/
static int
cifs_setup_ipc(struct cifs_ses *ses, struct smb3_fs_context *ctx)
struct cifs_tcon *cifs_setup_ipc(struct cifs_ses *ses, bool seal)
{
int rc = 0, xid;
struct cifs_tcon *tcon;
char unc[SERVER_NAME_LENGTH + sizeof("//x/IPC$")] = {0};
bool seal = false;
struct TCP_Server_Info *server = ses->server;
/*
* If the mount request that resulted in the creation of the
* session requires encryption, force IPC to be encrypted too.
*/
if (ctx->seal) {
if (server->capabilities & SMB2_GLOBAL_CAP_ENCRYPTION)
seal = true;
else {
cifs_server_dbg(VFS,
"IPC: server doesn't support encryption\n");
return -EOPNOTSUPP;
}
if (seal && !(server->capabilities & SMB2_GLOBAL_CAP_ENCRYPTION)) {
cifs_server_dbg(VFS, "IPC: server doesn't support encryption\n");
return ERR_PTR(-EOPNOTSUPP);
}
/* no need to setup directory caching on IPC share, so pass in false */
tcon = tcon_info_alloc(false, netfs_trace_tcon_ref_new_ipc);
if (tcon == NULL)
return -ENOMEM;
return ERR_PTR(-ENOMEM);
spin_lock(&server->srv_lock);
scnprintf(unc, sizeof(unc), "\\\\%s\\IPC$", server->hostname);
@ -2057,13 +2049,13 @@ cifs_setup_ipc(struct cifs_ses *ses, struct smb3_fs_context *ctx)
tcon->ses = ses;
tcon->ipc = true;
tcon->seal = seal;
rc = server->ops->tree_connect(xid, ses, unc, tcon, ctx->local_nls);
rc = server->ops->tree_connect(xid, ses, unc, tcon, ses->local_nls);
free_xid(xid);
if (rc) {
cifs_server_dbg(VFS, "failed to connect to IPC (rc=%d)\n", rc);
cifs_server_dbg(VFS | ONCE, "failed to connect to IPC (rc=%d)\n", rc);
tconInfoFree(tcon, netfs_trace_tcon_ref_free_ipc_fail);
goto out;
return ERR_PTR(rc);
}
cifs_dbg(FYI, "IPC tcon rc=%d ipc tid=0x%x\n", rc, tcon->tid);
@ -2071,9 +2063,7 @@ cifs_setup_ipc(struct cifs_ses *ses, struct smb3_fs_context *ctx)
spin_lock(&tcon->tc_lock);
tcon->status = TID_GOOD;
spin_unlock(&tcon->tc_lock);
ses->tcon_ipc = tcon;
out:
return rc;
return tcon;
}
static struct cifs_ses *
@ -2347,6 +2337,7 @@ cifs_get_smb_ses(struct TCP_Server_Info *server, struct smb3_fs_context *ctx)
{
struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)&server->dstaddr;
struct sockaddr_in *addr = (struct sockaddr_in *)&server->dstaddr;
struct cifs_tcon *ipc;
struct cifs_ses *ses;
unsigned int xid;
int retries = 0;
@ -2525,7 +2516,12 @@ retry_new_session:
list_add(&ses->smb_ses_list, &server->smb_ses_list);
spin_unlock(&cifs_tcp_ses_lock);
cifs_setup_ipc(ses, ctx);
ipc = cifs_setup_ipc(ses, ctx->seal);
spin_lock(&cifs_tcp_ses_lock);
spin_lock(&ses->ses_lock);
ses->tcon_ipc = !IS_ERR(ipc) ? ipc : NULL;
spin_unlock(&ses->ses_lock);
spin_unlock(&cifs_tcp_ses_lock);
free_xid(xid);

View File

@ -1120,24 +1120,63 @@ static bool target_share_equal(struct cifs_tcon *tcon, const char *s1)
return match;
}
static bool is_ses_good(struct cifs_ses *ses)
static bool is_ses_good(struct cifs_tcon *tcon, struct cifs_ses *ses)
{
struct TCP_Server_Info *server = ses->server;
struct cifs_tcon *tcon = ses->tcon_ipc;
struct cifs_tcon *ipc = NULL;
bool ret;
spin_lock(&cifs_tcp_ses_lock);
spin_lock(&ses->ses_lock);
spin_lock(&ses->chan_lock);
ret = !cifs_chan_needs_reconnect(ses, server) &&
ses->ses_status == SES_GOOD &&
!tcon->need_reconnect;
ses->ses_status == SES_GOOD;
spin_unlock(&ses->chan_lock);
if (!ret)
goto out;
if (likely(ses->tcon_ipc)) {
if (ses->tcon_ipc->need_reconnect) {
ret = false;
goto out;
}
} else {
spin_unlock(&ses->ses_lock);
spin_unlock(&cifs_tcp_ses_lock);
ipc = cifs_setup_ipc(ses, tcon->seal);
spin_lock(&cifs_tcp_ses_lock);
spin_lock(&ses->ses_lock);
if (!IS_ERR(ipc)) {
if (!ses->tcon_ipc) {
ses->tcon_ipc = ipc;
ipc = NULL;
}
} else {
ret = false;
ipc = NULL;
}
}
out:
spin_unlock(&ses->ses_lock);
spin_unlock(&cifs_tcp_ses_lock);
if (ipc && server->ops->tree_disconnect) {
unsigned int xid = get_xid();
(void)server->ops->tree_disconnect(xid, ipc);
_free_xid(xid);
}
tconInfoFree(ipc, netfs_trace_tcon_ref_free_ipc);
return ret;
}
/* Refresh dfs referral of @ses */
static void refresh_ses_referral(struct cifs_ses *ses)
static void refresh_ses_referral(struct cifs_tcon *tcon, struct cifs_ses *ses)
{
struct cache_entry *ce;
unsigned int xid;
@ -1153,7 +1192,7 @@ static void refresh_ses_referral(struct cifs_ses *ses)
}
ses = CIFS_DFS_ROOT_SES(ses);
if (!is_ses_good(ses)) {
if (!is_ses_good(tcon, ses)) {
cifs_dbg(FYI, "%s: skip cache refresh due to disconnected ipc\n",
__func__);
goto out;
@ -1241,7 +1280,7 @@ static void refresh_tcon_referral(struct cifs_tcon *tcon, bool force_refresh)
up_read(&htable_rw_lock);
ses = CIFS_DFS_ROOT_SES(ses);
if (!is_ses_good(ses)) {
if (!is_ses_good(tcon, ses)) {
cifs_dbg(FYI, "%s: skip cache refresh due to disconnected ipc\n",
__func__);
goto out;
@ -1309,7 +1348,7 @@ void dfs_cache_refresh(struct work_struct *work)
tcon = container_of(work, struct cifs_tcon, dfs_cache_work.work);
list_for_each_entry(ses, &tcon->dfs_ses_list, dlist)
refresh_ses_referral(ses);
refresh_ses_referral(tcon, ses);
refresh_tcon_referral(tcon, false);
queue_delayed_work(dfscache_wq, &tcon->dfs_cache_work,

View File

@ -217,7 +217,21 @@ enum node_stat_item {
#endif
#ifdef CONFIG_NUMA_BALANCING
PGPROMOTE_SUCCESS, /* promote successfully */
PGPROMOTE_CANDIDATE, /* candidate pages to promote */
/**
* Candidate pages for promotion based on hint fault latency. This
* counter is used to control the promotion rate and adjust the hot
* threshold.
*/
PGPROMOTE_CANDIDATE,
/**
* Not rate-limited (NRL) candidate pages for those can be promoted
* without considering hot threshold because of enough free pages in
* fast-tier node. These promotions bypass the regular hotness checks
* and do NOT influence the promotion rate-limiter or
* threshold-adjustment logic.
* This is for statistics/monitoring purposes.
*/
RH_KABI_BROKEN_INSERT_ENUM(PGPROMOTE_CANDIDATE_NRL)
#endif
/* PGDEMOTE_*: pages demoted */
PGDEMOTE_KSWAPD,

View File

@ -96,30 +96,28 @@ static inline struct in6_addr *inetpeer_get_addr_v6(struct inetpeer_addr *iaddr)
/* can be called with or without local BH being disabled */
struct inet_peer *inet_getpeer(struct inet_peer_base *base,
const struct inetpeer_addr *daddr,
int create);
const struct inetpeer_addr *daddr);
static inline struct inet_peer *inet_getpeer_v4(struct inet_peer_base *base,
__be32 v4daddr,
int vif, int create)
int vif)
{
struct inetpeer_addr daddr;
daddr.a4.addr = v4daddr;
daddr.a4.vif = vif;
daddr.family = AF_INET;
return inet_getpeer(base, &daddr, create);
return inet_getpeer(base, &daddr);
}
static inline struct inet_peer *inet_getpeer_v6(struct inet_peer_base *base,
const struct in6_addr *v6daddr,
int create)
const struct in6_addr *v6daddr)
{
struct inetpeer_addr daddr;
daddr.a6 = *v6daddr;
daddr.family = AF_INET6;
return inet_getpeer(base, &daddr, create);
return inet_getpeer(base, &daddr);
}
static inline int inetpeer_addr_cmp(const struct inetpeer_addr *a,

View File

@ -22,6 +22,7 @@ TRACE_EVENT(kmem_cache_alloc,
TP_STRUCT__entry(
__field( unsigned long, call_site )
__field( const void *, ptr )
__string( name, s->name )
__field( size_t, bytes_req )
__field( size_t, bytes_alloc )
__field( unsigned long, gfp_flags )
@ -32,6 +33,7 @@ TRACE_EVENT(kmem_cache_alloc,
TP_fast_assign(
__entry->call_site = call_site;
__entry->ptr = ptr;
__assign_str(name);
__entry->bytes_req = s->object_size;
__entry->bytes_alloc = s->size;
__entry->gfp_flags = (__force unsigned long)gfp_flags;
@ -41,9 +43,10 @@ TRACE_EVENT(kmem_cache_alloc,
(s->flags & SLAB_ACCOUNT)) : false;
),
TP_printk("call_site=%pS ptr=%p bytes_req=%zu bytes_alloc=%zu gfp_flags=%s node=%d accounted=%s",
TP_printk("call_site=%pS ptr=%p name=%s bytes_req=%zu bytes_alloc=%zu gfp_flags=%s node=%d accounted=%s",
(void *)__entry->call_site,
__entry->ptr,
__get_str(name),
__entry->bytes_req,
__entry->bytes_alloc,
show_gfp_flags(__entry->gfp_flags),

View File

@ -1326,7 +1326,7 @@ int audit_compare_dname_path(const struct qstr *dname, const char *path, int par
/* handle trailing slashes */
pathlen -= parentlen;
while (p[pathlen - 1] == '/')
while (pathlen > 0 && p[pathlen - 1] == '/')
pathlen--;
if (pathlen != dlen)

View File

@ -1564,10 +1564,12 @@ throttle:
}
if (unlikely(is_dl_boosted(dl_se) || !start_dl_timer(dl_se))) {
if (dl_server(dl_se))
enqueue_dl_entity(dl_se, ENQUEUE_REPLENISH);
else
if (dl_server(dl_se)) {
replenish_dl_new_period(dl_se, rq);
start_dl_timer(dl_se);
} else {
enqueue_task_dl(rq, dl_task_of(dl_se), ENQUEUE_REPLENISH);
}
}
if (!is_leftmost(dl_se, &rq->dl))

View File

@ -1936,11 +1936,13 @@ bool should_numa_migrate_memory(struct task_struct *p, struct folio *folio,
struct pglist_data *pgdat;
unsigned long rate_limit;
unsigned int latency, th, def_th;
long nr = folio_nr_pages(folio);
pgdat = NODE_DATA(dst_nid);
if (pgdat_free_space_enough(pgdat)) {
/* workload changed, reset hot threshold */
pgdat->nbp_threshold = 0;
mod_node_page_state(pgdat, PGPROMOTE_CANDIDATE_NRL, nr);
return true;
}
@ -1954,8 +1956,7 @@ bool should_numa_migrate_memory(struct task_struct *p, struct folio *folio,
if (latency >= th)
return false;
return !numa_promotion_rate_limit(pgdat, rate_limit,
folio_nr_pages(folio));
return !numa_promotion_rate_limit(pgdat, rate_limit, nr);
}
this_cpupid = cpu_pid_to_cpupid(dst_cpu, current->pid);

View File

@ -925,19 +925,19 @@ static struct track *get_track(struct kmem_cache *s, void *object,
}
#ifdef CONFIG_STACKDEPOT
static noinline depot_stack_handle_t set_track_prepare(void)
static noinline depot_stack_handle_t set_track_prepare(gfp_t gfp_flags)
{
depot_stack_handle_t handle;
unsigned long entries[TRACK_ADDRS_COUNT];
unsigned int nr_entries;
nr_entries = stack_trace_save(entries, ARRAY_SIZE(entries), 3);
handle = stack_depot_save(entries, nr_entries, GFP_NOWAIT);
handle = stack_depot_save(entries, nr_entries, gfp_flags);
return handle;
}
#else
static inline depot_stack_handle_t set_track_prepare(void)
static inline depot_stack_handle_t set_track_prepare(gfp_t gfp_flags)
{
return 0;
}
@ -959,9 +959,9 @@ static void set_track_update(struct kmem_cache *s, void *object,
}
static __always_inline void set_track(struct kmem_cache *s, void *object,
enum track_item alloc, unsigned long addr)
enum track_item alloc, unsigned long addr, gfp_t gfp_flags)
{
depot_stack_handle_t handle = set_track_prepare();
depot_stack_handle_t handle = set_track_prepare(gfp_flags);
set_track_update(s, object, alloc, addr, handle);
}
@ -1868,9 +1868,9 @@ static inline bool free_debug_processing(struct kmem_cache *s,
static inline void slab_pad_check(struct kmem_cache *s, struct slab *slab) {}
static inline int check_object(struct kmem_cache *s, struct slab *slab,
void *object, u8 val) { return 1; }
static inline depot_stack_handle_t set_track_prepare(void) { return 0; }
static inline depot_stack_handle_t set_track_prepare(gfp_t gfp_flags) { return 0; }
static inline void set_track(struct kmem_cache *s, void *object,
enum track_item alloc, unsigned long addr) {}
enum track_item alloc, unsigned long addr, gfp_t gfp_flags) {}
static inline void add_full(struct kmem_cache *s, struct kmem_cache_node *n,
struct slab *slab) {}
static inline void remove_full(struct kmem_cache *s, struct kmem_cache_node *n,
@ -3831,9 +3831,14 @@ new_objects:
* For debug caches here we had to go through
* alloc_single_from_partial() so just store the
* tracking info and return the object.
*
* Due to disabled preemption we need to disallow
* blocking. The flags are further adjusted by
* gfp_nested_mask() in stack_depot itself.
*/
if (s->flags & SLAB_STORE_USER)
set_track(s, freelist, TRACK_ALLOC, addr);
set_track(s, freelist, TRACK_ALLOC, addr,
gfpflags & ~(__GFP_DIRECT_RECLAIM));
return freelist;
}
@ -3865,7 +3870,8 @@ new_objects:
goto new_objects;
if (s->flags & SLAB_STORE_USER)
set_track(s, freelist, TRACK_ALLOC, addr);
set_track(s, freelist, TRACK_ALLOC, addr,
gfpflags & ~(__GFP_DIRECT_RECLAIM));
return freelist;
}
@ -4370,8 +4376,12 @@ static noinline void free_to_partial_list(
unsigned long flags;
depot_stack_handle_t handle = 0;
/*
* We cannot use GFP_NOWAIT as there are callsites where waking up
* kswapd could deadlock
*/
if (s->flags & SLAB_STORE_USER)
handle = set_track_prepare();
handle = set_track_prepare(__GFP_NOWARN);
spin_lock_irqsave(&n->list_lock, flags);

View File

@ -1269,6 +1269,7 @@ const char * const vmstat_text[] = {
#ifdef CONFIG_NUMA_BALANCING
"pgpromote_success",
"pgpromote_candidate",
"pgpromote_candidate_nrl",
#endif
"pgdemote_kswapd",
"pgdemote_direct",

View File

@ -312,7 +312,6 @@ static bool icmpv4_xrlim_allow(struct net *net, struct rtable *rt,
struct dst_entry *dst = &rt->dst;
struct inet_peer *peer;
bool rc = true;
int vif;
if (!apply_ratelimit)
return true;
@ -321,12 +320,12 @@ static bool icmpv4_xrlim_allow(struct net *net, struct rtable *rt,
if (dst->dev && (dst->dev->flags&IFF_LOOPBACK))
goto out;
vif = l3mdev_master_ifindex(dst->dev);
peer = inet_getpeer_v4(net->ipv4.peers, fl4->daddr, vif, 1);
rcu_read_lock();
peer = inet_getpeer_v4(net->ipv4.peers, fl4->daddr,
l3mdev_master_ifindex_rcu(dst->dev));
rc = inet_peer_xrlim_allow(peer,
READ_ONCE(net->ipv4.sysctl_icmp_ratelimit));
if (peer)
inet_putpeer(peer);
rcu_read_unlock();
out:
if (!rc)
__ICMP_INC_STATS(net, ICMP_MIB_RATELIMITHOST);

View File

@ -95,6 +95,7 @@ static struct inet_peer *lookup(const struct inetpeer_addr *daddr,
{
struct rb_node **pp, *parent, *next;
struct inet_peer *p;
u32 now;
pp = &base->rb_root.rb_node;
parent = NULL;
@ -108,8 +109,9 @@ static struct inet_peer *lookup(const struct inetpeer_addr *daddr,
p = rb_entry(parent, struct inet_peer, rb_node);
cmp = inetpeer_addr_cmp(daddr, &p->daddr);
if (cmp == 0) {
if (!refcount_inc_not_zero(&p->refcnt))
break;
now = jiffies;
if (READ_ONCE(p->dtime) != now)
WRITE_ONCE(p->dtime, now);
return p;
}
if (gc_stack) {
@ -155,9 +157,6 @@ static void inet_peer_gc(struct inet_peer_base *base,
for (i = 0; i < gc_cnt; i++) {
p = gc_stack[i];
/* The READ_ONCE() pairs with the WRITE_ONCE()
* in inet_putpeer()
*/
delta = (__u32)jiffies - READ_ONCE(p->dtime);
if (delta < ttl || !refcount_dec_if_one(&p->refcnt))
@ -173,31 +172,23 @@ static void inet_peer_gc(struct inet_peer_base *base,
}
}
/* Must be called under RCU : No refcount change is done here. */
struct inet_peer *inet_getpeer(struct inet_peer_base *base,
const struct inetpeer_addr *daddr,
int create)
const struct inetpeer_addr *daddr)
{
struct inet_peer *p, *gc_stack[PEER_MAX_GC];
struct rb_node **pp, *parent;
unsigned int gc_cnt, seq;
int invalidated;
/* Attempt a lockless lookup first.
* Because of a concurrent writer, we might not find an existing entry.
*/
rcu_read_lock();
seq = read_seqbegin(&base->lock);
p = lookup(daddr, base, seq, NULL, &gc_cnt, &parent, &pp);
invalidated = read_seqretry(&base->lock, seq);
rcu_read_unlock();
if (p)
return p;
/* If no writer did a change during our lookup, we can return early. */
if (!create && !invalidated)
return NULL;
/* retry an exact lookup, taking the lock before.
* At least, nodes should be hot in our cache.
*/
@ -206,12 +197,12 @@ struct inet_peer *inet_getpeer(struct inet_peer_base *base,
gc_cnt = 0;
p = lookup(daddr, base, seq, gc_stack, &gc_cnt, &parent, &pp);
if (!p && create) {
if (!p) {
p = kmem_cache_alloc(peer_cachep, GFP_ATOMIC);
if (p) {
p->daddr = *daddr;
p->dtime = (__u32)jiffies;
refcount_set(&p->refcnt, 2);
refcount_set(&p->refcnt, 1);
atomic_set(&p->rid, 0);
p->metrics[RTAX_LOCK-1] = INETPEER_METRICS_NEW;
p->rate_tokens = 0;
@ -236,15 +227,9 @@ EXPORT_SYMBOL_GPL(inet_getpeer);
void inet_putpeer(struct inet_peer *p)
{
/* The WRITE_ONCE() pairs with itself (we run lockless)
* and the READ_ONCE() in inet_peer_gc()
*/
WRITE_ONCE(p->dtime, (__u32)jiffies);
if (refcount_dec_and_test(&p->refcnt))
call_rcu(&p->rcu, inetpeer_free_rcu);
}
EXPORT_SYMBOL_GPL(inet_putpeer);
/*
* Check transmit rate limitation for given message.

View File

@ -82,15 +82,20 @@ static int ip_frag_reasm(struct ipq *qp, struct sk_buff *skb,
static void ip4_frag_init(struct inet_frag_queue *q, const void *a)
{
struct ipq *qp = container_of(q, struct ipq, q);
struct net *net = q->fqdir->net;
const struct frag_v4_compare_key *key = a;
struct net *net = q->fqdir->net;
struct inet_peer *p = NULL;
q->key.v4 = *key;
qp->ecn = 0;
qp->peer = q->fqdir->max_dist ?
inet_getpeer_v4(net->ipv4.peers, key->saddr, key->vif, 1) :
NULL;
if (q->fqdir->max_dist) {
rcu_read_lock();
p = inet_getpeer_v4(net->ipv4.peers, key->saddr, key->vif);
if (p && !refcount_inc_not_zero(&p->refcnt))
p = NULL;
rcu_read_unlock();
}
qp->peer = p;
}
static void ip4_frag_free(struct inet_frag_queue *q)

View File

@ -876,11 +876,11 @@ void ip_rt_send_redirect(struct sk_buff *skb)
}
log_martians = IN_DEV_LOG_MARTIANS(in_dev);
vif = l3mdev_master_ifindex_rcu(rt->dst.dev);
rcu_read_unlock();
net = dev_net(rt->dst.dev);
peer = inet_getpeer_v4(net->ipv4.peers, ip_hdr(skb)->saddr, vif, 1);
peer = inet_getpeer_v4(net->ipv4.peers, ip_hdr(skb)->saddr, vif);
if (!peer) {
rcu_read_unlock();
icmp_send(skb, ICMP_REDIRECT, ICMP_REDIR_HOST,
rt_nexthop(rt, ip_hdr(skb)->daddr));
return;
@ -899,7 +899,7 @@ void ip_rt_send_redirect(struct sk_buff *skb)
*/
if (peer->n_redirects >= ip_rt_redirect_number) {
peer->rate_last = jiffies;
goto out_put_peer;
goto out_unlock;
}
/* Check for load limit; set rate_last to the latest sent
@ -920,8 +920,8 @@ void ip_rt_send_redirect(struct sk_buff *skb)
&ip_hdr(skb)->saddr, inet_iif(skb),
&ip_hdr(skb)->daddr, &gw);
}
out_put_peer:
inet_putpeer(peer);
out_unlock:
rcu_read_unlock();
}
static int ip_error(struct sk_buff *skb)
@ -981,9 +981,9 @@ static int ip_error(struct sk_buff *skb)
break;
}
rcu_read_lock();
peer = inet_getpeer_v4(net->ipv4.peers, ip_hdr(skb)->saddr,
l3mdev_master_ifindex(skb->dev), 1);
l3mdev_master_ifindex_rcu(skb->dev));
send = true;
if (peer) {
now = jiffies;
@ -995,8 +995,9 @@ static int ip_error(struct sk_buff *skb)
peer->rate_tokens -= ip_rt_error_cost;
else
send = false;
inet_putpeer(peer);
}
rcu_read_unlock();
if (send)
icmp_send(skb, ICMP_DEST_UNREACH, code, 0);

View File

@ -222,10 +222,10 @@ static bool icmpv6_xrlim_allow(struct sock *sk, u8 type,
if (rt->rt6i_dst.plen < 128)
tmo >>= ((128 - rt->rt6i_dst.plen)>>5);
peer = inet_getpeer_v6(net->ipv6.peers, &fl6->daddr, 1);
rcu_read_lock();
peer = inet_getpeer_v6(net->ipv6.peers, &fl6->daddr);
res = inet_peer_xrlim_allow(peer, tmo);
if (peer)
inet_putpeer(peer);
rcu_read_unlock();
}
if (!res)
__ICMP6_INC_STATS(net, ip6_dst_idev(dst),

View File

@ -613,15 +613,15 @@ int ip6_forward(struct sk_buff *skb)
else
target = &hdr->daddr;
peer = inet_getpeer_v6(net->ipv6.peers, &hdr->daddr, 1);
rcu_read_lock();
peer = inet_getpeer_v6(net->ipv6.peers, &hdr->daddr);
/* Limit redirects both by destination (here)
and by source (inside ndisc_send_redirect)
*/
if (inet_peer_xrlim_allow(peer, 1*HZ))
ndisc_send_redirect(skb, target);
if (peer)
inet_putpeer(peer);
rcu_read_unlock();
} else {
int addrtype = ipv6_addr_type(&hdr->saddr);

View File

@ -1729,10 +1729,12 @@ void ndisc_send_redirect(struct sk_buff *skb, const struct in6_addr *target)
"Redirect: destination is not a neighbour\n");
goto release;
}
peer = inet_getpeer_v6(net->ipv6.peers, &ipv6_hdr(skb)->saddr, 1);
rcu_read_lock();
peer = inet_getpeer_v6(net->ipv6.peers, &ipv6_hdr(skb)->saddr);
ret = inet_peer_xrlim_allow(peer, 1*HZ);
if (peer)
inet_putpeer(peer);
rcu_read_unlock();
if (!ret)
goto release;

View File

@ -169,13 +169,14 @@ next_chunk:
chunk->head_skb = chunk->skb;
/* skbs with "cover letter" */
if (chunk->head_skb && chunk->skb->data_len == chunk->skb->len)
if (chunk->head_skb && chunk->skb->data_len == chunk->skb->len) {
if (WARN_ON(!skb_shinfo(chunk->skb)->frag_list)) {
__SCTP_INC_STATS(dev_net(chunk->skb->dev),
SCTP_MIB_IN_PKT_DISCARDS);
sctp_chunk_free(chunk);
goto next_chunk;
}
chunk->skb = skb_shinfo(chunk->skb)->frag_list;
if (WARN_ON(!chunk->skb)) {
__SCTP_INC_STATS(dev_net(chunk->skb->dev), SCTP_MIB_IN_PKT_DISCARDS);
sctp_chunk_free(chunk);
goto next_chunk;
}
}

View File

@ -1612,8 +1612,10 @@ static int tls_decrypt_sg(struct sock *sk, struct iov_iter *out_iov,
if (unlikely(darg->async)) {
err = tls_strp_msg_hold(&ctx->strp, &ctx->async_hold);
if (err)
__skb_queue_tail(&ctx->async_hold, darg->skb);
if (err) {
err = tls_decrypt_async_wait(ctx);
darg->async = false;
}
return err;
}

View File

@ -115,21 +115,29 @@ ifndef RHJOBS
fi)
endif
LOCVERFILE:=../localversion
# create an empty localversion file if you don't want a local buildid
ifneq ($(wildcard $(LOCVERFILE)),)
DISTLOCALVERSION:=$(shell cat $(LOCVERFILE))
ifeq (,$(findstring s,$(firstword -$(MAKEFLAGS))))
$(info DISTLOCALVERSION is "$(DISTLOCALVERSION)". Update '$(shell dirname $(REDHAT))/localversion' to change.)
endif
else
ifeq ($(DISTLOCALVERSION),)
DISTLOCALVERSION:=.test
endif
# for official builds use RELEASE_LOCALVERSION persisted in Makefile.variables
ifneq ($(filter $(MAKECMDGOALS),dist-release dist-release-tag dist-release-git dist-rtg dist-get-tag),)
DISTLOCALVERSION:=$(RELEASE_LOCALVERSION)
ifeq (,$(findstring s,$(firstword -$(MAKEFLAGS))))
$(info DISTLOCALVERSION is "$(DISTLOCALVERSION)".)
endif
endif
else
LOCVERFILE:=../localversion
# create an empty localversion file if you don't want a local buildid
ifneq ($(wildcard $(LOCVERFILE)),)
DISTLOCALVERSION:=$(shell cat $(LOCVERFILE))
ifeq (,$(findstring s,$(firstword -$(MAKEFLAGS))))
$(info DISTLOCALVERSION is "$(DISTLOCALVERSION)". Update '$(shell dirname $(REDHAT))/localversion' to change.)
endif
else
ifeq ($(DISTLOCALVERSION),)
DISTLOCALVERSION:=.test
endif
ifeq (,$(findstring s,$(firstword -$(MAKEFLAGS))))
$(info DISTLOCALVERSION is "$(DISTLOCALVERSION)".)
endif
endif
endif # MAKECMDGOALS
# options for process_configs.sh script
ifdef NO_CONFIGCHECKS

View File

@ -94,6 +94,10 @@ PATCHLIST_URL ?= none
# unreleased kernel development snapshot.
RELEASED_KERNEL:=0
# Local version to be used for official (non-scratch) builds. Makefile
# dist-{release/tag/git} targets will ignore localversion and DISTLOCALVERSION
RELEASE_LOCALVERSION:=
# This variable is used by the redhat/self-tests. It should not be
# considered stable and my be changed or removed without warning.
RHDISTDATADIR ?=

View File

@ -1,3 +1,55 @@
* Sat Dec 27 2025 CKI KWF Bot <cki-ci-bot+kwf-gitlab-com@redhat.com> [6.12.0-124.27.1.el10_1]
- arm64: errata: Expand speculative SSBS workaround for Cortex-A720AE (Waiman Long) [RHEL-120684]
- arm64: cputype: Add Cortex-A720AE definitions (Waiman Long) [RHEL-120684]
- arm64: errata: Add missing sentinels to Spectre-BHB MIDR arrays (Waiman Long) [RHEL-120684]
- arm64: Add support for HIP09 Spectre-BHB mitigation (Waiman Long) [RHEL-120684]
- arm64: errata: Add newer ARM cores to the spectre_bhb_loop_affected() lists (Waiman Long) [RHEL-120684]
- arm64: cputype: Add MIDR_CORTEX_A76AE (Waiman Long) [RHEL-120684]
- arm64: errata: Add KRYO 2XX/3XX/4XX silver cores to Spectre BHB safe list (Waiman Long) [RHEL-120684]
- kmem/tracing: add kmem name to kmem_cache_alloc tracepoint (Charles Haithcock) [RHEL-129882]
- mm: memory-tiering: fix PGPROMOTE_CANDIDATE counting (Rafael Aquini) [RHEL-128383]
Resolves: RHEL-120684, RHEL-128383, RHEL-129882
* Tue Dec 23 2025 CKI KWF Bot <cki-ci-bot+kwf-gitlab-com@redhat.com> [6.12.0-124.26.1.el10_1]
- usb: dwc3: Fix race condition between concurrent dwc3_remove_requests() call paths (CKI Backport Bot) [RHEL-137150] {CVE-2025-68287}
- drm/vmwgfx: Validate command header size against SVGA_CMD_MAX_DATASIZE (CKI Backport Bot) [RHEL-134431] {CVE-2025-40277}
- net: phylink: add lock for serializing concurrent pl->phydev writes with resolver (CKI Backport Bot) [RHEL-129812] {CVE-2025-39905}
Resolves: RHEL-129812, RHEL-134431, RHEL-137150
* Sat Dec 20 2025 CKI KWF Bot <cki-ci-bot+kwf-gitlab-com@redhat.com> [6.12.0-124.25.1.el10_1]
- sctp: avoid NULL dereference when chunk data buffer is missing (CKI Backport Bot) [RHEL-134010] {CVE-2025-40240}
- HID: i2c-hid: Resolve touchpad issues on Dell systems during S4 (CKI Backport Bot) [RHEL-128281]
- HID: multitouch: fix slab out-of-bounds access in mt_report_fixup() (CKI Backport Bot) [RHEL-124610] {CVE-2025-39806}
- inetpeer: do not get a refcount in inet_getpeer() (Guillaume Nault) [RHEL-115287]
- inetpeer: update inetpeer timestamp in inet_getpeer() (Guillaume Nault) [RHEL-115287]
- inetpeer: remove create argument of inet_getpeer() (Guillaume Nault) [RHEL-115287]
- inetpeer: remove create argument of inet_getpeer_v[46]() (Guillaume Nault) [RHEL-115287]
Resolves: RHEL-115287, RHEL-124610, RHEL-128281, RHEL-134010
* Tue Dec 16 2025 CKI KWF Bot <cki-ci-bot+kwf-gitlab-com@redhat.com> [6.12.0-124.24.1.el10_1]
- audit: fix out-of-bounds read in audit_compare_dname_path() (Richard Guy Briggs) [RHEL-119185] {CVE-2025-39840}
Resolves: RHEL-119185
* Sat Dec 13 2025 CKI KWF Bot <cki-ci-bot+kwf-gitlab-com@redhat.com> [6.12.0-124.23.1.el10_1]
- redhat: use RELEASE_LOCALVERSION also for dist-get-tag (Jan Stancek)
- redhat: introduce RELEASE_LOCALVERSION variable (Jan Stancek)
- iommufd: Fix race during abort for file descriptors (Eder Zulian) [RHEL-123789] {CVE-2025-39966}
- smb: client: handle lack of IPC in dfs_cache_refresh() (Paulo Alcantara) [RHEL-126227]
- mm: slub: avoid wake up kswapd in set_track_prepare (Audra Mitchell) [RHEL-125522] {CVE-2025-39843}
- dpll: zl3073x: Increase maximum size of flash utility (Ivan Vecera) [RHEL-116157]
- dpll: zl3073x: Fix double free in zl3073x_devlink_flash_update() (Ivan Vecera) [RHEL-116157]
- dpll: zl3073x: Implement devlink flash callback (Ivan Vecera) [RHEL-116157]
- dpll: zl3073x: Add firmware loading functionality (Ivan Vecera) [RHEL-116157]
- dpll: zl3073x: Add low-level flash functions (Ivan Vecera) [RHEL-116157]
- dpll: zl3073x: Add functions to access hardware registers (Ivan Vecera) [RHEL-116157]
Resolves: RHEL-116157, RHEL-123789, RHEL-125522, RHEL-126227
* Sun Dec 07 2025 CKI KWF Bot <cki-ci-bot+kwf-gitlab-com@redhat.com> [6.12.0-124.22.1.el10_1]
- ASoC: Intel: sof_sdw: Add quirks for Lenovo P1 and P16 (CKI Backport Bot) [RHEL-130550]
- tls: wait for pending async decryptions if tls_strp_msg_hold fails (CKI Backport Bot) [RHEL-128866] {CVE-2025-40176}
- sched/deadline: Fix RT task potential starvation when expiry time passed (CKI Backport Bot) [RHEL-124660]
Resolves: RHEL-124660, RHEL-128866, RHEL-130550
* Thu Dec 04 2025 CKI KWF Bot <cki-ci-bot+kwf-gitlab-com@redhat.com> [6.12.0-124.21.1.el10_1]
- CVE-2025-38499 kernel: clone_private_mnt(): make sure that caller has CAP_SYS_ADMIN in the right userns (Abhi Das) [RHEL-129282] {CVE-2025-38499}
- net: tun: Update napi->skb after XDP process (CKI Backport Bot) [RHEL-122247] {CVE-2025-39984}

View File

@ -57,6 +57,7 @@ PROCESS_CONFIGS_OPTS=-n -w -c
REDHAT=../redhat
RELEASED_KERNEL=0
RELEASETAG=kernel-5.16.0-0.rc5.6.test
RELEASE_LOCALVERSION=
RHDISTGIT_BRANCH=c10s
RHDISTGIT_CACHE=
RHDISTGIT_TMP=/tmp

View File

@ -57,6 +57,7 @@ PROCESS_CONFIGS_OPTS=-n -w -c
REDHAT=../redhat
RELEASED_KERNEL=0
RELEASETAG=kernel-5.16.0-0.rc5.6.test
RELEASE_LOCALVERSION=
RHDISTGIT_BRANCH=c10s
RHDISTGIT_CACHE=
RHDISTGIT_TMP=/tmp

View File

@ -57,6 +57,7 @@ PROCESS_CONFIGS_OPTS=-n -w -c
REDHAT=../redhat
RELEASED_KERNEL=0
RELEASETAG=kernel-5.16.0-6.test
RELEASE_LOCALVERSION=
RHDISTGIT_BRANCH=c10s
RHDISTGIT_CACHE=
RHDISTGIT_TMP=/tmp

View File

@ -57,6 +57,7 @@ PROCESS_CONFIGS_OPTS=-n -w -c
REDHAT=../redhat
RELEASED_KERNEL=0
RELEASETAG=kernel-5.16.0-6.test
RELEASE_LOCALVERSION=
RHDISTGIT_BRANCH=c10s
RHDISTGIT_CACHE=
RHDISTGIT_TMP=/tmp

View File

@ -57,6 +57,7 @@ PROCESS_CONFIGS_OPTS=-n -w -c
REDHAT=../redhat
RELEASED_KERNEL=0
RELEASETAG=kernel-5.16.0-6.test
RELEASE_LOCALVERSION=
RHDISTGIT_BRANCH=c10s
RHDISTGIT_CACHE=
RHDISTGIT_TMP=/tmp

View File

@ -57,6 +57,7 @@ PROCESS_CONFIGS_OPTS=-n -w -c
REDHAT=../redhat
RELEASED_KERNEL=0
RELEASETAG=kernel-5.16.0-6.test
RELEASE_LOCALVERSION=
RHDISTGIT_BRANCH=c10s
RHDISTGIT_CACHE=
RHDISTGIT_TMP=/tmp

View File

@ -57,6 +57,7 @@ PROCESS_CONFIGS_OPTS=-n -w -c
REDHAT=../redhat
RELEASED_KERNEL=0
RELEASETAG=kernel-5.16.0-0.rc5.6.test
RELEASE_LOCALVERSION=
RHDISTGIT_BRANCH=c10s
RHDISTGIT_CACHE=
RHDISTGIT_TMP=/tmp

View File

@ -57,6 +57,7 @@ PROCESS_CONFIGS_OPTS=-n -w -c
REDHAT=../redhat
RELEASED_KERNEL=0
RELEASETAG=kernel-5.16.0-0.rc5.6.test
RELEASE_LOCALVERSION=
RHDISTGIT_BRANCH=c10s
RHDISTGIT_CACHE=
RHDISTGIT_TMP=/tmp

View File

@ -57,6 +57,7 @@ PROCESS_CONFIGS_OPTS=-n -w -c
REDHAT=../redhat
RELEASED_KERNEL=0
RELEASETAG=kernel-5.16.0-0.rc5.6.test
RELEASE_LOCALVERSION=
RHDISTGIT_BRANCH=rawhide
RHDISTGIT_CACHE=
RHDISTGIT_TMP=/tmp

View File

@ -57,6 +57,7 @@ PROCESS_CONFIGS_OPTS=-n -w -c
REDHAT=../redhat
RELEASED_KERNEL=0
RELEASETAG=kernel-5.16.0-0.rc5.6.test
RELEASE_LOCALVERSION=
RHDISTGIT_BRANCH=rawhide
RHDISTGIT_CACHE=
RHDISTGIT_TMP=/tmp

View File

@ -57,6 +57,7 @@ PROCESS_CONFIGS_OPTS=-n -w -c
REDHAT=../redhat
RELEASED_KERNEL=0
RELEASETAG=kernel-5.16.0-6.test
RELEASE_LOCALVERSION=
RHDISTGIT_BRANCH=rawhide
RHDISTGIT_CACHE=
RHDISTGIT_TMP=/tmp

View File

@ -57,6 +57,7 @@ PROCESS_CONFIGS_OPTS=-n -w -c
REDHAT=../redhat
RELEASED_KERNEL=0
RELEASETAG=kernel-5.16.0-6.test
RELEASE_LOCALVERSION=
RHDISTGIT_BRANCH=rawhide
RHDISTGIT_CACHE=
RHDISTGIT_TMP=/tmp

View File

@ -57,6 +57,7 @@ PROCESS_CONFIGS_OPTS=-n -w -c
REDHAT=../redhat
RELEASED_KERNEL=0
RELEASETAG=kernel-5.16.0-6.test
RELEASE_LOCALVERSION=
RHDISTGIT_BRANCH=rawhide
RHDISTGIT_CACHE=
RHDISTGIT_TMP=/tmp

View File

@ -57,6 +57,7 @@ PROCESS_CONFIGS_OPTS=-n -w -c
REDHAT=../redhat
RELEASED_KERNEL=0
RELEASETAG=kernel-5.16.0-6.test
RELEASE_LOCALVERSION=
RHDISTGIT_BRANCH=rawhide
RHDISTGIT_CACHE=
RHDISTGIT_TMP=/tmp

View File

@ -57,6 +57,7 @@ PROCESS_CONFIGS_OPTS=-n -w -c
REDHAT=../redhat
RELEASED_KERNEL=0
RELEASETAG=kernel-5.16.0-0.rc5.6.test
RELEASE_LOCALVERSION=
RHDISTGIT_BRANCH=rawhide
RHDISTGIT_CACHE=
RHDISTGIT_TMP=/tmp

View File

@ -57,6 +57,7 @@ PROCESS_CONFIGS_OPTS=-n -w -c
REDHAT=../redhat
RELEASED_KERNEL=0
RELEASETAG=kernel-5.16.0-0.rc5.6.test
RELEASE_LOCALVERSION=
RHDISTGIT_BRANCH=rawhide
RHDISTGIT_CACHE=
RHDISTGIT_TMP=/tmp

View File

@ -57,6 +57,7 @@ PROCESS_CONFIGS_OPTS=-n -w -c
REDHAT=../redhat
RELEASED_KERNEL=0
RELEASETAG=kernel-5.16.0-0.rc5.6.test
RELEASE_LOCALVERSION=
RHDISTGIT_BRANCH=rhel-10.1
RHDISTGIT_CACHE=
RHDISTGIT_TMP=/tmp

View File

@ -57,6 +57,7 @@ PROCESS_CONFIGS_OPTS=-n -w -c
REDHAT=../redhat
RELEASED_KERNEL=0
RELEASETAG=kernel-5.16.0-0.rc5.6.test
RELEASE_LOCALVERSION=
RHDISTGIT_BRANCH=rhel-10.1
RHDISTGIT_CACHE=
RHDISTGIT_TMP=/tmp

View File

@ -57,6 +57,7 @@ PROCESS_CONFIGS_OPTS=-n -w -c
REDHAT=../redhat
RELEASED_KERNEL=0
RELEASETAG=kernel-5.16.0-6.test
RELEASE_LOCALVERSION=
RHDISTGIT_BRANCH=rhel-10.1
RHDISTGIT_CACHE=
RHDISTGIT_TMP=/tmp

View File

@ -57,6 +57,7 @@ PROCESS_CONFIGS_OPTS=-n -w -c
REDHAT=../redhat
RELEASED_KERNEL=0
RELEASETAG=kernel-5.16.0-6.test
RELEASE_LOCALVERSION=
RHDISTGIT_BRANCH=rhel-10.1
RHDISTGIT_CACHE=
RHDISTGIT_TMP=/tmp

View File

@ -57,6 +57,7 @@ PROCESS_CONFIGS_OPTS=-n -w -c
REDHAT=../redhat
RELEASED_KERNEL=0
RELEASETAG=kernel-5.16.0-6.test
RELEASE_LOCALVERSION=
RHDISTGIT_BRANCH=rhel-10.1
RHDISTGIT_CACHE=
RHDISTGIT_TMP=/tmp

View File

@ -57,6 +57,7 @@ PROCESS_CONFIGS_OPTS=-n -w -c
REDHAT=../redhat
RELEASED_KERNEL=0
RELEASETAG=kernel-5.16.0-6.test
RELEASE_LOCALVERSION=
RHDISTGIT_BRANCH=rhel-10.1
RHDISTGIT_CACHE=
RHDISTGIT_TMP=/tmp

View File

@ -57,6 +57,7 @@ PROCESS_CONFIGS_OPTS=-n -w -c
REDHAT=../redhat
RELEASED_KERNEL=0
RELEASETAG=kernel-5.16.0-0.rc5.6.test
RELEASE_LOCALVERSION=
RHDISTGIT_BRANCH=rhel-10.1
RHDISTGIT_CACHE=
RHDISTGIT_TMP=/tmp

View File

@ -57,6 +57,7 @@ PROCESS_CONFIGS_OPTS=-n -w -c
REDHAT=../redhat
RELEASED_KERNEL=0
RELEASETAG=kernel-5.16.0-0.rc5.6.test
RELEASE_LOCALVERSION=
RHDISTGIT_BRANCH=rhel-10.1
RHDISTGIT_CACHE=
RHDISTGIT_TMP=/tmp

View File

@ -765,6 +765,9 @@ static const struct dmi_system_id sof_sdw_quirk_table[] = {
static const struct snd_pci_quirk sof_sdw_ssid_quirk_table[] = {
SND_PCI_QUIRK(0x1043, 0x1e13, "ASUS Zenbook S14", SOC_SDW_CODEC_MIC),
SND_PCI_QUIRK(0x1043, 0x1f43, "ASUS Zenbook S16", SOC_SDW_CODEC_MIC),
SND_PCI_QUIRK(0x17aa, 0x2347, "Lenovo P16", SOC_SDW_CODEC_MIC),
SND_PCI_QUIRK(0x17aa, 0x2348, "Lenovo P16", SOC_SDW_CODEC_MIC),
SND_PCI_QUIRK(0x17aa, 0x2349, "Lenovo P1", SOC_SDW_CODEC_MIC),
{}
};

View File

@ -1,3 +1,3 @@
sbat,1,SBAT Version,sbat,1,https://github.com/rhboot/shim/blob/main/SBAT.md
kernel-uki-virt-addons.centos,1,Red Hat,kernel-uki-virt-addons,6.12.0-124.21.1.el10.x86_64,mailto:secalert@redhat.com
kernel-uki-virt-addons.almalinux,1,AlmaLinux,kernel-uki-virt-addons,6.12.0-124.21.1.el10.x86_64,mailto:security@almalinux.org
kernel-uki-virt-addons.centos,1,Red Hat,kernel-uki-virt-addons,6.12.0-124.27.1.el10.x86_64,mailto:secalert@redhat.com
kernel-uki-virt-addons.almalinux,1,AlmaLinux,kernel-uki-virt-addons,6.12.0-124.27.1.el10.x86_64,mailto:security@almalinux.org

View File

@ -1,3 +1,3 @@
sbat,1,SBAT Version,sbat,1,https://github.com/rhboot/shim/blob/main/SBAT.md
kernel-uki-virt.centos,1,Red Hat,kernel-uki-virt,6.12.0-124.21.1.el10.x86_64,mailto:secalert@redhat.com
kernel-uki-virt.almalinux,1,AlmaLinux,kernel-uki-virt,6.12.0-124.21.1.el10.x86_64,mailto:security@almalinux.org
kernel-uki-virt.centos,1,Red Hat,kernel-uki-virt,6.12.0-124.27.1.el10.x86_64,mailto:secalert@redhat.com
kernel-uki-virt.almalinux,1,AlmaLinux,kernel-uki-virt,6.12.0-124.27.1.el10.x86_64,mailto:security@almalinux.org