1805 lines
58 KiB
Diff
1805 lines
58 KiB
Diff
diff --git a/Makefile b/Makefile
|
|
index c6b3a3d62f6ca..4eeb72027815b 100644
|
|
--- a/Makefile
|
|
+++ b/Makefile
|
|
@@ -1,7 +1,7 @@
|
|
# SPDX-License-Identifier: GPL-2.0
|
|
VERSION = 5
|
|
PATCHLEVEL = 4
|
|
-SUBLEVEL = 150
|
|
+SUBLEVEL = 151
|
|
EXTRAVERSION =
|
|
NAME = Kleptomaniac Octopus
|
|
|
|
diff --git a/arch/x86/events/intel/core.c b/arch/x86/events/intel/core.c
|
|
index 9cb3266e148dc..70758f99c9e47 100644
|
|
--- a/arch/x86/events/intel/core.c
|
|
+++ b/arch/x86/events/intel/core.c
|
|
@@ -259,6 +259,7 @@ static struct event_constraint intel_icl_event_constraints[] = {
|
|
INTEL_EVENT_CONSTRAINT_RANGE(0xa8, 0xb0, 0xf),
|
|
INTEL_EVENT_CONSTRAINT_RANGE(0xb7, 0xbd, 0xf),
|
|
INTEL_EVENT_CONSTRAINT_RANGE(0xd0, 0xe6, 0xf),
|
|
+ INTEL_EVENT_CONSTRAINT(0xef, 0xf),
|
|
INTEL_EVENT_CONSTRAINT_RANGE(0xf0, 0xf4, 0xf),
|
|
EVENT_CONSTRAINT_END
|
|
};
|
|
diff --git a/arch/x86/include/asm/kvmclock.h b/arch/x86/include/asm/kvmclock.h
|
|
index eceea92990974..6c57651921028 100644
|
|
--- a/arch/x86/include/asm/kvmclock.h
|
|
+++ b/arch/x86/include/asm/kvmclock.h
|
|
@@ -2,6 +2,20 @@
|
|
#ifndef _ASM_X86_KVM_CLOCK_H
|
|
#define _ASM_X86_KVM_CLOCK_H
|
|
|
|
+#include <linux/percpu.h>
|
|
+
|
|
extern struct clocksource kvm_clock;
|
|
|
|
+DECLARE_PER_CPU(struct pvclock_vsyscall_time_info *, hv_clock_per_cpu);
|
|
+
|
|
+static inline struct pvclock_vcpu_time_info *this_cpu_pvti(void)
|
|
+{
|
|
+ return &this_cpu_read(hv_clock_per_cpu)->pvti;
|
|
+}
|
|
+
|
|
+static inline struct pvclock_vsyscall_time_info *this_cpu_hvclock(void)
|
|
+{
|
|
+ return this_cpu_read(hv_clock_per_cpu);
|
|
+}
|
|
+
|
|
#endif /* _ASM_X86_KVM_CLOCK_H */
|
|
diff --git a/arch/x86/kernel/kvmclock.c b/arch/x86/kernel/kvmclock.c
|
|
index 4a0802af2e3e0..d81e34e614e00 100644
|
|
--- a/arch/x86/kernel/kvmclock.c
|
|
+++ b/arch/x86/kernel/kvmclock.c
|
|
@@ -50,18 +50,9 @@ early_param("no-kvmclock-vsyscall", parse_no_kvmclock_vsyscall);
|
|
static struct pvclock_vsyscall_time_info
|
|
hv_clock_boot[HVC_BOOT_ARRAY_SIZE] __bss_decrypted __aligned(PAGE_SIZE);
|
|
static struct pvclock_wall_clock wall_clock __bss_decrypted;
|
|
-static DEFINE_PER_CPU(struct pvclock_vsyscall_time_info *, hv_clock_per_cpu);
|
|
static struct pvclock_vsyscall_time_info *hvclock_mem;
|
|
-
|
|
-static inline struct pvclock_vcpu_time_info *this_cpu_pvti(void)
|
|
-{
|
|
- return &this_cpu_read(hv_clock_per_cpu)->pvti;
|
|
-}
|
|
-
|
|
-static inline struct pvclock_vsyscall_time_info *this_cpu_hvclock(void)
|
|
-{
|
|
- return this_cpu_read(hv_clock_per_cpu);
|
|
-}
|
|
+DEFINE_PER_CPU(struct pvclock_vsyscall_time_info *, hv_clock_per_cpu);
|
|
+EXPORT_PER_CPU_SYMBOL_GPL(hv_clock_per_cpu);
|
|
|
|
/*
|
|
* The wallclock is the time of day when we booted. Since then, some time may
|
|
diff --git a/block/bfq-iosched.c b/block/bfq-iosched.c
|
|
index 8dee243e639f0..73bffd7af15c1 100644
|
|
--- a/block/bfq-iosched.c
|
|
+++ b/block/bfq-iosched.c
|
|
@@ -2523,15 +2523,6 @@ bfq_setup_merge(struct bfq_queue *bfqq, struct bfq_queue *new_bfqq)
|
|
* are likely to increase the throughput.
|
|
*/
|
|
bfqq->new_bfqq = new_bfqq;
|
|
- /*
|
|
- * The above assignment schedules the following redirections:
|
|
- * each time some I/O for bfqq arrives, the process that
|
|
- * generated that I/O is disassociated from bfqq and
|
|
- * associated with new_bfqq. Here we increases new_bfqq->ref
|
|
- * in advance, adding the number of processes that are
|
|
- * expected to be associated with new_bfqq as they happen to
|
|
- * issue I/O.
|
|
- */
|
|
new_bfqq->ref += process_refs;
|
|
return new_bfqq;
|
|
}
|
|
@@ -2591,10 +2582,6 @@ bfq_setup_cooperator(struct bfq_data *bfqd, struct bfq_queue *bfqq,
|
|
{
|
|
struct bfq_queue *in_service_bfqq, *new_bfqq;
|
|
|
|
- /* if a merge has already been setup, then proceed with that first */
|
|
- if (bfqq->new_bfqq)
|
|
- return bfqq->new_bfqq;
|
|
-
|
|
/*
|
|
* Do not perform queue merging if the device is non
|
|
* rotational and performs internal queueing. In fact, such a
|
|
@@ -2649,6 +2636,9 @@ bfq_setup_cooperator(struct bfq_data *bfqd, struct bfq_queue *bfqq,
|
|
if (bfq_too_late_for_merging(bfqq))
|
|
return NULL;
|
|
|
|
+ if (bfqq->new_bfqq)
|
|
+ return bfqq->new_bfqq;
|
|
+
|
|
if (!io_struct || unlikely(bfqq == &bfqd->oom_bfqq))
|
|
return NULL;
|
|
|
|
diff --git a/drivers/cpufreq/cpufreq_governor_attr_set.c b/drivers/cpufreq/cpufreq_governor_attr_set.c
|
|
index 66b05a326910e..a6f365b9cc1ad 100644
|
|
--- a/drivers/cpufreq/cpufreq_governor_attr_set.c
|
|
+++ b/drivers/cpufreq/cpufreq_governor_attr_set.c
|
|
@@ -74,8 +74,8 @@ unsigned int gov_attr_set_put(struct gov_attr_set *attr_set, struct list_head *l
|
|
if (count)
|
|
return count;
|
|
|
|
- kobject_put(&attr_set->kobj);
|
|
mutex_destroy(&attr_set->update_lock);
|
|
+ kobject_put(&attr_set->kobj);
|
|
return 0;
|
|
}
|
|
EXPORT_SYMBOL_GPL(gov_attr_set_put);
|
|
diff --git a/drivers/crypto/ccp/ccp-ops.c b/drivers/crypto/ccp/ccp-ops.c
|
|
index 7234b95241e91..e826c4b6b3afd 100644
|
|
--- a/drivers/crypto/ccp/ccp-ops.c
|
|
+++ b/drivers/crypto/ccp/ccp-ops.c
|
|
@@ -778,7 +778,7 @@ ccp_run_aes_gcm_cmd(struct ccp_cmd_queue *cmd_q, struct ccp_cmd *cmd)
|
|
in_place ? DMA_BIDIRECTIONAL
|
|
: DMA_TO_DEVICE);
|
|
if (ret)
|
|
- goto e_ctx;
|
|
+ goto e_aad;
|
|
|
|
if (in_place) {
|
|
dst = src;
|
|
@@ -863,7 +863,7 @@ ccp_run_aes_gcm_cmd(struct ccp_cmd_queue *cmd_q, struct ccp_cmd *cmd)
|
|
op.u.aes.size = 0;
|
|
ret = cmd_q->ccp->vdata->perform->aes(&op);
|
|
if (ret)
|
|
- goto e_dst;
|
|
+ goto e_final_wa;
|
|
|
|
if (aes->action == CCP_AES_ACTION_ENCRYPT) {
|
|
/* Put the ciphered tag after the ciphertext. */
|
|
@@ -873,17 +873,19 @@ ccp_run_aes_gcm_cmd(struct ccp_cmd_queue *cmd_q, struct ccp_cmd *cmd)
|
|
ret = ccp_init_dm_workarea(&tag, cmd_q, authsize,
|
|
DMA_BIDIRECTIONAL);
|
|
if (ret)
|
|
- goto e_tag;
|
|
+ goto e_final_wa;
|
|
ret = ccp_set_dm_area(&tag, 0, p_tag, 0, authsize);
|
|
- if (ret)
|
|
- goto e_tag;
|
|
+ if (ret) {
|
|
+ ccp_dm_free(&tag);
|
|
+ goto e_final_wa;
|
|
+ }
|
|
|
|
ret = crypto_memneq(tag.address, final_wa.address,
|
|
authsize) ? -EBADMSG : 0;
|
|
ccp_dm_free(&tag);
|
|
}
|
|
|
|
-e_tag:
|
|
+e_final_wa:
|
|
ccp_dm_free(&final_wa);
|
|
|
|
e_dst:
|
|
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
|
|
index 0dc60fe22aefc..8e4d863c7570b 100644
|
|
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
|
|
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
|
|
@@ -664,6 +664,7 @@ static int amdgpu_dm_init(struct amdgpu_device *adev)
|
|
|
|
init_data.asic_id.pci_revision_id = adev->rev_id;
|
|
init_data.asic_id.hw_internal_rev = adev->external_rev_id;
|
|
+ init_data.asic_id.chip_id = adev->pdev->device;
|
|
|
|
init_data.asic_id.vram_width = adev->gmc.vram_width;
|
|
/* TODO: initialize init_data.asic_id.vram_type here!!!! */
|
|
diff --git a/drivers/hid/hid-betopff.c b/drivers/hid/hid-betopff.c
|
|
index 0790fbd3fc9a2..467d789f9bc2d 100644
|
|
--- a/drivers/hid/hid-betopff.c
|
|
+++ b/drivers/hid/hid-betopff.c
|
|
@@ -56,15 +56,22 @@ static int betopff_init(struct hid_device *hid)
|
|
{
|
|
struct betopff_device *betopff;
|
|
struct hid_report *report;
|
|
- struct hid_input *hidinput =
|
|
- list_first_entry(&hid->inputs, struct hid_input, list);
|
|
+ struct hid_input *hidinput;
|
|
struct list_head *report_list =
|
|
&hid->report_enum[HID_OUTPUT_REPORT].report_list;
|
|
- struct input_dev *dev = hidinput->input;
|
|
+ struct input_dev *dev;
|
|
int field_count = 0;
|
|
int error;
|
|
int i, j;
|
|
|
|
+ if (list_empty(&hid->inputs)) {
|
|
+ hid_err(hid, "no inputs found\n");
|
|
+ return -ENODEV;
|
|
+ }
|
|
+
|
|
+ hidinput = list_first_entry(&hid->inputs, struct hid_input, list);
|
|
+ dev = hidinput->input;
|
|
+
|
|
if (list_empty(report_list)) {
|
|
hid_err(hid, "no output reports found\n");
|
|
return -ENODEV;
|
|
diff --git a/drivers/hid/hid-u2fzero.c b/drivers/hid/hid-u2fzero.c
|
|
index 95e0807878c7e..d70cd3d7f583b 100644
|
|
--- a/drivers/hid/hid-u2fzero.c
|
|
+++ b/drivers/hid/hid-u2fzero.c
|
|
@@ -198,7 +198,9 @@ static int u2fzero_rng_read(struct hwrng *rng, void *data,
|
|
}
|
|
|
|
ret = u2fzero_recv(dev, &req, &resp);
|
|
- if (ret < 0)
|
|
+
|
|
+ /* ignore errors or packets without data */
|
|
+ if (ret < offsetof(struct u2f_hid_msg, init.data))
|
|
return 0;
|
|
|
|
/* only take the minimum amount of data it is safe to take */
|
|
diff --git a/drivers/hid/usbhid/hid-core.c b/drivers/hid/usbhid/hid-core.c
|
|
index 1cfbbaf6901da..8537fcdb456df 100644
|
|
--- a/drivers/hid/usbhid/hid-core.c
|
|
+++ b/drivers/hid/usbhid/hid-core.c
|
|
@@ -503,7 +503,7 @@ static void hid_ctrl(struct urb *urb)
|
|
|
|
if (unplug) {
|
|
usbhid->ctrltail = usbhid->ctrlhead;
|
|
- } else {
|
|
+ } else if (usbhid->ctrlhead != usbhid->ctrltail) {
|
|
usbhid->ctrltail = (usbhid->ctrltail + 1) & (HID_CONTROL_FIFO_SIZE - 1);
|
|
|
|
if (usbhid->ctrlhead != usbhid->ctrltail &&
|
|
@@ -1221,9 +1221,20 @@ static void usbhid_stop(struct hid_device *hid)
|
|
mutex_lock(&usbhid->mutex);
|
|
|
|
clear_bit(HID_STARTED, &usbhid->iofl);
|
|
+
|
|
spin_lock_irq(&usbhid->lock); /* Sync with error and led handlers */
|
|
set_bit(HID_DISCONNECTED, &usbhid->iofl);
|
|
+ while (usbhid->ctrltail != usbhid->ctrlhead) {
|
|
+ if (usbhid->ctrl[usbhid->ctrltail].dir == USB_DIR_OUT) {
|
|
+ kfree(usbhid->ctrl[usbhid->ctrltail].raw_report);
|
|
+ usbhid->ctrl[usbhid->ctrltail].raw_report = NULL;
|
|
+ }
|
|
+
|
|
+ usbhid->ctrltail = (usbhid->ctrltail + 1) &
|
|
+ (HID_CONTROL_FIFO_SIZE - 1);
|
|
+ }
|
|
spin_unlock_irq(&usbhid->lock);
|
|
+
|
|
usb_kill_urb(usbhid->urbin);
|
|
usb_kill_urb(usbhid->urbout);
|
|
usb_kill_urb(usbhid->urbctrl);
|
|
diff --git a/drivers/hwmon/mlxreg-fan.c b/drivers/hwmon/mlxreg-fan.c
|
|
index ed8d59d4eecb3..bd8f5a3aaad9c 100644
|
|
--- a/drivers/hwmon/mlxreg-fan.c
|
|
+++ b/drivers/hwmon/mlxreg-fan.c
|
|
@@ -291,8 +291,8 @@ static int mlxreg_fan_set_cur_state(struct thermal_cooling_device *cdev,
|
|
{
|
|
struct mlxreg_fan *fan = cdev->devdata;
|
|
unsigned long cur_state;
|
|
+ int i, config = 0;
|
|
u32 regval;
|
|
- int i;
|
|
int err;
|
|
|
|
/*
|
|
@@ -305,6 +305,12 @@ static int mlxreg_fan_set_cur_state(struct thermal_cooling_device *cdev,
|
|
* overwritten.
|
|
*/
|
|
if (state >= MLXREG_FAN_SPEED_MIN && state <= MLXREG_FAN_SPEED_MAX) {
|
|
+ /*
|
|
+ * This is configuration change, which is only supported through sysfs.
|
|
+ * For configuration non-zero value is to be returned to avoid thermal
|
|
+ * statistics update.
|
|
+ */
|
|
+ config = 1;
|
|
state -= MLXREG_FAN_MAX_STATE;
|
|
for (i = 0; i < state; i++)
|
|
fan->cooling_levels[i] = state;
|
|
@@ -319,7 +325,7 @@ static int mlxreg_fan_set_cur_state(struct thermal_cooling_device *cdev,
|
|
|
|
cur_state = MLXREG_FAN_PWM_DUTY2STATE(regval);
|
|
if (state < cur_state)
|
|
- return 0;
|
|
+ return config;
|
|
|
|
state = cur_state;
|
|
}
|
|
@@ -335,7 +341,7 @@ static int mlxreg_fan_set_cur_state(struct thermal_cooling_device *cdev,
|
|
dev_err(fan->dev, "Failed to write PWM duty\n");
|
|
return err;
|
|
}
|
|
- return 0;
|
|
+ return config;
|
|
}
|
|
|
|
static const struct thermal_cooling_device_ops mlxreg_fan_cooling_ops = {
|
|
diff --git a/drivers/hwmon/tmp421.c b/drivers/hwmon/tmp421.c
|
|
index a94e35cff3e5f..876ccf77a825a 100644
|
|
--- a/drivers/hwmon/tmp421.c
|
|
+++ b/drivers/hwmon/tmp421.c
|
|
@@ -100,23 +100,17 @@ struct tmp421_data {
|
|
s16 temp[4];
|
|
};
|
|
|
|
-static int temp_from_s16(s16 reg)
|
|
+static int temp_from_raw(u16 reg, bool extended)
|
|
{
|
|
/* Mask out status bits */
|
|
int temp = reg & ~0xf;
|
|
|
|
- return (temp * 1000 + 128) / 256;
|
|
-}
|
|
-
|
|
-static int temp_from_u16(u16 reg)
|
|
-{
|
|
- /* Mask out status bits */
|
|
- int temp = reg & ~0xf;
|
|
-
|
|
- /* Add offset for extended temperature range. */
|
|
- temp -= 64 * 256;
|
|
+ if (extended)
|
|
+ temp = temp - 64 * 256;
|
|
+ else
|
|
+ temp = (s16)temp;
|
|
|
|
- return (temp * 1000 + 128) / 256;
|
|
+ return DIV_ROUND_CLOSEST(temp * 1000, 256);
|
|
}
|
|
|
|
static struct tmp421_data *tmp421_update_device(struct device *dev)
|
|
@@ -153,17 +147,15 @@ static int tmp421_read(struct device *dev, enum hwmon_sensor_types type,
|
|
|
|
switch (attr) {
|
|
case hwmon_temp_input:
|
|
- if (tmp421->config & TMP421_CONFIG_RANGE)
|
|
- *val = temp_from_u16(tmp421->temp[channel]);
|
|
- else
|
|
- *val = temp_from_s16(tmp421->temp[channel]);
|
|
+ *val = temp_from_raw(tmp421->temp[channel],
|
|
+ tmp421->config & TMP421_CONFIG_RANGE);
|
|
return 0;
|
|
case hwmon_temp_fault:
|
|
/*
|
|
- * The OPEN bit signals a fault. This is bit 0 of the temperature
|
|
- * register (low byte).
|
|
+ * Any of OPEN or /PVLD bits indicate a hardware mulfunction
|
|
+ * and the conversion result may be incorrect
|
|
*/
|
|
- *val = tmp421->temp[channel] & 0x01;
|
|
+ *val = !!(tmp421->temp[channel] & 0x03);
|
|
return 0;
|
|
default:
|
|
return -EOPNOTSUPP;
|
|
@@ -176,9 +168,6 @@ static umode_t tmp421_is_visible(const void *data, enum hwmon_sensor_types type,
|
|
{
|
|
switch (attr) {
|
|
case hwmon_temp_fault:
|
|
- if (channel == 0)
|
|
- return 0;
|
|
- return 0444;
|
|
case hwmon_temp_input:
|
|
return 0444;
|
|
default:
|
|
diff --git a/drivers/hwmon/w83791d.c b/drivers/hwmon/w83791d.c
|
|
index aad8d4da5802b..b586e917e6ede 100644
|
|
--- a/drivers/hwmon/w83791d.c
|
|
+++ b/drivers/hwmon/w83791d.c
|
|
@@ -273,9 +273,6 @@ struct w83791d_data {
|
|
char valid; /* !=0 if following fields are valid */
|
|
unsigned long last_updated; /* In jiffies */
|
|
|
|
- /* array of 2 pointers to subclients */
|
|
- struct i2c_client *lm75[2];
|
|
-
|
|
/* volts */
|
|
u8 in[NUMBER_OF_VIN]; /* Register value */
|
|
u8 in_max[NUMBER_OF_VIN]; /* Register value */
|
|
@@ -1258,7 +1255,6 @@ static const struct attribute_group w83791d_group_fanpwm45 = {
|
|
static int w83791d_detect_subclients(struct i2c_client *client)
|
|
{
|
|
struct i2c_adapter *adapter = client->adapter;
|
|
- struct w83791d_data *data = i2c_get_clientdata(client);
|
|
int address = client->addr;
|
|
int i, id;
|
|
u8 val;
|
|
@@ -1281,22 +1277,19 @@ static int w83791d_detect_subclients(struct i2c_client *client)
|
|
}
|
|
|
|
val = w83791d_read(client, W83791D_REG_I2C_SUBADDR);
|
|
- if (!(val & 0x08))
|
|
- data->lm75[0] = devm_i2c_new_dummy_device(&client->dev, adapter,
|
|
- 0x48 + (val & 0x7));
|
|
- if (!(val & 0x80)) {
|
|
- if (!IS_ERR(data->lm75[0]) &&
|
|
- ((val & 0x7) == ((val >> 4) & 0x7))) {
|
|
- dev_err(&client->dev,
|
|
- "duplicate addresses 0x%x, "
|
|
- "use force_subclient\n",
|
|
- data->lm75[0]->addr);
|
|
- return -ENODEV;
|
|
- }
|
|
- data->lm75[1] = devm_i2c_new_dummy_device(&client->dev, adapter,
|
|
- 0x48 + ((val >> 4) & 0x7));
|
|
+
|
|
+ if (!(val & 0x88) && (val & 0x7) == ((val >> 4) & 0x7)) {
|
|
+ dev_err(&client->dev,
|
|
+ "duplicate addresses 0x%x, use force_subclient\n", 0x48 + (val & 0x7));
|
|
+ return -ENODEV;
|
|
}
|
|
|
|
+ if (!(val & 0x08))
|
|
+ devm_i2c_new_dummy_device(&client->dev, adapter, 0x48 + (val & 0x7));
|
|
+
|
|
+ if (!(val & 0x80))
|
|
+ devm_i2c_new_dummy_device(&client->dev, adapter, 0x48 + ((val >> 4) & 0x7));
|
|
+
|
|
return 0;
|
|
}
|
|
|
|
diff --git a/drivers/hwmon/w83792d.c b/drivers/hwmon/w83792d.c
|
|
index 7fc8a1160c8f9..f91db4be2fc79 100644
|
|
--- a/drivers/hwmon/w83792d.c
|
|
+++ b/drivers/hwmon/w83792d.c
|
|
@@ -264,9 +264,6 @@ struct w83792d_data {
|
|
char valid; /* !=0 if following fields are valid */
|
|
unsigned long last_updated; /* In jiffies */
|
|
|
|
- /* array of 2 pointers to subclients */
|
|
- struct i2c_client *lm75[2];
|
|
-
|
|
u8 in[9]; /* Register value */
|
|
u8 in_max[9]; /* Register value */
|
|
u8 in_min[9]; /* Register value */
|
|
@@ -928,7 +925,6 @@ w83792d_detect_subclients(struct i2c_client *new_client)
|
|
int address = new_client->addr;
|
|
u8 val;
|
|
struct i2c_adapter *adapter = new_client->adapter;
|
|
- struct w83792d_data *data = i2c_get_clientdata(new_client);
|
|
|
|
id = i2c_adapter_id(adapter);
|
|
if (force_subclients[0] == id && force_subclients[1] == address) {
|
|
@@ -947,21 +943,19 @@ w83792d_detect_subclients(struct i2c_client *new_client)
|
|
}
|
|
|
|
val = w83792d_read_value(new_client, W83792D_REG_I2C_SUBADDR);
|
|
- if (!(val & 0x08))
|
|
- data->lm75[0] = devm_i2c_new_dummy_device(&new_client->dev, adapter,
|
|
- 0x48 + (val & 0x7));
|
|
- if (!(val & 0x80)) {
|
|
- if (!IS_ERR(data->lm75[0]) &&
|
|
- ((val & 0x7) == ((val >> 4) & 0x7))) {
|
|
- dev_err(&new_client->dev,
|
|
- "duplicate addresses 0x%x, use force_subclient\n",
|
|
- data->lm75[0]->addr);
|
|
- return -ENODEV;
|
|
- }
|
|
- data->lm75[1] = devm_i2c_new_dummy_device(&new_client->dev, adapter,
|
|
- 0x48 + ((val >> 4) & 0x7));
|
|
+
|
|
+ if (!(val & 0x88) && (val & 0x7) == ((val >> 4) & 0x7)) {
|
|
+ dev_err(&new_client->dev,
|
|
+ "duplicate addresses 0x%x, use force_subclient\n", 0x48 + (val & 0x7));
|
|
+ return -ENODEV;
|
|
}
|
|
|
|
+ if (!(val & 0x08))
|
|
+ devm_i2c_new_dummy_device(&new_client->dev, adapter, 0x48 + (val & 0x7));
|
|
+
|
|
+ if (!(val & 0x80))
|
|
+ devm_i2c_new_dummy_device(&new_client->dev, adapter, 0x48 + ((val >> 4) & 0x7));
|
|
+
|
|
return 0;
|
|
}
|
|
|
|
diff --git a/drivers/hwmon/w83793.c b/drivers/hwmon/w83793.c
|
|
index 9df48b70c70c7..640330a3a8dc4 100644
|
|
--- a/drivers/hwmon/w83793.c
|
|
+++ b/drivers/hwmon/w83793.c
|
|
@@ -202,7 +202,6 @@ static inline s8 TEMP_TO_REG(long val, s8 min, s8 max)
|
|
}
|
|
|
|
struct w83793_data {
|
|
- struct i2c_client *lm75[2];
|
|
struct device *hwmon_dev;
|
|
struct mutex update_lock;
|
|
char valid; /* !=0 if following fields are valid */
|
|
@@ -1566,7 +1565,6 @@ w83793_detect_subclients(struct i2c_client *client)
|
|
int address = client->addr;
|
|
u8 tmp;
|
|
struct i2c_adapter *adapter = client->adapter;
|
|
- struct w83793_data *data = i2c_get_clientdata(client);
|
|
|
|
id = i2c_adapter_id(adapter);
|
|
if (force_subclients[0] == id && force_subclients[1] == address) {
|
|
@@ -1586,21 +1584,19 @@ w83793_detect_subclients(struct i2c_client *client)
|
|
}
|
|
|
|
tmp = w83793_read_value(client, W83793_REG_I2C_SUBADDR);
|
|
- if (!(tmp & 0x08))
|
|
- data->lm75[0] = devm_i2c_new_dummy_device(&client->dev, adapter,
|
|
- 0x48 + (tmp & 0x7));
|
|
- if (!(tmp & 0x80)) {
|
|
- if (!IS_ERR(data->lm75[0])
|
|
- && ((tmp & 0x7) == ((tmp >> 4) & 0x7))) {
|
|
- dev_err(&client->dev,
|
|
- "duplicate addresses 0x%x, "
|
|
- "use force_subclients\n", data->lm75[0]->addr);
|
|
- return -ENODEV;
|
|
- }
|
|
- data->lm75[1] = devm_i2c_new_dummy_device(&client->dev, adapter,
|
|
- 0x48 + ((tmp >> 4) & 0x7));
|
|
+
|
|
+ if (!(tmp & 0x88) && (tmp & 0x7) == ((tmp >> 4) & 0x7)) {
|
|
+ dev_err(&client->dev,
|
|
+ "duplicate addresses 0x%x, use force_subclient\n", 0x48 + (tmp & 0x7));
|
|
+ return -ENODEV;
|
|
}
|
|
|
|
+ if (!(tmp & 0x08))
|
|
+ devm_i2c_new_dummy_device(&client->dev, adapter, 0x48 + (tmp & 0x7));
|
|
+
|
|
+ if (!(tmp & 0x80))
|
|
+ devm_i2c_new_dummy_device(&client->dev, adapter, 0x48 + ((tmp >> 4) & 0x7));
|
|
+
|
|
return 0;
|
|
}
|
|
|
|
diff --git a/drivers/ipack/devices/ipoctal.c b/drivers/ipack/devices/ipoctal.c
|
|
index 9c2a4b5d30cfc..0f1dca623b5a1 100644
|
|
--- a/drivers/ipack/devices/ipoctal.c
|
|
+++ b/drivers/ipack/devices/ipoctal.c
|
|
@@ -35,6 +35,7 @@ struct ipoctal_channel {
|
|
unsigned int pointer_read;
|
|
unsigned int pointer_write;
|
|
struct tty_port tty_port;
|
|
+ bool tty_registered;
|
|
union scc2698_channel __iomem *regs;
|
|
union scc2698_block __iomem *block_regs;
|
|
unsigned int board_id;
|
|
@@ -83,22 +84,34 @@ static int ipoctal_port_activate(struct tty_port *port, struct tty_struct *tty)
|
|
return 0;
|
|
}
|
|
|
|
-static int ipoctal_open(struct tty_struct *tty, struct file *file)
|
|
+static int ipoctal_install(struct tty_driver *driver, struct tty_struct *tty)
|
|
{
|
|
struct ipoctal_channel *channel = dev_get_drvdata(tty->dev);
|
|
struct ipoctal *ipoctal = chan_to_ipoctal(channel, tty->index);
|
|
- int err;
|
|
-
|
|
- tty->driver_data = channel;
|
|
+ int res;
|
|
|
|
if (!ipack_get_carrier(ipoctal->dev))
|
|
return -EBUSY;
|
|
|
|
- err = tty_port_open(&channel->tty_port, tty, file);
|
|
- if (err)
|
|
- ipack_put_carrier(ipoctal->dev);
|
|
+ res = tty_standard_install(driver, tty);
|
|
+ if (res)
|
|
+ goto err_put_carrier;
|
|
+
|
|
+ tty->driver_data = channel;
|
|
+
|
|
+ return 0;
|
|
+
|
|
+err_put_carrier:
|
|
+ ipack_put_carrier(ipoctal->dev);
|
|
+
|
|
+ return res;
|
|
+}
|
|
+
|
|
+static int ipoctal_open(struct tty_struct *tty, struct file *file)
|
|
+{
|
|
+ struct ipoctal_channel *channel = tty->driver_data;
|
|
|
|
- return err;
|
|
+ return tty_port_open(&channel->tty_port, tty, file);
|
|
}
|
|
|
|
static void ipoctal_reset_stats(struct ipoctal_stats *stats)
|
|
@@ -266,7 +279,6 @@ static int ipoctal_inst_slot(struct ipoctal *ipoctal, unsigned int bus_nr,
|
|
int res;
|
|
int i;
|
|
struct tty_driver *tty;
|
|
- char name[20];
|
|
struct ipoctal_channel *channel;
|
|
struct ipack_region *region;
|
|
void __iomem *addr;
|
|
@@ -357,8 +369,11 @@ static int ipoctal_inst_slot(struct ipoctal *ipoctal, unsigned int bus_nr,
|
|
/* Fill struct tty_driver with ipoctal data */
|
|
tty->owner = THIS_MODULE;
|
|
tty->driver_name = KBUILD_MODNAME;
|
|
- sprintf(name, KBUILD_MODNAME ".%d.%d.", bus_nr, slot);
|
|
- tty->name = name;
|
|
+ tty->name = kasprintf(GFP_KERNEL, KBUILD_MODNAME ".%d.%d.", bus_nr, slot);
|
|
+ if (!tty->name) {
|
|
+ res = -ENOMEM;
|
|
+ goto err_put_driver;
|
|
+ }
|
|
tty->major = 0;
|
|
|
|
tty->minor_start = 0;
|
|
@@ -374,8 +389,7 @@ static int ipoctal_inst_slot(struct ipoctal *ipoctal, unsigned int bus_nr,
|
|
res = tty_register_driver(tty);
|
|
if (res) {
|
|
dev_err(&ipoctal->dev->dev, "Can't register tty driver.\n");
|
|
- put_tty_driver(tty);
|
|
- return res;
|
|
+ goto err_free_name;
|
|
}
|
|
|
|
/* Save struct tty_driver for use it when uninstalling the device */
|
|
@@ -386,7 +400,9 @@ static int ipoctal_inst_slot(struct ipoctal *ipoctal, unsigned int bus_nr,
|
|
|
|
channel = &ipoctal->channel[i];
|
|
tty_port_init(&channel->tty_port);
|
|
- tty_port_alloc_xmit_buf(&channel->tty_port);
|
|
+ res = tty_port_alloc_xmit_buf(&channel->tty_port);
|
|
+ if (res)
|
|
+ continue;
|
|
channel->tty_port.ops = &ipoctal_tty_port_ops;
|
|
|
|
ipoctal_reset_stats(&channel->stats);
|
|
@@ -394,13 +410,15 @@ static int ipoctal_inst_slot(struct ipoctal *ipoctal, unsigned int bus_nr,
|
|
spin_lock_init(&channel->lock);
|
|
channel->pointer_read = 0;
|
|
channel->pointer_write = 0;
|
|
- tty_dev = tty_port_register_device(&channel->tty_port, tty, i, NULL);
|
|
+ tty_dev = tty_port_register_device_attr(&channel->tty_port, tty,
|
|
+ i, NULL, channel, NULL);
|
|
if (IS_ERR(tty_dev)) {
|
|
dev_err(&ipoctal->dev->dev, "Failed to register tty device.\n");
|
|
+ tty_port_free_xmit_buf(&channel->tty_port);
|
|
tty_port_destroy(&channel->tty_port);
|
|
continue;
|
|
}
|
|
- dev_set_drvdata(tty_dev, channel);
|
|
+ channel->tty_registered = true;
|
|
}
|
|
|
|
/*
|
|
@@ -412,6 +430,13 @@ static int ipoctal_inst_slot(struct ipoctal *ipoctal, unsigned int bus_nr,
|
|
ipoctal_irq_handler, ipoctal);
|
|
|
|
return 0;
|
|
+
|
|
+err_free_name:
|
|
+ kfree(tty->name);
|
|
+err_put_driver:
|
|
+ put_tty_driver(tty);
|
|
+
|
|
+ return res;
|
|
}
|
|
|
|
static inline int ipoctal_copy_write_buffer(struct ipoctal_channel *channel,
|
|
@@ -652,6 +677,7 @@ static void ipoctal_cleanup(struct tty_struct *tty)
|
|
|
|
static const struct tty_operations ipoctal_fops = {
|
|
.ioctl = NULL,
|
|
+ .install = ipoctal_install,
|
|
.open = ipoctal_open,
|
|
.close = ipoctal_close,
|
|
.write = ipoctal_write_tty,
|
|
@@ -694,12 +720,17 @@ static void __ipoctal_remove(struct ipoctal *ipoctal)
|
|
|
|
for (i = 0; i < NR_CHANNELS; i++) {
|
|
struct ipoctal_channel *channel = &ipoctal->channel[i];
|
|
+
|
|
+ if (!channel->tty_registered)
|
|
+ continue;
|
|
+
|
|
tty_unregister_device(ipoctal->tty_drv, i);
|
|
tty_port_free_xmit_buf(&channel->tty_port);
|
|
tty_port_destroy(&channel->tty_port);
|
|
}
|
|
|
|
tty_unregister_driver(ipoctal->tty_drv);
|
|
+ kfree(ipoctal->tty_drv->name);
|
|
put_tty_driver(ipoctal->tty_drv);
|
|
kfree(ipoctal);
|
|
}
|
|
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c
|
|
index db9c8f943811b..ffd1018d43fbe 100644
|
|
--- a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c
|
|
+++ b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c
|
|
@@ -452,6 +452,11 @@ static int hns3_nic_net_open(struct net_device *netdev)
|
|
if (hns3_nic_resetting(netdev))
|
|
return -EBUSY;
|
|
|
|
+ if (!test_bit(HNS3_NIC_STATE_DOWN, &priv->state)) {
|
|
+ netdev_warn(netdev, "net open repeatedly!\n");
|
|
+ return 0;
|
|
+ }
|
|
+
|
|
netif_carrier_off(netdev);
|
|
|
|
ret = hns3_nic_set_real_num_queue(netdev);
|
|
diff --git a/drivers/net/ethernet/intel/e100.c b/drivers/net/ethernet/intel/e100.c
|
|
index 911b3d2a94e1c..70962967d7141 100644
|
|
--- a/drivers/net/ethernet/intel/e100.c
|
|
+++ b/drivers/net/ethernet/intel/e100.c
|
|
@@ -2435,11 +2435,15 @@ static void e100_get_drvinfo(struct net_device *netdev,
|
|
sizeof(info->bus_info));
|
|
}
|
|
|
|
-#define E100_PHY_REGS 0x1C
|
|
+#define E100_PHY_REGS 0x1D
|
|
static int e100_get_regs_len(struct net_device *netdev)
|
|
{
|
|
struct nic *nic = netdev_priv(netdev);
|
|
- return 1 + E100_PHY_REGS + sizeof(nic->mem->dump_buf);
|
|
+
|
|
+ /* We know the number of registers, and the size of the dump buffer.
|
|
+ * Calculate the total size in bytes.
|
|
+ */
|
|
+ return (1 + E100_PHY_REGS) * sizeof(u32) + sizeof(nic->mem->dump_buf);
|
|
}
|
|
|
|
static void e100_get_regs(struct net_device *netdev,
|
|
@@ -2453,14 +2457,18 @@ static void e100_get_regs(struct net_device *netdev,
|
|
buff[0] = ioread8(&nic->csr->scb.cmd_hi) << 24 |
|
|
ioread8(&nic->csr->scb.cmd_lo) << 16 |
|
|
ioread16(&nic->csr->scb.status);
|
|
- for (i = E100_PHY_REGS; i >= 0; i--)
|
|
- buff[1 + E100_PHY_REGS - i] =
|
|
- mdio_read(netdev, nic->mii.phy_id, i);
|
|
+ for (i = 0; i < E100_PHY_REGS; i++)
|
|
+ /* Note that we read the registers in reverse order. This
|
|
+ * ordering is the ABI apparently used by ethtool and other
|
|
+ * applications.
|
|
+ */
|
|
+ buff[1 + i] = mdio_read(netdev, nic->mii.phy_id,
|
|
+ E100_PHY_REGS - 1 - i);
|
|
memset(nic->mem->dump_buf, 0, sizeof(nic->mem->dump_buf));
|
|
e100_exec_cb(nic, NULL, e100_dump);
|
|
msleep(10);
|
|
- memcpy(&buff[2 + E100_PHY_REGS], nic->mem->dump_buf,
|
|
- sizeof(nic->mem->dump_buf));
|
|
+ memcpy(&buff[1 + E100_PHY_REGS], nic->mem->dump_buf,
|
|
+ sizeof(nic->mem->dump_buf));
|
|
}
|
|
|
|
static void e100_get_wol(struct net_device *netdev, struct ethtool_wolinfo *wol)
|
|
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
|
|
index e09851c7da9b8..835ac178bc8c0 100644
|
|
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
|
|
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
|
|
@@ -4855,8 +4855,6 @@ int stmmac_resume(struct device *dev)
|
|
stmmac_mdio_reset(priv->mii);
|
|
}
|
|
|
|
- netif_device_attach(ndev);
|
|
-
|
|
mutex_lock(&priv->lock);
|
|
|
|
stmmac_reset_queues_param(priv);
|
|
@@ -4880,6 +4878,8 @@ int stmmac_resume(struct device *dev)
|
|
|
|
phylink_mac_change(priv->phylink, true);
|
|
|
|
+ netif_device_attach(ndev);
|
|
+
|
|
return 0;
|
|
}
|
|
EXPORT_SYMBOL_GPL(stmmac_resume);
|
|
diff --git a/drivers/net/usb/hso.c b/drivers/net/usb/hso.c
|
|
index 9ad1f093c4ae1..31200275a0640 100644
|
|
--- a/drivers/net/usb/hso.c
|
|
+++ b/drivers/net/usb/hso.c
|
|
@@ -2497,7 +2497,7 @@ static struct hso_device *hso_create_net_device(struct usb_interface *interface,
|
|
hso_net_init);
|
|
if (!net) {
|
|
dev_err(&interface->dev, "Unable to create ethernet device\n");
|
|
- goto exit;
|
|
+ goto err_hso_dev;
|
|
}
|
|
|
|
hso_net = netdev_priv(net);
|
|
@@ -2510,13 +2510,13 @@ static struct hso_device *hso_create_net_device(struct usb_interface *interface,
|
|
USB_DIR_IN);
|
|
if (!hso_net->in_endp) {
|
|
dev_err(&interface->dev, "Can't find BULK IN endpoint\n");
|
|
- goto exit;
|
|
+ goto err_net;
|
|
}
|
|
hso_net->out_endp = hso_get_ep(interface, USB_ENDPOINT_XFER_BULK,
|
|
USB_DIR_OUT);
|
|
if (!hso_net->out_endp) {
|
|
dev_err(&interface->dev, "Can't find BULK OUT endpoint\n");
|
|
- goto exit;
|
|
+ goto err_net;
|
|
}
|
|
SET_NETDEV_DEV(net, &interface->dev);
|
|
SET_NETDEV_DEVTYPE(net, &hso_type);
|
|
@@ -2525,18 +2525,18 @@ static struct hso_device *hso_create_net_device(struct usb_interface *interface,
|
|
for (i = 0; i < MUX_BULK_RX_BUF_COUNT; i++) {
|
|
hso_net->mux_bulk_rx_urb_pool[i] = usb_alloc_urb(0, GFP_KERNEL);
|
|
if (!hso_net->mux_bulk_rx_urb_pool[i])
|
|
- goto exit;
|
|
+ goto err_mux_bulk_rx;
|
|
hso_net->mux_bulk_rx_buf_pool[i] = kzalloc(MUX_BULK_RX_BUF_SIZE,
|
|
GFP_KERNEL);
|
|
if (!hso_net->mux_bulk_rx_buf_pool[i])
|
|
- goto exit;
|
|
+ goto err_mux_bulk_rx;
|
|
}
|
|
hso_net->mux_bulk_tx_urb = usb_alloc_urb(0, GFP_KERNEL);
|
|
if (!hso_net->mux_bulk_tx_urb)
|
|
- goto exit;
|
|
+ goto err_mux_bulk_rx;
|
|
hso_net->mux_bulk_tx_buf = kzalloc(MUX_BULK_TX_BUF_SIZE, GFP_KERNEL);
|
|
if (!hso_net->mux_bulk_tx_buf)
|
|
- goto exit;
|
|
+ goto err_free_tx_urb;
|
|
|
|
add_net_device(hso_dev);
|
|
|
|
@@ -2544,7 +2544,7 @@ static struct hso_device *hso_create_net_device(struct usb_interface *interface,
|
|
result = register_netdev(net);
|
|
if (result) {
|
|
dev_err(&interface->dev, "Failed to register device\n");
|
|
- goto exit;
|
|
+ goto err_free_tx_buf;
|
|
}
|
|
|
|
hso_log_port(hso_dev);
|
|
@@ -2552,8 +2552,21 @@ static struct hso_device *hso_create_net_device(struct usb_interface *interface,
|
|
hso_create_rfkill(hso_dev, interface);
|
|
|
|
return hso_dev;
|
|
-exit:
|
|
- hso_free_net_device(hso_dev);
|
|
+
|
|
+err_free_tx_buf:
|
|
+ remove_net_device(hso_dev);
|
|
+ kfree(hso_net->mux_bulk_tx_buf);
|
|
+err_free_tx_urb:
|
|
+ usb_free_urb(hso_net->mux_bulk_tx_urb);
|
|
+err_mux_bulk_rx:
|
|
+ for (i = 0; i < MUX_BULK_RX_BUF_COUNT; i++) {
|
|
+ usb_free_urb(hso_net->mux_bulk_rx_urb_pool[i]);
|
|
+ kfree(hso_net->mux_bulk_rx_buf_pool[i]);
|
|
+ }
|
|
+err_net:
|
|
+ free_netdev(net);
|
|
+err_hso_dev:
|
|
+ kfree(hso_dev);
|
|
return NULL;
|
|
}
|
|
|
|
diff --git a/drivers/net/wireless/mac80211_hwsim.c b/drivers/net/wireless/mac80211_hwsim.c
|
|
index 1033513d3d9de..07b070b14d75d 100644
|
|
--- a/drivers/net/wireless/mac80211_hwsim.c
|
|
+++ b/drivers/net/wireless/mac80211_hwsim.c
|
|
@@ -1603,8 +1603,8 @@ mac80211_hwsim_beacon(struct hrtimer *timer)
|
|
bcn_int -= data->bcn_delta;
|
|
data->bcn_delta = 0;
|
|
}
|
|
- hrtimer_forward(&data->beacon_timer, hrtimer_get_expires(timer),
|
|
- ns_to_ktime(bcn_int * NSEC_PER_USEC));
|
|
+ hrtimer_forward_now(&data->beacon_timer,
|
|
+ ns_to_ktime(bcn_int * NSEC_PER_USEC));
|
|
return HRTIMER_RESTART;
|
|
}
|
|
|
|
diff --git a/drivers/nvdimm/pmem.c b/drivers/nvdimm/pmem.c
|
|
index f9f76f6ba07b1..7e65306b2bf24 100644
|
|
--- a/drivers/nvdimm/pmem.c
|
|
+++ b/drivers/nvdimm/pmem.c
|
|
@@ -423,11 +423,11 @@ static int pmem_attach_disk(struct device *dev,
|
|
pmem->pfn_flags |= PFN_MAP;
|
|
memcpy(&bb_res, &pmem->pgmap.res, sizeof(bb_res));
|
|
} else {
|
|
+ addr = devm_memremap(dev, pmem->phys_addr,
|
|
+ pmem->size, ARCH_MEMREMAP_PMEM);
|
|
if (devm_add_action_or_reset(dev, pmem_release_queue,
|
|
&pmem->pgmap))
|
|
return -ENOMEM;
|
|
- addr = devm_memremap(dev, pmem->phys_addr,
|
|
- pmem->size, ARCH_MEMREMAP_PMEM);
|
|
memcpy(&bb_res, &nsio->res, sizeof(bb_res));
|
|
}
|
|
|
|
diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c
|
|
index f28213b625279..a41d04c57642d 100644
|
|
--- a/drivers/pci/probe.c
|
|
+++ b/drivers/pci/probe.c
|
|
@@ -564,7 +564,7 @@ static struct pci_bus *pci_alloc_bus(struct pci_bus *parent)
|
|
return b;
|
|
}
|
|
|
|
-static void devm_pci_release_host_bridge_dev(struct device *dev)
|
|
+static void pci_release_host_bridge_dev(struct device *dev)
|
|
{
|
|
struct pci_host_bridge *bridge = to_pci_host_bridge(dev);
|
|
|
|
@@ -573,12 +573,7 @@ static void devm_pci_release_host_bridge_dev(struct device *dev)
|
|
|
|
pci_free_resource_list(&bridge->windows);
|
|
pci_free_resource_list(&bridge->dma_ranges);
|
|
-}
|
|
-
|
|
-static void pci_release_host_bridge_dev(struct device *dev)
|
|
-{
|
|
- devm_pci_release_host_bridge_dev(dev);
|
|
- kfree(to_pci_host_bridge(dev));
|
|
+ kfree(bridge);
|
|
}
|
|
|
|
static void pci_init_host_bridge(struct pci_host_bridge *bridge)
|
|
@@ -597,6 +592,8 @@ static void pci_init_host_bridge(struct pci_host_bridge *bridge)
|
|
bridge->native_shpc_hotplug = 1;
|
|
bridge->native_pme = 1;
|
|
bridge->native_ltr = 1;
|
|
+
|
|
+ device_initialize(&bridge->dev);
|
|
}
|
|
|
|
struct pci_host_bridge *pci_alloc_host_bridge(size_t priv)
|
|
@@ -614,17 +611,25 @@ struct pci_host_bridge *pci_alloc_host_bridge(size_t priv)
|
|
}
|
|
EXPORT_SYMBOL(pci_alloc_host_bridge);
|
|
|
|
+static void devm_pci_alloc_host_bridge_release(void *data)
|
|
+{
|
|
+ pci_free_host_bridge(data);
|
|
+}
|
|
+
|
|
struct pci_host_bridge *devm_pci_alloc_host_bridge(struct device *dev,
|
|
size_t priv)
|
|
{
|
|
+ int ret;
|
|
struct pci_host_bridge *bridge;
|
|
|
|
- bridge = devm_kzalloc(dev, sizeof(*bridge) + priv, GFP_KERNEL);
|
|
+ bridge = pci_alloc_host_bridge(priv);
|
|
if (!bridge)
|
|
return NULL;
|
|
|
|
- pci_init_host_bridge(bridge);
|
|
- bridge->dev.release = devm_pci_release_host_bridge_dev;
|
|
+ ret = devm_add_action_or_reset(dev, devm_pci_alloc_host_bridge_release,
|
|
+ bridge);
|
|
+ if (ret)
|
|
+ return NULL;
|
|
|
|
return bridge;
|
|
}
|
|
@@ -632,10 +637,7 @@ EXPORT_SYMBOL(devm_pci_alloc_host_bridge);
|
|
|
|
void pci_free_host_bridge(struct pci_host_bridge *bridge)
|
|
{
|
|
- pci_free_resource_list(&bridge->windows);
|
|
- pci_free_resource_list(&bridge->dma_ranges);
|
|
-
|
|
- kfree(bridge);
|
|
+ put_device(&bridge->dev);
|
|
}
|
|
EXPORT_SYMBOL(pci_free_host_bridge);
|
|
|
|
@@ -866,7 +868,7 @@ static int pci_register_host_bridge(struct pci_host_bridge *bridge)
|
|
if (err)
|
|
goto free;
|
|
|
|
- err = device_register(&bridge->dev);
|
|
+ err = device_add(&bridge->dev);
|
|
if (err) {
|
|
put_device(&bridge->dev);
|
|
goto free;
|
|
@@ -933,7 +935,7 @@ static int pci_register_host_bridge(struct pci_host_bridge *bridge)
|
|
|
|
unregister:
|
|
put_device(&bridge->dev);
|
|
- device_unregister(&bridge->dev);
|
|
+ device_del(&bridge->dev);
|
|
|
|
free:
|
|
kfree(bus);
|
|
@@ -2945,7 +2947,7 @@ struct pci_bus *pci_create_root_bus(struct device *parent, int bus,
|
|
return bridge->bus;
|
|
|
|
err_out:
|
|
- kfree(bridge);
|
|
+ put_device(&bridge->dev);
|
|
return NULL;
|
|
}
|
|
EXPORT_SYMBOL_GPL(pci_create_root_bus);
|
|
diff --git a/drivers/pci/remove.c b/drivers/pci/remove.c
|
|
index e9c6b120cf451..95dec03d9f2a9 100644
|
|
--- a/drivers/pci/remove.c
|
|
+++ b/drivers/pci/remove.c
|
|
@@ -160,6 +160,6 @@ void pci_remove_root_bus(struct pci_bus *bus)
|
|
host_bridge->bus = NULL;
|
|
|
|
/* remove the host bridge */
|
|
- device_unregister(&host_bridge->dev);
|
|
+ device_del(&host_bridge->dev);
|
|
}
|
|
EXPORT_SYMBOL_GPL(pci_remove_root_bus);
|
|
diff --git a/drivers/scsi/csiostor/csio_init.c b/drivers/scsi/csiostor/csio_init.c
|
|
index a6dd704d7f2de..1b8ccadc7cf67 100644
|
|
--- a/drivers/scsi/csiostor/csio_init.c
|
|
+++ b/drivers/scsi/csiostor/csio_init.c
|
|
@@ -1257,3 +1257,4 @@ MODULE_DEVICE_TABLE(pci, csio_pci_tbl);
|
|
MODULE_VERSION(CSIO_DRV_VERSION);
|
|
MODULE_FIRMWARE(FW_FNAME_T5);
|
|
MODULE_FIRMWARE(FW_FNAME_T6);
|
|
+MODULE_SOFTDEP("pre: cxgb4");
|
|
diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
|
|
index 0429ba5d7d23c..24396f4d5f2d3 100644
|
|
--- a/drivers/scsi/ufs/ufshcd.c
|
|
+++ b/drivers/scsi/ufs/ufshcd.c
|
|
@@ -320,8 +320,7 @@ static void ufshcd_add_query_upiu_trace(struct ufs_hba *hba, unsigned int tag,
|
|
static void ufshcd_add_tm_upiu_trace(struct ufs_hba *hba, unsigned int tag,
|
|
const char *str)
|
|
{
|
|
- int off = (int)tag - hba->nutrs;
|
|
- struct utp_task_req_desc *descp = &hba->utmrdl_base_addr[off];
|
|
+ struct utp_task_req_desc *descp = &hba->utmrdl_base_addr[tag];
|
|
|
|
trace_ufshcd_upiu(dev_name(hba->dev), str, &descp->req_header,
|
|
&descp->input_param1);
|
|
diff --git a/drivers/tty/vt/vt.c b/drivers/tty/vt/vt.c
|
|
index 404b80dc06b87..d1ab8561e2581 100644
|
|
--- a/drivers/tty/vt/vt.c
|
|
+++ b/drivers/tty/vt/vt.c
|
|
@@ -1215,8 +1215,25 @@ static int vc_do_resize(struct tty_struct *tty, struct vc_data *vc,
|
|
new_row_size = new_cols << 1;
|
|
new_screen_size = new_row_size * new_rows;
|
|
|
|
- if (new_cols == vc->vc_cols && new_rows == vc->vc_rows)
|
|
- return 0;
|
|
+ if (new_cols == vc->vc_cols && new_rows == vc->vc_rows) {
|
|
+ /*
|
|
+ * This function is being called here to cover the case
|
|
+ * where the userspace calls the FBIOPUT_VSCREENINFO twice,
|
|
+ * passing the same fb_var_screeninfo containing the fields
|
|
+ * yres/xres equal to a number non-multiple of vc_font.height
|
|
+ * and yres_virtual/xres_virtual equal to number lesser than the
|
|
+ * vc_font.height and yres/xres.
|
|
+ * In the second call, the struct fb_var_screeninfo isn't
|
|
+ * being modified by the underlying driver because of the
|
|
+ * if above, and this causes the fbcon_display->vrows to become
|
|
+ * negative and it eventually leads to out-of-bound
|
|
+ * access by the imageblit function.
|
|
+ * To give the correct values to the struct and to not have
|
|
+ * to deal with possible errors from the code below, we call
|
|
+ * the resize_screen here as well.
|
|
+ */
|
|
+ return resize_screen(vc, new_cols, new_rows, user);
|
|
+ }
|
|
|
|
if (new_screen_size > KMALLOC_MAX_SIZE || !new_screen_size)
|
|
return -EINVAL;
|
|
diff --git a/drivers/usb/cdns3/gadget.c b/drivers/usb/cdns3/gadget.c
|
|
index c3bf54cc530f9..296f2ee1b6803 100644
|
|
--- a/drivers/usb/cdns3/gadget.c
|
|
+++ b/drivers/usb/cdns3/gadget.c
|
|
@@ -807,6 +807,19 @@ static void cdns3_wa1_tray_restore_cycle_bit(struct cdns3_device *priv_dev,
|
|
cdns3_wa1_restore_cycle_bit(priv_ep);
|
|
}
|
|
|
|
+static void cdns3_rearm_drdy_if_needed(struct cdns3_endpoint *priv_ep)
|
|
+{
|
|
+ struct cdns3_device *priv_dev = priv_ep->cdns3_dev;
|
|
+
|
|
+ if (priv_dev->dev_ver < DEV_VER_V3)
|
|
+ return;
|
|
+
|
|
+ if (readl(&priv_dev->regs->ep_sts) & EP_STS_TRBERR) {
|
|
+ writel(EP_STS_TRBERR, &priv_dev->regs->ep_sts);
|
|
+ writel(EP_CMD_DRDY, &priv_dev->regs->ep_cmd);
|
|
+ }
|
|
+}
|
|
+
|
|
/**
|
|
* cdns3_ep_run_transfer - start transfer on no-default endpoint hardware
|
|
* @priv_ep: endpoint object
|
|
@@ -1003,6 +1016,7 @@ int cdns3_ep_run_transfer(struct cdns3_endpoint *priv_ep,
|
|
/*clearing TRBERR and EP_STS_DESCMIS before seting DRDY*/
|
|
writel(EP_STS_TRBERR | EP_STS_DESCMIS, &priv_dev->regs->ep_sts);
|
|
writel(EP_CMD_DRDY, &priv_dev->regs->ep_cmd);
|
|
+ cdns3_rearm_drdy_if_needed(priv_ep);
|
|
trace_cdns3_doorbell_epx(priv_ep->name,
|
|
readl(&priv_dev->regs->ep_traddr));
|
|
}
|
|
diff --git a/fs/binfmt_elf.c b/fs/binfmt_elf.c
|
|
index 7ce3cfd965d25..72cd871544ac0 100644
|
|
--- a/fs/binfmt_elf.c
|
|
+++ b/fs/binfmt_elf.c
|
|
@@ -583,7 +583,7 @@ static unsigned long load_elf_interp(struct elfhdr *interp_elf_ex,
|
|
|
|
vaddr = eppnt->p_vaddr;
|
|
if (interp_elf_ex->e_type == ET_EXEC || load_addr_set)
|
|
- elf_type |= MAP_FIXED_NOREPLACE;
|
|
+ elf_type |= MAP_FIXED;
|
|
else if (no_base && interp_elf_ex->e_type == ET_DYN)
|
|
load_addr = -vaddr;
|
|
|
|
diff --git a/fs/debugfs/inode.c b/fs/debugfs/inode.c
|
|
index 1c74a7cbf5b19..e595a29bf46e3 100644
|
|
--- a/fs/debugfs/inode.c
|
|
+++ b/fs/debugfs/inode.c
|
|
@@ -522,7 +522,7 @@ struct dentry *debugfs_create_file_size(const char *name, umode_t mode,
|
|
{
|
|
struct dentry *de = debugfs_create_file(name, mode, parent, data, fops);
|
|
|
|
- if (de)
|
|
+ if (!IS_ERR(de))
|
|
d_inode(de)->i_size = file_size;
|
|
return de;
|
|
}
|
|
diff --git a/fs/ext4/dir.c b/fs/ext4/dir.c
|
|
index 0589e914663fb..e8275b5d27439 100644
|
|
--- a/fs/ext4/dir.c
|
|
+++ b/fs/ext4/dir.c
|
|
@@ -536,7 +536,7 @@ static int ext4_dx_readdir(struct file *file, struct dir_context *ctx)
|
|
struct dir_private_info *info = file->private_data;
|
|
struct inode *inode = file_inode(file);
|
|
struct fname *fname;
|
|
- int ret;
|
|
+ int ret = 0;
|
|
|
|
if (!info) {
|
|
info = ext4_htree_create_dir_info(file, ctx->pos);
|
|
@@ -584,7 +584,7 @@ static int ext4_dx_readdir(struct file *file, struct dir_context *ctx)
|
|
info->curr_minor_hash,
|
|
&info->next_hash);
|
|
if (ret < 0)
|
|
- return ret;
|
|
+ goto finished;
|
|
if (ret == 0) {
|
|
ctx->pos = ext4_get_htree_eof(file);
|
|
break;
|
|
@@ -615,7 +615,7 @@ static int ext4_dx_readdir(struct file *file, struct dir_context *ctx)
|
|
}
|
|
finished:
|
|
info->last_pos = ctx->pos;
|
|
- return 0;
|
|
+ return ret < 0 ? ret : 0;
|
|
}
|
|
|
|
static int ext4_dir_open(struct inode * inode, struct file * filp)
|
|
diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
|
|
index 1429d01d836bb..48b467353f6f1 100644
|
|
--- a/fs/ext4/inode.c
|
|
+++ b/fs/ext4/inode.c
|
|
@@ -1782,6 +1782,7 @@ static int ext4_insert_delayed_block(struct inode *inode, ext4_lblk_t lblk)
|
|
struct ext4_sb_info *sbi = EXT4_SB(inode->i_sb);
|
|
int ret;
|
|
bool allocated = false;
|
|
+ bool reserved = false;
|
|
|
|
/*
|
|
* If the cluster containing lblk is shared with a delayed,
|
|
@@ -1798,6 +1799,7 @@ static int ext4_insert_delayed_block(struct inode *inode, ext4_lblk_t lblk)
|
|
ret = ext4_da_reserve_space(inode);
|
|
if (ret != 0) /* ENOSPC */
|
|
goto errout;
|
|
+ reserved = true;
|
|
} else { /* bigalloc */
|
|
if (!ext4_es_scan_clu(inode, &ext4_es_is_delonly, lblk)) {
|
|
if (!ext4_es_scan_clu(inode,
|
|
@@ -1810,6 +1812,7 @@ static int ext4_insert_delayed_block(struct inode *inode, ext4_lblk_t lblk)
|
|
ret = ext4_da_reserve_space(inode);
|
|
if (ret != 0) /* ENOSPC */
|
|
goto errout;
|
|
+ reserved = true;
|
|
} else {
|
|
allocated = true;
|
|
}
|
|
@@ -1820,6 +1823,8 @@ static int ext4_insert_delayed_block(struct inode *inode, ext4_lblk_t lblk)
|
|
}
|
|
|
|
ret = ext4_es_insert_delayed_block(inode, lblk, allocated);
|
|
+ if (ret && reserved)
|
|
+ ext4_da_release_space(inode, 1);
|
|
|
|
errout:
|
|
return ret;
|
|
diff --git a/fs/ext4/super.c b/fs/ext4/super.c
|
|
index ce8372ceaa43e..1211ae203face 100644
|
|
--- a/fs/ext4/super.c
|
|
+++ b/fs/ext4/super.c
|
|
@@ -1141,6 +1141,12 @@ static void ext4_destroy_inode(struct inode *inode)
|
|
true);
|
|
dump_stack();
|
|
}
|
|
+
|
|
+ if (EXT4_I(inode)->i_reserved_data_blocks)
|
|
+ ext4_msg(inode->i_sb, KERN_ERR,
|
|
+ "Inode %lu (%p): i_reserved_data_blocks (%u) not cleared!",
|
|
+ inode->i_ino, EXT4_I(inode),
|
|
+ EXT4_I(inode)->i_reserved_data_blocks);
|
|
}
|
|
|
|
static void init_once(void *foo)
|
|
@@ -2830,17 +2836,17 @@ static loff_t ext4_max_size(int blkbits, int has_huge_files)
|
|
*/
|
|
static loff_t ext4_max_bitmap_size(int bits, int has_huge_files)
|
|
{
|
|
- loff_t res = EXT4_NDIR_BLOCKS;
|
|
+ unsigned long long upper_limit, res = EXT4_NDIR_BLOCKS;
|
|
int meta_blocks;
|
|
- loff_t upper_limit;
|
|
- /* This is calculated to be the largest file size for a dense, block
|
|
+
|
|
+ /*
|
|
+ * This is calculated to be the largest file size for a dense, block
|
|
* mapped file such that the file's total number of 512-byte sectors,
|
|
* including data and all indirect blocks, does not exceed (2^48 - 1).
|
|
*
|
|
* __u32 i_blocks_lo and _u16 i_blocks_high represent the total
|
|
* number of 512-byte sectors of the file.
|
|
*/
|
|
-
|
|
if (!has_huge_files) {
|
|
/*
|
|
* !has_huge_files or implies that the inode i_block field
|
|
@@ -2883,7 +2889,7 @@ static loff_t ext4_max_bitmap_size(int bits, int has_huge_files)
|
|
if (res > MAX_LFS_FILESIZE)
|
|
res = MAX_LFS_FILESIZE;
|
|
|
|
- return res;
|
|
+ return (loff_t)res;
|
|
}
|
|
|
|
static ext4_fsblk_t descriptor_loc(struct super_block *sb,
|
|
diff --git a/fs/verity/enable.c b/fs/verity/enable.c
|
|
index eabc6ac199064..1370bfd17e870 100644
|
|
--- a/fs/verity/enable.c
|
|
+++ b/fs/verity/enable.c
|
|
@@ -136,7 +136,7 @@ static int build_merkle_tree(struct inode *inode,
|
|
* (level 0) and ascending to the root node (level 'num_levels - 1').
|
|
* Then at the end (level 'num_levels'), calculate the root hash.
|
|
*/
|
|
- blocks = (inode->i_size + params->block_size - 1) >>
|
|
+ blocks = ((u64)inode->i_size + params->block_size - 1) >>
|
|
params->log_blocksize;
|
|
for (level = 0; level <= params->num_levels; level++) {
|
|
err = build_merkle_tree_level(inode, level, blocks, params,
|
|
diff --git a/fs/verity/open.c b/fs/verity/open.c
|
|
index 63d1004b688cb..6200826107c24 100644
|
|
--- a/fs/verity/open.c
|
|
+++ b/fs/verity/open.c
|
|
@@ -89,7 +89,7 @@ int fsverity_init_merkle_tree_params(struct merkle_tree_params *params,
|
|
*/
|
|
|
|
/* Compute number of levels and the number of blocks in each level */
|
|
- blocks = (inode->i_size + params->block_size - 1) >> log_blocksize;
|
|
+ blocks = ((u64)inode->i_size + params->block_size - 1) >> log_blocksize;
|
|
pr_debug("Data is %lld bytes (%llu blocks)\n", inode->i_size, blocks);
|
|
while (blocks > 1) {
|
|
if (params->num_levels >= FS_VERITY_MAX_LEVELS) {
|
|
diff --git a/include/net/ip_fib.h b/include/net/ip_fib.h
|
|
index ffbae7683450a..cb6c125628990 100644
|
|
--- a/include/net/ip_fib.h
|
|
+++ b/include/net/ip_fib.h
|
|
@@ -524,5 +524,5 @@ int ip_valid_fib_dump_req(struct net *net, const struct nlmsghdr *nlh,
|
|
int fib_nexthop_info(struct sk_buff *skb, const struct fib_nh_common *nh,
|
|
u8 rt_family, unsigned char *flags, bool skip_oif);
|
|
int fib_add_nexthop(struct sk_buff *skb, const struct fib_nh_common *nh,
|
|
- int nh_weight, u8 rt_family);
|
|
+ int nh_weight, u8 rt_family, u32 nh_tclassid);
|
|
#endif /* _NET_FIB_H */
|
|
diff --git a/include/net/nexthop.h b/include/net/nexthop.h
|
|
index 18a5aca264767..5ad614793af26 100644
|
|
--- a/include/net/nexthop.h
|
|
+++ b/include/net/nexthop.h
|
|
@@ -173,7 +173,7 @@ int nexthop_mpath_fill_node(struct sk_buff *skb, struct nexthop *nh,
|
|
struct fib_nh_common *nhc = &nhi->fib_nhc;
|
|
int weight = nhg->nh_entries[i].weight;
|
|
|
|
- if (fib_add_nexthop(skb, nhc, weight, rt_family) < 0)
|
|
+ if (fib_add_nexthop(skb, nhc, weight, rt_family, 0) < 0)
|
|
return -EMSGSIZE;
|
|
}
|
|
|
|
diff --git a/include/net/sock.h b/include/net/sock.h
|
|
index d3dd89b6e2cba..079b5f6f13d81 100644
|
|
--- a/include/net/sock.h
|
|
+++ b/include/net/sock.h
|
|
@@ -470,8 +470,10 @@ struct sock {
|
|
u32 sk_ack_backlog;
|
|
u32 sk_max_ack_backlog;
|
|
kuid_t sk_uid;
|
|
+ spinlock_t sk_peer_lock;
|
|
struct pid *sk_peer_pid;
|
|
const struct cred *sk_peer_cred;
|
|
+
|
|
long sk_rcvtimeo;
|
|
ktime_t sk_stamp;
|
|
#if BITS_PER_LONG==32
|
|
diff --git a/kernel/sched/cpufreq_schedutil.c b/kernel/sched/cpufreq_schedutil.c
|
|
index 4cb80e6042c4f..831fee509404e 100644
|
|
--- a/kernel/sched/cpufreq_schedutil.c
|
|
+++ b/kernel/sched/cpufreq_schedutil.c
|
|
@@ -624,9 +624,17 @@ static struct attribute *sugov_attrs[] = {
|
|
};
|
|
ATTRIBUTE_GROUPS(sugov);
|
|
|
|
+static void sugov_tunables_free(struct kobject *kobj)
|
|
+{
|
|
+ struct gov_attr_set *attr_set = container_of(kobj, struct gov_attr_set, kobj);
|
|
+
|
|
+ kfree(to_sugov_tunables(attr_set));
|
|
+}
|
|
+
|
|
static struct kobj_type sugov_tunables_ktype = {
|
|
.default_groups = sugov_groups,
|
|
.sysfs_ops = &governor_sysfs_ops,
|
|
+ .release = &sugov_tunables_free,
|
|
};
|
|
|
|
/********************** cpufreq governor interface *********************/
|
|
@@ -726,12 +734,10 @@ static struct sugov_tunables *sugov_tunables_alloc(struct sugov_policy *sg_polic
|
|
return tunables;
|
|
}
|
|
|
|
-static void sugov_tunables_free(struct sugov_tunables *tunables)
|
|
+static void sugov_clear_global_tunables(void)
|
|
{
|
|
if (!have_governor_per_policy())
|
|
global_tunables = NULL;
|
|
-
|
|
- kfree(tunables);
|
|
}
|
|
|
|
static int sugov_init(struct cpufreq_policy *policy)
|
|
@@ -794,7 +800,7 @@ out:
|
|
fail:
|
|
kobject_put(&tunables->attr_set.kobj);
|
|
policy->governor_data = NULL;
|
|
- sugov_tunables_free(tunables);
|
|
+ sugov_clear_global_tunables();
|
|
|
|
stop_kthread:
|
|
sugov_kthread_stop(sg_policy);
|
|
@@ -821,7 +827,7 @@ static void sugov_exit(struct cpufreq_policy *policy)
|
|
count = gov_attr_set_put(&tunables->attr_set, &sg_policy->tunables_hook);
|
|
policy->governor_data = NULL;
|
|
if (!count)
|
|
- sugov_tunables_free(tunables);
|
|
+ sugov_clear_global_tunables();
|
|
|
|
mutex_unlock(&global_tunables_lock);
|
|
|
|
diff --git a/net/core/sock.c b/net/core/sock.c
|
|
index 452883b28abab..57b7a10703c36 100644
|
|
--- a/net/core/sock.c
|
|
+++ b/net/core/sock.c
|
|
@@ -1181,6 +1181,16 @@ set_rcvbuf:
|
|
}
|
|
EXPORT_SYMBOL(sock_setsockopt);
|
|
|
|
+static const struct cred *sk_get_peer_cred(struct sock *sk)
|
|
+{
|
|
+ const struct cred *cred;
|
|
+
|
|
+ spin_lock(&sk->sk_peer_lock);
|
|
+ cred = get_cred(sk->sk_peer_cred);
|
|
+ spin_unlock(&sk->sk_peer_lock);
|
|
+
|
|
+ return cred;
|
|
+}
|
|
|
|
static void cred_to_ucred(struct pid *pid, const struct cred *cred,
|
|
struct ucred *ucred)
|
|
@@ -1355,7 +1365,11 @@ int sock_getsockopt(struct socket *sock, int level, int optname,
|
|
struct ucred peercred;
|
|
if (len > sizeof(peercred))
|
|
len = sizeof(peercred);
|
|
+
|
|
+ spin_lock(&sk->sk_peer_lock);
|
|
cred_to_ucred(sk->sk_peer_pid, sk->sk_peer_cred, &peercred);
|
|
+ spin_unlock(&sk->sk_peer_lock);
|
|
+
|
|
if (copy_to_user(optval, &peercred, len))
|
|
return -EFAULT;
|
|
goto lenout;
|
|
@@ -1363,20 +1377,23 @@ int sock_getsockopt(struct socket *sock, int level, int optname,
|
|
|
|
case SO_PEERGROUPS:
|
|
{
|
|
+ const struct cred *cred;
|
|
int ret, n;
|
|
|
|
- if (!sk->sk_peer_cred)
|
|
+ cred = sk_get_peer_cred(sk);
|
|
+ if (!cred)
|
|
return -ENODATA;
|
|
|
|
- n = sk->sk_peer_cred->group_info->ngroups;
|
|
+ n = cred->group_info->ngroups;
|
|
if (len < n * sizeof(gid_t)) {
|
|
len = n * sizeof(gid_t);
|
|
+ put_cred(cred);
|
|
return put_user(len, optlen) ? -EFAULT : -ERANGE;
|
|
}
|
|
len = n * sizeof(gid_t);
|
|
|
|
- ret = groups_to_user((gid_t __user *)optval,
|
|
- sk->sk_peer_cred->group_info);
|
|
+ ret = groups_to_user((gid_t __user *)optval, cred->group_info);
|
|
+ put_cred(cred);
|
|
if (ret)
|
|
return ret;
|
|
goto lenout;
|
|
@@ -1714,9 +1731,10 @@ static void __sk_destruct(struct rcu_head *head)
|
|
sk->sk_frag.page = NULL;
|
|
}
|
|
|
|
- if (sk->sk_peer_cred)
|
|
- put_cred(sk->sk_peer_cred);
|
|
+ /* We do not need to acquire sk->sk_peer_lock, we are the last user. */
|
|
+ put_cred(sk->sk_peer_cred);
|
|
put_pid(sk->sk_peer_pid);
|
|
+
|
|
if (likely(sk->sk_net_refcnt))
|
|
put_net(sock_net(sk));
|
|
sk_prot_free(sk->sk_prot_creator, sk);
|
|
@@ -2915,6 +2933,8 @@ void sock_init_data(struct socket *sock, struct sock *sk)
|
|
|
|
sk->sk_peer_pid = NULL;
|
|
sk->sk_peer_cred = NULL;
|
|
+ spin_lock_init(&sk->sk_peer_lock);
|
|
+
|
|
sk->sk_write_pending = 0;
|
|
sk->sk_rcvlowat = 1;
|
|
sk->sk_rcvtimeo = MAX_SCHEDULE_TIMEOUT;
|
|
diff --git a/net/ipv4/fib_semantics.c b/net/ipv4/fib_semantics.c
|
|
index b1b3220917ca0..dce85a9c20c60 100644
|
|
--- a/net/ipv4/fib_semantics.c
|
|
+++ b/net/ipv4/fib_semantics.c
|
|
@@ -1654,7 +1654,7 @@ EXPORT_SYMBOL_GPL(fib_nexthop_info);
|
|
|
|
#if IS_ENABLED(CONFIG_IP_ROUTE_MULTIPATH) || IS_ENABLED(CONFIG_IPV6)
|
|
int fib_add_nexthop(struct sk_buff *skb, const struct fib_nh_common *nhc,
|
|
- int nh_weight, u8 rt_family)
|
|
+ int nh_weight, u8 rt_family, u32 nh_tclassid)
|
|
{
|
|
const struct net_device *dev = nhc->nhc_dev;
|
|
struct rtnexthop *rtnh;
|
|
@@ -1672,6 +1672,9 @@ int fib_add_nexthop(struct sk_buff *skb, const struct fib_nh_common *nhc,
|
|
|
|
rtnh->rtnh_flags = flags;
|
|
|
|
+ if (nh_tclassid && nla_put_u32(skb, RTA_FLOW, nh_tclassid))
|
|
+ goto nla_put_failure;
|
|
+
|
|
/* length of rtnetlink header + attributes */
|
|
rtnh->rtnh_len = nlmsg_get_pos(skb) - (void *)rtnh;
|
|
|
|
@@ -1699,14 +1702,13 @@ static int fib_add_multipath(struct sk_buff *skb, struct fib_info *fi)
|
|
}
|
|
|
|
for_nexthops(fi) {
|
|
- if (fib_add_nexthop(skb, &nh->nh_common, nh->fib_nh_weight,
|
|
- AF_INET) < 0)
|
|
- goto nla_put_failure;
|
|
+ u32 nh_tclassid = 0;
|
|
#ifdef CONFIG_IP_ROUTE_CLASSID
|
|
- if (nh->nh_tclassid &&
|
|
- nla_put_u32(skb, RTA_FLOW, nh->nh_tclassid))
|
|
- goto nla_put_failure;
|
|
+ nh_tclassid = nh->nh_tclassid;
|
|
#endif
|
|
+ if (fib_add_nexthop(skb, &nh->nh_common, nh->fib_nh_weight,
|
|
+ AF_INET, nh_tclassid) < 0)
|
|
+ goto nla_put_failure;
|
|
} endfor_nexthops(fi);
|
|
|
|
mp_end:
|
|
diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c
|
|
index 6f277bd30ea3c..de04d99418850 100644
|
|
--- a/net/ipv4/udp.c
|
|
+++ b/net/ipv4/udp.c
|
|
@@ -981,7 +981,7 @@ int udp_sendmsg(struct sock *sk, struct msghdr *msg, size_t len)
|
|
__be16 dport;
|
|
u8 tos;
|
|
int err, is_udplite = IS_UDPLITE(sk);
|
|
- int corkreq = up->corkflag || msg->msg_flags&MSG_MORE;
|
|
+ int corkreq = READ_ONCE(up->corkflag) || msg->msg_flags&MSG_MORE;
|
|
int (*getfrag)(void *, char *, int, int, int, struct sk_buff *);
|
|
struct sk_buff *skb;
|
|
struct ip_options_data opt_copy;
|
|
@@ -1289,7 +1289,7 @@ int udp_sendpage(struct sock *sk, struct page *page, int offset,
|
|
}
|
|
|
|
up->len += size;
|
|
- if (!(up->corkflag || (flags&MSG_MORE)))
|
|
+ if (!(READ_ONCE(up->corkflag) || (flags&MSG_MORE)))
|
|
ret = udp_push_pending_frames(sk);
|
|
if (!ret)
|
|
ret = size;
|
|
@@ -2551,9 +2551,9 @@ int udp_lib_setsockopt(struct sock *sk, int level, int optname,
|
|
switch (optname) {
|
|
case UDP_CORK:
|
|
if (val != 0) {
|
|
- up->corkflag = 1;
|
|
+ WRITE_ONCE(up->corkflag, 1);
|
|
} else {
|
|
- up->corkflag = 0;
|
|
+ WRITE_ONCE(up->corkflag, 0);
|
|
lock_sock(sk);
|
|
push_pending_frames(sk);
|
|
release_sock(sk);
|
|
@@ -2676,7 +2676,7 @@ int udp_lib_getsockopt(struct sock *sk, int level, int optname,
|
|
|
|
switch (optname) {
|
|
case UDP_CORK:
|
|
- val = up->corkflag;
|
|
+ val = READ_ONCE(up->corkflag);
|
|
break;
|
|
|
|
case UDP_ENCAP:
|
|
diff --git a/net/ipv6/route.c b/net/ipv6/route.c
|
|
index 575bd0f1b0089..3fb259c20546e 100644
|
|
--- a/net/ipv6/route.c
|
|
+++ b/net/ipv6/route.c
|
|
@@ -5523,14 +5523,15 @@ static int rt6_fill_node(struct net *net, struct sk_buff *skb,
|
|
goto nla_put_failure;
|
|
|
|
if (fib_add_nexthop(skb, &rt->fib6_nh->nh_common,
|
|
- rt->fib6_nh->fib_nh_weight, AF_INET6) < 0)
|
|
+ rt->fib6_nh->fib_nh_weight, AF_INET6,
|
|
+ 0) < 0)
|
|
goto nla_put_failure;
|
|
|
|
list_for_each_entry_safe(sibling, next_sibling,
|
|
&rt->fib6_siblings, fib6_siblings) {
|
|
if (fib_add_nexthop(skb, &sibling->fib6_nh->nh_common,
|
|
sibling->fib6_nh->fib_nh_weight,
|
|
- AF_INET6) < 0)
|
|
+ AF_INET6, 0) < 0)
|
|
goto nla_put_failure;
|
|
}
|
|
|
|
diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c
|
|
index 776427e80efbd..5b8266f3e47f0 100644
|
|
--- a/net/ipv6/udp.c
|
|
+++ b/net/ipv6/udp.c
|
|
@@ -1231,7 +1231,7 @@ int udpv6_sendmsg(struct sock *sk, struct msghdr *msg, size_t len)
|
|
int addr_len = msg->msg_namelen;
|
|
bool connected = false;
|
|
int ulen = len;
|
|
- int corkreq = up->corkflag || msg->msg_flags&MSG_MORE;
|
|
+ int corkreq = READ_ONCE(up->corkflag) || msg->msg_flags&MSG_MORE;
|
|
int err;
|
|
int is_udplite = IS_UDPLITE(sk);
|
|
int (*getfrag)(void *, char *, int, int, int, struct sk_buff *);
|
|
diff --git a/net/mac80211/mesh_ps.c b/net/mac80211/mesh_ps.c
|
|
index 031e905f684a2..bf83f512f748b 100644
|
|
--- a/net/mac80211/mesh_ps.c
|
|
+++ b/net/mac80211/mesh_ps.c
|
|
@@ -2,6 +2,7 @@
|
|
/*
|
|
* Copyright 2012-2013, Marco Porsch <marco.porsch@s2005.tu-chemnitz.de>
|
|
* Copyright 2012-2013, cozybit Inc.
|
|
+ * Copyright (C) 2021 Intel Corporation
|
|
*/
|
|
|
|
#include "mesh.h"
|
|
@@ -584,7 +585,7 @@ void ieee80211_mps_frame_release(struct sta_info *sta,
|
|
|
|
/* only transmit to PS STA with announced, non-zero awake window */
|
|
if (test_sta_flag(sta, WLAN_STA_PS_STA) &&
|
|
- (!elems->awake_window || !le16_to_cpu(*elems->awake_window)))
|
|
+ (!elems->awake_window || !get_unaligned_le16(elems->awake_window)))
|
|
return;
|
|
|
|
if (!test_sta_flag(sta, WLAN_STA_MPSP_OWNER))
|
|
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c
|
|
index 4dfac7a25e5ad..d82d22b6a2a94 100644
|
|
--- a/net/mac80211/tx.c
|
|
+++ b/net/mac80211/tx.c
|
|
@@ -2156,7 +2156,11 @@ static bool ieee80211_parse_tx_radiotap(struct ieee80211_local *local,
|
|
}
|
|
|
|
vht_mcs = iterator.this_arg[4] >> 4;
|
|
+ if (vht_mcs > 11)
|
|
+ vht_mcs = 0;
|
|
vht_nss = iterator.this_arg[4] & 0xF;
|
|
+ if (!vht_nss || vht_nss > 8)
|
|
+ vht_nss = 1;
|
|
break;
|
|
|
|
/*
|
|
@@ -3325,6 +3329,14 @@ static bool ieee80211_amsdu_aggregate(struct ieee80211_sub_if_data *sdata,
|
|
if (!ieee80211_amsdu_prepare_head(sdata, fast_tx, head))
|
|
goto out;
|
|
|
|
+ /* If n == 2, the "while (*frag_tail)" loop above didn't execute
|
|
+ * and frag_tail should be &skb_shinfo(head)->frag_list.
|
|
+ * However, ieee80211_amsdu_prepare_head() can reallocate it.
|
|
+ * Reload frag_tail to have it pointing to the correct place.
|
|
+ */
|
|
+ if (n == 2)
|
|
+ frag_tail = &skb_shinfo(head)->frag_list;
|
|
+
|
|
/*
|
|
* Pad out the previous subframe to a multiple of 4 by adding the
|
|
* padding to the next one, that's being added. Note that head->len
|
|
diff --git a/net/mac80211/wpa.c b/net/mac80211/wpa.c
|
|
index bca47fad5a162..4eed23e276104 100644
|
|
--- a/net/mac80211/wpa.c
|
|
+++ b/net/mac80211/wpa.c
|
|
@@ -520,6 +520,9 @@ ieee80211_crypto_ccmp_decrypt(struct ieee80211_rx_data *rx,
|
|
return RX_DROP_UNUSABLE;
|
|
}
|
|
|
|
+ /* reload hdr - skb might have been reallocated */
|
|
+ hdr = (void *)rx->skb->data;
|
|
+
|
|
data_len = skb->len - hdrlen - IEEE80211_CCMP_HDR_LEN - mic_len;
|
|
if (!rx->sta || data_len < 0)
|
|
return RX_DROP_UNUSABLE;
|
|
@@ -749,6 +752,9 @@ ieee80211_crypto_gcmp_decrypt(struct ieee80211_rx_data *rx)
|
|
return RX_DROP_UNUSABLE;
|
|
}
|
|
|
|
+ /* reload hdr - skb might have been reallocated */
|
|
+ hdr = (void *)rx->skb->data;
|
|
+
|
|
data_len = skb->len - hdrlen - IEEE80211_GCMP_HDR_LEN - mic_len;
|
|
if (!rx->sta || data_len < 0)
|
|
return RX_DROP_UNUSABLE;
|
|
diff --git a/net/netfilter/ipset/ip_set_hash_gen.h b/net/netfilter/ipset/ip_set_hash_gen.h
|
|
index 500de37858ac8..1b44dfa7ba856 100644
|
|
--- a/net/netfilter/ipset/ip_set_hash_gen.h
|
|
+++ b/net/netfilter/ipset/ip_set_hash_gen.h
|
|
@@ -132,11 +132,11 @@ htable_size(u8 hbits)
|
|
{
|
|
size_t hsize;
|
|
|
|
- /* We must fit both into u32 in jhash and size_t */
|
|
+ /* We must fit both into u32 in jhash and INT_MAX in kvmalloc_node() */
|
|
if (hbits > 31)
|
|
return 0;
|
|
hsize = jhash_size(hbits);
|
|
- if ((((size_t)-1) - sizeof(struct htable)) / sizeof(struct hbucket *)
|
|
+ if ((INT_MAX - sizeof(struct htable)) / sizeof(struct hbucket *)
|
|
< hsize)
|
|
return 0;
|
|
|
|
diff --git a/net/netfilter/ipvs/ip_vs_conn.c b/net/netfilter/ipvs/ip_vs_conn.c
|
|
index 02f2f636798d1..d1524ca4b90ef 100644
|
|
--- a/net/netfilter/ipvs/ip_vs_conn.c
|
|
+++ b/net/netfilter/ipvs/ip_vs_conn.c
|
|
@@ -1394,6 +1394,10 @@ int __init ip_vs_conn_init(void)
|
|
int idx;
|
|
|
|
/* Compute size and mask */
|
|
+ if (ip_vs_conn_tab_bits < 8 || ip_vs_conn_tab_bits > 20) {
|
|
+ pr_info("conn_tab_bits not in [8, 20]. Using default value\n");
|
|
+ ip_vs_conn_tab_bits = CONFIG_IP_VS_TAB_BITS;
|
|
+ }
|
|
ip_vs_conn_tab_size = 1 << ip_vs_conn_tab_bits;
|
|
ip_vs_conn_tab_mask = ip_vs_conn_tab_size - 1;
|
|
|
|
diff --git a/net/sched/cls_flower.c b/net/sched/cls_flower.c
|
|
index c5a0f2c2635ed..26979b4853bdb 100644
|
|
--- a/net/sched/cls_flower.c
|
|
+++ b/net/sched/cls_flower.c
|
|
@@ -1741,18 +1741,24 @@ static void fl_walk(struct tcf_proto *tp, struct tcf_walker *arg,
|
|
|
|
arg->count = arg->skip;
|
|
|
|
+ rcu_read_lock();
|
|
idr_for_each_entry_continue_ul(&head->handle_idr, f, tmp, id) {
|
|
/* don't return filters that are being deleted */
|
|
if (!refcount_inc_not_zero(&f->refcnt))
|
|
continue;
|
|
+ rcu_read_unlock();
|
|
+
|
|
if (arg->fn(tp, f, arg) < 0) {
|
|
__fl_put(f);
|
|
arg->stop = 1;
|
|
+ rcu_read_lock();
|
|
break;
|
|
}
|
|
__fl_put(f);
|
|
arg->count++;
|
|
+ rcu_read_lock();
|
|
}
|
|
+ rcu_read_unlock();
|
|
arg->cookie = id;
|
|
}
|
|
|
|
diff --git a/net/sctp/input.c b/net/sctp/input.c
|
|
index 2aca37717ed1e..9616b600a8766 100644
|
|
--- a/net/sctp/input.c
|
|
+++ b/net/sctp/input.c
|
|
@@ -676,7 +676,7 @@ static int sctp_rcv_ootb(struct sk_buff *skb)
|
|
ch = skb_header_pointer(skb, offset, sizeof(*ch), &_ch);
|
|
|
|
/* Break out if chunk length is less then minimal. */
|
|
- if (ntohs(ch->length) < sizeof(_ch))
|
|
+ if (!ch || ntohs(ch->length) < sizeof(_ch))
|
|
break;
|
|
|
|
ch_end = offset + SCTP_PAD4(ntohs(ch->length));
|
|
diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c
|
|
index 3098710c9c344..05470ca91bd94 100644
|
|
--- a/net/unix/af_unix.c
|
|
+++ b/net/unix/af_unix.c
|
|
@@ -595,20 +595,42 @@ static void unix_release_sock(struct sock *sk, int embrion)
|
|
|
|
static void init_peercred(struct sock *sk)
|
|
{
|
|
- put_pid(sk->sk_peer_pid);
|
|
- if (sk->sk_peer_cred)
|
|
- put_cred(sk->sk_peer_cred);
|
|
+ const struct cred *old_cred;
|
|
+ struct pid *old_pid;
|
|
+
|
|
+ spin_lock(&sk->sk_peer_lock);
|
|
+ old_pid = sk->sk_peer_pid;
|
|
+ old_cred = sk->sk_peer_cred;
|
|
sk->sk_peer_pid = get_pid(task_tgid(current));
|
|
sk->sk_peer_cred = get_current_cred();
|
|
+ spin_unlock(&sk->sk_peer_lock);
|
|
+
|
|
+ put_pid(old_pid);
|
|
+ put_cred(old_cred);
|
|
}
|
|
|
|
static void copy_peercred(struct sock *sk, struct sock *peersk)
|
|
{
|
|
- put_pid(sk->sk_peer_pid);
|
|
- if (sk->sk_peer_cred)
|
|
- put_cred(sk->sk_peer_cred);
|
|
+ const struct cred *old_cred;
|
|
+ struct pid *old_pid;
|
|
+
|
|
+ if (sk < peersk) {
|
|
+ spin_lock(&sk->sk_peer_lock);
|
|
+ spin_lock_nested(&peersk->sk_peer_lock, SINGLE_DEPTH_NESTING);
|
|
+ } else {
|
|
+ spin_lock(&peersk->sk_peer_lock);
|
|
+ spin_lock_nested(&sk->sk_peer_lock, SINGLE_DEPTH_NESTING);
|
|
+ }
|
|
+ old_pid = sk->sk_peer_pid;
|
|
+ old_cred = sk->sk_peer_cred;
|
|
sk->sk_peer_pid = get_pid(peersk->sk_peer_pid);
|
|
sk->sk_peer_cred = get_cred(peersk->sk_peer_cred);
|
|
+
|
|
+ spin_unlock(&sk->sk_peer_lock);
|
|
+ spin_unlock(&peersk->sk_peer_lock);
|
|
+
|
|
+ put_pid(old_pid);
|
|
+ put_cred(old_cred);
|
|
}
|
|
|
|
static int unix_listen(struct socket *sock, int backlog)
|
|
diff --git a/tools/testing/selftests/bpf/test_lwt_ip_encap.sh b/tools/testing/selftests/bpf/test_lwt_ip_encap.sh
|
|
index 59ea56945e6cd..b497bb85b667f 100755
|
|
--- a/tools/testing/selftests/bpf/test_lwt_ip_encap.sh
|
|
+++ b/tools/testing/selftests/bpf/test_lwt_ip_encap.sh
|
|
@@ -112,6 +112,14 @@ setup()
|
|
ip netns add "${NS2}"
|
|
ip netns add "${NS3}"
|
|
|
|
+ # rp_filter gets confused by what these tests are doing, so disable it
|
|
+ ip netns exec ${NS1} sysctl -wq net.ipv4.conf.all.rp_filter=0
|
|
+ ip netns exec ${NS2} sysctl -wq net.ipv4.conf.all.rp_filter=0
|
|
+ ip netns exec ${NS3} sysctl -wq net.ipv4.conf.all.rp_filter=0
|
|
+ ip netns exec ${NS1} sysctl -wq net.ipv4.conf.default.rp_filter=0
|
|
+ ip netns exec ${NS2} sysctl -wq net.ipv4.conf.default.rp_filter=0
|
|
+ ip netns exec ${NS3} sysctl -wq net.ipv4.conf.default.rp_filter=0
|
|
+
|
|
ip link add veth1 type veth peer name veth2
|
|
ip link add veth3 type veth peer name veth4
|
|
ip link add veth5 type veth peer name veth6
|
|
@@ -236,11 +244,6 @@ setup()
|
|
ip -netns ${NS1} -6 route add ${IPv6_GRE}/128 dev veth5 via ${IPv6_6} ${VRF}
|
|
ip -netns ${NS2} -6 route add ${IPv6_GRE}/128 dev veth7 via ${IPv6_8} ${VRF}
|
|
|
|
- # rp_filter gets confused by what these tests are doing, so disable it
|
|
- ip netns exec ${NS1} sysctl -wq net.ipv4.conf.all.rp_filter=0
|
|
- ip netns exec ${NS2} sysctl -wq net.ipv4.conf.all.rp_filter=0
|
|
- ip netns exec ${NS3} sysctl -wq net.ipv4.conf.all.rp_filter=0
|
|
-
|
|
TMPFILE=$(mktemp /tmp/test_lwt_ip_encap.XXXXXX)
|
|
|
|
sleep 1 # reduce flakiness
|