Re: [PATCH] zram: fix null dereference of handle
On Tue, Sep 19, 2017 at 07:21:25PM +0900, Sergey Senozhatsky wrote: > Minchan, > > I just ran across it [because I had a bug to analize where this > part was involved]. I'd really prefer the kernel to BUG_ON immediately > instead of dying in agony. > > can we, please, return BUG_ON() back? > > there is no point in trying to save the kernel once it did that type > of violation. I agree. If it happens, it would corrupt other user's buffer which ends up leaking some private data from others so there is pointless to keep system alive to debug it. Do you mind sending a formal patch? Thanks! > > --- > > diff --git a/mm/zsmalloc.c b/mm/zsmalloc.c > index 7c38e850a8fc..685049a9048d 100644 > --- a/mm/zsmalloc.c > +++ b/mm/zsmalloc.c > @@ -1349,7 +1349,7 @@ void *zs_map_object(struct zs_pool *pool, unsigned long > handle, > * pools/users, we can't allow mapping in interrupt context > * because it can corrupt another users mappings. > */ > - WARN_ON_ONCE(in_interrupt()); > + BUG_ON(in_interrupt()); > > /* From now on, migration cannot move the object */ > pin_tag(handle); >
Re: [PATCH] zram: fix null dereference of handle
On Tue, Sep 19, 2017 at 07:21:25PM +0900, Sergey Senozhatsky wrote: > Minchan, > > I just ran across it [because I had a bug to analize where this > part was involved]. I'd really prefer the kernel to BUG_ON immediately > instead of dying in agony. > > can we, please, return BUG_ON() back? > > there is no point in trying to save the kernel once it did that type > of violation. I agree. If it happens, it would corrupt other user's buffer which ends up leaking some private data from others so there is pointless to keep system alive to debug it. Do you mind sending a formal patch? Thanks! > > --- > > diff --git a/mm/zsmalloc.c b/mm/zsmalloc.c > index 7c38e850a8fc..685049a9048d 100644 > --- a/mm/zsmalloc.c > +++ b/mm/zsmalloc.c > @@ -1349,7 +1349,7 @@ void *zs_map_object(struct zs_pool *pool, unsigned long > handle, > * pools/users, we can't allow mapping in interrupt context > * because it can corrupt another users mappings. > */ > - WARN_ON_ONCE(in_interrupt()); > + BUG_ON(in_interrupt()); > > /* From now on, migration cannot move the object */ > pin_tag(handle); >
Re: Error when building the kernel on top of 4.14-rc1 for target firmware_install?
On Wed, Sep 20, 2017 at 1:37 PM, Greg Kroah-Hartmanwrote: > On Wed, Sep 20, 2017 at 11:20:19AM +0800, Yu Chen wrote: >> Hi, >> kernel compile failed after running # make rpm >> >> + >> INSTALL_FW_PATH=/root/rpmbuild/BUILDROOT/kernel-4.14.0_rc1+-22.x86_64/lib/firmware/4.14.0-rc1+ >> + make >> INSTALL_FW_PATH=/root/rpmbuild/BUILDROOT/kernel-4.14.0_rc1+-22.x86_64/lib/firmware/4.14.0-rc1+ >> firmware_install >> make[2]: warning: jobserver unavailable: using -j1. Add '+' to parent >> make rule. >> make[2]: *** No rule to make target 'firmware_install'. Stop. >> >> I have to hack the script to compile through: >> diff --git a/scripts/package/mkspec b/scripts/package/mkspec >> index bb43f15..cb9c1b3 100755 >> --- a/scripts/package/mkspec >> +++ b/scripts/package/mkspec >> @@ -92,7 +92,7 @@ echo 'mkdir -p >> $RPM_BUILD_ROOT'"/lib/firmware/$KERNELRELEASE" >> >> echo 'INSTALL_MOD_PATH=$RPM_BUILD_ROOT make %{?_smp_mflags} >> KBUILD_SRC= mod-fw= modules_install' >> echo 'INSTALL_FW_PATH=$RPM_BUILD_ROOT'"/lib/firmware/$KERNELRELEASE" >> -echo 'make INSTALL_FW_PATH=$INSTALL_FW_PATH' firmware_install >> +echo 'make INSTALL_FW_PATH=$INSTALL_FW_PATH' >> echo "%ifarch ia64" >> >> Not sure if this is a regression but several version ago it works well. > > See the maling list for fixes for this already :) > > thanks, > > greg k-h Got it! thanks.
Re: [PATCH v2 3/5] dmaengine: zynqmp_ps_pcie: Adding PS PCIe DMA driver
On 8.9.2017 14:23, Ravi Shankar Jonnalagadda wrote: > Adding support for ZynqmMP PS PCIe EP driver. > Adding support for ZynqmMP PS PCIe Root DMA driver. > Modifying Kconfig and Makefile to add the support. > > Signed-off-by: Ravi Shankar Jonnalagadda> Signed-off-by: RaviKiran Gummaluri > --- > drivers/dma/Kconfig | 12 +++ > drivers/dma/xilinx/Makefile | 2 + > drivers/dma/xilinx/ps_pcie.h | 44 + > drivers/dma/xilinx/ps_pcie_main.c | 200 > ++ > include/linux/dma/ps_pcie_dma.h | 69 + > 5 files changed, 327 insertions(+) > create mode 100644 drivers/dma/xilinx/ps_pcie.h > create mode 100644 drivers/dma/xilinx/ps_pcie_main.c > create mode 100644 include/linux/dma/ps_pcie_dma.h > > diff --git a/drivers/dma/Kconfig b/drivers/dma/Kconfig > index fa8f9c0..e2fe4e5 100644 > --- a/drivers/dma/Kconfig > +++ b/drivers/dma/Kconfig > @@ -586,6 +586,18 @@ config XILINX_ZYNQMP_DMA > help > Enable support for Xilinx ZynqMP DMA controller. > > +config XILINX_PS_PCIE_DMA > + tristate "Xilinx PS PCIe DMA support" > + depends on (PCI && X86_64 || ARM64) > + select DMA_ENGINE > + help > + Enable support for the Xilinx PS PCIe DMA engine present > + in recent Xilinx ZynqMP chipsets. > + > + Say Y here if you have such a chipset. > + > + If unsure, say N. > + > config ZX_DMA > tristate "ZTE ZX DMA support" > depends on ARCH_ZX || COMPILE_TEST > diff --git a/drivers/dma/xilinx/Makefile b/drivers/dma/xilinx/Makefile > index 9e91f8f..04f6f99 100644 > --- a/drivers/dma/xilinx/Makefile > +++ b/drivers/dma/xilinx/Makefile > @@ -1,2 +1,4 @@ > obj-$(CONFIG_XILINX_DMA) += xilinx_dma.o > obj-$(CONFIG_XILINX_ZYNQMP_DMA) += zynqmp_dma.o > +ps_pcie_dma-objs := ps_pcie_main.o ps_pcie_platform.o > +obj-$(CONFIG_XILINX_PS_PCIE_DMA) += ps_pcie_dma.o > diff --git a/drivers/dma/xilinx/ps_pcie.h b/drivers/dma/xilinx/ps_pcie.h > new file mode 100644 > index 000..351f051 > --- /dev/null > +++ b/drivers/dma/xilinx/ps_pcie.h > @@ -0,0 +1,44 @@ > +/* > + * Xilinx PS PCIe DMA Engine platform header file > + * > + * Copyright (C) 2010-2017 Xilinx, Inc. All rights reserved. > + * > + * This program is free software: you can redistribute it and/or modify > + * it under the terms of the GNU General Public License version 2 as > + * published by the Free Software Foundation > + */ > + > +#ifndef __XILINX_PS_PCIE_H > +#define __XILINX_PS_PCIE_H > + > +#include > +#include this is included via dma-mapping.h below. > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include this is already include via of.h > +#include > +#include > +#include Don't we have any script for checking this? > + > +/** > + * dma_platform_driver_register - This will be invoked by module init > + * > + * Return: returns status of platform_driver_register > + */ > +int dma_platform_driver_register(void); put empty line here. > +/** > + * dma_platform_driver_unregister - This will be invoked by module exit > + * > + * Return: returns void after unregustering platform driver > + */ > +void dma_platform_driver_unregister(void); > + > +#endif > diff --git a/drivers/dma/xilinx/ps_pcie_main.c > b/drivers/dma/xilinx/ps_pcie_main.c > new file mode 100644 > index 000..4ccd8ef > --- /dev/null > +++ b/drivers/dma/xilinx/ps_pcie_main.c > @@ -0,0 +1,200 @@ > +/* > + * XILINX PS PCIe driver > + * > + * Copyright (C) 2017 Xilinx, Inc. All rights reserved. > + * > + * Description > + * PS PCIe DMA is memory mapped DMA used to execute PS to PL transfers > + * on ZynqMP UltraScale+ Devices. > + * This PCIe driver creates a platform device with specific platform > + * info enabling creation of DMA device corresponding to the channel > + * information provided in the properties > + * > + * This program is free software: you can redistribute it and/or modify > + * it under the terms of the GNU General Public License version 2 as > + * published by the Free Software Foundation > + */ > + > +#include "ps_pcie.h" > +#include "../dmaengine.h" > + > +#define DRV_MODULE_NAME"ps_pcie_dma" > + > +static int ps_pcie_dma_probe(struct pci_dev *pdev, > + const struct pci_device_id *ent); > +static void ps_pcie_dma_remove(struct pci_dev *pdev); > + > +static u32 channel_properties_pcie_axi[] = { > + (u32)(PCIE_AXI_DIRECTION), (u32)(NUMBER_OF_BUFFER_DESCRIPTORS), > + (u32)(DEFAULT_DMA_QUEUES), (u32)(CHANNEL_COAELSE_COUNT), > + (u32)(CHANNEL_POLL_TIMER_FREQUENCY) }; > + > +static u32 channel_properties_axi_pcie[] = { > + (u32)(AXI_PCIE_DIRECTION), (u32)(NUMBER_OF_BUFFER_DESCRIPTORS), > + (u32)(DEFAULT_DMA_QUEUES), (u32)(CHANNEL_COAELSE_COUNT), > + (u32)(CHANNEL_POLL_TIMER_FREQUENCY) }; > + > +static struct property_entry generic_pcie_ep_property[]
Re: Error when building the kernel on top of 4.14-rc1 for target firmware_install?
On Wed, Sep 20, 2017 at 1:37 PM, Greg Kroah-Hartman wrote: > On Wed, Sep 20, 2017 at 11:20:19AM +0800, Yu Chen wrote: >> Hi, >> kernel compile failed after running # make rpm >> >> + >> INSTALL_FW_PATH=/root/rpmbuild/BUILDROOT/kernel-4.14.0_rc1+-22.x86_64/lib/firmware/4.14.0-rc1+ >> + make >> INSTALL_FW_PATH=/root/rpmbuild/BUILDROOT/kernel-4.14.0_rc1+-22.x86_64/lib/firmware/4.14.0-rc1+ >> firmware_install >> make[2]: warning: jobserver unavailable: using -j1. Add '+' to parent >> make rule. >> make[2]: *** No rule to make target 'firmware_install'. Stop. >> >> I have to hack the script to compile through: >> diff --git a/scripts/package/mkspec b/scripts/package/mkspec >> index bb43f15..cb9c1b3 100755 >> --- a/scripts/package/mkspec >> +++ b/scripts/package/mkspec >> @@ -92,7 +92,7 @@ echo 'mkdir -p >> $RPM_BUILD_ROOT'"/lib/firmware/$KERNELRELEASE" >> >> echo 'INSTALL_MOD_PATH=$RPM_BUILD_ROOT make %{?_smp_mflags} >> KBUILD_SRC= mod-fw= modules_install' >> echo 'INSTALL_FW_PATH=$RPM_BUILD_ROOT'"/lib/firmware/$KERNELRELEASE" >> -echo 'make INSTALL_FW_PATH=$INSTALL_FW_PATH' firmware_install >> +echo 'make INSTALL_FW_PATH=$INSTALL_FW_PATH' >> echo "%ifarch ia64" >> >> Not sure if this is a regression but several version ago it works well. > > See the maling list for fixes for this already :) > > thanks, > > greg k-h Got it! thanks.
Re: [PATCH v2 3/5] dmaengine: zynqmp_ps_pcie: Adding PS PCIe DMA driver
On 8.9.2017 14:23, Ravi Shankar Jonnalagadda wrote: > Adding support for ZynqmMP PS PCIe EP driver. > Adding support for ZynqmMP PS PCIe Root DMA driver. > Modifying Kconfig and Makefile to add the support. > > Signed-off-by: Ravi Shankar Jonnalagadda > Signed-off-by: RaviKiran Gummaluri > --- > drivers/dma/Kconfig | 12 +++ > drivers/dma/xilinx/Makefile | 2 + > drivers/dma/xilinx/ps_pcie.h | 44 + > drivers/dma/xilinx/ps_pcie_main.c | 200 > ++ > include/linux/dma/ps_pcie_dma.h | 69 + > 5 files changed, 327 insertions(+) > create mode 100644 drivers/dma/xilinx/ps_pcie.h > create mode 100644 drivers/dma/xilinx/ps_pcie_main.c > create mode 100644 include/linux/dma/ps_pcie_dma.h > > diff --git a/drivers/dma/Kconfig b/drivers/dma/Kconfig > index fa8f9c0..e2fe4e5 100644 > --- a/drivers/dma/Kconfig > +++ b/drivers/dma/Kconfig > @@ -586,6 +586,18 @@ config XILINX_ZYNQMP_DMA > help > Enable support for Xilinx ZynqMP DMA controller. > > +config XILINX_PS_PCIE_DMA > + tristate "Xilinx PS PCIe DMA support" > + depends on (PCI && X86_64 || ARM64) > + select DMA_ENGINE > + help > + Enable support for the Xilinx PS PCIe DMA engine present > + in recent Xilinx ZynqMP chipsets. > + > + Say Y here if you have such a chipset. > + > + If unsure, say N. > + > config ZX_DMA > tristate "ZTE ZX DMA support" > depends on ARCH_ZX || COMPILE_TEST > diff --git a/drivers/dma/xilinx/Makefile b/drivers/dma/xilinx/Makefile > index 9e91f8f..04f6f99 100644 > --- a/drivers/dma/xilinx/Makefile > +++ b/drivers/dma/xilinx/Makefile > @@ -1,2 +1,4 @@ > obj-$(CONFIG_XILINX_DMA) += xilinx_dma.o > obj-$(CONFIG_XILINX_ZYNQMP_DMA) += zynqmp_dma.o > +ps_pcie_dma-objs := ps_pcie_main.o ps_pcie_platform.o > +obj-$(CONFIG_XILINX_PS_PCIE_DMA) += ps_pcie_dma.o > diff --git a/drivers/dma/xilinx/ps_pcie.h b/drivers/dma/xilinx/ps_pcie.h > new file mode 100644 > index 000..351f051 > --- /dev/null > +++ b/drivers/dma/xilinx/ps_pcie.h > @@ -0,0 +1,44 @@ > +/* > + * Xilinx PS PCIe DMA Engine platform header file > + * > + * Copyright (C) 2010-2017 Xilinx, Inc. All rights reserved. > + * > + * This program is free software: you can redistribute it and/or modify > + * it under the terms of the GNU General Public License version 2 as > + * published by the Free Software Foundation > + */ > + > +#ifndef __XILINX_PS_PCIE_H > +#define __XILINX_PS_PCIE_H > + > +#include > +#include this is included via dma-mapping.h below. > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include this is already include via of.h > +#include > +#include > +#include Don't we have any script for checking this? > + > +/** > + * dma_platform_driver_register - This will be invoked by module init > + * > + * Return: returns status of platform_driver_register > + */ > +int dma_platform_driver_register(void); put empty line here. > +/** > + * dma_platform_driver_unregister - This will be invoked by module exit > + * > + * Return: returns void after unregustering platform driver > + */ > +void dma_platform_driver_unregister(void); > + > +#endif > diff --git a/drivers/dma/xilinx/ps_pcie_main.c > b/drivers/dma/xilinx/ps_pcie_main.c > new file mode 100644 > index 000..4ccd8ef > --- /dev/null > +++ b/drivers/dma/xilinx/ps_pcie_main.c > @@ -0,0 +1,200 @@ > +/* > + * XILINX PS PCIe driver > + * > + * Copyright (C) 2017 Xilinx, Inc. All rights reserved. > + * > + * Description > + * PS PCIe DMA is memory mapped DMA used to execute PS to PL transfers > + * on ZynqMP UltraScale+ Devices. > + * This PCIe driver creates a platform device with specific platform > + * info enabling creation of DMA device corresponding to the channel > + * information provided in the properties > + * > + * This program is free software: you can redistribute it and/or modify > + * it under the terms of the GNU General Public License version 2 as > + * published by the Free Software Foundation > + */ > + > +#include "ps_pcie.h" > +#include "../dmaengine.h" > + > +#define DRV_MODULE_NAME"ps_pcie_dma" > + > +static int ps_pcie_dma_probe(struct pci_dev *pdev, > + const struct pci_device_id *ent); > +static void ps_pcie_dma_remove(struct pci_dev *pdev); > + > +static u32 channel_properties_pcie_axi[] = { > + (u32)(PCIE_AXI_DIRECTION), (u32)(NUMBER_OF_BUFFER_DESCRIPTORS), > + (u32)(DEFAULT_DMA_QUEUES), (u32)(CHANNEL_COAELSE_COUNT), > + (u32)(CHANNEL_POLL_TIMER_FREQUENCY) }; > + > +static u32 channel_properties_axi_pcie[] = { > + (u32)(AXI_PCIE_DIRECTION), (u32)(NUMBER_OF_BUFFER_DESCRIPTORS), > + (u32)(DEFAULT_DMA_QUEUES), (u32)(CHANNEL_COAELSE_COUNT), > + (u32)(CHANNEL_POLL_TIMER_FREQUENCY) }; > + > +static struct property_entry generic_pcie_ep_property[] = { > +
[PATCH v2 4/4] mm:swap: skip swapcache for swapin of synchronous device
With fast swap storage, platform want to use swap more aggressively and swap-in is crucial to application latency. The rw_page based synchronous devices like zram, pmem and btt are such fast storage. When I profile swapin performance with zram lz4 decompress test, S/W overhead is more than 70%. Maybe, it would be bigger in nvdimm. This patch aims for reducing swap-in latency via skipping swapcache if swap device is synchronous device like rw_page based device. It enhances 45% my swapin test(5G sequential swapin, no readahead, from 2.41sec to 1.64sec). Cc: Dan WilliamsCc: Ross Zwisler Cc: Hugh Dickins Signed-off-by: Minchan Kim --- include/linux/swap.h | 11 +++ mm/memory.c | 52 mm/page_io.c | 6 +++--- mm/swapfile.c| 11 +++ 4 files changed, 57 insertions(+), 23 deletions(-) diff --git a/include/linux/swap.h b/include/linux/swap.h index fbb33919d1c6..cd2f66fdfc2d 100644 --- a/include/linux/swap.h +++ b/include/linux/swap.h @@ -461,6 +461,7 @@ extern int page_swapcount(struct page *); extern int __swp_swapcount(swp_entry_t entry); extern int swp_swapcount(swp_entry_t entry); extern struct swap_info_struct *page_swap_info(struct page *); +extern struct swap_info_struct *swp_swap_info(swp_entry_t entry); extern bool reuse_swap_page(struct page *, int *); extern int try_to_free_swap(struct page *); struct backing_dev_info; @@ -469,6 +470,16 @@ extern void exit_swap_address_space(unsigned int type); #else /* CONFIG_SWAP */ +static inline int swap_readpage(struct page *page, bool do_poll) +{ + return 0; +} + +static inline struct swap_info_struct *swp_swap_info(swp_entry_t entry) +{ + return NULL; +} + #define swap_address_space(entry) (NULL) #define get_nr_swap_pages()0L #define total_swap_pages 0L diff --git a/mm/memory.c b/mm/memory.c index ec4e15494901..163ab2062385 100644 --- a/mm/memory.c +++ b/mm/memory.c @@ -2842,7 +2842,7 @@ EXPORT_SYMBOL(unmap_mapping_range); int do_swap_page(struct vm_fault *vmf) { struct vm_area_struct *vma = vmf->vma; - struct page *page = NULL, *swapcache; + struct page *page = NULL, *swapcache = NULL; struct mem_cgroup *memcg; struct vma_swap_readahead swap_ra; swp_entry_t entry; @@ -2881,17 +2881,35 @@ int do_swap_page(struct vm_fault *vmf) } goto out; } + + delayacct_set_flag(DELAYACCT_PF_SWAPIN); if (!page) page = lookup_swap_cache(entry, vma_readahead ? vma : NULL, vmf->address); if (!page) { - if (vma_readahead) - page = do_swap_page_readahead(entry, - GFP_HIGHUSER_MOVABLE, vmf, _ra); - else - page = swapin_readahead(entry, - GFP_HIGHUSER_MOVABLE, vma, vmf->address); + struct swap_info_struct *si = swp_swap_info(entry); + + if (!(si->flags & SWP_SYNCHRONOUS_IO)) { + if (vma_readahead) + page = do_swap_page_readahead(entry, + GFP_HIGHUSER_MOVABLE, vmf, _ra); + else + page = swapin_readahead(entry, + GFP_HIGHUSER_MOVABLE, vma, vmf->address); + swapcache = page; + } else { + /* skip swapcache */ + page = alloc_page_vma(GFP_HIGHUSER_MOVABLE, vma, vmf->address); + if (page) { + __SetPageLocked(page); + __SetPageSwapBacked(page); + set_page_private(page, entry.val); + lru_cache_add_anon(page); + swap_readpage(page, true); + } + } + if (!page) { /* * Back out if somebody else faulted in this pte @@ -2920,7 +2938,6 @@ int do_swap_page(struct vm_fault *vmf) goto out_release; } - swapcache = page; locked = lock_page_or_retry(page, vma->vm_mm, vmf->flags); delayacct_clear_flag(DELAYACCT_PF_SWAPIN); @@ -2935,7 +2952,8 @@ int do_swap_page(struct vm_fault *vmf) * test below, are not enough to exclude that. Even if it is still * swapcache, we need to check that the page's swap has not changed. */ - if (unlikely(!PageSwapCache(page) || page_private(page) != entry.val)) + if (unlikely((!PageSwapCache(page) || + page_private(page) != entry.val)) && swapcache)
[PATCH v2 4/4] mm:swap: skip swapcache for swapin of synchronous device
With fast swap storage, platform want to use swap more aggressively and swap-in is crucial to application latency. The rw_page based synchronous devices like zram, pmem and btt are such fast storage. When I profile swapin performance with zram lz4 decompress test, S/W overhead is more than 70%. Maybe, it would be bigger in nvdimm. This patch aims for reducing swap-in latency via skipping swapcache if swap device is synchronous device like rw_page based device. It enhances 45% my swapin test(5G sequential swapin, no readahead, from 2.41sec to 1.64sec). Cc: Dan Williams Cc: Ross Zwisler Cc: Hugh Dickins Signed-off-by: Minchan Kim --- include/linux/swap.h | 11 +++ mm/memory.c | 52 mm/page_io.c | 6 +++--- mm/swapfile.c| 11 +++ 4 files changed, 57 insertions(+), 23 deletions(-) diff --git a/include/linux/swap.h b/include/linux/swap.h index fbb33919d1c6..cd2f66fdfc2d 100644 --- a/include/linux/swap.h +++ b/include/linux/swap.h @@ -461,6 +461,7 @@ extern int page_swapcount(struct page *); extern int __swp_swapcount(swp_entry_t entry); extern int swp_swapcount(swp_entry_t entry); extern struct swap_info_struct *page_swap_info(struct page *); +extern struct swap_info_struct *swp_swap_info(swp_entry_t entry); extern bool reuse_swap_page(struct page *, int *); extern int try_to_free_swap(struct page *); struct backing_dev_info; @@ -469,6 +470,16 @@ extern void exit_swap_address_space(unsigned int type); #else /* CONFIG_SWAP */ +static inline int swap_readpage(struct page *page, bool do_poll) +{ + return 0; +} + +static inline struct swap_info_struct *swp_swap_info(swp_entry_t entry) +{ + return NULL; +} + #define swap_address_space(entry) (NULL) #define get_nr_swap_pages()0L #define total_swap_pages 0L diff --git a/mm/memory.c b/mm/memory.c index ec4e15494901..163ab2062385 100644 --- a/mm/memory.c +++ b/mm/memory.c @@ -2842,7 +2842,7 @@ EXPORT_SYMBOL(unmap_mapping_range); int do_swap_page(struct vm_fault *vmf) { struct vm_area_struct *vma = vmf->vma; - struct page *page = NULL, *swapcache; + struct page *page = NULL, *swapcache = NULL; struct mem_cgroup *memcg; struct vma_swap_readahead swap_ra; swp_entry_t entry; @@ -2881,17 +2881,35 @@ int do_swap_page(struct vm_fault *vmf) } goto out; } + + delayacct_set_flag(DELAYACCT_PF_SWAPIN); if (!page) page = lookup_swap_cache(entry, vma_readahead ? vma : NULL, vmf->address); if (!page) { - if (vma_readahead) - page = do_swap_page_readahead(entry, - GFP_HIGHUSER_MOVABLE, vmf, _ra); - else - page = swapin_readahead(entry, - GFP_HIGHUSER_MOVABLE, vma, vmf->address); + struct swap_info_struct *si = swp_swap_info(entry); + + if (!(si->flags & SWP_SYNCHRONOUS_IO)) { + if (vma_readahead) + page = do_swap_page_readahead(entry, + GFP_HIGHUSER_MOVABLE, vmf, _ra); + else + page = swapin_readahead(entry, + GFP_HIGHUSER_MOVABLE, vma, vmf->address); + swapcache = page; + } else { + /* skip swapcache */ + page = alloc_page_vma(GFP_HIGHUSER_MOVABLE, vma, vmf->address); + if (page) { + __SetPageLocked(page); + __SetPageSwapBacked(page); + set_page_private(page, entry.val); + lru_cache_add_anon(page); + swap_readpage(page, true); + } + } + if (!page) { /* * Back out if somebody else faulted in this pte @@ -2920,7 +2938,6 @@ int do_swap_page(struct vm_fault *vmf) goto out_release; } - swapcache = page; locked = lock_page_or_retry(page, vma->vm_mm, vmf->flags); delayacct_clear_flag(DELAYACCT_PF_SWAPIN); @@ -2935,7 +2952,8 @@ int do_swap_page(struct vm_fault *vmf) * test below, are not enough to exclude that. Even if it is still * swapcache, we need to check that the page's swap has not changed. */ - if (unlikely(!PageSwapCache(page) || page_private(page) != entry.val)) + if (unlikely((!PageSwapCache(page) || + page_private(page) != entry.val)) && swapcache) goto out_page; page = ksm_might_need_to_copy(page, vma, vmf->address);
[PATCH v2 1/4] zram: set BDI_CAP_STABLE_WRITES once
[1] fixed weird thing(i.e., reset BDI_CAP_STABLE_WRITES flag unconditionally whenever revalidat_disk is called) so zram doesn't need to reset the flag any more whenever revalidating the bdev. Instead, set the flag just once when the zram device is created. It shouldn't change any behavior. [1] 19b7ccf8651d, block: get rid of blk_integrity_revalidate() Cc: Ilya DryomovReviewed-by: Sergey Senozhatsky Signed-off-by: Minchan Kim --- drivers/block/zram/zram_drv.c | 16 ++-- 1 file changed, 6 insertions(+), 10 deletions(-) diff --git a/drivers/block/zram/zram_drv.c b/drivers/block/zram/zram_drv.c index cc78f61e22d1..98ef1a8389b0 100644 --- a/drivers/block/zram/zram_drv.c +++ b/drivers/block/zram/zram_drv.c @@ -122,14 +122,6 @@ static inline bool is_partial_io(struct bio_vec *bvec) } #endif -static void zram_revalidate_disk(struct zram *zram) -{ - revalidate_disk(zram->disk); - /* revalidate_disk reset the BDI_CAP_STABLE_WRITES so set again */ - zram->disk->queue->backing_dev_info->capabilities |= - BDI_CAP_STABLE_WRITES; -} - /* * Check if request is within bounds and aligned on zram logical blocks. */ @@ -1371,7 +1363,8 @@ static ssize_t disksize_store(struct device *dev, zram->comp = comp; zram->disksize = disksize; set_capacity(zram->disk, zram->disksize >> SECTOR_SHIFT); - zram_revalidate_disk(zram); + + revalidate_disk(zram->disk); up_write(>init_lock); return len; @@ -1418,7 +1411,7 @@ static ssize_t reset_store(struct device *dev, /* Make sure all the pending I/O are finished */ fsync_bdev(bdev); zram_reset_device(zram); - zram_revalidate_disk(zram); + revalidate_disk(zram->disk); bdput(bdev); mutex_lock(>bd_mutex); @@ -1537,6 +1530,7 @@ static int zram_add(void) /* zram devices sort of resembles non-rotational disks */ queue_flag_set_unlocked(QUEUE_FLAG_NONROT, zram->disk->queue); queue_flag_clear_unlocked(QUEUE_FLAG_ADD_RANDOM, zram->disk->queue); + /* * To ensure that we always get PAGE_SIZE aligned * and n*PAGE_SIZED sized I/O requests. @@ -1561,6 +1555,8 @@ static int zram_add(void) if (ZRAM_LOGICAL_BLOCK_SIZE == PAGE_SIZE) blk_queue_max_write_zeroes_sectors(zram->disk->queue, UINT_MAX); + zram->disk->queue->backing_dev_info->capabilities |= + BDI_CAP_STABLE_WRITES; add_disk(zram->disk); ret = sysfs_create_group(_to_dev(zram->disk)->kobj, -- 2.7.4
[PATCH v2 1/4] zram: set BDI_CAP_STABLE_WRITES once
[1] fixed weird thing(i.e., reset BDI_CAP_STABLE_WRITES flag unconditionally whenever revalidat_disk is called) so zram doesn't need to reset the flag any more whenever revalidating the bdev. Instead, set the flag just once when the zram device is created. It shouldn't change any behavior. [1] 19b7ccf8651d, block: get rid of blk_integrity_revalidate() Cc: Ilya Dryomov Reviewed-by: Sergey Senozhatsky Signed-off-by: Minchan Kim --- drivers/block/zram/zram_drv.c | 16 ++-- 1 file changed, 6 insertions(+), 10 deletions(-) diff --git a/drivers/block/zram/zram_drv.c b/drivers/block/zram/zram_drv.c index cc78f61e22d1..98ef1a8389b0 100644 --- a/drivers/block/zram/zram_drv.c +++ b/drivers/block/zram/zram_drv.c @@ -122,14 +122,6 @@ static inline bool is_partial_io(struct bio_vec *bvec) } #endif -static void zram_revalidate_disk(struct zram *zram) -{ - revalidate_disk(zram->disk); - /* revalidate_disk reset the BDI_CAP_STABLE_WRITES so set again */ - zram->disk->queue->backing_dev_info->capabilities |= - BDI_CAP_STABLE_WRITES; -} - /* * Check if request is within bounds and aligned on zram logical blocks. */ @@ -1371,7 +1363,8 @@ static ssize_t disksize_store(struct device *dev, zram->comp = comp; zram->disksize = disksize; set_capacity(zram->disk, zram->disksize >> SECTOR_SHIFT); - zram_revalidate_disk(zram); + + revalidate_disk(zram->disk); up_write(>init_lock); return len; @@ -1418,7 +1411,7 @@ static ssize_t reset_store(struct device *dev, /* Make sure all the pending I/O are finished */ fsync_bdev(bdev); zram_reset_device(zram); - zram_revalidate_disk(zram); + revalidate_disk(zram->disk); bdput(bdev); mutex_lock(>bd_mutex); @@ -1537,6 +1530,7 @@ static int zram_add(void) /* zram devices sort of resembles non-rotational disks */ queue_flag_set_unlocked(QUEUE_FLAG_NONROT, zram->disk->queue); queue_flag_clear_unlocked(QUEUE_FLAG_ADD_RANDOM, zram->disk->queue); + /* * To ensure that we always get PAGE_SIZE aligned * and n*PAGE_SIZED sized I/O requests. @@ -1561,6 +1555,8 @@ static int zram_add(void) if (ZRAM_LOGICAL_BLOCK_SIZE == PAGE_SIZE) blk_queue_max_write_zeroes_sectors(zram->disk->queue, UINT_MAX); + zram->disk->queue->backing_dev_info->capabilities |= + BDI_CAP_STABLE_WRITES; add_disk(zram->disk); ret = sysfs_create_group(_to_dev(zram->disk)->kobj, -- 2.7.4
[PATCH v2 2/4] bdi: introduce BDI_CAP_SYNCHRONOUS_IO
By discussion[1], someday we will remove rw_page function. If so, we need something to detect such super-fast storage which synchronous IO operation like current rw_page is always win. This patch introduces BDI_CAP_SYNCHRONOUS_IO to indicate such devices. With it, we could use various optimization techniques. [1] lkml.kernel.org/r/<20170728165604.10455-1-ross.zwis...@linux.intel.com> Cc: Christoph HellwigCc: Dan Williams Cc: Ross Zwisler Signed-off-by: Minchan Kim --- drivers/block/brd.c | 2 ++ drivers/block/zram/zram_drv.c | 2 +- drivers/nvdimm/btt.c | 3 +++ drivers/nvdimm/pmem.c | 2 ++ include/linux/backing-dev.h | 8 5 files changed, 16 insertions(+), 1 deletion(-) diff --git a/drivers/block/brd.c b/drivers/block/brd.c index bbd0d186cfc0..1fdb736aa882 100644 --- a/drivers/block/brd.c +++ b/drivers/block/brd.c @@ -20,6 +20,7 @@ #include #include #include +#include #ifdef CONFIG_BLK_DEV_RAM_DAX #include #include @@ -449,6 +450,7 @@ static struct brd_device *brd_alloc(int i) disk->flags = GENHD_FL_EXT_DEVT; sprintf(disk->disk_name, "ram%d", i); set_capacity(disk, rd_size * 2); + disk->queue->backing_dev_info->capabilities |= BDI_CAP_SYNCHRONOUS_IO; #ifdef CONFIG_BLK_DEV_RAM_DAX queue_flag_set_unlocked(QUEUE_FLAG_DAX, brd->brd_queue); diff --git a/drivers/block/zram/zram_drv.c b/drivers/block/zram/zram_drv.c index 98ef1a8389b0..23172641fc01 100644 --- a/drivers/block/zram/zram_drv.c +++ b/drivers/block/zram/zram_drv.c @@ -1556,7 +1556,7 @@ static int zram_add(void) blk_queue_max_write_zeroes_sectors(zram->disk->queue, UINT_MAX); zram->disk->queue->backing_dev_info->capabilities |= - BDI_CAP_STABLE_WRITES; + (BDI_CAP_STABLE_WRITES | BDI_CAP_SYNCHRONOUS_IO); add_disk(zram->disk); ret = sysfs_create_group(_to_dev(zram->disk)->kobj, diff --git a/drivers/nvdimm/btt.c b/drivers/nvdimm/btt.c index d5612bd1cc81..e949e3302af4 100644 --- a/drivers/nvdimm/btt.c +++ b/drivers/nvdimm/btt.c @@ -23,6 +23,7 @@ #include #include #include +#include #include "btt.h" #include "nd.h" @@ -1402,6 +1403,8 @@ static int btt_blk_init(struct btt *btt) btt->btt_disk->private_data = btt; btt->btt_disk->queue = btt->btt_queue; btt->btt_disk->flags = GENHD_FL_EXT_DEVT; + btt->btt_disk->queue->backing_dev_info->capabilities |= + BDI_CAP_SYNCHRONOUS_IO; blk_queue_make_request(btt->btt_queue, btt_make_request); blk_queue_logical_block_size(btt->btt_queue, btt->sector_size); diff --git a/drivers/nvdimm/pmem.c b/drivers/nvdimm/pmem.c index 39dfd7affa31..7fbc5c5dc8e1 100644 --- a/drivers/nvdimm/pmem.c +++ b/drivers/nvdimm/pmem.c @@ -31,6 +31,7 @@ #include #include #include +#include #include "pmem.h" #include "pfn.h" #include "nd.h" @@ -394,6 +395,7 @@ static int pmem_attach_disk(struct device *dev, disk->fops = _fops; disk->queue = q; disk->flags = GENHD_FL_EXT_DEVT; + disk->queue->backing_dev_info->capabilities |= BDI_CAP_SYNCHRONOUS_IO; nvdimm_namespace_disk_name(ndns, disk->disk_name); set_capacity(disk, (pmem->size - pmem->pfn_pad - pmem->data_offset) / 512); diff --git a/include/linux/backing-dev.h b/include/linux/backing-dev.h index 854e1bdd0b2a..cd41617c6594 100644 --- a/include/linux/backing-dev.h +++ b/include/linux/backing-dev.h @@ -123,6 +123,8 @@ int bdi_set_max_ratio(struct backing_dev_info *bdi, unsigned int max_ratio); * BDI_CAP_STRICTLIMIT:Keep number of dirty pages below bdi threshold. * * BDI_CAP_CGROUP_WRITEBACK: Supports cgroup-aware writeback. + * BDI_CAP_SYNCHRONOUS_IO: Device is so fast that asynchronous IO would be + *inefficient. */ #define BDI_CAP_NO_ACCT_DIRTY 0x0001 #define BDI_CAP_NO_WRITEBACK 0x0002 @@ -130,6 +132,7 @@ int bdi_set_max_ratio(struct backing_dev_info *bdi, unsigned int max_ratio); #define BDI_CAP_STABLE_WRITES 0x0008 #define BDI_CAP_STRICTLIMIT0x0010 #define BDI_CAP_CGROUP_WRITEBACK 0x0020 +#define BDI_CAP_SYNCHRONOUS_IO 0x0040 #define BDI_CAP_NO_ACCT_AND_WRITEBACK \ (BDI_CAP_NO_WRITEBACK | BDI_CAP_NO_ACCT_DIRTY | BDI_CAP_NO_ACCT_WB) @@ -177,6 +180,11 @@ long wait_iff_congested(struct pglist_data *pgdat, int sync, long timeout); int pdflush_proc_obsolete(struct ctl_table *table, int write, void __user *buffer, size_t *lenp, loff_t *ppos); +static inline bool bdi_cap_synchronous_io(struct backing_dev_info *bdi) +{ + return bdi->capabilities & BDI_CAP_SYNCHRONOUS_IO; +} + static inline bool bdi_cap_stable_pages_required(struct backing_dev_info *bdi) { return bdi->capabilities &
[PATCH v2 2/4] bdi: introduce BDI_CAP_SYNCHRONOUS_IO
By discussion[1], someday we will remove rw_page function. If so, we need something to detect such super-fast storage which synchronous IO operation like current rw_page is always win. This patch introduces BDI_CAP_SYNCHRONOUS_IO to indicate such devices. With it, we could use various optimization techniques. [1] lkml.kernel.org/r/<20170728165604.10455-1-ross.zwis...@linux.intel.com> Cc: Christoph Hellwig Cc: Dan Williams Cc: Ross Zwisler Signed-off-by: Minchan Kim --- drivers/block/brd.c | 2 ++ drivers/block/zram/zram_drv.c | 2 +- drivers/nvdimm/btt.c | 3 +++ drivers/nvdimm/pmem.c | 2 ++ include/linux/backing-dev.h | 8 5 files changed, 16 insertions(+), 1 deletion(-) diff --git a/drivers/block/brd.c b/drivers/block/brd.c index bbd0d186cfc0..1fdb736aa882 100644 --- a/drivers/block/brd.c +++ b/drivers/block/brd.c @@ -20,6 +20,7 @@ #include #include #include +#include #ifdef CONFIG_BLK_DEV_RAM_DAX #include #include @@ -449,6 +450,7 @@ static struct brd_device *brd_alloc(int i) disk->flags = GENHD_FL_EXT_DEVT; sprintf(disk->disk_name, "ram%d", i); set_capacity(disk, rd_size * 2); + disk->queue->backing_dev_info->capabilities |= BDI_CAP_SYNCHRONOUS_IO; #ifdef CONFIG_BLK_DEV_RAM_DAX queue_flag_set_unlocked(QUEUE_FLAG_DAX, brd->brd_queue); diff --git a/drivers/block/zram/zram_drv.c b/drivers/block/zram/zram_drv.c index 98ef1a8389b0..23172641fc01 100644 --- a/drivers/block/zram/zram_drv.c +++ b/drivers/block/zram/zram_drv.c @@ -1556,7 +1556,7 @@ static int zram_add(void) blk_queue_max_write_zeroes_sectors(zram->disk->queue, UINT_MAX); zram->disk->queue->backing_dev_info->capabilities |= - BDI_CAP_STABLE_WRITES; + (BDI_CAP_STABLE_WRITES | BDI_CAP_SYNCHRONOUS_IO); add_disk(zram->disk); ret = sysfs_create_group(_to_dev(zram->disk)->kobj, diff --git a/drivers/nvdimm/btt.c b/drivers/nvdimm/btt.c index d5612bd1cc81..e949e3302af4 100644 --- a/drivers/nvdimm/btt.c +++ b/drivers/nvdimm/btt.c @@ -23,6 +23,7 @@ #include #include #include +#include #include "btt.h" #include "nd.h" @@ -1402,6 +1403,8 @@ static int btt_blk_init(struct btt *btt) btt->btt_disk->private_data = btt; btt->btt_disk->queue = btt->btt_queue; btt->btt_disk->flags = GENHD_FL_EXT_DEVT; + btt->btt_disk->queue->backing_dev_info->capabilities |= + BDI_CAP_SYNCHRONOUS_IO; blk_queue_make_request(btt->btt_queue, btt_make_request); blk_queue_logical_block_size(btt->btt_queue, btt->sector_size); diff --git a/drivers/nvdimm/pmem.c b/drivers/nvdimm/pmem.c index 39dfd7affa31..7fbc5c5dc8e1 100644 --- a/drivers/nvdimm/pmem.c +++ b/drivers/nvdimm/pmem.c @@ -31,6 +31,7 @@ #include #include #include +#include #include "pmem.h" #include "pfn.h" #include "nd.h" @@ -394,6 +395,7 @@ static int pmem_attach_disk(struct device *dev, disk->fops = _fops; disk->queue = q; disk->flags = GENHD_FL_EXT_DEVT; + disk->queue->backing_dev_info->capabilities |= BDI_CAP_SYNCHRONOUS_IO; nvdimm_namespace_disk_name(ndns, disk->disk_name); set_capacity(disk, (pmem->size - pmem->pfn_pad - pmem->data_offset) / 512); diff --git a/include/linux/backing-dev.h b/include/linux/backing-dev.h index 854e1bdd0b2a..cd41617c6594 100644 --- a/include/linux/backing-dev.h +++ b/include/linux/backing-dev.h @@ -123,6 +123,8 @@ int bdi_set_max_ratio(struct backing_dev_info *bdi, unsigned int max_ratio); * BDI_CAP_STRICTLIMIT:Keep number of dirty pages below bdi threshold. * * BDI_CAP_CGROUP_WRITEBACK: Supports cgroup-aware writeback. + * BDI_CAP_SYNCHRONOUS_IO: Device is so fast that asynchronous IO would be + *inefficient. */ #define BDI_CAP_NO_ACCT_DIRTY 0x0001 #define BDI_CAP_NO_WRITEBACK 0x0002 @@ -130,6 +132,7 @@ int bdi_set_max_ratio(struct backing_dev_info *bdi, unsigned int max_ratio); #define BDI_CAP_STABLE_WRITES 0x0008 #define BDI_CAP_STRICTLIMIT0x0010 #define BDI_CAP_CGROUP_WRITEBACK 0x0020 +#define BDI_CAP_SYNCHRONOUS_IO 0x0040 #define BDI_CAP_NO_ACCT_AND_WRITEBACK \ (BDI_CAP_NO_WRITEBACK | BDI_CAP_NO_ACCT_DIRTY | BDI_CAP_NO_ACCT_WB) @@ -177,6 +180,11 @@ long wait_iff_congested(struct pglist_data *pgdat, int sync, long timeout); int pdflush_proc_obsolete(struct ctl_table *table, int write, void __user *buffer, size_t *lenp, loff_t *ppos); +static inline bool bdi_cap_synchronous_io(struct backing_dev_info *bdi) +{ + return bdi->capabilities & BDI_CAP_SYNCHRONOUS_IO; +} + static inline bool bdi_cap_stable_pages_required(struct backing_dev_info *bdi) { return bdi->capabilities & BDI_CAP_STABLE_WRITES; -- 2.7.4
[PATCH v2 3/4] mm:swap: introduce SWP_SYNCHRONOUS_IO
If rw-page based fast storage is used for swap devices, we need to detect it to enhance swap IO operations. This patch is preparation for optimizing of swap-in operation with next patch. Cc: Hugh DickinsSigned-off-by: Minchan Kim --- include/linux/swap.h | 3 ++- mm/swapfile.c| 3 +++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/include/linux/swap.h b/include/linux/swap.h index 8a807292037f..fbb33919d1c6 100644 --- a/include/linux/swap.h +++ b/include/linux/swap.h @@ -170,8 +170,9 @@ enum { SWP_AREA_DISCARD = (1 << 8),/* single-time swap area discards */ SWP_PAGE_DISCARD = (1 << 9),/* freed swap page-cluster discards */ SWP_STABLE_WRITES = (1 << 10), /* no overwrite PG_writeback pages */ + SWP_SYNCHRONOUS_IO = (1 << 11), /* synchronous IO is efficient */ /* add others here before... */ - SWP_SCANNING= (1 << 11),/* refcount in scan_swap_map */ + SWP_SCANNING= (1 << 12),/* refcount in scan_swap_map */ }; #define SWAP_CLUSTER_MAX 32UL diff --git a/mm/swapfile.c b/mm/swapfile.c index bf91dc9e7a79..1305591cde4d 100644 --- a/mm/swapfile.c +++ b/mm/swapfile.c @@ -3168,6 +3168,9 @@ SYSCALL_DEFINE2(swapon, const char __user *, specialfile, int, swap_flags) if (bdi_cap_stable_pages_required(inode_to_bdi(inode))) p->flags |= SWP_STABLE_WRITES; + if (bdi_cap_synchronous_io(inode_to_bdi(inode))) + p->flags |= SWP_SYNCHRONOUS_IO; + if (p->bdev && blk_queue_nonrot(bdev_get_queue(p->bdev))) { int cpu; unsigned long ci, nr_cluster; -- 2.7.4
[PATCH v2 0/4] skip swapcache for super fast device
With fast swap storage, platform want to use swap more aggressively and swap-in is crucial to application latency. The rw_page based synchronous devices like zram, pmem and btt are such fast storage. When I profile swapin performance with zram lz4 decompress test, S/W overhead is more than 70%. Maybe, it would be bigger in nvdimm. This patch aims for reducing swap-in latency via skipping swapcache if swap device is synchronous device like rw_page based device. It enhances 45% my swapin test(5G sequential swapin, no readahead, from 2.41sec to 1.64sec). Andrew, [1] is zram specific patch so could be applied separately but this patch is based on that so I include it in this series. * From v1 * style fix * a bug fix * drop page-cluster based readahead off * This regression could be solved by other patch from Huang. http://lkml.kernel.org/r/87tw04in60@yhuang-dev.intel.com Minchan Kim (4): [1] zram: set BDI_CAP_STABLE_WRITES once [2] bdi: introduce BDI_CAP_SYNCHRONOUS_IO [3] mm:swap: introduce SWP_SYNCHRONOUS_IO [4] mm:swap: skip swapcache for swapin of synchronous device drivers/block/brd.c | 2 ++ drivers/block/zram/zram_drv.c | 16 + drivers/nvdimm/btt.c | 3 +++ drivers/nvdimm/pmem.c | 2 ++ include/linux/backing-dev.h | 8 +++ include/linux/swap.h | 14 +++- mm/memory.c | 52 ++- mm/page_io.c | 6 ++--- mm/swapfile.c | 14 9 files changed, 83 insertions(+), 34 deletions(-) -- 2.7.4
[PATCH v2 3/4] mm:swap: introduce SWP_SYNCHRONOUS_IO
If rw-page based fast storage is used for swap devices, we need to detect it to enhance swap IO operations. This patch is preparation for optimizing of swap-in operation with next patch. Cc: Hugh Dickins Signed-off-by: Minchan Kim --- include/linux/swap.h | 3 ++- mm/swapfile.c| 3 +++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/include/linux/swap.h b/include/linux/swap.h index 8a807292037f..fbb33919d1c6 100644 --- a/include/linux/swap.h +++ b/include/linux/swap.h @@ -170,8 +170,9 @@ enum { SWP_AREA_DISCARD = (1 << 8),/* single-time swap area discards */ SWP_PAGE_DISCARD = (1 << 9),/* freed swap page-cluster discards */ SWP_STABLE_WRITES = (1 << 10), /* no overwrite PG_writeback pages */ + SWP_SYNCHRONOUS_IO = (1 << 11), /* synchronous IO is efficient */ /* add others here before... */ - SWP_SCANNING= (1 << 11),/* refcount in scan_swap_map */ + SWP_SCANNING= (1 << 12),/* refcount in scan_swap_map */ }; #define SWAP_CLUSTER_MAX 32UL diff --git a/mm/swapfile.c b/mm/swapfile.c index bf91dc9e7a79..1305591cde4d 100644 --- a/mm/swapfile.c +++ b/mm/swapfile.c @@ -3168,6 +3168,9 @@ SYSCALL_DEFINE2(swapon, const char __user *, specialfile, int, swap_flags) if (bdi_cap_stable_pages_required(inode_to_bdi(inode))) p->flags |= SWP_STABLE_WRITES; + if (bdi_cap_synchronous_io(inode_to_bdi(inode))) + p->flags |= SWP_SYNCHRONOUS_IO; + if (p->bdev && blk_queue_nonrot(bdev_get_queue(p->bdev))) { int cpu; unsigned long ci, nr_cluster; -- 2.7.4
[PATCH v2 0/4] skip swapcache for super fast device
With fast swap storage, platform want to use swap more aggressively and swap-in is crucial to application latency. The rw_page based synchronous devices like zram, pmem and btt are such fast storage. When I profile swapin performance with zram lz4 decompress test, S/W overhead is more than 70%. Maybe, it would be bigger in nvdimm. This patch aims for reducing swap-in latency via skipping swapcache if swap device is synchronous device like rw_page based device. It enhances 45% my swapin test(5G sequential swapin, no readahead, from 2.41sec to 1.64sec). Andrew, [1] is zram specific patch so could be applied separately but this patch is based on that so I include it in this series. * From v1 * style fix * a bug fix * drop page-cluster based readahead off * This regression could be solved by other patch from Huang. http://lkml.kernel.org/r/87tw04in60@yhuang-dev.intel.com Minchan Kim (4): [1] zram: set BDI_CAP_STABLE_WRITES once [2] bdi: introduce BDI_CAP_SYNCHRONOUS_IO [3] mm:swap: introduce SWP_SYNCHRONOUS_IO [4] mm:swap: skip swapcache for swapin of synchronous device drivers/block/brd.c | 2 ++ drivers/block/zram/zram_drv.c | 16 + drivers/nvdimm/btt.c | 3 +++ drivers/nvdimm/pmem.c | 2 ++ include/linux/backing-dev.h | 8 +++ include/linux/swap.h | 14 +++- mm/memory.c | 52 ++- mm/page_io.c | 6 ++--- mm/swapfile.c | 14 9 files changed, 83 insertions(+), 34 deletions(-) -- 2.7.4
Re: [PATCH v2 2/4] bdi: introduce BDI_CAP_SYNCHRONOUS_IO
On Tue, Sep 19, 2017 at 04:25:03PM +0200, Christoph Hellwig wrote: > I'm only seeing patch 2 of 4 - please resend the whole series so > that it can properly be reviewed. Yub, I will resend. Thanks for the review in advance.
Re: [PATCH v2 2/4] bdi: introduce BDI_CAP_SYNCHRONOUS_IO
On Tue, Sep 19, 2017 at 04:25:03PM +0200, Christoph Hellwig wrote: > I'm only seeing patch 2 of 4 - please resend the whole series so > that it can properly be reviewed. Yub, I will resend. Thanks for the review in advance.
Re: Error when building the kernel on top of 4.14-rc1 for target firmware_install?
On Wed, Sep 20, 2017 at 11:20:19AM +0800, Yu Chen wrote: > Hi, > kernel compile failed after running # make rpm > > + > INSTALL_FW_PATH=/root/rpmbuild/BUILDROOT/kernel-4.14.0_rc1+-22.x86_64/lib/firmware/4.14.0-rc1+ > + make > INSTALL_FW_PATH=/root/rpmbuild/BUILDROOT/kernel-4.14.0_rc1+-22.x86_64/lib/firmware/4.14.0-rc1+ > firmware_install > make[2]: warning: jobserver unavailable: using -j1. Add '+' to parent > make rule. > make[2]: *** No rule to make target 'firmware_install'. Stop. > > I have to hack the script to compile through: > diff --git a/scripts/package/mkspec b/scripts/package/mkspec > index bb43f15..cb9c1b3 100755 > --- a/scripts/package/mkspec > +++ b/scripts/package/mkspec > @@ -92,7 +92,7 @@ echo 'mkdir -p > $RPM_BUILD_ROOT'"/lib/firmware/$KERNELRELEASE" > > echo 'INSTALL_MOD_PATH=$RPM_BUILD_ROOT make %{?_smp_mflags} > KBUILD_SRC= mod-fw= modules_install' > echo 'INSTALL_FW_PATH=$RPM_BUILD_ROOT'"/lib/firmware/$KERNELRELEASE" > -echo 'make INSTALL_FW_PATH=$INSTALL_FW_PATH' firmware_install > +echo 'make INSTALL_FW_PATH=$INSTALL_FW_PATH' > echo "%ifarch ia64" > > Not sure if this is a regression but several version ago it works well. See the maling list for fixes for this already :) thanks, greg k-h
Re: Error when building the kernel on top of 4.14-rc1 for target firmware_install?
On Wed, Sep 20, 2017 at 11:20:19AM +0800, Yu Chen wrote: > Hi, > kernel compile failed after running # make rpm > > + > INSTALL_FW_PATH=/root/rpmbuild/BUILDROOT/kernel-4.14.0_rc1+-22.x86_64/lib/firmware/4.14.0-rc1+ > + make > INSTALL_FW_PATH=/root/rpmbuild/BUILDROOT/kernel-4.14.0_rc1+-22.x86_64/lib/firmware/4.14.0-rc1+ > firmware_install > make[2]: warning: jobserver unavailable: using -j1. Add '+' to parent > make rule. > make[2]: *** No rule to make target 'firmware_install'. Stop. > > I have to hack the script to compile through: > diff --git a/scripts/package/mkspec b/scripts/package/mkspec > index bb43f15..cb9c1b3 100755 > --- a/scripts/package/mkspec > +++ b/scripts/package/mkspec > @@ -92,7 +92,7 @@ echo 'mkdir -p > $RPM_BUILD_ROOT'"/lib/firmware/$KERNELRELEASE" > > echo 'INSTALL_MOD_PATH=$RPM_BUILD_ROOT make %{?_smp_mflags} > KBUILD_SRC= mod-fw= modules_install' > echo 'INSTALL_FW_PATH=$RPM_BUILD_ROOT'"/lib/firmware/$KERNELRELEASE" > -echo 'make INSTALL_FW_PATH=$INSTALL_FW_PATH' firmware_install > +echo 'make INSTALL_FW_PATH=$INSTALL_FW_PATH' > echo "%ifarch ia64" > > Not sure if this is a regression but several version ago it works well. See the maling list for fixes for this already :) thanks, greg k-h
Re: linux-next: error while fetching the microblaze tree
Hi Stephen, On 20.9.2017 01:26, Stephen Rothwell wrote: > Hi Michal, > > On Thu, 7 Jan 2016 09:38:56 +1100 Stephen Rothwell> wrote: >> >> Fetching the microblaze tree >> (git://git.monstr.eu/linux-2.6-microblaze.git#next) produces this error. >> >> fatal: read error: Connection reset by peer >> >> I will use the previously fetched version for today. > > I have been unable to fetch the microblaze tree again for the past few > days. This time it is is getting: > > git.monstr.eu[0: 195.88.143.27]: errno=Connection refused > Thanks for letting me know. I have contacted admin to look at it. Will let you know when it is recover. Thanks, Michal -- Michal Simek, Ing. (M.Eng), OpenPGP -> KeyID: FE3D1F91 w: www.monstr.eu p: +42-0-721842854 Maintainer of Linux kernel - Xilinx Microblaze Maintainer of Linux kernel - Xilinx Zynq ARM and ZynqMP ARM64 SoCs U-Boot custodian - Xilinx Microblaze/Zynq/ZynqMP SoCs signature.asc Description: OpenPGP digital signature
Re: linux-next: error while fetching the microblaze tree
Hi Stephen, On 20.9.2017 01:26, Stephen Rothwell wrote: > Hi Michal, > > On Thu, 7 Jan 2016 09:38:56 +1100 Stephen Rothwell > wrote: >> >> Fetching the microblaze tree >> (git://git.monstr.eu/linux-2.6-microblaze.git#next) produces this error. >> >> fatal: read error: Connection reset by peer >> >> I will use the previously fetched version for today. > > I have been unable to fetch the microblaze tree again for the past few > days. This time it is is getting: > > git.monstr.eu[0: 195.88.143.27]: errno=Connection refused > Thanks for letting me know. I have contacted admin to look at it. Will let you know when it is recover. Thanks, Michal -- Michal Simek, Ing. (M.Eng), OpenPGP -> KeyID: FE3D1F91 w: www.monstr.eu p: +42-0-721842854 Maintainer of Linux kernel - Xilinx Microblaze Maintainer of Linux kernel - Xilinx Zynq ARM and ZynqMP ARM64 SoCs U-Boot custodian - Xilinx Microblaze/Zynq/ZynqMP SoCs signature.asc Description: OpenPGP digital signature
Re: [PATCH v6] security/keys: rewrite all of big_key crypto
Am Sonntag, 17. September 2017, 13:52:17 CEST schrieb Jason A. Donenfeld: Hi Jason, > * Use of ECB mode, allowing an attacker to trivially swap blocks or > compare identical plaintext blocks. The use of GCM with the implementtion here is just as challenging. The implementation uses a NULL IV. GCM is a very brittle cipher where the construction of the IV is of special importance. SP800-38D section 8.2.1 and 8.2.2 outlines the generation methods of the IV. A collision of keys/IVs is fatal. I understand that keys are generated anew each time which makes that issue less critical here. However, as user space may see the ciphertext, GCM should simply not be used. A fix could be as easy as to use CCM or one of the authenc() ciphers. Yet, for both I am not sure how a zero IV affects the cipher. The cipher where you do not need to handle the IV at all would be the RFC3394/ SP800-38F keywrapping cipher which is meant for the encryption of key material which includes authentication as well. It is available as an skcipher under the name of kw(aes). If you want to use it, please be careful that you obtain the generated IV to be stored with the plaintext as documented in the comments in crypto/keywrap.c Ciao Stephan
Re: [PATCH v6] security/keys: rewrite all of big_key crypto
Am Sonntag, 17. September 2017, 13:52:17 CEST schrieb Jason A. Donenfeld: Hi Jason, > * Use of ECB mode, allowing an attacker to trivially swap blocks or > compare identical plaintext blocks. The use of GCM with the implementtion here is just as challenging. The implementation uses a NULL IV. GCM is a very brittle cipher where the construction of the IV is of special importance. SP800-38D section 8.2.1 and 8.2.2 outlines the generation methods of the IV. A collision of keys/IVs is fatal. I understand that keys are generated anew each time which makes that issue less critical here. However, as user space may see the ciphertext, GCM should simply not be used. A fix could be as easy as to use CCM or one of the authenc() ciphers. Yet, for both I am not sure how a zero IV affects the cipher. The cipher where you do not need to handle the IV at all would be the RFC3394/ SP800-38F keywrapping cipher which is meant for the encryption of key material which includes authentication as well. It is available as an skcipher under the name of kw(aes). If you want to use it, please be careful that you obtain the generated IV to be stored with the plaintext as documented in the comments in crypto/keywrap.c Ciao Stephan
[PATCH v2 1/4] watchdog: aspeed: Retain watchdog enabled state
An unintended post-condition of probe() is that the watchdog is disabled. This behaviour was introduced by an unnecessary write to the control register to configure the hardware based on the devicetree. The write is unnecessary because the cached control value that is manipulated by the code parsing the devicetree is eventually written by aspeed_wdt_enable(), which is when we care how the control register should be configured. Remove the write to restore expected behaviour. Fixes: b7f0b8ad25f3 ("drivers/watchdog: ASPEED reference dev tree properties for config") Signed-off-by: Andrew Jeffery--- drivers/watchdog/aspeed_wdt.c | 8 ++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/drivers/watchdog/aspeed_wdt.c b/drivers/watchdog/aspeed_wdt.c index 79cc766cd30f..6c6dd3f4c48d 100644 --- a/drivers/watchdog/aspeed_wdt.c +++ b/drivers/watchdog/aspeed_wdt.c @@ -243,9 +243,13 @@ static int aspeed_wdt_probe(struct platform_device *pdev) if (of_property_read_bool(np, "aspeed,external-signal")) wdt->ctrl |= WDT_CTRL_WDT_EXT; - writel(wdt->ctrl, wdt->base + WDT_CTRL); - if (readl(wdt->base + WDT_CTRL) & WDT_CTRL_ENABLE) { + /* +* The watchdog is running, but invoke aspeed_wdt_start() to +* write wdt->ctrl to WDT_CTRL to ensure the watchdog's +* configuration conforms to the driver's expectations. +* Primarily, ensure we're using the 1MHz clock source. +*/ aspeed_wdt_start(>wdd); set_bit(WDOG_HW_RUNNING, >wdd.status); } -- 2.11.0
[PATCH v2 3/4] watchdog: aspeed: Remove specific reference to AST2400 in Kconfig
The driver also supports the watchdog in the AST25xx series, and may work on earlier SoCs as well. Signed-off-by: Andrew JefferyReviewed-by: Guenter Roeck --- drivers/watchdog/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig index b562d2e03eb9..a1b92ebe74b6 100644 --- a/drivers/watchdog/Kconfig +++ b/drivers/watchdog/Kconfig @@ -741,7 +741,7 @@ config RENESAS_RZAWDT Renesas RZ/A SoCs. These watchdogs can be used to reset a system. config ASPEED_WATCHDOG - tristate "Aspeed 2400 watchdog support" + tristate "Aspeed BMC watchdog support" depends on ARCH_ASPEED || COMPILE_TEST select WATCHDOG_CORE help -- 2.11.0
[PATCH v2 1/4] watchdog: aspeed: Retain watchdog enabled state
An unintended post-condition of probe() is that the watchdog is disabled. This behaviour was introduced by an unnecessary write to the control register to configure the hardware based on the devicetree. The write is unnecessary because the cached control value that is manipulated by the code parsing the devicetree is eventually written by aspeed_wdt_enable(), which is when we care how the control register should be configured. Remove the write to restore expected behaviour. Fixes: b7f0b8ad25f3 ("drivers/watchdog: ASPEED reference dev tree properties for config") Signed-off-by: Andrew Jeffery --- drivers/watchdog/aspeed_wdt.c | 8 ++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/drivers/watchdog/aspeed_wdt.c b/drivers/watchdog/aspeed_wdt.c index 79cc766cd30f..6c6dd3f4c48d 100644 --- a/drivers/watchdog/aspeed_wdt.c +++ b/drivers/watchdog/aspeed_wdt.c @@ -243,9 +243,13 @@ static int aspeed_wdt_probe(struct platform_device *pdev) if (of_property_read_bool(np, "aspeed,external-signal")) wdt->ctrl |= WDT_CTRL_WDT_EXT; - writel(wdt->ctrl, wdt->base + WDT_CTRL); - if (readl(wdt->base + WDT_CTRL) & WDT_CTRL_ENABLE) { + /* +* The watchdog is running, but invoke aspeed_wdt_start() to +* write wdt->ctrl to WDT_CTRL to ensure the watchdog's +* configuration conforms to the driver's expectations. +* Primarily, ensure we're using the 1MHz clock source. +*/ aspeed_wdt_start(>wdd); set_bit(WDOG_HW_RUNNING, >wdd.status); } -- 2.11.0
[PATCH v2 3/4] watchdog: aspeed: Remove specific reference to AST2400 in Kconfig
The driver also supports the watchdog in the AST25xx series, and may work on earlier SoCs as well. Signed-off-by: Andrew Jeffery Reviewed-by: Guenter Roeck --- drivers/watchdog/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig index b562d2e03eb9..a1b92ebe74b6 100644 --- a/drivers/watchdog/Kconfig +++ b/drivers/watchdog/Kconfig @@ -741,7 +741,7 @@ config RENESAS_RZAWDT Renesas RZ/A SoCs. These watchdogs can be used to reset a system. config ASPEED_WATCHDOG - tristate "Aspeed 2400 watchdog support" + tristate "Aspeed BMC watchdog support" depends on ARCH_ASPEED || COMPILE_TEST select WATCHDOG_CORE help -- 2.11.0
[PATCH v2 2/4] watchdog: aspeed: Fix 'Apseed' typo in Kconfig
Apseed sounds like a good name for a web/mobile start-up incubator, but isn't a reflection of Aspeed themselves. Signed-off-by: Andrew JefferyReviewed-by: Guenter Roeck --- drivers/watchdog/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig index c722cbfdc7e6..b562d2e03eb9 100644 --- a/drivers/watchdog/Kconfig +++ b/drivers/watchdog/Kconfig @@ -746,7 +746,7 @@ config ASPEED_WATCHDOG select WATCHDOG_CORE help Say Y here to include support for the watchdog timer - in Apseed BMC SoCs. + in Aspeed BMC SoCs. This driver is required to reboot the SoC. -- 2.11.0
[PATCH v2 2/4] watchdog: aspeed: Fix 'Apseed' typo in Kconfig
Apseed sounds like a good name for a web/mobile start-up incubator, but isn't a reflection of Aspeed themselves. Signed-off-by: Andrew Jeffery Reviewed-by: Guenter Roeck --- drivers/watchdog/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig index c722cbfdc7e6..b562d2e03eb9 100644 --- a/drivers/watchdog/Kconfig +++ b/drivers/watchdog/Kconfig @@ -746,7 +746,7 @@ config ASPEED_WATCHDOG select WATCHDOG_CORE help Say Y here to include support for the watchdog timer - in Apseed BMC SoCs. + in Aspeed BMC SoCs. This driver is required to reboot the SoC. -- 2.11.0
[PATCH v2 0/4] watchdog: aspeed: Retain enabled state and move to arch_initcall
Hello, This series fixes some issues with the Aspeed watchdog, as outlined in the v1[1] cover letter. I've added a bit of an explanation as to why we call aspeed_wdt_start() in probe() if the watchdog is already enabled, but the essence of it is to ensure the watchdog is configured to the expectations of the kernel driver (rather than however the bootloader configured it). Please review! Andrew Since v1: * Rework patch 1/4 to simply remove the writel() call to restore the original behaviour. * Rework patch 4/4 to remove the Kconfig changes to retain the ability to build the watchdog as a module, and add the exit handler. [1] https://lkml.org/lkml/2017/9/18/14 Andrew Jeffery (4): watchdog: aspeed: Retain watchdog enabled state watchdog: aspeed: Fix 'Apseed' typo in Kconfig watchdog: aspeed: Remove specific reference to AST2400 in Kconfig watchdog: aspeed: Move init to arch_initcall drivers/watchdog/Kconfig | 4 ++-- drivers/watchdog/aspeed_wdt.c | 21 ++--- 2 files changed, 20 insertions(+), 5 deletions(-) -- 2.11.0
[PATCH v2 0/4] watchdog: aspeed: Retain enabled state and move to arch_initcall
Hello, This series fixes some issues with the Aspeed watchdog, as outlined in the v1[1] cover letter. I've added a bit of an explanation as to why we call aspeed_wdt_start() in probe() if the watchdog is already enabled, but the essence of it is to ensure the watchdog is configured to the expectations of the kernel driver (rather than however the bootloader configured it). Please review! Andrew Since v1: * Rework patch 1/4 to simply remove the writel() call to restore the original behaviour. * Rework patch 4/4 to remove the Kconfig changes to retain the ability to build the watchdog as a module, and add the exit handler. [1] https://lkml.org/lkml/2017/9/18/14 Andrew Jeffery (4): watchdog: aspeed: Retain watchdog enabled state watchdog: aspeed: Fix 'Apseed' typo in Kconfig watchdog: aspeed: Remove specific reference to AST2400 in Kconfig watchdog: aspeed: Move init to arch_initcall drivers/watchdog/Kconfig | 4 ++-- drivers/watchdog/aspeed_wdt.c | 21 ++--- 2 files changed, 20 insertions(+), 5 deletions(-) -- 2.11.0
[PATCH v2 4/4] watchdog: aspeed: Move init to arch_initcall
Probing at device_initcall time lead to perverse cases where the watchdog was probed after, say, I2C devices, which then leaves a potentially running watchdog at the mercy of I2C device behaviour and bus conditions. Load the watchdog driver early to ensure that the kernel is patting it well before initialising peripherals. Signed-off-by: Andrew Jeffery--- drivers/watchdog/aspeed_wdt.c | 13 - 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/drivers/watchdog/aspeed_wdt.c b/drivers/watchdog/aspeed_wdt.c index 6c6dd3f4c48d..ca5b91e2eb92 100644 --- a/drivers/watchdog/aspeed_wdt.c +++ b/drivers/watchdog/aspeed_wdt.c @@ -316,7 +316,18 @@ static struct platform_driver aspeed_watchdog_driver = { .of_match_table = of_match_ptr(aspeed_wdt_of_table), }, }; -module_platform_driver(aspeed_watchdog_driver); + +static int __init aspeed_wdt_init(void) +{ + return platform_driver_register(_watchdog_driver); +} +arch_initcall(aspeed_wdt_init); + +static void __exit aspeed_wdt_exit(void) +{ + platform_driver_unregister(_watchdog_driver); +} +module_exit(aspeed_wdt_exit); MODULE_DESCRIPTION("Aspeed Watchdog Driver"); MODULE_LICENSE("GPL"); -- 2.11.0
[PATCH v2 4/4] watchdog: aspeed: Move init to arch_initcall
Probing at device_initcall time lead to perverse cases where the watchdog was probed after, say, I2C devices, which then leaves a potentially running watchdog at the mercy of I2C device behaviour and bus conditions. Load the watchdog driver early to ensure that the kernel is patting it well before initialising peripherals. Signed-off-by: Andrew Jeffery --- drivers/watchdog/aspeed_wdt.c | 13 - 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/drivers/watchdog/aspeed_wdt.c b/drivers/watchdog/aspeed_wdt.c index 6c6dd3f4c48d..ca5b91e2eb92 100644 --- a/drivers/watchdog/aspeed_wdt.c +++ b/drivers/watchdog/aspeed_wdt.c @@ -316,7 +316,18 @@ static struct platform_driver aspeed_watchdog_driver = { .of_match_table = of_match_ptr(aspeed_wdt_of_table), }, }; -module_platform_driver(aspeed_watchdog_driver); + +static int __init aspeed_wdt_init(void) +{ + return platform_driver_register(_watchdog_driver); +} +arch_initcall(aspeed_wdt_init); + +static void __exit aspeed_wdt_exit(void) +{ + platform_driver_unregister(_watchdog_driver); +} +module_exit(aspeed_wdt_exit); MODULE_DESCRIPTION("Aspeed Watchdog Driver"); MODULE_LICENSE("GPL"); -- 2.11.0
Re: [PATCH v3] pci: dwc: dra7xx: Add shutdown handler to cleanly turn off clocks
On Wednesday 20 September 2017 01:00 AM, Bjorn Helgaas wrote: > On Fri, Sep 08, 2017 at 10:44:54AM +0530, Keerthy wrote: >> Add shutdown handler to cleanly turn off clocks. This will help >> in cases of kexec where in a new kernel can boot abruptly. >> >> Signed-off-by: Keerthy>> Acked-by: Kishon Vijay Abraham I >> --- >> >> Changes in v3: >> >> * Pushed the function outside #ifdef CONFIG_PM_SLEEP. >> * Added more details to commit log. >> >> Changes in v2: >> >> * used a local dev pointer instead of dereferencing dev at multiple places. >> * dra7xx_pcie_stop_link before disabling clks in the shutdown path. > > You lost both these changes in v3. I assume you'll post a v4. Thanks Bjorn for catching this! Sent v4 with the corrections. https://patchwork.ozlabs.org/patch/816010/ Regards, Keerthy > >> drivers/pci/dwc/pci-dra7xx.c | 14 ++ >> 1 file changed, 14 insertions(+) >> >> diff --git a/drivers/pci/dwc/pci-dra7xx.c b/drivers/pci/dwc/pci-dra7xx.c >> index 0f9adf2..ec8f842 100644 >> --- a/drivers/pci/dwc/pci-dra7xx.c >> +++ b/drivers/pci/dwc/pci-dra7xx.c >> @@ -794,6 +794,19 @@ static int dra7xx_pcie_resume_noirq(struct device *dev) >> } >> #endif >> >> +void dra7xx_pcie_shutdown(struct platform_device *pdev) >> +{ >> +struct dra7xx_pcie *dra7xx = dev_get_drvdata(>dev); >> +int ret; >> + >> +ret = pm_runtime_put_sync(>dev); >> +if (ret < 0) >> +dev_dbg(>dev, "pm_runtime_put_sync failed\n"); >> + >> +pm_runtime_disable(>dev); >> +dra7xx_pcie_disable_phy(dra7xx); >> +} >> + >> static const struct dev_pm_ops dra7xx_pcie_pm_ops = { >> SET_SYSTEM_SLEEP_PM_OPS(dra7xx_pcie_suspend, dra7xx_pcie_resume) >> SET_NOIRQ_SYSTEM_SLEEP_PM_OPS(dra7xx_pcie_suspend_noirq, >> @@ -807,5 +820,6 @@ static int dra7xx_pcie_resume_noirq(struct device *dev) >> .suppress_bind_attrs = true, >> .pm = _pcie_pm_ops, >> }, >> +.shutdown = dra7xx_pcie_shutdown, >> }; >> builtin_platform_driver_probe(dra7xx_pcie_driver, dra7xx_pcie_probe); >> -- >> 1.9.1 >>
Re: [PATCH v3] pci: dwc: dra7xx: Add shutdown handler to cleanly turn off clocks
On Wednesday 20 September 2017 01:00 AM, Bjorn Helgaas wrote: > On Fri, Sep 08, 2017 at 10:44:54AM +0530, Keerthy wrote: >> Add shutdown handler to cleanly turn off clocks. This will help >> in cases of kexec where in a new kernel can boot abruptly. >> >> Signed-off-by: Keerthy >> Acked-by: Kishon Vijay Abraham I >> --- >> >> Changes in v3: >> >> * Pushed the function outside #ifdef CONFIG_PM_SLEEP. >> * Added more details to commit log. >> >> Changes in v2: >> >> * used a local dev pointer instead of dereferencing dev at multiple places. >> * dra7xx_pcie_stop_link before disabling clks in the shutdown path. > > You lost both these changes in v3. I assume you'll post a v4. Thanks Bjorn for catching this! Sent v4 with the corrections. https://patchwork.ozlabs.org/patch/816010/ Regards, Keerthy > >> drivers/pci/dwc/pci-dra7xx.c | 14 ++ >> 1 file changed, 14 insertions(+) >> >> diff --git a/drivers/pci/dwc/pci-dra7xx.c b/drivers/pci/dwc/pci-dra7xx.c >> index 0f9adf2..ec8f842 100644 >> --- a/drivers/pci/dwc/pci-dra7xx.c >> +++ b/drivers/pci/dwc/pci-dra7xx.c >> @@ -794,6 +794,19 @@ static int dra7xx_pcie_resume_noirq(struct device *dev) >> } >> #endif >> >> +void dra7xx_pcie_shutdown(struct platform_device *pdev) >> +{ >> +struct dra7xx_pcie *dra7xx = dev_get_drvdata(>dev); >> +int ret; >> + >> +ret = pm_runtime_put_sync(>dev); >> +if (ret < 0) >> +dev_dbg(>dev, "pm_runtime_put_sync failed\n"); >> + >> +pm_runtime_disable(>dev); >> +dra7xx_pcie_disable_phy(dra7xx); >> +} >> + >> static const struct dev_pm_ops dra7xx_pcie_pm_ops = { >> SET_SYSTEM_SLEEP_PM_OPS(dra7xx_pcie_suspend, dra7xx_pcie_resume) >> SET_NOIRQ_SYSTEM_SLEEP_PM_OPS(dra7xx_pcie_suspend_noirq, >> @@ -807,5 +820,6 @@ static int dra7xx_pcie_resume_noirq(struct device *dev) >> .suppress_bind_attrs = true, >> .pm = _pcie_pm_ops, >> }, >> +.shutdown = dra7xx_pcie_shutdown, >> }; >> builtin_platform_driver_probe(dra7xx_pcie_driver, dra7xx_pcie_probe); >> -- >> 1.9.1 >>
[PATCH v4 2/2] ACPI / CPPC: Make cppc acpi driver aware of pcc subspace ids
Based on ACPI 6.2 Section 8.4.7.1.9 If the PCC register space is used, all PCC registers, for all processors in the same performance domain (as defined by _PSD), must be defined to be in the same subspace. Based on Section 14.1 of ACPI specification, it is possible to have a maximum of 256 PCC subspace ids. Add support of multiple PCC subspace id instead of using a single global pcc_data structure. While at that fix the time_delta check in send_pcc_cmd() so that last_mpar_reset and mpar_count is initialized properly. Signed-off-by: George Cherian--- drivers/acpi/cppc_acpi.c | 243 +-- 1 file changed, 153 insertions(+), 90 deletions(-) diff --git a/drivers/acpi/cppc_acpi.c b/drivers/acpi/cppc_acpi.c index e5b47f0..3ae79ef 100644 --- a/drivers/acpi/cppc_acpi.c +++ b/drivers/acpi/cppc_acpi.c @@ -75,13 +75,16 @@ struct cppc_pcc_data { /* Wait queue for CPUs whose requests were batched */ wait_queue_head_t pcc_write_wait_q; + ktime_t last_cmd_cmpl_time; + ktime_t last_mpar_reset; + int mpar_count; + int refcount; }; -/* Structure to represent the single PCC channel */ -static struct cppc_pcc_data pcc_data = { - .pcc_subspace_idx = -1, - .platform_owns_pcc = true, -}; +/* Array to represent the PCC channel per subspace id */ +static struct cppc_pcc_data *pcc_data[MAX_PCC_SUBSPACES]; +/* The cpu_pcc_subspace_idx containsper CPU subspace id */ +static DEFINE_PER_CPU(int, cpu_pcc_subspace_idx); /* * The cpc_desc structure contains the ACPI register details @@ -93,7 +96,8 @@ static struct cppc_pcc_data pcc_data = { static DEFINE_PER_CPU(struct cpc_desc *, cpc_desc_ptr); /* pcc mapped address + header size + offset within PCC subspace */ -#define GET_PCC_VADDR(offs) (pcc_data.pcc_comm_addr + 0x8 + (offs)) +#define GET_PCC_VADDR(offs, pcc_ss_id) (pcc_data[pcc_ss_id]->pcc_comm_addr + \ + 0x8 + (offs)) /* Check if a CPC register is in PCC */ #define CPC_IN_PCC(cpc) ((cpc)->type == ACPI_TYPE_BUFFER &&\ @@ -188,13 +192,16 @@ static struct kobj_type cppc_ktype = { .default_attrs = cppc_attrs, }; -static int check_pcc_chan(bool chk_err_bit) +static int check_pcc_chan(int pcc_ss_id, bool chk_err_bit) { int ret = -EIO, status = 0; - struct acpi_pcct_shared_memory __iomem *generic_comm_base = pcc_data.pcc_comm_addr; - ktime_t next_deadline = ktime_add(ktime_get(), pcc_data.deadline); + struct cppc_pcc_data *pcc_ss_data = pcc_data[pcc_ss_id]; + struct acpi_pcct_shared_memory __iomem *generic_comm_base = + pcc_ss_data->pcc_comm_addr; + ktime_t next_deadline = ktime_add(ktime_get(), + pcc_ss_data->deadline); - if (!pcc_data.platform_owns_pcc) + if (!pcc_ss_data->platform_owns_pcc) return 0; /* Retry in case the remote processor was too slow to catch up. */ @@ -219,7 +226,7 @@ static int check_pcc_chan(bool chk_err_bit) } if (likely(!ret)) - pcc_data.platform_owns_pcc = false; + pcc_ss_data->platform_owns_pcc = false; else pr_err("PCC check channel failed. Status=%x\n", status); @@ -230,13 +237,12 @@ static int check_pcc_chan(bool chk_err_bit) * This function transfers the ownership of the PCC to the platform * So it must be called while holding write_lock(pcc_lock) */ -static int send_pcc_cmd(u16 cmd) +static int send_pcc_cmd(int pcc_ss_id, u16 cmd) { int ret = -EIO, i; + struct cppc_pcc_data *pcc_ss_data = pcc_data[pcc_ss_id]; struct acpi_pcct_shared_memory *generic_comm_base = - (struct acpi_pcct_shared_memory *) pcc_data.pcc_comm_addr; - static ktime_t last_cmd_cmpl_time, last_mpar_reset; - static int mpar_count; + (struct acpi_pcct_shared_memory *)pcc_ss_data->pcc_comm_addr; unsigned int time_delta; /* @@ -249,24 +255,25 @@ static int send_pcc_cmd(u16 cmd) * before write completion, so first send a WRITE command to * platform */ - if (pcc_data.pending_pcc_write_cmd) - send_pcc_cmd(CMD_WRITE); + if (pcc_ss_data->pending_pcc_write_cmd) + send_pcc_cmd(pcc_ss_id, CMD_WRITE); - ret = check_pcc_chan(false); + ret = check_pcc_chan(pcc_ss_id, false); if (ret) goto end; } else /* CMD_WRITE */ - pcc_data.pending_pcc_write_cmd = FALSE; + pcc_ss_data->pending_pcc_write_cmd = FALSE; /* * Handle the Minimum Request Turnaround Time(MRTT) * "The minimum amount of time that OSPM must wait after the completion * of a command before issuing the next command, in microseconds"
[PATCH v4 2/2] ACPI / CPPC: Make cppc acpi driver aware of pcc subspace ids
Based on ACPI 6.2 Section 8.4.7.1.9 If the PCC register space is used, all PCC registers, for all processors in the same performance domain (as defined by _PSD), must be defined to be in the same subspace. Based on Section 14.1 of ACPI specification, it is possible to have a maximum of 256 PCC subspace ids. Add support of multiple PCC subspace id instead of using a single global pcc_data structure. While at that fix the time_delta check in send_pcc_cmd() so that last_mpar_reset and mpar_count is initialized properly. Signed-off-by: George Cherian --- drivers/acpi/cppc_acpi.c | 243 +-- 1 file changed, 153 insertions(+), 90 deletions(-) diff --git a/drivers/acpi/cppc_acpi.c b/drivers/acpi/cppc_acpi.c index e5b47f0..3ae79ef 100644 --- a/drivers/acpi/cppc_acpi.c +++ b/drivers/acpi/cppc_acpi.c @@ -75,13 +75,16 @@ struct cppc_pcc_data { /* Wait queue for CPUs whose requests were batched */ wait_queue_head_t pcc_write_wait_q; + ktime_t last_cmd_cmpl_time; + ktime_t last_mpar_reset; + int mpar_count; + int refcount; }; -/* Structure to represent the single PCC channel */ -static struct cppc_pcc_data pcc_data = { - .pcc_subspace_idx = -1, - .platform_owns_pcc = true, -}; +/* Array to represent the PCC channel per subspace id */ +static struct cppc_pcc_data *pcc_data[MAX_PCC_SUBSPACES]; +/* The cpu_pcc_subspace_idx containsper CPU subspace id */ +static DEFINE_PER_CPU(int, cpu_pcc_subspace_idx); /* * The cpc_desc structure contains the ACPI register details @@ -93,7 +96,8 @@ static struct cppc_pcc_data pcc_data = { static DEFINE_PER_CPU(struct cpc_desc *, cpc_desc_ptr); /* pcc mapped address + header size + offset within PCC subspace */ -#define GET_PCC_VADDR(offs) (pcc_data.pcc_comm_addr + 0x8 + (offs)) +#define GET_PCC_VADDR(offs, pcc_ss_id) (pcc_data[pcc_ss_id]->pcc_comm_addr + \ + 0x8 + (offs)) /* Check if a CPC register is in PCC */ #define CPC_IN_PCC(cpc) ((cpc)->type == ACPI_TYPE_BUFFER &&\ @@ -188,13 +192,16 @@ static struct kobj_type cppc_ktype = { .default_attrs = cppc_attrs, }; -static int check_pcc_chan(bool chk_err_bit) +static int check_pcc_chan(int pcc_ss_id, bool chk_err_bit) { int ret = -EIO, status = 0; - struct acpi_pcct_shared_memory __iomem *generic_comm_base = pcc_data.pcc_comm_addr; - ktime_t next_deadline = ktime_add(ktime_get(), pcc_data.deadline); + struct cppc_pcc_data *pcc_ss_data = pcc_data[pcc_ss_id]; + struct acpi_pcct_shared_memory __iomem *generic_comm_base = + pcc_ss_data->pcc_comm_addr; + ktime_t next_deadline = ktime_add(ktime_get(), + pcc_ss_data->deadline); - if (!pcc_data.platform_owns_pcc) + if (!pcc_ss_data->platform_owns_pcc) return 0; /* Retry in case the remote processor was too slow to catch up. */ @@ -219,7 +226,7 @@ static int check_pcc_chan(bool chk_err_bit) } if (likely(!ret)) - pcc_data.platform_owns_pcc = false; + pcc_ss_data->platform_owns_pcc = false; else pr_err("PCC check channel failed. Status=%x\n", status); @@ -230,13 +237,12 @@ static int check_pcc_chan(bool chk_err_bit) * This function transfers the ownership of the PCC to the platform * So it must be called while holding write_lock(pcc_lock) */ -static int send_pcc_cmd(u16 cmd) +static int send_pcc_cmd(int pcc_ss_id, u16 cmd) { int ret = -EIO, i; + struct cppc_pcc_data *pcc_ss_data = pcc_data[pcc_ss_id]; struct acpi_pcct_shared_memory *generic_comm_base = - (struct acpi_pcct_shared_memory *) pcc_data.pcc_comm_addr; - static ktime_t last_cmd_cmpl_time, last_mpar_reset; - static int mpar_count; + (struct acpi_pcct_shared_memory *)pcc_ss_data->pcc_comm_addr; unsigned int time_delta; /* @@ -249,24 +255,25 @@ static int send_pcc_cmd(u16 cmd) * before write completion, so first send a WRITE command to * platform */ - if (pcc_data.pending_pcc_write_cmd) - send_pcc_cmd(CMD_WRITE); + if (pcc_ss_data->pending_pcc_write_cmd) + send_pcc_cmd(pcc_ss_id, CMD_WRITE); - ret = check_pcc_chan(false); + ret = check_pcc_chan(pcc_ss_id, false); if (ret) goto end; } else /* CMD_WRITE */ - pcc_data.pending_pcc_write_cmd = FALSE; + pcc_ss_data->pending_pcc_write_cmd = FALSE; /* * Handle the Minimum Request Turnaround Time(MRTT) * "The minimum amount of time that OSPM must wait after the completion * of a command before issuing the next command, in microseconds" */ - if
[PATCH v4 1/2] mailbox: PCC: Move the MAX_PCC_SUBSPACES definition to header file
Move the MAX_PCC_SUBSPACES definition to acpi/pcc.h file. In preparation to add subspace id support for cppc_acpi driver. Signed-off-by: George Cherian--- drivers/mailbox/pcc.c | 1 - include/acpi/pcc.h| 1 + 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/mailbox/pcc.c b/drivers/mailbox/pcc.c index 9b7005e..e5a6967 100644 --- a/drivers/mailbox/pcc.c +++ b/drivers/mailbox/pcc.c @@ -69,7 +69,6 @@ #include "mailbox.h" -#define MAX_PCC_SUBSPACES 256 #define MBOX_IRQ_NAME "pcc-mbox" static struct mbox_chan *pcc_mbox_channels; diff --git a/include/acpi/pcc.h b/include/acpi/pcc.h index 8caa79c..cd6ef45 100644 --- a/include/acpi/pcc.h +++ b/include/acpi/pcc.h @@ -13,6 +13,7 @@ #include #include +#define MAX_PCC_SUBSPACES 256 #ifdef CONFIG_PCC extern struct mbox_chan *pcc_mbox_request_channel(struct mbox_client *cl, int subspace_id); -- 2.1.4
[PATCH v4] pci: dwc: dra7xx: Add shutdown handler to cleanly turn off clocks
Add shutdown handler to cleanly turn off clocks. This will help in cases of kexec where in a new kernel can boot abruptly. Signed-off-by: KeerthyAcked-by: Kishon Vijay Abraham I --- Changes in v4: * Added the missing changes from v2! Changes in v3: * Pushed the function outside #ifdef CONFIG_PM_SLEEP. * Added more details to commit log. Changes in v2: * used a local dev pointer instead of dereferencing dev at multiple places. * dra7xx_pcie_stop_link before disabling clks in the shutdown path. drivers/pci/dwc/pci-dra7xx.c | 17 + 1 file changed, 17 insertions(+) diff --git a/drivers/pci/dwc/pci-dra7xx.c b/drivers/pci/dwc/pci-dra7xx.c index 34427a6..d084800 100644 --- a/drivers/pci/dwc/pci-dra7xx.c +++ b/drivers/pci/dwc/pci-dra7xx.c @@ -794,6 +794,22 @@ static int dra7xx_pcie_resume_noirq(struct device *dev) } #endif +void dra7xx_pcie_shutdown(struct platform_device *pdev) +{ + struct device *dev = >dev; + struct dra7xx_pcie *dra7xx = dev_get_drvdata(dev); + int ret; + + dra7xx_pcie_stop_link(dra7xx->pci); + + ret = pm_runtime_put_sync(dev); + if (ret < 0) + dev_dbg(dev, "pm_runtime_put_sync failed\n"); + + pm_runtime_disable(dev); + dra7xx_pcie_disable_phy(dra7xx); +} + static const struct dev_pm_ops dra7xx_pcie_pm_ops = { SET_SYSTEM_SLEEP_PM_OPS(dra7xx_pcie_suspend, dra7xx_pcie_resume) SET_NOIRQ_SYSTEM_SLEEP_PM_OPS(dra7xx_pcie_suspend_noirq, @@ -807,5 +823,6 @@ static int dra7xx_pcie_resume_noirq(struct device *dev) .suppress_bind_attrs = true, .pm = _pcie_pm_ops, }, + .shutdown = dra7xx_pcie_shutdown, }; builtin_platform_driver_probe(dra7xx_pcie_driver, dra7xx_pcie_probe); -- 1.9.1
[PATCH v4 1/2] mailbox: PCC: Move the MAX_PCC_SUBSPACES definition to header file
Move the MAX_PCC_SUBSPACES definition to acpi/pcc.h file. In preparation to add subspace id support for cppc_acpi driver. Signed-off-by: George Cherian --- drivers/mailbox/pcc.c | 1 - include/acpi/pcc.h| 1 + 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/mailbox/pcc.c b/drivers/mailbox/pcc.c index 9b7005e..e5a6967 100644 --- a/drivers/mailbox/pcc.c +++ b/drivers/mailbox/pcc.c @@ -69,7 +69,6 @@ #include "mailbox.h" -#define MAX_PCC_SUBSPACES 256 #define MBOX_IRQ_NAME "pcc-mbox" static struct mbox_chan *pcc_mbox_channels; diff --git a/include/acpi/pcc.h b/include/acpi/pcc.h index 8caa79c..cd6ef45 100644 --- a/include/acpi/pcc.h +++ b/include/acpi/pcc.h @@ -13,6 +13,7 @@ #include #include +#define MAX_PCC_SUBSPACES 256 #ifdef CONFIG_PCC extern struct mbox_chan *pcc_mbox_request_channel(struct mbox_client *cl, int subspace_id); -- 2.1.4
[PATCH v4] pci: dwc: dra7xx: Add shutdown handler to cleanly turn off clocks
Add shutdown handler to cleanly turn off clocks. This will help in cases of kexec where in a new kernel can boot abruptly. Signed-off-by: Keerthy Acked-by: Kishon Vijay Abraham I --- Changes in v4: * Added the missing changes from v2! Changes in v3: * Pushed the function outside #ifdef CONFIG_PM_SLEEP. * Added more details to commit log. Changes in v2: * used a local dev pointer instead of dereferencing dev at multiple places. * dra7xx_pcie_stop_link before disabling clks in the shutdown path. drivers/pci/dwc/pci-dra7xx.c | 17 + 1 file changed, 17 insertions(+) diff --git a/drivers/pci/dwc/pci-dra7xx.c b/drivers/pci/dwc/pci-dra7xx.c index 34427a6..d084800 100644 --- a/drivers/pci/dwc/pci-dra7xx.c +++ b/drivers/pci/dwc/pci-dra7xx.c @@ -794,6 +794,22 @@ static int dra7xx_pcie_resume_noirq(struct device *dev) } #endif +void dra7xx_pcie_shutdown(struct platform_device *pdev) +{ + struct device *dev = >dev; + struct dra7xx_pcie *dra7xx = dev_get_drvdata(dev); + int ret; + + dra7xx_pcie_stop_link(dra7xx->pci); + + ret = pm_runtime_put_sync(dev); + if (ret < 0) + dev_dbg(dev, "pm_runtime_put_sync failed\n"); + + pm_runtime_disable(dev); + dra7xx_pcie_disable_phy(dra7xx); +} + static const struct dev_pm_ops dra7xx_pcie_pm_ops = { SET_SYSTEM_SLEEP_PM_OPS(dra7xx_pcie_suspend, dra7xx_pcie_resume) SET_NOIRQ_SYSTEM_SLEEP_PM_OPS(dra7xx_pcie_suspend_noirq, @@ -807,5 +823,6 @@ static int dra7xx_pcie_resume_noirq(struct device *dev) .suppress_bind_attrs = true, .pm = _pcie_pm_ops, }, + .shutdown = dra7xx_pcie_shutdown, }; builtin_platform_driver_probe(dra7xx_pcie_driver, dra7xx_pcie_probe); -- 1.9.1
[PATCH v4 0/2] Make cppc acpi driver aware of pcc subspace ids
The current cppc acpi driver works with only one pcc subspace id. It maintains and registers only one pcc channel even if the acpi table has different pcc subspace ids. As per ACPI 6.2 spec all PCC registers, for all processors in the same performance domain (as defined by _PSD), must be defined to be in the same subspace. The series tries to address the same by making cppc acpi driver aware of multiple possible pcc subspace ids. Patch 1 : In preparation to share the MAX_PCC_SUBSPACE definition with cppc acpi driver Patch 2 : Make the cppc acpi driver aware of multiple pcc subspace ids. Changes from v3: - Address Issue reported by kbuild-robot. Changes from v2: - Addressed Prashanth's comments on * Not to use local variables to update mpar_count, last_mpar_reset and last_cmd_cmpl_time * Add check for kzalloc failure in pcc_data_alloc() * Initialize pcc_subspace_id to -1 in acpi_cppc_processor_probe() * Check for pcc_subspace_id validity before registering pcc_channel Changes from v1: - Add last_cmd_cmpl_time, last_mpar_reset, mpar_count to the cppc_pcc_data to make it per subspace. - PCC per subspace dynamic allocation support added instead of static allocation - Added a new function pcc_data_alloc, In instances where CPU's with SMT support same PCC subspace would be used for all CPU's belonging to same physical core. This function adds the pcc_subspace refcounting and allocates the cppc_pcc_data per unique subspace idx. - Added cleanup in acpi_cppc_processor_exit. Free the mbox channel and free the cppc_pcc_data in case refcount is zero. George Cherian (2): mailbox: PCC: Move the MAX_PCC_SUBSPACES definition to header file ACPI / CPPC: Make cppc acpi driver aware of pcc subspace ids drivers/acpi/cppc_acpi.c | 243 +-- drivers/mailbox/pcc.c| 1 - include/acpi/pcc.h | 1 + 3 files changed, 154 insertions(+), 91 deletions(-) -- 2.1.4
[PATCH v4 0/2] Make cppc acpi driver aware of pcc subspace ids
The current cppc acpi driver works with only one pcc subspace id. It maintains and registers only one pcc channel even if the acpi table has different pcc subspace ids. As per ACPI 6.2 spec all PCC registers, for all processors in the same performance domain (as defined by _PSD), must be defined to be in the same subspace. The series tries to address the same by making cppc acpi driver aware of multiple possible pcc subspace ids. Patch 1 : In preparation to share the MAX_PCC_SUBSPACE definition with cppc acpi driver Patch 2 : Make the cppc acpi driver aware of multiple pcc subspace ids. Changes from v3: - Address Issue reported by kbuild-robot. Changes from v2: - Addressed Prashanth's comments on * Not to use local variables to update mpar_count, last_mpar_reset and last_cmd_cmpl_time * Add check for kzalloc failure in pcc_data_alloc() * Initialize pcc_subspace_id to -1 in acpi_cppc_processor_probe() * Check for pcc_subspace_id validity before registering pcc_channel Changes from v1: - Add last_cmd_cmpl_time, last_mpar_reset, mpar_count to the cppc_pcc_data to make it per subspace. - PCC per subspace dynamic allocation support added instead of static allocation - Added a new function pcc_data_alloc, In instances where CPU's with SMT support same PCC subspace would be used for all CPU's belonging to same physical core. This function adds the pcc_subspace refcounting and allocates the cppc_pcc_data per unique subspace idx. - Added cleanup in acpi_cppc_processor_exit. Free the mbox channel and free the cppc_pcc_data in case refcount is zero. George Cherian (2): mailbox: PCC: Move the MAX_PCC_SUBSPACES definition to header file ACPI / CPPC: Make cppc acpi driver aware of pcc subspace ids drivers/acpi/cppc_acpi.c | 243 +-- drivers/mailbox/pcc.c| 1 - include/acpi/pcc.h | 1 + 3 files changed, 154 insertions(+), 91 deletions(-) -- 2.1.4
[PATCH v5] [DVB][FRONTEND] Modified the code related to FE_SET_PROPERTY ioctl
-Since all the properties in the func dtv_property_process_set are 4 bytes, We have added 2 new arguments u32 cmd and u32 data; in place of older argument struct dtv_property *tvp. -We have removed property validation in function dtv_property_process_set because most of the frontend drivers in linux source are not using the method ops.set_property. -In place of dtv_property_dump, we have added own logic to dump cmd and data of the incoming property -We have also re-named dtv_property_dump to dtv_get_property_dump. -We have modified logs in this func to be suitable only for getting properties. Signed-off-by: Satendra Singh Thakur--- drivers/media/dvb-core/dvb_frontend.c | 135 ++ 1 file changed, 73 insertions(+), 62 deletions(-) diff --git a/drivers/media/dvb-core/dvb_frontend.c b/drivers/media/dvb-core/dvb_frontend.c index 2fcba16..013476e 100644 --- a/drivers/media/dvb-core/dvb_frontend.c +++ b/drivers/media/dvb-core/dvb_frontend.c @@ -1092,22 +1092,19 @@ static struct dtv_cmds_h dtv_cmds[DTV_MAX_COMMAND + 1] = { _DTV_CMD(DTV_STAT_TOTAL_BLOCK_COUNT, 0, 0), }; -static void dtv_property_dump(struct dvb_frontend *fe, - bool is_set, +static void dtv_get_property_dump(struct dvb_frontend *fe, struct dtv_property *tvp) { int i; if (tvp->cmd <= 0 || tvp->cmd > DTV_MAX_COMMAND) { - dev_warn(fe->dvb->device, "%s: %s tvp.cmd = 0x%08x undefined\n", - __func__, - is_set ? "SET" : "GET", + dev_warn(fe->dvb->device, "%s: GET tvp.cmd = 0x%08x undefined\n" + , __func__, tvp->cmd); return; } - dev_dbg(fe->dvb->device, "%s: %s tvp.cmd= 0x%08x (%s)\n", __func__, - is_set ? "SET" : "GET", + dev_dbg(fe->dvb->device, "%s: GET tvp.cmd= 0x%08x (%s)\n", __func__, tvp->cmd, dtv_cmds[tvp->cmd].name); @@ -1526,7 +1523,7 @@ static int dtv_property_process_get(struct dvb_frontend *fe, return r; } - dtv_property_dump(fe, false, tvp); + dtv_get_property_dump(fe, tvp); return 0; } @@ -1749,23 +1746,35 @@ static int dvbv3_set_delivery_system(struct dvb_frontend *fe) return emulate_delivery_system(fe, delsys); } +/** + * dtv_property_process_set - Sets a single DTV property + * @fe:Pointer to dvb_frontend + * @file: Pointer to file + * @cmd: Digital TV command + * @data: An unsigned 32-bits number + * + * This routine assigns the property + * value to the corresponding member of + * dtv_frontend_properties + * + * Returns: + * Zero on success, negative errno on failure. + */ static int dtv_property_process_set(struct dvb_frontend *fe, - struct dtv_property *tvp, - struct file *file) + struct file *file, + u32 cmd, u32 data) { int r = 0; struct dtv_frontend_properties *c = >dtv_property_cache; - - /* Allow the frontend to validate incoming properties */ - if (fe->ops.set_property) { - r = fe->ops.set_property(fe, tvp); - if (r < 0) - return r; - } - - dtv_property_dump(fe, true, tvp); - - switch(tvp->cmd) { + /** Dump DTV command name and value*/ + if (!cmd || cmd > DTV_MAX_COMMAND) + dev_warn(fe->dvb->device, "%s: SET cmd 0x%08x undefined\n", +__func__, cmd); + else + dev_dbg(fe->dvb->device, + "%s: SET cmd 0x%08x (%s) to 0x%08x\n", + __func__, cmd, dtv_cmds[cmd].name, data); + switch (cmd) { case DTV_CLEAR: /* * Reset a cache of data specific to the frontend here. This does @@ -1778,140 +1787,140 @@ static int dtv_property_process_set(struct dvb_frontend *fe, * tunerequest so we can pass validation in the FE_SET_FRONTEND * ioctl. */ - c->state = tvp->cmd; + c->state = cmd; dev_dbg(fe->dvb->device, "%s: Finalised property cache\n", __func__); r = dtv_set_frontend(fe); break; case DTV_FREQUENCY: - c->frequency = tvp->u.data; + c->frequency = data; break; case DTV_MODULATION: - c->modulation = tvp->u.data; + c->modulation = data; break; case DTV_BANDWIDTH_HZ: - c->bandwidth_hz = tvp->u.data; + c->bandwidth_hz = data;
[PATCH v5] [DVB][FRONTEND] Modified the code related to FE_SET_PROPERTY ioctl
-Since all the properties in the func dtv_property_process_set are 4 bytes, We have added 2 new arguments u32 cmd and u32 data; in place of older argument struct dtv_property *tvp. -We have removed property validation in function dtv_property_process_set because most of the frontend drivers in linux source are not using the method ops.set_property. -In place of dtv_property_dump, we have added own logic to dump cmd and data of the incoming property -We have also re-named dtv_property_dump to dtv_get_property_dump. -We have modified logs in this func to be suitable only for getting properties. Signed-off-by: Satendra Singh Thakur --- drivers/media/dvb-core/dvb_frontend.c | 135 ++ 1 file changed, 73 insertions(+), 62 deletions(-) diff --git a/drivers/media/dvb-core/dvb_frontend.c b/drivers/media/dvb-core/dvb_frontend.c index 2fcba16..013476e 100644 --- a/drivers/media/dvb-core/dvb_frontend.c +++ b/drivers/media/dvb-core/dvb_frontend.c @@ -1092,22 +1092,19 @@ static struct dtv_cmds_h dtv_cmds[DTV_MAX_COMMAND + 1] = { _DTV_CMD(DTV_STAT_TOTAL_BLOCK_COUNT, 0, 0), }; -static void dtv_property_dump(struct dvb_frontend *fe, - bool is_set, +static void dtv_get_property_dump(struct dvb_frontend *fe, struct dtv_property *tvp) { int i; if (tvp->cmd <= 0 || tvp->cmd > DTV_MAX_COMMAND) { - dev_warn(fe->dvb->device, "%s: %s tvp.cmd = 0x%08x undefined\n", - __func__, - is_set ? "SET" : "GET", + dev_warn(fe->dvb->device, "%s: GET tvp.cmd = 0x%08x undefined\n" + , __func__, tvp->cmd); return; } - dev_dbg(fe->dvb->device, "%s: %s tvp.cmd= 0x%08x (%s)\n", __func__, - is_set ? "SET" : "GET", + dev_dbg(fe->dvb->device, "%s: GET tvp.cmd= 0x%08x (%s)\n", __func__, tvp->cmd, dtv_cmds[tvp->cmd].name); @@ -1526,7 +1523,7 @@ static int dtv_property_process_get(struct dvb_frontend *fe, return r; } - dtv_property_dump(fe, false, tvp); + dtv_get_property_dump(fe, tvp); return 0; } @@ -1749,23 +1746,35 @@ static int dvbv3_set_delivery_system(struct dvb_frontend *fe) return emulate_delivery_system(fe, delsys); } +/** + * dtv_property_process_set - Sets a single DTV property + * @fe:Pointer to dvb_frontend + * @file: Pointer to file + * @cmd: Digital TV command + * @data: An unsigned 32-bits number + * + * This routine assigns the property + * value to the corresponding member of + * dtv_frontend_properties + * + * Returns: + * Zero on success, negative errno on failure. + */ static int dtv_property_process_set(struct dvb_frontend *fe, - struct dtv_property *tvp, - struct file *file) + struct file *file, + u32 cmd, u32 data) { int r = 0; struct dtv_frontend_properties *c = >dtv_property_cache; - - /* Allow the frontend to validate incoming properties */ - if (fe->ops.set_property) { - r = fe->ops.set_property(fe, tvp); - if (r < 0) - return r; - } - - dtv_property_dump(fe, true, tvp); - - switch(tvp->cmd) { + /** Dump DTV command name and value*/ + if (!cmd || cmd > DTV_MAX_COMMAND) + dev_warn(fe->dvb->device, "%s: SET cmd 0x%08x undefined\n", +__func__, cmd); + else + dev_dbg(fe->dvb->device, + "%s: SET cmd 0x%08x (%s) to 0x%08x\n", + __func__, cmd, dtv_cmds[cmd].name, data); + switch (cmd) { case DTV_CLEAR: /* * Reset a cache of data specific to the frontend here. This does @@ -1778,140 +1787,140 @@ static int dtv_property_process_set(struct dvb_frontend *fe, * tunerequest so we can pass validation in the FE_SET_FRONTEND * ioctl. */ - c->state = tvp->cmd; + c->state = cmd; dev_dbg(fe->dvb->device, "%s: Finalised property cache\n", __func__); r = dtv_set_frontend(fe); break; case DTV_FREQUENCY: - c->frequency = tvp->u.data; + c->frequency = data; break; case DTV_MODULATION: - c->modulation = tvp->u.data; + c->modulation = data; break; case DTV_BANDWIDTH_HZ: - c->bandwidth_hz = tvp->u.data; + c->bandwidth_hz = data; break; case
Re: [RFC] sched/fair: Use wake_q length as a hint for wake_wide
> On Tue, Sep 19, 2017 at 3:05 AM, Brendan Jackman >wrote: >> On Mon, Sep 18 2017 at 22:15, Joel Fernandes wrote: [..] IIUC, if wake_affine() behaves correctly this trick wouldn't be necessary on SMP systems, so it might be best guarded by the presence >>> >>> Actually wake_affine doesn't check for balance if previous/next cpu >>> are within the same shared cache domain. The difference is some time >>> ago it would return true for shared cache but now it returns false as >>> of 4.14-rc1: >>> http://elixir.free-electrons.com/linux/v4.14-rc1/source/kernel/sched/fair.c#L5466 >>> >>> Since it would return false in the above wake up cases for task 1 and >>> 2, it would then run select_idle_sibling on the previous CPU which is >>> also within the big cluster, so I don't think it will make a >>> difference in this case... Infact what it returns probably doesn't >>> matter. >> >> So my paragraph here was making a leap in reasoning, let me try to fill >> the gap: On SMP these tasks never need to move around. If by some chance >> they did get coscheduled, the first load balance would spread them out and >> then every time they wake up from then on, prev_cpu is the sensible >> choice. So it will look something like: >> >> v CPU v ->time-> >> >> - >> { 0 (SAME) 111 >> cache { - >> { 1 (SAME) | >> - >> { 2 (SAME) 333 >> cache { - >> { 3 (SAME) 444 >> - >> >> So here, task 2 wakes up the other guys and when it's doing tasks 3 and >> 4, prev_cpu and smp_processor_id() don't share a cache, so IIUC its' >> basically wake_affine's job to decide between prev_cpu and >> smp_processor_id(). So "if wake_affine is behaving correctly" the >> problem that this patch aims to solve (i.e. the fact that we overload >> the waker's LLC domain because of bias towards prev_cpu) does not arise >> on SMP. >> > > Yes SMP, but your patch is for solving a problem for non-SMP. So your > original statement about wake_affine solving any problem for SMP is > not relevant I feel :-P. I guess you can just kill this para from the > commit message to prevent confusion. Ok I take that back, you were talking about guarding this feature by the SD_ASYM_CPUCAPACITY flag. I don't think that protection would be helpful because you can have the same issue if the tasks do different amount of work on SMP. So in that case some threads might still complete before the others and you run into the same thing. thanks, - Joel
Re: [RFC] sched/fair: Use wake_q length as a hint for wake_wide
> On Tue, Sep 19, 2017 at 3:05 AM, Brendan Jackman > wrote: >> On Mon, Sep 18 2017 at 22:15, Joel Fernandes wrote: [..] IIUC, if wake_affine() behaves correctly this trick wouldn't be necessary on SMP systems, so it might be best guarded by the presence >>> >>> Actually wake_affine doesn't check for balance if previous/next cpu >>> are within the same shared cache domain. The difference is some time >>> ago it would return true for shared cache but now it returns false as >>> of 4.14-rc1: >>> http://elixir.free-electrons.com/linux/v4.14-rc1/source/kernel/sched/fair.c#L5466 >>> >>> Since it would return false in the above wake up cases for task 1 and >>> 2, it would then run select_idle_sibling on the previous CPU which is >>> also within the big cluster, so I don't think it will make a >>> difference in this case... Infact what it returns probably doesn't >>> matter. >> >> So my paragraph here was making a leap in reasoning, let me try to fill >> the gap: On SMP these tasks never need to move around. If by some chance >> they did get coscheduled, the first load balance would spread them out and >> then every time they wake up from then on, prev_cpu is the sensible >> choice. So it will look something like: >> >> v CPU v ->time-> >> >> - >> { 0 (SAME) 111 >> cache { - >> { 1 (SAME) | >> - >> { 2 (SAME) 333 >> cache { - >> { 3 (SAME) 444 >> - >> >> So here, task 2 wakes up the other guys and when it's doing tasks 3 and >> 4, prev_cpu and smp_processor_id() don't share a cache, so IIUC its' >> basically wake_affine's job to decide between prev_cpu and >> smp_processor_id(). So "if wake_affine is behaving correctly" the >> problem that this patch aims to solve (i.e. the fact that we overload >> the waker's LLC domain because of bias towards prev_cpu) does not arise >> on SMP. >> > > Yes SMP, but your patch is for solving a problem for non-SMP. So your > original statement about wake_affine solving any problem for SMP is > not relevant I feel :-P. I guess you can just kill this para from the > commit message to prevent confusion. Ok I take that back, you were talking about guarding this feature by the SD_ASYM_CPUCAPACITY flag. I don't think that protection would be helpful because you can have the same issue if the tasks do different amount of work on SMP. So in that case some threads might still complete before the others and you run into the same thing. thanks, - Joel
[PATCH review for 4.4 14/47] iio: adc: axp288: Drop bogus AXP288_ADC_TS_PIN_CTRL register modifications
From: Hans de Goede[ Upstream commit fa2849e9649b5180ffc4cb3c3b005261c403093a ] For some reason the axp288_adc driver was modifying the AXP288_ADC_TS_PIN_CTRL register, changing bits 0-1 depending on whether the GP_ADC channel or another channel was written. These bits control when a bias current is send to the TS_PIN, the GP_ADC has its own pin and a separate bit in another register to control the bias current. Not only does changing when to enable the TS_PIN bias current (always or only when sampling) when reading the GP_ADC make no sense at all, the code is modifying these bits is writing the entire register, assuming that all the other bits have their default value. So if the firmware has configured a different bias-current for either pin, then that change gets clobbered by the write, likewise if the firmware has set bit 2 to indicate that the battery has no thermal sensor, this will get clobbered by the write. This commit fixes all this, by simply removing all writes to the AXP288_ADC_TS_PIN_CTRL register, they are not needed to read the GP_ADC pin, and can actually be harmful. Signed-off-by: Hans de Goede Acked-by: Chen-Yu Tsai Signed-off-by: Jonathan Cameron Signed-off-by: Sasha Levin --- drivers/iio/adc/axp288_adc.c | 32 +--- 1 file changed, 1 insertion(+), 31 deletions(-) diff --git a/drivers/iio/adc/axp288_adc.c b/drivers/iio/adc/axp288_adc.c index 0c904edd6c00..f684fe31f832 100644 --- a/drivers/iio/adc/axp288_adc.c +++ b/drivers/iio/adc/axp288_adc.c @@ -28,8 +28,6 @@ #include #define AXP288_ADC_EN_MASK 0xF1 -#define AXP288_ADC_TS_PIN_GPADC0xF2 -#define AXP288_ADC_TS_PIN_ON 0xF3 enum axp288_adc_id { AXP288_ADC_TS, @@ -123,16 +121,6 @@ static int axp288_adc_read_channel(int *val, unsigned long address, return IIO_VAL_INT; } -static int axp288_adc_set_ts(struct regmap *regmap, unsigned int mode, - unsigned long address) -{ - /* channels other than GPADC do not need to switch TS pin */ - if (address != AXP288_GP_ADC_H) - return 0; - - return regmap_write(regmap, AXP288_ADC_TS_PIN_CTRL, mode); -} - static int axp288_adc_read_raw(struct iio_dev *indio_dev, struct iio_chan_spec const *chan, int *val, int *val2, long mask) @@ -143,16 +131,7 @@ static int axp288_adc_read_raw(struct iio_dev *indio_dev, mutex_lock(_dev->mlock); switch (mask) { case IIO_CHAN_INFO_RAW: - if (axp288_adc_set_ts(info->regmap, AXP288_ADC_TS_PIN_GPADC, - chan->address)) { - dev_err(_dev->dev, "GPADC mode\n"); - ret = -EINVAL; - break; - } ret = axp288_adc_read_channel(val, chan->address, info->regmap); - if (axp288_adc_set_ts(info->regmap, AXP288_ADC_TS_PIN_ON, - chan->address)) - dev_err(_dev->dev, "TS pin restore\n"); break; default: ret = -EINVAL; @@ -162,15 +141,6 @@ static int axp288_adc_read_raw(struct iio_dev *indio_dev, return ret; } -static int axp288_adc_set_state(struct regmap *regmap) -{ - /* ADC should be always enabled for internal FG to function */ - if (regmap_write(regmap, AXP288_ADC_TS_PIN_CTRL, AXP288_ADC_TS_PIN_ON)) - return -EIO; - - return regmap_write(regmap, AXP20X_ADC_EN1, AXP288_ADC_EN_MASK); -} - static const struct iio_info axp288_adc_iio_info = { .read_raw = _adc_read_raw, .driver_module = THIS_MODULE, @@ -199,7 +169,7 @@ static int axp288_adc_probe(struct platform_device *pdev) * Set ADC to enabled state at all time, including system suspend. * otherwise internal fuel gauge functionality may be affected. */ - ret = axp288_adc_set_state(axp20x->regmap); + ret = regmap_write(info->regmap, AXP20X_ADC_EN1, AXP288_ADC_EN_MASK); if (ret) { dev_err(>dev, "unable to enable ADC device\n"); return ret; -- 2.11.0
[PATCH review for 4.4 14/47] iio: adc: axp288: Drop bogus AXP288_ADC_TS_PIN_CTRL register modifications
From: Hans de Goede [ Upstream commit fa2849e9649b5180ffc4cb3c3b005261c403093a ] For some reason the axp288_adc driver was modifying the AXP288_ADC_TS_PIN_CTRL register, changing bits 0-1 depending on whether the GP_ADC channel or another channel was written. These bits control when a bias current is send to the TS_PIN, the GP_ADC has its own pin and a separate bit in another register to control the bias current. Not only does changing when to enable the TS_PIN bias current (always or only when sampling) when reading the GP_ADC make no sense at all, the code is modifying these bits is writing the entire register, assuming that all the other bits have their default value. So if the firmware has configured a different bias-current for either pin, then that change gets clobbered by the write, likewise if the firmware has set bit 2 to indicate that the battery has no thermal sensor, this will get clobbered by the write. This commit fixes all this, by simply removing all writes to the AXP288_ADC_TS_PIN_CTRL register, they are not needed to read the GP_ADC pin, and can actually be harmful. Signed-off-by: Hans de Goede Acked-by: Chen-Yu Tsai Signed-off-by: Jonathan Cameron Signed-off-by: Sasha Levin --- drivers/iio/adc/axp288_adc.c | 32 +--- 1 file changed, 1 insertion(+), 31 deletions(-) diff --git a/drivers/iio/adc/axp288_adc.c b/drivers/iio/adc/axp288_adc.c index 0c904edd6c00..f684fe31f832 100644 --- a/drivers/iio/adc/axp288_adc.c +++ b/drivers/iio/adc/axp288_adc.c @@ -28,8 +28,6 @@ #include #define AXP288_ADC_EN_MASK 0xF1 -#define AXP288_ADC_TS_PIN_GPADC0xF2 -#define AXP288_ADC_TS_PIN_ON 0xF3 enum axp288_adc_id { AXP288_ADC_TS, @@ -123,16 +121,6 @@ static int axp288_adc_read_channel(int *val, unsigned long address, return IIO_VAL_INT; } -static int axp288_adc_set_ts(struct regmap *regmap, unsigned int mode, - unsigned long address) -{ - /* channels other than GPADC do not need to switch TS pin */ - if (address != AXP288_GP_ADC_H) - return 0; - - return regmap_write(regmap, AXP288_ADC_TS_PIN_CTRL, mode); -} - static int axp288_adc_read_raw(struct iio_dev *indio_dev, struct iio_chan_spec const *chan, int *val, int *val2, long mask) @@ -143,16 +131,7 @@ static int axp288_adc_read_raw(struct iio_dev *indio_dev, mutex_lock(_dev->mlock); switch (mask) { case IIO_CHAN_INFO_RAW: - if (axp288_adc_set_ts(info->regmap, AXP288_ADC_TS_PIN_GPADC, - chan->address)) { - dev_err(_dev->dev, "GPADC mode\n"); - ret = -EINVAL; - break; - } ret = axp288_adc_read_channel(val, chan->address, info->regmap); - if (axp288_adc_set_ts(info->regmap, AXP288_ADC_TS_PIN_ON, - chan->address)) - dev_err(_dev->dev, "TS pin restore\n"); break; default: ret = -EINVAL; @@ -162,15 +141,6 @@ static int axp288_adc_read_raw(struct iio_dev *indio_dev, return ret; } -static int axp288_adc_set_state(struct regmap *regmap) -{ - /* ADC should be always enabled for internal FG to function */ - if (regmap_write(regmap, AXP288_ADC_TS_PIN_CTRL, AXP288_ADC_TS_PIN_ON)) - return -EIO; - - return regmap_write(regmap, AXP20X_ADC_EN1, AXP288_ADC_EN_MASK); -} - static const struct iio_info axp288_adc_iio_info = { .read_raw = _adc_read_raw, .driver_module = THIS_MODULE, @@ -199,7 +169,7 @@ static int axp288_adc_probe(struct platform_device *pdev) * Set ADC to enabled state at all time, including system suspend. * otherwise internal fuel gauge functionality may be affected. */ - ret = axp288_adc_set_state(axp20x->regmap); + ret = regmap_write(info->regmap, AXP20X_ADC_EN1, AXP288_ADC_EN_MASK); if (ret) { dev_err(>dev, "unable to enable ADC device\n"); return ret; -- 2.11.0
[PATCH review for 4.4 25/47] partitions/efi: Fix integer overflow in GPT size calculation
From: Alden Tondettar[ Upstream commit c5082b70adfe8e1ea1cf4a8eff92c9f260e364d2 ] If a GUID Partition Table claims to have more than 2**25 entries, the calculation of the partition table size in alloc_read_gpt_entries() will overflow a 32-bit integer and not enough space will be allocated for the table. Nothing seems to get written out of bounds, but later efi_partition() will read up to 32768 bytes from a 128 byte buffer, possibly OOPSing or exposing information to /proc/partitions and uevents. The problem exists on both 64-bit and 32-bit platforms. Fix the overflow and also print a meaningful debug message if the table size is too large. Signed-off-by: Alden Tondettar Acked-by: Ard Biesheuvel Signed-off-by: Jens Axboe Signed-off-by: Sasha Levin --- block/partitions/efi.c | 17 - 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/block/partitions/efi.c b/block/partitions/efi.c index 26cb624ace05..d26d0d27f5fd 100644 --- a/block/partitions/efi.c +++ b/block/partitions/efi.c @@ -293,7 +293,7 @@ static gpt_entry *alloc_read_gpt_entries(struct parsed_partitions *state, if (!gpt) return NULL; - count = le32_to_cpu(gpt->num_partition_entries) * + count = (size_t)le32_to_cpu(gpt->num_partition_entries) * le32_to_cpu(gpt->sizeof_partition_entry); if (!count) return NULL; @@ -352,7 +352,7 @@ static int is_gpt_valid(struct parsed_partitions *state, u64 lba, gpt_header **gpt, gpt_entry **ptes) { u32 crc, origcrc; - u64 lastlba; + u64 lastlba, pt_size; if (!ptes) return 0; @@ -434,13 +434,20 @@ static int is_gpt_valid(struct parsed_partitions *state, u64 lba, goto fail; } + /* Sanity check partition table size */ + pt_size = (u64)le32_to_cpu((*gpt)->num_partition_entries) * + le32_to_cpu((*gpt)->sizeof_partition_entry); + if (pt_size > KMALLOC_MAX_SIZE) { + pr_debug("GUID Partition Table is too large: %llu > %lu bytes\n", +(unsigned long long)pt_size, KMALLOC_MAX_SIZE); + goto fail; + } + if (!(*ptes = alloc_read_gpt_entries(state, *gpt))) goto fail; /* Check the GUID Partition Entry Array CRC */ - crc = efi_crc32((const unsigned char *) (*ptes), - le32_to_cpu((*gpt)->num_partition_entries) * - le32_to_cpu((*gpt)->sizeof_partition_entry)); + crc = efi_crc32((const unsigned char *) (*ptes), pt_size); if (crc != le32_to_cpu((*gpt)->partition_entry_array_crc32)) { pr_debug("GUID Partitition Entry Array CRC check failed.\n"); -- 2.11.0
[PATCH review for 4.4 25/47] partitions/efi: Fix integer overflow in GPT size calculation
From: Alden Tondettar [ Upstream commit c5082b70adfe8e1ea1cf4a8eff92c9f260e364d2 ] If a GUID Partition Table claims to have more than 2**25 entries, the calculation of the partition table size in alloc_read_gpt_entries() will overflow a 32-bit integer and not enough space will be allocated for the table. Nothing seems to get written out of bounds, but later efi_partition() will read up to 32768 bytes from a 128 byte buffer, possibly OOPSing or exposing information to /proc/partitions and uevents. The problem exists on both 64-bit and 32-bit platforms. Fix the overflow and also print a meaningful debug message if the table size is too large. Signed-off-by: Alden Tondettar Acked-by: Ard Biesheuvel Signed-off-by: Jens Axboe Signed-off-by: Sasha Levin --- block/partitions/efi.c | 17 - 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/block/partitions/efi.c b/block/partitions/efi.c index 26cb624ace05..d26d0d27f5fd 100644 --- a/block/partitions/efi.c +++ b/block/partitions/efi.c @@ -293,7 +293,7 @@ static gpt_entry *alloc_read_gpt_entries(struct parsed_partitions *state, if (!gpt) return NULL; - count = le32_to_cpu(gpt->num_partition_entries) * + count = (size_t)le32_to_cpu(gpt->num_partition_entries) * le32_to_cpu(gpt->sizeof_partition_entry); if (!count) return NULL; @@ -352,7 +352,7 @@ static int is_gpt_valid(struct parsed_partitions *state, u64 lba, gpt_header **gpt, gpt_entry **ptes) { u32 crc, origcrc; - u64 lastlba; + u64 lastlba, pt_size; if (!ptes) return 0; @@ -434,13 +434,20 @@ static int is_gpt_valid(struct parsed_partitions *state, u64 lba, goto fail; } + /* Sanity check partition table size */ + pt_size = (u64)le32_to_cpu((*gpt)->num_partition_entries) * + le32_to_cpu((*gpt)->sizeof_partition_entry); + if (pt_size > KMALLOC_MAX_SIZE) { + pr_debug("GUID Partition Table is too large: %llu > %lu bytes\n", +(unsigned long long)pt_size, KMALLOC_MAX_SIZE); + goto fail; + } + if (!(*ptes = alloc_read_gpt_entries(state, *gpt))) goto fail; /* Check the GUID Partition Entry Array CRC */ - crc = efi_crc32((const unsigned char *) (*ptes), - le32_to_cpu((*gpt)->num_partition_entries) * - le32_to_cpu((*gpt)->sizeof_partition_entry)); + crc = efi_crc32((const unsigned char *) (*ptes), pt_size); if (crc != le32_to_cpu((*gpt)->partition_entry_array_crc32)) { pr_debug("GUID Partitition Entry Array CRC check failed.\n"); -- 2.11.0
[PATCH review for 4.4 01/47] drm_fourcc: Fix DRM_FORMAT_MOD_LINEAR #define
From: "Kristian H. Kristensen"[ Upstream commit af913418261d6d3e7a29f06cf35f04610ead667c ] We need to define DRM_FORMAT_MOD_VENDOR_NONE for the fourcc_mod_code() macro to work correctly. Signed-off-by: Kristian H. Kristensen Signed-off-by: Daniel Vetter Link: http://patchwork.freedesktop.org/patch/msgid/1481657272-25975-1-git-send-email-hoegsb...@google.com Signed-off-by: Sasha Levin --- include/uapi/drm/drm_fourcc.h | 1 + 1 file changed, 1 insertion(+) diff --git a/include/uapi/drm/drm_fourcc.h b/include/uapi/drm/drm_fourcc.h index 0b69a7753558..f28f79966e9e 100644 --- a/include/uapi/drm/drm_fourcc.h +++ b/include/uapi/drm/drm_fourcc.h @@ -150,6 +150,7 @@ /* Vendor Ids: */ #define DRM_FORMAT_MOD_NONE 0 +#define DRM_FORMAT_MOD_VENDOR_NONE0 #define DRM_FORMAT_MOD_VENDOR_INTEL 0x01 #define DRM_FORMAT_MOD_VENDOR_AMD 0x02 #define DRM_FORMAT_MOD_VENDOR_NV 0x03 -- 2.11.0
[PATCH review for 4.4 01/47] drm_fourcc: Fix DRM_FORMAT_MOD_LINEAR #define
From: "Kristian H. Kristensen" [ Upstream commit af913418261d6d3e7a29f06cf35f04610ead667c ] We need to define DRM_FORMAT_MOD_VENDOR_NONE for the fourcc_mod_code() macro to work correctly. Signed-off-by: Kristian H. Kristensen Signed-off-by: Daniel Vetter Link: http://patchwork.freedesktop.org/patch/msgid/1481657272-25975-1-git-send-email-hoegsb...@google.com Signed-off-by: Sasha Levin --- include/uapi/drm/drm_fourcc.h | 1 + 1 file changed, 1 insertion(+) diff --git a/include/uapi/drm/drm_fourcc.h b/include/uapi/drm/drm_fourcc.h index 0b69a7753558..f28f79966e9e 100644 --- a/include/uapi/drm/drm_fourcc.h +++ b/include/uapi/drm/drm_fourcc.h @@ -150,6 +150,7 @@ /* Vendor Ids: */ #define DRM_FORMAT_MOD_NONE 0 +#define DRM_FORMAT_MOD_VENDOR_NONE0 #define DRM_FORMAT_MOD_VENDOR_INTEL 0x01 #define DRM_FORMAT_MOD_VENDOR_AMD 0x02 #define DRM_FORMAT_MOD_VENDOR_NV 0x03 -- 2.11.0
[PATCH review for 4.4 02/47] drm: bridge: add DT bindings for TI ths8135
From: Bartosz Golaszewski[ Upstream commit 2e644be30fcc08c736f66b60f4898d274d4873ab ] THS8135 is a configurable video DAC. Add DT bindings for this chip. Signed-off-by: Bartosz Golaszewski Reviewed-by: Laurent Pinchart Acked-by: Rob Herring Signed-off-by: Archit Taneja Link: http://patchwork.freedesktop.org/patch/msgid/1481623759-12786-3-git-send-email-bgolaszew...@baylibre.com Signed-off-by: Sasha Levin --- .../bindings/display/bridge/ti,ths8135.txt | 46 ++ 1 file changed, 46 insertions(+) create mode 100644 Documentation/devicetree/bindings/display/bridge/ti,ths8135.txt diff --git a/Documentation/devicetree/bindings/display/bridge/ti,ths8135.txt b/Documentation/devicetree/bindings/display/bridge/ti,ths8135.txt new file mode 100644 index ..6ec1a880ac18 --- /dev/null +++ b/Documentation/devicetree/bindings/display/bridge/ti,ths8135.txt @@ -0,0 +1,46 @@ +THS8135 Video DAC +- + +This is the binding for Texas Instruments THS8135 Video DAC bridge. + +Required properties: + +- compatible: Must be "ti,ths8135" + +Required nodes: + +This device has two video ports. Their connections are modelled using the OF +graph bindings specified in Documentation/devicetree/bindings/graph.txt. + +- Video port 0 for RGB input +- Video port 1 for VGA output + +Example +--- + +vga-bridge { + compatible = "ti,ths8135"; + #address-cells = <1>; + #size-cells = <0>; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + + vga_bridge_in: endpoint { + remote-endpoint = <_out_vga>; + }; + }; + + port@1 { + reg = <1>; + + vga_bridge_out: endpoint { + remote-endpoint = <_con_in>; + }; + }; + }; +}; -- 2.11.0
[PATCH review for 4.4 02/47] drm: bridge: add DT bindings for TI ths8135
From: Bartosz Golaszewski [ Upstream commit 2e644be30fcc08c736f66b60f4898d274d4873ab ] THS8135 is a configurable video DAC. Add DT bindings for this chip. Signed-off-by: Bartosz Golaszewski Reviewed-by: Laurent Pinchart Acked-by: Rob Herring Signed-off-by: Archit Taneja Link: http://patchwork.freedesktop.org/patch/msgid/1481623759-12786-3-git-send-email-bgolaszew...@baylibre.com Signed-off-by: Sasha Levin --- .../bindings/display/bridge/ti,ths8135.txt | 46 ++ 1 file changed, 46 insertions(+) create mode 100644 Documentation/devicetree/bindings/display/bridge/ti,ths8135.txt diff --git a/Documentation/devicetree/bindings/display/bridge/ti,ths8135.txt b/Documentation/devicetree/bindings/display/bridge/ti,ths8135.txt new file mode 100644 index ..6ec1a880ac18 --- /dev/null +++ b/Documentation/devicetree/bindings/display/bridge/ti,ths8135.txt @@ -0,0 +1,46 @@ +THS8135 Video DAC +- + +This is the binding for Texas Instruments THS8135 Video DAC bridge. + +Required properties: + +- compatible: Must be "ti,ths8135" + +Required nodes: + +This device has two video ports. Their connections are modelled using the OF +graph bindings specified in Documentation/devicetree/bindings/graph.txt. + +- Video port 0 for RGB input +- Video port 1 for VGA output + +Example +--- + +vga-bridge { + compatible = "ti,ths8135"; + #address-cells = <1>; + #size-cells = <0>; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + + vga_bridge_in: endpoint { + remote-endpoint = <_out_vga>; + }; + }; + + port@1 { + reg = <1>; + + vga_bridge_out: endpoint { + remote-endpoint = <_con_in>; + }; + }; + }; +}; -- 2.11.0
[PATCH review for 4.4 28/47] usb: chipidea: vbus event may exist before starting gadget
From: Peter Chen[ Upstream commit c3b674a04b8ab62a1d35e86714d466af0a0ecc18 ] At some situations, the vbus may already be there before starting gadget. So we need to check vbus event after switching to gadget in order to handle missing vbus event. The typical use cases are plugging vbus cable before driver load or the vbus has already been there after stopping host but before starting gadget. Signed-off-by: Peter Chen Tested-by: Stephen Boyd Reported-by: Stephen Boyd Signed-off-by: Sasha Levin --- drivers/usb/chipidea/otg.c | 17 - 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/drivers/usb/chipidea/otg.c b/drivers/usb/chipidea/otg.c index 0cf149e8..f36a1ac3bfbd 100644 --- a/drivers/usb/chipidea/otg.c +++ b/drivers/usb/chipidea/otg.c @@ -134,9 +134,9 @@ void ci_handle_vbus_change(struct ci_hdrc *ci) if (!ci->is_otg) return; - if (hw_read_otgsc(ci, OTGSC_BSV)) + if (hw_read_otgsc(ci, OTGSC_BSV) && !ci->vbus_active) usb_gadget_vbus_connect(>gadget); - else + else if (!hw_read_otgsc(ci, OTGSC_BSV) && ci->vbus_active) usb_gadget_vbus_disconnect(>gadget); } @@ -175,14 +175,21 @@ static void ci_handle_id_switch(struct ci_hdrc *ci) ci_role_stop(ci); - if (role == CI_ROLE_GADGET) + if (role == CI_ROLE_GADGET && + IS_ERR(ci->platdata->vbus_extcon.edev)) /* -* wait vbus lower than OTGSC_BSV before connecting -* to host +* Wait vbus lower than OTGSC_BSV before connecting +* to host. If connecting status is from an external +* connector instead of register, we don't need to +* care vbus on the board, since it will not affect +* external connector status. */ hw_wait_vbus_lower_bsv(ci); ci_role_start(ci, role); + /* vbus change may have already occurred */ + if (role == CI_ROLE_GADGET) + ci_handle_vbus_change(ci); } } /** -- 2.11.0
[PATCH review for 4.4 28/47] usb: chipidea: vbus event may exist before starting gadget
From: Peter Chen [ Upstream commit c3b674a04b8ab62a1d35e86714d466af0a0ecc18 ] At some situations, the vbus may already be there before starting gadget. So we need to check vbus event after switching to gadget in order to handle missing vbus event. The typical use cases are plugging vbus cable before driver load or the vbus has already been there after stopping host but before starting gadget. Signed-off-by: Peter Chen Tested-by: Stephen Boyd Reported-by: Stephen Boyd Signed-off-by: Sasha Levin --- drivers/usb/chipidea/otg.c | 17 - 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/drivers/usb/chipidea/otg.c b/drivers/usb/chipidea/otg.c index 0cf149e8..f36a1ac3bfbd 100644 --- a/drivers/usb/chipidea/otg.c +++ b/drivers/usb/chipidea/otg.c @@ -134,9 +134,9 @@ void ci_handle_vbus_change(struct ci_hdrc *ci) if (!ci->is_otg) return; - if (hw_read_otgsc(ci, OTGSC_BSV)) + if (hw_read_otgsc(ci, OTGSC_BSV) && !ci->vbus_active) usb_gadget_vbus_connect(>gadget); - else + else if (!hw_read_otgsc(ci, OTGSC_BSV) && ci->vbus_active) usb_gadget_vbus_disconnect(>gadget); } @@ -175,14 +175,21 @@ static void ci_handle_id_switch(struct ci_hdrc *ci) ci_role_stop(ci); - if (role == CI_ROLE_GADGET) + if (role == CI_ROLE_GADGET && + IS_ERR(ci->platdata->vbus_extcon.edev)) /* -* wait vbus lower than OTGSC_BSV before connecting -* to host +* Wait vbus lower than OTGSC_BSV before connecting +* to host. If connecting status is from an external +* connector instead of register, we don't need to +* care vbus on the board, since it will not affect +* external connector status. */ hw_wait_vbus_lower_bsv(ci); ci_role_start(ci, role); + /* vbus change may have already occurred */ + if (role == CI_ROLE_GADGET) + ci_handle_vbus_change(ci); } } /** -- 2.11.0
[PATCH review for 4.4 13/47] hwmon: (gl520sm) Fix overflows and crash seen when writing into limit attributes
From: Guenter Roeck[ Upstream commit 87cdfa9d60f4f40e6d71b04b10b36d9df3c89282 ] Writes into limit attributes can overflow due to multplications and additions with unbound input values. Writing into fan limit attributes can result in a crash with a division by zero if very large values are written and the fan divider is larger than 1. Signed-off-by: Guenter Roeck Signed-off-by: Sasha Levin --- drivers/hwmon/gl520sm.c | 25 - 1 file changed, 16 insertions(+), 9 deletions(-) diff --git a/drivers/hwmon/gl520sm.c b/drivers/hwmon/gl520sm.c index dee93ec87d02..84e0994aafdd 100644 --- a/drivers/hwmon/gl520sm.c +++ b/drivers/hwmon/gl520sm.c @@ -208,11 +208,13 @@ static ssize_t get_cpu_vid(struct device *dev, struct device_attribute *attr, } static DEVICE_ATTR(cpu0_vid, S_IRUGO, get_cpu_vid, NULL); -#define VDD_FROM_REG(val) (((val) * 95 + 2) / 4) -#define VDD_TO_REG(val) clamp_valval) * 4 + 47) / 95), 0, 255) +#define VDD_FROM_REG(val) DIV_ROUND_CLOSEST((val) * 95, 4) +#define VDD_CLAMP(val) clamp_val(val, 0, 255 * 95 / 4) +#define VDD_TO_REG(val)DIV_ROUND_CLOSEST(VDD_CLAMP(val) * 4, 95) -#define IN_FROM_REG(val) ((val) * 19) -#define IN_TO_REG(val) clamp_valval) + 9) / 19), 0, 255) +#define IN_FROM_REG(val) ((val) * 19) +#define IN_CLAMP(val) clamp_val(val, 0, 255 * 19) +#define IN_TO_REG(val) DIV_ROUND_CLOSEST(IN_CLAMP(val), 19) static ssize_t get_in_input(struct device *dev, struct device_attribute *attr, char *buf) @@ -349,8 +351,13 @@ static SENSOR_DEVICE_ATTR(in4_max, S_IRUGO | S_IWUSR, #define DIV_FROM_REG(val) (1 << (val)) #define FAN_FROM_REG(val, div) ((val) == 0 ? 0 : (48 / ((val) << (div -#define FAN_TO_REG(val, div) ((val) <= 0 ? 0 : \ - clamp_val((48 + ((val) << ((div)-1))) / ((val) << (div)), 1, 255)) + +#define FAN_BASE(div) (48 >> (div)) +#define FAN_CLAMP(val, div)clamp_val(val, FAN_BASE(div) / 255, \ + FAN_BASE(div)) +#define FAN_TO_REG(val, div) ((val) == 0 ? 0 : \ +DIV_ROUND_CLOSEST(48, \ + FAN_CLAMP(val, div) << (div))) static ssize_t get_fan_input(struct device *dev, struct device_attribute *attr, char *buf) @@ -513,9 +520,9 @@ static SENSOR_DEVICE_ATTR(fan2_div, S_IRUGO | S_IWUSR, static DEVICE_ATTR(fan1_off, S_IRUGO | S_IWUSR, get_fan_off, set_fan_off); -#define TEMP_FROM_REG(val) (((val) - 130) * 1000) -#define TEMP_TO_REG(val) clamp_val(val) < 0 ? \ - (val) - 500 : (val) + 500) / 1000) + 130), 0, 255) +#define TEMP_FROM_REG(val) (((val) - 130) * 1000) +#define TEMP_CLAMP(val)clamp_val(val, -13, 125000) +#define TEMP_TO_REG(val) (DIV_ROUND_CLOSEST(TEMP_CLAMP(val), 1000) + 130) static ssize_t get_temp_input(struct device *dev, struct device_attribute *attr, char *buf) -- 2.11.0
[PATCH review for 4.4 13/47] hwmon: (gl520sm) Fix overflows and crash seen when writing into limit attributes
From: Guenter Roeck [ Upstream commit 87cdfa9d60f4f40e6d71b04b10b36d9df3c89282 ] Writes into limit attributes can overflow due to multplications and additions with unbound input values. Writing into fan limit attributes can result in a crash with a division by zero if very large values are written and the fan divider is larger than 1. Signed-off-by: Guenter Roeck Signed-off-by: Sasha Levin --- drivers/hwmon/gl520sm.c | 25 - 1 file changed, 16 insertions(+), 9 deletions(-) diff --git a/drivers/hwmon/gl520sm.c b/drivers/hwmon/gl520sm.c index dee93ec87d02..84e0994aafdd 100644 --- a/drivers/hwmon/gl520sm.c +++ b/drivers/hwmon/gl520sm.c @@ -208,11 +208,13 @@ static ssize_t get_cpu_vid(struct device *dev, struct device_attribute *attr, } static DEVICE_ATTR(cpu0_vid, S_IRUGO, get_cpu_vid, NULL); -#define VDD_FROM_REG(val) (((val) * 95 + 2) / 4) -#define VDD_TO_REG(val) clamp_valval) * 4 + 47) / 95), 0, 255) +#define VDD_FROM_REG(val) DIV_ROUND_CLOSEST((val) * 95, 4) +#define VDD_CLAMP(val) clamp_val(val, 0, 255 * 95 / 4) +#define VDD_TO_REG(val)DIV_ROUND_CLOSEST(VDD_CLAMP(val) * 4, 95) -#define IN_FROM_REG(val) ((val) * 19) -#define IN_TO_REG(val) clamp_valval) + 9) / 19), 0, 255) +#define IN_FROM_REG(val) ((val) * 19) +#define IN_CLAMP(val) clamp_val(val, 0, 255 * 19) +#define IN_TO_REG(val) DIV_ROUND_CLOSEST(IN_CLAMP(val), 19) static ssize_t get_in_input(struct device *dev, struct device_attribute *attr, char *buf) @@ -349,8 +351,13 @@ static SENSOR_DEVICE_ATTR(in4_max, S_IRUGO | S_IWUSR, #define DIV_FROM_REG(val) (1 << (val)) #define FAN_FROM_REG(val, div) ((val) == 0 ? 0 : (48 / ((val) << (div -#define FAN_TO_REG(val, div) ((val) <= 0 ? 0 : \ - clamp_val((48 + ((val) << ((div)-1))) / ((val) << (div)), 1, 255)) + +#define FAN_BASE(div) (48 >> (div)) +#define FAN_CLAMP(val, div)clamp_val(val, FAN_BASE(div) / 255, \ + FAN_BASE(div)) +#define FAN_TO_REG(val, div) ((val) == 0 ? 0 : \ +DIV_ROUND_CLOSEST(48, \ + FAN_CLAMP(val, div) << (div))) static ssize_t get_fan_input(struct device *dev, struct device_attribute *attr, char *buf) @@ -513,9 +520,9 @@ static SENSOR_DEVICE_ATTR(fan2_div, S_IRUGO | S_IWUSR, static DEVICE_ATTR(fan1_off, S_IRUGO | S_IWUSR, get_fan_off, set_fan_off); -#define TEMP_FROM_REG(val) (((val) - 130) * 1000) -#define TEMP_TO_REG(val) clamp_val(val) < 0 ? \ - (val) - 500 : (val) + 500) / 1000) + 130), 0, 255) +#define TEMP_FROM_REG(val) (((val) - 130) * 1000) +#define TEMP_CLAMP(val)clamp_val(val, -13, 125000) +#define TEMP_TO_REG(val) (DIV_ROUND_CLOSEST(TEMP_CLAMP(val), 1000) + 130) static ssize_t get_temp_input(struct device *dev, struct device_attribute *attr, char *buf) -- 2.11.0
[PATCH review for 4.4 12/47] clk: wm831x: fix usleep_range with bad range
From: Nicholas Mc Guire[ Upstream commit ed784c532a3d0959db488f40a96c5127f63d42dc ] The delay here is not in atomic context and does not seem critical with respect to precision, but usleep_range(min,max) with min==max results in giving the timer subsystem no room to optimize uncritical delays. Fix this by setting the range to 2000,3000 us. Fixes: commit f05259a6ffa4 ("clk: wm831x: Add initial WM831x clock driver") Signed-off-by: Nicholas Mc Guire Acked-by: Charles Keepax Signed-off-by: Stephen Boyd Signed-off-by: Sasha Levin --- drivers/clk/clk-wm831x.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/clk/clk-wm831x.c b/drivers/clk/clk-wm831x.c index 763aed2de893..dfedcf5bc429 100644 --- a/drivers/clk/clk-wm831x.c +++ b/drivers/clk/clk-wm831x.c @@ -101,7 +101,8 @@ static int wm831x_fll_prepare(struct clk_hw *hw) if (ret != 0) dev_crit(wm831x->dev, "Failed to enable FLL: %d\n", ret); - usleep_range(2000, 2000); + /* wait 2-3 ms for new frequency taking effect */ + usleep_range(2000, 3000); return ret; } -- 2.11.0
[PATCH review for 4.4 12/47] clk: wm831x: fix usleep_range with bad range
From: Nicholas Mc Guire [ Upstream commit ed784c532a3d0959db488f40a96c5127f63d42dc ] The delay here is not in atomic context and does not seem critical with respect to precision, but usleep_range(min,max) with min==max results in giving the timer subsystem no room to optimize uncritical delays. Fix this by setting the range to 2000,3000 us. Fixes: commit f05259a6ffa4 ("clk: wm831x: Add initial WM831x clock driver") Signed-off-by: Nicholas Mc Guire Acked-by: Charles Keepax Signed-off-by: Stephen Boyd Signed-off-by: Sasha Levin --- drivers/clk/clk-wm831x.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/clk/clk-wm831x.c b/drivers/clk/clk-wm831x.c index 763aed2de893..dfedcf5bc429 100644 --- a/drivers/clk/clk-wm831x.c +++ b/drivers/clk/clk-wm831x.c @@ -101,7 +101,8 @@ static int wm831x_fll_prepare(struct clk_hw *hw) if (ret != 0) dev_crit(wm831x->dev, "Failed to enable FLL: %d\n", ret); - usleep_range(2000, 2000); + /* wait 2-3 ms for new frequency taking effect */ + usleep_range(2000, 3000); return ret; } -- 2.11.0
[PATCH review for 4.4 08/47] MIPS: ralink: Fix incorrect assignment on ralink_soc
From: Colin Ian King[ Upstream commit 08d90c81b714482dceb5323d14f6617bcf55ee61 ] ralink_soc sould be assigned to RT3883_SOC, replace incorrect comparision with assignment. Signed-off-by: Colin Ian King Fixes: 418d29c87061 ("MIPS: ralink: Unify SoC id handling") Cc: John Crispin Cc: linux-m...@linux-mips.org Cc: linux-kernel@vger.kernel.org Patchwork: https://patchwork.linux-mips.org/patch/14903/ Signed-off-by: Ralf Baechle Signed-off-by: Sasha Levin --- arch/mips/ralink/rt3883.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/mips/ralink/rt3883.c b/arch/mips/ralink/rt3883.c index 3c575093f8f1..f2a6e1b8cce0 100644 --- a/arch/mips/ralink/rt3883.c +++ b/arch/mips/ralink/rt3883.c @@ -144,5 +144,5 @@ void prom_soc_init(struct ralink_soc_info *soc_info) rt2880_pinmux_data = rt3883_pinmux_data; - ralink_soc == RT3883_SOC; + ralink_soc = RT3883_SOC; } -- 2.11.0
[PATCH review for 4.4 08/47] MIPS: ralink: Fix incorrect assignment on ralink_soc
From: Colin Ian King [ Upstream commit 08d90c81b714482dceb5323d14f6617bcf55ee61 ] ralink_soc sould be assigned to RT3883_SOC, replace incorrect comparision with assignment. Signed-off-by: Colin Ian King Fixes: 418d29c87061 ("MIPS: ralink: Unify SoC id handling") Cc: John Crispin Cc: linux-m...@linux-mips.org Cc: linux-kernel@vger.kernel.org Patchwork: https://patchwork.linux-mips.org/patch/14903/ Signed-off-by: Ralf Baechle Signed-off-by: Sasha Levin --- arch/mips/ralink/rt3883.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/mips/ralink/rt3883.c b/arch/mips/ralink/rt3883.c index 3c575093f8f1..f2a6e1b8cce0 100644 --- a/arch/mips/ralink/rt3883.c +++ b/arch/mips/ralink/rt3883.c @@ -144,5 +144,5 @@ void prom_soc_init(struct ralink_soc_info *soc_info) rt2880_pinmux_data = rt3883_pinmux_data; - ralink_soc == RT3883_SOC; + ralink_soc = RT3883_SOC; } -- 2.11.0
[PATCH review for 4.4 11/47] sh_eth: use correct name for ECMR_MPDE bit
From: Niklas Söderlund[ Upstream commit 6dcf45e514974a1ff10755015b5e06746a033e5f ] This bit was wrongly named due to a typo, Sergei checked the SH7734/63 manuals and this bit should be named MPDE. Suggested-by: Sergei Shtylyov Signed-off-by: Niklas Söderlund Signed-off-by: David S. Miller Signed-off-by: Sasha Levin --- drivers/net/ethernet/renesas/sh_eth.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/ethernet/renesas/sh_eth.h b/drivers/net/ethernet/renesas/sh_eth.h index 72fcfc924589..0d18be0fed8e 100644 --- a/drivers/net/ethernet/renesas/sh_eth.h +++ b/drivers/net/ethernet/renesas/sh_eth.h @@ -339,7 +339,7 @@ enum FELIC_MODE_BIT { ECMR_DPAD = 0x0020, ECMR_RZPF = 0x0010, ECMR_ZPF = 0x0008, ECMR_PFR = 0x0004, ECMR_RXF = 0x0002, ECMR_TXF = 0x0001, ECMR_MCT = 0x2000, ECMR_PRCEF = 0x1000, - ECMR_PMDE = 0x0200, ECMR_RE = 0x0040, ECMR_TE = 0x0020, + ECMR_MPDE = 0x0200, ECMR_RE = 0x0040, ECMR_TE = 0x0020, ECMR_RTM = 0x0010, ECMR_ILB = 0x0008, ECMR_ELB = 0x0004, ECMR_DM = 0x0002, ECMR_PRM = 0x0001, }; -- 2.11.0
[PATCH review for 4.4 11/47] sh_eth: use correct name for ECMR_MPDE bit
From: Niklas Söderlund [ Upstream commit 6dcf45e514974a1ff10755015b5e06746a033e5f ] This bit was wrongly named due to a typo, Sergei checked the SH7734/63 manuals and this bit should be named MPDE. Suggested-by: Sergei Shtylyov Signed-off-by: Niklas Söderlund Signed-off-by: David S. Miller Signed-off-by: Sasha Levin --- drivers/net/ethernet/renesas/sh_eth.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/ethernet/renesas/sh_eth.h b/drivers/net/ethernet/renesas/sh_eth.h index 72fcfc924589..0d18be0fed8e 100644 --- a/drivers/net/ethernet/renesas/sh_eth.h +++ b/drivers/net/ethernet/renesas/sh_eth.h @@ -339,7 +339,7 @@ enum FELIC_MODE_BIT { ECMR_DPAD = 0x0020, ECMR_RZPF = 0x0010, ECMR_ZPF = 0x0008, ECMR_PFR = 0x0004, ECMR_RXF = 0x0002, ECMR_TXF = 0x0001, ECMR_MCT = 0x2000, ECMR_PRCEF = 0x1000, - ECMR_PMDE = 0x0200, ECMR_RE = 0x0040, ECMR_TE = 0x0020, + ECMR_MPDE = 0x0200, ECMR_RE = 0x0040, ECMR_TE = 0x0020, ECMR_RTM = 0x0010, ECMR_ILB = 0x0008, ECMR_ELB = 0x0004, ECMR_DM = 0x0002, ECMR_PRM = 0x0001, }; -- 2.11.0
[PATCH review for 4.4 19/47] IB/ipoib: rtnl_unlock can not come after free_netdev
From: Feras Daoud[ Upstream commit 89a3987ab7a923c047c6dec008e60ad6f41fac22 ] The ipoib_vlan_add function calls rtnl_unlock after free_netdev, rtnl_unlock not only releases the lock, but also calls netdev_run_todo. The latter function browses the net_todo_list array and completes the unregistration of all its net_device instances. If we call free_netdev before rtnl_unlock, then netdev_run_todo call over the freed device causes panic. To fix, move rtnl_unlock call before free_netdev call. Fixes: 9baa0b036410 ("IB/ipoib: Add rtnl_link_ops support") Cc: Or Gerlitz Signed-off-by: Feras Daoud Signed-off-by: Erez Shitrit Reviewed-by: Yuval Shaia Signed-off-by: Leon Romanovsky Signed-off-by: Doug Ledford Signed-off-by: Sasha Levin --- drivers/infiniband/ulp/ipoib/ipoib_vlan.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/infiniband/ulp/ipoib/ipoib_vlan.c b/drivers/infiniband/ulp/ipoib/ipoib_vlan.c index 3a647fd50f09..9b47a437d6c9 100644 --- a/drivers/infiniband/ulp/ipoib/ipoib_vlan.c +++ b/drivers/infiniband/ulp/ipoib/ipoib_vlan.c @@ -160,11 +160,11 @@ int ipoib_vlan_add(struct net_device *pdev, unsigned short pkey) out: up_write(>vlan_rwsem); + rtnl_unlock(); + if (result) free_netdev(priv->dev); - rtnl_unlock(); - return result; } -- 2.11.0
[PATCH review for 4.4 15/47] iio: adc: hx711: Add DT binding for avia,hx711
From: Andreas Klinger[ Upstream commit ff1293f67734da68e23fecb6ecdae7112b8c43f9 ] Add DT bindings for avia,hx711 Add vendor avia to vendor list Signed-off-by: Andreas Klinger Acked-by: Rob Herring Signed-off-by: Jonathan Cameron Signed-off-by: Sasha Levin --- .../devicetree/bindings/iio/adc/avia-hx711.txt | 18 ++ Documentation/devicetree/bindings/vendor-prefixes.txt | 1 + 2 files changed, 19 insertions(+) create mode 100644 Documentation/devicetree/bindings/iio/adc/avia-hx711.txt diff --git a/Documentation/devicetree/bindings/iio/adc/avia-hx711.txt b/Documentation/devicetree/bindings/iio/adc/avia-hx711.txt new file mode 100644 index ..b3629405f568 --- /dev/null +++ b/Documentation/devicetree/bindings/iio/adc/avia-hx711.txt @@ -0,0 +1,18 @@ +* AVIA HX711 ADC chip for weight cells + Bit-banging driver + +Required properties: + - compatible: Should be "avia,hx711" + - sck-gpios: Definition of the GPIO for the clock + - dout-gpios: Definition of the GPIO for data-out + See Documentation/devicetree/bindings/gpio/gpio.txt + - avdd-supply:Definition of the regulator used as analog supply + +Example: +weight@0 { + compatible = "avia,hx711"; + sck-gpios = < 10 GPIO_ACTIVE_HIGH>; + dout-gpios = < 7 GPIO_ACTIVE_HIGH>; + avdd-suppy = <>; +}; + diff --git a/Documentation/devicetree/bindings/vendor-prefixes.txt b/Documentation/devicetree/bindings/vendor-prefixes.txt index 55df1d444e9f..98dc17507a84 100644 --- a/Documentation/devicetree/bindings/vendor-prefixes.txt +++ b/Documentation/devicetree/bindings/vendor-prefixes.txt @@ -31,6 +31,7 @@ asahi-kasei Asahi Kasei Corp. atmel Atmel Corporation auoAU Optronics Corporation avago Avago Technologies +avia avia semiconductor avic Shanghai AVIC Optoelectronics Co., Ltd. axis Axis Communications AB bosch Bosch Sensortec GmbH -- 2.11.0
[PATCH review for 4.4 19/47] IB/ipoib: rtnl_unlock can not come after free_netdev
From: Feras Daoud [ Upstream commit 89a3987ab7a923c047c6dec008e60ad6f41fac22 ] The ipoib_vlan_add function calls rtnl_unlock after free_netdev, rtnl_unlock not only releases the lock, but also calls netdev_run_todo. The latter function browses the net_todo_list array and completes the unregistration of all its net_device instances. If we call free_netdev before rtnl_unlock, then netdev_run_todo call over the freed device causes panic. To fix, move rtnl_unlock call before free_netdev call. Fixes: 9baa0b036410 ("IB/ipoib: Add rtnl_link_ops support") Cc: Or Gerlitz Signed-off-by: Feras Daoud Signed-off-by: Erez Shitrit Reviewed-by: Yuval Shaia Signed-off-by: Leon Romanovsky Signed-off-by: Doug Ledford Signed-off-by: Sasha Levin --- drivers/infiniband/ulp/ipoib/ipoib_vlan.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/infiniband/ulp/ipoib/ipoib_vlan.c b/drivers/infiniband/ulp/ipoib/ipoib_vlan.c index 3a647fd50f09..9b47a437d6c9 100644 --- a/drivers/infiniband/ulp/ipoib/ipoib_vlan.c +++ b/drivers/infiniband/ulp/ipoib/ipoib_vlan.c @@ -160,11 +160,11 @@ int ipoib_vlan_add(struct net_device *pdev, unsigned short pkey) out: up_write(>vlan_rwsem); + rtnl_unlock(); + if (result) free_netdev(priv->dev); - rtnl_unlock(); - return result; } -- 2.11.0
[PATCH review for 4.4 15/47] iio: adc: hx711: Add DT binding for avia,hx711
From: Andreas Klinger [ Upstream commit ff1293f67734da68e23fecb6ecdae7112b8c43f9 ] Add DT bindings for avia,hx711 Add vendor avia to vendor list Signed-off-by: Andreas Klinger Acked-by: Rob Herring Signed-off-by: Jonathan Cameron Signed-off-by: Sasha Levin --- .../devicetree/bindings/iio/adc/avia-hx711.txt | 18 ++ Documentation/devicetree/bindings/vendor-prefixes.txt | 1 + 2 files changed, 19 insertions(+) create mode 100644 Documentation/devicetree/bindings/iio/adc/avia-hx711.txt diff --git a/Documentation/devicetree/bindings/iio/adc/avia-hx711.txt b/Documentation/devicetree/bindings/iio/adc/avia-hx711.txt new file mode 100644 index ..b3629405f568 --- /dev/null +++ b/Documentation/devicetree/bindings/iio/adc/avia-hx711.txt @@ -0,0 +1,18 @@ +* AVIA HX711 ADC chip for weight cells + Bit-banging driver + +Required properties: + - compatible: Should be "avia,hx711" + - sck-gpios: Definition of the GPIO for the clock + - dout-gpios: Definition of the GPIO for data-out + See Documentation/devicetree/bindings/gpio/gpio.txt + - avdd-supply:Definition of the regulator used as analog supply + +Example: +weight@0 { + compatible = "avia,hx711"; + sck-gpios = < 10 GPIO_ACTIVE_HIGH>; + dout-gpios = < 7 GPIO_ACTIVE_HIGH>; + avdd-suppy = <>; +}; + diff --git a/Documentation/devicetree/bindings/vendor-prefixes.txt b/Documentation/devicetree/bindings/vendor-prefixes.txt index 55df1d444e9f..98dc17507a84 100644 --- a/Documentation/devicetree/bindings/vendor-prefixes.txt +++ b/Documentation/devicetree/bindings/vendor-prefixes.txt @@ -31,6 +31,7 @@ asahi-kasei Asahi Kasei Corp. atmel Atmel Corporation auoAU Optronics Corporation avago Avago Technologies +avia avia semiconductor avic Shanghai AVIC Optoelectronics Co., Ltd. axis Axis Communications AB bosch Bosch Sensortec GmbH -- 2.11.0
[PATCH review for 4.4 05/47] ARM: dts: r8a7790: Use R-Car Gen 2 fallback binding for msiof nodes
From: Simon Horman[ Upstream commit 654450baf2afba86cf328e1849ccac61ec4630af ] Use recently added R-Car Gen 2 fallback binding for msiof nodes in DT for r8a7790 SoC. This has no run-time effect for the current driver as the initialisation sequence is the same for the SoC-specific binding for r8a7790 and the fallback binding for R-Car Gen 2. Signed-off-by: Simon Horman Reviewed-by: Geert Uytterhoeven Signed-off-by: Sasha Levin --- arch/arm/boot/dts/r8a7790.dtsi | 12 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/arch/arm/boot/dts/r8a7790.dtsi b/arch/arm/boot/dts/r8a7790.dtsi index e07ae5d45e19..7b39d8fae61e 100644 --- a/arch/arm/boot/dts/r8a7790.dtsi +++ b/arch/arm/boot/dts/r8a7790.dtsi @@ -1409,7 +1409,8 @@ }; msiof0: spi@e6e2 { - compatible = "renesas,msiof-r8a7790"; + compatible = "renesas,msiof-r8a7790", +"renesas,rcar-gen2-msiof"; reg = <0 0xe6e2 0 0x0064>; interrupts = <0 156 IRQ_TYPE_LEVEL_HIGH>; clocks = <_clks R8A7790_CLK_MSIOF0>; @@ -1422,7 +1423,8 @@ }; msiof1: spi@e6e1 { - compatible = "renesas,msiof-r8a7790"; + compatible = "renesas,msiof-r8a7790", +"renesas,rcar-gen2-msiof"; reg = <0 0xe6e1 0 0x0064>; interrupts = <0 157 IRQ_TYPE_LEVEL_HIGH>; clocks = <_clks R8A7790_CLK_MSIOF1>; @@ -1435,7 +1437,8 @@ }; msiof2: spi@e6e0 { - compatible = "renesas,msiof-r8a7790"; + compatible = "renesas,msiof-r8a7790", +"renesas,rcar-gen2-msiof"; reg = <0 0xe6e0 0 0x0064>; interrupts = <0 158 IRQ_TYPE_LEVEL_HIGH>; clocks = <_clks R8A7790_CLK_MSIOF2>; @@ -1448,7 +1451,8 @@ }; msiof3: spi@e6c9 { - compatible = "renesas,msiof-r8a7790"; + compatible = "renesas,msiof-r8a7790", +"renesas,rcar-gen2-msiof"; reg = <0 0xe6c9 0 0x0064>; interrupts = <0 159 IRQ_TYPE_LEVEL_HIGH>; clocks = <_clks R8A7790_CLK_MSIOF3>; -- 2.11.0
[PATCH review for 4.4 05/47] ARM: dts: r8a7790: Use R-Car Gen 2 fallback binding for msiof nodes
From: Simon Horman [ Upstream commit 654450baf2afba86cf328e1849ccac61ec4630af ] Use recently added R-Car Gen 2 fallback binding for msiof nodes in DT for r8a7790 SoC. This has no run-time effect for the current driver as the initialisation sequence is the same for the SoC-specific binding for r8a7790 and the fallback binding for R-Car Gen 2. Signed-off-by: Simon Horman Reviewed-by: Geert Uytterhoeven Signed-off-by: Sasha Levin --- arch/arm/boot/dts/r8a7790.dtsi | 12 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/arch/arm/boot/dts/r8a7790.dtsi b/arch/arm/boot/dts/r8a7790.dtsi index e07ae5d45e19..7b39d8fae61e 100644 --- a/arch/arm/boot/dts/r8a7790.dtsi +++ b/arch/arm/boot/dts/r8a7790.dtsi @@ -1409,7 +1409,8 @@ }; msiof0: spi@e6e2 { - compatible = "renesas,msiof-r8a7790"; + compatible = "renesas,msiof-r8a7790", +"renesas,rcar-gen2-msiof"; reg = <0 0xe6e2 0 0x0064>; interrupts = <0 156 IRQ_TYPE_LEVEL_HIGH>; clocks = <_clks R8A7790_CLK_MSIOF0>; @@ -1422,7 +1423,8 @@ }; msiof1: spi@e6e1 { - compatible = "renesas,msiof-r8a7790"; + compatible = "renesas,msiof-r8a7790", +"renesas,rcar-gen2-msiof"; reg = <0 0xe6e1 0 0x0064>; interrupts = <0 157 IRQ_TYPE_LEVEL_HIGH>; clocks = <_clks R8A7790_CLK_MSIOF1>; @@ -1435,7 +1437,8 @@ }; msiof2: spi@e6e0 { - compatible = "renesas,msiof-r8a7790"; + compatible = "renesas,msiof-r8a7790", +"renesas,rcar-gen2-msiof"; reg = <0 0xe6e0 0 0x0064>; interrupts = <0 158 IRQ_TYPE_LEVEL_HIGH>; clocks = <_clks R8A7790_CLK_MSIOF2>; @@ -1448,7 +1451,8 @@ }; msiof3: spi@e6c9 { - compatible = "renesas,msiof-r8a7790"; + compatible = "renesas,msiof-r8a7790", +"renesas,rcar-gen2-msiof"; reg = <0 0xe6c9 0 0x0064>; interrupts = <0 159 IRQ_TYPE_LEVEL_HIGH>; clocks = <_clks R8A7790_CLK_MSIOF3>; -- 2.11.0
[PATCH review for 4.4 35/47] mmc: sdio: fix alignment issue in struct sdio_func
From: Heiner Kallweit[ Upstream commit 5ef1ecf060f28ecef313b5723f1fd39bf5a35f56 ] Certain 64-bit systems (e.g. Amlogic Meson GX) require buffers to be used for DMA to be 8-byte-aligned. struct sdio_func has an embedded small DMA buffer not meeting this requirement. When testing switching to descriptor chain mode in meson-gx driver SDIO is broken therefore. Fix this by allocating the small DMA buffer separately as kmalloc ensures that the returned memory area is properly aligned for every basic data type. Signed-off-by: Heiner Kallweit Tested-by: Helmut Klein Signed-off-by: Ulf Hansson Signed-off-by: Sasha Levin --- drivers/mmc/core/sdio_bus.c | 12 +++- include/linux/mmc/sdio_func.h | 2 +- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/drivers/mmc/core/sdio_bus.c b/drivers/mmc/core/sdio_bus.c index 7e327a6dd53d..c23bc4f331bd 100644 --- a/drivers/mmc/core/sdio_bus.c +++ b/drivers/mmc/core/sdio_bus.c @@ -266,7 +266,7 @@ static void sdio_release_func(struct device *dev) sdio_free_func_cis(func); kfree(func->info); - + kfree(func->tmpbuf); kfree(func); } @@ -281,6 +281,16 @@ struct sdio_func *sdio_alloc_func(struct mmc_card *card) if (!func) return ERR_PTR(-ENOMEM); + /* +* allocate buffer separately to make sure it's properly aligned for +* DMA usage (incl. 64 bit DMA) +*/ + func->tmpbuf = kmalloc(4, GFP_KERNEL); + if (!func->tmpbuf) { + kfree(func); + return ERR_PTR(-ENOMEM); + } + func->card = card; device_initialize(>dev); diff --git a/include/linux/mmc/sdio_func.h b/include/linux/mmc/sdio_func.h index aab032a6ae61..97ca105347a6 100644 --- a/include/linux/mmc/sdio_func.h +++ b/include/linux/mmc/sdio_func.h @@ -53,7 +53,7 @@ struct sdio_func { unsigned intstate; /* function state */ #define SDIO_STATE_PRESENT (1<<0) /* present in sysfs */ - u8 tmpbuf[4]; /* DMA:able scratch buffer */ + u8 *tmpbuf;/* DMA:able scratch buffer */ unsignednum_info; /* number of info strings */ const char **info; /* info strings */ -- 2.11.0
[PATCH review for 4.4 35/47] mmc: sdio: fix alignment issue in struct sdio_func
From: Heiner Kallweit [ Upstream commit 5ef1ecf060f28ecef313b5723f1fd39bf5a35f56 ] Certain 64-bit systems (e.g. Amlogic Meson GX) require buffers to be used for DMA to be 8-byte-aligned. struct sdio_func has an embedded small DMA buffer not meeting this requirement. When testing switching to descriptor chain mode in meson-gx driver SDIO is broken therefore. Fix this by allocating the small DMA buffer separately as kmalloc ensures that the returned memory area is properly aligned for every basic data type. Signed-off-by: Heiner Kallweit Tested-by: Helmut Klein Signed-off-by: Ulf Hansson Signed-off-by: Sasha Levin --- drivers/mmc/core/sdio_bus.c | 12 +++- include/linux/mmc/sdio_func.h | 2 +- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/drivers/mmc/core/sdio_bus.c b/drivers/mmc/core/sdio_bus.c index 7e327a6dd53d..c23bc4f331bd 100644 --- a/drivers/mmc/core/sdio_bus.c +++ b/drivers/mmc/core/sdio_bus.c @@ -266,7 +266,7 @@ static void sdio_release_func(struct device *dev) sdio_free_func_cis(func); kfree(func->info); - + kfree(func->tmpbuf); kfree(func); } @@ -281,6 +281,16 @@ struct sdio_func *sdio_alloc_func(struct mmc_card *card) if (!func) return ERR_PTR(-ENOMEM); + /* +* allocate buffer separately to make sure it's properly aligned for +* DMA usage (incl. 64 bit DMA) +*/ + func->tmpbuf = kmalloc(4, GFP_KERNEL); + if (!func->tmpbuf) { + kfree(func); + return ERR_PTR(-ENOMEM); + } + func->card = card; device_initialize(>dev); diff --git a/include/linux/mmc/sdio_func.h b/include/linux/mmc/sdio_func.h index aab032a6ae61..97ca105347a6 100644 --- a/include/linux/mmc/sdio_func.h +++ b/include/linux/mmc/sdio_func.h @@ -53,7 +53,7 @@ struct sdio_func { unsigned intstate; /* function state */ #define SDIO_STATE_PRESENT (1<<0) /* present in sysfs */ - u8 tmpbuf[4]; /* DMA:able scratch buffer */ + u8 *tmpbuf;/* DMA:able scratch buffer */ unsignednum_info; /* number of info strings */ const char **info; /* info strings */ -- 2.11.0
[PATCH review for 4.4 18/47] IB/ipoib: Fix deadlock over vlan_mutex
From: Feras Daoud[ Upstream commit 1c3098cdb05207e740715857df7b0998e372f527 ] This patch fixes Deadlock while executing ipoib_vlan_delete. The function takes the vlan_rwsem semaphore and calls unregister_netdevice. The later function calls ipoib_mcast_stop_thread that cause workqueue flush. When the queue has one of the ipoib_ib_dev_flush_xxx events, a deadlock occur because these events also tries to catch the same vlan_rwsem semaphore. To fix, unregister_netdevice should be called after releasing the semaphore. Fixes: cbbe1efa4972 ("IPoIB: Fix deadlock between ipoib_open() and child interface create") Signed-off-by: Feras Daoud Signed-off-by: Erez Shitrit Reviewed-by: Alex Vesker Signed-off-by: Leon Romanovsky Signed-off-by: Doug Ledford Signed-off-by: Sasha Levin --- drivers/infiniband/ulp/ipoib/ipoib_vlan.c | 6 +- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/drivers/infiniband/ulp/ipoib/ipoib_vlan.c b/drivers/infiniband/ulp/ipoib/ipoib_vlan.c index 57a34f87dedf..3a647fd50f09 100644 --- a/drivers/infiniband/ulp/ipoib/ipoib_vlan.c +++ b/drivers/infiniband/ulp/ipoib/ipoib_vlan.c @@ -185,7 +185,6 @@ int ipoib_vlan_delete(struct net_device *pdev, unsigned short pkey) list_for_each_entry_safe(priv, tpriv, >child_intfs, list) { if (priv->pkey == pkey && priv->child_type == IPOIB_LEGACY_CHILD) { - unregister_netdevice(priv->dev); list_del(>list); dev = priv->dev; break; @@ -193,6 +192,11 @@ int ipoib_vlan_delete(struct net_device *pdev, unsigned short pkey) } up_write(>vlan_rwsem); + if (dev) { + ipoib_dbg(ppriv, "delete child vlan %s\n", dev->name); + unregister_netdevice(dev); + } + rtnl_unlock(); if (dev) { -- 2.11.0
[PATCH review for 4.4 18/47] IB/ipoib: Fix deadlock over vlan_mutex
From: Feras Daoud [ Upstream commit 1c3098cdb05207e740715857df7b0998e372f527 ] This patch fixes Deadlock while executing ipoib_vlan_delete. The function takes the vlan_rwsem semaphore and calls unregister_netdevice. The later function calls ipoib_mcast_stop_thread that cause workqueue flush. When the queue has one of the ipoib_ib_dev_flush_xxx events, a deadlock occur because these events also tries to catch the same vlan_rwsem semaphore. To fix, unregister_netdevice should be called after releasing the semaphore. Fixes: cbbe1efa4972 ("IPoIB: Fix deadlock between ipoib_open() and child interface create") Signed-off-by: Feras Daoud Signed-off-by: Erez Shitrit Reviewed-by: Alex Vesker Signed-off-by: Leon Romanovsky Signed-off-by: Doug Ledford Signed-off-by: Sasha Levin --- drivers/infiniband/ulp/ipoib/ipoib_vlan.c | 6 +- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/drivers/infiniband/ulp/ipoib/ipoib_vlan.c b/drivers/infiniband/ulp/ipoib/ipoib_vlan.c index 57a34f87dedf..3a647fd50f09 100644 --- a/drivers/infiniband/ulp/ipoib/ipoib_vlan.c +++ b/drivers/infiniband/ulp/ipoib/ipoib_vlan.c @@ -185,7 +185,6 @@ int ipoib_vlan_delete(struct net_device *pdev, unsigned short pkey) list_for_each_entry_safe(priv, tpriv, >child_intfs, list) { if (priv->pkey == pkey && priv->child_type == IPOIB_LEGACY_CHILD) { - unregister_netdevice(priv->dev); list_del(>list); dev = priv->dev; break; @@ -193,6 +192,11 @@ int ipoib_vlan_delete(struct net_device *pdev, unsigned short pkey) } up_write(>vlan_rwsem); + if (dev) { + ipoib_dbg(ppriv, "delete child vlan %s\n", dev->name); + unregister_netdevice(dev); + } + rtnl_unlock(); if (dev) { -- 2.11.0
[PATCH review for 4.4 21/47] drm/amdkfd: fix improper return value on error
From: Pan Bian[ Upstream commit 8bf793883da213864efc50c274d2b38ec0ca58b2 ] In function kfd_wait_on_events(), when the call to copy_from_user() fails, the value of return variable ret is 0. 0 indicates success, which is inconsistent with the execution status. This patch fixes the bug by assigning "-EFAULT" to ret when copy_from_user() returns an unexpected value. Signed-off-by: Pan Bian Signed-off-by: Oded Gabbay Signed-off-by: Sasha Levin --- drivers/gpu/drm/amd/amdkfd/kfd_events.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_events.c b/drivers/gpu/drm/amd/amdkfd/kfd_events.c index b6e28dcaea1d..1fb1daa0b366 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_events.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_events.c @@ -739,8 +739,10 @@ int kfd_wait_on_events(struct kfd_process *p, struct kfd_event_data event_data; if (copy_from_user(_data, [i], - sizeof(struct kfd_event_data))) + sizeof(struct kfd_event_data))) { + ret = -EFAULT; goto fail; + } ret = init_event_waiter(p, _waiters[i], event_data.event_id, i); -- 2.11.0
[PATCH review for 4.4 21/47] drm/amdkfd: fix improper return value on error
From: Pan Bian [ Upstream commit 8bf793883da213864efc50c274d2b38ec0ca58b2 ] In function kfd_wait_on_events(), when the call to copy_from_user() fails, the value of return variable ret is 0. 0 indicates success, which is inconsistent with the execution status. This patch fixes the bug by assigning "-EFAULT" to ret when copy_from_user() returns an unexpected value. Signed-off-by: Pan Bian Signed-off-by: Oded Gabbay Signed-off-by: Sasha Levin --- drivers/gpu/drm/amd/amdkfd/kfd_events.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_events.c b/drivers/gpu/drm/amd/amdkfd/kfd_events.c index b6e28dcaea1d..1fb1daa0b366 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_events.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_events.c @@ -739,8 +739,10 @@ int kfd_wait_on_events(struct kfd_process *p, struct kfd_event_data event_data; if (copy_from_user(_data, [i], - sizeof(struct kfd_event_data))) + sizeof(struct kfd_event_data))) { + ret = -EFAULT; goto fail; + } ret = init_event_waiter(p, _waiters[i], event_data.event_id, i); -- 2.11.0
[PATCH review for 4.4 04/47] RDS: RDMA: Fix the composite message user notification
From: Santosh Shilimkar[ Upstream commit 941f8d55f6d613a460a5e080d25a38509f45eb75 ] When application sends an RDS RDMA composite message consist of RDMA transfer to be followed up by non RDMA payload, it expect to be notified *only* when the full message gets delivered. RDS RDMA notification doesn't behave this way though. Thanks to Venkat for debug and root casuing the issue where only first part of the message(RDMA) was successfully delivered but remainder payload delivery failed. In that case, application should not be notified with a false positive of message delivery success. Fix this case by making sure the user gets notified only after the full message delivery. Reviewed-by: Venkat Venkatsubra Signed-off-by: Santosh Shilimkar Signed-off-by: Sasha Levin --- net/rds/ib_send.c | 25 +++-- net/rds/rdma.c| 10 ++ net/rds/rds.h | 1 + net/rds/send.c| 4 +++- 4 files changed, 29 insertions(+), 11 deletions(-) diff --git a/net/rds/ib_send.c b/net/rds/ib_send.c index eac30bf486d7..094e2a12860a 100644 --- a/net/rds/ib_send.c +++ b/net/rds/ib_send.c @@ -68,16 +68,6 @@ static void rds_ib_send_complete(struct rds_message *rm, complete(rm, notify_status); } -static void rds_ib_send_unmap_data(struct rds_ib_connection *ic, - struct rm_data_op *op, - int wc_status) -{ - if (op->op_nents) - ib_dma_unmap_sg(ic->i_cm_id->device, - op->op_sg, op->op_nents, - DMA_TO_DEVICE); -} - static void rds_ib_send_unmap_rdma(struct rds_ib_connection *ic, struct rm_rdma_op *op, int wc_status) @@ -138,6 +128,21 @@ static void rds_ib_send_unmap_atomic(struct rds_ib_connection *ic, rds_ib_stats_inc(s_ib_atomic_fadd); } +static void rds_ib_send_unmap_data(struct rds_ib_connection *ic, + struct rm_data_op *op, + int wc_status) +{ + struct rds_message *rm = container_of(op, struct rds_message, data); + + if (op->op_nents) + ib_dma_unmap_sg(ic->i_cm_id->device, + op->op_sg, op->op_nents, + DMA_TO_DEVICE); + + if (rm->rdma.op_active && rm->data.op_notify) + rds_ib_send_unmap_rdma(ic, >rdma, wc_status); +} + /* * Unmap the resources associated with a struct send_work. * diff --git a/net/rds/rdma.c b/net/rds/rdma.c index 4c93badeabf2..8d3a851a3476 100644 --- a/net/rds/rdma.c +++ b/net/rds/rdma.c @@ -626,6 +626,16 @@ int rds_cmsg_rdma_args(struct rds_sock *rs, struct rds_message *rm, } op->op_notifier->n_user_token = args->user_token; op->op_notifier->n_status = RDS_RDMA_SUCCESS; + + /* Enable rmda notification on data operation for composite +* rds messages and make sure notification is enabled only +* for the data operation which follows it so that application +* gets notified only after full message gets delivered. +*/ + if (rm->data.op_sg) { + rm->rdma.op_notify = 0; + rm->data.op_notify = !!(args->flags & RDS_RDMA_NOTIFY_ME); + } } /* The cookie contains the R_Key of the remote memory region, and diff --git a/net/rds/rds.h b/net/rds/rds.h index 0e2797bdc316..4588860f4c3b 100644 --- a/net/rds/rds.h +++ b/net/rds/rds.h @@ -378,6 +378,7 @@ struct rds_message { } rdma; struct rm_data_op { unsigned intop_active:1; + unsigned intop_notify:1; unsigned intop_nents; unsigned intop_count; unsigned intop_dmasg; diff --git a/net/rds/send.c b/net/rds/send.c index c9cdb358ea88..6815f03324d7 100644 --- a/net/rds/send.c +++ b/net/rds/send.c @@ -467,12 +467,14 @@ void rds_rdma_send_complete(struct rds_message *rm, int status) struct rm_rdma_op *ro; struct rds_notifier *notifier; unsigned long flags; + unsigned int notify = 0; spin_lock_irqsave(>m_rs_lock, flags); + notify = rm->rdma.op_notify | rm->data.op_notify; ro = >rdma; if (test_bit(RDS_MSG_ON_SOCK, >m_flags) && - ro->op_active && ro->op_notify && ro->op_notifier) { + ro->op_active && notify && ro->op_notifier) { notifier = ro->op_notifier; rs = rm->m_rs; sock_hold(rds_rs_to_sk(rs)); -- 2.11.0
[PATCH review for 4.4 22/47] USB: serial: mos7720: fix control-message error handling
From: Johan Hovold[ Upstream commit 0d130367abf582e7cbf60075c2a7ab53817b1d14 ] Make sure to log an error on short transfers when reading a device register. Also clear the provided buffer (which if often an uninitialised automatic variable) on errors as the driver currently does not bother to check for errors. Reviewed-by: Greg Kroah-Hartman Signed-off-by: Johan Hovold Signed-off-by: Sasha Levin --- drivers/usb/serial/mos7720.c | 9 +++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/drivers/usb/serial/mos7720.c b/drivers/usb/serial/mos7720.c index e56cdb436de3..4581fa1dec98 100644 --- a/drivers/usb/serial/mos7720.c +++ b/drivers/usb/serial/mos7720.c @@ -234,11 +234,16 @@ static int read_mos_reg(struct usb_serial *serial, unsigned int serial_portnum, status = usb_control_msg(usbdev, pipe, request, requesttype, value, index, buf, 1, MOS_WDR_TIMEOUT); - if (status == 1) + if (status == 1) { *data = *buf; - else if (status < 0) + } else { dev_err(>dev, "mos7720: usb_control_msg() failed: %d\n", status); + if (status >= 0) + status = -EIO; + *data = 0; + } + kfree(buf); return status; -- 2.11.0
[PATCH review for 4.4 04/47] RDS: RDMA: Fix the composite message user notification
From: Santosh Shilimkar [ Upstream commit 941f8d55f6d613a460a5e080d25a38509f45eb75 ] When application sends an RDS RDMA composite message consist of RDMA transfer to be followed up by non RDMA payload, it expect to be notified *only* when the full message gets delivered. RDS RDMA notification doesn't behave this way though. Thanks to Venkat for debug and root casuing the issue where only first part of the message(RDMA) was successfully delivered but remainder payload delivery failed. In that case, application should not be notified with a false positive of message delivery success. Fix this case by making sure the user gets notified only after the full message delivery. Reviewed-by: Venkat Venkatsubra Signed-off-by: Santosh Shilimkar Signed-off-by: Sasha Levin --- net/rds/ib_send.c | 25 +++-- net/rds/rdma.c| 10 ++ net/rds/rds.h | 1 + net/rds/send.c| 4 +++- 4 files changed, 29 insertions(+), 11 deletions(-) diff --git a/net/rds/ib_send.c b/net/rds/ib_send.c index eac30bf486d7..094e2a12860a 100644 --- a/net/rds/ib_send.c +++ b/net/rds/ib_send.c @@ -68,16 +68,6 @@ static void rds_ib_send_complete(struct rds_message *rm, complete(rm, notify_status); } -static void rds_ib_send_unmap_data(struct rds_ib_connection *ic, - struct rm_data_op *op, - int wc_status) -{ - if (op->op_nents) - ib_dma_unmap_sg(ic->i_cm_id->device, - op->op_sg, op->op_nents, - DMA_TO_DEVICE); -} - static void rds_ib_send_unmap_rdma(struct rds_ib_connection *ic, struct rm_rdma_op *op, int wc_status) @@ -138,6 +128,21 @@ static void rds_ib_send_unmap_atomic(struct rds_ib_connection *ic, rds_ib_stats_inc(s_ib_atomic_fadd); } +static void rds_ib_send_unmap_data(struct rds_ib_connection *ic, + struct rm_data_op *op, + int wc_status) +{ + struct rds_message *rm = container_of(op, struct rds_message, data); + + if (op->op_nents) + ib_dma_unmap_sg(ic->i_cm_id->device, + op->op_sg, op->op_nents, + DMA_TO_DEVICE); + + if (rm->rdma.op_active && rm->data.op_notify) + rds_ib_send_unmap_rdma(ic, >rdma, wc_status); +} + /* * Unmap the resources associated with a struct send_work. * diff --git a/net/rds/rdma.c b/net/rds/rdma.c index 4c93badeabf2..8d3a851a3476 100644 --- a/net/rds/rdma.c +++ b/net/rds/rdma.c @@ -626,6 +626,16 @@ int rds_cmsg_rdma_args(struct rds_sock *rs, struct rds_message *rm, } op->op_notifier->n_user_token = args->user_token; op->op_notifier->n_status = RDS_RDMA_SUCCESS; + + /* Enable rmda notification on data operation for composite +* rds messages and make sure notification is enabled only +* for the data operation which follows it so that application +* gets notified only after full message gets delivered. +*/ + if (rm->data.op_sg) { + rm->rdma.op_notify = 0; + rm->data.op_notify = !!(args->flags & RDS_RDMA_NOTIFY_ME); + } } /* The cookie contains the R_Key of the remote memory region, and diff --git a/net/rds/rds.h b/net/rds/rds.h index 0e2797bdc316..4588860f4c3b 100644 --- a/net/rds/rds.h +++ b/net/rds/rds.h @@ -378,6 +378,7 @@ struct rds_message { } rdma; struct rm_data_op { unsigned intop_active:1; + unsigned intop_notify:1; unsigned intop_nents; unsigned intop_count; unsigned intop_dmasg; diff --git a/net/rds/send.c b/net/rds/send.c index c9cdb358ea88..6815f03324d7 100644 --- a/net/rds/send.c +++ b/net/rds/send.c @@ -467,12 +467,14 @@ void rds_rdma_send_complete(struct rds_message *rm, int status) struct rm_rdma_op *ro; struct rds_notifier *notifier; unsigned long flags; + unsigned int notify = 0; spin_lock_irqsave(>m_rs_lock, flags); + notify = rm->rdma.op_notify | rm->data.op_notify; ro = >rdma; if (test_bit(RDS_MSG_ON_SOCK, >m_flags) && - ro->op_active && ro->op_notify && ro->op_notifier) { + ro->op_active && notify && ro->op_notifier) { notifier = ro->op_notifier; rs = rm->m_rs; sock_hold(rds_rs_to_sk(rs)); -- 2.11.0
[PATCH review for 4.4 22/47] USB: serial: mos7720: fix control-message error handling
From: Johan Hovold [ Upstream commit 0d130367abf582e7cbf60075c2a7ab53817b1d14 ] Make sure to log an error on short transfers when reading a device register. Also clear the provided buffer (which if often an uninitialised automatic variable) on errors as the driver currently does not bother to check for errors. Reviewed-by: Greg Kroah-Hartman Signed-off-by: Johan Hovold Signed-off-by: Sasha Levin --- drivers/usb/serial/mos7720.c | 9 +++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/drivers/usb/serial/mos7720.c b/drivers/usb/serial/mos7720.c index e56cdb436de3..4581fa1dec98 100644 --- a/drivers/usb/serial/mos7720.c +++ b/drivers/usb/serial/mos7720.c @@ -234,11 +234,16 @@ static int read_mos_reg(struct usb_serial *serial, unsigned int serial_portnum, status = usb_control_msg(usbdev, pipe, request, requesttype, value, index, buf, 1, MOS_WDR_TIMEOUT); - if (status == 1) + if (status == 1) { *data = *buf; - else if (status < 0) + } else { dev_err(>dev, "mos7720: usb_control_msg() failed: %d\n", status); + if (status >= 0) + status = -EIO; + *data = 0; + } + kfree(buf); return status; -- 2.11.0
[PATCH review for 4.4 37/47] netfilter: invoke synchronize_rcu after set the _hook_ to NULL
From: Liping Zhang[ Upstream commit 3b7dabf029478bb80507a6c4500ca94132a2bc0b ] Otherwise, another CPU may access the invalid pointer. For example: CPU0CPU1 - rcu_read_lock(); - pfunc = _hook_; _hook_ = NULL; - mod unload - - pfunc(); // invalid, panic - rcu_read_unlock(); So we must call synchronize_rcu() to wait the rcu reader to finish. Also note, in nf_nat_snmp_basic_fini, synchronize_rcu() will be invoked by later nf_conntrack_helper_unregister, but I'm inclined to add a explicit synchronize_rcu after set the nf_nat_snmp_hook to NULL. Depend on such obscure assumptions is not a good idea. Last, in nfnetlink_cttimeout, we use kfree_rcu to free the time object, so in cttimeout_exit, invoking rcu_barrier() is not necessary at all, remove it too. Signed-off-by: Liping Zhang Signed-off-by: Pablo Neira Ayuso Signed-off-by: Sasha Levin --- net/ipv4/netfilter/nf_nat_snmp_basic.c | 1 + net/netfilter/nf_conntrack_ecache.c| 2 ++ net/netfilter/nf_conntrack_netlink.c | 1 + net/netfilter/nf_nat_core.c| 2 ++ net/netfilter/nfnetlink_cttimeout.c| 2 +- 5 files changed, 7 insertions(+), 1 deletion(-) diff --git a/net/ipv4/netfilter/nf_nat_snmp_basic.c b/net/ipv4/netfilter/nf_nat_snmp_basic.c index ddb894ac1458..2689c9c4f1a0 100644 --- a/net/ipv4/netfilter/nf_nat_snmp_basic.c +++ b/net/ipv4/netfilter/nf_nat_snmp_basic.c @@ -1304,6 +1304,7 @@ static int __init nf_nat_snmp_basic_init(void) static void __exit nf_nat_snmp_basic_fini(void) { RCU_INIT_POINTER(nf_nat_snmp_hook, NULL); + synchronize_rcu(); nf_conntrack_helper_unregister(_trap_helper); } diff --git a/net/netfilter/nf_conntrack_ecache.c b/net/netfilter/nf_conntrack_ecache.c index 4e78c57b818f..f3b92ce463b0 100644 --- a/net/netfilter/nf_conntrack_ecache.c +++ b/net/netfilter/nf_conntrack_ecache.c @@ -200,6 +200,7 @@ void nf_conntrack_unregister_notifier(struct net *net, BUG_ON(notify != new); RCU_INIT_POINTER(net->ct.nf_conntrack_event_cb, NULL); mutex_unlock(_ct_ecache_mutex); + /* synchronize_rcu() is called from ctnetlink_exit. */ } EXPORT_SYMBOL_GPL(nf_conntrack_unregister_notifier); @@ -236,6 +237,7 @@ void nf_ct_expect_unregister_notifier(struct net *net, BUG_ON(notify != new); RCU_INIT_POINTER(net->ct.nf_expect_event_cb, NULL); mutex_unlock(_ct_ecache_mutex); + /* synchronize_rcu() is called from ctnetlink_exit. */ } EXPORT_SYMBOL_GPL(nf_ct_expect_unregister_notifier); diff --git a/net/netfilter/nf_conntrack_netlink.c b/net/netfilter/nf_conntrack_netlink.c index e565b2becb14..660939df7c94 100644 --- a/net/netfilter/nf_conntrack_netlink.c +++ b/net/netfilter/nf_conntrack_netlink.c @@ -3415,6 +3415,7 @@ static void __exit ctnetlink_exit(void) #ifdef CONFIG_NETFILTER_NETLINK_GLUE_CT RCU_INIT_POINTER(nfnl_ct_hook, NULL); #endif + synchronize_rcu(); } module_init(ctnetlink_init); diff --git a/net/netfilter/nf_nat_core.c b/net/netfilter/nf_nat_core.c index 06a9f45771ab..44516c90118a 100644 --- a/net/netfilter/nf_nat_core.c +++ b/net/netfilter/nf_nat_core.c @@ -892,6 +892,8 @@ static void __exit nf_nat_cleanup(void) #ifdef CONFIG_XFRM RCU_INIT_POINTER(nf_nat_decode_session_hook, NULL); #endif + synchronize_rcu(); + for (i = 0; i < NFPROTO_NUMPROTO; i++) kfree(nf_nat_l4protos[i]); synchronize_net(); diff --git a/net/netfilter/nfnetlink_cttimeout.c b/net/netfilter/nfnetlink_cttimeout.c index c7a2d0e1c462..ed9153bd7e73 100644 --- a/net/netfilter/nfnetlink_cttimeout.c +++ b/net/netfilter/nfnetlink_cttimeout.c @@ -611,8 +611,8 @@ static void __exit cttimeout_exit(void) #ifdef CONFIG_NF_CONNTRACK_TIMEOUT RCU_INIT_POINTER(nf_ct_timeout_find_get_hook, NULL); RCU_INIT_POINTER(nf_ct_timeout_put_hook, NULL); + synchronize_rcu(); #endif /* CONFIG_NF_CONNTRACK_TIMEOUT */ - rcu_barrier(); } module_init(cttimeout_init); -- 2.11.0
[PATCH review for 4.4 37/47] netfilter: invoke synchronize_rcu after set the _hook_ to NULL
From: Liping Zhang [ Upstream commit 3b7dabf029478bb80507a6c4500ca94132a2bc0b ] Otherwise, another CPU may access the invalid pointer. For example: CPU0CPU1 - rcu_read_lock(); - pfunc = _hook_; _hook_ = NULL; - mod unload - - pfunc(); // invalid, panic - rcu_read_unlock(); So we must call synchronize_rcu() to wait the rcu reader to finish. Also note, in nf_nat_snmp_basic_fini, synchronize_rcu() will be invoked by later nf_conntrack_helper_unregister, but I'm inclined to add a explicit synchronize_rcu after set the nf_nat_snmp_hook to NULL. Depend on such obscure assumptions is not a good idea. Last, in nfnetlink_cttimeout, we use kfree_rcu to free the time object, so in cttimeout_exit, invoking rcu_barrier() is not necessary at all, remove it too. Signed-off-by: Liping Zhang Signed-off-by: Pablo Neira Ayuso Signed-off-by: Sasha Levin --- net/ipv4/netfilter/nf_nat_snmp_basic.c | 1 + net/netfilter/nf_conntrack_ecache.c| 2 ++ net/netfilter/nf_conntrack_netlink.c | 1 + net/netfilter/nf_nat_core.c| 2 ++ net/netfilter/nfnetlink_cttimeout.c| 2 +- 5 files changed, 7 insertions(+), 1 deletion(-) diff --git a/net/ipv4/netfilter/nf_nat_snmp_basic.c b/net/ipv4/netfilter/nf_nat_snmp_basic.c index ddb894ac1458..2689c9c4f1a0 100644 --- a/net/ipv4/netfilter/nf_nat_snmp_basic.c +++ b/net/ipv4/netfilter/nf_nat_snmp_basic.c @@ -1304,6 +1304,7 @@ static int __init nf_nat_snmp_basic_init(void) static void __exit nf_nat_snmp_basic_fini(void) { RCU_INIT_POINTER(nf_nat_snmp_hook, NULL); + synchronize_rcu(); nf_conntrack_helper_unregister(_trap_helper); } diff --git a/net/netfilter/nf_conntrack_ecache.c b/net/netfilter/nf_conntrack_ecache.c index 4e78c57b818f..f3b92ce463b0 100644 --- a/net/netfilter/nf_conntrack_ecache.c +++ b/net/netfilter/nf_conntrack_ecache.c @@ -200,6 +200,7 @@ void nf_conntrack_unregister_notifier(struct net *net, BUG_ON(notify != new); RCU_INIT_POINTER(net->ct.nf_conntrack_event_cb, NULL); mutex_unlock(_ct_ecache_mutex); + /* synchronize_rcu() is called from ctnetlink_exit. */ } EXPORT_SYMBOL_GPL(nf_conntrack_unregister_notifier); @@ -236,6 +237,7 @@ void nf_ct_expect_unregister_notifier(struct net *net, BUG_ON(notify != new); RCU_INIT_POINTER(net->ct.nf_expect_event_cb, NULL); mutex_unlock(_ct_ecache_mutex); + /* synchronize_rcu() is called from ctnetlink_exit. */ } EXPORT_SYMBOL_GPL(nf_ct_expect_unregister_notifier); diff --git a/net/netfilter/nf_conntrack_netlink.c b/net/netfilter/nf_conntrack_netlink.c index e565b2becb14..660939df7c94 100644 --- a/net/netfilter/nf_conntrack_netlink.c +++ b/net/netfilter/nf_conntrack_netlink.c @@ -3415,6 +3415,7 @@ static void __exit ctnetlink_exit(void) #ifdef CONFIG_NETFILTER_NETLINK_GLUE_CT RCU_INIT_POINTER(nfnl_ct_hook, NULL); #endif + synchronize_rcu(); } module_init(ctnetlink_init); diff --git a/net/netfilter/nf_nat_core.c b/net/netfilter/nf_nat_core.c index 06a9f45771ab..44516c90118a 100644 --- a/net/netfilter/nf_nat_core.c +++ b/net/netfilter/nf_nat_core.c @@ -892,6 +892,8 @@ static void __exit nf_nat_cleanup(void) #ifdef CONFIG_XFRM RCU_INIT_POINTER(nf_nat_decode_session_hook, NULL); #endif + synchronize_rcu(); + for (i = 0; i < NFPROTO_NUMPROTO; i++) kfree(nf_nat_l4protos[i]); synchronize_net(); diff --git a/net/netfilter/nfnetlink_cttimeout.c b/net/netfilter/nfnetlink_cttimeout.c index c7a2d0e1c462..ed9153bd7e73 100644 --- a/net/netfilter/nfnetlink_cttimeout.c +++ b/net/netfilter/nfnetlink_cttimeout.c @@ -611,8 +611,8 @@ static void __exit cttimeout_exit(void) #ifdef CONFIG_NF_CONNTRACK_TIMEOUT RCU_INIT_POINTER(nf_ct_timeout_find_get_hook, NULL); RCU_INIT_POINTER(nf_ct_timeout_put_hook, NULL); + synchronize_rcu(); #endif /* CONFIG_NF_CONNTRACK_TIMEOUT */ - rcu_barrier(); } module_init(cttimeout_init); -- 2.11.0
[PATCH review for 4.4 24/47] pinctrl: mvebu: Use seq_puts() in mvebu_pinconf_group_dbg_show()
From: Markus Elfring[ Upstream commit 420dc61642920849d824a0de2aa853db59f5244f ] Strings which did not contain data format specifications should be put into a sequence. Thus use the corresponding function "seq_puts". This issue was detected by using the Coccinelle software. Signed-off-by: Markus Elfring Signed-off-by: Linus Walleij Signed-off-by: Sasha Levin --- drivers/pinctrl/mvebu/pinctrl-mvebu.c | 9 + 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/drivers/pinctrl/mvebu/pinctrl-mvebu.c b/drivers/pinctrl/mvebu/pinctrl-mvebu.c index 77d2221d379d..076c2ee2ff70 100644 --- a/drivers/pinctrl/mvebu/pinctrl-mvebu.c +++ b/drivers/pinctrl/mvebu/pinctrl-mvebu.c @@ -195,11 +195,12 @@ static void mvebu_pinconf_group_dbg_show(struct pinctrl_dev *pctldev, seq_printf(s, "o"); seq_printf(s, ")"); } - } else - seq_printf(s, "current: UNKNOWN"); + } else { + seq_puts(s, "current: UNKNOWN"); + } if (grp->num_settings > 1) { - seq_printf(s, ", available = ["); + seq_puts(s, ", available = ["); for (n = 0; n < grp->num_settings; n++) { if (curr == >settings[n]) continue; @@ -222,7 +223,7 @@ static void mvebu_pinconf_group_dbg_show(struct pinctrl_dev *pctldev, seq_printf(s, ")"); } } - seq_printf(s, " ]"); + seq_puts(s, " ]"); } return; } -- 2.11.0
[PATCH review for 4.4 40/47] netfilter: nfnl_cthelper: fix incorrect helper->expect_class_max
From: Liping Zhang[ Upstream commit ae5c682113f9f94cc5e76f92cf041ee624c173ee ] The helper->expect_class_max must be set to the total number of expect_policy minus 1, since we will use the statement "if (class > helper->expect_class_max)" to validate the CTA_EXPECT_CLASS attr in ctnetlink_alloc_expect. So for compatibility, set the helper->expect_class_max to the NFCTH_POLICY_SET_NUM attr's value minus 1. Also: it's invalid when the NFCTH_POLICY_SET_NUM attr's value is zero. 1. this will result "expect_policy = kzalloc(0, GFP_KERNEL);"; 2. we cannot set the helper->expect_class_max to a proper value. So if nla_get_be32(tb[NFCTH_POLICY_SET_NUM]) is zero, report -EINVAL to the userspace. Signed-off-by: Liping Zhang Signed-off-by: Pablo Neira Ayuso Signed-off-by: Sasha Levin --- net/netfilter/nfnetlink_cthelper.c | 20 +++- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/net/netfilter/nfnetlink_cthelper.c b/net/netfilter/nfnetlink_cthelper.c index 54330fb5efaf..6d10002d23f8 100644 --- a/net/netfilter/nfnetlink_cthelper.c +++ b/net/netfilter/nfnetlink_cthelper.c @@ -161,6 +161,7 @@ nfnl_cthelper_parse_expect_policy(struct nf_conntrack_helper *helper, int i, ret; struct nf_conntrack_expect_policy *expect_policy; struct nlattr *tb[NFCTH_POLICY_SET_MAX+1]; + unsigned int class_max; ret = nla_parse_nested(tb, NFCTH_POLICY_SET_MAX, attr, nfnl_cthelper_expect_policy_set); @@ -170,19 +171,18 @@ nfnl_cthelper_parse_expect_policy(struct nf_conntrack_helper *helper, if (!tb[NFCTH_POLICY_SET_NUM]) return -EINVAL; - helper->expect_class_max = - ntohl(nla_get_be32(tb[NFCTH_POLICY_SET_NUM])); - - if (helper->expect_class_max != 0 && - helper->expect_class_max > NF_CT_MAX_EXPECT_CLASSES) + class_max = ntohl(nla_get_be32(tb[NFCTH_POLICY_SET_NUM])); + if (class_max == 0) + return -EINVAL; + if (class_max > NF_CT_MAX_EXPECT_CLASSES) return -EOVERFLOW; expect_policy = kzalloc(sizeof(struct nf_conntrack_expect_policy) * - helper->expect_class_max, GFP_KERNEL); + class_max, GFP_KERNEL); if (expect_policy == NULL) return -ENOMEM; - for (i=0; iexpect_class_max; i++) { + for (i = 0; i < class_max; i++) { if (!tb[NFCTH_POLICY_SET+i]) goto err; @@ -191,6 +191,8 @@ nfnl_cthelper_parse_expect_policy(struct nf_conntrack_helper *helper, if (ret < 0) goto err; } + + helper->expect_class_max = class_max - 1; helper->expect_policy = expect_policy; return 0; err: @@ -377,10 +379,10 @@ nfnl_cthelper_dump_policy(struct sk_buff *skb, goto nla_put_failure; if (nla_put_be32(skb, NFCTH_POLICY_SET_NUM, -htonl(helper->expect_class_max))) +htonl(helper->expect_class_max + 1))) goto nla_put_failure; - for (i=0; iexpect_class_max; i++) { + for (i = 0; i < helper->expect_class_max + 1; i++) { nest_parms2 = nla_nest_start(skb, (NFCTH_POLICY_SET+i) | NLA_F_NESTED); if (nest_parms2 == NULL) -- 2.11.0
[PATCH review for 4.4 24/47] pinctrl: mvebu: Use seq_puts() in mvebu_pinconf_group_dbg_show()
From: Markus Elfring [ Upstream commit 420dc61642920849d824a0de2aa853db59f5244f ] Strings which did not contain data format specifications should be put into a sequence. Thus use the corresponding function "seq_puts". This issue was detected by using the Coccinelle software. Signed-off-by: Markus Elfring Signed-off-by: Linus Walleij Signed-off-by: Sasha Levin --- drivers/pinctrl/mvebu/pinctrl-mvebu.c | 9 + 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/drivers/pinctrl/mvebu/pinctrl-mvebu.c b/drivers/pinctrl/mvebu/pinctrl-mvebu.c index 77d2221d379d..076c2ee2ff70 100644 --- a/drivers/pinctrl/mvebu/pinctrl-mvebu.c +++ b/drivers/pinctrl/mvebu/pinctrl-mvebu.c @@ -195,11 +195,12 @@ static void mvebu_pinconf_group_dbg_show(struct pinctrl_dev *pctldev, seq_printf(s, "o"); seq_printf(s, ")"); } - } else - seq_printf(s, "current: UNKNOWN"); + } else { + seq_puts(s, "current: UNKNOWN"); + } if (grp->num_settings > 1) { - seq_printf(s, ", available = ["); + seq_puts(s, ", available = ["); for (n = 0; n < grp->num_settings; n++) { if (curr == >settings[n]) continue; @@ -222,7 +223,7 @@ static void mvebu_pinconf_group_dbg_show(struct pinctrl_dev *pctldev, seq_printf(s, ")"); } } - seq_printf(s, " ]"); + seq_puts(s, " ]"); } return; } -- 2.11.0
[PATCH review for 4.4 40/47] netfilter: nfnl_cthelper: fix incorrect helper->expect_class_max
From: Liping Zhang [ Upstream commit ae5c682113f9f94cc5e76f92cf041ee624c173ee ] The helper->expect_class_max must be set to the total number of expect_policy minus 1, since we will use the statement "if (class > helper->expect_class_max)" to validate the CTA_EXPECT_CLASS attr in ctnetlink_alloc_expect. So for compatibility, set the helper->expect_class_max to the NFCTH_POLICY_SET_NUM attr's value minus 1. Also: it's invalid when the NFCTH_POLICY_SET_NUM attr's value is zero. 1. this will result "expect_policy = kzalloc(0, GFP_KERNEL);"; 2. we cannot set the helper->expect_class_max to a proper value. So if nla_get_be32(tb[NFCTH_POLICY_SET_NUM]) is zero, report -EINVAL to the userspace. Signed-off-by: Liping Zhang Signed-off-by: Pablo Neira Ayuso Signed-off-by: Sasha Levin --- net/netfilter/nfnetlink_cthelper.c | 20 +++- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/net/netfilter/nfnetlink_cthelper.c b/net/netfilter/nfnetlink_cthelper.c index 54330fb5efaf..6d10002d23f8 100644 --- a/net/netfilter/nfnetlink_cthelper.c +++ b/net/netfilter/nfnetlink_cthelper.c @@ -161,6 +161,7 @@ nfnl_cthelper_parse_expect_policy(struct nf_conntrack_helper *helper, int i, ret; struct nf_conntrack_expect_policy *expect_policy; struct nlattr *tb[NFCTH_POLICY_SET_MAX+1]; + unsigned int class_max; ret = nla_parse_nested(tb, NFCTH_POLICY_SET_MAX, attr, nfnl_cthelper_expect_policy_set); @@ -170,19 +171,18 @@ nfnl_cthelper_parse_expect_policy(struct nf_conntrack_helper *helper, if (!tb[NFCTH_POLICY_SET_NUM]) return -EINVAL; - helper->expect_class_max = - ntohl(nla_get_be32(tb[NFCTH_POLICY_SET_NUM])); - - if (helper->expect_class_max != 0 && - helper->expect_class_max > NF_CT_MAX_EXPECT_CLASSES) + class_max = ntohl(nla_get_be32(tb[NFCTH_POLICY_SET_NUM])); + if (class_max == 0) + return -EINVAL; + if (class_max > NF_CT_MAX_EXPECT_CLASSES) return -EOVERFLOW; expect_policy = kzalloc(sizeof(struct nf_conntrack_expect_policy) * - helper->expect_class_max, GFP_KERNEL); + class_max, GFP_KERNEL); if (expect_policy == NULL) return -ENOMEM; - for (i=0; iexpect_class_max; i++) { + for (i = 0; i < class_max; i++) { if (!tb[NFCTH_POLICY_SET+i]) goto err; @@ -191,6 +191,8 @@ nfnl_cthelper_parse_expect_policy(struct nf_conntrack_helper *helper, if (ret < 0) goto err; } + + helper->expect_class_max = class_max - 1; helper->expect_policy = expect_policy; return 0; err: @@ -377,10 +379,10 @@ nfnl_cthelper_dump_policy(struct sk_buff *skb, goto nla_put_failure; if (nla_put_be32(skb, NFCTH_POLICY_SET_NUM, -htonl(helper->expect_class_max))) +htonl(helper->expect_class_max + 1))) goto nla_put_failure; - for (i=0; iexpect_class_max; i++) { + for (i = 0; i < helper->expect_class_max + 1; i++) { nest_parms2 = nla_nest_start(skb, (NFCTH_POLICY_SET+i) | NLA_F_NESTED); if (nest_parms2 == NULL) -- 2.11.0
[PATCH review for 4.4 23/47] USB: serial: mos7840: fix control-message error handling
From: Johan Hovold[ Upstream commit cd8db057e93ddaacbec025b567490555d2bca280 ] Make sure to detect short transfers when reading a device register. The modem-status handling had sufficient error checks in place, but move handling of short transfers into the register accessor function itself for consistency. Reviewed-by: Greg Kroah-Hartman Signed-off-by: Johan Hovold Signed-off-by: Sasha Levin --- drivers/usb/serial/mos7840.c | 19 +++ 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/drivers/usb/serial/mos7840.c b/drivers/usb/serial/mos7840.c index d17685cc00c9..ed883a7ad533 100644 --- a/drivers/usb/serial/mos7840.c +++ b/drivers/usb/serial/mos7840.c @@ -285,9 +285,15 @@ static int mos7840_get_reg_sync(struct usb_serial_port *port, __u16 reg, ret = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), MCS_RDREQ, MCS_RD_RTYPE, 0, reg, buf, VENDOR_READ_LENGTH, MOS_WDR_TIMEOUT); + if (ret < VENDOR_READ_LENGTH) { + if (ret >= 0) + ret = -EIO; + goto out; + } + *val = buf[0]; dev_dbg(>dev, "%s offset is %x, return val %x\n", __func__, reg, *val); - +out: kfree(buf); return ret; } @@ -353,8 +359,13 @@ static int mos7840_get_uart_reg(struct usb_serial_port *port, __u16 reg, ret = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), MCS_RDREQ, MCS_RD_RTYPE, Wval, reg, buf, VENDOR_READ_LENGTH, MOS_WDR_TIMEOUT); + if (ret < VENDOR_READ_LENGTH) { + if (ret >= 0) + ret = -EIO; + goto out; + } *val = buf[0]; - +out: kfree(buf); return ret; } @@ -1490,10 +1501,10 @@ static int mos7840_tiocmget(struct tty_struct *tty) return -ENODEV; status = mos7840_get_uart_reg(port, MODEM_STATUS_REGISTER, ); - if (status != 1) + if (status < 0) return -EIO; status = mos7840_get_uart_reg(port, MODEM_CONTROL_REGISTER, ); - if (status != 1) + if (status < 0) return -EIO; result = ((mcr & MCR_DTR) ? TIOCM_DTR : 0) | ((mcr & MCR_RTS) ? TIOCM_RTS : 0) -- 2.11.0
[PATCH review for 4.4 23/47] USB: serial: mos7840: fix control-message error handling
From: Johan Hovold [ Upstream commit cd8db057e93ddaacbec025b567490555d2bca280 ] Make sure to detect short transfers when reading a device register. The modem-status handling had sufficient error checks in place, but move handling of short transfers into the register accessor function itself for consistency. Reviewed-by: Greg Kroah-Hartman Signed-off-by: Johan Hovold Signed-off-by: Sasha Levin --- drivers/usb/serial/mos7840.c | 19 +++ 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/drivers/usb/serial/mos7840.c b/drivers/usb/serial/mos7840.c index d17685cc00c9..ed883a7ad533 100644 --- a/drivers/usb/serial/mos7840.c +++ b/drivers/usb/serial/mos7840.c @@ -285,9 +285,15 @@ static int mos7840_get_reg_sync(struct usb_serial_port *port, __u16 reg, ret = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), MCS_RDREQ, MCS_RD_RTYPE, 0, reg, buf, VENDOR_READ_LENGTH, MOS_WDR_TIMEOUT); + if (ret < VENDOR_READ_LENGTH) { + if (ret >= 0) + ret = -EIO; + goto out; + } + *val = buf[0]; dev_dbg(>dev, "%s offset is %x, return val %x\n", __func__, reg, *val); - +out: kfree(buf); return ret; } @@ -353,8 +359,13 @@ static int mos7840_get_uart_reg(struct usb_serial_port *port, __u16 reg, ret = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), MCS_RDREQ, MCS_RD_RTYPE, Wval, reg, buf, VENDOR_READ_LENGTH, MOS_WDR_TIMEOUT); + if (ret < VENDOR_READ_LENGTH) { + if (ret >= 0) + ret = -EIO; + goto out; + } *val = buf[0]; - +out: kfree(buf); return ret; } @@ -1490,10 +1501,10 @@ static int mos7840_tiocmget(struct tty_struct *tty) return -ENODEV; status = mos7840_get_uart_reg(port, MODEM_STATUS_REGISTER, ); - if (status != 1) + if (status < 0) return -EIO; status = mos7840_get_uart_reg(port, MODEM_CONTROL_REGISTER, ); - if (status != 1) + if (status < 0) return -EIO; result = ((mcr & MCR_DTR) ? TIOCM_DTR : 0) | ((mcr & MCR_RTS) ? TIOCM_RTS : 0) -- 2.11.0
[PATCH review for 4.4 16/47] ARM: 8635/1: nommu: allow enabling REMAP_VECTORS_TO_RAM
From: Afzal Mohammed[ Upstream commit 8a792e9afbce84a0fdaf213fe42bb97382487094 ] REMAP_VECTORS_TO_RAM depends on DRAM_BASE, but since DRAM_BASE is a hex, REMAP_VECTORS_TO_RAM could never get enabled. Also depending on DRAM_BASE is redundant as whenever REMAP_VECTORS_TO_RAM makes itself available to Kconfig, DRAM_BASE also is available as the Kconfig gets sourced on !MMU. Signed-off-by: Afzal Mohammed Reviewed-by: Vladimir Murzin Signed-off-by: Russell King Signed-off-by: Sasha Levin --- arch/arm/Kconfig-nommu | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/arch/arm/Kconfig-nommu b/arch/arm/Kconfig-nommu index aed66d5df7f1..b7576349528c 100644 --- a/arch/arm/Kconfig-nommu +++ b/arch/arm/Kconfig-nommu @@ -34,8 +34,7 @@ config PROCESSOR_ID used instead of the auto-probing which utilizes the register. config REMAP_VECTORS_TO_RAM - bool 'Install vectors to the beginning of RAM' if DRAM_BASE - depends on DRAM_BASE + bool 'Install vectors to the beginning of RAM' help The kernel needs to change the hardware exception vectors. In nommu mode, the hardware exception vectors are normally -- 2.11.0
[PATCH review for 4.4 16/47] ARM: 8635/1: nommu: allow enabling REMAP_VECTORS_TO_RAM
From: Afzal Mohammed [ Upstream commit 8a792e9afbce84a0fdaf213fe42bb97382487094 ] REMAP_VECTORS_TO_RAM depends on DRAM_BASE, but since DRAM_BASE is a hex, REMAP_VECTORS_TO_RAM could never get enabled. Also depending on DRAM_BASE is redundant as whenever REMAP_VECTORS_TO_RAM makes itself available to Kconfig, DRAM_BASE also is available as the Kconfig gets sourced on !MMU. Signed-off-by: Afzal Mohammed Reviewed-by: Vladimir Murzin Signed-off-by: Russell King Signed-off-by: Sasha Levin --- arch/arm/Kconfig-nommu | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/arch/arm/Kconfig-nommu b/arch/arm/Kconfig-nommu index aed66d5df7f1..b7576349528c 100644 --- a/arch/arm/Kconfig-nommu +++ b/arch/arm/Kconfig-nommu @@ -34,8 +34,7 @@ config PROCESSOR_ID used instead of the auto-probing which utilizes the register. config REMAP_VECTORS_TO_RAM - bool 'Install vectors to the beginning of RAM' if DRAM_BASE - depends on DRAM_BASE + bool 'Install vectors to the beginning of RAM' help The kernel needs to change the hardware exception vectors. In nommu mode, the hardware exception vectors are normally -- 2.11.0
[PATCH review for 4.4 29/47] ASoC: dapm: fix some pointer error handling
From: Linus Walleij[ Upstream commit 639467c8f26d834c934215e8b59129ce442475fe ] commit 66feeec9322132689d42723df2537d60f96f8e44 "RFC: ASoC: dapm: handle probe deferrals" forgot a to update some two sites where the call was used. The static codechecks quickly found them. Reported-by: Dan Carpenter Fixes: 66feeec93221 ("RFC: ASoC: dapm: handle probe deferrals") Signed-off-by: Linus Walleij Signed-off-by: Mark Brown Signed-off-by: Sasha Levin --- sound/soc/soc-dapm.c | 20 1 file changed, 20 insertions(+) diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c index df036afb2197..6a438a361592 100644 --- a/sound/soc/soc-dapm.c +++ b/sound/soc/soc-dapm.c @@ -3794,6 +3794,16 @@ int snd_soc_dapm_new_dai_widgets(struct snd_soc_dapm_context *dapm, template.name); w = snd_soc_dapm_new_control_unlocked(dapm, ); + if (IS_ERR(w)) { + int ret = PTR_ERR(w); + + /* Do not nag about probe deferrals */ + if (ret != -EPROBE_DEFER) + dev_err(dapm->dev, + "ASoC: Failed to create %s widget (%d)\n", + dai->driver->playback.stream_name, ret); + return ret; + } if (!w) { dev_err(dapm->dev, "ASoC: Failed to create %s widget\n", dai->driver->playback.stream_name); @@ -3813,6 +3823,16 @@ int snd_soc_dapm_new_dai_widgets(struct snd_soc_dapm_context *dapm, template.name); w = snd_soc_dapm_new_control_unlocked(dapm, ); + if (IS_ERR(w)) { + int ret = PTR_ERR(w); + + /* Do not nag about probe deferrals */ + if (ret != -EPROBE_DEFER) + dev_err(dapm->dev, + "ASoC: Failed to create %s widget (%d)\n", + dai->driver->playback.stream_name, ret); + return ret; + } if (!w) { dev_err(dapm->dev, "ASoC: Failed to create %s widget\n", dai->driver->capture.stream_name); -- 2.11.0
[PATCH review for 4.4 26/47] ASoC: dapm: handle probe deferrals
From: Linus Walleij[ Upstream commit 37e1df8c95e2c8a57c77eafc097648f6e40a60ff ] This starts to handle probe deferrals on regulators and clocks on the ASoC DAPM. I came to this patch after audio stopped working on Ux500 ages ago and I finally looked into it to see what is wrong. I had messages like this in the console since a while back: ab8500-codec.0: ASoC: Failed to request audioclk: -517 ab8500-codec.0: ASoC: Failed to create DAPM control audioclk ab8500-codec.0: Failed to create new controls -12 snd-soc-mop500.0: ASoC: failed to instantiate card -12 snd-soc-mop500.0: Error: snd_soc_register_card failed (-12)! snd-soc-mop500: probe of snd-soc-mop500.0 failed with error -12 Apparently because the widget table for the codec looks like this (sound/soc/codecs/ab8500-codec.c): static const struct snd_soc_dapm_widget ab8500_dapm_widgets[] = { /* Clocks */ SND_SOC_DAPM_CLOCK_SUPPLY("audioclk"), /* Regulators */ SND_SOC_DAPM_REGULATOR_SUPPLY("V-AUD", 0, 0), SND_SOC_DAPM_REGULATOR_SUPPLY("V-AMIC1", 0, 0), SND_SOC_DAPM_REGULATOR_SUPPLY("V-AMIC2", 0, 0), SND_SOC_DAPM_REGULATOR_SUPPLY("V-DMIC", 0, 0), So when we call snd_soc_register_codec() and any of these widgets get a deferred probe we do not get an -EPROBE_DEFER (-517) back as we should and instead we just fail. Apparently the code assumes that clocks and regulators must be available at this point and not defer. After this patch it rather looks like this: ab8500-codec.0: Failed to create new controls -517 snd-soc-mop500.0: ASoC: failed to instantiate card -517 snd-soc-mop500.0: Error: snd_soc_register_card failed (-517)! (...) abx500-clk.0: registered clocks for ab850x snd-soc-mop500.0: ab8500-codec-dai.0 <-> ux500-msp-i2s.1 mapping ok snd-soc-mop500.0: ab8500-codec-dai.1 <-> ux500-msp-i2s.3 mapping ok I'm pretty happy about the patch as it it, but I'm a bit uncertain on how to proceed: there are a lot of users of the external functions snd_soc_dapm_new_control() (111 sites) and that will now return an occassional error pointer, which is not handled in the calling sites. I want an indication from the maintainers whether I should just go in and augment all these call sites, or if deferred probe is frowned upon when it leads to this much overhead. Signed-off-by: Linus Walleij Signed-off-by: Mark Brown Signed-off-by: Sasha Levin --- sound/soc/soc-dapm.c | 42 ++ sound/soc/soc-topology.c | 9 + 2 files changed, 51 insertions(+) diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c index b8a256dfed7e..df036afb2197 100644 --- a/sound/soc/soc-dapm.c +++ b/sound/soc/soc-dapm.c @@ -358,6 +358,10 @@ static int dapm_kcontrol_data_alloc(struct snd_soc_dapm_widget *widget, snd_soc_dapm_new_control_unlocked(widget->dapm, ); kfree(name); + if (IS_ERR(data->widget)) { + ret = PTR_ERR(data->widget); + goto err_data; + } if (!data->widget) { ret = -ENOMEM; goto err_data; @@ -392,6 +396,10 @@ static int dapm_kcontrol_data_alloc(struct snd_soc_dapm_widget *widget, data->widget = snd_soc_dapm_new_control_unlocked( widget->dapm, ); kfree(name); + if (IS_ERR(data->widget)) { + ret = PTR_ERR(data->widget); + goto err_data; + } if (!data->widget) { ret = -ENOMEM; goto err_data; @@ -3278,11 +3286,22 @@ snd_soc_dapm_new_control(struct snd_soc_dapm_context *dapm, mutex_lock_nested(>card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME); w = snd_soc_dapm_new_control_unlocked(dapm, widget); + /* Do not nag about probe deferrals */ + if (IS_ERR(w)) { + int ret = PTR_ERR(w); + + if (ret != -EPROBE_DEFER) + dev_err(dapm->dev, + "ASoC: Failed to create DAPM control %s (%d)\n", + widget->name, ret); + goto out_unlock; + } if (!w) dev_err(dapm->dev, "ASoC: Failed to create DAPM control %s\n", widget->name); +out_unlock: mutex_unlock(>card->dapm_mutex); return w; } @@ -3304,6 +3323,8 @@ snd_soc_dapm_new_control_unlocked(struct snd_soc_dapm_context *dapm, w->regulator = devm_regulator_get(dapm->dev, w->name); if (IS_ERR(w->regulator)) {
[PATCH review for 4.4 29/47] ASoC: dapm: fix some pointer error handling
From: Linus Walleij [ Upstream commit 639467c8f26d834c934215e8b59129ce442475fe ] commit 66feeec9322132689d42723df2537d60f96f8e44 "RFC: ASoC: dapm: handle probe deferrals" forgot a to update some two sites where the call was used. The static codechecks quickly found them. Reported-by: Dan Carpenter Fixes: 66feeec93221 ("RFC: ASoC: dapm: handle probe deferrals") Signed-off-by: Linus Walleij Signed-off-by: Mark Brown Signed-off-by: Sasha Levin --- sound/soc/soc-dapm.c | 20 1 file changed, 20 insertions(+) diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c index df036afb2197..6a438a361592 100644 --- a/sound/soc/soc-dapm.c +++ b/sound/soc/soc-dapm.c @@ -3794,6 +3794,16 @@ int snd_soc_dapm_new_dai_widgets(struct snd_soc_dapm_context *dapm, template.name); w = snd_soc_dapm_new_control_unlocked(dapm, ); + if (IS_ERR(w)) { + int ret = PTR_ERR(w); + + /* Do not nag about probe deferrals */ + if (ret != -EPROBE_DEFER) + dev_err(dapm->dev, + "ASoC: Failed to create %s widget (%d)\n", + dai->driver->playback.stream_name, ret); + return ret; + } if (!w) { dev_err(dapm->dev, "ASoC: Failed to create %s widget\n", dai->driver->playback.stream_name); @@ -3813,6 +3823,16 @@ int snd_soc_dapm_new_dai_widgets(struct snd_soc_dapm_context *dapm, template.name); w = snd_soc_dapm_new_control_unlocked(dapm, ); + if (IS_ERR(w)) { + int ret = PTR_ERR(w); + + /* Do not nag about probe deferrals */ + if (ret != -EPROBE_DEFER) + dev_err(dapm->dev, + "ASoC: Failed to create %s widget (%d)\n", + dai->driver->playback.stream_name, ret); + return ret; + } if (!w) { dev_err(dapm->dev, "ASoC: Failed to create %s widget\n", dai->driver->capture.stream_name); -- 2.11.0
[PATCH review for 4.4 26/47] ASoC: dapm: handle probe deferrals
From: Linus Walleij [ Upstream commit 37e1df8c95e2c8a57c77eafc097648f6e40a60ff ] This starts to handle probe deferrals on regulators and clocks on the ASoC DAPM. I came to this patch after audio stopped working on Ux500 ages ago and I finally looked into it to see what is wrong. I had messages like this in the console since a while back: ab8500-codec.0: ASoC: Failed to request audioclk: -517 ab8500-codec.0: ASoC: Failed to create DAPM control audioclk ab8500-codec.0: Failed to create new controls -12 snd-soc-mop500.0: ASoC: failed to instantiate card -12 snd-soc-mop500.0: Error: snd_soc_register_card failed (-12)! snd-soc-mop500: probe of snd-soc-mop500.0 failed with error -12 Apparently because the widget table for the codec looks like this (sound/soc/codecs/ab8500-codec.c): static const struct snd_soc_dapm_widget ab8500_dapm_widgets[] = { /* Clocks */ SND_SOC_DAPM_CLOCK_SUPPLY("audioclk"), /* Regulators */ SND_SOC_DAPM_REGULATOR_SUPPLY("V-AUD", 0, 0), SND_SOC_DAPM_REGULATOR_SUPPLY("V-AMIC1", 0, 0), SND_SOC_DAPM_REGULATOR_SUPPLY("V-AMIC2", 0, 0), SND_SOC_DAPM_REGULATOR_SUPPLY("V-DMIC", 0, 0), So when we call snd_soc_register_codec() and any of these widgets get a deferred probe we do not get an -EPROBE_DEFER (-517) back as we should and instead we just fail. Apparently the code assumes that clocks and regulators must be available at this point and not defer. After this patch it rather looks like this: ab8500-codec.0: Failed to create new controls -517 snd-soc-mop500.0: ASoC: failed to instantiate card -517 snd-soc-mop500.0: Error: snd_soc_register_card failed (-517)! (...) abx500-clk.0: registered clocks for ab850x snd-soc-mop500.0: ab8500-codec-dai.0 <-> ux500-msp-i2s.1 mapping ok snd-soc-mop500.0: ab8500-codec-dai.1 <-> ux500-msp-i2s.3 mapping ok I'm pretty happy about the patch as it it, but I'm a bit uncertain on how to proceed: there are a lot of users of the external functions snd_soc_dapm_new_control() (111 sites) and that will now return an occassional error pointer, which is not handled in the calling sites. I want an indication from the maintainers whether I should just go in and augment all these call sites, or if deferred probe is frowned upon when it leads to this much overhead. Signed-off-by: Linus Walleij Signed-off-by: Mark Brown Signed-off-by: Sasha Levin --- sound/soc/soc-dapm.c | 42 ++ sound/soc/soc-topology.c | 9 + 2 files changed, 51 insertions(+) diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c index b8a256dfed7e..df036afb2197 100644 --- a/sound/soc/soc-dapm.c +++ b/sound/soc/soc-dapm.c @@ -358,6 +358,10 @@ static int dapm_kcontrol_data_alloc(struct snd_soc_dapm_widget *widget, snd_soc_dapm_new_control_unlocked(widget->dapm, ); kfree(name); + if (IS_ERR(data->widget)) { + ret = PTR_ERR(data->widget); + goto err_data; + } if (!data->widget) { ret = -ENOMEM; goto err_data; @@ -392,6 +396,10 @@ static int dapm_kcontrol_data_alloc(struct snd_soc_dapm_widget *widget, data->widget = snd_soc_dapm_new_control_unlocked( widget->dapm, ); kfree(name); + if (IS_ERR(data->widget)) { + ret = PTR_ERR(data->widget); + goto err_data; + } if (!data->widget) { ret = -ENOMEM; goto err_data; @@ -3278,11 +3286,22 @@ snd_soc_dapm_new_control(struct snd_soc_dapm_context *dapm, mutex_lock_nested(>card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME); w = snd_soc_dapm_new_control_unlocked(dapm, widget); + /* Do not nag about probe deferrals */ + if (IS_ERR(w)) { + int ret = PTR_ERR(w); + + if (ret != -EPROBE_DEFER) + dev_err(dapm->dev, + "ASoC: Failed to create DAPM control %s (%d)\n", + widget->name, ret); + goto out_unlock; + } if (!w) dev_err(dapm->dev, "ASoC: Failed to create DAPM control %s\n", widget->name); +out_unlock: mutex_unlock(>card->dapm_mutex); return w; } @@ -3304,6 +3323,8 @@ snd_soc_dapm_new_control_unlocked(struct snd_soc_dapm_context *dapm, w->regulator = devm_regulator_get(dapm->dev, w->name); if (IS_ERR(w->regulator)) { ret = PTR_ERR(w->regulator); + if (ret ==
[PATCH review for 4.4 38/47] MIPS: IRQ Stack: Unwind IRQ stack onto task stack
From: Matt Redfearn[ Upstream commit db8466c581cca1a08b505f1319c3ecd246f16fa8 ] When the separate IRQ stack was introduced, stack unwinding only proceeded as far as the top of the IRQ stack, leading to kernel backtraces being less useful, lacking the trace of what was interrupted. Fix this by providing a means for the kernel to unwind the IRQ stack onto the interrupted task stack. The processor state is saved to the kernel task stack on interrupt. The IRQ_STACK_START macro reserves an unsigned long at the top of the IRQ stack where the interrupted task stack pointer can be saved. After the active stack is switched to the IRQ stack, save the interrupted tasks stack pointer to the reserved location. Fix the stack unwinding code to look for the frame being the top of the IRQ stack and if so get the next frame from the saved location. The existing test does not work with the separate stack since the ra is no longer pointed at ret_from_{irq,exception}. The test to stop unwinding the stack 32 bytes from the top of a stack must be modified to allow unwinding to continue up to the location of the saved task stack pointer when on the IRQ stack. The low / high marks of the stack are set depending on whether the sp is on an irq stack or not. Signed-off-by: Matt Redfearn Cc: Paolo Bonzini Cc: Marcin Nowakowski Cc: Masanari Iida Cc: Chris Metcalf Cc: James Hogan Cc: Paul Burton Cc: Ingo Molnar Cc: Jason A. Donenfeld Cc: Andrew Morton Cc: linux-m...@linux-mips.org Cc: linux-kernel@vger.kernel.org Patchwork: https://patchwork.linux-mips.org/patch/15788/ Signed-off-by: Ralf Baechle Signed-off-by: Sasha Levin --- arch/mips/include/asm/irq.h| 15 +++ arch/mips/kernel/asm-offsets.c | 1 + arch/mips/kernel/genex.S | 8 -- arch/mips/kernel/process.c | 56 -- 4 files changed, 60 insertions(+), 20 deletions(-) diff --git a/arch/mips/include/asm/irq.h b/arch/mips/include/asm/irq.h index ebb9efb02502..77edb22f855d 100644 --- a/arch/mips/include/asm/irq.h +++ b/arch/mips/include/asm/irq.h @@ -18,9 +18,24 @@ #include #define IRQ_STACK_SIZE THREAD_SIZE +#define IRQ_STACK_START(IRQ_STACK_SIZE - sizeof(unsigned long)) extern void *irq_stack[NR_CPUS]; +/* + * The highest address on the IRQ stack contains a dummy frame put down in + * genex.S (handle_int & except_vec_vi_handler) which is structured as follows: + * + * top + * | task sp | <- irq_stack[cpu] + IRQ_STACK_START + * + * | | <- First frame of IRQ context + * + * + * task sp holds a copy of the task stack pointer where the struct pt_regs + * from exception entry can be found. + */ + static inline bool on_irq_stack(int cpu, unsigned long sp) { unsigned long low = (unsigned long)irq_stack[cpu]; diff --git a/arch/mips/kernel/asm-offsets.c b/arch/mips/kernel/asm-offsets.c index ec053ce7bb38..7ab8004c1659 100644 --- a/arch/mips/kernel/asm-offsets.c +++ b/arch/mips/kernel/asm-offsets.c @@ -102,6 +102,7 @@ void output_thread_info_defines(void) DEFINE(_THREAD_SIZE, THREAD_SIZE); DEFINE(_THREAD_MASK, THREAD_MASK); DEFINE(_IRQ_STACK_SIZE, IRQ_STACK_SIZE); + DEFINE(_IRQ_STACK_START, IRQ_STACK_START); BLANK(); } diff --git a/arch/mips/kernel/genex.S b/arch/mips/kernel/genex.S index 619e30e2c4f0..bb72f3ce7e29 100644 --- a/arch/mips/kernel/genex.S +++ b/arch/mips/kernel/genex.S @@ -216,9 +216,11 @@ NESTED(handle_int, PT_SIZE, sp) beq t0, t1, 2f /* Switch to IRQ stack */ - li t1, _IRQ_STACK_SIZE + li t1, _IRQ_STACK_START PTR_ADD sp, t0, t1 + /* Save task's sp on IRQ stack so that unwinding can follow it */ + LONG_S s1, 0(sp) 2: jal plat_irq_dispatch @@ -326,9 +328,11 @@ NESTED(except_vec_vi_handler, 0, sp) beq t0, t1, 2f /* Switch to IRQ stack */ - li t1, _IRQ_STACK_SIZE + li t1, _IRQ_STACK_START PTR_ADD sp, t0, t1 + /* Save task's sp on IRQ stack so that unwinding can follow it */ + LONG_S s1, 0(sp) 2: jalrv0 diff --git a/arch/mips/kernel/process.c b/arch/mips/kernel/process.c index 8c26ecac930d..477ba026c3e5 100644 --- a/arch/mips/kernel/process.c +++ b/arch/mips/kernel/process.c @@ -483,31 +483,52 @@ unsigned long notrace unwind_stack_by_address(unsigned long stack_page, unsigned long pc, unsigned long *ra) { + unsigned long low, high, irq_stack_high; struct
[PATCH review for 4.4 38/47] MIPS: IRQ Stack: Unwind IRQ stack onto task stack
From: Matt Redfearn [ Upstream commit db8466c581cca1a08b505f1319c3ecd246f16fa8 ] When the separate IRQ stack was introduced, stack unwinding only proceeded as far as the top of the IRQ stack, leading to kernel backtraces being less useful, lacking the trace of what was interrupted. Fix this by providing a means for the kernel to unwind the IRQ stack onto the interrupted task stack. The processor state is saved to the kernel task stack on interrupt. The IRQ_STACK_START macro reserves an unsigned long at the top of the IRQ stack where the interrupted task stack pointer can be saved. After the active stack is switched to the IRQ stack, save the interrupted tasks stack pointer to the reserved location. Fix the stack unwinding code to look for the frame being the top of the IRQ stack and if so get the next frame from the saved location. The existing test does not work with the separate stack since the ra is no longer pointed at ret_from_{irq,exception}. The test to stop unwinding the stack 32 bytes from the top of a stack must be modified to allow unwinding to continue up to the location of the saved task stack pointer when on the IRQ stack. The low / high marks of the stack are set depending on whether the sp is on an irq stack or not. Signed-off-by: Matt Redfearn Cc: Paolo Bonzini Cc: Marcin Nowakowski Cc: Masanari Iida Cc: Chris Metcalf Cc: James Hogan Cc: Paul Burton Cc: Ingo Molnar Cc: Jason A. Donenfeld Cc: Andrew Morton Cc: linux-m...@linux-mips.org Cc: linux-kernel@vger.kernel.org Patchwork: https://patchwork.linux-mips.org/patch/15788/ Signed-off-by: Ralf Baechle Signed-off-by: Sasha Levin --- arch/mips/include/asm/irq.h| 15 +++ arch/mips/kernel/asm-offsets.c | 1 + arch/mips/kernel/genex.S | 8 -- arch/mips/kernel/process.c | 56 -- 4 files changed, 60 insertions(+), 20 deletions(-) diff --git a/arch/mips/include/asm/irq.h b/arch/mips/include/asm/irq.h index ebb9efb02502..77edb22f855d 100644 --- a/arch/mips/include/asm/irq.h +++ b/arch/mips/include/asm/irq.h @@ -18,9 +18,24 @@ #include #define IRQ_STACK_SIZE THREAD_SIZE +#define IRQ_STACK_START(IRQ_STACK_SIZE - sizeof(unsigned long)) extern void *irq_stack[NR_CPUS]; +/* + * The highest address on the IRQ stack contains a dummy frame put down in + * genex.S (handle_int & except_vec_vi_handler) which is structured as follows: + * + * top + * | task sp | <- irq_stack[cpu] + IRQ_STACK_START + * + * | | <- First frame of IRQ context + * + * + * task sp holds a copy of the task stack pointer where the struct pt_regs + * from exception entry can be found. + */ + static inline bool on_irq_stack(int cpu, unsigned long sp) { unsigned long low = (unsigned long)irq_stack[cpu]; diff --git a/arch/mips/kernel/asm-offsets.c b/arch/mips/kernel/asm-offsets.c index ec053ce7bb38..7ab8004c1659 100644 --- a/arch/mips/kernel/asm-offsets.c +++ b/arch/mips/kernel/asm-offsets.c @@ -102,6 +102,7 @@ void output_thread_info_defines(void) DEFINE(_THREAD_SIZE, THREAD_SIZE); DEFINE(_THREAD_MASK, THREAD_MASK); DEFINE(_IRQ_STACK_SIZE, IRQ_STACK_SIZE); + DEFINE(_IRQ_STACK_START, IRQ_STACK_START); BLANK(); } diff --git a/arch/mips/kernel/genex.S b/arch/mips/kernel/genex.S index 619e30e2c4f0..bb72f3ce7e29 100644 --- a/arch/mips/kernel/genex.S +++ b/arch/mips/kernel/genex.S @@ -216,9 +216,11 @@ NESTED(handle_int, PT_SIZE, sp) beq t0, t1, 2f /* Switch to IRQ stack */ - li t1, _IRQ_STACK_SIZE + li t1, _IRQ_STACK_START PTR_ADD sp, t0, t1 + /* Save task's sp on IRQ stack so that unwinding can follow it */ + LONG_S s1, 0(sp) 2: jal plat_irq_dispatch @@ -326,9 +328,11 @@ NESTED(except_vec_vi_handler, 0, sp) beq t0, t1, 2f /* Switch to IRQ stack */ - li t1, _IRQ_STACK_SIZE + li t1, _IRQ_STACK_START PTR_ADD sp, t0, t1 + /* Save task's sp on IRQ stack so that unwinding can follow it */ + LONG_S s1, 0(sp) 2: jalrv0 diff --git a/arch/mips/kernel/process.c b/arch/mips/kernel/process.c index 8c26ecac930d..477ba026c3e5 100644 --- a/arch/mips/kernel/process.c +++ b/arch/mips/kernel/process.c @@ -483,31 +483,52 @@ unsigned long notrace unwind_stack_by_address(unsigned long stack_page, unsigned long pc, unsigned long *ra) { + unsigned long low, high, irq_stack_high; struct mips_frame_info info; unsigned long size, ofs; + struct pt_regs *regs; int leaf; - extern void ret_from_irq(void); - extern void ret_from_exception(void); if (!stack_page) return 0; /* -* If we reached the bottom of interrupt
[PATCH review for 4.4 33/47] team: fix memory leaks
From: Pan Bian[ Upstream commit 72ec0bc64b9a5d8e0efcb717abfc757746b101b7 ] In functions team_nl_send_port_list_get() and team_nl_send_options_get(), pointer skb keeps the return value of nlmsg_new(). When the call to genlmsg_put() fails, the memory is not freed(). This will result in memory leak bugs. Fixes: 9b00cf2d1024 ("team: implement multipart netlink messages for options transfers") Signed-off-by: Pan Bian Acked-by: Jiri Pirko Signed-off-by: David S. Miller Signed-off-by: Sasha Levin --- drivers/net/team/team.c | 8 ++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/drivers/net/team/team.c b/drivers/net/team/team.c index a5f392ae30d5..61cd53838360 100644 --- a/drivers/net/team/team.c +++ b/drivers/net/team/team.c @@ -2343,8 +2343,10 @@ start_again: hdr = genlmsg_put(skb, portid, seq, _nl_family, flags | NLM_F_MULTI, TEAM_CMD_OPTIONS_GET); - if (!hdr) + if (!hdr) { + nlmsg_free(skb); return -EMSGSIZE; + } if (nla_put_u32(skb, TEAM_ATTR_TEAM_IFINDEX, team->dev->ifindex)) goto nla_put_failure; @@ -2611,8 +2613,10 @@ start_again: hdr = genlmsg_put(skb, portid, seq, _nl_family, flags | NLM_F_MULTI, TEAM_CMD_PORT_LIST_GET); - if (!hdr) + if (!hdr) { + nlmsg_free(skb); return -EMSGSIZE; + } if (nla_put_u32(skb, TEAM_ATTR_TEAM_IFINDEX, team->dev->ifindex)) goto nla_put_failure; -- 2.11.0
[PATCH review for 4.4 33/47] team: fix memory leaks
From: Pan Bian [ Upstream commit 72ec0bc64b9a5d8e0efcb717abfc757746b101b7 ] In functions team_nl_send_port_list_get() and team_nl_send_options_get(), pointer skb keeps the return value of nlmsg_new(). When the call to genlmsg_put() fails, the memory is not freed(). This will result in memory leak bugs. Fixes: 9b00cf2d1024 ("team: implement multipart netlink messages for options transfers") Signed-off-by: Pan Bian Acked-by: Jiri Pirko Signed-off-by: David S. Miller Signed-off-by: Sasha Levin --- drivers/net/team/team.c | 8 ++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/drivers/net/team/team.c b/drivers/net/team/team.c index a5f392ae30d5..61cd53838360 100644 --- a/drivers/net/team/team.c +++ b/drivers/net/team/team.c @@ -2343,8 +2343,10 @@ start_again: hdr = genlmsg_put(skb, portid, seq, _nl_family, flags | NLM_F_MULTI, TEAM_CMD_OPTIONS_GET); - if (!hdr) + if (!hdr) { + nlmsg_free(skb); return -EMSGSIZE; + } if (nla_put_u32(skb, TEAM_ATTR_TEAM_IFINDEX, team->dev->ifindex)) goto nla_put_failure; @@ -2611,8 +2613,10 @@ start_again: hdr = genlmsg_put(skb, portid, seq, _nl_family, flags | NLM_F_MULTI, TEAM_CMD_PORT_LIST_GET); - if (!hdr) + if (!hdr) { + nlmsg_free(skb); return -EMSGSIZE; + } if (nla_put_u32(skb, TEAM_ATTR_TEAM_IFINDEX, team->dev->ifindex)) goto nla_put_failure; -- 2.11.0