From 95f32191e50b75e0f75fae1bb925cdf51d8df0a3 Mon Sep 17 00:00:00 2001 From: Issam Hamdi Date: Fri, 16 Aug 2024 16:24:18 +0200 Subject: [PATCH 001/267] wifi: cfg80211: Set correct chandef when starting CAC [ Upstream commit 20361712880396e44ce80aaeec2d93d182035651 ] When starting CAC in a mode other than AP mode, it return a "WARNING: CPU: 0 PID: 63 at cfg80211_chandef_dfs_usable+0x20/0xaf [cfg80211]" caused by the chandef.chan being null at the end of CAC. Solution: Ensure the channel definition is set for the different modes when starting CAC to avoid getting a NULL 'chan' at the end of CAC. Call Trace: ? show_regs.part.0+0x14/0x16 ? __warn+0x67/0xc0 ? cfg80211_chandef_dfs_usable+0x20/0xaf [cfg80211] ? report_bug+0xa7/0x130 ? exc_overflow+0x30/0x30 ? handle_bug+0x27/0x50 ? exc_invalid_op+0x18/0x60 ? handle_exception+0xf6/0xf6 ? exc_overflow+0x30/0x30 ? cfg80211_chandef_dfs_usable+0x20/0xaf [cfg80211] ? exc_overflow+0x30/0x30 ? cfg80211_chandef_dfs_usable+0x20/0xaf [cfg80211] ? regulatory_propagate_dfs_state.cold+0x1b/0x4c [cfg80211] ? cfg80211_propagate_cac_done_wk+0x1a/0x30 [cfg80211] ? process_one_work+0x165/0x280 ? worker_thread+0x120/0x3f0 ? kthread+0xc2/0xf0 ? process_one_work+0x280/0x280 ? kthread_complete_and_exit+0x20/0x20 ? ret_from_fork+0x19/0x24 Reported-by: Kretschmer Mathias Signed-off-by: Issam Hamdi Link: https://patch.msgid.link/20240816142418.3381951-1-ih@simonwunderlich.de [shorten subject, remove OCB, reorder cases to match previous list] Signed-off-by: Johannes Berg Signed-off-by: Sasha Levin --- net/wireless/nl80211.c | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index fe14997ce2c0..4df7a285a7de 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c @@ -9834,7 +9834,20 @@ static int nl80211_start_radar_detection(struct sk_buff *skb, err = rdev_start_radar_detection(rdev, dev, &chandef, cac_time_ms); if (!err) { - wdev->links[0].ap.chandef = chandef; + switch (wdev->iftype) { + case NL80211_IFTYPE_AP: + case NL80211_IFTYPE_P2P_GO: + wdev->links[0].ap.chandef = chandef; + break; + case NL80211_IFTYPE_ADHOC: + wdev->u.ibss.chandef = chandef; + break; + case NL80211_IFTYPE_MESH_POINT: + wdev->u.mesh.chandef = chandef; + break; + default: + break; + } wdev->cac_started = true; wdev->cac_start_time = jiffies; wdev->cac_time_ms = cac_time_ms; From efcff6ce7467f01f0753609f420333f3f2ceceda Mon Sep 17 00:00:00 2001 From: Jeongjun Park Date: Fri, 23 Aug 2024 03:11:09 +0900 Subject: [PATCH 002/267] net/xen-netback: prevent UAF in xenvif_flush_hash() [ Upstream commit 0fa5e94a1811d68fbffa0725efe6d4ca62c03d12 ] During the list_for_each_entry_rcu iteration call of xenvif_flush_hash, kfree_rcu does not exist inside the rcu read critical section, so if kfree_rcu is called when the rcu grace period ends during the iteration, UAF occurs when accessing head->next after the entry becomes free. Therefore, to solve this, you need to change it to list_for_each_entry_safe. Signed-off-by: Jeongjun Park Link: https://patch.msgid.link/20240822181109.2577354-1-aha310510@gmail.com Signed-off-by: Jakub Kicinski Signed-off-by: Sasha Levin --- drivers/net/xen-netback/hash.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/drivers/net/xen-netback/hash.c b/drivers/net/xen-netback/hash.c index ff96f22648ef..45ddce35f6d2 100644 --- a/drivers/net/xen-netback/hash.c +++ b/drivers/net/xen-netback/hash.c @@ -95,7 +95,7 @@ static u32 xenvif_new_hash(struct xenvif *vif, const u8 *data, static void xenvif_flush_hash(struct xenvif *vif) { - struct xenvif_hash_cache_entry *entry; + struct xenvif_hash_cache_entry *entry, *n; unsigned long flags; if (xenvif_hash_cache_size == 0) @@ -103,8 +103,7 @@ static void xenvif_flush_hash(struct xenvif *vif) spin_lock_irqsave(&vif->hash.cache.lock, flags); - list_for_each_entry_rcu(entry, &vif->hash.cache.list, link, - lockdep_is_held(&vif->hash.cache.lock)) { + list_for_each_entry_safe(entry, n, &vif->hash.cache.list, link) { list_del_rcu(&entry->link); vif->hash.cache.count--; kfree_rcu(entry, rcu); From 933e7f90e0f3bcd9d1e15154d7dfc8f54d7abfc8 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Tue, 27 Aug 2024 16:44:19 +0200 Subject: [PATCH 003/267] net: hisilicon: hip04: fix OF node leak in probe() [ Upstream commit 17555297dbd5bccc93a01516117547e26a61caf1 ] Driver is leaking OF node reference from of_parse_phandle_with_fixed_args() in probe(). Signed-off-by: Krzysztof Kozlowski Reviewed-by: Simon Horman Link: https://patch.msgid.link/20240827144421.52852-2-krzysztof.kozlowski@linaro.org Signed-off-by: Jakub Kicinski Signed-off-by: Sasha Levin --- drivers/net/ethernet/hisilicon/hip04_eth.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/net/ethernet/hisilicon/hip04_eth.c b/drivers/net/ethernet/hisilicon/hip04_eth.c index 50c3f5d6611f..2abdb5d98691 100644 --- a/drivers/net/ethernet/hisilicon/hip04_eth.c +++ b/drivers/net/ethernet/hisilicon/hip04_eth.c @@ -947,6 +947,7 @@ static int hip04_mac_probe(struct platform_device *pdev) priv->tx_coalesce_timer.function = tx_done; priv->map = syscon_node_to_regmap(arg.np); + of_node_put(arg.np); if (IS_ERR(priv->map)) { dev_warn(d, "no syscon hisilicon,hip04-ppe\n"); ret = PTR_ERR(priv->map); From 2bb3368d3c5921e409913238e9dc011cbe494706 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Tue, 27 Aug 2024 16:44:20 +0200 Subject: [PATCH 004/267] net: hisilicon: hns_dsaf_mac: fix OF node leak in hns_mac_get_info() [ Upstream commit 5680cf8d34e1552df987e2f4bb1bff0b2a8c8b11 ] Driver is leaking OF node reference from of_parse_phandle_with_fixed_args() in hns_mac_get_info(). Signed-off-by: Krzysztof Kozlowski Reviewed-by: Simon Horman Link: https://patch.msgid.link/20240827144421.52852-3-krzysztof.kozlowski@linaro.org Signed-off-by: Jakub Kicinski Signed-off-by: Sasha Levin --- drivers/net/ethernet/hisilicon/hns/hns_dsaf_mac.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_mac.c b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_mac.c index f75668c47935..616a2768e504 100644 --- a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_mac.c +++ b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_mac.c @@ -933,6 +933,7 @@ static int hns_mac_get_info(struct hns_mac_cb *mac_cb) mac_cb->cpld_ctrl = NULL; } else { syscon = syscon_node_to_regmap(cpld_args.np); + of_node_put(cpld_args.np); if (IS_ERR_OR_NULL(syscon)) { dev_dbg(mac_cb->dev, "no cpld-syscon found!\n"); mac_cb->cpld_ctrl = NULL; From c80a203364b73b986493c923938cab5dbb2f6b28 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Tue, 27 Aug 2024 16:44:21 +0200 Subject: [PATCH 005/267] net: hisilicon: hns_mdio: fix OF node leak in probe() [ Upstream commit e62beddc45f487b9969821fad3a0913d9bc18a2f ] Driver is leaking OF node reference from of_parse_phandle_with_fixed_args() in probe(). Signed-off-by: Krzysztof Kozlowski Reviewed-by: Simon Horman Link: https://patch.msgid.link/20240827144421.52852-4-krzysztof.kozlowski@linaro.org Signed-off-by: Jakub Kicinski Signed-off-by: Sasha Levin --- drivers/net/ethernet/hisilicon/hns_mdio.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/net/ethernet/hisilicon/hns_mdio.c b/drivers/net/ethernet/hisilicon/hns_mdio.c index c2ae1b4f9a5f..8a9dce6017d8 100644 --- a/drivers/net/ethernet/hisilicon/hns_mdio.c +++ b/drivers/net/ethernet/hisilicon/hns_mdio.c @@ -497,6 +497,7 @@ static int hns_mdio_probe(struct platform_device *pdev) MDIO_SC_RESET_ST; } } + of_node_put(reg_args.np); } else { dev_warn(&pdev->dev, "find syscon ret = %#x\n", ret); mdio_dev->subctrl_vbase = NULL; From 68a599da16ebad442ce295d8d2d5c488e3992822 Mon Sep 17 00:00:00 2001 From: Seiji Nishikawa Date: Sun, 25 Aug 2024 23:13:52 +0900 Subject: [PATCH 006/267] ACPI: PAD: fix crash in exit_round_robin() [ Upstream commit 0a2ed70a549e61c5181bad5db418d223b68ae932 ] The kernel occasionally crashes in cpumask_clear_cpu(), which is called within exit_round_robin(), because when executing clear_bit(nr, addr) with nr set to 0xffffffff, the address calculation may cause misalignment within the memory, leading to access to an invalid memory address. ---------- BUG: unable to handle kernel paging request at ffffffffe0740618 ... CPU: 3 PID: 2919323 Comm: acpi_pad/14 Kdump: loaded Tainted: G OE X --------- - - 4.18.0-425.19.2.el8_7.x86_64 #1 ... RIP: 0010:power_saving_thread+0x313/0x411 [acpi_pad] Code: 89 cd 48 89 d3 eb d1 48 c7 c7 55 70 72 c0 e8 64 86 b0 e4 c6 05 0d a1 02 00 01 e9 bc fd ff ff 45 89 e4 42 8b 04 a5 20 82 72 c0 48 0f b3 05 f4 9c 01 00 42 c7 04 a5 20 82 72 c0 ff ff ff ff 31 RSP: 0018:ff72a5d51fa77ec8 EFLAGS: 00010202 RAX: 00000000ffffffff RBX: ff462981e5d8cb80 RCX: 0000000000000000 RDX: 0000000000000000 RSI: 0000000000000246 RDI: 0000000000000246 RBP: ff46297556959d80 R08: 0000000000000382 R09: ff46297c8d0f38d8 R10: 0000000000000000 R11: 0000000000000001 R12: 000000000000000e R13: 0000000000000000 R14: ffffffffffffffff R15: 000000000000000e FS: 0000000000000000(0000) GS:ff46297a800c0000(0000) knlGS:0000000000000000 CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 CR2: ffffffffe0740618 CR3: 0000007e20410004 CR4: 0000000000771ee0 DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000 DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400 PKRU: 55555554 Call Trace: ? acpi_pad_add+0x120/0x120 [acpi_pad] kthread+0x10b/0x130 ? set_kthread_struct+0x50/0x50 ret_from_fork+0x1f/0x40 ... CR2: ffffffffe0740618 crash> dis -lr ffffffffc0726923 ... /usr/src/debug/kernel-4.18.0-425.19.2.el8_7/linux-4.18.0-425.19.2.el8_7.x86_64/./include/linux/cpumask.h: 114 0xffffffffc0726918 : mov %r12d,%r12d /usr/src/debug/kernel-4.18.0-425.19.2.el8_7/linux-4.18.0-425.19.2.el8_7.x86_64/./include/linux/cpumask.h: 325 0xffffffffc072691b : mov -0x3f8d7de0(,%r12,4),%eax /usr/src/debug/kernel-4.18.0-425.19.2.el8_7/linux-4.18.0-425.19.2.el8_7.x86_64/./arch/x86/include/asm/bitops.h: 80 0xffffffffc0726923 : lock btr %rax,0x19cf4(%rip) # 0xffffffffc0740620 crash> px tsk_in_cpu[14] $66 = 0xffffffff crash> px 0xffffffffc072692c+0x19cf4 $99 = 0xffffffffc0740620 crash> sym 0xffffffffc0740620 ffffffffc0740620 (b) pad_busy_cpus_bits [acpi_pad] crash> px pad_busy_cpus_bits[0] $42 = 0xfffc0 ---------- To fix this, ensure that tsk_in_cpu[tsk_index] != -1 before calling cpumask_clear_cpu() in exit_round_robin(), just as it is done in round_robin_cpu(). Signed-off-by: Seiji Nishikawa Link: https://patch.msgid.link/20240825141352.25280-1-snishika@redhat.com [ rjw: Subject edit, avoid updates to the same value ] Signed-off-by: Rafael J. Wysocki Signed-off-by: Sasha Levin --- drivers/acpi/acpi_pad.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/acpi/acpi_pad.c b/drivers/acpi/acpi_pad.c index ec0e22a1e25d..bfb8ad1e2e85 100644 --- a/drivers/acpi/acpi_pad.c +++ b/drivers/acpi/acpi_pad.c @@ -130,8 +130,10 @@ static void exit_round_robin(unsigned int tsk_index) { struct cpumask *pad_busy_cpus = to_cpumask(pad_busy_cpus_bits); - cpumask_clear_cpu(tsk_in_cpu[tsk_index], pad_busy_cpus); - tsk_in_cpu[tsk_index] = -1; + if (tsk_in_cpu[tsk_index] != -1) { + cpumask_clear_cpu(tsk_in_cpu[tsk_index], pad_busy_cpus); + tsk_in_cpu[tsk_index] = -1; + } } static unsigned int idle_pct = 5; /* percentage */ From 55076cdb8698720807d3c025f00acb3cc0da281c Mon Sep 17 00:00:00 2001 From: Armin Wolf Date: Wed, 3 Apr 2024 20:50:11 +0200 Subject: [PATCH 007/267] ACPICA: Fix memory leak if acpi_ps_get_next_namepath() fails [ Upstream commit 5accb265f7a1b23e52b0ec42313d1e12895552f4 ] ACPICA commit 2802af722bbde7bf1a7ac68df68e179e2555d361 If acpi_ps_get_next_namepath() fails, the previously allocated union acpi_parse_object needs to be freed before returning the status code. The issue was first being reported on the Linux ACPI mailing list: Link: https://lore.kernel.org/linux-acpi/56f94776-484f-48c0-8855-dba8e6a7793b@yandex.ru/T/ Link: https://github.com/acpica/acpica/commit/2802af72 Signed-off-by: Armin Wolf Signed-off-by: Rafael J. Wysocki Signed-off-by: Sasha Levin --- drivers/acpi/acpica/psargs.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/drivers/acpi/acpica/psargs.c b/drivers/acpi/acpica/psargs.c index f7ec5606098c..919a7aebcc03 100644 --- a/drivers/acpi/acpica/psargs.c +++ b/drivers/acpi/acpica/psargs.c @@ -820,6 +820,10 @@ acpi_ps_get_next_arg(struct acpi_walk_state *walk_state, acpi_ps_get_next_namepath(walk_state, parser_state, arg, ACPI_NOT_METHOD_CALL); + if (ACPI_FAILURE(status)) { + acpi_ps_free_op(arg); + return_ACPI_STATUS(status); + } } else { /* Single complex argument, nothing returned */ @@ -854,6 +858,10 @@ acpi_ps_get_next_arg(struct acpi_walk_state *walk_state, acpi_ps_get_next_namepath(walk_state, parser_state, arg, ACPI_POSSIBLE_METHOD_CALL); + if (ACPI_FAILURE(status)) { + acpi_ps_free_op(arg); + return_ACPI_STATUS(status); + } if (arg->common.aml_opcode == AML_INT_METHODCALL_OP) { From 5bc1ee87f4ca1ee9f371df1ea60c25461699a65c Mon Sep 17 00:00:00 2001 From: Armin Wolf Date: Sun, 14 Apr 2024 21:50:33 +0200 Subject: [PATCH 008/267] ACPICA: Fix memory leak if acpi_ps_get_next_field() fails [ Upstream commit e6169a8ffee8a012badd8c703716e761ce851b15 ] ACPICA commit 1280045754264841b119a5ede96cd005bc09b5a7 If acpi_ps_get_next_field() fails, the previously created field list needs to be properly disposed before returning the status code. Link: https://github.com/acpica/acpica/commit/12800457 Signed-off-by: Armin Wolf [ rjw: Rename local variable to avoid compiler confusion ] Signed-off-by: Rafael J. Wysocki Signed-off-by: Sasha Levin --- drivers/acpi/acpica/psargs.c | 39 ++++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) diff --git a/drivers/acpi/acpica/psargs.c b/drivers/acpi/acpica/psargs.c index 919a7aebcc03..418d56203e27 100644 --- a/drivers/acpi/acpica/psargs.c +++ b/drivers/acpi/acpica/psargs.c @@ -25,6 +25,8 @@ acpi_ps_get_next_package_length(struct acpi_parse_state *parser_state); static union acpi_parse_object *acpi_ps_get_next_field(struct acpi_parse_state *parser_state); +static void acpi_ps_free_field_list(union acpi_parse_object *start); + /******************************************************************************* * * FUNCTION: acpi_ps_get_next_package_length @@ -683,6 +685,39 @@ static union acpi_parse_object *acpi_ps_get_next_field(struct acpi_parse_state return_PTR(field); } +/******************************************************************************* + * + * FUNCTION: acpi_ps_free_field_list + * + * PARAMETERS: start - First Op in field list + * + * RETURN: None. + * + * DESCRIPTION: Free all Op objects inside a field list. + * + ******************************************************************************/ + +static void acpi_ps_free_field_list(union acpi_parse_object *start) +{ + union acpi_parse_object *cur = start; + union acpi_parse_object *next; + union acpi_parse_object *arg; + + while (cur) { + next = cur->common.next; + + /* AML_INT_CONNECTION_OP can have a single argument */ + + arg = acpi_ps_get_arg(cur, 0); + if (arg) { + acpi_ps_free_op(arg); + } + + acpi_ps_free_op(cur); + cur = next; + } +} + /******************************************************************************* * * FUNCTION: acpi_ps_get_next_arg @@ -751,6 +786,10 @@ acpi_ps_get_next_arg(struct acpi_walk_state *walk_state, while (parser_state->aml < parser_state->pkg_end) { field = acpi_ps_get_next_field(parser_state); if (!field) { + if (arg) { + acpi_ps_free_field_list(arg); + } + return_ACPI_STATUS(AE_NO_MEMORY); } From 89fbb0d2bc31fb0b9ceddafb12405f3a9df18e01 Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Tue, 27 Aug 2024 11:29:54 +0200 Subject: [PATCH 009/267] wifi: mt76: mt7915: disable tx worker during tx BA session enable/disable [ Upstream commit 256cbd26fbafb30ba3314339106e5c594e9bd5f9 ] Avoids firmware race condition. Link: https://patch.msgid.link/20240827093011.18621-7-nbd@nbd.name Signed-off-by: Felix Fietkau Signed-off-by: Sasha Levin --- drivers/net/wireless/mediatek/mt76/mt7915/mcu.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c index 65f07cc2acdd..44fbfe3775e0 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c +++ b/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c @@ -661,13 +661,17 @@ int mt7915_mcu_add_tx_ba(struct mt7915_dev *dev, { struct mt7915_sta *msta = (struct mt7915_sta *)params->sta->drv_priv; struct mt7915_vif *mvif = msta->vif; + int ret; + mt76_worker_disable(&dev->mt76.tx_worker); if (enable && !params->amsdu) msta->wcid.amsdu = false; + ret = mt76_connac_mcu_sta_ba(&dev->mt76, &mvif->mt76, params, + MCU_EXT_CMD(STA_REC_UPDATE), + enable, true); + mt76_worker_enable(&dev->mt76.tx_worker); - return mt76_connac_mcu_sta_ba(&dev->mt76, &mvif->mt76, params, - MCU_EXT_CMD(STA_REC_UPDATE), - enable, true); + return ret; } int mt7915_mcu_add_rx_ba(struct mt7915_dev *dev, From cad3093a9fd69a4dfe25db8501952b7430d52369 Mon Sep 17 00:00:00 2001 From: Dmitry Antipov Date: Wed, 4 Sep 2024 14:54:01 +0300 Subject: [PATCH 010/267] net: sched: consistently use rcu_replace_pointer() in taprio_change() [ Upstream commit d5c4546062fd6f5dbce575c7ea52ad66d1968678 ] According to Vinicius (and carefully looking through the whole https://syzkaller.appspot.com/bug?extid=b65e0af58423fc8a73aa once again), txtime branch of 'taprio_change()' is not going to race against 'advance_sched()'. But using 'rcu_replace_pointer()' in the former may be a good idea as well. Suggested-by: Vinicius Costa Gomes Signed-off-by: Dmitry Antipov Acked-by: Vinicius Costa Gomes Signed-off-by: David S. Miller Signed-off-by: Sasha Levin --- net/sched/sch_taprio.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/net/sched/sch_taprio.c b/net/sched/sch_taprio.c index 41187bbd25ee..07f6f5343dd7 100644 --- a/net/sched/sch_taprio.c +++ b/net/sched/sch_taprio.c @@ -1668,7 +1668,9 @@ static int taprio_change(struct Qdisc *sch, struct nlattr *opt, goto unlock; } - rcu_assign_pointer(q->admin_sched, new_admin); + /* Not going to race against advance_sched(), but still */ + admin = rcu_replace_pointer(q->admin_sched, new_admin, + lockdep_rtnl_is_held()); if (admin) call_rcu(&admin->rcu, taprio_free_sched_cb); } else { From cf4e0b68ae857e9d7393b1ce70af99840f121671 Mon Sep 17 00:00:00 2001 From: Hilda Wu Date: Fri, 16 Aug 2024 16:58:22 +0800 Subject: [PATCH 011/267] Bluetooth: btusb: Add Realtek RTL8852C support ID 0x0489:0xe122 [ Upstream commit bdf9557f70e7512bb2f754abf90d9e9958745316 ] Add the support ID (0x0489, 0xe122) to usb_device_id table for Realtek RTL8852C. The device info from /sys/kernel/debug/usb/devices as below. T: Bus=03 Lev=01 Prnt=01 Port=02 Cnt=01 Dev#= 2 Spd=12 MxCh= 0 D: Ver= 1.00 Cls=e0(wlcon) Sub=01 Prot=01 MxPS=64 #Cfgs= 1 P: Vendor=0489 ProdID=e122 Rev= 0.00 S: Manufacturer=Realtek S: Product=Bluetooth Radio S: SerialNumber=00e04c000001 C:* #Ifs= 2 Cfg#= 1 Atr=e0 MxPwr=500mA I:* If#= 0 Alt= 0 #EPs= 3 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb E: Ad=81(I) Atr=03(Int.) MxPS= 16 Ivl=1ms E: Ad=02(O) Atr=02(Bulk) MxPS= 64 Ivl=0ms E: Ad=82(I) Atr=02(Bulk) MxPS= 64 Ivl=0ms I:* If#= 1 Alt= 0 #EPs= 2 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb E: Ad=03(O) Atr=01(Isoc) MxPS= 0 Ivl=1ms E: Ad=83(I) Atr=01(Isoc) MxPS= 0 Ivl=1ms I: If#= 1 Alt= 1 #EPs= 2 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb E: Ad=03(O) Atr=01(Isoc) MxPS= 9 Ivl=1ms E: Ad=83(I) Atr=01(Isoc) MxPS= 9 Ivl=1ms I: If#= 1 Alt= 2 #EPs= 2 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb E: Ad=03(O) Atr=01(Isoc) MxPS= 17 Ivl=1ms E: Ad=83(I) Atr=01(Isoc) MxPS= 17 Ivl=1ms I: If#= 1 Alt= 3 #EPs= 2 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb E: Ad=03(O) Atr=01(Isoc) MxPS= 25 Ivl=1ms E: Ad=83(I) Atr=01(Isoc) MxPS= 25 Ivl=1ms I: If#= 1 Alt= 4 #EPs= 2 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb E: Ad=03(O) Atr=01(Isoc) MxPS= 33 Ivl=1ms E: Ad=83(I) Atr=01(Isoc) MxPS= 33 Ivl=1ms I: If#= 1 Alt= 5 #EPs= 2 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb E: Ad=03(O) Atr=01(Isoc) MxPS= 49 Ivl=1ms E: Ad=83(I) Atr=01(Isoc) MxPS= 49 Ivl=1ms Signed-off-by: Hilda Wu Signed-off-by: Luiz Augusto von Dentz Signed-off-by: Sasha Levin --- drivers/bluetooth/btusb.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c index dc5150f67723..ca5828a274cd 100644 --- a/drivers/bluetooth/btusb.c +++ b/drivers/bluetooth/btusb.c @@ -531,6 +531,8 @@ static const struct usb_device_id blacklist_table[] = { BTUSB_WIDEBAND_SPEECH }, { USB_DEVICE(0x13d3, 0x3592), .driver_info = BTUSB_REALTEK | BTUSB_WIDEBAND_SPEECH }, + { USB_DEVICE(0x0489, 0xe122), .driver_info = BTUSB_REALTEK | + BTUSB_WIDEBAND_SPEECH }, /* Realtek 8852BE Bluetooth devices */ { USB_DEVICE(0x0cb8, 0xc559), .driver_info = BTUSB_REALTEK | From 0fe5621176a0449f3abf710dc0faf9905d0c3f05 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Sat, 7 Sep 2024 14:44:19 +0200 Subject: [PATCH 012/267] ACPI: video: Add force_vendor quirk for Panasonic Toughbook CF-18 [ Upstream commit eb7b0f12e13ba99e64e3a690c2166895ed63b437 ] The Panasonic Toughbook CF-18 advertises both native and vendor backlight control interfaces. But only the vendor one actually works. acpi_video_get_backlight_type() will pick the non working native backlight by default, add a quirk to select the working vendor backlight instead. Signed-off-by: Hans de Goede Link: https://patch.msgid.link/20240907124419.21195-1-hdegoede@redhat.com Signed-off-by: Rafael J. Wysocki Signed-off-by: Sasha Levin --- drivers/acpi/video_detect.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/drivers/acpi/video_detect.c b/drivers/acpi/video_detect.c index 60b0128a10e8..f7a2ab62c6c2 100644 --- a/drivers/acpi/video_detect.c +++ b/drivers/acpi/video_detect.c @@ -258,6 +258,14 @@ static const struct dmi_system_id video_detect_dmi_table[] = { DMI_MATCH(DMI_PRODUCT_NAME, "PCG-FRV35"), }, }, + { + .callback = video_detect_force_vendor, + /* Panasonic Toughbook CF-18 */ + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Matsushita Electric Industrial"), + DMI_MATCH(DMI_PRODUCT_NAME, "CF-18"), + }, + }, /* * Toshiba models with Transflective display, these need to use From 59121bb38fdc01434ea3fe361ee02b59f036227f Mon Sep 17 00:00:00 2001 From: Konstantin Ovsepian Date: Thu, 22 Aug 2024 08:41:36 -0700 Subject: [PATCH 013/267] blk_iocost: fix more out of bound shifts [ Upstream commit 9bce8005ec0dcb23a58300e8522fe4a31da606fa ] Recently running UBSAN caught few out of bound shifts in the ioc_forgive_debts() function: UBSAN: shift-out-of-bounds in block/blk-iocost.c:2142:38 shift exponent 80 is too large for 64-bit type 'u64' (aka 'unsigned long long') ... UBSAN: shift-out-of-bounds in block/blk-iocost.c:2144:30 shift exponent 80 is too large for 64-bit type 'u64' (aka 'unsigned long long') ... Call Trace: dump_stack_lvl+0xca/0x130 __ubsan_handle_shift_out_of_bounds+0x22c/0x280 ? __lock_acquire+0x6441/0x7c10 ioc_timer_fn+0x6cec/0x7750 ? blk_iocost_init+0x720/0x720 ? call_timer_fn+0x5d/0x470 call_timer_fn+0xfa/0x470 ? blk_iocost_init+0x720/0x720 __run_timer_base+0x519/0x700 ... Actual impact of this issue was not identified but I propose to fix the undefined behaviour. The proposed fix to prevent those out of bound shifts consist of precalculating exponent before using it the shift operations by taking min value from the actual exponent and maximum possible number of bits. Reported-by: Breno Leitao Signed-off-by: Konstantin Ovsepian Acked-by: Tejun Heo Link: https://lore.kernel.org/r/20240822154137.2627818-1-ovs@ovs.to Signed-off-by: Jens Axboe Signed-off-by: Sasha Levin --- block/blk-iocost.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/block/blk-iocost.c b/block/blk-iocost.c index 64b594d660b7..772e909e9fbf 100644 --- a/block/blk-iocost.c +++ b/block/blk-iocost.c @@ -2057,7 +2057,7 @@ static void ioc_forgive_debts(struct ioc *ioc, u64 usage_us_sum, int nr_debtors, struct ioc_now *now) { struct ioc_gq *iocg; - u64 dur, usage_pct, nr_cycles; + u64 dur, usage_pct, nr_cycles, nr_cycles_shift; /* if no debtor, reset the cycle */ if (!nr_debtors) { @@ -2119,10 +2119,12 @@ static void ioc_forgive_debts(struct ioc *ioc, u64 usage_us_sum, int nr_debtors, old_debt = iocg->abs_vdebt; old_delay = iocg->delay; + nr_cycles_shift = min_t(u64, nr_cycles, BITS_PER_LONG - 1); if (iocg->abs_vdebt) - iocg->abs_vdebt = iocg->abs_vdebt >> nr_cycles ?: 1; + iocg->abs_vdebt = iocg->abs_vdebt >> nr_cycles_shift ?: 1; + if (iocg->delay) - iocg->delay = iocg->delay >> nr_cycles ?: 1; + iocg->delay = iocg->delay >> nr_cycles_shift ?: 1; iocg_kick_waitq(iocg, true, now); From 0087dc9e7016fae8bd656300f282d440c72a523f Mon Sep 17 00:00:00 2001 From: Keith Busch Date: Wed, 11 Sep 2024 10:39:59 -0700 Subject: [PATCH 014/267] nvme-pci: qdepth 1 quirk [ Upstream commit 83bdfcbdbe5d901c5fa432decf12e1725a840a56 ] Another device has been reported to be unreliable if we have more than one outstanding command. In this new case, data corruption may occur. Since we have two devices now needing this quirky behavior, make a generic quirk flag. The same Apple quirk is clearly not "temporary", so update the comment while moving it. Link: https://lore.kernel.org/linux-nvme/191d810a4e3.fcc6066c765804.973611676137075390@collabora.com/ Reported-by: Robert Beckett Reviewed-by: Christoph Hellwig hch@lst.de> Signed-off-by: Keith Busch Signed-off-by: Sasha Levin --- drivers/nvme/host/nvme.h | 5 +++++ drivers/nvme/host/pci.c | 18 +++++++++--------- 2 files changed, 14 insertions(+), 9 deletions(-) diff --git a/drivers/nvme/host/nvme.h b/drivers/nvme/host/nvme.h index 8e28d2de45c0..5f8a146b7014 100644 --- a/drivers/nvme/host/nvme.h +++ b/drivers/nvme/host/nvme.h @@ -86,6 +86,11 @@ enum nvme_quirks { */ NVME_QUIRK_NO_DEEPEST_PS = (1 << 5), + /* + * Problems seen with concurrent commands + */ + NVME_QUIRK_QDEPTH_ONE = (1 << 6), + /* * Set MEDIUM priority on SQ creation */ diff --git a/drivers/nvme/host/pci.c b/drivers/nvme/host/pci.c index 54a969aa72be..f0063962c2c8 100644 --- a/drivers/nvme/host/pci.c +++ b/drivers/nvme/host/pci.c @@ -2621,15 +2621,8 @@ static int nvme_pci_enable(struct nvme_dev *dev) else dev->io_sqes = NVME_NVM_IOSQES; - /* - * Temporary fix for the Apple controller found in the MacBook8,1 and - * some MacBook7,1 to avoid controller resets and data loss. - */ - if (pdev->vendor == PCI_VENDOR_ID_APPLE && pdev->device == 0x2001) { + if (dev->ctrl.quirks & NVME_QUIRK_QDEPTH_ONE) { dev->q_depth = 2; - dev_warn(dev->ctrl.device, "detected Apple NVMe controller, " - "set queue depth=%u to work around controller resets\n", - dev->q_depth); } else if (pdev->vendor == PCI_VENDOR_ID_SAMSUNG && (pdev->device == 0xa821 || pdev->device == 0xa822) && NVME_CAP_MQES(dev->ctrl.cap) == 0) { @@ -3491,6 +3484,8 @@ static const struct pci_device_id nvme_id_table[] = { NVME_QUIRK_BOGUS_NID, }, { PCI_VDEVICE(REDHAT, 0x0010), /* Qemu emulated controller */ .driver_data = NVME_QUIRK_BOGUS_NID, }, + { PCI_DEVICE(0x1217, 0x8760), /* O2 Micro 64GB Steam Deck */ + .driver_data = NVME_QUIRK_QDEPTH_ONE }, { PCI_DEVICE(0x126f, 0x2262), /* Silicon Motion generic */ .driver_data = NVME_QUIRK_NO_DEEPEST_PS | NVME_QUIRK_BOGUS_NID, }, @@ -3617,7 +3612,12 @@ static const struct pci_device_id nvme_id_table[] = { { PCI_DEVICE(PCI_VENDOR_ID_AMAZON, 0xcd02), .driver_data = NVME_QUIRK_DMA_ADDRESS_BITS_48, }, { PCI_DEVICE(PCI_VENDOR_ID_APPLE, 0x2001), - .driver_data = NVME_QUIRK_SINGLE_VECTOR }, + /* + * Fix for the Apple controller found in the MacBook8,1 and + * some MacBook7,1 to avoid controller resets and data loss. + */ + .driver_data = NVME_QUIRK_SINGLE_VECTOR | + NVME_QUIRK_QDEPTH_ONE }, { PCI_DEVICE(PCI_VENDOR_ID_APPLE, 0x2003) }, { PCI_DEVICE(PCI_VENDOR_ID_APPLE, 0x2005), .driver_data = NVME_QUIRK_SINGLE_VECTOR | From 73e235728e515faccc104b0153b47d0f263b3344 Mon Sep 17 00:00:00 2001 From: Karthikeyan Periyasamy Date: Thu, 4 Jul 2024 12:38:11 +0530 Subject: [PATCH 015/267] wifi: ath11k: fix array out-of-bound access in SoC stats [ Upstream commit 69f253e46af98af17e3efa3e5dfa72fcb7d1983d ] Currently, the ath11k_soc_dp_stats::hal_reo_error array is defined with a maximum size of DP_REO_DST_RING_MAX. However, the ath11k_dp_process_rx() function access ath11k_soc_dp_stats::hal_reo_error using the REO destination SRNG ring ID, which is incorrect. SRNG ring ID differ from normal ring ID, and this usage leads to out-of-bounds array access. To fix this issue, modify ath11k_dp_process_rx() to use the normal ring ID directly instead of the SRNG ring ID to avoid out-of-bounds array access. Tested-on: QCN9074 hw1.0 PCI WLAN.HK.2.7.0.1-01744-QCAHKSWPL_SILICONZ-1 Signed-off-by: Karthikeyan Periyasamy Signed-off-by: Kalle Valo Link: https://patch.msgid.link/20240704070811.4186543-3-quic_periyasa@quicinc.com Signed-off-by: Sasha Levin --- drivers/net/wireless/ath/ath11k/dp_rx.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/ath/ath11k/dp_rx.c b/drivers/net/wireless/ath/ath11k/dp_rx.c index 3746f9c95696..73f299f65e2e 100644 --- a/drivers/net/wireless/ath/ath11k/dp_rx.c +++ b/drivers/net/wireless/ath/ath11k/dp_rx.c @@ -2699,7 +2699,7 @@ try_again: if (unlikely(push_reason != HAL_REO_DEST_RING_PUSH_REASON_ROUTING_INSTRUCTION)) { dev_kfree_skb_any(msdu); - ab->soc_stats.hal_reo_error[dp->reo_dst_ring[ring_id].ring_id]++; + ab->soc_stats.hal_reo_error[ring_id]++; continue; } From bc51ebfd9bc771f942321d95a9cda1ac7aeb6e81 Mon Sep 17 00:00:00 2001 From: Zong-Zhe Yang Date: Thu, 18 Jul 2024 15:06:15 +0800 Subject: [PATCH 016/267] wifi: rtw88: select WANT_DEV_COREDUMP [ Upstream commit 7e989b0c1e33210c07340bf5228aa83ea52515b5 ] We have invoked device coredump when fw crash. Should select WANT_DEV_COREDUMP by ourselves. Signed-off-by: Zong-Zhe Yang Signed-off-by: Ping-Ke Shih Link: https://patch.msgid.link/20240718070616.42217-1-pkshih@realtek.com Signed-off-by: Sasha Levin --- drivers/net/wireless/realtek/rtw88/Kconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/net/wireless/realtek/rtw88/Kconfig b/drivers/net/wireless/realtek/rtw88/Kconfig index e3d7cb6c1290..5c18da555681 100644 --- a/drivers/net/wireless/realtek/rtw88/Kconfig +++ b/drivers/net/wireless/realtek/rtw88/Kconfig @@ -12,6 +12,7 @@ if RTW88 config RTW88_CORE tristate + select WANT_DEV_COREDUMP config RTW88_PCI tristate From de6a9bb884e522ba29ac919a2718cc66e66f5fd5 Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Thu, 4 Jul 2024 18:26:54 +0200 Subject: [PATCH 017/267] ACPI: EC: Do not release locks during operation region accesses [ Upstream commit dc171114926ec390ab90f46534545420ec03e458 ] It is not particularly useful to release locks (the EC mutex and the ACPI global lock, if present) and re-acquire them immediately thereafter during EC address space accesses in acpi_ec_space_handler(). First, releasing them for a while before grabbing them again does not really help anyone because there may not be enough time for another thread to acquire them. Second, if another thread successfully acquires them and carries out a new EC write or read in the middle if an operation region access in progress, it may confuse the EC firmware, especially after the burst mode has been enabled. Finally, manipulating the locks after writing or reading every single byte of data is overhead that it is better to avoid. Accordingly, modify the code to carry out EC address space accesses entirely without releasing the locks. Signed-off-by: Rafael J. Wysocki Reviewed-by: Hans de Goede Link: https://patch.msgid.link/12473338.O9o76ZdvQC@rjwysocki.net Signed-off-by: Sasha Levin --- drivers/acpi/ec.c | 55 +++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 49 insertions(+), 6 deletions(-) diff --git a/drivers/acpi/ec.c b/drivers/acpi/ec.c index 7589908b358e..63803091f8b1 100644 --- a/drivers/acpi/ec.c +++ b/drivers/acpi/ec.c @@ -797,6 +797,9 @@ static int acpi_ec_transaction_unlocked(struct acpi_ec *ec, unsigned long tmp; int ret = 0; + if (t->rdata) + memset(t->rdata, 0, t->rlen); + /* start transaction */ spin_lock_irqsave(&ec->lock, tmp); /* Enable GPE for command processing (IBF=0/OBF=1) */ @@ -833,8 +836,6 @@ static int acpi_ec_transaction(struct acpi_ec *ec, struct transaction *t) if (!ec || (!t) || (t->wlen && !t->wdata) || (t->rlen && !t->rdata)) return -EINVAL; - if (t->rdata) - memset(t->rdata, 0, t->rlen); mutex_lock(&ec->mutex); if (ec->global_lock) { @@ -861,7 +862,7 @@ static int acpi_ec_burst_enable(struct acpi_ec *ec) .wdata = NULL, .rdata = &d, .wlen = 0, .rlen = 1}; - return acpi_ec_transaction(ec, &t); + return acpi_ec_transaction_unlocked(ec, &t); } static int acpi_ec_burst_disable(struct acpi_ec *ec) @@ -871,7 +872,7 @@ static int acpi_ec_burst_disable(struct acpi_ec *ec) .wlen = 0, .rlen = 0}; return (acpi_ec_read_status(ec) & ACPI_EC_FLAG_BURST) ? - acpi_ec_transaction(ec, &t) : 0; + acpi_ec_transaction_unlocked(ec, &t) : 0; } static int acpi_ec_read(struct acpi_ec *ec, u8 address, u8 *data) @@ -887,6 +888,19 @@ static int acpi_ec_read(struct acpi_ec *ec, u8 address, u8 *data) return result; } +static int acpi_ec_read_unlocked(struct acpi_ec *ec, u8 address, u8 *data) +{ + int result; + u8 d; + struct transaction t = {.command = ACPI_EC_COMMAND_READ, + .wdata = &address, .rdata = &d, + .wlen = 1, .rlen = 1}; + + result = acpi_ec_transaction_unlocked(ec, &t); + *data = d; + return result; +} + static int acpi_ec_write(struct acpi_ec *ec, u8 address, u8 data) { u8 wdata[2] = { address, data }; @@ -897,6 +911,16 @@ static int acpi_ec_write(struct acpi_ec *ec, u8 address, u8 data) return acpi_ec_transaction(ec, &t); } +static int acpi_ec_write_unlocked(struct acpi_ec *ec, u8 address, u8 data) +{ + u8 wdata[2] = { address, data }; + struct transaction t = {.command = ACPI_EC_COMMAND_WRITE, + .wdata = wdata, .rdata = NULL, + .wlen = 2, .rlen = 0}; + + return acpi_ec_transaction_unlocked(ec, &t); +} + int ec_read(u8 addr, u8 *val) { int err; @@ -1304,6 +1328,7 @@ acpi_ec_space_handler(u32 function, acpi_physical_address address, struct acpi_ec *ec = handler_context; int result = 0, i, bytes = bits / 8; u8 *value = (u8 *)value64; + u32 glk; if ((address > 0xFF) || !value || !handler_context) return AE_BAD_PARAMETER; @@ -1311,13 +1336,25 @@ acpi_ec_space_handler(u32 function, acpi_physical_address address, if (function != ACPI_READ && function != ACPI_WRITE) return AE_BAD_PARAMETER; + mutex_lock(&ec->mutex); + + if (ec->global_lock) { + acpi_status status; + + status = acpi_acquire_global_lock(ACPI_EC_UDELAY_GLK, &glk); + if (ACPI_FAILURE(status)) { + result = -ENODEV; + goto unlock; + } + } + if (ec->busy_polling || bits > 8) acpi_ec_burst_enable(ec); for (i = 0; i < bytes; ++i, ++address, ++value) { result = (function == ACPI_READ) ? - acpi_ec_read(ec, address, value) : - acpi_ec_write(ec, address, *value); + acpi_ec_read_unlocked(ec, address, value) : + acpi_ec_write_unlocked(ec, address, *value); if (result < 0) break; } @@ -1325,6 +1362,12 @@ acpi_ec_space_handler(u32 function, acpi_physical_address address, if (ec->busy_polling || bits > 8) acpi_ec_burst_disable(ec); + if (ec->global_lock) + acpi_release_global_lock(glk); + +unlock: + mutex_unlock(&ec->mutex); + switch (result) { case -EINVAL: return AE_BAD_PARAMETER; From f282db38953ad71dd4f3f8877a4e1d37e580e30a Mon Sep 17 00:00:00 2001 From: Pei Xiao Date: Thu, 18 Jul 2024 14:05:48 +0800 Subject: [PATCH 018/267] ACPICA: check null return of ACPI_ALLOCATE_ZEROED() in acpi_db_convert_to_package() [ Upstream commit a5242874488eba2b9062985bf13743c029821330 ] ACPICA commit 4d4547cf13cca820ff7e0f859ba83e1a610b9fd0 ACPI_ALLOCATE_ZEROED() may fail, elements might be NULL and will cause NULL pointer dereference later. Link: https://github.com/acpica/acpica/commit/4d4547cf Signed-off-by: Pei Xiao Link: https://patch.msgid.link/tencent_4A21A2865B8B0A0D12CAEBEB84708EDDB505@qq.com [ rjw: Subject and changelog edits ] Signed-off-by: Rafael J. Wysocki Signed-off-by: Sasha Levin --- drivers/acpi/acpica/dbconvert.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/acpi/acpica/dbconvert.c b/drivers/acpi/acpica/dbconvert.c index 2b84ac093698..8dbab6932049 100644 --- a/drivers/acpi/acpica/dbconvert.c +++ b/drivers/acpi/acpica/dbconvert.c @@ -174,6 +174,8 @@ acpi_status acpi_db_convert_to_package(char *string, union acpi_object *object) elements = ACPI_ALLOCATE_ZEROED(DB_DEFAULT_PKG_ELEMENTS * sizeof(union acpi_object)); + if (!elements) + return (AE_NO_MEMORY); this = string; for (i = 0; i < (DB_DEFAULT_PKG_ELEMENTS - 1); i++) { From 80c0be7bcf940ce9308311575c3aff8983c9b97a Mon Sep 17 00:00:00 2001 From: Simon Horman Date: Thu, 1 Aug 2024 19:35:37 +0100 Subject: [PATCH 019/267] tipc: guard against string buffer overrun [ Upstream commit 6555a2a9212be6983d2319d65276484f7c5f431a ] Smatch reports that copying media_name and if_name to name_parts may overwrite the destination. .../bearer.c:166 bearer_name_validate() error: strcpy() 'media_name' too large for 'name_parts->media_name' (32 vs 16) .../bearer.c:167 bearer_name_validate() error: strcpy() 'if_name' too large for 'name_parts->if_name' (1010102 vs 16) This does seem to be the case so guard against this possibility by using strscpy() and failing if truncation occurs. Introduced by commit b97bf3fd8f6a ("[TIPC] Initial merge") Compile tested only. Reviewed-by: Jakub Kicinski Signed-off-by: Simon Horman Link: https://patch.msgid.link/20240801-tipic-overrun-v2-1-c5b869d1f074@kernel.org Signed-off-by: Jakub Kicinski Signed-off-by: Sasha Levin --- net/tipc/bearer.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/net/tipc/bearer.c b/net/tipc/bearer.c index 1cb993562088..538bb63e07d5 100644 --- a/net/tipc/bearer.c +++ b/net/tipc/bearer.c @@ -163,8 +163,12 @@ static int bearer_name_validate(const char *name, /* return bearer name components, if necessary */ if (name_parts) { - strcpy(name_parts->media_name, media_name); - strcpy(name_parts->if_name, if_name); + if (strscpy(name_parts->media_name, media_name, + TIPC_MAX_MEDIA_NAME) < 0) + return 0; + if (strscpy(name_parts->if_name, if_name, + TIPC_MAX_IF_NAME) < 0) + return 0; } return 1; } From 25c764f87fe7d05ff6875bfd1e5c398a2c0c889f Mon Sep 17 00:00:00 2001 From: Simon Horman Date: Tue, 6 Aug 2024 12:28:24 +0100 Subject: [PATCH 020/267] net: mvpp2: Increase size of queue_name buffer [ Upstream commit 91d516d4de48532d967a77967834e00c8c53dfe6 ] Increase size of queue_name buffer from 30 to 31 to accommodate the largest string written to it. This avoids truncation in the possibly unlikely case where the string is name is the maximum size. Flagged by gcc-14: .../mvpp2_main.c: In function 'mvpp2_probe': .../mvpp2_main.c:7636:32: warning: 'snprintf' output may be truncated before the last format character [-Wformat-truncation=] 7636 | "stats-wq-%s%s", netdev_name(priv->port_list[0]->dev), | ^ .../mvpp2_main.c:7635:9: note: 'snprintf' output between 10 and 31 bytes into a destination of size 30 7635 | snprintf(priv->queue_name, sizeof(priv->queue_name), | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 7636 | "stats-wq-%s%s", netdev_name(priv->port_list[0]->dev), | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 7637 | priv->port_count > 1 ? "+" : ""); | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Introduced by commit 118d6298f6f0 ("net: mvpp2: add ethtool GOP statistics"). I am not flagging this as a bug as I am not aware that it is one. Compile tested only. Signed-off-by: Simon Horman Reviewed-by: Marcin Wojtas Link: https://patch.msgid.link/20240806-mvpp2-namelen-v1-1-6dc773653f2f@kernel.org Signed-off-by: Jakub Kicinski Signed-off-by: Sasha Levin --- drivers/net/ethernet/marvell/mvpp2/mvpp2.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/ethernet/marvell/mvpp2/mvpp2.h b/drivers/net/ethernet/marvell/mvpp2/mvpp2.h index 11e603686a27..522d65acfc47 100644 --- a/drivers/net/ethernet/marvell/mvpp2/mvpp2.h +++ b/drivers/net/ethernet/marvell/mvpp2/mvpp2.h @@ -1088,7 +1088,7 @@ struct mvpp2 { unsigned int max_port_rxqs; /* Workqueue to gather hardware statistics */ - char queue_name[30]; + char queue_name[31]; struct workqueue_struct *stats_queue; /* Debugfs root entry */ From 12bc48a1115a85f6863595aff07f54fa1dfb78f1 Mon Sep 17 00:00:00 2001 From: Simon Horman Date: Tue, 13 Aug 2024 15:32:55 +0100 Subject: [PATCH 021/267] bnxt_en: Extend maximum length of version string by 1 byte [ Upstream commit ffff7ee843c351ce71d6e0d52f0f20bea35e18c9 ] This corrects an out-by-one error in the maximum length of the package version string. The size argument of snprintf includes space for the trailing '\0' byte, so there is no need to allow extra space for it by reducing the value of the size argument by 1. Found by inspection. Compile tested only. Signed-off-by: Simon Horman Reviewed-by: Michael Chan Link: https://patch.msgid.link/20240813-bnxt-str-v2-1-872050a157e7@kernel.org Signed-off-by: Jakub Kicinski Signed-off-by: Sasha Levin --- drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c b/drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c index 7260b4671ecc..799adba0034a 100644 --- a/drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c +++ b/drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c @@ -2980,7 +2980,7 @@ static void bnxt_get_pkgver(struct net_device *dev) if (!bnxt_get_pkginfo(dev, buf, sizeof(buf))) { len = strlen(bp->fw_ver_str); - snprintf(bp->fw_ver_str + len, FW_VER_STR_LEN - len - 1, + snprintf(bp->fw_ver_str + len, FW_VER_STR_LEN - len, "/pkg %s", buf); } } From 75aa1df311be4c42ef9887e2ac90e5b90745092f Mon Sep 17 00:00:00 2001 From: Kuniyuki Iwashima Date: Fri, 9 Aug 2024 16:54:02 -0700 Subject: [PATCH 022/267] ipv4: Check !in_dev earlier for ioctl(SIOCSIFADDR). [ Upstream commit e3af3d3c5b26c33a7950e34e137584f6056c4319 ] dev->ip_ptr could be NULL if we set an invalid MTU. Even then, if we issue ioctl(SIOCSIFADDR) for a new IPv4 address, devinet_ioctl() allocates struct in_ifaddr and fails later in inet_set_ifa() because in_dev is NULL. Let's move the check earlier. Signed-off-by: Kuniyuki Iwashima Link: https://patch.msgid.link/20240809235406.50187-2-kuniyu@amazon.com Signed-off-by: Jakub Kicinski Signed-off-by: Sasha Levin --- net/ipv4/devinet.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/net/ipv4/devinet.c b/net/ipv4/devinet.c index bb0d1252cad8..f07778c34098 100644 --- a/net/ipv4/devinet.c +++ b/net/ipv4/devinet.c @@ -567,10 +567,6 @@ static int inet_set_ifa(struct net_device *dev, struct in_ifaddr *ifa) ASSERT_RTNL(); - if (!in_dev) { - inet_free_ifa(ifa); - return -ENOBUFS; - } ipv4_devconf_setall(in_dev); neigh_parms_data_state_setall(in_dev->arp_parms); if (ifa->ifa_dev != in_dev) { @@ -1153,6 +1149,8 @@ int devinet_ioctl(struct net *net, unsigned int cmd, struct ifreq *ifr) if (!ifa) { ret = -ENOBUFS; + if (!in_dev) + break; ifa = inet_alloc_ifa(); if (!ifa) break; From af79fa5f9844a2dd53672b69f31b2200f90f15d1 Mon Sep 17 00:00:00 2001 From: Ping-Ke Shih Date: Fri, 9 Aug 2024 15:20:10 +0800 Subject: [PATCH 023/267] wifi: rtw89: correct base HT rate mask for firmware [ Upstream commit 45742881f9eee2a4daeb6008e648a460dd3742cd ] Coverity reported that u8 rx_mask << 24 will become signed 32 bits, which casting to unsigned 64 bits will do sign extension. For example, putting 0x80000000 (signed 32 bits) to a u64 variable will become 0xFFFFFFFF_80000000. The real case we meet is: rx_mask[0...3] = ff ff 00 00 ra_mask = 0xffffffff_ff0ff000 After this fix: rx_mask[0...3] = ff ff 00 00 ra_mask = 0x00000000_ff0ff000 Fortunately driver does bitwise-AND with incorrect ra_mask and supported rates (1ss and 2ss rate only) afterward, so the final rate mask of original code is still correct. Addresses-Coverity-ID: 1504762 ("Unintended sign extension") Signed-off-by: Ping-Ke Shih Link: https://patch.msgid.link/20240809072012.84152-5-pkshih@realtek.com Signed-off-by: Sasha Levin --- drivers/net/wireless/realtek/rtw89/phy.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/realtek/rtw89/phy.c b/drivers/net/wireless/realtek/rtw89/phy.c index c894a2b614eb..f6647f9d2393 100644 --- a/drivers/net/wireless/realtek/rtw89/phy.c +++ b/drivers/net/wireless/realtek/rtw89/phy.c @@ -281,8 +281,8 @@ static void rtw89_phy_ra_sta_update(struct rtw89_dev *rtwdev, csi_mode = RTW89_RA_RPT_MODE_HT; ra_mask |= ((u64)sta->deflink.ht_cap.mcs.rx_mask[3] << 48) | ((u64)sta->deflink.ht_cap.mcs.rx_mask[2] << 36) | - (sta->deflink.ht_cap.mcs.rx_mask[1] << 24) | - (sta->deflink.ht_cap.mcs.rx_mask[0] << 12); + ((u64)sta->deflink.ht_cap.mcs.rx_mask[1] << 24) | + ((u64)sta->deflink.ht_cap.mcs.rx_mask[0] << 12); high_rate_masks = rtw89_ra_mask_ht_rates; if (sta->deflink.ht_cap.cap & IEEE80211_HT_CAP_RX_STBC) stbc_en = 1; From 8cbda417274029f9a97ade71acc864075a4c07c4 Mon Sep 17 00:00:00 2001 From: Ido Schimmel Date: Wed, 14 Aug 2024 15:52:22 +0300 Subject: [PATCH 024/267] ipv4: Mask upper DSCP bits and ECN bits in NETLINK_FIB_LOOKUP family [ Upstream commit 8fed54758cd248cd311a2b5c1e180abef1866237 ] The NETLINK_FIB_LOOKUP netlink family can be used to perform a FIB lookup according to user provided parameters and communicate the result back to user space. However, unlike other users of the FIB lookup API, the upper DSCP bits and the ECN bits of the DS field are not masked, which can result in the wrong result being returned. Solve this by masking the upper DSCP bits and the ECN bits using IPTOS_RT_MASK. The structure that communicates the request and the response is not exported to user space, so it is unlikely that this netlink family is actually in use [1]. [1] https://lore.kernel.org/netdev/ZpqpB8vJU%2FQ6LSqa@debian/ Signed-off-by: Ido Schimmel Reviewed-by: Guillaume Nault Signed-off-by: Paolo Abeni Signed-off-by: Sasha Levin --- net/ipv4/fib_frontend.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/ipv4/fib_frontend.c b/net/ipv4/fib_frontend.c index 390f4be7f7be..90ce87ffed46 100644 --- a/net/ipv4/fib_frontend.c +++ b/net/ipv4/fib_frontend.c @@ -1343,7 +1343,7 @@ static void nl_fib_lookup(struct net *net, struct fib_result_nl *frn) struct flowi4 fl4 = { .flowi4_mark = frn->fl_mark, .daddr = frn->fl_addr, - .flowi4_tos = frn->fl_tos, + .flowi4_tos = frn->fl_tos & IPTOS_RT_MASK, .flowi4_scope = frn->fl_scope, }; struct fib_table *tb; From 2738388d9586a0a6d20258c8106783c5654d52c8 Mon Sep 17 00:00:00 2001 From: Simon Horman Date: Wed, 21 Aug 2024 16:58:57 +0100 Subject: [PATCH 025/267] net: atlantic: Avoid warning about potential string truncation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [ Upstream commit 5874e0c9f25661c2faefe4809907166defae3d7f ] W=1 builds with GCC 14.2.0 warn that: .../aq_ethtool.c:278:59: warning: ‘%d’ directive output may be truncated writing between 1 and 11 bytes into a region of size 6 [-Wformat-truncation=] 278 | snprintf(tc_string, 8, "TC%d ", tc); | ^~ .../aq_ethtool.c:278:56: note: directive argument in the range [-2147483641, 254] 278 | snprintf(tc_string, 8, "TC%d ", tc); | ^~~~~~~ .../aq_ethtool.c:278:33: note: ‘snprintf’ output between 5 and 15 bytes into a destination of size 8 278 | snprintf(tc_string, 8, "TC%d ", tc); | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ tc is always in the range 0 - cfg->tcs. And as cfg->tcs is a u8, the range is 0 - 255. Further, on inspecting the code, it seems that cfg->tcs will never be more than AQ_CFG_TCS_MAX (8), so the range is actually 0 - 8. So, it seems that the condition that GCC flags will not occur. But, nonetheless, it would be nice if it didn't emit the warning. It seems that this can be achieved by changing the format specifier from %d to %u, in which case I believe GCC recognises an upper bound on the range of tc of 0 - 255. After some experimentation I think this is due to the combination of the use of %u and the type of cfg->tcs (u8). Empirically, updating the type of the tc variable to unsigned int has the same effect. As both of these changes seem to make sense in relation to what the code is actually doing - iterating over unsigned values - do both. Compile tested only. Signed-off-by: Simon Horman Link: https://patch.msgid.link/20240821-atlantic-str-v1-1-fa2cfe38ca00@kernel.org Signed-off-by: Jakub Kicinski Signed-off-by: Sasha Levin --- drivers/net/ethernet/aquantia/atlantic/aq_ethtool.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_ethtool.c b/drivers/net/ethernet/aquantia/atlantic/aq_ethtool.c index ac4ea93bd8dd..eaef14ea5dd2 100644 --- a/drivers/net/ethernet/aquantia/atlantic/aq_ethtool.c +++ b/drivers/net/ethernet/aquantia/atlantic/aq_ethtool.c @@ -265,7 +265,7 @@ static void aq_ethtool_get_strings(struct net_device *ndev, const int rx_stat_cnt = ARRAY_SIZE(aq_ethtool_queue_rx_stat_names); const int tx_stat_cnt = ARRAY_SIZE(aq_ethtool_queue_tx_stat_names); char tc_string[8]; - int tc; + unsigned int tc; memset(tc_string, 0, sizeof(tc_string)); memcpy(p, aq_ethtool_stat_names, @@ -274,7 +274,7 @@ static void aq_ethtool_get_strings(struct net_device *ndev, for (tc = 0; tc < cfg->tcs; tc++) { if (cfg->is_qos) - snprintf(tc_string, 8, "TC%d ", tc); + snprintf(tc_string, 8, "TC%u ", tc); for (i = 0; i < cfg->vecs; i++) { for (si = 0; si < rx_stat_cnt; si++) { From a3dde0782166d2d8e80d70d7766bfdfa4c038996 Mon Sep 17 00:00:00 2001 From: Herbert Xu Date: Sat, 17 Aug 2024 14:58:35 +0800 Subject: [PATCH 026/267] crypto: simd - Do not call crypto_alloc_tfm during registration [ Upstream commit 3c44d31cb34ce4eb8311a2e73634d57702948230 ] Algorithm registration is usually carried out during module init, where as little work as possible should be carried out. The SIMD code violated this rule by allocating a tfm, this then triggers a full test of the algorithm which may dead-lock in certain cases. SIMD is only allocating the tfm to get at the alg object, which is in fact already available as it is what we are registering. Use that directly and remove the crypto_alloc_tfm call. Also remove some obsolete and unused SIMD API. Signed-off-by: Herbert Xu Signed-off-by: Sasha Levin --- arch/arm/crypto/aes-ce-glue.c | 2 +- arch/arm/crypto/aes-neonbs-glue.c | 2 +- crypto/simd.c | 76 ++++++------------------------- include/crypto/internal/simd.h | 12 +---- 4 files changed, 19 insertions(+), 73 deletions(-) diff --git a/arch/arm/crypto/aes-ce-glue.c b/arch/arm/crypto/aes-ce-glue.c index b668c97663ec..f5b66f4cf45d 100644 --- a/arch/arm/crypto/aes-ce-glue.c +++ b/arch/arm/crypto/aes-ce-glue.c @@ -711,7 +711,7 @@ static int __init aes_init(void) algname = aes_algs[i].base.cra_name + 2; drvname = aes_algs[i].base.cra_driver_name + 2; basename = aes_algs[i].base.cra_driver_name; - simd = simd_skcipher_create_compat(algname, drvname, basename); + simd = simd_skcipher_create_compat(aes_algs + i, algname, drvname, basename); err = PTR_ERR(simd); if (IS_ERR(simd)) goto unregister_simds; diff --git a/arch/arm/crypto/aes-neonbs-glue.c b/arch/arm/crypto/aes-neonbs-glue.c index f00f042ef357..0ca94b90bc4e 100644 --- a/arch/arm/crypto/aes-neonbs-glue.c +++ b/arch/arm/crypto/aes-neonbs-glue.c @@ -539,7 +539,7 @@ static int __init aes_init(void) algname = aes_algs[i].base.cra_name + 2; drvname = aes_algs[i].base.cra_driver_name + 2; basename = aes_algs[i].base.cra_driver_name; - simd = simd_skcipher_create_compat(algname, drvname, basename); + simd = simd_skcipher_create_compat(aes_algs + i, algname, drvname, basename); err = PTR_ERR(simd); if (IS_ERR(simd)) goto unregister_simds; diff --git a/crypto/simd.c b/crypto/simd.c index edaa479a1ec5..d109866641a2 100644 --- a/crypto/simd.c +++ b/crypto/simd.c @@ -136,27 +136,19 @@ static int simd_skcipher_init(struct crypto_skcipher *tfm) return 0; } -struct simd_skcipher_alg *simd_skcipher_create_compat(const char *algname, +struct simd_skcipher_alg *simd_skcipher_create_compat(struct skcipher_alg *ialg, + const char *algname, const char *drvname, const char *basename) { struct simd_skcipher_alg *salg; - struct crypto_skcipher *tfm; - struct skcipher_alg *ialg; struct skcipher_alg *alg; int err; - tfm = crypto_alloc_skcipher(basename, CRYPTO_ALG_INTERNAL, - CRYPTO_ALG_INTERNAL | CRYPTO_ALG_ASYNC); - if (IS_ERR(tfm)) - return ERR_CAST(tfm); - - ialg = crypto_skcipher_alg(tfm); - salg = kzalloc(sizeof(*salg), GFP_KERNEL); if (!salg) { salg = ERR_PTR(-ENOMEM); - goto out_put_tfm; + goto out; } salg->ialg_name = basename; @@ -195,30 +187,16 @@ struct simd_skcipher_alg *simd_skcipher_create_compat(const char *algname, if (err) goto out_free_salg; -out_put_tfm: - crypto_free_skcipher(tfm); +out: return salg; out_free_salg: kfree(salg); salg = ERR_PTR(err); - goto out_put_tfm; + goto out; } EXPORT_SYMBOL_GPL(simd_skcipher_create_compat); -struct simd_skcipher_alg *simd_skcipher_create(const char *algname, - const char *basename) -{ - char drvname[CRYPTO_MAX_ALG_NAME]; - - if (snprintf(drvname, CRYPTO_MAX_ALG_NAME, "simd-%s", basename) >= - CRYPTO_MAX_ALG_NAME) - return ERR_PTR(-ENAMETOOLONG); - - return simd_skcipher_create_compat(algname, drvname, basename); -} -EXPORT_SYMBOL_GPL(simd_skcipher_create); - void simd_skcipher_free(struct simd_skcipher_alg *salg) { crypto_unregister_skcipher(&salg->alg); @@ -246,7 +224,7 @@ int simd_register_skciphers_compat(struct skcipher_alg *algs, int count, algname = algs[i].base.cra_name + 2; drvname = algs[i].base.cra_driver_name + 2; basename = algs[i].base.cra_driver_name; - simd = simd_skcipher_create_compat(algname, drvname, basename); + simd = simd_skcipher_create_compat(algs + i, algname, drvname, basename); err = PTR_ERR(simd); if (IS_ERR(simd)) goto err_unregister; @@ -383,27 +361,19 @@ static int simd_aead_init(struct crypto_aead *tfm) return 0; } -struct simd_aead_alg *simd_aead_create_compat(const char *algname, - const char *drvname, - const char *basename) +static struct simd_aead_alg *simd_aead_create_compat(struct aead_alg *ialg, + const char *algname, + const char *drvname, + const char *basename) { struct simd_aead_alg *salg; - struct crypto_aead *tfm; - struct aead_alg *ialg; struct aead_alg *alg; int err; - tfm = crypto_alloc_aead(basename, CRYPTO_ALG_INTERNAL, - CRYPTO_ALG_INTERNAL | CRYPTO_ALG_ASYNC); - if (IS_ERR(tfm)) - return ERR_CAST(tfm); - - ialg = crypto_aead_alg(tfm); - salg = kzalloc(sizeof(*salg), GFP_KERNEL); if (!salg) { salg = ERR_PTR(-ENOMEM); - goto out_put_tfm; + goto out; } salg->ialg_name = basename; @@ -442,36 +412,20 @@ struct simd_aead_alg *simd_aead_create_compat(const char *algname, if (err) goto out_free_salg; -out_put_tfm: - crypto_free_aead(tfm); +out: return salg; out_free_salg: kfree(salg); salg = ERR_PTR(err); - goto out_put_tfm; + goto out; } -EXPORT_SYMBOL_GPL(simd_aead_create_compat); -struct simd_aead_alg *simd_aead_create(const char *algname, - const char *basename) -{ - char drvname[CRYPTO_MAX_ALG_NAME]; - - if (snprintf(drvname, CRYPTO_MAX_ALG_NAME, "simd-%s", basename) >= - CRYPTO_MAX_ALG_NAME) - return ERR_PTR(-ENAMETOOLONG); - - return simd_aead_create_compat(algname, drvname, basename); -} -EXPORT_SYMBOL_GPL(simd_aead_create); - -void simd_aead_free(struct simd_aead_alg *salg) +static void simd_aead_free(struct simd_aead_alg *salg) { crypto_unregister_aead(&salg->alg); kfree(salg); } -EXPORT_SYMBOL_GPL(simd_aead_free); int simd_register_aeads_compat(struct aead_alg *algs, int count, struct simd_aead_alg **simd_algs) @@ -493,7 +447,7 @@ int simd_register_aeads_compat(struct aead_alg *algs, int count, algname = algs[i].base.cra_name + 2; drvname = algs[i].base.cra_driver_name + 2; basename = algs[i].base.cra_driver_name; - simd = simd_aead_create_compat(algname, drvname, basename); + simd = simd_aead_create_compat(algs + i, algname, drvname, basename); err = PTR_ERR(simd); if (IS_ERR(simd)) goto err_unregister; diff --git a/include/crypto/internal/simd.h b/include/crypto/internal/simd.h index d2316242a988..be97b97a75dd 100644 --- a/include/crypto/internal/simd.h +++ b/include/crypto/internal/simd.h @@ -14,11 +14,10 @@ struct simd_skcipher_alg; struct skcipher_alg; -struct simd_skcipher_alg *simd_skcipher_create_compat(const char *algname, +struct simd_skcipher_alg *simd_skcipher_create_compat(struct skcipher_alg *ialg, + const char *algname, const char *drvname, const char *basename); -struct simd_skcipher_alg *simd_skcipher_create(const char *algname, - const char *basename); void simd_skcipher_free(struct simd_skcipher_alg *alg); int simd_register_skciphers_compat(struct skcipher_alg *algs, int count, @@ -32,13 +31,6 @@ void simd_unregister_skciphers(struct skcipher_alg *algs, int count, struct simd_aead_alg; struct aead_alg; -struct simd_aead_alg *simd_aead_create_compat(const char *algname, - const char *drvname, - const char *basename); -struct simd_aead_alg *simd_aead_create(const char *algname, - const char *basename); -void simd_aead_free(struct simd_aead_alg *alg); - int simd_register_aeads_compat(struct aead_alg *algs, int count, struct simd_aead_alg **simd_algs); From 465d3bad19c451f70d3516f3807183f0ad00f7f8 Mon Sep 17 00:00:00 2001 From: Jason Xing Date: Fri, 23 Aug 2024 08:11:52 +0800 Subject: [PATCH 027/267] tcp: avoid reusing FIN_WAIT2 when trying to find port in connect() process [ Upstream commit 0d9e5df4a257afc3a471a82961ace9a22b88295a ] We found that one close-wait socket was reset by the other side due to a new connection reusing the same port which is beyond our expectation, so we have to investigate the underlying reason. The following experiment is conducted in the test environment. We limit the port range from 40000 to 40010 and delay the time to close() after receiving a fin from the active close side, which can help us easily reproduce like what happened in production. Here are three connections captured by tcpdump: 127.0.0.1.40002 > 127.0.0.1.9999: Flags [S], seq 2965525191 127.0.0.1.9999 > 127.0.0.1.40002: Flags [S.], seq 2769915070 127.0.0.1.40002 > 127.0.0.1.9999: Flags [.], ack 1 127.0.0.1.40002 > 127.0.0.1.9999: Flags [F.], seq 1, ack 1 // a few seconds later, within 60 seconds 127.0.0.1.40002 > 127.0.0.1.9999: Flags [S], seq 2965590730 127.0.0.1.9999 > 127.0.0.1.40002: Flags [.], ack 2 127.0.0.1.40002 > 127.0.0.1.9999: Flags [R], seq 2965525193 // later, very quickly 127.0.0.1.40002 > 127.0.0.1.9999: Flags [S], seq 2965590730 127.0.0.1.9999 > 127.0.0.1.40002: Flags [S.], seq 3120990805 127.0.0.1.40002 > 127.0.0.1.9999: Flags [.], ack 1 As we can see, the first flow is reset because: 1) client starts a new connection, I mean, the second one 2) client tries to find a suitable port which is a timewait socket (its state is timewait, substate is fin_wait2) 3) client occupies that timewait port to send a SYN 4) server finds a corresponding close-wait socket in ehash table, then replies with a challenge ack 5) client sends an RST to terminate this old close-wait socket. I don't think the port selection algo can choose a FIN_WAIT2 socket when we turn on tcp_tw_reuse because on the server side there remain unread data. In some cases, if one side haven't call close() yet, we should not consider it as expendable and treat it at will. Even though, sometimes, the server isn't able to call close() as soon as possible like what we expect, it can not be terminated easily, especially due to a second unrelated connection happening. After this patch, we can see the expected failure if we start a connection when all the ports are occupied in fin_wait2 state: "Ncat: Cannot assign requested address." Reported-by: Jade Dong Signed-off-by: Jason Xing Reviewed-by: Eric Dumazet Link: https://patch.msgid.link/20240823001152.31004-1-kerneljasonxing@gmail.com Signed-off-by: Jakub Kicinski Signed-off-by: Sasha Levin --- net/ipv4/tcp_ipv4.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c index 1327447a3aad..984435cb1013 100644 --- a/net/ipv4/tcp_ipv4.c +++ b/net/ipv4/tcp_ipv4.c @@ -115,6 +115,9 @@ int tcp_twsk_unique(struct sock *sk, struct sock *sktw, void *twp) const struct tcp_timewait_sock *tcptw = tcp_twsk(sktw); struct tcp_sock *tp = tcp_sk(sk); + if (tw->tw_substate == TCP_FIN_WAIT2) + reuse = 0; + if (reuse == 2) { /* Still does not detect *everything* that goes through * lo, since we require a loopback src or dst address From b0b2dc1eaa7ec509e07a78c9974097168ae565b7 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Tue, 27 Aug 2024 09:49:40 +0200 Subject: [PATCH 028/267] wifi: mac80211: fix RCU list iterations [ Upstream commit ac35180032fbc5d80b29af00ba4881815ceefcb6 ] There are a number of places where RCU list iteration is used, but that aren't (always) called with RCU held. Use just list_for_each_entry() in most, and annotate iface iteration with the required locks. Reviewed-by: Miriam Rachel Korenblit Link: https://patch.msgid.link/20240827094939.ed8ac0b2f897.I8443c9c3c0f8051841353491dae758021b53115e@changeid Signed-off-by: Johannes Berg Signed-off-by: Sasha Levin --- net/mac80211/chan.c | 4 +++- net/mac80211/mlme.c | 2 +- net/mac80211/scan.c | 2 +- net/mac80211/util.c | 4 +++- 4 files changed, 8 insertions(+), 4 deletions(-) diff --git a/net/mac80211/chan.c b/net/mac80211/chan.c index f07e34bed8f3..807bea1a7d3c 100644 --- a/net/mac80211/chan.c +++ b/net/mac80211/chan.c @@ -245,7 +245,9 @@ ieee80211_get_max_required_bw(struct ieee80211_sub_if_data *sdata, enum nl80211_chan_width max_bw = NL80211_CHAN_WIDTH_20_NOHT; struct sta_info *sta; - list_for_each_entry_rcu(sta, &sdata->local->sta_list, list) { + lockdep_assert_wiphy(sdata->local->hw.wiphy); + + list_for_each_entry(sta, &sdata->local->sta_list, list) { if (sdata != sta->sdata && !(sta->sdata->bss && sta->sdata->bss == sdata->bss)) continue; diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index 9a5530ca2f6b..ee9ec74b9553 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c @@ -660,7 +660,7 @@ static bool ieee80211_add_vht_ie(struct ieee80211_sub_if_data *sdata, bool disable_mu_mimo = false; struct ieee80211_sub_if_data *other; - list_for_each_entry_rcu(other, &local->interfaces, list) { + list_for_each_entry(other, &local->interfaces, list) { if (other->vif.bss_conf.mu_mimo_owner) { disable_mu_mimo = true; break; diff --git a/net/mac80211/scan.c b/net/mac80211/scan.c index 6432dd3ec2a7..0a6e40bd42f6 100644 --- a/net/mac80211/scan.c +++ b/net/mac80211/scan.c @@ -500,7 +500,7 @@ static void __ieee80211_scan_completed(struct ieee80211_hw *hw, bool aborted) * the scan was in progress; if there was none this will * just be a no-op for the particular interface. */ - list_for_each_entry_rcu(sdata, &local->interfaces, list) { + list_for_each_entry(sdata, &local->interfaces, list) { if (ieee80211_sdata_running(sdata)) ieee80211_queue_work(&sdata->local->hw, &sdata->work); } diff --git a/net/mac80211/util.c b/net/mac80211/util.c index 738f1f139a90..3fe15089b24f 100644 --- a/net/mac80211/util.c +++ b/net/mac80211/util.c @@ -767,7 +767,9 @@ static void __iterate_interfaces(struct ieee80211_local *local, struct ieee80211_sub_if_data *sdata; bool active_only = iter_flags & IEEE80211_IFACE_ITER_ACTIVE; - list_for_each_entry_rcu(sdata, &local->interfaces, list) { + list_for_each_entry_rcu(sdata, &local->interfaces, list, + lockdep_is_held(&local->iflist_mtx) || + lockdep_is_held(&local->hw.wiphy->mtx)) { switch (sdata->vif.type) { case NL80211_IFTYPE_MONITOR: if (!(sdata->u.mntr.flags & MONITOR_FLAG_ACTIVE)) From 7f570d6729a2bd094a79020d2a668d85f1edee58 Mon Sep 17 00:00:00 2001 From: Aleksandrs Vinarskis Date: Sun, 11 Aug 2024 23:33:44 +0200 Subject: [PATCH 029/267] ACPICA: iasl: handle empty connection_node [ Upstream commit a0a2459b79414584af6c46dd8c6f866d8f1aa421 ] ACPICA commit 6c551e2c9487067d4b085333e7fe97e965a11625 Link: https://github.com/acpica/acpica/commit/6c551e2c Signed-off-by: Aleksandrs Vinarskis Signed-off-by: Rafael J. Wysocki Signed-off-by: Sasha Levin --- drivers/acpi/acpica/exprep.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/acpi/acpica/exprep.c b/drivers/acpi/acpica/exprep.c index 08f06797386a..4daef7530d91 100644 --- a/drivers/acpi/acpica/exprep.c +++ b/drivers/acpi/acpica/exprep.c @@ -437,6 +437,9 @@ acpi_status acpi_ex_prep_field_value(struct acpi_create_field_info *info) if (info->connection_node) { second_desc = info->connection_node->object; + if (second_desc == NULL) { + break; + } if (!(second_desc->common.flags & AOPOBJ_DATA_VALID)) { status = acpi_ds_get_buffer_arguments(second_desc); From ca5ef2759daa86981dbdbee31f4802e82b459b29 Mon Sep 17 00:00:00 2001 From: Adrian Ratiu Date: Fri, 2 Aug 2024 11:02:25 +0300 Subject: [PATCH 030/267] proc: add config & param to block forcing mem writes [ Upstream commit 41e8149c8892ed1962bd15350b3c3e6e90cba7f4 ] This adds a Kconfig option and boot param to allow removing the FOLL_FORCE flag from /proc/pid/mem write calls because it can be abused. The traditional forcing behavior is kept as default because it can break GDB and some other use cases. Previously we tried a more sophisticated approach allowing distributions to fine-tune /proc/pid/mem behavior, however that got NAK-ed by Linus [1], who prefers this simpler approach with semantics also easier to understand for users. Link: https://lore.kernel.org/lkml/CAHk-=wiGWLChxYmUA5HrT5aopZrB7_2VTa0NLZcxORgkUe5tEQ@mail.gmail.com/ [1] Cc: Doug Anderson Cc: Jeff Xu Cc: Jann Horn Cc: Kees Cook Cc: Ard Biesheuvel Cc: Christian Brauner Suggested-by: Linus Torvalds Signed-off-by: Linus Torvalds Signed-off-by: Adrian Ratiu Link: https://lore.kernel.org/r/20240802080225.89408-1-adrian.ratiu@collabora.com Signed-off-by: Christian Brauner Signed-off-by: Sasha Levin --- .../admin-guide/kernel-parameters.txt | 10 +++ fs/proc/base.c | 61 ++++++++++++++++++- security/Kconfig | 32 ++++++++++ 3 files changed, 102 insertions(+), 1 deletion(-) diff --git a/Documentation/admin-guide/kernel-parameters.txt b/Documentation/admin-guide/kernel-parameters.txt index 8df4c1c5c619..18c8fc60db93 100644 --- a/Documentation/admin-guide/kernel-parameters.txt +++ b/Documentation/admin-guide/kernel-parameters.txt @@ -4540,6 +4540,16 @@ printk.time= Show timing data prefixed to each printk message line Format: (1/Y/y=enable, 0/N/n=disable) + proc_mem.force_override= [KNL] + Format: {always | ptrace | never} + Traditionally /proc/pid/mem allows memory permissions to be + overridden without restrictions. This option may be set to + restrict that. Can be one of: + - 'always': traditional behavior always allows mem overrides. + - 'ptrace': only allow mem overrides for active ptracers. + - 'never': never allow mem overrides. + If not specified, default is the CONFIG_PROC_MEM_* choice. + processor.max_cstate= [HW,ACPI] Limit processor to maximum C-state max_cstate=9 overrides any DMI blacklist limit. diff --git a/fs/proc/base.c b/fs/proc/base.c index 74442e01793f..ecc45389ea79 100644 --- a/fs/proc/base.c +++ b/fs/proc/base.c @@ -85,6 +85,7 @@ #include #include #include +#include #include #include #include @@ -115,6 +116,40 @@ static u8 nlink_tid __ro_after_init; static u8 nlink_tgid __ro_after_init; +enum proc_mem_force { + PROC_MEM_FORCE_ALWAYS, + PROC_MEM_FORCE_PTRACE, + PROC_MEM_FORCE_NEVER +}; + +static enum proc_mem_force proc_mem_force_override __ro_after_init = + IS_ENABLED(CONFIG_PROC_MEM_NO_FORCE) ? PROC_MEM_FORCE_NEVER : + IS_ENABLED(CONFIG_PROC_MEM_FORCE_PTRACE) ? PROC_MEM_FORCE_PTRACE : + PROC_MEM_FORCE_ALWAYS; + +static const struct constant_table proc_mem_force_table[] __initconst = { + { "always", PROC_MEM_FORCE_ALWAYS }, + { "ptrace", PROC_MEM_FORCE_PTRACE }, + { "never", PROC_MEM_FORCE_NEVER }, + { } +}; + +static int __init early_proc_mem_force_override(char *buf) +{ + if (!buf) + return -EINVAL; + + /* + * lookup_constant() defaults to proc_mem_force_override to preseve + * the initial Kconfig choice in case an invalid param gets passed. + */ + proc_mem_force_override = lookup_constant(proc_mem_force_table, + buf, proc_mem_force_override); + + return 0; +} +early_param("proc_mem.force_override", early_proc_mem_force_override); + struct pid_entry { const char *name; unsigned int len; @@ -834,6 +869,28 @@ static int mem_open(struct inode *inode, struct file *file) return ret; } +static bool proc_mem_foll_force(struct file *file, struct mm_struct *mm) +{ + struct task_struct *task; + bool ptrace_active = false; + + switch (proc_mem_force_override) { + case PROC_MEM_FORCE_NEVER: + return false; + case PROC_MEM_FORCE_PTRACE: + task = get_proc_task(file_inode(file)); + if (task) { + ptrace_active = READ_ONCE(task->ptrace) && + READ_ONCE(task->mm) == mm && + READ_ONCE(task->parent) == current; + put_task_struct(task); + } + return ptrace_active; + default: + return true; + } +} + static ssize_t mem_rw(struct file *file, char __user *buf, size_t count, loff_t *ppos, int write) { @@ -854,7 +911,9 @@ static ssize_t mem_rw(struct file *file, char __user *buf, if (!mmget_not_zero(mm)) goto free; - flags = FOLL_FORCE | (write ? FOLL_WRITE : 0); + flags = write ? FOLL_WRITE : 0; + if (proc_mem_foll_force(file, mm)) + flags |= FOLL_FORCE; while (count > 0) { size_t this_len = min_t(size_t, count, PAGE_SIZE); diff --git a/security/Kconfig b/security/Kconfig index e6db09a779b7..8cd544714ed2 100644 --- a/security/Kconfig +++ b/security/Kconfig @@ -19,6 +19,38 @@ config SECURITY_DMESG_RESTRICT If you are unsure how to answer this question, answer N. +choice + prompt "Allow /proc/pid/mem access override" + default PROC_MEM_ALWAYS_FORCE + help + Traditionally /proc/pid/mem allows users to override memory + permissions for users like ptrace, assuming they have ptrace + capability. + + This allows people to limit that - either never override, or + require actual active ptrace attachment. + + Defaults to the traditional behavior (for now) + +config PROC_MEM_ALWAYS_FORCE + bool "Traditional /proc/pid/mem behavior" + help + This allows /proc/pid/mem accesses to override memory mapping + permissions if you have ptrace access rights. + +config PROC_MEM_FORCE_PTRACE + bool "Require active ptrace() use for access override" + help + This allows /proc/pid/mem accesses to override memory mapping + permissions for active ptracers like gdb. + +config PROC_MEM_NO_FORCE + bool "Never" + help + Never override memory mapping permissions + +endchoice + config SECURITY bool "Enable different security models" depends on SYSFS From 0f78947e4d39930dd59da4ddeba928b3ce1b4b76 Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Tue, 27 Aug 2024 11:30:04 +0200 Subject: [PATCH 031/267] wifi: mt76: mt7915: hold dev->mt76.mutex while disabling tx worker [ Upstream commit 8f7152f10cb434f954aeff85ca1be9cd4d01912b ] Prevent racing against other functions disabling the same worker Link: https://patch.msgid.link/20240827093011.18621-17-nbd@nbd.name Signed-off-by: Felix Fietkau Signed-off-by: Sasha Levin --- drivers/net/wireless/mediatek/mt76/mt7915/mac.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/mac.c b/drivers/net/wireless/mediatek/mt76/mt7915/mac.c index 1f3b7e7f48d5..36c4bfb7776b 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7915/mac.c +++ b/drivers/net/wireless/mediatek/mt76/mt7915/mac.c @@ -1409,12 +1409,14 @@ void mt7915_mac_reset_work(struct work_struct *work) set_bit(MT76_RESET, &phy2->mt76->state); cancel_delayed_work_sync(&phy2->mt76->mac_work); } + + mutex_lock(&dev->mt76.mutex); + mt76_worker_disable(&dev->mt76.tx_worker); mt76_for_each_q_rx(&dev->mt76, i) napi_disable(&dev->mt76.napi[i]); napi_disable(&dev->mt76.tx_napi); - mutex_lock(&dev->mt76.mutex); mt76_wr(dev, MT_MCU_INT_EVENT, MT_MCU_INT_EVENT_DMA_STOPPED); From 17199b69a84798efffc475040fbef44374ef1de1 Mon Sep 17 00:00:00 2001 From: "Gustavo A. R. Silva" Date: Wed, 21 Aug 2024 15:23:51 -0600 Subject: [PATCH 032/267] wifi: mwifiex: Fix memcpy() field-spanning write warning in mwifiex_cmd_802_11_scan_ext() [ Upstream commit 498365e52bebcbc36a93279fe7e9d6aec8479cee ] Replace one-element array with a flexible-array member in `struct host_cmd_ds_802_11_scan_ext`. With this, fix the following warning: elo 16 17:51:58 surfacebook kernel: ------------[ cut here ]------------ elo 16 17:51:58 surfacebook kernel: memcpy: detected field-spanning write (size 243) of single field "ext_scan->tlv_buffer" at drivers/net/wireless/marvell/mwifiex/scan.c:2239 (size 1) elo 16 17:51:58 surfacebook kernel: WARNING: CPU: 0 PID: 498 at drivers/net/wireless/marvell/mwifiex/scan.c:2239 mwifiex_cmd_802_11_scan_ext+0x83/0x90 [mwifiex] Reported-by: Andy Shevchenko Closes: https://lore.kernel.org/linux-hardening/ZsZNgfnEwOcPdCly@black.fi.intel.com/ Signed-off-by: Gustavo A. R. Silva Reviewed-by: Andy Shevchenko Acked-by: Brian Norris Signed-off-by: Kalle Valo Link: https://patch.msgid.link/ZsZa5xRcsLq9D+RX@elsanto Signed-off-by: Sasha Levin --- drivers/net/wireless/marvell/mwifiex/fw.h | 2 +- drivers/net/wireless/marvell/mwifiex/scan.c | 3 +-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/drivers/net/wireless/marvell/mwifiex/fw.h b/drivers/net/wireless/marvell/mwifiex/fw.h index 863f5f2247a0..26979013ca52 100644 --- a/drivers/net/wireless/marvell/mwifiex/fw.h +++ b/drivers/net/wireless/marvell/mwifiex/fw.h @@ -1586,7 +1586,7 @@ struct host_cmd_ds_802_11_scan_rsp { struct host_cmd_ds_802_11_scan_ext { u32 reserved; - u8 tlv_buffer[1]; + u8 tlv_buffer[]; } __packed; struct mwifiex_ie_types_bss_mode { diff --git a/drivers/net/wireless/marvell/mwifiex/scan.c b/drivers/net/wireless/marvell/mwifiex/scan.c index 644b1e134b01..eadb903f07b9 100644 --- a/drivers/net/wireless/marvell/mwifiex/scan.c +++ b/drivers/net/wireless/marvell/mwifiex/scan.c @@ -2548,8 +2548,7 @@ int mwifiex_ret_802_11_scan_ext(struct mwifiex_private *priv, ext_scan_resp = &resp->params.ext_scan; tlv = (void *)ext_scan_resp->tlv_buffer; - buf_left = le16_to_cpu(resp->size) - (sizeof(*ext_scan_resp) + S_DS_GEN - - 1); + buf_left = le16_to_cpu(resp->size) - (sizeof(*ext_scan_resp) + S_DS_GEN); while (buf_left >= sizeof(struct mwifiex_ie_types_header)) { type = le16_to_cpu(tlv->type); From 99fcb55180743dbbe27d26c58d60c16dbc718038 Mon Sep 17 00:00:00 2001 From: Jinjie Ruan Date: Wed, 11 Sep 2024 17:44:45 +0800 Subject: [PATCH 033/267] nfp: Use IRQF_NO_AUTOEN flag in request_irq() [ Upstream commit daaba19d357f0900b303a530ced96c78086267ea ] disable_irq() after request_irq() still has a time gap in which interrupts can come. request_irq() with IRQF_NO_AUTOEN flag will disable IRQ auto-enable when request IRQ. Reviewed-by: Louis Peens Signed-off-by: Jinjie Ruan Link: https://patch.msgid.link/20240911094445.1922476-4-ruanjinjie@huawei.com Signed-off-by: Jakub Kicinski Signed-off-by: Sasha Levin --- drivers/net/ethernet/netronome/nfp/nfp_net_common.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/drivers/net/ethernet/netronome/nfp/nfp_net_common.c b/drivers/net/ethernet/netronome/nfp/nfp_net_common.c index 27f4786ace4f..4fbf2d6129ff 100644 --- a/drivers/net/ethernet/netronome/nfp/nfp_net_common.c +++ b/drivers/net/ethernet/netronome/nfp/nfp_net_common.c @@ -818,14 +818,13 @@ nfp_net_prepare_vector(struct nfp_net *nn, struct nfp_net_r_vector *r_vec, snprintf(r_vec->name, sizeof(r_vec->name), "%s-rxtx-%d", nfp_net_name(nn), idx); - err = request_irq(r_vec->irq_vector, r_vec->handler, 0, r_vec->name, - r_vec); + err = request_irq(r_vec->irq_vector, r_vec->handler, IRQF_NO_AUTOEN, + r_vec->name, r_vec); if (err) { nfp_net_napi_del(&nn->dp, r_vec); nn_err(nn, "Error requesting IRQ %d\n", r_vec->irq_vector); return err; } - disable_irq(r_vec->irq_vector); irq_set_affinity_hint(r_vec->irq_vector, &r_vec->affinity_mask); From 95b901dc34cf04c634e053d401d7ea8d314e738b Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 6 Aug 2024 14:46:50 +0200 Subject: [PATCH 034/267] ALSA: usb-audio: Add input value sanity checks for standard types [ Upstream commit 901e85677ec0bb9a69fb9eab1feafe0c4eb7d07e ] For an invalid input value that is out of the given range, currently USB-audio driver corrects the value silently and accepts without errors. This is no wrong behavior, per se, but the recent kselftest rather wants to have an error in such a case, hence a different behavior is expected now. This patch adds a sanity check at each control put for the standard mixer types and returns an error if an invalid value is given. Note that this covers only the standard mixer types. The mixer quirks that have own control callbacks would need different coverage. Link: https://patch.msgid.link/20240806124651.28203-1-tiwai@suse.de Signed-off-by: Takashi Iwai Signed-off-by: Sasha Levin --- sound/usb/mixer.c | 35 +++++++++++++++++++++++++++-------- sound/usb/mixer.h | 1 + 2 files changed, 28 insertions(+), 8 deletions(-) diff --git a/sound/usb/mixer.c b/sound/usb/mixer.c index 34ded71cb807..49facdf35b15 100644 --- a/sound/usb/mixer.c +++ b/sound/usb/mixer.c @@ -1377,6 +1377,19 @@ no_res_check: #define get_min_max(cval, def) get_min_max_with_quirks(cval, def, NULL) +/* get the max value advertised via control API */ +static int get_max_exposed(struct usb_mixer_elem_info *cval) +{ + if (!cval->max_exposed) { + if (cval->res) + cval->max_exposed = + DIV_ROUND_UP(cval->max - cval->min, cval->res); + else + cval->max_exposed = cval->max - cval->min; + } + return cval->max_exposed; +} + /* get a feature/mixer unit info */ static int mixer_ctl_feature_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) @@ -1389,11 +1402,8 @@ static int mixer_ctl_feature_info(struct snd_kcontrol *kcontrol, else uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; uinfo->count = cval->channels; - if (cval->val_type == USB_MIXER_BOOLEAN || - cval->val_type == USB_MIXER_INV_BOOLEAN) { - uinfo->value.integer.min = 0; - uinfo->value.integer.max = 1; - } else { + if (cval->val_type != USB_MIXER_BOOLEAN && + cval->val_type != USB_MIXER_INV_BOOLEAN) { if (!cval->initialized) { get_min_max_with_quirks(cval, 0, kcontrol); if (cval->initialized && cval->dBmin >= cval->dBmax) { @@ -1405,10 +1415,10 @@ static int mixer_ctl_feature_info(struct snd_kcontrol *kcontrol, &kcontrol->id); } } - uinfo->value.integer.min = 0; - uinfo->value.integer.max = - DIV_ROUND_UP(cval->max - cval->min, cval->res); } + + uinfo->value.integer.min = 0; + uinfo->value.integer.max = get_max_exposed(cval); return 0; } @@ -1449,6 +1459,7 @@ static int mixer_ctl_feature_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { struct usb_mixer_elem_info *cval = kcontrol->private_data; + int max_val = get_max_exposed(cval); int c, cnt, val, oval, err; int changed = 0; @@ -1461,6 +1472,8 @@ static int mixer_ctl_feature_put(struct snd_kcontrol *kcontrol, if (err < 0) return filter_error(cval, err); val = ucontrol->value.integer.value[cnt]; + if (val < 0 || val > max_val) + return -EINVAL; val = get_abs_value(cval, val); if (oval != val) { snd_usb_set_cur_mix_value(cval, c + 1, cnt, val); @@ -1474,6 +1487,8 @@ static int mixer_ctl_feature_put(struct snd_kcontrol *kcontrol, if (err < 0) return filter_error(cval, err); val = ucontrol->value.integer.value[0]; + if (val < 0 || val > max_val) + return -EINVAL; val = get_abs_value(cval, val); if (val != oval) { snd_usb_set_cur_mix_value(cval, 0, 0, val); @@ -2339,6 +2354,8 @@ static int mixer_ctl_procunit_put(struct snd_kcontrol *kcontrol, if (err < 0) return filter_error(cval, err); val = ucontrol->value.integer.value[0]; + if (val < 0 || val > get_max_exposed(cval)) + return -EINVAL; val = get_abs_value(cval, val); if (val != oval) { set_cur_ctl_value(cval, cval->control << 8, val); @@ -2701,6 +2718,8 @@ static int mixer_ctl_selector_put(struct snd_kcontrol *kcontrol, if (err < 0) return filter_error(cval, err); val = ucontrol->value.enumerated.item[0]; + if (val < 0 || val >= cval->max) /* here cval->max = # elements */ + return -EINVAL; val = get_abs_value(cval, val); if (val != oval) { set_cur_ctl_value(cval, cval->control << 8, val); diff --git a/sound/usb/mixer.h b/sound/usb/mixer.h index d43895c1ae5c..167fbfcf01ac 100644 --- a/sound/usb/mixer.h +++ b/sound/usb/mixer.h @@ -88,6 +88,7 @@ struct usb_mixer_elem_info { int channels; int val_type; int min, max, res; + int max_exposed; /* control API exposes the value in 0..max_exposed */ int dBmin, dBmax; int cached; int cache_val[MAX_CHANNELS]; From ec862cd843faa6f0e84a7a07362f2786446bf697 Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Fri, 2 Aug 2024 18:15:34 +0200 Subject: [PATCH 035/267] x86/ioapic: Handle allocation failures gracefully [ Upstream commit 830802a0fea8fb39d3dc9fb7d6b5581e1343eb1f ] Breno observed panics when using failslab under certain conditions during runtime: can not alloc irq_pin_list (-1,0,20) Kernel panic - not syncing: IO-APIC: failed to add irq-pin. Can not proceed panic+0x4e9/0x590 mp_irqdomain_alloc+0x9ab/0xa80 irq_domain_alloc_irqs_locked+0x25d/0x8d0 __irq_domain_alloc_irqs+0x80/0x110 mp_map_pin_to_irq+0x645/0x890 acpi_register_gsi_ioapic+0xe6/0x150 hpet_open+0x313/0x480 That's a pointless panic which is a leftover of the historic IO/APIC code which panic'ed during early boot when the interrupt allocation failed. The only place which might justify panic is the PIT/HPET timer_check() code which tries to figure out whether the timer interrupt is delivered through the IO/APIC. But that code does not require to handle interrupt allocation failures. If the interrupt cannot be allocated then timer delivery fails and it either panics due to that or falls back to legacy mode. Cure this by removing the panic wrapper around __add_pin_to_irq_node() and making mp_irqdomain_alloc() aware of the failure condition and handle it as any other failure in this function gracefully. Reported-by: Breno Leitao Signed-off-by: Thomas Gleixner Tested-by: Breno Leitao Tested-by: Qiuxu Zhuo Link: https://lore.kernel.org/all/ZqfJmUF8sXIyuSHN@gmail.com Link: https://lore.kernel.org/all/20240802155440.275200843@linutronix.de Signed-off-by: Sasha Levin --- arch/x86/kernel/apic/io_apic.c | 46 ++++++++++++++++------------------ 1 file changed, 22 insertions(+), 24 deletions(-) diff --git a/arch/x86/kernel/apic/io_apic.c b/arch/x86/kernel/apic/io_apic.c index efa87b6bb1cd..5e606477960c 100644 --- a/arch/x86/kernel/apic/io_apic.c +++ b/arch/x86/kernel/apic/io_apic.c @@ -351,27 +351,26 @@ static void ioapic_mask_entry(int apic, int pin) * shared ISA-space IRQs, so we have to support them. We are super * fast in the common case, and fast for shared ISA-space IRQs. */ -static int __add_pin_to_irq_node(struct mp_chip_data *data, - int node, int apic, int pin) +static bool add_pin_to_irq_node(struct mp_chip_data *data, int node, int apic, int pin) { struct irq_pin_list *entry; - /* don't allow duplicates */ - for_each_irq_pin(entry, data->irq_2_pin) + /* Don't allow duplicates */ + for_each_irq_pin(entry, data->irq_2_pin) { if (entry->apic == apic && entry->pin == pin) - return 0; + return true; + } entry = kzalloc_node(sizeof(struct irq_pin_list), GFP_ATOMIC, node); if (!entry) { - pr_err("can not alloc irq_pin_list (%d,%d,%d)\n", - node, apic, pin); - return -ENOMEM; + pr_err("Cannot allocate irq_pin_list (%d,%d,%d)\n", node, apic, pin); + return false; } + entry->apic = apic; entry->pin = pin; list_add_tail(&entry->list, &data->irq_2_pin); - - return 0; + return true; } static void __remove_pin_from_irq(struct mp_chip_data *data, int apic, int pin) @@ -386,13 +385,6 @@ static void __remove_pin_from_irq(struct mp_chip_data *data, int apic, int pin) } } -static void add_pin_to_irq_node(struct mp_chip_data *data, - int node, int apic, int pin) -{ - if (__add_pin_to_irq_node(data, node, apic, pin)) - panic("IO-APIC: failed to add irq-pin. Can not proceed\n"); -} - /* * Reroute an IRQ to a different pin. */ @@ -1001,8 +993,7 @@ static int alloc_isa_irq_from_domain(struct irq_domain *domain, if (irq_data && irq_data->parent_data) { if (!mp_check_pin_attr(irq, info)) return -EBUSY; - if (__add_pin_to_irq_node(irq_data->chip_data, node, ioapic, - info->ioapic.pin)) + if (!add_pin_to_irq_node(irq_data->chip_data, node, ioapic, info->ioapic.pin)) return -ENOMEM; } else { info->flags |= X86_IRQ_ALLOC_LEGACY; @@ -3038,10 +3029,8 @@ int mp_irqdomain_alloc(struct irq_domain *domain, unsigned int virq, return -ENOMEM; ret = irq_domain_alloc_irqs_parent(domain, virq, nr_irqs, info); - if (ret < 0) { - kfree(data); - return ret; - } + if (ret < 0) + goto free_data; INIT_LIST_HEAD(&data->irq_2_pin); irq_data->hwirq = info->ioapic.pin; @@ -3050,7 +3039,10 @@ int mp_irqdomain_alloc(struct irq_domain *domain, unsigned int virq, irq_data->chip_data = data; mp_irqdomain_get_attr(mp_pin_to_gsi(ioapic, pin), data, info); - add_pin_to_irq_node(data, ioapic_alloc_attr_node(info), ioapic, pin); + if (!add_pin_to_irq_node(data, ioapic_alloc_attr_node(info), ioapic, pin)) { + ret = -ENOMEM; + goto free_irqs; + } mp_preconfigure_entry(data); mp_register_handler(virq, data->is_level); @@ -3065,6 +3057,12 @@ int mp_irqdomain_alloc(struct irq_domain *domain, unsigned int virq, ioapic, mpc_ioapic_id(ioapic), pin, virq, data->is_level, data->active_low); return 0; + +free_irqs: + irq_domain_free_irqs_parent(domain, virq, nr_irqs); +free_data: + kfree(data); + return ret; } void mp_irqdomain_free(struct irq_domain *domain, unsigned int virq, From b3dcf220c913a432b50213b296dbf16bca17788a Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Wed, 14 Aug 2024 15:48:41 +0200 Subject: [PATCH 036/267] ALSA: usb-audio: Define macros for quirk table entries [ Upstream commit 0c3ad39b791c2ecf718afcaca30e5ceafa939d5c ] Many entries in the USB-audio quirk tables have relatively complex expressions. For improving the readability, introduce a few macros. Those are applied in the following patch. Link: https://patch.msgid.link/20240814134844.2726-2-tiwai@suse.de Signed-off-by: Takashi Iwai Signed-off-by: Sasha Levin --- sound/usb/quirks-table.h | 77 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 77 insertions(+) diff --git a/sound/usb/quirks-table.h b/sound/usb/quirks-table.h index d2aa97a5c438..a0063caa769c 100644 --- a/sound/usb/quirks-table.h +++ b/sound/usb/quirks-table.h @@ -35,6 +35,83 @@ .bInterfaceClass = USB_CLASS_AUDIO, \ .bInterfaceSubClass = USB_SUBCLASS_AUDIOCONTROL +/* Quirk .driver_info, followed by the definition of the quirk entry; + * put like QUIRK_DRIVER_INFO { ... } in each entry of the quirk table + */ +#define QUIRK_DRIVER_INFO \ + .driver_info = (unsigned long)&(const struct snd_usb_audio_quirk) + +/* + * Macros for quirk data entries + */ + +/* Quirk data entry for ignoring the interface */ +#define QUIRK_DATA_IGNORE(_ifno) \ + .ifnum = (_ifno), .type = QUIRK_IGNORE_INTERFACE +/* Quirk data entry for a standard audio interface */ +#define QUIRK_DATA_STANDARD_AUDIO(_ifno) \ + .ifnum = (_ifno), .type = QUIRK_AUDIO_STANDARD_INTERFACE +/* Quirk data entry for a standard MIDI interface */ +#define QUIRK_DATA_STANDARD_MIDI(_ifno) \ + .ifnum = (_ifno), .type = QUIRK_MIDI_STANDARD_INTERFACE +/* Quirk data entry for a standard mixer interface */ +#define QUIRK_DATA_STANDARD_MIXER(_ifno) \ + .ifnum = (_ifno), .type = QUIRK_AUDIO_STANDARD_MIXER + +/* Quirk data entry for Yamaha MIDI */ +#define QUIRK_DATA_MIDI_YAMAHA(_ifno) \ + .ifnum = (_ifno), .type = QUIRK_MIDI_YAMAHA +/* Quirk data entry for Edirol UAxx */ +#define QUIRK_DATA_EDIROL_UAXX(_ifno) \ + .ifnum = (_ifno), .type = QUIRK_AUDIO_EDIROL_UAXX +/* Quirk data entry for raw bytes interface */ +#define QUIRK_DATA_RAW_BYTES(_ifno) \ + .ifnum = (_ifno), .type = QUIRK_MIDI_RAW_BYTES + +/* Quirk composite array terminator */ +#define QUIRK_COMPOSITE_END { .ifnum = -1 } + +/* Quirk data entry for composite quirks; + * followed by the quirk array that is terminated with QUIRK_COMPOSITE_END + * e.g. QUIRK_DATA_COMPOSITE { { quirk1 }, { quirk2 },..., QUIRK_COMPOSITE_END } + */ +#define QUIRK_DATA_COMPOSITE \ + .ifnum = QUIRK_ANY_INTERFACE, \ + .type = QUIRK_COMPOSITE, \ + .data = &(const struct snd_usb_audio_quirk[]) + +/* Quirk data entry for a fixed audio endpoint; + * followed by audioformat definition + * e.g. QUIRK_DATA_AUDIOFORMAT(n) { .formats = xxx, ... } + */ +#define QUIRK_DATA_AUDIOFORMAT(_ifno) \ + .ifnum = (_ifno), \ + .type = QUIRK_AUDIO_FIXED_ENDPOINT, \ + .data = &(const struct audioformat) + +/* Quirk data entry for a fixed MIDI endpoint; + * followed by snd_usb_midi_endpoint_info definition + * e.g. QUIRK_DATA_MIDI_FIXED_ENDPOINT(n) { .out_cables = x, .in_cables = y } + */ +#define QUIRK_DATA_MIDI_FIXED_ENDPOINT(_ifno) \ + .ifnum = (_ifno), \ + .type = QUIRK_MIDI_FIXED_ENDPOINT, \ + .data = &(const struct snd_usb_midi_endpoint_info) +/* Quirk data entry for a MIDIMAN MIDI endpoint */ +#define QUIRK_DATA_MIDI_MIDIMAN(_ifno) \ + .ifnum = (_ifno), \ + .type = QUIRK_MIDI_MIDIMAN, \ + .data = &(const struct snd_usb_midi_endpoint_info) +/* Quirk data entry for a EMAGIC MIDI endpoint */ +#define QUIRK_DATA_MIDI_EMAGIC(_ifno) \ + .ifnum = (_ifno), \ + .type = QUIRK_MIDI_EMAGIC, \ + .data = &(const struct snd_usb_midi_endpoint_info) + +/* + * Here we go... the quirk table definition begins: + */ + /* FTDI devices */ { USB_DEVICE(0x0403, 0xb8d8), From 779c0e63f2a0904d8a9ad661459ffc0b191055d5 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Wed, 14 Aug 2024 15:48:42 +0200 Subject: [PATCH 037/267] ALSA: usb-audio: Replace complex quirk lines with macros [ Upstream commit d79e13f8e8abb5cd3a2a0f9fc9bc3fc750c5b06f ] Apply the newly introduced macros for reduce the complex expressions and cast in the quirk table definitions. It results in a significant code reduction, too. There should be no functional changes. Link: https://patch.msgid.link/20240814134844.2726-3-tiwai@suse.de Signed-off-by: Takashi Iwai Signed-off-by: Sasha Levin --- sound/usb/quirks-table.h | 2206 ++++++++++---------------------------- 1 file changed, 591 insertions(+), 1615 deletions(-) diff --git a/sound/usb/quirks-table.h b/sound/usb/quirks-table.h index a0063caa769c..75cde5779f38 100644 --- a/sound/usb/quirks-table.h +++ b/sound/usb/quirks-table.h @@ -115,7 +115,7 @@ /* FTDI devices */ { USB_DEVICE(0x0403, 0xb8d8), - .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { + QUIRK_DRIVER_INFO { /* .vendor_name = "STARR LABS", */ /* .product_name = "Starr Labs MIDI USB device", */ .ifnum = 0, @@ -126,10 +126,8 @@ { /* Creative BT-D1 */ USB_DEVICE(0x041e, 0x0005), - .driver_info = (unsigned long) &(const struct snd_usb_audio_quirk) { - .ifnum = 1, - .type = QUIRK_AUDIO_FIXED_ENDPOINT, - .data = &(const struct audioformat) { + QUIRK_DRIVER_INFO { + QUIRK_DATA_AUDIOFORMAT(1) { .formats = SNDRV_PCM_FMTBIT_S16_LE, .channels = 2, .iface = 1, @@ -164,18 +162,11 @@ */ { USB_AUDIO_DEVICE(0x041e, 0x4095), - .driver_info = (unsigned long) &(const struct snd_usb_audio_quirk) { - .ifnum = QUIRK_ANY_INTERFACE, - .type = QUIRK_COMPOSITE, - .data = &(const struct snd_usb_audio_quirk[]) { + QUIRK_DRIVER_INFO { + QUIRK_DATA_COMPOSITE { + { QUIRK_DATA_STANDARD_MIXER(2) }, { - .ifnum = 2, - .type = QUIRK_AUDIO_STANDARD_MIXER, - }, - { - .ifnum = 3, - .type = QUIRK_AUDIO_FIXED_ENDPOINT, - .data = &(const struct audioformat) { + QUIRK_DATA_AUDIOFORMAT(3) { .formats = SNDRV_PCM_FMTBIT_S16_LE, .channels = 2, .fmt_bits = 16, @@ -191,9 +182,7 @@ .rate_table = (unsigned int[]) { 48000 }, }, }, - { - .ifnum = -1 - }, + QUIRK_COMPOSITE_END }, }, }, @@ -205,31 +194,18 @@ */ { USB_DEVICE(0x0424, 0xb832), - .driver_info = (unsigned long) &(const struct snd_usb_audio_quirk) { + QUIRK_DRIVER_INFO { .vendor_name = "Standard Microsystems Corp.", .product_name = "HP Wireless Audio", - .ifnum = QUIRK_ANY_INTERFACE, - .type = QUIRK_COMPOSITE, - .data = (const struct snd_usb_audio_quirk[]) { + QUIRK_DATA_COMPOSITE { /* Mixer */ - { - .ifnum = 0, - .type = QUIRK_IGNORE_INTERFACE, - }, + { QUIRK_DATA_IGNORE(0) }, /* Playback */ - { - .ifnum = 1, - .type = QUIRK_IGNORE_INTERFACE, - }, + { QUIRK_DATA_IGNORE(1) }, /* Capture */ - { - .ifnum = 2, - .type = QUIRK_IGNORE_INTERFACE, - }, + { QUIRK_DATA_IGNORE(2) }, /* HID Device, .ifnum = 3 */ - { - .ifnum = -1, - } + QUIRK_COMPOSITE_END } } }, @@ -252,20 +228,18 @@ #define YAMAHA_DEVICE(id, name) { \ USB_DEVICE(0x0499, id), \ - .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { \ + QUIRK_DRIVER_INFO { \ .vendor_name = "Yamaha", \ .product_name = name, \ - .ifnum = QUIRK_ANY_INTERFACE, \ - .type = QUIRK_MIDI_YAMAHA \ + QUIRK_DATA_MIDI_YAMAHA(QUIRK_ANY_INTERFACE) \ } \ } #define YAMAHA_INTERFACE(id, intf, name) { \ USB_DEVICE_VENDOR_SPEC(0x0499, id), \ - .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { \ + QUIRK_DRIVER_INFO { \ .vendor_name = "Yamaha", \ .product_name = name, \ - .ifnum = intf, \ - .type = QUIRK_MIDI_YAMAHA \ + QUIRK_DATA_MIDI_YAMAHA(intf) \ } \ } YAMAHA_DEVICE(0x1000, "UX256"), @@ -353,135 +327,67 @@ YAMAHA_DEVICE(0x105d, NULL), YAMAHA_DEVICE(0x1718, "P-125"), { USB_DEVICE(0x0499, 0x1503), - .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { + QUIRK_DRIVER_INFO { /* .vendor_name = "Yamaha", */ /* .product_name = "MOX6/MOX8", */ - .ifnum = QUIRK_ANY_INTERFACE, - .type = QUIRK_COMPOSITE, - .data = (const struct snd_usb_audio_quirk[]) { - { - .ifnum = 1, - .type = QUIRK_AUDIO_STANDARD_INTERFACE - }, - { - .ifnum = 2, - .type = QUIRK_AUDIO_STANDARD_INTERFACE - }, - { - .ifnum = 3, - .type = QUIRK_MIDI_YAMAHA - }, - { - .ifnum = -1 - } + QUIRK_DATA_COMPOSITE { + { QUIRK_DATA_STANDARD_AUDIO(1) }, + { QUIRK_DATA_STANDARD_AUDIO(2) }, + { QUIRK_DATA_MIDI_YAMAHA(3) }, + QUIRK_COMPOSITE_END } } }, { USB_DEVICE(0x0499, 0x1507), - .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { + QUIRK_DRIVER_INFO { /* .vendor_name = "Yamaha", */ /* .product_name = "THR10", */ - .ifnum = QUIRK_ANY_INTERFACE, - .type = QUIRK_COMPOSITE, - .data = (const struct snd_usb_audio_quirk[]) { - { - .ifnum = 1, - .type = QUIRK_AUDIO_STANDARD_INTERFACE - }, - { - .ifnum = 2, - .type = QUIRK_AUDIO_STANDARD_INTERFACE - }, - { - .ifnum = 3, - .type = QUIRK_MIDI_YAMAHA - }, - { - .ifnum = -1 - } + QUIRK_DATA_COMPOSITE { + { QUIRK_DATA_STANDARD_AUDIO(1) }, + { QUIRK_DATA_STANDARD_AUDIO(2) }, + { QUIRK_DATA_MIDI_YAMAHA(3) }, + QUIRK_COMPOSITE_END } } }, { USB_DEVICE(0x0499, 0x1509), - .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { + QUIRK_DRIVER_INFO { /* .vendor_name = "Yamaha", */ /* .product_name = "Steinberg UR22", */ - .ifnum = QUIRK_ANY_INTERFACE, - .type = QUIRK_COMPOSITE, - .data = (const struct snd_usb_audio_quirk[]) { - { - .ifnum = 1, - .type = QUIRK_AUDIO_STANDARD_INTERFACE - }, - { - .ifnum = 2, - .type = QUIRK_AUDIO_STANDARD_INTERFACE - }, - { - .ifnum = 3, - .type = QUIRK_MIDI_YAMAHA - }, - { - .ifnum = 4, - .type = QUIRK_IGNORE_INTERFACE - }, - { - .ifnum = -1 - } + QUIRK_DATA_COMPOSITE { + { QUIRK_DATA_STANDARD_AUDIO(1) }, + { QUIRK_DATA_STANDARD_AUDIO(2) }, + { QUIRK_DATA_MIDI_YAMAHA(3) }, + { QUIRK_DATA_IGNORE(4) }, + QUIRK_COMPOSITE_END } } }, { USB_DEVICE(0x0499, 0x150a), - .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { + QUIRK_DRIVER_INFO { /* .vendor_name = "Yamaha", */ /* .product_name = "THR5A", */ - .ifnum = QUIRK_ANY_INTERFACE, - .type = QUIRK_COMPOSITE, - .data = (const struct snd_usb_audio_quirk[]) { - { - .ifnum = 1, - .type = QUIRK_AUDIO_STANDARD_INTERFACE - }, - { - .ifnum = 2, - .type = QUIRK_AUDIO_STANDARD_INTERFACE - }, - { - .ifnum = 3, - .type = QUIRK_MIDI_YAMAHA - }, - { - .ifnum = -1 - } + QUIRK_DATA_COMPOSITE { + { QUIRK_DATA_STANDARD_AUDIO(1) }, + { QUIRK_DATA_STANDARD_AUDIO(2) }, + { QUIRK_DATA_MIDI_YAMAHA(3) }, + QUIRK_COMPOSITE_END } } }, { USB_DEVICE(0x0499, 0x150c), - .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { + QUIRK_DRIVER_INFO { /* .vendor_name = "Yamaha", */ /* .product_name = "THR10C", */ - .ifnum = QUIRK_ANY_INTERFACE, - .type = QUIRK_COMPOSITE, - .data = (const struct snd_usb_audio_quirk[]) { - { - .ifnum = 1, - .type = QUIRK_AUDIO_STANDARD_INTERFACE - }, - { - .ifnum = 2, - .type = QUIRK_AUDIO_STANDARD_INTERFACE - }, - { - .ifnum = 3, - .type = QUIRK_MIDI_YAMAHA - }, - { - .ifnum = -1 - } + QUIRK_DATA_COMPOSITE { + { QUIRK_DATA_STANDARD_AUDIO(1) }, + { QUIRK_DATA_STANDARD_AUDIO(2) }, + { QUIRK_DATA_MIDI_YAMAHA(3) }, + QUIRK_COMPOSITE_END } } }, @@ -515,7 +421,7 @@ YAMAHA_DEVICE(0x7010, "UB99"), USB_DEVICE_ID_MATCH_INT_CLASS, .idVendor = 0x0499, .bInterfaceClass = USB_CLASS_VENDOR_SPEC, - .driver_info = (unsigned long) &(const struct snd_usb_audio_quirk) { + QUIRK_DRIVER_INFO { .ifnum = QUIRK_ANY_INTERFACE, .type = QUIRK_AUTODETECT } @@ -526,16 +432,12 @@ YAMAHA_DEVICE(0x7010, "UB99"), */ { USB_DEVICE(0x0582, 0x0000), - .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { + QUIRK_DRIVER_INFO { .vendor_name = "Roland", .product_name = "UA-100", - .ifnum = QUIRK_ANY_INTERFACE, - .type = QUIRK_COMPOSITE, - .data = (const struct snd_usb_audio_quirk[]) { + QUIRK_DATA_COMPOSITE { { - .ifnum = 0, - .type = QUIRK_AUDIO_FIXED_ENDPOINT, - .data = & (const struct audioformat) { + QUIRK_DATA_AUDIOFORMAT(0) { .formats = SNDRV_PCM_FMTBIT_S16_LE, .channels = 4, .iface = 0, @@ -550,9 +452,7 @@ YAMAHA_DEVICE(0x7010, "UB99"), } }, { - .ifnum = 1, - .type = QUIRK_AUDIO_FIXED_ENDPOINT, - .data = & (const struct audioformat) { + QUIRK_DATA_AUDIOFORMAT(1) { .formats = SNDRV_PCM_FMTBIT_S16_LE, .channels = 2, .iface = 1, @@ -567,106 +467,66 @@ YAMAHA_DEVICE(0x7010, "UB99"), } }, { - .ifnum = 2, - .type = QUIRK_MIDI_FIXED_ENDPOINT, - .data = & (const struct snd_usb_midi_endpoint_info) { + QUIRK_DATA_MIDI_FIXED_ENDPOINT(2) { .out_cables = 0x0007, .in_cables = 0x0007 } }, - { - .ifnum = -1 - } + QUIRK_COMPOSITE_END } } }, { USB_DEVICE(0x0582, 0x0002), - .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { + QUIRK_DRIVER_INFO { .vendor_name = "EDIROL", .product_name = "UM-4", - .ifnum = QUIRK_ANY_INTERFACE, - .type = QUIRK_COMPOSITE, - .data = (const struct snd_usb_audio_quirk[]) { + QUIRK_DATA_COMPOSITE { + { QUIRK_DATA_IGNORE(0) }, + { QUIRK_DATA_IGNORE(1) }, { - .ifnum = 0, - .type = QUIRK_IGNORE_INTERFACE - }, - { - .ifnum = 1, - .type = QUIRK_IGNORE_INTERFACE - }, - { - .ifnum = 2, - .type = QUIRK_MIDI_FIXED_ENDPOINT, - .data = & (const struct snd_usb_midi_endpoint_info) { + QUIRK_DATA_MIDI_FIXED_ENDPOINT(2) { .out_cables = 0x000f, .in_cables = 0x000f } }, - { - .ifnum = -1 - } + QUIRK_COMPOSITE_END } } }, { USB_DEVICE(0x0582, 0x0003), - .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { + QUIRK_DRIVER_INFO { .vendor_name = "Roland", .product_name = "SC-8850", - .ifnum = QUIRK_ANY_INTERFACE, - .type = QUIRK_COMPOSITE, - .data = (const struct snd_usb_audio_quirk[]) { + QUIRK_DATA_COMPOSITE { + { QUIRK_DATA_IGNORE(0) }, + { QUIRK_DATA_IGNORE(1) }, { - .ifnum = 0, - .type = QUIRK_IGNORE_INTERFACE - }, - { - .ifnum = 1, - .type = QUIRK_IGNORE_INTERFACE - }, - { - .ifnum = 2, - .type = QUIRK_MIDI_FIXED_ENDPOINT, - .data = & (const struct snd_usb_midi_endpoint_info) { + QUIRK_DATA_MIDI_FIXED_ENDPOINT(2) { .out_cables = 0x003f, .in_cables = 0x003f } }, - { - .ifnum = -1 - } + QUIRK_COMPOSITE_END } } }, { USB_DEVICE(0x0582, 0x0004), - .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { + QUIRK_DRIVER_INFO { .vendor_name = "Roland", .product_name = "U-8", - .ifnum = QUIRK_ANY_INTERFACE, - .type = QUIRK_COMPOSITE, - .data = (const struct snd_usb_audio_quirk[]) { + QUIRK_DATA_COMPOSITE { + { QUIRK_DATA_IGNORE(0) }, + { QUIRK_DATA_IGNORE(1) }, { - .ifnum = 0, - .type = QUIRK_IGNORE_INTERFACE - }, - { - .ifnum = 1, - .type = QUIRK_IGNORE_INTERFACE - }, - { - .ifnum = 2, - .type = QUIRK_MIDI_FIXED_ENDPOINT, - .data = & (const struct snd_usb_midi_endpoint_info) { + QUIRK_DATA_MIDI_FIXED_ENDPOINT(2) { .out_cables = 0x0005, .in_cables = 0x0005 } }, - { - .ifnum = -1 - } + QUIRK_COMPOSITE_END } } }, @@ -674,152 +534,92 @@ YAMAHA_DEVICE(0x7010, "UB99"), /* Has ID 0x0099 when not in "Advanced Driver" mode. * The UM-2EX has only one input, but we cannot detect this. */ USB_DEVICE(0x0582, 0x0005), - .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { + QUIRK_DRIVER_INFO { .vendor_name = "EDIROL", .product_name = "UM-2", - .ifnum = QUIRK_ANY_INTERFACE, - .type = QUIRK_COMPOSITE, - .data = (const struct snd_usb_audio_quirk[]) { + QUIRK_DATA_COMPOSITE { + { QUIRK_DATA_IGNORE(0) }, + { QUIRK_DATA_IGNORE(1) }, { - .ifnum = 0, - .type = QUIRK_IGNORE_INTERFACE - }, - { - .ifnum = 1, - .type = QUIRK_IGNORE_INTERFACE - }, - { - .ifnum = 2, - .type = QUIRK_MIDI_FIXED_ENDPOINT, - .data = & (const struct snd_usb_midi_endpoint_info) { + QUIRK_DATA_MIDI_FIXED_ENDPOINT(2) { .out_cables = 0x0003, .in_cables = 0x0003 } }, - { - .ifnum = -1 - } + QUIRK_COMPOSITE_END } } }, { USB_DEVICE(0x0582, 0x0007), - .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { + QUIRK_DRIVER_INFO { .vendor_name = "Roland", .product_name = "SC-8820", - .ifnum = QUIRK_ANY_INTERFACE, - .type = QUIRK_COMPOSITE, - .data = (const struct snd_usb_audio_quirk[]) { + QUIRK_DATA_COMPOSITE { + { QUIRK_DATA_IGNORE(0) }, + { QUIRK_DATA_IGNORE(1) }, { - .ifnum = 0, - .type = QUIRK_IGNORE_INTERFACE - }, - { - .ifnum = 1, - .type = QUIRK_IGNORE_INTERFACE - }, - { - .ifnum = 2, - .type = QUIRK_MIDI_FIXED_ENDPOINT, - .data = & (const struct snd_usb_midi_endpoint_info) { + QUIRK_DATA_MIDI_FIXED_ENDPOINT(2) { .out_cables = 0x0013, .in_cables = 0x0013 } }, - { - .ifnum = -1 - } + QUIRK_COMPOSITE_END } } }, { USB_DEVICE(0x0582, 0x0008), - .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { + QUIRK_DRIVER_INFO { .vendor_name = "Roland", .product_name = "PC-300", - .ifnum = QUIRK_ANY_INTERFACE, - .type = QUIRK_COMPOSITE, - .data = (const struct snd_usb_audio_quirk[]) { + QUIRK_DATA_COMPOSITE { + { QUIRK_DATA_IGNORE(0) }, + { QUIRK_DATA_IGNORE(1) }, { - .ifnum = 0, - .type = QUIRK_IGNORE_INTERFACE - }, - { - .ifnum = 1, - .type = QUIRK_IGNORE_INTERFACE - }, - { - .ifnum = 2, - .type = QUIRK_MIDI_FIXED_ENDPOINT, - .data = & (const struct snd_usb_midi_endpoint_info) { + QUIRK_DATA_MIDI_FIXED_ENDPOINT(2) { .out_cables = 0x0001, .in_cables = 0x0001 } }, - { - .ifnum = -1 - } + QUIRK_COMPOSITE_END } } }, { /* has ID 0x009d when not in "Advanced Driver" mode */ USB_DEVICE(0x0582, 0x0009), - .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { + QUIRK_DRIVER_INFO { .vendor_name = "EDIROL", .product_name = "UM-1", - .ifnum = QUIRK_ANY_INTERFACE, - .type = QUIRK_COMPOSITE, - .data = (const struct snd_usb_audio_quirk[]) { + QUIRK_DATA_COMPOSITE { + { QUIRK_DATA_IGNORE(0) }, + { QUIRK_DATA_IGNORE(1) }, { - .ifnum = 0, - .type = QUIRK_IGNORE_INTERFACE - }, - { - .ifnum = 1, - .type = QUIRK_IGNORE_INTERFACE - }, - { - .ifnum = 2, - .type = QUIRK_MIDI_FIXED_ENDPOINT, - .data = & (const struct snd_usb_midi_endpoint_info) { + QUIRK_DATA_MIDI_FIXED_ENDPOINT(2) { .out_cables = 0x0001, .in_cables = 0x0001 } }, - { - .ifnum = -1 - } + QUIRK_COMPOSITE_END } } }, { USB_DEVICE(0x0582, 0x000b), - .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { + QUIRK_DRIVER_INFO { .vendor_name = "Roland", .product_name = "SK-500", - .ifnum = QUIRK_ANY_INTERFACE, - .type = QUIRK_COMPOSITE, - .data = (const struct snd_usb_audio_quirk[]) { + QUIRK_DATA_COMPOSITE { + { QUIRK_DATA_IGNORE(0) }, + { QUIRK_DATA_IGNORE(1) }, { - .ifnum = 0, - .type = QUIRK_IGNORE_INTERFACE - }, - { - .ifnum = 1, - .type = QUIRK_IGNORE_INTERFACE - }, - { - .ifnum = 2, - .type = QUIRK_MIDI_FIXED_ENDPOINT, - .data = & (const struct snd_usb_midi_endpoint_info) { + QUIRK_DATA_MIDI_FIXED_ENDPOINT(2) { .out_cables = 0x0013, .in_cables = 0x0013 } }, - { - .ifnum = -1 - } + QUIRK_COMPOSITE_END } } }, @@ -827,31 +627,19 @@ YAMAHA_DEVICE(0x7010, "UB99"), /* thanks to Emiliano Grilli * for helping researching this data */ USB_DEVICE(0x0582, 0x000c), - .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { + QUIRK_DRIVER_INFO { .vendor_name = "Roland", .product_name = "SC-D70", - .ifnum = QUIRK_ANY_INTERFACE, - .type = QUIRK_COMPOSITE, - .data = (const struct snd_usb_audio_quirk[]) { + QUIRK_DATA_COMPOSITE { + { QUIRK_DATA_STANDARD_AUDIO(0) }, + { QUIRK_DATA_STANDARD_AUDIO(1) }, { - .ifnum = 0, - .type = QUIRK_AUDIO_STANDARD_INTERFACE - }, - { - .ifnum = 1, - .type = QUIRK_AUDIO_STANDARD_INTERFACE - }, - { - .ifnum = 2, - .type = QUIRK_MIDI_FIXED_ENDPOINT, - .data = & (const struct snd_usb_midi_endpoint_info) { + QUIRK_DATA_MIDI_FIXED_ENDPOINT(2) { .out_cables = 0x0007, .in_cables = 0x0007 } }, - { - .ifnum = -1 - } + QUIRK_COMPOSITE_END } } }, @@ -865,35 +653,23 @@ YAMAHA_DEVICE(0x7010, "UB99"), * the 96kHz sample rate. */ USB_DEVICE(0x0582, 0x0010), - .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { + QUIRK_DRIVER_INFO { .vendor_name = "EDIROL", .product_name = "UA-5", - .ifnum = QUIRK_ANY_INTERFACE, - .type = QUIRK_COMPOSITE, - .data = (const struct snd_usb_audio_quirk[]) { - { - .ifnum = 1, - .type = QUIRK_AUDIO_STANDARD_INTERFACE - }, - { - .ifnum = 2, - .type = QUIRK_AUDIO_STANDARD_INTERFACE - }, - { - .ifnum = -1 - } + QUIRK_DATA_COMPOSITE { + { QUIRK_DATA_STANDARD_AUDIO(1) }, + { QUIRK_DATA_STANDARD_AUDIO(2) }, + QUIRK_COMPOSITE_END } } }, { /* has ID 0x0013 when not in "Advanced Driver" mode */ USB_DEVICE(0x0582, 0x0012), - .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { + QUIRK_DRIVER_INFO { .vendor_name = "Roland", .product_name = "XV-5050", - .ifnum = 0, - .type = QUIRK_MIDI_FIXED_ENDPOINT, - .data = & (const struct snd_usb_midi_endpoint_info) { + QUIRK_DATA_MIDI_FIXED_ENDPOINT(0) { .out_cables = 0x0001, .in_cables = 0x0001 } @@ -902,12 +678,10 @@ YAMAHA_DEVICE(0x7010, "UB99"), { /* has ID 0x0015 when not in "Advanced Driver" mode */ USB_DEVICE(0x0582, 0x0014), - .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { + QUIRK_DRIVER_INFO { .vendor_name = "EDIROL", .product_name = "UM-880", - .ifnum = 0, - .type = QUIRK_MIDI_FIXED_ENDPOINT, - .data = & (const struct snd_usb_midi_endpoint_info) { + QUIRK_DATA_MIDI_FIXED_ENDPOINT(0) { .out_cables = 0x01ff, .in_cables = 0x01ff } @@ -916,74 +690,48 @@ YAMAHA_DEVICE(0x7010, "UB99"), { /* has ID 0x0017 when not in "Advanced Driver" mode */ USB_DEVICE(0x0582, 0x0016), - .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { + QUIRK_DRIVER_INFO { .vendor_name = "EDIROL", .product_name = "SD-90", - .ifnum = QUIRK_ANY_INTERFACE, - .type = QUIRK_COMPOSITE, - .data = (const struct snd_usb_audio_quirk[]) { + QUIRK_DATA_COMPOSITE { + { QUIRK_DATA_STANDARD_AUDIO(0) }, + { QUIRK_DATA_STANDARD_AUDIO(1) }, { - .ifnum = 0, - .type = QUIRK_AUDIO_STANDARD_INTERFACE - }, - { - .ifnum = 1, - .type = QUIRK_AUDIO_STANDARD_INTERFACE - }, - { - .ifnum = 2, - .type = QUIRK_MIDI_FIXED_ENDPOINT, - .data = & (const struct snd_usb_midi_endpoint_info) { + QUIRK_DATA_MIDI_FIXED_ENDPOINT(2) { .out_cables = 0x000f, .in_cables = 0x000f } }, - { - .ifnum = -1 - } + QUIRK_COMPOSITE_END } } }, { /* has ID 0x001c when not in "Advanced Driver" mode */ USB_DEVICE(0x0582, 0x001b), - .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { + QUIRK_DRIVER_INFO { .vendor_name = "Roland", .product_name = "MMP-2", - .ifnum = QUIRK_ANY_INTERFACE, - .type = QUIRK_COMPOSITE, - .data = (const struct snd_usb_audio_quirk[]) { + QUIRK_DATA_COMPOSITE { + { QUIRK_DATA_IGNORE(0) }, + { QUIRK_DATA_IGNORE(1) }, { - .ifnum = 0, - .type = QUIRK_IGNORE_INTERFACE - }, - { - .ifnum = 1, - .type = QUIRK_IGNORE_INTERFACE - }, - { - .ifnum = 2, - .type = QUIRK_MIDI_FIXED_ENDPOINT, - .data = & (const struct snd_usb_midi_endpoint_info) { + QUIRK_DATA_MIDI_FIXED_ENDPOINT(2) { .out_cables = 0x0001, .in_cables = 0x0001 } }, - { - .ifnum = -1 - } + QUIRK_COMPOSITE_END } } }, { /* has ID 0x001e when not in "Advanced Driver" mode */ USB_DEVICE(0x0582, 0x001d), - .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { + QUIRK_DRIVER_INFO { .vendor_name = "Roland", .product_name = "V-SYNTH", - .ifnum = 0, - .type = QUIRK_MIDI_FIXED_ENDPOINT, - .data = & (const struct snd_usb_midi_endpoint_info) { + QUIRK_DATA_MIDI_FIXED_ENDPOINT(0) { .out_cables = 0x0001, .in_cables = 0x0001 } @@ -992,12 +740,10 @@ YAMAHA_DEVICE(0x7010, "UB99"), { /* has ID 0x0024 when not in "Advanced Driver" mode */ USB_DEVICE(0x0582, 0x0023), - .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { + QUIRK_DRIVER_INFO { .vendor_name = "EDIROL", .product_name = "UM-550", - .ifnum = 0, - .type = QUIRK_MIDI_FIXED_ENDPOINT, - .data = & (const struct snd_usb_midi_endpoint_info) { + QUIRK_DATA_MIDI_FIXED_ENDPOINT(0) { .out_cables = 0x003f, .in_cables = 0x003f } @@ -1010,20 +756,13 @@ YAMAHA_DEVICE(0x7010, "UB99"), * and no MIDI. */ USB_DEVICE(0x0582, 0x0025), - .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { + QUIRK_DRIVER_INFO { .vendor_name = "EDIROL", .product_name = "UA-20", - .ifnum = QUIRK_ANY_INTERFACE, - .type = QUIRK_COMPOSITE, - .data = (const struct snd_usb_audio_quirk[]) { + QUIRK_DATA_COMPOSITE { + { QUIRK_DATA_IGNORE(0) }, { - .ifnum = 0, - .type = QUIRK_IGNORE_INTERFACE - }, - { - .ifnum = 1, - .type = QUIRK_AUDIO_FIXED_ENDPOINT, - .data = & (const struct audioformat) { + QUIRK_DATA_AUDIOFORMAT(1) { .formats = SNDRV_PCM_FMTBIT_S24_3LE, .channels = 2, .iface = 1, @@ -1038,9 +777,7 @@ YAMAHA_DEVICE(0x7010, "UB99"), } }, { - .ifnum = 2, - .type = QUIRK_AUDIO_FIXED_ENDPOINT, - .data = & (const struct audioformat) { + QUIRK_DATA_AUDIOFORMAT(2) { .formats = SNDRV_PCM_FMTBIT_S24_3LE, .channels = 2, .iface = 2, @@ -1055,28 +792,22 @@ YAMAHA_DEVICE(0x7010, "UB99"), } }, { - .ifnum = 3, - .type = QUIRK_MIDI_FIXED_ENDPOINT, - .data = & (const struct snd_usb_midi_endpoint_info) { + QUIRK_DATA_MIDI_FIXED_ENDPOINT(3) { .out_cables = 0x0001, .in_cables = 0x0001 } }, - { - .ifnum = -1 - } + QUIRK_COMPOSITE_END } } }, { /* has ID 0x0028 when not in "Advanced Driver" mode */ USB_DEVICE(0x0582, 0x0027), - .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { + QUIRK_DRIVER_INFO { .vendor_name = "EDIROL", .product_name = "SD-20", - .ifnum = 0, - .type = QUIRK_MIDI_FIXED_ENDPOINT, - .data = & (const struct snd_usb_midi_endpoint_info) { + QUIRK_DATA_MIDI_FIXED_ENDPOINT(0) { .out_cables = 0x0003, .in_cables = 0x0007 } @@ -1085,12 +816,10 @@ YAMAHA_DEVICE(0x7010, "UB99"), { /* has ID 0x002a when not in "Advanced Driver" mode */ USB_DEVICE(0x0582, 0x0029), - .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { + QUIRK_DRIVER_INFO { .vendor_name = "EDIROL", .product_name = "SD-80", - .ifnum = 0, - .type = QUIRK_MIDI_FIXED_ENDPOINT, - .data = & (const struct snd_usb_midi_endpoint_info) { + QUIRK_DATA_MIDI_FIXED_ENDPOINT(0) { .out_cables = 0x000f, .in_cables = 0x000f } @@ -1103,39 +832,24 @@ YAMAHA_DEVICE(0x7010, "UB99"), * but offers only 16-bit PCM and no MIDI. */ USB_DEVICE_VENDOR_SPEC(0x0582, 0x002b), - .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { + QUIRK_DRIVER_INFO { .vendor_name = "EDIROL", .product_name = "UA-700", - .ifnum = QUIRK_ANY_INTERFACE, - .type = QUIRK_COMPOSITE, - .data = (const struct snd_usb_audio_quirk[]) { - { - .ifnum = 1, - .type = QUIRK_AUDIO_EDIROL_UAXX - }, - { - .ifnum = 2, - .type = QUIRK_AUDIO_EDIROL_UAXX - }, - { - .ifnum = 3, - .type = QUIRK_AUDIO_EDIROL_UAXX - }, - { - .ifnum = -1 - } + QUIRK_DATA_COMPOSITE { + { QUIRK_DATA_EDIROL_UAXX(1) }, + { QUIRK_DATA_EDIROL_UAXX(2) }, + { QUIRK_DATA_EDIROL_UAXX(3) }, + QUIRK_COMPOSITE_END } } }, { /* has ID 0x002e when not in "Advanced Driver" mode */ USB_DEVICE(0x0582, 0x002d), - .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { + QUIRK_DRIVER_INFO { .vendor_name = "Roland", .product_name = "XV-2020", - .ifnum = 0, - .type = QUIRK_MIDI_FIXED_ENDPOINT, - .data = & (const struct snd_usb_midi_endpoint_info) { + QUIRK_DATA_MIDI_FIXED_ENDPOINT(0) { .out_cables = 0x0001, .in_cables = 0x0001 } @@ -1144,12 +858,10 @@ YAMAHA_DEVICE(0x7010, "UB99"), { /* has ID 0x0030 when not in "Advanced Driver" mode */ USB_DEVICE(0x0582, 0x002f), - .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { + QUIRK_DRIVER_INFO { .vendor_name = "Roland", .product_name = "VariOS", - .ifnum = 0, - .type = QUIRK_MIDI_FIXED_ENDPOINT, - .data = & (const struct snd_usb_midi_endpoint_info) { + QUIRK_DATA_MIDI_FIXED_ENDPOINT(0) { .out_cables = 0x0007, .in_cables = 0x0007 } @@ -1158,12 +870,10 @@ YAMAHA_DEVICE(0x7010, "UB99"), { /* has ID 0x0034 when not in "Advanced Driver" mode */ USB_DEVICE(0x0582, 0x0033), - .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { + QUIRK_DRIVER_INFO { .vendor_name = "EDIROL", .product_name = "PCR", - .ifnum = 0, - .type = QUIRK_MIDI_FIXED_ENDPOINT, - .data = & (const struct snd_usb_midi_endpoint_info) { + QUIRK_DATA_MIDI_FIXED_ENDPOINT(0) { .out_cables = 0x0003, .in_cables = 0x0007 } @@ -1175,12 +885,10 @@ YAMAHA_DEVICE(0x7010, "UB99"), * later revisions use IDs 0x0054 and 0x00a2. */ USB_DEVICE(0x0582, 0x0037), - .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { + QUIRK_DRIVER_INFO { .vendor_name = "Roland", .product_name = "Digital Piano", - .ifnum = 0, - .type = QUIRK_MIDI_FIXED_ENDPOINT, - .data = & (const struct snd_usb_midi_endpoint_info) { + QUIRK_DATA_MIDI_FIXED_ENDPOINT(0) { .out_cables = 0x0001, .in_cables = 0x0001 } @@ -1193,39 +901,24 @@ YAMAHA_DEVICE(0x7010, "UB99"), * and no MIDI. */ USB_DEVICE_VENDOR_SPEC(0x0582, 0x003b), - .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { + QUIRK_DRIVER_INFO { .vendor_name = "BOSS", .product_name = "GS-10", - .ifnum = QUIRK_ANY_INTERFACE, - .type = QUIRK_COMPOSITE, - .data = & (const struct snd_usb_audio_quirk[]) { - { - .ifnum = 1, - .type = QUIRK_AUDIO_STANDARD_INTERFACE - }, - { - .ifnum = 2, - .type = QUIRK_AUDIO_STANDARD_INTERFACE - }, - { - .ifnum = 3, - .type = QUIRK_MIDI_STANDARD_INTERFACE - }, - { - .ifnum = -1 - } + QUIRK_DATA_COMPOSITE { + { QUIRK_DATA_STANDARD_AUDIO(1) }, + { QUIRK_DATA_STANDARD_AUDIO(2) }, + { QUIRK_DATA_STANDARD_MIDI(3) }, + QUIRK_COMPOSITE_END } } }, { /* has ID 0x0041 when not in "Advanced Driver" mode */ USB_DEVICE(0x0582, 0x0040), - .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { + QUIRK_DRIVER_INFO { .vendor_name = "Roland", .product_name = "GI-20", - .ifnum = 0, - .type = QUIRK_MIDI_FIXED_ENDPOINT, - .data = & (const struct snd_usb_midi_endpoint_info) { + QUIRK_DATA_MIDI_FIXED_ENDPOINT(0) { .out_cables = 0x0001, .in_cables = 0x0001 } @@ -1234,12 +927,10 @@ YAMAHA_DEVICE(0x7010, "UB99"), { /* has ID 0x0043 when not in "Advanced Driver" mode */ USB_DEVICE(0x0582, 0x0042), - .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { + QUIRK_DRIVER_INFO { .vendor_name = "Roland", .product_name = "RS-70", - .ifnum = 0, - .type = QUIRK_MIDI_FIXED_ENDPOINT, - .data = & (const struct snd_usb_midi_endpoint_info) { + QUIRK_DATA_MIDI_FIXED_ENDPOINT(0) { .out_cables = 0x0001, .in_cables = 0x0001 } @@ -1248,36 +939,24 @@ YAMAHA_DEVICE(0x7010, "UB99"), { /* has ID 0x0049 when not in "Advanced Driver" mode */ USB_DEVICE(0x0582, 0x0047), - .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { + QUIRK_DRIVER_INFO { /* .vendor_name = "EDIROL", */ /* .product_name = "UR-80", */ - .ifnum = QUIRK_ANY_INTERFACE, - .type = QUIRK_COMPOSITE, - .data = (const struct snd_usb_audio_quirk[]) { + QUIRK_DATA_COMPOSITE { /* in the 96 kHz modes, only interface 1 is there */ - { - .ifnum = 1, - .type = QUIRK_AUDIO_STANDARD_INTERFACE - }, - { - .ifnum = 2, - .type = QUIRK_AUDIO_STANDARD_INTERFACE - }, - { - .ifnum = -1 - } + { QUIRK_DATA_STANDARD_AUDIO(1) }, + { QUIRK_DATA_STANDARD_AUDIO(2) }, + QUIRK_COMPOSITE_END } } }, { /* has ID 0x004a when not in "Advanced Driver" mode */ USB_DEVICE(0x0582, 0x0048), - .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { + QUIRK_DRIVER_INFO { /* .vendor_name = "EDIROL", */ /* .product_name = "UR-80", */ - .ifnum = 0, - .type = QUIRK_MIDI_FIXED_ENDPOINT, - .data = & (const struct snd_usb_midi_endpoint_info) { + QUIRK_DATA_MIDI_FIXED_ENDPOINT(0) { .out_cables = 0x0003, .in_cables = 0x0007 } @@ -1286,35 +965,23 @@ YAMAHA_DEVICE(0x7010, "UB99"), { /* has ID 0x004e when not in "Advanced Driver" mode */ USB_DEVICE(0x0582, 0x004c), - .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { + QUIRK_DRIVER_INFO { .vendor_name = "EDIROL", .product_name = "PCR-A", - .ifnum = QUIRK_ANY_INTERFACE, - .type = QUIRK_COMPOSITE, - .data = (const struct snd_usb_audio_quirk[]) { - { - .ifnum = 1, - .type = QUIRK_AUDIO_STANDARD_INTERFACE - }, - { - .ifnum = 2, - .type = QUIRK_AUDIO_STANDARD_INTERFACE - }, - { - .ifnum = -1 - } + QUIRK_DATA_COMPOSITE { + { QUIRK_DATA_STANDARD_AUDIO(1) }, + { QUIRK_DATA_STANDARD_AUDIO(2) }, + QUIRK_COMPOSITE_END } } }, { /* has ID 0x004f when not in "Advanced Driver" mode */ USB_DEVICE(0x0582, 0x004d), - .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { + QUIRK_DRIVER_INFO { .vendor_name = "EDIROL", .product_name = "PCR-A", - .ifnum = 0, - .type = QUIRK_MIDI_FIXED_ENDPOINT, - .data = & (const struct snd_usb_midi_endpoint_info) { + QUIRK_DATA_MIDI_FIXED_ENDPOINT(0) { .out_cables = 0x0003, .in_cables = 0x0007 } @@ -1326,76 +993,52 @@ YAMAHA_DEVICE(0x7010, "UB99"), * is standard compliant, but has only 16-bit PCM. */ USB_DEVICE(0x0582, 0x0050), - .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { + QUIRK_DRIVER_INFO { .vendor_name = "EDIROL", .product_name = "UA-3FX", - .ifnum = QUIRK_ANY_INTERFACE, - .type = QUIRK_COMPOSITE, - .data = (const struct snd_usb_audio_quirk[]) { - { - .ifnum = 1, - .type = QUIRK_AUDIO_STANDARD_INTERFACE - }, - { - .ifnum = 2, - .type = QUIRK_AUDIO_STANDARD_INTERFACE - }, - { - .ifnum = -1 - } + QUIRK_DATA_COMPOSITE { + { QUIRK_DATA_STANDARD_AUDIO(1) }, + { QUIRK_DATA_STANDARD_AUDIO(2) }, + QUIRK_COMPOSITE_END } } }, { USB_DEVICE(0x0582, 0x0052), - .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { + QUIRK_DRIVER_INFO { .vendor_name = "EDIROL", .product_name = "UM-1SX", - .ifnum = 0, - .type = QUIRK_MIDI_STANDARD_INTERFACE + QUIRK_DATA_STANDARD_MIDI(0) } }, { USB_DEVICE(0x0582, 0x0060), - .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { + QUIRK_DRIVER_INFO { .vendor_name = "Roland", .product_name = "EXR Series", - .ifnum = 0, - .type = QUIRK_MIDI_STANDARD_INTERFACE + QUIRK_DATA_STANDARD_MIDI(0) } }, { /* has ID 0x0066 when not in "Advanced Driver" mode */ USB_DEVICE(0x0582, 0x0064), - .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { + QUIRK_DRIVER_INFO { /* .vendor_name = "EDIROL", */ /* .product_name = "PCR-1", */ - .ifnum = QUIRK_ANY_INTERFACE, - .type = QUIRK_COMPOSITE, - .data = (const struct snd_usb_audio_quirk[]) { - { - .ifnum = 1, - .type = QUIRK_AUDIO_STANDARD_INTERFACE - }, - { - .ifnum = 2, - .type = QUIRK_AUDIO_STANDARD_INTERFACE - }, - { - .ifnum = -1 - } + QUIRK_DATA_COMPOSITE { + { QUIRK_DATA_STANDARD_AUDIO(1) }, + { QUIRK_DATA_STANDARD_AUDIO(2) }, + QUIRK_COMPOSITE_END } } }, { /* has ID 0x0067 when not in "Advanced Driver" mode */ USB_DEVICE(0x0582, 0x0065), - .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { + QUIRK_DRIVER_INFO { /* .vendor_name = "EDIROL", */ /* .product_name = "PCR-1", */ - .ifnum = 0, - .type = QUIRK_MIDI_FIXED_ENDPOINT, - .data = & (const struct snd_usb_midi_endpoint_info) { + QUIRK_DATA_MIDI_FIXED_ENDPOINT(0) { .out_cables = 0x0001, .in_cables = 0x0003 } @@ -1404,12 +1047,10 @@ YAMAHA_DEVICE(0x7010, "UB99"), { /* has ID 0x006e when not in "Advanced Driver" mode */ USB_DEVICE(0x0582, 0x006d), - .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { + QUIRK_DRIVER_INFO { .vendor_name = "Roland", .product_name = "FANTOM-X", - .ifnum = 0, - .type = QUIRK_MIDI_FIXED_ENDPOINT, - .data = & (const struct snd_usb_midi_endpoint_info) { + QUIRK_DATA_MIDI_FIXED_ENDPOINT(0) { .out_cables = 0x0001, .in_cables = 0x0001 } @@ -1422,39 +1063,24 @@ YAMAHA_DEVICE(0x7010, "UB99"), * offers only 16-bit PCM at 44.1 kHz and no MIDI. */ USB_DEVICE_VENDOR_SPEC(0x0582, 0x0074), - .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { + QUIRK_DRIVER_INFO { .vendor_name = "EDIROL", .product_name = "UA-25", - .ifnum = QUIRK_ANY_INTERFACE, - .type = QUIRK_COMPOSITE, - .data = (const struct snd_usb_audio_quirk[]) { - { - .ifnum = 0, - .type = QUIRK_AUDIO_EDIROL_UAXX - }, - { - .ifnum = 1, - .type = QUIRK_AUDIO_EDIROL_UAXX - }, - { - .ifnum = 2, - .type = QUIRK_AUDIO_EDIROL_UAXX - }, - { - .ifnum = -1 - } + QUIRK_DATA_COMPOSITE { + { QUIRK_DATA_EDIROL_UAXX(0) }, + { QUIRK_DATA_EDIROL_UAXX(1) }, + { QUIRK_DATA_EDIROL_UAXX(2) }, + QUIRK_COMPOSITE_END } } }, { /* has ID 0x0076 when not in "Advanced Driver" mode */ USB_DEVICE(0x0582, 0x0075), - .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { + QUIRK_DRIVER_INFO { .vendor_name = "BOSS", .product_name = "DR-880", - .ifnum = 0, - .type = QUIRK_MIDI_FIXED_ENDPOINT, - .data = & (const struct snd_usb_midi_endpoint_info) { + QUIRK_DATA_MIDI_FIXED_ENDPOINT(0) { .out_cables = 0x0001, .in_cables = 0x0001 } @@ -1463,12 +1089,10 @@ YAMAHA_DEVICE(0x7010, "UB99"), { /* has ID 0x007b when not in "Advanced Driver" mode */ USB_DEVICE_VENDOR_SPEC(0x0582, 0x007a), - .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { + QUIRK_DRIVER_INFO { .vendor_name = "Roland", /* "RD" or "RD-700SX"? */ - .ifnum = 0, - .type = QUIRK_MIDI_FIXED_ENDPOINT, - .data = & (const struct snd_usb_midi_endpoint_info) { + QUIRK_DATA_MIDI_FIXED_ENDPOINT(0) { .out_cables = 0x0003, .in_cables = 0x0003 } @@ -1477,12 +1101,10 @@ YAMAHA_DEVICE(0x7010, "UB99"), { /* has ID 0x0081 when not in "Advanced Driver" mode */ USB_DEVICE(0x0582, 0x0080), - .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { + QUIRK_DRIVER_INFO { .vendor_name = "Roland", .product_name = "G-70", - .ifnum = 0, - .type = QUIRK_MIDI_FIXED_ENDPOINT, - .data = & (const struct snd_usb_midi_endpoint_info) { + QUIRK_DATA_MIDI_FIXED_ENDPOINT(0) { .out_cables = 0x0001, .in_cables = 0x0001 } @@ -1491,12 +1113,10 @@ YAMAHA_DEVICE(0x7010, "UB99"), { /* has ID 0x008c when not in "Advanced Driver" mode */ USB_DEVICE(0x0582, 0x008b), - .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { + QUIRK_DRIVER_INFO { .vendor_name = "EDIROL", .product_name = "PC-50", - .ifnum = 0, - .type = QUIRK_MIDI_FIXED_ENDPOINT, - .data = & (const struct snd_usb_midi_endpoint_info) { + QUIRK_DATA_MIDI_FIXED_ENDPOINT(0) { .out_cables = 0x0001, .in_cables = 0x0001 } @@ -1508,56 +1128,31 @@ YAMAHA_DEVICE(0x7010, "UB99"), * is standard compliant, but has only 16-bit PCM and no MIDI. */ USB_DEVICE(0x0582, 0x00a3), - .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { + QUIRK_DRIVER_INFO { .vendor_name = "EDIROL", .product_name = "UA-4FX", - .ifnum = QUIRK_ANY_INTERFACE, - .type = QUIRK_COMPOSITE, - .data = (const struct snd_usb_audio_quirk[]) { - { - .ifnum = 0, - .type = QUIRK_AUDIO_EDIROL_UAXX - }, - { - .ifnum = 1, - .type = QUIRK_AUDIO_EDIROL_UAXX - }, - { - .ifnum = 2, - .type = QUIRK_AUDIO_EDIROL_UAXX - }, - { - .ifnum = -1 - } + QUIRK_DATA_COMPOSITE { + { QUIRK_DATA_EDIROL_UAXX(0) }, + { QUIRK_DATA_EDIROL_UAXX(1) }, + { QUIRK_DATA_EDIROL_UAXX(2) }, + QUIRK_COMPOSITE_END } } }, { /* Edirol M-16DX */ USB_DEVICE(0x0582, 0x00c4), - .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { - .ifnum = QUIRK_ANY_INTERFACE, - .type = QUIRK_COMPOSITE, - .data = (const struct snd_usb_audio_quirk[]) { + QUIRK_DRIVER_INFO { + QUIRK_DATA_COMPOSITE { + { QUIRK_DATA_STANDARD_AUDIO(0) }, + { QUIRK_DATA_STANDARD_AUDIO(1) }, { - .ifnum = 0, - .type = QUIRK_AUDIO_STANDARD_INTERFACE - }, - { - .ifnum = 1, - .type = QUIRK_AUDIO_STANDARD_INTERFACE - }, - { - .ifnum = 2, - .type = QUIRK_MIDI_FIXED_ENDPOINT, - .data = & (const struct snd_usb_midi_endpoint_info) { + QUIRK_DATA_MIDI_FIXED_ENDPOINT(2) { .out_cables = 0x0001, .in_cables = 0x0001 } }, - { - .ifnum = -1 - } + QUIRK_COMPOSITE_END } } }, @@ -1567,37 +1162,22 @@ YAMAHA_DEVICE(0x7010, "UB99"), * offers only 16-bit PCM at 44.1 kHz and no MIDI. */ USB_DEVICE_VENDOR_SPEC(0x0582, 0x00e6), - .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { + QUIRK_DRIVER_INFO { .vendor_name = "EDIROL", .product_name = "UA-25EX", - .ifnum = QUIRK_ANY_INTERFACE, - .type = QUIRK_COMPOSITE, - .data = (const struct snd_usb_audio_quirk[]) { - { - .ifnum = 0, - .type = QUIRK_AUDIO_EDIROL_UAXX - }, - { - .ifnum = 1, - .type = QUIRK_AUDIO_EDIROL_UAXX - }, - { - .ifnum = 2, - .type = QUIRK_AUDIO_EDIROL_UAXX - }, - { - .ifnum = -1 - } + QUIRK_DATA_COMPOSITE { + { QUIRK_DATA_EDIROL_UAXX(0) }, + { QUIRK_DATA_EDIROL_UAXX(1) }, + { QUIRK_DATA_EDIROL_UAXX(2) }, + QUIRK_COMPOSITE_END } } }, { /* Edirol UM-3G */ USB_DEVICE_VENDOR_SPEC(0x0582, 0x0108), - .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { - .ifnum = 0, - .type = QUIRK_MIDI_FIXED_ENDPOINT, - .data = & (const struct snd_usb_midi_endpoint_info) { + QUIRK_DRIVER_INFO { + QUIRK_DATA_MIDI_FIXED_ENDPOINT(0) { .out_cables = 0x0007, .in_cables = 0x0007 } @@ -1606,45 +1186,29 @@ YAMAHA_DEVICE(0x7010, "UB99"), { /* BOSS ME-25 */ USB_DEVICE(0x0582, 0x0113), - .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { - .ifnum = QUIRK_ANY_INTERFACE, - .type = QUIRK_COMPOSITE, - .data = (const struct snd_usb_audio_quirk[]) { + QUIRK_DRIVER_INFO { + QUIRK_DATA_COMPOSITE { + { QUIRK_DATA_STANDARD_AUDIO(0) }, + { QUIRK_DATA_STANDARD_AUDIO(1) }, { - .ifnum = 0, - .type = QUIRK_AUDIO_STANDARD_INTERFACE - }, - { - .ifnum = 1, - .type = QUIRK_AUDIO_STANDARD_INTERFACE - }, - { - .ifnum = 2, - .type = QUIRK_MIDI_FIXED_ENDPOINT, - .data = & (const struct snd_usb_midi_endpoint_info) { + QUIRK_DATA_MIDI_FIXED_ENDPOINT(2) { .out_cables = 0x0001, .in_cables = 0x0001 } }, - { - .ifnum = -1 - } + QUIRK_COMPOSITE_END } } }, { /* only 44.1 kHz works at the moment */ USB_DEVICE(0x0582, 0x0120), - .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { + QUIRK_DRIVER_INFO { /* .vendor_name = "Roland", */ /* .product_name = "OCTO-CAPTURE", */ - .ifnum = QUIRK_ANY_INTERFACE, - .type = QUIRK_COMPOSITE, - .data = (const struct snd_usb_audio_quirk[]) { + QUIRK_DATA_COMPOSITE { { - .ifnum = 0, - .type = QUIRK_AUDIO_FIXED_ENDPOINT, - .data = & (const struct audioformat) { + QUIRK_DATA_AUDIOFORMAT(0) { .formats = SNDRV_PCM_FMTBIT_S32_LE, .channels = 10, .iface = 0, @@ -1660,9 +1224,7 @@ YAMAHA_DEVICE(0x7010, "UB99"), } }, { - .ifnum = 1, - .type = QUIRK_AUDIO_FIXED_ENDPOINT, - .data = & (const struct audioformat) { + QUIRK_DATA_AUDIOFORMAT(1) { .formats = SNDRV_PCM_FMTBIT_S32_LE, .channels = 12, .iface = 1, @@ -1678,40 +1240,26 @@ YAMAHA_DEVICE(0x7010, "UB99"), } }, { - .ifnum = 2, - .type = QUIRK_MIDI_FIXED_ENDPOINT, - .data = & (const struct snd_usb_midi_endpoint_info) { + QUIRK_DATA_MIDI_FIXED_ENDPOINT(2) { .out_cables = 0x0001, .in_cables = 0x0001 } }, - { - .ifnum = 3, - .type = QUIRK_IGNORE_INTERFACE - }, - { - .ifnum = 4, - .type = QUIRK_IGNORE_INTERFACE - }, - { - .ifnum = -1 - } + { QUIRK_DATA_IGNORE(3) }, + { QUIRK_DATA_IGNORE(4) }, + QUIRK_COMPOSITE_END } } }, { /* only 44.1 kHz works at the moment */ USB_DEVICE(0x0582, 0x012f), - .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { + QUIRK_DRIVER_INFO { /* .vendor_name = "Roland", */ /* .product_name = "QUAD-CAPTURE", */ - .ifnum = QUIRK_ANY_INTERFACE, - .type = QUIRK_COMPOSITE, - .data = (const struct snd_usb_audio_quirk[]) { + QUIRK_DATA_COMPOSITE { { - .ifnum = 0, - .type = QUIRK_AUDIO_FIXED_ENDPOINT, - .data = & (const struct audioformat) { + QUIRK_DATA_AUDIOFORMAT(0) { .formats = SNDRV_PCM_FMTBIT_S32_LE, .channels = 4, .iface = 0, @@ -1727,9 +1275,7 @@ YAMAHA_DEVICE(0x7010, "UB99"), } }, { - .ifnum = 1, - .type = QUIRK_AUDIO_FIXED_ENDPOINT, - .data = & (const struct audioformat) { + QUIRK_DATA_AUDIOFORMAT(1) { .formats = SNDRV_PCM_FMTBIT_S32_LE, .channels = 6, .iface = 1, @@ -1745,54 +1291,32 @@ YAMAHA_DEVICE(0x7010, "UB99"), } }, { - .ifnum = 2, - .type = QUIRK_MIDI_FIXED_ENDPOINT, - .data = & (const struct snd_usb_midi_endpoint_info) { + QUIRK_DATA_MIDI_FIXED_ENDPOINT(2) { .out_cables = 0x0001, .in_cables = 0x0001 } }, - { - .ifnum = 3, - .type = QUIRK_IGNORE_INTERFACE - }, - { - .ifnum = 4, - .type = QUIRK_IGNORE_INTERFACE - }, - { - .ifnum = -1 - } + { QUIRK_DATA_IGNORE(3) }, + { QUIRK_DATA_IGNORE(4) }, + QUIRK_COMPOSITE_END } } }, { USB_DEVICE(0x0582, 0x0159), - .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { + QUIRK_DRIVER_INFO { /* .vendor_name = "Roland", */ /* .product_name = "UA-22", */ - .ifnum = QUIRK_ANY_INTERFACE, - .type = QUIRK_COMPOSITE, - .data = (const struct snd_usb_audio_quirk[]) { + QUIRK_DATA_COMPOSITE { + { QUIRK_DATA_STANDARD_AUDIO(0) }, + { QUIRK_DATA_STANDARD_AUDIO(1) }, { - .ifnum = 0, - .type = QUIRK_AUDIO_STANDARD_INTERFACE - }, - { - .ifnum = 1, - .type = QUIRK_AUDIO_STANDARD_INTERFACE - }, - { - .ifnum = 2, - .type = QUIRK_MIDI_FIXED_ENDPOINT, - .data = & (const struct snd_usb_midi_endpoint_info) { + QUIRK_DATA_MIDI_FIXED_ENDPOINT(2) { .out_cables = 0x0001, .in_cables = 0x0001 } }, - { - .ifnum = -1 - } + QUIRK_COMPOSITE_END } } }, @@ -1800,19 +1324,19 @@ YAMAHA_DEVICE(0x7010, "UB99"), /* UA101 and co are supported by another driver */ { USB_DEVICE(0x0582, 0x0044), /* UA-1000 high speed */ - .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { + QUIRK_DRIVER_INFO { .ifnum = QUIRK_NODEV_INTERFACE }, }, { USB_DEVICE(0x0582, 0x007d), /* UA-101 high speed */ - .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { + QUIRK_DRIVER_INFO { .ifnum = QUIRK_NODEV_INTERFACE }, }, { USB_DEVICE(0x0582, 0x008d), /* UA-101 full speed */ - .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { + QUIRK_DRIVER_INFO { .ifnum = QUIRK_NODEV_INTERFACE }, }, @@ -1823,7 +1347,7 @@ YAMAHA_DEVICE(0x7010, "UB99"), USB_DEVICE_ID_MATCH_INT_CLASS, .idVendor = 0x0582, .bInterfaceClass = USB_CLASS_VENDOR_SPEC, - .driver_info = (unsigned long) &(const struct snd_usb_audio_quirk) { + QUIRK_DRIVER_INFO { .ifnum = QUIRK_ANY_INTERFACE, .type = QUIRK_AUTODETECT } @@ -1838,12 +1362,10 @@ YAMAHA_DEVICE(0x7010, "UB99"), * compliant USB MIDI ports for external MIDI and controls. */ USB_DEVICE_VENDOR_SPEC(0x06f8, 0xb000), - .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { + QUIRK_DRIVER_INFO { .vendor_name = "Hercules", .product_name = "DJ Console (WE)", - .ifnum = 4, - .type = QUIRK_MIDI_FIXED_ENDPOINT, - .data = & (const struct snd_usb_midi_endpoint_info) { + QUIRK_DATA_MIDI_FIXED_ENDPOINT(4) { .out_cables = 0x0001, .in_cables = 0x0001 } @@ -1853,12 +1375,10 @@ YAMAHA_DEVICE(0x7010, "UB99"), /* Midiman/M-Audio devices */ { USB_DEVICE_VENDOR_SPEC(0x0763, 0x1002), - .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { + QUIRK_DRIVER_INFO { .vendor_name = "M-Audio", .product_name = "MidiSport 2x2", - .ifnum = QUIRK_ANY_INTERFACE, - .type = QUIRK_MIDI_MIDIMAN, - .data = & (const struct snd_usb_midi_endpoint_info) { + QUIRK_DATA_MIDI_MIDIMAN(QUIRK_ANY_INTERFACE) { .out_cables = 0x0003, .in_cables = 0x0003 } @@ -1866,12 +1386,10 @@ YAMAHA_DEVICE(0x7010, "UB99"), }, { USB_DEVICE_VENDOR_SPEC(0x0763, 0x1011), - .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { + QUIRK_DRIVER_INFO { .vendor_name = "M-Audio", .product_name = "MidiSport 1x1", - .ifnum = QUIRK_ANY_INTERFACE, - .type = QUIRK_MIDI_MIDIMAN, - .data = & (const struct snd_usb_midi_endpoint_info) { + QUIRK_DATA_MIDI_MIDIMAN(QUIRK_ANY_INTERFACE) { .out_cables = 0x0001, .in_cables = 0x0001 } @@ -1879,12 +1397,10 @@ YAMAHA_DEVICE(0x7010, "UB99"), }, { USB_DEVICE_VENDOR_SPEC(0x0763, 0x1015), - .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { + QUIRK_DRIVER_INFO { .vendor_name = "M-Audio", .product_name = "Keystation", - .ifnum = QUIRK_ANY_INTERFACE, - .type = QUIRK_MIDI_MIDIMAN, - .data = & (const struct snd_usb_midi_endpoint_info) { + QUIRK_DATA_MIDI_MIDIMAN(QUIRK_ANY_INTERFACE) { .out_cables = 0x0001, .in_cables = 0x0001 } @@ -1892,12 +1408,10 @@ YAMAHA_DEVICE(0x7010, "UB99"), }, { USB_DEVICE_VENDOR_SPEC(0x0763, 0x1021), - .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { + QUIRK_DRIVER_INFO { .vendor_name = "M-Audio", .product_name = "MidiSport 4x4", - .ifnum = QUIRK_ANY_INTERFACE, - .type = QUIRK_MIDI_MIDIMAN, - .data = & (const struct snd_usb_midi_endpoint_info) { + QUIRK_DATA_MIDI_MIDIMAN(QUIRK_ANY_INTERFACE) { .out_cables = 0x000f, .in_cables = 0x000f } @@ -1910,12 +1424,10 @@ YAMAHA_DEVICE(0x7010, "UB99"), * Thanks to Olaf Giesbrecht */ USB_DEVICE_VER(0x0763, 0x1031, 0x0100, 0x0109), - .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { + QUIRK_DRIVER_INFO { .vendor_name = "M-Audio", .product_name = "MidiSport 8x8", - .ifnum = QUIRK_ANY_INTERFACE, - .type = QUIRK_MIDI_MIDIMAN, - .data = & (const struct snd_usb_midi_endpoint_info) { + QUIRK_DATA_MIDI_MIDIMAN(QUIRK_ANY_INTERFACE) { .out_cables = 0x01ff, .in_cables = 0x01ff } @@ -1923,12 +1435,10 @@ YAMAHA_DEVICE(0x7010, "UB99"), }, { USB_DEVICE_VENDOR_SPEC(0x0763, 0x1033), - .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { + QUIRK_DRIVER_INFO { .vendor_name = "M-Audio", .product_name = "MidiSport 8x8", - .ifnum = QUIRK_ANY_INTERFACE, - .type = QUIRK_MIDI_MIDIMAN, - .data = & (const struct snd_usb_midi_endpoint_info) { + QUIRK_DATA_MIDI_MIDIMAN(QUIRK_ANY_INTERFACE) { .out_cables = 0x01ff, .in_cables = 0x01ff } @@ -1936,12 +1446,10 @@ YAMAHA_DEVICE(0x7010, "UB99"), }, { USB_DEVICE_VENDOR_SPEC(0x0763, 0x1041), - .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { + QUIRK_DRIVER_INFO { .vendor_name = "M-Audio", .product_name = "MidiSport 2x4", - .ifnum = QUIRK_ANY_INTERFACE, - .type = QUIRK_MIDI_MIDIMAN, - .data = & (const struct snd_usb_midi_endpoint_info) { + QUIRK_DATA_MIDI_MIDIMAN(QUIRK_ANY_INTERFACE) { .out_cables = 0x000f, .in_cables = 0x0003 } @@ -1949,76 +1457,41 @@ YAMAHA_DEVICE(0x7010, "UB99"), }, { USB_DEVICE_VENDOR_SPEC(0x0763, 0x2001), - .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { + QUIRK_DRIVER_INFO { .vendor_name = "M-Audio", .product_name = "Quattro", - .ifnum = QUIRK_ANY_INTERFACE, - .type = QUIRK_COMPOSITE, - .data = & (const struct snd_usb_audio_quirk[]) { + QUIRK_DATA_COMPOSITE { /* * Interfaces 0-2 are "Windows-compatible", 16-bit only, * and share endpoints with the other interfaces. * Ignore them. The other interfaces can do 24 bits, * but captured samples are big-endian (see usbaudio.c). */ + { QUIRK_DATA_IGNORE(0) }, + { QUIRK_DATA_IGNORE(1) }, + { QUIRK_DATA_IGNORE(2) }, + { QUIRK_DATA_IGNORE(3) }, + { QUIRK_DATA_STANDARD_AUDIO(4) }, + { QUIRK_DATA_STANDARD_AUDIO(5) }, + { QUIRK_DATA_IGNORE(6) }, + { QUIRK_DATA_STANDARD_AUDIO(7) }, + { QUIRK_DATA_STANDARD_AUDIO(8) }, { - .ifnum = 0, - .type = QUIRK_IGNORE_INTERFACE - }, - { - .ifnum = 1, - .type = QUIRK_IGNORE_INTERFACE - }, - { - .ifnum = 2, - .type = QUIRK_IGNORE_INTERFACE - }, - { - .ifnum = 3, - .type = QUIRK_IGNORE_INTERFACE - }, - { - .ifnum = 4, - .type = QUIRK_AUDIO_STANDARD_INTERFACE - }, - { - .ifnum = 5, - .type = QUIRK_AUDIO_STANDARD_INTERFACE - }, - { - .ifnum = 6, - .type = QUIRK_IGNORE_INTERFACE - }, - { - .ifnum = 7, - .type = QUIRK_AUDIO_STANDARD_INTERFACE - }, - { - .ifnum = 8, - .type = QUIRK_AUDIO_STANDARD_INTERFACE - }, - { - .ifnum = 9, - .type = QUIRK_MIDI_MIDIMAN, - .data = & (const struct snd_usb_midi_endpoint_info) { + QUIRK_DATA_MIDI_MIDIMAN(9) { .out_cables = 0x0001, .in_cables = 0x0001 } }, - { - .ifnum = -1 - } + QUIRK_COMPOSITE_END } } }, { USB_DEVICE_VENDOR_SPEC(0x0763, 0x2003), - .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { + QUIRK_DRIVER_INFO { .vendor_name = "M-Audio", .product_name = "AudioPhile", - .ifnum = 6, - .type = QUIRK_MIDI_MIDIMAN, - .data = & (const struct snd_usb_midi_endpoint_info) { + QUIRK_DATA_MIDI_MIDIMAN(6) { .out_cables = 0x0001, .in_cables = 0x0001 } @@ -2026,12 +1499,10 @@ YAMAHA_DEVICE(0x7010, "UB99"), }, { USB_DEVICE_VENDOR_SPEC(0x0763, 0x2008), - .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { + QUIRK_DRIVER_INFO { .vendor_name = "M-Audio", .product_name = "Ozone", - .ifnum = 3, - .type = QUIRK_MIDI_MIDIMAN, - .data = & (const struct snd_usb_midi_endpoint_info) { + QUIRK_DATA_MIDI_MIDIMAN(3) { .out_cables = 0x0001, .in_cables = 0x0001 } @@ -2039,93 +1510,45 @@ YAMAHA_DEVICE(0x7010, "UB99"), }, { USB_DEVICE_VENDOR_SPEC(0x0763, 0x200d), - .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { + QUIRK_DRIVER_INFO { .vendor_name = "M-Audio", .product_name = "OmniStudio", - .ifnum = QUIRK_ANY_INTERFACE, - .type = QUIRK_COMPOSITE, - .data = & (const struct snd_usb_audio_quirk[]) { + QUIRK_DATA_COMPOSITE { + { QUIRK_DATA_IGNORE(0) }, + { QUIRK_DATA_IGNORE(1) }, + { QUIRK_DATA_IGNORE(2) }, + { QUIRK_DATA_IGNORE(3) }, + { QUIRK_DATA_STANDARD_AUDIO(4) }, + { QUIRK_DATA_STANDARD_AUDIO(5) }, + { QUIRK_DATA_IGNORE(6) }, + { QUIRK_DATA_STANDARD_AUDIO(7) }, + { QUIRK_DATA_STANDARD_AUDIO(8) }, { - .ifnum = 0, - .type = QUIRK_IGNORE_INTERFACE - }, - { - .ifnum = 1, - .type = QUIRK_IGNORE_INTERFACE - }, - { - .ifnum = 2, - .type = QUIRK_IGNORE_INTERFACE - }, - { - .ifnum = 3, - .type = QUIRK_IGNORE_INTERFACE - }, - { - .ifnum = 4, - .type = QUIRK_AUDIO_STANDARD_INTERFACE - }, - { - .ifnum = 5, - .type = QUIRK_AUDIO_STANDARD_INTERFACE - }, - { - .ifnum = 6, - .type = QUIRK_IGNORE_INTERFACE - }, - { - .ifnum = 7, - .type = QUIRK_AUDIO_STANDARD_INTERFACE - }, - { - .ifnum = 8, - .type = QUIRK_AUDIO_STANDARD_INTERFACE - }, - { - .ifnum = 9, - .type = QUIRK_MIDI_MIDIMAN, - .data = & (const struct snd_usb_midi_endpoint_info) { + QUIRK_DATA_MIDI_MIDIMAN(9) { .out_cables = 0x0001, .in_cables = 0x0001 } }, - { - .ifnum = -1 - } + QUIRK_COMPOSITE_END } } }, { USB_DEVICE(0x0763, 0x2019), - .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { + QUIRK_DRIVER_INFO { /* .vendor_name = "M-Audio", */ /* .product_name = "Ozone Academic", */ - .ifnum = QUIRK_ANY_INTERFACE, - .type = QUIRK_COMPOSITE, - .data = & (const struct snd_usb_audio_quirk[]) { + QUIRK_DATA_COMPOSITE { + { QUIRK_DATA_STANDARD_AUDIO(0) }, + { QUIRK_DATA_STANDARD_AUDIO(1) }, + { QUIRK_DATA_STANDARD_AUDIO(2) }, { - .ifnum = 0, - .type = QUIRK_AUDIO_STANDARD_INTERFACE - }, - { - .ifnum = 1, - .type = QUIRK_AUDIO_STANDARD_INTERFACE - }, - { - .ifnum = 2, - .type = QUIRK_AUDIO_STANDARD_INTERFACE - }, - { - .ifnum = 3, - .type = QUIRK_MIDI_MIDIMAN, - .data = & (const struct snd_usb_midi_endpoint_info) { + QUIRK_DATA_MIDI_MIDIMAN(3) { .out_cables = 0x0001, .in_cables = 0x0001 } }, - { - .ifnum = -1 - } + QUIRK_COMPOSITE_END } } }, @@ -2135,21 +1558,14 @@ YAMAHA_DEVICE(0x7010, "UB99"), }, { USB_DEVICE_VENDOR_SPEC(0x0763, 0x2030), - .driver_info = (unsigned long) &(const struct snd_usb_audio_quirk) { + QUIRK_DRIVER_INFO { /* .vendor_name = "M-Audio", */ /* .product_name = "Fast Track C400", */ - .ifnum = QUIRK_ANY_INTERFACE, - .type = QUIRK_COMPOSITE, - .data = &(const struct snd_usb_audio_quirk[]) { - { - .ifnum = 1, - .type = QUIRK_AUDIO_STANDARD_MIXER, - }, + QUIRK_DATA_COMPOSITE { + { QUIRK_DATA_STANDARD_MIXER(1) }, /* Playback */ { - .ifnum = 2, - .type = QUIRK_AUDIO_FIXED_ENDPOINT, - .data = &(const struct audioformat) { + QUIRK_DATA_AUDIOFORMAT(2) { .formats = SNDRV_PCM_FMTBIT_S24_3LE, .channels = 6, .iface = 2, @@ -2173,9 +1589,7 @@ YAMAHA_DEVICE(0x7010, "UB99"), }, /* Capture */ { - .ifnum = 3, - .type = QUIRK_AUDIO_FIXED_ENDPOINT, - .data = &(const struct audioformat) { + QUIRK_DATA_AUDIOFORMAT(3) { .formats = SNDRV_PCM_FMTBIT_S24_3LE, .channels = 4, .iface = 3, @@ -2197,30 +1611,21 @@ YAMAHA_DEVICE(0x7010, "UB99"), .clock = 0x80, } }, - /* MIDI */ - { - .ifnum = -1 /* Interface = 4 */ - } + /* MIDI: Interface = 4*/ + QUIRK_COMPOSITE_END } } }, { USB_DEVICE_VENDOR_SPEC(0x0763, 0x2031), - .driver_info = (unsigned long) &(const struct snd_usb_audio_quirk) { + QUIRK_DRIVER_INFO { /* .vendor_name = "M-Audio", */ /* .product_name = "Fast Track C600", */ - .ifnum = QUIRK_ANY_INTERFACE, - .type = QUIRK_COMPOSITE, - .data = &(const struct snd_usb_audio_quirk[]) { - { - .ifnum = 1, - .type = QUIRK_AUDIO_STANDARD_MIXER, - }, + QUIRK_DATA_COMPOSITE { + { QUIRK_DATA_STANDARD_MIXER(1) }, /* Playback */ { - .ifnum = 2, - .type = QUIRK_AUDIO_FIXED_ENDPOINT, - .data = &(const struct audioformat) { + QUIRK_DATA_AUDIOFORMAT(2) { .formats = SNDRV_PCM_FMTBIT_S24_3LE, .channels = 8, .iface = 2, @@ -2244,9 +1649,7 @@ YAMAHA_DEVICE(0x7010, "UB99"), }, /* Capture */ { - .ifnum = 3, - .type = QUIRK_AUDIO_FIXED_ENDPOINT, - .data = &(const struct audioformat) { + QUIRK_DATA_AUDIOFORMAT(3) { .formats = SNDRV_PCM_FMTBIT_S24_3LE, .channels = 6, .iface = 3, @@ -2268,29 +1671,20 @@ YAMAHA_DEVICE(0x7010, "UB99"), .clock = 0x80, } }, - /* MIDI */ - { - .ifnum = -1 /* Interface = 4 */ - } + /* MIDI: Interface = 4 */ + QUIRK_COMPOSITE_END } } }, { USB_DEVICE_VENDOR_SPEC(0x0763, 0x2080), - .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { + QUIRK_DRIVER_INFO { /* .vendor_name = "M-Audio", */ /* .product_name = "Fast Track Ultra", */ - .ifnum = QUIRK_ANY_INTERFACE, - .type = QUIRK_COMPOSITE, - .data = & (const struct snd_usb_audio_quirk[]) { + QUIRK_DATA_COMPOSITE { + { QUIRK_DATA_STANDARD_MIXER(0) }, { - .ifnum = 0, - .type = QUIRK_AUDIO_STANDARD_MIXER, - }, - { - .ifnum = 1, - .type = QUIRK_AUDIO_FIXED_ENDPOINT, - .data = & (const struct audioformat) { + QUIRK_DATA_AUDIOFORMAT(1) { .formats = SNDRV_PCM_FMTBIT_S24_3LE, .channels = 8, .iface = 1, @@ -2312,9 +1706,7 @@ YAMAHA_DEVICE(0x7010, "UB99"), } }, { - .ifnum = 2, - .type = QUIRK_AUDIO_FIXED_ENDPOINT, - .data = & (const struct audioformat) { + QUIRK_DATA_AUDIOFORMAT(2) { .formats = SNDRV_PCM_FMTBIT_S24_3LE, .channels = 8, .iface = 2, @@ -2336,28 +1728,19 @@ YAMAHA_DEVICE(0x7010, "UB99"), } }, /* interface 3 (MIDI) is standard compliant */ - { - .ifnum = -1 - } + QUIRK_COMPOSITE_END } } }, { USB_DEVICE_VENDOR_SPEC(0x0763, 0x2081), - .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { + QUIRK_DRIVER_INFO { /* .vendor_name = "M-Audio", */ /* .product_name = "Fast Track Ultra 8R", */ - .ifnum = QUIRK_ANY_INTERFACE, - .type = QUIRK_COMPOSITE, - .data = & (const struct snd_usb_audio_quirk[]) { + QUIRK_DATA_COMPOSITE { + { QUIRK_DATA_STANDARD_MIXER(0) }, { - .ifnum = 0, - .type = QUIRK_AUDIO_STANDARD_MIXER, - }, - { - .ifnum = 1, - .type = QUIRK_AUDIO_FIXED_ENDPOINT, - .data = & (const struct audioformat) { + QUIRK_DATA_AUDIOFORMAT(1) { .formats = SNDRV_PCM_FMTBIT_S24_3LE, .channels = 8, .iface = 1, @@ -2379,9 +1762,7 @@ YAMAHA_DEVICE(0x7010, "UB99"), } }, { - .ifnum = 2, - .type = QUIRK_AUDIO_FIXED_ENDPOINT, - .data = & (const struct audioformat) { + QUIRK_DATA_AUDIOFORMAT(2) { .formats = SNDRV_PCM_FMTBIT_S24_3LE, .channels = 8, .iface = 2, @@ -2403,9 +1784,7 @@ YAMAHA_DEVICE(0x7010, "UB99"), } }, /* interface 3 (MIDI) is standard compliant */ - { - .ifnum = -1 - } + QUIRK_COMPOSITE_END } } }, @@ -2413,21 +1792,19 @@ YAMAHA_DEVICE(0x7010, "UB99"), /* Casio devices */ { USB_DEVICE(0x07cf, 0x6801), - .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { + QUIRK_DRIVER_INFO { .vendor_name = "Casio", .product_name = "PL-40R", - .ifnum = 0, - .type = QUIRK_MIDI_YAMAHA + QUIRK_DATA_MIDI_YAMAHA(0) } }, { /* this ID is used by several devices without a product ID */ USB_DEVICE(0x07cf, 0x6802), - .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { + QUIRK_DRIVER_INFO { .vendor_name = "Casio", .product_name = "Keyboard", - .ifnum = 0, - .type = QUIRK_MIDI_YAMAHA + QUIRK_DATA_MIDI_YAMAHA(0) } }, @@ -2440,23 +1817,13 @@ YAMAHA_DEVICE(0x7010, "UB99"), .idVendor = 0x07fd, .idProduct = 0x0001, .bDeviceSubClass = 2, - .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { + QUIRK_DRIVER_INFO { .vendor_name = "MOTU", .product_name = "Fastlane", - .ifnum = QUIRK_ANY_INTERFACE, - .type = QUIRK_COMPOSITE, - .data = & (const struct snd_usb_audio_quirk[]) { - { - .ifnum = 0, - .type = QUIRK_MIDI_RAW_BYTES - }, - { - .ifnum = 1, - .type = QUIRK_IGNORE_INTERFACE - }, - { - .ifnum = -1 - } + QUIRK_DATA_COMPOSITE { + { QUIRK_DATA_RAW_BYTES(0) }, + { QUIRK_DATA_IGNORE(1) }, + QUIRK_COMPOSITE_END } } }, @@ -2464,12 +1831,10 @@ YAMAHA_DEVICE(0x7010, "UB99"), /* Emagic devices */ { USB_DEVICE(0x086a, 0x0001), - .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { + QUIRK_DRIVER_INFO { .vendor_name = "Emagic", .product_name = "Unitor8", - .ifnum = 2, - .type = QUIRK_MIDI_EMAGIC, - .data = & (const struct snd_usb_midi_endpoint_info) { + QUIRK_DATA_MIDI_EMAGIC(2) { .out_cables = 0x80ff, .in_cables = 0x80ff } @@ -2477,12 +1842,10 @@ YAMAHA_DEVICE(0x7010, "UB99"), }, { USB_DEVICE(0x086a, 0x0002), - .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { + QUIRK_DRIVER_INFO { .vendor_name = "Emagic", /* .product_name = "AMT8", */ - .ifnum = 2, - .type = QUIRK_MIDI_EMAGIC, - .data = & (const struct snd_usb_midi_endpoint_info) { + QUIRK_DATA_MIDI_EMAGIC(2) { .out_cables = 0x80ff, .in_cables = 0x80ff } @@ -2490,12 +1853,10 @@ YAMAHA_DEVICE(0x7010, "UB99"), }, { USB_DEVICE(0x086a, 0x0003), - .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { + QUIRK_DRIVER_INFO { .vendor_name = "Emagic", /* .product_name = "MT4", */ - .ifnum = 2, - .type = QUIRK_MIDI_EMAGIC, - .data = & (const struct snd_usb_midi_endpoint_info) { + QUIRK_DATA_MIDI_EMAGIC(2) { .out_cables = 0x800f, .in_cables = 0x8003 } @@ -2505,38 +1866,35 @@ YAMAHA_DEVICE(0x7010, "UB99"), /* KORG devices */ { USB_DEVICE_VENDOR_SPEC(0x0944, 0x0200), - .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { + QUIRK_DRIVER_INFO { .vendor_name = "KORG, Inc.", /* .product_name = "PANDORA PX5D", */ - .ifnum = 3, - .type = QUIRK_MIDI_STANDARD_INTERFACE, + QUIRK_DATA_STANDARD_MIDI(3) } }, { USB_DEVICE_VENDOR_SPEC(0x0944, 0x0201), - .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { + QUIRK_DRIVER_INFO { .vendor_name = "KORG, Inc.", /* .product_name = "ToneLab ST", */ - .ifnum = 3, - .type = QUIRK_MIDI_STANDARD_INTERFACE, + QUIRK_DATA_STANDARD_MIDI(3) } }, { USB_DEVICE_VENDOR_SPEC(0x0944, 0x0204), - .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { + QUIRK_DRIVER_INFO { .vendor_name = "KORG, Inc.", /* .product_name = "ToneLab EX", */ - .ifnum = 3, - .type = QUIRK_MIDI_STANDARD_INTERFACE, + QUIRK_DATA_STANDARD_MIDI(3) } }, /* AKAI devices */ { USB_DEVICE(0x09e8, 0x0062), - .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { + QUIRK_DRIVER_INFO { .vendor_name = "AKAI", .product_name = "MPD16", .ifnum = 0, @@ -2547,21 +1905,11 @@ YAMAHA_DEVICE(0x7010, "UB99"), { /* Akai MPC Element */ USB_DEVICE(0x09e8, 0x0021), - .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { - .ifnum = QUIRK_ANY_INTERFACE, - .type = QUIRK_COMPOSITE, - .data = & (const struct snd_usb_audio_quirk[]) { - { - .ifnum = 0, - .type = QUIRK_IGNORE_INTERFACE - }, - { - .ifnum = 1, - .type = QUIRK_MIDI_STANDARD_INTERFACE - }, - { - .ifnum = -1 - } + QUIRK_DRIVER_INFO { + QUIRK_DATA_COMPOSITE { + { QUIRK_DATA_IGNORE(0) }, + { QUIRK_DATA_STANDARD_MIDI(1) }, + QUIRK_COMPOSITE_END } } }, @@ -2570,66 +1918,36 @@ YAMAHA_DEVICE(0x7010, "UB99"), { /* Steinberg MI2 */ USB_DEVICE_VENDOR_SPEC(0x0a4e, 0x2040), - .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { - .ifnum = QUIRK_ANY_INTERFACE, - .type = QUIRK_COMPOSITE, - .data = & (const struct snd_usb_audio_quirk[]) { + QUIRK_DRIVER_INFO { + QUIRK_DATA_COMPOSITE { + { QUIRK_DATA_STANDARD_AUDIO(0) }, + { QUIRK_DATA_STANDARD_AUDIO(1) }, + { QUIRK_DATA_STANDARD_AUDIO(2) }, { - .ifnum = 0, - .type = QUIRK_AUDIO_STANDARD_INTERFACE - }, - { - .ifnum = 1, - .type = QUIRK_AUDIO_STANDARD_INTERFACE - }, - { - .ifnum = 2, - .type = QUIRK_AUDIO_STANDARD_INTERFACE - }, - { - .ifnum = 3, - .type = QUIRK_MIDI_FIXED_ENDPOINT, - .data = &(const struct snd_usb_midi_endpoint_info) { + QUIRK_DATA_MIDI_FIXED_ENDPOINT(3) { .out_cables = 0x0001, .in_cables = 0x0001 } }, - { - .ifnum = -1 - } + QUIRK_COMPOSITE_END } } }, { /* Steinberg MI4 */ USB_DEVICE_VENDOR_SPEC(0x0a4e, 0x4040), - .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { - .ifnum = QUIRK_ANY_INTERFACE, - .type = QUIRK_COMPOSITE, - .data = & (const struct snd_usb_audio_quirk[]) { + QUIRK_DRIVER_INFO { + QUIRK_DATA_COMPOSITE { + { QUIRK_DATA_STANDARD_AUDIO(0) }, + { QUIRK_DATA_STANDARD_AUDIO(1) }, + { QUIRK_DATA_STANDARD_AUDIO(2) }, { - .ifnum = 0, - .type = QUIRK_AUDIO_STANDARD_INTERFACE - }, - { - .ifnum = 1, - .type = QUIRK_AUDIO_STANDARD_INTERFACE - }, - { - .ifnum = 2, - .type = QUIRK_AUDIO_STANDARD_INTERFACE - }, - { - .ifnum = 3, - .type = QUIRK_MIDI_FIXED_ENDPOINT, - .data = &(const struct snd_usb_midi_endpoint_info) { + QUIRK_DATA_MIDI_FIXED_ENDPOINT(3) { .out_cables = 0x0001, .in_cables = 0x0001 } }, - { - .ifnum = -1 - } + QUIRK_COMPOSITE_END } } }, @@ -2637,34 +1955,31 @@ YAMAHA_DEVICE(0x7010, "UB99"), /* TerraTec devices */ { USB_DEVICE_VENDOR_SPEC(0x0ccd, 0x0012), - .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { + QUIRK_DRIVER_INFO { .vendor_name = "TerraTec", .product_name = "PHASE 26", - .ifnum = 3, - .type = QUIRK_MIDI_STANDARD_INTERFACE + QUIRK_DATA_STANDARD_MIDI(3) } }, { USB_DEVICE_VENDOR_SPEC(0x0ccd, 0x0013), - .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { + QUIRK_DRIVER_INFO { .vendor_name = "TerraTec", .product_name = "PHASE 26", - .ifnum = 3, - .type = QUIRK_MIDI_STANDARD_INTERFACE + QUIRK_DATA_STANDARD_MIDI(3) } }, { USB_DEVICE_VENDOR_SPEC(0x0ccd, 0x0014), - .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { + QUIRK_DRIVER_INFO { .vendor_name = "TerraTec", .product_name = "PHASE 26", - .ifnum = 3, - .type = QUIRK_MIDI_STANDARD_INTERFACE + QUIRK_DATA_STANDARD_MIDI(3) } }, { USB_DEVICE(0x0ccd, 0x0035), - .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { + QUIRK_DRIVER_INFO { .vendor_name = "Miditech", .product_name = "Play'n Roll", .ifnum = 0, @@ -2679,7 +1994,7 @@ YAMAHA_DEVICE(0x7010, "UB99"), /* Novation EMS devices */ { USB_DEVICE_VENDOR_SPEC(0x1235, 0x0001), - .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { + QUIRK_DRIVER_INFO { .vendor_name = "Novation", .product_name = "ReMOTE Audio/XStation", .ifnum = 4, @@ -2688,7 +2003,7 @@ YAMAHA_DEVICE(0x7010, "UB99"), }, { USB_DEVICE_VENDOR_SPEC(0x1235, 0x0002), - .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { + QUIRK_DRIVER_INFO { .vendor_name = "Novation", .product_name = "Speedio", .ifnum = 3, @@ -2697,38 +2012,29 @@ YAMAHA_DEVICE(0x7010, "UB99"), }, { USB_DEVICE(0x1235, 0x000a), - .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { + QUIRK_DRIVER_INFO { /* .vendor_name = "Novation", */ /* .product_name = "Nocturn", */ - .ifnum = 0, - .type = QUIRK_MIDI_RAW_BYTES + QUIRK_DATA_RAW_BYTES(0) } }, { USB_DEVICE(0x1235, 0x000e), - .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { + QUIRK_DRIVER_INFO { /* .vendor_name = "Novation", */ /* .product_name = "Launchpad", */ - .ifnum = 0, - .type = QUIRK_MIDI_RAW_BYTES + QUIRK_DATA_RAW_BYTES(0) } }, { USB_DEVICE(0x1235, 0x0010), - .driver_info = (unsigned long) &(const struct snd_usb_audio_quirk) { + QUIRK_DRIVER_INFO { .vendor_name = "Focusrite", .product_name = "Saffire 6 USB", - .ifnum = QUIRK_ANY_INTERFACE, - .type = QUIRK_COMPOSITE, - .data = (const struct snd_usb_audio_quirk[]) { + QUIRK_DATA_COMPOSITE { + { QUIRK_DATA_STANDARD_MIXER(0) }, { - .ifnum = 0, - .type = QUIRK_AUDIO_STANDARD_MIXER, - }, - { - .ifnum = 0, - .type = QUIRK_AUDIO_FIXED_ENDPOINT, - .data = &(const struct audioformat) { + QUIRK_DATA_AUDIOFORMAT(0) { .formats = SNDRV_PCM_FMTBIT_S24_3LE, .channels = 4, .iface = 0, @@ -2755,9 +2061,7 @@ YAMAHA_DEVICE(0x7010, "UB99"), } }, { - .ifnum = 0, - .type = QUIRK_AUDIO_FIXED_ENDPOINT, - .data = &(const struct audioformat) { + QUIRK_DATA_AUDIOFORMAT(0) { .formats = SNDRV_PCM_FMTBIT_S24_3LE, .channels = 2, .iface = 0, @@ -2779,28 +2083,19 @@ YAMAHA_DEVICE(0x7010, "UB99"), } } }, - { - .ifnum = 1, - .type = QUIRK_MIDI_RAW_BYTES - }, - { - .ifnum = -1 - } + { QUIRK_DATA_RAW_BYTES(1) }, + QUIRK_COMPOSITE_END } } }, { USB_DEVICE(0x1235, 0x0018), - .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { + QUIRK_DRIVER_INFO { .vendor_name = "Novation", .product_name = "Twitch", - .ifnum = QUIRK_ANY_INTERFACE, - .type = QUIRK_COMPOSITE, - .data = (const struct snd_usb_audio_quirk[]) { + QUIRK_DATA_COMPOSITE { { - .ifnum = 0, - .type = QUIRK_AUDIO_FIXED_ENDPOINT, - .data = & (const struct audioformat) { + QUIRK_DATA_AUDIOFORMAT(0) { .formats = SNDRV_PCM_FMTBIT_S24_3LE, .channels = 4, .iface = 0, @@ -2819,19 +2114,14 @@ YAMAHA_DEVICE(0x7010, "UB99"), } } }, - { - .ifnum = 1, - .type = QUIRK_MIDI_RAW_BYTES - }, - { - .ifnum = -1 - } + { QUIRK_DATA_RAW_BYTES(1) }, + QUIRK_COMPOSITE_END } } }, { USB_DEVICE_VENDOR_SPEC(0x1235, 0x4661), - .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { + QUIRK_DRIVER_INFO { .vendor_name = "Novation", .product_name = "ReMOTE25", .ifnum = 0, @@ -2843,25 +2133,16 @@ YAMAHA_DEVICE(0x7010, "UB99"), { /* VirusTI Desktop */ USB_DEVICE_VENDOR_SPEC(0x133e, 0x0815), - .driver_info = (unsigned long) &(const struct snd_usb_audio_quirk) { - .ifnum = QUIRK_ANY_INTERFACE, - .type = QUIRK_COMPOSITE, - .data = &(const struct snd_usb_audio_quirk[]) { + QUIRK_DRIVER_INFO { + QUIRK_DATA_COMPOSITE { { - .ifnum = 3, - .type = QUIRK_MIDI_FIXED_ENDPOINT, - .data = &(const struct snd_usb_midi_endpoint_info) { + QUIRK_DATA_MIDI_FIXED_ENDPOINT(3) { .out_cables = 0x0003, .in_cables = 0x0003 } }, - { - .ifnum = 4, - .type = QUIRK_IGNORE_INTERFACE - }, - { - .ifnum = -1 - } + { QUIRK_DATA_IGNORE(4) }, + QUIRK_COMPOSITE_END } } }, @@ -2889,7 +2170,7 @@ YAMAHA_DEVICE(0x7010, "UB99"), /* QinHeng devices */ { USB_DEVICE(0x1a86, 0x752d), - .driver_info = (unsigned long) &(const struct snd_usb_audio_quirk) { + QUIRK_DRIVER_INFO { .vendor_name = "QinHeng", .product_name = "CH345", .ifnum = 1, @@ -2903,7 +2184,7 @@ YAMAHA_DEVICE(0x7010, "UB99"), /* Miditech devices */ { USB_DEVICE(0x4752, 0x0011), - .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { + QUIRK_DRIVER_INFO { .vendor_name = "Miditech", .product_name = "Midistart-2", .ifnum = 0, @@ -2915,7 +2196,7 @@ YAMAHA_DEVICE(0x7010, "UB99"), { /* this ID used by both Miditech MidiStudio-2 and CME UF-x */ USB_DEVICE(0x7104, 0x2202), - .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { + QUIRK_DRIVER_INFO { .ifnum = 0, .type = QUIRK_MIDI_CME } @@ -2925,20 +2206,13 @@ YAMAHA_DEVICE(0x7010, "UB99"), { /* Thanks to Clemens Ladisch */ USB_DEVICE(0x0dba, 0x1000), - .driver_info = (unsigned long) &(const struct snd_usb_audio_quirk) { + QUIRK_DRIVER_INFO { .vendor_name = "Digidesign", .product_name = "MBox", - .ifnum = QUIRK_ANY_INTERFACE, - .type = QUIRK_COMPOSITE, - .data = (const struct snd_usb_audio_quirk[]){ + QUIRK_DATA_COMPOSITE{ + { QUIRK_DATA_STANDARD_MIXER(0) }, { - .ifnum = 0, - .type = QUIRK_AUDIO_STANDARD_MIXER, - }, - { - .ifnum = 1, - .type = QUIRK_AUDIO_FIXED_ENDPOINT, - .data = &(const struct audioformat) { + QUIRK_DATA_AUDIOFORMAT(1) { .formats = SNDRV_PCM_FMTBIT_S24_3BE, .channels = 2, .iface = 1, @@ -2959,9 +2233,7 @@ YAMAHA_DEVICE(0x7010, "UB99"), } }, { - .ifnum = 1, - .type = QUIRK_AUDIO_FIXED_ENDPOINT, - .data = &(const struct audioformat) { + QUIRK_DATA_AUDIOFORMAT(1) { .formats = SNDRV_PCM_FMTBIT_S24_3BE, .channels = 2, .iface = 1, @@ -2982,9 +2254,7 @@ YAMAHA_DEVICE(0x7010, "UB99"), } } }, - { - .ifnum = -1 - } + QUIRK_COMPOSITE_END } } }, @@ -2992,24 +2262,14 @@ YAMAHA_DEVICE(0x7010, "UB99"), /* DIGIDESIGN MBOX 2 */ { USB_DEVICE(0x0dba, 0x3000), - .driver_info = (unsigned long) &(const struct snd_usb_audio_quirk) { + QUIRK_DRIVER_INFO { .vendor_name = "Digidesign", .product_name = "Mbox 2", - .ifnum = QUIRK_ANY_INTERFACE, - .type = QUIRK_COMPOSITE, - .data = (const struct snd_usb_audio_quirk[]) { + QUIRK_DATA_COMPOSITE { + { QUIRK_DATA_IGNORE(0) }, + { QUIRK_DATA_IGNORE(1) }, { - .ifnum = 0, - .type = QUIRK_IGNORE_INTERFACE - }, - { - .ifnum = 1, - .type = QUIRK_IGNORE_INTERFACE - }, - { - .ifnum = 2, - .type = QUIRK_AUDIO_FIXED_ENDPOINT, - .data = &(const struct audioformat) { + QUIRK_DATA_AUDIOFORMAT(2) { .formats = SNDRV_PCM_FMTBIT_S24_3BE, .channels = 2, .iface = 2, @@ -3027,15 +2287,10 @@ YAMAHA_DEVICE(0x7010, "UB99"), } } }, + { QUIRK_DATA_IGNORE(3) }, { - .ifnum = 3, - .type = QUIRK_IGNORE_INTERFACE - }, - { - .ifnum = 4, - .type = QUIRK_AUDIO_FIXED_ENDPOINT, - .data = &(const struct audioformat) { - .formats = SNDRV_PCM_FMTBIT_S24_3BE, + QUIRK_DATA_AUDIOFORMAT(4) { + .formats = SNDRV_PCM_FMTBIT_S24_3BE, .channels = 2, .iface = 4, .altsetting = 2, @@ -3052,14 +2307,9 @@ YAMAHA_DEVICE(0x7010, "UB99"), } } }, + { QUIRK_DATA_IGNORE(5) }, { - .ifnum = 5, - .type = QUIRK_IGNORE_INTERFACE - }, - { - .ifnum = 6, - .type = QUIRK_MIDI_MIDIMAN, - .data = &(const struct snd_usb_midi_endpoint_info) { + QUIRK_DATA_MIDI_MIDIMAN(6) { .out_ep = 0x02, .out_cables = 0x0001, .in_ep = 0x81, @@ -3067,33 +2317,21 @@ YAMAHA_DEVICE(0x7010, "UB99"), .in_cables = 0x0001 } }, - { - .ifnum = -1 - } + QUIRK_COMPOSITE_END } } }, /* DIGIDESIGN MBOX 3 */ { USB_DEVICE(0x0dba, 0x5000), - .driver_info = (unsigned long) &(const struct snd_usb_audio_quirk) { + QUIRK_DRIVER_INFO { .vendor_name = "Digidesign", .product_name = "Mbox 3", - .ifnum = QUIRK_ANY_INTERFACE, - .type = QUIRK_COMPOSITE, - .data = (const struct snd_usb_audio_quirk[]) { + QUIRK_DATA_COMPOSITE { + { QUIRK_DATA_IGNORE(0) }, + { QUIRK_DATA_IGNORE(1) }, { - .ifnum = 0, - .type = QUIRK_IGNORE_INTERFACE - }, - { - .ifnum = 1, - .type = QUIRK_IGNORE_INTERFACE - }, - { - .ifnum = 2, - .type = QUIRK_AUDIO_FIXED_ENDPOINT, - .data = &(const struct audioformat) { + QUIRK_DATA_AUDIOFORMAT(2) { .formats = SNDRV_PCM_FMTBIT_S24_3LE, .channels = 4, .iface = 2, @@ -3113,9 +2351,7 @@ YAMAHA_DEVICE(0x7010, "UB99"), } }, { - .ifnum = 3, - .type = QUIRK_AUDIO_FIXED_ENDPOINT, - .data = &(const struct audioformat) { + QUIRK_DATA_AUDIOFORMAT(3) { .formats = SNDRV_PCM_FMTBIT_S24_3LE, .channels = 4, .iface = 3, @@ -3136,36 +2372,25 @@ YAMAHA_DEVICE(0x7010, "UB99"), } }, { - .ifnum = 4, - .type = QUIRK_MIDI_FIXED_ENDPOINT, - .data = &(const struct snd_usb_midi_endpoint_info) { + QUIRK_DATA_MIDI_FIXED_ENDPOINT(4) { .out_cables = 0x0001, .in_cables = 0x0001 } }, - { - .ifnum = -1 - } + QUIRK_COMPOSITE_END } } }, { /* Tascam US122 MKII - playback-only support */ USB_DEVICE_VENDOR_SPEC(0x0644, 0x8021), - .driver_info = (unsigned long) &(const struct snd_usb_audio_quirk) { + QUIRK_DRIVER_INFO { .vendor_name = "TASCAM", .product_name = "US122 MKII", - .ifnum = QUIRK_ANY_INTERFACE, - .type = QUIRK_COMPOSITE, - .data = (const struct snd_usb_audio_quirk[]) { + QUIRK_DATA_COMPOSITE { + { QUIRK_DATA_IGNORE(0) }, { - .ifnum = 0, - .type = QUIRK_IGNORE_INTERFACE - }, - { - .ifnum = 1, - .type = QUIRK_AUDIO_FIXED_ENDPOINT, - .data = &(const struct audioformat) { + QUIRK_DATA_AUDIOFORMAT(1) { .formats = SNDRV_PCM_FMTBIT_S24_3LE, .channels = 2, .iface = 1, @@ -3186,9 +2411,7 @@ YAMAHA_DEVICE(0x7010, "UB99"), } } }, - { - .ifnum = -1 - } + QUIRK_COMPOSITE_END } } }, @@ -3196,20 +2419,13 @@ YAMAHA_DEVICE(0x7010, "UB99"), /* Denon DN-X1600 */ { USB_AUDIO_DEVICE(0x154e, 0x500e), - .driver_info = (unsigned long) &(const struct snd_usb_audio_quirk) { + QUIRK_DRIVER_INFO { .vendor_name = "Denon", .product_name = "DN-X1600", - .ifnum = QUIRK_ANY_INTERFACE, - .type = QUIRK_COMPOSITE, - .data = (const struct snd_usb_audio_quirk[]){ + QUIRK_DATA_COMPOSITE{ + { QUIRK_DATA_IGNORE(0) }, { - .ifnum = 0, - .type = QUIRK_IGNORE_INTERFACE, - }, - { - .ifnum = 1, - .type = QUIRK_AUDIO_FIXED_ENDPOINT, - .data = &(const struct audioformat) { + QUIRK_DATA_AUDIOFORMAT(1) { .formats = SNDRV_PCM_FMTBIT_S24_3LE, .channels = 8, .iface = 1, @@ -3230,9 +2446,7 @@ YAMAHA_DEVICE(0x7010, "UB99"), } }, { - .ifnum = 2, - .type = QUIRK_AUDIO_FIXED_ENDPOINT, - .data = &(const struct audioformat) { + QUIRK_DATA_AUDIOFORMAT(2) { .formats = SNDRV_PCM_FMTBIT_S24_3LE, .channels = 8, .iface = 2, @@ -3252,13 +2466,8 @@ YAMAHA_DEVICE(0x7010, "UB99"), } } }, - { - .ifnum = 4, - .type = QUIRK_MIDI_STANDARD_INTERFACE, - }, - { - .ifnum = -1 - } + { QUIRK_DATA_STANDARD_MIDI(4) }, + QUIRK_COMPOSITE_END } } }, @@ -3267,17 +2476,13 @@ YAMAHA_DEVICE(0x7010, "UB99"), { USB_DEVICE(0x045e, 0x0283), .bInterfaceClass = USB_CLASS_PER_INTERFACE, - .driver_info = (unsigned long) &(const struct snd_usb_audio_quirk) { + QUIRK_DRIVER_INFO { .vendor_name = "Microsoft", .product_name = "XboxLive Headset/Xbox Communicator", - .ifnum = QUIRK_ANY_INTERFACE, - .type = QUIRK_COMPOSITE, - .data = &(const struct snd_usb_audio_quirk[]) { + QUIRK_DATA_COMPOSITE { { /* playback */ - .ifnum = 0, - .type = QUIRK_AUDIO_FIXED_ENDPOINT, - .data = &(const struct audioformat) { + QUIRK_DATA_AUDIOFORMAT(0) { .formats = SNDRV_PCM_FMTBIT_S16_LE, .channels = 1, .iface = 0, @@ -3293,9 +2498,7 @@ YAMAHA_DEVICE(0x7010, "UB99"), }, { /* capture */ - .ifnum = 1, - .type = QUIRK_AUDIO_FIXED_ENDPOINT, - .data = &(const struct audioformat) { + QUIRK_DATA_AUDIOFORMAT(1) { .formats = SNDRV_PCM_FMTBIT_S16_LE, .channels = 1, .iface = 1, @@ -3309,9 +2512,7 @@ YAMAHA_DEVICE(0x7010, "UB99"), .rate_max = 16000 } }, - { - .ifnum = -1 - } + QUIRK_COMPOSITE_END } } }, @@ -3320,18 +2521,11 @@ YAMAHA_DEVICE(0x7010, "UB99"), { USB_DEVICE(0x200c, 0x100b), .bInterfaceClass = USB_CLASS_PER_INTERFACE, - .driver_info = (unsigned long) &(const struct snd_usb_audio_quirk) { - .ifnum = QUIRK_ANY_INTERFACE, - .type = QUIRK_COMPOSITE, - .data = &(const struct snd_usb_audio_quirk[]) { + QUIRK_DRIVER_INFO { + QUIRK_DATA_COMPOSITE { + { QUIRK_DATA_STANDARD_MIXER(0) }, { - .ifnum = 0, - .type = QUIRK_AUDIO_STANDARD_MIXER, - }, - { - .ifnum = 1, - .type = QUIRK_AUDIO_FIXED_ENDPOINT, - .data = &(const struct audioformat) { + QUIRK_DATA_AUDIOFORMAT(1) { .formats = SNDRV_PCM_FMTBIT_S24_3LE, .channels = 4, .iface = 1, @@ -3350,9 +2544,7 @@ YAMAHA_DEVICE(0x7010, "UB99"), } } }, - { - .ifnum = -1 - } + QUIRK_COMPOSITE_END } } }, @@ -3365,28 +2557,12 @@ YAMAHA_DEVICE(0x7010, "UB99"), * enabled in create_standard_audio_quirk(). */ USB_DEVICE(0x1686, 0x00dd), - .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { - .ifnum = QUIRK_ANY_INTERFACE, - .type = QUIRK_COMPOSITE, - .data = (const struct snd_usb_audio_quirk[]) { - { - /* Playback */ - .ifnum = 1, - .type = QUIRK_AUDIO_STANDARD_INTERFACE, - }, - { - /* Capture */ - .ifnum = 2, - .type = QUIRK_AUDIO_STANDARD_INTERFACE, - }, - { - /* Midi */ - .ifnum = 3, - .type = QUIRK_MIDI_STANDARD_INTERFACE - }, - { - .ifnum = -1 - }, + QUIRK_DRIVER_INFO { + QUIRK_DATA_COMPOSITE { + { QUIRK_DATA_STANDARD_AUDIO(1) }, /* Playback */ + { QUIRK_DATA_STANDARD_AUDIO(2) }, /* Capture */ + { QUIRK_DATA_STANDARD_MIDI(3) }, /* Midi */ + QUIRK_COMPOSITE_END } } }, @@ -3400,18 +2576,16 @@ YAMAHA_DEVICE(0x7010, "UB99"), USB_DEVICE_ID_MATCH_INT_SUBCLASS, .bInterfaceClass = USB_CLASS_AUDIO, .bInterfaceSubClass = USB_SUBCLASS_MIDISTREAMING, - .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { - .ifnum = QUIRK_ANY_INTERFACE, - .type = QUIRK_MIDI_STANDARD_INTERFACE + QUIRK_DRIVER_INFO { + QUIRK_DATA_STANDARD_MIDI(QUIRK_ANY_INTERFACE) } }, /* Rane SL-1 */ { USB_DEVICE(0x13e5, 0x0001), - .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { - .ifnum = QUIRK_ANY_INTERFACE, - .type = QUIRK_AUDIO_STANDARD_INTERFACE + QUIRK_DRIVER_INFO { + QUIRK_DATA_STANDARD_AUDIO(QUIRK_ANY_INTERFACE) } }, @@ -3427,24 +2601,13 @@ YAMAHA_DEVICE(0x7010, "UB99"), * and only the 48 kHz sample rate works for the playback interface. */ USB_DEVICE(0x0a12, 0x1243), - .driver_info = (unsigned long) &(const struct snd_usb_audio_quirk) { - .ifnum = QUIRK_ANY_INTERFACE, - .type = QUIRK_COMPOSITE, - .data = (const struct snd_usb_audio_quirk[]) { - { - .ifnum = 0, - .type = QUIRK_AUDIO_STANDARD_MIXER, - }, - /* Capture */ - { - .ifnum = 1, - .type = QUIRK_IGNORE_INTERFACE, - }, + QUIRK_DRIVER_INFO { + QUIRK_DATA_COMPOSITE { + { QUIRK_DATA_STANDARD_MIXER(0) }, + { QUIRK_DATA_IGNORE(1) }, /* Capture */ /* Playback */ { - .ifnum = 2, - .type = QUIRK_AUDIO_FIXED_ENDPOINT, - .data = &(const struct audioformat) { + QUIRK_DATA_AUDIOFORMAT(2) { .formats = SNDRV_PCM_FMTBIT_S16_LE, .channels = 2, .iface = 2, @@ -3463,9 +2626,7 @@ YAMAHA_DEVICE(0x7010, "UB99"), } } }, - { - .ifnum = -1 - }, + QUIRK_COMPOSITE_END } } }, @@ -3478,19 +2639,12 @@ YAMAHA_DEVICE(0x7010, "UB99"), * even on windows. */ USB_DEVICE(0x19b5, 0x0021), - .driver_info = (unsigned long) &(const struct snd_usb_audio_quirk) { - .ifnum = QUIRK_ANY_INTERFACE, - .type = QUIRK_COMPOSITE, - .data = (const struct snd_usb_audio_quirk[]) { - { - .ifnum = 0, - .type = QUIRK_AUDIO_STANDARD_MIXER, - }, + QUIRK_DRIVER_INFO { + QUIRK_DATA_COMPOSITE { + { QUIRK_DATA_STANDARD_MIXER(0) }, /* Playback */ { - .ifnum = 1, - .type = QUIRK_AUDIO_FIXED_ENDPOINT, - .data = &(const struct audioformat) { + QUIRK_DATA_AUDIOFORMAT(1) { .formats = SNDRV_PCM_FMTBIT_S16_LE, .channels = 2, .iface = 1, @@ -3509,29 +2663,20 @@ YAMAHA_DEVICE(0x7010, "UB99"), } } }, - { - .ifnum = -1 - }, + QUIRK_COMPOSITE_END } } }, /* MOTU Microbook II */ { USB_DEVICE_VENDOR_SPEC(0x07fd, 0x0004), - .driver_info = (unsigned long) &(const struct snd_usb_audio_quirk) { + QUIRK_DRIVER_INFO { .vendor_name = "MOTU", .product_name = "MicroBookII", - .ifnum = QUIRK_ANY_INTERFACE, - .type = QUIRK_COMPOSITE, - .data = (const struct snd_usb_audio_quirk[]) { + QUIRK_DATA_COMPOSITE { + { QUIRK_DATA_STANDARD_MIXER(0) }, { - .ifnum = 0, - .type = QUIRK_AUDIO_STANDARD_MIXER, - }, - { - .ifnum = 0, - .type = QUIRK_AUDIO_FIXED_ENDPOINT, - .data = &(const struct audioformat) { + QUIRK_DATA_AUDIOFORMAT(0) { .formats = SNDRV_PCM_FMTBIT_S24_3BE, .channels = 6, .iface = 0, @@ -3552,9 +2697,7 @@ YAMAHA_DEVICE(0x7010, "UB99"), } }, { - .ifnum = 0, - .type = QUIRK_AUDIO_FIXED_ENDPOINT, - .data = &(const struct audioformat) { + QUIRK_DATA_AUDIOFORMAT(0) { .formats = SNDRV_PCM_FMTBIT_S24_3BE, .channels = 8, .iface = 0, @@ -3575,9 +2718,7 @@ YAMAHA_DEVICE(0x7010, "UB99"), } } }, - { - .ifnum = -1 - } + QUIRK_COMPOSITE_END } } }, @@ -3589,14 +2730,10 @@ YAMAHA_DEVICE(0x7010, "UB99"), * The feedback for the output is the input. */ USB_DEVICE_VENDOR_SPEC(0x2b73, 0x0023), - .driver_info = (unsigned long) &(const struct snd_usb_audio_quirk) { - .ifnum = QUIRK_ANY_INTERFACE, - .type = QUIRK_COMPOSITE, - .data = (const struct snd_usb_audio_quirk[]) { + QUIRK_DRIVER_INFO { + QUIRK_DATA_COMPOSITE { { - .ifnum = 0, - .type = QUIRK_AUDIO_FIXED_ENDPOINT, - .data = &(const struct audioformat) { + QUIRK_DATA_AUDIOFORMAT(0) { .formats = SNDRV_PCM_FMTBIT_S32_LE, .channels = 12, .iface = 0, @@ -3613,9 +2750,7 @@ YAMAHA_DEVICE(0x7010, "UB99"), } }, { - .ifnum = 0, - .type = QUIRK_AUDIO_FIXED_ENDPOINT, - .data = &(const struct audioformat) { + QUIRK_DATA_AUDIOFORMAT(0) { .formats = SNDRV_PCM_FMTBIT_S32_LE, .channels = 10, .iface = 0, @@ -3633,9 +2768,7 @@ YAMAHA_DEVICE(0x7010, "UB99"), .rate_table = (unsigned int[]) { 44100 } } }, - { - .ifnum = -1 - } + QUIRK_COMPOSITE_END } } }, @@ -3678,14 +2811,10 @@ YAMAHA_DEVICE(0x7010, "UB99"), * but not for DVS (Digital Vinyl Systems) like in Mixxx. */ USB_DEVICE_VENDOR_SPEC(0x2b73, 0x0017), - .driver_info = (unsigned long) &(const struct snd_usb_audio_quirk) { - .ifnum = QUIRK_ANY_INTERFACE, - .type = QUIRK_COMPOSITE, - .data = (const struct snd_usb_audio_quirk[]) { + QUIRK_DRIVER_INFO { + QUIRK_DATA_COMPOSITE { { - .ifnum = 0, - .type = QUIRK_AUDIO_FIXED_ENDPOINT, - .data = &(const struct audioformat) { + QUIRK_DATA_AUDIOFORMAT(0) { .formats = SNDRV_PCM_FMTBIT_S24_3LE, .channels = 8, // outputs .iface = 0, @@ -3702,9 +2831,7 @@ YAMAHA_DEVICE(0x7010, "UB99"), } }, { - .ifnum = 0, - .type = QUIRK_AUDIO_FIXED_ENDPOINT, - .data = &(const struct audioformat) { + QUIRK_DATA_AUDIOFORMAT(0) { .formats = SNDRV_PCM_FMTBIT_S24_3LE, .channels = 8, // inputs .iface = 0, @@ -3722,9 +2849,7 @@ YAMAHA_DEVICE(0x7010, "UB99"), .rate_table = (unsigned int[]) { 48000 } } }, - { - .ifnum = -1 - } + QUIRK_COMPOSITE_END } } }, @@ -3735,14 +2860,10 @@ YAMAHA_DEVICE(0x7010, "UB99"), * The feedback for the output is the dummy input. */ USB_DEVICE_VENDOR_SPEC(0x2b73, 0x000e), - .driver_info = (unsigned long) &(const struct snd_usb_audio_quirk) { - .ifnum = QUIRK_ANY_INTERFACE, - .type = QUIRK_COMPOSITE, - .data = (const struct snd_usb_audio_quirk[]) { + QUIRK_DRIVER_INFO { + QUIRK_DATA_COMPOSITE { { - .ifnum = 0, - .type = QUIRK_AUDIO_FIXED_ENDPOINT, - .data = &(const struct audioformat) { + QUIRK_DATA_AUDIOFORMAT(0) { .formats = SNDRV_PCM_FMTBIT_S24_3LE, .channels = 4, .iface = 0, @@ -3759,9 +2880,7 @@ YAMAHA_DEVICE(0x7010, "UB99"), } }, { - .ifnum = 0, - .type = QUIRK_AUDIO_FIXED_ENDPOINT, - .data = &(const struct audioformat) { + QUIRK_DATA_AUDIOFORMAT(0) { .formats = SNDRV_PCM_FMTBIT_S24_3LE, .channels = 2, .iface = 0, @@ -3779,9 +2898,7 @@ YAMAHA_DEVICE(0x7010, "UB99"), .rate_table = (unsigned int[]) { 44100 } } }, - { - .ifnum = -1 - } + QUIRK_COMPOSITE_END } } }, @@ -3792,14 +2909,10 @@ YAMAHA_DEVICE(0x7010, "UB99"), * PCM is 6 channels out & 4 channels in @ 44.1 fixed */ USB_DEVICE_VENDOR_SPEC(0x2b73, 0x000d), - .driver_info = (unsigned long) &(const struct snd_usb_audio_quirk) { - .ifnum = QUIRK_ANY_INTERFACE, - .type = QUIRK_COMPOSITE, - .data = (const struct snd_usb_audio_quirk[]) { + QUIRK_DRIVER_INFO { + QUIRK_DATA_COMPOSITE { { - .ifnum = 0, - .type = QUIRK_AUDIO_FIXED_ENDPOINT, - .data = &(const struct audioformat) { + QUIRK_DATA_AUDIOFORMAT(0) { .formats = SNDRV_PCM_FMTBIT_S24_3LE, .channels = 6, //Master, Headphones & Booth .iface = 0, @@ -3816,9 +2929,7 @@ YAMAHA_DEVICE(0x7010, "UB99"), } }, { - .ifnum = 0, - .type = QUIRK_AUDIO_FIXED_ENDPOINT, - .data = &(const struct audioformat) { + QUIRK_DATA_AUDIOFORMAT(0) { .formats = SNDRV_PCM_FMTBIT_S24_3LE, .channels = 4, //2x RCA inputs (CH1 & CH2) .iface = 0, @@ -3836,9 +2947,7 @@ YAMAHA_DEVICE(0x7010, "UB99"), .rate_table = (unsigned int[]) { 44100 } } }, - { - .ifnum = -1 - } + QUIRK_COMPOSITE_END } } }, @@ -3850,14 +2959,10 @@ YAMAHA_DEVICE(0x7010, "UB99"), * The Feedback for the output is the input */ USB_DEVICE_VENDOR_SPEC(0x2b73, 0x001e), - .driver_info = (unsigned long) &(const struct snd_usb_audio_quirk) { - .ifnum = QUIRK_ANY_INTERFACE, - .type = QUIRK_COMPOSITE, - .data = (const struct snd_usb_audio_quirk[]) { + QUIRK_DRIVER_INFO { + QUIRK_DATA_COMPOSITE { { - .ifnum = 0, - .type = QUIRK_AUDIO_FIXED_ENDPOINT, - .data = &(const struct audioformat) { + QUIRK_DATA_AUDIOFORMAT(0) { .formats = SNDRV_PCM_FMTBIT_S24_3LE, .channels = 4, .iface = 0, @@ -3874,9 +2979,7 @@ YAMAHA_DEVICE(0x7010, "UB99"), } }, { - .ifnum = 0, - .type = QUIRK_AUDIO_FIXED_ENDPOINT, - .data = &(const struct audioformat) { + QUIRK_DATA_AUDIOFORMAT(0) { .formats = SNDRV_PCM_FMTBIT_S24_3LE, .channels = 6, .iface = 0, @@ -3894,9 +2997,7 @@ YAMAHA_DEVICE(0x7010, "UB99"), .rate_table = (unsigned int[]) { 44100 } } }, - { - .ifnum = -1 - } + QUIRK_COMPOSITE_END } } }, @@ -3907,14 +3008,10 @@ YAMAHA_DEVICE(0x7010, "UB99"), * 10 channels playback & 12 channels capture @ 44.1/48/96kHz S24LE */ USB_DEVICE_VENDOR_SPEC(0x2b73, 0x000a), - .driver_info = (unsigned long) &(const struct snd_usb_audio_quirk) { - .ifnum = QUIRK_ANY_INTERFACE, - .type = QUIRK_COMPOSITE, - .data = (const struct snd_usb_audio_quirk[]) { + QUIRK_DRIVER_INFO { + QUIRK_DATA_COMPOSITE { { - .ifnum = 0, - .type = QUIRK_AUDIO_FIXED_ENDPOINT, - .data = &(const struct audioformat) { + QUIRK_DATA_AUDIOFORMAT(0) { .formats = SNDRV_PCM_FMTBIT_S24_3LE, .channels = 10, .iface = 0, @@ -3935,9 +3032,7 @@ YAMAHA_DEVICE(0x7010, "UB99"), } }, { - .ifnum = 0, - .type = QUIRK_AUDIO_FIXED_ENDPOINT, - .data = &(const struct audioformat) { + QUIRK_DATA_AUDIOFORMAT(0) { .formats = SNDRV_PCM_FMTBIT_S24_3LE, .channels = 12, .iface = 0, @@ -3959,9 +3054,7 @@ YAMAHA_DEVICE(0x7010, "UB99"), } } }, - { - .ifnum = -1 - } + QUIRK_COMPOSITE_END } } }, @@ -3973,14 +3066,10 @@ YAMAHA_DEVICE(0x7010, "UB99"), * The Feedback for the output is the input */ USB_DEVICE_VENDOR_SPEC(0x2b73, 0x0029), - .driver_info = (unsigned long) &(const struct snd_usb_audio_quirk) { - .ifnum = QUIRK_ANY_INTERFACE, - .type = QUIRK_COMPOSITE, - .data = (const struct snd_usb_audio_quirk[]) { + QUIRK_DRIVER_INFO { + QUIRK_DATA_COMPOSITE { { - .ifnum = 0, - .type = QUIRK_AUDIO_FIXED_ENDPOINT, - .data = &(const struct audioformat) { + QUIRK_DATA_AUDIOFORMAT(0) { .formats = SNDRV_PCM_FMTBIT_S24_3LE, .channels = 6, .iface = 0, @@ -3997,9 +3086,7 @@ YAMAHA_DEVICE(0x7010, "UB99"), } }, { - .ifnum = 0, - .type = QUIRK_AUDIO_FIXED_ENDPOINT, - .data = &(const struct audioformat) { + QUIRK_DATA_AUDIOFORMAT(0) { .formats = SNDRV_PCM_FMTBIT_S24_3LE, .channels = 6, .iface = 0, @@ -4017,9 +3104,7 @@ YAMAHA_DEVICE(0x7010, "UB99"), .rate_table = (unsigned int[]) { 44100 } } }, - { - .ifnum = -1 - } + QUIRK_COMPOSITE_END } } }, @@ -4037,20 +3122,13 @@ YAMAHA_DEVICE(0x7010, "UB99"), */ { USB_AUDIO_DEVICE(0x534d, 0x0021), - .driver_info = (unsigned long) &(const struct snd_usb_audio_quirk) { + QUIRK_DRIVER_INFO { .vendor_name = "MacroSilicon", .product_name = "MS210x", - .ifnum = QUIRK_ANY_INTERFACE, - .type = QUIRK_COMPOSITE, - .data = &(const struct snd_usb_audio_quirk[]) { + QUIRK_DATA_COMPOSITE { + { QUIRK_DATA_STANDARD_MIXER(2) }, { - .ifnum = 2, - .type = QUIRK_AUDIO_STANDARD_MIXER, - }, - { - .ifnum = 3, - .type = QUIRK_AUDIO_FIXED_ENDPOINT, - .data = &(const struct audioformat) { + QUIRK_DATA_AUDIOFORMAT(3) { .formats = SNDRV_PCM_FMTBIT_S16_LE, .channels = 2, .iface = 3, @@ -4065,9 +3143,7 @@ YAMAHA_DEVICE(0x7010, "UB99"), .rate_max = 48000, } }, - { - .ifnum = -1 - } + QUIRK_COMPOSITE_END } } }, @@ -4085,20 +3161,13 @@ YAMAHA_DEVICE(0x7010, "UB99"), */ { USB_AUDIO_DEVICE(0x534d, 0x2109), - .driver_info = (unsigned long) &(const struct snd_usb_audio_quirk) { + QUIRK_DRIVER_INFO { .vendor_name = "MacroSilicon", .product_name = "MS2109", - .ifnum = QUIRK_ANY_INTERFACE, - .type = QUIRK_COMPOSITE, - .data = &(const struct snd_usb_audio_quirk[]) { + QUIRK_DATA_COMPOSITE { + { QUIRK_DATA_STANDARD_MIXER(2) }, { - .ifnum = 2, - .type = QUIRK_AUDIO_STANDARD_MIXER, - }, - { - .ifnum = 3, - .type = QUIRK_AUDIO_FIXED_ENDPOINT, - .data = &(const struct audioformat) { + QUIRK_DATA_AUDIOFORMAT(3) { .formats = SNDRV_PCM_FMTBIT_S16_LE, .channels = 2, .iface = 3, @@ -4113,9 +3182,7 @@ YAMAHA_DEVICE(0x7010, "UB99"), .rate_max = 48000, } }, - { - .ifnum = -1 - } + QUIRK_COMPOSITE_END } } }, @@ -4125,14 +3192,10 @@ YAMAHA_DEVICE(0x7010, "UB99"), * 8 channels playback & 8 channels capture @ 44.1/48/96kHz S24LE */ USB_DEVICE_VENDOR_SPEC(0x08e4, 0x017f), - .driver_info = (unsigned long) &(const struct snd_usb_audio_quirk) { - .ifnum = QUIRK_ANY_INTERFACE, - .type = QUIRK_COMPOSITE, - .data = (const struct snd_usb_audio_quirk[]) { + QUIRK_DRIVER_INFO { + QUIRK_DATA_COMPOSITE { { - .ifnum = 0, - .type = QUIRK_AUDIO_FIXED_ENDPOINT, - .data = &(const struct audioformat) { + QUIRK_DATA_AUDIOFORMAT(0) { .formats = SNDRV_PCM_FMTBIT_S24_3LE, .channels = 8, .iface = 0, @@ -4151,9 +3214,7 @@ YAMAHA_DEVICE(0x7010, "UB99"), } }, { - .ifnum = 0, - .type = QUIRK_AUDIO_FIXED_ENDPOINT, - .data = &(const struct audioformat) { + QUIRK_DATA_AUDIOFORMAT(0) { .formats = SNDRV_PCM_FMTBIT_S24_3LE, .channels = 8, .iface = 0, @@ -4173,9 +3234,7 @@ YAMAHA_DEVICE(0x7010, "UB99"), .rate_table = (unsigned int[]) { 44100, 48000, 96000 } } }, - { - .ifnum = -1 - } + QUIRK_COMPOSITE_END } } }, @@ -4185,14 +3244,10 @@ YAMAHA_DEVICE(0x7010, "UB99"), * 10 channels playback & 12 channels capture @ 48kHz S24LE */ USB_DEVICE_VENDOR_SPEC(0x2b73, 0x001b), - .driver_info = (unsigned long) &(const struct snd_usb_audio_quirk) { - .ifnum = QUIRK_ANY_INTERFACE, - .type = QUIRK_COMPOSITE, - .data = (const struct snd_usb_audio_quirk[]) { + QUIRK_DRIVER_INFO { + QUIRK_DATA_COMPOSITE { { - .ifnum = 0, - .type = QUIRK_AUDIO_FIXED_ENDPOINT, - .data = &(const struct audioformat) { + QUIRK_DATA_AUDIOFORMAT(0) { .formats = SNDRV_PCM_FMTBIT_S24_3LE, .channels = 10, .iface = 0, @@ -4211,9 +3266,7 @@ YAMAHA_DEVICE(0x7010, "UB99"), } }, { - .ifnum = 0, - .type = QUIRK_AUDIO_FIXED_ENDPOINT, - .data = &(const struct audioformat) { + QUIRK_DATA_AUDIOFORMAT(0) { .formats = SNDRV_PCM_FMTBIT_S24_3LE, .channels = 12, .iface = 0, @@ -4231,9 +3284,7 @@ YAMAHA_DEVICE(0x7010, "UB99"), .rate_table = (unsigned int[]) { 48000 } } }, - { - .ifnum = -1 - } + QUIRK_COMPOSITE_END } } }, @@ -4245,14 +3296,10 @@ YAMAHA_DEVICE(0x7010, "UB99"), * Capture on EP 0x86 */ USB_DEVICE_VENDOR_SPEC(0x08e4, 0x0163), - .driver_info = (unsigned long) &(const struct snd_usb_audio_quirk) { - .ifnum = QUIRK_ANY_INTERFACE, - .type = QUIRK_COMPOSITE, - .data = (const struct snd_usb_audio_quirk[]) { + QUIRK_DRIVER_INFO { + QUIRK_DATA_COMPOSITE { { - .ifnum = 0, - .type = QUIRK_AUDIO_FIXED_ENDPOINT, - .data = &(const struct audioformat) { + QUIRK_DATA_AUDIOFORMAT(0) { .formats = SNDRV_PCM_FMTBIT_S24_3LE, .channels = 8, .iface = 0, @@ -4272,9 +3319,7 @@ YAMAHA_DEVICE(0x7010, "UB99"), } }, { - .ifnum = 0, - .type = QUIRK_AUDIO_FIXED_ENDPOINT, - .data = &(const struct audioformat) { + QUIRK_DATA_AUDIOFORMAT(0) { .formats = SNDRV_PCM_FMTBIT_S24_3LE, .channels = 8, .iface = 0, @@ -4294,9 +3339,7 @@ YAMAHA_DEVICE(0x7010, "UB99"), .rate_table = (unsigned int[]) { 44100, 48000, 96000 } } }, - { - .ifnum = -1 - } + QUIRK_COMPOSITE_END } } }, @@ -4307,14 +3350,10 @@ YAMAHA_DEVICE(0x7010, "UB99"), * and 8 channels in @ 48 fixed (endpoint 0x82). */ USB_DEVICE_VENDOR_SPEC(0x2b73, 0x0013), - .driver_info = (unsigned long) &(const struct snd_usb_audio_quirk) { - .ifnum = QUIRK_ANY_INTERFACE, - .type = QUIRK_COMPOSITE, - .data = (const struct snd_usb_audio_quirk[]) { + QUIRK_DRIVER_INFO { + QUIRK_DATA_COMPOSITE { { - .ifnum = 0, - .type = QUIRK_AUDIO_FIXED_ENDPOINT, - .data = &(const struct audioformat) { + QUIRK_DATA_AUDIOFORMAT(0) { .formats = SNDRV_PCM_FMTBIT_S24_3LE, .channels = 8, // outputs .iface = 0, @@ -4331,9 +3370,7 @@ YAMAHA_DEVICE(0x7010, "UB99"), } }, { - .ifnum = 0, - .type = QUIRK_AUDIO_FIXED_ENDPOINT, - .data = &(const struct audioformat) { + QUIRK_DATA_AUDIOFORMAT(0) { .formats = SNDRV_PCM_FMTBIT_S24_3LE, .channels = 8, // inputs .iface = 0, @@ -4351,9 +3388,7 @@ YAMAHA_DEVICE(0x7010, "UB99"), .rate_table = (unsigned int[]) { 48000 } } }, - { - .ifnum = -1 - } + QUIRK_COMPOSITE_END } } }, @@ -4364,28 +3399,15 @@ YAMAHA_DEVICE(0x7010, "UB99"), */ USB_DEVICE(0x1395, 0x0300), .bInterfaceClass = USB_CLASS_PER_INTERFACE, - .driver_info = (unsigned long) &(const struct snd_usb_audio_quirk) { - .ifnum = QUIRK_ANY_INTERFACE, - .type = QUIRK_COMPOSITE, - .data = &(const struct snd_usb_audio_quirk[]) { + QUIRK_DRIVER_INFO { + QUIRK_DATA_COMPOSITE { // Communication - { - .ifnum = 3, - .type = QUIRK_AUDIO_STANDARD_INTERFACE - }, + { QUIRK_DATA_STANDARD_AUDIO(3) }, // Recording - { - .ifnum = 4, - .type = QUIRK_AUDIO_STANDARD_INTERFACE - }, + { QUIRK_DATA_STANDARD_AUDIO(4) }, // Main - { - .ifnum = 1, - .type = QUIRK_AUDIO_STANDARD_INTERFACE - }, - { - .ifnum = -1 - } + { QUIRK_DATA_STANDARD_AUDIO(1) }, + QUIRK_COMPOSITE_END } } }, @@ -4394,21 +3416,14 @@ YAMAHA_DEVICE(0x7010, "UB99"), * Fiero SC-01 (firmware v1.0.0 @ 48 kHz) */ USB_DEVICE(0x2b53, 0x0023), - .driver_info = (unsigned long) &(const struct snd_usb_audio_quirk) { + QUIRK_DRIVER_INFO { .vendor_name = "Fiero", .product_name = "SC-01", - .ifnum = QUIRK_ANY_INTERFACE, - .type = QUIRK_COMPOSITE, - .data = &(const struct snd_usb_audio_quirk[]) { - { - .ifnum = 0, - .type = QUIRK_AUDIO_STANDARD_INTERFACE - }, + QUIRK_DATA_COMPOSITE { + { QUIRK_DATA_STANDARD_AUDIO(0) }, /* Playback */ { - .ifnum = 1, - .type = QUIRK_AUDIO_FIXED_ENDPOINT, - .data = &(const struct audioformat) { + QUIRK_DATA_AUDIOFORMAT(1) { .formats = SNDRV_PCM_FMTBIT_S32_LE, .channels = 2, .fmt_bits = 24, @@ -4428,9 +3443,7 @@ YAMAHA_DEVICE(0x7010, "UB99"), }, /* Capture */ { - .ifnum = 2, - .type = QUIRK_AUDIO_FIXED_ENDPOINT, - .data = &(const struct audioformat) { + QUIRK_DATA_AUDIOFORMAT(2) { .formats = SNDRV_PCM_FMTBIT_S32_LE, .channels = 2, .fmt_bits = 24, @@ -4449,9 +3462,7 @@ YAMAHA_DEVICE(0x7010, "UB99"), .clock = 0x29 } }, - { - .ifnum = -1 - } + QUIRK_COMPOSITE_END } } }, @@ -4460,21 +3471,14 @@ YAMAHA_DEVICE(0x7010, "UB99"), * Fiero SC-01 (firmware v1.0.0 @ 96 kHz) */ USB_DEVICE(0x2b53, 0x0024), - .driver_info = (unsigned long) &(const struct snd_usb_audio_quirk) { + QUIRK_DRIVER_INFO { .vendor_name = "Fiero", .product_name = "SC-01", - .ifnum = QUIRK_ANY_INTERFACE, - .type = QUIRK_COMPOSITE, - .data = &(const struct snd_usb_audio_quirk[]) { - { - .ifnum = 0, - .type = QUIRK_AUDIO_STANDARD_INTERFACE - }, + QUIRK_DATA_COMPOSITE { + { QUIRK_DATA_STANDARD_AUDIO(0) }, /* Playback */ { - .ifnum = 1, - .type = QUIRK_AUDIO_FIXED_ENDPOINT, - .data = &(const struct audioformat) { + QUIRK_DATA_AUDIOFORMAT(1) { .formats = SNDRV_PCM_FMTBIT_S32_LE, .channels = 2, .fmt_bits = 24, @@ -4494,9 +3498,7 @@ YAMAHA_DEVICE(0x7010, "UB99"), }, /* Capture */ { - .ifnum = 2, - .type = QUIRK_AUDIO_FIXED_ENDPOINT, - .data = &(const struct audioformat) { + QUIRK_DATA_AUDIOFORMAT(2) { .formats = SNDRV_PCM_FMTBIT_S32_LE, .channels = 2, .fmt_bits = 24, @@ -4515,9 +3517,7 @@ YAMAHA_DEVICE(0x7010, "UB99"), .clock = 0x29 } }, - { - .ifnum = -1 - } + QUIRK_COMPOSITE_END } } }, @@ -4526,21 +3526,14 @@ YAMAHA_DEVICE(0x7010, "UB99"), * Fiero SC-01 (firmware v1.1.0) */ USB_DEVICE(0x2b53, 0x0031), - .driver_info = (unsigned long) &(const struct snd_usb_audio_quirk) { + QUIRK_DRIVER_INFO { .vendor_name = "Fiero", .product_name = "SC-01", - .ifnum = QUIRK_ANY_INTERFACE, - .type = QUIRK_COMPOSITE, - .data = &(const struct snd_usb_audio_quirk[]) { - { - .ifnum = 0, - .type = QUIRK_AUDIO_STANDARD_INTERFACE - }, + QUIRK_DATA_COMPOSITE { + { QUIRK_DATA_STANDARD_AUDIO(0) }, /* Playback */ { - .ifnum = 1, - .type = QUIRK_AUDIO_FIXED_ENDPOINT, - .data = &(const struct audioformat) { + QUIRK_DATA_AUDIOFORMAT(1) { .formats = SNDRV_PCM_FMTBIT_S32_LE, .channels = 2, .fmt_bits = 24, @@ -4561,9 +3554,7 @@ YAMAHA_DEVICE(0x7010, "UB99"), }, /* Capture */ { - .ifnum = 2, - .type = QUIRK_AUDIO_FIXED_ENDPOINT, - .data = &(const struct audioformat) { + QUIRK_DATA_AUDIOFORMAT(2) { .formats = SNDRV_PCM_FMTBIT_S32_LE, .channels = 2, .fmt_bits = 24, @@ -4583,9 +3574,7 @@ YAMAHA_DEVICE(0x7010, "UB99"), .clock = 0x29 } }, - { - .ifnum = -1 - } + QUIRK_COMPOSITE_END } } }, @@ -4594,27 +3583,14 @@ YAMAHA_DEVICE(0x7010, "UB99"), * For the standard mode, Mythware XA001AU has ID ffad:a001 */ USB_DEVICE_VENDOR_SPEC(0xffad, 0xa001), - .driver_info = (unsigned long) &(const struct snd_usb_audio_quirk) { + QUIRK_DRIVER_INFO { .vendor_name = "Mythware", .product_name = "XA001AU", - .ifnum = QUIRK_ANY_INTERFACE, - .type = QUIRK_COMPOSITE, - .data = (const struct snd_usb_audio_quirk[]) { - { - .ifnum = 0, - .type = QUIRK_IGNORE_INTERFACE, - }, - { - .ifnum = 1, - .type = QUIRK_AUDIO_STANDARD_INTERFACE, - }, - { - .ifnum = 2, - .type = QUIRK_AUDIO_STANDARD_INTERFACE, - }, - { - .ifnum = -1 - } + QUIRK_DATA_COMPOSITE { + { QUIRK_DATA_IGNORE(0) }, + { QUIRK_DATA_STANDARD_AUDIO(1) }, + { QUIRK_DATA_STANDARD_AUDIO(2) }, + QUIRK_COMPOSITE_END } } }, From 759d02ea182a90da951adab7e43524f8c4330b7b Mon Sep 17 00:00:00 2001 From: Joshua Pius Date: Thu, 12 Sep 2024 15:26:28 +0000 Subject: [PATCH 038/267] ALSA: usb-audio: Add logitech Audio profile quirk [ Upstream commit a51c925c11d7b855167e64b63eb4378e5adfc11d ] Specify shortnames for the following Logitech Devices: Rally bar, Rally bar mini, Tap, MeetUp and Huddle. Signed-off-by: Joshua Pius Link: https://patch.msgid.link/20240912152635.1859737-1-joshuapius@google.com Signed-off-by: Takashi Iwai Signed-off-by: Sasha Levin --- sound/usb/card.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/sound/usb/card.c b/sound/usb/card.c index 26268ffb8274..5f539a1baef3 100644 --- a/sound/usb/card.c +++ b/sound/usb/card.c @@ -382,6 +382,12 @@ static const struct usb_audio_device_name usb_audio_names[] = { /* Creative/Toshiba Multimedia Center SB-0500 */ DEVICE_NAME(0x041e, 0x3048, "Toshiba", "SB-0500"), + /* Logitech Audio Devices */ + DEVICE_NAME(0x046d, 0x0867, "Logitech, Inc.", "Logi-MeetUp"), + DEVICE_NAME(0x046d, 0x0874, "Logitech, Inc.", "Logi-Tap-Audio"), + DEVICE_NAME(0x046d, 0x087c, "Logitech, Inc.", "Logi-Huddle"), + DEVICE_NAME(0x046d, 0x0898, "Logitech, Inc.", "Logi-RB-Audio"), + DEVICE_NAME(0x046d, 0x08d2, "Logitech, Inc.", "Logi-RBM-Audio"), DEVICE_NAME(0x046d, 0x0990, "Logitech, Inc.", "QuickCam Pro 9000"), DEVICE_NAME(0x05e1, 0x0408, "Syntek", "STK1160"), From dfec74d6856478f5a898c0917fb224fbcba6f4c4 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Wed, 10 Jul 2024 15:52:31 +0200 Subject: [PATCH 039/267] ASoC: codecs: wsa883x: Handle reading version failure [ Upstream commit 2fbf16992e5aa14acf0441320033a01a32309ded ] If reading version and variant from registers fails (which is unlikely but possible, because it is a read over bus), the driver will proceed and perform device configuration based on uninitialized stack variables. Handle it a bit better - bail out without doing any init and failing the update status Soundwire callback. Signed-off-by: Krzysztof Kozlowski Link: https://patch.msgid.link/20240710-asoc-wsa88xx-version-v1-2-f1c54966ccde@linaro.org Signed-off-by: Mark Brown Signed-off-by: Sasha Levin --- sound/soc/codecs/wsa883x.c | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/sound/soc/codecs/wsa883x.c b/sound/soc/codecs/wsa883x.c index f4b81ebab353..639fb77170ac 100644 --- a/sound/soc/codecs/wsa883x.c +++ b/sound/soc/codecs/wsa883x.c @@ -1002,15 +1002,19 @@ static const struct reg_sequence reg_init[] = { {WSA883X_GMAMP_SUP1, 0xE2}, }; -static void wsa883x_init(struct wsa883x_priv *wsa883x) +static int wsa883x_init(struct wsa883x_priv *wsa883x) { struct regmap *regmap = wsa883x->regmap; - int variant, version; + int variant, version, ret; - regmap_read(regmap, WSA883X_OTP_REG_0, &variant); + ret = regmap_read(regmap, WSA883X_OTP_REG_0, &variant); + if (ret) + return ret; wsa883x->variant = variant & WSA883X_ID_MASK; - regmap_read(regmap, WSA883X_CHIP_ID0, &version); + ret = regmap_read(regmap, WSA883X_CHIP_ID0, &version); + if (ret) + return ret; wsa883x->version = version; switch (wsa883x->variant) { @@ -1045,6 +1049,8 @@ static void wsa883x_init(struct wsa883x_priv *wsa883x) WSA883X_DRE_OFFSET_MASK, wsa883x->comp_offset); } + + return 0; } static int wsa883x_update_status(struct sdw_slave *slave, @@ -1053,7 +1059,7 @@ static int wsa883x_update_status(struct sdw_slave *slave, struct wsa883x_priv *wsa883x = dev_get_drvdata(&slave->dev); if (status == SDW_SLAVE_ATTACHED && slave->dev_num > 0) - wsa883x_init(wsa883x); + return wsa883x_init(wsa883x); return 0; } From 198314189f46c92e9ef950feda104a6b2e8beb28 Mon Sep 17 00:00:00 2001 From: "Ahmed S. Darwish" Date: Thu, 18 Jul 2024 15:47:44 +0200 Subject: [PATCH 040/267] tools/x86/kcpuid: Protect against faulty "max subleaf" values MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [ Upstream commit cf96ab1a966b87b09fdd9e8cc8357d2d00776a3a ] Protect against the kcpuid code parsing faulty max subleaf numbers through a min() expression. Thus, ensuring that max_subleaf will always be ≤ MAX_SUBLEAF_NUM. Use "u32" for the subleaf numbers since kcpuid is compiled with -Wextra, which includes signed/unsigned comparisons warnings. Signed-off-by: Ahmed S. Darwish Signed-off-by: Thomas Gleixner Link: https://lore.kernel.org/all/20240718134755.378115-5-darwi@linutronix.de Signed-off-by: Sasha Levin --- tools/arch/x86/kcpuid/kcpuid.c | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/tools/arch/x86/kcpuid/kcpuid.c b/tools/arch/x86/kcpuid/kcpuid.c index dae75511fef7..bbeb2dc86410 100644 --- a/tools/arch/x86/kcpuid/kcpuid.c +++ b/tools/arch/x86/kcpuid/kcpuid.c @@ -7,7 +7,8 @@ #include #include -#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0])) +#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0])) +#define min(a, b) (((a) < (b)) ? (a) : (b)) typedef unsigned int u32; typedef unsigned long long u64; @@ -203,12 +204,9 @@ static void raw_dump_range(struct cpuid_range *range) #define MAX_SUBLEAF_NUM 32 struct cpuid_range *setup_cpuid_range(u32 input_eax) { - u32 max_func, idx_func; - int subleaf; + u32 max_func, idx_func, subleaf, max_subleaf; + u32 eax, ebx, ecx, edx, f = input_eax; struct cpuid_range *range; - u32 eax, ebx, ecx, edx; - u32 f = input_eax; - int max_subleaf; bool allzero; eax = input_eax; @@ -254,7 +252,7 @@ struct cpuid_range *setup_cpuid_range(u32 input_eax) * others have to be tried (0xf) */ if (f == 0x7 || f == 0x14 || f == 0x17 || f == 0x18) - max_subleaf = (eax & 0xff) + 1; + max_subleaf = min((eax & 0xff) + 1, max_subleaf); if (f == 0xb) max_subleaf = 2; From 10f502d2d78770d4aca625a5816d74fe44cd9376 Mon Sep 17 00:00:00 2001 From: Tao Liu Date: Wed, 17 Jul 2024 16:31:20 -0500 Subject: [PATCH 041/267] x86/kexec: Add EFI config table identity mapping for kexec kernel [ Upstream commit 5760929f6545c651682de3c2c6c6786816b17bb1 ] A kexec kernel boot failure is sometimes observed on AMD CPUs due to an unmapped EFI config table array. This can be seen when "nogbpages" is on the kernel command line, and has been observed as a full BIOS reboot rather than a successful kexec. This was also the cause of reported regressions attributed to Commit 7143c5f4cf20 ("x86/mm/ident_map: Use gbpages only where full GB page should be mapped.") which was subsequently reverted. To avoid this page fault, explicitly include the EFI config table array in the kexec identity map. Further explanation: The following 2 commits caused the EFI config table array to be accessed when enabling sev at kernel startup. commit ec1c66af3a30 ("x86/compressed/64: Detect/setup SEV/SME features earlier during boot") commit c01fce9cef84 ("x86/compressed: Add SEV-SNP feature detection/setup") This is in the code that examines whether SEV should be enabled or not, so it can even affect systems that are not SEV capable. This may result in a page fault if the EFI config table array's address is unmapped. Since the page fault occurs before the new kernel establishes its own identity map and page fault routines, it is unrecoverable and kexec fails. Most often, this problem is not seen because the EFI config table array gets included in the map by the luck of being placed at a memory address close enough to other memory areas that *are* included in the map created by kexec. Both the "nogbpages" command line option and the "use gpbages only where full GB page should be mapped" change greatly reduce the chance of being included in the map by luck, which is why the problem appears. Signed-off-by: Tao Liu Signed-off-by: Steve Wahl Signed-off-by: Thomas Gleixner Tested-by: Pavin Joseph Tested-by: Sarah Brofeldt Tested-by: Eric Hagberg Reviewed-by: Ard Biesheuvel Link: https://lore.kernel.org/all/20240717213121.3064030-2-steve.wahl@hpe.com Signed-off-by: Sasha Levin --- arch/x86/kernel/machine_kexec_64.c | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/arch/x86/kernel/machine_kexec_64.c b/arch/x86/kernel/machine_kexec_64.c index 0611fd83858e..24b6eaacc81e 100644 --- a/arch/x86/kernel/machine_kexec_64.c +++ b/arch/x86/kernel/machine_kexec_64.c @@ -28,6 +28,7 @@ #include #include #include +#include #ifdef CONFIG_ACPI /* @@ -90,6 +91,8 @@ map_efi_systab(struct x86_mapping_info *info, pgd_t *level4p) { #ifdef CONFIG_EFI unsigned long mstart, mend; + void *kaddr; + int ret; if (!efi_enabled(EFI_BOOT)) return 0; @@ -105,6 +108,30 @@ map_efi_systab(struct x86_mapping_info *info, pgd_t *level4p) if (!mstart) return 0; + ret = kernel_ident_mapping_init(info, level4p, mstart, mend); + if (ret) + return ret; + + kaddr = memremap(mstart, mend - mstart, MEMREMAP_WB); + if (!kaddr) { + pr_err("Could not map UEFI system table\n"); + return -ENOMEM; + } + + mstart = efi_config_table; + + if (efi_enabled(EFI_64BIT)) { + efi_system_table_64_t *stbl = (efi_system_table_64_t *)kaddr; + + mend = mstart + sizeof(efi_config_table_64_t) * stbl->nr_tables; + } else { + efi_system_table_32_t *stbl = (efi_system_table_32_t *)kaddr; + + mend = mstart + sizeof(efi_config_table_32_t) * stbl->nr_tables; + } + + memunmap(kaddr); + return kernel_ident_mapping_init(info, level4p, mstart, mend); #endif return 0; From e658227d9d4f4e122d81690fdbc0d438b10288f5 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Thu, 8 Aug 2024 11:14:42 +0200 Subject: [PATCH 042/267] ALSA: asihpi: Fix potential OOB array access [ Upstream commit 7b986c7430a6bb68d523dac7bfc74cbd5b44ef96 ] ASIHPI driver stores some values in the static array upon a response from the driver, and its index depends on the firmware. We shouldn't trust it blindly. This patch adds a sanity check of the array index to fit in the array size. Link: https://patch.msgid.link/20240808091454.30846-1-tiwai@suse.de Signed-off-by: Takashi Iwai Signed-off-by: Sasha Levin --- sound/pci/asihpi/hpimsgx.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/pci/asihpi/hpimsgx.c b/sound/pci/asihpi/hpimsgx.c index d0caef299481..b68e6bfbbfba 100644 --- a/sound/pci/asihpi/hpimsgx.c +++ b/sound/pci/asihpi/hpimsgx.c @@ -708,7 +708,7 @@ static u16 HPIMSGX__init(struct hpi_message *phm, phr->error = HPI_ERROR_PROCESSING_MESSAGE; return phr->error; } - if (hr.error == 0) { + if (hr.error == 0 && hr.u.s.adapter_index < HPI_MAX_ADAPTERS) { /* the adapter was created successfully save the mapping for future use */ hpi_entry_points[hr.u.s.adapter_index] = entry_point_func; From 9bf125a138f683d09ad3a49e3474418ddb0dc76f Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Thu, 8 Aug 2024 11:15:12 +0200 Subject: [PATCH 043/267] ALSA: hdsp: Break infinite MIDI input flush loop [ Upstream commit c01f3815453e2d5f699ccd8c8c1f93a5b8669e59 ] The current MIDI input flush on HDSP and HDSPM drivers relies on the hardware reporting the right value. If the hardware doesn't give the proper value but returns -1, it may be stuck at an infinite loop. Add a counter and break if the loop is unexpectedly too long. Link: https://patch.msgid.link/20240808091513.31380-1-tiwai@suse.de Signed-off-by: Takashi Iwai Signed-off-by: Sasha Levin --- sound/pci/rme9652/hdsp.c | 6 ++++-- sound/pci/rme9652/hdspm.c | 6 ++++-- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/sound/pci/rme9652/hdsp.c b/sound/pci/rme9652/hdsp.c index 65add92c88aa..cd7bf4d7ca08 100644 --- a/sound/pci/rme9652/hdsp.c +++ b/sound/pci/rme9652/hdsp.c @@ -1298,8 +1298,10 @@ static int snd_hdsp_midi_output_possible (struct hdsp *hdsp, int id) static void snd_hdsp_flush_midi_input (struct hdsp *hdsp, int id) { - while (snd_hdsp_midi_input_available (hdsp, id)) - snd_hdsp_midi_read_byte (hdsp, id); + int count = 256; + + while (snd_hdsp_midi_input_available(hdsp, id) && --count) + snd_hdsp_midi_read_byte(hdsp, id); } static int snd_hdsp_midi_output_write (struct hdsp_midi *hmidi) diff --git a/sound/pci/rme9652/hdspm.c b/sound/pci/rme9652/hdspm.c index fa1812e7a49d..247f5c52fb09 100644 --- a/sound/pci/rme9652/hdspm.c +++ b/sound/pci/rme9652/hdspm.c @@ -1838,8 +1838,10 @@ static inline int snd_hdspm_midi_output_possible (struct hdspm *hdspm, int id) static void snd_hdspm_flush_midi_input(struct hdspm *hdspm, int id) { - while (snd_hdspm_midi_input_available (hdspm, id)) - snd_hdspm_midi_read_byte (hdspm, id); + int count = 256; + + while (snd_hdspm_midi_input_available(hdspm, id) && --count) + snd_hdspm_midi_read_byte(hdspm, id); } static int snd_hdspm_midi_output_write (struct hdspm_midi *hmidi) From 0a13f60c95a48729628565184f06155fd17f2cea Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20Wei=C3=9Fschuh?= Date: Wed, 7 Aug 2024 23:51:44 +0200 Subject: [PATCH 044/267] selftests/nolibc: avoid passing NULL to printf("%s") MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [ Upstream commit f1a58f61d88642ae1e6e97e9d72d73bc70a93cb8 ] Clang on higher optimization levels detects that NULL is passed to printf("%s") and warns about it. While printf() from nolibc gracefully handles that NULL, it is undefined behavior as per POSIX, so the warning is reasonable. Avoid the warning by transforming NULL into a non-NULL placeholder. Reviewed-by: Shuah Khan Acked-by: Willy Tarreau Link: https://lore.kernel.org/r/20240807-nolibc-llvm-v2-8-c20f2f5fc7c2@weissschuh.net Signed-off-by: Thomas Weißschuh Signed-off-by: Sasha Levin --- tools/testing/selftests/nolibc/nolibc-test.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/testing/selftests/nolibc/nolibc-test.c b/tools/testing/selftests/nolibc/nolibc-test.c index f8e8e8d2a5e1..c6ef8b3e8345 100644 --- a/tools/testing/selftests/nolibc/nolibc-test.c +++ b/tools/testing/selftests/nolibc/nolibc-test.c @@ -353,7 +353,7 @@ static int expect_strzr(const char *expr, int llen) { int ret = 0; - llen += printf(" = <%s> ", expr); + llen += printf(" = <%s> ", expr ? expr : "(null)"); if (expr) { ret = 1; llen += pad_spc(llen, 40, "[FAIL]\n"); @@ -371,7 +371,7 @@ static int expect_strnz(const char *expr, int llen) { int ret = 0; - llen += printf(" = <%s> ", expr); + llen += printf(" = <%s> ", expr ? expr : "(null)"); if (!expr) { ret = 1; llen += pad_spc(llen, 40, "[FAIL]\n"); From 1553085fe990b06053555a34206a09cb21ff4e7f Mon Sep 17 00:00:00 2001 From: Kees Cook Date: Mon, 8 Jul 2024 13:22:06 -0700 Subject: [PATCH 045/267] x86/syscall: Avoid memcpy() for ia32 syscall_get_arguments() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [ Upstream commit d19d638b1e6cf746263ef60b7d0dee0204d8216a ] Modern (fortified) memcpy() prefers to avoid writing (or reading) beyond the end of the addressed destination (or source) struct member: In function ‘fortify_memcpy_chk’, inlined from ‘syscall_get_arguments’ at ./arch/x86/include/asm/syscall.h:85:2, inlined from ‘populate_seccomp_data’ at kernel/seccomp.c:258:2, inlined from ‘__seccomp_filter’ at kernel/seccomp.c:1231:3: ./include/linux/fortify-string.h:580:25: error: call to ‘__read_overflow2_field’ declared with attribute warning: detected read beyond size of field (2nd parameter); maybe use struct_group()? [-Werror=attribute-warning] 580 | __read_overflow2_field(q_size_field, size); | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ As already done for x86_64 and compat mode, do not use memcpy() to extract syscall arguments from struct pt_regs but rather just perform direct assignments. Binary output differences are negligible, and actually ends up using less stack space: - sub $0x84,%esp + sub $0x6c,%esp and less text size: text data bss dec hex filename 10794 252 0 11046 2b26 gcc-32b/kernel/seccomp.o.stock 10714 252 0 10966 2ad6 gcc-32b/kernel/seccomp.o.after Closes: https://lore.kernel.org/lkml/9b69fb14-df89-4677-9c82-056ea9e706f5@gmail.com/ Reported-by: Mirsad Todorovac Signed-off-by: Kees Cook Signed-off-by: Dave Hansen Reviewed-by: Gustavo A. R. Silva Acked-by: Dave Hansen Tested-by: Mirsad Todorovac Link: https://lore.kernel.org/all/20240708202202.work.477-kees%40kernel.org Signed-off-by: Sasha Levin --- arch/x86/include/asm/syscall.h | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/arch/x86/include/asm/syscall.h b/arch/x86/include/asm/syscall.h index 2725a4502321..bad79b82dfa0 100644 --- a/arch/x86/include/asm/syscall.h +++ b/arch/x86/include/asm/syscall.h @@ -82,7 +82,12 @@ static inline void syscall_get_arguments(struct task_struct *task, struct pt_regs *regs, unsigned long *args) { - memcpy(args, ®s->bx, 6 * sizeof(args[0])); + args[0] = regs->bx; + args[1] = regs->cx; + args[2] = regs->dx; + args[3] = regs->si; + args[4] = regs->di; + args[5] = regs->bp; } static inline int syscall_get_arch(struct task_struct *task) From 3c0d416eb4bef705f699213cee94bf54b6acdacd Mon Sep 17 00:00:00 2001 From: Kaixin Wang Date: Wed, 11 Sep 2024 22:29:52 +0800 Subject: [PATCH 046/267] fbdev: pxafb: Fix possible use after free in pxafb_task() [ Upstream commit 4a6921095eb04a900e0000da83d9475eb958e61e ] In the pxafb_probe function, it calls the pxafb_init_fbinfo function, after which &fbi->task is associated with pxafb_task. Moreover, within this pxafb_init_fbinfo function, the pxafb_blank function within the &pxafb_ops struct is capable of scheduling work. If we remove the module which will call pxafb_remove to make cleanup, it will call unregister_framebuffer function which can call do_unregister_framebuffer to free fbi->fb through put_fb_info(fb_info), while the work mentioned above will be used. The sequence of operations that may lead to a UAF bug is as follows: CPU0 CPU1 | pxafb_task pxafb_remove | unregister_framebuffer(info) | do_unregister_framebuffer(fb_info) | put_fb_info(fb_info) | // free fbi->fb | set_ctrlr_state(fbi, state) | __pxafb_lcd_power(fbi, 0) | fbi->lcd_power(on, &fbi->fb.var) | //use fbi->fb Fix it by ensuring that the work is canceled before proceeding with the cleanup in pxafb_remove. Note that only root user can remove the driver at runtime. Signed-off-by: Kaixin Wang Signed-off-by: Helge Deller Signed-off-by: Sasha Levin --- drivers/video/fbdev/pxafb.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/video/fbdev/pxafb.c b/drivers/video/fbdev/pxafb.c index 696ac5431180..492809d37414 100644 --- a/drivers/video/fbdev/pxafb.c +++ b/drivers/video/fbdev/pxafb.c @@ -2408,6 +2408,7 @@ static int pxafb_remove(struct platform_device *dev) info = &fbi->fb; pxafb_overlay_exit(fbi); + cancel_work_sync(&fbi->task); unregister_framebuffer(info); pxafb_disable_controller(fbi); From bc4da4cf2b8bbb1abef762c27490bf56b7a40dc1 Mon Sep 17 00:00:00 2001 From: "Paul E. McKenney" Date: Thu, 1 Aug 2024 17:43:03 -0700 Subject: [PATCH 047/267] rcuscale: Provide clear error when async specified without primitives [ Upstream commit 11377947b5861fa59bf77c827e1dd7c081842cc9 ] Currently, if the rcuscale module's async module parameter is specified for RCU implementations that do not have async primitives such as RCU Tasks Rude (which now lacks a call_rcu_tasks_rude() function), there will be a series of splats due to calls to a NULL pointer. This commit therefore warns of this situation, but switches to non-async testing. Signed-off-by: "Paul E. McKenney" Signed-off-by: Neeraj Upadhyay Signed-off-by: Sasha Levin --- kernel/rcu/rcuscale.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/kernel/rcu/rcuscale.c b/kernel/rcu/rcuscale.c index 0b88d96511ad..6595e166f6d5 100644 --- a/kernel/rcu/rcuscale.c +++ b/kernel/rcu/rcuscale.c @@ -449,7 +449,7 @@ rcu_scale_writer(void *arg) udelay(writer_holdoff); wdp = &wdpp[i]; *wdp = ktime_get_mono_fast_ns(); - if (gp_async) { + if (gp_async && !WARN_ON_ONCE(!cur_ops->async)) { retry: if (!rhp) rhp = kmalloc(sizeof(*rhp), GFP_KERNEL); @@ -505,7 +505,7 @@ retry: i++; rcu_scale_wait_shutdown(); } while (!torture_must_stop()); - if (gp_async) { + if (gp_async && cur_ops->async) { cur_ops->gp_barrier(); } writer_n_durations[me] = i_max + 1; From 85b778bc255437a2f07745a9a148cfb9856099db Mon Sep 17 00:00:00 2001 From: Marc Gonzalez Date: Tue, 20 Aug 2024 15:27:19 +0200 Subject: [PATCH 048/267] iommu/arm-smmu-qcom: hide last LPASS SMMU context bank from linux [ Upstream commit 3a8990b8a778219327c5f8ecf10b5d81377b925a ] On qcom msm8998, writing to the last context bank of lpass_q6_smmu (base address 0x05100000) produces a system freeze & reboot. The hardware/hypervisor reports 13 context banks for the LPASS SMMU on msm8998, but only the first 12 are accessible... Override the number of context banks [ 2.546101] arm-smmu 5100000.iommu: probing hardware configuration... [ 2.552439] arm-smmu 5100000.iommu: SMMUv2 with: [ 2.558945] arm-smmu 5100000.iommu: stage 1 translation [ 2.563627] arm-smmu 5100000.iommu: address translation ops [ 2.568923] arm-smmu 5100000.iommu: non-coherent table walk [ 2.574566] arm-smmu 5100000.iommu: (IDR0.CTTW overridden by FW configuration) [ 2.580220] arm-smmu 5100000.iommu: stream matching with 12 register groups [ 2.587263] arm-smmu 5100000.iommu: 13 context banks (0 stage-2 only) [ 2.614447] arm-smmu 5100000.iommu: Supported page sizes: 0x63315000 [ 2.621358] arm-smmu 5100000.iommu: Stage-1: 36-bit VA -> 36-bit IPA [ 2.627772] arm-smmu 5100000.iommu: preserved 0 boot mappings Specifically, the crashes occur here: qsmmu->bypass_cbndx = smmu->num_context_banks - 1; arm_smmu_cb_write(smmu, qsmmu->bypass_cbndx, ARM_SMMU_CB_SCTLR, 0); and here: arm_smmu_write_context_bank(smmu, i); arm_smmu_cb_write(smmu, i, ARM_SMMU_CB_FSR, ARM_SMMU_CB_FSR_FAULT); It is likely that FW reserves the last context bank for its own use, thus a simple work-around is: DON'T USE IT in Linux. If we decrease the number of context banks, last one will be "hidden". Signed-off-by: Marc Gonzalez Reviewed-by: Caleb Connolly Reviewed-by: Bjorn Andersson Link: https://lore.kernel.org/r/20240820-smmu-v3-1-2f71483b00ec@freebox.fr Signed-off-by: Will Deacon Signed-off-by: Sasha Levin --- drivers/iommu/arm/arm-smmu/arm-smmu-qcom.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/drivers/iommu/arm/arm-smmu/arm-smmu-qcom.c b/drivers/iommu/arm/arm-smmu/arm-smmu-qcom.c index f15dcb9e4175..3d1313ed7a84 100644 --- a/drivers/iommu/arm/arm-smmu/arm-smmu-qcom.c +++ b/drivers/iommu/arm/arm-smmu/arm-smmu-qcom.c @@ -273,6 +273,13 @@ static int qcom_smmu_cfg_probe(struct arm_smmu_device *smmu) u32 smr; int i; + /* + * MSM8998 LPASS SMMU reports 13 context banks, but accessing + * the last context bank crashes the system. + */ + if (of_device_is_compatible(smmu->dev->of_node, "qcom,msm8998-smmu-v2") && smmu->num_context_banks == 13) + smmu->num_context_banks = 12; + /* * Some platforms support more than the Arm SMMU architected maximum of * 128 stream matching groups. For unknown reasons, the additional From e0cf57612a3a9ec5f5223b40292a2c39236a4039 Mon Sep 17 00:00:00 2001 From: Andrew Davis Date: Mon, 10 Jun 2024 09:28:36 -0500 Subject: [PATCH 049/267] power: reset: brcmstb: Do not go into infinite loop if reset fails [ Upstream commit cf8c39b00e982fa506b16f9d76657838c09150cb ] There may be other backup reset methods available, do not halt here so that other reset methods can be tried. Signed-off-by: Andrew Davis Reviewed-by: Dhruva Gole Acked-by: Florian Fainelli Link: https://lore.kernel.org/r/20240610142836.168603-5-afd@ti.com Signed-off-by: Sebastian Reichel Signed-off-by: Sasha Levin --- drivers/power/reset/brcmstb-reboot.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/drivers/power/reset/brcmstb-reboot.c b/drivers/power/reset/brcmstb-reboot.c index 0f2944dc9355..a04713f191a1 100644 --- a/drivers/power/reset/brcmstb-reboot.c +++ b/drivers/power/reset/brcmstb-reboot.c @@ -62,9 +62,6 @@ static int brcmstb_restart_handler(struct notifier_block *this, return NOTIFY_DONE; } - while (1) - ; - return NOTIFY_DONE; } From cfc1def24b0a4101aa082b53bd3ec6a34830d93a Mon Sep 17 00:00:00 2001 From: Lu Baolu Date: Mon, 2 Sep 2024 10:27:13 +0800 Subject: [PATCH 050/267] iommu/vt-d: Always reserve a domain ID for identity setup [ Upstream commit 2c13012e09190174614fd6901857a1b8c199e17d ] We will use a global static identity domain. Reserve a static domain ID for it. Signed-off-by: Lu Baolu Reviewed-by: Jason Gunthorpe Reviewed-by: Kevin Tian Reviewed-by: Jerry Snitselaar Link: https://lore.kernel.org/r/20240809055431.36513-4-baolu.lu@linux.intel.com Signed-off-by: Joerg Roedel Signed-off-by: Sasha Levin --- drivers/iommu/intel/iommu.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/iommu/intel/iommu.c b/drivers/iommu/intel/iommu.c index 7b9502c30fe9..962b7370192a 100644 --- a/drivers/iommu/intel/iommu.c +++ b/drivers/iommu/intel/iommu.c @@ -1697,10 +1697,10 @@ static int iommu_init_domains(struct intel_iommu *iommu) * entry for first-level or pass-through translation modes should * be programmed with a domain id different from those used for * second-level or nested translation. We reserve a domain id for - * this purpose. + * this purpose. This domain id is also used for identity domain + * in legacy mode. */ - if (sm_supported(iommu)) - set_bit(FLPT_DEFAULT_DID, iommu->domain_ids); + set_bit(FLPT_DEFAULT_DID, iommu->domain_ids); return 0; } From e03f00aa4a6c0c49c17857a4048f586636abdc32 Mon Sep 17 00:00:00 2001 From: Sanjay K Kumar Date: Mon, 2 Sep 2024 10:27:18 +0800 Subject: [PATCH 051/267] iommu/vt-d: Fix potential lockup if qi_submit_sync called with 0 count [ Upstream commit 3cf74230c139f208b7fb313ae0054386eee31a81 ] If qi_submit_sync() is invoked with 0 invalidation descriptors (for instance, for DMA draining purposes), we can run into a bug where a submitting thread fails to detect the completion of invalidation_wait. Subsequently, this led to a soft lockup. Currently, there is no impact by this bug on the existing users because no callers are submitting invalidations with 0 descriptors. This fix will enable future users (such as DMA drain) calling qi_submit_sync() with 0 count. Suppose thread T1 invokes qi_submit_sync() with non-zero descriptors, while concurrently, thread T2 calls qi_submit_sync() with zero descriptors. Both threads then enter a while loop, waiting for their respective descriptors to complete. T1 detects its completion (i.e., T1's invalidation_wait status changes to QI_DONE by HW) and proceeds to call reclaim_free_desc() to reclaim all descriptors, potentially including adjacent ones of other threads that are also marked as QI_DONE. During this time, while T2 is waiting to acquire the qi->q_lock, the IOMMU hardware may complete the invalidation for T2, setting its status to QI_DONE. However, if T1's execution of reclaim_free_desc() frees T2's invalidation_wait descriptor and changes its status to QI_FREE, T2 will not observe the QI_DONE status for its invalidation_wait and will indefinitely remain stuck. This soft lockup does not occur when only non-zero descriptors are submitted.In such cases, invalidation descriptors are interspersed among wait descriptors with the status QI_IN_USE, acting as barriers. These barriers prevent the reclaim code from mistakenly freeing descriptors belonging to other submitters. Considered the following example timeline: T1 T2 ======================================== ID1 WD1 while(WD1!=QI_DONE) unlock lock WD1=QI_DONE* WD2 while(WD2!=QI_DONE) unlock lock WD1==QI_DONE? ID1=QI_DONE WD2=DONE* reclaim() ID1=FREE WD1=FREE WD2=FREE unlock soft lockup! T2 never sees QI_DONE in WD2 Where: ID = invalidation descriptor WD = wait descriptor * Written by hardware The root of the problem is that the descriptor status QI_DONE flag is used for two conflicting purposes: 1. signal a descriptor is ready for reclaim (to be freed) 2. signal by the hardware that a wait descriptor is complete The solution (in this patch) is state separation by using QI_FREE flag for #1. Once a thread's invalidation descriptors are complete, their status would be set to QI_FREE. The reclaim_free_desc() function would then only free descriptors marked as QI_FREE instead of those marked as QI_DONE. This change ensures that T2 (from the previous example) will correctly observe the completion of its invalidation_wait (marked as QI_DONE). Signed-off-by: Sanjay K Kumar Signed-off-by: Jacob Pan Reviewed-by: Kevin Tian Link: https://lore.kernel.org/r/20240728210059.1964602-1-jacob.jun.pan@linux.intel.com Signed-off-by: Lu Baolu Signed-off-by: Joerg Roedel Signed-off-by: Sasha Levin --- drivers/iommu/intel/dmar.c | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/drivers/iommu/intel/dmar.c b/drivers/iommu/intel/dmar.c index 345c161ffb27..76fa7d823b3d 100644 --- a/drivers/iommu/intel/dmar.c +++ b/drivers/iommu/intel/dmar.c @@ -1182,9 +1182,7 @@ static void free_iommu(struct intel_iommu *iommu) */ static inline void reclaim_free_desc(struct q_inval *qi) { - while (qi->desc_status[qi->free_tail] == QI_DONE || - qi->desc_status[qi->free_tail] == QI_ABORT) { - qi->desc_status[qi->free_tail] = QI_FREE; + while (qi->desc_status[qi->free_tail] == QI_FREE && qi->free_tail != qi->free_head) { qi->free_tail = (qi->free_tail + 1) % QI_LENGTH; qi->free_cnt++; } @@ -1419,8 +1417,16 @@ restart: raw_spin_lock(&qi->q_lock); } - for (i = 0; i < count; i++) - qi->desc_status[(index + i) % QI_LENGTH] = QI_DONE; + /* + * The reclaim code can free descriptors from multiple submissions + * starting from the tail of the queue. When count == 0, the + * status of the standalone wait descriptor at the tail of the queue + * must be set to QI_FREE to allow the reclaim code to proceed. + * It is also possible that descriptors from one of the previous + * submissions has to be reclaimed by a subsequent submission. + */ + for (i = 0; i <= count; i++) + qi->desc_status[(index + i) % QI_LENGTH] = QI_FREE; reclaim_free_desc(qi); raw_spin_unlock_irqrestore(&qi->q_lock, flags); From d02611ff001454358be6910cb926799e2d818716 Mon Sep 17 00:00:00 2001 From: Katya Orlova Date: Fri, 16 Feb 2024 15:50:40 +0300 Subject: [PATCH 052/267] drm/stm: Avoid use-after-free issues with crtc and plane MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [ Upstream commit 19dd9780b7ac673be95bf6fd6892a184c9db611f ] ltdc_load() calls functions drm_crtc_init_with_planes(), drm_universal_plane_init() and drm_encoder_init(). These functions should not be called with parameters allocated with devm_kzalloc() to avoid use-after-free issues [1]. Use allocations managed by the DRM framework. Found by Linux Verification Center (linuxtesting.org). [1] https://lore.kernel.org/lkml/u366i76e3qhh3ra5oxrtngjtm2u5lterkekcz6y2jkndhuxzli@diujon4h7qwb/ Signed-off-by: Katya Orlova Acked-by: Raphaël Gallais-Pou Link: https://patchwork.freedesktop.org/patch/msgid/20240216125040.8968-1-e.orlova@ispras.ru Signed-off-by: Raphael Gallais-Pou Signed-off-by: Sasha Levin --- drivers/gpu/drm/stm/drv.c | 3 +- drivers/gpu/drm/stm/ltdc.c | 73 ++++++++++---------------------------- 2 files changed, 20 insertions(+), 56 deletions(-) diff --git a/drivers/gpu/drm/stm/drv.c b/drivers/gpu/drm/stm/drv.c index 77b1b10456f5..7a3f1b402029 100644 --- a/drivers/gpu/drm/stm/drv.c +++ b/drivers/gpu/drm/stm/drv.c @@ -24,6 +24,7 @@ #include #include #include +#include #include "ltdc.h" @@ -74,7 +75,7 @@ static int drv_load(struct drm_device *ddev) DRM_DEBUG("%s\n", __func__); - ldev = devm_kzalloc(ddev->dev, sizeof(*ldev), GFP_KERNEL); + ldev = drmm_kzalloc(ddev, sizeof(*ldev), GFP_KERNEL); if (!ldev) return -ENOMEM; diff --git a/drivers/gpu/drm/stm/ltdc.c b/drivers/gpu/drm/stm/ltdc.c index b8c1636168cf..1d22afcf34ba 100644 --- a/drivers/gpu/drm/stm/ltdc.c +++ b/drivers/gpu/drm/stm/ltdc.c @@ -37,6 +37,7 @@ #include #include #include +#include #include