bus: ti-sysc: Probe for l4_wkup and l4_cfg interconnect devices first
Subsystems (6)
Sasha Levin
maintainerPATCH 1/79 bus: ti-sysc: Probe for l4_wkup and l4_cfg interconnect devices first
From: Tony Lindgren <[email protected]>
[ Upstream commit 4700a00755fb5a4bb5109128297d6fd2d1272ee6 ]
We want to probe l4_wkup and l4_cfg interconnect devices first to avoid issues with missing resources. Otherwise we attempt to probe l4_per devices first causing pointless deferred probe and also annoyingh renumbering of the MMC devices for example.
--- drivers/bus/ti-sysc.c | 49 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 49 insertions(+)
drivers/bus/ti-sysc.c +49 -0
@@ -635,6 +635,51 @@ static int sysc_parse_and_check_child_range(struct sysc *ddata)return 0 ; } +/* Interconnect instances to probe before l4_per instances */ +static struct resource early_bus_ranges[] = { +/* am3/4 l4_wkup */ + { .start =0x44c00000 , .end =0x44c00000 +0x300000 , }, +/* omap4/5 and dra7 l4_cfg */ + { .start =0x4a000000 , .end =0x4a000000 +0x300000 , }, +/* omap4 l4_wkup */ + { .start =0x4a300000 , .end =0x4a300000 +0x30000 , }, +/* omap5 and dra7 l4_wkup without dra7 dcan segment */ + { .start =0x4ae00000 , .end =0x4ae00000 +0x30000 , }, +}; + +static atomic_t sysc_defer =ATOMIC_INIT (10 ); + +/** +* sysc_defer_non_critical - defer non_critical interconnect probing +* @ddata: device driver data +* +* We want to probe l4_cfg and l4_wkup interconnect instances before any +* l4_per instances as l4_per instances depend on resources on l4_cfg and +* l4_wkup interconnects. +*/ +static int sysc_defer_non_critical (struct sysc *ddata) +{ +struct resource *res; +int i; + +if (!atomic_read (&sysc_defer)) +return 0 ; + +for (i =0 ; i <ARRAY_SIZE (early_bus_ranges); i++) { + res = &early_bus_ranges[i]; +if (ddata->module_pa >= res->start && + ddata->module_pa <= res->end) { +atomic_set (&sysc_defer,0 ); + +return 0 ; + } + } + +atomic_dec_if_positive (&sysc_defer); + +return -EPROBE_DEFER ; +} +static struct device_node *stdout_path;static void sysc_init_stdout_path (struct sysc *ddata)
@@ -863,6 +908,10 @@ static int sysc_map_and_check_registers(struct sysc *ddata)if (error)return error; + error =sysc_defer_non_critical (ddata); +if (error) +return error; +sysc_check_children (ddata); error =sysc_parse_registers (ddata);
Signature · 1 line
2.30.2
Sasha Levin
maintainerPATCH 2/79 staging: wimax/i2400m: fix byte-order issue
From: karthik alapati <[email protected]>
[ Upstream commit 0c37baae130df39b19979bba88bde2ee70a33355 ]
fix sparse byte-order warnings by converting host byte-order type to __le16 byte-order types before assigning to hdr.length
--- drivers/staging/wimax/i2400m/op-rfkill.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/staging/wimax/i2400m/op-rfkill.c +1 -1
@@ -86,7 +86,7 @@ int i2400m_op_rfkill_sw_toggle(struct wimax_dev *wimax_dev,if (cmd ==NULL ) goto error_alloc; cmd->hdr.type =cpu_to_le16 (I2400M_MT_CMD_RF_CONTROL ); - cmd->hdr.length =sizeof (cmd->sw_rf); + cmd->hdr.length =cpu_to_le16 (sizeof (cmd->sw_rf)); cmd->hdr.version =cpu_to_le16 (I2400M_L3L4_VERSION ); cmd->sw_rf.hdr.type =cpu_to_le16 (I2400M_TLV_RF_OPERATION ); cmd->sw_rf.hdr.length =cpu_to_le16 (sizeof (cmd->sw_rf.status));
Signature · 1 line
2.30.2
Sasha Levin
maintainerPATCH 3/79 spi: ath79: always call chipselect function
In reply to Sasha LevinFrom: David Bauer <[email protected]>
[ Upstream commit 19e2132174583beb90c1bd3e9c842bc6d5c944d1 ]
spi-bitbang has to call the chipselect function on the ath79 SPI driver in order to communicate with the SPI slave device, as the ath79 SPI driver has three dedicated chipselect lines but can also be used with GPIOs for the CS lines.
Fixes commit 4a07b8bcd503 ("spi: bitbang: Make chipselect callback optional")
--- drivers/spi/spi-ath79.c | 1 + 1 file changed, 1 insertion(+)
drivers/spi/spi-ath79.c +1 -0
@@ -158,6 +158,7 @@ static int ath79_spi_probe(struct platform_device *pdev) master->bits_per_word_mask =SPI_BPW_RANGE_MASK (1 ,32 ); master->setup = spi_bitbang_setup; master->cleanup = spi_bitbang_cleanup; + master->flags =SPI_MASTER_GPIO_SS ;if (pdata) { master->bus_num = pdata->bus_num; master->num_chipselect = pdata->num_chipselect;
Signature · 1 line
2.30.2
Sasha Levin
maintainerPATCH 4/79 spi: ath79: remove spi-master setup and cleanup assignment
In reply to Sasha LevinFrom: David Bauer <[email protected]>
[ Upstream commit ffb597b2bd3cd78b9bfb68f536743cd46dbb2cc4 ]
This removes the assignment of setup and cleanup functions for the ath79 target. Assigning the setup-method will lead to 'setup_transfer' not being assigned in spi_bitbang_init. Because of this, performing any TX/RX operation will lead to a kernel oops.
Also drop the redundant cleanup assignment, as it's also assigned in spi_bitbang_init.
--- drivers/spi/spi-ath79.c | 2 -- 1 file changed, 2 deletions(-)
drivers/spi/spi-ath79.c +0 -2
@@ -156,8 +156,6 @@ static int ath79_spi_probe(struct platform_device *pdev) master->use_gpio_descriptors = true; master->bits_per_word_mask =SPI_BPW_RANGE_MASK (1 ,32 ); - master->setup = spi_bitbang_setup; - master->cleanup = spi_bitbang_cleanup; master->flags =SPI_MASTER_GPIO_SS ;if (pdata) { master->bus_num = pdata->bus_num;
Signature · 1 line
2.30.2
Sasha Levin
maintainerPATCH 5/79 bus: mhi: pci_generic: No-Op for device_wake operations
In reply to Sasha LevinFrom: Loic Poulain <[email protected]>
[ Upstream commit e3e5e6508fc1c0e98a5a264853713dd30a60e5e5 ]
The wake_db register presence is highly speculative and can fuze MHI devices. Indeed, currently the wake_db register address is defined at entry 127 of the 'Channel doorbell array', thus writing to this address is equivalent to ringing the doorbell for channel 127, causing trouble with some devics (e.g. SDX24 based modems) that get an unexpected channel 127 doorbell interrupt.
This change fixes that issue by setting wake get/put as no-op for pci_generic devices. The wake device sideband mechanism seems really specific to each device, and is AFAIK not defined by the MHI spec.
It also removes zeroing initialization of wake_db register during MMIO initialization, the register being set via wake_get/put accessors few cycles later during M0 transition.
--- drivers/bus/mhi/core/init.c | 2 -- drivers/bus/mhi/pci_generic.c | 18 ++++++++++++++++++ 2 files changed, 18 insertions(+), 2 deletions(-)
drivers/bus/mhi/core/init.c +0 -2
@@ -508,8 +508,6 @@ int mhi_init_mmio(struct mhi_controller *mhi_cntrl)/* Setup wake db */ mhi_cntrl->wake_db = base + val + (8 *MHI_DEV_WAKE_DB ); -mhi_write_reg (mhi_cntrl, mhi_cntrl->wake_db,4 ,0 ); -mhi_write_reg (mhi_cntrl, mhi_cntrl->wake_db,0 ,0 ); mhi_cntrl->wake_set = false;/* Setup channel db address for each channel in tre_ring */
drivers/bus/mhi/pci_generic.c +18 -0
@@ -230,6 +230,21 @@ static void mhi_pci_status_cb(struct mhi_controller *mhi_cntrl, } } +static void mhi_pci_wake_get_nop (struct mhi_controller *mhi_cntrl,bool force) +{ +/* no-op */ +} + +static void mhi_pci_wake_put_nop (struct mhi_controller *mhi_cntrl,bool override) +{ +/* no-op */ +} + +static void mhi_pci_wake_toggle_nop (struct mhi_controller *mhi_cntrl) +{ +/* no-op */ +} +static bool mhi_pci_is_alive (struct mhi_controller *mhi_cntrl) {struct pci_dev *pdev =to_pci_dev (mhi_cntrl->cntrl_dev);
@@ -433,6 +448,9 @@ static int mhi_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) mhi_cntrl->status_cb = mhi_pci_status_cb; mhi_cntrl->runtime_get = mhi_pci_runtime_get; mhi_cntrl->runtime_put = mhi_pci_runtime_put; + mhi_cntrl->wake_get = mhi_pci_wake_get_nop; + mhi_cntrl->wake_put = mhi_pci_wake_put_nop; + mhi_cntrl->wake_toggle = mhi_pci_wake_toggle_nop; err =mhi_pci_claim (mhi_cntrl, info->bar_num,DMA_BIT_MASK (info->dma_data_width));if (err)
Signature · 1 line
2.30.2
Sasha Levin
maintainerPATCH 6/79 bus: mhi: core: Destroy SBL devices when moving to mission mode
In reply to Sasha LevinFrom: Bhaumik Bhatt <[email protected]>
[ Upstream commit 925089c1900f588615db5bf4e1d9064a5f2c18c7 ]
Currently, client devices are created in SBL or AMSS (mission mode) and only destroyed after power down or SYS ERROR. When moving between certain execution environments, such as from SBL to AMSS, no clean-up is required. This presents an issue where SBL-specific channels are left open and client drivers now run in an execution environment where they cannot operate. Fix this by expanding the mhi_destroy_device() to do an execution environment specific clean-up if one is requested. Close the gap and destroy devices in such scenarios that allow SBL client drivers to clean up once device enters mission mode.
--- drivers/bus/mhi/core/main.c | 29 +++++++++++++++++++++++++---- drivers/bus/mhi/core/pm.c | 3 +++ 2 files changed, 28 insertions(+), 4 deletions(-)
drivers/bus/mhi/core/main.c +25 -4
@@ -244,8 +244,10 @@ static void mhi_del_ring_element(struct mhi_controller *mhi_cntrl,int mhi_destroy_device (struct device *dev,void *data) { +struct mhi_chan *ul_chan, *dl_chan;struct mhi_device *mhi_dev;struct mhi_controller *mhi_cntrl; +enum mhi_ee_type ee =MHI_EE_MAX ;if (dev->bus != &mhi_bus_type)return 0 ;
@@ -257,6 +259,17 @@ int mhi_destroy_device(struct device *dev, void *data)if (mhi_dev->dev_type ==MHI_DEVICE_CONTROLLER )return 0 ; + ul_chan = mhi_dev->ul_chan; + dl_chan = mhi_dev->dl_chan; + +/* +* If execution environment is specified, remove only those devices that +* started in them based on ee_mask for the channels as we move on to a +* different execution environment +*/ +if (data) + ee = *(enum mhi_ee_type *)data; +/* * For the suspend and resume case, this function will get called * without mhi_unregister_controller(). Hence, we need to drop the
@@ -264,11 +277,19 @@ int mhi_destroy_device(struct device *dev, void *data)* be sure that there will be no instances of mhi_dev left after * this. */ -if (mhi_dev->ul_chan) -put_device (&mhi_dev->ul_chan->mhi_dev->dev); +if (ul_chan) { +if (ee !=MHI_EE_MAX && !(ul_chan->ee_mask &BIT (ee))) +return 0 ; -if (mhi_dev->dl_chan) -put_device (&mhi_dev->dl_chan->mhi_dev->dev); +put_device (&ul_chan->mhi_dev->dev); + } + +if (dl_chan) { +if (ee !=MHI_EE_MAX && !(dl_chan->ee_mask &BIT (ee))) +return 0 ; + +put_device (&dl_chan->mhi_dev->dev); + }dev_dbg (&mhi_cntrl->mhi_dev->dev,"destroy device for chan:%s\n" , mhi_dev->name);
drivers/bus/mhi/core/pm.c +3 -0
@@ -377,6 +377,7 @@ static int mhi_pm_mission_mode_transition(struct mhi_controller *mhi_cntrl) {struct mhi_event *mhi_event;struct device *dev = &mhi_cntrl->mhi_dev->dev; +enum mhi_ee_type current_ee = mhi_cntrl->ee;int i, ret;dev_dbg (dev,"Processing Mission Mode transition\n" );
@@ -395,6 +396,8 @@ static int mhi_pm_mission_mode_transition(struct mhi_controller *mhi_cntrl)wake_up_all (&mhi_cntrl->state_event); +device_for_each_child (&mhi_cntrl->mhi_dev->dev, ¤t_ee, + mhi_destroy_device); mhi_cntrl->status_cb (mhi_cntrl,MHI_CB_EE_MISSION_MODE );/* Force MHI to be in M0 state before continuing */
Signature · 1 line
2.30.2
Sasha Levin
maintainerPATCH 7/79 bus: mhi: core: Process execution environment changes serially
In reply to Sasha LevinFrom: Bhaumik Bhatt <[email protected]>
[ Upstream commit ef2126c4e2ea2b92f543fae00a2a0332e4573c48 ]
In current design, whenever the BHI interrupt is fired, the execution environment is updated. This can cause race conditions and impede ongoing power up/down processing. For example, if a power down is in progress, MHI host updates to a local "disabled" execution environment. If a BHI interrupt fires later, that value gets replaced with one from the BHI EE register. This impacts the controller as it does not expect multiple RDDM execution environment change status callbacks as an example. Another issue would be that the device can enter mission mode and the execution environment is updated, while device creation for SBL channels is still going on due to slower PM state worker thread run, leading to multiple attempts at opening the same channel.
Ensure that EE changes are handled only from appropriate places and occur one after another and handle only PBL modes or RDDM EE changes as critical events directly from the interrupt handler. Simplify handling by waiting for SYS ERROR before handling RDDM. This also makes sure that we use the correct execution environment to notify the controller driver when the device resets to one of the PBL execution environments.
--- drivers/bus/mhi/core/main.c | 40 +++++++++++++++++++------------------ drivers/bus/mhi/core/pm.c | 7 ++++--- 2 files changed, 25 insertions(+), 22 deletions(-)
drivers/bus/mhi/core/main.c +21 -19
@@ -430,7 +430,7 @@ irqreturn_t mhi_intvec_threaded_handler(int irq_number, void *priv)struct device *dev = &mhi_cntrl->mhi_dev->dev;enum mhi_state state =MHI_STATE_MAX ;enum mhi_pm_state pm_state =0 ; -enum mhi_ee_type ee =0 ; +enum mhi_ee_type ee =MHI_EE_MAX ;write_lock_irq (&mhi_cntrl->pm_lock);if (!MHI_REG_ACCESS_VALID (mhi_cntrl->pm_state)) {
@@ -439,8 +439,7 @@ irqreturn_t mhi_intvec_threaded_handler(int irq_number, void *priv) } state =mhi_get_mhi_state (mhi_cntrl); - ee = mhi_cntrl->ee; - mhi_cntrl->ee =mhi_get_exec_env (mhi_cntrl); + ee =mhi_get_exec_env (mhi_cntrl);dev_dbg (dev,"local ee:%s device ee:%s dev_state:%s\n" ,TO_MHI_EXEC_STR (mhi_cntrl->ee),TO_MHI_EXEC_STR (ee),TO_MHI_STATE_STR (state));
@@ -452,27 +451,30 @@ irqreturn_t mhi_intvec_threaded_handler(int irq_number, void *priv) }write_unlock_irq (&mhi_cntrl->pm_lock); -/* If device supports RDDM don't bother processing SYS error */ -if (mhi_cntrl->rddm_image) { -/* host may be performing a device power down already */ -if (!mhi_is_active (mhi_cntrl)) - goto exit_intvec; +if (pm_state !=MHI_PM_SYS_ERR_DETECT || ee == mhi_cntrl->ee) + goto exit_intvec; -if (mhi_cntrl->ee ==MHI_EE_RDDM && mhi_cntrl->ee != ee) { +switch (ee) { +case MHI_EE_RDDM : +/* proceed if power down is not already in progress */ +if (mhi_cntrl->rddm_image &&mhi_is_active (mhi_cntrl)) { mhi_cntrl->status_cb (mhi_cntrl,MHI_CB_EE_RDDM ); + mhi_cntrl->ee = ee;wake_up_all (&mhi_cntrl->state_event); } - goto exit_intvec; - } - -if (pm_state ==MHI_PM_SYS_ERR_DETECT ) { +break ; +case MHI_EE_PBL : +case MHI_EE_EDL : +case MHI_EE_PTHRU : + mhi_cntrl->status_cb (mhi_cntrl,MHI_CB_FATAL_ERROR ); + mhi_cntrl->ee = ee;wake_up_all (&mhi_cntrl->state_event); - -/* For fatal errors, we let controller decide next step */ -if (MHI_IN_PBL (ee)) - mhi_cntrl->status_cb (mhi_cntrl,MHI_CB_FATAL_ERROR ); -else -mhi_pm_sys_err_handler (mhi_cntrl); +mhi_pm_sys_err_handler (mhi_cntrl); +break ; +default : +wake_up_all (&mhi_cntrl->state_event); +mhi_pm_sys_err_handler (mhi_cntrl); +break ; } exit_intvec:
drivers/bus/mhi/core/pm.c +4 -3
@@ -377,21 +377,22 @@ static int mhi_pm_mission_mode_transition(struct mhi_controller *mhi_cntrl) {struct mhi_event *mhi_event;struct device *dev = &mhi_cntrl->mhi_dev->dev; -enum mhi_ee_type current_ee = mhi_cntrl->ee; +enum mhi_ee_type ee =MHI_EE_MAX , current_ee = mhi_cntrl->ee;int i, ret;dev_dbg (dev,"Processing Mission Mode transition\n" );write_lock_irq (&mhi_cntrl->pm_lock);if (MHI_REG_ACCESS_VALID (mhi_cntrl->pm_state)) - mhi_cntrl->ee =mhi_get_exec_env (mhi_cntrl); + ee =mhi_get_exec_env (mhi_cntrl); -if (!MHI_IN_MISSION_MODE (mhi_cntrl->ee)) { +if (!MHI_IN_MISSION_MODE (ee)) { mhi_cntrl->pm_state =MHI_PM_LD_ERR_FATAL_DETECT ;write_unlock_irq (&mhi_cntrl->pm_lock);wake_up_all (&mhi_cntrl->state_event);return -EIO ; } + mhi_cntrl->ee = ee;write_unlock_irq (&mhi_cntrl->pm_lock);wake_up_all (&mhi_cntrl->state_event);
Signature · 1 line
2.30.2
Sasha Levin
maintainerPATCH 8/79 crypto: api - check for ERR pointers in crypto_destroy_tfm()
In reply to Sasha LevinFrom: Ard Biesheuvel <[email protected]>
[ Upstream commit 83681f2bebb34dbb3f03fecd8f570308ab8b7c2c ]
Given that crypto_alloc_tfm() may return ERR pointers, and to avoid crashes on obscure error paths where such pointers are presented to crypto_destroy_tfm() (such as [0]), add an ERR_PTR check there before dereferencing the second argument as a struct crypto_tfm pointer.
[0] https://lore.kernel.org/linux-crypto/[email protected]/
--- crypto/api.c | 2 +- include/crypto/acompress.h | 2 ++ include/crypto/aead.h | 2 ++ include/crypto/akcipher.h | 2 ++ include/crypto/hash.h | 4 ++++ include/crypto/kpp.h | 2 ++ include/crypto/rng.h | 2 ++ include/crypto/skcipher.h | 2 ++ 8 files changed, 17 insertions(+), 1 deletion(-)
crypto/api.c +1 -1
@@ -562,7 +562,7 @@ void crypto_destroy_tfm(void *mem, struct crypto_tfm *tfm) {struct crypto_alg *alg; -if (unlikely (!mem)) +if (IS_ERR_OR_NULL (mem))return ; alg = tfm->__crt_alg;
include/crypto/acompress.h +2 -0
@@ -165,6 +165,8 @@ static inline struct crypto_acomp *crypto_acomp_reqtfm(struct acomp_req *req)* crypto_free_acomp() -- free ACOMPRESS tfm handle * * @tfm: ACOMPRESS tfm handle allocated with crypto_alloc_acomp() +* +* If @tfm is a NULL or error pointer, this function does nothing. */ static inline void crypto_free_acomp (struct crypto_acomp *tfm) {
include/crypto/aead.h +2 -0
@@ -185,6 +185,8 @@ static inline struct crypto_tfm *crypto_aead_tfm(struct crypto_aead *tfm)/** * crypto_free_aead() - zeroize and free aead handle * @tfm: cipher handle to be freed +* +* If @tfm is a NULL or error pointer, this function does nothing. */ static inline void crypto_free_aead (struct crypto_aead *tfm) {
include/crypto/akcipher.h +2 -0
@@ -174,6 +174,8 @@ static inline struct crypto_akcipher *crypto_akcipher_reqtfm(* crypto_free_akcipher() - free AKCIPHER tfm handle * * @tfm: AKCIPHER tfm handle allocated with crypto_alloc_akcipher() +* +* If @tfm is a NULL or error pointer, this function does nothing. */ static inline void crypto_free_akcipher (struct crypto_akcipher *tfm) {
include/crypto/hash.h +4 -0
@@ -281,6 +281,8 @@ static inline struct crypto_tfm *crypto_ahash_tfm(struct crypto_ahash *tfm)/** * crypto_free_ahash() - zeroize and free the ahash handle * @tfm: cipher handle to be freed +* +* If @tfm is a NULL or error pointer, this function does nothing. */ static inline void crypto_free_ahash (struct crypto_ahash *tfm) {
@@ -724,6 +726,8 @@ static inline struct crypto_tfm *crypto_shash_tfm(struct crypto_shash *tfm)/** * crypto_free_shash() - zeroize and free the message digest handle * @tfm: cipher handle to be freed +* +* If @tfm is a NULL or error pointer, this function does nothing. */ static inline void crypto_free_shash (struct crypto_shash *tfm) {
include/crypto/kpp.h +2 -0
@@ -154,6 +154,8 @@ static inline void crypto_kpp_set_flags(struct crypto_kpp *tfm, u32 flags)* crypto_free_kpp() - free KPP tfm handle * * @tfm: KPP tfm handle allocated with crypto_alloc_kpp() +* +* If @tfm is a NULL or error pointer, this function does nothing. */ static inline void crypto_free_kpp (struct crypto_kpp *tfm) {
include/crypto/rng.h +2 -0
@@ -111,6 +111,8 @@ static inline struct rng_alg *crypto_rng_alg(struct crypto_rng *tfm)/** * crypto_free_rng() - zeroize and free RNG handle * @tfm: cipher handle to be freed +* +* If @tfm is a NULL or error pointer, this function does nothing. */ static inline void crypto_free_rng (struct crypto_rng *tfm) {
include/crypto/skcipher.h +2 -0
@@ -196,6 +196,8 @@ static inline struct crypto_tfm *crypto_skcipher_tfm(/** * crypto_free_skcipher() - zeroize and free cipher handle * @tfm: cipher handle to be freed +* +* If @tfm is a NULL or error pointer, this function does nothing. */ static inline void crypto_free_skcipher (struct crypto_skcipher *tfm) {
Signature · 1 line
2.30.2
Sasha Levin
maintainerPATCH 9/79 crypto: qat - fix unmap invalid dma address
In reply to Sasha LevinFrom: Hui Tang <[email protected]>
[ Upstream commit 792b32fad548281e1b7fe14df9063a96c54b32a2 ]
'dma_mapping_error' return a negative value if 'dma_addr' is equal to 'DMA_MAPPING_ERROR' not zero, so fix initialization of 'dma_addr'.
--- drivers/crypto/qat/qat_common/qat_algs.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-)
drivers/crypto/qat/qat_common/qat_algs.c +9 -2
@@ -719,7 +719,7 @@ static int qat_alg_sgl_to_bufl(struct qat_crypto_instance *inst,struct qat_alg_buf_list *bufl;struct qat_alg_buf_list *buflout =NULL ;dma_addr_t blp; -dma_addr_t bloutp =0 ; +dma_addr_t bloutp;struct scatterlist *sg;size_t sz_out, sz =struct_size (bufl, bufers, n +1 );
@@ -731,6 +731,9 @@ static int qat_alg_sgl_to_bufl(struct qat_crypto_instance *inst,if (unlikely (!bufl))return -ENOMEM ; +for_each_sg (sgl, sg, n, i) + bufl->bufers[i].addr =DMA_MAPPING_ERROR ; + blp =dma_map_single (dev, bufl, sz,DMA_TO_DEVICE );if (unlikely (dma_mapping_error (dev, blp))) goto err_in;
@@ -764,10 +767,14 @@ static int qat_alg_sgl_to_bufl(struct qat_crypto_instance *inst, dev_to_node(&GET_DEV(inst->accel_dev)));if (unlikely (!buflout)) goto err_in; + + bufers = buflout->bufers; +for_each_sg (sglout, sg, n, i) + bufers[i].addr =DMA_MAPPING_ERROR ; + bloutp =dma_map_single (dev, buflout, sz_out,DMA_TO_DEVICE );if (unlikely (dma_mapping_error (dev, bloutp))) goto err_out; - bufers = buflout->bufers;for_each_sg (sglout, sg, n, i) {int y = sg_nctr;
Signature · 1 line
2.30.2
Sasha Levin
maintainerPATCH 10/79 usb: gadget: uvc: add bInterval checking for HS mode
In reply to Sasha LevinFrom: Pawel Laszczak <[email protected]>
[ Upstream commit 26adde04acdff14a1f28d4a5dce46a8513a3038b ]
Patch adds extra checking for bInterval passed by configfs. The 5.6.4 chapter of USB Specification (rev. 2.0) say:
"A high-bandwidth endpoint must specify a period of 1x125 µs (i.e., a bInterval value of 1)."
The issue was observed during testing UVC class on CV. I treat this change as improvement because we can control bInterval by configfs.
--- drivers/usb/gadget/function/f_uvc.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-)
drivers/usb/gadget/function/f_uvc.c +6 -1
@@ -633,7 +633,12 @@ uvc_function_bind(struct usb_configuration *c, struct usb_function *f) uvc_hs_streaming_ep.wMaxPacketSize =cpu_to_le16 (max_packet_size | ((max_packet_mult -1 ) <<11 )); - uvc_hs_streaming_ep.bInterval = opts->streaming_interval; + +/* A high-bandwidth endpoint must specify a bInterval value of 1 */ +if (max_packet_mult >1 ) + uvc_hs_streaming_ep.bInterval =1 ; +else + uvc_hs_streaming_ep.bInterval = opts->streaming_interval; uvc_ss_streaming_ep.wMaxPacketSize =cpu_to_le16 (max_packet_size); uvc_ss_streaming_ep.bInterval = opts->streaming_interval;
Signature · 1 line
2.30.2
Sasha Levin
maintainerPATCH 11/79 usb: webcam: Invalid size of Processing Unit Descriptor
In reply to Sasha LevinFrom: Pawel Laszczak <[email protected]>
[ Upstream commit 6a154ec9ef6762c774cd2b50215c7a8f0f08a862 ]
According with USB Device Class Definition for Video Device the Processing Unit Descriptor bLength should be 12 (10 + bmControlSize), but it has 11.
Invalid length caused that Processing Unit Descriptor Test Video form CV tool failed. To fix this issue patch adds bmVideoStandards into uvc_processing_unit_descriptor structure.
The bmVideoStandards field was added in UVC 1.1 and it wasn't part of UVC 1.0a.
--- drivers/usb/gadget/function/f_uvc.c | 1 + drivers/usb/gadget/legacy/webcam.c | 1 + include/uapi/linux/usb/video.h | 3 ++- 3 files changed, 4 insertions(+), 1 deletion(-)
drivers/usb/gadget/function/f_uvc.c +1 -0
@@ -822,6 +822,7 @@ static struct usb_function_instance *uvc_alloc_inst(void) pd->bmControls[0 ] =1 ; pd->bmControls[1 ] =0 ; pd->iProcessing =0 ; + pd->bmVideoStandards =0 ; od = &opts->uvc_output_terminal; od->bLength =UVC_DT_OUTPUT_TERMINAL_SIZE ;
drivers/usb/gadget/legacy/webcam.c +1 -0
@@ -125,6 +125,7 @@ static const struct uvc_processing_unit_descriptor uvc_processing = { .bmControls[0] = 1, .bmControls[1] = 0, .iProcessing = 0, + .bmVideoStandards = 0, };static const struct uvc_output_terminal_descriptor uvc_output_terminal = {
include/uapi/linux/usb/video.h +2 -1
@@ -302,9 +302,10 @@ struct uvc_processing_unit_descriptor {__u8 bControlSize;__u8 bmControls[2 ];__u8 iProcessing; +__u8 bmVideoStandards; } __attribute__((__packed__)); -#define UVC_DT_PROCESSING_UNIT_SIZE (n) (9+(n)) +#define UVC_DT_PROCESSING_UNIT_SIZE (n) (10+(n))/* 3.7.2.6. Extension Unit Descriptor */ struct uvc_extension_unit_descriptor {
Signature · 1 line
2.30.2
Sasha Levin
maintainerPATCH 12/79 x86/sev: Do not require Hypervisor CPUID bit for SEV guests
In reply to Sasha LevinFrom: Joerg Roedel <[email protected]>
[ Upstream commit eab696d8e8b9c9d600be6fad8dd8dfdfaca6ca7c ]
A malicious hypervisor could disable the CPUID intercept for an SEV or SEV-ES guest and trick it into the no-SEV boot path, where it could potentially reveal secrets. This is not an issue for SEV-SNP guests, as the CPUID intercept can't be disabled for those.
Remove the Hypervisor CPUID bit check from the SEV detection code to protect against this kind of attack and add a Hypervisor bit equals zero check to the SME detection path to prevent non-encrypted guests from trying to enable SME.
This handles the following cases:
1) SEV(-ES) guest where CPUID intercept is disabled. The guest will still see leaf 0x8000001f and the SEV bit. It can retrieve the C-bit and boot normally.
2) Non-encrypted guests with intercepted CPUID will check the SEV_STATUS MSR and find it 0 and will try to enable SME. This will fail when the guest finds MSR_K8_SYSCFG to be zero, as it is emulated by KVM. But we can't rely on that, as there might be other hypervisors which return this MSR with bit 23 set. The Hypervisor bit check will prevent that the guest tries to enable SME in this case.
3) Non-encrypted guests on SEV capable hosts with CPUID intercept disabled (by a malicious hypervisor) will try to boot into the SME path. This will fail, but it is also not considered a problem because non-encrypted guests have no protection against the hypervisor anyway.
[ bp: s/non-SEV/non-encrypted/g ]
--- arch/x86/boot/compressed/mem_encrypt.S | 6 ----- arch/x86/kernel/sev-es-shared.c | 6 +---- arch/x86/mm/mem_encrypt_identity.c | 35 ++++++++++++++------------ 3 files changed, 20 insertions(+), 27 deletions(-)
arch/x86/boot/compressed/mem_encrypt.S +0 -6
@@ -23,12 +23,6 @@ SYM_FUNC_START(get_sev_encryption_bit) push %ecx push %edx - /* Check if running under a hypervisor */ - movl $1, %eax - cpuid - bt $31, %ecx /* Check the hypervisor bit */ - jnc .Lno_sev - movl $0x80000000, %eax /* CPUID to check the highest leaf */ cpuid cmpl $0x8000001f, %eax /* See if 0x8000001f is available */
arch/x86/kernel/sev-es-shared.c +1 -5
@@ -186,7 +186,6 @@ void __init do_vc_no_ghcb(struct pt_regs *regs, unsigned long exit_code)* make it accessible to the hypervisor. * * In particular, check for: -* - Hypervisor CPUID bit * - Availability of CPUID leaf 0x8000001f * - SEV CPUID bit. *
@@ -194,10 +193,7 @@ void __init do_vc_no_ghcb(struct pt_regs *regs, unsigned long exit_code)* can't be checked here. */ -if ((fn ==1 && !(regs->cx &BIT (31 )))) -/* Hypervisor bit */ - goto fail; -else if (fn ==0x80000000 && (regs->ax <0x8000001f )) +if (fn ==0x80000000 && (regs->ax <0x8000001f ))/* SEV leaf check */ goto fail;else if ((fn ==0x8000001f && !(regs->ax &BIT (1 ))))
arch/x86/mm/mem_encrypt_identity.c +19 -16
@@ -503,14 +503,10 @@ void __init sme_enable(struct boot_params *bp)#define AMD_SME_BIT BIT(0)#define AMD_SEV_BIT BIT(1) -/* -* Set the feature mask (SME or SEV) based on whether we are -* running under a hypervisor. -*/ - eax =1 ; - ecx =0 ; -native_cpuid (&eax, &ebx, &ecx, &edx); - feature_mask = (ecx &BIT (31 )) ?AMD_SEV_BIT :AMD_SME_BIT ; + +/* Check the SEV MSR whether SEV or SME is enabled */ + sev_status =__rdmsr (MSR_AMD64_SEV ); + feature_mask = (sev_status &MSR_AMD64_SEV_ENABLED ) ?AMD_SEV_BIT :AMD_SME_BIT ;/* * Check for the SME/SEV feature:
@@ -530,19 +526,26 @@ void __init sme_enable(struct boot_params *bp)/* Check if memory encryption is enabled */ if (feature_mask ==AMD_SME_BIT ) { +/* +* No SME if Hypervisor bit is set. This check is here to +* prevent a guest from trying to enable SME. For running as a +* KVM guest the MSR_K8_SYSCFG will be sufficient, but there +* might be other hypervisors which emulate that MSR as non-zero +* or even pass it through to the guest. +* A malicious hypervisor can still trick a guest into this +* path, but there is no way to protect against that. +*/ + eax =1 ; + ecx =0 ; +native_cpuid (&eax, &ebx, &ecx, &edx); +if (ecx &BIT (31 )) +return ; +/* For SME, check the SYSCFG MSR */ msr =__rdmsr (MSR_K8_SYSCFG );if (!(msr &MSR_K8_SYSCFG_MEM_ENCRYPT ))return ; }else { -/* For SEV, check the SEV MSR */ - msr =__rdmsr (MSR_AMD64_SEV ); -if (!(msr &MSR_AMD64_SEV_ENABLED )) -return ; - -/* Save SEV_STATUS to avoid reading MSR again */ - sev_status = msr; -/* SEV state cannot be controlled by a command line option */ sme_me_mask = me_mask; sev_enabled = true;
Signature · 1 line
2.30.2
Sasha Levin
maintainerPATCH 13/79 x86/boot/compressed/64: Check SEV encryption in the 32-bit boot-path
In reply to Sasha LevinFrom: Joerg Roedel <[email protected]>
[ Upstream commit fef81c86262879d4b1176ef51a834c15b805ebb9 ]
Check whether the hypervisor reported the correct C-bit when running as an SEV guest. Using a wrong C-bit position could be used to leak sensitive data from the guest to the hypervisor.
--- arch/x86/boot/compressed/head_64.S | 83 ++++++++++++++++++++++++++++++ 1 file changed, 83 insertions(+)
arch/x86/boot/compressed/head_64.S +83 -0
@@ -172,11 +172,21 @@ SYM_FUNC_START(startup_32) */ call get_sev_encryption_bit xorl %edx, %edx +#ifdef CONFIG_AMD_MEM_ENCRYPT testl %eax, %eax jz 1f subl $32, %eax /* Encryption bit is always above bit 31 */ bts %eax, %edx /* Set encryption mask for page tables */ + /* + * Mark SEV as active in sev_status so that startup32_check_sev_cbit() + * will do a check. The sev_status memory will be fully initialized + * with the contents of MSR_AMD_SEV_STATUS later in + * set_sev_encryption_mask(). For now it is sufficient to know that SEV + * is active. + */ + movl $1, rva(sev_status)(%ebp) 1: +#endif /* Initialize Page tables to 0 */ leal rva(pgtable)(%ebx), %edi
@@ -261,6 +271,9 @@ SYM_FUNC_START(startup_32) movl %esi, %edx 1: #endif + /* Check if the C-bit position is correct when SEV is active */ + call startup32_check_sev_cbit + pushl $__KERNEL_CS pushl %eax
@@ -786,6 +799,76 @@ SYM_DATA_START_LOCAL(loaded_image_proto) SYM_DATA_END(loaded_image_proto) #endif +/* + * Check for the correct C-bit position when the startup_32 boot-path is used. + * + * The check makes use of the fact that all memory is encrypted when paging is + * disabled. The function creates 64 bits of random data using the RDRAND + * instruction. RDRAND is mandatory for SEV guests, so always available. If the + * hypervisor violates that the kernel will crash right here. + * + * The 64 bits of random data are stored to a memory location and at the same + * time kept in the %eax and %ebx registers. Since encryption is always active + * when paging is off the random data will be stored encrypted in main memory. + * + * Then paging is enabled. When the C-bit position is correct all memory is + * still mapped encrypted and comparing the register values with memory will + * succeed. An incorrect C-bit position will map all memory unencrypted, so that + * the compare will use the encrypted random data and fail. + */ +SYM_FUNC_START(startup32_check_sev_cbit) +#ifdef CONFIG_AMD_MEM_ENCRYPT + pushl %eax + pushl %ebx + pushl %ecx + pushl %edx + + /* Check for non-zero sev_status */ + movl rva(sev_status)(%ebp), %eax + testl %eax, %eax + jz 4f + + /* + * Get two 32-bit random values - Don't bail out if RDRAND fails + * because it is better to prevent forward progress if no random value + * can be gathered. + */ +1: rdrand %eax + jnc 1b +2: rdrand %ebx + jnc 2b + + /* Store to memory and keep it in the registers */ + movl %eax, rva(sev_check_data)(%ebp) + movl %ebx, rva(sev_check_data+4)(%ebp) + + /* Enable paging to see if encryption is active */ + movl %cr0, %edx /* Backup %cr0 in %edx */ + movl $(X86_CR0_PG | X86_CR0_PE), %ecx /* Enable Paging and Protected mode */ + movl %ecx, %cr0 + + cmpl %eax, rva(sev_check_data)(%ebp) + jne 3f + cmpl %ebx, rva(sev_check_data+4)(%ebp) + jne 3f + + movl %edx, %cr0 /* Restore previous %cr0 */ + + jmp 4f + +3: /* Check failed - hlt the machine */ + hlt + jmp 3b + +4: + popl %edx + popl %ecx + popl %ebx + popl %eax +#endif + ret +SYM_FUNC_END(startup32_check_sev_cbit) + /* * Stack and heap for uncompression */
Signature · 1 line
2.30.2
Sasha Levin
maintainerPATCH 14/79 crypto: hisilicon/sec - fixes a printing error
In reply to Sasha LevinFrom: Longfang Liu <[email protected]>
[ Upstream commit 4b7aef0230418345be1fb77abbb1592801869901 ]
When the log is output here, the device has not
been initialized yet.
--- drivers/crypto/hisilicon/sec2/sec_crypto.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/crypto/hisilicon/sec2/sec_crypto.c +1 -1
@@ -546,7 +546,7 @@ static int sec_skcipher_init(struct crypto_skcipher *tfm)crypto_skcipher_set_reqsize (tfm,sizeof (struct sec_req )); ctx->c_ctx.ivsize =crypto_skcipher_ivsize (tfm);if (ctx->c_ctx.ivsize >SEC_IV_SIZE ) { -dev_err (SEC_CTX_DEV (ctx),"get error skcipher iv size!\n" ); +pr_err ("get error skcipher iv size!\n" );return -EINVAL ; }
Signature · 1 line
2.30.2
Sasha Levin
maintainerPATCH 15/79 genirq/matrix: Prevent allocation counter corruption
In reply to Sasha LevinFrom: Vitaly Kuznetsov <[email protected]>
[ Upstream commit c93a5e20c3c2dabef8ea360a3d3f18c6f68233ab ]
When irq_matrix_free() is called for an unallocated vector the managed_allocated and total_allocated counters get out of sync with the real state of the matrix. Later, when the last interrupt is freed, these counters will underflow resulting in UINTMAX because the counters are unsigned.
While this is certainly a problem of the calling code, this can be catched in the allocator by checking the allocation bit for the to be freed vector which simplifies debugging.
An example of the problem described above:
https://lore.kernel.org/lkml/[email protected]/
Add the missing sanity check and emit a warning when it triggers.
--- kernel/irq/matrix.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
kernel/irq/matrix.c +3 -1
@@ -423,7 +423,9 @@ void irq_matrix_free(struct irq_matrix *m, unsigned int cpu,if (WARN_ON_ONCE (bit < m->alloc_start || bit >= m->alloc_end))return ; -clear_bit (bit, cm->alloc_map); +if (WARN_ON_ONCE (!test_and_clear_bit (bit, cm->alloc_map))) +return ; + cm->allocated--;if (managed) cm->managed_allocated--;
Signature · 1 line
2.30.2
Sasha Levin
maintainerPATCH 16/79 usb: dwc3: gadget: Remove invalid low-speed setting
In reply to Sasha LevinFrom: Thinh Nguyen <[email protected]>
[ Upstream commit 0c59f678fcfc6dd53ba493915794636a230bc4cc ]
None of the DWC_usb3x IPs (and all their versions) supports low-speed setting in device mode. In the early days, our "Early Adopter Edition" DWC_usb3 databook shows that the controller may be configured to operate in low-speed, but it was revised on release. Let's remove this invalid speed setting to avoid any confusion.
--- drivers/usb/dwc3/core.c | 1 - drivers/usb/dwc3/core.h | 2 -- drivers/usb/dwc3/gadget.c | 8 -------- 3 files changed, 11 deletions(-)
drivers/usb/dwc3/core.c +0 -1
@@ -1385,7 +1385,6 @@ static void dwc3_check_params(struct dwc3 *dwc)/* Check the maximum_speed parameter */ switch (dwc->maximum_speed) { -case USB_SPEED_LOW :case USB_SPEED_FULL :case USB_SPEED_HIGH :break ;
drivers/usb/dwc3/core.h +0 -2
@@ -396,7 +396,6 @@#define DWC3_DCFG_SUPERSPEED (4 << 0)#define DWC3_DCFG_HIGHSPEED (0 << 0)#define DWC3_DCFG_FULLSPEED BIT(0) -#define DWC3_DCFG_LOWSPEED (2 << 0)#define DWC3_DCFG_NUMP_SHIFT 17#define DWC3_DCFG_NUMP (n) (((n) >> DWC3_DCFG_NUMP_SHIFT) & 0x1f)
@@ -490,7 +489,6 @@#define DWC3_DSTS_SUPERSPEED (4 << 0)#define DWC3_DSTS_HIGHSPEED (0 << 0)#define DWC3_DSTS_FULLSPEED BIT(0) -#define DWC3_DSTS_LOWSPEED (2 << 0)/* Device Generic Command Register */ #define DWC3_DGCMD_SET_LMP 0x01
drivers/usb/dwc3/gadget.c +0 -8
@@ -2113,9 +2113,6 @@ static void __dwc3_gadget_set_speed(struct dwc3 *dwc) reg |=DWC3_DCFG_SUPERSPEED ; }else {switch (speed) { -case USB_SPEED_LOW : - reg |=DWC3_DCFG_LOWSPEED ; -break ;case USB_SPEED_FULL : reg |=DWC3_DCFG_FULLSPEED ;break ;
@@ -3448,11 +3445,6 @@ static void dwc3_gadget_conndone_interrupt(struct dwc3 *dwc) dwc->gadget->ep0->maxpacket =64 ; dwc->gadget->speed =USB_SPEED_FULL ;break ; -case DWC3_DSTS_LOWSPEED : - dwc3_gadget_ep0_desc.wMaxPacketSize =cpu_to_le16 (8 ); - dwc->gadget->ep0->maxpacket =8 ; - dwc->gadget->speed =USB_SPEED_LOW ; -break ; } dwc->eps[1 ]->endpoint.maxpacket = dwc->gadget->ep0->maxpacket;
Signature · 1 line
2.30.2
Greg Kroah-Hartman
maintainerRe: [PATCH AUTOSEL 5.12 16/79] usb: dwc3: gadget: Remove invalid low-speed setting
Quoted 14 lines · Sasha Levin
From: Thinh Nguyen <[email protected]>
[ Upstream commit
0c59f678fcfc6dd53ba493915794636a230bc4cc]None of the
DWC_usb3xIPs (and all their versions) supports low-speed setting in device mode. In the early days, our "Early Adopter Edition"DWC_usb3databook shows that the controller may be configured to operate in low-speed, but it was revised on release. Let's remove this invalid speed setting to avoid any confusion.
Quoted 5 lines
--- drivers/usb/dwc3/core.c | 1 - drivers/usb/dwc3/core.h | 2 -- drivers/usb/dwc3/gadget.c | 8 -------- 3 files changed, 11 deletions(-)
This is a "cleanup only" and does not fix or solve anything, so it can be dropped from all of the kernels it has been "autoselected" for.
thanks,
greg k-h
Sasha Levin
maintainerRe: [PATCH AUTOSEL 5.12 16/79] usb: dwc3: gadget: Remove invalid low-speed setting
Quoted 21 lines · Greg Kroah-Hartman
Quoted 14 lines · Sasha Levin
From: Thinh Nguyen <[email protected]>
[ Upstream commit
0c59f678fcfc6dd53ba493915794636a230bc4cc]None of the
DWC_usb3xIPs (and all their versions) supports low-speed setting in device mode. In the early days, our "Early Adopter Edition"DWC_usb3databook shows that the controller may be configured to operate in low-speed, but it was revised on release. Let's remove this invalid speed setting to avoid any confusion.Quoted 5 lines
--- drivers/usb/dwc3/core.c | 1 - drivers/usb/dwc3/core.h | 2 -- drivers/usb/dwc3/gadget.c | 8 -------- 3 files changed, 11 deletions(-)
Quoted 2 lines
This is a "cleanup only" and does not fix or solve anything, so it can be dropped from all of the kernels it has been "autoselected" for.
Dropped, thanks!
Signature · 2 lines
Thanks, Sasha
Sasha Levin
maintainerPATCH 17/79 usb: gadget: f_uac2: validate input parameters
In reply to Sasha LevinFrom: Ruslan Bilovol <[email protected]>
[ Upstream commit 3713d5ceb04d5ab6a5e2b86dfca49170053f3a5e ]
Currently user can configure UAC2 function with parameters that violate UAC2 spec or are not supported by UAC2 gadget implementation.
This can lead to incorrect behavior if such gadget is connected to the host - like enumeration failure or other issues depending on host's UAC2 driver implementation, bringing user to a long hours of debugging the issue.
Instead of silently accept these parameters, throw an error if they are not valid.
--- drivers/usb/gadget/function/f_uac2.c | 39 ++++++++++++++++++++++++++-- 1 file changed, 37 insertions(+), 2 deletions(-)
drivers/usb/gadget/function/f_uac2.c +37 -2
@@ -14,6 +14,9 @@#include "u_audio.h" #include "u_uac2.h" +/* UAC2 spec: 4.1 Audio Channel Cluster Descriptor */ +#define UAC2_CHANNEL_MASK 0x07FFFFFF +/* * The driver implements a simple UAC_2 topology. * USB-OUT -> IT_1 -> OT_3 -> ALSA_Capture
@@ -604,6 +607,36 @@ static void setup_descriptor(struct f_uac2_opts *opts) hs_audio_desc[i] =NULL ; } +static int afunc_validate_opts (struct g_audio *agdev,struct device *dev) +{ +struct f_uac2_opts *opts =g_audio_to_uac2_opts (agdev); + +if (!opts->p_chmask && !opts->c_chmask) { +dev_err (dev,"Error: no playback and capture channels\n" ); +return -EINVAL ; + }else if (opts->p_chmask & ~UAC2_CHANNEL_MASK ) { +dev_err (dev,"Error: unsupported playback channels mask\n" ); +return -EINVAL ; + }else if (opts->c_chmask & ~UAC2_CHANNEL_MASK ) { +dev_err (dev,"Error: unsupported capture channels mask\n" ); +return -EINVAL ; + }else if ((opts->p_ssize <1 ) || (opts->p_ssize >4 )) { +dev_err (dev,"Error: incorrect playback sample size\n" ); +return -EINVAL ; + }else if ((opts->c_ssize <1 ) || (opts->c_ssize >4 )) { +dev_err (dev,"Error: incorrect capture sample size\n" ); +return -EINVAL ; + }else if (!opts->p_srate) { +dev_err (dev,"Error: incorrect playback sampling rate\n" ); +return -EINVAL ; + }else if (!opts->c_srate) { +dev_err (dev,"Error: incorrect capture sampling rate\n" ); +return -EINVAL ; + } + +return 0 ; +} +static int afunc_bind (struct usb_configuration *cfg,struct usb_function *fn) {
@@ -612,11 +645,13 @@ afunc_bind(struct usb_configuration *cfg, struct usb_function *fn)struct usb_composite_dev *cdev = cfg->cdev;struct usb_gadget *gadget = cdev->gadget;struct device *dev = &gadget->dev; -struct f_uac2_opts *uac2_opts; +struct f_uac2_opts *uac2_opts =g_audio_to_uac2_opts (agdev);struct usb_string *us;int ret; - uac2_opts = container_of(fn->fi, struct f_uac2_opts, func_inst); + ret =afunc_validate_opts (agdev, dev); +if (ret) +return ret; us =usb_gstrings_attach (cdev, fn_strings,ARRAY_SIZE (strings_fn));if (IS_ERR (us))
Signature · 1 line
2.30.2
Sasha Levin
maintainerPATCH 18/79 usb: gadget: f_uac1: validate input parameters
In reply to Sasha LevinFrom: Ruslan Bilovol <[email protected]>
[ Upstream commit a59c68a6a3d1b18e2494f526eb19893a34fa6ec6 ]
Currently user can configure UAC1 function with parameters that violate UAC1 spec or are not supported by UAC1 gadget implementation.
This can lead to incorrect behavior if such gadget is connected to the host - like enumeration failure or other issues depending on host's UAC1 driver implementation, bringing user to a long hours of debugging the issue.
Instead of silently accept these parameters, throw an error if they are not valid.
--- drivers/usb/gadget/function/f_uac1.c | 43 ++++++++++++++++++++++++++++ 1 file changed, 43 insertions(+)
drivers/usb/gadget/function/f_uac1.c +43 -0
@@ -19,6 +19,9 @@#include "u_audio.h" #include "u_uac1.h" +/* UAC1 spec: 3.7.2.3 Audio Channel Cluster Format */ +#define UAC1_CHANNEL_MASK 0x0FFF +struct f_uac1 {struct g_audio g_audio;u8 ac_intf, as_in_intf, as_out_intf;
@@ -30,6 +33,11 @@ static inline struct f_uac1 *func_to_uac1(struct usb_function *f) return container_of(f, struct f_uac1, g_audio.func); } +static inline struct f_uac1_opts *g_audio_to_uac1_opts (struct g_audio *audio) +{ + return container_of(audio->func.fi, struct f_uac1_opts, func_inst); +} +/* * DESCRIPTORS ... most are static, but strings and full * configuration descriptors are built on demand.
@@ -505,11 +513,42 @@ static void f_audio_disable(struct usb_function *f)/*-------------------------------------------------------------------------*/ +static int f_audio_validate_opts (struct g_audio *audio,struct device *dev) +{ +struct f_uac1_opts *opts =g_audio_to_uac1_opts (audio); + +if (!opts->p_chmask && !opts->c_chmask) { +dev_err (dev,"Error: no playback and capture channels\n" ); +return -EINVAL ; + }else if (opts->p_chmask & ~UAC1_CHANNEL_MASK ) { +dev_err (dev,"Error: unsupported playback channels mask\n" ); +return -EINVAL ; + }else if (opts->c_chmask & ~UAC1_CHANNEL_MASK ) { +dev_err (dev,"Error: unsupported capture channels mask\n" ); +return -EINVAL ; + }else if ((opts->p_ssize <1 ) || (opts->p_ssize >4 )) { +dev_err (dev,"Error: incorrect playback sample size\n" ); +return -EINVAL ; + }else if ((opts->c_ssize <1 ) || (opts->c_ssize >4 )) { +dev_err (dev,"Error: incorrect capture sample size\n" ); +return -EINVAL ; + }else if (!opts->p_srate) { +dev_err (dev,"Error: incorrect playback sampling rate\n" ); +return -EINVAL ; + }else if (!opts->c_srate) { +dev_err (dev,"Error: incorrect capture sampling rate\n" ); +return -EINVAL ; + } + +return 0 ; +} +/* audio function driver setup/binding */ static int f_audio_bind (struct usb_configuration *c,struct usb_function *f) {struct usb_composite_dev *cdev = c->cdev;struct usb_gadget *gadget = cdev->gadget; +struct device *dev = &gadget->dev;struct f_uac1 *uac1 =func_to_uac1 (f);struct g_audio *audio =func_to_g_audio (f);struct f_uac1_opts *audio_opts;
@@ -519,6 +558,10 @@ static int f_audio_bind(struct usb_configuration *c, struct usb_function *f)int rate;int status; + status =f_audio_validate_opts (audio, dev); +if (status) +return status; + audio_opts = container_of(f->fi, struct f_uac1_opts, func_inst); us =usb_gstrings_attach (cdev, uac1_strings,ARRAY_SIZE (strings_uac1));
Signature · 1 line
2.30.2
Sasha Levin
maintainerPATCH 19/79 usb: dwc3: gadget: Ignore EP queue requests during bus reset
In reply to Sasha LevinFrom: Wesley Cheng <[email protected]>
[ Upstream commit 71ca43f30df9c642970f9dc9b2d6f463f4967e7b ]
The current dwc3_gadget_reset_interrupt() will stop any active transfers, but only addresses blocking of EP queuing for while we are coming from a disconnected scenario, i.e. after receiving the disconnect event. If the host decides to issue a bus reset on the device, the connected parameter will still be set to true, allowing for EP queuing to continue while we are disabling the functions. To avoid this, set the connected flag to false until the stop active transfers is complete.
--- drivers/usb/dwc3/gadget.c | 9 +++++++++ 1 file changed, 9 insertions(+)
drivers/usb/dwc3/gadget.c +9 -0
@@ -3319,6 +3319,15 @@ static void dwc3_gadget_reset_interrupt(struct dwc3 *dwc) {u32 reg; +/* +* Ideally, dwc3_reset_gadget() would trigger the function +* drivers to stop any active transfers through ep disable. +* However, for functions which defer ep disable, such as mass +* storage, we will need to rely on the call to stop active +* transfers here, and avoid allowing of request queuing. +*/ + dwc->connected = false; +/* * WORKAROUND: DWC3 revisions <1.88a have an issue which * would cause a missing Disconnect Event if there's a
Signature · 1 line
2.30.2
Sasha Levin
maintainerPATCH 20/79 usb: xhci: Fix port minor revision
In reply to Sasha LevinFrom: Thinh Nguyen <[email protected]>
[ Upstream commit 64364bc912c01b33bba6c22e3ccb849bfca96398 ]
Some hosts incorrectly use sub-minor version for minor version (i.e. 0x02 instead of 0x20 for bcdUSB 0x320 and 0x01 for bcdUSB 0x310). Currently the xHCI driver works around this by just checking for minor revision > 0x01 for USB 3.1 everywhere. With the addition of USB 3.2, checking this gets a bit cumbersome. Since there is no USB release with bcdUSB 0x301 to 0x309, we can assume that sub-minor version 01 to 09 is incorrect. Let's try to fix this and use the minor revision that matches with the USB/xHCI spec to help with the version checking within the driver.
--- drivers/usb/host/xhci-mem.c | 9 +++++++++ 1 file changed, 9 insertions(+)
drivers/usb/host/xhci-mem.c +9 -0
@@ -2129,6 +2129,15 @@ static void xhci_add_in_port(struct xhci_hcd *xhci, unsigned int num_ports,if (major_revision ==0x03 ) { rhub = &xhci->usb3_rhub; +/* +* Some hosts incorrectly use sub-minor version for minor +* version (i.e. 0x02 instead of 0x20 for bcdUSB 0x320 and 0x01 +* for bcdUSB 0x310). Since there is no USB release with sub +* minor version 0x301 to 0x309, we can assume that they are +* incorrect and fix it here. +*/ +if (minor_revision >0x00 && minor_revision <0x10 ) + minor_revision <<=4 ; }else if (major_revision <=0x02 ) { rhub = &xhci->usb2_rhub; }else {
Signature · 1 line
2.30.2