Re: [PATCH] habanalabs: fix up absolute include instructions
On Wed, Jul 29, 2020 at 08:09:38AM +1000, Stephen Rothwell wrote: > Hi Greg, > > On Tue, 28 Jul 2020 19:18:51 +0200 Greg Kroah-Hartman > wrote: > > > > diff --git a/drivers/misc/habanalabs/common/Makefile > > b/drivers/misc/habanalabs/common/Makefile > > index 97d03b5c8683..b984bfa4face 100644 > > --- a/drivers/misc/habanalabs/common/Makefile > > +++ b/drivers/misc/habanalabs/common/Makefile > > @@ -1,6 +1,4 @@ > > # SPDX-License-Identifier: GPL-2.0-only > > -subdir-ccflags-y += -I$(src)/common > > I've seen oter places use > > subdir-ccflags-y += -I$(srcdir)/$(src)/common > > which would probably work as well. i.e. just change this in the > Makefiles rather than every source file. I hate seeing odd ccflags stuff in Makefiles as it can catch you "by surprise" as to what exactly is happening when looking at .c code. But yes, your change would also work. thanks, greg k-h
Re: [PATCH v2 1/1] Input: atmel_mxt_ts - only read messages in mxt_acquire_irq() when necessary
On Tue, Jul 28, 2020 at 12:16:37AM +0900, Jiada Wang wrote: > From: Nick Dyer > > The workaround of reading all messages until an invalid is received is a > way of forcing the CHG line high, which means that when using > edge-triggered interrupts the interrupt can be acquired. > > With level-triggered interrupts the workaround is unnecessary. > > Also, most recent maXTouch chips have a feature called RETRIGEN which, when > enabled, reasserts the interrupt line every cycle if there are messages > waiting. This also makes the workaround unnecessary. > > Note: the RETRIGEN feature is only in some firmware versions/chips, it's > not valid simply to enable the bit. > > Signed-off-by: Nick Dyer > Acked-by: Benson Leung > Acked-by: Yufeng Shen > (cherry picked from ndyer/linux/for-upstream commit > 1ae4e8281e491b22442cd5acdfca1862555f8ecb) > [gdavis: Fix conflicts due to v4.6-rc7 commit eb43335c4095 ("Input: >atmel_mxt_ts - use mxt_acquire_irq in mxt_soft_reset").] > Signed-off-by: George G. Davis > [jiada: reset use_retrigen_workaround at beginning of mxt_check_retrigen() > call mxt_check_retrigen() after mxt_acquire_irq() in mxt_initialize() > replace white-spaces with tab for MXT_COMMS_RETRIGEN > Changed to check if IRQ is level type] > Signed-off-by: Jiada Wang Applied, thank you. -- Dmitry
Re: [PATCH V3 vhost next 00/10] VDPA support for Mellanox ConnectX devices
On Tue, Jul 28, 2020 at 02:53:34PM +0800, Jason Wang wrote: > > Just notice Michael's vhost branch can not compile due to this commit: > > commit fee8fe6bd8ccacd27e963b71b4f943be3721779e > Author: Michael S. Tsirkin > Date: Mon Jul 27 10:51:55 2020 -0400 > > vdpa: make sure set_features in invoked for legacy > > Let's wait for Michael to clarify the correct branch to use then. > Michael, are you going to send a path to a git tree that I can rebase my series on top of it, or maybe you can just take my v3 and apply them on the right tree? If you do, you can take Jason's patches from the series he posted here https://lkml.org/lkml/2020/7/1/301 and take my 0003-0010 patches. Let me know.
INFO: rcu detected stall in tc_modify_qdisc
Hello, syzbot found the following issue on: HEAD commit:181964e6 fix a braino in cmsghdr_from_user_compat_to_kern() git tree: net console output: https://syzkaller.appspot.com/x/log.txt?x=12925e3890 kernel config: https://syzkaller.appspot.com/x/.config?x=f87a5e4232fdb267 dashboard link: https://syzkaller.appspot.com/bug?extid=9f78d5c664a8c33f4cce compiler: gcc (GCC) 10.1.0-syz 20200507 syz repro: https://syzkaller.appspot.com/x/repro.syz?x=16587f8c90 C reproducer: https://syzkaller.appspot.com/x/repro.c?x=15b2d79090 The issue was bisected to: commit 5a781ccbd19e4664babcbe4b4ead7aa2b9283d22 Author: Vinicius Costa Gomes Date: Sat Sep 29 00:59:43 2018 + tc: Add support for configuring the taprio scheduler bisection log: https://syzkaller.appspot.com/x/bisect.txt?x=160e1bac90 console output: https://syzkaller.appspot.com/x/log.txt?x=110e1bac90 IMPORTANT: if you fix the issue, please add the following tag to the commit: Reported-by: syzbot+9f78d5c664a8c33f4...@syzkaller.appspotmail.com Fixes: 5a781ccbd19e ("tc: Add support for configuring the taprio scheduler") rcu: INFO: rcu_preempt self-detected stall on CPU rcu:1-...!: (1 GPs behind) idle=6f6/1/0x4000 softirq=10195/10196 fqs=1 (t=27930 jiffies g=9233 q=413) rcu: rcu_preempt kthread starved for 27901 jiffies! g9233 f0x0 RCU_GP_WAIT_FQS(5) ->state=0x0 ->cpu=0 rcu:Unless rcu_preempt kthread gets sufficient CPU time, OOM is now expected behavior. rcu: RCU grace-period kthread stack dump: rcu_preempt R running task2911210 2 0x4000 Call Trace: context_switch kernel/sched/core.c:3458 [inline] __schedule+0x8ea/0x2210 kernel/sched/core.c:4219 schedule+0xd0/0x2a0 kernel/sched/core.c:4294 schedule_timeout+0x148/0x250 kernel/time/timer.c:1908 rcu_gp_fqs_loop kernel/rcu/tree.c:1874 [inline] rcu_gp_kthread+0xae5/0x1b50 kernel/rcu/tree.c:2044 kthread+0x3b5/0x4a0 kernel/kthread.c:291 ret_from_fork+0x1f/0x30 arch/x86/entry/entry_64.S:293 NMI backtrace for cpu 1 CPU: 1 PID: 6799 Comm: syz-executor494 Not tainted 5.8.0-rc6-syzkaller #0 Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 01/01/2011 Call Trace: __dump_stack lib/dump_stack.c:77 [inline] dump_stack+0x18f/0x20d lib/dump_stack.c:118 nmi_cpu_backtrace.cold+0x70/0xb1 lib/nmi_backtrace.c:101 nmi_trigger_cpumask_backtrace+0x1b3/0x223 lib/nmi_backtrace.c:62 trigger_single_cpu_backtrace include/linux/nmi.h:164 [inline] rcu_dump_cpu_stacks+0x194/0x1cf kernel/rcu/tree_stall.h:320 print_cpu_stall kernel/rcu/tree_stall.h:553 [inline] check_cpu_stall kernel/rcu/tree_stall.h:627 [inline] rcu_pending kernel/rcu/tree.c:3489 [inline] rcu_sched_clock_irq.cold+0x5b3/0xccc kernel/rcu/tree.c:2504 update_process_times+0x25/0x60 kernel/time/timer.c:1737 tick_sched_handle+0x9b/0x180 kernel/time/tick-sched.c:176 tick_sched_timer+0x108/0x290 kernel/time/tick-sched.c:1320 __run_hrtimer kernel/time/hrtimer.c:1520 [inline] __hrtimer_run_queues+0x1d5/0xfc0 kernel/time/hrtimer.c:1584 hrtimer_interrupt+0x32a/0x930 kernel/time/hrtimer.c:1646 local_apic_timer_interrupt arch/x86/kernel/apic/apic.c:1080 [inline] __sysvec_apic_timer_interrupt+0x142/0x5e0 arch/x86/kernel/apic/apic.c:1097 asm_call_on_stack+0xf/0x20 arch/x86/entry/entry_64.S:711 __run_on_irqstack arch/x86/include/asm/irq_stack.h:22 [inline] run_on_irqstack_cond arch/x86/include/asm/irq_stack.h:48 [inline] sysvec_apic_timer_interrupt+0xe0/0x120 arch/x86/kernel/apic/apic.c:1091 asm_sysvec_apic_timer_interrupt+0x12/0x20 arch/x86/include/asm/idtentry.h:585 RIP: 0010:arch_local_irq_restore arch/x86/include/asm/paravirt.h:770 [inline] RIP: 0010:__raw_spin_unlock_irqrestore include/linux/spinlock_api_smp.h:160 [inline] RIP: 0010:_raw_spin_unlock_irqrestore+0x8c/0xe0 kernel/locking/spinlock.c:191 Code: 48 c7 c0 88 e0 b4 89 48 ba 00 00 00 00 00 fc ff df 48 c1 e8 03 80 3c 10 00 75 37 48 83 3d e3 52 cc 01 00 74 22 48 89 df 57 9d <0f> 1f 44 00 00 bf 01 00 00 00 e8 35 e5 66 f9 65 8b 05 fe 70 19 78 RSP: 0018:c900016672c0 EFLAGS: 0282 RAX: 11369c11 RBX: 0282 RCX: 0002 RDX: dc00 RSI: RDI: 0282 RBP: 888093a052e8 R08: R09: R10: 0001 R11: R12: 0282 R13: 0078100c35c3 R14: 888093a05000 R15: spin_unlock_irqrestore include/linux/spinlock.h:408 [inline] taprio_change+0x1fdc/0x2960 net/sched/sch_taprio.c:1557 taprio_init+0x52e/0x670 net/sched/sch_taprio.c:1670 qdisc_create+0x4b6/0x12e0 net/sched/sch_api.c:1246 tc_modify_qdisc+0x4c8/0x1990 net/sched/sch_api.c:1662 rtnetlink_rcv_msg+0x44e/0xad0 net/core/rtnetlink.c:5461 netlink_rcv_skb+0x15a/0x430 net/netlink/af_netlink.c:2469 netlink_unicast_kernel net/netlink/af_netlink.c:1303 [inline] netlink_unicast+0x533/0x7d0 net/netlink/af_netlink.c:1329 netlink_sendmsg+0x856/0xd90
Re: [PATCH] cpufreq: intel_pstate: Fix EPP setting via sysfs in active mode
"Rafael J. Wysocki" writes: > From: Rafael J. Wysocki > > Because intel_pstate_set_energy_pref_index() reads and writes the > MSR_HWP_REQUEST register without using the cached value of it used by > intel_pstate_hwp_boost_up() and intel_pstate_hwp_boost_down(), those > functions may overwrite the value written by it and so the EPP value > set via sysfs may be lost. > > To avoid that, make intel_pstate_set_energy_pref_index() take the > cached value of MSR_HWP_REQUEST just like the other two routines > mentioned above and update it with the new EPP value coming from > user space in addition to updating the MSR. > > Note that the MSR itself still needs to be updated too in case > hwp_boost is unset or the boosting mechanism is not active at the > EPP change time. > > Fixes: e0efd5be63e8 ("cpufreq: intel_pstate: Add HWP boost utility and sched > util hooks") > Reported-by: Francisco Jerez > Signed-off-by: Rafael J. Wysocki Reviewed-by: Francisco Jerez > --- > > This patch is on top of https://patchwork.kernel.org/patch/11689347/ > > --- > drivers/cpufreq/intel_pstate.c | 17 - > 1 file changed, 12 insertions(+), 5 deletions(-) > > Index: linux-pm/drivers/cpufreq/intel_pstate.c > === > --- linux-pm.orig/drivers/cpufreq/intel_pstate.c > +++ linux-pm/drivers/cpufreq/intel_pstate.c > @@ -653,11 +653,12 @@ static int intel_pstate_set_energy_pref_ > epp = cpu_data->epp_default; > > if (boot_cpu_has(X86_FEATURE_HWP_EPP)) { > - u64 value; > - > - ret = rdmsrl_on_cpu(cpu_data->cpu, MSR_HWP_REQUEST, ); > - if (ret) > - return ret; > + /* > + * Use the cached HWP Request MSR value, because the register > + * itself may be updated by intel_pstate_hwp_boost_up() or > + * intel_pstate_hwp_boost_down() at any time. > + */ > + u64 value = READ_ONCE(cpu_data->hwp_req_cached); > > value &= ~GENMASK_ULL(31, 24); > > @@ -667,6 +668,12 @@ static int intel_pstate_set_energy_pref_ > epp = epp_values[pref_index - 1]; > > value |= (u64)epp << 24; > + /* > + * The only other updater of hwp_req_cached in the active mode, > + * intel_pstate_hwp_set(), is called under the same lock as this > + * function, so it cannot run in parallel with the update below. > + */ > + WRITE_ONCE(cpu_data->hwp_req_cached, value); > ret = wrmsrl_on_cpu(cpu_data->cpu, MSR_HWP_REQUEST, value); > } else { > if (epp == -EINVAL) signature.asc Description: PGP signature
Re: [PATCH] staging: qlge: qlge_dbg: removed comment repition
A: http://en.wikipedia.org/wiki/Top_post Q: Were do I find info about this thing called top-posting? A: Because it messes up the order in which people normally read text. Q: Why is top-posting such a bad thing? A: Top-posting. Q: What is the most annoying thing in e-mail? A: No. Q: Should I include quotations after my reply? http://daringfireball.net/2007/07/on_top On Wed, Jul 29, 2020 at 11:06:56AM +0530, Dhiraj Sharma wrote: > Hello, It has been less than 24 hours for a simple comment cleanup patch. Please give maintainers time, they deal with thousands of patches a week. Usually, if after 2 weeks, you have not gotten a response, you can resend it. > I know that I should ask for reviews etc after a week but the change > is for my eudyptula task and until it doesn't get merged little > penguin will not pass the task for me so please look at it. If you knew that you should wait for at least a week, and yet you did not, that implies that you somehow feel this comment cleanup patch is more important than everyone else, which is a bit rude, don't you think? There are no such things as deadlines when it comes to upstream kernel development, sorry. greg k-h
Re: [PATCH] cpufreq: intel_pstate: Implement passive mode with HWP enabled
"Rafael J. Wysocki" writes: > On Tuesday, July 28, 2020 4:32:22 AM CEST Francisco Jerez wrote: >> >> "Rafael J. Wysocki" writes: >> >> > On Tuesday, July 21, 2020 1:20:14 AM CEST Francisco Jerez wrote: >> > >> > [cut] >> > >> >> > >> >> > However, in the active mode the only updater of hwp_req_cached is >> >> > intel_pstate_hwp_set() and this patch doesn't introduce any >> >> > differences in behavior in that case. >> >> > >> >>=20 >> >> intel_pstate_hwp_set() is the only updater, but there are other >> >> consumers that can get out of sync with the HWP request value written by >> >> intel_pstate_set_energy_pref_index(). intel_pstate_hwp_boost_up() seems >> >> like the most concerning example I named earlier. >> >>=20 >> >> >> > So there may be a short time window after the >> >> >> > intel_pstate_set_energy_pref_index() invocation in which the new EPP >> >> >> > value may not be in effect, but in general there is no guarantee th= >> at >> >> >> > the new EPP will take effect immediately after updating the MSR >> >> >> > anyway, so that race doesn't matter. >> >> >> > >> >> >> > That said, that race is avoidable, but I was thinking that trying to >> >> >> > avoid it might not be worth it. Now I see a better way to avoid it, >> >> >> > though, so I'm going to update the patch to that end. >> >> >> > >> >> >> >> Seems like a bug to me. >> >> >> > >> >> >> > It is racy, but not every race is a bug. >> >> >> > >> >> >> >> >> >> Still seems like there is a bug in intel_pstate_set_energy_pref_index= >> () >> >> >> AFAICT. >> >> > >> >> > If there is a bug, then what exactly is it, from the users' perspectiv= >> e? >> >> > >> >>=20 >> >> It can be reproduced easily as follows: >> >>=20 >> >> | echo 1 > /sys/devices/system/cpu/intel_pstate/hwp_dynamic_boost >> >> | for p in /sys/devices/system/cpu/cpufreq/policy*/energy_performance_pr= >> eference; do echo performance > $p; done >> > >> > Is this the active mode or the passive mode with the $subject patch appli= >> ed? >> > >> > If the former, the issue is there regardless of the patch, so it needs to= >> be >> > fixed. >> > >> > If the latter, there should be no effect of hwp_dynamic_boost (which was >> > overlooked by me). >> > >> >> This seems to be a problem in active mode only, so yeah the bug exists >> regardless of your patch, but the fix is likely to allow you to simplify >> this series slightly if it allows you to take full advantage of >> hwp_req_cached and drop the additional EPP cache. > > The additional EPP cache is there to avoid synchronizing the scheduler > context directly with a random process running on another CPU and doing > things that may take time. > > The difference between the active mode and the passive mode in this respect > is that in the latter case hwp_req_cached generally needs to be updated from > the scheduler context, whereas in the former case it does not. > Hm, that's unfortunate. Though I'd be surprised to see any appreciable performance penalty from synchronizing with a sysfs handler that should hardly ever be called. Anyway thanks for the fix. > [cut] > >> >> No, I explicitly dismissed that in my previous reply. >> > >> > But at the same time you seem to agree that without the non-CPU component >> > (or thermal pressure) the existing CPU performance scaling would be >> > sufficient. >> > >> >> Yes, but not necessarily in order to allow the non-CPU component to draw >> more power as you said above, but also because the existence of a >> bottleneck in a non-CPU component gives us an opportunity to improve the >> energy efficiency of the CPU, regardless of whether that allows the >> workload to run faster. > > But why would the bottleneck be there otherwise? > Because some resource of the system (e.g. memory bandwidth, GPU fill rate) may be close to 100% utilized, causing a bottleneck for reasons unrelated to its energy usage. >> > [cut] >> > >> >> > Yes, it is, and so I don't quite see the connection between it and my = >> question. >> >> > >> >> > Apparently, the unmodified performance scaling governors are not >> >> > sufficient, so there must be something beyond the above which allows >> >> > you to determine the frequency in question and so I'm asking what that >> >> > is. >> >> > >> >>=20 >> >> The underlying heuristic assumption is the same as I outlined above, but >> >> in any implementation of such a heuristic there is necessarily a >> >> trade-off between responsiveness to short-term fluctuations and >> >> long-term energy usage. This trade-off is a function of the somewhat >> >> arbitrary time interval I was referring to as "immediate past" -- A >> >> longer time parameter allows the controller to consider a greater >> >> portion of the workload's history while computing the response with >> >> optimal energy usage, at the cost of increasing its reaction time to >> >> discontinuous changes in the behavior of the workload (AKA increased >> >> latency). >> > >> > OK >> > >> >> One of the key
Re: [PATCH] staging: qlge: qlge_dbg: removed comment repition
Hello, I know that I should ask for reviews etc after a week but the change is for my eudyptula task and until it doesn't get merged little penguin will not pass the task for me so please look at it. Thank You Dhiraj Sharma On Tue, Jul 28, 2020 at 11:56 PM Dhiraj Sharma wrote: > > Inside function ql_get_dump comment statement had a repition of word > "to" which I removed and checkpatch.pl ouputs zero error or warnings > now. > > Signed-off-by: Dhiraj Sharma > --- > drivers/staging/qlge/qlge_dbg.c | 2 +- > 1 file changed, 1 insertion(+), 1 deletion(-) > > diff --git a/drivers/staging/qlge/qlge_dbg.c b/drivers/staging/qlge/qlge_dbg.c > index 985a6c341294..a55bf0b3e9dc 100644 > --- a/drivers/staging/qlge/qlge_dbg.c > +++ b/drivers/staging/qlge/qlge_dbg.c > @@ -1298,7 +1298,7 @@ void ql_get_dump(struct ql_adapter *qdev, void *buff) > * If the dump has already been taken and is stored > * in our internal buffer and if force dump is set then > * just start the spool to dump it to the log file > -* and also, take a snapshot of the general regs to > +* and also, take a snapshot of the general regs > * to the user's buffer or else take complete dump > * to the user's buffer if force is not set. > */ > -- > 2.17.1 >
Re: [PATCH] thermal: core: Add thermal zone enable/disable notification
On Tue, Jul 28, 2020 at 4:40 AM Daniel Lezcano wrote: > > Now the calls to enable/disable a thermal zone are centralized in a > call to a function, we can add in these the corresponding netlink > notifications. > > Signed-off-by: Daniel Lezcano Reviewed-by: Amit Kucheria > --- > drivers/thermal/thermal_core.c | 5 + > 1 file changed, 5 insertions(+) > > diff --git a/drivers/thermal/thermal_core.c b/drivers/thermal/thermal_core.c > index 9748fbb9a3a1..72bf159bcecc 100644 > --- a/drivers/thermal/thermal_core.c > +++ b/drivers/thermal/thermal_core.c > @@ -509,6 +509,11 @@ static int thermal_zone_device_set_mode(struct > thermal_zone_device *tz, > > thermal_zone_device_update(tz, THERMAL_EVENT_UNSPECIFIED); > > + if (mode == THERMAL_DEVICE_ENABLED) > + thermal_notify_tz_enable(tz->id); > + else > + thermal_notify_tz_disable(tz->id); > + > return ret; > } > > -- > 2.17.1 >
Re: [PATCH v1 1/2] scsi: ufs: Introduce device quirk "DELAY_AFTER_LPM"
Hi Stanley, On 2020-07-29 13:18, Stanley Chu wrote: Some UFS devices require delay after VCC power rail is turned-off. Introduce a device quirk "DELAY_AFTER_LPM" to add 5ms delays after VCC power-off during suspend flow. Just curious, I can understand if you want to add some delays before turnning off VCC/VCCQ/VCCQ2, but what is the delay AFTER turnning them off for? I mean the power has been cut by host from PMIC, how can the delay benefit the UFS device? Thanks, Can Guo. Signed-off-by: Andy Teng Signed-off-by: Peter Wang Signed-off-by: Stanley Chu --- drivers/scsi/ufs/ufs_quirks.h | 7 +++ drivers/scsi/ufs/ufshcd.c | 11 +++ 2 files changed, 18 insertions(+) diff --git a/drivers/scsi/ufs/ufs_quirks.h b/drivers/scsi/ufs/ufs_quirks.h index 2a0041493e30..07f559ac5883 100644 --- a/drivers/scsi/ufs/ufs_quirks.h +++ b/drivers/scsi/ufs/ufs_quirks.h @@ -109,4 +109,11 @@ struct ufs_dev_fix { */ #define UFS_DEVICE_QUIRK_SUPPORT_EXTENDED_FEATURES (1 << 10) +/* + * Some UFS devices require delay after VCC power rail is turned-off. + * Enable this quirk to introduce 5ms delays after VCC power-off during + * suspend flow. + */ +#define UFS_DEVICE_QUIRK_DELAY_AFTER_LPM(1 << 11) + #endif /* UFS_QUIRKS_H_ */ diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c index acba2271c5d3..63f4e2f75aa1 100644 --- a/drivers/scsi/ufs/ufshcd.c +++ b/drivers/scsi/ufs/ufshcd.c @@ -8111,6 +8111,8 @@ static int ufshcd_link_state_transition(struct ufs_hba *hba, static void ufshcd_vreg_set_lpm(struct ufs_hba *hba) { + bool vcc_off = false; + /* * It seems some UFS devices may keep drawing more than sleep current * (atleast for 500us) from UFS rails (especially from VCCQ rail). @@ -8139,13 +8141,22 @@ static void ufshcd_vreg_set_lpm(struct ufs_hba *hba) if (ufshcd_is_ufs_dev_poweroff(hba) && ufshcd_is_link_off(hba) && !hba->dev_info.is_lu_power_on_wp) { ufshcd_setup_vreg(hba, false); + vcc_off = true; } else if (!ufshcd_is_ufs_dev_active(hba)) { ufshcd_toggle_vreg(hba->dev, hba->vreg_info.vcc, false); + vcc_off = true; if (!ufshcd_is_link_active(hba)) { ufshcd_config_vreg_lpm(hba, hba->vreg_info.vccq); ufshcd_config_vreg_lpm(hba, hba->vreg_info.vccq2); } } + + /* +* Some UFS devices require delay after VCC power rail is turned-off. +*/ + if (vcc_off && hba->vreg_info.vcc && + hba->dev_quirks & UFS_DEVICE_QUIRK_DELAY_AFTER_LPM) + usleep_range(5000, 5100); } static int ufshcd_vreg_set_hpm(struct ufs_hba *hba)
Re: PROBLEM: 5.8-rc7 no video output with nouveau on NV36 (regression)
On 2020-07-29, Dave Airlie wrote: > On Wed, 29 Jul 2020 at 15:05, Nick Bowler wrote: >> >> Hi, >> >> After installing Linux 5.8-rc7 I seem to get no video output on my >> NV36 card once the nouveau module is loaded. The display (connected >> to the digital output) simply reports "No Signal". >> >> I bisected to the following commit, and reverting this commit on >> top of 5.8-rc7 appears to correct the issue. > > Can you test the drm fixes pull I just sent to Linus > > https://patchwork.freedesktop.org/patch/381225/ Yes, pulling this seems to fix things. Thanks, Nick
[PATCH] vt: Handle recursion in vc_do_resize().
syzbot is reporting OOB read bug in vc_do_resize() [1] caused by memcpy() based on outdated old_{rows,row_size} values, for resize_screen() can recurse into vc_do_resize() which changes vc->vc_{cols,rows} that outdates old_{rows,row_size} values which were read before calling resize_screen(). Minimal fix might be to read vc->vc_{rows,size_row} after resize_screen(). A different fix might be to forbid recursive vc_do_resize() request. I can't tell which fix is the better. But since I guess that new_cols == vc->vc_cols && new_rows == vc->vc_rows check could become true after returning from resize_screen(), and I assume that not calling clear_selection() when resize_screen() will return error is harmless, let's redo the check by moving resize_screen() earlier. [1] https://syzkaller.appspot.com/bug?id=c70c88cfd16dcf6e1d3c7f0ab8648b3144b5b25e Reported-by: syzbot Signed-off-by: Tetsuo Handa --- drivers/tty/vt/vt.c | 24 +--- 1 file changed, 17 insertions(+), 7 deletions(-) diff --git a/drivers/tty/vt/vt.c b/drivers/tty/vt/vt.c index 42d8c67..952a067 100644 --- a/drivers/tty/vt/vt.c +++ b/drivers/tty/vt/vt.c @@ -1217,7 +1217,24 @@ static int vc_do_resize(struct tty_struct *tty, struct vc_data *vc, if (new_cols == vc->vc_cols && new_rows == vc->vc_rows) return 0; + if (new_screen_size > KMALLOC_MAX_SIZE || !new_screen_size) + return -EINVAL; + /* +* Since fbcon_resize() from resize_screen() can recurse into +* this function via fb_set_var(), handle recursion now. +*/ + err = resize_screen(vc, new_cols, new_rows, user); + if (err) + return err; + /* Reload values in case recursion changed vc->vc_{cols,rows}. */ + new_cols = (cols ? cols : vc->vc_cols); + new_rows = (lines ? lines : vc->vc_rows); + new_row_size = new_cols << 1; + new_screen_size = new_row_size * new_rows; + + if (new_cols == vc->vc_cols && new_rows == vc->vc_rows) + return 0; if (new_screen_size > KMALLOC_MAX_SIZE || !new_screen_size) return -EINVAL; newscreen = kzalloc(new_screen_size, GFP_USER); @@ -1238,13 +1255,6 @@ static int vc_do_resize(struct tty_struct *tty, struct vc_data *vc, old_rows = vc->vc_rows; old_row_size = vc->vc_size_row; - err = resize_screen(vc, new_cols, new_rows, user); - if (err) { - kfree(newscreen); - vc_uniscr_free(new_uniscr); - return err; - } - vc->vc_rows = new_rows; vc->vc_cols = new_cols; vc->vc_size_row = new_row_size; -- 1.8.3.1
[PATCH v1 1/2] scsi: ufs: Introduce device quirk "DELAY_AFTER_LPM"
Some UFS devices require delay after VCC power rail is turned-off. Introduce a device quirk "DELAY_AFTER_LPM" to add 5ms delays after VCC power-off during suspend flow. Signed-off-by: Andy Teng Signed-off-by: Peter Wang Signed-off-by: Stanley Chu --- drivers/scsi/ufs/ufs_quirks.h | 7 +++ drivers/scsi/ufs/ufshcd.c | 11 +++ 2 files changed, 18 insertions(+) diff --git a/drivers/scsi/ufs/ufs_quirks.h b/drivers/scsi/ufs/ufs_quirks.h index 2a0041493e30..07f559ac5883 100644 --- a/drivers/scsi/ufs/ufs_quirks.h +++ b/drivers/scsi/ufs/ufs_quirks.h @@ -109,4 +109,11 @@ struct ufs_dev_fix { */ #define UFS_DEVICE_QUIRK_SUPPORT_EXTENDED_FEATURES (1 << 10) +/* + * Some UFS devices require delay after VCC power rail is turned-off. + * Enable this quirk to introduce 5ms delays after VCC power-off during + * suspend flow. + */ +#define UFS_DEVICE_QUIRK_DELAY_AFTER_LPM(1 << 11) + #endif /* UFS_QUIRKS_H_ */ diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c index acba2271c5d3..63f4e2f75aa1 100644 --- a/drivers/scsi/ufs/ufshcd.c +++ b/drivers/scsi/ufs/ufshcd.c @@ -8111,6 +8111,8 @@ static int ufshcd_link_state_transition(struct ufs_hba *hba, static void ufshcd_vreg_set_lpm(struct ufs_hba *hba) { + bool vcc_off = false; + /* * It seems some UFS devices may keep drawing more than sleep current * (atleast for 500us) from UFS rails (especially from VCCQ rail). @@ -8139,13 +8141,22 @@ static void ufshcd_vreg_set_lpm(struct ufs_hba *hba) if (ufshcd_is_ufs_dev_poweroff(hba) && ufshcd_is_link_off(hba) && !hba->dev_info.is_lu_power_on_wp) { ufshcd_setup_vreg(hba, false); + vcc_off = true; } else if (!ufshcd_is_ufs_dev_active(hba)) { ufshcd_toggle_vreg(hba->dev, hba->vreg_info.vcc, false); + vcc_off = true; if (!ufshcd_is_link_active(hba)) { ufshcd_config_vreg_lpm(hba, hba->vreg_info.vccq); ufshcd_config_vreg_lpm(hba, hba->vreg_info.vccq2); } } + + /* +* Some UFS devices require delay after VCC power rail is turned-off. +*/ + if (vcc_off && hba->vreg_info.vcc && + hba->dev_quirks & UFS_DEVICE_QUIRK_DELAY_AFTER_LPM) + usleep_range(5000, 5100); } static int ufshcd_vreg_set_hpm(struct ufs_hba *hba) -- 2.18.0
[PATCH v1 0/2] scsi: ufs: Introduce and apply DELAY_AFTER_LPM device quirk
Hi, This patchset introduces and applies DELAY_AFTER_LPM device quirk in MediaTek platforms. Stanley Chu (2): scsi: ufs: Introduce device quirk "DELAY_AFTER_LPM" scsi: ufs-mediatek: Apply DELAY_AFTER_LPM quirk to Micron devices drivers/scsi/ufs/ufs-mediatek.c | 2 ++ drivers/scsi/ufs/ufs_quirks.h | 7 +++ drivers/scsi/ufs/ufshcd.c | 11 +++ 3 files changed, 20 insertions(+) -- 2.18.0
[PATCH v1 2/2] scsi: ufs-mediatek: Apply DELAY_AFTER_LPM quirk to Micron devices
Micron UFS devices require DELAY_AFTER_LPM device quirk in MediaTek platforms. Signed-off-by: Andy Teng Signed-off-by: Peter Wang Signed-off-by: Stanley Chu --- drivers/scsi/ufs/ufs-mediatek.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/scsi/ufs/ufs-mediatek.c b/drivers/scsi/ufs/ufs-mediatek.c index 31af8b3d2b53..7ff2682f481c 100644 --- a/drivers/scsi/ufs/ufs-mediatek.c +++ b/drivers/scsi/ufs/ufs-mediatek.c @@ -36,6 +36,8 @@ ufs_mtk_smc(UFS_MTK_SIP_DEVICE_RESET, high, res) static struct ufs_dev_fix ufs_mtk_dev_fixups[] = { + UFS_FIX(UFS_VENDOR_MICRON, UFS_ANY_MODEL, + UFS_DEVICE_QUIRK_DELAY_AFTER_LPM), UFS_FIX(UFS_VENDOR_SKHYNIX, "H9HQ21AFAMZDAR", UFS_DEVICE_QUIRK_SUPPORT_EXTENDED_FEATURES), END_FIX -- 2.18.0
Re: [PATCH v1 0/4] [RFC] Implement Trampoline File Descriptor
On Tue, Jul 28, 2020 at 10:40 AM Madhavan T. Venkataraman wrote: > > > > On 7/28/20 12:16 PM, Andy Lutomirski wrote: > > On Tue, Jul 28, 2020 at 9:32 AM Madhavan T. Venkataraman > wrote: > > Thanks. See inline.. > > On 7/28/20 10:13 AM, David Laight wrote: > > From: madve...@linux.microsoft.com > > Sent: 28 July 2020 14:11 > > ... > > The kernel creates the trampoline mapping without any permissions. When > the trampoline is executed by user code, a page fault happens and the > kernel gets control. The kernel recognizes that this is a trampoline > invocation. It sets up the user registers based on the specified > register context, and/or pushes values on the user stack based on the > specified stack context, and sets the user PC to the requested target > PC. When the kernel returns, execution continues at the target PC. > So, the kernel does the work of the trampoline on behalf of the > application. > > Isn't the performance of this going to be horrid? > > It takes about the same amount of time as getpid(). So, it is > one quick trip into the kernel. I expect that applications will > typically not care about this extra overhead as long as > they are able to run. > > What did you test this on? A page fault on any modern x86_64 system > is much, much, much, much slower than a syscall. > > > I tested it in on a KVM guest running Ubuntu. So, when you say > that a page fault is much slower, do you mean a regular page > fault that is handled through the VM layer? Here is the relevant code > in do_user_addr_fault(): I mean that x86 CPUs have reasonably SYSCALL and SYSRET instructions (the former is used for 64-bit system calls on Linux and the latter is mostly used to return from system calls), but hardware page fault delivery and IRET (used to return from page faults) are very slow.
[RFC][PATCH 2/2] dma-heap: Add a system-uncached heap
This adds a heap that allocates non-contiguous buffers that are marked as writecombined, so they are not cached by the CPU. This is useful, as most graphics buffers are usually not touched by the CPU or only written into once by the CPU. So when mapping the buffer over and over between devices, we can skip the CPU syncing, which saves a lot of cache management overhead, greatly improving performance. For folk using ION, there was a ION_FLAG_CACHED flag, which signaled if the returned buffer should be CPU cacheable or not. With DMA-BUF heaps, we have no such flag, and by default the current heaps (system and cma) produce CPU cachable buffers. So for folks transitioning from ION to DMA-BUF Heaps, this fills in some of that missing functionality. This does have a few "ugly" bits that were required to get the buffer properly flushed out initially which I'd like to improve. So feedback would be very welcome! Many thanks to Liam Mark for his help to get this working. Cc: Sumit Semwal Cc: Andrew F. Davis Cc: Benjamin Gaignard Cc: Liam Mark Cc: Laura Abbott Cc: Brian Starkey Cc: Hridya Valsaraju Cc: linux-me...@vger.kernel.org Cc: dri-de...@lists.freedesktop.org Signed-off-by: John Stultz --- drivers/dma-buf/heaps/Kconfig| 10 + drivers/dma-buf/heaps/Makefile | 1 + drivers/dma-buf/heaps/system_uncached_heap.c | 392 +++ 3 files changed, 403 insertions(+) create mode 100644 drivers/dma-buf/heaps/system_uncached_heap.c diff --git a/drivers/dma-buf/heaps/Kconfig b/drivers/dma-buf/heaps/Kconfig index a5eef06c4226..420b0ed0a512 100644 --- a/drivers/dma-buf/heaps/Kconfig +++ b/drivers/dma-buf/heaps/Kconfig @@ -5,6 +5,16 @@ config DMABUF_HEAPS_SYSTEM Choose this option to enable the system dmabuf heap. The system heap is backed by pages from the buddy allocator. If in doubt, say Y. +config DMABUF_HEAPS_SYSTEM_UNCACHED + bool "DMA-BUF Uncached System Heap" + depends on DMABUF_HEAPS + help + Choose this option to enable the uncached system dmabuf heap. This + heap is backed by pages from the buddy allocator, but pages are setup + for write combining. This avoids cache management overhead, and can + be faster if pages are mostly untouched by the cpu. If in doubt, + say Y. + config DMABUF_HEAPS_CMA bool "DMA-BUF CMA Heap" depends on DMABUF_HEAPS && DMA_CMA diff --git a/drivers/dma-buf/heaps/Makefile b/drivers/dma-buf/heaps/Makefile index 6e54cdec3da0..085685ec478f 100644 --- a/drivers/dma-buf/heaps/Makefile +++ b/drivers/dma-buf/heaps/Makefile @@ -1,4 +1,5 @@ # SPDX-License-Identifier: GPL-2.0 obj-y += heap-helpers.o obj-$(CONFIG_DMABUF_HEAPS_SYSTEM) += system_heap.o +obj-$(CONFIG_DMABUF_HEAPS_SYSTEM_UNCACHED) += system_uncached_heap.o obj-$(CONFIG_DMABUF_HEAPS_CMA) += cma_heap.o diff --git a/drivers/dma-buf/heaps/system_uncached_heap.c b/drivers/dma-buf/heaps/system_uncached_heap.c new file mode 100644 index ..d23908038376 --- /dev/null +++ b/drivers/dma-buf/heaps/system_uncached_heap.c @@ -0,0 +1,392 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Uncached System DMA-Heap exporter + * + * Copyright (C) 2020 Linaro Ltd. + * + * Based off of Andrew Davis' SRAM heap: + * Copyright (C) 2019 Texas Instruments Incorporated - http://www.ti.com/ + * Andrew F. Davis + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +struct uncached_heap { + struct dma_heap *heap; +}; + +struct uncached_heap_buffer { + struct dma_heap *heap; + struct list_head attachments; + struct mutex lock; + unsigned long len; + struct sg_table sg_table; + int vmap_cnt; + void *vaddr; +}; + +struct dma_heap_attachment { + struct device *dev; + struct sg_table *table; + struct list_head list; +}; + +static struct sg_table *dup_sg_table(struct sg_table *table) +{ + struct sg_table *new_table; + int ret, i; + struct scatterlist *sg, *new_sg; + + new_table = kzalloc(sizeof(*new_table), GFP_KERNEL); + if (!new_table) + return ERR_PTR(-ENOMEM); + + ret = sg_alloc_table(new_table, table->nents, GFP_KERNEL); + if (ret) { + kfree(new_table); + return ERR_PTR(-ENOMEM); + } + + new_sg = new_table->sgl; + for_each_sg(table->sgl, sg, table->nents, i) { + memcpy(new_sg, sg, sizeof(*sg)); + new_sg->dma_address = 0; + new_sg = sg_next(new_sg); + } + + return new_table; +} + +static int dma_heap_attach(struct dma_buf *dmabuf, + struct dma_buf_attachment *attachment) +{ + struct uncached_heap_buffer *buffer = dmabuf->priv; + struct dma_heap_attachment *a; + struct sg_table *table; + + a = kzalloc(sizeof(*a), GFP_KERNEL); +
[RFC][PATCH 1/2] dma-heap: Keep track of the heap device struct
Keep track of the heap device struct. This will be useful for special DMA allocations and actions. Cc: Sumit Semwal Cc: Andrew F. Davis Cc: Benjamin Gaignard Cc: Liam Mark Cc: Laura Abbott Cc: Brian Starkey Cc: Hridya Valsaraju Cc: linux-me...@vger.kernel.org Cc: dri-de...@lists.freedesktop.org Signed-off-by: John Stultz --- drivers/dma-buf/dma-heap.c | 33 + include/linux/dma-heap.h | 9 + 2 files changed, 34 insertions(+), 8 deletions(-) diff --git a/drivers/dma-buf/dma-heap.c b/drivers/dma-buf/dma-heap.c index afd22c9dbdcf..72c746755d89 100644 --- a/drivers/dma-buf/dma-heap.c +++ b/drivers/dma-buf/dma-heap.c @@ -30,6 +30,7 @@ * @heap_devt heap device node * @list list head connecting to list of heaps * @heap_cdev heap char device + * @heap_dev heap device struct * * Represents a heap of memory from which buffers can be made. */ @@ -40,6 +41,7 @@ struct dma_heap { dev_t heap_devt; struct list_head list; struct cdev heap_cdev; + struct device *heap_dev; }; static LIST_HEAD(heap_list); @@ -190,10 +192,21 @@ void *dma_heap_get_drvdata(struct dma_heap *heap) return heap->priv; } +/** + * dma_heap_get_dev() - get device struct for the heap + * @heap: DMA-Heap to retrieve device struct from + * + * Returns: + * The device struct for the heap. + */ +struct device *dma_heap_get_dev(struct dma_heap *heap) +{ + return heap->heap_dev; +} + struct dma_heap *dma_heap_add(const struct dma_heap_export_info *exp_info) { struct dma_heap *heap, *h, *err_ret; - struct device *dev_ret; unsigned int minor; int ret; @@ -247,16 +260,20 @@ struct dma_heap *dma_heap_add(const struct dma_heap_export_info *exp_info) goto err1; } - dev_ret = device_create(dma_heap_class, - NULL, - heap->heap_devt, - NULL, - heap->name); - if (IS_ERR(dev_ret)) { + heap->heap_dev = device_create(dma_heap_class, + NULL, + heap->heap_devt, + NULL, + heap->name); + if (IS_ERR(heap->heap_dev)) { pr_err("dma_heap: Unable to create device\n"); - err_ret = ERR_CAST(dev_ret); + err_ret = ERR_CAST(heap->heap_dev); goto err2; } + + /* Make sure it doesn't disappear on us */ + heap->heap_dev = get_device(heap->heap_dev); + /* Add heap to the list */ mutex_lock(_list_lock); list_add(>list, _list); diff --git a/include/linux/dma-heap.h b/include/linux/dma-heap.h index 454e354d1ffb..82857e096910 100644 --- a/include/linux/dma-heap.h +++ b/include/linux/dma-heap.h @@ -50,6 +50,15 @@ struct dma_heap_export_info { */ void *dma_heap_get_drvdata(struct dma_heap *heap); +/** + * dma_heap_get_dev() - get device struct for the heap + * @heap: DMA-Heap to retrieve device struct from + * + * Returns: + * The device struct for the heap. + */ +struct device *dma_heap_get_dev(struct dma_heap *heap); + /** * dma_heap_add - adds a heap to dmabuf heaps * @exp_info: information needed to register this heap -- 2.17.1
[PATCH v2 2/4] dt-bindings: regulator: mp886x: support mps,switch-frequency
From: Jisheng Zhang Both MP8867 and MP8869 support different switch frequency. Signed-off-by: Jisheng Zhang --- Documentation/devicetree/bindings/regulator/mp886x.txt | 4 1 file changed, 4 insertions(+) diff --git a/Documentation/devicetree/bindings/regulator/mp886x.txt b/Documentation/devicetree/bindings/regulator/mp886x.txt index 551867829459..e747000cebba 100644 --- a/Documentation/devicetree/bindings/regulator/mp886x.txt +++ b/Documentation/devicetree/bindings/regulator/mp886x.txt @@ -9,6 +9,10 @@ Required properties: - mps,fb-voltage-divider: An array of two integers containing the resistor values R1 and R2 of the feedback voltage divider in kilo ohms. +Optional properties: +- mps,switch-frequency: The valid switch frequency in Hertz. Available values + are: 50, 75, 100, 125, 150 + Any property defined as part of the core regulator binding, defined in ./regulator.txt, can also be used. -- 2.28.0.rc1
[PATCH v2 4/4] dt-bindings: regulator: Convert mp886x to json-schema
From: Jisheng Zhang Convert the mp886x binding to DT schema format using json-schema. Signed-off-by: Jisheng Zhang --- .../devicetree/bindings/regulator/mp886x.txt | 31 -- .../bindings/regulator/mps,mp886x.yaml| 58 +++ 2 files changed, 58 insertions(+), 31 deletions(-) delete mode 100644 Documentation/devicetree/bindings/regulator/mp886x.txt create mode 100644 Documentation/devicetree/bindings/regulator/mps,mp886x.yaml diff --git a/Documentation/devicetree/bindings/regulator/mp886x.txt b/Documentation/devicetree/bindings/regulator/mp886x.txt deleted file mode 100644 index e747000cebba.. --- a/Documentation/devicetree/bindings/regulator/mp886x.txt +++ /dev/null @@ -1,31 +0,0 @@ -Monolithic Power Systems MP8867/MP8869 voltage regulator - -Required properties: -- compatible: Must be one of the following. - "mps,mp8867" - "mps,mp8869" -- reg: I2C slave address. -- enable-gpios: enable gpios. -- mps,fb-voltage-divider: An array of two integers containing the resistor - values R1 and R2 of the feedback voltage divider in kilo ohms. - -Optional properties: -- mps,switch-frequency: The valid switch frequency in Hertz. Available values - are: 50, 75, 100, 125, 150 - -Any property defined as part of the core regulator binding, defined in -./regulator.txt, can also be used. - -Example: - - vcpu: regulator@62 { - compatible = "mps,mp8869"; - regulator-name = "vcpu"; - regulator-min-microvolt = <70>; - regulator-max-microvolt = <85>; - regulator-always-on; - regulator-boot-on; - enable-gpios = < 1 GPIO_ACTIVE_LOW>; - mps,fb-voltage-divider = <80 240>; - reg = <0x62>; - }; diff --git a/Documentation/devicetree/bindings/regulator/mps,mp886x.yaml b/Documentation/devicetree/bindings/regulator/mps,mp886x.yaml new file mode 100644 index ..991f2de7eda8 --- /dev/null +++ b/Documentation/devicetree/bindings/regulator/mps,mp886x.yaml @@ -0,0 +1,58 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/regulator/mps,mp886x.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Monolithic Power Systems MP8867/MP8869 voltage regulator + +maintainers: + - Jisheng Zhang + +properties: + compatible: +enum: + - mps,mp8867 + - mps,mp8869 + + reg: +maxItems: 1 + + enable-gpios: +description: GPIO to enable/disable the regulator. +maxItems: 1 + + mps,fb-voltage-divider: +description: An array of two integers containing the resistor + values R1 and R2 of the feedback voltage divider in kilo ohms. +$ref: "/schemas/types.yaml#/definitions/uint32-array" + + mps,switch-frequency: +description: The valid switch frequency in Hertz. +enum: [50, 75, 100, 125, 150] +$ref: "/schemas/types.yaml#/definitions/uint32" + +required: + - compatible + - reg + - enable-gpios + - mps,fb-voltage-divider + +examples: + - | +#include +i2c { +#address-cells = <1>; +#size-cells = <0>; +regulator@62 { + compatible = "mps,mp8869"; + regulator-name = "vcpu"; + regulator-min-microvolt = <80>; + regulator-max-microvolt = <115>; + enable-gpios = < 1 GPIO_ACTIVE_LOW>; + mps,fb-voltage-divider = <80 240>; + reg = <0x62>; +}; +}; + +... -- 2.28.0.rc1
[PATCH v2 3/4] regulator: mp886x: support setting switch freq
From: Jisheng Zhang Both MP8867 and MP8869 support different switch frequency. Signed-off-by: Jisheng Zhang --- drivers/regulator/mp886x.c | 42 ++ 1 file changed, 42 insertions(+) diff --git a/drivers/regulator/mp886x.c b/drivers/regulator/mp886x.c index 3c9a6605b115..e3c7813bed4b 100644 --- a/drivers/regulator/mp886x.c +++ b/drivers/regulator/mp886x.c @@ -22,10 +22,14 @@ #define MP886X_SLEW_MASK (0x7 << MP886X_SLEW_SHIFT) #define MP886X_GO (1 << 6) #define MP886X_EN (1 << 7) +#define MP8869_SYSCNTLREG2 0x02 struct mp886x_cfg_info { const struct regulator_ops *rops; const int slew_rates[8]; + const int switch_freq[4]; + const u8 fs_reg; + const u8 fs_shift; }; struct mp886x_device_info { @@ -60,6 +64,24 @@ static int mp886x_set_ramp(struct regulator_dev *rdev, int ramp) MP886X_SLEW_MASK, reg << MP886X_SLEW_SHIFT); } +static void mp886x_set_switch_freq(struct mp886x_device_info *di, + struct regmap *regmap, + u32 freq) +{ + const struct mp886x_cfg_info *ci = di->ci; + int i; + + for (i = 0; i < ARRAY_SIZE(ci->switch_freq); i++) { + if (freq == ci->switch_freq[i]) { + regmap_update_bits(regmap, ci->fs_reg, + 0x3 << ci->fs_shift, i << ci->fs_shift); + return; + } + } + + dev_err(di->dev, "invalid frequency %d\n", freq); +} + static int mp886x_set_mode(struct regulator_dev *rdev, unsigned int mode) { switch (mode) { @@ -162,6 +184,14 @@ static const struct mp886x_cfg_info mp8869_ci = { 1250, 625, }, + .switch_freq = { + 50, + 75, + 100, + 125, + }, + .fs_reg = MP8869_SYSCNTLREG2, + .fs_shift = 4, }; static int mp8867_set_voltage_sel(struct regulator_dev *rdev, unsigned int sel) @@ -233,6 +263,14 @@ static const struct mp886x_cfg_info mp8867_ci = { 1000, 500, }, + .switch_freq = { + 50, + 75, + 100, + 150, + }, + .fs_reg = MP886X_SYSCNTLREG1, + .fs_shift = 1, }; static int mp886x_regulator_register(struct mp886x_device_info *di, @@ -274,6 +312,7 @@ static int mp886x_i2c_probe(struct i2c_client *client, struct mp886x_device_info *di; struct regulator_config config = { }; struct regmap *regmap; + u32 freq; int ret; di = devm_kzalloc(dev, sizeof(struct mp886x_device_info), GFP_KERNEL); @@ -311,6 +350,9 @@ static int mp886x_i2c_probe(struct i2c_client *client, config.driver_data = di; config.of_node = np; + if (!of_property_read_u32(np, "mps,switch-frequency", )) + mp886x_set_switch_freq(di, regmap, freq); + ret = mp886x_regulator_register(di, ); if (ret < 0) dev_err(dev, "Failed to register regulator!\n"); -- 2.28.0.rc1
[PATCH v2 0/4] regulator: mp886x: two features and dt json convert
From: Jisheng Zhang This is to improve the mp886x regulator driver support. patch1 implments .set_ramp_delay patch2 and patch3 support the switch freq setting patch4 converts dt binding to json-schema Since v2: - put any schema conversions at the end of the series as Mark suggested. Jisheng Zhang (4): regulator: mp886x: implement set_ramp_delay dt-bindings: regulator: mp886x: support mps,switch-frequency regulator: mp886x: support setting switch freq dt-bindings: regulator: Convert mp886x to json-schema .../devicetree/bindings/regulator/mp886x.txt | 27 - .../bindings/regulator/mps,mp886x.yaml| 58 ++ drivers/regulator/mp886x.c| 109 +- 3 files changed, 164 insertions(+), 30 deletions(-) delete mode 100644 Documentation/devicetree/bindings/regulator/mp886x.txt create mode 100644 Documentation/devicetree/bindings/regulator/mps,mp886x.yaml -- 2.28.0.rc1
[PATCHv3] coresight: etm4x: Fix etm4_count race by moving cpuhp callbacks to init
etm4_count keeps track of number of ETMv4 registered and on some systems, a race is observed on etm4_count variable which can lead to multiple calls to cpuhp_setup_state_nocalls_cpuslocked(). This function internally calls cpuhp_store_callbacks() which prevents multiple registrations of callbacks for a given state and due to this race, it returns -EBUSY leading to ETM probe failures like below. coresight-etm4x: probe of 704.etm failed with error -16 This race can easily be triggered with async probe by setting probe type as PROBE_PREFER_ASYNCHRONOUS and with ETM power management property "arm,coresight-loses-context-with-cpu". Prevent this race by moving cpuhp callbacks to etm driver init since the cpuhp callbacks doesn't have to depend on the etm4_count and can be once setup during driver init. Similarly we move cpu_pm notifier registration to driver init and completely remove etm4_count usage. Also now we can use non cpuslocked version of cpuhp callbacks with this movement. Fixes: 9b6a3f3633a5 ("coresight: etmv4: Fix CPU power management setup in probe() function") Fixes: 58eb457be028 ("hwtracing/coresight-etm4x: Convert to hotplug state machine") Suggested-by: Suzuki K Poulose Signed-off-by: Sai Prakash Ranjan --- Changes in v3: * Minor cleanups from v2 and change to device_initcall (Stephen Boyd) * Move to non cpuslocked cpuhp callbacks and rename to etm_pm_setup() (Mike Leach) Changes in v2: * Rearrange cpuhp callbacks and move them to driver init (Suzuki K Poulose) --- drivers/hwtracing/coresight/coresight-etm4x.c | 65 +-- 1 file changed, 31 insertions(+), 34 deletions(-) diff --git a/drivers/hwtracing/coresight/coresight-etm4x.c b/drivers/hwtracing/coresight/coresight-etm4x.c index 6d7d2169bfb2..fddfd93b9a7b 100644 --- a/drivers/hwtracing/coresight/coresight-etm4x.c +++ b/drivers/hwtracing/coresight/coresight-etm4x.c @@ -48,8 +48,6 @@ module_param(pm_save_enable, int, 0444); MODULE_PARM_DESC(pm_save_enable, "Save/restore state on power down: 1 = never, 2 = self-hosted"); -/* The number of ETMv4 currently registered */ -static int etm4_count; static struct etmv4_drvdata *etmdrvdata[NR_CPUS]; static void etm4_set_default_config(struct etmv4_config *config); static int etm4_set_event_filters(struct etmv4_drvdata *drvdata, @@ -1398,28 +1396,25 @@ static struct notifier_block etm4_cpu_pm_nb = { .notifier_call = etm4_cpu_pm_notify, }; -/* Setup PM. Called with cpus locked. Deals with error conditions and counts */ -static int etm4_pm_setup_cpuslocked(void) +/* Setup PM. Deals with error conditions and counts */ +static int __init etm4_pm_setup(void) { int ret; - if (etm4_count++) - return 0; - ret = cpu_pm_register_notifier(_cpu_pm_nb); if (ret) - goto reduce_count; + return ret; - ret = cpuhp_setup_state_nocalls_cpuslocked(CPUHP_AP_ARM_CORESIGHT_STARTING, - "arm/coresight4:starting", - etm4_starting_cpu, etm4_dying_cpu); + ret = cpuhp_setup_state_nocalls(CPUHP_AP_ARM_CORESIGHT_STARTING, + "arm/coresight4:starting", + etm4_starting_cpu, etm4_dying_cpu); if (ret) goto unregister_notifier; - ret = cpuhp_setup_state_nocalls_cpuslocked(CPUHP_AP_ONLINE_DYN, - "arm/coresight4:online", - etm4_online_cpu, NULL); + ret = cpuhp_setup_state_nocalls(CPUHP_AP_ONLINE_DYN, + "arm/coresight4:online", + etm4_online_cpu, NULL); /* HP dyn state ID returned in ret on success */ if (ret > 0) { @@ -1428,21 +1423,15 @@ static int etm4_pm_setup_cpuslocked(void) } /* failed dyn state - remove others */ - cpuhp_remove_state_nocalls_cpuslocked(CPUHP_AP_ARM_CORESIGHT_STARTING); + cpuhp_remove_state_nocalls(CPUHP_AP_ARM_CORESIGHT_STARTING); unregister_notifier: cpu_pm_unregister_notifier(_cpu_pm_nb); - -reduce_count: - --etm4_count; return ret; } -static void etm4_pm_clear(void) +static void __init etm4_pm_clear(void) { - if (--etm4_count != 0) - return; - cpu_pm_unregister_notifier(_cpu_pm_nb); cpuhp_remove_state_nocalls(CPUHP_AP_ARM_CORESIGHT_STARTING); if (hp_online) { @@ -1498,22 +1487,12 @@ static int etm4_probe(struct amba_device *adev, const struct amba_id *id) if (!desc.name) return -ENOMEM; - cpus_read_lock(); etmdrvdata[drvdata->cpu] = drvdata; if (smp_call_function_single(drvdata->cpu, etm4_init_arch_data, drvdata, 1)) dev_err(dev, "ETM arch init failed\n"); -
[PATCH v2 1/4] regulator: mp886x: implement set_ramp_delay
From: Jisheng Zhang Implement the .set_ramp_delay for MP8867 and MP8869. MP8867 and MP8869 could share the implementation, the only difference is the slew_rates array. Signed-off-by: Jisheng Zhang --- drivers/regulator/mp886x.c | 67 -- 1 file changed, 64 insertions(+), 3 deletions(-) diff --git a/drivers/regulator/mp886x.c b/drivers/regulator/mp886x.c index 1786f7162019..3c9a6605b115 100644 --- a/drivers/regulator/mp886x.c +++ b/drivers/regulator/mp886x.c @@ -18,18 +18,48 @@ #define MP886X_V_BOOT (1 << 7) #define MP886X_SYSCNTLREG1 0x01 #define MP886X_MODE (1 << 0) +#define MP886X_SLEW_SHIFT 3 +#define MP886X_SLEW_MASK (0x7 << MP886X_SLEW_SHIFT) #define MP886X_GO (1 << 6) #define MP886X_EN (1 << 7) +struct mp886x_cfg_info { + const struct regulator_ops *rops; + const int slew_rates[8]; +}; + struct mp886x_device_info { struct device *dev; struct regulator_desc desc; struct regulator_init_data *regulator; struct gpio_desc *en_gpio; + const struct mp886x_cfg_info *ci; u32 r[2]; unsigned int sel; }; +static int mp886x_set_ramp(struct regulator_dev *rdev, int ramp) +{ + struct mp886x_device_info *di = rdev_get_drvdata(rdev); + const struct mp886x_cfg_info *ci = di->ci; + int reg = -1, i; + + for (i = 0; i < ARRAY_SIZE(ci->slew_rates); i++) { + if (ramp <= ci->slew_rates[i]) + reg = i; + else + break; + } + + if (reg < 0) { + dev_err(di->dev, "unsupported ramp value %d\n", ramp); + return -EINVAL; + } + + return regmap_update_bits(rdev->regmap, MP886X_SYSCNTLREG1, + MP886X_SLEW_MASK, reg << MP886X_SLEW_SHIFT); +} + static int mp886x_set_mode(struct regulator_dev *rdev, unsigned int mode) { switch (mode) { @@ -117,6 +147,21 @@ static const struct regulator_ops mp8869_regulator_ops = { .is_enabled = regulator_is_enabled_regmap, .set_mode = mp886x_set_mode, .get_mode = mp886x_get_mode, + .set_ramp_delay = mp886x_set_ramp, +}; + +static const struct mp886x_cfg_info mp8869_ci = { + .rops = _regulator_ops, + .slew_rates = { + 4, + 3, + 2, + 1, + 5000, + 2500, + 1250, + 625, + }, }; static int mp8867_set_voltage_sel(struct regulator_dev *rdev, unsigned int sel) @@ -173,6 +218,21 @@ static const struct regulator_ops mp8867_regulator_ops = { .is_enabled = regulator_is_enabled_regmap, .set_mode = mp886x_set_mode, .get_mode = mp886x_get_mode, + .set_ramp_delay = mp886x_set_ramp, +}; + +static const struct mp886x_cfg_info mp8867_ci = { + .rops = _regulator_ops, + .slew_rates = { + 64000, + 32000, + 16000, + 8000, + 4000, + 2000, + 1000, + 500, + }, }; static int mp886x_regulator_register(struct mp886x_device_info *di, @@ -183,7 +243,7 @@ static int mp886x_regulator_register(struct mp886x_device_info *di, rdesc->name = "mp886x-reg"; rdesc->supply_name = "vin"; - rdesc->ops = of_device_get_match_data(di->dev); + rdesc->ops = di->ci->rops; rdesc->type = REGULATOR_VOLTAGE; rdesc->n_voltages = 128; rdesc->enable_reg = MP886X_SYSCNTLREG1; @@ -235,6 +295,7 @@ static int mp886x_i2c_probe(struct i2c_client *client, if (IS_ERR(di->en_gpio)) return PTR_ERR(di->en_gpio); + di->ci = of_device_get_match_data(dev); di->dev = dev; regmap = devm_regmap_init_i2c(client, _regmap_config); @@ -259,11 +320,11 @@ static int mp886x_i2c_probe(struct i2c_client *client, static const struct of_device_id mp886x_dt_ids[] = { { .compatible = "mps,mp8867", - .data = _regulator_ops + .data = _ci }, { .compatible = "mps,mp8869", - .data = _regulator_ops + .data = _ci }, { } }; -- 2.28.0.rc1
Re: [PATCH 2/6] arch: x86: Wrap TIF_IA32 checks
On Tue, Jul 28, 2020 at 9:46 PM Gabriel Krisman Bertazi wrote: > > Andy Lutomirski writes: > > > On Tue, Jul 28, 2020 at 1:22 PM Gabriel Krisman Bertazi > > wrote: > >> > >> In preparation to remove TIF_IA32, add wrapper that check the process > >> has IA32 ABI without using the flag directly. > > > > Thank you for doing this, but let's please do it right. There is, > > fundamentally, no such thing as a "process with IA32 ABI". > > Hi Andy, > > Thanks a lot for your review. > > As you can see, I'm learning my way here. Can you clarify "there is no > such a thing as a 'process with IA32 ABI'"? I'm not sure if I confused > the terminology or if (more worrisome for me) I got the concepts wrong. > > My understanding is that TIF_IA32 marks a thread that is running under > the 32-bit compat mode, which would be running a 32-bit process (as in > compiled with -m32, for instance), while TIF_X32 marks a process running > under the X32 ABI. Each process would have only one of these > "personalities". This is what I meant by a process with IA32 ABI (which > is wrong in any case). Is there more to it, or is the problem the > terminology I used? There's more to it. On sane architectures like Linux on ARM64, a process can be 32-bit or 64-bit. If you are a 64-bit ARM process, you run in 64-bit mode, period. Anything other than execve() that lets you become 32-bit is a bug. Linux on x86 is nutty, though. (IIRC Sparc is too.) In particular, it's entirely legal for a Linux program to switch between 32-bit and 64-bit mode all by itself. This can be done with LJMP, LRET, IRET, or a few other hacks. It can also be done using any of the sigreturn syscalls. (SYSENTER comes to mind, but anyone who uses SYSENTER to switch modes is *nuts*.) Certain evil people named Andy Lutomirski write kernel selftests that switch modes using sigreturn just to abuse the kernel. But some real programs do this too. For example, I think that CRIU restores 32-bit programs by starting out as a 64-bit program, restoring everything, and then switching to 32-bit mode. Keep in mind that most of these mode-switching tricks do not enter the kernel at all. The upshot is that kernel does not actually know what the running program's ABI is. For all the kernel knows, a process uses the Linux/psABI 64-bit ABI, the ia32 ABI, the x32 ABI, the Windows 32-bit ABI, the Windows 64-bit ABI, and some gnarly ABI from DOS or OS/2, all in the same process. So we really shouldn't be trying to keep track of what we think the user program should be doing, and instead we should pay attention to what the user program actually did in its interactions with the kernel. If we want to know whether a user task is running in 64-bit mode right now, we can use user_64bit_mode(regs). (And keep in mind that syscalls like rt_sigreturn() and anything that gets ptraced can *change* the outcome of user_64bit_mode(regs) mid-syscall.) If we're delivering a signal, we instead want to know the ABI of the signal's handler, so we use is_ia32_frame(ksig) and is_x32_frame(ksig). If we want to know whether mmap() should return values above 2^32-1, we currently use some hackery, but we really ought to be looking at whether the call was 64-bit mmap() or compat mmap(). (I had some really half-baked patches to fix this at one point, but the core code was a real mess and I didn't finish it.) If we still supported MPX in the kernel, we'd have a real mess, because MPX malfunctions if user programs switch bitness on us. Good riddance! > > I don't have any comments on the other things you mentioned, except that > I need to go through them and better understand your suggestions. Would > you prefer me to rework this patch series with what you suggested or is > this something you want to take over and do yourself? Both ways are > fine by me. Please rework it :) I have seriously limited bandwidth right now.
Re: PROBLEM: 5.8-rc7 no video output with nouveau on NV36 (regression)
On Wed, 29 Jul 2020 at 15:05, Nick Bowler wrote: > > Hi, > > After installing Linux 5.8-rc7 I seem to get no video output on my > NV36 card once the nouveau module is loaded. The display (connected > to the digital output) simply reports "No Signal". > > I bisected to the following commit, and reverting this commit on > top of 5.8-rc7 appears to correct the issue. Can you test the drm fixes pull I just sent to Linus https://patchwork.freedesktop.org/patch/381225/ Otherwise we are awaiting a fix from James for one other issue, should be here today/tomorrow. Dave.
Re: [PATCH] ASoC: Intel: Atom: use hardware counter to update hw_ptr
On Wed, Jul 29, 2020 at 1:31 AM Pierre-Louis Bossart wrote: > > > > On 7/28/20 12:02 PM, Lu, Brent wrote: > >> > >> So if there are already quirks in atom machine drivers to change the period > >> size, why is this patch necessary? > >> > > > > The story is: google implemented the constraint but doesn't know why it > > works > > so asked us to explain. After checking the two counters I realized the > > increase of > > ring buffer pointer follows the period size setting in hw_param (256) but > > the > > period of interrupt is always 5ms instead of 5.33 so it's running little > > bit too fast. > > It seems the LPE keeps tracking the difference of two counters. When the > > difference exceeds 2160 samples, the next interrupt will be canceled so the > > hardware counter could catch up a little. > > > > [ 43.208299] intel_sst_acpi 808622A8:00: mrfld ring_buffer_counter 107520 > > hardware_counter 98880 pcm delay 8640 (in bytes) > > [ 43.208306] intel_sst_acpi 808622A8:00: buffer ptr 26880 pcm_delay rep: > > 2160 > > [ 43.208321] sound pcmC1D0p: [Q] pos 26880 hw_ptr 26880 appl_ptr 4 > > avail 191680 > > => one interrupt is skipped. > > [ 43.218299] intel_sst_acpi 808622A8:00: mrfld ring_buffer_counter 108544 > > hardware_counter 100800 pcm delay 7744 (in bytes) > > [ 43.218307] intel_sst_acpi 808622A8:00: buffer ptr 27136 pcm_delay rep: > > 1936 > > [ 43.218336] sound pcmC1D0p: [Q] pos 27136 hw_ptr 27136 appl_ptr 4 > > avail 191936 > > > > So I think why not using the hardware counter? It increases 240 samples > > every 5ms > > perfectly match the 48000 sample rate. The test result is good but I know > > there must > > be a reason for the original designer to use ring buffer counter instead of > > hardware > > counter. I uploaded this patch to see if anyone still remember the reason > > and share > > some insight with me. > > > > I totally agree that we shouldn't touch this part of design. Do you think > > it make sense > > to add a constraint to enforce the period size in machine driver? If yes > > then I would > > upload patches for Chrome atom machines for google. > > I think it'd make sense to add this constraint, either in the machine > driver or in the platform driver, so that we don't change the position > updates and introduce more issues by accident by doing so. As you > rightly said, I don't think anyone tested periods multiple of 256 > samples so it's not a regression, more aligning with the internal design. Thanks for the explanation and discussion. A slight correction in this thread is that CRAS does not set period size to 256. It just uses whatever value that driver wants to use, which happens to be 256. If the driver can limit the selection to only correct values that would be the best. Adding constraints in the machine driver or platform driver looks good. Prefer to adding in platform driver so we don't need to add for each machine driver. Thanks!
Re: [PATCHv2] coresight: etm4x: Fix etm4_count race by moving cpuhp callbacks to init
Hi Mike, On 2020-07-29 01:46, Mike Leach wrote: Hi Sai, On Tue, 28 Jul 2020 at 08:51, Sai Prakash Ranjan wrote: etm4_count keeps track of number of ETMv4 registered and on some systems, a race is observed on etm4_count variable which can lead to multiple calls to cpuhp_setup_state_nocalls_cpuslocked(). This function internally calls cpuhp_store_callbacks() which prevents multiple registrations of callbacks for a given state and due to this race, it returns -EBUSY leading to ETM probe failures like below. coresight-etm4x: probe of 704.etm failed with error -16 This race can easily be triggered with async probe by setting probe type as PROBE_PREFER_ASYNCHRONOUS and with ETM power management property "arm,coresight-loses-context-with-cpu". Prevent this race by moving cpuhp callbacks to etm driver init since the cpuhp callbacks doesn't have to depend on the etm4_count and can be once setup during driver init. Similarly we move cpu_pm notifier registration to driver init and completely remove etm4_count usage. Fixes: 9b6a3f3633a5 ("coresight: etmv4: Fix CPU power management setup in probe() function") Fixes: 58eb457be028 ("hwtracing/coresight-etm4x: Convert to hotplug state machine") Suggested-by: Suzuki K Poulose Signed-off-by: Sai Prakash Ranjan --- Changes in v2: * Rearrange cpuhp callbacks and move them to driver init (Suzuki K Poulose) --- drivers/hwtracing/coresight/coresight-etm4x.c | 51 ++- 1 file changed, 27 insertions(+), 24 deletions(-) diff --git a/drivers/hwtracing/coresight/coresight-etm4x.c b/drivers/hwtracing/coresight/coresight-etm4x.c index 6d7d2169bfb2..adb71987a1e3 100644 --- a/drivers/hwtracing/coresight/coresight-etm4x.c +++ b/drivers/hwtracing/coresight/coresight-etm4x.c @@ -48,8 +48,6 @@ module_param(pm_save_enable, int, 0444); MODULE_PARM_DESC(pm_save_enable, "Save/restore state on power down: 1 = never, 2 = self-hosted"); -/* The number of ETMv4 currently registered */ -static int etm4_count; static struct etmv4_drvdata *etmdrvdata[NR_CPUS]; static void etm4_set_default_config(struct etmv4_config *config); static int etm4_set_event_filters(struct etmv4_drvdata *drvdata, @@ -1403,12 +1401,9 @@ static int etm4_pm_setup_cpuslocked(void) { consider renaming this to etm4_pm_setup() and handing any cpu locking inside the function. In the circumstances - as part of the driver init rather than probe it may be sufficient to call the cpuhp_setup functions without the _cpuslocked suffix and allow the calls to lock the cpus as they are made. i.e. cpuhp_setup_state_nocalls_cpuslocked() => cpuhp_setup_state_nocalls() Sure, will make this change. int ret; - if (etm4_count++) - return 0; - ret = cpu_pm_register_notifier(_cpu_pm_nb); if (ret) - goto reduce_count; + return ret; ret = cpuhp_setup_state_nocalls_cpuslocked(CPUHP_AP_ARM_CORESIGHT_STARTING, "arm/coresight4:starting", @@ -1432,17 +1427,11 @@ static int etm4_pm_setup_cpuslocked(void) unregister_notifier: cpu_pm_unregister_notifier(_cpu_pm_nb); - -reduce_count: - --etm4_count; return ret; } static void etm4_pm_clear(void) { - if (--etm4_count != 0) - return; - cpu_pm_unregister_notifier(_cpu_pm_nb); cpuhp_remove_state_nocalls(CPUHP_AP_ARM_CORESIGHT_STARTING); if (hp_online) { @@ -1498,22 +1487,12 @@ static int etm4_probe(struct amba_device *adev, const struct amba_id *id) if (!desc.name) return -ENOMEM; - cpus_read_lock(); etmdrvdata[drvdata->cpu] = drvdata; if (smp_call_function_single(drvdata->cpu, etm4_init_arch_data, drvdata, 1)) dev_err(dev, "ETM arch init failed\n"); - ret = etm4_pm_setup_cpuslocked(); - cpus_read_unlock(); - - /* etm4_pm_setup_cpuslocked() does its own cleanup - exit on error */ - if (ret) { - etmdrvdata[drvdata->cpu] = NULL; - return ret; - } - if (etm4_arch_supported(drvdata->arch) == false) { ret = -EINVAL; goto err_arch_supported; @@ -1560,7 +1539,6 @@ static int etm4_probe(struct amba_device *adev, const struct amba_id *id) err_arch_supported: etmdrvdata[drvdata->cpu] = NULL; - etm4_pm_clear(); return ret; } @@ -1598,4 +1576,29 @@ static struct amba_driver etm4x_driver = { .probe = etm4_probe, .id_table = etm4_ids, }; -builtin_amba_driver(etm4x_driver); + +static int __init etm4x_init(void) +{ + int ret; + + cpus_read_lock(); + ret = etm4_pm_setup_cpuslocked(); + cpus_read_unlock(); See my comment above about rename and use of cpus_read_lock Yes, thanks for the review Mike. Thanks, Sai -- QUALCOMM INDIA, on behalf of Qualcomm Innovation
PROBLEM: 5.8-rc7 no video output with nouveau on NV36 (regression)
Hi, After installing Linux 5.8-rc7 I seem to get no video output on my NV36 card once the nouveau module is loaded. The display (connected to the digital output) simply reports "No Signal". I bisected to the following commit, and reverting this commit on top of 5.8-rc7 appears to correct the issue. fa4f4c213f5f7807360c41f2501a3031a9940f3a is the first bad commit commit fa4f4c213f5f7807360c41f2501a3031a9940f3a Author: James Jones Date: Mon Feb 10 15:15:55 2020 -0800 drm/nouveau/kms: Support NVIDIA format modifiers Allow setting the block layout of a nouveau FB object using DRM format modifiers. When specified, the format modifier block layout and kind overrides the GEM buffer's implicit layout and kind. The specified format modifier is validated against the list of modifiers supported by the target display hardware. v2: Used Tesla family instead of NV50 chipset compare v4: Do not cache kind, tile_mode in nouveau_framebuffer v5: Resolved against nouveau_framebuffer cleanup Signed-off-by: James Jones Signed-off-by: Ben Skeggs drivers/gpu/drm/nouveau/dispnv50/wndw.c | 20 --- drivers/gpu/drm/nouveau/nouveau_display.c | 89 ++- drivers/gpu/drm/nouveau/nouveau_display.h | 4 ++ 3 files changed, 104 insertions(+), 9 deletions(-) The dmesg output from loading the driver is identical except several lines are missing in the non-working case, which I have marked with "XXX" below: [ 168.222926] PCI Interrupt Link [LNKE] enabled at IRQ 16 [ 168.223199] nouveau :01:00.0: vgaarb: deactivate vga console [ 168.224379] Console: switching to colour dummy device 80x25 [ 168.224612] nouveau :01:00.0: NVIDIA NV36 (436200a1) [ 168.324779] nouveau :01:00.0: bios: version 04.36.20.21.00 [ 168.325646] agpgart-amd64 :00:00.0: AGP 3.0 bridge [ 168.325657] agpgart: modprobe tried to set rate=x12. Setting to AGP3 x8 mode. [ 168.325662] agpgart-amd64 :00:00.0: putting AGP V3 device into 8x mode [ 168.325679] nouveau :01:00.0: putting AGP V3 device into 8x mode [ 168.325908] agpgart-amd64 :00:00.0: AGP 3.0 bridge [ 168.325914] agpgart: modprobe tried to set rate=x12. Setting to AGP3 x8 mode. [ 168.325918] agpgart-amd64 :00:00.0: putting AGP V3 device into 8x mode [ 168.325933] nouveau :01:00.0: putting AGP V3 device into 8x mode [ 168.325990] nouveau :01:00.0: tmr: unknown input clock freq [ 168.326732] nouveau :01:00.0: fb: 256 MiB DDR1 [ 168.328174] [TTM] Zone kernel: Available graphics memory: 1022540 KiB [ 168.328175] [TTM] Initializing pool allocator [ 168.328181] [TTM] Initializing DMA pool allocator [ 168.328200] nouveau :01:00.0: DRM: VRAM: 255 MiB [ 168.328201] nouveau :01:00.0: DRM: GART: 128 MiB [ 168.328204] nouveau :01:00.0: DRM: BMP version 5.40 [ 168.328208] nouveau :01:00.0: DRM: DCB version 2.2 [ 168.328210] nouveau :01:00.0: DRM: DCB outp 00: 01000300 9c40 [ 168.328214] nouveau :01:00.0: DRM: DCB outp 01: 02010310 9c40 [ 168.328215] nouveau :01:00.0: DRM: DCB outp 02: 04000302 [ 168.328217] nouveau :01:00.0: DRM: DCB outp 03: 02020321 0303 [ 168.328495] nouveau :01:00.0: DRM: Loading NV17 power sequencing microcode [ 168.329691] nouveau :01:00.0: DRM: MM: using M2MF for buffer copies [ 168.330258] nouveau :01:00.0: DRM: Saving VGA fonts [ 168.389460] [drm] Supports vblank timestamp caching Rev 2 (21.10.2013). [ 168.391250] nouveau :01:00.0: DRM: Setting dpms mode 3 on TV encoder (output 3) XXX [ 168.487647] nouveau :01:00.0: DRM: allocated 1920x1080 fb: 0x9000, bo ff426de1 XXX [ 168.491835] fbcon: nouveaudrmfb (fb0) is primary device XXX [ 168.608512] nouveau :01:00.0: DRM: 0xE4FB: Parsing digital output script table XXX [ 168.662451] Console: switching to colour frame buffer device 240x67 XXX [ 168.755987] nouveau :01:00.0: fb0: nouveaudrmfb frame buffer device [ 168.763736] [drm] Initialized nouveau 1.3.1 20120801 for :01:00.0 on minor 0 Let me know if you need any more info. Cheers, Nick
RE: [PATCH V2 1/2] watchdog: imx7ulp: Strictly follow the sequence for wdog operations
Hi, Guenter > Subject: RE: [PATCH V2 1/2] watchdog: imx7ulp: Strictly follow the sequence > for wdog operations > > Hi, Guenter > > > > Subject: Re: [PATCH V2 1/2] watchdog: imx7ulp: Strictly follow the > > sequence for wdog operations > > > > On 7/28/20 7:20 PM, Anson Huang wrote: > > > According to reference manual, the i.MX7ULP WDOG's operations should > > > follow below sequence: > > > > > > 1. disable global interrupts; > > > 2. unlock the wdog and wait unlock bit set; 3. reconfigure the wdog > > > and wait for reconfiguration bit set; 4. enabel global interrupts. > > > > > > Strictly follow the recommended sequence can make it more robust. > > > > > > Signed-off-by: Anson Huang > > > --- > > > Changes since V1: > > > - use readl_poll_timeout_atomic() instead of usleep_ranges() since > > > IRQ is > > disabled. > > > --- > > > drivers/watchdog/imx7ulp_wdt.c | 29 + > > > 1 file changed, 29 insertions(+) > > > > > > diff --git a/drivers/watchdog/imx7ulp_wdt.c > > > b/drivers/watchdog/imx7ulp_wdt.c index 7993c8c..7d2b12e 100644 > > > --- a/drivers/watchdog/imx7ulp_wdt.c > > > +++ b/drivers/watchdog/imx7ulp_wdt.c > > > @@ -5,6 +5,7 @@ > > > > > > #include > > > #include > > > +#include > > > #include > > > #include > > > #include > > > @@ -36,6 +37,7 @@ > > > #define DEFAULT_TIMEOUT 60 > > > #define MAX_TIMEOUT 128 > > > #define WDOG_CLOCK_RATE 1000 > > > +#define WDOG_WAIT_TIMEOUT1 > > > > > > static bool nowayout = WATCHDOG_NOWAYOUT; > > module_param(nowayout, > > > bool, ); @@ -48,17 +50,31 @@ struct imx7ulp_wdt_device { > > > struct clk *clk; > > > }; > > > > > > +static inline void imx7ulp_wdt_wait(void __iomem *base, u32 mask) { > > > + u32 val = readl(base + WDOG_CS); > > > + > > > + if (!(val & mask)) > > > + WARN_ON(readl_poll_timeout_atomic(base + WDOG_CS, val, > > > + val & mask, 0, > > > + WDOG_WAIT_TIMEOUT)); > > > > I am not a friend of WARN_ON, especially in situations like this. > > Please explain why this is needed, and why a return of -ETIMEDOUT is > > not feasible. > > OK, I will use return value of -ETIMEOUT and handle it in the caller. After a further look, some of the imx7ulp_wdt_wait () callers are void function, so if want to handle the return value, all those functions return type need to be changed. And, when the return value is -ETIMEDOUT, the ONLY action is to print out some error message for these void function, need to use pr_err() due to no dev pointer available, so do you think it is acceptable to just replace the WARN_ON with pr_err() as below? + if (!(val & mask)) { + if (readl_poll_timeout_atomic(base + WDOG_CS, val, + val & mask, 0, + WDOG_WAIT_TIMEOUT)) + pr_err("wdog wait timeout, mask 0x%x\n", mask); + } Thanks, Anson
[PATCH v2] dt-bindings: regulator: Convert sy8824x to json-schema
From: Jisheng Zhang Convert the sy8824x binding to DT schema format using json-schema. Signed-off-by: Jisheng Zhang --- Since v1 -It seems there's something wrong with my last email, so send out a v2 with another email account .../bindings/regulator/silergy,sy8824x.yaml | 40 +++ .../devicetree/bindings/regulator/sy8824x.txt | 24 --- 2 files changed, 40 insertions(+), 24 deletions(-) create mode 100644 Documentation/devicetree/bindings/regulator/silergy,sy8824x.yaml delete mode 100644 Documentation/devicetree/bindings/regulator/sy8824x.txt diff --git a/Documentation/devicetree/bindings/regulator/silergy,sy8824x.yaml b/Documentation/devicetree/bindings/regulator/silergy,sy8824x.yaml new file mode 100644 index ..62a476c94111 --- /dev/null +++ b/Documentation/devicetree/bindings/regulator/silergy,sy8824x.yaml @@ -0,0 +1,40 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/regulator/silergy,sy8824x.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: silergy sy8824c,sy8824e,sy20276 and sy20278 PMIC + +maintainers: + - Jisheng Zhang + +properties: + compatible: +enum: + - silergy,sy8824c + - silergy,sy8824e + - silergy,sy20276 + - silergy,sy20278 + + reg: +maxItems: 1 + +required: + - compatible + - reg + +examples: + - | +i2c { +#address-cells = <1>; +#size-cells = <0>; +regulator@60 { + compatible = "silergy,sy8824c"; + regulator-min-microvolt = <80>; + regulator-max-microvolt = <115>; + reg = <0x60>; +}; +}; + +... diff --git a/Documentation/devicetree/bindings/regulator/sy8824x.txt b/Documentation/devicetree/bindings/regulator/sy8824x.txt deleted file mode 100644 index c5e95850c427.. --- a/Documentation/devicetree/bindings/regulator/sy8824x.txt +++ /dev/null @@ -1,24 +0,0 @@ -SY8824C/SY8824E/SY20276 Voltage regulator - -Required properties: -- compatible: Must be one of the following. - "silergy,sy8824c" - "silergy,sy8824e" - "silergy,sy20276" - "silergy,sy20278" -- reg: I2C slave address - -Any property defined as part of the core regulator binding, defined in -./regulator.txt, can also be used. - -Example: - - vcore: regulator@00 { - compatible = "silergy,sy8824c"; - reg = <0x66>; - regulator-name = "vcore"; - regulator-min-microvolt = <80>; - regulator-max-microvolt = <115>; - regulator-boot-on; - regulator-always-on; - }; -- 2.28.0.rc0
Re: [PATCH 3/6] arch: x86: Wrap TIF_X32 checks
On Tue, Jul 28, 2020 at 1:22 PM Gabriel Krisman Bertazi wrote: > > In preparation to remove TIF_X32, add a wrapper that checks the process > is using the X32 ABI without using the flag directly. I'm not sure what the right solution here is, but all three of these functions are in the ELF loading path, and the callers of all three have access to the full ELF info. Let's instead either stick enough information into bprm to figure out what ABI is being loaded or pass in a pointer to the ELF headers. The latter might be a bit nasty due to the way that the ELF headers have a different type for compat. In any case, sticking this into per-task state (task_struct or anything in it) is silly. The full ABI info is on the call stack, and there's no need to keep this particular bit around forever. --Andy
Re: [PATCH] scsi: 3w-9xxx: Fix endianness issues found by sparse
On 7/27/20 2:18 PM, Arnd Bergmann wrote: > On Sun, Jul 26, 2020 at 9:15 PM Samuel Holland wrote: >> >> The main issue observed was at the call to scsi_set_resid, where the >> byteswapped parameter would eventually trigger the alignment check at >> drivers/scsi/sd.c:2009. At that point, the kernel would continuously >> complain about an "Unaligned partial completion", and no further I/O >> could occur. >> >> This gets the controller working on big endian powerpc64. >> >> Signed-off-by: Samuel Holland >> --- >> drivers/scsi/3w-9xxx.c | 35 +-- >> drivers/scsi/3w-9xxx.h | 6 +- >> 2 files changed, 22 insertions(+), 19 deletions(-) >> >> diff --git a/drivers/scsi/3w-9xxx.c b/drivers/scsi/3w-9xxx.c >> index 3337b1e80412..95e25fda1f90 100644 >> --- a/drivers/scsi/3w-9xxx.c >> +++ b/drivers/scsi/3w-9xxx.c >> @@ -303,10 +303,10 @@ static int twa_aen_drain_queue(TW_Device_Extension >> *tw_dev, int no_check_reset) >> >> /* Initialize sglist */ >> memset(, 0, sizeof(TW_SG_Entry)); >> - sglist[0].length = TW_SECTOR_SIZE; >> - sglist[0].address = tw_dev->generic_buffer_phys[request_id]; >> + sglist[0].length = cpu_to_le32(TW_SECTOR_SIZE); >> + sglist[0].address = >> TW_CPU_TO_SGL(tw_dev->generic_buffer_phys[request_id]); > > This looks like it would add a sparse warning, not fix one, unless you also > change the types of the target structure. Yes, I meant to change the structure types as well. All of the command structures sent to the card are little-endian. I pulled this bugfix patch out of a series of unrelated changes, and I missed the header changes. I'll send a v2. >> @@ -501,7 +501,7 @@ static void twa_aen_sync_time(TW_Device_Extension >> *tw_dev, int request_id) >> Sunday 12:00AM */ >> local_time = (ktime_get_real_seconds() - (sys_tz.tz_minuteswest * >> 60)); >> div_u64_rem(local_time - (3 * 86400), 604800, ); >> - schedulertime = cpu_to_le32(schedulertime % 604800); >> + cpu_to_le32p(); >> >> memcpy(param->data, , sizeof(u32)); > > You dropped the '%' operation, and the result of the byteswap? schedulertime is the remainder from the previous line, so it is <604800 already. You're right about that being the wrong function -- I meant to use cpu_to_le32s to swap it in place, to avoid needing a second variable. >> @@ -1004,7 +1004,7 @@ static int twa_fill_sense(TW_Device_Extension *tw_dev, >> int request_id, int copy_ >> >> full_command_packet->header.status_block.error, >>error_str[0] == '\0' ? >>twa_string_lookup(twa_error_table, >> - >> full_command_packet->header.status_block.error) : error_str, >> + >> le16_to_cpu(full_command_packet->header.status_block.error)) : error_str, >> >> full_command_packet->header.err_specific_desc); >> else > > This looks correct, but the error value has already been copied into the local > 'error' variable, which you could use for simplification. As 'status_block' is > defined as a native_endian structure, this also introduced a sparse warning. I'll use 'error' in v2, thanks for the hint. >> @@ -1012,7 +1012,7 @@ static int twa_fill_sense(TW_Device_Extension *tw_dev, >> int request_id, int copy_ >> >> full_command_packet->header.status_block.error, >>error_str[0] == '\0' ? >>twa_string_lookup(twa_error_table, >> - >> full_command_packet->header.status_block.error) : error_str, >> + >> le16_to_cpu(full_command_packet->header.status_block.error)) : error_str, > > Same here > >Arnd > Cheers, Samuel
RE: [PATCH V2 1/2] watchdog: imx7ulp: Strictly follow the sequence for wdog operations
Hi, Guenter > Subject: Re: [PATCH V2 1/2] watchdog: imx7ulp: Strictly follow the sequence > for wdog operations > > On 7/28/20 7:20 PM, Anson Huang wrote: > > According to reference manual, the i.MX7ULP WDOG's operations should > > follow below sequence: > > > > 1. disable global interrupts; > > 2. unlock the wdog and wait unlock bit set; 3. reconfigure the wdog > > and wait for reconfiguration bit set; 4. enabel global interrupts. > > > > Strictly follow the recommended sequence can make it more robust. > > > > Signed-off-by: Anson Huang > > --- > > Changes since V1: > > - use readl_poll_timeout_atomic() instead of usleep_ranges() since IRQ > > is > disabled. > > --- > > drivers/watchdog/imx7ulp_wdt.c | 29 + > > 1 file changed, 29 insertions(+) > > > > diff --git a/drivers/watchdog/imx7ulp_wdt.c > > b/drivers/watchdog/imx7ulp_wdt.c index 7993c8c..7d2b12e 100644 > > --- a/drivers/watchdog/imx7ulp_wdt.c > > +++ b/drivers/watchdog/imx7ulp_wdt.c > > @@ -5,6 +5,7 @@ > > > > #include > > #include > > +#include > > #include > > #include > > #include > > @@ -36,6 +37,7 @@ > > #define DEFAULT_TIMEOUT60 > > #define MAX_TIMEOUT128 > > #define WDOG_CLOCK_RATE1000 > > +#define WDOG_WAIT_TIMEOUT 1 > > > > static bool nowayout = WATCHDOG_NOWAYOUT; > module_param(nowayout, > > bool, ); @@ -48,17 +50,31 @@ struct imx7ulp_wdt_device { > > struct clk *clk; > > }; > > > > +static inline void imx7ulp_wdt_wait(void __iomem *base, u32 mask) { > > + u32 val = readl(base + WDOG_CS); > > + > > + if (!(val & mask)) > > + WARN_ON(readl_poll_timeout_atomic(base + WDOG_CS, val, > > + val & mask, 0, > > + WDOG_WAIT_TIMEOUT)); > > I am not a friend of WARN_ON, especially in situations like this. > Please explain why this is needed, and why a return of -ETIMEDOUT is not > feasible. OK, I will use return value of -ETIMEOUT and handle it in the caller. > > Also, I do not believe that a 10 milli-second timeout is warranted. > This will need to be backed up by the datasheet. > There is no such info provided in reference manual or datasheet, but I just did an experiment, the unlock window is open in less than 1us after sending unlock command, and ONLY last for ONLY 2~3 us then close, the reconfiguration status bit will be set in less than 1us after register write. So what do you recommend for this timeout value? 100mS for safe? Thanks, Anson
Re: [PATCH 2/6] arch: x86: Wrap TIF_IA32 checks
Andy Lutomirski writes: > On Tue, Jul 28, 2020 at 1:22 PM Gabriel Krisman Bertazi > wrote: >> >> In preparation to remove TIF_IA32, add wrapper that check the process >> has IA32 ABI without using the flag directly. > > Thank you for doing this, but let's please do it right. There is, > fundamentally, no such thing as a "process with IA32 ABI". Hi Andy, Thanks a lot for your review. As you can see, I'm learning my way here. Can you clarify "there is no such a thing as a 'process with IA32 ABI'"? I'm not sure if I confused the terminology or if (more worrisome for me) I got the concepts wrong. My understanding is that TIF_IA32 marks a thread that is running under the 32-bit compat mode, which would be running a 32-bit process (as in compiled with -m32, for instance), while TIF_X32 marks a process running under the X32 ABI. Each process would have only one of these "personalities". This is what I meant by a process with IA32 ABI (which is wrong in any case). Is there more to it, or is the problem the terminology I used? I don't have any comments on the other things you mentioned, except that I need to go through them and better understand your suggestions. Would you prefer me to rework this patch series with what you suggested or is this something you want to take over and do yourself? Both ways are fine by me. Thanks, -- Gabriel Krisman Bertazi
[git pull] drm fixes for 5.8-rc8
Hi Linus, I'm sending this out a bit early, just to give you a chance to reject it or help decide on an rc8. The nouveau fixes missed the last pull by a few hours, and we had a few arm driver/panel/bridge fixes come in. This is possibly a bit more than I'm comfortable sending at this stage, but I've looked at each patch, the core + nouveau patches fix regressions, and the arm related ones are all around screens turning on and working, and are mostly trivial patches, the line count is mostly in comments. If you feel this is too much I'm happy to respin with the core/drm_fb_helper and nouveau fixes. we have one outstanding nouveau regression fix, that I'll follow this up with in the next day or so once Ben and James get it reviewed. Dave. This is possibly a bit drm-fixes-2020-07-29: drm fixes for 5.8-rc8 core: - fix possible use-after-free drm_fb_helper: - regression fix to use memcpy_io on bochs' sparc64 nouveau: - format modifiers fixes - HDA regression fix - turing modesetting race fix of: - fix a double free dbi: - fix SPI Type 1 transfer mcde: - fix screen stability crash panel: - panel: fix display noise on auo,kd101n80-45na - panel: delay HPD checks for boe_nv133fhm_n61 bridge: - bridge: drop connector check in nwl-dsi bridge - bridge: set proper bridge type for adv7511 The following changes since commit 92ed301919932f13b9172e525674157e983d: Linux 5.8-rc7 (2020-07-26 14:14:06 -0700) are available in the Git repository at: git://anongit.freedesktop.org/drm/drm tags/drm-fixes-2020-07-29 for you to fetch changes up to a4a2739beb8933a19281bca077fdb852598803ed: Merge tag 'drm-misc-fixes-2020-07-28' of git://anongit.freedesktop.org/drm/drm-misc into drm-fixes (2020-07-29 12:46:58 +1000) drm fixes for 5.8-rc8 core: - fix possible use-after-free drm_fb_helper: - regression fix to use memcpy_io on bochs' sparc64 nouveau: - format modifiers fixes - HDA regression fix - turing modesetting race fix of: - fix a double free dbi: - fix SPI Type 1 transfer mcde: - fix screen stability crash panel: - panel: fix display noise on auo,kd101n80-45na - panel: delay HPD checks for boe_nv133fhm_n61 bridge: - bridge: drop connector check in nwl-dsi bridge - bridge: set proper bridge type for adv7511 Ben Skeggs (5): drm/nouveau/disp/gm200-: fix regression from HDA SOR selection changes drm/nouveau/kms/gf100: use correct format modifiers drm/nouveau/kms/tu102: wait for core update to complete when assigning windows drm/nouveau/fbcon: fix module unload when fbcon init has failed for some reason drm/nouveau/fbcon: zero-initialise the mode_cmd2 structure Biju Das (1): drm: of: Fix double-free bug Dave Airlie (2): Merge branch 'linux-5.8' of git://github.com/skeggsb/linux into drm-fixes Merge tag 'drm-misc-fixes-2020-07-28' of git://anongit.freedesktop.org/drm/drm-misc into drm-fixes Douglas Anderson (1): drm: panel: simple: Delay HPD checking on boe_nv133fhm_n61 for 15 ms Guido Günther (1): drm/bridge: nwl-dsi: Drop DRM_BRIDGE_ATTACH_NO_CONNECTOR check. Jitao Shi (1): drm/panel: Fix auo, kd101n80-45na horizontal noise on edges of panel Laurentiu Palcu (1): drm/bridge/adv7511: set the bridge type properly Linus Walleij (1): drm/mcde: Fix stability issue Paul Cercueil (1): drm/dbi: Fix SPI Type 1 (9-bit) transfer Sam Ravnborg (1): drm/drm_fb_helper: fix fbdev with sparc64 Steve Cohen (1): drm: hold gem reference until object is no longer accessed drivers/gpu/drm/bochs/bochs_kms.c | 1 + drivers/gpu/drm/bridge/adv7511/adv7511_drv.c| 1 + drivers/gpu/drm/bridge/nwl-dsi.c| 5 - drivers/gpu/drm/drm_fb_helper.c | 6 - drivers/gpu/drm/drm_gem.c | 10 - drivers/gpu/drm/drm_mipi_dbi.c | 2 +- drivers/gpu/drm/drm_of.c| 4 +--- drivers/gpu/drm/mcde/mcde_display.c | 11 ++--- drivers/gpu/drm/nouveau/dispnv50/disp.c | 4 ++-- drivers/gpu/drm/nouveau/nouveau_fbcon.c | 3 ++- drivers/gpu/drm/nouveau/nvkm/engine/disp/outp.c | 30 + drivers/gpu/drm/panel/panel-boe-tv101wum-nl6.c | 6 ++--- drivers/gpu/drm/panel/panel-simple.c| 16 - include/drm/drm_mode_config.h | 12 ++ 14 files changed, 76 insertions(+), 35 deletions(-)
Re: [PATCH 02/10] block: virtio-blk: check logical block size
Hi Maxim, > Instead of this adding blk_is_valid_logical_block_size allowed me to > trivially convert most of the uses. > > For RFC I converted only some drivers that I am more familiar with > and/or can test but I can remove the driver's own checks in most other > drivers with low chance of introducing a bug, even if I can't test the > driver. > > What do you think? > > I can also both make blk_queue_logical_block_size return an error > value, and have blk_is_valid_logical_block_size and use either of > these checks, depending on the driver with eventual goal of > un-exporting blk_is_valid_logical_block_size. My concern is that blk_is_valid_logical_block_size() deviates from the regular block layer convention where the function to set a given queue limit will either adjust the passed value or print a warning. I guess I won't entirely object to having the actual check in a helper function that drivers with a peculiar initialization pattern can use. And then make blk_queue_logical_block_size() call that helper as well to validate the lbs. But I do think that blk_queue_logical_block_size() should be the preferred interface and that, where possible, drivers should be updated to check the return value of that. -- Martin K. Petersen Oracle Linux Engineering
[PATCH] idr: Fix a typo in idr_alloc_cyclic()'s comment
This patch fix a typo in comment for function idr_alloc_cyclic(). Signed-off-by: Wang Long --- lib/idr.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/idr.c b/lib/idr.c index c2cf2c5..47d203f 100644 --- a/lib/idr.c +++ b/lib/idr.c @@ -100,7 +100,7 @@ int idr_alloc(struct idr *idr, void *ptr, int start, int end, gfp_t gfp) * @end: The maximum ID (exclusive). * @gfp: Memory allocation flags. * - * Allocates an unused ID in the range specified by @nextid and @end. If + * Allocates an unused ID in the range specified by @start and @end. If * @end is <= 0, it is treated as one larger than %INT_MAX. This allows * callers to use @start + N as @end as long as N is within integer range. * The search for an unused ID will start at the last ID allocated and will -- 1.8.3.1
Re: [PATCH V2 1/2] watchdog: imx7ulp: Strictly follow the sequence for wdog operations
On 7/28/20 7:20 PM, Anson Huang wrote: > According to reference manual, the i.MX7ULP WDOG's operations should > follow below sequence: > > 1. disable global interrupts; > 2. unlock the wdog and wait unlock bit set; > 3. reconfigure the wdog and wait for reconfiguration bit set; > 4. enabel global interrupts. > > Strictly follow the recommended sequence can make it more robust. > > Signed-off-by: Anson Huang > --- > Changes since V1: > - use readl_poll_timeout_atomic() instead of usleep_ranges() since IRQ > is disabled. > --- > drivers/watchdog/imx7ulp_wdt.c | 29 + > 1 file changed, 29 insertions(+) > > diff --git a/drivers/watchdog/imx7ulp_wdt.c b/drivers/watchdog/imx7ulp_wdt.c > index 7993c8c..7d2b12e 100644 > --- a/drivers/watchdog/imx7ulp_wdt.c > +++ b/drivers/watchdog/imx7ulp_wdt.c > @@ -5,6 +5,7 @@ > > #include > #include > +#include > #include > #include > #include > @@ -36,6 +37,7 @@ > #define DEFAULT_TIMEOUT 60 > #define MAX_TIMEOUT 128 > #define WDOG_CLOCK_RATE 1000 > +#define WDOG_WAIT_TIMEOUT1 > > static bool nowayout = WATCHDOG_NOWAYOUT; > module_param(nowayout, bool, ); > @@ -48,17 +50,31 @@ struct imx7ulp_wdt_device { > struct clk *clk; > }; > > +static inline void imx7ulp_wdt_wait(void __iomem *base, u32 mask) > +{ > + u32 val = readl(base + WDOG_CS); > + > + if (!(val & mask)) > + WARN_ON(readl_poll_timeout_atomic(base + WDOG_CS, val, > + val & mask, 0, > + WDOG_WAIT_TIMEOUT)); I am not a friend of WARN_ON, especially in situations like this. Please explain why this is needed, and why a return of -ETIMEDOUT is not feasible. Also, I do not believe that a 10 milli-second timeout is warranted. This will need to be backed up by the datasheet. Guenter > +} > + > static void imx7ulp_wdt_enable(struct watchdog_device *wdog, bool enable) > { > struct imx7ulp_wdt_device *wdt = watchdog_get_drvdata(wdog); > > u32 val = readl(wdt->base + WDOG_CS); > > + local_irq_disable(); > writel(UNLOCK, wdt->base + WDOG_CNT); > + imx7ulp_wdt_wait(wdt->base, WDOG_CS_ULK); > if (enable) > writel(val | WDOG_CS_EN, wdt->base + WDOG_CS); > else > writel(val & ~WDOG_CS_EN, wdt->base + WDOG_CS); > + imx7ulp_wdt_wait(wdt->base, WDOG_CS_RCS); > + local_irq_enable(); > } > > static bool imx7ulp_wdt_is_enabled(void __iomem *base) > @@ -72,7 +88,12 @@ static int imx7ulp_wdt_ping(struct watchdog_device *wdog) > { > struct imx7ulp_wdt_device *wdt = watchdog_get_drvdata(wdog); > > + local_irq_disable(); > + writel(UNLOCK, wdt->base + WDOG_CNT); > + imx7ulp_wdt_wait(wdt->base, WDOG_CS_ULK); > writel(REFRESH, wdt->base + WDOG_CNT); > + imx7ulp_wdt_wait(wdt->base, WDOG_CS_RCS); > + local_irq_enable(); > > return 0; > } > @@ -98,8 +119,12 @@ static int imx7ulp_wdt_set_timeout(struct watchdog_device > *wdog, > struct imx7ulp_wdt_device *wdt = watchdog_get_drvdata(wdog); > u32 val = WDOG_CLOCK_RATE * timeout; > > + local_irq_disable(); > writel(UNLOCK, wdt->base + WDOG_CNT); > + imx7ulp_wdt_wait(wdt->base, WDOG_CS_ULK); > writel(val, wdt->base + WDOG_TOVAL); > + imx7ulp_wdt_wait(wdt->base, WDOG_CS_RCS); > + local_irq_enable(); > > wdog->timeout = timeout; > > @@ -140,15 +165,19 @@ static void imx7ulp_wdt_init(void __iomem *base, > unsigned int timeout) > { > u32 val; > > + local_irq_disable(); > /* unlock the wdog for reconfiguration */ > writel_relaxed(UNLOCK_SEQ0, base + WDOG_CNT); > writel_relaxed(UNLOCK_SEQ1, base + WDOG_CNT); > + imx7ulp_wdt_wait(base, WDOG_CS_ULK); > > /* set an initial timeout value in TOVAL */ > writel(timeout, base + WDOG_TOVAL); > /* enable 32bit command sequence and reconfigure */ > val = WDOG_CS_CMD32EN | WDOG_CS_CLK | WDOG_CS_UPDATE; > writel(val, base + WDOG_CS); > + imx7ulp_wdt_wait(base, WDOG_CS_RCS); > + local_irq_enable(); > } > > static void imx7ulp_wdt_action(void *data) >
Re: [PATCH] scsi: iscsi: Do not put host in iscsi_set_flashnode_param()
On Mon, 15 Jun 2020 16:12:26 +0800, Jing Xiangfeng wrote: > If scsi_host_lookup() failes we will jump to put_host, which may > cause panic. Jump to exit_set_fnode to fix it. Applied to 5.9/scsi-queue, thanks! [1/1] scsi: iscsi: Do not put host in iscsi_set_flashnode_param() https://git.kernel.org/mkp/scsi/c/68e12e5f6135 -- Martin K. Petersen Oracle Linux Engineering
Re: [PATCH v1] scsi: ufs-mediatek: Prevent LPM operation on undeclared VCC
On Fri, 24 Jul 2020 22:16:27 +0800, Stanley Chu wrote: > In some platforms, VCC regulator may not be declared in device tree > to keep itself "always-on". In this case, hba->vreg_info.vcc is NULL > and shall not be operated during any flow. > > Prevent possible NULL hba->vreg_info.vcc access in LPM mode by checking > if it is valid first. Applied to 5.9/scsi-queue, thanks! [1/1] scsi: ufs-mediatek: Prevent LPM operation on undeclared VCC https://git.kernel.org/mkp/scsi/c/0255b1e3d849 -- Martin K. Petersen Oracle Linux Engineering
Re: [PATCH v17 17/21] mm/lru: replace pgdat lru_lock with lruvec lock
rewrite the commit log. >From 5e9340444632d69cf10c8db521577d0637819c5f Mon Sep 17 00:00:00 2001 From: Alex Shi Date: Tue, 26 May 2020 17:27:52 +0800 Subject: [PATCH v17 17/23] mm/lru: replace pgdat lru_lock with lruvec lock This patch moves per node lru_lock into lruvec, thus bring a lru_lock for each of memcg per node. So on a large machine, each of memcg don't have to suffer from per node pgdat->lru_lock competition. They could go fast with their self lru_lock. After move memcg charge before lru inserting, page isolation could serialize page's memcg, then per memcg lruvec lock is stable and could replace per node lru lock. In func isolate_migratepages_block, compact_unlock_should_abort is opend, and lock_page_lruvec logical is embedded for tight process. Also add a debug func in locking which may give some clues if there are sth out of hands. According to Daniel Jordan's suggestion, I run 208 'dd' with on 104 containers on a 2s * 26cores * HT box with a modefied case: https://git.kernel.org/pub/scm/linux/kernel/git/wfg/vm-scalability.git/tree/case-lru-file-readtwice With this and later patches, the readtwice performance increases about 80% within concurrent containers. On a large but non memcg machine, the extra recheck if page's lruvec should be changed in few place, that increase a little lock holding time, and a little regression. Hugh Dickins helped on patch polish, thanks! Reported-by: kernel test robot Signed-off-by: Alex Shi Cc: Hugh Dickins Cc: Andrew Morton Cc: Johannes Weiner Cc: Michal Hocko Cc: Vladimir Davydov Cc: Yang Shi Cc: Matthew Wilcox Cc: Konstantin Khlebnikov Cc: Tejun Heo Cc: linux-kernel@vger.kernel.org Cc: linux...@kvack.org Cc: cgro...@vger.kernel.org --- include/linux/memcontrol.h | 58 + include/linux/mmzone.h | 2 + mm/compaction.c| 67 ++--- mm/huge_memory.c | 11 ++--- mm/memcontrol.c| 63 ++- mm/mlock.c | 47 +--- mm/mmzone.c| 1 + mm/swap.c | 104 + mm/vmscan.c| 70 -- 9 files changed, 288 insertions(+), 135 deletions(-) diff --git a/include/linux/memcontrol.h b/include/linux/memcontrol.h index e77197a62809..258901021c6c 100644 --- a/include/linux/memcontrol.h +++ b/include/linux/memcontrol.h @@ -411,6 +411,19 @@ static inline struct lruvec *mem_cgroup_lruvec(struct mem_cgroup *memcg, struct mem_cgroup *get_mem_cgroup_from_page(struct page *page); +struct lruvec *lock_page_lruvec(struct page *page); +struct lruvec *lock_page_lruvec_irq(struct page *page); +struct lruvec *lock_page_lruvec_irqsave(struct page *page, + unsigned long *flags); + +#ifdef CONFIG_DEBUG_VM +void lruvec_memcg_debug(struct lruvec *lruvec, struct page *page); +#else +static inline void lruvec_memcg_debug(struct lruvec *lruvec, struct page *page) +{ +} +#endif + static inline struct mem_cgroup *mem_cgroup_from_css(struct cgroup_subsys_state *css){ return css ? container_of(css, struct mem_cgroup, css) : NULL; @@ -892,6 +905,31 @@ static inline void mem_cgroup_put(struct mem_cgroup *memcg) { } +static inline struct lruvec *lock_page_lruvec(struct page *page) +{ + struct pglist_data *pgdat = page_pgdat(page); + + spin_lock(>__lruvec.lru_lock); + return >__lruvec; +} + +static inline struct lruvec *lock_page_lruvec_irq(struct page *page) +{ + struct pglist_data *pgdat = page_pgdat(page); + + spin_lock_irq(>__lruvec.lru_lock); + return >__lruvec; +} + +static inline struct lruvec *lock_page_lruvec_irqsave(struct page *page, + unsigned long *flagsp) +{ + struct pglist_data *pgdat = page_pgdat(page); + + spin_lock_irqsave(>__lruvec.lru_lock, *flagsp); + return >__lruvec; +} + static inline struct mem_cgroup * mem_cgroup_iter(struct mem_cgroup *root, struct mem_cgroup *prev, @@ -1126,6 +1164,10 @@ static inline void count_memcg_page_event(struct page *page, void count_memcg_event_mm(struct mm_struct *mm, enum vm_event_item idx) { } + +static inline void lruvec_memcg_debug(struct lruvec *lruvec, struct page *page) +{ +} #endif /* CONFIG_MEMCG */ /* idx can be of type enum memcg_stat_item or node_stat_item */ @@ -1255,6 +1297,22 @@ static inline struct lruvec *parent_lruvec(struct lruvec *lruvec) return mem_cgroup_lruvec(memcg, lruvec_pgdat(lruvec)); } +static inline void unlock_page_lruvec(struct lruvec *lruvec) +{ + spin_unlock(>lru_lock); +} + +static inline void unlock_page_lruvec_irq(struct lruvec *lruvec) +{ + spin_unlock_irq(>lru_lock); +} + +static inline void unlock_page_lruvec_irqrestore(struct lruvec *lruvec, + unsigned long flags) +{ + spin_unlock_irqrestore(>lru_lock, flags); +} + #ifdef
Re: [PATCH v17 13/21] mm/lru: introduce TestClearPageLRU
rewrite the commit log. >From 9310c359b0049e3cc9827b771dc583d504bbf022 Mon Sep 17 00:00:00 2001 From: Alex Shi Date: Sat, 25 Apr 2020 12:03:30 +0800 Subject: [PATCH v17 13/23] mm/lru: introduce TestClearPageLRU Currently lru_lock still guards both lru list and page's lru bit, that's ok. but if we want to use specific lruvec lock on the page, we need to pin down the page's lruvec/memcg during locking. Just taking lruvec lock first may be undermined by the page's memcg charge/migration. To fix this problem, we could clear the lru bit out of locking and use it as pin down action to block the page isolation in memcg changing. So now a standard steps of page isolation is following: 1, get_page(); #pin the page avoid to be free 2, TestClearPageLRU(); #block other isolation like memcg change 3, spin_lock on lru_lock; #serialize lru list access 4, delete page from lru list; The step 2 could be optimzed/replaced in scenarios which page is unlikely be accessed or be moved between memcgs. This patch start with the first part: TestClearPageLRU, which combines PageLRU check and ClearPageLRU into a macro func TestClearPageLRU. This function will be used as page isolation precondition to prevent other isolations some where else. Then there are may !PageLRU page on lru list, need to remove BUG() checking accordingly. There 2 rules for lru bit now: 1, the lru bit still indicate if a page on lru list, just in some temporary moment(isolating), the page may have no lru bit when it's on lru list. but the page still must be on lru list when the lru bit set. 2, have to remove lru bit before delete it from lru list. Hugh Dickins pointed that when a page is in free path and no one is possible to take it, non atomic lru bit clearing is better, like in __page_cache_release and release_pages. And no need get_page() before lru bit clear in isolate_lru_page, since it '(1) Must be called with an elevated refcount on the page'. As Andrew Morton mentioned this change would dirty cacheline for page isn't on LRU. But the lost would be acceptable with Rong Chen report: https://lkml.org/lkml/2020/3/4/173 Suggested-by: Johannes Weiner Signed-off-by: Alex Shi Cc: Hugh Dickins Cc: Johannes Weiner Cc: Michal Hocko Cc: Vladimir Davydov Cc: Andrew Morton Cc: linux-kernel@vger.kernel.org Cc: cgro...@vger.kernel.org Cc: linux...@kvack.org --- include/linux/page-flags.h | 1 + mm/mlock.c | 3 +-- mm/swap.c | 6 ++ mm/vmscan.c| 18 +++--- 4 files changed, 11 insertions(+), 17 deletions(-) diff --git a/include/linux/page-flags.h b/include/linux/page-flags.h index 6be1aa559b1e..9554ed1387dc 100644 --- a/include/linux/page-flags.h +++ b/include/linux/page-flags.h @@ -326,6 +326,7 @@ static inline void page_init_poison(struct page *page, size_t size) PAGEFLAG(Dirty, dirty, PF_HEAD) TESTSCFLAG(Dirty, dirty, PF_HEAD) __CLEARPAGEFLAG(Dirty, dirty, PF_HEAD) PAGEFLAG(LRU, lru, PF_HEAD) __CLEARPAGEFLAG(LRU, lru, PF_HEAD) + TESTCLEARFLAG(LRU, lru, PF_HEAD) PAGEFLAG(Active, active, PF_HEAD) __CLEARPAGEFLAG(Active, active, PF_HEAD) TESTCLEARFLAG(Active, active, PF_HEAD) PAGEFLAG(Workingset, workingset, PF_HEAD) diff --git a/mm/mlock.c b/mm/mlock.c index f8736136fad7..228ba5a8e0a5 100644 --- a/mm/mlock.c +++ b/mm/mlock.c @@ -108,13 +108,12 @@ void mlock_vma_page(struct page *page) */ static bool __munlock_isolate_lru_page(struct page *page, bool getpage) { - if (PageLRU(page)) { + if (TestClearPageLRU(page)) { struct lruvec *lruvec; lruvec = mem_cgroup_page_lruvec(page, page_pgdat(page)); if (getpage) get_page(page); - ClearPageLRU(page); del_page_from_lru_list(page, lruvec, page_lru(page)); return true; } diff --git a/mm/swap.c b/mm/swap.c index f645965fde0e..5092fe9c8c47 100644 --- a/mm/swap.c +++ b/mm/swap.c @@ -83,10 +83,9 @@ static void __page_cache_release(struct page *page) struct lruvec *lruvec; unsigned long flags; + __ClearPageLRU(page); spin_lock_irqsave(>lru_lock, flags); lruvec = mem_cgroup_page_lruvec(page, pgdat); - VM_BUG_ON_PAGE(!PageLRU(page), page); - __ClearPageLRU(page); del_page_from_lru_list(page, lruvec, page_off_lru(page)); spin_unlock_irqrestore(>lru_lock, flags); } @@ -878,9 +877,8 @@ void release_pages(struct page **pages, int nr) spin_lock_irqsave(_pgdat->lru_lock, flags); } - lruvec = mem_cgroup_page_lruvec(page, locked_pgdat); - VM_BUG_ON_PAGE(!PageLRU(page), page); __ClearPageLRU(page); + lruvec = mem_cgroup_page_lruvec(page, locked_pgdat);
Re: [PATCH v10 4/5] arm64: kdump: fix kdump broken with ZONE_DMA reintroduced
Hi Catalin, On 2020/7/28 1:30, Catalin Marinas wrote: > On Fri, Jul 03, 2020 at 11:58:15AM +0800, Chen Zhou wrote: >> commit 1a8e1cef7603 ("arm64: use both ZONE_DMA and ZONE_DMA32") >> broken the arm64 kdump. If the memory reserved for crash dump kernel >> falled in ZONE_DMA32, the devices in crash dump kernel need to use >> ZONE_DMA will alloc fail. >> >> This patch addressed the above issue based on "reserving crashkernel >> above 4G". Originally, we reserve low memory below 4G, and now just need >> to adjust memory limit to arm64_dma_phys_limit in reserve_crashkernel_low >> if ZONE_DMA is enabled. That is, if there are devices need to use ZONE_DMA >> in crash dump kernel, it is a good choice to use parameters >> "crashkernel=X crashkernel=Y,low". >> >> Signed-off-by: Chen Zhou >> --- >> kernel/crash_core.c | 7 ++- >> 1 file changed, 6 insertions(+), 1 deletion(-) >> >> diff --git a/kernel/crash_core.c b/kernel/crash_core.c >> index a7580d291c37..e8ecbbc761a3 100644 >> --- a/kernel/crash_core.c >> +++ b/kernel/crash_core.c >> @@ -320,6 +320,7 @@ int __init reserve_crashkernel_low(void) >> unsigned long long base, low_base = 0, low_size = 0; >> unsigned long total_low_mem; >> int ret; >> +phys_addr_t crash_max = 1ULL << 32; >> >> total_low_mem = memblock_mem_size(1UL << (32 - PAGE_SHIFT)); >> >> @@ -352,7 +353,11 @@ int __init reserve_crashkernel_low(void) >> return 0; >> } >> >> -low_base = memblock_find_in_range(0, 1ULL << 32, low_size, CRASH_ALIGN); >> +#ifdef CONFIG_ARM64 >> +if (IS_ENABLED(CONFIG_ZONE_DMA)) >> +crash_max = arm64_dma_phys_limit; >> +#endif >> +low_base = memblock_find_in_range(0, crash_max, low_size, CRASH_ALIGN); >> if (!low_base) { >> pr_err("Cannot reserve %ldMB crashkernel low memory, please try >> smaller size.\n", >> (unsigned long)(low_size >> 20)); > Given the number of #ifdefs we end up with in this function, I think > it's better to simply copy to the code to arch/arm64 and tailor it > accordingly. > > Anyway, there are two series solving slightly different issues with > kdump reservations: > > 1. This series which relaxes the crashkernel= allocation to go anywhere >in the accessible space while having a dedicated crashkernel=X,low >option for ZONE_DMA. > > 2. Bhupesh's series [1] forcing crashkernel=X allocations only from >ZONE_DMA. > > For RPi4 support, we limited ZONE_DMA allocations to the 1st GB. > Existing crashkernel= uses may no longer work, depending on where the > allocation falls. Option (2) above is a quick fix assuming that the > crashkernel reservation is small enough. What's a typical crashkernel > option here? That series is probably more prone to reservation failures. > > Option (1), i.e. this series, doesn't solve the problem raised by > Bhupesh unless one uses the crashkernel=X,low argument. It can actually > make it worse even for ZONE_DMA32 since the allocation can go above 4G > (assuming that we change the ZONE_DMA configuration to only limit it to > 1GB on RPi4). > > I'm more inclined to keep the crashkernel= behaviour to ZONE_DMA > allocations. If this is too small for typical kdump, we can look into > expanding ZONE_DMA to 4G on non-RPi4 hardware (we had patches on the > list). In addition, if Chen thinks allocations above 4G are still needed > or if RPi4 needs a sufficiently large crashkernel=, I'd rather have a > ",high" option to explicitly require such access. Thanks for your reply and exhaustive explanation. In our ARM servers, we need to to reserve a large chunk for kdump(512M or 1G), there is no enough low memory. So we proposed this patch series "support reserving crashkernel above 4G on arm64 kdump" In April 2019. I introduce parameters "crashkernel=X,[high,low]" as x86_64 does in earlier versions. Suggested by James, to simplify, we call reserve_crashkernel_low() at the beginning of reserve_crashkernel() and then relax the arm64_dma32_phys_limit if reserve_crashkernel_low() allocated something. That is, just the parameter "crashkernel=X,low" is ok and i deleted "crashkernel=X,high". After the ZONE_DMA introduced in December 2019, the issue occurred as you said above. In fact, we didn't have RPi4 machine. Originally, i suggested to fix this based on this patch series and used the dedicated option. According to your clarify, for typical kdump, there are other solutions. In this case, "keep the crashkernel= behaviour to ZONE_DMA allocations" looks much better. How about like this: 1. For ZONE_DMA issue, use Bhupesh's solution, keep the crashkernel= behaviour to ZONE_DMA allocations. 2. For this patch series, make the reserve_crashkernel_low() to ZONE_DMA allocations. Thanks, Chen Zhou > [1] http://lists.infradead.org/pipermail/kexec/2020-July/020777.html >
Re: [char-misc-next] Revert "mei: hdcp: Replace one-element array with flexible-array member"
On 7/28/20 18:16, Gustavo A. R. Silva wrote: > > > On 7/28/20 18:04, Gustavo A. R. Silva wrote: >> Tomas, >> >> Please, see some comments below... >> >> On 7/28/20 17:29, Winkler, Tomas wrote: >>> >>> Hi Tomas, >>> >>> On 7/28/20 16:41, Tomas Winkler wrote: Greg please revert, this commit it changes size of struct wired_cmd_repeater_auth_stream_req_in, this is not what firmware is expecting. >>> Instead of reverting that commit, I think this patch should be applied to fix it, if Tomas consider this is the appropiate solution: diff --git a/drivers/misc/mei/hdcp/mei_hdcp.c b/drivers/misc/mei/hdcp/mei_hdcp.c index d1d3e025ca0e..852374565cba 100644 --- a/drivers/misc/mei/hdcp/mei_hdcp.c +++ b/drivers/misc/mei/hdcp/mei_hdcp.c @@ -572,12 +572,12 @@ static int mei_hdcp_verify_mprime(struct device *dev, HDCP_2_2_MPRIME_LEN); drm_hdcp_cpu_to_be24(verify_mprime_in.seq_num_m, data->seq_num_m); memcpy(verify_mprime_in.streams, data->streams, - array_size(data->k, sizeof(*data->streams))); + flex_array_size(_mprime_in, streams, data->k)); verify_mprime_in.k = cpu_to_be16(data->k); byte = mei_cldev_send(cldev, (u8 *)_mprime_in, - sizeof(verify_mprime_in)); + struct_size(_mprime_in, streams, data->k)); if (byte < 0) { dev_dbg(dev, "mei_cldev_send failed. %zd\n", byte); return byte; I'll write up a proper patch after getting some feedback. Thanks -- Gustavo >>> Could you elaborate on what's the firmware expecting, exactly? >> struct wired_cmd_repeater_auth_stream_req_in { >> - struct hdcp2_streamid_type streams[1]; >> + struct hdcp2_streamid_type streams[]; >> } >> >> But then you have, which you haven't changed to + 1 byte = >> mei_cldev_send(cldev, (u8 *)_mprime_in, >> sizeof(verify_mprime_in)); >> >> >> I don't think the fix for this is to add 1 byte, if any, it seems >> to be sizeof(*data->streams), or sizeof(struct hdcp2_streamid_type) >> what needs to be added. >> >> But it might be better to code something like this, instead: >> >> diff --git a/drivers/misc/mei/hdcp/mei_hdcp.c >> b/drivers/misc/mei/hdcp/mei_hdcp.c >> index e6c3dc595617..7fe63c915548 100644 >> --- a/drivers/misc/mei/hdcp/mei_hdcp.c >> +++ b/drivers/misc/mei/hdcp/mei_hdcp.c >> @@ -572,12 +572,12 @@ static int mei_hdcp_verify_mprime(struct device *dev, >>HDCP_2_2_MPRIME_LEN); >> drm_hdcp_cpu_to_be24(verify_mprime_in.seq_num_m, data->seq_num_m); >> memcpy(verify_mprime_in.streams, data->streams, >> - (data->k * sizeof(struct hdcp2_streamid_type))); >> + (data->k * sizeof(*data->streams))); >> >> verify_mprime_in.k = cpu_to_be16(data->k); >> >> byte = mei_cldev_send(cldev, (u8 *)_mprime_in, >> - sizeof(verify_mprime_in)); >> + struct_size(_mprime_in, streams, >> data->k)); >> if (byte < 0) { >> dev_dbg(dev, "mei_cldev_send failed. %zd\n", byte); >> return byte; >> >> struct_size(_mprime_in, streams, data->k) will give us the size, in >> bytes, >> of struct wired_cmd_repeater_auth_stream_req_in plus the size in bytes for >> the streams[] flexible-array, which is determined by struct >> hdcp2_streamid_type and >> data->k. >> >> What do you think? >> > > This is even better: > > diff --git a/drivers/misc/mei/hdcp/mei_hdcp.c > b/drivers/misc/mei/hdcp/mei_hdcp.c > index e6c3dc595617..852374565cba 100644 > --- a/drivers/misc/mei/hdcp/mei_hdcp.c > +++ b/drivers/misc/mei/hdcp/mei_hdcp.c > @@ -572,12 +572,12 @@ static int mei_hdcp_verify_mprime(struct device *dev, >HDCP_2_2_MPRIME_LEN); > drm_hdcp_cpu_to_be24(verify_mprime_in.seq_num_m, data->seq_num_m); > memcpy(verify_mprime_in.streams, data->streams, > - (data->k * sizeof(struct hdcp2_streamid_type))); > + flex_array_size(_mprime_in, streams, data->k)); > > verify_mprime_in.k = cpu_to_be16(data->k); > > byte = mei_cldev_send(cldev, (u8 *)_mprime_in, > - sizeof(verify_mprime_in)); > + struct_size(_mprime_in, streams, > data->k)); > if (byte < 0) { > dev_dbg(dev, "mei_cldev_send failed. %zd\n", byte); > return byte; > > the flex_array_size() is a new helper that was designed for this situations. > :) > It calculates the size of a flexible array member within an enclosing > structure, > which is exactly the case. > > Thanks > -- > Gustavo > >> See more comments below... >> > > I see, this is the kind of feedback I need from people that knows the > code better. Thanks! > >> But that's not the major point. Point is that we should
[PATCH v4 3/4] docs: Add documentation for userspace client interface
MHI userspace client driver is creating device file node for user application to perform file operations. File operations are handled by MHI core driver. Currently Loopback MHI channel is supported by this driver. Signed-off-by: Hemant Kumar --- Documentation/mhi/index.rst | 1 + Documentation/mhi/uci.rst | 39 +++ 2 files changed, 40 insertions(+) create mode 100644 Documentation/mhi/uci.rst diff --git a/Documentation/mhi/index.rst b/Documentation/mhi/index.rst index 1d8dec3..c75a371 100644 --- a/Documentation/mhi/index.rst +++ b/Documentation/mhi/index.rst @@ -9,6 +9,7 @@ MHI mhi topology + uci .. only:: subproject and html diff --git a/Documentation/mhi/uci.rst b/Documentation/mhi/uci.rst new file mode 100644 index 000..5d92939 --- /dev/null +++ b/Documentation/mhi/uci.rst @@ -0,0 +1,39 @@ +.. SPDX-License-Identifier: GPL-2.0 + += +Userspace Client Interface (UCI) += + +UCI driver enables userspace clients to communicate to external MHI devices +like modem and WLAN. It creates standard character device file nodes for user +space clients to perform open, read, write, poll and close file operations. + +Device file node is created with format:- + +/dev/mhi__ + +controller_name is the name of underlying bus used to transfer data. +mhi_device_name is the name of the MHI channel being used by MHI client in +userspace to send or receive data using MHI protocol. + +There is a separate character device file node created for each channel specified +in mhi device id table. MHI channels are statically defined by MHI specification. +Driver currently supports LOOPBACK channel 0 (Host to device) and 1 (Device to Host). + +LOOPBACK Channel + + +Userspace MHI client using LOOPBACK channel opens device file node. As part of +open operation TREs to transfer ring of LOOPBACK channel 1 gets queued and channel +doorbell is rung. When userspace MHI client performs write operation on device node, +data buffer gets queued as a TRE to transfer ring of LOOPBACK channel 0. MHI Core +driver rings the channel doorbell for MHI device to move data over underlying bus. +When userspace MHI client driver performs read operation, same data gets looped back +to MHI host using LOOPBACK channel 1. LOOPBACK channel is used to verify data path +and data integrity between MHI Host and MHI device. + +Other Use Cases +--- + +Getting MHI device specific diagnostics information to userspace MHI diag client +using DIAG channel 4 (Host to device) and 5 (Device to Host). -- The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum, a Linux Foundation Collaborative Project
[PATCH v4 1/4] bus: mhi: core: Add helper API to return number of free TREs
Introduce mhi_get_no_free_descriptors() API to return number of TREs available to queue buffer. MHI clients can use this API to know before hand if ring is full without calling queue API. Signed-off-by: Hemant Kumar --- drivers/bus/mhi/core/main.c | 12 include/linux/mhi.h | 9 + 2 files changed, 21 insertions(+) diff --git a/drivers/bus/mhi/core/main.c b/drivers/bus/mhi/core/main.c index 2cff5dd..0599e7d 100644 --- a/drivers/bus/mhi/core/main.c +++ b/drivers/bus/mhi/core/main.c @@ -258,6 +258,18 @@ int mhi_destroy_device(struct device *dev, void *data) return 0; } +int mhi_get_no_free_descriptors(struct mhi_device *mhi_dev, + enum dma_data_direction dir) +{ + struct mhi_controller *mhi_cntrl = mhi_dev->mhi_cntrl; + struct mhi_chan *mhi_chan = (dir == DMA_TO_DEVICE) ? + mhi_dev->ul_chan : mhi_dev->dl_chan; + struct mhi_ring *tre_ring = _chan->tre_ring; + + return get_nr_avail_ring_elements(mhi_cntrl, tre_ring); +} +EXPORT_SYMBOL_GPL(mhi_get_no_free_descriptors); + void mhi_notify(struct mhi_device *mhi_dev, enum mhi_callback cb_reason) { struct mhi_driver *mhi_drv; diff --git a/include/linux/mhi.h b/include/linux/mhi.h index a35d876..6565528 100644 --- a/include/linux/mhi.h +++ b/include/linux/mhi.h @@ -600,6 +600,15 @@ void mhi_set_mhi_state(struct mhi_controller *mhi_cntrl, void mhi_notify(struct mhi_device *mhi_dev, enum mhi_callback cb_reason); /** + * mhi_get_no_free_descriptors - Get transfer ring length + * Get # of TD available to queue buffers + * @mhi_dev: Device associated with the channels + * @dir: Direction of the channel + */ +int mhi_get_no_free_descriptors(struct mhi_device *mhi_dev, + enum dma_data_direction dir); + +/** * mhi_prepare_for_power_up - Do pre-initialization before power up. *This is optional, call this before power up if *the controller does not want bus framework to -- The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum, a Linux Foundation Collaborative Project
[RFC PATCH] arm64: defconfig: Disable fine-grained task level IRQ time accounting
In the current arm64 defconfig, CONFIG_IRQ_TIME_ACCOUNTING is enabled as default. According to my tests on NXP's LayerScape and i.MX platforms, the system hangs when running the command "stress-ng --hrtimers 1" with CONFIG_IRQ_TIME_ACCOUNTING enabled. Disabling this option, the issue disappears. CONFIG_IRQ_TIME_ACCOUNTING causes serious performance impact when running hrtimer stress test at the same time. Signed-off-by: Alison Wang --- arch/arm64/configs/defconfig | 1 - 1 file changed, 1 deletion(-) diff --git a/arch/arm64/configs/defconfig b/arch/arm64/configs/defconfig index e0f33826819f..ff1c11d8b10b 100644 --- a/arch/arm64/configs/defconfig +++ b/arch/arm64/configs/defconfig @@ -4,7 +4,6 @@ CONFIG_AUDIT=y CONFIG_NO_HZ_IDLE=y CONFIG_HIGH_RES_TIMERS=y CONFIG_PREEMPT=y -CONFIG_IRQ_TIME_ACCOUNTING=y CONFIG_BSD_PROCESS_ACCT=y CONFIG_BSD_PROCESS_ACCT_V3=y CONFIG_TASK_XACCT=y -- 2.17.1
[PATCH v4 0/4] user space client interface driver
V4: - Fix locking to protect proper struct members. - Updated documentation describing uci client driver use cases. - Fixed uci ref counting in mhi_uci_open for error case. - Addressed style related review comments. V3: Added documentation for MHI UCI driver. V2: Added mutex lock to prevent multiple readers to access same mhi buffer which can result into use after free. Hemant Kumar (4): bus: mhi: core: Add helper API to return number of free TREs bus: mhi: core: Move MHI_MAX_MTU to external header file docs: Add documentation for userspace client interface bus: mhi: clients: Add userspace client interface driver Documentation/mhi/index.rst | 1 + Documentation/mhi/uci.rst| 39 +++ drivers/bus/mhi/Kconfig | 6 + drivers/bus/mhi/Makefile | 1 + drivers/bus/mhi/clients/Kconfig | 15 + drivers/bus/mhi/clients/Makefile | 3 + drivers/bus/mhi/clients/uci.c| 690 +++ drivers/bus/mhi/core/internal.h | 1 - drivers/bus/mhi/core/main.c | 12 + include/linux/mhi.h | 12 + 10 files changed, 779 insertions(+), 1 deletion(-) create mode 100644 Documentation/mhi/uci.rst create mode 100644 drivers/bus/mhi/clients/Kconfig create mode 100644 drivers/bus/mhi/clients/Makefile create mode 100644 drivers/bus/mhi/clients/uci.c -- The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum, a Linux Foundation Collaborative Project
[PATCH v4 2/4] bus: mhi: core: Move MHI_MAX_MTU to external header file
Currently this macro is defined in internal MHI header as a TRE length mask. Moving it to external header allows MHI client drivers to set this upper bound for the transmit buffer size. Signed-off-by: Hemant Kumar --- drivers/bus/mhi/core/internal.h | 1 - include/linux/mhi.h | 3 +++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/bus/mhi/core/internal.h b/drivers/bus/mhi/core/internal.h index 7989269..4abf0cf 100644 --- a/drivers/bus/mhi/core/internal.h +++ b/drivers/bus/mhi/core/internal.h @@ -453,7 +453,6 @@ enum mhi_pm_state { #define CMD_EL_PER_RING128 #define PRIMARY_CMD_RING 0 #define MHI_DEV_WAKE_DB127 -#define MHI_MAX_MTU0x #define MHI_RANDOM_U32_NONZERO(bmsk) (prandom_u32_max(bmsk) + 1) enum mhi_er_type { diff --git a/include/linux/mhi.h b/include/linux/mhi.h index 6565528..610f3b0 100644 --- a/include/linux/mhi.h +++ b/include/linux/mhi.h @@ -16,6 +16,9 @@ #include #include +/* MHI client drivers to set this upper bound for tx buffer */ +#define MHI_MAX_MTU 0x + #define MHI_MAX_OEM_PK_HASH_SEGMENTS 16 struct mhi_chan; -- The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum, a Linux Foundation Collaborative Project
[PATCH v4 4/4] bus: mhi: clients: Add userspace client interface driver
This MHI client driver allows userspace clients to transfer raw data between MHI device and host using standard file operations. Device file node is created with format /dev/mhi__ Currently it supports LOOPBACK channel. Signed-off-by: Hemant Kumar --- drivers/bus/mhi/Kconfig | 6 + drivers/bus/mhi/Makefile | 1 + drivers/bus/mhi/clients/Kconfig | 15 + drivers/bus/mhi/clients/Makefile | 3 + drivers/bus/mhi/clients/uci.c| 690 +++ 5 files changed, 715 insertions(+) create mode 100644 drivers/bus/mhi/clients/Kconfig create mode 100644 drivers/bus/mhi/clients/Makefile create mode 100644 drivers/bus/mhi/clients/uci.c diff --git a/drivers/bus/mhi/Kconfig b/drivers/bus/mhi/Kconfig index 6a217ff..927c392 100644 --- a/drivers/bus/mhi/Kconfig +++ b/drivers/bus/mhi/Kconfig @@ -20,3 +20,9 @@ config MHI_BUS_DEBUG Enable debugfs support for use with the MHI transport. Allows reading and/or modifying some values within the MHI controller for debug and test purposes. + +if MHI_BUS + +source "drivers/bus/mhi/clients/Kconfig" + +endif diff --git a/drivers/bus/mhi/Makefile b/drivers/bus/mhi/Makefile index 19e6443..48f6028 100644 --- a/drivers/bus/mhi/Makefile +++ b/drivers/bus/mhi/Makefile @@ -1,2 +1,3 @@ # core layer obj-y += core/ +obj-y += clients/ diff --git a/drivers/bus/mhi/clients/Kconfig b/drivers/bus/mhi/clients/Kconfig new file mode 100644 index 000..37aaf51 --- /dev/null +++ b/drivers/bus/mhi/clients/Kconfig @@ -0,0 +1,15 @@ +# SPDX-License-Identifier: GPL-2.0-only + +menu "MHI clients support" + +config MHI_UCI + tristate "MHI UCI" + depends on MHI_BUS + help +MHI based userspace client interface driver is used for transferring +raw data between host and device using standard file operations from +userspace. Open, read, write, and close operations are supported +by this driver. Please check mhi_uci_match_table for all supported +channels that are exposed to userspace. + +endmenu diff --git a/drivers/bus/mhi/clients/Makefile b/drivers/bus/mhi/clients/Makefile new file mode 100644 index 000..cd34282 --- /dev/null +++ b/drivers/bus/mhi/clients/Makefile @@ -0,0 +1,3 @@ +# SPDX-License-Identifier: GPL-2.0-only + +obj-$(CONFIG_MHI_UCI) += uci.o diff --git a/drivers/bus/mhi/clients/uci.c b/drivers/bus/mhi/clients/uci.c new file mode 100644 index 000..3ddf017 --- /dev/null +++ b/drivers/bus/mhi/clients/uci.c @@ -0,0 +1,690 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* Copyright (c) 2018-2020, The Linux Foundation. All rights reserved.*/ + +#include +#include +#include +#include +#include + +#define DEVICE_NAME "mhi" +#define MHI_UCI_DRIVER_NAME "mhi_uci" +#define MAX_UCI_DEVICES (64) + +/** + * struct uci_chan - MHI channel for a uci device + * @wq: wait queue for reader/writer + * @lock: spin lock + * @pending: list of rx buffers userspace is waiting to read + * @cur_buf: current buffer userspace is reading + * @rx_size: size of the current rx buffer userspace is reading + */ +struct uci_chan { + wait_queue_head_t wq; + + /* protects pending and cur_buf members */ + spinlock_t lock; + + struct list_head pending; + struct uci_buf *cur_buf; + size_t rx_size; +}; + +/** + * struct uci_buf - uci buffer + * @data: data buffer + * @len: length of data buffer + * @node: list node of the uci buffer + */ +struct uci_buf { + void *data; + size_t len; + struct list_head node; +}; + +/** + * struct mhi_uci_drv - MHI uci driver + * @head: list head of a uci device nodes + * @lock: mutex lock + * @class: current buffer userspace is reading + * @major: major number for uci driver + * @devt: dev_t object to hold major and minor info + */ +struct mhi_uci_drv { + struct list_head head; + + /* protects mhi_uci_drv struct members */ + struct mutex lock; + + struct class *class; + int major; + dev_t devt; +}; + +/** + * struct uci_dev - MHI uci device + * @node: uci device node + * @devt: dev_t object to hold major and minor info + * @dev: uci device object + * @mhi_dev: associated mhi device object + * @chan: MHI channel name + * @lock: mutex lock + * @ul_chan: uplink uci channel object + * @dl_chan: downlink uci channel object + * @mtu: max tx buffer length + * @actual_mtu: maximum size of incoming buffer + * @ref_count: uci_dev reference count + * @enabled: uci device node accessibility + */ +struct uci_dev { + struct list_head node; + dev_t devt; + struct device *dev; + struct mhi_device *mhi_dev; + const char *chan; + + /* protects uci_dev struct members */ + struct mutex lock; + + struct uci_chan ul_chan; + struct uci_chan dl_chan; + size_t mtu; + size_t actual_mtu; + int ref_count; + bool enabled; +}; + +static DECLARE_BITMAP(uci_minors, MAX_UCI_DEVICES); +static struct mhi_uci_drv
Re: [PATCH 4/6] arch: x86: Expose psABI on thread_info
On Tue, Jul 28, 2020 at 1:22 PM Gabriel Krisman Bertazi wrote: > > Expose psABI in thread_info, in preparation for the TIF_IA32 and > TIF_X32 flags removal. NAK. Linux threads don't have a user ABI like this. See my other comments :) --Andy
[PATCH] dax: Fix wrong error-number passed into xas_set_err()
The error-number passed into xas_set_err() should be negative. Otherwise, the xas_error() will return 0, and grab_mapping_entry() will return the found entry instead of a SIGBUS error when the entry is not a value. And then, the subsequent code path would be wrong. Signed-off-by: Hao Li --- fs/dax.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/dax.c b/fs/dax.c index 11b16729b86f..acac675fe7a6 100644 --- a/fs/dax.c +++ b/fs/dax.c @@ -488,7 +488,7 @@ static void *grab_mapping_entry(struct xa_state *xas, if (dax_is_conflict(entry)) goto fallback; if (!xa_is_value(entry)) { - xas_set_err(xas, EIO); + xas_set_err(xas, -EIO); goto out_unlock; } -- 2.28.0
Re: [PATCH 2/6] arch: x86: Wrap TIF_IA32 checks
On Tue, Jul 28, 2020 at 1:22 PM Gabriel Krisman Bertazi wrote: > > In preparation to remove TIF_IA32, add wrapper that check the process > has IA32 ABI without using the flag directly. Thank you for doing this, but let's please do it right. There is, fundamentally, no such thing as a "process with IA32 ABI". > > Signed-off-by: Gabriel Krisman Bertazi > --- > arch/x86/events/core.c | 2 +- > arch/x86/events/intel/ds.c | 2 +- > arch/x86/events/intel/lbr.c| 2 +- > arch/x86/include/asm/compat.h | 2 +- > arch/x86/include/asm/thread_info.h | 2 ++ > arch/x86/kernel/perf_regs.c| 2 +- > arch/x86/oprofile/backtrace.c | 2 +- > 7 files changed, 8 insertions(+), 6 deletions(-) > > diff --git a/arch/x86/events/core.c b/arch/x86/events/core.c > index 4103665c6e03..42dff74c6197 100644 > --- a/arch/x86/events/core.c > +++ b/arch/x86/events/core.c > @@ -2491,7 +2491,7 @@ perf_callchain_user32(struct pt_regs *regs, struct > perf_callchain_entry_ctx *ent > struct stack_frame_ia32 frame; > const struct stack_frame_ia32 __user *fp; > > - if (!test_thread_flag(TIF_IA32)) > + if (!TASK_IA32(current)) > return 0; if (user_64bit_mode(regs)) return 0; > > cs_base = get_segment_base(regs->cs); > diff --git a/arch/x86/events/intel/ds.c b/arch/x86/events/intel/ds.c > index dc43cc124e09..27d1cc1f3d05 100644 > --- a/arch/x86/events/intel/ds.c > +++ b/arch/x86/events/intel/ds.c > @@ -1261,7 +1261,7 @@ static int intel_pmu_pebs_fixup_ip(struct pt_regs *regs) > old_to = to; > > #ifdef CONFIG_X86_64 > - is_64bit = kernel_ip(to) || !test_thread_flag(TIF_IA32); > + is_64bit = kernel_ip(to) || !TASK_IA32(current); PeterZ, does PEBS not give us a CPL? Is it really just IP? Anyway, this should probably be: is_64bit = kernel_ip(to) || user_64bit_mode(regs) || !user_mode(regs); > #ifdef CONFIG_X86_64 > - is64 = kernel_ip((unsigned long)addr) || !test_thread_flag(TIF_IA32); > + is64 = kernel_ip((unsigned long)addr) || !TASK_IA32(current); Same as above. > diff --git a/arch/x86/include/asm/compat.h b/arch/x86/include/asm/compat.h > index d4edf281fff4..d39f9b3ae683 100644 > --- a/arch/x86/include/asm/compat.h > +++ b/arch/x86/include/asm/compat.h > @@ -181,7 +181,7 @@ static inline void __user > *arch_compat_alloc_user_space(long len) > { > compat_uptr_t sp; > > - if (test_thread_flag(TIF_IA32)) { > + if (TASK_IA32(current)) { > sp = task_pt_regs(current)->sp; Christoph, you spend a *lot* more time looking at this stuff lately than I do, but this looks totally wrong. Shouldn't this be either: sp = task_pt_regs(current)->sp; /* This might be a compat syscall issued via int $0x80 from 64-bit-ABI code. */ if (user_64bit_mode(task_pt_regs(current)) sp -= 128; Or perhaps the same thing without the user_64bit_mode() check at all? There shouldn't be much if any harm done by respecting the redzone unnecessarily. > --- a/arch/x86/kernel/perf_regs.c > +++ b/arch/x86/kernel/perf_regs.c > @@ -123,7 +123,7 @@ int perf_reg_validate(u64 mask) > > u64 perf_reg_abi(struct task_struct *task) > { > - if (test_tsk_thread_flag(task, TIF_IA32)) > + if (TASK_IA32(task)) > return PERF_SAMPLE_REGS_ABI_32; > else > return PERF_SAMPLE_REGS_ABI_64; Surely this should be: if (user_64bit_mode(task_pt_regs(regs)) return PERF_SAMPLE_REGS_ABI_64; else return PERF_SAMPLE_REGS_ABI_32; > diff --git a/arch/x86/oprofile/backtrace.c b/arch/x86/oprofile/backtrace.c > index a2488b6e27d6..3f1086afa297 100644 > --- a/arch/x86/oprofile/backtrace.c > +++ b/arch/x86/oprofile/backtrace.c > @@ -49,7 +49,7 @@ x86_backtrace_32(struct pt_regs * const regs, unsigned int > depth) > struct stack_frame_ia32 *head; > > /* User process is IA32 */ > - if (!current || !test_thread_flag(TIF_IA32)) > + if (!current || !TASK_IA32(current)) > return 0; if (user_64bit_mode(regs)) return 0; And now you don't need the TASK_IA32 macro :) All of the above being said, I'm wondering how many of these profiling users remember to check whether the task is a kernel thread. And I have no idea what task_pt_regs(current) contains in a kernel thread. --Andy
Re: [PATCH RESEND 1/2] scsi: megaraid: Remove pci-dma-compat wrapper APIs.
Hello Suraj! > The legacy API wrappers in include/linux/pci-dma-compat.h > should go away as it creates unnecessary midlayering > for include/linux/dma-mapping.h APIs, instead use dma-mapping.h > APIs directly. Instead of all these individual patches, please submit a combined patch series for the changes under SCSI. Each patch should fix a single driver. Please don't mix changes to completely different drivers such as hpsa and dc395x in a single commit. And please don't split semantically identical changes to the same driver into multiple commits (megaraid [2/2]). Thank you! -- Martin K. Petersen Oracle Linux Engineering
[RFC PATCH 1/6] mm/memory_hotplug: remove redundant memory block size alignment check
The alignment check has been done by check_hotplug_memory_range(). Hence the redundant one in create_memory_block_devices() can be removed. The similar redundant check is removed in remove_memory_block_devices(). Signed-off-by: Jia He --- drivers/base/memory.c | 8 1 file changed, 8 deletions(-) diff --git a/drivers/base/memory.c b/drivers/base/memory.c index 2b09b68b9f78..4a1691664c6c 100644 --- a/drivers/base/memory.c +++ b/drivers/base/memory.c @@ -642,10 +642,6 @@ int create_memory_block_devices(unsigned long start, unsigned long size) unsigned long block_id; int ret = 0; - if (WARN_ON_ONCE(!IS_ALIGNED(start, memory_block_size_bytes()) || -!IS_ALIGNED(size, memory_block_size_bytes( - return -EINVAL; - for (block_id = start_block_id; block_id != end_block_id; block_id++) { ret = init_memory_block(, block_id, MEM_OFFLINE); if (ret) @@ -678,10 +674,6 @@ void remove_memory_block_devices(unsigned long start, unsigned long size) struct memory_block *mem; unsigned long block_id; - if (WARN_ON_ONCE(!IS_ALIGNED(start, memory_block_size_bytes()) || -!IS_ALIGNED(size, memory_block_size_bytes( - return; - for (block_id = start_block_id; block_id != end_block_id; block_id++) { mem = find_memory_block_by_id(block_id); if (WARN_ON_ONCE(!mem)) -- 2.17.1
[RFC PATCH 2/6] resource: export find_next_iomem_res() helper
The helper is to find the lowest iomem resource that covers part of [@start..@end] It is useful when relaxing the alignment check for dax pmem kmem. Signed-off-by: Jia He --- include/linux/ioport.h | 3 +++ kernel/resource.c | 3 ++- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/include/linux/ioport.h b/include/linux/ioport.h index 6c2b06fe8beb..203fd16c9f45 100644 --- a/include/linux/ioport.h +++ b/include/linux/ioport.h @@ -247,6 +247,9 @@ extern struct resource * __request_region(struct resource *, extern void __release_region(struct resource *, resource_size_t, resource_size_t); +extern int find_next_iomem_res(resource_size_t start, resource_size_t end, + unsigned long flags, unsigned long desc, + bool first_lvl, struct resource *res); #ifdef CONFIG_MEMORY_HOTREMOVE extern int release_mem_region_adjustable(struct resource *, resource_size_t, resource_size_t); diff --git a/kernel/resource.c b/kernel/resource.c index 841737bbda9e..57e6a6802a3d 100644 --- a/kernel/resource.c +++ b/kernel/resource.c @@ -338,7 +338,7 @@ EXPORT_SYMBOL(release_resource); * @first_lvl: walk only the first level children, if set * @res: return ptr, if resource found */ -static int find_next_iomem_res(resource_size_t start, resource_size_t end, +int find_next_iomem_res(resource_size_t start, resource_size_t end, unsigned long flags, unsigned long desc, bool first_lvl, struct resource *res) { @@ -391,6 +391,7 @@ static int find_next_iomem_res(resource_size_t start, resource_size_t end, read_unlock(_lock); return p ? 0 : -ENODEV; } +EXPORT_SYMBOL(find_next_iomem_res); static int __walk_iomem_res_desc(resource_size_t start, resource_size_t end, unsigned long flags, unsigned long desc, -- 2.17.1
[RFC PATCH 3/6] mm/memory_hotplug: allow pmem kmem not to align with memory_block_size
When dax pmem is probed as RAM device on arm64, previously, kmem_start in dev_dax_kmem_probe() should be aligned with 1G memblock size on arm64 due to SECTION_SIZE_BITS(30). There will be some meta data at the beginning/end of the iomem space, e.g. namespace info and nvdimm label: 24000-33fdf : Persistent Memory 24000-2403f : namespace0.0 28000-2bfff : dax0.0 28000-2bfff : System RAM Hence it makes the whole kmem space not aligned with memory_block_size for both start addr and end addr. Hence there is a big gap when kmem is added into memory block which causes big memory space wasting. This changes it by relaxing the alignment check for dax pmem kmem in the path of online/offline memory blocks. Signed-off-by: Jia He --- drivers/base/memory.c | 16 mm/memory_hotplug.c | 39 ++- 2 files changed, 54 insertions(+), 1 deletion(-) diff --git a/drivers/base/memory.c b/drivers/base/memory.c index 4a1691664c6c..3d2a94f3b1d9 100644 --- a/drivers/base/memory.c +++ b/drivers/base/memory.c @@ -334,6 +334,22 @@ static ssize_t valid_zones_show(struct device *dev, * online nodes otherwise the page_zone is not reliable */ if (mem->state == MEM_ONLINE) { +#ifdef CONFIG_ZONE_DEVICE + struct resource res; + int ret; + + /* adjust start_pfn for dax pmem kmem */ + ret = find_next_iomem_res(start_pfn << PAGE_SHIFT, + ((start_pfn + nr_pages) << PAGE_SHIFT) - 1, + IORESOURCE_SYSTEM_RAM | IORESOURCE_BUSY, + IORES_DESC_PERSISTENT_MEMORY, + false, ); + if (!ret && PFN_UP(res.start) > start_pfn) { + nr_pages -= PFN_UP(res.start) - start_pfn; + start_pfn = PFN_UP(res.start); + } +#endif + /* * The block contains more than one zone can not be offlined. * This can happen e.g. for ZONE_DMA and ZONE_DMA32 diff --git a/mm/memory_hotplug.c b/mm/memory_hotplug.c index a53103dc292b..25745f67b680 100644 --- a/mm/memory_hotplug.c +++ b/mm/memory_hotplug.c @@ -999,6 +999,20 @@ int try_online_node(int nid) static int check_hotplug_memory_range(u64 start, u64 size) { +#ifdef CONFIG_ZONE_DEVICE + struct resource res; + int ret; + + /* Allow pmem kmem not to align with block size */ + ret = find_next_iomem_res(start, start + size - 1, + IORESOURCE_SYSTEM_RAM | IORESOURCE_BUSY, + IORES_DESC_PERSISTENT_MEMORY, + false, ); + if (!ret) { + return 0; + } +#endif + /* memory range must be block size aligned */ if (!size || !IS_ALIGNED(start, memory_block_size_bytes()) || !IS_ALIGNED(size, memory_block_size_bytes())) { @@ -1481,19 +1495,42 @@ static int __ref __offline_pages(unsigned long start_pfn, mem_hotplug_begin(); /* -* Don't allow to offline memory blocks that contain holes. +* Don't allow to offline memory blocks that contain holes except +* for pmem. * Consequently, memory blocks with holes can never get onlined * via the hotplug path - online_pages() - as hotplugged memory has * no holes. This way, we e.g., don't have to worry about marking * memory holes PG_reserved, don't need pfn_valid() checks, and can * avoid using walk_system_ram_range() later. +* When dax pmem is used as RAM (kmem), holes at the beginning is +* allowed. */ walk_system_ram_range(start_pfn, end_pfn - start_pfn, _pages, count_system_ram_pages_cb); if (nr_pages != end_pfn - start_pfn) { +#ifdef CONFIG_ZONE_DEVICE + struct resource res; + + /* Allow pmem kmem not to align with block size */ + ret = find_next_iomem_res(start_pfn << PAGE_SHIFT, + (end_pfn << PAGE_SHIFT) - 1, + IORESOURCE_SYSTEM_RAM | IORESOURCE_BUSY, + IORES_DESC_PERSISTENT_MEMORY, + false, ); + if (ret) { + ret = -EINVAL; + reason = "memory holes"; + goto failed_removal; + } + + /* adjust start_pfn for dax pmem kmem */ + start_pfn = PFN_UP(res.start); + end_pfn = PFN_DOWN(res.end + 1); +#else ret = -EINVAL; reason = "memory holes"; goto failed_removal; +#endif } /* This makes hotplug much easier...and readable. -- 2.17.1
[RFC PATCH 6/6] arm64: fall back to vmemmap_populate_basepages if not aligned with PMD_SIZE
In dax pmem kmem (dax pmem used as RAM device) case, the start address might not be aligned with PMD_SIZE e.g. 24000-33fdf : Persistent Memory 24000-2421f : namespace0.0 24240-2bfff : dax0.0 24240-2bfff : System RAM (kmem) pfn_to_page(0x24240) is fe0007e9. Without this patch, vmemmap_populate(fe0007e9, ...) will incorrectly create a pmd mapping [fe0007e0, fe000800] which contains fe0007e9. This adds the check and then falls back to vmemmap_populate_basepages() Signed-off-by: Jia He --- arch/arm64/mm/mmu.c | 4 1 file changed, 4 insertions(+) diff --git a/arch/arm64/mm/mmu.c b/arch/arm64/mm/mmu.c index d69feb2cfb84..3b21bd47e801 100644 --- a/arch/arm64/mm/mmu.c +++ b/arch/arm64/mm/mmu.c @@ -1102,6 +1102,10 @@ int __meminit vmemmap_populate(unsigned long start, unsigned long end, int node, do { next = pmd_addr_end(addr, end); + if (next - addr < PMD_SIZE) { + vmemmap_populate_basepages(start, next, node, altmap); + continue; + } pgdp = vmemmap_pgd_populate(addr, node); if (!pgdp) -- 2.17.1
[RFC PATCH 4/6] mm/page_alloc: adjust the start,end in dax pmem kmem case
There are 3 cases when doing online pages: - normal RAM, should be aligned with memory block size - persistent memory with ZONE_DEVICE - persistent memory used as normal RAM (kmem) with ZONE_NORMAL, this patch tries to adjust the start_pfn/end_pfn after finding the corresponding resource range. Without this patch, the check of __init_single_page when doing online memory will be failed because those pages haven't been mapped in mmu(not present from mmu's point of view). Signed-off-by: Jia He --- mm/page_alloc.c | 14 ++ 1 file changed, 14 insertions(+) diff --git a/mm/page_alloc.c b/mm/page_alloc.c index e028b87ce294..13216ab3623f 100644 --- a/mm/page_alloc.c +++ b/mm/page_alloc.c @@ -5971,6 +5971,20 @@ void __meminit memmap_init_zone(unsigned long size, int nid, unsigned long zone, if (start_pfn == altmap->base_pfn) start_pfn += altmap->reserve; end_pfn = altmap->base_pfn + vmem_altmap_offset(altmap); + } else { + struct resource res; + int ret; + + /* adjust the start,end in dax pmem kmem case */ + ret = find_next_iomem_res(start_pfn << PAGE_SHIFT, + (end_pfn << PAGE_SHIFT) - 1, + IORESOURCE_SYSTEM_RAM | IORESOURCE_BUSY, + IORES_DESC_PERSISTENT_MEMORY, + false, ); + if (!ret) { + start_pfn = PFN_UP(res.start); + end_pfn = PFN_DOWN(res.end + 1); + } } #endif -- 2.17.1
[RFC PATCH 5/6] device-dax: relax the memblock size alignment for kmem_start
Previously, kmem_start in dev_dax_kmem_probe should be aligned with SECTION_SIZE_BITS(30), i.e. 1G memblock size on arm64. Even with Dan Williams' sub-section patch series, it was not helpful when adding the dax pmem kmem to memblock: $ndctl create-namespace -e namespace0.0 --mode=devdax --map=dev -s 2g -f -a 2M $echo dax0.0 > /sys/bus/dax/drivers/device_dax/unbind $echo dax0.0 > /sys/bus/dax/drivers/kmem/new_id $cat /proc/iomem ... 23c00-23fff : System RAM 23dd4-23fec : reserved 23fed-23fff : reserved 24000-33fdf : Persistent Memory 24000-2403f : namespace0.0 28000-2bfff : dax0.0 <- boundary are aligned with 1G 28000-2bfff : System RAM (kmem) $ lsmem RANGE SIZE STATE REMOVABLE BLOCK 0x4000-0x00023fff 8G online yes 1-8 0x00028000-0x0002bfff 1G online yes10 Memory block size: 1G Total online memory: 9G Total offline memory: 0B ... Hence there is a big gap between 0x2403f and 0x28000 due to the 1G alignment on arm64. More than that, only 1G memory is returned while 2G is requested. On x86, the gap is relatively small due to SECTION_SIZE_BITS(27). Besides descreasing SECTION_SIZE_BITS on arm64, we can relax the alignment when adding the kmem. After this patch: 24000-33fdf : Persistent Memory 24000-2421f : namespace0.0 24240-2bfff : dax0.0 24240-2bfff : System RAM (kmem) $ lsmem RANGE SIZE STATE REMOVABLE BLOCK 0x4000-0x0002bfff 10G online yes 1-10 Memory block size: 1G Total online memory: 10G Total offline memory: 0B Notes, block 9-10 are the newly hotplug added. This patches remove the tight alignment constraint of memory_block_size_bytes(), but still keep the constraint from online_pages_range(). Signed-off-by: Jia He --- drivers/dax/kmem.c | 22 +- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/drivers/dax/kmem.c b/drivers/dax/kmem.c index d77786dc0d92..849d0706dfe0 100644 --- a/drivers/dax/kmem.c +++ b/drivers/dax/kmem.c @@ -30,9 +30,20 @@ int dev_dax_kmem_probe(struct device *dev) const char *new_res_name; int numa_node; int rc; + int order; - /* Hotplug starting at the beginning of the next block: */ - kmem_start = ALIGN(res->start, memory_block_size_bytes()); + /* kmem_start needn't be aligned with memory_block_size_bytes(). +* But given the constraint in online_pages_range(), adjust the +* alignment of kmem_start and kmem_size +*/ + kmem_size = resource_size(res); + order = min_t(int, MAX_ORDER - 1, get_order(kmem_size)); + kmem_start = ALIGN(res->start, 1ul << (order + PAGE_SHIFT)); + /* Adjust the size down to compensate for moving up kmem_start: */ + kmem_size -= kmem_start - res->start; + /* Align the size down to cover only complete blocks: */ + kmem_size &= ~((1ul << (order + PAGE_SHIFT)) - 1); + kmem_end = kmem_start + kmem_size; /* * Ensure good NUMA information for the persistent memory. @@ -48,13 +59,6 @@ int dev_dax_kmem_probe(struct device *dev) numa_node, res); } - kmem_size = resource_size(res); - /* Adjust the size down to compensate for moving up kmem_start: */ - kmem_size -= kmem_start - res->start; - /* Align the size down to cover only complete blocks: */ - kmem_size &= ~(memory_block_size_bytes() - 1); - kmem_end = kmem_start + kmem_size; - new_res_name = kstrdup(dev_name(dev), GFP_KERNEL); if (!new_res_name) return -ENOMEM; -- 2.17.1
[RFC PATCH 0/6] decrease unnecessary gap due to pmem kmem alignment
When enabling dax pmem as RAM device on arm64, I noticed that kmem_start addr in dev_dax_kmem_probe() should be aligned w/ SECTION_SIZE_BITS(30),i.e. 1G memblock size. Even Dan Williams' sub-section patch series [1] had been upstream merged, it was not helpful due to hard limitation of kmem_start: $ndctl create-namespace -e namespace0.0 --mode=devdax --map=dev -s 2g -f -a 2M $echo dax0.0 > /sys/bus/dax/drivers/device_dax/unbind $echo dax0.0 > /sys/bus/dax/drivers/kmem/new_id $cat /proc/iomem ... 23c00-23fff : System RAM 23dd4-23fec : reserved 23fed-23fff : reserved 24000-33fdf : Persistent Memory 24000-2403f : namespace0.0 28000-2bfff : dax0.0 <- aligned with 1G boundary 28000-2bfff : System RAM Hence there is a big gap between 0x2403f and 0x28000 due to the 1G alignment. Without this series, if qemu creates a 4G bytes nvdimm device, we can only use 2G bytes for dax pmem(kmem) in the worst case. e.g. 24000-33fdf : Persistent Memory We can only use the memblock between [24000, 2] due to the hard limitation. It wastes too much memory space. Decreasing the SECTION_SIZE_BITS on arm64 might be an alternative, but there are too many concerns from other constraints, e.g. PAGE_SIZE, hugetlb, SPARSEMEM_VMEMMAP, page bits in struct page ... Beside decreasing the SECTION_SIZE_BITS, we can also relax the kmem alignment with memory_block_size_bytes(). Tested on arm64 guest and x86 guest, qemu creates a 4G pmem device. dax pmem can be used as ram with smaller gap. Also the kmem hotplug add/remove are both tested on arm64/x86 guest. This patch series (mainly patch6/6) is based on the fixing patch, ~v5.8-rc5 [2]. [1] https://lkml.org/lkml/2019/6/19/67 [2] https://lkml.org/lkml/2020/7/8/1546 Jia He (6): mm/memory_hotplug: remove redundant memory block size alignment check resource: export find_next_iomem_res() helper mm/memory_hotplug: allow pmem kmem not to align with memory_block_size mm/page_alloc: adjust the start,end in dax pmem kmem case device-dax: relax the memblock size alignment for kmem_start arm64: fall back to vmemmap_populate_basepages if not aligned with PMD_SIZE arch/arm64/mm/mmu.c| 4 drivers/base/memory.c | 24 drivers/dax/kmem.c | 22 +- include/linux/ioport.h | 3 +++ kernel/resource.c | 3 ++- mm/memory_hotplug.c| 39 ++- mm/page_alloc.c| 14 ++ 7 files changed, 90 insertions(+), 19 deletions(-) -- 2.17.1
[PATCH V3] dt-bindings: pci: convert QCOM pci bindings to YAML
Convert QCOM pci bindings to YAML schema Reviewed-by: Rob Herring Signed-off-by: Sivaprakash Murugesan --- [V3] * Rebased V2 including recent patches from Ansuel * Addressed Review comments from Rob * Apart from properties commented by Rob interrupt-map is also removed as it is documented in pci-bus.yaml and throwing error when included * check patch warning "Use of 'slave' is deprecated, please '(secondary|target|...)', instead." is not addressed in this patch as it requires changes in code and dts .../devicetree/bindings/pci/qcom,pcie.txt | 337 .../devicetree/bindings/pci/qcom,pcie.yaml | 437 + 2 files changed, 437 insertions(+), 337 deletions(-) delete mode 100644 Documentation/devicetree/bindings/pci/qcom,pcie.txt create mode 100644 Documentation/devicetree/bindings/pci/qcom,pcie.yaml diff --git a/Documentation/devicetree/bindings/pci/qcom,pcie.txt b/Documentation/devicetree/bindings/pci/qcom,pcie.txt deleted file mode 100644 index 02bc81b..000 --- a/Documentation/devicetree/bindings/pci/qcom,pcie.txt +++ /dev/null @@ -1,337 +0,0 @@ -* Qualcomm PCI express root complex - -- compatible: - Usage: required - Value type: - Definition: Value should contain - - "qcom,pcie-ipq8064" for ipq8064 - - "qcom,pcie-ipq8064-v2" for ipq8064 rev 2 or ipq8065 - - "qcom,pcie-apq8064" for apq8064 - - "qcom,pcie-apq8084" for apq8084 - - "qcom,pcie-msm8996" for msm8996 or apq8096 - - "qcom,pcie-ipq4019" for ipq4019 - - "qcom,pcie-ipq8074" for ipq8074 - - "qcom,pcie-qcs404" for qcs404 - - "qcom,pcie-sdm845" for sdm845 - -- reg: - Usage: required - Value type: - Definition: Register ranges as listed in the reg-names property - -- reg-names: - Usage: required - Value type: - Definition: Must include the following entries - - "parf" Qualcomm specific registers - - "dbi"DesignWare PCIe registers - - "elbi" External local bus interface registers - - "config" PCIe configuration space - -- device_type: - Usage: required - Value type: - Definition: Should be "pci". As specified in designware-pcie.txt - -- #address-cells: - Usage: required - Value type: - Definition: Should be 3. As specified in designware-pcie.txt - -- #size-cells: - Usage: required - Value type: - Definition: Should be 2. As specified in designware-pcie.txt - -- ranges: - Usage: required - Value type: - Definition: As specified in designware-pcie.txt - -- interrupts: - Usage: required - Value type: - Definition: MSI interrupt - -- interrupt-names: - Usage: required - Value type: - Definition: Should contain "msi" - -- #interrupt-cells: - Usage: required - Value type: - Definition: Should be 1. As specified in designware-pcie.txt - -- interrupt-map-mask: - Usage: required - Value type: - Definition: As specified in designware-pcie.txt - -- interrupt-map: - Usage: required - Value type: - Definition: As specified in designware-pcie.txt - -- clocks: - Usage: required - Value type: - Definition: List of phandle and clock specifier pairs as listed - in clock-names property - -- clock-names: - Usage: required - Value type: - Definition: Should contain the following entries - - "iface" Configuration AHB clock - -- clock-names: - Usage: required for ipq/apq8064 - Value type: - Definition: Should contain the following entries - - "core"Clocks the pcie hw block - - "phy" Clocks the pcie PHY block - - "aux" Clocks the pcie AUX block - - "ref" Clocks the pcie ref block -- clock-names: - Usage: required for apq8084/ipq4019 - Value type: - Definition: Should contain the following entries - - "aux" Auxiliary (AUX) clock - - "bus_master" Master AXI clock - - "bus_slave" Slave AXI clock - -- clock-names: - Usage: required for msm8996/apq8096 - Value type: - Definition: Should contain the following entries - - "pipe"Pipe Clock driving internal logic - - "aux" Auxiliary (AUX) clock - - "cfg" Configuration clock - - "bus_master" Master AXI clock - - "bus_slave" Slave AXI clock - -- clock-names: - Usage: required for
[PATCH 1/5] block: Move bio merge related functions into blk-merge.c
It's better to move bio merge related functions into blk-merge.c, which contains all merge related functions. Signed-off-by: Baolin Wang --- block/blk-core.c | 156 - block/blk-merge.c | 157 ++ 2 files changed, 157 insertions(+), 156 deletions(-) diff --git a/block/blk-core.c b/block/blk-core.c index d9d6326..ed79109 100644 --- a/block/blk-core.c +++ b/block/blk-core.c @@ -642,162 +642,6 @@ void blk_put_request(struct request *req) } EXPORT_SYMBOL(blk_put_request); -static void blk_account_io_merge_bio(struct request *req) -{ - if (!blk_do_io_stat(req)) - return; - - part_stat_lock(); - part_stat_inc(req->part, merges[op_stat_group(req_op(req))]); - part_stat_unlock(); -} - -bool bio_attempt_back_merge(struct request *req, struct bio *bio, - unsigned int nr_segs) -{ - const int ff = bio->bi_opf & REQ_FAILFAST_MASK; - - if (!ll_back_merge_fn(req, bio, nr_segs)) - return false; - - trace_block_bio_backmerge(req->q, req, bio); - rq_qos_merge(req->q, req, bio); - - if ((req->cmd_flags & REQ_FAILFAST_MASK) != ff) - blk_rq_set_mixed_merge(req); - - req->biotail->bi_next = bio; - req->biotail = bio; - req->__data_len += bio->bi_iter.bi_size; - - bio_crypt_free_ctx(bio); - - blk_account_io_merge_bio(req); - return true; -} - -bool bio_attempt_front_merge(struct request *req, struct bio *bio, - unsigned int nr_segs) -{ - const int ff = bio->bi_opf & REQ_FAILFAST_MASK; - - if (!ll_front_merge_fn(req, bio, nr_segs)) - return false; - - trace_block_bio_frontmerge(req->q, req, bio); - rq_qos_merge(req->q, req, bio); - - if ((req->cmd_flags & REQ_FAILFAST_MASK) != ff) - blk_rq_set_mixed_merge(req); - - bio->bi_next = req->bio; - req->bio = bio; - - req->__sector = bio->bi_iter.bi_sector; - req->__data_len += bio->bi_iter.bi_size; - - bio_crypt_do_front_merge(req, bio); - - blk_account_io_merge_bio(req); - return true; -} - -bool bio_attempt_discard_merge(struct request_queue *q, struct request *req, - struct bio *bio) -{ - unsigned short segments = blk_rq_nr_discard_segments(req); - - if (segments >= queue_max_discard_segments(q)) - goto no_merge; - if (blk_rq_sectors(req) + bio_sectors(bio) > - blk_rq_get_max_sectors(req, blk_rq_pos(req))) - goto no_merge; - - rq_qos_merge(q, req, bio); - - req->biotail->bi_next = bio; - req->biotail = bio; - req->__data_len += bio->bi_iter.bi_size; - req->nr_phys_segments = segments + 1; - - blk_account_io_merge_bio(req); - return true; -no_merge: - req_set_nomerge(q, req); - return false; -} - -/** - * blk_attempt_plug_merge - try to merge with %current's plugged list - * @q: request_queue new bio is being queued at - * @bio: new bio being queued - * @nr_segs: number of segments in @bio - * @same_queue_rq: pointer to request that gets filled in when - * another request associated with @q is found on the plug list - * (optional, may be %NULL) - * - * Determine whether @bio being queued on @q can be merged with a request - * on %current's plugged list. Returns %true if merge was successful, - * otherwise %false. - * - * Plugging coalesces IOs from the same issuer for the same purpose without - * going through @q->queue_lock. As such it's more of an issuing mechanism - * than scheduling, and the request, while may have elvpriv data, is not - * added on the elevator at this point. In addition, we don't have - * reliable access to the elevator outside queue lock. Only check basic - * merging parameters without querying the elevator. - * - * Caller must ensure !blk_queue_nomerges(q) beforehand. - */ -bool blk_attempt_plug_merge(struct request_queue *q, struct bio *bio, - unsigned int nr_segs, struct request **same_queue_rq) -{ - struct blk_plug *plug; - struct request *rq; - struct list_head *plug_list; - - plug = blk_mq_plug(q, bio); - if (!plug) - return false; - - plug_list = >mq_list; - - list_for_each_entry_reverse(rq, plug_list, queuelist) { - bool merged = false; - - if (rq->q == q && same_queue_rq) { - /* -* Only blk-mq multiple hardware queues case checks the -* rq in the same queue, there should be only one such -* rq in a queue -**/ - *same_queue_rq = rq; - } - - if (rq->q != q || !blk_rq_merge_ok(rq, bio)) - continue; - - switch (blk_try_merge(rq, bio)) { - case
[PATCH 2/5] block: Remove redundant blk_mq_sched_allow_merge() validation
Only software queue and kyber IO scheduler will call blk_mq_bio_list_merge() to merge a bio, and kyber IO scheduler did not implement the ops->allow_merge(). Thus we can remove the redundant blk_mq_sched_allow_merge() in blk_mq_bio_list_merge() function. Signed-off-by: Baolin Wang --- block/blk-mq-sched.c | 8 ++-- 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/block/blk-mq-sched.c b/block/blk-mq-sched.c index b8db72c..cc34f69 100644 --- a/block/blk-mq-sched.c +++ b/block/blk-mq-sched.c @@ -403,14 +403,10 @@ bool blk_mq_bio_list_merge(struct request_queue *q, struct list_head *list, switch (blk_try_merge(rq, bio)) { case ELEVATOR_BACK_MERGE: - if (blk_mq_sched_allow_merge(q, rq, bio)) - merged = bio_attempt_back_merge(rq, bio, - nr_segs); + merged = bio_attempt_back_merge(rq, bio, nr_segs); break; case ELEVATOR_FRONT_MERGE: - if (blk_mq_sched_allow_merge(q, rq, bio)) - merged = bio_attempt_front_merge(rq, bio, - nr_segs); + merged = bio_attempt_front_merge(rq, bio, nr_segs); break; case ELEVATOR_DISCARD_MERGE: merged = bio_attempt_discard_merge(q, rq, bio); -- 1.8.3.1
[PATCH 0/5] Some clean-ups for bio merge
Hi, There are some duplicated code when trying to merge bio from pluged list and software queue, thus this patch set did some clean-ups when merging a bio. Any comments are welcome. Thanks. Baolin Wang (5): block: Move bio merge related functions into blk-merge.c block: Remove redundant blk_mq_sched_allow_merge() validation block: Add a new helper to attempt to merge a bio block: Remove blk_mq_attempt_merge() function block: Remove __blk_mq_sched_bio_merge() helper block/blk-core.c | 156 --- block/blk-merge.c| 168 +++ block/blk-mq-sched.c | 64 ++-- block/blk-mq-sched.h | 13 +--- block/blk.h | 9 +++ 5 files changed, 197 insertions(+), 213 deletions(-) -- 1.8.3.1
[PATCH 5/5] block: Remove __blk_mq_sched_bio_merge() helper
The blk_mq_sched_bio_merge() just wrap the __blk_mq_sched_bio_merge(), and no other places will use __blk_mq_sched_bio_merge(). Thus we can combine these 2 similar functions into one function. Signed-off-by: Baolin Wang --- block/blk-mq-sched.c | 5 - block/blk-mq-sched.h | 13 ++--- 2 files changed, 6 insertions(+), 12 deletions(-) diff --git a/block/blk-mq-sched.c b/block/blk-mq-sched.c index 4e3eef5..f7ae74a 100644 --- a/block/blk-mq-sched.c +++ b/block/blk-mq-sched.c @@ -408,7 +408,7 @@ bool blk_mq_bio_list_merge(struct request_queue *q, struct list_head *list, } EXPORT_SYMBOL_GPL(blk_mq_bio_list_merge); -bool __blk_mq_sched_bio_merge(struct request_queue *q, struct bio *bio, +bool blk_mq_sched_bio_merge(struct request_queue *q, struct bio *bio, unsigned int nr_segs) { struct elevator_queue *e = q->elevator; @@ -417,6 +417,9 @@ bool __blk_mq_sched_bio_merge(struct request_queue *q, struct bio *bio, bool ret = false; enum hctx_type type; + if (blk_queue_nomerges(q) || !bio_mergeable(bio)) + return false; + if (e && e->type->ops.bio_merge) return e->type->ops.bio_merge(hctx, bio, nr_segs); diff --git a/block/blk-mq-sched.h b/block/blk-mq-sched.h index 126021f..65151de 100644 --- a/block/blk-mq-sched.h +++ b/block/blk-mq-sched.h @@ -13,8 +13,6 @@ void blk_mq_sched_free_hctx_data(struct request_queue *q, void blk_mq_sched_request_inserted(struct request *rq); bool blk_mq_sched_try_merge(struct request_queue *q, struct bio *bio, unsigned int nr_segs, struct request **merged_request); -bool __blk_mq_sched_bio_merge(struct request_queue *q, struct bio *bio, - unsigned int nr_segs); bool blk_mq_sched_try_insert_merge(struct request_queue *q, struct request *rq); void blk_mq_sched_mark_restart_hctx(struct blk_mq_hw_ctx *hctx); void blk_mq_sched_restart(struct blk_mq_hw_ctx *hctx); @@ -31,15 +29,8 @@ void blk_mq_sched_insert_requests(struct blk_mq_hw_ctx *hctx, void blk_mq_exit_sched(struct request_queue *q, struct elevator_queue *e); void blk_mq_sched_free_requests(struct request_queue *q); -static inline bool -blk_mq_sched_bio_merge(struct request_queue *q, struct bio *bio, - unsigned int nr_segs) -{ - if (blk_queue_nomerges(q) || !bio_mergeable(bio)) - return false; - - return __blk_mq_sched_bio_merge(q, bio, nr_segs); -} +bool blk_mq_sched_bio_merge(struct request_queue *q, struct bio *bio, + unsigned int nr_segs); static inline bool blk_mq_sched_allow_merge(struct request_queue *q, struct request *rq, -- 1.8.3.1
[PATCH 3/5] block: Add a new helper to attempt to merge a bio
There are lots of duplicated code when trying to merge a bio from plug list and sw queue, we can introduce a new helper to attempt to merge a bio, which can simplify the blk_mq_bio_list_merge() and blk_attempt_plug_merge(). Signed-off-by: Baolin Wang --- block/blk-merge.c| 47 +-- block/blk-mq-sched.c | 22 -- block/blk.h | 9 + 3 files changed, 42 insertions(+), 36 deletions(-) diff --git a/block/blk-merge.c b/block/blk-merge.c index 1993e6a..feaee53 100644 --- a/block/blk-merge.c +++ b/block/blk-merge.c @@ -975,6 +975,33 @@ bool bio_attempt_discard_merge(struct request_queue *q, struct request *req, return false; } +enum bio_merge_status blk_attempt_bio_merge(struct request_queue *q, + struct request *rq, + struct bio *bio, + unsigned int nr_segs) +{ + bool merged = false; + + if (!blk_rq_merge_ok(rq, bio)) + return BIO_MERGE_NONE; + + switch (blk_try_merge(rq, bio)) { + case ELEVATOR_BACK_MERGE: + merged = bio_attempt_back_merge(rq, bio, nr_segs); + break; + case ELEVATOR_FRONT_MERGE: + merged = bio_attempt_front_merge(rq, bio, nr_segs); + break; + case ELEVATOR_DISCARD_MERGE: + merged = bio_attempt_discard_merge(q, rq, bio); + break; + default: + return BIO_MERGE_NONE; + } + + return merged ? BIO_MERGE_OK : BIO_MERGE_FAILED; +} + /** * blk_attempt_plug_merge - try to merge with %current's plugged list * @q: request_queue new bio is being queued at @@ -1011,8 +1038,6 @@ bool blk_attempt_plug_merge(struct request_queue *q, struct bio *bio, plug_list = >mq_list; list_for_each_entry_reverse(rq, plug_list, queuelist) { - bool merged = false; - if (rq->q == q && same_queue_rq) { /* * Only blk-mq multiple hardware queues case checks the @@ -1022,24 +1047,10 @@ bool blk_attempt_plug_merge(struct request_queue *q, struct bio *bio, *same_queue_rq = rq; } - if (rq->q != q || !blk_rq_merge_ok(rq, bio)) + if (rq->q != q) continue; - switch (blk_try_merge(rq, bio)) { - case ELEVATOR_BACK_MERGE: - merged = bio_attempt_back_merge(rq, bio, nr_segs); - break; - case ELEVATOR_FRONT_MERGE: - merged = bio_attempt_front_merge(rq, bio, nr_segs); - break; - case ELEVATOR_DISCARD_MERGE: - merged = bio_attempt_discard_merge(q, rq, bio); - break; - default: - break; - } - - if (merged) + if (blk_attempt_bio_merge(q, rq, bio, nr_segs) == BIO_MERGE_OK) return true; } diff --git a/block/blk-mq-sched.c b/block/blk-mq-sched.c index cc34f69..24d5078 100644 --- a/block/blk-mq-sched.c +++ b/block/blk-mq-sched.c @@ -391,31 +391,17 @@ bool blk_mq_bio_list_merge(struct request_queue *q, struct list_head *list, { struct request *rq; int checked = 8; + enum bio_merge_status merge; list_for_each_entry_reverse(rq, list, queuelist) { - bool merged = false; - if (!checked--) break; - if (!blk_rq_merge_ok(rq, bio)) + merge = blk_attempt_bio_merge(q, rq, bio, nr_segs); + if (merge == BIO_MERGE_NONE) continue; - switch (blk_try_merge(rq, bio)) { - case ELEVATOR_BACK_MERGE: - merged = bio_attempt_back_merge(rq, bio, nr_segs); - break; - case ELEVATOR_FRONT_MERGE: - merged = bio_attempt_front_merge(rq, bio, nr_segs); - break; - case ELEVATOR_DISCARD_MERGE: - merged = bio_attempt_discard_merge(q, rq, bio); - break; - default: - continue; - } - - return merged; + return merge == BIO_MERGE_OK ? true: false; } return false; diff --git a/block/blk.h b/block/blk.h index 49e2928..a6c54e1 100644 --- a/block/blk.h +++ b/block/blk.h @@ -234,6 +234,15 @@ int blk_attempt_req_merge(struct request_queue *q, struct request *rq, bool blk_rq_merge_ok(struct request *rq, struct bio *bio); enum elv_merge blk_try_merge(struct request *rq, struct bio *bio); +enum bio_merge_status { + BIO_MERGE_OK, + BIO_MERGE_NONE, + BIO_MERGE_FAILED,
[PATCH 4/5] block: Remove blk_mq_attempt_merge() function
The small blk_mq_attempt_merge() function is only called by __blk_mq_sched_bio_merge(), just open code it. Signed-off-by: Baolin Wang --- block/blk-mq-sched.c | 33 ++--- 1 file changed, 10 insertions(+), 23 deletions(-) diff --git a/block/blk-mq-sched.c b/block/blk-mq-sched.c index 24d5078..4e3eef5 100644 --- a/block/blk-mq-sched.c +++ b/block/blk-mq-sched.c @@ -408,28 +408,6 @@ bool blk_mq_bio_list_merge(struct request_queue *q, struct list_head *list, } EXPORT_SYMBOL_GPL(blk_mq_bio_list_merge); -/* - * Reverse check our software queue for entries that we could potentially - * merge with. Currently includes a hand-wavy stop count of 8, to not spend - * too much time checking for merges. - */ -static bool blk_mq_attempt_merge(struct request_queue *q, -struct blk_mq_hw_ctx *hctx, -struct blk_mq_ctx *ctx, struct bio *bio, -unsigned int nr_segs) -{ - enum hctx_type type = hctx->type; - - lockdep_assert_held(>lock); - - if (blk_mq_bio_list_merge(q, >rq_lists[type], bio, nr_segs)) { - ctx->rq_merged++; - return true; - } - - return false; -} - bool __blk_mq_sched_bio_merge(struct request_queue *q, struct bio *bio, unsigned int nr_segs) { @@ -447,7 +425,16 @@ bool __blk_mq_sched_bio_merge(struct request_queue *q, struct bio *bio, !list_empty_careful(>rq_lists[type])) { /* default per sw-queue merge */ spin_lock(>lock); - ret = blk_mq_attempt_merge(q, hctx, ctx, bio, nr_segs); + /* +* Reverse check our software queue for entries that we could +* potentially merge with. Currently includes a hand-wavy stop +* count of 8, to not spend too much time checking for merges. +*/ + if (blk_mq_bio_list_merge(q, >rq_lists[type], bio, nr_segs)) { + ctx->rq_merged++; + ret = true; + } + spin_unlock(>lock); } -- 1.8.3.1
[PATCH] fat: Add newline after declarations
Add a newline after declarations in muliple places within the fat driver where checkpatch.pl identified this problem. Signed-off-by: Coleman Kane --- fs/fat/cache.c | 1 + fs/fat/dir.c | 6 ++ fs/fat/fatent.c | 8 fs/fat/file.c| 2 ++ fs/fat/inode.c | 14 ++ fs/fat/misc.c| 2 ++ fs/fat/namei_msdos.c | 1 + fs/fat/namei_vfat.c | 4 fs/fat/nfs.c | 3 +++ 9 files changed, 41 insertions(+) diff --git a/fs/fat/cache.c b/fs/fat/cache.c index 738e427e2d21..8031e5ca15d1 100644 --- a/fs/fat/cache.c +++ b/fs/fat/cache.c @@ -167,6 +167,7 @@ static void fat_cache_add(struct inode *inode, struct fat_cache_id *new) cache = tmp; } else { struct list_head *p = MSDOS_I(inode)->cache_lru.prev; + cache = list_entry(p, struct fat_cache, cache_list); } cache->fcluster = new->fcluster; diff --git a/fs/fat/dir.c b/fs/fat/dir.c index b4ddf48fa444..50b8b88d68c7 100644 --- a/fs/fat/dir.c +++ b/fs/fat/dir.c @@ -182,6 +182,7 @@ static inline int fat_uni_to_x8(struct super_block *sb, const wchar_t *uni, unsigned char *buf, int size) { struct msdos_sb_info *sbi = MSDOS_SB(sb); + if (sbi->options.utf8) return utf16s_to_utf8s(uni, FAT_MAX_UNI_CHARS, UTF16_HOST_ENDIAN, buf, size); @@ -431,6 +432,7 @@ static int fat_parse_short(struct super_block *sb, uni_len = j; if (isvfat) { int offset = min(chl, MSDOS_NAME-k); + k += offset; i += offset; } else { @@ -669,6 +671,7 @@ static int __fat_readdir(struct inode *inode, struct file *file, unsigned long inum; loff_t i_pos = fat_make_i_pos(sb, bh, de); struct inode *tmp = fat_iget(sb, i_pos); + if (tmp) { inum = tmp->i_ino; iput(tmp); @@ -1343,6 +1346,7 @@ int fat_add_entries(struct inode *dir, void *slots, int nr_slots, /* Fill the long name slots. */ for (i = 0; i < long_bhs; i++) { int copy = min_t(int, sb->s_blocksize - offset, size); + memcpy(bhs[i]->b_data + offset, slots, copy); mark_buffer_dirty_inode(bhs[i], dir); offset = 0; @@ -1353,7 +1357,9 @@ int fat_add_entries(struct inode *dir, void *slots, int nr_slots, err = fat_sync_bhs(bhs, long_bhs); if (!err && i < nr_bhs) { /* Fill the short name slot. */ + int copy = min_t(int, sb->s_blocksize - offset, size); + memcpy(bhs[i]->b_data + offset, slots, copy); mark_buffer_dirty_inode(bhs[i], dir); if (IS_DIRSYNC(dir)) diff --git a/fs/fat/fatent.c b/fs/fat/fatent.c index bbfe18c07417..872550ffbc9b 100644 --- a/fs/fat/fatent.c +++ b/fs/fat/fatent.c @@ -24,6 +24,7 @@ static void fat12_ent_blocknr(struct super_block *sb, int entry, { struct msdos_sb_info *sbi = MSDOS_SB(sb); int bytes = entry + (entry >> 1); + WARN_ON(!fat_valid_entry(sbi, entry)); *offset = bytes & (sb->s_blocksize - 1); *blocknr = sbi->fat_start + (bytes >> sb->s_blocksize_bits); @@ -34,6 +35,7 @@ static void fat_ent_blocknr(struct super_block *sb, int entry, { struct msdos_sb_info *sbi = MSDOS_SB(sb); int bytes = (entry << sbi->fatent_shift); + WARN_ON(!fat_valid_entry(sbi, entry)); *offset = bytes & (sb->s_blocksize - 1); *blocknr = sbi->fat_start + (bytes >> sb->s_blocksize_bits); @@ -42,6 +44,7 @@ static void fat_ent_blocknr(struct super_block *sb, int entry, static void fat12_ent_set_ptr(struct fat_entry *fatent, int offset) { struct buffer_head **bhs = fatent->bhs; + if (fatent->nr_bhs == 1) { WARN_ON(offset >= (bhs[0]->b_size - 1)); fatent->u.ent12_p[0] = bhs[0]->b_data + offset; @@ -136,6 +139,7 @@ static int fat12_ent_get(struct fat_entry *fatent) static int fat16_ent_get(struct fat_entry *fatent) { int next = le16_to_cpu(*fatent->u.ent16_p); + WARN_ON((unsigned long)fatent->u.ent16_p & (2 - 1)); if (next >= BAD_FAT16) next = FAT_ENT_EOF; @@ -145,6 +149,7 @@ static int fat16_ent_get(struct fat_entry *fatent) static int fat32_ent_get(struct fat_entry *fatent) { int next = le32_to_cpu(*fatent->u.ent32_p) & 0x0fff; + WARN_ON((unsigned long)fatent->u.ent32_p & (4 - 1)); if (next >= BAD_FAT32) next = FAT_ENT_EOF; @@ -226,6 +231,7 @@ static int fat12_ent_next(struct fat_entry *fatent)
[PATCH v18 1/3] MAINTAINERS: da7280 updates to the Dialog Semiconductor search terms
This patch adds the da7280 bindings doc and driver to the Dialog Semiconductor support list. Signed-off-by: Roy Im --- v18: No changes. v17: No changes. v16: No changes. v15: No changes. v14: No changes. v13: No changes. v12: Corrected file list order. v11: No changes. v10: No changes. v9: No changes. v8: No changes. v7: No changes. v6: No changes. v5: No changes. v4: No changes. v3: No changes. v2: No changes. MAINTAINERS | 2 ++ 1 file changed, 2 insertions(+) diff --git a/MAINTAINERS b/MAINTAINERS index f0569cf..6d76a80 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -5003,6 +5003,7 @@ M:Support Opensource S: Supported W: http://www.dialog-semiconductor.com/products F: Documentation/devicetree/bindings/input/da90??-onkey.txt +F: Documentation/devicetree/bindings/input/dlg,da72??.txt F: Documentation/devicetree/bindings/mfd/da90*.txt F: Documentation/devicetree/bindings/regulator/da92*.txt F: Documentation/devicetree/bindings/regulator/slg51000.txt @@ -5013,6 +5014,7 @@ F:Documentation/hwmon/da90??.rst F: drivers/gpio/gpio-da90??.c F: drivers/hwmon/da90??-hwmon.c F: drivers/iio/adc/da91??-*.c +F: drivers/input/misc/da72??.[ch] F: drivers/input/misc/da90??_onkey.c F: drivers/input/touchscreen/da9052_tsi.c F: drivers/leds/leds-da90??.c -- end-of-patch for PATCH v18
[PATCH v18 3/3] Input: new da7280 haptic driver
Adds support for the Dialog DA7280 LRA/ERM Haptic Driver with multiple mode and integrated waveform memory and wideband support. It communicates via an I2C bus to the device. Reviewed-by: Jes Sorensen . Signed-off-by: Roy Im --- v18: - Corrected comments in Kconfig - Updated to preferred style for multi line comments in c file. v17: - fixed an issue. v16: - Corrected some code and updated description in Kconfig. v15: - Removed some defines and updated some comments. v14: - Updated pwm related code, alignments and comments. v13: - Updated some conditions in pwm function and alignments. v12: No changes. v11: - Updated the pwm related code, comments and typo. v10: - Updated the pwm related function and added some comments. v9: - Removed the header file and put the definitions into the c file. - Updated the pwm code and error logs with %pE v8: - Added changes to support FF_PERIODIC/FF_CUSTOM and FF_CONSTANT. - Updated the dt-related code. - Removed memless related functions. v7: - Added more attributes to handle one value per file. - Replaced and updated the dt-related code and functions called. - Fixed error/functions. v6: No changes. v5: Fixed errors in Kconfig file. v4: Updated code as dt-bindings are changed. v3: No changes. v2: Fixed kbuild error/warning drivers/input/misc/Kconfig | 12 + drivers/input/misc/Makefile |1 + drivers/input/misc/da7280.c | 1845 +++ 3 files changed, 1858 insertions(+) create mode 100644 drivers/input/misc/da7280.c diff --git a/drivers/input/misc/Kconfig b/drivers/input/misc/Kconfig index 362e8a0..d38b466 100644 --- a/drivers/input/misc/Kconfig +++ b/drivers/input/misc/Kconfig @@ -869,4 +869,16 @@ config INPUT_STPMIC1_ONKEY To compile this driver as a module, choose M here: the module will be called stpmic1_onkey. +config INPUT_DA7280_HAPTICS + tristate "Dialog Semiconductor DA7280 haptics support" + depends on INPUT && I2C + select REGMAP_I2C + help + Say Y to enable support for the Dialog DA7280 haptics driver. + The haptics can be controlled by PWM or GPIO + with I2C communication. + + To compile this driver as a module, choose M here: the + module will be called da7280. + endif diff --git a/drivers/input/misc/Makefile b/drivers/input/misc/Makefile index a48e5f2..9cfd6ab 100644 --- a/drivers/input/misc/Makefile +++ b/drivers/input/misc/Makefile @@ -25,6 +25,7 @@ obj-$(CONFIG_INPUT_CMA3000) += cma3000_d0x.o obj-$(CONFIG_INPUT_CMA3000_I2C)+= cma3000_d0x_i2c.o obj-$(CONFIG_INPUT_COBALT_BTNS)+= cobalt_btns.o obj-$(CONFIG_INPUT_CPCAP_PWRBUTTON)+= cpcap-pwrbutton.o +obj-$(CONFIG_INPUT_DA7280_HAPTICS) += da7280.o obj-$(CONFIG_INPUT_DA9052_ONKEY) += da9052_onkey.o obj-$(CONFIG_INPUT_DA9055_ONKEY) += da9055_onkey.o obj-$(CONFIG_INPUT_DA9063_ONKEY) += da9063_onkey.o diff --git a/drivers/input/misc/da7280.c b/drivers/input/misc/da7280.c new file mode 100644 index 000..ecc8428 --- /dev/null +++ b/drivers/input/misc/da7280.c @@ -0,0 +1,1845 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * DA7280 Haptic device driver + * + * Copyright (c) 2020 Dialog Semiconductor. + * Author: Roy Im + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* Registers */ +#define DA7280_IRQ_EVENT1 0x03 +#define DA7280_IRQ_EVENT_WARNING_DIAG 0x04 +#define DA7280_IRQ_EVENT_SEQ_DIAG 0x05 +#define DA7280_IRQ_STATUS10x06 +#define DA7280_IRQ_MASK1 0x07 +#define DA7280_FRQ_LRA_PER_H 0x0A +#define DA7280_FRQ_LRA_PER_L 0x0B +#define DA7280_ACTUATOR1 0x0C +#define DA7280_ACTUATOR2 0x0D +#define DA7280_ACTUATOR3 0x0E +#define DA7280_CALIB_V2I_H0x0F +#define DA7280_CALIB_V2I_L0x10 +#define DA7280_TOP_CFG1 0x13 +#define DA7280_TOP_CFG2 0x14 +#define DA7280_TOP_CFG4 0x16 +#define DA7280_TOP_INT_CFG1 0x17 +#define DA7280_TOP_CTL1 0x22 +#define DA7280_TOP_CTL2 0x23 +#define DA7280_SEQ_CTL2 0x28 +#define DA7280_GPI_0_CTL 0x29 +#define DA7280_GPI_1_CTL 0x2A +#define DA7280_GPI_2_CTL 0x2B +#define DA7280_MEM_CTL1 0x2C +#define DA7280_MEM_CTL2 0x2D +#define DA7280_TOP_CFG5 0x6E +#define DA7280_IRQ_MASK2 0x83 +#define DA7280_SNP_MEM_99 0xE7 + +/* Register field */ +
[PATCH v18 2/3] dt-bindings: input: Add document bindings for DA7280
Add device tree binding information for DA7280 haptic driver. Example bindings for DA7280 are added. Reviewed-by: Rob Herring . Signed-off-by: Roy Im --- v18: No changes. v17: No changes. v16: No changes. v15: No changes. v14: No changes. v13: No changes. v12: No changes. v11: No changes. v10: No changes. v9: No changes. v8: Updated descriptions for new properties. v7: No changes. v6: No changes. v5: Updated descriptions and fixed errors. v4: Fixed commit message, properties. v3: Fixed subject format. v2: No changes .../devicetree/bindings/input/dlg,da7280.txt | 109 + 1 file changed, 109 insertions(+) create mode 100644 Documentation/devicetree/bindings/input/dlg,da7280.txt diff --git a/Documentation/devicetree/bindings/input/dlg,da7280.txt b/Documentation/devicetree/bindings/input/dlg,da7280.txt new file mode 100644 index 000..e6b719d --- /dev/null +++ b/Documentation/devicetree/bindings/input/dlg,da7280.txt @@ -0,0 +1,109 @@ +Dialog Semiconductor DA7280 Haptics bindings + +Required properties: +- compatible: Should be "dlg,da7280". +- reg: Specifies the I2C slave address. + +- interrupt-parent : Specifies the phandle of the interrupt controller to + which the IRQs from DA7280 are delivered to. + +- dlg,actuator-type: Set Actuator type. it should be one of: + "LRA" - Linear Resonance Actuator type. + "ERM-bar" - Bar type Eccentric Rotating Mass. + "ERM-coin" - Coin type Eccentric Rotating Mass. + +- dlg,const-op-mode: Haptic operation mode for FF_CONSTANT. + Possible values: + 1 - Direct register override(DRO) mode triggered by i2c(default), + 2 - PWM data source mode controlled by PWM duty, +- dlg,periodic-op-mode: Haptic operation mode for FF_PERIODIC. + Possible values: + 1 - Register triggered waveform memory(RTWM) mode, the pattern + assigned to the PS_SEQ_ID played as much times as PS_SEQ_LOOP, + 2 - Edge triggered waveform memory(ETWM) mode, external GPI(N) + control are required to enable/disable and it needs to keep + device enabled by sending magnitude (X > 0), + the pattern is assigned to the GPI(N)_SEQUENCE_ID below. + The default value is 1 for both of the operation modes. + For more details, please see the datasheet. + +- dlg,nom-microvolt: Nominal actuator voltage rating. + Valid values: 0 - 600. +- dlg,abs-max-microvolt: Absolute actuator maximum voltage rating. + Valid values: 0 - 600. +- dlg,imax-microamp: Actuator max current rating. + Valid values: 0 - 252000. + Default: 13. +- dlg,impd-micro-ohms: the impedance of the actuator in micro ohms. + Valid values: 0 - 15. + +Optional properties: +- pwms : phandle to the physical PWM(Pulse Width Modulation) device. + PWM properties should be named "pwms". And number of cell is different + for each pwm device. + (See Documentation/devicetree/bindings/pwm/pwm.txt + for further information relating to pwm properties) + +- dlg,ps-seq-id: the PS_SEQ_ID(pattern ID in waveform memory inside chip) + to play back when RTWM-MODE is enabled. + Valid range: 0 - 15. +- dlg,ps-seq-loop: the PS_SEQ_LOOP, Number of times the pre-stored sequence + pointed to by PS_SEQ_ID or GPI(N)_SEQUENCE_ID is repeated. + Valid range: 0 - 15. +- dlg,gpiN-seq-id: the GPI(N)_SEQUENCE_ID, pattern to play + when gpi0 is triggered, 'N' must be 0 - 2. + Valid range: 0 - 15. +- dlg,gpiN-mode: the pattern mode which can select either + "Single-pattern" or "Multi-pattern", 'N' must be 0 - 2. +- dlg,gpiN-polarity: gpiN polarity which can be chosen among + "Rising-edge", "Falling-edge" and "Both-edge", + 'N' must be 0 - 2 + Haptic will work by this edge option in case of ETWM mode. + +- dlg,resonant-freq-hz: use in case of LRA. + the frequency range: 50 - 300. + Default: 205. + +- dlg,bemf-sens-enable: Enable for internal loop computations. +- dlg,freq-track-enable: Enable for resonant frequency tracking. +- dlg,acc-enable: Enable for active acceleration. +- dlg,rapid-stop-enable: Enable for rapid stop. +- dlg,amp-pid-enable: Enable for the amplitude PID. +- dlg,mem-array: Customized waveform memory(patterns) data downloaded to + the device during initialization. This is an array of 100 values(u8). + +For further information, see device datasheet. + +== + +Example: + + haptics: da7280-haptics@4a { + compatible = "dlg,da7280"; + reg = <0x4a>; + interrupt-parent = <>; + interrupts = <11 IRQ_TYPE_LEVEL_LOW>; + dlg,actuator-type = "LRA"; + dlg,dlg,const-op-mode = <1>; + dlg,dlg,periodic-op-mode = <1>; + dlg,nom-microvolt = <200>; + dlg,abs-max-microvolt = <200>; + dlg,imax-microamp = <17>; + dlg,resonant-freq-hz = <180>; + dlg,impd-micro-ohms = <1050>; + dlg,freq-track-enable; + dlg,rapid-stop-enable; +
[PATCH v18 0/3] da7280: haptic driver submission
This patch adds support for the Dialog DA7280 Haptic driver IC. In this patch set the following is provided: [PATCH v18 1/3] MAINTAINERS file update for DA7280 [PATCH v18 2/3] DA7280 DT Binding [PATCH v18 3/3] DA7280 Driver This patch applies against linux-next and v5.8-rc7 Thank you, Roy Im, Dialog Semiconductor Ltd. Roy Im (3): MAINTAINERS: da7280 updates to the Dialog Semiconductor search terms dt-bindings: input: Add document bindings for DA7280 Input: new da7280 haptic driver .../devicetree/bindings/input/dlg,da7280.txt | 109 ++ MAINTAINERS|2 + drivers/input/misc/Kconfig | 12 + drivers/input/misc/Makefile|1 + drivers/input/misc/da7280.c| 1845 5 files changed, 1969 insertions(+) create mode 100644 Documentation/devicetree/bindings/input/dlg,da7280.txt create mode 100644 drivers/input/misc/da7280.c -- end-of-patch for PATCH v18
[PATCH 2/2] kbuild: sort hostprogs before passing it to ifneq
The conditional: ifneq ($(hostprogs),) ... is evaluated to true if $(hostprogs) does not contain any word but whitespace characters. ifneq ($(strip $(hostprogs)),) ... is a safe way to avoid interpreting whitespace as a non-empty value, but I'd rather want to use the side-effect of $(sort ...) to do the equivalent. $(sort ...) is used in scripts/Makefile.host in order to drop duplication in $(hostprogs). It is also useful to strip excessive spaces. Move $(sort ...) before evaluating the ifneq. Signed-off-by: Masahiro Yamada --- scripts/Makefile.build | 5 - scripts/Makefile.host | 10 -- 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/scripts/Makefile.build b/scripts/Makefile.build index d41c1cd453b9..e0b6b5db11c2 100644 --- a/scripts/Makefile.build +++ b/scripts/Makefile.build @@ -45,12 +45,15 @@ include $(kbuild-file) include scripts/Makefile.lib -# Do not include hostprogs rules unless needed +# Do not include hostprogs rules unless needed. +# $(sort ...) is used here to remove duplicated words and excessive spaces. +hostprogs := $(sort $(hostprogs)) ifneq ($(hostprogs),) include scripts/Makefile.host endif # Do not include userprogs rules unless needed. +# $(sort ...) is used here to remove duplicated words and excessive spaces. userprogs := $(sort $(userprogs)) ifneq ($(userprogs),) include scripts/Makefile.userprogs diff --git a/scripts/Makefile.host b/scripts/Makefile.host index 687ca3f309e9..278b4d6ac945 100644 --- a/scripts/Makefile.host +++ b/scripts/Makefile.host @@ -38,24 +38,22 @@ $(obj)/%.tab.c $(obj)/%.tab.h: $(src)/%.y FORCE # Will compile qconf as a C++ program, and menu as a C program. # They are linked as C++ code to the executable qconf -__hostprogs := $(sort $(hostprogs)) - # C code # Executables compiled from a single .c file -host-csingle := $(foreach m,$(__hostprogs), \ +host-csingle := $(foreach m,$(hostprogs), \ $(if $($(m)-objs)$($(m)-cxxobjs),,$(m))) # C executables linked based on several .o files -host-cmulti:= $(foreach m,$(__hostprogs),\ +host-cmulti:= $(foreach m,$(hostprogs),\ $(if $($(m)-cxxobjs),,$(if $($(m)-objs),$(m # Object (.o) files compiled from .c files -host-cobjs := $(sort $(foreach m,$(__hostprogs),$($(m)-objs))) +host-cobjs := $(sort $(foreach m,$(hostprogs),$($(m)-objs))) # C++ code # C++ executables compiled from at least one .cc file # and zero or more .c files -host-cxxmulti := $(foreach m,$(__hostprogs),$(if $($(m)-cxxobjs),$(m))) +host-cxxmulti := $(foreach m,$(hostprogs),$(if $($(m)-cxxobjs),$(m))) # C++ Object (.o) files compiled from .cc files host-cxxobjs := $(sort $(foreach m,$(host-cxxmulti),$($(m)-cxxobjs))) -- 2.25.1
linux-next: manual merge of the net-next tree with the risc-v tree
Hi all, Today's linux-next merge of the net-next tree got a conflict in: lib/Kconfig between commit: 1a479f783857 ("lib: Add a generic version of devmem_is_allowed()") from the risc-v tree and commit: b8265621f488 ("Add pldmfw library for PLDM firmware update") from the net-next tree. I fixed it up (see below) and can carry the fix as necessary. This is now fixed as far as linux-next is concerned, but any non trivial conflicts should be mentioned to your upstream maintainer when your tree is submitted for merging. You may also want to consider cooperating with the maintainer of the conflicting tree to minimise any particularly complex conflicts. -- Cheers, Stephen Rothwell diff --cc lib/Kconfig index 610c16ecbb7c,3ffbca6998e5.. --- a/lib/Kconfig +++ b/lib/Kconfig @@@ -677,5 -677,6 +677,9 @@@ config GENERIC_LIB_CMPDI config GENERIC_LIB_UCMPDI2 bool +config GENERIC_LIB_DEVMEM_IS_ALLOWED + bool ++ + config PLDMFW + bool + default n pgpZamCHwqAQ7.pgp Description: OpenPGP digital signature
[PATCH] extract-cert: add static to local data
Fix the following warning from sparse: scripts/extract-cert.c:74:5: warning: symbol 'kbuild_verbose' was not declared. Should it be static? Signed-off-by: Masahiro Yamada --- scripts/extract-cert.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/extract-cert.c b/scripts/extract-cert.c index b071bf476fea..3bc48c726c41 100644 --- a/scripts/extract-cert.c +++ b/scripts/extract-cert.c @@ -71,7 +71,7 @@ static void drain_openssl_errors(void) static const char *key_pass; static BIO *wb; static char *cert_dst; -int kbuild_verbose; +static int kbuild_verbose; static void write_cert(X509 *x509) { -- 2.25.1
[PATCH] kconfig: add 'static' to some file-local data
Fix some warnings from sparce like follows: warning: symbol '...' was not declared. Should it be static? Signed-off-by: Masahiro Yamada --- scripts/kconfig/lexer.l | 2 +- scripts/kconfig/symbol.c | 14 ++ 2 files changed, 11 insertions(+), 5 deletions(-) diff --git a/scripts/kconfig/lexer.l b/scripts/kconfig/lexer.l index 6354c905b006..98daac3bc829 100644 --- a/scripts/kconfig/lexer.l +++ b/scripts/kconfig/lexer.l @@ -36,7 +36,7 @@ struct buffer { YY_BUFFER_STATE state; }; -struct buffer *current_buf; +static struct buffer *current_buf; static int last_ts, first_ts; diff --git a/scripts/kconfig/symbol.c b/scripts/kconfig/symbol.c index 9363e37b8870..ffa3ec65cc90 100644 --- a/scripts/kconfig/symbol.c +++ b/scripts/kconfig/symbol.c @@ -15,15 +15,21 @@ struct symbol symbol_yes = { .name = "y", .curr = { "y", yes }, .flags = SYMBOL_CONST|SYMBOL_VALID, -}, symbol_mod = { +}; + +struct symbol symbol_mod = { .name = "m", .curr = { "m", mod }, .flags = SYMBOL_CONST|SYMBOL_VALID, -}, symbol_no = { +}; + +struct symbol symbol_no = { .name = "n", .curr = { "n", no }, .flags = SYMBOL_CONST|SYMBOL_VALID, -}, symbol_empty = { +}; + +static struct symbol symbol_empty = { .name = "", .curr = { "", no }, .flags = SYMBOL_VALID, @@ -31,7 +37,7 @@ struct symbol symbol_yes = { struct symbol *sym_defconfig_list; struct symbol *modules_sym; -tristate modules_val; +static tristate modules_val; enum symbol_type sym_get_type(struct symbol *sym) { -- 2.25.1
Re: [PATCH v3 2/2] soc: mediatek: add mtk-devapc driver
On Wed, 2020-07-29 at 10:22 +0800, Chun-Kuang Hu wrote: > Neal Liu 於 2020年7月29日 週三 上午10:10寫道: > > > > Hi Chun-Kuang, > > > > On Tue, 2020-07-28 at 23:35 +0800, Chun-Kuang Hu wrote: > > > Hi, Neal: > > > > > > Neal Liu 於 2020年7月28日 週二 上午11:52寫道: > > > > > > > > Hi Chun-Kuang, > > > > > > > > On Mon, 2020-07-27 at 22:47 +0800, Chun-Kuang Hu wrote: > > > > > Hi, Neal: > > > > > > > > > > Neal Liu 於 2020年7月27日 週一 上午11:06寫道: > > > > > > > > > > > > Hi Chun-Kuang, > > > > > > > > > > > > On Fri, 2020-07-24 at 23:55 +0800, Chun-Kuang Hu wrote: > > > > > > > Hi, Neal: > > > > > > > > > > > > > > Neal Liu 於 2020年7月24日 週五 下午2:55寫道: > > > > > > > > > > > > > > > > Hi Chun-Kuang, > > > > > > > > > > > > > > > > On Fri, 2020-07-24 at 00:32 +0800, Chun-Kuang Hu wrote: > > > > > > > > > Hi, Neal: > > > > > > > > > > > > > > > > > > Neal Liu 於 2020年7月23日 週四 下午2:11寫道: > > > > > > > > > > > > > > > > > > > > Hi Chun-Kuang, > > > > > > > > > > > > > > > > > > > > On Wed, 2020-07-22 at 22:25 +0800, Chun-Kuang Hu wrote: > > > > > > > > > > > Hi, Neal: > > > > > > > > > > > > > > > > > > > > > > Neal Liu 於 2020年7月22日 週三 > > > > > > > > > > > 上午11:49寫道: > > > > > > > > > > > > > > > > > > > > > > > > Hi Chun-Kuang, > > > > > > > > > > > > > > > > > > > > > > > > On Wed, 2020-07-22 at 07:21 +0800, Chun-Kuang Hu wrote: > > > > > > > > > > > > > Hi, Neal: > > > > > > > > > > > > > > > > > > > > > > > > > > Neal Liu 於 2020年7月21日 週二 > > > > > > > > > > > > > 下午12:00寫道: > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > + > > > > > > > > > > > > > > +/* > > > > > > > > > > > > > > + * mtk_devapc_dump_vio_dbg - get the violation > > > > > > > > > > > > > > index and dump the full violation > > > > > > > > > > > > > > + * debug information. > > > > > > > > > > > > > > + */ > > > > > > > > > > > > > > +static bool mtk_devapc_dump_vio_dbg(struct > > > > > > > > > > > > > > mtk_devapc_context *ctx, u32 vio_idx) > > > > > > > > > > > > > > +{ > > > > > > > > > > > > > > + u32 shift_bit; > > > > > > > > > > > > > > + > > > > > > > > > > > > > > + if (check_vio_mask(ctx, vio_idx)) > > > > > > > > > > > > > > + return false; > > > > > > > > > > > > > > + > > > > > > > > > > > > > > + if (!check_vio_status(ctx, vio_idx)) > > > > > > > > > > > > > > + return false; > > > > > > > > > > > > > > + > > > > > > > > > > > > > > + shift_bit = get_shift_group(ctx, vio_idx); > > > > > > > > > > > > > > + > > > > > > > > > > > > > > + if (sync_vio_dbg(ctx, shift_bit)) > > > > > > > > > > > > > > + return false; > > > > > > > > > > > > > > + > > > > > > > > > > > > > > + devapc_extract_vio_dbg(ctx); > > > > > > > > > > > > > > > > > > > > > > > > > > I think get_shift_group(), sync_vio_dbg(), and > > > > > > > > > > > > > devapc_extract_vio_dbg() should be moved out of > > > > > > > > > > > > > vio_idx for-loop (the > > > > > > > > > > > > > loop in devapc_violation_irq()) because these three > > > > > > > > > > > > > function is not > > > > > > > > > > > > > related to vio_idx. > > > > > > > > > > > > > Another question: when multiple vio_idx violation > > > > > > > > > > > > > occur, vio_addr is > > > > > > > > > > > > > related to which one vio_idx? The latest happened one? > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > Actually, it's related to vio_idx. But we don't use it > > > > > > > > > > > > directly on these > > > > > > > > > > > > function. I think below snip code might be better way > > > > > > > > > > > > to understand it. > > > > > > > > > > > > > > > > > > > > > > > > for (...) > > > > > > > > > > > > { > > > > > > > > > > > > check_vio_mask() > > > > > > > > > > > > check_vio_status() > > > > > > > > > > > > > > > > > > > > > > > > // if get vio_idx, mask it temporarily > > > > > > > > > > > > mask_module_irq(true) > > > > > > > > > > > > clear_vio_status() > > > > > > > > > > > > > > > > > > > > > > > > // dump violation info > > > > > > > > > > > > get_shift_group() > > > > > > > > > > > > sync_vio_dbg() > > > > > > > > > > > > devapc_extract_vio_dbg() > > > > > > > > > > > > > > > > > > > > > > > > // unmask > > > > > > > > > > > > mask_module_irq(false) > > > > > > > > > > > > } > > > > > > > > > > > > > > > > > > > > > > This snip code does not explain any thing. I could > > > > > > > > > > > rewrite this code as: > > > > > > > > > > > > > > > > > > > > > > for (...) > > > > > > > > > > > { > > > > > > > > > > > check_vio_mask() > > > > > > > > > > > check_vio_status() > > > > > > > > > > > > > > > > > > > > > > // if get vio_idx, mask it temporarily > > > > > > > > > > > mask_module_irq(true) > > > > > > > > > > > clear_vio_status() > > > > > > > > > > > // unmask > > > > > > > > > > > mask_module_irq(false) > > > > > > > > > > > } > > > > > >
[PATCH 1/2] kbuild: move shared library build rules to scripts/gcc-plugins/Makefile
The shared library build rules are currently implemented in scripts/Makefile.host, but actually GCC-plugin is the only user of them. Hence, they do not need to be treewide available. Move all the relevant build rules to scripts/gcc-plugins/Makefile. I also optimized the build steps so *.so is directly built from .c because every upstream plugin is compiled from a single source file. I am still keeping the infrastructure to build a plugin from multiple files because Kees suggested to do so in my previous attempt. (https://lkml.org/lkml/2019/1/11/1107) If the plugin, foo.so, is compiled from two files foo.c and foo2.c, then you can do like follows: foo-objs := foo.o foo2.o Single-file plugins do not need the *-objs notation. Signed-off-by: Masahiro Yamada --- scripts/Makefile.build | 4 +-- scripts/Makefile.clean | 3 +- scripts/Makefile.host| 30 ++ scripts/gcc-plugins/Makefile | 61 +--- 4 files changed, 55 insertions(+), 43 deletions(-) diff --git a/scripts/Makefile.build b/scripts/Makefile.build index 2e8810b7e5ed..d41c1cd453b9 100644 --- a/scripts/Makefile.build +++ b/scripts/Makefile.build @@ -45,8 +45,8 @@ include $(kbuild-file) include scripts/Makefile.lib -# Do not include host rules unless needed -ifneq ($(hostprogs)$(hostcxxlibs-y)$(hostcxxlibs-m),) +# Do not include hostprogs rules unless needed +ifneq ($(hostprogs),) include scripts/Makefile.host endif diff --git a/scripts/Makefile.clean b/scripts/Makefile.clean index e2c76122319d..3cdf31218198 100644 --- a/scripts/Makefile.clean +++ b/scripts/Makefile.clean @@ -29,8 +29,7 @@ subdir-ymn:= $(addprefix $(obj)/,$(subdir-ymn)) __clean-files := $(extra-y) $(extra-m) $(extra-) \ $(always) $(always-y) $(always-m) $(always-) $(targets) $(clean-files) \ - $(hostprogs) $(hostprogs-y) $(hostprogs-m) $(hostprogs-) $(userprogs) \ - $(hostcxxlibs-y) $(hostcxxlibs-m) + $(hostprogs) $(hostprogs-y) $(hostprogs-m) $(hostprogs-) $(userprogs) __clean-files := $(filter-out $(no-clean-files), $(__clean-files)) diff --git a/scripts/Makefile.host b/scripts/Makefile.host index c8a4a033dc3e..687ca3f309e9 100644 --- a/scripts/Makefile.host +++ b/scripts/Makefile.host @@ -39,7 +39,6 @@ $(obj)/%.tab.c $(obj)/%.tab.h: $(src)/%.y FORCE # They are linked as C++ code to the executable qconf __hostprogs := $(sort $(hostprogs)) -host-cxxshlib := $(sort $(hostcxxlibs-y) $(hostcxxlibs-m)) # C code # Executables compiled from a single .c file @@ -61,16 +60,11 @@ host-cxxmulti := $(foreach m,$(__hostprogs),$(if $($(m)-cxxobjs),$(m))) # C++ Object (.o) files compiled from .cc files host-cxxobjs := $(sort $(foreach m,$(host-cxxmulti),$($(m)-cxxobjs))) -# Object (.o) files used by the shared libaries -host-cxxshobjs := $(sort $(foreach m,$(host-cxxshlib),$($(m:.so=-objs - host-csingle := $(addprefix $(obj)/,$(host-csingle)) host-cmulti:= $(addprefix $(obj)/,$(host-cmulti)) host-cobjs := $(addprefix $(obj)/,$(host-cobjs)) host-cxxmulti := $(addprefix $(obj)/,$(host-cxxmulti)) host-cxxobjs := $(addprefix $(obj)/,$(host-cxxobjs)) -host-cxxshlib := $(addprefix $(obj)/,$(host-cxxshlib)) -host-cxxshobjs := $(addprefix $(obj)/,$(host-cxxshobjs)) # # Handle options to gcc. Support building with separate output directory @@ -136,25 +130,5 @@ quiet_cmd_host-cxxobjs = HOSTCXX $@ $(host-cxxobjs): $(obj)/%.o: $(src)/%.cc FORCE $(call if_changed_dep,host-cxxobjs) -# Compile .c file, create position independent .o file -# Note that plugin capable gcc versions can be either C or C++ based -# therefore plugin source files have to be compilable in both C and C++ mode. -# This is why a C++ compiler is invoked on a .c file. -# host-cxxshobjs -> .o -quiet_cmd_host-cxxshobjs = HOSTCXX -fPIC $@ - cmd_host-cxxshobjs = $(HOSTCXX) $(hostcxx_flags) -fPIC -c -o $@ $< -$(host-cxxshobjs): $(obj)/%.o: $(src)/%.c FORCE - $(call if_changed_dep,host-cxxshobjs) - -# Link a shared library, based on position independent .o files -# *.o -> .so shared library (host-cxxshlib) -quiet_cmd_host-cxxshlib= HOSTLLD -shared $@ - cmd_host-cxxshlib= $(HOSTCXX) $(KBUILD_HOSTLDFLAGS) -shared -o $@ \ - $(addprefix $(obj)/, $($(target-stem)-objs)) \ - $(KBUILD_HOSTLDLIBS) $(HOSTLDLIBS_$(target-stem).so) -$(host-cxxshlib): FORCE - $(call if_changed,host-cxxshlib) -$(call multi_depend, $(host-cxxshlib), .so, -objs) - -targets += $(host-csingle) $(host-cmulti) $(host-cobjs)\ - $(host-cxxmulti) $(host-cxxobjs) $(host-cxxshlib) $(host-cxxshobjs) +targets += $(host-csingle) $(host-cmulti) $(host-cobjs) \ + $(host-cxxmulti) $(host-cxxobjs) diff --git a/scripts/gcc-plugins/Makefile b/scripts/gcc-plugins/Makefile index 4014ba7e2fbd..d66949bfeba4 100644 ---
Re: [PATCH] i2c: mv64xxx: Add bus error recovery
Hi Mark, On 8/07/20 9:10 am, Mark Tomlinson wrote: > This adds i2c bus recovery to the mv64xxx driver. > > Implement bus recovery to recover from SCL/SDA stuck low. > > This uses the generic recovery function, setting the clock/data lines as > GPIO pins, and sending 9 clocks to try and recover the bus. > > Signed-off-by: Mark Tomlinson Reviewed-by: Chris Packham One additional comment below > --- > drivers/i2c/busses/i2c-mv64xxx.c | 77 +++- > 1 file changed, 76 insertions(+), 1 deletion(-) > > diff --git a/drivers/i2c/busses/i2c-mv64xxx.c > b/drivers/i2c/busses/i2c-mv64xxx.c > index 829b8c98ae51..e58853ba3ef0 100644 > --- a/drivers/i2c/busses/i2c-mv64xxx.c > +++ b/drivers/i2c/busses/i2c-mv64xxx.c > @@ -21,6 +21,7 @@ > #include > #include > #include > +#include > #include > #include > #include > @@ -147,6 +148,10 @@ struct mv64xxx_i2c_data { > boolirq_clear_inverted; > /* Clk div is 2 to the power n, not 2 to the power n + 1 */ > boolclk_n_base_0; > + struct pinctrl *pinctrl; > + struct i2c_bus_recovery_inforinfo; > + struct pinctrl_state*pin_default_state; > + struct pinctrl_state*pin_gpio_state; > }; > > static struct mv64xxx_i2c_regs mv64xxx_i2c_regs_mv64xxx = { > @@ -325,7 +330,8 @@ mv64xxx_i2c_fsm(struct mv64xxx_i2c_data *drv_data, u32 > status) >drv_data->msg->flags); > drv_data->action = MV64XXX_I2C_ACTION_SEND_STOP; > mv64xxx_i2c_hw_init(drv_data); > - drv_data->rc = -EIO; > + i2c_recover_bus(_data->adapter); > + drv_data->rc = -EAGAIN; > } > } > > @@ -563,6 +569,7 @@ mv64xxx_i2c_wait_for_completion(struct mv64xxx_i2c_data > *drv_data) > "time_left: %d\n", drv_data->block, > (int)time_left); > mv64xxx_i2c_hw_init(drv_data); > + i2c_recover_bus(_data->adapter); > } > } else > spin_unlock_irqrestore(_data->lock, flags); > @@ -872,6 +879,69 @@ mv64xxx_of_config(struct mv64xxx_i2c_data *drv_data, > } > #endif /* CONFIG_OF */ > > +/* > + * Switch to bit bang mode to prepare for i2c generic recovery. > + */ > +static void mv64xxx_i2c_prepare_recovery(struct i2c_adapter *adap) > +{ > + struct mv64xxx_i2c_data *drv_data = i2c_get_adapdata(adap); > + > + pinctrl_select_state(drv_data->pinctrl, drv_data->pin_gpio_state); > +} > + > +/* > + * Return to normal i2c operation following recovery. > + */ > +static void mv64xxx_i2c_unprepare_recovery(struct i2c_adapter *adap) > +{ > + struct mv64xxx_i2c_data *drv_data = i2c_get_adapdata(adap); > + > + pinctrl_select_state(drv_data->pinctrl, drv_data->pin_default_state); > +} > + > +static int mv64xxx_i2c_init_recovery_info(struct mv64xxx_i2c_data *drv_data, > + struct platform_device *pd) > +{ > + struct i2c_bus_recovery_info *rinfo = _data->rinfo; > + struct device *dev = >dev; > + > + drv_data->pinctrl = devm_pinctrl_get(dev); > + if (!drv_data->pinctrl || IS_ERR(drv_data->pinctrl)) { > + dev_err(dev, "can't get pinctrl, bus recovery not supported\n"); > + return PTR_ERR(drv_data->pinctrl); > + } > + > + drv_data->pin_default_state = pinctrl_lookup_state(drv_data->pinctrl, > + PINCTRL_STATE_DEFAULT); > + drv_data->pin_gpio_state = pinctrl_lookup_state(drv_data->pinctrl, > + "gpio"); > + rinfo->scl_gpiod = devm_gpiod_get(dev, "scl", > + GPIOD_OUT_HIGH_OPEN_DRAIN); > + rinfo->sda_gpiod = devm_gpiod_get(dev, "sda", GPIOD_IN); Should these be mentioned in Documentation/devicetree/bindings/i2c/marvell,mv64xxx-i2c.yaml? > + if (PTR_ERR(rinfo->scl_gpiod) == -EPROBE_DEFER || > + PTR_ERR(rinfo->sda_gpiod) == -EPROBE_DEFER) > + return -EPROBE_DEFER; > + > + if (IS_ERR(rinfo->sda_gpiod) || > + IS_ERR(rinfo->scl_gpiod) || > + IS_ERR(drv_data->pin_default_state) || > + IS_ERR(drv_data->pin_gpio_state)) { > + dev_dbg(dev, "recovery information incomplete\n"); > + return 0; > + } > + > + dev_dbg(dev, "using scl-gpio %d and sda-gpio %d for recovery\n", > + rinfo->scl_gpiod ? desc_to_gpio(rinfo->scl_gpiod) : -1, > + rinfo->sda_gpiod ? desc_to_gpio(rinfo->sda_gpiod) : -1); > + > + rinfo->prepare_recovery = mv64xxx_i2c_prepare_recovery; > + rinfo->unprepare_recovery = mv64xxx_i2c_unprepare_recovery; > + rinfo->recover_bus = i2c_generic_scl_recovery; > + drv_data->adapter.bus_recovery_info = rinfo; > + > + return 0; > +} > + > static int > mv64xxx_i2c_probe(struct platform_device *pd) > { > @@ -939,6 +1009,10 @@ mv64xxx_i2c_probe(struct platform_device *pd) > >
[PATCH] net: nixge: fix potential memory leak in nixge_probe()
If some processes in nixge_probe() fail, free_netdev(dev) needs to be called to aviod a memory leak. Fixes: 87ab207981ec ("net: nixge: Separate ctrl and dma resources") Fixes: abcd3d6fc640 ("net: nixge: Fix error path for obtaining mac address") Reported-by: Hulk Robot Signed-off-by: Lu Wei --- drivers/net/ethernet/ni/nixge.c | 8 +--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/drivers/net/ethernet/ni/nixge.c b/drivers/net/ethernet/ni/nixge.c index d2708a57f2ff..4075f5e59955 100644 --- a/drivers/net/ethernet/ni/nixge.c +++ b/drivers/net/ethernet/ni/nixge.c @@ -1299,19 +1299,21 @@ static int nixge_probe(struct platform_device *pdev) netif_napi_add(ndev, >napi, nixge_poll, NAPI_POLL_WEIGHT); err = nixge_of_get_resources(pdev); if (err) - return err; + goto free_netdev; __nixge_hw_set_mac_address(ndev); priv->tx_irq = platform_get_irq_byname(pdev, "tx"); if (priv->tx_irq < 0) { netdev_err(ndev, "could not find 'tx' irq"); - return priv->tx_irq; + err = priv->tx_irq; + goto free_netdev; } priv->rx_irq = platform_get_irq_byname(pdev, "rx"); if (priv->rx_irq < 0) { netdev_err(ndev, "could not find 'rx' irq"); - return priv->rx_irq; + err = priv->rx_irq; + goto free_netdev; } priv->coalesce_count_rx = XAXIDMA_DFT_RX_THRESHOLD; -- 2.17.1
Re: [PATCH RFC] x86/bus_lock: Enable bus lock detection
On Fri, Jul 17, 2020 at 02:35:00PM -0700, Fenghua Yu wrote: > A bus lock [1] is acquired either through split locked access to writeback > (WB) > memory or by using locks to uncacheable (UC) memory (e.g. direct device Does SLD not detect the lock to UC memory? > assignment). This is typically >1000 cycles slower than an atomic operation > within a cache line. It also disrupts performance on other cores. > > Although split lock can be detected by #AC trap, the trap is triggered > before the instruction acquires bus lock. This makes it difficult to > mitigate bus lock (e.g. throttle the user application). Mitigate _in a non-fatal way_. The #AC makes it very easy to mitigate split locks, it just has the side effect of SIGBUGS or killing the KVM guest. > Some CPUs have ability to notify the kernel by an #DB trap after the > instruction acquires a bus lock and is executed. This allows the kernel > to enforce user application throttling or mitigations and also provides > a better environment to debug kernel split lock issues since the kernel > can continue instead of crashing. > > #DB for bus lock detect fixes all issues in #AC for split lock detect: Fixes "all" issues... and creates some new ones, e.g. there are use cases where preventing the split lock from happening in the first place is strongly desired. It's why that train wreck exists. > 1) It's architectural ... just need to look at one CPUID bit to know it >exists > 2) The IA32_DEBUGCTL MSR, which reports bus lock in #DB, is per-thread. >So each process or guest can have different behavior. > 3) It has support for VMM/guests (new VMEXIT codes, etc). > > Use the existing kernel command line option "split_lock_detect=" to handle > #DB for bus lock: Are SLD and BLD mutually exclusive? Can we even guarantee that given the track record of SLD? If not, we'll likely want to allow the user to choose between SDL and BLD via split_lock_detect. > split_lock_detect= > #AC for split lock #DB for bus lock > > off Do nothing Do nothing > > warn Kernel OOPs Kernel warns rate limited > Warn once per task and and continues to run. > disable future checking Warn once per task and > and continue to run. > When both features are > supported, warn in #DB > > fatal Kernel OOPs Kernel warn rate limited Unless the lock to UC #DB is new behavior, why would we revert to allowing split locks in the kernel? > Send SIGBUS to user Send SIGBUS to user > When both features are > supported, fatal in #AC. > > ratelimit:N Do nothing Kernel warns rate limited This should be more than "Do nothing" for #AC, e.g. fall back to warn or at least print a loud error. > and continue to run. > Limit bus lock rate to > N per second in the > current non root user. > > On systems that support #DB for bus lock detection the default is "warn". > > [1] Chapter 8 > https://software.intel.com/sites/default/files/managed/c5/15/architecture-instruction-set-extensions-programming-reference.pdf > > Signed-off-by: Fenghua Yu > Reviewed-by: Tony Luck > --- > .../admin-guide/kernel-parameters.txt | 48 +- > arch/x86/include/asm/cpu.h| 16 +- > arch/x86/include/asm/cpufeatures.h| 1 + > arch/x86/include/asm/msr-index.h | 1 + > arch/x86/include/uapi/asm/debugreg.h | 3 +- > arch/x86/kernel/cpu/common.c | 2 +- > arch/x86/kernel/cpu/intel.c | 156 +++--- > arch/x86/kernel/traps.c | 10 ++ > include/linux/sched/user.h| 4 +- > kernel/user.c | 7 + > 10 files changed, 214 insertions(+), 34 deletions(-) Maybe it's just me, but it'd be nice to break this into multiple patches so that the SLD refactoring is separate from the introduction of BLD. As is, I find it hard to review as I can't easily distinguish refactoring from new functionality. > diff --git a/Documentation/admin-guide/kernel-parameters.txt > b/Documentation/admin-guide/kernel-parameters.txt > index fb95fad81c79..7a1cb6fe8b8e 100644 > --- a/Documentation/admin-guide/kernel-parameters.txt > +++ b/Documentation/admin-guide/kernel-parameters.txt > @@ -4816,27 +4816,59 @@ > spia_peddr= > > split_lock_detect= > - [X86] Enable split lock detection > + [X86] Enable split lock detection or bus lock detection > >
[PATCH] net: ethernet: fix potential memory leak in gemini_ethernet_port_probe()
If some processes in gemini_ethernet_port_probe() fail, free_netdev(dev) needs to be called to avoid a memory leak. Fixes: 4d5ae32f5e1e ("net: ethernet: Add a driver for Gemini gigabit ethernet") Reported-by: Hulk Robot Signed-off-by: Lu Wei --- drivers/net/ethernet/cortina/gemini.c | 24 +++- 1 file changed, 19 insertions(+), 5 deletions(-) diff --git a/drivers/net/ethernet/cortina/gemini.c b/drivers/net/ethernet/cortina/gemini.c index 8d13ea370db1..5e93a1a570b6 100644 --- a/drivers/net/ethernet/cortina/gemini.c +++ b/drivers/net/ethernet/cortina/gemini.c @@ -2407,37 +2407,48 @@ static int gemini_ethernet_port_probe(struct platform_device *pdev) dmares = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (!dmares) { dev_err(dev, "no DMA resource\n"); + free_netdev(netdev); return -ENODEV; } port->dma_base = devm_ioremap_resource(dev, dmares); - if (IS_ERR(port->dma_base)) + if (IS_ERR(port->dma_base)) { + free_netdev(netdev); return PTR_ERR(port->dma_base); + } /* GMAC config memory */ gmacres = platform_get_resource(pdev, IORESOURCE_MEM, 1); if (!gmacres) { dev_err(dev, "no GMAC resource\n"); + free_netdev(netdev); return -ENODEV; } port->gmac_base = devm_ioremap_resource(dev, gmacres); - if (IS_ERR(port->gmac_base)) + if (IS_ERR(port->gmac_base)) { + free_netdev(netdev); return PTR_ERR(port->gmac_base); + } /* Interrupt */ irq = platform_get_irq(pdev, 0); - if (irq <= 0) + if (irq <= 0) { + free_netdev(netdev); return irq ? irq : -ENODEV; + } port->irq = irq; /* Clock the port */ port->pclk = devm_clk_get(dev, "PCLK"); if (IS_ERR(port->pclk)) { dev_err(dev, "no PCLK\n"); + free_netdev(netdev); return PTR_ERR(port->pclk); } ret = clk_prepare_enable(port->pclk); - if (ret) + if (ret) { + free_netdev(netdev); return ret; + } /* Maybe there is a nice ethernet address we should use */ gemini_port_save_mac_addr(port); @@ -2446,6 +2457,7 @@ static int gemini_ethernet_port_probe(struct platform_device *pdev) port->reset = devm_reset_control_get_exclusive(dev, NULL); if (IS_ERR(port->reset)) { dev_err(dev, "no reset\n"); + free_netdev(netdev); return PTR_ERR(port->reset); } reset_control_reset(port->reset); @@ -2501,8 +2513,10 @@ static int gemini_ethernet_port_probe(struct platform_device *pdev) IRQF_SHARED, port_names[port->id], port); - if (ret) + if (ret) { + free_netdev(netdev); return ret; + } ret = register_netdev(netdev); if (!ret) { -- 2.17.1
Re: [PATCH 0/9] arm64: Stolen time support
Hi Steven, On 2020/7/27 18:48, Steven Price wrote: > On 21/07/2020 04:26, zhukeqian wrote: >> Hi Steven, > > Hi Keqian, > >> On 2019/8/2 22:50, Steven Price wrote: >>> This series add support for paravirtualized time for arm64 guests and >>> KVM hosts following the specification in Arm's document DEN 0057A: >>> >>> https://developer.arm.com/docs/den0057/a >>> >>> It implements support for stolen time, allowing the guest to >>> identify time when it is forcibly not executing. >>> >>> It doesn't implement support for Live Physical Time (LPT) as there are >>> some concerns about the overheads and approach in the above >> Do you plan to pick up LPT support? As there is demand of cross-frequency >> migration >> (from older platform to newer platform). > > I don't have any plans to pick up the LPT support at the moment - feel free > to pick it up! ;) > >> I am not clear about the overheads and approach problem here, could you >> please >> give some detail information? Maybe we can work together to solve these >> concerns. :-) > > Fundamentally the issue here is that LPT only solves one small part of > migration between different hosts. To successfully migrate between hosts with > different CPU implementations it is also necessary to be able to virtualise > various ID registers (e.g. MIDR_EL1, REVIDR_EL1, AIDR_EL1) which we have no > support for currently. > Yeah, currently we are trying to do both timer freq virtualization and CPU feature virtualization. > The problem with just virtualising the registers is how you handle errata. > The guest will currently use those (and other) ID registers to decide whether > to enable specific errata workarounds. But what errata should be enabled for > a guest which might migrate to another host? > Thanks for pointing this out. I think the most important thing is that we should introduce a concept named CPU baseline which represents a standard platform. If we bring up a guest with a specific CPU baseline, then this guest can only run on a platform that is compatible with this CPU baseline. So "baseline" and "compatible" are the key point to promise successful cross-platform migration. > What we ideally need is a mechanism to communicate to the guest what > workarounds are required to successfully run on any of the hosts that the > guest may be migrated to. You may also have the situation where the > workarounds required for two hosts are mutually incompatible - something > needs to understand this and do the "right thing" (most likely just reject > this situation, i.e. prevent the migration). > > There are various options here: e.g. a para-virtualised interface to describe > the workarounds (but this is hard to do in an OS-agnostic way), or virtual-ID > registers describing an idealised environment where no workarounds are > required (and only hosts that have no errata affecting a guest would be able > to provide this). > My idea is similar with the "idealised environment", but errata workaround still exists. We do not provide para-virtualised interface, and migration is restricted between platforms that are compatible with baseline. Baseline should has two aspects: CPU feature and errata. These platforms that are compatible with a specific baseline should have the corresponding CPU feature and errata. > Given the above complexity and the fact that Armv8.6-A standardises the > frequency to 1GHz this didn't seem worth continuing with. So LPT was dropped > from the spec and patches to avoid holding up the stolen time support. > > However, if you have a use case which doesn't require such a generic > migration (e.g. perhaps old and new platforms are based on the same IP) then > it might be worth looking at bring this back. But to make the problem > solvable it either needs to be restricted to platforms which are > substantially the same (so the errata list will be identical), or there's > work to be done in preparation to deal with migrating a guest successfully > between hosts with potentially different errata requirements. > > Can you share more details about the hosts that you are interested in > migrating between? Here we have new platform with 1GHz timer, and old platform is 100MHZ, so we want to solve the cross-platform migration firstly. Thanks, Keqian > > Thanks, > > Steve > . >
Re: [PATCH] kunit: tool: adjust parse regex
On Wed, Jul 29, 2020 at 10:42 AM Marcelo Schmitt wrote: > > kunit config subcommand terminates with error if .config has a > configuration assigned with a string, for instance: > > CONFIG_CC_VERSION_TEXT="gcc (distro package version) ..." > > This patch adjusts the parse regex to consider such string assignments. > > Signed-off-by: Marcelo Schmitt > --- Thanks, Marcelo. I think we've actually already got a fix for this upstream: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=3f37d14b8a3152441f36b6bc74000996679f0998 Cheers, -- David
Re: [PATCH V2] dt-bindings: pci: convert QCOM pci bindings to YAML
Hi Rob, On 7/28/2020 9:24 PM, Rob Herring wrote: On Tue, Jul 28, 2020 at 9:27 AM Rob Herring wrote: On Sun, Jul 26, 2020 at 9:07 AM Sivaprakash Murugesan wrote: From: Sivaprakash Murugesan Convert QCOM pci bindings to YAML schema Signed-off-by: Sivaprakash Murugesan --- [v2] - Referenced pci-bus.yaml - removed duplicate properties already referenced by pci-bus.yaml - Addressed comments from Rob .../devicetree/bindings/pci/qcom,pcie.txt | 330 --- .../devicetree/bindings/pci/qcom,pcie.yaml | 447 + 2 files changed, 447 insertions(+), 330 deletions(-) delete mode 100644 Documentation/devicetree/bindings/pci/qcom,pcie.txt create mode 100644 Documentation/devicetree/bindings/pci/qcom,pcie.yaml diff --git a/Documentation/devicetree/bindings/pci/qcom,pcie.yaml b/Documentation/devicetree/bindings/pci/qcom,pcie.yaml new file mode 100644 index ..ddb84f49ac1c --- /dev/null +++ b/Documentation/devicetree/bindings/pci/qcom,pcie.yaml @@ -0,0 +1,447 @@ +# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause) + +%YAML 1.2 +--- +$id: "http://devicetree.org/schemas/pci/qcom,pcie.yaml#; +$schema: "http://devicetree.org/meta-schemas/core.yaml#; + +title: Qualcomm PCI express root complex + +maintainers: + - Sivaprakash Murugesan + +description: + QCOM PCIe controller uses Designware IP with Qualcomm specific hardware + wrappers. + +properties: + compatible: +enum: + - qcom,pcie-apq8064 + - qcom,pcie-apq8084 + - qcom,pcie-ipq4019 + - qcom,pcie-ipq8064 + - qcom,pcie-ipq8074 + - qcom,pcie-msm8996 + - qcom,pcie-qcs404 + - qcom,pcie-sdm845 + + reg: +description: Register ranges as listed in the reg-names property Can drop this. +maxItems: 4 + + reg-names: +items: + - const: dbi + - const: elbi + - const: parf + - const: config + + ranges: +maxItems: 2 + + interrupts: +items: + - description: MSI interrupts + + interrupt-names: +const: msi + + "#interrupt-cells": In pci-bus.yaml, so you can drop. I am getting the below error if I remove #interrupt-cells alone. properties: '#interrupt-cells' is a dependency of 'interrupt-map' interrupt-map is also documented in pci-bus.yaml hence dropping that as well.
PROBLEM: IO lockup on reiserfs FS.
Hello, When running rtorrent (in sync to file mode), my kernel eventually will not write to the disk causing all access to md7 to hang and eventually the kernel will become totally unresponsive. EDIT: I have since gotten a response in the bug tracker and I am filing thins to the reiserfs maintainers. (I'd find the file and report to the correct maintainer, but the docs are incomplete when it comes to discovering the source of the hung tasks in my case. I have filed bugs to correct this.) I still have no clue how to get gdb to print out where exactly this is happening. It can't find the __schedule function in the kernel or in the reiserfs.ko object file. I'm not even sure __schedule is the problem as it seems to be lock related which would point to __mutex_lock.isra. EDIT: I've managed to verify that all disks are accessible (smartctl -a /dev/sdX) and that the RAID array is working and accessible (mdadm --detail and echo-ing check/idle to the array and seeing progress). Keywords: Hung tasks, Lockup, reiserfs, RAID. Linux version 4.14.184-nopreempt-AMDGPU-dav9 (root@Phenom-II-x6) (gcc version 6.3.0 20170516 (Debian 6.3.0-18+deb9u1)) #1 SMP Fri Jun 19 17:02:34 UTC 2020 I didn't have Internet before 4.9.X so I can't say if any version of the Linux kernel didn't have this problem. [68812.480459] Not tainted 4.14.184-nopreempt-AMDGPU-dav9 #1 [68812.480464] "echo 0 > /proc/sys/kernel/hung_task_timeout_secs" disables this message. [68812.480469] CacheThread_Blo D0 9414 9082 0x0080 [68812.480476] Call Trace: [68812.480494] __schedule+0x29e/0x6c0 [68812.480505] schedule+0x32/0x80 [68812.480513] schedule_preempt_disabled+0xa/0x10 [68812.480520] __mutex_lock.isra.1+0x26b/0x4e0 [68812.480550] ? do_journal_begin_r+0xbe/0x390 [reiserfs] [68812.480570] do_journal_begin_r+0xbe/0x390 [reiserfs] [68812.480586] ? __switch_to_asm+0x35/0x70 [68812.480588] ? __switch_to_asm+0x41/0x70 [68812.480590] ? __switch_to_asm+0x35/0x70 [68812.480592] ? __switch_to_asm+0x41/0x70 [68812.480593] ? __switch_to_asm+0x35/0x70 [68812.480595] ? __switch_to_asm+0x41/0x70 [68812.480597] ? __switch_to_asm+0x35/0x70 [68812.480601] journal_begin+0x80/0x140 [reiserfs] [68812.480606] reiserfs_dirty_inode+0x3d/0xa0 [reiserfs] [68812.480609] ? __switch_to+0x1ee/0x3f0 [68812.480610] ? __switch_to+0x1ee/0x3f0 [68812.480612] __mark_inode_dirty+0x163/0x350 [68812.480615] generic_update_time+0x79/0xc0 [68812.480617] ? current_time+0x38/0x70 [68812.480619] file_update_time+0xbe/0x110 [68812.480622] __generic_file_write_iter+0x99/0x1b0 [68812.480624] generic_file_write_iter+0xe2/0x1c0 [68812.480626] __vfs_write+0x102/0x180 [68812.480628] vfs_write+0xb0/0x190 [68812.480630] SyS_pwrite64+0x90/0xb0 [68812.480632] do_syscall_64+0x6e/0x110 [68812.480634] entry_SYSCALL_64_after_hwframe+0x41/0xa6 [68812.480637] RIP: 0033:0x7f8a92976983 [68812.480638] RSP: 002b:7f8a779e1630 EFLAGS: 0293 ORIG_RAX: 0012 [68812.480640] RAX: ffda RBX: 7f8a779e1640 RCX: 7f8a92976983 [68812.480641] RDX: 0128 RSI: 01790ddf3c00 RDI: 0040 [68812.480642] RBP: 7f8a779e16f0 R08: 7f8a779e1558 R09: 0001 [68812.480643] R10: 2000 R11: 0293 R12: 2000 [68812.480644] R13: 01790a6b8dd0 R14: 01790ddf3c00 R15: 0128 [68812.480647] INFO: task ThreadPoolSingl:9908 blocked for more than 480 seconds. [68812.480648] Not tainted 4.14.184-nopreempt-AMDGPU-dav9 #1 [68812.480649] "echo 0 > /proc/sys/kernel/hung_task_timeout_secs" disables this message. [68812.480650] ThreadPoolSingl D0 9908 9082 0x0080 [68812.480651] Call Trace: [68812.480653] __schedule+0x29e/0x6c0 [68812.480655] schedule+0x32/0x80 [68812.480657] schedule_preempt_disabled+0xa/0x10 [68812.480658] __mutex_lock.isra.1+0x26b/0x4e0 [68812.480664] ? do_journal_begin_r+0xbe/0x390 [reiserfs] [68812.480668] do_journal_begin_r+0xbe/0x390 [reiserfs] [68812.480672] ? reiserfs_lookup+0xb5/0x160 [reiserfs] [68812.480677] journal_begin+0x80/0x140 [reiserfs] [68812.480681] reiserfs_create+0xfc/0x210 [reiserfs] [68812.480685] path_openat+0x1419/0x14d0 [68812.480687] ? futex_wake+0x91/0x170 [68812.480689] do_filp_open+0x99/0x110 [68812.480693] ? __check_object_size+0xfa/0x1a0 [68812.480695] ? __alloc_fd+0x3d/0x160 [68812.480696] ? do_sys_open+0x12e/0x210 [68812.480698] do_sys_open+0x12e/0x210 [68812.480700] do_syscall_64+0x6e/0x110 [68812.480702] entry_SYSCALL_64_after_hwframe+0x41/0xa6 [68812.480703] RIP: 0033:0x7f8a8c48770d [68812.480704] RSP: 002b:7f8a73eeb220 EFLAGS: 0293 ORIG_RAX: 0002 [68812.480706] RAX: ffda RBX: RCX: 7f8a8c48770d [68812.480707] RDX: 0180 RSI: 00c2 RDI: 0179286b1ae0 [68812.480708] RBP: 0003a2f8 R08: c0c1 R09: 01792b1b04e0 [68812.480709] R10: R11: 0293 R12: 0179286b1b1a [68812.480710]
Re: PROBLEM: IO lockup on reiserfs FS.
I should add that in chasing down this bug I have tried all the IO schedulers available (noop deadline and cfq). Cfq is the one I'm now using to reproduce this. Also, I don't know if it makes a difference, but when the system first starts up it takes 20m to get from the login manager to having my web browsers restart and get all their pages from online. It might be because there is a lot of IO going on or it might be that there are several stalls in the scheduling; just not bad enough to cause a hung task problem like above.
[PATCH] kunit: tool: adjust parse regex
kunit config subcommand terminates with error if .config has a configuration assigned with a string, for instance: CONFIG_CC_VERSION_TEXT="gcc (distro package version) ..." This patch adjusts the parse regex to consider such string assignments. Signed-off-by: Marcelo Schmitt --- tools/testing/kunit/kunit_config.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/testing/kunit/kunit_config.py b/tools/testing/kunit/kunit_config.py index e75063d603b5..8e55693fe812 100644 --- a/tools/testing/kunit/kunit_config.py +++ b/tools/testing/kunit/kunit_config.py @@ -10,7 +10,7 @@ import collections import re CONFIG_IS_NOT_SET_PATTERN = r'^# CONFIG_(\w+) is not set$' -CONFIG_PATTERN = r'^CONFIG_(\w+)=(\S+)$' +CONFIG_PATTERN = r'^CONFIG_(\w+)=((\S+)|(".*"))$' KconfigEntryBase = collections.namedtuple('KconfigEntry', ['name', 'value']) -- 2.27.0
Re: [PATCH] block: fix possible race on blk_get_queue()
On 2020-07-28 18:51, Luis Chamberlain wrote: > diff --git a/block/blk-core.c b/block/blk-core.c > index d9d632639bd1..febdd8e8d409 100644 > --- a/block/blk-core.c > +++ b/block/blk-core.c > @@ -605,12 +605,18 @@ EXPORT_SYMBOL(blk_alloc_queue); > */ > bool blk_get_queue(struct request_queue *q) > { > - if (likely(!blk_queue_dying(q))) { > - __blk_get_queue(q); > - return true; > + struct kobject *obj; > + > + obj = __blk_get_queue(q); > + if (!obj) > + return false; > + > + if (unlikely(blk_queue_dying(q))) { > + blk_put_queue(q); > + return false; > } > > - return false; > + return true; > } This change is not sufficient to prevent that the QUEUE_FLAG_DYING flag is set immediately after this function returns. I propose not to modify this function but instead to add a comment that is the responsibility of the caller to prevent that such a race condition occurs. > -static inline void __blk_get_queue(struct request_queue *q) > +static inline struct kobject * __must_check > +__blk_get_queue(struct request_queue *q) > { > - kobject_get(>kobj); > + return kobject_get_unless_zero(>kobj); > } If a function passes a queue pointer to another function that calls blk_get_queue() then the caller should guarantee that 'q' is valid during the entire duration of the call. In other words, I'm not sure the above change is an improvement. Thanks, Bart.
[PATCH v2] scsi: ufs: Fix possible infinite loop in ufshcd_hold
In ufshcd_suspend(), after clk-gating is suspended and link is set as Hibern8 state, ufshcd_hold() is still possibly invoked before ufshcd_suspend() returns. For example, MediaTek's suspend vops may issue UIC commands which would call ufshcd_hold() during the command issuing flow. Now if UFSHCD_CAP_HIBERN8_WITH_CLK_GATING capability is enabled, then ufshcd_hold() may enter infinite loops because there is no clk-ungating work scheduled or pending. In this case, ufshcd_hold() shall just bypass, and keep the link as Hibern8 state. Signed-off-by: Stanley Chu Signed-off-by: Andy Teng --- Changes since v1: - Fix return value: Use unique bool variable to get the result of flush_work(). Thcan prevent incorrect returned value, i.e., rc, if flush_work() returns true - Fix commit message --- drivers/scsi/ufs/ufshcd.c | 5 - 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c index 577cc0d7487f..acba2271c5d3 100644 --- a/drivers/scsi/ufs/ufshcd.c +++ b/drivers/scsi/ufs/ufshcd.c @@ -1561,6 +1561,7 @@ static void ufshcd_ungate_work(struct work_struct *work) int ufshcd_hold(struct ufs_hba *hba, bool async) { int rc = 0; + bool flush_result; unsigned long flags; if (!ufshcd_is_clkgating_allowed(hba)) @@ -1592,7 +1593,9 @@ int ufshcd_hold(struct ufs_hba *hba, bool async) break; } spin_unlock_irqrestore(hba->host->host_lock, flags); - flush_work(>clk_gating.ungate_work); + flush_result = flush_work(>clk_gating.ungate_work); + if (hba->clk_gating.is_suspended && !flush_result) + goto out; spin_lock_irqsave(hba->host->host_lock, flags); goto start; } -- 2.18.0
Re: WARNING: suspicious RCU usage - while installing a VM on a CPU listed under nohz_full
Hi Nitesh, On Wed, 29 Jul 2020 at 09:00, Wanpeng Li wrote: > > On Tue, 28 Jul 2020 at 22:40, Nitesh Narayan Lal wrote: > > > > Hi, > > > > I have recently come across an RCU trace with the 5.8-rc7 kernel that has > > the > > debug configs enabled while installing a VM on a CPU that is listed under > > nohz_full. > > > > Based on some of the initial debugging, my impression is that the issue is > > triggered because of the fastpath that is meant to optimize the writes to > > x2APIC > > ICR that eventually leads to a virtual IPI in fixed delivery mode, is > > getting > > invoked from the quiescent state. Could you try latest linux-next tree? I guess maybe some patches are pending in linux-next tree, I can't reproduce against linux-next tree.
Re: [PATCH v2 05/18] gpiolib: cdev: support GPIO_GET_LINE_IOCTL and GPIOLINE_GET_VALUES_IOCTL
On Sun, Jul 26, 2020 at 09:12:44AM +0800, Kent Gibson wrote: > On Sat, Jul 25, 2020 at 11:51:54PM +0300, Andy Shevchenko wrote: > > On Sat, Jul 25, 2020 at 7:24 AM Kent Gibson wrote: > > > [ snip ] > > > + test_bit(line_idx, (unsigned long > > > *)lc->attrs[i].mask)) > > > > This casting is not good. What about BE 32-bit architecture? > > > > I agree the casting is hideous, but I thought the outcome was correct > as it is manipulating addresses, not data. > You think the address of a 64-bit differs based on endian?? > Happy to change it - but not sure what to. > You are right - using bitops on u64 is problematic for BE-32 - the 32-bit words will be swapped if userspace treats the flags as the u64 it is defined as. I'll rework that for v3. Cheers, Kent.
Re: [PATCH v17 17/21] mm/lru: replace pgdat lru_lock with lruvec lock
在 2020/7/29 上午9:27, Alexander Duyck 写道: > On Tue, Jul 28, 2020 at 6:00 PM Alex Shi wrote: >> >> >> >> 在 2020/7/28 下午10:54, Alexander Duyck 写道: >>> On Tue, Jul 28, 2020 at 4:20 AM Alex Shi wrote: 在 2020/7/28 上午7:34, Alexander Duyck 写道: >> @@ -1876,6 +1876,12 @@ static unsigned noinline_for_stack >> move_pages_to_lru(struct lruvec *lruvec, >> * >> list_add(>lru,) >> * list_add(>lru,) //corrupt >> */ >> + new_lruvec = mem_cgroup_page_lruvec(page, >> page_pgdat(page)); >> + if (new_lruvec != lruvec) { >> + if (lruvec) >> + spin_unlock_irq(>lru_lock); >> + lruvec = lock_page_lruvec_irq(page); >> + } >> SetPageLRU(page); >> >> if (unlikely(put_page_testzero(page))) { > I was going through the code of the entire patch set and I noticed > these changes in move_pages_to_lru. What is the reason for adding the > new_lruvec logic? My understanding is that we are moving the pages to > the lruvec provided are we not?If so why do we need to add code to get > a new lruvec? The code itself seems to stand out from the rest of the > patch as it is introducing new code instead of replacing existing > locking code, and it doesn't match up with the description of what > this function is supposed to do since it changes the lruvec. this new_lruvec is the replacement of removed line, as following code: >> - lruvec = mem_cgroup_page_lruvec(page, pgdat); This recheck is for the page move the root memcg, otherwise it cause the bug: >>> >>> Okay, now I see where the issue is. You moved this code so now it has >>> a different effect than it did before. You are relocking things before >>> you needed to. Don't forget that when you came into this function you >>> already had the lock. In addition the patch is broken as it currently >>> stands as you aren't using similar logic in the code just above this >>> addition if you encounter an evictable page. As a result this is >>> really difficult to review as there are subtle bugs here. >> >> Why you think its a bug? the relock only happens if locked lruvec is >> different. >> and unlock the old one. > > The section I am talking about with the bug is this section here: >while (!list_empty(list)) { > + struct lruvec *new_lruvec = NULL; > + > page = lru_to_page(list); > VM_BUG_ON_PAGE(PageLRU(page), page); > list_del(>lru); > if (unlikely(!page_evictable(page))) { > - spin_unlock_irq(>lru_lock); > + spin_unlock_irq(>lru_lock); > putback_lru_page(page); > - spin_lock_irq(>lru_lock); > + spin_lock_irq(>lru_lock); It would be still fine. The lruvec->lru_lock will be checked again before we take and use it. And this lock will optimized in patch 19th which did by Hugh Dickins. > continue; > } > > Basically it probably is not advisable to be retaking the > lruvec->lru_lock directly as the lruvec may have changed so it > wouldn't be correct for the next page. It would make more sense to be > using your API and calling unlock_page_lruvec_irq and > lock_page_lruvec_irq instead of using the lock directly. > >>> >>> I suppose the correct fix is to get rid of this line, but it should >>> be placed everywhere the original function was calling >>> spin_lock_irq(). >>> >>> In addition I would consider changing the arguments/documentation for >>> move_pages_to_lru. You aren't moving the pages to lruvec, so there is >>> probably no need to pass that as an argument. Instead I would pass >>> pgdat since that isn't going to be moving and is the only thing you >>> actually derive based on the original lruvec. >> >> yes, The comments should be changed with the line was introduced from long >> ago. :) >> Anyway, I am wondering if it worth a v18 version resend? > > So I have been looking over the function itself and I wonder if it > isn't worth looking at rewriting this to optimize the locking behavior > to minimize the number of times we have to take the LRU lock. I have > some code I am working on that I plan to submit as an RFC in the next > day or so after I can get it smoke tested. The basic idea would be to > defer returning the evictiable pages or freeing the compound pages > until after we have processed the pages that can be moved while still > holding the lock. I would think it should reduce the lock contention > significantly while improving the throughput. > I had tried once, but the freeing page cross onto release_pages which hard to deal with. I am very glad to
RE: [PATCH v6 01/15] vfio/type1: Refactor vfio_iommu_type1_ioctl()
> From: Alex Williamson > Sent: Tuesday, July 28, 2020 11:54 PM > > On Mon, 27 Jul 2020 23:27:30 -0700 > Liu Yi L wrote: > > > This patch refactors the vfio_iommu_type1_ioctl() to use switch > > instead of if-else, and each command got a helper function. > > > > Cc: Kevin Tian > > CC: Jacob Pan > > Cc: Alex Williamson > > Cc: Eric Auger > > Cc: Jean-Philippe Brucker > > Cc: Joerg Roedel > > Cc: Lu Baolu > > Reviewed-by: Eric Auger > > Suggested-by: Christoph Hellwig > > Signed-off-by: Liu Yi L > > --- > > FYI, this commit is already in my next branch and linux-next as of today, you > can > drop it from future series. Thanks, got it. thanks. :-) Regards, Yi Liu > Alex > > > v4 -> v5: > > *) address comments from Eric Auger, add r-b from Eric. > > --- > > drivers/vfio/vfio_iommu_type1.c | 394 > > ++-- > > 1 file changed, 213 insertions(+), 181 deletions(-) > > > > diff --git a/drivers/vfio/vfio_iommu_type1.c > > b/drivers/vfio/vfio_iommu_type1.c index 5e556ac..3bd70ff 100644 > > --- a/drivers/vfio/vfio_iommu_type1.c > > +++ b/drivers/vfio/vfio_iommu_type1.c > > @@ -2453,6 +2453,23 @@ static int vfio_domains_have_iommu_cache(struct > vfio_iommu *iommu) > > return ret; > > } > > > > +static int vfio_iommu_type1_check_extension(struct vfio_iommu *iommu, > > + unsigned long arg) > > +{ > > + switch (arg) { > > + case VFIO_TYPE1_IOMMU: > > + case VFIO_TYPE1v2_IOMMU: > > + case VFIO_TYPE1_NESTING_IOMMU: > > + return 1; > > + case VFIO_DMA_CC_IOMMU: > > + if (!iommu) > > + return 0; > > + return vfio_domains_have_iommu_cache(iommu); > > + default: > > + return 0; > > + } > > +} > > + > > static int vfio_iommu_iova_add_cap(struct vfio_info_cap *caps, > > struct vfio_iommu_type1_info_cap_iova_range *cap_iovas, > > size_t size) > > @@ -2529,241 +2546,256 @@ static int vfio_iommu_migration_build_caps(struct > vfio_iommu *iommu, > > return vfio_info_add_capability(caps, _mig.header, > > sizeof(cap_mig)); } > > > > -static long vfio_iommu_type1_ioctl(void *iommu_data, > > - unsigned int cmd, unsigned long arg) > > +static int vfio_iommu_type1_get_info(struct vfio_iommu *iommu, > > +unsigned long arg) > > { > > - struct vfio_iommu *iommu = iommu_data; > > + struct vfio_iommu_type1_info info; > > unsigned long minsz; > > + struct vfio_info_cap caps = { .buf = NULL, .size = 0 }; > > + unsigned long capsz; > > + int ret; > > > > - if (cmd == VFIO_CHECK_EXTENSION) { > > - switch (arg) { > > - case VFIO_TYPE1_IOMMU: > > - case VFIO_TYPE1v2_IOMMU: > > - case VFIO_TYPE1_NESTING_IOMMU: > > - return 1; > > - case VFIO_DMA_CC_IOMMU: > > - if (!iommu) > > - return 0; > > - return vfio_domains_have_iommu_cache(iommu); > > - default: > > - return 0; > > - } > > - } else if (cmd == VFIO_IOMMU_GET_INFO) { > > - struct vfio_iommu_type1_info info; > > - struct vfio_info_cap caps = { .buf = NULL, .size = 0 }; > > - unsigned long capsz; > > - int ret; > > - > > - minsz = offsetofend(struct vfio_iommu_type1_info, iova_pgsizes); > > + minsz = offsetofend(struct vfio_iommu_type1_info, iova_pgsizes); > > > > - /* For backward compatibility, cannot require this */ > > - capsz = offsetofend(struct vfio_iommu_type1_info, cap_offset); > > + /* For backward compatibility, cannot require this */ > > + capsz = offsetofend(struct vfio_iommu_type1_info, cap_offset); > > > > - if (copy_from_user(, (void __user *)arg, minsz)) > > - return -EFAULT; > > + if (copy_from_user(, (void __user *)arg, minsz)) > > + return -EFAULT; > > > > - if (info.argsz < minsz) > > - return -EINVAL; > > + if (info.argsz < minsz) > > + return -EINVAL; > > > > - if (info.argsz >= capsz) { > > - minsz = capsz; > > - info.cap_offset = 0; /* output, no-recopy necessary */ > > - } > > + if (info.argsz >= capsz) { > > + minsz = capsz; > > + info.cap_offset = 0; /* output, no-recopy necessary */ > > + } > > > > - mutex_lock(>lock); > > - info.flags = VFIO_IOMMU_INFO_PGSIZES; > > + mutex_lock(>lock); > > + info.flags = VFIO_IOMMU_INFO_PGSIZES; > > > > - info.iova_pgsizes = iommu->pgsize_bitmap; > > + info.iova_pgsizes = iommu->pgsize_bitmap; > > > > - ret = vfio_iommu_migration_build_caps(iommu, ); > > + ret = vfio_iommu_migration_build_caps(iommu, ); > > > > - if (!ret) > > - ret = vfio_iommu_iova_build_caps(iommu, ); > > + if
RE: [PATCH 1/2] watchdog: imx7ulp: Strictly follow the sequence for wdog operations
Hi, Guenter > Subject: RE: [PATCH 1/2] watchdog: imx7ulp: Strictly follow the sequence for > wdog operations > > Hi, Guenter > > > > Subject: Re: [PATCH 1/2] watchdog: imx7ulp: Strictly follow the > > sequence for wdog operations > > > > On 7/27/20 11:42 PM, Anson Huang wrote: > > > According to reference manual, the i.MX7ULP WDOG's operations should > > > follow below sequence: > > > > > > 1. disable global interrupts; > > > 2. unlock the wdog and wait unlock bit set; 3. reconfigure the wdog > > > and wait for reconfiguration bit set; 4. enabel global interrupts. > > > > > > Strictly follow the recommended sequence can make it more robust. > > > > > > Signed-off-by: Anson Huang > > > --- > > > drivers/watchdog/imx7ulp_wdt.c | 29 + > > > 1 file changed, 29 insertions(+) > > > > > > diff --git a/drivers/watchdog/imx7ulp_wdt.c > > > b/drivers/watchdog/imx7ulp_wdt.c index 7993c8c..b414ecf 100644 > > > --- a/drivers/watchdog/imx7ulp_wdt.c > > > +++ b/drivers/watchdog/imx7ulp_wdt.c > > > @@ -4,6 +4,7 @@ > > > */ > > > > > > #include > > > +#include > > > #include > > > #include > > > #include > > > @@ -48,17 +49,32 @@ struct imx7ulp_wdt_device { > > > struct clk *clk; > > > }; > > > > > > +static inline void imx7ulp_wdt_wait(void __iomem *base, u32 mask) { > > > + int retries = 100; > > > + > > > + do { > > > + if (readl_relaxed(base + WDOG_CS) & mask) > > > + return; > > > + usleep_range(200, 1000); > > > + } while (retries--); > > > > Sleep with interrupts disabled ? I can not imagine that this works > > well in a single CPU system. On top of that, it seems quite pointless. > > Either you don't want to be interrupted or you do, but sleeping with > > interrupts disabled really doesn't make sense. And does it really take > > 200-1000 uS for the watchdog subsystem to react, and sometimes up to > > 200 * 100 = 20 mS ? That seems highly unlikely. If such a delay loop > > is indeed needed, it should be limited by a time, not by number of > repetitions. > > > > Unless there is evidence that there is a problem that needs to be > > solved, I am not going to accept this code. > > > > Oops, this is a mistake of using sleep with interrupt disabled, sorry for > that. > The best option is to use readl_relaxed_poll_timeout_atomic() to poll the > status bit, however, the i.MX7ULP watchdog is very special that the unlock > window ONLY open for several cycles, that means the unlock status bit will be > set and then clear automatically after those cycles, using > readl_relaxed_poll_timeout_atomic() will fail since there are many timeout > handle code in it and the unlock window is open and close during this timeout > handle interval, so it fail to catch the unlock bit. > > The ideal option is using atomic polling without any other timeout check to > make sure the unlock window is NOT missed, but I think Linux kernel will NOT > accept a while loop without timeout, and that is why I tried to use > usleep_ranges(), but obviously I made a mistake of using it with IRQ disabled. > > Do you have any suggestion of how to handle such case? If the hardware ONLY > unlock the register for a small window, how to poll the status bit with > timeout > handle and also make sure the timeout handle code as quick as possible to > NOT miss the window? > I did more experiment and found that below readl_poll_timeout_atomic() is actually working, so I sent a V2 with it, please help review, thank you. + u32 val = readl(base + WDOG_CS); + + if (!(val & mask)) + WARN_ON(readl_poll_timeout_atomic(base + WDOG_CS, val, + val & mask, 0, + WDOG_WAIT_TIMEOUT)); Thanks, Anson
[PATCH] drm/vkms: Fix soft lockup.
A soft deadlock occurs when call hrtimer_cancel in softirq context: a) The main frequency of the machine is very slow b) output->period_ns is very small, even only 1 ns The problem can be solved in the following way: Setting a hrtimer exit flag in the vkms_disable_vblank function and checking the flag in the vkms_vblank_simulate function. If the flag is set, the hrtimer is not added to hrtimer queue again,the hrtimer_cancel function can exit quickly without deadlock. watchdog: BUG: soft lockup - CPU#2 stuck for 134s! [syz-executor.2:18027] Modules linked in: CPU: 2 PID: 18027 Comm: syz-executor.2 Tainted: GW 5.8.0-rc2-csan #2 Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS Ubuntu-1.8.2-1ubuntu1 04/01/2014 RIP: 0010:csd_lock_wait kernel/smp.c:108 [inline] RIP: 0010:smp_call_function_many_cond+0x40c/0x470 kernel/smp.c:555 RSP: 0018:c900028d3a88 EFLAGS: 0297 RAX: 0002 RBX: 888237cacc80 RCX: 813240fc RDX: 0001 RSI: RDI: 0005 RBP: 0001 R08: 8881f497d000 R09: R10: R11: 0100 R12: 888237cf6fc0 R13: 0003 R14: 888237cacc88 R15: 0001 FS: 7fa6314a9700() GS:888237c8() knlGS: CS: 0010 DS: ES: CR0: 80050033 CR2: 00513c80 CR3: 0001e3df3002 CR4: 000626e0 Call Trace: smp_call_function_many kernel/smp.c:577 [inline] smp_call_function+0x40/0x80 kernel/smp.c:599 on_each_cpu+0x2a/0xc0 kernel/smp.c:717 __purge_vmap_area_lazy+0x7c/0xbc0 mm/vmalloc.c:1367 _vm_unmap_aliases.part.0+0x126/0x180 mm/vmalloc.c:1800 _vm_unmap_aliases mm/vmalloc.c:1769 [inline] vm_unmap_aliases+0x2f/0x40 mm/vmalloc.c:1823 change_page_attr_set_clr+0x10a/0x4a0 arch/x86/mm/pat/set_memory.c:1732 change_page_attr_clear arch/x86/mm/pat/set_memory.c:1789 [inline] set_memory_ro+0x2b/0x40 arch/x86/mm/pat/set_memory.c:1935 bpf_jit_binary_lock_ro include/linux/filter.h:815 [inline] bpf_int_jit_compile+0x54f/0x663 arch/x86/net/bpf_jit_comp.c:1929 bpf_prog_select_runtime+0x1cc/0x2c0 kernel/bpf/core.c:1807 bpf_migrate_filter net/core/filter.c:1264 [inline] bpf_prepare_filter net/core/filter.c:1312 [inline] bpf_prepare_filter+0x518/0x620 net/core/filter.c:1278 __get_filter+0x107/0x160 net/core/filter.c:1481 sk_attach_filter+0x19/0xa0 net/core/filter.c:1496 sock_setsockopt+0x1208/0x1230 net/core/sock.c:1080 __sys_setsockopt+0x248/0x270 net/socket.c:2123 __do_sys_setsockopt net/socket.c:2143 [inline] __se_sys_setsockopt net/socket.c:2140 [inline] __x64_sys_setsockopt+0x22/0x30 net/socket.c:2140 do_syscall_64+0x48/0xb0 arch/x86/entry/common.c:359 entry_SYSCALL_64_after_hwframe+0x44/0xa9 Sending NMI from CPU 2 to CPUs 0-1,3-5: NMI backtrace for cpu 4 skipped: idling at native_safe_halt+0xe/0x10 arch/x86/include/asm/irqflags.h:60 NMI backtrace for cpu 0 skipped: idling at native_safe_halt+0xe/0x10 arch/x86/include/asm/irqflags.h:60 NMI backtrace for cpu 1 NMI backtrace for cpu 3 CPU: 3 PID: 0 Comm: swapper/3 Tainted: GW 5.8.0-rc2-csan #2 Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS Ubuntu-1.8.2-1ubuntu1 04/01/2014 RIP: 0010:preempt_count arch/x86/include/asm/preempt.h:26 [inline] RIP: 0010:preempt_count_sub+0xa/0x90 kernel/sched/core.c:3874 RSP: 0018:c912cdd0 EFLAGS: 0046 RAX: 0001 RBX: 88822ecb8fb0 RCX: RDX: RSI: 0086 RDI: 0001 RBP: 888237d5edc0 R08: 888236ddc000 R09: R10: R11: R12: R13: 0086 R14: 888237d5edc0 R15: 85bc6d60 FS: () GS:888237cc() knlGS: CS: 0010 DS: ES: CR0: 80050033 CR2: 7f35cc47adb8 CR3: 05a23006 CR4: 000626e0 Call Trace: __raw_spin_unlock_irqrestore include/linux/spinlock_api_smp.h:161 [inline] _raw_spin_unlock_irqrestore+0x2f/0x50 kernel/locking/spinlock.c:191 unlock_hrtimer_base kernel/time/hrtimer.c:898 [inline] hrtimer_try_to_cancel kernel/time/hrtimer.c:1171 [inline] hrtimer_try_to_cancel+0xbd/0x1b0 kernel/time/hrtimer.c:1151 hrtimer_cancel+0x13/0x40 kernel/time/hrtimer.c:1278 __disable_vblank drivers/gpu/drm/drm_vblank.c:429 [inline] drm_vblank_disable_and_save+0x122/0x140 drivers/gpu/drm/drm_vblank.c:470 vblank_disable_fn+0x96/0xa0 drivers/gpu/drm/drm_vblank.c:487 call_timer_fn+0x3a/0x230 kernel/time/timer.c:1404 expire_timers kernel/time/timer.c:1449 [inline] __run_timers kernel/time/timer.c:1773 [inline] __run_timers kernel/time/timer.c:1740 [inline] run_timer_softirq+0x2b8/0x840 kernel/time/timer.c:1786 __do_softirq+0x118/0x344 kernel/softirq.c:292 asm_call_on_stack+0xf/0x20 arch/x86/entry/entry_64.S:711 __run_on_irqstack arch/x86/include/asm/irq_stack.h:22 [inline] run_on_irqstack_cond
[PATCH V2 2/2] watchdog: imx7ulp: Watchdog should continue running for wait/stop mode
When kernel idle, system will enter wait/stop mode, wdog should continue running in this scenario, and the refresh thread can wake up system from wait/stop mode. Signed-off-by: Anson Huang --- no change. --- drivers/watchdog/imx7ulp_wdt.c | 5 - 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/watchdog/imx7ulp_wdt.c b/drivers/watchdog/imx7ulp_wdt.c index 7d2b12e..2b4ff43 100644 --- a/drivers/watchdog/imx7ulp_wdt.c +++ b/drivers/watchdog/imx7ulp_wdt.c @@ -22,6 +22,8 @@ #define WDOG_CS_CLK(LPO_CLK << LPO_CLK_SHIFT) #define WDOG_CS_EN BIT(7) #define WDOG_CS_UPDATE BIT(5) +#define WDOG_CS_WAIT BIT(1) +#define WDOG_CS_STOP BIT(0) #define WDOG_CNT 0x4 #define WDOG_TOVAL 0x8 @@ -174,7 +176,8 @@ static void imx7ulp_wdt_init(void __iomem *base, unsigned int timeout) /* set an initial timeout value in TOVAL */ writel(timeout, base + WDOG_TOVAL); /* enable 32bit command sequence and reconfigure */ - val = WDOG_CS_CMD32EN | WDOG_CS_CLK | WDOG_CS_UPDATE; + val = WDOG_CS_CMD32EN | WDOG_CS_CLK | WDOG_CS_UPDATE | + WDOG_CS_WAIT | WDOG_CS_STOP; writel(val, base + WDOG_CS); imx7ulp_wdt_wait(base, WDOG_CS_RCS); local_irq_enable(); -- 2.7.4
[PATCH V2 1/2] watchdog: imx7ulp: Strictly follow the sequence for wdog operations
According to reference manual, the i.MX7ULP WDOG's operations should follow below sequence: 1. disable global interrupts; 2. unlock the wdog and wait unlock bit set; 3. reconfigure the wdog and wait for reconfiguration bit set; 4. enabel global interrupts. Strictly follow the recommended sequence can make it more robust. Signed-off-by: Anson Huang --- Changes since V1: - use readl_poll_timeout_atomic() instead of usleep_ranges() since IRQ is disabled. --- drivers/watchdog/imx7ulp_wdt.c | 29 + 1 file changed, 29 insertions(+) diff --git a/drivers/watchdog/imx7ulp_wdt.c b/drivers/watchdog/imx7ulp_wdt.c index 7993c8c..7d2b12e 100644 --- a/drivers/watchdog/imx7ulp_wdt.c +++ b/drivers/watchdog/imx7ulp_wdt.c @@ -5,6 +5,7 @@ #include #include +#include #include #include #include @@ -36,6 +37,7 @@ #define DEFAULT_TIMEOUT60 #define MAX_TIMEOUT128 #define WDOG_CLOCK_RATE1000 +#define WDOG_WAIT_TIMEOUT 1 static bool nowayout = WATCHDOG_NOWAYOUT; module_param(nowayout, bool, ); @@ -48,17 +50,31 @@ struct imx7ulp_wdt_device { struct clk *clk; }; +static inline void imx7ulp_wdt_wait(void __iomem *base, u32 mask) +{ + u32 val = readl(base + WDOG_CS); + + if (!(val & mask)) + WARN_ON(readl_poll_timeout_atomic(base + WDOG_CS, val, + val & mask, 0, + WDOG_WAIT_TIMEOUT)); +} + static void imx7ulp_wdt_enable(struct watchdog_device *wdog, bool enable) { struct imx7ulp_wdt_device *wdt = watchdog_get_drvdata(wdog); u32 val = readl(wdt->base + WDOG_CS); + local_irq_disable(); writel(UNLOCK, wdt->base + WDOG_CNT); + imx7ulp_wdt_wait(wdt->base, WDOG_CS_ULK); if (enable) writel(val | WDOG_CS_EN, wdt->base + WDOG_CS); else writel(val & ~WDOG_CS_EN, wdt->base + WDOG_CS); + imx7ulp_wdt_wait(wdt->base, WDOG_CS_RCS); + local_irq_enable(); } static bool imx7ulp_wdt_is_enabled(void __iomem *base) @@ -72,7 +88,12 @@ static int imx7ulp_wdt_ping(struct watchdog_device *wdog) { struct imx7ulp_wdt_device *wdt = watchdog_get_drvdata(wdog); + local_irq_disable(); + writel(UNLOCK, wdt->base + WDOG_CNT); + imx7ulp_wdt_wait(wdt->base, WDOG_CS_ULK); writel(REFRESH, wdt->base + WDOG_CNT); + imx7ulp_wdt_wait(wdt->base, WDOG_CS_RCS); + local_irq_enable(); return 0; } @@ -98,8 +119,12 @@ static int imx7ulp_wdt_set_timeout(struct watchdog_device *wdog, struct imx7ulp_wdt_device *wdt = watchdog_get_drvdata(wdog); u32 val = WDOG_CLOCK_RATE * timeout; + local_irq_disable(); writel(UNLOCK, wdt->base + WDOG_CNT); + imx7ulp_wdt_wait(wdt->base, WDOG_CS_ULK); writel(val, wdt->base + WDOG_TOVAL); + imx7ulp_wdt_wait(wdt->base, WDOG_CS_RCS); + local_irq_enable(); wdog->timeout = timeout; @@ -140,15 +165,19 @@ static void imx7ulp_wdt_init(void __iomem *base, unsigned int timeout) { u32 val; + local_irq_disable(); /* unlock the wdog for reconfiguration */ writel_relaxed(UNLOCK_SEQ0, base + WDOG_CNT); writel_relaxed(UNLOCK_SEQ1, base + WDOG_CNT); + imx7ulp_wdt_wait(base, WDOG_CS_ULK); /* set an initial timeout value in TOVAL */ writel(timeout, base + WDOG_TOVAL); /* enable 32bit command sequence and reconfigure */ val = WDOG_CS_CMD32EN | WDOG_CS_CLK | WDOG_CS_UPDATE; writel(val, base + WDOG_CS); + imx7ulp_wdt_wait(base, WDOG_CS_RCS); + local_irq_enable(); } static void imx7ulp_wdt_action(void *data) -- 2.7.4