From: Yang Yingliang yangyingliang@huawei.com
[ Upstream commit ee522bcf026ec82ada793979c3a906274430595a ]
After device_get_match_data(), tlc591xx is not checked, add check for it and also check np after dev_of_node.
Reported-by: Hulk Robot hulkci@huawei.com Signed-off-by: Yang Yingliang yangyingliang@huawei.com Signed-off-by: Pavel Machek pavel@ucw.cz Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/leds/leds-tlc591xx.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-)
diff --git a/drivers/leds/leds-tlc591xx.c b/drivers/leds/leds-tlc591xx.c index 5b9dfdf743ec..cb7bd1353f9f 100644 --- a/drivers/leds/leds-tlc591xx.c +++ b/drivers/leds/leds-tlc591xx.c @@ -148,16 +148,20 @@ static int tlc591xx_probe(struct i2c_client *client, const struct i2c_device_id *id) { - struct device_node *np = dev_of_node(&client->dev), *child; + struct device_node *np, *child; struct device *dev = &client->dev; const struct tlc591xx *tlc591xx; struct tlc591xx_priv *priv; int err, count, reg;
- tlc591xx = device_get_match_data(dev); + np = dev_of_node(dev); if (!np) return -ENODEV;
+ tlc591xx = device_get_match_data(dev); + if (!tlc591xx) + return -ENODEV; + count = of_get_available_child_count(np); if (!count || count > tlc591xx->max_leds) return -EINVAL;
From: Pierre-Louis Bossart pierre-louis.bossart@linux.intel.com
[ Upstream commit 35564e2bf94611c3eb51d35362addb3cb394ad54 ]
When external RT714/715 devices are used for capture, we don't want the PCH DMICs to be used.
Any information provided by the SOF platform driver or DMI quirks will be overridden.
Signed-off-by: Pierre-Louis Bossart pierre-louis.bossart@linux.intel.com Reviewed-by: Kai Vehmanen kai.vehmanen@linux.intel.com Reviewed-by: Libin Yang libin.yang@intel.com Link: https://lore.kernel.org/r/20210505163705.305616-5-pierre-louis.bossart@linux... Signed-off-by: Mark Brown broonie@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- sound/soc/intel/boards/sof_sdw.c | 19 +++++++++++++++++-- sound/soc/intel/boards/sof_sdw_common.h | 1 + 2 files changed, 18 insertions(+), 2 deletions(-)
diff --git a/sound/soc/intel/boards/sof_sdw.c b/sound/soc/intel/boards/sof_sdw.c index ecd3f90f4bbe..85a2797c2550 100644 --- a/sound/soc/intel/boards/sof_sdw.c +++ b/sound/soc/intel/boards/sof_sdw.c @@ -353,6 +353,7 @@ static struct sof_sdw_codec_info codec_info_list[] = { .part_id = 0x714, .version_id = 3, .direction = {false, true}, + .ignore_pch_dmic = true, .dai_name = "rt715-aif2", .init = sof_sdw_rt715_sdca_init, }, @@ -360,6 +361,7 @@ static struct sof_sdw_codec_info codec_info_list[] = { .part_id = 0x715, .version_id = 3, .direction = {false, true}, + .ignore_pch_dmic = true, .dai_name = "rt715-aif2", .init = sof_sdw_rt715_sdca_init, }, @@ -367,6 +369,7 @@ static struct sof_sdw_codec_info codec_info_list[] = { .part_id = 0x714, .version_id = 2, .direction = {false, true}, + .ignore_pch_dmic = true, .dai_name = "rt715-aif2", .init = sof_sdw_rt715_init, }, @@ -374,6 +377,7 @@ static struct sof_sdw_codec_info codec_info_list[] = { .part_id = 0x715, .version_id = 2, .direction = {false, true}, + .ignore_pch_dmic = true, .dai_name = "rt715-aif2", .init = sof_sdw_rt715_init, }, @@ -729,7 +733,8 @@ static int create_sdw_dailink(struct device *dev, int *be_index, int *cpu_id, bool *group_generated, struct snd_soc_codec_conf *codec_conf, int codec_count, - int *codec_conf_index) + int *codec_conf_index, + bool *ignore_pch_dmic) { const struct snd_soc_acpi_link_adr *link_next; struct snd_soc_dai_link_component *codecs; @@ -782,6 +787,9 @@ static int create_sdw_dailink(struct device *dev, int *be_index, if (codec_index < 0) return codec_index;
+ if (codec_info_list[codec_index].ignore_pch_dmic) + *ignore_pch_dmic = true; + cpu_dai_index = *cpu_id; for_each_pcm_streams(stream) { char *name, *cpu_name; @@ -913,6 +921,7 @@ static int sof_card_dai_links_create(struct device *dev, const struct snd_soc_acpi_link_adr *adr_link; struct snd_soc_dai_link_component *cpus; struct snd_soc_codec_conf *codec_conf; + bool ignore_pch_dmic = false; int codec_conf_count; int codec_conf_index = 0; bool group_generated[SDW_MAX_GROUPS]; @@ -1019,7 +1028,8 @@ static int sof_card_dai_links_create(struct device *dev, sdw_cpu_dai_num, cpus, adr_link, &cpu_id, group_generated, codec_conf, codec_conf_count, - &codec_conf_index); + &codec_conf_index, + &ignore_pch_dmic); if (ret < 0) { dev_err(dev, "failed to create dai link %d", be_id); return -ENOMEM; @@ -1087,6 +1097,10 @@ static int sof_card_dai_links_create(struct device *dev, DMIC: /* dmic */ if (dmic_num > 0) { + if (ignore_pch_dmic) { + dev_warn(dev, "Ignoring PCH DMIC\n"); + goto HDMI; + } cpus[cpu_id].dai_name = "DMIC01 Pin"; init_dai_link(dev, links + link_id, be_id, "dmic01", 0, 1, // DMIC only supports capture @@ -1105,6 +1119,7 @@ static int sof_card_dai_links_create(struct device *dev, INC_ID(be_id, cpu_id, link_id); }
+HDMI: /* HDMI */ if (hdmi_num > 0) { idisp_components = devm_kcalloc(dev, hdmi_num, diff --git a/sound/soc/intel/boards/sof_sdw_common.h b/sound/soc/intel/boards/sof_sdw_common.h index f3cb6796363e..ea60e8ed215c 100644 --- a/sound/soc/intel/boards/sof_sdw_common.h +++ b/sound/soc/intel/boards/sof_sdw_common.h @@ -56,6 +56,7 @@ struct sof_sdw_codec_info { int amp_num; const u8 acpi_id[ACPI_ID_LEN]; const bool direction[2]; // playback & capture support + const bool ignore_pch_dmic; const char *dai_name; const struct snd_soc_ops *ops;
From: Libin Yang libin.yang@intel.com
[ Upstream commit 81cd42e5174ba7918edd3d006406ce21ebaa8507 ]
AlderLake needs the flag SOF_RT715_DAI_ID_FIX if it is using the rt715 DMIC.
Reviewed-by: Bard Liao bard.liao@intel.com Signed-off-by: Libin Yang libin.yang@intel.com Signed-off-by: Pierre-Louis Bossart pierre-louis.bossart@linux.intel.com Link: https://lore.kernel.org/r/20210505163705.305616-11-pierre-louis.bossart@linu... Signed-off-by: Mark Brown broonie@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- sound/soc/intel/boards/sof_sdw.c | 1 + 1 file changed, 1 insertion(+)
diff --git a/sound/soc/intel/boards/sof_sdw.c b/sound/soc/intel/boards/sof_sdw.c index 85a2797c2550..5827a16773c9 100644 --- a/sound/soc/intel/boards/sof_sdw.c +++ b/sound/soc/intel/boards/sof_sdw.c @@ -196,6 +196,7 @@ static const struct dmi_system_id sof_sdw_quirk_table[] = { }, .driver_data = (void *)(SOF_RT711_JD_SRC_JD1 | SOF_SDW_TGL_HDMI | + SOF_RT715_DAI_ID_FIX | SOF_SDW_PCH_DMIC), }, {}
From: Robin Gong yibin.gong@nxp.com
[ Upstream commit f0c07993af0acf5545d5c1445798846565f4f147 ]
For fix below warning reported by static code analysis tool like Coverity from Synopsys:
Signed-off-by: Robin Gong yibin.gong@nxp.com Addresses-Coverity-ID: 12285639 ("Unchecked return value") Link: https://lore.kernel.org/r/1619427549-20498-1-git-send-email-yibin.gong@nxp.c... Signed-off-by: Vinod Koul vkoul@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/dma/fsl-qdma.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-)
diff --git a/drivers/dma/fsl-qdma.c b/drivers/dma/fsl-qdma.c index ed2ab46b15e7..045ead46ec8f 100644 --- a/drivers/dma/fsl-qdma.c +++ b/drivers/dma/fsl-qdma.c @@ -1235,7 +1235,11 @@ static int fsl_qdma_probe(struct platform_device *pdev) fsl_qdma->dma_dev.device_synchronize = fsl_qdma_synchronize; fsl_qdma->dma_dev.device_terminate_all = fsl_qdma_terminate_all;
- dma_set_mask(&pdev->dev, DMA_BIT_MASK(40)); + ret = dma_set_mask(&pdev->dev, DMA_BIT_MASK(40)); + if (ret) { + dev_err(&pdev->dev, "dma_set_mask failure.\n"); + return ret; + }
platform_set_drvdata(pdev, fsl_qdma);
From: ching Huang ching2048@areca.com.tw
[ Upstream commit 5b8644968d2ca85abb785e83efec36934974b0c2 ]
This patch fixes the wrong CDB payload report to IOP.
Link: https://lore.kernel.org/r/d2c97df3c817595c6faf582839316209022f70da.camel@are... Signed-off-by: ching Huang ching2048@areca.com.tw Signed-off-by: Martin K. Petersen martin.petersen@oracle.com Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/scsi/arcmsr/arcmsr_hba.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-)
diff --git a/drivers/scsi/arcmsr/arcmsr_hba.c b/drivers/scsi/arcmsr/arcmsr_hba.c index 4b79661275c9..930972cda38c 100644 --- a/drivers/scsi/arcmsr/arcmsr_hba.c +++ b/drivers/scsi/arcmsr/arcmsr_hba.c @@ -1923,8 +1923,12 @@ static void arcmsr_post_ccb(struct AdapterControlBlock *acb, struct CommandContr
if (ccb->arc_cdb_size <= 0x300) arc_cdb_size = (ccb->arc_cdb_size - 1) >> 6 | 1; - else - arc_cdb_size = (((ccb->arc_cdb_size + 0xff) >> 8) + 2) << 1 | 1; + else { + arc_cdb_size = ((ccb->arc_cdb_size + 0xff) >> 8) + 2; + if (arc_cdb_size > 0xF) + arc_cdb_size = 0xF; + arc_cdb_size = (arc_cdb_size << 1) | 1; + } ccb_post_stamp = (ccb->smid | arc_cdb_size); writel(0, &pmu->inbound_queueport_high); writel(ccb_post_stamp, &pmu->inbound_queueport_low);
From: Frederic Weisbecker frederic@kernel.org
[ Upstream commit b5befe842e6612cf894cf4a199924ee872d8b7d8 ]
An srcu_struct structure that is initialized before rcu_init_geometry() will have its srcu_node hierarchy based on CONFIG_NR_CPUS. Once rcu_init_geometry() is called, this hierarchy is compressed as needed for the actual maximum number of CPUs for this system.
Later on, that srcu_struct structure is confused, sometimes referring to its initial CONFIG_NR_CPUS-based hierarchy, and sometimes instead to the new num_possible_cpus() hierarchy. For example, each of its ->mynode fields continues to reference the original leaf rcu_node structures, some of which might no longer exist. On the other hand, srcu_for_each_node_breadth_first() traverses to the new node hierarchy.
There are at least two bad possible outcomes to this:
1) a) A callback enqueued early on an srcu_data structure (call it *sdp) is recorded pending on sdp->mynode->srcu_data_have_cbs in srcu_funnel_gp_start() with sdp->mynode pointing to a deep leaf (say 3 levels).
b) The grace period ends after rcu_init_geometry() shrinks the nodes level to a single one. srcu_gp_end() walks through the new srcu_node hierarchy without ever reaching the old leaves so the callback is never executed.
This is easily reproduced on an 8 CPUs machine with CONFIG_NR_CPUS >= 32 and "rcupdate.rcu_self_test=1". The srcu_barrier() after early tests verification never completes and the boot hangs:
[ 5413.141029] INFO: task swapper/0:1 blocked for more than 4915 seconds. [ 5413.147564] Not tainted 5.12.0-rc4+ #28 [ 5413.151927] "echo 0 > /proc/sys/kernel/hung_task_timeout_secs" disables this message. [ 5413.159753] task:swapper/0 state:D stack: 0 pid: 1 ppid: 0 flags:0x00004000 [ 5413.168099] Call Trace: [ 5413.170555] __schedule+0x36c/0x930 [ 5413.174057] ? wait_for_completion+0x88/0x110 [ 5413.178423] schedule+0x46/0xf0 [ 5413.181575] schedule_timeout+0x284/0x380 [ 5413.185591] ? wait_for_completion+0x88/0x110 [ 5413.189957] ? mark_held_locks+0x61/0x80 [ 5413.193882] ? mark_held_locks+0x61/0x80 [ 5413.197809] ? _raw_spin_unlock_irq+0x24/0x50 [ 5413.202173] ? wait_for_completion+0x88/0x110 [ 5413.206535] wait_for_completion+0xb4/0x110 [ 5413.210724] ? srcu_torture_stats_print+0x110/0x110 [ 5413.215610] srcu_barrier+0x187/0x200 [ 5413.219277] ? rcu_tasks_verify_self_tests+0x50/0x50 [ 5413.224244] ? rdinit_setup+0x2b/0x2b [ 5413.227907] rcu_verify_early_boot_tests+0x2d/0x40 [ 5413.232700] do_one_initcall+0x63/0x310 [ 5413.236541] ? rdinit_setup+0x2b/0x2b [ 5413.240207] ? rcu_read_lock_sched_held+0x52/0x80 [ 5413.244912] kernel_init_freeable+0x253/0x28f [ 5413.249273] ? rest_init+0x250/0x250 [ 5413.252846] kernel_init+0xa/0x110 [ 5413.256257] ret_from_fork+0x22/0x30
2) An srcu_struct structure that is initialized before rcu_init_geometry() and used afterward will always have stale rdp->mynode references, resulting in callbacks to be missed in srcu_gp_end(), just like in the previous scenario.
This commit therefore causes init_srcu_struct_nodes to initialize the geometry, if needed. This ensures that the srcu_node hierarchy is properly built and distributed from the get-go.
Suggested-by: Paul E. McKenney paulmck@kernel.org Signed-off-by: Frederic Weisbecker frederic@kernel.org Cc: Boqun Feng boqun.feng@gmail.com Cc: Lai Jiangshan jiangshanlai@gmail.com Cc: Neeraj Upadhyay neeraju@codeaurora.org Cc: Josh Triplett josh@joshtriplett.org Cc: Joel Fernandes joel@joelfernandes.org Cc: Uladzislau Rezki urezki@gmail.com Signed-off-by: Paul E. McKenney paulmck@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- kernel/rcu/rcu.h | 2 ++ kernel/rcu/srcutree.c | 3 +++ kernel/rcu/tree.c | 16 +++++++++++++++- 3 files changed, 20 insertions(+), 1 deletion(-)
diff --git a/kernel/rcu/rcu.h b/kernel/rcu/rcu.h index bf0827d4b659..cfd06fb5ba6d 100644 --- a/kernel/rcu/rcu.h +++ b/kernel/rcu/rcu.h @@ -308,6 +308,8 @@ static inline void rcu_init_levelspread(int *levelspread, const int *levelcnt) } }
+extern void rcu_init_geometry(void); + /* Returns a pointer to the first leaf rcu_node structure. */ #define rcu_first_leaf_node() (rcu_state.level[rcu_num_lvls - 1])
diff --git a/kernel/rcu/srcutree.c b/kernel/rcu/srcutree.c index e26547b34ad3..072e47288f1f 100644 --- a/kernel/rcu/srcutree.c +++ b/kernel/rcu/srcutree.c @@ -90,6 +90,9 @@ static void init_srcu_struct_nodes(struct srcu_struct *ssp, bool is_static) struct srcu_node *snp; struct srcu_node *snp_first;
+ /* Initialize geometry if it has not already been initialized. */ + rcu_init_geometry(); + /* Work out the overall tree geometry. */ ssp->level[0] = &ssp->node[0]; for (i = 1; i < rcu_num_lvls; i++) diff --git a/kernel/rcu/tree.c b/kernel/rcu/tree.c index 8e78b2430c16..1fa5f5c2654b 100644 --- a/kernel/rcu/tree.c +++ b/kernel/rcu/tree.c @@ -4582,11 +4582,25 @@ static void __init rcu_init_one(void) * replace the definitions in tree.h because those are needed to size * the ->node array in the rcu_state structure. */ -static void __init rcu_init_geometry(void) +void rcu_init_geometry(void) { ulong d; int i; + static unsigned long old_nr_cpu_ids; int rcu_capacity[RCU_NUM_LVLS]; + static bool initialized; + + if (initialized) { + /* + * Warn if setup_nr_cpu_ids() had not yet been invoked, + * unless nr_cpus_ids == NR_CPUS, in which case who cares? + */ + WARN_ON_ONCE(old_nr_cpu_ids != nr_cpu_ids); + return; + } + + old_nr_cpu_ids = nr_cpu_ids; + initialized = true;
/* * Initialize any unspecified boot parameters.
From: "Paul E. McKenney" paulmck@kernel.org
[ Upstream commit 3066820034b5dd4e89bd74a7739c51c2d6f5e554 ]
If another lockdep report runs concurrently with an RCU lockdep report from RCU_LOCKDEP_WARN(), the following sequence of events can occur:
1. debug_lockdep_rcu_enabled() sees that lockdep is enabled when called from (say) synchronize_rcu().
2. Lockdep is disabled by a concurrent lockdep report.
3. debug_lockdep_rcu_enabled() evaluates its lockdep-expression argument, for example, lock_is_held(&rcu_bh_lock_map).
4. Because lockdep is now disabled, lock_is_held() plays it safe and returns the constant 1.
5. But in this case, the constant 1 is not safe, because invoking synchronize_rcu() under rcu_read_lock_bh() is disallowed.
6. debug_lockdep_rcu_enabled() wrongly invokes lockdep_rcu_suspicious(), resulting in a false-positive splat.
This commit therefore changes RCU_LOCKDEP_WARN() to check debug_lockdep_rcu_enabled() after checking the lockdep expression, so that any "safe" returns from lock_is_held() are rejected by debug_lockdep_rcu_enabled(). This requires memory ordering, which is supplied by READ_ONCE(debug_locks). The resulting volatile accesses prevent the compiler from reordering and the fact that only one variable is being accessed prevents the underlying hardware from reordering. The combination works for IA64, which can reorder reads to the same location, but this is defeated by the volatile accesses, which compile to load instructions that provide ordering.
Reported-by: syzbot+dde0cc33951735441301@syzkaller.appspotmail.com Reported-by: Matthew Wilcox willy@infradead.org Reported-by: syzbot+88e4f02896967fe1ab0d@syzkaller.appspotmail.com Reported-by: Thomas Gleixner tglx@linutronix.de Suggested-by: Boqun Feng boqun.feng@gmail.com Reviewed-by: Boqun Feng boqun.feng@gmail.com Signed-off-by: Paul E. McKenney paulmck@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- include/linux/rcupdate.h | 2 +- kernel/rcu/update.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/include/linux/rcupdate.h b/include/linux/rcupdate.h index 9455476c5ba2..1199ffd305d1 100644 --- a/include/linux/rcupdate.h +++ b/include/linux/rcupdate.h @@ -315,7 +315,7 @@ static inline int rcu_read_lock_any_held(void) #define RCU_LOCKDEP_WARN(c, s) \ do { \ static bool __section(".data.unlikely") __warned; \ - if (debug_lockdep_rcu_enabled() && !__warned && (c)) { \ + if ((c) && debug_lockdep_rcu_enabled() && !__warned) { \ __warned = true; \ lockdep_rcu_suspicious(__FILE__, __LINE__, s); \ } \ diff --git a/kernel/rcu/update.c b/kernel/rcu/update.c index b95ae86c40a7..dd94a602a6d2 100644 --- a/kernel/rcu/update.c +++ b/kernel/rcu/update.c @@ -277,7 +277,7 @@ EXPORT_SYMBOL_GPL(rcu_callback_map);
noinstr int notrace debug_lockdep_rcu_enabled(void) { - return rcu_scheduler_active != RCU_SCHEDULER_INACTIVE && debug_locks && + return rcu_scheduler_active != RCU_SCHEDULER_INACTIVE && READ_ONCE(debug_locks) && current->lockdep_recursion == 0; } EXPORT_SYMBOL_GPL(debug_lockdep_rcu_enabled);
From: Pierre-Louis Bossart pierre-louis.bossart@linux.intel.com
[ Upstream commit 345e9f5ca798600e44c0843646621f2804eb99f4 ]
Existing devices and implementations only support the required CLOCK_STOP_MODE0. All the code related to CLOCK_STOP_MODE1 has not been tested and is highly questionable, with a clear confusion between CLOCK_STOP_MODE1 and the simple clock stop state machine.
This patch removes all usages of CLOCK_STOP_MODE1 - which has no impact on any solution - and fixes the use of the simple clock stop state machine. The resulting code should be a lot more symmetrical and easier to maintain.
Note that CLOCK_STOP_MODE1 is not supported in the SoundWire Device Class specification so it's rather unlikely that we need to re-add this mode later.
Signed-off-by: Pierre-Louis Bossart pierre-louis.bossart@linux.intel.com Reviewed-by: Guennadi Liakhovetski guennadi.liakhovetski@linux.intel.com Reviewed-by: Rander Wang rander.wang@intel.com Signed-off-by: Bard Liao yung-chuan.liao@linux.intel.com Link: https://lore.kernel.org/r/20210511030048.25622-2-yung-chuan.liao@linux.intel... Signed-off-by: Vinod Koul vkoul@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/soundwire/bus.c | 100 ++++++++++++++-------------------- include/linux/soundwire/sdw.h | 2 - 2 files changed, 40 insertions(+), 62 deletions(-)
diff --git a/drivers/soundwire/bus.c b/drivers/soundwire/bus.c index a9e0aa72654d..dc4033b6f2e9 100644 --- a/drivers/soundwire/bus.c +++ b/drivers/soundwire/bus.c @@ -821,26 +821,6 @@ static void sdw_modify_slave_status(struct sdw_slave *slave, mutex_unlock(&bus->bus_lock); }
-static enum sdw_clk_stop_mode sdw_get_clk_stop_mode(struct sdw_slave *slave) -{ - enum sdw_clk_stop_mode mode; - - /* - * Query for clock stop mode if Slave implements - * ops->get_clk_stop_mode, else read from property. - */ - if (slave->ops && slave->ops->get_clk_stop_mode) { - mode = slave->ops->get_clk_stop_mode(slave); - } else { - if (slave->prop.clk_stop_mode1) - mode = SDW_CLK_STOP_MODE1; - else - mode = SDW_CLK_STOP_MODE0; - } - - return mode; -} - static int sdw_slave_clk_stop_callback(struct sdw_slave *slave, enum sdw_clk_stop_mode mode, enum sdw_clk_stop_type type) @@ -933,7 +913,6 @@ static int sdw_bus_wait_for_clk_prep_deprep(struct sdw_bus *bus, u16 dev_num) */ int sdw_bus_prep_clk_stop(struct sdw_bus *bus) { - enum sdw_clk_stop_mode slave_mode; bool simple_clk_stop = true; struct sdw_slave *slave; bool is_slave = false; @@ -955,10 +934,8 @@ int sdw_bus_prep_clk_stop(struct sdw_bus *bus) /* Identify if Slave(s) are available on Bus */ is_slave = true;
- slave_mode = sdw_get_clk_stop_mode(slave); - slave->curr_clk_stop_mode = slave_mode; - - ret = sdw_slave_clk_stop_callback(slave, slave_mode, + ret = sdw_slave_clk_stop_callback(slave, + SDW_CLK_STOP_MODE0, SDW_CLK_PRE_PREPARE); if (ret < 0) { dev_err(&slave->dev, @@ -966,22 +943,29 @@ int sdw_bus_prep_clk_stop(struct sdw_bus *bus) return ret; }
- ret = sdw_slave_clk_stop_prepare(slave, - slave_mode, true); - if (ret < 0) { - dev_err(&slave->dev, - "pre-prepare failed:%d", ret); - return ret; - } - - if (slave_mode == SDW_CLK_STOP_MODE1) + /* Only prepare a Slave device if needed */ + if (!slave->prop.simple_clk_stop_capable) { simple_clk_stop = false; + + ret = sdw_slave_clk_stop_prepare(slave, + SDW_CLK_STOP_MODE0, + true); + if (ret < 0) { + dev_err(&slave->dev, + "pre-prepare failed:%d", ret); + return ret; + } + } }
/* Skip remaining clock stop preparation if no Slave is attached */ if (!is_slave) return ret;
+ /* + * Don't wait for all Slaves to be ready if they follow the simple + * state machine + */ if (!simple_clk_stop) { ret = sdw_bus_wait_for_clk_prep_deprep(bus, SDW_BROADCAST_DEV_NUM); @@ -998,17 +982,13 @@ int sdw_bus_prep_clk_stop(struct sdw_bus *bus) slave->status != SDW_SLAVE_ALERT) continue;
- slave_mode = slave->curr_clk_stop_mode; - - if (slave_mode == SDW_CLK_STOP_MODE1) { - ret = sdw_slave_clk_stop_callback(slave, - slave_mode, - SDW_CLK_POST_PREPARE); + ret = sdw_slave_clk_stop_callback(slave, + SDW_CLK_STOP_MODE0, + SDW_CLK_POST_PREPARE);
- if (ret < 0) { - dev_err(&slave->dev, - "post-prepare failed:%d", ret); - } + if (ret < 0) { + dev_err(&slave->dev, + "post-prepare failed:%d", ret); } }
@@ -1059,7 +1039,6 @@ EXPORT_SYMBOL(sdw_bus_clk_stop); */ int sdw_bus_exit_clk_stop(struct sdw_bus *bus) { - enum sdw_clk_stop_mode mode; bool simple_clk_stop = true; struct sdw_slave *slave; bool is_slave = false; @@ -1081,31 +1060,33 @@ int sdw_bus_exit_clk_stop(struct sdw_bus *bus) /* Identify if Slave(s) are available on Bus */ is_slave = true;
- mode = slave->curr_clk_stop_mode; - - if (mode == SDW_CLK_STOP_MODE1) { - simple_clk_stop = false; - continue; - } - - ret = sdw_slave_clk_stop_callback(slave, mode, + ret = sdw_slave_clk_stop_callback(slave, SDW_CLK_STOP_MODE0, SDW_CLK_PRE_DEPREPARE); if (ret < 0) dev_warn(&slave->dev, "clk stop deprep failed:%d", ret);
- ret = sdw_slave_clk_stop_prepare(slave, mode, - false); + /* Only de-prepare a Slave device if needed */ + if (!slave->prop.simple_clk_stop_capable) { + simple_clk_stop = false;
- if (ret < 0) - dev_warn(&slave->dev, - "clk stop deprep failed:%d", ret); + ret = sdw_slave_clk_stop_prepare(slave, SDW_CLK_STOP_MODE0, + false); + + if (ret < 0) + dev_warn(&slave->dev, + "clk stop deprep failed:%d", ret); + } }
/* Skip remaining clock stop de-preparation if no Slave is attached */ if (!is_slave) return 0;
+ /* + * Don't wait for all Slaves to be ready if they follow the simple + * state machine + */ if (!simple_clk_stop) sdw_bus_wait_for_clk_prep_deprep(bus, SDW_BROADCAST_DEV_NUM);
@@ -1117,8 +1098,7 @@ int sdw_bus_exit_clk_stop(struct sdw_bus *bus) slave->status != SDW_SLAVE_ALERT) continue;
- mode = slave->curr_clk_stop_mode; - sdw_slave_clk_stop_callback(slave, mode, + sdw_slave_clk_stop_callback(slave, SDW_CLK_STOP_MODE0, SDW_CLK_POST_DEPREPARE); }
diff --git a/include/linux/soundwire/sdw.h b/include/linux/soundwire/sdw.h index ced07f8fde87..5d93d9949653 100644 --- a/include/linux/soundwire/sdw.h +++ b/include/linux/soundwire/sdw.h @@ -624,7 +624,6 @@ struct sdw_slave_ops { int (*port_prep)(struct sdw_slave *slave, struct sdw_prepare_ch *prepare_ch, enum sdw_port_prep_ops pre_ops); - int (*get_clk_stop_mode)(struct sdw_slave *slave); int (*clk_stop)(struct sdw_slave *slave, enum sdw_clk_stop_mode mode, enum sdw_clk_stop_type type); @@ -675,7 +674,6 @@ struct sdw_slave { struct list_head node; struct completion port_ready[SDW_MAX_PORTS]; unsigned int m_port_map[SDW_MAX_PORTS]; - enum sdw_clk_stop_mode curr_clk_stop_mode; u16 dev_num; u16 dev_num_sticky; bool probed;
From: Pierre-Louis Bossart pierre-louis.bossart@linux.intel.com
[ Upstream commit b50bb8ba369cdc8814e82558117711c12ef3af3d ]
If a device lost sync and can no longer ACK a command, it may not be able to enter a lower-power state but it will still be able to resync when the clock restarts. In those cases, we want to continue with the clock stop sequence.
This patch modifies the behavior during clock stop sequences to only log errors unrelated to -ENODATA/Command_Ignored. The flow is also modified so that loops continue to prepare/deprepare other devices even when one seems to have lost sync.
When resuming the clocks, all issues are logged with a dev_warn(), previously only some of them were checked. This is the only part that now differs between the clock stop entry and clock stop exit sequences: while we don't want to stop the suspend flow, we do want information on potential issues while resuming, as they may have ripple effects.
For consistency the log messages are also modified to be unique and self-explanatory. Errors in sdw_slave_clk_stop_callback() were removed, they are now handled in the caller.
Signed-off-by: Pierre-Louis Bossart pierre-louis.bossart@linux.intel.com Reviewed-by: Guennadi Liakhovetski guennadi.liakhovetski@linux.intel.com Reviewed-by: Rander Wang rander.wang@intel.com Signed-off-by: Bard Liao yung-chuan.liao@linux.intel.com Link: https://lore.kernel.org/r/20210511030048.25622-4-yung-chuan.liao@linux.intel... Signed-off-by: Vinod Koul vkoul@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/soundwire/bus.c | 69 +++++++++++++++++++++-------------------- 1 file changed, 36 insertions(+), 33 deletions(-)
diff --git a/drivers/soundwire/bus.c b/drivers/soundwire/bus.c index dc4033b6f2e9..100d904bf700 100644 --- a/drivers/soundwire/bus.c +++ b/drivers/soundwire/bus.c @@ -829,11 +829,8 @@ static int sdw_slave_clk_stop_callback(struct sdw_slave *slave,
if (slave->ops && slave->ops->clk_stop) { ret = slave->ops->clk_stop(slave, mode, type); - if (ret < 0) { - dev_err(&slave->dev, - "Clk Stop type =%d failed: %d\n", type, ret); + if (ret < 0) return ret; - } }
return 0; @@ -860,7 +857,8 @@ static int sdw_slave_clk_stop_prepare(struct sdw_slave *slave, } else { ret = sdw_read_no_pm(slave, SDW_SCP_SYSTEMCTRL); if (ret < 0) { - dev_err(&slave->dev, "SDW_SCP_SYSTEMCTRL read failed:%d\n", ret); + if (ret != -ENODATA) + dev_err(&slave->dev, "SDW_SCP_SYSTEMCTRL read failed:%d\n", ret); return ret; } val = ret; @@ -869,9 +867,8 @@ static int sdw_slave_clk_stop_prepare(struct sdw_slave *slave,
ret = sdw_write_no_pm(slave, SDW_SCP_SYSTEMCTRL, val);
- if (ret < 0) - dev_err(&slave->dev, - "Clock Stop prepare failed for slave: %d", ret); + if (ret < 0 && ret != -ENODATA) + dev_err(&slave->dev, "SDW_SCP_SYSTEMCTRL write failed:%d\n", ret);
return ret; } @@ -922,6 +919,9 @@ int sdw_bus_prep_clk_stop(struct sdw_bus *bus) * In order to save on transition time, prepare * each Slave and then wait for all Slave(s) to be * prepared for clock stop. + * If one of the Slave devices has lost sync and + * replies with Command Ignored/-ENODATA, we continue + * the loop */ list_for_each_entry(slave, &bus->slaves, node) { if (!slave->dev_num) @@ -937,9 +937,8 @@ int sdw_bus_prep_clk_stop(struct sdw_bus *bus) ret = sdw_slave_clk_stop_callback(slave, SDW_CLK_STOP_MODE0, SDW_CLK_PRE_PREPARE); - if (ret < 0) { - dev_err(&slave->dev, - "pre-prepare failed:%d", ret); + if (ret < 0 && ret != -ENODATA) { + dev_err(&slave->dev, "clock stop pre-prepare cb failed:%d\n", ret); return ret; }
@@ -950,9 +949,8 @@ int sdw_bus_prep_clk_stop(struct sdw_bus *bus) ret = sdw_slave_clk_stop_prepare(slave, SDW_CLK_STOP_MODE0, true); - if (ret < 0) { - dev_err(&slave->dev, - "pre-prepare failed:%d", ret); + if (ret < 0 && ret != -ENODATA) { + dev_err(&slave->dev, "clock stop prepare failed:%d\n", ret); return ret; } } @@ -960,7 +958,7 @@ int sdw_bus_prep_clk_stop(struct sdw_bus *bus)
/* Skip remaining clock stop preparation if no Slave is attached */ if (!is_slave) - return ret; + return 0;
/* * Don't wait for all Slaves to be ready if they follow the simple @@ -969,6 +967,12 @@ int sdw_bus_prep_clk_stop(struct sdw_bus *bus) if (!simple_clk_stop) { ret = sdw_bus_wait_for_clk_prep_deprep(bus, SDW_BROADCAST_DEV_NUM); + /* + * if there are no Slave devices present and the reply is + * Command_Ignored/-ENODATA, we don't need to continue with the + * flow and can just return here. The error code is not modified + * and its handling left as an exercise for the caller. + */ if (ret < 0) return ret; } @@ -986,13 +990,13 @@ int sdw_bus_prep_clk_stop(struct sdw_bus *bus) SDW_CLK_STOP_MODE0, SDW_CLK_POST_PREPARE);
- if (ret < 0) { - dev_err(&slave->dev, - "post-prepare failed:%d", ret); + if (ret < 0 && ret != -ENODATA) { + dev_err(&slave->dev, "clock stop post-prepare cb failed:%d\n", ret); + return ret; } }
- return ret; + return 0; } EXPORT_SYMBOL(sdw_bus_prep_clk_stop);
@@ -1015,12 +1019,8 @@ int sdw_bus_clk_stop(struct sdw_bus *bus) ret = sdw_bwrite_no_pm(bus, SDW_BROADCAST_DEV_NUM, SDW_SCP_CTRL, SDW_SCP_CTRL_CLK_STP_NOW); if (ret < 0) { - if (ret == -ENODATA) - dev_dbg(bus->dev, - "ClockStopNow Broadcast msg ignored %d", ret); - else - dev_err(bus->dev, - "ClockStopNow Broadcast msg failed %d", ret); + if (ret != -ENODATA) + dev_err(bus->dev, "ClockStopNow Broadcast msg failed %d\n", ret); return ret; }
@@ -1063,8 +1063,7 @@ int sdw_bus_exit_clk_stop(struct sdw_bus *bus) ret = sdw_slave_clk_stop_callback(slave, SDW_CLK_STOP_MODE0, SDW_CLK_PRE_DEPREPARE); if (ret < 0) - dev_warn(&slave->dev, - "clk stop deprep failed:%d", ret); + dev_warn(&slave->dev, "clock stop pre-deprepare cb failed:%d\n", ret);
/* Only de-prepare a Slave device if needed */ if (!slave->prop.simple_clk_stop_capable) { @@ -1074,8 +1073,7 @@ int sdw_bus_exit_clk_stop(struct sdw_bus *bus) false);
if (ret < 0) - dev_warn(&slave->dev, - "clk stop deprep failed:%d", ret); + dev_warn(&slave->dev, "clock stop deprepare failed:%d\n", ret); } }
@@ -1087,8 +1085,11 @@ int sdw_bus_exit_clk_stop(struct sdw_bus *bus) * Don't wait for all Slaves to be ready if they follow the simple * state machine */ - if (!simple_clk_stop) - sdw_bus_wait_for_clk_prep_deprep(bus, SDW_BROADCAST_DEV_NUM); + if (!simple_clk_stop) { + ret = sdw_bus_wait_for_clk_prep_deprep(bus, SDW_BROADCAST_DEV_NUM); + if (ret < 0) + dev_warn(&slave->dev, "clock stop deprepare wait failed:%d\n", ret); + }
list_for_each_entry(slave, &bus->slaves, node) { if (!slave->dev_num) @@ -1098,8 +1099,10 @@ int sdw_bus_exit_clk_stop(struct sdw_bus *bus) slave->status != SDW_SLAVE_ALERT) continue;
- sdw_slave_clk_stop_callback(slave, SDW_CLK_STOP_MODE0, - SDW_CLK_POST_DEPREPARE); + ret = sdw_slave_clk_stop_callback(slave, SDW_CLK_STOP_MODE0, + SDW_CLK_POST_DEPREPARE); + if (ret < 0) + dev_warn(&slave->dev, "clock stop post-deprepare cb failed:%d\n", ret); }
return 0;
From: Raymond Tan raymond.tan@intel.com
[ Upstream commit 457d22850b27de3aea336108272d08602c55fdf7 ]
There's no separate low power (LP) version of Elkhart Lake, thus this patch updates the PCI Device ID DEFINE to indicate this.
Acked-by: Felipe Balbi balbi@kernel.org Signed-off-by: Raymond Tan raymond.tan@intel.com Signed-off-by: Heikki Krogerus heikki.krogerus@linux.intel.com Link: https://lore.kernel.org/r/20210512135901.28495-1-heikki.krogerus@linux.intel... Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/usb/dwc3/dwc3-pci.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/drivers/usb/dwc3/dwc3-pci.c b/drivers/usb/dwc3/dwc3-pci.c index 1e51460938b8..2b37bdd39a74 100644 --- a/drivers/usb/dwc3/dwc3-pci.c +++ b/drivers/usb/dwc3/dwc3-pci.c @@ -36,7 +36,7 @@ #define PCI_DEVICE_ID_INTEL_CNPH 0xa36e #define PCI_DEVICE_ID_INTEL_CNPV 0xa3b0 #define PCI_DEVICE_ID_INTEL_ICLLP 0x34ee -#define PCI_DEVICE_ID_INTEL_EHLLP 0x4b7e +#define PCI_DEVICE_ID_INTEL_EHL 0x4b7e #define PCI_DEVICE_ID_INTEL_TGPLP 0xa0ee #define PCI_DEVICE_ID_INTEL_TGPH 0x43ee #define PCI_DEVICE_ID_INTEL_JSP 0x4dee @@ -167,7 +167,7 @@ static int dwc3_pci_quirks(struct dwc3_pci *dwc) if (pdev->vendor == PCI_VENDOR_ID_INTEL) { if (pdev->device == PCI_DEVICE_ID_INTEL_BXT || pdev->device == PCI_DEVICE_ID_INTEL_BXT_M || - pdev->device == PCI_DEVICE_ID_INTEL_EHLLP) { + pdev->device == PCI_DEVICE_ID_INTEL_EHL) { guid_parse(PCI_INTEL_BXT_DSM_GUID, &dwc->guid); dwc->has_dsm_for_pm = true; } @@ -375,8 +375,8 @@ static const struct pci_device_id dwc3_pci_id_table[] = { { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_ICLLP), (kernel_ulong_t) &dwc3_pci_intel_swnode, },
- { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_EHLLP), - (kernel_ulong_t) &dwc3_pci_intel_swnode }, + { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_EHL), + (kernel_ulong_t) &dwc3_pci_intel_swnode, },
{ PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_TGPLP), (kernel_ulong_t) &dwc3_pci_intel_swnode, },
From: Sherry Sun sherry.sun@nxp.com
[ Upstream commit fcb10ee27fb91b25b68d7745db9817ecea9f1038 ]
We should be very careful about the register values that will be used for division or modulo operations, althrough the possibility that the UARTBAUD register value is zero is very low, but we had better to deal with the "bad data" of hardware in advance to avoid division or modulo by zero leading to undefined kernel behavior.
Signed-off-by: Sherry Sun sherry.sun@nxp.com Link: https://lore.kernel.org/r/20210427021226.27468-1-sherry.sun@nxp.com Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/tty/serial/fsl_lpuart.c | 3 +++ 1 file changed, 3 insertions(+)
diff --git a/drivers/tty/serial/fsl_lpuart.c b/drivers/tty/serial/fsl_lpuart.c index 794035041744..777d54b593f8 100644 --- a/drivers/tty/serial/fsl_lpuart.c +++ b/drivers/tty/serial/fsl_lpuart.c @@ -2414,6 +2414,9 @@ lpuart32_console_get_options(struct lpuart_port *sport, int *baud,
bd = lpuart32_read(&sport->port, UARTBAUD); bd &= UARTBAUD_SBR_MASK; + if (!bd) + return; + sbr = bd; uartclk = lpuart_get_baud_clk_rate(sport); /*
From: Michael Walle michael@walle.cc
[ Upstream commit 8cac2f6eb8548245e6f8fb893fc7f2a714952654 ]
SYSRQ doesn't work with DMA. This is because there is no error indication whether a symbol had a framing error or not. Actually, this is not completely correct, there is a bit in the data register which is set in this case, but we'd have to read change the DMA access to 16 bit and we'd need to post process the data, thus make the DMA pointless in the first place.
Signed-off-by: Michael Walle michael@walle.cc Link: https://lore.kernel.org/r/20210512141255.18277-10-michael@walle.cc Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/tty/serial/fsl_lpuart.c | 6 ++++++ 1 file changed, 6 insertions(+)
diff --git a/drivers/tty/serial/fsl_lpuart.c b/drivers/tty/serial/fsl_lpuart.c index 777d54b593f8..109131b84945 100644 --- a/drivers/tty/serial/fsl_lpuart.c +++ b/drivers/tty/serial/fsl_lpuart.c @@ -1581,6 +1581,9 @@ static void lpuart_tx_dma_startup(struct lpuart_port *sport) u32 uartbaud; int ret;
+ if (uart_console(&sport->port)) + goto err; + if (!sport->dma_tx_chan) goto err;
@@ -1610,6 +1613,9 @@ static void lpuart_rx_dma_startup(struct lpuart_port *sport) int ret; unsigned char cr3;
+ if (uart_console(&sport->port)) + goto err; + if (!sport->dma_rx_chan) goto err;
From: Jim Quinlan jim2101024@gmail.com
[ Upstream commit f5b08386dee439c7a9e60ce0a4a4a705f3a60dff ]
Our SoC's have always had a NS16650A UART core and older SoC's would have a compatible string of: 'compatible = ""ns16550a"' and use the 8250_of driver. Our newer SoC's have added enhancements to the base core to add support for DMA and accurate high speed baud rates and use this newer 8250_bcm7271 driver. The Device Tree node for our enhanced UARTs has a compatible string of: 'compatible = "brcm,bcm7271-uart", "ns16550a"''. With both drivers running and the link order setup so that the 8250_bcm7217 driver is initialized before the 8250_of driver, we should bind the 8250_bcm7271 driver to the enhanced UART, or for upstream kernels that don't have the 8250_bcm7271 driver, we bind to the 8250_of driver.
The problem is that when both the 8250_of and 8250_bcm7271 drivers were running, occasionally the 8250_of driver would be bound to the enhanced UART instead of the 8250_bcm7271 driver. This was happening because we use SCMI based clocks which come up late in initialization and cause probe DEFER's when the two drivers get their clocks.
Occasionally the SCMI clock would become ready between the 8250_bcm7271 probe and the 8250_of probe and the 8250_of driver would be bound. To fix this we decided to config only our 8250_bcm7271 driver and added "ns16665a0" to the compatible string so the driver would work on our older system.
This commit has of_platform_serial_probe() check specifically for the "brcm,bcm7271-uart" and whether its companion driver is enabled. If it is the case, and the clock provider is not ready, we want to make sure that when the 8250_bcm7271.c driver returns EPROBE_DEFER, we are not getting the UART registered via 8250_of.c.
Reviewed-by: Andy Shevchenko andy.shevchenko@gmail.com Signed-off-by: Jim Quinlan jim2101024@gmail.com Signed-off-by: Al Cooper alcooperx@gmail.com Signed-off-by: Florian Fainelli f.fainelli@gmail.com Link: https://lore.kernel.org/r/20210423183206.3917725-1-f.fainelli@gmail.com Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/tty/serial/8250/8250_of.c | 4 ++++ 1 file changed, 4 insertions(+)
diff --git a/drivers/tty/serial/8250/8250_of.c b/drivers/tty/serial/8250/8250_of.c index 0b077b45d6a9..bce28729dd7b 100644 --- a/drivers/tty/serial/8250/8250_of.c +++ b/drivers/tty/serial/8250/8250_of.c @@ -192,6 +192,10 @@ static int of_platform_serial_probe(struct platform_device *ofdev) u32 tx_threshold; int ret;
+ if (IS_ENABLED(CONFIG_SERIAL_8250_BCM7271) && + of_device_is_compatible(ofdev->dev.of_node, "brcm,bcm7271-uart")) + return -ENODEV; + port_type = (unsigned long)of_device_get_match_data(&ofdev->dev); if (port_type == PORT_UNKNOWN) return -EINVAL;
On 7/9/2021 7:16 PM, Sasha Levin wrote:
From: Jim Quinlan jim2101024@gmail.com
[ Upstream commit f5b08386dee439c7a9e60ce0a4a4a705f3a60dff ]
Our SoC's have always had a NS16650A UART core and older SoC's would have a compatible string of: 'compatible = ""ns16550a"' and use the 8250_of driver. Our newer SoC's have added enhancements to the base core to add support for DMA and accurate high speed baud rates and use this newer 8250_bcm7271 driver. The Device Tree node for our enhanced UARTs has a compatible string of: 'compatible = "brcm,bcm7271-uart", "ns16550a"''. With both drivers running and the link order setup so that the 8250_bcm7217 driver is initialized before the 8250_of driver, we should bind the 8250_bcm7271 driver to the enhanced UART, or for upstream kernels that don't have the 8250_bcm7271 driver, we bind to the 8250_of driver.
The problem is that when both the 8250_of and 8250_bcm7271 drivers were running, occasionally the 8250_of driver would be bound to the enhanced UART instead of the 8250_bcm7271 driver. This was happening because we use SCMI based clocks which come up late in initialization and cause probe DEFER's when the two drivers get their clocks.
Occasionally the SCMI clock would become ready between the 8250_bcm7271 probe and the 8250_of probe and the 8250_of driver would be bound. To fix this we decided to config only our 8250_bcm7271 driver and added "ns16665a0" to the compatible string so the driver would work on our older system.
This commit has of_platform_serial_probe() check specifically for the "brcm,bcm7271-uart" and whether its companion driver is enabled. If it is the case, and the clock provider is not ready, we want to make sure that when the 8250_bcm7271.c driver returns EPROBE_DEFER, we are not getting the UART registered via 8250_of.c.
Reviewed-by: Andy Shevchenko andy.shevchenko@gmail.com Signed-off-by: Jim Quinlan jim2101024@gmail.com Signed-off-by: Al Cooper alcooperx@gmail.com Signed-off-by: Florian Fainelli f.fainelli@gmail.com Link: https://lore.kernel.org/r/20210423183206.3917725-1-f.fainelli@gmail.com Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org Signed-off-by: Sasha Levin sashal@kernel.org
This commit is only relevant with 41a469482de257ea8db43cf74b6311bd055de030 ("serial: 8250: Add new 8250-core based Broadcom STB driver") which is included in v5.13 and newer. You would want to drop that commit from the 5.12, 5.10 and 5.4 auto-selection.
Thanks!
On Fri, Jul 09, 2021 at 07:33:25PM -0700, Florian Fainelli wrote:
On 7/9/2021 7:16 PM, Sasha Levin wrote:
From: Jim Quinlan jim2101024@gmail.com
[ Upstream commit f5b08386dee439c7a9e60ce0a4a4a705f3a60dff ]
Our SoC's have always had a NS16650A UART core and older SoC's would have a compatible string of: 'compatible = ""ns16550a"' and use the 8250_of driver. Our newer SoC's have added enhancements to the base core to add support for DMA and accurate high speed baud rates and use this newer 8250_bcm7271 driver. The Device Tree node for our enhanced UARTs has a compatible string of: 'compatible = "brcm,bcm7271-uart", "ns16550a"''. With both drivers running and the link order setup so that the 8250_bcm7217 driver is initialized before the 8250_of driver, we should bind the 8250_bcm7271 driver to the enhanced UART, or for upstream kernels that don't have the 8250_bcm7271 driver, we bind to the 8250_of driver.
The problem is that when both the 8250_of and 8250_bcm7271 drivers were running, occasionally the 8250_of driver would be bound to the enhanced UART instead of the 8250_bcm7271 driver. This was happening because we use SCMI based clocks which come up late in initialization and cause probe DEFER's when the two drivers get their clocks.
Occasionally the SCMI clock would become ready between the 8250_bcm7271 probe and the 8250_of probe and the 8250_of driver would be bound. To fix this we decided to config only our 8250_bcm7271 driver and added "ns16665a0" to the compatible string so the driver would work on our older system.
This commit has of_platform_serial_probe() check specifically for the "brcm,bcm7271-uart" and whether its companion driver is enabled. If it is the case, and the clock provider is not ready, we want to make sure that when the 8250_bcm7271.c driver returns EPROBE_DEFER, we are not getting the UART registered via 8250_of.c.
Reviewed-by: Andy Shevchenko andy.shevchenko@gmail.com Signed-off-by: Jim Quinlan jim2101024@gmail.com Signed-off-by: Al Cooper alcooperx@gmail.com Signed-off-by: Florian Fainelli f.fainelli@gmail.com Link: https://lore.kernel.org/r/20210423183206.3917725-1-f.fainelli@gmail.com Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org Signed-off-by: Sasha Levin sashal@kernel.org
This commit is only relevant with 41a469482de257ea8db43cf74b6311bd055de030 ("serial: 8250: Add new 8250-core based Broadcom STB driver") which is included in v5.13 and newer. You would want to drop that commit from the 5.12, 5.10 and 5.4 auto-selection.
I'll drop it from 5.12 and older, thanks!
From: Lv Yunlong lyl2019@mail.ustc.edu.cn
[ Upstream commit 7272b591c4cb9327c43443f67b8fbae7657dd9ae ]
In ibmasm_init_one, it calls ibmasm_init_remote_input_dev(). Inside ibmasm_init_remote_input_dev, mouse_dev and keybd_dev are allocated by input_allocate_device(), and assigned to sp->remote.mouse_dev and sp->remote.keybd_dev respectively.
In the err_free_devices error branch of ibmasm_init_one, mouse_dev and keybd_dev are freed by input_free_device(), and return error. Then the execution runs into error_send_message error branch of ibmasm_init_one, where ibmasm_free_remote_input_dev(sp) is called to unregister the freed sp->remote.mouse_dev and sp->remote.keybd_dev.
My patch add a "error_init_remote" label to handle the error of ibmasm_init_remote_input_dev(), to avoid the uaf bugs.
Signed-off-by: Lv Yunlong lyl2019@mail.ustc.edu.cn Link: https://lore.kernel.org/r/20210426170620.10546-1-lyl2019@mail.ustc.edu.cn Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/misc/ibmasm/module.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/drivers/misc/ibmasm/module.c b/drivers/misc/ibmasm/module.c index 4edad6c445d3..dc8a06c06c63 100644 --- a/drivers/misc/ibmasm/module.c +++ b/drivers/misc/ibmasm/module.c @@ -111,7 +111,7 @@ static int ibmasm_init_one(struct pci_dev *pdev, const struct pci_device_id *id) result = ibmasm_init_remote_input_dev(sp); if (result) { dev_err(sp->dev, "Failed to initialize remote queue\n"); - goto error_send_message; + goto error_init_remote; }
result = ibmasm_send_driver_vpd(sp); @@ -131,8 +131,9 @@ static int ibmasm_init_one(struct pci_dev *pdev, const struct pci_device_id *id) return 0;
error_send_message: - disable_sp_interrupts(sp->base_address); ibmasm_free_remote_input_dev(sp); +error_init_remote: + disable_sp_interrupts(sp->base_address); free_irq(sp->irq, (void *)sp); error_request_irq: iounmap(sp->base_address);
From: Tong Zhang ztong0001@gmail.com
[ Upstream commit 3ce3e45cc333da707d4d6eb433574b990bcc26f5 ]
There is an issue with the ASPM(optional) capability checking function. A device might be attached to root complex directly, in this case, bus->self(bridge) will be NULL, thus priv->parent_pdev is NULL. Since alcor_pci_init_check_aspm(priv->parent_pdev) checks the PCI link's ASPM capability and populate parent_cap_off, which will be used later by alcor_pci_aspm_ctrl() to dynamically turn on/off device, what we can do here is to avoid checking the capability if we are on the root complex. This will make pdev_cap_off 0 and alcor_pci_aspm_ctrl() will simply return when bring called, effectively disable ASPM for the device.
[ 1.246492] BUG: kernel NULL pointer dereference, address: 00000000000000c0 [ 1.248731] RIP: 0010:pci_read_config_byte+0x5/0x40 [ 1.253998] Call Trace: [ 1.254131] ? alcor_pci_find_cap_offset.isra.0+0x3a/0x100 [alcor_pci] [ 1.254476] alcor_pci_probe+0x169/0x2d5 [alcor_pci]
Co-developed-by: Greg Kroah-Hartman gregkh@linuxfoundation.org Signed-off-by: Tong Zhang ztong0001@gmail.com Link: https://lore.kernel.org/r/20210513040732.1310159-1-ztong0001@gmail.com Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/misc/cardreader/alcor_pci.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-)
diff --git a/drivers/misc/cardreader/alcor_pci.c b/drivers/misc/cardreader/alcor_pci.c index cd402c89189e..0a62307f7ffb 100644 --- a/drivers/misc/cardreader/alcor_pci.c +++ b/drivers/misc/cardreader/alcor_pci.c @@ -139,7 +139,13 @@ static void alcor_pci_init_check_aspm(struct alcor_pci_priv *priv) u32 val32;
priv->pdev_cap_off = alcor_pci_find_cap_offset(priv, priv->pdev); - priv->parent_cap_off = alcor_pci_find_cap_offset(priv, + /* + * A device might be attached to root complex directly and + * priv->parent_pdev will be NULL. In this case we don't check its + * capability and disable ASPM completely. + */ + if (!priv->parent_pdev) + priv->parent_cap_off = alcor_pci_find_cap_offset(priv, priv->parent_pdev);
if ((priv->pdev_cap_off == 0) || (priv->parent_cap_off == 0)) {
From: Zou Wei zou_wei@huawei.com
[ Upstream commit a75e5cdf4dd1307bb1541edbb0c008f40896644c ]
This patch adds missing MODULE_DEVICE_TABLE definition which generates correct modalias for automatic loading of this driver when it is built as an external module.
Reported-by: Hulk Robot hulkci@huawei.com Signed-off-by: Zou Wei zou_wei@huawei.com Link: https://lore.kernel.org/r/1620791647-16024-1-git-send-email-zou_wei@huawei.c... Signed-off-by: Mark Brown broonie@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- sound/soc/intel/boards/sof_da7219_max98373.c | 1 + sound/soc/intel/boards/sof_rt5682.c | 1 + 2 files changed, 2 insertions(+)
diff --git a/sound/soc/intel/boards/sof_da7219_max98373.c b/sound/soc/intel/boards/sof_da7219_max98373.c index f3cb0773e70e..8d1ad892e86b 100644 --- a/sound/soc/intel/boards/sof_da7219_max98373.c +++ b/sound/soc/intel/boards/sof_da7219_max98373.c @@ -440,6 +440,7 @@ static const struct platform_device_id board_ids[] = { }, { } }; +MODULE_DEVICE_TABLE(platform, board_ids);
static struct platform_driver audio = { .probe = audio_probe, diff --git a/sound/soc/intel/boards/sof_rt5682.c b/sound/soc/intel/boards/sof_rt5682.c index 58548ea0d915..cf1d053733e2 100644 --- a/sound/soc/intel/boards/sof_rt5682.c +++ b/sound/soc/intel/boards/sof_rt5682.c @@ -968,6 +968,7 @@ static const struct platform_device_id board_ids[] = { }, { } }; +MODULE_DEVICE_TABLE(platform, board_ids);
static struct platform_driver sof_audio = { .probe = sof_audio_probe,
From: Arnd Bergmann arnd@arndb.de
[ Upstream commit 1b1774998b2dec837a57d729d1a22e5eb2d6d206 ]
A simplification of get_unaligned() clashes with callers that pass in a character pointer, causing a harmless warning like:
block/partitions/msdos.c: In function 'msdos_partition': include/asm-generic/unaligned.h:13:22: warning: 'packed' attribute ignored for field of type 'u8' {aka 'unsigned char'} [-Wattributes]
Remove the SYS_IND() macro with the get_unaligned() call and just use the ->ind field directly.
Signed-off-by: Arnd Bergmann arnd@arndb.de Signed-off-by: Sasha Levin sashal@kernel.org --- block/partitions/ldm.c | 2 +- block/partitions/ldm.h | 3 --- block/partitions/msdos.c | 24 +++++++++++------------- 3 files changed, 12 insertions(+), 17 deletions(-)
diff --git a/block/partitions/ldm.c b/block/partitions/ldm.c index d333786b5c7e..cc86534c80ad 100644 --- a/block/partitions/ldm.c +++ b/block/partitions/ldm.c @@ -510,7 +510,7 @@ static bool ldm_validate_partition_table(struct parsed_partitions *state)
p = (struct msdos_partition *)(data + 0x01BE); for (i = 0; i < 4; i++, p++) - if (SYS_IND (p) == LDM_PARTITION) { + if (p->sys_ind == LDM_PARTITION) { result = true; break; } diff --git a/block/partitions/ldm.h b/block/partitions/ldm.h index d8d6beaa72c4..8693704dcf5e 100644 --- a/block/partitions/ldm.h +++ b/block/partitions/ldm.h @@ -84,9 +84,6 @@ struct parsed_partitions; #define TOC_BITMAP1 "config" /* Names of the two defined */ #define TOC_BITMAP2 "log" /* bitmaps in the TOCBLOCK. */
-/* Borrowed from msdos.c */ -#define SYS_IND(p) (get_unaligned(&(p)->sys_ind)) - struct frag { /* VBLK Fragment handling */ struct list_head list; u32 group; diff --git a/block/partitions/msdos.c b/block/partitions/msdos.c index 8f2fcc080264..c94de377c502 100644 --- a/block/partitions/msdos.c +++ b/block/partitions/msdos.c @@ -38,8 +38,6 @@ */ #include <asm/unaligned.h>
-#define SYS_IND(p) get_unaligned(&p->sys_ind) - static inline sector_t nr_sects(struct msdos_partition *p) { return (sector_t)get_unaligned_le32(&p->nr_sects); @@ -52,9 +50,9 @@ static inline sector_t start_sect(struct msdos_partition *p)
static inline int is_extended_partition(struct msdos_partition *p) { - return (SYS_IND(p) == DOS_EXTENDED_PARTITION || - SYS_IND(p) == WIN98_EXTENDED_PARTITION || - SYS_IND(p) == LINUX_EXTENDED_PARTITION); + return (p->sys_ind == DOS_EXTENDED_PARTITION || + p->sys_ind == WIN98_EXTENDED_PARTITION || + p->sys_ind == LINUX_EXTENDED_PARTITION); }
#define MSDOS_LABEL_MAGIC1 0x55 @@ -193,7 +191,7 @@ static void parse_extended(struct parsed_partitions *state,
put_partition(state, state->next, next, size); set_info(state, state->next, disksig); - if (SYS_IND(p) == LINUX_RAID_PARTITION) + if (p->sys_ind == LINUX_RAID_PARTITION) state->parts[state->next].flags = ADDPART_FLAG_RAID; loopct = 0; if (++state->next == state->limit) @@ -546,7 +544,7 @@ static void parse_minix(struct parsed_partitions *state, * a secondary MBR describing its subpartitions, or * the normal boot sector. */ if (msdos_magic_present(data + 510) && - SYS_IND(p) == MINIX_PARTITION) { /* subpartition table present */ + p->sys_ind == MINIX_PARTITION) { /* subpartition table present */ char tmp[1 + BDEVNAME_SIZE + 10 + 9 + 1];
snprintf(tmp, sizeof(tmp), " %s%d: <minix:", state->name, origin); @@ -555,7 +553,7 @@ static void parse_minix(struct parsed_partitions *state, if (state->next == state->limit) break; /* add each partition in use */ - if (SYS_IND(p) == MINIX_PARTITION) + if (p->sys_ind == MINIX_PARTITION) put_partition(state, state->next++, start_sect(p), nr_sects(p)); } @@ -643,7 +641,7 @@ int msdos_partition(struct parsed_partitions *state) p = (struct msdos_partition *) (data + 0x1be); for (slot = 1 ; slot <= 4 ; slot++, p++) { /* If this is an EFI GPT disk, msdos should ignore it. */ - if (SYS_IND(p) == EFI_PMBR_OSTYPE_EFI_GPT) { + if (p->sys_ind == EFI_PMBR_OSTYPE_EFI_GPT) { put_dev_sector(sect); return 0; } @@ -685,11 +683,11 @@ int msdos_partition(struct parsed_partitions *state) } put_partition(state, slot, start, size); set_info(state, slot, disksig); - if (SYS_IND(p) == LINUX_RAID_PARTITION) + if (p->sys_ind == LINUX_RAID_PARTITION) state->parts[slot].flags = ADDPART_FLAG_RAID; - if (SYS_IND(p) == DM6_PARTITION) + if (p->sys_ind == DM6_PARTITION) strlcat(state->pp_buf, "[DM]", PAGE_SIZE); - if (SYS_IND(p) == EZD_PARTITION) + if (p->sys_ind == EZD_PARTITION) strlcat(state->pp_buf, "[EZD]", PAGE_SIZE); }
@@ -698,7 +696,7 @@ int msdos_partition(struct parsed_partitions *state) /* second pass - output for each on a separate line */ p = (struct msdos_partition *) (0x1be + data); for (slot = 1 ; slot <= 4 ; slot++, p++) { - unsigned char id = SYS_IND(p); + unsigned char id = p->sys_ind; int n;
if (!nr_sects(p))
From: Sean Nyekjaer sean@geanix.com
[ Upstream commit f7d5c18a8c371c306d73757547c2e0d6cfc764b3 ]
Fix wrongly stated 13 Hz ODR for accelerometers, the correct ODR is 12.5 Hz
Signed-off-by: Sean Nyekjaer sean@geanix.com Acked-by: Lorenzo Bianconi lorenzo@kernel.org Signed-off-by: Jonathan Cameron Jonathan.Cameron@huawei.com Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_core.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_core.c b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_core.c index 7cedaab096a7..e8d242ee6743 100644 --- a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_core.c +++ b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_core.c @@ -15,19 +15,19 @@ * * Supported sensors: * - LSM6DS3: - * - Accelerometer/Gyroscope supported ODR [Hz]: 13, 26, 52, 104, 208, 416 + * - Accelerometer/Gyroscope supported ODR [Hz]: 12.5, 26, 52, 104, 208, 416 * - Accelerometer supported full-scale [g]: +-2/+-4/+-8/+-16 * - Gyroscope supported full-scale [dps]: +-125/+-245/+-500/+-1000/+-2000 * - FIFO size: 8KB * * - LSM6DS3H/LSM6DSL/LSM6DSM/ISM330DLC/LSM6DS3TR-C: - * - Accelerometer/Gyroscope supported ODR [Hz]: 13, 26, 52, 104, 208, 416 + * - Accelerometer/Gyroscope supported ODR [Hz]: 12.5, 26, 52, 104, 208, 416 * - Accelerometer supported full-scale [g]: +-2/+-4/+-8/+-16 * - Gyroscope supported full-scale [dps]: +-125/+-245/+-500/+-1000/+-2000 * - FIFO size: 4KB * * - LSM6DSO/LSM6DSOX/ASM330LHH/LSM6DSR/ISM330DHCX/LSM6DST/LSM6DSOP: - * - Accelerometer/Gyroscope supported ODR [Hz]: 13, 26, 52, 104, 208, 416, + * - Accelerometer/Gyroscope supported ODR [Hz]: 12.5, 26, 52, 104, 208, 416, * 833 * - Accelerometer supported full-scale [g]: +-2/+-4/+-8/+-16 * - Gyroscope supported full-scale [dps]: +-125/+-245/+-500/+-1000/+-2000
From: Jonathan Cameron Jonathan.Cameron@huawei.com
[ Upstream commit 41120ebbb1eb5e9dec93320e259d5b2c93226073 ]
In both the probe() error path and remove() pm_runtime_put_noidle() is called which will decrement the runtime pm reference count. However, there is no matching function to have raised the reference count. Not this isn't a fix as the runtime pm core will stop the reference count going negative anyway.
An alternative would have been to raise the count in these paths, but it is not clear why that would be necessary.
Whilst we are here replace some boilerplate with pm_runtime_resume_and_get() Found using coccicheck script under review at: https://lore.kernel.org/lkml/20210427141946.2478411-1-Julia.Lawall@inria.fr/
Signed-off-by: Jonathan Cameron Jonathan.Cameron@huawei.com Reviewed-by: Rui Miguel Silva rui.silva@linaro.org Reviewed-by: Mauro Carvalho Chehab mchehab+huawei@kernel.org Link: https://lore.kernel.org/r/20210509113354.660190-2-jic23@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/iio/gyro/fxas21002c_core.c | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-)
diff --git a/drivers/iio/gyro/fxas21002c_core.c b/drivers/iio/gyro/fxas21002c_core.c index 645461c70454..6a85f231fd57 100644 --- a/drivers/iio/gyro/fxas21002c_core.c +++ b/drivers/iio/gyro/fxas21002c_core.c @@ -366,14 +366,7 @@ static int fxas21002c_write(struct fxas21002c_data *data,
static int fxas21002c_pm_get(struct fxas21002c_data *data) { - struct device *dev = regmap_get_device(data->regmap); - int ret; - - ret = pm_runtime_get_sync(dev); - if (ret < 0) - pm_runtime_put_noidle(dev); - - return ret; + return pm_runtime_resume_and_get(regmap_get_device(data->regmap)); }
static int fxas21002c_pm_put(struct fxas21002c_data *data) @@ -1004,7 +997,6 @@ int fxas21002c_core_probe(struct device *dev, struct regmap *regmap, int irq, pm_disable: pm_runtime_disable(dev); pm_runtime_set_suspended(dev); - pm_runtime_put_noidle(dev);
return ret; } @@ -1018,7 +1010,6 @@ void fxas21002c_core_remove(struct device *dev)
pm_runtime_disable(dev); pm_runtime_set_suspended(dev); - pm_runtime_put_noidle(dev); } EXPORT_SYMBOL_GPL(fxas21002c_core_remove);
From: Jonathan Cameron Jonathan.Cameron@huawei.com
[ Upstream commit 264da512431495e542fcaf56ffe75e7df0e7db74 ]
probe() error paths after runtime pm is enabled, should disable it. remove() should not call pm_runtime_put_noidle() as there is no matching get() to have raised the reference count. This case has no affect a the runtime pm core protects against going negative.
Whilst here use pm_runtime_resume_and_get() to tidy things up a little. coccicheck script didn't get this one due to complex code structure so found by inspection.
Signed-off-by: Jonathan Cameron Jonathan.Cameron@huawei.com Cc: Linus Walleij linus.walleij@linaro.org Reviewed-by: Mauro Carvalho Chehab mchehab+huawei@kernel.org Link: https://lore.kernel.org/r/20210509113354.660190-12-jic23@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/iio/magnetometer/bmc150_magn.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-)
diff --git a/drivers/iio/magnetometer/bmc150_magn.c b/drivers/iio/magnetometer/bmc150_magn.c index 00f9766bad5c..8ed548ef6924 100644 --- a/drivers/iio/magnetometer/bmc150_magn.c +++ b/drivers/iio/magnetometer/bmc150_magn.c @@ -262,7 +262,7 @@ static int bmc150_magn_set_power_state(struct bmc150_magn_data *data, bool on) int ret;
if (on) { - ret = pm_runtime_get_sync(data->dev); + ret = pm_runtime_resume_and_get(data->dev); } else { pm_runtime_mark_last_busy(data->dev); ret = pm_runtime_put_autosuspend(data->dev); @@ -271,9 +271,6 @@ static int bmc150_magn_set_power_state(struct bmc150_magn_data *data, bool on) if (ret < 0) { dev_err(data->dev, "failed to change power state to %d\n", on); - if (on) - pm_runtime_put_noidle(data->dev); - return ret; } #endif @@ -963,12 +960,14 @@ int bmc150_magn_probe(struct device *dev, struct regmap *regmap, ret = iio_device_register(indio_dev); if (ret < 0) { dev_err(dev, "unable to register iio device\n"); - goto err_buffer_cleanup; + goto err_disable_runtime_pm; }
dev_dbg(dev, "Registered device %s\n", name); return 0;
+err_disable_runtime_pm: + pm_runtime_disable(dev); err_buffer_cleanup: iio_triggered_buffer_cleanup(indio_dev); err_free_irq: @@ -992,7 +991,6 @@ int bmc150_magn_remove(struct device *dev)
pm_runtime_disable(dev); pm_runtime_set_suspended(dev); - pm_runtime_put_noidle(dev);
iio_triggered_buffer_cleanup(indio_dev);
From: Takashi Iwai tiwai@suse.de
[ Upstream commit bae3ce4942980d5f7b2b9855f4a2db0c00f9dfbd ]
For improving readability, convert camelCase fields, variables and functions to the plain names with underscore. Also align the macros to be capital letters.
All done via sed, no functional changes.
Note that you'll still see many coding style issues even after this patch; the fixes will follow.
Link: https://lore.kernel.org/r/20210517131545.27252-2-tiwai@suse.de Signed-off-by: Takashi Iwai tiwai@suse.de Signed-off-by: Sasha Levin sashal@kernel.org --- sound/usb/usx2y/usX2Yhwdep.c | 56 ++-- sound/usb/usx2y/usX2Yhwdep.h | 2 +- sound/usb/usx2y/usbus428ctldefs.h | 102 +++---- sound/usb/usx2y/usbusx2y.c | 218 +++++++-------- sound/usb/usx2y/usbusx2y.h | 58 ++-- sound/usb/usx2y/usbusx2yaudio.c | 448 +++++++++++++++--------------- sound/usb/usx2y/usx2yhwdeppcm.c | 410 +++++++++++++-------------- sound/usb/usx2y/usx2yhwdeppcm.h | 4 +- 8 files changed, 649 insertions(+), 649 deletions(-)
diff --git a/sound/usb/usx2y/usX2Yhwdep.c b/sound/usb/usx2y/usX2Yhwdep.c index 22412cd69e98..10868c3fb656 100644 --- a/sound/usb/usx2y/usX2Yhwdep.c +++ b/sound/usb/usx2y/usX2Yhwdep.c @@ -29,7 +29,7 @@ static vm_fault_t snd_us428ctls_vm_fault(struct vm_fault *vmf) vmf->pgoff); offset = vmf->pgoff << PAGE_SHIFT; - vaddr = (char *)((struct usX2Ydev *)vmf->vma->vm_private_data)->us428ctls_sharedmem + offset; + vaddr = (char *)((struct usx2ydev *)vmf->vma->vm_private_data)->us428ctls_sharedmem + offset; page = virt_to_page(vaddr); get_page(page); vmf->page = page; @@ -47,7 +47,7 @@ static const struct vm_operations_struct us428ctls_vm_ops = { static int snd_us428ctls_mmap(struct snd_hwdep * hw, struct file *filp, struct vm_area_struct *area) { unsigned long size = (unsigned long)(area->vm_end - area->vm_start); - struct usX2Ydev *us428 = hw->private_data; + struct usx2ydev *us428 = hw->private_data;
// FIXME this hwdep interface is used twice: fpga download and mmap for controlling Lights etc. Maybe better using 2 hwdep devs? // so as long as the device isn't fully initialised yet we return -EBUSY here. @@ -66,7 +66,7 @@ static int snd_us428ctls_mmap(struct snd_hwdep * hw, struct file *filp, struct v if (!us428->us428ctls_sharedmem) return -ENOMEM; memset(us428->us428ctls_sharedmem, -1, sizeof(struct us428ctls_sharedmem)); - us428->us428ctls_sharedmem->CtlSnapShotLast = -2; + us428->us428ctls_sharedmem->ctl_snapshot_last = -2; } area->vm_ops = &us428ctls_vm_ops; area->vm_flags |= VM_DONTEXPAND | VM_DONTDUMP; @@ -77,21 +77,21 @@ static int snd_us428ctls_mmap(struct snd_hwdep * hw, struct file *filp, struct v static __poll_t snd_us428ctls_poll(struct snd_hwdep *hw, struct file *file, poll_table *wait) { __poll_t mask = 0; - struct usX2Ydev *us428 = hw->private_data; + struct usx2ydev *us428 = hw->private_data; struct us428ctls_sharedmem *shm = us428->us428ctls_sharedmem; if (us428->chip_status & USX2Y_STAT_CHIP_HUP) return EPOLLHUP;
poll_wait(file, &us428->us428ctls_wait_queue_head, wait);
- if (shm != NULL && shm->CtlSnapShotLast != shm->CtlSnapShotRed) + if (shm != NULL && shm->ctl_snapshot_last != shm->ctl_snapshot_red) mask |= EPOLLIN;
return mask; }
-static int snd_usX2Y_hwdep_dsp_status(struct snd_hwdep *hw, +static int snd_usx2y_hwdep_dsp_status(struct snd_hwdep *hw, struct snd_hwdep_dsp_status *info) { static const char * const type_ids[USX2Y_TYPE_NUMS] = { @@ -99,7 +99,7 @@ static int snd_usX2Y_hwdep_dsp_status(struct snd_hwdep *hw, [USX2Y_TYPE_224] = "us224", [USX2Y_TYPE_428] = "us428", }; - struct usX2Ydev *us428 = hw->private_data; + struct usx2ydev *us428 = hw->private_data; int id = -1;
switch (le16_to_cpu(us428->dev->descriptor.idProduct)) { @@ -124,7 +124,7 @@ static int snd_usX2Y_hwdep_dsp_status(struct snd_hwdep *hw, }
-static int usX2Y_create_usbmidi(struct snd_card *card) +static int usx2y_create_usbmidi(struct snd_card *card) { static const struct snd_usb_midi_endpoint_info quirk_data_1 = { .out_ep = 0x06, @@ -152,28 +152,28 @@ static int usX2Y_create_usbmidi(struct snd_card *card) .type = QUIRK_MIDI_FIXED_ENDPOINT, .data = &quirk_data_2 }; - struct usb_device *dev = usX2Y(card)->dev; + struct usb_device *dev = usx2y(card)->dev; struct usb_interface *iface = usb_ifnum_to_if(dev, 0); const struct snd_usb_audio_quirk *quirk = le16_to_cpu(dev->descriptor.idProduct) == USB_ID_US428 ? &quirk_2 : &quirk_1;
- snd_printdd("usX2Y_create_usbmidi \n"); - return snd_usbmidi_create(card, iface, &usX2Y(card)->midi_list, quirk); + snd_printdd("usx2y_create_usbmidi \n"); + return snd_usbmidi_create(card, iface, &usx2y(card)->midi_list, quirk); }
-static int usX2Y_create_alsa_devices(struct snd_card *card) +static int usx2y_create_alsa_devices(struct snd_card *card) { int err;
do { - if ((err = usX2Y_create_usbmidi(card)) < 0) { - snd_printk(KERN_ERR "usX2Y_create_alsa_devices: usX2Y_create_usbmidi error %i \n", err); + if ((err = usx2y_create_usbmidi(card)) < 0) { + snd_printk(KERN_ERR "usx2y_create_alsa_devices: usx2y_create_usbmidi error %i \n", err); break; } - if ((err = usX2Y_audio_create(card)) < 0) + if ((err = usx2y_audio_create(card)) < 0) break; - if ((err = usX2Y_hwdep_pcm_new(card)) < 0) + if ((err = usx2y_hwdep_pcm_new(card)) < 0) break; if ((err = snd_card_register(card)) < 0) break; @@ -182,10 +182,10 @@ static int usX2Y_create_alsa_devices(struct snd_card *card) return err; }
-static int snd_usX2Y_hwdep_dsp_load(struct snd_hwdep *hw, +static int snd_usx2y_hwdep_dsp_load(struct snd_hwdep *hw, struct snd_hwdep_dsp_image *dsp) { - struct usX2Ydev *priv = hw->private_data; + struct usx2ydev *priv = hw->private_data; struct usb_device* dev = priv->dev; int lret, err; char *buf; @@ -206,19 +206,19 @@ static int snd_usX2Y_hwdep_dsp_load(struct snd_hwdep *hw, return err; if (dsp->index == 1) { msleep(250); // give the device some time - err = usX2Y_AsyncSeq04_init(priv); + err = usx2y_async_seq04_init(priv); if (err) { - snd_printk(KERN_ERR "usX2Y_AsyncSeq04_init error \n"); + snd_printk(KERN_ERR "usx2y_async_seq04_init error \n"); return err; } - err = usX2Y_In04_init(priv); + err = usx2y_in04_init(priv); if (err) { - snd_printk(KERN_ERR "usX2Y_In04_init error \n"); + snd_printk(KERN_ERR "usx2y_in04_init error \n"); return err; } - err = usX2Y_create_alsa_devices(hw->card); + err = usx2y_create_alsa_devices(hw->card); if (err) { - snd_printk(KERN_ERR "usX2Y_create_alsa_devices error %i \n", err); + snd_printk(KERN_ERR "usx2y_create_alsa_devices error %i \n", err); snd_card_free(hw->card); return err; } @@ -229,7 +229,7 @@ static int snd_usX2Y_hwdep_dsp_load(struct snd_hwdep *hw, }
-int usX2Y_hwdep_new(struct snd_card *card, struct usb_device* device) +int usx2y_hwdep_new(struct snd_card *card, struct usb_device* device) { int err; struct snd_hwdep *hw; @@ -238,9 +238,9 @@ int usX2Y_hwdep_new(struct snd_card *card, struct usb_device* device) return err;
hw->iface = SNDRV_HWDEP_IFACE_USX2Y; - hw->private_data = usX2Y(card); - hw->ops.dsp_status = snd_usX2Y_hwdep_dsp_status; - hw->ops.dsp_load = snd_usX2Y_hwdep_dsp_load; + hw->private_data = usx2y(card); + hw->ops.dsp_status = snd_usx2y_hwdep_dsp_status; + hw->ops.dsp_load = snd_usx2y_hwdep_dsp_load; hw->ops.mmap = snd_us428ctls_mmap; hw->ops.poll = snd_us428ctls_poll; hw->exclusive = 1; diff --git a/sound/usb/usx2y/usX2Yhwdep.h b/sound/usb/usx2y/usX2Yhwdep.h index 457199b5ed03..34cef625712c 100644 --- a/sound/usb/usx2y/usX2Yhwdep.h +++ b/sound/usb/usx2y/usX2Yhwdep.h @@ -2,6 +2,6 @@ #ifndef USX2YHWDEP_H #define USX2YHWDEP_H
-int usX2Y_hwdep_new(struct snd_card *card, struct usb_device* device); +int usx2y_hwdep_new(struct snd_card *card, struct usb_device* device);
#endif diff --git a/sound/usb/usx2y/usbus428ctldefs.h b/sound/usb/usx2y/usbus428ctldefs.h index 5a7518ea3aeb..7366a940ffbb 100644 --- a/sound/usb/usx2y/usbus428ctldefs.h +++ b/sound/usb/usx2y/usbus428ctldefs.h @@ -4,28 +4,28 @@ * Copyright (c) 2003 by Karsten Wiese annabellesgarden@yahoo.de */
-enum E_In84{ - eFader0 = 0, - eFader1, - eFader2, - eFader3, - eFader4, - eFader5, - eFader6, - eFader7, - eFaderM, - eTransport, - eModifier = 10, - eFilterSelect, - eSelect, - eMute, +enum E_IN84 { + E_FADER_0 = 0, + E_FADER_1, + E_FADER_2, + E_FADER_3, + E_FADER_4, + E_FADER_5, + E_FADER_6, + E_FADER_7, + E_FADER_M, + E_TRANSPORT, + E_MODIFIER = 10, + E_FILTER_SELECT, + E_SELECT, + E_MUTE,
- eSwitch = 15, - eWheelGain, - eWheelFreq, - eWheelQ, - eWheelPan, - eWheel = 20 + E_SWITCH = 15, + E_WHEEL_GAIN, + E_WHEEL_FREQ, + E_WHEEL_Q, + E_WHEEL_PAN, + E_WHEEL = 20 };
#define T_RECORD 1 @@ -39,53 +39,53 @@ enum E_In84{
struct us428_ctls { - unsigned char Fader[9]; - unsigned char Transport; - unsigned char Modifier; - unsigned char FilterSelect; - unsigned char Select; - unsigned char Mute; - unsigned char UNKNOWN; - unsigned char Switch; - unsigned char Wheel[5]; + unsigned char fader[9]; + unsigned char transport; + unsigned char modifier; + unsigned char filters_elect; + unsigned char select; + unsigned char mute; + unsigned char unknown; + unsigned char wswitch; + unsigned char wheel[5]; };
-struct us428_setByte { - unsigned char Offset, - Value; +struct us428_set_byte { + unsigned char offset, + value; };
enum { - eLT_Volume = 0, - eLT_Light + ELT_VOLUME = 0, + ELT_LIGHT };
-struct usX2Y_volume { - unsigned char Channel, - LH, - LL, - RH, - RL; +struct usx2y_volume { + unsigned char channel, + lh, + ll, + rh, + rl; };
struct us428_lights { - struct us428_setByte Light[7]; + struct us428_set_byte light[7]; };
struct us428_p4out { char type; union { - struct usX2Y_volume vol; + struct usx2y_volume vol; struct us428_lights lights; } val; };
-#define N_us428_ctl_BUFS 16 -#define N_us428_p4out_BUFS 16 -struct us428ctls_sharedmem{ - struct us428_ctls CtlSnapShot[N_us428_ctl_BUFS]; - int CtlSnapShotDiffersAt[N_us428_ctl_BUFS]; - int CtlSnapShotLast, CtlSnapShotRed; - struct us428_p4out p4out[N_us428_p4out_BUFS]; - int p4outLast, p4outSent; +#define N_US428_CTL_BUFS 16 +#define N_US428_P4OUT_BUFS 16 +struct us428ctls_sharedmem { + struct us428_ctls ctl_snapshot[N_US428_CTL_BUFS]; + int ctl_snapshot_differs_at[N_US428_CTL_BUFS]; + int ctl_snapshot_last, ctl_snapshot_red; + struct us428_p4out p4out[N_US428_P4OUT_BUFS]; + int p4out_last, p4out_sent; }; diff --git a/sound/usb/usx2y/usbusx2y.c b/sound/usb/usx2y/usbusx2y.c index 3cd28d24f0a7..cdbb27a96e04 100644 --- a/sound/usb/usx2y/usbusx2y.c +++ b/sound/usb/usx2y/usbusx2y.c @@ -17,7 +17,7 @@
2004-10-26 Karsten Wiese Version 0.8.6: - wake_up() process waiting in usX2Y_urbs_start() on error. + wake_up() process waiting in usx2y_urbs_start() on error.
2004-10-21 Karsten Wiese Version 0.8.5: @@ -48,7 +48,7 @@ 2004-06-12 Karsten Wiese Version 0.6.3: Made it thus the following rule is enforced: - "All pcm substreams of one usX2Y have to operate at the same rate & format." + "All pcm substreams of one usx2y have to operate at the same rate & format."
2004-04-06 Karsten Wiese Version 0.6.0: @@ -150,161 +150,161 @@ module_param_array(enable, bool, NULL, 0444); MODULE_PARM_DESC(enable, "Enable "NAME_ALLCAPS".");
-static int snd_usX2Y_card_used[SNDRV_CARDS]; +static int snd_usx2y_card_used[SNDRV_CARDS];
-static void usX2Y_usb_disconnect(struct usb_device* usb_device, void* ptr); -static void snd_usX2Y_card_private_free(struct snd_card *card); +static void usx2y_usb_disconnect(struct usb_device* usb_device, void* ptr); +static void snd_usx2y_card_private_free(struct snd_card *card);
/* * pipe 4 is used for switching the lamps, setting samplerate, volumes .... */ -static void i_usX2Y_Out04Int(struct urb *urb) +static void i_usx2y_out04_int(struct urb *urb) { #ifdef CONFIG_SND_DEBUG if (urb->status) { int i; - struct usX2Ydev *usX2Y = urb->context; - for (i = 0; i < 10 && usX2Y->AS04.urb[i] != urb; i++); - snd_printdd("i_usX2Y_Out04Int() urb %i status=%i\n", i, urb->status); + struct usx2ydev *usx2y = urb->context; + for (i = 0; i < 10 && usx2y->as04.urb[i] != urb; i++); + snd_printdd("i_usx2y_out04_int() urb %i status=%i\n", i, urb->status); } #endif }
-static void i_usX2Y_In04Int(struct urb *urb) +static void i_usx2y_in04_int(struct urb *urb) { int err = 0; - struct usX2Ydev *usX2Y = urb->context; - struct us428ctls_sharedmem *us428ctls = usX2Y->us428ctls_sharedmem; + struct usx2ydev *usx2y = urb->context; + struct us428ctls_sharedmem *us428ctls = usx2y->us428ctls_sharedmem;
- usX2Y->In04IntCalls++; + usx2y->in04_int_calls++;
if (urb->status) { snd_printdd("Interrupt Pipe 4 came back with status=%i\n", urb->status); return; }
- // printk("%i:0x%02X ", 8, (int)((unsigned char*)usX2Y->In04Buf)[8]); Master volume shows 0 here if fader is at max during boot ?!? + // printk("%i:0x%02X ", 8, (int)((unsigned char*)usx2y->in04_buf)[8]); Master volume shows 0 here if fader is at max during boot ?!? if (us428ctls) { int diff = -1; - if (-2 == us428ctls->CtlSnapShotLast) { + if (-2 == us428ctls->ctl_snapshot_last) { diff = 0; - memcpy(usX2Y->In04Last, usX2Y->In04Buf, sizeof(usX2Y->In04Last)); - us428ctls->CtlSnapShotLast = -1; + memcpy(usx2y->in04_last, usx2y->in04_buf, sizeof(usx2y->in04_last)); + us428ctls->ctl_snapshot_last = -1; } else { int i; for (i = 0; i < 21; i++) { - if (usX2Y->In04Last[i] != ((char*)usX2Y->In04Buf)[i]) { + if (usx2y->in04_last[i] != ((char*)usx2y->in04_buf)[i]) { if (diff < 0) diff = i; - usX2Y->In04Last[i] = ((char*)usX2Y->In04Buf)[i]; + usx2y->in04_last[i] = ((char*)usx2y->in04_buf)[i]; } } } if (0 <= diff) { - int n = us428ctls->CtlSnapShotLast + 1; - if (n >= N_us428_ctl_BUFS || n < 0) + int n = us428ctls->ctl_snapshot_last + 1; + if (n >= N_US428_CTL_BUFS || n < 0) n = 0; - memcpy(us428ctls->CtlSnapShot + n, usX2Y->In04Buf, sizeof(us428ctls->CtlSnapShot[0])); - us428ctls->CtlSnapShotDiffersAt[n] = diff; - us428ctls->CtlSnapShotLast = n; - wake_up(&usX2Y->us428ctls_wait_queue_head); + memcpy(us428ctls->ctl_snapshot + n, usx2y->in04_buf, sizeof(us428ctls->ctl_snapshot[0])); + us428ctls->ctl_snapshot_differs_at[n] = diff; + us428ctls->ctl_snapshot_last = n; + wake_up(&usx2y->us428ctls_wait_queue_head); } } - if (usX2Y->US04) { - if (0 == usX2Y->US04->submitted) + if (usx2y->us04) { + if (0 == usx2y->us04->submitted) do { - err = usb_submit_urb(usX2Y->US04->urb[usX2Y->US04->submitted++], GFP_ATOMIC); - } while (!err && usX2Y->US04->submitted < usX2Y->US04->len); + err = usb_submit_urb(usx2y->us04->urb[usx2y->us04->submitted++], GFP_ATOMIC); + } while (!err && usx2y->us04->submitted < usx2y->us04->len); } else - if (us428ctls && us428ctls->p4outLast >= 0 && us428ctls->p4outLast < N_us428_p4out_BUFS) { - if (us428ctls->p4outLast != us428ctls->p4outSent) { - int j, send = us428ctls->p4outSent + 1; - if (send >= N_us428_p4out_BUFS) + if (us428ctls && us428ctls->p4out_last >= 0 && us428ctls->p4out_last < N_US428_P4OUT_BUFS) { + if (us428ctls->p4out_last != us428ctls->p4out_sent) { + int j, send = us428ctls->p4out_sent + 1; + if (send >= N_US428_P4OUT_BUFS) send = 0; - for (j = 0; j < URBS_AsyncSeq && !err; ++j) - if (0 == usX2Y->AS04.urb[j]->status) { + for (j = 0; j < URBS_ASYNC_SEQ && !err; ++j) + if (0 == usx2y->as04.urb[j]->status) { struct us428_p4out *p4out = us428ctls->p4out + send; // FIXME if more than 1 p4out is new, 1 gets lost. - usb_fill_bulk_urb(usX2Y->AS04.urb[j], usX2Y->dev, - usb_sndbulkpipe(usX2Y->dev, 0x04), &p4out->val.vol, - p4out->type == eLT_Light ? sizeof(struct us428_lights) : 5, - i_usX2Y_Out04Int, usX2Y); - err = usb_submit_urb(usX2Y->AS04.urb[j], GFP_ATOMIC); - us428ctls->p4outSent = send; + usb_fill_bulk_urb(usx2y->as04.urb[j], usx2y->dev, + usb_sndbulkpipe(usx2y->dev, 0x04), &p4out->val.vol, + p4out->type == ELT_LIGHT ? sizeof(struct us428_lights) : 5, + i_usx2y_out04_int, usx2y); + err = usb_submit_urb(usx2y->as04.urb[j], GFP_ATOMIC); + us428ctls->p4out_sent = send; break; } } }
if (err) - snd_printk(KERN_ERR "In04Int() usb_submit_urb err=%i\n", err); + snd_printk(KERN_ERR "in04_int() usb_submit_urb err=%i\n", err);
- urb->dev = usX2Y->dev; + urb->dev = usx2y->dev; usb_submit_urb(urb, GFP_ATOMIC); }
/* * Prepare some urbs */ -int usX2Y_AsyncSeq04_init(struct usX2Ydev *usX2Y) +int usx2y_async_seq04_init(struct usx2ydev *usx2y) { int err = 0, i;
- usX2Y->AS04.buffer = kmalloc_array(URBS_AsyncSeq, - URB_DataLen_AsyncSeq, GFP_KERNEL); - if (NULL == usX2Y->AS04.buffer) { + usx2y->as04.buffer = kmalloc_array(URBS_ASYNC_SEQ, + URB_DATA_LEN_ASYNC_SEQ, GFP_KERNEL); + if (NULL == usx2y->as04.buffer) { err = -ENOMEM; } else - for (i = 0; i < URBS_AsyncSeq; ++i) { - if (NULL == (usX2Y->AS04.urb[i] = usb_alloc_urb(0, GFP_KERNEL))) { + for (i = 0; i < URBS_ASYNC_SEQ; ++i) { + if (NULL == (usx2y->as04.urb[i] = usb_alloc_urb(0, GFP_KERNEL))) { err = -ENOMEM; break; } - usb_fill_bulk_urb( usX2Y->AS04.urb[i], usX2Y->dev, - usb_sndbulkpipe(usX2Y->dev, 0x04), - usX2Y->AS04.buffer + URB_DataLen_AsyncSeq*i, 0, - i_usX2Y_Out04Int, usX2Y + usb_fill_bulk_urb( usx2y->as04.urb[i], usx2y->dev, + usb_sndbulkpipe(usx2y->dev, 0x04), + usx2y->as04.buffer + URB_DATA_LEN_ASYNC_SEQ*i, 0, + i_usx2y_out04_int, usx2y ); - err = usb_urb_ep_type_check(usX2Y->AS04.urb[i]); + err = usb_urb_ep_type_check(usx2y->as04.urb[i]); if (err < 0) break; } return err; }
-int usX2Y_In04_init(struct usX2Ydev *usX2Y) +int usx2y_in04_init(struct usx2ydev *usx2y) { - if (! (usX2Y->In04urb = usb_alloc_urb(0, GFP_KERNEL))) + if (! (usx2y->in04_urb = usb_alloc_urb(0, GFP_KERNEL))) return -ENOMEM;
- if (! (usX2Y->In04Buf = kmalloc(21, GFP_KERNEL))) + if (! (usx2y->in04_buf = kmalloc(21, GFP_KERNEL))) return -ENOMEM; - init_waitqueue_head(&usX2Y->In04WaitQueue); - usb_fill_int_urb(usX2Y->In04urb, usX2Y->dev, usb_rcvintpipe(usX2Y->dev, 0x4), - usX2Y->In04Buf, 21, - i_usX2Y_In04Int, usX2Y, + init_waitqueue_head(&usx2y->in04_wait_queue); + usb_fill_int_urb(usx2y->in04_urb, usx2y->dev, usb_rcvintpipe(usx2y->dev, 0x4), + usx2y->in04_buf, 21, + i_usx2y_in04_int, usx2y, 10); - if (usb_urb_ep_type_check(usX2Y->In04urb)) + if (usb_urb_ep_type_check(usx2y->in04_urb)) return -EINVAL; - return usb_submit_urb(usX2Y->In04urb, GFP_KERNEL); + return usb_submit_urb(usx2y->in04_urb, GFP_KERNEL); }
-static void usX2Y_unlinkSeq(struct snd_usX2Y_AsyncSeq *S) +static void usx2y_unlinkseq(struct snd_usx2y_async_seq *s) { int i; - for (i = 0; i < URBS_AsyncSeq; ++i) { - usb_kill_urb(S->urb[i]); - usb_free_urb(S->urb[i]); - S->urb[i] = NULL; + for (i = 0; i < URBS_ASYNC_SEQ; ++i) { + usb_kill_urb(s->urb[i]); + usb_free_urb(s->urb[i]); + s->urb[i] = NULL; } - kfree(S->buffer); + kfree(s->buffer); }
-static const struct usb_device_id snd_usX2Y_usb_id_table[] = { +static const struct usb_device_id snd_usx2y_usb_id_table[] = { { .match_flags = USB_DEVICE_ID_MATCH_DEVICE, .idVendor = 0x1604, @@ -323,7 +323,7 @@ static const struct usb_device_id snd_usX2Y_usb_id_table[] = { { /* terminator */ } };
-static int usX2Y_create_card(struct usb_device *device, +static int usx2y_create_card(struct usb_device *device, struct usb_interface *intf, struct snd_card **cardp) { @@ -332,20 +332,20 @@ static int usX2Y_create_card(struct usb_device *device, int err;
for (dev = 0; dev < SNDRV_CARDS; ++dev) - if (enable[dev] && !snd_usX2Y_card_used[dev]) + if (enable[dev] && !snd_usx2y_card_used[dev]) break; if (dev >= SNDRV_CARDS) return -ENODEV; err = snd_card_new(&intf->dev, index[dev], id[dev], THIS_MODULE, - sizeof(struct usX2Ydev), &card); + sizeof(struct usx2ydev), &card); if (err < 0) return err; - snd_usX2Y_card_used[usX2Y(card)->card_index = dev] = 1; - card->private_free = snd_usX2Y_card_private_free; - usX2Y(card)->dev = device; - init_waitqueue_head(&usX2Y(card)->prepare_wait_queue); - mutex_init(&usX2Y(card)->pcm_mutex); - INIT_LIST_HEAD(&usX2Y(card)->midi_list); + snd_usx2y_card_used[usx2y(card)->card_index = dev] = 1; + card->private_free = snd_usx2y_card_private_free; + usx2y(card)->dev = device; + init_waitqueue_head(&usx2y(card)->prepare_wait_queue); + mutex_init(&usx2y(card)->pcm_mutex); + INIT_LIST_HEAD(&usx2y(card)->midi_list); strcpy(card->driver, "USB "NAME_ALLCAPS""); sprintf(card->shortname, "TASCAM "NAME_ALLCAPS""); sprintf(card->longname, "%s (%x:%x if %d at %03d/%03d)", @@ -353,14 +353,14 @@ static int usX2Y_create_card(struct usb_device *device, le16_to_cpu(device->descriptor.idVendor), le16_to_cpu(device->descriptor.idProduct), 0,//us428(card)->usbmidi.ifnum, - usX2Y(card)->dev->bus->busnum, usX2Y(card)->dev->devnum + usx2y(card)->dev->bus->busnum, usx2y(card)->dev->devnum ); *cardp = card; return 0; }
-static int usX2Y_usb_probe(struct usb_device *device, +static int usx2y_usb_probe(struct usb_device *device, struct usb_interface *intf, const struct usb_device_id *device_id, struct snd_card **cardp) @@ -375,10 +375,10 @@ static int usX2Y_usb_probe(struct usb_device *device, le16_to_cpu(device->descriptor.idProduct) != USB_ID_US428)) return -EINVAL;
- err = usX2Y_create_card(device, intf, &card); + err = usx2y_create_card(device, intf, &card); if (err < 0) return err; - if ((err = usX2Y_hwdep_new(card, device)) < 0 || + if ((err = usx2y_hwdep_new(card, device)) < 0 || (err = snd_card_register(card)) < 0) { snd_card_free(card); return err; @@ -390,64 +390,64 @@ static int usX2Y_usb_probe(struct usb_device *device, /* * new 2.5 USB kernel API */ -static int snd_usX2Y_probe(struct usb_interface *intf, const struct usb_device_id *id) +static int snd_usx2y_probe(struct usb_interface *intf, const struct usb_device_id *id) { struct snd_card *card; int err;
- err = usX2Y_usb_probe(interface_to_usbdev(intf), intf, id, &card); + err = usx2y_usb_probe(interface_to_usbdev(intf), intf, id, &card); if (err < 0) return err; dev_set_drvdata(&intf->dev, card); return 0; }
-static void snd_usX2Y_disconnect(struct usb_interface *intf) +static void snd_usx2y_disconnect(struct usb_interface *intf) { - usX2Y_usb_disconnect(interface_to_usbdev(intf), + usx2y_usb_disconnect(interface_to_usbdev(intf), usb_get_intfdata(intf)); }
-MODULE_DEVICE_TABLE(usb, snd_usX2Y_usb_id_table); -static struct usb_driver snd_usX2Y_usb_driver = { +MODULE_DEVICE_TABLE(usb, snd_usx2y_usb_id_table); +static struct usb_driver snd_usx2y_usb_driver = { .name = "snd-usb-usx2y", - .probe = snd_usX2Y_probe, - .disconnect = snd_usX2Y_disconnect, - .id_table = snd_usX2Y_usb_id_table, + .probe = snd_usx2y_probe, + .disconnect = snd_usx2y_disconnect, + .id_table = snd_usx2y_usb_id_table, };
-static void snd_usX2Y_card_private_free(struct snd_card *card) +static void snd_usx2y_card_private_free(struct snd_card *card) { - kfree(usX2Y(card)->In04Buf); - usb_free_urb(usX2Y(card)->In04urb); - if (usX2Y(card)->us428ctls_sharedmem) - free_pages_exact(usX2Y(card)->us428ctls_sharedmem, - sizeof(*usX2Y(card)->us428ctls_sharedmem)); - if (usX2Y(card)->card_index >= 0 && usX2Y(card)->card_index < SNDRV_CARDS) - snd_usX2Y_card_used[usX2Y(card)->card_index] = 0; + kfree(usx2y(card)->in04_buf); + usb_free_urb(usx2y(card)->in04_urb); + if (usx2y(card)->us428ctls_sharedmem) + free_pages_exact(usx2y(card)->us428ctls_sharedmem, + sizeof(*usx2y(card)->us428ctls_sharedmem)); + if (usx2y(card)->card_index >= 0 && usx2y(card)->card_index < SNDRV_CARDS) + snd_usx2y_card_used[usx2y(card)->card_index] = 0; }
/* * Frees the device. */ -static void usX2Y_usb_disconnect(struct usb_device *device, void* ptr) +static void usx2y_usb_disconnect(struct usb_device *device, void* ptr) { if (ptr) { struct snd_card *card = ptr; - struct usX2Ydev *usX2Y = usX2Y(card); + struct usx2ydev *usx2y = usx2y(card); struct list_head *p; - usX2Y->chip_status = USX2Y_STAT_CHIP_HUP; - usX2Y_unlinkSeq(&usX2Y->AS04); - usb_kill_urb(usX2Y->In04urb); + usx2y->chip_status = USX2Y_STAT_CHIP_HUP; + usx2y_unlinkseq(&usx2y->as04); + usb_kill_urb(usx2y->in04_urb); snd_card_disconnect(card); /* release the midi resources */ - list_for_each(p, &usX2Y->midi_list) { + list_for_each(p, &usx2y->midi_list) { snd_usbmidi_disconnect(p); } - if (usX2Y->us428ctls_sharedmem) - wake_up(&usX2Y->us428ctls_wait_queue_head); + if (usx2y->us428ctls_sharedmem) + wake_up(&usx2y->us428ctls_wait_queue_head); snd_card_free(card); } }
-module_usb_driver(snd_usX2Y_usb_driver); +module_usb_driver(snd_usx2y_usb_driver); diff --git a/sound/usb/usx2y/usbusx2y.h b/sound/usb/usx2y/usbusx2y.h index 144b85f57bd2..c330af628bcc 100644 --- a/sound/usb/usx2y/usbusx2y.h +++ b/sound/usb/usx2y/usbusx2y.h @@ -8,14 +8,14 @@ #define NRURBS 2
-#define URBS_AsyncSeq 10 -#define URB_DataLen_AsyncSeq 32 -struct snd_usX2Y_AsyncSeq { - struct urb *urb[URBS_AsyncSeq]; +#define URBS_ASYNC_SEQ 10 +#define URB_DATA_LEN_ASYNC_SEQ 32 +struct snd_usx2y_async_seq { + struct urb *urb[URBS_ASYNC_SEQ]; char *buffer; };
-struct snd_usX2Y_urbSeq { +struct snd_usx2y_urb_seq { int submitted; int len; struct urb *urb[]; @@ -23,17 +23,17 @@ struct snd_usX2Y_urbSeq {
#include "usx2yhwdeppcm.h"
-struct usX2Ydev { +struct usx2ydev { struct usb_device *dev; int card_index; int stride; - struct urb *In04urb; - void *In04Buf; - char In04Last[24]; - unsigned In04IntCalls; - struct snd_usX2Y_urbSeq *US04; - wait_queue_head_t In04WaitQueue; - struct snd_usX2Y_AsyncSeq AS04; + struct urb *in04_urb; + void *in04_buf; + char in04_last[24]; + unsigned in04_int_calls; + struct snd_usx2y_urb_seq *us04; + wait_queue_head_t in04_wait_queue; + struct snd_usx2y_async_seq as04; unsigned int rate, format; int chip_status; @@ -41,9 +41,9 @@ struct usX2Ydev { struct us428ctls_sharedmem *us428ctls_sharedmem; int wait_iso_frame; wait_queue_head_t us428ctls_wait_queue_head; - struct snd_usX2Y_hwdep_pcm_shm *hwdep_pcm_shm; - struct snd_usX2Y_substream *subs[4]; - struct snd_usX2Y_substream * volatile prepare_subs; + struct snd_usx2y_hwdep_pcm_shm *hwdep_pcm_shm; + struct snd_usx2y_substream *subs[4]; + struct snd_usx2y_substream * volatile prepare_subs; wait_queue_head_t prepare_wait_queue; struct list_head midi_list; struct list_head pcm_list; @@ -51,21 +51,21 @@ struct usX2Ydev { };
-struct snd_usX2Y_substream { - struct usX2Ydev *usX2Y; +struct snd_usx2y_substream { + struct usx2ydev *usx2y; struct snd_pcm_substream *pcm_substream;
int endpoint; unsigned int maxpacksize; /* max packet size in bytes */
atomic_t state; -#define state_STOPPED 0 -#define state_STARTING1 1 -#define state_STARTING2 2 -#define state_STARTING3 3 -#define state_PREPARED 4 -#define state_PRERUNNING 6 -#define state_RUNNING 8 +#define STATE_STOPPED 0 +#define STATE_STARTING1 1 +#define STATE_STARTING2 2 +#define STATE_STARTING3 3 +#define STATE_PREPARED 4 +#define STATE_PRERUNNING 6 +#define STATE_RUNNING 8
int hwptr; /* free frame position in the buffer (only for playback) */ int hwptr_done; /* processed frame position in the buffer */ @@ -77,12 +77,12 @@ struct snd_usX2Y_substream { };
-#define usX2Y(c) ((struct usX2Ydev *)(c)->private_data) +#define usx2y(c) ((struct usx2ydev *)(c)->private_data)
-int usX2Y_audio_create(struct snd_card *card); +int usx2y_audio_create(struct snd_card *card);
-int usX2Y_AsyncSeq04_init(struct usX2Ydev *usX2Y); -int usX2Y_In04_init(struct usX2Ydev *usX2Y); +int usx2y_async_seq04_init(struct usx2ydev *usx2y); +int usx2y_in04_init(struct usx2ydev *usx2y);
#define NAME_ALLCAPS "US-X2Y"
diff --git a/sound/usb/usx2y/usbusx2yaudio.c b/sound/usb/usx2y/usbusx2yaudio.c index ecaf41265dcd..8033bb7255d5 100644 --- a/sound/usb/usx2y/usbusx2yaudio.c +++ b/sound/usb/usx2y/usbusx2yaudio.c @@ -54,13 +54,13 @@ #endif
-static int usX2Y_urb_capt_retire(struct snd_usX2Y_substream *subs) +static int usx2y_urb_capt_retire(struct snd_usx2y_substream *subs) { struct urb *urb = subs->completed_urb; struct snd_pcm_runtime *runtime = subs->pcm_substream->runtime; unsigned char *cp; int i, len, lens = 0, hwptr_done = subs->hwptr_done; - struct usX2Ydev *usX2Y = subs->usX2Y; + struct usx2ydev *usx2y = subs->usx2y;
for (i = 0; i < nr_of_packs(); i++) { cp = (unsigned char*)urb->transfer_buffer + urb->iso_frame_desc[i].offset; @@ -70,7 +70,7 @@ static int usX2Y_urb_capt_retire(struct snd_usX2Y_substream *subs) urb->iso_frame_desc[i].status); return urb->iso_frame_desc[i].status; } - len = urb->iso_frame_desc[i].actual_length / usX2Y->stride; + len = urb->iso_frame_desc[i].actual_length / usx2y->stride; if (! len) { snd_printd("0 == len ERROR!\n"); continue; @@ -79,12 +79,12 @@ static int usX2Y_urb_capt_retire(struct snd_usX2Y_substream *subs) /* copy a data chunk */ if ((hwptr_done + len) > runtime->buffer_size) { int cnt = runtime->buffer_size - hwptr_done; - int blen = cnt * usX2Y->stride; - memcpy(runtime->dma_area + hwptr_done * usX2Y->stride, cp, blen); - memcpy(runtime->dma_area, cp + blen, len * usX2Y->stride - blen); + int blen = cnt * usx2y->stride; + memcpy(runtime->dma_area + hwptr_done * usx2y->stride, cp, blen); + memcpy(runtime->dma_area, cp + blen, len * usx2y->stride - blen); } else { - memcpy(runtime->dma_area + hwptr_done * usX2Y->stride, cp, - len * usX2Y->stride); + memcpy(runtime->dma_area + hwptr_done * usx2y->stride, cp, + len * usx2y->stride); } lens += len; if ((hwptr_done += len) >= runtime->buffer_size) @@ -110,18 +110,18 @@ static int usX2Y_urb_capt_retire(struct snd_usX2Y_substream *subs) * it directly from the buffer. thus the data is once copied to * a temporary buffer and urb points to that. */ -static int usX2Y_urb_play_prepare(struct snd_usX2Y_substream *subs, +static int usx2y_urb_play_prepare(struct snd_usx2y_substream *subs, struct urb *cap_urb, struct urb *urb) { int count, counts, pack; - struct usX2Ydev *usX2Y = subs->usX2Y; + struct usx2ydev *usx2y = subs->usx2y; struct snd_pcm_runtime *runtime = subs->pcm_substream->runtime;
count = 0; for (pack = 0; pack < nr_of_packs(); pack++) { /* calculate the size of a packet */ - counts = cap_urb->iso_frame_desc[pack].actual_length / usX2Y->stride; + counts = cap_urb->iso_frame_desc[pack].actual_length / usx2y->stride; count += counts; if (counts < 43 || counts > 50) { snd_printk(KERN_ERR "should not be here with counts=%i\n", counts); @@ -134,7 +134,7 @@ static int usX2Y_urb_play_prepare(struct snd_usX2Y_substream *subs, 0; urb->iso_frame_desc[pack].length = cap_urb->iso_frame_desc[pack].actual_length; } - if (atomic_read(&subs->state) >= state_PRERUNNING) + if (atomic_read(&subs->state) >= STATE_PRERUNNING) if (subs->hwptr + count > runtime->buffer_size) { /* err, the transferred area goes over buffer boundary. * copy the data to the temp buffer. @@ -143,20 +143,20 @@ static int usX2Y_urb_play_prepare(struct snd_usX2Y_substream *subs, len = runtime->buffer_size - subs->hwptr; urb->transfer_buffer = subs->tmpbuf; memcpy(subs->tmpbuf, runtime->dma_area + - subs->hwptr * usX2Y->stride, len * usX2Y->stride); - memcpy(subs->tmpbuf + len * usX2Y->stride, - runtime->dma_area, (count - len) * usX2Y->stride); + subs->hwptr * usx2y->stride, len * usx2y->stride); + memcpy(subs->tmpbuf + len * usx2y->stride, + runtime->dma_area, (count - len) * usx2y->stride); subs->hwptr += count; subs->hwptr -= runtime->buffer_size; } else { /* set the buffer pointer */ - urb->transfer_buffer = runtime->dma_area + subs->hwptr * usX2Y->stride; + urb->transfer_buffer = runtime->dma_area + subs->hwptr * usx2y->stride; if ((subs->hwptr += count) >= runtime->buffer_size) subs->hwptr -= runtime->buffer_size; } else urb->transfer_buffer = subs->tmpbuf; - urb->transfer_buffer_length = count * usX2Y->stride; + urb->transfer_buffer_length = count * usx2y->stride; return 0; }
@@ -165,10 +165,10 @@ static int usX2Y_urb_play_prepare(struct snd_usX2Y_substream *subs, * * update the current position and call callback if a period is processed. */ -static void usX2Y_urb_play_retire(struct snd_usX2Y_substream *subs, struct urb *urb) +static void usx2y_urb_play_retire(struct snd_usx2y_substream *subs, struct urb *urb) { struct snd_pcm_runtime *runtime = subs->pcm_substream->runtime; - int len = urb->actual_length / subs->usX2Y->stride; + int len = urb->actual_length / subs->usx2y->stride;
subs->transfer_done += len; subs->hwptr_done += len; @@ -180,14 +180,14 @@ static void usX2Y_urb_play_retire(struct snd_usX2Y_substream *subs, struct urb * } }
-static int usX2Y_urb_submit(struct snd_usX2Y_substream *subs, struct urb *urb, int frame) +static int usx2y_urb_submit(struct snd_usx2y_substream *subs, struct urb *urb, int frame) { int err; if (!urb) return -ENODEV; urb->start_frame = (frame + NRURBS * nr_of_packs()); // let hcd do rollover sanity checks urb->hcpriv = NULL; - urb->dev = subs->usX2Y->dev; /* we need to set this at each time */ + urb->dev = subs->usx2y->dev; /* we need to set this at each time */ if ((err = usb_submit_urb(urb, GFP_ATOMIC)) < 0) { snd_printk(KERN_ERR "usb_submit_urb() returned %i\n", err); return err; @@ -195,8 +195,8 @@ static int usX2Y_urb_submit(struct snd_usX2Y_substream *subs, struct urb *urb, i return 0; }
-static inline int usX2Y_usbframe_complete(struct snd_usX2Y_substream *capsubs, - struct snd_usX2Y_substream *playbacksubs, +static inline int usx2y_usbframe_complete(struct snd_usx2y_substream *capsubs, + struct snd_usx2y_substream *playbacksubs, int frame) { int err, state; @@ -204,25 +204,25 @@ static inline int usX2Y_usbframe_complete(struct snd_usX2Y_substream *capsubs,
state = atomic_read(&playbacksubs->state); if (NULL != urb) { - if (state == state_RUNNING) - usX2Y_urb_play_retire(playbacksubs, urb); - else if (state >= state_PRERUNNING) + if (state == STATE_RUNNING) + usx2y_urb_play_retire(playbacksubs, urb); + else if (state >= STATE_PRERUNNING) atomic_inc(&playbacksubs->state); } else { switch (state) { - case state_STARTING1: + case STATE_STARTING1: urb = playbacksubs->urb[0]; atomic_inc(&playbacksubs->state); break; - case state_STARTING2: + case STATE_STARTING2: urb = playbacksubs->urb[1]; atomic_inc(&playbacksubs->state); break; } } if (urb) { - if ((err = usX2Y_urb_play_prepare(playbacksubs, capsubs->completed_urb, urb)) || - (err = usX2Y_urb_submit(playbacksubs, urb, frame))) { + if ((err = usx2y_urb_play_prepare(playbacksubs, capsubs->completed_urb, urb)) || + (err = usx2y_urb_submit(playbacksubs, urb, frame))) { return err; } } @@ -230,13 +230,13 @@ static inline int usX2Y_usbframe_complete(struct snd_usX2Y_substream *capsubs, playbacksubs->completed_urb = NULL;
state = atomic_read(&capsubs->state); - if (state >= state_PREPARED) { - if (state == state_RUNNING) { - if ((err = usX2Y_urb_capt_retire(capsubs))) + if (state >= STATE_PREPARED) { + if (state == STATE_RUNNING) { + if ((err = usx2y_urb_capt_retire(capsubs))) return err; - } else if (state >= state_PRERUNNING) + } else if (state >= STATE_PRERUNNING) atomic_inc(&capsubs->state); - if ((err = usX2Y_urb_submit(capsubs, capsubs->completed_urb, frame))) + if ((err = usx2y_urb_submit(capsubs, capsubs->completed_urb, frame))) return err; } capsubs->completed_urb = NULL; @@ -244,21 +244,21 @@ static inline int usX2Y_usbframe_complete(struct snd_usX2Y_substream *capsubs, }
-static void usX2Y_clients_stop(struct usX2Ydev *usX2Y) +static void usx2y_clients_stop(struct usx2ydev *usx2y) { int s, u;
for (s = 0; s < 4; s++) { - struct snd_usX2Y_substream *subs = usX2Y->subs[s]; + struct snd_usx2y_substream *subs = usx2y->subs[s]; if (subs) { snd_printdd("%i %p state=%i\n", s, subs, atomic_read(&subs->state)); - atomic_set(&subs->state, state_STOPPED); + atomic_set(&subs->state, STATE_STOPPED); } } for (s = 0; s < 4; s++) { - struct snd_usX2Y_substream *subs = usX2Y->subs[s]; + struct snd_usx2y_substream *subs = usx2y->subs[s]; if (subs) { - if (atomic_read(&subs->state) >= state_PRERUNNING) + if (atomic_read(&subs->state) >= STATE_PRERUNNING) snd_pcm_stop_xrun(subs->pcm_substream); for (u = 0; u < NRURBS; u++) { struct urb *urb = subs->urb[u]; @@ -268,60 +268,60 @@ static void usX2Y_clients_stop(struct usX2Ydev *usX2Y) } } } - usX2Y->prepare_subs = NULL; - wake_up(&usX2Y->prepare_wait_queue); + usx2y->prepare_subs = NULL; + wake_up(&usx2y->prepare_wait_queue); }
-static void usX2Y_error_urb_status(struct usX2Ydev *usX2Y, - struct snd_usX2Y_substream *subs, struct urb *urb) +static void usx2y_error_urb_status(struct usx2ydev *usx2y, + struct snd_usx2y_substream *subs, struct urb *urb) { snd_printk(KERN_ERR "ep=%i stalled with status=%i\n", subs->endpoint, urb->status); urb->status = 0; - usX2Y_clients_stop(usX2Y); + usx2y_clients_stop(usx2y); }
-static void i_usX2Y_urb_complete(struct urb *urb) +static void i_usx2y_urb_complete(struct urb *urb) { - struct snd_usX2Y_substream *subs = urb->context; - struct usX2Ydev *usX2Y = subs->usX2Y; + struct snd_usx2y_substream *subs = urb->context; + struct usx2ydev *usx2y = subs->usx2y;
- if (unlikely(atomic_read(&subs->state) < state_PREPARED)) { + if (unlikely(atomic_read(&subs->state) < STATE_PREPARED)) { snd_printdd("hcd_frame=%i ep=%i%s status=%i start_frame=%i\n", - usb_get_current_frame_number(usX2Y->dev), + usb_get_current_frame_number(usx2y->dev), subs->endpoint, usb_pipein(urb->pipe) ? "in" : "out", urb->status, urb->start_frame); return; } if (unlikely(urb->status)) { - usX2Y_error_urb_status(usX2Y, subs, urb); + usx2y_error_urb_status(usx2y, subs, urb); return; }
subs->completed_urb = urb;
{ - struct snd_usX2Y_substream *capsubs = usX2Y->subs[SNDRV_PCM_STREAM_CAPTURE], - *playbacksubs = usX2Y->subs[SNDRV_PCM_STREAM_PLAYBACK]; + struct snd_usx2y_substream *capsubs = usx2y->subs[SNDRV_PCM_STREAM_CAPTURE], + *playbacksubs = usx2y->subs[SNDRV_PCM_STREAM_PLAYBACK]; if (capsubs->completed_urb && - atomic_read(&capsubs->state) >= state_PREPARED && + atomic_read(&capsubs->state) >= STATE_PREPARED && (playbacksubs->completed_urb || - atomic_read(&playbacksubs->state) < state_PREPARED)) { - if (!usX2Y_usbframe_complete(capsubs, playbacksubs, urb->start_frame)) - usX2Y->wait_iso_frame += nr_of_packs(); + atomic_read(&playbacksubs->state) < STATE_PREPARED)) { + if (!usx2y_usbframe_complete(capsubs, playbacksubs, urb->start_frame)) + usx2y->wait_iso_frame += nr_of_packs(); else { snd_printdd("\n"); - usX2Y_clients_stop(usX2Y); + usx2y_clients_stop(usx2y); } } } }
-static void usX2Y_urbs_set_complete(struct usX2Ydev * usX2Y, +static void usx2y_urbs_set_complete(struct usx2ydev * usx2y, void (*complete)(struct urb *)) { int s, u; for (s = 0; s < 4; s++) { - struct snd_usX2Y_substream *subs = usX2Y->subs[s]; + struct snd_usx2y_substream *subs = usx2y->subs[s]; if (NULL != subs) for (u = 0; u < NRURBS; u++) { struct urb * urb = subs->urb[u]; @@ -331,30 +331,30 @@ static void usX2Y_urbs_set_complete(struct usX2Ydev * usX2Y, } }
-static void usX2Y_subs_startup_finish(struct usX2Ydev * usX2Y) +static void usx2y_subs_startup_finish(struct usx2ydev * usx2y) { - usX2Y_urbs_set_complete(usX2Y, i_usX2Y_urb_complete); - usX2Y->prepare_subs = NULL; + usx2y_urbs_set_complete(usx2y, i_usx2y_urb_complete); + usx2y->prepare_subs = NULL; }
-static void i_usX2Y_subs_startup(struct urb *urb) +static void i_usx2y_subs_startup(struct urb *urb) { - struct snd_usX2Y_substream *subs = urb->context; - struct usX2Ydev *usX2Y = subs->usX2Y; - struct snd_usX2Y_substream *prepare_subs = usX2Y->prepare_subs; + struct snd_usx2y_substream *subs = urb->context; + struct usx2ydev *usx2y = subs->usx2y; + struct snd_usx2y_substream *prepare_subs = usx2y->prepare_subs; if (NULL != prepare_subs) if (urb->start_frame == prepare_subs->urb[0]->start_frame) { - usX2Y_subs_startup_finish(usX2Y); + usx2y_subs_startup_finish(usx2y); atomic_inc(&prepare_subs->state); - wake_up(&usX2Y->prepare_wait_queue); + wake_up(&usx2y->prepare_wait_queue); }
- i_usX2Y_urb_complete(urb); + i_usx2y_urb_complete(urb); }
-static void usX2Y_subs_prepare(struct snd_usX2Y_substream *subs) +static void usx2y_subs_prepare(struct snd_usx2y_substream *subs) { - snd_printdd("usX2Y_substream_prepare(%p) ep=%i urb0=%p urb1=%p\n", + snd_printdd("usx2y_substream_prepare(%p) ep=%i urb0=%p urb1=%p\n", subs, subs->endpoint, subs->urb[0], subs->urb[1]); /* reset the pointer */ subs->hwptr = 0; @@ -363,7 +363,7 @@ static void usX2Y_subs_prepare(struct snd_usX2Y_substream *subs) }
-static void usX2Y_urb_release(struct urb **urb, int free_tb) +static void usx2y_urb_release(struct urb **urb, int free_tb) { if (*urb) { usb_kill_urb(*urb); @@ -376,13 +376,13 @@ static void usX2Y_urb_release(struct urb **urb, int free_tb) /* * release a substreams urbs */ -static void usX2Y_urbs_release(struct snd_usX2Y_substream *subs) +static void usx2y_urbs_release(struct snd_usx2y_substream *subs) { int i; - snd_printdd("usX2Y_urbs_release() %i\n", subs->endpoint); + snd_printdd("usx2y_urbs_release() %i\n", subs->endpoint); for (i = 0; i < NRURBS; i++) - usX2Y_urb_release(subs->urb + i, - subs != subs->usX2Y->subs[SNDRV_PCM_STREAM_PLAYBACK]); + usx2y_urb_release(subs->urb + i, + subs != subs->usx2y->subs[SNDRV_PCM_STREAM_PLAYBACK]);
kfree(subs->tmpbuf); subs->tmpbuf = NULL; @@ -390,12 +390,12 @@ static void usX2Y_urbs_release(struct snd_usX2Y_substream *subs) /* * initialize a substream's urbs */ -static int usX2Y_urbs_allocate(struct snd_usX2Y_substream *subs) +static int usx2y_urbs_allocate(struct snd_usx2y_substream *subs) { int i; unsigned int pipe; - int is_playback = subs == subs->usX2Y->subs[SNDRV_PCM_STREAM_PLAYBACK]; - struct usb_device *dev = subs->usX2Y->dev; + int is_playback = subs == subs->usx2y->subs[SNDRV_PCM_STREAM_PLAYBACK]; + struct usb_device *dev = subs->usx2y->dev;
pipe = is_playback ? usb_sndisocpipe(dev, subs->endpoint) : usb_rcvisocpipe(dev, subs->endpoint); @@ -417,7 +417,7 @@ static int usX2Y_urbs_allocate(struct snd_usX2Y_substream *subs) } *purb = usb_alloc_urb(nr_of_packs(), GFP_KERNEL); if (NULL == *purb) { - usX2Y_urbs_release(subs); + usx2y_urbs_release(subs); return -ENOMEM; } if (!is_playback && !(*purb)->transfer_buffer) { @@ -426,7 +426,7 @@ static int usX2Y_urbs_allocate(struct snd_usX2Y_substream *subs) kmalloc_array(subs->maxpacksize, nr_of_packs(), GFP_KERNEL); if (NULL == (*purb)->transfer_buffer) { - usX2Y_urbs_release(subs); + usx2y_urbs_release(subs); return -ENOMEM; } } @@ -435,43 +435,43 @@ static int usX2Y_urbs_allocate(struct snd_usX2Y_substream *subs) (*purb)->number_of_packets = nr_of_packs(); (*purb)->context = subs; (*purb)->interval = 1; - (*purb)->complete = i_usX2Y_subs_startup; + (*purb)->complete = i_usx2y_subs_startup; } return 0; }
-static void usX2Y_subs_startup(struct snd_usX2Y_substream *subs) +static void usx2y_subs_startup(struct snd_usx2y_substream *subs) { - struct usX2Ydev *usX2Y = subs->usX2Y; - usX2Y->prepare_subs = subs; + struct usx2ydev *usx2y = subs->usx2y; + usx2y->prepare_subs = subs; subs->urb[0]->start_frame = -1; wmb(); - usX2Y_urbs_set_complete(usX2Y, i_usX2Y_subs_startup); + usx2y_urbs_set_complete(usx2y, i_usx2y_subs_startup); }
-static int usX2Y_urbs_start(struct snd_usX2Y_substream *subs) +static int usx2y_urbs_start(struct snd_usx2y_substream *subs) { int i, err; - struct usX2Ydev *usX2Y = subs->usX2Y; + struct usx2ydev *usx2y = subs->usx2y;
- if ((err = usX2Y_urbs_allocate(subs)) < 0) + if ((err = usx2y_urbs_allocate(subs)) < 0) return err; subs->completed_urb = NULL; for (i = 0; i < 4; i++) { - struct snd_usX2Y_substream *subs = usX2Y->subs[i]; - if (subs != NULL && atomic_read(&subs->state) >= state_PREPARED) + struct snd_usx2y_substream *subs = usx2y->subs[i]; + if (subs != NULL && atomic_read(&subs->state) >= STATE_PREPARED) goto start; }
start: - usX2Y_subs_startup(subs); + usx2y_subs_startup(subs); for (i = 0; i < NRURBS; i++) { struct urb *urb = subs->urb[i]; if (usb_pipein(urb->pipe)) { unsigned long pack; if (0 == i) - atomic_set(&subs->state, state_STARTING3); - urb->dev = usX2Y->dev; + atomic_set(&subs->state, STATE_STARTING3); + urb->dev = usx2y->dev; for (pack = 0; pack < nr_of_packs(); pack++) { urb->iso_frame_desc[pack].offset = subs->maxpacksize * pack; urb->iso_frame_desc[pack].length = subs->maxpacksize; @@ -483,22 +483,22 @@ static int usX2Y_urbs_start(struct snd_usX2Y_substream *subs) goto cleanup; } else if (i == 0) - usX2Y->wait_iso_frame = urb->start_frame; + usx2y->wait_iso_frame = urb->start_frame; urb->transfer_flags = 0; } else { - atomic_set(&subs->state, state_STARTING1); + atomic_set(&subs->state, STATE_STARTING1); break; } } err = 0; - wait_event(usX2Y->prepare_wait_queue, NULL == usX2Y->prepare_subs); - if (atomic_read(&subs->state) != state_PREPARED) + wait_event(usx2y->prepare_wait_queue, NULL == usx2y->prepare_subs); + if (atomic_read(&subs->state) != STATE_PREPARED) err = -EPIPE;
cleanup: if (err) { - usX2Y_subs_startup_finish(usX2Y); - usX2Y_clients_stop(usX2Y); // something is completely wroong > stop evrything + usx2y_subs_startup_finish(usx2y); + usx2y_clients_stop(usx2y); // something is completely wroong > stop evrything } return err; } @@ -506,33 +506,33 @@ static int usX2Y_urbs_start(struct snd_usX2Y_substream *subs) /* * return the current pcm pointer. just return the hwptr_done value. */ -static snd_pcm_uframes_t snd_usX2Y_pcm_pointer(struct snd_pcm_substream *substream) +static snd_pcm_uframes_t snd_usx2y_pcm_pointer(struct snd_pcm_substream *substream) { - struct snd_usX2Y_substream *subs = substream->runtime->private_data; + struct snd_usx2y_substream *subs = substream->runtime->private_data; return subs->hwptr_done; } /* * start/stop substream */ -static int snd_usX2Y_pcm_trigger(struct snd_pcm_substream *substream, int cmd) +static int snd_usx2y_pcm_trigger(struct snd_pcm_substream *substream, int cmd) { - struct snd_usX2Y_substream *subs = substream->runtime->private_data; + struct snd_usx2y_substream *subs = substream->runtime->private_data;
switch (cmd) { case SNDRV_PCM_TRIGGER_START: - snd_printdd("snd_usX2Y_pcm_trigger(START)\n"); - if (atomic_read(&subs->state) == state_PREPARED && - atomic_read(&subs->usX2Y->subs[SNDRV_PCM_STREAM_CAPTURE]->state) >= state_PREPARED) { - atomic_set(&subs->state, state_PRERUNNING); + snd_printdd("snd_usx2y_pcm_trigger(START)\n"); + if (atomic_read(&subs->state) == STATE_PREPARED && + atomic_read(&subs->usx2y->subs[SNDRV_PCM_STREAM_CAPTURE]->state) >= STATE_PREPARED) { + atomic_set(&subs->state, STATE_PRERUNNING); } else { snd_printdd("\n"); return -EPIPE; } break; case SNDRV_PCM_TRIGGER_STOP: - snd_printdd("snd_usX2Y_pcm_trigger(STOP)\n"); - if (atomic_read(&subs->state) >= state_PRERUNNING) - atomic_set(&subs->state, state_PREPARED); + snd_printdd("snd_usx2y_pcm_trigger(STOP)\n"); + if (atomic_read(&subs->state) >= STATE_PRERUNNING) + atomic_set(&subs->state, STATE_PREPARED); break; default: return -EINVAL; @@ -553,7 +553,7 @@ static const struct s_c2 { char c1, c2; } - SetRate44100[] = + setrate_44100[] = { { 0x14, 0x08}, // this line sets 44100, well actually a little less { 0x18, 0x40}, // only tascam / frontier design knows the further lines ....... @@ -589,7 +589,7 @@ static const struct s_c2 { 0x18, 0x7C}, { 0x18, 0x7E} }; -static const struct s_c2 SetRate48000[] = +static const struct s_c2 setrate_48000[] = { { 0x14, 0x09}, // this line sets 48000, well actually a little less { 0x18, 0x40}, // only tascam / frontier design knows the further lines ....... @@ -625,26 +625,26 @@ static const struct s_c2 SetRate48000[] = { 0x18, 0x7C}, { 0x18, 0x7E} }; -#define NOOF_SETRATE_URBS ARRAY_SIZE(SetRate48000) +#define NOOF_SETRATE_URBS ARRAY_SIZE(setrate_48000)
-static void i_usX2Y_04Int(struct urb *urb) +static void i_usx2y_04int(struct urb *urb) { - struct usX2Ydev *usX2Y = urb->context; + struct usx2ydev *usx2y = urb->context; if (urb->status) - snd_printk(KERN_ERR "snd_usX2Y_04Int() urb->status=%i\n", urb->status); - if (0 == --usX2Y->US04->len) - wake_up(&usX2Y->In04WaitQueue); + snd_printk(KERN_ERR "snd_usx2y_04int() urb->status=%i\n", urb->status); + if (0 == --usx2y->us04->len) + wake_up(&usx2y->in04_wait_queue); }
-static int usX2Y_rate_set(struct usX2Ydev *usX2Y, int rate) +static int usx2y_rate_set(struct usx2ydev *usx2y, int rate) { int err = 0, i; - struct snd_usX2Y_urbSeq *us = NULL; + struct snd_usx2y_urb_seq *us = NULL; int *usbdata = NULL; - const struct s_c2 *ra = rate == 48000 ? SetRate48000 : SetRate44100; + const struct s_c2 *ra = rate == 48000 ? setrate_48000 : setrate_44100;
- if (usX2Y->rate != rate) { + if (usx2y->rate != rate) { us = kzalloc(sizeof(*us) + sizeof(struct urb*) * NOOF_SETRATE_URBS, GFP_KERNEL); if (NULL == us) { err = -ENOMEM; @@ -663,17 +663,17 @@ static int usX2Y_rate_set(struct usX2Ydev *usX2Y, int rate) } ((char*)(usbdata + i))[0] = ra[i].c1; ((char*)(usbdata + i))[1] = ra[i].c2; - usb_fill_bulk_urb(us->urb[i], usX2Y->dev, usb_sndbulkpipe(usX2Y->dev, 4), - usbdata + i, 2, i_usX2Y_04Int, usX2Y); + usb_fill_bulk_urb(us->urb[i], usx2y->dev, usb_sndbulkpipe(usx2y->dev, 4), + usbdata + i, 2, i_usx2y_04int, usx2y); } err = usb_urb_ep_type_check(us->urb[0]); if (err < 0) goto cleanup; us->submitted = 0; us->len = NOOF_SETRATE_URBS; - usX2Y->US04 = us; - wait_event_timeout(usX2Y->In04WaitQueue, 0 == us->len, HZ); - usX2Y->US04 = NULL; + usx2y->us04 = us; + wait_event_timeout(usx2y->in04_wait_queue, 0 == us->len, HZ); + usx2y->us04 = NULL; if (us->len) err = -ENODEV; cleanup: @@ -690,11 +690,11 @@ static int usX2Y_rate_set(struct usX2Ydev *usX2Y, int rate) } usb_free_urb(urb); } - usX2Y->US04 = NULL; + usx2y->us04 = NULL; kfree(usbdata); kfree(us); if (!err) - usX2Y->rate = rate; + usx2y->rate = rate; } }
@@ -702,53 +702,53 @@ static int usX2Y_rate_set(struct usX2Ydev *usX2Y, int rate) }
-static int usX2Y_format_set(struct usX2Ydev *usX2Y, snd_pcm_format_t format) +static int usx2y_format_set(struct usx2ydev *usx2y, snd_pcm_format_t format) { int alternate, err; struct list_head* p; if (format == SNDRV_PCM_FORMAT_S24_3LE) { alternate = 2; - usX2Y->stride = 6; + usx2y->stride = 6; } else { alternate = 1; - usX2Y->stride = 4; + usx2y->stride = 4; } - list_for_each(p, &usX2Y->midi_list) { + list_for_each(p, &usx2y->midi_list) { snd_usbmidi_input_stop(p); } - usb_kill_urb(usX2Y->In04urb); - if ((err = usb_set_interface(usX2Y->dev, 0, alternate))) { + usb_kill_urb(usx2y->in04_urb); + if ((err = usb_set_interface(usx2y->dev, 0, alternate))) { snd_printk(KERN_ERR "usb_set_interface error \n"); return err; } - usX2Y->In04urb->dev = usX2Y->dev; - err = usb_submit_urb(usX2Y->In04urb, GFP_KERNEL); - list_for_each(p, &usX2Y->midi_list) { + usx2y->in04_urb->dev = usx2y->dev; + err = usb_submit_urb(usx2y->in04_urb, GFP_KERNEL); + list_for_each(p, &usx2y->midi_list) { snd_usbmidi_input_start(p); } - usX2Y->format = format; - usX2Y->rate = 0; + usx2y->format = format; + usx2y->rate = 0; return err; }
-static int snd_usX2Y_pcm_hw_params(struct snd_pcm_substream *substream, +static int snd_usx2y_pcm_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *hw_params) { int err = 0; unsigned int rate = params_rate(hw_params); snd_pcm_format_t format = params_format(hw_params); struct snd_card *card = substream->pstr->pcm->card; - struct usX2Ydev *dev = usX2Y(card); + struct usx2ydev *dev = usx2y(card); int i;
- mutex_lock(&usX2Y(card)->pcm_mutex); - snd_printdd("snd_usX2Y_hw_params(%p, %p)\n", substream, hw_params); - /* all pcm substreams off one usX2Y have to operate at the same + mutex_lock(&usx2y(card)->pcm_mutex); + snd_printdd("snd_usx2y_hw_params(%p, %p)\n", substream, hw_params); + /* all pcm substreams off one usx2y have to operate at the same * rate & format */ for (i = 0; i < dev->pcm_devs * 2; i++) { - struct snd_usX2Y_substream *subs = dev->subs[i]; + struct snd_usx2y_substream *subs = dev->subs[i]; struct snd_pcm_substream *test_substream;
if (!subs) @@ -767,39 +767,39 @@ static int snd_usX2Y_pcm_hw_params(struct snd_pcm_substream *substream, }
error: - mutex_unlock(&usX2Y(card)->pcm_mutex); + mutex_unlock(&usx2y(card)->pcm_mutex); return err; }
/* * free the buffer */ -static int snd_usX2Y_pcm_hw_free(struct snd_pcm_substream *substream) +static int snd_usx2y_pcm_hw_free(struct snd_pcm_substream *substream) { struct snd_pcm_runtime *runtime = substream->runtime; - struct snd_usX2Y_substream *subs = runtime->private_data; - mutex_lock(&subs->usX2Y->pcm_mutex); - snd_printdd("snd_usX2Y_hw_free(%p)\n", substream); + struct snd_usx2y_substream *subs = runtime->private_data; + mutex_lock(&subs->usx2y->pcm_mutex); + snd_printdd("snd_usx2y_hw_free(%p)\n", substream);
if (SNDRV_PCM_STREAM_PLAYBACK == substream->stream) { - struct snd_usX2Y_substream *cap_subs = subs->usX2Y->subs[SNDRV_PCM_STREAM_CAPTURE]; - atomic_set(&subs->state, state_STOPPED); - usX2Y_urbs_release(subs); + struct snd_usx2y_substream *cap_subs = subs->usx2y->subs[SNDRV_PCM_STREAM_CAPTURE]; + atomic_set(&subs->state, STATE_STOPPED); + usx2y_urbs_release(subs); if (!cap_subs->pcm_substream || !cap_subs->pcm_substream->runtime || !cap_subs->pcm_substream->runtime->status || cap_subs->pcm_substream->runtime->status->state < SNDRV_PCM_STATE_PREPARED) { - atomic_set(&cap_subs->state, state_STOPPED); - usX2Y_urbs_release(cap_subs); + atomic_set(&cap_subs->state, STATE_STOPPED); + usx2y_urbs_release(cap_subs); } } else { - struct snd_usX2Y_substream *playback_subs = subs->usX2Y->subs[SNDRV_PCM_STREAM_PLAYBACK]; - if (atomic_read(&playback_subs->state) < state_PREPARED) { - atomic_set(&subs->state, state_STOPPED); - usX2Y_urbs_release(subs); + struct snd_usx2y_substream *playback_subs = subs->usx2y->subs[SNDRV_PCM_STREAM_PLAYBACK]; + if (atomic_read(&playback_subs->state) < STATE_PREPARED) { + atomic_set(&subs->state, STATE_STOPPED); + usx2y_urbs_release(subs); } } - mutex_unlock(&subs->usX2Y->pcm_mutex); + mutex_unlock(&subs->usx2y->pcm_mutex); return 0; } /* @@ -807,40 +807,40 @@ static int snd_usX2Y_pcm_hw_free(struct snd_pcm_substream *substream) * * set format and initialize urbs */ -static int snd_usX2Y_pcm_prepare(struct snd_pcm_substream *substream) +static int snd_usx2y_pcm_prepare(struct snd_pcm_substream *substream) { struct snd_pcm_runtime *runtime = substream->runtime; - struct snd_usX2Y_substream *subs = runtime->private_data; - struct usX2Ydev *usX2Y = subs->usX2Y; - struct snd_usX2Y_substream *capsubs = subs->usX2Y->subs[SNDRV_PCM_STREAM_CAPTURE]; + struct snd_usx2y_substream *subs = runtime->private_data; + struct usx2ydev *usx2y = subs->usx2y; + struct snd_usx2y_substream *capsubs = subs->usx2y->subs[SNDRV_PCM_STREAM_CAPTURE]; int err = 0; - snd_printdd("snd_usX2Y_pcm_prepare(%p)\n", substream); + snd_printdd("snd_usx2y_pcm_prepare(%p)\n", substream);
- mutex_lock(&usX2Y->pcm_mutex); - usX2Y_subs_prepare(subs); + mutex_lock(&usx2y->pcm_mutex); + usx2y_subs_prepare(subs); // Start hardware streams // SyncStream first.... - if (atomic_read(&capsubs->state) < state_PREPARED) { - if (usX2Y->format != runtime->format) - if ((err = usX2Y_format_set(usX2Y, runtime->format)) < 0) + if (atomic_read(&capsubs->state) < STATE_PREPARED) { + if (usx2y->format != runtime->format) + if ((err = usx2y_format_set(usx2y, runtime->format)) < 0) goto up_prepare_mutex; - if (usX2Y->rate != runtime->rate) - if ((err = usX2Y_rate_set(usX2Y, runtime->rate)) < 0) + if (usx2y->rate != runtime->rate) + if ((err = usx2y_rate_set(usx2y, runtime->rate)) < 0) goto up_prepare_mutex; snd_printdd("starting capture pipe for %s\n", subs == capsubs ? "self" : "playpipe"); - if (0 > (err = usX2Y_urbs_start(capsubs))) + if (0 > (err = usx2y_urbs_start(capsubs))) goto up_prepare_mutex; }
- if (subs != capsubs && atomic_read(&subs->state) < state_PREPARED) - err = usX2Y_urbs_start(subs); + if (subs != capsubs && atomic_read(&subs->state) < STATE_PREPARED) + err = usx2y_urbs_start(subs);
up_prepare_mutex: - mutex_unlock(&usX2Y->pcm_mutex); + mutex_unlock(&usx2y->pcm_mutex); return err; }
-static const struct snd_pcm_hardware snd_usX2Y_2c = +static const struct snd_pcm_hardware snd_usx2y_2c = { .info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_BLOCK_TRANSFER | @@ -862,16 +862,16 @@ static const struct snd_pcm_hardware snd_usX2Y_2c =
-static int snd_usX2Y_pcm_open(struct snd_pcm_substream *substream) +static int snd_usx2y_pcm_open(struct snd_pcm_substream *substream) { - struct snd_usX2Y_substream *subs = ((struct snd_usX2Y_substream **) + struct snd_usx2y_substream *subs = ((struct snd_usx2y_substream **) snd_pcm_substream_chip(substream))[substream->stream]; struct snd_pcm_runtime *runtime = substream->runtime;
- if (subs->usX2Y->chip_status & USX2Y_STAT_CHIP_MMAP_PCM_URBS) + if (subs->usx2y->chip_status & USX2Y_STAT_CHIP_MMAP_PCM_URBS) return -EBUSY;
- runtime->hw = snd_usX2Y_2c; + runtime->hw = snd_usx2y_2c; runtime->private_data = subs; subs->pcm_substream = substream; snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_PERIOD_TIME, 1000, 200000); @@ -880,10 +880,10 @@ static int snd_usX2Y_pcm_open(struct snd_pcm_substream *substream)
-static int snd_usX2Y_pcm_close(struct snd_pcm_substream *substream) +static int snd_usx2y_pcm_close(struct snd_pcm_substream *substream) { struct snd_pcm_runtime *runtime = substream->runtime; - struct snd_usX2Y_substream *subs = runtime->private_data; + struct snd_usx2y_substream *subs = runtime->private_data;
subs->pcm_substream = NULL;
@@ -891,75 +891,75 @@ static int snd_usX2Y_pcm_close(struct snd_pcm_substream *substream) }
-static const struct snd_pcm_ops snd_usX2Y_pcm_ops = +static const struct snd_pcm_ops snd_usx2y_pcm_ops = { - .open = snd_usX2Y_pcm_open, - .close = snd_usX2Y_pcm_close, - .hw_params = snd_usX2Y_pcm_hw_params, - .hw_free = snd_usX2Y_pcm_hw_free, - .prepare = snd_usX2Y_pcm_prepare, - .trigger = snd_usX2Y_pcm_trigger, - .pointer = snd_usX2Y_pcm_pointer, + .open = snd_usx2y_pcm_open, + .close = snd_usx2y_pcm_close, + .hw_params = snd_usx2y_pcm_hw_params, + .hw_free = snd_usx2y_pcm_hw_free, + .prepare = snd_usx2y_pcm_prepare, + .trigger = snd_usx2y_pcm_trigger, + .pointer = snd_usx2y_pcm_pointer, };
/* * free a usb stream instance */ -static void usX2Y_audio_stream_free(struct snd_usX2Y_substream **usX2Y_substream) +static void usx2y_audio_stream_free(struct snd_usx2y_substream **usx2y_substream) { int stream;
for_each_pcm_streams(stream) { - kfree(usX2Y_substream[stream]); - usX2Y_substream[stream] = NULL; + kfree(usx2y_substream[stream]); + usx2y_substream[stream] = NULL; } }
-static void snd_usX2Y_pcm_private_free(struct snd_pcm *pcm) +static void snd_usx2y_pcm_private_free(struct snd_pcm *pcm) { - struct snd_usX2Y_substream **usX2Y_stream = pcm->private_data; - if (usX2Y_stream) - usX2Y_audio_stream_free(usX2Y_stream); + struct snd_usx2y_substream **usx2y_stream = pcm->private_data; + if (usx2y_stream) + usx2y_audio_stream_free(usx2y_stream); }
-static int usX2Y_audio_stream_new(struct snd_card *card, int playback_endpoint, int capture_endpoint) +static int usx2y_audio_stream_new(struct snd_card *card, int playback_endpoint, int capture_endpoint) { struct snd_pcm *pcm; int err, i; - struct snd_usX2Y_substream **usX2Y_substream = - usX2Y(card)->subs + 2 * usX2Y(card)->pcm_devs; + struct snd_usx2y_substream **usx2y_substream = + usx2y(card)->subs + 2 * usx2y(card)->pcm_devs;
for (i = playback_endpoint ? SNDRV_PCM_STREAM_PLAYBACK : SNDRV_PCM_STREAM_CAPTURE; i <= SNDRV_PCM_STREAM_CAPTURE; ++i) { - usX2Y_substream[i] = kzalloc(sizeof(struct snd_usX2Y_substream), GFP_KERNEL); - if (!usX2Y_substream[i]) + usx2y_substream[i] = kzalloc(sizeof(struct snd_usx2y_substream), GFP_KERNEL); + if (!usx2y_substream[i]) return -ENOMEM;
- usX2Y_substream[i]->usX2Y = usX2Y(card); + usx2y_substream[i]->usx2y = usx2y(card); }
if (playback_endpoint) - usX2Y_substream[SNDRV_PCM_STREAM_PLAYBACK]->endpoint = playback_endpoint; - usX2Y_substream[SNDRV_PCM_STREAM_CAPTURE]->endpoint = capture_endpoint; + usx2y_substream[SNDRV_PCM_STREAM_PLAYBACK]->endpoint = playback_endpoint; + usx2y_substream[SNDRV_PCM_STREAM_CAPTURE]->endpoint = capture_endpoint;
- err = snd_pcm_new(card, NAME_ALLCAPS" Audio", usX2Y(card)->pcm_devs, + err = snd_pcm_new(card, NAME_ALLCAPS" Audio", usx2y(card)->pcm_devs, playback_endpoint ? 1 : 0, 1, &pcm); if (err < 0) { - usX2Y_audio_stream_free(usX2Y_substream); + usx2y_audio_stream_free(usx2y_substream); return err; }
if (playback_endpoint) - snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_usX2Y_pcm_ops); - snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_usX2Y_pcm_ops); + snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_usx2y_pcm_ops); + snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_usx2y_pcm_ops);
- pcm->private_data = usX2Y_substream; - pcm->private_free = snd_usX2Y_pcm_private_free; + pcm->private_data = usx2y_substream; + pcm->private_free = snd_usx2y_pcm_private_free; pcm->info_flags = 0;
- sprintf(pcm->name, NAME_ALLCAPS" Audio #%d", usX2Y(card)->pcm_devs); + sprintf(pcm->name, NAME_ALLCAPS" Audio #%d", usx2y(card)->pcm_devs);
if (playback_endpoint) { snd_pcm_set_managed_buffer(pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream, @@ -972,7 +972,7 @@ static int usX2Y_audio_stream_new(struct snd_card *card, int playback_endpoint, SNDRV_DMA_TYPE_CONTINUOUS, NULL, 64*1024, 128*1024); - usX2Y(card)->pcm_devs++; + usx2y(card)->pcm_devs++;
return 0; } @@ -980,18 +980,18 @@ static int usX2Y_audio_stream_new(struct snd_card *card, int playback_endpoint, /* * create a chip instance and set its names. */ -int usX2Y_audio_create(struct snd_card *card) +int usx2y_audio_create(struct snd_card *card) { int err = 0; - INIT_LIST_HEAD(&usX2Y(card)->pcm_list); + INIT_LIST_HEAD(&usx2y(card)->pcm_list);
- if (0 > (err = usX2Y_audio_stream_new(card, 0xA, 0x8))) + if (0 > (err = usx2y_audio_stream_new(card, 0xA, 0x8))) return err; - if (le16_to_cpu(usX2Y(card)->dev->descriptor.idProduct) == USB_ID_US428) - if (0 > (err = usX2Y_audio_stream_new(card, 0, 0xA))) + if (le16_to_cpu(usx2y(card)->dev->descriptor.idProduct) == USB_ID_US428) + if (0 > (err = usx2y_audio_stream_new(card, 0, 0xA))) return err; - if (le16_to_cpu(usX2Y(card)->dev->descriptor.idProduct) != USB_ID_US122) - err = usX2Y_rate_set(usX2Y(card), 44100); // Lets us428 recognize output-volume settings, disturbs us122. + if (le16_to_cpu(usx2y(card)->dev->descriptor.idProduct) != USB_ID_US122) + err = usx2y_rate_set(usx2y(card), 44100); // Lets us428 recognize output-volume settings, disturbs us122. return err; } diff --git a/sound/usb/usx2y/usx2yhwdeppcm.c b/sound/usb/usx2y/usx2yhwdeppcm.c index 8253669c6a7d..399470e51c41 100644 --- a/sound/usb/usx2y/usx2yhwdeppcm.c +++ b/sound/usb/usx2y/usx2yhwdeppcm.c @@ -47,17 +47,17 @@ #include <sound/hwdep.h>
-static int usX2Y_usbpcm_urb_capt_retire(struct snd_usX2Y_substream *subs) +static int usx2y_usbpcm_urb_capt_retire(struct snd_usx2y_substream *subs) { struct urb *urb = subs->completed_urb; struct snd_pcm_runtime *runtime = subs->pcm_substream->runtime; int i, lens = 0, hwptr_done = subs->hwptr_done; - struct usX2Ydev *usX2Y = subs->usX2Y; - if (0 > usX2Y->hwdep_pcm_shm->capture_iso_start) { //FIXME - int head = usX2Y->hwdep_pcm_shm->captured_iso_head + 1; - if (head >= ARRAY_SIZE(usX2Y->hwdep_pcm_shm->captured_iso)) + struct usx2ydev *usx2y = subs->usx2y; + if (0 > usx2y->hwdep_pcm_shm->capture_iso_start) { //FIXME + int head = usx2y->hwdep_pcm_shm->captured_iso_head + 1; + if (head >= ARRAY_SIZE(usx2y->hwdep_pcm_shm->captured_iso)) head = 0; - usX2Y->hwdep_pcm_shm->capture_iso_start = head; + usx2y->hwdep_pcm_shm->capture_iso_start = head; snd_printdd("cap start %i\n", head); } for (i = 0; i < nr_of_packs(); i++) { @@ -65,7 +65,7 @@ static int usX2Y_usbpcm_urb_capt_retire(struct snd_usX2Y_substream *subs) snd_printk(KERN_ERR "active frame status %i. Most probably some hardware problem.\n", urb->iso_frame_desc[i].status); return urb->iso_frame_desc[i].status; } - lens += urb->iso_frame_desc[i].actual_length / usX2Y->stride; + lens += urb->iso_frame_desc[i].actual_length / usx2y->stride; } if ((hwptr_done += lens) >= runtime->buffer_size) hwptr_done -= runtime->buffer_size; @@ -79,10 +79,10 @@ static int usX2Y_usbpcm_urb_capt_retire(struct snd_usX2Y_substream *subs) return 0; }
-static inline int usX2Y_iso_frames_per_buffer(struct snd_pcm_runtime *runtime, - struct usX2Ydev * usX2Y) +static inline int usx2y_iso_frames_per_buffer(struct snd_pcm_runtime *runtime, + struct usx2ydev * usx2y) { - return (runtime->buffer_size * 1000) / usX2Y->rate + 1; //FIXME: so far only correct period_size == 2^x ? + return (runtime->buffer_size * 1000) / usx2y->rate + 1; //FIXME: so far only correct period_size == 2^x ? }
/* @@ -95,17 +95,17 @@ static inline int usX2Y_iso_frames_per_buffer(struct snd_pcm_runtime *runtime, * it directly from the buffer. thus the data is once copied to * a temporary buffer and urb points to that. */ -static int usX2Y_hwdep_urb_play_prepare(struct snd_usX2Y_substream *subs, +static int usx2y_hwdep_urb_play_prepare(struct snd_usx2y_substream *subs, struct urb *urb) { int count, counts, pack; - struct usX2Ydev *usX2Y = subs->usX2Y; - struct snd_usX2Y_hwdep_pcm_shm *shm = usX2Y->hwdep_pcm_shm; + struct usx2ydev *usx2y = subs->usx2y; + struct snd_usx2y_hwdep_pcm_shm *shm = usx2y->hwdep_pcm_shm; struct snd_pcm_runtime *runtime = subs->pcm_substream->runtime;
if (0 > shm->playback_iso_start) { shm->playback_iso_start = shm->captured_iso_head - - usX2Y_iso_frames_per_buffer(runtime, usX2Y); + usx2y_iso_frames_per_buffer(runtime, usx2y); if (0 > shm->playback_iso_start) shm->playback_iso_start += ARRAY_SIZE(shm->captured_iso); shm->playback_iso_head = shm->playback_iso_start; @@ -114,7 +114,7 @@ static int usX2Y_hwdep_urb_play_prepare(struct snd_usX2Y_substream *subs, count = 0; for (pack = 0; pack < nr_of_packs(); pack++) { /* calculate the size of a packet */ - counts = shm->captured_iso[shm->playback_iso_head].length / usX2Y->stride; + counts = shm->captured_iso[shm->playback_iso_head].length / usx2y->stride; if (counts < 43 || counts > 50) { snd_printk(KERN_ERR "should not be here with counts=%i\n", counts); return -EPIPE; @@ -122,26 +122,26 @@ static int usX2Y_hwdep_urb_play_prepare(struct snd_usX2Y_substream *subs, /* set up descriptor */ urb->iso_frame_desc[pack].offset = shm->captured_iso[shm->playback_iso_head].offset; urb->iso_frame_desc[pack].length = shm->captured_iso[shm->playback_iso_head].length; - if (atomic_read(&subs->state) != state_RUNNING) + if (atomic_read(&subs->state) != STATE_RUNNING) memset((char *)urb->transfer_buffer + urb->iso_frame_desc[pack].offset, 0, urb->iso_frame_desc[pack].length); if (++shm->playback_iso_head >= ARRAY_SIZE(shm->captured_iso)) shm->playback_iso_head = 0; count += counts; } - urb->transfer_buffer_length = count * usX2Y->stride; + urb->transfer_buffer_length = count * usx2y->stride; return 0; }
-static inline void usX2Y_usbpcm_urb_capt_iso_advance(struct snd_usX2Y_substream *subs, +static inline void usx2y_usbpcm_urb_capt_iso_advance(struct snd_usx2y_substream *subs, struct urb *urb) { int pack; for (pack = 0; pack < nr_of_packs(); ++pack) { struct usb_iso_packet_descriptor *desc = urb->iso_frame_desc + pack; if (NULL != subs) { - struct snd_usX2Y_hwdep_pcm_shm *shm = subs->usX2Y->hwdep_pcm_shm; + struct snd_usx2y_hwdep_pcm_shm *shm = subs->usx2y->hwdep_pcm_shm; int head = shm->captured_iso_head + 1; if (head >= ARRAY_SIZE(shm->captured_iso)) head = 0; @@ -157,9 +157,9 @@ static inline void usX2Y_usbpcm_urb_capt_iso_advance(struct snd_usX2Y_substream } }
-static inline int usX2Y_usbpcm_usbframe_complete(struct snd_usX2Y_substream *capsubs, - struct snd_usX2Y_substream *capsubs2, - struct snd_usX2Y_substream *playbacksubs, +static inline int usx2y_usbpcm_usbframe_complete(struct snd_usx2y_substream *capsubs, + struct snd_usx2y_substream *capsubs2, + struct snd_usx2y_substream *playbacksubs, int frame) { int err, state; @@ -167,25 +167,25 @@ static inline int usX2Y_usbpcm_usbframe_complete(struct snd_usX2Y_substream *cap
state = atomic_read(&playbacksubs->state); if (NULL != urb) { - if (state == state_RUNNING) - usX2Y_urb_play_retire(playbacksubs, urb); - else if (state >= state_PRERUNNING) + if (state == STATE_RUNNING) + usx2y_urb_play_retire(playbacksubs, urb); + else if (state >= STATE_PRERUNNING) atomic_inc(&playbacksubs->state); } else { switch (state) { - case state_STARTING1: + case STATE_STARTING1: urb = playbacksubs->urb[0]; atomic_inc(&playbacksubs->state); break; - case state_STARTING2: + case STATE_STARTING2: urb = playbacksubs->urb[1]; atomic_inc(&playbacksubs->state); break; } } if (urb) { - if ((err = usX2Y_hwdep_urb_play_prepare(playbacksubs, urb)) || - (err = usX2Y_urb_submit(playbacksubs, urb, frame))) { + if ((err = usx2y_hwdep_urb_play_prepare(playbacksubs, urb)) || + (err = usx2y_urb_submit(playbacksubs, urb, frame))) { return err; } } @@ -193,19 +193,19 @@ static inline int usX2Y_usbpcm_usbframe_complete(struct snd_usX2Y_substream *cap playbacksubs->completed_urb = NULL;
state = atomic_read(&capsubs->state); - if (state >= state_PREPARED) { - if (state == state_RUNNING) { - if ((err = usX2Y_usbpcm_urb_capt_retire(capsubs))) + if (state >= STATE_PREPARED) { + if (state == STATE_RUNNING) { + if ((err = usx2y_usbpcm_urb_capt_retire(capsubs))) return err; - } else if (state >= state_PRERUNNING) + } else if (state >= STATE_PRERUNNING) atomic_inc(&capsubs->state); - usX2Y_usbpcm_urb_capt_iso_advance(capsubs, capsubs->completed_urb); + usx2y_usbpcm_urb_capt_iso_advance(capsubs, capsubs->completed_urb); if (NULL != capsubs2) - usX2Y_usbpcm_urb_capt_iso_advance(NULL, capsubs2->completed_urb); - if ((err = usX2Y_urb_submit(capsubs, capsubs->completed_urb, frame))) + usx2y_usbpcm_urb_capt_iso_advance(NULL, capsubs2->completed_urb); + if ((err = usx2y_urb_submit(capsubs, capsubs->completed_urb, frame))) return err; if (NULL != capsubs2) - if ((err = usX2Y_urb_submit(capsubs2, capsubs2->completed_urb, frame))) + if ((err = usx2y_urb_submit(capsubs2, capsubs2->completed_urb, frame))) return err; } capsubs->completed_urb = NULL; @@ -215,42 +215,42 @@ static inline int usX2Y_usbpcm_usbframe_complete(struct snd_usX2Y_substream *cap }
-static void i_usX2Y_usbpcm_urb_complete(struct urb *urb) +static void i_usx2y_usbpcm_urb_complete(struct urb *urb) { - struct snd_usX2Y_substream *subs = urb->context; - struct usX2Ydev *usX2Y = subs->usX2Y; - struct snd_usX2Y_substream *capsubs, *capsubs2, *playbacksubs; + struct snd_usx2y_substream *subs = urb->context; + struct usx2ydev *usx2y = subs->usx2y; + struct snd_usx2y_substream *capsubs, *capsubs2, *playbacksubs;
- if (unlikely(atomic_read(&subs->state) < state_PREPARED)) { + if (unlikely(atomic_read(&subs->state) < STATE_PREPARED)) { snd_printdd("hcd_frame=%i ep=%i%s status=%i start_frame=%i\n", - usb_get_current_frame_number(usX2Y->dev), + usb_get_current_frame_number(usx2y->dev), subs->endpoint, usb_pipein(urb->pipe) ? "in" : "out", urb->status, urb->start_frame); return; } if (unlikely(urb->status)) { - usX2Y_error_urb_status(usX2Y, subs, urb); + usx2y_error_urb_status(usx2y, subs, urb); return; }
subs->completed_urb = urb; - capsubs = usX2Y->subs[SNDRV_PCM_STREAM_CAPTURE]; - capsubs2 = usX2Y->subs[SNDRV_PCM_STREAM_CAPTURE + 2]; - playbacksubs = usX2Y->subs[SNDRV_PCM_STREAM_PLAYBACK]; - if (capsubs->completed_urb && atomic_read(&capsubs->state) >= state_PREPARED && + capsubs = usx2y->subs[SNDRV_PCM_STREAM_CAPTURE]; + capsubs2 = usx2y->subs[SNDRV_PCM_STREAM_CAPTURE + 2]; + playbacksubs = usx2y->subs[SNDRV_PCM_STREAM_PLAYBACK]; + if (capsubs->completed_urb && atomic_read(&capsubs->state) >= STATE_PREPARED && (NULL == capsubs2 || capsubs2->completed_urb) && - (playbacksubs->completed_urb || atomic_read(&playbacksubs->state) < state_PREPARED)) { - if (!usX2Y_usbpcm_usbframe_complete(capsubs, capsubs2, playbacksubs, urb->start_frame)) - usX2Y->wait_iso_frame += nr_of_packs(); + (playbacksubs->completed_urb || atomic_read(&playbacksubs->state) < STATE_PREPARED)) { + if (!usx2y_usbpcm_usbframe_complete(capsubs, capsubs2, playbacksubs, urb->start_frame)) + usx2y->wait_iso_frame += nr_of_packs(); else { snd_printdd("\n"); - usX2Y_clients_stop(usX2Y); + usx2y_clients_stop(usx2y); } } }
-static void usX2Y_hwdep_urb_release(struct urb **urb) +static void usx2y_hwdep_urb_release(struct urb **urb) { usb_kill_urb(*urb); usb_free_urb(*urb); @@ -260,49 +260,49 @@ static void usX2Y_hwdep_urb_release(struct urb **urb) /* * release a substream */ -static void usX2Y_usbpcm_urbs_release(struct snd_usX2Y_substream *subs) +static void usx2y_usbpcm_urbs_release(struct snd_usx2y_substream *subs) { int i; - snd_printdd("snd_usX2Y_urbs_release() %i\n", subs->endpoint); + snd_printdd("snd_usx2y_urbs_release() %i\n", subs->endpoint); for (i = 0; i < NRURBS; i++) - usX2Y_hwdep_urb_release(subs->urb + i); + usx2y_hwdep_urb_release(subs->urb + i); }
-static void usX2Y_usbpcm_subs_startup_finish(struct usX2Ydev * usX2Y) +static void usx2y_usbpcm_subs_startup_finish(struct usx2ydev * usx2y) { - usX2Y_urbs_set_complete(usX2Y, i_usX2Y_usbpcm_urb_complete); - usX2Y->prepare_subs = NULL; + usx2y_urbs_set_complete(usx2y, i_usx2y_usbpcm_urb_complete); + usx2y->prepare_subs = NULL; }
-static void i_usX2Y_usbpcm_subs_startup(struct urb *urb) +static void i_usx2y_usbpcm_subs_startup(struct urb *urb) { - struct snd_usX2Y_substream *subs = urb->context; - struct usX2Ydev *usX2Y = subs->usX2Y; - struct snd_usX2Y_substream *prepare_subs = usX2Y->prepare_subs; + struct snd_usx2y_substream *subs = urb->context; + struct usx2ydev *usx2y = subs->usx2y; + struct snd_usx2y_substream *prepare_subs = usx2y->prepare_subs; if (NULL != prepare_subs && urb->start_frame == prepare_subs->urb[0]->start_frame) { atomic_inc(&prepare_subs->state); - if (prepare_subs == usX2Y->subs[SNDRV_PCM_STREAM_CAPTURE]) { - struct snd_usX2Y_substream *cap_subs2 = usX2Y->subs[SNDRV_PCM_STREAM_CAPTURE + 2]; + if (prepare_subs == usx2y->subs[SNDRV_PCM_STREAM_CAPTURE]) { + struct snd_usx2y_substream *cap_subs2 = usx2y->subs[SNDRV_PCM_STREAM_CAPTURE + 2]; if (cap_subs2 != NULL) atomic_inc(&cap_subs2->state); } - usX2Y_usbpcm_subs_startup_finish(usX2Y); - wake_up(&usX2Y->prepare_wait_queue); + usx2y_usbpcm_subs_startup_finish(usx2y); + wake_up(&usx2y->prepare_wait_queue); }
- i_usX2Y_usbpcm_urb_complete(urb); + i_usx2y_usbpcm_urb_complete(urb); }
/* * initialize a substream's urbs */ -static int usX2Y_usbpcm_urbs_allocate(struct snd_usX2Y_substream *subs) +static int usx2y_usbpcm_urbs_allocate(struct snd_usx2y_substream *subs) { int i; unsigned int pipe; - int is_playback = subs == subs->usX2Y->subs[SNDRV_PCM_STREAM_PLAYBACK]; - struct usb_device *dev = subs->usX2Y->dev; + int is_playback = subs == subs->usx2y->subs[SNDRV_PCM_STREAM_PLAYBACK]; + struct usb_device *dev = subs->usx2y->dev;
pipe = is_playback ? usb_sndisocpipe(dev, subs->endpoint) : usb_rcvisocpipe(dev, subs->endpoint); @@ -319,21 +319,21 @@ static int usX2Y_usbpcm_urbs_allocate(struct snd_usX2Y_substream *subs) } *purb = usb_alloc_urb(nr_of_packs(), GFP_KERNEL); if (NULL == *purb) { - usX2Y_usbpcm_urbs_release(subs); + usx2y_usbpcm_urbs_release(subs); return -ENOMEM; } (*purb)->transfer_buffer = is_playback ? - subs->usX2Y->hwdep_pcm_shm->playback : ( + subs->usx2y->hwdep_pcm_shm->playback : ( subs->endpoint == 0x8 ? - subs->usX2Y->hwdep_pcm_shm->capture0x8 : - subs->usX2Y->hwdep_pcm_shm->capture0xA); + subs->usx2y->hwdep_pcm_shm->capture0x8 : + subs->usx2y->hwdep_pcm_shm->capture0xA);
(*purb)->dev = dev; (*purb)->pipe = pipe; (*purb)->number_of_packets = nr_of_packs(); (*purb)->context = subs; (*purb)->interval = 1; - (*purb)->complete = i_usX2Y_usbpcm_subs_startup; + (*purb)->complete = i_usx2y_usbpcm_subs_startup; } return 0; } @@ -341,91 +341,91 @@ static int usX2Y_usbpcm_urbs_allocate(struct snd_usX2Y_substream *subs) /* * free the buffer */ -static int snd_usX2Y_usbpcm_hw_free(struct snd_pcm_substream *substream) +static int snd_usx2y_usbpcm_hw_free(struct snd_pcm_substream *substream) { struct snd_pcm_runtime *runtime = substream->runtime; - struct snd_usX2Y_substream *subs = runtime->private_data, - *cap_subs2 = subs->usX2Y->subs[SNDRV_PCM_STREAM_CAPTURE + 2]; - mutex_lock(&subs->usX2Y->pcm_mutex); - snd_printdd("snd_usX2Y_usbpcm_hw_free(%p)\n", substream); + struct snd_usx2y_substream *subs = runtime->private_data, + *cap_subs2 = subs->usx2y->subs[SNDRV_PCM_STREAM_CAPTURE + 2]; + mutex_lock(&subs->usx2y->pcm_mutex); + snd_printdd("snd_usx2y_usbpcm_hw_free(%p)\n", substream);
if (SNDRV_PCM_STREAM_PLAYBACK == substream->stream) { - struct snd_usX2Y_substream *cap_subs = subs->usX2Y->subs[SNDRV_PCM_STREAM_CAPTURE]; - atomic_set(&subs->state, state_STOPPED); - usX2Y_usbpcm_urbs_release(subs); + struct snd_usx2y_substream *cap_subs = subs->usx2y->subs[SNDRV_PCM_STREAM_CAPTURE]; + atomic_set(&subs->state, STATE_STOPPED); + usx2y_usbpcm_urbs_release(subs); if (!cap_subs->pcm_substream || !cap_subs->pcm_substream->runtime || !cap_subs->pcm_substream->runtime->status || cap_subs->pcm_substream->runtime->status->state < SNDRV_PCM_STATE_PREPARED) { - atomic_set(&cap_subs->state, state_STOPPED); + atomic_set(&cap_subs->state, STATE_STOPPED); if (NULL != cap_subs2) - atomic_set(&cap_subs2->state, state_STOPPED); - usX2Y_usbpcm_urbs_release(cap_subs); + atomic_set(&cap_subs2->state, STATE_STOPPED); + usx2y_usbpcm_urbs_release(cap_subs); if (NULL != cap_subs2) - usX2Y_usbpcm_urbs_release(cap_subs2); + usx2y_usbpcm_urbs_release(cap_subs2); } } else { - struct snd_usX2Y_substream *playback_subs = subs->usX2Y->subs[SNDRV_PCM_STREAM_PLAYBACK]; - if (atomic_read(&playback_subs->state) < state_PREPARED) { - atomic_set(&subs->state, state_STOPPED); + struct snd_usx2y_substream *playback_subs = subs->usx2y->subs[SNDRV_PCM_STREAM_PLAYBACK]; + if (atomic_read(&playback_subs->state) < STATE_PREPARED) { + atomic_set(&subs->state, STATE_STOPPED); if (NULL != cap_subs2) - atomic_set(&cap_subs2->state, state_STOPPED); - usX2Y_usbpcm_urbs_release(subs); + atomic_set(&cap_subs2->state, STATE_STOPPED); + usx2y_usbpcm_urbs_release(subs); if (NULL != cap_subs2) - usX2Y_usbpcm_urbs_release(cap_subs2); + usx2y_usbpcm_urbs_release(cap_subs2); } } - mutex_unlock(&subs->usX2Y->pcm_mutex); + mutex_unlock(&subs->usx2y->pcm_mutex); return 0; }
-static void usX2Y_usbpcm_subs_startup(struct snd_usX2Y_substream *subs) +static void usx2y_usbpcm_subs_startup(struct snd_usx2y_substream *subs) { - struct usX2Ydev * usX2Y = subs->usX2Y; - usX2Y->prepare_subs = subs; + struct usx2ydev * usx2y = subs->usx2y; + usx2y->prepare_subs = subs; subs->urb[0]->start_frame = -1; - smp_wmb(); // Make sure above modifications are seen by i_usX2Y_subs_startup() - usX2Y_urbs_set_complete(usX2Y, i_usX2Y_usbpcm_subs_startup); + smp_wmb(); // Make sure above modifications are seen by i_usx2y_subs_startup() + usx2y_urbs_set_complete(usx2y, i_usx2y_usbpcm_subs_startup); }
-static int usX2Y_usbpcm_urbs_start(struct snd_usX2Y_substream *subs) +static int usx2y_usbpcm_urbs_start(struct snd_usx2y_substream *subs) { int p, u, err, stream = subs->pcm_substream->stream; - struct usX2Ydev *usX2Y = subs->usX2Y; + struct usx2ydev *usx2y = subs->usx2y;
if (SNDRV_PCM_STREAM_CAPTURE == stream) { - usX2Y->hwdep_pcm_shm->captured_iso_head = -1; - usX2Y->hwdep_pcm_shm->captured_iso_frames = 0; + usx2y->hwdep_pcm_shm->captured_iso_head = -1; + usx2y->hwdep_pcm_shm->captured_iso_frames = 0; }
for (p = 0; 3 >= (stream + p); p += 2) { - struct snd_usX2Y_substream *subs = usX2Y->subs[stream + p]; + struct snd_usx2y_substream *subs = usx2y->subs[stream + p]; if (subs != NULL) { - if ((err = usX2Y_usbpcm_urbs_allocate(subs)) < 0) + if ((err = usx2y_usbpcm_urbs_allocate(subs)) < 0) return err; subs->completed_urb = NULL; } }
for (p = 0; p < 4; p++) { - struct snd_usX2Y_substream *subs = usX2Y->subs[p]; - if (subs != NULL && atomic_read(&subs->state) >= state_PREPARED) + struct snd_usx2y_substream *subs = usx2y->subs[p]; + if (subs != NULL && atomic_read(&subs->state) >= STATE_PREPARED) goto start; }
start: - usX2Y_usbpcm_subs_startup(subs); + usx2y_usbpcm_subs_startup(subs); for (u = 0; u < NRURBS; u++) { for (p = 0; 3 >= (stream + p); p += 2) { - struct snd_usX2Y_substream *subs = usX2Y->subs[stream + p]; + struct snd_usx2y_substream *subs = usx2y->subs[stream + p]; if (subs != NULL) { struct urb *urb = subs->urb[u]; if (usb_pipein(urb->pipe)) { unsigned long pack; if (0 == u) - atomic_set(&subs->state, state_STARTING3); - urb->dev = usX2Y->dev; + atomic_set(&subs->state, STATE_STARTING3); + urb->dev = usx2y->dev; for (pack = 0; pack < nr_of_packs(); pack++) { urb->iso_frame_desc[pack].offset = subs->maxpacksize * (pack + u * nr_of_packs()); urb->iso_frame_desc[pack].length = subs->maxpacksize; @@ -438,25 +438,25 @@ static int usX2Y_usbpcm_urbs_start(struct snd_usX2Y_substream *subs) } else { snd_printdd("%i\n", urb->start_frame); if (u == 0) - usX2Y->wait_iso_frame = urb->start_frame; + usx2y->wait_iso_frame = urb->start_frame; } urb->transfer_flags = 0; } else { - atomic_set(&subs->state, state_STARTING1); + atomic_set(&subs->state, STATE_STARTING1); break; } } } } err = 0; - wait_event(usX2Y->prepare_wait_queue, NULL == usX2Y->prepare_subs); - if (atomic_read(&subs->state) != state_PREPARED) + wait_event(usx2y->prepare_wait_queue, NULL == usx2y->prepare_subs); + if (atomic_read(&subs->state) != STATE_PREPARED) err = -EPIPE; cleanup: if (err) { - usX2Y_subs_startup_finish(usX2Y); // Call it now - usX2Y_clients_stop(usX2Y); // something is completely wroong > stop evrything + usx2y_subs_startup_finish(usx2y); // Call it now + usx2y_clients_stop(usx2y); // something is completely wroong > stop evrything } return err; } @@ -466,69 +466,69 @@ static int usX2Y_usbpcm_urbs_start(struct snd_usX2Y_substream *subs) * * set format and initialize urbs */ -static int snd_usX2Y_usbpcm_prepare(struct snd_pcm_substream *substream) +static int snd_usx2y_usbpcm_prepare(struct snd_pcm_substream *substream) { struct snd_pcm_runtime *runtime = substream->runtime; - struct snd_usX2Y_substream *subs = runtime->private_data; - struct usX2Ydev *usX2Y = subs->usX2Y; - struct snd_usX2Y_substream *capsubs = subs->usX2Y->subs[SNDRV_PCM_STREAM_CAPTURE]; + struct snd_usx2y_substream *subs = runtime->private_data; + struct usx2ydev *usx2y = subs->usx2y; + struct snd_usx2y_substream *capsubs = subs->usx2y->subs[SNDRV_PCM_STREAM_CAPTURE]; int err = 0; - snd_printdd("snd_usX2Y_pcm_prepare(%p)\n", substream); + snd_printdd("snd_usx2y_pcm_prepare(%p)\n", substream);
- if (NULL == usX2Y->hwdep_pcm_shm) { - usX2Y->hwdep_pcm_shm = alloc_pages_exact(sizeof(struct snd_usX2Y_hwdep_pcm_shm), + if (NULL == usx2y->hwdep_pcm_shm) { + usx2y->hwdep_pcm_shm = alloc_pages_exact(sizeof(struct snd_usx2y_hwdep_pcm_shm), GFP_KERNEL); - if (!usX2Y->hwdep_pcm_shm) + if (!usx2y->hwdep_pcm_shm) return -ENOMEM; - memset(usX2Y->hwdep_pcm_shm, 0, sizeof(struct snd_usX2Y_hwdep_pcm_shm)); + memset(usx2y->hwdep_pcm_shm, 0, sizeof(struct snd_usx2y_hwdep_pcm_shm)); }
- mutex_lock(&usX2Y->pcm_mutex); - usX2Y_subs_prepare(subs); + mutex_lock(&usx2y->pcm_mutex); + usx2y_subs_prepare(subs); // Start hardware streams // SyncStream first.... - if (atomic_read(&capsubs->state) < state_PREPARED) { - if (usX2Y->format != runtime->format) - if ((err = usX2Y_format_set(usX2Y, runtime->format)) < 0) + if (atomic_read(&capsubs->state) < STATE_PREPARED) { + if (usx2y->format != runtime->format) + if ((err = usx2y_format_set(usx2y, runtime->format)) < 0) goto up_prepare_mutex; - if (usX2Y->rate != runtime->rate) - if ((err = usX2Y_rate_set(usX2Y, runtime->rate)) < 0) + if (usx2y->rate != runtime->rate) + if ((err = usx2y_rate_set(usx2y, runtime->rate)) < 0) goto up_prepare_mutex; snd_printdd("starting capture pipe for %s\n", subs == capsubs ? "self" : "playpipe"); - if (0 > (err = usX2Y_usbpcm_urbs_start(capsubs))) + if (0 > (err = usx2y_usbpcm_urbs_start(capsubs))) goto up_prepare_mutex; }
if (subs != capsubs) { - usX2Y->hwdep_pcm_shm->playback_iso_start = -1; - if (atomic_read(&subs->state) < state_PREPARED) { - while (usX2Y_iso_frames_per_buffer(runtime, usX2Y) > - usX2Y->hwdep_pcm_shm->captured_iso_frames) { + usx2y->hwdep_pcm_shm->playback_iso_start = -1; + if (atomic_read(&subs->state) < STATE_PREPARED) { + while (usx2y_iso_frames_per_buffer(runtime, usx2y) > + usx2y->hwdep_pcm_shm->captured_iso_frames) { snd_printdd("Wait: iso_frames_per_buffer=%i," "captured_iso_frames=%i\n", - usX2Y_iso_frames_per_buffer(runtime, usX2Y), - usX2Y->hwdep_pcm_shm->captured_iso_frames); + usx2y_iso_frames_per_buffer(runtime, usx2y), + usx2y->hwdep_pcm_shm->captured_iso_frames); if (msleep_interruptible(10)) { err = -ERESTARTSYS; goto up_prepare_mutex; } } - if (0 > (err = usX2Y_usbpcm_urbs_start(subs))) + if (0 > (err = usx2y_usbpcm_urbs_start(subs))) goto up_prepare_mutex; } snd_printdd("Ready: iso_frames_per_buffer=%i,captured_iso_frames=%i\n", - usX2Y_iso_frames_per_buffer(runtime, usX2Y), - usX2Y->hwdep_pcm_shm->captured_iso_frames); + usx2y_iso_frames_per_buffer(runtime, usx2y), + usx2y->hwdep_pcm_shm->captured_iso_frames); } else - usX2Y->hwdep_pcm_shm->capture_iso_start = -1; + usx2y->hwdep_pcm_shm->capture_iso_start = -1;
up_prepare_mutex: - mutex_unlock(&usX2Y->pcm_mutex); + mutex_unlock(&usx2y->pcm_mutex); return err; }
-static const struct snd_pcm_hardware snd_usX2Y_4c = +static const struct snd_pcm_hardware snd_usx2y_4c = { .info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_BLOCK_TRANSFER | @@ -549,17 +549,17 @@ static const struct snd_pcm_hardware snd_usX2Y_4c =
-static int snd_usX2Y_usbpcm_open(struct snd_pcm_substream *substream) +static int snd_usx2y_usbpcm_open(struct snd_pcm_substream *substream) { - struct snd_usX2Y_substream *subs = ((struct snd_usX2Y_substream **) + struct snd_usx2y_substream *subs = ((struct snd_usx2y_substream **) snd_pcm_substream_chip(substream))[substream->stream]; struct snd_pcm_runtime *runtime = substream->runtime;
- if (!(subs->usX2Y->chip_status & USX2Y_STAT_CHIP_MMAP_PCM_URBS)) + if (!(subs->usx2y->chip_status & USX2Y_STAT_CHIP_MMAP_PCM_URBS)) return -EBUSY;
- runtime->hw = SNDRV_PCM_STREAM_PLAYBACK == substream->stream ? snd_usX2Y_2c : - (subs->usX2Y->subs[3] ? snd_usX2Y_4c : snd_usX2Y_2c); + runtime->hw = SNDRV_PCM_STREAM_PLAYBACK == substream->stream ? snd_usx2y_2c : + (subs->usx2y->subs[3] ? snd_usx2y_4c : snd_usx2y_2c); runtime->private_data = subs; subs->pcm_substream = substream; snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_PERIOD_TIME, 1000, 200000); @@ -567,35 +567,35 @@ static int snd_usX2Y_usbpcm_open(struct snd_pcm_substream *substream) }
-static int snd_usX2Y_usbpcm_close(struct snd_pcm_substream *substream) +static int snd_usx2y_usbpcm_close(struct snd_pcm_substream *substream) { struct snd_pcm_runtime *runtime = substream->runtime; - struct snd_usX2Y_substream *subs = runtime->private_data; + struct snd_usx2y_substream *subs = runtime->private_data;
subs->pcm_substream = NULL; return 0; }
-static const struct snd_pcm_ops snd_usX2Y_usbpcm_ops = +static const struct snd_pcm_ops snd_usx2y_usbpcm_ops = { - .open = snd_usX2Y_usbpcm_open, - .close = snd_usX2Y_usbpcm_close, - .hw_params = snd_usX2Y_pcm_hw_params, - .hw_free = snd_usX2Y_usbpcm_hw_free, - .prepare = snd_usX2Y_usbpcm_prepare, - .trigger = snd_usX2Y_pcm_trigger, - .pointer = snd_usX2Y_pcm_pointer, + .open = snd_usx2y_usbpcm_open, + .close = snd_usx2y_usbpcm_close, + .hw_params = snd_usx2y_pcm_hw_params, + .hw_free = snd_usx2y_usbpcm_hw_free, + .prepare = snd_usx2y_usbpcm_prepare, + .trigger = snd_usx2y_pcm_trigger, + .pointer = snd_usx2y_pcm_pointer, };
-static int usX2Y_pcms_busy_check(struct snd_card *card) +static int usx2y_pcms_busy_check(struct snd_card *card) { - struct usX2Ydev *dev = usX2Y(card); + struct usx2ydev *dev = usx2y(card); int i;
for (i = 0; i < dev->pcm_devs * 2; i++) { - struct snd_usX2Y_substream *subs = dev->subs[i]; + struct snd_usx2y_substream *subs = dev->subs[i]; if (subs && subs->pcm_substream && SUBSTREAM_BUSY(subs->pcm_substream)) return -EBUSY; @@ -603,102 +603,102 @@ static int usX2Y_pcms_busy_check(struct snd_card *card) return 0; }
-static int snd_usX2Y_hwdep_pcm_open(struct snd_hwdep *hw, struct file *file) +static int snd_usx2y_hwdep_pcm_open(struct snd_hwdep *hw, struct file *file) { struct snd_card *card = hw->card; int err;
- mutex_lock(&usX2Y(card)->pcm_mutex); - err = usX2Y_pcms_busy_check(card); + mutex_lock(&usx2y(card)->pcm_mutex); + err = usx2y_pcms_busy_check(card); if (!err) - usX2Y(card)->chip_status |= USX2Y_STAT_CHIP_MMAP_PCM_URBS; - mutex_unlock(&usX2Y(card)->pcm_mutex); + usx2y(card)->chip_status |= USX2Y_STAT_CHIP_MMAP_PCM_URBS; + mutex_unlock(&usx2y(card)->pcm_mutex); return err; }
-static int snd_usX2Y_hwdep_pcm_release(struct snd_hwdep *hw, struct file *file) +static int snd_usx2y_hwdep_pcm_release(struct snd_hwdep *hw, struct file *file) { struct snd_card *card = hw->card; int err;
- mutex_lock(&usX2Y(card)->pcm_mutex); - err = usX2Y_pcms_busy_check(card); + mutex_lock(&usx2y(card)->pcm_mutex); + err = usx2y_pcms_busy_check(card); if (!err) - usX2Y(hw->card)->chip_status &= ~USX2Y_STAT_CHIP_MMAP_PCM_URBS; - mutex_unlock(&usX2Y(card)->pcm_mutex); + usx2y(hw->card)->chip_status &= ~USX2Y_STAT_CHIP_MMAP_PCM_URBS; + mutex_unlock(&usx2y(card)->pcm_mutex); return err; }
-static void snd_usX2Y_hwdep_pcm_vm_open(struct vm_area_struct *area) +static void snd_usx2y_hwdep_pcm_vm_open(struct vm_area_struct *area) { }
-static void snd_usX2Y_hwdep_pcm_vm_close(struct vm_area_struct *area) +static void snd_usx2y_hwdep_pcm_vm_close(struct vm_area_struct *area) { }
-static vm_fault_t snd_usX2Y_hwdep_pcm_vm_fault(struct vm_fault *vmf) +static vm_fault_t snd_usx2y_hwdep_pcm_vm_fault(struct vm_fault *vmf) { unsigned long offset; void *vaddr;
offset = vmf->pgoff << PAGE_SHIFT; - vaddr = (char *)((struct usX2Ydev *)vmf->vma->vm_private_data)->hwdep_pcm_shm + offset; + vaddr = (char *)((struct usx2ydev *)vmf->vma->vm_private_data)->hwdep_pcm_shm + offset; vmf->page = virt_to_page(vaddr); get_page(vmf->page); return 0; }
-static const struct vm_operations_struct snd_usX2Y_hwdep_pcm_vm_ops = { - .open = snd_usX2Y_hwdep_pcm_vm_open, - .close = snd_usX2Y_hwdep_pcm_vm_close, - .fault = snd_usX2Y_hwdep_pcm_vm_fault, +static const struct vm_operations_struct snd_usx2y_hwdep_pcm_vm_ops = { + .open = snd_usx2y_hwdep_pcm_vm_open, + .close = snd_usx2y_hwdep_pcm_vm_close, + .fault = snd_usx2y_hwdep_pcm_vm_fault, };
-static int snd_usX2Y_hwdep_pcm_mmap(struct snd_hwdep * hw, struct file *filp, struct vm_area_struct *area) +static int snd_usx2y_hwdep_pcm_mmap(struct snd_hwdep * hw, struct file *filp, struct vm_area_struct *area) { unsigned long size = (unsigned long)(area->vm_end - area->vm_start); - struct usX2Ydev *usX2Y = hw->private_data; + struct usx2ydev *usx2y = hw->private_data;
- if (!(usX2Y->chip_status & USX2Y_STAT_CHIP_INIT)) + if (!(usx2y->chip_status & USX2Y_STAT_CHIP_INIT)) return -EBUSY;
/* if userspace tries to mmap beyond end of our buffer, fail */ - if (size > PAGE_ALIGN(sizeof(struct snd_usX2Y_hwdep_pcm_shm))) { - snd_printd("%lu > %lu\n", size, (unsigned long)sizeof(struct snd_usX2Y_hwdep_pcm_shm)); + if (size > PAGE_ALIGN(sizeof(struct snd_usx2y_hwdep_pcm_shm))) { + snd_printd("%lu > %lu\n", size, (unsigned long)sizeof(struct snd_usx2y_hwdep_pcm_shm)); return -EINVAL; }
- if (!usX2Y->hwdep_pcm_shm) { + if (!usx2y->hwdep_pcm_shm) { return -ENODEV; } - area->vm_ops = &snd_usX2Y_hwdep_pcm_vm_ops; + area->vm_ops = &snd_usx2y_hwdep_pcm_vm_ops; area->vm_flags |= VM_DONTEXPAND | VM_DONTDUMP; area->vm_private_data = hw->private_data; return 0; }
-static void snd_usX2Y_hwdep_pcm_private_free(struct snd_hwdep *hwdep) +static void snd_usx2y_hwdep_pcm_private_free(struct snd_hwdep *hwdep) { - struct usX2Ydev *usX2Y = hwdep->private_data; - if (NULL != usX2Y->hwdep_pcm_shm) - free_pages_exact(usX2Y->hwdep_pcm_shm, sizeof(struct snd_usX2Y_hwdep_pcm_shm)); + struct usx2ydev *usx2y = hwdep->private_data; + if (NULL != usx2y->hwdep_pcm_shm) + free_pages_exact(usx2y->hwdep_pcm_shm, sizeof(struct snd_usx2y_hwdep_pcm_shm)); }
-int usX2Y_hwdep_pcm_new(struct snd_card *card) +int usx2y_hwdep_pcm_new(struct snd_card *card) { int err; struct snd_hwdep *hw; struct snd_pcm *pcm; - struct usb_device *dev = usX2Y(card)->dev; + struct usb_device *dev = usx2y(card)->dev; if (1 != nr_of_packs()) return 0;
@@ -706,11 +706,11 @@ int usX2Y_hwdep_pcm_new(struct snd_card *card) return err;
hw->iface = SNDRV_HWDEP_IFACE_USX2Y_PCM; - hw->private_data = usX2Y(card); - hw->private_free = snd_usX2Y_hwdep_pcm_private_free; - hw->ops.open = snd_usX2Y_hwdep_pcm_open; - hw->ops.release = snd_usX2Y_hwdep_pcm_release; - hw->ops.mmap = snd_usX2Y_hwdep_pcm_mmap; + hw->private_data = usx2y(card); + hw->private_free = snd_usx2y_hwdep_pcm_private_free; + hw->ops.open = snd_usx2y_hwdep_pcm_open; + hw->ops.release = snd_usx2y_hwdep_pcm_release; + hw->ops.mmap = snd_usx2y_hwdep_pcm_mmap; hw->exclusive = 1; sprintf(hw->name, "/dev/bus/usb/%03d/%03d/hwdeppcm", dev->bus->busnum, dev->devnum);
@@ -718,10 +718,10 @@ int usX2Y_hwdep_pcm_new(struct snd_card *card) if (err < 0) { return err; } - snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_usX2Y_usbpcm_ops); - snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_usX2Y_usbpcm_ops); + snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_usx2y_usbpcm_ops); + snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_usx2y_usbpcm_ops);
- pcm->private_data = usX2Y(card)->subs; + pcm->private_data = usx2y(card)->subs; pcm->info_flags = 0;
sprintf(pcm->name, NAME_ALLCAPS" hwdep Audio"); @@ -739,7 +739,7 @@ int usX2Y_hwdep_pcm_new(struct snd_card *card)
#else
-int usX2Y_hwdep_pcm_new(struct snd_card *card) +int usx2y_hwdep_pcm_new(struct snd_card *card) { return 0; } diff --git a/sound/usb/usx2y/usx2yhwdeppcm.h b/sound/usb/usx2y/usx2yhwdeppcm.h index eb5a46466f0e..731b1c5a3474 100644 --- a/sound/usb/usx2y/usx2yhwdeppcm.h +++ b/sound/usb/usx2y/usx2yhwdeppcm.h @@ -4,7 +4,7 @@ #define MAXSTRIDE 3
#define SSS (((MAXPACK*MAXBUFFERMS*MAXSTRIDE + 4096) / 4096) * 4096) -struct snd_usX2Y_hwdep_pcm_shm { +struct snd_usx2y_hwdep_pcm_shm { char playback[SSS]; char capture0x8[SSS]; char capture0xA[SSS]; @@ -20,4 +20,4 @@ struct snd_usX2Y_hwdep_pcm_shm { int capture_iso_start; };
-int usX2Y_hwdep_pcm_new(struct snd_card *card); +int usx2y_hwdep_pcm_new(struct snd_card *card);
From: Takashi Iwai tiwai@suse.de
[ Upstream commit cae0cf651adccee2c3f376e78f30fbd788d0829f ]
Unlike some other functions, we can't pass NULL pointer to free_pages_exact(). Add a proper NULL check for avoiding possible Oops.
Link: https://lore.kernel.org/r/20210517131545.27252-10-tiwai@suse.de Signed-off-by: Takashi Iwai tiwai@suse.de Signed-off-by: Sasha Levin sashal@kernel.org --- sound/usb/usx2y/usb_stream.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-)
diff --git a/sound/usb/usx2y/usb_stream.c b/sound/usb/usx2y/usb_stream.c index 091c071b270a..cff684942c4f 100644 --- a/sound/usb/usx2y/usb_stream.c +++ b/sound/usb/usx2y/usb_stream.c @@ -142,8 +142,11 @@ void usb_stream_free(struct usb_stream_kernel *sk) if (!s) return;
- free_pages_exact(sk->write_page, s->write_size); - sk->write_page = NULL; + if (sk->write_page) { + free_pages_exact(sk->write_page, s->write_size); + sk->write_page = NULL; + } + free_pages_exact(s, s->read_size); sk->s = NULL; }
From: Takashi Sakamoto o-takashi@sakamocchi.jp
[ Upstream commit 5d6fb80a142b5994355ce675c517baba6089d199 ]
This reverts commit 0edabdfe89581669609eaac5f6a8d0ae6fe95e7f.
I've explained that optional FireWire card for d.2 is also built-in to d.2 Pro, however it's wrong. The optional card uses DM1000 ASIC and has 'Mackie DJ Mixer' in its model name of configuration ROM. On the other hand, built-in FireWire card for d.2 Pro and d.4 Pro uses OXFW971 ASIC and has 'd.Pro' in its model name according to manuals and user experiences. The former card is not the card for d.2 Pro. They are similar in appearance but different internally.
Signed-off-by: Takashi Sakamoto o-takashi@sakamocchi.jp Link: https://lore.kernel.org/r/20210518084557.102681-2-o-takashi@sakamocchi.jp Signed-off-by: Takashi Iwai tiwai@suse.de Signed-off-by: Sasha Levin sashal@kernel.org --- sound/firewire/Kconfig | 4 ++-- sound/firewire/bebob/bebob.c | 2 +- sound/firewire/oxfw/oxfw.c | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/sound/firewire/Kconfig b/sound/firewire/Kconfig index 9897bd26a438..def1f3d5ecf5 100644 --- a/sound/firewire/Kconfig +++ b/sound/firewire/Kconfig @@ -38,7 +38,7 @@ config SND_OXFW * Mackie(Loud) Onyx 1640i (former model) * Mackie(Loud) Onyx Satellite * Mackie(Loud) Tapco Link.Firewire - * Mackie(Loud) d.4 pro + * Mackie(Loud) d.2 pro/d.4 pro (built-in FireWire card with OXFW971 ASIC) * Mackie(Loud) U.420/U.420d * TASCAM FireOne * Stanton Controllers & Systems 1 Deck/Mixer @@ -84,7 +84,7 @@ config SND_BEBOB * PreSonus FIREBOX/FIREPOD/FP10/Inspire1394 * BridgeCo RDAudio1/Audio5 * Mackie Onyx 1220/1620/1640 (FireWire I/O Card) - * Mackie d.2 (FireWire Option) and d.2 Pro + * Mackie d.2 (optional FireWire card with DM1000 ASIC) * Stanton FinalScratch 2 (ScratchAmp) * Tascam IF-FW/DM * Behringer XENIX UFX 1204/1604 diff --git a/sound/firewire/bebob/bebob.c b/sound/firewire/bebob/bebob.c index daeecfa8b9aa..90e98a6d1546 100644 --- a/sound/firewire/bebob/bebob.c +++ b/sound/firewire/bebob/bebob.c @@ -387,7 +387,7 @@ static const struct ieee1394_device_id bebob_id_table[] = { SND_BEBOB_DEV_ENTRY(VEN_BRIDGECO, 0x00010049, &spec_normal), /* Mackie, Onyx 1220/1620/1640 (Firewire I/O Card) */ SND_BEBOB_DEV_ENTRY(VEN_MACKIE2, 0x00010065, &spec_normal), - // Mackie, d.2 (Firewire option card) and d.2 Pro (the card is built-in). + // Mackie, d.2 (optional Firewire card with DM1000). SND_BEBOB_DEV_ENTRY(VEN_MACKIE1, 0x00010067, &spec_normal), /* Stanton, ScratchAmp */ SND_BEBOB_DEV_ENTRY(VEN_STANTON, 0x00000001, &spec_normal), diff --git a/sound/firewire/oxfw/oxfw.c b/sound/firewire/oxfw/oxfw.c index 9eea25c46dc7..5490637d278a 100644 --- a/sound/firewire/oxfw/oxfw.c +++ b/sound/firewire/oxfw/oxfw.c @@ -355,7 +355,7 @@ static const struct ieee1394_device_id oxfw_id_table[] = { * Onyx-i series (former models): 0x081216 * Mackie Onyx Satellite: 0x00200f * Tapco LINK.firewire 4x6: 0x000460 - * d.4 pro: Unknown + * d.2 pro/d.4 pro (built-in card): Unknown * U.420: Unknown * U.420d: Unknown */
From: Chunfeng Yun chunfeng.yun@mediatek.com
[ Upstream commit 880287910b1892ed2cb38977893b947382a09d21 ]
When power on system with OTG cable, IDDIG's interrupt arises before the charger registration, it will cause a NULL pointer dereference, fix the issue by registering the power supply before requesting IDDIG/VBUS irq.
Signed-off-by: Chunfeng Yun chunfeng.yun@mediatek.com Link: https://lore.kernel.org/r/1621406386-18838-1-git-send-email-chunfeng.yun@med... Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/usb/common/usb-conn-gpio.c | 44 ++++++++++++++++++------------ 1 file changed, 26 insertions(+), 18 deletions(-)
diff --git a/drivers/usb/common/usb-conn-gpio.c b/drivers/usb/common/usb-conn-gpio.c index 6c4e3a19f42c..c9545a4eff66 100644 --- a/drivers/usb/common/usb-conn-gpio.c +++ b/drivers/usb/common/usb-conn-gpio.c @@ -149,14 +149,32 @@ static int usb_charger_get_property(struct power_supply *psy, return 0; }
-static int usb_conn_probe(struct platform_device *pdev) +static int usb_conn_psy_register(struct usb_conn_info *info) { - struct device *dev = &pdev->dev; - struct power_supply_desc *desc; - struct usb_conn_info *info; + struct device *dev = info->dev; + struct power_supply_desc *desc = &info->desc; struct power_supply_config cfg = { .of_node = dev->of_node, }; + + desc->name = "usb-charger"; + desc->properties = usb_charger_properties; + desc->num_properties = ARRAY_SIZE(usb_charger_properties); + desc->get_property = usb_charger_get_property; + desc->type = POWER_SUPPLY_TYPE_USB; + cfg.drv_data = info; + + info->charger = devm_power_supply_register(dev, desc, &cfg); + if (IS_ERR(info->charger)) + dev_err(dev, "Unable to register charger\n"); + + return PTR_ERR_OR_ZERO(info->charger); +} + +static int usb_conn_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct usb_conn_info *info; bool need_vbus = true; int ret = 0;
@@ -218,6 +236,10 @@ static int usb_conn_probe(struct platform_device *pdev) return PTR_ERR(info->role_sw); }
+ ret = usb_conn_psy_register(info); + if (ret) + goto put_role_sw; + if (info->id_gpiod) { info->id_irq = gpiod_to_irq(info->id_gpiod); if (info->id_irq < 0) { @@ -252,20 +274,6 @@ static int usb_conn_probe(struct platform_device *pdev) } }
- desc = &info->desc; - desc->name = "usb-charger"; - desc->properties = usb_charger_properties; - desc->num_properties = ARRAY_SIZE(usb_charger_properties); - desc->get_property = usb_charger_get_property; - desc->type = POWER_SUPPLY_TYPE_USB; - cfg.drv_data = info; - - info->charger = devm_power_supply_register(dev, desc, &cfg); - if (IS_ERR(info->charger)) { - dev_err(dev, "Unable to register charger\n"); - return PTR_ERR(info->charger); - } - platform_set_drvdata(pdev, info);
/* Perform initial detection */
From: Jaska Uimonen jaska.uimonen@linux.intel.com
[ Upstream commit ccaea61a8d1b8180cc3c470e383381884e4bc1f2 ]
Fix sparse warning by using le32_to_cpu.
Signed-off-by: Jaska Uimonen jaska.uimonen@linux.intel.com Reviewed-by: Pierre-Louis Bossart pierre-louis.bossart@linux.intel.com Reviewed-by: Ranjani Sridharan ranjani.sridharan@linux.intel.com Signed-off-by: Kai Vehmanen kai.vehmanen@linux.intel.com Link: https://lore.kernel.org/r/20210521092804.3721324-6-kai.vehmanen@linux.intel.... Signed-off-by: Mark Brown broonie@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- sound/soc/sof/topology.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/sound/soc/sof/topology.c b/sound/soc/sof/topology.c index 59abcfc9bd55..cb16b2bd8c21 100644 --- a/sound/soc/sof/topology.c +++ b/sound/soc/sof/topology.c @@ -3335,7 +3335,7 @@ static int sof_link_load(struct snd_soc_component *scomp, int index, /* Copy common data to all config ipc structs */ for (i = 0; i < num_conf; i++) { config[i].hdr.cmd = SOF_IPC_GLB_DAI_MSG | SOF_IPC_DAI_CONFIG; - config[i].format = hw_config[i].fmt; + config[i].format = le32_to_cpu(hw_config[i].fmt); config[i].type = common_config.type; config[i].dai_index = common_config.dai_index; }
From: Luiz Sampaio sampaio.ime@gmail.com
[ Upstream commit 1f5e7518f063728aee0679c5086b92d8ea429e11 ]
The purpose of the w1_ds2438_get_page function is to get the register values at the page passed as the pageno parameter. However, the page0 was hardcoded, such that the function always returned the page0 contents. Fixed so that the function can retrieve any page.
Signed-off-by: Luiz Sampaio sampaio.ime@gmail.com Link: https://lore.kernel.org/r/20210519223046.13798-5-sampaio.ime@gmail.com Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/w1/slaves/w1_ds2438.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/drivers/w1/slaves/w1_ds2438.c b/drivers/w1/slaves/w1_ds2438.c index 5cfb0ae23e91..5698566b0ee0 100644 --- a/drivers/w1/slaves/w1_ds2438.c +++ b/drivers/w1/slaves/w1_ds2438.c @@ -62,13 +62,13 @@ static int w1_ds2438_get_page(struct w1_slave *sl, int pageno, u8 *buf) if (w1_reset_select_slave(sl)) continue; w1_buf[0] = W1_DS2438_RECALL_MEMORY; - w1_buf[1] = 0x00; + w1_buf[1] = (u8)pageno; w1_write_block(sl->master, w1_buf, 2);
if (w1_reset_select_slave(sl)) continue; w1_buf[0] = W1_DS2438_READ_SCRATCH; - w1_buf[1] = 0x00; + w1_buf[1] = (u8)pageno; w1_write_block(sl->master, w1_buf, 2);
count = w1_read_block(sl->master, buf, DS2438_PAGE_SIZE + 1);
From: Vamshi Krishna Gopal vamshi.krishna.gopal@intel.com
[ Upstream commit 03effde3a2ea1d82c4dd6b634fc6174545d2c34f ]
Brya is another ADL-P product.
AlderLake has support for Bluetooth audio offload capability. Enable the BT-offload quirk for ADL-P Brya and the Intel RVP.
Signed-off-by: Vamshi Krishna Gopal vamshi.krishna.gopal@intel.com Signed-off-by: Yong Zhi yong.zhi@intel.com Reviewed-by: Bard Liao bard.liao@intel.com Reviewed-by: Ranjani Sridharan ranjani.sridharan@linux.intel.com Signed-off-by: Kai Vehmanen kai.vehmanen@linux.intel.com Link: https://lore.kernel.org/r/20210521155632.3736393-2-kai.vehmanen@linux.intel.... Signed-off-by: Mark Brown broonie@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- sound/soc/intel/boards/sof_sdw.c | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-)
diff --git a/sound/soc/intel/boards/sof_sdw.c b/sound/soc/intel/boards/sof_sdw.c index 5827a16773c9..2ba3eefb9c8d 100644 --- a/sound/soc/intel/boards/sof_sdw.c +++ b/sound/soc/intel/boards/sof_sdw.c @@ -197,7 +197,21 @@ static const struct dmi_system_id sof_sdw_quirk_table[] = { .driver_data = (void *)(SOF_RT711_JD_SRC_JD1 | SOF_SDW_TGL_HDMI | SOF_RT715_DAI_ID_FIX | - SOF_SDW_PCH_DMIC), + SOF_SDW_PCH_DMIC | + SOF_BT_OFFLOAD_SSP(2) | + SOF_SSP_BT_OFFLOAD_PRESENT), + }, + { + .callback = sof_sdw_quirk_cb, + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Google"), + DMI_MATCH(DMI_PRODUCT_NAME, "Brya"), + }, + .driver_data = (void *)(SOF_SDW_TGL_HDMI | + SOF_SDW_PCH_DMIC | + SOF_SDW_FOUR_SPK | + SOF_BT_OFFLOAD_SSP(2) | + SOF_SSP_BT_OFFLOAD_PRESENT), }, {} };
From: ching Huang ching2048@areca.com.tw
[ Upstream commit d9a231226f28261a787535e08d0c78669e1ad010 ]
It is possible for the IOP to be delayed in updating the doorbell status. The doorbell status should not be 0 so loop until the value changes.
Link: https://lore.kernel.org/r/afdfdf7eabecf14632492c4987a6b9ac6312a7ad.camel@are... Signed-off-by: ching Huang ching2048@areca.com.tw Signed-off-by: Martin K. Petersen martin.petersen@oracle.com Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/scsi/arcmsr/arcmsr_hba.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-)
diff --git a/drivers/scsi/arcmsr/arcmsr_hba.c b/drivers/scsi/arcmsr/arcmsr_hba.c index 930972cda38c..42e494a7106c 100644 --- a/drivers/scsi/arcmsr/arcmsr_hba.c +++ b/drivers/scsi/arcmsr/arcmsr_hba.c @@ -2419,10 +2419,17 @@ static void arcmsr_hbaD_doorbell_isr(struct AdapterControlBlock *pACB)
static void arcmsr_hbaE_doorbell_isr(struct AdapterControlBlock *pACB) { - uint32_t outbound_doorbell, in_doorbell, tmp; + uint32_t outbound_doorbell, in_doorbell, tmp, i; struct MessageUnit_E __iomem *reg = pACB->pmuE;
- in_doorbell = readl(®->iobound_doorbell); + if (pACB->adapter_type == ACB_ADAPTER_TYPE_F) { + for (i = 0; i < 5; i++) { + in_doorbell = readl(®->iobound_doorbell); + if (in_doorbell != 0) + break; + } + } else + in_doorbell = readl(®->iobound_doorbell); outbound_doorbell = in_doorbell ^ pACB->in_doorbell; do { writel(0, ®->host_int_status); /* clear interrupt */
From: Sergey Shtylyov s.shtylyov@omp.ru
[ Upstream commit ab17122e758ef68fb21033e25c041144067975f5 ]
After commit 6c11dc060427 ("scsi: hisi_sas: Fix IRQ checks") we have the error codes returned by platform_get_irq() ready for the propagation upsream in interrupt_init_v1_hw() -- that will fix still broken deferred probing. Let's propagate the error codes from devm_request_irq() as well since I don't see the reason to override them with -ENOENT...
Link: https://lore.kernel.org/r/49ba93a3-d427-7542-d85a-b74fe1a33a73@omp.ru Acked-by: John Garry john.garry@huawei.com Signed-off-by: Sergey Shtylyov s.shtylyov@omp.ru Signed-off-by: Martin K. Petersen martin.petersen@oracle.com Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/scsi/hisi_sas/hisi_sas_v1_hw.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-)
diff --git a/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c b/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c index 3e359ac752fd..3cba7bfba296 100644 --- a/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c +++ b/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c @@ -1649,7 +1649,7 @@ static int interrupt_init_v1_hw(struct hisi_hba *hisi_hba) if (irq < 0) { dev_err(dev, "irq init: fail map phy interrupt %d\n", idx); - return -ENOENT; + return irq; }
rc = devm_request_irq(dev, irq, phy_interrupts[j], 0, @@ -1657,7 +1657,7 @@ static int interrupt_init_v1_hw(struct hisi_hba *hisi_hba) if (rc) { dev_err(dev, "irq init: could not request phy interrupt %d, rc=%d\n", irq, rc); - return -ENOENT; + return rc; } } } @@ -1668,7 +1668,7 @@ static int interrupt_init_v1_hw(struct hisi_hba *hisi_hba) if (irq < 0) { dev_err(dev, "irq init: could not map cq interrupt %d\n", idx); - return -ENOENT; + return irq; }
rc = devm_request_irq(dev, irq, cq_interrupt_v1_hw, 0, @@ -1676,7 +1676,7 @@ static int interrupt_init_v1_hw(struct hisi_hba *hisi_hba) if (rc) { dev_err(dev, "irq init: could not request cq interrupt %d, rc=%d\n", irq, rc); - return -ENOENT; + return rc; } }
@@ -1686,7 +1686,7 @@ static int interrupt_init_v1_hw(struct hisi_hba *hisi_hba) if (irq < 0) { dev_err(dev, "irq init: could not map fatal interrupt %d\n", idx); - return -ENOENT; + return irq; }
rc = devm_request_irq(dev, irq, fatal_interrupts[i], 0, @@ -1694,7 +1694,7 @@ static int interrupt_init_v1_hw(struct hisi_hba *hisi_hba) if (rc) { dev_err(dev, "irq init: could not request fatal interrupt %d, rc=%d\n", irq, rc); - return -ENOENT; + return rc; } }
From: James Smart jsmart2021@gmail.com
[ Upstream commit e30d55137edef47434c40d7570276a0846fe922c ]
An 'unexpected timeout' message may be seen in a point-2-point topology. The message occurs when a PLOGI is received before the driver is notified of FLOGI completion. The FLOGI completion failure causes discovery to be triggered for a second time. The discovery timer is restarted but no new discovery activity is initiated, thus the timeout message eventually appears.
In point-2-point, when discovery has progressed before the FLOGI completion is processed, it is not a failure. Add code to FLOGI completion to detect that discovery has progressed and exit the FLOGI handling (noop'ing it).
Link: https://lore.kernel.org/r/20210514195559.119853-4-jsmart2021@gmail.com Co-developed-by: Justin Tee justin.tee@broadcom.com Signed-off-by: Justin Tee justin.tee@broadcom.com Signed-off-by: James Smart jsmart2021@gmail.com Signed-off-by: Martin K. Petersen martin.petersen@oracle.com Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/scsi/lpfc/lpfc_els.c | 9 +++++++++ 1 file changed, 9 insertions(+)
diff --git a/drivers/scsi/lpfc/lpfc_els.c b/drivers/scsi/lpfc/lpfc_els.c index 21108f322c99..04568c6183ac 100644 --- a/drivers/scsi/lpfc/lpfc_els.c +++ b/drivers/scsi/lpfc/lpfc_els.c @@ -1175,6 +1175,15 @@ lpfc_cmpl_els_flogi(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, phba->fcf.fcf_redisc_attempted = 0; /* reset */ goto out; } + } else if (vport->port_state > LPFC_FLOGI && + vport->fc_flag & FC_PT2PT) { + /* + * In a p2p topology, it is possible that discovery has + * already progressed, and this completion can be ignored. + * Recheck the indicated topology. + */ + if (!sp->cmn.fPort) + goto out; }
flogifail:
From: James Smart jsmart2021@gmail.com
[ Upstream commit 5aa615d195f1e142c662cb2253f057c9baec7531 ]
The driver is encountering a crash in lpfc_free_iocb_list() while performing initial attachment.
Code review found this to be an errant failure path that was taken, jumping to a tag that then referenced structures that were uninitialized.
Fix the failure path.
Link: https://lore.kernel.org/r/20210514195559.119853-9-jsmart2021@gmail.com Co-developed-by: Justin Tee justin.tee@broadcom.com Signed-off-by: Justin Tee justin.tee@broadcom.com Signed-off-by: James Smart jsmart2021@gmail.com Signed-off-by: Martin K. Petersen martin.petersen@oracle.com Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/scsi/lpfc/lpfc_sli.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/drivers/scsi/lpfc/lpfc_sli.c b/drivers/scsi/lpfc/lpfc_sli.c index fc3682f15f50..3106ebc586f6 100644 --- a/drivers/scsi/lpfc/lpfc_sli.c +++ b/drivers/scsi/lpfc/lpfc_sli.c @@ -7959,7 +7959,7 @@ lpfc_sli4_hba_setup(struct lpfc_hba *phba) "0393 Error %d during rpi post operation\n", rc); rc = -ENODEV; - goto out_destroy_queue; + goto out_free_iocblist; } lpfc_sli4_node_prep(phba);
@@ -8125,8 +8125,9 @@ lpfc_sli4_hba_setup(struct lpfc_hba *phba) out_unset_queue: /* Unset all the queues set up in this routine when error out */ lpfc_sli4_queue_unset(phba); -out_destroy_queue: +out_free_iocblist: lpfc_free_iocb_list(phba); +out_destroy_queue: lpfc_sli4_queue_destroy(phba); out_stop_timers: lpfc_stop_hba_timers(phba);
From: John Garry john.garry@huawei.com
[ Upstream commit ea2f0f77538c50739b9fb4de4700cee5535e1f77 ]
The sysfs handling function sdev_store_queue_depth() enforces that the sdev queue depth cannot exceed shost can_queue. The initial sdev queue depth comes from shost cmd_per_lun. However, the LLDD may manually set cmd_per_lun to be larger than can_queue, which leads to an initial sdev queue depth greater than can_queue.
Such an issue was reported in [0], which caused a hang. That has since been fixed in commit fc09acb7de31 ("scsi: scsi_debug: Fix cmd_per_lun, set to max_queue").
Stop this possibly happening for other drivers by capping shost cmd_per_lun at shost can_queue.
[0] https://lore.kernel.org/linux-scsi/YHaez6iN2HHYxYOh@T590/
Link: https://lore.kernel.org/r/1621434662-173079-1-git-send-email-john.garry@huaw... Reviewed-by: Ming Lei ming.lei@redhat.com Reviewed-by: Bart Van Assche bvanassche@acm.org Signed-off-by: John Garry john.garry@huawei.com Signed-off-by: Martin K. Petersen martin.petersen@oracle.com Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/scsi/hosts.c | 3 +++ 1 file changed, 3 insertions(+)
diff --git a/drivers/scsi/hosts.c b/drivers/scsi/hosts.c index cd52664920e1..2684be9a79a8 100644 --- a/drivers/scsi/hosts.c +++ b/drivers/scsi/hosts.c @@ -220,6 +220,9 @@ int scsi_add_host_with_dma(struct Scsi_Host *shost, struct device *dev, goto fail; }
+ shost->cmd_per_lun = min_t(short, shost->cmd_per_lun, + shost->can_queue); + error = scsi_init_sense_cache(shost); if (error) goto fail;
From: Yufen Yu yuyufen@huawei.com
[ Upstream commit a38e93302ee25b2ca6f4ee76c6c974cf3637985e ]
pm_runtime_get_sync will increment pm usage counter even it failed. Forgetting to putting operation will result in reference leak here. Fix it by replacing it with pm_runtime_resume_and_get to keep usage counter balanced.
Reported-by: Hulk Robot hulkci@huawei.com Signed-off-by: Yufen Yu yuyufen@huawei.com Link: https://lore.kernel.org/r/20210524093811.612302-1-yuyufen@huawei.com Signed-off-by: Takashi Iwai tiwai@suse.de Signed-off-by: Sasha Levin sashal@kernel.org --- sound/ac97/bus.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/sound/ac97/bus.c b/sound/ac97/bus.c index d9077e91382b..6ddf646cda65 100644 --- a/sound/ac97/bus.c +++ b/sound/ac97/bus.c @@ -520,7 +520,7 @@ static int ac97_bus_remove(struct device *dev) struct ac97_codec_driver *adrv = to_ac97_driver(dev->driver); int ret;
- ret = pm_runtime_get_sync(dev); + ret = pm_runtime_resume_and_get(dev); if (ret < 0) return ret;
From: Lucas Tanure tanureal@opensource.cirrus.com
[ Upstream commit 1c52825c38fc4e44c61ed75a8ae32f5fa580383b ]
The 16 Bits, 2 channels, 48K sample rate use case needs to configure a safer pll_divout during the start of PLL After 800us from the start of PLL the correct pll_divout can be set
Signed-off-by: Lucas Tanure tanureal@opensource.cirrus.com Reviewed-by: Richard Fitzgerald rf@opensource.cirrus.com Message-Id: 20210525090822.64577-1-tanureal@opensource.cirrus.com Signed-off-by: Mark Brown broonie@sirena.org.uk Signed-off-by: Sasha Levin sashal@kernel.org --- sound/soc/codecs/cs42l42.c | 47 +++++++++++++++++++++++++------------- sound/soc/codecs/cs42l42.h | 2 ++ 2 files changed, 33 insertions(+), 16 deletions(-)
diff --git a/sound/soc/codecs/cs42l42.c b/sound/soc/codecs/cs42l42.c index 77473c226f9e..8434c48354f1 100644 --- a/sound/soc/codecs/cs42l42.c +++ b/sound/soc/codecs/cs42l42.c @@ -581,6 +581,7 @@ struct cs42l42_pll_params { u8 pll_divout; u32 mclk_int; u8 pll_cal_ratio; + u8 n; };
/* @@ -588,21 +589,21 @@ struct cs42l42_pll_params { * Table 4-5 from the Datasheet */ static const struct cs42l42_pll_params pll_ratio_table[] = { - { 1536000, 0, 1, 0x00, 0x7D, 0x000000, 0x03, 0x10, 12000000, 125 }, - { 2822400, 0, 1, 0x00, 0x40, 0x000000, 0x03, 0x10, 11289600, 128 }, - { 3000000, 0, 1, 0x00, 0x40, 0x000000, 0x03, 0x10, 12000000, 128 }, - { 3072000, 0, 1, 0x00, 0x3E, 0x800000, 0x03, 0x10, 12000000, 125 }, - { 4000000, 0, 1, 0x00, 0x30, 0x800000, 0x03, 0x10, 12000000, 96 }, - { 4096000, 0, 1, 0x00, 0x2E, 0xE00000, 0x03, 0x10, 12000000, 94 }, - { 5644800, 0, 1, 0x01, 0x40, 0x000000, 0x03, 0x10, 11289600, 128 }, - { 6000000, 0, 1, 0x01, 0x40, 0x000000, 0x03, 0x10, 12000000, 128 }, - { 6144000, 0, 1, 0x01, 0x3E, 0x800000, 0x03, 0x10, 12000000, 125 }, - { 11289600, 0, 0, 0, 0, 0, 0, 0, 11289600, 0 }, - { 12000000, 0, 0, 0, 0, 0, 0, 0, 12000000, 0 }, - { 12288000, 0, 0, 0, 0, 0, 0, 0, 12288000, 0 }, - { 22579200, 1, 0, 0, 0, 0, 0, 0, 22579200, 0 }, - { 24000000, 1, 0, 0, 0, 0, 0, 0, 24000000, 0 }, - { 24576000, 1, 0, 0, 0, 0, 0, 0, 24576000, 0 } + { 1536000, 0, 1, 0x00, 0x7D, 0x000000, 0x03, 0x10, 12000000, 125, 2}, + { 2822400, 0, 1, 0x00, 0x40, 0x000000, 0x03, 0x10, 11289600, 128, 1}, + { 3000000, 0, 1, 0x00, 0x40, 0x000000, 0x03, 0x10, 12000000, 128, 1}, + { 3072000, 0, 1, 0x00, 0x3E, 0x800000, 0x03, 0x10, 12000000, 125, 1}, + { 4000000, 0, 1, 0x00, 0x30, 0x800000, 0x03, 0x10, 12000000, 96, 1}, + { 4096000, 0, 1, 0x00, 0x2E, 0xE00000, 0x03, 0x10, 12000000, 94, 1}, + { 5644800, 0, 1, 0x01, 0x40, 0x000000, 0x03, 0x10, 11289600, 128, 1}, + { 6000000, 0, 1, 0x01, 0x40, 0x000000, 0x03, 0x10, 12000000, 128, 1}, + { 6144000, 0, 1, 0x01, 0x3E, 0x800000, 0x03, 0x10, 12000000, 125, 1}, + { 11289600, 0, 0, 0, 0, 0, 0, 0, 11289600, 0, 1}, + { 12000000, 0, 0, 0, 0, 0, 0, 0, 12000000, 0, 1}, + { 12288000, 0, 0, 0, 0, 0, 0, 0, 12288000, 0, 1}, + { 22579200, 1, 0, 0, 0, 0, 0, 0, 22579200, 0, 1}, + { 24000000, 1, 0, 0, 0, 0, 0, 0, 24000000, 0, 1}, + { 24576000, 1, 0, 0, 0, 0, 0, 0, 24576000, 0, 1} };
static int cs42l42_pll_config(struct snd_soc_component *component) @@ -738,8 +739,12 @@ static int cs42l42_pll_config(struct snd_soc_component *component) snd_soc_component_update_bits(component, CS42L42_PLL_CTL3, CS42L42_PLL_DIVOUT_MASK, - pll_ratio_table[i].pll_divout + (pll_ratio_table[i].pll_divout * pll_ratio_table[i].n) << CS42L42_PLL_DIVOUT_SHIFT); + if (pll_ratio_table[i].n != 1) + cs42l42->pll_divout = pll_ratio_table[i].pll_divout; + else + cs42l42->pll_divout = 0; snd_soc_component_update_bits(component, CS42L42_PLL_CAL_RATIO, CS42L42_PLL_CAL_RATIO_MASK, @@ -894,6 +899,16 @@ static int cs42l42_mute_stream(struct snd_soc_dai *dai, int mute, int stream) if ((cs42l42->bclk < 11289600) && (cs42l42->sclk < 11289600)) { snd_soc_component_update_bits(component, CS42L42_PLL_CTL1, CS42L42_PLL_START_MASK, 1); + + if (cs42l42->pll_divout) { + usleep_range(CS42L42_PLL_DIVOUT_TIME_US, + CS42L42_PLL_DIVOUT_TIME_US * 2); + snd_soc_component_update_bits(component, CS42L42_PLL_CTL3, + CS42L42_PLL_DIVOUT_MASK, + cs42l42->pll_divout << + CS42L42_PLL_DIVOUT_SHIFT); + } + ret = regmap_read_poll_timeout(cs42l42->regmap, CS42L42_PLL_LOCK_STATUS, regval, diff --git a/sound/soc/codecs/cs42l42.h b/sound/soc/codecs/cs42l42.h index 36b763f0d1a0..be5fbf0df3e5 100644 --- a/sound/soc/codecs/cs42l42.h +++ b/sound/soc/codecs/cs42l42.h @@ -755,6 +755,7 @@
#define CS42L42_NUM_SUPPLIES 5 #define CS42L42_BOOT_TIME_US 3000 +#define CS42L42_PLL_DIVOUT_TIME_US 800 #define CS42L42_CLOCK_SWITCH_DELAY_US 150 #define CS42L42_PLL_LOCK_POLL_US 250 #define CS42L42_PLL_LOCK_TIMEOUT_US 1250 @@ -777,6 +778,7 @@ struct cs42l42_private { int bclk; u32 sclk; u32 srate; + u8 pll_divout; u8 plug_state; u8 hs_type; u8 ts_inv;
From: Christophe JAILLET christophe.jaillet@wanadoo.fr
[ Upstream commit fad92b11047a748c996ebd6cfb164a63814eeb2e ]
In the probe function, if the final 'serial_config()' fails, 'info' is leaking.
Add a resource handling path to free this memory.
Signed-off-by: Christophe JAILLET christophe.jaillet@wanadoo.fr Link: https://lore.kernel.org/r/dc25f96b7faebf42e60fe8d02963c941cf4d8124.162197172... Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/tty/serial/8250/serial_cs.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-)
diff --git a/drivers/tty/serial/8250/serial_cs.c b/drivers/tty/serial/8250/serial_cs.c index 63ea9c4da3d5..3708114343b0 100644 --- a/drivers/tty/serial/8250/serial_cs.c +++ b/drivers/tty/serial/8250/serial_cs.c @@ -306,6 +306,7 @@ static int serial_resume(struct pcmcia_device *link) static int serial_probe(struct pcmcia_device *link) { struct serial_info *info; + int ret;
dev_dbg(&link->dev, "serial_attach()\n");
@@ -320,7 +321,15 @@ static int serial_probe(struct pcmcia_device *link) if (do_sound) link->config_flags |= CONF_ENABLE_SPKR;
- return serial_config(link); + ret = serial_config(link); + if (ret) + goto free_info; + + return 0; + +free_info: + kfree(info); + return ret; }
static void serial_detach(struct pcmcia_device *link)
From: Suganath Prabu S suganath-prabu.subramani@broadcom.com
[ Upstream commit e2fac6c44ae06e58ac02181b048af31195883c31 ]
Do not cancel current running firmware event work if the event type is different from MPT3SAS_REMOVE_UNRESPONDING_DEVICES. Otherwise a deadlock can be observed while cancelling the current firmware event work if a hard reset operation is called as part of processing the current event.
Link: https://lore.kernel.org/r/20210518051625.1596742-2-suganath-prabu.subramani@... Signed-off-by: Suganath Prabu S suganath-prabu.subramani@broadcom.com Signed-off-by: Martin K. Petersen martin.petersen@oracle.com Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/scsi/mpt3sas/mpt3sas_scsih.c | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+)
diff --git a/drivers/scsi/mpt3sas/mpt3sas_scsih.c b/drivers/scsi/mpt3sas/mpt3sas_scsih.c index d00aca3c77ce..79e34b5090b1 100644 --- a/drivers/scsi/mpt3sas/mpt3sas_scsih.c +++ b/drivers/scsi/mpt3sas/mpt3sas_scsih.c @@ -3697,6 +3697,28 @@ _scsih_fw_event_cleanup_queue(struct MPT3SAS_ADAPTER *ioc) ioc->fw_events_cleanup = 1; while ((fw_event = dequeue_next_fw_event(ioc)) || (fw_event = ioc->current_event)) { + + /* + * Don't call cancel_work_sync() for current_event + * other than MPT3SAS_REMOVE_UNRESPONDING_DEVICES; + * otherwise we may observe deadlock if current + * hard reset issued as part of processing the current_event. + * + * Orginal logic of cleaning the current_event is added + * for handling the back to back host reset issued by the user. + * i.e. during back to back host reset, driver use to process + * the two instances of MPT3SAS_REMOVE_UNRESPONDING_DEVICES + * event back to back and this made the drives to unregister + * the devices from SML. + */ + + if (fw_event == ioc->current_event && + ioc->current_event->event != + MPT3SAS_REMOVE_UNRESPONDING_DEVICES) { + ioc->current_event = NULL; + continue; + } + /* * Wait on the fw_event to complete. If this returns 1, then * the event was never executed, and we need a put for the
From: Hannes Reinecke hare@suse.de
[ Upstream commit 8793613de913e03e7c884f4cc56e350bc716431e ]
The description for scsi_mode_sense() claims to return the number of valid bytes on success, which is not what the code does. Additionally there is no gain in returning the SCSI status, as everything the callers do is to check against scsi_result_is_good(), which is what scsi_mode_sense() does already. So change the calling convention to return a standard error code on failure, and 0 on success, and adapt the description and all callers.
Link: https://lore.kernel.org/r/20210427083046.31620-4-hare@suse.de Reviewed-by: Bart Van Assche bvanassche@acm.org Signed-off-by: Hannes Reinecke hare@suse.de Signed-off-by: Martin K. Petersen martin.petersen@oracle.com Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/scsi/scsi_lib.c | 10 ++++++---- drivers/scsi/scsi_transport_sas.c | 9 ++++----- drivers/scsi/sd.c | 12 ++++++------ drivers/scsi/sr.c | 2 +- 4 files changed, 17 insertions(+), 16 deletions(-)
diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c index 532304d42f00..8614f61e385d 100644 --- a/drivers/scsi/scsi_lib.c +++ b/drivers/scsi/scsi_lib.c @@ -2093,9 +2093,7 @@ EXPORT_SYMBOL_GPL(scsi_mode_select); * @sshdr: place to put sense data (or NULL if no sense to be collected). * must be SCSI_SENSE_BUFFERSIZE big. * - * Returns zero if unsuccessful, or the header offset (either 4 - * or 8 depending on whether a six or ten byte command was - * issued) if successful. + * Returns zero if successful, or a negative error number on failure */ int scsi_mode_sense(struct scsi_device *sdev, int dbd, int modepage, @@ -2142,6 +2140,8 @@ scsi_mode_sense(struct scsi_device *sdev, int dbd, int modepage,
result = scsi_execute_req(sdev, cmd, DMA_FROM_DEVICE, buffer, len, sshdr, timeout, retries, NULL); + if (result < 0) + return result;
/* This code looks awful: what it's doing is making sure an * ILLEGAL REQUEST sense return identifies the actual command @@ -2186,13 +2186,15 @@ scsi_mode_sense(struct scsi_device *sdev, int dbd, int modepage, data->block_descriptor_length = buffer[3]; } data->header_length = header_length; + result = 0; } else if ((status_byte(result) == CHECK_CONDITION) && scsi_sense_valid(sshdr) && sshdr->sense_key == UNIT_ATTENTION && retry_count) { retry_count--; goto retry; } - + if (result > 0) + result = -EIO; return result; } EXPORT_SYMBOL(scsi_mode_sense); diff --git a/drivers/scsi/scsi_transport_sas.c b/drivers/scsi/scsi_transport_sas.c index c9abed8429c9..4a96fb05731d 100644 --- a/drivers/scsi/scsi_transport_sas.c +++ b/drivers/scsi/scsi_transport_sas.c @@ -1229,16 +1229,15 @@ int sas_read_port_mode_page(struct scsi_device *sdev) char *buffer = kzalloc(BUF_SIZE, GFP_KERNEL), *msdata; struct sas_end_device *rdev = sas_sdev_to_rdev(sdev); struct scsi_mode_data mode_data; - int res, error; + int error;
if (!buffer) return -ENOMEM;
- res = scsi_mode_sense(sdev, 1, 0x19, buffer, BUF_SIZE, 30*HZ, 3, - &mode_data, NULL); + error = scsi_mode_sense(sdev, 1, 0x19, buffer, BUF_SIZE, 30*HZ, 3, + &mode_data, NULL);
- error = -EINVAL; - if (!scsi_status_is_good(res)) + if (error) goto out;
msdata = buffer + mode_data.header_length + diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c index a2c3d9ad9ee4..4df54d4b3c65 100644 --- a/drivers/scsi/sd.c +++ b/drivers/scsi/sd.c @@ -2684,18 +2684,18 @@ sd_read_write_protect_flag(struct scsi_disk *sdkp, unsigned char *buffer) * 5: Illegal Request, Sense Code 24: Invalid field in * CDB. */ - if (!scsi_status_is_good(res)) + if (res < 0) res = sd_do_mode_sense(sdkp, 0, 0, buffer, 4, &data, NULL);
/* * Third attempt: ask 255 bytes, as we did earlier. */ - if (!scsi_status_is_good(res)) + if (res < 0) res = sd_do_mode_sense(sdkp, 0, 0x3F, buffer, 255, &data, NULL); }
- if (!scsi_status_is_good(res)) { + if (res < 0) { sd_first_printk(KERN_WARNING, sdkp, "Test WP failed, assume Write Enabled\n"); } else { @@ -2756,7 +2756,7 @@ sd_read_cache_type(struct scsi_disk *sdkp, unsigned char *buffer) res = sd_do_mode_sense(sdkp, dbd, modepage, buffer, first_len, &data, &sshdr);
- if (!scsi_status_is_good(res)) + if (res < 0) goto bad_sense;
if (!data.header_length) { @@ -2788,7 +2788,7 @@ sd_read_cache_type(struct scsi_disk *sdkp, unsigned char *buffer) res = sd_do_mode_sense(sdkp, dbd, modepage, buffer, len, &data, &sshdr);
- if (scsi_status_is_good(res)) { + if (!res) { int offset = data.header_length + data.block_descriptor_length;
while (offset < len) { @@ -2906,7 +2906,7 @@ static void sd_read_app_tag_own(struct scsi_disk *sdkp, unsigned char *buffer) res = scsi_mode_sense(sdp, 1, 0x0a, buffer, 36, SD_TIMEOUT, sdkp->max_retries, &data, &sshdr);
- if (!scsi_status_is_good(res) || !data.header_length || + if (res < 0 || !data.header_length || data.length < 6) { sd_first_printk(KERN_WARNING, sdkp, "getting Control mode page failed, assume no ATO\n"); diff --git a/drivers/scsi/sr.c b/drivers/scsi/sr.c index 7815ed642d43..1a94c7b1de2d 100644 --- a/drivers/scsi/sr.c +++ b/drivers/scsi/sr.c @@ -913,7 +913,7 @@ static void get_capabilities(struct scsi_cd *cd) rc = scsi_mode_sense(cd->device, 0, 0x2a, buffer, ms_len, SR_TIMEOUT, 3, &data, NULL);
- if (!scsi_status_is_good(rc) || data.length > ms_len || + if (rc < 0 || data.length > ms_len || data.header_length + data.block_descriptor_length > data.length) { /* failed, drive doesn't have capabilities mode page */ cd->cdi.speed = 1;
From: Hannes Reinecke hare@suse.de
[ Upstream commit 7e26e3ea028740f934477ec01ba586ab033c35aa ]
scsi_execute() will now return a negative error if there was an error prior to command submission; evaluate that instead if checking for DRIVER_ERROR.
[mkp: build fix]
Link: https://lore.kernel.org/r/20210427083046.31620-6-hare@suse.de Signed-off-by: Hannes Reinecke hare@suse.de Signed-off-by: Martin K. Petersen martin.petersen@oracle.com Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/scsi/device_handler/scsi_dh_alua.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/drivers/scsi/device_handler/scsi_dh_alua.c b/drivers/scsi/device_handler/scsi_dh_alua.c index efa8c0381476..c8bfd87a8047 100644 --- a/drivers/scsi/device_handler/scsi_dh_alua.c +++ b/drivers/scsi/device_handler/scsi_dh_alua.c @@ -562,12 +562,12 @@ static int alua_rtpg(struct scsi_device *sdev, struct alua_port_group *pg) kfree(buff); return SCSI_DH_OK; } - if (!scsi_sense_valid(&sense_hdr)) { + if (retval < 0 || !scsi_sense_valid(&sense_hdr)) { sdev_printk(KERN_INFO, sdev, "%s: rtpg failed, result %d\n", ALUA_DH_NAME, retval); kfree(buff); - if (driver_byte(retval) == DRIVER_ERROR) + if (retval < 0) return SCSI_DH_DEV_TEMP_BUSY; return SCSI_DH_IO; } @@ -791,11 +791,11 @@ static unsigned alua_stpg(struct scsi_device *sdev, struct alua_port_group *pg) retval = submit_stpg(sdev, pg->group_id, &sense_hdr);
if (retval) { - if (!scsi_sense_valid(&sense_hdr)) { + if (retval < 0 || !scsi_sense_valid(&sense_hdr)) { sdev_printk(KERN_INFO, sdev, "%s: stpg failed, result %d", ALUA_DH_NAME, retval); - if (driver_byte(retval) == DRIVER_ERROR) + if (retval < 0) return SCSI_DH_DEV_TEMP_BUSY; } else { sdev_printk(KERN_INFO, sdev, "%s: stpg failed\n",
From: Jiapeng Chong jiapeng.chong@linux.alibaba.com
[ Upstream commit 492109333c29e1bb16d8732e1d597b02e8e0bf2e ]
The error code is missing in this code scenario, add the error code '-EINVAL' to the return value 'rc.
Eliminate the follow smatch warning:
fs/jfs/jfs_logmgr.c:1327 lmLogInit() warn: missing error code 'rc'.
Reported-by: Abaci Robot abaci@linux.alibaba.com Signed-off-by: Jiapeng Chong jiapeng.chong@linux.alibaba.com Signed-off-by: Dave Kleikamp dave.kleikamp@oracle.com Signed-off-by: Sasha Levin sashal@kernel.org --- fs/jfs/jfs_logmgr.c | 1 + 1 file changed, 1 insertion(+)
diff --git a/fs/jfs/jfs_logmgr.c b/fs/jfs/jfs_logmgr.c index 9330eff210e0..78fd136ac13b 100644 --- a/fs/jfs/jfs_logmgr.c +++ b/fs/jfs/jfs_logmgr.c @@ -1324,6 +1324,7 @@ int lmLogInit(struct jfs_log * log) } else { if (!uuid_equal(&logsuper->uuid, &log->uuid)) { jfs_warn("wrong uuid on JFS log device"); + rc = -EINVAL; goto errout20; } log->size = le32_to_cpu(logsuper->size);
From: Chandrakanth Patil chandrakanth.patil@broadcom.com
[ Upstream commit b5438f48fdd8e1c3f130d32637511efd32038152 ]
The driver doesn't clean up all the allocated resources properly when scsi_add_host(), megasas_start_aen() function fails during the PCI device probe.
Clean up all those resources.
Link: https://lore.kernel.org/r/20210528131307.25683-3-chandrakanth.patil@broadcom... Signed-off-by: Chandrakanth Patil chandrakanth.patil@broadcom.com Signed-off-by: Sumit Saxena sumit.saxena@broadcom.com Signed-off-by: Martin K. Petersen martin.petersen@oracle.com Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/scsi/megaraid/megaraid_sas_base.c | 13 +++++++++++++ drivers/scsi/megaraid/megaraid_sas_fusion.c | 1 + 2 files changed, 14 insertions(+)
diff --git a/drivers/scsi/megaraid/megaraid_sas_base.c b/drivers/scsi/megaraid/megaraid_sas_base.c index 4d4e9dbe5193..e4004d3353b8 100644 --- a/drivers/scsi/megaraid/megaraid_sas_base.c +++ b/drivers/scsi/megaraid/megaraid_sas_base.c @@ -7545,11 +7545,16 @@ static int megasas_probe_one(struct pci_dev *pdev, return 0;
fail_start_aen: + instance->unload = 1; + scsi_remove_host(instance->host); fail_io_attach: megasas_mgmt_info.count--; megasas_mgmt_info.max_index--; megasas_mgmt_info.instance[megasas_mgmt_info.max_index] = NULL;
+ if (instance->requestorId && !instance->skip_heartbeat_timer_del) + del_timer_sync(&instance->sriov_heartbeat_timer); + instance->instancet->disable_intr(instance); megasas_destroy_irqs(instance);
@@ -7557,8 +7562,16 @@ static int megasas_probe_one(struct pci_dev *pdev, megasas_release_fusion(instance); else megasas_release_mfi(instance); + if (instance->msix_vectors) pci_free_irq_vectors(instance->pdev); + instance->msix_vectors = 0; + + if (instance->fw_crash_state != UNAVAILABLE) + megasas_free_host_crash_buffer(instance); + + if (instance->adapter_type != MFI_SERIES) + megasas_fusion_stop_watchdog(instance); fail_init_mfi: scsi_host_put(host); fail_alloc_instance: diff --git a/drivers/scsi/megaraid/megaraid_sas_fusion.c b/drivers/scsi/megaraid/megaraid_sas_fusion.c index 2221175ae051..8bf7db921758 100644 --- a/drivers/scsi/megaraid/megaraid_sas_fusion.c +++ b/drivers/scsi/megaraid/megaraid_sas_fusion.c @@ -5266,6 +5266,7 @@ megasas_alloc_fusion_context(struct megasas_instance *instance) if (!fusion->log_to_span) { dev_err(&instance->pdev->dev, "Failed from %s %d\n", __func__, __LINE__); + kfree(instance->ctrl_context); return -ENOMEM; } }
From: Kashyap Desai kashyap.desai@broadcom.com
[ Upstream commit ae6874ba4b43c5a00065f48599811a09d33b873d ]
Consider the case where a VD is deleted and the targetID of that VD is assigned to a newly created VD. If the sequence of deletion/addition of VD happens very quickly there is a possibility that second event (VD add) occurs even before the driver processes the first event (VD delete). As event processing is done in deferred context the device list remains the same (but targetID is re-used) so driver will not learn the VD deletion/additon. I/Os meant for the older VD will be directed to new VD which may lead to data corruption.
Make driver detect the deleted VD as soon as possible based on the RaidMap update and block further I/O to that device.
Link: https://lore.kernel.org/r/20210528131307.25683-4-chandrakanth.patil@broadcom... Reported-by: kernel test robot lkp@intel.com Signed-off-by: Kashyap Desai kashyap.desai@broadcom.com Signed-off-by: Chandrakanth Patil chandrakanth.patil@broadcom.com Signed-off-by: Martin K. Petersen martin.petersen@oracle.com Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/scsi/megaraid/megaraid_sas.h | 12 ++++ drivers/scsi/megaraid/megaraid_sas_base.c | 83 ++++++++++++++++++++--- drivers/scsi/megaraid/megaraid_sas_fp.c | 6 +- 3 files changed, 92 insertions(+), 9 deletions(-)
diff --git a/drivers/scsi/megaraid/megaraid_sas.h b/drivers/scsi/megaraid/megaraid_sas.h index b5a765b73c76..a43b67299b08 100644 --- a/drivers/scsi/megaraid/megaraid_sas.h +++ b/drivers/scsi/megaraid/megaraid_sas.h @@ -2262,6 +2262,15 @@ enum MR_PERF_MODE { (mode) == MR_LATENCY_PERF_MODE ? "Latency" : \ "Unknown")
+enum MEGASAS_LD_TARGET_ID_STATUS { + LD_TARGET_ID_INITIAL, + LD_TARGET_ID_ACTIVE, + LD_TARGET_ID_DELETED, +}; + +#define MEGASAS_TARGET_ID(sdev) \ + (((sdev->channel % 2) * MEGASAS_MAX_DEV_PER_CHANNEL) + sdev->id) + struct megasas_instance {
unsigned int *reply_map; @@ -2326,6 +2335,9 @@ struct megasas_instance { struct megasas_pd_list pd_list[MEGASAS_MAX_PD]; struct megasas_pd_list local_pd_list[MEGASAS_MAX_PD]; u8 ld_ids[MEGASAS_MAX_LD_IDS]; + u8 ld_tgtid_status[MEGASAS_MAX_LD_IDS]; + u8 ld_ids_prev[MEGASAS_MAX_LD_IDS]; + u8 ld_ids_from_raidmap[MEGASAS_MAX_LD_IDS]; s8 init_id;
u16 max_num_sge; diff --git a/drivers/scsi/megaraid/megaraid_sas_base.c b/drivers/scsi/megaraid/megaraid_sas_base.c index e4004d3353b8..3fecf4b2b0bd 100644 --- a/drivers/scsi/megaraid/megaraid_sas_base.c +++ b/drivers/scsi/megaraid/megaraid_sas_base.c @@ -141,6 +141,8 @@ static int megasas_register_aen(struct megasas_instance *instance, u32 seq_num, u32 class_locale_word); static void megasas_get_pd_info(struct megasas_instance *instance, struct scsi_device *sdev); +static void +megasas_set_ld_removed_by_fw(struct megasas_instance *instance);
/* * PCI ID table for all supported controllers @@ -436,6 +438,12 @@ megasas_decode_evt(struct megasas_instance *instance) (class_locale.members.locale), format_class(class_locale.members.class), evt_detail->description); + + if (megasas_dbg_lvl & LD_PD_DEBUG) + dev_info(&instance->pdev->dev, + "evt_detail.args.ld.target_id/index %d/%d\n", + evt_detail->args.ld.target_id, evt_detail->args.ld.ld_index); + }
/* @@ -1779,6 +1787,7 @@ megasas_queue_command(struct Scsi_Host *shost, struct scsi_cmnd *scmd) { struct megasas_instance *instance; struct MR_PRIV_DEVICE *mr_device_priv_data; + u32 ld_tgt_id;
instance = (struct megasas_instance *) scmd->device->host->hostdata; @@ -1805,17 +1814,21 @@ megasas_queue_command(struct Scsi_Host *shost, struct scsi_cmnd *scmd) } }
- if (atomic_read(&instance->adprecovery) == MEGASAS_HW_CRITICAL_ERROR) { + mr_device_priv_data = scmd->device->hostdata; + if (!mr_device_priv_data || + (atomic_read(&instance->adprecovery) == MEGASAS_HW_CRITICAL_ERROR)) { scmd->result = DID_NO_CONNECT << 16; scmd->scsi_done(scmd); return 0; }
- mr_device_priv_data = scmd->device->hostdata; - if (!mr_device_priv_data) { - scmd->result = DID_NO_CONNECT << 16; - scmd->scsi_done(scmd); - return 0; + if (MEGASAS_IS_LOGICAL(scmd->device)) { + ld_tgt_id = MEGASAS_TARGET_ID(scmd->device); + if (instance->ld_tgtid_status[ld_tgt_id] == LD_TARGET_ID_DELETED) { + scmd->result = DID_NO_CONNECT << 16; + scmd->scsi_done(scmd); + return 0; + } }
if (atomic_read(&instance->adprecovery) != MEGASAS_HBA_OPERATIONAL) @@ -2095,7 +2108,7 @@ static int megasas_slave_configure(struct scsi_device *sdev)
static int megasas_slave_alloc(struct scsi_device *sdev) { - u16 pd_index = 0; + u16 pd_index = 0, ld_tgt_id; struct megasas_instance *instance ; struct MR_PRIV_DEVICE *mr_device_priv_data;
@@ -2120,6 +2133,14 @@ static int megasas_slave_alloc(struct scsi_device *sdev) GFP_KERNEL); if (!mr_device_priv_data) return -ENOMEM; + + if (MEGASAS_IS_LOGICAL(sdev)) { + ld_tgt_id = MEGASAS_TARGET_ID(sdev); + instance->ld_tgtid_status[ld_tgt_id] = LD_TARGET_ID_ACTIVE; + if (megasas_dbg_lvl & LD_PD_DEBUG) + sdev_printk(KERN_INFO, sdev, "LD target ID %d created.\n", ld_tgt_id); + } + sdev->hostdata = mr_device_priv_data;
atomic_set(&mr_device_priv_data->r1_ldio_hint, @@ -2129,6 +2150,19 @@ static int megasas_slave_alloc(struct scsi_device *sdev)
static void megasas_slave_destroy(struct scsi_device *sdev) { + u16 ld_tgt_id; + struct megasas_instance *instance; + + instance = megasas_lookup_instance(sdev->host->host_no); + + if (MEGASAS_IS_LOGICAL(sdev)) { + ld_tgt_id = MEGASAS_TARGET_ID(sdev); + instance->ld_tgtid_status[ld_tgt_id] = LD_TARGET_ID_DELETED; + if (megasas_dbg_lvl & LD_PD_DEBUG) + sdev_printk(KERN_INFO, sdev, + "LD target ID %d removed from OS stack\n", ld_tgt_id); + } + kfree(sdev->hostdata); sdev->hostdata = NULL; } @@ -3525,6 +3559,22 @@ megasas_complete_abort(struct megasas_instance *instance, } }
+static void +megasas_set_ld_removed_by_fw(struct megasas_instance *instance) +{ + uint i; + + for (i = 0; (i < MEGASAS_MAX_LD_IDS); i++) { + if (instance->ld_ids_prev[i] != 0xff && + instance->ld_ids_from_raidmap[i] == 0xff) { + if (megasas_dbg_lvl & LD_PD_DEBUG) + dev_info(&instance->pdev->dev, + "LD target ID %d removed from RAID map\n", i); + instance->ld_tgtid_status[i] = LD_TARGET_ID_DELETED; + } + } +} + /** * megasas_complete_cmd - Completes a command * @instance: Adapter soft state @@ -3687,9 +3737,13 @@ megasas_complete_cmd(struct megasas_instance *instance, struct megasas_cmd *cmd, fusion->fast_path_io = 0; }
+ if (instance->adapter_type >= INVADER_SERIES) + megasas_set_ld_removed_by_fw(instance); + megasas_sync_map_info(instance); spin_unlock_irqrestore(instance->host->host_lock, flags); + break; } if (opcode == MR_DCMD_CTRL_EVENT_GET_INFO || @@ -8831,8 +8885,10 @@ megasas_aen_polling(struct work_struct *work) union megasas_evt_class_locale class_locale; int event_type = 0; u32 seq_num; + u16 ld_target_id; int error; u8 dcmd_ret = DCMD_SUCCESS; + struct scsi_device *sdev1;
if (!instance) { printk(KERN_ERR "invalid instance!\n"); @@ -8855,12 +8911,23 @@ megasas_aen_polling(struct work_struct *work) break;
case MR_EVT_LD_OFFLINE: - case MR_EVT_CFG_CLEARED: case MR_EVT_LD_DELETED: + ld_target_id = instance->evt_detail->args.ld.target_id; + sdev1 = scsi_device_lookup(instance->host, + MEGASAS_MAX_PD_CHANNELS + + (ld_target_id / MEGASAS_MAX_DEV_PER_CHANNEL), + (ld_target_id - MEGASAS_MAX_DEV_PER_CHANNEL), + 0); + if (sdev1) + megasas_remove_scsi_device(sdev1); + + event_type = SCAN_VD_CHANNEL; + break; case MR_EVT_LD_CREATED: event_type = SCAN_VD_CHANNEL; break;
+ case MR_EVT_CFG_CLEARED: case MR_EVT_CTRL_HOST_BUS_SCAN_REQUESTED: case MR_EVT_FOREIGN_CFG_IMPORTED: case MR_EVT_LD_STATE_CHANGE: diff --git a/drivers/scsi/megaraid/megaraid_sas_fp.c b/drivers/scsi/megaraid/megaraid_sas_fp.c index b6c08d620033..83f69c33b01a 100644 --- a/drivers/scsi/megaraid/megaraid_sas_fp.c +++ b/drivers/scsi/megaraid/megaraid_sas_fp.c @@ -349,6 +349,10 @@ u8 MR_ValidateMapInfo(struct megasas_instance *instance, u64 map_id)
num_lds = le16_to_cpu(drv_map->raidMap.ldCount);
+ memcpy(instance->ld_ids_prev, + instance->ld_ids_from_raidmap, + sizeof(instance->ld_ids_from_raidmap)); + memset(instance->ld_ids_from_raidmap, 0xff, MEGASAS_MAX_LD_IDS); /*Convert Raid capability values to CPU arch */ for (i = 0; (num_lds > 0) && (i < MAX_LOGICAL_DRIVES_EXT); i++) { ld = MR_TargetIdToLdGet(i, drv_map); @@ -359,7 +363,7 @@ u8 MR_ValidateMapInfo(struct megasas_instance *instance, u64 map_id)
raid = MR_LdRaidGet(ld, drv_map); le32_to_cpus((u32 *)&raid->capability); - + instance->ld_ids_from_raidmap[i] = i; num_lds--; }
From: Chandrakanth Patil chandrakanth.patil@broadcom.com
[ Upstream commit 9bedd36e9146b34dda4d6994e3aa1d72bc6442c1 ]
While reenabling the IRQ after IRQ poll there may be a small window for the firmware to post the replies with interrupts raised. In that case the driver will not see the interrupts which leads to I/O timeout.
This issue only happens when there are many I/O completions on a single reply queue. This forces the driver to switch between the interrupt and IRQ context.
Make the driver process the reply queue one more time after enabling the IRQ.
Link: https://lore.kernel.org/linux-scsi/20201102072746.27410-1-sreekanth.reddy@br... Link: https://lore.kernel.org/r/20210528131307.25683-5-chandrakanth.patil@broadcom... Cc: Tomas Henzl thenzl@redhat.com Reported-by: kernel test robot lkp@intel.com Signed-off-by: Chandrakanth Patil chandrakanth.patil@broadcom.com Signed-off-by: Sumit Saxena sumit.saxena@broadcom.com Signed-off-by: Martin K. Petersen martin.petersen@oracle.com Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/scsi/megaraid/megaraid_sas_fusion.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-)
diff --git a/drivers/scsi/megaraid/megaraid_sas_fusion.c b/drivers/scsi/megaraid/megaraid_sas_fusion.c index 8bf7db921758..123fa271c27f 100644 --- a/drivers/scsi/megaraid/megaraid_sas_fusion.c +++ b/drivers/scsi/megaraid/megaraid_sas_fusion.c @@ -3739,6 +3739,7 @@ static void megasas_sync_irqs(unsigned long instance_addr) if (irq_ctx->irq_poll_scheduled) { irq_ctx->irq_poll_scheduled = false; enable_irq(irq_ctx->os_irq); + complete_cmd_fusion(instance, irq_ctx->MSIxIndex, irq_ctx); } } } @@ -3770,6 +3771,7 @@ int megasas_irqpoll(struct irq_poll *irqpoll, int budget) irq_poll_complete(irqpoll); irq_ctx->irq_poll_scheduled = false; enable_irq(irq_ctx->os_irq); + complete_cmd_fusion(instance, irq_ctx->MSIxIndex, irq_ctx); }
return num_entries; @@ -3786,6 +3788,7 @@ megasas_complete_cmd_dpc_fusion(unsigned long instance_addr) { struct megasas_instance *instance = (struct megasas_instance *)instance_addr; + struct megasas_irq_context *irq_ctx = NULL; u32 count, MSIxIndex;
count = instance->msix_vectors > 0 ? instance->msix_vectors : 1; @@ -3794,8 +3797,10 @@ megasas_complete_cmd_dpc_fusion(unsigned long instance_addr) if (atomic_read(&instance->adprecovery) == MEGASAS_HW_CRITICAL_ERROR) return;
- for (MSIxIndex = 0 ; MSIxIndex < count; MSIxIndex++) - complete_cmd_fusion(instance, MSIxIndex, NULL); + for (MSIxIndex = 0 ; MSIxIndex < count; MSIxIndex++) { + irq_ctx = &instance->irq_context[MSIxIndex]; + complete_cmd_fusion(instance, MSIxIndex, irq_ctx); + } }
/**
From: Mike Christie michael.christie@oracle.com
[ Upstream commit 891e2639deae721dc43764a44fa255890dc34313 ]
During ep_disconnect we have been doing iscsi_suspend_tx/queue to block new I/O but every driver except cxgbi and iscsi_tcp can still get I/O from __iscsi_conn_send_pdu() if we haven't called iscsi_conn_failure() before ep_disconnect. This could happen if we were terminating the session, and the logout timed out before it was even sent to libiscsi.
Fix the issue by adding a helper which reverses the bind_conn call that allows new I/O to be queued. Drivers implementing ep_disconnect can use this to make sure new I/O is not queued to them when handling the disconnect.
Link: https://lore.kernel.org/r/20210525181821.7617-3-michael.christie@oracle.com Reviewed-by: Lee Duncan lduncan@suse.com Signed-off-by: Mike Christie michael.christie@oracle.com Signed-off-by: Martin K. Petersen martin.petersen@oracle.com Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/infiniband/ulp/iser/iscsi_iser.c | 1 + drivers/scsi/be2iscsi/be_main.c | 1 + drivers/scsi/bnx2i/bnx2i_iscsi.c | 1 + drivers/scsi/cxgbi/cxgb3i/cxgb3i.c | 1 + drivers/scsi/cxgbi/cxgb4i/cxgb4i.c | 1 + drivers/scsi/libiscsi.c | 70 +++++++++++++++++++++--- drivers/scsi/qedi/qedi_iscsi.c | 1 + drivers/scsi/qla4xxx/ql4_os.c | 1 + drivers/scsi/scsi_transport_iscsi.c | 10 +++- include/scsi/libiscsi.h | 1 + include/scsi/scsi_transport_iscsi.h | 1 + 11 files changed, 78 insertions(+), 11 deletions(-)
diff --git a/drivers/infiniband/ulp/iser/iscsi_iser.c b/drivers/infiniband/ulp/iser/iscsi_iser.c index 8fcaa1136f2c..6baebcb6d14d 100644 --- a/drivers/infiniband/ulp/iser/iscsi_iser.c +++ b/drivers/infiniband/ulp/iser/iscsi_iser.c @@ -1002,6 +1002,7 @@ static struct iscsi_transport iscsi_iser_transport = { /* connection management */ .create_conn = iscsi_iser_conn_create, .bind_conn = iscsi_iser_conn_bind, + .unbind_conn = iscsi_conn_unbind, .destroy_conn = iscsi_conn_teardown, .attr_is_visible = iser_attr_is_visible, .set_param = iscsi_iser_set_param, diff --git a/drivers/scsi/be2iscsi/be_main.c b/drivers/scsi/be2iscsi/be_main.c index 22cf7f4b8d8c..27c4f1598f76 100644 --- a/drivers/scsi/be2iscsi/be_main.c +++ b/drivers/scsi/be2iscsi/be_main.c @@ -5809,6 +5809,7 @@ struct iscsi_transport beiscsi_iscsi_transport = { .destroy_session = beiscsi_session_destroy, .create_conn = beiscsi_conn_create, .bind_conn = beiscsi_conn_bind, + .unbind_conn = iscsi_conn_unbind, .destroy_conn = iscsi_conn_teardown, .attr_is_visible = beiscsi_attr_is_visible, .set_iface_param = beiscsi_iface_set_param, diff --git a/drivers/scsi/bnx2i/bnx2i_iscsi.c b/drivers/scsi/bnx2i/bnx2i_iscsi.c index 1e6d8f62ea3c..b6c1da46d582 100644 --- a/drivers/scsi/bnx2i/bnx2i_iscsi.c +++ b/drivers/scsi/bnx2i/bnx2i_iscsi.c @@ -2276,6 +2276,7 @@ struct iscsi_transport bnx2i_iscsi_transport = { .destroy_session = bnx2i_session_destroy, .create_conn = bnx2i_conn_create, .bind_conn = bnx2i_conn_bind, + .unbind_conn = iscsi_conn_unbind, .destroy_conn = bnx2i_conn_destroy, .attr_is_visible = bnx2i_attr_is_visible, .set_param = iscsi_set_param, diff --git a/drivers/scsi/cxgbi/cxgb3i/cxgb3i.c b/drivers/scsi/cxgbi/cxgb3i/cxgb3i.c index 203f938fca7e..f949a4e00783 100644 --- a/drivers/scsi/cxgbi/cxgb3i/cxgb3i.c +++ b/drivers/scsi/cxgbi/cxgb3i/cxgb3i.c @@ -117,6 +117,7 @@ static struct iscsi_transport cxgb3i_iscsi_transport = { /* connection management */ .create_conn = cxgbi_create_conn, .bind_conn = cxgbi_bind_conn, + .unbind_conn = iscsi_conn_unbind, .destroy_conn = iscsi_tcp_conn_teardown, .start_conn = iscsi_conn_start, .stop_conn = iscsi_conn_stop, diff --git a/drivers/scsi/cxgbi/cxgb4i/cxgb4i.c b/drivers/scsi/cxgbi/cxgb4i/cxgb4i.c index 2c3491528d42..efb3e2b3398e 100644 --- a/drivers/scsi/cxgbi/cxgb4i/cxgb4i.c +++ b/drivers/scsi/cxgbi/cxgb4i/cxgb4i.c @@ -134,6 +134,7 @@ static struct iscsi_transport cxgb4i_iscsi_transport = { /* connection management */ .create_conn = cxgbi_create_conn, .bind_conn = cxgbi_bind_conn, + .unbind_conn = iscsi_conn_unbind, .destroy_conn = iscsi_tcp_conn_teardown, .start_conn = iscsi_conn_start, .stop_conn = iscsi_conn_stop, diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c index 4834219497ee..2aaf83678654 100644 --- a/drivers/scsi/libiscsi.c +++ b/drivers/scsi/libiscsi.c @@ -1387,23 +1387,32 @@ void iscsi_session_failure(struct iscsi_session *session, } EXPORT_SYMBOL_GPL(iscsi_session_failure);
-void iscsi_conn_failure(struct iscsi_conn *conn, enum iscsi_err err) +static bool iscsi_set_conn_failed(struct iscsi_conn *conn) { struct iscsi_session *session = conn->session;
- spin_lock_bh(&session->frwd_lock); - if (session->state == ISCSI_STATE_FAILED) { - spin_unlock_bh(&session->frwd_lock); - return; - } + if (session->state == ISCSI_STATE_FAILED) + return false;
if (conn->stop_stage == 0) session->state = ISCSI_STATE_FAILED; - spin_unlock_bh(&session->frwd_lock);
set_bit(ISCSI_SUSPEND_BIT, &conn->suspend_tx); set_bit(ISCSI_SUSPEND_BIT, &conn->suspend_rx); - iscsi_conn_error_event(conn->cls_conn, err); + return true; +} + +void iscsi_conn_failure(struct iscsi_conn *conn, enum iscsi_err err) +{ + struct iscsi_session *session = conn->session; + bool needs_evt; + + spin_lock_bh(&session->frwd_lock); + needs_evt = iscsi_set_conn_failed(conn); + spin_unlock_bh(&session->frwd_lock); + + if (needs_evt) + iscsi_conn_error_event(conn->cls_conn, err); } EXPORT_SYMBOL_GPL(iscsi_conn_failure);
@@ -2180,6 +2189,51 @@ static void iscsi_check_transport_timeouts(struct timer_list *t) spin_unlock(&session->frwd_lock); }
+/** + * iscsi_conn_unbind - prevent queueing to conn. + * @cls_conn: iscsi conn ep is bound to. + * @is_active: is the conn in use for boot or is this for EH/termination + * + * This must be called by drivers implementing the ep_disconnect callout. + * It disables queueing to the connection from libiscsi in preparation for + * an ep_disconnect call. + */ +void iscsi_conn_unbind(struct iscsi_cls_conn *cls_conn, bool is_active) +{ + struct iscsi_session *session; + struct iscsi_conn *conn; + + if (!cls_conn) + return; + + conn = cls_conn->dd_data; + session = conn->session; + /* + * Wait for iscsi_eh calls to exit. We don't wait for the tmf to + * complete or timeout. The caller just wants to know what's running + * is everything that needs to be cleaned up, and no cmds will be + * queued. + */ + mutex_lock(&session->eh_mutex); + + iscsi_suspend_queue(conn); + iscsi_suspend_tx(conn); + + spin_lock_bh(&session->frwd_lock); + if (!is_active) { + /* + * if logout timed out before userspace could even send a PDU + * the state might still be in ISCSI_STATE_LOGGED_IN and + * allowing new cmds and TMFs. + */ + if (session->state == ISCSI_STATE_LOGGED_IN) + iscsi_set_conn_failed(conn); + } + spin_unlock_bh(&session->frwd_lock); + mutex_unlock(&session->eh_mutex); +} +EXPORT_SYMBOL_GPL(iscsi_conn_unbind); + static void iscsi_prep_abort_task_pdu(struct iscsi_task *task, struct iscsi_tm *hdr) { diff --git a/drivers/scsi/qedi/qedi_iscsi.c b/drivers/scsi/qedi/qedi_iscsi.c index 08c05403cd72..ef16537c523c 100644 --- a/drivers/scsi/qedi/qedi_iscsi.c +++ b/drivers/scsi/qedi/qedi_iscsi.c @@ -1401,6 +1401,7 @@ struct iscsi_transport qedi_iscsi_transport = { .destroy_session = qedi_session_destroy, .create_conn = qedi_conn_create, .bind_conn = qedi_conn_bind, + .unbind_conn = iscsi_conn_unbind, .start_conn = qedi_conn_start, .stop_conn = iscsi_conn_stop, .destroy_conn = qedi_conn_destroy, diff --git a/drivers/scsi/qla4xxx/ql4_os.c b/drivers/scsi/qla4xxx/ql4_os.c index ad3afe30f617..74d0d1bc208d 100644 --- a/drivers/scsi/qla4xxx/ql4_os.c +++ b/drivers/scsi/qla4xxx/ql4_os.c @@ -259,6 +259,7 @@ static struct iscsi_transport qla4xxx_iscsi_transport = { .start_conn = qla4xxx_conn_start, .create_conn = qla4xxx_conn_create, .bind_conn = qla4xxx_conn_bind, + .unbind_conn = iscsi_conn_unbind, .stop_conn = iscsi_conn_stop, .destroy_conn = qla4xxx_conn_destroy, .set_param = iscsi_set_param, diff --git a/drivers/scsi/scsi_transport_iscsi.c b/drivers/scsi/scsi_transport_iscsi.c index 441f0152193f..82491343e94a 100644 --- a/drivers/scsi/scsi_transport_iscsi.c +++ b/drivers/scsi/scsi_transport_iscsi.c @@ -2964,7 +2964,7 @@ static int iscsi_if_ep_connect(struct iscsi_transport *transport, }
static int iscsi_if_ep_disconnect(struct iscsi_transport *transport, - u64 ep_handle) + u64 ep_handle, bool is_active) { struct iscsi_cls_conn *conn; struct iscsi_endpoint *ep; @@ -2981,6 +2981,8 @@ static int iscsi_if_ep_disconnect(struct iscsi_transport *transport, conn->ep = NULL; mutex_unlock(&conn->ep_mutex); conn->state = ISCSI_CONN_FAILED; + + transport->unbind_conn(conn, is_active); }
transport->ep_disconnect(ep); @@ -3012,7 +3014,8 @@ iscsi_if_transport_ep(struct iscsi_transport *transport, break; case ISCSI_UEVENT_TRANSPORT_EP_DISCONNECT: rc = iscsi_if_ep_disconnect(transport, - ev->u.ep_disconnect.ep_handle); + ev->u.ep_disconnect.ep_handle, + false); break; } return rc; @@ -3737,7 +3740,7 @@ iscsi_if_recv_msg(struct sk_buff *skb, struct nlmsghdr *nlh, uint32_t *group) conn = iscsi_conn_lookup(ev->u.b_conn.sid, ev->u.b_conn.cid);
if (conn && conn->ep) - iscsi_if_ep_disconnect(transport, conn->ep->id); + iscsi_if_ep_disconnect(transport, conn->ep->id, true);
if (!session || !conn) { err = -EINVAL; @@ -4656,6 +4659,7 @@ iscsi_register_transport(struct iscsi_transport *tt) int err;
BUG_ON(!tt); + WARN_ON(tt->ep_disconnect && !tt->unbind_conn);
priv = iscsi_if_transport_lookup(tt); if (priv) diff --git a/include/scsi/libiscsi.h b/include/scsi/libiscsi.h index 02f966e9358f..091f284bd6e9 100644 --- a/include/scsi/libiscsi.h +++ b/include/scsi/libiscsi.h @@ -424,6 +424,7 @@ extern int iscsi_conn_start(struct iscsi_cls_conn *); extern void iscsi_conn_stop(struct iscsi_cls_conn *, int); extern int iscsi_conn_bind(struct iscsi_cls_session *, struct iscsi_cls_conn *, int); +extern void iscsi_conn_unbind(struct iscsi_cls_conn *cls_conn, bool is_active); extern void iscsi_conn_failure(struct iscsi_conn *conn, enum iscsi_err err); extern void iscsi_session_failure(struct iscsi_session *session, enum iscsi_err err); diff --git a/include/scsi/scsi_transport_iscsi.h b/include/scsi/scsi_transport_iscsi.h index fc5a39839b4b..8874016b3c9a 100644 --- a/include/scsi/scsi_transport_iscsi.h +++ b/include/scsi/scsi_transport_iscsi.h @@ -82,6 +82,7 @@ struct iscsi_transport { void (*destroy_session) (struct iscsi_cls_session *session); struct iscsi_cls_conn *(*create_conn) (struct iscsi_cls_session *sess, uint32_t cid); + void (*unbind_conn) (struct iscsi_cls_conn *conn, bool is_active); int (*bind_conn) (struct iscsi_cls_session *session, struct iscsi_cls_conn *cls_conn, uint64_t transport_eph, int is_leading);
From: Mike Christie michael.christie@oracle.com
[ Upstream commit b1d19e8c92cfb0ded180ef3376c20e130414e067 ]
There are a couple places where we could free the iscsi_cls_conn while it's still in use. This adds some helpers to get/put a refcount on the struct and converts an exiting user. Subsequent commits will then use the helpers to fix 2 bugs in the eh code.
Link: https://lore.kernel.org/r/20210525181821.7617-11-michael.christie@oracle.com Reviewed-by: Lee Duncan lduncan@suse.com Signed-off-by: Mike Christie michael.christie@oracle.com Signed-off-by: Martin K. Petersen martin.petersen@oracle.com Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/scsi/libiscsi.c | 7 ++----- drivers/scsi/scsi_transport_iscsi.c | 12 ++++++++++++ include/scsi/scsi_transport_iscsi.h | 2 ++ 3 files changed, 16 insertions(+), 5 deletions(-)
diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c index 2aaf83678654..ab39d7f65bbb 100644 --- a/drivers/scsi/libiscsi.c +++ b/drivers/scsi/libiscsi.c @@ -1361,7 +1361,6 @@ void iscsi_session_failure(struct iscsi_session *session, enum iscsi_err err) { struct iscsi_conn *conn; - struct device *dev;
spin_lock_bh(&session->frwd_lock); conn = session->leadconn; @@ -1370,10 +1369,8 @@ void iscsi_session_failure(struct iscsi_session *session, return; }
- dev = get_device(&conn->cls_conn->dev); + iscsi_get_conn(conn->cls_conn); spin_unlock_bh(&session->frwd_lock); - if (!dev) - return; /* * if the host is being removed bypass the connection * recovery initialization because we are going to kill @@ -1383,7 +1380,7 @@ void iscsi_session_failure(struct iscsi_session *session, iscsi_conn_error_event(conn->cls_conn, err); else iscsi_conn_failure(conn, err); - put_device(dev); + iscsi_put_conn(conn->cls_conn); } EXPORT_SYMBOL_GPL(iscsi_session_failure);
diff --git a/drivers/scsi/scsi_transport_iscsi.c b/drivers/scsi/scsi_transport_iscsi.c index 82491343e94a..869cfc329da9 100644 --- a/drivers/scsi/scsi_transport_iscsi.c +++ b/drivers/scsi/scsi_transport_iscsi.c @@ -2348,6 +2348,18 @@ int iscsi_destroy_conn(struct iscsi_cls_conn *conn) } EXPORT_SYMBOL_GPL(iscsi_destroy_conn);
+void iscsi_put_conn(struct iscsi_cls_conn *conn) +{ + put_device(&conn->dev); +} +EXPORT_SYMBOL_GPL(iscsi_put_conn); + +void iscsi_get_conn(struct iscsi_cls_conn *conn) +{ + get_device(&conn->dev); +} +EXPORT_SYMBOL_GPL(iscsi_get_conn); + /* * iscsi interface functions */ diff --git a/include/scsi/scsi_transport_iscsi.h b/include/scsi/scsi_transport_iscsi.h index 8874016b3c9a..eb6ed499324d 100644 --- a/include/scsi/scsi_transport_iscsi.h +++ b/include/scsi/scsi_transport_iscsi.h @@ -435,6 +435,8 @@ extern void iscsi_remove_session(struct iscsi_cls_session *session); extern void iscsi_free_session(struct iscsi_cls_session *session); extern struct iscsi_cls_conn *iscsi_create_conn(struct iscsi_cls_session *sess, int dd_size, uint32_t cid); +extern void iscsi_put_conn(struct iscsi_cls_conn *conn); +extern void iscsi_get_conn(struct iscsi_cls_conn *conn); extern int iscsi_destroy_conn(struct iscsi_cls_conn *conn); extern void iscsi_unblock_session(struct iscsi_cls_session *session); extern void iscsi_block_session(struct iscsi_cls_session *session);
From: Mike Christie michael.christie@oracle.com
[ Upstream commit ec29d0ac29be366450a7faffbcf8cba3a6a3b506 ]
If we haven't done a unbind target call we can race where iscsi_conn_teardown wakes up the EH thread and then frees the conn while those threads are still accessing the conn ehwait.
We can only do one TMF per session so this just moves the TMF fields from the conn to the session. We can then rely on the iscsi_session_teardown->iscsi_remove_session->__iscsi_unbind_session call to remove the target and it's devices, and know after that point there is no device or scsi-ml callout trying to access the session.
Link: https://lore.kernel.org/r/20210525181821.7617-14-michael.christie@oracle.com Reviewed-by: Lee Duncan lduncan@suse.com Signed-off-by: Mike Christie michael.christie@oracle.com Signed-off-by: Martin K. Petersen martin.petersen@oracle.com Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/scsi/libiscsi.c | 115 +++++++++++++++++++--------------------- include/scsi/libiscsi.h | 11 ++-- 2 files changed, 60 insertions(+), 66 deletions(-)
diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c index ab39d7f65bbb..dfe906307e55 100644 --- a/drivers/scsi/libiscsi.c +++ b/drivers/scsi/libiscsi.c @@ -230,11 +230,11 @@ static int iscsi_prep_ecdb_ahs(struct iscsi_task *task) */ static int iscsi_check_tmf_restrictions(struct iscsi_task *task, int opcode) { - struct iscsi_conn *conn = task->conn; - struct iscsi_tm *tmf = &conn->tmhdr; + struct iscsi_session *session = task->conn->session; + struct iscsi_tm *tmf = &session->tmhdr; u64 hdr_lun;
- if (conn->tmf_state == TMF_INITIAL) + if (session->tmf_state == TMF_INITIAL) return 0;
if ((tmf->opcode & ISCSI_OPCODE_MASK) != ISCSI_OP_SCSI_TMFUNC) @@ -254,24 +254,19 @@ static int iscsi_check_tmf_restrictions(struct iscsi_task *task, int opcode) * Fail all SCSI cmd PDUs */ if (opcode != ISCSI_OP_SCSI_DATA_OUT) { - iscsi_conn_printk(KERN_INFO, conn, - "task [op %x itt " - "0x%x/0x%x] " - "rejected.\n", - opcode, task->itt, - task->hdr_itt); + iscsi_session_printk(KERN_INFO, session, + "task [op %x itt 0x%x/0x%x] rejected.\n", + opcode, task->itt, task->hdr_itt); return -EACCES; } /* * And also all data-out PDUs in response to R2T * if fast_abort is set. */ - if (conn->session->fast_abort) { - iscsi_conn_printk(KERN_INFO, conn, - "task [op %x itt " - "0x%x/0x%x] fast abort.\n", - opcode, task->itt, - task->hdr_itt); + if (session->fast_abort) { + iscsi_session_printk(KERN_INFO, session, + "task [op %x itt 0x%x/0x%x] fast abort.\n", + opcode, task->itt, task->hdr_itt); return -EACCES; } break; @@ -284,7 +279,7 @@ static int iscsi_check_tmf_restrictions(struct iscsi_task *task, int opcode) */ if (opcode == ISCSI_OP_SCSI_DATA_OUT && task->hdr_itt == tmf->rtt) { - ISCSI_DBG_SESSION(conn->session, + ISCSI_DBG_SESSION(session, "Preventing task %x/%x from sending " "data-out due to abort task in " "progress\n", task->itt, @@ -936,20 +931,21 @@ iscsi_data_in_rsp(struct iscsi_conn *conn, struct iscsi_hdr *hdr, static void iscsi_tmf_rsp(struct iscsi_conn *conn, struct iscsi_hdr *hdr) { struct iscsi_tm_rsp *tmf = (struct iscsi_tm_rsp *)hdr; + struct iscsi_session *session = conn->session;
conn->exp_statsn = be32_to_cpu(hdr->statsn) + 1; conn->tmfrsp_pdus_cnt++;
- if (conn->tmf_state != TMF_QUEUED) + if (session->tmf_state != TMF_QUEUED) return;
if (tmf->response == ISCSI_TMF_RSP_COMPLETE) - conn->tmf_state = TMF_SUCCESS; + session->tmf_state = TMF_SUCCESS; else if (tmf->response == ISCSI_TMF_RSP_NO_TASK) - conn->tmf_state = TMF_NOT_FOUND; + session->tmf_state = TMF_NOT_FOUND; else - conn->tmf_state = TMF_FAILED; - wake_up(&conn->ehwait); + session->tmf_state = TMF_FAILED; + wake_up(&session->ehwait); }
static int iscsi_send_nopout(struct iscsi_conn *conn, struct iscsi_nopin *rhdr) @@ -1826,15 +1822,14 @@ EXPORT_SYMBOL_GPL(iscsi_target_alloc);
static void iscsi_tmf_timedout(struct timer_list *t) { - struct iscsi_conn *conn = from_timer(conn, t, tmf_timer); - struct iscsi_session *session = conn->session; + struct iscsi_session *session = from_timer(session, t, tmf_timer);
spin_lock(&session->frwd_lock); - if (conn->tmf_state == TMF_QUEUED) { - conn->tmf_state = TMF_TIMEDOUT; + if (session->tmf_state == TMF_QUEUED) { + session->tmf_state = TMF_TIMEDOUT; ISCSI_DBG_EH(session, "tmf timedout\n"); /* unblock eh_abort() */ - wake_up(&conn->ehwait); + wake_up(&session->ehwait); } spin_unlock(&session->frwd_lock); } @@ -1857,8 +1852,8 @@ static int iscsi_exec_task_mgmt_fn(struct iscsi_conn *conn, return -EPERM; } conn->tmfcmd_pdus_cnt++; - conn->tmf_timer.expires = timeout * HZ + jiffies; - add_timer(&conn->tmf_timer); + session->tmf_timer.expires = timeout * HZ + jiffies; + add_timer(&session->tmf_timer); ISCSI_DBG_EH(session, "tmf set timeout\n");
spin_unlock_bh(&session->frwd_lock); @@ -1872,12 +1867,12 @@ static int iscsi_exec_task_mgmt_fn(struct iscsi_conn *conn, * 3) session is terminated or restarted or userspace has * given up on recovery */ - wait_event_interruptible(conn->ehwait, age != session->age || + wait_event_interruptible(session->ehwait, age != session->age || session->state != ISCSI_STATE_LOGGED_IN || - conn->tmf_state != TMF_QUEUED); + session->tmf_state != TMF_QUEUED); if (signal_pending(current)) flush_signals(current); - del_timer_sync(&conn->tmf_timer); + del_timer_sync(&session->tmf_timer);
mutex_lock(&session->eh_mutex); spin_lock_bh(&session->frwd_lock); @@ -2309,17 +2304,17 @@ int iscsi_eh_abort(struct scsi_cmnd *sc) }
/* only have one tmf outstanding at a time */ - if (conn->tmf_state != TMF_INITIAL) + if (session->tmf_state != TMF_INITIAL) goto failed; - conn->tmf_state = TMF_QUEUED; + session->tmf_state = TMF_QUEUED;
- hdr = &conn->tmhdr; + hdr = &session->tmhdr; iscsi_prep_abort_task_pdu(task, hdr);
if (iscsi_exec_task_mgmt_fn(conn, hdr, age, session->abort_timeout)) goto failed;
- switch (conn->tmf_state) { + switch (session->tmf_state) { case TMF_SUCCESS: spin_unlock_bh(&session->frwd_lock); /* @@ -2334,7 +2329,7 @@ int iscsi_eh_abort(struct scsi_cmnd *sc) */ spin_lock_bh(&session->frwd_lock); fail_scsi_task(task, DID_ABORT); - conn->tmf_state = TMF_INITIAL; + session->tmf_state = TMF_INITIAL; memset(hdr, 0, sizeof(*hdr)); spin_unlock_bh(&session->frwd_lock); iscsi_start_tx(conn); @@ -2345,7 +2340,7 @@ int iscsi_eh_abort(struct scsi_cmnd *sc) goto failed_unlocked; case TMF_NOT_FOUND: if (!sc->SCp.ptr) { - conn->tmf_state = TMF_INITIAL; + session->tmf_state = TMF_INITIAL; memset(hdr, 0, sizeof(*hdr)); /* task completed before tmf abort response */ ISCSI_DBG_EH(session, "sc completed while abort in " @@ -2354,7 +2349,7 @@ int iscsi_eh_abort(struct scsi_cmnd *sc) } fallthrough; default: - conn->tmf_state = TMF_INITIAL; + session->tmf_state = TMF_INITIAL; goto failed; }
@@ -2413,11 +2408,11 @@ int iscsi_eh_device_reset(struct scsi_cmnd *sc) conn = session->leadconn;
/* only have one tmf outstanding at a time */ - if (conn->tmf_state != TMF_INITIAL) + if (session->tmf_state != TMF_INITIAL) goto unlock; - conn->tmf_state = TMF_QUEUED; + session->tmf_state = TMF_QUEUED;
- hdr = &conn->tmhdr; + hdr = &session->tmhdr; iscsi_prep_lun_reset_pdu(sc, hdr);
if (iscsi_exec_task_mgmt_fn(conn, hdr, session->age, @@ -2426,7 +2421,7 @@ int iscsi_eh_device_reset(struct scsi_cmnd *sc) goto unlock; }
- switch (conn->tmf_state) { + switch (session->tmf_state) { case TMF_SUCCESS: break; case TMF_TIMEDOUT: @@ -2434,7 +2429,7 @@ int iscsi_eh_device_reset(struct scsi_cmnd *sc) iscsi_conn_failure(conn, ISCSI_ERR_SCSI_EH_SESSION_RST); goto done; default: - conn->tmf_state = TMF_INITIAL; + session->tmf_state = TMF_INITIAL; goto unlock; }
@@ -2446,7 +2441,7 @@ int iscsi_eh_device_reset(struct scsi_cmnd *sc) spin_lock_bh(&session->frwd_lock); memset(hdr, 0, sizeof(*hdr)); fail_scsi_tasks(conn, sc->device->lun, DID_ERROR); - conn->tmf_state = TMF_INITIAL; + session->tmf_state = TMF_INITIAL; spin_unlock_bh(&session->frwd_lock);
iscsi_start_tx(conn); @@ -2469,8 +2464,7 @@ void iscsi_session_recovery_timedout(struct iscsi_cls_session *cls_session) spin_lock_bh(&session->frwd_lock); if (session->state != ISCSI_STATE_LOGGED_IN) { session->state = ISCSI_STATE_RECOVERY_FAILED; - if (session->leadconn) - wake_up(&session->leadconn->ehwait); + wake_up(&session->ehwait); } spin_unlock_bh(&session->frwd_lock); } @@ -2515,7 +2509,7 @@ int iscsi_eh_session_reset(struct scsi_cmnd *sc) iscsi_conn_failure(conn, ISCSI_ERR_SCSI_EH_SESSION_RST);
ISCSI_DBG_EH(session, "wait for relogin\n"); - wait_event_interruptible(conn->ehwait, + wait_event_interruptible(session->ehwait, session->state == ISCSI_STATE_TERMINATE || session->state == ISCSI_STATE_LOGGED_IN || session->state == ISCSI_STATE_RECOVERY_FAILED); @@ -2576,11 +2570,11 @@ static int iscsi_eh_target_reset(struct scsi_cmnd *sc) conn = session->leadconn;
/* only have one tmf outstanding at a time */ - if (conn->tmf_state != TMF_INITIAL) + if (session->tmf_state != TMF_INITIAL) goto unlock; - conn->tmf_state = TMF_QUEUED; + session->tmf_state = TMF_QUEUED;
- hdr = &conn->tmhdr; + hdr = &session->tmhdr; iscsi_prep_tgt_reset_pdu(sc, hdr);
if (iscsi_exec_task_mgmt_fn(conn, hdr, session->age, @@ -2589,7 +2583,7 @@ static int iscsi_eh_target_reset(struct scsi_cmnd *sc) goto unlock; }
- switch (conn->tmf_state) { + switch (session->tmf_state) { case TMF_SUCCESS: break; case TMF_TIMEDOUT: @@ -2597,7 +2591,7 @@ static int iscsi_eh_target_reset(struct scsi_cmnd *sc) iscsi_conn_failure(conn, ISCSI_ERR_SCSI_EH_SESSION_RST); goto done; default: - conn->tmf_state = TMF_INITIAL; + session->tmf_state = TMF_INITIAL; goto unlock; }
@@ -2609,7 +2603,7 @@ static int iscsi_eh_target_reset(struct scsi_cmnd *sc) spin_lock_bh(&session->frwd_lock); memset(hdr, 0, sizeof(*hdr)); fail_scsi_tasks(conn, -1, DID_ERROR); - conn->tmf_state = TMF_INITIAL; + session->tmf_state = TMF_INITIAL; spin_unlock_bh(&session->frwd_lock);
iscsi_start_tx(conn); @@ -2939,7 +2933,10 @@ iscsi_session_setup(struct iscsi_transport *iscsit, struct Scsi_Host *shost, session->tt = iscsit; session->dd_data = cls_session->dd_data + sizeof(*session);
+ session->tmf_state = TMF_INITIAL; + timer_setup(&session->tmf_timer, iscsi_tmf_timedout, 0); mutex_init(&session->eh_mutex); + spin_lock_init(&session->frwd_lock); spin_lock_init(&session->back_lock);
@@ -3043,7 +3040,6 @@ iscsi_conn_setup(struct iscsi_cls_session *cls_session, int dd_size, conn->c_stage = ISCSI_CONN_INITIAL_STAGE; conn->id = conn_idx; conn->exp_statsn = 0; - conn->tmf_state = TMF_INITIAL;
timer_setup(&conn->transport_timer, iscsi_check_transport_timeouts, 0);
@@ -3068,8 +3064,7 @@ iscsi_conn_setup(struct iscsi_cls_session *cls_session, int dd_size, goto login_task_data_alloc_fail; conn->login_task->data = conn->data = data;
- timer_setup(&conn->tmf_timer, iscsi_tmf_timedout, 0); - init_waitqueue_head(&conn->ehwait); + init_waitqueue_head(&session->ehwait);
return cls_conn;
@@ -3104,7 +3099,7 @@ void iscsi_conn_teardown(struct iscsi_cls_conn *cls_conn) * leading connection? then give up on recovery. */ session->state = ISCSI_STATE_TERMINATE; - wake_up(&conn->ehwait); + wake_up(&session->ehwait); } spin_unlock_bh(&session->frwd_lock);
@@ -3179,7 +3174,7 @@ int iscsi_conn_start(struct iscsi_cls_conn *cls_conn) * commands after successful recovery */ conn->stop_stage = 0; - conn->tmf_state = TMF_INITIAL; + session->tmf_state = TMF_INITIAL; session->age++; if (session->age == 16) session->age = 0; @@ -3193,7 +3188,7 @@ int iscsi_conn_start(struct iscsi_cls_conn *cls_conn) spin_unlock_bh(&session->frwd_lock);
iscsi_unblock_session(session->cls_session); - wake_up(&conn->ehwait); + wake_up(&session->ehwait); return 0; } EXPORT_SYMBOL_GPL(iscsi_conn_start); @@ -3287,7 +3282,7 @@ void iscsi_conn_stop(struct iscsi_cls_conn *cls_conn, int flag) spin_lock_bh(&session->frwd_lock); fail_scsi_tasks(conn, -1, DID_TRANSPORT_DISRUPTED); fail_mgmt_tasks(session, conn); - memset(&conn->tmhdr, 0, sizeof(conn->tmhdr)); + memset(&session->tmhdr, 0, sizeof(session->tmhdr)); spin_unlock_bh(&session->frwd_lock); mutex_unlock(&session->eh_mutex); } diff --git a/include/scsi/libiscsi.h b/include/scsi/libiscsi.h index 091f284bd6e9..2bb452a8f134 100644 --- a/include/scsi/libiscsi.h +++ b/include/scsi/libiscsi.h @@ -195,12 +195,6 @@ struct iscsi_conn { unsigned long suspend_tx; /* suspend Tx */ unsigned long suspend_rx; /* suspend Rx */
- /* abort */ - wait_queue_head_t ehwait; /* used in eh_abort() */ - struct iscsi_tm tmhdr; - struct timer_list tmf_timer; - int tmf_state; /* see TMF_INITIAL, etc.*/ - /* negotiated params */ unsigned max_recv_dlength; /* initiator_max_recv_dsl*/ unsigned max_xmit_dlength; /* target_max_recv_dsl */ @@ -270,6 +264,11 @@ struct iscsi_session { * and recv lock. */ struct mutex eh_mutex; + /* abort */ + wait_queue_head_t ehwait; /* used in eh_abort() */ + struct iscsi_tm tmhdr; + struct timer_list tmf_timer; + int tmf_state; /* see TMF_INITIAL, etc.*/
/* iSCSI session-wide sequencing */ uint32_t cmdsn;
From: Mike Christie michael.christie@oracle.com
[ Upstream commit bdd4aad7ff92ae39c2e93c415bb6761cb8b584da ]
The iscsi offload drivers are setting the shost->max_id to the max number of sessions they support. The problem is that max_id is not the max number of targets but the highest identifier the targets can have. To use it to limit the number of targets we need to set it to max sessions - 1, or we can end up with a session we might not have preallocated resources for.
Link: https://lore.kernel.org/r/20210525181821.7617-15-michael.christie@oracle.com Reviewed-by: Lee Duncan lduncan@suse.com Signed-off-by: Mike Christie michael.christie@oracle.com Signed-off-by: Martin K. Petersen martin.petersen@oracle.com Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/scsi/be2iscsi/be_main.c | 4 ++-- drivers/scsi/bnx2i/bnx2i_iscsi.c | 2 +- drivers/scsi/cxgbi/libcxgbi.c | 4 ++-- drivers/scsi/qedi/qedi_main.c | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-)
diff --git a/drivers/scsi/be2iscsi/be_main.c b/drivers/scsi/be2iscsi/be_main.c index 27c4f1598f76..d941e1561527 100644 --- a/drivers/scsi/be2iscsi/be_main.c +++ b/drivers/scsi/be2iscsi/be_main.c @@ -416,7 +416,7 @@ static struct beiscsi_hba *beiscsi_hba_alloc(struct pci_dev *pcidev) "beiscsi_hba_alloc - iscsi_host_alloc failed\n"); return NULL; } - shost->max_id = BE2_MAX_SESSIONS; + shost->max_id = BE2_MAX_SESSIONS - 1; shost->max_channel = 0; shost->max_cmd_len = BEISCSI_MAX_CMD_LEN; shost->max_lun = BEISCSI_NUM_MAX_LUN; @@ -5318,7 +5318,7 @@ static int beiscsi_enable_port(struct beiscsi_hba *phba) /* Re-enable UER. If different TPE occurs then it is recoverable. */ beiscsi_set_uer_feature(phba);
- phba->shost->max_id = phba->params.cxns_per_ctrl; + phba->shost->max_id = phba->params.cxns_per_ctrl - 1; phba->shost->can_queue = phba->params.ios_per_ctrl; ret = beiscsi_init_port(phba); if (ret < 0) { diff --git a/drivers/scsi/bnx2i/bnx2i_iscsi.c b/drivers/scsi/bnx2i/bnx2i_iscsi.c index b6c1da46d582..197aca76a69d 100644 --- a/drivers/scsi/bnx2i/bnx2i_iscsi.c +++ b/drivers/scsi/bnx2i/bnx2i_iscsi.c @@ -791,7 +791,7 @@ struct bnx2i_hba *bnx2i_alloc_hba(struct cnic_dev *cnic) return NULL; shost->dma_boundary = cnic->pcidev->dma_mask; shost->transportt = bnx2i_scsi_xport_template; - shost->max_id = ISCSI_MAX_CONNS_PER_HBA; + shost->max_id = ISCSI_MAX_CONNS_PER_HBA - 1; shost->max_channel = 0; shost->max_lun = 512; shost->max_cmd_len = 16; diff --git a/drivers/scsi/cxgbi/libcxgbi.c b/drivers/scsi/cxgbi/libcxgbi.c index f078b3c4e083..ecb134b4699f 100644 --- a/drivers/scsi/cxgbi/libcxgbi.c +++ b/drivers/scsi/cxgbi/libcxgbi.c @@ -337,7 +337,7 @@ void cxgbi_hbas_remove(struct cxgbi_device *cdev) EXPORT_SYMBOL_GPL(cxgbi_hbas_remove);
int cxgbi_hbas_add(struct cxgbi_device *cdev, u64 max_lun, - unsigned int max_id, struct scsi_host_template *sht, + unsigned int max_conns, struct scsi_host_template *sht, struct scsi_transport_template *stt) { struct cxgbi_hba *chba; @@ -357,7 +357,7 @@ int cxgbi_hbas_add(struct cxgbi_device *cdev, u64 max_lun,
shost->transportt = stt; shost->max_lun = max_lun; - shost->max_id = max_id; + shost->max_id = max_conns - 1; shost->max_channel = 0; shost->max_cmd_len = SCSI_MAX_VARLEN_CDB_SIZE;
diff --git a/drivers/scsi/qedi/qedi_main.c b/drivers/scsi/qedi/qedi_main.c index 2455d1448a7e..edf915432704 100644 --- a/drivers/scsi/qedi/qedi_main.c +++ b/drivers/scsi/qedi/qedi_main.c @@ -640,7 +640,7 @@ static struct qedi_ctx *qedi_host_alloc(struct pci_dev *pdev) goto exit_setup_shost; }
- shost->max_id = QEDI_MAX_ISCSI_CONNS_PER_HBA; + shost->max_id = QEDI_MAX_ISCSI_CONNS_PER_HBA - 1; shost->max_channel = 0; shost->max_lun = ~0; shost->max_cmd_len = 16;
From: Mike Christie michael.christie@oracle.com
[ Upstream commit 5777b7f0f03ce49372203b6521631f62f2810c8f ]
If qedi_process_cmd_cleanup_resp finds the cmd it frees the work and sets list_tmf_work to NULL, so qedi_tmf_work should check if list_tmf_work is non-NULL when it wants to force cleanup.
Link: https://lore.kernel.org/r/20210525181821.7617-20-michael.christie@oracle.com Reviewed-by: Manish Rangankar mrangankar@marvell.com Signed-off-by: Mike Christie michael.christie@oracle.com Signed-off-by: Martin K. Petersen martin.petersen@oracle.com Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/scsi/qedi/qedi_fw.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/scsi/qedi/qedi_fw.c b/drivers/scsi/qedi/qedi_fw.c index 440ddd2309f1..cf57b4e49700 100644 --- a/drivers/scsi/qedi/qedi_fw.c +++ b/drivers/scsi/qedi/qedi_fw.c @@ -1453,7 +1453,7 @@ static void qedi_tmf_work(struct work_struct *work)
ldel_exit: spin_lock_bh(&qedi_conn->tmf_work_lock); - if (!qedi_cmd->list_tmf_work) { + if (qedi_cmd->list_tmf_work) { list_del_init(&list_work->list); qedi_cmd->list_tmf_work = NULL; kfree(list_work);
From: Mike Christie michael.christie@oracle.com
[ Upstream commit 2ce002366a3fcc3f9616d4583194f65dde0ad253 ]
If the SCSI cmd completes after qedi_tmf_work calls iscsi_itt_to_task then the qedi qedi_cmd->task_id could be freed and used for another cmd. If we then call qedi_iscsi_cleanup_task with that task_id we will be cleaning up the wrong cmd.
Wait to release the task_id until the last put has been done on the iscsi_task. Because libiscsi grabs a ref to the task when sending the abort, we know that for the non-abort timeout case that the task_id we are referencing is for the cmd that was supposed to be aborted.
A latter commit will fix the case where the abort times out while we are running qedi_tmf_work.
Link: https://lore.kernel.org/r/20210525181821.7617-21-michael.christie@oracle.com Reviewed-by: Manish Rangankar mrangankar@marvell.com Signed-off-by: Mike Christie michael.christie@oracle.com Signed-off-by: Martin K. Petersen martin.petersen@oracle.com Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/scsi/qedi/qedi_fw.c | 15 --------------- drivers/scsi/qedi/qedi_iscsi.c | 20 +++++++++++++++++--- 2 files changed, 17 insertions(+), 18 deletions(-)
diff --git a/drivers/scsi/qedi/qedi_fw.c b/drivers/scsi/qedi/qedi_fw.c index cf57b4e49700..c12bb2dd5ff9 100644 --- a/drivers/scsi/qedi/qedi_fw.c +++ b/drivers/scsi/qedi/qedi_fw.c @@ -73,7 +73,6 @@ static void qedi_process_logout_resp(struct qedi_ctx *qedi, spin_unlock(&qedi_conn->list_lock);
cmd->state = RESPONSE_RECEIVED; - qedi_clear_task_idx(qedi, cmd->task_id); __iscsi_complete_pdu(conn, (struct iscsi_hdr *)resp_hdr, NULL, 0);
spin_unlock(&session->back_lock); @@ -138,7 +137,6 @@ static void qedi_process_text_resp(struct qedi_ctx *qedi, spin_unlock(&qedi_conn->list_lock);
cmd->state = RESPONSE_RECEIVED; - qedi_clear_task_idx(qedi, cmd->task_id);
__iscsi_complete_pdu(conn, (struct iscsi_hdr *)resp_hdr_ptr, qedi_conn->gen_pdu.resp_buf, @@ -164,13 +162,11 @@ static void qedi_tmf_resp_work(struct work_struct *work) iscsi_block_session(session->cls_session); rval = qedi_cleanup_all_io(qedi, qedi_conn, qedi_cmd->task, true); if (rval) { - qedi_clear_task_idx(qedi, qedi_cmd->task_id); iscsi_unblock_session(session->cls_session); goto exit_tmf_resp; }
iscsi_unblock_session(session->cls_session); - qedi_clear_task_idx(qedi, qedi_cmd->task_id);
spin_lock(&session->back_lock); __iscsi_complete_pdu(conn, (struct iscsi_hdr *)resp_hdr_ptr, NULL, 0); @@ -245,8 +241,6 @@ static void qedi_process_tmf_resp(struct qedi_ctx *qedi, goto unblock_sess; }
- qedi_clear_task_idx(qedi, qedi_cmd->task_id); - __iscsi_complete_pdu(conn, (struct iscsi_hdr *)resp_hdr_ptr, NULL, 0); kfree(resp_hdr_ptr);
@@ -314,7 +308,6 @@ static void qedi_process_login_resp(struct qedi_ctx *qedi, "Freeing tid=0x%x for cid=0x%x\n", cmd->task_id, qedi_conn->iscsi_conn_id); cmd->state = RESPONSE_RECEIVED; - qedi_clear_task_idx(qedi, cmd->task_id); }
static void qedi_get_rq_bdq_buf(struct qedi_ctx *qedi, @@ -468,7 +461,6 @@ static int qedi_process_nopin_mesg(struct qedi_ctx *qedi, }
spin_unlock(&qedi_conn->list_lock); - qedi_clear_task_idx(qedi, cmd->task_id); }
done: @@ -673,7 +665,6 @@ static void qedi_scsi_completion(struct qedi_ctx *qedi, if (qedi_io_tracing) qedi_trace_io(qedi, task, cmd->task_id, QEDI_IO_TRACE_RSP);
- qedi_clear_task_idx(qedi, cmd->task_id); __iscsi_complete_pdu(conn, (struct iscsi_hdr *)hdr, conn->data, datalen); error: @@ -730,7 +721,6 @@ static void qedi_process_nopin_local_cmpl(struct qedi_ctx *qedi, cqe->itid, cmd->task_id);
cmd->state = RESPONSE_RECEIVED; - qedi_clear_task_idx(qedi, cmd->task_id);
spin_lock_bh(&session->back_lock); __iscsi_put_task(task); @@ -748,7 +738,6 @@ static void qedi_process_cmd_cleanup_resp(struct qedi_ctx *qedi, itt_t protoitt = 0; int found = 0; struct qedi_cmd *qedi_cmd = NULL; - u32 rtid = 0; u32 iscsi_cid; struct qedi_conn *qedi_conn; struct qedi_cmd *dbg_cmd; @@ -779,7 +768,6 @@ static void qedi_process_cmd_cleanup_resp(struct qedi_ctx *qedi, found = 1; mtask = qedi_cmd->task; tmf_hdr = (struct iscsi_tm *)mtask->hdr; - rtid = work->rtid;
list_del_init(&work->list); kfree(work); @@ -821,8 +809,6 @@ static void qedi_process_cmd_cleanup_resp(struct qedi_ctx *qedi, if (qedi_cmd->state == CLEANUP_WAIT_FAILED) qedi_cmd->state = CLEANUP_RECV;
- qedi_clear_task_idx(qedi_conn->qedi, rtid); - spin_lock(&qedi_conn->list_lock); if (likely(dbg_cmd->io_cmd_in_list)) { dbg_cmd->io_cmd_in_list = false; @@ -856,7 +842,6 @@ static void qedi_process_cmd_cleanup_resp(struct qedi_ctx *qedi, QEDI_INFO(&qedi->dbg_ctx, QEDI_LOG_TID, "Freeing tid=0x%x for cid=0x%x\n", cqe->itid, qedi_conn->iscsi_conn_id); - qedi_clear_task_idx(qedi_conn->qedi, cqe->itid);
} else { qedi_get_proto_itt(qedi, cqe->itid, &ptmp_itt); diff --git a/drivers/scsi/qedi/qedi_iscsi.c b/drivers/scsi/qedi/qedi_iscsi.c index ef16537c523c..a7003847bd4c 100644 --- a/drivers/scsi/qedi/qedi_iscsi.c +++ b/drivers/scsi/qedi/qedi_iscsi.c @@ -772,7 +772,6 @@ static int qedi_mtask_xmit(struct iscsi_conn *conn, struct iscsi_task *task) }
cmd->conn = conn->dd_data; - cmd->scsi_cmd = NULL; return qedi_iscsi_send_generic_request(task); }
@@ -783,6 +782,10 @@ static int qedi_task_xmit(struct iscsi_task *task) struct qedi_cmd *cmd = task->dd_data; struct scsi_cmnd *sc = task->sc;
+ /* Clear now so in cleanup_task we know it didn't make it */ + cmd->scsi_cmd = NULL; + cmd->task_id = U16_MAX; + if (test_bit(QEDI_IN_SHUTDOWN, &qedi_conn->qedi->flags)) return -ENODEV;
@@ -1383,13 +1386,24 @@ static umode_t qedi_attr_is_visible(int param_type, int param)
static void qedi_cleanup_task(struct iscsi_task *task) { - if (!task->sc || task->state == ISCSI_TASK_PENDING) { + struct qedi_cmd *cmd; + + if (task->state == ISCSI_TASK_PENDING) { QEDI_INFO(NULL, QEDI_LOG_IO, "Returning ref_cnt=%d\n", refcount_read(&task->refcount)); return; }
- qedi_iscsi_unmap_sg_list(task->dd_data); + if (task->sc) + qedi_iscsi_unmap_sg_list(task->dd_data); + + cmd = task->dd_data; + if (cmd->task_id != U16_MAX) + qedi_clear_task_idx(iscsi_host_priv(task->conn->session->host), + cmd->task_id); + + cmd->task_id = U16_MAX; + cmd->scsi_cmd = NULL; }
struct iscsi_transport qedi_iscsi_transport = {
From: Mike Christie michael.christie@oracle.com
[ Upstream commit 2819b4ae2873d50fd55292877b0231ec936c3b2e ]
Drivers shouldn't be calling block/unblock session for tmf handling because the functions can change the session state from under libiscsi. iscsi_queuecommand's call to iscsi_prep_scsi_cmd_pdu-> iscsi_check_tmf_restrictions will prevent new cmds from being sent to qedi after we've started handling a TMF. So we don't need to try and block it in the driver, and we can remove these block calls.
Link: https://lore.kernel.org/r/20210525181821.7617-25-michael.christie@oracle.com Reviewed-by: Manish Rangankar mrangankar@marvell.com Signed-off-by: Mike Christie michael.christie@oracle.com Signed-off-by: Martin K. Petersen martin.petersen@oracle.com Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/scsi/qedi/qedi_fw.c | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-)
diff --git a/drivers/scsi/qedi/qedi_fw.c b/drivers/scsi/qedi/qedi_fw.c index c12bb2dd5ff9..4c87640e6a91 100644 --- a/drivers/scsi/qedi/qedi_fw.c +++ b/drivers/scsi/qedi/qedi_fw.c @@ -159,14 +159,9 @@ static void qedi_tmf_resp_work(struct work_struct *work) set_bit(QEDI_CONN_FW_CLEANUP, &qedi_conn->flags); resp_hdr_ptr = (struct iscsi_tm_rsp *)qedi_cmd->tmf_resp_buf;
- iscsi_block_session(session->cls_session); rval = qedi_cleanup_all_io(qedi, qedi_conn, qedi_cmd->task, true); - if (rval) { - iscsi_unblock_session(session->cls_session); + if (rval) goto exit_tmf_resp; - } - - iscsi_unblock_session(session->cls_session);
spin_lock(&session->back_lock); __iscsi_complete_pdu(conn, (struct iscsi_hdr *)resp_hdr_ptr, NULL, 0);
From: Mike Christie michael.christie@oracle.com
[ Upstream commit 0c72191da68638a479602dd515b587ada913184a ]
Drivers shouldn't be calling block/unblock session for cmd cleanup because the functions can change the session state from under libiscsi. This adds a new a driver level bit so it can block all I/O the host while it drains the card.
Link: https://lore.kernel.org/r/20210525181821.7617-26-michael.christie@oracle.com Reviewed-by: Manish Rangankar mrangankar@marvell.com Signed-off-by: Mike Christie michael.christie@oracle.com Signed-off-by: Martin K. Petersen martin.petersen@oracle.com Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/scsi/qedi/qedi.h | 1 + drivers/scsi/qedi/qedi_iscsi.c | 17 +++++++++++++++-- 2 files changed, 16 insertions(+), 2 deletions(-)
diff --git a/drivers/scsi/qedi/qedi.h b/drivers/scsi/qedi/qedi.h index c342defc3f52..ce199a7a16b8 100644 --- a/drivers/scsi/qedi/qedi.h +++ b/drivers/scsi/qedi/qedi.h @@ -284,6 +284,7 @@ struct qedi_ctx { #define QEDI_IN_RECOVERY 5 #define QEDI_IN_OFFLINE 6 #define QEDI_IN_SHUTDOWN 7 +#define QEDI_BLOCK_IO 8
u8 mac[ETH_ALEN]; u32 src_ip[4]; diff --git a/drivers/scsi/qedi/qedi_iscsi.c b/drivers/scsi/qedi/qedi_iscsi.c index a7003847bd4c..8f8036ae9a56 100644 --- a/drivers/scsi/qedi/qedi_iscsi.c +++ b/drivers/scsi/qedi/qedi_iscsi.c @@ -330,12 +330,22 @@ qedi_conn_create(struct iscsi_cls_session *cls_session, uint32_t cid)
void qedi_mark_device_missing(struct iscsi_cls_session *cls_session) { - iscsi_block_session(cls_session); + struct iscsi_session *session = cls_session->dd_data; + struct qedi_conn *qedi_conn = session->leadconn->dd_data; + + spin_lock_bh(&session->frwd_lock); + set_bit(QEDI_BLOCK_IO, &qedi_conn->qedi->flags); + spin_unlock_bh(&session->frwd_lock); }
void qedi_mark_device_available(struct iscsi_cls_session *cls_session) { - iscsi_unblock_session(cls_session); + struct iscsi_session *session = cls_session->dd_data; + struct qedi_conn *qedi_conn = session->leadconn->dd_data; + + spin_lock_bh(&session->frwd_lock); + clear_bit(QEDI_BLOCK_IO, &qedi_conn->qedi->flags); + spin_unlock_bh(&session->frwd_lock); }
static int qedi_bind_conn_to_iscsi_cid(struct qedi_ctx *qedi, @@ -789,6 +799,9 @@ static int qedi_task_xmit(struct iscsi_task *task) if (test_bit(QEDI_IN_SHUTDOWN, &qedi_conn->qedi->flags)) return -ENODEV;
+ if (test_bit(QEDI_BLOCK_IO, &qedi_conn->qedi->flags)) + return -EACCES; + cmd->state = 0; cmd->task = NULL; cmd->use_slowpath = false;
From: Zou Wei zou_wei@huawei.com
[ Upstream commit 4700ef326556ed74aba188f12396740a8c1c21dd ]
This patch adds/modifies MODULE_DEVICE_TABLE definition which generates correct modalias for automatic loading of this driver when it is built as an external module.
Reported-by: Hulk Robot hulkci@huawei.com Signed-off-by: Zou Wei zou_wei@huawei.com Signed-off-by: Lee Jones lee.jones@linaro.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/mfd/da9052-i2c.c | 1 + drivers/mfd/stmpe-i2c.c | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-)
diff --git a/drivers/mfd/da9052-i2c.c b/drivers/mfd/da9052-i2c.c index 47556d2d9abe..8ebfc7bbe4e0 100644 --- a/drivers/mfd/da9052-i2c.c +++ b/drivers/mfd/da9052-i2c.c @@ -113,6 +113,7 @@ static const struct i2c_device_id da9052_i2c_id[] = { {"da9053-bc", DA9053_BC}, {} }; +MODULE_DEVICE_TABLE(i2c, da9052_i2c_id);
#ifdef CONFIG_OF static const struct of_device_id dialog_dt_ids[] = { diff --git a/drivers/mfd/stmpe-i2c.c b/drivers/mfd/stmpe-i2c.c index 61aa020199f5..cd2f45257dc1 100644 --- a/drivers/mfd/stmpe-i2c.c +++ b/drivers/mfd/stmpe-i2c.c @@ -109,7 +109,7 @@ static const struct i2c_device_id stmpe_i2c_id[] = { { "stmpe2403", STMPE2403 }, { } }; -MODULE_DEVICE_TABLE(i2c, stmpe_id); +MODULE_DEVICE_TABLE(i2c, stmpe_i2c_id);
static struct i2c_driver stmpe_i2c_driver = { .driver = {
From: Tony Lindgren tony@atomide.com
[ Upstream commit 0b7cbe811ca524295ea43d9a4d73d3427e419c54 ]
We have started to get a bunch of pointless dmamask not set warnings that makes the output of dmesg -l err,warn hard to read with many extra warnings:
cpcap-regulator cpcap-regulator.0: DMA mask not set cpcap_adc cpcap_adc.0: DMA mask not set cpcap_battery cpcap_battery.0: DMA mask not set cpcap-charger cpcap-charger.0: DMA mask not set cpcap-pwrbutton cpcap-pwrbutton.0: DMA mask not set cpcap-led cpcap-led.0: DMA mask not set cpcap-led cpcap-led.1: DMA mask not set cpcap-led cpcap-led.2: DMA mask not set cpcap-led cpcap-led.3: DMA mask not set cpcap-led cpcap-led.4: DMA mask not set cpcap-rtc cpcap-rtc.0: DMA mask not set cpcap-usb-phy cpcap-usb-phy.0: DMA mask not set
This seems to have started with commit 4d8bde883bfb ("OF: Don't set default coherent DMA mask"). We have the parent SPI controller use DMA, while CPCAP driver and it's children do not. For audio, the DMA is handled over I2S bus with the McBSP driver.
Cc: Carl Philipp Klemm philipp@uvos.xyz Cc: Ivan Jelincic parazyd@dyne.org Cc: Merlijn Wajer merlijn@wizzup.org Cc: Pavel Machek pavel@ucw.cz Cc: Sebastian Reichel sre@kernel.org Cc: Sicelo A. Mhlongo absicsz@gmail.com Signed-off-by: Tony Lindgren tony@atomide.com Signed-off-by: Lee Jones lee.jones@linaro.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/mfd/motorola-cpcap.c | 4 ++++ 1 file changed, 4 insertions(+)
diff --git a/drivers/mfd/motorola-cpcap.c b/drivers/mfd/motorola-cpcap.c index 30d82bfe5b02..6fb206da2729 100644 --- a/drivers/mfd/motorola-cpcap.c +++ b/drivers/mfd/motorola-cpcap.c @@ -327,6 +327,10 @@ static int cpcap_probe(struct spi_device *spi) if (ret) return ret;
+ /* Parent SPI controller uses DMA, CPCAP and child devices do not */ + spi->dev.coherent_dma_mask = 0; + spi->dev.dma_mask = &spi->dev.coherent_dma_mask; + return devm_mfd_add_devices(&spi->dev, 0, cpcap_mfd_devices, ARRAY_SIZE(cpcap_mfd_devices), NULL, 0, NULL); }
From: Eli Billauer eli.billauer@gmail.com
[ Upstream commit 1b1ee3a91d21fdf7d415c1060db1a7a07ae296b6 ]
As Xillybus' configuration symbol hierarchy has been reorganized recently, the correct condition for compiling the xillybus/ subdirectory is now CONFIG_XILLYBUS_CLASS, and not CONFIG_XILLYBUS.
Reported-by: Greg Kroah-Hartman gregkh@linuxfoundation.org Signed-off-by: Eli Billauer eli.billauer@gmail.com Link: https://lore.kernel.org/r/20210528092242.51104-1-eli.billauer@gmail.com Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/char/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/char/Makefile b/drivers/char/Makefile index ffce287ef415..c7e4fc733a37 100644 --- a/drivers/char/Makefile +++ b/drivers/char/Makefile @@ -44,6 +44,6 @@ obj-$(CONFIG_TCG_TPM) += tpm/
obj-$(CONFIG_PS3_FLASH) += ps3flash.o
-obj-$(CONFIG_XILLYBUS) += xillybus/ +obj-$(CONFIG_XILLYBUS_CLASS) += xillybus/ obj-$(CONFIG_POWERNV_OP_PANEL) += powernv-op-panel.o obj-$(CONFIG_ADI) += adi.o
Hello Sasha,
Thanks for trying, but this is a NACK.
On 10/07/21 05:16, Sasha Levin wrote:
diff --git a/drivers/char/Makefile b/drivers/char/Makefile index ffce287ef415..c7e4fc733a37 100644 --- a/drivers/char/Makefile +++ b/drivers/char/Makefile @@ -44,6 +44,6 @@ obj-$(CONFIG_TCG_TPM) += tpm/
obj-$(CONFIG_PS3_FLASH) += ps3flash.o
-obj-$(CONFIG_XILLYBUS) += xillybus/ +obj-$(CONFIG_XILLYBUS_CLASS) += xillybus/ obj-$(CONFIG_POWERNV_OP_PANEL) += powernv-op-panel.o
CONFIG_XILLYBUS_CLASS will be introduced in v5.14, so backporting this commit will break the kernel's build.
Since this patch was created for three kernel versions, I'm repeating this response on all three, just be sure. Hope I'm not being annoying.
Eli
On Sat, Jul 10, 2021 at 08:17:07AM +0300, Eli Billauer wrote:
Hello Sasha,
Thanks for trying, but this is a NACK.
On 10/07/21 05:16, Sasha Levin wrote:
diff --git a/drivers/char/Makefile b/drivers/char/Makefile index ffce287ef415..c7e4fc733a37 100644 --- a/drivers/char/Makefile +++ b/drivers/char/Makefile @@ -44,6 +44,6 @@ obj-$(CONFIG_TCG_TPM) += tpm/
obj-$(CONFIG_PS3_FLASH) += ps3flash.o
-obj-$(CONFIG_XILLYBUS) += xillybus/ +obj-$(CONFIG_XILLYBUS_CLASS) += xillybus/ obj-$(CONFIG_POWERNV_OP_PANEL) += powernv-op-panel.o
CONFIG_XILLYBUS_CLASS will be introduced in v5.14, so backporting this commit will break the kernel's build.
Since this patch was created for three kernel versions, I'm repeating this response on all three, just be sure. Hope I'm not being annoying.
I'll drop it everywhere, thanks!
From: Yufen Yu yuyufen@huawei.com
[ Upstream commit 81aad47278539f02de808bcc8251fed0ad3d6f55 ]
pm_runtime_get_sync will increment pm usage counter even it failed. Forgetting to putting operation will result in reference leak here. Fix it by replacing it with pm_runtime_resume_and_get to keep usage counter balanced.
Reported-by: Hulk Robot hulkci@huawei.com Signed-off-by: Yufen Yu yuyufen@huawei.com Link: https://lore.kernel.org/r/20210524093521.612176-1-yuyufen@huawei.com Signed-off-by: Mark Brown broonie@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- sound/soc/img/img-i2s-in.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/sound/soc/img/img-i2s-in.c b/sound/soc/img/img-i2s-in.c index 0843235d73c9..fd3432a1d6ab 100644 --- a/sound/soc/img/img-i2s-in.c +++ b/sound/soc/img/img-i2s-in.c @@ -464,7 +464,7 @@ static int img_i2s_in_probe(struct platform_device *pdev) if (ret) goto err_pm_disable; } - ret = pm_runtime_get_sync(&pdev->dev); + ret = pm_runtime_resume_and_get(&pdev->dev); if (ret < 0) goto err_suspend;
From: Al Viro viro@zeniv.linux.org.uk
[ Upstream commit 3b3fc051cd2cba42bf736fa62780857d251a1236 ]
asking to advance by more than we have left in the iov_iter should move to the very end; it should *not* leave negative i->count and it should not spew into syslog, etc. - it's a legitimate operation.
Signed-off-by: Al Viro viro@zeniv.linux.org.uk Signed-off-by: Sasha Levin sashal@kernel.org --- lib/iov_iter.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-)
diff --git a/lib/iov_iter.c b/lib/iov_iter.c index c701b7a187f2..82a889283eca 100644 --- a/lib/iov_iter.c +++ b/lib/iov_iter.c @@ -1092,8 +1092,6 @@ static inline void pipe_truncate(struct iov_iter *i) static void pipe_advance(struct iov_iter *i, size_t size) { struct pipe_inode_info *pipe = i->pipe; - if (unlikely(i->count < size)) - size = i->count; if (size) { struct pipe_buffer *buf; unsigned int p_mask = pipe->ring_size - 1; @@ -1134,6 +1132,8 @@ static void iov_iter_bvec_advance(struct iov_iter *i, size_t size)
void iov_iter_advance(struct iov_iter *i, size_t size) { + if (unlikely(i->count < size)) + size = i->count; if (unlikely(iov_iter_is_pipe(i))) { pipe_advance(i, size); return; @@ -1143,7 +1143,6 @@ void iov_iter_advance(struct iov_iter *i, size_t size) return; } if (unlikely(iov_iter_is_xarray(i))) { - size = min(size, i->count); i->iov_offset += size; i->count -= size; return;
From: Zou Wei zou_wei@huawei.com
[ Upstream commit 19a52178125c1e8b84444d85f2ce34c0964b4a91 ]
This patch adds missing MODULE_DEVICE_TABLE definition which generates correct modalias for automatic loading of this driver when it is built as an external module.
Reported-by: Hulk Robot hulkci@huawei.com Signed-off-by: Zou Wei zou_wei@huawei.com Link: https://lore.kernel.org/r/1620896249-52769-1-git-send-email-zou_wei@huawei.c... Signed-off-by: Joel Stanley joel@jms.id.au Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/fsi/fsi-master-aspeed.c | 1 + drivers/fsi/fsi-master-ast-cf.c | 1 + drivers/fsi/fsi-master-gpio.c | 1 + drivers/fsi/fsi-occ.c | 1 + 4 files changed, 4 insertions(+)
diff --git a/drivers/fsi/fsi-master-aspeed.c b/drivers/fsi/fsi-master-aspeed.c index 90dbe58ca1ed..dbad73162c83 100644 --- a/drivers/fsi/fsi-master-aspeed.c +++ b/drivers/fsi/fsi-master-aspeed.c @@ -645,6 +645,7 @@ static const struct of_device_id fsi_master_aspeed_match[] = { { .compatible = "aspeed,ast2600-fsi-master" }, { }, }; +MODULE_DEVICE_TABLE(of, fsi_master_aspeed_match);
static struct platform_driver fsi_master_aspeed_driver = { .driver = { diff --git a/drivers/fsi/fsi-master-ast-cf.c b/drivers/fsi/fsi-master-ast-cf.c index 57a779a89b07..70c03e304d6c 100644 --- a/drivers/fsi/fsi-master-ast-cf.c +++ b/drivers/fsi/fsi-master-ast-cf.c @@ -1427,6 +1427,7 @@ static const struct of_device_id fsi_master_acf_match[] = { { .compatible = "aspeed,ast2500-cf-fsi-master" }, { }, }; +MODULE_DEVICE_TABLE(of, fsi_master_acf_match);
static struct platform_driver fsi_master_acf = { .driver = { diff --git a/drivers/fsi/fsi-master-gpio.c b/drivers/fsi/fsi-master-gpio.c index aa97c4a250cb..7d5f29b4b595 100644 --- a/drivers/fsi/fsi-master-gpio.c +++ b/drivers/fsi/fsi-master-gpio.c @@ -882,6 +882,7 @@ static const struct of_device_id fsi_master_gpio_match[] = { { .compatible = "fsi-master-gpio" }, { }, }; +MODULE_DEVICE_TABLE(of, fsi_master_gpio_match);
static struct platform_driver fsi_master_gpio_driver = { .driver = { diff --git a/drivers/fsi/fsi-occ.c b/drivers/fsi/fsi-occ.c index 10ca2e290655..f9a88083e5f3 100644 --- a/drivers/fsi/fsi-occ.c +++ b/drivers/fsi/fsi-occ.c @@ -635,6 +635,7 @@ static const struct of_device_id occ_match[] = { }, { }, }; +MODULE_DEVICE_TABLE(of, occ_match);
static struct platform_driver occ_driver = { .driver = {
From: Daniel Mack daniel@zonque.org
[ Upstream commit d157fca711ad42e75efef3444c83d2e1a17be27a ]
Remove the hack to assign the global console_port variable at probe time. This assumption that cons->index is -1 is wrong for systems that specify 'console=' in the cmdline (or 'stdout-path' in dts). Hence, on such system the actual console assignment is ignored, and the first UART that happens to be probed is used as console instead.
Move the logic to console_setup() and map the console to the correct port through the array of available ports instead.
Signed-off-by: Daniel Mack daniel@zonque.org Link: https://lore.kernel.org/r/20210528133321.1859346-1-daniel@zonque.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/tty/serial/uartlite.c | 27 ++++++--------------------- 1 file changed, 6 insertions(+), 21 deletions(-)
diff --git a/drivers/tty/serial/uartlite.c b/drivers/tty/serial/uartlite.c index f42ccc40ffa6..a5f15f22d9ef 100644 --- a/drivers/tty/serial/uartlite.c +++ b/drivers/tty/serial/uartlite.c @@ -505,21 +505,23 @@ static void ulite_console_write(struct console *co, const char *s,
static int ulite_console_setup(struct console *co, char *options) { - struct uart_port *port; + struct uart_port *port = NULL; int baud = 9600; int bits = 8; int parity = 'n'; int flow = 'n';
- - port = console_port; + if (co->index >= 0 && co->index < ULITE_NR_UARTS) + port = ulite_ports + co->index;
/* Has the device been initialized yet? */ - if (!port->mapbase) { + if (!port || !port->mapbase) { pr_debug("console on ttyUL%i not present\n", co->index); return -ENODEV; }
+ console_port = port; + /* not initialized yet? */ if (!port->membase) { if (ulite_request_port(port)) @@ -655,17 +657,6 @@ static int ulite_assign(struct device *dev, int id, u32 base, int irq,
dev_set_drvdata(dev, port);
-#ifdef CONFIG_SERIAL_UARTLITE_CONSOLE - /* - * If console hasn't been found yet try to assign this port - * because it is required to be assigned for console setup function. - * If register_console() don't assign value, then console_port pointer - * is cleanup. - */ - if (ulite_uart_driver.cons->index == -1) - console_port = port; -#endif - /* Register the port */ rc = uart_add_one_port(&ulite_uart_driver, port); if (rc) { @@ -675,12 +666,6 @@ static int ulite_assign(struct device *dev, int id, u32 base, int irq, return rc; }
-#ifdef CONFIG_SERIAL_UARTLITE_CONSOLE - /* This is not port which is used for console that's why clean it up */ - if (ulite_uart_driver.cons->index == -1) - console_port = NULL; -#endif - return 0; }
From: Valentin Vidic vvidic@valentin-vidic.from.hr
[ Upstream commit b7d91d230a119fdcc334d10c9889ce9c5e15118b ]
Console name reported in /proc/consoles:
ttyS1 -W- (EC p ) 4:65
does not match the char device name:
crw--w---- 1 root root 4, 65 May 17 12:18 /dev/ttysclp0
so debian-installer inside a QEMU s390x instance gets confused and fails to start with the following error:
steal-ctty: No such file or directory
Signed-off-by: Valentin Vidic vvidic@valentin-vidic.from.hr Link: https://lore.kernel.org/r/20210427194010.9330-1-vvidic@valentin-vidic.from.h... Signed-off-by: Christian Borntraeger borntraeger@de.ibm.com Signed-off-by: Vasily Gorbik gor@linux.ibm.com Signed-off-by: Sasha Levin sashal@kernel.org --- arch/s390/kernel/setup.c | 2 +- drivers/s390/char/sclp_vt220.c | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/arch/s390/kernel/setup.c b/arch/s390/kernel/setup.c index 5aab59ad5688..248d134a0592 100644 --- a/arch/s390/kernel/setup.c +++ b/arch/s390/kernel/setup.c @@ -165,7 +165,7 @@ static void __init set_preferred_console(void) else if (CONSOLE_IS_3270) add_preferred_console("tty3270", 0, NULL); else if (CONSOLE_IS_VT220) - add_preferred_console("ttyS", 1, NULL); + add_preferred_console("ttysclp", 0, NULL); else if (CONSOLE_IS_HVC) add_preferred_console("hvc", 0, NULL); } diff --git a/drivers/s390/char/sclp_vt220.c b/drivers/s390/char/sclp_vt220.c index 7f4445b0f819..2f96c31e9b7b 100644 --- a/drivers/s390/char/sclp_vt220.c +++ b/drivers/s390/char/sclp_vt220.c @@ -35,8 +35,8 @@ #define SCLP_VT220_MINOR 65 #define SCLP_VT220_DRIVER_NAME "sclp_vt220" #define SCLP_VT220_DEVICE_NAME "ttysclp" -#define SCLP_VT220_CONSOLE_NAME "ttyS" -#define SCLP_VT220_CONSOLE_INDEX 1 /* console=ttyS1 */ +#define SCLP_VT220_CONSOLE_NAME "ttysclp" +#define SCLP_VT220_CONSOLE_INDEX 0 /* console=ttysclp0 */
/* Representation of a single write request */ struct sclp_vt220_request {
From: Fabrice Fontaine fontaine.fabrice@gmail.com
[ Upstream commit 42e8d652438f5ddf04e5dac299cb5e623d113dc0 ]
Though -nostdlib is passed in PURGATORY_LDFLAGS and -ffreestanding in KBUILD_CFLAGS_DECOMPRESSOR, -fno-stack-protector must also be passed to avoid linking errors related to undefined references to '__stack_chk_guard' and '__stack_chk_fail' if toolchain enforces -fstack-protector.
Fixes - https://gitlab.com/kubu93/buildroot/-/jobs/1247043361
Signed-off-by: Fabrice Fontaine fontaine.fabrice@gmail.com Signed-off-by: Vasily Gorbik gor@linux.ibm.com Reviewed-by: Alexander Egorenkov egorenar@linux.ibm.com Tested-by: Alexander Egorenkov egorenar@linux.ibm.com Link: https://lore.kernel.org/r/20210510053133.1220167-1-fontaine.fabrice@gmail.co... Signed-off-by: Vasily Gorbik gor@linux.ibm.com Signed-off-by: Sasha Levin sashal@kernel.org --- arch/s390/Makefile | 1 + arch/s390/purgatory/Makefile | 1 + 2 files changed, 2 insertions(+)
diff --git a/arch/s390/Makefile b/arch/s390/Makefile index e443ed9947bd..098abe3a56f3 100644 --- a/arch/s390/Makefile +++ b/arch/s390/Makefile @@ -28,6 +28,7 @@ KBUILD_CFLAGS_DECOMPRESSOR += -DDISABLE_BRANCH_PROFILING -D__NO_FORTIFY KBUILD_CFLAGS_DECOMPRESSOR += -fno-delete-null-pointer-checks -msoft-float -mbackchain KBUILD_CFLAGS_DECOMPRESSOR += -fno-asynchronous-unwind-tables KBUILD_CFLAGS_DECOMPRESSOR += -ffreestanding +KBUILD_CFLAGS_DECOMPRESSOR += -fno-stack-protector KBUILD_CFLAGS_DECOMPRESSOR += $(call cc-disable-warning, address-of-packed-member) KBUILD_CFLAGS_DECOMPRESSOR += $(if $(CONFIG_DEBUG_INFO),-g) KBUILD_CFLAGS_DECOMPRESSOR += $(if $(CONFIG_DEBUG_INFO_DWARF4), $(call cc-option, -gdwarf-4,)) diff --git a/arch/s390/purgatory/Makefile b/arch/s390/purgatory/Makefile index c57f8c40e992..21c4ebe29b9a 100644 --- a/arch/s390/purgatory/Makefile +++ b/arch/s390/purgatory/Makefile @@ -24,6 +24,7 @@ KBUILD_CFLAGS := -fno-strict-aliasing -Wall -Wstrict-prototypes KBUILD_CFLAGS += -Wno-pointer-sign -Wno-sign-compare KBUILD_CFLAGS += -fno-zero-initialized-in-bss -fno-builtin -ffreestanding KBUILD_CFLAGS += -c -MD -Os -m64 -msoft-float -fno-common +KBUILD_CFLAGS += -fno-stack-protector KBUILD_CFLAGS += $(CLANG_FLAGS) KBUILD_CFLAGS += $(call cc-option,-fno-PIE) KBUILD_AFLAGS := $(filter-out -DCC_USING_EXPOLINE,$(KBUILD_AFLAGS))
From: Po-Hsu Lin po-hsu.lin@canonical.com
[ Upstream commit 0d3e5a057992bdc66e4dca2ca50b77fa4a7bd90e ]
This test will require /dev/rtc0, the default RTC device, or one specified by user to run. Since this default RTC is not guaranteed to exist on all of the devices, so check its existence first, otherwise skip this test with the kselftest skip code 4.
Without this patch this test will fail like this on a s390x zVM: $ selftests: timers: rtcpie $ /dev/rtc0: No such file or directory not ok 1 selftests: timers: rtcpie # exit=22
With this patch: $ selftests: timers: rtcpie $ Default RTC /dev/rtc0 does not exist. Test Skipped! not ok 9 selftests: timers: rtcpie # SKIP
Fixed up change log so "With this patch" text doesn't get dropped. Shuah Khan skhan@linuxfoundation.org
Signed-off-by: Po-Hsu Lin po-hsu.lin@canonical.com Signed-off-by: Shuah Khan skhan@linuxfoundation.org Signed-off-by: Sasha Levin sashal@kernel.org --- tools/testing/selftests/timers/rtcpie.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-)
diff --git a/tools/testing/selftests/timers/rtcpie.c b/tools/testing/selftests/timers/rtcpie.c index 47b5bad1b393..4ef2184f1558 100644 --- a/tools/testing/selftests/timers/rtcpie.c +++ b/tools/testing/selftests/timers/rtcpie.c @@ -18,6 +18,8 @@ #include <stdlib.h> #include <errno.h>
+#include "../kselftest.h" + /* * This expects the new RTC class driver framework, working with * clocks that will often not be clones of what the PC-AT had. @@ -35,8 +37,14 @@ int main(int argc, char **argv) switch (argc) { case 2: rtc = argv[1]; - /* FALLTHROUGH */ + break; case 1: + fd = open(default_rtc, O_RDONLY); + if (fd == -1) { + printf("Default RTC %s does not exist. Test Skipped!\n", default_rtc); + exit(KSFT_SKIP); + } + close(fd); break; default: fprintf(stderr, "usage: rtctest [rtcdev] [d]\n");
From: Eric Anholt eric@anholt.net
[ Upstream commit a242f4297cfe3f4589a7620dcd42cc503607fc6b ]
db820c wants to use the qcom smmu path to get HUPCF set (which keeps the GPU from wedging and then sometimes wedging the kernel after a page fault), but it doesn't have separate pagetables support yet in drm/msm so we can't go all the way to the TTBR1 path.
Signed-off-by: Eric Anholt eric@anholt.net Reviewed-by: Bjorn Andersson bjorn.andersson@linaro.org Link: https://lore.kernel.org/r/20210326231303.3071950-1-eric@anholt.net Signed-off-by: Will Deacon will@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/iommu/arm/arm-smmu/arm-smmu-qcom.c | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-)
diff --git a/drivers/iommu/arm/arm-smmu/arm-smmu-qcom.c b/drivers/iommu/arm/arm-smmu/arm-smmu-qcom.c index 98b3a1c2a181..44a427833385 100644 --- a/drivers/iommu/arm/arm-smmu/arm-smmu-qcom.c +++ b/drivers/iommu/arm/arm-smmu/arm-smmu-qcom.c @@ -130,6 +130,16 @@ static int qcom_adreno_smmu_alloc_context_bank(struct arm_smmu_domain *smmu_doma return __arm_smmu_alloc_bitmap(smmu->context_map, start, count); }
+static bool qcom_adreno_can_do_ttbr1(struct arm_smmu_device *smmu) +{ + const struct device_node *np = smmu->dev->of_node; + + if (of_device_is_compatible(np, "qcom,msm8996-smmu-v2")) + return false; + + return true; +} + static int qcom_adreno_smmu_init_context(struct arm_smmu_domain *smmu_domain, struct io_pgtable_cfg *pgtbl_cfg, struct device *dev) { @@ -144,7 +154,8 @@ static int qcom_adreno_smmu_init_context(struct arm_smmu_domain *smmu_domain, * be AARCH64 stage 1 but double check because the arm-smmu code assumes * that is the case when the TTBR1 quirk is enabled */ - if ((smmu_domain->stage == ARM_SMMU_DOMAIN_S1) && + if (qcom_adreno_can_do_ttbr1(smmu_domain->smmu) && + (smmu_domain->stage == ARM_SMMU_DOMAIN_S1) && (smmu_domain->cfg.fmt == ARM_SMMU_CTX_FMT_AARCH64)) pgtbl_cfg->quirks |= IO_PGTABLE_QUIRK_ARM_TTBR1;
From: Alan Stern stern@rowland.harvard.edu
[ Upstream commit 60dfe484cef45293e631b3a6e8995f1689818172 ]
The USB core has utility routines to retrieve various types of descriptors. These routines will now provoke a WARN if they are asked to retrieve 0 bytes (USB "receive" requests must not have zero length), so avert this by checking the size argument at the start.
CC: Johan Hovold johan@kernel.org Reported-and-tested-by: syzbot+7dbcd9ff34dc4ed45240@syzkaller.appspotmail.com Reviewed-by: Johan Hovold johan@kernel.org Signed-off-by: Alan Stern stern@rowland.harvard.edu Link: https://lore.kernel.org/r/20210607152307.GD1768031@rowland.harvard.edu Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/usb/core/message.c | 6 ++++++ 1 file changed, 6 insertions(+)
diff --git a/drivers/usb/core/message.c b/drivers/usb/core/message.c index 30e9e680c74c..4d59d927ae3e 100644 --- a/drivers/usb/core/message.c +++ b/drivers/usb/core/message.c @@ -783,6 +783,9 @@ int usb_get_descriptor(struct usb_device *dev, unsigned char type, int i; int result;
+ if (size <= 0) /* No point in asking for no data */ + return -EINVAL; + memset(buf, 0, size); /* Make sure we parse really received data */
for (i = 0; i < 3; ++i) { @@ -832,6 +835,9 @@ static int usb_get_string(struct usb_device *dev, unsigned short langid, int i; int result;
+ if (size <= 0) /* No point in asking for no data */ + return -EINVAL; + for (i = 0; i < 3; ++i) { /* retry on length 0 or stall; some devices are flakey */ result = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),
On Fri, Jul 09, 2021 at 10:16:56PM -0400, Sasha Levin wrote:
From: Alan Stern stern@rowland.harvard.edu
[ Upstream commit 60dfe484cef45293e631b3a6e8995f1689818172 ]
The USB core has utility routines to retrieve various types of descriptors. These routines will now provoke a WARN if they are asked to retrieve 0 bytes (USB "receive" requests must not have zero length), so avert this by checking the size argument at the start.
CC: Johan Hovold johan@kernel.org Reported-and-tested-by: syzbot+7dbcd9ff34dc4ed45240@syzkaller.appspotmail.com Reviewed-by: Johan Hovold johan@kernel.org Signed-off-by: Alan Stern stern@rowland.harvard.edu Link: https://lore.kernel.org/r/20210607152307.GD1768031@rowland.harvard.edu Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org Signed-off-by: Sasha Levin sashal@kernel.org
drivers/usb/core/message.c | 6 ++++++ 1 file changed, 6 insertions(+)
diff --git a/drivers/usb/core/message.c b/drivers/usb/core/message.c index 30e9e680c74c..4d59d927ae3e 100644 --- a/drivers/usb/core/message.c +++ b/drivers/usb/core/message.c @@ -783,6 +783,9 @@ int usb_get_descriptor(struct usb_device *dev, unsigned char type, int i; int result;
- if (size <= 0) /* No point in asking for no data */
return -EINVAL;
- memset(buf, 0, size); /* Make sure we parse really received data */
for (i = 0; i < 3; ++i) { @@ -832,6 +835,9 @@ static int usb_get_string(struct usb_device *dev, unsigned short langid, int i; int result;
- if (size <= 0) /* No point in asking for no data */
return -EINVAL;
- for (i = 0; i < 3; ++i) { /* retry on length 0 or stall; some devices are flakey */ result = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),
-- 2.30.2
This patch should be dropped from all of the autosel branches it was picked to, as I do not think the USB core has been fixed up, along with all of the different drivers that we noticed doing this, in the stable trees.
So please drop from everywhere at this time.
thanks,
greg k-h
On Sat, Jul 10, 2021 at 08:23:50AM +0200, Greg Kroah-Hartman wrote:
On Fri, Jul 09, 2021 at 10:16:56PM -0400, Sasha Levin wrote:
From: Alan Stern stern@rowland.harvard.edu
[ Upstream commit 60dfe484cef45293e631b3a6e8995f1689818172 ]
The USB core has utility routines to retrieve various types of descriptors. These routines will now provoke a WARN if they are asked to retrieve 0 bytes (USB "receive" requests must not have zero length), so avert this by checking the size argument at the start.
CC: Johan Hovold johan@kernel.org Reported-and-tested-by: syzbot+7dbcd9ff34dc4ed45240@syzkaller.appspotmail.com Reviewed-by: Johan Hovold johan@kernel.org Signed-off-by: Alan Stern stern@rowland.harvard.edu Link: https://lore.kernel.org/r/20210607152307.GD1768031@rowland.harvard.edu Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org Signed-off-by: Sasha Levin sashal@kernel.org
drivers/usb/core/message.c | 6 ++++++ 1 file changed, 6 insertions(+)
diff --git a/drivers/usb/core/message.c b/drivers/usb/core/message.c index 30e9e680c74c..4d59d927ae3e 100644 --- a/drivers/usb/core/message.c +++ b/drivers/usb/core/message.c @@ -783,6 +783,9 @@ int usb_get_descriptor(struct usb_device *dev, unsigned char type, int i; int result;
if (size <= 0) /* No point in asking for no data */
return -EINVAL;
memset(buf, 0, size); /* Make sure we parse really received data */
for (i = 0; i < 3; ++i) {
@@ -832,6 +835,9 @@ static int usb_get_string(struct usb_device *dev, unsigned short langid, int i; int result;
- if (size <= 0) /* No point in asking for no data */
return -EINVAL;
- for (i = 0; i < 3; ++i) { /* retry on length 0 or stall; some devices are flakey */ result = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),
-- 2.30.2
This patch should be dropped from all of the autosel branches it was picked to, as I do not think the USB core has been fixed up, along with all of the different drivers that we noticed doing this, in the stable trees.
So please drop from everywhere at this time.
Will do, thanks!
From: Takashi Iwai tiwai@suse.de
[ Upstream commit c305366a37441c2ac90b08711cb6f032b43672f2 ]
snd_sb_qsound_destroy() contains the calls of removing the previously created mixer controls, but it doesn't clear the pointers. As snd_sb_qsound_destroy() itself may be repeatedly called via ioctl, this could lead to double-free potentially.
Fix it by clearing the struct fields properly afterwards.
Link: https://lore.kernel.org/r/20210608140540.17885-4-tiwai@suse.de Signed-off-by: Takashi Iwai tiwai@suse.de Signed-off-by: Sasha Levin sashal@kernel.org --- sound/isa/sb/sb16_csp.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-)
diff --git a/sound/isa/sb/sb16_csp.c b/sound/isa/sb/sb16_csp.c index 4789345a8fdd..c98ccd421a2e 100644 --- a/sound/isa/sb/sb16_csp.c +++ b/sound/isa/sb/sb16_csp.c @@ -1072,10 +1072,14 @@ static void snd_sb_qsound_destroy(struct snd_sb_csp * p) card = p->chip->card; down_write(&card->controls_rwsem); - if (p->qsound_switch) + if (p->qsound_switch) { snd_ctl_remove(card, p->qsound_switch); - if (p->qsound_space) + p->qsound_switch = NULL; + } + if (p->qsound_space) { snd_ctl_remove(card, p->qsound_space); + p->qsound_space = NULL; + } up_write(&card->controls_rwsem);
/* cancel pending transfer of QSound parameters */
From: Geoff Levand geoff@infradead.org
[ Upstream commit 9733862e50fdba55e7f1554e4286fcc5302ff28e ]
Commit f959dcd6ddfd29235030e8026471ac1b022ad2b0 (dma-direct: Fix potential NULL pointer dereference) added a null check on the dma_mask pointer of the kernel's device structure.
Add a dma_mask variable to the ps3_dma_region structure and set the device structure's dma_mask pointer to point to this new variable.
Fixes runtime errors like these: # WARNING: Fixes tag on line 10 doesn't match correct format # WARNING: Fixes tag on line 10 doesn't match correct format
ps3_system_bus_match:349: dev=8.0(sb_01), drv=8.0(ps3flash): match WARNING: CPU: 0 PID: 1 at kernel/dma/mapping.c:151 .dma_map_page_attrs+0x34/0x1e0 ps3flash sb_01: ps3stor_setup:193: map DMA region failed
Signed-off-by: Geoff Levand geoff@infradead.org Signed-off-by: Michael Ellerman mpe@ellerman.id.au Link: https://lore.kernel.org/r/562d0c9ea0100a30c3b186bcc7adb34b0bbd2cd7.162274642... Signed-off-by: Sasha Levin sashal@kernel.org --- arch/powerpc/include/asm/ps3.h | 2 ++ arch/powerpc/platforms/ps3/mm.c | 12 ++++++++++++ 2 files changed, 14 insertions(+)
diff --git a/arch/powerpc/include/asm/ps3.h b/arch/powerpc/include/asm/ps3.h index e646c7f218bc..12b6b76e8d0f 100644 --- a/arch/powerpc/include/asm/ps3.h +++ b/arch/powerpc/include/asm/ps3.h @@ -71,6 +71,7 @@ struct ps3_dma_region_ops; * @bus_addr: The 'translated' bus address of the region. * @len: The length in bytes of the region. * @offset: The offset from the start of memory of the region. + * @dma_mask: Device dma_mask. * @ioid: The IOID of the device who owns this region * @chunk_list: Opaque variable used by the ioc page manager. * @region_ops: struct ps3_dma_region_ops - dma region operations @@ -85,6 +86,7 @@ struct ps3_dma_region { enum ps3_dma_region_type region_type; unsigned long len; unsigned long offset; + u64 dma_mask;
/* driver variables (set by ps3_dma_region_create) */ unsigned long bus_addr; diff --git a/arch/powerpc/platforms/ps3/mm.c b/arch/powerpc/platforms/ps3/mm.c index d094321964fb..a81eac35d900 100644 --- a/arch/powerpc/platforms/ps3/mm.c +++ b/arch/powerpc/platforms/ps3/mm.c @@ -6,6 +6,7 @@ * Copyright 2006 Sony Corp. */
+#include <linux/dma-mapping.h> #include <linux/kernel.h> #include <linux/export.h> #include <linux/memblock.h> @@ -1118,6 +1119,7 @@ int ps3_dma_region_init(struct ps3_system_bus_device *dev, enum ps3_dma_region_type region_type, void *addr, unsigned long len) { unsigned long lpar_addr; + int result;
lpar_addr = addr ? ps3_mm_phys_to_lpar(__pa(addr)) : 0;
@@ -1129,6 +1131,16 @@ int ps3_dma_region_init(struct ps3_system_bus_device *dev, r->offset -= map.r1.offset; r->len = len ? len : ALIGN(map.total, 1 << r->page_size);
+ dev->core.dma_mask = &r->dma_mask; + + result = dma_set_mask_and_coherent(&dev->core, DMA_BIT_MASK(32)); + + if (result < 0) { + dev_err(&dev->core, "%s:%d: dma_set_mask_and_coherent failed: %d\n", + __func__, __LINE__, result); + return result; + } + switch (dev->dev_type) { case PS3_DEVICE_TYPE_SB: r->region_ops = (USE_DYNAMIC_DMA)
From: Xiyu Yang xiyuyang19@fudan.edu.cn
[ Upstream commit 1adf30f198c26539a62d761e45af72cde570413d ]
arm_smmu_rpm_get() invokes pm_runtime_get_sync(), which increases the refcount of the "smmu" even though the return value is less than 0.
The reference counting issue happens in some error handling paths of arm_smmu_rpm_get() in its caller functions. When arm_smmu_rpm_get() fails, the caller functions forget to decrease the refcount of "smmu" increased by arm_smmu_rpm_get(), causing a refcount leak.
Fix this issue by calling pm_runtime_resume_and_get() instead of pm_runtime_get_sync() in arm_smmu_rpm_get(), which can keep the refcount balanced in case of failure.
Signed-off-by: Xiyu Yang xiyuyang19@fudan.edu.cn Signed-off-by: Xin Tan tanxin.ctf@gmail.com Link: https://lore.kernel.org/r/1623293672-17954-1-git-send-email-xiyuyang19@fudan... Signed-off-by: Will Deacon will@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/iommu/arm/arm-smmu/arm-smmu.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/iommu/arm/arm-smmu/arm-smmu.c b/drivers/iommu/arm/arm-smmu/arm-smmu.c index 6f72c4d208ca..ee6cac9e7c02 100644 --- a/drivers/iommu/arm/arm-smmu/arm-smmu.c +++ b/drivers/iommu/arm/arm-smmu/arm-smmu.c @@ -74,7 +74,7 @@ static bool using_legacy_binding, using_generic_binding; static inline int arm_smmu_rpm_get(struct arm_smmu_device *smmu) { if (pm_runtime_enabled(smmu->dev)) - return pm_runtime_get_sync(smmu->dev); + return pm_runtime_resume_and_get(smmu->dev);
return 0; }
From: Xiyu Yang xiyuyang19@fudan.edu.cn
[ Upstream commit 7c8f176d6a3fa18aa0f8875da6f7c672ed2a8554 ]
The reference counting issue happens in several exception handling paths of arm_smmu_iova_to_phys_hard(). When those error scenarios occur, the function forgets to decrease the refcount of "smmu" increased by arm_smmu_rpm_get(), causing a refcount leak.
Fix this issue by jumping to "out" label when those error scenarios occur.
Signed-off-by: Xiyu Yang xiyuyang19@fudan.edu.cn Signed-off-by: Xin Tan tanxin.ctf@gmail.com Reviewed-by: Rob Clark robdclark@chromium.org Link: https://lore.kernel.org/r/1623293391-17261-1-git-send-email-xiyuyang19@fudan... Signed-off-by: Will Deacon will@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/iommu/arm/arm-smmu/arm-smmu.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-)
diff --git a/drivers/iommu/arm/arm-smmu/arm-smmu.c b/drivers/iommu/arm/arm-smmu/arm-smmu.c index ee6cac9e7c02..1a647e0ea3eb 100644 --- a/drivers/iommu/arm/arm-smmu/arm-smmu.c +++ b/drivers/iommu/arm/arm-smmu/arm-smmu.c @@ -1271,6 +1271,7 @@ static phys_addr_t arm_smmu_iova_to_phys_hard(struct iommu_domain *domain, u64 phys; unsigned long va, flags; int ret, idx = cfg->cbndx; + phys_addr_t addr = 0;
ret = arm_smmu_rpm_get(smmu); if (ret < 0) @@ -1290,6 +1291,7 @@ static phys_addr_t arm_smmu_iova_to_phys_hard(struct iommu_domain *domain, dev_err(dev, "iova to phys timed out on %pad. Falling back to software table walk.\n", &iova); + arm_smmu_rpm_put(smmu); return ops->iova_to_phys(ops, iova); }
@@ -1298,12 +1300,14 @@ static phys_addr_t arm_smmu_iova_to_phys_hard(struct iommu_domain *domain, if (phys & ARM_SMMU_CB_PAR_F) { dev_err(dev, "translation fault!\n"); dev_err(dev, "PAR = 0x%llx\n", phys); - return 0; + goto out; }
+ addr = (phys & GENMASK_ULL(39, 12)) | (iova & 0xfff); +out: arm_smmu_rpm_put(smmu);
- return (phys & GENMASK_ULL(39, 12)) | (iova & 0xfff); + return addr; }
static phys_addr_t arm_smmu_iova_to_phys(struct iommu_domain *domain,
From: Yang Yingliang yangyingliang@huawei.com
[ Upstream commit be471fe332f7f14aa6828010b220d7e6902b91a0 ]
It will cause null-ptr-deref if platform_get_resource() returns NULL, we need check the return value.
Signed-off-by: Yang Yingliang yangyingliang@huawei.com Link: https://lore.kernel.org/r/20210610124958.116142-1-yangyingliang@huawei.com Signed-off-by: Takashi Iwai tiwai@suse.de Signed-off-by: Sasha Levin sashal@kernel.org --- sound/mips/snd-n64.c | 4 ++++ 1 file changed, 4 insertions(+)
diff --git a/sound/mips/snd-n64.c b/sound/mips/snd-n64.c index e35e93157755..463a6fe589eb 100644 --- a/sound/mips/snd-n64.c +++ b/sound/mips/snd-n64.c @@ -338,6 +338,10 @@ static int __init n64audio_probe(struct platform_device *pdev) strcpy(card->longname, "N64 Audio");
res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); + if (!res) { + err = -EINVAL; + goto fail_dma_alloc; + } if (devm_request_irq(&pdev->dev, res->start, n64audio_isr, IRQF_SHARED, "N64 Audio", priv)) { err = -EBUSY;
From: Jaroslav Kysela perex@perex.cz
[ Upstream commit e381a14c3e3a4e90e293d4eaa5a3ab8ae98b9973 ]
The str variable should be always initialized before use even if the switch covers all cases. This is a minimalistic fix: Assign NULL, the sprintf() may print '(null)' if something is corrupted.
Signed-off-by: Jaroslav Kysela perex@perex.cz Link: https://lore.kernel.org/r/20210614071710.1786866-1-perex@perex.cz Signed-off-by: Takashi Iwai tiwai@suse.de Signed-off-by: Sasha Levin sashal@kernel.org --- sound/core/control_led.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/sound/core/control_led.c b/sound/core/control_led.c index a90e31dbde61..ff7fd5e29551 100644 --- a/sound/core/control_led.c +++ b/sound/core/control_led.c @@ -397,7 +397,7 @@ static ssize_t show_mode(struct device *dev, struct device_attribute *attr, char *buf) { struct snd_ctl_led *led = container_of(dev, struct snd_ctl_led, dev); - const char *str; + const char *str = NULL;
switch (led->mode) { case MODE_FOLLOW_MUTE: str = "follow-mute"; break;
From: Jaroslav Kysela perex@perex.cz
[ Upstream commit 12ffd726824a2f52486f72338b6fd3244b512959 ]
In case, where the loops are not executed for a reason, the uninitialized variable 'err' is returned to the caller. Make code fully predictible and assign zero in the declaration.
Signed-off-by: Jaroslav Kysela perex@perex.cz Cc: Mark Brown broonie@kernel.org Cc: Kuninori Morimoto kuninori.morimoto.gx@renesas.com Link: https://lore.kernel.org/r/20210614071746.1787072-1-perex@perex.cz Signed-off-by: Mark Brown broonie@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- sound/soc/soc-pcm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c index 8659089a87a0..46513bb97904 100644 --- a/sound/soc/soc-pcm.c +++ b/sound/soc/soc-pcm.c @@ -1700,7 +1700,7 @@ static int dpcm_apply_symmetry(struct snd_pcm_substream *fe_substream, struct snd_soc_dpcm *dpcm; struct snd_soc_pcm_runtime *fe = asoc_substream_to_rtd(fe_substream); struct snd_soc_dai *fe_cpu_dai; - int err; + int err = 0; int i;
/* apply symmetry for FE */
From: Srinivas Neeli srinivas.neeli@xilinx.com
[ Upstream commit a51b2fb94b04ab71e53a71b9fad03fa826941254 ]
Return value of "pm_runtime_get_sync" API was neither captured nor checked. Fixed it by capturing the return value and then checking for any warning.
Addresses-Coverity: "check_return" Signed-off-by: Srinivas Neeli srinivas.neeli@xilinx.com Signed-off-by: Bartosz Golaszewski bgolaszewski@baylibre.com Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/gpio/gpio-zynq.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/drivers/gpio/gpio-zynq.c b/drivers/gpio/gpio-zynq.c index 3521c1dc3ac0..fb8684d70fe3 100644 --- a/drivers/gpio/gpio-zynq.c +++ b/drivers/gpio/gpio-zynq.c @@ -1001,8 +1001,11 @@ static int zynq_gpio_probe(struct platform_device *pdev) static int zynq_gpio_remove(struct platform_device *pdev) { struct zynq_gpio *gpio = platform_get_drvdata(pdev); + int ret;
- pm_runtime_get_sync(&pdev->dev); + ret = pm_runtime_get_sync(&pdev->dev); + if (ret < 0) + dev_warn(&pdev->dev, "pm_runtime_get_sync() Failed\n"); gpiochip_remove(&gpio->chip); clk_disable_unprepare(gpio->clk); device_set_wakeup_capable(&pdev->dev, 0);
From: Srinivas Neeli srinivas.neeli@xilinx.com
[ Upstream commit 35d7b72a632bc7afb15356f44005554af8697904 ]
In two different instances the return value of "irq_get_irq_data" API was neither captured nor checked. Fixed it by capturing the return value and then checking for any error.
Addresses-Coverity: "returned_null" Signed-off-by: Srinivas Neeli srinivas.neeli@xilinx.com Signed-off-by: Bartosz Golaszewski bgolaszewski@baylibre.com Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/gpio/gpio-zynq.c | 10 ++++++++++ 1 file changed, 10 insertions(+)
diff --git a/drivers/gpio/gpio-zynq.c b/drivers/gpio/gpio-zynq.c index fb8684d70fe3..c288a7502de2 100644 --- a/drivers/gpio/gpio-zynq.c +++ b/drivers/gpio/gpio-zynq.c @@ -736,6 +736,11 @@ static int __maybe_unused zynq_gpio_suspend(struct device *dev) struct zynq_gpio *gpio = dev_get_drvdata(dev); struct irq_data *data = irq_get_irq_data(gpio->irq);
+ if (!data) { + dev_err(dev, "irq_get_irq_data() failed\n"); + return -EINVAL; + } + if (!device_may_wakeup(dev)) disable_irq(gpio->irq);
@@ -753,6 +758,11 @@ static int __maybe_unused zynq_gpio_resume(struct device *dev) struct irq_data *data = irq_get_irq_data(gpio->irq); int ret;
+ if (!data) { + dev_err(dev, "irq_get_irq_data() failed\n"); + return -EINVAL; + } + if (!device_may_wakeup(dev)) enable_irq(gpio->irq);
From: Gil Fine gil.fine@intel.com
[ Upstream commit b18f901382fdb74a138a0bf30458c54a023a1d86 ]
DROM for USB4 host/device has a shorter header than Thunderbolt DROM header. This patch addresses host/device with USB4 DROM (According to spec: Universal Serial Bus 4 (USB4) Device ROM Specification, Rev 1.0, Feb-2021).
While there correct the data_len field to be 12 bits and rename __unknown1 to reserved following the spec.
Signed-off-by: Gil Fine gil.fine@intel.com Signed-off-by: Mika Westerberg mika.westerberg@linux.intel.com Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/thunderbolt/eeprom.c | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-)
diff --git a/drivers/thunderbolt/eeprom.c b/drivers/thunderbolt/eeprom.c index 46d0906a3070..470885e6f1c8 100644 --- a/drivers/thunderbolt/eeprom.c +++ b/drivers/thunderbolt/eeprom.c @@ -214,7 +214,10 @@ static u32 tb_crc32(void *data, size_t len) return ~__crc32c_le(~0, data, len); }
-#define TB_DROM_DATA_START 13 +#define TB_DROM_DATA_START 13 +#define TB_DROM_HEADER_SIZE 22 +#define USB4_DROM_HEADER_SIZE 16 + struct tb_drom_header { /* BYTE 0 */ u8 uid_crc8; /* checksum for uid */ @@ -224,9 +227,9 @@ struct tb_drom_header { u32 data_crc32; /* checksum for data_len bytes starting at byte 13 */ /* BYTE 13 */ u8 device_rom_revision; /* should be <= 1 */ - u16 data_len:10; - u8 __unknown1:6; - /* BYTES 16-21 */ + u16 data_len:12; + u8 reserved:4; + /* BYTES 16-21 - Only for TBT DROM, nonexistent in USB4 DROM */ u16 vendor_id; u16 model_id; u8 model_rev; @@ -401,10 +404,10 @@ static int tb_drom_parse_entry_port(struct tb_switch *sw, * * Drom must have been copied to sw->drom. */ -static int tb_drom_parse_entries(struct tb_switch *sw) +static int tb_drom_parse_entries(struct tb_switch *sw, size_t header_size) { struct tb_drom_header *header = (void *) sw->drom; - u16 pos = sizeof(*header); + u16 pos = header_size; u16 drom_size = header->data_len + TB_DROM_DATA_START; int res;
@@ -566,7 +569,7 @@ static int tb_drom_parse(struct tb_switch *sw) header->data_crc32, crc); }
- return tb_drom_parse_entries(sw); + return tb_drom_parse_entries(sw, TB_DROM_HEADER_SIZE); }
static int usb4_drom_parse(struct tb_switch *sw) @@ -583,7 +586,7 @@ static int usb4_drom_parse(struct tb_switch *sw) return -EINVAL; }
- return tb_drom_parse_entries(sw); + return tb_drom_parse_entries(sw, USB4_DROM_HEADER_SIZE); }
/**
From: Christophe Leroy christophe.leroy@csgroup.eu
[ Upstream commit b3a9e523237013477bea914b7fbfbe420428b988 ]
get_user_instr() lacks sparse detection for the __user tag.
This is because __gui_ptr is assigned with a cast.
Fix that by adding a __chk_user_ptr()
Signed-off-by: Christophe Leroy christophe.leroy@csgroup.eu Signed-off-by: Michael Ellerman mpe@ellerman.id.au Link: https://lore.kernel.org/r/0320e5b41a794fd456ab8c5993bbfadcf9e1d8b4.162151682... Signed-off-by: Sasha Levin sashal@kernel.org --- arch/powerpc/include/asm/inst.h | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-)
diff --git a/arch/powerpc/include/asm/inst.h b/arch/powerpc/include/asm/inst.h index 268d3bd073c8..887ef150fdda 100644 --- a/arch/powerpc/include/asm/inst.h +++ b/arch/powerpc/include/asm/inst.h @@ -12,6 +12,8 @@ unsigned long __gui_ptr = (unsigned long)ptr; \ struct ppc_inst __gui_inst; \ unsigned int __prefix, __suffix; \ + \ + __chk_user_ptr(ptr); \ __gui_ret = gu_op(__prefix, (unsigned int __user *)__gui_ptr); \ if (__gui_ret == 0) { \ if ((__prefix >> 26) == OP_PREFIX) { \ @@ -29,7 +31,10 @@ }) #else /* !CONFIG_PPC64 */ #define ___get_user_instr(gu_op, dest, ptr) \ - gu_op((dest).val, (u32 __user *)(ptr)) +({ \ + __chk_user_ptr(ptr); \ + gu_op((dest).val, (u32 __user *)(ptr)); \ +}) #endif /* CONFIG_PPC64 */
#define get_user_instr(x, ptr) \
From: Michael Kelley mikelley@microsoft.com
[ Upstream commit 52e1b3b3daa9d53f0204bf474ee1d4b1beb38234 ]
Hyper-V is observed to sometimes set multiple flags in the srb_status, such as ABORTED and ERROR. Current code in storvsc_handle_error() handles only a single flag being set, and does nothing when multiple flags are set. Fix this by changing the case statement into a series of "if" statements testing individual flags. The functionality for handling each flag is unchanged.
Link: https://lore.kernel.org/r/1622827263-12516-3-git-send-email-mikelley@microso... Signed-off-by: Michael Kelley mikelley@microsoft.com Signed-off-by: Martin K. Petersen martin.petersen@oracle.com Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/scsi/storvsc_drv.c | 61 +++++++++++++++++++++----------------- 1 file changed, 33 insertions(+), 28 deletions(-)
diff --git a/drivers/scsi/storvsc_drv.c b/drivers/scsi/storvsc_drv.c index e6718a74e5da..b2e28197a086 100644 --- a/drivers/scsi/storvsc_drv.c +++ b/drivers/scsi/storvsc_drv.c @@ -1009,17 +1009,40 @@ static void storvsc_handle_error(struct vmscsi_request *vm_srb, struct storvsc_scan_work *wrk; void (*process_err_fn)(struct work_struct *work); struct hv_host_device *host_dev = shost_priv(host); - bool do_work = false;
- switch (SRB_STATUS(vm_srb->srb_status)) { - case SRB_STATUS_ERROR: + /* + * In some situations, Hyper-V sets multiple bits in the + * srb_status, such as ABORTED and ERROR. So process them + * individually, with the most specific bits first. + */ + + if (vm_srb->srb_status & SRB_STATUS_INVALID_LUN) { + set_host_byte(scmnd, DID_NO_CONNECT); + process_err_fn = storvsc_remove_lun; + goto do_work; + } + + if (vm_srb->srb_status & SRB_STATUS_ABORTED) { + if (vm_srb->srb_status & SRB_STATUS_AUTOSENSE_VALID && + /* Capacity data has changed */ + (asc == 0x2a) && (ascq == 0x9)) { + process_err_fn = storvsc_device_scan; + /* + * Retry the I/O that triggered this. + */ + set_host_byte(scmnd, DID_REQUEUE); + goto do_work; + } + } + + if (vm_srb->srb_status & SRB_STATUS_ERROR) { /* * Let upper layer deal with error when * sense message is present. */ - if (vm_srb->srb_status & SRB_STATUS_AUTOSENSE_VALID) - break; + return; + /* * If there is an error; offline the device since all * error recovery strategies would have already been @@ -1032,37 +1055,19 @@ static void storvsc_handle_error(struct vmscsi_request *vm_srb, set_host_byte(scmnd, DID_PASSTHROUGH); break; /* - * On Some Windows hosts TEST_UNIT_READY command can return - * SRB_STATUS_ERROR, let the upper level code deal with it - * based on the sense information. + * On some Hyper-V hosts TEST_UNIT_READY command can + * return SRB_STATUS_ERROR. Let the upper level code + * deal with it based on the sense information. */ case TEST_UNIT_READY: break; default: set_host_byte(scmnd, DID_ERROR); } - break; - case SRB_STATUS_INVALID_LUN: - set_host_byte(scmnd, DID_NO_CONNECT); - do_work = true; - process_err_fn = storvsc_remove_lun; - break; - case SRB_STATUS_ABORTED: - if (vm_srb->srb_status & SRB_STATUS_AUTOSENSE_VALID && - (asc == 0x2a) && (ascq == 0x9)) { - do_work = true; - process_err_fn = storvsc_device_scan; - /* - * Retry the I/O that triggered this. - */ - set_host_byte(scmnd, DID_REQUEUE); - } - break; } + return;
- if (!do_work) - return; - +do_work: /* * We need to schedule work to process this error; schedule it. */
From: Yang Yingliang yangyingliang@huawei.com
[ Upstream commit 80b9c1be567c3c6bbe0d4b290af578e630485b5d ]
If snd_pmac_tumbler_init() or snd_pmac_tumbler_post_init() fails, snd_pmac_probe() need return error code.
Reported-by: Hulk Robot hulkci@huawei.com Signed-off-by: Yang Yingliang yangyingliang@huawei.com Link: https://lore.kernel.org/r/20210616021121.1991502-1-yangyingliang@huawei.com Signed-off-by: Takashi Iwai tiwai@suse.de Signed-off-by: Sasha Levin sashal@kernel.org --- sound/ppc/powermac.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-)
diff --git a/sound/ppc/powermac.c b/sound/ppc/powermac.c index 9fb51ebafde1..8088f77d5a74 100644 --- a/sound/ppc/powermac.c +++ b/sound/ppc/powermac.c @@ -76,7 +76,11 @@ static int snd_pmac_probe(struct platform_device *devptr) sprintf(card->shortname, "PowerMac %s", name_ext); sprintf(card->longname, "%s (Dev %d) Sub-frame %d", card->shortname, chip->device_id, chip->subframe); - if ( snd_pmac_tumbler_init(chip) < 0 || snd_pmac_tumbler_post_init() < 0) + err = snd_pmac_tumbler_init(chip); + if (err < 0) + goto __error; + err = snd_pmac_tumbler_post_init(); + if (err < 0) goto __error; break; case PMAC_AWACS:
linux-stable-mirror@lists.linaro.org