From 629405d18543b6caec22c2bd359a2de6a406e1c6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Paku=C5=82a?= Date: Sat, 1 Feb 2025 12:38:47 +0100 Subject: [PATCH 001/136] HID: pidff: Clamp PERIODIC effect period to device's logical range MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [ Upstream commit f538183e997a9fb6087e94e71e372de967b9e56a ] This ensures the effect can actually be played on the connected force feedback device. Adds clamping functions used instead of rescaling, as we don't want to change the characteristics of the periodic effects. Fixes edge cases found on Moza Racing and some other hardware where the effects would not play if the period is outside the defined logical range. Changes in v6: - Use in-kernel clamp macro instead of a custom solution Signed-off-by: Tomasz Pakuła Reviewed-by: Michał Kopeć Reviewed-by: Paul Dino Jones Tested-by: Paul Dino Jones Tested-by: Cristóferson Bueno Tested-by: Pablo Cisneros Signed-off-by: Jiri Kosina Signed-off-by: Sasha Levin --- drivers/hid/usbhid/hid-pidff.c | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/drivers/hid/usbhid/hid-pidff.c b/drivers/hid/usbhid/hid-pidff.c index 25dbed076f53..6b55345ce75a 100644 --- a/drivers/hid/usbhid/hid-pidff.c +++ b/drivers/hid/usbhid/hid-pidff.c @@ -15,10 +15,9 @@ #include #include #include - #include +#include -#include "usbhid.h" #define PID_EFFECTS_MAX 64 #define PID_INFINITE 0xffff @@ -192,6 +191,16 @@ struct pidff_device { u32 quirks; }; +/* + * Clamp value for a given field + */ +static s32 pidff_clamp(s32 i, struct hid_field *field) +{ + s32 clamped = clamp(i, field->logical_minimum, field->logical_maximum); + pr_debug("clamped from %d to %d", i, clamped); + return clamped; +} + /* * Scale an unsigned value with range 0..max for the given field */ @@ -372,7 +381,11 @@ static void pidff_set_periodic_report(struct pidff_device *pidff, pidff_set_signed(&pidff->set_periodic[PID_OFFSET], effect->u.periodic.offset); pidff_set(&pidff->set_periodic[PID_PHASE], effect->u.periodic.phase); - pidff->set_periodic[PID_PERIOD].value[0] = effect->u.periodic.period; + + /* Clamp period to ensure the device can play the effect */ + pidff->set_periodic[PID_PERIOD].value[0] = + pidff_clamp(effect->u.periodic.period, + pidff->set_periodic[PID_PERIOD].field); hid_hw_request(pidff->hid, pidff->reports[PID_SET_PERIODIC], HID_REQ_SET_REPORT); From 2b1e13ed295a207c5523721edad67013c8eef942 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Paku=C5=82a?= Date: Sat, 1 Feb 2025 12:38:53 +0100 Subject: [PATCH 002/136] HID: pidff: Stop all effects before enabling actuators MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [ Upstream commit ce52c0c939fcb568d1abe454821d5623de38b424 ] Some PID compliant devices automatically play effects after boot (i.e. autocenter spring) that prevent the rendering of other effects since it is done outside the kernel driver. This makes sure all the effects currently played are stopped after resetting the device. It brings compatibility to the Brunner CLS-P joystick and others Reported-by: Jules Noirant Signed-off-by: Tomasz Pakuła Reviewed-by: Michał Kopeć Reviewed-by: Paul Dino Jones Tested-by: Paul Dino Jones Tested-by: Cristóferson Bueno Tested-by: Pablo Cisneros Signed-off-by: Jiri Kosina Signed-off-by: Sasha Levin --- drivers/hid/usbhid/hid-pidff.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/drivers/hid/usbhid/hid-pidff.c b/drivers/hid/usbhid/hid-pidff.c index 6b55345ce75a..635596a57c75 100644 --- a/drivers/hid/usbhid/hid-pidff.c +++ b/drivers/hid/usbhid/hid-pidff.c @@ -109,8 +109,9 @@ static const u8 pidff_pool[] = { 0x80, 0x83, 0xa9 }; /* Special field key tables used to put special field keys into arrays */ #define PID_ENABLE_ACTUATORS 0 -#define PID_RESET 1 -static const u8 pidff_device_control[] = { 0x97, 0x9a }; +#define PID_STOP_ALL_EFFECTS 1 +#define PID_RESET 2 +static const u8 pidff_device_control[] = { 0x97, 0x99, 0x9a }; #define PID_CONSTANT 0 #define PID_RAMP 1 @@ -1235,6 +1236,10 @@ static void pidff_reset(struct pidff_device *pidff) hid_hw_request(hid, pidff->reports[PID_DEVICE_CONTROL], HID_REQ_SET_REPORT); hid_hw_wait(hid); + pidff->device_control->value[0] = pidff->control_id[PID_STOP_ALL_EFFECTS]; + hid_hw_request(hid, pidff->reports[PID_DEVICE_CONTROL], HID_REQ_SET_REPORT); + hid_hw_wait(hid); + pidff->device_control->value[0] = pidff->control_id[PID_ENABLE_ACTUATORS]; hid_hw_request(hid, pidff->reports[PID_DEVICE_CONTROL], HID_REQ_SET_REPORT); From 433c4234ff7365368ece8ba9ae94c23210dc93a8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Paku=C5=82a?= Date: Sat, 1 Feb 2025 12:38:57 +0100 Subject: [PATCH 003/136] HID: pidff: Completely rework and fix pidff_reset function MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [ Upstream commit cb3fd788e3fa5358602a49809c4eb4911539c9d0 ] Previously, it was assumed that DEVICE_CONTROL usage is always an array but a lot of devices implements it as a bitmask variable. This led to the pidff_reset function not working and causing errors in such cases. Selectors can come in three types. One selection of a set, N selections and Any selection in form of bitmask as from USB Hid Usage Tables v1.5, subsection 3.4.2.1 Added pidff_send_device_control which handles usage flag check which decides whether DEVICE_CONTROL should be handled as "One selection of a set" or "Any selection of a set". Reset was triggered once, on device initialization. Now, it's triggered every time when uploading an effect to an empty device (no currently stored effects), tracked by pidff->effect_count variable. Co-developed-by: Makarenko Oleg Signed-off-by: Makarenko Oleg Signed-off-by: Tomasz Pakuła Reviewed-by: Michał Kopeć Reviewed-by: Paul Dino Jones Tested-by: Paul Dino Jones Tested-by: Cristóferson Bueno Tested-by: Pablo Cisneros Signed-off-by: Jiri Kosina Signed-off-by: Sasha Levin --- drivers/hid/usbhid/hid-pidff.c | 138 +++++++++++++++++++++------------ 1 file changed, 89 insertions(+), 49 deletions(-) diff --git a/drivers/hid/usbhid/hid-pidff.c b/drivers/hid/usbhid/hid-pidff.c index 635596a57c75..99b5d3deb40d 100644 --- a/drivers/hid/usbhid/hid-pidff.c +++ b/drivers/hid/usbhid/hid-pidff.c @@ -109,9 +109,10 @@ static const u8 pidff_pool[] = { 0x80, 0x83, 0xa9 }; /* Special field key tables used to put special field keys into arrays */ #define PID_ENABLE_ACTUATORS 0 -#define PID_STOP_ALL_EFFECTS 1 -#define PID_RESET 2 -static const u8 pidff_device_control[] = { 0x97, 0x99, 0x9a }; +#define PID_DISABLE_ACTUATORS 1 +#define PID_STOP_ALL_EFFECTS 2 +#define PID_RESET 3 +static const u8 pidff_device_control[] = { 0x97, 0x98, 0x99, 0x9a }; #define PID_CONSTANT 0 #define PID_RAMP 1 @@ -190,6 +191,7 @@ struct pidff_device { int pid_id[PID_EFFECTS_MAX]; u32 quirks; + u8 effect_count; }; /* @@ -490,9 +492,83 @@ static int pidff_needs_set_ramp(struct ff_effect *effect, struct ff_effect *old) effect->u.ramp.end_level != old->u.ramp.end_level; } +/* + * Clear device control report + */ +static void pidff_send_device_control(struct pidff_device *pidff, int field) +{ + int i, tmp; + int field_index = pidff->control_id[field]; + + /* Detect if the field is a bitmask variable or an array */ + if (pidff->device_control->flags & HID_MAIN_ITEM_VARIABLE) { + hid_dbg(pidff->hid, "DEVICE_CONTROL is a bitmask\n"); + /* Clear current bitmask */ + for(i = 0; i < sizeof(pidff_device_control); i++) { + tmp = pidff->control_id[i]; + pidff->device_control->value[tmp] = 0; + } + pidff->device_control->value[field_index - 1] = 1; + } else { + hid_dbg(pidff->hid, "DEVICE_CONTROL is an array\n"); + pidff->device_control->value[0] = field_index; + } + + hid_hw_request(pidff->hid, pidff->reports[PID_DEVICE_CONTROL], HID_REQ_SET_REPORT); + hid_hw_wait(pidff->hid); +} + +/* + * Modify actuators state + */ +static void pidff_modify_actuators_state(struct pidff_device *pidff, bool enable) +{ + hid_dbg(pidff->hid, "%s actuators\n", enable ? "Enable" : "Disable"); + pidff_send_device_control(pidff, + enable ? PID_ENABLE_ACTUATORS : PID_DISABLE_ACTUATORS); +} + +/* + * Reset the device, stop all effects, enable actuators + * Refetch pool report + */ +static void pidff_reset(struct pidff_device *pidff) +{ + int i = 0; + + /* We reset twice as sometimes hid_wait_io isn't waiting long enough */ + pidff_send_device_control(pidff, PID_RESET); + pidff_send_device_control(pidff, PID_RESET); + pidff->effect_count = 0; + + pidff_send_device_control(pidff, PID_STOP_ALL_EFFECTS); + pidff_modify_actuators_state(pidff, 1); + + /* pool report is sometimes messed up, refetch it */ + hid_hw_request(pidff->hid, pidff->reports[PID_POOL], HID_REQ_GET_REPORT); + hid_hw_wait(pidff->hid); + + if (pidff->pool[PID_SIMULTANEOUS_MAX].value) { + while (pidff->pool[PID_SIMULTANEOUS_MAX].value[0] < 2) { + if (i++ > 20) { + hid_warn(pidff->hid, + "device reports %d simultaneous effects\n", + pidff->pool[PID_SIMULTANEOUS_MAX].value[0]); + break; + } + hid_dbg(pidff->hid, "pid_pool requested again\n"); + hid_hw_request(pidff->hid, pidff->reports[PID_POOL], + HID_REQ_GET_REPORT); + hid_hw_wait(pidff->hid); + } + } +} + /* * Send a request for effect upload to the device * + * Reset and enable actuators if no effects were present on the device + * * Returns 0 if device reported success, -ENOSPC if the device reported memory * is full. Upon unknown response the function will retry for 60 times, if * still unsuccessful -EIO is returned. @@ -501,6 +577,9 @@ static int pidff_request_effect_upload(struct pidff_device *pidff, int efnum) { int j; + if (!pidff->effect_count) + pidff_reset(pidff); + pidff->create_new_effect_type->value[0] = efnum; hid_hw_request(pidff->hid, pidff->reports[PID_CREATE_NEW_EFFECT], HID_REQ_SET_REPORT); @@ -520,6 +599,8 @@ static int pidff_request_effect_upload(struct pidff_device *pidff, int efnum) hid_dbg(pidff->hid, "device reported free memory: %d bytes\n", pidff->block_load[PID_RAM_POOL_AVAILABLE].value ? pidff->block_load[PID_RAM_POOL_AVAILABLE].value[0] : -1); + + pidff->effect_count++; return 0; } if (pidff->block_load_status->value[0] == @@ -568,12 +649,16 @@ static int pidff_playback(struct input_dev *dev, int effect_id, int value) /* * Erase effect with PID id + * Decrease the device effect counter */ static void pidff_erase_pid(struct pidff_device *pidff, int pid_id) { pidff->block_free[PID_EFFECT_BLOCK_INDEX].value[0] = pid_id; hid_hw_request(pidff->hid, pidff->reports[PID_BLOCK_FREE], HID_REQ_SET_REPORT); + + if (pidff->effect_count > 0) + pidff->effect_count--; } /* @@ -1221,50 +1306,6 @@ static int pidff_init_fields(struct pidff_device *pidff, struct input_dev *dev) return 0; } -/* - * Reset the device - */ -static void pidff_reset(struct pidff_device *pidff) -{ - struct hid_device *hid = pidff->hid; - int i = 0; - - pidff->device_control->value[0] = pidff->control_id[PID_RESET]; - /* We reset twice as sometimes hid_wait_io isn't waiting long enough */ - hid_hw_request(hid, pidff->reports[PID_DEVICE_CONTROL], HID_REQ_SET_REPORT); - hid_hw_wait(hid); - hid_hw_request(hid, pidff->reports[PID_DEVICE_CONTROL], HID_REQ_SET_REPORT); - hid_hw_wait(hid); - - pidff->device_control->value[0] = pidff->control_id[PID_STOP_ALL_EFFECTS]; - hid_hw_request(hid, pidff->reports[PID_DEVICE_CONTROL], HID_REQ_SET_REPORT); - hid_hw_wait(hid); - - pidff->device_control->value[0] = - pidff->control_id[PID_ENABLE_ACTUATORS]; - hid_hw_request(hid, pidff->reports[PID_DEVICE_CONTROL], HID_REQ_SET_REPORT); - hid_hw_wait(hid); - - /* pool report is sometimes messed up, refetch it */ - hid_hw_request(hid, pidff->reports[PID_POOL], HID_REQ_GET_REPORT); - hid_hw_wait(hid); - - if (pidff->pool[PID_SIMULTANEOUS_MAX].value) { - while (pidff->pool[PID_SIMULTANEOUS_MAX].value[0] < 2) { - if (i++ > 20) { - hid_warn(pidff->hid, - "device reports %d simultaneous effects\n", - pidff->pool[PID_SIMULTANEOUS_MAX].value[0]); - break; - } - hid_dbg(pidff->hid, "pid_pool requested again\n"); - hid_hw_request(hid, pidff->reports[PID_POOL], - HID_REQ_GET_REPORT); - hid_hw_wait(hid); - } - } -} - /* * Test if autocenter modification is using the supported method */ @@ -1330,6 +1371,7 @@ int hid_pidff_init_with_quirks(struct hid_device *hid, __u32 initial_quirks) pidff->hid = hid; pidff->quirks = initial_quirks; + pidff->effect_count = 0; hid_device_io_start(hid); @@ -1346,8 +1388,6 @@ int hid_pidff_init_with_quirks(struct hid_device *hid, __u32 initial_quirks) if (error) goto fail; - pidff_reset(pidff); - if (test_bit(FF_GAIN, dev->ffbit)) { pidff_set(&pidff->device_gain[PID_DEVICE_GAIN_FIELD], 0xffff); hid_hw_request(hid, pidff->reports[PID_DEVICE_GAIN], From 9cdd95f9a4f3f60388c069d262953d9f19b5a692 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Paku=C5=82a?= Date: Sat, 1 Feb 2025 12:38:58 +0100 Subject: [PATCH 004/136] HID: pidff: Simplify pidff_upload_effect function MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [ Upstream commit e4bdc80ef14272ef56c38d8ca2f365fdf59cd0ba ] Merge a bit of code that reqeusts conditional effects upload. Makes it clear, that effect handling should be identical for SPRING, DAMPER, INERTIA and FRICTION. Signed-off-by: Tomasz Pakuła Reviewed-by: Michał Kopeć Reviewed-by: Paul Dino Jones Tested-by: Paul Dino Jones Tested-by: Cristóferson Bueno Tested-by: Pablo Cisneros Signed-off-by: Jiri Kosina Signed-off-by: Sasha Levin --- drivers/hid/usbhid/hid-pidff.c | 56 +++++++++++----------------------- 1 file changed, 17 insertions(+), 39 deletions(-) diff --git a/drivers/hid/usbhid/hid-pidff.c b/drivers/hid/usbhid/hid-pidff.c index 99b5d3deb40d..42c951a1d65b 100644 --- a/drivers/hid/usbhid/hid-pidff.c +++ b/drivers/hid/usbhid/hid-pidff.c @@ -770,48 +770,26 @@ static int pidff_upload_effect(struct input_dev *dev, struct ff_effect *effect, break; case FF_SPRING: - if (!old) { - error = pidff_request_effect_upload(pidff, - pidff->type_id[PID_SPRING]); - if (error) - return error; - } - if (!old || pidff_needs_set_effect(effect, old)) - pidff_set_effect_report(pidff, effect); - if (!old || pidff_needs_set_condition(effect, old)) - pidff_set_condition_report(pidff, effect); - break; - + case FF_DAMPER: + case FF_INERTIA: case FF_FRICTION: if (!old) { + switch(effect->type) { + case FF_SPRING: + type_id = PID_SPRING; + break; + case FF_DAMPER: + type_id = PID_DAMPER; + break; + case FF_INERTIA: + type_id = PID_INERTIA; + break; + case FF_FRICTION: + type_id = PID_FRICTION; + break; + } error = pidff_request_effect_upload(pidff, - pidff->type_id[PID_FRICTION]); - if (error) - return error; - } - if (!old || pidff_needs_set_effect(effect, old)) - pidff_set_effect_report(pidff, effect); - if (!old || pidff_needs_set_condition(effect, old)) - pidff_set_condition_report(pidff, effect); - break; - - case FF_DAMPER: - if (!old) { - error = pidff_request_effect_upload(pidff, - pidff->type_id[PID_DAMPER]); - if (error) - return error; - } - if (!old || pidff_needs_set_effect(effect, old)) - pidff_set_effect_report(pidff, effect); - if (!old || pidff_needs_set_condition(effect, old)) - pidff_set_condition_report(pidff, effect); - break; - - case FF_INERTIA: - if (!old) { - error = pidff_request_effect_upload(pidff, - pidff->type_id[PID_INERTIA]); + pidff->type_id[type_id]); if (error) return error; } From 7009a060ffef4c757c40297fc4b7345ec7c63dbd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Paku=C5=82a?= Date: Sat, 1 Feb 2025 12:38:59 +0100 Subject: [PATCH 005/136] HID: pidff: Define values used in pidff_find_special_fields MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [ Upstream commit 1c12f136891cf4d2d4e6aa202d671a9d2171a716 ] Makes it clear where did these values came from Signed-off-by: Tomasz Pakuła Reviewed-by: Michał Kopeć Reviewed-by: Paul Dino Jones Tested-by: Paul Dino Jones Tested-by: Cristóferson Bueno Tested-by: Pablo Cisneros Signed-off-by: Jiri Kosina Signed-off-by: Sasha Levin --- drivers/hid/usbhid/hid-pidff.c | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/drivers/hid/usbhid/hid-pidff.c b/drivers/hid/usbhid/hid-pidff.c index 42c951a1d65b..bd913d57e4d7 100644 --- a/drivers/hid/usbhid/hid-pidff.c +++ b/drivers/hid/usbhid/hid-pidff.c @@ -48,6 +48,14 @@ static const u8 pidff_reports[] = { /* device_control is really 0x95, but 0x96 specified as it is the usage of the only field in that report */ +/* PID special fields */ + +#define PID_EFFECT_TYPE 0x25 +#define PID_DIRECTION 0x57 +#define PID_EFFECT_OPERATION_ARRAY 0x78 +#define PID_BLOCK_LOAD_STATUS 0x8b +#define PID_DEVICE_CONTROL_ARRAY 0x96 + /* Value usage tables used to put fields and values into arrays */ #define PID_EFFECT_BLOCK_INDEX 0 @@ -1056,23 +1064,24 @@ static int pidff_find_special_fields(struct pidff_device *pidff) pidff->create_new_effect_type = pidff_find_special_field(pidff->reports[PID_CREATE_NEW_EFFECT], - 0x25, 1); + PID_EFFECT_TYPE, 1); pidff->set_effect_type = pidff_find_special_field(pidff->reports[PID_SET_EFFECT], - 0x25, 1); + PID_EFFECT_TYPE, 1); pidff->effect_direction = pidff_find_special_field(pidff->reports[PID_SET_EFFECT], - 0x57, 0); + PID_DIRECTION, 0); pidff->device_control = pidff_find_special_field(pidff->reports[PID_DEVICE_CONTROL], - 0x96, !(pidff->quirks & HID_PIDFF_QUIRK_PERMISSIVE_CONTROL)); + PID_DEVICE_CONTROL_ARRAY, + !(pidff->quirks & HID_PIDFF_QUIRK_PERMISSIVE_CONTROL)); pidff->block_load_status = pidff_find_special_field(pidff->reports[PID_BLOCK_LOAD], - 0x8b, 1); + PID_BLOCK_LOAD_STATUS, 1); pidff->effect_operation_status = pidff_find_special_field(pidff->reports[PID_EFFECT_OPERATION], - 0x78, 1); + PID_EFFECT_OPERATION_ARRAY, 1); hid_dbg(pidff->hid, "search done\n"); From 5243ca2a5c678bf86150a8f8567b505c1d154524 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Paku=C5=82a?= Date: Sat, 1 Feb 2025 12:39:00 +0100 Subject: [PATCH 006/136] HID: pidff: Rescale time values to match field units MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [ Upstream commit 8713107221a8ce4021ec5fa12bb50ecc8165cf08 ] PID devices can use different exponents for time fields, while Linux Force Feedback API only supports miliseconds. Read the exponent of a given time field and scale its value accordingly. Changes in v7: - Rescale all time fields, not only period changes in v9: - Properly assign fade_lenght, not attack_length to PID_FADE_TIME Co-developed-by: Makarenko Oleg Signed-off-by: Makarenko Oleg Signed-off-by: Tomasz Pakuła Reviewed-by: Michał Kopeć Reviewed-by: Paul Dino Jones Tested-by: Paul Dino Jones Tested-by: Cristóferson Bueno Tested-by: Pablo Cisneros Signed-off-by: Jiri Kosina Signed-off-by: Sasha Levin --- drivers/hid/usbhid/hid-pidff.c | 69 ++++++++++++++++++++++++++-------- 1 file changed, 54 insertions(+), 15 deletions(-) diff --git a/drivers/hid/usbhid/hid-pidff.c b/drivers/hid/usbhid/hid-pidff.c index bd913d57e4d7..180b2cf66e4c 100644 --- a/drivers/hid/usbhid/hid-pidff.c +++ b/drivers/hid/usbhid/hid-pidff.c @@ -22,6 +22,9 @@ #define PID_EFFECTS_MAX 64 #define PID_INFINITE 0xffff +/* Linux Force Feedback API uses miliseconds as time unit */ +#define FF_TIME_EXPONENT -3 + /* Report usage table used to put reports into an array */ #define PID_SET_EFFECT 0 @@ -231,6 +234,24 @@ static int pidff_rescale_signed(int i, struct hid_field *field) field->logical_minimum / -0x8000; } +/* + * Scale time value from Linux default (ms) to field units + */ +static u32 pidff_rescale_time(u16 time, struct hid_field *field) +{ + u32 scaled_time = time; + int exponent = field->unit_exponent; + pr_debug("time field exponent: %d\n", exponent); + + for (;exponent < FF_TIME_EXPONENT; exponent++) + scaled_time *= 10; + for (;exponent > FF_TIME_EXPONENT; exponent--) + scaled_time /= 10; + + pr_debug("time calculated from %d to %d\n", time, scaled_time); + return scaled_time; +} + static void pidff_set(struct pidff_usage *usage, u16 value) { usage->value[0] = pidff_rescale(value, 0xffff, usage->field); @@ -252,6 +273,27 @@ static void pidff_set_signed(struct pidff_usage *usage, s16 value) pr_debug("calculated from %d to %d\n", value, usage->value[0]); } +static void pidff_set_time(struct pidff_usage *usage, u16 time) +{ + u32 modified_time = pidff_rescale_time(time, usage->field); + usage->value[0] = pidff_clamp(modified_time, usage->field); +} + +static void pidff_set_duration(struct pidff_usage *usage, u16 duration) +{ + /* Convert infinite length from Linux API (0) + to PID standard (NULL) if needed */ + if (duration == 0) + duration = PID_INFINITE; + + if (duration == PID_INFINITE) { + usage->value[0] = PID_INFINITE; + return; + } + + pidff_set_time(usage, duration); +} + /* * Send envelope report to the device */ @@ -270,8 +312,10 @@ static void pidff_set_envelope_report(struct pidff_device *pidff, 0x7fff ? 0x7fff : envelope->fade_level, 0x7fff, pidff->set_envelope[PID_FADE_LEVEL].field); - pidff->set_envelope[PID_ATTACK_TIME].value[0] = envelope->attack_length; - pidff->set_envelope[PID_FADE_TIME].value[0] = envelope->fade_length; + pidff_set_time(&pidff->set_envelope[PID_ATTACK_TIME], + envelope->attack_length); + pidff_set_time(&pidff->set_envelope[PID_FADE_TIME], + envelope->fade_length); hid_dbg(pidff->hid, "attack %u => %d\n", envelope->attack_level, @@ -340,14 +384,12 @@ static void pidff_set_effect_report(struct pidff_device *pidff, pidff->set_effect_type->value[0] = pidff->create_new_effect_type->value[0]; - /* Convert infinite length from Linux API (0) - to PID standard (NULL) if needed */ - pidff->set_effect[PID_DURATION].value[0] = - effect->replay.length == 0 ? PID_INFINITE : effect->replay.length; + pidff_set_duration(&pidff->set_effect[PID_DURATION], + effect->replay.length); pidff->set_effect[PID_TRIGGER_BUTTON].value[0] = effect->trigger.button; - pidff->set_effect[PID_TRIGGER_REPEAT_INT].value[0] = - effect->trigger.interval; + pidff_set_time(&pidff->set_effect[PID_TRIGGER_REPEAT_INT], + effect->trigger.interval); pidff->set_effect[PID_GAIN].value[0] = pidff->set_effect[PID_GAIN].field->logical_maximum; pidff->set_effect[PID_DIRECTION_ENABLE].value[0] = 1; @@ -360,7 +402,8 @@ static void pidff_set_effect_report(struct pidff_device *pidff, /* Omit setting delay field if it's missing */ if (!(pidff->quirks & HID_PIDFF_QUIRK_MISSING_DELAY)) - pidff->set_effect[PID_START_DELAY].value[0] = effect->replay.delay; + pidff_set_time(&pidff->set_effect[PID_START_DELAY], + effect->replay.delay); hid_hw_request(pidff->hid, pidff->reports[PID_SET_EFFECT], HID_REQ_SET_REPORT); @@ -392,15 +435,11 @@ static void pidff_set_periodic_report(struct pidff_device *pidff, pidff_set_signed(&pidff->set_periodic[PID_OFFSET], effect->u.periodic.offset); pidff_set(&pidff->set_periodic[PID_PHASE], effect->u.periodic.phase); - - /* Clamp period to ensure the device can play the effect */ - pidff->set_periodic[PID_PERIOD].value[0] = - pidff_clamp(effect->u.periodic.period, - pidff->set_periodic[PID_PERIOD].field); + pidff_set_time(&pidff->set_periodic[PID_PERIOD], + effect->u.periodic.period); hid_hw_request(pidff->hid, pidff->reports[PID_SET_PERIODIC], HID_REQ_SET_REPORT); - } /* From 8f0b2d791e0fcaa8afe9a6a28ba300dab63fe6ed Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Paku=C5=82a?= Date: Sat, 1 Feb 2025 12:39:01 +0100 Subject: [PATCH 007/136] HID: pidff: Factor out code for setting gain MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [ Upstream commit f7ebf0b11b9e04bf59c438ad14f0115b12aa2f44 ] Makes it possible to easily set gain from inside hid-pidff.c Changes in v7: - Check if device gain field exists before setting device gain Signed-off-by: Tomasz Pakuła Reviewed-by: Michał Kopeć Reviewed-by: Paul Dino Jones Tested-by: Paul Dino Jones Tested-by: Cristóferson Bueno Tested-by: Pablo Cisneros Signed-off-by: Jiri Kosina Signed-off-by: Sasha Levin --- drivers/hid/usbhid/hid-pidff.c | 26 +++++++++++++++----------- 1 file changed, 15 insertions(+), 11 deletions(-) diff --git a/drivers/hid/usbhid/hid-pidff.c b/drivers/hid/usbhid/hid-pidff.c index 180b2cf66e4c..ac6f940abd90 100644 --- a/drivers/hid/usbhid/hid-pidff.c +++ b/drivers/hid/usbhid/hid-pidff.c @@ -539,6 +539,19 @@ static int pidff_needs_set_ramp(struct ff_effect *effect, struct ff_effect *old) effect->u.ramp.end_level != old->u.ramp.end_level; } +/* + * Set device gain + */ +static void pidff_set_gain_report(struct pidff_device *pidff, u16 gain) +{ + if (!pidff->device_gain[PID_DEVICE_GAIN_FIELD].field) + return; + + pidff_set(&pidff->device_gain[PID_DEVICE_GAIN_FIELD], gain); + hid_hw_request(pidff->hid, pidff->reports[PID_DEVICE_GAIN], + HID_REQ_SET_REPORT); +} + /* * Clear device control report */ @@ -865,11 +878,7 @@ static int pidff_upload_effect(struct input_dev *dev, struct ff_effect *effect, */ static void pidff_set_gain(struct input_dev *dev, u16 gain) { - struct pidff_device *pidff = dev->ff->private; - - pidff_set(&pidff->device_gain[PID_DEVICE_GAIN_FIELD], gain); - hid_hw_request(pidff->hid, pidff->reports[PID_DEVICE_GAIN], - HID_REQ_SET_REPORT); + pidff_set_gain_report(dev->ff->private, gain); } static void pidff_autocenter(struct pidff_device *pidff, u16 magnitude) @@ -1414,12 +1423,7 @@ int hid_pidff_init_with_quirks(struct hid_device *hid, __u32 initial_quirks) if (error) goto fail; - if (test_bit(FF_GAIN, dev->ffbit)) { - pidff_set(&pidff->device_gain[PID_DEVICE_GAIN_FIELD], 0xffff); - hid_hw_request(hid, pidff->reports[PID_DEVICE_GAIN], - HID_REQ_SET_REPORT); - } - + pidff_set_gain_report(pidff, 0xffff); error = pidff_check_autocenter(pidff, dev); if (error) goto fail; From 61e4de1728aca6aa886940c725faf713cfffe187 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Paku=C5=82a?= Date: Sat, 1 Feb 2025 12:39:03 +0100 Subject: [PATCH 008/136] HID: pidff: Move all hid-pidff definitions to a dedicated header MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [ Upstream commit 0d24d4b1da96df9fc5ff36966f40f980ef864d46 ] Do not clutter hid includes with stuff not needed outside of the kernel. Signed-off-by: Tomasz Pakuła Reviewed-by: Michał Kopeć Reviewed-by: Paul Dino Jones Tested-by: Paul Dino Jones Tested-by: Cristóferson Bueno Tested-by: Pablo Cisneros Signed-off-by: Jiri Kosina Signed-off-by: Sasha Levin --- drivers/hid/hid-universal-pidff.c | 3 ++- drivers/hid/usbhid/hid-core.c | 1 + drivers/hid/usbhid/hid-pidff.c | 3 ++- drivers/hid/usbhid/hid-pidff.h | 33 +++++++++++++++++++++++++++++++ include/linux/hid.h | 15 -------------- 5 files changed, 38 insertions(+), 17 deletions(-) create mode 100644 drivers/hid/usbhid/hid-pidff.h diff --git a/drivers/hid/hid-universal-pidff.c b/drivers/hid/hid-universal-pidff.c index 7ef5ab9146b1..1b713b741d19 100644 --- a/drivers/hid/hid-universal-pidff.c +++ b/drivers/hid/hid-universal-pidff.c @@ -13,6 +13,7 @@ #include #include #include "hid-ids.h" +#include "usbhid/hid-pidff.h" #define JOY_RANGE (BTN_DEAD - BTN_JOYSTICK + 1) @@ -89,7 +90,7 @@ static int universal_pidff_probe(struct hid_device *hdev, } /* Check if HID_PID support is enabled */ - int (*init_function)(struct hid_device *, __u32); + int (*init_function)(struct hid_device *, u32); init_function = hid_pidff_init_with_quirks; if (!init_function) { diff --git a/drivers/hid/usbhid/hid-core.c b/drivers/hid/usbhid/hid-core.c index a9e85bdd4cc6..bf0f51ef0149 100644 --- a/drivers/hid/usbhid/hid-core.c +++ b/drivers/hid/usbhid/hid-core.c @@ -35,6 +35,7 @@ #include #include #include "usbhid.h" +#include "hid-pidff.h" /* * Version Information diff --git a/drivers/hid/usbhid/hid-pidff.c b/drivers/hid/usbhid/hid-pidff.c index ac6f940abd90..a8eaa77e80be 100644 --- a/drivers/hid/usbhid/hid-pidff.c +++ b/drivers/hid/usbhid/hid-pidff.c @@ -12,6 +12,7 @@ #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt +#include "hid-pidff.h" #include #include #include @@ -1383,7 +1384,7 @@ static int pidff_check_autocenter(struct pidff_device *pidff, * Check if the device is PID and initialize it * Set initial quirks */ -int hid_pidff_init_with_quirks(struct hid_device *hid, __u32 initial_quirks) +int hid_pidff_init_with_quirks(struct hid_device *hid, u32 initial_quirks) { struct pidff_device *pidff; struct hid_input *hidinput = list_entry(hid->inputs.next, diff --git a/drivers/hid/usbhid/hid-pidff.h b/drivers/hid/usbhid/hid-pidff.h new file mode 100644 index 000000000000..dda571e0a5bd --- /dev/null +++ b/drivers/hid/usbhid/hid-pidff.h @@ -0,0 +1,33 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ +#ifndef __HID_PIDFF_H +#define __HID_PIDFF_H + +#include + +/* HID PIDFF quirks */ + +/* Delay field (0xA7) missing. Skip it during set effect report upload */ +#define HID_PIDFF_QUIRK_MISSING_DELAY BIT(0) + +/* Missing Paramter block offset (0x23). Skip it during SET_CONDITION + report upload */ +#define HID_PIDFF_QUIRK_MISSING_PBO BIT(1) + +/* Initialise device control field even if logical_minimum != 1 */ +#define HID_PIDFF_QUIRK_PERMISSIVE_CONTROL BIT(2) + +/* Use fixed 0x4000 direction during SET_EFFECT report upload */ +#define HID_PIDFF_QUIRK_FIX_WHEEL_DIRECTION BIT(3) + +/* Force all periodic effects to be uploaded as SINE */ +#define HID_PIDFF_QUIRK_PERIODIC_SINE_ONLY BIT(4) + +#ifdef CONFIG_HID_PID +int hid_pidff_init(struct hid_device *hid); +int hid_pidff_init_with_quirks(struct hid_device *hid, u32 initial_quirks); +#else +#define hid_pidff_init NULL +#define hid_pidff_init_with_quirks NULL +#endif + +#endif diff --git a/include/linux/hid.h b/include/linux/hid.h index 495b5b3b2cb8..018de72505b0 100644 --- a/include/linux/hid.h +++ b/include/linux/hid.h @@ -1221,21 +1221,6 @@ unsigned long hid_lookup_quirk(const struct hid_device *hdev); int hid_quirks_init(char **quirks_param, __u16 bus, int count); void hid_quirks_exit(__u16 bus); -#ifdef CONFIG_HID_PID -int hid_pidff_init(struct hid_device *hid); -int hid_pidff_init_with_quirks(struct hid_device *hid, __u32 initial_quirks); -#else -#define hid_pidff_init NULL -#define hid_pidff_init_with_quirks NULL -#endif - -/* HID PIDFF quirks */ -#define HID_PIDFF_QUIRK_MISSING_DELAY BIT(0) -#define HID_PIDFF_QUIRK_MISSING_PBO BIT(1) -#define HID_PIDFF_QUIRK_PERMISSIVE_CONTROL BIT(2) -#define HID_PIDFF_QUIRK_FIX_WHEEL_DIRECTION BIT(3) -#define HID_PIDFF_QUIRK_PERIODIC_SINE_ONLY BIT(4) - #define dbg_hid(fmt, ...) pr_debug("%s: " fmt, __FILE__, ##__VA_ARGS__) #define hid_err(hid, fmt, ...) \ From 87783d301e9893451ff52ed2f3d81c14365a5083 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Paku=C5=82a?= Date: Sat, 1 Feb 2025 12:39:04 +0100 Subject: [PATCH 009/136] HID: pidff: Simplify pidff_rescale_signed MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [ Upstream commit 4eb9c2ee538b62dc5dcae192297c3a4044b7ade5 ] This function overrelies on ternary operators and makes it hard to parse it mentally. New version makes it very easy to understand. Signed-off-by: Tomasz Pakuła Reviewed-by: Michał Kopeć Reviewed-by: Paul Dino Jones Tested-by: Paul Dino Jones Tested-by: Cristóferson Bueno Tested-by: Pablo Cisneros Signed-off-by: Jiri Kosina Signed-off-by: Sasha Levin --- drivers/hid/usbhid/hid-pidff.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/hid/usbhid/hid-pidff.c b/drivers/hid/usbhid/hid-pidff.c index a8eaa77e80be..8083eb7684e5 100644 --- a/drivers/hid/usbhid/hid-pidff.c +++ b/drivers/hid/usbhid/hid-pidff.c @@ -230,9 +230,9 @@ static int pidff_rescale(int i, int max, struct hid_field *field) */ static int pidff_rescale_signed(int i, struct hid_field *field) { - return i == 0 ? 0 : i > - 0 ? i * field->logical_maximum / 0x7fff : i * - field->logical_minimum / -0x8000; + if (i > 0) return i * field->logical_maximum / 0x7fff; + if (i < 0) return i * field->logical_minimum / -0x8000; + return 0; } /* From 6fbf2ac6d5b63312167977d14288b68dcfc3d37d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Paku=C5=82a?= Date: Sat, 1 Feb 2025 12:39:05 +0100 Subject: [PATCH 010/136] HID: pidff: Use macros instead of hardcoded min/max values for shorts MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [ Upstream commit 21755162456902998f8d9897086b8c980c540df5 ] Makes it obvious these magic values ARE in fact derived from min and max values for s16 and u16 Signed-off-by: Tomasz Pakuła Reviewed-by: Michał Kopeć Reviewed-by: Paul Dino Jones Tested-by: Paul Dino Jones Tested-by: Cristóferson Bueno Tested-by: Pablo Cisneros Signed-off-by: Jiri Kosina Signed-off-by: Sasha Levin --- drivers/hid/usbhid/hid-pidff.c | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/drivers/hid/usbhid/hid-pidff.c b/drivers/hid/usbhid/hid-pidff.c index 8083eb7684e5..b21e844f5f3a 100644 --- a/drivers/hid/usbhid/hid-pidff.c +++ b/drivers/hid/usbhid/hid-pidff.c @@ -21,7 +21,7 @@ #define PID_EFFECTS_MAX 64 -#define PID_INFINITE 0xffff +#define PID_INFINITE U16_MAX /* Linux Force Feedback API uses miliseconds as time unit */ #define FF_TIME_EXPONENT -3 @@ -226,12 +226,12 @@ static int pidff_rescale(int i, int max, struct hid_field *field) } /* - * Scale a signed value in range -0x8000..0x7fff for the given field + * Scale a signed value in range S16_MIN..S16_MAX for the given field */ static int pidff_rescale_signed(int i, struct hid_field *field) { - if (i > 0) return i * field->logical_maximum / 0x7fff; - if (i < 0) return i * field->logical_minimum / -0x8000; + if (i > 0) return i * field->logical_maximum / S16_MAX; + if (i < 0) return i * field->logical_minimum / S16_MIN; return 0; } @@ -255,7 +255,7 @@ static u32 pidff_rescale_time(u16 time, struct hid_field *field) static void pidff_set(struct pidff_usage *usage, u16 value) { - usage->value[0] = pidff_rescale(value, 0xffff, usage->field); + usage->value[0] = pidff_rescale(value, U16_MAX, usage->field); pr_debug("calculated from %d to %d\n", value, usage->value[0]); } @@ -266,10 +266,10 @@ static void pidff_set_signed(struct pidff_usage *usage, s16 value) else { if (value < 0) usage->value[0] = - pidff_rescale(-value, 0x8000, usage->field); + pidff_rescale(-value, -S16_MIN, usage->field); else usage->value[0] = - pidff_rescale(value, 0x7fff, usage->field); + pidff_rescale(value, S16_MAX, usage->field); } pr_debug("calculated from %d to %d\n", value, usage->value[0]); } @@ -306,11 +306,11 @@ static void pidff_set_envelope_report(struct pidff_device *pidff, pidff->set_envelope[PID_ATTACK_LEVEL].value[0] = pidff_rescale(envelope->attack_level > - 0x7fff ? 0x7fff : envelope->attack_level, 0x7fff, + S16_MAX ? S16_MAX : envelope->attack_level, S16_MAX, pidff->set_envelope[PID_ATTACK_LEVEL].field); pidff->set_envelope[PID_FADE_LEVEL].value[0] = pidff_rescale(envelope->fade_level > - 0x7fff ? 0x7fff : envelope->fade_level, 0x7fff, + S16_MAX ? S16_MAX : envelope->fade_level, S16_MAX, pidff->set_envelope[PID_FADE_LEVEL].field); pidff_set_time(&pidff->set_envelope[PID_ATTACK_TIME], @@ -399,7 +399,7 @@ static void pidff_set_effect_report(struct pidff_device *pidff, pidff->effect_direction->value[0] = pidff_rescale( pidff->quirks & HID_PIDFF_QUIRK_FIX_WHEEL_DIRECTION ? PIDFF_FIXED_WHEEL_DIRECTION : effect->direction, - 0xffff, pidff->effect_direction); + U16_MAX, pidff->effect_direction); /* Omit setting delay field if it's missing */ if (!(pidff->quirks & HID_PIDFF_QUIRK_MISSING_DELAY)) @@ -1366,7 +1366,7 @@ static int pidff_check_autocenter(struct pidff_device *pidff, if (pidff->block_load[PID_EFFECT_BLOCK_INDEX].value[0] == pidff->block_load[PID_EFFECT_BLOCK_INDEX].field->logical_minimum + 1) { - pidff_autocenter(pidff, 0xffff); + pidff_autocenter(pidff, U16_MAX); set_bit(FF_AUTOCENTER, dev->ffbit); } else { hid_notice(pidff->hid, @@ -1424,7 +1424,7 @@ int hid_pidff_init_with_quirks(struct hid_device *hid, u32 initial_quirks) if (error) goto fail; - pidff_set_gain_report(pidff, 0xffff); + pidff_set_gain_report(pidff, U16_MAX); error = pidff_check_autocenter(pidff, dev); if (error) goto fail; From 13d15dd6175e1e3eb70ce95e3da0b8a0a5a54d34 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Paku=C5=82a?= Date: Sat, 1 Feb 2025 12:39:06 +0100 Subject: [PATCH 011/136] HID: pidff: Factor out pool report fetch and remove excess declaration MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [ Upstream commit 5d98079b2d0186e1f586301a9c00144a669416a8 ] We only want to refetch the pool report during device init. Reset function is now called when uploading effects to an empty device so extract pool fetch to separate function and call it from init before autocenter check (autocenter check triggered reset during init). Remove a superfluous pointer declaration and assigment as well. Signed-off-by: Tomasz Pakuła Reviewed-by: Michał Kopeć Reviewed-by: Paul Dino Jones Tested-by: Paul Dino Jones Tested-by: Cristóferson Bueno Tested-by: Pablo Cisneros Signed-off-by: Jiri Kosina Signed-off-by: Sasha Levin --- drivers/hid/usbhid/hid-pidff.c | 45 ++++++++++++++++++---------------- 1 file changed, 24 insertions(+), 21 deletions(-) diff --git a/drivers/hid/usbhid/hid-pidff.c b/drivers/hid/usbhid/hid-pidff.c index b21e844f5f3a..f23381b6e344 100644 --- a/drivers/hid/usbhid/hid-pidff.c +++ b/drivers/hid/usbhid/hid-pidff.c @@ -591,12 +591,9 @@ static void pidff_modify_actuators_state(struct pidff_device *pidff, bool enable /* * Reset the device, stop all effects, enable actuators - * Refetch pool report */ static void pidff_reset(struct pidff_device *pidff) { - int i = 0; - /* We reset twice as sometimes hid_wait_io isn't waiting long enough */ pidff_send_device_control(pidff, PID_RESET); pidff_send_device_control(pidff, PID_RESET); @@ -604,23 +601,29 @@ static void pidff_reset(struct pidff_device *pidff) pidff_send_device_control(pidff, PID_STOP_ALL_EFFECTS); pidff_modify_actuators_state(pidff, 1); +} - /* pool report is sometimes messed up, refetch it */ - hid_hw_request(pidff->hid, pidff->reports[PID_POOL], HID_REQ_GET_REPORT); - hid_hw_wait(pidff->hid); +/* + * Refetch pool report + */ +static void pidff_fetch_pool(struct pidff_device *pidff) +{ + if (!pidff->pool[PID_SIMULTANEOUS_MAX].value) + return; - if (pidff->pool[PID_SIMULTANEOUS_MAX].value) { - while (pidff->pool[PID_SIMULTANEOUS_MAX].value[0] < 2) { - if (i++ > 20) { - hid_warn(pidff->hid, - "device reports %d simultaneous effects\n", - pidff->pool[PID_SIMULTANEOUS_MAX].value[0]); - break; - } - hid_dbg(pidff->hid, "pid_pool requested again\n"); - hid_hw_request(pidff->hid, pidff->reports[PID_POOL], - HID_REQ_GET_REPORT); - hid_hw_wait(pidff->hid); + int i = 0; + while (pidff->pool[PID_SIMULTANEOUS_MAX].value[0] < 2) { + hid_dbg(pidff->hid, "pid_pool requested again\n"); + hid_hw_request(pidff->hid, pidff->reports[PID_POOL], + HID_REQ_GET_REPORT); + hid_hw_wait(pidff->hid); + + /* break after 20 tries with SIMULTANEOUS_MAX < 2 */ + if (i++ > 20) { + hid_warn(pidff->hid, + "device reports %d simultaneous effects\n", + pidff->pool[PID_SIMULTANEOUS_MAX].value[0]); + break; } } } @@ -916,9 +919,7 @@ static void pidff_autocenter(struct pidff_device *pidff, u16 magnitude) */ static void pidff_set_autocenter(struct input_dev *dev, u16 magnitude) { - struct pidff_device *pidff = dev->ff->private; - - pidff_autocenter(pidff, magnitude); + pidff_autocenter(dev->ff->private, magnitude); } /* @@ -1424,6 +1425,8 @@ int hid_pidff_init_with_quirks(struct hid_device *hid, u32 initial_quirks) if (error) goto fail; + /* pool report is sometimes messed up, refetch it */ + pidff_fetch_pool(pidff); pidff_set_gain_report(pidff, U16_MAX); error = pidff_check_autocenter(pidff, dev); if (error) From 211861869766a7bb7c72158aee0140ec67e182a7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Paku=C5=82a?= Date: Tue, 11 Feb 2025 15:35:08 +0100 Subject: [PATCH 012/136] HID: pidff: Make sure to fetch pool before checking SIMULTANEOUS_MAX MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [ Upstream commit 1f650dcec32d22deb1d6db12300a2b98483099a9 ] As noted by Anssi some 20 years ago, pool report is sometimes messed up. This worked fine on many devices but casued oops on VRS DirectForce PRO. Here, we're making sure pool report is refetched before trying to access any of it's fields. While loop was replaced with a for loop + exit conditions were moved aroud to decrease the possibility of creating an infinite loop scenario. Signed-off-by: Tomasz Pakuła Signed-off-by: Jiri Kosina Signed-off-by: Sasha Levin --- drivers/hid/usbhid/hid-pidff.c | 29 +++++++++++++---------------- 1 file changed, 13 insertions(+), 16 deletions(-) diff --git a/drivers/hid/usbhid/hid-pidff.c b/drivers/hid/usbhid/hid-pidff.c index f23381b6e344..503f643b59ca 100644 --- a/drivers/hid/usbhid/hid-pidff.c +++ b/drivers/hid/usbhid/hid-pidff.c @@ -604,28 +604,25 @@ static void pidff_reset(struct pidff_device *pidff) } /* - * Refetch pool report + * Fetch pool report */ static void pidff_fetch_pool(struct pidff_device *pidff) { - if (!pidff->pool[PID_SIMULTANEOUS_MAX].value) - return; + int i; + struct hid_device *hid = pidff->hid; - int i = 0; - while (pidff->pool[PID_SIMULTANEOUS_MAX].value[0] < 2) { - hid_dbg(pidff->hid, "pid_pool requested again\n"); - hid_hw_request(pidff->hid, pidff->reports[PID_POOL], - HID_REQ_GET_REPORT); - hid_hw_wait(pidff->hid); + /* Repeat if PID_SIMULTANEOUS_MAX < 2 to make sure it's correct */ + for(i = 0; i < 20; i++) { + hid_hw_request(hid, pidff->reports[PID_POOL], HID_REQ_GET_REPORT); + hid_hw_wait(hid); - /* break after 20 tries with SIMULTANEOUS_MAX < 2 */ - if (i++ > 20) { - hid_warn(pidff->hid, - "device reports %d simultaneous effects\n", - pidff->pool[PID_SIMULTANEOUS_MAX].value[0]); - break; - } + if (!pidff->pool[PID_SIMULTANEOUS_MAX].value) + return; + if (pidff->pool[PID_SIMULTANEOUS_MAX].value[0] >= 2) + return; } + hid_warn(hid, "device reports %d simultaneous effects\n", + pidff->pool[PID_SIMULTANEOUS_MAX].value[0]); } /* From 35ebc643aff90e08f6696f75d49dc26e33fe3b50 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Paku=C5=82a?= Date: Tue, 11 Feb 2025 15:35:09 +0100 Subject: [PATCH 013/136] HID: hid-universal-pidff: Add Asetek wheelbases support MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [ Upstream commit c385f61108d403633e8cfbdae15b35ccf7cee686 ] Adds Asetek vendor id and product ids for: - Invicta - Forte - La Prima - Tony Kanaan v2: - Misc spelling fix in driver loaded info v3: - Chanage Oleg's name order Signed-off-by: Tomasz Pakuła Signed-off-by: Jiri Kosina Signed-off-by: Sasha Levin --- drivers/hid/hid-ids.h | 6 ++++++ drivers/hid/hid-universal-pidff.c | 10 +++++++--- 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h index 08be87b3cc99..92baa34f42f2 100644 --- a/drivers/hid/hid-ids.h +++ b/drivers/hid/hid-ids.h @@ -190,6 +190,12 @@ #define USB_DEVICE_ID_APPLE_TOUCHBAR_BACKLIGHT 0x8102 #define USB_DEVICE_ID_APPLE_TOUCHBAR_DISPLAY 0x8302 +#define USB_VENDOR_ID_ASETEK 0x2433 +#define USB_DEVICE_ID_ASETEK_INVICTA 0xf300 +#define USB_DEVICE_ID_ASETEK_FORTE 0xf301 +#define USB_DEVICE_ID_ASETEK_LA_PRIMA 0xf303 +#define USB_DEVICE_ID_ASETEK_TONY_KANAAN 0xf306 + #define USB_VENDOR_ID_ASUS 0x0486 #define USB_DEVICE_ID_ASUS_T91MT 0x0185 #define USB_DEVICE_ID_ASUSTEK_MULTITOUCH_YFO 0x0186 diff --git a/drivers/hid/hid-universal-pidff.c b/drivers/hid/hid-universal-pidff.c index 1b713b741d19..5b89ec7b5c26 100644 --- a/drivers/hid/hid-universal-pidff.c +++ b/drivers/hid/hid-universal-pidff.c @@ -4,7 +4,7 @@ * hid-pidff wrapper for PID-enabled devices * Handles device reports, quirks and extends usable button range * - * Copyright (c) 2024, 2025 Makarenko Oleg + * Copyright (c) 2024, 2025 Oleg Makarenko * Copyright (c) 2024, 2025 Tomasz Pakuła */ @@ -104,7 +104,7 @@ static int universal_pidff_probe(struct hid_device *hdev, goto err; } - hid_info(hdev, "Universal pidff driver loaded sucesfully!"); + hid_info(hdev, "Universal pidff driver loaded sucessfully!"); return 0; err: @@ -179,6 +179,10 @@ static const struct hid_device_id universal_pidff_devices[] = { .driver_data = HID_PIDFF_QUIRK_PERIODIC_SINE_ONLY }, { HID_USB_DEVICE(USB_VENDOR_ID_LITE_STAR, USB_DEVICE_LITE_STAR_GT987_FF), .driver_data = HID_PIDFF_QUIRK_PERIODIC_SINE_ONLY }, + { HID_USB_DEVICE(USB_VENDOR_ID_ASETEK, USB_DEVICE_ID_ASETEK_INVICTA) }, + { HID_USB_DEVICE(USB_VENDOR_ID_ASETEK, USB_DEVICE_ID_ASETEK_FORTE) }, + { HID_USB_DEVICE(USB_VENDOR_ID_ASETEK, USB_DEVICE_ID_ASETEK_LA_PRIMA) }, + { HID_USB_DEVICE(USB_VENDOR_ID_ASETEK, USB_DEVICE_ID_ASETEK_TONY_KANAAN) }, { } }; MODULE_DEVICE_TABLE(hid, universal_pidff_devices); @@ -194,5 +198,5 @@ module_hid_driver(universal_pidff); MODULE_DESCRIPTION("Universal driver for USB PID Force Feedback devices"); MODULE_LICENSE("GPL"); -MODULE_AUTHOR("Makarenko Oleg "); +MODULE_AUTHOR("Oleg Makarenko "); MODULE_AUTHOR("Tomasz Pakuła "); From 2d698115f9b3e44caf03b9899a3100f2a1075000 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Paku=C5=82a?= Date: Tue, 11 Feb 2025 15:35:10 +0100 Subject: [PATCH 014/136] HID: pidff: Comment and code style update MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [ Upstream commit e19675c2477491401b236ed939ad5a43ddc339af ] Update comments to fully conform to the Linux comment styling. Define Linux infinite effect duration (0) as FF_INFINITE Chanage Oleg's name order Signed-off-by: Tomasz Pakuła Signed-off-by: Jiri Kosina Signed-off-by: Sasha Levin --- drivers/hid/usbhid/hid-pidff.c | 57 +++++++++++++++------------------- 1 file changed, 25 insertions(+), 32 deletions(-) diff --git a/drivers/hid/usbhid/hid-pidff.c b/drivers/hid/usbhid/hid-pidff.c index 503f643b59ca..e2508a4d754d 100644 --- a/drivers/hid/usbhid/hid-pidff.c +++ b/drivers/hid/usbhid/hid-pidff.c @@ -3,13 +3,9 @@ * Force feedback driver for USB HID PID compliant devices * * Copyright (c) 2005, 2006 Anssi Hannula + * Upgraded 2025 by Oleg Makarenko and Tomasz Pakuła */ -/* - */ - -/* #define DEBUG */ - #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt #include "hid-pidff.h" @@ -25,9 +21,9 @@ /* Linux Force Feedback API uses miliseconds as time unit */ #define FF_TIME_EXPONENT -3 +#define FF_INFINITE 0 /* Report usage table used to put reports into an array */ - #define PID_SET_EFFECT 0 #define PID_EFFECT_OPERATION 1 #define PID_DEVICE_GAIN 2 @@ -48,12 +44,12 @@ static const u8 pidff_reports[] = { 0x21, 0x77, 0x7d, 0x7f, 0x89, 0x90, 0x96, 0xab, 0x5a, 0x5f, 0x6e, 0x73, 0x74 }; - -/* device_control is really 0x95, but 0x96 specified as it is the usage of -the only field in that report */ +/* + * device_control is really 0x95, but 0x96 specified + * as it is the usage of the only field in that report. + */ /* PID special fields */ - #define PID_EFFECT_TYPE 0x25 #define PID_DIRECTION 0x57 #define PID_EFFECT_OPERATION_ARRAY 0x78 @@ -61,7 +57,6 @@ the only field in that report */ #define PID_DEVICE_CONTROL_ARRAY 0x96 /* Value usage tables used to put fields and values into arrays */ - #define PID_EFFECT_BLOCK_INDEX 0 #define PID_DURATION 1 @@ -119,7 +114,6 @@ static const u8 pidff_device_gain[] = { 0x7e }; static const u8 pidff_pool[] = { 0x80, 0x83, 0xa9 }; /* Special field key tables used to put special field keys into arrays */ - #define PID_ENABLE_ACTUATORS 0 #define PID_DISABLE_ACTUATORS 1 #define PID_STOP_ALL_EFFECTS 2 @@ -176,8 +170,10 @@ struct pidff_device { struct pidff_usage effect_operation[sizeof(pidff_effect_operation)]; struct pidff_usage block_free[sizeof(pidff_block_free)]; - /* Special field is a field that is not composed of - usage<->value pairs that pidff_usage values are */ + /* + * Special field is a field that is not composed of + * usage<->value pairs that pidff_usage values are + */ /* Special field in create_new_effect */ struct hid_field *create_new_effect_type; @@ -222,7 +218,7 @@ static s32 pidff_clamp(s32 i, struct hid_field *field) static int pidff_rescale(int i, int max, struct hid_field *field) { return i * (field->logical_maximum - field->logical_minimum) / max + - field->logical_minimum; + field->logical_minimum; } /* @@ -282,9 +278,8 @@ static void pidff_set_time(struct pidff_usage *usage, u16 time) static void pidff_set_duration(struct pidff_usage *usage, u16 duration) { - /* Convert infinite length from Linux API (0) - to PID standard (NULL) if needed */ - if (duration == 0) + /* Infinite value conversion from Linux API -> PID */ + if (duration == FF_INFINITE) duration = PID_INFINITE; if (duration == PID_INFINITE) { @@ -302,16 +297,16 @@ static void pidff_set_envelope_report(struct pidff_device *pidff, struct ff_envelope *envelope) { pidff->set_envelope[PID_EFFECT_BLOCK_INDEX].value[0] = - pidff->block_load[PID_EFFECT_BLOCK_INDEX].value[0]; + pidff->block_load[PID_EFFECT_BLOCK_INDEX].value[0]; pidff->set_envelope[PID_ATTACK_LEVEL].value[0] = - pidff_rescale(envelope->attack_level > - S16_MAX ? S16_MAX : envelope->attack_level, S16_MAX, - pidff->set_envelope[PID_ATTACK_LEVEL].field); + pidff_rescale(envelope->attack_level > + S16_MAX ? S16_MAX : envelope->attack_level, S16_MAX, + pidff->set_envelope[PID_ATTACK_LEVEL].field); pidff->set_envelope[PID_FADE_LEVEL].value[0] = - pidff_rescale(envelope->fade_level > - S16_MAX ? S16_MAX : envelope->fade_level, S16_MAX, - pidff->set_envelope[PID_FADE_LEVEL].field); + pidff_rescale(envelope->fade_level > + S16_MAX ? S16_MAX : envelope->fade_level, S16_MAX, + pidff->set_envelope[PID_FADE_LEVEL].field); pidff_set_time(&pidff->set_envelope[PID_ATTACK_TIME], envelope->attack_length); @@ -702,9 +697,7 @@ static void pidff_playback_pid(struct pidff_device *pidff, int pid_id, int n) static int pidff_playback(struct input_dev *dev, int effect_id, int value) { struct pidff_device *pidff = dev->ff->private; - pidff_playback_pid(pidff, pidff->pid_id[effect_id], value); - return 0; } @@ -732,8 +725,11 @@ static int pidff_erase_effect(struct input_dev *dev, int effect_id) hid_dbg(pidff->hid, "starting to erase %d/%d\n", effect_id, pidff->pid_id[effect_id]); - /* Wait for the queue to clear. We do not want a full fifo to - prevent the effect removal. */ + + /* + * Wait for the queue to clear. We do not want + * a full fifo to prevent the effect removal. + */ hid_hw_wait(pidff->hid); pidff_playback_pid(pidff, pid_id, 0); pidff_erase_pid(pidff, pid_id); @@ -1239,7 +1235,6 @@ static int pidff_find_effects(struct pidff_device *pidff, set_bit(FF_FRICTION, dev->ffbit); return 0; - } #define PIDFF_FIND_FIELDS(name, report, strict) \ @@ -1370,12 +1365,10 @@ static int pidff_check_autocenter(struct pidff_device *pidff, hid_notice(pidff->hid, "device has unknown autocenter control method\n"); } - pidff_erase_pid(pidff, pidff->block_load[PID_EFFECT_BLOCK_INDEX].value[0]); return 0; - } /* From 239c8ac58cfc35dc61e53770f0bd24ea8d685d72 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Paku=C5=82a?= Date: Tue, 11 Feb 2025 15:35:11 +0100 Subject: [PATCH 015/136] HID: pidff: Support device error response from PID_BLOCK_LOAD MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [ Upstream commit 9d4174dc4a234408d91fd83725e1899766cd1731 ] If an error happens on the device, the driver will no longer fall into the trap of reading this status 60 times before it decides that this reply won't change to success/memory full. Greatly reduces communication overhead during device error situation. Signed-off-by: Tomasz Pakuła Signed-off-by: Jiri Kosina Signed-off-by: Sasha Levin --- drivers/hid/usbhid/hid-pidff.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/drivers/hid/usbhid/hid-pidff.c b/drivers/hid/usbhid/hid-pidff.c index e2508a4d754d..d5734cbf745d 100644 --- a/drivers/hid/usbhid/hid-pidff.c +++ b/drivers/hid/usbhid/hid-pidff.c @@ -138,7 +138,8 @@ static const u8 pidff_effect_types[] = { #define PID_BLOCK_LOAD_SUCCESS 0 #define PID_BLOCK_LOAD_FULL 1 -static const u8 pidff_block_load_status[] = { 0x8c, 0x8d }; +#define PID_BLOCK_LOAD_ERROR 2 +static const u8 pidff_block_load_status[] = { 0x8c, 0x8d, 0x8e}; #define PID_EFFECT_START 0 #define PID_EFFECT_STOP 1 @@ -666,6 +667,11 @@ static int pidff_request_effect_upload(struct pidff_device *pidff, int efnum) pidff->block_load[PID_RAM_POOL_AVAILABLE].value[0] : -1); return -ENOSPC; } + if (pidff->block_load_status->value[0] == + pidff->status_id[PID_BLOCK_LOAD_ERROR]) { + hid_dbg(pidff->hid, "device error during effect creation\n"); + return -EREMOTEIO; + } } hid_err(pidff->hid, "pid_block_load failed 60 times\n"); return -EIO; From b782892cd264629caf810ca0d2c17fb77c6dc92a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Paku=C5=82a?= Date: Tue, 11 Feb 2025 15:35:12 +0100 Subject: [PATCH 016/136] HID: pidff: Remove redundant call to pidff_find_special_keys MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [ Upstream commit 1bd55e79cbc0ea2d6a65f51e06c891806359c2f2 ] Probably left out as a mistake after Anssi created the helper macro Signed-off-by: Tomasz Pakuła Signed-off-by: Jiri Kosina Signed-off-by: Sasha Levin --- drivers/hid/usbhid/hid-pidff.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/drivers/hid/usbhid/hid-pidff.c b/drivers/hid/usbhid/hid-pidff.c index d5734cbf745d..6f6c47bd57ea 100644 --- a/drivers/hid/usbhid/hid-pidff.c +++ b/drivers/hid/usbhid/hid-pidff.c @@ -1159,10 +1159,6 @@ static int pidff_find_special_fields(struct pidff_device *pidff) return -1; } - pidff_find_special_keys(pidff->control_id, pidff->device_control, - pidff_device_control, - sizeof(pidff_device_control)); - PIDFF_FIND_SPECIAL_KEYS(control_id, device_control, device_control); if (!PIDFF_FIND_SPECIAL_KEYS(type_id, create_new_effect_type, From 42ec3b5bf7e6980ec219888fdb9e0090bd83cb30 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Paku=C5=82a?= Date: Tue, 25 Feb 2025 23:30:00 +0100 Subject: [PATCH 017/136] HID: pidff: Rename two functions to align them with naming convention MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [ Upstream commit bbeface1051142bcb0473fdcc89102ea5b31607d ] Driver uses "set" everywhere to indicate setting report values and requesting HID_REQ_SET_REPORT Signed-off-by: Tomasz Pakuła Signed-off-by: Jiri Kosina Signed-off-by: Sasha Levin --- drivers/hid/usbhid/hid-pidff.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/drivers/hid/usbhid/hid-pidff.c b/drivers/hid/usbhid/hid-pidff.c index 6f6c47bd57ea..ffecc712be00 100644 --- a/drivers/hid/usbhid/hid-pidff.c +++ b/drivers/hid/usbhid/hid-pidff.c @@ -552,7 +552,7 @@ static void pidff_set_gain_report(struct pidff_device *pidff, u16 gain) /* * Clear device control report */ -static void pidff_send_device_control(struct pidff_device *pidff, int field) +static void pidff_set_device_control(struct pidff_device *pidff, int field) { int i, tmp; int field_index = pidff->control_id[field]; @@ -578,10 +578,10 @@ static void pidff_send_device_control(struct pidff_device *pidff, int field) /* * Modify actuators state */ -static void pidff_modify_actuators_state(struct pidff_device *pidff, bool enable) +static void pidff_set_actuators(struct pidff_device *pidff, bool enable) { hid_dbg(pidff->hid, "%s actuators\n", enable ? "Enable" : "Disable"); - pidff_send_device_control(pidff, + pidff_set_device_control(pidff, enable ? PID_ENABLE_ACTUATORS : PID_DISABLE_ACTUATORS); } @@ -591,12 +591,12 @@ static void pidff_modify_actuators_state(struct pidff_device *pidff, bool enable static void pidff_reset(struct pidff_device *pidff) { /* We reset twice as sometimes hid_wait_io isn't waiting long enough */ - pidff_send_device_control(pidff, PID_RESET); - pidff_send_device_control(pidff, PID_RESET); + pidff_set_device_control(pidff, PID_RESET); + pidff_set_device_control(pidff, PID_RESET); pidff->effect_count = 0; - pidff_send_device_control(pidff, PID_STOP_ALL_EFFECTS); - pidff_modify_actuators_state(pidff, 1); + pidff_set_device_control(pidff, PID_STOP_ALL_EFFECTS); + pidff_set_actuators(pidff, 1); } /* From b15301f289602eb93bc0a0b823a95a0a37b60b0e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Paku=C5=82a?= Date: Tue, 25 Feb 2025 23:30:01 +0100 Subject: [PATCH 018/136] HID: pidff: Clamp effect playback LOOP_COUNT value MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [ Upstream commit 0c6673e3d17b258b8c5c7331d28bf6c49f25ed30 ] Ensures the loop count will never exceed the logical_maximum. Fixes implementation errors happening when applications use the max value of int32/DWORD as the effect iterations. This could be observed when running software both native and in wine. Signed-off-by: Tomasz Pakuła Signed-off-by: Jiri Kosina Signed-off-by: Sasha Levin --- drivers/hid/usbhid/hid-pidff.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/hid/usbhid/hid-pidff.c b/drivers/hid/usbhid/hid-pidff.c index ffecc712be00..74b033a4ac1b 100644 --- a/drivers/hid/usbhid/hid-pidff.c +++ b/drivers/hid/usbhid/hid-pidff.c @@ -690,7 +690,8 @@ static void pidff_playback_pid(struct pidff_device *pidff, int pid_id, int n) } else { pidff->effect_operation_status->value[0] = pidff->operation_id[PID_EFFECT_START]; - pidff->effect_operation[PID_LOOP_COUNT].value[0] = n; + pidff->effect_operation[PID_LOOP_COUNT].value[0] = + pidff_clamp(n, pidff->effect_operation[PID_LOOP_COUNT].field); } hid_hw_request(pidff->hid, pidff->reports[PID_EFFECT_OPERATION], From 5318556ed31fd6964818339e764f6817cc6a2041 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Paku=C5=82a?= Date: Tue, 25 Feb 2025 23:30:02 +0100 Subject: [PATCH 019/136] HID: pidff: Compute INFINITE value instead of using hardcoded 0xffff MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [ Upstream commit 1a575044d516972a1d036d54c0180b9085e21dc6 ] As per USB PID standard: INFINITE - Referrers to the maximum value of a range. i.e. if in an 8 bit unsigned field the value of 255 would indicate INFINITE. Detecting 0xffff (U16_MAX) is still important as we MIGHT get this value as infinite from some native software as 0 was never actually defined in Linux' FF api as the infinite value. I'm working on it though. Signed-off-by: Tomasz Pakuła Signed-off-by: Jiri Kosina Signed-off-by: Sasha Levin --- drivers/hid/usbhid/hid-pidff.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/hid/usbhid/hid-pidff.c b/drivers/hid/usbhid/hid-pidff.c index 74b033a4ac1b..a614438e43bd 100644 --- a/drivers/hid/usbhid/hid-pidff.c +++ b/drivers/hid/usbhid/hid-pidff.c @@ -283,8 +283,9 @@ static void pidff_set_duration(struct pidff_usage *usage, u16 duration) if (duration == FF_INFINITE) duration = PID_INFINITE; + /* PID defines INFINITE as the max possible value for duration field */ if (duration == PID_INFINITE) { - usage->value[0] = PID_INFINITE; + usage->value[0] = (1U << usage->field->report_size) - 1; return; } From 1565ead12f5c581550ef07c30ee33fe7022f9859 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Paku=C5=82a?= Date: Tue, 25 Feb 2025 23:30:03 +0100 Subject: [PATCH 020/136] HID: pidff: Fix 90 degrees direction name North -> East [ Upstream commit f98ecedbeca34a8df1460c3a03cce32639c99a9d ] Signed-off-by: Jiri Kosina Signed-off-by: Sasha Levin --- drivers/hid/usbhid/hid-pidff.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/hid/usbhid/hid-pidff.c b/drivers/hid/usbhid/hid-pidff.c index a614438e43bd..6eb7934c8f53 100644 --- a/drivers/hid/usbhid/hid-pidff.c +++ b/drivers/hid/usbhid/hid-pidff.c @@ -145,7 +145,7 @@ static const u8 pidff_block_load_status[] = { 0x8c, 0x8d, 0x8e}; #define PID_EFFECT_STOP 1 static const u8 pidff_effect_operation_status[] = { 0x79, 0x7b }; -/* Polar direction 90 degrees (North) */ +/* Polar direction 90 degrees (East) */ #define PIDFF_FIXED_WHEEL_DIRECTION 0x4000 struct pidff_usage { From bdbc38bd12eb36bbbcce4f013879c1755c9a9084 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Paku=C5=82a?= Date: Tue, 25 Feb 2025 23:30:04 +0100 Subject: [PATCH 021/136] HID: pidff: Fix set_device_control() [ Upstream commit e2fa0bdf08a70623f24ed52f2037a330999d9800 ] As the search for Device Control report is permissive, make sure the desired field was actually found, before trying to set it. Fix bitmask clearing as it was erronously using index instead of index - 1 (HID arrays index is 1-based). Add last two missing Device Control usages to the defined array. PID_PAUSE and PID_CONTINUE. Signed-off-by: Jiri Kosina Signed-off-by: Sasha Levin --- drivers/hid/usbhid/hid-pidff.c | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/drivers/hid/usbhid/hid-pidff.c b/drivers/hid/usbhid/hid-pidff.c index 6eb7934c8f53..8dfd2c554a27 100644 --- a/drivers/hid/usbhid/hid-pidff.c +++ b/drivers/hid/usbhid/hid-pidff.c @@ -118,7 +118,9 @@ static const u8 pidff_pool[] = { 0x80, 0x83, 0xa9 }; #define PID_DISABLE_ACTUATORS 1 #define PID_STOP_ALL_EFFECTS 2 #define PID_RESET 3 -static const u8 pidff_device_control[] = { 0x97, 0x98, 0x99, 0x9a }; +#define PID_PAUSE 4 +#define PID_CONTINUE 5 +static const u8 pidff_device_control[] = { 0x97, 0x98, 0x99, 0x9a, 0x9b, 0x9c }; #define PID_CONSTANT 0 #define PID_RAMP 1 @@ -551,21 +553,29 @@ static void pidff_set_gain_report(struct pidff_device *pidff, u16 gain) } /* - * Clear device control report + * Send device control report to the device */ static void pidff_set_device_control(struct pidff_device *pidff, int field) { - int i, tmp; + int i, index; int field_index = pidff->control_id[field]; + if (field_index < 1) + return; + /* Detect if the field is a bitmask variable or an array */ if (pidff->device_control->flags & HID_MAIN_ITEM_VARIABLE) { hid_dbg(pidff->hid, "DEVICE_CONTROL is a bitmask\n"); + /* Clear current bitmask */ for(i = 0; i < sizeof(pidff_device_control); i++) { - tmp = pidff->control_id[i]; - pidff->device_control->value[tmp] = 0; + index = pidff->control_id[i]; + if (index < 1) + continue; + + pidff->device_control->value[index - 1] = 0; } + pidff->device_control->value[field_index - 1] = 1; } else { hid_dbg(pidff->hid, "DEVICE_CONTROL is an array\n"); From a9a73da6e014e0469a5d03ecc4b8c7017ccc19c9 Mon Sep 17 00:00:00 2001 From: Haoxiang Li Date: Mon, 24 Feb 2025 18:15:27 +0800 Subject: [PATCH 022/136] auxdisplay: hd44780: Fix an API misuse in hd44780.c commit 9b98a7d2e5f4e2beeff88f6571da0cdc5883c7fb upstream. Variable allocated by charlcd_alloc() should be released by charlcd_free(). The following patch changed kfree() to charlcd_free() to fix an API misuse. Fixes: 718e05ed92ec ("auxdisplay: Introduce hd44780_common.[ch]") Cc: stable@vger.kernel.org Signed-off-by: Haoxiang Li Reviewed-by: Geert Uytterhoeven Signed-off-by: Andy Shevchenko Signed-off-by: Greg Kroah-Hartman --- drivers/auxdisplay/hd44780.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/auxdisplay/hd44780.c b/drivers/auxdisplay/hd44780.c index 025dc6855cb2..41807ce36339 100644 --- a/drivers/auxdisplay/hd44780.c +++ b/drivers/auxdisplay/hd44780.c @@ -313,7 +313,7 @@ static int hd44780_probe(struct platform_device *pdev) fail3: kfree(hd); fail2: - kfree(lcd); + charlcd_free(lcd); fail1: kfree(hdc); return ret; @@ -328,7 +328,7 @@ static void hd44780_remove(struct platform_device *pdev) kfree(hdc->hd44780); kfree(lcd->drvdata); - kfree(lcd); + charlcd_free(lcd); } static const struct of_device_id hd44780_of_match[] = { From 956c5e4965d59abff6bd9dc3e0f3566286db454e Mon Sep 17 00:00:00 2001 From: Alain Volmat Date: Mon, 10 Feb 2025 11:04:31 +0100 Subject: [PATCH 023/136] dt-bindings: media: st,stmipid02: correct lane-polarities maxItems commit 3a544a39e0a4c492e3026dfbed018321d2bd6caa upstream. The MIPID02 can use up to 2 data lanes which leads to having a maximum item number of 3 for the lane-polarities since this also contains the clock lane. CC: stable@vger.kernel.org Fixes: c2741cbe7f8a ("dt-bindings: media: st,stmipid02: Convert the text bindings to YAML") Signed-off-by: Alain Volmat Acked-by: Conor Dooley Signed-off-by: Hans Verkuil Signed-off-by: Greg Kroah-Hartman --- Documentation/devicetree/bindings/media/i2c/st,st-mipid02.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Documentation/devicetree/bindings/media/i2c/st,st-mipid02.yaml b/Documentation/devicetree/bindings/media/i2c/st,st-mipid02.yaml index b68141264c0e..4d40e75b4e1e 100644 --- a/Documentation/devicetree/bindings/media/i2c/st,st-mipid02.yaml +++ b/Documentation/devicetree/bindings/media/i2c/st,st-mipid02.yaml @@ -71,7 +71,7 @@ properties: description: Any lane can be inverted or not. minItems: 1 - maxItems: 2 + maxItems: 3 required: - data-lanes From 9f009fa823c54ca0857c81f7525ea5a5d32de29c Mon Sep 17 00:00:00 2001 From: Jiasheng Jiang Date: Tue, 18 Feb 2025 18:58:09 +0000 Subject: [PATCH 024/136] media: mediatek: vcodec: Fix a resource leak related to the scp device in FW initialization commit 4936cd5817af35d23e4d283f48fa59a18ef481e4 upstream. On Mediatek devices with a system companion processor (SCP) the mtk_scp structure has to be removed explicitly to avoid a resource leak. Free the structure in case the allocation of the firmware structure fails during the firmware initialization. Fixes: 53dbe0850444 ("media: mtk-vcodec: potential null pointer deference in SCP") Cc: stable@vger.kernel.org Signed-off-by: Jiasheng Jiang Signed-off-by: Hans Verkuil Signed-off-by: Greg Kroah-Hartman --- .../platform/mediatek/vcodec/common/mtk_vcodec_fw_scp.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/media/platform/mediatek/vcodec/common/mtk_vcodec_fw_scp.c b/drivers/media/platform/mediatek/vcodec/common/mtk_vcodec_fw_scp.c index ff23b225db70..1b0bc47355c0 100644 --- a/drivers/media/platform/mediatek/vcodec/common/mtk_vcodec_fw_scp.c +++ b/drivers/media/platform/mediatek/vcodec/common/mtk_vcodec_fw_scp.c @@ -79,8 +79,11 @@ struct mtk_vcodec_fw *mtk_vcodec_fw_scp_init(void *priv, enum mtk_vcodec_fw_use } fw = devm_kzalloc(&plat_dev->dev, sizeof(*fw), GFP_KERNEL); - if (!fw) + if (!fw) { + scp_put(scp); return ERR_PTR(-ENOMEM); + } + fw->type = SCP; fw->ops = &mtk_vcodec_rproc_msg; fw->scp = scp; From 8c64a2cfdbb810ca059a24742a13bd8bef5b1904 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Fri, 18 Oct 2024 15:21:10 +0000 Subject: [PATCH 025/136] media: mtk-vcodec: venc: avoid -Wenum-compare-conditional warning commit 07df4f23ef3ffe6fee697cd2e03623ad27108843 upstream. This is one of three clang warnings about incompatible enum types in a conditional expression: drivers/media/platform/mediatek/vcodec/encoder/venc/venc_h264_if.c:597:29: error: conditional expression between different enumeration types ('enum scp_ipi_id' and 'enum ipi_id') [-Werror,-Wenum-compare-conditional] 597 | inst->vpu_inst.id = is_ext ? SCP_IPI_VENC_H264 : IPI_VENC_H264; | ^ ~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~ The code is correct, so just rework it to avoid the warning. Fixes: 0dc4b3286125 ("media: mtk-vcodec: venc: support SCP firmware") Cc: stable@vger.kernel.org Signed-off-by: Arnd Bergmann Reviewed-by: Nathan Chancellor Reviewed-by: Alexandre Courbot Signed-off-by: Hans Verkuil Signed-off-by: Greg Kroah-Hartman --- .../platform/mediatek/vcodec/encoder/venc/venc_h264_if.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/drivers/media/platform/mediatek/vcodec/encoder/venc/venc_h264_if.c b/drivers/media/platform/mediatek/vcodec/encoder/venc/venc_h264_if.c index f8145998fcaf..8522f71fc901 100644 --- a/drivers/media/platform/mediatek/vcodec/encoder/venc/venc_h264_if.c +++ b/drivers/media/platform/mediatek/vcodec/encoder/venc/venc_h264_if.c @@ -594,7 +594,11 @@ static int h264_enc_init(struct mtk_vcodec_enc_ctx *ctx) inst->ctx = ctx; inst->vpu_inst.ctx = ctx; - inst->vpu_inst.id = is_ext ? SCP_IPI_VENC_H264 : IPI_VENC_H264; + if (is_ext) + inst->vpu_inst.id = SCP_IPI_VENC_H264; + else + inst->vpu_inst.id = IPI_VENC_H264; + inst->hw_base = mtk_vcodec_get_reg_addr(inst->ctx->dev->reg_base, VENC_SYS); ret = vpu_enc_init(&inst->vpu_inst); From ced0ddecc04b314e30c033c14e2fa964de40efa6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niklas=20S=C3=B6derlund?= Date: Wed, 12 Feb 2025 17:50:53 +0100 Subject: [PATCH 026/136] media: uapi: rkisp1-config: Fix typo in extensible params example MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit commit 7b0ee2de7c76e5518e2235a927fd211bc785d320 upstream. The define used for the version in the example diagram does not match what is defined in enum rksip1_ext_param_buffer_version, nor the description above it. Correct the typo to make it clear which define to use. Fixes: e9d05e9d5db1 ("media: uapi: rkisp1-config: Add extensible params format") Cc: stable@vger.kernel.org Signed-off-by: Niklas Söderlund Reviewed-by: Laurent Pinchart Signed-off-by: Hans Verkuil Signed-off-by: Greg Kroah-Hartman --- include/uapi/linux/rkisp1-config.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/uapi/linux/rkisp1-config.h b/include/uapi/linux/rkisp1-config.h index 430daceafac7..2d995f3c1ca3 100644 --- a/include/uapi/linux/rkisp1-config.h +++ b/include/uapi/linux/rkisp1-config.h @@ -1528,7 +1528,7 @@ enum rksip1_ext_param_buffer_version { * The expected memory layout of the parameters buffer is:: * * +-------------------- struct rkisp1_ext_params_cfg -------------------+ - * | version = RKISP_EXT_PARAMS_BUFFER_V1; | + * | version = RKISP1_EXT_PARAM_BUFFER_V1; | * | data_size = sizeof(struct rkisp1_ext_params_bls_config) | * | + sizeof(struct rkisp1_ext_params_dpcc_config); | * | +------------------------- data ---------------------------------+ | From 1c673fa8889ec04952c70ed343ab0a118200f70f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20T=C5=AFma?= Date: Fri, 21 Feb 2025 13:07:42 +0100 Subject: [PATCH 027/136] media: mgb4: Fix CMT registers update logic MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit commit dd05443189f9ae175dd806594b67bf55ddb6539e upstream. The CMT "magic values" registers must be updated while the CMT reset registers are active. Fixes: 0ab13674a9bd ("media: pci: mgb4: Added Digiteq Automotive MGB4 driver") Cc: stable@vger.kernel.org Signed-off-by: Martin Tůma Signed-off-by: Hans Verkuil Signed-off-by: Greg Kroah-Hartman --- drivers/media/pci/mgb4/mgb4_cmt.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/media/pci/mgb4/mgb4_cmt.c b/drivers/media/pci/mgb4/mgb4_cmt.c index a25b68403bc6..bee4bdf54d1c 100644 --- a/drivers/media/pci/mgb4/mgb4_cmt.c +++ b/drivers/media/pci/mgb4/mgb4_cmt.c @@ -206,10 +206,11 @@ u32 mgb4_cmt_set_vout_freq(struct mgb4_vout_dev *voutdev, unsigned int freq) mgb4_write_reg(video, regs->config, 0x1 | (config & ~0x3)); + mgb4_mask_reg(video, regs->config, 0x100, 0x100); + for (i = 0; i < ARRAY_SIZE(cmt_addrs_out[0]); i++) mgb4_write_reg(&voutdev->mgbdev->cmt, addr[i], reg_set[i]); - mgb4_mask_reg(video, regs->config, 0x100, 0x100); mgb4_mask_reg(video, regs->config, 0x100, 0x0); mgb4_write_reg(video, regs->config, config & ~0x1); @@ -236,10 +237,11 @@ void mgb4_cmt_set_vin_freq_range(struct mgb4_vin_dev *vindev, mgb4_write_reg(video, regs->config, 0x1 | (config & ~0x3)); + mgb4_mask_reg(video, regs->config, 0x1000, 0x1000); + for (i = 0; i < ARRAY_SIZE(cmt_addrs_in[0]); i++) mgb4_write_reg(&vindev->mgbdev->cmt, addr[i], reg_set[i]); - mgb4_mask_reg(video, regs->config, 0x1000, 0x1000); mgb4_mask_reg(video, regs->config, 0x1000, 0x0); mgb4_write_reg(video, regs->config, config & ~0x1); From 66e35600f7264d1b69b1fcab906b6477a552bc1a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niklas=20S=C3=B6derlund?= Date: Tue, 21 Jan 2025 21:44:00 +0100 Subject: [PATCH 028/136] media: i2c: adv748x: Fix test pattern selection mask MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit commit 9e38acacb9d809b97a0bdc5c76e725355a47158a upstream. The mask to select the test-pattern in register ADV748X_SDP_FRP is incorrect, it's the lower 3 bits which controls the pattern. The GENMASK() macro is used incorrectly and the generated mask is 0x0e instead of 0x07. The result is that not all test patterns are selectable, and that in some cases the wrong test pattern is activated. Fix this by correcting the GENMASK(). Fixes: 3e89586a64df ("media: i2c: adv748x: add adv748x driver") Cc: stable@vger.kernel.org Signed-off-by: Niklas Söderlund Reviewed-by: Kieran Bingham Signed-off-by: Hans Verkuil [hverkuil: fixed tiny typo in commit log: my -> by] Signed-off-by: Greg Kroah-Hartman --- drivers/media/i2c/adv748x/adv748x.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/media/i2c/adv748x/adv748x.h b/drivers/media/i2c/adv748x/adv748x.h index 9bc0121d0eff..2c1db5968af8 100644 --- a/drivers/media/i2c/adv748x/adv748x.h +++ b/drivers/media/i2c/adv748x/adv748x.h @@ -320,7 +320,7 @@ struct adv748x_state { /* Free run pattern select */ #define ADV748X_SDP_FRP 0x14 -#define ADV748X_SDP_FRP_MASK GENMASK(3, 1) +#define ADV748X_SDP_FRP_MASK GENMASK(2, 0) /* Saturation */ #define ADV748X_SDP_SD_SAT_U 0xe3 /* user_map_rw_reg_e3 */ From f598940803cd2800796c5433abec82ccef48f21e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20T=C5=AFma?= Date: Fri, 21 Feb 2025 13:07:43 +0100 Subject: [PATCH 029/136] media: mgb4: Fix switched CMT frequency range "magic values" sets MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit commit 450acf0840232eaf6eb7a80da11cf492e57498e8 upstream. The reason why this passed unnoticed is that most infotainment systems use frequencies near enough the middle (50MHz) where both sets work. Fixes: 0ab13674a9bd ("media: pci: mgb4: Added Digiteq Automotive MGB4 driver") Cc: stable@vger.kernel.org Signed-off-by: Martin Tůma Signed-off-by: Hans Verkuil Signed-off-by: Greg Kroah-Hartman --- drivers/media/pci/mgb4/mgb4_cmt.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/media/pci/mgb4/mgb4_cmt.c b/drivers/media/pci/mgb4/mgb4_cmt.c index bee4bdf54d1c..c22ef51436ed 100644 --- a/drivers/media/pci/mgb4/mgb4_cmt.c +++ b/drivers/media/pci/mgb4/mgb4_cmt.c @@ -135,8 +135,8 @@ static const u16 cmt_vals_out[][15] = { }; static const u16 cmt_vals_in[][13] = { - {0x1082, 0x0000, 0x5104, 0x0000, 0x11C7, 0x0000, 0x1041, 0x02BC, 0x7C01, 0xFFE9, 0x9900, 0x9908, 0x8100}, {0x1104, 0x0000, 0x9208, 0x0000, 0x138E, 0x0000, 0x1041, 0x015E, 0x7C01, 0xFFE9, 0x0100, 0x0908, 0x1000}, + {0x1082, 0x0000, 0x5104, 0x0000, 0x11C7, 0x0000, 0x1041, 0x02BC, 0x7C01, 0xFFE9, 0x9900, 0x9908, 0x8100}, }; static const u32 cmt_addrs_out[][15] = { From 72629a582db72a4f4c9ecbd32dbe40d220d1746d Mon Sep 17 00:00:00 2001 From: Bingbu Cao Date: Fri, 14 Feb 2025 18:52:38 +0800 Subject: [PATCH 030/136] media: intel/ipu6: set the dev_parent of video device to pdev commit 6f0ab5d3671f7cbb326c8cab6fb69cb7ab9901cc upstream. The bus_info in v4l2_capability of IPU6 isys v4l2_dev is missing. The driver didn't set the dev_parent of v4l2_dev, its parent is set to its parent auxdev which is neither platform nor PCI device, thus media_set_bus_info() will not set the bus_info of v4l2_capability, then `v4l2-ctl --all` cannot show the bus_info. This patch fixes it by setting the dev_parent of video_device and v4l2 framework can detect the device type and set the bus_info instead. Fixes: 3c1dfb5a69cf ("media: intel/ipu6: input system video nodes and buffer queues") Cc: stable@vger.kernel.org Signed-off-by: Hidenori Kobayashi Signed-off-by: Bingbu Cao Signed-off-by: Sakari Ailus Signed-off-by: Hans Verkuil Signed-off-by: Greg Kroah-Hartman --- drivers/media/pci/intel/ipu6/ipu6-isys-video.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/media/pci/intel/ipu6/ipu6-isys-video.c b/drivers/media/pci/intel/ipu6/ipu6-isys-video.c index b37561352ead..48388c0c851c 100644 --- a/drivers/media/pci/intel/ipu6/ipu6-isys-video.c +++ b/drivers/media/pci/intel/ipu6/ipu6-isys-video.c @@ -1296,6 +1296,7 @@ int ipu6_isys_video_init(struct ipu6_isys_video *av) av->vdev.release = video_device_release_empty; av->vdev.fops = &isys_fops; av->vdev.v4l2_dev = &av->isys->v4l2_dev; + av->vdev.dev_parent = &av->isys->adev->isp->pdev->dev; if (!av->vdev.ioctl_ops) av->vdev.ioctl_ops = &ipu6_v4l2_ioctl_ops; av->vdev.queue = &av->aq.vbq; From 530f623f56a6680792499a8404083e17f8ec51f4 Mon Sep 17 00:00:00 2001 From: Vikash Garodia Date: Thu, 20 Feb 2025 22:50:11 +0530 Subject: [PATCH 031/136] media: venus: hfi: add a check to handle OOB in sfr region commit f4b211714bcc70effa60c34d9fa613d182e3ef1e upstream. sfr->buf_size is in shared memory and can be modified by malicious user. OOB write is possible when the size is made higher than actual sfr data buffer. Cap the size to allocated size for such cases. Cc: stable@vger.kernel.org Fixes: d96d3f30c0f2 ("[media] media: venus: hfi: add Venus HFI files") Reviewed-by: Bryan O'Donoghue Signed-off-by: Vikash Garodia Signed-off-by: Hans Verkuil Signed-off-by: Greg Kroah-Hartman --- drivers/media/platform/qcom/venus/hfi_venus.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/drivers/media/platform/qcom/venus/hfi_venus.c b/drivers/media/platform/qcom/venus/hfi_venus.c index f9437b6412b9..cfd9471560cc 100644 --- a/drivers/media/platform/qcom/venus/hfi_venus.c +++ b/drivers/media/platform/qcom/venus/hfi_venus.c @@ -1035,18 +1035,26 @@ static void venus_sfr_print(struct venus_hfi_device *hdev) { struct device *dev = hdev->core->dev; struct hfi_sfr *sfr = hdev->sfr.kva; + u32 size; void *p; if (!sfr) return; - p = memchr(sfr->data, '\0', sfr->buf_size); + size = sfr->buf_size; + if (!size) + return; + + if (size > ALIGNED_SFR_SIZE) + size = ALIGNED_SFR_SIZE; + + p = memchr(sfr->data, '\0', size); /* * SFR isn't guaranteed to be NULL terminated since SYS_ERROR indicates * that Venus is in the process of crashing. */ if (!p) - sfr->data[sfr->buf_size - 1] = '\0'; + sfr->data[size - 1] = '\0'; dev_err_ratelimited(dev, "SFR message from FW: %s\n", sfr->data); } From 679424f8b31446f90080befd0300ea915485b096 Mon Sep 17 00:00:00 2001 From: Vikash Garodia Date: Thu, 20 Feb 2025 22:50:10 +0530 Subject: [PATCH 032/136] media: venus: hfi: add check to handle incorrect queue size commit 69baf245b23e20efda0079238b27fc63ecf13de1 upstream. qsize represents size of shared queued between driver and video firmware. Firmware can modify this value to an invalid large value. In such situation, empty_space will be bigger than the space actually available. Since new_wr_idx is not checked, so the following code will result in an OOB write. ... qsize = qhdr->q_size if (wr_idx >= rd_idx) empty_space = qsize - (wr_idx - rd_idx) .... if (new_wr_idx < qsize) { memcpy(wr_ptr, packet, dwords << 2) --> OOB write Add check to ensure qsize is within the allocated size while reading and writing packets into the queue. Cc: stable@vger.kernel.org Fixes: d96d3f30c0f2 ("[media] media: venus: hfi: add Venus HFI files") Reviewed-by: Bryan O'Donoghue Signed-off-by: Vikash Garodia Signed-off-by: Hans Verkuil Signed-off-by: Greg Kroah-Hartman --- drivers/media/platform/qcom/venus/hfi_venus.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/drivers/media/platform/qcom/venus/hfi_venus.c b/drivers/media/platform/qcom/venus/hfi_venus.c index cfd9471560cc..ab93757fff4b 100644 --- a/drivers/media/platform/qcom/venus/hfi_venus.c +++ b/drivers/media/platform/qcom/venus/hfi_venus.c @@ -187,6 +187,9 @@ static int venus_write_queue(struct venus_hfi_device *hdev, /* ensure rd/wr indices's are read from memory */ rmb(); + if (qsize > IFACEQ_QUEUE_SIZE / 4) + return -EINVAL; + if (wr_idx >= rd_idx) empty_space = qsize - (wr_idx - rd_idx); else @@ -255,6 +258,9 @@ static int venus_read_queue(struct venus_hfi_device *hdev, wr_idx = qhdr->write_idx; qsize = qhdr->q_size; + if (qsize > IFACEQ_QUEUE_SIZE / 4) + return -EINVAL; + /* make sure data is valid before using it */ rmb(); From 7631d176086c1bec0dc29ab3e90d5fe58ce38195 Mon Sep 17 00:00:00 2001 From: Matthew Majewski Date: Wed, 19 Feb 2025 14:05:01 -0500 Subject: [PATCH 033/136] media: vim2m: print device name after registering device commit 143d75583f2427f3a97dba62413c4f0604867ebf upstream. Move the v4l2_info() call displaying the video device name after the device is actually registered. This fixes a bug where the driver was always displaying "/dev/video0" since it was reading from the vfd before it was registered. Fixes: cf7f34777a5b ("media: vim2m: Register video device after setting up internals") Cc: stable@vger.kernel.org Signed-off-by: Matthew Majewski Signed-off-by: Hans Verkuil Signed-off-by: Greg Kroah-Hartman --- drivers/media/test-drivers/vim2m.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/media/test-drivers/vim2m.c b/drivers/media/test-drivers/vim2m.c index 3e3b424b4860..8ca6459286ba 100644 --- a/drivers/media/test-drivers/vim2m.c +++ b/drivers/media/test-drivers/vim2m.c @@ -1316,9 +1316,6 @@ static int vim2m_probe(struct platform_device *pdev) vfd->v4l2_dev = &dev->v4l2_dev; video_set_drvdata(vfd, dev); - v4l2_info(&dev->v4l2_dev, - "Device registered as /dev/video%d\n", vfd->num); - platform_set_drvdata(pdev, dev); dev->m2m_dev = v4l2_m2m_init(&m2m_ops); @@ -1345,6 +1342,9 @@ static int vim2m_probe(struct platform_device *pdev) goto error_m2m; } + v4l2_info(&dev->v4l2_dev, + "Device registered as /dev/video%d\n", vfd->num); + #ifdef CONFIG_MEDIA_CONTROLLER ret = v4l2_m2m_register_media_controller(dev->m2m_dev, vfd, MEDIA_ENT_F_PROC_VIDEO_SCALER); From ceb23f66ef8fde1ed949e96f1a27323625ddc0ff Mon Sep 17 00:00:00 2001 From: Yuan Can Date: Tue, 22 Oct 2024 14:50:37 +0800 Subject: [PATCH 034/136] media: siano: Fix error handling in smsdvb_module_init() commit 734ac57e47b3bdd140a1119e2c4e8e6f8ef8b33d upstream. The smsdvb_module_init() returns without checking the retval from smscore_register_hotplug(). If the smscore_register_hotplug() failed, the module failed to install, leaving the smsdvb_debugfs not unregistered. Fixes: 3f6b87cff66b ("[media] siano: allow showing the complete statistics via debugfs") Cc: stable@vger.kernel.org Signed-off-by: Yuan Can Acked-by: Ricardo Ribalda Signed-off-by: Hans Verkuil Signed-off-by: Greg Kroah-Hartman --- drivers/media/common/siano/smsdvb-main.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/media/common/siano/smsdvb-main.c b/drivers/media/common/siano/smsdvb-main.c index 44d8fe8b220e..9b1a650ed055 100644 --- a/drivers/media/common/siano/smsdvb-main.c +++ b/drivers/media/common/siano/smsdvb-main.c @@ -1243,6 +1243,8 @@ static int __init smsdvb_module_init(void) smsdvb_debugfs_register(); rc = smscore_register_hotplug(smsdvb_hotplug); + if (rc) + smsdvb_debugfs_unregister(); pr_debug("\n"); From 88962f1978761e0f247b99bfe36804b13d960778 Mon Sep 17 00:00:00 2001 From: John Keeping Date: Sat, 10 Aug 2024 14:02:54 +0100 Subject: [PATCH 035/136] media: rockchip: rga: fix rga offset lookup commit 11de3582675cc0b7136e12f3971f1da3e5a05382 upstream. The arguments to rga_lookup_draw_pos() are passed in the wrong order, rotate mode should be before mirror mode. Fixes: 558c248f930e6 ("media: rockchip: rga: split src and dst buffer setup") Cc: stable@vger.kernel.org Signed-off-by: John Keeping Reviewed-by: Michael Tretter Signed-off-by: Hans Verkuil Signed-off-by: Greg Kroah-Hartman --- drivers/media/platform/rockchip/rga/rga-hw.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/media/platform/rockchip/rga/rga-hw.c b/drivers/media/platform/rockchip/rga/rga-hw.c index 11c3d7234757..b2ef3beec525 100644 --- a/drivers/media/platform/rockchip/rga/rga-hw.c +++ b/drivers/media/platform/rockchip/rga/rga-hw.c @@ -376,7 +376,7 @@ static void rga_cmd_set_dst_info(struct rga_ctx *ctx, * Configure the dest framebuffer base address with pixel offset. */ offsets = rga_get_addr_offset(&ctx->out, offset, dst_x, dst_y, dst_w, dst_h); - dst_offset = rga_lookup_draw_pos(&offsets, mir_mode, rot_mode); + dst_offset = rga_lookup_draw_pos(&offsets, rot_mode, mir_mode); dest[(RGA_DST_Y_RGB_BASE_ADDR - RGA_MODE_BASE_REG) >> 2] = dst_offset->y_off; From 7e619d4d2715af933a554801ad5b4e9a739120dc Mon Sep 17 00:00:00 2001 From: Jan Beulich Date: Wed, 12 Mar 2025 16:32:45 +0100 Subject: [PATCH 036/136] xenfs/xensyms: respect hypervisor's "next" indication commit 5c4e79e29a9fe4ea132118ac40c2bc97cfe23077 upstream. The interface specifies the symnum field as an input and output; the hypervisor sets it to the next sequential symbol's index. xensyms_next() incrementing the position explicitly (and xensyms_next_sym() decrementing it to "rewind") is only correct as long as the sequence of symbol indexes is non-sparse. Use the hypervisor-supplied value instead to update the position in xensyms_next(), and use the saved incoming index in xensyms_next_sym(). Cc: stable@kernel.org Fixes: a11f4f0a4e18 ("xen: xensyms support") Signed-off-by: Jan Beulich Reviewed-by: Juergen Gross Message-ID: <15d5e7fa-ec5d-422f-9319-d28bed916349@suse.com> Signed-off-by: Juergen Gross Signed-off-by: Greg Kroah-Hartman --- drivers/xen/xenfs/xensyms.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/xen/xenfs/xensyms.c b/drivers/xen/xenfs/xensyms.c index b799bc759c15..088b7f02c358 100644 --- a/drivers/xen/xenfs/xensyms.c +++ b/drivers/xen/xenfs/xensyms.c @@ -48,7 +48,7 @@ static int xensyms_next_sym(struct xensyms *xs) return -ENOMEM; set_xen_guest_handle(symdata->name, xs->name); - symdata->symnum--; /* Rewind */ + symdata->symnum = symnum; /* Rewind */ ret = HYPERVISOR_platform_op(&xs->op); if (ret < 0) @@ -78,7 +78,7 @@ static void *xensyms_next(struct seq_file *m, void *p, loff_t *pos) { struct xensyms *xs = m->private; - xs->op.u.symdata.symnum = ++(*pos); + *pos = xs->op.u.symdata.symnum; if (xensyms_next_sym(xs)) return NULL; From 2ff58c5b260f7d663a73d4c12b599600d47e20a5 Mon Sep 17 00:00:00 2001 From: Douglas Anderson Date: Tue, 7 Jan 2025 12:06:01 -0800 Subject: [PATCH 037/136] arm64: cputype: Add MIDR_CORTEX_A76AE commit a9b5bd81b294d30a747edd125e9f6aef2def7c79 upstream. >From the TRM, MIDR_CORTEX_A76AE has a partnum of 0xDOE and an implementor of 0x41 (ARM). Add the values. Cc: stable@vger.kernel.org # dependency of the next fix in the series Signed-off-by: Douglas Anderson Link: https://lore.kernel.org/r/20250107120555.v4.4.I151f3b7ee323bcc3082179b8c60c3cd03308aa94@changeid Signed-off-by: Catalin Marinas Signed-off-by: Greg Kroah-Hartman --- arch/arm64/include/asm/cputype.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/arm64/include/asm/cputype.h b/arch/arm64/include/asm/cputype.h index c8058f91a5bd..2a4e686e633c 100644 --- a/arch/arm64/include/asm/cputype.h +++ b/arch/arm64/include/asm/cputype.h @@ -75,6 +75,7 @@ #define ARM_CPU_PART_CORTEX_A76 0xD0B #define ARM_CPU_PART_NEOVERSE_N1 0xD0C #define ARM_CPU_PART_CORTEX_A77 0xD0D +#define ARM_CPU_PART_CORTEX_A76AE 0xD0E #define ARM_CPU_PART_NEOVERSE_V1 0xD40 #define ARM_CPU_PART_CORTEX_A78 0xD41 #define ARM_CPU_PART_CORTEX_A78AE 0xD42 @@ -159,6 +160,7 @@ #define MIDR_CORTEX_A76 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_A76) #define MIDR_NEOVERSE_N1 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_NEOVERSE_N1) #define MIDR_CORTEX_A77 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_A77) +#define MIDR_CORTEX_A76AE MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_A76AE) #define MIDR_NEOVERSE_V1 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_NEOVERSE_V1) #define MIDR_CORTEX_A78 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_A78) #define MIDR_CORTEX_A78AE MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_A78AE) From 4af285843525c8db4215ec28e4e639bfd4ed2029 Mon Sep 17 00:00:00 2001 From: Douglas Anderson Date: Tue, 7 Jan 2025 12:05:58 -0800 Subject: [PATCH 038/136] arm64: errata: Add QCOM_KRYO_4XX_GOLD to the spectre_bhb_k24_list commit ed1ce841245d8febe3badf51c57e81c3619d0a1d upstream. Qualcomm Kryo 400-series Gold cores have a derivative of an ARM Cortex A76 in them. Since A76 needs Spectre mitigation via looping then the Kyro 400-series Gold cores also need Spectre mitigation via looping. Qualcomm has confirmed that the proper "k" value for Kryo 400-series Gold cores is 24. Fixes: 558c303c9734 ("arm64: Mitigate spectre style branch history side channels") Cc: stable@vger.kernel.org Cc: Scott Bauer Signed-off-by: Douglas Anderson Acked-by: Trilok Soni Link: https://lore.kernel.org/r/20250107120555.v4.1.Ie4ef54abe02e7eb0eee50f830575719bf23bda48@changeid Signed-off-by: Catalin Marinas Signed-off-by: Greg Kroah-Hartman --- arch/arm64/kernel/proton-pack.c | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm64/kernel/proton-pack.c b/arch/arm64/kernel/proton-pack.c index da53722f95d4..e149efadff20 100644 --- a/arch/arm64/kernel/proton-pack.c +++ b/arch/arm64/kernel/proton-pack.c @@ -866,6 +866,7 @@ u8 spectre_bhb_loop_affected(int scope) MIDR_ALL_VERSIONS(MIDR_CORTEX_A76), MIDR_ALL_VERSIONS(MIDR_CORTEX_A77), MIDR_ALL_VERSIONS(MIDR_NEOVERSE_N1), + MIDR_ALL_VERSIONS(MIDR_QCOM_KRYO_4XX_GOLD), {}, }; static const struct midr_range spectre_bhb_k11_list[] = { From 3b0f2526c87e00adfd3bcc9e3dd9b4fa77b62465 Mon Sep 17 00:00:00 2001 From: Douglas Anderson Date: Tue, 7 Jan 2025 12:05:59 -0800 Subject: [PATCH 039/136] arm64: errata: Assume that unknown CPUs _are_ vulnerable to Spectre BHB commit e403e8538359d8580cbee1976ff71813e947101e upstream. The code for detecting CPUs that are vulnerable to Spectre BHB was based on a hardcoded list of CPU IDs that were known to be affected. Unfortunately, the list mostly only contained the IDs of standard ARM cores. The IDs for many cores that are minor variants of the standard ARM cores (like many Qualcomm Kyro CPUs) weren't listed. This led the code to assume that those variants were not affected. Flip the code on its head and instead assume that a core is vulnerable if it doesn't have CSV2_3 but is unrecognized as being safe. This involves creating a "Spectre BHB safe" list. As of right now, the only CPU IDs added to the "Spectre BHB safe" list are ARM Cortex A35, A53, A55, A510, and A520. This list was created by looking for cores that weren't listed in ARM's list [1] as per review feedback on v2 of this patch [2]. Additionally Brahma A53 is added as per mailing list feedback [3]. NOTE: this patch will not actually _mitigate_ anyone, it will simply cause them to report themselves as vulnerable. If any cores in the system are reported as vulnerable but not mitigated then the whole system will be reported as vulnerable though the system will attempt to mitigate with the information it has about the known cores. [1] https://developer.arm.com/Arm%20Security%20Center/Spectre-BHB [2] https://lore.kernel.org/r/20241219175128.GA25477@willie-the-truck [3] https://lore.kernel.org/r/18dbd7d1-a46c-4112-a425-320c99f67a8d@broadcom.com Fixes: 558c303c9734 ("arm64: Mitigate spectre style branch history side channels") Cc: stable@vger.kernel.org Reviewed-by: Julius Werner Signed-off-by: Douglas Anderson Link: https://lore.kernel.org/r/20250107120555.v4.2.I2040fa004dafe196243f67ebcc647cbedbb516e6@changeid Signed-off-by: Catalin Marinas Signed-off-by: Greg Kroah-Hartman --- arch/arm64/include/asm/spectre.h | 1 - arch/arm64/kernel/proton-pack.c | 193 ++++++++++++++++--------------- 2 files changed, 97 insertions(+), 97 deletions(-) diff --git a/arch/arm64/include/asm/spectre.h b/arch/arm64/include/asm/spectre.h index 0c4d9045c31f..f1524cdeacf1 100644 --- a/arch/arm64/include/asm/spectre.h +++ b/arch/arm64/include/asm/spectre.h @@ -97,7 +97,6 @@ enum mitigation_state arm64_get_meltdown_state(void); enum mitigation_state arm64_get_spectre_bhb_state(void); bool is_spectre_bhb_affected(const struct arm64_cpu_capabilities *entry, int scope); -u8 spectre_bhb_loop_affected(int scope); void spectre_bhb_enable_mitigation(const struct arm64_cpu_capabilities *__unused); bool try_emulate_el1_ssbs(struct pt_regs *regs, u32 instr); diff --git a/arch/arm64/kernel/proton-pack.c b/arch/arm64/kernel/proton-pack.c index e149efadff20..17aa836fe46d 100644 --- a/arch/arm64/kernel/proton-pack.c +++ b/arch/arm64/kernel/proton-pack.c @@ -845,53 +845,70 @@ static unsigned long system_bhb_mitigations; * This must be called with SCOPE_LOCAL_CPU for each type of CPU, before any * SCOPE_SYSTEM call will give the right answer. */ -u8 spectre_bhb_loop_affected(int scope) +static bool is_spectre_bhb_safe(int scope) +{ + static const struct midr_range spectre_bhb_safe_list[] = { + MIDR_ALL_VERSIONS(MIDR_CORTEX_A35), + MIDR_ALL_VERSIONS(MIDR_CORTEX_A53), + MIDR_ALL_VERSIONS(MIDR_CORTEX_A55), + MIDR_ALL_VERSIONS(MIDR_CORTEX_A510), + MIDR_ALL_VERSIONS(MIDR_CORTEX_A520), + MIDR_ALL_VERSIONS(MIDR_BRAHMA_B53), + {}, + }; + static bool all_safe = true; + + if (scope != SCOPE_LOCAL_CPU) + return all_safe; + + if (is_midr_in_range_list(read_cpuid_id(), spectre_bhb_safe_list)) + return true; + + all_safe = false; + + return false; +} + +static u8 spectre_bhb_loop_affected(void) { u8 k = 0; - static u8 max_bhb_k; - if (scope == SCOPE_LOCAL_CPU) { - static const struct midr_range spectre_bhb_k32_list[] = { - MIDR_ALL_VERSIONS(MIDR_CORTEX_A78), - MIDR_ALL_VERSIONS(MIDR_CORTEX_A78AE), - MIDR_ALL_VERSIONS(MIDR_CORTEX_A78C), - MIDR_ALL_VERSIONS(MIDR_CORTEX_X1), - MIDR_ALL_VERSIONS(MIDR_CORTEX_A710), - MIDR_ALL_VERSIONS(MIDR_CORTEX_X2), - MIDR_ALL_VERSIONS(MIDR_NEOVERSE_N2), - MIDR_ALL_VERSIONS(MIDR_NEOVERSE_V1), - {}, - }; - static const struct midr_range spectre_bhb_k24_list[] = { - MIDR_ALL_VERSIONS(MIDR_CORTEX_A76), - MIDR_ALL_VERSIONS(MIDR_CORTEX_A77), - MIDR_ALL_VERSIONS(MIDR_NEOVERSE_N1), - MIDR_ALL_VERSIONS(MIDR_QCOM_KRYO_4XX_GOLD), - {}, - }; - static const struct midr_range spectre_bhb_k11_list[] = { - MIDR_ALL_VERSIONS(MIDR_AMPERE1), - {}, - }; - static const struct midr_range spectre_bhb_k8_list[] = { - MIDR_ALL_VERSIONS(MIDR_CORTEX_A72), - MIDR_ALL_VERSIONS(MIDR_CORTEX_A57), - {}, - }; + static const struct midr_range spectre_bhb_k32_list[] = { + MIDR_ALL_VERSIONS(MIDR_CORTEX_A78), + MIDR_ALL_VERSIONS(MIDR_CORTEX_A78AE), + MIDR_ALL_VERSIONS(MIDR_CORTEX_A78C), + MIDR_ALL_VERSIONS(MIDR_CORTEX_X1), + MIDR_ALL_VERSIONS(MIDR_CORTEX_A710), + MIDR_ALL_VERSIONS(MIDR_CORTEX_X2), + MIDR_ALL_VERSIONS(MIDR_NEOVERSE_N2), + MIDR_ALL_VERSIONS(MIDR_NEOVERSE_V1), + {}, + }; + static const struct midr_range spectre_bhb_k24_list[] = { + MIDR_ALL_VERSIONS(MIDR_CORTEX_A76), + MIDR_ALL_VERSIONS(MIDR_CORTEX_A77), + MIDR_ALL_VERSIONS(MIDR_NEOVERSE_N1), + MIDR_ALL_VERSIONS(MIDR_QCOM_KRYO_4XX_GOLD), + {}, + }; + static const struct midr_range spectre_bhb_k11_list[] = { + MIDR_ALL_VERSIONS(MIDR_AMPERE1), + {}, + }; + static const struct midr_range spectre_bhb_k8_list[] = { + MIDR_ALL_VERSIONS(MIDR_CORTEX_A72), + MIDR_ALL_VERSIONS(MIDR_CORTEX_A57), + {}, + }; - if (is_midr_in_range_list(read_cpuid_id(), spectre_bhb_k32_list)) - k = 32; - else if (is_midr_in_range_list(read_cpuid_id(), spectre_bhb_k24_list)) - k = 24; - else if (is_midr_in_range_list(read_cpuid_id(), spectre_bhb_k11_list)) - k = 11; - else if (is_midr_in_range_list(read_cpuid_id(), spectre_bhb_k8_list)) - k = 8; - - max_bhb_k = max(max_bhb_k, k); - } else { - k = max_bhb_k; - } + if (is_midr_in_range_list(read_cpuid_id(), spectre_bhb_k32_list)) + k = 32; + else if (is_midr_in_range_list(read_cpuid_id(), spectre_bhb_k24_list)) + k = 24; + else if (is_midr_in_range_list(read_cpuid_id(), spectre_bhb_k11_list)) + k = 11; + else if (is_midr_in_range_list(read_cpuid_id(), spectre_bhb_k8_list)) + k = 8; return k; } @@ -917,29 +934,13 @@ static enum mitigation_state spectre_bhb_get_cpu_fw_mitigation_state(void) } } -static bool is_spectre_bhb_fw_affected(int scope) +static bool has_spectre_bhb_fw_mitigation(void) { - static bool system_affected; enum mitigation_state fw_state; bool has_smccc = arm_smccc_1_1_get_conduit() != SMCCC_CONDUIT_NONE; - static const struct midr_range spectre_bhb_firmware_mitigated_list[] = { - MIDR_ALL_VERSIONS(MIDR_CORTEX_A73), - MIDR_ALL_VERSIONS(MIDR_CORTEX_A75), - {}, - }; - bool cpu_in_list = is_midr_in_range_list(read_cpuid_id(), - spectre_bhb_firmware_mitigated_list); - - if (scope != SCOPE_LOCAL_CPU) - return system_affected; fw_state = spectre_bhb_get_cpu_fw_mitigation_state(); - if (cpu_in_list || (has_smccc && fw_state == SPECTRE_MITIGATED)) { - system_affected = true; - return true; - } - - return false; + return has_smccc && fw_state == SPECTRE_MITIGATED; } static bool supports_ecbhb(int scope) @@ -955,6 +956,8 @@ static bool supports_ecbhb(int scope) ID_AA64MMFR1_EL1_ECBHB_SHIFT); } +static u8 max_bhb_k; + bool is_spectre_bhb_affected(const struct arm64_cpu_capabilities *entry, int scope) { @@ -963,16 +966,18 @@ bool is_spectre_bhb_affected(const struct arm64_cpu_capabilities *entry, if (supports_csv2p3(scope)) return false; - if (supports_clearbhb(scope)) - return true; + if (is_spectre_bhb_safe(scope)) + return false; - if (spectre_bhb_loop_affected(scope)) - return true; + /* + * At this point the core isn't known to be "safe" so we're going to + * assume it's vulnerable. We still need to update `max_bhb_k` though, + * but only if we aren't mitigating with clearbhb though. + */ + if (scope == SCOPE_LOCAL_CPU && !supports_clearbhb(SCOPE_LOCAL_CPU)) + max_bhb_k = max(max_bhb_k, spectre_bhb_loop_affected()); - if (is_spectre_bhb_fw_affected(scope)) - return true; - - return false; + return true; } static void this_cpu_set_vectors(enum arm64_bp_harden_el1_vectors slot) @@ -1003,7 +1008,7 @@ early_param("nospectre_bhb", parse_spectre_bhb_param); void spectre_bhb_enable_mitigation(const struct arm64_cpu_capabilities *entry) { bp_hardening_cb_t cpu_cb; - enum mitigation_state fw_state, state = SPECTRE_VULNERABLE; + enum mitigation_state state = SPECTRE_VULNERABLE; struct bp_hardening_data *data = this_cpu_ptr(&bp_hardening_data); if (!is_spectre_bhb_affected(entry, SCOPE_LOCAL_CPU)) @@ -1029,7 +1034,7 @@ void spectre_bhb_enable_mitigation(const struct arm64_cpu_capabilities *entry) this_cpu_set_vectors(EL1_VECTOR_BHB_CLEAR_INSN); state = SPECTRE_MITIGATED; set_bit(BHB_INSN, &system_bhb_mitigations); - } else if (spectre_bhb_loop_affected(SCOPE_LOCAL_CPU)) { + } else if (spectre_bhb_loop_affected()) { /* * Ensure KVM uses the indirect vector which will have the * branchy-loop added. A57/A72-r0 will already have selected @@ -1042,32 +1047,29 @@ void spectre_bhb_enable_mitigation(const struct arm64_cpu_capabilities *entry) this_cpu_set_vectors(EL1_VECTOR_BHB_LOOP); state = SPECTRE_MITIGATED; set_bit(BHB_LOOP, &system_bhb_mitigations); - } else if (is_spectre_bhb_fw_affected(SCOPE_LOCAL_CPU)) { - fw_state = spectre_bhb_get_cpu_fw_mitigation_state(); - if (fw_state == SPECTRE_MITIGATED) { - /* - * Ensure KVM uses one of the spectre bp_hardening - * vectors. The indirect vector doesn't include the EL3 - * call, so needs upgrading to - * HYP_VECTOR_SPECTRE_INDIRECT. - */ - if (!data->slot || data->slot == HYP_VECTOR_INDIRECT) - data->slot += 1; + } else if (has_spectre_bhb_fw_mitigation()) { + /* + * Ensure KVM uses one of the spectre bp_hardening + * vectors. The indirect vector doesn't include the EL3 + * call, so needs upgrading to + * HYP_VECTOR_SPECTRE_INDIRECT. + */ + if (!data->slot || data->slot == HYP_VECTOR_INDIRECT) + data->slot += 1; - this_cpu_set_vectors(EL1_VECTOR_BHB_FW); + this_cpu_set_vectors(EL1_VECTOR_BHB_FW); - /* - * The WA3 call in the vectors supersedes the WA1 call - * made during context-switch. Uninstall any firmware - * bp_hardening callback. - */ - cpu_cb = spectre_v2_get_sw_mitigation_cb(); - if (__this_cpu_read(bp_hardening_data.fn) != cpu_cb) - __this_cpu_write(bp_hardening_data.fn, NULL); + /* + * The WA3 call in the vectors supersedes the WA1 call + * made during context-switch. Uninstall any firmware + * bp_hardening callback. + */ + cpu_cb = spectre_v2_get_sw_mitigation_cb(); + if (__this_cpu_read(bp_hardening_data.fn) != cpu_cb) + __this_cpu_write(bp_hardening_data.fn, NULL); - state = SPECTRE_MITIGATED; - set_bit(BHB_FW, &system_bhb_mitigations); - } + state = SPECTRE_MITIGATED; + set_bit(BHB_FW, &system_bhb_mitigations); } update_mitigation_state(&spectre_bhb_state, state); @@ -1101,7 +1103,6 @@ void noinstr spectre_bhb_patch_loop_iter(struct alt_instr *alt, { u8 rd; u32 insn; - u16 loop_count = spectre_bhb_loop_affected(SCOPE_SYSTEM); BUG_ON(nr_inst != 1); /* MOV -> MOV */ @@ -1110,7 +1111,7 @@ void noinstr spectre_bhb_patch_loop_iter(struct alt_instr *alt, insn = le32_to_cpu(*origptr); rd = aarch64_insn_decode_register(AARCH64_INSN_REGTYPE_RD, insn); - insn = aarch64_insn_gen_movewide(rd, loop_count, 0, + insn = aarch64_insn_gen_movewide(rd, max_bhb_k, 0, AARCH64_INSN_VARIANT_64BIT, AARCH64_INSN_MOVEWIDE_ZERO); *updptr++ = cpu_to_le32(insn); From 20c105f5876953b12f773972b442ffda8795c71d Mon Sep 17 00:00:00 2001 From: Douglas Anderson Date: Tue, 7 Jan 2025 12:06:00 -0800 Subject: [PATCH 040/136] arm64: errata: Add KRYO 2XX/3XX/4XX silver cores to Spectre BHB safe list commit 0c9fc6e652cd5aed48c5f700c32b7642bea7f453 upstream. Qualcomm has confirmed that, much like Cortex A53 and A55, KRYO 2XX/3XX/4XX silver cores are unaffected by Spectre BHB. Add them to the safe list. Fixes: 558c303c9734 ("arm64: Mitigate spectre style branch history side channels") Cc: stable@vger.kernel.org Cc: Scott Bauer Signed-off-by: Douglas Anderson Acked-by: Trilok Soni Link: https://lore.kernel.org/r/20250107120555.v4.3.Iab8dbfb5c9b1e143e7a29f410bce5f9525a0ba32@changeid Signed-off-by: Catalin Marinas Signed-off-by: Greg Kroah-Hartman --- arch/arm64/kernel/proton-pack.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/arch/arm64/kernel/proton-pack.c b/arch/arm64/kernel/proton-pack.c index 17aa836fe46d..89405be53d8f 100644 --- a/arch/arm64/kernel/proton-pack.c +++ b/arch/arm64/kernel/proton-pack.c @@ -854,6 +854,9 @@ static bool is_spectre_bhb_safe(int scope) MIDR_ALL_VERSIONS(MIDR_CORTEX_A510), MIDR_ALL_VERSIONS(MIDR_CORTEX_A520), MIDR_ALL_VERSIONS(MIDR_BRAHMA_B53), + MIDR_ALL_VERSIONS(MIDR_QCOM_KRYO_2XX_SILVER), + MIDR_ALL_VERSIONS(MIDR_QCOM_KRYO_3XX_SILVER), + MIDR_ALL_VERSIONS(MIDR_QCOM_KRYO_4XX_SILVER), {}, }; static bool all_safe = true; From c322789613407647a05ff5c451a7bf545fb34e73 Mon Sep 17 00:00:00 2001 From: Will Deacon Date: Fri, 14 Mar 2025 13:34:09 +0000 Subject: [PATCH 041/136] KVM: arm64: Tear down vGIC on failed vCPU creation commit 250f25367b58d8c65a1b060a2dda037eea09a672 upstream. If kvm_arch_vcpu_create() fails to share the vCPU page with the hypervisor, we propagate the error back to the ioctl but leave the vGIC vCPU data initialised. Note only does this leak the corresponding memory when the vCPU is destroyed but it can also lead to use-after-free if the redistributor device handling tries to walk into the vCPU. Add the missing cleanup to kvm_arch_vcpu_create(), ensuring that the vGIC vCPU structures are destroyed on error. Cc: Cc: Marc Zyngier Cc: Oliver Upton Cc: Quentin Perret Signed-off-by: Will Deacon Reviewed-by: Marc Zyngier Link: https://lore.kernel.org/r/20250314133409.9123-1-will@kernel.org Signed-off-by: Oliver Upton Signed-off-by: Greg Kroah-Hartman --- arch/arm64/kvm/arm.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/arch/arm64/kvm/arm.c b/arch/arm64/kvm/arm.c index 634d3f624818..7d301da8ff28 100644 --- a/arch/arm64/kvm/arm.c +++ b/arch/arm64/kvm/arm.c @@ -493,7 +493,11 @@ int kvm_arch_vcpu_create(struct kvm_vcpu *vcpu) if (err) return err; - return kvm_share_hyp(vcpu, vcpu + 1); + err = kvm_share_hyp(vcpu, vcpu + 1); + if (err) + kvm_vgic_vcpu_destroy(vcpu); + + return err; } void kvm_arch_vcpu_postcreate(struct kvm_vcpu *vcpu) From 33607e92402324245e0d5b8028055f49ba81beaa Mon Sep 17 00:00:00 2001 From: Miquel Raynal Date: Wed, 5 Mar 2025 21:09:32 +0100 Subject: [PATCH 042/136] spi: cadence-qspi: Fix probe on AM62A LP SK commit b8665a1b49f5498edb7b21d730030c06b7348a3c upstream. In 2020, there's been an unnoticed change which rightfully attempted to report probe deferrals upon DMA absence by checking the return value of dma_request_chan_by_mask(). By doing so, it also reported errors which were simply ignored otherwise, likely on purpose. This change actually turned a void return into an error code. Hence, not only the -EPROBE_DEFER error codes but all error codes got reported to the callers, now failing to probe in the absence of Rx DMA channel, despite the fact that DMA seems to not be supported natively by many implementations. Looking at the history, this change probably led to: ad2775dc3fc5 ("spi: cadence-quadspi: Disable the DAC for Intel LGM SoC") f724c296f2f2 ("spi: cadence-quadspi: fix Direct Access Mode disable for SoCFPGA") In my case, the AM62A LP SK core octo-SPI node from TI does not advertise any DMA channel, hinting that there is likely no support for it, but yet when the support for the am654 compatible was added, DMA seemed to be used, so just discarding its use with the CQSPI_DISABLE_DAC_MODE quirk for this compatible does not seem the correct approach. Let's get change the return condition back to: - return a probe deferral error if we get one - ignore the return value otherwise The "error" log level was however likely too high for something that is expected to fail, so let's lower it arbitrarily to the info level. Fixes: 935da5e5100f ("mtd: spi-nor: cadence-quadspi: Handle probe deferral while requesting DMA channel") Cc: stable@vger.kernel.org Signed-off-by: Miquel Raynal Link: https://patch.msgid.link/20250305200933.2512925-2-miquel.raynal@bootlin.com Signed-off-by: Mark Brown Signed-off-by: Greg Kroah-Hartman --- drivers/spi/spi-cadence-quadspi.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/drivers/spi/spi-cadence-quadspi.c b/drivers/spi/spi-cadence-quadspi.c index 73b1edd0531b..f9463f263fba 100644 --- a/drivers/spi/spi-cadence-quadspi.c +++ b/drivers/spi/spi-cadence-quadspi.c @@ -1634,6 +1634,12 @@ static int cqspi_request_mmap_dma(struct cqspi_st *cqspi) int ret = PTR_ERR(cqspi->rx_chan); cqspi->rx_chan = NULL; + if (ret == -ENODEV) { + /* DMA support is not mandatory */ + dev_info(&cqspi->pdev->dev, "No Rx DMA available\n"); + return 0; + } + return dev_err_probe(&cqspi->pdev->dev, ret, "No Rx DMA available\n"); } init_completion(&cqspi->rx_dma_complete); From 7266066b9469f04ed1d4c0fdddaea1425835eb55 Mon Sep 17 00:00:00 2001 From: Kamal Dasu Date: Thu, 27 Feb 2025 12:46:08 -0500 Subject: [PATCH 043/136] mtd: rawnand: brcmnand: fix PM resume warning commit ddc210cf8b8a8be68051ad958bf3e2cef6b681c2 upstream. Fixed warning on PM resume as shown below caused due to uninitialized struct nand_operation that checks chip select field : WARN_ON(op->cs >= nanddev_ntargets(&chip->base) [ 14.588522] ------------[ cut here ]------------ [ 14.588529] WARNING: CPU: 0 PID: 1392 at drivers/mtd/nand/raw/internals.h:139 nand_reset_op+0x1e0/0x1f8 [ 14.588553] Modules linked in: bdc udc_core [ 14.588579] CPU: 0 UID: 0 PID: 1392 Comm: rtcwake Tainted: G W 6.14.0-rc4-g5394eea10651 #16 [ 14.588590] Tainted: [W]=WARN [ 14.588593] Hardware name: Broadcom STB (Flattened Device Tree) [ 14.588598] Call trace: [ 14.588604] dump_backtrace from show_stack+0x18/0x1c [ 14.588622] r7:00000009 r6:0000008b r5:60000153 r4:c0fa558c [ 14.588625] show_stack from dump_stack_lvl+0x70/0x7c [ 14.588639] dump_stack_lvl from dump_stack+0x18/0x1c [ 14.588653] r5:c08d40b0 r4:c1003cb0 [ 14.588656] dump_stack from __warn+0x84/0xe4 [ 14.588668] __warn from warn_slowpath_fmt+0x18c/0x194 [ 14.588678] r7:c08d40b0 r6:c1003cb0 r5:00000000 r4:00000000 [ 14.588681] warn_slowpath_fmt from nand_reset_op+0x1e0/0x1f8 [ 14.588695] r8:70c40dff r7:89705f41 r6:36b4a597 r5:c26c9444 r4:c26b0048 [ 14.588697] nand_reset_op from brcmnand_resume+0x13c/0x150 [ 14.588714] r9:00000000 r8:00000000 r7:c24f8010 r6:c228a3f8 r5:c26c94bc r4:c26b0040 [ 14.588717] brcmnand_resume from platform_pm_resume+0x34/0x54 [ 14.588735] r5:00000010 r4:c0840a50 [ 14.588738] platform_pm_resume from dpm_run_callback+0x5c/0x14c [ 14.588757] dpm_run_callback from device_resume+0xc0/0x324 [ 14.588776] r9:c24f8054 r8:c24f80a0 r7:00000000 r6:00000000 r5:00000010 r4:c24f8010 [ 14.588779] device_resume from dpm_resume+0x130/0x160 [ 14.588799] r9:c22539e4 r8:00000010 r7:c22bebb0 r6:c24f8010 r5:c22539dc r4:c22539b0 [ 14.588802] dpm_resume from dpm_resume_end+0x14/0x20 [ 14.588822] r10:c2204e40 r9:00000000 r8:c228a3fc r7:00000000 r6:00000003 r5:c228a414 [ 14.588826] r4:00000010 [ 14.588828] dpm_resume_end from suspend_devices_and_enter+0x274/0x6f8 [ 14.588848] r5:c228a414 r4:00000000 [ 14.588851] suspend_devices_and_enter from pm_suspend+0x228/0x2bc [ 14.588868] r10:c3502910 r9:c3501f40 r8:00000004 r7:c228a438 r6:c0f95e18 r5:00000000 [ 14.588871] r4:00000003 [ 14.588874] pm_suspend from state_store+0x74/0xd0 [ 14.588889] r7:c228a438 r6:c0f934c8 r5:00000003 r4:00000003 [ 14.588892] state_store from kobj_attr_store+0x1c/0x28 [ 14.588913] r9:00000000 r8:00000000 r7:f09f9f08 r6:00000004 r5:c3502900 r4:c0283250 [ 14.588916] kobj_attr_store from sysfs_kf_write+0x40/0x4c [ 14.588936] r5:c3502900 r4:c0d92a48 [ 14.588939] sysfs_kf_write from kernfs_fop_write_iter+0x104/0x1f0 [ 14.588956] r5:c3502900 r4:c3501f40 [ 14.588960] kernfs_fop_write_iter from vfs_write+0x250/0x420 [ 14.588980] r10:c0e14b48 r9:00000000 r8:c25f5780 r7:00443398 r6:f09f9f68 r5:c34f7f00 [ 14.588983] r4:c042a88c [ 14.588987] vfs_write from ksys_write+0x74/0xe4 [ 14.589005] r10:00000004 r9:c25f5780 r8:c02002fA0 r7:00000000 r6:00000000 r5:c34f7f00 [ 14.589008] r4:c34f7f00 [ 14.589011] ksys_write from sys_write+0x10/0x14 [ 14.589029] r7:00000004 r6:004421c0 r5:00443398 r4:00000004 [ 14.589032] sys_write from ret_fast_syscall+0x0/0x5c [ 14.589044] Exception stack(0xf09f9fa8 to 0xf09f9ff0) [ 14.589050] 9fa0: 00000004 00443398 00000004 00443398 00000004 00000001 [ 14.589056] 9fc0: 00000004 00443398 004421c0 00000004 b6ecbd58 00000008 bebfbc38 0043eb78 [ 14.589062] 9fe0: 00440eb0 bebfbaf8 b6de18a0 b6e579e8 [ 14.589065] ---[ end trace 0000000000000000 ]--- The fix uses the higher level nand_reset(chip, chipnr); where chipnr = 0, when doing PM resume operation in compliance with the controller support for single die nand chip. Switching from nand_reset_op() to nand_reset() implies more than just setting the cs field op->cs, it also reconfigures the data interface (ie. the timings). Tested and confirmed the NAND chip is in sync timing wise with host after the fix. Fixes: 97d90da8a886 ("mtd: nand: provide several helpers to do common NAND operations") Cc: stable@vger.kernel.org Signed-off-by: Kamal Dasu Reviewed-by: Florian Fainelli Signed-off-by: Miquel Raynal Signed-off-by: Greg Kroah-Hartman --- drivers/mtd/nand/raw/brcmnand/brcmnand.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/mtd/nand/raw/brcmnand/brcmnand.c b/drivers/mtd/nand/raw/brcmnand/brcmnand.c index e76df6a00ed4..2eb44c1428fb 100644 --- a/drivers/mtd/nand/raw/brcmnand/brcmnand.c +++ b/drivers/mtd/nand/raw/brcmnand/brcmnand.c @@ -3008,7 +3008,7 @@ static int brcmnand_resume(struct device *dev) brcmnand_save_restore_cs_config(host, 1); /* Reset the chip, required by some chips after power-up */ - nand_reset_op(chip); + nand_reset(chip, 0); } return 0; From 4c8056fbb17d652227b66f53162601b043a06ece Mon Sep 17 00:00:00 2001 From: Jonathan McDowell Date: Wed, 12 Mar 2025 07:31:57 +0200 Subject: [PATCH 044/136] tpm, tpm_tis: Fix timeout handling when waiting for TPM status MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit commit 7146dffa875cd00e7a7f918e1fce79c7593ac1fa upstream. The change to only use interrupts to handle supported status changes introduced an issue when it is necessary to poll for the status. Rather than checking for the status after sleeping the code now sleeps after the check. This means a correct, but slower, status change on the part of the TPM can be missed, resulting in a spurious timeout error, especially on a more loaded system. Switch back to sleeping *then* checking. An up front check of the status has been done at the start of the function, so this does not cause an additional delay when the status is already what we're looking for. Cc: stable@vger.kernel.org # v6.4+ Fixes: e87fcf0dc2b4 ("tpm, tpm_tis: Only handle supported interrupts") Signed-off-by: Jonathan McDowell Reviewed-by: Michal Suchánek Reviewed-by: Lino Sanfilippo Reviewed-by: Jarkko Sakkinen Signed-off-by: Jarkko Sakkinen Signed-off-by: Greg Kroah-Hartman --- drivers/char/tpm/tpm_tis_core.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/char/tpm/tpm_tis_core.c b/drivers/char/tpm/tpm_tis_core.c index 4cc2ab2d16cc..ed0d3d8449b3 100644 --- a/drivers/char/tpm/tpm_tis_core.c +++ b/drivers/char/tpm/tpm_tis_core.c @@ -114,11 +114,10 @@ again: return 0; /* process status changes without irq support */ do { + usleep_range(priv->timeout_min, priv->timeout_max); status = chip->ops->status(chip); if ((status & mask) == mask) return 0; - usleep_range(priv->timeout_min, - priv->timeout_max); } while (time_before(jiffies, stop)); return -ETIME; } From afada73000bef7c79a22f0d7e93fac414eeff19e Mon Sep 17 00:00:00 2001 From: Jacek Lawrynowicz Date: Tue, 25 Mar 2025 12:43:06 +0100 Subject: [PATCH 045/136] accel/ivpu: Fix PM related deadlocks in MS IOCTLs commit d893da85e06edf54737bb80648bb58ba8fd56d9f upstream. Prevent runtime resume/suspend while MS IOCTLs are in progress. Failed suspend will call ivpu_ms_cleanup() that would try to acquire file_priv->ms_lock, which is already held by the IOCTLs. Fixes: cdfad4db7756 ("accel/ivpu: Add NPU profiling support") Cc: stable@vger.kernel.org # v6.11+ Signed-off-by: Maciej Falkowski Reviewed-by: Lizhi Hou Signed-off-by: Jacek Lawrynowicz Link: https://lore.kernel.org/r/20250325114306.3740022-3-maciej.falkowski@linux.intel.com Signed-off-by: Greg Kroah-Hartman --- drivers/accel/ivpu/ivpu_debugfs.c | 4 ++-- drivers/accel/ivpu/ivpu_ms.c | 18 ++++++++++++++++++ 2 files changed, 20 insertions(+), 2 deletions(-) diff --git a/drivers/accel/ivpu/ivpu_debugfs.c b/drivers/accel/ivpu/ivpu_debugfs.c index 8d50981594d1..eccedb0c8886 100644 --- a/drivers/accel/ivpu/ivpu_debugfs.c +++ b/drivers/accel/ivpu/ivpu_debugfs.c @@ -331,7 +331,7 @@ ivpu_force_recovery_fn(struct file *file, const char __user *user_buf, size_t si return -EINVAL; ret = ivpu_rpm_get(vdev); - if (ret) + if (ret < 0) return ret; ivpu_pm_trigger_recovery(vdev, "debugfs"); @@ -408,7 +408,7 @@ static int dct_active_set(void *data, u64 active_percent) return -EINVAL; ret = ivpu_rpm_get(vdev); - if (ret) + if (ret < 0) return ret; if (active_percent) diff --git a/drivers/accel/ivpu/ivpu_ms.c b/drivers/accel/ivpu/ivpu_ms.c index 2f9d37f5c208..dfb75c8b52ce 100644 --- a/drivers/accel/ivpu/ivpu_ms.c +++ b/drivers/accel/ivpu/ivpu_ms.c @@ -44,6 +44,10 @@ int ivpu_ms_start_ioctl(struct drm_device *dev, void *data, struct drm_file *fil args->sampling_period_ns < MS_MIN_SAMPLE_PERIOD_NS) return -EINVAL; + ret = ivpu_rpm_get(vdev); + if (ret < 0) + return ret; + mutex_lock(&file_priv->ms_lock); if (get_instance_by_mask(file_priv, args->metric_group_mask)) { @@ -96,6 +100,8 @@ err_free_ms: kfree(ms); unlock: mutex_unlock(&file_priv->ms_lock); + + ivpu_rpm_put(vdev); return ret; } @@ -160,6 +166,10 @@ int ivpu_ms_get_data_ioctl(struct drm_device *dev, void *data, struct drm_file * if (!args->metric_group_mask) return -EINVAL; + ret = ivpu_rpm_get(vdev); + if (ret < 0) + return ret; + mutex_lock(&file_priv->ms_lock); ms = get_instance_by_mask(file_priv, args->metric_group_mask); @@ -187,6 +197,7 @@ int ivpu_ms_get_data_ioctl(struct drm_device *dev, void *data, struct drm_file * unlock: mutex_unlock(&file_priv->ms_lock); + ivpu_rpm_put(vdev); return ret; } @@ -204,11 +215,17 @@ int ivpu_ms_stop_ioctl(struct drm_device *dev, void *data, struct drm_file *file { struct ivpu_file_priv *file_priv = file->driver_priv; struct drm_ivpu_metric_streamer_stop *args = data; + struct ivpu_device *vdev = file_priv->vdev; struct ivpu_ms_instance *ms; + int ret; if (!args->metric_group_mask) return -EINVAL; + ret = ivpu_rpm_get(vdev); + if (ret < 0) + return ret; + mutex_lock(&file_priv->ms_lock); ms = get_instance_by_mask(file_priv, args->metric_group_mask); @@ -217,6 +234,7 @@ int ivpu_ms_stop_ioctl(struct drm_device *dev, void *data, struct drm_file *file mutex_unlock(&file_priv->ms_lock); + ivpu_rpm_put(vdev); return ms ? 0 : -EINVAL; } From df6ef66cc3ff93287d38b4bec043c8a0596a2701 Mon Sep 17 00:00:00 2001 From: Murad Masimov Date: Mon, 13 Jan 2025 13:51:31 +0300 Subject: [PATCH 046/136] media: streamzap: prevent processing IR data on URB failure commit 549f6d348167fb2f7800ed7c8d4bce9630c74498 upstream. If streamzap_callback() receives an urb with any non-critical error status, i.e. any error code other than -ECONNRESET, -ENOENT or -ESHUTDOWN, it will try to process IR data, ignoring a possible transfer failure. Make streamzap_callback() process IR data only when urb->status is 0. Move processing logic to a separate function to make code cleaner and more similar to the URB completion handlers in other RC drivers. Found by Linux Verification Center (linuxtesting.org) with Syzkaller. Fixes: 19770693c354 ("V4L/DVB: staging/lirc: add lirc_streamzap driver") Cc: stable@vger.kernel.org Signed-off-by: Murad Masimov Signed-off-by: Sean Young Signed-off-by: Hans Verkuil Signed-off-by: Greg Kroah-Hartman --- drivers/media/rc/streamzap.c | 68 ++++++++++++++++++++---------------- 1 file changed, 38 insertions(+), 30 deletions(-) diff --git a/drivers/media/rc/streamzap.c b/drivers/media/rc/streamzap.c index 2ce62fe5d60f..d3b48a0dd1f4 100644 --- a/drivers/media/rc/streamzap.c +++ b/drivers/media/rc/streamzap.c @@ -138,39 +138,10 @@ static void sz_push_half_space(struct streamzap_ir *sz, sz_push_full_space(sz, value & SZ_SPACE_MASK); } -/* - * streamzap_callback - usb IRQ handler callback - * - * This procedure is invoked on reception of data from - * the usb remote. - */ -static void streamzap_callback(struct urb *urb) +static void sz_process_ir_data(struct streamzap_ir *sz, int len) { - struct streamzap_ir *sz; unsigned int i; - int len; - if (!urb) - return; - - sz = urb->context; - len = urb->actual_length; - - switch (urb->status) { - case -ECONNRESET: - case -ENOENT: - case -ESHUTDOWN: - /* - * this urb is terminated, clean up. - * sz might already be invalid at this point - */ - dev_err(sz->dev, "urb terminated, status: %d\n", urb->status); - return; - default: - break; - } - - dev_dbg(sz->dev, "%s: received urb, len %d\n", __func__, len); for (i = 0; i < len; i++) { dev_dbg(sz->dev, "sz->buf_in[%d]: %x\n", i, (unsigned char)sz->buf_in[i]); @@ -219,6 +190,43 @@ static void streamzap_callback(struct urb *urb) } ir_raw_event_handle(sz->rdev); +} + +/* + * streamzap_callback - usb IRQ handler callback + * + * This procedure is invoked on reception of data from + * the usb remote. + */ +static void streamzap_callback(struct urb *urb) +{ + struct streamzap_ir *sz; + int len; + + if (!urb) + return; + + sz = urb->context; + len = urb->actual_length; + + switch (urb->status) { + case 0: + dev_dbg(sz->dev, "%s: received urb, len %d\n", __func__, len); + sz_process_ir_data(sz, len); + break; + case -ECONNRESET: + case -ENOENT: + case -ESHUTDOWN: + /* + * this urb is terminated, clean up. + * sz might already be invalid at this point + */ + dev_err(sz->dev, "urb terminated, status: %d\n", urb->status); + return; + default: + break; + } + usb_submit_urb(urb, GFP_ATOMIC); } From f67c3f84520b4069761119e25cdf283bc026563c Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Thu, 19 Dec 2024 20:27:30 +0100 Subject: [PATCH 047/136] media: hi556: Fix memory leak (on error) in hi556_check_hwcfg() commit ed554da65abd0c561e40d35272d1a61d030fe977 upstream. Commit 7d968b5badfc ("media: hi556: Return -EPROBE_DEFER if no endpoint is found") moved the v4l2_fwnode_endpoint_alloc_parse() call in hi556_check_hwcfg() up, but it did not make the error-exit paths between the old and new call-site use "goto check_hwcfg_error;" to free the bus_cfg on errors. Add the missing "goto check_hwcfg_error;" statements to fix a memleak on early error-exits from hi556_check_hwcfg(). Fixes: 7d968b5badfc ("media: hi556: Return -EPROBE_DEFER if no endpoint is found") Cc: stable@vger.kernel.org Signed-off-by: Hans de Goede Signed-off-by: Sakari Ailus Signed-off-by: Hans Verkuil Signed-off-by: Greg Kroah-Hartman --- drivers/media/i2c/hi556.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/media/i2c/hi556.c b/drivers/media/i2c/hi556.c index f31f9886c924..0e89aff9c664 100644 --- a/drivers/media/i2c/hi556.c +++ b/drivers/media/i2c/hi556.c @@ -1230,12 +1230,13 @@ static int hi556_check_hwcfg(struct device *dev) ret = fwnode_property_read_u32(fwnode, "clock-frequency", &mclk); if (ret) { dev_err(dev, "can't get clock frequency"); - return ret; + goto check_hwcfg_error; } if (mclk != HI556_MCLK) { dev_err(dev, "external clock %d is not supported", mclk); - return -EINVAL; + ret = -EINVAL; + goto check_hwcfg_error; } if (bus_cfg.bus.mipi_csi2.num_data_lanes != 2) { From 3f1f712f80db845441eca5ae0d63b75f8736d975 Mon Sep 17 00:00:00 2001 From: Nicolas Dufresne Date: Tue, 10 Dec 2024 16:02:53 -0500 Subject: [PATCH 048/136] media: visl: Fix ERANGE error when setting enum controls commit d98e9213a768a3cc3a99f5e1abe09ad3baff2104 upstream. The visl driver supports both frame and slice mode, with and without a start-code. But, the range and default for these enum controls was not set, which currently limits the decoder to enums with a value of 0. Fix this by setting the decoder mode and start code controls for both the H.264 and HEVC codecs. Fixes: 0c078e310b6d ("media: visl: add virtual stateless decoder driver") Cc: stable@vger.kernel.org Signed-off-by: Nicolas Dufresne Signed-off-by: Sebastian Fricke Signed-off-by: Hans Verkuil Signed-off-by: Greg Kroah-Hartman --- drivers/media/test-drivers/visl/visl-core.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/drivers/media/test-drivers/visl/visl-core.c b/drivers/media/test-drivers/visl/visl-core.c index c46464bcaf2e..93239391f2cf 100644 --- a/drivers/media/test-drivers/visl/visl-core.c +++ b/drivers/media/test-drivers/visl/visl-core.c @@ -161,9 +161,15 @@ static const struct visl_ctrl_desc visl_h264_ctrl_descs[] = { }, { .cfg.id = V4L2_CID_STATELESS_H264_DECODE_MODE, + .cfg.min = V4L2_STATELESS_H264_DECODE_MODE_SLICE_BASED, + .cfg.max = V4L2_STATELESS_H264_DECODE_MODE_FRAME_BASED, + .cfg.def = V4L2_STATELESS_H264_DECODE_MODE_SLICE_BASED, }, { .cfg.id = V4L2_CID_STATELESS_H264_START_CODE, + .cfg.min = V4L2_STATELESS_H264_START_CODE_NONE, + .cfg.max = V4L2_STATELESS_H264_START_CODE_ANNEX_B, + .cfg.def = V4L2_STATELESS_H264_START_CODE_NONE, }, { .cfg.id = V4L2_CID_STATELESS_H264_SLICE_PARAMS, @@ -198,9 +204,15 @@ static const struct visl_ctrl_desc visl_hevc_ctrl_descs[] = { }, { .cfg.id = V4L2_CID_STATELESS_HEVC_DECODE_MODE, + .cfg.min = V4L2_STATELESS_HEVC_DECODE_MODE_SLICE_BASED, + .cfg.max = V4L2_STATELESS_HEVC_DECODE_MODE_FRAME_BASED, + .cfg.def = V4L2_STATELESS_HEVC_DECODE_MODE_SLICE_BASED, }, { .cfg.id = V4L2_CID_STATELESS_HEVC_START_CODE, + .cfg.min = V4L2_STATELESS_HEVC_START_CODE_NONE, + .cfg.max = V4L2_STATELESS_HEVC_START_CODE_ANNEX_B, + .cfg.def = V4L2_STATELESS_HEVC_START_CODE_NONE, }, { .cfg.id = V4L2_CID_STATELESS_HEVC_ENTRY_POINT_OFFSETS, From dd0d323b472f7251d09f5d4b5ce731ffad20e01b Mon Sep 17 00:00:00 2001 From: Jiasheng Jiang Date: Fri, 22 Nov 2024 20:46:03 +0000 Subject: [PATCH 049/136] media: platform: stm32: Add check for clk_enable() commit f883f34b6a46b1a09d44d7f94c3cd72fe0e8f93b upstream. Add check for the return value of clk_enable() to gurantee the success. Fixes: 002e8f0d5927 ("media: stm32-dma2d: STM32 DMA2D driver") Cc: stable@vger.kernel.org Signed-off-by: Jiasheng Jiang Signed-off-by: Hans Verkuil Signed-off-by: Greg Kroah-Hartman --- drivers/media/platform/st/stm32/dma2d/dma2d.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/media/platform/st/stm32/dma2d/dma2d.c b/drivers/media/platform/st/stm32/dma2d/dma2d.c index 92f1edee58f8..3c64e9126025 100644 --- a/drivers/media/platform/st/stm32/dma2d/dma2d.c +++ b/drivers/media/platform/st/stm32/dma2d/dma2d.c @@ -492,7 +492,8 @@ static void device_run(void *prv) dst->sequence = frm_cap->sequence++; v4l2_m2m_buf_copy_metadata(src, dst, true); - clk_enable(dev->gate); + if (clk_enable(dev->gate)) + goto end; dma2d_config_fg(dev, frm_out, vb2_dma_contig_plane_dma_addr(&src->vb2_buf, 0)); From b933486f6b8049dc1e05d263db848ec44b79f958 Mon Sep 17 00:00:00 2001 From: Dave Stevenson Date: Thu, 23 Jan 2025 15:37:49 +0000 Subject: [PATCH 050/136] media: imx219: Adjust PLL settings based on the number of MIPI lanes commit 591a07588c03437dbcc3addfff07675de95a461e upstream. Commit ceddfd4493b3 ("media: i2c: imx219: Support four-lane operation") added support for device tree to allow configuration of the sensor to use 4 lanes with a link frequency of 363MHz, and amended the advertised pixel rate to 280.8MPix/s. However it didn't change any of the PLL settings, so actually it would have been running overclocked in the MIPI block, and with the frame rate and exposure calculations being wrong as the pixel rate was unchanged. The pixel rate and link frequency advertised were taken from the "Clock Setting Example" section of the datasheet. However those are based on an external clock of 12MHz, and are unachievable with a clock of 24MHz - it seems PREPLLCLK_VT_DIV and PREPLLCK_OP_DIV can ONLY be set via the automatic configuration documented in "9-1-2 EXCK_FREQ setting depend on INCK frequency", not by writing the registers. The closest we can get with a 24MHz clock is 281.6MPix/s and 364MHz. Dropping all support for the 363MHz link frequency would cause problems for existing users, so allow it, but log a warning that the requested value is being changed to the supported one. Fixes: ceddfd4493b3 ("media: i2c: imx219: Support four-lane operation") Cc: stable@vger.kernel.org Co-developed-by: Peyton Howe Signed-off-by: Peyton Howe Signed-off-by: Dave Stevenson Signed-off-by: Sakari Ailus Signed-off-by: Hans Verkuil Signed-off-by: Greg Kroah-Hartman --- drivers/media/i2c/imx219.c | 93 ++++++++++++++++++++++++++++---------- 1 file changed, 69 insertions(+), 24 deletions(-) diff --git a/drivers/media/i2c/imx219.c b/drivers/media/i2c/imx219.c index e78a80b2bb2e..d34fa3d9519a 100644 --- a/drivers/media/i2c/imx219.c +++ b/drivers/media/i2c/imx219.c @@ -134,10 +134,11 @@ /* Pixel rate is fixed for all the modes */ #define IMX219_PIXEL_RATE 182400000 -#define IMX219_PIXEL_RATE_4LANE 280800000 +#define IMX219_PIXEL_RATE_4LANE 281600000 #define IMX219_DEFAULT_LINK_FREQ 456000000 -#define IMX219_DEFAULT_LINK_FREQ_4LANE 363000000 +#define IMX219_DEFAULT_LINK_FREQ_4LANE_UNSUPPORTED 363000000 +#define IMX219_DEFAULT_LINK_FREQ_4LANE 364000000 /* IMX219 native and active pixel array size. */ #define IMX219_NATIVE_WIDTH 3296U @@ -169,15 +170,6 @@ static const struct cci_reg_sequence imx219_common_regs[] = { { CCI_REG8(0x30eb), 0x05 }, { CCI_REG8(0x30eb), 0x09 }, - /* PLL Clock Table */ - { IMX219_REG_VTPXCK_DIV, 5 }, - { IMX219_REG_VTSYCK_DIV, 1 }, - { IMX219_REG_PREPLLCK_VT_DIV, 3 }, /* 0x03 = AUTO set */ - { IMX219_REG_PREPLLCK_OP_DIV, 3 }, /* 0x03 = AUTO set */ - { IMX219_REG_PLL_VT_MPY, 57 }, - { IMX219_REG_OPSYCK_DIV, 1 }, - { IMX219_REG_PLL_OP_MPY, 114 }, - /* Undocumented registers */ { CCI_REG8(0x455e), 0x00 }, { CCI_REG8(0x471e), 0x4b }, @@ -202,12 +194,45 @@ static const struct cci_reg_sequence imx219_common_regs[] = { { IMX219_REG_EXCK_FREQ, IMX219_EXCK_FREQ(IMX219_XCLK_FREQ / 1000000) }, }; +static const struct cci_reg_sequence imx219_2lane_regs[] = { + /* PLL Clock Table */ + { IMX219_REG_VTPXCK_DIV, 5 }, + { IMX219_REG_VTSYCK_DIV, 1 }, + { IMX219_REG_PREPLLCK_VT_DIV, 3 }, /* 0x03 = AUTO set */ + { IMX219_REG_PREPLLCK_OP_DIV, 3 }, /* 0x03 = AUTO set */ + { IMX219_REG_PLL_VT_MPY, 57 }, + { IMX219_REG_OPSYCK_DIV, 1 }, + { IMX219_REG_PLL_OP_MPY, 114 }, + + /* 2-Lane CSI Mode */ + { IMX219_REG_CSI_LANE_MODE, IMX219_CSI_2_LANE_MODE }, +}; + +static const struct cci_reg_sequence imx219_4lane_regs[] = { + /* PLL Clock Table */ + { IMX219_REG_VTPXCK_DIV, 5 }, + { IMX219_REG_VTSYCK_DIV, 1 }, + { IMX219_REG_PREPLLCK_VT_DIV, 3 }, /* 0x03 = AUTO set */ + { IMX219_REG_PREPLLCK_OP_DIV, 3 }, /* 0x03 = AUTO set */ + { IMX219_REG_PLL_VT_MPY, 88 }, + { IMX219_REG_OPSYCK_DIV, 1 }, + { IMX219_REG_PLL_OP_MPY, 91 }, + + /* 4-Lane CSI Mode */ + { IMX219_REG_CSI_LANE_MODE, IMX219_CSI_4_LANE_MODE }, +}; + static const s64 imx219_link_freq_menu[] = { IMX219_DEFAULT_LINK_FREQ, }; static const s64 imx219_link_freq_4lane_menu[] = { IMX219_DEFAULT_LINK_FREQ_4LANE, + /* + * This will never be advertised to userspace, but will be used for + * v4l2_link_freq_to_bitmap + */ + IMX219_DEFAULT_LINK_FREQ_4LANE_UNSUPPORTED, }; static const char * const imx219_test_pattern_menu[] = { @@ -663,9 +688,11 @@ static int imx219_set_framefmt(struct imx219 *imx219, static int imx219_configure_lanes(struct imx219 *imx219) { - return cci_write(imx219->regmap, IMX219_REG_CSI_LANE_MODE, - imx219->lanes == 2 ? IMX219_CSI_2_LANE_MODE : - IMX219_CSI_4_LANE_MODE, NULL); + /* Write the appropriate PLL settings for the number of MIPI lanes */ + return cci_multi_reg_write(imx219->regmap, + imx219->lanes == 2 ? imx219_2lane_regs : imx219_4lane_regs, + imx219->lanes == 2 ? ARRAY_SIZE(imx219_2lane_regs) : + ARRAY_SIZE(imx219_4lane_regs), NULL); }; static int imx219_start_streaming(struct imx219 *imx219, @@ -1042,6 +1069,7 @@ static int imx219_check_hwcfg(struct device *dev, struct imx219 *imx219) struct v4l2_fwnode_endpoint ep_cfg = { .bus_type = V4L2_MBUS_CSI2_DPHY }; + unsigned long link_freq_bitmap; int ret = -EINVAL; endpoint = fwnode_graph_get_next_endpoint(dev_fwnode(dev), NULL); @@ -1063,23 +1091,40 @@ static int imx219_check_hwcfg(struct device *dev, struct imx219 *imx219) imx219->lanes = ep_cfg.bus.mipi_csi2.num_data_lanes; /* Check the link frequency set in device tree */ - if (!ep_cfg.nr_of_link_frequencies) { - dev_err_probe(dev, -EINVAL, - "link-frequency property not found in DT\n"); - goto error_out; + switch (imx219->lanes) { + case 2: + ret = v4l2_link_freq_to_bitmap(dev, + ep_cfg.link_frequencies, + ep_cfg.nr_of_link_frequencies, + imx219_link_freq_menu, + ARRAY_SIZE(imx219_link_freq_menu), + &link_freq_bitmap); + break; + case 4: + ret = v4l2_link_freq_to_bitmap(dev, + ep_cfg.link_frequencies, + ep_cfg.nr_of_link_frequencies, + imx219_link_freq_4lane_menu, + ARRAY_SIZE(imx219_link_freq_4lane_menu), + &link_freq_bitmap); + + if (!ret && (link_freq_bitmap & BIT(1))) { + dev_warn(dev, "Link frequency of %d not supported, but has been incorrectly advertised previously\n", + IMX219_DEFAULT_LINK_FREQ_4LANE_UNSUPPORTED); + dev_warn(dev, "Using link frequency of %d\n", + IMX219_DEFAULT_LINK_FREQ_4LANE); + link_freq_bitmap |= BIT(0); + } + break; } - if (ep_cfg.nr_of_link_frequencies != 1 || - (ep_cfg.link_frequencies[0] != ((imx219->lanes == 2) ? - IMX219_DEFAULT_LINK_FREQ : IMX219_DEFAULT_LINK_FREQ_4LANE))) { + if (ret || !(link_freq_bitmap & BIT(0))) { + ret = -EINVAL; dev_err_probe(dev, -EINVAL, "Link frequency not supported: %lld\n", ep_cfg.link_frequencies[0]); - goto error_out; } - ret = 0; - error_out: v4l2_fwnode_endpoint_free(&ep_cfg); fwnode_handle_put(endpoint); From baea1762cdf20cfd9d66014e79d773a1eeef67a1 Mon Sep 17 00:00:00 2001 From: Karina Yankevich Date: Wed, 21 Aug 2024 14:31:34 +0300 Subject: [PATCH 051/136] media: v4l2-dv-timings: prevent possible overflow in v4l2_detect_gtf() commit 3edd1fc48d2c045e8259561797c89fe78f01717e upstream. In v4l2_detect_gtf(), it seems safer to cast the 32-bit image_width variable to the 64-bit type u64 before multiplying to avoid a possible overflow. The resulting object code even seems to look better, at least on x86_64. Found by Linux Verification Center (linuxtesting.org) with Svace. [Sergey: rewrote the patch subject/descripition] Fixes: c9bc9f50753d ("[media] v4l2-dv-timings: fix overflow in gtf timings calculation") Cc: stable@vger.kernel.org Signed-off-by: Karina Yankevich Signed-off-by: Sergey Shtylyov Signed-off-by: Hans Verkuil Signed-off-by: Greg Kroah-Hartman --- drivers/media/v4l2-core/v4l2-dv-timings.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/media/v4l2-core/v4l2-dv-timings.c b/drivers/media/v4l2-core/v4l2-dv-timings.c index 2cf5dcee0ce8..4d05873892c1 100644 --- a/drivers/media/v4l2-core/v4l2-dv-timings.c +++ b/drivers/media/v4l2-core/v4l2-dv-timings.c @@ -764,7 +764,7 @@ bool v4l2_detect_gtf(unsigned int frame_height, u64 num; u32 den; - num = ((image_width * GTF_D_C_PRIME * (u64)hfreq) - + num = (((u64)image_width * GTF_D_C_PRIME * hfreq) - ((u64)image_width * GTF_D_M_PRIME * 1000)); den = (hfreq * (100 - GTF_D_C_PRIME) + GTF_D_M_PRIME * 1000) * (2 * GTF_CELL_GRAN); @@ -774,7 +774,7 @@ bool v4l2_detect_gtf(unsigned int frame_height, u64 num; u32 den; - num = ((image_width * GTF_S_C_PRIME * (u64)hfreq) - + num = (((u64)image_width * GTF_S_C_PRIME * hfreq) - ((u64)image_width * GTF_S_M_PRIME * 1000)); den = (hfreq * (100 - GTF_S_C_PRIME) + GTF_S_M_PRIME * 1000) * (2 * GTF_CELL_GRAN); From 3ff4feef7af388299a23a0a49a48679b633b0a0e Mon Sep 17 00:00:00 2001 From: Sakari Ailus Date: Fri, 10 Jan 2025 10:11:51 +0200 Subject: [PATCH 052/136] Revert "media: imx214: Fix the error handling in imx214_probe()" commit abd88757252c2a2cea7909f3922de1f0e9e04002 upstream. This reverts commit 9bc92332cc3f06fda3c6e2423995ca2da0a7ec9a. Revert this "fix" as it's not really helpful but makes backporting a proper fix harder. Fixes: 9bc92332cc3f ("media: imx214: Fix the error handling in imx214_probe()") Cc: stable@vger.kernel.org # for >= v6.12 Signed-off-by: Sakari Ailus Signed-off-by: Hans Verkuil Signed-off-by: Greg Kroah-Hartman --- drivers/media/i2c/imx214.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/media/i2c/imx214.c b/drivers/media/i2c/imx214.c index 4962cfe7c83d..10b6ad66d126 100644 --- a/drivers/media/i2c/imx214.c +++ b/drivers/media/i2c/imx214.c @@ -1114,7 +1114,6 @@ free_ctrl: v4l2_ctrl_handler_free(&imx214->ctrls); error_power_off: pm_runtime_disable(imx214->dev); - regulator_bulk_disable(IMX214_NUM_SUPPLIES, imx214->supplies); return ret; } From 983b5434a66b84a6c06c6d5dfe2dbe11e8feb5d2 Mon Sep 17 00:00:00 2001 From: Sakari Ailus Date: Fri, 10 Jan 2025 14:50:27 +0200 Subject: [PATCH 053/136] media: i2c: ccs: Set the device's runtime PM status correctly in remove commit e04604583095faf455b3490b004254a225fd60d4 upstream. Set the device's runtime PM status to suspended in device removal only if it wasn't suspended already. Fixes: 9447082ae666 ("[media] smiapp: Implement power-on and power-off sequences without runtime PM") Cc: stable@vger.kernel.org # for >= v5.15 Signed-off-by: Sakari Ailus Signed-off-by: Hans Verkuil Signed-off-by: Greg Kroah-Hartman --- drivers/media/i2c/ccs/ccs-core.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/media/i2c/ccs/ccs-core.c b/drivers/media/i2c/ccs/ccs-core.c index cb21df46bab1..62e745c34827 100644 --- a/drivers/media/i2c/ccs/ccs-core.c +++ b/drivers/media/i2c/ccs/ccs-core.c @@ -3591,9 +3591,10 @@ static void ccs_remove(struct i2c_client *client) v4l2_async_unregister_subdev(subdev); pm_runtime_disable(&client->dev); - if (!pm_runtime_status_suspended(&client->dev)) + if (!pm_runtime_status_suspended(&client->dev)) { ccs_power_off(&client->dev); - pm_runtime_set_suspended(&client->dev); + pm_runtime_set_suspended(&client->dev); + } for (i = 0; i < sensor->ssds_used; i++) v4l2_device_unregister_subdev(&sensor->ssds[i].sd); From ad466aacb17f960e02854e45641462a9f6612f9a Mon Sep 17 00:00:00 2001 From: Sakari Ailus Date: Fri, 10 Jan 2025 15:54:22 +0200 Subject: [PATCH 054/136] media: i2c: ccs: Set the device's runtime PM status correctly in probe commit 80704d14f1bd3628f578510e0a88b66824990ef6 upstream. Set the device's runtime PM status to suspended in probe error paths where it was previously set to active. Fixes: 9447082ae666 ("[media] smiapp: Implement power-on and power-off sequences without runtime PM") Cc: stable@vger.kernel.org # for >= v5.15 Signed-off-by: Sakari Ailus Signed-off-by: Hans Verkuil Signed-off-by: Greg Kroah-Hartman --- drivers/media/i2c/ccs/ccs-core.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/media/i2c/ccs/ccs-core.c b/drivers/media/i2c/ccs/ccs-core.c index 62e745c34827..4b7d8039b1c9 100644 --- a/drivers/media/i2c/ccs/ccs-core.c +++ b/drivers/media/i2c/ccs/ccs-core.c @@ -3562,6 +3562,7 @@ static int ccs_probe(struct i2c_client *client) out_disable_runtime_pm: pm_runtime_put_noidle(&client->dev); pm_runtime_disable(&client->dev); + pm_runtime_set_suspended(&client->dev); out_cleanup: ccs_cleanup(sensor); From b155aecd7f0fdc36c8e06af424e280a5a4875c69 Mon Sep 17 00:00:00 2001 From: Sakari Ailus Date: Fri, 17 Jan 2025 15:38:13 +0200 Subject: [PATCH 055/136] media: i2c: ov7251: Set enable GPIO low in probe commit a1963698d59cec83df640ded343af08b76c8e9c5 upstream. Set the enable GPIO low when acquiring it. Fixes: d30bb512da3d ("media: Add a driver for the ov7251 camera sensor") Cc: stable@vger.kernel.org Signed-off-by: Sakari Ailus Reviewed-by: Dave Stevenson Signed-off-by: Hans Verkuil Signed-off-by: Greg Kroah-Hartman --- drivers/media/i2c/ov7251.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/media/i2c/ov7251.c b/drivers/media/i2c/ov7251.c index 30f61e04ecaf..f3e2d26bb840 100644 --- a/drivers/media/i2c/ov7251.c +++ b/drivers/media/i2c/ov7251.c @@ -1696,7 +1696,7 @@ static int ov7251_probe(struct i2c_client *client) return PTR_ERR(ov7251->analog_regulator); } - ov7251->enable_gpio = devm_gpiod_get(dev, "enable", GPIOD_OUT_HIGH); + ov7251->enable_gpio = devm_gpiod_get(dev, "enable", GPIOD_OUT_LOW); if (IS_ERR(ov7251->enable_gpio)) { dev_err(dev, "cannot get enable gpio\n"); return PTR_ERR(ov7251->enable_gpio); From e22fa60bcd85bb392422bf9f3210694893dc1347 Mon Sep 17 00:00:00 2001 From: Sakari Ailus Date: Fri, 17 Jan 2025 16:04:02 +0200 Subject: [PATCH 056/136] media: i2c: ov7251: Introduce 1 ms delay between regulators and en GPIO commit 3d391292cdd53984ec1b9a1f6182a62a62751e03 upstream. Lift the xshutdown (enable) GPIO 1 ms after enabling the regulators, as required by the sensor's power-up sequence. Fixes: d30bb512da3d ("media: Add a driver for the ov7251 camera sensor") Cc: stable@vger.kernel.org Signed-off-by: Sakari Ailus Reviewed-by: Dave Stevenson Signed-off-by: Hans Verkuil Signed-off-by: Greg Kroah-Hartman --- drivers/media/i2c/ov7251.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/media/i2c/ov7251.c b/drivers/media/i2c/ov7251.c index f3e2d26bb840..3226888d77e9 100644 --- a/drivers/media/i2c/ov7251.c +++ b/drivers/media/i2c/ov7251.c @@ -922,6 +922,8 @@ static int ov7251_set_power_on(struct device *dev) return ret; } + usleep_range(1000, 1100); + gpiod_set_value_cansleep(ov7251->enable_gpio, 1); /* wait at least 65536 external clock cycles */ From 4b1bdaadbf19f6c0d1a8d7e43418eb97c224a017 Mon Sep 17 00:00:00 2001 From: Ricardo Ribalda Date: Mon, 24 Feb 2025 07:03:54 +0000 Subject: [PATCH 057/136] media: nuvoton: Fix reference handling of ece_node commit 8ba4ef40ad6ca62368292a69855324213181abfb upstream. Make sure all the code paths call of_node_put(). Instead of manually calling of_node_put, use the __free macros/helpers. Cc: stable@vger.kernel.org Fixes: 46c15a4ff1f4 ("media: nuvoton: Add driver for NPCM video capture and encoding engine") Signed-off-by: Ricardo Ribalda Signed-off-by: Hans Verkuil Signed-off-by: Greg Kroah-Hartman --- drivers/media/platform/nuvoton/npcm-video.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/media/platform/nuvoton/npcm-video.c b/drivers/media/platform/nuvoton/npcm-video.c index db454c9d2641..5b8a7e190194 100644 --- a/drivers/media/platform/nuvoton/npcm-video.c +++ b/drivers/media/platform/nuvoton/npcm-video.c @@ -1650,8 +1650,8 @@ rel_ctrl_handler: static int npcm_video_ece_init(struct npcm_video *video) { + struct device_node *ece_node __free(device_node) = NULL; struct device *dev = video->dev; - struct device_node *ece_node; struct platform_device *ece_pdev; void __iomem *regs; @@ -1671,7 +1671,6 @@ static int npcm_video_ece_init(struct npcm_video *video) dev_err(dev, "Failed to find ECE device\n"); return -ENODEV; } - of_node_put(ece_node); regs = devm_platform_ioremap_resource(ece_pdev, 0); if (IS_ERR(regs)) { From 3da0d7318730a45fdba5623974f518c62188fea2 Mon Sep 17 00:00:00 2001 From: Ricardo Ribalda Date: Mon, 24 Feb 2025 07:03:55 +0000 Subject: [PATCH 058/136] media: nuvoton: Fix reference handling of ece_pdev commit 453d5cadab1bde8e6fdd5bd05f4200338cb21e72 upstream. When we obtain a reference to of a platform_device, we need to release it via put_device. Found by cocci: ./platform/nuvoton/npcm-video.c:1677:3-9: ERROR: missing put_device; call of_find_device_by_node on line 1667, but without a corresponding object release within this function. ./platform/nuvoton/npcm-video.c:1684:3-9: ERROR: missing put_device; call of_find_device_by_node on line 1667, but without a corresponding object release within this function. ./platform/nuvoton/npcm-video.c:1690:3-9: ERROR: missing put_device; call of_find_device_by_node on line 1667, but without a corresponding object release within this function. ./platform/nuvoton/npcm-video.c:1694:1-7: ERROR: missing put_device; call of_find_device_by_node on line 1667, but without a corresponding object release within this function. Instead of manually calling put_device, use the __free macros. Cc: stable@vger.kernel.org Fixes: 46c15a4ff1f4 ("media: nuvoton: Add driver for NPCM video capture and encoding engine") Signed-off-by: Ricardo Ribalda Signed-off-by: Hans Verkuil Signed-off-by: Greg Kroah-Hartman --- drivers/media/platform/nuvoton/npcm-video.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/media/platform/nuvoton/npcm-video.c b/drivers/media/platform/nuvoton/npcm-video.c index 5b8a7e190194..e0dee768a3be 100644 --- a/drivers/media/platform/nuvoton/npcm-video.c +++ b/drivers/media/platform/nuvoton/npcm-video.c @@ -1671,6 +1671,7 @@ static int npcm_video_ece_init(struct npcm_video *video) dev_err(dev, "Failed to find ECE device\n"); return -ENODEV; } + struct device *ece_dev __free(put_device) = &ece_pdev->dev; regs = devm_platform_ioremap_resource(ece_pdev, 0); if (IS_ERR(regs)) { @@ -1685,7 +1686,7 @@ static int npcm_video_ece_init(struct npcm_video *video) return PTR_ERR(video->ece.regmap); } - video->ece.reset = devm_reset_control_get(&ece_pdev->dev, NULL); + video->ece.reset = devm_reset_control_get(ece_dev, NULL); if (IS_ERR(video->ece.reset)) { dev_err(dev, "Failed to get ECE reset control in DTS\n"); return PTR_ERR(video->ece.reset); From 53e376178ceacca3ef1795038b22fc9ef45ff1d3 Mon Sep 17 00:00:00 2001 From: Vikash Garodia Date: Thu, 20 Feb 2025 22:50:08 +0530 Subject: [PATCH 059/136] media: venus: hfi_parser: add check to avoid out of bound access commit 172bf5a9ef70a399bb227809db78442dc01d9e48 upstream. There is a possibility that init_codecs is invoked multiple times during manipulated payload from video firmware. In such case, if codecs_count can get incremented to value more than MAX_CODEC_NUM, there can be OOB access. Reset the count so that it always starts from beginning. Cc: stable@vger.kernel.org Fixes: 1a73374a04e5 ("media: venus: hfi_parser: add common capability parser") Reviewed-by: Bryan O'Donoghue Signed-off-by: Vikash Garodia Signed-off-by: Hans Verkuil Signed-off-by: Greg Kroah-Hartman --- drivers/media/platform/qcom/venus/hfi_parser.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/media/platform/qcom/venus/hfi_parser.c b/drivers/media/platform/qcom/venus/hfi_parser.c index 3df241dc3a11..1425c69d9006 100644 --- a/drivers/media/platform/qcom/venus/hfi_parser.c +++ b/drivers/media/platform/qcom/venus/hfi_parser.c @@ -19,6 +19,8 @@ static void init_codecs(struct venus_core *core) struct hfi_plat_caps *caps = core->caps, *cap; unsigned long bit; + core->codecs_count = 0; + if (hweight_long(core->dec_codecs) + hweight_long(core->enc_codecs) > MAX_CODEC_NUM) return; From bb3fd8b7906a12dc2b61389abb742bf6542d97fb Mon Sep 17 00:00:00 2001 From: Vikash Garodia Date: Thu, 20 Feb 2025 22:50:09 +0530 Subject: [PATCH 060/136] media: venus: hfi_parser: refactor hfi packet parsing logic commit 9edaaa8e3e15aab1ca413ab50556de1975bcb329 upstream. words_count denotes the number of words in total payload, while data points to payload of various property within it. When words_count reaches last word, data can access memory beyond the total payload. This can lead to OOB access. With this patch, the utility api for handling individual properties now returns the size of data consumed. Accordingly remaining bytes are calculated before parsing the payload, thereby eliminates the OOB access possibilities. Cc: stable@vger.kernel.org Fixes: 1a73374a04e5 ("media: venus: hfi_parser: add common capability parser") Signed-off-by: Vikash Garodia Reviewed-by: Bryan O'Donoghue Signed-off-by: Hans Verkuil Signed-off-by: Greg Kroah-Hartman --- .../media/platform/qcom/venus/hfi_parser.c | 98 ++++++++++++++----- 1 file changed, 72 insertions(+), 26 deletions(-) diff --git a/drivers/media/platform/qcom/venus/hfi_parser.c b/drivers/media/platform/qcom/venus/hfi_parser.c index 1425c69d9006..1b3db2caa99f 100644 --- a/drivers/media/platform/qcom/venus/hfi_parser.c +++ b/drivers/media/platform/qcom/venus/hfi_parser.c @@ -64,7 +64,7 @@ fill_buf_mode(struct hfi_plat_caps *cap, const void *data, unsigned int num) cap->cap_bufs_mode_dynamic = true; } -static void +static int parse_alloc_mode(struct venus_core *core, u32 codecs, u32 domain, void *data) { struct hfi_buffer_alloc_mode_supported *mode = data; @@ -72,7 +72,7 @@ parse_alloc_mode(struct venus_core *core, u32 codecs, u32 domain, void *data) u32 *type; if (num_entries > MAX_ALLOC_MODE_ENTRIES) - return; + return -EINVAL; type = mode->data; @@ -84,6 +84,8 @@ parse_alloc_mode(struct venus_core *core, u32 codecs, u32 domain, void *data) type++; } + + return sizeof(*mode); } static void fill_profile_level(struct hfi_plat_caps *cap, const void *data, @@ -98,7 +100,7 @@ static void fill_profile_level(struct hfi_plat_caps *cap, const void *data, cap->num_pl += num; } -static void +static int parse_profile_level(struct venus_core *core, u32 codecs, u32 domain, void *data) { struct hfi_profile_level_supported *pl = data; @@ -106,12 +108,14 @@ parse_profile_level(struct venus_core *core, u32 codecs, u32 domain, void *data) struct hfi_profile_level pl_arr[HFI_MAX_PROFILE_COUNT] = {}; if (pl->profile_count > HFI_MAX_PROFILE_COUNT) - return; + return -EINVAL; memcpy(pl_arr, proflevel, pl->profile_count * sizeof(*proflevel)); for_each_codec(core->caps, ARRAY_SIZE(core->caps), codecs, domain, fill_profile_level, pl_arr, pl->profile_count); + + return pl->profile_count * sizeof(*proflevel) + sizeof(u32); } static void @@ -126,7 +130,7 @@ fill_caps(struct hfi_plat_caps *cap, const void *data, unsigned int num) cap->num_caps += num; } -static void +static int parse_caps(struct venus_core *core, u32 codecs, u32 domain, void *data) { struct hfi_capabilities *caps = data; @@ -135,12 +139,14 @@ parse_caps(struct venus_core *core, u32 codecs, u32 domain, void *data) struct hfi_capability caps_arr[MAX_CAP_ENTRIES] = {}; if (num_caps > MAX_CAP_ENTRIES) - return; + return -EINVAL; memcpy(caps_arr, cap, num_caps * sizeof(*cap)); for_each_codec(core->caps, ARRAY_SIZE(core->caps), codecs, domain, fill_caps, caps_arr, num_caps); + + return sizeof(*caps); } static void fill_raw_fmts(struct hfi_plat_caps *cap, const void *fmts, @@ -155,7 +161,7 @@ static void fill_raw_fmts(struct hfi_plat_caps *cap, const void *fmts, cap->num_fmts += num_fmts; } -static void +static int parse_raw_formats(struct venus_core *core, u32 codecs, u32 domain, void *data) { struct hfi_uncompressed_format_supported *fmt = data; @@ -164,7 +170,8 @@ parse_raw_formats(struct venus_core *core, u32 codecs, u32 domain, void *data) struct raw_formats rawfmts[MAX_FMT_ENTRIES] = {}; u32 entries = fmt->format_entries; unsigned int i = 0; - u32 num_planes; + u32 num_planes = 0; + u32 size; while (entries) { num_planes = pinfo->num_planes; @@ -174,7 +181,7 @@ parse_raw_formats(struct venus_core *core, u32 codecs, u32 domain, void *data) i++; if (i >= MAX_FMT_ENTRIES) - return; + return -EINVAL; if (pinfo->num_planes > MAX_PLANES) break; @@ -186,9 +193,13 @@ parse_raw_formats(struct venus_core *core, u32 codecs, u32 domain, void *data) for_each_codec(core->caps, ARRAY_SIZE(core->caps), codecs, domain, fill_raw_fmts, rawfmts, i); + size = fmt->format_entries * (sizeof(*constr) * num_planes + 2 * sizeof(u32)) + + 2 * sizeof(u32); + + return size; } -static void parse_codecs(struct venus_core *core, void *data) +static int parse_codecs(struct venus_core *core, void *data) { struct hfi_codec_supported *codecs = data; @@ -200,21 +211,27 @@ static void parse_codecs(struct venus_core *core, void *data) core->dec_codecs &= ~HFI_VIDEO_CODEC_SPARK; core->enc_codecs &= ~HFI_VIDEO_CODEC_HEVC; } + + return sizeof(*codecs); } -static void parse_max_sessions(struct venus_core *core, const void *data) +static int parse_max_sessions(struct venus_core *core, const void *data) { const struct hfi_max_sessions_supported *sessions = data; core->max_sessions_supported = sessions->max_sessions; + + return sizeof(*sessions); } -static void parse_codecs_mask(u32 *codecs, u32 *domain, void *data) +static int parse_codecs_mask(u32 *codecs, u32 *domain, void *data) { struct hfi_codec_mask_supported *mask = data; *codecs = mask->codecs; *domain = mask->video_domains; + + return sizeof(*mask); } static void parser_init(struct venus_inst *inst, u32 *codecs, u32 *domain) @@ -283,8 +300,9 @@ static int hfi_platform_parser(struct venus_core *core, struct venus_inst *inst) u32 hfi_parser(struct venus_core *core, struct venus_inst *inst, void *buf, u32 size) { - unsigned int words_count = size >> 2; - u32 *word = buf, *data, codecs = 0, domain = 0; + u32 *words = buf, *payload, codecs = 0, domain = 0; + u32 *frame_size = buf + size; + u32 rem_bytes = size; int ret; ret = hfi_platform_parser(core, inst); @@ -301,38 +319,66 @@ u32 hfi_parser(struct venus_core *core, struct venus_inst *inst, void *buf, memset(core->caps, 0, sizeof(core->caps)); } - while (words_count) { - data = word + 1; + while (words < frame_size) { + payload = words + 1; - switch (*word) { + switch (*words) { case HFI_PROPERTY_PARAM_CODEC_SUPPORTED: - parse_codecs(core, data); + if (rem_bytes <= sizeof(struct hfi_codec_supported)) + return HFI_ERR_SYS_INSUFFICIENT_RESOURCES; + + ret = parse_codecs(core, payload); + if (ret < 0) + return HFI_ERR_SYS_INSUFFICIENT_RESOURCES; + init_codecs(core); break; case HFI_PROPERTY_PARAM_MAX_SESSIONS_SUPPORTED: - parse_max_sessions(core, data); + if (rem_bytes <= sizeof(struct hfi_max_sessions_supported)) + return HFI_ERR_SYS_INSUFFICIENT_RESOURCES; + + ret = parse_max_sessions(core, payload); break; case HFI_PROPERTY_PARAM_CODEC_MASK_SUPPORTED: - parse_codecs_mask(&codecs, &domain, data); + if (rem_bytes <= sizeof(struct hfi_codec_mask_supported)) + return HFI_ERR_SYS_INSUFFICIENT_RESOURCES; + + ret = parse_codecs_mask(&codecs, &domain, payload); break; case HFI_PROPERTY_PARAM_UNCOMPRESSED_FORMAT_SUPPORTED: - parse_raw_formats(core, codecs, domain, data); + if (rem_bytes <= sizeof(struct hfi_uncompressed_format_supported)) + return HFI_ERR_SYS_INSUFFICIENT_RESOURCES; + + ret = parse_raw_formats(core, codecs, domain, payload); break; case HFI_PROPERTY_PARAM_CAPABILITY_SUPPORTED: - parse_caps(core, codecs, domain, data); + if (rem_bytes <= sizeof(struct hfi_capabilities)) + return HFI_ERR_SYS_INSUFFICIENT_RESOURCES; + + ret = parse_caps(core, codecs, domain, payload); break; case HFI_PROPERTY_PARAM_PROFILE_LEVEL_SUPPORTED: - parse_profile_level(core, codecs, domain, data); + if (rem_bytes <= sizeof(struct hfi_profile_level_supported)) + return HFI_ERR_SYS_INSUFFICIENT_RESOURCES; + + ret = parse_profile_level(core, codecs, domain, payload); break; case HFI_PROPERTY_PARAM_BUFFER_ALLOC_MODE_SUPPORTED: - parse_alloc_mode(core, codecs, domain, data); + if (rem_bytes <= sizeof(struct hfi_buffer_alloc_mode_supported)) + return HFI_ERR_SYS_INSUFFICIENT_RESOURCES; + + ret = parse_alloc_mode(core, codecs, domain, payload); break; default: + ret = sizeof(u32); break; } - word++; - words_count--; + if (ret < 0) + return HFI_ERR_SYS_INSUFFICIENT_RESOURCES; + + words += ret / sizeof(u32); + rem_bytes -= ret; } if (!core->max_sessions_supported) From 99f929914713bff32737e703f67b39dedbb6bcc3 Mon Sep 17 00:00:00 2001 From: Sakari Ailus Date: Fri, 10 Jan 2025 14:55:59 +0200 Subject: [PATCH 061/136] media: i2c: imx319: Rectify runtime PM handling probe and remove commit 5f5ffd3bc62b2e6c478061918b10473d8b90ac2d upstream. Idle the device only after the async sub-device has been successfully registered. In error handling, set the device's runtime PM status to suspended only if it has been set to active previously in probe. Also set the device's runtime PM status to suspended in remove only if it wasn't so already. Fixes: 8a89dc62f28c ("media: add imx319 camera sensor driver") Cc: stable@vger.kernel.org # for >= v6.12 Signed-off-by: Sakari Ailus Signed-off-by: Hans Verkuil Signed-off-by: Greg Kroah-Hartman --- drivers/media/i2c/imx319.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/drivers/media/i2c/imx319.c b/drivers/media/i2c/imx319.c index dd1b4ff983dc..701840f4a5cc 100644 --- a/drivers/media/i2c/imx319.c +++ b/drivers/media/i2c/imx319.c @@ -2442,17 +2442,19 @@ static int imx319_probe(struct i2c_client *client) if (full_power) pm_runtime_set_active(&client->dev); pm_runtime_enable(&client->dev); - pm_runtime_idle(&client->dev); ret = v4l2_async_register_subdev_sensor(&imx319->sd); if (ret < 0) goto error_media_entity_pm; + pm_runtime_idle(&client->dev); + return 0; error_media_entity_pm: pm_runtime_disable(&client->dev); - pm_runtime_set_suspended(&client->dev); + if (full_power) + pm_runtime_set_suspended(&client->dev); media_entity_cleanup(&imx319->sd.entity); error_handler_free: @@ -2474,7 +2476,8 @@ static void imx319_remove(struct i2c_client *client) v4l2_ctrl_handler_free(sd->ctrl_handler); pm_runtime_disable(&client->dev); - pm_runtime_set_suspended(&client->dev); + if (!pm_runtime_status_suspended(&client->dev)) + pm_runtime_set_suspended(&client->dev); mutex_destroy(&imx319->mutex); } From 8dd2d1561c6a42213ad2e118cef805ec81c544b1 Mon Sep 17 00:00:00 2001 From: Sakari Ailus Date: Fri, 10 Jan 2025 14:53:20 +0200 Subject: [PATCH 062/136] media: i2c: imx219: Rectify runtime PM handling in probe and remove commit 42eceae9793566d0df53d509be3e416465c347f5 upstream. Set the device's runtime PM status and enable runtime PM before registering the async sub-device. This is needed to avoid the case where the device is runtime PM resumed while runtime PM has not been enabled yet. Also set the device's runtime PM status to suspended in remove only if it wasn't so already. Fixes: 1283b3b8f82b ("media: i2c: Add driver for Sony IMX219 sensor") Cc: stable@vger.kernel.org # for >= v6.6 Reviewed-by: Bingbu Cao Signed-off-by: Sakari Ailus Signed-off-by: Hans Verkuil Signed-off-by: Greg Kroah-Hartman --- drivers/media/i2c/imx219.c | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/drivers/media/i2c/imx219.c b/drivers/media/i2c/imx219.c index d34fa3d9519a..906aa314b7f8 100644 --- a/drivers/media/i2c/imx219.c +++ b/drivers/media/i2c/imx219.c @@ -1231,6 +1231,9 @@ static int imx219_probe(struct i2c_client *client) goto error_media_entity; } + pm_runtime_set_active(dev); + pm_runtime_enable(dev); + ret = v4l2_async_register_subdev_sensor(&imx219->sd); if (ret < 0) { dev_err_probe(dev, ret, @@ -1238,15 +1241,14 @@ static int imx219_probe(struct i2c_client *client) goto error_subdev_cleanup; } - /* Enable runtime PM and turn off the device */ - pm_runtime_set_active(dev); - pm_runtime_enable(dev); pm_runtime_idle(dev); return 0; error_subdev_cleanup: v4l2_subdev_cleanup(&imx219->sd); + pm_runtime_disable(dev); + pm_runtime_set_suspended(dev); error_media_entity: media_entity_cleanup(&imx219->sd.entity); @@ -1271,9 +1273,10 @@ static void imx219_remove(struct i2c_client *client) imx219_free_controls(imx219); pm_runtime_disable(&client->dev); - if (!pm_runtime_status_suspended(&client->dev)) + if (!pm_runtime_status_suspended(&client->dev)) { imx219_power_off(&client->dev); - pm_runtime_set_suspended(&client->dev); + pm_runtime_set_suspended(&client->dev); + } } static const struct of_device_id imx219_dt_ids[] = { From 6f77a6d2ea31dd8a0a59ba4f7eb0cd1b2ca4599a Mon Sep 17 00:00:00 2001 From: Sakari Ailus Date: Fri, 10 Jan 2025 14:36:01 +0200 Subject: [PATCH 063/136] media: i2c: imx214: Rectify probe error handling related to runtime PM MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit commit ccc888d1698b6f42d52ddf5cecfe50fe925c95e5 upstream. There were multiple issues in the driver's probe function related to error handling: - Device's PM runtime status wasn't reverted to suspended on some errors in probe. - Runtime PM was left enabled for the device on some probe errors. - Device was left powered on if a probe failure happened or when it was removed when it was powered on. - An extra pm_runtime_set_suspended() was issued in driver's remove function when the device was suspended. Fix these bugs. Fixes: 436190596241 ("media: imx214: Add imx214 camera sensor driver") Cc: stable@vger.kernel.org # for >= v6.12 Signed-off-by: Sakari Ailus Acked-by: André Apitzsch Signed-off-by: Hans Verkuil Signed-off-by: Greg Kroah-Hartman --- drivers/media/i2c/imx214.c | 24 +++++++++++++++--------- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/drivers/media/i2c/imx214.c b/drivers/media/i2c/imx214.c index 10b6ad66d126..6a393e18267f 100644 --- a/drivers/media/i2c/imx214.c +++ b/drivers/media/i2c/imx214.c @@ -1075,10 +1075,6 @@ static int imx214_probe(struct i2c_client *client) */ imx214_power_on(imx214->dev); - pm_runtime_set_active(imx214->dev); - pm_runtime_enable(imx214->dev); - pm_runtime_idle(imx214->dev); - ret = imx214_ctrls_init(imx214); if (ret < 0) goto error_power_off; @@ -1099,21 +1095,30 @@ static int imx214_probe(struct i2c_client *client) imx214_entity_init_state(&imx214->sd, NULL); + pm_runtime_set_active(imx214->dev); + pm_runtime_enable(imx214->dev); + ret = v4l2_async_register_subdev_sensor(&imx214->sd); if (ret < 0) { dev_err(dev, "could not register v4l2 device\n"); goto free_entity; } + pm_runtime_idle(imx214->dev); + return 0; free_entity: + pm_runtime_disable(imx214->dev); + pm_runtime_set_suspended(&client->dev); media_entity_cleanup(&imx214->sd.entity); + free_ctrl: mutex_destroy(&imx214->mutex); v4l2_ctrl_handler_free(&imx214->ctrls); + error_power_off: - pm_runtime_disable(imx214->dev); + imx214_power_off(imx214->dev); return ret; } @@ -1126,11 +1131,12 @@ static void imx214_remove(struct i2c_client *client) v4l2_async_unregister_subdev(&imx214->sd); media_entity_cleanup(&imx214->sd.entity); v4l2_ctrl_handler_free(&imx214->ctrls); - - pm_runtime_disable(&client->dev); - pm_runtime_set_suspended(&client->dev); - mutex_destroy(&imx214->mutex); + pm_runtime_disable(&client->dev); + if (!pm_runtime_status_suspended(&client->dev)) { + imx214_power_off(imx214->dev); + pm_runtime_set_suspended(&client->dev); + } } static const struct of_device_id imx214_of_match[] = { From 7fafaf00cc5fd1fd7b828a1dc73bda79683b629b Mon Sep 17 00:00:00 2001 From: "Jackson.lee" Date: Tue, 17 Dec 2024 13:51:22 +0900 Subject: [PATCH 064/136] media: chips-media: wave5: Fix gray color on screen commit 6bae4d5053da634eecb611118e7cd91a677a4bbf upstream. When a decoder instance is created, the W5_CMD_ERR_CONCEAL register should be initialized to 0. Otherwise, gray color is occasionally displayed on the screen while decoding. Fixes: 45d1a2b93277 ("media: chips-media: wave5: Add vpuapi layer") Cc: stable@vger.kernel.org Signed-off-by: Jackson.lee Signed-off-by: Nas Chung Reviewed-by: Nicolas Dufresne Signed-off-by: Sebastian Fricke Signed-off-by: Hans Verkuil Signed-off-by: Greg Kroah-Hartman --- drivers/media/platform/chips-media/wave5/wave5-hw.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/media/platform/chips-media/wave5/wave5-hw.c b/drivers/media/platform/chips-media/wave5/wave5-hw.c index c89aafabc742..710311d85113 100644 --- a/drivers/media/platform/chips-media/wave5/wave5-hw.c +++ b/drivers/media/platform/chips-media/wave5/wave5-hw.c @@ -576,7 +576,7 @@ int wave5_vpu_build_up_dec_param(struct vpu_instance *inst, vpu_write_reg(inst->dev, W5_CMD_NUM_CQ_DEPTH_M1, WAVE521_COMMAND_QUEUE_DEPTH - 1); } - + vpu_write_reg(inst->dev, W5_CMD_ERR_CONCEAL, 0); ret = send_firmware_command(inst, W5_CREATE_INSTANCE, true, NULL, NULL); if (ret) { wave5_vdi_free_dma_memory(vpu_dev, &p_dec_info->vb_work); From 76cab9f540cce46e8cf9a3189a20a40870e5d36c Mon Sep 17 00:00:00 2001 From: "Jackson.lee" Date: Tue, 17 Dec 2024 13:51:23 +0900 Subject: [PATCH 065/136] media: chips-media: wave5: Avoid race condition in the interrupt handler commit ac35f768986610480a1c01323d9cf9f5eaf3ee9b upstream. In case of multiple active instances, new interrupts can occur as soon as the current interrupt is cleared. If the driver reads the instance_info after clearing the interrupt, then there is no guarantee, that the instance_info is still valid for the current interrupt. Read the instance_info register for each interrupt before clearing the interrupt. Fixes: ed7276ed2fd0 ("media: chips-media: wave5: Add hrtimer based polling support") Cc: stable@vger.kernel.org Signed-off-by: Jackson.lee Signed-off-by: Nas Chung Reviewed-by: Nicolas Dufresne Signed-off-by: Sebastian Fricke Signed-off-by: Hans Verkuil Signed-off-by: Greg Kroah-Hartman --- drivers/media/platform/chips-media/wave5/wave5-vpu.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/media/platform/chips-media/wave5/wave5-vpu.c b/drivers/media/platform/chips-media/wave5/wave5-vpu.c index 7273254ecb03..b13c5cd46d7e 100644 --- a/drivers/media/platform/chips-media/wave5/wave5-vpu.c +++ b/drivers/media/platform/chips-media/wave5/wave5-vpu.c @@ -54,12 +54,12 @@ static void wave5_vpu_handle_irq(void *dev_id) struct vpu_device *dev = dev_id; irq_reason = wave5_vdi_read_register(dev, W5_VPU_VINT_REASON); + seq_done = wave5_vdi_read_register(dev, W5_RET_SEQ_DONE_INSTANCE_INFO); + cmd_done = wave5_vdi_read_register(dev, W5_RET_QUEUE_CMD_DONE_INST); wave5_vdi_write_register(dev, W5_VPU_VINT_REASON_CLR, irq_reason); wave5_vdi_write_register(dev, W5_VPU_VINT_CLEAR, 0x1); list_for_each_entry(inst, &dev->instances, list) { - seq_done = wave5_vdi_read_register(dev, W5_RET_SEQ_DONE_INSTANCE_INFO); - cmd_done = wave5_vdi_read_register(dev, W5_RET_QUEUE_CMD_DONE_INST); if (irq_reason & BIT(INT_WAVE5_INIT_SEQ) || irq_reason & BIT(INT_WAVE5_ENC_SET_PARAM)) { From d595713de7f867d9fc6ad7bef9e9776f9977067b Mon Sep 17 00:00:00 2001 From: "Jackson.lee" Date: Tue, 17 Dec 2024 13:51:24 +0900 Subject: [PATCH 066/136] media: chips-media: wave5: Fix a hang after seeking commit a2c75e964e51b096e9fe6adfa3eaed53594a668b upstream. While seeking, the driver calls the flush command. Before the flush command is sent to the VPU, the driver should handle the display buffer flags and should get all decoded information from the VPU if the VCORE is running. Fixes: 9707a6254a8a ("media: chips-media: wave5: Add the v4l2 layer") Cc: stable@vger.kernel.org Signed-off-by: Jackson.lee Signed-off-by: Nas Chung Reviewed-by: Nicolas Dufresne Signed-off-by: Sebastian Fricke Signed-off-by: Hans Verkuil Signed-off-by: Greg Kroah-Hartman --- .../platform/chips-media/wave5/wave5-vpu-dec.c | 17 ++++++++++++++++- .../platform/chips-media/wave5/wave5-vpuapi.c | 10 ++++++++++ 2 files changed, 26 insertions(+), 1 deletion(-) diff --git a/drivers/media/platform/chips-media/wave5/wave5-vpu-dec.c b/drivers/media/platform/chips-media/wave5/wave5-vpu-dec.c index 0c5c9a8de91f..1ca14032f8b9 100644 --- a/drivers/media/platform/chips-media/wave5/wave5-vpu-dec.c +++ b/drivers/media/platform/chips-media/wave5/wave5-vpu-dec.c @@ -1446,6 +1446,16 @@ static int streamoff_output(struct vb2_queue *q) struct vb2_v4l2_buffer *buf; int ret; dma_addr_t new_rd_ptr; + struct dec_output_info dec_info; + unsigned int i; + + for (i = 0; i < v4l2_m2m_num_dst_bufs_ready(m2m_ctx); i++) { + ret = wave5_vpu_dec_set_disp_flag(inst, i); + if (ret) + dev_dbg(inst->dev->dev, + "%s: Setting display flag of buf index: %u, fail: %d\n", + __func__, i, ret); + } while ((buf = v4l2_m2m_src_buf_remove(m2m_ctx))) { dev_dbg(inst->dev->dev, "%s: (Multiplanar) buf type %4u | index %4u\n", @@ -1453,6 +1463,11 @@ static int streamoff_output(struct vb2_queue *q) v4l2_m2m_buf_done(buf, VB2_BUF_STATE_ERROR); } + while (wave5_vpu_dec_get_output_info(inst, &dec_info) == 0) { + if (dec_info.index_frame_display >= 0) + wave5_vpu_dec_set_disp_flag(inst, dec_info.index_frame_display); + } + ret = wave5_vpu_flush_instance(inst); if (ret) return ret; @@ -1535,7 +1550,7 @@ static void wave5_vpu_dec_stop_streaming(struct vb2_queue *q) break; if (wave5_vpu_dec_get_output_info(inst, &dec_output_info)) - dev_dbg(inst->dev->dev, "Getting decoding results from fw, fail\n"); + dev_dbg(inst->dev->dev, "there is no output info\n"); } v4l2_m2m_update_stop_streaming_state(m2m_ctx, q); diff --git a/drivers/media/platform/chips-media/wave5/wave5-vpuapi.c b/drivers/media/platform/chips-media/wave5/wave5-vpuapi.c index 1a3efb638dde..65fdabcd9d29 100644 --- a/drivers/media/platform/chips-media/wave5/wave5-vpuapi.c +++ b/drivers/media/platform/chips-media/wave5/wave5-vpuapi.c @@ -73,6 +73,16 @@ int wave5_vpu_flush_instance(struct vpu_instance *inst) inst->type == VPU_INST_TYPE_DEC ? "DECODER" : "ENCODER", inst->id); mutex_unlock(&inst->dev->hw_lock); return -ETIMEDOUT; + } else if (ret == -EBUSY) { + struct dec_output_info dec_info; + + mutex_unlock(&inst->dev->hw_lock); + wave5_vpu_dec_get_output_info(inst, &dec_info); + ret = mutex_lock_interruptible(&inst->dev->hw_lock); + if (ret) + return ret; + if (dec_info.index_frame_display > 0) + wave5_vpu_dec_set_disp_flag(inst, dec_info.index_frame_display); } } while (ret != 0); mutex_unlock(&inst->dev->hw_lock); From c59dc7c425cc17dd7b0ebde27fbff4ff7092598d Mon Sep 17 00:00:00 2001 From: "Jackson.lee" Date: Tue, 17 Dec 2024 13:51:25 +0900 Subject: [PATCH 067/136] media: chips-media: wave5: Fix timeout while testing 10bit hevc fluster commit 035371c9e5098018b8512efc6a8812912469480c upstream. The Wave5 521C variant does not support 10 bit decoding. When 10 bit decoding support was added for the 515 variant, a section of the code was removed which returned an error. This removal causes a timeout for the 521 variant, which was discovered during HEVC 10-bit decoding tests. Fixes: 143e7ab4d9a0 ("media: chips-media: wave5: support decoding HEVC Main10 profile") Cc: stable@vger.kernel.org Signed-off-by: Jackson.lee Signed-off-by: Nas Chung Reviewed-by: Nicolas Dufresne Signed-off-by: Sebastian Fricke Signed-off-by: Hans Verkuil Signed-off-by: Greg Kroah-Hartman --- .../platform/chips-media/wave5/wave5-vpu-dec.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/drivers/media/platform/chips-media/wave5/wave5-vpu-dec.c b/drivers/media/platform/chips-media/wave5/wave5-vpu-dec.c index 1ca14032f8b9..e238447c88bb 100644 --- a/drivers/media/platform/chips-media/wave5/wave5-vpu-dec.c +++ b/drivers/media/platform/chips-media/wave5/wave5-vpu-dec.c @@ -1424,10 +1424,24 @@ static int wave5_vpu_dec_start_streaming(struct vb2_queue *q, unsigned int count if (ret) goto free_bitstream_vbuf; } else if (q->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) { + struct dec_initial_info *initial_info = + &inst->codec_info->dec_info.initial_info; + if (inst->state == VPU_INST_STATE_STOP) ret = switch_state(inst, VPU_INST_STATE_INIT_SEQ); if (ret) goto return_buffers; + + if (inst->state == VPU_INST_STATE_INIT_SEQ && + inst->dev->product_code == WAVE521C_CODE) { + if (initial_info->luma_bitdepth != 8) { + dev_info(inst->dev->dev, "%s: no support for %d bit depth", + __func__, initial_info->luma_bitdepth); + ret = -EINVAL; + goto return_buffers; + } + } + } return ret; From 1b4ecd033e3066fa82b4ed33b66deffef2e9c7cb Mon Sep 17 00:00:00 2001 From: "Matthieu Baerts (NGI0)" Date: Fri, 14 Mar 2025 21:11:32 +0100 Subject: [PATCH 068/136] mptcp: sockopt: fix getting IPV6_V6ONLY commit 8c39633759885b6ff85f6d96cf445560e74df5e8 upstream. When adding a socket option support in MPTCP, both the get and set parts are supposed to be implemented. IPV6_V6ONLY support for the setsockopt part has been added a while ago, but it looks like the get part got forgotten. It should have been present as a way to verify a setting has been set as expected, and not to act differently from TCP or any other socket types. Not supporting this getsockopt(IPV6_V6ONLY) blocks some apps which want to check the default value, before doing extra actions. On Linux, the default value is 0, but this can be changed with the net.ipv6.bindv6only sysctl knob. On Windows, it is set to 1 by default. So supporting the get part, like for all other socket options, is important. Everything was in place to expose it, just the last step was missing. Only new code is added to cover this specific getsockopt(), that seems safe. Fixes: c9b95a135987 ("mptcp: support IPV6_V6ONLY setsockopt") Cc: stable@vger.kernel.org Closes: https://github.com/multipath-tcp/mptcp_net-next/issues/550 Reviewed-by: Mat Martineau Signed-off-by: Matthieu Baerts (NGI0) Reviewed-by: Simon Horman Link: https://patch.msgid.link/20250314-net-mptcp-fix-data-stream-corr-sockopt-v1-2-122dbb249db3@kernel.org Signed-off-by: Paolo Abeni Signed-off-by: Greg Kroah-Hartman --- net/mptcp/sockopt.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/net/mptcp/sockopt.c b/net/mptcp/sockopt.c index 505445a9598f..4b99eb796855 100644 --- a/net/mptcp/sockopt.c +++ b/net/mptcp/sockopt.c @@ -1430,6 +1430,20 @@ static int mptcp_getsockopt_v4(struct mptcp_sock *msk, int optname, return -EOPNOTSUPP; } +static int mptcp_getsockopt_v6(struct mptcp_sock *msk, int optname, + char __user *optval, int __user *optlen) +{ + struct sock *sk = (void *)msk; + + switch (optname) { + case IPV6_V6ONLY: + return mptcp_put_int_option(msk, optval, optlen, + sk->sk_ipv6only); + } + + return -EOPNOTSUPP; +} + static int mptcp_getsockopt_sol_mptcp(struct mptcp_sock *msk, int optname, char __user *optval, int __user *optlen) { @@ -1469,6 +1483,8 @@ int mptcp_getsockopt(struct sock *sk, int level, int optname, if (level == SOL_IP) return mptcp_getsockopt_v4(msk, optname, optval, option); + if (level == SOL_IPV6) + return mptcp_getsockopt_v6(msk, optname, optval, option); if (level == SOL_TCP) return mptcp_getsockopt_sol_tcp(msk, optname, optval, option); if (level == SOL_MPTCP) From 91e1405088a9e31b61acbd6774d98f23fbd2d95a Mon Sep 17 00:00:00 2001 From: "Matthieu Baerts (NGI0)" Date: Fri, 14 Mar 2025 21:11:33 +0100 Subject: [PATCH 069/136] mptcp: sockopt: fix getting freebind & transparent commit e2f4ac7bab2205d3c4dd9464e6ffd82502177c51 upstream. When adding a socket option support in MPTCP, both the get and set parts are supposed to be implemented. IP(V6)_FREEBIND and IP(V6)_TRANSPARENT support for the setsockopt part has been added a while ago, but it looks like the get part got forgotten. It should have been present as a way to verify a setting has been set as expected, and not to act differently from TCP or any other socket types. Everything was in place to expose it, just the last step was missing. Only new code is added to cover these specific getsockopt(), that seems safe. Fixes: c9406a23c116 ("mptcp: sockopt: add SOL_IP freebind & transparent options") Cc: stable@vger.kernel.org Reviewed-by: Mat Martineau Signed-off-by: Matthieu Baerts (NGI0) Reviewed-by: Simon Horman Link: https://patch.msgid.link/20250314-net-mptcp-fix-data-stream-corr-sockopt-v1-3-122dbb249db3@kernel.org Signed-off-by: Paolo Abeni Signed-off-by: Greg Kroah-Hartman --- net/mptcp/sockopt.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/net/mptcp/sockopt.c b/net/mptcp/sockopt.c index 4b99eb796855..3caa0a9d3b38 100644 --- a/net/mptcp/sockopt.c +++ b/net/mptcp/sockopt.c @@ -1419,6 +1419,12 @@ static int mptcp_getsockopt_v4(struct mptcp_sock *msk, int optname, switch (optname) { case IP_TOS: return mptcp_put_int_option(msk, optval, optlen, READ_ONCE(inet_sk(sk)->tos)); + case IP_FREEBIND: + return mptcp_put_int_option(msk, optval, optlen, + inet_test_bit(FREEBIND, sk)); + case IP_TRANSPARENT: + return mptcp_put_int_option(msk, optval, optlen, + inet_test_bit(TRANSPARENT, sk)); case IP_BIND_ADDRESS_NO_PORT: return mptcp_put_int_option(msk, optval, optlen, inet_test_bit(BIND_ADDRESS_NO_PORT, sk)); @@ -1439,6 +1445,12 @@ static int mptcp_getsockopt_v6(struct mptcp_sock *msk, int optname, case IPV6_V6ONLY: return mptcp_put_int_option(msk, optval, optlen, sk->sk_ipv6only); + case IPV6_TRANSPARENT: + return mptcp_put_int_option(msk, optval, optlen, + inet_test_bit(TRANSPARENT, sk)); + case IPV6_FREEBIND: + return mptcp_put_int_option(msk, optval, optlen, + inet_test_bit(FREEBIND, sk)); } return -EOPNOTSUPP; From 39fc12742292ed1ba38ac0f08ac324b1ad6ca297 Mon Sep 17 00:00:00 2001 From: Jiasheng Jiang Date: Wed, 5 Feb 2025 02:31:41 +0000 Subject: [PATCH 070/136] mtd: Add check for devm_kcalloc() commit 2aee30bb10d7bad0a60255059c9ce1b84cf0130e upstream. Add a check for devm_kcalloc() to ensure successful allocation. Fixes: 78c08247b9d3 ("mtd: Support kmsg dumper based on pstore/blk") Cc: stable@vger.kernel.org # v5.10+ Signed-off-by: Jiasheng Jiang Signed-off-by: Miquel Raynal Signed-off-by: Greg Kroah-Hartman --- drivers/mtd/mtdpstore.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/mtd/mtdpstore.c b/drivers/mtd/mtdpstore.c index 7ac8ac901306..b3e2ea4dd40e 100644 --- a/drivers/mtd/mtdpstore.c +++ b/drivers/mtd/mtdpstore.c @@ -423,6 +423,9 @@ static void mtdpstore_notify_add(struct mtd_info *mtd) longcnt = BITS_TO_LONGS(div_u64(mtd->size, mtd->erasesize)); cxt->badmap = kcalloc(longcnt, sizeof(long), GFP_KERNEL); + if (!cxt->rmmap || !cxt->usedmap || !cxt->badmap) + return; + /* just support dmesg right now */ cxt->dev.flags = PSTORE_FLAGS_DMESG; cxt->dev.zone.read = mtdpstore_read; From 020404265b871a74730bdebdeafa6c8ebecf2188 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marek=20Beh=C3=BAn?= Date: Mon, 17 Mar 2025 18:32:50 +0100 Subject: [PATCH 071/136] net: dsa: mv88e6xxx: workaround RGMII transmit delay erratum for 6320 family MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit commit 1ebc8e1ef906db9c08e9abe9776d85ddec837725 upstream. Implement the workaround for erratum 3.3 RGMII timing may be out of spec when transmit delay is enabled for the 6320 family, which says: When transmit delay is enabled via Port register 1 bit 14 = 1, duty cycle may be out of spec. Under very rare conditions this may cause the attached device receive CRC errors. Signed-off-by: Marek Behún Cc: # 5.4.x Reviewed-by: Andrew Lunn Link: https://patch.msgid.link/20250317173250.28780-8-kabel@kernel.org Signed-off-by: Jakub Kicinski Signed-off-by: Greg Kroah-Hartman --- drivers/net/dsa/mv88e6xxx/chip.c | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/drivers/net/dsa/mv88e6xxx/chip.c b/drivers/net/dsa/mv88e6xxx/chip.c index 5935100e7d65..28c9a38727c3 100644 --- a/drivers/net/dsa/mv88e6xxx/chip.c +++ b/drivers/net/dsa/mv88e6xxx/chip.c @@ -3691,6 +3691,21 @@ static int mv88e6xxx_stats_setup(struct mv88e6xxx_chip *chip) return mv88e6xxx_g1_stats_clear(chip); } +static int mv88e6320_setup_errata(struct mv88e6xxx_chip *chip) +{ + u16 dummy; + int err; + + /* Workaround for erratum + * 3.3 RGMII timing may be out of spec when transmit delay is enabled + */ + err = mv88e6xxx_port_hidden_write(chip, 0, 0xf, 0x7, 0xe000); + if (err) + return err; + + return mv88e6xxx_port_hidden_read(chip, 0, 0xf, 0x7, &dummy); +} + /* Check if the errata has already been applied. */ static bool mv88e6390_setup_errata_applied(struct mv88e6xxx_chip *chip) { @@ -5144,6 +5159,7 @@ static const struct mv88e6xxx_ops mv88e6290_ops = { static const struct mv88e6xxx_ops mv88e6320_ops = { /* MV88E6XXX_FAMILY_6320 */ + .setup_errata = mv88e6320_setup_errata, .ieee_pri_map = mv88e6085_g1_ieee_pri_map, .ip_pri_map = mv88e6085_g1_ip_pri_map, .irl_init_all = mv88e6352_g2_irl_init_all, @@ -5193,6 +5209,7 @@ static const struct mv88e6xxx_ops mv88e6320_ops = { static const struct mv88e6xxx_ops mv88e6321_ops = { /* MV88E6XXX_FAMILY_6320 */ + .setup_errata = mv88e6320_setup_errata, .ieee_pri_map = mv88e6085_g1_ieee_pri_map, .ip_pri_map = mv88e6085_g1_ip_pri_map, .irl_init_all = mv88e6352_g2_irl_init_all, From 2b27df6852444b76724f5d425826a38581d63407 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marek=20Beh=C3=BAn?= Date: Mon, 17 Mar 2025 18:32:49 +0100 Subject: [PATCH 072/136] net: dsa: mv88e6xxx: fix internal PHYs for 6320 family MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit commit 52fdc41c3278c981066a461d03d5477ebfcf270c upstream. Fix internal PHYs definition for the 6320 family, which has only 2 internal PHYs (on ports 3 and 4). Fixes: bc3931557d1d ("net: dsa: mv88e6xxx: Add number of internal PHYs") Signed-off-by: Marek Behún Cc: # 6.6.x Reviewed-by: Andrew Lunn Link: https://patch.msgid.link/20250317173250.28780-7-kabel@kernel.org Signed-off-by: Jakub Kicinski Signed-off-by: Greg Kroah-Hartman --- drivers/net/dsa/mv88e6xxx/chip.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/net/dsa/mv88e6xxx/chip.c b/drivers/net/dsa/mv88e6xxx/chip.c index 28c9a38727c3..e20d9d62032e 100644 --- a/drivers/net/dsa/mv88e6xxx/chip.c +++ b/drivers/net/dsa/mv88e6xxx/chip.c @@ -6171,7 +6171,8 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = { .num_databases = 4096, .num_macs = 8192, .num_ports = 7, - .num_internal_phys = 5, + .num_internal_phys = 2, + .internal_phys_offset = 3, .num_gpio = 15, .max_vid = 4095, .max_sid = 63, @@ -6365,7 +6366,8 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = { .num_databases = 4096, .num_macs = 8192, .num_ports = 7, - .num_internal_phys = 5, + .num_internal_phys = 2, + .internal_phys_offset = 3, .num_gpio = 15, .max_vid = 4095, .max_sid = 63, From 9d99358349e4600601dc2dae5f6fe349e744564c Mon Sep 17 00:00:00 2001 From: Jiasheng Jiang Date: Wed, 5 Feb 2025 02:31:40 +0000 Subject: [PATCH 073/136] mtd: Replace kcalloc() with devm_kcalloc() commit 1b61a59876f0eafc19b23007c522ee407f55dbec upstream. Replace kcalloc() with devm_kcalloc() to prevent memory leaks in case of errors. Fixes: 78c08247b9d3 ("mtd: Support kmsg dumper based on pstore/blk") Cc: stable@vger.kernel.org # v5.10+ Signed-off-by: Jiasheng Jiang Signed-off-by: Miquel Raynal Signed-off-by: Greg Kroah-Hartman --- drivers/mtd/mtdpstore.c | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/drivers/mtd/mtdpstore.c b/drivers/mtd/mtdpstore.c index b3e2ea4dd40e..9cf3872e37ae 100644 --- a/drivers/mtd/mtdpstore.c +++ b/drivers/mtd/mtdpstore.c @@ -417,11 +417,11 @@ static void mtdpstore_notify_add(struct mtd_info *mtd) } longcnt = BITS_TO_LONGS(div_u64(mtd->size, info->kmsg_size)); - cxt->rmmap = kcalloc(longcnt, sizeof(long), GFP_KERNEL); - cxt->usedmap = kcalloc(longcnt, sizeof(long), GFP_KERNEL); + cxt->rmmap = devm_kcalloc(&mtd->dev, longcnt, sizeof(long), GFP_KERNEL); + cxt->usedmap = devm_kcalloc(&mtd->dev, longcnt, sizeof(long), GFP_KERNEL); longcnt = BITS_TO_LONGS(div_u64(mtd->size, mtd->erasesize)); - cxt->badmap = kcalloc(longcnt, sizeof(long), GFP_KERNEL); + cxt->badmap = devm_kcalloc(&mtd->dev, longcnt, sizeof(long), GFP_KERNEL); if (!cxt->rmmap || !cxt->usedmap || !cxt->badmap) return; @@ -530,9 +530,6 @@ static void mtdpstore_notify_remove(struct mtd_info *mtd) mtdpstore_flush_removed(cxt); unregister_pstore_device(&cxt->dev); - kfree(cxt->badmap); - kfree(cxt->usedmap); - kfree(cxt->rmmap); cxt->mtd = NULL; cxt->index = -1; } From 9d6b789a8ff95d4fc4df389f4c57693b11c3f5c8 Mon Sep 17 00:00:00 2001 From: Alexandre Torgue Date: Thu, 6 Mar 2025 11:25:01 +0100 Subject: [PATCH 074/136] clocksource/drivers/stm32-lptimer: Use wakeup capable instead of init wakeup commit 96bf4b89a6ab22426ad83ef76e66c72a5a8daca0 upstream. "wakeup-source" property describes a device which has wakeup capability but should not force this device as a wakeup source. Fixes: 48b41c5e2de6 ("clocksource: Add Low Power STM32 timers driver") Cc: stable@vger.kernel.org Signed-off-by: Alexandre Torgue Signed-off-by: Fabrice Gasnier Rule: add Link: https://lore.kernel.org/stable/20250306083407.2374894-1-fabrice.gasnier%40foss.st.com Link: https://lore.kernel.org/r/20250306102501.2980153-1-fabrice.gasnier@foss.st.com Signed-off-by: Daniel Lezcano Signed-off-by: Greg Kroah-Hartman --- drivers/clocksource/timer-stm32-lp.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/clocksource/timer-stm32-lp.c b/drivers/clocksource/timer-stm32-lp.c index a4c95161cb22..193e4f643358 100644 --- a/drivers/clocksource/timer-stm32-lp.c +++ b/drivers/clocksource/timer-stm32-lp.c @@ -168,9 +168,7 @@ static int stm32_clkevent_lp_probe(struct platform_device *pdev) } if (of_property_read_bool(pdev->dev.parent->of_node, "wakeup-source")) { - ret = device_init_wakeup(&pdev->dev, true); - if (ret) - goto out_clk_disable; + device_set_wakeup_capable(&pdev->dev, true); ret = dev_pm_set_wake_irq(&pdev->dev, irq); if (ret) From ef44c9e81172fd3495ae0852047510b6dfdb4e40 Mon Sep 17 00:00:00 2001 From: Haoxiang Li Date: Wed, 19 Feb 2025 11:36:45 +0800 Subject: [PATCH 075/136] wifi: mt76: Add check for devm_kstrdup() commit 4bc1da524b502999da28d287de4286c986a1af57 upstream. Add check for the return value of devm_kstrdup() in mt76_get_of_data_from_mtd() to catch potential exception. Fixes: e7a6a044f9b9 ("mt76: testmode: move mtd part to mt76_dev") Cc: stable@vger.kernel.org Signed-off-by: Haoxiang Li Link: https://patch.msgid.link/20250219033645.2594753-1-haoxiang_li2024@163.com Signed-off-by: Felix Fietkau Signed-off-by: Greg Kroah-Hartman --- drivers/net/wireless/mediatek/mt76/eeprom.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/net/wireless/mediatek/mt76/eeprom.c b/drivers/net/wireless/mediatek/mt76/eeprom.c index 0bc66cc19acd..443517d06c9f 100644 --- a/drivers/net/wireless/mediatek/mt76/eeprom.c +++ b/drivers/net/wireless/mediatek/mt76/eeprom.c @@ -95,6 +95,10 @@ int mt76_get_of_data_from_mtd(struct mt76_dev *dev, void *eep, int offset, int l #ifdef CONFIG_NL80211_TESTMODE dev->test_mtd.name = devm_kstrdup(dev->dev, part, GFP_KERNEL); + if (!dev->test_mtd.name) { + ret = -ENOMEM; + goto out_put_node; + } dev->test_mtd.offset = offset; #endif From eb434adf79ddb0a6296fe82b04ae6f483dc28466 Mon Sep 17 00:00:00 2001 From: Gavrilov Ilia Date: Wed, 12 Feb 2025 08:21:25 +0000 Subject: [PATCH 076/136] wifi: mac80211: fix integer overflow in hwmp_route_info_get() commit d00c0c4105e5ab8a6a13ed23d701cceb285761fa upstream. Since the new_metric and last_hop_metric variables can reach the MAX_METRIC(0xffffffff) value, an integer overflow may occur when multiplying them by 10/9. It can lead to incorrect behavior. Found by InfoTeCS on behalf of Linux Verification Center (linuxtesting.org) with SVACE. Fixes: a8d418d9ac25 ("mac80211: mesh: only switch path when new metric is at least 10% better") Cc: stable@vger.kernel.org Signed-off-by: Ilia Gavrilov Link: https://patch.msgid.link/20250212082124.4078236-1-Ilia.Gavrilov@infotecs.ru Signed-off-by: Johannes Berg Signed-off-by: Greg Kroah-Hartman --- net/mac80211/mesh_hwmp.c | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/net/mac80211/mesh_hwmp.c b/net/mac80211/mesh_hwmp.c index 579d0f24ac9d..2922a9fec950 100644 --- a/net/mac80211/mesh_hwmp.c +++ b/net/mac80211/mesh_hwmp.c @@ -367,6 +367,12 @@ u32 airtime_link_metric_get(struct ieee80211_local *local, return (u32)result; } +/* Check that the first metric is at least 10% better than the second one */ +static bool is_metric_better(u32 x, u32 y) +{ + return (x < y) && (x < (y - x / 10)); +} + /** * hwmp_route_info_get - Update routing info to originator and transmitter * @@ -458,8 +464,8 @@ static u32 hwmp_route_info_get(struct ieee80211_sub_if_data *sdata, (mpath->sn == orig_sn && (rcu_access_pointer(mpath->next_hop) != sta ? - mult_frac(new_metric, 10, 9) : - new_metric) >= mpath->metric)) { + !is_metric_better(new_metric, mpath->metric) : + new_metric >= mpath->metric))) { process = false; fresh_info = false; } @@ -533,8 +539,8 @@ static u32 hwmp_route_info_get(struct ieee80211_sub_if_data *sdata, if ((mpath->flags & MESH_PATH_FIXED) || ((mpath->flags & MESH_PATH_ACTIVE) && ((rcu_access_pointer(mpath->next_hop) != sta ? - mult_frac(last_hop_metric, 10, 9) : - last_hop_metric) > mpath->metric))) + !is_metric_better(last_hop_metric, mpath->metric) : + last_hop_metric > mpath->metric)))) fresh_info = false; } else { mpath = mesh_path_add(sdata, ta); From 1706a07b38ae061ca42acfa004d0d49d1f1fe786 Mon Sep 17 00:00:00 2001 From: Ming Yen Hsieh Date: Thu, 16 Jan 2025 13:59:25 +0800 Subject: [PATCH 077/136] wifi: mt76: mt7925: ensure wow pattern command align fw format commit 8ae45b1f699bbc27ea8647093f794f671e77410b upstream. Align the format of "struct mt7925_wow_pattern_tlv" with firmware to ensure proper functionality. Cc: stable@vger.kernel.org Fixes: c948b5da6bbe ("wifi: mt76: mt7925: add Mediatek Wi-Fi7 driver for mt7925 chips") Signed-off-by: Ming Yen Hsieh Link: https://patch.msgid.link/20250116055925.3856856-1-mingyen.hsieh@mediatek.com Signed-off-by: Felix Fietkau Signed-off-by: Greg Kroah-Hartman --- drivers/net/wireless/mediatek/mt76/mt7925/mcu.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/mediatek/mt76/mt7925/mcu.h b/drivers/net/wireless/mediatek/mt76/mt7925/mcu.h index fe6a613ba008..887427e0760a 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7925/mcu.h +++ b/drivers/net/wireless/mediatek/mt76/mt7925/mcu.h @@ -566,8 +566,8 @@ struct mt7925_wow_pattern_tlv { u8 offset; u8 mask[MT76_CONNAC_WOW_MASK_MAX_LEN]; u8 pattern[MT76_CONNAC_WOW_PATTEN_MAX_LEN]; - u8 rsv[7]; -} __packed; + u8 rsv[4]; +}; struct roc_acquire_tlv { __le16 tag; From 0dd6c62c1370918eb5c38b00cb0ca1b64a9c9302 Mon Sep 17 00:00:00 2001 From: Ming Yen Hsieh Date: Thu, 16 Jan 2025 14:21:31 +0800 Subject: [PATCH 078/136] wifi: mt76: mt7925: fix country count limitation for CLC commit 6458d760a0c0afd2fda11e83ed3e1125a252432f upstream. Due to the increase in the number of power tables for 6Ghz on CLC, the variable nr_country is no longer sufficient to represent the total quantity. Therefore, we have switched to calculating the length of clc buf to obtain the correct power table. Cc: stable@vger.kernel.org Fixes: c948b5da6bbe ("wifi: mt76: mt7925: add Mediatek Wi-Fi7 driver for mt7925 chips") Signed-off-by: Ming Yen Hsieh Link: https://patch.msgid.link/20250116062131.3860198-1-mingyen.hsieh@mediatek.com Signed-off-by: Felix Fietkau Signed-off-by: Greg Kroah-Hartman --- drivers/net/wireless/mediatek/mt76/mt7925/mcu.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/mediatek/mt76/mt7925/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7925/mcu.c index c7eba60897d2..8476f9caa98d 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7925/mcu.c +++ b/drivers/net/wireless/mediatek/mt76/mt7925/mcu.c @@ -3119,13 +3119,14 @@ __mt7925_mcu_set_clc(struct mt792x_dev *dev, u8 *alpha2, .env = env_cap, }; int ret, valid_cnt = 0; - u8 i, *pos; + u8 *pos, *last_pos; if (!clc) return 0; pos = clc->data + sizeof(*seg) * clc->nr_seg; - for (i = 0; i < clc->nr_country; i++) { + last_pos = clc->data + le32_to_cpu(*(__le32 *)(clc->data + 4)); + while (pos < last_pos) { struct mt7925_clc_rule *rule = (struct mt7925_clc_rule *)pos; pos += sizeof(*rule); From 374f2bf7b3ffa9d176dd096c8a04cb33033542b6 Mon Sep 17 00:00:00 2001 From: Ming Yen Hsieh Date: Tue, 4 Mar 2025 16:08:47 -0800 Subject: [PATCH 079/136] wifi: mt76: mt7925: fix the wrong link_idx when a p2p_device is present commit 4bada9b0a29c185d45cc9512509edd6069fbfa79 upstream. When the p2p device and MLO station are running concurrently, the p2p device will occupy the wrong link_idx when the MLO secondary link is added. Fixes: 9e4c3a007f01 ("wifi: mt76: connac: Extend mt76_connac_mcu_uni_add_dev for MLO") Cc: stable@vger.kernel.org Co-developed-by: Sean Wang Signed-off-by: Sean Wang Tested-by: Caleb Jorden Signed-off-by: Ming Yen Hsieh Link: https://patch.msgid.link/20250305000851.493671-2-sean.wang@kernel.org Signed-off-by: Felix Fietkau Signed-off-by: Greg Kroah-Hartman --- drivers/net/wireless/mediatek/mt76/mt76.h | 1 + .../net/wireless/mediatek/mt76/mt76_connac_mcu.c | 4 ++-- drivers/net/wireless/mediatek/mt76/mt7925/main.c | 14 ++++++++++---- 3 files changed, 13 insertions(+), 6 deletions(-) diff --git a/drivers/net/wireless/mediatek/mt76/mt76.h b/drivers/net/wireless/mediatek/mt76/mt76.h index 0b75a45ad2e8..e2e9b5ece74e 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76.h +++ b/drivers/net/wireless/mediatek/mt76/mt76.h @@ -755,6 +755,7 @@ struct mt76_testmode_data { struct mt76_vif { u8 idx; + u8 link_idx; u8 omac_idx; u8 band_idx; u8 wmm_idx; diff --git a/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c b/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c index 7d07e720e4ec..452579ccc492 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c +++ b/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c @@ -1164,7 +1164,7 @@ int mt76_connac_mcu_uni_add_dev(struct mt76_phy *phy, .tag = cpu_to_le16(DEV_INFO_ACTIVE), .len = cpu_to_le16(sizeof(struct req_tlv)), .active = enable, - .link_idx = mvif->idx, + .link_idx = mvif->link_idx, }, }; struct { @@ -1187,7 +1187,7 @@ int mt76_connac_mcu_uni_add_dev(struct mt76_phy *phy, .bmc_tx_wlan_idx = cpu_to_le16(wcid->idx), .sta_idx = cpu_to_le16(wcid->idx), .conn_state = 1, - .link_idx = mvif->idx, + .link_idx = mvif->link_idx, }, }; int err, idx, cmd, len; diff --git a/drivers/net/wireless/mediatek/mt76/mt7925/main.c b/drivers/net/wireless/mediatek/mt76/mt7925/main.c index ddc67423efe2..bf0b149055ef 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7925/main.c +++ b/drivers/net/wireless/mediatek/mt76/mt7925/main.c @@ -356,10 +356,15 @@ static int mt7925_mac_link_bss_add(struct mt792x_dev *dev, struct mt76_txq *mtxq; int idx, ret = 0; - mconf->mt76.idx = __ffs64(~dev->mt76.vif_mask); - if (mconf->mt76.idx >= MT792x_MAX_INTERFACES) { - ret = -ENOSPC; - goto out; + if (vif->type == NL80211_IFTYPE_P2P_DEVICE) { + mconf->mt76.idx = MT792x_MAX_INTERFACES; + } else { + mconf->mt76.idx = __ffs64(~dev->mt76.vif_mask); + + if (mconf->mt76.idx >= MT792x_MAX_INTERFACES) { + ret = -ENOSPC; + goto out; + } } mconf->mt76.omac_idx = ieee80211_vif_is_mld(vif) ? @@ -367,6 +372,7 @@ static int mt7925_mac_link_bss_add(struct mt792x_dev *dev, mconf->mt76.band_idx = 0xff; mconf->mt76.wmm_idx = ieee80211_vif_is_mld(vif) ? 0 : mconf->mt76.idx % MT76_CONNAC_MAX_WMM_SETS; + mconf->mt76.link_idx = hweight16(mvif->valid_links); if (mvif->phy->mt76->chandef.chan->band != NL80211_BAND_2GHZ) mconf->mt76.basic_rates_idx = MT792x_BASIC_RATES_TBL + 4; From 00026f80c430077f7298262d14d783b33ec23342 Mon Sep 17 00:00:00 2001 From: Ming Yen Hsieh Date: Tue, 4 Mar 2025 16:08:48 -0800 Subject: [PATCH 080/136] wifi: mt76: mt7925: fix the wrong simultaneous cap for MLO commit 7dcea6fe33ee3d7cbb65baee0dd7adc76d1c9ddc upstream. The mt7925 chip is only support a single radio, so the maximum number of simultaneous should be 0. Fixes: 86c051f2c418 ("wifi: mt76: mt7925: enabling MLO when the firmware supports it") Cc: stable@vger.kernel.org Co-developed-by: Sean Wang Signed-off-by: Sean Wang Tested-by: Caleb Jorden Signed-off-by: Ming Yen Hsieh Link: https://patch.msgid.link/20250305000851.493671-3-sean.wang@kernel.org Signed-off-by: Felix Fietkau Signed-off-by: Greg Kroah-Hartman --- drivers/net/wireless/mediatek/mt76/mt7925/main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/mediatek/mt76/mt7925/main.c b/drivers/net/wireless/mediatek/mt76/mt7925/main.c index bf0b149055ef..d2a98c92e114 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7925/main.c +++ b/drivers/net/wireless/mediatek/mt76/mt7925/main.c @@ -256,7 +256,7 @@ int mt7925_init_mlo_caps(struct mt792x_phy *phy) ext_capab[0].eml_capabilities = phy->eml_cap; ext_capab[0].mld_capa_and_ops = - u16_encode_bits(1, IEEE80211_MLD_CAP_OP_MAX_SIMUL_LINKS); + u16_encode_bits(0, IEEE80211_MLD_CAP_OP_MAX_SIMUL_LINKS); wiphy->flags |= WIPHY_FLAG_SUPPORTS_MLO; wiphy->iftype_ext_capab = ext_capab; From 0828d6e9add67ce4f893c5fbb31ec6c23f34426c Mon Sep 17 00:00:00 2001 From: Pavel Begunkov Date: Sun, 23 Feb 2025 17:22:29 +0000 Subject: [PATCH 081/136] io_uring/net: fix accept multishot handling commit f6a89bf5278d6e15016a736db67043560d1b50d5 upstream. REQ_F_APOLL_MULTISHOT doesn't guarantee it's executed from the multishot context, so a multishot accept may get executed inline, fail io_req_post_cqe(), and ask the core code to kill the request with -ECANCELED by returning IOU_STOP_MULTISHOT even when a socket has been accepted and installed. Cc: stable@vger.kernel.org Fixes: 390ed29b5e425 ("io_uring: add IORING_ACCEPT_MULTISHOT for accept") Signed-off-by: Pavel Begunkov Link: https://lore.kernel.org/r/51c6deb01feaa78b08565ca8f24843c017f5bc80.1740331076.git.asml.silence@gmail.com Signed-off-by: Jens Axboe Signed-off-by: Greg Kroah-Hartman --- io_uring/net.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/io_uring/net.c b/io_uring/net.c index 7ea99e082e97..8ef96c4427fb 100644 --- a/io_uring/net.c +++ b/io_uring/net.c @@ -1616,6 +1616,8 @@ retry: } io_req_set_res(req, ret, cflags); + if (!(issue_flags & IO_URING_F_MULTISHOT)) + return IOU_OK; return IOU_STOP_MULTISHOT; } From b7c6d081c19a5e11bbd77bb97a62cff2b6b21cb5 Mon Sep 17 00:00:00 2001 From: Pavel Begunkov Date: Thu, 27 Mar 2025 09:57:27 +0000 Subject: [PATCH 082/136] io_uring/net: fix io_req_post_cqe abuse by send bundle commit 6889ae1b4df1579bcdffef023e2ea9a982565dff upstream. [ 114.987980][ T5313] WARNING: CPU: 6 PID: 5313 at io_uring/io_uring.c:872 io_req_post_cqe+0x12e/0x4f0 [ 114.991597][ T5313] RIP: 0010:io_req_post_cqe+0x12e/0x4f0 [ 115.001880][ T5313] Call Trace: [ 115.002222][ T5313] [ 115.007813][ T5313] io_send+0x4fe/0x10f0 [ 115.009317][ T5313] io_issue_sqe+0x1a6/0x1740 [ 115.012094][ T5313] io_wq_submit_work+0x38b/0xed0 [ 115.013223][ T5313] io_worker_handle_work+0x62a/0x1600 [ 115.013876][ T5313] io_wq_worker+0x34f/0xdf0 As the comment states, io_req_post_cqe() should only be used by multishot requests, i.e. REQ_F_APOLL_MULTISHOT, which bundled sends are not. Add a flag signifying whether a request wants to post multiple CQEs. Eventually REQ_F_APOLL_MULTISHOT should imply the new flag, but that's left out for simplicity. Cc: stable@vger.kernel.org Fixes: a05d1f625c7aa ("io_uring/net: support bundles for send") Signed-off-by: Pavel Begunkov Link: https://lore.kernel.org/r/8b611dbb54d1cd47a88681f5d38c84d0c02bc563.1743067183.git.asml.silence@gmail.com Signed-off-by: Jens Axboe Signed-off-by: Greg Kroah-Hartman --- include/linux/io_uring_types.h | 3 +++ io_uring/io_uring.c | 4 ++-- io_uring/net.c | 1 + 3 files changed, 6 insertions(+), 2 deletions(-) diff --git a/include/linux/io_uring_types.h b/include/linux/io_uring_types.h index 4b9ba523978d..5ce332fc6ff5 100644 --- a/include/linux/io_uring_types.h +++ b/include/linux/io_uring_types.h @@ -457,6 +457,7 @@ enum { REQ_F_SKIP_LINK_CQES_BIT, REQ_F_SINGLE_POLL_BIT, REQ_F_DOUBLE_POLL_BIT, + REQ_F_MULTISHOT_BIT, REQ_F_APOLL_MULTISHOT_BIT, REQ_F_CLEAR_POLLIN_BIT, REQ_F_HASH_LOCKED_BIT, @@ -530,6 +531,8 @@ enum { REQ_F_SINGLE_POLL = IO_REQ_FLAG(REQ_F_SINGLE_POLL_BIT), /* double poll may active */ REQ_F_DOUBLE_POLL = IO_REQ_FLAG(REQ_F_DOUBLE_POLL_BIT), + /* request posts multiple completions, should be set at prep time */ + REQ_F_MULTISHOT = IO_REQ_FLAG(REQ_F_MULTISHOT_BIT), /* fast poll multishot mode */ REQ_F_APOLL_MULTISHOT = IO_REQ_FLAG(REQ_F_APOLL_MULTISHOT_BIT), /* recvmsg special flag, clear EPOLLIN */ diff --git a/io_uring/io_uring.c b/io_uring/io_uring.c index cf28d29fffbf..19de7129ae0b 100644 --- a/io_uring/io_uring.c +++ b/io_uring/io_uring.c @@ -1821,7 +1821,7 @@ fail: * Don't allow any multishot execution from io-wq. It's more restrictive * than necessary and also cleaner. */ - if (req->flags & REQ_F_APOLL_MULTISHOT) { + if (req->flags & (REQ_F_MULTISHOT|REQ_F_APOLL_MULTISHOT)) { err = -EBADFD; if (!io_file_can_poll(req)) goto fail; @@ -1832,7 +1832,7 @@ fail: goto fail; return; } else { - req->flags &= ~REQ_F_APOLL_MULTISHOT; + req->flags &= ~(REQ_F_APOLL_MULTISHOT|REQ_F_MULTISHOT); } } diff --git a/io_uring/net.c b/io_uring/net.c index 8ef96c4427fb..384915d931b7 100644 --- a/io_uring/net.c +++ b/io_uring/net.c @@ -435,6 +435,7 @@ int io_sendmsg_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe) sr->msg_flags |= MSG_WAITALL; sr->buf_group = req->buf_index; req->buf_list = NULL; + req->flags |= REQ_F_MULTISHOT; } #ifdef CONFIG_COMPAT From 3e0356857ed5986d62203a567cd5e51513643176 Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Mon, 7 Apr 2025 07:51:23 -0600 Subject: [PATCH 083/136] io_uring/kbuf: reject zero sized provided buffers commit cf960726eb65e8d0bfecbcce6cf95f47b1ffa6cc upstream. This isn't fixing a real issue, but there's also zero point in going through group and buffer setup, when the buffers are going to be rejected once attempted to get used. Cc: stable@vger.kernel.org Reported-by: syzbot+58928048fd1416f1457c@syzkaller.appspotmail.com Signed-off-by: Jens Axboe Signed-off-by: Greg Kroah-Hartman --- io_uring/kbuf.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/io_uring/kbuf.c b/io_uring/kbuf.c index e1895952066e..7a8c3a004800 100644 --- a/io_uring/kbuf.c +++ b/io_uring/kbuf.c @@ -484,6 +484,8 @@ int io_provide_buffers_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe p->nbufs = tmp; p->addr = READ_ONCE(sqe->addr); p->len = READ_ONCE(sqe->len); + if (!p->len) + return -EINVAL; if (check_mul_overflow((unsigned long)p->len, (unsigned long)p->nbufs, &size)) From acadb2e2b3c5b9977a843a3a94fece9bdcf6aea1 Mon Sep 17 00:00:00 2001 From: Haoxiang Li Date: Wed, 26 Feb 2025 16:50:50 +0800 Subject: [PATCH 084/136] ASoC: codecs: wcd937x: fix a potential memory leak in wcd937x_soc_codec_probe() commit 3e330acf4efd63876d673c046cd073a1d4ed57a8 upstream. When snd_soc_dapm_new_controls() or snd_soc_dapm_add_routes() fails, wcd937x_soc_codec_probe() returns without releasing 'wcd937x->clsh_info', which is allocated by wcd_clsh_ctrl_alloc. Add wcd_clsh_ctrl_free() to prevent potential memory leak. Fixes: 313e978df7fc ("ASoC: codecs: wcd937x: add audio routing and Kconfig") Cc: stable@vger.kernel.org Signed-off-by: Haoxiang Li Link: https://patch.msgid.link/20250226085050.3584898-1-haoxiang_li2024@163.com Signed-off-by: Mark Brown Signed-off-by: Greg Kroah-Hartman --- sound/soc/codecs/wcd937x.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sound/soc/codecs/wcd937x.c b/sound/soc/codecs/wcd937x.c index 08fb13a334a4..9c1997a42334 100644 --- a/sound/soc/codecs/wcd937x.c +++ b/sound/soc/codecs/wcd937x.c @@ -2564,6 +2564,7 @@ static int wcd937x_soc_codec_probe(struct snd_soc_component *component) ARRAY_SIZE(wcd9375_dapm_widgets)); if (ret < 0) { dev_err(component->dev, "Failed to add snd_ctls\n"); + wcd_clsh_ctrl_free(wcd937x->clsh_info); return ret; } @@ -2571,6 +2572,7 @@ static int wcd937x_soc_codec_probe(struct snd_soc_component *component) ARRAY_SIZE(wcd9375_audio_map)); if (ret < 0) { dev_err(component->dev, "Failed to add routes\n"); + wcd_clsh_ctrl_free(wcd937x->clsh_info); return ret; } } From d383051f8293f564a5f82052e25048c18aced33e Mon Sep 17 00:00:00 2001 From: Srinivas Kandagatla Date: Fri, 14 Mar 2025 17:47:57 +0000 Subject: [PATCH 085/136] ASoC: q6apm: add q6apm_get_hw_pointer helper commit 0badb5432fd525a00db5630c459b635e9d47f445 upstream. Implement an helper function in q6apm to be able to read the current hardware pointer for both read and write buffers. This should help q6apm-dai to get the hardware pointer consistently without it doing manual calculation, which could go wrong in some race conditions. Fixes: 9b4fe0f1cd79 ("ASoC: qdsp6: audioreach: add q6apm-dai support") Cc: stable@vger.kernel.org Signed-off-by: Srinivas Kandagatla Tested-by: Krzysztof Kozlowski Tested-by: Johan Hovold Link: https://patch.msgid.link/20250314174800.10142-3-srinivas.kandagatla@linaro.org Signed-off-by: Mark Brown Signed-off-by: Greg Kroah-Hartman --- sound/soc/qcom/qdsp6/q6apm.c | 18 +++++++++++++++++- sound/soc/qcom/qdsp6/q6apm.h | 3 +++ 2 files changed, 20 insertions(+), 1 deletion(-) diff --git a/sound/soc/qcom/qdsp6/q6apm.c b/sound/soc/qcom/qdsp6/q6apm.c index 2a2a5bd98110..ca57413cb784 100644 --- a/sound/soc/qcom/qdsp6/q6apm.c +++ b/sound/soc/qcom/qdsp6/q6apm.c @@ -494,6 +494,19 @@ int q6apm_read(struct q6apm_graph *graph) } EXPORT_SYMBOL_GPL(q6apm_read); +int q6apm_get_hw_pointer(struct q6apm_graph *graph, int dir) +{ + struct audioreach_graph_data *data; + + if (dir == SNDRV_PCM_STREAM_PLAYBACK) + data = &graph->rx_data; + else + data = &graph->tx_data; + + return (int)atomic_read(&data->hw_ptr); +} +EXPORT_SYMBOL_GPL(q6apm_get_hw_pointer); + static int graph_callback(struct gpr_resp_pkt *data, void *priv, int op) { struct data_cmd_rsp_rd_sh_mem_ep_data_buffer_done_v2 *rd_done; @@ -520,7 +533,8 @@ static int graph_callback(struct gpr_resp_pkt *data, void *priv, int op) done = data->payload; phys = graph->rx_data.buf[token].phys; mutex_unlock(&graph->lock); - + /* token numbering starts at 0 */ + atomic_set(&graph->rx_data.hw_ptr, token + 1); if (lower_32_bits(phys) == done->buf_addr_lsw && upper_32_bits(phys) == done->buf_addr_msw) { graph->result.opcode = hdr->opcode; @@ -553,6 +567,8 @@ static int graph_callback(struct gpr_resp_pkt *data, void *priv, int op) rd_done = data->payload; phys = graph->tx_data.buf[hdr->token].phys; mutex_unlock(&graph->lock); + /* token numbering starts at 0 */ + atomic_set(&graph->tx_data.hw_ptr, hdr->token + 1); if (upper_32_bits(phys) == rd_done->buf_addr_msw && lower_32_bits(phys) == rd_done->buf_addr_lsw) { diff --git a/sound/soc/qcom/qdsp6/q6apm.h b/sound/soc/qcom/qdsp6/q6apm.h index c248c8d2b1ab..7ce08b401e31 100644 --- a/sound/soc/qcom/qdsp6/q6apm.h +++ b/sound/soc/qcom/qdsp6/q6apm.h @@ -2,6 +2,7 @@ #ifndef __Q6APM_H__ #define __Q6APM_H__ #include +#include #include #include #include @@ -77,6 +78,7 @@ struct audioreach_graph_data { uint32_t num_periods; uint32_t dsp_buf; uint32_t mem_map_handle; + atomic_t hw_ptr; }; struct audioreach_graph { @@ -150,4 +152,5 @@ int q6apm_enable_compress_module(struct device *dev, struct q6apm_graph *graph, int q6apm_remove_initial_silence(struct device *dev, struct q6apm_graph *graph, uint32_t samples); int q6apm_remove_trailing_silence(struct device *dev, struct q6apm_graph *graph, uint32_t samples); int q6apm_set_real_module_id(struct device *dev, struct q6apm_graph *graph, uint32_t codec_id); +int q6apm_get_hw_pointer(struct q6apm_graph *graph, int dir); #endif /* __APM_GRAPH_ */ From f5891f204d1381ba40cef9bf8f13f579e17250a2 Mon Sep 17 00:00:00 2001 From: Srinivas Kandagatla Date: Fri, 14 Mar 2025 17:47:56 +0000 Subject: [PATCH 086/136] ASoC: q6apm-dai: schedule all available frames to avoid dsp under-runs commit 3d4a4411aa8bbc3653ff22a1ff0432eb93d22ae0 upstream. With the existing code, we are only setting up one period at a time, in a ping-pong buffer style. This triggers lot of underruns in the dsp leading to jitter noise during audio playback. Fix this by scheduling all available periods, this will ensure that the dsp has enough buffer feed and ultimatley fixing the underruns and audio distortion. Fixes: 9b4fe0f1cd79 ("ASoC: qdsp6: audioreach: add q6apm-dai support") Cc: stable@vger.kernel.org Reported-by: Krzysztof Kozlowski Signed-off-by: Srinivas Kandagatla Tested-by: Krzysztof Kozlowski Tested-by: Johan Hovold Link: https://patch.msgid.link/20250314174800.10142-2-srinivas.kandagatla@linaro.org Signed-off-by: Mark Brown Signed-off-by: Greg Kroah-Hartman --- sound/soc/qcom/qdsp6/q6apm-dai.c | 28 +++++++++++++++++++++++----- 1 file changed, 23 insertions(+), 5 deletions(-) diff --git a/sound/soc/qcom/qdsp6/q6apm-dai.c b/sound/soc/qcom/qdsp6/q6apm-dai.c index c9404b5934c7..9d8e8e37c6de 100644 --- a/sound/soc/qcom/qdsp6/q6apm-dai.c +++ b/sound/soc/qcom/qdsp6/q6apm-dai.c @@ -70,6 +70,7 @@ struct q6apm_dai_rtd { unsigned int bytes_received; unsigned int copied_total; uint16_t bits_per_sample; + snd_pcm_uframes_t queue_ptr; bool next_track; enum stream_state state; struct q6apm_graph *graph; @@ -134,8 +135,6 @@ static void event_handler(uint32_t opcode, uint32_t token, void *payload, void * prtd->pos += prtd->pcm_count; spin_unlock_irqrestore(&prtd->lock, flags); snd_pcm_period_elapsed(substream); - if (prtd->state == Q6APM_STREAM_RUNNING) - q6apm_write_async(prtd->graph, prtd->pcm_count, 0, 0, 0); break; case APM_CLIENT_EVENT_DATA_READ_DONE: @@ -294,6 +293,27 @@ static int q6apm_dai_prepare(struct snd_soc_component *component, return 0; } +static int q6apm_dai_ack(struct snd_soc_component *component, struct snd_pcm_substream *substream) +{ + struct snd_pcm_runtime *runtime = substream->runtime; + struct q6apm_dai_rtd *prtd = runtime->private_data; + int i, ret = 0, avail_periods; + + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { + avail_periods = (runtime->control->appl_ptr - prtd->queue_ptr)/runtime->period_size; + for (i = 0; i < avail_periods; i++) { + ret = q6apm_write_async(prtd->graph, prtd->pcm_count, 0, 0, NO_TIMESTAMP); + if (ret < 0) { + dev_err(component->dev, "Error queuing playback buffer %d\n", ret); + return ret; + } + prtd->queue_ptr += runtime->period_size; + } + } + + return ret; +} + static int q6apm_dai_trigger(struct snd_soc_component *component, struct snd_pcm_substream *substream, int cmd) { @@ -305,9 +325,6 @@ static int q6apm_dai_trigger(struct snd_soc_component *component, case SNDRV_PCM_TRIGGER_START: case SNDRV_PCM_TRIGGER_RESUME: case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: - /* start writing buffers for playback only as we already queued capture buffers */ - if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) - ret = q6apm_write_async(prtd->graph, prtd->pcm_count, 0, 0, 0); break; case SNDRV_PCM_TRIGGER_STOP: /* TODO support be handled via SoftPause Module */ @@ -836,6 +853,7 @@ static const struct snd_soc_component_driver q6apm_fe_dai_component = { .hw_params = q6apm_dai_hw_params, .pointer = q6apm_dai_pointer, .trigger = q6apm_dai_trigger, + .ack = q6apm_dai_ack, .compress_ops = &q6apm_dai_compress_ops, .use_dai_pcm_id = true, }; From a28217b064f8619282a6d05e2bfc465c2f78b6e9 Mon Sep 17 00:00:00 2001 From: Srinivas Kandagatla Date: Fri, 14 Mar 2025 17:47:58 +0000 Subject: [PATCH 087/136] ASoC: q6apm-dai: make use of q6apm_get_hw_pointer commit a93dad6f4e6a04a5943f6ee5686585f24abf7063 upstream. With the existing code, the buffer position is only reset in pointer callback, which leaves the possiblity of it going over the size of buffer size and reporting incorrect position to userspace. Without this patch, its possible to see errors like: snd-x1e80100 sound: invalid position: pcmC0D0p:0, pos = 12288, buffer size = 12288, period size = 1536 snd-x1e80100 sound: invalid position: pcmC0D0p:0, pos = 12288, buffer size = 12288, period size = 1536 Fixes: 9b4fe0f1cd791 ("ASoC: qdsp6: audioreach: add q6apm-dai support") Cc: stable@vger.kernel.org Signed-off-by: Srinivas Kandagatla Tested-by: Krzysztof Kozlowski Tested-by: Johan Hovold Link: https://patch.msgid.link/20250314174800.10142-4-srinivas.kandagatla@linaro.org Signed-off-by: Mark Brown Signed-off-by: Greg Kroah-Hartman --- sound/soc/qcom/qdsp6/q6apm-dai.c | 23 ++++------------------- 1 file changed, 4 insertions(+), 19 deletions(-) diff --git a/sound/soc/qcom/qdsp6/q6apm-dai.c b/sound/soc/qcom/qdsp6/q6apm-dai.c index 9d8e8e37c6de..90cb24947f31 100644 --- a/sound/soc/qcom/qdsp6/q6apm-dai.c +++ b/sound/soc/qcom/qdsp6/q6apm-dai.c @@ -64,7 +64,6 @@ struct q6apm_dai_rtd { phys_addr_t phys; unsigned int pcm_size; unsigned int pcm_count; - unsigned int pos; /* Buffer position */ unsigned int periods; unsigned int bytes_sent; unsigned int bytes_received; @@ -124,23 +123,16 @@ static void event_handler(uint32_t opcode, uint32_t token, void *payload, void * { struct q6apm_dai_rtd *prtd = priv; struct snd_pcm_substream *substream = prtd->substream; - unsigned long flags; switch (opcode) { case APM_CLIENT_EVENT_CMD_EOS_DONE: prtd->state = Q6APM_STREAM_STOPPED; break; case APM_CLIENT_EVENT_DATA_WRITE_DONE: - spin_lock_irqsave(&prtd->lock, flags); - prtd->pos += prtd->pcm_count; - spin_unlock_irqrestore(&prtd->lock, flags); snd_pcm_period_elapsed(substream); break; case APM_CLIENT_EVENT_DATA_READ_DONE: - spin_lock_irqsave(&prtd->lock, flags); - prtd->pos += prtd->pcm_count; - spin_unlock_irqrestore(&prtd->lock, flags); snd_pcm_period_elapsed(substream); if (prtd->state == Q6APM_STREAM_RUNNING) q6apm_read(prtd->graph); @@ -247,7 +239,6 @@ static int q6apm_dai_prepare(struct snd_soc_component *component, } prtd->pcm_count = snd_pcm_lib_period_bytes(substream); - prtd->pos = 0; /* rate and channels are sent to audio driver */ ret = q6apm_graph_media_format_shmem(prtd->graph, &cfg); if (ret < 0) { @@ -445,16 +436,12 @@ static snd_pcm_uframes_t q6apm_dai_pointer(struct snd_soc_component *component, struct snd_pcm_runtime *runtime = substream->runtime; struct q6apm_dai_rtd *prtd = runtime->private_data; snd_pcm_uframes_t ptr; - unsigned long flags; - spin_lock_irqsave(&prtd->lock, flags); - if (prtd->pos == prtd->pcm_size) - prtd->pos = 0; + ptr = q6apm_get_hw_pointer(prtd->graph, substream->stream) * runtime->period_size; + if (ptr) + return ptr - 1; - ptr = bytes_to_frames(runtime, prtd->pos); - spin_unlock_irqrestore(&prtd->lock, flags); - - return ptr; + return 0; } static int q6apm_dai_hw_params(struct snd_soc_component *component, @@ -669,8 +656,6 @@ static int q6apm_dai_compr_set_params(struct snd_soc_component *component, prtd->pcm_size = runtime->fragments * runtime->fragment_size; prtd->bits_per_sample = 16; - prtd->pos = 0; - if (prtd->next_track != true) { memcpy(&prtd->codec, codec, sizeof(*codec)); From aa7e9eabe68ce69f213e8d234a53cdd76676664f Mon Sep 17 00:00:00 2001 From: Srinivas Kandagatla Date: Fri, 14 Mar 2025 17:47:59 +0000 Subject: [PATCH 088/136] ASoC: qdsp6: q6apm-dai: set 10 ms period and buffer alignment. commit 3107019501842c27334554ba9d6583b1f200f61f upstream. DSP expects the periods to be aligned to fragment sizes, currently setting up to hw constriants on periods bytes is not going to work correctly as we can endup with periods sizes aligned to 32 bytes however not aligned to fragment size. Update the constriants to use fragment size, and also set at step of 10ms for period size to accommodate DSP requirements of 10ms latency. Fixes: 9b4fe0f1cd79 ("ASoC: qdsp6: audioreach: add q6apm-dai support") Cc: stable@vger.kernel.org Signed-off-by: Srinivas Kandagatla Tested-by: Johan Hovold Link: https://patch.msgid.link/20250314174800.10142-5-srinivas.kandagatla@linaro.org Signed-off-by: Mark Brown Signed-off-by: Greg Kroah-Hartman --- sound/soc/qcom/qdsp6/q6apm-dai.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/sound/soc/qcom/qdsp6/q6apm-dai.c b/sound/soc/qcom/qdsp6/q6apm-dai.c index 90cb24947f31..180ff24041bf 100644 --- a/sound/soc/qcom/qdsp6/q6apm-dai.c +++ b/sound/soc/qcom/qdsp6/q6apm-dai.c @@ -385,13 +385,14 @@ static int q6apm_dai_open(struct snd_soc_component *component, } } - ret = snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_BYTES, 32); + /* setup 10ms latency to accommodate DSP restrictions */ + ret = snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_SIZE, 480); if (ret < 0) { dev_err(dev, "constraint for period bytes step ret = %d\n", ret); goto err; } - ret = snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_BUFFER_BYTES, 32); + ret = snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_BUFFER_SIZE, 480); if (ret < 0) { dev_err(dev, "constraint for buffer bytes step ret = %d\n", ret); goto err; From 17f1e421311360cb8fd363c1236a142b8a99f72c Mon Sep 17 00:00:00 2001 From: Srinivas Kandagatla Date: Fri, 14 Mar 2025 17:48:00 +0000 Subject: [PATCH 089/136] ASoC: qdsp6: q6apm-dai: fix capture pipeline overruns. commit 5d01ed9b9939b4c726be74db291a982bc984c584 upstream. Period sizes less than 6k for capture path triggers overruns in the dsp capture pipeline. Change the period size and number of periods to value which DSP is happy with. Fixes: 9b4fe0f1cd79 ("ASoC: qdsp6: audioreach: add q6apm-dai support") Cc: stable@vger.kernel.org Signed-off-by: Srinivas Kandagatla Tested-by: Krzysztof Kozlowski Tested-by: Johan Hovold Link: https://patch.msgid.link/20250314174800.10142-6-srinivas.kandagatla@linaro.org Signed-off-by: Mark Brown Signed-off-by: Greg Kroah-Hartman --- sound/soc/qcom/qdsp6/q6apm-dai.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sound/soc/qcom/qdsp6/q6apm-dai.c b/sound/soc/qcom/qdsp6/q6apm-dai.c index 180ff24041bf..2cd522108221 100644 --- a/sound/soc/qcom/qdsp6/q6apm-dai.c +++ b/sound/soc/qcom/qdsp6/q6apm-dai.c @@ -24,8 +24,8 @@ #define PLAYBACK_MIN_PERIOD_SIZE 128 #define CAPTURE_MIN_NUM_PERIODS 2 #define CAPTURE_MAX_NUM_PERIODS 8 -#define CAPTURE_MAX_PERIOD_SIZE 4096 -#define CAPTURE_MIN_PERIOD_SIZE 320 +#define CAPTURE_MAX_PERIOD_SIZE 65536 +#define CAPTURE_MIN_PERIOD_SIZE 6144 #define BUFFER_BYTES_MAX (PLAYBACK_MAX_NUM_PERIODS * PLAYBACK_MAX_PERIOD_SIZE) #define BUFFER_BYTES_MIN (PLAYBACK_MIN_NUM_PERIODS * PLAYBACK_MIN_PERIOD_SIZE) #define COMPR_PLAYBACK_MAX_FRAGMENT_SIZE (128 * 1024) From d2a2076d9cb7492a8435b5c7f589c796b144361b Mon Sep 17 00:00:00 2001 From: Alexey Klimov Date: Thu, 27 Mar 2025 15:46:50 +0000 Subject: [PATCH 090/136] ASoC: qdsp6: q6asm-dai: fix q6asm_dai_compr_set_params error path commit 7eccc86e90f04a0d758d16c08627a620ac59604d upstream. In case of attempts to compress playback something, for instance, when audio routing is not set up correctly, the audio DSP is left in inconsistent state because we are not doing the correct things in the error path of q6asm_dai_compr_set_params(). So, when routing is not set up and compress playback is attempted the following errors are present (simplified log): q6routing routing: Routing not setup for MultiMedia-1 Session q6asm-dai dais: Stream reg failed ret:-22 q6asm-dai dais: ASoC error (-22): at snd_soc_component_compr_set_params() on 17300000.remoteproc:glink-edge:apr:service@7:dais After setting the correct routing the compress playback will always fail: q6asm-dai dais: cmd = 0x10db3 returned error = 0x9 q6asm-dai dais: DSP returned error[9] q6asm-dai dais: q6asm_open_write failed q6asm-dai dais: ASoC error (-22): at snd_soc_component_compr_set_params() on 17300000.remoteproc:glink-edge:apr:service@7:dais 0x9 here means "Operation is already processed". The CMD_OPEN here was sent the second time hence DSP responds that it was already done. Turns out the CMD_CLOSE should be sent after the q6asm_open_write() succeeded but something failed after that, for instance, routing setup. Fix this by slightly reworking the error path in q6asm_dai_compr_set_params(). Tested on QRB5165 RB5 and SDM845 RB3 boards. Cc: stable@vger.kernel.org Fixes: 5b39363e54cc ("ASoC: q6asm-dai: prepare set params to accept profile change") Cc: Srinivas Kandagatla Cc: Vinod Koul Cc: Pierre-Louis Bossart Signed-off-by: Alexey Klimov Reviewed-by: Srinivas Kandagatla Link: https://patch.msgid.link/20250327154650.337404-1-alexey.klimov@linaro.org Signed-off-by: Mark Brown Signed-off-by: Greg Kroah-Hartman --- sound/soc/qcom/qdsp6/q6asm-dai.c | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/sound/soc/qcom/qdsp6/q6asm-dai.c b/sound/soc/qcom/qdsp6/q6asm-dai.c index 045100c94352..a400c9a31fea 100644 --- a/sound/soc/qcom/qdsp6/q6asm-dai.c +++ b/sound/soc/qcom/qdsp6/q6asm-dai.c @@ -892,9 +892,7 @@ static int q6asm_dai_compr_set_params(struct snd_soc_component *component, if (ret < 0) { dev_err(dev, "q6asm_open_write failed\n"); - q6asm_audio_client_free(prtd->audio_client); - prtd->audio_client = NULL; - return ret; + goto open_err; } } @@ -903,7 +901,7 @@ static int q6asm_dai_compr_set_params(struct snd_soc_component *component, prtd->session_id, dir); if (ret) { dev_err(dev, "Stream reg failed ret:%d\n", ret); - return ret; + goto q6_err; } ret = __q6asm_dai_compr_set_codec_params(component, stream, @@ -911,7 +909,7 @@ static int q6asm_dai_compr_set_params(struct snd_soc_component *component, prtd->stream_id); if (ret) { dev_err(dev, "codec param setup failed ret:%d\n", ret); - return ret; + goto q6_err; } ret = q6asm_map_memory_regions(dir, prtd->audio_client, prtd->phys, @@ -920,12 +918,21 @@ static int q6asm_dai_compr_set_params(struct snd_soc_component *component, if (ret < 0) { dev_err(dev, "Buffer Mapping failed ret:%d\n", ret); - return -ENOMEM; + ret = -ENOMEM; + goto q6_err; } prtd->state = Q6ASM_STREAM_RUNNING; return 0; + +q6_err: + q6asm_cmd(prtd->audio_client, prtd->stream_id, CMD_CLOSE); + +open_err: + q6asm_audio_client_free(prtd->audio_client); + prtd->audio_client = NULL; + return ret; } static int q6asm_dai_compr_set_metadata(struct snd_soc_component *component, From 7022946773d7bd5e834ab4398b5797ce261c5a2b Mon Sep 17 00:00:00 2001 From: Sharan Kumar M Date: Sat, 29 Mar 2025 21:11:06 +0530 Subject: [PATCH 091/136] ALSA: hda/realtek: Enable Mute LED on HP OMEN 16 Laptop xd000xx commit e5182305a5199246dbcb4053299dcb1c8867b6ff upstream. This patch adds the HP OMEN 16 Laptop xd000xx to enable mute led. it uses ALC245_FIXUP_HP_MUTE_LED_COEFBIT with a slight modification setting mute_led_coef.off to 0(it was set to 4 i guess in that function) which i referred to your previous patch disscusion https://bugzilla.kernel.org/show_bug.cgi?id=214735 . i am not sure whether i can modify the current working function so i added another version calling ALC245_FIXUP_HP_MUTE_LED_V1_COEFBIT. and both works for me. Tested on 6.13.4-arch1-1 to 6.14.0-arch1-1 Signed-off-by: Sharan Kumar M Cc: Link: https://patch.msgid.link/20250329154105.7618-2-sharweshraajan@gmail.com Signed-off-by: Takashi Iwai Signed-off-by: Greg Kroah-Hartman --- sound/pci/hda/patch_realtek.c | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index 59e59fdc38f2..0bf833c96021 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -4744,6 +4744,22 @@ static void alc245_fixup_hp_mute_led_coefbit(struct hda_codec *codec, } } +static void alc245_fixup_hp_mute_led_v1_coefbit(struct hda_codec *codec, + const struct hda_fixup *fix, + int action) +{ + struct alc_spec *spec = codec->spec; + + if (action == HDA_FIXUP_ACT_PRE_PROBE) { + spec->mute_led_polarity = 0; + spec->mute_led_coef.idx = 0x0b; + spec->mute_led_coef.mask = 1 << 3; + spec->mute_led_coef.on = 1 << 3; + spec->mute_led_coef.off = 0; + snd_hda_gen_add_mute_led_cdev(codec, coef_mute_led_set); + } +} + /* turn on/off mic-mute LED per capture hook by coef bit */ static int coef_micmute_led_set(struct led_classdev *led_cdev, enum led_brightness brightness) @@ -7851,6 +7867,7 @@ enum { ALC287_FIXUP_TAS2781_I2C, ALC287_FIXUP_YOGA7_14ARB7_I2C, ALC245_FIXUP_HP_MUTE_LED_COEFBIT, + ALC245_FIXUP_HP_MUTE_LED_V1_COEFBIT, ALC245_FIXUP_HP_X360_MUTE_LEDS, ALC287_FIXUP_THINKPAD_I2S_SPK, ALC287_FIXUP_MG_RTKC_CSAMP_CS35L41_I2C_THINKPAD, @@ -10084,6 +10101,10 @@ static const struct hda_fixup alc269_fixups[] = { .type = HDA_FIXUP_FUNC, .v.func = alc245_fixup_hp_mute_led_coefbit, }, + [ALC245_FIXUP_HP_MUTE_LED_V1_COEFBIT] = { + .type = HDA_FIXUP_FUNC, + .v.func = alc245_fixup_hp_mute_led_v1_coefbit, + }, [ALC245_FIXUP_HP_X360_MUTE_LEDS] = { .type = HDA_FIXUP_FUNC, .v.func = alc245_fixup_hp_mute_led_coefbit, @@ -10569,6 +10590,7 @@ static const struct hda_quirk alc269_fixup_tbl[] = { SND_PCI_QUIRK(0x103c, 0x8b97, "HP", ALC236_FIXUP_HP_MUTE_LED_MICMUTE_VREF), SND_PCI_QUIRK(0x103c, 0x8bb3, "HP Slim OMEN", ALC287_FIXUP_CS35L41_I2C_2), SND_PCI_QUIRK(0x103c, 0x8bb4, "HP Slim OMEN", ALC287_FIXUP_CS35L41_I2C_2), + SND_PCI_QUIRK(0x103c, 0x8bcd, "HP Omen 16-xd0xxx", ALC245_FIXUP_HP_MUTE_LED_V1_COEFBIT), SND_PCI_QUIRK(0x103c, 0x8bdd, "HP Envy 17", ALC287_FIXUP_CS35L41_I2C_2), SND_PCI_QUIRK(0x103c, 0x8bde, "HP Envy 17", ALC287_FIXUP_CS35L41_I2C_2), SND_PCI_QUIRK(0x103c, 0x8bdf, "HP Envy 15", ALC287_FIXUP_CS35L41_I2C_2), From 5c200b7ebdf932d0f61c68815b8867792c01663c Mon Sep 17 00:00:00 2001 From: Jacek Lawrynowicz Date: Tue, 25 Mar 2025 12:42:19 +0100 Subject: [PATCH 092/136] accel/ivpu: Fix warning in ivpu_ipc_send_receive_internal() commit 6b4568b675b14cf890c0c21779773c3e08e80ce5 upstream. Warn if device is suspended only when runtime PM is enabled. Runtime PM is disabled during reset/recovery and it is not an error to use ivpu_ipc_send_receive_internal() in such cases. Fixes: 5eaa49741119 ("accel/ivpu: Prevent recovery invocation during probe and resume") Cc: stable@vger.kernel.org # v6.13+ Signed-off-by: Maciej Falkowski Reviewed-by: Lizhi Hou Signed-off-by: Jacek Lawrynowicz Link: https://lore.kernel.org/r/20250325114219.3739951-1-maciej.falkowski@linux.intel.com Signed-off-by: Greg Kroah-Hartman --- drivers/accel/ivpu/ivpu_ipc.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/accel/ivpu/ivpu_ipc.c b/drivers/accel/ivpu/ivpu_ipc.c index 13c8a12162e8..f0402dc84758 100644 --- a/drivers/accel/ivpu/ivpu_ipc.c +++ b/drivers/accel/ivpu/ivpu_ipc.c @@ -299,7 +299,8 @@ ivpu_ipc_send_receive_internal(struct ivpu_device *vdev, struct vpu_jsm_msg *req struct ivpu_ipc_consumer cons; int ret; - drm_WARN_ON(&vdev->drm, pm_runtime_status_suspended(vdev->drm.dev)); + drm_WARN_ON(&vdev->drm, pm_runtime_status_suspended(vdev->drm.dev) && + pm_runtime_enabled(vdev->drm.dev)); ivpu_ipc_consumer_add(vdev, &cons, channel, NULL); From 7d12a7d43c7bab9097ba466581d8db702e7908dc Mon Sep 17 00:00:00 2001 From: Jacek Lawrynowicz Date: Tue, 25 Mar 2025 12:43:05 +0100 Subject: [PATCH 093/136] accel/ivpu: Fix deadlock in ivpu_ms_cleanup() commit 9a6f56762d23a1f3af15e67901493c927caaf882 upstream. Fix deadlock in ivpu_ms_cleanup() by preventing runtime resume after file_priv->ms_lock is acquired. During a failure in runtime resume, a cold boot is executed, which calls ivpu_ms_cleanup_all(). This function calls ivpu_ms_cleanup() that acquires file_priv->ms_lock and causes the deadlock. Fixes: cdfad4db7756 ("accel/ivpu: Add NPU profiling support") Cc: stable@vger.kernel.org # v6.11+ Signed-off-by: Maciej Falkowski Reviewed-by: Lizhi Hou Signed-off-by: Jacek Lawrynowicz Link: https://lore.kernel.org/r/20250325114306.3740022-2-maciej.falkowski@linux.intel.com Signed-off-by: Greg Kroah-Hartman --- drivers/accel/ivpu/ivpu_ms.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/drivers/accel/ivpu/ivpu_ms.c b/drivers/accel/ivpu/ivpu_ms.c index dfb75c8b52ce..a961002fe25b 100644 --- a/drivers/accel/ivpu/ivpu_ms.c +++ b/drivers/accel/ivpu/ivpu_ms.c @@ -4,6 +4,7 @@ */ #include +#include #include "ivpu_drv.h" #include "ivpu_gem.h" @@ -299,6 +300,9 @@ unlock: void ivpu_ms_cleanup(struct ivpu_file_priv *file_priv) { struct ivpu_ms_instance *ms, *tmp; + struct ivpu_device *vdev = file_priv->vdev; + + pm_runtime_get_sync(vdev->drm.dev); mutex_lock(&file_priv->ms_lock); @@ -311,6 +315,8 @@ void ivpu_ms_cleanup(struct ivpu_file_priv *file_priv) free_instance(file_priv, ms); mutex_unlock(&file_priv->ms_lock); + + pm_runtime_put_autosuspend(vdev->drm.dev); } void ivpu_ms_cleanup_all(struct ivpu_device *vdev) From a77955f7704b2a00385e232cbcc1cb06b5c7a425 Mon Sep 17 00:00:00 2001 From: Jeff Hugo Date: Thu, 6 Mar 2025 10:29:13 -0700 Subject: [PATCH 094/136] bus: mhi: host: Fix race between unprepare and queue_buf commit 0686a818d77a431fc3ba2fab4b46bbb04e8c9380 upstream. A client driver may use mhi_unprepare_from_transfer() to quiesce incoming data during the client driver's tear down. The client driver might also be processing data at the same time, resulting in a call to mhi_queue_buf() which will invoke mhi_gen_tre(). If mhi_gen_tre() runs after mhi_unprepare_from_transfer() has torn down the channel, a panic will occur due to an invalid dereference leading to a page fault. This occurs because mhi_gen_tre() does not verify the channel state after locking it. Fix this by having mhi_gen_tre() confirm the channel state is valid, or return error to avoid accessing deinitialized data. Cc: stable@vger.kernel.org # 6.8 Fixes: b89b6a863dd5 ("bus: mhi: host: Add spinlock to protect WP access when queueing TREs") Signed-off-by: Jeffrey Hugo Signed-off-by: Jeff Hugo Reviewed-by: Krishna Chaitanya Chundru Reviewed-by: Youssef Samir Reviewed-by: Manivannan Sadhasivam Reviewed-by: Troy Hanson Link: https://lore.kernel.org/r/20250306172913.856982-1-jeff.hugo@oss.qualcomm.com [mani: added stable tag] Signed-off-by: Manivannan Sadhasivam Signed-off-by: Greg Kroah-Hartman --- drivers/bus/mhi/host/main.c | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/drivers/bus/mhi/host/main.c b/drivers/bus/mhi/host/main.c index 4de75674f193..aa8a0ef697c7 100644 --- a/drivers/bus/mhi/host/main.c +++ b/drivers/bus/mhi/host/main.c @@ -1207,11 +1207,16 @@ int mhi_gen_tre(struct mhi_controller *mhi_cntrl, struct mhi_chan *mhi_chan, struct mhi_ring_element *mhi_tre; struct mhi_buf_info *buf_info; int eot, eob, chain, bei; - int ret; + int ret = 0; /* Protect accesses for reading and incrementing WP */ write_lock_bh(&mhi_chan->lock); + if (mhi_chan->ch_state != MHI_CH_STATE_ENABLED) { + ret = -ENODEV; + goto out; + } + buf_ring = &mhi_chan->buf_ring; tre_ring = &mhi_chan->tre_ring; @@ -1229,10 +1234,8 @@ int mhi_gen_tre(struct mhi_controller *mhi_cntrl, struct mhi_chan *mhi_chan, if (!info->pre_mapped) { ret = mhi_cntrl->map_single(mhi_cntrl, buf_info); - if (ret) { - write_unlock_bh(&mhi_chan->lock); - return ret; - } + if (ret) + goto out; } eob = !!(flags & MHI_EOB); @@ -1250,9 +1253,10 @@ int mhi_gen_tre(struct mhi_controller *mhi_cntrl, struct mhi_chan *mhi_chan, mhi_add_ring_element(mhi_cntrl, tre_ring); mhi_add_ring_element(mhi_cntrl, buf_ring); +out: write_unlock_bh(&mhi_chan->lock); - return 0; + return ret; } int mhi_queue_buf(struct mhi_device *mhi_dev, enum dma_data_direction dir, From 16d9067f00e3a7d1df7c3aa9c20d214923d27e10 Mon Sep 17 00:00:00 2001 From: Artem Sadovnikov Date: Fri, 4 Apr 2025 08:28:05 +0000 Subject: [PATCH 095/136] ext4: fix off-by-one error in do_split commit 94824ac9a8aaf2fb3c54b4bdde842db80ffa555d upstream. Syzkaller detected a use-after-free issue in ext4_insert_dentry that was caused by out-of-bounds access due to incorrect splitting in do_split. BUG: KASAN: use-after-free in ext4_insert_dentry+0x36a/0x6d0 fs/ext4/namei.c:2109 Write of size 251 at addr ffff888074572f14 by task syz-executor335/5847 CPU: 0 UID: 0 PID: 5847 Comm: syz-executor335 Not tainted 6.12.0-rc6-syzkaller-00318-ga9cda7c0ffed #0 Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 10/30/2024 Call Trace: __dump_stack lib/dump_stack.c:94 [inline] dump_stack_lvl+0x241/0x360 lib/dump_stack.c:120 print_address_description mm/kasan/report.c:377 [inline] print_report+0x169/0x550 mm/kasan/report.c:488 kasan_report+0x143/0x180 mm/kasan/report.c:601 kasan_check_range+0x282/0x290 mm/kasan/generic.c:189 __asan_memcpy+0x40/0x70 mm/kasan/shadow.c:106 ext4_insert_dentry+0x36a/0x6d0 fs/ext4/namei.c:2109 add_dirent_to_buf+0x3d9/0x750 fs/ext4/namei.c:2154 make_indexed_dir+0xf98/0x1600 fs/ext4/namei.c:2351 ext4_add_entry+0x222a/0x25d0 fs/ext4/namei.c:2455 ext4_add_nondir+0x8d/0x290 fs/ext4/namei.c:2796 ext4_symlink+0x920/0xb50 fs/ext4/namei.c:3431 vfs_symlink+0x137/0x2e0 fs/namei.c:4615 do_symlinkat+0x222/0x3a0 fs/namei.c:4641 __do_sys_symlink fs/namei.c:4662 [inline] __se_sys_symlink fs/namei.c:4660 [inline] __x64_sys_symlink+0x7a/0x90 fs/namei.c:4660 do_syscall_x64 arch/x86/entry/common.c:52 [inline] do_syscall_64+0xf3/0x230 arch/x86/entry/common.c:83 entry_SYSCALL_64_after_hwframe+0x77/0x7f The following loop is located right above 'if' statement. for (i = count-1; i >= 0; i--) { /* is more than half of this entry in 2nd half of the block? */ if (size + map[i].size/2 > blocksize/2) break; size += map[i].size; move++; } 'i' in this case could go down to -1, in which case sum of active entries wouldn't exceed half the block size, but previous behaviour would also do split in half if sum would exceed at the very last block, which in case of having too many long name files in a single block could lead to out-of-bounds access and following use-after-free. Found by Linux Verification Center (linuxtesting.org) with Syzkaller. Cc: stable@vger.kernel.org Fixes: 5872331b3d91 ("ext4: fix potential negative array index in do_split()") Signed-off-by: Artem Sadovnikov Reviewed-by: Jan Kara Link: https://patch.msgid.link/20250404082804.2567-3-a.sadovnikov@ispras.ru Signed-off-by: Theodore Ts'o Signed-off-by: Greg Kroah-Hartman --- fs/ext4/namei.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/ext4/namei.c b/fs/ext4/namei.c index 790db7eac6c2..286f8fcb74cc 100644 --- a/fs/ext4/namei.c +++ b/fs/ext4/namei.c @@ -1995,7 +1995,7 @@ static struct ext4_dir_entry_2 *do_split(handle_t *handle, struct inode *dir, * split it in half by count; each resulting block will have at least * half the space free. */ - if (i > 0) + if (i >= 0) split = count - move; else split = count/2; From a1dde7457d5722a8f54fbceb98aafdeb0e31e5e1 Mon Sep 17 00:00:00 2001 From: Yeongjin Gil Date: Fri, 14 Mar 2025 21:06:51 +0900 Subject: [PATCH 096/136] f2fs: fix to avoid atomicity corruption of atomic file commit f098aeba04c9328571567dca45159358a250240c upstream. In the case of the following call stack for an atomic file, FI_DIRTY_INODE is set, but FI_ATOMIC_DIRTIED is not subsequently set. f2fs_file_write_iter f2fs_map_blocks f2fs_reserve_new_blocks inc_valid_block_count __mark_inode_dirty(dquot) f2fs_dirty_inode If FI_ATOMIC_DIRTIED is not set, atomic file can encounter corruption due to a mismatch between old file size and new data. To resolve this issue, I changed to set FI_ATOMIC_DIRTIED when FI_DIRTY_INODE is set. This ensures that FI_DIRTY_INODE, which was previously cleared by the Writeback thread during the commit atomic, is set and i_size is updated. Cc: Fixes: fccaa81de87e ("f2fs: prevent atomic file from being dirtied before commit") Reviewed-by: Sungjong Seo Reviewed-by: Sunmin Jeong Signed-off-by: Yeongjin Gil Reviewed-by: Daeho Jeong Reviewed-by: Chao Yu Signed-off-by: Jaegeuk Kim Signed-off-by: Greg Kroah-Hartman --- fs/f2fs/inode.c | 4 +--- fs/f2fs/super.c | 4 ++++ 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/fs/f2fs/inode.c b/fs/f2fs/inode.c index 6135eee771cc..a60db5e795a4 100644 --- a/fs/f2fs/inode.c +++ b/fs/f2fs/inode.c @@ -34,10 +34,8 @@ void f2fs_mark_inode_dirty_sync(struct inode *inode, bool sync) if (f2fs_inode_dirtied(inode, sync)) return; - if (f2fs_is_atomic_file(inode)) { - set_inode_flag(inode, FI_ATOMIC_DIRTIED); + if (f2fs_is_atomic_file(inode)) return; - } mark_inode_dirty_sync(inode); } diff --git a/fs/f2fs/super.c b/fs/f2fs/super.c index a622056f27f3..573cc4725e2e 100644 --- a/fs/f2fs/super.c +++ b/fs/f2fs/super.c @@ -1515,6 +1515,10 @@ int f2fs_inode_dirtied(struct inode *inode, bool sync) inc_page_count(sbi, F2FS_DIRTY_IMETA); } spin_unlock(&sbi->inode_lock[DIRTY_META]); + + if (!ret && f2fs_is_atomic_file(inode)) + set_inode_flag(inode, FI_ATOMIC_DIRTIED); + return ret; } From 8fd217a99dbbe64ef533c08ad13b0f1df35f4cf5 Mon Sep 17 00:00:00 2001 From: Si-Wei Liu Date: Thu, 20 Feb 2025 21:37:33 +0200 Subject: [PATCH 097/136] vdpa/mlx5: Fix oversized null mkey longer than 32bit MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit commit a6097e0a54a5c24f8d577ffecbc35289ae281c2e upstream. create_user_mr() has correct code to count the number of null keys used to fill in a hole for the memory map. However, fill_indir() does not follow the same to cap the range up to the 1GB limit correspondingly. Fill in more null keys for the gaps in between, so that null keys are correctly populated. Fixes: 94abbccdf291 ("vdpa/mlx5: Add shared memory registration code") Cc: stable@vger.kernel.org Reported-by: Cong Meng Signed-off-by: Si-Wei Liu Signed-off-by: Dragos Tatulea Acked-by: Eugenio Pérez Message-Id: <20250220193732.521462-2-dtatulea@nvidia.com> Signed-off-by: Michael S. Tsirkin Acked-by: Jason Wang Signed-off-by: Greg Kroah-Hartman --- drivers/vdpa/mlx5/core/mr.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/drivers/vdpa/mlx5/core/mr.c b/drivers/vdpa/mlx5/core/mr.c index 8455f08f5d40..61424342c096 100644 --- a/drivers/vdpa/mlx5/core/mr.c +++ b/drivers/vdpa/mlx5/core/mr.c @@ -190,9 +190,12 @@ again: klm->bcount = cpu_to_be32(klm_bcount(dmr->end - dmr->start)); preve = dmr->end; } else { + u64 bcount = min_t(u64, dmr->start - preve, MAX_KLM_SIZE); + klm->key = cpu_to_be32(mvdev->res.null_mkey); - klm->bcount = cpu_to_be32(klm_bcount(dmr->start - preve)); - preve = dmr->start; + klm->bcount = cpu_to_be32(klm_bcount(bcount)); + preve += bcount; + goto again; } } From 76cc21a9a40f2ed8bc74bb040a8e188070872d59 Mon Sep 17 00:00:00 2001 From: Jan Kara Date: Wed, 12 Mar 2025 16:18:39 +0100 Subject: [PATCH 098/136] udf: Fix inode_getblk() return value commit 6afdc60ec30b0a9390d11b7cebed79c857ce82aa upstream. Smatch noticed that inode_getblk() can return 1 on successful mapping of a block instead of expected 0 after commit b405c1e58b73 ("udf: refactor udf_next_aext() to handle error"). This could confuse some of the callers and lead to strange failures (although the one reported by Smatch in udf_mkdir() is impossible to trigger in practice). Fix the return value of inode_getblk(). Link: https://lore.kernel.org/all/cb514af7-bbe0-435b-934f-dd1d7a16d2cd@stanley.mountain Reported-by: Dan Carpenter Reviewed-by: Carlos Maiolino Fixes: b405c1e58b73 ("udf: refactor udf_next_aext() to handle error") CC: stable@vger.kernel.org Signed-off-by: Jan Kara Signed-off-by: Greg Kroah-Hartman --- fs/udf/inode.c | 1 + 1 file changed, 1 insertion(+) diff --git a/fs/udf/inode.c b/fs/udf/inode.c index 70c907fe8af9..4386dd845e40 100644 --- a/fs/udf/inode.c +++ b/fs/udf/inode.c @@ -810,6 +810,7 @@ static int inode_getblk(struct inode *inode, struct udf_map_rq *map) } map->oflags = UDF_BLK_MAPPED; map->pblk = udf_get_lb_pblock(inode->i_sb, &eloc, offset); + ret = 0; goto out_free; } From f3cb81cb96d587f9f235a11789d1ec0992643078 Mon Sep 17 00:00:00 2001 From: Thadeu Lima de Souza Cascardo Date: Fri, 7 Feb 2025 15:07:46 -0300 Subject: [PATCH 099/136] tpm: do not start chip while suspended commit 17d253af4c2c8a2acf84bb55a0c2045f150b7dfd upstream. Checking TPM_CHIP_FLAG_SUSPENDED after the call to tpm_find_get_ops() can lead to a spurious tpm_chip_start() call: [35985.503771] i2c i2c-1: Transfer while suspended [35985.503796] WARNING: CPU: 0 PID: 74 at drivers/i2c/i2c-core.h:56 __i2c_transfer+0xbe/0x810 [35985.503802] Modules linked in: [35985.503808] CPU: 0 UID: 0 PID: 74 Comm: hwrng Tainted: G W 6.13.0-next-20250203-00005-gfa0cb5642941 #19 9c3d7f78192f2d38e32010ac9c90fdc71109ef6f [35985.503814] Tainted: [W]=WARN [35985.503817] Hardware name: Google Morphius/Morphius, BIOS Google_Morphius.13434.858.0 10/26/2023 [35985.503819] RIP: 0010:__i2c_transfer+0xbe/0x810 [35985.503825] Code: 30 01 00 00 4c 89 f7 e8 40 fe d8 ff 48 8b 93 80 01 00 00 48 85 d2 75 03 49 8b 16 48 c7 c7 0a fb 7c a7 48 89 c6 e8 32 ad b0 fe <0f> 0b b8 94 ff ff ff e9 33 04 00 00 be 02 00 00 00 83 fd 02 0f 5 [35985.503828] RSP: 0018:ffffa106c0333d30 EFLAGS: 00010246 [35985.503833] RAX: 074ba64aa20f7000 RBX: ffff8aa4c1167120 RCX: 0000000000000000 [35985.503836] RDX: 0000000000000000 RSI: ffffffffa77ab0e4 RDI: 0000000000000001 [35985.503838] RBP: 0000000000000001 R08: 0000000000000001 R09: 0000000000000000 [35985.503841] R10: 0000000000000004 R11: 00000001000313d5 R12: ffff8aa4c10f1820 [35985.503843] R13: ffff8aa4c0e243c0 R14: ffff8aa4c1167250 R15: ffff8aa4c1167120 [35985.503846] FS: 0000000000000000(0000) GS:ffff8aa4eae00000(0000) knlGS:0000000000000000 [35985.503849] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 [35985.503852] CR2: 00007fab0aaf1000 CR3: 0000000105328000 CR4: 00000000003506f0 [35985.503855] Call Trace: [35985.503859] [35985.503863] ? __warn+0xd4/0x260 [35985.503868] ? __i2c_transfer+0xbe/0x810 [35985.503874] ? report_bug+0xf3/0x210 [35985.503882] ? handle_bug+0x63/0xb0 [35985.503887] ? exc_invalid_op+0x16/0x50 [35985.503892] ? asm_exc_invalid_op+0x16/0x20 [35985.503904] ? __i2c_transfer+0xbe/0x810 [35985.503913] tpm_cr50_i2c_transfer_message+0x24/0xf0 [35985.503920] tpm_cr50_i2c_read+0x8e/0x120 [35985.503928] tpm_cr50_request_locality+0x75/0x170 [35985.503935] tpm_chip_start+0x116/0x160 [35985.503942] tpm_try_get_ops+0x57/0x90 [35985.503948] tpm_find_get_ops+0x26/0xd0 [35985.503955] tpm_get_random+0x2d/0x80 Don't move forward with tpm_chip_start() inside tpm_try_get_ops(), unless TPM_CHIP_FLAG_SUSPENDED is not set. tpm_find_get_ops() will return NULL in such a failure case. Fixes: 9265fed6db60 ("tpm: Lock TPM chip in tpm_pm_suspend() first") Signed-off-by: Thadeu Lima de Souza Cascardo Cc: stable@vger.kernel.org Cc: Jerry Snitselaar Cc: Mike Seo Cc: Jarkko Sakkinen Reviewed-by: Jerry Snitselaar Reviewed-by: Jarkko Sakkinen Signed-off-by: Jarkko Sakkinen Signed-off-by: Greg Kroah-Hartman --- drivers/char/tpm/tpm-chip.c | 5 +++++ drivers/char/tpm/tpm-interface.c | 7 ------- 2 files changed, 5 insertions(+), 7 deletions(-) diff --git a/drivers/char/tpm/tpm-chip.c b/drivers/char/tpm/tpm-chip.c index 87f01269b9b5..e25daf2396d3 100644 --- a/drivers/char/tpm/tpm-chip.c +++ b/drivers/char/tpm/tpm-chip.c @@ -168,6 +168,11 @@ int tpm_try_get_ops(struct tpm_chip *chip) goto out_ops; mutex_lock(&chip->tpm_mutex); + + /* tmp_chip_start may issue IO that is denied while suspended */ + if (chip->flags & TPM_CHIP_FLAG_SUSPENDED) + goto out_lock; + rc = tpm_chip_start(chip); if (rc) goto out_lock; diff --git a/drivers/char/tpm/tpm-interface.c b/drivers/char/tpm/tpm-interface.c index b1daa0d7b341..f62f7871edbd 100644 --- a/drivers/char/tpm/tpm-interface.c +++ b/drivers/char/tpm/tpm-interface.c @@ -445,18 +445,11 @@ int tpm_get_random(struct tpm_chip *chip, u8 *out, size_t max) if (!chip) return -ENODEV; - /* Give back zero bytes, as TPM chip has not yet fully resumed: */ - if (chip->flags & TPM_CHIP_FLAG_SUSPENDED) { - rc = 0; - goto out; - } - if (chip->flags & TPM_CHIP_FLAG_TPM2) rc = tpm2_get_random(chip, out, max); else rc = tpm1_get_random(chip, out, max); -out: tpm_put_ops(chip); return rc; } From fbda9cac1bb3651ec4f994dba71ce7b186a81a0d Mon Sep 17 00:00:00 2001 From: Olga Kornievskaia Date: Thu, 6 Feb 2025 13:15:34 -0500 Subject: [PATCH 100/136] svcrdma: do not unregister device for listeners commit 750037aa0a9f28d84df3dcf319a28423d69092fd upstream. On an rdma-capable machine, a start/stop/start and then on a stop of a knfsd server would lead kref underflow warning because svc_rdma_free would indiscriminately unregister the rdma device but a listening transport never calls the rdma_rn_register() thus leading to kref going down to 0 on the 1st stop of the server and on the 2nd stop it leads to a problem. Suggested-by: Chuck Lever Fixes: c4de97f7c454 ("svcrdma: Handle device removal outside of the CM event handler") Signed-off-by: Olga Kornievskaia Cc: stable@vger.kernel.org Signed-off-by: Chuck Lever Signed-off-by: Greg Kroah-Hartman --- net/sunrpc/xprtrdma/svc_rdma_transport.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/net/sunrpc/xprtrdma/svc_rdma_transport.c b/net/sunrpc/xprtrdma/svc_rdma_transport.c index c3fbf0779d4a..aca8bdf65d72 100644 --- a/net/sunrpc/xprtrdma/svc_rdma_transport.c +++ b/net/sunrpc/xprtrdma/svc_rdma_transport.c @@ -621,7 +621,8 @@ static void __svc_rdma_free(struct work_struct *work) /* Destroy the CM ID */ rdma_destroy_id(rdma->sc_cm_id); - rpcrdma_rn_unregister(device, &rdma->sc_rn); + if (!test_bit(XPT_LISTENER, &rdma->sc_xprt.xpt_flags)) + rpcrdma_rn_unregister(device, &rdma->sc_rn); kfree(rdma); } From 44a2572a0fdcf3e7565763690d579b998a8f0562 Mon Sep 17 00:00:00 2001 From: Chenyuan Yang Date: Wed, 12 Feb 2025 15:35:18 -0600 Subject: [PATCH 101/136] soc: samsung: exynos-chipid: Add NULL pointer check in exynos_chipid_probe() commit c8222ef6cf29dd7cad21643228f96535cc02b327 upstream. soc_dev_attr->revision could be NULL, thus, a pointer check is added to prevent potential NULL pointer dereference. This is similar to the fix in commit 3027e7b15b02 ("ice: Fix some null pointer dereference issues in ice_ptp.c"). This issue is found by our static analysis tool. Signed-off-by: Chenyuan Yang Link: https://lore.kernel.org/r/20250212213518.69432-1-chenyuan0y@gmail.com Fixes: 3253b7b7cd44 ("soc: samsung: Add exynos chipid driver support") Cc: Signed-off-by: Krzysztof Kozlowski Signed-off-by: Greg Kroah-Hartman --- drivers/soc/samsung/exynos-chipid.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/soc/samsung/exynos-chipid.c b/drivers/soc/samsung/exynos-chipid.c index b1118d37779e..bba8d86ae1bb 100644 --- a/drivers/soc/samsung/exynos-chipid.c +++ b/drivers/soc/samsung/exynos-chipid.c @@ -131,6 +131,8 @@ static int exynos_chipid_probe(struct platform_device *pdev) soc_dev_attr->revision = devm_kasprintf(&pdev->dev, GFP_KERNEL, "%x", soc_info.revision); + if (!soc_dev_attr->revision) + return -ENOMEM; soc_dev_attr->soc_id = product_id_to_soc_id(soc_info.product_id); if (!soc_dev_attr->soc_id) { pr_err("Unknown SoC\n"); From 9a264e4a595df65eeeaf35d3ba4af8c73a9ffb36 Mon Sep 17 00:00:00 2001 From: Steve French Date: Sun, 6 Apr 2025 14:09:19 -0500 Subject: [PATCH 102/136] smb311 client: fix missing tcon check when mounting with linux/posix extensions commit b365b9d404b7376c60c91cd079218bfef11b7822 upstream. When mounting the same share twice, once with the "linux" mount parameter (or equivalently "posix") and then once without (or e.g. with "nolinux"), we were incorrectly reusing the same tree connection for both mounts. This meant that the first mount of the share on the client, would cause subsequent mounts of that same share on the same client to ignore that mount parm ("linux" vs. "nolinux") and incorrectly reuse the same tcon. Cc: stable@vger.kernel.org Signed-off-by: Steve French Signed-off-by: Greg Kroah-Hartman --- fs/smb/client/connect.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/fs/smb/client/connect.c b/fs/smb/client/connect.c index 8b8475b4e262..18443d879c2d 100644 --- a/fs/smb/client/connect.c +++ b/fs/smb/client/connect.c @@ -2474,6 +2474,8 @@ static int match_tcon(struct cifs_tcon *tcon, struct smb3_fs_context *ctx) return 0; if (tcon->nodelete != ctx->nodelete) return 0; + if (tcon->posix_extensions != ctx->linux_ext) + return 0; return 1; } From 48085ab823f00cb7a63ce1cdf2185214d89590a2 Mon Sep 17 00:00:00 2001 From: Mimi Zohar Date: Mon, 27 Jan 2025 10:24:13 -0500 Subject: [PATCH 103/136] ima: limit the number of open-writers integrity violations commit 5b3cd801155f0b34b0b95942a5b057c9b8cad33e upstream. Each time a file in policy, that is already opened for write, is opened for read, an open-writers integrity violation audit message is emitted and a violation record is added to the IMA measurement list. This occurs even if an open-writers violation has already been recorded. Limit the number of open-writers integrity violations for an existing file open for write to one. After the existing file open for write closes (__fput), subsequent open-writers integrity violations may be emitted. Cc: stable@vger.kernel.org # applies cleanly up to linux-6.6 Tested-by: Stefan Berger Reviewed-by: Petr Vorel Tested-by: Petr Vorel Reviewed-by: Roberto Sassu Signed-off-by: Mimi Zohar Signed-off-by: Greg Kroah-Hartman --- security/integrity/ima/ima.h | 1 + security/integrity/ima/ima_main.c | 11 +++++++++-- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/security/integrity/ima/ima.h b/security/integrity/ima/ima.h index abfdb4905ca2..062f8039e339 100644 --- a/security/integrity/ima/ima.h +++ b/security/integrity/ima/ima.h @@ -182,6 +182,7 @@ struct ima_kexec_hdr { #define IMA_CHANGE_ATTR 2 #define IMA_DIGSIG 3 #define IMA_MUST_MEASURE 4 +#define IMA_EMITTED_OPENWRITERS 5 /* IMA integrity metadata associated with an inode */ struct ima_iint_cache { diff --git a/security/integrity/ima/ima_main.c b/security/integrity/ima/ima_main.c index 4b213de8dcb4..417552f3110d 100644 --- a/security/integrity/ima/ima_main.c +++ b/security/integrity/ima/ima_main.c @@ -137,8 +137,13 @@ static void ima_rdwr_violation_check(struct file *file, } else { if (must_measure) set_bit(IMA_MUST_MEASURE, &iint->atomic_flags); - if (inode_is_open_for_write(inode) && must_measure) - send_writers = true; + + /* Limit number of open_writers violations */ + if (inode_is_open_for_write(inode) && must_measure) { + if (!test_and_set_bit(IMA_EMITTED_OPENWRITERS, + &iint->atomic_flags)) + send_writers = true; + } } if (!send_tomtou && !send_writers) @@ -167,6 +172,8 @@ static void ima_check_last_writer(struct ima_iint_cache *iint, if (atomic_read(&inode->i_writecount) == 1) { struct kstat stat; + clear_bit(IMA_EMITTED_OPENWRITERS, &iint->atomic_flags); + update = test_and_clear_bit(IMA_UPDATE_XATTR, &iint->atomic_flags); if ((iint->flags & IMA_NEW_FILE) || From 0327683c5571dc24f07c1c45c17a9a08fa38b592 Mon Sep 17 00:00:00 2001 From: Mimi Zohar Date: Mon, 27 Jan 2025 10:45:48 -0500 Subject: [PATCH 104/136] ima: limit the number of ToMToU integrity violations commit a414016218ca97140171aa3bb926b02e1f68c2cc upstream. Each time a file in policy, that is already opened for read, is opened for write, a Time-of-Measure-Time-of-Use (ToMToU) integrity violation audit message is emitted and a violation record is added to the IMA measurement list. This occurs even if a ToMToU violation has already been recorded. Limit the number of ToMToU integrity violations per file open for read. Note: The IMA_MAY_EMIT_TOMTOU atomic flag must be set from the reader side based on policy. This may result in a per file open for read ToMToU violation. Since IMA_MUST_MEASURE is only used for violations, rename the atomic IMA_MUST_MEASURE flag to IMA_MAY_EMIT_TOMTOU. Cc: stable@vger.kernel.org # applies cleanly up to linux-6.6 Tested-by: Stefan Berger Reviewed-by: Petr Vorel Tested-by: Petr Vorel Reviewed-by: Roberto Sassu Signed-off-by: Mimi Zohar Signed-off-by: Greg Kroah-Hartman --- security/integrity/ima/ima.h | 2 +- security/integrity/ima/ima_main.c | 7 ++++--- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/security/integrity/ima/ima.h b/security/integrity/ima/ima.h index 062f8039e339..56bf2f55d938 100644 --- a/security/integrity/ima/ima.h +++ b/security/integrity/ima/ima.h @@ -181,7 +181,7 @@ struct ima_kexec_hdr { #define IMA_UPDATE_XATTR 1 #define IMA_CHANGE_ATTR 2 #define IMA_DIGSIG 3 -#define IMA_MUST_MEASURE 4 +#define IMA_MAY_EMIT_TOMTOU 4 #define IMA_EMITTED_OPENWRITERS 5 /* IMA integrity metadata associated with an inode */ diff --git a/security/integrity/ima/ima_main.c b/security/integrity/ima/ima_main.c index 417552f3110d..a9aab10bebca 100644 --- a/security/integrity/ima/ima_main.c +++ b/security/integrity/ima/ima_main.c @@ -129,14 +129,15 @@ static void ima_rdwr_violation_check(struct file *file, if (atomic_read(&inode->i_readcount) && IS_IMA(inode)) { if (!iint) iint = ima_iint_find(inode); + /* IMA_MEASURE is set from reader side */ - if (iint && test_bit(IMA_MUST_MEASURE, - &iint->atomic_flags)) + if (iint && test_and_clear_bit(IMA_MAY_EMIT_TOMTOU, + &iint->atomic_flags)) send_tomtou = true; } } else { if (must_measure) - set_bit(IMA_MUST_MEASURE, &iint->atomic_flags); + set_bit(IMA_MAY_EMIT_TOMTOU, &iint->atomic_flags); /* Limit number of open_writers violations */ if (inode_is_open_for_write(inode) && must_measure) { From 34aaf448e204b83bf59dbfb5f15d191d7ae51eee Mon Sep 17 00:00:00 2001 From: Stanley Chu Date: Tue, 18 Mar 2025 13:36:05 +0800 Subject: [PATCH 105/136] i3c: master: svc: Use readsb helper for reading MDB commit c06acf7143bddaa3c0f7bedd8b99e48f6acb85c3 upstream. The target can send the MDB byte followed by additional data bytes. The readl on MRDATAB reads one actual byte, but the readsl advances the destination pointer by 4 bytes. This causes the subsequent payload to be copied to wrong position in the destination buffer. Cc: stable@kernel.org Fixes: dd3c52846d59 ("i3c: master: svc: Add Silvaco I3C master driver") Signed-off-by: Stanley Chu Reviewed-by: Frank Li Link: https://lore.kernel.org/r/20250318053606.3087121-3-yschu@nuvoton.com Signed-off-by: Alexandre Belloni Signed-off-by: Greg Kroah-Hartman --- drivers/i3c/master/svc-i3c-master.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/i3c/master/svc-i3c-master.c b/drivers/i3c/master/svc-i3c-master.c index 87f98fa8afd5..42102baabcdd 100644 --- a/drivers/i3c/master/svc-i3c-master.c +++ b/drivers/i3c/master/svc-i3c-master.c @@ -378,7 +378,7 @@ static int svc_i3c_master_handle_ibi(struct svc_i3c_master *master, slot->len < SVC_I3C_FIFO_SIZE) { mdatactrl = readl(master->regs + SVC_I3C_MDATACTRL); count = SVC_I3C_MDATACTRL_RXCOUNT(mdatactrl); - readsl(master->regs + SVC_I3C_MRDATAB, buf, count); + readsb(master->regs + SVC_I3C_MRDATAB, buf, count); slot->len += count; buf += count; } From e6bba328578feb58c614c11868c259b40484c5fa Mon Sep 17 00:00:00 2001 From: Manjunatha Venkatesh Date: Wed, 26 Mar 2025 18:00:46 +0530 Subject: [PATCH 106/136] i3c: Add NULL pointer check in i3c_master_queue_ibi() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit commit bd496a44f041da9ef3afe14d1d6193d460424e91 upstream. The I3C master driver may receive an IBI from a target device that has not been probed yet. In such cases, the master calls `i3c_master_queue_ibi()` to queue an IBI work task, leading to "Unable to handle kernel read from unreadable memory" and resulting in a kernel panic. Typical IBI handling flow: 1. The I3C master scans target devices and probes their respective drivers. 2. The target device driver calls `i3c_device_request_ibi()` to enable IBI and assigns `dev->ibi = ibi`. 3. The I3C master receives an IBI from the target device and calls `i3c_master_queue_ibi()` to queue the target device driver’s IBI handler task. However, since target device events are asynchronous to the I3C probe sequence, step 3 may occur before step 2, causing `dev->ibi` to be `NULL`, leading to a kernel panic. Add a NULL pointer check in `i3c_master_queue_ibi()` to prevent accessing an uninitialized `dev->ibi`, ensuring stability. Fixes: 3a379bbcea0af ("i3c: Add core I3C infrastructure") Cc: stable@vger.kernel.org Link: https://lore.kernel.org/lkml/Z9gjGYudiYyl3bSe@lizhi-Precision-Tower-5810/ Signed-off-by: Manjunatha Venkatesh Reviewed-by: Frank Li Link: https://lore.kernel.org/r/20250326123047.2797946-1-manjunatha.venkatesh@nxp.com Signed-off-by: Alexandre Belloni Signed-off-by: Greg Kroah-Hartman --- drivers/i3c/master.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/i3c/master.c b/drivers/i3c/master.c index 53ab814b676f..7c1dc42b809b 100644 --- a/drivers/i3c/master.c +++ b/drivers/i3c/master.c @@ -2553,6 +2553,9 @@ static void i3c_master_unregister_i3c_devs(struct i3c_master_controller *master) */ void i3c_master_queue_ibi(struct i3c_dev_desc *dev, struct i3c_ibi_slot *slot) { + if (!dev->ibi || !slot) + return; + atomic_inc(&dev->ibi->pending_ibis); queue_work(dev->ibi->wq, &slot->work); } From 9eaec071f111cd2124ce9a5b93536d3f6837d457 Mon Sep 17 00:00:00 2001 From: Jan Kara Date: Thu, 6 Feb 2025 10:46:58 +0100 Subject: [PATCH 107/136] jbd2: remove wrong sb->s_sequence check commit e6eff39dd0fe4190c6146069cc16d160e71d1148 upstream. Journal emptiness is not determined by sb->s_sequence == 0 but rather by sb->s_start == 0 (which is set a few lines above). Furthermore 0 is a valid transaction ID so the check can spuriously trigger. Remove the invalid WARN_ON. CC: stable@vger.kernel.org Signed-off-by: Jan Kara Reviewed-by: Zhang Yi Link: https://patch.msgid.link/20250206094657.20865-3-jack@suse.cz Signed-off-by: Theodore Ts'o Signed-off-by: Greg Kroah-Hartman --- fs/jbd2/journal.c | 1 - 1 file changed, 1 deletion(-) diff --git a/fs/jbd2/journal.c b/fs/jbd2/journal.c index 97f487c3d8fc..c073f5fb9859 100644 --- a/fs/jbd2/journal.c +++ b/fs/jbd2/journal.c @@ -1884,7 +1884,6 @@ int jbd2_journal_update_sb_log_tail(journal_t *journal, tid_t tail_tid, /* Log is no longer empty */ write_lock(&journal->j_state_lock); - WARN_ON(!sb->s_sequence); journal->j_flags &= ~JBD2_FLUSHED; write_unlock(&journal->j_state_lock); From e94314b727683f2b2d969a85e88d730caa7fe180 Mon Sep 17 00:00:00 2001 From: Kris Van Hees Date: Fri, 7 Mar 2025 11:53:28 -0500 Subject: [PATCH 108/136] kbuild: exclude .rodata.(cst|str)* when building ranges commit 87bb368d0637c466a8a77433837056f981d01991 upstream. The .rodata.(cst|str)* sections are often resized during the final linking and since these sections do not cover actual symbols there is no need to include them in the modules.builtin.ranges data. When these sections were included in processing and resizing occurred, modules were reported with ranges that extended beyond their true end, causing subsequent symbols (in address order) to be associated with the wrong module. Fixes: 5f5e7344322f ("kbuild: generate offset range data for builtin modules") Cc: stable@vger.kernel.org Signed-off-by: Kris Van Hees Reviewed-by: Jack Vogel Signed-off-by: Masahiro Yamada Signed-off-by: Greg Kroah-Hartman --- scripts/generate_builtin_ranges.awk | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/scripts/generate_builtin_ranges.awk b/scripts/generate_builtin_ranges.awk index b9ec761b3bef..d4bd5c2b998c 100755 --- a/scripts/generate_builtin_ranges.awk +++ b/scripts/generate_builtin_ranges.awk @@ -282,6 +282,11 @@ ARGIND == 2 && !anchor && NF == 2 && $1 ~ /^0x/ && $2 !~ /^0x/ { # section. # ARGIND == 2 && sect && NF == 4 && /^ [^ \*]/ && !($1 in sect_addend) { + # There are a few sections with constant data (without symbols) that + # can get resized during linking, so it is best to ignore them. + if ($1 ~ /^\.rodata\.(cst|str)[0-9]/) + next; + if (!($1 in sect_base)) { sect_base[$1] = base; From 5ae9e361e28476a37f1099100d8b214607220bb6 Mon Sep 17 00:00:00 2001 From: Abel Vesa Date: Wed, 5 Mar 2025 15:09:05 +0200 Subject: [PATCH 109/136] leds: rgb: leds-qcom-lpg: Fix pwm resolution max for Hi-Res PWMs commit b7881eacc07fdf50be3f33c662997541bb59366d upstream. Ideally, the requested duty cycle should never translate to a PWM value higher than the selected resolution (PWM size), but currently the best matched period is never reported back to the PWM consumer, so the consumer will still be using the requested period which is higher than the best matched one. This will result in PWM consumer requesting duty cycle values higher than the allowed PWM value. For example, a consumer might request a period of 5ms while the best (closest) period the PWM hardware will do is 4.26ms. For this best matched resolution, if the selected resolution is 8-bit wide, when the consumer asks for a duty cycle of 5ms, the PWM value will be 300, which is outside of what the resolution allows. This will happen with all possible resolutions when selected. Since for these Hi-Res PWMs, the current implementation is capping the PWM value at a 15-bit resolution, even when lower resolutions are selected, the value will be wrapped around by the HW internal logic to the selected resolution. Fix the issue by capping the PWM value to the maximum value allowed by the selected resolution. Cc: stable@vger.kernel.org # 6.4 Fixes: b00d2ed37617 ("leds: rgb: leds-qcom-lpg: Add support for high resolution PWM") Signed-off-by: Abel Vesa Reviewed-by: Bjorn Andersson Reviewed-by: Sebastian Reichel Link: https://lore.kernel.org/r/20250305-leds-qcom-lpg-fix-max-pwm-on-hi-res-v4-2-bfe124a53a9f@linaro.org Signed-off-by: Lee Jones Signed-off-by: Greg Kroah-Hartman --- drivers/leds/rgb/leds-qcom-lpg.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/leds/rgb/leds-qcom-lpg.c b/drivers/leds/rgb/leds-qcom-lpg.c index f3c9ef2bfa57..146cd9b44778 100644 --- a/drivers/leds/rgb/leds-qcom-lpg.c +++ b/drivers/leds/rgb/leds-qcom-lpg.c @@ -529,7 +529,7 @@ static void lpg_calc_duty(struct lpg_channel *chan, uint64_t duty) unsigned int clk_rate; if (chan->subtype == LPG_SUBTYPE_HI_RES_PWM) { - max = LPG_RESOLUTION_15BIT - 1; + max = BIT(lpg_pwm_resolution_hi_res[chan->pwm_resolution_sel]) - 1; clk_rate = lpg_clk_rates_hi_res[chan->clk_sel]; } else { max = LPG_RESOLUTION_9BIT - 1; From 4b037851edd7eedecee9ab31a871ffde0169fc20 Mon Sep 17 00:00:00 2001 From: Abel Vesa Date: Wed, 5 Mar 2025 15:09:06 +0200 Subject: [PATCH 110/136] leds: rgb: leds-qcom-lpg: Fix calculation of best period Hi-Res PWMs commit 2528eec7da0ec58fcae6d12cfa79a622c933d86b upstream. When determining the actual best period by looping through all possible PWM configs, the resolution currently used is based on bit shift value which is off-by-one above the possible maximum PWM value allowed. So subtract one from the resolution before determining the best period so that the maximum duty cycle requested by the PWM user won't result in a value above the maximum allowed by the selected resolution. Cc: stable@vger.kernel.org # 6.4 Fixes: b00d2ed37617 ("leds: rgb: leds-qcom-lpg: Add support for high resolution PWM") Signed-off-by: Abel Vesa Reviewed-by: Sebastian Reichel Link: https://lore.kernel.org/r/20250305-leds-qcom-lpg-fix-max-pwm-on-hi-res-v4-3-bfe124a53a9f@linaro.org Signed-off-by: Lee Jones Signed-off-by: Greg Kroah-Hartman --- drivers/leds/rgb/leds-qcom-lpg.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/leds/rgb/leds-qcom-lpg.c b/drivers/leds/rgb/leds-qcom-lpg.c index 146cd9b44778..5d8e27e2e7ae 100644 --- a/drivers/leds/rgb/leds-qcom-lpg.c +++ b/drivers/leds/rgb/leds-qcom-lpg.c @@ -461,7 +461,7 @@ static int lpg_calc_freq(struct lpg_channel *chan, uint64_t period) max_res = LPG_RESOLUTION_9BIT; } - min_period = div64_u64((u64)NSEC_PER_SEC * (1 << pwm_resolution_arr[0]), + min_period = div64_u64((u64)NSEC_PER_SEC * ((1 << pwm_resolution_arr[0]) - 1), clk_rate_arr[clk_len - 1]); if (period <= min_period) return -EINVAL; @@ -482,7 +482,7 @@ static int lpg_calc_freq(struct lpg_channel *chan, uint64_t period) */ for (i = 0; i < pwm_resolution_count; i++) { - resolution = 1 << pwm_resolution_arr[i]; + resolution = (1 << pwm_resolution_arr[i]) - 1; for (clk_sel = 1; clk_sel < clk_len; clk_sel++) { u64 numerator = period * clk_rate_arr[clk_sel]; @@ -1291,7 +1291,7 @@ static int lpg_pwm_get_state(struct pwm_chip *chip, struct pwm_device *pwm, if (ret) return ret; - state->period = DIV_ROUND_UP_ULL((u64)NSEC_PER_SEC * (1 << resolution) * + state->period = DIV_ROUND_UP_ULL((u64)NSEC_PER_SEC * ((1 << resolution) - 1) * pre_div * (1 << m), refclk); state->duty_cycle = DIV_ROUND_UP_ULL((u64)NSEC_PER_SEC * pwm_value * pre_div * (1 << m), refclk); } else { From 7b47df6498f223c8956bfe0d994a0e42a520dfcd Mon Sep 17 00:00:00 2001 From: Chenyuan Yang Date: Mon, 24 Feb 2025 17:37:36 -0600 Subject: [PATCH 111/136] mfd: ene-kb3930: Fix a potential NULL pointer dereference commit 4cdf1d2a816a93fa02f7b6b5492dc7f55af2a199 upstream. The off_gpios could be NULL. Add missing check in the kb3930_probe(). This is similar to the issue fixed in commit b1ba8bcb2d1f ("backlight: hx8357: Fix potential NULL pointer dereference"). This was detected by our static analysis tool. Cc: stable@vger.kernel.org Fixes: ede6b2d1dfc0 ("mfd: ene-kb3930: Add driver for ENE KB3930 Embedded Controller") Suggested-by: Lee Jones Signed-off-by: Chenyuan Yang Link: https://lore.kernel.org/r/20250224233736.1919739-1-chenyuan0y@gmail.com Signed-off-by: Lee Jones Signed-off-by: Greg Kroah-Hartman --- drivers/mfd/ene-kb3930.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/mfd/ene-kb3930.c b/drivers/mfd/ene-kb3930.c index fa0ad2f14a39..9460a67acb0b 100644 --- a/drivers/mfd/ene-kb3930.c +++ b/drivers/mfd/ene-kb3930.c @@ -162,7 +162,7 @@ static int kb3930_probe(struct i2c_client *client) devm_gpiod_get_array_optional(dev, "off", GPIOD_IN); if (IS_ERR(ddata->off_gpios)) return PTR_ERR(ddata->off_gpios); - if (ddata->off_gpios->ndescs < 2) { + if (ddata->off_gpios && ddata->off_gpios->ndescs < 2) { dev_err(dev, "invalid off-gpios property\n"); return -EINVAL; } From 008b90d36d913604ad206e706a9ac4b3630e6c88 Mon Sep 17 00:00:00 2001 From: Kartik Rajput Date: Thu, 23 Jan 2025 18:16:32 +0530 Subject: [PATCH 112/136] mailbox: tegra-hsp: Define dimensioning masks in SoC data commit bf0c9fb462038815f5f502653fb6dba06e6af415 upstream. Tegra264 has updated HSP_INT_DIMENSIONING register as follows: * nSI is now BIT17:BIT21. * nDB is now BIT12:BIT16. Currently, we are using a static macro HSP_nINT_MASK to get the values from HSP_INT_DIMENSIONING register. This results in wrong values for nSI for HSP instances that supports 16 shared interrupts. Define dimensioning masks in soc data and use them to parse nSI, nDB, nAS, nSS & nSM values. Fixes: 602dbbacc3ef ("mailbox: tegra: add support for Tegra264") Cc: stable@vger.kernel.org Signed-off-by: Kartik Rajput Acked-by: Thierry Reding Acked-by: Jon Hunter Signed-off-by: Jassi Brar Signed-off-by: Greg Kroah-Hartman --- drivers/mailbox/tegra-hsp.c | 72 ++++++++++++++++++++++++++++++------- 1 file changed, 60 insertions(+), 12 deletions(-) diff --git a/drivers/mailbox/tegra-hsp.c b/drivers/mailbox/tegra-hsp.c index 46c921000a34..76f54f8b6b6c 100644 --- a/drivers/mailbox/tegra-hsp.c +++ b/drivers/mailbox/tegra-hsp.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2016-2023, NVIDIA CORPORATION. All rights reserved. + * Copyright (c) 2016-2025, NVIDIA CORPORATION. All rights reserved. */ #include @@ -28,12 +28,6 @@ #define HSP_INT_FULL_MASK 0xff #define HSP_INT_DIMENSIONING 0x380 -#define HSP_nSM_SHIFT 0 -#define HSP_nSS_SHIFT 4 -#define HSP_nAS_SHIFT 8 -#define HSP_nDB_SHIFT 12 -#define HSP_nSI_SHIFT 16 -#define HSP_nINT_MASK 0xf #define HSP_DB_TRIGGER 0x0 #define HSP_DB_ENABLE 0x4 @@ -97,6 +91,20 @@ struct tegra_hsp_soc { bool has_per_mb_ie; bool has_128_bit_mb; unsigned int reg_stride; + + /* Shifts for dimensioning register. */ + unsigned int si_shift; + unsigned int db_shift; + unsigned int as_shift; + unsigned int ss_shift; + unsigned int sm_shift; + + /* Masks for dimensioning register. */ + unsigned int si_mask; + unsigned int db_mask; + unsigned int as_mask; + unsigned int ss_mask; + unsigned int sm_mask; }; struct tegra_hsp { @@ -747,11 +755,11 @@ static int tegra_hsp_probe(struct platform_device *pdev) return PTR_ERR(hsp->regs); value = tegra_hsp_readl(hsp, HSP_INT_DIMENSIONING); - hsp->num_sm = (value >> HSP_nSM_SHIFT) & HSP_nINT_MASK; - hsp->num_ss = (value >> HSP_nSS_SHIFT) & HSP_nINT_MASK; - hsp->num_as = (value >> HSP_nAS_SHIFT) & HSP_nINT_MASK; - hsp->num_db = (value >> HSP_nDB_SHIFT) & HSP_nINT_MASK; - hsp->num_si = (value >> HSP_nSI_SHIFT) & HSP_nINT_MASK; + hsp->num_sm = (value >> hsp->soc->sm_shift) & hsp->soc->sm_mask; + hsp->num_ss = (value >> hsp->soc->ss_shift) & hsp->soc->ss_mask; + hsp->num_as = (value >> hsp->soc->as_shift) & hsp->soc->as_mask; + hsp->num_db = (value >> hsp->soc->db_shift) & hsp->soc->db_mask; + hsp->num_si = (value >> hsp->soc->si_shift) & hsp->soc->si_mask; err = platform_get_irq_byname_optional(pdev, "doorbell"); if (err >= 0) @@ -915,6 +923,16 @@ static const struct tegra_hsp_soc tegra186_hsp_soc = { .has_per_mb_ie = false, .has_128_bit_mb = false, .reg_stride = 0x100, + .si_shift = 16, + .db_shift = 12, + .as_shift = 8, + .ss_shift = 4, + .sm_shift = 0, + .si_mask = 0xf, + .db_mask = 0xf, + .as_mask = 0xf, + .ss_mask = 0xf, + .sm_mask = 0xf, }; static const struct tegra_hsp_soc tegra194_hsp_soc = { @@ -922,6 +940,16 @@ static const struct tegra_hsp_soc tegra194_hsp_soc = { .has_per_mb_ie = true, .has_128_bit_mb = false, .reg_stride = 0x100, + .si_shift = 16, + .db_shift = 12, + .as_shift = 8, + .ss_shift = 4, + .sm_shift = 0, + .si_mask = 0xf, + .db_mask = 0xf, + .as_mask = 0xf, + .ss_mask = 0xf, + .sm_mask = 0xf, }; static const struct tegra_hsp_soc tegra234_hsp_soc = { @@ -929,6 +957,16 @@ static const struct tegra_hsp_soc tegra234_hsp_soc = { .has_per_mb_ie = false, .has_128_bit_mb = true, .reg_stride = 0x100, + .si_shift = 16, + .db_shift = 12, + .as_shift = 8, + .ss_shift = 4, + .sm_shift = 0, + .si_mask = 0xf, + .db_mask = 0xf, + .as_mask = 0xf, + .ss_mask = 0xf, + .sm_mask = 0xf, }; static const struct tegra_hsp_soc tegra264_hsp_soc = { @@ -936,6 +974,16 @@ static const struct tegra_hsp_soc tegra264_hsp_soc = { .has_per_mb_ie = false, .has_128_bit_mb = true, .reg_stride = 0x1000, + .si_shift = 17, + .db_shift = 12, + .as_shift = 8, + .ss_shift = 4, + .sm_shift = 0, + .si_mask = 0x1f, + .db_mask = 0x1f, + .as_mask = 0xf, + .ss_mask = 0xf, + .sm_mask = 0xf, }; static const struct of_device_id tegra_hsp_match[] = { From 95f0958240e6e63b6da2836629e74b16ca08d544 Mon Sep 17 00:00:00 2001 From: Boqun Feng Date: Wed, 26 Mar 2025 11:08:30 -0700 Subject: [PATCH 113/136] locking/lockdep: Decrease nr_unused_locks if lock unused in zap_class() commit 495f53d5cca0f939eaed9dca90b67e7e6fb0e30c upstream. Currently, when a lock class is allocated, nr_unused_locks will be increased by 1, until it gets used: nr_unused_locks will be decreased by 1 in mark_lock(). However, one scenario is missed: a lock class may be zapped without even being used once. This could result into a situation that nr_unused_locks != 0 but no unused lock class is active in the system, and when `cat /proc/lockdep_stats`, a WARN_ON() will be triggered in a CONFIG_DEBUG_LOCKDEP=y kernel: [...] DEBUG_LOCKS_WARN_ON(debug_atomic_read(nr_unused_locks) != nr_unused) [...] WARNING: CPU: 41 PID: 1121 at kernel/locking/lockdep_proc.c:283 lockdep_stats_show+0xba9/0xbd0 And as a result, lockdep will be disabled after this. Therefore, nr_unused_locks needs to be accounted correctly at zap_class() time. Signed-off-by: Boqun Feng Signed-off-by: Ingo Molnar Reviewed-by: Waiman Long Cc: stable@vger.kernel.org Link: https://lore.kernel.org/r/20250326180831.510348-1-boqun.feng@gmail.com Signed-off-by: Greg Kroah-Hartman --- kernel/locking/lockdep.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/kernel/locking/lockdep.c b/kernel/locking/lockdep.c index 536bd471557f..53c76dc71f3f 100644 --- a/kernel/locking/lockdep.c +++ b/kernel/locking/lockdep.c @@ -6223,6 +6223,9 @@ static void zap_class(struct pending_free *pf, struct lock_class *class) hlist_del_rcu(&class->hash_entry); WRITE_ONCE(class->key, NULL); WRITE_ONCE(class->name, NULL); + /* Class allocated but not used, -1 in nr_unused_locks */ + if (class->usage_mask == 0) + debug_atomic_dec(nr_unused_locks); nr_lock_classes--; __clear_bit(class - lock_classes, lock_classes_in_use); if (class - lock_classes == max_lock_class_idx) From c7f611e711c870ac18a4e8e592751630c8e26940 Mon Sep 17 00:00:00 2001 From: T Pratham Date: Wed, 19 Mar 2025 16:44:38 +0530 Subject: [PATCH 114/136] lib: scatterlist: fix sg_split_phys to preserve original scatterlist offsets commit 8b46fdaea819a679da176b879e7b0674a1161a5e upstream. The split_sg_phys function was incorrectly setting the offsets of all scatterlist entries (except the first) to 0. Only the first scatterlist entry's offset and length needs to be modified to account for the skip. Setting the rest entries' offsets to 0 could lead to incorrect data access. I am using this function in a crypto driver that I'm currently developing (not yet sent to mailing list). During testing, it was observed that the output scatterlists (except the first one) contained incorrect garbage data. I narrowed this issue down to the call of sg_split(). Upon debugging inside this function, I found that this resetting of offset is the cause of the problem, causing the subsequent scatterlists to point to incorrect memory locations in a page. By removing this code, I am obtaining expected data in all the split output scatterlists. Thus, this was indeed causing observable runtime effects! This patch removes the offending code, ensuring that the page offsets in the input scatterlist are preserved in the output scatterlist. Link: https://lkml.kernel.org/r/20250319111437.1969903-1-t-pratham@ti.com Fixes: f8bcbe62acd0 ("lib: scatterlist: add sg splitting function") Signed-off-by: T Pratham Cc: Robert Jarzmik Cc: Jens Axboe Cc: Kamlesh Gurudasani Cc: Praneeth Bajjuri Cc: Vignesh Raghavendra Cc: Signed-off-by: Andrew Morton Signed-off-by: Greg Kroah-Hartman --- lib/sg_split.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/lib/sg_split.c b/lib/sg_split.c index 60a0babebf2e..0f89aab5c671 100644 --- a/lib/sg_split.c +++ b/lib/sg_split.c @@ -88,8 +88,6 @@ static void sg_split_phys(struct sg_splitter *splitters, const int nb_splits) if (!j) { out_sg->offset += split->skip_sg0; out_sg->length -= split->skip_sg0; - } else { - out_sg->offset = 0; } sg_dma_address(out_sg) = 0; sg_dma_len(out_sg) = 0; From dc81e41a307df523072186b241fa8244fecd7803 Mon Sep 17 00:00:00 2001 From: Gang Yan Date: Fri, 28 Mar 2025 15:27:16 +0100 Subject: [PATCH 115/136] mptcp: fix NULL pointer in can_accept_new_subflow commit 443041deb5ef6a1289a99ed95015ec7442f141dc upstream. When testing valkey benchmark tool with MPTCP, the kernel panics in 'mptcp_can_accept_new_subflow' because subflow_req->msk is NULL. Call trace: mptcp_can_accept_new_subflow (./net/mptcp/subflow.c:63 (discriminator 4)) (P) subflow_syn_recv_sock (./net/mptcp/subflow.c:854) tcp_check_req (./net/ipv4/tcp_minisocks.c:863) tcp_v4_rcv (./net/ipv4/tcp_ipv4.c:2268) ip_protocol_deliver_rcu (./net/ipv4/ip_input.c:207) ip_local_deliver_finish (./net/ipv4/ip_input.c:234) ip_local_deliver (./net/ipv4/ip_input.c:254) ip_rcv_finish (./net/ipv4/ip_input.c:449) ... According to the debug log, the same req received two SYN-ACK in a very short time, very likely because the client retransmits the syn ack due to multiple reasons. Even if the packets are transmitted with a relevant time interval, they can be processed by the server on different CPUs concurrently). The 'subflow_req->msk' ownership is transferred to the subflow the first, and there will be a risk of a null pointer dereference here. This patch fixes this issue by moving the 'subflow_req->msk' under the `own_req == true` conditional. Note that the !msk check in subflow_hmac_valid() can be dropped, because the same check already exists under the own_req mpj branch where the code has been moved to. Fixes: 9466a1ccebbe ("mptcp: enable JOIN requests even if cookies are in use") Cc: stable@vger.kernel.org Suggested-by: Paolo Abeni Signed-off-by: Gang Yan Reviewed-by: Matthieu Baerts (NGI0) Signed-off-by: Matthieu Baerts (NGI0) Link: https://patch.msgid.link/20250328-net-mptcp-misc-fixes-6-15-v1-1-34161a482a7f@kernel.org Signed-off-by: Jakub Kicinski Signed-off-by: Greg Kroah-Hartman --- net/mptcp/subflow.c | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/net/mptcp/subflow.c b/net/mptcp/subflow.c index b56bbee7312c..4011eb6aecd0 100644 --- a/net/mptcp/subflow.c +++ b/net/mptcp/subflow.c @@ -754,8 +754,6 @@ static bool subflow_hmac_valid(const struct request_sock *req, subflow_req = mptcp_subflow_rsk(req); msk = subflow_req->msk; - if (!msk) - return false; subflow_generate_hmac(READ_ONCE(msk->remote_key), READ_ONCE(msk->local_key), @@ -853,12 +851,8 @@ static struct sock *subflow_syn_recv_sock(const struct sock *sk, } else if (subflow_req->mp_join) { mptcp_get_options(skb, &mp_opt); - if (!(mp_opt.suboptions & OPTION_MPTCP_MPJ_ACK) || - !subflow_hmac_valid(req, &mp_opt) || - !mptcp_can_accept_new_subflow(subflow_req->msk)) { - SUBFLOW_REQ_INC_STATS(req, MPTCP_MIB_JOINACKMAC); + if (!(mp_opt.suboptions & OPTION_MPTCP_MPJ_ACK)) fallback = true; - } } create_child: @@ -908,6 +902,13 @@ create_child: goto dispose_child; } + if (!subflow_hmac_valid(req, &mp_opt) || + !mptcp_can_accept_new_subflow(subflow_req->msk)) { + SUBFLOW_REQ_INC_STATS(req, MPTCP_MIB_JOINACKMAC); + subflow_add_reset_reason(skb, MPTCP_RST_EPROHIBIT); + goto dispose_child; + } + /* move the msk reference ownership to the subflow */ subflow_req->msk = NULL; ctx->conn = (struct sock *)owner; From 6554491b4a770ec0ddd4a13b4420d51685849c3f Mon Sep 17 00:00:00 2001 From: "Matthieu Baerts (NGI0)" Date: Mon, 7 Apr 2025 20:26:32 +0200 Subject: [PATCH 116/136] mptcp: only inc MPJoinAckHMacFailure for HMAC failures commit 21c02e8272bc95ba0dd44943665c669029b42760 upstream. Recently, during a debugging session using local MPTCP connections, I noticed MPJoinAckHMacFailure was not zero on the server side. The counter was in fact incremented when the PM rejected new subflows, because the 'subflow' limit was reached. The fix is easy, simply dissociating the two cases: only the HMAC validation check should increase MPTCP_MIB_JOINACKMAC counter. Fixes: 4cf8b7e48a09 ("subflow: introduce and use mptcp_can_accept_new_subflow()") Cc: stable@vger.kernel.org Reviewed-by: Geliang Tang Signed-off-by: Matthieu Baerts (NGI0) Reviewed-by: Simon Horman Link: https://patch.msgid.link/20250407-net-mptcp-hmac-failure-mib-v1-1-3c9ecd0a3a50@kernel.org Signed-off-by: Jakub Kicinski Signed-off-by: Greg Kroah-Hartman --- net/mptcp/subflow.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/net/mptcp/subflow.c b/net/mptcp/subflow.c index 4011eb6aecd0..4c2aa45c466d 100644 --- a/net/mptcp/subflow.c +++ b/net/mptcp/subflow.c @@ -902,13 +902,17 @@ create_child: goto dispose_child; } - if (!subflow_hmac_valid(req, &mp_opt) || - !mptcp_can_accept_new_subflow(subflow_req->msk)) { + if (!subflow_hmac_valid(req, &mp_opt)) { SUBFLOW_REQ_INC_STATS(req, MPTCP_MIB_JOINACKMAC); subflow_add_reset_reason(skb, MPTCP_RST_EPROHIBIT); goto dispose_child; } + if (!mptcp_can_accept_new_subflow(owner)) { + subflow_add_reset_reason(skb, MPTCP_RST_EPROHIBIT); + goto dispose_child; + } + /* move the msk reference ownership to the subflow */ subflow_req->msk = NULL; ctx->conn = (struct sock *)owner; From 5479a6af3c96f73bec2d2819532b6d6814f52dd6 Mon Sep 17 00:00:00 2001 From: Wentao Liang Date: Wed, 2 Apr 2025 11:16:43 +0800 Subject: [PATCH 117/136] mtd: inftlcore: Add error check for inftl_read_oob() commit d027951dc85cb2e15924c980dc22a6754d100c7c upstream. In INFTL_findwriteunit(), the return value of inftl_read_oob() need to be checked. A proper implementation can be found in INFTL_deleteblock(). The status will be set as SECTOR_IGNORE to break from the while-loop correctly if the inftl_read_oob() fails. Fixes: 8593fbc68b0d ("[MTD] Rework the out of band handling completely") Cc: stable@vger.kernel.org # v2.6+ Signed-off-by: Wentao Liang Signed-off-by: Miquel Raynal Signed-off-by: Greg Kroah-Hartman --- drivers/mtd/inftlcore.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/drivers/mtd/inftlcore.c b/drivers/mtd/inftlcore.c index 9739387cff8c..58c6e1743f5c 100644 --- a/drivers/mtd/inftlcore.c +++ b/drivers/mtd/inftlcore.c @@ -482,10 +482,11 @@ static inline u16 INFTL_findwriteunit(struct INFTLrecord *inftl, unsigned block) silly = MAX_LOOPS; while (thisEUN <= inftl->lastEUN) { - inftl_read_oob(mtd, (thisEUN * inftl->EraseSize) + - blockofs, 8, &retlen, (char *)&bci); - - status = bci.Status | bci.Status1; + if (inftl_read_oob(mtd, (thisEUN * inftl->EraseSize) + + blockofs, 8, &retlen, (char *)&bci) < 0) + status = SECTOR_IGNORE; + else + status = bci.Status | bci.Status1; pr_debug("INFTL: status of block %d in EUN %d is %x\n", block , writeEUN, status); From 52f251dbfb387339879120f5de4c8194a5c4fd82 Mon Sep 17 00:00:00 2001 From: Wentao Liang Date: Wed, 2 Apr 2025 15:56:23 +0800 Subject: [PATCH 118/136] mtd: rawnand: Add status chack in r852_ready() commit b79fe1829975556854665258cf4d2476784a89db upstream. In r852_ready(), the dev get from r852_get_dev() need to be checked. An unstable device should not be ready. A proper implementation can be found in r852_read_byte(). Add a status check and return 0 when it is unstable. Fixes: 50a487e7719c ("mtd: rawnand: Pass a nand_chip object to chip->dev_ready()") Cc: stable@vger.kernel.org # v4.20+ Signed-off-by: Wentao Liang Signed-off-by: Miquel Raynal Signed-off-by: Greg Kroah-Hartman --- drivers/mtd/nand/raw/r852.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/mtd/nand/raw/r852.c b/drivers/mtd/nand/raw/r852.c index ed0cf732d20e..36cfe03cd4ac 100644 --- a/drivers/mtd/nand/raw/r852.c +++ b/drivers/mtd/nand/raw/r852.c @@ -387,6 +387,9 @@ static int r852_wait(struct nand_chip *chip) static int r852_ready(struct nand_chip *chip) { struct r852_device *dev = r852_get_dev(nand_to_mtd(chip)); + if (dev->card_unstable) + return 0; + return !(r852_read_reg(dev, R852_CARD_STA) & R852_CARD_STA_BUSY); } From eec737e17e5567e08148550a7f1d94d495b9fb17 Mon Sep 17 00:00:00 2001 From: Keir Fraser Date: Wed, 26 Mar 2025 11:04:47 +0000 Subject: [PATCH 119/136] arm64: mops: Do not dereference src reg for a set operation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit commit a13bfa4fe0d6949cea14718df2d1fe84c38cd113 upstream. The source register is not used for SET* and reading it can result in a UBSAN out-of-bounds array access error, specifically when the MOPS exception is taken from a SET* sequence with XZR (reg 31) as the source. Architecturally this is the only case where a src/dst/size field in the ESR can be reported as 31. Prior to 2de451a329cf662b the code in do_el0_mops() was benign as the use of pt_regs_read_reg() prevented the out-of-bounds access. Fixes: 2de451a329cf ("KVM: arm64: Add handler for MOPS exceptions") Cc: # 6.12.x Cc: Kristina Martsenko Cc: Will Deacon Cc: stable@vger.kernel.org Reviewed-by: Marc Zyngier Signed-off-by: Keir Fraser Reviewed-by: Kristina Martšenko Acked-by: Mark Rutland Link: https://lore.kernel.org/r/20250326110448.3792396-1-keirf@google.com Signed-off-by: Catalin Marinas Signed-off-by: Greg Kroah-Hartman --- arch/arm64/include/asm/traps.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/arm64/include/asm/traps.h b/arch/arm64/include/asm/traps.h index d780d1bd2eac..82cf1f879c61 100644 --- a/arch/arm64/include/asm/traps.h +++ b/arch/arm64/include/asm/traps.h @@ -109,10 +109,9 @@ static inline void arm64_mops_reset_regs(struct user_pt_regs *regs, unsigned lon int dstreg = ESR_ELx_MOPS_ISS_DESTREG(esr); int srcreg = ESR_ELx_MOPS_ISS_SRCREG(esr); int sizereg = ESR_ELx_MOPS_ISS_SIZEREG(esr); - unsigned long dst, src, size; + unsigned long dst, size; dst = regs->regs[dstreg]; - src = regs->regs[srcreg]; size = regs->regs[sizereg]; /* @@ -129,6 +128,7 @@ static inline void arm64_mops_reset_regs(struct user_pt_regs *regs, unsigned lon } } else { /* CPY* instruction */ + unsigned long src = regs->regs[srcreg]; if (!(option_a ^ wrong_option)) { /* Format is from Option B */ if (regs->pstate & PSR_N_BIT) { From 21c5124304242170f93842c186ffa6fda682121b Mon Sep 17 00:00:00 2001 From: Ninad Malwade Date: Thu, 6 Feb 2025 22:40:34 +0000 Subject: [PATCH 120/136] arm64: tegra: Remove the Orin NX/Nano suspend key commit bb8a3ad25f098b6ea9b1d0f522427b4ad53a7bba upstream. As per the Orin Nano Dev Kit schematic, GPIO_G.02 is not available on this device family. It should not be used at all on Orin NX/Nano. Having this unused pin mapped as the suspend key can lead to unpredictable behavior for low power modes. Orin NX/Nano uses GPIO_EE.04 as both a "power" button and a "suspend" button. However, we cannot have two gpio-keys mapped to the same GPIO. Therefore remove the "suspend" key. Cc: stable@vger.kernel.org Fixes: e63472eda5ea ("arm64: tegra: Support Jetson Orin NX reference platform") Signed-off-by: Ninad Malwade Signed-off-by: Ivy Huang Link: https://lore.kernel.org/r/20250206224034.3691397-1-yijuh@nvidia.com Signed-off-by: Thierry Reding Signed-off-by: Greg Kroah-Hartman --- arch/arm64/boot/dts/nvidia/tegra234-p3768-0000+p3767.dtsi | 7 ------- 1 file changed, 7 deletions(-) diff --git a/arch/arm64/boot/dts/nvidia/tegra234-p3768-0000+p3767.dtsi b/arch/arm64/boot/dts/nvidia/tegra234-p3768-0000+p3767.dtsi index 19340d13f789..41821354bbda 100644 --- a/arch/arm64/boot/dts/nvidia/tegra234-p3768-0000+p3767.dtsi +++ b/arch/arm64/boot/dts/nvidia/tegra234-p3768-0000+p3767.dtsi @@ -227,13 +227,6 @@ wakeup-event-action = ; wakeup-source; }; - - key-suspend { - label = "Suspend"; - gpios = <&gpio TEGRA234_MAIN_GPIO(G, 2) GPIO_ACTIVE_LOW>; - linux,input-type = ; - linux,code = ; - }; }; fan: pwm-fan { From 1dd288783dcb113982352f8a7dd38fe75791b9ed Mon Sep 17 00:00:00 2001 From: Zhenhua Huang Date: Fri, 21 Mar 2025 15:00:19 +0800 Subject: [PATCH 121/136] arm64: mm: Correct the update of max_pfn commit 89f43e1ce6f60d4f44399059595ac47f7a90a393 upstream. Hotplugged memory can be smaller than the original memory. For example, on my target: root@genericarmv8:~# cat /sys/kernel/debug/memblock/memory 0: 0x0000000064005000..0x0000000064023fff 0 NOMAP 1: 0x0000000064400000..0x00000000647fffff 0 NOMAP 2: 0x0000000068000000..0x000000006fffffff 0 DRV_MNG 3: 0x0000000088800000..0x0000000094ffefff 0 NONE 4: 0x0000000094fff000..0x0000000094ffffff 0 NOMAP max_pfn will affect read_page_owner. Therefore, it should first compare and then select the larger value for max_pfn. Fixes: 8fac67ca236b ("arm64: mm: update max_pfn after memory hotplug") Cc: # 6.1.x Signed-off-by: Zhenhua Huang Acked-by: David Hildenbrand Reviewed-by: Anshuman Khandual Link: https://lore.kernel.org/r/20250321070019.1271859-1-quic_zhenhuah@quicinc.com Signed-off-by: Catalin Marinas Signed-off-by: Greg Kroah-Hartman --- arch/arm64/mm/mmu.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/arch/arm64/mm/mmu.c b/arch/arm64/mm/mmu.c index e59c628c93f2..9bcd51fd67d4 100644 --- a/arch/arm64/mm/mmu.c +++ b/arch/arm64/mm/mmu.c @@ -1360,7 +1360,8 @@ int arch_add_memory(int nid, u64 start, u64 size, __remove_pgd_mapping(swapper_pg_dir, __phys_to_virt(start), size); else { - max_pfn = PFN_UP(start + size); + /* Address of hotplugged memory can be smaller */ + max_pfn = max(max_pfn, PFN_UP(start + size)); max_low_pfn = max_pfn; } From ac45d49df9dc606d362fabc523696cd5ebd569a5 Mon Sep 17 00:00:00 2001 From: Chen-Yu Tsai Date: Wed, 8 Jan 2025 16:34:22 +0800 Subject: [PATCH 122/136] arm64: dts: mediatek: mt8173: Fix disp-pwm compatible string commit 46ad36002088eff8fc5cae200aa42ae9f9310ddd upstream. The MT8173 disp-pwm device should have only one compatible string, based on the following DT validation error: arch/arm64/boot/dts/mediatek/mt8173-elm.dtb: pwm@1401e000: compatible: 'oneOf' conditional failed, one must be fixed: ['mediatek,mt8173-disp-pwm', 'mediatek,mt6595-disp-pwm'] is too long 'mediatek,mt8173-disp-pwm' is not one of ['mediatek,mt6795-disp-pwm', 'mediatek,mt8167-disp-pwm'] 'mediatek,mt8173-disp-pwm' is not one of ['mediatek,mt8186-disp-pwm', 'mediatek,mt8188-disp-pwm', 'mediatek,mt8192-disp-pwm', 'mediatek,mt8195-disp-pwm', 'mediatek,mt8365-disp-pwm'] 'mediatek,mt8173-disp-pwm' was expected 'mediatek,mt8183-disp-pwm' was expected from schema $id: http://devicetree.org/schemas/pwm/mediatek,pwm-disp.yaml# arch/arm64/boot/dts/mediatek/mt8173-elm.dtb: pwm@1401f000: compatible: 'oneOf' conditional failed, one must be fixed: ['mediatek,mt8173-disp-pwm', 'mediatek,mt6595-disp-pwm'] is too long 'mediatek,mt8173-disp-pwm' is not one of ['mediatek,mt6795-disp-pwm', 'mediatek,mt8167-disp-pwm'] 'mediatek,mt8173-disp-pwm' is not one of ['mediatek,mt8186-disp-pwm', 'mediatek,mt8188-disp-pwm', 'mediatek,mt8192-disp-pwm', 'mediatek,mt8195-disp-pwm', 'mediatek,mt8365-disp-pwm'] 'mediatek,mt8173-disp-pwm' was expected 'mediatek,mt8183-disp-pwm' was expected from schema $id: http://devicetree.org/schemas/pwm/mediatek,pwm-disp.yaml# Drop the extra "mediatek,mt6595-disp-pwm" compatible string. Fixes: 61aee9342514 ("arm64: dts: mt8173: add MT8173 display PWM driver support node") Cc: YH Huang Cc: stable@vger.kernel.org # v4.5+ Signed-off-by: Chen-Yu Tsai Reviewed-by: AngeloGioacchino Del Regno Link: https://lore.kernel.org/r/20250108083424.2732375-2-wenst@chromium.org Signed-off-by: AngeloGioacchino Del Regno Signed-off-by: Greg Kroah-Hartman --- arch/arm64/boot/dts/mediatek/mt8173.dtsi | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/arch/arm64/boot/dts/mediatek/mt8173.dtsi b/arch/arm64/boot/dts/mediatek/mt8173.dtsi index 3458be7f7f61..f49ec7495906 100644 --- a/arch/arm64/boot/dts/mediatek/mt8173.dtsi +++ b/arch/arm64/boot/dts/mediatek/mt8173.dtsi @@ -1255,8 +1255,7 @@ }; pwm0: pwm@1401e000 { - compatible = "mediatek,mt8173-disp-pwm", - "mediatek,mt6595-disp-pwm"; + compatible = "mediatek,mt8173-disp-pwm"; reg = <0 0x1401e000 0 0x1000>; #pwm-cells = <2>; clocks = <&mmsys CLK_MM_DISP_PWM026M>, @@ -1266,8 +1265,7 @@ }; pwm1: pwm@1401f000 { - compatible = "mediatek,mt8173-disp-pwm", - "mediatek,mt6595-disp-pwm"; + compatible = "mediatek,mt8173-disp-pwm"; reg = <0 0x1401f000 0 0x1000>; #pwm-cells = <2>; clocks = <&mmsys CLK_MM_DISP_PWM126M>, From a3b36c9da305c206833b5b116f7da51e3a5bba9c Mon Sep 17 00:00:00 2001 From: Peter Griffin Date: Mon, 6 Jan 2025 14:57:46 +0000 Subject: [PATCH 123/136] arm64: dts: exynos: gs101: disable pinctrl_gsacore node commit 168e24966f10ff635b0ec9728aa71833bf850ee5 upstream. gsacore registers are not accessible from normal world. Disable this node, so that the suspend/resume callbacks in the pinctrl driver don't cause a Serror attempting to access the registers. Fixes: ea89fdf24fd9 ("arm64: dts: exynos: google: Add initial Google gs101 SoC support") Signed-off-by: Peter Griffin To: Rob Herring To: Krzysztof Kozlowski To: Conor Dooley To: Alim Akhtar Cc: linux-arm-kernel@lists.infradead.org Cc: linux-samsung-soc@vger.kernel.org Cc: devicetree@vger.kernel.org Cc: linux-kernel@vger.kernel.org Cc: tudor.ambarus@linaro.org Cc: andre.draszik@linaro.org Cc: kernel-team@android.com Cc: willmcvicker@google.com Cc: stable@vger.kernel.org Link: https://lore.kernel.org/r/20250106-contrib-pg-pinctrl_gsacore_disable-v1-1-d3fc88a48aed@linaro.org Signed-off-by: Krzysztof Kozlowski Signed-off-by: Greg Kroah-Hartman --- arch/arm64/boot/dts/exynos/google/gs101.dtsi | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm64/boot/dts/exynos/google/gs101.dtsi b/arch/arm64/boot/dts/exynos/google/gs101.dtsi index 302c5beb224a..b8f8255f840b 100644 --- a/arch/arm64/boot/dts/exynos/google/gs101.dtsi +++ b/arch/arm64/boot/dts/exynos/google/gs101.dtsi @@ -1451,6 +1451,7 @@ /* TODO: update once support for this CMU exists */ clocks = <0>; clock-names = "pclk"; + status = "disabled"; }; cmu_top: clock-controller@1e080000 { From 61a5c565fd2442d3128f3bab5f022658adc3a4e6 Mon Sep 17 00:00:00 2001 From: Herve Codina Date: Wed, 22 Jan 2025 10:19:14 +0100 Subject: [PATCH 124/136] backlight: led_bl: Hold led_access lock when calling led_sysfs_disable() commit 276822a00db3c1061382b41e72cafc09d6a0ec30 upstream. Lockdep detects the following issue on led-backlight removal: [ 142.315935] ------------[ cut here ]------------ [ 142.315954] WARNING: CPU: 2 PID: 292 at drivers/leds/led-core.c:455 led_sysfs_enable+0x54/0x80 ... [ 142.500725] Call trace: [ 142.503176] led_sysfs_enable+0x54/0x80 (P) [ 142.507370] led_bl_remove+0x80/0xa8 [led_bl] [ 142.511742] platform_remove+0x30/0x58 [ 142.515501] device_remove+0x54/0x90 ... Indeed, led_sysfs_enable() has to be called with the led_access lock held. Hold the lock when calling led_sysfs_disable(). Fixes: ae232e45acf9 ("backlight: add led-backlight driver") Cc: stable@vger.kernel.org Signed-off-by: Herve Codina Link: https://lore.kernel.org/r/20250122091914.309533-1-herve.codina@bootlin.com Signed-off-by: Lee Jones Signed-off-by: Greg Kroah-Hartman --- drivers/video/backlight/led_bl.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/video/backlight/led_bl.c b/drivers/video/backlight/led_bl.c index c7aefcd6e4e3..782600601845 100644 --- a/drivers/video/backlight/led_bl.c +++ b/drivers/video/backlight/led_bl.c @@ -229,8 +229,11 @@ static void led_bl_remove(struct platform_device *pdev) backlight_device_unregister(bl); led_bl_power_off(priv); - for (i = 0; i < priv->nb_leds; i++) + for (i = 0; i < priv->nb_leds; i++) { + mutex_lock(&priv->leds[i]->led_access); led_sysfs_enable(priv->leds[i]); + mutex_unlock(&priv->leds[i]->led_access); + } } static const struct of_device_id led_bl_of_match[] = { From 601db4e8bfe86ef32c498d62f57c2a9fc4d82b4c Mon Sep 17 00:00:00 2001 From: Filipe Manana Date: Wed, 5 Mar 2025 16:52:26 +0000 Subject: [PATCH 125/136] btrfs: fix non-empty delayed iputs list on unmount due to compressed write workers commit 4c782247b89376a83fa132f7d45d6977edae0629 upstream. At close_ctree() after we have ran delayed iputs either through explicitly calling btrfs_run_delayed_iputs() or later during the call to btrfs_commit_super() or btrfs_error_commit_super(), we assert that the delayed iputs list is empty. When we have compressed writes this assertion may fail because delayed iputs may have been added to the list after we last ran delayed iputs. This happens like this: 1) We have a compressed write bio executing; 2) We enter close_ctree() and flush the fs_info->endio_write_workers queue which is the queue used for running ordered extent completion; 3) The compressed write bio finishes and enters btrfs_finish_compressed_write_work(), where it calls btrfs_finish_ordered_extent() which in turn calls btrfs_queue_ordered_fn(), which queues a work item in the fs_info->endio_write_workers queue that we have flushed before; 4) At close_ctree() we proceed, run all existing delayed iputs and call btrfs_commit_super() (which also runs delayed iputs), but before we run the following assertion below: ASSERT(list_empty(&fs_info->delayed_iputs)) A delayed iput is added by the step below... 5) The ordered extent completion job queued in step 3 runs and results in creating a delayed iput when dropping the last reference of the ordered extent (a call to btrfs_put_ordered_extent() made from btrfs_finish_one_ordered()); 6) At this point the delayed iputs list is not empty, so the assertion at close_ctree() fails. Fix this by flushing the fs_info->compressed_write_workers queue at close_ctree() before flushing the fs_info->endio_write_workers queue, respecting the queue dependency as the later is responsible for the execution of ordered extent completion. CC: stable@vger.kernel.org # 5.15+ Reviewed-by: Qu Wenruo Signed-off-by: Filipe Manana Signed-off-by: David Sterba Signed-off-by: Greg Kroah-Hartman --- fs/btrfs/disk-io.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c index 563f106774e5..19e5f8eaae77 100644 --- a/fs/btrfs/disk-io.c +++ b/fs/btrfs/disk-io.c @@ -4274,6 +4274,18 @@ void __cold close_ctree(struct btrfs_fs_info *fs_info) */ btrfs_flush_workqueue(fs_info->delalloc_workers); + /* + * When finishing a compressed write bio we schedule a work queue item + * to finish an ordered extent - btrfs_finish_compressed_write_work() + * calls btrfs_finish_ordered_extent() which in turns does a call to + * btrfs_queue_ordered_fn(), and that queues the ordered extent + * completion either in the endio_write_workers work queue or in the + * fs_info->endio_freespace_worker work queue. We flush those queues + * below, so before we flush them we must flush this queue for the + * workers of compressed writes. + */ + flush_workqueue(fs_info->compressed_write_workers); + /* * After we parked the cleaner kthread, ordered extents may have * completed and created new delayed iputs. If one of the async reclaim From b9af27d020e4fbc20529cfde494b2bb77ec39a4c Mon Sep 17 00:00:00 2001 From: Filipe Manana Date: Tue, 11 Mar 2025 15:50:50 +0000 Subject: [PATCH 126/136] btrfs: tests: fix chunk map leak after failure to add it to the tree commit 009ca358486ded9b4822eddb924009b6848d7271 upstream. If we fail to add the chunk map to the fs mapping tree we exit test_rmap_block() without freeing the chunk map. Fix this by adding a call to btrfs_free_chunk_map() before exiting the test function if the call to btrfs_add_chunk_map() failed. Fixes: 7dc66abb5a47 ("btrfs: use a dedicated data structure for chunk maps") CC: stable@vger.kernel.org # 6.12+ Reviewed-by: Boris Burkov Signed-off-by: Filipe Manana Reviewed-by: David Sterba Signed-off-by: David Sterba Signed-off-by: Greg Kroah-Hartman --- fs/btrfs/tests/extent-map-tests.c | 1 + 1 file changed, 1 insertion(+) diff --git a/fs/btrfs/tests/extent-map-tests.c b/fs/btrfs/tests/extent-map-tests.c index 56e61ac1cc64..609bb6c9c087 100644 --- a/fs/btrfs/tests/extent-map-tests.c +++ b/fs/btrfs/tests/extent-map-tests.c @@ -1045,6 +1045,7 @@ static int test_rmap_block(struct btrfs_fs_info *fs_info, ret = btrfs_add_chunk_map(fs_info, map); if (ret) { test_err("error adding chunk map to mapping tree"); + btrfs_free_chunk_map(map); goto out_free; } From 380ba38801eb32d76e283469dad8c2a68e0a2ee2 Mon Sep 17 00:00:00 2001 From: Johannes Thumshirn Date: Mon, 17 Mar 2025 12:24:58 +0100 Subject: [PATCH 127/136] btrfs: zoned: fix zone activation with missing devices commit 2bbc4a45e5eb6b868357c1045bf6f38f6ba576e0 upstream. If btrfs_zone_activate() is called with a filesystem that has missing devices (e.g. a RAID file system mounted in degraded mode) it is accessing the btrfs_device::zone_info pointer, which will not be set if the device in question is missing. Check if the device is present (by checking if it has a valid block device pointer associated) and if not, skip zone activation for it. Fixes: f9a912a3c45f ("btrfs: zoned: make zone activation multi stripe capable") CC: stable@vger.kernel.org # 6.1+ Reviewed-by: Naohiro Aota Reviewed-by: Anand Jain Signed-off-by: Johannes Thumshirn Reviewed-by: David Sterba Signed-off-by: David Sterba Signed-off-by: Greg Kroah-Hartman --- fs/btrfs/zoned.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/fs/btrfs/zoned.c b/fs/btrfs/zoned.c index 69d03feea4e0..9b834a1b8410 100644 --- a/fs/btrfs/zoned.c +++ b/fs/btrfs/zoned.c @@ -2107,6 +2107,9 @@ bool btrfs_zone_activate(struct btrfs_block_group *block_group) physical = map->stripes[i].physical; zinfo = device->zone_info; + if (!device->bdev) + continue; + if (zinfo->max_active_zones == 0) continue; From 327e6b8b2816e0599c62ef684841ba3f04f148f9 Mon Sep 17 00:00:00 2001 From: Johannes Thumshirn Date: Mon, 17 Mar 2025 12:24:59 +0100 Subject: [PATCH 128/136] btrfs: zoned: fix zone finishing with missing devices commit 35fec1089ebb5617f85884d3fa6a699ce6337a75 upstream. If do_zone_finish() is called with a filesystem that has missing devices (e.g. a RAID file system mounted in degraded mode) it is accessing the btrfs_device::zone_info pointer, which will not be set if the device in question is missing. Check if the device is present (by checking if it has a valid block device pointer associated) and if not, skip zone finishing for it. Fixes: 4dcbb8ab31c1 ("btrfs: zoned: make zone finishing multi stripe capable") CC: stable@vger.kernel.org # 6.1+ Reviewed-by: Naohiro Aota Reviewed-by: Anand Jain Signed-off-by: Johannes Thumshirn Reviewed-by: David Sterba Signed-off-by: David Sterba Signed-off-by: Greg Kroah-Hartman --- fs/btrfs/zoned.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/fs/btrfs/zoned.c b/fs/btrfs/zoned.c index 9b834a1b8410..2bb7e32ad945 100644 --- a/fs/btrfs/zoned.c +++ b/fs/btrfs/zoned.c @@ -2271,6 +2271,9 @@ static int do_zone_finish(struct btrfs_block_group *block_group, bool fully_writ struct btrfs_zoned_device_info *zinfo = device->zone_info; unsigned int nofs_flags; + if (!device->bdev) + continue; + if (zinfo->max_active_zones == 0) continue; From b8b41eac70546c19e5812330634457110378899d Mon Sep 17 00:00:00 2001 From: Nicolin Chen Date: Thu, 27 Feb 2025 12:07:29 -0800 Subject: [PATCH 129/136] iommufd: Fix uninitialized rc in iommufd_access_rw() commit a05df03a88bc1088be8e9d958f208d6484691e43 upstream. Reported by smatch: drivers/iommu/iommufd/device.c:1392 iommufd_access_rw() error: uninitialized symbol 'rc'. Fixes: 8d40205f6093 ("iommufd: Add kAPI toward external drivers for kernel access") Link: https://patch.msgid.link/r/20250227200729.85030-1-nicolinc@nvidia.com Cc: stable@vger.kernel.org Reported-by: kernel test robot Reported-by: Dan Carpenter Closes: https://lore.kernel.org/r/202502271339.a2nWr9UA-lkp@intel.com/ [nicolinc: can't find an original report but only in "old smatch warnings"] Signed-off-by: Nicolin Chen Signed-off-by: Jason Gunthorpe Signed-off-by: Greg Kroah-Hartman --- drivers/iommu/iommufd/device.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/iommu/iommufd/device.c b/drivers/iommu/iommufd/device.c index 5fd3dd420290..19a94999708b 100644 --- a/drivers/iommu/iommufd/device.c +++ b/drivers/iommu/iommufd/device.c @@ -1127,7 +1127,7 @@ int iommufd_access_rw(struct iommufd_access *access, unsigned long iova, struct io_pagetable *iopt; struct iopt_area *area; unsigned long last_iova; - int rc; + int rc = -EINVAL; if (!length) return -EINVAL; From e5dd974d6e00704553308ef1a88659f8dcfb39d4 Mon Sep 17 00:00:00 2001 From: Nicolin Chen Date: Mon, 7 Apr 2025 13:19:08 -0700 Subject: [PATCH 130/136] iommu/tegra241-cmdqv: Fix warnings due to dmam_free_coherent() commit 767e22001dfce64cc03b7def1562338591ab6031 upstream. Two WARNINGs are observed when SMMU driver rolls back upon failure: arm-smmu-v3.9.auto: Failed to register iommu arm-smmu-v3.9.auto: probe with driver arm-smmu-v3 failed with error -22 ------------[ cut here ]------------ WARNING: CPU: 5 PID: 1 at kernel/dma/mapping.c:74 dmam_free_coherent+0xc0/0xd8 Call trace: dmam_free_coherent+0xc0/0xd8 (P) tegra241_vintf_free_lvcmdq+0x74/0x188 tegra241_cmdqv_remove_vintf+0x60/0x148 tegra241_cmdqv_remove+0x48/0xc8 arm_smmu_impl_remove+0x28/0x60 devm_action_release+0x1c/0x40 ------------[ cut here ]------------ 128 pages are still in use! WARNING: CPU: 16 PID: 1 at mm/page_alloc.c:6902 free_contig_range+0x18c/0x1c8 Call trace: free_contig_range+0x18c/0x1c8 (P) cma_release+0x154/0x2f0 dma_free_contiguous+0x38/0xa0 dma_direct_free+0x10c/0x248 dma_free_attrs+0x100/0x290 dmam_free_coherent+0x78/0xd8 tegra241_vintf_free_lvcmdq+0x74/0x160 tegra241_cmdqv_remove+0x98/0x198 arm_smmu_impl_remove+0x28/0x60 devm_action_release+0x1c/0x40 This is because the LVCMDQ queue memory are managed by devres, while that dmam_free_coherent() is called in the context of devm_action_release(). Jason pointed out that "arm_smmu_impl_probe() has mis-ordered the devres callbacks if ops->device_remove() is going to be manually freeing things that probe allocated": https://lore.kernel.org/linux-iommu/20250407174408.GB1722458@nvidia.com/ In fact, tegra241_cmdqv_init_structures() only allocates memory resources which means any failure that it generates would be similar to -ENOMEM, so there is no point in having that "falling back to standard SMMU" routine, as the standard SMMU would likely fail to allocate memory too. Remove the unwind part in tegra241_cmdqv_init_structures(), and return a proper error code to ask SMMU driver to call tegra241_cmdqv_remove() via impl_ops->device_remove(). Then, drop tegra241_vintf_free_lvcmdq() since devres will take care of that. Fixes: 483e0bd8883a ("iommu/tegra241-cmdqv: Do not allocate vcmdq until dma_set_mask_and_coherent") Cc: stable@vger.kernel.org Suggested-by: Jason Gunthorpe Signed-off-by: Nicolin Chen Reviewed-by: Jason Gunthorpe Link: https://lore.kernel.org/r/20250407201908.172225-1-nicolinc@nvidia.com Signed-off-by: Joerg Roedel Signed-off-by: Greg Kroah-Hartman --- .../iommu/arm/arm-smmu-v3/tegra241-cmdqv.c | 32 +++---------------- 1 file changed, 5 insertions(+), 27 deletions(-) diff --git a/drivers/iommu/arm/arm-smmu-v3/tegra241-cmdqv.c b/drivers/iommu/arm/arm-smmu-v3/tegra241-cmdqv.c index d525ab43a4ae..dd7d030d2e89 100644 --- a/drivers/iommu/arm/arm-smmu-v3/tegra241-cmdqv.c +++ b/drivers/iommu/arm/arm-smmu-v3/tegra241-cmdqv.c @@ -487,17 +487,6 @@ static int tegra241_cmdqv_hw_reset(struct arm_smmu_device *smmu) /* VCMDQ Resource Helpers */ -static void tegra241_vcmdq_free_smmu_cmdq(struct tegra241_vcmdq *vcmdq) -{ - struct arm_smmu_queue *q = &vcmdq->cmdq.q; - size_t nents = 1 << q->llq.max_n_shift; - size_t qsz = nents << CMDQ_ENT_SZ_SHIFT; - - if (!q->base) - return; - dmam_free_coherent(vcmdq->cmdqv->smmu.dev, qsz, q->base, q->base_dma); -} - static int tegra241_vcmdq_alloc_smmu_cmdq(struct tegra241_vcmdq *vcmdq) { struct arm_smmu_device *smmu = &vcmdq->cmdqv->smmu; @@ -560,7 +549,8 @@ static void tegra241_vintf_free_lvcmdq(struct tegra241_vintf *vintf, u16 lidx) struct tegra241_vcmdq *vcmdq = vintf->lvcmdqs[lidx]; char header[64]; - tegra241_vcmdq_free_smmu_cmdq(vcmdq); + /* Note that the lvcmdq queue memory space is managed by devres */ + tegra241_vintf_deinit_lvcmdq(vintf, lidx); dev_dbg(vintf->cmdqv->dev, @@ -768,13 +758,13 @@ static int tegra241_cmdqv_init_structures(struct arm_smmu_device *smmu) vintf = kzalloc(sizeof(*vintf), GFP_KERNEL); if (!vintf) - goto out_fallback; + return -ENOMEM; /* Init VINTF0 for in-kernel use */ ret = tegra241_cmdqv_init_vintf(cmdqv, 0, vintf); if (ret) { dev_err(cmdqv->dev, "failed to init vintf0: %d\n", ret); - goto free_vintf; + return ret; } /* Preallocate logical VCMDQs to VINTF0 */ @@ -783,24 +773,12 @@ static int tegra241_cmdqv_init_structures(struct arm_smmu_device *smmu) vcmdq = tegra241_vintf_alloc_lvcmdq(vintf, lidx); if (IS_ERR(vcmdq)) - goto free_lvcmdq; + return PTR_ERR(vcmdq); } /* Now, we are ready to run all the impl ops */ smmu->impl_ops = &tegra241_cmdqv_impl_ops; return 0; - -free_lvcmdq: - for (lidx--; lidx >= 0; lidx--) - tegra241_vintf_free_lvcmdq(vintf, lidx); - tegra241_cmdqv_deinit_vintf(cmdqv, vintf->idx); -free_vintf: - kfree(vintf); -out_fallback: - dev_info(smmu->impl_dev, "Falling back to standard SMMU CMDQ\n"); - smmu->options &= ~ARM_SMMU_OPT_TEGRA241_CMDQV; - tegra241_cmdqv_remove(smmu); - return 0; } #ifdef CONFIG_IOMMU_DEBUGFS From c95a438d2c37748541b696053cd5c72042c838ad Mon Sep 17 00:00:00 2001 From: Sean Christopherson Date: Wed, 19 Mar 2025 10:20:59 +0800 Subject: [PATCH 131/136] iommu/vt-d: Put IRTE back into posted MSI mode if vCPU posting is disabled commit 2454823e97a63d85a6b215905f71e5a06324eab7 upstream. Add a helper to take care of reconfiguring an IRTE to deliver IRQs to the host, i.e. not to a vCPU, and use the helper when an IRTE's vCPU affinity is nullified, i.e. when KVM puts an IRTE back into "host" mode. Because posted MSIs use an ephemeral IRTE, using modify_irte() puts the IRTE into full remapped mode, i.e. unintentionally disables posted MSIs on the IRQ. Fixes: ed1e48ea4370 ("iommu/vt-d: Enable posted mode for device MSIs") Cc: stable@vger.kernel.org Cc: Thomas Gleixner Cc: Jacob Pan Signed-off-by: Sean Christopherson Link: https://lore.kernel.org/r/20250315025135.2365846-2-seanjc@google.com Signed-off-by: Lu Baolu Signed-off-by: Joerg Roedel Signed-off-by: Greg Kroah-Hartman --- drivers/iommu/intel/irq_remapping.c | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/drivers/iommu/intel/irq_remapping.c b/drivers/iommu/intel/irq_remapping.c index 7a6d188e3bea..6166ad999b0e 100644 --- a/drivers/iommu/intel/irq_remapping.c +++ b/drivers/iommu/intel/irq_remapping.c @@ -1173,7 +1173,17 @@ static void intel_ir_reconfigure_irte_posted(struct irq_data *irqd) static inline void intel_ir_reconfigure_irte_posted(struct irq_data *irqd) {} #endif -static void intel_ir_reconfigure_irte(struct irq_data *irqd, bool force) +static void __intel_ir_reconfigure_irte(struct irq_data *irqd, bool force_host) +{ + struct intel_ir_data *ir_data = irqd->chip_data; + + if (ir_data->irq_2_iommu.posted_msi) + intel_ir_reconfigure_irte_posted(irqd); + else if (force_host || ir_data->irq_2_iommu.mode == IRQ_REMAPPING) + modify_irte(&ir_data->irq_2_iommu, &ir_data->irte_entry); +} + +static void intel_ir_reconfigure_irte(struct irq_data *irqd, bool force_host) { struct intel_ir_data *ir_data = irqd->chip_data; struct irte *irte = &ir_data->irte_entry; @@ -1186,10 +1196,7 @@ static void intel_ir_reconfigure_irte(struct irq_data *irqd, bool force) irte->vector = cfg->vector; irte->dest_id = IRTE_DEST(cfg->dest_apicid); - if (ir_data->irq_2_iommu.posted_msi) - intel_ir_reconfigure_irte_posted(irqd); - else if (force || ir_data->irq_2_iommu.mode == IRQ_REMAPPING) - modify_irte(&ir_data->irq_2_iommu, irte); + __intel_ir_reconfigure_irte(irqd, force_host); } /* @@ -1244,7 +1251,7 @@ static int intel_ir_set_vcpu_affinity(struct irq_data *data, void *info) /* stop posting interrupts, back to the default mode */ if (!vcpu_pi_info) { - modify_irte(&ir_data->irq_2_iommu, &ir_data->irte_entry); + __intel_ir_reconfigure_irte(data, true); } else { struct irte irte_pi; From e953e11123aa703241418ee69a82e5538e58eaff Mon Sep 17 00:00:00 2001 From: Sean Christopherson Date: Wed, 19 Mar 2025 10:21:00 +0800 Subject: [PATCH 132/136] iommu/vt-d: Don't clobber posted vCPU IRTE when host IRQ affinity changes commit 688124cc541f60d26a7547f45637b23dada4e527 upstream. Don't overwrite an IRTE that is posting IRQs to a vCPU with a posted MSI entry if the host IRQ affinity happens to change. If/when the IRTE is reverted back to "host mode", it will be reconfigured as a posted MSI or remapped entry as appropriate. Drop the "mode" field, which doesn't differentiate between posted MSIs and posted vCPUs, in favor of a dedicated posted_vcpu flag. Note! The two posted_{msi,vcpu} flags are intentionally not mutually exclusive; an IRTE can transition between posted MSI and posted vCPU. Fixes: ed1e48ea4370 ("iommu/vt-d: Enable posted mode for device MSIs") Cc: stable@vger.kernel.org Cc: Thomas Gleixner Cc: Jacob Pan Signed-off-by: Sean Christopherson Link: https://lore.kernel.org/r/20250315025135.2365846-3-seanjc@google.com Signed-off-by: Lu Baolu Signed-off-by: Joerg Roedel Signed-off-by: Greg Kroah-Hartman --- drivers/iommu/intel/irq_remapping.c | 25 +++++++++++++++---------- 1 file changed, 15 insertions(+), 10 deletions(-) diff --git a/drivers/iommu/intel/irq_remapping.c b/drivers/iommu/intel/irq_remapping.c index 6166ad999b0e..8093ba109d65 100644 --- a/drivers/iommu/intel/irq_remapping.c +++ b/drivers/iommu/intel/irq_remapping.c @@ -26,11 +26,6 @@ #include "../iommu-pages.h" #include "cap_audit.h" -enum irq_mode { - IRQ_REMAPPING, - IRQ_POSTING, -}; - struct ioapic_scope { struct intel_iommu *iommu; unsigned int id; @@ -50,8 +45,8 @@ struct irq_2_iommu { u16 irte_index; u16 sub_handle; u8 irte_mask; - enum irq_mode mode; bool posted_msi; + bool posted_vcpu; }; struct intel_ir_data { @@ -139,7 +134,6 @@ static int alloc_irte(struct intel_iommu *iommu, irq_iommu->irte_index = index; irq_iommu->sub_handle = 0; irq_iommu->irte_mask = mask; - irq_iommu->mode = IRQ_REMAPPING; } raw_spin_unlock_irqrestore(&irq_2_ir_lock, flags); @@ -194,8 +188,6 @@ static int modify_irte(struct irq_2_iommu *irq_iommu, rc = qi_flush_iec(iommu, index, 0); - /* Update iommu mode according to the IRTE mode */ - irq_iommu->mode = irte->pst ? IRQ_POSTING : IRQ_REMAPPING; raw_spin_unlock_irqrestore(&irq_2_ir_lock, flags); return rc; @@ -1177,9 +1169,18 @@ static void __intel_ir_reconfigure_irte(struct irq_data *irqd, bool force_host) { struct intel_ir_data *ir_data = irqd->chip_data; + /* + * Don't modify IRTEs for IRQs that are being posted to vCPUs if the + * host CPU affinity changes. + */ + if (ir_data->irq_2_iommu.posted_vcpu && !force_host) + return; + + ir_data->irq_2_iommu.posted_vcpu = false; + if (ir_data->irq_2_iommu.posted_msi) intel_ir_reconfigure_irte_posted(irqd); - else if (force_host || ir_data->irq_2_iommu.mode == IRQ_REMAPPING) + else modify_irte(&ir_data->irq_2_iommu, &ir_data->irte_entry); } @@ -1274,6 +1275,7 @@ static int intel_ir_set_vcpu_affinity(struct irq_data *data, void *info) irte_pi.pda_h = (vcpu_pi_info->pi_desc_addr >> 32) & ~(-1UL << PDA_HIGH_BIT); + ir_data->irq_2_iommu.posted_vcpu = true; modify_irte(&ir_data->irq_2_iommu, &irte_pi); } @@ -1501,6 +1503,9 @@ static void intel_irq_remapping_deactivate(struct irq_domain *domain, struct intel_ir_data *data = irq_data->chip_data; struct irte entry; + WARN_ON_ONCE(data->irq_2_iommu.posted_vcpu); + data->irq_2_iommu.posted_vcpu = false; + memset(&entry, 0, sizeof(entry)); modify_irte(&data->irq_2_iommu, &entry); } From 6722a0cb818691e63c613fa801d6ccfba3f7d38c Mon Sep 17 00:00:00 2001 From: Lu Baolu Date: Wed, 19 Mar 2025 10:21:01 +0800 Subject: [PATCH 133/136] iommu/vt-d: Fix possible circular locking dependency commit 93ae6e68b6d6b62d92b3a89d1c253d4a1721a1d3 upstream. We have recently seen report of lockdep circular lock dependency warnings on platforms like Skylake and Kabylake: ====================================================== WARNING: possible circular locking dependency detected 6.14.0-rc6-CI_DRM_16276-gca2c04fe76e8+ #1 Not tainted ------------------------------------------------------ swapper/0/1 is trying to acquire lock: ffffffff8360ee48 (iommu_probe_device_lock){+.+.}-{3:3}, at: iommu_probe_device+0x1d/0x70 but task is already holding lock: ffff888102c7efa8 (&device->physical_node_lock){+.+.}-{3:3}, at: intel_iommu_init+0xe75/0x11f0 which lock already depends on the new lock. the existing dependency chain (in reverse order) is: -> #6 (&device->physical_node_lock){+.+.}-{3:3}: __mutex_lock+0xb4/0xe40 mutex_lock_nested+0x1b/0x30 intel_iommu_init+0xe75/0x11f0 pci_iommu_init+0x13/0x70 do_one_initcall+0x62/0x3f0 kernel_init_freeable+0x3da/0x6a0 kernel_init+0x1b/0x200 ret_from_fork+0x44/0x70 ret_from_fork_asm+0x1a/0x30 -> #5 (dmar_global_lock){++++}-{3:3}: down_read+0x43/0x1d0 enable_drhd_fault_handling+0x21/0x110 cpuhp_invoke_callback+0x4c6/0x870 cpuhp_issue_call+0xbf/0x1f0 __cpuhp_setup_state_cpuslocked+0x111/0x320 __cpuhp_setup_state+0xb0/0x220 irq_remap_enable_fault_handling+0x3f/0xa0 apic_intr_mode_init+0x5c/0x110 x86_late_time_init+0x24/0x40 start_kernel+0x895/0xbd0 x86_64_start_reservations+0x18/0x30 x86_64_start_kernel+0xbf/0x110 common_startup_64+0x13e/0x141 -> #4 (cpuhp_state_mutex){+.+.}-{3:3}: __mutex_lock+0xb4/0xe40 mutex_lock_nested+0x1b/0x30 __cpuhp_setup_state_cpuslocked+0x67/0x320 __cpuhp_setup_state+0xb0/0x220 page_alloc_init_cpuhp+0x2d/0x60 mm_core_init+0x18/0x2c0 start_kernel+0x576/0xbd0 x86_64_start_reservations+0x18/0x30 x86_64_start_kernel+0xbf/0x110 common_startup_64+0x13e/0x141 -> #3 (cpu_hotplug_lock){++++}-{0:0}: __cpuhp_state_add_instance+0x4f/0x220 iova_domain_init_rcaches+0x214/0x280 iommu_setup_dma_ops+0x1a4/0x710 iommu_device_register+0x17d/0x260 intel_iommu_init+0xda4/0x11f0 pci_iommu_init+0x13/0x70 do_one_initcall+0x62/0x3f0 kernel_init_freeable+0x3da/0x6a0 kernel_init+0x1b/0x200 ret_from_fork+0x44/0x70 ret_from_fork_asm+0x1a/0x30 -> #2 (&domain->iova_cookie->mutex){+.+.}-{3:3}: __mutex_lock+0xb4/0xe40 mutex_lock_nested+0x1b/0x30 iommu_setup_dma_ops+0x16b/0x710 iommu_device_register+0x17d/0x260 intel_iommu_init+0xda4/0x11f0 pci_iommu_init+0x13/0x70 do_one_initcall+0x62/0x3f0 kernel_init_freeable+0x3da/0x6a0 kernel_init+0x1b/0x200 ret_from_fork+0x44/0x70 ret_from_fork_asm+0x1a/0x30 -> #1 (&group->mutex){+.+.}-{3:3}: __mutex_lock+0xb4/0xe40 mutex_lock_nested+0x1b/0x30 __iommu_probe_device+0x24c/0x4e0 probe_iommu_group+0x2b/0x50 bus_for_each_dev+0x7d/0xe0 iommu_device_register+0xe1/0x260 intel_iommu_init+0xda4/0x11f0 pci_iommu_init+0x13/0x70 do_one_initcall+0x62/0x3f0 kernel_init_freeable+0x3da/0x6a0 kernel_init+0x1b/0x200 ret_from_fork+0x44/0x70 ret_from_fork_asm+0x1a/0x30 -> #0 (iommu_probe_device_lock){+.+.}-{3:3}: __lock_acquire+0x1637/0x2810 lock_acquire+0xc9/0x300 __mutex_lock+0xb4/0xe40 mutex_lock_nested+0x1b/0x30 iommu_probe_device+0x1d/0x70 intel_iommu_init+0xe90/0x11f0 pci_iommu_init+0x13/0x70 do_one_initcall+0x62/0x3f0 kernel_init_freeable+0x3da/0x6a0 kernel_init+0x1b/0x200 ret_from_fork+0x44/0x70 ret_from_fork_asm+0x1a/0x30 other info that might help us debug this: Chain exists of: iommu_probe_device_lock --> dmar_global_lock --> &device->physical_node_lock Possible unsafe locking scenario: CPU0 CPU1 ---- ---- lock(&device->physical_node_lock); lock(dmar_global_lock); lock(&device->physical_node_lock); lock(iommu_probe_device_lock); *** DEADLOCK *** This driver uses a global lock to protect the list of enumerated DMA remapping units. It is necessary due to the driver's support for dynamic addition and removal of remapping units at runtime. Two distinct code paths require iteration over this remapping unit list: - Device registration and probing: the driver iterates the list to register each remapping unit with the upper layer IOMMU framework and subsequently probe the devices managed by that unit. - Global configuration: Upper layer components may also iterate the list to apply configuration changes. The lock acquisition order between these two code paths was reversed. This caused lockdep warnings, indicating a risk of deadlock. Fix this warning by releasing the global lock before invoking upper layer interfaces for device registration. Fixes: b150654f74bf ("iommu/vt-d: Fix suspicious RCU usage") Closes: https://lore.kernel.org/linux-iommu/SJ1PR11MB612953431F94F18C954C4A9CB9D32@SJ1PR11MB6129.namprd11.prod.outlook.com/ Tested-by: Chaitanya Kumar Borah Cc: stable@vger.kernel.org Signed-off-by: Lu Baolu Link: https://lore.kernel.org/r/20250317035714.1041549-1-baolu.lu@linux.intel.com Signed-off-by: Joerg Roedel Signed-off-by: Greg Kroah-Hartman --- drivers/iommu/intel/iommu.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/iommu/intel/iommu.c b/drivers/iommu/intel/iommu.c index 9c46a4cd3848..038a66388564 100644 --- a/drivers/iommu/intel/iommu.c +++ b/drivers/iommu/intel/iommu.c @@ -3174,6 +3174,7 @@ static int __init probe_acpi_namespace_devices(void) if (dev->bus != &acpi_bus_type) continue; + up_read(&dmar_global_lock); adev = to_acpi_device(dev); mutex_lock(&adev->physical_node_lock); list_for_each_entry(pn, @@ -3183,6 +3184,7 @@ static int __init probe_acpi_namespace_devices(void) break; } mutex_unlock(&adev->physical_node_lock); + down_read(&dmar_global_lock); if (ret) return ret; From cb6b9bd66181f43c6723f20c91878b1de864933a Mon Sep 17 00:00:00 2001 From: Sean Christopherson Date: Thu, 10 Apr 2025 15:32:46 +0800 Subject: [PATCH 134/136] iommu/vt-d: Wire up irq_ack() to irq_move_irq() for posted MSIs commit 548183ea388c12b6d76d6982f3d72df3887af0da upstream. Set the posted MSI irq_chip's irq_ack() hook to irq_move_irq() instead of a dummy/empty callback so that posted MSIs process pending changes to the IRQ's SMP affinity. Failure to honor a pending set-affinity results in userspace being unable to change the effective affinity of the IRQ, as IRQD_SETAFFINITY_PENDING is never cleared and so irq_set_affinity_locked() always defers moving the IRQ. The issue is most easily reproducible by setting /proc/irq/xx/smp_affinity multiple times in quick succession, as only the first update is likely to be handled in process context. Fixes: ed1e48ea4370 ("iommu/vt-d: Enable posted mode for device MSIs") Cc: Robert Lippert Cc: Thomas Gleixner Reported-by: Wentao Yang Cc: stable@vger.kernel.org Signed-off-by: Sean Christopherson Reviewed-by: Thomas Gleixner Link: https://lore.kernel.org/r/20250321194249.1217961-1-seanjc@google.com Signed-off-by: Lu Baolu Signed-off-by: Joerg Roedel Signed-off-by: Greg Kroah-Hartman --- drivers/iommu/intel/irq_remapping.c | 29 +++++++++++++++-------------- 1 file changed, 15 insertions(+), 14 deletions(-) diff --git a/drivers/iommu/intel/irq_remapping.c b/drivers/iommu/intel/irq_remapping.c index 8093ba109d65..71b3383b7115 100644 --- a/drivers/iommu/intel/irq_remapping.c +++ b/drivers/iommu/intel/irq_remapping.c @@ -1291,43 +1291,44 @@ static struct irq_chip intel_ir_chip = { }; /* - * With posted MSIs, all vectors are multiplexed into a single notification - * vector. Devices MSIs are then dispatched in a demux loop where - * EOIs can be coalesced as well. + * With posted MSIs, the MSI vectors are multiplexed into a single notification + * vector, and only the notification vector is sent to the APIC IRR. Device + * MSIs are then dispatched in a demux loop that harvests the MSIs from the + * CPU's Posted Interrupt Request bitmap. I.e. Posted MSIs never get sent to + * the APIC IRR, and thus do not need an EOI. The notification handler instead + * performs a single EOI after processing the PIR. * - * "INTEL-IR-POST" IRQ chip does not do EOI on ACK, thus the dummy irq_ack() - * function. Instead EOI is performed by the posted interrupt notification - * handler. + * Note! Pending SMP/CPU affinity changes, which are per MSI, must still be + * honored, only the APIC EOI is omitted. * * For the example below, 3 MSIs are coalesced into one CPU notification. Only - * one apic_eoi() is needed. + * one apic_eoi() is needed, but each MSI needs to process pending changes to + * its CPU affinity. * * __sysvec_posted_msi_notification() * irq_enter(); * handle_edge_irq() * irq_chip_ack_parent() - * dummy(); // No EOI + * irq_move_irq(); // No EOI * handle_irq_event() * driver_handler() * handle_edge_irq() * irq_chip_ack_parent() - * dummy(); // No EOI + * irq_move_irq(); // No EOI * handle_irq_event() * driver_handler() * handle_edge_irq() * irq_chip_ack_parent() - * dummy(); // No EOI + * irq_move_irq(); // No EOI * handle_irq_event() * driver_handler() * apic_eoi() * irq_exit() + * */ - -static void dummy_ack(struct irq_data *d) { } - static struct irq_chip intel_ir_chip_post_msi = { .name = "INTEL-IR-POST", - .irq_ack = dummy_ack, + .irq_ack = irq_move_irq, .irq_set_affinity = intel_ir_set_affinity, .irq_compose_msi_msg = intel_ir_compose_msi_msg, .irq_set_vcpu_affinity = intel_ir_set_vcpu_affinity, From 690446dc72d5de012d8d0301bc1454c4ec740923 Mon Sep 17 00:00:00 2001 From: Ryan Roberts Date: Mon, 3 Mar 2025 14:15:37 +0000 Subject: [PATCH 135/136] sparc/mm: disable preemption in lazy mmu mode commit a1d416bf9faf4f4871cb5a943614a07f80a7d70f upstream. Since commit 38e0edb15bd0 ("mm/apply_to_range: call pte function with lazy updates") it's been possible for arch_[enter|leave]_lazy_mmu_mode() to be called without holding a page table lock (for the kernel mappings case), and therefore it is possible that preemption may occur while in the lazy mmu mode. The Sparc lazy mmu implementation is not robust to preemption since it stores the lazy mode state in a per-cpu structure and does not attempt to manage that state on task switch. Powerpc had the same issue and fixed it by explicitly disabling preemption in arch_enter_lazy_mmu_mode() and re-enabling in arch_leave_lazy_mmu_mode(). See commit b9ef323ea168 ("powerpc/64s: Disable preemption in hash lazy mmu mode"). Given Sparc's lazy mmu mode is based on powerpc's, let's fix it in the same way here. Link: https://lkml.kernel.org/r/20250303141542.3371656-4-ryan.roberts@arm.com Fixes: 38e0edb15bd0 ("mm/apply_to_range: call pte function with lazy updates") Signed-off-by: Ryan Roberts Acked-by: David Hildenbrand Acked-by: Andreas Larsson Acked-by: Juergen Gross Cc: Borislav Betkov Cc: Boris Ostrovsky Cc: Catalin Marinas Cc: Dave Hansen Cc: David S. Miller Cc: "H. Peter Anvin" Cc: Ingo Molnar Cc: Juegren Gross Cc: Matthew Wilcow (Oracle) Cc: Thomas Gleinxer Cc: Signed-off-by: Andrew Morton Signed-off-by: Greg Kroah-Hartman --- arch/sparc/mm/tlb.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/arch/sparc/mm/tlb.c b/arch/sparc/mm/tlb.c index 8648a50afe88..a35ddcca5e76 100644 --- a/arch/sparc/mm/tlb.c +++ b/arch/sparc/mm/tlb.c @@ -52,8 +52,10 @@ out: void arch_enter_lazy_mmu_mode(void) { - struct tlb_batch *tb = this_cpu_ptr(&tlb_batch); + struct tlb_batch *tb; + preempt_disable(); + tb = this_cpu_ptr(&tlb_batch); tb->active = 1; } @@ -64,6 +66,7 @@ void arch_leave_lazy_mmu_mode(void) if (tb->tlb_nr) flush_tlb_pending(); tb->active = 0; + preempt_enable(); } static void tlb_batch_add_one(struct mm_struct *mm, unsigned long vaddr, From fba396b79942be5432ca27ec003fa0f151235ca6 Mon Sep 17 00:00:00 2001 From: Ryan Roberts Date: Mon, 3 Mar 2025 14:15:38 +0000 Subject: [PATCH 136/136] sparc/mm: avoid calling arch_enter/leave_lazy_mmu() in set_ptes commit eb61ad14c459b54f71f76331ca35d12fa3eb8f98 upstream. With commit 1a10a44dfc1d ("sparc64: implement the new page table range API") set_ptes was added to the sparc architecture. The implementation included calling arch_enter/leave_lazy_mmu() calls. The patch removes the usage of arch_enter/leave_lazy_mmu() since this implies nesting of lazy mmu regions which is not supported. Without this fix, lazy mmu mode is effectively disabled because we exit the mode after the first set_ptes: remap_pte_range() -> arch_enter_lazy_mmu() -> set_ptes() -> arch_enter_lazy_mmu() -> arch_leave_lazy_mmu() -> arch_leave_lazy_mmu() Powerpc suffered the same problem and fixed it in a corresponding way with commit 47b8def9358c ("powerpc/mm: Avoid calling arch_enter/leave_lazy_mmu() in set_ptes"). Link: https://lkml.kernel.org/r/20250303141542.3371656-5-ryan.roberts@arm.com Fixes: 1a10a44dfc1d ("sparc64: implement the new page table range API") Signed-off-by: Ryan Roberts Acked-by: David Hildenbrand Acked-by: Andreas Larsson Acked-by: Juergen Gross Cc: Borislav Betkov Cc: Boris Ostrovsky Cc: Catalin Marinas Cc: Dave Hansen Cc: David S. Miller Cc: "H. Peter Anvin" Cc: Ingo Molnar Cc: Juegren Gross Cc: Matthew Wilcow (Oracle) Cc: Thomas Gleinxer Cc: Signed-off-by: Andrew Morton Signed-off-by: Greg Kroah-Hartman --- arch/sparc/include/asm/pgtable_64.h | 2 -- 1 file changed, 2 deletions(-) diff --git a/arch/sparc/include/asm/pgtable_64.h b/arch/sparc/include/asm/pgtable_64.h index 2b7f358762c1..dc28f2c4eee3 100644 --- a/arch/sparc/include/asm/pgtable_64.h +++ b/arch/sparc/include/asm/pgtable_64.h @@ -936,7 +936,6 @@ static inline void __set_pte_at(struct mm_struct *mm, unsigned long addr, static inline void set_ptes(struct mm_struct *mm, unsigned long addr, pte_t *ptep, pte_t pte, unsigned int nr) { - arch_enter_lazy_mmu_mode(); for (;;) { __set_pte_at(mm, addr, ptep, pte, 0); if (--nr == 0) @@ -945,7 +944,6 @@ static inline void set_ptes(struct mm_struct *mm, unsigned long addr, pte_val(pte) += PAGE_SIZE; addr += PAGE_SIZE; } - arch_leave_lazy_mmu_mode(); } #define set_ptes set_ptes