From: Greg Kroah-Hartman gregkh@linuxfoundation.org
This is the start of the stable review cycle for the 5.11.6 release. There are 36 patches in this series, all will be posted as a response to this one. If anyone has any issues with these being applied, please let me know.
Responses should be made by Fri, 12 Mar 2021 13:23:09 +0000. Anything received after that time might be too late.
The whole patch series can be found in one patch at: https://www.kernel.org/pub/linux/kernel/v5.x/stable-review/patch-5.11.6-rc1.... or in the git tree and branch at: git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable-rc.git linux-5.11.y and the diffstat can be found below.
thanks,
greg k-h
------------- Pseudo-Shortlog of commits:
Greg Kroah-Hartman gregkh@linuxfoundation.org Linux 5.11.6-rc1
Pascal Terjan pterjan@google.com nvme-pci: add quirks for Lexar 256GB SSD
Julian Einwag jeinwag-nvme@marcapo.com nvme-pci: mark Seagate Nytro XM1440 as QUIRK_NO_NS_DESC_LIST.
Babu Moger babu.moger@amd.com KVM: SVM: Clear the CR4 register on reset
Avri Altman avri.altman@wdc.com scsi: ufs: Fix a duplicate dev quirk number
Pierre-Louis Bossart pierre-louis.bossart@linux.intel.com ASoC: Intel: sof_sdw: add quirk for HP Spectre x360 convertible
Pierre-Louis Bossart pierre-louis.bossart@linux.intel.com ASoC: Intel: sof_sdw: reorganize quirks by generation
Nadeem Athani nadeem@cadence.com PCI: cadence: Retrain Link to work around Gen2 training defect
Hans de Goede hdegoede@redhat.com HID: ite: Enable QUIRK_TOUCHPAD_ON_OFF_REPORT on Acer Aspire Switch 10E
Fabian Lesniak fabian@lesniak-it.de ALSA: usb-audio: add mixer quirks for Pioneer DJM-900NXS2
Olivia Mackintosh livvy@base.nu ALSA: usb-audio: Add DJM750 to Pioneer mixer quirk
Hans de Goede hdegoede@redhat.com HID: i2c-hid: Add I2C_HID_QUIRK_NO_IRQ_AFTER_RESET for ITE8568 EC on Voyo Winpad A15
Jisheng Zhang Jisheng.Zhang@synaptics.com mmc: sdhci-of-dwcmshc: set SDHCI_QUIRK2_PRESET_VALUE_BROKEN
AngeloGioacchino Del Regno angelogioacchino.delregno@somainline.org drm/msm/a5xx: Remove overwriting A5XX_PC_DBG_ECO_CNTL register
Kiwoong Kim kwmad.kim@samsung.com scsi: ufs: ufs-exynos: Use UFSHCD_QUIRK_ALIGN_SG_WITH_PAGE_SIZE
Kiwoong Kim kwmad.kim@samsung.com scsi: ufs: ufs-exynos: Apply vendor-specific values for three timeouts
Kiwoong Kim kwmad.kim@samsung.com scsi: ufs: Introduce a quirk to allow only page-aligned sg entries
Aswath Govindraju a-govindraju@ti.com misc: eeprom_93xx46: Add quirk to support Microchip 93LC46B eeprom
Kiwoong Kim kwmad.kim@samsung.com scsi: ufs: Add a quirk to permit overriding UniPro defaults
Stanley Chu stanley.chu@mediatek.com scsi: ufs-mediatek: Enable UFSHCI_QUIRK_SKIP_MANUAL_WB_FLUSH_CTRL
Andrey Ryabinin arbn@yandex-team.com iommu/amd: Fix sleeping in atomic in increase_address_space()
Nikolay Borisov nborisov@suse.com btrfs: don't flush from btrfs_delayed_inode_reserve_metadata
Nikolay Borisov nborisov@suse.com btrfs: export and rename qgroup_reserve_meta
Nathan Chancellor nathan@kernel.org arm64: Make CPU_BIG_ENDIAN depend on ld.bfd or ld.lld 13.0.0+
Helge Deller deller@gmx.de parisc: Enable -mlong-calls gcc option with CONFIG_COMPILE_TEST
Zoltán Böszörményi zboszor@gmail.com nvme-pci: mark Kingston SKC2000 as not supporting the deepest power state
Jernej Skrabec jernej.skrabec@siol.net media: cedrus: Remove checking for required controls
Pavel Begunkov asml.silence@gmail.com io_uring: don't take uring_lock during iowq cancel
Pavel Begunkov asml.silence@gmail.com io_uring/io-wq: return 2-step work swap scheme
Jens Axboe axboe@kernel.dk io_uring/io-wq: kill off now unused IO_WQ_WORK_NO_CANCEL
Jens Axboe axboe@kernel.dk io_uring: get rid of intermediate IORING_OP_CLOSE stage
Jens Axboe axboe@kernel.dk fs: provide locked helper variant of close_fd_get_file()
Pavel Begunkov asml.silence@gmail.com io_uring: deduplicate failing task_work_add
Pavel Begunkov asml.silence@gmail.com io_uring: unpark SQPOLL thread for cancelation
Pavel Begunkov asml.silence@gmail.com io_uring: deduplicate core cancellations sequence
Pavel Begunkov asml.silence@gmail.com io_uring: fix inconsistent lock state
Hans de Goede hdegoede@redhat.com ACPICA: Fix race in generic_serial_bus (I2C) and GPIO op_region parameter handling
-------------
Diffstat:
Makefile | 4 +- arch/arm64/Kconfig | 5 +- arch/parisc/Kconfig | 7 +- arch/x86/kvm/svm/svm.c | 1 + drivers/acpi/acpica/acobject.h | 1 + drivers/acpi/acpica/evhandler.c | 7 + drivers/acpi/acpica/evregion.c | 64 +++- drivers/acpi/acpica/evxfregn.c | 2 + drivers/gpu/drm/msm/adreno/a5xx_gpu.c | 2 - drivers/hid/hid-ids.h | 2 + drivers/hid/hid-ite.c | 12 +- drivers/hid/i2c-hid/i2c-hid-core.c | 2 + drivers/iommu/amd/iommu.c | 10 +- drivers/misc/eeprom/eeprom_93xx46.c | 15 + drivers/mmc/host/sdhci-of-dwcmshc.c | 1 + drivers/nvme/host/pci.c | 8 +- drivers/pci/controller/cadence/pci-j721e.c | 3 + drivers/pci/controller/cadence/pcie-cadence-host.c | 81 ++++- drivers/pci/controller/cadence/pcie-cadence.h | 11 +- drivers/scsi/ufs/ufs-exynos.c | 9 +- drivers/scsi/ufs/ufs-mediatek.c | 1 + drivers/scsi/ufs/ufshcd.c | 42 +-- drivers/scsi/ufs/ufshcd.h | 10 + drivers/staging/media/sunxi/cedrus/cedrus.c | 49 --- drivers/staging/media/sunxi/cedrus/cedrus.h | 1 - fs/btrfs/delayed-inode.c | 3 +- fs/btrfs/inode.c | 2 +- fs/btrfs/qgroup.c | 8 +- fs/btrfs/qgroup.h | 2 + fs/file.c | 36 +- fs/internal.h | 1 + fs/io-wq.c | 17 +- fs/io-wq.h | 5 +- fs/io_uring.c | 241 +++++++------- include/linux/eeprom_93xx46.h | 2 + sound/soc/intel/boards/sof_sdw.c | 89 +++-- sound/usb/mixer_quirks.c | 367 ++++++++++++++------- 37 files changed, 686 insertions(+), 437 deletions(-)
From: Greg Kroah-Hartman gregkh@linuxfoundation.org
From: Hans de Goede hdegoede@redhat.com
commit c27f3d011b08540e68233cf56274fdc34bebb9b5 upstream.
ACPICA commit c9e0116952363b0fa815143dca7e9a2eb4fefa61
The handling of the generic_serial_bus (I2C) and GPIO op_regions in acpi_ev_address_space_dispatch() passes a number of extra parameters to the address-space handler through the address-space Context pointer (instead of using more function parameters).
The Context is shared between threads, so if multiple threads try to call the handler for the same address-space at the same time, then a second thread could change the parameters of a first thread while the handler is running for the first thread.
An example of this race hitting is the Lenovo Yoga Tablet2 1015L, where there are both attrib_bytes accesses and attrib_byte accesses to the same address-space. The attrib_bytes access stores the number of bytes to transfer in Context->access_length. Where as for the attrib_byte access the number of bytes to transfer is always 1 and field_obj->Field.access_length is unused (so 0). Both types of accesses racing from different threads leads to the following problem:
1. Thread a. starts an attrib_bytes access, stores a non 0 value from field_obj->Field.access_length in Context->access_length
2. Thread b. starts an attrib_byte access, stores 0 in Context->access_length
3. Thread a. calls i2c_acpi_space_handler() (under Linux). Which sees that the access-type is ACPI_GSB_ACCESS_ATTRIB_MULTIBYTE and calls acpi_gsb_i2c_read_bytes(..., Context->access_length)
4. At this point Context->access_length is 0 (set by thread b.)
rather then the field_obj->Field.access_length value from thread a. This 0 length reads leads to the following errors being logged:
i2c i2c-0: adapter quirk: no zero length (addr 0x0078, size 0, read) i2c i2c-0: i2c read 0 bytes from client@0x78 starting at reg 0x0 failed, error: -95
Note this is just an example of the problems which this race can cause.
There are likely many more (sporadic) problems caused by this race.
This commit adds a new context_mutex to struct acpi_object_addr_handler and makes acpi_ev_address_space_dispatch() take that mutex when using the shared Context to pass extra parameters to an address-space handler, fixing this race.
Note the new mutex must be taken *after* exiting the interpreter, therefor the existing acpi_ex_exit_interpreter() call is moved to above the code which stores the extra parameters in the Context.
Link: https://github.com/acpica/acpica/commit/c9e01169 Signed-off-by: Hans de Goede hdegoede@redhat.com Signed-off-by: Bob Moore robert.moore@intel.com Signed-off-by: Erik Kaneda erik.kaneda@intel.com Signed-off-by: Rafael J. Wysocki rafael.j.wysocki@intel.com Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/acpi/acpica/acobject.h | 1 drivers/acpi/acpica/evhandler.c | 7 ++++ drivers/acpi/acpica/evregion.c | 64 +++++++++++++++++++++++++++++----------- drivers/acpi/acpica/evxfregn.c | 2 + 4 files changed, 57 insertions(+), 17 deletions(-)
--- a/drivers/acpi/acpica/acobject.h +++ b/drivers/acpi/acpica/acobject.h @@ -284,6 +284,7 @@ struct acpi_object_addr_handler { acpi_adr_space_handler handler; struct acpi_namespace_node *node; /* Parent device */ void *context; + acpi_mutex context_mutex; acpi_adr_space_setup setup; union acpi_operand_object *region_list; /* Regions using this handler */ union acpi_operand_object *next; --- a/drivers/acpi/acpica/evhandler.c +++ b/drivers/acpi/acpica/evhandler.c @@ -489,6 +489,13 @@ acpi_ev_install_space_handler(struct acp
/* Init handler obj */
+ status = + acpi_os_create_mutex(&handler_obj->address_space.context_mutex); + if (ACPI_FAILURE(status)) { + acpi_ut_remove_reference(handler_obj); + goto unlock_and_exit; + } + handler_obj->address_space.space_id = (u8)space_id; handler_obj->address_space.handler_flags = flags; handler_obj->address_space.region_list = NULL; --- a/drivers/acpi/acpica/evregion.c +++ b/drivers/acpi/acpica/evregion.c @@ -112,6 +112,8 @@ acpi_ev_address_space_dispatch(union acp union acpi_operand_object *region_obj2; void *region_context = NULL; struct acpi_connection_info *context; + acpi_mutex context_mutex; + u8 context_locked; acpi_physical_address address;
ACPI_FUNCTION_TRACE(ev_address_space_dispatch); @@ -136,6 +138,8 @@ acpi_ev_address_space_dispatch(union acp }
context = handler_desc->address_space.context; + context_mutex = handler_desc->address_space.context_mutex; + context_locked = FALSE;
/* * It may be the case that the region has never been initialized. @@ -204,6 +208,23 @@ acpi_ev_address_space_dispatch(union acp handler = handler_desc->address_space.handler; address = (region_obj->region.address + region_offset);
+ ACPI_DEBUG_PRINT((ACPI_DB_OPREGION, + "Handler %p (@%p) Address %8.8X%8.8X [%s]\n", + ®ion_obj->region.handler->address_space, handler, + ACPI_FORMAT_UINT64(address), + acpi_ut_get_region_name(region_obj->region. + space_id))); + + if (!(handler_desc->address_space.handler_flags & + ACPI_ADDR_HANDLER_DEFAULT_INSTALLED)) { + /* + * For handlers other than the default (supplied) handlers, we must + * exit the interpreter because the handler *might* block -- we don't + * know what it will do, so we can't hold the lock on the interpreter. + */ + acpi_ex_exit_interpreter(); + } + /* * Special handling for generic_serial_bus and general_purpose_io: * There are three extra parameters that must be passed to the @@ -212,6 +233,11 @@ acpi_ev_address_space_dispatch(union acp * 2) Length of the above buffer * 3) Actual access length from the access_as() op * + * Since we pass these extra parameters via the context, which is + * shared between threads, we must lock the context to avoid these + * parameters being changed from another thread before the handler + * has completed running. + * * In addition, for general_purpose_io, the Address and bit_width fields * are defined as follows: * 1) Address is the pin number index of the field (bit offset from @@ -221,6 +247,14 @@ acpi_ev_address_space_dispatch(union acp if ((region_obj->region.space_id == ACPI_ADR_SPACE_GSBUS) && context && field_obj) {
+ status = + acpi_os_acquire_mutex(context_mutex, ACPI_WAIT_FOREVER); + if (ACPI_FAILURE(status)) { + goto re_enter_interpreter; + } + + context_locked = TRUE; + /* Get the Connection (resource_template) buffer */
context->connection = field_obj->field.resource_buffer; @@ -230,6 +264,14 @@ acpi_ev_address_space_dispatch(union acp if ((region_obj->region.space_id == ACPI_ADR_SPACE_GPIO) && context && field_obj) {
+ status = + acpi_os_acquire_mutex(context_mutex, ACPI_WAIT_FOREVER); + if (ACPI_FAILURE(status)) { + goto re_enter_interpreter; + } + + context_locked = TRUE; + /* Get the Connection (resource_template) buffer */
context->connection = field_obj->field.resource_buffer; @@ -239,28 +281,15 @@ acpi_ev_address_space_dispatch(union acp bit_width = field_obj->field.bit_length; }
- ACPI_DEBUG_PRINT((ACPI_DB_OPREGION, - "Handler %p (@%p) Address %8.8X%8.8X [%s]\n", - ®ion_obj->region.handler->address_space, handler, - ACPI_FORMAT_UINT64(address), - acpi_ut_get_region_name(region_obj->region. - space_id))); - - if (!(handler_desc->address_space.handler_flags & - ACPI_ADDR_HANDLER_DEFAULT_INSTALLED)) { - /* - * For handlers other than the default (supplied) handlers, we must - * exit the interpreter because the handler *might* block -- we don't - * know what it will do, so we can't hold the lock on the interpreter. - */ - acpi_ex_exit_interpreter(); - } - /* Call the handler */
status = handler(function, address, bit_width, value, context, region_obj2->extra.region_context);
+ if (context_locked) { + acpi_os_release_mutex(context_mutex); + } + if (ACPI_FAILURE(status)) { ACPI_EXCEPTION((AE_INFO, status, "Returned by Handler for [%s]", acpi_ut_get_region_name(region_obj->region. @@ -277,6 +306,7 @@ acpi_ev_address_space_dispatch(union acp } }
+re_enter_interpreter: if (!(handler_desc->address_space.handler_flags & ACPI_ADDR_HANDLER_DEFAULT_INSTALLED)) { /* --- a/drivers/acpi/acpica/evxfregn.c +++ b/drivers/acpi/acpica/evxfregn.c @@ -201,6 +201,8 @@ acpi_remove_address_space_handler(acpi_h
/* Now we can delete the handler object */
+ acpi_os_release_mutex(handler_obj->address_space. + context_mutex); acpi_ut_remove_reference(handler_obj); goto unlock_and_exit; }
From: Greg Kroah-Hartman gregkh@linuxfoundation.org
From: Pavel Begunkov asml.silence@gmail.com
commin 9ae1f8dd372e0e4c020b345cf9e09f519265e981 upstream
WARNING: inconsistent lock state
inconsistent {HARDIRQ-ON-W} -> {IN-HARDIRQ-W} usage. syz-executor217/8450 [HC1[1]:SC0[0]:HE0:SE1] takes: ffff888023d6e620 (&fs->lock){?.+.}-{2:2}, at: spin_lock include/linux/spinlock.h:354 [inline] ffff888023d6e620 (&fs->lock){?.+.}-{2:2}, at: io_req_clean_work fs/io_uring.c:1398 [inline] ffff888023d6e620 (&fs->lock){?.+.}-{2:2}, at: io_dismantle_req+0x66f/0xf60 fs/io_uring.c:2029
other info that might help us debug this: Possible unsafe locking scenario:
CPU0 ---- lock(&fs->lock); <Interrupt> lock(&fs->lock);
*** DEADLOCK ***
1 lock held by syz-executor217/8450: #0: ffff88802417c3e8 (&ctx->uring_lock){+.+.}-{3:3}, at: __do_sys_io_uring_enter+0x1071/0x1f30 fs/io_uring.c:9442
stack backtrace: CPU: 1 PID: 8450 Comm: syz-executor217 Not tainted 5.11.0-rc5-next-20210129-syzkaller #0 Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 01/01/2011 Call Trace: <IRQ> [...] _raw_spin_lock+0x2a/0x40 kernel/locking/spinlock.c:151 spin_lock include/linux/spinlock.h:354 [inline] io_req_clean_work fs/io_uring.c:1398 [inline] io_dismantle_req+0x66f/0xf60 fs/io_uring.c:2029 __io_free_req+0x3d/0x2e0 fs/io_uring.c:2046 io_free_req fs/io_uring.c:2269 [inline] io_double_put_req fs/io_uring.c:2392 [inline] io_put_req+0xf9/0x570 fs/io_uring.c:2388 io_link_timeout_fn+0x30c/0x480 fs/io_uring.c:6497 __run_hrtimer kernel/time/hrtimer.c:1519 [inline] __hrtimer_run_queues+0x609/0xe40 kernel/time/hrtimer.c:1583 hrtimer_interrupt+0x334/0x940 kernel/time/hrtimer.c:1645 local_apic_timer_interrupt arch/x86/kernel/apic/apic.c:1085 [inline] __sysvec_apic_timer_interrupt+0x146/0x540 arch/x86/kernel/apic/apic.c:1102 asm_call_irq_on_stack+0xf/0x20 </IRQ> __run_sysvec_on_irqstack arch/x86/include/asm/irq_stack.h:37 [inline] run_sysvec_on_irqstack_cond arch/x86/include/asm/irq_stack.h:89 [inline] sysvec_apic_timer_interrupt+0xbd/0x100 arch/x86/kernel/apic/apic.c:1096 asm_sysvec_apic_timer_interrupt+0x12/0x20 arch/x86/include/asm/idtentry.h:629 RIP: 0010:__raw_spin_unlock_irq include/linux/spinlock_api_smp.h:169 [inline] RIP: 0010:_raw_spin_unlock_irq+0x25/0x40 kernel/locking/spinlock.c:199 spin_unlock_irq include/linux/spinlock.h:404 [inline] io_queue_linked_timeout+0x194/0x1f0 fs/io_uring.c:6525 __io_queue_sqe+0x328/0x1290 fs/io_uring.c:6594 io_queue_sqe+0x631/0x10d0 fs/io_uring.c:6639 io_queue_link_head fs/io_uring.c:6650 [inline] io_submit_sqe fs/io_uring.c:6697 [inline] io_submit_sqes+0x19b5/0x2720 fs/io_uring.c:6960 __do_sys_io_uring_enter+0x107d/0x1f30 fs/io_uring.c:9443 do_syscall_64+0x2d/0x70 arch/x86/entry/common.c:46 entry_SYSCALL_64_after_hwframe+0x44/0xa9
Don't free requests from under hrtimer context (softirq) as it may sleep or take spinlocks improperly (e.g. non-irq versions).
Cc: stable@vger.kernel.org # 5.6+ Reported-by: syzbot+81d17233a2b02eafba33@syzkaller.appspotmail.com Signed-off-by: Pavel Begunkov asml.silence@gmail.com Signed-off-by: Jens Axboe axboe@kernel.dk Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- fs/io_uring.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-)
--- a/fs/io_uring.c +++ b/fs/io_uring.c @@ -6506,9 +6506,10 @@ static enum hrtimer_restart io_link_time if (prev) { req_set_fail_links(prev); io_async_find_and_cancel(ctx, req, prev->user_data, -ETIME); - io_put_req(prev); + io_put_req_deferred(prev, 1); } else { - io_req_complete(req, -ETIME); + io_cqring_add_event(req, -ETIME, 0); + io_put_req_deferred(req, 1); } return HRTIMER_NORESTART; }
From: Greg Kroah-Hartman gregkh@linuxfoundation.org
From: Pavel Begunkov asml.silence@gmail.com
commit 9936c7c2bc76a0b2276f6d19de6d1d92f03deeab upstream
Files and task cancellations go over same steps trying to cancel requests in io-wq, poll, etc. Deduplicate it with a helper.
note: new io_uring_try_cancel_requests() is former __io_uring_cancel_task_requests() with files passed as an agrument and flushing overflowed requests.
Signed-off-by: Pavel Begunkov asml.silence@gmail.com Signed-off-by: Jens Axboe axboe@kernel.dk Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- fs/io_uring.c | 85 +++++++++++++++++++++++++++------------------------------- 1 file changed, 40 insertions(+), 45 deletions(-)
--- a/fs/io_uring.c +++ b/fs/io_uring.c @@ -996,9 +996,9 @@ enum io_mem_account { ACCT_PINNED, };
-static void __io_uring_cancel_task_requests(struct io_ring_ctx *ctx, - struct task_struct *task); - +static void io_uring_try_cancel_requests(struct io_ring_ctx *ctx, + struct task_struct *task, + struct files_struct *files); static void destroy_fixed_file_ref_node(struct fixed_file_ref_node *ref_node); static struct fixed_file_ref_node *alloc_fixed_file_ref_node( struct io_ring_ctx *ctx); @@ -8780,7 +8780,7 @@ static void io_ring_exit_work(struct wor * as nobody else will be looking for them. */ do { - __io_uring_cancel_task_requests(ctx, NULL); + io_uring_try_cancel_requests(ctx, NULL, NULL); } while (!wait_for_completion_timeout(&ctx->ref_comp, HZ/20)); io_ring_ctx_free(ctx); } @@ -8894,6 +8894,40 @@ static void io_cancel_defer_files(struct } }
+static void io_uring_try_cancel_requests(struct io_ring_ctx *ctx, + struct task_struct *task, + struct files_struct *files) +{ + struct io_task_cancel cancel = { .task = task, .files = files, }; + + while (1) { + enum io_wq_cancel cret; + bool ret = false; + + if (ctx->io_wq) { + cret = io_wq_cancel_cb(ctx->io_wq, io_cancel_task_cb, + &cancel, true); + ret |= (cret != IO_WQ_CANCEL_NOTFOUND); + } + + /* SQPOLL thread does its own polling */ + if (!(ctx->flags & IORING_SETUP_SQPOLL) && !files) { + while (!list_empty_careful(&ctx->iopoll_list)) { + io_iopoll_try_reap_events(ctx); + ret = true; + } + } + + ret |= io_poll_remove_all(ctx, task, files); + ret |= io_kill_timeouts(ctx, task, files); + ret |= io_run_task_work(); + io_cqring_overflow_flush(ctx, true, task, files); + if (!ret) + break; + cond_resched(); + } +} + static int io_uring_count_inflight(struct io_ring_ctx *ctx, struct task_struct *task, struct files_struct *files) @@ -8913,7 +8947,6 @@ static void io_uring_cancel_files(struct struct files_struct *files) { while (!list_empty_careful(&ctx->inflight_list)) { - struct io_task_cancel cancel = { .task = task, .files = files }; DEFINE_WAIT(wait); int inflight;
@@ -8921,13 +8954,7 @@ static void io_uring_cancel_files(struct if (!inflight) break;
- io_wq_cancel_cb(ctx->io_wq, io_cancel_task_cb, &cancel, true); - io_poll_remove_all(ctx, task, files); - io_kill_timeouts(ctx, task, files); - io_cqring_overflow_flush(ctx, true, task, files); - /* cancellations _may_ trigger task work */ - io_run_task_work(); - + io_uring_try_cancel_requests(ctx, task, files); prepare_to_wait(&task->io_uring->wait, &wait, TASK_UNINTERRUPTIBLE); if (inflight == io_uring_count_inflight(ctx, task, files)) @@ -8936,37 +8963,6 @@ static void io_uring_cancel_files(struct } }
-static void __io_uring_cancel_task_requests(struct io_ring_ctx *ctx, - struct task_struct *task) -{ - while (1) { - struct io_task_cancel cancel = { .task = task, .files = NULL, }; - enum io_wq_cancel cret; - bool ret = false; - - if (ctx->io_wq) { - cret = io_wq_cancel_cb(ctx->io_wq, io_cancel_task_cb, - &cancel, true); - ret |= (cret != IO_WQ_CANCEL_NOTFOUND); - } - - /* SQPOLL thread does its own polling */ - if (!(ctx->flags & IORING_SETUP_SQPOLL)) { - while (!list_empty_careful(&ctx->iopoll_list)) { - io_iopoll_try_reap_events(ctx); - ret = true; - } - } - - ret |= io_poll_remove_all(ctx, task, NULL); - ret |= io_kill_timeouts(ctx, task, NULL); - ret |= io_run_task_work(); - if (!ret) - break; - cond_resched(); - } -} - static void io_disable_sqo_submit(struct io_ring_ctx *ctx) { mutex_lock(&ctx->uring_lock); @@ -8996,11 +8992,10 @@ static void io_uring_cancel_task_request }
io_cancel_defer_files(ctx, task, files); - io_cqring_overflow_flush(ctx, true, task, files);
io_uring_cancel_files(ctx, task, files); if (!files) - __io_uring_cancel_task_requests(ctx, task); + io_uring_try_cancel_requests(ctx, task, NULL);
if ((ctx->flags & IORING_SETUP_SQPOLL) && ctx->sq_data) { atomic_dec(&task->io_uring->in_idle);
From: Greg Kroah-Hartman gregkh@linuxfoundation.org
From: Pavel Begunkov asml.silence@gmail.com
commit 34343786ecc5ff493ca4d1f873b4386759ba52ee upstream
We park SQPOLL task before going into io_uring_cancel_files(), so the task won't run task_works including those that might be important for the cancellation passes. In this case it's io_poll_remove_one(), which frees requests via io_put_req_deferred().
Unpark it for while waiting, it's ok as we disable submissions beforehand, so no new requests will be generated.
INFO: task syz-executor893:8493 blocked for more than 143 seconds. Call Trace: context_switch kernel/sched/core.c:4327 [inline] __schedule+0x90c/0x21a0 kernel/sched/core.c:5078 schedule+0xcf/0x270 kernel/sched/core.c:5157 io_uring_cancel_files fs/io_uring.c:8912 [inline] io_uring_cancel_task_requests+0xe70/0x11a0 fs/io_uring.c:8979 __io_uring_files_cancel+0x110/0x1b0 fs/io_uring.c:9067 io_uring_files_cancel include/linux/io_uring.h:51 [inline] do_exit+0x2fe/0x2ae0 kernel/exit.c:780 do_group_exit+0x125/0x310 kernel/exit.c:922 __do_sys_exit_group kernel/exit.c:933 [inline] __se_sys_exit_group kernel/exit.c:931 [inline] __x64_sys_exit_group+0x3a/0x50 kernel/exit.c:931 do_syscall_64+0x2d/0x70 arch/x86/entry/common.c:46 entry_SYSCALL_64_after_hwframe+0x44/0xa9
Cc: stable@vger.kernel.org # 5.5+ Reported-by: syzbot+695b03d82fa8e4901b06@syzkaller.appspotmail.com Signed-off-by: Pavel Begunkov asml.silence@gmail.com Signed-off-by: Jens Axboe axboe@kernel.dk Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- fs/io_uring.c | 5 +++++ 1 file changed, 5 insertions(+)
--- a/fs/io_uring.c +++ b/fs/io_uring.c @@ -8955,11 +8955,16 @@ static void io_uring_cancel_files(struct break;
io_uring_try_cancel_requests(ctx, task, files); + + if (ctx->sq_data) + io_sq_thread_unpark(ctx->sq_data); prepare_to_wait(&task->io_uring->wait, &wait, TASK_UNINTERRUPTIBLE); if (inflight == io_uring_count_inflight(ctx, task, files)) schedule(); finish_wait(&task->io_uring->wait, &wait); + if (ctx->sq_data) + io_sq_thread_park(ctx->sq_data); } }
From: Greg Kroah-Hartman gregkh@linuxfoundation.org
From: Pavel Begunkov asml.silence@gmail.com
commit eab30c4d20dc761d463445e5130421863ff81505 upstream
When io_req_task_work_add() fails, the request will be cancelled by enqueueing via task_works of io-wq. Extract a function for that.
Signed-off-by: Pavel Begunkov asml.silence@gmail.com Signed-off-by: Jens Axboe axboe@kernel.dk Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- fs/io_uring.c | 46 +++++++++++++++++----------------------------- 1 file changed, 17 insertions(+), 29 deletions(-)
--- a/fs/io_uring.c +++ b/fs/io_uring.c @@ -2172,6 +2172,16 @@ static int io_req_task_work_add(struct i return ret; }
+static void io_req_task_work_add_fallback(struct io_kiocb *req, + void (*cb)(struct callback_head *)) +{ + struct task_struct *tsk = io_wq_get_task(req->ctx->io_wq); + + init_task_work(&req->task_work, cb); + task_work_add(tsk, &req->task_work, TWA_NONE); + wake_up_process(tsk); +} + static void __io_req_task_cancel(struct io_kiocb *req, int error) { struct io_ring_ctx *ctx = req->ctx; @@ -2229,14 +2239,8 @@ static void io_req_task_queue(struct io_ percpu_ref_get(&req->ctx->refs);
ret = io_req_task_work_add(req); - if (unlikely(ret)) { - struct task_struct *tsk; - - init_task_work(&req->task_work, io_req_task_cancel); - tsk = io_wq_get_task(req->ctx->io_wq); - task_work_add(tsk, &req->task_work, TWA_NONE); - wake_up_process(tsk); - } + if (unlikely(ret)) + io_req_task_work_add_fallback(req, io_req_task_cancel); }
static inline void io_queue_next(struct io_kiocb *req) @@ -2354,13 +2358,8 @@ static void io_free_req_deferred(struct
init_task_work(&req->task_work, io_put_req_deferred_cb); ret = io_req_task_work_add(req); - if (unlikely(ret)) { - struct task_struct *tsk; - - tsk = io_wq_get_task(req->ctx->io_wq); - task_work_add(tsk, &req->task_work, TWA_NONE); - wake_up_process(tsk); - } + if (unlikely(ret)) + io_req_task_work_add_fallback(req, io_put_req_deferred_cb); }
static inline void io_put_req_deferred(struct io_kiocb *req, int refs) @@ -3439,15 +3438,8 @@ static int io_async_buf_func(struct wait /* submit ref gets dropped, acquire a new one */ refcount_inc(&req->refs); ret = io_req_task_work_add(req); - if (unlikely(ret)) { - struct task_struct *tsk; - - /* queue just for cancelation */ - init_task_work(&req->task_work, io_req_task_cancel); - tsk = io_wq_get_task(req->ctx->io_wq); - task_work_add(tsk, &req->task_work, TWA_NONE); - wake_up_process(tsk); - } + if (unlikely(ret)) + io_req_task_work_add_fallback(req, io_req_task_cancel); return 1; }
@@ -5159,12 +5151,8 @@ static int __io_async_wake(struct io_kio */ ret = io_req_task_work_add(req); if (unlikely(ret)) { - struct task_struct *tsk; - WRITE_ONCE(poll->canceled, true); - tsk = io_wq_get_task(req->ctx->io_wq); - task_work_add(tsk, &req->task_work, TWA_NONE); - wake_up_process(tsk); + io_req_task_work_add_fallback(req, func); } return 1; }
From: Greg Kroah-Hartman gregkh@linuxfoundation.org
From: Jens Axboe axboe@kernel.dk
commit 53dec2ea74f2ef360e8455439be96a780baa6097 upstream
Assumes current->files->file_lock is already held on invocation. Helps the caller check the file before removing the fd, if it needs to.
Signed-off-by: Jens Axboe axboe@kernel.dk Signed-off-by: Pavel Begunkov asml.silence@gmail.com Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- fs/file.c | 36 +++++++++++++++++++++++++----------- fs/internal.h | 1 + 2 files changed, 26 insertions(+), 11 deletions(-)
--- a/fs/file.c +++ b/fs/file.c @@ -22,6 +22,8 @@ #include <linux/close_range.h> #include <net/sock.h>
+#include "internal.h" + unsigned int sysctl_nr_open __read_mostly = 1024*1024; unsigned int sysctl_nr_open_min = BITS_PER_LONG; /* our min() is unusable in constant expressions ;-/ */ @@ -732,36 +734,48 @@ int __close_range(unsigned fd, unsigned }
/* - * variant of close_fd that gets a ref on the file for later fput. - * The caller must ensure that filp_close() called on the file, and then - * an fput(). + * See close_fd_get_file() below, this variant assumes current->files->file_lock + * is held. */ -int close_fd_get_file(unsigned int fd, struct file **res) +int __close_fd_get_file(unsigned int fd, struct file **res) { struct files_struct *files = current->files; struct file *file; struct fdtable *fdt;
- spin_lock(&files->file_lock); fdt = files_fdtable(files); if (fd >= fdt->max_fds) - goto out_unlock; + goto out_err; file = fdt->fd[fd]; if (!file) - goto out_unlock; + goto out_err; rcu_assign_pointer(fdt->fd[fd], NULL); __put_unused_fd(files, fd); - spin_unlock(&files->file_lock); get_file(file); *res = file; return 0; - -out_unlock: - spin_unlock(&files->file_lock); +out_err: *res = NULL; return -ENOENT; }
+/* + * variant of close_fd that gets a ref on the file for later fput. + * The caller must ensure that filp_close() called on the file, and then + * an fput(). + */ +int close_fd_get_file(unsigned int fd, struct file **res) +{ + struct files_struct *files = current->files; + int ret; + + spin_lock(&files->file_lock); + ret = __close_fd_get_file(fd, res); + spin_unlock(&files->file_lock); + + return ret; +} + void do_close_on_exec(struct files_struct *files) { unsigned i; --- a/fs/internal.h +++ b/fs/internal.h @@ -132,6 +132,7 @@ extern struct file *do_file_open_root(st const char *, const struct open_flags *); extern struct open_how build_open_how(int flags, umode_t mode); extern int build_open_flags(const struct open_how *how, struct open_flags *op); +extern int __close_fd_get_file(unsigned int fd, struct file **res);
long do_sys_ftruncate(unsigned int fd, loff_t length, int small); int chmod_common(const struct path *path, umode_t mode);
From: Greg Kroah-Hartman gregkh@linuxfoundation.org
From: Jens Axboe axboe@kernel.dk
commit 9eac1904d3364254d622bf2c771c4f85cd435fc2 upstream
We currently split the close into two, in case we have a ->flush op that we can't safely handle from non-blocking context. This requires us to flag the op as uncancelable if we do need to punt it async, and that means special handling for just this op type.
Use __close_fd_get_file() and grab the files lock so we can get the file and check if we need to go async in one atomic operation. That gets rid of the need for splitting this into two steps, and hence the need for IO_WQ_WORK_NO_CANCEL.
Signed-off-by: Jens Axboe axboe@kernel.dk Signed-off-by: Pavel Begunkov asml.silence@gmail.com Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- fs/io_uring.c | 64 +++++++++++++++++++++++++++++++--------------------------- 1 file changed, 35 insertions(+), 29 deletions(-)
--- a/fs/io_uring.c +++ b/fs/io_uring.c @@ -411,7 +411,6 @@ struct io_poll_remove {
struct io_close { struct file *file; - struct file *put_file; int fd; };
@@ -908,8 +907,6 @@ static const struct io_op_def io_op_defs IO_WQ_WORK_FS | IO_WQ_WORK_MM, }, [IORING_OP_CLOSE] = { - .needs_file = 1, - .needs_file_no_error = 1, .work_flags = IO_WQ_WORK_FILES | IO_WQ_WORK_BLKCG, }, [IORING_OP_FILES_UPDATE] = { @@ -4473,13 +4470,6 @@ static int io_statx(struct io_kiocb *req
static int io_close_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe) { - /* - * If we queue this for async, it must not be cancellable. That would - * leave the 'file' in an undeterminate state, and here need to modify - * io_wq_work.flags, so initialize io_wq_work firstly. - */ - io_req_init_async(req); - if (unlikely(req->ctx->flags & IORING_SETUP_IOPOLL)) return -EINVAL; if (sqe->ioprio || sqe->off || sqe->addr || sqe->len || @@ -4489,43 +4479,59 @@ static int io_close_prep(struct io_kiocb return -EBADF;
req->close.fd = READ_ONCE(sqe->fd); - if ((req->file && req->file->f_op == &io_uring_fops)) - return -EBADF; - - req->close.put_file = NULL; return 0; }
static int io_close(struct io_kiocb *req, bool force_nonblock, struct io_comp_state *cs) { + struct files_struct *files = current->files; struct io_close *close = &req->close; + struct fdtable *fdt; + struct file *file; int ret;
- /* might be already done during nonblock submission */ - if (!close->put_file) { - ret = close_fd_get_file(close->fd, &close->put_file); - if (ret < 0) - return (ret == -ENOENT) ? -EBADF : ret; + file = NULL; + ret = -EBADF; + spin_lock(&files->file_lock); + fdt = files_fdtable(files); + if (close->fd >= fdt->max_fds) { + spin_unlock(&files->file_lock); + goto err; + } + file = fdt->fd[close->fd]; + if (!file) { + spin_unlock(&files->file_lock); + goto err; + } + + if (file->f_op == &io_uring_fops) { + spin_unlock(&files->file_lock); + file = NULL; + goto err; }
/* if the file has a flush method, be safe and punt to async */ - if (close->put_file->f_op->flush && force_nonblock) { - /* not safe to cancel at this point */ - req->work.flags |= IO_WQ_WORK_NO_CANCEL; - /* was never set, but play safe */ - req->flags &= ~REQ_F_NOWAIT; - /* avoid grabbing files - we don't need the files */ - req->flags |= REQ_F_NO_FILE_TABLE; + if (file->f_op->flush && force_nonblock) { + spin_unlock(&files->file_lock); return -EAGAIN; }
+ ret = __close_fd_get_file(close->fd, &file); + spin_unlock(&files->file_lock); + if (ret < 0) { + if (ret == -ENOENT) + ret = -EBADF; + goto err; + } + /* No ->flush() or already async, safely close from here */ - ret = filp_close(close->put_file, req->work.identity->files); + ret = filp_close(file, current->files); +err: if (ret < 0) req_set_fail_links(req); - fput(close->put_file); - close->put_file = NULL; + if (file) + fput(file); __io_req_complete(req, ret, 0, cs); return 0; }
From: Greg Kroah-Hartman gregkh@linuxfoundation.org
From: Jens Axboe axboe@kernel.dk
commit 4014d943cb62db892eb023d385a966a3fce5ee4c upstream
It's no longer used as IORING_OP_CLOSE got rid for the need of flagging it as uncancelable, kill it of.
Signed-off-by: Jens Axboe axboe@kernel.dk Signed-off-by: Pavel Begunkov asml.silence@gmail.com Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- fs/io-wq.c | 1 - fs/io-wq.h | 1 - fs/io_uring.c | 5 +---- 3 files changed, 1 insertion(+), 6 deletions(-)
--- a/fs/io-wq.c +++ b/fs/io-wq.c @@ -944,7 +944,6 @@ static bool io_wq_worker_cancel(struct i */ spin_lock_irqsave(&worker->lock, flags); if (worker->cur_work && - !(worker->cur_work->flags & IO_WQ_WORK_NO_CANCEL) && match->fn(worker->cur_work, match->data)) { send_sig(SIGINT, worker->task, 1); match->nr_running++; --- a/fs/io-wq.h +++ b/fs/io-wq.h @@ -9,7 +9,6 @@ enum { IO_WQ_WORK_CANCEL = 1, IO_WQ_WORK_HASHED = 2, IO_WQ_WORK_UNBOUND = 4, - IO_WQ_WORK_NO_CANCEL = 8, IO_WQ_WORK_CONCURRENT = 16,
IO_WQ_WORK_FILES = 32, --- a/fs/io_uring.c +++ b/fs/io_uring.c @@ -6388,11 +6388,8 @@ static struct io_wq_work *io_wq_submit_w if (timeout) io_queue_linked_timeout(timeout);
- /* if NO_CANCEL is set, we must still run the work */ - if ((work->flags & (IO_WQ_WORK_CANCEL|IO_WQ_WORK_NO_CANCEL)) == - IO_WQ_WORK_CANCEL) { + if (work->flags & IO_WQ_WORK_CANCEL) ret = -ECANCELED; - }
if (!ret) { do {
From: Greg Kroah-Hartman gregkh@linuxfoundation.org
From: Pavel Begunkov asml.silence@gmail.com
commit 5280f7e530f71ba85baf90169393196976ad0e52 upstream
Saving one lock/unlock for io-wq is not super important, but adds some ugliness in the code. More important, atomic decs not turning it to zero for some archs won't give the right ordering/barriers so the io_steal_work() may pretty easily get subtly and completely broken.
Return back 2-step io-wq work exchange and clean it up.
Signed-off-by: Pavel Begunkov asml.silence@gmail.com Signed-off-by: Jens Axboe axboe@kernel.dk Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- fs/io-wq.c | 16 ++++++---------- fs/io-wq.h | 4 ++-- fs/io_uring.c | 26 ++++---------------------- 3 files changed, 12 insertions(+), 34 deletions(-)
--- a/fs/io-wq.c +++ b/fs/io-wq.c @@ -555,23 +555,21 @@ get_next:
/* handle a whole dependent link */ do { - struct io_wq_work *old_work, *next_hashed, *linked; + struct io_wq_work *next_hashed, *linked; unsigned int hash = io_get_work_hash(work);
next_hashed = wq_next_work(work); io_impersonate_work(worker, work); + wq->do_work(work); + io_assign_current_work(worker, NULL);
- old_work = work; - linked = wq->do_work(work); - + linked = wq->free_work(work); work = next_hashed; if (!work && linked && !io_wq_is_hashed(linked)) { work = linked; linked = NULL; } io_assign_current_work(worker, work); - wq->free_work(old_work); - if (linked) io_wqe_enqueue(wqe, linked);
@@ -850,11 +848,9 @@ static void io_run_cancel(struct io_wq_w struct io_wq *wq = wqe->wq;
do { - struct io_wq_work *old_work = work; - work->flags |= IO_WQ_WORK_CANCEL; - work = wq->do_work(work); - wq->free_work(old_work); + wq->do_work(work); + work = wq->free_work(work); } while (work); }
--- a/fs/io-wq.h +++ b/fs/io-wq.h @@ -106,8 +106,8 @@ static inline struct io_wq_work *wq_next return container_of(work->list.next, struct io_wq_work, list); }
-typedef void (free_work_fn)(struct io_wq_work *); -typedef struct io_wq_work *(io_wq_work_fn)(struct io_wq_work *); +typedef struct io_wq_work *(free_work_fn)(struct io_wq_work *); +typedef void (io_wq_work_fn)(struct io_wq_work *);
struct io_wq_data { struct user_struct *user; --- a/fs/io_uring.c +++ b/fs/io_uring.c @@ -2365,22 +2365,6 @@ static inline void io_put_req_deferred(s io_free_req_deferred(req); }
-static struct io_wq_work *io_steal_work(struct io_kiocb *req) -{ - struct io_kiocb *nxt; - - /* - * A ref is owned by io-wq in which context we're. So, if that's the - * last one, it's safe to steal next work. False negatives are Ok, - * it just will be re-punted async in io_put_work() - */ - if (refcount_read(&req->refs) != 1) - return NULL; - - nxt = io_req_find_next(req); - return nxt ? &nxt->work : NULL; -} - static void io_double_put_req(struct io_kiocb *req) { /* drop both submit and complete references */ @@ -6378,7 +6362,7 @@ static int io_issue_sqe(struct io_kiocb return 0; }
-static struct io_wq_work *io_wq_submit_work(struct io_wq_work *work) +static void io_wq_submit_work(struct io_wq_work *work) { struct io_kiocb *req = container_of(work, struct io_kiocb, work); struct io_kiocb *timeout; @@ -6429,8 +6413,6 @@ static struct io_wq_work *io_wq_submit_w if (lock_ctx) mutex_unlock(&lock_ctx->uring_lock); } - - return io_steal_work(req); }
static inline struct file *io_file_from_index(struct io_ring_ctx *ctx, @@ -8062,12 +8044,12 @@ static int io_sqe_files_update(struct io return __io_sqe_files_update(ctx, &up, nr_args); }
-static void io_free_work(struct io_wq_work *work) +static struct io_wq_work *io_free_work(struct io_wq_work *work) { struct io_kiocb *req = container_of(work, struct io_kiocb, work);
- /* Consider that io_steal_work() relies on this ref */ - io_put_req(req); + req = io_put_req_find_next(req); + return req ? &req->work : NULL; }
static int io_init_wq_offload(struct io_ring_ctx *ctx,
From: Greg Kroah-Hartman gregkh@linuxfoundation.org
From: Pavel Begunkov asml.silence@gmail.com
commit 792bb6eb862333658bf1bd2260133f0507e2da8d upstream
[ 97.866748] a.out/2890 is trying to acquire lock: [ 97.867829] ffff8881046763e8 (&ctx->uring_lock){+.+.}-{3:3}, at: io_wq_submit_work+0x155/0x240 [ 97.869735] [ 97.869735] but task is already holding lock: [ 97.871033] ffff88810dfe0be8 (&ctx->uring_lock){+.+.}-{3:3}, at: __x64_sys_io_uring_enter+0x3f0/0x5b0 [ 97.873074] [ 97.873074] other info that might help us debug this: [ 97.874520] Possible unsafe locking scenario: [ 97.874520] [ 97.875845] CPU0 [ 97.876440] ---- [ 97.877048] lock(&ctx->uring_lock); [ 97.877961] lock(&ctx->uring_lock); [ 97.878881] [ 97.878881] *** DEADLOCK *** [ 97.878881] [ 97.880341] May be due to missing lock nesting notation [ 97.880341] [ 97.881952] 1 lock held by a.out/2890: [ 97.882873] #0: ffff88810dfe0be8 (&ctx->uring_lock){+.+.}-{3:3}, at: __x64_sys_io_uring_enter+0x3f0/0x5b0 [ 97.885108] [ 97.885108] stack backtrace: [ 97.890457] Call Trace: [ 97.891121] dump_stack+0xac/0xe3 [ 97.891972] __lock_acquire+0xab6/0x13a0 [ 97.892940] lock_acquire+0x2c3/0x390 [ 97.894894] __mutex_lock+0xae/0x9f0 [ 97.901101] io_wq_submit_work+0x155/0x240 [ 97.902112] io_wq_cancel_cb+0x162/0x490 [ 97.904126] io_async_find_and_cancel+0x3b/0x140 [ 97.905247] io_issue_sqe+0x86d/0x13e0 [ 97.909122] __io_queue_sqe+0x10b/0x550 [ 97.913971] io_queue_sqe+0x235/0x470 [ 97.914894] io_submit_sqes+0xcce/0xf10 [ 97.917872] __x64_sys_io_uring_enter+0x3fb/0x5b0 [ 97.921424] do_syscall_64+0x2d/0x40 [ 97.922329] entry_SYSCALL_64_after_hwframe+0x44/0xa9
While holding uring_lock, e.g. from inline execution, async cancel request may attempt cancellations through io_wq_submit_work, which may try to grab a lock. Delay it to task_work, so we do it from a clean context and don't have to worry about locking.
Cc: stable@vger.kernel.org # 5.5+ Fixes: c07e6719511e ("io_uring: hold uring_lock while completing failed polled io in io_wq_submit_work()") Reported-by: Abaci abaci@linux.alibaba.com Reported-by: Hao Xu haoxu@linux.alibaba.com Signed-off-by: Pavel Begunkov asml.silence@gmail.com Signed-off-by: Jens Axboe axboe@kernel.dk Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- fs/io_uring.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-)
--- a/fs/io_uring.c +++ b/fs/io_uring.c @@ -2198,7 +2198,9 @@ static void io_req_task_cancel(struct ca struct io_kiocb *req = container_of(cb, struct io_kiocb, task_work); struct io_ring_ctx *ctx = req->ctx;
+ mutex_lock(&ctx->uring_lock); __io_req_task_cancel(req, -ECANCELED); + mutex_unlock(&ctx->uring_lock); percpu_ref_put(&ctx->refs); }
@@ -6372,8 +6374,13 @@ static void io_wq_submit_work(struct io_ if (timeout) io_queue_linked_timeout(timeout);
- if (work->flags & IO_WQ_WORK_CANCEL) - ret = -ECANCELED; + if (work->flags & IO_WQ_WORK_CANCEL) { + /* io-wq is going to take down one */ + refcount_inc(&req->refs); + percpu_ref_get(&req->ctx->refs); + io_req_task_work_add_fallback(req, io_req_task_cancel); + return; + }
if (!ret) { do {
From: Greg Kroah-Hartman gregkh@linuxfoundation.org
From: Jernej Skrabec jernej.skrabec@siol.net
commit 7072db89572135f28cad65f15877bf7e67cf2ff8 upstream.
According to v4l2 request api specifications, it's allowed to skip control if its content isn't changed for performance reasons. Cedrus driver predates that, so it has implemented mechanism to check if all required controls are included in one request.
Conform to specifications with removing that mechanism.
Note that this mechanism with static required flag isn't very good anyway because need for control is usually signaled in other controls.
Fixes: 50e761516f2b ("media: platform: Add Cedrus VPU decoder driver") Signed-off-by: Jernej Skrabec jernej.skrabec@siol.net Signed-off-by: Hans Verkuil hverkuil-cisco@xs4all.nl Signed-off-by: Mauro Carvalho Chehab mchehab+huawei@kernel.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/staging/media/sunxi/cedrus/cedrus.c | 49 ---------------------------- drivers/staging/media/sunxi/cedrus/cedrus.h | 1 2 files changed, 50 deletions(-)
--- a/drivers/staging/media/sunxi/cedrus/cedrus.c +++ b/drivers/staging/media/sunxi/cedrus/cedrus.c @@ -34,56 +34,48 @@ static const struct cedrus_control cedru .id = V4L2_CID_MPEG_VIDEO_MPEG2_SLICE_PARAMS, }, .codec = CEDRUS_CODEC_MPEG2, - .required = true, }, { .cfg = { .id = V4L2_CID_MPEG_VIDEO_MPEG2_QUANTIZATION, }, .codec = CEDRUS_CODEC_MPEG2, - .required = false, }, { .cfg = { .id = V4L2_CID_STATELESS_H264_DECODE_PARAMS, }, .codec = CEDRUS_CODEC_H264, - .required = true, }, { .cfg = { .id = V4L2_CID_STATELESS_H264_SLICE_PARAMS, }, .codec = CEDRUS_CODEC_H264, - .required = true, }, { .cfg = { .id = V4L2_CID_STATELESS_H264_SPS, }, .codec = CEDRUS_CODEC_H264, - .required = true, }, { .cfg = { .id = V4L2_CID_STATELESS_H264_PPS, }, .codec = CEDRUS_CODEC_H264, - .required = true, }, { .cfg = { .id = V4L2_CID_STATELESS_H264_SCALING_MATRIX, }, .codec = CEDRUS_CODEC_H264, - .required = false, }, { .cfg = { .id = V4L2_CID_STATELESS_H264_PRED_WEIGHTS, }, .codec = CEDRUS_CODEC_H264, - .required = false, }, { .cfg = { @@ -92,7 +84,6 @@ static const struct cedrus_control cedru .def = V4L2_STATELESS_H264_DECODE_MODE_SLICE_BASED, }, .codec = CEDRUS_CODEC_H264, - .required = false, }, { .cfg = { @@ -101,7 +92,6 @@ static const struct cedrus_control cedru .def = V4L2_STATELESS_H264_START_CODE_NONE, }, .codec = CEDRUS_CODEC_H264, - .required = false, }, /* * We only expose supported profiles information, @@ -120,28 +110,24 @@ static const struct cedrus_control cedru BIT(V4L2_MPEG_VIDEO_H264_PROFILE_EXTENDED), }, .codec = CEDRUS_CODEC_H264, - .required = false, }, { .cfg = { .id = V4L2_CID_MPEG_VIDEO_HEVC_SPS, }, .codec = CEDRUS_CODEC_H265, - .required = true, }, { .cfg = { .id = V4L2_CID_MPEG_VIDEO_HEVC_PPS, }, .codec = CEDRUS_CODEC_H265, - .required = true, }, { .cfg = { .id = V4L2_CID_MPEG_VIDEO_HEVC_SLICE_PARAMS, }, .codec = CEDRUS_CODEC_H265, - .required = true, }, { .cfg = { @@ -150,7 +136,6 @@ static const struct cedrus_control cedru .def = V4L2_MPEG_VIDEO_HEVC_DECODE_MODE_SLICE_BASED, }, .codec = CEDRUS_CODEC_H265, - .required = false, }, { .cfg = { @@ -159,14 +144,12 @@ static const struct cedrus_control cedru .def = V4L2_MPEG_VIDEO_HEVC_START_CODE_NONE, }, .codec = CEDRUS_CODEC_H265, - .required = false, }, { .cfg = { .id = V4L2_CID_MPEG_VIDEO_VP8_FRAME_HEADER, }, .codec = CEDRUS_CODEC_VP8, - .required = true, }, };
@@ -227,12 +210,8 @@ static int cedrus_init_ctrls(struct cedr static int cedrus_request_validate(struct media_request *req) { struct media_request_object *obj; - struct v4l2_ctrl_handler *parent_hdl, *hdl; struct cedrus_ctx *ctx = NULL; - struct v4l2_ctrl *ctrl_test; unsigned int count; - unsigned int i; - int ret = 0;
list_for_each_entry(obj, &req->objects, list) { struct vb2_buffer *vb; @@ -259,34 +238,6 @@ static int cedrus_request_validate(struc return -EINVAL; }
- parent_hdl = &ctx->hdl; - - hdl = v4l2_ctrl_request_hdl_find(req, parent_hdl); - if (!hdl) { - v4l2_info(&ctx->dev->v4l2_dev, "Missing codec control(s)\n"); - return -ENOENT; - } - - for (i = 0; i < CEDRUS_CONTROLS_COUNT; i++) { - if (cedrus_controls[i].codec != ctx->current_codec || - !cedrus_controls[i].required) - continue; - - ctrl_test = v4l2_ctrl_request_hdl_ctrl_find(hdl, - cedrus_controls[i].cfg.id); - if (!ctrl_test) { - v4l2_info(&ctx->dev->v4l2_dev, - "Missing required codec control\n"); - ret = -ENOENT; - break; - } - } - - v4l2_ctrl_request_hdl_put(hdl); - - if (ret) - return ret; - return vb2_request_validate(req); }
--- a/drivers/staging/media/sunxi/cedrus/cedrus.h +++ b/drivers/staging/media/sunxi/cedrus/cedrus.h @@ -56,7 +56,6 @@ enum cedrus_h264_pic_type { struct cedrus_control { struct v4l2_ctrl_config cfg; enum cedrus_codec codec; - unsigned char required:1; };
struct cedrus_h264_run {
From: Greg Kroah-Hartman gregkh@linuxfoundation.org
From: "Zolt�n B�sz�rm�nyi" zboszor@gmail.com
commit dc22c1c058b5c4fe967a20589e36f029ee42a706 upstream
My 2TB SKC2000 showed the exact same symptoms that were provided in 538e4a8c57 ("nvme-pci: avoid the deepest sleep state on Kingston A2000 SSDs"), i.e. a complete NVME lockup that needed cold boot to get it back.
According to some sources, the A2000 is simply a rebadged SKC2000 with a slightly optimized firmware.
Adding the SKC2000 PCI ID to the quirk list with the same workaround as the A2000 made my laptop survive a 5 hours long Yocto bootstrap buildfest which reliably triggered the SSD lockup previously.
Signed-off-by: Zoltán Böszörményi zboszor@gmail.com Signed-off-by: Christoph Hellwig hch@lst.de Signed-off-by: Sudip Mukherjee sudipm.mukherjee@gmail.com Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/nvme/host/pci.c | 2 ++ 1 file changed, 2 insertions(+)
--- a/drivers/nvme/host/pci.c +++ b/drivers/nvme/host/pci.c @@ -3261,6 +3261,8 @@ static const struct pci_device_id nvme_i .driver_data = NVME_QUIRK_DISABLE_WRITE_ZEROES, }, { PCI_DEVICE(0x1d97, 0x2263), /* SPCC */ .driver_data = NVME_QUIRK_DISABLE_WRITE_ZEROES, }, + { PCI_DEVICE(0x2646, 0x2262), /* KINGSTON SKC2000 NVMe SSD */ + .driver_data = NVME_QUIRK_NO_DEEPEST_PS, }, { PCI_DEVICE(0x2646, 0x2263), /* KINGSTON A2000 NVMe SSD */ .driver_data = NVME_QUIRK_NO_DEEPEST_PS, }, { PCI_DEVICE(PCI_VENDOR_ID_APPLE, 0x2001),
From: Greg Kroah-Hartman gregkh@linuxfoundation.org
From: Helge Deller deller@gmx.de
commit 778e45d7720d663811352943dd515b41f6849637 upstream
The kernel test robot reported multiple linkage problems like this:
hppa64-linux-ld: init/main.o(.init.text+0x56c): cannot reach printk init/main.o: in function `unknown_bootoption': (.init.text+0x56c): relocation truncated to fit: R_PARISC_PCREL22F against symbol `printk' defined in .text.unlikely section in kernel/printk/printk.o
There are two ways to solve it: a) Enable the -mlong-call compiler option (CONFIG_MLONGCALLS), b) Add long branch stub support in 64-bit linker.
While b) is the long-term solution, this patch works around the issue by automatically enabling the CONFIG_MLONGCALLS option when CONFIG_COMPILE_TEST is set, which indicates that a non-production kernel (e.g. 0-day kernel) is built.
Signed-off-by: Helge Deller deller@gmx.de Reported-by: kernel test robot lkp@intel.com Fixes: 00e35f2b0e8a ("parisc: Enable -mlong-calls gcc option by default when !CONFIG_MODULES") Cc: stable@vger.kernel.org # v5.6+ Signed-off-by: Sudip Mukherjee sudipm.mukherjee@gmail.com Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- arch/parisc/Kconfig | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-)
--- a/arch/parisc/Kconfig +++ b/arch/parisc/Kconfig @@ -201,9 +201,12 @@ config PREFETCH def_bool y depends on PA8X00 || PA7200
+config PARISC_HUGE_KERNEL + def_bool y if !MODULES || UBSAN || FTRACE || COMPILE_TEST + config MLONGCALLS - def_bool y if !MODULES || UBSAN || FTRACE - bool "Enable the -mlong-calls compiler option for big kernels" if MODULES && !UBSAN && !FTRACE + def_bool y if PARISC_HUGE_KERNEL + bool "Enable the -mlong-calls compiler option for big kernels" if !PARISC_HUGE_KERNEL depends on PA8X00 help If you configure the kernel to include many drivers built-in instead
From: Greg Kroah-Hartman gregkh@linuxfoundation.org
From: Nathan Chancellor nathan@kernel.org
commit e9c6deee00e9197e75cd6aa0d265d3d45bd7cc28 upstream
Similar to commit 28187dc8ebd9 ("ARM: 9025/1: Kconfig: CPU_BIG_ENDIAN depends on !LD_IS_LLD"), ld.lld prior to 13.0.0 does not properly support aarch64 big endian, leading to the following build error when CONFIG_CPU_BIG_ENDIAN is selected:
ld.lld: error: unknown emulation: aarch64linuxb
This has been resolved in LLVM 13. To avoid errors like this, only allow CONFIG_CPU_BIG_ENDIAN to be selected if using ld.bfd or ld.lld 13.0.0 and newer.
While we are here, the indentation of this symbol used spaces since its introduction in commit a872013d6d03 ("arm64: kconfig: allow CPU_BIG_ENDIAN to be selected"). Change it to tabs to be consistent with kernel coding style.
Link: https://github.com/ClangBuiltLinux/linux/issues/380 Link: https://github.com/ClangBuiltLinux/linux/issues/1288 Link: https://github.com/llvm/llvm-project/commit/7605a9a009b5fa3bdac07e3131c8d82f... Link: https://github.com/llvm/llvm-project/commit/eea34aae2e74e9b6fbdd5b95f479bc7f... Reported-by: Arnd Bergmann arnd@arndb.de Signed-off-by: Nathan Chancellor nathan@kernel.org Reviewed-by: Nick Desaulniers ndesaulniers@google.com Link: https://lore.kernel.org/r/20210209005719.803608-1-nathan@kernel.org Signed-off-by: Will Deacon will@kernel.org Signed-off-by: Sudip Mukherjee sudipm.mukherjee@gmail.com Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- arch/arm64/Kconfig | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-)
--- a/arch/arm64/Kconfig +++ b/arch/arm64/Kconfig @@ -952,8 +952,9 @@ choice that is selected here.
config CPU_BIG_ENDIAN - bool "Build big-endian kernel" - help + bool "Build big-endian kernel" + depends on !LD_IS_LLD || LLD_VERSION >= 130000 + help Say Y if you plan on running a kernel with a big-endian userspace.
config CPU_LITTLE_ENDIAN
From: Greg Kroah-Hartman gregkh@linuxfoundation.org
From: Nikolay Borisov nborisov@suse.com
commit 80e9baed722c853056e0c5374f51524593cb1031 upstream
Signed-off-by: Nikolay Borisov nborisov@suse.com Reviewed-by: David Sterba dsterba@suse.com Signed-off-by: David Sterba dsterba@suse.com Signed-off-by: Sudip Mukherjee sudipm.mukherjee@gmail.com Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- fs/btrfs/qgroup.c | 8 ++++---- fs/btrfs/qgroup.h | 2 ++ 2 files changed, 6 insertions(+), 4 deletions(-)
--- a/fs/btrfs/qgroup.c +++ b/fs/btrfs/qgroup.c @@ -3841,8 +3841,8 @@ static int sub_root_meta_rsv(struct btrf return num_bytes; }
-static int qgroup_reserve_meta(struct btrfs_root *root, int num_bytes, - enum btrfs_qgroup_rsv_type type, bool enforce) +int btrfs_qgroup_reserve_meta(struct btrfs_root *root, int num_bytes, + enum btrfs_qgroup_rsv_type type, bool enforce) { struct btrfs_fs_info *fs_info = root->fs_info; int ret; @@ -3873,14 +3873,14 @@ int __btrfs_qgroup_reserve_meta(struct b { int ret;
- ret = qgroup_reserve_meta(root, num_bytes, type, enforce); + ret = btrfs_qgroup_reserve_meta(root, num_bytes, type, enforce); if (ret <= 0 && ret != -EDQUOT) return ret;
ret = try_flush_qgroup(root); if (ret < 0) return ret; - return qgroup_reserve_meta(root, num_bytes, type, enforce); + return btrfs_qgroup_reserve_meta(root, num_bytes, type, enforce); }
void btrfs_qgroup_free_meta_all_pertrans(struct btrfs_root *root) --- a/fs/btrfs/qgroup.h +++ b/fs/btrfs/qgroup.h @@ -361,6 +361,8 @@ int btrfs_qgroup_release_data(struct btr int btrfs_qgroup_free_data(struct btrfs_inode *inode, struct extent_changeset *reserved, u64 start, u64 len); +int btrfs_qgroup_reserve_meta(struct btrfs_root *root, int num_bytes, + enum btrfs_qgroup_rsv_type type, bool enforce); int __btrfs_qgroup_reserve_meta(struct btrfs_root *root, int num_bytes, enum btrfs_qgroup_rsv_type type, bool enforce); /* Reserve metadata space for pertrans and prealloc type */
From: Greg Kroah-Hartman gregkh@linuxfoundation.org
From: Nikolay Borisov nborisov@suse.com
commit 4d14c5cde5c268a2bc26addecf09489cb953ef64 upstream
Calling btrfs_qgroup_reserve_meta_prealloc from btrfs_delayed_inode_reserve_metadata can result in flushing delalloc while holding a transaction and delayed node locks. This is deadlock prone. In the past multiple commits:
* ae5e070eaca9 ("btrfs: qgroup: don't try to wait flushing if we're already holding a transaction")
* 6f23277a49e6 ("btrfs: qgroup: don't commit transaction when we already hold the handle")
Tried to solve various aspects of this but this was always a whack-a-mole game. Unfortunately those 2 fixes don't solve a deadlock scenario involving btrfs_delayed_node::mutex. Namely, one thread can call btrfs_dirty_inode as a result of reading a file and modifying its atime:
PID: 6963 TASK: ffff8c7f3f94c000 CPU: 2 COMMAND: "test" #0 __schedule at ffffffffa529e07d #1 schedule at ffffffffa529e4ff #2 schedule_timeout at ffffffffa52a1bdd #3 wait_for_completion at ffffffffa529eeea <-- sleeps with delayed node mutex held #4 start_delalloc_inodes at ffffffffc0380db5 #5 btrfs_start_delalloc_snapshot at ffffffffc0393836 #6 try_flush_qgroup at ffffffffc03f04b2 #7 __btrfs_qgroup_reserve_meta at ffffffffc03f5bb6 <-- tries to reserve space and starts delalloc inodes. #8 btrfs_delayed_update_inode at ffffffffc03e31aa <-- acquires delayed node mutex #9 btrfs_update_inode at ffffffffc0385ba8 #10 btrfs_dirty_inode at ffffffffc038627b <-- TRANSACTIION OPENED #11 touch_atime at ffffffffa4cf0000 #12 generic_file_read_iter at ffffffffa4c1f123 #13 new_sync_read at ffffffffa4ccdc8a #14 vfs_read at ffffffffa4cd0849 #15 ksys_read at ffffffffa4cd0bd1 #16 do_syscall_64 at ffffffffa4a052eb #17 entry_SYSCALL_64_after_hwframe at ffffffffa540008c
This will cause an asynchronous work to flush the delalloc inodes to happen which can try to acquire the same delayed_node mutex:
PID: 455 TASK: ffff8c8085fa4000 CPU: 5 COMMAND: "kworker/u16:30" #0 __schedule at ffffffffa529e07d #1 schedule at ffffffffa529e4ff #2 schedule_preempt_disabled at ffffffffa529e80a #3 __mutex_lock at ffffffffa529fdcb <-- goes to sleep, never wakes up. #4 btrfs_delayed_update_inode at ffffffffc03e3143 <-- tries to acquire the mutex #5 btrfs_update_inode at ffffffffc0385ba8 <-- this is the same inode that pid 6963 is holding #6 cow_file_range_inline.constprop.78 at ffffffffc0386be7 #7 cow_file_range at ffffffffc03879c1 #8 btrfs_run_delalloc_range at ffffffffc038894c #9 writepage_delalloc at ffffffffc03a3c8f #10 __extent_writepage at ffffffffc03a4c01 #11 extent_write_cache_pages at ffffffffc03a500b #12 extent_writepages at ffffffffc03a6de2 #13 do_writepages at ffffffffa4c277eb #14 __filemap_fdatawrite_range at ffffffffa4c1e5bb #15 btrfs_run_delalloc_work at ffffffffc0380987 <-- starts running delayed nodes #16 normal_work_helper at ffffffffc03b706c #17 process_one_work at ffffffffa4aba4e4 #18 worker_thread at ffffffffa4aba6fd #19 kthread at ffffffffa4ac0a3d #20 ret_from_fork at ffffffffa54001ff
To fully address those cases the complete fix is to never issue any flushing while holding the transaction or the delayed node lock. This patch achieves it by calling qgroup_reserve_meta directly which will either succeed without flushing or will fail and return -EDQUOT. In the latter case that return value is going to be propagated to btrfs_dirty_inode which will fallback to start a new transaction. That's fine as the majority of time we expect the inode will have BTRFS_DELAYED_NODE_INODE_DIRTY flag set which will result in directly copying the in-memory state.
Fixes: c53e9653605d ("btrfs: qgroup: try to flush qgroup space when we get -EDQUOT") CC: stable@vger.kernel.org # 5.10+ Reviewed-by: Qu Wenruo wqu@suse.com Signed-off-by: Nikolay Borisov nborisov@suse.com Signed-off-by: David Sterba dsterba@suse.com Signed-off-by: Sudip Mukherjee sudipm.mukherjee@gmail.com Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- fs/btrfs/delayed-inode.c | 3 ++- fs/btrfs/inode.c | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-)
--- a/fs/btrfs/delayed-inode.c +++ b/fs/btrfs/delayed-inode.c @@ -627,7 +627,8 @@ static int btrfs_delayed_inode_reserve_m */ if (!src_rsv || (!trans->bytes_reserved && src_rsv->type != BTRFS_BLOCK_RSV_DELALLOC)) { - ret = btrfs_qgroup_reserve_meta_prealloc(root, num_bytes, true); + ret = btrfs_qgroup_reserve_meta(root, num_bytes, + BTRFS_QGROUP_RSV_META_PREALLOC, true); if (ret < 0) return ret; ret = btrfs_block_rsv_add(root, dst_rsv, num_bytes, --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c @@ -5916,7 +5916,7 @@ static int btrfs_dirty_inode(struct inod return PTR_ERR(trans);
ret = btrfs_update_inode(trans, root, BTRFS_I(inode)); - if (ret && ret == -ENOSPC) { + if (ret && (ret == -ENOSPC || ret == -EDQUOT)) { /* whoops, lets try again with the full transaction */ btrfs_end_transaction(trans); trans = btrfs_start_transaction(root, 1);
From: Greg Kroah-Hartman gregkh@linuxfoundation.org
From: Andrey Ryabinin arbn@yandex-team.com
commit 140456f994195b568ecd7fc2287a34eadffef3ca upstream.
increase_address_space() calls get_zeroed_page(gfp) under spin_lock with disabled interrupts. gfp flags passed to increase_address_space() may allow sleeping, so it comes to this:
BUG: sleeping function called from invalid context at mm/page_alloc.c:4342 in_atomic(): 1, irqs_disabled(): 1, pid: 21555, name: epdcbbf1qnhbsd8
Call Trace: dump_stack+0x66/0x8b ___might_sleep+0xec/0x110 __alloc_pages_nodemask+0x104/0x300 get_zeroed_page+0x15/0x40 iommu_map_page+0xdd/0x3e0 amd_iommu_map+0x50/0x70 iommu_map+0x106/0x220 vfio_iommu_type1_ioctl+0x76e/0x950 [vfio_iommu_type1] do_vfs_ioctl+0xa3/0x6f0 ksys_ioctl+0x66/0x70 __x64_sys_ioctl+0x16/0x20 do_syscall_64+0x4e/0x100 entry_SYSCALL_64_after_hwframe+0x44/0xa9
Fix this by moving get_zeroed_page() out of spin_lock/unlock section.
Fixes: 754265bcab ("iommu/amd: Fix race in increase_address_space()") Signed-off-by: Andrey Ryabinin arbn@yandex-team.com Acked-by: Will Deacon will@kernel.org Cc: stable@vger.kernel.org Link: https://lore.kernel.org/r/20210217143004.19165-1-arbn@yandex-team.com Signed-off-by: Joerg Roedel jroedel@suse.de Signed-off-by: Andrey Ryabinin arbn@yandex-team.com Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org
--- drivers/iommu/amd/iommu.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-)
--- a/drivers/iommu/amd/iommu.c +++ b/drivers/iommu/amd/iommu.c @@ -1502,6 +1502,10 @@ static bool increase_address_space(struc bool ret = true; u64 *pte;
+ pte = (void *)get_zeroed_page(gfp); + if (!pte) + return false; + spin_lock_irqsave(&domain->lock, flags);
amd_iommu_domain_get_pgtable(domain, &pgtable); @@ -1513,10 +1517,6 @@ static bool increase_address_space(struc if (WARN_ON_ONCE(pgtable.mode == PAGE_MODE_6_LEVEL)) goto out;
- pte = (void *)get_zeroed_page(gfp); - if (!pte) - goto out; - *pte = PM_LEVEL_PDE(pgtable.mode, iommu_virt_to_phys(pgtable.root));
pgtable.root = pte; @@ -1530,10 +1530,12 @@ static bool increase_address_space(struc */ amd_iommu_domain_set_pgtable(domain, pte, pgtable.mode);
+ pte = NULL; ret = true;
out: spin_unlock_irqrestore(&domain->lock, flags); + free_page((unsigned long)pte);
return ret; }
From: Greg Kroah-Hartman gregkh@linuxfoundation.org
From: Stanley Chu stanley.chu@mediatek.com
[ Upstream commit 46ec9592ffd679fa26142dcb9e5119aad7e60b55 ]
Flush during hibern8 is sufficient on MediaTek platforms, thus enable UFSHCI_QUIRK_SKIP_MANUAL_WB_FLUSH_CTRL to skip enabling fWriteBoosterBufferFlush during WriteBooster initialization.
Link: https://lore.kernel.org/r/20201222072928.32328-1-stanley.chu@mediatek.com Reviewed-by: Avri Altman avri.altman@wdc.com Signed-off-by: Stanley Chu stanley.chu@mediatek.com Signed-off-by: Martin K. Petersen martin.petersen@oracle.com Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/scsi/ufs/ufs-mediatek.c | 1 + 1 file changed, 1 insertion(+)
diff --git a/drivers/scsi/ufs/ufs-mediatek.c b/drivers/scsi/ufs/ufs-mediatek.c index 80618af7c872..c55202b92a43 100644 --- a/drivers/scsi/ufs/ufs-mediatek.c +++ b/drivers/scsi/ufs/ufs-mediatek.c @@ -661,6 +661,7 @@ static int ufs_mtk_init(struct ufs_hba *hba)
/* Enable WriteBooster */ hba->caps |= UFSHCD_CAP_WB_EN; + hba->quirks |= UFSHCI_QUIRK_SKIP_MANUAL_WB_FLUSH_CTRL; hba->vps->wb_flush_threshold = UFS_WB_BUF_REMAIN_PERCENT(80);
if (host->caps & UFS_MTK_CAP_DISABLE_AH8)
From: Greg Kroah-Hartman gregkh@linuxfoundation.org
From: Kiwoong Kim kwmad.kim@samsung.com
[ Upstream commit b1d0d2eb89d4e3a25b212a9d836587503537067e ]
The UniPro specification states that attribute IDs of the following parameters are vendor-specific so some SoCs could have no regions at the defined addresses:
- DME_LocalFC0ProtectionTimeOutVal - DME_LocalTC0ReplayTimeOutVal - DME_LocalAFC0ReqTimeOutVal
In addition, the following parameters should be set considering the compatibility between host and device.
- PA_PWRMODEUSERDATA0 - PA_PWRMODEUSERDATA1 - PA_PWRMODEUSERDATA2 - PA_PWRMODEUSERDATA3 - PA_PWRMODEUSERDATA4 - PA_PWRMODEUSERDATA5
Introduce a quirk to allow vendor drivers to override the UniPro defaults.
Link: https://lore.kernel.org/r/1fedd3dea0ccc980913a5995a10510d86a5b01b9.160851378... Acked-by: Avri Altman Avri.Altman@wdc.com Signed-off-by: Kiwoong Kim kwmad.kim@samsung.com Signed-off-by: Martin K. Petersen martin.petersen@oracle.com Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/scsi/ufs/ufshcd.c | 40 ++++++++++++++++++++------------------- drivers/scsi/ufs/ufshcd.h | 6 ++++++ 2 files changed, 27 insertions(+), 19 deletions(-)
diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c index 728168cd18f5..8ecdd53c9746 100644 --- a/drivers/scsi/ufs/ufshcd.c +++ b/drivers/scsi/ufs/ufshcd.c @@ -4220,25 +4220,27 @@ static int ufshcd_change_power_mode(struct ufs_hba *hba, ufshcd_dme_set(hba, UIC_ARG_MIB(PA_HSSERIES), pwr_mode->hs_rate);
- ufshcd_dme_set(hba, UIC_ARG_MIB(PA_PWRMODEUSERDATA0), - DL_FC0ProtectionTimeOutVal_Default); - ufshcd_dme_set(hba, UIC_ARG_MIB(PA_PWRMODEUSERDATA1), - DL_TC0ReplayTimeOutVal_Default); - ufshcd_dme_set(hba, UIC_ARG_MIB(PA_PWRMODEUSERDATA2), - DL_AFC0ReqTimeOutVal_Default); - ufshcd_dme_set(hba, UIC_ARG_MIB(PA_PWRMODEUSERDATA3), - DL_FC1ProtectionTimeOutVal_Default); - ufshcd_dme_set(hba, UIC_ARG_MIB(PA_PWRMODEUSERDATA4), - DL_TC1ReplayTimeOutVal_Default); - ufshcd_dme_set(hba, UIC_ARG_MIB(PA_PWRMODEUSERDATA5), - DL_AFC1ReqTimeOutVal_Default); - - ufshcd_dme_set(hba, UIC_ARG_MIB(DME_LocalFC0ProtectionTimeOutVal), - DL_FC0ProtectionTimeOutVal_Default); - ufshcd_dme_set(hba, UIC_ARG_MIB(DME_LocalTC0ReplayTimeOutVal), - DL_TC0ReplayTimeOutVal_Default); - ufshcd_dme_set(hba, UIC_ARG_MIB(DME_LocalAFC0ReqTimeOutVal), - DL_AFC0ReqTimeOutVal_Default); + if (!(hba->quirks & UFSHCD_QUIRK_SKIP_DEF_UNIPRO_TIMEOUT_SETTING)) { + ufshcd_dme_set(hba, UIC_ARG_MIB(PA_PWRMODEUSERDATA0), + DL_FC0ProtectionTimeOutVal_Default); + ufshcd_dme_set(hba, UIC_ARG_MIB(PA_PWRMODEUSERDATA1), + DL_TC0ReplayTimeOutVal_Default); + ufshcd_dme_set(hba, UIC_ARG_MIB(PA_PWRMODEUSERDATA2), + DL_AFC0ReqTimeOutVal_Default); + ufshcd_dme_set(hba, UIC_ARG_MIB(PA_PWRMODEUSERDATA3), + DL_FC1ProtectionTimeOutVal_Default); + ufshcd_dme_set(hba, UIC_ARG_MIB(PA_PWRMODEUSERDATA4), + DL_TC1ReplayTimeOutVal_Default); + ufshcd_dme_set(hba, UIC_ARG_MIB(PA_PWRMODEUSERDATA5), + DL_AFC1ReqTimeOutVal_Default); + + ufshcd_dme_set(hba, UIC_ARG_MIB(DME_LocalFC0ProtectionTimeOutVal), + DL_FC0ProtectionTimeOutVal_Default); + ufshcd_dme_set(hba, UIC_ARG_MIB(DME_LocalTC0ReplayTimeOutVal), + DL_TC0ReplayTimeOutVal_Default); + ufshcd_dme_set(hba, UIC_ARG_MIB(DME_LocalAFC0ReqTimeOutVal), + DL_AFC0ReqTimeOutVal_Default); + }
ret = ufshcd_uic_change_pwr_mode(hba, pwr_mode->pwr_rx << 4 | pwr_mode->pwr_tx); diff --git a/drivers/scsi/ufs/ufshcd.h b/drivers/scsi/ufs/ufshcd.h index aa9ea3552323..85f9d0fbfbd9 100644 --- a/drivers/scsi/ufs/ufshcd.h +++ b/drivers/scsi/ufs/ufshcd.h @@ -551,6 +551,12 @@ enum ufshcd_quirks { */ UFSHCI_QUIRK_SKIP_MANUAL_WB_FLUSH_CTRL = 1 << 12,
+ /* + * This quirk needs to disable unipro timeout values + * before power mode change + */ + UFSHCD_QUIRK_SKIP_DEF_UNIPRO_TIMEOUT_SETTING = 1 << 13, + };
enum ufshcd_caps {
From: Greg Kroah-Hartman gregkh@linuxfoundation.org
From: Aswath Govindraju a-govindraju@ti.com
[ Upstream commit f6f1f8e6e3eea25f539105d48166e91f0ab46dd1 ]
A dummy zero bit is sent preceding the data during a read transfer by the Microchip 93LC46B eeprom (section 2.7 of[1]). This results in right shift of data during a read. In order to ignore this bit a quirk can be added to send an extra zero bit after the read address.
Add a quirk to ignore the zero bit sent before data by adding a zero bit after the read address.
[1] - https://www.mouser.com/datasheet/2/268/20001749K-277859.pdf
Signed-off-by: Aswath Govindraju a-govindraju@ti.com Link: https://lore.kernel.org/r/20210105105817.17644-3-a-govindraju@ti.com Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/misc/eeprom/eeprom_93xx46.c | 15 +++++++++++++++ include/linux/eeprom_93xx46.h | 2 ++ 2 files changed, 17 insertions(+)
diff --git a/drivers/misc/eeprom/eeprom_93xx46.c b/drivers/misc/eeprom/eeprom_93xx46.c index d92c4d2c521a..6e5f544c9c73 100644 --- a/drivers/misc/eeprom/eeprom_93xx46.c +++ b/drivers/misc/eeprom/eeprom_93xx46.c @@ -35,6 +35,10 @@ static const struct eeprom_93xx46_devtype_data atmel_at93c46d_data = { EEPROM_93XX46_QUIRK_INSTRUCTION_LENGTH, };
+static const struct eeprom_93xx46_devtype_data microchip_93lc46b_data = { + .quirks = EEPROM_93XX46_QUIRK_EXTRA_READ_CYCLE, +}; + struct eeprom_93xx46_dev { struct spi_device *spi; struct eeprom_93xx46_platform_data *pdata; @@ -55,6 +59,11 @@ static inline bool has_quirk_instruction_length(struct eeprom_93xx46_dev *edev) return edev->pdata->quirks & EEPROM_93XX46_QUIRK_INSTRUCTION_LENGTH; }
+static inline bool has_quirk_extra_read_cycle(struct eeprom_93xx46_dev *edev) +{ + return edev->pdata->quirks & EEPROM_93XX46_QUIRK_EXTRA_READ_CYCLE; +} + static int eeprom_93xx46_read(void *priv, unsigned int off, void *val, size_t count) { @@ -96,6 +105,11 @@ static int eeprom_93xx46_read(void *priv, unsigned int off, dev_dbg(&edev->spi->dev, "read cmd 0x%x, %d Hz\n", cmd_addr, edev->spi->max_speed_hz);
+ if (has_quirk_extra_read_cycle(edev)) { + cmd_addr <<= 1; + bits += 1; + } + spi_message_init(&m);
t[0].tx_buf = (char *)&cmd_addr; @@ -363,6 +377,7 @@ static void select_deassert(void *context) static const struct of_device_id eeprom_93xx46_of_table[] = { { .compatible = "eeprom-93xx46", }, { .compatible = "atmel,at93c46d", .data = &atmel_at93c46d_data, }, + { .compatible = "microchip,93lc46b", .data = µchip_93lc46b_data, }, {} }; MODULE_DEVICE_TABLE(of, eeprom_93xx46_of_table); diff --git a/include/linux/eeprom_93xx46.h b/include/linux/eeprom_93xx46.h index eec7928ff8fe..99580c22f91a 100644 --- a/include/linux/eeprom_93xx46.h +++ b/include/linux/eeprom_93xx46.h @@ -16,6 +16,8 @@ struct eeprom_93xx46_platform_data { #define EEPROM_93XX46_QUIRK_SINGLE_WORD_READ (1 << 0) /* Instructions such as EWEN are (addrlen + 2) in length. */ #define EEPROM_93XX46_QUIRK_INSTRUCTION_LENGTH (1 << 1) +/* Add extra cycle after address during a read */ +#define EEPROM_93XX46_QUIRK_EXTRA_READ_CYCLE BIT(2)
/* * optional hooks to control additional logic
From: Greg Kroah-Hartman gregkh@linuxfoundation.org
From: Kiwoong Kim kwmad.kim@samsung.com
[ Upstream commit 2b2bfc8aa519f696087475ed8e8c61850c673272 ]
Some SoCs require a single scatterlist entry for smaller than page size, i.e. 4KB. When dispatching commands with more than one scatterlist entry under 4KB in size the following behavior is observed:
A command to read a block range is dispatched with two scatterlist entries that are named AAA and BBB. After dispatching, the host builds two PRDT entries and during transmission, device sends just one DATA IN because device doesn't care about host DMA. The host then transfers the combined amount of data from start address of the area named AAA. As a consequence, the area that follows AAA in memory would be corrupted.
|<------------->| +-------+------------ +-------+ + AAA + (corrupted) ... + BBB + +-------+------------ +-------+
To avoid this we need to enforce page size alignment for sg entries.
Link: https://lore.kernel.org/r/56dddef94f60bd9466fd77e69f64bbbd657ed2a1.161102690... Signed-off-by: Kiwoong Kim kwmad.kim@samsung.com Signed-off-by: Martin K. Petersen martin.petersen@oracle.com Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/scsi/ufs/ufshcd.c | 2 ++ drivers/scsi/ufs/ufshcd.h | 4 ++++ 2 files changed, 6 insertions(+)
diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c index 8ecdd53c9746..428b9e0ac47e 100644 --- a/drivers/scsi/ufs/ufshcd.c +++ b/drivers/scsi/ufs/ufshcd.c @@ -4831,6 +4831,8 @@ static int ufshcd_slave_configure(struct scsi_device *sdev) struct request_queue *q = sdev->request_queue;
blk_queue_update_dma_pad(q, PRDT_DATA_BYTE_COUNT_PAD - 1); + if (hba->quirks & UFSHCD_QUIRK_ALIGN_SG_WITH_PAGE_SIZE) + blk_queue_update_dma_alignment(q, PAGE_SIZE - 1);
if (ufshcd_is_rpm_autosuspend_allowed(hba)) sdev->rpm_autosuspend = 1; diff --git a/drivers/scsi/ufs/ufshcd.h b/drivers/scsi/ufs/ufshcd.h index 85f9d0fbfbd9..8cb64ae95462 100644 --- a/drivers/scsi/ufs/ufshcd.h +++ b/drivers/scsi/ufs/ufshcd.h @@ -557,6 +557,10 @@ enum ufshcd_quirks { */ UFSHCD_QUIRK_SKIP_DEF_UNIPRO_TIMEOUT_SETTING = 1 << 13,
+ /* + * This quirk allows only sg entries aligned with page size. + */ + UFSHCD_QUIRK_ALIGN_SG_WITH_PAGE_SIZE = 1 << 13, };
enum ufshcd_caps {
From: Greg Kroah-Hartman gregkh@linuxfoundation.org
From: Kiwoong Kim kwmad.kim@samsung.com
[ Upstream commit a967ddb22d94eb476ccef983b5f2730fa4d184d0 ]
Set optimized values for the following timeouts:
- FC0_PROTECTION_TIMER - TC0_REPLAY_TIMER - AFC0_REQUEST_TIMER
Exynos doesn't yet use traffic class #1.
Link: https://lore.kernel.org/r/a0ff44f665a4f31d2f945fd71de03571204c576c.160851378... Signed-off-by: Kiwoong Kim kwmad.kim@samsung.com Signed-off-by: Martin K. Petersen martin.petersen@oracle.com Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/scsi/ufs/ufs-exynos.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-)
diff --git a/drivers/scsi/ufs/ufs-exynos.c b/drivers/scsi/ufs/ufs-exynos.c index a8770ff14588..5ca21d1550df 100644 --- a/drivers/scsi/ufs/ufs-exynos.c +++ b/drivers/scsi/ufs/ufs-exynos.c @@ -640,6 +640,11 @@ static int exynos_ufs_pre_pwr_mode(struct ufs_hba *hba, } }
+ /* setting for three timeout values for traffic class #0 */ + ufshcd_dme_set(hba, UIC_ARG_MIB(PA_PWRMODEUSERDATA0), 8064); + ufshcd_dme_set(hba, UIC_ARG_MIB(PA_PWRMODEUSERDATA1), 28224); + ufshcd_dme_set(hba, UIC_ARG_MIB(PA_PWRMODEUSERDATA2), 20160); + return 0; out: return ret; @@ -1236,7 +1241,8 @@ struct exynos_ufs_drv_data exynos_ufs_drvs = { UFSHCI_QUIRK_BROKEN_HCE | UFSHCI_QUIRK_SKIP_RESET_INTR_AGGR | UFSHCD_QUIRK_BROKEN_OCS_FATAL_ERROR | - UFSHCI_QUIRK_SKIP_MANUAL_WB_FLUSH_CTRL, + UFSHCI_QUIRK_SKIP_MANUAL_WB_FLUSH_CTRL | + UFSHCD_QUIRK_SKIP_DEF_UNIPRO_TIMEOUT_SETTING, .opts = EXYNOS_UFS_OPT_HAS_APB_CLK_CTRL | EXYNOS_UFS_OPT_BROKEN_AUTO_CLK_CTRL | EXYNOS_UFS_OPT_BROKEN_RX_SEL_IDX |
From: Greg Kroah-Hartman gregkh@linuxfoundation.org
From: Kiwoong Kim kwmad.kim@samsung.com
[ Upstream commit f1ef9047aaab036edb39261b0a7a6bdcf3010b87 ]
Exynos needs scatterlist entries aligned to page size because it isn't capable of transferring data contained in one DATA IN operation to seversal areas in memory.
Link: https://lore.kernel.org/r/80d7e27d6ec537e650a6bd74897b6c60618efcdc.161102690... Signed-off-by: Kiwoong Kim kwmad.kim@samsung.com Signed-off-by: Martin K. Petersen martin.petersen@oracle.com Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/scsi/ufs/ufs-exynos.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/drivers/scsi/ufs/ufs-exynos.c b/drivers/scsi/ufs/ufs-exynos.c index 5ca21d1550df..267943a13a94 100644 --- a/drivers/scsi/ufs/ufs-exynos.c +++ b/drivers/scsi/ufs/ufs-exynos.c @@ -1242,7 +1242,8 @@ struct exynos_ufs_drv_data exynos_ufs_drvs = { UFSHCI_QUIRK_SKIP_RESET_INTR_AGGR | UFSHCD_QUIRK_BROKEN_OCS_FATAL_ERROR | UFSHCI_QUIRK_SKIP_MANUAL_WB_FLUSH_CTRL | - UFSHCD_QUIRK_SKIP_DEF_UNIPRO_TIMEOUT_SETTING, + UFSHCD_QUIRK_SKIP_DEF_UNIPRO_TIMEOUT_SETTING | + UFSHCD_QUIRK_ALIGN_SG_WITH_PAGE_SIZE, .opts = EXYNOS_UFS_OPT_HAS_APB_CLK_CTRL | EXYNOS_UFS_OPT_BROKEN_AUTO_CLK_CTRL | EXYNOS_UFS_OPT_BROKEN_RX_SEL_IDX |
From: Greg Kroah-Hartman gregkh@linuxfoundation.org
From: AngeloGioacchino Del Regno angelogioacchino.delregno@somainline.org
[ Upstream commit 8f03c30cb814213e36032084a01f49a9e604a3e3 ]
The PC_DBG_ECO_CNTL register on the Adreno A5xx family gets programmed to some different values on a per-model basis. At least, this is what we intend to do here;
Unfortunately, though, this register is being overwritten with a static magic number, right after applying the GPU-specific configuration (including the GPU-specific quirks) and that is effectively nullifying the efforts.
Let's remove the redundant and wrong write to the PC_DBG_ECO_CNTL register in order to retain the wanted configuration for the target GPU.
Signed-off-by: AngeloGioacchino Del Regno angelogioacchino.delregno@somainline.org Reviewed-by: Jordan Crouse jcrouse@codeaurora.org Signed-off-by: Rob Clark robdclark@chromium.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/gpu/drm/msm/adreno/a5xx_gpu.c | 2 -- 1 file changed, 2 deletions(-)
diff --git a/drivers/gpu/drm/msm/adreno/a5xx_gpu.c b/drivers/gpu/drm/msm/adreno/a5xx_gpu.c index a5af223eaf50..81506d2539b0 100644 --- a/drivers/gpu/drm/msm/adreno/a5xx_gpu.c +++ b/drivers/gpu/drm/msm/adreno/a5xx_gpu.c @@ -626,8 +626,6 @@ static int a5xx_hw_init(struct msm_gpu *gpu) if (adreno_gpu->info->quirks & ADRENO_QUIRK_TWO_PASS_USE_WFI) gpu_rmw(gpu, REG_A5XX_PC_DBG_ECO_CNTL, 0, (1 << 8));
- gpu_write(gpu, REG_A5XX_PC_DBG_ECO_CNTL, 0xc0200100); - /* Enable USE_RETENTION_FLOPS */ gpu_write(gpu, REG_A5XX_CP_CHICKEN_DBG, 0x02000000);
From: Greg Kroah-Hartman gregkh@linuxfoundation.org
From: Jisheng Zhang Jisheng.Zhang@synaptics.com
[ Upstream commit 5f7dfda4f2cec580c135fd81d96a05006651c128 ]
The SDHCI_PRESET_FOR_* registers are not set(all read as zeros), so set the quirk.
Signed-off-by: Jisheng Zhang Jisheng.Zhang@synaptics.com Link: https://lore.kernel.org/r/20201210165510.76b917e5@xhacker.debian Signed-off-by: Ulf Hansson ulf.hansson@linaro.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/mmc/host/sdhci-of-dwcmshc.c | 1 + 1 file changed, 1 insertion(+)
diff --git a/drivers/mmc/host/sdhci-of-dwcmshc.c b/drivers/mmc/host/sdhci-of-dwcmshc.c index d90020ed3622..59d8d96ce206 100644 --- a/drivers/mmc/host/sdhci-of-dwcmshc.c +++ b/drivers/mmc/host/sdhci-of-dwcmshc.c @@ -112,6 +112,7 @@ static const struct sdhci_ops sdhci_dwcmshc_ops = { static const struct sdhci_pltfm_data sdhci_dwcmshc_pdata = { .ops = &sdhci_dwcmshc_ops, .quirks = SDHCI_QUIRK_CAP_CLOCK_BASE_BROKEN, + .quirks2 = SDHCI_QUIRK2_PRESET_VALUE_BROKEN, };
static int dwcmshc_probe(struct platform_device *pdev)
From: Greg Kroah-Hartman gregkh@linuxfoundation.org
From: Hans de Goede hdegoede@redhat.com
[ Upstream commit fc6a31b00739356809dd566e16f2c4325a63285d ]
The ITE8568 EC on the Voyo Winpad A15 presents itself as an I2C-HID attached keyboard and mouse (which seems to never send any events).
This needs the I2C_HID_QUIRK_NO_IRQ_AFTER_RESET quirk, otherwise we get the following errors:
[ 3688.770850] i2c_hid i2c-ITE8568:00: failed to reset device. [ 3694.915865] i2c_hid i2c-ITE8568:00: failed to reset device. [ 3701.059717] i2c_hid i2c-ITE8568:00: failed to reset device. [ 3707.205944] i2c_hid i2c-ITE8568:00: failed to reset device. [ 3708.227940] i2c_hid i2c-ITE8568:00: can't add hid device: -61 [ 3708.236518] i2c_hid: probe of i2c-ITE8568:00 failed with error -61
Which leads to a significant boot delay.
Signed-off-by: Hans de Goede hdegoede@redhat.com Signed-off-by: Jiri Kosina jkosina@suse.cz Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/hid/hid-ids.h | 2 ++ drivers/hid/i2c-hid/i2c-hid-core.c | 2 ++ 2 files changed, 4 insertions(+)
diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h index 5ba0aa1d2335..b60279aaed43 100644 --- a/drivers/hid/hid-ids.h +++ b/drivers/hid/hid-ids.h @@ -641,6 +641,8 @@ #define USB_DEVICE_ID_INNEX_GENESIS_ATARI 0x4745
#define USB_VENDOR_ID_ITE 0x048d +#define I2C_VENDOR_ID_ITE 0x103c +#define I2C_DEVICE_ID_ITE_VOYO_WINPAD_A15 0x184f #define USB_DEVICE_ID_ITE_LENOVO_YOGA 0x8386 #define USB_DEVICE_ID_ITE_LENOVO_YOGA2 0x8350 #define I2C_DEVICE_ID_ITE_LENOVO_LEGION_Y720 0x837a diff --git a/drivers/hid/i2c-hid/i2c-hid-core.c b/drivers/hid/i2c-hid/i2c-hid-core.c index bfe716d7ea44..c586acf2fc0b 100644 --- a/drivers/hid/i2c-hid/i2c-hid-core.c +++ b/drivers/hid/i2c-hid/i2c-hid-core.c @@ -171,6 +171,8 @@ static const struct i2c_hid_quirks { I2C_HID_QUIRK_SET_PWR_WAKEUP_DEV }, { I2C_VENDOR_ID_HANTICK, I2C_PRODUCT_ID_HANTICK_5288, I2C_HID_QUIRK_NO_IRQ_AFTER_RESET }, + { I2C_VENDOR_ID_ITE, I2C_DEVICE_ID_ITE_VOYO_WINPAD_A15, + I2C_HID_QUIRK_NO_IRQ_AFTER_RESET }, { I2C_VENDOR_ID_RAYDIUM, I2C_PRODUCT_ID_RAYDIUM_3118, I2C_HID_QUIRK_NO_IRQ_AFTER_RESET }, { USB_VENDOR_ID_ELAN, HID_ANY_ID,
From: Greg Kroah-Hartman gregkh@linuxfoundation.org
From: Olivia Mackintosh livvy@base.nu
[ Upstream commit a07df82c799013236aa90a140785775eda9f9523 ]
This allows for N different devices to use the pioneer mixer quirk for setting capture/record type and recording level. The impementation has not changed much with the exception of an additional mask on private_value to allow storing of a device index: DEVICE MASK 0xff000000 GROUP_MASK 0x00ff0000 VALUE_MASK 0x0000ffff
This could be improved by changing the arrays of wValues for each channel to contain named definitions (e.g. SND_DJM_CAP_LINE). It would improve readability and perhaps would allow using the same array for multiple channels. The channel number can be specified on the control next to the wIndex.
Feedback is very much appreciated as I'm not the most proficient C programmer but am learning as I go.
Signed-off-by: Olivia Mackintosh livvy@base.nu Link: https://lore.kernel.org/r/20210205184256.10201-2-livvy@base.nu Signed-off-by: Takashi Iwai tiwai@suse.de Signed-off-by: Sasha Levin sashal@kernel.org --- sound/usb/mixer_quirks.c | 336 +++++++++++++++++++++++++-------------- 1 file changed, 216 insertions(+), 120 deletions(-)
diff --git a/sound/usb/mixer_quirks.c b/sound/usb/mixer_quirks.c index df036a359f2f..788b75cb9447 100644 --- a/sound/usb/mixer_quirks.c +++ b/sound/usb/mixer_quirks.c @@ -2603,141 +2603,221 @@ static int snd_bbfpro_controls_create(struct usb_mixer_interface *mixer) }
/* - * Pioneer DJ DJM-250MK2 and maybe other DJM models + * Pioneer DJ DJM Mixers * - * For playback, no duplicate mapping should be set. - * There are three mixer stereo channels (CH1, CH2, AUX) - * and three stereo sources (Playback 1-2, Playback 3-4, Playback 5-6). - * Each channel should be mapped just once to one source. - * If mapped multiple times, only one source will play on given channel - * (sources are not mixed together). + * These devices generally have options for soft-switching the playback and + * capture sources in addition to the recording level. Although different + * devices have different configurations, there seems to be canonical values + * for specific capture/playback types: See the definitions of these below. * - * For recording, duplicate mapping is OK. We will get the same signal multiple times. - * - * Channels 7-8 are in both directions fixed to FX SEND / FX RETURN. - * - * See also notes in the quirks-table.h file. + * The wValue is masked with the stereo channel number. e.g. Setting Ch2 to + * capture phono would be 0x0203. Capture, playback and capture level have + * different wIndexes. */
-struct snd_pioneer_djm_option { - const u16 wIndex; - const u16 wValue; +// Capture types +#define SND_DJM_CAP_LINE 0x00 +#define SND_DJM_CAP_CDLINE 0x01 +#define SND_DJM_CAP_PHONO 0x03 +#define SND_DJM_CAP_PFADER 0x06 +#define SND_DJM_CAP_XFADERA 0x07 +#define SND_DJM_CAP_XFADERB 0x08 +#define SND_DJM_CAP_MIC 0x09 +#define SND_DJM_CAP_AUX 0x0d +#define SND_DJM_CAP_RECOUT 0x0a +#define SND_DJM_CAP_NONE 0x0f +#define SND_DJM_CAP_CH1PFADER 0x11 +#define SND_DJM_CAP_CH2PFADER 0x12 + +// Playback types +#define SND_DJM_PB_CH1 0x00 +#define SND_DJM_PB_CH2 0x01 +#define SND_DJM_PB_AUX 0x04 + +#define SND_DJM_WINDEX_CAP 0x8002 +#define SND_DJM_WINDEX_CAPLVL 0x8003 +#define SND_DJM_WINDEX_PB 0x8016 + +// kcontrol->private_value layout +#define SND_DJM_VALUE_MASK 0x0000ffff +#define SND_DJM_GROUP_MASK 0x00ff0000 +#define SND_DJM_DEVICE_MASK 0xff000000 +#define SND_DJM_GROUP_SHIFT 16 +#define SND_DJM_DEVICE_SHIFT 24 + +// device table index +#define SND_DJM_250MK2_IDX 0x0 +#define SND_DJM_750_IDX 0x1 + + +#define SND_DJM_CTL(_name, suffix, _default_value, _windex) { \ + .name = _name, \ + .options = snd_djm_opts_##suffix, \ + .noptions = ARRAY_SIZE(snd_djm_opts_##suffix), \ + .default_value = _default_value, \ + .wIndex = _windex } + +#define SND_DJM_DEVICE(suffix) { \ + .controls = snd_djm_ctls_##suffix, \ + .ncontrols = ARRAY_SIZE(snd_djm_ctls_##suffix) } + + +struct snd_djm_device { const char *name; + const struct snd_djm_ctl *controls; + size_t ncontrols; };
-static const struct snd_pioneer_djm_option snd_pioneer_djm_options_capture_level[] = { - { .name = "-5 dB", .wValue = 0x0300, .wIndex = 0x8003 }, - { .name = "-10 dB", .wValue = 0x0200, .wIndex = 0x8003 }, - { .name = "-15 dB", .wValue = 0x0100, .wIndex = 0x8003 }, - { .name = "-19 dB", .wValue = 0x0000, .wIndex = 0x8003 } +struct snd_djm_ctl { + const char *name; + const u16 *options; + size_t noptions; + u16 default_value; + u16 wIndex; };
-static const struct snd_pioneer_djm_option snd_pioneer_djm_options_capture_ch12[] = { - { .name = "CH1 Control Tone PHONO", .wValue = 0x0103, .wIndex = 0x8002 }, - { .name = "CH1 Control Tone LINE", .wValue = 0x0100, .wIndex = 0x8002 }, - { .name = "Post CH1 Fader", .wValue = 0x0106, .wIndex = 0x8002 }, - { .name = "Cross Fader A", .wValue = 0x0107, .wIndex = 0x8002 }, - { .name = "Cross Fader B", .wValue = 0x0108, .wIndex = 0x8002 }, - { .name = "MIC", .wValue = 0x0109, .wIndex = 0x8002 }, - { .name = "AUX", .wValue = 0x010d, .wIndex = 0x8002 }, - { .name = "REC OUT", .wValue = 0x010a, .wIndex = 0x8002 } +static const char *snd_djm_get_label_caplevel(u16 wvalue) +{ + switch (wvalue) { + case 0x0000: return "-19dB"; + case 0x0100: return "-15dB"; + case 0x0200: return "-10dB"; + case 0x0300: return "-5dB"; + default: return NULL; + } };
-static const struct snd_pioneer_djm_option snd_pioneer_djm_options_capture_ch34[] = { - { .name = "CH2 Control Tone PHONO", .wValue = 0x0203, .wIndex = 0x8002 }, - { .name = "CH2 Control Tone LINE", .wValue = 0x0200, .wIndex = 0x8002 }, - { .name = "Post CH2 Fader", .wValue = 0x0206, .wIndex = 0x8002 }, - { .name = "Cross Fader A", .wValue = 0x0207, .wIndex = 0x8002 }, - { .name = "Cross Fader B", .wValue = 0x0208, .wIndex = 0x8002 }, - { .name = "MIC", .wValue = 0x0209, .wIndex = 0x8002 }, - { .name = "AUX", .wValue = 0x020d, .wIndex = 0x8002 }, - { .name = "REC OUT", .wValue = 0x020a, .wIndex = 0x8002 } +static const char *snd_djm_get_label_cap(u16 wvalue) +{ + switch (wvalue & 0x00ff) { + case SND_DJM_CAP_LINE: return "Control Tone LINE"; + case SND_DJM_CAP_CDLINE: return "Control Tone CD/LINE"; + case SND_DJM_CAP_PHONO: return "Control Tone PHONO"; + case SND_DJM_CAP_PFADER: return "Post Fader"; + case SND_DJM_CAP_XFADERA: return "Cross Fader A"; + case SND_DJM_CAP_XFADERB: return "Cross Fader B"; + case SND_DJM_CAP_MIC: return "Mic"; + case SND_DJM_CAP_RECOUT: return "Rec Out"; + case SND_DJM_CAP_AUX: return "Aux"; + case SND_DJM_CAP_NONE: return "None"; + case SND_DJM_CAP_CH1PFADER: return "Post Fader Ch1"; + case SND_DJM_CAP_CH2PFADER: return "Post Fader Ch2"; + default: return NULL; + } };
-static const struct snd_pioneer_djm_option snd_pioneer_djm_options_capture_ch56[] = { - { .name = "REC OUT", .wValue = 0x030a, .wIndex = 0x8002 }, - { .name = "Post CH1 Fader", .wValue = 0x0311, .wIndex = 0x8002 }, - { .name = "Post CH2 Fader", .wValue = 0x0312, .wIndex = 0x8002 }, - { .name = "Cross Fader A", .wValue = 0x0307, .wIndex = 0x8002 }, - { .name = "Cross Fader B", .wValue = 0x0308, .wIndex = 0x8002 }, - { .name = "MIC", .wValue = 0x0309, .wIndex = 0x8002 }, - { .name = "AUX", .wValue = 0x030d, .wIndex = 0x8002 } +static const char *snd_djm_get_label_pb(u16 wvalue) +{ + switch (wvalue & 0x00ff) { + case SND_DJM_PB_CH1: return "Ch1"; + case SND_DJM_PB_CH2: return "Ch2"; + case SND_DJM_PB_AUX: return "Aux"; + default: return NULL; + } };
-static const struct snd_pioneer_djm_option snd_pioneer_djm_options_playback_12[] = { - { .name = "CH1", .wValue = 0x0100, .wIndex = 0x8016 }, - { .name = "CH2", .wValue = 0x0101, .wIndex = 0x8016 }, - { .name = "AUX", .wValue = 0x0104, .wIndex = 0x8016 } +static const char *snd_djm_get_label(u16 wvalue, u16 windex) +{ + switch (windex) { + case SND_DJM_WINDEX_CAPLVL: return snd_djm_get_label_caplevel(wvalue); + case SND_DJM_WINDEX_CAP: return snd_djm_get_label_cap(wvalue); + case SND_DJM_WINDEX_PB: return snd_djm_get_label_pb(wvalue); + default: return NULL; + } };
-static const struct snd_pioneer_djm_option snd_pioneer_djm_options_playback_34[] = { - { .name = "CH1", .wValue = 0x0200, .wIndex = 0x8016 }, - { .name = "CH2", .wValue = 0x0201, .wIndex = 0x8016 }, - { .name = "AUX", .wValue = 0x0204, .wIndex = 0x8016 } -};
-static const struct snd_pioneer_djm_option snd_pioneer_djm_options_playback_56[] = { - { .name = "CH1", .wValue = 0x0300, .wIndex = 0x8016 }, - { .name = "CH2", .wValue = 0x0301, .wIndex = 0x8016 }, - { .name = "AUX", .wValue = 0x0304, .wIndex = 0x8016 } +// DJM-250MK2 +static const u16 snd_djm_opts_cap_level[] = { + 0x0000, 0x0100, 0x0200, 0x0300 }; + +static const u16 snd_djm_opts_250mk2_cap1[] = { + 0x0103, 0x0100, 0x0106, 0x0107, 0x0108, 0x0109, 0x010d, 0x010a }; + +static const u16 snd_djm_opts_250mk2_cap2[] = { + 0x0203, 0x0200, 0x0206, 0x0207, 0x0208, 0x0209, 0x020d, 0x020a }; + +static const u16 snd_djm_opts_250mk2_cap3[] = { + 0x030a, 0x0311, 0x0312, 0x0307, 0x0308, 0x0309, 0x030d }; + +static const u16 snd_djm_opts_250mk2_pb1[] = { 0x0100, 0x0101, 0x0104 }; +static const u16 snd_djm_opts_250mk2_pb2[] = { 0x0200, 0x0201, 0x0204 }; +static const u16 snd_djm_opts_250mk2_pb3[] = { 0x0300, 0x0301, 0x0304 }; + +static const struct snd_djm_ctl snd_djm_ctls_250mk2[] = { + SND_DJM_CTL("Capture Level", cap_level, 0, SND_DJM_WINDEX_CAPLVL), + SND_DJM_CTL("Ch1 Input", 250mk2_cap1, 2, SND_DJM_WINDEX_CAP), + SND_DJM_CTL("Ch2 Input", 250mk2_cap2, 2, SND_DJM_WINDEX_CAP), + SND_DJM_CTL("Ch3 Input", 250mk2_cap3, 0, SND_DJM_WINDEX_CAP), + SND_DJM_CTL("Ch1 Output", 250mk2_pb1, 0, SND_DJM_WINDEX_PB), + SND_DJM_CTL("Ch2 Output", 250mk2_pb2, 1, SND_DJM_WINDEX_PB), + SND_DJM_CTL("Ch3 Output", 250mk2_pb3, 2, SND_DJM_WINDEX_PB) };
-struct snd_pioneer_djm_option_group { - const char *name; - const struct snd_pioneer_djm_option *options; - const size_t count; - const u16 default_value; + +// DJM-750 +static const u16 snd_djm_opts_750_cap1[] = { + 0x0101, 0x0103, 0x0106, 0x0107, 0x0108, 0x0109, 0x010a, 0x010f }; +static const u16 snd_djm_opts_750_cap2[] = { + 0x0200, 0x0201, 0x0206, 0x0207, 0x0208, 0x0209, 0x020a, 0x020f }; +static const u16 snd_djm_opts_750_cap3[] = { + 0x0300, 0x0301, 0x0306, 0x0307, 0x0308, 0x0309, 0x030a, 0x030f }; +static const u16 snd_djm_opts_750_cap4[] = { + 0x0401, 0x0403, 0x0406, 0x0407, 0x0408, 0x0409, 0x040a, 0x040f }; + +static const struct snd_djm_ctl snd_djm_ctls_750[] = { + SND_DJM_CTL("Capture Level", cap_level, 0, SND_DJM_WINDEX_CAPLVL), + SND_DJM_CTL("Ch1 Input", 750_cap1, 2, SND_DJM_WINDEX_CAP), + SND_DJM_CTL("Ch2 Input", 750_cap2, 2, SND_DJM_WINDEX_CAP), + SND_DJM_CTL("Ch3 Input", 750_cap3, 0, SND_DJM_WINDEX_CAP), + SND_DJM_CTL("Ch4 Input", 750_cap4, 0, SND_DJM_WINDEX_CAP) };
-#define snd_pioneer_djm_option_group_item(_name, suffix, _default_value) { \ - .name = _name, \ - .options = snd_pioneer_djm_options_##suffix, \ - .count = ARRAY_SIZE(snd_pioneer_djm_options_##suffix), \ - .default_value = _default_value } - -static const struct snd_pioneer_djm_option_group snd_pioneer_djm_option_groups[] = { - snd_pioneer_djm_option_group_item("Master Capture Level Capture Switch", capture_level, 0), - snd_pioneer_djm_option_group_item("Capture 1-2 Capture Switch", capture_ch12, 2), - snd_pioneer_djm_option_group_item("Capture 3-4 Capture Switch", capture_ch34, 2), - snd_pioneer_djm_option_group_item("Capture 5-6 Capture Switch", capture_ch56, 0), - snd_pioneer_djm_option_group_item("Playback 1-2 Playback Switch", playback_12, 0), - snd_pioneer_djm_option_group_item("Playback 3-4 Playback Switch", playback_34, 1), - snd_pioneer_djm_option_group_item("Playback 5-6 Playback Switch", playback_56, 2) + +static const struct snd_djm_device snd_djm_devices[] = { + SND_DJM_DEVICE(250mk2), + SND_DJM_DEVICE(750) };
-// layout of the kcontrol->private_value: -#define SND_PIONEER_DJM_VALUE_MASK 0x0000ffff -#define SND_PIONEER_DJM_GROUP_MASK 0xffff0000 -#define SND_PIONEER_DJM_GROUP_SHIFT 16
-static int snd_pioneer_djm_controls_info(struct snd_kcontrol *kctl, struct snd_ctl_elem_info *info) +static int snd_djm_controls_info(struct snd_kcontrol *kctl, + struct snd_ctl_elem_info *info) { - u16 group_index = kctl->private_value >> SND_PIONEER_DJM_GROUP_SHIFT; - size_t count; + unsigned long private_value = kctl->private_value; + u8 device_idx = (private_value & SND_DJM_DEVICE_MASK) >> SND_DJM_DEVICE_SHIFT; + u8 ctl_idx = (private_value & SND_DJM_GROUP_MASK) >> SND_DJM_GROUP_SHIFT; + const struct snd_djm_device *device = &snd_djm_devices[device_idx]; const char *name; - const struct snd_pioneer_djm_option_group *group; + const struct snd_djm_ctl *ctl; + size_t noptions; + + if (ctl_idx >= device->ncontrols) + return -EINVAL; + + ctl = &device->controls[ctl_idx]; + noptions = ctl->noptions; + if (info->value.enumerated.item >= noptions) + info->value.enumerated.item = noptions - 1;
- if (group_index >= ARRAY_SIZE(snd_pioneer_djm_option_groups)) + name = snd_djm_get_label(ctl->options[info->value.enumerated.item], + ctl->wIndex); + if (!name) return -EINVAL;
- group = &snd_pioneer_djm_option_groups[group_index]; - count = group->count; - if (info->value.enumerated.item >= count) - info->value.enumerated.item = count - 1; - name = group->options[info->value.enumerated.item].name; strlcpy(info->value.enumerated.name, name, sizeof(info->value.enumerated.name)); info->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; info->count = 1; - info->value.enumerated.items = count; + info->value.enumerated.items = noptions; return 0; }
-static int snd_pioneer_djm_controls_update(struct usb_mixer_interface *mixer, u16 group, u16 value) +static int snd_djm_controls_update(struct usb_mixer_interface *mixer, + u8 device_idx, u8 group, u16 value) { int err; + const struct snd_djm_device *device = &snd_djm_devices[device_idx];
- if (group >= ARRAY_SIZE(snd_pioneer_djm_option_groups) - || value >= snd_pioneer_djm_option_groups[group].count) + if ((group >= device->ncontrols) || value >= device->controls[group].noptions) return -EINVAL;
err = snd_usb_lock_shutdown(mixer->chip); @@ -2748,63 +2828,76 @@ static int snd_pioneer_djm_controls_update(struct usb_mixer_interface *mixer, u1 mixer->chip->dev, usb_sndctrlpipe(mixer->chip->dev, 0), USB_REQ_SET_FEATURE, USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, - snd_pioneer_djm_option_groups[group].options[value].wValue, - snd_pioneer_djm_option_groups[group].options[value].wIndex, + device->controls[group].options[value], + device->controls[group].wIndex, NULL, 0);
snd_usb_unlock_shutdown(mixer->chip); return err; }
-static int snd_pioneer_djm_controls_get(struct snd_kcontrol *kctl, struct snd_ctl_elem_value *elem) +static int snd_djm_controls_get(struct snd_kcontrol *kctl, + struct snd_ctl_elem_value *elem) { - elem->value.enumerated.item[0] = kctl->private_value & SND_PIONEER_DJM_VALUE_MASK; + elem->value.enumerated.item[0] = kctl->private_value & SND_DJM_VALUE_MASK; return 0; }
-static int snd_pioneer_djm_controls_put(struct snd_kcontrol *kctl, struct snd_ctl_elem_value *elem) +static int snd_djm_controls_put(struct snd_kcontrol *kctl, struct snd_ctl_elem_value *elem) { struct usb_mixer_elem_list *list = snd_kcontrol_chip(kctl); struct usb_mixer_interface *mixer = list->mixer; unsigned long private_value = kctl->private_value; - u16 group = (private_value & SND_PIONEER_DJM_GROUP_MASK) >> SND_PIONEER_DJM_GROUP_SHIFT; + + u8 device = (private_value & SND_DJM_DEVICE_MASK) >> SND_DJM_DEVICE_SHIFT; + u8 group = (private_value & SND_DJM_GROUP_MASK) >> SND_DJM_GROUP_SHIFT; u16 value = elem->value.enumerated.item[0];
- kctl->private_value = (group << SND_PIONEER_DJM_GROUP_SHIFT) | value; + kctl->private_value = ((device << SND_DJM_DEVICE_SHIFT) | + (group << SND_DJM_GROUP_SHIFT) | + value);
- return snd_pioneer_djm_controls_update(mixer, group, value); + return snd_djm_controls_update(mixer, device, group, value); }
-static int snd_pioneer_djm_controls_resume(struct usb_mixer_elem_list *list) +static int snd_djm_controls_resume(struct usb_mixer_elem_list *list) { unsigned long private_value = list->kctl->private_value; - u16 group = (private_value & SND_PIONEER_DJM_GROUP_MASK) >> SND_PIONEER_DJM_GROUP_SHIFT; - u16 value = (private_value & SND_PIONEER_DJM_VALUE_MASK); + u8 device = (private_value & SND_DJM_DEVICE_MASK) >> SND_DJM_DEVICE_SHIFT; + u8 group = (private_value & SND_DJM_GROUP_MASK) >> SND_DJM_GROUP_SHIFT; + u16 value = (private_value & SND_DJM_VALUE_MASK);
- return snd_pioneer_djm_controls_update(list->mixer, group, value); + return snd_djm_controls_update(list->mixer, device, group, value); }
-static int snd_pioneer_djm_controls_create(struct usb_mixer_interface *mixer) +static int snd_djm_controls_create(struct usb_mixer_interface *mixer, + const u8 device_idx) { int err, i; - const struct snd_pioneer_djm_option_group *group; + u16 value; + + const struct snd_djm_device *device = &snd_djm_devices[device_idx]; + struct snd_kcontrol_new knew = { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, .index = 0, - .info = snd_pioneer_djm_controls_info, - .get = snd_pioneer_djm_controls_get, - .put = snd_pioneer_djm_controls_put + .info = snd_djm_controls_info, + .get = snd_djm_controls_get, + .put = snd_djm_controls_put };
- for (i = 0; i < ARRAY_SIZE(snd_pioneer_djm_option_groups); i++) { - group = &snd_pioneer_djm_option_groups[i]; - knew.name = group->name; - knew.private_value = (i << SND_PIONEER_DJM_GROUP_SHIFT) | group->default_value; - err = snd_pioneer_djm_controls_update(mixer, i, group->default_value); + for (i = 0; i < device->ncontrols; i++) { + value = device->controls[i].default_value; + knew.name = device->controls[i].name; + knew.private_value = ( + (device_idx << SND_DJM_DEVICE_SHIFT) | + (i << SND_DJM_GROUP_SHIFT) | + value); + err = snd_djm_controls_update(mixer, device_idx, i, value); if (err) return err; - err = add_single_ctl_with_resume(mixer, 0, snd_pioneer_djm_controls_resume, + err = add_single_ctl_with_resume(mixer, 0, snd_djm_controls_resume, &knew, NULL); if (err) return err; @@ -2917,7 +3010,10 @@ int snd_usb_mixer_apply_create_quirk(struct usb_mixer_interface *mixer) err = snd_bbfpro_controls_create(mixer); break; case USB_ID(0x2b73, 0x0017): /* Pioneer DJ DJM-250MK2 */ - err = snd_pioneer_djm_controls_create(mixer); + err = snd_djm_controls_create(mixer, SND_DJM_250MK2_IDX); + break; + case USB_ID(0x08e4, 0x017f): /* Pioneer DJ DJM-750 */ + err = snd_djm_controls_create(mixer, SND_DJM_750_IDX); break; }
From: Greg Kroah-Hartman gregkh@linuxfoundation.org
From: Fabian Lesniak fabian@lesniak-it.de
[ Upstream commit fee03efc69345344c8851596d74d93199b175bfe ]
This commit adds mixer quirks for the Pioneer DJM-900NXS2 mixer. This device has 6 capture channels, 5 of them allow setting the signal source. This adds controls for these, similar to the DJM-250Mk2. However, playpack channels are not controllable via software like on the 250Mk2, as they can only be set manually on the mixing console. Read-only controls showing the currently selected playback channels are omitted.
Signed-off-by: Fabian Lesniak fabian@lesniak-it.de Link: https://lore.kernel.org/r/20210205215116.258724-2-fabian@lesniak-it.de Signed-off-by: Takashi Iwai tiwai@suse.de Signed-off-by: Sasha Levin sashal@kernel.org --- sound/usb/mixer_quirks.c | 35 ++++++++++++++++++++++++++++++++++- 1 file changed, 34 insertions(+), 1 deletion(-)
diff --git a/sound/usb/mixer_quirks.c b/sound/usb/mixer_quirks.c index 788b75cb9447..448de77f43fd 100644 --- a/sound/usb/mixer_quirks.c +++ b/sound/usb/mixer_quirks.c @@ -2618,6 +2618,7 @@ static int snd_bbfpro_controls_create(struct usb_mixer_interface *mixer) // Capture types #define SND_DJM_CAP_LINE 0x00 #define SND_DJM_CAP_CDLINE 0x01 +#define SND_DJM_CAP_DIGITAL 0x02 #define SND_DJM_CAP_PHONO 0x03 #define SND_DJM_CAP_PFADER 0x06 #define SND_DJM_CAP_XFADERA 0x07 @@ -2628,6 +2629,8 @@ static int snd_bbfpro_controls_create(struct usb_mixer_interface *mixer) #define SND_DJM_CAP_NONE 0x0f #define SND_DJM_CAP_CH1PFADER 0x11 #define SND_DJM_CAP_CH2PFADER 0x12 +#define SND_DJM_CAP_CH3PFADER 0x13 +#define SND_DJM_CAP_CH4PFADER 0x14
// Playback types #define SND_DJM_PB_CH1 0x00 @@ -2648,6 +2651,7 @@ static int snd_bbfpro_controls_create(struct usb_mixer_interface *mixer) // device table index #define SND_DJM_250MK2_IDX 0x0 #define SND_DJM_750_IDX 0x1 +#define SND_DJM_900NXS2_IDX 0x2
#define SND_DJM_CTL(_name, suffix, _default_value, _windex) { \ @@ -2692,6 +2696,7 @@ static const char *snd_djm_get_label_cap(u16 wvalue) switch (wvalue & 0x00ff) { case SND_DJM_CAP_LINE: return "Control Tone LINE"; case SND_DJM_CAP_CDLINE: return "Control Tone CD/LINE"; + case SND_DJM_CAP_DIGITAL: return "Control Tone DIGITAL"; case SND_DJM_CAP_PHONO: return "Control Tone PHONO"; case SND_DJM_CAP_PFADER: return "Post Fader"; case SND_DJM_CAP_XFADERA: return "Cross Fader A"; @@ -2702,6 +2707,8 @@ static const char *snd_djm_get_label_cap(u16 wvalue) case SND_DJM_CAP_NONE: return "None"; case SND_DJM_CAP_CH1PFADER: return "Post Fader Ch1"; case SND_DJM_CAP_CH2PFADER: return "Post Fader Ch2"; + case SND_DJM_CAP_CH3PFADER: return "Post Fader Ch3"; + case SND_DJM_CAP_CH4PFADER: return "Post Fader Ch4"; default: return NULL; } }; @@ -2774,9 +2781,32 @@ static const struct snd_djm_ctl snd_djm_ctls_750[] = { };
+// DJM-900NXS2 +static const u16 snd_djm_opts_900nxs2_cap1[] = { + 0x0100, 0x0102, 0x0103, 0x0106, 0x0107, 0x0108, 0x0109, 0x010a }; +static const u16 snd_djm_opts_900nxs2_cap2[] = { + 0x0200, 0x0202, 0x0203, 0x0206, 0x0207, 0x0208, 0x0209, 0x020a }; +static const u16 snd_djm_opts_900nxs2_cap3[] = { + 0x0300, 0x0302, 0x0303, 0x0306, 0x0307, 0x0308, 0x0309, 0x030a }; +static const u16 snd_djm_opts_900nxs2_cap4[] = { + 0x0400, 0x0402, 0x0403, 0x0406, 0x0407, 0x0408, 0x0409, 0x040a }; +static const u16 snd_djm_opts_900nxs2_cap5[] = { + 0x0507, 0x0508, 0x0509, 0x050a, 0x0511, 0x0512, 0x0513, 0x0514 }; + +static const struct snd_djm_ctl snd_djm_ctls_900nxs2[] = { + SND_DJM_CTL("Capture Level", cap_level, 0, SND_DJM_WINDEX_CAPLVL), + SND_DJM_CTL("Ch1 Input", 900nxs2_cap1, 2, SND_DJM_WINDEX_CAP), + SND_DJM_CTL("Ch2 Input", 900nxs2_cap2, 2, SND_DJM_WINDEX_CAP), + SND_DJM_CTL("Ch3 Input", 900nxs2_cap3, 2, SND_DJM_WINDEX_CAP), + SND_DJM_CTL("Ch4 Input", 900nxs2_cap4, 2, SND_DJM_WINDEX_CAP), + SND_DJM_CTL("Ch5 Input", 900nxs2_cap5, 3, SND_DJM_WINDEX_CAP) +}; + + static const struct snd_djm_device snd_djm_devices[] = { SND_DJM_DEVICE(250mk2), - SND_DJM_DEVICE(750) + SND_DJM_DEVICE(750), + SND_DJM_DEVICE(900nxs2) };
@@ -3015,6 +3045,9 @@ int snd_usb_mixer_apply_create_quirk(struct usb_mixer_interface *mixer) case USB_ID(0x08e4, 0x017f): /* Pioneer DJ DJM-750 */ err = snd_djm_controls_create(mixer, SND_DJM_750_IDX); break; + case USB_ID(0x2b73, 0x000a): /* Pioneer DJ DJM-900NXS2 */ + err = snd_djm_controls_create(mixer, SND_DJM_900NXS2_IDX); + break; }
return err;
From: Greg Kroah-Hartman gregkh@linuxfoundation.org
From: Hans de Goede hdegoede@redhat.com
[ Upstream commit b7c20f3815985570ac71c39b1a3e68c201109578 ]
The Acer Aspire Switch 10E (SW3-016)'s keyboard-dock uses the same USB-ids as the Acer One S1003 keyboard-dock. Yet they are not entirely the same:
1. The S1003 keyboard-dock has the same report descriptors as the S1002 keyboard-dock (which has different USB-ids)
2. The Acer Aspire Switch 10E's keyboard-dock has different report descriptors from the S1002/S1003 keyboard docks and it sends 0x00880078 / 0x00880079 usage events when the touchpad is toggled on/off (which is handled internally).
This means that all Acer kbd-docks handled by the hid-ite.c drivers report their touchpad being toggled on/off through these custom usage-codes with the exception of the S1003 dock, which likely is a bug of that dock.
Add a QUIRK_TOUCHPAD_ON_OFF_REPORT quirk for the Aspire Switch 10E / S1003 usb-id so that the touchpad toggling will get reported to userspace on the Aspire Switch 10E.
Since the Aspire Switch 10E's kbd-dock has different report-descriptors, this also requires adding support for fixing those to ite_report_fixup().
Setting the quirk will also cause ite_report_fixup() to hit the S1002/S1003 descriptors path on the S1003. Since the S1003 kbd-dock never generates any input-reports for the fixed up part of the descriptors this does not matter; and if there are versions out there which do actually send input-reports for the touchpad-toggle then the fixup should actually help to make things work.
This was tested on both an Acer Aspire Switch 10E and on an Acer One S1003.
Signed-off-by: Hans de Goede hdegoede@redhat.com Signed-off-by: Jiri Kosina jkosina@suse.cz Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/hid/hid-ite.c | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-)
diff --git a/drivers/hid/hid-ite.c b/drivers/hid/hid-ite.c index 22bfbebceaf4..14fc068affad 100644 --- a/drivers/hid/hid-ite.c +++ b/drivers/hid/hid-ite.c @@ -23,11 +23,16 @@ static __u8 *ite_report_fixup(struct hid_device *hdev, __u8 *rdesc, unsigned int hid_info(hdev, "Fixing up Acer Sw5-012 ITE keyboard report descriptor\n"); rdesc[163] = HID_MAIN_ITEM_RELATIVE; } - /* For Acer One S1002 keyboard-dock */ + /* For Acer One S1002/S1003 keyboard-dock */ if (*rsize == 188 && rdesc[185] == 0x81 && rdesc[186] == 0x02) { - hid_info(hdev, "Fixing up Acer S1002 ITE keyboard report descriptor\n"); + hid_info(hdev, "Fixing up Acer S1002/S1003 ITE keyboard report descriptor\n"); rdesc[186] = HID_MAIN_ITEM_RELATIVE; } + /* For Acer Aspire Switch 10E (SW3-016) keyboard-dock */ + if (*rsize == 210 && rdesc[184] == 0x81 && rdesc[185] == 0x02) { + hid_info(hdev, "Fixing up Acer Aspire Switch 10E (SW3-016) ITE keyboard report descriptor\n"); + rdesc[185] = HID_MAIN_ITEM_RELATIVE; + } }
return rdesc; @@ -114,7 +119,8 @@ static const struct hid_device_id ite_devices[] = { /* ITE8910 USB kbd ctlr, with Synaptics touchpad connected to it. */ { HID_DEVICE(BUS_USB, HID_GROUP_GENERIC, USB_VENDOR_ID_SYNAPTICS, - USB_DEVICE_ID_SYNAPTICS_ACER_ONE_S1003) }, + USB_DEVICE_ID_SYNAPTICS_ACER_ONE_S1003), + .driver_data = QUIRK_TOUCHPAD_ON_OFF_REPORT }, { } }; MODULE_DEVICE_TABLE(hid, ite_devices);
From: Greg Kroah-Hartman gregkh@linuxfoundation.org
From: Nadeem Athani nadeem@cadence.com
[ Upstream commit 4740b969aaf58adeca6829947a3ad8da423976cf ]
Cadence controller will not initiate autonomous speed change if strapped as Gen2. The Retrain Link bit is set as quirk to enable this speed change.
Link: https://lore.kernel.org/r/20210209144622.26683-3-nadeem@cadence.com Signed-off-by: Nadeem Athani nadeem@cadence.com Signed-off-by: Lorenzo Pieralisi lorenzo.pieralisi@arm.com Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/pci/controller/cadence/pci-j721e.c | 3 + .../controller/cadence/pcie-cadence-host.c | 81 ++++++++++++++----- drivers/pci/controller/cadence/pcie-cadence.h | 11 ++- 3 files changed, 76 insertions(+), 19 deletions(-)
diff --git a/drivers/pci/controller/cadence/pci-j721e.c b/drivers/pci/controller/cadence/pci-j721e.c index dac1ac8a7615..849f1e416ea5 100644 --- a/drivers/pci/controller/cadence/pci-j721e.c +++ b/drivers/pci/controller/cadence/pci-j721e.c @@ -64,6 +64,7 @@ enum j721e_pcie_mode {
struct j721e_pcie_data { enum j721e_pcie_mode mode; + bool quirk_retrain_flag; };
static inline u32 j721e_pcie_user_readl(struct j721e_pcie *pcie, u32 offset) @@ -280,6 +281,7 @@ static struct pci_ops cdns_ti_pcie_host_ops = {
static const struct j721e_pcie_data j721e_pcie_rc_data = { .mode = PCI_MODE_RC, + .quirk_retrain_flag = true, };
static const struct j721e_pcie_data j721e_pcie_ep_data = { @@ -388,6 +390,7 @@ static int j721e_pcie_probe(struct platform_device *pdev)
bridge->ops = &cdns_ti_pcie_host_ops; rc = pci_host_bridge_priv(bridge); + rc->quirk_retrain_flag = data->quirk_retrain_flag;
cdns_pcie = &rc->pcie; cdns_pcie->dev = dev; diff --git a/drivers/pci/controller/cadence/pcie-cadence-host.c b/drivers/pci/controller/cadence/pcie-cadence-host.c index 1cb7cfc75d6e..73dcf8cf98fb 100644 --- a/drivers/pci/controller/cadence/pcie-cadence-host.c +++ b/drivers/pci/controller/cadence/pcie-cadence-host.c @@ -77,6 +77,68 @@ static struct pci_ops cdns_pcie_host_ops = { .write = pci_generic_config_write, };
+static int cdns_pcie_host_wait_for_link(struct cdns_pcie *pcie) +{ + struct device *dev = pcie->dev; + int retries; + + /* Check if the link is up or not */ + for (retries = 0; retries < LINK_WAIT_MAX_RETRIES; retries++) { + if (cdns_pcie_link_up(pcie)) { + dev_info(dev, "Link up\n"); + return 0; + } + usleep_range(LINK_WAIT_USLEEP_MIN, LINK_WAIT_USLEEP_MAX); + } + + return -ETIMEDOUT; +} + +static int cdns_pcie_retrain(struct cdns_pcie *pcie) +{ + u32 lnk_cap_sls, pcie_cap_off = CDNS_PCIE_RP_CAP_OFFSET; + u16 lnk_stat, lnk_ctl; + int ret = 0; + + /* + * Set retrain bit if current speed is 2.5 GB/s, + * but the PCIe root port support is > 2.5 GB/s. + */ + + lnk_cap_sls = cdns_pcie_readl(pcie, (CDNS_PCIE_RP_BASE + pcie_cap_off + + PCI_EXP_LNKCAP)); + if ((lnk_cap_sls & PCI_EXP_LNKCAP_SLS) <= PCI_EXP_LNKCAP_SLS_2_5GB) + return ret; + + lnk_stat = cdns_pcie_rp_readw(pcie, pcie_cap_off + PCI_EXP_LNKSTA); + if ((lnk_stat & PCI_EXP_LNKSTA_CLS) == PCI_EXP_LNKSTA_CLS_2_5GB) { + lnk_ctl = cdns_pcie_rp_readw(pcie, + pcie_cap_off + PCI_EXP_LNKCTL); + lnk_ctl |= PCI_EXP_LNKCTL_RL; + cdns_pcie_rp_writew(pcie, pcie_cap_off + PCI_EXP_LNKCTL, + lnk_ctl); + + ret = cdns_pcie_host_wait_for_link(pcie); + } + return ret; +} + +static int cdns_pcie_host_start_link(struct cdns_pcie_rc *rc) +{ + struct cdns_pcie *pcie = &rc->pcie; + int ret; + + ret = cdns_pcie_host_wait_for_link(pcie); + + /* + * Retrain link for Gen2 training defect + * if quirk flag is set. + */ + if (!ret && rc->quirk_retrain_flag) + ret = cdns_pcie_retrain(pcie); + + return ret; +}
static int cdns_pcie_host_init_root_port(struct cdns_pcie_rc *rc) { @@ -399,23 +461,6 @@ static int cdns_pcie_host_init(struct device *dev, return cdns_pcie_host_init_address_translation(rc); }
-static int cdns_pcie_host_wait_for_link(struct cdns_pcie *pcie) -{ - struct device *dev = pcie->dev; - int retries; - - /* Check if the link is up or not */ - for (retries = 0; retries < LINK_WAIT_MAX_RETRIES; retries++) { - if (cdns_pcie_link_up(pcie)) { - dev_info(dev, "Link up\n"); - return 0; - } - usleep_range(LINK_WAIT_USLEEP_MIN, LINK_WAIT_USLEEP_MAX); - } - - return -ETIMEDOUT; -} - int cdns_pcie_host_setup(struct cdns_pcie_rc *rc) { struct device *dev = rc->pcie.dev; @@ -458,7 +503,7 @@ int cdns_pcie_host_setup(struct cdns_pcie_rc *rc) return ret; }
- ret = cdns_pcie_host_wait_for_link(pcie); + ret = cdns_pcie_host_start_link(rc); if (ret) dev_dbg(dev, "PCIe link never came up\n");
diff --git a/drivers/pci/controller/cadence/pcie-cadence.h b/drivers/pci/controller/cadence/pcie-cadence.h index 30eba6cafe2c..254d2570f8c9 100644 --- a/drivers/pci/controller/cadence/pcie-cadence.h +++ b/drivers/pci/controller/cadence/pcie-cadence.h @@ -119,7 +119,7 @@ * Root Port Registers (PCI configuration space for the root port function) */ #define CDNS_PCIE_RP_BASE 0x00200000 - +#define CDNS_PCIE_RP_CAP_OFFSET 0xc0
/* * Address Translation Registers @@ -291,6 +291,7 @@ struct cdns_pcie { * @device_id: PCI device ID * @avail_ib_bar: Satus of RP_BAR0, RP_BAR1 and RP_NO_BAR if it's free or * available + * @quirk_retrain_flag: Retrain link as quirk for PCIe Gen2 */ struct cdns_pcie_rc { struct cdns_pcie pcie; @@ -299,6 +300,7 @@ struct cdns_pcie_rc { u32 vendor_id; u32 device_id; bool avail_ib_bar[CDNS_PCIE_RP_MAX_IB]; + bool quirk_retrain_flag; };
/** @@ -414,6 +416,13 @@ static inline void cdns_pcie_rp_writew(struct cdns_pcie *pcie, cdns_pcie_write_sz(addr, 0x2, value); }
+static inline u16 cdns_pcie_rp_readw(struct cdns_pcie *pcie, u32 reg) +{ + void __iomem *addr = pcie->reg_base + CDNS_PCIE_RP_BASE + reg; + + return cdns_pcie_read_sz(addr, 0x2); +} + /* Endpoint Function register access */ static inline void cdns_pcie_ep_fn_writeb(struct cdns_pcie *pcie, u8 fn, u32 reg, u8 value)
From: Greg Kroah-Hartman gregkh@linuxfoundation.org
From: Pierre-Louis Bossart pierre-louis.bossart@linux.intel.com
[ Upstream commit 3d09cf8d0d791a41a75123e135f604d59f4aa870 ]
The quirk table is a mess, let's reorganize it by generation before making sure that the quirks are consistent for each generation.
Signed-off-by: Pierre-Louis Bossart pierre-louis.bossart@linux.intel.com Reviewed-by: Guennadi Liakhovetski guennadi.liakhovetski@intel.com Reviewed-by: Kai Vehmanen kai.vehmanen@linux.intel.com Link: https://lore.kernel.org/r/20210208233336.59449-2-pierre-louis.bossart@linux.... Signed-off-by: Mark Brown broonie@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- sound/soc/intel/boards/sof_sdw.c | 73 +++++++++++++++++--------------- 1 file changed, 38 insertions(+), 35 deletions(-)
diff --git a/sound/soc/intel/boards/sof_sdw.c b/sound/soc/intel/boards/sof_sdw.c index daca06dde99b..9e2e8f508ed4 100644 --- a/sound/soc/intel/boards/sof_sdw.c +++ b/sound/soc/intel/boards/sof_sdw.c @@ -48,37 +48,14 @@ static int sof_sdw_quirk_cb(const struct dmi_system_id *id) }
static const struct dmi_system_id sof_sdw_quirk_table[] = { + /* CometLake devices */ { .callback = sof_sdw_quirk_cb, .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"), - DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0A32") - }, - .driver_data = (void *)(SOF_SDW_TGL_HDMI | - SOF_RT711_JD_SRC_JD2 | - SOF_RT715_DAI_ID_FIX | - SOF_SDW_FOUR_SPK), - }, - { - .callback = sof_sdw_quirk_cb, - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"), - DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0A3E") - }, - .driver_data = (void *)(SOF_SDW_TGL_HDMI | - SOF_RT711_JD_SRC_JD2 | - SOF_RT715_DAI_ID_FIX), - }, - { - .callback = sof_sdw_quirk_cb, - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"), - DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0A5E") + DMI_MATCH(DMI_SYS_VENDOR, "Intel Corporation"), + DMI_MATCH(DMI_PRODUCT_NAME, "CometLake Client"), }, - .driver_data = (void *)(SOF_SDW_TGL_HDMI | - SOF_RT711_JD_SRC_JD2 | - SOF_RT715_DAI_ID_FIX | - SOF_SDW_FOUR_SPK), + .driver_data = (void *)SOF_SDW_PCH_DMIC, }, { .callback = sof_sdw_quirk_cb, @@ -109,7 +86,7 @@ static const struct dmi_system_id sof_sdw_quirk_table[] = { SOF_RT715_DAI_ID_FIX | SOF_SDW_FOUR_SPK), }, - { + { .callback = sof_sdw_quirk_cb, .matches = { DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"), @@ -119,6 +96,16 @@ static const struct dmi_system_id sof_sdw_quirk_table[] = { SOF_RT715_DAI_ID_FIX | SOF_SDW_FOUR_SPK), }, + /* IceLake devices */ + { + .callback = sof_sdw_quirk_cb, + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Intel Corporation"), + DMI_MATCH(DMI_PRODUCT_NAME, "Ice Lake Client"), + }, + .driver_data = (void *)SOF_SDW_PCH_DMIC, + }, + /* TigerLake devices */ { .callback = sof_sdw_quirk_cb, .matches = { @@ -134,18 +121,23 @@ static const struct dmi_system_id sof_sdw_quirk_table[] = { { .callback = sof_sdw_quirk_cb, .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "Intel Corporation"), - DMI_MATCH(DMI_PRODUCT_NAME, "Ice Lake Client"), + DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"), + DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0A3E") }, - .driver_data = (void *)SOF_SDW_PCH_DMIC, + .driver_data = (void *)(SOF_SDW_TGL_HDMI | + SOF_RT711_JD_SRC_JD2 | + SOF_RT715_DAI_ID_FIX), }, { .callback = sof_sdw_quirk_cb, .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "Intel Corporation"), - DMI_MATCH(DMI_PRODUCT_NAME, "CometLake Client"), + DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"), + DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0A5E") }, - .driver_data = (void *)SOF_SDW_PCH_DMIC, + .driver_data = (void *)(SOF_SDW_TGL_HDMI | + SOF_RT711_JD_SRC_JD2 | + SOF_RT715_DAI_ID_FIX | + SOF_SDW_FOUR_SPK), }, { .callback = sof_sdw_quirk_cb, @@ -167,7 +159,18 @@ static const struct dmi_system_id sof_sdw_quirk_table[] = { SOF_SDW_PCH_DMIC | SOF_SDW_FOUR_SPK), }, - + /* TigerLake-SDCA devices */ + { + .callback = sof_sdw_quirk_cb, + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"), + DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0A32") + }, + .driver_data = (void *)(SOF_SDW_TGL_HDMI | + SOF_RT711_JD_SRC_JD2 | + SOF_RT715_DAI_ID_FIX | + SOF_SDW_FOUR_SPK), + }, {} };
From: Greg Kroah-Hartman gregkh@linuxfoundation.org
From: Pierre-Louis Bossart pierre-louis.bossart@linux.intel.com
[ Upstream commit d92e279dee56b4b65c1af21f972413f172a9734a ]
This set of devices has SoundWire support along with DMICs. The DMI information was provided by users for 3 separate skus.
BugLink: https://github.com/thesofproject/linux/issues/2700 Signed-off-by: Pierre-Louis Bossart pierre-louis.bossart@linux.intel.com Reviewed-by: Guennadi Liakhovetski guennadi.liakhovetski@intel.com Reviewed-by: Kai Vehmanen kai.vehmanen@linux.intel.com Link: https://lore.kernel.org/r/20210208233336.59449-4-pierre-louis.bossart@linux.... Signed-off-by: Mark Brown broonie@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- sound/soc/intel/boards/sof_sdw.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+)
diff --git a/sound/soc/intel/boards/sof_sdw.c b/sound/soc/intel/boards/sof_sdw.c index 9e2e8f508ed4..1d7677376e74 100644 --- a/sound/soc/intel/boards/sof_sdw.c +++ b/sound/soc/intel/boards/sof_sdw.c @@ -159,6 +159,22 @@ static const struct dmi_system_id sof_sdw_quirk_table[] = { SOF_SDW_PCH_DMIC | SOF_SDW_FOUR_SPK), }, + { + /* + * this entry covers multiple HP SKUs. The family name + * does not seem robust enough, so we use a partial + * match that ignores the product name suffix + * (e.g. 15-eb1xxx, 14t-ea000 or 13-aw2xxx) + */ + .callback = sof_sdw_quirk_cb, + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "HP"), + DMI_MATCH(DMI_PRODUCT_NAME, "HP Spectre x360 Convertible"), + }, + .driver_data = (void *)(SOF_SDW_TGL_HDMI | + SOF_SDW_PCH_DMIC | + SOF_RT711_JD_SRC_JD2), + }, /* TigerLake-SDCA devices */ { .callback = sof_sdw_quirk_cb,
From: Greg Kroah-Hartman gregkh@linuxfoundation.org
From: Avri Altman avri.altman@wdc.com
[ Upstream commit 9599a1cf23330008d90b7c232efe95de7510ff29 ]
Fixes: 2b2bfc8aa519 ("scsi: ufs: Introduce a quirk to allow only page-aligned sg entries") Link: https://lore.kernel.org/r/20210211104638.292499-1-avri.altman@wdc.com Reviewed-by: Bean Huo beanhuo@micron.com Signed-off-by: Avri Altman avri.altman@wdc.com Signed-off-by: Martin K. Petersen martin.petersen@oracle.com Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/scsi/ufs/ufshcd.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/scsi/ufs/ufshcd.h b/drivers/scsi/ufs/ufshcd.h index 8cb64ae95462..1885ec9126c4 100644 --- a/drivers/scsi/ufs/ufshcd.h +++ b/drivers/scsi/ufs/ufshcd.h @@ -560,7 +560,7 @@ enum ufshcd_quirks { /* * This quirk allows only sg entries aligned with page size. */ - UFSHCD_QUIRK_ALIGN_SG_WITH_PAGE_SIZE = 1 << 13, + UFSHCD_QUIRK_ALIGN_SG_WITH_PAGE_SIZE = 1 << 14, };
enum ufshcd_caps {
From: Greg Kroah-Hartman gregkh@linuxfoundation.org
From: Babu Moger babu.moger@amd.com
[ Upstream commit 9e46f6c6c959d9bb45445c2e8f04a75324a0dfd0 ]
This problem was reported on a SVM guest while executing kexec. Kexec fails to load the new kernel when the PCID feature is enabled.
When kexec starts loading the new kernel, it starts the process by resetting the vCPU's and then bringing each vCPU online one by one. The vCPU reset is supposed to reset all the register states before the vCPUs are brought online. However, the CR4 register is not reset during this process. If this register is already setup during the last boot, all the flags can remain intact. The X86_CR4_PCIDE bit can only be enabled in long mode. So, it must be enabled much later in SMP initialization. Having the X86_CR4_PCIDE bit set during SMP boot can cause a boot failures.
Fix the issue by resetting the CR4 register in init_vmcb().
Signed-off-by: Babu Moger babu.moger@amd.com Message-Id: 161471109108.30811.6392805173629704166.stgit@bmoger-ubuntu Signed-off-by: Paolo Bonzini pbonzini@redhat.com Signed-off-by: Sasha Levin sashal@kernel.org --- arch/x86/kvm/svm/svm.c | 1 + 1 file changed, 1 insertion(+)
diff --git a/arch/x86/kvm/svm/svm.c b/arch/x86/kvm/svm/svm.c index 825ef6d281c9..6a0670548125 100644 --- a/arch/x86/kvm/svm/svm.c +++ b/arch/x86/kvm/svm/svm.c @@ -1205,6 +1205,7 @@ static void init_vmcb(struct vcpu_svm *svm) init_sys_seg(&save->ldtr, SEG_TYPE_LDT); init_sys_seg(&save->tr, SEG_TYPE_BUSY_TSS16);
+ svm_set_cr4(&svm->vcpu, 0); svm_set_efer(&svm->vcpu, 0); save->dr6 = 0xffff0ff0; kvm_set_rflags(&svm->vcpu, 2);
From: Greg Kroah-Hartman gregkh@linuxfoundation.org
From: Julian Einwag jeinwag-nvme@marcapo.com
[ Upstream commit 5e112d3fb89703a4981ded60561b5647db3693bf ]
The kernel fails to fully detect these SSDs, only the character devices are present:
[ 10.785605] nvme nvme0: pci function 0000:04:00.0 [ 10.876787] nvme nvme1: pci function 0000:81:00.0 [ 13.198614] nvme nvme0: missing or invalid SUBNQN field. [ 13.198658] nvme nvme1: missing or invalid SUBNQN field. [ 13.206896] nvme nvme0: Shutdown timeout set to 20 seconds [ 13.215035] nvme nvme1: Shutdown timeout set to 20 seconds [ 13.225407] nvme nvme0: 16/0/0 default/read/poll queues [ 13.233602] nvme nvme1: 16/0/0 default/read/poll queues [ 13.239627] nvme nvme0: Identify Descriptors failed (8194) [ 13.246315] nvme nvme1: Identify Descriptors failed (8194)
Adding the NVME_QUIRK_NO_NS_DESC_LIST fixes this problem.
BugLink: https://bugzilla.kernel.org/show_bug.cgi?id=205679 Signed-off-by: Julian Einwag jeinwag-nvme@marcapo.com Signed-off-by: Christoph Hellwig hch@lst.de Reviewed-by: Keith Busch kbusch@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/nvme/host/pci.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/drivers/nvme/host/pci.c b/drivers/nvme/host/pci.c index 6bad4d4dcdf0..7a38d764b486 100644 --- a/drivers/nvme/host/pci.c +++ b/drivers/nvme/host/pci.c @@ -3230,7 +3230,8 @@ static const struct pci_device_id nvme_id_table[] = { { PCI_DEVICE(0x126f, 0x2263), /* Silicon Motion unidentified */ .driver_data = NVME_QUIRK_NO_NS_DESC_LIST, }, { PCI_DEVICE(0x1bb1, 0x0100), /* Seagate Nytro Flash Storage */ - .driver_data = NVME_QUIRK_DELAY_BEFORE_CHK_RDY, }, + .driver_data = NVME_QUIRK_DELAY_BEFORE_CHK_RDY | + NVME_QUIRK_NO_NS_DESC_LIST, }, { PCI_DEVICE(0x1c58, 0x0003), /* HGST adapter */ .driver_data = NVME_QUIRK_DELAY_BEFORE_CHK_RDY, }, { PCI_DEVICE(0x1c58, 0x0023), /* WDC SN200 adapter */
From: Greg Kroah-Hartman gregkh@linuxfoundation.org
From: Pascal Terjan pterjan@google.com
[ Upstream commit 6e6a6828c517fb6819479bf5187df5f39084eb9e ]
Add the NVME_QUIRK_NO_NS_DESC_LIST and NVME_QUIRK_IGNORE_DEV_SUBNQN quirks for this buggy device.
Reported and tested in https://bugs.mageia.org/show_bug.cgi?id=28417
Signed-off-by: Pascal Terjan pterjan@google.com Signed-off-by: Christoph Hellwig hch@lst.de Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/nvme/host/pci.c | 3 +++ 1 file changed, 3 insertions(+)
diff --git a/drivers/nvme/host/pci.c b/drivers/nvme/host/pci.c index 14c5b52400ef..806a5d071ef6 100644 --- a/drivers/nvme/host/pci.c +++ b/drivers/nvme/host/pci.c @@ -3245,6 +3245,9 @@ static const struct pci_device_id nvme_id_table[] = { NVME_QUIRK_IGNORE_DEV_SUBNQN, }, { PCI_DEVICE(0x1987, 0x5016), /* Phison E16 */ .driver_data = NVME_QUIRK_IGNORE_DEV_SUBNQN, }, + { PCI_DEVICE(0x1b4b, 0x1092), /* Lexar 256 GB SSD */ + .driver_data = NVME_QUIRK_NO_NS_DESC_LIST | + NVME_QUIRK_IGNORE_DEV_SUBNQN, }, { PCI_DEVICE(0x1d1d, 0x1f1f), /* LighNVM qemu device */ .driver_data = NVME_QUIRK_LIGHTNVM, }, { PCI_DEVICE(0x1d1d, 0x2807), /* CNEX WL */
On 3/10/21 6:23 AM, gregkh@linuxfoundation.org wrote:
From: Greg Kroah-Hartman gregkh@linuxfoundation.org
This is the start of the stable review cycle for the 5.11.6 release. There are 36 patches in this series, all will be posted as a response to this one. If anyone has any issues with these being applied, please let me know.
Responses should be made by Fri, 12 Mar 2021 13:23:09 +0000. Anything received after that time might be too late.
The whole patch series can be found in one patch at: https://www.kernel.org/pub/linux/kernel/v5.x/stable-review/patch-5.11.6-rc1.... or in the git tree and branch at: git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable-rc.git linux-5.11.y and the diffstat can be found below.
thanks,
greg k-h
Compiled and booted on my test system. No dmesg regressions.
Tested-by: Shuah Khan skhan@linuxfoundation.org
thanks, -- Shuah
On Wed, Mar 10, 2021 at 02:59:43PM -0700, Shuah Khan wrote:
On 3/10/21 6:23 AM, gregkh@linuxfoundation.org wrote:
From: Greg Kroah-Hartman gregkh@linuxfoundation.org
This is the start of the stable review cycle for the 5.11.6 release. There are 36 patches in this series, all will be posted as a response to this one. If anyone has any issues with these being applied, please let me know.
Responses should be made by Fri, 12 Mar 2021 13:23:09 +0000. Anything received after that time might be too late.
The whole patch series can be found in one patch at: https://www.kernel.org/pub/linux/kernel/v5.x/stable-review/patch-5.11.6-rc1.... or in the git tree and branch at: git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable-rc.git linux-5.11.y and the diffstat can be found below.
thanks,
greg k-h
Compiled and booted on my test system. No dmesg regressions.
Tested-by: Shuah Khan skhan@linuxfoundation.org
Thanks for testing all of these and letting me know.
greg k-h
On Wed, Mar 10, 2021 at 02:23:13PM +0100, gregkh@linuxfoundation.org wrote:
From: Greg Kroah-Hartman gregkh@linuxfoundation.org
This is the start of the stable review cycle for the 5.11.6 release. There are 36 patches in this series, all will be posted as a response to this one. If anyone has any issues with these being applied, please let me know.
Responses should be made by Fri, 12 Mar 2021 13:23:09 +0000. Anything received after that time might be too late.
Build results: total: 155 pass: 155 fail: 0 Qemu test results: total: 437 pass: 437 fail: 0
Tested-by: Guenter Roeck linux@roeck-us.net
Guenter
On Wed, Mar 10, 2021 at 03:53:01PM -0800, Guenter Roeck wrote:
On Wed, Mar 10, 2021 at 02:23:13PM +0100, gregkh@linuxfoundation.org wrote:
From: Greg Kroah-Hartman gregkh@linuxfoundation.org
This is the start of the stable review cycle for the 5.11.6 release. There are 36 patches in this series, all will be posted as a response to this one. If anyone has any issues with these being applied, please let me know.
Responses should be made by Fri, 12 Mar 2021 13:23:09 +0000. Anything received after that time might be too late.
Build results: total: 155 pass: 155 fail: 0 Qemu test results: total: 437 pass: 437 fail: 0
Tested-by: Guenter Roeck linux@roeck-us.net
Thanks for all the testing.
greg k-h
On Wed, 10 Mar 2021 at 18:54, gregkh@linuxfoundation.org wrote:
From: Greg Kroah-Hartman gregkh@linuxfoundation.org
This is the start of the stable review cycle for the 5.11.6 release. There are 36 patches in this series, all will be posted as a response to this one. If anyone has any issues with these being applied, please let me know.
Responses should be made by Fri, 12 Mar 2021 13:23:09 +0000. Anything received after that time might be too late.
The whole patch series can be found in one patch at: https://www.kernel.org/pub/linux/kernel/v5.x/stable-review/patch-5.11.6-rc1.... or in the git tree and branch at: git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable-rc.git linux-5.11.y and the diffstat can be found below.
thanks,
greg k-h
Results from Linaro’s test farm. No regressions on arm64, arm, x86_64, and i386.
Tested-by: Linux Kernel Functional Testing lkft@linaro.org
Summary ------------------------------------------------------------------------
kernel: 5.11.6-rc1 git repo: https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable-rc.git git branch: linux-5.11.y git commit: 4107fbb88ee5fa94c8e94ffe5833b7fbda792c96 git describe: v5.11.5-37-g4107fbb88ee5 Test details: https://qa-reports.linaro.org/lkft/linux-stable-rc-linux-5.11.y/build/v5.11....
No regressions (compared to build v5.11.5)
No fixes (compared to build v5.11.5)
Ran 52341 total tests in the following environments and test suites.
Environments -------------- - arc - arm - arm64 - dragonboard-410c - hi6220-hikey - i386 - juno-64k_page_size - juno-r2 - juno-r2-compat - juno-r2-kasan - mips - nxp-ls2088 - nxp-ls2088-64k_page_size - parisc - powerpc - qemu-arm-clang - qemu-arm64-clang - qemu-arm64-kasan - qemu-i386-clang - qemu-x86_64-clang - qemu-x86_64-kasan - qemu-x86_64-kcsan - qemu_arm - qemu_arm64 - qemu_arm64-compat - qemu_i386 - qemu_x86_64 - qemu_x86_64-compat - riscv - s390 - sh - sparc - x15 - x86 - x86-kasan - x86_64
Test Suites ----------- * build * linux-log-parser * install-android-platform-tools-r2600 * kselftest- * kselftest-android * kselftest-bpf * kselftest-capabilities * kselftest-cgroup * kselftest-clone3 * kselftest-core * kselftest-cpu-hotplug * kselftest-cpufreq * kselftest-efivarfs * kselftest-filesystems * kselftest-firmware * kselftest-fpu * kselftest-futex * kselftest-gpio * kselftest-intel_pstate * kselftest-ipc * kselftest-ir * kselftest-kcmp * kselftest-lib * kselftest-livepatch * kselftest-membarrier * kselftest-memfd * kselftest-memory-hotplug * kselftest-mincore * kselftest-mount * kselftest-mqueue * kselftest-net * kselftest-netfilter * kselftest-nsfs * kselftest-openat2 * kselftest-pid_namespace * kselftest-pidfd * kselftest-proc * kselftest-pstore * kselftest-ptrace * kselftest-tc-testing * kselftest-timens * kselftest-timers * kselftest-tmpfs * kselftest-tpm2 * kselftest-user * kselftest-zram * ltp-commands-tests * ltp-cve-tests * ltp-dio-tests * ltp-fcntl-locktests-tests * ltp-filecaps-tests * ltp-fs-tests * ltp-fs_bind-tests * ltp-fs_perms_simple-tests * ltp-fsx-tests * ltp-hugetlb-tests * ltp-io-tests * ltp-math-tests * ltp-mm-tests * ltp-nptl-tests * ltp-pty-tests * ltp-securebits-tests * perf * fwts * kselftest-rseq * kselftest-rtc * kselftest-seccomp * kselftest-sigaltstack * kselftest-size * kselftest-splice * kselftest-static_keys * kselftest-sync * kselftest-sysctl * libhugetlbfs * ltp-cap_bounds-tests * ltp-containers-tests * ltp-cpuhotplug-tests * ltp-crypto-tests * ltp-ipc-tests * ltp-sched-tests * ltp-tracing-tests * network-basic-tests * v4l2-compliance * kselftest-kexec * kselftest-kvm * kselftest-lkdtm * kselftest-vm * kselftest-x86 * ltp-controllers-tests * ltp-open-posix-tests * ltp-syscalls-tests * kvm-unit-tests * rcutorture * kunit * kselftest-vsyscall-mode-native- * kselftest-vsyscall-mode-none- * ssuite
On Thu, Mar 11, 2021 at 08:51:27AM +0530, Naresh Kamboju wrote:
On Wed, 10 Mar 2021 at 18:54, gregkh@linuxfoundation.org wrote:
From: Greg Kroah-Hartman gregkh@linuxfoundation.org
This is the start of the stable review cycle for the 5.11.6 release. There are 36 patches in this series, all will be posted as a response to this one. If anyone has any issues with these being applied, please let me know.
Responses should be made by Fri, 12 Mar 2021 13:23:09 +0000. Anything received after that time might be too late.
The whole patch series can be found in one patch at: https://www.kernel.org/pub/linux/kernel/v5.x/stable-review/patch-5.11.6-rc1.... or in the git tree and branch at: git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable-rc.git linux-5.11.y and the diffstat can be found below.
thanks,
greg k-h
Results from Linaro’s test farm. No regressions on arm64, arm, x86_64, and i386.
Tested-by: Linux Kernel Functional Testing lkft@linaro.org
Thanks for testing them all and letting me know.
greg k-h
On Wed, Mar 10, 2021 at 02:23:13PM +0100, gregkh@linuxfoundation.org wrote:
From: Greg Kroah-Hartman gregkh@linuxfoundation.org
This is the start of the stable review cycle for the 5.11.6 release. There are 36 patches in this series, all will be posted as a response to this one. If anyone has any issues with these being applied, please let me know.
Compiled and booted with no regressions on x86_64.
Tested-by: Ross Schmidt ross.schm.dev@gmail.com
thanks,
Ross
On Wed, Mar 10, 2021 at 10:09:55PM -0600, Ross Schmidt wrote:
On Wed, Mar 10, 2021 at 02:23:13PM +0100, gregkh@linuxfoundation.org wrote:
From: Greg Kroah-Hartman gregkh@linuxfoundation.org
This is the start of the stable review cycle for the 5.11.6 release. There are 36 patches in this series, all will be posted as a response to this one. If anyone has any issues with these being applied, please let me know.
Compiled and booted with no regressions on x86_64.
Tested-by: Ross Schmidt ross.schm.dev@gmail.com
Thanks for testing.
On Wed, 10 Mar 2021 14:23:13 +0100, gregkh@linuxfoundation.org wrote:
From: Greg Kroah-Hartman gregkh@linuxfoundation.org
This is the start of the stable review cycle for the 5.11.6 release. There are 36 patches in this series, all will be posted as a response to this one. If anyone has any issues with these being applied, please let me know.
Responses should be made by Fri, 12 Mar 2021 13:23:09 +0000. Anything received after that time might be too late.
The whole patch series can be found in one patch at: https://www.kernel.org/pub/linux/kernel/v5.x/stable-review/patch-5.11.6-rc1.... or in the git tree and branch at: git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable-rc.git linux-5.11.y and the diffstat can be found below.
thanks,
greg k-h
All tests passing for Tegra ...
Test results for stable-v5.11: 12 builds: 12 pass, 0 fail 26 boots: 26 pass, 0 fail 65 tests: 65 pass, 0 fail
Linux version: 5.11.6-rc1-g4107fbb88ee5 Boards tested: tegra124-jetson-tk1, tegra186-p2771-0000, tegra194-p2972-0000, tegra20-ventana, tegra210-p2371-2180, tegra210-p3450-0000, tegra30-cardhu-a04
Tested-by: Jon Hunter jonathanh@nvidia.com
Jon
On Thu, Mar 11, 2021 at 07:59:56AM +0000, Jon Hunter wrote:
On Wed, 10 Mar 2021 14:23:13 +0100, gregkh@linuxfoundation.org wrote:
From: Greg Kroah-Hartman gregkh@linuxfoundation.org
This is the start of the stable review cycle for the 5.11.6 release. There are 36 patches in this series, all will be posted as a response to this one. If anyone has any issues with these being applied, please let me know.
Responses should be made by Fri, 12 Mar 2021 13:23:09 +0000. Anything received after that time might be too late.
The whole patch series can be found in one patch at: https://www.kernel.org/pub/linux/kernel/v5.x/stable-review/patch-5.11.6-rc1.... or in the git tree and branch at: git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable-rc.git linux-5.11.y and the diffstat can be found below.
thanks,
greg k-h
All tests passing for Tegra ...
Test results for stable-v5.11: 12 builds: 12 pass, 0 fail 26 boots: 26 pass, 0 fail 65 tests: 65 pass, 0 fail
Linux version: 5.11.6-rc1-g4107fbb88ee5 Boards tested: tegra124-jetson-tk1, tegra186-p2771-0000, tegra194-p2972-0000, tegra20-ventana, tegra210-p2371-2180, tegra210-p3450-0000, tegra30-cardhu-a04
Tested-by: Jon Hunter jonathanh@nvidia.com
thanks for testing them all.
linux-stable-mirror@lists.linaro.org