6.11.3-rc1 review
Subsystems (4)
Greg Kroah-Hartman
maintainerPATCH 127/558 wifi: rtw89: correct base HT rate mask for firmware
In reply to Greg Kroah-Hartman6.11-stable review patch. If anyone has any objections, please let me know.
------------------
From: Ping-Ke Shih <[email protected]>
[ 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")
--- drivers/net/wireless/realtek/rtw89/phy.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
drivers/net/wireless/realtek/rtw89/phy.c +2 -2
@@ -353,8 +353,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 ;
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 128/558 netfilter: nf_tables: do not remove elements if set backend implements .abort
In reply to Greg Kroah-Hartman6.11-stable review patch. If anyone has any objections, please let me know.
------------------
From: Pablo Neira Ayuso <[email protected]>
[ Upstream commit c9526aeb4998393171d85225ff540e28c7d4ab86 ]
pipapo set backend maintains two copies of the datastructure, removing the elements from the copy that is going to be discarded slows down the abort path significantly, from several minutes to few seconds after this patch.
This patch was previously reverted by
f86fb94011ae ("netfilter: nf_tables: revert do not remove elements if set backend implements .abort")
but it is now possible since recent work by Florian Westphal to perform on-demand clone from insert/remove path:
532aec7e878b ("netfilter: nft_set_pipapo: remove dirty flag")
3f1d886cc7c3 ("netfilter: nft_set_pipapo: move cloning of match info to insert/removal path") a238106703ab ("netfilter: nft_set_pipapo: prepare pipapo_get helper for on-demand clone") c5444786d0ea ("netfilter: nft_set_pipapo: merge deactivate helper into caller") 6c108d9bee44 ("netfilter: nft_set_pipapo: prepare walk function for on-demand clone") 8b8a2417558c ("netfilter: nft_set_pipapo: prepare destroy function for on-demand clone") 80efd2997fb9 ("netfilter: nft_set_pipapo: make pipapo_clone helper return NULL") a590f4760922 ("netfilter: nft_set_pipapo: move prove_locking helper around")
after this series, the clone is fully released once aborted, no need to take it back to previous state. Thus, no stale reference to elements can occur.
--- net/netfilter/nf_tables_api.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-)
net/netfilter/nf_tables_api.c +4 -1
@@ -10795,7 +10795,10 @@ static int __nf_tables_abort(struct net *net, enum nfnl_abort_action action)break ; } te =nft_trans_container_elem (trans); -nft_setelem_remove (net, te->set, te->elem_priv); +if (!te->set->ops->abort || +nft_setelem_is_catchall (te->set, te->elem_priv)) +nft_setelem_remove (net, te->set, te->elem_priv); +if (!nft_setelem_is_catchall (te->set, te->elem_priv))atomic_dec (&te->set->nelems);
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 129/558 ipv4: Mask upper DSCP bits and ECN bits in NETLINK_FIB_LOOKUP family
In reply to Greg Kroah-Hartman6.11-stable review patch. If anyone has any objections, please let me know.
------------------
From: Ido Schimmel <[email protected]>
[ 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/
--- net/ipv4/fib_frontend.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
net/ipv4/fib_frontend.c +1 -1
@@ -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;
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 130/558 nvme-keyring: restrict match length for version 1 identifiers
In reply to Greg Kroah-Hartman6.11-stable review patch. If anyone has any objections, please let me know.
------------------
From: Hannes Reinecke <[email protected]>
[ Upstream commit 79559c75332458985ab8a21f11b08bf7c9b833b0 ]
TP8018 introduced a new TLS PSK identifier version (version 1), which appended a PSK hash value to the existing identifier (cf NVMe TCP specification v1.1, section 3.6.1.3 'TLS PSK and PSK Identity Derivation').
An original (version 0) identifier has the form:
NVMe0<type><hmac> <hostnqn> <subsysnqn>
and a version 1 identifier has the form:
NVMe1<type><hmac> <hostnqn> <subsysnqn> <hash>
This patch modifies the lookup algorthm to compare only the first part of the identifier (excluding the hash value) to handle both version 0 and version 1 identifiers.
And the spec declares 'version 0' identifiers obsolete, so the lookup algorithm is modified to prever v1 identifiers.
--- drivers/nvme/common/keyring.c | 36 +++++++++++++++++++++++++---------- 1 file changed, 26 insertions(+), 10 deletions(-)
drivers/nvme/common/keyring.c +26 -10
@@ -36,14 +36,12 @@ static bool nvme_tls_psk_match(const struct key *key,pr_debug ("%s: no key description\n" , __func__);return false; } - match_len =strlen (key->description); -pr_debug ("%s: id %s len %zd\n" , __func__, key->description, match_len); -if (!match_data->raw_data) {pr_debug ("%s: no match data\n" , __func__);return false; } match_id = match_data->raw_data; + match_len =strlen (match_id);pr_debug ("%s: match '%s' '%s' len %zd\n" , __func__, match_id, key->description, match_len);return !memcmp (key->description, match_id, match_len);
@@ -71,7 +69,7 @@ static struct key_type nvme_tls_psk_key_type = {static struct key *nvme_tls_psk_lookup (struct key *keyring,const char *hostnqn,const char *subnqn, -int hmac,bool generated) +u8 hmac,u8 psk_ver,bool generated) {char *identity;size_t identity_len = (NVMF_NQN_SIZE ) *2 +11 ;
@@ -82,8 +80,8 @@ static struct key *nvme_tls_psk_lookup(struct key *keyring,if (!identity)return ERR_PTR (-ENOMEM ); -snprintf (identity, identity_len,"NVMe0%c%02d %s %s" , - generated ?'G' :'R' , hmac, hostnqn, subnqn); +snprintf (identity, identity_len,"NVMe%u%c%02u %s %s" , + psk_ver, generated ?'G' :'R' , hmac, hostnqn, subnqn);if (!keyring) keyring = nvme_keyring;
@@ -107,21 +105,38 @@ static struct key *nvme_tls_psk_lookup(struct key *keyring,/* * NVMe PSK priority list * -* 'Retained' PSKs (ie 'generated == false') -* should be preferred to 'generated' PSKs, -* and SHA-384 should be preferred to SHA-256. +* 'Retained' PSKs (ie 'generated == false') should be preferred to 'generated' +* PSKs, PSKs with hash (psk_ver 1) should be preferred to PSKs without hash +* (psk_ver 0), and SHA-384 should be preferred to SHA-256. */ static struct nvme_tls_psk_priority_list {bool generated; +u8 psk_ver;enum nvme_tcp_tls_cipher cipher; } nvme_tls_psk_prio[] = { { .generated = false, + .psk_ver =1 , + .cipher =NVME_TCP_TLS_CIPHER_SHA384 , }, + { .generated = false, + .psk_ver =1 , + .cipher =NVME_TCP_TLS_CIPHER_SHA256 , }, + { .generated = false, + .psk_ver =0 , .cipher =NVME_TCP_TLS_CIPHER_SHA384 , }, { .generated = false, + .psk_ver =0 , + .cipher =NVME_TCP_TLS_CIPHER_SHA256 , }, + { .generated = true, + .psk_ver =1 , + .cipher =NVME_TCP_TLS_CIPHER_SHA384 , }, + { .generated = true, + .psk_ver =1 , .cipher =NVME_TCP_TLS_CIPHER_SHA256 , }, { .generated = true, + .psk_ver =0 , .cipher =NVME_TCP_TLS_CIPHER_SHA384 , }, { .generated = true, + .psk_ver =0 , .cipher =NVME_TCP_TLS_CIPHER_SHA256 , }, };
@@ -137,10 +152,11 @@ key_serial_t nvme_tls_psk_default(struct key *keyring,for (prio =0 ; prio <ARRAY_SIZE (nvme_tls_psk_prio); prio++) {bool generated = nvme_tls_psk_prio[prio].generated; +u8 ver = nvme_tls_psk_prio[prio].psk_ver;enum nvme_tcp_tls_cipher cipher = nvme_tls_psk_prio[prio].cipher; tls_key =nvme_tls_psk_lookup (keyring, hostnqn, subnqn, - cipher, generated); + cipher, ver, generated);if (!IS_ERR (tls_key)) { tls_key_id = tls_key->serial;key_put (tls_key);
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 131/558 nvme-tcp: sanitize TLS key handling
In reply to Greg Kroah-Hartman6.11-stable review patch. If anyone has any objections, please let me know.
------------------
From: Hannes Reinecke <[email protected]>
[ Upstream commit 363895767fbfa05891b0b4d9e06ebde7a10c6a07 ]
There is a difference between TLS configured (ie the user has provisioned/requested a key) and TLS enabled (ie the connection is encrypted with TLS). This becomes important for secure concatenation, where the initial authentication is run on an unencrypted connection (ie with TLS configured, but not enabled), and then the queue is reset to run over TLS (ie TLS configured _and_ enabled).
So to differentiate between those two states store the generated key in opts->tls_key (as we're using the same TLS key for all queues), the key serial of the resulting TLS handshake in ctrl->tls_pskid (to signal that TLS on the admin queue is enabled), and a simple flag for the queues to indicated that TLS has been enabled.
--- drivers/nvme/host/core.c | 1 - drivers/nvme/host/nvme.h | 2 +- drivers/nvme/host/sysfs.c | 4 +-- drivers/nvme/host/tcp.c | 53 +++++++++++++++++++++++++++++---------- 4 files changed, 43 insertions(+), 17 deletions(-)
drivers/nvme/host/core.c +0 -1
@@ -4678,7 +4678,6 @@ static void nvme_free_ctrl(struct device *dev)if (!subsys || ctrl->instance != subsys->instance)ida_free (&nvme_instance_ida, ctrl->instance); -key_put (ctrl->tls_key);nvme_free_cels (ctrl);nvme_mpath_uninit (ctrl);cleanup_srcu_struct (&ctrl->srcu);
drivers/nvme/host/nvme.h +1 -1
@@ -377,7 +377,7 @@ struct nvme_ctrl {struct nvme_dhchap_key *ctrl_key;u16 transaction;#endif -struct key *tls_key; +key_serial_t tls_pskid;/* Power saving configuration */ u64 ps_max_latency_us;
drivers/nvme/host/sysfs.c +2 -2
@@ -670,9 +670,9 @@ static ssize_t tls_key_show(struct device *dev, {struct nvme_ctrl *ctrl =dev_get_drvdata (dev); -if (!ctrl->tls_key) +if (!ctrl->tls_pskid)return 0 ; -return sysfs_emit (buf,"%08x" ,key_serial (ctrl->tls_key)); +return sysfs_emit (buf,"%08x" , ctrl->tls_pskid); }static DEVICE_ATTR_RO (tls_key);#endif
drivers/nvme/host/tcp.c +40 -13
129 lines not on this page · raw message
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 132/558 nvme-tcp: check for invalidated or revoked key
In reply to Greg Kroah-Hartman6.11-stable review patch. If anyone has any objections, please let me know.
------------------
From: Hannes Reinecke <[email protected]>
[ Upstream commit 5bc46b49c828a6dfaab80b71ecb63fe76a1096d2 ]
key_lookup() will always return a key, even if that key is revoked or invalidated. So check for invalid keys before continuing.
--- drivers/nvme/common/keyring.c | 22 ++++++++++++++++++++++ drivers/nvme/host/Kconfig | 1 + drivers/nvme/host/fabrics.c | 2 +- drivers/nvme/host/tcp.c | 2 +- include/linux/nvme-keyring.h | 6 +++++- 5 files changed, 30 insertions(+), 3 deletions(-)
drivers/nvme/common/keyring.c +22 -0
@@ -20,6 +20,28 @@ key_serial_t nvme_keyring_id(void) }EXPORT_SYMBOL_GPL (nvme_keyring_id); +static bool nvme_tls_psk_revoked (struct key *psk) +{ +return test_bit (KEY_FLAG_REVOKED , &psk->flags) || +test_bit (KEY_FLAG_INVALIDATED , &psk->flags); +} + +struct key *nvme_tls_key_lookup (key_serial_t key_id) +{ +struct key *key =key_lookup (key_id); + +if (IS_ERR (key)) { +pr_err ("key id %08x not found\n" , key_id); +return key; + } +if (nvme_tls_psk_revoked (key)) { +pr_err ("key id %08x revoked\n" , key_id); +return ERR_PTR (-EKEYREVOKED ); + } +return key; +} +EXPORT_SYMBOL_GPL (nvme_tls_key_lookup); +static void nvme_tls_psk_describe (const struct key *key,struct seq_file *m) {seq_puts (m, key->description);
drivers/nvme/host/Kconfig +1 -0
@@ -109,6 +109,7 @@ config NVME_HOST_AUTH bool "NVMe over Fabrics In-Band Authentication in host side" depends on NVME_CORE select NVME_AUTH + select NVME_KEYRING if NVME_TCP_TLS help This provides support for NVMe over Fabrics In-Band Authentication in host side.
drivers/nvme/host/fabrics.c +1 -1
@@ -665,7 +665,7 @@ static struct key *nvmf_parse_key(int key_id)return ERR_PTR (-EINVAL ); } - key =key_lookup (key_id); + key =nvme_tls_key_lookup (key_id);if (IS_ERR (key))pr_err ("key id %08x not found\n" , key_id);else
drivers/nvme/host/tcp.c +1 -1
@@ -1596,7 +1596,7 @@ static void nvme_tcp_tls_done(void *data, int status, key_serial_t pskid) goto out_complete; } - tls_key =key_lookup (pskid); + tls_key =nvme_tls_key_lookup (pskid);if (IS_ERR (tls_key)) {dev_warn (ctrl->ctrl.device,"queue %d: Invalid key %x\n" , qid, pskid);
include/linux/nvme-keyring.h +5 -1
@@ -12,7 +12,7 @@ key_serial_t nvme_tls_psk_default(struct key *keyring, const char *hostnqn, const char *subnqn);key_serial_t nvme_keyring_id (void ); - +struct key *nvme_tls_key_lookup (key_serial_t key_id);#else static inline key_serial_t nvme_tls_psk_default(struct key *keyring,
@@ -24,5 +24,9 @@ static inline key_serial_t nvme_keyring_id(void) {return 0 ; } +static inline struct key *nvme_tls_key_lookup (key_serial_t key_id) +{ +return ERR_PTR (-ENOTSUPP ); +}#endif /* !CONFIG_NVME_KEYRING */ #endif /* _NVME_KEYRING_H */
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 133/558 net: atlantic: Avoid warning about potential string truncation
In reply to Greg Kroah-Hartman6.11-stable review patch. If anyone has any objections, please let me know.
------------------
From: Simon Horman <[email protected]>
[ 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.
--- drivers/net/ethernet/aquantia/atlantic/aq_ethtool.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
drivers/net/ethernet/aquantia/atlantic/aq_ethtool.c +2 -2
@@ -266,7 +266,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,
@@ -275,7 +275,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++) {
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 134/558 crypto: simd - Do not call crypto_alloc_tfm during registration
In reply to Greg Kroah-Hartman6.11-stable review patch. If anyone has any objections, please let me know.
------------------
From: Herbert Xu <[email protected]>
[ 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.
--- 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(-)
arch/arm/crypto/aes-ce-glue.c +1 -1
@@ -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;
arch/arm/crypto/aes-neonbs-glue.c +1 -1
@@ -540,7 +540,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;
crypto/simd.c +15 -61
149 lines not on this page · raw message
include/crypto/internal/simd.h +2 -10
@@ -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);
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 135/558 netpoll: Ensure clean state on setup failures
In reply to Greg Kroah-Hartman6.11-stable review patch. If anyone has any objections, please let me know.
------------------
From: Breno Leitao <[email protected]>
[ Upstream commit ae5a0456e0b4cfd7e61619e55251ffdf1bc7adfb ]
Modify netpoll_setup() and __netpoll_setup() to ensure that the netpoll structure (np) is left in a clean state if setup fails for any reason. This prevents carrying over misconfigured fields in case of partial setup success.
Key changes:
- np->dev is now set only after successful setup, ensuring it's always NULL if netpoll is not configured or if netpoll_setup() fails.
- np->local_ip is zeroed if netpoll setup doesn't complete successfully.
- Added DEBUG_NET_WARN_ON_ONCE() checks to catch unexpected states.
- Reordered some operations in __netpoll_setup() for better logical flow.
These changes improve the reliability of netpoll configuration, since it assures that the structure is fully initialized or totally unset.
--- net/core/netpoll.c | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-)
net/core/netpoll.c +10 -5
@@ -624,12 +624,9 @@ int __netpoll_setup(struct netpoll *np, struct net_device *ndev)const struct net_device_ops *ops;int err; - np->dev = ndev; -strscpy (np->dev_name, ndev->name,IFNAMSIZ ); -if (ndev->priv_flags &IFF_DISABLE_NETPOLL ) {np_err (np,"%s doesn't support polling, aborting\n" , - np->dev_name); + ndev->name); err = -ENOTSUPP ; goto out; }
@@ -647,7 +644,7 @@ int __netpoll_setup(struct netpoll *np, struct net_device *ndev)refcount_set (&npinfo->refcnt,1 ); - ops = np->dev->netdev_ops; + ops = ndev->netdev_ops;if (ops->ndo_netpoll_setup) { err = ops->ndo_netpoll_setup (ndev, npinfo);if (err)
@@ -658,6 +655,8 @@ int __netpoll_setup(struct netpoll *np, struct net_device *ndev)refcount_inc (&npinfo->refcnt); } + np->dev = ndev; +strscpy (np->dev_name, ndev->name,IFNAMSIZ ); npinfo->netpoll = np;/* last thing to do is link it to the net device structure */
@@ -675,6 +674,7 @@ EXPORT_SYMBOL_GPL(__netpoll_setup);int netpoll_setup (struct netpoll *np) {struct net_device *ndev =NULL ; +bool ip_overwritten = false;struct in_device *in_dev;int err;
@@ -739,6 +739,7 @@ int netpoll_setup(struct netpoll *np) } np->local_ip.ip = ifa->ifa_local; + ip_overwritten = true;np_info (np,"local IP %pI4\n" , &np->local_ip.ip); }else {#if IS_ENABLED (CONFIG_IPV6 )
@@ -755,6 +756,7 @@ int netpoll_setup(struct netpoll *np) !!(ipv6_addr_type(&np->remote_ip.in6) & IPV6_ADDR_LINKLOCAL)) continue; np->local_ip.in6 = ifp->addr; + ip_overwritten = true; err =0 ;break ; }
@@ -785,6 +787,9 @@ int netpoll_setup(struct netpoll *np)return 0 ; put: +DEBUG_NET_WARN_ON_ONCE (np->dev); +if (ip_overwritten) +memset (&np->local_ip,0 ,sizeof (np->local_ip));netdev_put (ndev, &np->dev_tracker); unlock:rtnl_unlock ();
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 136/558 tcp: avoid reusing FIN_WAIT2 when trying to find port in connect() process
In reply to Greg Kroah-Hartman6.11-stable review patch. If anyone has any objections, please let me know.
------------------
From: Jason Xing <[email protected]>
[ 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."
--- net/ipv4/tcp_ipv4.c | 3 +++ 1 file changed, 3 insertions(+)
net/ipv4/tcp_ipv4.c +3 -0
@@ -120,6 +120,9 @@ int tcp_twsk_unique(struct sock *sk, struct sock *sktw, void *twp)struct tcp_sock *tp =tcp_sk (sk);int ts_recent_stamp; +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
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 137/558 wifi: iwlwifi: mvm: use correct key iteration
In reply to Greg Kroah-Hartman6.11-stable review patch. If anyone has any objections, please let me know.
------------------
From: Johannes Berg <[email protected]>
[ Upstream commit 4f1591d292277eec51d027405a92f0d4ef5e299e ]
In the cases changed here, key iteration isn't done from an RCU critical section, but rather using the wiphy lock as protection. Therefore, just use ieee80211_iter_keys(). The link switch case can therefore also use sync commands.
--- drivers/net/wireless/intel/iwlwifi/mvm/mld-key.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-)
drivers/net/wireless/intel/iwlwifi/mvm/mld-key.c +6 -6
@@ -144,7 +144,7 @@ static void iwl_mvm_mld_update_sta_key(struct ieee80211_hw *hw,if (sta != data->sta || key->link_id >=0 )return ; - err =iwl_mvm_send_cmd_pdu (mvm, cmd_id,CMD_ASYNC ,sizeof (cmd), &cmd); + err =iwl_mvm_send_cmd_pdu (mvm, cmd_id,0 ,sizeof (cmd), &cmd);if (err) data->err = err;
@@ -162,8 +162,8 @@ int iwl_mvm_mld_update_sta_keys(struct iwl_mvm *mvm, .new_sta_mask = new_sta_mask, }; -ieee80211_iter_keys_rcu (mvm->hw, vif, iwl_mvm_mld_update_sta_key, - &data); +ieee80211_iter_keys (mvm->hw, vif, iwl_mvm_mld_update_sta_key, + &data);return data.err; }
@@ -402,7 +402,7 @@ void iwl_mvm_sec_key_remove_ap(struct iwl_mvm *mvm,if (!sec_key_ver)return ; -ieee80211_iter_keys_rcu (mvm->hw, vif, - iwl_mvm_sec_key_remove_ap_iter, - (void *)(uintptr_t )link_id); +ieee80211_iter_keys (mvm->hw, vif, + iwl_mvm_sec_key_remove_ap_iter, + (void *)(uintptr_t )link_id); }
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 138/558 wifi: iwlwifi: allow only CN mcc from WRDD
In reply to Greg Kroah-Hartman6.11-stable review patch. If anyone has any objections, please let me know.
------------------
From: Anjaneyulu <[email protected]>
[ Upstream commit ff5aabe7c2a4a4b089a9ced0cb3d0e284963a7dd ]
Block other mcc expect CN from WRDD ACPI.
--- drivers/net/wireless/intel/iwlwifi/fw/acpi.c | 5 +++++ drivers/net/wireless/intel/iwlwifi/fw/regulatory.h | 2 ++ drivers/net/wireless/intel/iwlwifi/fw/uefi.c | 2 +- drivers/net/wireless/intel/iwlwifi/fw/uefi.h | 2 -- 4 files changed, 8 insertions(+), 3 deletions(-)
drivers/net/wireless/intel/iwlwifi/fw/acpi.c +5 -0
@@ -357,6 +357,11 @@ int iwl_acpi_get_mcc(struct iwl_fw_runtime *fwrt, char *mcc) } mcc_val = wifi_pkg->package.elements[1 ].integer.value; +if (mcc_val !=BIOS_MCC_CHINA ) { + ret = -EINVAL ; +IWL_DEBUG_RADIO (fwrt,"ACPI WRDD is supported only for CN\n" ); + goto out_free; + } mcc[0 ] = (mcc_val >>8 ) &0xff ; mcc[1 ] = mcc_val &0xff ;
drivers/net/wireless/intel/iwlwifi/fw/regulatory.h +2 -0
@@ -45,6 +45,8 @@#define IWL_WTAS_ENABLE_IEC_MSK 0x4#define IWL_WTAS_USA_UHB_MSK BIT(16) +#define BIOS_MCC_CHINA 0x434e +/* * The profile for revision 2 is a superset of revision 1, which is in * turn a superset of revision 0. So we can store all revisions
drivers/net/wireless/intel/iwlwifi/fw/uefi.c +1 -1
@@ -638,7 +638,7 @@ int iwl_uefi_get_mcc(struct iwl_fw_runtime *fwrt, char *mcc) goto out; } -if (data->mcc !=UEFI_MCC_CHINA ) { +if (data->mcc !=BIOS_MCC_CHINA ) { ret = -EINVAL ;IWL_DEBUG_RADIO (fwrt,"UEFI WRDD is supported only for CN\n" ); goto out;
drivers/net/wireless/intel/iwlwifi/fw/uefi.h +0 -2
@@ -149,8 +149,6 @@ struct uefi_cnv_var_splc {u32 default_pwr_limit; } __packed; -#define UEFI_MCC_CHINA 0x434e -/* struct uefi_cnv_var_wrdd - WRDD table as defined in UEFI * @revision: the revision of the table * @mcc: country identifier as defined in ISO/IEC 3166-1 Alpha 2 code
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 139/558 wifi: iwlwifi: mvm: avoid NULL pointer dereference
In reply to Greg Kroah-Hartman6.11-stable review patch. If anyone has any objections, please let me know.
------------------
From: Miri Korenblit <[email protected]>
[ Upstream commit 557a6cd847645e667f3b362560bd7e7c09aac284 ]
iwl_mvm_tx_skb_sta() and iwl_mvm_tx_mpdu() verify that the mvmvsta pointer is not NULL.
It retrieves this pointer using iwl_mvm_sta_from_mac80211, which is dereferencing the ieee80211_sta pointer.
If sta is NULL, iwl_mvm_sta_from_mac80211 will dereference a NULL pointer.
Fix this by checking the sta pointer before retrieving the mvmsta from it. If sta is not NULL, then mvmsta isn't either.
--- drivers/net/wireless/intel/iwlwifi/mvm/tx.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-)
drivers/net/wireless/intel/iwlwifi/mvm/tx.c +7 -5
@@ -1203,6 +1203,9 @@ static int iwl_mvm_tx_mpdu(struct iwl_mvm *mvm, struct sk_buff *skb,bool is_ampdu = false;int hdrlen; +if (WARN_ON_ONCE (!sta)) +return -1 ; + mvmsta =iwl_mvm_sta_from_mac80211 (sta); fc = hdr->frame_control; hdrlen =ieee80211_hdrlen (fc);
@@ -1210,9 +1213,6 @@ static int iwl_mvm_tx_mpdu(struct iwl_mvm *mvm, struct sk_buff *skb,if (IWL_MVM_NON_TRANSMITTING_AP &&ieee80211_is_probe_resp (fc))return -1 ; -if (WARN_ON_ONCE (!mvmsta)) -return -1 ; -if (WARN_ON_ONCE (mvmsta->deflink.sta_id ==IWL_MVM_INVALID_STA ))return -1 ;
@@ -1343,7 +1343,7 @@ static int iwl_mvm_tx_mpdu(struct iwl_mvm *mvm, struct sk_buff *skb,int iwl_mvm_tx_skb_sta (struct iwl_mvm *mvm,struct sk_buff *skb,struct ieee80211_sta *sta) { -struct iwl_mvm_sta *mvmsta =iwl_mvm_sta_from_mac80211 (sta); +struct iwl_mvm_sta *mvmsta;struct ieee80211_tx_info info;struct sk_buff_head mpdus_skbs;struct ieee80211_vif *vif;
@@ -1352,9 +1352,11 @@ int iwl_mvm_tx_skb_sta(struct iwl_mvm *mvm, struct sk_buff *skb,struct sk_buff *orig_skb = skb;const u8 *addr3; -if (WARN_ON_ONCE (!mvmsta)) +if (WARN_ON_ONCE (!sta))return -1 ; + mvmsta =iwl_mvm_sta_from_mac80211 (sta); +if (WARN_ON_ONCE (mvmsta->deflink.sta_id ==IWL_MVM_INVALID_STA ))return -1 ;
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 140/558 virt: sev-guest: Ensure the SNP guest messages do not exceed a page
In reply to Greg Kroah-Hartman6.11-stable review patch. If anyone has any objections, please let me know.
------------------
From: Nikunj A Dadhania <[email protected]>
[ Upstream commit 2b9ac0b84c2cae91bbaceab62df4de6d503421ec ]
Currently, struct snp_guest_msg includes a message header (96 bytes) and a payload (4000 bytes). There is an implicit assumption here that the SNP message header will always be 96 bytes, and with that assumption the payload array size has been set to 4000 bytes - a magic number. If any new member is added to the SNP message header, the SNP guest message will span more than a page.
Instead of using a magic number for the payload, declare struct snp_guest_msg in a way that payload plus the message header do not exceed a page.
[ bp: Massage. ]
--- arch/x86/include/asm/sev.h | 2 +- drivers/virt/coco/sev-guest/sev-guest.c | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-)
arch/x86/include/asm/sev.h +1 -1
@@ -164,7 +164,7 @@ struct snp_guest_msg_hdr {struct snp_guest_msg {struct snp_guest_msg_hdr hdr; -u8 payload[4000 ]; +u8 payload[PAGE_SIZE -sizeof (struct snp_guest_msg_hdr )]; } __packed;struct sev_guest_platform_data {
drivers/virt/coco/sev-guest/sev-guest.c +2 -0
@@ -1090,6 +1090,8 @@ static int __init sev_guest_probe(struct platform_device *pdev)void __iomem *mapping;int ret; +BUILD_BUG_ON (sizeof (struct snp_guest_msg ) >PAGE_SIZE ); +if (!cc_platform_has (CC_ATTR_GUEST_SEV_SNP ))return -ENODEV ;
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 141/558 wifi: mac80211: fix RCU list iterations
In reply to Greg Kroah-Hartman6.11-stable review patch. If anyone has any objections, please let me know.
------------------
From: Johannes Berg <[email protected]>
[ 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.
--- 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(-)
net/mac80211/chan.c +3 -1
@@ -286,7 +286,9 @@ ieee80211_get_max_required_bw(struct ieee80211_link_data *link)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 ;
net/mac80211/mlme.c +1 -1
@@ -1231,7 +1231,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 ;
net/mac80211/scan.c +1 -1
@@ -504,7 +504,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))wiphy_work_queue (sdata->local->hw.wiphy, &sdata->work); }
net/mac80211/util.c +3 -1
@@ -751,7 +751,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 ))
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 142/558 ACPICA: iasl: handle empty connection_node
In reply to Greg Kroah-Hartman6.11-stable review patch. If anyone has any objections, please let me know.
------------------
From: Aleksandrs Vinarskis <[email protected]>
[ Upstream commit a0a2459b79414584af6c46dd8c6f866d8f1aa421 ]
ACPICA commit 6c551e2c9487067d4b085333e7fe97e965a11625
--- drivers/acpi/acpica/exprep.c | 3 +++ 1 file changed, 3 insertions(+)
drivers/acpi/acpica/exprep.c +3 -0
@@ -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);
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 143/558 proc: add config & param to block forcing mem writes
In reply to Greg Kroah-Hartman6.11-stable review patch. If anyone has any objections, please let me know.
------------------
From: Adrian Ratiu <[email protected]>
[ 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.
--- .../admin-guide/kernel-parameters.txt | 10 +++ fs/proc/base.c | 61 ++++++++++++++++++- security/Kconfig | 32 ++++++++++ 3 files changed, 102 insertions(+), 1 deletion(-)
Documentation/admin-guide/kernel-parameters.txt +10 -0
@@ -4788,6 +4788,16 @@ printk.time= Show timing data prefixed to each printk message line Format: <bool> (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.
fs/proc/base.c +60 -1
85 lines not on this page · raw message
security/Kconfig +32 -0
@@ -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
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 144/558 vfs: use RCU in ilookup
In reply to Greg Kroah-Hartman6.11-stable review patch. If anyone has any objections, please let me know.
------------------
From: Mateusz Guzik <[email protected]>
[ Upstream commit 122381a46954ad592ee93d7da2bef5074b396247 ]
A soft lockup in ilookup was reported when stress-testing a 512-way system [1] (see [2] for full context) and it was verified that not taking the lock shifts issues back to mm.
[1] https://lore.kernel.org/linux-mm/[email protected]/
[2] https://lore.kernel.org/linux-mm/[email protected]/
--- fs/inode.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-)
fs/inode.c +1 -3
@@ -1578,9 +1578,7 @@ struct inode *ilookup(struct super_block *sb, unsigned long ino)struct hlist_head *head = inode_hashtable +hash (sb, ino);struct inode *inode; again: -spin_lock (&inode_hash_lock); - inode =find_inode_fast (sb, head, ino, true); -spin_unlock (&inode_hash_lock); + inode =find_inode_fast (sb, head, ino, false);if (inode) {if (IS_ERR (inode))
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 145/558 drivers/perf: arm_spe: Use perf_allow_kernel() for permissions
In reply to Greg Kroah-Hartman6.11-stable review patch. If anyone has any objections, please let me know.
------------------
From: James Clark <[email protected]>
[ Upstream commit 5e9629d0ae977d6f6916d7e519724804e95f0b07 ]
Use perf_allow_kernel() for 'pa_enable' (physical addresses), 'pct_enable' (physical timestamps) and context IDs. This means that perf_event_paranoid is now taken into account and LSM hooks can be used, which is more consistent with other perf_event_open calls. For example PERF_SAMPLE_PHYS_ADDR uses perf_allow_kernel() rather than just perfmon_capable().
This also indirectly fixes the following error message which is misleading because perf_event_paranoid is not taken into account by perfmon_capable():
$ perf record -e arm_spe/pa_enable/
Error:
Access to performance monitoring and observability operations is limited. Consider adjusting /proc/sys/kernel/perf_event_paranoid setting ...
--- drivers/perf/arm_spe_pmu.c | 9 ++++----- include/linux/perf_event.h | 8 +------- kernel/events/core.c | 9 +++++++++ 3 files changed, 14 insertions(+), 12 deletions(-)
drivers/perf/arm_spe_pmu.c +4 -5
@@ -41,7 +41,7 @@/* * Cache if the event is allowed to trace Context information. -* This allows us to perform the check, i.e, perfmon_capable(), +* This allows us to perform the check, i.e, perf_allow_kernel(), * in the context of the event owner, once, during the event_init(). */ #define SPE_PMU_HW_FLAGS_CX 0x00001
@@ -50,7 +50,7 @@ static_assert((PERF_EVENT_FLAG_ARCH & SPE_PMU_HW_FLAGS_CX) == SPE_PMU_HW_FLAGS_Cstatic void set_spe_event_has_cx (struct perf_event *event) { -if (IS_ENABLED (CONFIG_PID_IN_CONTEXTIDR ) &&perfmon_capable ()) +if (IS_ENABLED (CONFIG_PID_IN_CONTEXTIDR ) && !perf_allow_kernel (&event->attr)) event->hw.flags |=SPE_PMU_HW_FLAGS_CX ; }
@@ -745,9 +745,8 @@ static int arm_spe_pmu_event_init(struct perf_event *event)set_spe_event_has_cx (event); reg =arm_spe_event_to_pmscr (event); -if (!perfmon_capable () && - (reg & (PMSCR_EL1_PA |PMSCR_EL1_PCT ))) -return -EACCES ; +if (reg & (PMSCR_EL1_PA |PMSCR_EL1_PCT )) +return perf_allow_kernel (&event->attr);return 0 ; }
include/linux/perf_event.h +1 -7
@@ -1602,13 +1602,7 @@ static inline int perf_is_paranoid(void)return sysctl_perf_event_paranoid >-1 ; } -static inline int perf_allow_kernel (struct perf_event_attr *attr) -{ -if (sysctl_perf_event_paranoid >1 && !perfmon_capable ()) -return -EACCES ; - -return security_perf_event_open (attr,PERF_SECURITY_KERNEL ); -} +int perf_allow_kernel (struct perf_event_attr *attr);static inline int perf_allow_cpu (struct perf_event_attr *attr) {
kernel/events/core.c +9 -0
@@ -13358,6 +13358,15 @@ const struct perf_event_attr *perf_event_attrs(struct perf_event *event)return &event->attr; } +int perf_allow_kernel (struct perf_event_attr *attr) +{ +if (sysctl_perf_event_paranoid >1 && !perfmon_capable ()) +return -EACCES ; + +return security_perf_event_open (attr,PERF_SECURITY_KERNEL ); +} +EXPORT_SYMBOL_GPL (perf_allow_kernel); +/* * Inherit an event from parent task to child task. *
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 146/558 nvme: fix metadata handling in nvme-passthrough
In reply to Greg Kroah-Hartman6.11-stable review patch. If anyone has any objections, please let me know.
------------------
From: Puranjay Mohan <[email protected]>
[ Upstream commit 7c2fd76048e95dd267055b5f5e0a48e6e7c81fd9 ]
On an NVMe namespace that does not support metadata, it is possible to send an IO command with metadata through io-passthru. This allows issues like [1] to trigger in the completion code path. nvme_map_user_request() doesn't check if the namespace supports metadata before sending it forward. It also allows admin commands with metadata to be processed as it ignores metadata when bdev == NULL and may report success.
Reject an IO command with metadata when the NVMe namespace doesn't support it and reject an admin command if it has metadata.
[1] https://lore.kernel.org/all/[email protected]/
--- drivers/nvme/host/ioctl.c | 22 ++++++++++++++-------- 1 file changed, 14 insertions(+), 8 deletions(-)
drivers/nvme/host/ioctl.c +14 -8
@@ -4,6 +4,7 @@* Copyright (c) 2017-2021 Christoph Hellwig. */ #include <linux/bio-integrity.h> +#include <linux/blk-integrity.h> #include <linux/ptrace.h> /* for force_successful_syscall_return */ #include <linux/nvme_ioctl.h> #include <linux/io_uring/cmd.h>
@@ -119,9 +120,14 @@ static int nvme_map_user_request(struct request *req, u64 ubuffer,struct request_queue *q = req->q;struct nvme_ns *ns = q->queuedata;struct block_device *bdev = ns ? ns->disk->part0 :NULL ; +bool supports_metadata = bdev &&blk_get_integrity (bdev->bd_disk); +bool has_metadata = meta_buffer && meta_len;struct bio *bio =NULL ;int ret; +if (has_metadata && !supports_metadata) +return -EINVAL ; +if (ioucmd && (ioucmd->flags &IORING_URING_CMD_FIXED )) {struct iov_iter iter;
@@ -143,15 +149,15 @@ static int nvme_map_user_request(struct request *req, u64 ubuffer, goto out; bio = req->bio; -if (bdev) { +if (bdev)bio_set_dev (bio, bdev); -if (meta_buffer && meta_len) { - ret =bio_integrity_map_user (bio, meta_buffer, meta_len, - meta_seed); -if (ret) - goto out_unmap; - req->cmd_flags |=REQ_INTEGRITY ; - } + +if (has_metadata) { + ret =bio_integrity_map_user (bio, meta_buffer, meta_len, + meta_seed); +if (ret) + goto out_unmap; + req->cmd_flags |=REQ_INTEGRITY ; }return ret;
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 147/558 can: netlink: avoid call to do_set_data_bittiming callback with stale can_priv::ctrlmode
In reply to Greg Kroah-Hartman6.11-stable review patch. If anyone has any objections, please let me know.
------------------
From: Stefan Mätje <[email protected]>
[ Upstream commit 2423cc20087ae9a7b7af575aa62304ef67cad7b6 ]
This patch moves the evaluation of data[IFLA_CAN_CTRLMODE] in function can_changelink in front of the evaluation of data[IFLA_CAN_BITTIMING].
This avoids a call to do_set_data_bittiming providing a stale can_priv::ctrlmode with a CAN_CTRLMODE_FD flag not matching the requested state when switching between a CAN Classic and CAN-FD bitrate.
In the same manner the evaluation of data[IFLA_CAN_CTRLMODE] in function can_validate is also moved in front of the evaluation of data[IFLA_CAN_BITTIMING].
This is a preparation for patches where the nominal and data bittiming may have interdependencies on the driver side depending on the CAN_CTRLMODE_FD flag state.
--- drivers/net/can/dev/netlink.c | 102 +++++++++++++++++----------------- 1 file changed, 51 insertions(+), 51 deletions(-)
drivers/net/can/dev/netlink.c +51 -51
@@ -65,15 +65,6 @@ static int can_validate(struct nlattr *tb[], struct nlattr *data[],if (!data)return 0 ; -if (data[IFLA_CAN_BITTIMING ]) { -struct can_bittiming bt; - -memcpy (&bt,nla_data (data[IFLA_CAN_BITTIMING ]),sizeof (bt)); - err =can_validate_bittiming (&bt, extack); -if (err) -return err; - } -if (data[IFLA_CAN_CTRLMODE ]) {struct can_ctrlmode *cm =nla_data (data[IFLA_CAN_CTRLMODE ]);u32 tdc_flags = cm->flags &CAN_CTRLMODE_TDC_MASK ;
@@ -114,6 +105,15 @@ static int can_validate(struct nlattr *tb[], struct nlattr *data[], } } +if (data[IFLA_CAN_BITTIMING ]) { +struct can_bittiming bt; + +memcpy (&bt,nla_data (data[IFLA_CAN_BITTIMING ]),sizeof (bt)); + err =can_validate_bittiming (&bt, extack); +if (err) +return err; + } +if (is_can_fd) {if (!data[IFLA_CAN_BITTIMING ] || !data[IFLA_CAN_DATA_BITTIMING ])return -EOPNOTSUPP ;
@@ -195,48 +195,6 @@ static int can_changelink(struct net_device *dev, struct nlattr *tb[],/* We need synchronization with dev->stop() */ ASSERT_RTNL (); -if (data[IFLA_CAN_BITTIMING ]) { -struct can_bittiming bt; - -/* Do not allow changing bittiming while running */ -if (dev->flags &IFF_UP ) -return -EBUSY ; - -/* Calculate bittiming parameters based on -* bittiming_const if set, otherwise pass bitrate -* directly via do_set_bitrate(). Bail out if neither -* is given. -*/ -if (!priv->bittiming_const && !priv->do_set_bittiming && - !priv->bitrate_const) -return -EOPNOTSUPP ; - -memcpy (&bt,nla_data (data[IFLA_CAN_BITTIMING ]),sizeof (bt)); - err =can_get_bittiming (dev, &bt, - priv->bittiming_const, - priv->bitrate_const, - priv->bitrate_const_cnt, - extack); -if (err) -return err; - -if (priv->bitrate_max && bt.bitrate > priv->bitrate_max) { -NL_SET_ERR_MSG_FMT (extack, -"arbitration bitrate %u bps surpasses transceiver capabilities of %u bps" , - bt.bitrate, priv->bitrate_max); -return -EINVAL ; - } - -memcpy (&priv->bittiming, &bt,sizeof (bt)); - -if (priv->do_set_bittiming) { -/* Finally, set the bit-timing registers */ - err = priv->do_set_bittiming (dev); -if (err) -return err; - } - } -if (data[IFLA_CAN_CTRLMODE ]) {struct can_ctrlmode *cm;u32 ctrlstatic;
@@ -284,6 +242,48 @@ static int can_changelink(struct net_device *dev, struct nlattr *tb[], priv->ctrlmode &= cm->flags | ~CAN_CTRLMODE_TDC_MASK ; } +if (data[IFLA_CAN_BITTIMING ]) { +struct can_bittiming bt; + +/* Do not allow changing bittiming while running */ +if (dev->flags &IFF_UP ) +return -EBUSY ; + +/* Calculate bittiming parameters based on +* bittiming_const if set, otherwise pass bitrate +* directly via do_set_bitrate(). Bail out if neither +* is given. +*/ +if (!priv->bittiming_const && !priv->do_set_bittiming && + !priv->bitrate_const) +return -EOPNOTSUPP ; + +memcpy (&bt,nla_data (data[IFLA_CAN_BITTIMING ]),sizeof (bt)); + err =can_get_bittiming (dev, &bt, + priv->bittiming_const, + priv->bitrate_const, + priv->bitrate_const_cnt, + extack); +if (err) +return err; + +if (priv->bitrate_max && bt.bitrate > priv->bitrate_max) { +NL_SET_ERR_MSG_FMT (extack, +"arbitration bitrate %u bps surpasses transceiver capabilities of %u bps" , + bt.bitrate, priv->bitrate_max); +return -EINVAL ; + } + +memcpy (&priv->bittiming, &bt,sizeof (bt)); + +if (priv->do_set_bittiming) { +/* Finally, set the bit-timing registers */ + err = priv->do_set_bittiming (dev); +if (err) +return err; + } + } +if (data[IFLA_CAN_RESTART_MS ]) {/* Do not allow changing restart delay while running */ if (dev->flags &IFF_UP )
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 148/558 netdev-genl: Set extack and fix error on napi-get
In reply to Greg Kroah-Hartman6.11-stable review patch. If anyone has any objections, please let me know.
------------------
From: Joe Damato <[email protected]>
[ Upstream commit 4e3a024b437ec0aee82550cc66a0f4e1a7a88a67 ]
In commit 27f91aaf49b3 ("netdev-genl: Add netlink framework functions for napi"), when an invalid NAPI ID is specified the return value -EINVAL is used and no extack is set.
Change the return value to -ENOENT and set the extack.
Before this commit:
$ ./tools/net/ynl/cli.py --spec Documentation/netlink/specs/netdev.yaml \
--do napi-get --json='{"id": 451}'
Netlink error: Invalid argument
nl_len = 36 (20) nl_flags = 0x100 nl_type = 2
error: -22After this commit:
$ ./tools/net/ynl/cli.py --spec Documentation/netlink/specs/netdev.yaml \
--do napi-get --json='{"id": 451}'
Netlink error: No such file or directory
nl_len = 44 (28) nl_flags = 0x300 nl_type = 2
error: -2
extack: {'bad-attr': '.id'}--- net/core/netdev-genl.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-)
net/core/netdev-genl.c +5 -3
@@ -216,10 +216,12 @@ int netdev_nl_napi_get_doit(struct sk_buff *skb, struct genl_info *info)rtnl_lock (); napi =napi_by_id (napi_id); -if (napi) +if (napi) { err =netdev_nl_napi_fill_one (rsp, napi, info); -else - err = -EINVAL ; + }else { +NL_SET_BAD_ATTR (info->extack, info->attrs[NETDEV_A_NAPI_ID ]); + err = -ENOENT ; + }rtnl_unlock ();
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 149/558 wifi: wilc1000: Do not operate uninitialized hardware during suspend/resume
In reply to Greg Kroah-Hartman6.11-stable review patch. If anyone has any objections, please let me know.
------------------
From: Marek Vasut <[email protected]>
[ Upstream commit b0dc7018477e8fbb7e40c908c29cf663d06b17a7 ]
In case the hardware is not initialized, do not operate it during suspend/resume cycle, the hardware is already off so there is no reason to access it.
In fact, wilc_sdio_enable_interrupt() in the resume callback does interfere with the same call when initializing the hardware after resume and makes such initialization after resume fail. Fix this by not operating uninitialized hardware during suspend/resume.
--- drivers/net/wireless/microchip/wilc1000/sdio.c | 7 +++++++ 1 file changed, 7 insertions(+)
drivers/net/wireless/microchip/wilc1000/sdio.c +7 -0
@@ -977,6 +977,9 @@ static int wilc_sdio_suspend(struct device *dev)dev_info (dev,"sdio suspend\n" ); +if (!wilc->initialized) +return 0 ; +if (!IS_ERR (wilc->rtc_clk))clk_disable_unprepare (wilc->rtc_clk);
@@ -999,6 +1002,10 @@ static int wilc_sdio_resume(struct device *dev)struct wilc *wilc =sdio_get_drvdata (func);dev_info (dev,"sdio resume\n" ); + +if (!wilc->initialized) +return 0 ; +wilc_sdio_init (wilc, true);wilc_sdio_enable_interrupt (wilc);
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 150/558 block: fix integer overflow in BLKSECDISCARD
In reply to Greg Kroah-Hartman6.11-stable review patch. If anyone has any objections, please let me know.
------------------
From: Alexey Dobriyan <[email protected]>
[ Upstream commit 697ba0b6ec4ae04afb67d3911799b5e2043b4455 ]
I independently rediscovered
commit 22d24a544b0d49bbcbd61c8c0eaf77d3c9297155 block: fix overflow in blk_ioctl_discard()
but for secure erase.
Same problem:
uint64_t r[2] = {512, 18446744073709551104ULL};
ioctl(fd, BLKSECDISCARD, r);will enter near infinite loop inside blkdev_issue_secure_erase():
a.out: attempt to access beyond end of device
loop0: rw=5, sector=3399043073, nr_sectors = 1024 limit=2048
bio_check_eod: 3286214 callbacks suppressed
--- block/ioctl.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-)
block/ioctl.c +5 -4
@@ -126,7 +126,7 @@ static int blk_ioctl_discard(struct block_device *bdev, blk_mode_t mode,return -EINVAL ;filemap_invalidate_lock (bdev->bd_mapping); - err =truncate_bdev_range (bdev, mode, start, start + len -1 ); + err =truncate_bdev_range (bdev, mode, start, end -1 );if (err) goto fail;
@@ -163,7 +163,7 @@ static int blk_ioctl_discard(struct block_device *bdev, blk_mode_t mode,static int blk_ioctl_secure_erase (struct block_device *bdev,blk_mode_t mode,void __user *argp) { -uint64_t start, len; +uint64_t start, len, end;uint64_t range[2 ];int err;
@@ -178,11 +178,12 @@ static int blk_ioctl_secure_erase(struct block_device *bdev, blk_mode_t mode, len = range[1 ];if ((start &511 ) || (len &511 ))return -EINVAL ; -if (start + len >bdev_nr_bytes (bdev)) +if (check_add_overflow (start, len, &end) || + end >bdev_nr_bytes (bdev))return -EINVAL ;filemap_invalidate_lock (bdev->bd_mapping); - err =truncate_bdev_range (bdev, mode, start, start + len -1 ); + err =truncate_bdev_range (bdev, mode, start, end -1 );if (!err) err =blkdev_issue_secure_erase (bdev, start >>9 , len >>9 ,GFP_KERNEL );
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 151/558 cpufreq: amd-pstate: add check for cpufreq_cpu_gets return value
In reply to Greg Kroah-Hartman6.11-stable review patch. If anyone has any objections, please let me know.
------------------
From: Anastasia Belova <[email protected]>
[ Upstream commit 5493f9714e4cdaf0ee7cec15899a231400cb1a9f ]
cpufreq_cpu_get may return NULL. To avoid NULL-dereference check it and return in case of error.
Found by Linux Verification Center (linuxtesting.org) with SVACE.
--- drivers/cpufreq/amd-pstate.c | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-)
drivers/cpufreq/amd-pstate.c +12 -2
@@ -659,7 +659,12 @@ static void amd_pstate_adjust_perf(unsigned int cpu,unsigned long max_perf, min_perf, des_perf, cap_perf, lowest_nonlinear_perf;struct cpufreq_policy *policy =cpufreq_cpu_get (cpu); -struct amd_cpudata *cpudata = policy->driver_data; +struct amd_cpudata *cpudata; + +if (!policy) +return ; + + cpudata = policy->driver_data;if (policy->min != cpudata->min_limit_freq || policy->max != cpudata->max_limit_freq)amd_pstate_update_min_max_limit (policy);
@@ -873,11 +878,16 @@ static void amd_pstate_init_prefcore(struct amd_cpudata *cpudata)static void amd_pstate_update_limits (unsigned int cpu) {struct cpufreq_policy *policy =cpufreq_cpu_get (cpu); -struct amd_cpudata *cpudata = policy->driver_data; +struct amd_cpudata *cpudata;u32 prev_high =0 , cur_high =0 ;int ret;bool highest_perf_changed = false; +if (!policy) +return ; + + cpudata = policy->driver_data; +mutex_lock (&amd_pstate_driver_lock);if ((!amd_pstate_prefcore) || (!cpudata->hw_prefcore)) goto free_cpufreq_put;
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 152/558 cpufreq: loongson3: Use raw_smp_processor_id() in do_service_request()
In reply to Greg Kroah-Hartman6.11-stable review patch. If anyone has any objections, please let me know.
------------------
From: Huacai Chen <[email protected]>
[ Upstream commit 2b7ec33e534f7a10033a5cf07794acf48b182bbe ]
Use raw_smp_processor_id() instead of plain smp_processor_id() in do_service_request(), otherwise we may get some errors with the driver enabled:
BUG: using smp_processor_id() in preemptible [00000000] code: (udev-worker)/208 caller is loongson3_cpufreq_probe+0x5c/0x250 [loongson3_cpufreq]
--- drivers/cpufreq/loongson3_cpufreq.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/cpufreq/loongson3_cpufreq.c +1 -1
@@ -176,7 +176,7 @@ static DEFINE_PER_CPU(struct loongson3_freq_data *, freq_data);static inline int do_service_request (u32 id,u32 info,u32 cmd,u32 val,u32 extra) {int retries; -unsigned int cpu =smp_processor_id (); +unsigned int cpu =raw_smp_processor_id ();unsigned int package = cpu_data[cpu].package;union smc_message msg, last;
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 153/558 arm64: trans_pgd: mark PTEs entries as valid to avoid dead kexec()
In reply to Greg Kroah-Hartman6.11-stable review patch. If anyone has any objections, please let me know.
------------------
From: Fares Mehanna <[email protected]>
[ Upstream commit 7eced90b202d63cdc1b9b11b1353adb1389830f9 ]
The reasons for PTEs in the kernel direct map to be marked invalid are not limited to kfence / debug pagealloc machinery. In particular, memfd_secret() also steals pages with set_direct_map_invalid_noflush().
When building the transitional page tables for kexec from the current kernel's page tables, those pages need to become regular writable pages, otherwise, if the relocation places kexec segments over such pages, a fault will occur during kexec, leading to host going dark during kexec.
This patch addresses the kexec issue by marking any PTE as valid if it is not none. While this fixes the kexec crash, it does not address the security concern that if processes owning secret memory are not terminated before kexec, the secret content will be mapped in the new kernel without being scrubbed.
--- arch/arm64/mm/trans_pgd.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-)
arch/arm64/mm/trans_pgd.c +4 -2
@@ -42,14 +42,16 @@ static void _copy_pte(pte_t *dst_ptep, pte_t *src_ptep, unsigned long addr)* the temporary mappings we use during restore. */ __set_pte (dst_ptep,pte_mkwrite_novma (pte)); - }else if ((debug_pagealloc_enabled () || -is_kfence_address ((void *)addr)) && !pte_none (pte)) { + }else if (!pte_none (pte)) {/* * debug_pagealloc will removed the PTE_VALID bit if * the page isn't in use by the resume kernel. It may have * been in use by the original kernel, in which case we need * to put it back in our copy to do the restore. * +* Other cases include kfence / vmalloc / memfd_secret which +* may call `set_direct_map_invalid_noflush()`. +* * Before marking this entry valid, check the pfn should * be mapped. */
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 154/558 net: phy: Check for read errors in SIOCGMIIREG
In reply to Greg Kroah-Hartman6.11-stable review patch. If anyone has any objections, please let me know.
------------------
From: Niklas Söderlund <[email protected]>
[ Upstream commit 569bf6d481b0b823c3c9c3b8be77908fd7caf66b ]
When reading registers from the PHY using the SIOCGMIIREG IOCTL any errors returned from either mdiobus_read() or mdiobus_c45_read() are ignored, and parts of the returned error is passed as the register value back to user-space.
For example, if mdiobus_c45_read() is used with a bus that do not implement the read_c45() callback -EOPNOTSUPP is returned. This is however directly stored in mii_data->val_out and returned as the registers content. As val_out is a u16 the error code is truncated and returned as a plausible register value.
Fix this by first checking the return value for errors before returning it as the register content.
Before this patch,
# phytool read eth0/0:1/0
0xffa1After this change,
$ phytool read eth0/0:1/0
error: phy_read (-95)--- drivers/net/phy/phy.c | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-)
drivers/net/phy/phy.c +11 -6
@@ -342,14 +342,19 @@ int phy_mii_ioctl(struct phy_device *phydev, struct ifreq *ifr, int cmd)if (mdio_phy_id_is_c45 (mii_data->phy_id)) { prtad =mdio_phy_id_prtad (mii_data->phy_id); devad =mdio_phy_id_devad (mii_data->phy_id); - mii_data->val_out =mdiobus_c45_read ( - phydev->mdio.bus, prtad, devad, - mii_data->reg_num); + ret =mdiobus_c45_read (phydev->mdio.bus, prtad, devad, + mii_data->reg_num); + }else { - mii_data->val_out =mdiobus_read ( - phydev->mdio.bus, mii_data->phy_id, - mii_data->reg_num); + ret =mdiobus_read (phydev->mdio.bus, mii_data->phy_id, + mii_data->reg_num); } + +if (ret <0 ) +return ret; + + mii_data->val_out = ret; +return 0 ;case SIOCSMIIREG :
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 155/558 wifi: rtw89: avoid reading out of bounds when loading TX power FW elements
In reply to Greg Kroah-Hartman6.11-stable review patch. If anyone has any objections, please let me know.
------------------
From: Zong-Zhe Yang <[email protected]>
[ Upstream commit ed2e4bb17a4884cf29c3347353d8aabb7265b46c ]
Because the loop-expression will do one more time before getting false from cond-expression, the original code copied one more entry size beyond valid region.
Fix it by moving the entry copy to loop-body.
--- drivers/net/wireless/realtek/rtw89/core.h | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-)
drivers/net/wireless/realtek/rtw89/core.h +12 -6
@@ -3909,16 +3909,22 @@ struct rtw89_txpwr_conf {const void *data; }; +static inline bool rtw89_txpwr_entcpy (void *entry,const void *cursor,u8 size, +const struct rtw89_txpwr_conf *conf) +{ +u8 valid_size =min (size, conf->ent_sz); + +memcpy (entry, cursor, valid_size); +return true; +} +#define rtw89_txpwr_conf_valid (conf) (!!(conf)->data)#define rtw89_for_each_in_txpwr_conf (entry, cursor, conf) \ - for (typecheck(const void *, cursor), (cursor) = (conf)->data, \ - memcpy(&(entry), cursor, \ - min_t(u8, sizeof(entry), (conf)->ent_sz)); \ + for (typecheck(const void *, cursor), (cursor) = (conf)->data; \ (cursor) < (conf)->data + (conf)->num_ents * (conf)->ent_sz; \ - (cursor) += (conf)->ent_sz, \ - memcpy(&(entry), cursor, \ - min_t(u8, sizeof(entry), (conf)->ent_sz))) + (cursor) += (conf)->ent_sz) \ + if (rtw89_txpwr_entcpy(&(entry), cursor, sizeof(entry), conf))struct rtw89_txpwr_byrate_data {struct rtw89_txpwr_conf conf;
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 156/558 x86/bugs: Add missing NO_SSB flag
In reply to Greg Kroah-Hartman6.11-stable review patch. If anyone has any objections, please let me know.
------------------
From: Daniel Sneddon <[email protected]>
[ Upstream commit 23e12b54acf621f4f03381dca91cc5f1334f21fd ]
The Moorefield and Lightning Mountain Atom processors are missing the NO_SSB flag in the vulnerabilities whitelist. This will cause unaffected parts to incorrectly be reported as vulnerable. Add the missing flag.
These parts are currently out of service and were verified internally with archived documentation that they need the NO_SSB flag.
--- arch/x86/kernel/cpu/common.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
arch/x86/kernel/cpu/common.c +2 -2
@@ -1165,8 +1165,8 @@ static const __initconst struct x86_cpu_id cpu_vuln_whitelist[] = {VULNWL_INTEL (INTEL_CORE_YONAH ,NO_SSB ), -VULNWL_INTEL (INTEL_ATOM_AIRMONT_MID ,NO_L1TF |MSBDS_ONLY |NO_SWAPGS |NO_ITLB_MULTIHIT ), -VULNWL_INTEL (INTEL_ATOM_AIRMONT_NP ,NO_L1TF |NO_SWAPGS |NO_ITLB_MULTIHIT ), +VULNWL_INTEL (INTEL_ATOM_AIRMONT_MID ,NO_SSB |NO_L1TF |NO_SWAPGS |NO_ITLB_MULTIHIT |MSBDS_ONLY ), +VULNWL_INTEL (INTEL_ATOM_AIRMONT_NP ,NO_SSB |NO_L1TF |NO_SWAPGS |NO_ITLB_MULTIHIT ),VULNWL_INTEL (INTEL_ATOM_GOLDMONT ,NO_MDS |NO_L1TF |NO_SWAPGS |NO_ITLB_MULTIHIT |NO_MMIO ), VULNWL_INTEL(INTEL_ATOM_GOLDMONT_D, NO_MDS | NO_L1TF | NO_SWAPGS | NO_ITLB_MULTIHIT | NO_MMIO),
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 157/558 x86/bugs: Fix handling when SRSO mitigation is disabled
In reply to Greg Kroah-Hartman6.11-stable review patch. If anyone has any objections, please let me know.
------------------
From: David Kaplan <[email protected]>
[ Upstream commit 1dbb6b1495d472806fef1f4c94f5b3e4c89a3c1d ]
When the SRSO mitigation is disabled, either via mitigations=off or spec_rstack_overflow=off, the warning about the lack of IBPB-enhancing microcode is printed anyway.
This is unnecessary since the user has turned off the mitigation.
[ bp: Massage, drop SBPB rationale as it doesn't matter because when
mitigations are disabled x86_pred_cmd is not being used anyway. ]
--- arch/x86/kernel/cpu/bugs.c | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-)
arch/x86/kernel/cpu/bugs.c +5 -9
@@ -2551,10 +2551,9 @@ static void __init srso_select_mitigation(void) {bool has_microcode =boot_cpu_has (X86_FEATURE_IBPB_BRTYPE ); -if (cpu_mitigations_off ()) -return ; - -if (!boot_cpu_has_bug (X86_BUG_SRSO )) { +if (!boot_cpu_has_bug (X86_BUG_SRSO ) || +cpu_mitigations_off () || + srso_cmd ==SRSO_CMD_OFF ) {if (boot_cpu_has (X86_FEATURE_SBPB )) x86_pred_cmd =PRED_CMD_SBPB ;return ;
@@ -2585,11 +2584,6 @@ static void __init srso_select_mitigation(void) }switch (srso_cmd) { -case SRSO_CMD_OFF : -if (boot_cpu_has (X86_FEATURE_SBPB )) - x86_pred_cmd =PRED_CMD_SBPB ; -return ; -case SRSO_CMD_MICROCODE :if (has_microcode) { srso_mitigation =SRSO_MITIGATION_MICROCODE ;
@@ -2643,6 +2637,8 @@ static void __init srso_select_mitigation(void)pr_err ("WARNING: kernel not compiled with MITIGATION_SRSO.\n" ); }break ; +default : +break ; } out:
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 158/558 net: napi: Prevent overflow of napi_defer_hard_irqs
In reply to Greg Kroah-Hartman6.11-stable review patch. If anyone has any objections, please let me know.
------------------
From: Joe Damato <[email protected]>
[ Upstream commit 08062af0a52107a243f7608fd972edb54ca5b7f8 ]
In commit 6f8b12d661d0 ("net: napi: add hard irqs deferral feature") napi_defer_irqs was added to net_device and napi_defer_irqs_count was added to napi_struct, both as type int.
This value never goes below zero, so there is not reason for it to be a signed int. Change the type for both from int to u32, and add an overflow check to sysfs to limit the value to S32_MAX.
The limit of S32_MAX was chosen because the practical limit before this patch was S32_MAX (anything larger was an overflow) and thus there are no behavioral changes introduced. If the extra bit is needed in the future, the limit can be raised.
Before this patch:
$ sudo bash -c 'echo 2147483649 > /sys/class/net/eth4/napi_defer_hard_irqs' $ cat /sys/class/net/eth4/napi_defer_hard_irqs -2147483647
After this patch:
$ sudo bash -c 'echo 2147483649 > /sys/class/net/eth4/napi_defer_hard_irqs' bash: line 0: echo: write error: Numerical result out of range
Similarly, /sys/class/net/XXXXX/tx_queue_len is defined as unsigned:
include/linux/netdevice.h: unsigned int tx_queue_len;
And has an overflow check:
dev_change_tx_queue_len(..., unsigned long new_len):
if (new_len != (unsigned int)new_len)
return -ERANGE;
--- Documentation/networking/net_cachelines/net_device.rst | 2 +- include/linux/netdevice.h | 4 ++-- net/core/net-sysfs.c | 6 +++++- 3 files changed, 8 insertions(+), 4 deletions(-)
Documentation/networking/net_cachelines/net_device.rst +1 -1
@@ -98,7 +98,7 @@ unsigned_int num_rx_queues unsigned_int real_num_rx_queues - read_mostly get_rps_cpu struct_bpf_prog* xdp_prog - read_mostly netif_elide_gro() unsigned_long gro_flush_timeout - read_mostly napi_complete_done -int napi_defer_hard_irqs - read_mostly napi_complete_done +u32 napi_defer_hard_irqs - read_mostly napi_complete_done unsigned_int gro_max_size - read_mostly skb_gro_receive unsigned_int gro_ipv4_max_size - read_mostly skb_gro_receive rx_handler_func_t* rx_handler read_mostly - __netif_receive_skb_core
include/linux/netdevice.h +2 -2
@@ -356,7 +356,7 @@ struct napi_struct {unsigned long state;int weight; -int defer_hard_irqs_count; +u32 defer_hard_irqs_count;unsigned long gro_bitmask;int (*poll)(struct napi_struct *,int );#ifdef CONFIG_NETPOLL
@@ -2091,7 +2091,7 @@ struct net_device {unsigned int real_num_rx_queues;struct netdev_rx_queue *_rx;unsigned long gro_flush_timeout; -int napi_defer_hard_irqs; +u32 napi_defer_hard_irqs;unsigned int gro_max_size;unsigned int gro_ipv4_max_size;rx_handler_func_t __rcu *rx_handler;
net/core/net-sysfs.c +5 -1
@@ -32,6 +32,7 @@#ifdef CONFIG_SYSFS static const char fmt_hex[] ="%#x\n" ;static const char fmt_dec[] ="%d\n" ; +static const char fmt_uint[] ="%u\n" ;static const char fmt_ulong[] ="%lu\n" ;static const char fmt_u64[] ="%llu\n" ;
@@ -425,6 +426,9 @@ NETDEVICE_SHOW_RW(gro_flush_timeout, fmt_ulong);static int change_napi_defer_hard_irqs (struct net_device *dev,unsigned long val) { +if (val >S32_MAX ) +return -ERANGE ; +WRITE_ONCE (dev->napi_defer_hard_irqs, val);return 0 ; }
@@ -438,7 +442,7 @@ static ssize_t napi_defer_hard_irqs_store(struct device *dev,return netdev_store (dev, attr, buf, len, change_napi_defer_hard_irqs); } -NETDEVICE_SHOW_RW (napi_defer_hard_irqs, fmt_dec); +NETDEVICE_SHOW_RW (napi_defer_hard_irqs, fmt_uint);static ssize_t ifalias_store (struct device *dev,struct device_attribute *attr,const char *buf,size_t len)
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 159/558 crypto: hisilicon - fix missed error branch
In reply to Greg Kroah-Hartman6.11-stable review patch. If anyone has any objections, please let me know.
------------------
From: Yang Shen <[email protected]>
[ Upstream commit f386dc64e1a5d3dcb84579119ec350ab026fea88 ]
If an error occurs in the process after the SGL is mapped successfully, it need to unmap the SGL.
Otherwise, memory problems may occur.
--- drivers/crypto/hisilicon/sgl.c | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-)
drivers/crypto/hisilicon/sgl.c +10 -4
@@ -225,7 +225,7 @@ hisi_acc_sg_buf_map_to_hw_sgl(struct device *dev,dma_addr_t curr_sgl_dma =0 ;struct acc_hw_sge *curr_hw_sge;struct scatterlist *sg; -int sg_n; +int sg_n, ret;if (!dev || !sgl || !pool || !hw_sgl_dma || index >= pool->count)return ERR_PTR (-EINVAL );
@@ -240,14 +240,15 @@ hisi_acc_sg_buf_map_to_hw_sgl(struct device *dev,if (sg_n_mapped > pool->sge_nr) {dev_err (dev,"the number of entries in input scatterlist is bigger than SGL pool setting.\n" ); -return ERR_PTR (-EINVAL ); + ret = -EINVAL ; + goto err_unmap; } curr_hw_sgl =acc_get_sgl (pool, index, &curr_sgl_dma);if (IS_ERR (curr_hw_sgl)) {dev_err (dev,"Get SGL error!\n" ); -dma_unmap_sg (dev, sgl, sg_n,DMA_BIDIRECTIONAL ); -return ERR_PTR (-ENOMEM ); + ret = -ENOMEM ; + goto err_unmap; } curr_hw_sgl->entry_length_in_sgl =cpu_to_le16 (pool->sge_nr); curr_hw_sge = curr_hw_sgl->sge_entries;
@@ -262,6 +263,11 @@ hisi_acc_sg_buf_map_to_hw_sgl(struct device *dev, *hw_sgl_dma = curr_sgl_dma;return curr_hw_sgl; + +err_unmap: +dma_unmap_sg (dev, sgl, sg_n,DMA_BIDIRECTIONAL ); + +return ERR_PTR (ret); }EXPORT_SYMBOL_GPL (hisi_acc_sg_buf_map_to_hw_sgl);
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 160/558 wifi: mt76: mt7915: add dummy HW offload of IEEE 802.11 fragmentation
In reply to Greg Kroah-Hartman6.11-stable review patch. If anyone has any objections, please let me know.
------------------
From: Benjamin Lin <[email protected]>
[ Upstream commit f2cc859149240d910fdc6405717673e0b84bfda8 ]
Currently, CONNAC2 series do not support encryption for fragmented Tx frames. Therefore, add dummy function mt7915_set_frag_threshold() to prevent SW IEEE 802.11 fragmentation.
--- drivers/net/wireless/mediatek/mt76/mt7915/init.c | 1 + drivers/net/wireless/mediatek/mt76/mt7915/main.c | 7 +++++++ 2 files changed, 8 insertions(+)
drivers/net/wireless/mediatek/mt76/mt7915/init.c +1 -0
@@ -400,6 +400,7 @@ mt7915_init_wiphy(struct mt7915_phy *phy)ieee80211_hw_set (hw,SUPPORTS_RX_DECAP_OFFLOAD );ieee80211_hw_set (hw,SUPPORTS_MULTI_BSSID );ieee80211_hw_set (hw,WANT_MONITOR_VIF ); +ieee80211_hw_set (hw,SUPPORTS_TX_FRAG ); hw->max_tx_fragments =4 ;
drivers/net/wireless/mediatek/mt76/mt7915/main.c +7 -0
@@ -1577,6 +1577,12 @@ mt7915_twt_teardown_request(struct ieee80211_hw *hw,mutex_unlock (&dev->mt76.mutex); } +static int +mt7915_set_frag_threshold (struct ieee80211_hw *hw,u32 val) +{ +return 0 ; +} +static int mt7915_set_radar_background (struct ieee80211_hw *hw,struct cfg80211_chan_def *chandef)
@@ -1707,6 +1713,7 @@ const struct ieee80211_ops mt7915_ops = { .sta_set_decap_offload = mt7915_sta_set_decap_offload, .add_twt_setup = mt7915_mac_add_twt_setup, .twt_teardown_request = mt7915_twt_teardown_request, + .set_frag_threshold = mt7915_set_frag_threshold, CFG80211_TESTMODE_CMD(mt76_testmode_cmd) CFG80211_TESTMODE_DUMP(mt76_testmode_dump)#ifdef CONFIG_MAC80211_DEBUGFS
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 161/558 wifi: mt76: mt7915: hold dev->mt76.mutex while disabling tx worker
In reply to Greg Kroah-Hartman6.11-stable review patch. If anyone has any objections, please let me know.
------------------
From: Felix Fietkau <[email protected]>
[ Upstream commit 8f7152f10cb434f954aeff85ca1be9cd4d01912b ]
Prevent racing against other functions disabling the same worker
--- drivers/net/wireless/mediatek/mt76/mt7915/mac.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
drivers/net/wireless/mediatek/mt76/mt7915/mac.c +3 -1
@@ -1537,12 +1537,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);if (mtk_wed_device_active (&dev->mt76.mmio.wed))mtk_wed_device_stop (&dev->mt76.mmio.wed);
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 162/558 wifi: mwifiex: Fix memcpy() field-spanning write warning in mwifiex_cmd_802_11_scan_ext()
In reply to Greg Kroah-Hartman6.11-stable review patch. If anyone has any objections, please let me know.
------------------
From: Gustavo A. R. Silva <[email protected]>
[ 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]
--- drivers/net/wireless/marvell/mwifiex/fw.h | 2 +- drivers/net/wireless/marvell/mwifiex/scan.c | 3 +-- 2 files changed, 2 insertions(+), 3 deletions(-)
drivers/net/wireless/marvell/mwifiex/fw.h +1 -1
@@ -1587,7 +1587,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 {
drivers/net/wireless/marvell/mwifiex/scan.c +1 -2
@@ -2530,8 +2530,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);
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 163/558 netfs: Cancel dirty folios that have no storage destination
In reply to Greg Kroah-Hartman6.11-stable review patch. If anyone has any objections, please let me know.
------------------
From: David Howells <[email protected]>
[ Upstream commit 8f246b7c0a1be0882374f2ff831a61f0dbe77678 ]
Kafs wants to be able to cache the contents of directories (and symlinks), but whilst these are downloaded from the server with the FS.FetchData RPC op and similar, the same as for regular files, they can't be updated by FS.StoreData, but rather have special operations (FS.MakeDir, etc.).
Now, rather than redownloading a directory's content after each change made to that directory, kafs modifies the local blob. This blob can be saved out to the cache, and since it's using netfslib, kafs just marks the folios dirty and lets ->writepages() on the directory take care of it, as for an regular file.
This is fine as long as there's a cache as although the upload stream is disabled, there's a cache stream to drive the procedure. But if the cache goes away in the meantime, suddenly there's no way do any writes and the code gets confused, complains "R=%x: No submit" to dmesg and leaves the dirty folio hanging.
Fix this by just cancelling the store of the folio if neither stream is active. (If there's no cache at the time of dirtying, we should just not mark the folio dirty).
--- fs/netfs/write_issue.c | 6 +++++- include/trace/events/netfs.h | 1 + 2 files changed, 6 insertions(+), 1 deletion(-)
fs/netfs/write_issue.c +5 -1
@@ -410,13 +410,17 @@ static int netfs_write_folio(struct netfs_io_request *wreq,folio_unlock (folio);if (fgroup ==NETFS_FOLIO_COPY_TO_CACHE ) { -if (!fscache_resources_valid (&wreq->cache_resources)) { +if (!cache->avail) {trace_netfs_folio (folio, netfs_folio_trace_cancel_copy);netfs_issue_write (wreq, upload);netfs_folio_written_back (folio);return 0 ; }trace_netfs_folio (folio, netfs_folio_trace_store_copy); + }else if (!upload->avail && !cache->avail) { +trace_netfs_folio (folio, netfs_folio_trace_cancel_store); +netfs_folio_written_back (folio); +return 0 ; }else if (!upload->construct) {trace_netfs_folio (folio, netfs_folio_trace_store); }else {
include/trace/events/netfs.h +1 -0
@@ -141,6 +141,7 @@EM (netfs_streaming_cont_filled_page,"mod-streamw-f+" ) \ /* The rest are for writeback */ \ EM(netfs_folio_trace_cancel_copy, "cancel-copy") \ + EM(netfs_folio_trace_cancel_store, "cancel-store") \ EM(netfs_folio_trace_clear, "clear") \ EM(netfs_folio_trace_clear_cc, "clear-cc") \EM (netfs_folio_trace_clear_g,"clear-g" ) \
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 164/558 nfp: Use IRQF_NO_AUTOEN flag in request_irq()
In reply to Greg Kroah-Hartman6.11-stable review patch. If anyone has any objections, please let me know.
------------------
From: Jinjie Ruan <[email protected]>
[ 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.
--- drivers/net/ethernet/netronome/nfp/nfp_net_common.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-)
drivers/net/ethernet/netronome/nfp/nfp_net_common.c +2 -3
@@ -821,14 +821,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);
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 165/558 ALSA: usb-audio: Add input value sanity checks for standard types
In reply to Greg Kroah-Hartman6.11-stable review patch. If anyone has any objections, please let me know.
------------------
From: Takashi Iwai <[email protected]>
[ 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.
--- sound/usb/mixer.c | 35 +++++++++++++++++++++++++++-------- sound/usb/mixer.h | 1 + 2 files changed, 28 insertions(+), 8 deletions(-)
sound/usb/mixer.c +27 -8
@@ -1377,6 +1377,19 @@ static int get_min_max_with_quirks(struct usb_mixer_elem_info *cval,#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);
@@ -2337,6 +2352,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);
@@ -2699,6 +2716,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);
sound/usb/mixer.h +1 -0
@@ -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 ];
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 166/558 x86/ioapic: Handle allocation failures gracefully
In reply to Greg Kroah-Hartman6.11-stable review patch. If anyone has any objections, please let me know.
------------------
From: Thomas Gleixner <[email protected]>
[ 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.
--- arch/x86/kernel/apic/io_apic.c | 46 ++++++++++++++++------------------ 1 file changed, 22 insertions(+), 24 deletions(-)
arch/x86/kernel/apic/io_apic.c +22 -24
@@ -352,27 +352,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)
@@ -387,13 +386,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. */
@@ -1002,8 +994,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 ;
@@ -3017,10 +3008,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;
@@ -3029,7 +3018,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);
@@ -3044,6 +3036,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,
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 167/558 x86/apic: Remove logical destination mode for 64-bit
In reply to Greg Kroah-Hartman6.11-stable review patch. If anyone has any objections, please let me know.
------------------
From: Thomas Gleixner <[email protected]>
[ Upstream commit 838ba7733e4e3a94a928e8d0a058de1811a58621 ]
Logical destination mode of the local APIC is used for systems with up to 8 CPUs. It has an advantage over physical destination mode as it allows to target multiple CPUs at once with IPIs.
That advantage was definitely worth it when systems with up to 8 CPUs were state of the art for servers and workstations, but that's history.
Aside of that there are systems which fail to work with logical destination mode as the ACPI/DMI quirks show and there are AMD Zen1 systems out there which fail when interrupt remapping is enabled as reported by Rob and Christian. The latter problem can be cured by firmware updates, but not all OEMs distribute the required changes.
Physical destination mode is guaranteed to work because it is the only way to get a CPU up and running via the INIT/INIT/STARTUP sequence.
As the number of CPUs keeps increasing, logical destination mode becomes a less used code path so there is no real good reason to keep it around.
Therefore remove logical destination mode support for 64-bit and default to physical destination mode.
--- arch/x86/include/asm/apic.h | 8 -- arch/x86/kernel/apic/apic_flat_64.c | 119 ++-------------------------- 2 files changed, 7 insertions(+), 120 deletions(-)
arch/x86/include/asm/apic.h +0 -8
@@ -345,20 +345,12 @@ extern struct apic *apic;* APIC drivers are probed based on how they are listed in the .apicdrivers * section. So the order is important and enforced by the ordering * of different apic driver files in the Makefile. -* -* For the files having two apic drivers, we use apic_drivers() -* to enforce the order with in them. */ #define apic_driver (sym) \ static const struct apic *__apicdrivers_##sym __used \ __aligned(sizeof(struct apic *)) \ __section(".apicdrivers") = { &sym } -#define apic_drivers (sym1, sym2) \ - static struct apic *__apicdrivers_##sym1##sym2[2] __used \ - __aligned(sizeof(struct apic *)) \ - __section(".apicdrivers") = { &sym1, &sym2 } -extern struct apic *__apicdrivers[], *__apicdrivers_end[];/*
arch/x86/kernel/apic/apic_flat_64.c +7 -112
151 lines not on this page · raw message
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 168/558 ALSA: usb-audio: Support multiple control interfaces
In reply to Greg Kroah-Hartman6.11-stable review patch. If anyone has any objections, please let me know.
------------------
From: Karol Kosik <[email protected]>
[ Upstream commit 6aa8700150f7dc62f60b4cf5b1624e2e3d9ed78e ]
Registering Numark Party Mix II fails with error 'bogus bTerminalLink 1'. The problem stems from the driver not being able to find input/output terminals required to configure audio streaming. The information about those terminals is stored in AudioControl Interface. Numark device contains 2 AudioControl Interfaces and the driver checks only one of them.
According to the USB standard, a device can have multiple audio functions, each represented by Audio Interface Collection. Every audio function is considered to be closed box and will contain unique AudioControl Interface and zero or more AudioStreaming and MIDIStreaming Interfaces.
The Numark device adheres to the standard and defines two audio functions:
- MIDIStreaming function
- AudioStreaming function
It starts with MIDI function, followed by the audio function. The driver saves the first AudioControl Interface in snd_usb_audio structure associated with the entire device. It then attempts to use this interface to query for terminals and clocks. However, this fails because the correct information is stored in the second AudioControl Interface, defined in the second Audio Interface Collection.
This patch introduces a structure holding association between each MIDI/Audio Interface and its corresponding AudioControl Interface, instead of relying on AudioControl Interface defined for the entire device. This structure is populated during usb probing phase and leveraged later when querying for terminals and when sending USB requests.
Alternative solutions considered include:
- defining a quirk for Numark where the order of interface is manually changed, or terminals are hardcoded in the driver. This solution would have fixed only this model, though it seems that device is USB compliant, and it also seems that other devices from this company may be affected. What's more, it looks like products from other manufacturers have similar problems, i.e. Rane One DJ console
- keeping a list of all AudioControl Interfaces and querying all of them to find required information. That would have solved my problem and have low probability of breaking other devices, as we would always start with the same logic of querying first AudioControl Interface. This solution would not have followed the standard though.
This patch preserves the snd_usb_audio.ctrl_intf variable, which holds the first AudioControl Interface, and uses it as a fallback when some interfaces are not parsed correctly and lack an associated AudioControl Interface, i.e., when configured via quirks.
--- sound/usb/card.c | 2 ++ sound/usb/clock.c | 62 ++++++++++++++++++++++++-------------- sound/usb/format.c | 6 ++-- sound/usb/helper.c | 34 +++++++++++++++++++++ sound/usb/helper.h | 10 ++++-- sound/usb/mixer.c | 2 +- sound/usb/mixer_quirks.c | 17 ++++++----- sound/usb/mixer_scarlett.c | 4 +-- sound/usb/power.c | 3 +- sound/usb/power.h | 1 + sound/usb/stream.c | 21 ++++++++----- sound/usb/usbaudio.h | 12 ++++++++ 12 files changed, 127 insertions(+), 47 deletions(-)
sound/usb/card.c +2 -0
@@ -206,6 +206,8 @@ static int snd_usb_create_stream(struct snd_usb_audio *chip, int ctrlif, int intreturn -EINVAL ; } +snd_usb_add_ctrl_interface_link (chip, interface, ctrlif); +if (!snd_usb_parse_audio_interface (chip, interface)) {usb_set_interface (dev, interface,0 );/* reset the current interface */ return usb_driver_claim_interface(&usb_audio_driver, iface,
sound/usb/clock.c +39 -23
187 lines not on this page · raw message
sound/usb/format.c +4 -2
@@ -545,7 +545,9 @@ static int parse_audio_format_rates_v2v3(struct snd_usb_audio *chip,unsigned char tmp[2 ], *data;int nr_triplets, data_size, ret =0 , ret_l6;int clock =snd_usb_clock_find_source (chip, fp, false); +struct usb_host_interface *ctrl_intf; + ctrl_intf =snd_usb_find_ctrl_interface (chip, fp->iface);if (clock <0 ) { dev_err(&dev->dev, "%s(): unable to find clock source (clock %d)\n",
@@ -557,7 +559,7 @@ static int parse_audio_format_rates_v2v3(struct snd_usb_audio *chip, ret =snd_usb_ctl_msg (dev,usb_rcvctrlpipe (dev,0 ),UAC2_CS_RANGE ,USB_TYPE_CLASS |USB_RECIP_INTERFACE |USB_DIR_IN ,UAC2_CS_CONTROL_SAM_FREQ <<8 , -snd_usb_ctrl_intf (chip) | (clock <<8 ), +snd_usb_ctrl_intf (ctrl_intf) | (clock <<8 ), tmp,sizeof (tmp));if (ret <0 ) {
@@ -592,7 +594,7 @@ static int parse_audio_format_rates_v2v3(struct snd_usb_audio *chip, ret =snd_usb_ctl_msg (dev,usb_rcvctrlpipe (dev,0 ),UAC2_CS_RANGE ,USB_TYPE_CLASS |USB_RECIP_INTERFACE |USB_DIR_IN ,UAC2_CS_CONTROL_SAM_FREQ <<8 , -snd_usb_ctrl_intf (chip) | (clock <<8 ), +snd_usb_ctrl_intf (ctrl_intf) | (clock <<8 ), data, data_size);if (ret <0 ) {
sound/usb/helper.c +34 -0
@@ -130,3 +130,37 @@ snd_usb_get_host_interface(struct snd_usb_audio *chip, int ifnum, int altsettingreturn NULL ;return usb_altnum_to_altsetting (iface, altsetting); } + +int snd_usb_add_ctrl_interface_link (struct snd_usb_audio *chip,int ifnum, +int ctrlif) +{ +struct usb_device *dev = chip->dev; +struct usb_host_interface *host_iface; + +if (chip->num_intf_to_ctrl >=MAX_CARD_INTERFACES ) { +dev_info (&dev->dev,"Too many interfaces assigned to the single USB-audio card\n" ); +return -EINVAL ; + } + +/* find audiocontrol interface */ + host_iface = &usb_ifnum_to_if (dev, ctrlif)->altsetting[0 ]; + + chip->intf_to_ctrl[chip->num_intf_to_ctrl].interface = ifnum; + chip->intf_to_ctrl[chip->num_intf_to_ctrl].ctrl_intf = host_iface; + chip->num_intf_to_ctrl++; + +return 0 ; +} + +struct usb_host_interface *snd_usb_find_ctrl_interface (struct snd_usb_audio *chip, +int ifnum) +{ +int i; + +for (i =0 ; i < chip->num_intf_to_ctrl; ++i) +if (chip->intf_to_ctrl[i].interface == ifnum) +return chip->intf_to_ctrl[i].ctrl_intf; + +/* Fallback to first audiocontrol interface */ +return chip->ctrl_intf; +}
sound/usb/helper.h +8 -2
@@ -17,6 +17,12 @@ unsigned char snd_usb_parse_datainterval(struct snd_usb_audio *chip,struct usb_host_interface *snd_usb_get_host_interface (struct snd_usb_audio *chip,int ifnum,int altsetting); +int snd_usb_add_ctrl_interface_link (struct snd_usb_audio *chip,int ifnum, +int ctrlif); + +struct usb_host_interface *snd_usb_find_ctrl_interface (struct snd_usb_audio *chip, +int ifnum); +/* * retrieve usb_interface descriptor from the host interface * (conditional for compatibility with the older API)
@@ -28,9 +34,9 @@ snd_usb_get_host_interface(struct snd_usb_audio *chip, int ifnum, int altsetting#define snd_usb_get_speed (dev) ((dev)->speed) -static inline int snd_usb_ctrl_intf (struct snd_usb_audio *chip) +static inline int snd_usb_ctrl_intf (struct usb_host_interface *ctrl_intf) { -return get_iface_desc (chip->ctrl_intf)->bInterfaceNumber; +return get_iface_desc (ctrl_intf)->bInterfaceNumber; }/* in validate.c */
sound/usb/mixer.c +1 -1
@@ -728,7 +728,7 @@ static int get_cluster_channels_v3(struct mixer_build *state, unsigned int clustUAC3_CS_REQ_HIGH_CAPABILITY_DESCRIPTOR ,USB_RECIP_INTERFACE |USB_TYPE_CLASS |USB_DIR_IN , cluster_id, -snd_usb_ctrl_intf (state->chip), +snd_usb_ctrl_intf (state->mixer->hostif), &c_header, sizeof(c_header));if (err <0 ) goto error;
sound/usb/mixer_quirks.c +9 -8
@@ -1043,7 +1043,7 @@ static int snd_ftu_eff_switch_init(struct usb_mixer_interface *mixer, err =snd_usb_ctl_msg (dev,usb_rcvctrlpipe (dev,0 ),UAC_GET_CUR ,USB_RECIP_INTERFACE |USB_TYPE_CLASS |USB_DIR_IN , pval &0xff00 , -snd_usb_ctrl_intf (mixer->chip) | ((pval &0xff ) <<8 ), +snd_usb_ctrl_intf (mixer->hostif) | ((pval &0xff ) <<8 ), value,2 );if (err <0 )return err;
@@ -1077,7 +1077,7 @@ static int snd_ftu_eff_switch_update(struct usb_mixer_elem_list *list)UAC_SET_CUR ,USB_RECIP_INTERFACE |USB_TYPE_CLASS |USB_DIR_OUT , pval &0xff00 , -snd_usb_ctrl_intf (chip) | ((pval &0xff ) <<8 ), +snd_usb_ctrl_intf (list->mixer->hostif) | ((pval &0xff ) <<8 ), value, 2);snd_usb_unlock_shutdown (chip);return err;
@@ -2115,24 +2115,25 @@ static int dell_dock_mixer_create(struct usb_mixer_interface *mixer)return 0 ; } -static void dell_dock_init_vol (struct snd_usb_audio *chip,int ch,int id) +static void dell_dock_init_vol (struct usb_mixer_interface *mixer,int ch,int id) { +struct snd_usb_audio *chip = mixer->chip;u16 buf =0 ;snd_usb_ctl_msg (chip->dev,usb_sndctrlpipe (chip->dev,0 ),UAC_SET_CUR ,USB_RECIP_INTERFACE |USB_TYPE_CLASS |USB_DIR_OUT , (UAC_FU_VOLUME <<8 ) | ch, -snd_usb_ctrl_intf (chip) | (id <<8 ), +snd_usb_ctrl_intf (mixer->hostif) | (id <<8 ), &buf,2 ); }static int dell_dock_mixer_init (struct usb_mixer_interface *mixer) {/* fix to 0dB playback volumes */ -dell_dock_init_vol (mixer->chip,1 ,16 ); -dell_dock_init_vol (mixer->chip,2 ,16 ); -dell_dock_init_vol (mixer->chip,1 ,19 ); -dell_dock_init_vol (mixer->chip,2 ,19 ); +dell_dock_init_vol (mixer,1 ,16 ); +dell_dock_init_vol (mixer,2 ,16 ); +dell_dock_init_vol (mixer,1 ,19 ); +dell_dock_init_vol (mixer,2 ,19 );return 0 ; }
sound/usb/mixer_scarlett.c +2 -2
@@ -460,7 +460,7 @@ static int scarlett_ctl_meter_get(struct snd_kcontrol *kctl,struct snd_usb_audio *chip = elem->head.mixer->chip;unsigned char buf[2 *MAX_CHANNELS ] = {0 , };int wValue = (elem->control <<8 ) | elem->idx_off; -int idx =snd_usb_ctrl_intf (chip) | (elem->head.id <<8 ); +int idx =snd_usb_ctrl_intf (elem->head.mixer->hostif) | (elem->head.id <<8 );int err; err = snd_usb_ctl_msg(chip->dev,
@@ -1002,7 +1002,7 @@ int snd_scarlett_controls_create(struct usb_mixer_interface *mixer) err =snd_usb_ctl_msg (mixer->chip->dev,usb_sndctrlpipe (mixer->chip->dev,0 ),UAC2_CS_CUR ,USB_RECIP_INTERFACE |USB_TYPE_CLASS | -USB_DIR_OUT ,0x0100 ,snd_usb_ctrl_intf (mixer->chip) | +USB_DIR_OUT ,0x0100 ,snd_usb_ctrl_intf (mixer->hostif) | (0x29 <<8 ), sample_rate_buffer,4 );if (err <0 )return err;
sound/usb/power.c +2 -1
@@ -40,6 +40,7 @@ snd_usb_find_power_domain(struct usb_host_interface *ctrl_iface,le16_to_cpu (pd_desc->waRecoveryTime1); pd->pd_d2d0_rec =le16_to_cpu (pd_desc->waRecoveryTime2); + pd->ctrl_iface = ctrl_iface;return pd; } }
@@ -57,7 +58,7 @@ int snd_usb_power_domain_set(struct snd_usb_audio *chip,unsigned char current_state;int err, idx; - idx =snd_usb_ctrl_intf (chip) | (pd->pd_id <<8 ); + idx =snd_usb_ctrl_intf (pd->ctrl_iface) | (pd->pd_id <<8 ); err = snd_usb_ctl_msg(chip->dev, usb_rcvctrlpipe(chip->dev, 0), UAC2_CS_CUR,
sound/usb/power.h +1 -0
@@ -6,6 +6,7 @@ struct snd_usb_power_domain {int pd_id;/* UAC3 Power Domain ID */ int pd_d1d0_rec;/* D1 to D0 recovery time */ int pd_d2d0_rec;/* D2 to D0 recovery time */ +struct usb_host_interface *ctrl_iface;/* Control interface */ };enum {
sound/usb/stream.c +13 -8
@@ -713,10 +713,13 @@ snd_usb_get_audioformat_uac12(struct snd_usb_audio *chip,struct usb_device *dev = chip->dev;struct uac_format_type_i_continuous_descriptor *fmt;unsigned int num_channels =0 , chconfig =0 ; +struct usb_host_interface *ctrl_intf;struct audioformat *fp;int clock =0 ;u64 format; + ctrl_intf =snd_usb_find_ctrl_interface (chip, iface_no); +/* get audio formats */ if (protocol ==UAC_VERSION_1 ) { struct uac1_as_header_descriptor *as =
@@ -740,7 +743,7 @@ snd_usb_get_audioformat_uac12(struct snd_usb_audio *chip, format =le16_to_cpu (as->wFormatTag);/* remember the format value */ - iterm =snd_usb_find_input_terminal_descriptor (chip->ctrl_intf, + iterm =snd_usb_find_input_terminal_descriptor (ctrl_intf, as->bTerminalLink, protocol);if (iterm) {
@@ -776,7 +779,7 @@ snd_usb_get_audioformat_uac12(struct snd_usb_audio *chip,* lookup the terminal associated to this interface * to extract the clock */ - input_term =snd_usb_find_input_terminal_descriptor (chip->ctrl_intf, + input_term =snd_usb_find_input_terminal_descriptor (ctrl_intf, as->bTerminalLink, protocol);if (input_term) {
@@ -786,7 +789,7 @@ snd_usb_get_audioformat_uac12(struct snd_usb_audio *chip, goto found_clock; } - output_term =snd_usb_find_output_terminal_descriptor (chip->ctrl_intf, + output_term =snd_usb_find_output_terminal_descriptor (ctrl_intf, as->bTerminalLink, protocol);if (output_term) {
@@ -870,6 +873,7 @@ snd_usb_get_audioformat_uac3(struct snd_usb_audio *chip,struct uac3_cluster_header_descriptor *cluster;struct uac3_as_header_descriptor *as =NULL ;struct uac3_hc_descriptor_header hc_header; +struct usb_host_interface *ctrl_intf;struct snd_pcm_chmap_elem *chmap;struct snd_usb_power_domain *pd;unsigned char badd_profile;
@@ -881,6 +885,7 @@ snd_usb_get_audioformat_uac3(struct snd_usb_audio *chip,int err; badd_profile = chip->badd_profile; + ctrl_intf =snd_usb_find_ctrl_interface (chip, iface_no);if (badd_profile >=UAC3_FUNCTION_SUBCLASS_GENERIC_IO ) { unsigned int maxpacksize =
@@ -966,7 +971,7 @@ snd_usb_get_audioformat_uac3(struct snd_usb_audio *chip,UAC3_CS_REQ_HIGH_CAPABILITY_DESCRIPTOR ,USB_RECIP_INTERFACE |USB_TYPE_CLASS |USB_DIR_IN , cluster_id, -snd_usb_ctrl_intf (chip), +snd_usb_ctrl_intf (ctrl_intf), &hc_header, sizeof(hc_header));if (err <0 )return ERR_PTR (err);
@@ -990,7 +995,7 @@ snd_usb_get_audioformat_uac3(struct snd_usb_audio *chip,UAC3_CS_REQ_HIGH_CAPABILITY_DESCRIPTOR ,USB_RECIP_INTERFACE |USB_TYPE_CLASS |USB_DIR_IN , cluster_id, -snd_usb_ctrl_intf (chip), +snd_usb_ctrl_intf (ctrl_intf), cluster, wLength);if (err <0 ) {kfree (cluster);
@@ -1011,7 +1016,7 @@ snd_usb_get_audioformat_uac3(struct snd_usb_audio *chip,* lookup the terminal associated to this interface * to extract the clock */ - input_term =snd_usb_find_input_terminal_descriptor (chip->ctrl_intf, + input_term =snd_usb_find_input_terminal_descriptor (ctrl_intf, as->bTerminalLink,UAC_VERSION_3 );if (input_term) {
@@ -1019,7 +1024,7 @@ snd_usb_get_audioformat_uac3(struct snd_usb_audio *chip, goto found_clock; } - output_term =snd_usb_find_output_terminal_descriptor (chip->ctrl_intf, + output_term =snd_usb_find_output_terminal_descriptor (ctrl_intf, as->bTerminalLink,UAC_VERSION_3 );if (output_term) {
@@ -1068,7 +1073,7 @@ snd_usb_get_audioformat_uac3(struct snd_usb_audio *chip,UAC_VERSION_3 , iface_no); - pd =snd_usb_find_power_domain (chip->ctrl_intf, + pd =snd_usb_find_power_domain (ctrl_intf, as->bTerminalLink);/* ok, let's parse further... */
sound/usb/usbaudio.h +12 -0
@@ -21,6 +21,15 @@ struct media_intf_devnode;#define MAX_CARD_INTERFACES 16 +/* +* Structure holding assosiation between Audio Control Interface +* and given Streaming or Midi Interface. +*/ +struct snd_intf_to_ctrl { +u8 interface; +struct usb_host_interface *ctrl_intf; +}; +struct snd_usb_audio {int index;struct usb_device *dev;
@@ -63,6 +72,9 @@ struct snd_usb_audio {struct usb_host_interface *ctrl_intf;/* the audio control interface */ struct media_device *media_dev;struct media_intf_devnode *ctl_intf_media_devnode; + +unsigned int num_intf_to_ctrl; +struct snd_intf_to_ctrl intf_to_ctrl[MAX_CARD_INTERFACES ]; };#define USB_AUDIO_IFACE_UNUSED ((void *)-1L)
Signature · 1 line
2.43.0
Re: [PATCH 6.11 168/558] ALSA: usb-audio: Support multiple control interfaces
Quoted 6 lines · Greg Kroah-Hartman
6.11-stable review patch. If anyone has any objections, please let me know.
------------------
From: Karol Kosik <[email protected]>
Quoted 7 lines
[ Upstream commit
6aa8700150f7dc62f60b4cf5b1624e2e3d9ed78e]Registering Numark Party Mix II fails with error 'bogus bTerminalLink 1'. The problem stems from the driver not being able to find input/output terminals required to configure audio streaming. The information about those terminals is stored in AudioControl Interface. Numark device contains 2 AudioControl Interfaces and the driver checks only one of them.
Please postpone (or skip) merging my patch to 6.11 due to regression.
I've just learned that my change causes kernel crash when Apple USB-C headphones are connected and confirmed it's related to my change.
TL;DR: The general idea is correct, but I missed one variable initialization when specific USB 3.0 audio device connects, as none of the devices I tested were relying on it.
I'm sorry for the disruption caused by this commit. One line fix will be sent for review tomorrow after I re-run all tests, and I aim to get it into 6.12-rc3.
Regards,
Karol Kosik
Greg Kroah-Hartman
maintainerRe: [PATCH 6.11 168/558] ALSA: usb-audio: Support multiple control interfaces
Quoted 22 lines · Karol Kosik
Quoted 6 lines · Greg Kroah-Hartman
6.11-stable review patch. If anyone has any objections, please let me know.
------------------
From: Karol Kosik <[email protected]>
Quoted 7 lines
[ Upstream commit
6aa8700150f7dc62f60b4cf5b1624e2e3d9ed78e]Registering Numark Party Mix II fails with error 'bogus bTerminalLink 1'. The problem stems from the driver not being able to find input/output terminals required to configure audio streaming. The information about those terminals is stored in AudioControl Interface. Numark device contains 2 AudioControl Interfaces and the driver checks only one of them.
Please postpone (or skip) merging my patch to 6.11 due to regression.
I've just learned that my change causes kernel crash when Apple USB-C headphones are connected and confirmed it's related to my change.
Quoted 6 lines
TL;DR: The general idea is correct, but I missed one variable initialization when specific USB 3.0 audio device connects, as none of the devices I tested were relying on it.
I'm sorry for the disruption caused by this commit. One line fix will be sent for review tomorrow after I re-run all tests, and I aim to get it into 6.12-rc3.
Ok, now dropped from all stable queues.
greg k-h
Greg Kroah-Hartman
maintainerPATCH 169/558 ALSA: usb-audio: Define macros for quirk table entries
In reply to Greg Kroah-Hartman6.11-stable review patch. If anyone has any objections, please let me know.
------------------
From: Takashi Iwai <[email protected]>
[ 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.
--- sound/usb/quirks-table.h | 77 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 77 insertions(+)
sound/usb/quirks-table.h +77 -0
@@ -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),
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 170/558 ALSA: usb-audio: Replace complex quirk lines with macros
In reply to Greg Kroah-Hartman6.11-stable review patch. If anyone has any objections, please let me know.
------------------
From: Takashi Iwai <[email protected]>
[ 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.
--- sound/usb/quirks-table.h | 2210 ++++++++++---------------------------- 1 file changed, 593 insertions(+), 1617 deletions(-)
sound/usb/quirks-table.h +593 -1617
@@ -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 []) { - { - .ifnum =2 , - .type =QUIRK_AUDIO_STANDARD_MIXER , - }, + QUIRK_DRIVER_INFO { + QUIRK_DATA_COMPOSITE { + { QUIRK_DATA_STANDARD_MIXER(2) }, { - .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 []) { - { - .ifnum =0 , - .type =QUIRK_IGNORE_INTERFACE - }, - { - .ifnum =1 , - .type =QUIRK_IGNORE_INTERFACE - }, + QUIRK_DATA_COMPOSITE { + { QUIRK_DATA_IGNORE(0) }, + { QUIRK_DATA_IGNORE(1) }, { - .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 []) { - { - .ifnum =0 , - .type =QUIRK_IGNORE_INTERFACE - }, + QUIRK_DATA_COMPOSITE { + { QUIRK_DATA_IGNORE(0) }, + { QUIRK_DATA_IGNORE(1) }, { - .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 []) { - { - .ifnum =0 , - .type =QUIRK_IGNORE_INTERFACE - }, + QUIRK_DATA_COMPOSITE { + { QUIRK_DATA_IGNORE(0) }, + { QUIRK_DATA_IGNORE(1) }, { - .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 []) { - { - .ifnum =0 , - .type =QUIRK_IGNORE_INTERFACE - }, - { - .ifnum =1 , - .type =QUIRK_IGNORE_INTERFACE - }, + QUIRK_DATA_COMPOSITE { + { QUIRK_DATA_IGNORE(0) }, + { QUIRK_DATA_IGNORE(1) }, { - .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 []) { - { - .ifnum =0 , - .type =QUIRK_IGNORE_INTERFACE - }, + QUIRK_DATA_COMPOSITE { + { QUIRK_DATA_IGNORE(0) }, + { QUIRK_DATA_IGNORE(1) }, { - .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 []) { - { - .ifnum =0 , - .type =QUIRK_IGNORE_INTERFACE - }, + QUIRK_DATA_COMPOSITE { + { QUIRK_DATA_IGNORE(0) }, + { QUIRK_DATA_IGNORE(1) }, { - .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 <[email protected]> * 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 []) { - { - .ifnum =0 , - .type =QUIRK_AUDIO_STANDARD_INTERFACE - }, - { - .ifnum =1 , - .type =QUIRK_AUDIO_STANDARD_INTERFACE - }, + QUIRK_DATA_COMPOSITE { + { QUIRK_DATA_STANDARD_AUDIO(0) }, + { QUIRK_DATA_STANDARD_AUDIO(1) }, { - .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 []) { - { - .ifnum =0 , - .type =QUIRK_AUDIO_STANDARD_INTERFACE - }, + QUIRK_DATA_COMPOSITE { + { QUIRK_DATA_STANDARD_AUDIO(0) }, + { QUIRK_DATA_STANDARD_AUDIO(1) }, { - .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 []) { - { - .ifnum =0 , - .type =QUIRK_IGNORE_INTERFACE - }, - { - .ifnum =1 , - .type =QUIRK_IGNORE_INTERFACE - }, + QUIRK_DATA_COMPOSITE { + { QUIRK_DATA_IGNORE(0) }, + { QUIRK_DATA_IGNORE(1) }, { - .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 []) { - { - .ifnum =0 , - .type =QUIRK_IGNORE_INTERFACE - }, + QUIRK_DATA_COMPOSITE { + { QUIRK_DATA_IGNORE(0) }, { - .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 []) { - { - .ifnum =0 , - .type =QUIRK_AUDIO_STANDARD_INTERFACE - }, + QUIRK_DATA_COMPOSITE { + { QUIRK_DATA_STANDARD_AUDIO(0) }, + { QUIRK_DATA_STANDARD_AUDIO(1) }, { - .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 <[email protected]> */ 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). */ - { - .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_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) }, + { + 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 []) { - { - .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_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) }, + { + 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 []) { - { - .ifnum =0 , - .type =QUIRK_AUDIO_STANDARD_INTERFACE - }, - { - .ifnum =1 , - .type =QUIRK_AUDIO_STANDARD_INTERFACE - }, + QUIRK_DATA_COMPOSITE { + { QUIRK_DATA_STANDARD_AUDIO(0) }, + { QUIRK_DATA_STANDARD_AUDIO(1) }, + { QUIRK_DATA_STANDARD_AUDIO(2) }, { - .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 []) { - { - .ifnum =0 , - .type =QUIRK_AUDIO_STANDARD_MIXER , - }, + QUIRK_DATA_COMPOSITE { + { QUIRK_DATA_STANDARD_MIXER(0) }, { - .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 []) { - { - .ifnum =0 , - .type =QUIRK_AUDIO_STANDARD_MIXER , - }, + QUIRK_DATA_COMPOSITE { + { QUIRK_DATA_STANDARD_MIXER(0) }, { - .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 []) { - { - .ifnum =0 , - .type =QUIRK_AUDIO_STANDARD_INTERFACE - }, - { - .ifnum =1 , - .type =QUIRK_AUDIO_STANDARD_INTERFACE - }, - { - .ifnum =2 , - .type =QUIRK_AUDIO_STANDARD_INTERFACE - }, + QUIRK_DRIVER_INFO { + QUIRK_DATA_COMPOSITE { + { QUIRK_DATA_STANDARD_AUDIO(0) }, + { QUIRK_DATA_STANDARD_AUDIO(1) }, + { QUIRK_DATA_STANDARD_AUDIO(2) }, { - .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 []) { - { - .ifnum =0 , - .type =QUIRK_AUDIO_STANDARD_INTERFACE - }, - { - .ifnum =1 , - .type =QUIRK_AUDIO_STANDARD_INTERFACE - }, - { - .ifnum =2 , - .type =QUIRK_AUDIO_STANDARD_INTERFACE - }, + QUIRK_DRIVER_INFO { + QUIRK_DATA_COMPOSITE { + { QUIRK_DATA_STANDARD_AUDIO(0) }, + { QUIRK_DATA_STANDARD_AUDIO(1) }, + { QUIRK_DATA_STANDARD_AUDIO(2) }, { - .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 <[email protected]> */ 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 []){ - { - .ifnum =0 , - .type =QUIRK_AUDIO_STANDARD_MIXER , - }, + QUIRK_DATA_COMPOSITE{ + { QUIRK_DATA_STANDARD_MIXER(0) }, { - .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 []) { - { - .ifnum =0 , - .type =QUIRK_IGNORE_INTERFACE - }, - { - .ifnum =1 , - .type =QUIRK_IGNORE_INTERFACE - }, + QUIRK_DATA_COMPOSITE { + { QUIRK_DATA_IGNORE(0) }, + { QUIRK_DATA_IGNORE(1) }, { - .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 []) { - { - .ifnum =0 , - .type =QUIRK_IGNORE_INTERFACE - }, + QUIRK_DATA_COMPOSITE { + { QUIRK_DATA_IGNORE(0) }, + { QUIRK_DATA_IGNORE(1) }, { - .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 , .fmt_bits = 24, .channels = 4,
@@ -3120,9 +2358,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, .fmt_bits = 24, .channels = 4,
@@ -3146,36 +2382,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,
@@ -3196,9 +2421,7 @@ YAMAHA_DEVICE(0x7010, "UB99"), } } }, - { - .ifnum = -1 - } + QUIRK_COMPOSITE_END } } },
@@ -3206,20 +2429,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,
@@ -3240,9 +2456,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,
@@ -3262,13 +2476,8 @@ YAMAHA_DEVICE(0x7010, "UB99"), } } }, - { - .ifnum = 4, - .type = QUIRK_MIDI_STANDARD_INTERFACE, - }, - { - .ifnum = -1 - } + { QUIRK_DATA_STANDARD_MIDI(4) }, + QUIRK_COMPOSITE_END } } },
@@ -3277,17 +2486,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,
@@ -3303,9 +2508,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,
@@ -3319,9 +2522,7 @@ YAMAHA_DEVICE(0x7010, "UB99"), .rate_max = 16000 } }, - { - .ifnum = -1 - } + QUIRK_COMPOSITE_END } } },
@@ -3330,18 +2531,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,
@@ -3360,9 +2554,7 @@ YAMAHA_DEVICE(0x7010, "UB99"), } } }, - { - .ifnum = -1 - } + QUIRK_COMPOSITE_END } } },
@@ -3375,28 +2567,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 } } },
@@ -3410,18 +2586,16 @@ YAMAHA_DEVICE(0x7010, "UB99"), USB_DEVICE_ID_MATCH_INT_SUBCLASS,
Lines of this file are not shown. View the raw message.
The rest of this diff is not shown. View the raw message.
Signature · 1 line
2.43.0
Part of the diff is not shown here. View the raw message.
Greg Kroah-Hartman
maintainerPATCH 171/558 ALSA: usb-audio: Add quirk for RME Digiface USB
In reply to Greg Kroah-Hartman6.11-stable review patch. If anyone has any objections, please let me know.
------------------
From: Cyan Nyan <[email protected]>
[ Upstream commit c032044e9672408c534d64a6df2b1ba14449e948 ]
Add trivial support for audio streaming on the RME Digiface USB. Binds only to the first interface to allow userspace to directly drive the complex I/O and matrix mixer controls.
--- sound/usb/quirks-table.h | 171 ++++++++++++++++++++++++++++++++++++++- sound/usb/quirks.c | 58 +++++++++++++ 2 files changed, 228 insertions(+), 1 deletion(-)
sound/usb/quirks-table.h +170 -1
@@ -3604,6 +3604,175 @@ YAMAHA_DEVICE(0x7010, "UB99"), } } }, - +{ + /* Only claim interface 0 */ + .match_flags = USB_DEVICE_ID_MATCH_VENDOR | + USB_DEVICE_ID_MATCH_PRODUCT | + USB_DEVICE_ID_MATCH_INT_CLASS | + USB_DEVICE_ID_MATCH_INT_NUMBER, + .idVendor = 0x2a39, + .idProduct = 0x3f8c, + .bInterfaceClass = USB_CLASS_VENDOR_SPEC, + .bInterfaceNumber = 0, + QUIRK_DRIVER_INFO { + QUIRK_DATA_COMPOSITE { + /* + * Three modes depending on sample rate band, + * with different channel counts for in/out + */ + { + QUIRK_DATA_AUDIOFORMAT(0) { + .formats = SNDRV_PCM_FMTBIT_S32_LE, + .channels = 34, // outputs + .fmt_bits = 24, + .iface = 0, + .altsetting = 1, + .altset_idx = 1, + .endpoint = 0x02, + .ep_idx = 1, + .ep_attr = USB_ENDPOINT_XFER_ISOC | + USB_ENDPOINT_SYNC_ASYNC, + .rates = SNDRV_PCM_RATE_32000 | + SNDRV_PCM_RATE_44100 | + SNDRV_PCM_RATE_48000, + .rate_min = 32000, + .rate_max = 48000, + .nr_rates = 3, + .rate_table = (unsigned int[]) { + 32000, 44100, 48000, + }, + .sync_ep = 0x81, + .sync_iface = 0, + .sync_altsetting = 1, + .sync_ep_idx = 0, + .implicit_fb = 1, + }, + }, + { + QUIRK_DATA_AUDIOFORMAT(0) { + .formats = SNDRV_PCM_FMTBIT_S32_LE, + .channels = 18, // outputs + .fmt_bits = 24, + .iface = 0, + .altsetting = 1, + .altset_idx = 1, + .endpoint = 0x02, + .ep_idx = 1, + .ep_attr = USB_ENDPOINT_XFER_ISOC | + USB_ENDPOINT_SYNC_ASYNC, + .rates = SNDRV_PCM_RATE_64000 | + SNDRV_PCM_RATE_88200 | + SNDRV_PCM_RATE_96000, + .rate_min = 64000, + .rate_max = 96000, + .nr_rates = 3, + .rate_table = (unsigned int[]) { + 64000, 88200, 96000, + }, + .sync_ep = 0x81, + .sync_iface = 0, + .sync_altsetting = 1, + .sync_ep_idx = 0, + .implicit_fb = 1, + }, + }, + { + QUIRK_DATA_AUDIOFORMAT(0) { + .formats = SNDRV_PCM_FMTBIT_S32_LE, + .channels = 10, // outputs + .fmt_bits = 24, + .iface = 0, + .altsetting = 1, + .altset_idx = 1, + .endpoint = 0x02, + .ep_idx = 1, + .ep_attr = USB_ENDPOINT_XFER_ISOC | + USB_ENDPOINT_SYNC_ASYNC, + .rates = SNDRV_PCM_RATE_KNOT | + SNDRV_PCM_RATE_176400 | + SNDRV_PCM_RATE_192000, + .rate_min = 128000, + .rate_max = 192000, + .nr_rates = 3, + .rate_table = (unsigned int[]) { + 128000, 176400, 192000, + }, + .sync_ep = 0x81, + .sync_iface = 0, + .sync_altsetting = 1, + .sync_ep_idx = 0, + .implicit_fb = 1, + }, + }, + { + QUIRK_DATA_AUDIOFORMAT(0) { + .formats = SNDRV_PCM_FMTBIT_S32_LE, + .channels = 32, // inputs + .fmt_bits = 24, + .iface = 0, + .altsetting = 1, + .altset_idx = 1, + .endpoint = 0x81, + .ep_attr = USB_ENDPOINT_XFER_ISOC | + USB_ENDPOINT_SYNC_ASYNC, + .rates = SNDRV_PCM_RATE_32000 | + SNDRV_PCM_RATE_44100 | + SNDRV_PCM_RATE_48000, + .rate_min = 32000, + .rate_max = 48000, + .nr_rates = 3, + .rate_table = (unsigned int[]) { + 32000, 44100, 48000, + } + } + }, + { + QUIRK_DATA_AUDIOFORMAT(0) { + .formats = SNDRV_PCM_FMTBIT_S32_LE, + .channels = 16, // inputs + .fmt_bits = 24, + .iface = 0, + .altsetting = 1, + .altset_idx = 1, + .endpoint = 0x81, + .ep_attr = USB_ENDPOINT_XFER_ISOC | + USB_ENDPOINT_SYNC_ASYNC, + .rates = SNDRV_PCM_RATE_64000 | + SNDRV_PCM_RATE_88200 | + SNDRV_PCM_RATE_96000, + .rate_min = 64000, + .rate_max = 96000, + .nr_rates = 3, + .rate_table = (unsigned int[]) { + 64000, 88200, 96000, + } + } + }, + { + QUIRK_DATA_AUDIOFORMAT(0) { + .formats = SNDRV_PCM_FMTBIT_S32_LE, + .channels = 8, // inputs + .fmt_bits = 24, + .iface = 0, + .altsetting = 1, + .altset_idx = 1, + .endpoint = 0x81, + .ep_attr = USB_ENDPOINT_XFER_ISOC | + USB_ENDPOINT_SYNC_ASYNC, + .rates = SNDRV_PCM_RATE_KNOT | + SNDRV_PCM_RATE_176400 | + SNDRV_PCM_RATE_192000, + .rate_min = 128000, + .rate_max = 192000, + .nr_rates = 3, + .rate_table = (unsigned int[]) { + 128000, 176400, 192000, + } + } + }, + QUIRK_COMPOSITE_END + } + } +}, #undef USB_DEVICE_VENDOR_SPEC #undef USB_AUDIO_DEVICE
sound/usb/quirks.c +58 -0
82 lines not on this page · raw message
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 172/558 ALSA: usb-audio: Add mixer quirk for RME Digiface USB
In reply to Greg Kroah-Hartman6.11-stable review patch. If anyone has any objections, please let me know.
------------------
From: Asahi Lina <[email protected]>
[ Upstream commit 611a96f6acf2e74fe28cb90908a9c183862348ce ]
Implement sync, output format, and input status mixer controls, to allow the interface to be used as a straight ADAT/SPDIF (+ Headphones) I/O interface.
This does not implement the matrix mixer, output gain controls, or input level meter feedback. The full mixer interface is only really usable using a dedicated userspace control app (there are too many mixer nodes for alsamixer to be usable), so for now we leave it up to userspace to directly control these features using raw USB control messages. This is similar to how it's done with some FireWire interfaces (ffado-mixer).
--- sound/usb/mixer_quirks.c | 413 +++++++++++++++++++++++++++++++++++++++ sound/usb/quirks-table.h | 1 + 2 files changed, 414 insertions(+)
sound/usb/mixer_quirks.c +413 -0
@@ -14,6 +14,7 @@* Przemek Rudy ([email protected]) */ +#include <linux/bitfield.h> #include <linux/hid.h> #include <linux/init.h> #include <linux/math64.h>
@@ -2926,6 +2927,415 @@ static int snd_bbfpro_controls_create(struct usb_mixer_interface *mixer)return 0 ; } +/* +* RME Digiface USB +*/ + +#define RME_DIGIFACE_READ_STATUS 17 +#define RME_DIGIFACE_STATUS_REG0L 0 +#define RME_DIGIFACE_STATUS_REG0H 1 +#define RME_DIGIFACE_STATUS_REG1L 2 +#define RME_DIGIFACE_STATUS_REG1H 3 +#define RME_DIGIFACE_STATUS_REG2L 4 +#define RME_DIGIFACE_STATUS_REG2H 5 +#define RME_DIGIFACE_STATUS_REG3L 6 +#define RME_DIGIFACE_STATUS_REG3H 7 + +#define RME_DIGIFACE_CTL_REG1 16 +#define RME_DIGIFACE_CTL_REG2 18 + +/* Reg is overloaded, 0-7 for status halfwords or 16 or 18 for control registers */ +#define RME_DIGIFACE_REGISTER (reg, mask) (((reg) << 16) | (mask)) +#define RME_DIGIFACE_INVERT BIT(31) + +/* Nonconst helpers */ +#define field_get (_mask, _reg) (((_reg) & (_mask)) >> (ffs(_mask) - 1)) +#define field_prep (_mask, _val) (((_val) << (ffs(_mask) - 1)) & (_mask)) + +static int snd_rme_digiface_write_reg (struct snd_kcontrol *kcontrol,int item,u16 mask,u16 val) +{ +struct usb_mixer_elem_list *list =snd_kcontrol_chip (kcontrol); +struct snd_usb_audio *chip = list->mixer->chip; +struct usb_device *dev = chip->dev; +int err; + + err =snd_usb_ctl_msg (dev,usb_sndctrlpipe (dev,0 ), + item, +USB_DIR_OUT |USB_TYPE_VENDOR |USB_RECIP_DEVICE , + val, mask,NULL ,0 ); +if (err <0 ) +dev_err (&dev->dev, +"unable to issue control set request %d (ret = %d)" , + item, err); +return err; +} + +static int snd_rme_digiface_read_status (struct snd_kcontrol *kcontrol,u32 status[4 ]) +{ +struct usb_mixer_elem_list *list =snd_kcontrol_chip (kcontrol); +struct snd_usb_audio *chip = list->mixer->chip; +struct usb_device *dev = chip->dev; +__le32 buf[4 ]; +int err; + + err =snd_usb_ctl_msg (dev,usb_rcvctrlpipe (dev,0 ), +RME_DIGIFACE_READ_STATUS , +USB_DIR_IN |USB_TYPE_VENDOR |USB_RECIP_DEVICE , +0 ,0 , + buf,sizeof (buf)); +if (err <0 ) { +dev_err (&dev->dev, +"unable to issue status read request (ret = %d)" , + err); + }else { +for (int i =0 ; i <ARRAY_SIZE (buf); i++) + status[i] =le32_to_cpu (buf[i]); + } +return err; +} + +static int snd_rme_digiface_get_status_val (struct snd_kcontrol *kcontrol) +{ +int err; +u32 status[4 ]; +bool invert = kcontrol->private_value &RME_DIGIFACE_INVERT ; +u8 reg = (kcontrol->private_value >>16 ) &0xff ; +u16 mask = kcontrol->private_value &0xffff ; +u16 val; + + err =snd_rme_digiface_read_status (kcontrol, status); +if (err <0 ) +return err; + +switch (reg) { +/* Status register halfwords */ + case RME_DIGIFACE_STATUS_REG0L ... RME_DIGIFACE_STATUS_REG3H: +break ; +case RME_DIGIFACE_CTL_REG1 :/* Control register 1, present in halfword 3L */ + reg =RME_DIGIFACE_STATUS_REG3L ; +break ; +case RME_DIGIFACE_CTL_REG2 :/* Control register 2, present in halfword 3H */ + reg =RME_DIGIFACE_STATUS_REG3H ; +break ; +default : +return -EINVAL ; + } + +if (reg &1 ) + val = status[reg >>1 ] >>16 ; +else + val = status[reg >>1 ] &0xffff ; + +if (invert) + val ^= mask; + +return field_get (mask, val); +} + +static int snd_rme_digiface_rate_get (struct snd_kcontrol *kcontrol, +struct snd_ctl_elem_value *ucontrol) +{ +int freq =snd_rme_digiface_get_status_val (kcontrol); + +if (freq <0 ) +return freq; +if (freq >=ARRAY_SIZE (snd_rme_rate_table)) +return -EIO ; + + ucontrol->value.integer.value[0 ] = snd_rme_rate_table[freq]; +return 0 ; +} + +static int snd_rme_digiface_enum_get (struct snd_kcontrol *kcontrol, +struct snd_ctl_elem_value *ucontrol) +{ +int val =snd_rme_digiface_get_status_val (kcontrol); + +if (val <0 ) +return val; + + ucontrol->value.enumerated.item[0 ] = val; +return 0 ; +} + +static int snd_rme_digiface_enum_put (struct snd_kcontrol *kcontrol, +struct snd_ctl_elem_value *ucontrol) +{ +bool invert = kcontrol->private_value &RME_DIGIFACE_INVERT ; +u8 reg = (kcontrol->private_value >>16 ) &0xff ; +u16 mask = kcontrol->private_value &0xffff ; +u16 val =field_prep (mask, ucontrol->value.enumerated.item[0 ]); + +if (invert) + val ^= mask; + +return snd_rme_digiface_write_reg (kcontrol, reg, mask, val); +} + +static int snd_rme_digiface_current_sync_get (struct snd_kcontrol *kcontrol, +struct snd_ctl_elem_value *ucontrol) +{ +int ret =snd_rme_digiface_enum_get (kcontrol, ucontrol); + +/* 7 means internal for current sync */ +if (ucontrol->value.enumerated.item[0 ] ==7 ) + ucontrol->value.enumerated.item[0 ] =0 ; + +return ret; +} + +static int snd_rme_digiface_sync_state_get (struct snd_kcontrol *kcontrol, +struct snd_ctl_elem_value *ucontrol) +{ +u32 status[4 ]; +int err; +bool valid, sync; + + err =snd_rme_digiface_read_status (kcontrol, status); +if (err <0 ) +return err; + + valid = status[0 ] &BIT (kcontrol->private_value); + sync = status[0 ] &BIT (5 + kcontrol->private_value); + +if (!valid) + ucontrol->value.enumerated.item[0 ] =SND_RME_CLOCK_NOLOCK ; +else if (!sync) + ucontrol->value.enumerated.item[0 ] =SND_RME_CLOCK_LOCK ; +else + ucontrol->value.enumerated.item[0 ] =SND_RME_CLOCK_SYNC ; +return 0 ; +} + + +static int snd_rme_digiface_format_info (struct snd_kcontrol *kcontrol, +struct snd_ctl_elem_info *uinfo) +{ +static const char *const format[] = { +"ADAT" ,"S/PDIF" + }; + +return snd_ctl_enum_info (uinfo,1 , +ARRAY_SIZE (format), format); +} + + +static int snd_rme_digiface_sync_source_info (struct snd_kcontrol *kcontrol, +struct snd_ctl_elem_info *uinfo) +{ +static const char *const sync_sources[] = { +"Internal" ,"Input 1" ,"Input 2" ,"Input 3" ,"Input 4" + }; + +return snd_ctl_enum_info (uinfo,1 , +ARRAY_SIZE (sync_sources), sync_sources); +} + +static int snd_rme_digiface_rate_info (struct snd_kcontrol *kcontrol, +struct snd_ctl_elem_info *uinfo) +{ + uinfo->type =SNDRV_CTL_ELEM_TYPE_INTEGER ; + uinfo->count =1 ; + uinfo->value.integer.min =0 ; + uinfo->value.integer.max =200000 ; + uinfo->value.integer.step =0 ; +return 0 ; +} + +static const struct snd_kcontrol_new snd_rme_digiface_controls[] = { + { + .iface =SNDRV_CTL_ELEM_IFACE_MIXER , + .name ="Input 1 Sync" , + .access =SNDRV_CTL_ELEM_ACCESS_READ |SNDRV_CTL_ELEM_ACCESS_VOLATILE , + .info = snd_rme_sync_state_info, + .get = snd_rme_digiface_sync_state_get, + .private_value =0 , + }, + { + .iface =SNDRV_CTL_ELEM_IFACE_MIXER , + .name ="Input 1 Format" , + .access =SNDRV_CTL_ELEM_ACCESS_READ |SNDRV_CTL_ELEM_ACCESS_VOLATILE , + .info = snd_rme_digiface_format_info, + .get = snd_rme_digiface_enum_get, + .private_value =RME_DIGIFACE_REGISTER (RME_DIGIFACE_STATUS_REG0H ,BIT (0 )) | +RME_DIGIFACE_INVERT , + }, + { + .iface =SNDRV_CTL_ELEM_IFACE_MIXER , + .name ="Input 1 Rate" , + .access =SNDRV_CTL_ELEM_ACCESS_READ |SNDRV_CTL_ELEM_ACCESS_VOLATILE , + .info = snd_rme_digiface_rate_info, + .get = snd_rme_digiface_rate_get, + .private_value =RME_DIGIFACE_REGISTER (RME_DIGIFACE_STATUS_REG1L ,GENMASK (3 ,0 )), + }, + { + .iface =SNDRV_CTL_ELEM_IFACE_MIXER , + .name ="Input 2 Sync" , + .access =SNDRV_CTL_ELEM_ACCESS_READ |SNDRV_CTL_ELEM_ACCESS_VOLATILE , + .info = snd_rme_sync_state_info, + .get = snd_rme_digiface_sync_state_get, + .private_value =1 , + }, + { + .iface =SNDRV_CTL_ELEM_IFACE_MIXER , + .name ="Input 2 Format" , + .access =SNDRV_CTL_ELEM_ACCESS_READ |SNDRV_CTL_ELEM_ACCESS_VOLATILE , + .info = snd_rme_digiface_format_info, + .get = snd_rme_digiface_enum_get, + .private_value =RME_DIGIFACE_REGISTER (RME_DIGIFACE_STATUS_REG0L ,BIT (13 )) | +RME_DIGIFACE_INVERT , + }, + { + .iface =SNDRV_CTL_ELEM_IFACE_MIXER , + .name ="Input 2 Rate" , + .access =SNDRV_CTL_ELEM_ACCESS_READ |SNDRV_CTL_ELEM_ACCESS_VOLATILE , + .info = snd_rme_digiface_rate_info, + .get = snd_rme_digiface_rate_get, + .private_value =RME_DIGIFACE_REGISTER (RME_DIGIFACE_STATUS_REG1L ,GENMASK (7 ,4 )), + }, + { + .iface =SNDRV_CTL_ELEM_IFACE_MIXER , + .name ="Input 3 Sync" , + .access =SNDRV_CTL_ELEM_ACCESS_READ |SNDRV_CTL_ELEM_ACCESS_VOLATILE , + .info = snd_rme_sync_state_info, + .get = snd_rme_digiface_sync_state_get, + .private_value =2 , + }, + { + .iface =SNDRV_CTL_ELEM_IFACE_MIXER , + .name ="Input 3 Format" , + .access =SNDRV_CTL_ELEM_ACCESS_READ |SNDRV_CTL_ELEM_ACCESS_VOLATILE , + .info = snd_rme_digiface_format_info, + .get = snd_rme_digiface_enum_get, + .private_value =RME_DIGIFACE_REGISTER (RME_DIGIFACE_STATUS_REG0L ,BIT (14 )) | +RME_DIGIFACE_INVERT , + }, + { + .iface =SNDRV_CTL_ELEM_IFACE_MIXER , + .name ="Input 3 Rate" , + .access =SNDRV_CTL_ELEM_ACCESS_READ |SNDRV_CTL_ELEM_ACCESS_VOLATILE , + .info = snd_rme_digiface_rate_info, + .get = snd_rme_digiface_rate_get, + .private_value =RME_DIGIFACE_REGISTER (RME_DIGIFACE_STATUS_REG1L ,GENMASK (11 ,8 )), + }, + { + .iface =SNDRV_CTL_ELEM_IFACE_MIXER , + .name ="Input 4 Sync" , + .access =SNDRV_CTL_ELEM_ACCESS_READ |SNDRV_CTL_ELEM_ACCESS_VOLATILE , + .info = snd_rme_sync_state_info, + .get = snd_rme_digiface_sync_state_get, + .private_value =3 , + }, + { + .iface =SNDRV_CTL_ELEM_IFACE_MIXER , + .name ="Input 4 Format" , + .access =SNDRV_CTL_ELEM_ACCESS_READ |SNDRV_CTL_ELEM_ACCESS_VOLATILE , + .info = snd_rme_digiface_format_info, + .get = snd_rme_digiface_enum_get, + .private_value =RME_DIGIFACE_REGISTER (RME_DIGIFACE_STATUS_REG0L ,GENMASK (15 ,12 )) | +RME_DIGIFACE_INVERT , + }, + { + .iface =SNDRV_CTL_ELEM_IFACE_MIXER , + .name ="Input 4 Rate" , + .access =SNDRV_CTL_ELEM_ACCESS_READ |SNDRV_CTL_ELEM_ACCESS_VOLATILE , + .info = snd_rme_digiface_rate_info, + .get = snd_rme_digiface_rate_get, + .private_value =RME_DIGIFACE_REGISTER (RME_DIGIFACE_STATUS_REG1L ,GENMASK (3 ,0 )), + }, + { + .iface =SNDRV_CTL_ELEM_IFACE_MIXER , + .name ="Output 1 Format" , + .access =SNDRV_CTL_ELEM_ACCESS_READWRITE , + .info = snd_rme_digiface_format_info, + .get = snd_rme_digiface_enum_get, + .put = snd_rme_digiface_enum_put, + .private_value =RME_DIGIFACE_REGISTER (RME_DIGIFACE_CTL_REG2 ,BIT (0 )), + }, + { + .iface =SNDRV_CTL_ELEM_IFACE_MIXER , + .name ="Output 2 Format" , + .access =SNDRV_CTL_ELEM_ACCESS_READWRITE , + .info = snd_rme_digiface_format_info, + .get = snd_rme_digiface_enum_get, + .put = snd_rme_digiface_enum_put, + .private_value =RME_DIGIFACE_REGISTER (RME_DIGIFACE_CTL_REG2 ,BIT (1 )), + }, + { + .iface =SNDRV_CTL_ELEM_IFACE_MIXER , + .name ="Output 3 Format" , + .access =SNDRV_CTL_ELEM_ACCESS_READWRITE , + .info = snd_rme_digiface_format_info, + .get = snd_rme_digiface_enum_get, + .put = snd_rme_digiface_enum_put, + .private_value =RME_DIGIFACE_REGISTER (RME_DIGIFACE_CTL_REG2 ,BIT (3 )), + }, + { + .iface =SNDRV_CTL_ELEM_IFACE_MIXER , + .name ="Output 4 Format" , + .access =SNDRV_CTL_ELEM_ACCESS_READWRITE , + .info = snd_rme_digiface_format_info, + .get = snd_rme_digiface_enum_get, + .put = snd_rme_digiface_enum_put, + .private_value =RME_DIGIFACE_REGISTER (RME_DIGIFACE_CTL_REG2 ,BIT (4 )), + }, + { + .iface =SNDRV_CTL_ELEM_IFACE_MIXER , + .name ="Sync Source" , + .access =SNDRV_CTL_ELEM_ACCESS_READWRITE , + .info = snd_rme_digiface_sync_source_info, + .get = snd_rme_digiface_enum_get, + .put = snd_rme_digiface_enum_put, + .private_value =RME_DIGIFACE_REGISTER (RME_DIGIFACE_CTL_REG1 ,GENMASK (2 ,0 )), + }, + { + .iface =SNDRV_CTL_ELEM_IFACE_MIXER , + .name ="Current Sync Source" , + .access =SNDRV_CTL_ELEM_ACCESS_READ |SNDRV_CTL_ELEM_ACCESS_VOLATILE , + .info = snd_rme_digiface_sync_source_info, + .get = snd_rme_digiface_current_sync_get, + .private_value =RME_DIGIFACE_REGISTER (RME_DIGIFACE_STATUS_REG0L ,GENMASK (12 ,10 )), + }, + { +/* +* This is writeable, but it is only set by the PCM rate. +* Mixer apps currently need to drive the mixer using raw USB requests, +* so they can also change this that way to configure the rate for +* stand-alone operation when the PCM is closed. +*/ + .iface =SNDRV_CTL_ELEM_IFACE_MIXER , + .name ="System Rate" , + .access =SNDRV_CTL_ELEM_ACCESS_READ |SNDRV_CTL_ELEM_ACCESS_VOLATILE , + .info = snd_rme_rate_info, + .get = snd_rme_digiface_rate_get, + .private_value =RME_DIGIFACE_REGISTER (RME_DIGIFACE_CTL_REG1 ,GENMASK (6 ,3 )), + }, + { + .iface =SNDRV_CTL_ELEM_IFACE_MIXER , + .name ="Current Rate" , + .access =SNDRV_CTL_ELEM_ACCESS_READ |SNDRV_CTL_ELEM_ACCESS_VOLATILE , + .info = snd_rme_rate_info, + .get = snd_rme_digiface_rate_get, + .private_value =RME_DIGIFACE_REGISTER (RME_DIGIFACE_STATUS_REG1H ,GENMASK (7 ,4 )), + } +}; + +static int snd_rme_digiface_controls_create (struct usb_mixer_interface *mixer) +{ +int err, i; + +for (i =0 ; i <ARRAY_SIZE (snd_rme_digiface_controls); ++i) { + err =add_single_ctl_with_resume (mixer,0 , +NULL , + &snd_rme_digiface_controls[i], +NULL ); +if (err <0 ) +return err; + } + +return 0 ; +} +/* * Pioneer DJ DJM Mixers *
@@ -3484,6 +3894,9 @@ int snd_usb_mixer_apply_create_quirk(struct usb_mixer_interface *mixer)case USB_ID (0x2a39 ,0x3fb0 ):/* RME Babyface Pro FS */ err =snd_bbfpro_controls_create (mixer);break ; +case USB_ID (0x2a39 ,0x3f8c ):/* RME Digiface USB */ + err =snd_rme_digiface_controls_create (mixer); +break ;case USB_ID (0x2b73 ,0x0017 ):/* Pioneer DJ DJM-250MK2 */ err =snd_djm_controls_create (mixer,SND_DJM_250MK2_IDX );break ;
sound/usb/quirks-table.h +1 -0
@@ -3620,6 +3620,7 @@ YAMAHA_DEVICE(0x7010, "UB99"),* Three modes depending on sample rate band, * with different channel counts for in/out */ + { QUIRK_DATA_STANDARD_MIXER(0) }, { QUIRK_DATA_AUDIOFORMAT(0) { .formats = SNDRV_PCM_FMTBIT_S32_LE,
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 173/558 ALSA: hda/realtek: Refactor and simplify Samsung Galaxy Book init
In reply to Greg Kroah-Hartman6.11-stable review patch. If anyone has any objections, please let me know.
------------------
From: Joshua Grisham <[email protected]>
[ Upstream commit 7e4d4b32ab9532bd1babcd5d0763d727ebb04be0 ]
I have done a lot of analysis for these type of devices and collaborated quite a bit with Nick Weihs (author of the first patch submitted for this including adding samsung_helper.c). More information can be found in the issue on Github [1] including additional rationale and testing.
The existing implementation includes a large number of equalizer coef values that are not necessary to actually init and enable the speaker amps, as well as create a somewhat worse sound profile. Users have reported "muffled" or "muddy" sound; more information about this including my analysis of the differences can be found in the linked Github issue.
This patch refactors the "v2" version of ALC298_FIXUP_SAMSUNG_AMP to a much simpler implementation which removes the new samsung_helper.c, reuses more of the existing patch_realtek.c, and sends significantly fewer unnecessary coef values (including removing all of these EQ-specific coef values).
A pcm_playback_hook is used to dynamically enable and disable the speaker amps only when there will be audio playback; this is to match the behavior of how the driver for these devices is working in Windows, and is suspected but not yet tested or confirmed to help with power consumption.
Support for models with 2 speaker amps vs 4 speaker amps is controlled by a specific quirk name for both types. A new int num_speaker_amps has been added to alc_spec so that the hooks can know how many speaker amps to enable or disable. This design was chosen to limit the number of places that subsystem ids will need to be maintained: like this, they can be maintained only once in the quirk table and there will not be another separate list of subsystem ids to maintain elsewhere in the code.
Also updated the quirk name from ALC298_FIXUP_SAMSUNG_AMP2 to ALC298_FIXUP_SAMSUNG_AMP_V2_.. as this is not a quirk for "Amp #2" on ALC298 but is instead a different version of how to handle it.
More devices have been added (see Github issue for testing confirmation), as well as a small cleanup to existing names.
[1]: https://github.com/thesofproject/linux/issues/4055#issuecomment-2323411911
--- sound/pci/hda/patch_realtek.c | 151 +++++++++++++++- sound/pci/hda/samsung_helper.c | 310 --------------------------------- 2 files changed, 144 insertions(+), 317 deletions(-) delete mode 100644 sound/pci/hda/samsung_helper.c
sound/pci/hda/patch_realtek.c +144 -7
@@ -125,6 +125,7 @@ struct alc_spec { unsigned int has_hs_key:1; unsigned int no_internal_mic_pin:1; unsigned int en_3kpull_low:1; +int num_speaker_amps;/* for PLL fix */ hda_nid_t pll_nid;
@@ -4803,7 +4804,133 @@ static void alc298_fixup_samsung_amp(struct hda_codec *codec, } } -#include "samsung_helper.c" +struct alc298_samsung_v2_amp_desc { +unsigned short nid; +int init_seq_size; +unsigned short init_seq[18 ][2 ]; +}; + +static const struct alc298_samsung_v2_amp_desc +alc298_samsung_v2_amp_desc_tbl[] = { + {0x38 ,18 , { + {0x23e1 ,0x0000 }, {0x2012 ,0x006f }, {0x2014 ,0x0000 }, + {0x201b ,0x0001 }, {0x201d ,0x0001 }, {0x201f ,0x00fe }, + {0x2021 ,0x0000 }, {0x2022 ,0x0010 }, {0x203d ,0x0005 }, + {0x203f ,0x0003 }, {0x2050 ,0x002c }, {0x2076 ,0x000e }, + {0x207c ,0x004a }, {0x2081 ,0x0003 }, {0x2399 ,0x0003 }, + {0x23a4 ,0x00b5 }, {0x23a5 ,0x0001 }, {0x23ba ,0x0094 } + }}, + {0x39 ,18 , { + {0x23e1 ,0x0000 }, {0x2012 ,0x006f }, {0x2014 ,0x0000 }, + {0x201b ,0x0002 }, {0x201d ,0x0002 }, {0x201f ,0x00fd }, + {0x2021 ,0x0001 }, {0x2022 ,0x0010 }, {0x203d ,0x0005 }, + {0x203f ,0x0003 }, {0x2050 ,0x002c }, {0x2076 ,0x000e }, + {0x207c ,0x004a }, {0x2081 ,0x0003 }, {0x2399 ,0x0003 }, + {0x23a4 ,0x00b5 }, {0x23a5 ,0x0001 }, {0x23ba ,0x0094 } + }}, + {0x3c ,15 , { + {0x23e1 ,0x0000 }, {0x2012 ,0x006f }, {0x2014 ,0x0000 }, + {0x201b ,0x0001 }, {0x201d ,0x0001 }, {0x201f ,0x00fe }, + {0x2021 ,0x0000 }, {0x2022 ,0x0010 }, {0x203d ,0x0005 }, + {0x203f ,0x0003 }, {0x2050 ,0x002c }, {0x2076 ,0x000e }, + {0x207c ,0x004a }, {0x2081 ,0x0003 }, {0x23ba ,0x008d } + }}, + {0x3d ,15 , { + {0x23e1 ,0x0000 }, {0x2012 ,0x006f }, {0x2014 ,0x0000 }, + {0x201b ,0x0002 }, {0x201d ,0x0002 }, {0x201f ,0x00fd }, + {0x2021 ,0x0001 }, {0x2022 ,0x0010 }, {0x203d ,0x0005 }, + {0x203f ,0x0003 }, {0x2050 ,0x002c }, {0x2076 ,0x000e }, + {0x207c ,0x004a }, {0x2081 ,0x0003 }, {0x23ba ,0x008d } + }} +}; + +static void alc298_samsung_v2_enable_amps (struct hda_codec *codec) +{ +struct alc_spec *spec = codec->spec; +static const unsigned short enable_seq[][2 ] = { + {0x203a ,0x0081 }, {0x23ff ,0x0001 }, + }; +int i, j; + +for (i =0 ; i < spec->num_speaker_amps; i++) { +alc_write_coef_idx (codec,0x22 , alc298_samsung_v2_amp_desc_tbl[i].nid); +for (j =0 ; j <ARRAY_SIZE (enable_seq); j++) +alc298_samsung_write_coef_pack (codec, enable_seq[j]); +codec_dbg (codec,"alc298_samsung_v2: Enabled speaker amp 0x%02x\n" , + alc298_samsung_v2_amp_desc_tbl[i].nid); + } +} + +static void alc298_samsung_v2_disable_amps (struct hda_codec *codec) +{ +struct alc_spec *spec = codec->spec; +static const unsigned short disable_seq[][2 ] = { + {0x23ff ,0x0000 }, {0x203a ,0x0080 }, + }; +int i, j; + +for (i =0 ; i < spec->num_speaker_amps; i++) { +alc_write_coef_idx (codec,0x22 , alc298_samsung_v2_amp_desc_tbl[i].nid); +for (j =0 ; j <ARRAY_SIZE (disable_seq); j++) +alc298_samsung_write_coef_pack (codec, disable_seq[j]); +codec_dbg (codec,"alc298_samsung_v2: Disabled speaker amp 0x%02x\n" , + alc298_samsung_v2_amp_desc_tbl[i].nid); + } +} + +static void alc298_samsung_v2_playback_hook (struct hda_pcm_stream *hinfo, +struct hda_codec *codec, +struct snd_pcm_substream *substream, +int action) +{ +/* Dynamically enable/disable speaker amps before and after playback */ +if (action ==HDA_GEN_PCM_ACT_OPEN ) +alc298_samsung_v2_enable_amps (codec); +if (action ==HDA_GEN_PCM_ACT_CLOSE ) +alc298_samsung_v2_disable_amps (codec); +} + +static void alc298_samsung_v2_init_amps (struct hda_codec *codec, +int num_speaker_amps) +{ +struct alc_spec *spec = codec->spec; +int i, j; + +/* Set spec's num_speaker_amps before doing anything else */ + spec->num_speaker_amps = num_speaker_amps; + +/* Disable speaker amps before init to prevent any physical damage */ +alc298_samsung_v2_disable_amps (codec); + +/* Initialize the speaker amps */ +for (i =0 ; i < spec->num_speaker_amps; i++) { +alc_write_coef_idx (codec,0x22 , alc298_samsung_v2_amp_desc_tbl[i].nid); +for (j =0 ; j < alc298_samsung_v2_amp_desc_tbl[i].init_seq_size; j++) { +alc298_samsung_write_coef_pack (codec, + alc298_samsung_v2_amp_desc_tbl[i].init_seq[j]); + } +alc_write_coef_idx (codec,0x89 ,0x0 ); +codec_dbg (codec,"alc298_samsung_v2: Initialized speaker amp 0x%02x\n" , + alc298_samsung_v2_amp_desc_tbl[i].nid); + } + +/* register hook to enable speaker amps only when they are needed */ + spec->gen.pcm_playback_hook = alc298_samsung_v2_playback_hook; +} + +static void alc298_fixup_samsung_amp_v2_2_amps (struct hda_codec *codec, +const struct hda_fixup *fix,int action) +{ +if (action ==HDA_FIXUP_ACT_PROBE ) +alc298_samsung_v2_init_amps (codec,2 ); +} + +static void alc298_fixup_samsung_amp_v2_4_amps (struct hda_codec *codec, +const struct hda_fixup *fix,int action) +{ +if (action ==HDA_FIXUP_ACT_PROBE ) +alc298_samsung_v2_init_amps (codec,4 ); +}#if IS_REACHABLE (CONFIG_INPUT ) static void gpio2_mic_hotkey_event(struct hda_codec *codec,
@@ -7541,7 +7668,8 @@ enum {ALC236_FIXUP_HP_MUTE_LED_MICMUTE_VREF ,ALC236_FIXUP_LENOVO_INV_DMIC ,ALC298_FIXUP_SAMSUNG_AMP , -ALC298_FIXUP_SAMSUNG_AMP2 , +ALC298_FIXUP_SAMSUNG_AMP_V2_2_AMPS , +ALC298_FIXUP_SAMSUNG_AMP_V2_4_AMPS ,ALC298_FIXUP_SAMSUNG_HEADPHONE_VERY_QUIET ,ALC256_FIXUP_SAMSUNG_HEADPHONE_VERY_QUIET , ALC295_FIXUP_ASUS_MIC_NO_PRESENCE,
@@ -9176,9 +9304,13 @@ static const struct hda_fixup alc269_fixups[] = { .chained = true, .chain_id =ALC298_FIXUP_SAMSUNG_HEADPHONE_VERY_QUIET }, - [ALC298_FIXUP_SAMSUNG_AMP2] = { + [ALC298_FIXUP_SAMSUNG_AMP_V2_2_AMPS] = { + .type = HDA_FIXUP_FUNC, + .v.func = alc298_fixup_samsung_amp_v2_2_amps + }, + [ALC298_FIXUP_SAMSUNG_AMP_V2_4_AMPS] = { .type = HDA_FIXUP_FUNC, - .v.func = alc298_fixup_samsung_amp2 + .v.func = alc298_fixup_samsung_amp_v2_4_amps }, [ALC298_FIXUP_SAMSUNG_HEADPHONE_VERY_QUIET] = { .type = HDA_FIXUP_VERBS,
@@ -10558,8 +10690,10 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {SND_PCI_QUIRK (0x144d ,0xc832 ,"Samsung Galaxy Book Flex Alpha (NP730QCJ)" ,ALC256_FIXUP_SAMSUNG_HEADPHONE_VERY_QUIET ),SND_PCI_QUIRK (0x144d ,0xca03 ,"Samsung Galaxy Book2 Pro 360 (NP930QED)" ,ALC298_FIXUP_SAMSUNG_AMP ),SND_PCI_QUIRK (0x144d ,0xc868 ,"Samsung Galaxy Book2 Pro (NP930XED)" ,ALC298_FIXUP_SAMSUNG_AMP ), -SND_PCI_QUIRK (0x144d ,0xc1ca ,"Samsung Galaxy Book3 Pro 360 (NP960QFG-KB1US)" ,ALC298_FIXUP_SAMSUNG_AMP2 ), -SND_PCI_QUIRK (0x144d ,0xc1cc ,"Samsung Galaxy Book3 Ultra (NT960XFH-XD92G))" ,ALC298_FIXUP_SAMSUNG_AMP2 ), +SND_PCI_QUIRK (0x144d ,0xc870 ,"Samsung Galaxy Book2 Pro (NP950XED)" ,ALC298_FIXUP_SAMSUNG_AMP_V2_2_AMPS ), +SND_PCI_QUIRK (0x144d ,0xc886 ,"Samsung Galaxy Book3 Pro (NP964XFG)" ,ALC298_FIXUP_SAMSUNG_AMP_V2_4_AMPS ), +SND_PCI_QUIRK (0x144d ,0xc1ca ,"Samsung Galaxy Book3 Pro 360 (NP960QFG)" ,ALC298_FIXUP_SAMSUNG_AMP_V2_4_AMPS ), +SND_PCI_QUIRK (0x144d ,0xc1cc ,"Samsung Galaxy Book3 Ultra (NT960XFH)" ,ALC298_FIXUP_SAMSUNG_AMP_V2_4_AMPS ),SND_PCI_QUIRK (0x1458 ,0xfa53 ,"Gigabyte BXBT-2807" ,ALC283_FIXUP_HEADSET_MIC ),SND_PCI_QUIRK (0x1462 ,0xb120 ,"MSI Cubi MS-B120" ,ALC283_FIXUP_HEADSET_MIC ), SND_PCI_QUIRK(0x1462, 0xb171, "Cubi N 8GL (MS-B171)", ALC283_FIXUP_HEADSET_MIC),
@@ -10790,6 +10924,8 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {SND_PCI_QUIRK (0x1849 ,0xa233 ,"Positivo Master C6300" ,ALC269_FIXUP_HEADSET_MIC ),SND_PCI_QUIRK (0x1854 ,0x0440 ,"LG CQ6" ,ALC256_FIXUP_HEADPHONE_AMP_VOL ),SND_PCI_QUIRK (0x1854 ,0x0441 ,"LG CQ6 AIO" ,ALC256_FIXUP_HEADPHONE_AMP_VOL ), +SND_PCI_QUIRK (0x1854 ,0x0488 ,"LG gram 16 (16Z90R)" ,ALC298_FIXUP_SAMSUNG_AMP_V2_4_AMPS ), +SND_PCI_QUIRK (0x1854 ,0x048a ,"LG gram 17 (17ZD90R)" ,ALC298_FIXUP_SAMSUNG_AMP_V2_4_AMPS ),SND_PCI_QUIRK (0x19e5 ,0x3204 ,"Huawei MACH-WX9" ,ALC256_FIXUP_HUAWEI_MACH_WX9_PINS ),SND_PCI_QUIRK (0x19e5 ,0x320f ,"Huawei WRT-WX9 " ,ALC256_FIXUP_ASUS_MIC_NO_PRESENCE ), SND_PCI_QUIRK(0x1b35, 0x1235, "CZC B20", ALC269_FIXUP_CZC_B20),
@@ -11000,7 +11136,8 @@ static const struct hda_model_fixup alc269_fixup_models[] = { {.id = ALC298_FIXUP_HUAWEI_MBX_STEREO, .name = "huawei-mbx-stereo"}, {.id = ALC256_FIXUP_MEDION_HEADSET_NO_PRESENCE, .name = "alc256-medion-headset"}, {.id = ALC298_FIXUP_SAMSUNG_AMP, .name = "alc298-samsung-amp"}, - {.id = ALC298_FIXUP_SAMSUNG_AMP2, .name = "alc298-samsung-amp2"}, + {.id = ALC298_FIXUP_SAMSUNG_AMP_V2_2_AMPS, .name = "alc298-samsung-amp-v2-2-amps"}, + {.id = ALC298_FIXUP_SAMSUNG_AMP_V2_4_AMPS, .name = "alc298-samsung-amp-v2-4-amps"}, {.id = ALC256_FIXUP_SAMSUNG_HEADPHONE_VERY_QUIET, .name = "alc256-samsung-headphone"}, {.id = ALC255_FIXUP_XIAOMI_HEADSET_MIC, .name = "alc255-xiaomi-headset"}, {.id = ALC274_FIXUP_HP_MIC, .name = "alc274-hp-mic-detect"},
sound/pci/hda/samsung_helper.c deleted +0 -310
310 lines not on this page · raw message
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 174/558 ALSA: usb-audio: Add logitech Audio profile quirk
In reply to Greg Kroah-Hartman6.11-stable review patch. If anyone has any objections, please let me know.
------------------
From: Joshua Pius <[email protected]>
[ Upstream commit a51c925c11d7b855167e64b63eb4378e5adfc11d ]
Specify shortnames for the following Logitech Devices: Rally bar, Rally bar mini, Tap, MeetUp and Huddle.
--- sound/usb/card.c | 6 ++++++ 1 file changed, 6 insertions(+)
sound/usb/card.c +6 -0
@@ -384,6 +384,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"),
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 175/558 ASoC: codecs: wsa883x: Handle reading version failure
In reply to Greg Kroah-Hartman6.11-stable review patch. If anyone has any objections, please let me know.
------------------
From: Krzysztof Kozlowski <[email protected]>
[ 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.
--- sound/soc/codecs/wsa883x.c | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-)
sound/soc/codecs/wsa883x.c +11 -5
@@ -997,15 +997,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) {
@@ -1040,6 +1044,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,
@@ -1048,7 +1054,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 ; }
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 176/558 ALSA: control: Take power_ref lock primarily
In reply to Greg Kroah-Hartman6.11-stable review patch. If anyone has any objections, please let me know.
------------------
From: Takashi Iwai <[email protected]>
[ Upstream commit fcc62b19104a67b9a2941513771e09389b75bd95 ]
The code path for kcontrol accesses have often nested locks of both card's controls_rwsem and power_ref, and applies in that order. However, what could take much longer is the latter, power_ref; it waits for the power state of the device, and it pretty much depends on the user's action.
This patch swaps the locking order of those locks to a more natural way, namely, power_ref -> controls_rwsem, in order to shorten the time of possible nested locks. For consistency, power_ref is taken always in the top-level caller side (that is, *_user() functions and the ioctl handler itself).
--- sound/core/control.c | 54 ++++++++++++++++++++++++++++---------------- 1 file changed, 34 insertions(+), 20 deletions(-)
sound/core/control.c +34 -20
@@ -1167,9 +1167,7 @@ static int __snd_ctl_elem_info(struct snd_card *card,#ifdef CONFIG_SND_DEBUG info->access =0 ;#endif - result =snd_power_ref_and_wait (card); -if (!result) - result = kctl->info (kctl, info); + result = kctl->info (kctl, info);snd_power_unref (card);if (result >=0 ) {snd_BUG_ON (info->access);
@@ -1208,12 +1206,17 @@ static int snd_ctl_elem_info(struct snd_ctl_file *ctl,static int snd_ctl_elem_info_user (struct snd_ctl_file *ctl,struct snd_ctl_elem_info __user *_info) { +struct snd_card *card = ctl->card;struct snd_ctl_elem_info info;int result;if (copy_from_user (&info, _info,sizeof (info)))return -EFAULT ; + result =snd_power_ref_and_wait (card); +if (result) +return result; result =snd_ctl_elem_info (ctl, &info); +snd_power_unref (card);if (result <0 )return result;/* drop internal access flags */
@@ -1257,10 +1260,7 @@ static int snd_ctl_elem_read(struct snd_card *card,if (!snd_ctl_skip_validation (&info))fill_remaining_elem_value (control, &info, pattern); - ret =snd_power_ref_and_wait (card); -if (!ret) - ret = kctl->get (kctl, control); -snd_power_unref (card); + ret = kctl->get (kctl, control);if (ret <0 )return ret; if (!snd_ctl_skip_validation(&info) &&
@@ -1285,7 +1285,11 @@ static int snd_ctl_elem_read_user(struct snd_card *card,if (IS_ERR (control))return PTR_ERR (no_free_ptr (control)); + result =snd_power_ref_and_wait (card); +if (result) +return result; result =snd_ctl_elem_read (card, control); +snd_power_unref (card);if (result <0 )return result;
@@ -1300,7 +1304,7 @@ static int snd_ctl_elem_write(struct snd_card *card, struct snd_ctl_file *file,struct snd_kcontrol *kctl;struct snd_kcontrol_volatile *vd;unsigned int index_offset; -int result; +int result =0 ;down_write (&card->controls_rwsem); kctl =snd_ctl_find_id_locked (card, &control->id);
@@ -1318,9 +1322,8 @@ static int snd_ctl_elem_write(struct snd_card *card, struct snd_ctl_file *file, }snd_ctl_build_ioff (&control->id, kctl, index_offset); - result =snd_power_ref_and_wait (card);/* validate input values */ -if (IS_ENABLED (CONFIG_SND_CTL_INPUT_VALIDATION ) && !result) { +if (IS_ENABLED (CONFIG_SND_CTL_INPUT_VALIDATION )) {struct snd_ctl_elem_info info;memset (&info,0 ,sizeof (info));
@@ -1332,7 +1335,6 @@ static int snd_ctl_elem_write(struct snd_card *card, struct snd_ctl_file *file, }if (!result) result = kctl->put (kctl, control); -snd_power_unref (card);if (result <0 ) {up_write (&card->controls_rwsem);return result;
@@ -1361,7 +1363,11 @@ static int snd_ctl_elem_write_user(struct snd_ctl_file *file,return PTR_ERR (no_free_ptr (control)); card = file->card; + result =snd_power_ref_and_wait (card); +if (result <0 ) +return result; result =snd_ctl_elem_write (card, file, control); +snd_power_unref (card);if (result <0 )return result;
@@ -1830,7 +1836,7 @@ static int call_tlv_handler(struct snd_ctl_file *file, int op_flag, {SNDRV_CTL_TLV_OP_CMD, SNDRV_CTL_ELEM_ACCESS_TLV_COMMAND}, };struct snd_kcontrol_volatile *vd = &kctl->vd[snd_ctl_get_ioff (kctl, id)]; -int i, ret; +int i;/* Check support of the request for this element. */ for (i =0 ; i <ARRAY_SIZE (pairs); ++i) {
@@ -1848,11 +1854,7 @@ static int call_tlv_handler(struct snd_ctl_file *file, int op_flag, vd->owner != NULL && vd->owner != file)return -EPERM ; - ret =snd_power_ref_and_wait (file->card); -if (!ret) - ret = kctl->tlv.c (kctl, op_flag, size, buf); -snd_power_unref (file->card); -return ret; +return kctl->tlv.c (kctl, op_flag, size, buf); } static int read_tlv_buf(struct snd_kcontrol *kctl, struct snd_ctl_elem_id *id,
@@ -1965,16 +1967,28 @@ static long snd_ctl_ioctl(struct file *file, unsigned int cmd, unsigned long argcase SNDRV_CTL_IOCTL_SUBSCRIBE_EVENTS :return snd_ctl_subscribe_events (ctl, ip);case SNDRV_CTL_IOCTL_TLV_READ : -scoped_guard (rwsem_read, &ctl->card->controls_rwsem) + err =snd_power_ref_and_wait (card); +if (err <0 ) +return err; +scoped_guard (rwsem_read, &card->controls_rwsem) err = snd_ctl_tlv_ioctl(ctl, argp, SNDRV_CTL_TLV_OP_READ); +snd_power_unref (card);return err;case SNDRV_CTL_IOCTL_TLV_WRITE : -scoped_guard (rwsem_write, &ctl->card->controls_rwsem) + err =snd_power_ref_and_wait (card); +if (err <0 ) +return err; +scoped_guard (rwsem_write, &card->controls_rwsem) err = snd_ctl_tlv_ioctl(ctl, argp, SNDRV_CTL_TLV_OP_WRITE); +snd_power_unref (card);return err;case SNDRV_CTL_IOCTL_TLV_COMMAND : -scoped_guard (rwsem_write, &ctl->card->controls_rwsem) + err =snd_power_ref_and_wait (card); +if (err <0 ) +return err; +scoped_guard (rwsem_write, &card->controls_rwsem) err = snd_ctl_tlv_ioctl(ctl, argp, SNDRV_CTL_TLV_OP_CMD); +snd_power_unref (card);return err;case SNDRV_CTL_IOCTL_POWER :return -ENOPROTOOPT ;
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 177/558 tools/x86/kcpuid: Protect against faulty "max subleaf" values
In reply to Greg Kroah-Hartman6.11-stable review patch. If anyone has any objections, please let me know.
------------------
From: Ahmed S. Darwish <[email protected]>
[ 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.
--- tools/arch/x86/kcpuid/kcpuid.c | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-)
tools/arch/x86/kcpuid/kcpuid.c +5 -7
@@ -7,7 +7,8 @@#include <string.h> #include <getopt.h> -#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 ;
@@ -207,12 +208,9 @@ static void raw_dump_range(struct cpuid_range *range)#define MAX_SUBLEAF_NUM 32struct 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;
@@ -258,7 +256,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 ;
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 178/558 x86/pkeys: Add PKRU as a parameter in signal handling functions
In reply to Greg Kroah-Hartman6.11-stable review patch. If anyone has any objections, please let me know.
------------------
From: Aruna Ramakrishna <[email protected]>
[ Upstream commit 24cf2bc982ffe02aeffb4a3885c71751a2c7023b ]
Assume there's a multithreaded application that runs untrusted user code. Each thread has its stack/code protected by a non-zero PKEY, and the PKRU register is set up such that only that particular non-zero PKEY is enabled. Each thread also sets up an alternate signal stack to handle signals, which is protected by PKEY zero. The PKEYs man page documents that the PKRU will be reset to init_pkru when the signal handler is invoked, which means that PKEY zero access will be enabled. But this reset happens after the kernel attempts to push fpu state to the alternate stack, which is not (yet) accessible by the kernel, which leads to a new SIGSEGV being sent to the application, terminating it.
Enabling both the non-zero PKEY (for the thread) and PKEY zero in userspace will not work for this use case. It cannot have the alt stack writeable by all - the rationale here is that the code running in that thread (using a non-zero PKEY) is untrusted and should not have access to the alternate signal stack (that uses PKEY zero), to prevent the return address of a function from being changed. The expectation is that kernel should be able to set up the alternate signal stack and deliver the signal to the application even if PKEY zero is explicitly disabled by the application. The signal handler accessibility should not be dictated by whatever PKRU value the thread sets up.
The PKRU register is managed by XSAVE, which means the sigframe contents must match the register contents - which is not the case here. It's required that the signal frame contains the user-defined PKRU value (so that it is restored correctly from sigcontext) but the actual register must be reset to init_pkru so that the alt stack is accessible and the signal can be delivered to the application. It seems that the proper fix here would be to remove PKRU from the XSAVE framework and manage it separately, which is quite complicated. As a workaround, do this:
orig_pkru = rdpkru();
wrpkru(orig_pkru & init_pkru_value);
xsave_to_user_sigframe();
put_user(pkru_sigframe_addr, orig_pkru)In preparation for writing PKRU to sigframe, pass PKRU as an additional parameter down the call chain from get_sigframe().
No functional change.
--- arch/x86/include/asm/fpu/signal.h | 2 +- arch/x86/kernel/fpu/signal.c | 6 +++--- arch/x86/kernel/signal.c | 3 ++- 3 files changed, 6 insertions(+), 5 deletions(-)
arch/x86/include/asm/fpu/signal.h +1 -1
@@ -29,7 +29,7 @@ fpu__alloc_mathframe(unsigned long sp, int ia32_frame,unsigned long fpu__get_fpstate_size (void ); -extern bool copy_fpstate_to_sigframe (void __user *buf,void __user *fp,int size); +extern bool copy_fpstate_to_sigframe (void __user *buf,void __user *fp,int size,u32 pkru);extern void fpu__clear_user_states (struct fpu *fpu);extern bool fpu__restore_sig (void __user *buf,int ia32_frame);
arch/x86/kernel/fpu/signal.c +3 -3
@@ -156,7 +156,7 @@ static inline bool save_xstate_epilog(void __user *buf, int ia32_frame,return !err; } -static inline int copy_fpregs_to_sigframe (struct xregs_state __user *buf) +static inline int copy_fpregs_to_sigframe (struct xregs_state __user *buf,u32 pkru) {if (use_xsave ())return xsave_to_user_sigframe (buf);
@@ -185,7 +185,7 @@ static inline int copy_fpregs_to_sigframe(struct xregs_state __user *buf)* For [f]xsave state, update the SW reserved fields in the [f]xsave frame * indicating the absence/presence of the extended state to the user. */ -bool copy_fpstate_to_sigframe (void __user *buf,void __user *buf_fx,int size) +bool copy_fpstate_to_sigframe (void __user *buf,void __user *buf_fx,int size,u32 pkru) {struct task_struct *tsk = current;struct fpstate *fpstate = tsk->thread.fpu.fpstate;
@@ -228,7 +228,7 @@ bool copy_fpstate_to_sigframe(void __user *buf, void __user *buf_fx, int size)fpregs_restore_userregs ();pagefault_disable (); - ret =copy_fpregs_to_sigframe (buf_fx); + ret =copy_fpregs_to_sigframe (buf_fx, pkru);pagefault_enable ();fpregs_unlock ();
arch/x86/kernel/signal.c +2 -1
@@ -84,6 +84,7 @@ get_sigframe(struct ksignal *ksig, struct pt_regs *regs, size_t frame_size,unsigned long math_size =0 ;unsigned long sp = regs->sp;unsigned long buf_fx =0 ; +u32 pkru =read_pkru ();/* redzone */ if (!ia32_frame)
@@ -139,7 +140,7 @@ get_sigframe(struct ksignal *ksig, struct pt_regs *regs, size_t frame_size, }/* save i387 and extended state */ -if (!copy_fpstate_to_sigframe (*fpstate, (void __user *)buf_fx, math_size)) +if (!copy_fpstate_to_sigframe (*fpstate, (void __user *)buf_fx, math_size, pkru))return (void __user *)-1L ;return (void __user *)sp;
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 179/558 x86/pkeys: Restore altstack access in sigreturn()
In reply to Greg Kroah-Hartman6.11-stable review patch. If anyone has any objections, please let me know.
------------------
From: Aruna Ramakrishna <[email protected]>
[ Upstream commit d10b554919d4cc8fa8fe2e95b57ad2624728c8e4 ]
A process can disable access to the alternate signal stack by not enabling the altstack's PKEY in the PKRU register.
Nevertheless, the kernel updates the PKRU temporarily for signal handling. However, in sigreturn(), restore_sigcontext() will restore the PKRU to the user-defined PKRU value.
This will cause restore_altstack() to fail with a SIGSEGV as it needs read access to the altstack which is prohibited by the user-defined PKRU value.
Fix this by restoring altstack before restoring PKRU.
--- arch/x86/kernel/signal_64.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-)
arch/x86/kernel/signal_64.c +3 -3
@@ -260,13 +260,13 @@ SYSCALL_DEFINE0(rt_sigreturn)set_current_blocked (&set); -if (!restore_sigcontext (regs, &frame->uc.uc_mcontext, uc_flags)) +if (restore_altstack (&frame->uc.uc_stack)) goto badframe; -if (restore_signal_shadow_stack ()) +if (!restore_sigcontext (regs, &frame->uc.uc_mcontext, uc_flags)) goto badframe; -if (restore_altstack (&frame->uc.uc_stack)) +if (restore_signal_shadow_stack ()) goto badframe;return regs->ax;
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 180/558 x86/kexec: Add EFI config table identity mapping for kexec kernel
In reply to Greg Kroah-Hartman6.11-stable review patch. If anyone has any objections, please let me know.
------------------
From: Tao Liu <[email protected]>
[ 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.
--- arch/x86/kernel/machine_kexec_64.c | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+)
arch/x86/kernel/machine_kexec_64.c +27 -0
@@ -28,6 +28,7 @@#include <asm/setup.h> #include <asm/set_memory.h> #include <asm/cpu.h> +#include <asm/efi.h> #ifdef CONFIG_ACPI /*
@@ -87,6 +88,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 ;
@@ -102,6 +105,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 ;
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 181/558 x86/mm/ident_map: Use gbpages only where full GB page should be mapped.
In reply to Greg Kroah-Hartman6.11-stable review patch. If anyone has any objections, please let me know.
------------------
From: Steve Wahl <[email protected]>
[ Upstream commit cc31744a294584a36bf764a0ffa3255a8e69f036 ]
When ident_pud_init() uses only GB pages to create identity maps, large ranges of addresses not actually requested can be included in the resulting table; a 4K request will map a full GB. This can include a lot of extra address space past that requested, including areas marked reserved by the BIOS. That allows processor speculation into reserved regions, that on UV systems can cause system halts.
Only use GB pages when map creation requests include the full GB page of space. Fall back to using smaller 2M pages when only portions of a GB page are included in the request.
No attempt is made to coalesce mapping requests. If a request requires a map entry at the 2M (pmd) level, subsequent mapping requests within the same 1G region will also be at the pmd level, even if adjacent or overlapping such requests could have been combined to map a full GB page. Existing usage starts with larger regions and then adds smaller regions, so this should not have any great consequence.
--- arch/x86/mm/ident_map.c | 23 ++++++++++++++++++----- 1 file changed, 18 insertions(+), 5 deletions(-)
arch/x86/mm/ident_map.c +18 -5
@@ -99,18 +99,31 @@ static int ident_pud_init(struct x86_mapping_info *info, pud_t *pud_page,for (; addr < end; addr = next) {pud_t *pud = pud_page +pud_index (addr);pmd_t *pmd; +bool use_gbpage; next = (addr &PUD_MASK ) +PUD_SIZE ;if (next > end) next = end; -if (info->direct_gbpages) { -pud_t pudval; +/* if this is already a gbpage, this portion is already mapped */ +if (pud_leaf (*pud)) +continue ; + +/* Is using a gbpage allowed? */ + use_gbpage = info->direct_gbpages; -if (pud_present (*pud)) -continue ; +/* Don't use gbpage if it maps more than the requested region. */ +/* at the begining: */ + use_gbpage &= ((addr & ~PUD_MASK ) ==0 ); +/* ... or at the end: */ + use_gbpage &= ((next & ~PUD_MASK ) ==0 ); + +/* Never overwrite existing mappings */ + use_gbpage &= !pud_present (*pud); + +if (use_gbpage) { +pud_t pudval; - addr &=PUD_MASK ; pudval =__pud ((addr - info->offset) | info->page_flag);set_pud (pud, pudval);continue ;
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 182/558 ALSA: asihpi: Fix potential OOB array access
In reply to Greg Kroah-Hartman6.11-stable review patch. If anyone has any objections, please let me know.
------------------
From: Takashi Iwai <[email protected]>
[ 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.
--- sound/pci/asihpi/hpimsgx.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
sound/pci/asihpi/hpimsgx.c +1 -1
@@ -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;
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 183/558 ALSA: hdsp: Break infinite MIDI input flush loop
In reply to Greg Kroah-Hartman6.11-stable review patch. If anyone has any objections, please let me know.
------------------
From: Takashi Iwai <[email protected]>
[ 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.
--- sound/pci/rme9652/hdsp.c | 6 ++++-- sound/pci/rme9652/hdspm.c | 6 ++++-- 2 files changed, 8 insertions(+), 4 deletions(-)
sound/pci/rme9652/hdsp.c +4 -2
@@ -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)
sound/pci/rme9652/hdspm.c +4 -2
@@ -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)
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 184/558 tools/nolibc: powerpc: limit stack-protector workaround to GCC
In reply to Greg Kroah-Hartman6.11-stable review patch. If anyone has any objections, please let me know.
------------------
From: Thomas Weißschuh <[email protected]>
[ Upstream commit 1daea158d0aae0770371f3079305a29fdb66829e ]
As mentioned in the comment, the workaround for __attribute__((no_stack_protector)) is only necessary on GCC. Avoid applying the workaround on clang, as clang does not recognize __attribute__((__optimize__)) and would fail.
--- tools/include/nolibc/arch-powerpc.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
tools/include/nolibc/arch-powerpc.h +1 -1
@@ -172,7 +172,7 @@ _ret; \ }) -#ifndef __powerpc64__ +#if !defined(__powerpc64__) && !defined(__clang__)/* FIXME: For 32-bit PowerPC, with newer gcc compilers (e.g. gcc 13.1.0), * "omit-frame-pointer" fails with __attribute__((no_stack_protector)) but * works with __attribute__((__optimize__("-fno-stack-protector")))
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 185/558 selftests/nolibc: avoid passing NULL to printf("%s")
In reply to Greg Kroah-Hartman6.11-stable review patch. If anyone has any objections, please let me know.
------------------
From: Thomas Weißschuh <[email protected]>
[ 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.
--- tools/testing/selftests/nolibc/nolibc-test.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
tools/testing/selftests/nolibc/nolibc-test.c +2 -2
@@ -542,7 +542,7 @@ 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 ;result (llen,FAIL );
@@ -561,7 +561,7 @@ 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 ;result (llen,FAIL );
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 186/558 x86/syscall: Avoid memcpy() for ia32 syscall_get_arguments()
In reply to Greg Kroah-Hartman6.11-stable review patch. If anyone has any objections, please let me know.
------------------
From: Kees Cook <[email protected]>
[ 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
--- arch/x86/include/asm/syscall.h | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-)
arch/x86/include/asm/syscall.h +6 -1
@@ -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)
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 187/558 ASoC: Intel: boards: always check the result of acpi_dev_get_first_match_dev()
In reply to Greg Kroah-Hartman6.11-stable review patch. If anyone has any objections, please let me know.
------------------
From: Pierre-Louis Bossart <[email protected]>
[ Upstream commit 14e91ddd5c02d8c3e5a682ebfa0546352b459911 ]
The code seems mostly copy-pasted, with some machine drivers forgetting to test if the 'adev' result is NULL.
Add this check when missing, and use -ENOENT consistently as an error code.
--- sound/soc/intel/boards/bytcht_cx2072x.c | 4 ++++ sound/soc/intel/boards/bytcht_da7213.c | 4 ++++ sound/soc/intel/boards/bytcht_es8316.c | 2 +- sound/soc/intel/boards/bytcr_rt5640.c | 2 +- sound/soc/intel/boards/bytcr_rt5651.c | 2 +- sound/soc/intel/boards/cht_bsw_rt5645.c | 4 ++++ sound/soc/intel/boards/cht_bsw_rt5672.c | 4 ++++ sound/soc/intel/boards/sof_es8336.c | 2 +- sound/soc/intel/boards/sof_wm8804.c | 4 ++++ 9 files changed, 24 insertions(+), 4 deletions(-)
sound/soc/intel/boards/bytcht_cx2072x.c +4 -0
@@ -255,7 +255,11 @@ static int snd_byt_cht_cx2072x_probe(struct platform_device *pdev)snprintf (codec_name,sizeof (codec_name),"i2c-%s" ,acpi_dev_name (adev)); byt_cht_cx2072x_dais[dai_index].codecs->name = codec_name; + }else { +dev_err (&pdev->dev,"Error cannot find '%s' dev\n" , mach->id); +return -ENOENT ; } +acpi_dev_put (adev);/* override platform name, if required */
sound/soc/intel/boards/bytcht_da7213.c +4 -0
@@ -258,7 +258,11 @@ static int bytcht_da7213_probe(struct platform_device *pdev)snprintf (codec_name,sizeof (codec_name),"i2c-%s" ,acpi_dev_name (adev)); dailink[dai_index].codecs->name = codec_name; + }else { +dev_err (&pdev->dev,"Error cannot find '%s' dev\n" , mach->id); +return -ENOENT ; } +acpi_dev_put (adev);/* override platform name, if required */
sound/soc/intel/boards/bytcht_es8316.c +1 -1
@@ -562,7 +562,7 @@ static int snd_byt_cht_es8316_mc_probe(struct platform_device *pdev) byt_cht_es8316_dais[dai_index].codecs->name = codec_name; }else {dev_err (dev,"Error cannot find '%s' dev\n" , mach->id); -return -ENXIO ; +return -ENOENT ; } codec_dev =acpi_get_first_physical_node (adev);
sound/soc/intel/boards/bytcr_rt5640.c +1 -1
@@ -1693,7 +1693,7 @@ static int snd_byt_rt5640_mc_probe(struct platform_device *pdev) byt_rt5640_dais[dai_index].codecs->name = byt_rt5640_codec_name; }else {dev_err (dev,"Error cannot find '%s' dev\n" , mach->id); -return -ENXIO ; +return -ENOENT ; } codec_dev =acpi_get_first_physical_node (adev);
sound/soc/intel/boards/bytcr_rt5651.c +1 -1
@@ -926,7 +926,7 @@ static int snd_byt_rt5651_mc_probe(struct platform_device *pdev) byt_rt5651_dais[dai_index].codecs->name = byt_rt5651_codec_name; }else {dev_err (dev,"Error cannot find '%s' dev\n" , mach->id); -return -ENXIO ; +return -ENOENT ; } codec_dev =acpi_get_first_physical_node (adev);
sound/soc/intel/boards/cht_bsw_rt5645.c +4 -0
@@ -582,7 +582,11 @@ static int snd_cht_mc_probe(struct platform_device *pdev)snprintf (cht_rt5645_codec_name,sizeof (cht_rt5645_codec_name),"i2c-%s" ,acpi_dev_name (adev)); cht_dailink[dai_index].codecs->name = cht_rt5645_codec_name; + }else { +dev_err (&pdev->dev,"Error cannot find '%s' dev\n" , mach->id); +return -ENOENT ; } +/* acpi_get_first_physical_node() returns a borrowed ref, no need to deref */ codec_dev =acpi_get_first_physical_node (adev);acpi_dev_put (adev);
sound/soc/intel/boards/cht_bsw_rt5672.c +4 -0
@@ -479,7 +479,11 @@ static int snd_cht_mc_probe(struct platform_device *pdev)snprintf (drv->codec_name,sizeof (drv->codec_name),"i2c-%s" ,acpi_dev_name (adev)); cht_dailink[dai_index].codecs->name = drv->codec_name; + }else { +dev_err (&pdev->dev,"Error cannot find '%s' dev\n" , mach->id); +return -ENOENT ; } +acpi_dev_put (adev);/* Use SSP0 on Bay Trail CR devices */
sound/soc/intel/boards/sof_es8336.c +1 -1
@@ -681,7 +681,7 @@ static int sof_es8336_probe(struct platform_device *pdev) dai_links[0 ].codecs->dai_name ="ES8326 HiFi" ; }else {dev_err (dev,"Error cannot find '%s' dev\n" , mach->id); -return -ENXIO ; +return -ENOENT ; } codec_dev =acpi_get_first_physical_node (adev);
sound/soc/intel/boards/sof_wm8804.c +4 -0
@@ -270,7 +270,11 @@ static int sof_wm8804_probe(struct platform_device *pdev)snprintf (codec_name,sizeof (codec_name),"%s%s" ,"i2c-" ,acpi_dev_name (adev)); dailink[dai_index].codecs->name = codec_name; + }else { +dev_err (&pdev->dev,"Error cannot find '%s' dev\n" , mach->id); +return -ENOENT ; } +acpi_dev_put (adev);snd_soc_card_set_drvdata (card, ctx);
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 188/558 rcu-tasks: Fix access non-existent percpu rtpcp variable in rcu_tasks_need_gpcb()
In reply to Greg Kroah-Hartman6.11-stable review patch. If anyone has any objections, please let me know.
------------------
From: Zqiang <[email protected]>
[ Upstream commit fd70e9f1d85f5323096ad313ba73f5fe3d15ea41 ]
For kernels built with CONFIG_FORCE_NR_CPUS=y, the nr_cpu_ids is defined as NR_CPUS instead of the number of possible cpus, this will cause the following system panic:
smpboot: Allowing 4 CPUs, 0 hotplug CPUs
...setup_percpu: NR_CPUS:512 nr_cpumask_bits:512 nr_cpu_ids:512 nr_node_ids:1
...
BUG: unable to handle page fault for address: ffffffff9911c8c8 Oops: 0000 [#1] PREEMPT SMP PTI CPU: 0 PID: 15 Comm: rcu_tasks_trace Tainted: G W 6.6.21 #1 5dc7acf91a5e8e9ac9dcfc35bee0245691283ea6 RIP: 0010:rcu_tasks_need_gpcb+0x25d/0x2c0 RSP: 0018:ffffa371c00a3e60 EFLAGS: 00010082 CR2: ffffffff9911c8c8 CR3: 000000040fa20005 CR4: 00000000001706f0 Call Trace: <TASK> ? __die+0x23/0x80 ? page_fault_oops+0xa4/0x180 ? exc_page_fault+0x152/0x180 ? asm_exc_page_fault+0x26/0x40 ? rcu_tasks_need_gpcb+0x25d/0x2c0 ? __pfx_rcu_tasks_kthread+0x40/0x40 rcu_tasks_one_gp+0x69/0x180 rcu_tasks_kthread+0x94/0xc0 kthread+0xe8/0x140 ? __pfx_kthread+0x40/0x40 ret_from_fork+0x34/0x80 ? __pfx_kthread+0x40/0x40 ret_from_fork_asm+0x1b/0x80 </TASK>
Considering that there may be holes in the CPU numbers, use the maximum possible cpu number, instead of nr_cpu_ids, for configuring enqueue and dequeue limits.
[ neeraj.upadhyay: Fix htmldocs build error reported by Stephen Rothwell ]
--- kernel/rcu/tasks.h | 82 ++++++++++++++++++++++++++++++---------------- 1 file changed, 53 insertions(+), 29 deletions(-)
kernel/rcu/tasks.h +53 -29
@@ -34,6 +34,7 @@ typedef void (*postgp_func_t)(struct rcu_tasks *rtp);* @rtp_blkd_tasks: List of tasks blocked as readers. * @rtp_exit_list: List of tasks in the latter portion of do_exit(). * @cpu: CPU number corresponding to this entry. +* @index: Index of this CPU in rtpcp_array of the rcu_tasks structure. * @rtpp: Pointer to the rcu_tasks structure. */ struct rcu_tasks_percpu {
@@ -49,6 +50,7 @@ struct rcu_tasks_percpu {struct list_head rtp_blkd_tasks;struct list_head rtp_exit_list;int cpu; +int index;struct rcu_tasks *rtpp; };
@@ -76,6 +78,7 @@ struct rcu_tasks_percpu {* @call_func: This flavor's call_rcu()-equivalent function. * @wait_state: Task state for synchronous grace-period waits (default TASK_UNINTERRUPTIBLE). * @rtpcpu: This flavor's rcu_tasks_percpu structure. +* @rtpcp_array: Array of pointers to rcu_tasks_percpu structure of CPUs in cpu_possible_mask. * @percpu_enqueue_shift: Shift down CPU ID this much when enqueuing callbacks. * @percpu_enqueue_lim: Number of per-CPU callback queues in use for enqueuing. * @percpu_dequeue_lim: Number of per-CPU callback queues in use for dequeuing.
@@ -110,6 +113,7 @@ struct rcu_tasks {call_rcu_func_t call_func;unsigned int wait_state;struct rcu_tasks_percpu __percpu *rtpcpu; +struct rcu_tasks_percpu **rtpcp_array;int percpu_enqueue_shift;int percpu_enqueue_lim;int percpu_dequeue_lim;
@@ -182,6 +186,8 @@ module_param(rcu_task_collapse_lim, int, 0444);static int rcu_task_lazy_lim__read_mostly =32 ;module_param (rcu_task_lazy_lim, int,0444 ); +static int rcu_task_cpu_ids; +/* RCU tasks grace-period state for debugging. */ #define RTGS_INIT 0#define RTGS_WAIT_WAIT_CBS 1
@@ -245,6 +251,8 @@ static void cblist_init_generic(struct rcu_tasks *rtp)int cpu;int lim;int shift; +int maxcpu; +int index =0 ;if (rcu_task_enqueue_lim <0 ) { rcu_task_enqueue_lim =1 ;
@@ -254,14 +262,9 @@ static void cblist_init_generic(struct rcu_tasks *rtp) } lim = rcu_task_enqueue_lim; -if (lim > nr_cpu_ids) - lim = nr_cpu_ids; - shift =ilog2 (nr_cpu_ids / lim); -if (((nr_cpu_ids -1 ) >> shift) >= lim) - shift++; -WRITE_ONCE (rtp->percpu_enqueue_shift, shift); -WRITE_ONCE (rtp->percpu_dequeue_lim, lim); -smp_store_release (&rtp->percpu_enqueue_lim, lim); + rtp->rtpcp_array =kcalloc (num_possible_cpus (),sizeof (struct rcu_tasks_percpu *),GFP_KERNEL ); +BUG_ON (!rtp->rtpcp_array); +for_each_possible_cpu (cpu) {struct rcu_tasks_percpu *rtpcp =per_cpu_ptr (rtp->rtpcpu, cpu);
@@ -273,14 +276,29 @@ static void cblist_init_generic(struct rcu_tasks *rtp)INIT_WORK (&rtpcp->rtp_work, rcu_tasks_invoke_cbs_wq); rtpcp->cpu = cpu; rtpcp->rtpp = rtp; + rtpcp->index = index; + rtp->rtpcp_array[index] = rtpcp; + index++;if (!rtpcp->rtp_blkd_tasks.next)INIT_LIST_HEAD (&rtpcp->rtp_blkd_tasks);if (!rtpcp->rtp_exit_list.next)INIT_LIST_HEAD (&rtpcp->rtp_exit_list); + maxcpu = cpu; } -pr_info ("%s: Setting shift to %d and lim to %d rcu_task_cb_adjust=%d.\n" , rtp->name, -data_race (rtp->percpu_enqueue_shift),data_race (rtp->percpu_enqueue_lim), rcu_task_cb_adjust); + rcu_task_cpu_ids = maxcpu +1 ; +if (lim > rcu_task_cpu_ids) + lim = rcu_task_cpu_ids; + shift =ilog2 (rcu_task_cpu_ids / lim); +if (((rcu_task_cpu_ids -1 ) >> shift) >= lim) + shift++; +WRITE_ONCE (rtp->percpu_enqueue_shift, shift); +WRITE_ONCE (rtp->percpu_dequeue_lim, lim); +smp_store_release (&rtp->percpu_enqueue_lim, lim); + +pr_info ("%s: Setting shift to %d and lim to %d rcu_task_cb_adjust=%d rcu_task_cpu_ids=%d.\n" , + rtp->name,data_race (rtp->percpu_enqueue_shift),data_race (rtp->percpu_enqueue_lim), + rcu_task_cb_adjust, rcu_task_cpu_ids); }// Compute wakeup time for lazy callback timer.
@@ -348,7 +366,7 @@ static void call_rcu_tasks_generic(struct rcu_head *rhp, rcu_callback_t func, rtpcp->rtp_n_lock_retries =0 ; }if (rcu_task_cb_adjust && ++rtpcp->rtp_n_lock_retries > rcu_task_contend_lim && -READ_ONCE (rtp->percpu_enqueue_lim) != nr_cpu_ids) +READ_ONCE (rtp->percpu_enqueue_lim) != rcu_task_cpu_ids) needadjust = true;// Defer adjustment to avoid deadlock. }// Queuing callbacks before initialization not yet supported.
@@ -368,10 +386,10 @@ static void call_rcu_tasks_generic(struct rcu_head *rhp, rcu_callback_t func,raw_spin_unlock_irqrestore_rcu_node (rtpcp, flags);if (unlikely (needadjust)) {raw_spin_lock_irqsave (&rtp->cbs_gbl_lock, flags); -if (rtp->percpu_enqueue_lim != nr_cpu_ids) { +if (rtp->percpu_enqueue_lim != rcu_task_cpu_ids) {WRITE_ONCE (rtp->percpu_enqueue_shift,0 ); -WRITE_ONCE (rtp->percpu_dequeue_lim, nr_cpu_ids); -smp_store_release (&rtp->percpu_enqueue_lim, nr_cpu_ids); +WRITE_ONCE (rtp->percpu_dequeue_lim, rcu_task_cpu_ids); +smp_store_release (&rtp->percpu_enqueue_lim, rcu_task_cpu_ids);pr_info ("Switching %s to per-CPU callback queuing.\n" , rtp->name); }raw_spin_unlock_irqrestore (&rtp->cbs_gbl_lock, flags);
@@ -444,6 +462,8 @@ static int rcu_tasks_need_gpcb(struct rcu_tasks *rtp) dequeue_limit =smp_load_acquire (&rtp->percpu_dequeue_lim);for (cpu =0 ; cpu < dequeue_limit; cpu++) { +if (!cpu_possible (cpu)) +continue ;struct rcu_tasks_percpu *rtpcp =per_cpu_ptr (rtp->rtpcpu, cpu);/* Advance and accelerate any new callbacks. */
@@ -481,7 +501,7 @@ static int rcu_tasks_need_gpcb(struct rcu_tasks *rtp)if (rcu_task_cb_adjust && ncbs <= rcu_task_collapse_lim) {raw_spin_lock_irqsave (&rtp->cbs_gbl_lock, flags);if (rtp->percpu_enqueue_lim >1 ) { -WRITE_ONCE (rtp->percpu_enqueue_shift,order_base_2 (nr_cpu_ids)); +WRITE_ONCE (rtp->percpu_enqueue_shift,order_base_2 (rcu_task_cpu_ids));smp_store_release (&rtp->percpu_enqueue_lim,1 ); rtp->percpu_dequeue_gpseq =get_state_synchronize_rcu (); gpdone = false;
@@ -496,7 +516,9 @@ static int rcu_tasks_need_gpcb(struct rcu_tasks *rtp)pr_info ("Completing switch %s to CPU-0 callback queuing.\n" , rtp->name); }if (rtp->percpu_dequeue_lim ==1 ) { -for (cpu = rtp->percpu_dequeue_lim; cpu < nr_cpu_ids; cpu++) { +for (cpu = rtp->percpu_dequeue_lim; cpu < rcu_task_cpu_ids; cpu++) { +if (!cpu_possible (cpu)) +continue ;struct rcu_tasks_percpu *rtpcp =per_cpu_ptr (rtp->rtpcpu, cpu);WARN_ON_ONCE (rcu_segcblist_n_cbs (&rtpcp->cblist));
@@ -511,30 +533,32 @@ static int rcu_tasks_need_gpcb(struct rcu_tasks *rtp)// Advance callbacks and invoke any that are ready. static void rcu_tasks_invoke_cbs (struct rcu_tasks *rtp,struct rcu_tasks_percpu *rtpcp) { -int cpu; -int cpunext;int cpuwq;unsigned long flags;int len; +int index;struct rcu_head *rhp;struct rcu_cblist rcl =RCU_CBLIST_INITIALIZER (rcl);struct rcu_tasks_percpu *rtpcp_next; - cpu = rtpcp->cpu; - cpunext = cpu *2 +1 ; -if (cpunext <smp_load_acquire (&rtp->percpu_dequeue_lim)) { - rtpcp_next =per_cpu_ptr (rtp->rtpcpu, cpunext); - cpuwq =rcu_cpu_beenfullyonline (cpunext) ? cpunext :WORK_CPU_UNBOUND ; -queue_work_on (cpuwq, system_wq, &rtpcp_next->rtp_work); - cpunext++; -if (cpunext <smp_load_acquire (&rtp->percpu_dequeue_lim)) { - rtpcp_next =per_cpu_ptr (rtp->rtpcpu, cpunext); - cpuwq =rcu_cpu_beenfullyonline (cpunext) ? cpunext :WORK_CPU_UNBOUND ; + index = rtpcp->index *2 +1 ; +if (index <num_possible_cpus ()) { + rtpcp_next = rtp->rtpcp_array[index]; +if (rtpcp_next->cpu <smp_load_acquire (&rtp->percpu_dequeue_lim)) { + cpuwq =rcu_cpu_beenfullyonline (rtpcp_next->cpu) ? rtpcp_next->cpu :WORK_CPU_UNBOUND ;queue_work_on (cpuwq, system_wq, &rtpcp_next->rtp_work); + index++; +if (index <num_possible_cpus ()) { + rtpcp_next = rtp->rtpcp_array[index]; +if (rtpcp_next->cpu <smp_load_acquire (&rtp->percpu_dequeue_lim)) { + cpuwq =rcu_cpu_beenfullyonline (rtpcp_next->cpu) ? rtpcp_next->cpu :WORK_CPU_UNBOUND ; +queue_work_on (cpuwq, system_wq, &rtpcp_next->rtp_work); + } + } } } -if (rcu_segcblist_empty (&rtpcp->cblist) || !cpu_possible (cpu)) +if (rcu_segcblist_empty (&rtpcp->cblist))return ;raw_spin_lock_irqsave_rcu_node (rtpcp, flags);rcu_segcblist_advance (&rtpcp->cblist,rcu_seq_current (&rtp->tasks_gp_seq));
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 189/558 hwmon: (nct6775) add G15CF to ASUS WMI monitoring list
In reply to Greg Kroah-Hartman6.11-stable review patch. If anyone has any objections, please let me know.
------------------
From: Denis Pauk <[email protected]>
[ Upstream commit 1f432e4cf1dd3ecfec5ed80051b4611632a0fd51 ]
Boards G15CF has got a nct6775 chip, but by default there's no use of it because of resource conflict with WMI method.
Add the board to the WMI monitoring list.
Message-ID: <[email protected]>
--- drivers/hwmon/nct6775-platform.c | 1 + 1 file changed, 1 insertion(+)
drivers/hwmon/nct6775-platform.c +1 -0
@@ -1269,6 +1269,7 @@ static const char * const asus_msi_boards[] = {"EX-B760M-V5 D4" ,"EX-H510M-V3" ,"EX-H610M-V3 D4" , +"G15CF" ,"PRIME A620M-A" ,"PRIME B560-PLUS" , "PRIME B560-PLUS AC-HES",
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 190/558 fbdev: efifb: Register sysfs groups through driver core
In reply to Greg Kroah-Hartman6.11-stable review patch. If anyone has any objections, please let me know.
------------------
From: Thomas Weißschuh <[email protected]>
[ Upstream commit 95cdd538e0e5677efbdf8aade04ec098ab98f457 ]
The driver core can register and cleanup sysfs groups already. Make use of that functionality to simplify the error handling and cleanup.
Also avoid a UAF race during unregistering where the sysctl attributes were usable after the info struct was freed.
--- drivers/video/fbdev/efifb.c | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-)
drivers/video/fbdev/efifb.c +2 -9
@@ -561,15 +561,10 @@ static int efifb_probe(struct platform_device *dev)break ; } - err =sysfs_create_groups (&dev->dev.kobj, efifb_groups); -if (err) { -pr_err ("efifb: cannot add sysfs attrs\n" ); - goto err_unmap; - } err =fb_alloc_cmap (&info->cmap,256 ,0 );if (err <0 ) {pr_err ("efifb: cannot allocate colormap\n" ); - goto err_groups; + goto err_unmap; } err =devm_aperture_acquire_for_platform_device (dev, par->base, par->size);
@@ -587,8 +582,6 @@ static int efifb_probe(struct platform_device *dev) err_fb_dealloc_cmap:fb_dealloc_cmap (&info->cmap); -err_groups: -sysfs_remove_groups (&dev->dev.kobj, efifb_groups); err_unmap:if (mem_flags & (EFI_MEMORY_UC |EFI_MEMORY_WC ))iounmap (info->screen_base);
@@ -608,12 +601,12 @@ static void efifb_remove(struct platform_device *pdev)/* efifb_destroy takes care of info cleanup */ unregister_framebuffer (info); -sysfs_remove_groups (&pdev->dev.kobj, efifb_groups); }static struct platform_driver efifb_driver = { .driver = { .name ="efi-framebuffer" , + .dev_groups = efifb_groups, }, .probe = efifb_probe, .remove_new = efifb_remove,
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 191/558 fbdev: pxafb: Fix possible use after free in pxafb_task()
In reply to Greg Kroah-Hartman6.11-stable review patch. If anyone has any objections, please let me know.
------------------
From: Kaixin Wang <[email protected]>
[ 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->fbFix 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.
--- drivers/video/fbdev/pxafb.c | 1 + 1 file changed, 1 insertion(+)
drivers/video/fbdev/pxafb.c +1 -0
@@ -2403,6 +2403,7 @@ static void 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);
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 192/558 pmdomain: core: Dont hold the genpd-lock when calling dev_pm_domain_set()
In reply to Greg Kroah-Hartman6.11-stable review patch. If anyone has any objections, please let me know.
------------------
From: Ulf Hansson <[email protected]>
[ Upstream commit b87eee38605c396f0e1fa435939960e5c6cd41d6 ]
There is no need to hold the genpd-lock, while assigning the dev->pm_domain. In fact, it becomes a problem on a PREEMPT_RT based configuration as the genpd-lock may be a raw spinlock, while the lock acquired through the call to dev_pm_domain_set() is a regular spinlock.
To fix the problem, let's simply move the calls to dev_pm_domain_set() outside the genpd-lock.
--- drivers/pmdomain/core.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-)
drivers/pmdomain/core.c +3 -2
@@ -1758,7 +1758,6 @@ static int genpd_add_device(struct generic_pm_domain *genpd, struct device *dev,genpd_lock (genpd);genpd_set_cpumask (genpd, gpd_data->cpu); -dev_pm_domain_set (dev, &genpd->domain); genpd->device_count++;if (gd)
@@ -1767,6 +1766,7 @@ static int genpd_add_device(struct generic_pm_domain *genpd, struct device *dev,list_add_tail (&gpd_data->base.list_node, &genpd->dev_list);genpd_unlock (genpd); +dev_pm_domain_set (dev, &genpd->domain); out:if (ret)genpd_free_dev_data (dev, gpd_data);
@@ -1823,12 +1823,13 @@ static int genpd_remove_device(struct generic_pm_domain *genpd, genpd->gd->max_off_time_changed = true;genpd_clear_cpumask (genpd, gpd_data->cpu); -dev_pm_domain_set (dev,NULL );list_del_init (&pdd->list_node);genpd_unlock (genpd); +dev_pm_domain_set (dev,NULL ); +if (genpd->detach_dev) genpd->detach_dev (genpd, dev);
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 193/558 pmdomain: core: Use dev_name() instead of kobject_get_path() in debugfs
In reply to Greg Kroah-Hartman6.11-stable review patch. If anyone has any objections, please let me know.
------------------
From: Ulf Hansson <[email protected]>
[ Upstream commit 9094e53ff5c86ebe372ad3960c3216c9817a1a04 ]
Using kobject_get_path() means a dynamic memory allocation gets done, which doesn't work on a PREEMPT_RT based configuration while holding genpd's raw spinlock.
To fix the problem, let's convert into using the simpler dev_name(). This means the information about the path doesn't get presented in debugfs, but hopefully this shouldn't be an issue.
--- drivers/pmdomain/core.c | 23 +++-------------------- 1 file changed, 3 insertions(+), 20 deletions(-)
drivers/pmdomain/core.c +3 -20
@@ -3210,7 +3210,6 @@ static int genpd_summary_one(struct seq_file *s, [GENPD_STATE_OFF] = "off" };struct pm_domain_data *pm_data; -const char *kobj_path;struct gpd_link *link;char state[16 ];int ret;
@@ -3243,17 +3242,10 @@ static int genpd_summary_one(struct seq_file *s, }list_for_each_entry (pm_data, &genpd->dev_list, list_node) { - kobj_path =kobject_get_path (&pm_data->dev->kobj, -genpd_is_irq_safe (genpd) ? -GFP_ATOMIC :GFP_KERNEL ); -if (kobj_path ==NULL ) -continue ; - -seq_printf (s,"\n %-50s " , kobj_path); +seq_printf (s,"\n %-50s " ,dev_name (pm_data->dev));rtpm_status_str (s, pm_data->dev);perf_status_str (s, pm_data->dev);mode_status_str (s, pm_data->dev); -kfree (kobj_path); }seq_puts (s,"\n" );
@@ -3422,23 +3414,14 @@ static int devices_show(struct seq_file *s, void *data) {struct generic_pm_domain *genpd = s->private;struct pm_domain_data *pm_data; -const char *kobj_path;int ret =0 ; ret =genpd_lock_interruptible (genpd);if (ret)return -ERESTARTSYS ; -list_for_each_entry (pm_data, &genpd->dev_list, list_node) { - kobj_path =kobject_get_path (&pm_data->dev->kobj, -genpd_is_irq_safe (genpd) ? -GFP_ATOMIC :GFP_KERNEL ); -if (kobj_path ==NULL ) -continue ; - -seq_printf (s,"%s\n" , kobj_path); -kfree (kobj_path); - } +list_for_each_entry (pm_data, &genpd->dev_list, list_node) +seq_printf (s,"%s\n" ,dev_name (pm_data->dev));genpd_unlock (genpd);return ret;
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 194/558 rcuscale: Provide clear error when async specified without primitives
In reply to Greg Kroah-Hartman6.11-stable review patch. If anyone has any objections, please let me know.
------------------
From: Paul E. McKenney <[email protected]>
[ 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.
--- kernel/rcu/rcuscale.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
kernel/rcu/rcuscale.c +2 -2
@@ -499,7 +499,7 @@ rcu_scale_writer(void *arg)schedule_timeout_idle (torture_random (&tr) % writer_holdoff_jiffies +1 ); 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 );
@@ -555,7 +555,7 @@ rcu_scale_writer(void *arg) 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 ;
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 195/558 power: reset: brcmstb: Do not go into infinite loop if reset fails
In reply to Greg Kroah-Hartman6.11-stable review patch. If anyone has any objections, please let me know.
------------------
From: Andrew Davis <[email protected]>
[ Upstream commit cf8c39b00e982fa506b16f9d76657838c09150cb ]
There may be other backup reset methods available, do not halt here so that other reset methods can be tried.
--- drivers/power/reset/brcmstb-reboot.c | 3 --- 1 file changed, 3 deletions(-)
drivers/power/reset/brcmstb-reboot.c +0 -3
@@ -62,9 +62,6 @@ static int brcmstb_restart_handler(struct notifier_block *this,return NOTIFY_DONE ; } -while (1 ) - ; -return NOTIFY_DONE ; }
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 196/558 iommu/arm-smmu-v3: Match Stall behaviour for S2
In reply to Greg Kroah-Hartman6.11-stable review patch. If anyone has any objections, please let me know.
------------------
From: Mostafa Saleh <[email protected]>
[ Upstream commit ce7cb08e22e09f43649b025c849a3ae3b80833c4 ]
According to the spec (ARM IHI 0070 F.b), in
"5.5 Fault configuration (A, R, S bits)":
A STE with stage 2 translation enabled and STE.S2S == 0 is
considered ILLEGAL if SMMU_IDR0.STALL_MODEL == 0b10.Also described in the pseudocode “SteIllegal()”
if STE.Config == '11x' then
[..]
if eff_idr0_stall_model == '10' && STE.S2S == '0' then
// stall_model forcing stall, but S2S == 0
return TRUE;Which means, S2S must be set when stall model is "ARM_SMMU_FEAT_STALL_FORCE", but currently the driver ignores that.
Although, the driver can do the minimum and only set S2S for “ARM_SMMU_FEAT_STALL_FORCE”, it is more consistent to match S1 behaviour, which also sets it for “ARM_SMMU_FEAT_STALL” if the master has requested stalls.
Also, since S2 stalls are enabled now, report them to the IOMMU layer and for VFIO devices it will fail anyway as VFIO doesn’t register an iopf handler.
--- drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c | 8 +++----- drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h | 1 + 2 files changed, 4 insertions(+), 5 deletions(-)
drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c +3 -5
@@ -1012,7 +1012,8 @@ void arm_smmu_get_ste_used(const __le64 *ent, __le64 *used_bits) used_bits[2 ] |=cpu_to_le64 (STRTAB_STE_2_S2VMID |STRTAB_STE_2_VTCR |STRTAB_STE_2_S2AA64 |STRTAB_STE_2_S2ENDI | -STRTAB_STE_2_S2PTW |STRTAB_STE_2_S2R ); +STRTAB_STE_2_S2PTW |STRTAB_STE_2_S2S | +STRTAB_STE_2_S2R ); used_bits[3 ] |=cpu_to_le64 (STRTAB_STE_3_S2TTB_MASK ); }
@@ -1646,6 +1647,7 @@ void arm_smmu_make_s2_domain_ste(struct arm_smmu_ste *target,STRTAB_STE_2_S2ENDI | #endifSTRTAB_STE_2_S2PTW | + (master->stall_enabled ?STRTAB_STE_2_S2S :0 ) | STRTAB_STE_2_S2R); target->data[3] = cpu_to_le64(pgtbl_cfg->arm_lpae_s2_cfg.vttbr &
@@ -1739,10 +1741,6 @@ static int arm_smmu_handle_evt(struct arm_smmu_device *smmu, u64 *evt)return -EOPNOTSUPP ; } -/* Stage-2 is always pinned at the moment */ -if (evt[1 ] &EVTQ_1_S2 ) -return -EFAULT ; -if (!(evt[1 ] &EVTQ_1_STALL ))return -EOPNOTSUPP ;
drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h +1 -0
@@ -267,6 +267,7 @@ struct arm_smmu_ste {#define STRTAB_STE_2_S2AA64 (1UL << 51)#define STRTAB_STE_2_S2ENDI (1UL << 52)#define STRTAB_STE_2_S2PTW (1UL << 54) +#define STRTAB_STE_2_S2S (1UL << 57)#define STRTAB_STE_2_S2R (1UL << 58)#define STRTAB_STE_3_S2TTB_MASK GENMASK_ULL(51, 4)
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 197/558 iommu/vt-d: Always reserve a domain ID for identity setup
In reply to Greg Kroah-Hartman6.11-stable review patch. If anyone has any objections, please let me know.
------------------
From: Lu Baolu <[email protected]>
[ Upstream commit 2c13012e09190174614fd6901857a1b8c199e17d ]
We will use a global static identity domain. Reserve a static domain ID for it.
--- drivers/iommu/intel/iommu.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-)
drivers/iommu/intel/iommu.c +3 -3
@@ -1447,10 +1447,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 ; }
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 198/558 iommu/vt-d: Fix potential lockup if qi_submit_sync called with 0 count
In reply to Greg Kroah-Hartman6.11-stable review patch. If anyone has any objections, please let me know.
------------------
From: Sanjay K Kumar <[email protected]>
[ 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).
--- drivers/iommu/intel/dmar.c | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-)
drivers/iommu/intel/dmar.c +11 -5
@@ -1204,9 +1204,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++; }
@@ -1463,8 +1461,16 @@ int qi_submit_sync(struct intel_iommu *iommu, struct qi_desc *desc,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);
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 199/558 iommu/vt-d: Unconditionally flush device TLB for pasid table updates
In reply to Greg Kroah-Hartman6.11-stable review patch. If anyone has any objections, please let me know.
------------------
From: Lu Baolu <[email protected]>
[ Upstream commit 1f5e307ca16c0c19186cbd56ac460a687e6daba0 ]
The caching mode of an IOMMU is irrelevant to the behavior of the device TLB. Previously, commit <304b3bde24b5> ("iommu/vt-d: Remove caching mode check before device TLB flush") removed this redundant check in the domain unmap path.
Checking the caching mode before flushing the device TLB after a pasid table entry is updated is unnecessary and can lead to inconsistent behavior.
Extends this consistency by removing the caching mode check in the pasid table update path.
--- drivers/iommu/intel/pasid.c | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-)
drivers/iommu/intel/pasid.c +3 -9
@@ -264,9 +264,7 @@ void intel_pasid_tear_down_entry(struct intel_iommu *iommu, struct device *dev,else iommu->flush.flush_iotlb (iommu, did,0 ,0 ,DMA_TLB_DSI_FLUSH ); -/* Device IOTLB doesn't need to be flushed in caching mode. */ -if (!cap_caching_mode (iommu->cap)) -devtlb_invalidation_with_pasid (iommu, dev, pasid); +devtlb_invalidation_with_pasid (iommu, dev, pasid); }/*
@@ -493,9 +491,7 @@ int intel_pasid_setup_dirty_tracking(struct intel_iommu *iommu, iommu->flush.flush_iotlb (iommu, did,0 ,0 ,DMA_TLB_DSI_FLUSH ); -/* Device IOTLB doesn't need to be flushed in caching mode. */ -if (!cap_caching_mode (iommu->cap)) -devtlb_invalidation_with_pasid (iommu, dev, pasid); +devtlb_invalidation_with_pasid (iommu, dev, pasid);return 0 ; }
@@ -572,9 +568,7 @@ void intel_pasid_setup_page_snoop_control(struct intel_iommu *iommu,pasid_cache_invalidation_with_pasid (iommu, did, pasid);qi_flush_piotlb (iommu, did, pasid,0 ,-1 ,0 ); -/* Device IOTLB doesn't need to be flushed in caching mode. */ -if (!cap_caching_mode (iommu->cap)) -devtlb_invalidation_with_pasid (iommu, dev, pasid); +devtlb_invalidation_with_pasid (iommu, dev, pasid); }/**
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 200/558 iommu/arm-smmu-v3: Do not use devm for the cd table allocations
In reply to Greg Kroah-Hartman6.11-stable review patch. If anyone has any objections, please let me know.
------------------
From: Jason Gunthorpe <[email protected]>
[ Upstream commit 47b2de35cab2b683f69d03515c2658c2d8515323 ]
The master->cd_table is entirely contained within the struct arm_smmu_master which is guaranteed to be freed by the core code under arm_smmu_release_device().
There is no reason to use devm here, arm_smmu_free_cd_tables() is reliably called to free the CD related memory. Remove it and save some memory.
--- drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c | 29 +++++++++------------ 1 file changed, 13 insertions(+), 16 deletions(-)
drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c +13 -16
@@ -1185,8 +1185,8 @@ static int arm_smmu_alloc_cd_leaf_table(struct arm_smmu_device *smmu, {size_t size =CTXDESC_L2_ENTRIES * (CTXDESC_CD_DWORDS <<3 ); - l1_desc->l2ptr =dmam_alloc_coherent (smmu->dev, size, - &l1_desc->l2ptr_dma,GFP_KERNEL ); + l1_desc->l2ptr =dma_alloc_coherent (smmu->dev, size, + &l1_desc->l2ptr_dma,GFP_KERNEL );if (!l1_desc->l2ptr) {dev_warn (smmu->dev,"failed to allocate context descriptor table\n" );
@@ -1400,17 +1400,17 @@ static int arm_smmu_alloc_cd_tables(struct arm_smmu_master *master) cd_table->num_l1_ents =DIV_ROUND_UP (max_contexts,CTXDESC_L2_ENTRIES ); - cd_table->l1_desc =devm_kcalloc (smmu->dev, cd_table->num_l1_ents, -sizeof (*cd_table->l1_desc), -GFP_KERNEL ); + cd_table->l1_desc =kcalloc (cd_table->num_l1_ents, +sizeof (*cd_table->l1_desc), +GFP_KERNEL );if (!cd_table->l1_desc)return -ENOMEM ; l1size = cd_table->num_l1_ents * (CTXDESC_L1_DESC_DWORDS <<3 ); } - cd_table->cdtab =dmam_alloc_coherent (smmu->dev, l1size, &cd_table->cdtab_dma, -GFP_KERNEL ); + cd_table->cdtab =dma_alloc_coherent (smmu->dev, l1size, + &cd_table->cdtab_dma,GFP_KERNEL );if (!cd_table->cdtab) {dev_warn (smmu->dev,"failed to allocate context descriptor\n" ); ret = -ENOMEM ;
@@ -1421,7 +1421,7 @@ static int arm_smmu_alloc_cd_tables(struct arm_smmu_master *master) err_free_l1:if (cd_table->l1_desc) { -devm_kfree (smmu->dev, cd_table->l1_desc); +kfree (cd_table->l1_desc); cd_table->l1_desc =NULL ; }return ret;
@@ -1441,21 +1441,18 @@ static void arm_smmu_free_cd_tables(struct arm_smmu_master *master)if (!cd_table->l1_desc[i].l2ptr)continue ; -dmam_free_coherent (smmu->dev, size, - cd_table->l1_desc[i].l2ptr, - cd_table->l1_desc[i].l2ptr_dma); +dma_free_coherent (smmu->dev, size, + cd_table->l1_desc[i].l2ptr, + cd_table->l1_desc[i].l2ptr_dma); } -devm_kfree (smmu->dev, cd_table->l1_desc); - cd_table->l1_desc =NULL ; +kfree (cd_table->l1_desc); l1size = cd_table->num_l1_ents * (CTXDESC_L1_DESC_DWORDS <<3 ); }else { l1size = cd_table->num_l1_ents * (CTXDESC_CD_DWORDS <<3 ); } -dmam_free_coherent (smmu->dev, l1size, cd_table->cdtab, cd_table->cdtab_dma); - cd_table->cdtab_dma =0 ; - cd_table->cdtab =NULL ; +dma_free_coherent (smmu->dev, l1size, cd_table->cdtab, cd_table->cdtab_dma); }/* Stream table manipulation functions */
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 201/558 cgroup: Disallow mounting v1 hierarchies without controller implementation
In reply to Greg Kroah-Hartman6.11-stable review patch. If anyone has any objections, please let me know.
------------------
From: Michal Koutný <[email protected]>
[ Upstream commit 3c41382e920f1dd5c9f432948fe799c07af1cced ]
The configs that disable some v1 controllers would still allow mounting them but with no controller-specific files. (Making such hierarchies equivalent to named v1 hierarchies.) To achieve behavior consistent with actual out-compilation of a whole controller, the mounts should treat respective controllers as non-existent.
Wrap implementation into a helper function, leverage legacy_files to detect compiled out controllers. The effect is that mounts on v1 would fail and produce a message like:
[ 1543.999081] cgroup: Unknown subsys name 'memory'
--- kernel/cgroup/cgroup-v1.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-)
kernel/cgroup/cgroup-v1.c +10 -2
@@ -46,6 +46,12 @@ bool cgroup1_ssid_disabled(int ssid)return cgroup_no_v1_mask & (1 << ssid); } +static bool cgroup1_subsys_absent (struct cgroup_subsys *ss) +{ +/* Check also dfl_cftypes for file-less controllers, i.e. perf_event */ +return ss->legacy_cftypes ==NULL && ss->dfl_cftypes; +} +/** * cgroup_attach_task_all - attach task 'tsk' to all cgroups of task 'from' * @from: attach to all cgroups of a given task
@@ -932,7 +938,8 @@ int cgroup1_parse_param(struct fs_context *fc, struct fs_parameter *param)if (ret != -ENOPARAM )return ret;for_each_subsys (ss, i) { -if (strcmp (param->key, ss->legacy_name)) +if (strcmp (param->key, ss->legacy_name) || +cgroup1_subsys_absent (ss))continue ;if (!cgroup_ssid_enabled (i) ||cgroup1_ssid_disabled (i)) return invalfc(fc, "Disabled controller '%s'",
@@ -1024,7 +1031,8 @@ static int check_cgroupfs_options(struct fs_context *fc) mask = ~((u16 )1 << cpuset_cgrp_id);#endif for_each_subsys (ss, i) -if (cgroup_ssid_enabled (i) && !cgroup1_ssid_disabled (i)) +if (cgroup_ssid_enabled (i) && !cgroup1_ssid_disabled (i) && + !cgroup1_subsys_absent (ss)) enabled |=1 << i; ctx->subsys_mask &= enabled;
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 202/558 drm/stm: Avoid use-after-free issues with crtc and plane
In reply to Greg Kroah-Hartman6.11-stable review patch. If anyone has any objections, please let me know.
------------------
From: Katya Orlova <[email protected]>
[ 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/
--- drivers/gpu/drm/stm/drv.c | 3 +- drivers/gpu/drm/stm/ltdc.c | 73 ++++++++++---------------------------- 2 files changed, 20 insertions(+), 56 deletions(-)
drivers/gpu/drm/stm/drv.c +2 -1
@@ -25,6 +25,7 @@#include <drm/drm_module.h> #include <drm/drm_probe_helper.h> #include <drm/drm_vblank.h> +#include <drm/drm_managed.h> #include "ltdc.h"
@@ -75,7 +76,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 ;
drivers/gpu/drm/stm/ltdc.c +18 -55
177 lines not on this page · raw message
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 203/558 drm/amd/display: Pass non-null to dcn20_validate_apply_pipe_split_flags
In reply to Greg Kroah-Hartman6.11-stable review patch. If anyone has any objections, please let me know.
------------------
From: Alex Hung <[email protected]>
[ Upstream commit 5559598742fb4538e4c51c48ef70563c49c2af23 ]
[WHAT & HOW]
"dcn20_validate_apply_pipe_split_flags" dereferences merge, and thus it cannot be a null pointer. Let's pass a valid pointer to avoid null dereference.
This fixes 2 FORWARD_NULL issues reported by Coverity.
--- drivers/gpu/drm/amd/display/dc/resource/dcn20/dcn20_resource.c | 3 ++- drivers/gpu/drm/amd/display/dc/resource/dcn21/dcn21_resource.c | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-)
drivers/gpu/drm/amd/display/dc/resource/dcn20/dcn20_resource.c +2 -1
@@ -2040,6 +2040,7 @@ bool dcn20_fast_validate_bw( {bool out = false;int split[MAX_PIPES ] = {0 }; +bool merge[MAX_PIPES ] = { false };int pipe_cnt, i, pipe_idx, vlevel;ASSERT (pipes);
@@ -2064,7 +2065,7 @@ bool dcn20_fast_validate_bw(if (vlevel > context->bw_ctx.dml.soc.num_states) goto validate_fail; - vlevel =dcn20_validate_apply_pipe_split_flags (dc, context, vlevel, split,NULL ); + vlevel =dcn20_validate_apply_pipe_split_flags (dc, context, vlevel, split, merge);/*initialize pipe_just_split_from to invalid idx*/ for (i =0 ; i <MAX_PIPES ; i++)
drivers/gpu/drm/amd/display/dc/resource/dcn21/dcn21_resource.c +2 -1
@@ -774,6 +774,7 @@ bool dcn21_fast_validate_bw(struct dc *dc, {bool out = false;int split[MAX_PIPES ] = {0 }; +bool merge[MAX_PIPES ] = { false };int pipe_cnt, i, pipe_idx, vlevel;ASSERT (pipes);
@@ -816,7 +817,7 @@ bool dcn21_fast_validate_bw(struct dc *dc, goto validate_fail; } - vlevel =dcn20_validate_apply_pipe_split_flags (dc, context, vlevel, split,NULL ); + vlevel =dcn20_validate_apply_pipe_split_flags (dc, context, vlevel, split, merge);for (i =0 , pipe_idx =0 ; i < dc->res_pool->pipe_count; i++) {struct pipe_ctx *pipe = &context->res_ctx.pipe_ctx[i];
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 204/558 drm/amd/display: Check null pointers before using them
In reply to Greg Kroah-Hartman6.11-stable review patch. If anyone has any objections, please let me know.
------------------
From: Alex Hung <[email protected]>
[ Upstream commit 1ff12bcd7deaeed25efb5120433c6a45dd5504a8 ]
[WHAT & HOW]
These pointers are null checked previously in the same function, indicating they might be null as reported by Coverity. As a result, they need to be checked when used again.
This fixes 3 FORWARD_NULL issue reported by Coverity.
--- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-)
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +8 -4
@@ -7275,6 +7275,9 @@ create_validate_stream_for_sink(struct amdgpu_dm_connector *aconnector,int requested_bpc = drm_state ? drm_state->max_requested_bpc :8 ;enum dc_status dc_result =DC_OK ; +if (!dm_state) +return NULL ; + do { stream = create_stream_for_sink(connector, drm_mode, dm_state, old_stream,
@@ -9382,7 +9385,7 @@ static void amdgpu_dm_commit_streams(struct drm_atomic_state *state,if (acrtc) old_crtc_state =drm_atomic_get_old_crtc_state (state, &acrtc->base); -if (!acrtc->wb_enabled) +if (!acrtc || !acrtc->wb_enabled)continue ; dm_old_crtc_state =to_dm_crtc_state (old_crtc_state);
@@ -9786,9 +9789,10 @@ static void amdgpu_dm_atomic_commit_tail(struct drm_atomic_state *state)DRM_INFO ("[HDCP_DM] hdcp_update_display enable_encryption = %x\n" , enable_encryption); -hdcp_update_display ( - adev->dm.hdcp_workqueue, aconnector->dc_link->link_index, aconnector, - new_con_state->hdcp_content_type, enable_encryption); +if (aconnector->dc_link) +hdcp_update_display ( + adev->dm.hdcp_workqueue, aconnector->dc_link->link_index, aconnector, + new_con_state->hdcp_content_type, enable_encryption); } }
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 205/558 drm/amd/display: Check null pointers before used
In reply to Greg Kroah-Hartman6.11-stable review patch. If anyone has any objections, please let me know.
------------------
From: Alex Hung <[email protected]>
[ Upstream commit be1fb44389ca3038ad2430dac4234669bc177ee3 ]
[WHAT & HOW]
Poniters, such as dc->clk_mgr, are null checked previously in the same function, so Coverity warns "implies that "dc->clk_mgr" might be null". As a result, these pointers need to be checked when used again.
This fixes 10 FORWARD_NULL issues reported by Coverity.
--- .../drm/amd/display/dc/clk_mgr/dce110/dce110_clk_mgr.c | 2 +- drivers/gpu/drm/amd/display/dc/hubp/dcn10/dcn10_hubp.c | 3 ++- drivers/gpu/drm/amd/display/dc/hubp/dcn20/dcn20_hubp.c | 3 ++- drivers/gpu/drm/amd/display/dc/hwss/dce110/dce110_hwseq.c | 5 +++-- drivers/gpu/drm/amd/display/dc/hwss/dcn10/dcn10_hwseq.c | 4 ++-- drivers/gpu/drm/amd/display/dc/hwss/dcn31/dcn31_hwseq.c | 4 ++-- drivers/gpu/drm/amd/display/dc/hwss/dcn35/dcn35_hwseq.c | 8 ++++---- .../amd/display/dc/link/protocols/link_dp_capability.c | 2 +- 8 files changed, 17 insertions(+), 14 deletions(-)
drivers/gpu/drm/amd/display/dc/clk_mgr/dce110/dce110_clk_mgr.c +1 -1
@@ -195,7 +195,7 @@ void dce11_pplib_apply_display_requirements(* , then change minimum memory clock based on real-time bandwidth * limitation. */ - if ((dc->ctx->asic_id.chip_family == FAMILY_AI) && + if (dc->bw_vbios && (dc->ctx->asic_id.chip_family == FAMILY_AI) && ASICREV_IS_VEGA20_P(dc->ctx->asic_id.hw_internal_rev) && (context->stream_count >= 2)) { pp_display_cfg->min_memory_clock_khz = max(pp_display_cfg->min_memory_clock_khz, (uint32_t) div64_s64(
drivers/gpu/drm/amd/display/dc/hubp/dcn10/dcn10_hubp.c +2 -1
@@ -749,7 +749,8 @@ bool hubp1_is_flip_pending(struct hubp *hubp)if (flip_pending)return true; -if (earliest_inuse_address.grph.addr.quad_part != hubp->request_address.grph.addr.quad_part) +if (hubp && + earliest_inuse_address.grph.addr.quad_part != hubp->request_address.grph.addr.quad_part)return true;return false;
drivers/gpu/drm/amd/display/dc/hubp/dcn20/dcn20_hubp.c +2 -1
@@ -927,7 +927,8 @@ bool hubp2_is_flip_pending(struct hubp *hubp)if (flip_pending)return true; -if (earliest_inuse_address.grph.addr.quad_part != hubp->request_address.grph.addr.quad_part) +if (hubp && + earliest_inuse_address.grph.addr.quad_part != hubp->request_address.grph.addr.quad_part)return true;return false;
drivers/gpu/drm/amd/display/dc/hwss/dce110/dce110_hwseq.c +3 -2
@@ -950,7 +950,7 @@ void dce110_edp_backlight_control( {struct dc_context *ctx = link->ctx;struct bp_transmitter_control cntl = {0 }; -uint8_t pwrseq_instance; +uint8_t pwrseq_instance =0 ;unsigned int pre_T11_delay =OLED_PRE_T11_DELAY ;unsigned int post_T7_delay =OLED_POST_T7_DELAY ;
@@ -1003,7 +1003,8 @@ void dce110_edp_backlight_control(*/ /* dc_service_sleep_in_milliseconds(50); */ /*edp 1.2*/ - pwrseq_instance = link->panel_cntl->pwrseq_inst; +if (link->panel_cntl) + pwrseq_instance = link->panel_cntl->pwrseq_inst;if (cntl.action ==TRANSMITTER_CONTROL_BACKLIGHT_ON ) {if (!link->dc->config.edp_no_power_sequencing)
drivers/gpu/drm/amd/display/dc/hwss/dcn10/dcn10_hwseq.c +2 -2
@@ -1554,7 +1554,7 @@ void dcn10_init_hw(struct dc *dc) dc->clk_mgr->funcs->init_clocks (dc->clk_mgr);/* Align bw context with hw config when system resume. */ -if (dc->clk_mgr->clks.dispclk_khz !=0 && dc->clk_mgr->clks.dppclk_khz !=0 ) { +if (dc->clk_mgr && dc->clk_mgr->clks.dispclk_khz !=0 && dc->clk_mgr->clks.dppclk_khz !=0 ) { dc->current_state->bw_ctx.bw.dcn.clk.dispclk_khz = dc->clk_mgr->clks.dispclk_khz; dc->current_state->bw_ctx.bw.dcn.clk.dppclk_khz = dc->clk_mgr->clks.dppclk_khz; }
@@ -1674,7 +1674,7 @@ void dcn10_init_hw(struct dc *dc)REG_UPDATE (DCFCLK_CNTL ,DCFCLK_GATE_DIS ,0 ); } -if (dc->clk_mgr->funcs->notify_wm_ranges) +if (dc->clk_mgr && dc->clk_mgr->funcs->notify_wm_ranges) dc->clk_mgr->funcs->notify_wm_ranges (dc->clk_mgr); }
drivers/gpu/drm/amd/display/dc/hwss/dcn31/dcn31_hwseq.c +2 -2
@@ -256,10 +256,10 @@ void dcn31_init_hw(struct dc *dc)if (!dcb->funcs->is_accelerated_mode (dcb) && dc->res_pool->hubbub->funcs->init_watermarks) dc->res_pool->hubbub->funcs->init_watermarks (dc->res_pool->hubbub); -if (dc->clk_mgr->funcs->notify_wm_ranges) +if (dc->clk_mgr && dc->clk_mgr->funcs->notify_wm_ranges) dc->clk_mgr->funcs->notify_wm_ranges (dc->clk_mgr); -if (dc->clk_mgr->funcs->set_hard_max_memclk && !dc->clk_mgr->dc_mode_softmax_enabled) +if (dc->clk_mgr && dc->clk_mgr->funcs->set_hard_max_memclk && !dc->clk_mgr->dc_mode_softmax_enabled) dc->clk_mgr->funcs->set_hard_max_memclk (dc->clk_mgr);if (dc->res_pool->hubbub->funcs->force_pstate_change_control)
drivers/gpu/drm/amd/display/dc/hwss/dcn35/dcn35_hwseq.c +4 -4
@@ -235,7 +235,7 @@ void dcn35_init_hw(struct dc *dc)if (hws->funcs.enable_power_gating_plane) hws->funcs.enable_power_gating_plane(dc->hwseq, true); */ -if (res_pool->hubbub->funcs->dchubbub_init) +if (res_pool->hubbub && res_pool->hubbub->funcs->dchubbub_init) res_pool->hubbub->funcs->dchubbub_init (dc->res_pool->hubbub);/* If taking control over from VBIOS, we may want to optimize our first * mode set, so we need to skip powering down pipes until we know which
@@ -328,10 +328,10 @@ void dcn35_init_hw(struct dc *dc)if (!dcb->funcs->is_accelerated_mode (dcb) && dc->res_pool->hubbub->funcs->init_watermarks) dc->res_pool->hubbub->funcs->init_watermarks (dc->res_pool->hubbub); -if (dc->clk_mgr->funcs->notify_wm_ranges) +if (dc->clk_mgr && dc->clk_mgr->funcs->notify_wm_ranges) dc->clk_mgr->funcs->notify_wm_ranges (dc->clk_mgr); -if (dc->clk_mgr->funcs->set_hard_max_memclk && !dc->clk_mgr->dc_mode_softmax_enabled) +if (dc->clk_mgr && dc->clk_mgr->funcs->set_hard_max_memclk && !dc->clk_mgr->dc_mode_softmax_enabled) dc->clk_mgr->funcs->set_hard_max_memclk (dc->clk_mgr);
@@ -1054,7 +1054,7 @@ void dcn35_calc_blocks_to_gate(struct dc *dc, struct dc_state *context,if (pipe_ctx->plane_res.hubp) update_state->pg_pipe_res_update[PG_HUBP ][pipe_ctx->plane_res.hubp->inst] = false; -if (pipe_ctx->plane_res.dpp) +if (pipe_ctx->plane_res.dpp && pipe_ctx->plane_res.hubp) update_state->pg_pipe_res_update[PG_DPP ][pipe_ctx->plane_res.hubp->inst] = false;if (pipe_ctx->plane_res.dpp || pipe_ctx->stream_res.opp)
drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_capability.c +1 -1
@@ -2254,7 +2254,7 @@ bool dp_verify_link_cap_with_retries(memset (&link->verified_link_cap,0 ,sizeof (struct dc_link_settings )); -if (!link_detect_connection_type (link, &type) || type == dc_connection_none) { +if (link->link_enc && (!link_detect_connection_type (link, &type) || type == dc_connection_none)) { link->verified_link_cap = fail_safe_link_settings;break ; }else if (dp_verify_link_cap (link, known_limit_link_setting, &fail_count)) {
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 206/558 drm/amd/display: Check null pointers before multiple uses
In reply to Greg Kroah-Hartman6.11-stable review patch. If anyone has any objections, please let me know.
------------------
From: Alex Hung <[email protected]>
[ Upstream commit fdd5ecbbff751c3b9061d8ebb08e5c96119915b4 ]
[WHAT & HOW]
Poniters, such as stream_enc and dc->bw_vbios, are null checked previously in the same function, so Coverity warns "implies that stream_enc and dc->bw_vbios might be null". They are used multiple times in the subsequent code and need to be checked.
This fixes 10 FORWARD_NULL issues reported by Coverity.
--- .../drm/amd/display/dc/core/dc_hw_sequencer.c | 96 ++++++++++--------- .../amd/display/dc/hwss/dcn20/dcn20_hwseq.c | 8 +- .../display/dc/link/accessories/link_dp_cts.c | 5 +- .../amd/display/dc/link/hwss/link_hwss_dio.c | 5 +- .../dc/resource/dce112/dce112_resource.c | 5 +- .../dc/resource/dcn32/dcn32_resource.c | 3 + .../resource/dcn32/dcn32_resource_helpers.c | 10 +- 7 files changed, 76 insertions(+), 56 deletions(-)
drivers/gpu/drm/amd/display/dc/core/dc_hw_sequencer.c +49 -47
@@ -636,57 +636,59 @@ void hwss_build_fast_sequence(struct dc *dc,while (current_pipe) { current_mpc_pipe = current_pipe;while (current_mpc_pipe) { -if (dc->hwss.set_flip_control_gsl && current_mpc_pipe->plane_state && current_mpc_pipe->plane_state->update_flags.raw) { - block_sequence[*num_steps].params.set_flip_control_gsl_params.pipe_ctx = current_mpc_pipe; - block_sequence[*num_steps].params.set_flip_control_gsl_params.flip_immediate = current_mpc_pipe->plane_state->flip_immediate; - block_sequence[*num_steps].func =HUBP_SET_FLIP_CONTROL_GSL ; - (*num_steps)++; - } -if (dc->hwss.program_triplebuffer && dc->debug.enable_tri_buf && current_mpc_pipe->plane_state->update_flags.raw) { - block_sequence[*num_steps].params.program_triplebuffer_params.dc = dc; - block_sequence[*num_steps].params.program_triplebuffer_params.pipe_ctx = current_mpc_pipe; - block_sequence[*num_steps].params.program_triplebuffer_params.enableTripleBuffer = current_mpc_pipe->plane_state->triplebuffer_flips; - block_sequence[*num_steps].func =HUBP_PROGRAM_TRIPLEBUFFER ; - (*num_steps)++; - } -if (dc->hwss.update_plane_addr && current_mpc_pipe->plane_state->update_flags.bits.addr_update) { -if (resource_is_pipe_type (current_mpc_pipe,OTG_MASTER ) && - stream_status->mall_stream_config.type ==SUBVP_MAIN ) { - block_sequence[*num_steps].params.subvp_save_surf_addr.dc_dmub_srv = dc->ctx->dmub_srv; - block_sequence[*num_steps].params.subvp_save_surf_addr.addr = ¤t_mpc_pipe->plane_state->address; - block_sequence[*num_steps].params.subvp_save_surf_addr.subvp_index = current_mpc_pipe->subvp_index; - block_sequence[*num_steps].func =DMUB_SUBVP_SAVE_SURF_ADDR ; +if (current_mpc_pipe->plane_state) { +if (dc->hwss.set_flip_control_gsl && current_mpc_pipe->plane_state->update_flags.raw) { + block_sequence[*num_steps].params.set_flip_control_gsl_params.pipe_ctx = current_mpc_pipe; + block_sequence[*num_steps].params.set_flip_control_gsl_params.flip_immediate = current_mpc_pipe->plane_state->flip_immediate; + block_sequence[*num_steps].func =HUBP_SET_FLIP_CONTROL_GSL ; + (*num_steps)++; + } +if (dc->hwss.program_triplebuffer && dc->debug.enable_tri_buf && current_mpc_pipe->plane_state->update_flags.raw) { + block_sequence[*num_steps].params.program_triplebuffer_params.dc = dc; + block_sequence[*num_steps].params.program_triplebuffer_params.pipe_ctx = current_mpc_pipe; + block_sequence[*num_steps].params.program_triplebuffer_params.enableTripleBuffer = current_mpc_pipe->plane_state->triplebuffer_flips; + block_sequence[*num_steps].func =HUBP_PROGRAM_TRIPLEBUFFER ; + (*num_steps)++; + } +if (dc->hwss.update_plane_addr && current_mpc_pipe->plane_state->update_flags.bits.addr_update) { +if (resource_is_pipe_type (current_mpc_pipe,OTG_MASTER ) && + stream_status->mall_stream_config.type ==SUBVP_MAIN ) { + block_sequence[*num_steps].params.subvp_save_surf_addr.dc_dmub_srv = dc->ctx->dmub_srv; + block_sequence[*num_steps].params.subvp_save_surf_addr.addr = ¤t_mpc_pipe->plane_state->address; + block_sequence[*num_steps].params.subvp_save_surf_addr.subvp_index = current_mpc_pipe->subvp_index; + block_sequence[*num_steps].func =DMUB_SUBVP_SAVE_SURF_ADDR ; + (*num_steps)++; + } + + block_sequence[*num_steps].params.update_plane_addr_params.dc = dc; + block_sequence[*num_steps].params.update_plane_addr_params.pipe_ctx = current_mpc_pipe; + block_sequence[*num_steps].func =HUBP_UPDATE_PLANE_ADDR ; (*num_steps)++; } - block_sequence[*num_steps].params.update_plane_addr_params.dc = dc; - block_sequence[*num_steps].params.update_plane_addr_params.pipe_ctx = current_mpc_pipe; - block_sequence[*num_steps].func =HUBP_UPDATE_PLANE_ADDR ; - (*num_steps)++; - } - -if (hws->funcs.set_input_transfer_func && current_mpc_pipe->plane_state->update_flags.bits.gamma_change) { - block_sequence[*num_steps].params.set_input_transfer_func_params.dc = dc; - block_sequence[*num_steps].params.set_input_transfer_func_params.pipe_ctx = current_mpc_pipe; - block_sequence[*num_steps].params.set_input_transfer_func_params.plane_state = current_mpc_pipe->plane_state; - block_sequence[*num_steps].func =DPP_SET_INPUT_TRANSFER_FUNC ; - (*num_steps)++; - } +if (hws->funcs.set_input_transfer_func && current_mpc_pipe->plane_state->update_flags.bits.gamma_change) { + block_sequence[*num_steps].params.set_input_transfer_func_params.dc = dc; + block_sequence[*num_steps].params.set_input_transfer_func_params.pipe_ctx = current_mpc_pipe; + block_sequence[*num_steps].params.set_input_transfer_func_params.plane_state = current_mpc_pipe->plane_state; + block_sequence[*num_steps].func =DPP_SET_INPUT_TRANSFER_FUNC ; + (*num_steps)++; + } -if (dc->hwss.program_gamut_remap && current_mpc_pipe->plane_state->update_flags.bits.gamut_remap_change) { - block_sequence[*num_steps].params.program_gamut_remap_params.pipe_ctx = current_mpc_pipe; - block_sequence[*num_steps].func =DPP_PROGRAM_GAMUT_REMAP ; - (*num_steps)++; - } -if (current_mpc_pipe->plane_state->update_flags.bits.input_csc_change) { - block_sequence[*num_steps].params.setup_dpp_params.pipe_ctx = current_mpc_pipe; - block_sequence[*num_steps].func =DPP_SETUP_DPP ; - (*num_steps)++; - } -if (current_mpc_pipe->plane_state->update_flags.bits.coeff_reduction_change) { - block_sequence[*num_steps].params.program_bias_and_scale_params.pipe_ctx = current_mpc_pipe; - block_sequence[*num_steps].func =DPP_PROGRAM_BIAS_AND_SCALE ; - (*num_steps)++; +if (dc->hwss.program_gamut_remap && current_mpc_pipe->plane_state->update_flags.bits.gamut_remap_change) { + block_sequence[*num_steps].params.program_gamut_remap_params.pipe_ctx = current_mpc_pipe; + block_sequence[*num_steps].func =DPP_PROGRAM_GAMUT_REMAP ; + (*num_steps)++; + } +if (current_mpc_pipe->plane_state->update_flags.bits.input_csc_change) { + block_sequence[*num_steps].params.setup_dpp_params.pipe_ctx = current_mpc_pipe; + block_sequence[*num_steps].func =DPP_SETUP_DPP ; + (*num_steps)++; + } +if (current_mpc_pipe->plane_state->update_flags.bits.coeff_reduction_change) { + block_sequence[*num_steps].params.program_bias_and_scale_params.pipe_ctx = current_mpc_pipe; + block_sequence[*num_steps].func =DPP_PROGRAM_BIAS_AND_SCALE ; + (*num_steps)++; + } }if (hws->funcs.set_output_transfer_func && current_mpc_pipe->stream->update_flags.bits.out_tf) { block_sequence[*num_steps].params.set_output_transfer_func_params.dc = dc;
drivers/gpu/drm/amd/display/dc/hwss/dcn20/dcn20_hwseq.c +7 -1
@@ -2283,6 +2283,9 @@ void dcn20_post_unlock_program_front_end( } } +if (!hwseq) +return ; +/* P-State support transitions: * Natural -> FPO: P-State disabled in prepare, force disallow anytime is safe * FPO -> Natural: Unforce anytime after FW disable is safe (P-State will assert naturally)
@@ -2290,7 +2293,7 @@ void dcn20_post_unlock_program_front_end(* FPO -> Unsupported: P-State disabled in prepare, unforce disallow anytime is safe * FPO <-> SubVP: Force disallow is maintained on the FPO / SubVP pipes */ -if (hwseq && hwseq->funcs.update_force_pstate) +if (hwseq->funcs.update_force_pstate) dc->hwseq->funcs.update_force_pstate (dc, context);/* Only program the MALL registers after all the main and phantom pipes
@@ -2529,6 +2532,9 @@ bool dcn20_wait_for_blank_complete( {int counter; +if (!opp) +return false; +for (counter =0 ; counter <1000 ; counter++) {if (!opp->funcs->dpg_is_pending (opp))break ;
drivers/gpu/drm/amd/display/dc/link/accessories/link_dp_cts.c +4 -1
@@ -804,8 +804,11 @@ bool dp_set_test_pattern(break ; } +if (!pipe_ctx->stream) +return false; +if (pipe_ctx->stream_res.tg->funcs->lock_doublebuffer_enable) { -if (pipe_ctx->stream &&should_use_dmub_lock (pipe_ctx->stream->link)) { +if (should_use_dmub_lock (pipe_ctx->stream->link)) {union dmub_hw_lock_flags hw_locks = {0 };struct dmub_hw_lock_inst_flags inst_flags = {0 };
drivers/gpu/drm/amd/display/dc/link/hwss/link_hwss_dio.c +4 -1
@@ -74,7 +74,10 @@ void reset_dio_stream_encoder(struct pipe_ctx *pipe_ctx)struct link_encoder *link_enc =link_enc_cfg_get_link_enc (pipe_ctx->stream->link);struct stream_encoder *stream_enc = pipe_ctx->stream_res.stream_enc; -if (stream_enc && stream_enc->funcs->disable_fifo) +if (!stream_enc) +return ; + +if (stream_enc->funcs->disable_fifo) stream_enc->funcs->disable_fifo (stream_enc);if (stream_enc->funcs->set_input_mode) stream_enc->funcs->set_input_mode (stream_enc,0 );
drivers/gpu/drm/amd/display/dc/resource/dce112/dce112_resource.c +4 -1
@@ -1067,7 +1067,10 @@ static void bw_calcs_data_update_from_pplib(struct dc *dc)struct dm_pp_clock_levels clks = {0 };int memory_type_multiplier =MEMORY_TYPE_MULTIPLIER_CZ ; -if (dc->bw_vbios && dc->bw_vbios->memory_type == bw_def_hbm) +if (!dc->bw_vbios) +return ; + +if (dc->bw_vbios->memory_type == bw_def_hbm) memory_type_multiplier =MEMORY_TYPE_HBM ;/*do system clock TODO PPLIB: after PPLIB implement,
drivers/gpu/drm/amd/display/dc/resource/dcn32/dcn32_resource.c +3 -0
@@ -1651,6 +1651,9 @@ static void dcn32_enable_phantom_plane(struct dc *dc,else phantom_plane =dc_state_create_phantom_plane (dc, context, curr_pipe->plane_state); +if (!phantom_plane) +continue ; +memcpy (&phantom_plane->address, &curr_pipe->plane_state->address,sizeof (phantom_plane->address));memcpy (&phantom_plane->scaling_quality, &curr_pipe->plane_state->scaling_quality,sizeof (phantom_plane->scaling_quality));
drivers/gpu/drm/amd/display/dc/resource/dcn32/dcn32_resource_helpers.c +5 -5
@@ -218,12 +218,12 @@ bool dcn32_is_center_timing(struct pipe_ctx *pipe) pipe->stream->timing.v_addressable != pipe->stream->src.height) { is_center_timing = true; } - } -if (pipe->plane_state) { -if (pipe->stream->timing.v_addressable != pipe->plane_state->dst_rect.height && - pipe->stream->timing.v_addressable != pipe->plane_state->src_rect.height) { - is_center_timing = true; +if (pipe->plane_state) { +if (pipe->stream->timing.v_addressable != pipe->plane_state->dst_rect.height && + pipe->stream->timing.v_addressable != pipe->plane_state->src_rect.height) { + is_center_timing = true; + } } }
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 207/558 drm/amdgpu: disallow multiple BO_HANDLES chunks in one submit
In reply to Greg Kroah-Hartman6.11-stable review patch. If anyone has any objections, please let me know.
------------------
From: Pierre-Eric Pelloux-Prayer <[email protected]>
[ Upstream commit fec5f8e8c6bcf83ed7a392801d7b44c5ecfc1e82 ]
Before this commit, only submits with both a BO_HANDLES chunk and a 'bo_list_handle' would be rejected (by amdgpu_cs_parser_bos).
But if UMD sent multiple BO_HANDLES, what would happen is:
* only the last one would be really used
* all the others would leak memory as amdgpu_cs_p1_bo_handles would overwrite the previous p->bo_list value
This commit rejects submissions with multiple BO_HANDLES chunks to match the implementation of the parser.
--- drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c | 4 ++++ 1 file changed, 4 insertions(+)
drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c +4 -0
@@ -263,6 +263,10 @@ static int amdgpu_cs_pass1(struct amdgpu_cs_parser *p,if (size <sizeof (struct drm_amdgpu_bo_list_in )) goto free_partial_kdata; +/* Only a single BO list is allowed to simplify handling. */ +if (p->bo_list) + ret = -EINVAL ; + ret =amdgpu_cs_p1_bo_handles (p, p->chunks[i].kdata);if (ret) goto free_partial_kdata;
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 208/558 drm/amdkfd: amdkfd_free_gtt_mem clear the correct pointer
In reply to Greg Kroah-Hartman6.11-stable review patch. If anyone has any objections, please let me know.
------------------
From: Philip Yang <[email protected]>
[ Upstream commit c86ad39140bbcb9dc75a10046c2221f657e8083b ]
Pass pointer reference to amdgpu_bo_unref to clear the correct pointer, otherwise amdgpu_bo_unref clear the local variable, the original pointer not set to NULL, this could cause use-after-free bug.
--- drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.c | 14 +++++++------- drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.h | 2 +- drivers/gpu/drm/amd/amdkfd/kfd_chardev.c | 2 +- drivers/gpu/drm/amd/amdkfd/kfd_device.c | 4 ++-- .../gpu/drm/amd/amdkfd/kfd_device_queue_manager.c | 2 +- drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager.c | 2 +- drivers/gpu/drm/amd/amdkfd/kfd_process.c | 2 +- .../gpu/drm/amd/amdkfd/kfd_process_queue_manager.c | 4 ++-- 8 files changed, 16 insertions(+), 16 deletions(-)
drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.c +7 -7
@@ -364,15 +364,15 @@ int amdgpu_amdkfd_alloc_gtt_mem(struct amdgpu_device *adev, size_t size,return r; } -void amdgpu_amdkfd_free_gtt_mem (struct amdgpu_device *adev,void *mem_obj) +void amdgpu_amdkfd_free_gtt_mem (struct amdgpu_device *adev,void **mem_obj) { -struct amdgpu_bo *bo = (struct amdgpu_bo *) mem_obj; +struct amdgpu_bo **bo = (struct amdgpu_bo **) mem_obj; -amdgpu_bo_reserve (bo, true); -amdgpu_bo_kunmap (bo); -amdgpu_bo_unpin (bo); -amdgpu_bo_unreserve (bo); -amdgpu_bo_unref (&(bo)); +amdgpu_bo_reserve (*bo, true); +amdgpu_bo_kunmap (*bo); +amdgpu_bo_unpin (*bo); +amdgpu_bo_unreserve (*bo); +amdgpu_bo_unref (bo); } int amdgpu_amdkfd_alloc_gws(struct amdgpu_device *adev, size_t size,
drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.h +1 -1
@@ -235,7 +235,7 @@ int amdgpu_amdkfd_bo_validate_and_fence(struct amdgpu_bo *bo,int amdgpu_amdkfd_alloc_gtt_mem (struct amdgpu_device *adev,size_t size,void **mem_obj,uint64_t *gpu_addr,void **cpu_ptr,bool mqd_gfx9); -void amdgpu_amdkfd_free_gtt_mem (struct amdgpu_device *adev,void *mem_obj); +void amdgpu_amdkfd_free_gtt_mem (struct amdgpu_device *adev,void **mem_obj);int amdgpu_amdkfd_alloc_gws (struct amdgpu_device *adev,size_t size,void **mem_obj);void amdgpu_amdkfd_free_gws (struct amdgpu_device *adev,void *mem_obj);
drivers/gpu/drm/amd/amdkfd/kfd_chardev.c +1 -1
@@ -423,7 +423,7 @@ static int kfd_ioctl_create_queue(struct file *filep, struct kfd_process *p, err_create_queue:if (wptr_bo) -amdgpu_amdkfd_free_gtt_mem (dev->adev, wptr_bo); +amdgpu_amdkfd_free_gtt_mem (dev->adev, (void **)&wptr_bo); err_wptr_map_gart: err_bind_process: err_pdd:
drivers/gpu/drm/amd/amdkfd/kfd_device.c +2 -2
@@ -907,7 +907,7 @@ bool kgd2kfd_device_init(struct kfd_dev *kfd, kfd_doorbell_error:kfd_gtt_sa_fini (kfd); kfd_gtt_sa_init_error: -amdgpu_amdkfd_free_gtt_mem (kfd->adev, kfd->gtt_mem); +amdgpu_amdkfd_free_gtt_mem (kfd->adev, &kfd->gtt_mem); alloc_gtt_mem_failure: dev_err(kfd_device, "device %x:%x NOT added due to errors\n",
@@ -925,7 +925,7 @@ void kgd2kfd_device_exit(struct kfd_dev *kfd)kfd_doorbell_fini (kfd);ida_destroy (&kfd->doorbell_ida);kfd_gtt_sa_fini (kfd); -amdgpu_amdkfd_free_gtt_mem (kfd->adev, kfd->gtt_mem); +amdgpu_amdkfd_free_gtt_mem (kfd->adev, &kfd->gtt_mem); }kfree (kfd);
drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c +1 -1
@@ -2621,7 +2621,7 @@ static void deallocate_hiq_sdma_mqd(struct kfd_node *dev, {WARN (!mqd,"No hiq sdma mqd trunk to free" ); -amdgpu_amdkfd_free_gtt_mem (dev->adev, mqd->gtt_mem); +amdgpu_amdkfd_free_gtt_mem (dev->adev, &mqd->gtt_mem); }void device_queue_manager_uninit (struct device_queue_manager *dqm)
drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager.c +1 -1
@@ -225,7 +225,7 @@ void kfd_free_mqd_cp(struct mqd_manager *mm, void *mqd, struct kfd_mem_obj *mqd_mem_obj) {if (mqd_mem_obj->gtt_mem) { -amdgpu_amdkfd_free_gtt_mem (mm->dev->adev, mqd_mem_obj->gtt_mem); +amdgpu_amdkfd_free_gtt_mem (mm->dev->adev, &mqd_mem_obj->gtt_mem);kfree (mqd_mem_obj); }else {kfd_gtt_sa_free (mm->dev, mqd_mem_obj);
drivers/gpu/drm/amd/amdkfd/kfd_process.c +1 -1
@@ -1048,7 +1048,7 @@ static void kfd_process_destroy_pdds(struct kfd_process *p)if (pdd->dev->kfd->shared_resources.enable_mes)amdgpu_amdkfd_free_gtt_mem (pdd->dev->adev, - pdd->proc_ctx_bo); + &pdd->proc_ctx_bo);/* * before destroying pdd, make sure to report availability * for auto suspend
drivers/gpu/drm/amd/amdkfd/kfd_process_queue_manager.c +2 -2
@@ -204,9 +204,9 @@ static void pqm_clean_queue_resource(struct process_queue_manager *pqm, }if (dev->kfd->shared_resources.enable_mes) { -amdgpu_amdkfd_free_gtt_mem (dev->adev, pqn->q->gang_ctx_bo); +amdgpu_amdkfd_free_gtt_mem (dev->adev, &pqn->q->gang_ctx_bo);if (pqn->q->wptr_bo) -amdgpu_amdkfd_free_gtt_mem (dev->adev, pqn->q->wptr_bo); +amdgpu_amdkfd_free_gtt_mem (dev->adev, (void **)&pqn->q->wptr_bo); } }
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 209/558 drm/amd/display: Add null check for head_pipe in dcn201_acquire_free_pipe_for_layer
In reply to Greg Kroah-Hartman6.11-stable review patch. If anyone has any objections, please let me know.
------------------
From: Srinivasan Shanmugam <[email protected]>
[ Upstream commit f22f4754aaa47d8c59f166ba3042182859e5dff7 ]
This commit addresses a potential null pointer dereference issue in the dcn201_acquire_free_pipe_for_layer function. The issue could occur when head_pipe is null.
The fix adds a check to ensure head_pipe is not null before asserting it. If head_pipe is null, the function returns NULL to prevent a potential null pointer dereference.
Reported by smatch:drivers/gpu/drm/amd/amdgpu/../display/dc/resource/dcn201/dcn201_resource.c:1016 dcn201_acquire_free_pipe_for_layer() error: we previously assumed 'head_pipe' could be null (see line 1010)
--- .../gpu/drm/amd/display/dc/resource/dcn201/dcn201_resource.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
drivers/gpu/drm/amd/display/dc/resource/dcn201/dcn201_resource.c +3 -1
@@ -1007,8 +1007,10 @@ static struct pipe_ctx *dcn201_acquire_free_pipe_for_layer(struct pipe_ctx *head_pipe =resource_get_otg_master_for_stream (res_ctx, opp_head_pipe->stream);struct pipe_ctx *idle_pipe =resource_find_free_secondary_pipe_legacy (res_ctx, pool, head_pipe); -if (!head_pipe) +if (!head_pipe) {ASSERT (0 ); +return NULL ; + }if (!idle_pipe)return NULL ;
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 210/558 drm/amd/display: Add null check for head_pipe in dcn32_acquire_idle_pipe_for_head_pipe_in_layer
In reply to Greg Kroah-Hartman6.11-stable review patch. If anyone has any objections, please let me know.
------------------
From: Srinivasan Shanmugam <[email protected]>
[ Upstream commit ac2140449184a26eac99585b7f69814bd3ba8f2d ]
This commit addresses a potential null pointer dereference issue in the dcn32_acquire_idle_pipe_for_head_pipe_in_layer function. The issue could occur when head_pipe is null.
The fix adds a check to ensure head_pipe is not null before asserting it. If head_pipe is null, the function returns NULL to prevent a potential null pointer dereference.
Reported by smatch:drivers/gpu/drm/amd/amdgpu/../display/dc/resource/dcn32/dcn32_resource.c:2690 dcn32_acquire_idle_pipe_for_head_pipe_in_layer() error: we previously assumed 'head_pipe' could be null (see line 2681)
--- .../gpu/drm/amd/display/dc/resource/dcn32/dcn32_resource.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
drivers/gpu/drm/amd/display/dc/resource/dcn32/dcn32_resource.c +3 -1
@@ -2674,8 +2674,10 @@ static struct pipe_ctx *dcn32_acquire_idle_pipe_for_head_pipe_in_layer(struct resource_context *old_ctx = &stream->ctx->dc->current_state->res_ctx;int head_index; -if (!head_pipe) +if (!head_pipe) {ASSERT (0 ); +return NULL ; + }/* * Modified from dcn20_acquire_idle_pipe_for_layer
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 211/558 drm/amd/display: Add NULL check for clk_mgr and clk_mgr->funcs in dcn30_init_hw
In reply to Greg Kroah-Hartman6.11-stable review patch. If anyone has any objections, please let me know.
------------------
From: Srinivasan Shanmugam <[email protected]>
[ Upstream commit cba7fec864172dadd953daefdd26e01742b71a6a ]
This commit addresses a potential null pointer dereference issue in the dcn30_init_hw function. The issue could occur when dc->clk_mgr or dc->clk_mgr->funcs is null.
The fix adds a check to ensure dc->clk_mgr and dc->clk_mgr->funcs is not null before accessing its functions. This prevents a potential null pointer dereference.
Reported by smatch:drivers/gpu/drm/amd/amdgpu/../display/dc/hwss/dcn30/dcn30_hwseq.c:789 dcn30_init_hw() error: we previously assumed 'dc->clk_mgr' could be null (see line 628)
--- drivers/gpu/drm/amd/display/dc/hwss/dcn30/dcn30_hwseq.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-)
drivers/gpu/drm/amd/display/dc/hwss/dcn30/dcn30_hwseq.c +4 -3
@@ -629,7 +629,7 @@ void dcn30_init_hw(struct dc *dc)uint32_t backlight =MAX_BACKLIGHT_LEVEL ;uint32_t user_level =MAX_BACKLIGHT_LEVEL ; -if (dc->clk_mgr && dc->clk_mgr->funcs->init_clocks) +if (dc->clk_mgr && dc->clk_mgr->funcs && dc->clk_mgr->funcs->init_clocks) dc->clk_mgr->funcs->init_clocks (dc->clk_mgr);// Initialize the dccg
@@ -790,11 +790,12 @@ void dcn30_init_hw(struct dc *dc)if (!dcb->funcs->is_accelerated_mode (dcb) && dc->res_pool->hubbub->funcs->init_watermarks) dc->res_pool->hubbub->funcs->init_watermarks (dc->res_pool->hubbub); -if (dc->clk_mgr->funcs->notify_wm_ranges) +if (dc->clk_mgr && dc->clk_mgr->funcs && dc->clk_mgr->funcs->notify_wm_ranges) dc->clk_mgr->funcs->notify_wm_ranges (dc->clk_mgr);//if softmax is enabled then hardmax will be set by a different call -if (dc->clk_mgr->funcs->set_hard_max_memclk && !dc->clk_mgr->dc_mode_softmax_enabled) +if (dc->clk_mgr && dc->clk_mgr->funcs && dc->clk_mgr->funcs->set_hard_max_memclk && + !dc->clk_mgr->dc_mode_softmax_enabled) dc->clk_mgr->funcs->set_hard_max_memclk (dc->clk_mgr);if (dc->res_pool->hubbub->funcs->force_pstate_change_control)
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 212/558 drm/amd/display: Add NULL check for clk_mgr and clk_mgr->funcs in dcn401_init_hw
In reply to Greg Kroah-Hartman6.11-stable review patch. If anyone has any objections, please let me know.
------------------
From: Srinivasan Shanmugam <[email protected]>
[ Upstream commit 4b6377f0e96085cbec96eb7f0b282430ccdd3d75 ]
This commit addresses a potential null pointer dereference issue in the dcn401_init_hw function. The issue could occur when dc->clk_mgr or dc->clk_mgr->funcs is null.
The fix adds a check to ensure dc->clk_mgr and dc->clk_mgr->funcs is not null before accessing its functions. This prevents a potential null pointer dereference.
Reported by smatch:drivers/gpu/drm/amd/amdgpu/../display/dc/hwss/dcn401/dcn401_hwseq.c:416 dcn401_init_hw() error: we previously assumed 'dc->clk_mgr' could be null (see line 225)
--- drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_hwseq.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-)
drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_hwseq.c +5 -3
@@ -222,7 +222,7 @@ void dcn401_init_hw(struct dc *dc)uint32_t backlight =MAX_BACKLIGHT_LEVEL ;uint32_t user_level =MAX_BACKLIGHT_LEVEL ; -if (dc->clk_mgr && dc->clk_mgr->funcs->init_clocks) { +if (dc->clk_mgr && dc->clk_mgr->funcs && dc->clk_mgr->funcs->init_clocks) { dc->clk_mgr->funcs->init_clocks (dc->clk_mgr);// mark dcmode limits present if any clock has distinct AC and DC values from SMU
@@ -413,7 +413,7 @@ void dcn401_init_hw(struct dc *dc)if (!dcb->funcs->is_accelerated_mode (dcb) && dc->res_pool->hubbub->funcs->init_watermarks) dc->res_pool->hubbub->funcs->init_watermarks (dc->res_pool->hubbub); -if (dc->clk_mgr->funcs->notify_wm_ranges) +if (dc->clk_mgr && dc->clk_mgr->funcs && dc->clk_mgr->funcs->notify_wm_ranges) dc->clk_mgr->funcs->notify_wm_ranges (dc->clk_mgr);if (dc->clk_mgr->funcs->set_hard_max_memclk && !dc->clk_mgr->dc_mode_softmax_enabled)
@@ -438,7 +438,9 @@ void dcn401_init_hw(struct dc *dc) dc->debug.fams2_config.bits.enable &= dc->ctx->dmub_srv->dmub->feature_caps.fw_assisted_mclk_switch_ver ==2 ;if (!dc->debug.fams2_config.bits.enable && dc->res_pool->funcs->update_bw_bounding_box) {/* update bounding box if FAMS2 disabled */ - dc->res_pool->funcs->update_bw_bounding_box (dc, dc->clk_mgr->bw_params); +if (dc->clk_mgr) + dc->res_pool->funcs->update_bw_bounding_box (dc, + dc->clk_mgr->bw_params); } } }
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 213/558 drm/amd/display: Add NULL check for clk_mgr in dcn32_init_hw
In reply to Greg Kroah-Hartman6.11-stable review patch. If anyone has any objections, please let me know.
------------------
From: Srinivasan Shanmugam <[email protected]>
[ Upstream commit c395fd47d1565bd67671f45cca281b3acc2c31ef ]
This commit addresses a potential null pointer dereference issue in the dcn32_init_hw function. The issue could occur when dc->clk_mgr is null.
The fix adds a check to ensure dc->clk_mgr is not null before accessing its functions. This prevents a potential null pointer dereference.
Reported by smatch:drivers/gpu/drm/amd/amdgpu/../display/dc/hwss/dcn32/dcn32_hwseq.c:961 dcn32_init_hw() error: we previously assumed 'dc->clk_mgr' could be null (see line 782)
--- drivers/gpu/drm/amd/display/dc/hwss/dcn32/dcn32_hwseq.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-)
drivers/gpu/drm/amd/display/dc/hwss/dcn32/dcn32_hwseq.c +4 -3
@@ -779,7 +779,7 @@ void dcn32_init_hw(struct dc *dc)uint32_t backlight =MAX_BACKLIGHT_LEVEL ;uint32_t user_level =MAX_BACKLIGHT_LEVEL ; -if (dc->clk_mgr && dc->clk_mgr->funcs->init_clocks) +if (dc->clk_mgr && dc->clk_mgr->funcs && dc->clk_mgr->funcs->init_clocks) dc->clk_mgr->funcs->init_clocks (dc->clk_mgr);// Initialize the dccg
@@ -958,10 +958,11 @@ void dcn32_init_hw(struct dc *dc)if (!dcb->funcs->is_accelerated_mode (dcb) && dc->res_pool->hubbub->funcs->init_watermarks) dc->res_pool->hubbub->funcs->init_watermarks (dc->res_pool->hubbub); -if (dc->clk_mgr->funcs->notify_wm_ranges) +if (dc->clk_mgr && dc->clk_mgr->funcs && dc->clk_mgr->funcs->notify_wm_ranges) dc->clk_mgr->funcs->notify_wm_ranges (dc->clk_mgr); -if (dc->clk_mgr->funcs->set_hard_max_memclk && !dc->clk_mgr->dc_mode_softmax_enabled) +if (dc->clk_mgr && dc->clk_mgr->funcs && dc->clk_mgr->funcs->set_hard_max_memclk && + !dc->clk_mgr->dc_mode_softmax_enabled) dc->clk_mgr->funcs->set_hard_max_memclk (dc->clk_mgr);if (dc->res_pool->hubbub->funcs->force_pstate_change_control)
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 214/558 drm/xe/hdcp: Check GSC structure validity
In reply to Greg Kroah-Hartman6.11-stable review patch. If anyone has any objections, please let me know.
------------------
From: Suraj Kandpal <[email protected]>
[ Upstream commit b4224f6bae3801d589f815672ec62800a1501b0d ]
Sometimes xe_gsc is not initialized when checked at HDCP capability check. Add gsc structure check to avoid null pointer error.
--- drivers/gpu/drm/xe/display/xe_hdcp_gsc.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-)
drivers/gpu/drm/xe/display/xe_hdcp_gsc.c +6 -2
@@ -40,10 +40,14 @@ bool intel_hdcp_gsc_check_status(struct xe_device *xe) {struct xe_tile *tile =xe_device_get_root_tile (xe);struct xe_gt *gt = tile->media_gt; +struct xe_gsc *gsc = >->uc.gsc;bool ret = true; -if (!xe_uc_fw_is_enabled (>->uc.gsc.fw)) +if (!gsc && !xe_uc_fw_is_enabled (&gsc->fw)) { +drm_dbg_kms (&xe->drm, +"GSC Components not ready for HDCP2.x\n" );return false; + }xe_pm_runtime_get (xe);if (xe_force_wake_get (gt_to_fw (gt),XE_FW_GSC )) {
@@ -53,7 +57,7 @@ bool intel_hdcp_gsc_check_status(struct xe_device *xe) goto out; } -if (!xe_gsc_proxy_init_done (>->uc.gsc)) +if (!xe_gsc_proxy_init_done (gsc)) ret = false;xe_force_wake_put (gt_to_fw (gt),XE_FW_GSC );
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 215/558 drm/amd/display: Add null check for pipe_ctx->plane_state in dcn20_program_pipe
In reply to Greg Kroah-Hartman6.11-stable review patch. If anyone has any objections, please let me know.
------------------
From: Srinivasan Shanmugam <[email protected]>
[ Upstream commit 8e4ed3cf1642df0c4456443d865cff61a9598aa8 ]
This commit addresses a null pointer dereference issue in the dcn20_program_pipe function. The issue could occur when pipe_ctx->plane_state is null.
The fix adds a check to ensure pipe_ctx->plane_state is not null before accessing. This prevents a null pointer dereference.
Reported by smatch:drivers/gpu/drm/amd/amdgpu/../display/dc/hwss/dcn20/dcn20_hwseq.c:1925 dcn20_program_pipe() error: we previously assumed 'pipe_ctx->plane_state' could be null (see line 1877)
--- .../amd/display/dc/hwss/dcn20/dcn20_hwseq.c | 30 ++++++++++++------- 1 file changed, 19 insertions(+), 11 deletions(-)
drivers/gpu/drm/amd/display/dc/hwss/dcn20/dcn20_hwseq.c +19 -11
@@ -1921,22 +1921,29 @@ static void dcn20_program_pipe( dc->res_pool->hubbub, pipe_ctx->plane_res.hubp->inst, pipe_ctx->hubp_regs.det_size); } -if (pipe_ctx->update_flags.raw || pipe_ctx->plane_state->update_flags.raw || pipe_ctx->stream->update_flags.raw) +if (pipe_ctx->update_flags.raw || + (pipe_ctx->plane_state && pipe_ctx->plane_state->update_flags.raw) || + pipe_ctx->stream->update_flags.raw)dcn20_update_dchubp_dpp (dc, pipe_ctx, context); -if (pipe_ctx->update_flags.bits.enable - || pipe_ctx->plane_state->update_flags.bits.hdr_mult) +if (pipe_ctx->update_flags.bits.enable || + (pipe_ctx->plane_state && pipe_ctx->plane_state->update_flags.bits.hdr_mult)) hws->funcs.set_hdr_multiplier (pipe_ctx);if (hws->funcs.populate_mcm_luts) { - hws->funcs.populate_mcm_luts (dc, pipe_ctx, pipe_ctx->plane_state->mcm_luts, - pipe_ctx->plane_state->lut_bank_a); - pipe_ctx->plane_state->lut_bank_a = !pipe_ctx->plane_state->lut_bank_a; +if (pipe_ctx->plane_state) { + hws->funcs.populate_mcm_luts (dc, pipe_ctx, pipe_ctx->plane_state->mcm_luts, + pipe_ctx->plane_state->lut_bank_a); + pipe_ctx->plane_state->lut_bank_a = !pipe_ctx->plane_state->lut_bank_a; + } }if (pipe_ctx->update_flags.bits.enable || - pipe_ctx->plane_state->update_flags.bits.in_transfer_func_change || - pipe_ctx->plane_state->update_flags.bits.gamma_change || - pipe_ctx->plane_state->update_flags.bits.lut_3d) + (pipe_ctx->plane_state && + pipe_ctx->plane_state->update_flags.bits.in_transfer_func_change) || + (pipe_ctx->plane_state && + pipe_ctx->plane_state->update_flags.bits.gamma_change) || + (pipe_ctx->plane_state && + pipe_ctx->plane_state->update_flags.bits.lut_3d)) hws->funcs.set_input_transfer_func (dc, pipe_ctx, pipe_ctx->plane_state);/* dcn10_translate_regamma_to_hw_format takes 750us to finish
@@ -1946,7 +1953,8 @@ static void dcn20_program_pipe(if (pipe_ctx->update_flags.bits.enable || pipe_ctx->update_flags.bits.plane_changed || pipe_ctx->stream->update_flags.bits.out_tf || - pipe_ctx->plane_state->update_flags.bits.output_tf_change) + (pipe_ctx->plane_state && + pipe_ctx->plane_state->update_flags.bits.output_tf_change)) hws->funcs.set_output_transfer_func (dc, pipe_ctx, pipe_ctx->stream);/* If the pipe has been enabled or has a different opp, we
@@ -1970,7 +1978,7 @@ static void dcn20_program_pipe( }/* Set ABM pipe after other pipe configurations done */ -if (pipe_ctx->plane_state->visible) { +if ((pipe_ctx->plane_state && pipe_ctx->plane_state->visible)) {if (pipe_ctx->stream_res.abm) { dc->hwss.set_pipe (pipe_ctx); pipe_ctx->stream_res.abm->funcs->set_abm_level(pipe_ctx->stream_res.abm,
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 216/558 drm/amd/display: Add null check for top_pipe_to_program in commit_planes_for_stream
In reply to Greg Kroah-Hartman6.11-stable review patch. If anyone has any objections, please let me know.
------------------
From: Srinivasan Shanmugam <[email protected]>
[ Upstream commit 66d71a72539e173a9b00ca0b1852cbaa5f5bf1ad ]
This commit addresses a null pointer dereference issue in the commit_planes_for_stream function at line 4140. The issue could occur when top_pipe_to_program is null.
The fix adds a check to ensure top_pipe_to_program is not null before accessing its stream_res. This prevents a null pointer dereference.
Reported by smatch:drivers/gpu/drm/amd/amdgpu/../display/dc/core/dc.c:4140 commit_planes_for_stream() error: we previously assumed 'top_pipe_to_program' could be null (see line 3906)
--- drivers/gpu/drm/amd/display/dc/core/dc.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
drivers/gpu/drm/amd/display/dc/core/dc.c +2 -1
@@ -4127,7 +4127,8 @@ static void commit_planes_for_stream(struct dc *dc, }if ((update_type !=UPDATE_TYPE_FAST ) && stream->update_flags.bits.dsc_changed) -if (top_pipe_to_program->stream_res.tg->funcs->lock_doublebuffer_enable) { +if (top_pipe_to_program && + top_pipe_to_program->stream_res.tg->funcs->lock_doublebuffer_enable) { top_pipe_to_program->stream_res.tg->funcs->wait_for_state ( top_pipe_to_program->stream_res.tg,CRTC_STATE_VACTIVE );
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 217/558 drm/amd/display: Use gpuvm_min_page_size_kbytes for DML2 surfaces
In reply to Greg Kroah-Hartman6.11-stable review patch. If anyone has any objections, please let me know.
------------------
From: Nicholas Kazlauskas <[email protected]>
[ Upstream commit 31663521ede2edb622ee1b397ae3ac666d6351c5 ]
[Why]
It's currently hard coded to 256 when it should be using the SOC provided values. This can result in corruption with linear surfaces where we prefetch more PTE than the buffer can hold.
[How]
Update the min page size correctly for the plane.
--- .../display/dc/dml2/dml2_translation_helper.c | 20 +++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-)
drivers/gpu/drm/amd/display/dc/dml2/dml2_translation_helper.c +14 -6
@@ -953,7 +953,9 @@ static void get_scaler_data_for_plane(const struct dc_plane_state *in, struct dcmemcpy (out, &temp_pipe->plane_res.scl_data,sizeof (*out)); } -static void populate_dummy_dml_plane_cfg (struct dml_plane_cfg_st *out,unsigned int location,const struct dc_stream_state *in) +static void populate_dummy_dml_plane_cfg (struct dml_plane_cfg_st *out,unsigned int location, +const struct dc_stream_state *in, +const struct soc_bounding_box_st *soc) {dml_uint_t width, height;
@@ -970,7 +972,7 @@ static void populate_dummy_dml_plane_cfg(struct dml_plane_cfg_st *out, unsigned out->CursorBPP[location] = dml_cur_32bit; out->CursorWidth[location] =256 ; - out->GPUVMMinPageSizeKBytes[location] =256 ; + out->GPUVMMinPageSizeKBytes[location] = soc->gpuvm_min_page_size_kbytes; out->ViewportWidth[location] = width; out->ViewportHeight[location] = height;
@@ -1007,7 +1009,9 @@ static void populate_dummy_dml_plane_cfg(struct dml_plane_cfg_st *out, unsigned out->ScalerEnabled[location] = false; } -static void populate_dml_plane_cfg_from_plane_state (struct dml_plane_cfg_st *out,unsigned int location,const struct dc_plane_state *in,struct dc_state *context) +static void populate_dml_plane_cfg_from_plane_state (struct dml_plane_cfg_st *out,unsigned int location, +const struct dc_plane_state *in,struct dc_state *context, +const struct soc_bounding_box_st *soc) {struct scaler_data *scaler_data =kzalloc (sizeof (*scaler_data),GFP_KERNEL );if (!scaler_data)
@@ -1018,7 +1022,7 @@ static void populate_dml_plane_cfg_from_plane_state(struct dml_plane_cfg_st *out out->CursorBPP[location] = dml_cur_32bit; out->CursorWidth[location] =256 ; - out->GPUVMMinPageSizeKBytes[location] =256 ; + out->GPUVMMinPageSizeKBytes[location] = soc->gpuvm_min_page_size_kbytes; out->ViewportWidth[location] = scaler_data->viewport.width; out->ViewportHeight[location] = scaler_data->viewport.height;
@@ -1299,7 +1303,8 @@ void map_dc_state_into_dml_display_cfg(struct dml2_context *dml2, struct dc_stat disp_cfg_plane_location = dml_dispcfg->num_surfaces++;populate_dummy_dml_surface_cfg (&dml_dispcfg->surface, disp_cfg_plane_location, context->streams[i]); -populate_dummy_dml_plane_cfg (&dml_dispcfg->plane, disp_cfg_plane_location, context->streams[i]); +populate_dummy_dml_plane_cfg (&dml_dispcfg->plane, disp_cfg_plane_location, + context->streams[i], &dml2->v20.dml_core_ctx.soc); dml_dispcfg->plane.BlendingAndTiming[disp_cfg_plane_location] = disp_cfg_stream_location;
@@ -1315,7 +1320,10 @@ void map_dc_state_into_dml_display_cfg(struct dml2_context *dml2, struct dc_statASSERT (disp_cfg_plane_location >=0 && disp_cfg_plane_location <= __DML2_WRAPPER_MAX_STREAMS_PLANES__);populate_dml_surface_cfg_from_plane_state (dml2->v20.dml_core_ctx.project, &dml_dispcfg->surface, disp_cfg_plane_location, context->stream_status[i].plane_states[j]); -populate_dml_plane_cfg_from_plane_state (&dml_dispcfg->plane, disp_cfg_plane_location, context->stream_status[i].plane_states[j], context); +populate_dml_plane_cfg_from_plane_state ( + &dml_dispcfg->plane, disp_cfg_plane_location, + context->stream_status[i].plane_states[j], context, + &dml2->v20.dml_core_ctx.soc);if (stream_mall_type ==SUBVP_MAIN ) { dml_dispcfg->plane.UseMALLForPStateChange[disp_cfg_plane_location] = dml_use_mall_pstate_change_sub_viewport;
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 218/558 ata: pata_serverworks: Do not use the term blacklist
In reply to Greg Kroah-Hartman6.11-stable review patch. If anyone has any objections, please let me know.
------------------
From: Damien Le Moal <[email protected]>
[ Upstream commit 858048568c9e3887d8b19e101ee72f129d65cb15 ]
Let's not use the term blacklist in the function serverworks_osb4_filter() documentation comment and rather simply refer to what that function looks at: the list of devices with groken UDMA5.
While at it, also constify the values of the csb_bad_ata100 array.
Of note is that all of this should probably be handled using libata quirk mechanism but it is unclear if these UDMA5 quirks are specific to this controller only.
--- drivers/ata/pata_serverworks.c | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-)
drivers/ata/pata_serverworks.c +9 -7
@@ -46,10 +46,11 @@#define SVWKS_CSB5_REVISION_NEW 0x92/* min PCI_REVISION_ID for UDMA5 (A2.0) */ #define SVWKS_CSB6_REVISION 0xa0/* min PCI_REVISION_ID for UDMA4 (A1.0) */ -/* Seagate Barracuda ATA IV Family drives in UDMA mode 5 -* can overrun their FIFOs when used with the CSB5 */ - -static const char *csb_bad_ata100[] = { +/* +* Seagate Barracuda ATA IV Family drives in UDMA mode 5 +* can overrun their FIFOs when used with the CSB5. +*/ +static const char *const csb_bad_ata100[] = {"ST320011A" ,"ST340016A" ,"ST360021A" ,
@@ -163,10 +164,11 @@ static unsigned int serverworks_osb4_filter(struct ata_device *adev, unsigned in* @adev: ATA device * @mask: Mask of proposed modes * -* Check the blacklist and disable UDMA5 if matched +* Check the list of devices with broken UDMA5 and +* disable UDMA5 if matched. */ - -static unsigned int serverworks_csb_filter (struct ata_device *adev,unsigned int mask) +static unsigned int serverworks_csb_filter (struct ata_device *adev, +unsigned int mask) {const char *p;char model_num[ATA_ID_PROD_LEN +1 ];
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 219/558 ata: sata_sil: Rename sil_blacklist to sil_quirks
In reply to Greg Kroah-Hartman6.11-stable review patch. If anyone has any objections, please let me know.
------------------
From: Damien Le Moal <[email protected]>
[ Upstream commit 93b0f9e11ce511353c65b7f924cf5f95bd9c3aba ]
Rename the array sil_blacklist to sil_quirks as this name is more neutral and is also consistent with how this driver define quirks with the SIL_QUIRK_XXX flags.
--- drivers/ata/sata_sil.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-)
drivers/ata/sata_sil.c +6 -6
@@ -128,7 +128,7 @@ static const struct pci_device_id sil_pci_tbl[] = {static const struct sil_drivelist {const char *product;unsigned int quirk; -} sil_blacklist [] = { +} sil_quirks[] = { {"ST320012AS" ,SIL_QUIRK_MOD15WRITE }, {"ST330013AS" ,SIL_QUIRK_MOD15WRITE }, {"ST340017AS" ,SIL_QUIRK_MOD15WRITE },
@@ -600,8 +600,8 @@ static void sil_thaw(struct ata_port *ap)* list, and apply the fixups to only the specific * devices/hosts/firmwares that need it. * -* 20040111 - Seagate drives affected by the Mod15Write bug are blacklisted -* The Maxtor quirk is in the blacklist, but I'm keeping the original +* 20040111 - Seagate drives affected by the Mod15Write bug are quirked +* The Maxtor quirk is in sil_quirks, but I'm keeping the original * pessimistic fix for the following reasons... * - There seems to be less info on it, only one device gleaned off the * Windows driver, maybe only one is affected. More info would be greatly
@@ -620,9 +620,9 @@ static void sil_dev_config(struct ata_device *dev)ata_id_c_string (dev->id, model_num,ATA_ID_PROD ,sizeof (model_num)); -for (n =0 ; sil_blacklist[n].product; n++) -if (!strcmp (sil_blacklist[n].product, model_num)) { - quirks = sil_blacklist[n].quirk; +for (n =0 ; sil_quirks[n].product; n++) +if (!strcmp (sil_quirks[n].product, model_num)) { + quirks = sil_quirks[n].quirk;break ; }
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 220/558 selftests/bpf: fix uprobe.path leak in bpf_testmod
In reply to Greg Kroah-Hartman6.11-stable review patch. If anyone has any objections, please let me know.
------------------
From: Jiri Olsa <[email protected]>
[ Upstream commit db61e6a4eee5a7884b2cafeaf407895f253bbaa7 ]
testmod_unregister_uprobe() forgets to path_put(&uprobe.path).
--- tools/testing/selftests/bpf/bpf_testmod/bpf_testmod.c | 1 + 1 file changed, 1 insertion(+)
tools/testing/selftests/bpf/bpf_testmod/bpf_testmod.c +1 -0
@@ -477,6 +477,7 @@ static void testmod_unregister_uprobe(void)if (uprobe.offset) {uprobe_unregister (d_real_inode (uprobe.path.dentry), uprobe.offset, &uprobe.consumer); +path_put (&uprobe.path); uprobe.offset =0 ; }
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 221/558 scsi: smartpqi: Add new controller PCI IDs
In reply to Greg Kroah-Hartman6.11-stable review patch. If anyone has any objections, please let me know.
------------------
From: David Strahan <[email protected]>
[ Upstream commit 0e21e73384d324f75ea16f3d622cfc433fa6209b ]
All PCI ID entries in hex.
Add new inagile PCI IDs:
VID / DID / SVID / SDID
---- ---- ---- ----
SMART-HBA 8242-24i 9005 / 028f / 1ff9 / 0045
RAID 8236-16i 9005 / 028f / 1ff9 / 0046
RAID 8240-24i 9005 / 028f / 1ff9 / 0047
SMART-HBA 8238-16i 9005 / 028f / 1ff9 / 0048
PM8222-SHBA 9005 / 028f / 1ff9 / 004a
RAID PM8204-2GB 9005 / 028f / 1ff9 / 004b
RAID PM8204-4GB 9005 / 028f / 1ff9 / 004c
PM8222-HBA 9005 / 028f / 1ff9 / 004f
MT0804M6R 9005 / 028f / 1ff9 / 0051
MT0801M6E 9005 / 028f / 1ff9 / 0052
MT0808M6R 9005 / 028f / 1ff9 / 0053
MT0800M6H 9005 / 028f / 1ff9 / 0054
RS0800M5H24i 9005 / 028f / 1ff9 / 006b
RS0800M5E8i 9005 / 028f / 1ff9 / 006c
RS0800M5H8i 9005 / 028f / 1ff9 / 006d
RS0804M5R16i 9005 / 028f / 1ff9 / 006f
RS0800M5E24i 9005 / 028f / 1ff9 / 0070
RS0800M5H16i 9005 / 028f / 1ff9 / 0071
RS0800M5E16i 9005 / 028f / 1ff9 / 0072
RT0800M7E 9005 / 028f / 1ff9 / 0086
RT0800M7H 9005 / 028f / 1ff9 / 0087
RT0804M7R 9005 / 028f / 1ff9 / 0088
RT0808M7R 9005 / 028f / 1ff9 / 0089
RT1608M6R16i 9005 / 028f / 1ff9 / 00a1Add new h3c pci_id:
VID / DID / SVID / SDID
---- ---- ---- ----
UN RAID P4408-Mr-2 9005 / 028f / 193d / 1110Add new powerleader pci ids:
VID / DID / SVID / SDID
---- ---- ---- ----
PL SmartROC PM8204 9005 / 028f / 1f3a / 0104--- drivers/scsi/smartpqi/smartpqi_init.c | 104 ++++++++++++++++++++++++++ 1 file changed, 104 insertions(+)
drivers/scsi/smartpqi/smartpqi_init.c +104 -0
@@ -9456,6 +9456,10 @@ static const struct pci_device_id pqi_pci_id_table[] = {PCI_DEVICE_SUB (PCI_VENDOR_ID_ADAPTEC2 ,0x028f ,0x193d ,0x110b ) }, + { +PCI_DEVICE_SUB (PCI_VENDOR_ID_ADAPTEC2 ,0x028f , +0x193d ,0x1110 ) + }, {PCI_DEVICE_SUB (PCI_VENDOR_ID_ADAPTEC2 ,0x028f ,0x193d ,0x8460 )
@@ -9572,6 +9576,14 @@ static const struct pci_device_id pqi_pci_id_table[] = {PCI_DEVICE_SUB (PCI_VENDOR_ID_ADAPTEC2 ,0x028f ,0x1bd4 ,0x0089 ) }, + { +PCI_DEVICE_SUB (PCI_VENDOR_ID_ADAPTEC2 ,0x028f , +0x1ff9 ,0x00a1 ) + }, + { +PCI_DEVICE_SUB (PCI_VENDOR_ID_ADAPTEC2 ,0x028f , +0x1f3a ,0x0104 ) + }, {PCI_DEVICE_SUB (PCI_VENDOR_ID_ADAPTEC2 ,0x028f ,0x19e5 ,0xd227 )
@@ -10164,6 +10176,98 @@ static const struct pci_device_id pqi_pci_id_table[] = {PCI_DEVICE_SUB (PCI_VENDOR_ID_ADAPTEC2 ,0x028f ,0x1137 ,0x02fa ) }, + { +PCI_DEVICE_SUB (PCI_VENDOR_ID_ADAPTEC2 ,0x028f , +0x1ff9 ,0x0045 ) + }, + { +PCI_DEVICE_SUB (PCI_VENDOR_ID_ADAPTEC2 ,0x028f , +0x1ff9 ,0x0046 ) + }, + { +PCI_DEVICE_SUB (PCI_VENDOR_ID_ADAPTEC2 ,0x028f , +0x1ff9 ,0x0047 ) + }, + { +PCI_DEVICE_SUB (PCI_VENDOR_ID_ADAPTEC2 ,0x028f , +0x1ff9 ,0x0048 ) + }, + { +PCI_DEVICE_SUB (PCI_VENDOR_ID_ADAPTEC2 ,0x028f , +0x1ff9 ,0x004a ) + }, + { +PCI_DEVICE_SUB (PCI_VENDOR_ID_ADAPTEC2 ,0x028f , +0x1ff9 ,0x004b ) + }, + { +PCI_DEVICE_SUB (PCI_VENDOR_ID_ADAPTEC2 ,0x028f , +0x1ff9 ,0x004c ) + }, + { +PCI_DEVICE_SUB (PCI_VENDOR_ID_ADAPTEC2 ,0x028f , +0x1ff9 ,0x004f ) + }, + { +PCI_DEVICE_SUB (PCI_VENDOR_ID_ADAPTEC2 ,0x028f , +0x1ff9 ,0x0051 ) + }, + { +PCI_DEVICE_SUB (PCI_VENDOR_ID_ADAPTEC2 ,0x028f , +0x1ff9 ,0x0052 ) + }, + { +PCI_DEVICE_SUB (PCI_VENDOR_ID_ADAPTEC2 ,0x028f , +0x1ff9 ,0x0053 ) + }, + { +PCI_DEVICE_SUB (PCI_VENDOR_ID_ADAPTEC2 ,0x028f , +0x1ff9 ,0x0054 ) + }, + { +PCI_DEVICE_SUB (PCI_VENDOR_ID_ADAPTEC2 ,0x028f , +0x1ff9 ,0x006b ) + }, + { +PCI_DEVICE_SUB (PCI_VENDOR_ID_ADAPTEC2 ,0x028f , +0x1ff9 ,0x006c ) + }, + { +PCI_DEVICE_SUB (PCI_VENDOR_ID_ADAPTEC2 ,0x028f , +0x1ff9 ,0x006d ) + }, + { +PCI_DEVICE_SUB (PCI_VENDOR_ID_ADAPTEC2 ,0x028f , +0x1ff9 ,0x006f ) + }, + { +PCI_DEVICE_SUB (PCI_VENDOR_ID_ADAPTEC2 ,0x028f , +0x1ff9 ,0x0070 ) + }, + { +PCI_DEVICE_SUB (PCI_VENDOR_ID_ADAPTEC2 ,0x028f , +0x1ff9 ,0x0071 ) + }, + { +PCI_DEVICE_SUB (PCI_VENDOR_ID_ADAPTEC2 ,0x028f , +0x1ff9 ,0x0072 ) + }, + { +PCI_DEVICE_SUB (PCI_VENDOR_ID_ADAPTEC2 ,0x028f , +0x1ff9 ,0x0086 ) + }, + { +PCI_DEVICE_SUB (PCI_VENDOR_ID_ADAPTEC2 ,0x028f , +0x1ff9 ,0x0087 ) + }, + { +PCI_DEVICE_SUB (PCI_VENDOR_ID_ADAPTEC2 ,0x028f , +0x1ff9 ,0x0088 ) + }, + { +PCI_DEVICE_SUB (PCI_VENDOR_ID_ADAPTEC2 ,0x028f , +0x1ff9 ,0x0089 ) + }, {PCI_DEVICE_SUB (PCI_VENDOR_ID_ADAPTEC2 ,0x028f ,0x1e93 ,0x1000 )
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 222/558 HID: Ignore battery for all ELAN I2C-HID devices
In reply to Greg Kroah-Hartman6.11-stable review patch. If anyone has any objections, please let me know.
------------------
From: Hans de Goede <[email protected]>
[ Upstream commit bcc31692a1d1e21f0d06c5f727c03ee299d2264e ]
Before this change there were 16 vid:pid based quirks to ignore the battery reported by Elan I2C-HID touchscreens on various Asus and HP laptops.
And a report has been received that the 04F3:2A00 I2C touchscreen on the HP ProBook x360 11 G5 EE/86CF also reports a non present battery.
Since I2C-HID devices are always builtin to laptops they are not battery owered so it should be safe to just ignore the battery on all Elan I2C-HID devices, rather then adding a 17th quirk for the 04F3:2A00 touchscreen.
As reported in the changelog of commit a3a5a37efba1 ("HID: Ignore battery for ELAN touchscreens 2F2C and 4116"), which added 2 new Elan touchscreen quirks about a month ago, the HID reported battery seems to be related to a stylus being used. But even when a stylus is in use it does not properly report the charge of the stylus battery, instead the reported battery charge jumps from 0% to 1%. So it is best to just ignore the HID battery.
--- drivers/hid/hid-ids.h | 16 ---------------- drivers/hid/hid-input.c | 37 +++++-------------------------------- 2 files changed, 5 insertions(+), 48 deletions(-)
drivers/hid/hid-ids.h +0 -16
@@ -417,24 +417,8 @@#define USB_DEVICE_ID_TOSHIBA_CLICK_L9W 0x0401#define USB_DEVICE_ID_HP_X2 0x074d#define USB_DEVICE_ID_HP_X2_10_COVER 0x0755 -#define I2C_DEVICE_ID_HP_ENVY_X360_15 0x2d05 -#define I2C_DEVICE_ID_HP_ENVY_X360_15T_DR100 0x29CF -#define I2C_DEVICE_ID_HP_ENVY_X360_EU0009NV 0x2CF9 -#define I2C_DEVICE_ID_HP_SPECTRE_X360_15 0x2817 -#define I2C_DEVICE_ID_HP_SPECTRE_X360_13_AW0020NG 0x29DF -#define I2C_DEVICE_ID_ASUS_TP420IA_TOUCHSCREEN 0x2BC8 -#define I2C_DEVICE_ID_ASUS_GV301RA_TOUCHSCREEN 0x2C82 -#define I2C_DEVICE_ID_ASUS_UX3402_TOUCHSCREEN 0x2F2C -#define I2C_DEVICE_ID_ASUS_UX6404_TOUCHSCREEN 0x4116#define USB_DEVICE_ID_ASUS_UX550VE_TOUCHSCREEN 0x2544#define USB_DEVICE_ID_ASUS_UX550_TOUCHSCREEN 0x2706 -#define I2C_DEVICE_ID_SURFACE_GO_TOUCHSCREEN 0x261A -#define I2C_DEVICE_ID_SURFACE_GO2_TOUCHSCREEN 0x2A1C -#define I2C_DEVICE_ID_LENOVO_YOGA_C630_TOUCHSCREEN 0x279F -#define I2C_DEVICE_ID_HP_SPECTRE_X360_13T_AW100 0x29F5 -#define I2C_DEVICE_ID_HP_SPECTRE_X360_14T_EA100_V1 0x2BED -#define I2C_DEVICE_ID_HP_SPECTRE_X360_14T_EA100_V2 0x2BEE -#define I2C_DEVICE_ID_HP_ENVY_X360_15_EU0556NG 0x2D02#define I2C_DEVICE_ID_CHROMEBOOK_TROGDOR_POMPOM 0x2F81#define USB_VENDOR_ID_ELECOM 0x056e
drivers/hid/hid-input.c +5 -32
@@ -373,14 +373,6 @@ static const struct hid_device_id hid_battery_quirks[] = { {HID_BLUETOOTH_DEVICE (USB_VENDOR_ID_LOGITECH ,USB_DEVICE_ID_LOGITECH_DINOVO_EDGE_KBD ), HID_BATTERY_QUIRK_IGNORE }, - { HID_I2C_DEVICE(USB_VENDOR_ID_ELAN, I2C_DEVICE_ID_ASUS_TP420IA_TOUCHSCREEN), - HID_BATTERY_QUIRK_IGNORE }, - { HID_I2C_DEVICE(USB_VENDOR_ID_ELAN, I2C_DEVICE_ID_ASUS_GV301RA_TOUCHSCREEN), - HID_BATTERY_QUIRK_IGNORE }, - { HID_I2C_DEVICE(USB_VENDOR_ID_ELAN, I2C_DEVICE_ID_ASUS_UX3402_TOUCHSCREEN), - HID_BATTERY_QUIRK_IGNORE }, - { HID_I2C_DEVICE(USB_VENDOR_ID_ELAN, I2C_DEVICE_ID_ASUS_UX6404_TOUCHSCREEN), - HID_BATTERY_QUIRK_IGNORE }, { HID_USB_DEVICE(USB_VENDOR_ID_ELAN, USB_DEVICE_ID_ASUS_UX550_TOUCHSCREEN), HID_BATTERY_QUIRK_IGNORE }, { HID_USB_DEVICE(USB_VENDOR_ID_ELAN, USB_DEVICE_ID_ASUS_UX550VE_TOUCHSCREEN),
@@ -391,32 +383,13 @@ static const struct hid_device_id hid_battery_quirks[] = { HID_BATTERY_QUIRK_AVOID_QUERY }, {HID_USB_DEVICE (USB_VENDOR_ID_UGEE ,USB_DEVICE_ID_UGEE_XPPEN_TABLET_DECO_PRO_SW ), HID_BATTERY_QUIRK_AVOID_QUERY }, - { HID_I2C_DEVICE(USB_VENDOR_ID_ELAN, I2C_DEVICE_ID_HP_ENVY_X360_15), - HID_BATTERY_QUIRK_IGNORE }, - { HID_I2C_DEVICE(USB_VENDOR_ID_ELAN, I2C_DEVICE_ID_HP_ENVY_X360_15T_DR100), - HID_BATTERY_QUIRK_IGNORE }, - { HID_I2C_DEVICE(USB_VENDOR_ID_ELAN, I2C_DEVICE_ID_HP_ENVY_X360_EU0009NV), - HID_BATTERY_QUIRK_IGNORE }, - { HID_I2C_DEVICE(USB_VENDOR_ID_ELAN, I2C_DEVICE_ID_HP_SPECTRE_X360_15), - HID_BATTERY_QUIRK_IGNORE }, - { HID_I2C_DEVICE(USB_VENDOR_ID_ELAN, I2C_DEVICE_ID_HP_SPECTRE_X360_13_AW0020NG), - HID_BATTERY_QUIRK_IGNORE }, - { HID_I2C_DEVICE(USB_VENDOR_ID_ELAN, I2C_DEVICE_ID_SURFACE_GO_TOUCHSCREEN), - HID_BATTERY_QUIRK_IGNORE }, - { HID_I2C_DEVICE(USB_VENDOR_ID_ELAN, I2C_DEVICE_ID_SURFACE_GO2_TOUCHSCREEN), - HID_BATTERY_QUIRK_IGNORE }, - { HID_I2C_DEVICE(USB_VENDOR_ID_ELAN, I2C_DEVICE_ID_LENOVO_YOGA_C630_TOUCHSCREEN), - HID_BATTERY_QUIRK_IGNORE }, - { HID_I2C_DEVICE(USB_VENDOR_ID_ELAN, I2C_DEVICE_ID_HP_SPECTRE_X360_13T_AW100), - HID_BATTERY_QUIRK_IGNORE }, - { HID_I2C_DEVICE(USB_VENDOR_ID_ELAN, I2C_DEVICE_ID_HP_SPECTRE_X360_14T_EA100_V1), - HID_BATTERY_QUIRK_IGNORE }, - { HID_I2C_DEVICE(USB_VENDOR_ID_ELAN, I2C_DEVICE_ID_HP_SPECTRE_X360_14T_EA100_V2), - HID_BATTERY_QUIRK_IGNORE }, - { HID_I2C_DEVICE(USB_VENDOR_ID_ELAN, I2C_DEVICE_ID_HP_ENVY_X360_15_EU0556NG), - HID_BATTERY_QUIRK_IGNORE }, { HID_I2C_DEVICE(USB_VENDOR_ID_ELAN, I2C_DEVICE_ID_CHROMEBOOK_TROGDOR_POMPOM), HID_BATTERY_QUIRK_AVOID_QUERY }, +/* +* Elan I2C-HID touchscreens seem to all report a non present battery, +* set HID_BATTERY_QUIRK_IGNORE for all Elan I2C-HID devices. +*/ + { HID_I2C_DEVICE(USB_VENDOR_ID_ELAN, HID_ANY_ID), HID_BATTERY_QUIRK_IGNORE }, {} };
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 223/558 drm/amd/display: Underflow Seen on DCN401 eGPU
In reply to Greg Kroah-Hartman6.11-stable review patch. If anyone has any objections, please let me know.
------------------
From: Daniel Sa <[email protected]>
[ Upstream commit ca0fb243c3bb53dbbd71d16c76f319bf923ee3d4 ]
[WHY]
In dcn401 we read clock values before FW is loaded. These incorrect values cause the driver to believe that we are running higher clocks than what we actually have. This then causes corruption/underflow for the eGPU.
[HOW]
When new values are read from HW, update internal structures to propagate the new/correct value. Fixes issue
--- drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_hwseq.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-)
drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_hwseq.c +6 -2
@@ -221,6 +221,7 @@ void dcn401_init_hw(struct dc *dc)int edp_num;uint32_t backlight =MAX_BACKLIGHT_LEVEL ;uint32_t user_level =MAX_BACKLIGHT_LEVEL ; +int current_dchub_ref_freq =0 ;if (dc->clk_mgr && dc->clk_mgr->funcs && dc->clk_mgr->funcs->init_clocks) { dc->clk_mgr->funcs->init_clocks (dc->clk_mgr);
@@ -264,6 +265,8 @@ void dcn401_init_hw(struct dc *dc) dc->ctx->dc_bios->fw_info.pll_info.crystal_frequency, &res_pool->ref_clocks.dccg_ref_clock_inKhz); + current_dchub_ref_freq = res_pool->ref_clocks.dchub_ref_clock_inKhz /1000 ; + (res_pool->hubbub->funcs->get_dchub_ref_freq)(res_pool->hubbub, res_pool->ref_clocks.dccg_ref_clock_inKhz, &res_pool->ref_clocks.dchub_ref_clock_inKhz);
@@ -436,8 +439,9 @@ void dcn401_init_hw(struct dc *dc) dc->caps.dmub_caps.mclk_sw = dc->ctx->dmub_srv->dmub->feature_caps.fw_assisted_mclk_switch_ver >0 ; dc->caps.dmub_caps.fams_ver = dc->ctx->dmub_srv->dmub->feature_caps.fw_assisted_mclk_switch_ver; dc->debug.fams2_config.bits.enable &= dc->ctx->dmub_srv->dmub->feature_caps.fw_assisted_mclk_switch_ver ==2 ; -if (!dc->debug.fams2_config.bits.enable && dc->res_pool->funcs->update_bw_bounding_box) { -/* update bounding box if FAMS2 disabled */ +if ((!dc->debug.fams2_config.bits.enable && dc->res_pool->funcs->update_bw_bounding_box) + || res_pool->ref_clocks.dchub_ref_clock_inKhz /1000 != current_dchub_ref_freq) { +/* update bounding box if FAMS2 disabled, or if dchub clk has changed */ if (dc->clk_mgr) dc->res_pool->funcs->update_bw_bounding_box (dc, dc->clk_mgr->bw_params);
Signature · 1 line
2.43.0