mirror of
https://github.com/torvalds/linux.git
synced 2026-06-07 14:04:54 +02:00
Linux 5.12-rc4
-----BEGIN PGP SIGNATURE----- iQFSBAABCAA8FiEEq68RxlopcLEwq+PEeb4+QwBBGIYFAmBXwRseHHRvcnZhbGRz QGxpbnV4LWZvdW5kYXRpb24ub3JnAAoJEHm+PkMAQRiGX80H/2qQ49e2lbOfIqdR CBThtgg89QmN9WPTfVhwB6b4vejB7kIiIpOPyJVkaio6lVe8Ewhl064fnGHwXm39 vPy0ZVAB96oaKaki6qi1k7jhCAMpl/vXf1RDe5PaEKPwp3Lr81BlY6dcTPbjxkFP Uw+uC3iRQnT8msSqA1vnhbDl9w6jfmuxX45Eo9NWGz0hDCpZNOEt2oSo/OcXTH4k c91FiW8Qv9uZX2tV4VSqFQgVPfneA+OWXMpjMg6kfK3jOJ5cZwmFGAa8ByqWACH/ U9OODYQCsyX5ZM11g7MOt7Iv+YSU8OA0We8KDN4cRZobrCHF0Txp3ZTSPjb/xHE3 9nUM50I= =a6Go -----END PGP SIGNATURE----- Merge tag 'v5.12-rc4' into android-mainline Linux 5.12-rc4 Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> Change-Id: I9370213bbbb4a0dbbfc91849eeaea674ce3e200a
This commit is contained in:
commit
ae001f3b8f
|
|
@ -1181,7 +1181,7 @@ M: Joel Fernandes <joel@joelfernandes.org>
|
|||
M: Christian Brauner <christian@brauner.io>
|
||||
M: Hridya Valsaraju <hridya@google.com>
|
||||
M: Suren Baghdasaryan <surenb@google.com>
|
||||
L: devel@driverdev.osuosl.org
|
||||
L: linux-kernel@vger.kernel.org
|
||||
S: Supported
|
||||
T: git git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/staging.git
|
||||
F: drivers/android/
|
||||
|
|
@ -8116,7 +8116,6 @@ F: drivers/crypto/hisilicon/sec2/sec_main.c
|
|||
|
||||
HISILICON STAGING DRIVERS FOR HIKEY 960/970
|
||||
M: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>
|
||||
L: devel@driverdev.osuosl.org
|
||||
S: Maintained
|
||||
F: drivers/staging/hikey9xx/
|
||||
|
||||
|
|
@ -17053,7 +17052,7 @@ F: drivers/staging/vt665?/
|
|||
|
||||
STAGING SUBSYSTEM
|
||||
M: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
|
||||
L: devel@driverdev.osuosl.org
|
||||
L: linux-staging@lists.linux.dev
|
||||
S: Supported
|
||||
T: git git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/staging.git
|
||||
F: drivers/staging/
|
||||
|
|
@ -19148,7 +19147,7 @@ VME SUBSYSTEM
|
|||
M: Martyn Welch <martyn@welchs.me.uk>
|
||||
M: Manohar Vanga <manohar.vanga@gmail.com>
|
||||
M: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
|
||||
L: devel@driverdev.osuosl.org
|
||||
L: linux-kernel@vger.kernel.org
|
||||
S: Maintained
|
||||
T: git git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/char-misc.git
|
||||
F: Documentation/driver-api/vme.rst
|
||||
|
|
|
|||
2
Makefile
2
Makefile
|
|
@ -2,7 +2,7 @@
|
|||
VERSION = 5
|
||||
PATCHLEVEL = 12
|
||||
SUBLEVEL = 0
|
||||
EXTRAVERSION = -rc3
|
||||
EXTRAVERSION = -rc4
|
||||
NAME = Frozen Wasteland
|
||||
|
||||
# *DOCUMENTATION*
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@
|
|||
#include <linux/bug.h>
|
||||
#include <asm/cputable.h>
|
||||
|
||||
static inline bool early_cpu_has_feature(unsigned long feature)
|
||||
static __always_inline bool early_cpu_has_feature(unsigned long feature)
|
||||
{
|
||||
return !!((CPU_FTRS_ALWAYS & feature) ||
|
||||
(CPU_FTRS_POSSIBLE & cur_cpu_spec->cpu_features & feature));
|
||||
|
|
@ -46,7 +46,7 @@ static __always_inline bool cpu_has_feature(unsigned long feature)
|
|||
return static_branch_likely(&cpu_feature_keys[i]);
|
||||
}
|
||||
#else
|
||||
static inline bool cpu_has_feature(unsigned long feature)
|
||||
static __always_inline bool cpu_has_feature(unsigned long feature)
|
||||
{
|
||||
return early_cpu_has_feature(feature);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -65,3 +65,14 @@ V_FUNCTION_END(__kernel_clock_getres)
|
|||
V_FUNCTION_BEGIN(__kernel_time)
|
||||
cvdso_call_time __c_kernel_time
|
||||
V_FUNCTION_END(__kernel_time)
|
||||
|
||||
/* Routines for restoring integer registers, called by the compiler. */
|
||||
/* Called with r11 pointing to the stack header word of the caller of the */
|
||||
/* function, just beyond the end of the integer restore area. */
|
||||
_GLOBAL(_restgpr_31_x)
|
||||
_GLOBAL(_rest32gpr_31_x)
|
||||
lwz r0,4(r11)
|
||||
lwz r31,-4(r11)
|
||||
mtlr r0
|
||||
mr r1,r11
|
||||
blr
|
||||
|
|
|
|||
|
|
@ -3659,6 +3659,9 @@ static int intel_pmu_hw_config(struct perf_event *event)
|
|||
return ret;
|
||||
|
||||
if (event->attr.precise_ip) {
|
||||
if ((event->attr.config & INTEL_ARCH_EVENT_MASK) == INTEL_FIXED_VLBR_EVENT)
|
||||
return -EINVAL;
|
||||
|
||||
if (!(event->attr.freq || (event->attr.wakeup_events && !event->attr.watermark))) {
|
||||
event->hw.flags |= PERF_X86_EVENT_AUTO_RELOAD;
|
||||
if (!(event->attr.sample_type &
|
||||
|
|
|
|||
|
|
@ -2010,7 +2010,7 @@ static void intel_pmu_drain_pebs_nhm(struct pt_regs *iregs, struct perf_sample_d
|
|||
*/
|
||||
if (!pebs_status && cpuc->pebs_enabled &&
|
||||
!(cpuc->pebs_enabled & (cpuc->pebs_enabled-1)))
|
||||
pebs_status = cpuc->pebs_enabled;
|
||||
pebs_status = p->status = cpuc->pebs_enabled;
|
||||
|
||||
bit = find_first_bit((unsigned long *)&pebs_status,
|
||||
x86_pmu.max_pebs_events);
|
||||
|
|
|
|||
|
|
@ -551,15 +551,6 @@ static inline void arch_thread_struct_whitelist(unsigned long *offset,
|
|||
*size = fpu_kernel_xstate_size;
|
||||
}
|
||||
|
||||
/*
|
||||
* Thread-synchronous status.
|
||||
*
|
||||
* This is different from the flags in that nobody else
|
||||
* ever touches our thread-synchronous status, so we don't
|
||||
* have to worry about atomic accesses.
|
||||
*/
|
||||
#define TS_COMPAT 0x0002 /* 32bit syscall active (64BIT)*/
|
||||
|
||||
static inline void
|
||||
native_load_sp0(unsigned long sp0)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -205,10 +205,23 @@ static inline int arch_within_stack_frames(const void * const stack,
|
|||
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Thread-synchronous status.
|
||||
*
|
||||
* This is different from the flags in that nobody else
|
||||
* ever touches our thread-synchronous status, so we don't
|
||||
* have to worry about atomic accesses.
|
||||
*/
|
||||
#define TS_COMPAT 0x0002 /* 32bit syscall active (64BIT)*/
|
||||
|
||||
#ifndef __ASSEMBLY__
|
||||
#ifdef CONFIG_COMPAT
|
||||
#define TS_I386_REGS_POKED 0x0004 /* regs poked by 32-bit ptracer */
|
||||
|
||||
#define arch_set_restart_data(restart) \
|
||||
do { restart->arch_data = current_thread_info()->status; } while (0)
|
||||
|
||||
#endif
|
||||
#ifndef __ASSEMBLY__
|
||||
|
||||
#ifdef CONFIG_X86_32
|
||||
#define in_ia32_syscall() true
|
||||
|
|
|
|||
|
|
@ -2342,6 +2342,11 @@ static int cpuid_to_apicid[] = {
|
|||
[0 ... NR_CPUS - 1] = -1,
|
||||
};
|
||||
|
||||
bool arch_match_cpu_phys_id(int cpu, u64 phys_id)
|
||||
{
|
||||
return phys_id == cpuid_to_apicid[cpu];
|
||||
}
|
||||
|
||||
#ifdef CONFIG_SMP
|
||||
/**
|
||||
* apic_id_is_primary_thread - Check whether APIC ID belongs to a primary thread
|
||||
|
|
|
|||
|
|
@ -1032,6 +1032,16 @@ static int mp_map_pin_to_irq(u32 gsi, int idx, int ioapic, int pin,
|
|||
if (idx >= 0 && test_bit(mp_irqs[idx].srcbus, mp_bus_not_pci)) {
|
||||
irq = mp_irqs[idx].srcbusirq;
|
||||
legacy = mp_is_legacy_irq(irq);
|
||||
/*
|
||||
* IRQ2 is unusable for historical reasons on systems which
|
||||
* have a legacy PIC. See the comment vs. IRQ2 further down.
|
||||
*
|
||||
* If this gets removed at some point then the related code
|
||||
* in lapic_assign_system_vectors() needs to be adjusted as
|
||||
* well.
|
||||
*/
|
||||
if (legacy && irq == PIC_CASCADE_IR)
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
mutex_lock(&ioapic_mutex);
|
||||
|
|
|
|||
|
|
@ -766,30 +766,8 @@ handle_signal(struct ksignal *ksig, struct pt_regs *regs)
|
|||
|
||||
static inline unsigned long get_nr_restart_syscall(const struct pt_regs *regs)
|
||||
{
|
||||
/*
|
||||
* This function is fundamentally broken as currently
|
||||
* implemented.
|
||||
*
|
||||
* The idea is that we want to trigger a call to the
|
||||
* restart_block() syscall and that we want in_ia32_syscall(),
|
||||
* in_x32_syscall(), etc. to match whatever they were in the
|
||||
* syscall being restarted. We assume that the syscall
|
||||
* instruction at (regs->ip - 2) matches whatever syscall
|
||||
* instruction we used to enter in the first place.
|
||||
*
|
||||
* The problem is that we can get here when ptrace pokes
|
||||
* syscall-like values into regs even if we're not in a syscall
|
||||
* at all.
|
||||
*
|
||||
* For now, we maintain historical behavior and guess based on
|
||||
* stored state. We could do better by saving the actual
|
||||
* syscall arch in restart_block or (with caveats on x32) by
|
||||
* checking if regs->ip points to 'int $0x80'. The current
|
||||
* behavior is incorrect if a tracer has a different bitness
|
||||
* than the tracee.
|
||||
*/
|
||||
#ifdef CONFIG_IA32_EMULATION
|
||||
if (current_thread_info()->status & (TS_COMPAT|TS_I386_REGS_POKED))
|
||||
if (current->restart_block.arch_data & TS_COMPAT)
|
||||
return __NR_ia32_restart_syscall;
|
||||
#endif
|
||||
#ifdef CONFIG_X86_X32_ABI
|
||||
|
|
|
|||
|
|
@ -31,7 +31,7 @@ struct stm32_timer_cnt {
|
|||
struct counter_device counter;
|
||||
struct regmap *regmap;
|
||||
struct clk *clk;
|
||||
u32 ceiling;
|
||||
u32 max_arr;
|
||||
bool enabled;
|
||||
struct stm32_timer_regs bak;
|
||||
};
|
||||
|
|
@ -44,13 +44,14 @@ struct stm32_timer_cnt {
|
|||
* @STM32_COUNT_ENCODER_MODE_3: counts on both TI1FP1 and TI2FP2 edges
|
||||
*/
|
||||
enum stm32_count_function {
|
||||
STM32_COUNT_SLAVE_MODE_DISABLED = -1,
|
||||
STM32_COUNT_SLAVE_MODE_DISABLED,
|
||||
STM32_COUNT_ENCODER_MODE_1,
|
||||
STM32_COUNT_ENCODER_MODE_2,
|
||||
STM32_COUNT_ENCODER_MODE_3,
|
||||
};
|
||||
|
||||
static enum counter_count_function stm32_count_functions[] = {
|
||||
[STM32_COUNT_SLAVE_MODE_DISABLED] = COUNTER_COUNT_FUNCTION_INCREASE,
|
||||
[STM32_COUNT_ENCODER_MODE_1] = COUNTER_COUNT_FUNCTION_QUADRATURE_X2_A,
|
||||
[STM32_COUNT_ENCODER_MODE_2] = COUNTER_COUNT_FUNCTION_QUADRATURE_X2_B,
|
||||
[STM32_COUNT_ENCODER_MODE_3] = COUNTER_COUNT_FUNCTION_QUADRATURE_X4,
|
||||
|
|
@ -73,8 +74,10 @@ static int stm32_count_write(struct counter_device *counter,
|
|||
const unsigned long val)
|
||||
{
|
||||
struct stm32_timer_cnt *const priv = counter->priv;
|
||||
u32 ceiling;
|
||||
|
||||
if (val > priv->ceiling)
|
||||
regmap_read(priv->regmap, TIM_ARR, &ceiling);
|
||||
if (val > ceiling)
|
||||
return -EINVAL;
|
||||
|
||||
return regmap_write(priv->regmap, TIM_CNT, val);
|
||||
|
|
@ -90,6 +93,9 @@ static int stm32_count_function_get(struct counter_device *counter,
|
|||
regmap_read(priv->regmap, TIM_SMCR, &smcr);
|
||||
|
||||
switch (smcr & TIM_SMCR_SMS) {
|
||||
case 0:
|
||||
*function = STM32_COUNT_SLAVE_MODE_DISABLED;
|
||||
return 0;
|
||||
case 1:
|
||||
*function = STM32_COUNT_ENCODER_MODE_1;
|
||||
return 0;
|
||||
|
|
@ -99,9 +105,9 @@ static int stm32_count_function_get(struct counter_device *counter,
|
|||
case 3:
|
||||
*function = STM32_COUNT_ENCODER_MODE_3;
|
||||
return 0;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static int stm32_count_function_set(struct counter_device *counter,
|
||||
|
|
@ -112,6 +118,9 @@ static int stm32_count_function_set(struct counter_device *counter,
|
|||
u32 cr1, sms;
|
||||
|
||||
switch (function) {
|
||||
case STM32_COUNT_SLAVE_MODE_DISABLED:
|
||||
sms = 0;
|
||||
break;
|
||||
case STM32_COUNT_ENCODER_MODE_1:
|
||||
sms = 1;
|
||||
break;
|
||||
|
|
@ -122,8 +131,7 @@ static int stm32_count_function_set(struct counter_device *counter,
|
|||
sms = 3;
|
||||
break;
|
||||
default:
|
||||
sms = 0;
|
||||
break;
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* Store enable status */
|
||||
|
|
@ -131,10 +139,6 @@ static int stm32_count_function_set(struct counter_device *counter,
|
|||
|
||||
regmap_update_bits(priv->regmap, TIM_CR1, TIM_CR1_CEN, 0);
|
||||
|
||||
/* TIMx_ARR register shouldn't be buffered (ARPE=0) */
|
||||
regmap_update_bits(priv->regmap, TIM_CR1, TIM_CR1_ARPE, 0);
|
||||
regmap_write(priv->regmap, TIM_ARR, priv->ceiling);
|
||||
|
||||
regmap_update_bits(priv->regmap, TIM_SMCR, TIM_SMCR_SMS, sms);
|
||||
|
||||
/* Make sure that registers are updated */
|
||||
|
|
@ -185,11 +189,13 @@ static ssize_t stm32_count_ceiling_write(struct counter_device *counter,
|
|||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (ceiling > priv->max_arr)
|
||||
return -ERANGE;
|
||||
|
||||
/* TIMx_ARR register shouldn't be buffered (ARPE=0) */
|
||||
regmap_update_bits(priv->regmap, TIM_CR1, TIM_CR1_ARPE, 0);
|
||||
regmap_write(priv->regmap, TIM_ARR, ceiling);
|
||||
|
||||
priv->ceiling = ceiling;
|
||||
return len;
|
||||
}
|
||||
|
||||
|
|
@ -274,31 +280,36 @@ static int stm32_action_get(struct counter_device *counter,
|
|||
size_t function;
|
||||
int err;
|
||||
|
||||
/* Default action mode (e.g. STM32_COUNT_SLAVE_MODE_DISABLED) */
|
||||
*action = STM32_SYNAPSE_ACTION_NONE;
|
||||
|
||||
err = stm32_count_function_get(counter, count, &function);
|
||||
if (err)
|
||||
return 0;
|
||||
return err;
|
||||
|
||||
switch (function) {
|
||||
case STM32_COUNT_SLAVE_MODE_DISABLED:
|
||||
/* counts on internal clock when CEN=1 */
|
||||
*action = STM32_SYNAPSE_ACTION_NONE;
|
||||
return 0;
|
||||
case STM32_COUNT_ENCODER_MODE_1:
|
||||
/* counts up/down on TI1FP1 edge depending on TI2FP2 level */
|
||||
if (synapse->signal->id == count->synapses[0].signal->id)
|
||||
*action = STM32_SYNAPSE_ACTION_BOTH_EDGES;
|
||||
break;
|
||||
else
|
||||
*action = STM32_SYNAPSE_ACTION_NONE;
|
||||
return 0;
|
||||
case STM32_COUNT_ENCODER_MODE_2:
|
||||
/* counts up/down on TI2FP2 edge depending on TI1FP1 level */
|
||||
if (synapse->signal->id == count->synapses[1].signal->id)
|
||||
*action = STM32_SYNAPSE_ACTION_BOTH_EDGES;
|
||||
break;
|
||||
else
|
||||
*action = STM32_SYNAPSE_ACTION_NONE;
|
||||
return 0;
|
||||
case STM32_COUNT_ENCODER_MODE_3:
|
||||
/* counts up/down on both TI1FP1 and TI2FP2 edges */
|
||||
*action = STM32_SYNAPSE_ACTION_BOTH_EDGES;
|
||||
break;
|
||||
return 0;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct counter_ops stm32_timer_cnt_ops = {
|
||||
|
|
@ -359,7 +370,7 @@ static int stm32_timer_cnt_probe(struct platform_device *pdev)
|
|||
|
||||
priv->regmap = ddata->regmap;
|
||||
priv->clk = ddata->clk;
|
||||
priv->ceiling = ddata->max_arr;
|
||||
priv->max_arr = ddata->max_arr;
|
||||
|
||||
priv->counter.name = dev_name(dev);
|
||||
priv->counter.parent = dev;
|
||||
|
|
|
|||
|
|
@ -927,7 +927,7 @@ int __ref efi_mem_reserve_persistent(phys_addr_t addr, u64 size)
|
|||
}
|
||||
|
||||
/* first try to find a slot in an existing linked list entry */
|
||||
for (prsv = efi_memreserve_root->next; prsv; prsv = rsv->next) {
|
||||
for (prsv = efi_memreserve_root->next; prsv; ) {
|
||||
rsv = memremap(prsv, sizeof(*rsv), MEMREMAP_WB);
|
||||
index = atomic_fetch_add_unless(&rsv->count, 1, rsv->size);
|
||||
if (index < rsv->size) {
|
||||
|
|
@ -937,6 +937,7 @@ int __ref efi_mem_reserve_persistent(phys_addr_t addr, u64 size)
|
|||
memunmap(rsv);
|
||||
return efi_mem_reserve_iomem(addr, size);
|
||||
}
|
||||
prsv = rsv->next;
|
||||
memunmap(rsv);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -484,6 +484,10 @@ int efivar_init(int (*func)(efi_char16_t *, efi_guid_t, unsigned long, void *),
|
|||
}
|
||||
}
|
||||
|
||||
break;
|
||||
case EFI_UNSUPPORTED:
|
||||
err = -EOPNOTSUPP;
|
||||
status = EFI_NOT_FOUND;
|
||||
break;
|
||||
case EFI_NOT_FOUND:
|
||||
break;
|
||||
|
|
|
|||
|
|
@ -266,6 +266,8 @@ config ADI_AXI_ADC
|
|||
select IIO_BUFFER
|
||||
select IIO_BUFFER_HW_CONSUMER
|
||||
select IIO_BUFFER_DMAENGINE
|
||||
depends on HAS_IOMEM
|
||||
depends on OF
|
||||
help
|
||||
Say yes here to build support for Analog Devices Generic
|
||||
AXI ADC IP core. The IP core is used for interfacing with
|
||||
|
|
@ -923,6 +925,7 @@ config STM32_ADC_CORE
|
|||
depends on ARCH_STM32 || COMPILE_TEST
|
||||
depends on OF
|
||||
depends on REGULATOR
|
||||
depends on HAS_IOMEM
|
||||
select IIO_BUFFER
|
||||
select MFD_STM32_TIMERS
|
||||
select IIO_STM32_TIMER_TRIGGER
|
||||
|
|
|
|||
|
|
@ -918,7 +918,7 @@ static int ab8500_gpadc_read_raw(struct iio_dev *indio_dev,
|
|||
return processed;
|
||||
|
||||
/* Return millivolt or milliamps or millicentigrades */
|
||||
*val = processed * 1000;
|
||||
*val = processed;
|
||||
return IIO_VAL_INT;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -91,7 +91,7 @@ static int ad7949_spi_read_channel(struct ad7949_adc_chip *ad7949_adc, int *val,
|
|||
int ret;
|
||||
int i;
|
||||
int bits_per_word = ad7949_adc->resolution;
|
||||
int mask = GENMASK(ad7949_adc->resolution, 0);
|
||||
int mask = GENMASK(ad7949_adc->resolution - 1, 0);
|
||||
struct spi_message msg;
|
||||
struct spi_transfer tx[] = {
|
||||
{
|
||||
|
|
|
|||
|
|
@ -597,7 +597,7 @@ static const struct vadc_channels vadc_chans[] = {
|
|||
VADC_CHAN_NO_SCALE(P_MUX16_1_3, 1)
|
||||
|
||||
VADC_CHAN_NO_SCALE(LR_MUX1_BAT_THERM, 0)
|
||||
VADC_CHAN_NO_SCALE(LR_MUX2_BAT_ID, 0)
|
||||
VADC_CHAN_VOLT(LR_MUX2_BAT_ID, 0, SCALE_DEFAULT)
|
||||
VADC_CHAN_NO_SCALE(LR_MUX3_XO_THERM, 0)
|
||||
VADC_CHAN_NO_SCALE(LR_MUX4_AMUX_THM1, 0)
|
||||
VADC_CHAN_NO_SCALE(LR_MUX5_AMUX_THM2, 0)
|
||||
|
|
|
|||
|
|
@ -551,6 +551,8 @@ static irqreturn_t mpu3050_trigger_handler(int irq, void *p)
|
|||
MPU3050_FIFO_R,
|
||||
&fifo_values[offset],
|
||||
toread);
|
||||
if (ret)
|
||||
goto out_trigger_unlock;
|
||||
|
||||
dev_dbg(mpu3050->dev,
|
||||
"%04x %04x %04x %04x %04x\n",
|
||||
|
|
|
|||
|
|
@ -15,7 +15,10 @@
|
|||
struct hid_humidity_state {
|
||||
struct hid_sensor_common common_attributes;
|
||||
struct hid_sensor_hub_attribute_info humidity_attr;
|
||||
s32 humidity_data;
|
||||
struct {
|
||||
s32 humidity_data;
|
||||
u64 timestamp __aligned(8);
|
||||
} scan;
|
||||
int scale_pre_decml;
|
||||
int scale_post_decml;
|
||||
int scale_precision;
|
||||
|
|
@ -125,9 +128,8 @@ static int humidity_proc_event(struct hid_sensor_hub_device *hsdev,
|
|||
struct hid_humidity_state *humid_st = iio_priv(indio_dev);
|
||||
|
||||
if (atomic_read(&humid_st->common_attributes.data_ready))
|
||||
iio_push_to_buffers_with_timestamp(indio_dev,
|
||||
&humid_st->humidity_data,
|
||||
iio_get_time_ns(indio_dev));
|
||||
iio_push_to_buffers_with_timestamp(indio_dev, &humid_st->scan,
|
||||
iio_get_time_ns(indio_dev));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -142,7 +144,7 @@ static int humidity_capture_sample(struct hid_sensor_hub_device *hsdev,
|
|||
|
||||
switch (usage_id) {
|
||||
case HID_USAGE_SENSOR_ATMOSPHERIC_HUMIDITY:
|
||||
humid_st->humidity_data = *(s32 *)raw_data;
|
||||
humid_st->scan.humidity_data = *(s32 *)raw_data;
|
||||
|
||||
return 0;
|
||||
default:
|
||||
|
|
|
|||
|
|
@ -462,8 +462,7 @@ static int adis16400_initial_setup(struct iio_dev *indio_dev)
|
|||
if (ret)
|
||||
goto err_ret;
|
||||
|
||||
ret = sscanf(indio_dev->name, "adis%u\n", &device_id);
|
||||
if (ret != 1) {
|
||||
if (sscanf(indio_dev->name, "adis%u\n", &device_id) != 1) {
|
||||
ret = -EINVAL;
|
||||
goto err_ret;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -23,6 +23,9 @@ struct prox_state {
|
|||
struct hid_sensor_common common_attributes;
|
||||
struct hid_sensor_hub_attribute_info prox_attr;
|
||||
u32 human_presence;
|
||||
int scale_pre_decml;
|
||||
int scale_post_decml;
|
||||
int scale_precision;
|
||||
};
|
||||
|
||||
/* Channel definitions */
|
||||
|
|
@ -93,8 +96,9 @@ static int prox_read_raw(struct iio_dev *indio_dev,
|
|||
ret_type = IIO_VAL_INT;
|
||||
break;
|
||||
case IIO_CHAN_INFO_SCALE:
|
||||
*val = prox_state->prox_attr.units;
|
||||
ret_type = IIO_VAL_INT;
|
||||
*val = prox_state->scale_pre_decml;
|
||||
*val2 = prox_state->scale_post_decml;
|
||||
ret_type = prox_state->scale_precision;
|
||||
break;
|
||||
case IIO_CHAN_INFO_OFFSET:
|
||||
*val = hid_sensor_convert_exponent(
|
||||
|
|
@ -234,6 +238,11 @@ static int prox_parse_report(struct platform_device *pdev,
|
|||
HID_USAGE_SENSOR_HUMAN_PRESENCE,
|
||||
&st->common_attributes.sensitivity);
|
||||
|
||||
st->scale_precision = hid_sensor_format_scale(
|
||||
hsdev->usage,
|
||||
&st->prox_attr,
|
||||
&st->scale_pre_decml, &st->scale_post_decml);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -15,7 +15,10 @@
|
|||
struct temperature_state {
|
||||
struct hid_sensor_common common_attributes;
|
||||
struct hid_sensor_hub_attribute_info temperature_attr;
|
||||
s32 temperature_data;
|
||||
struct {
|
||||
s32 temperature_data;
|
||||
u64 timestamp __aligned(8);
|
||||
} scan;
|
||||
int scale_pre_decml;
|
||||
int scale_post_decml;
|
||||
int scale_precision;
|
||||
|
|
@ -32,7 +35,7 @@ static const struct iio_chan_spec temperature_channels[] = {
|
|||
BIT(IIO_CHAN_INFO_SAMP_FREQ) |
|
||||
BIT(IIO_CHAN_INFO_HYSTERESIS),
|
||||
},
|
||||
IIO_CHAN_SOFT_TIMESTAMP(3),
|
||||
IIO_CHAN_SOFT_TIMESTAMP(1),
|
||||
};
|
||||
|
||||
/* Adjust channel real bits based on report descriptor */
|
||||
|
|
@ -123,9 +126,8 @@ static int temperature_proc_event(struct hid_sensor_hub_device *hsdev,
|
|||
struct temperature_state *temp_st = iio_priv(indio_dev);
|
||||
|
||||
if (atomic_read(&temp_st->common_attributes.data_ready))
|
||||
iio_push_to_buffers_with_timestamp(indio_dev,
|
||||
&temp_st->temperature_data,
|
||||
iio_get_time_ns(indio_dev));
|
||||
iio_push_to_buffers_with_timestamp(indio_dev, &temp_st->scan,
|
||||
iio_get_time_ns(indio_dev));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -140,7 +142,7 @@ static int temperature_capture_sample(struct hid_sensor_hub_device *hsdev,
|
|||
|
||||
switch (usage_id) {
|
||||
case HID_USAGE_SENSOR_DATA_ENVIRONMENTAL_TEMPERATURE:
|
||||
temp_st->temperature_data = *(s32 *)raw_data;
|
||||
temp_st->scan.temperature_data = *(s32 *)raw_data;
|
||||
return 0;
|
||||
default:
|
||||
return -EINVAL;
|
||||
|
|
|
|||
|
|
@ -34,12 +34,11 @@ static ssize_t add_slot_store(struct kobject *kobj, struct kobj_attribute *attr,
|
|||
if (nbytes >= MAX_DRC_NAME_LEN)
|
||||
return 0;
|
||||
|
||||
memcpy(drc_name, buf, nbytes);
|
||||
strscpy(drc_name, buf, nbytes + 1);
|
||||
|
||||
end = strchr(drc_name, '\n');
|
||||
if (!end)
|
||||
end = &drc_name[nbytes];
|
||||
*end = '\0';
|
||||
if (end)
|
||||
*end = '\0';
|
||||
|
||||
rc = dlpar_add_slot(drc_name);
|
||||
if (rc)
|
||||
|
|
@ -65,12 +64,11 @@ static ssize_t remove_slot_store(struct kobject *kobj,
|
|||
if (nbytes >= MAX_DRC_NAME_LEN)
|
||||
return 0;
|
||||
|
||||
memcpy(drc_name, buf, nbytes);
|
||||
strscpy(drc_name, buf, nbytes + 1);
|
||||
|
||||
end = strchr(drc_name, '\n');
|
||||
if (!end)
|
||||
end = &drc_name[nbytes];
|
||||
*end = '\0';
|
||||
if (end)
|
||||
*end = '\0';
|
||||
|
||||
rc = dlpar_remove_slot(drc_name);
|
||||
if (rc)
|
||||
|
|
|
|||
|
|
@ -1281,7 +1281,7 @@ static int cb_pcidas_auto_attach(struct comedi_device *dev,
|
|||
devpriv->amcc + AMCC_OP_REG_INTCSR);
|
||||
|
||||
ret = request_irq(pcidev->irq, cb_pcidas_interrupt, IRQF_SHARED,
|
||||
dev->board_name, dev);
|
||||
"cb_pcidas", dev);
|
||||
if (ret) {
|
||||
dev_dbg(dev->class_dev, "unable to allocate irq %d\n",
|
||||
pcidev->irq);
|
||||
|
|
|
|||
|
|
@ -4035,7 +4035,7 @@ static int auto_attach(struct comedi_device *dev,
|
|||
init_stc_registers(dev);
|
||||
|
||||
retval = request_irq(pcidev->irq, handle_interrupt, IRQF_SHARED,
|
||||
dev->board_name, dev);
|
||||
"cb_pcidas64", dev);
|
||||
if (retval) {
|
||||
dev_dbg(dev->class_dev, "unable to allocate irq %u\n",
|
||||
pcidev->irq);
|
||||
|
|
|
|||
|
|
@ -150,7 +150,7 @@ struct vnt_cts {
|
|||
u16 reserved;
|
||||
struct ieee80211_cts data;
|
||||
u16 reserved2;
|
||||
} __packed;
|
||||
} __packed __aligned(2);
|
||||
|
||||
struct vnt_cts_fb {
|
||||
struct vnt_phy_field b;
|
||||
|
|
@ -160,7 +160,7 @@ struct vnt_cts_fb {
|
|||
__le16 cts_duration_ba_f1;
|
||||
struct ieee80211_cts data;
|
||||
u16 reserved2;
|
||||
} __packed;
|
||||
} __packed __aligned(2);
|
||||
|
||||
struct vnt_tx_fifo_head {
|
||||
u8 tx_key[WLAN_KEY_LEN_CCMP];
|
||||
|
|
|
|||
|
|
@ -768,12 +768,6 @@ static int tb_init_port(struct tb_port *port)
|
|||
|
||||
tb_dump_port(port->sw->tb, &port->config);
|
||||
|
||||
/* Control port does not need HopID allocation */
|
||||
if (port->port) {
|
||||
ida_init(&port->in_hopids);
|
||||
ida_init(&port->out_hopids);
|
||||
}
|
||||
|
||||
INIT_LIST_HEAD(&port->list);
|
||||
return 0;
|
||||
|
||||
|
|
@ -1842,10 +1836,8 @@ static void tb_switch_release(struct device *dev)
|
|||
dma_port_free(sw->dma_port);
|
||||
|
||||
tb_switch_for_each_port(sw, port) {
|
||||
if (!port->disabled) {
|
||||
ida_destroy(&port->in_hopids);
|
||||
ida_destroy(&port->out_hopids);
|
||||
}
|
||||
ida_destroy(&port->in_hopids);
|
||||
ida_destroy(&port->out_hopids);
|
||||
}
|
||||
|
||||
kfree(sw->uuid);
|
||||
|
|
@ -2025,6 +2017,12 @@ struct tb_switch *tb_switch_alloc(struct tb *tb, struct device *parent,
|
|||
/* minimum setup for tb_find_cap and tb_drom_read to work */
|
||||
sw->ports[i].sw = sw;
|
||||
sw->ports[i].port = i;
|
||||
|
||||
/* Control port does not need HopID allocation */
|
||||
if (i) {
|
||||
ida_init(&sw->ports[i].in_hopids);
|
||||
ida_init(&sw->ports[i].out_hopids);
|
||||
}
|
||||
}
|
||||
|
||||
ret = tb_switch_find_vse_cap(sw, TB_VSE_CAP_PLUG_EVENTS);
|
||||
|
|
|
|||
|
|
@ -138,6 +138,10 @@ static void tb_discover_tunnels(struct tb_switch *sw)
|
|||
parent->boot = true;
|
||||
parent = tb_switch_parent(parent);
|
||||
}
|
||||
} else if (tb_tunnel_is_dp(tunnel)) {
|
||||
/* Keep the domain from powering down */
|
||||
pm_runtime_get_sync(&tunnel->src_port->sw->dev);
|
||||
pm_runtime_get_sync(&tunnel->dst_port->sw->dev);
|
||||
}
|
||||
|
||||
list_add_tail(&tunnel->list, &tcm->tunnel_list);
|
||||
|
|
|
|||
|
|
@ -2197,7 +2197,10 @@ static int cdnsp_queue_isoc_tx(struct cdnsp_device *pdev,
|
|||
* inverted in the first TDs isoc TRB.
|
||||
*/
|
||||
field = TRB_TYPE(TRB_ISOC) | TRB_TLBPC(last_burst_pkt) |
|
||||
start_cycle ? 0 : 1 | TRB_SIA | TRB_TBC(burst_count);
|
||||
TRB_SIA | TRB_TBC(burst_count);
|
||||
|
||||
if (!start_cycle)
|
||||
field |= TRB_CYCLE;
|
||||
|
||||
/* Fill the rest of the TRB fields, and remaining normal TRBs. */
|
||||
for (i = 0; i < trbs_per_td; i++) {
|
||||
|
|
|
|||
|
|
@ -783,8 +783,6 @@ static int __dwc3_gadget_ep_disable(struct dwc3_ep *dep)
|
|||
|
||||
trace_dwc3_gadget_ep_disable(dep);
|
||||
|
||||
dwc3_remove_requests(dwc, dep);
|
||||
|
||||
/* make sure HW endpoint isn't stalled */
|
||||
if (dep->flags & DWC3_EP_STALL)
|
||||
__dwc3_gadget_ep_set_halt(dep, 0, false);
|
||||
|
|
@ -803,6 +801,8 @@ static int __dwc3_gadget_ep_disable(struct dwc3_ep *dep)
|
|||
dep->endpoint.desc = NULL;
|
||||
}
|
||||
|
||||
dwc3_remove_requests(dwc, dep);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -1617,7 +1617,7 @@ static int __dwc3_gadget_ep_queue(struct dwc3_ep *dep, struct dwc3_request *req)
|
|||
{
|
||||
struct dwc3 *dwc = dep->dwc;
|
||||
|
||||
if (!dep->endpoint.desc || !dwc->pullups_connected) {
|
||||
if (!dep->endpoint.desc || !dwc->pullups_connected || !dwc->connected) {
|
||||
dev_err(dwc->dev, "%s: can't queue to disabled endpoint\n",
|
||||
dep->name);
|
||||
return -ESHUTDOWN;
|
||||
|
|
@ -2247,6 +2247,7 @@ static int dwc3_gadget_pullup(struct usb_gadget *g, int is_on)
|
|||
if (!is_on) {
|
||||
u32 count;
|
||||
|
||||
dwc->connected = false;
|
||||
/*
|
||||
* In the Synopsis DesignWare Cores USB3 Databook Rev. 3.30a
|
||||
* Section 4.1.8 Table 4-7, it states that for a device-initiated
|
||||
|
|
@ -2271,7 +2272,6 @@ static int dwc3_gadget_pullup(struct usb_gadget *g, int is_on)
|
|||
dwc->ev_buf->lpos = (dwc->ev_buf->lpos + count) %
|
||||
dwc->ev_buf->length;
|
||||
}
|
||||
dwc->connected = false;
|
||||
} else {
|
||||
__dwc3_gadget_start(dwc);
|
||||
}
|
||||
|
|
@ -3321,8 +3321,6 @@ static void dwc3_gadget_reset_interrupt(struct dwc3 *dwc)
|
|||
{
|
||||
u32 reg;
|
||||
|
||||
dwc->connected = true;
|
||||
|
||||
/*
|
||||
* WORKAROUND: DWC3 revisions <1.88a have an issue which
|
||||
* would cause a missing Disconnect Event if there's a
|
||||
|
|
@ -3362,6 +3360,7 @@ static void dwc3_gadget_reset_interrupt(struct dwc3 *dwc)
|
|||
* transfers."
|
||||
*/
|
||||
dwc3_stop_active_transfers(dwc);
|
||||
dwc->connected = true;
|
||||
|
||||
reg = dwc3_readl(dwc->regs, DWC3_DCTL);
|
||||
reg &= ~DWC3_DCTL_TSTCTRL_MASK;
|
||||
|
|
|
|||
|
|
@ -129,6 +129,8 @@ struct gadget_config_name {
|
|||
struct list_head list;
|
||||
};
|
||||
|
||||
#define USB_MAX_STRING_WITH_NULL_LEN (USB_MAX_STRING_LEN+1)
|
||||
|
||||
static int usb_string_copy(const char *s, char **s_copy)
|
||||
{
|
||||
int ret;
|
||||
|
|
@ -138,12 +140,16 @@ static int usb_string_copy(const char *s, char **s_copy)
|
|||
if (ret > USB_MAX_STRING_LEN)
|
||||
return -EOVERFLOW;
|
||||
|
||||
str = kstrdup(s, GFP_KERNEL);
|
||||
if (!str)
|
||||
return -ENOMEM;
|
||||
if (copy) {
|
||||
str = copy;
|
||||
} else {
|
||||
str = kmalloc(USB_MAX_STRING_WITH_NULL_LEN, GFP_KERNEL);
|
||||
if (!str)
|
||||
return -ENOMEM;
|
||||
}
|
||||
strcpy(str, s);
|
||||
if (str[ret - 1] == '\n')
|
||||
str[ret - 1] = '\0';
|
||||
kfree(copy);
|
||||
*s_copy = str;
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -656,6 +656,13 @@ void usb_stor_invoke_transport(struct scsi_cmnd *srb, struct us_data *us)
|
|||
need_auto_sense = 1;
|
||||
}
|
||||
|
||||
/* Some devices (Kindle) require another command after SYNC CACHE */
|
||||
if ((us->fflags & US_FL_SENSE_AFTER_SYNC) &&
|
||||
srb->cmnd[0] == SYNCHRONIZE_CACHE) {
|
||||
usb_stor_dbg(us, "-- sense after SYNC CACHE\n");
|
||||
need_auto_sense = 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* If we have a failure, we're going to do a REQUEST_SENSE
|
||||
* automatically. Note that we differentiate between a command
|
||||
|
|
|
|||
|
|
@ -2211,6 +2211,18 @@ UNUSUAL_DEV( 0x1908, 0x3335, 0x0200, 0x0200,
|
|||
USB_SC_DEVICE, USB_PR_DEVICE, NULL,
|
||||
US_FL_NO_READ_DISC_INFO ),
|
||||
|
||||
/*
|
||||
* Reported by Matthias Schwarzott <zzam@gentoo.org>
|
||||
* The Amazon Kindle treats SYNCHRONIZE CACHE as an indication that
|
||||
* the host may be finished with it, and automatically ejects its
|
||||
* emulated media unless it receives another command within one second.
|
||||
*/
|
||||
UNUSUAL_DEV( 0x1949, 0x0004, 0x0000, 0x9999,
|
||||
"Amazon",
|
||||
"Kindle",
|
||||
USB_SC_DEVICE, USB_PR_DEVICE, NULL,
|
||||
US_FL_SENSE_AFTER_SYNC ),
|
||||
|
||||
/*
|
||||
* Reported by Oliver Neukum <oneukum@suse.com>
|
||||
* This device morphes spontaneously into another device if the access
|
||||
|
|
|
|||
|
|
@ -960,6 +960,7 @@ static int tcpm_set_current_limit(struct tcpm_port *port, u32 max_ma, u32 mv)
|
|||
|
||||
port->supply_voltage = mv;
|
||||
port->current_limit = max_ma;
|
||||
power_supply_changed(port->psy);
|
||||
|
||||
if (port->tcpc->set_current_limit)
|
||||
ret = port->tcpc->set_current_limit(port->tcpc, max_ma, mv);
|
||||
|
|
@ -2946,6 +2947,7 @@ static int tcpm_pd_select_pdo(struct tcpm_port *port, int *sink_pdo,
|
|||
|
||||
port->pps_data.supported = false;
|
||||
port->usb_type = POWER_SUPPLY_USB_TYPE_PD;
|
||||
power_supply_changed(port->psy);
|
||||
|
||||
/*
|
||||
* Select the source PDO providing the most power which has a
|
||||
|
|
@ -2970,6 +2972,7 @@ static int tcpm_pd_select_pdo(struct tcpm_port *port, int *sink_pdo,
|
|||
port->pps_data.supported = true;
|
||||
port->usb_type =
|
||||
POWER_SUPPLY_USB_TYPE_PD_PPS;
|
||||
power_supply_changed(port->psy);
|
||||
}
|
||||
continue;
|
||||
default:
|
||||
|
|
@ -3127,6 +3130,7 @@ static unsigned int tcpm_pd_select_pps_apdo(struct tcpm_port *port)
|
|||
port->pps_data.out_volt));
|
||||
port->pps_data.op_curr = min(port->pps_data.max_curr,
|
||||
port->pps_data.op_curr);
|
||||
power_supply_changed(port->psy);
|
||||
}
|
||||
|
||||
return src_pdo;
|
||||
|
|
@ -3362,6 +3366,7 @@ static int tcpm_set_charge(struct tcpm_port *port, bool charge)
|
|||
return ret;
|
||||
}
|
||||
port->vbus_charge = charge;
|
||||
power_supply_changed(port->psy);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -3542,6 +3547,7 @@ static void tcpm_reset_port(struct tcpm_port *port)
|
|||
port->try_src_count = 0;
|
||||
port->try_snk_count = 0;
|
||||
port->usb_type = POWER_SUPPLY_USB_TYPE_C;
|
||||
power_supply_changed(port->psy);
|
||||
port->nr_sink_caps = 0;
|
||||
port->sink_cap_done = false;
|
||||
if (port->tcpc->enable_frs)
|
||||
|
|
@ -5213,7 +5219,7 @@ static void tcpm_enable_frs_work(struct kthread_work *work)
|
|||
goto unlock;
|
||||
|
||||
/* Send when the state machine is idle */
|
||||
if (port->state != SNK_READY || port->vdm_state != VDM_STATE_DONE || port->send_discover)
|
||||
if (port->state != SNK_READY || port->vdm_sm_running || port->send_discover)
|
||||
goto resched;
|
||||
|
||||
port->upcoming_state = GET_SINK_CAP;
|
||||
|
|
@ -5994,7 +6000,7 @@ static int tcpm_psy_set_prop(struct power_supply *psy,
|
|||
ret = -EINVAL;
|
||||
break;
|
||||
}
|
||||
|
||||
power_supply_changed(port->psy);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
@ -6147,6 +6153,7 @@ struct tcpm_port *tcpm_register_port(struct device *dev, struct tcpc_dev *tcpc)
|
|||
err = devm_tcpm_psy_register(port);
|
||||
if (err)
|
||||
goto out_role_sw_put;
|
||||
power_supply_changed(port->psy);
|
||||
|
||||
port->typec_port = typec_register_port(port->dev, &port->typec_caps);
|
||||
if (IS_ERR(port->typec_port)) {
|
||||
|
|
|
|||
|
|
@ -64,7 +64,6 @@ enum {
|
|||
struct tps6598x_rx_identity_reg {
|
||||
u8 status;
|
||||
struct usb_pd_identity identity;
|
||||
u32 vdo[3];
|
||||
} __packed;
|
||||
|
||||
/* Standard Task return codes */
|
||||
|
|
|
|||
|
|
@ -174,7 +174,7 @@ static ssize_t usbip_sockfd_store(struct device *dev,
|
|||
|
||||
udc->ud.tcp_socket = socket;
|
||||
udc->ud.tcp_rx = tcp_rx;
|
||||
udc->ud.tcp_rx = tcp_tx;
|
||||
udc->ud.tcp_tx = tcp_tx;
|
||||
udc->ud.status = SDEV_ST_USED;
|
||||
|
||||
spin_unlock_irq(&udc->ud.lock);
|
||||
|
|
|
|||
|
|
@ -626,27 +626,41 @@ int ext4_claim_free_clusters(struct ext4_sb_info *sbi,
|
|||
|
||||
/**
|
||||
* ext4_should_retry_alloc() - check if a block allocation should be retried
|
||||
* @sb: super block
|
||||
* @retries: number of attemps has been made
|
||||
* @sb: superblock
|
||||
* @retries: number of retry attempts made so far
|
||||
*
|
||||
* ext4_should_retry_alloc() is called when ENOSPC is returned, and if
|
||||
* it is profitable to retry the operation, this function will wait
|
||||
* for the current or committing transaction to complete, and then
|
||||
* return TRUE. We will only retry once.
|
||||
* ext4_should_retry_alloc() is called when ENOSPC is returned while
|
||||
* attempting to allocate blocks. If there's an indication that a pending
|
||||
* journal transaction might free some space and allow another attempt to
|
||||
* succeed, this function will wait for the current or committing transaction
|
||||
* to complete and then return TRUE.
|
||||
*/
|
||||
int ext4_should_retry_alloc(struct super_block *sb, int *retries)
|
||||
{
|
||||
if (!ext4_has_free_clusters(EXT4_SB(sb), 1, 0) ||
|
||||
(*retries)++ > 1 ||
|
||||
!EXT4_SB(sb)->s_journal)
|
||||
struct ext4_sb_info *sbi = EXT4_SB(sb);
|
||||
|
||||
if (!sbi->s_journal)
|
||||
return 0;
|
||||
|
||||
if (++(*retries) > 3) {
|
||||
percpu_counter_inc(&sbi->s_sra_exceeded_retry_limit);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* if there's no indication that blocks are about to be freed it's
|
||||
* possible we just missed a transaction commit that did so
|
||||
*/
|
||||
smp_mb();
|
||||
if (EXT4_SB(sb)->s_mb_free_pending == 0)
|
||||
return 0;
|
||||
if (sbi->s_mb_free_pending == 0)
|
||||
return ext4_has_free_clusters(sbi, 1, 0);
|
||||
|
||||
/*
|
||||
* it's possible we've just missed a transaction commit here,
|
||||
* so ignore the returned status
|
||||
*/
|
||||
jbd_debug(1, "%s: retrying operation after ENOSPC\n", sb->s_id);
|
||||
jbd2_journal_force_commit_nested(EXT4_SB(sb)->s_journal);
|
||||
(void) jbd2_journal_force_commit_nested(sbi->s_journal);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1484,6 +1484,7 @@ struct ext4_sb_info {
|
|||
struct percpu_counter s_freeinodes_counter;
|
||||
struct percpu_counter s_dirs_counter;
|
||||
struct percpu_counter s_dirtyclusters_counter;
|
||||
struct percpu_counter s_sra_exceeded_retry_limit;
|
||||
struct blockgroup_lock *s_blockgroup_lock;
|
||||
struct proc_dir_entry *s_proc;
|
||||
struct kobject s_kobj;
|
||||
|
|
@ -2838,6 +2839,8 @@ void __ext4_fc_track_link(handle_t *handle, struct inode *inode,
|
|||
struct dentry *dentry);
|
||||
void ext4_fc_track_unlink(handle_t *handle, struct dentry *dentry);
|
||||
void ext4_fc_track_link(handle_t *handle, struct dentry *dentry);
|
||||
void __ext4_fc_track_create(handle_t *handle, struct inode *inode,
|
||||
struct dentry *dentry);
|
||||
void ext4_fc_track_create(handle_t *handle, struct dentry *dentry);
|
||||
void ext4_fc_track_inode(handle_t *handle, struct inode *inode);
|
||||
void ext4_fc_mark_ineligible(struct super_block *sb, int reason);
|
||||
|
|
|
|||
|
|
@ -4382,7 +4382,7 @@ static int ext4_alloc_file_blocks(struct file *file, ext4_lblk_t offset,
|
|||
{
|
||||
struct inode *inode = file_inode(file);
|
||||
handle_t *handle;
|
||||
int ret, ret2 = 0, ret3 = 0;
|
||||
int ret = 0, ret2 = 0, ret3 = 0;
|
||||
int retries = 0;
|
||||
int depth = 0;
|
||||
struct ext4_map_blocks map;
|
||||
|
|
|
|||
|
|
@ -513,10 +513,10 @@ void ext4_fc_track_link(handle_t *handle, struct dentry *dentry)
|
|||
__ext4_fc_track_link(handle, d_inode(dentry), dentry);
|
||||
}
|
||||
|
||||
void ext4_fc_track_create(handle_t *handle, struct dentry *dentry)
|
||||
void __ext4_fc_track_create(handle_t *handle, struct inode *inode,
|
||||
struct dentry *dentry)
|
||||
{
|
||||
struct __track_dentry_update_args args;
|
||||
struct inode *inode = d_inode(dentry);
|
||||
int ret;
|
||||
|
||||
args.dentry = dentry;
|
||||
|
|
@ -527,6 +527,11 @@ void ext4_fc_track_create(handle_t *handle, struct dentry *dentry)
|
|||
trace_ext4_fc_track_create(inode, dentry, ret);
|
||||
}
|
||||
|
||||
void ext4_fc_track_create(handle_t *handle, struct dentry *dentry)
|
||||
{
|
||||
__ext4_fc_track_create(handle, d_inode(dentry), dentry);
|
||||
}
|
||||
|
||||
/* __track_fn for inode tracking */
|
||||
static int __track_inode(struct inode *inode, void *arg, bool update)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -1951,13 +1951,13 @@ static int __ext4_journalled_writepage(struct page *page,
|
|||
if (!ret)
|
||||
ret = err;
|
||||
|
||||
if (!ext4_has_inline_data(inode))
|
||||
ext4_walk_page_buffers(NULL, page_bufs, 0, len,
|
||||
NULL, bput_one);
|
||||
ext4_set_inode_state(inode, EXT4_STATE_JDATA);
|
||||
out:
|
||||
unlock_page(page);
|
||||
out_no_pagelock:
|
||||
if (!inline_data && page_bufs)
|
||||
ext4_walk_page_buffers(NULL, page_bufs, 0, len,
|
||||
NULL, bput_one);
|
||||
brelse(inode_bh);
|
||||
return ret;
|
||||
}
|
||||
|
|
@ -5058,7 +5058,7 @@ static int ext4_do_update_inode(handle_t *handle,
|
|||
struct ext4_inode_info *ei = EXT4_I(inode);
|
||||
struct buffer_head *bh = iloc->bh;
|
||||
struct super_block *sb = inode->i_sb;
|
||||
int err = 0, rc, block;
|
||||
int err = 0, block;
|
||||
int need_datasync = 0, set_large_file = 0;
|
||||
uid_t i_uid;
|
||||
gid_t i_gid;
|
||||
|
|
@ -5170,9 +5170,9 @@ static int ext4_do_update_inode(handle_t *handle,
|
|||
bh->b_data);
|
||||
|
||||
BUFFER_TRACE(bh, "call ext4_handle_dirty_metadata");
|
||||
rc = ext4_handle_dirty_metadata(handle, NULL, bh);
|
||||
if (!err)
|
||||
err = rc;
|
||||
err = ext4_handle_dirty_metadata(handle, NULL, bh);
|
||||
if (err)
|
||||
goto out_brelse;
|
||||
ext4_clear_inode_state(inode, EXT4_STATE_NEW);
|
||||
if (set_large_file) {
|
||||
BUFFER_TRACE(EXT4_SB(sb)->s_sbh, "get write access");
|
||||
|
|
@ -5419,8 +5419,10 @@ int ext4_setattr(struct user_namespace *mnt_userns, struct dentry *dentry,
|
|||
inode->i_gid = attr->ia_gid;
|
||||
error = ext4_mark_inode_dirty(handle, inode);
|
||||
ext4_journal_stop(handle);
|
||||
if (unlikely(error))
|
||||
if (unlikely(error)) {
|
||||
ext4_fc_stop_update(inode);
|
||||
return error;
|
||||
}
|
||||
}
|
||||
|
||||
if (attr->ia_valid & ATTR_SIZE) {
|
||||
|
|
|
|||
|
|
@ -2709,8 +2709,15 @@ static int ext4_mb_init_backend(struct super_block *sb)
|
|||
}
|
||||
|
||||
if (ext4_has_feature_flex_bg(sb)) {
|
||||
/* a single flex group is supposed to be read by a single IO */
|
||||
sbi->s_mb_prefetch = min(1 << sbi->s_es->s_log_groups_per_flex,
|
||||
/* a single flex group is supposed to be read by a single IO.
|
||||
* 2 ^ s_log_groups_per_flex != UINT_MAX as s_mb_prefetch is
|
||||
* unsigned integer, so the maximum shift is 32.
|
||||
*/
|
||||
if (sbi->s_es->s_log_groups_per_flex >= 32) {
|
||||
ext4_msg(sb, KERN_ERR, "too many log groups per flexible block group");
|
||||
goto err_freesgi;
|
||||
}
|
||||
sbi->s_mb_prefetch = min_t(uint, 1 << sbi->s_es->s_log_groups_per_flex,
|
||||
BLK_MAX_SEGMENT_SIZE >> (sb->s_blocksize_bits - 9));
|
||||
sbi->s_mb_prefetch *= 8; /* 8 prefetch IOs in flight at most */
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -3729,6 +3729,31 @@ static int ext4_setent(handle_t *handle, struct ext4_renament *ent,
|
|||
return retval;
|
||||
}
|
||||
|
||||
static void ext4_resetent(handle_t *handle, struct ext4_renament *ent,
|
||||
unsigned ino, unsigned file_type)
|
||||
{
|
||||
struct ext4_renament old = *ent;
|
||||
int retval = 0;
|
||||
|
||||
/*
|
||||
* old->de could have moved from under us during make indexed dir,
|
||||
* so the old->de may no longer valid and need to find it again
|
||||
* before reset old inode info.
|
||||
*/
|
||||
old.bh = ext4_find_entry(old.dir, &old.dentry->d_name, &old.de, NULL);
|
||||
if (IS_ERR(old.bh))
|
||||
retval = PTR_ERR(old.bh);
|
||||
if (!old.bh)
|
||||
retval = -ENOENT;
|
||||
if (retval) {
|
||||
ext4_std_error(old.dir->i_sb, retval);
|
||||
return;
|
||||
}
|
||||
|
||||
ext4_setent(handle, &old, ino, file_type);
|
||||
brelse(old.bh);
|
||||
}
|
||||
|
||||
static int ext4_find_delete_entry(handle_t *handle, struct inode *dir,
|
||||
const struct qstr *d_name)
|
||||
{
|
||||
|
|
@ -3893,14 +3918,14 @@ static int ext4_rename(struct user_namespace *mnt_userns, struct inode *old_dir,
|
|||
*/
|
||||
retval = -ENOENT;
|
||||
if (!old.bh || le32_to_cpu(old.de->inode) != old.inode->i_ino)
|
||||
goto end_rename;
|
||||
goto release_bh;
|
||||
|
||||
new.bh = ext4_find_entry(new.dir, &new.dentry->d_name,
|
||||
&new.de, &new.inlined, NULL);
|
||||
if (IS_ERR(new.bh)) {
|
||||
retval = PTR_ERR(new.bh);
|
||||
new.bh = NULL;
|
||||
goto end_rename;
|
||||
goto release_bh;
|
||||
}
|
||||
if (new.bh) {
|
||||
if (!new.inode) {
|
||||
|
|
@ -3917,15 +3942,13 @@ static int ext4_rename(struct user_namespace *mnt_userns, struct inode *old_dir,
|
|||
handle = ext4_journal_start(old.dir, EXT4_HT_DIR, credits);
|
||||
if (IS_ERR(handle)) {
|
||||
retval = PTR_ERR(handle);
|
||||
handle = NULL;
|
||||
goto end_rename;
|
||||
goto release_bh;
|
||||
}
|
||||
} else {
|
||||
whiteout = ext4_whiteout_for_rename(mnt_userns, &old, credits, &handle);
|
||||
if (IS_ERR(whiteout)) {
|
||||
retval = PTR_ERR(whiteout);
|
||||
whiteout = NULL;
|
||||
goto end_rename;
|
||||
goto release_bh;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -3969,6 +3992,7 @@ static int ext4_rename(struct user_namespace *mnt_userns, struct inode *old_dir,
|
|||
retval = ext4_mark_inode_dirty(handle, whiteout);
|
||||
if (unlikely(retval))
|
||||
goto end_rename;
|
||||
|
||||
}
|
||||
if (!new.bh) {
|
||||
retval = ext4_add_entry(handle, new.dentry, old.inode);
|
||||
|
|
@ -4042,6 +4066,8 @@ static int ext4_rename(struct user_namespace *mnt_userns, struct inode *old_dir,
|
|||
ext4_fc_track_unlink(handle, new.dentry);
|
||||
__ext4_fc_track_link(handle, old.inode, new.dentry);
|
||||
__ext4_fc_track_unlink(handle, old.inode, old.dentry);
|
||||
if (whiteout)
|
||||
__ext4_fc_track_create(handle, whiteout, old.dentry);
|
||||
}
|
||||
|
||||
if (new.inode) {
|
||||
|
|
@ -4056,19 +4082,21 @@ static int ext4_rename(struct user_namespace *mnt_userns, struct inode *old_dir,
|
|||
end_rename:
|
||||
if (whiteout) {
|
||||
if (retval) {
|
||||
ext4_setent(handle, &old,
|
||||
old.inode->i_ino, old_file_type);
|
||||
ext4_resetent(handle, &old,
|
||||
old.inode->i_ino, old_file_type);
|
||||
drop_nlink(whiteout);
|
||||
ext4_orphan_add(handle, whiteout);
|
||||
}
|
||||
unlock_new_inode(whiteout);
|
||||
ext4_journal_stop(handle);
|
||||
iput(whiteout);
|
||||
|
||||
} else {
|
||||
ext4_journal_stop(handle);
|
||||
}
|
||||
release_bh:
|
||||
brelse(old.dir_bh);
|
||||
brelse(old.bh);
|
||||
brelse(new.bh);
|
||||
if (handle)
|
||||
ext4_journal_stop(handle);
|
||||
return retval;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1210,6 +1210,7 @@ static void ext4_put_super(struct super_block *sb)
|
|||
percpu_counter_destroy(&sbi->s_freeinodes_counter);
|
||||
percpu_counter_destroy(&sbi->s_dirs_counter);
|
||||
percpu_counter_destroy(&sbi->s_dirtyclusters_counter);
|
||||
percpu_counter_destroy(&sbi->s_sra_exceeded_retry_limit);
|
||||
percpu_free_rwsem(&sbi->s_writepages_rwsem);
|
||||
#ifdef CONFIG_QUOTA
|
||||
for (i = 0; i < EXT4_MAXQUOTAS; i++)
|
||||
|
|
@ -5005,6 +5006,9 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
|
|||
if (!err)
|
||||
err = percpu_counter_init(&sbi->s_dirtyclusters_counter, 0,
|
||||
GFP_KERNEL);
|
||||
if (!err)
|
||||
err = percpu_counter_init(&sbi->s_sra_exceeded_retry_limit, 0,
|
||||
GFP_KERNEL);
|
||||
if (!err)
|
||||
err = percpu_init_rwsem(&sbi->s_writepages_rwsem);
|
||||
|
||||
|
|
@ -5118,6 +5122,7 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
|
|||
percpu_counter_destroy(&sbi->s_freeinodes_counter);
|
||||
percpu_counter_destroy(&sbi->s_dirs_counter);
|
||||
percpu_counter_destroy(&sbi->s_dirtyclusters_counter);
|
||||
percpu_counter_destroy(&sbi->s_sra_exceeded_retry_limit);
|
||||
percpu_free_rwsem(&sbi->s_writepages_rwsem);
|
||||
failed_mount5:
|
||||
ext4_ext_release(sb);
|
||||
|
|
@ -5143,8 +5148,8 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
|
|||
failed_mount3a:
|
||||
ext4_es_unregister_shrinker(sbi);
|
||||
failed_mount3:
|
||||
del_timer_sync(&sbi->s_err_report);
|
||||
flush_work(&sbi->s_error_work);
|
||||
del_timer_sync(&sbi->s_err_report);
|
||||
if (sbi->s_mmp_tsk)
|
||||
kthread_stop(sbi->s_mmp_tsk);
|
||||
failed_mount2:
|
||||
|
|
|
|||
|
|
@ -24,6 +24,7 @@ typedef enum {
|
|||
attr_session_write_kbytes,
|
||||
attr_lifetime_write_kbytes,
|
||||
attr_reserved_clusters,
|
||||
attr_sra_exceeded_retry_limit,
|
||||
attr_inode_readahead,
|
||||
attr_trigger_test_error,
|
||||
attr_first_error_time,
|
||||
|
|
@ -202,6 +203,7 @@ EXT4_ATTR_FUNC(delayed_allocation_blocks, 0444);
|
|||
EXT4_ATTR_FUNC(session_write_kbytes, 0444);
|
||||
EXT4_ATTR_FUNC(lifetime_write_kbytes, 0444);
|
||||
EXT4_ATTR_FUNC(reserved_clusters, 0644);
|
||||
EXT4_ATTR_FUNC(sra_exceeded_retry_limit, 0444);
|
||||
|
||||
EXT4_ATTR_OFFSET(inode_readahead_blks, 0644, inode_readahead,
|
||||
ext4_sb_info, s_inode_readahead_blks);
|
||||
|
|
@ -251,6 +253,7 @@ static struct attribute *ext4_attrs[] = {
|
|||
ATTR_LIST(session_write_kbytes),
|
||||
ATTR_LIST(lifetime_write_kbytes),
|
||||
ATTR_LIST(reserved_clusters),
|
||||
ATTR_LIST(sra_exceeded_retry_limit),
|
||||
ATTR_LIST(inode_readahead_blks),
|
||||
ATTR_LIST(inode_goal),
|
||||
ATTR_LIST(mb_stats),
|
||||
|
|
@ -374,6 +377,10 @@ static ssize_t ext4_attr_show(struct kobject *kobj,
|
|||
return snprintf(buf, PAGE_SIZE, "%llu\n",
|
||||
(unsigned long long)
|
||||
atomic64_read(&sbi->s_resv_clusters));
|
||||
case attr_sra_exceeded_retry_limit:
|
||||
return snprintf(buf, PAGE_SIZE, "%llu\n",
|
||||
(unsigned long long)
|
||||
percpu_counter_sum(&sbi->s_sra_exceeded_retry_limit));
|
||||
case attr_inode_readahead:
|
||||
case attr_pointer_ui:
|
||||
if (!ptr)
|
||||
|
|
|
|||
|
|
@ -201,55 +201,76 @@ static int ext4_end_enable_verity(struct file *filp, const void *desc,
|
|||
struct inode *inode = file_inode(filp);
|
||||
const int credits = 2; /* superblock and inode for ext4_orphan_del() */
|
||||
handle_t *handle;
|
||||
struct ext4_iloc iloc;
|
||||
int err = 0;
|
||||
int err2;
|
||||
|
||||
if (desc != NULL) {
|
||||
/* Succeeded; write the verity descriptor. */
|
||||
err = ext4_write_verity_descriptor(inode, desc, desc_size,
|
||||
merkle_tree_size);
|
||||
|
||||
/* Write all pages before clearing VERITY_IN_PROGRESS. */
|
||||
if (!err)
|
||||
err = filemap_write_and_wait(inode->i_mapping);
|
||||
}
|
||||
|
||||
/* If we failed, truncate anything we wrote past i_size. */
|
||||
if (desc == NULL || err)
|
||||
ext4_truncate(inode);
|
||||
|
||||
/*
|
||||
* We must always clean up by clearing EXT4_STATE_VERITY_IN_PROGRESS and
|
||||
* deleting the inode from the orphan list, even if something failed.
|
||||
* If everything succeeded, we'll also set the verity bit in the same
|
||||
* transaction.
|
||||
* If an error already occurred (which fs/verity/ signals by passing
|
||||
* desc == NULL), then only clean-up is needed.
|
||||
*/
|
||||
if (desc == NULL)
|
||||
goto cleanup;
|
||||
|
||||
ext4_clear_inode_state(inode, EXT4_STATE_VERITY_IN_PROGRESS);
|
||||
/* Append the verity descriptor. */
|
||||
err = ext4_write_verity_descriptor(inode, desc, desc_size,
|
||||
merkle_tree_size);
|
||||
if (err)
|
||||
goto cleanup;
|
||||
|
||||
/*
|
||||
* Write all pages (both data and verity metadata). Note that this must
|
||||
* happen before clearing EXT4_STATE_VERITY_IN_PROGRESS; otherwise pages
|
||||
* beyond i_size won't be written properly. For crash consistency, this
|
||||
* also must happen before the verity inode flag gets persisted.
|
||||
*/
|
||||
err = filemap_write_and_wait(inode->i_mapping);
|
||||
if (err)
|
||||
goto cleanup;
|
||||
|
||||
/*
|
||||
* Finally, set the verity inode flag and remove the inode from the
|
||||
* orphan list (in a single transaction).
|
||||
*/
|
||||
|
||||
handle = ext4_journal_start(inode, EXT4_HT_INODE, credits);
|
||||
if (IS_ERR(handle)) {
|
||||
ext4_orphan_del(NULL, inode);
|
||||
return PTR_ERR(handle);
|
||||
err = PTR_ERR(handle);
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
err2 = ext4_orphan_del(handle, inode);
|
||||
if (err2)
|
||||
goto out_stop;
|
||||
err = ext4_orphan_del(handle, inode);
|
||||
if (err)
|
||||
goto stop_and_cleanup;
|
||||
|
||||
if (desc != NULL && !err) {
|
||||
struct ext4_iloc iloc;
|
||||
err = ext4_reserve_inode_write(handle, inode, &iloc);
|
||||
if (err)
|
||||
goto stop_and_cleanup;
|
||||
|
||||
ext4_set_inode_flag(inode, EXT4_INODE_VERITY);
|
||||
ext4_set_inode_flags(inode, false);
|
||||
err = ext4_mark_iloc_dirty(handle, inode, &iloc);
|
||||
if (err)
|
||||
goto stop_and_cleanup;
|
||||
|
||||
err = ext4_reserve_inode_write(handle, inode, &iloc);
|
||||
if (err)
|
||||
goto out_stop;
|
||||
ext4_set_inode_flag(inode, EXT4_INODE_VERITY);
|
||||
ext4_set_inode_flags(inode, false);
|
||||
err = ext4_mark_iloc_dirty(handle, inode, &iloc);
|
||||
}
|
||||
out_stop:
|
||||
ext4_journal_stop(handle);
|
||||
return err ?: err2;
|
||||
|
||||
ext4_clear_inode_state(inode, EXT4_STATE_VERITY_IN_PROGRESS);
|
||||
return 0;
|
||||
|
||||
stop_and_cleanup:
|
||||
ext4_journal_stop(handle);
|
||||
cleanup:
|
||||
/*
|
||||
* Verity failed to be enabled, so clean up by truncating any verity
|
||||
* metadata that was written beyond i_size (both from cache and from
|
||||
* disk), removing the inode from the orphan list (if it wasn't done
|
||||
* already), and clearing EXT4_STATE_VERITY_IN_PROGRESS.
|
||||
*/
|
||||
truncate_inode_pages(inode->i_mapping, inode->i_size);
|
||||
ext4_truncate(inode);
|
||||
ext4_orphan_del(NULL, inode);
|
||||
ext4_clear_inode_state(inode, EXT4_STATE_VERITY_IN_PROGRESS);
|
||||
return err;
|
||||
}
|
||||
|
||||
static int ext4_get_verity_descriptor_location(struct inode *inode,
|
||||
|
|
|
|||
|
|
@ -1462,6 +1462,9 @@ ext4_xattr_inode_cache_find(struct inode *inode, const void *value,
|
|||
if (!ce)
|
||||
return NULL;
|
||||
|
||||
WARN_ON_ONCE(ext4_handle_valid(journal_current_handle()) &&
|
||||
!(current->flags & PF_MEMALLOC_NOFS));
|
||||
|
||||
ea_data = kvmalloc(value_len, GFP_KERNEL);
|
||||
if (!ea_data) {
|
||||
mb_cache_entry_put(ea_inode_cache, ce);
|
||||
|
|
@ -2327,6 +2330,7 @@ ext4_xattr_set_handle(handle_t *handle, struct inode *inode, int name_index,
|
|||
error = -ENOSPC;
|
||||
goto cleanup;
|
||||
}
|
||||
WARN_ON_ONCE(!(current->flags & PF_MEMALLOC_NOFS));
|
||||
}
|
||||
|
||||
error = ext4_reserve_inode_write(handle, inode, &is.iloc);
|
||||
|
|
@ -2400,7 +2404,7 @@ ext4_xattr_set_handle(handle_t *handle, struct inode *inode, int name_index,
|
|||
* external inode if possible.
|
||||
*/
|
||||
if (ext4_has_feature_ea_inode(inode->i_sb) &&
|
||||
!i.in_inode) {
|
||||
i.value_len && !i.in_inode) {
|
||||
i.in_inode = 1;
|
||||
goto retry_inode;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -386,13 +386,16 @@ static struct io_wq_work *io_get_next_work(struct io_wqe *wqe)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
static void io_flush_signals(void)
|
||||
static bool io_flush_signals(void)
|
||||
{
|
||||
if (unlikely(test_tsk_thread_flag(current, TIF_NOTIFY_SIGNAL))) {
|
||||
__set_current_state(TASK_RUNNING);
|
||||
if (current->task_works)
|
||||
task_work_run();
|
||||
clear_tsk_thread_flag(current, TIF_NOTIFY_SIGNAL);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static void io_assign_current_work(struct io_worker *worker,
|
||||
|
|
@ -499,7 +502,8 @@ static int io_wqe_worker(void *data)
|
|||
}
|
||||
__io_worker_idle(wqe, worker);
|
||||
raw_spin_unlock_irq(&wqe->lock);
|
||||
io_flush_signals();
|
||||
if (io_flush_signals())
|
||||
continue;
|
||||
ret = schedule_timeout(WORKER_IDLE_TIMEOUT);
|
||||
if (try_to_freeze() || ret)
|
||||
continue;
|
||||
|
|
|
|||
|
|
@ -4386,6 +4386,7 @@ static int io_sendmsg(struct io_kiocb *req, unsigned int issue_flags)
|
|||
struct io_async_msghdr iomsg, *kmsg;
|
||||
struct socket *sock;
|
||||
unsigned flags;
|
||||
int min_ret = 0;
|
||||
int ret;
|
||||
|
||||
sock = sock_from_file(req->file);
|
||||
|
|
@ -4406,6 +4407,9 @@ static int io_sendmsg(struct io_kiocb *req, unsigned int issue_flags)
|
|||
else if (issue_flags & IO_URING_F_NONBLOCK)
|
||||
flags |= MSG_DONTWAIT;
|
||||
|
||||
if (flags & MSG_WAITALL)
|
||||
min_ret = iov_iter_count(&kmsg->msg.msg_iter);
|
||||
|
||||
ret = __sys_sendmsg_sock(sock, &kmsg->msg, flags);
|
||||
if ((issue_flags & IO_URING_F_NONBLOCK) && ret == -EAGAIN)
|
||||
return io_setup_async_msg(req, kmsg);
|
||||
|
|
@ -4416,7 +4420,7 @@ static int io_sendmsg(struct io_kiocb *req, unsigned int issue_flags)
|
|||
if (kmsg->free_iov)
|
||||
kfree(kmsg->free_iov);
|
||||
req->flags &= ~REQ_F_NEED_CLEANUP;
|
||||
if (ret < 0)
|
||||
if (ret < min_ret)
|
||||
req_set_fail_links(req);
|
||||
__io_req_complete(req, issue_flags, ret, 0);
|
||||
return 0;
|
||||
|
|
@ -4429,6 +4433,7 @@ static int io_send(struct io_kiocb *req, unsigned int issue_flags)
|
|||
struct iovec iov;
|
||||
struct socket *sock;
|
||||
unsigned flags;
|
||||
int min_ret = 0;
|
||||
int ret;
|
||||
|
||||
sock = sock_from_file(req->file);
|
||||
|
|
@ -4450,6 +4455,9 @@ static int io_send(struct io_kiocb *req, unsigned int issue_flags)
|
|||
else if (issue_flags & IO_URING_F_NONBLOCK)
|
||||
flags |= MSG_DONTWAIT;
|
||||
|
||||
if (flags & MSG_WAITALL)
|
||||
min_ret = iov_iter_count(&msg.msg_iter);
|
||||
|
||||
msg.msg_flags = flags;
|
||||
ret = sock_sendmsg(sock, &msg);
|
||||
if ((issue_flags & IO_URING_F_NONBLOCK) && ret == -EAGAIN)
|
||||
|
|
@ -4457,7 +4465,7 @@ static int io_send(struct io_kiocb *req, unsigned int issue_flags)
|
|||
if (ret == -ERESTARTSYS)
|
||||
ret = -EINTR;
|
||||
|
||||
if (ret < 0)
|
||||
if (ret < min_ret)
|
||||
req_set_fail_links(req);
|
||||
__io_req_complete(req, issue_flags, ret, 0);
|
||||
return 0;
|
||||
|
|
@ -4609,6 +4617,7 @@ static int io_recvmsg(struct io_kiocb *req, unsigned int issue_flags)
|
|||
struct socket *sock;
|
||||
struct io_buffer *kbuf;
|
||||
unsigned flags;
|
||||
int min_ret = 0;
|
||||
int ret, cflags = 0;
|
||||
bool force_nonblock = issue_flags & IO_URING_F_NONBLOCK;
|
||||
|
||||
|
|
@ -4640,6 +4649,9 @@ static int io_recvmsg(struct io_kiocb *req, unsigned int issue_flags)
|
|||
else if (force_nonblock)
|
||||
flags |= MSG_DONTWAIT;
|
||||
|
||||
if (flags & MSG_WAITALL)
|
||||
min_ret = iov_iter_count(&kmsg->msg.msg_iter);
|
||||
|
||||
ret = __sys_recvmsg_sock(sock, &kmsg->msg, req->sr_msg.umsg,
|
||||
kmsg->uaddr, flags);
|
||||
if (force_nonblock && ret == -EAGAIN)
|
||||
|
|
@ -4653,7 +4665,7 @@ static int io_recvmsg(struct io_kiocb *req, unsigned int issue_flags)
|
|||
if (kmsg->free_iov)
|
||||
kfree(kmsg->free_iov);
|
||||
req->flags &= ~REQ_F_NEED_CLEANUP;
|
||||
if (ret < 0)
|
||||
if (ret < min_ret || ((flags & MSG_WAITALL) && (kmsg->msg.msg_flags & (MSG_TRUNC | MSG_CTRUNC))))
|
||||
req_set_fail_links(req);
|
||||
__io_req_complete(req, issue_flags, ret, cflags);
|
||||
return 0;
|
||||
|
|
@ -4668,6 +4680,7 @@ static int io_recv(struct io_kiocb *req, unsigned int issue_flags)
|
|||
struct socket *sock;
|
||||
struct iovec iov;
|
||||
unsigned flags;
|
||||
int min_ret = 0;
|
||||
int ret, cflags = 0;
|
||||
bool force_nonblock = issue_flags & IO_URING_F_NONBLOCK;
|
||||
|
||||
|
|
@ -4699,6 +4712,9 @@ static int io_recv(struct io_kiocb *req, unsigned int issue_flags)
|
|||
else if (force_nonblock)
|
||||
flags |= MSG_DONTWAIT;
|
||||
|
||||
if (flags & MSG_WAITALL)
|
||||
min_ret = iov_iter_count(&msg.msg_iter);
|
||||
|
||||
ret = sock_recvmsg(sock, &msg, flags);
|
||||
if (force_nonblock && ret == -EAGAIN)
|
||||
return -EAGAIN;
|
||||
|
|
@ -4707,7 +4723,7 @@ static int io_recv(struct io_kiocb *req, unsigned int issue_flags)
|
|||
out_free:
|
||||
if (req->flags & REQ_F_BUFFER_SELECTED)
|
||||
cflags = io_put_recv_kbuf(req);
|
||||
if (ret < 0)
|
||||
if (ret < min_ret || ((flags & MSG_WAITALL) && (msg.msg_flags & (MSG_TRUNC | MSG_CTRUNC))))
|
||||
req_set_fail_links(req);
|
||||
__io_req_complete(req, issue_flags, ret, cflags);
|
||||
return 0;
|
||||
|
|
|
|||
10
fs/select.c
10
fs/select.c
|
|
@ -1055,10 +1055,9 @@ static long do_restart_poll(struct restart_block *restart_block)
|
|||
|
||||
ret = do_sys_poll(ufds, nfds, to);
|
||||
|
||||
if (ret == -ERESTARTNOHAND) {
|
||||
restart_block->fn = do_restart_poll;
|
||||
ret = -ERESTART_RESTARTBLOCK;
|
||||
}
|
||||
if (ret == -ERESTARTNOHAND)
|
||||
ret = set_restart_fn(restart_block, do_restart_poll);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
@ -1080,7 +1079,6 @@ SYSCALL_DEFINE3(poll, struct pollfd __user *, ufds, unsigned int, nfds,
|
|||
struct restart_block *restart_block;
|
||||
|
||||
restart_block = ¤t->restart_block;
|
||||
restart_block->fn = do_restart_poll;
|
||||
restart_block->poll.ufds = ufds;
|
||||
restart_block->poll.nfds = nfds;
|
||||
|
||||
|
|
@ -1091,7 +1089,7 @@ SYSCALL_DEFINE3(poll, struct pollfd __user *, ufds, unsigned int, nfds,
|
|||
} else
|
||||
restart_block->poll.has_timeout = 0;
|
||||
|
||||
ret = -ERESTART_RESTARTBLOCK;
|
||||
ret = set_restart_fn(restart_block, do_restart_poll);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -72,8 +72,10 @@ typedef void *efi_handle_t;
|
|||
*/
|
||||
typedef guid_t efi_guid_t __aligned(__alignof__(u32));
|
||||
|
||||
#define EFI_GUID(a,b,c,d0,d1,d2,d3,d4,d5,d6,d7) \
|
||||
GUID_INIT(a, b, c, d0, d1, d2, d3, d4, d5, d6, d7)
|
||||
#define EFI_GUID(a, b, c, d...) (efi_guid_t){ { \
|
||||
(a) & 0xff, ((a) >> 8) & 0xff, ((a) >> 16) & 0xff, ((a) >> 24) & 0xff, \
|
||||
(b) & 0xff, ((b) >> 8) & 0xff, \
|
||||
(c) & 0xff, ((c) >> 8) & 0xff, d } }
|
||||
|
||||
/*
|
||||
* Generic EFI table header
|
||||
|
|
|
|||
|
|
@ -23,6 +23,7 @@ enum timespec_type {
|
|||
* System call restart block.
|
||||
*/
|
||||
struct restart_block {
|
||||
unsigned long arch_data;
|
||||
long (*fn)(struct restart_block *);
|
||||
union {
|
||||
/* For futex_wait and futex_wait_requeue_pi */
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@
|
|||
#include <linux/types.h>
|
||||
#include <linux/bug.h>
|
||||
#include <linux/restart_block.h>
|
||||
#include <linux/errno.h>
|
||||
|
||||
#ifdef CONFIG_THREAD_INFO_IN_TASK
|
||||
/*
|
||||
|
|
@ -59,6 +60,18 @@ enum syscall_work_bit {
|
|||
|
||||
#ifdef __KERNEL__
|
||||
|
||||
#ifndef arch_set_restart_data
|
||||
#define arch_set_restart_data(restart) do { } while (0)
|
||||
#endif
|
||||
|
||||
static inline long set_restart_fn(struct restart_block *restart,
|
||||
long (*fn)(struct restart_block *))
|
||||
{
|
||||
restart->fn = fn;
|
||||
arch_set_restart_data(restart);
|
||||
return -ERESTART_RESTARTBLOCK;
|
||||
}
|
||||
|
||||
#ifndef THREAD_ALIGN
|
||||
#define THREAD_ALIGN THREAD_SIZE
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -86,6 +86,8 @@
|
|||
/* lies about caching, so always sync */ \
|
||||
US_FLAG(NO_SAME, 0x40000000) \
|
||||
/* Cannot handle WRITE_SAME */ \
|
||||
US_FLAG(SENSE_AFTER_SYNC, 0x80000000) \
|
||||
/* Do REQUEST_SENSE after SYNCHRONIZE_CACHE */ \
|
||||
|
||||
#define US_FLAG(name, value) US_FL_##name = value ,
|
||||
enum { US_DO_ALL_FLAGS };
|
||||
|
|
|
|||
|
|
@ -173,9 +173,10 @@ static inline void ww_acquire_done(struct ww_acquire_ctx *ctx)
|
|||
*/
|
||||
static inline void ww_acquire_fini(struct ww_acquire_ctx *ctx)
|
||||
{
|
||||
#ifdef CONFIG_DEBUG_MUTEXES
|
||||
#ifdef CONFIG_DEBUG_LOCK_ALLOC
|
||||
mutex_release(&ctx->dep_map, _THIS_IP_);
|
||||
|
||||
#endif
|
||||
#ifdef CONFIG_DEBUG_MUTEXES
|
||||
DEBUG_LOCKS_WARN_ON(ctx->acquired);
|
||||
if (!IS_ENABLED(CONFIG_PROVE_LOCKING))
|
||||
/*
|
||||
|
|
|
|||
|
|
@ -2732,14 +2732,13 @@ static int futex_wait(u32 __user *uaddr, unsigned int flags, u32 val,
|
|||
goto out;
|
||||
|
||||
restart = ¤t->restart_block;
|
||||
restart->fn = futex_wait_restart;
|
||||
restart->futex.uaddr = uaddr;
|
||||
restart->futex.val = val;
|
||||
restart->futex.time = *abs_time;
|
||||
restart->futex.bitset = bitset;
|
||||
restart->futex.flags = flags | FLAGS_HAS_TIMEOUT;
|
||||
|
||||
ret = -ERESTART_RESTARTBLOCK;
|
||||
ret = set_restart_fn(restart, futex_wait_restart);
|
||||
|
||||
out:
|
||||
if (to) {
|
||||
|
|
|
|||
|
|
@ -159,7 +159,7 @@ static const struct irq_domain_ops irq_sim_domain_ops = {
|
|||
* irq_domain_create_sim - Create a new interrupt simulator irq_domain and
|
||||
* allocate a range of dummy interrupts.
|
||||
*
|
||||
* @fnode: struct fwnode_handle to be associated with this domain.
|
||||
* @fwnode: struct fwnode_handle to be associated with this domain.
|
||||
* @num_irqs: Number of interrupts to allocate.
|
||||
*
|
||||
* On success: return a new irq_domain object.
|
||||
|
|
@ -228,7 +228,7 @@ static void devm_irq_domain_release_sim(struct device *dev, void *res)
|
|||
* a managed device.
|
||||
*
|
||||
* @dev: Device to initialize the simulator object for.
|
||||
* @fnode: struct fwnode_handle to be associated with this domain.
|
||||
* @fwnode: struct fwnode_handle to be associated with this domain.
|
||||
* @num_irqs: Number of interrupts to allocate
|
||||
*
|
||||
* On success: return a new irq_domain object.
|
||||
|
|
|
|||
|
|
@ -1142,11 +1142,15 @@ irq_forced_thread_fn(struct irq_desc *desc, struct irqaction *action)
|
|||
irqreturn_t ret;
|
||||
|
||||
local_bh_disable();
|
||||
if (!IS_ENABLED(CONFIG_PREEMPT_RT))
|
||||
local_irq_disable();
|
||||
ret = action->thread_fn(action->irq, action->dev_id);
|
||||
if (ret == IRQ_HANDLED)
|
||||
atomic_inc(&desc->threads_handled);
|
||||
|
||||
irq_finalize_oneshot(desc, action);
|
||||
if (!IS_ENABLED(CONFIG_PREEMPT_RT))
|
||||
local_irq_enable();
|
||||
local_bh_enable();
|
||||
return ret;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -407,6 +407,14 @@ static bool jump_label_can_update(struct jump_entry *entry, bool init)
|
|||
return false;
|
||||
|
||||
if (!kernel_text_address(jump_entry_code(entry))) {
|
||||
/*
|
||||
* This skips patching built-in __exit, which
|
||||
* is part of init_section_contains() but is
|
||||
* not part of kernel_text_address().
|
||||
*
|
||||
* Skipping built-in __exit is fine since it
|
||||
* will never be executed.
|
||||
*/
|
||||
WARN_ONCE(!jump_entry_is_init(entry),
|
||||
"can't patch jump_label at %pS",
|
||||
(void *)jump_entry_code(entry));
|
||||
|
|
|
|||
|
|
@ -628,7 +628,7 @@ static inline int mutex_can_spin_on_owner(struct mutex *lock)
|
|||
*/
|
||||
static __always_inline bool
|
||||
mutex_optimistic_spin(struct mutex *lock, struct ww_acquire_ctx *ww_ctx,
|
||||
const bool use_ww_ctx, struct mutex_waiter *waiter)
|
||||
struct mutex_waiter *waiter)
|
||||
{
|
||||
if (!waiter) {
|
||||
/*
|
||||
|
|
@ -704,7 +704,7 @@ mutex_optimistic_spin(struct mutex *lock, struct ww_acquire_ctx *ww_ctx,
|
|||
#else
|
||||
static __always_inline bool
|
||||
mutex_optimistic_spin(struct mutex *lock, struct ww_acquire_ctx *ww_ctx,
|
||||
const bool use_ww_ctx, struct mutex_waiter *waiter)
|
||||
struct mutex_waiter *waiter)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
|
@ -924,6 +924,9 @@ __mutex_lock_common(struct mutex *lock, long state, unsigned int subclass,
|
|||
struct ww_mutex *ww;
|
||||
int ret;
|
||||
|
||||
if (!use_ww_ctx)
|
||||
ww_ctx = NULL;
|
||||
|
||||
might_sleep();
|
||||
|
||||
#ifdef CONFIG_DEBUG_MUTEXES
|
||||
|
|
@ -931,7 +934,7 @@ __mutex_lock_common(struct mutex *lock, long state, unsigned int subclass,
|
|||
#endif
|
||||
|
||||
ww = container_of(lock, struct ww_mutex, base);
|
||||
if (use_ww_ctx && ww_ctx) {
|
||||
if (ww_ctx) {
|
||||
if (unlikely(ww_ctx == READ_ONCE(ww->ctx)))
|
||||
return -EALREADY;
|
||||
|
||||
|
|
@ -948,10 +951,10 @@ __mutex_lock_common(struct mutex *lock, long state, unsigned int subclass,
|
|||
mutex_acquire_nest(&lock->dep_map, subclass, 0, nest_lock, ip);
|
||||
|
||||
if (__mutex_trylock(lock) ||
|
||||
mutex_optimistic_spin(lock, ww_ctx, use_ww_ctx, NULL)) {
|
||||
mutex_optimistic_spin(lock, ww_ctx, NULL)) {
|
||||
/* got the lock, yay! */
|
||||
lock_acquired(&lock->dep_map, ip);
|
||||
if (use_ww_ctx && ww_ctx)
|
||||
if (ww_ctx)
|
||||
ww_mutex_set_context_fastpath(ww, ww_ctx);
|
||||
preempt_enable();
|
||||
return 0;
|
||||
|
|
@ -962,7 +965,7 @@ __mutex_lock_common(struct mutex *lock, long state, unsigned int subclass,
|
|||
* After waiting to acquire the wait_lock, try again.
|
||||
*/
|
||||
if (__mutex_trylock(lock)) {
|
||||
if (use_ww_ctx && ww_ctx)
|
||||
if (ww_ctx)
|
||||
__ww_mutex_check_waiters(lock, ww_ctx);
|
||||
|
||||
goto skip_wait;
|
||||
|
|
@ -1016,7 +1019,7 @@ __mutex_lock_common(struct mutex *lock, long state, unsigned int subclass,
|
|||
goto err;
|
||||
}
|
||||
|
||||
if (use_ww_ctx && ww_ctx) {
|
||||
if (ww_ctx) {
|
||||
ret = __ww_mutex_check_kill(lock, &waiter, ww_ctx);
|
||||
if (ret)
|
||||
goto err;
|
||||
|
|
@ -1029,7 +1032,7 @@ __mutex_lock_common(struct mutex *lock, long state, unsigned int subclass,
|
|||
* ww_mutex needs to always recheck its position since its waiter
|
||||
* list is not FIFO ordered.
|
||||
*/
|
||||
if ((use_ww_ctx && ww_ctx) || !first) {
|
||||
if (ww_ctx || !first) {
|
||||
first = __mutex_waiter_is_first(lock, &waiter);
|
||||
if (first)
|
||||
__mutex_set_flag(lock, MUTEX_FLAG_HANDOFF);
|
||||
|
|
@ -1042,7 +1045,7 @@ __mutex_lock_common(struct mutex *lock, long state, unsigned int subclass,
|
|||
* or we must see its unlock and acquire.
|
||||
*/
|
||||
if (__mutex_trylock(lock) ||
|
||||
(first && mutex_optimistic_spin(lock, ww_ctx, use_ww_ctx, &waiter)))
|
||||
(first && mutex_optimistic_spin(lock, ww_ctx, &waiter)))
|
||||
break;
|
||||
|
||||
spin_lock(&lock->wait_lock);
|
||||
|
|
@ -1052,7 +1055,7 @@ __mutex_lock_common(struct mutex *lock, long state, unsigned int subclass,
|
|||
__set_current_state(TASK_RUNNING);
|
||||
trace_android_vh_mutex_wait_finish(lock);
|
||||
|
||||
if (use_ww_ctx && ww_ctx) {
|
||||
if (ww_ctx) {
|
||||
/*
|
||||
* Wound-Wait; we stole the lock (!first_waiter), check the
|
||||
* waiters as anyone might want to wound us.
|
||||
|
|
@ -1072,7 +1075,7 @@ __mutex_lock_common(struct mutex *lock, long state, unsigned int subclass,
|
|||
/* got the lock - cleanup and rejoice! */
|
||||
lock_acquired(&lock->dep_map, ip);
|
||||
|
||||
if (use_ww_ctx && ww_ctx)
|
||||
if (ww_ctx)
|
||||
ww_mutex_lock_acquired(ww, ww_ctx);
|
||||
|
||||
spin_unlock(&lock->wait_lock);
|
||||
|
|
|
|||
|
|
@ -288,7 +288,8 @@ bool task_set_jobctl_pending(struct task_struct *task, unsigned long mask)
|
|||
JOBCTL_STOP_SIGMASK | JOBCTL_TRAPPING));
|
||||
BUG_ON((mask & JOBCTL_TRAPPING) && !(mask & JOBCTL_PENDING_MASK));
|
||||
|
||||
if (unlikely(fatal_signal_pending(task) || (task->flags & PF_EXITING)))
|
||||
if (unlikely(fatal_signal_pending(task) ||
|
||||
(task->flags & (PF_EXITING | PF_IO_WORKER))))
|
||||
return false;
|
||||
|
||||
if (mask & JOBCTL_STOP_SIGMASK)
|
||||
|
|
@ -833,6 +834,9 @@ static int check_kill_permission(int sig, struct kernel_siginfo *info,
|
|||
|
||||
if (!valid_signal(sig))
|
||||
return -EINVAL;
|
||||
/* PF_IO_WORKER threads don't take any signals */
|
||||
if (t->flags & PF_IO_WORKER)
|
||||
return -ESRCH;
|
||||
|
||||
if (!si_fromuser(info))
|
||||
return 0;
|
||||
|
|
|
|||
|
|
@ -35,27 +35,30 @@ static inline void *static_call_addr(struct static_call_site *site)
|
|||
return (void *)((long)site->addr + (long)&site->addr);
|
||||
}
|
||||
|
||||
static inline unsigned long __static_call_key(const struct static_call_site *site)
|
||||
{
|
||||
return (long)site->key + (long)&site->key;
|
||||
}
|
||||
|
||||
static inline struct static_call_key *static_call_key(const struct static_call_site *site)
|
||||
{
|
||||
return (struct static_call_key *)
|
||||
(((long)site->key + (long)&site->key) & ~STATIC_CALL_SITE_FLAGS);
|
||||
return (void *)(__static_call_key(site) & ~STATIC_CALL_SITE_FLAGS);
|
||||
}
|
||||
|
||||
/* These assume the key is word-aligned. */
|
||||
static inline bool static_call_is_init(struct static_call_site *site)
|
||||
{
|
||||
return ((long)site->key + (long)&site->key) & STATIC_CALL_SITE_INIT;
|
||||
return __static_call_key(site) & STATIC_CALL_SITE_INIT;
|
||||
}
|
||||
|
||||
static inline bool static_call_is_tail(struct static_call_site *site)
|
||||
{
|
||||
return ((long)site->key + (long)&site->key) & STATIC_CALL_SITE_TAIL;
|
||||
return __static_call_key(site) & STATIC_CALL_SITE_TAIL;
|
||||
}
|
||||
|
||||
static inline void static_call_set_init(struct static_call_site *site)
|
||||
{
|
||||
site->key = ((long)static_call_key(site) | STATIC_CALL_SITE_INIT) -
|
||||
site->key = (__static_call_key(site) | STATIC_CALL_SITE_INIT) -
|
||||
(long)&site->key;
|
||||
}
|
||||
|
||||
|
|
@ -146,6 +149,7 @@ void __static_call_update(struct static_call_key *key, void *tramp, void *func)
|
|||
};
|
||||
|
||||
for (site_mod = &first; site_mod; site_mod = site_mod->next) {
|
||||
bool init = system_state < SYSTEM_RUNNING;
|
||||
struct module *mod = site_mod->mod;
|
||||
|
||||
if (!site_mod->sites) {
|
||||
|
|
@ -165,6 +169,7 @@ void __static_call_update(struct static_call_key *key, void *tramp, void *func)
|
|||
if (mod) {
|
||||
stop = mod->static_call_sites +
|
||||
mod->num_static_call_sites;
|
||||
init = mod->state == MODULE_STATE_COMING;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
|
@ -172,25 +177,26 @@ void __static_call_update(struct static_call_key *key, void *tramp, void *func)
|
|||
site < stop && static_call_key(site) == key; site++) {
|
||||
void *site_addr = static_call_addr(site);
|
||||
|
||||
if (static_call_is_init(site)) {
|
||||
/*
|
||||
* Don't write to call sites which were in
|
||||
* initmem and have since been freed.
|
||||
*/
|
||||
if (!mod && system_state >= SYSTEM_RUNNING)
|
||||
continue;
|
||||
if (mod && !within_module_init((unsigned long)site_addr, mod))
|
||||
continue;
|
||||
}
|
||||
if (!init && static_call_is_init(site))
|
||||
continue;
|
||||
|
||||
if (!kernel_text_address((unsigned long)site_addr)) {
|
||||
WARN_ONCE(1, "can't patch static call site at %pS",
|
||||
/*
|
||||
* This skips patching built-in __exit, which
|
||||
* is part of init_section_contains() but is
|
||||
* not part of kernel_text_address().
|
||||
*
|
||||
* Skipping built-in __exit is fine since it
|
||||
* will never be executed.
|
||||
*/
|
||||
WARN_ONCE(!static_call_is_init(site),
|
||||
"can't patch static call site at %pS",
|
||||
site_addr);
|
||||
continue;
|
||||
}
|
||||
|
||||
arch_static_call_transform(site_addr, NULL, func,
|
||||
static_call_is_tail(site));
|
||||
static_call_is_tail(site));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -349,7 +355,7 @@ static int static_call_add_module(struct module *mod)
|
|||
struct static_call_site *site;
|
||||
|
||||
for (site = start; site != stop; site++) {
|
||||
unsigned long s_key = (long)site->key + (long)&site->key;
|
||||
unsigned long s_key = __static_call_key(site);
|
||||
unsigned long addr = s_key & ~STATIC_CALL_SITE_FLAGS;
|
||||
unsigned long key;
|
||||
|
||||
|
|
|
|||
|
|
@ -854,9 +854,9 @@ static int alarm_timer_nsleep(const clockid_t which_clock, int flags,
|
|||
if (flags == TIMER_ABSTIME)
|
||||
return -ERESTARTNOHAND;
|
||||
|
||||
restart->fn = alarm_timer_nsleep_restart;
|
||||
restart->nanosleep.clockid = type;
|
||||
restart->nanosleep.expires = exp;
|
||||
set_restart_fn(restart, alarm_timer_nsleep_restart);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1957,9 +1957,9 @@ long hrtimer_nanosleep(ktime_t rqtp, const enum hrtimer_mode mode,
|
|||
}
|
||||
|
||||
restart = ¤t->restart_block;
|
||||
restart->fn = hrtimer_nanosleep_restart;
|
||||
restart->nanosleep.clockid = t.timer.base->clockid;
|
||||
restart->nanosleep.expires = hrtimer_get_expires_tv64(&t.timer);
|
||||
set_restart_fn(restart, hrtimer_nanosleep_restart);
|
||||
out:
|
||||
destroy_hrtimer_on_stack(&t.timer);
|
||||
return ret;
|
||||
|
|
|
|||
|
|
@ -1480,8 +1480,8 @@ static int posix_cpu_nsleep(const clockid_t which_clock, int flags,
|
|||
if (flags & TIMER_ABSTIME)
|
||||
return -ERESTARTNOHAND;
|
||||
|
||||
restart_block->fn = posix_cpu_nsleep_restart;
|
||||
restart_block->nanosleep.clockid = which_clock;
|
||||
set_restart_fn(restart_block, posix_cpu_nsleep_restart);
|
||||
}
|
||||
return error;
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user