Re: [PATCH 05/11] btrfs: add helper methods for workspace manager init and cleanup
On 28.01.19 г. 23:24 ч., Dennis Zhou wrote: > Workspace manager init and cleanup code is open coded inside a for loop > over the compression types. This forces each compression type to rely on > the same workspace manager implementation. This patch creates helper > methods that will be the generic implementation for btrfs workspace > management. > > Signed-off-by: Dennis Zhou Reviewed-by: Nikolay Borisov
Re: WARNING in vb2_core_reqbufs
syzbot has found a reproducer for the following crash on: HEAD commit:39ad1c1b6bb8 Add linux-next specific files for 20190129 git tree: linux-next console output: https://syzkaller.appspot.com/x/log.txt?x=17971f1740 kernel config: https://syzkaller.appspot.com/x/.config?x=a2b2e9c0bc43c14d dashboard link: https://syzkaller.appspot.com/bug?extid=f9966a25169b6d66d61f compiler: gcc (GCC) 9.0.0 20181231 (experimental) syz repro: https://syzkaller.appspot.com/x/repro.syz?x=1342c7a0c0 C reproducer: https://syzkaller.appspot.com/x/repro.c?x=15a241c4c0 IMPORTANT: if you fix the bug, please add the following tag to the commit: Reported-by: syzbot+f9966a25169b6d66d...@syzkaller.appspotmail.com WARNING: CPU: 1 PID: 8082 at drivers/media/common/videobuf2/videobuf2-core.c:728 vb2_core_reqbufs+0x59b/0xf10 drivers/media/common/videobuf2/videobuf2-core.c:728 Kernel panic - not syncing: panic_on_warn set ... CPU: 1 PID: 8082 Comm: syz-executor505 Not tainted 5.0.0-rc4-next-20190129 #21 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+0x1db/0x2d0 lib/dump_stack.c:113 panic+0x2cb/0x65c kernel/panic.c:214 __warn.cold+0x20/0x48 kernel/panic.c:571 report_bug+0x263/0x2b0 lib/bug.c:186 fixup_bug arch/x86/kernel/traps.c:178 [inline] fixup_bug arch/x86/kernel/traps.c:173 [inline] do_error_trap+0x11b/0x200 arch/x86/kernel/traps.c:271 do_invalid_op+0x37/0x50 arch/x86/kernel/traps.c:290 invalid_op+0x14/0x20 arch/x86/entry/entry_64.S:973 RIP: 0010:vb2_core_reqbufs+0x59b/0xf10 drivers/media/common/videobuf2/videobuf2-core.c:728 Code: 83 e0 07 83 c0 03 38 d0 7c 08 84 d2 0f 85 56 08 00 00 45 8b 3c 9e 31 ff 44 89 fe e8 9f 41 3d fc 45 85 ff 75 9f e8 15 40 3d fc <0f> 0b 41 bc ea ff ff ff e8 08 40 3d fc 48 b8 00 00 00 00 00 fc ff RSP: 0018:88809d8e7680 EFLAGS: 00010293 RAX: 88809138e3c0 RBX: RCX: 8544da11 RDX: RSI: 8544da1b RDI: 0005 RBP: 88809d8e77b0 R08: 88809138e3c0 R09: 88808d42d6f0 R10: ed1011a85ae5 R11: 88808d42d72f R12: 0001 R13: dc00 R14: 88809d8e7728 R15: vb2_reqbufs drivers/media/common/videobuf2/videobuf2-v4l2.c:664 [inline] vb2_reqbufs+0x1cb/0x210 drivers/media/common/videobuf2/videobuf2-v4l2.c:659 v4l2_m2m_reqbufs+0x90/0x1d0 drivers/media/v4l2-core/v4l2-mem2mem.c:457 v4l2_m2m_ioctl_reqbufs+0x6b/0x80 drivers/media/v4l2-core/v4l2-mem2mem.c:1051 v4l_reqbufs drivers/media/v4l2-core/v4l2-ioctl.c:1932 [inline] v4l_reqbufs+0xad/0xe0 drivers/media/v4l2-core/v4l2-ioctl.c:1921 __video_do_ioctl+0x805/0xd80 drivers/media/v4l2-core/v4l2-ioctl.c:2872 video_usercopy+0x460/0x16b0 drivers/media/v4l2-core/v4l2-ioctl.c:3054 video_ioctl2+0x2d/0x35 drivers/media/v4l2-core/v4l2-ioctl.c:3098 v4l2_ioctl+0x156/0x1b0 drivers/media/v4l2-core/v4l2-dev.c:364 vfs_ioctl fs/ioctl.c:46 [inline] file_ioctl fs/ioctl.c:509 [inline] do_vfs_ioctl+0x107b/0x17d0 fs/ioctl.c:696 ksys_ioctl+0xab/0xd0 fs/ioctl.c:713 __do_sys_ioctl fs/ioctl.c:720 [inline] __se_sys_ioctl fs/ioctl.c:718 [inline] __x64_sys_ioctl+0x73/0xb0 fs/ioctl.c:718 do_syscall_64+0x1a3/0x800 arch/x86/entry/common.c:290 entry_SYSCALL_64_after_hwframe+0x49/0xbe RIP: 0033:0x440049 Code: 18 89 d0 c3 66 2e 0f 1f 84 00 00 00 00 00 0f 1f 00 48 89 f8 48 89 f7 48 89 d6 48 89 ca 4d 89 c2 4d 89 c8 4c 8b 4c 24 08 0f 05 <48> 3d 01 f0 ff ff 0f 83 fb 13 fc ff c3 66 2e 0f 1f 84 00 00 00 00 RSP: 002b:7ffc76fc9aa8 EFLAGS: 0246 ORIG_RAX: 0010 RAX: ffda RBX: 004002c8 RCX: 00440049 RDX: 2400 RSI: c0145608 RDI: 0003 RBP: 006ca018 R08: R09: 004002c8 R10: R11: 0246 R12: 004018d0 R13: 00401960 R14: R15: Kernel Offset: disabled Rebooting in 86400 seconds..
Re: [PATCH 04/11] btrfs: unify compression ops with workspace_manager
On 28.01.19 г. 23:24 ч., Dennis Zhou wrote: > Make the workspace_manager own the interface operations rather than > managing index-paired arrays for the workspace_manager and compression > operations. > > Signed-off-by: Dennis Zhou Reviewed-by: Nikolay Borisov > --- > fs/btrfs/compression.c | 11 +++ > 1 file changed, 7 insertions(+), 4 deletions(-) > > diff --git a/fs/btrfs/compression.c b/fs/btrfs/compression.c > index bda7e8d2cbc7..b7e986e16640 100644 > --- a/fs/btrfs/compression.c > +++ b/fs/btrfs/compression.c > @@ -777,6 +777,7 @@ const struct btrfs_compress_op btrfs_heuristic_compress = > { > }; > > struct workspace_manager { > + const struct btrfs_compress_op *ops; > struct list_head idle_ws; > spinlock_t ws_lock; > /* Number of free workspaces */ > @@ -802,6 +803,8 @@ void __init btrfs_init_compress(void) > int i; > > for (i = 0; i < BTRFS_COMPRESS_TYPES; i++) { > + wsm[i].ops = btrfs_compress_op[i]; > + > INIT_LIST_HEAD([i].idle_ws); > spin_lock_init([i].ws_lock); > atomic_set([i].total_ws, 0); > @@ -811,7 +814,7 @@ void __init btrfs_init_compress(void) >* Preallocate one workspace for each compression type so >* we can guarantee forward progress in the worst case >*/ > - workspace = btrfs_compress_op[i]->alloc_workspace(); > + workspace = wsm[i].ops->alloc_workspace(); > if (IS_ERR(workspace)) { > pr_warn("BTRFS: cannot preallocate compression > workspace, will try later\n"); > } else { > @@ -874,7 +877,7 @@ static struct list_head *find_workspace(int type) >* context of btrfs_compress_bio/btrfs_compress_pages >*/ > nofs_flag = memalloc_nofs_save(); > - workspace = btrfs_compress_op[type]->alloc_workspace(); > + workspace = wsm[type].ops->alloc_workspace(); > memalloc_nofs_restore(nofs_flag); > > if (IS_ERR(workspace)) { > @@ -932,7 +935,7 @@ static void free_workspace(int type, struct list_head > *workspace) > } > spin_unlock(ws_lock); > > - btrfs_compress_op[type]->free_workspace(workspace); > + wsm[type].ops->free_workspace(workspace); > atomic_dec(total_ws); > wake: > cond_wake_up(ws_wait); > @@ -950,7 +953,7 @@ static void free_workspaces(void) > while (!list_empty([i].idle_ws)) { > workspace = wsm[i].idle_ws.next; > list_del(workspace); > - btrfs_compress_op[i]->free_workspace(workspace); > + wsm[i].ops->free_workspace(workspace); > atomic_dec([i].total_ws); > } > } >
Re: [PATCH 03/11] btrfs: manage heuristic workspace as index 0
On 28.01.19 г. 23:24 ч., Dennis Zhou wrote: > While the heuristic workspaces aren't really compression workspaces, > they use the same interface for managing them. So rather than branching, > let's just handle them once again as the index 0 compression type. > > Signed-off-by: Dennis Zhou Reviewed-by: Nikolay Borisov albeit one minor nit below. > --- > fs/btrfs/compression.c | 107 +++- > fs/btrfs/compression.h | 3 +- > fs/btrfs/ioctl.c| 2 +- > fs/btrfs/tree-checker.c | 4 +- > 4 files changed, 33 insertions(+), 83 deletions(-) > > diff --git a/fs/btrfs/compression.c b/fs/btrfs/compression.c > index aced261984e2..bda7e8d2cbc7 100644 > --- a/fs/btrfs/compression.c > +++ b/fs/btrfs/compression.c > @@ -37,6 +37,8 @@ const char* btrfs_compress_type2str(enum > btrfs_compression_type type) > case BTRFS_COMPRESS_ZSTD: > case BTRFS_COMPRESS_NONE: > return btrfs_compress_types[type]; > + default: > + return NULL; nit: With this change... > } > > return NULL; This becomes redundant. I doubt the compiler will issue a warning since it should be clever enough to figure we will never exit the switch() construct. > @@ -769,6 +771,11 @@ static struct list_head *alloc_heuristic_ws(void) > return ERR_PTR(-ENOMEM); > } > > +const struct btrfs_compress_op btrfs_heuristic_compress = { > + .alloc_workspace = alloc_heuristic_ws, > + .free_workspace = free_heuristic_ws, > +}; > + > struct workspace_manager { > struct list_head idle_ws; > spinlock_t ws_lock; > @@ -782,9 +789,8 @@ struct workspace_manager { > > static struct workspace_manager wsm[BTRFS_COMPRESS_TYPES]; > > -static struct workspace_manager btrfs_heuristic_ws; > - > static const struct btrfs_compress_op * const btrfs_compress_op[] = { > + _heuristic_compress, > _zlib_compress, > _lzo_compress, > _zstd_compress, > @@ -795,21 +801,6 @@ void __init btrfs_init_compress(void) > struct list_head *workspace; > int i; > > - INIT_LIST_HEAD(_heuristic_ws.idle_ws); > - spin_lock_init(_heuristic_ws.ws_lock); > - atomic_set(_heuristic_ws.total_ws, 0); > - init_waitqueue_head(_heuristic_ws.ws_wait); > - > - workspace = alloc_heuristic_ws(); > - if (IS_ERR(workspace)) { > - pr_warn( > - "BTRFS: cannot preallocate heuristic workspace, will try later\n"); > - } else { > - atomic_set(_heuristic_ws.total_ws, 1); > - btrfs_heuristic_ws.free_ws = 1; > - list_add(workspace, _heuristic_ws.idle_ws); > - } > - > for (i = 0; i < BTRFS_COMPRESS_TYPES; i++) { > INIT_LIST_HEAD([i].idle_ws); > spin_lock_init([i].ws_lock); > @@ -837,11 +828,10 @@ void __init btrfs_init_compress(void) > * Preallocation makes a forward progress guarantees and we do not return > * errors. > */ > -static struct list_head *__find_workspace(int type, bool heuristic) > +static struct list_head *find_workspace(int type) > { > struct list_head *workspace; > int cpus = num_online_cpus(); > - int idx = type - 1; > unsigned nofs_flag; > struct list_head *idle_ws; > spinlock_t *ws_lock; > @@ -849,19 +839,11 @@ static struct list_head *__find_workspace(int type, > bool heuristic) > wait_queue_head_t *ws_wait; > int *free_ws; > > - if (heuristic) { > - idle_ws = _heuristic_ws.idle_ws; > - ws_lock = _heuristic_ws.ws_lock; > - total_ws = _heuristic_ws.total_ws; > - ws_wait = _heuristic_ws.ws_wait; > - free_ws = _heuristic_ws.free_ws; > - } else { > - idle_ws = [idx].idle_ws; > - ws_lock = [idx].ws_lock; > - total_ws = [idx].total_ws; > - ws_wait = [idx].ws_wait; > - free_ws = [idx].free_ws; > - } > + idle_ws = [type].idle_ws; > + ws_lock = [type].ws_lock; > + total_ws = [type].total_ws; > + ws_wait = [type].ws_wait; > + free_ws = [type].free_ws; > > again: > spin_lock(ws_lock); > @@ -892,10 +874,7 @@ static struct list_head *__find_workspace(int type, bool > heuristic) >* context of btrfs_compress_bio/btrfs_compress_pages >*/ > nofs_flag = memalloc_nofs_save(); > - if (heuristic) > - workspace = alloc_heuristic_ws(); > - else > - workspace = btrfs_compress_op[idx]->alloc_workspace(); > + workspace = btrfs_compress_op[type]->alloc_workspace(); > memalloc_nofs_restore(nofs_flag); > > if (IS_ERR(workspace)) { > @@ -926,38 +905,23 @@ static struct list_head *__find_workspace(int type, > bool heuristic) > return workspace; > } > > -static struct list_head *find_workspace(int type) > -{ > - return __find_workspace(type, false); > -} > - > /* > * put a workspace struct back on the list or free it if we have enough >
Re: [PATCH v2] mm/slub: introduce SLAB_WARN_ON_ERROR
On Tue, 2019-01-29 at 05:46 +, Christopher Lameter wrote: > On Mon, 28 Jan 2019, Andrew Morton wrote: > > > > When debugging slab errors in slub.c, sometimes we have to trigger > > > a panic in order to get the coredump file. Add a debug option > > > SLAB_WARN_ON_ERROR to toggle WARN_ON() when the option is set. > > > > > > Change since v1: > > > 1. Add a special debug option SLAB_WARN_ON_ERROR and toggle WARN_ON() > > > if it is set. > > > 2. SLAB_WARN_ON_ERROR can be set by kernel parameter slub_debug. > > > > > > > Hopefully the slab developers will have an opinion on this. > > Debugging slab itself is usually done in kvm or some other virtualized > environment. Then gdb can be used to set breakpoints. Otherwise one may > add printks and stuff to the allocators to figure out more or use perf. > > > What you are changing here is the debugging for data corruption within > objects managed by slub or the metadata. Slub currently outputs extensive > data about the metadata corruption (typically caused by a user of > slab allocation) which should allow you to set a proper > breakpoint not in the allocator but in the subsystem where the corruption > occurs. > Thanks for your comments. The real problems the change can help are: a) classic slub issue. e.g., use-after-free, redzone overwritten. It's more efficient to report a issue as soon as slub detects it. (comparing to monitor the log, set a breakpoint, and re-produce the issue). With the coredump file, we can analyze the issue. b) memory corruption issues caused by h/w write. e.g., memory overwritten by a DMA engine. Memory corruptions may or may not related to the slab cache that reports any error. For example: kmalloc-256 or dentry may report the same errors. If we can preserve the the coredump file without any restore/reset processing in slub, we could have more information of this memory corruption. c) memory corruption issues caused by unstable h/w. e.g., bit flipping because of DRAM die or applying new power settings. It's hard to re-produce this kind of issue and it much easier to tell this kind of issue in the coredump file without any restore/reset processing. Users can set the option by slub_debug. We can still have the original behavior(keep the system alive) if the option is not set. We can turn on the option when we need the coredump file. (with panic_on_warn is set, of course).
Re: [linux-sunxi] [PATCH v2 1/2] media: v4l: Add definitions for the HEVC slice format and controls
On Fri, Jan 25, 2019 at 10:04 PM Paul Kocialkowski wrote: > > Hi, > > On Thu, 2019-01-24 at 20:23 +0800, Ayaka wrote: > > > > Sent from my iPad > > > > > On Jan 24, 2019, at 6:27 PM, Paul Kocialkowski > > > wrote: > > > > > > Hi, > > > > > > > On Thu, 2019-01-10 at 21:32 +0800, ayaka wrote: > > > > I forget a important thing, for the rkvdec and rk hevc decoder, it would > > > > requests cabac table, scaling list, picture parameter set and reference > > > > picture storing in one or various of DMA buffers. I am not talking about > > > > the data been parsed, the decoder would requests a raw data. > > > > > > > > For the pps and rps, it is possible to reuse the slice header, just let > > > > the decoder know the offset from the bitstream bufer, I would suggest to > > > > add three properties(with sps) for them. But I think we need a method to > > > > mark a OUTPUT side buffer for those aux data. > > > > > > I'm quite confused about the hardware implementation then. From what > > > you're saying, it seems that it takes the raw bitstream elements rather > > > than parsed elements. Is it really a stateless implementation? > > > > > > The stateless implementation was designed with the idea that only the > > > raw slice data should be passed in bitstream form to the decoder. For > > > H.264, it seems that some decoders also need the slice header in raw > > > bitstream form (because they take the full slice NAL unit), see the > > > discussions in this thread: > > > media: docs-rst: Document m2m stateless video decoder interface > > > > Stateless just mean it won’t track the previous result, but I don’t > > think you can define what a date the hardware would need. Even you > > just build a dpb for the decoder, it is still stateless, but parsing > > less or more data from the bitstream doesn’t stop a decoder become a > > stateless decoder. > > Yes fair enough, the format in which the hardware decoder takes the > bitstream parameters does not make it stateless or stateful per-se. > It's just that stateless decoders should have no particular reason for > parsing the bitstream on their own since the hardware can be designed > with registers for each relevant bitstream element to configure the > decoding pipeline. That's how GPU-based decoder implementations are > implemented (VAAPI/VDPAU/NVDEC, etc). > > So the format we have agreed on so far for the stateless interface is > to pass parsed elements via v4l2 control structures. > > If the hardware can only work by parsing the bitstream itself, I'm not > sure what the best solution would be. Reconstructing the bitstream in > the kernel is a pretty bad option, but so is parsing in the kernel or > having the data both in parsed and raw forms. Do you see another > possibility? Is reconstructing the bitstream so bad? The v4l2 controls provide a generic interface to an encoded format which the driver needs to convert into a sequence that the hardware can understand. Typically this is done by populating hardware-specific structures. Can't we consider that in this specific instance, the hardware-specific structure just happens to be identical to the original bitstream format? I agree that this is not strictly optimal for that particular hardware, but such is the cost of abstractions, and in this specific case I don't believe the cost would be particularly high?
[PATCH] spi: ti-qspi: Fix mmap read when more than one CS in use
Commit 4dea6c9b0b64 ("spi: spi-ti-qspi: add mmap mode read support") has has got order of parameter wrong when calling regmap_update_bits() to select CS for mmap access. Mask and value arguments are interchanged. Code will work on a system with single slave, but fails when more than one CS is in use. Fix this by correcting the order of parameters when calling regmap_update_bits(). Fixes: 4dea6c9b0b64 ("spi: spi-ti-qspi: add mmap mode read support") Cc: sta...@vger.kernel.org Signed-off-by: Vignesh R --- drivers/spi/spi-ti-qspi.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/spi/spi-ti-qspi.c b/drivers/spi/spi-ti-qspi.c index 5f19016bbf10..b9fb6493cd6b 100644 --- a/drivers/spi/spi-ti-qspi.c +++ b/drivers/spi/spi-ti-qspi.c @@ -490,8 +490,8 @@ static void ti_qspi_enable_memory_map(struct spi_device *spi) ti_qspi_write(qspi, MM_SWITCH, QSPI_SPI_SWITCH_REG); if (qspi->ctrl_base) { regmap_update_bits(qspi->ctrl_base, qspi->ctrl_reg, - MEM_CS_EN(spi->chip_select), - MEM_CS_MASK); + MEM_CS_MASK, + MEM_CS_EN(spi->chip_select)); } qspi->mmap_enabled = true; } @@ -503,7 +503,7 @@ static void ti_qspi_disable_memory_map(struct spi_device *spi) ti_qspi_write(qspi, 0, QSPI_SPI_SWITCH_REG); if (qspi->ctrl_base) regmap_update_bits(qspi->ctrl_base, qspi->ctrl_reg, - 0, MEM_CS_MASK); + MEM_CS_MASK, 0); qspi->mmap_enabled = false; } -- 2.20.1
答复: [2/2] mfd: max77620: Add low battery monitor support
Oh yeah will do, thanks. -邮件原件- 发件人: Billy Laws 发送时间: Tuesday, January 29, 2019 3:36 PM 收件人: Mark Zhang 抄送: Lee Jones ; linux-kernel@vger.kernel.org; linux-te...@vger.kernel.org; Laxman Dewangan ; Venkat Reddy Talla 主题: Re: [2/2] mfd: max77620: Add low battery monitor support Sure, that's fine with me, will send then this gets accepted. Two other things: you should probably set the reg to 0 if the property isn't specified as regmap_add_irqchip sets it to 0xff (basically all enabled on highest limit), and you haven't updated the dt-bindings. On Tue, Jan 29, 2019 at 6:52 AM Mark Zhang wrote: > > On 1/27/2019 10:54 PM, Billy Laws wrote: > > >This patch adds PMIC configurations for low-battery >monitoring > > by handling max77620 register CNFGGLBL1. > > > > > It might be an idea to add lbhyst configuration here and support > > using custom lbdac values to specify a different cutoff point. > > Yeah this patch doesn't have support to program LBHYST & LBDAC because > according to our experiences, we don't have requirement to modify them > when low battery monitor support added. > > I think we can create a new patch to support these 2 fields in the > future when we really need them. Or you can create a patch if you have > requirement for them, is this OK to you Billy? > > Mark > > > > > See: https://datasheetspdf.com/pdf-file/924230/Maxim/MAX8698C/1 pg > > 46 > > >Signed-off-by: Laxman Dewangan > > >Signed-off-by: Venkat Reddy Talla > > >Signed-off-by: Mark Zhang > > >--- > > > drivers/mfd/max77620.c | 57 > > +- > > > 1 file changed, 56 insertions(+), 1 deletion(-) > >diff --git > > a/drivers/mfd/max77620.c b/drivers/mfd/max77620.c >index > > f58143103185..9e50d145afd8 100644 > > >--- a/drivers/mfd/max77620.c > > >+++ b/drivers/mfd/max77620.c > > >@@ -474,6 +474,57 @@ static int > > max77620_init_backup_battery_charging(struct max77620_chip *chip) > > > return ret; > } > >+static int > > max77620_init_low_battery_monitor(struct max77620_chip *chip) >+{ > > >+ struct device *dev = chip->dev; >+ struct device_node *np; >+ > > bool pval; >+ u8 mask = 0; >+ u8 val = 0; >+ int ret; >+ >+ np > > = of_get_child_by_name(dev->of_node, "low-battery-monitor"); >+ if > > (!np) { >+ dev_info(dev, "Low battery monitoring support > > disabled\n"); >+ return 0; >+ } >+ >+ pval = > > of_property_read_bool(np, "maxim,low-battery-dac-enable"); >+ if > > (pval) { >+ mask |= MAX77620_CNFGGLBL1_LBDAC_EN; >+ val |= > > MAX77620_CNFGGLBL1_LBDAC_EN; >+ } >+ >+ pval = > > of_property_read_bool(np, "maxim,low-battery-dac-disable"); >+ if > > (pval) >+ mask |= MAX77620_CNFGGLBL1_LBDAC_EN; >+ >+ pval = > > of_property_read_bool(np, "maxim,low-battery-shutdown-enable"); > > >+ if (pval) { > > >+ mask |= MAX77620_CNFGGLBL1_MPPLD; >+ val |= > > MAX77620_CNFGGLBL1_MPPLD; >+ } >+ >+ pval = > > of_property_read_bool(np, "maxim,low-battery-shutdown-disable"); > > >+ if (pval) > > >+ mask |= MAX77620_CNFGGLBL1_MPPLD; >+ >+ pval = > > of_property_read_bool(np, "maxim,low-battery-reset-enable"); > > >+ if (pval) { > > >+ mask |= MAX77620_CNFGGLBL1_LBRSTEN; >+ val |= > > MAX77620_CNFGGLBL1_LBRSTEN; >+ } >+ >+ pval = > > of_property_read_bool(np, "maxim,low-battery-reset-disable"); > > >+ if (pval) > > >+ mask |= MAX77620_CNFGGLBL1_LBRSTEN; >+ >+ ret = > > regmap_update_bits(chip->rmap, MAX77620_REG_CNFGGLBL1, mask, val); > > >+ if (ret < 0) >+ dev_err(dev, "Reg CNFGGLBL1 update failed: > > %d\n", ret); >+ return ret; >+} >+ > static int > > max77620_read_es_version(struct max77620_chip *chip) > { > > > unsigned int val; >@@ -563,7 +614,11 @@ static int > > max77620_probe(struct i2c_client *client, > if (ret < 0) > > > return ret; > > > >- ret = devm_mfd_add_devices(chip->dev, PLATFORM_DEVID_NONE, >+ > > ret = max77620_init_low_battery_monitor(chip); > > >+ if (ret < 0) > > >+ return ret; > > >+ > > >+ ret = devm_mfd_add_devices(chip->dev, PLATFORM_DEVID_NONE, > > > mfd_cells, n_mfd_cells, NULL, 0, > > > regmap_irq_get_domain(chip->top_irq_data)); > > > if (ret < 0) { > >
Re: [PATCH trivial] kernel.h: Make container_of_safe type safe
On Mon, Jan 28, 2019 at 06:44:24PM +, Jason Gunthorpe wrote: > On Mon, Jan 28, 2019 at 05:42:42AM -0800, Christoph Hellwig wrote: > > On Thu, Jan 24, 2019 at 08:55:05PM +, Jason Gunthorpe wrote: > > > The final ternary expression is given void * and type * as arguments, so > > > the resulting type of the macro ends up being void *. > > > > > > container_of returns a type which maches the argument, this provides type > > > safety and allows the expression to be immediately used as the target > > > type. > > > > > > Explicitly cast ERR_CAST() to get the correct type. > > > > I think we should just kill off container_of_safe - it has no user > > in the tree, is grossly misnamed and not really all that useful to start > > with. > > I see it open coded from time to time, here someone sent a patch > open-coding it yesterday (with the same bug even): > > https://patchwork.kernel.org/patch/10783535/ > > I noticed it didn't work right because I had a use for it.. And the patch is a good example for an anti-pattern to avoid, I'll chime in there..
Re: [PATCH 5/5] virtio-blk: Consider virtio_max_dma_size() for maximum segment size
On Mon, Jan 28, 2019 at 12:14:33PM -0500, Michael S. Tsirkin wrote: > On Mon, Jan 28, 2019 at 09:05:26AM +0100, Christoph Hellwig wrote: > > On Thu, Jan 24, 2019 at 10:51:51AM +0100, Joerg Roedel wrote: > > > On Thu, Jan 24, 2019 at 09:42:21AM +0100, Christoph Hellwig wrote: > > > > Yes. But more importantly it would fix the limit for all other block > > > > drivers that set large segment sizes when running over swiotlb. > > > > > > True, so it would be something like the diff below? I havn't worked on > > > the block layer, so I don't know if that needs additional checks for > > > ->dev or anything. > > > > Looks sensible. Maybe for now we'll just do the virtio-blk case > > that triggered it, and we'll do something like this patch for the > > next merge window. We'll also need to apply the same magic to the > > DMA boundary. > > So do I get an ack for this patch then? I'll wait for a resend of the series to review the whole thing.
[PATCH] x86/mm: Remove unused cpu variable
cpu variable is never used after commit ("x86/mm: Pass flush_tlb_info to flush_tlb_others() etc"), so remove it. Cc: Andy Lutomirski Cc: Dave Hansen Cc: Peter Zijlstra Signed-off-by: Shaokun Zhang --- arch/x86/mm/tlb.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/arch/x86/mm/tlb.c b/arch/x86/mm/tlb.c index 999d6d8f0bef..bc4bc7b2f075 100644 --- a/arch/x86/mm/tlb.c +++ b/arch/x86/mm/tlb.c @@ -685,9 +685,6 @@ void native_flush_tlb_others(const struct cpumask *cpumask, * that UV should be updated so that smp_call_function_many(), * etc, are optimal on UV. */ - unsigned int cpu; - - cpu = smp_processor_id(); cpumask = uv_flush_tlb_others(cpumask, info); if (cpumask) smp_call_function_many(cpumask, flush_tlb_func_remote, -- 2.7.4
Re: [2/2] mfd: max77620: Add low battery monitor support
Sure, that's fine with me, will send then this gets accepted. Two other things: you should probably set the reg to 0 if the property isn't specified as regmap_add_irqchip sets it to 0xff (basically all enabled on highest limit), and you haven't updated the dt-bindings. On Tue, Jan 29, 2019 at 6:52 AM Mark Zhang wrote: > > On 1/27/2019 10:54 PM, Billy Laws wrote: > > >This patch adds PMIC configurations for low-battery > > >monitoring by handling max77620 register CNFGGLBL1. > > > > > It might be an idea to add lbhyst configuration here and support using > > custom lbdac values to specify a different cutoff point. > > Yeah this patch doesn't have support to program LBHYST & LBDAC because > according to our experiences, we don't have requirement to modify them > when low battery monitor support added. > > I think we can create a new patch to support these 2 fields in the future > when we really need them. Or you can create a patch if you have requirement > for them, is this OK to you Billy? > > Mark > > > > > See: https://datasheetspdf.com/pdf-file/924230/Maxim/MAX8698C/1 pg 46 > > >Signed-off-by: Laxman Dewangan > > >Signed-off-by: Venkat Reddy Talla > > >Signed-off-by: Mark Zhang > > >--- > > > drivers/mfd/max77620.c | 57 +- > > > 1 file changed, 56 insertions(+), 1 deletion(-) > > > > > >diff --git a/drivers/mfd/max77620.c b/drivers/mfd/max77620.c > > >index f58143103185..9e50d145afd8 100644 > > >--- a/drivers/mfd/max77620.c > > >+++ b/drivers/mfd/max77620.c > > >@@ -474,6 +474,57 @@ static int > > max77620_init_backup_battery_charging(struct max77620_chip *chip) > > > return ret; > > > } > > > > > >+static int max77620_init_low_battery_monitor(struct max77620_chip *chip) > > >+{ > > >+ struct device *dev = chip->dev; > > >+ struct device_node *np; > > >+ bool pval; > > >+ u8 mask = 0; > > >+ u8 val = 0; > > >+ int ret; > > >+ > > >+ np = of_get_child_by_name(dev->of_node, "low-battery-monitor"); > > >+ if (!np) { > > >+ dev_info(dev, "Low battery monitoring support disabled\n"); > > >+ return 0; > > >+ } > > >+ > > >+ pval = of_property_read_bool(np, "maxim,low-battery-dac-enable"); > > >+ if (pval) { > > >+ mask |= MAX77620_CNFGGLBL1_LBDAC_EN; > > >+ val |= MAX77620_CNFGGLBL1_LBDAC_EN; > > >+ } > > >+ > > >+ pval = of_property_read_bool(np, "maxim,low-battery-dac-disable"); > > >+ if (pval) > > >+ mask |= MAX77620_CNFGGLBL1_LBDAC_EN; > > >+ > > >+ pval = of_property_read_bool(np, "maxim,low-battery-shutdown-enable"); > > >+ if (pval) { > > >+ mask |= MAX77620_CNFGGLBL1_MPPLD; > > >+ val |= MAX77620_CNFGGLBL1_MPPLD; > > >+ } > > >+ > > >+ pval = of_property_read_bool(np, "maxim,low-battery-shutdown-disable"); > > >+ if (pval) > > >+ mask |= MAX77620_CNFGGLBL1_MPPLD; > > >+ > > >+ pval = of_property_read_bool(np, "maxim,low-battery-reset-enable"); > > >+ if (pval) { > > >+ mask |= MAX77620_CNFGGLBL1_LBRSTEN; > > >+ val |= MAX77620_CNFGGLBL1_LBRSTEN; > > >+ } > > >+ > > >+ pval = of_property_read_bool(np, "maxim,low-battery-reset-disable"); > > >+ if (pval) > > >+ mask |= MAX77620_CNFGGLBL1_LBRSTEN; > > >+ > > >+ ret = regmap_update_bits(chip->rmap, MAX77620_REG_CNFGGLBL1, mask, val); > > >+ if (ret < 0) > > >+ dev_err(dev, "Reg CNFGGLBL1 update failed: %d\n", ret); > > >+ return ret; > > >+} > > >+ > > > static int max77620_read_es_version(struct max77620_chip *chip) > > > { > > > unsigned int val; > > >@@ -563,7 +614,11 @@ static int max77620_probe(struct i2c_client *client, > > > if (ret < 0) > > > return ret; > > > > > >- ret = devm_mfd_add_devices(chip->dev, PLATFORM_DEVID_NONE, > > >+ ret = max77620_init_low_battery_monitor(chip); > > >+ if (ret < 0) > > >+ return ret; > > >+ > > >+ ret = devm_mfd_add_devices(chip->dev, PLATFORM_DEVID_NONE, > > > mfd_cells, n_mfd_cells, NULL, 0, > > > regmap_irq_get_domain(chip->top_irq_data)); > > > if (ret < 0) { > >
Re: [PATCH v2] iommu/vt-d: Implement dma_[un]map_resource()
Looks good: Reviewed-by: Christoph Hellwig
[PATCH] dell_rbu: stop abusing the DMA API
For some odd reason dell_rbu actually seems to want the physical and not a bus address for the allocated buffer. Lets assume that actually is correct given that it is BIOS-related and that is a good source of insanity. In that case we should not use dma_alloc_coherent with a NULL device to allocate memory, but use GFP_DMA32 to stay under the 32-bit BIOS limit. Signed-off-by: Christoph Hellwig --- drivers/platform/x86/dell_rbu.c | 52 ++--- 1 file changed, 15 insertions(+), 37 deletions(-) diff --git a/drivers/platform/x86/dell_rbu.c b/drivers/platform/x86/dell_rbu.c index ccefa84f7305..fba7d96c1714 100644 --- a/drivers/platform/x86/dell_rbu.c +++ b/drivers/platform/x86/dell_rbu.c @@ -59,7 +59,6 @@ static struct _rbu_data { unsigned long image_update_buffer_size; unsigned long bios_image_size; int image_update_ordernum; - int dma_alloc; spinlock_t lock; unsigned long packet_read_count; unsigned long num_packets; @@ -89,7 +88,6 @@ static struct packet_data packet_data_head; static struct platform_device *rbu_device; static int context; -static dma_addr_t dell_rbu_dmaaddr; static void init_packet_head(void) { @@ -380,12 +378,8 @@ static void img_update_free(void) */ memset(rbu_data.image_update_buffer, 0, rbu_data.image_update_buffer_size); - if (rbu_data.dma_alloc == 1) - dma_free_coherent(NULL, rbu_data.bios_image_size, - rbu_data.image_update_buffer, dell_rbu_dmaaddr); - else - free_pages((unsigned long) rbu_data.image_update_buffer, - rbu_data.image_update_ordernum); + free_pages((unsigned long) rbu_data.image_update_buffer, + rbu_data.image_update_ordernum); /* * Re-initialize the rbu_data variables after a free @@ -394,7 +388,6 @@ static void img_update_free(void) rbu_data.image_update_buffer = NULL; rbu_data.image_update_buffer_size = 0; rbu_data.bios_image_size = 0; - rbu_data.dma_alloc = 0; } /* @@ -410,10 +403,8 @@ static void img_update_free(void) static int img_update_realloc(unsigned long size) { unsigned char *image_update_buffer = NULL; - unsigned long rc; unsigned long img_buf_phys_addr; int ordernum; - int dma_alloc = 0; /* * check if the buffer of sufficient size has been @@ -444,36 +435,23 @@ static int img_update_realloc(unsigned long size) ordernum = get_order(size); image_update_buffer = - (unsigned char *) __get_free_pages(GFP_KERNEL, ordernum); - - img_buf_phys_addr = - (unsigned long) virt_to_phys(image_update_buffer); - - if (img_buf_phys_addr > BIOS_SCAN_LIMIT) { - free_pages((unsigned long) image_update_buffer, ordernum); - ordernum = -1; - image_update_buffer = dma_alloc_coherent(NULL, size, - _rbu_dmaaddr, GFP_KERNEL); - dma_alloc = 1; - } - - spin_lock(_data.lock); - - if (image_update_buffer != NULL) { - rbu_data.image_update_buffer = image_update_buffer; - rbu_data.image_update_buffer_size = size; - rbu_data.bios_image_size = - rbu_data.image_update_buffer_size; - rbu_data.image_update_ordernum = ordernum; - rbu_data.dma_alloc = dma_alloc; - rc = 0; - } else { + (unsigned char *)__get_free_pages(GFP_DMA32, ordernum); + if (!image_update_buffer) { pr_debug("Not enough memory for image update:" "size = %ld\n", size); - rc = -ENOMEM; + return -ENOMEM; } - return rc; + img_buf_phys_addr = (unsigned long)virt_to_phys(image_update_buffer); + if (WARN_ON_ONCE(img_buf_phys_addr > BIOS_SCAN_LIMIT)) + return -EINVAL; /* can't happen per defintion */ + + spin_lock(_data.lock); + rbu_data.image_update_buffer = image_update_buffer; + rbu_data.image_update_buffer_size = size; + rbu_data.bios_image_size = rbu_data.image_update_buffer_size; + rbu_data.image_update_ordernum = ordernum; + return 0; } static ssize_t read_packet_data(char *buffer, loff_t pos, size_t count) -- 2.20.1
Re: [PATCH] mm,memory_hotplug: Fix scan_movable_pages for gigantic hugepages
On Mon 28-01-19 14:56:17, Andrew Morton wrote: [...] > --- > a/mm/memory_hotplug.c~mmmemory_hotplug-fix-scan_movable_pages-for-gigantic-hugepages-fix > +++ a/mm/memory_hotplug.c > @@ -1305,28 +1305,27 @@ int test_pages_in_a_zone(unsigned long s > static unsigned long scan_movable_pages(unsigned long start, unsigned long > end) > { > unsigned long pfn; > - struct page *page; > + > for (pfn = start; pfn < end; pfn++) { > - if (pfn_valid(pfn)) { > - page = pfn_to_page(pfn); > - if (PageLRU(page)) > - return pfn; > - if (__PageMovable(page)) > - return pfn; > - if (PageHuge(page)) { > - struct page *head = compound_head(page); > + struct page *page, *head; > + unsigned long skip; > > - if > (hugepage_migration_supported(page_hstate(head)) && > - page_huge_active(head)) > - return pfn; > - else { > - unsigned long skip; > + if (!pfn_valid(pfn)) > + continue; > + page = pfn_to_page(pfn); > + if (PageLRU(page)) > + return pfn; > + if (__PageMovable(page)) > + return pfn; > > - skip = (1 << compound_order(head)) - > (page - head); > - pfn += skip - 1; > - } > - } > - } > + if (!PageHuge(page)) > + continue; > + head = compound_head(page); > + if (hugepage_migration_supported(page_hstate(head)) && > + page_huge_active(head)) > + return pfn; > + skip = (1 << compound_order(head)) - (page - head); > + pfn += skip - 1; > } > return 0; > } > _ > LGTM -- Michal Hocko SUSE Labs
[PATCH 05/10] soc: mediatek: add subsys-base address transform function
GCE cannot know the register base address, we store the subsys-base address relationship in the device node, and store the relationship by cmdq_register_device function. When the client pass the base address and offset into GCE API, we will get the subsys ID by this API. Signed-off-by: Bibby Hsieh --- drivers/soc/mediatek/mtk-cmdq-helper.c | 17 + include/linux/soc/mediatek/mtk-cmdq.h | 12 2 files changed, 29 insertions(+) diff --git a/drivers/soc/mediatek/mtk-cmdq-helper.c b/drivers/soc/mediatek/mtk-cmdq-helper.c index ff9fef5..6e4b85e 100644 --- a/drivers/soc/mediatek/mtk-cmdq-helper.c +++ b/drivers/soc/mediatek/mtk-cmdq-helper.c @@ -15,6 +15,23 @@ #define CMDQ_EOC_CMD ((u64)((CMDQ_CODE_EOC << CMDQ_OP_CODE_SHIFT)) \ << 32 | CMDQ_EOC_IRQ_EN) +u8 cmdq_subsys_base_to_id(struct cmdq_base *clt_base, u32 base) +{ + u8 i; + + if (!clt_base) + return -EINVAL; + + base = base & 0x; + for (i = 0; i < clt_base->count; i++) { + if (clt_base->subsys[i].base == base) + return clt_base->subsys[i].id; + } + + return -EINVAL; +} +EXPORT_SYMBOL(cmdq_subsys_base_to_id); + static void cmdq_client_timeout(struct timer_list *t) { struct cmdq_client *client = from_timer(client, t, timer); diff --git a/include/linux/soc/mediatek/mtk-cmdq.h b/include/linux/soc/mediatek/mtk-cmdq.h index 4e88999..0c7a6ee 100644 --- a/include/linux/soc/mediatek/mtk-cmdq.h +++ b/include/linux/soc/mediatek/mtk-cmdq.h @@ -15,6 +15,16 @@ struct cmdq_pkt; +struct cmdq_subsys { + u32 base; + u8 id; +}; + +struct cmdq_base { + struct cmdq_subsys subsys[32]; + u8 count; +}; + struct cmdq_client { spinlock_t lock; u32 pkt_cnt; @@ -127,4 +137,6 @@ int cmdq_pkt_flush_async(struct cmdq_pkt *pkt, cmdq_async_flush_cb cb, */ int cmdq_pkt_flush(struct cmdq_pkt *pkt); +u8 cmdq_subsys_base_to_id(struct cmdq_base *clt_base, u32 base); + #endif /* __MTK_CMDQ_H__ */ -- 1.9.1
[PATCH 10/10] soc: mediatek: add polling function
add polling function in cmdq helper functions Signed-off-by: Bibby Hsieh --- drivers/soc/mediatek/mtk-cmdq-helper.c | 24 include/linux/mailbox/mtk-cmdq-mailbox.h | 1 + include/linux/soc/mediatek/mtk-cmdq.h| 15 +++ 3 files changed, 40 insertions(+) diff --git a/drivers/soc/mediatek/mtk-cmdq-helper.c b/drivers/soc/mediatek/mtk-cmdq-helper.c index 34ae712..bc504ff 100644 --- a/drivers/soc/mediatek/mtk-cmdq-helper.c +++ b/drivers/soc/mediatek/mtk-cmdq-helper.c @@ -298,6 +298,30 @@ int cmdq_pkt_clear_event(struct cmdq_pkt *pkt, u16 event) } EXPORT_SYMBOL(cmdq_pkt_clear_event); +int cmdq_pkt_poll(struct cmdq_pkt *pkt, struct cmdq_base *clt_base, + dma_addr_t addr, u32 value, u32 mask) +{ + int err; + const u32 base = (addr >> 32) ? 0 : addr & 0x; + u8 subsys = cmdq_subsys_base_to_id(clt_base, base); + s16 offset = addr & 0x; + + if (mask != 0x) { + err = cmdq_pkt_append_command(pkt, CMDQ_GET_ARG_C(~mask), + CMDQ_GET_ARG_B(~mask), + 0, 0, 0, 0, 0, CMDQ_CODE_MASK); + + if (err != 0) + return err; + } + offset = offset | 0x1; + + return cmdq_pkt_append_command(pkt, CMDQ_GET_ARG_C(value), + CMDQ_GET_ARG_B(value), + offset, subsys, 0, 0, 0, CMDQ_CODE_POLL); +} +EXPORT_SYMBOL(cmdq_pkt_poll); + static int cmdq_pkt_finalize(struct cmdq_pkt *pkt) { int err; diff --git a/include/linux/mailbox/mtk-cmdq-mailbox.h b/include/linux/mailbox/mtk-cmdq-mailbox.h index f21801d..1dfd5ed 100644 --- a/include/linux/mailbox/mtk-cmdq-mailbox.h +++ b/include/linux/mailbox/mtk-cmdq-mailbox.h @@ -46,6 +46,7 @@ enum cmdq_code { CMDQ_CODE_MASK = 0x02, CMDQ_CODE_WRITE = 0x04, + CMDQ_CODE_POLL = 0x08, CMDQ_CODE_JUMP = 0x10, CMDQ_CODE_WFE = 0x20, CMDQ_CODE_EOC = 0x40, diff --git a/include/linux/soc/mediatek/mtk-cmdq.h b/include/linux/soc/mediatek/mtk-cmdq.h index 230bc2b..f6227bf 100644 --- a/include/linux/soc/mediatek/mtk-cmdq.h +++ b/include/linux/soc/mediatek/mtk-cmdq.h @@ -110,6 +110,21 @@ int cmdq_pkt_write_mask(struct cmdq_pkt *pkt, struct cmdq_base *clt_base, int cmdq_pkt_clear_event(struct cmdq_pkt *pkt, u16 event); /** + * cmdq_pkt_poll() - Append polling command to the CMDQ packet, ask GCE to + * execute an instruction that wait for a specified hardware + * register to check for the value. All GCE hardware + * threads will be blocked by this instruction. + * @pkt: the CMDQ packet + * @cmdq_base: the CMDQ sub system code and base address + * @addr: register address + * @value: the specified target register value + * @mask: the specified target register mask + * + * Return: 0 for success; else the error code is returned + */ +int cmdq_pkt_poll(struct cmdq_pkt *pkt, struct cmdq_base *clt_base, + dma_addr_t addr, u32 value, u32 mask); +/** * cmdq_pkt_flush_async() - trigger CMDQ to asynchronously execute the CMDQ * packet and call back at the end of done packet * @pkt: the CMDQ packet -- 1.9.1
[PATCH 04/10] soc: mediatek: clear the event in cmdq initial flow
GCE hardware stored event information in own internal sysram, if the initial value in those sysram is not zero value it will cause a situation that gce can wait the event immediately after client ask gce to wait event but not really trigger the corresponding hardware. In order to make sure that the wait event function is exactly correct, we need to clear the sysram value in cmdq initial flow. Signed-off-by: Bibby Hsieh --- drivers/mailbox/mtk-cmdq-mailbox.c | 5 + include/linux/mailbox/mtk-cmdq-mailbox.h | 2 ++ include/linux/soc/mediatek/mtk-cmdq.h| 3 --- 3 files changed, 7 insertions(+), 3 deletions(-) diff --git a/drivers/mailbox/mtk-cmdq-mailbox.c b/drivers/mailbox/mtk-cmdq-mailbox.c index f6174ca..2b5febd 100644 --- a/drivers/mailbox/mtk-cmdq-mailbox.c +++ b/drivers/mailbox/mtk-cmdq-mailbox.c @@ -33,6 +33,7 @@ #define CMDQ_THR_END_ADDR 0x24 #define CMDQ_THR_WAIT_TOKEN0x30 #define CMDQ_THR_PRIORITY 0x40 +#define CMDQ_SYNC_TOKEN_UPDATE 0x68 #define CMDQ_THR_ACTIVE_SLOT_CYCLES0x3200 #define CMDQ_THR_ENABLED 0x1 @@ -103,8 +104,12 @@ static void cmdq_thread_resume(struct cmdq_thread *thread) static void cmdq_init(struct cmdq *cmdq) { + int i; + WARN_ON(clk_enable(cmdq->clock) < 0); writel(CMDQ_THR_ACTIVE_SLOT_CYCLES, cmdq->base + CMDQ_THR_SLOT_CYCLES); + for (i = 0; i <= CMDQ_MAX_EVENT; i++) + writel(i, cmdq->base + CMDQ_SYNC_TOKEN_UPDATE); clk_disable(cmdq->clock); } diff --git a/include/linux/mailbox/mtk-cmdq-mailbox.h b/include/linux/mailbox/mtk-cmdq-mailbox.h index ccb7342..911475da 100644 --- a/include/linux/mailbox/mtk-cmdq-mailbox.h +++ b/include/linux/mailbox/mtk-cmdq-mailbox.h @@ -19,6 +19,8 @@ #define CMDQ_WFE_UPDATEBIT(31) #define CMDQ_WFE_WAIT BIT(15) #define CMDQ_WFE_WAIT_VALUE0x1 +/** cmdq event maximum */ +#define CMDQ_MAX_EVENT 0x3ff /* * CMDQ_CODE_MASK: diff --git a/include/linux/soc/mediatek/mtk-cmdq.h b/include/linux/soc/mediatek/mtk-cmdq.h index 54ade13..4e88999 100644 --- a/include/linux/soc/mediatek/mtk-cmdq.h +++ b/include/linux/soc/mediatek/mtk-cmdq.h @@ -13,9 +13,6 @@ #define CMDQ_NO_TIMEOUT0xu -/** cmdq event maximum */ -#define CMDQ_MAX_EVENT 0x3ff - struct cmdq_pkt; struct cmdq_client { -- 1.9.1
[PATCH 01/10] soc: mediatek: add mt8183 compatible name
add mt8183 compatible name Signed-off-by: Bibby Hsieh --- drivers/mailbox/mtk-cmdq-mailbox.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/mailbox/mtk-cmdq-mailbox.c b/drivers/mailbox/mtk-cmdq-mailbox.c index 2281178..909eb23 100644 --- a/drivers/mailbox/mtk-cmdq-mailbox.c +++ b/drivers/mailbox/mtk-cmdq-mailbox.c @@ -536,6 +536,7 @@ static int cmdq_probe(struct platform_device *pdev) static const struct of_device_id cmdq_of_ids[] = { {.compatible = "mediatek,mt8173-gce", .data = (void *)16}, + {.compatible = "mediatek,mt8183-gce", .data = (void *)24}, {} }; -- 1.9.1
[PATCH 08/10] soc: mediatek: add packet encoder function
Implement a function can encode the GCE instructions Signed-off-by: Bibby Hsieh --- drivers/soc/mediatek/mtk-cmdq-helper.c | 102 --- include/linux/mailbox/mtk-cmdq-mailbox.h | 2 + include/linux/soc/mediatek/mtk-cmdq.h| 14 ++--- 3 files changed, 76 insertions(+), 42 deletions(-) diff --git a/drivers/soc/mediatek/mtk-cmdq-helper.c b/drivers/soc/mediatek/mtk-cmdq-helper.c index 16c0393..923a815 100644 --- a/drivers/soc/mediatek/mtk-cmdq-helper.c +++ b/drivers/soc/mediatek/mtk-cmdq-helper.c @@ -9,11 +9,43 @@ #include #include -#define CMDQ_ARG_A_WRITE_MASK 0x +#define CMDQ_GET_ARG_B(arg)(((arg) & GENMASK(31, 16)) >> 16) +#define CMDQ_GET_ARG_C(arg)((arg) & GENMASK(15, 0)) #define CMDQ_WRITE_ENABLE_MASK BIT(0) #define CMDQ_EOC_IRQ_ENBIT(0) #define CMDQ_EOC_CMD ((u64)((CMDQ_CODE_EOC << CMDQ_OP_CODE_SHIFT)) \ << 32 | CMDQ_EOC_IRQ_EN) +#define CMDQ_IMMEDIATE_VALUE 0 +#define CMDQ_REG_TYPE 1 + +struct cmdq_instruction { + s16 arg_c:16; + s16 arg_b:16; + s16 arg_a:16; + u8 s_op:5; + u8 arg_c_type:1; + u8 arg_b_type:1; + u8 arg_a_type:1; + u8 op:8; +}; + +static void cmdq_pkt_instr_encoder(struct cmdq_pkt *pkt, s16 arg_c, s16 arg_b, + s16 arg_a, u8 s_op, u8 arg_c_type, + u8 arg_b_type, u8 arg_a_type, u8 op) +{ + struct cmdq_instruction *cmdq_inst; + + cmdq_inst = pkt->va_base + pkt->cmd_buf_size; + cmdq_inst->op = op; + cmdq_inst->arg_a_type = arg_a_type; + cmdq_inst->arg_b_type = arg_b_type; + cmdq_inst->arg_c_type = arg_c_type; + cmdq_inst->s_op = s_op; + cmdq_inst->arg_a = arg_a; + cmdq_inst->arg_b = arg_b; + cmdq_inst->arg_c = arg_c; + pkt->cmd_buf_size += CMDQ_INST_SIZE; +} u8 cmdq_subsys_base_to_id(struct cmdq_base *clt_base, u32 base) { @@ -180,10 +212,11 @@ void cmdq_pkt_destroy(struct cmdq_pkt *pkt) } EXPORT_SYMBOL(cmdq_pkt_destroy); -static int cmdq_pkt_append_command(struct cmdq_pkt *pkt, enum cmdq_code code, - u32 arg_a, u32 arg_b) +static int cmdq_pkt_append_command(struct cmdq_pkt *pkt, s16 arg_c, s16 arg_b, + s16 arg_a, u8 s_op, u8 arg_c_type, + u8 arg_b_type, u8 arg_a_type, + enum cmdq_code code) { - u64 *cmd_ptr; if (unlikely(pkt->cmd_buf_size + CMDQ_INST_SIZE > pkt->buf_size)) { /* @@ -199,65 +232,59 @@ static int cmdq_pkt_append_command(struct cmdq_pkt *pkt, enum cmdq_code code, __func__, (u32)pkt->buf_size); return -ENOMEM; } - cmd_ptr = pkt->va_base + pkt->cmd_buf_size; - (*cmd_ptr) = (u64)((code << CMDQ_OP_CODE_SHIFT) | arg_a) << 32 | arg_b; - pkt->cmd_buf_size += CMDQ_INST_SIZE; + cmdq_pkt_instr_encoder(pkt, arg_c, arg_b, arg_a, s_op, arg_c_type, + arg_b_type, arg_a_type, code); return 0; } -int cmdq_pkt_write(struct cmdq_pkt *pkt, u32 value, u32 subsys, u32 offset) +int cmdq_pkt_write(struct cmdq_pkt *pkt, u8 subsys, u16 offset, u32 value) { - u32 arg_a = (offset & CMDQ_ARG_A_WRITE_MASK) | - (subsys << CMDQ_SUBSYS_SHIFT); - - return cmdq_pkt_append_command(pkt, CMDQ_CODE_WRITE, arg_a, value); + return cmdq_pkt_append_command(pkt, CMDQ_GET_ARG_C(value), + CMDQ_GET_ARG_B(value), offset, subsys, + CMDQ_IMMEDIATE_VALUE, + CMDQ_IMMEDIATE_VALUE, + CMDQ_IMMEDIATE_VALUE, CMDQ_CODE_WRITE); } EXPORT_SYMBOL(cmdq_pkt_write); -int cmdq_pkt_write_mask(struct cmdq_pkt *pkt, u32 value, - u32 subsys, u32 offset, u32 mask) +int cmdq_pkt_write_mask(struct cmdq_pkt *pkt, u8 subsys, u16 offset, + u32 value, u32 mask) { u32 offset_mask = offset; int err = 0; if (mask != 0x) { - err = cmdq_pkt_append_command(pkt, CMDQ_CODE_MASK, 0, ~mask); + err = cmdq_pkt_append_command(pkt, CMDQ_GET_ARG_C(~mask), + CMDQ_GET_ARG_B(~mask), 0, 0, 0, 0, + 0, CMDQ_CODE_MASK); offset_mask |= CMDQ_WRITE_ENABLE_MASK; } - err |= cmdq_pkt_write(pkt, value, subsys, offset_mask); + err |= cmdq_pkt_write(pkt, subsys, offset_mask, value); return err; } EXPORT_SYMBOL(cmdq_pkt_write_mask); -int cmdq_pkt_wfe(struct cmdq_pkt *pkt, u32 event) +int cmdq_pkt_wfe(struct cmdq_pkt *pkt, u16 event) { - u32 arg_b; - if (event >= CMDQ_MAX_EVENT) return -EINVAL; - /* -* WFE arg_b -*
[PATCH 07/10] soc: mediatek: add cmdq_dev_get_event function
When client ask gce to clear or wait for event, client need to pass event number to the API. We suggest client store the event information in device node, so we provide an API for client parse the event property. Signed-off-by: Bibby Hsieh --- drivers/soc/mediatek/mtk-cmdq-helper.c | 29 + include/linux/soc/mediatek/mtk-cmdq.h | 1 + 2 files changed, 30 insertions(+) diff --git a/drivers/soc/mediatek/mtk-cmdq-helper.c b/drivers/soc/mediatek/mtk-cmdq-helper.c index 6ad997f..16c0393 100644 --- a/drivers/soc/mediatek/mtk-cmdq-helper.c +++ b/drivers/soc/mediatek/mtk-cmdq-helper.c @@ -56,6 +56,35 @@ struct cmdq_base *cmdq_register_device(struct device *dev) } EXPORT_SYMBOL(cmdq_register_device); +s32 cmdq_dev_get_event(struct device *dev, const char *name) +{ + s32 index = 0; + struct of_phandle_args spec; + s32 result; + + if (!dev) + return -EINVAL; + + index = of_property_match_string(dev->of_node, "gce-event-names", name); + if (index < 0) { + dev_err(dev, "no gce-event-names property or no such event:%s", + name); + return index; + } + + if (of_parse_phandle_with_args(dev->of_node, "gce-events", + "#gce-event-cells", index, )) { + dev_err(dev, "can't parse gce-events property"); + return -ENODEV; + } + + result = spec.args[0]; + of_node_put(spec.np); + + return result; +} +EXPORT_SYMBOL(cmdq_dev_get_event); + static void cmdq_client_timeout(struct timer_list *t) { struct cmdq_client *client = from_timer(client, t, timer); diff --git a/include/linux/soc/mediatek/mtk-cmdq.h b/include/linux/soc/mediatek/mtk-cmdq.h index a1f5eb6..e5b0a98 100644 --- a/include/linux/soc/mediatek/mtk-cmdq.h +++ b/include/linux/soc/mediatek/mtk-cmdq.h @@ -139,5 +139,6 @@ int cmdq_pkt_flush_async(struct cmdq_pkt *pkt, cmdq_async_flush_cb cb, u8 cmdq_subsys_base_to_id(struct cmdq_base *clt_base, u32 base); struct cmdq_base *cmdq_register_device(struct device *dev); +s32 cmdq_dev_get_event(struct device *dev, const char *name); #endif /* __MTK_CMDQ_H__ */ -- 1.9.1
[PATCH 03/10] soc: mediatek: move the CMDQ_IRQ_MASK into cmdq driver data
The interrupt mask and thread number has positive correlation, so we move the CMDQ_IRQ_MASK into cmdq driver data and calculate it by thread number. Signed-off-by: Bibby Hsieh --- drivers/mailbox/mtk-cmdq-mailbox.c | 12 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/drivers/mailbox/mtk-cmdq-mailbox.c b/drivers/mailbox/mtk-cmdq-mailbox.c index 909eb23..f6174ca 100644 --- a/drivers/mailbox/mtk-cmdq-mailbox.c +++ b/drivers/mailbox/mtk-cmdq-mailbox.c @@ -17,7 +17,6 @@ #include #define CMDQ_OP_CODE_MASK (0xff << CMDQ_OP_CODE_SHIFT) -#define CMDQ_IRQ_MASK 0x #define CMDQ_NUM_CMD(t)(t->cmd_buf_size / CMDQ_INST_SIZE) #define CMDQ_CURR_IRQ_STATUS 0x10 @@ -71,6 +70,7 @@ struct cmdq { void __iomem*base; u32 irq; u32 thread_nr; + u32 irq_mask; struct cmdq_thread *thread; struct clk *clock; boolsuspended; @@ -284,11 +284,11 @@ static irqreturn_t cmdq_irq_handler(int irq, void *dev) unsigned long irq_status, flags = 0L; int bit; - irq_status = readl(cmdq->base + CMDQ_CURR_IRQ_STATUS) & CMDQ_IRQ_MASK; - if (!(irq_status ^ CMDQ_IRQ_MASK)) + irq_status = readl(cmdq->base + CMDQ_CURR_IRQ_STATUS) & cmdq->irq_mask; + if (!(irq_status ^ cmdq->irq_mask)) return IRQ_NONE; - for_each_clear_bit(bit, _status, fls(CMDQ_IRQ_MASK)) { + for_each_clear_bit(bit, _status, fls(cmdq->irq_mask)) { struct cmdq_thread *thread = >thread[bit]; spin_lock_irqsave(>chan->lock, flags); @@ -472,6 +472,9 @@ static int cmdq_probe(struct platform_device *pdev) dev_err(dev, "failed to get irq\n"); return -EINVAL; } + + cmdq->thread_nr = (u32)(unsigned long)of_device_get_match_data(dev); + cmdq->irq_mask = GENMASK(cmdq->thread_nr - 1, 0); err = devm_request_irq(dev, cmdq->irq, cmdq_irq_handler, IRQF_SHARED, "mtk_cmdq", cmdq); if (err < 0) { @@ -489,6 +492,7 @@ static int cmdq_probe(struct platform_device *pdev) } cmdq->thread_nr = (u32)(unsigned long)of_device_get_match_data(dev); + cmdq->irq_mask = GENMASK(cmdq->thread_nr - 1, 0); cmdq->mbox.dev = dev; cmdq->mbox.chans = devm_kcalloc(dev, cmdq->thread_nr, sizeof(*cmdq->mbox.chans), GFP_KERNEL); -- 1.9.1
[PATCH 06/10] soc: mediatek: add register device function
GCE cannot know the register base address, we store the subsys-base address relationship in the device node, and store the relationship by cmdq_register_device function. Signed-off-by: Bibby Hsieh --- drivers/soc/mediatek/mtk-cmdq-helper.c | 24 include/linux/soc/mediatek/mtk-cmdq.h | 1 + 2 files changed, 25 insertions(+) diff --git a/drivers/soc/mediatek/mtk-cmdq-helper.c b/drivers/soc/mediatek/mtk-cmdq-helper.c index 6e4b85e..6ad997f 100644 --- a/drivers/soc/mediatek/mtk-cmdq-helper.c +++ b/drivers/soc/mediatek/mtk-cmdq-helper.c @@ -32,6 +32,30 @@ u8 cmdq_subsys_base_to_id(struct cmdq_base *clt_base, u32 base) } EXPORT_SYMBOL(cmdq_subsys_base_to_id); +struct cmdq_base *cmdq_register_device(struct device *dev) +{ + struct cmdq_base *clt_base; + struct of_phandle_args spec; + u32 idx; + + clt_base = devm_kzalloc(dev, sizeof(*clt_base), GFP_KERNEL); + if (!clt_base) + return NULL; + + /* parse subsys */ + for (idx = 0; idx < ARRAY_SIZE(clt_base->subsys); idx++) { + if (of_parse_phandle_with_args(dev->of_node, "gce-subsys", + "#gce-subsys-cells", idx, )) + break; + clt_base->subsys[idx].base = spec.args[0]; + clt_base->subsys[idx].id = spec.args[1]; + } + clt_base->count = idx; + + return clt_base; +} +EXPORT_SYMBOL(cmdq_register_device); + static void cmdq_client_timeout(struct timer_list *t) { struct cmdq_client *client = from_timer(client, t, timer); diff --git a/include/linux/soc/mediatek/mtk-cmdq.h b/include/linux/soc/mediatek/mtk-cmdq.h index 0c7a6ee..a1f5eb6 100644 --- a/include/linux/soc/mediatek/mtk-cmdq.h +++ b/include/linux/soc/mediatek/mtk-cmdq.h @@ -138,5 +138,6 @@ int cmdq_pkt_flush_async(struct cmdq_pkt *pkt, cmdq_async_flush_cb cb, int cmdq_pkt_flush(struct cmdq_pkt *pkt); u8 cmdq_subsys_base_to_id(struct cmdq_base *clt_base, u32 base); +struct cmdq_base *cmdq_register_device(struct device *dev); #endif /* __MTK_CMDQ_H__ */ -- 1.9.1
[PATCH 00/10] support gce on mt8183 platform
MTK will support gce function on mt8183 platform. soc: mediatek: add mt8183 compatible name dt-binding: gce: add gce header file for mt8183 Besides above patches, we refine gce driver on those patches. soc: mediatek: move the CMDQ_IRQ_MASK into cmdq driver data soc: mediatek: clear the event in cmdq initial flow In ordet to enhance the convenience of gce usage, we add new helper functions and refine the method of instruction combining. soc: mediatek: add subsys-base address transform function soc: mediatek: add register device function soc: mediatek: add cmdq_dev_get_event function soc: mediatek: add packet encoder function soc: mediatek: change the argument of write and write_mask API soc: mediatek: add polling function Bibby Hsieh (10): soc: mediatek: add mt8183 compatible name dt-binding: gce: add gce header file for mt8183 soc: mediatek: move the CMDQ_IRQ_MASK into cmdq driver data soc: mediatek: clear the event in cmdq initial flow soc: mediatek: add subsys-base address transform function soc: mediatek: add register device function soc: mediatek: add cmdq_dev_get_event function soc: mediatek: add packet encoder function soc: mediatek: change the argument of write and write_mask API soc: mediatek: add polling function .../devicetree/bindings/mailbox/mtk-gce.txt| 6 +- drivers/mailbox/mtk-cmdq-mailbox.c | 18 +- drivers/soc/mediatek/mtk-cmdq-helper.c | 212 + include/dt-bindings/gce/mt8183-gce.h | 177 + include/linux/mailbox/mtk-cmdq-mailbox.h | 5 + include/linux/soc/mediatek/mtk-cmdq.h | 52 +++-- 6 files changed, 412 insertions(+), 58 deletions(-) create mode 100644 include/dt-bindings/gce/mt8183-gce.h -- 1.9.1
[PATCH 09/10] soc: mediatek: change the argument of write and write_mask API
In order to enhance the convienience of client usage, we change the input argument from subsys and offset to struct cmdq_base and dma_addr_t. Signed-off-by: Bibby Hsieh --- drivers/soc/mediatek/mtk-cmdq-helper.c | 24 +--- include/linux/soc/mediatek/mtk-cmdq.h | 16 2 files changed, 25 insertions(+), 15 deletions(-) diff --git a/drivers/soc/mediatek/mtk-cmdq-helper.c b/drivers/soc/mediatek/mtk-cmdq-helper.c index 923a815..34ae712 100644 --- a/drivers/soc/mediatek/mtk-cmdq-helper.c +++ b/drivers/soc/mediatek/mtk-cmdq-helper.c @@ -238,8 +238,13 @@ static int cmdq_pkt_append_command(struct cmdq_pkt *pkt, s16 arg_c, s16 arg_b, return 0; } -int cmdq_pkt_write(struct cmdq_pkt *pkt, u8 subsys, u16 offset, u32 value) +int cmdq_pkt_write(struct cmdq_pkt *pkt, struct cmdq_base *clt_base, + dma_addr_t addr, u32 value) { + const u32 base = (addr >> 32) ? 0 : addr & 0x; + u8 subsys = cmdq_subsys_base_to_id(clt_base, base); + s16 offset = addr & 0x; + return cmdq_pkt_append_command(pkt, CMDQ_GET_ARG_C(value), CMDQ_GET_ARG_B(value), offset, subsys, CMDQ_IMMEDIATE_VALUE, @@ -248,21 +253,26 @@ int cmdq_pkt_write(struct cmdq_pkt *pkt, u8 subsys, u16 offset, u32 value) } EXPORT_SYMBOL(cmdq_pkt_write); -int cmdq_pkt_write_mask(struct cmdq_pkt *pkt, u8 subsys, u16 offset, - u32 value, u32 mask) +int cmdq_pkt_write_mask(struct cmdq_pkt *pkt, struct cmdq_base *clt_base, + dma_addr_t addr, u32 value, u32 mask) { - u32 offset_mask = offset; + const u32 base = (addr >> 32) ? 0 : addr & 0x; + u8 subsys = cmdq_subsys_base_to_id(clt_base, base); + s16 offset = addr & 0x; int err = 0; if (mask != 0x) { err = cmdq_pkt_append_command(pkt, CMDQ_GET_ARG_C(~mask), CMDQ_GET_ARG_B(~mask), 0, 0, 0, 0, 0, CMDQ_CODE_MASK); - offset_mask |= CMDQ_WRITE_ENABLE_MASK; + offset |= CMDQ_WRITE_ENABLE_MASK; } - err |= cmdq_pkt_write(pkt, subsys, offset_mask, value); - return err; + return cmdq_pkt_append_command(pkt, CMDQ_GET_ARG_C(value), + CMDQ_GET_ARG_B(value), offset, subsys, + CMDQ_IMMEDIATE_VALUE, + CMDQ_IMMEDIATE_VALUE, + CMDQ_IMMEDIATE_VALUE, CMDQ_CODE_WRITE); } EXPORT_SYMBOL(cmdq_pkt_write_mask); diff --git a/include/linux/soc/mediatek/mtk-cmdq.h b/include/linux/soc/mediatek/mtk-cmdq.h index e4d1876..230bc2b 100644 --- a/include/linux/soc/mediatek/mtk-cmdq.h +++ b/include/linux/soc/mediatek/mtk-cmdq.h @@ -70,26 +70,26 @@ struct cmdq_client *cmdq_mbox_create(struct device *dev, int index, /** * cmdq_pkt_write() - append write command to the CMDQ packet * @pkt: the CMDQ packet - * @subsys:the CMDQ sub system code - * @offset:register offset from CMDQ sub system + * @cmdq_base: the CMDQ sub system code and base address + * @addr: register address * @value: the specified target register value * * Return: 0 for success; else the error code is returned */ -int cmdq_pkt_write(struct cmdq_pkt *pkt, u8 subsys, u16 offset, u32 value); - +int cmdq_pkt_write(struct cmdq_pkt *pkt, struct cmdq_base *clt_base, + dma_addr_t addr, u32 value); /** * cmdq_pkt_write_mask() - append write command with mask to the CMDQ packet * @pkt: the CMDQ packet - * @subsys:the CMDQ sub system code - * @offset:register offset from CMDQ sub system + * @cmdq_base: the CMDQ sub system code and base address + * @addr: register address * @value: the specified target register value * @mask: the specified target register mask * * Return: 0 for success; else the error code is returned */ -int cmdq_pkt_write_mask(struct cmdq_pkt *pkt, u8 subsys, u16 offset, - u32 value, u32 mask); +int cmdq_pkt_write_mask(struct cmdq_pkt *pkt, struct cmdq_base *clt_base, + dma_addr_t addr, u32 value, u32 mask); /** * cmdq_pkt_wfe() - append wait for event command to the CMDQ packet -- 1.9.1
[PATCH 02/10] dt-binding: gce: add gce header file for mt8183
Add documentation for the mt8183 gce. Add gce header file defined the gce hardware event, subsys number and constant for mt8183. Signed-off-by: Bibby Hsieh --- .../devicetree/bindings/mailbox/mtk-gce.txt| 6 +- include/dt-bindings/gce/mt8183-gce.h | 177 + 2 files changed, 180 insertions(+), 3 deletions(-) create mode 100644 include/dt-bindings/gce/mt8183-gce.h diff --git a/Documentation/devicetree/bindings/mailbox/mtk-gce.txt b/Documentation/devicetree/bindings/mailbox/mtk-gce.txt index 7d72b21..9c0d982 100644 --- a/Documentation/devicetree/bindings/mailbox/mtk-gce.txt +++ b/Documentation/devicetree/bindings/mailbox/mtk-gce.txt @@ -9,7 +9,7 @@ CMDQ driver uses mailbox framework for communication. Please refer to mailbox.txt for generic information about mailbox device-tree bindings. Required properties: -- compatible: Must be "mediatek,mt8173-gce" +- compatible: can be "mediatek,mt8173-gce" or "mediatek,mt8183-gce" - reg: Address range of the GCE unit - interrupts: The interrupt signal from the GCE block - clock: Clocks according to the common clock binding @@ -28,8 +28,8 @@ Required properties for a client device: - mediatek,gce-subsys: u32, specify the sub-system id which is corresponding to the register address. -Some vaules of properties are defined in 'dt-bindings/gce/mt8173-gce.h'. Such as -sub-system ids, thread priority, event ids. +Some vaules of properties are defined in 'dt-bindings/gce/mt8173-gce.h' +or 'dt-binding/gce/mt8183-gce.h'. Such as sub-system ids, thread priority, event ids. Example: diff --git a/include/dt-bindings/gce/mt8183-gce.h b/include/dt-bindings/gce/mt8183-gce.h new file mode 100644 index 000..aeb9515 --- /dev/null +++ b/include/dt-bindings/gce/mt8183-gce.h @@ -0,0 +1,177 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) 2019 MediaTek Inc. + * Author: Bibby Hsieh + * + */ + +#ifndef _DT_BINDINGS_GCE_MT8183_H +#define _DT_BINDINGS_GCE_MT8183_H + +#define CMDQ_NO_TIMEOUT0x + +#define CMDQ_THR_MAX_COUNT 24 + +/* GCE HW thread priority */ +#define CMDQ_THR_PRIO_LOWEST 0 +#define CMDQ_THR_PRIO_HIGHEST 1 + +/* GCE SUBSYS */ +#define SUBSYS_13000 +#define SUBSYS_14001 +#define SUBSYS_14012 +#define SUBSYS_14023 +#define SUBSYS_15024 +#define SUBSYS_18805 +#define SUBSYS_18816 +#define SUBSYS_18827 +#define SUBSYS_18838 +#define SUBSYS_18849 +#define SUBSYS_100010 +#define SUBSYS_100111 +#define SUBSYS_100212 +#define SUBSYS_100313 +#define SUBSYS_100414 +#define SUBSYS_100515 +#define SUBSYS_102016 +#define SUBSYS_102817 +#define SUBSYS_170018 +#define SUBSYS_170119 +#define SUBSYS_170220 +#define SUBSYS_170321 +#define SUBSYS_180022 +#define SUBSYS_180123 +#define SUBSYS_180224 +#define SUBSYS_180425 +#define SUBSYS_180526 +#define SUBSYS_180827 +#define SUBSYS_180a28 +#define SUBSYS_180b29 + +#define CMDQ_EVENT_DISP_RDMA0_SOF 0 +#define CMDQ_EVENT_DISP_RDMA1_SOF 1 +#define CMDQ_EVENT_MDP_RDMA0_SOF 2 +#define CMDQ_EVENT_MDP_RSZ0_SOF 4 +#define CMDQ_EVENT_MDP_RSZ1_SOF 5 +#define CMDQ_EVENT_MDP_TDSHP_SOF 6 +#define CMDQ_EVENT_MDP_WROT0_SOF 7 +#define CMDQ_EVENT_MDP_WDMA0_SOF 8 +#define CMDQ_EVENT_DISP_OVL0_SOF 9 +#define CMDQ_EVENT_DISP_OVL0_2L_SOF10 +#define CMDQ_EVENT_DISP_OVL1_2L_SOF11 +#define CMDQ_EVENT_DISP_WDMA0_SOF 12 +#define CMDQ_EVENT_DISP_COLOR0_SOF 13 +#define CMDQ_EVENT_DISP_CCORR0_SOF 14 +#define CMDQ_EVENT_DISP_AAL0_SOF 15 +#define CMDQ_EVENT_DISP_GAMMA0_SOF 16 +#define CMDQ_EVENT_DISP_DITHER0_SOF17 +#define CMDQ_EVENT_DISP_PWM0_SOF 18 +#define CMDQ_EVENT_DISP_DSI0_SOF 19 +#define CMDQ_EVENT_DISP_DPI0_SOF
Re: [PATCH 02/11] btrfs: rename workspaces_list to workspace_manager
On 28.01.19 г. 23:24 ч., Dennis Zhou wrote: > This is in preparation for zstd compression levels. As each level will > require different sized workspaces, workspaces_list is no longer a > really fitting name. > > Signed-off-by: Dennis Zhou Reviewed-by: Nikolay Borisov > --- > fs/btrfs/compression.c | 46 +- > 1 file changed, 23 insertions(+), 23 deletions(-) > > diff --git a/fs/btrfs/compression.c b/fs/btrfs/compression.c > index 586f95ac0aea..aced261984e2 100644 > --- a/fs/btrfs/compression.c > +++ b/fs/btrfs/compression.c > @@ -769,7 +769,7 @@ static struct list_head *alloc_heuristic_ws(void) > return ERR_PTR(-ENOMEM); > } > > -struct workspaces_list { > +struct workspace_manager { > struct list_head idle_ws; > spinlock_t ws_lock; > /* Number of free workspaces */ > @@ -780,9 +780,9 @@ struct workspaces_list { > wait_queue_head_t ws_wait; > }; > > -static struct workspaces_list btrfs_comp_ws[BTRFS_COMPRESS_TYPES]; > +static struct workspace_manager wsm[BTRFS_COMPRESS_TYPES]; > > -static struct workspaces_list btrfs_heuristic_ws; > +static struct workspace_manager btrfs_heuristic_ws; > > static const struct btrfs_compress_op * const btrfs_compress_op[] = { > _zlib_compress, > @@ -811,10 +811,10 @@ void __init btrfs_init_compress(void) > } > > for (i = 0; i < BTRFS_COMPRESS_TYPES; i++) { > - INIT_LIST_HEAD(_comp_ws[i].idle_ws); > - spin_lock_init(_comp_ws[i].ws_lock); > - atomic_set(_comp_ws[i].total_ws, 0); > - init_waitqueue_head(_comp_ws[i].ws_wait); > + INIT_LIST_HEAD([i].idle_ws); > + spin_lock_init([i].ws_lock); > + atomic_set([i].total_ws, 0); > + init_waitqueue_head([i].ws_wait); > > /* >* Preallocate one workspace for each compression type so > @@ -824,9 +824,9 @@ void __init btrfs_init_compress(void) > if (IS_ERR(workspace)) { > pr_warn("BTRFS: cannot preallocate compression > workspace, will try later\n"); > } else { > - atomic_set(_comp_ws[i].total_ws, 1); > - btrfs_comp_ws[i].free_ws = 1; > - list_add(workspace, _comp_ws[i].idle_ws); > + atomic_set([i].total_ws, 1); > + wsm[i].free_ws = 1; > + list_add(workspace, [i].idle_ws); > } > } > } > @@ -856,11 +856,11 @@ static struct list_head *__find_workspace(int type, > bool heuristic) > ws_wait = _heuristic_ws.ws_wait; > free_ws = _heuristic_ws.free_ws; > } else { > - idle_ws = _comp_ws[idx].idle_ws; > - ws_lock = _comp_ws[idx].ws_lock; > - total_ws = _comp_ws[idx].total_ws; > - ws_wait = _comp_ws[idx].ws_wait; > - free_ws = _comp_ws[idx].free_ws; > + idle_ws = [idx].idle_ws; > + ws_lock = [idx].ws_lock; > + total_ws = [idx].total_ws; > + ws_wait = [idx].ws_wait; > + free_ws = [idx].free_ws; > } > > again: > @@ -952,11 +952,11 @@ static void __free_workspace(int type, struct list_head > *workspace, > ws_wait = _heuristic_ws.ws_wait; > free_ws = _heuristic_ws.free_ws; > } else { > - idle_ws = _comp_ws[idx].idle_ws; > - ws_lock = _comp_ws[idx].ws_lock; > - total_ws = _comp_ws[idx].total_ws; > - ws_wait = _comp_ws[idx].ws_wait; > - free_ws = _comp_ws[idx].free_ws; > + idle_ws = [idx].idle_ws; > + ws_lock = [idx].ws_lock; > + total_ws = [idx].total_ws; > + ws_wait = [idx].ws_wait; > + free_ws = [idx].free_ws; > } > > spin_lock(ws_lock); > @@ -998,11 +998,11 @@ static void free_workspaces(void) > } > > for (i = 0; i < BTRFS_COMPRESS_TYPES; i++) { > - while (!list_empty(_comp_ws[i].idle_ws)) { > - workspace = btrfs_comp_ws[i].idle_ws.next; > + while (!list_empty([i].idle_ws)) { > + workspace = wsm[i].idle_ws.next; > list_del(workspace); > btrfs_compress_op[i]->free_workspace(workspace); > - atomic_dec(_comp_ws[i].total_ws); > + atomic_dec([i].total_ws); > } > } > } >
Re: [PATCH 01/11] btrfs: add macros for compression type and level
On 28.01.19 г. 23:24 ч., Dennis Zhou wrote: > It is very easy to miss places that rely on a certain bitshifting for > decyphering the type_level overloading. Make macros handle this instead. > > Signed-off-by: Dennis Zhou Reviewed-by: Nikolay Borisov
Re: linux-next: build warning after merge of the spi tree
On 29.01.19 07:57, Yogesh Narayan Gaur wrote: > Hi, > >> -Original Message- >> From: Stephen Rothwell [mailto:s...@canb.auug.org.au] >> Sent: Tuesday, January 29, 2019 7:33 AM >> To: Mark Brown >> Cc: Linux Next Mailing List ; Linux Kernel >> Mailing >> List ; Yogesh Narayan Gaur >> ; Frieder Schrempf >> ; Boris Brezillon ; >> Ashish Kumar >> Subject: linux-next: build warning after merge of the spi tree >> >> Hi all, >> >> After merging the spi tree, today's linux-next build (KCONFIG_NAME) produced >> this warning: >> >> WARNING: modpost: missing MODULE_LICENSE() in drivers/spi/spi-nxp-fspi.o >> see include/linux/module.h for more information >> > Can someone help in pointing out that why above warning message is coming for > mentioned commit. > Below MODULE_LICENSE string is present in the above mentioned file, > drivers/spi/spi-nxp-fspi.c. > MODULE_LICENSE("GPL v2"); No, it is not present. Look at your patches [1] or at spi-next [2]. MODULE_LICENSE is definitely missing. In patchwork the missing line was appended to the commit message instead of the actual patch for some reason. [1] https://patchwork.kernel.org/patch/10764347/ [2] https://git.kernel.org/pub/scm/linux/kernel/git/broonie/spi.git/commit/?h=for-next=a5356aef6a907c2e2aed0caaa2b88b6021394471
Re: [PATCH] s390/jump_label: Correct asm contraint
On 1/23/19 5:24 AM, Heiko Carstens wrote: On Wed, Jan 23, 2019 at 01:55:13PM +0100, Laura Abbott wrote: There's a build failure with gcc9: ./arch/s390/include/asm/jump_label.h: Assembler messages: ./arch/s390/include/asm/jump_label.h:23: Error: bad expression ./arch/s390/include/asm/jump_label.h:23: Error: junk at end of line, first unrecognized character is `r' make[1]: *** [scripts/Makefile.build:277: init/main.o] Error 1 According to the toolchain people, the actual issue is the use of "X" constraint which is too permissive. Switch to using "i" instead. Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1668703 Signed-off-by: Laura Abbott --- arch/s390/include/asm/jump_label.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/s390/include/asm/jump_label.h b/arch/s390/include/asm/jump_label.h index e2d3e6c43395..41dabfd8518d 100644 --- a/arch/s390/include/asm/jump_label.h +++ b/arch/s390/include/asm/jump_label.h @@ -22,7 +22,7 @@ static inline bool arch_static_branch(struct static_key *key, bool branch) ".long 0b-.,%l[label]-.\n" ".quad %0-.\n" ".popsection\n" - : : "X" (&((char *)key)[branch]) : : label); + : : "i" (&((char *)key)[branch]) : : label); return false; label: return true; Hmmm, this works only for the kernel image, but not for modules, which we compile with "-fPIC", which again doesn't work as described in the referenced bugzilla: In file included from ././include/linux/compiler_types.h:68, from : ./arch/s390/include/asm/jump_label.h: In function 'kvm_vcpu_ioctl': ./include/linux/compiler-gcc.h:124:38: warning: asm operand 0 probably doesn't match constraints #define asm_volatile_goto(x...) do { asm goto(x); asm (""); } while (0) ^~~ ./arch/s390/include/asm/jump_label.h:19:2: note: in expansion of macro 'asm_volatile_goto' asm_volatile_goto("0: brcl 0,"__stringify(JUMP_LABEL_NOP_OFFSET)"\n" ^ ./include/linux/compiler-gcc.h:124:38: error: impossible constraint in 'asm' #define asm_volatile_goto(x...) do { asm goto(x); asm (""); } while (0) ^~~ ./arch/s390/include/asm/jump_label.h:19:2: note: in expansion of macro 'asm_volatile_goto' asm_volatile_goto("0: brcl 0,"__stringify(JUMP_LABEL_NOP_OFFSET)"\n" Andreas, Ilya, any idea how to fix this? I've had to turn off s390 in Fedora until this gets fixed :(
Re: [PATCH 11/11] btrfs: add zstd compression level support
On 28.01.19 г. 23:24 ч., Dennis Zhou wrote: > Zstd compression requires different amounts of memory for each level of > compression. The prior patches implemented indirection to allow for each > compression type to manage their workspaces independently. This patch > uses this indirection to implement compression level support for zstd. > > As mentioned above, a requirement that differs zstd from zlib is that > higher levels of compression require more memory. To manage this, each > compression level has its own queue of workspaces. A global LRU is used > to help with reclaim. To guarantee forward progress, a max level > workspace is preallocated and hidden from the LRU. > > When getting a workspace, it uses a bitmap to identify the levels that > are populated and scans up. If it finds a workspace that is greater than > it, it uses it, but does not update the last_used time and the > corresponding place in the LRU. This provides a mechanism to decrease > memory utilization as we only keep around workspaces that are sized > appropriately for the in use compression levels. > > By knowing which compression levels have available workspaces, we can > recycle rather than always create new workspaces as well as take > advantage of the preallocated max level for forward progress. If we hit > memory pressure, we sleep on the max level workspace. We continue to > rescan in case we can use a smaller workspace, but eventually should be > able to obtain the max level workspace or allocate one again should > memory pressure subside. The memory requirement for decompression is the > same as level 1, and therefore can use any of available workspace. > > The number of workspaces is bound by an upper limit of the workqueue's > limit which currently is 2 (percpu limit). Second, a reclaim timer is > used to free inactive/improperly sized workspaces. The reclaim timer is > set to 67s to avoid colliding with transaction commit (every 30s) and > attempts to reclaim any unused workspace older than 45s. > > Repeating the experiment from v2 [1], the Silesia corpus was copied to a > btrfs filesystem 10 times and then read back after dropping the caches. > The btrfs filesystem was on an SSD. > > Level Ratio Compression (MB/s) Decompression (MB/s) > 1 2.658438.47910.51 > 2 2.744364.86886.55 > 3 2.801336.33828.41 > 4 2.858286.71886.55 > 5 2.916212.77556.84 > 6 2.363119.82990.85 > 7 3.000154.06849.30 > 8 3.011159.54875.03 > 9 3.025100.51940.15 > 10 3.033118.97616.26 > 11 3.036 94.19802.11 > 12 3.037 73.45931.49 > 13 3.041 55.17835.26 > 14 3.087 44.70716.78 > 15 3.126 37.30878.84 > > [1] > https://lore.kernel.org/linux-btrfs/20181031181108.289340-1-terre...@fb.com/ > > Signed-off-by: Dennis Zhou > Cc: Nick Terrell > Cc: Omar Sandoval > --- > fs/btrfs/super.c | 6 +- > fs/btrfs/zstd.c | 229 +-- > 2 files changed, 226 insertions(+), 9 deletions(-) > > diff --git a/fs/btrfs/super.c b/fs/btrfs/super.c > index b28dff207383..0ecc513cb56c 100644 > --- a/fs/btrfs/super.c > +++ b/fs/btrfs/super.c > @@ -544,9 +544,13 @@ int btrfs_parse_options(struct btrfs_fs_info *info, char > *options, > btrfs_clear_opt(info->mount_opt, NODATASUM); > btrfs_set_fs_incompat(info, COMPRESS_LZO); > no_compress = 0; > - } else if (strcmp(args[0].from, "zstd") == 0) { > + } else if (strncmp(args[0].from, "zstd", 4) == 0) { > compress_type = "zstd"; > info->compress_type = BTRFS_COMPRESS_ZSTD; > + info->compress_level = > + btrfs_compress_str2level( > + BTRFS_COMPRESS_ZSTD, > + args[0].from + 4); > btrfs_set_opt(info->mount_opt, COMPRESS); > btrfs_clear_opt(info->mount_opt, NODATACOW); > btrfs_clear_opt(info->mount_opt, NODATASUM); > diff --git a/fs/btrfs/zstd.c b/fs/btrfs/zstd.c > index a951d4fe77f7..ce9b466c197f 100644 > --- a/fs/btrfs/zstd.c > +++ b/fs/btrfs/zstd.c > @@ -6,20 +6,27 @@ > */ > > #include > +#include > #include > #include > #include > #include > +#include > #include > #include > #include > #include > #include > #include "compression.h" > +#include "ctree.h" > > #define
[PATCH v3 2/2] PCI: hv: Refactor hv_irq_unmask() to use cpumask_to_vpset()
Remove the duplicate implementation of cpumask_to_vpset() and use the shared implementation. Export hv_max_vp_index, which is required by cpumask_to_vpset(). Apply changes to hv_irq_unmask() based on feedback. Signed-off-by: Maya Nakamura --- Changes in v3: - Modify to catch all failures from cpumask_to_vpset(). - Correct the v2 change log about the commit message. Changes in v2: - Remove unnecessary nr_bank initialization. - Delete two unnecessary dev_err()'s. - Unlock before returning. - Update the commit message. arch/x86/hyperv/hv_init.c | 1 + drivers/pci/controller/pci-hyperv.c | 38 + 2 files changed, 18 insertions(+), 21 deletions(-) diff --git a/arch/x86/hyperv/hv_init.c b/arch/x86/hyperv/hv_init.c index 7abb09e2eeb8..7f2eed1fc81b 100644 --- a/arch/x86/hyperv/hv_init.c +++ b/arch/x86/hyperv/hv_init.c @@ -96,6 +96,7 @@ void __percpu **hyperv_pcpu_input_arg; EXPORT_SYMBOL_GPL(hyperv_pcpu_input_arg); u32 hv_max_vp_index; +EXPORT_SYMBOL_GPL(hv_max_vp_index); static int hv_cpu_init(unsigned int cpu) { diff --git a/drivers/pci/controller/pci-hyperv.c b/drivers/pci/controller/pci-hyperv.c index da8b58d8630d..a78def332bbc 100644 --- a/drivers/pci/controller/pci-hyperv.c +++ b/drivers/pci/controller/pci-hyperv.c @@ -391,8 +391,6 @@ struct hv_interrupt_entry { u32 data; }; -#define HV_VP_SET_BANK_COUNT_MAX 5 /* current implementation limit */ - /* * flags for hv_device_interrupt_target.flags */ @@ -908,12 +906,12 @@ static void hv_irq_unmask(struct irq_data *data) struct retarget_msi_interrupt *params; struct hv_pcibus_device *hbus; struct cpumask *dest; + cpumask_var_t tmp; struct pci_bus *pbus; struct pci_dev *pdev; unsigned long flags; u32 var_size = 0; - int cpu_vmbus; - int cpu; + int cpu, nr_bank; u64 res; dest = irq_data_get_effective_affinity_mask(data); @@ -953,29 +951,27 @@ static void hv_irq_unmask(struct irq_data *data) */ params->int_target.flags |= HV_DEVICE_INTERRUPT_TARGET_PROCESSOR_SET; - params->int_target.vp_set.valid_bank_mask = - (1ull << HV_VP_SET_BANK_COUNT_MAX) - 1; + + if (!alloc_cpumask_var(, GFP_KERNEL)) { + res = 1; + goto exit_unlock; + } + + cpumask_and(tmp, dest, cpu_online_mask); + nr_bank = cpumask_to_vpset(>int_target.vp_set, tmp); + free_cpumask_var(tmp); + + if (nr_bank <= 0) { + res = 1; + goto exit_unlock; + } /* * var-sized hypercall, var-size starts after vp_mask (thus * vp_set.format does not count, but vp_set.valid_bank_mask * does). */ - var_size = 1 + HV_VP_SET_BANK_COUNT_MAX; - - for_each_cpu_and(cpu, dest, cpu_online_mask) { - cpu_vmbus = hv_cpu_number_to_vp_number(cpu); - - if (cpu_vmbus >= HV_VP_SET_BANK_COUNT_MAX * 64) { - dev_err(>hdev->device, - "too high CPU %d", cpu_vmbus); - res = 1; - goto exit_unlock; - } - - params->int_target.vp_set.bank_contents[cpu_vmbus / 64] |= - (1ULL << (cpu_vmbus & 63)); - } + var_size = 1 + nr_bank; } else { for_each_cpu_and(cpu, dest, cpu_online_mask) { params->int_target.vp_mask |= -- 2.17.1
Re: [PATCH v1] mm: migrate: don't rely on PageMovable() of newpage after unlocking it
On Mon 28-01-19 22:09:14, David Hildenbrand wrote: > On 28.01.19 21:19, Michal Hocko wrote: [...] > > David, could you reformulate the changelog accordingly please? My ack > > still holds. > > You mean reformulating + resending for stable kernels only? I would merge your patch even if it doesn't fix any real problem _now_. If for not other reasons it makes the code less subtle because we no longer depend on this crazy __PageMovable is special. If the movable flag is supposed to be synchronized with the page lock then do not do tricks and make code more robust because the next time somebody would like to fix up the current semantic he might reintroduce the bug easily. -- Michal Hocko SUSE Labs
[PATCH v3 1/2] PCI: hv: Replace hv_vp_set with hv_vpset
Remove a duplicate definition of VP set (hv_vp_set) and use the common definition (hv_vpset) that is used in other places. Change the order of the members in struct hv_pcibus_device so that the declaration of retarget_msi_interrupt_params is the last member. Struct hv_vpset, which contains a flexible array, is nested two levels deep in struct hv_pcibus_device via retarget_msi_interrupt_params. Add a comment that retarget_msi_interrupt_params should be the last member of struct hv_pcibus_device. Signed-off-by: Maya Nakamura --- Change in v3: - Correct the v2 change log. Change in v2: - Update the commit message. drivers/pci/controller/pci-hyperv.c | 25 - 1 file changed, 12 insertions(+), 13 deletions(-) diff --git a/drivers/pci/controller/pci-hyperv.c b/drivers/pci/controller/pci-hyperv.c index 9ba4d12c179c..da8b58d8630d 100644 --- a/drivers/pci/controller/pci-hyperv.c +++ b/drivers/pci/controller/pci-hyperv.c @@ -393,12 +393,6 @@ struct hv_interrupt_entry { #define HV_VP_SET_BANK_COUNT_MAX 5 /* current implementation limit */ -struct hv_vp_set { - u64 format; /* 0 (HvGenericSetSparse4k) */ - u64 valid_banks; - u64 masks[HV_VP_SET_BANK_COUNT_MAX]; -}; - /* * flags for hv_device_interrupt_target.flags */ @@ -410,7 +404,7 @@ struct hv_device_interrupt_target { u32 flags; union { u64 vp_mask; - struct hv_vp_set vp_set; + struct hv_vpset vp_set; }; }; @@ -460,12 +454,16 @@ struct hv_pcibus_device { struct msi_controller msi_chip; struct irq_domain *irq_domain; - /* hypercall arg, must not cross page boundary */ - struct retarget_msi_interrupt retarget_msi_interrupt_params; - spinlock_t retarget_msi_interrupt_lock; struct workqueue_struct *wq; + + /* hypercall arg, must not cross page boundary */ + struct retarget_msi_interrupt retarget_msi_interrupt_params; + + /* +* Don't put anything here: retarget_msi_interrupt_params must be last +*/ }; /* @@ -955,12 +953,13 @@ static void hv_irq_unmask(struct irq_data *data) */ params->int_target.flags |= HV_DEVICE_INTERRUPT_TARGET_PROCESSOR_SET; - params->int_target.vp_set.valid_banks = + params->int_target.vp_set.valid_bank_mask = (1ull << HV_VP_SET_BANK_COUNT_MAX) - 1; /* * var-sized hypercall, var-size starts after vp_mask (thus -* vp_set.format does not count, but vp_set.valid_banks does). +* vp_set.format does not count, but vp_set.valid_bank_mask +* does). */ var_size = 1 + HV_VP_SET_BANK_COUNT_MAX; @@ -974,7 +973,7 @@ static void hv_irq_unmask(struct irq_data *data) goto exit_unlock; } - params->int_target.vp_set.masks[cpu_vmbus / 64] |= + params->int_target.vp_set.bank_contents[cpu_vmbus / 64] |= (1ULL << (cpu_vmbus & 63)); } } else { -- 2.17.1
[PATCH v3 0/2] PCI: hv: Refactor hv_irq_unmask() to use hv_vpset and cpumask_to_vpset()
This patchset removes a duplicate definition of VP set (hv_vp_set) and uses the common definition (hv_vpset) that is used in other places. It changes the order of the members in struct hv_pcibus_device due to flexible array in hv_vpset. It also removes the duplicate implementation of cpumask_to_vpset(), uses the shared implementation, and exports hv_max_vp_index, which is required by cpumask_to_vpset(). Maya Nakamura (2): PCI: hv: Replace hv_vp_set with hv_vpset PCI: hv: Refactor hv_irq_unmask() to use cpumask_to_vpset() arch/x86/hyperv/hv_init.c | 1 + drivers/pci/controller/pci-hyperv.c | 59 + 2 files changed, 28 insertions(+), 32 deletions(-) -- 2.17.1
Re: [PATCH net] net: apple: replace dev_kfree_skb_irq by dev_consume_skb_irq for drop profiles
From: Yang Wei Date: Tue, 29 Jan 2019 07:39:13 +0800 > dev_consume_skb_irq() should be called in bmac_txdma_intr() when > xmit done. It makes drop profiles more friendly. > > Signed-off-by: Yang Wei Applied.
Re: [PATCH net] net: ti: replace dev_kfree_skb_irq by dev_consume_skb_irq for drop profiles
From: Yang Wei Date: Tue, 29 Jan 2019 07:40:10 +0800 > dev_consume_skb_irq() should be called in cpmac_end_xmit() when > xmit done. It makes drop profiles more friendly. > > Signed-off-by: Yang Wei Applied.
Re: [PATCH] perf/x86/intel/uncore: Add Node ID mask
> On Jan 27, 2019, at 6:53 AM, kan.li...@linux.intel.com wrote: > > From: Kan Liang > > Some PCI uncore PMUs cannot be registered on a 8-socket system (HPE > Superdome Flex). > > To understand which Socket the PCI uncore PMUs belong to, perf retrieves > the local Node ID of the uncore device from CPUNODEID(0xC0) of the PCI > configuration space, and the mapping between Socket ID and Node ID from > GIDNIDMAP(0xD4). The Socket ID can be calculated accordingly. > The local Node ID is only available at bit 2:0, but current code doesn't > mask it. If a BIOS doesn't clear the rest of the bits, a wrong Node ID > will be fetched. > > Filter the Node ID by adding a mask. > > Fixes: 7c94ee2e0917 ("perf/x86: Add Intel Nehalem and Sandy Bridge-EP uncore > support") > Reported-by: Song Liu > Tested-by: Song Liu > Signed-off-by: Kan Liang > Cc: sta...@vger.kernel.org Thanks Kan! Acked-by: Song Liu > --- > arch/x86/events/intel/uncore_snbep.c | 4 +++- > 1 file changed, 3 insertions(+), 1 deletion(-) > > diff --git a/arch/x86/events/intel/uncore_snbep.c > b/arch/x86/events/intel/uncore_snbep.c > index c07bee3..b10e043 100644 > --- a/arch/x86/events/intel/uncore_snbep.c > +++ b/arch/x86/events/intel/uncore_snbep.c > @@ -1222,6 +1222,8 @@ static struct pci_driver snbep_uncore_pci_driver = { > .id_table = snbep_uncore_pci_ids, > }; > > +#define NODE_ID_MASK 0x7 > + > /* > * build pci bus to socket mapping > */ > @@ -1243,7 +1245,7 @@ static int snbep_pci2phy_map_init(int devid, int > nodeid_loc, int idmap_loc, bool > err = pci_read_config_dword(ubox_dev, nodeid_loc, ); > if (err) > break; > - nodeid = config; > + nodeid = config & NODE_ID_MASK; > /* get the Node ID mapping */ > err = pci_read_config_dword(ubox_dev, idmap_loc, ); > if (err) > -- > 2.7.4 >
Re: [PATCH v5 2/9] cpufreq: Auto-register the driver as a thermal cooling device if asked
On 29-01-19, 11:50, Amit Kucheria wrote: > On Tue, Jan 29, 2019 at 11:16 AM Amit Kucheria > wrote: > > > > On Tue, Jan 29, 2019 at 11:06 AM Viresh Kumar > > wrote: > > > > > > On 29-01-19, 10:25, Amit Kucheria wrote: > > > > All cpufreq drivers do similar things to register as a cooling device. > > > > Provide a cpufreq driver flag so drivers can just ask the cpufreq core > > > > to register the cooling device on their behalf. This allows us to get > > > > rid of duplicated code in the drivers. > > > > > > > > In order to allow this, we add a struct thermal_cooling_device pointer > > > > to struct cpufreq_policy so that drivers don't need to store it in a > > > > private data structure. > > > > > > > > Suggested-by: Stephen Boyd > > > > Suggested-by: Viresh Kumar > > > > Signed-off-by: Amit Kucheria > > > > Reviewed-by: Matthias Kaehlcke > > > > Tested-by: Matthias Kaehlcke > > > > Acked-by: Viresh Kumar > > > > --- > > > > drivers/cpufreq/cpufreq.c | 13 + > > > > include/linux/cpufreq.h | 9 + > > > > 2 files changed, 22 insertions(+) > > > > > > > > diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c > > > > index e35a886e00bc..0f9b50d3ee91 100644 > > > > --- a/drivers/cpufreq/cpufreq.c > > > > +++ b/drivers/cpufreq/cpufreq.c > > > > @@ -19,6 +19,7 @@ > > > > > > > > #include > > > > #include > > > > +#include > > > > #include > > > > #include > > > > #include > > > > @@ -1318,6 +1319,11 @@ static int cpufreq_online(unsigned int cpu) > > > > if (cpufreq_driver->ready) > > > > cpufreq_driver->ready(policy); > > > > > > > > +#if IS_ENABLED(CONFIG_CPU_THERMAL) > > > > + if (cpufreq_driver->flags & CPUFREQ_IS_COOLING_DEV) > > > > + policy->cdev = of_cpufreq_cooling_register(policy); > > > > +#endif > > > > > > I am not sure if Rafael wanted it this way but maybe something like this: > > > > > > if (IS_ENABLED(CONFIG_CPU_THERMAL) && > > > cpufreq_driver->flags & CPUFREQ_IS_COOLING_DEV)) > > > policy->cdev = of_cpufreq_cooling_register(policy); > > > > > > We never wanted ifdef hackery to be in there :) > > > > OK, that makes more sense. Should I just send out a fixup patch or the > > entire series? Single patch should be fine I believe. > FWIW, I checked drivers/cpufreq and drivers/thermal before converting > over and there is a mixed use of #if IS_ENABLED and if(IS_ENABLED). > > Perhaps we should clean it up? No objections from me on that. -- viresh
Re: [PATCH] include/linux/bpf.h - fix missing prototype warnings...
On Mon, Jan 28, 2019 at 10:05 PM wrote: > > Compiling with W=1 generates warnings: > > CC kernel/bpf/core.o > kernel/bpf/core.c:721:12: warning: no previous prototype for > ?bpf_jit_alloc_exec_limit? [-Wmissing-prototypes] > 721 | u64 __weak bpf_jit_alloc_exec_limit(void) > |^~~~ > kernel/bpf/core.c:757:14: warning: no previous prototype for > ?bpf_jit_alloc_exec? [-Wmissing-prototypes] > 757 | void *__weak bpf_jit_alloc_exec(unsigned long size) > | ^~ > kernel/bpf/core.c:762:13: warning: no previous prototype for > ?bpf_jit_free_exec? [-Wmissing-prototypes] > 762 | void __weak bpf_jit_free_exec(void *addr) > | ^ > > All three are weak functions that archs can override, although none do so > currently. Provide prototypes for when a new arch provides its own. > > Signed-off-by: Valdis Kletnieks Acked-by: Song Liu > > diff --git a/include/linux/bpf.h b/include/linux/bpf.h > index 3851529062ec..99e55313123f 100644 > --- a/include/linux/bpf.h > +++ b/include/linux/bpf.h > @@ -472,6 +472,10 @@ _out: > \ > #define BPF_PROG_RUN_ARRAY_CHECK(array, ctx, func) \ > __BPF_PROG_RUN_ARRAY(array, ctx, func, true) > > +u64 __weak bpf_jit_alloc_exec_limit(void); > +void *__weak bpf_jit_alloc_exec(unsigned long size); > +void __weak bpf_jit_free_exec(void *addr); > + > #ifdef CONFIG_BPF_SYSCALL > DECLARE_PER_CPU(int, bpf_prog_active); > >
AW: [PATCH 2/3] Input: st1232 - add support for st1633
Hi Martin, Matthias Fend R Electronics Wolfvision GmbH Oberes Ried 14 | 6833 Klaus | Austria Tel: +43 5523 52250 | Mail: matthias.f...@wolfvision.net Webpage: www.wolfvision.com | www.wolfvision.com/green Firmenbuch / Commercial Register: FN283521v Feldkirch/Austria > -Ursprüngliche Nachricht- > Von: linux-input-ow...@vger.kernel.org ow...@vger.kernel.org> Im Auftrag von Martin Kepplinger > Gesendet: Montag, 28. Jänner 2019 20:10 > An: Dmitry Torokhov > Cc: devicet...@vger.kernel.org; linux-in...@vger.kernel.org; > robh...@kernel.org; mark.rutl...@arm.com; linux-kernel@vger.kernel.org; > Martin Kepplinger > Betreff: Re: [PATCH 2/3] Input: st1232 - add support for st1633 > > Am 28.01.2019 20:03 schrieb Dmitry Torokhov: > > Hi Martin, > > > > On Mon, Jan 28, 2019 at 09:44:48AM +0100, Martin Kepplinger wrote: > >> From: Martin Kepplinger > >> > >> Add support for the Sitronix ST1633 touchscreen controller to the > >> st1232 > >> driver. A protocol spec can be found here: > >> > https://emea01.safelinks.protection.outlook.com/?url=www.ampdisplay.co > m%2Fdocuments%2Fpdf%2FAM-320480B6TZQW- > TC0H.pdfdata=01%7C01%7CMatthias.Fend%40wolfvision.net%7C4f9d > 56475f674b1e3b4008d685543b35%7Ce94ec9da9183471e83b351baa8eb804f% > 7C0sdata=YTw33BPKKpdN%2BBFrufVk8e4YqXOzR6VQKuzRMOjcwWk > %3Dreserved=0 > >> > >> Signed-off-by: Martin Kepplinger > >> --- > >> drivers/input/touchscreen/Kconfig | 6 +- > >> drivers/input/touchscreen/st1232.c | 122 > >> + > >> 2 files changed, 94 insertions(+), 34 deletions(-) > >> > >> diff --git a/drivers/input/touchscreen/Kconfig > >> b/drivers/input/touchscreen/Kconfig > >> index 068dbbc610fc..7c597a49c265 100644 > >> --- a/drivers/input/touchscreen/Kconfig > >> +++ b/drivers/input/touchscreen/Kconfig > >> @@ -1168,11 +1168,11 @@ config TOUCHSCREEN_SIS_I2C > >> module will be called sis_i2c. > >> > >> config TOUCHSCREEN_ST1232 > >> - tristate "Sitronix ST1232 touchscreen controllers" > >> + tristate "Sitronix ST1232 or ST1633 touchscreen controllers" > >>depends on I2C > >>help > >> -Say Y here if you want to support Sitronix ST1232 > >> -touchscreen controller. > >> +Say Y here if you want to support the Sitronix ST1232 > >> +or ST1633 touchscreen controller. > >> > >> If unsure, say N. > >> > >> diff --git a/drivers/input/touchscreen/st1232.c > >> b/drivers/input/touchscreen/st1232.c > >> index 11ff32c68025..19a665d48dad 100644 > >> --- a/drivers/input/touchscreen/st1232.c > >> +++ b/drivers/input/touchscreen/st1232.c > >> @@ -23,13 +23,15 @@ > >> #include > >> > >> #define ST1232_TS_NAME"st1232-ts" > >> +#define ST1633_TS_NAME"st1633-ts" > >> + > >> +enum { > >> + st1232, > >> + st1633, > >> +}; > > > > This enum seems no longer needed, I dropped it. > > > >> > >> #define MIN_X 0x00 > >> #define MIN_Y 0x00 > > > > Given we no longer have constant MAX_X/Y I simply used 0 in > > input_set_abs_params() and dropped MIN-X/Y. > > > >> -#define MAX_X 0x31f /* (800 - 1) */ > >> -#define MAX_Y 0x1df /* (480 - 1) */ > >> -#define MAX_AREA 0xff > >> -#define MAX_FINGERS 2 > >> > >> struct st1232_ts_finger { > >>u16 x; > >> @@ -38,12 +40,24 @@ struct st1232_ts_finger { > >>bool is_valid; > >> }; > >> > >> +struct st_chip_info { > >> + boolhave_z; > >> + u16 max_x; > >> + u16 max_y; > >> + u16 max_area; > >> + u16 max_fingers; > >> + u8 start_reg; > >> +}; > >> + > >> struct st1232_ts_data { > >>struct i2c_client *client; > >>struct input_dev *input_dev; > >> - struct st1232_ts_finger finger[MAX_FINGERS]; > >>struct dev_pm_qos_request low_latency_req; > >>int reset_gpio; > > > > Could you please create an additional patch converting this to gpiod? > > Instead of doing of_get_gpio()/gpio_is_valid()/devm_gpio_request() > > smply > > do > > > > ts->reset_gpio = devm_gpiod_get_optional(); > > if (IS_ERR(ts->reset_gpio)) { > > ... > > } > > > > and later > > > > if (ts->reset_gpio) > > ... > > > > Looking at the code it looks like reset is as usual active low, so you > > will need to invert the logic as gpiod takes care of convertion logical > > value to proper level (active low or high). > > I'll test your applied changes and get back to this tomorrow. > > thanks. > > > > >> + const struct st_chip_info *chip_info; > >> + int read_buf_len; > >> + u8 *read_buf; > >> + struct st1232_ts_finger *finger; > >> }; > >> > >> static int st1232_ts_read_data(struct st1232_ts_data *ts) > >> @@ -52,40 +66,35 @@ static int st1232_ts_read_data(struct > >> st1232_ts_data *ts) > >>struct i2c_client *client = ts->client; > >>struct i2c_msg msg[2]; > >>int error; > >> - u8 start_reg; > >> - u8 buf[10]; > >> + int i, y; > >> + u8 start_reg = ts->chip_info->start_reg; > >> + u8 *buf = ts->read_buf; > >> > >> - /* read touchscreen data from
Re: [PATCH] kernel/bpf/cgroup.c - clean up kerneldoc warnings
On Mon, Jan 28, 2019 at 10:48 PM wrote: > > Building with W=1 reveals some bitrot > > CC kernel/bpf/cgroup.o > kernel/bpf/cgroup.c:238: warning: Function parameter or member 'flags' not > described in '__cgroup_bpf_attach' > kernel/bpf/cgroup.c:367: warning: Function parameter or member 'unused_flags' > not described in '__cgroup_bpf_detach' > > Add a kerneldoc line for 'flags'. > > Fixing the warning for 'unused_flags' is best approached by > removing the unused parameter on the function call. > > Signed-off-by: Valdis Kletnieks Thanks! Acked-by: Song Liu PS: For future patches, please specify which tree the patch should be applied to with [PATCH bpf] or [PATCH bpf-next]. > > diff --git a/include/linux/bpf-cgroup.h b/include/linux/bpf-cgroup.h > index 588dd5f0bd85..695b2a880d9a 100644 > --- a/include/linux/bpf-cgroup.h > +++ b/include/linux/bpf-cgroup.h > @@ -78,7 +78,7 @@ int cgroup_bpf_inherit(struct cgroup *cgrp); > int __cgroup_bpf_attach(struct cgroup *cgrp, struct bpf_prog *prog, > enum bpf_attach_type type, u32 flags); > int __cgroup_bpf_detach(struct cgroup *cgrp, struct bpf_prog *prog, > - enum bpf_attach_type type, u32 flags); > + enum bpf_attach_type type); > int __cgroup_bpf_query(struct cgroup *cgrp, const union bpf_attr *attr, >union bpf_attr __user *uattr); > > diff --git a/kernel/bpf/cgroup.c b/kernel/bpf/cgroup.c > index ab612fe9862f..d78cfec5807d 100644 > --- a/kernel/bpf/cgroup.c > +++ b/kernel/bpf/cgroup.c > @@ -230,6 +230,7 @@ static int update_effective_progs(struct cgroup *cgrp, > * @cgrp: The cgroup which descendants to traverse > * @prog: A program to attach > * @type: Type of attach operation > + * @flags: Option flags > * > * Must be called with cgroup_mutex held. > */ > @@ -363,7 +364,7 @@ int __cgroup_bpf_attach(struct cgroup *cgrp, struct > bpf_prog *prog, > * Must be called with cgroup_mutex held. > */ > int __cgroup_bpf_detach(struct cgroup *cgrp, struct bpf_prog *prog, > - enum bpf_attach_type type, u32 unused_flags) > + enum bpf_attach_type type) > { > struct list_head *progs = >bpf.progs[type]; > enum bpf_cgroup_storage_type stype; > diff --git a/kernel/cgroup/cgroup.c b/kernel/cgroup/cgroup.c > index 6d03a27918f4..9802ab424397 100644 > --- a/kernel/cgroup/cgroup.c > +++ b/kernel/cgroup/cgroup.c > @@ -6059,7 +6059,7 @@ int cgroup_bpf_detach(struct cgroup *cgrp, struct > bpf_prog *prog, > int ret; > > mutex_lock(_mutex); > - ret = __cgroup_bpf_detach(cgrp, prog, type, flags); > + ret = __cgroup_bpf_detach(cgrp, prog, type); > mutex_unlock(_mutex); > return ret; > } >
[PATCH 3/3] KVM: x86: Add support of clear Trace_ToPA_PMI status
Add support of clear Intel PT ToPA PMI status for KVM guest. Signed-off-by: Luwei Kang --- arch/x86/include/asm/kvm_host.h | 1 + arch/x86/include/asm/msr-index.h | 4 arch/x86/kvm/vmx/pmu_intel.c | 8 +++- 3 files changed, 12 insertions(+), 1 deletion(-) diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h index 4660ce9..de95704 100644 --- a/arch/x86/include/asm/kvm_host.h +++ b/arch/x86/include/asm/kvm_host.h @@ -468,6 +468,7 @@ struct kvm_pmu { u64 global_ovf_ctrl; u64 counter_bitmask[2]; u64 global_ctrl_mask; + u64 global_ovf_ctrl_mask; u64 reserved_bits; u8 version; struct kvm_pmc gp_counters[INTEL_PMC_MAX_GENERIC]; diff --git a/arch/x86/include/asm/msr-index.h b/arch/x86/include/asm/msr-index.h index ae01fb0..c0ea4aa 100644 --- a/arch/x86/include/asm/msr-index.h +++ b/arch/x86/include/asm/msr-index.h @@ -778,6 +778,10 @@ /* PERF_GLOBAL_OVF_CTL bits */ #define MSR_CORE_PERF_GLOBAL_OVF_CTRL_TRACE_TOPA_PMI_BIT 55 #define MSR_CORE_PERF_GLOBAL_OVF_CTRL_TRACE_TOPA_PMI (1ULL << MSR_CORE_PERF_GLOBAL_OVF_CTRL_TRACE_TOPA_PMI_BIT) +#define MSR_CORE_PERF_GLOBAL_OVF_CTRL_OVF_BUF_BIT 62 +#define MSR_CORE_PERF_GLOBAL_OVF_CTRL_OVF_BUF (1ULL << MSR_CORE_PERF_GLOBAL_OVF_CTRL_OVF_BUF_BIT) +#define MSR_CORE_PERF_GLOBAL_OVF_CTRL_COND_CHGD_BIT63 +#define MSR_CORE_PERF_GLOBAL_OVF_CTRL_COND_CHGD(1ULL << MSR_CORE_PERF_GLOBAL_OVF_CTRL_COND_CHGD_BIT) /* Geode defined MSRs */ #define MSR_GEODE_BUSCONT_CONF00x1900 diff --git a/arch/x86/kvm/vmx/pmu_intel.c b/arch/x86/kvm/vmx/pmu_intel.c index 5ab4a36..6dee7cf 100644 --- a/arch/x86/kvm/vmx/pmu_intel.c +++ b/arch/x86/kvm/vmx/pmu_intel.c @@ -227,7 +227,7 @@ static int intel_pmu_set_msr(struct kvm_vcpu *vcpu, struct msr_data *msr_info) } break; case MSR_CORE_PERF_GLOBAL_OVF_CTRL: - if (!(data & (pmu->global_ctrl_mask & ~(3ull<<62 { + if (!(data & pmu->global_ovf_ctrl_mask)) { if (!msr_info->host_initiated) pmu->global_status &= ~data; pmu->global_ovf_ctrl = data; @@ -297,6 +297,12 @@ static void intel_pmu_refresh(struct kvm_vcpu *vcpu) pmu->global_ctrl = ((1ull << pmu->nr_arch_gp_counters) - 1) | (((1ull << pmu->nr_arch_fixed_counters) - 1) << INTEL_PMC_IDX_FIXED); pmu->global_ctrl_mask = ~pmu->global_ctrl; + pmu->global_ovf_ctrl_mask = ~(pmu->global_ctrl | + MSR_CORE_PERF_GLOBAL_OVF_CTRL_OVF_BUF | + MSR_CORE_PERF_GLOBAL_OVF_CTRL_COND_CHGD); + if (kvm_x86_ops->pt_supported()) + pmu->global_ovf_ctrl_mask &= + ~MSR_CORE_PERF_GLOBAL_OVF_CTRL_TRACE_TOPA_PMI; entry = kvm_find_cpuid_entry(vcpu, 7, 0); if (entry && -- 1.8.3.1
[PATCH 2/3] perf/x86/intel/pt: Inject PMI for KVM guest
Inject a PMI for KVM guest when Intel PT working in Host-Guest mode and Guest ToPA entry memory buffer was completely filled. The definition of ‘kvm_make_request’ and ‘KVM_REQ_PMI’ depend on "linux/kvm_host.h" header. Signed-off-by: Luwei Kang --- arch/x86/events/intel/pt.c | 12 +++- arch/x86/include/asm/intel_pt.h | 1 + arch/x86/include/asm/msr-index.h | 4 arch/x86/kvm/x86.h | 6 ++ 4 files changed, 22 insertions(+), 1 deletion(-) diff --git a/arch/x86/events/intel/pt.c b/arch/x86/events/intel/pt.c index 9494ca6..09375bd 100644 --- a/arch/x86/events/intel/pt.c +++ b/arch/x86/events/intel/pt.c @@ -23,6 +23,7 @@ #include #include #include +#include #include #include @@ -33,7 +34,8 @@ #include "../perf_event.h" #include "pt.h" -static DEFINE_PER_CPU(struct pt, pt_ctx); +DEFINE_PER_CPU(struct pt, pt_ctx); +EXPORT_PER_CPU_SYMBOL_GPL(pt_ctx); static struct pt_pmu pt_pmu; @@ -1260,6 +1262,14 @@ void intel_pt_interrupt(void) struct pt_buffer *buf; struct perf_event *event = pt->handle.event; + if (pt->vcpu) { + /* Inject PMI to Guest */ + kvm_make_request(KVM_REQ_PMI, pt->vcpu); + __set_bit(MSR_CORE_PERF_GLOBAL_OVF_CTRL_TRACE_TOPA_PMI_BIT, + (unsigned long *)>vcpu->arch.pmu.global_status); + return; + } + /* * There may be a dangling PT bit in the interrupt status register * after PT has been disabled by pt_event_stop(). Make sure we don't diff --git a/arch/x86/include/asm/intel_pt.h b/arch/x86/include/asm/intel_pt.h index ee960fb..32da2e9 100644 --- a/arch/x86/include/asm/intel_pt.h +++ b/arch/x86/include/asm/intel_pt.h @@ -62,6 +62,7 @@ struct pt { struct pt_filters filters; int handle_nmi; int vmx_on; + struct kvm_vcpu *vcpu; }; #if defined(CONFIG_PERF_EVENTS) && defined(CONFIG_CPU_SUP_INTEL) diff --git a/arch/x86/include/asm/msr-index.h b/arch/x86/include/asm/msr-index.h index 8e40c24..ae01fb0 100644 --- a/arch/x86/include/asm/msr-index.h +++ b/arch/x86/include/asm/msr-index.h @@ -775,6 +775,10 @@ #define MSR_CORE_PERF_GLOBAL_CTRL 0x038f #define MSR_CORE_PERF_GLOBAL_OVF_CTRL 0x0390 +/* PERF_GLOBAL_OVF_CTL bits */ +#define MSR_CORE_PERF_GLOBAL_OVF_CTRL_TRACE_TOPA_PMI_BIT 55 +#define MSR_CORE_PERF_GLOBAL_OVF_CTRL_TRACE_TOPA_PMI (1ULL << MSR_CORE_PERF_GLOBAL_OVF_CTRL_TRACE_TOPA_PMI_BIT) + /* Geode defined MSRs */ #define MSR_GEODE_BUSCONT_CONF00x1900 diff --git a/arch/x86/kvm/x86.h b/arch/x86/kvm/x86.h index 224cd0a..a9ee498 100644 --- a/arch/x86/kvm/x86.h +++ b/arch/x86/kvm/x86.h @@ -4,6 +4,7 @@ #include #include +#include #include "kvm_cache_regs.h" #define KVM_DEFAULT_PLE_GAP128 @@ -331,15 +332,20 @@ static inline bool kvm_pause_in_guest(struct kvm *kvm) } DECLARE_PER_CPU(struct kvm_vcpu *, current_vcpu); +DECLARE_PER_CPU(struct pt, pt_ctx); static inline void kvm_before_interrupt(struct kvm_vcpu *vcpu) { __this_cpu_write(current_vcpu, vcpu); + if (kvm_x86_ops->pt_supported()) + this_cpu_ptr(_ctx)->vcpu = vcpu; } static inline void kvm_after_interrupt(struct kvm_vcpu *vcpu) { __this_cpu_write(current_vcpu, NULL); + if (kvm_x86_ops->pt_supported()) + this_cpu_ptr(_ctx)->vcpu = NULL; } #endif -- 1.8.3.1
[PATCH 1/3] perf/x86/intel/pt: Move pt structure to global header
Intel PT structure (struct pt) is in a private header. Move it (and sub structure) to a global header so that it can be accessible from KVM code. The definition of perf_output_handle structure included in "linux/perf_event.h". Signed-off-by: Luwei Kang --- arch/x86/events/intel/pt.h | 38 -- arch/x86/include/asm/intel_pt.h | 40 2 files changed, 40 insertions(+), 38 deletions(-) diff --git a/arch/x86/events/intel/pt.h b/arch/x86/events/intel/pt.h index 269e15a..964948f 100644 --- a/arch/x86/events/intel/pt.h +++ b/arch/x86/events/intel/pt.h @@ -93,42 +93,4 @@ struct pt_buffer { struct topa_entry *topa_index[0]; }; -#define PT_FILTERS_NUM 4 - -/** - * struct pt_filter - IP range filter configuration - * @msr_a: range start, goes to RTIT_ADDRn_A - * @msr_b: range end, goes to RTIT_ADDRn_B - * @config:4-bit field in RTIT_CTL - */ -struct pt_filter { - unsigned long msr_a; - unsigned long msr_b; - unsigned long config; -}; - -/** - * struct pt_filters - IP range filtering context - * @filter:filters defined for this context - * @nr_filters:number of defined filters in the @filter array - */ -struct pt_filters { - struct pt_filterfilter[PT_FILTERS_NUM]; - unsigned intnr_filters; -}; - -/** - * struct pt - per-cpu pt context - * @handle:perf output handle - * @filters: last configured filters - * @handle_nmi:do handle PT PMI on this cpu, there's an active event - * @vmx_on:1 if VMX is ON on this cpu - */ -struct pt { - struct perf_output_handle handle; - struct pt_filters filters; - int handle_nmi; - int vmx_on; -}; - #endif /* __INTEL_PT_H__ */ diff --git a/arch/x86/include/asm/intel_pt.h b/arch/x86/include/asm/intel_pt.h index 634f99b..ee960fb 100644 --- a/arch/x86/include/asm/intel_pt.h +++ b/arch/x86/include/asm/intel_pt.h @@ -2,6 +2,8 @@ #ifndef _ASM_X86_INTEL_PT_H #define _ASM_X86_INTEL_PT_H +#include + #define PT_CPUID_LEAVES2 #define PT_CPUID_REGS_NUM 4 /* number of regsters (eax, ebx, ecx, edx) */ @@ -24,6 +26,44 @@ enum pt_capabilities { PT_CAP_psb_periods, }; +#define PT_FILTERS_NUM 4 + +/** + * struct pt_filter - IP range filter configuration + * @msr_a: range start, goes to RTIT_ADDRn_A + * @msr_b: range end, goes to RTIT_ADDRn_B + * @config:4-bit field in RTIT_CTL + */ +struct pt_filter { + unsigned long msr_a; + unsigned long msr_b; + unsigned long config; +}; + +/** + * struct pt_filters - IP range filtering context + * @filter:filters defined for this context + * @nr_filters:number of defined filters in the @filter array + */ +struct pt_filters { + struct pt_filterfilter[PT_FILTERS_NUM]; + unsigned intnr_filters; +}; + +/** + * struct pt - per-cpu pt context + * @handle:perf output handle + * @filters: last configured filters + * @handle_nmi:do handle PT PMI on this cpu, there's an active event + * @vmx_on:1 if VMX is ON on this cpu + */ +struct pt { + struct perf_output_handle handle; + struct pt_filters filters; + int handle_nmi; + int vmx_on; +}; + #if defined(CONFIG_PERF_EVENTS) && defined(CONFIG_CPU_SUP_INTEL) void cpu_emergency_stop_pt(void); extern u32 intel_pt_validate_hw_cap(enum pt_capabilities cap); -- 1.8.3.1
[PATCH 0/3] Inject a PMI for KVM Guest when ToPA buffer is filled
Each intel processor trace table of physical addresses (ToPA) entry has an INT bit. If this bit is set, the processor will signal a performance-monitoring interrupt (PMI) when the corresponding trace output region is filled. This patch set will inject a PMI for Intel Processor Trace when ToPA buffer is filled. Luwei Kang (3): perf/x86/intel/pt: Move pt structure to global header perf/x86/intel/pt: Inject PMI for KVM guest KVM: x86: Add support of clear Trace_ToPA_PMI status arch/x86/events/intel/pt.c | 12 +++- arch/x86/events/intel/pt.h | 38 - arch/x86/include/asm/intel_pt.h | 41 arch/x86/include/asm/kvm_host.h | 1 + arch/x86/include/asm/msr-index.h | 8 arch/x86/kvm/vmx/pmu_intel.c | 8 +++- arch/x86/kvm/x86.h | 6 ++ 7 files changed, 74 insertions(+), 40 deletions(-) -- 1.8.3.1
PCI LTR - ASPM handling upon suspend / resume cycle. Regression since 4.18
Hi, Lately we (Intel) have got a few bugs on suspend / resume. The complaint is that our device becomes unavailable after suspend / resume cycle. The bug on which we have most data is [1]. The original submitter reported a regression since commit 9ab105deb60fa76d66cae5548819b4e8703d2056: PCI/ASPM: Disable ASPM L1.2 Substate if we don't have LTR When in the ASPM L1.0 state (but not the PCI-PM L1.0 state), the most recent LTR value and the LTR_L1.2_THRESHOLD determines whether the link enters the L1.2 substate. If we don't have LTR enabled, prevent the use of ASPM L1.2. PCI-PM L1.2 may still be used because it doesn't depend on LTR_L1.2_THRESHOLD (see PCIe r4.0, sec 5.5.1). After this commit, L1.2 is disabled upon resume: L1SubCtl1: PCI-PM_L1.2+ PCI-PM_L1.1+ ASPM_L1.2- ASPM_L1.1+ T_CommonMode=0us LTR1.2_Threshold=163840ns Whereas it wasn't before this commit: L1SubCtl1: PCI-PM_L1.2+ PCI-PM_L1.1+ ASPM_L1.2+ ASPM_L1.1+ T_CommonMode=0us LTR1.2_Threshold=163840ns I am copying here an initial analysis by Bjorn (from [2]): 1) Linux has no support for saving/restoring the Max Latency values in the LTR Capability. This results in the latencies being zero after you resume, as you see in the lspci output. The device still *works* after resume, but power consumption should increase because the device is effectively requesting the best possible service, so we probably don't use the L1.2 state at all. 2) Linux has no support for programming the Max Latency values for hot- added devices. When using ACPI hotplug, firmware may do this, but for native PCIe hotplug (pciehp), the new device should again be requesting the best possible service, resulting in more power consumption than necessary. The platform is supposed to supply a _DSM method with information required to program these values Another user found another commit impacting his device after suspend / resume: commit 6f9db69ad93cd6ab77d5571cf748ff7cdcfb0285 ACPI / PM: Default to s2idle in all machines supporting LP S0 The Dell Venue Pro 7140 supports the Low Power S0 Idle state, but does not support any of the _DSM functions that the current heuristic checks for. Since suspend-to-mem can not be safely performed on this machine, and since the bitfield check can't cover this case, it is safer to enable s2idle by default by checking for the presence of the _DSM alone and removing the bitfield check. This user confirmed that using suspend-to-mem instead of suspend-to- idle works for him. A user contacted my privately to let me know that he has issues with devices from other vendors although I can't tell if the problem is the same or not. Note that this problem started from kernel 4.18. Thank you. [1] - https://bugzilla.kernel.org/show_bug.cgi?id=201469 [2] - https://bugzilla.kernel.org/show_bug.cgi?id=201469#c26
Re: [PATCH net-next] net: nci: remove set-but-not-used variable 'status'
From: YueHaibing Date: Tue, 29 Jan 2019 14:40:28 +0800 > gcc warning this: > net/nfc/nci/hci.c:373:5: > warning: variable 'status' set but not used [-Wunused-but-set-variable] > > It not used since commit d8cd37ed2fc8 ("NFC: nci: Fix improper > management of HCI return code"), so can be removed. > > Signed-off-by: YueHaibing I'll let the wireless/nfc folks pick this up.
Re: [RFC PATCH v2 08/10] rtc: bd70528: Initial support for ROHM bd70528 RTC
On Mon, Jan 28, 2019 at 01:26:56PM -0700, Jerry Hoemann wrote: > On Sat, Jan 26, 2019 at 08:30:24AM -0800, Guenter Roeck wrote: > > On 1/25/19 3:05 AM, Matti Vaittinen wrote: > > > +static int bd70528_set_wake(struct bd70528 *bd70528, > > > + int enable, int *old_state) > > > +{ > > > + int ret; > > > + unsigned int ctrl_reg; > > > + > > > + ret = regmap_read(bd70528->chip.regmap, BD70528_REG_WAKE_EN, _reg); > > > + if (ret) > > > + return ret; > > > + > > > + if (old_state) { > > > + if (ctrl_reg & BD70528_MASK_WAKE_EN) > > > + *old_state |= BD70528_WAKE_STATE_BIT; > > > + else > > > + *old_state &= ~BD70528_WAKE_STATE_BIT; > > > + > > > + if ((!enable) == (!(*old_state & BD70528_WAKE_STATE_BIT))) > > > + return 0; > > > > I think > > if (enable == !!(*old_state & BD70528_WAKE_STATE_BIT)) > > would be much better readable. Even if not, there are way too many () > > in the above conditional. > > > > The substitution is not equivalent to original. I think you mean: > > if (!!enable == !!(*old_state & BD70528_WAKE_STATE_BIT)) Thanks Jerry! Good catch! I originally wanted that all non-zero values of 'enable' would be 'true'. So maybe I just use the original approach but get rid of extra parenthesis which were pointed out by Guenter. if (!enable == !(*old_state & BD70528_WAKE_STATE_BIT)) should do it just fine, right? Br, Matti
Re: [PATCH] drivers: qcom: rpmh: use struct_size() in kzalloc()
On 1/28/19 11:26 PM, Amit Kucheria wrote: > On Mon, Dec 24, 2018 at 11:52 AM Gustavo A. R. Silva > wrote: >> >> One of the more common cases of allocation size calculations is finding >> the size of a structure that has a zero-sized array at the end, along >> with memory for some number of elements for that array. For example: >> >> struct foo { >> int stuff; >> void *entry[]; >> }; >> >> instance = kzalloc(sizeof(struct foo) + sizeof(void *) * count, GFP_KERNEL); >> >> Instead of leaving these open-coded and prone to type mistakes, we can >> now use the new struct_size() helper: >> >> instance = kzalloc(struct_size(instance, entry, count), GFP_KERNEL); >> >> This issue was detected with the help of Coccinelle. >> >> Signed-off-by: Gustavo A. R. Silva > > Reviewed-by: Amit Kucheria > Thanks, Amit. -- Gustavo >> --- >> drivers/soc/qcom/rpmh.c | 3 +-- >> 1 file changed, 1 insertion(+), 2 deletions(-) >> >> diff --git a/drivers/soc/qcom/rpmh.c b/drivers/soc/qcom/rpmh.c >> index c7beb6841289..12c057a0b325 100644 >> --- a/drivers/soc/qcom/rpmh.c >> +++ b/drivers/soc/qcom/rpmh.c >> @@ -362,8 +362,7 @@ int rpmh_write_batch(const struct device *dev, enum >> rpmh_state state, >> if (!count) >> return -EINVAL; >> >> - req = kzalloc(sizeof(*req) + count * sizeof(req->rpm_msgs[0]), >> - GFP_ATOMIC); >> + req = kzalloc(struct_size(req, rpm_msgs, count), GFP_ATOMIC); >> if (!req) >> return -ENOMEM; >> req->count = count; >> -- >> 2.17.0 >>
RE: linux-next: build warning after merge of the spi tree
Hi, > -Original Message- > From: Stephen Rothwell [mailto:s...@canb.auug.org.au] > Sent: Tuesday, January 29, 2019 7:33 AM > To: Mark Brown > Cc: Linux Next Mailing List ; Linux Kernel Mailing > List ; Yogesh Narayan Gaur > ; Frieder Schrempf > ; Boris Brezillon ; > Ashish Kumar > Subject: linux-next: build warning after merge of the spi tree > > Hi all, > > After merging the spi tree, today's linux-next build (KCONFIG_NAME) produced > this warning: > > WARNING: modpost: missing MODULE_LICENSE() in drivers/spi/spi-nxp-fspi.o > see include/linux/module.h for more information > Can someone help in pointing out that why above warning message is coming for mentioned commit. Below MODULE_LICENSE string is present in the above mentioned file, drivers/spi/spi-nxp-fspi.c. MODULE_LICENSE("GPL v2"); -- Regards, Yogesh Gaur > Introduced by commit > > a5356aef6a90 ("spi: spi-mem: Add driver for NXP FlexSPI controller") > > -- > Cheers, > Stephen Rothwell
[PATCH] dt-bindings: hwmon: Add lm75 documentation
Add dt-binding documentation for lm75 hwmon sensor. Currently documented for national,lm75 and st,stlm75 and rest might add when required. Signed-off-by: Jagan Teki --- Documentation/devicetree/bindings/hwmon/lm75.txt | 15 +++ 1 file changed, 15 insertions(+) create mode 100644 Documentation/devicetree/bindings/hwmon/lm75.txt diff --git a/Documentation/devicetree/bindings/hwmon/lm75.txt b/Documentation/devicetree/bindings/hwmon/lm75.txt new file mode 100644 index ..e384a3765f10 --- /dev/null +++ b/Documentation/devicetree/bindings/hwmon/lm75.txt @@ -0,0 +1,15 @@ +*LM75 hwmon sensor. + +Required properties: +- compatible: one of + "national,lm75" + "st,stlm75" + +- reg: I2C address + +Example: + +sensor@48 { + compatible = "st,stlm75"; + reg = <0x48>; +}; -- 2.18.0.321.gffc6fa0e3
[PATCH net-next] net: nci: remove set-but-not-used variable 'status'
gcc warning this: net/nfc/nci/hci.c:373:5: warning: variable 'status' set but not used [-Wunused-but-set-variable] It not used since commit d8cd37ed2fc8 ("NFC: nci: Fix improper management of HCI return code"), so can be removed. Signed-off-by: YueHaibing --- net/nfc/nci/hci.c | 10 ++ 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/net/nfc/nci/hci.c b/net/nfc/nci/hci.c index ddfc52a..4debba8 100644 --- a/net/nfc/nci/hci.c +++ b/net/nfc/nci/hci.c @@ -370,17 +370,11 @@ static void nci_hci_resp_received(struct nci_dev *ndev, u8 pipe, u8 result, struct sk_buff *skb) { struct nci_conn_info*conn_info; - u8 status = result; conn_info = ndev->hci_dev->conn_info; - if (!conn_info) { - status = NCI_STATUS_REJECTED; - goto exit; - } - - conn_info->rx_skb = skb; + if (conn_info) + conn_info->rx_skb = skb; -exit: nci_req_complete(ndev, NCI_STATUS_OK); } -- 2.7.0
Re: [PATCH v3 1/3] mfd: cros_ec: Add commands to control codec
On Mon, Jan 28, 2019 at 2:50 PM Lee Jones wrote: > > On Mon, 28 Jan 2019, Cheng-yi Chiang wrote: > > > Hi Lee, > > Could you please give Mark a tag so he can merge ? > > The later patch for cros_ec_codec driver is pending on it. > > Apologies for not getting back to you. > > I was waiting to see if my late PR would be merged. > > It was, which means the tag you were asking for is actually upstream. > > Any issues, let me know. Hi Lee, Thanks for the reply. I see. Yes it was merged in upstream: c1f3375be60c mfd: cros_ec: Add commands to control codec Hi Mark, I am not sure what would be the best practice for you. Would it work if you cherrypick this patch from upstream into your branch ? Thanks! > > -- > Lee Jones [李琼斯] > Linaro Services Technical Lead > Linaro.org │ Open source software for ARM SoCs > Follow Linaro: Facebook | Twitter | Blog
Re: [PATCH net] vhost: fix OOB in get_rx_bufs()
From: Jason Wang Date: Mon, 28 Jan 2019 15:05:05 +0800 > After batched used ring updating was introduced in commit e2b3b35eb989 > ("vhost_net: batch used ring update in rx"). We tend to batch heads in > vq->heads for more than one packet. But the quota passed to > get_rx_bufs() was not correctly limited, which can result a OOB write > in vq->heads. > > headcount = get_rx_bufs(vq, vq->heads + nvq->done_idx, > vhost_len, , vq_log, , > likely(mergeable) ? UIO_MAXIOV : 1); > > UIO_MAXIOV was still used which is wrong since we could have batched > used in vq->heads, this will cause OOB if the next buffer needs more > than 960 (1024 (UIO_MAXIOV) - 64 (VHOST_NET_BATCH)) heads after we've > batched 64 (VHOST_NET_BATCH) heads: ... > Fixing this by allocating UIO_MAXIOV + VHOST_NET_BATCH iovs for > vhost-net. This is done through set the limitation through > vhost_dev_init(), then set_owner can allocate the number of iov in a > per device manner. > > This fixes CVE-2018-16880. > > Fixes: e2b3b35eb989 ("vhost_net: batch used ring update in rx") > Signed-off-by: Jason Wang Applied and queued up for -stable, thanks!
RE: [PATCH] nfit: Fix nfit_intel_shutdown_status() command submission
> From: Dan Williams > Sent: Monday, January 28, 2019 9:22 PM > To: linux-nvd...@lists.01.org > Cc: sta...@vger.kernel.org; Dexuan Cui ; > linux-kernel@vger.kernel.org > Subject: [PATCH] nfit: Fix nfit_intel_shutdown_status() command submission > > The implementation is broken in all the ways the unit test did not touch: > > 1/ The local definition of in_buf and in_obj violated C99 initializer >expectations for zeroing. By only initializing 2 out of the three >struct members the compiler was free to zero-initialize the remaining >entry even though the aliased location in the union was initialized. > > 2/ The implementation made assumptions about the state of the 'smart' >payload after command execution that are satisfied by >acpi_nfit_ctl(), but not acpi_evaluate_dsm(). > > 3/ populate_shutdown_status() is skipped on Intel NVDIMMs due to the early >return for skipping the common _LS{I,R,W} enabling. > > 4/ The input length should be zero. > > This breakage was missed due to the unit test implementation only > testing the case where nfit_intel_shutdown_status() returns a valid > payload. > > Much of this complexity would be saved if acpi_nfit_ctl() could be used, but > that currently requires a 'struct nvdimm *' argument and one is not created > until later in the init process. The health result is needed before the device > is created because the payload gates whether the nmemX/nfit/dirty_shutdown > property is visible in sysfs. > > Cc: > Fixes: 0ead11181fe0 ("acpi, nfit: Collect shutdown status") > Reported-by: Dexuan Cui > Signed-off-by: Dan Williams > --- > drivers/acpi/nfit/core.c | 41 - > 1 file changed, 24 insertions(+), 17 deletions(-) > > diff --git a/drivers/acpi/nfit/core.c b/drivers/acpi/nfit/core.c > index e18ade5d74e9..0a49c57334cc 100644 > --- a/drivers/acpi/nfit/core.c > +++ b/drivers/acpi/nfit/core.c > @@ -1759,14 +1759,14 @@ static bool acpi_nvdimm_has_method(struct > acpi_device *adev, char *method) > > __weak void nfit_intel_shutdown_status(struct nfit_mem *nfit_mem) > { > + struct device *dev = _mem->adev->dev; > struct nd_intel_smart smart = { 0 }; > union acpi_object in_buf = { > - .type = ACPI_TYPE_BUFFER, > - .buffer.pointer = (char *) , > - .buffer.length = sizeof(smart), > + .buffer.type = ACPI_TYPE_BUFFER, > + .buffer.length = 0, > }; > union acpi_object in_obj = { > - .type = ACPI_TYPE_PACKAGE, > + .package.type = ACPI_TYPE_PACKAGE, > .package.count = 1, > .package.elements = _buf, > }; > @@ -1781,8 +1781,15 @@ __weak void nfit_intel_shutdown_status(struct > nfit_mem *nfit_mem) > return; > > out_obj = acpi_evaluate_dsm(handle, guid, revid, func, _obj); > - if (!out_obj) > + if (!out_obj || out_obj->type != ACPI_TYPE_BUFFER > + || out_obj->buffer.length < sizeof(smart)) { > + dev_dbg(dev->parent, "%s: failed to retrieve initial health\n", > + dev_name(dev)); > + ACPI_FREE(out_obj); > return; > + } > + memcpy(, out_obj->buffer.pointer, sizeof(smart)); > + ACPI_FREE(out_obj); > > if (smart.flags & ND_INTEL_SMART_SHUTDOWN_VALID) { > if (smart.shutdown_state) > @@ -1793,7 +1800,6 @@ __weak void nfit_intel_shutdown_status(struct > nfit_mem *nfit_mem) > set_bit(NFIT_MEM_DIRTY_COUNT, _mem->flags); > nfit_mem->dirty_shutdown = smart.shutdown_count; > } > - ACPI_FREE(out_obj); > } > > static void populate_shutdown_status(struct nfit_mem *nfit_mem) > @@ -1915,18 +1921,19 @@ static int acpi_nfit_add_dimm(struct > acpi_nfit_desc *acpi_desc, > | 1 << ND_CMD_SET_CONFIG_DATA; > if (family == NVDIMM_FAMILY_INTEL > && (dsm_mask & label_mask) == label_mask) > - return 0; > - > - if (acpi_nvdimm_has_method(adev_dimm, "_LSI") > - && acpi_nvdimm_has_method(adev_dimm, "_LSR")) { > - dev_dbg(dev, "%s: has _LSR\n", dev_name(_dimm->dev)); > - set_bit(NFIT_MEM_LSR, _mem->flags); > - } > + /* skip _LS{I,R,W} enabling */; > + else { > + if (acpi_nvdimm_has_method(adev_dimm, "_LSI") > + && acpi_nvdimm_has_method(adev_dimm, "_LSR")) { > + dev_dbg(dev, "%s: has _LSR\n", > dev_name(_dimm->dev)); > + set_bit(NFIT_MEM_LSR, _mem->flags); > + } > > - if (test_bit(NFIT_MEM_LSR, _mem->flags) > - && acpi_nvdimm_has_method(adev_dimm, "_LSW")) { > - dev_dbg(dev, "%s: has _LSW\n", dev_name(_dimm->dev)); > - set_bit(NFIT_MEM_LSW, _mem->flags); > + if (test_bit(NFIT_MEM_LSR, _mem->flags) > + &&
Re: [2/2] mfd: max77620: Add low battery monitor support
On 1/27/2019 10:54 PM, Billy Laws wrote: > >This patch adds PMIC configurations for low-battery > >monitoring by handling max77620 register CNFGGLBL1. > > > It might be an idea to add lbhyst configuration here and support using > custom lbdac values to specify a different cutoff point. Yeah this patch doesn't have support to program LBHYST & LBDAC because according to our experiences, we don't have requirement to modify them when low battery monitor support added. I think we can create a new patch to support these 2 fields in the future when we really need them. Or you can create a patch if you have requirement for them, is this OK to you Billy? Mark > > See: https://datasheetspdf.com/pdf-file/924230/Maxim/MAX8698C/1 pg 46 > >Signed-off-by: Laxman Dewangan > >Signed-off-by: Venkat Reddy Talla > >Signed-off-by: Mark Zhang > >--- > > drivers/mfd/max77620.c | 57 +- > > 1 file changed, 56 insertions(+), 1 deletion(-) > > > >diff --git a/drivers/mfd/max77620.c b/drivers/mfd/max77620.c > >index f58143103185..9e50d145afd8 100644 > >--- a/drivers/mfd/max77620.c > >+++ b/drivers/mfd/max77620.c > >@@ -474,6 +474,57 @@ static int > max77620_init_backup_battery_charging(struct max77620_chip *chip) > > return ret; > > } > > > >+static int max77620_init_low_battery_monitor(struct max77620_chip *chip) > >+{ > >+ struct device *dev = chip->dev; > >+ struct device_node *np; > >+ bool pval; > >+ u8 mask = 0; > >+ u8 val = 0; > >+ int ret; > >+ > >+ np = of_get_child_by_name(dev->of_node, "low-battery-monitor"); > >+ if (!np) { > >+ dev_info(dev, "Low battery monitoring support disabled\n"); > >+ return 0; > >+ } > >+ > >+ pval = of_property_read_bool(np, "maxim,low-battery-dac-enable"); > >+ if (pval) { > >+ mask |= MAX77620_CNFGGLBL1_LBDAC_EN; > >+ val |= MAX77620_CNFGGLBL1_LBDAC_EN; > >+ } > >+ > >+ pval = of_property_read_bool(np, "maxim,low-battery-dac-disable"); > >+ if (pval) > >+ mask |= MAX77620_CNFGGLBL1_LBDAC_EN; > >+ > >+ pval = of_property_read_bool(np, "maxim,low-battery-shutdown-enable"); > >+ if (pval) { > >+ mask |= MAX77620_CNFGGLBL1_MPPLD; > >+ val |= MAX77620_CNFGGLBL1_MPPLD; > >+ } > >+ > >+ pval = of_property_read_bool(np, "maxim,low-battery-shutdown-disable"); > >+ if (pval) > >+ mask |= MAX77620_CNFGGLBL1_MPPLD; > >+ > >+ pval = of_property_read_bool(np, "maxim,low-battery-reset-enable"); > >+ if (pval) { > >+ mask |= MAX77620_CNFGGLBL1_LBRSTEN; > >+ val |= MAX77620_CNFGGLBL1_LBRSTEN; > >+ } > >+ > >+ pval = of_property_read_bool(np, "maxim,low-battery-reset-disable"); > >+ if (pval) > >+ mask |= MAX77620_CNFGGLBL1_LBRSTEN; > >+ > >+ ret = regmap_update_bits(chip->rmap, MAX77620_REG_CNFGGLBL1, mask, val); > >+ if (ret < 0) > >+ dev_err(dev, "Reg CNFGGLBL1 update failed: %d\n", ret); > >+ return ret; > >+} > >+ > > static int max77620_read_es_version(struct max77620_chip *chip) > > { > > unsigned int val; > >@@ -563,7 +614,11 @@ static int max77620_probe(struct i2c_client *client, > > if (ret < 0) > > return ret; > > > >- ret = devm_mfd_add_devices(chip->dev, PLATFORM_DEVID_NONE, > >+ ret = max77620_init_low_battery_monitor(chip); > >+ if (ret < 0) > >+ return ret; > >+ > >+ ret = devm_mfd_add_devices(chip->dev, PLATFORM_DEVID_NONE, > > mfd_cells, n_mfd_cells, NULL, 0, > > regmap_irq_get_domain(chip->top_irq_data)); > > if (ret < 0) { >
[PATCH] dt-bindings: Add vendor prefix for techstar
Add vendor prefix for techstar, known as Shenzhen Techstar Electronics Co., Ltd. a known producer for LCD modules. Signed-off-by: Jagan Teki --- Documentation/devicetree/bindings/vendor-prefixes.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/Documentation/devicetree/bindings/vendor-prefixes.txt b/Documentation/devicetree/bindings/vendor-prefixes.txt index 88dcdc04c8c9..2aa2688b21a5 100644 --- a/Documentation/devicetree/bindings/vendor-prefixes.txt +++ b/Documentation/devicetree/bindings/vendor-prefixes.txt @@ -392,6 +392,7 @@ tcl Toby Churchill Ltd. technexion TechNexion technologicTechnologic Systems tempo Tempo Semiconductor +techstar Shenzhen Techstar Electronics Co., Ltd. terasicTerasic Inc. thine THine Electronics, Inc. ti Texas Instruments -- 2.18.0.321.gffc6fa0e3
Re: [PATCH 4/5] phy: tegra: xusb: Add support for power supplies
Thanks Thierry. Reviewed-by: JC Kuo On 1/28/19 4:00 PM, Thierry Reding wrote: On Mon, Jan 28, 2019 at 03:22:09PM +0800, jckuo wrote: Hi Thierry, I think any non-zero return value of regulator_bulk_enable()/devm_regulator_bulk_get() means error. Thanks, JC Theoretically I think only regulator_bulk_enable() could return a positive value, but even so it never will in practice because all of the regulator_enable() (see _regulator_enable()) calls will only ever return negative error codes. I can change this and resend if you have strong concerns about this possibly missing legitimate error cases. Thierry On 1/25/19 7:25 PM, Thierry Reding wrote: From: Thierry Reding Support enabling various supplies needed to provide power to the PLLs and logic used to drive the USB, PCI and SATA pads. Signed-off-by: Thierry Reding --- drivers/phy/tegra/xusb.c | 34 +- drivers/phy/tegra/xusb.h | 5 + 2 files changed, 38 insertions(+), 1 deletion(-) diff --git a/drivers/phy/tegra/xusb.c b/drivers/phy/tegra/xusb.c index 57a2d08ef6da..e510629f4f1c 100644 --- a/drivers/phy/tegra/xusb.c +++ b/drivers/phy/tegra/xusb.c @@ -864,6 +864,7 @@ static int tegra_xusb_padctl_probe(struct platform_device *pdev) struct tegra_xusb_padctl *padctl; const struct of_device_id *match; struct resource *res; + unsigned int i; int err; /* for backwards compatibility with old device trees */ @@ -901,14 +902,38 @@ static int tegra_xusb_padctl_probe(struct platform_device *pdev) goto remove; } + padctl->supplies = devm_kcalloc(>dev, padctl->soc->num_supplies, + sizeof(*padctl->supplies), GFP_KERNEL); + if (!padctl->supplies) { + err = -ENOMEM; + goto remove; + } + + for (i = 0; i < padctl->soc->num_supplies; i++) + padctl->supplies[i].supply = padctl->soc->supply_names[i]; + + err = devm_regulator_bulk_get(>dev, padctl->soc->num_supplies, + padctl->supplies); + if (err < 0) { + dev_err(>dev, "failed to get regulators: %d\n", err); + goto remove; + } + err = reset_control_deassert(padctl->rst); if (err < 0) goto remove; + err = regulator_bulk_enable(padctl->soc->num_supplies, + padctl->supplies); + if (err < 0) { + dev_err(>dev, "failed to enable supplies: %d\n", err); + goto reset; + } + err = tegra_xusb_setup_pads(padctl); if (err < 0) { dev_err(>dev, "failed to setup pads: %d\n", err); - goto reset; + goto power_down; } err = tegra_xusb_setup_ports(padctl); @@ -921,6 +946,8 @@ static int tegra_xusb_padctl_probe(struct platform_device *pdev) remove_pads: tegra_xusb_remove_pads(padctl); +power_down: + regulator_bulk_disable(padctl->soc->num_supplies, padctl->supplies); reset: reset_control_assert(padctl->rst); remove: @@ -936,6 +963,11 @@ static int tegra_xusb_padctl_remove(struct platform_device *pdev) tegra_xusb_remove_ports(padctl); tegra_xusb_remove_pads(padctl); + err = regulator_bulk_disable(padctl->soc->num_supplies, +padctl->supplies); + if (err < 0) + dev_err(>dev, "failed to disable supplies: %d\n", err); + err = reset_control_assert(padctl->rst); if (err < 0) dev_err(>dev, "failed to assert reset: %d\n", err); diff --git a/drivers/phy/tegra/xusb.h b/drivers/phy/tegra/xusb.h index bb60fc09c752..5d5d22f6cb41 100644 --- a/drivers/phy/tegra/xusb.h +++ b/drivers/phy/tegra/xusb.h @@ -370,6 +370,9 @@ struct tegra_xusb_padctl_soc { } ports; const struct tegra_xusb_padctl_ops *ops; + + const char * const *supply_names; + unsigned int num_supplies; }; struct tegra_xusb_padctl { @@ -393,6 +396,8 @@ struct tegra_xusb_padctl { unsigned int enable; struct clk *clk; + + struct regulator_bulk_data *supplies; }; static inline void padctl_writel(struct tegra_xusb_padctl *padctl, u32 value,
[PATCH] kernel/bpf/cgroup.c - clean up kerneldoc warnings
Building with W=1 reveals some bitrot CC kernel/bpf/cgroup.o kernel/bpf/cgroup.c:238: warning: Function parameter or member 'flags' not described in '__cgroup_bpf_attach' kernel/bpf/cgroup.c:367: warning: Function parameter or member 'unused_flags' not described in '__cgroup_bpf_detach' Add a kerneldoc line for 'flags'. Fixing the warning for 'unused_flags' is best approached by removing the unused parameter on the function call. Signed-off-by: Valdis Kletnieks diff --git a/include/linux/bpf-cgroup.h b/include/linux/bpf-cgroup.h index 588dd5f0bd85..695b2a880d9a 100644 --- a/include/linux/bpf-cgroup.h +++ b/include/linux/bpf-cgroup.h @@ -78,7 +78,7 @@ int cgroup_bpf_inherit(struct cgroup *cgrp); int __cgroup_bpf_attach(struct cgroup *cgrp, struct bpf_prog *prog, enum bpf_attach_type type, u32 flags); int __cgroup_bpf_detach(struct cgroup *cgrp, struct bpf_prog *prog, - enum bpf_attach_type type, u32 flags); + enum bpf_attach_type type); int __cgroup_bpf_query(struct cgroup *cgrp, const union bpf_attr *attr, union bpf_attr __user *uattr); diff --git a/kernel/bpf/cgroup.c b/kernel/bpf/cgroup.c index ab612fe9862f..d78cfec5807d 100644 --- a/kernel/bpf/cgroup.c +++ b/kernel/bpf/cgroup.c @@ -230,6 +230,7 @@ static int update_effective_progs(struct cgroup *cgrp, * @cgrp: The cgroup which descendants to traverse * @prog: A program to attach * @type: Type of attach operation + * @flags: Option flags * * Must be called with cgroup_mutex held. */ @@ -363,7 +364,7 @@ int __cgroup_bpf_attach(struct cgroup *cgrp, struct bpf_prog *prog, * Must be called with cgroup_mutex held. */ int __cgroup_bpf_detach(struct cgroup *cgrp, struct bpf_prog *prog, - enum bpf_attach_type type, u32 unused_flags) + enum bpf_attach_type type) { struct list_head *progs = >bpf.progs[type]; enum bpf_cgroup_storage_type stype; diff --git a/kernel/cgroup/cgroup.c b/kernel/cgroup/cgroup.c index 6d03a27918f4..9802ab424397 100644 --- a/kernel/cgroup/cgroup.c +++ b/kernel/cgroup/cgroup.c @@ -6059,7 +6059,7 @@ int cgroup_bpf_detach(struct cgroup *cgrp, struct bpf_prog *prog, int ret; mutex_lock(_mutex); - ret = __cgroup_bpf_detach(cgrp, prog, type, flags); + ret = __cgroup_bpf_detach(cgrp, prog, type); mutex_unlock(_mutex); return ret; }
Re: linux-next: build failure after merge of the net-next tree
From: Stephen Rothwell Date: Tue, 29 Jan 2019 16:17:42 +1100 > I have added the following fix patch for today: > > From: Stephen Rothwell > Date: Tue, 29 Jan 2019 16:13:08 +1100 > Subject: [PATCH] enetc: include linux/vmalloc.h for vzalloc etc > > Fixes: d4fd0404c1c9 ("enetc: Introduce basic PF and VF ENETC ethernet > drivers") > Signed-off-by: Stephen Rothwell Applied to net-next.
Re: [PATCH 00/13] hisi_sas: Misc fixes and other more minor patches
John, > This series includes a misc assortment of fixes found during testing. > > Also includes is some debugfs tidy-up and a patch missed from original > upstreaming. Applied to 5.1/scsi-queue, thanks. -- Martin K. Petersen Oracle Linux Engineering
Re: [PATCH 1/2] mm: introduce put_user_page*(), placeholder versions
On 1/28/19 5:23 PM, Jerome Glisse wrote: On Mon, Jan 28, 2019 at 04:22:16PM -0800, John Hubbard wrote: On 1/23/19 11:04 AM, Jerome Glisse wrote: On Wed, Jan 23, 2019 at 07:02:30PM +0100, Jan Kara wrote: On Tue 22-01-19 11:46:13, Jerome Glisse wrote: On Tue, Jan 22, 2019 at 04:24:59PM +0100, Jan Kara wrote: On Thu 17-01-19 10:17:59, Jerome Glisse wrote: On Thu, Jan 17, 2019 at 10:30:47AM +0100, Jan Kara wrote: On Wed 16-01-19 08:08:14, Jerome Glisse wrote: On Wed, Jan 16, 2019 at 12:38:19PM +0100, Jan Kara wrote: On Tue 15-01-19 09:07:59, Jan Kara wrote: Agreed. So with page lock it would actually look like: get_page_pin() lock_page(page); wait_for_stable_page(); atomic_add(>_refcount, PAGE_PIN_BIAS); unlock_page(page); And if we perform page_pinned() check under page lock, then if page_pinned() returned false, we are sure page is not and will not be pinned until we drop the page lock (and also until page writeback is completed if needed). After some more though, why do we even need wait_for_stable_page() and lock_page() in get_page_pin()? During writepage page_mkclean() will write protect all page tables. So there can be no new writeable GUP pins until we unlock the page as all such GUPs will have to first go through fault and ->page_mkwrite() handler. And that will wait on page lock and do wait_for_stable_page() for us anyway. Am I just confused? Yeah with page lock it should synchronize on the pte but you still need to check for writeback iirc the page is unlocked after file system has queue up the write and thus the page can be unlock with write back pending (and PageWriteback() == trye) and i am not sure that in that states we can safely let anyone write to that page. I am assuming that in some case the block device also expect stable page content (RAID stuff). So the PageWriteback() test is not only for racing page_mkclean()/ test_set_page_writeback() and GUP but also for pending write back. But this is prevented by wait_for_stable_page() that is already present in ->page_mkwrite() handlers. Look: ->writepage() /* Page is locked here */ clear_page_dirty_for_io(page) page_mkclean(page) -> page tables get writeprotected /* The following line will be added by our patches */ if (page_pinned(page)) -> bounce TestClearPageDirty(page) set_page_writeback(page); unlock_page(page); ...submit_io... IRQ - IO completion end_page_writeback() So if GUP happens before page_mkclean() writeprotects corresponding PTE (and these two actions are synchronized on the PTE lock), page_pinned() will see the increment and report the page as pinned. If GUP happens after page_mkclean() writeprotects corresponding PTE, it will fault: handle_mm_fault() do_wp_page() wp_page_shared() do_page_mkwrite() ->page_mkwrite() - that is block_page_mkwrite() or iomap_page_mkwrite() or whatever filesystem provides lock_page(page) ... prepare page ... wait_for_stable_page(page) -> this blocks until IO completes if someone cares about pages not being modified while under IO. The case i am worried is GUP see pte with write flag set but has not lock the page yet (GUP is get pte first, then pte to page then lock page), then it locks the page but the lock page can make it wait for a racing page_mkclean()...write back that have not yet write protected the pte the GUP just read. So by the time GUP has the page locked the pte it read might no longer have the write flag set. Hence why you need to also check for write back after taking the page lock. Alternatively you could recheck the pte after a successful try_lock on the page. This isn't really possible. GUP does: get_user_pages() ... follow_page_mask() ... follow_page_pte() ptep = pte_offset_map_lock() check permissions and page sanity if (flags & FOLL_GET) get_page(page); -> this would become atomic_add(>_refcount, PAGE_PIN_BIAS); pte_unmap_unlock(ptep, ptl); page_mkclean() on the other hand grabs the same pte lock to change the pte to write-protected. So after page_mkclean() has modified the PTE we are racing on for access, we are sure to either see increased _refcount or get page fault from GUP. If we see increased _refcount, we bounce the page and are fine. If GUP faults, we will wait for page lock (so wait until page is prepared for IO and has PageWriteback set) while handling the fault, then enter ->page_mkwrite, which will do wait_for_stable_page() -> wait for outstanding writeback to complete. So I still conclude - no need for page lock in the GUP path at all AFAICT. In fact we rely on the very same page fault vs page writeback synchronization for normal user faults as well. And normal user mmap access is even nastier than GUP access because the CPU reads page tables without taking PTE lock. For the "slow" GUP path you are right you
[PATCH] parport_pc: fix find_superio io compare code, should use equal test.
From: QiaoChong Fixes: 181bf1e815a2a("parport_pc: clean up the modified while loops using for"). The code find_superio should test superio[i].io == p->base then find out superio, fix it. Signed-off-by: QiaoChong --- drivers/parport/parport_pc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/parport/parport_pc.c b/drivers/parport/parport_pc.c index 9c8249f744792..6296dbb83d470 100644 --- a/drivers/parport/parport_pc.c +++ b/drivers/parport/parport_pc.c @@ -1377,7 +1377,7 @@ static struct superio_struct *find_superio(struct parport *p) { int i; for (i = 0; i < NR_SUPERIOS; i++) - if (superios[i].io != p->base) + if (superios[i].io == p->base) return [i]; return NULL; } -- 2.17.0
[PATCH 0/3] Add cpufreq and cci devfreq for mt8183
MT8183 supports CPU DVFS and CCI DVFS, and LITTLE cpus and CCI are in the same voltage domain. So, this series is to add drivers to handle the voltage coupling between CPU and CCI DVFS. Andrew-sh.Cheng (3): cpufreq: mediatek: add mt8183 cpufreq support dt-bindings: devfreq: add compatible for mt8183 cci devfreq devfreq: add mediatek cci devfreq .../bindings/devfreq/mt8183-cci-devfreq.txt| 19 ++ drivers/cpufreq/cpufreq-dt-platdev.c | 1 + drivers/cpufreq/mediatek-cpufreq.c | 7 +- drivers/devfreq/Kconfig| 9 + drivers/devfreq/Makefile | 1 + drivers/devfreq/mt8183-cci-devfreq.c | 224 + 6 files changed, 260 insertions(+), 1 deletion(-) create mode 100644 Documentation/devicetree/bindings/devfreq/mt8183-cci-devfreq.txt create mode 100644 drivers/devfreq/mt8183-cci-devfreq.c -- 1.8.1.1.dirty
Re: [PATCH] pcmcia: Remove unnecessary parentheses
Nathan, >> drivers/scsi/pcmcia/nsp_cs.c:1137:27: warning: equality comparison with >> extraneous parentheses [-Wparentheses-equality] >> if ((tmpSC->SCp.Message == MSG_COMMAND_COMPLETE)) { >> ~~~^~~ Applied to 5.1/scsi-queue. -- Martin K. Petersen Oracle Linux Engineering
Re: [PATCH] scsi: nsp32: Remove unnecessary self assignment in nsp32_set_sync_entry
Nathan, >> drivers/scsi/nsp32.c:2444:14: warning: explicitly assigning value of >> variable of type 'unsigned char' to itself [-Wself-assign] >> offset = offset; >> ~~ ^ Applied to 5.1/scsi-queue. Thanks. -- Martin K. Petersen Oracle Linux Engineering
Re: [PATCH net] vhost: fix OOB in get_rx_bufs()
On Mon, Jan 28, 2019 at 03:05:05PM +0800, Jason Wang wrote: > After batched used ring updating was introduced in commit e2b3b35eb989 > ("vhost_net: batch used ring update in rx"). We tend to batch heads in > vq->heads for more than one packet. But the quota passed to > get_rx_bufs() was not correctly limited, which can result a OOB write > in vq->heads. > > headcount = get_rx_bufs(vq, vq->heads + nvq->done_idx, > vhost_len, , vq_log, , > likely(mergeable) ? UIO_MAXIOV : 1); > > UIO_MAXIOV was still used which is wrong since we could have batched > used in vq->heads, this will cause OOB if the next buffer needs more > than 960 (1024 (UIO_MAXIOV) - 64 (VHOST_NET_BATCH)) heads after we've > batched 64 (VHOST_NET_BATCH) heads: > > = > BUG kmalloc-8k (Tainted: GB): Redzone overwritten > - > > INFO: 0xfd93b7a2-0xf0713384. First byte 0xa9 instead of 0xcc > INFO: Allocated in alloc_pd+0x22/0x60 age=3933677 cpu=2 pid=2674 > kmem_cache_alloc_trace+0xbb/0x140 > alloc_pd+0x22/0x60 > gen8_ppgtt_create+0x11d/0x5f0 > i915_ppgtt_create+0x16/0x80 > i915_gem_create_context+0x248/0x390 > i915_gem_context_create_ioctl+0x4b/0xe0 > drm_ioctl_kernel+0xa5/0xf0 > drm_ioctl+0x2ed/0x3a0 > do_vfs_ioctl+0x9f/0x620 > ksys_ioctl+0x6b/0x80 > __x64_sys_ioctl+0x11/0x20 > do_syscall_64+0x43/0xf0 > entry_SYSCALL_64_after_hwframe+0x44/0xa9 > INFO: Slab 0xd13e87af objects=3 used=3 fp=0x (null) > flags=0x2010201 > INFO: Object 0x03278802 @offset=17064 fp=0xe2e6652b > > Fixing this by allocating UIO_MAXIOV + VHOST_NET_BATCH iovs for > vhost-net. This is done through set the limitation through > vhost_dev_init(), then set_owner can allocate the number of iov in a > per device manner. > > This fixes CVE-2018-16880. > > Fixes: e2b3b35eb989 ("vhost_net: batch used ring update in rx") > Signed-off-by: Jason Wang > --- > drivers/vhost/net.c | 3 ++- > drivers/vhost/scsi.c | 2 +- > drivers/vhost/vhost.c | 7 --- > drivers/vhost/vhost.h | 4 +++- > drivers/vhost/vsock.c | 2 +- > 5 files changed, 11 insertions(+), 7 deletions(-) No change in the scsi and vsock cases. I haven't reviewed the net case. Acked-by: Stefan Hajnoczi signature.asc Description: PGP signature
Re: [PATCH 0/2] scsi: trivial header search path fixups
Masahiro, > My main motivation is to get rid of crappy header search path manipulation > from Kbuild core. > > Before that, I want to do as many treewide cleanups as possible. Applied to 5.1/scsi-queue, thanks! -- Martin K. Petersen Oracle Linux Engineering
Re: [PATCH] pinctrl: mediatek: fix dependencies for PINCTRL_MT76XX
On 1/29/19 6:02 AM, Sean Wang wrote: > On Mon, Jan 28, 2019 at 2:35 PM Dmitry Voytik wrote: >> >> How to reproduce the problem: >> $ make tinyconfig >> $ make menuconfig >> then enable: >> CONFIG_COMPILE_TEST=y >> CONFIG_PINCTRL=y >> and any of these: >> CONFIG_PINCTRL_MT7622=y >> CONFIG_PINCTRL_MT7629=y >> CONFIG_PINCTRL_MT7623=y >> >> This combination causes build failure. >> >> Fix the problem by making PINCTRL_MT76XX to depend on CONFIG_OF=y. >> >> Signed-off-by: Dmitry Voytik >> --- >> drivers/pinctrl/mediatek/Kconfig | 3 +++ >> 1 file changed, 3 insertions(+) >> >> diff --git a/drivers/pinctrl/mediatek/Kconfig >> b/drivers/pinctrl/mediatek/Kconfig >> index 1817786ab6aa..a005cbccb4f7 100644 >> --- a/drivers/pinctrl/mediatek/Kconfig >> +++ b/drivers/pinctrl/mediatek/Kconfig >> @@ -45,12 +45,14 @@ config PINCTRL_MT2701 >> config PINCTRL_MT7623 >> bool "Mediatek MT7623 pin control with generic binding" >> depends on MACH_MT7623 || COMPILE_TEST >> + depends on OF >> default MACH_MT7623 >> select PINCTRL_MTK_MOORE >> >> config PINCTRL_MT7629 >> bool "Mediatek MT7629 pin control" >> depends on MACH_MT7629 || COMPILE_TEST >> + depends on OF >> default MACH_MT7629 >> select PINCTRL_MTK_MOORE >> >> @@ -92,6 +94,7 @@ config PINCTRL_MT6797 >> >> config PINCTRL_MT7622 >> bool "MediaTek MT7622 pin control" >> + depends on OF >> depends on ARM64 || COMPILE_TEST >> default ARM64 && ARCH_MEDIATEK >> select PINCTRL_MTK_MOORE >> -- >> 2.20.1 >> > > It seems the commit 2d2d478576d71000b29c52668c5712c825ee9af8 already > fixed the problem or is there something I'm missing? > Opps, sorry. Should have checked linux-pinctrl.git. Sorry for spamming. BR, Dmitry.
Re: [PATCH] netfilter: nat: Update comment of get_unique_tuple
Friendly ping... On 2019/1/10 21:06, YueHaibing wrote: > Replace outdated __ip_conntrack_confirm in comment. > > Signed-off-by: YueHaibing > --- > net/netfilter/nf_nat_core.c | 3 ++- > 1 file changed, 2 insertions(+), 1 deletion(-) > > diff --git a/net/netfilter/nf_nat_core.c b/net/netfilter/nf_nat_core.c > index d159e9e..f54a8db 100644 > --- a/net/netfilter/nf_nat_core.c > +++ b/net/netfilter/nf_nat_core.c > @@ -460,7 +460,8 @@ static void nf_nat_l4proto_unique_tuple(struct > nf_conntrack_tuple *tuple, > * and NF_INET_LOCAL_OUT, we change the destination to map into the > * range. It might not be possible to get a unique tuple, but we try. > * At worst (or if we race), we will end up with a final duplicate in > - * __ip_conntrack_confirm and drop the packet. */ > + * __nf_conntrack_confirm and drop the packet. > + */ > static void > get_unique_tuple(struct nf_conntrack_tuple *tuple, >const struct nf_conntrack_tuple *orig_tuple, >
Re: [PATCH v5 2/9] cpufreq: Auto-register the driver as a thermal cooling device if asked
On Tue, Jan 29, 2019 at 11:16 AM Amit Kucheria wrote: > > On Tue, Jan 29, 2019 at 11:06 AM Viresh Kumar wrote: > > > > On 29-01-19, 10:25, Amit Kucheria wrote: > > > All cpufreq drivers do similar things to register as a cooling device. > > > Provide a cpufreq driver flag so drivers can just ask the cpufreq core > > > to register the cooling device on their behalf. This allows us to get > > > rid of duplicated code in the drivers. > > > > > > In order to allow this, we add a struct thermal_cooling_device pointer > > > to struct cpufreq_policy so that drivers don't need to store it in a > > > private data structure. > > > > > > Suggested-by: Stephen Boyd > > > Suggested-by: Viresh Kumar > > > Signed-off-by: Amit Kucheria > > > Reviewed-by: Matthias Kaehlcke > > > Tested-by: Matthias Kaehlcke > > > Acked-by: Viresh Kumar > > > --- > > > drivers/cpufreq/cpufreq.c | 13 + > > > include/linux/cpufreq.h | 9 + > > > 2 files changed, 22 insertions(+) > > > > > > diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c > > > index e35a886e00bc..0f9b50d3ee91 100644 > > > --- a/drivers/cpufreq/cpufreq.c > > > +++ b/drivers/cpufreq/cpufreq.c > > > @@ -19,6 +19,7 @@ > > > > > > #include > > > #include > > > +#include > > > #include > > > #include > > > #include > > > @@ -1318,6 +1319,11 @@ static int cpufreq_online(unsigned int cpu) > > > if (cpufreq_driver->ready) > > > cpufreq_driver->ready(policy); > > > > > > +#if IS_ENABLED(CONFIG_CPU_THERMAL) > > > + if (cpufreq_driver->flags & CPUFREQ_IS_COOLING_DEV) > > > + policy->cdev = of_cpufreq_cooling_register(policy); > > > +#endif > > > > I am not sure if Rafael wanted it this way but maybe something like this: > > > > if (IS_ENABLED(CONFIG_CPU_THERMAL) && > > cpufreq_driver->flags & CPUFREQ_IS_COOLING_DEV)) > > policy->cdev = of_cpufreq_cooling_register(policy); > > > > We never wanted ifdef hackery to be in there :) > > OK, that makes more sense. Should I just send out a fixup patch or the > entire series? FWIW, I checked drivers/cpufreq and drivers/thermal before converting over and there is a mixed use of #if IS_ENABLED and if(IS_ENABLED). Perhaps we should clean it up?
Re: [PATCH -next] scsi: fnic: Remove set but not used variable 'vdev'
YueHaibing, > Fixes gcc '-Wunused-but-set-variable' warning: > > drivers/scsi/fnic/vnic_wq.c: In function 'vnic_wq_alloc_bufs': > drivers/scsi/fnic/vnic_wq.c:50:19: warning: > variable 'vdev' set but not used [-Wunused-but-set-variable] > > drivers/scsi/fnic/vnic_rq.c: In function 'vnic_rq_alloc_bufs': > drivers/scsi/fnic/vnic_rq.c:30:19: warning: > variable 'vdev' set but not used [-Wunused-but-set-variable] Applied to 5.1/scsi-queue, thanks! -- Martin K. Petersen Oracle Linux Engineering
linux-next: Tree for Jan 29
Hi all, Changes since 20190125: The vfs tree still had its build failure for which I applied a patch. The net-next tree gained a build failure for which I applied a patch. The mtd tree gained a conflict against Linus' tree. The char-misc tree gained conflicts against the qcom tree. Non-merge commits (relative to Linus' tree): 4055 4580 files changed, 177213 insertions(+), 110378 deletions(-) I have created today's linux-next tree at git://git.kernel.org/pub/scm/linux/kernel/git/next/linux-next.git (patches at http://www.kernel.org/pub/linux/kernel/next/ ). If you are tracking the linux-next tree using git, you should not use "git pull" to do so as that will try to merge the new linux-next release with the old one. You should use "git fetch" and checkout or reset to the new master. You can see which trees have been included by looking in the Next/Trees file in the source. There are also quilt-import.log and merge.log files in the Next directory. Between each merge, the tree was built with a ppc64_defconfig for powerpc, an allmodconfig for x86_64, a multi_v7_defconfig for arm and a native build of tools/perf. After the final fixups (if any), I do an x86_64 modules_install followed by builds for x86_64 allnoconfig, powerpc allnoconfig (32 and 64 bit), ppc44x_defconfig, allyesconfig and pseries_le_defconfig and i386, sparc and sparc64 defconfig. And finally, a simple boot test of the powerpc pseries_le_defconfig kernel in qemu (with and without kvm enabled). Below is a summary of the state of the merge. I am currently merging 296 trees (counting Linus' and 69 trees of bug fix patches pending for the current merge release). Stats about the size of the tree over time can be seen at http://neuling.org/linux-next-size.html . Status of my local build tests will be at http://kisskb.ellerman.id.au/linux-next . If maintainers want to give advice about cross compilers/configs that work, we are always open to add more builds. Thanks to Randy Dunlap for doing many randconfig builds. And to Paul Gortmaker for triage and bug fixes. -- Cheers, Stephen Rothwell $ git checkout master $ git reset --hard stable Merging origin/master (4aa9fc2a435a Revert "mm, memory_hotplug: initialize struct pages for the full memory section") Merging fixes/master (d8d0c3a7f601 x86/syscalls: Mark expected switch fall-throughs) Merging kbuild-current/fixes (7c2614bf7a1f Merge tag '5.0-rc3-smb3-fixes' of git://git.samba.org/sfrench/cifs-2.6) Merging arc-current/for-curr (18094d0b55d5 ARC: DTB: [scripted] fix node name and address spelling) Merging arm-current/fixes (c2a3831df6dc ARM: 8816/1: dma-mapping: fix potential uninitialized return) Merging arm64-fixes/for-next/fixes (7fa1e2e6afa7 kasan, arm64: remove redundant ARCH_SLAB_MINALIGN define) Merging m68k-current/for-linus (bed1369f5190 m68k: Fix memblock-related crashes) Merging powerpc-fixes/fixes (7bea7ac0ca01 powerpc/syscalls: Fix syscall tracing) Merging sparc/master (b71acb0e3721 Merge branch 'linus' of git://git.kernel.org/pub/scm/linux/kernel/git/herbert/crypto-2.6) Merging fscrypt-current/for-stable (ae64f9bd1d36 Linux 4.15-rc2) Merging net/master (bfe2599dd2f9 Merge branch 'qed-Bug-fixes') Merging bpf/master (c9e4576743ee bpf: sock recvbuff must be limited by rmem_max in bpf_setsockopt()) Merging ipsec/master (6fb6e6371f8c net: dsa: mv88e6xxx: Fix serdes irq setup going recursive) Merging netfilter/master (206b8cc514d7 netfilter: ipt_CLUSTERIP: fix warning unused variable cn) Merging ipvs/master (b2e3d68d1251 netfilter: nft_compat: destroy function must not have side effects) Merging wireless-drivers/master (13e62626c578 wlcore: sdio: Fixup power on/off sequence) Merging mac80211/master (93183bdbe73b cfg80211: extend range deviation for DMG) Merging rdma-fixes/for-rc (951d01b96f17 IB/mlx5: Fix how advise_mr() launches async work) Merging sound-current/for-linus (e190161f96b8 ALSA: pcm: Fix tight loop of OSS capture stream) Merging sound-asoc-fixes/for-linus (dfe189574409 Merge branch 'asoc-5.0' into asoc-linus) Merging regmap-fixes/for-linus (49a57857aeea Linux 5.0-rc3) Merging regulator-fixes/for-linus (45fff6c2b44f Merge branch 'regulator-5.0' into regulator-linus) Merging spi-fixes/for-linus (e8012472356f Merge branch 'spi-5.0' into spi-linus) Merging pci-current/for-linus (0084379b5a13 Merge remote-tracking branch 'lorenzo/pci/controller-fixes' into for-linus) Merging driver-core.current/driver-core-linus (d88c93f090f7 debugfs: fix debugfs_rename parameter checking) Merging tty.current/tty-linus (f17b5f06cb92 Linux 5.0-rc4) Merging usb.current/usb-linus (f17b5f06cb92 Linux 5.0-rc4) Merging usb-gadget-fixes/fixes (87b6d2c56825 usb: dwc2: gadget: Fix Remote Wakeup interrupt bit clearing) Merging usb-serial-fixes/usb-linus (527c1e567ead USB: serial: keyspan_usa: add proper SPDX lines for .h files) Merging usb-chipidea-fixes/ci-for-usb-stable (d6d768a0ec3c usb:
[PATCH 1/9] clk: Combine __clk_get() and __clk_create_clk()
The __clk_get() function is practically a private clk implementation detail now. No architecture defines it, and given that new code should be using the common clk framework there isn't a need for it to keep existing just to serve clkdev purposes. Let's fold it into the __clk_create_clk() function and make that a little more generic by renaming it to clk_hw_create_clk(). This will allow the framework to create a struct clk handle to a particular clk_hw pointer and link it up as a consumer wherever that's needed. Doing this also lets us get rid of the __clk_free_clk() API that had to be kept in sync with __clk_put(). Splitting that API up into the "link and unlink from consumer list" phase and "free the clk pointer" phase allows us to reuse that logic in a couple places, simplifying the code. Cc: Miquel Raynal Cc: Jerome Brunet Cc: Russell King Cc: Michael Turquette Signed-off-by: Stephen Boyd --- drivers/clk/clk.c| 140 +-- drivers/clk/clk.h| 10 +--- drivers/clk/clkdev.c | 9 +-- 3 files changed, 98 insertions(+), 61 deletions(-) diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c index af011974d4ec..01b36f0851bd 100644 --- a/drivers/clk/clk.c +++ b/drivers/clk/clk.c @@ -3202,42 +3202,103 @@ static int __clk_core_init(struct clk_core *core) return ret; } -struct clk *__clk_create_clk(struct clk_hw *hw, const char *dev_id, +/** + * clk_core_link_consumer - Add a clk consumer to the list of consumers in a clk_core + * @core: clk to add consumer to + * @clk: consumer to link to a clk + */ +static void clk_core_link_consumer(struct clk_core *core, struct clk *clk) +{ + clk_prepare_lock(); + hlist_add_head(>clks_node, >clks); + clk_prepare_unlock(); +} + +/** + * clk_core_unlink_consumer - Remove a clk consumer from the list of consumers in a clk_core + * @clk: consumer to unlink + */ +static void clk_core_unlink_consumer(struct clk *clk) +{ + lockdep_assert_held(_lock); + hlist_del(>clks_node); +} + +/** + * alloc_clk - Allocate a clk consumer, but leave it unlinked to the clk_core + * @core: clk to allocate a consumer for + * @dev_id: string describing device name + * @con_id: connection ID string on device + * + * Returns: clk consumer left unlinked from the consumer list + */ +static struct clk *alloc_clk(struct clk_core *core, const char *dev_id, const char *con_id) { struct clk *clk; - /* This is to allow this function to be chained to others */ - if (IS_ERR_OR_NULL(hw)) - return ERR_CAST(hw); - clk = kzalloc(sizeof(*clk), GFP_KERNEL); if (!clk) return ERR_PTR(-ENOMEM); - clk->core = hw->core; + clk->core = core; clk->dev_id = dev_id; clk->con_id = kstrdup_const(con_id, GFP_KERNEL); clk->max_rate = ULONG_MAX; - clk_prepare_lock(); - hlist_add_head(>clks_node, >core->clks); - clk_prepare_unlock(); - return clk; } -/* keep in sync with __clk_put */ -void __clk_free_clk(struct clk *clk) +/** + * free_clk - Free a clk consumer + * @clk: clk consumer to free + * + * Note, this assumes the clk has been unlinked from the clk_core consumer + * list. + */ +static void free_clk(struct clk *clk) { - clk_prepare_lock(); - hlist_del(>clks_node); - clk_prepare_unlock(); - kfree_const(clk->con_id); kfree(clk); } +/** + * clk_hw_create_clk: Allocate and link a clk consumer to a clk_core given + * a clk_hw + * @hw: clk_hw associated with the clk being consumed + * @dev_id: string describing device name + * @con_id: connection ID string on device + * + * This is the main function used to create a clk pointer for use by clk + * consumers. It connects a consumer to the clk_core and clk_hw structures + * used by the framework and clk provider respectively. + */ +struct clk *clk_hw_create_clk(struct clk_hw *hw, + const char *dev_id, const char *con_id) +{ + struct clk *clk; + struct clk_core *core; + + /* This is to allow this function to be chained to others */ + if (IS_ERR_OR_NULL(hw)) + return ERR_CAST(hw); + + core = hw->core; + clk = alloc_clk(core, dev_id, con_id); + if (IS_ERR(clk)) + return clk; + + if (!try_module_get(core->owner)) { + free_clk(clk); + return ERR_PTR(-ENOENT); + } + + kref_get(>ref); + clk_core_link_consumer(core, clk); + + return clk; +} + /** * clk_register - allocate a new clock, register it and return an opaque cookie * @dev: device that is registering this clock @@ -3313,17 +3374,27 @@ struct clk *clk_register(struct device *dev, struct clk_hw *hw) INIT_HLIST_HEAD(>clks); - hw->clk = __clk_create_clk(hw, NULL, NULL); + /* +* Don't call clk_hw_create_clk() here because that would pin the +*
[PATCH 3/9] clk: core: clarify the check for runtime PM
From: Miquel Raynal Currently, the core->dev entry is populated only if runtime PM is enabled. Doing so prevents accessing the device structure in any case. Keep the same logic but instead of using the presence of core->dev as the only condition, also check the status of pm_runtime_enabled(). Then, we can set the core->dev pointer at any time as long as a device structure is available. This change will help supporting device links in the clock subsystem. Signed-off-by: Miquel Raynal Cc: Jerome Brunet Cc: Russell King Cc: Michael Turquette [sb...@kernel.org: Change to a boolean flag] Signed-off-by: Stephen Boyd --- drivers/clk/clk.c | 14 -- 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c index 5d82cf25bb29..01cdb9ae03fa 100644 --- a/drivers/clk/clk.c +++ b/drivers/clk/clk.c @@ -60,6 +60,7 @@ struct clk_core { struct clk_core *new_child; unsigned long flags; boolorphan; + boolrpm_enabled; unsigned intenable_count; unsigned intprepare_count; unsigned intprotect_count; @@ -95,9 +96,9 @@ struct clk { /*** runtime pm ***/ static int clk_pm_runtime_get(struct clk_core *core) { - int ret = 0; + int ret; - if (!core->dev) + if (!core->rpm_enabled) return 0; ret = pm_runtime_get_sync(core->dev); @@ -106,7 +107,7 @@ static int clk_pm_runtime_get(struct clk_core *core) static void clk_pm_runtime_put(struct clk_core *core) { - if (!core->dev) + if (!core->rpm_enabled) return; pm_runtime_put_sync(core->dev); @@ -226,7 +227,7 @@ static bool clk_core_is_enabled(struct clk_core *core) * taking enable spinlock, but the below check is needed if one tries * to call it from other places. */ - if (core->dev) { + if (core->rpm_enabled) { pm_runtime_get_noresume(core->dev); if (!pm_runtime_active(core->dev)) { ret = false; @@ -236,7 +237,7 @@ static bool clk_core_is_enabled(struct clk_core *core) ret = core->ops->is_enabled(core->hw); done: - if (core->dev) + if (core->rpm_enabled) pm_runtime_put(core->dev); return ret; @@ -3391,7 +3392,8 @@ struct clk *clk_register(struct device *dev, struct clk_hw *hw) core->ops = hw->init->ops; if (dev && pm_runtime_enabled(dev)) - core->dev = dev; + core->rpm_enabled = true; + core->dev = dev; if (dev && dev->driver) core->owner = dev->driver->owner; core->hw = hw; -- Sent by a computer through tubes
[PATCH 0/9] Rewrite clk parent handling
There are a couple problems with clk parent handling in the common clk framework. This patch series combines a few different topics together as all this code is closely related. First off, we don't do well at determining parents of clks at clk registration time because the return type of the clk_ops::get_parent() op is a u8 which isn't expressive enough to cover all our use-cases. Secondly, we use strings for all parent-child linkages, and this leads to poorly written code that extracts clk names from struct clk pointers and makes clk provider drivers use clk consumer APIs. Thirdly, clkdev.c has a collection of DT parsing logic in it that is only used when the common clk framework is present but we want to use that same logic for describing parent-child linkages of clk providers via in DT. This should all be moved into the common clk framework and used from there as well as from clkdev.c, so this series changes the way clkdev interacts with the clk framework by having clkdev get clk_hw pointers out of DT clk specifiers and then convert those into clk pointers with clk_hw_create_clk(). Splitting the API this way lets us get clk_hw pointers for clk providers and skip the struct clk pointer creation phase that we don't need to do when describing parent-child linkages. And finally, we have a few patches in here that lay the groundwork for supporting device links in the common clk framework. We do that by pushing the consuming device pointer through to the clk pointer creation in clk_hw_create_clk(). This wasn't always easy to do when we had __clk_create_clk() called from multiple places, some being deep in the clk registration path. This series simplifies that logic so that we can always attach a consumer device to a clk that we create in one place, instead of making that linkage in multiple places near where we create struct clk pointers. Miquel Raynal (1): clk: core: clarify the check for runtime PM Stephen Boyd (8): clk: Combine __clk_get() and __clk_create_clk() clk: Introduce get_parent_hw clk op clk: Introduce of_clk_get_hw_from_clkspec() clk: Inform the core about consumer devices clk: Move of_clk_*() APIs into clk.c from clkdev.c clk: Allow parents to be specified without string names clk: qcom: gcc-sdm845: Migrate to DT parent mapping arm64: dts: qcom: Specify XO clk as input to GCC node Cc: Miquel Raynal Cc: Jerome Brunet Cc: Russell King Cc: Michael Turquette arch/arm64/boot/dts/qcom/sdm845.dtsi | 2 + drivers/clk/clk.c| 584 --- drivers/clk/clk.h| 23 +- drivers/clk/clkdev.c | 120 +- drivers/clk/qcom/gcc-sdm845.c| 180 - include/linux/clk-provider.h | 26 +- 6 files changed, 583 insertions(+), 352 deletions(-) base-commit: 651022382c7f8da46cb4872a545ee1da6d097d2a -- Sent by a computer through tubes
[PATCH 5/9] clk: Inform the core about consumer devices
We'd like to have a pointer to the device that's consuming a particular clk in the clk framework so we can link the consumer to the clk provider with a PM device link. Add a device argument to clk_hw_create_clk() for this so it can be used in subsequent patches to add and remove the link. Cc: Miquel Raynal Cc: Jerome Brunet Cc: Russell King Cc: Michael Turquette Signed-off-by: Stephen Boyd --- drivers/clk/clk.c| 7 +-- drivers/clk/clk.h| 7 +-- drivers/clk/clkdev.c | 16 +++- 3 files changed, 21 insertions(+), 9 deletions(-) diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c index d4c4cab42375..73f8a287bf42 100644 --- a/drivers/clk/clk.c +++ b/drivers/clk/clk.c @@ -85,6 +85,7 @@ struct clk_core { struct clk { struct clk_core *core; + struct device *dev; const char *dev_id; const char *con_id; unsigned long min_rate; @@ -3323,6 +3324,7 @@ static void free_clk(struct clk *clk) /** * clk_hw_create_clk: Allocate and link a clk consumer to a clk_core given * a clk_hw + * @dev: clk consumer device * @hw: clk_hw associated with the clk being consumed * @dev_id: string describing device name * @con_id: connection ID string on device @@ -3331,7 +,7 @@ static void free_clk(struct clk *clk) * consumers. It connects a consumer to the clk_core and clk_hw structures * used by the framework and clk provider respectively. */ -struct clk *clk_hw_create_clk(struct clk_hw *hw, +struct clk *clk_hw_create_clk(struct device *dev, struct clk_hw *hw, const char *dev_id, const char *con_id) { struct clk *clk; @@ -3345,6 +3347,7 @@ struct clk *clk_hw_create_clk(struct clk_hw *hw, clk = alloc_clk(core, dev_id, con_id); if (IS_ERR(clk)) return clk; + clk->dev = dev; if (!try_module_get(core->owner)) { free_clk(clk); @@ -4161,7 +4164,7 @@ struct clk *of_clk_get_from_provider(struct of_phandle_args *clkspec) { struct clk_hw *hw = of_clk_get_hw_from_clkspec(clkspec); - return clk_hw_create_clk(hw, NULL, __func__); + return clk_hw_create_clk(NULL, hw, NULL, __func__); } EXPORT_SYMBOL_GPL(of_clk_get_from_provider); diff --git a/drivers/clk/clk.h b/drivers/clk/clk.h index cdac6dfa8094..fda0ad483416 100644 --- a/drivers/clk/clk.h +++ b/drivers/clk/clk.h @@ -10,6 +10,8 @@ */ struct clk_hw; +struct device; +struct of_phandle_args; #if defined(CONFIG_OF) && defined(CONFIG_COMMON_CLK) int of_parse_clkspec(const struct device_node *np, int index, const char *name, @@ -18,13 +20,14 @@ struct clk_hw *of_clk_get_hw_from_clkspec(struct of_phandle_args *clkspec); #endif #ifdef CONFIG_COMMON_CLK -struct clk *clk_hw_create_clk(struct clk_hw *hw, +struct clk *clk_hw_create_clk(struct device *dev, struct clk_hw *hw, const char *dev_id, const char *con_id); void __clk_put(struct clk *clk); #else /* All these casts to avoid ifdefs in clkdev... */ static inline struct clk * -clk_hw_create_clk(struct clk_hw *hw, const char *dev_id, const char *con_id) +clk_hw_create_clk(struct device *dev, struct clk_hw *hw, const char *dev_id, + const char *con_id) { return (struct clk *)hw; } diff --git a/drivers/clk/clkdev.c b/drivers/clk/clkdev.c index 5ebb2119c0b9..f2f4f2afd28c 100644 --- a/drivers/clk/clkdev.c +++ b/drivers/clk/clkdev.c @@ -51,7 +51,7 @@ static struct clk *__of_clk_get(struct device_node *np, { struct clk_hw *hw = of_clk_get_hw(np, index, con_id); - return clk_hw_create_clk(hw, dev_id, con_id); + return clk_hw_create_clk(NULL, hw, dev_id, con_id); } struct clk *of_clk_get(struct device_node *np, int index) @@ -130,7 +130,8 @@ static struct clk_lookup *clk_find(const char *dev_id, const char *con_id) return cl; } -struct clk *clk_get_sys(const char *dev_id, const char *con_id) +static struct clk *__clk_get_sys(struct device *dev, const char *dev_id, +const char *con_id) { struct clk_lookup *cl; struct clk *clk = NULL; @@ -141,7 +142,7 @@ struct clk *clk_get_sys(const char *dev_id, const char *con_id) if (!cl) goto out; - clk = clk_hw_create_clk(cl->clk_hw, dev_id, con_id); + clk = clk_hw_create_clk(dev, cl->clk_hw, dev_id, con_id); if (IS_ERR(clk)) cl = NULL; out: @@ -149,6 +150,11 @@ struct clk *clk_get_sys(const char *dev_id, const char *con_id) return cl ? clk : ERR_PTR(-ENOENT); } + +struct clk *clk_get_sys(const char *dev_id, const char *con_id) +{ + return __clk_get_sys(NULL, dev_id, con_id); +} EXPORT_SYMBOL(clk_get_sys); struct clk *clk_get(struct device *dev, const char *con_id) @@ -159,10 +165,10 @@ struct clk *clk_get(struct device *dev, const char *con_id) if (dev && dev->of_node) { hw = of_clk_get_hw(dev->of_node, 0, con_id); if
[PATCH 9/9] arm64: dts: qcom: Specify XO clk as input to GCC node
This is an example patch to show how DT nodes are updated to specify the clocks which are external to the clock controller can be specified in DT and then found by the clk core to do parent-child linkage. Cc: Miquel Raynal Cc: Jerome Brunet Cc: Russell King Cc: Michael Turquette Signed-off-by: Stephen Boyd --- arch/arm64/boot/dts/qcom/sdm845.dtsi | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/sdm845.dtsi b/arch/arm64/boot/dts/qcom/sdm845.dtsi index b72bdb0a31a5..46e0b467b411 100644 --- a/arch/arm64/boot/dts/qcom/sdm845.dtsi +++ b/arch/arm64/boot/dts/qcom/sdm845.dtsi @@ -338,6 +338,8 @@ #clock-cells = <1>; #reset-cells = <1>; #power-domain-cells = <1>; + clocks = < RPMH_CXO_CLK>; + clock-names = "xo"; }; qfprom@784000 { -- Sent by a computer through tubes
[PATCH 8/9] clk: qcom: gcc-sdm845: Migrate to DT parent mapping
TODO: Fully convert driver Cc: Miquel Raynal Cc: Jerome Brunet Cc: Russell King Cc: Michael Turquette Signed-off-by: Stephen Boyd --- drivers/clk/qcom/gcc-sdm845.c | 180 +- 1 file changed, 89 insertions(+), 91 deletions(-) diff --git a/drivers/clk/qcom/gcc-sdm845.c b/drivers/clk/qcom/gcc-sdm845.c index f133b7f5652f..9da9a337238d 100644 --- a/drivers/clk/qcom/gcc-sdm845.c +++ b/drivers/clk/qcom/gcc-sdm845.c @@ -25,6 +25,59 @@ #include "gdsc.h" #include "reset.h" +static struct clk_alpha_pll gpll0 = { + .offset = 0x0, + .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_FABIA], + .clkr = { + .enable_reg = 0x52000, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gpll0", + .parent_names = (const char *[]){ "bi_tcxo" }, + .num_parents = 1, + .ops = _alpha_pll_fixed_fabia_ops, + }, + }, +}; + +static struct clk_alpha_pll gpll4 = { + .offset = 0x76000, + .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_FABIA], + .clkr = { + .enable_reg = 0x52000, + .enable_mask = BIT(4), + .hw.init = &(struct clk_init_data){ + .name = "gpll4", + .parent_names = (const char *[]){ "bi_tcxo" }, + .num_parents = 1, + .ops = _alpha_pll_fixed_fabia_ops, + }, + }, +}; + +static const struct clk_div_table post_div_table_fabia_even[] = { + { 0x0, 1 }, + { 0x1, 2 }, + { 0x3, 4 }, + { 0x7, 8 }, + { } +}; + +static struct clk_alpha_pll_postdiv gpll0_out_even = { + .offset = 0x0, + .post_div_shift = 8, + .post_div_table = post_div_table_fabia_even, + .num_post_div = ARRAY_SIZE(post_div_table_fabia_even), + .width = 4, + .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_FABIA], + .clkr.hw.init = &(struct clk_init_data){ + .name = "gpll0_out_even", + .parent_names = (const char *[]){ "gpll0" }, + .num_parents = 1, + .ops = _alpha_pll_postdiv_fabia_ops, + }, +}; + enum { P_BI_TCXO, P_AUD_REF_CLK, @@ -42,11 +95,11 @@ static const struct parent_map gcc_parent_map_0[] = { { P_CORE_BI_PLL_TEST_SE, 7 }, }; -static const char * const gcc_parent_names_0[] = { - "bi_tcxo", - "gpll0", - "gpll0_out_even", - "core_bi_pll_test_se", +static const struct clk_parent_data gcc_parent_data_0[] = { + { .name = "xo", .fallback = "bi_tcxo" }, + { .hw = }, + { .hw = _out_even.clkr.hw }, + { .name = "core_bi_pll_test_se", .fallback = "core_bi_pll_test_se" } }; static const struct parent_map gcc_parent_map_1[] = { @@ -144,59 +197,6 @@ static const char * const gcc_parent_names_10[] = { "core_bi_pll_test_se", }; -static struct clk_alpha_pll gpll0 = { - .offset = 0x0, - .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_FABIA], - .clkr = { - .enable_reg = 0x52000, - .enable_mask = BIT(0), - .hw.init = &(struct clk_init_data){ - .name = "gpll0", - .parent_names = (const char *[]){ "bi_tcxo" }, - .num_parents = 1, - .ops = _alpha_pll_fixed_fabia_ops, - }, - }, -}; - -static struct clk_alpha_pll gpll4 = { - .offset = 0x76000, - .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_FABIA], - .clkr = { - .enable_reg = 0x52000, - .enable_mask = BIT(4), - .hw.init = &(struct clk_init_data){ - .name = "gpll4", - .parent_names = (const char *[]){ "bi_tcxo" }, - .num_parents = 1, - .ops = _alpha_pll_fixed_fabia_ops, - }, - }, -}; - -static const struct clk_div_table post_div_table_fabia_even[] = { - { 0x0, 1 }, - { 0x1, 2 }, - { 0x3, 4 }, - { 0x7, 8 }, - { } -}; - -static struct clk_alpha_pll_postdiv gpll0_out_even = { - .offset = 0x0, - .post_div_shift = 8, - .post_div_table = post_div_table_fabia_even, - .num_post_div = ARRAY_SIZE(post_div_table_fabia_even), - .width = 4, - .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_FABIA], - .clkr.hw.init = &(struct clk_init_data){ - .name = "gpll0_out_even", - .parent_names = (const char *[]){ "gpll0" }, - .num_parents = 1, - .ops = _alpha_pll_postdiv_fabia_ops, - }, -}; - static const struct freq_tbl ftbl_gcc_cpuss_ahb_clk_src[] = { F(1920, P_BI_TCXO, 1, 0, 0), { } @@ -334,7 +334,7 @@ static struct clk_rcg2 gcc_pcie_phy_refgen_clk_src = { .freq_tbl =
[PATCH 4/9] clk: Introduce of_clk_get_hw_from_clkspec()
We want to get struct clk_hw pointers from a DT clk specifier (i.e. a clocks property) so that we can find parent clks without searching for globally unique clk names. This should save time by avoiding the global string search for clks that are external to the clock controller providing the clk and let us move away from string comparisons in general. Introduce of_clk_get_hw_from_clkspec() which is largely the DT parsing part of finding clks implemented in clkdev.c and have that return a clk_hw pointer instead of converting that into a clk pointer. This lets us push up the clk pointer creation to the caller in clk_get() and avoids the need to push the dev_id and con_id throughout the DT parsing code. Cc: Miquel Raynal Cc: Jerome Brunet Cc: Russell King Cc: Michael Turquette Signed-off-by: Stephen Boyd --- drivers/clk/clk.c| 46 +--- drivers/clk/clk.h| 5 +-- drivers/clk/clkdev.c | 83 +--- 3 files changed, 69 insertions(+), 65 deletions(-) diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c index 01cdb9ae03fa..d4c4cab42375 100644 --- a/drivers/clk/clk.c +++ b/drivers/clk/clk.c @@ -4077,6 +4077,42 @@ void devm_of_clk_del_provider(struct device *dev) } EXPORT_SYMBOL(devm_of_clk_del_provider); +int of_parse_clkspec(const struct device_node *np, int index, const char *name, +struct of_phandle_args *out_args) +{ + int ret = -ENOENT; + + /* Walk up the tree of devices looking for a clock property that matches */ + while (np) { + /* +* For named clocks, first look up the name in the +* "clock-names" property. If it cannot be found, then index +* will be an error code and of_parse_phandle_with_args() will +* return -EINVAL. +*/ + if (name) + index = of_property_match_string(np, "clock-names", name); + ret = of_parse_phandle_with_args(np, "clocks", "#clock-cells", +index, out_args); + if (!ret) + break; + if (name && index >= 0) + break; + + /* +* No matching clock found on this node. If the parent node +* has a "clock-ranges" property, then we can try one of its +* clocks. +*/ + np = np->parent; + if (np && !of_get_property(np, "clock-ranges", NULL)) + break; + index = 0; + } + + return ret; +} + static struct clk_hw * __of_clk_get_hw_from_provider(struct of_clk_provider *provider, struct of_phandle_args *clkspec) @@ -4092,8 +4128,7 @@ __of_clk_get_hw_from_provider(struct of_clk_provider *provider, return __clk_get_hw(clk); } -struct clk *__of_clk_get_from_provider(struct of_phandle_args *clkspec, - const char *dev_id, const char *con_id) +struct clk_hw *of_clk_get_hw_from_clkspec(struct of_phandle_args *clkspec) { struct of_clk_provider *provider; struct clk_hw *hw = ERR_PTR(-EPROBE_DEFER); @@ -4101,7 +4136,6 @@ struct clk *__of_clk_get_from_provider(struct of_phandle_args *clkspec, if (!clkspec) return ERR_PTR(-EINVAL); - /* Check if we have such a provider in our array */ mutex_lock(_clk_mutex); list_for_each_entry(provider, _clk_providers, link) { if (provider->node == clkspec->np) { @@ -4112,7 +4146,7 @@ struct clk *__of_clk_get_from_provider(struct of_phandle_args *clkspec, } mutex_unlock(_clk_mutex); - return clk_hw_create_clk(hw, dev_id, con_id); + return hw; } /** @@ -4125,7 +4159,9 @@ struct clk *__of_clk_get_from_provider(struct of_phandle_args *clkspec, */ struct clk *of_clk_get_from_provider(struct of_phandle_args *clkspec) { - return __of_clk_get_from_provider(clkspec, NULL, __func__); + struct clk_hw *hw = of_clk_get_hw_from_clkspec(clkspec); + + return clk_hw_create_clk(hw, NULL, __func__); } EXPORT_SYMBOL_GPL(of_clk_get_from_provider); diff --git a/drivers/clk/clk.h b/drivers/clk/clk.h index c9a14122fadc..cdac6dfa8094 100644 --- a/drivers/clk/clk.h +++ b/drivers/clk/clk.h @@ -12,8 +12,9 @@ struct clk_hw; #if defined(CONFIG_OF) && defined(CONFIG_COMMON_CLK) -struct clk *__of_clk_get_from_provider(struct of_phandle_args *clkspec, - const char *dev_id, const char *con_id); +int of_parse_clkspec(const struct device_node *np, int index, const char *name, +struct of_phandle_args *out_args); +struct clk_hw *of_clk_get_hw_from_clkspec(struct of_phandle_args *clkspec); #endif #ifdef CONFIG_COMMON_CLK diff --git a/drivers/clk/clkdev.c b/drivers/clk/clkdev.c index bdeaffc950ae..5ebb2119c0b9
[PATCH 7/9] clk: Allow parents to be specified without string names
The common clk framework is lacking in ability to describe the clk topology without specifying strings for every possible parent-child link. There are a few drawbacks to the current approach: 1) String comparisons are used for everything, including describing topologies that are 'local' to a single clock controller. 2) clk providers (e.g. i2c clk drivers) need to create globally unique clk names to avoid collisions in the clk namespace, leading to awkward name generation code in various clk drivers. 3) DT bindings may not fully describe the clk topology and linkages between clk controllers because drivers can easily rely on globally unique strings to describe connections between clks. This leads to confusing DT bindings, complicated clk name generation code, and inefficient string comparisons during clk registration just so that the clk framework can detect the topology of the clk tree. Furthermore, some drivers call clk_get() and then __clk_get_name() to extract the globally unique clk name just so they can specify the parent of the clk they're registering. We have of_clk_parent_fill() but that mostly only works for single clks registered from a DT node, which isn't the norm. Let's simplify this all by introducing two new ways of specifying clk parents. The first method is an array of pointers to clk_hw structures corresponding to the parents at that index. This works for clks that are registered when we have access to all the clk_hw pointers for the parents. The second method is a mix of clk_hw pointers and strings of local and global parent clk names. If the .name member of the map is set we'll look for that clk by performing a DT based lookup of the device the clk is registered with and the .name specified in the map. If that fails, we'll fallback to the .fallback member and perform a global clk name lookup like we've always done before. Using either one of these new methods is entirely optional. Existing drivers will continue to work, and they can migrate to this new approach as they see fit. Eventually, we'll want to get rid of the 'parent_names' array in struct clk_init_data and use one of these new methods instead. Cc: Miquel Raynal Cc: Jerome Brunet Cc: Russell King Cc: Michael Turquette Signed-off-by: Stephen Boyd --- drivers/clk/clk.c| 215 +-- include/linux/clk-provider.h | 17 ++- 2 files changed, 173 insertions(+), 59 deletions(-) diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c index 202902e64799..0cd90a2339ad 100644 --- a/drivers/clk/clk.c +++ b/drivers/clk/clk.c @@ -42,6 +42,13 @@ static LIST_HEAD(clk_notifier_list); /***private data structures***/ +struct clk_parent_map { + struct clk_hw *hw; + struct clk_core *core; + const char *name; + const char *fallback; +}; + struct clk_core { const char *name; const struct clk_ops*ops; @@ -49,8 +56,7 @@ struct clk_core { struct module *owner; struct device *dev; struct clk_core *parent; - const char **parent_names; - struct clk_core **parents; + struct clk_parent_map *parents; u8 num_parents; u8 new_parent_index; unsigned long rate; @@ -319,17 +325,77 @@ static struct clk_core *clk_core_lookup(const char *name) return NULL; } +/** + * clk_core_get - Find the parent of a clk using a clock specifier in DT + * @core: clk to find parent of + * @name: name to search for in 'clock-names' of device providing clk + * + * This is the preferred method for clk providers to find the parent of a + * clk when that parent is external to the clk controller. The parent_names + * array is indexed and treated as a local name matching a string in the device + * node's 'clock-names' property. This allows clk providers to use their own + * namespace instead of looking for a globally unique parent string. + * + * For example the following DT snippet would allow a clock registered by the + * clock-controller@c001 that has a clk_init_data::parent_data array + * with 'xtal' in the 'name' member to find the clock provided by the + * clock-controller@f00abcd without needing to get the globally unique name of + * the xtal clk. + * + * parent: clock-controller@f00abcd { + * reg = <0xf00abcd 0xabcd>; + * #clock-cells = <0>; + * }; + * + * clock-controller@c001 { + * reg = <0xc001 0xf00d>; + * clocks = <>; + * clock-names = "xtal"; + * #clock-cells = <1>; + * }; + */ +static struct clk_core *clk_core_get(struct clk_core *core, const char *name) +{ + struct clk_hw *hw; + struct device *dev = core->dev; + + if (!dev) + return NULL; + + /* TODO: Support clkdev clk_lookups */ + hw =
[PATCH 2/9] clk: Introduce get_parent_hw clk op
The clk_ops::get_parent function is limited in ability to return errors because it returns a u8. A "workaround" to return an error is to return a number >= the number of parents of a clk. This will in turn cause the framework to "orphan" the clk and make the parent of the clk NULL. This isn't really correct, because if an error occurs while reading the parents of a clk we should fail the clk registration, instead of orphaning the clk and waiting for the clk to appear later. We really need to have three different return values from the get_parent clk op. Something valid for a clk that exists, something invalid for a clk that doesn't exist and never will exist or can't be determined because the register operation to read the parent failed, and something for a clk that doesn't exist because the framework doesn't know about what it is. Introduce a new clk_op that can express all of this by returning a pointer to the clk_hw of the parent. It's expected that clk provider drivers will return a valid pointer when the parent is findable, an error pointer like EPROBE_DEFER if their parent provider hasn't probed yet but is valid, a NULL pointer if they can't find the clk but index is valid, and an error pointer with an appropriate error code otherwise. Cc: Miquel Raynal Cc: Jerome Brunet Cc: Russell King Cc: Michael Turquette Signed-off-by: Stephen Boyd --- drivers/clk/clk.c| 117 ++- include/linux/clk-provider.h | 9 +++ 2 files changed, 96 insertions(+), 30 deletions(-) diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c index 01b36f0851bd..5d82cf25bb29 100644 --- a/drivers/clk/clk.c +++ b/drivers/clk/clk.c @@ -2242,14 +2242,84 @@ struct clk *clk_get_parent(struct clk *clk) } EXPORT_SYMBOL_GPL(clk_get_parent); -static struct clk_core *__clk_init_parent(struct clk_core *core) +static struct clk_core * +__clk_init_parent(struct clk_core *core, bool update_orphan) { u8 index = 0; + struct clk_hw *parent_hw = NULL; - if (core->num_parents > 1 && core->ops->get_parent) - index = core->ops->get_parent(core->hw); + if (core->ops->get_parent_hw) { + parent_hw = core->ops->get_parent_hw(core->hw); + /* +* The provider driver doesn't know what the parent is, +* but it's at least something valid, so it's not an +* orphan, just a clk with some unknown parent. +*/ + if (!parent_hw && update_orphan) + core->orphan = false; + } else { + if (core->num_parents > 1 && core->ops->get_parent) + index = core->ops->get_parent(core->hw); + + parent_hw = clk_hw_get_parent_by_index(core->hw, index); + } + + if (IS_ERR(parent_hw)) { + /* Parent clk provider hasn't probed yet, orphan it */ + if (PTR_ERR(parent_hw) == -EPROBE_DEFER) { + if (update_orphan) + core->orphan = true; + + return NULL; + } + + return ERR_CAST(parent_hw); + } + + if (!parent_hw) + return NULL; + + return parent_hw->core; +} + +static int clk_init_parent(struct clk_core *core) +{ + core->parent = __clk_init_parent(core, true); + if (IS_ERR(core->parent)) + return PTR_ERR(core->parent); + + /* +* Populate core->parent if parent has already been clk_core_init'd. If +* parent has not yet been clk_core_init'd then place clk in the orphan +* list. If clk doesn't have any parents then place it in the root +* clk list. +* +* Every time a new clk is clk_init'd then we walk the list of orphan +* clocks and re-parent any that are children of the clock currently +* being clk_init'd. +*/ + if (core->parent) { + hlist_add_head(>child_node, + >parent->children); + core->orphan = core->parent->orphan; + } else if (!core->num_parents) { + hlist_add_head(>child_node, _root_list); + core->orphan = false; + } else { + hlist_add_head(>child_node, _orphan_list); + } + + return 0; +} - return clk_core_get_parent_by_index(core, index); +static struct clk_core *clk_find_parent(struct clk_core *core) +{ + return __clk_init_parent(core, false); +} + +static bool clk_has_parent_op(const struct clk_ops *ops) +{ + return ops->get_parent || ops->get_parent_hw; } static void clk_core_reparent(struct clk_core *core, @@ -3045,14 +3115,14 @@ static int __clk_core_init(struct clk_core *core) goto out; } - if (core->ops->set_parent && !core->ops->get_parent) { + if (core->ops->set_parent && !clk_has_parent_op(core->ops)) { pr_err("%s: %s must
[PATCH 6/9] clk: Move of_clk_*() APIs into clk.c from clkdev.c
The API between clk.c and clkdev.c is purely getting the clk_hw structure (or the struct clk if it's not CCF) and then turning that struct clk_hw pointer into a struct clk pointer via clk_hw_create_clk(). There's no need to complicate clkdev.c with these DT parsing details that are only relevant to the common clk framework. Move the DT parsing logic into the core framework and just expose the APIs to get a clk_hw pointer and convert it. Cc: Miquel Raynal Cc: Jerome Brunet Cc: Russell King Cc: Michael Turquette Signed-off-by: Stephen Boyd --- drivers/clk/clk.c| 57 ++--- drivers/clk/clk.h| 11 +--- drivers/clk/clkdev.c | 60 3 files changed, 62 insertions(+), 66 deletions(-) diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c index 73f8a287bf42..202902e64799 100644 --- a/drivers/clk/clk.c +++ b/drivers/clk/clk.c @@ -4080,8 +4080,8 @@ void devm_of_clk_del_provider(struct device *dev) } EXPORT_SYMBOL(devm_of_clk_del_provider); -int of_parse_clkspec(const struct device_node *np, int index, const char *name, -struct of_phandle_args *out_args) +static int of_parse_clkspec(const struct device_node *np, int index, + const char *name, struct of_phandle_args *out_args) { int ret = -ENOENT; @@ -4131,7 +4131,8 @@ __of_clk_get_hw_from_provider(struct of_clk_provider *provider, return __clk_get_hw(clk); } -struct clk_hw *of_clk_get_hw_from_clkspec(struct of_phandle_args *clkspec) +static struct clk_hw * +of_clk_get_hw_from_clkspec(struct of_phandle_args *clkspec) { struct of_clk_provider *provider; struct clk_hw *hw = ERR_PTR(-EPROBE_DEFER); @@ -4168,6 +4169,56 @@ struct clk *of_clk_get_from_provider(struct of_phandle_args *clkspec) } EXPORT_SYMBOL_GPL(of_clk_get_from_provider); +struct clk_hw *of_clk_get_hw(struct device_node *np, int index, +const char *con_id) +{ + int ret; + struct clk_hw *hw; + struct of_phandle_args clkspec; + + ret = of_parse_clkspec(np, index, con_id, ); + if (ret) + return ERR_PTR(ret); + + hw = of_clk_get_hw_from_clkspec(); + of_node_put(clkspec.np); + + return hw; +} + +static struct clk *__of_clk_get(struct device_node *np, + int index, const char *dev_id, + const char *con_id) +{ + struct clk_hw *hw = of_clk_get_hw(np, index, con_id); + + return clk_hw_create_clk(NULL, hw, dev_id, con_id); +} + +struct clk *of_clk_get(struct device_node *np, int index) +{ + return __of_clk_get(np, index, np->full_name, NULL); +} +EXPORT_SYMBOL(of_clk_get); + +/** + * of_clk_get_by_name() - Parse and lookup a clock referenced by a device node + * @np: pointer to clock consumer node + * @name: name of consumer's clock input, or NULL for the first clock reference + * + * This function parses the clocks and clock-names properties, + * and uses them to look up the struct clk from the registered list of clock + * providers. + */ +struct clk *of_clk_get_by_name(struct device_node *np, const char *name) +{ + if (!np) + return ERR_PTR(-ENOENT); + + return __of_clk_get(np, -1, np->full_name, name); +} +EXPORT_SYMBOL(of_clk_get_by_name); + /** * of_clk_get_parent_count() - Count the number of clocks a device node has * @np: device node to count diff --git a/drivers/clk/clk.h b/drivers/clk/clk.h index fda0ad483416..46e668d64da8 100644 --- a/drivers/clk/clk.h +++ b/drivers/clk/clk.h @@ -14,9 +14,14 @@ struct device; struct of_phandle_args; #if defined(CONFIG_OF) && defined(CONFIG_COMMON_CLK) -int of_parse_clkspec(const struct device_node *np, int index, const char *name, -struct of_phandle_args *out_args); -struct clk_hw *of_clk_get_hw_from_clkspec(struct of_phandle_args *clkspec); +struct clk_hw *of_clk_get_hw(struct device_node *np, + int index, const char *con_id); +#else /* !CONFIG_COMMON_CLK || !CONFIG_OF */ +static inline struct clk_hw *of_clk_get_hw(struct device_node *np, + int index, const char *con_id) +{ + return ERR_PTR(-ENOENT); +} #endif #ifdef CONFIG_COMMON_CLK diff --git a/drivers/clk/clkdev.c b/drivers/clk/clkdev.c index f2f4f2afd28c..d3758bf4305c 100644 --- a/drivers/clk/clkdev.c +++ b/drivers/clk/clkdev.c @@ -27,66 +27,6 @@ static LIST_HEAD(clocks); static DEFINE_MUTEX(clocks_mutex); -#if defined(CONFIG_OF) && defined(CONFIG_COMMON_CLK) -static struct clk_hw *of_clk_get_hw(struct device_node *np, - int index, const char *con_id) -{ - int ret; - struct clk_hw *hw; - struct of_phandle_args clkspec; - - ret = of_parse_clkspec(np, index, con_id, ); - if (ret) - return ERR_PTR(ret); - - hw = of_clk_get_hw_from_clkspec(); -
[PATCH] include/linux/bpf.h - fix missing prototype warnings...
Compiling with W=1 generates warnings: CC kernel/bpf/core.o kernel/bpf/core.c:721:12: warning: no previous prototype for ?bpf_jit_alloc_exec_limit? [-Wmissing-prototypes] 721 | u64 __weak bpf_jit_alloc_exec_limit(void) |^~~~ kernel/bpf/core.c:757:14: warning: no previous prototype for ?bpf_jit_alloc_exec? [-Wmissing-prototypes] 757 | void *__weak bpf_jit_alloc_exec(unsigned long size) | ^~ kernel/bpf/core.c:762:13: warning: no previous prototype for ?bpf_jit_free_exec? [-Wmissing-prototypes] 762 | void __weak bpf_jit_free_exec(void *addr) | ^ All three are weak functions that archs can override, although none do so currently. Provide prototypes for when a new arch provides its own. Signed-off-by: Valdis Kletnieks diff --git a/include/linux/bpf.h b/include/linux/bpf.h index 3851529062ec..99e55313123f 100644 --- a/include/linux/bpf.h +++ b/include/linux/bpf.h @@ -472,6 +472,10 @@ _out: \ #define BPF_PROG_RUN_ARRAY_CHECK(array, ctx, func) \ __BPF_PROG_RUN_ARRAY(array, ctx, func, true) +u64 __weak bpf_jit_alloc_exec_limit(void); +void *__weak bpf_jit_alloc_exec(unsigned long size); +void __weak bpf_jit_free_exec(void *addr); + #ifdef CONFIG_BPF_SYSCALL DECLARE_PER_CPU(int, bpf_prog_active);
Re: [PATCH v2 2/2] PCI: hv: Refactor hv_irq_unmask() to use cpumask_to_vpset()
On Sun, Jan 27, 2019 at 05:22:06AM +, Michael Kelley wrote: > From: Maya Nakamura Sent: Saturday, January 26, > 2019 12:55 AM > > > > @@ -953,29 +951,27 @@ static void hv_irq_unmask(struct irq_data *data) > > */ > > params->int_target.flags |= > > HV_DEVICE_INTERRUPT_TARGET_PROCESSOR_SET; > > - params->int_target.vp_set.valid_bank_mask = > > - (1ull << HV_VP_SET_BANK_COUNT_MAX) - 1; > > + > > + if (!alloc_cpumask_var(, GFP_KERNEL)) { > > + res = 1; > > + goto exit_unlock; > > + } > > + > > + cpumask_and(tmp, dest, cpu_online_mask); > > + nr_bank = cpumask_to_vpset(>int_target.vp_set, tmp); > > + free_cpumask_var(tmp); > > + > > + if (!nr_bank) { > > There are two failures cases in cpumask_to_vpset(). One case returns > 0, and the other case returns -1. The above test only catches the 0 > failure case. Need to modify the test to catch both cases. > > Michael > Thank you for your feedback. I will correct it in v3. Maya > > + res = 1; > > + goto exit_unlock; > > + } > > >
Re: [PATCHv7] x86/kdump: bugfix, make the behavior of crashkernel=X consistent with kaslr
On Fri, Jan 25, 2019 at 6:39 PM Borislav Petkov wrote: > > > > Subject: Re: [PATCHv7] x86/kdump: bugfix, make the behavior of > > crashkernel=X > > s/bugfix, // > OK. > On Mon, Jan 21, 2019 at 01:16:08PM +0800, Pingfan Liu wrote: > > People reported crashkernel=384M reservation failed on a high end server > > with KASLR enabled. In that case there is enough free memory under 896M > > but crashkernel reservation still fails intermittently. > > > > The situation is crashkernel reservation code only finds free region under > > 896 MB with 128M aligned in case no ',high' being used. And KASLR could > > break the first 896M into several parts randomly thus the failure happens. > > This reads very strange. > What about " It turns out that crashkernel reservation code only tries to find a region under 896 MB, aligned on 128M. But KASLR randomly breaks big region inside [0,896M] into smaller pieces, not big enough as demanded in the "crashkernel=X" parameter." > > User has no way to predict and make sure crashkernel=xM working unless > > he/she use 'crashkernel=xM,high'. Since 'crashkernel=xM' is the most > > common use case this issue is a serious bug. > > > > And we can't answer questions raised from customer: > > 1) why it doesn't succeed to reserve 896 MB; > > 2) what's wrong with memory region under 4G; > > 3) why I have to add ',high', I only require 384 MB, not 3840 MB. > > Errr, this looks like communication issue. Sounds to me like the text > around crashkernel= in > What about dropping this section in commit log and another patch to fix the document? > Documentation/admin-guide/kernel-parameters.txt > > needs improving? > > > This patch tries to get memory region from 896 MB firstly, then [896MB,4G], > > Avoid having "This patch" or "This commit" in the commit message. It is > tautologically useless. > OK > Also, do > > $ git grep 'This patch' Documentation/process > > for more details. > > > finally above 4G. > > > > Dave Young sent the original post, and I just re-post it with commit log > > If he sent it, he should be the author I guess. > > > improvement as his requirement. > > http://lists.infradead.org/pipermail/kexec/2017-October/019571.html > > There was an old discussion below (previously posted by Chao Wang): > > https://lkml.org/lkml/2013/10/15/601 > > All that changelog info doesn't belong in the commit message ... > > > Signed-off-by: Pingfan Liu > > Cc: Dave Young > > Cc: Baoquan He > > Cc: Andrew Morton > > Cc: Mike Rapoport > > Cc: ying...@kernel.org, > > Cc: vgo...@redhat.com > > Cc: Randy Dunlap > > Cc: Borislav Petkov > > Cc: x...@kernel.org > > Cc: linux-kernel@vger.kernel.org > > --- > > but here. > > > v6 -> v7: commit log improvement > > arch/x86/kernel/setup.c | 16 > > 1 file changed, 16 insertions(+) > > > > diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c > > index 3d872a5..fa62c81 100644 > > --- a/arch/x86/kernel/setup.c > > +++ b/arch/x86/kernel/setup.c > > @@ -551,6 +551,22 @@ static void __init reserve_crashkernel(void) > > high ? CRASH_ADDR_HIGH_MAX > >: CRASH_ADDR_LOW_MAX, > > crash_size, CRASH_ALIGN); > > +#ifdef CONFIG_X86_64 > > + /* > > + * crashkernel=X reserve below 896M fails? Try below 4G > > + */ > > + if (!high && !crash_base) > > + crash_base = memblock_find_in_range(CRASH_ALIGN, > > + (1ULL << 32), > > + crash_size, CRASH_ALIGN); > > + /* > > + * crashkernel=X reserve below 4G fails? Try MAXMEM > > + */ > > + if (!high && !crash_base) > > + crash_base = memblock_find_in_range(CRASH_ALIGN, > > + CRASH_ADDR_HIGH_MAX, > > + crash_size, CRASH_ALIGN); > > +#endif > > Ok, so this is silly: we know at which physical address KASLR allocated > the kernel so why aren't we querying that and seeing if there's enough > room before it or after it to call memblock_find_in_range() on the > bigger range? > Sorry, can not catch up with you. Do you suggestion memblock_find_in_range(0, kernel_start) and memblock_find_in_range(kernel_end, mem_end)? But the memory is truncated into fraction by many component which call memblock_reserve(), besides kernel. For the left question, Dave has follow the discussion in another email, will follow there. Thanks and regards, Pingfan > Also, why is "high" dealt with separately and why isn't the code > enforcing "high" if the normal reservation fails? > > The presence of high is requiring from our users to pay attention what > to use when the kernel can do all that automatically. Looks like a UI > fail to me. > > And look
[PATCH v6 1/4] tee: add bus driver framework for TEE based devices
Introduce a generic TEE bus driver concept for TEE based kernel drivers which would like to communicate with TEE based devices/services. Also add support in module device table for these new TEE based devices. In this TEE bus concept, devices/services are identified via Universally Unique Identifier (UUID) and drivers register a table of device UUIDs which they can support. So this TEE bus framework registers following apis: - match(): Iterates over the driver UUID table to find a corresponding match for device UUID. If a match is found, then this particular device is probed via corresponding probe api registered by the driver. This process happens whenever a device or a driver is registered with TEE bus. - uevent(): Notifies user-space (udev) whenever a new device is registered on this bus for auto-loading of modularized drivers. Also this framework allows for device enumeration to be specific to corresponding TEE implementation like OP-TEE etc. Signed-off-by: Sumit Garg Reviewed-by: Daniel Thompson Reviewed-by: Bhupesh Sharma --- drivers/tee/tee_core.c| 54 --- include/linux/mod_devicetable.h | 9 +++ include/linux/tee_drv.h | 32 ++- scripts/mod/devicetable-offsets.c | 3 +++ scripts/mod/file2alias.c | 19 ++ 5 files changed, 112 insertions(+), 5 deletions(-) diff --git a/drivers/tee/tee_core.c b/drivers/tee/tee_core.c index 7b2bb4c..1e14897 100644 --- a/drivers/tee/tee_core.c +++ b/drivers/tee/tee_core.c @@ -15,7 +15,6 @@ #define pr_fmt(fmt) "%s: " fmt, __func__ #include -#include #include #include #include @@ -1027,6 +1026,39 @@ int tee_client_invoke_func(struct tee_context *ctx, } EXPORT_SYMBOL_GPL(tee_client_invoke_func); +static int tee_client_device_match(struct device *dev, + struct device_driver *drv) +{ + const struct tee_client_device_id *id_table; + struct tee_client_device *tee_device; + + id_table = to_tee_client_driver(drv)->id_table; + tee_device = to_tee_client_device(dev); + + while (!uuid_is_null(_table->uuid)) { + if (uuid_equal(_device->id.uuid, _table->uuid)) + return 1; + id_table++; + } + + return 0; +} + +static int tee_client_device_uevent(struct device *dev, + struct kobj_uevent_env *env) +{ + uuid_t *dev_id = _tee_client_device(dev)->id.uuid; + + return add_uevent_var(env, "MODALIAS=tee:%pUb", dev_id); +} + +struct bus_type tee_bus_type = { + .name = "tee", + .match = tee_client_device_match, + .uevent = tee_client_device_uevent, +}; +EXPORT_SYMBOL_GPL(tee_bus_type); + static int __init tee_init(void) { int rc; @@ -1040,18 +1072,32 @@ static int __init tee_init(void) rc = alloc_chrdev_region(_devt, 0, TEE_NUM_DEVICES, "tee"); if (rc) { pr_err("failed to allocate char dev region\n"); - class_destroy(tee_class); - tee_class = NULL; + goto out_unreg_class; + } + + rc = bus_register(_bus_type); + if (rc) { + pr_err("failed to register tee bus\n"); + goto out_unreg_chrdev; } + return 0; + +out_unreg_chrdev: + unregister_chrdev_region(tee_devt, TEE_NUM_DEVICES); +out_unreg_class: + class_destroy(tee_class); + tee_class = NULL; + return rc; } static void __exit tee_exit(void) { + bus_unregister(_bus_type); + unregister_chrdev_region(tee_devt, TEE_NUM_DEVICES); class_destroy(tee_class); tee_class = NULL; - unregister_chrdev_region(tee_devt, TEE_NUM_DEVICES); } subsys_initcall(tee_init); diff --git a/include/linux/mod_devicetable.h b/include/linux/mod_devicetable.h index f9bd2f3..14eaeeb 100644 --- a/include/linux/mod_devicetable.h +++ b/include/linux/mod_devicetable.h @@ -779,4 +779,13 @@ struct typec_device_id { kernel_ulong_t driver_data; }; +/** + * struct tee_client_device_id - tee based device identifier + * @uuid: For TEE based client devices we use the device uuid as + *the identifier. + */ +struct tee_client_device_id { + uuid_t uuid; +}; + #endif /* LINUX_MOD_DEVICETABLE_H */ diff --git a/include/linux/tee_drv.h b/include/linux/tee_drv.h index 6cfe058..ce957ce 100644 --- a/include/linux/tee_drv.h +++ b/include/linux/tee_drv.h @@ -15,11 +15,14 @@ #ifndef __TEE_DRV_H #define __TEE_DRV_H -#include +#include #include #include #include +#include #include +#include +#include /* * The file describes the API provided by the generic TEE driver to the @@ -538,4 +541,31 @@ static inline bool tee_param_is_memref(struct tee_param *param) } } +extern struct bus_type tee_bus_type; + +/** + * struct tee_client_device - tee based device + * @id:
[PATCH v6 3/4] tee: optee: add TEE bus device enumeration support
OP-TEE provides a pseudo TA to enumerate TAs which can act as devices/ services for TEE bus. So implement device enumeration using invoke function: PTA_CMD_GET_DEVICES provided by pseudo TA to fetch array of device UUIDs. Also register these enumerated devices with TEE bus as "optee-clntX" device. Signed-off-by: Sumit Garg Reviewed-by: Daniel Thompson --- drivers/tee/optee/Makefile| 1 + drivers/tee/optee/core.c | 4 + drivers/tee/optee/device.c| 155 ++ drivers/tee/optee/optee_private.h | 3 + 4 files changed, 163 insertions(+) create mode 100644 drivers/tee/optee/device.c diff --git a/drivers/tee/optee/Makefile b/drivers/tee/optee/Makefile index 48d262a..56263ae 100644 --- a/drivers/tee/optee/Makefile +++ b/drivers/tee/optee/Makefile @@ -5,3 +5,4 @@ optee-objs += call.o optee-objs += rpc.o optee-objs += supp.o optee-objs += shm_pool.o +optee-objs += device.o diff --git a/drivers/tee/optee/core.c b/drivers/tee/optee/core.c index e5efce3..ac59c77 100644 --- a/drivers/tee/optee/core.c +++ b/drivers/tee/optee/core.c @@ -634,6 +634,10 @@ static struct optee *optee_probe(struct device_node *np) if (optee->sec_caps & OPTEE_SMC_SEC_CAP_DYNAMIC_SHM) pr_info("dynamic shared memory is enabled\n"); + rc = optee_enumerate_devices(); + if (rc) + goto err; + pr_info("initialized driver\n"); return optee; err: diff --git a/drivers/tee/optee/device.c b/drivers/tee/optee/device.c new file mode 100644 index 000..c24c37f --- /dev/null +++ b/drivers/tee/optee/device.c @@ -0,0 +1,155 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (C) 2019 Linaro Ltd. + */ + +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + +#include +#include +#include +#include +#include "optee_private.h" + +/* + * Get device UUIDs + * + * [out] memref[0]Array of device UUIDs + * + * Return codes: + * TEE_SUCCESS - Invoke command success + * TEE_ERROR_BAD_PARAMETERS - Incorrect input param + * TEE_ERROR_SHORT_BUFFER - Output buffer size less than required + */ +#define PTA_CMD_GET_DEVICES0x0 + +static int optee_ctx_match(struct tee_ioctl_version_data *ver, const void *data) +{ + if (ver->impl_id == TEE_IMPL_ID_OPTEE) + return 1; + else + return 0; +} + +static int get_devices(struct tee_context *ctx, u32 session, + struct tee_shm *device_shm, u32 *shm_size) +{ + u32 ret = 0; + struct tee_ioctl_invoke_arg inv_arg = {0}; + struct tee_param param[4] = {0}; + + /* Invoke PTA_CMD_GET_DEVICES function */ + inv_arg.func = PTA_CMD_GET_DEVICES; + inv_arg.session = session; + inv_arg.num_params = 4; + + /* Fill invoke cmd params */ + param[0].attr = TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_OUTPUT; + param[0].u.memref.shm = device_shm; + param[0].u.memref.size = *shm_size; + param[0].u.memref.shm_offs = 0; + + ret = tee_client_invoke_func(ctx, _arg, param); + if ((ret < 0) || ((inv_arg.ret != TEEC_SUCCESS) && + (inv_arg.ret != TEEC_ERROR_SHORT_BUFFER))) { + pr_err("PTA_CMD_GET_DEVICES invoke function err: %x\n", + inv_arg.ret); + return -EINVAL; + } + + *shm_size = param[0].u.memref.size; + + return 0; +} + +static int optee_register_device(const uuid_t *device_uuid, u32 device_id) +{ + struct tee_client_device *optee_device = NULL; + int rc; + + optee_device = kzalloc(sizeof(*optee_device), GFP_KERNEL); + if (!optee_device) + return -ENOMEM; + + optee_device->dev.bus = _bus_type; + dev_set_name(_device->dev, "optee-clnt%u", device_id); + uuid_copy(_device->id.uuid, device_uuid); + + rc = device_register(_device->dev); + if (rc) { + pr_err("device registration failed, err: %d\n", rc); + kfree(optee_device); + } + + return rc; +} + +int optee_enumerate_devices(void) +{ + const uuid_t pta_uuid = + UUID_INIT(0x7011a688, 0xddde, 0x4053, + 0xa5, 0xa9, 0x7b, 0x3c, 0x4d, 0xdf, 0x13, 0xb8); + struct tee_ioctl_open_session_arg sess_arg = {0}; + struct tee_shm *device_shm = NULL; + const uuid_t *device_uuid = NULL; + struct tee_context *ctx = NULL; + u32 shm_size = 0, idx, num_devices = 0; + int rc; + + /* Open context with OP-TEE driver */ + ctx = tee_client_open_context(NULL, optee_ctx_match, NULL, NULL); + if (IS_ERR(ctx)) + return -ENODEV; + + /* Open session with device enumeration pseudo TA */ + memcpy(sess_arg.uuid, pta_uuid.b, TEE_IOCTL_UUID_LEN); + sess_arg.clnt_login = TEE_IOCTL_LOGIN_PUBLIC; + sess_arg.num_params = 0; + + rc = tee_client_open_session(ctx, _arg, NULL); + if ((rc < 0) || (sess_arg.ret !=
[PATCH v6 2/4] tee: add supp_nowait flag in tee_context struct
This flag indicates that requests in this context should not wait for tee-supplicant daemon to be started if not present and just return with an error code. It is needed for requests which should be non-blocking in nature like ones arising from TEE based kernel drivers or any in kernel api that uses TEE internal client interface. Signed-off-by: Sumit Garg Reviewed-by: Daniel Thompson --- drivers/tee/optee/supp.c | 10 +- drivers/tee/tee_core.c | 13 + include/linux/tee_drv.h | 6 ++ 3 files changed, 28 insertions(+), 1 deletion(-) diff --git a/drivers/tee/optee/supp.c b/drivers/tee/optee/supp.c index 43626e1..92f56b8 100644 --- a/drivers/tee/optee/supp.c +++ b/drivers/tee/optee/supp.c @@ -88,10 +88,18 @@ u32 optee_supp_thrd_req(struct tee_context *ctx, u32 func, size_t num_params, { struct optee *optee = tee_get_drvdata(ctx->teedev); struct optee_supp *supp = >supp; - struct optee_supp_req *req = kzalloc(sizeof(*req), GFP_KERNEL); + struct optee_supp_req *req; bool interruptable; u32 ret; + /* +* Return in case there is no supplicant available and +* non-blocking request. +*/ + if (!supp->ctx && ctx->supp_nowait) + return TEEC_ERROR_COMMUNICATION; + + req = kzalloc(sizeof(*req), GFP_KERNEL); if (!req) return TEEC_ERROR_OUT_OF_MEMORY; diff --git a/drivers/tee/tee_core.c b/drivers/tee/tee_core.c index 1e14897..25f3b9c 100644 --- a/drivers/tee/tee_core.c +++ b/drivers/tee/tee_core.c @@ -105,6 +105,11 @@ static int tee_open(struct inode *inode, struct file *filp) if (IS_ERR(ctx)) return PTR_ERR(ctx); + /* +* Default user-space behaviour is to wait for tee-supplicant +* if not present for any requests in this context. +*/ + ctx->supp_nowait = false; filp->private_data = ctx; return 0; } @@ -981,6 +986,14 @@ tee_client_open_context(struct tee_context *start, } while (IS_ERR(ctx) && PTR_ERR(ctx) != -ENOMEM); put_device(put_dev); + /* +* Default behaviour for in kernel client is to not wait for +* tee-supplicant if not present for any requests in this context. +* Also this flag could be configured again before call to +* tee_client_open_session() if any in kernel client requires +* different behaviour. +*/ + ctx->supp_nowait = true; return ctx; } EXPORT_SYMBOL_GPL(tee_client_open_context); diff --git a/include/linux/tee_drv.h b/include/linux/tee_drv.h index ce957ce..56d7f1b 100644 --- a/include/linux/tee_drv.h +++ b/include/linux/tee_drv.h @@ -50,6 +50,11 @@ struct tee_shm_pool; * @releasing: flag that indicates if context is being released right now. * It is needed to break circular dependency on context during * shared memory release. + * @supp_nowait: flag that indicates that requests in this context should not + * wait for tee-supplicant daemon to be started if not present + * and just return with an error code. It is needed for requests + * that arises from TEE based kernel drivers that should be + * non-blocking in nature. */ struct tee_context { struct tee_device *teedev; @@ -57,6 +62,7 @@ struct tee_context { void *data; struct kref refcount; bool releasing; + bool supp_nowait; }; struct tee_param_memref { -- 2.7.4
[PATCH v6 4/4] hwrng: add OP-TEE based rng driver
On ARM SoC's with TrustZone enabled, peripherals like entropy sources might not be accessible to normal world (linux in this case) and rather accessible to secure world (OP-TEE in this case) only. So this driver aims to provides a generic interface to OP-TEE based random number generator service. This driver registers on TEE bus to interact with OP-TEE based rng device/service. Signed-off-by: Sumit Garg --- MAINTAINERS| 5 + drivers/char/hw_random/Kconfig | 15 ++ drivers/char/hw_random/Makefile| 1 + drivers/char/hw_random/optee-rng.c | 298 + 4 files changed, 319 insertions(+) create mode 100644 drivers/char/hw_random/optee-rng.c diff --git a/MAINTAINERS b/MAINTAINERS index 51029a4..dcef7e9 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -11262,6 +11262,11 @@ M: Jens Wiklander S: Maintained F: drivers/tee/optee/ +OP-TEE RANDOM NUMBER GENERATOR (RNG) DRIVER +M: Sumit Garg +S: Maintained +F: drivers/char/hw_random/optee-rng.c + OPA-VNIC DRIVER M: Dennis Dalessandro M: Niranjana Vishwanathapura diff --git a/drivers/char/hw_random/Kconfig b/drivers/char/hw_random/Kconfig index dac895d..25a7d8f 100644 --- a/drivers/char/hw_random/Kconfig +++ b/drivers/char/hw_random/Kconfig @@ -424,6 +424,21 @@ config HW_RANDOM_EXYNOS will be called exynos-trng. If unsure, say Y. + +config HW_RANDOM_OPTEE + tristate "OP-TEE based Random Number Generator support" + depends on OPTEE + default HW_RANDOM + help + This driver provides support for OP-TEE based Random Number + Generator on ARM SoCs where hardware entropy sources are not + accessible to normal world (Linux). + + To compile this driver as a module, choose M here: the module + will be called optee-rng. + + If unsure, say Y. + endif # HW_RANDOM config UML_RANDOM diff --git a/drivers/char/hw_random/Makefile b/drivers/char/hw_random/Makefile index e35ec3c..7c9ef4a 100644 --- a/drivers/char/hw_random/Makefile +++ b/drivers/char/hw_random/Makefile @@ -38,3 +38,4 @@ obj-$(CONFIG_HW_RANDOM_CAVIUM) += cavium-rng.o cavium-rng-vf.o obj-$(CONFIG_HW_RANDOM_MTK)+= mtk-rng.o obj-$(CONFIG_HW_RANDOM_S390) += s390-trng.o obj-$(CONFIG_HW_RANDOM_KEYSTONE) += ks-sa-rng.o +obj-$(CONFIG_HW_RANDOM_OPTEE) += optee-rng.o diff --git a/drivers/char/hw_random/optee-rng.c b/drivers/char/hw_random/optee-rng.c new file mode 100644 index 000..2b9fc8a --- /dev/null +++ b/drivers/char/hw_random/optee-rng.c @@ -0,0 +1,298 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (C) 2018-2019 Linaro Ltd. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#define DRIVER_NAME "optee-rng" + +#define TEE_ERROR_HEALTH_TEST_FAIL 0x0001 + +/* + * TA_CMD_GET_ENTROPY - Get Entropy from RNG + * + * param[0] (inout memref) - Entropy buffer memory reference + * param[1] unused + * param[2] unused + * param[3] unused + * + * Result: + * TEE_SUCCESS - Invoke command success + * TEE_ERROR_BAD_PARAMETERS - Incorrect input param + * TEE_ERROR_NOT_SUPPORTED - Requested entropy size greater than size of pool + * TEE_ERROR_HEALTH_TEST_FAIL - Continuous health testing failed + */ +#define TA_CMD_GET_ENTROPY 0x0 + +/* + * TA_CMD_GET_RNG_INFO - Get RNG information + * + * param[0] (out value) - value.a: RNG data-rate in bytes per second + *value.b: Quality/Entropy per 1024 bit of data + * param[1] unused + * param[2] unused + * param[3] unused + * + * Result: + * TEE_SUCCESS - Invoke command success + * TEE_ERROR_BAD_PARAMETERS - Incorrect input param + */ +#define TA_CMD_GET_RNG_INFO0x1 + +#define MAX_ENTROPY_REQ_SZ (4 * 1024) + +/** + * struct optee_rng_private - OP-TEE Random Number Generator private data + * @dev: OP-TEE based RNG device. + * @ctx: OP-TEE context handler. + * @session_id:RNG TA session identifier. + * @data_rate: RNG data rate. + * @entropy_shm_pool: Memory pool shared with RNG device. + * @optee_rng: OP-TEE RNG driver structure. + */ +struct optee_rng_private { + struct device *dev; + struct tee_context *ctx; + u32 session_id; + u32 data_rate; + struct tee_shm *entropy_shm_pool; + struct hwrng optee_rng; +}; + +#define to_optee_rng_private(r) \ + container_of(r, struct optee_rng_private, optee_rng) + +static size_t get_optee_rng_data(struct optee_rng_private *pvt_data, +void *buf, size_t req_size) +{ + u32 ret = 0; + u8 *rng_data = NULL; + size_t rng_size = 0; + struct tee_ioctl_invoke_arg inv_arg = {0}; + struct tee_param param[4] = {0}; + + /* Invoke TA_CMD_GET_ENTROPY function of Trusted App */ + inv_arg.func = TA_CMD_GET_ENTROPY; + inv_arg.session = pvt_data->session_id; +
[PATCH v6 0/4] Introduce TEE bus driver framework
This series introduces a generic TEE bus driver concept for TEE based kernel drivers which would like to communicate with TEE based devices/ services. Patch #1 adds TEE bus concept where devices/services are identified via Universally Unique Identifier (UUID) and drivers register a table of device UUIDs which they can support. This concept also allows for device enumeration to be specific to corresponding TEE implementation like OP-TEE etc. Patch #2 adds supp_nowait flag for non-blocking requests arising via TEE internal client interface. Patch #3 adds TEE bus device enumeration support for OP-TEE. OP-TEE provides a pseudo TA to enumerate TAs which can act as devices/services for TEE bus. Patch #4 adds OP-TEE based hwrng driver which act as TEE bus driver. On ARM SoC's with TrustZone enabled, peripherals like entropy sources might not be accessible to normal world (linux in this case) and rather accessible to secure world (OP-TEE in this case) only. So this driver aims to provides a generic interface to OP-TEE based random number generator service. Example case is Developerbox based on Socionext's Synquacer SoC [1] which provides 7 thermal sensors accessible from secure world only which could be used as entropy sources (thermal/measurement noise). [1] https://www.96boards.org/product/developerbox/ Changes in v6: 1. Incorporate some nitpicks in patch #1 and #3. 2. Bundle all statics in a data structure in patch #4 and use dev_* instead of pr_*. 3. Add reviewed-by tags for patch #1, #2 and #3. Changes in v5: 1. Add support in module device table for TEE bus devices. 2. Correct license for optee-rng module. Changes in v4: 1. Use typedef instead of single member tee_client_device_id struct. 2. Incorporate TEE bus nitpicks. Changes in v3: 1. Fixed bus error path in Patch #1. 2. Reversed order of Patch #2 and #3. 3. Fixed miscellaneous syntax comments and memory leak. 4. Added comments in Patch #2 for supp_nowait flag. Changes in v2: Based on review comments, the scope of this series has increased as follows: 1. Added TEE bus driver framework. 2. Added OP-TEE based device enumeration. 3. Register optee-rng driver as TEE bus driver. 4. Removed DT dependency for optee-rng device UUID. 5. Added supp_nowait flag. Sumit Garg (4): tee: add bus driver framework for TEE based devices tee: add supp_nowait flag in tee_context struct tee: optee: add TEE bus device enumeration support hwrng: add OP-TEE based rng driver MAINTAINERS| 5 + drivers/char/hw_random/Kconfig | 15 ++ drivers/char/hw_random/Makefile| 1 + drivers/char/hw_random/optee-rng.c | 298 + drivers/tee/optee/Makefile | 1 + drivers/tee/optee/core.c | 4 + drivers/tee/optee/device.c | 155 +++ drivers/tee/optee/optee_private.h | 3 + drivers/tee/optee/supp.c | 10 +- drivers/tee/tee_core.c | 67 - include/linux/mod_devicetable.h| 9 ++ include/linux/tee_drv.h| 38 - scripts/mod/devicetable-offsets.c | 3 + scripts/mod/file2alias.c | 19 +++ 14 files changed, 622 insertions(+), 6 deletions(-) create mode 100644 drivers/char/hw_random/optee-rng.c create mode 100644 drivers/tee/optee/device.c -- 2.7.4
Re: [PATCH v2 1/2] PCI: hv: Replace hv_vp_set with hv_vpset
On Sun, Jan 27, 2019 at 05:11:48AM +, Michael Kelley wrote: > From: Maya Nakamura Sent: Saturday, January 26, > 2019 12:52 AM > > > > Remove a duplicate definition of VP set (hv_vp_set) and use the common > > definition (hv_vpset) that is used in other places. > > > > Change the order of the members in struct hv_pcibus_device so that the > > declaration of retarget_msi_interrupt_params is the last member. Struct > > hv_vpset, which contains a flexible array, is nested two levels deep in > > struct hv_pcibus_device via retarget_msi_interrupt_params. > > > > Add a comment that retarget_msi_interrupt_params should be the last member > > of struct hv_pcibus_device. > > > > Signed-off-by: Maya Nakamura > > --- > > Change in v2: > > - None > > > > Right -- there was no code change. But it's customary to note that > you updated the commit message. > Thank you for your feedback. I will edit the change log in v3. > Reviewed-by: Michael Kelley
[PATCH] parport_pc.c change for fix hanging problem while suspend machine. parport_pc.c has the samevendor id and device id definition as sunix multi-I/O board driver, when the sunix multi-io board dr
Signed-off-by: saumah --- parport_pc.c | 17 + 1 file changed, 1 insertion(+), 16 deletions(-) diff --git a/parport_pc.c b/parport_pc.c index 380916b..8c163b9 100644 --- a/parport_pc.c +++ b/parport_pc.c @@ -2622,11 +2622,6 @@ enum parport_pc_pci_cards { lava_parallel_dual_b, boca_ioppar, plx_9050, - timedia_4006a, - timedia_4014, - timedia_4008a, - timedia_4018, - timedia_9018a, syba_2p_epp, syba_1p_ecp, titan_010l, @@ -2679,11 +2674,7 @@ static struct parport_pc_pci { /* lava_parallel_dual_b */ { 1, { { 0, -1 }, } }, /* boca_ioppar */ { 1, { { 0, -1 }, } }, /* plx_9050 */ { 2, { { 4, -1 }, { 5, -1 }, } }, - /* timedia_4006a */ { 1, { { 0, -1 }, } }, - /* timedia_4014 */ { 2, { { 0, -1 }, { 2, -1 }, } }, - /* timedia_4008a */ { 1, { { 0, 1 }, } }, - /* timedia_4018 */ { 2, { { 0, 1 }, { 2, 3 }, } }, - /* timedia_9018a */ { 2, { { 0, 1 }, { 2, 3 }, } }, + /* SYBA uses fixed offsets in a 1K io window */ /* syba_2p_epp AP138B */{ 2, { { 0, 0x078 }, { 0, 0x178 }, } }, @@ -2738,12 +2729,6 @@ static const struct pci_device_id parport_pc_pci_tbl[] = { PCI_ANY_ID, PCI_ANY_ID, 0, 0, boca_ioppar }, { PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_9050, PCI_SUBVENDOR_ID_EXSYS, PCI_SUBDEVICE_ID_EXSYS_4014, 0, 0, plx_9050 }, - /* PCI_VENDOR_ID_TIMEDIA/SUNIX has many differing cards ...*/ - { 0x1409, 0x7268, 0x1409, 0x0101, 0, 0, timedia_4006a }, - { 0x1409, 0x7268, 0x1409, 0x0102, 0, 0, timedia_4014 }, - { 0x1409, 0x7268, 0x1409, 0x0103, 0, 0, timedia_4008a }, - { 0x1409, 0x7268, 0x1409, 0x0104, 0, 0, timedia_4018 }, - { 0x1409, 0x7268, 0x1409, 0x9018, 0, 0, timedia_9018a }, { PCI_VENDOR_ID_SYBA, PCI_DEVICE_ID_SYBA_2P_EPP, PCI_ANY_ID, PCI_ANY_ID, 0, 0, syba_2p_epp }, { PCI_VENDOR_ID_SYBA, PCI_DEVICE_ID_SYBA_1P_ECP, -- 2.17.1
Re: [PATCH v5 2/9] cpufreq: Auto-register the driver as a thermal cooling device if asked
On Tue, Jan 29, 2019 at 11:06 AM Viresh Kumar wrote: > > On 29-01-19, 10:25, Amit Kucheria wrote: > > All cpufreq drivers do similar things to register as a cooling device. > > Provide a cpufreq driver flag so drivers can just ask the cpufreq core > > to register the cooling device on their behalf. This allows us to get > > rid of duplicated code in the drivers. > > > > In order to allow this, we add a struct thermal_cooling_device pointer > > to struct cpufreq_policy so that drivers don't need to store it in a > > private data structure. > > > > Suggested-by: Stephen Boyd > > Suggested-by: Viresh Kumar > > Signed-off-by: Amit Kucheria > > Reviewed-by: Matthias Kaehlcke > > Tested-by: Matthias Kaehlcke > > Acked-by: Viresh Kumar > > --- > > drivers/cpufreq/cpufreq.c | 13 + > > include/linux/cpufreq.h | 9 + > > 2 files changed, 22 insertions(+) > > > > diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c > > index e35a886e00bc..0f9b50d3ee91 100644 > > --- a/drivers/cpufreq/cpufreq.c > > +++ b/drivers/cpufreq/cpufreq.c > > @@ -19,6 +19,7 @@ > > > > #include > > #include > > +#include > > #include > > #include > > #include > > @@ -1318,6 +1319,11 @@ static int cpufreq_online(unsigned int cpu) > > if (cpufreq_driver->ready) > > cpufreq_driver->ready(policy); > > > > +#if IS_ENABLED(CONFIG_CPU_THERMAL) > > + if (cpufreq_driver->flags & CPUFREQ_IS_COOLING_DEV) > > + policy->cdev = of_cpufreq_cooling_register(policy); > > +#endif > > I am not sure if Rafael wanted it this way but maybe something like this: > > if (IS_ENABLED(CONFIG_CPU_THERMAL) && > cpufreq_driver->flags & CPUFREQ_IS_COOLING_DEV)) > policy->cdev = of_cpufreq_cooling_register(policy); > > We never wanted ifdef hackery to be in there :) OK, that makes more sense. Should I just send out a fixup patch or the entire series?
Re: [PATCH v2] mm/slub: introduce SLAB_WARN_ON_ERROR
On Mon, 28 Jan 2019, Andrew Morton wrote: > > When debugging slab errors in slub.c, sometimes we have to trigger > > a panic in order to get the coredump file. Add a debug option > > SLAB_WARN_ON_ERROR to toggle WARN_ON() when the option is set. > > > > Change since v1: > > 1. Add a special debug option SLAB_WARN_ON_ERROR and toggle WARN_ON() > > if it is set. > > 2. SLAB_WARN_ON_ERROR can be set by kernel parameter slub_debug. > > > > Hopefully the slab developers will have an opinion on this. Debugging slab itself is usually done in kvm or some other virtualized environment. Then gdb can be used to set breakpoints. Otherwise one may add printks and stuff to the allocators to figure out more or use perf. What you are changing here is the debugging for data corruption within objects managed by slub or the metadata. Slub currently outputs extensive data about the metadata corruption (typically caused by a user of slab allocation) which should allow you to set a proper breakpoint not in the allocator but in the subsystem where the corruption occurs.
Re: [PATCH] irqchip/gic-v3-its: Lock its device list during find and create its device
On 2019/1/28 21:51, Marc Zyngier wrote: > On 28/01/2019 07:13, Zheng Xiang wrote: >> Hi Marc, >> >> Thanks for your review. >> >> On 2019/1/26 19:38, Marc Zyngier wrote: >>> Hi Zheng, >>> >>> On Sat, 26 Jan 2019 06:16:24 +, >>> Zheng Xiang wrote: Currently each PCI device under a PCI Bridge shares the same device id and ITS device. Assume there are two PCI devices call its_msi_prepare concurrently and they are both going to find and create their ITS device. There is a chance that the later one couldn't find ITS device before the other one creating the ITS device. It will cause the later one to create a different ITS device even if they have the same device_id. >>> >>> Interesting finding. Is this something you've actually seen in practice >>> with two devices being probed in parallel? Or something that you found >>> by inspection? >> >> Yes, I find this problem after analyzing the reason of VM hung. At last, I >> find that the virtio-gpu cannot receive the MSI interrupts due to sharing >> a same event_id as virtio-serial. >> >> See https://lkml.org/lkml/2019/1/10/299 for the bug report. >> >> This problem can be reproducted with high probability by booting a Qemu/KVM >> VM with a virtio-serial controller and a virtio-gpu adding to a PCI Bridge >> and also adding some delay before creating ITS device. > > Fair enough. Do you mind sharing your QEMU command line? It'd be useful > if I could reproduce it here (and would give me a way to check that it > doesn't regress). Yes of course, my QEMU command line is below: qemu-system-aarch64 \ -name guest=arm64 \ -machine virt,accel=kvm,usb=off,gic-version=3 \ -cpu host \ -bios /usr/share/edk2/aarch64/QEMU_EFI.fd \ -nodefaults \ -m 2048 \ -smp 1 \ -device ioh3420,port=0x8,chassis=1,id=pci.1,bus=pcie.0,multifunction=on,addr=0x1 \ -device i82801b11-bridge,id=pci.2,bus=pcie.0,addr=0x2 \ -device pci-bridge,chassis_nr=3,id=pci.3,bus=pci.2,addr=0x0 \ -device ioh3420,port=0x9,chassis=4,id=pci.4,bus=pcie.0,addr=0x1.0x1 \ -device virtio-scsi-pci,id=scsi0,bus=pci.4,addr=0x0 \ -drive file=/home/zhengxiang/tmp.raw,format=raw,if=none,id=drive-scsi0-0-0-0,cache=none,aio=threads \ -device scsi-hd,bus=scsi0.0,channel=0,scsi-id=0,lun=0,drive=drive-scsi0-0-0-0,id=scsi0-0-0-0,bootindex=1 \ -drive file=/dev/mapper/VolGroup00-lvol_7,format=raw,if=none,id=drive-virtio-disk0,cache=none,aio=threads \ -device virtio-blk-pci,scsi=off,bus=pci.1,addr=0x0,drive=drive-virtio-disk0,id=virtio-disk0 \ -device virtio-gpu-pci,id=video0,bus=pci.3,addr=0x2 \ -device virtio-serial-pci,id=virtio-serial0,bus=pci.3,addr=0x3 \ -device usb-ehci,id=usb,bus=pci.3,addr=0x1 \ -device usb-kbd,id=input1,bus=usb.0,port=2 \ -monitor telnet:0.0.0.0:2,server,nowait \ -vnc 0.0.0.0:8 \ -msg timestamp=on \ -serial stdio \ Add *msleep* between *its_find_device* and *its_create_device* to increase the rate of probability, . > >> >>> >>> The whole RID aliasing is such a mess, I wish we never supported >>> it. Anyway, comments below. >>> Signed-off-by: Zheng Xiang --- drivers/irqchip/irq-gic-v3-its.c | 52 +++- 1 file changed, 19 insertions(+), 33 deletions(-) diff --git a/drivers/irqchip/irq-gic-v3-its.c b/drivers/irqchip/irq-gic-v3-its.c index db20e99..397edc8 100644 --- a/drivers/irqchip/irq-gic-v3-its.c +++ b/drivers/irqchip/irq-gic-v3-its.c @@ -2205,25 +2205,6 @@ static void its_cpu_init_collections(void) raw_spin_unlock(_lock); } -static struct its_device *its_find_device(struct its_node *its, u32 dev_id) -{ - struct its_device *its_dev = NULL, *tmp; - unsigned long flags; - - raw_spin_lock_irqsave(>lock, flags); - - list_for_each_entry(tmp, >its_device_list, entry) { - if (tmp->device_id == dev_id) { - its_dev = tmp; - break; - } - } - - raw_spin_unlock_irqrestore(>lock, flags); - - return its_dev; -} - static struct its_baser *its_get_baser(struct its_node *its, u32 type) { int i; @@ -2321,7 +2302,7 @@ static bool its_alloc_vpe_table(u32 vpe_id) static struct its_device *its_create_device(struct its_node *its, u32 dev_id, int nvecs, bool alloc_lpis) { - struct its_device *dev; + struct its_device *dev = NULL, *tmp; unsigned long *lpi_map = NULL; unsigned long flags; u16 *col_map = NULL; @@ -2331,6 +2312,24 @@ static struct its_device *its_create_device(struct its_node *its, u32 dev_id, int nr_ites; int sz; + raw_spin_lock_irqsave(>lock, flags); + list_for_each_entry(tmp, >its_device_list, entry) { +
Re: [PATCH] scsi: hpsa: clean up two indentation issues
Colin, > There are two statements that are indented incorrectly. Fix these. Applied to 5.1/scsi-queue, thanks. -- Martin K. Petersen Oracle Linux Engineering
Re: [RESEND PATCH v2 8/8] Input: sx8654 - convert #defined flags to BIT(x)
On Mon, 2019-01-28 at 16:25 -0800, Dmitry Torokhov wrote: > On Tue, Dec 18, 2018 at 09:40:02AM +0100, Richard Leitner wrote: > > Some of the #defined register values are one-bit flags. Convert them to > > use the BIT(x) macro instead of 1 byte hexadecimal values. This improves > > readability and clarifies the intent. > > > > Signed-off-by: Richard Leitner > > Applied, thank you. Not so sure this should be applied. > > diff --git a/drivers/input/touchscreen/sx8654.c > > b/drivers/input/touchscreen/sx8654.c [] > > @@ -46,7 +47,7 @@ [] > > /* bits for I2C_REG_IRQSRC */ > > -#define IRQ_PENTOUCH_TOUCHCONVDONE 0x08 > > -#define IRQ_PENRELEASE 0x04 > > +#define IRQ_PENTOUCH_TOUCHCONVDONE BIT(7) > > +#define IRQ_PENRELEASE BIT(6) Shouldn't this be BIT(3) and BIT(2) or did you mean to change the values too? If so, this change should be noted in the commit message.
[PATCH] mm: Prevent mapping typed pages to userspace
Pages which use page_type must never be mapped to userspace as it would destroy their page type. Add an explicit check for this instead of assuming that kernel drivers always get this right. Signed-off-by: Matthew Wilcox --- mm/memory.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mm/memory.c b/mm/memory.c index ce8c90b752be..db3534bbd652 100644 --- a/mm/memory.c +++ b/mm/memory.c @@ -1451,7 +1451,7 @@ static int insert_page(struct vm_area_struct *vma, unsigned long addr, spinlock_t *ptl; retval = -EINVAL; - if (PageAnon(page) || PageSlab(page)) + if (PageAnon(page) || PageSlab(page) || page_has_type(page)) goto out; retval = -ENOMEM; flush_dcache_page(page); -- 2.20.1