Re: [PATCH v1] DMA:omap-dma:Avoid build error by changing the function name
On 2017-12-18 07:29, Vinod Koul wrote: > On Tue, Dec 12, 2017 at 12:58:41PM +0530, venkat.prashanth2...@gmail.com > wrote: >> From: Venkat Prashanth B U>> >> Change the name of the function omap_dma_filter_fn to avoid >> the following build error in linux kernel version 4.4 : >> >> drivers/dma/dma-omap.c:1273:6: error: >> redefinition of 'omap_dma_filter_fn' What is your config regarding to omap_dma? in the include/linux/omap-dmaengine.h : #if defined(CONFIG_DMA_OMAP) || (defined(CONFIG_DMA_OMAP_MODULE) && defined(MODULE)) bool omap_dma_filter_fn(struct dma_chan *, void *); #else static inline bool omap_dma_filter_fn(struct dma_chan *c, void *d) { return false; } #endif DMA_OMAP enables the build of drivers/dma/omap-dma.c > > Okay I do not see this error, which tree are you running? I have not seen this either, and looking at the code I don't think it is possible. Not with what we have upstream. > In code is see omap_dma_filter_fn is used everywhere and no reference to > omap_dma_filter_func > > Adding peter too.. > > >> >> Signed-off-by: Venkat Prashanth B U >> Changes for v1: >> - Edited subject and description of the patch to fit with the change >> done in the code base, as suggested by Vinod Koul. >> >> - In order to avoid issues like backporting on stable the >> checkpatch.pl issues are dropped as suggested by Vinod Koul. >> --- >> drivers/dma/omap-dma.c | 2 +- >> 1 file changed, 1 insertion(+), 1 deletion(-) >> >> diff --git a/drivers/dma/omap-dma.c b/drivers/dma/omap-dma.c >> index 1dfc71c..8545dda 100644 >> --- a/drivers/dma/omap-dma.c >> +++ b/drivers/dma/omap-dma.c >> @@ -1269,7 +1269,7 @@ static struct platform_driver omap_dma_driver = { >> }, >> }; >> >> -bool omap_dma_filter_fn(struct dma_chan *chan, void *param) >> +bool omap_dma_filter_func(struct dma_chan *chan, void *param) this certainly breaks the omap_dma driver on non DT booted systems. >> { >> if (chan->device->dev->driver == _dma_driver.driver) { >> struct omap_dmadev *od = to_omap_dma_dev(chan->device); >> -- >> 1.9.1 >> -- >> To unsubscribe from this list: send the line "unsubscribe dmaengine" in >> the body of a message to majord...@vger.kernel.org >> More majordomo info at http://vger.kernel.org/majordomo-info.html > - Péter Texas Instruments Finland Oy, Porkkalankatu 22, 00180 Helsinki. Y-tunnus/Business ID: 0615521-4. Kotipaikka/Domicile: Helsinki
Re: [PATCH v1] DMA:omap-dma:Avoid build error by changing the function name
On 2017-12-18 07:29, Vinod Koul wrote: > On Tue, Dec 12, 2017 at 12:58:41PM +0530, venkat.prashanth2...@gmail.com > wrote: >> From: Venkat Prashanth B U >> >> Change the name of the function omap_dma_filter_fn to avoid >> the following build error in linux kernel version 4.4 : >> >> drivers/dma/dma-omap.c:1273:6: error: >> redefinition of 'omap_dma_filter_fn' What is your config regarding to omap_dma? in the include/linux/omap-dmaengine.h : #if defined(CONFIG_DMA_OMAP) || (defined(CONFIG_DMA_OMAP_MODULE) && defined(MODULE)) bool omap_dma_filter_fn(struct dma_chan *, void *); #else static inline bool omap_dma_filter_fn(struct dma_chan *c, void *d) { return false; } #endif DMA_OMAP enables the build of drivers/dma/omap-dma.c > > Okay I do not see this error, which tree are you running? I have not seen this either, and looking at the code I don't think it is possible. Not with what we have upstream. > In code is see omap_dma_filter_fn is used everywhere and no reference to > omap_dma_filter_func > > Adding peter too.. > > >> >> Signed-off-by: Venkat Prashanth B U >> Changes for v1: >> - Edited subject and description of the patch to fit with the change >> done in the code base, as suggested by Vinod Koul. >> >> - In order to avoid issues like backporting on stable the >> checkpatch.pl issues are dropped as suggested by Vinod Koul. >> --- >> drivers/dma/omap-dma.c | 2 +- >> 1 file changed, 1 insertion(+), 1 deletion(-) >> >> diff --git a/drivers/dma/omap-dma.c b/drivers/dma/omap-dma.c >> index 1dfc71c..8545dda 100644 >> --- a/drivers/dma/omap-dma.c >> +++ b/drivers/dma/omap-dma.c >> @@ -1269,7 +1269,7 @@ static struct platform_driver omap_dma_driver = { >> }, >> }; >> >> -bool omap_dma_filter_fn(struct dma_chan *chan, void *param) >> +bool omap_dma_filter_func(struct dma_chan *chan, void *param) this certainly breaks the omap_dma driver on non DT booted systems. >> { >> if (chan->device->dev->driver == _dma_driver.driver) { >> struct omap_dmadev *od = to_omap_dma_dev(chan->device); >> -- >> 1.9.1 >> -- >> To unsubscribe from this list: send the line "unsubscribe dmaengine" in >> the body of a message to majord...@vger.kernel.org >> More majordomo info at http://vger.kernel.org/majordomo-info.html > - Péter Texas Instruments Finland Oy, Porkkalankatu 22, 00180 Helsinki. Y-tunnus/Business ID: 0615521-4. Kotipaikka/Domicile: Helsinki
Re: [PATCH 4/5] arm: dts: sun8i: a83t: Add support for the ir interface
On Sun, Dec 17, 2017 at 11:45:46PM +0100, Philipp Rossak wrote: > The ir interface is like on the H3 located at 0x01f02000 and is exactly > the same. This patch adds support for the ir interface on the A83T. > > Signed-off-by: Philipp Rossak> --- > arch/arm/boot/dts/sun8i-a83t.dtsi | 10 ++ > 1 file changed, 10 insertions(+) > > diff --git a/arch/arm/boot/dts/sun8i-a83t.dtsi > b/arch/arm/boot/dts/sun8i-a83t.dtsi > index 954c2393325f..9e7ed3b9a6b8 100644 > --- a/arch/arm/boot/dts/sun8i-a83t.dtsi > +++ b/arch/arm/boot/dts/sun8i-a83t.dtsi > @@ -503,6 +503,16 @@ > #reset-cells = <1>; > }; > > + ir: ir@01f02000 { > + compatible = "allwinner,sun5i-a13-ir"; > + clocks = <_ccu CLK_APB0_IR>, <_ccu CLK_IR>; > + clock-names = "apb", "ir"; > + resets = <_ccu RST_APB0_IR>; > + interrupts = ; > + reg = <0x01f02000 0x40>; The size should be the size of the whole memory block, not just the registers you need. Maxime -- Maxime Ripard, Free Electrons Embedded Linux and Kernel engineering http://free-electrons.com signature.asc Description: PGP signature
Re: [PATCH 4/5] arm: dts: sun8i: a83t: Add support for the ir interface
On Sun, Dec 17, 2017 at 11:45:46PM +0100, Philipp Rossak wrote: > The ir interface is like on the H3 located at 0x01f02000 and is exactly > the same. This patch adds support for the ir interface on the A83T. > > Signed-off-by: Philipp Rossak > --- > arch/arm/boot/dts/sun8i-a83t.dtsi | 10 ++ > 1 file changed, 10 insertions(+) > > diff --git a/arch/arm/boot/dts/sun8i-a83t.dtsi > b/arch/arm/boot/dts/sun8i-a83t.dtsi > index 954c2393325f..9e7ed3b9a6b8 100644 > --- a/arch/arm/boot/dts/sun8i-a83t.dtsi > +++ b/arch/arm/boot/dts/sun8i-a83t.dtsi > @@ -503,6 +503,16 @@ > #reset-cells = <1>; > }; > > + ir: ir@01f02000 { > + compatible = "allwinner,sun5i-a13-ir"; > + clocks = <_ccu CLK_APB0_IR>, <_ccu CLK_IR>; > + clock-names = "apb", "ir"; > + resets = <_ccu RST_APB0_IR>; > + interrupts = ; > + reg = <0x01f02000 0x40>; The size should be the size of the whole memory block, not just the registers you need. Maxime -- Maxime Ripard, Free Electrons Embedded Linux and Kernel engineering http://free-electrons.com signature.asc Description: PGP signature
Re: block: oopses on 4.13.*, 4.14.* and 4.15-rc2 (bisected)
On Sat, Dec 9, 2017 at 7:27 AM, Michele Ballabiowrote: > On Fri, 8 Dec 2017 13:08:37 -0700 > Jens Axboe wrote: > >> On 12/08/2017 08:38 AM, Michele Ballabio wrote: >> > Hi, >> > kernels 4.13.*, 4.14.* 4.15-rc2 crash on occasion, >> > especially on x86-32 systems. To trigger the problem, run as root: >> > >> > while true >> > do >> > /sbin/udevadm trigger --type=subsystems --action=change >> > /sbin/udevadm trigger --type=devices --action=change >> > /sbin/udevadm settle --timeout=120 >> > done >> > >> > (Thanks to Patrick Volkerding for the reproducer). >> > >> > Sometimes the kernel oopses immediately, sometimes a bit later >> > (less than five minutes). >> > >> > The bisection pointed to commit >> > caa4b02476e31fc7933d2138062f7f355d3cd8f7 (blk-map: call >> > blk_queue_bounce from blk_rq_append_bio). A revert fixes the >> > problem (tested on 4.13 and master). >> >> Thanks for your report - can you try the below patch? Totally >> untested... > > I applied the patch on master > (968edbd93c0cbb40ab48aca972392d377713a0c3), I tried two times to boot > the system but couldn't get to the shell. I found this in the log: Hi Michele, Please test the patches I sent out and see if it fixes your issue. In my environment the two just works fine. https://marc.info/?l=linux-block=151358285916762=2 -- Ming Lei
Re: [PATCH 2/5] media: dt: bindings: Update binding documentation for sunxi IR controller
Hi, On Sun, Dec 17, 2017 at 11:45:44PM +0100, Philipp Rossak wrote: > This patch updates documentation for Device-Tree bindings for sunxi IR > controller and adds the new optional property for the base clock > frequency. > > Signed-off-by: Philipp Rossak> --- > Documentation/devicetree/bindings/media/sunxi-ir.txt | 2 ++ > 1 file changed, 2 insertions(+) > > diff --git a/Documentation/devicetree/bindings/media/sunxi-ir.txt > b/Documentation/devicetree/bindings/media/sunxi-ir.txt > index 91648c569b1e..9f45bab07d6e 100644 > --- a/Documentation/devicetree/bindings/media/sunxi-ir.txt > +++ b/Documentation/devicetree/bindings/media/sunxi-ir.txt > @@ -11,6 +11,7 @@ Required properties: > Optional properties: > - linux,rc-map-name: see rc.txt file in the same directory. > - resets : phandle + reset specifier pair > +- clock-frequency : overrides the default base clock frequency (8 MHz) You're at least missing the unit one needs to use, but something like: IR Receiver clock frequency, in Hertz. Defaults to 8MHz if missing. Maxime -- Maxime Ripard, Free Electrons Embedded Linux and Kernel engineering http://free-electrons.com signature.asc Description: PGP signature
Re: block: oopses on 4.13.*, 4.14.* and 4.15-rc2 (bisected)
On Sat, Dec 9, 2017 at 7:27 AM, Michele Ballabio wrote: > On Fri, 8 Dec 2017 13:08:37 -0700 > Jens Axboe wrote: > >> On 12/08/2017 08:38 AM, Michele Ballabio wrote: >> > Hi, >> > kernels 4.13.*, 4.14.* 4.15-rc2 crash on occasion, >> > especially on x86-32 systems. To trigger the problem, run as root: >> > >> > while true >> > do >> > /sbin/udevadm trigger --type=subsystems --action=change >> > /sbin/udevadm trigger --type=devices --action=change >> > /sbin/udevadm settle --timeout=120 >> > done >> > >> > (Thanks to Patrick Volkerding for the reproducer). >> > >> > Sometimes the kernel oopses immediately, sometimes a bit later >> > (less than five minutes). >> > >> > The bisection pointed to commit >> > caa4b02476e31fc7933d2138062f7f355d3cd8f7 (blk-map: call >> > blk_queue_bounce from blk_rq_append_bio). A revert fixes the >> > problem (tested on 4.13 and master). >> >> Thanks for your report - can you try the below patch? Totally >> untested... > > I applied the patch on master > (968edbd93c0cbb40ab48aca972392d377713a0c3), I tried two times to boot > the system but couldn't get to the shell. I found this in the log: Hi Michele, Please test the patches I sent out and see if it fixes your issue. In my environment the two just works fine. https://marc.info/?l=linux-block=151358285916762=2 -- Ming Lei
Re: [PATCH 2/5] media: dt: bindings: Update binding documentation for sunxi IR controller
Hi, On Sun, Dec 17, 2017 at 11:45:44PM +0100, Philipp Rossak wrote: > This patch updates documentation for Device-Tree bindings for sunxi IR > controller and adds the new optional property for the base clock > frequency. > > Signed-off-by: Philipp Rossak > --- > Documentation/devicetree/bindings/media/sunxi-ir.txt | 2 ++ > 1 file changed, 2 insertions(+) > > diff --git a/Documentation/devicetree/bindings/media/sunxi-ir.txt > b/Documentation/devicetree/bindings/media/sunxi-ir.txt > index 91648c569b1e..9f45bab07d6e 100644 > --- a/Documentation/devicetree/bindings/media/sunxi-ir.txt > +++ b/Documentation/devicetree/bindings/media/sunxi-ir.txt > @@ -11,6 +11,7 @@ Required properties: > Optional properties: > - linux,rc-map-name: see rc.txt file in the same directory. > - resets : phandle + reset specifier pair > +- clock-frequency : overrides the default base clock frequency (8 MHz) You're at least missing the unit one needs to use, but something like: IR Receiver clock frequency, in Hertz. Defaults to 8MHz if missing. Maxime -- Maxime Ripard, Free Electrons Embedded Linux and Kernel engineering http://free-electrons.com signature.asc Description: PGP signature
Re: [PATCH -V3 -mm] mm, swap: Fix race between swapoff and some swap operations
"Huang, Ying"writes: > From: Huang Ying > > When the swapin is performed, after getting the swap entry information > from the page table, system will swap in the swap entry, without any > lock held to prevent the swap device from being swapoff. This may > cause the race like below, > > CPU 1 CPU 2 > - - > do_swap_page > swapin_readahead > __read_swap_cache_async > swapoff swapcache_prepare > p->swap_map = NULL __swap_duplicate > p->swap_map[?] /* !!! NULL pointer > access */ > > Because swapoff is usually done when system shutdown only, the race > may not hit many people in practice. But it is still a race need to > be fixed. > > To fix the race, get_swap_device() is added to check whether the > specified swap entry is valid in its swap device. If so, it will keep > the swap entry valid via preventing the swap device from being > swapoff, until put_swap_device() is called. > > Because swapoff() is very race code path, to make the normal path runs > as fast as possible, RCU instead of reference count is used to > implement get/put_swap_device(). From get_swap_device() to > put_swap_device(), the RCU read lock is held, so synchronize_rcu() in > swapoff() will wait until put_swap_device() is called. > > In addition to swap_map, cluster_info, etc. data structure in the > struct swap_info_struct, the swap cache radix tree will be freed after > swapoff, so this patch fixes the race between swap cache looking up > and swapoff too. > > Cc: Hugh Dickins > Cc: Paul E. McKenney > Cc: Minchan Kim > Cc: Johannes Weiner > Cc: Tim Chen > Cc: Shaohua Li > Cc: Mel Gorman > Cc: "Jérôme Glisse" > Cc: Michal Hocko > Cc: Andrea Arcangeli > Cc: David Rientjes > Cc: Rik van Riel > Cc: Jan Kara > Cc: Dave Jiang > Cc: Aaron Lu > Signed-off-by: "Huang, Ying" > > Changelog: > > v3: > > - Re-implemented with RCU to reduce the overhead of normal paths > > v2: > > - Re-implemented with SRCU to reduce the overhead of normal paths. > > - Avoid to check whether the swap device has been swapoff in > get_swap_device(). Because we can check the origin of the swap > entry to make sure the swap device hasn't bee swapoff. A version implemented via stop_machine() could be gotten via a small patch as below. If you still prefer stop_machine(), I can resend a version implemented with stop_machine(). And, it appears that if we replace smp_wmb() in _enable_swap_info() with stop_machine() in some way, we can avoid smp_rmb() in get_swap_device(). This can reduce overhead in normal path further. Can we get same effect with RCU? For example, use synchronize_rcu() instead of stop_machine()? Hi, Paul, can you help me on this? Best Regards, Huang, Ying 8<-- --- include/linux/swap.h | 2 +- mm/swapfile.c| 12 +--- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/include/linux/swap.h b/include/linux/swap.h index f7e8f26cf07f..1027169d5a04 100644 --- a/include/linux/swap.h +++ b/include/linux/swap.h @@ -475,7 +475,7 @@ extern struct swap_info_struct *get_swap_device(swp_entry_t entry); static inline void put_swap_device(struct swap_info_struct *si) { - rcu_read_unlock(); + preempt_enable(); } #else /* CONFIG_SWAP */ diff --git a/mm/swapfile.c b/mm/swapfile.c index ca7b4c5ebe34..feb13ce01045 100644 --- a/mm/swapfile.c +++ b/mm/swapfile.c @@ -38,6 +38,7 @@ #include #include #include +#include #include #include @@ -1125,7 +1126,7 @@ struct swap_info_struct *get_swap_device(swp_entry_t entry) goto bad_nofile; si = swap_info[type]; - rcu_read_lock(); + preempt_disable(); if (!(si->flags & SWP_VALID)) goto unlock_out; /* @@ -1143,7 +1144,7 @@ struct swap_info_struct *get_swap_device(swp_entry_t entry) out: return NULL; unlock_out: - rcu_read_unlock(); + preempt_enable(); return NULL; } @@ -2581,6 +2582,11 @@ bool has_usable_swap(void) return ret; } +static int swapoff_stop(void *arg) +{ + return 0; +} + SYSCALL_DEFINE1(swapoff, const char __user *, specialfile) { struct swap_info_struct *p = NULL; @@ -2677,7 +2683,7 @@ SYSCALL_DEFINE1(swapoff, const char __user *, specialfile) * wait for swap operations protected by get/put_swap_device() * to complete */
Re: [PATCH -V3 -mm] mm, swap: Fix race between swapoff and some swap operations
"Huang, Ying" writes: > From: Huang Ying > > When the swapin is performed, after getting the swap entry information > from the page table, system will swap in the swap entry, without any > lock held to prevent the swap device from being swapoff. This may > cause the race like below, > > CPU 1 CPU 2 > - - > do_swap_page > swapin_readahead > __read_swap_cache_async > swapoff swapcache_prepare > p->swap_map = NULL __swap_duplicate > p->swap_map[?] /* !!! NULL pointer > access */ > > Because swapoff is usually done when system shutdown only, the race > may not hit many people in practice. But it is still a race need to > be fixed. > > To fix the race, get_swap_device() is added to check whether the > specified swap entry is valid in its swap device. If so, it will keep > the swap entry valid via preventing the swap device from being > swapoff, until put_swap_device() is called. > > Because swapoff() is very race code path, to make the normal path runs > as fast as possible, RCU instead of reference count is used to > implement get/put_swap_device(). From get_swap_device() to > put_swap_device(), the RCU read lock is held, so synchronize_rcu() in > swapoff() will wait until put_swap_device() is called. > > In addition to swap_map, cluster_info, etc. data structure in the > struct swap_info_struct, the swap cache radix tree will be freed after > swapoff, so this patch fixes the race between swap cache looking up > and swapoff too. > > Cc: Hugh Dickins > Cc: Paul E. McKenney > Cc: Minchan Kim > Cc: Johannes Weiner > Cc: Tim Chen > Cc: Shaohua Li > Cc: Mel Gorman > Cc: "Jérôme Glisse" > Cc: Michal Hocko > Cc: Andrea Arcangeli > Cc: David Rientjes > Cc: Rik van Riel > Cc: Jan Kara > Cc: Dave Jiang > Cc: Aaron Lu > Signed-off-by: "Huang, Ying" > > Changelog: > > v3: > > - Re-implemented with RCU to reduce the overhead of normal paths > > v2: > > - Re-implemented with SRCU to reduce the overhead of normal paths. > > - Avoid to check whether the swap device has been swapoff in > get_swap_device(). Because we can check the origin of the swap > entry to make sure the swap device hasn't bee swapoff. A version implemented via stop_machine() could be gotten via a small patch as below. If you still prefer stop_machine(), I can resend a version implemented with stop_machine(). And, it appears that if we replace smp_wmb() in _enable_swap_info() with stop_machine() in some way, we can avoid smp_rmb() in get_swap_device(). This can reduce overhead in normal path further. Can we get same effect with RCU? For example, use synchronize_rcu() instead of stop_machine()? Hi, Paul, can you help me on this? Best Regards, Huang, Ying 8<-- --- include/linux/swap.h | 2 +- mm/swapfile.c| 12 +--- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/include/linux/swap.h b/include/linux/swap.h index f7e8f26cf07f..1027169d5a04 100644 --- a/include/linux/swap.h +++ b/include/linux/swap.h @@ -475,7 +475,7 @@ extern struct swap_info_struct *get_swap_device(swp_entry_t entry); static inline void put_swap_device(struct swap_info_struct *si) { - rcu_read_unlock(); + preempt_enable(); } #else /* CONFIG_SWAP */ diff --git a/mm/swapfile.c b/mm/swapfile.c index ca7b4c5ebe34..feb13ce01045 100644 --- a/mm/swapfile.c +++ b/mm/swapfile.c @@ -38,6 +38,7 @@ #include #include #include +#include #include #include @@ -1125,7 +1126,7 @@ struct swap_info_struct *get_swap_device(swp_entry_t entry) goto bad_nofile; si = swap_info[type]; - rcu_read_lock(); + preempt_disable(); if (!(si->flags & SWP_VALID)) goto unlock_out; /* @@ -1143,7 +1144,7 @@ struct swap_info_struct *get_swap_device(swp_entry_t entry) out: return NULL; unlock_out: - rcu_read_unlock(); + preempt_enable(); return NULL; } @@ -2581,6 +2582,11 @@ bool has_usable_swap(void) return ret; } +static int swapoff_stop(void *arg) +{ + return 0; +} + SYSCALL_DEFINE1(swapoff, const char __user *, specialfile) { struct swap_info_struct *p = NULL; @@ -2677,7 +2683,7 @@ SYSCALL_DEFINE1(swapoff, const char __user *, specialfile) * wait for swap operations protected by get/put_swap_device() * to complete */ - synchronize_rcu(); + stop_machine(swapoff_stop, NULL, cpu_online_mask); flush_work(>discard_work);
Re: [PATCH net-next v5 1/4] phylib: Add device reset delay support
Hi Rob, On 12/15/2017 11:17 PM, Rob Herring wrote: > On Mon, Dec 11, 2017 at 01:16:57PM +0100, Richard Leitner wrote: >> From: Richard Leitner>> >> Some PHYs need a minimum time after the reset gpio was asserted and/or >> deasserted. To ensure we meet these timing requirements add two new >> optional devicetree parameters for the phy: reset-delay-us and >> reset-post-delay-us. >> >> Signed-off-by: Richard Leitner >> Reviewed-by: Geert Uytterhoeven >> --- >> Documentation/devicetree/bindings/net/phy.txt | 10 ++ >> drivers/net/phy/mdio_device.c | 13 +++-- >> drivers/of/of_mdio.c | 4 >> include/linux/mdio.h | 2 ++ >> 4 files changed, 27 insertions(+), 2 deletions(-) >> >> diff --git a/Documentation/devicetree/bindings/net/phy.txt >> b/Documentation/devicetree/bindings/net/phy.txt >> index c05479f5ac7c..72860ce7f610 100644 >> --- a/Documentation/devicetree/bindings/net/phy.txt >> +++ b/Documentation/devicetree/bindings/net/phy.txt >> @@ -55,6 +55,12 @@ Optional Properties: >> >> - reset-gpios: The GPIO phandle and specifier for the PHY reset signal. >> >> +- reset-delay-us: Delay after the reset was asserted in microseconds. >> + If this property is missing the delay will be skipped. >> + >> +- reset-post-delay-us: Delay after the reset was deasserted in microseconds. >> + If this property is missing the delay will be skipped. > > I think these names could be clearer as to exactly what they mean. > Looking at existing properties with "reset-delay" there's a mixture of > definitions whether it is the assert time or the time after deassert. > > So I'd call these "reset-assert-us" and "reset-deassert-us". Ok, that would be fine with me, but are you sure that we should omit the "-delay" term completely? What would be the best approach to post this change (as the patchset was already merged to net-next)? A separate patch or a v6 of the complete patchset? > > Rob > regards;Richard.L
Re: [PATCH net-next v5 1/4] phylib: Add device reset delay support
Hi Rob, On 12/15/2017 11:17 PM, Rob Herring wrote: > On Mon, Dec 11, 2017 at 01:16:57PM +0100, Richard Leitner wrote: >> From: Richard Leitner >> >> Some PHYs need a minimum time after the reset gpio was asserted and/or >> deasserted. To ensure we meet these timing requirements add two new >> optional devicetree parameters for the phy: reset-delay-us and >> reset-post-delay-us. >> >> Signed-off-by: Richard Leitner >> Reviewed-by: Geert Uytterhoeven >> --- >> Documentation/devicetree/bindings/net/phy.txt | 10 ++ >> drivers/net/phy/mdio_device.c | 13 +++-- >> drivers/of/of_mdio.c | 4 >> include/linux/mdio.h | 2 ++ >> 4 files changed, 27 insertions(+), 2 deletions(-) >> >> diff --git a/Documentation/devicetree/bindings/net/phy.txt >> b/Documentation/devicetree/bindings/net/phy.txt >> index c05479f5ac7c..72860ce7f610 100644 >> --- a/Documentation/devicetree/bindings/net/phy.txt >> +++ b/Documentation/devicetree/bindings/net/phy.txt >> @@ -55,6 +55,12 @@ Optional Properties: >> >> - reset-gpios: The GPIO phandle and specifier for the PHY reset signal. >> >> +- reset-delay-us: Delay after the reset was asserted in microseconds. >> + If this property is missing the delay will be skipped. >> + >> +- reset-post-delay-us: Delay after the reset was deasserted in microseconds. >> + If this property is missing the delay will be skipped. > > I think these names could be clearer as to exactly what they mean. > Looking at existing properties with "reset-delay" there's a mixture of > definitions whether it is the assert time or the time after deassert. > > So I'd call these "reset-assert-us" and "reset-deassert-us". Ok, that would be fine with me, but are you sure that we should omit the "-delay" term completely? What would be the best approach to post this change (as the patchset was already merged to net-next)? A separate patch or a v6 of the complete patchset? > > Rob > regards;Richard.L
Re: Detecting RWF_NOWAIT support
On 12/18/2017 05:28 AM, Goldwyn Rodrigues wrote: On 12/16/2017 08:49 AM, Avi Kivity wrote: On 12/14/2017 09:15 PM, Goldwyn Rodrigues wrote: On 12/14/2017 11:38 AM, Avi Kivity wrote: I'm looking to add support for RWF_NOWAIT within a linux-aio iocb. Naturally, I need to detect at runtime whether the kernel support RWF_NOWAIT or not. The only method I could find was to issue an I/O with RWF_NOWAIT set, and look for errors. This is somewhat less than perfect: - from the error, I can't tell whether RWF_NOWAIT was the problem, or something else. If I enable a number of new features, I have to run through all combinations to figure out which ones are supported and which are not. Here is the return codes for RWF_NOWAIT EINVAL - not supported (older kernel) EOPNOTSUPP - not supported EAGAIN - supported but could not complete because I/O will be delayed Which of these are returned from io_submit() and which are returned in the iocb? These are returned in iocb. Thanks. 0 - supported and I/O completed (success). - RWF_NOWAIT support is per-filesystem, so I can't just remember not to enable RWF_NOWAIT globally, I have to track it per file. Yes, the support is per filesystem. So, the application must know if the filesystem supports it, possibly by performing a small I/O. So the application must know about filesystem mount points, and be prepared to create a file and try to write it (in case the filesystem is empty) or alter its behavior during runtime depending on the errors it sees. Well yes. Hopefully, the application knows what it is doing when it performs RWF_NOWAIT. This type of interface makes it very hard to consume new kernel facilities in a backward compatible way. The kernel should advertise what support it provides; for example this support could be advertised via statx(2). For examples of facilities that advertise their capabilities, see membarrier(2) and KVM.
Re: Detecting RWF_NOWAIT support
On 12/18/2017 05:28 AM, Goldwyn Rodrigues wrote: On 12/16/2017 08:49 AM, Avi Kivity wrote: On 12/14/2017 09:15 PM, Goldwyn Rodrigues wrote: On 12/14/2017 11:38 AM, Avi Kivity wrote: I'm looking to add support for RWF_NOWAIT within a linux-aio iocb. Naturally, I need to detect at runtime whether the kernel support RWF_NOWAIT or not. The only method I could find was to issue an I/O with RWF_NOWAIT set, and look for errors. This is somewhat less than perfect: - from the error, I can't tell whether RWF_NOWAIT was the problem, or something else. If I enable a number of new features, I have to run through all combinations to figure out which ones are supported and which are not. Here is the return codes for RWF_NOWAIT EINVAL - not supported (older kernel) EOPNOTSUPP - not supported EAGAIN - supported but could not complete because I/O will be delayed Which of these are returned from io_submit() and which are returned in the iocb? These are returned in iocb. Thanks. 0 - supported and I/O completed (success). - RWF_NOWAIT support is per-filesystem, so I can't just remember not to enable RWF_NOWAIT globally, I have to track it per file. Yes, the support is per filesystem. So, the application must know if the filesystem supports it, possibly by performing a small I/O. So the application must know about filesystem mount points, and be prepared to create a file and try to write it (in case the filesystem is empty) or alter its behavior during runtime depending on the errors it sees. Well yes. Hopefully, the application knows what it is doing when it performs RWF_NOWAIT. This type of interface makes it very hard to consume new kernel facilities in a backward compatible way. The kernel should advertise what support it provides; for example this support could be advertised via statx(2). For examples of facilities that advertise their capabilities, see membarrier(2) and KVM.
Re: [PATCH V3 2/2] Xen/PCIback: Implement PCI flr/slot/bus reset with 'reset' SysFS attribute
>>> On 15.12.17 at 20:52,wrote: +static int pcistub_device_reset(struct pci_dev *dev) +{ + struct xen_pcibk_dev_data *dev_data; + bool slot = false, bus = false; + struct pcistub_args arg = {}; + + if (!dev) + return -EINVAL; + + dev_dbg(>dev, "[%s]\n", __func__); + + /* First check and try FLR */ + if (pcie_has_flr(dev)) { + dev_dbg(>dev, "resetting %s device using FLR\n", + pci_name(dev)); + pcie_flr(dev); >>> The lack of error check here puzzled me, but I see the function >>> indeed returns void right now. I think the prereq patch should >>> change this along with exporting the function - you really don't >>> want the device to be handed to a guest when the FLR timed >>> out. >> We will change pcie_flr() to return error code. I will make this change >> in the next version of this patch. > I exchanged some emails with Bjorn/Christoph and it looks like Christoph > as some planto restructure pcie flr specific functions but I don't know > the exact time-frame. For now,I am planning to use existing pcie_flr() > after checking FLR capability. We will switchto revised pcie_flr() once > it is available. > > I hope you are fine with this approach. Please let me know. Thanks. I've seen that other discussion. I don't think the change here should be done prior to the error reporting being put in place, for security reasons. But in the end it'll be Konrad as the maintainer to judge. Or wait, looks like there's some confusion in ./MAINTAINERS: Konrad is listed as maintainer for "XEN PCI SUBSYSTEM", but the list of files doesn't include pciback. So it would instead be Boris or Jürgen to give you a final word. Jan
Re: [PATCH V3 2/2] Xen/PCIback: Implement PCI flr/slot/bus reset with 'reset' SysFS attribute
>>> On 15.12.17 at 20:52, wrote: +static int pcistub_device_reset(struct pci_dev *dev) +{ + struct xen_pcibk_dev_data *dev_data; + bool slot = false, bus = false; + struct pcistub_args arg = {}; + + if (!dev) + return -EINVAL; + + dev_dbg(>dev, "[%s]\n", __func__); + + /* First check and try FLR */ + if (pcie_has_flr(dev)) { + dev_dbg(>dev, "resetting %s device using FLR\n", + pci_name(dev)); + pcie_flr(dev); >>> The lack of error check here puzzled me, but I see the function >>> indeed returns void right now. I think the prereq patch should >>> change this along with exporting the function - you really don't >>> want the device to be handed to a guest when the FLR timed >>> out. >> We will change pcie_flr() to return error code. I will make this change >> in the next version of this patch. > I exchanged some emails with Bjorn/Christoph and it looks like Christoph > as some planto restructure pcie flr specific functions but I don't know > the exact time-frame. For now,I am planning to use existing pcie_flr() > after checking FLR capability. We will switchto revised pcie_flr() once > it is available. > > I hope you are fine with this approach. Please let me know. Thanks. I've seen that other discussion. I don't think the change here should be done prior to the error reporting being put in place, for security reasons. But in the end it'll be Konrad as the maintainer to judge. Or wait, looks like there's some confusion in ./MAINTAINERS: Konrad is listed as maintainer for "XEN PCI SUBSYSTEM", but the list of files doesn't include pciback. So it would instead be Boris or Jürgen to give you a final word. Jan
[PATCH -V3 -mm] mm, swap: Fix race between swapoff and some swap operations
From: Huang YingWhen the swapin is performed, after getting the swap entry information from the page table, system will swap in the swap entry, without any lock held to prevent the swap device from being swapoff. This may cause the race like below, CPU 1 CPU 2 - - do_swap_page swapin_readahead __read_swap_cache_async swapoff swapcache_prepare p->swap_map = NULL__swap_duplicate p->swap_map[?] /* !!! NULL pointer access */ Because swapoff is usually done when system shutdown only, the race may not hit many people in practice. But it is still a race need to be fixed. To fix the race, get_swap_device() is added to check whether the specified swap entry is valid in its swap device. If so, it will keep the swap entry valid via preventing the swap device from being swapoff, until put_swap_device() is called. Because swapoff() is very race code path, to make the normal path runs as fast as possible, RCU instead of reference count is used to implement get/put_swap_device(). From get_swap_device() to put_swap_device(), the RCU read lock is held, so synchronize_rcu() in swapoff() will wait until put_swap_device() is called. In addition to swap_map, cluster_info, etc. data structure in the struct swap_info_struct, the swap cache radix tree will be freed after swapoff, so this patch fixes the race between swap cache looking up and swapoff too. Cc: Hugh Dickins Cc: Paul E. McKenney Cc: Minchan Kim Cc: Johannes Weiner Cc: Tim Chen Cc: Shaohua Li Cc: Mel Gorman Cc: "Jérôme Glisse" Cc: Michal Hocko Cc: Andrea Arcangeli Cc: David Rientjes Cc: Rik van Riel Cc: Jan Kara Cc: Dave Jiang Cc: Aaron Lu Signed-off-by: "Huang, Ying" Changelog: v3: - Re-implemented with RCU to reduce the overhead of normal paths v2: - Re-implemented with SRCU to reduce the overhead of normal paths. - Avoid to check whether the swap device has been swapoff in get_swap_device(). Because we can check the origin of the swap entry to make sure the swap device hasn't bee swapoff. --- include/linux/swap.h | 11 +- mm/memory.c | 2 +- mm/swap_state.c | 16 ++-- mm/swapfile.c| 105 +++ 4 files changed, 103 insertions(+), 31 deletions(-) diff --git a/include/linux/swap.h b/include/linux/swap.h index 2417d288e016..f7e8f26cf07f 100644 --- a/include/linux/swap.h +++ b/include/linux/swap.h @@ -172,8 +172,9 @@ enum { 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 */ + SWP_VALID = (1 << 12),/* swap is valid to be operated on? */ /* add others here before... */ - SWP_SCANNING= (1 << 12),/* refcount in scan_swap_map */ + SWP_SCANNING= (1 << 13),/* refcount in scan_swap_map */ }; #define SWAP_CLUSTER_MAX 32UL @@ -460,7 +461,7 @@ extern unsigned int count_swap_pages(int, int); extern sector_t map_swap_page(struct page *, struct block_device **); extern sector_t swapdev_block(int, pgoff_t); extern int page_swapcount(struct page *); -extern int __swap_count(struct swap_info_struct *si, swp_entry_t entry); +extern int __swap_count(swp_entry_t entry); 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 *); @@ -470,6 +471,12 @@ extern int try_to_free_swap(struct page *); struct backing_dev_info; extern int init_swap_address_space(unsigned int type, unsigned long nr_pages); extern void exit_swap_address_space(unsigned int type); +extern struct swap_info_struct *get_swap_device(swp_entry_t entry); + +static inline void put_swap_device(struct swap_info_struct *si) +{ + rcu_read_unlock(); +} #else /* CONFIG_SWAP */ diff --git a/mm/memory.c b/mm/memory.c index 1a969992f76b..77a7d6191218 100644 --- a/mm/memory.c +++ b/mm/memory.c @@ -2909,7 +2909,7 @@ int do_swap_page(struct vm_fault *vmf) struct swap_info_struct *si = swp_swap_info(entry); if (si->flags & SWP_SYNCHRONOUS_IO && - __swap_count(si, entry) == 1) { + __swap_count(entry) == 1) { /* skip swapcache */
[PATCH -V3 -mm] mm, swap: Fix race between swapoff and some swap operations
From: Huang Ying When the swapin is performed, after getting the swap entry information from the page table, system will swap in the swap entry, without any lock held to prevent the swap device from being swapoff. This may cause the race like below, CPU 1 CPU 2 - - do_swap_page swapin_readahead __read_swap_cache_async swapoff swapcache_prepare p->swap_map = NULL__swap_duplicate p->swap_map[?] /* !!! NULL pointer access */ Because swapoff is usually done when system shutdown only, the race may not hit many people in practice. But it is still a race need to be fixed. To fix the race, get_swap_device() is added to check whether the specified swap entry is valid in its swap device. If so, it will keep the swap entry valid via preventing the swap device from being swapoff, until put_swap_device() is called. Because swapoff() is very race code path, to make the normal path runs as fast as possible, RCU instead of reference count is used to implement get/put_swap_device(). From get_swap_device() to put_swap_device(), the RCU read lock is held, so synchronize_rcu() in swapoff() will wait until put_swap_device() is called. In addition to swap_map, cluster_info, etc. data structure in the struct swap_info_struct, the swap cache radix tree will be freed after swapoff, so this patch fixes the race between swap cache looking up and swapoff too. Cc: Hugh Dickins Cc: Paul E. McKenney Cc: Minchan Kim Cc: Johannes Weiner Cc: Tim Chen Cc: Shaohua Li Cc: Mel Gorman Cc: "Jérôme Glisse" Cc: Michal Hocko Cc: Andrea Arcangeli Cc: David Rientjes Cc: Rik van Riel Cc: Jan Kara Cc: Dave Jiang Cc: Aaron Lu Signed-off-by: "Huang, Ying" Changelog: v3: - Re-implemented with RCU to reduce the overhead of normal paths v2: - Re-implemented with SRCU to reduce the overhead of normal paths. - Avoid to check whether the swap device has been swapoff in get_swap_device(). Because we can check the origin of the swap entry to make sure the swap device hasn't bee swapoff. --- include/linux/swap.h | 11 +- mm/memory.c | 2 +- mm/swap_state.c | 16 ++-- mm/swapfile.c| 105 +++ 4 files changed, 103 insertions(+), 31 deletions(-) diff --git a/include/linux/swap.h b/include/linux/swap.h index 2417d288e016..f7e8f26cf07f 100644 --- a/include/linux/swap.h +++ b/include/linux/swap.h @@ -172,8 +172,9 @@ enum { 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 */ + SWP_VALID = (1 << 12),/* swap is valid to be operated on? */ /* add others here before... */ - SWP_SCANNING= (1 << 12),/* refcount in scan_swap_map */ + SWP_SCANNING= (1 << 13),/* refcount in scan_swap_map */ }; #define SWAP_CLUSTER_MAX 32UL @@ -460,7 +461,7 @@ extern unsigned int count_swap_pages(int, int); extern sector_t map_swap_page(struct page *, struct block_device **); extern sector_t swapdev_block(int, pgoff_t); extern int page_swapcount(struct page *); -extern int __swap_count(struct swap_info_struct *si, swp_entry_t entry); +extern int __swap_count(swp_entry_t entry); 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 *); @@ -470,6 +471,12 @@ extern int try_to_free_swap(struct page *); struct backing_dev_info; extern int init_swap_address_space(unsigned int type, unsigned long nr_pages); extern void exit_swap_address_space(unsigned int type); +extern struct swap_info_struct *get_swap_device(swp_entry_t entry); + +static inline void put_swap_device(struct swap_info_struct *si) +{ + rcu_read_unlock(); +} #else /* CONFIG_SWAP */ diff --git a/mm/memory.c b/mm/memory.c index 1a969992f76b..77a7d6191218 100644 --- a/mm/memory.c +++ b/mm/memory.c @@ -2909,7 +2909,7 @@ int do_swap_page(struct vm_fault *vmf) struct swap_info_struct *si = swp_swap_info(entry); if (si->flags & SWP_SYNCHRONOUS_IO && - __swap_count(si, entry) == 1) { + __swap_count(entry) == 1) { /* skip swapcache */ page = alloc_page_vma(GFP_HIGHUSER_MOVABLE, vma, vmf->address); diff --git a/mm/swap_state.c b/mm/swap_state.c index 0b8ae361981f..8dde719e973c 100644 --- a/mm/swap_state.c +++ b/mm/swap_state.c @@ -337,8 +337,13 @@ struct page *lookup_swap_cache(swp_entry_t entry, struct
Re: [PATCH] media: v4l: xilinx: Use SPDX-License-Identifier
Hi guys, On 15.12.2017 10:27, Mauro Carvalho Chehab wrote: > Em Fri, 15 Dec 2017 10:55:26 +0530 > Dhaval Shahescreveu: > >> Hi Laurent/Mauro/Greg, >> >> On Fri, Dec 15, 2017 at 3:32 AM, Laurent Pinchart >> wrote: >>> Hi Mauro, >>> >>> On Thursday, 14 December 2017 23:50:03 EET Mauro Carvalho Chehab wrote: Em Thu, 14 Dec 2017 21:57:06 +0100 Greg KH escreveu: > On Thu, Dec 14, 2017 at 10:44:16PM +0200, Laurent Pinchart wrote: >> On Thursday, 14 December 2017 22:08:51 EET Greg KH wrote: >>> On Thu, Dec 14, 2017 at 09:05:27PM +0200, Laurent Pinchart wrote: On Thursday, 14 December 2017 20:54:39 EET Joe Perches wrote: > On Thu, 2017-12-14 at 20:37 +0200, Laurent Pinchart wrote: >> On Thursday, 14 December 2017 20:32:20 EET Joe Perches wrote: >>> On Thu, 2017-12-14 at 20:28 +0200, Laurent Pinchart wrote: On Thursday, 14 December 2017 19:05:27 EET Mauro Carvalho Chehab wrote: > Em Fri, 8 Dec 2017 18:05:37 +0530 Dhaval Shah escreveu: >> SPDX-License-Identifier is used for the Xilinx Video IP and >> related drivers. >> >> Signed-off-by: Dhaval Shah > > Hi Dhaval, > > You're not listed as one of the Xilinx driver maintainers. I'm > afraid that, without their explicit acks, sent to the ML, I > can't accept a patch touching at the driver's license tags. The patch doesn't change the license, I don't see why it would cause any issue. Greg isn't listed as the maintainer or copyright holder of any of the 10k+ files to which he added an SPDX license header in the last kernel release. >>> >>> Adding a comment line that describes an implicit or >>> explicit license is different than removing the license >>> text itself. >> >> The SPDX license header is meant to be equivalent to the license >> text. > > I understand that. > At a minimum, removing BSD license text is undesirable > > as that license states: > ** Redistributions of source code must retain the above copyright > * notice, this list of conditions and the following disclaimer. > > etc... But this patch only removes the following text: - * 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. and replaces it by the corresponding SPDX header. >> The only reason why the large SPDX patch didn't touch the whole >> kernel in one go was that it was easier to split in in multiple >> chunks. > > Not really, it was scripted. But still manually reviewed as far as I know. >> This is no different than not including the full GPL license in >> every header file but only pointing to it through its name and >> reference, as every kernel source file does. > > Not every kernel source file had a license text > or a reference to another license file. Correct, but the files touched by this patch do. This issue is in no way specific to linux-media and should be decided upon at the top level, not on a per-subsystem basis. Greg, could you comment on this ? >>> >>> Comment on what exactly? I don't understand the problem here, care to >>> summarize it? >> >> In a nutshell (if I understand it correctly), Dhaval Shah submitted >> https:// patchwork.kernel.org/patch/10102451/ which replaces >> >> +// SPDX-License-Identifier: GPL-2.0 >> [...] >> - * >> - * 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. >> >> in all .c and .h files of the Xilinx V4L2 driver >> (drivers/media/platform/ >> xilinx). I have reviewed the patch and acked it. Mauro then rejected it, >> stating that he can't accept a change to license text without an >> explicit ack from the official driver's maintainers. My position is >> that such a change doesn't change the license and thus doesn't need to >> track all copyright holders, and can be merged without an explicit ack >> from the respective maintainers. > > Yes, I agree with you, no license is being changed here, and no > copyright is either. > > BUT, I know that most major companies are reviewing this process right > now. We have gotten
Re: [PATCH] media: v4l: xilinx: Use SPDX-License-Identifier
Hi guys, On 15.12.2017 10:27, Mauro Carvalho Chehab wrote: > Em Fri, 15 Dec 2017 10:55:26 +0530 > Dhaval Shah escreveu: > >> Hi Laurent/Mauro/Greg, >> >> On Fri, Dec 15, 2017 at 3:32 AM, Laurent Pinchart >> wrote: >>> Hi Mauro, >>> >>> On Thursday, 14 December 2017 23:50:03 EET Mauro Carvalho Chehab wrote: Em Thu, 14 Dec 2017 21:57:06 +0100 Greg KH escreveu: > On Thu, Dec 14, 2017 at 10:44:16PM +0200, Laurent Pinchart wrote: >> On Thursday, 14 December 2017 22:08:51 EET Greg KH wrote: >>> On Thu, Dec 14, 2017 at 09:05:27PM +0200, Laurent Pinchart wrote: On Thursday, 14 December 2017 20:54:39 EET Joe Perches wrote: > On Thu, 2017-12-14 at 20:37 +0200, Laurent Pinchart wrote: >> On Thursday, 14 December 2017 20:32:20 EET Joe Perches wrote: >>> On Thu, 2017-12-14 at 20:28 +0200, Laurent Pinchart wrote: On Thursday, 14 December 2017 19:05:27 EET Mauro Carvalho Chehab wrote: > Em Fri, 8 Dec 2017 18:05:37 +0530 Dhaval Shah escreveu: >> SPDX-License-Identifier is used for the Xilinx Video IP and >> related drivers. >> >> Signed-off-by: Dhaval Shah > > Hi Dhaval, > > You're not listed as one of the Xilinx driver maintainers. I'm > afraid that, without their explicit acks, sent to the ML, I > can't accept a patch touching at the driver's license tags. The patch doesn't change the license, I don't see why it would cause any issue. Greg isn't listed as the maintainer or copyright holder of any of the 10k+ files to which he added an SPDX license header in the last kernel release. >>> >>> Adding a comment line that describes an implicit or >>> explicit license is different than removing the license >>> text itself. >> >> The SPDX license header is meant to be equivalent to the license >> text. > > I understand that. > At a minimum, removing BSD license text is undesirable > > as that license states: > ** Redistributions of source code must retain the above copyright > * notice, this list of conditions and the following disclaimer. > > etc... But this patch only removes the following text: - * 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. and replaces it by the corresponding SPDX header. >> The only reason why the large SPDX patch didn't touch the whole >> kernel in one go was that it was easier to split in in multiple >> chunks. > > Not really, it was scripted. But still manually reviewed as far as I know. >> This is no different than not including the full GPL license in >> every header file but only pointing to it through its name and >> reference, as every kernel source file does. > > Not every kernel source file had a license text > or a reference to another license file. Correct, but the files touched by this patch do. This issue is in no way specific to linux-media and should be decided upon at the top level, not on a per-subsystem basis. Greg, could you comment on this ? >>> >>> Comment on what exactly? I don't understand the problem here, care to >>> summarize it? >> >> In a nutshell (if I understand it correctly), Dhaval Shah submitted >> https:// patchwork.kernel.org/patch/10102451/ which replaces >> >> +// SPDX-License-Identifier: GPL-2.0 >> [...] >> - * >> - * 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. >> >> in all .c and .h files of the Xilinx V4L2 driver >> (drivers/media/platform/ >> xilinx). I have reviewed the patch and acked it. Mauro then rejected it, >> stating that he can't accept a change to license text without an >> explicit ack from the official driver's maintainers. My position is >> that such a change doesn't change the license and thus doesn't need to >> track all copyright holders, and can be merged without an explicit ack >> from the respective maintainers. > > Yes, I agree with you, no license is being changed here, and no > copyright is either. > > BUT, I know that most major companies are reviewing this process right > now. We have gotten approval from almost all of the major kernel > developer companies to do this, which
Re: [PATCH] trace: reenable preemption if we modify the ip
On Fri, 15 Dec 2017 21:42:57 -0500 Josef Bacikwrote: > From: Josef Bacik > > Things got moved around between the original bpf_override_return patches > and the final version, and now the ftrace kprobe dispatcher assumes if > you modified the ip that you also enabled preemption. Make a comment of > this and enable preemption, this fixes the lockdep splat that happened > when using this feature. > > Signed-off-by: Josef Bacik > --- > kernel/trace/trace_kprobe.c | 9 - > 1 file changed, 8 insertions(+), 1 deletion(-) > > diff --git a/kernel/trace/trace_kprobe.c b/kernel/trace/trace_kprobe.c > index 5db849809a56..91f4b57dab82 100644 > --- a/kernel/trace/trace_kprobe.c > +++ b/kernel/trace/trace_kprobe.c > @@ -1322,8 +1322,15 @@ static int kprobe_dispatcher(struct kprobe *kp, struct > pt_regs *regs) > if (tk->tp.flags & TP_FLAG_TRACE) > kprobe_trace_func(tk, regs); > #ifdef CONFIG_PERF_EVENTS > - if (tk->tp.flags & TP_FLAG_PROFILE) > + if (tk->tp.flags & TP_FLAG_PROFILE) { > ret = kprobe_perf_func(tk, regs); > + /* > + * The ftrace kprobe handler leaves it up to us to re-enable > + * preemption here before returning if we've modified the ip. > + */ > + if (ret) > + preempt_enable_no_resched(); Where is reset_current_kprobe()? Since kprobes still expects this modification is used by jprobes, we need to call it in caller-side. Thank you, > + } > #endif > return ret; > } > -- > 2.7.5 > -- Masami Hiramatsu
Re: [PATCH] trace: reenable preemption if we modify the ip
On Fri, 15 Dec 2017 21:42:57 -0500 Josef Bacik wrote: > From: Josef Bacik > > Things got moved around between the original bpf_override_return patches > and the final version, and now the ftrace kprobe dispatcher assumes if > you modified the ip that you also enabled preemption. Make a comment of > this and enable preemption, this fixes the lockdep splat that happened > when using this feature. > > Signed-off-by: Josef Bacik > --- > kernel/trace/trace_kprobe.c | 9 - > 1 file changed, 8 insertions(+), 1 deletion(-) > > diff --git a/kernel/trace/trace_kprobe.c b/kernel/trace/trace_kprobe.c > index 5db849809a56..91f4b57dab82 100644 > --- a/kernel/trace/trace_kprobe.c > +++ b/kernel/trace/trace_kprobe.c > @@ -1322,8 +1322,15 @@ static int kprobe_dispatcher(struct kprobe *kp, struct > pt_regs *regs) > if (tk->tp.flags & TP_FLAG_TRACE) > kprobe_trace_func(tk, regs); > #ifdef CONFIG_PERF_EVENTS > - if (tk->tp.flags & TP_FLAG_PROFILE) > + if (tk->tp.flags & TP_FLAG_PROFILE) { > ret = kprobe_perf_func(tk, regs); > + /* > + * The ftrace kprobe handler leaves it up to us to re-enable > + * preemption here before returning if we've modified the ip. > + */ > + if (ret) > + preempt_enable_no_resched(); Where is reset_current_kprobe()? Since kprobes still expects this modification is used by jprobes, we need to call it in caller-side. Thank you, > + } > #endif > return ret; > } > -- > 2.7.5 > -- Masami Hiramatsu
[PATCH v4 01/36] asm-generic/io.h: move ioremap_nocache/ioremap_uc/ioremap_wc/ioremap_wt out of ifndef CONFIG_MMU
From: Greentime HuIt allows some architectures to use this generic macro instead of defining theirs. Signed-off-by: Vincent Chen Signed-off-by: Greentime Hu Acked-by: Arnd Bergmann --- include/asm-generic/io.h | 18 +- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/include/asm-generic/io.h b/include/asm-generic/io.h index b4531e3..7c6a39e 100644 --- a/include/asm-generic/io.h +++ b/include/asm-generic/io.h @@ -852,7 +852,16 @@ static inline void __iomem *__ioremap(phys_addr_t offset, size_t size, } #endif +#ifndef iounmap +#define iounmap iounmap + +static inline void iounmap(void __iomem *addr) +{ +} +#endif +#endif /* CONFIG_MMU */ #ifndef ioremap_nocache +void __iomem *ioremap(phys_addr_t phys_addr, size_t size); #define ioremap_nocache ioremap_nocache static inline void __iomem *ioremap_nocache(phys_addr_t offset, size_t size) { @@ -884,15 +893,6 @@ static inline void __iomem *ioremap_wt(phys_addr_t offset, size_t size) } #endif -#ifndef iounmap -#define iounmap iounmap - -static inline void iounmap(void __iomem *addr) -{ -} -#endif -#endif /* CONFIG_MMU */ - #ifdef CONFIG_HAS_IOPORT_MAP #ifndef CONFIG_GENERIC_IOMAP #ifndef ioport_map -- 1.7.9.5
[PATCH 2/2] perf-probe: Skip searching debuginfo if we know no debuginfo
Skip searching debuginfo if we have already searched and there is no debuginfo for given file. This also reduce debuginfo mismatch warnings for listing events on same binary. Signed-off-by: Masami Hiramatsu--- tools/perf/util/probe-finder.c | 16 +++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/tools/perf/util/probe-finder.c b/tools/perf/util/probe-finder.c index 5bb71e056b21..cafc3e5b9863 100644 --- a/tools/perf/util/probe-finder.c +++ b/tools/perf/util/probe-finder.c @@ -119,6 +119,8 @@ enum dso_binary_type distro_dwarf_types[] = { struct debuginfo *debuginfo__new(const char *path) { + static struct strlist *no_debuginfo_files; + u8 bid[BUILD_ID_SIZE], bid2[BUILD_ID_SIZE]; enum dso_binary_type *type; char buf[PATH_MAX], nil = '\0'; @@ -126,6 +128,12 @@ struct debuginfo *debuginfo__new(const char *path) bool have_build_id = false; struct debuginfo *dinfo = NULL; + /* Skip if we already know it has no debuginfo */ + if (!no_debuginfo_files) + no_debuginfo_files = strlist__new(NULL, NULL); + else if (strlist__find(no_debuginfo_files, path)) + return NULL; + /* Try to open distro debuginfo files */ dso = dso__new(path); if (!dso) @@ -159,7 +167,13 @@ struct debuginfo *debuginfo__new(const char *path) out: /* if failed to open all distro debuginfo, open given binary */ - return dinfo ? : __debuginfo__new(path); + if (!dinfo) { + dinfo = __debuginfo__new(path); + if (!dinfo) + strlist__add(no_debuginfo_files, path); + } + + return dinfo; } void debuginfo__delete(struct debuginfo *dbg)
[PATCH v4 01/36] asm-generic/io.h: move ioremap_nocache/ioremap_uc/ioremap_wc/ioremap_wt out of ifndef CONFIG_MMU
From: Greentime Hu It allows some architectures to use this generic macro instead of defining theirs. Signed-off-by: Vincent Chen Signed-off-by: Greentime Hu Acked-by: Arnd Bergmann --- include/asm-generic/io.h | 18 +- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/include/asm-generic/io.h b/include/asm-generic/io.h index b4531e3..7c6a39e 100644 --- a/include/asm-generic/io.h +++ b/include/asm-generic/io.h @@ -852,7 +852,16 @@ static inline void __iomem *__ioremap(phys_addr_t offset, size_t size, } #endif +#ifndef iounmap +#define iounmap iounmap + +static inline void iounmap(void __iomem *addr) +{ +} +#endif +#endif /* CONFIG_MMU */ #ifndef ioremap_nocache +void __iomem *ioremap(phys_addr_t phys_addr, size_t size); #define ioremap_nocache ioremap_nocache static inline void __iomem *ioremap_nocache(phys_addr_t offset, size_t size) { @@ -884,15 +893,6 @@ static inline void __iomem *ioremap_wt(phys_addr_t offset, size_t size) } #endif -#ifndef iounmap -#define iounmap iounmap - -static inline void iounmap(void __iomem *addr) -{ -} -#endif -#endif /* CONFIG_MMU */ - #ifdef CONFIG_HAS_IOPORT_MAP #ifndef CONFIG_GENERIC_IOMAP #ifndef ioport_map -- 1.7.9.5
[PATCH 2/2] perf-probe: Skip searching debuginfo if we know no debuginfo
Skip searching debuginfo if we have already searched and there is no debuginfo for given file. This also reduce debuginfo mismatch warnings for listing events on same binary. Signed-off-by: Masami Hiramatsu --- tools/perf/util/probe-finder.c | 16 +++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/tools/perf/util/probe-finder.c b/tools/perf/util/probe-finder.c index 5bb71e056b21..cafc3e5b9863 100644 --- a/tools/perf/util/probe-finder.c +++ b/tools/perf/util/probe-finder.c @@ -119,6 +119,8 @@ enum dso_binary_type distro_dwarf_types[] = { struct debuginfo *debuginfo__new(const char *path) { + static struct strlist *no_debuginfo_files; + u8 bid[BUILD_ID_SIZE], bid2[BUILD_ID_SIZE]; enum dso_binary_type *type; char buf[PATH_MAX], nil = '\0'; @@ -126,6 +128,12 @@ struct debuginfo *debuginfo__new(const char *path) bool have_build_id = false; struct debuginfo *dinfo = NULL; + /* Skip if we already know it has no debuginfo */ + if (!no_debuginfo_files) + no_debuginfo_files = strlist__new(NULL, NULL); + else if (strlist__find(no_debuginfo_files, path)) + return NULL; + /* Try to open distro debuginfo files */ dso = dso__new(path); if (!dso) @@ -159,7 +167,13 @@ struct debuginfo *debuginfo__new(const char *path) out: /* if failed to open all distro debuginfo, open given binary */ - return dinfo ? : __debuginfo__new(path); + if (!dinfo) { + dinfo = __debuginfo__new(path); + if (!dinfo) + strlist__add(no_debuginfo_files, path); + } + + return dinfo; } void debuginfo__delete(struct debuginfo *dbg)
[PATCH 0/2] perf-probe: Improve warning message for buildid mismatch
Hello, This series ensure the build-ids for target binary and debuginfo are matched. If there is a mismatch, it warns user to check the package versions. To reproduce the problematic environment (on Fedora26), I did following operations; = # rpm -q glibc glibc-debuginfo glibc-2.25-12.fc26.x86_64 package glibc-debuginfo is not installed # dnf debuginfo-install glibc [...] Installed: glibc-debuginfo.x86_64 2.25-12.fc26 glibc-debuginfo-common.x86_64 2.25-12.fc26 Complete! # dnf downgrade glibc [...] Downgraded: glibc.x86_64 2.25-6.fc26 glibc-common.x86_64 2.25-6.fc26 glibc-devel.x86_64 2.25-6.fc26 glibc-headers.x86_64 2.25-6.fc26 glibc-langpack-en.x86_64 2.25-6.fc26 libcrypt-nss.x86_64 2.25-6.fc26 Complete! # rpm -q glibc glibc-debuginfo glibc-2.25-6.fc26.x86_64 glibc-debuginfo-2.25-12.fc26.x86_64 = OK, so you can see now we have different versions of glibc and glibc-debuginfo. Each debuginfo must be different. With this series, defining new events also warns :) = # perf probe -x /usr/lib64/libc-2.25.so -a malloc_get_state\\@GLIBC_2.2.5 WARN: There is a build-id mismatch between /usr/lib/debug/usr/lib64/libc-2.25.so.debug and /usr/lib64/libc-2.25.so Please check your system's debuginfo files for mismatches, e.g. check the versions for the target package and debuginfo package. Added new event: probe_libc:malloc_get_state (on malloc_get_state@GLIBC_2.2.5 in /usr/lib64/libc-2.25.so) You can now use it in all perf tools, such as: perf record -e probe_libc:malloc_get_state -aR sleep 1 = And listing up events warns. = # perf probe -l | more WARN: There is a build-id mismatch between /usr/lib/debug/usr/lib64/libc-2.25.so.debug and /usr/lib64/libc-2.25.so Please check your system's debuginfo files for mismatches, e.g. check the versions for the target package and debuginfo package. probe_libc:malloc_get_state (on malloc_get_state@GLIBC_2.2.5 in /usr/lib64/libc-2.25.so) = With [1/2], this warning messages repeated on same target (glibc). To suppress this, [2/2] introduces no-debuginfo blacklist to skip it 2nd time as below. = # perf probe -l | more WARN: There is a build-id mismatch between /usr/lib/debug/usr/lib64/libc-2.25.so.debug and /usr/lib64/libc-2.25.so Please check your system's debuginfo files for mismatches, e.g. check the versions for the target package and debuginfo package. probe_libc:malloc_get_state (on malloc_get_state@GLIBC_2.2.5 in /usr/lib64/libc-2.25.so) probe_libc:malloc_get_state_1 (on malloc_get_state@GLIBC_2.2.5 in /usr/lib64/libc-2.25.so) probe_libc:malloc_get_state_2 (on malloc_get_state@GLIBC_2.2.5 in /usr/lib64/libc-2.25.so) = Arnaldo, would this match to your request? Thank you, --- Masami Hiramatsu (2): perf-probe: Ensure debuginfo's build-id is correct perf-probe: Skip searching debuginfo if we know no debuginfo tools/perf/util/probe-finder.c | 34 +- 1 file changed, 33 insertions(+), 1 deletion(-) -- Masami Hiramatsu (Linaro Ltd.)
[PATCH 0/2] perf-probe: Improve warning message for buildid mismatch
Hello, This series ensure the build-ids for target binary and debuginfo are matched. If there is a mismatch, it warns user to check the package versions. To reproduce the problematic environment (on Fedora26), I did following operations; = # rpm -q glibc glibc-debuginfo glibc-2.25-12.fc26.x86_64 package glibc-debuginfo is not installed # dnf debuginfo-install glibc [...] Installed: glibc-debuginfo.x86_64 2.25-12.fc26 glibc-debuginfo-common.x86_64 2.25-12.fc26 Complete! # dnf downgrade glibc [...] Downgraded: glibc.x86_64 2.25-6.fc26 glibc-common.x86_64 2.25-6.fc26 glibc-devel.x86_64 2.25-6.fc26 glibc-headers.x86_64 2.25-6.fc26 glibc-langpack-en.x86_64 2.25-6.fc26 libcrypt-nss.x86_64 2.25-6.fc26 Complete! # rpm -q glibc glibc-debuginfo glibc-2.25-6.fc26.x86_64 glibc-debuginfo-2.25-12.fc26.x86_64 = OK, so you can see now we have different versions of glibc and glibc-debuginfo. Each debuginfo must be different. With this series, defining new events also warns :) = # perf probe -x /usr/lib64/libc-2.25.so -a malloc_get_state\\@GLIBC_2.2.5 WARN: There is a build-id mismatch between /usr/lib/debug/usr/lib64/libc-2.25.so.debug and /usr/lib64/libc-2.25.so Please check your system's debuginfo files for mismatches, e.g. check the versions for the target package and debuginfo package. Added new event: probe_libc:malloc_get_state (on malloc_get_state@GLIBC_2.2.5 in /usr/lib64/libc-2.25.so) You can now use it in all perf tools, such as: perf record -e probe_libc:malloc_get_state -aR sleep 1 = And listing up events warns. = # perf probe -l | more WARN: There is a build-id mismatch between /usr/lib/debug/usr/lib64/libc-2.25.so.debug and /usr/lib64/libc-2.25.so Please check your system's debuginfo files for mismatches, e.g. check the versions for the target package and debuginfo package. probe_libc:malloc_get_state (on malloc_get_state@GLIBC_2.2.5 in /usr/lib64/libc-2.25.so) = With [1/2], this warning messages repeated on same target (glibc). To suppress this, [2/2] introduces no-debuginfo blacklist to skip it 2nd time as below. = # perf probe -l | more WARN: There is a build-id mismatch between /usr/lib/debug/usr/lib64/libc-2.25.so.debug and /usr/lib64/libc-2.25.so Please check your system's debuginfo files for mismatches, e.g. check the versions for the target package and debuginfo package. probe_libc:malloc_get_state (on malloc_get_state@GLIBC_2.2.5 in /usr/lib64/libc-2.25.so) probe_libc:malloc_get_state_1 (on malloc_get_state@GLIBC_2.2.5 in /usr/lib64/libc-2.25.so) probe_libc:malloc_get_state_2 (on malloc_get_state@GLIBC_2.2.5 in /usr/lib64/libc-2.25.so) = Arnaldo, would this match to your request? Thank you, --- Masami Hiramatsu (2): perf-probe: Ensure debuginfo's build-id is correct perf-probe: Skip searching debuginfo if we know no debuginfo tools/perf/util/probe-finder.c | 34 +- 1 file changed, 33 insertions(+), 1 deletion(-) -- Masami Hiramatsu (Linaro Ltd.)
Re: [f2fs-dev] [PATCH 1/2] f2fs: pass down write hints to block layer for bufferd write
Hi Jaegeuk, Agreed. If Chao agrees with this policy, I will implement it. Thanks for the comment. On 12/15/2017 11:06 AM, Jaegeuk Kim wrote: > On 12/14, Hyunchul Lee wrote: >> Hi Jaegeuk, >> >> I need your comment about the fs_iohint mount option. >> >> a) w/o fs_iohint, propagate user hints to low layer. >> b) w/ fs_iohint, ignore user hints, and use hints which is generated >> with F2FS. >> >> Chao suggests this option. because user hints are more accurate than >> file system. >> >> This is resonable, But I have some concerns about this option. >> The first thing is that blocks of a segments have different hints. This >> could make GC less effective. >> The second is that the separation between LIFE_MEDIUM and LIFE_LONG is >> really needed. I think that difference between them is a little ambigous >> for users, and LIFE_SHORT and LIFE_EXTREME is converted to different >> hints by F2FS. > > I think what we really can do would assign many user hints to our 3 DATA > logs likewise rw_hint_to_seg_type(), since it's just hints for user data. > Then, we can decide how to keep that as much as possible, since we have > another filesystem metadata such as meta and nodes. In addition, I don't > think we have to keep the original user-hints which makes F2FS logs be > messed up. > > With that mind, I can think of the below cases. Especially, if user wants > to keep their io_hints, we'd better recommend to use direct_io w/o fs_iohints. > In order to keep this policy, I think fs_iohints would be better to be a > feature set by mkfs.f2fs and detected by sysfs entries for users. > > 1) w/ fs_iohints > > UserF2FS Block > --- > Meta WRITE_LIFE_MEDIUM > HOT_NODE WRITE_LIFE_NOTSET > WARM_NODE -' > COLD_NODE WRITE_LIFE_NONE > ioctl(cold) COLD_DATA WRITE_LIFE_EXTREME > extention list -' -' > WRITE_LIFE_EXTREME -' -' > WRITE_LIFE_SHORTHOT_DATA WRITE_LIFE_SHORT > > -- buffered_io > WRITE_LIFE_NOT_SET WARM_DATA WRITE_LIFE_LONG > WRITE_LIFE_NONE -' -' > WRITE_LIFE_MEDIUM -' -' > WRITE_LIFE_LONG -' -' > > -- direct_io (Not recommendable) > WRITE_LIFE_NOT_SET WARM_DATA WRITE_LIFE_NOT_SET > WRITE_LIFE_NONE -' WRITE_LIFE_NONE > WRITE_LIFE_MEDIUM -' WRITE_LIFE_MEDIUM > WRITE_LIFE_LONG -' WRITE_LIFE_LONG > > 2) w/o fs_iohints > > UserF2FS Block > --- > Meta - > HOT_NODE - > WARM_NODE - > COLD_NODE - > ioctl(cold) COLD_DATA - > extention list -' - > > -- buffered_io > WRITE_LIFE_EXTREME COLD_DATA - > WRITE_LIFE_SHORTHOT_DATA - > WRITE_LIFE_NOT_SET WARM_DATA - > WRITE_LIFE_NONE -' - > WRITE_LIFE_MEDIUM -' - > WRITE_LIFE_LONG -' - > > -- direct_io > WRITE_LIFE_EXTREME COLD_DATA WRITE_LIFE_EXTREME > WRITE_LIFE_SHORTHOT_DATA WRITE_LIFE_SHORT > WRITE_LIFE_NOT_SET WARM_DATA WRITE_LIFE_NOT_SET > WRITE_LIFE_NONE -' WRITE_LIFE_NONE > WRITE_LIFE_MEDIUM -' WRITE_LIFE_MEDIUM > WRITE_LIFE_LONG -' WRITE_LIFE_LONG > > > Note that, I don't much care about how to manipulate streamid in nvme driver > in terms of LIFE_NONE or LIFE_NOTSET, since other drivers can handle them > in different ways. Taking a look at the definition, at least, we don't need > to assume that those are same at all. For example, if we can expolit this in > UFS driver, we can pass all the stream ids to the device as context ids. > > Thanks, > >> >> Thanks. >> >> On 12/12/2017 11:45 AM, Chao Yu wrote: >>> Hi Hyunchul, >>> >>> On 2017/12/12 10:15, Hyunchul Lee wrote: Hi Chao, On 12/11/2017 10:15 PM, Chao Yu wrote: > Hi Hyunchul, > > On 2017/12/1 16:28, Hyunchul Lee wrote: >> Hi Chao, >> >> On 11/30/2017 04:06 PM, Chao Yu wrote: >>> Hi Hyunchul, >>> >>> On 2017/11/28 8:23, Hyunchul Lee wrote: From: Hyunchul LeeThis implements which hint is passed down to block layer for datas from the specific segment type. segment
[PATCH 1/2] perf-probe: Ensure debuginfo's build-id is correct
Ensure that the build-id of debuginfo is correctly matched to target build-id, if not, it warns user to check the system debuginfo package is correctly installed. E.g. on such environment, you will see below warning. == # perf probe -l WARN: There is a build-id mismatch between /usr/lib/debug/usr/lib64/libc-2.25.so.debug and /usr/lib64/libc-2.25.so Please check your system's debuginfo files for mismatches, e.g. check the versions for the target package and debuginfo package. probe_libc:malloc_get_state (on malloc_get_state@GLIBC_2.2.5 in /us r/lib64/libc-2.25.so) == Signed-off-by: Masami Hiramatsu--- tools/perf/util/probe-finder.c | 18 ++ 1 file changed, 18 insertions(+) diff --git a/tools/perf/util/probe-finder.c b/tools/perf/util/probe-finder.c index a5731de0e5eb..5bb71e056b21 100644 --- a/tools/perf/util/probe-finder.c +++ b/tools/perf/util/probe-finder.c @@ -119,9 +119,11 @@ enum dso_binary_type distro_dwarf_types[] = { struct debuginfo *debuginfo__new(const char *path) { + u8 bid[BUILD_ID_SIZE], bid2[BUILD_ID_SIZE]; enum dso_binary_type *type; char buf[PATH_MAX], nil = '\0'; struct dso *dso; + bool have_build_id = false; struct debuginfo *dinfo = NULL; /* Try to open distro debuginfo files */ @@ -129,12 +131,28 @@ struct debuginfo *debuginfo__new(const char *path) if (!dso) goto out; + if (filename__read_build_id(path, bid, BUILD_ID_SIZE) > 0) + have_build_id = true; + for (type = distro_dwarf_types; !dinfo && *type != DSO_BINARY_TYPE__NOT_FOUND; type++) { if (dso__read_binary_type_filename(dso, *type, , buf, PATH_MAX) < 0) continue; + + if (have_build_id) { + /* This can be fail because the file doesn't exist */ + if (filename__read_build_id(buf, bid2, + BUILD_ID_SIZE) < 0) + continue; + if (memcmp(bid, bid2, BUILD_ID_SIZE)) { + pr_warning("WARN: There is a build-id mismatch between\n %s\n and\n %s\n" + "Please check your system's debuginfo files for mismatches, e.g. check the " + "versions for the target package and debuginfo package.\n", buf, path); + continue; + } + } dinfo = __debuginfo__new(buf); } dso__put(dso);
Re: [f2fs-dev] [PATCH 1/2] f2fs: pass down write hints to block layer for bufferd write
Hi Jaegeuk, Agreed. If Chao agrees with this policy, I will implement it. Thanks for the comment. On 12/15/2017 11:06 AM, Jaegeuk Kim wrote: > On 12/14, Hyunchul Lee wrote: >> Hi Jaegeuk, >> >> I need your comment about the fs_iohint mount option. >> >> a) w/o fs_iohint, propagate user hints to low layer. >> b) w/ fs_iohint, ignore user hints, and use hints which is generated >> with F2FS. >> >> Chao suggests this option. because user hints are more accurate than >> file system. >> >> This is resonable, But I have some concerns about this option. >> The first thing is that blocks of a segments have different hints. This >> could make GC less effective. >> The second is that the separation between LIFE_MEDIUM and LIFE_LONG is >> really needed. I think that difference between them is a little ambigous >> for users, and LIFE_SHORT and LIFE_EXTREME is converted to different >> hints by F2FS. > > I think what we really can do would assign many user hints to our 3 DATA > logs likewise rw_hint_to_seg_type(), since it's just hints for user data. > Then, we can decide how to keep that as much as possible, since we have > another filesystem metadata such as meta and nodes. In addition, I don't > think we have to keep the original user-hints which makes F2FS logs be > messed up. > > With that mind, I can think of the below cases. Especially, if user wants > to keep their io_hints, we'd better recommend to use direct_io w/o fs_iohints. > In order to keep this policy, I think fs_iohints would be better to be a > feature set by mkfs.f2fs and detected by sysfs entries for users. > > 1) w/ fs_iohints > > UserF2FS Block > --- > Meta WRITE_LIFE_MEDIUM > HOT_NODE WRITE_LIFE_NOTSET > WARM_NODE -' > COLD_NODE WRITE_LIFE_NONE > ioctl(cold) COLD_DATA WRITE_LIFE_EXTREME > extention list -' -' > WRITE_LIFE_EXTREME -' -' > WRITE_LIFE_SHORTHOT_DATA WRITE_LIFE_SHORT > > -- buffered_io > WRITE_LIFE_NOT_SET WARM_DATA WRITE_LIFE_LONG > WRITE_LIFE_NONE -' -' > WRITE_LIFE_MEDIUM -' -' > WRITE_LIFE_LONG -' -' > > -- direct_io (Not recommendable) > WRITE_LIFE_NOT_SET WARM_DATA WRITE_LIFE_NOT_SET > WRITE_LIFE_NONE -' WRITE_LIFE_NONE > WRITE_LIFE_MEDIUM -' WRITE_LIFE_MEDIUM > WRITE_LIFE_LONG -' WRITE_LIFE_LONG > > 2) w/o fs_iohints > > UserF2FS Block > --- > Meta - > HOT_NODE - > WARM_NODE - > COLD_NODE - > ioctl(cold) COLD_DATA - > extention list -' - > > -- buffered_io > WRITE_LIFE_EXTREME COLD_DATA - > WRITE_LIFE_SHORTHOT_DATA - > WRITE_LIFE_NOT_SET WARM_DATA - > WRITE_LIFE_NONE -' - > WRITE_LIFE_MEDIUM -' - > WRITE_LIFE_LONG -' - > > -- direct_io > WRITE_LIFE_EXTREME COLD_DATA WRITE_LIFE_EXTREME > WRITE_LIFE_SHORTHOT_DATA WRITE_LIFE_SHORT > WRITE_LIFE_NOT_SET WARM_DATA WRITE_LIFE_NOT_SET > WRITE_LIFE_NONE -' WRITE_LIFE_NONE > WRITE_LIFE_MEDIUM -' WRITE_LIFE_MEDIUM > WRITE_LIFE_LONG -' WRITE_LIFE_LONG > > > Note that, I don't much care about how to manipulate streamid in nvme driver > in terms of LIFE_NONE or LIFE_NOTSET, since other drivers can handle them > in different ways. Taking a look at the definition, at least, we don't need > to assume that those are same at all. For example, if we can expolit this in > UFS driver, we can pass all the stream ids to the device as context ids. > > Thanks, > >> >> Thanks. >> >> On 12/12/2017 11:45 AM, Chao Yu wrote: >>> Hi Hyunchul, >>> >>> On 2017/12/12 10:15, Hyunchul Lee wrote: Hi Chao, On 12/11/2017 10:15 PM, Chao Yu wrote: > Hi Hyunchul, > > On 2017/12/1 16:28, Hyunchul Lee wrote: >> Hi Chao, >> >> On 11/30/2017 04:06 PM, Chao Yu wrote: >>> Hi Hyunchul, >>> >>> On 2017/11/28 8:23, Hyunchul Lee wrote: From: Hyunchul Lee This implements which hint is passed down to block layer for datas from the specific segment type. segment type
[PATCH 1/2] perf-probe: Ensure debuginfo's build-id is correct
Ensure that the build-id of debuginfo is correctly matched to target build-id, if not, it warns user to check the system debuginfo package is correctly installed. E.g. on such environment, you will see below warning. == # perf probe -l WARN: There is a build-id mismatch between /usr/lib/debug/usr/lib64/libc-2.25.so.debug and /usr/lib64/libc-2.25.so Please check your system's debuginfo files for mismatches, e.g. check the versions for the target package and debuginfo package. probe_libc:malloc_get_state (on malloc_get_state@GLIBC_2.2.5 in /us r/lib64/libc-2.25.so) == Signed-off-by: Masami Hiramatsu --- tools/perf/util/probe-finder.c | 18 ++ 1 file changed, 18 insertions(+) diff --git a/tools/perf/util/probe-finder.c b/tools/perf/util/probe-finder.c index a5731de0e5eb..5bb71e056b21 100644 --- a/tools/perf/util/probe-finder.c +++ b/tools/perf/util/probe-finder.c @@ -119,9 +119,11 @@ enum dso_binary_type distro_dwarf_types[] = { struct debuginfo *debuginfo__new(const char *path) { + u8 bid[BUILD_ID_SIZE], bid2[BUILD_ID_SIZE]; enum dso_binary_type *type; char buf[PATH_MAX], nil = '\0'; struct dso *dso; + bool have_build_id = false; struct debuginfo *dinfo = NULL; /* Try to open distro debuginfo files */ @@ -129,12 +131,28 @@ struct debuginfo *debuginfo__new(const char *path) if (!dso) goto out; + if (filename__read_build_id(path, bid, BUILD_ID_SIZE) > 0) + have_build_id = true; + for (type = distro_dwarf_types; !dinfo && *type != DSO_BINARY_TYPE__NOT_FOUND; type++) { if (dso__read_binary_type_filename(dso, *type, , buf, PATH_MAX) < 0) continue; + + if (have_build_id) { + /* This can be fail because the file doesn't exist */ + if (filename__read_build_id(buf, bid2, + BUILD_ID_SIZE) < 0) + continue; + if (memcmp(bid, bid2, BUILD_ID_SIZE)) { + pr_warning("WARN: There is a build-id mismatch between\n %s\n and\n %s\n" + "Please check your system's debuginfo files for mismatches, e.g. check the " + "versions for the target package and debuginfo package.\n", buf, path); + continue; + } + } dinfo = __debuginfo__new(buf); } dso__put(dso);
[PATCH v4 03/36] nds32: Assembly macros and definitions
From: Greentime HuThis patch includes assembly macros, bit field definitions used in .S files across arch/nds32/. Signed-off-by: Vincent Chen Signed-off-by: Greentime Hu --- arch/nds32/include/asm/assembler.h | 39 ++ arch/nds32/include/asm/bitfield.h | 963 arch/nds32/include/asm/nds32.h | 83 arch/nds32/kernel/asm-offsets.c| 28 ++ 4 files changed, 1113 insertions(+) create mode 100644 arch/nds32/include/asm/assembler.h create mode 100644 arch/nds32/include/asm/bitfield.h create mode 100644 arch/nds32/include/asm/nds32.h create mode 100644 arch/nds32/kernel/asm-offsets.c diff --git a/arch/nds32/include/asm/assembler.h b/arch/nds32/include/asm/assembler.h new file mode 100644 index 000..c385578 --- /dev/null +++ b/arch/nds32/include/asm/assembler.h @@ -0,0 +1,39 @@ +// SPDX-License-Identifier: GPL-2.0 +// Copyright (C) 2005-2017 Andes Technology Corporation + +#ifndef __NDS32_ASSEMBLER_H__ +#define __NDS32_ASSEMBLER_H__ + +.macro gie_disable + setgie.d + dsb +.endm + +.macro gie_enable + setgie.e + dsb +.endm + +.macro gie_save oldpsw + mfsr \oldpsw, $ir0 + setgie.d +dsb +.endm + +.macro gie_restore oldpsw + andi \oldpsw, \oldpsw, #0x1 + beqz \oldpsw, 7001f + setgie.e + dsb +7001: +.endm + + +#define USER(insn, reg, addr, opr)\ +: insn reg, addr, opr; \ + .section __ex_table,"a";\ + .align 3; \ + .long b, 9001f; \ + .previous + +#endif /* __NDS32_ASSEMBLER_H__ */ diff --git a/arch/nds32/include/asm/bitfield.h b/arch/nds32/include/asm/bitfield.h new file mode 100644 index 000..c73f71d --- /dev/null +++ b/arch/nds32/include/asm/bitfield.h @@ -0,0 +1,963 @@ +// SPDX-License-Identifier: GPL-2.0 +// Copyright (C) 2005-2017 Andes Technology Corporation + +#ifndef __NDS32_BITFIELD_H__ +#define __NDS32_BITFIELD_H__ +/** + * cr0: CPU_VER (CPU Version Register) + */ +#define CPU_VER_offCFGID 0 /* Minor configuration */ +#define CPU_VER_offREV 16 /* Revision of the CPU version */ +#define CPU_VER_offCPUID 24 /* Major CPU versions */ + +#define CPU_VER_mskCFGID ( 0x << CPU_VER_offCFGID ) +#define CPU_VER_mskREV ( 0xFF << CPU_VER_offREV ) +#define CPU_VER_mskCPUID ( 0xFF << CPU_VER_offCPUID ) + +/** + * cr1: ICM_CFG (Instruction Cache/Memory Configuration Register) + */ +#define ICM_CFG_offISET0 /* I-cache sets (# of cache lines) per way */ +#define ICM_CFG_offIWAY3 /* I-cache ways */ +#define ICM_CFG_offISZ 6 /* I-cache line size */ +#define ICM_CFG_offILCK9 /* I-cache locking support */ +#define ICM_CFG_offILMB10 /* On-chip ILM banks */ +#define ICM_CFG_offBSAV13 /* ILM base register alignment version */ +/* bit 15:31 reserved */ + +#define ICM_CFG_mskISET( 0x7 << ICM_CFG_offISET ) +#define ICM_CFG_mskIWAY( 0x7 << ICM_CFG_offIWAY ) +#define ICM_CFG_mskISZ ( 0x7 << ICM_CFG_offISZ ) +#define ICM_CFG_mskILCK( 0x1 << ICM_CFG_offILCK ) +#define ICM_CFG_mskILMB( 0x7 << ICM_CFG_offILMB ) +#define ICM_CFG_mskBSAV( 0x3 << ICM_CFG_offBSAV ) + +/** + * cr2: DCM_CFG (Data Cache/Memory Configuration Register) + */ +#define DCM_CFG_offDSET0 /* D-cache sets (# of cache lines) per way */ +#define DCM_CFG_offDWAY3 /* D-cache ways */ +#define DCM_CFG_offDSZ 6 /* D-cache line size */ +#define DCM_CFG_offDLCK9 /* D-cache locking support */ +#define DCM_CFG_offDLMB10 /* On-chip DLM banks */ +#define DCM_CFG_offBSAV13 /* DLM base register alignment version */ +/* bit 15:31 reserved */ + +#define DCM_CFG_mskDSET( 0x7 << DCM_CFG_offDSET ) +#define DCM_CFG_mskDWAY( 0x7 << DCM_CFG_offDWAY ) +#define DCM_CFG_mskDSZ ( 0x7 << DCM_CFG_offDSZ ) +#define DCM_CFG_mskDLCK( 0x1 << DCM_CFG_offDLCK ) +#define DCM_CFG_mskDLMB( 0x7 << DCM_CFG_offDLMB ) +#define DCM_CFG_mskBSAV( 0x3 << DCM_CFG_offBSAV ) + +/** + * cr3: MMU_CFG (MMU
[PATCH v4 03/36] nds32: Assembly macros and definitions
From: Greentime Hu This patch includes assembly macros, bit field definitions used in .S files across arch/nds32/. Signed-off-by: Vincent Chen Signed-off-by: Greentime Hu --- arch/nds32/include/asm/assembler.h | 39 ++ arch/nds32/include/asm/bitfield.h | 963 arch/nds32/include/asm/nds32.h | 83 arch/nds32/kernel/asm-offsets.c| 28 ++ 4 files changed, 1113 insertions(+) create mode 100644 arch/nds32/include/asm/assembler.h create mode 100644 arch/nds32/include/asm/bitfield.h create mode 100644 arch/nds32/include/asm/nds32.h create mode 100644 arch/nds32/kernel/asm-offsets.c diff --git a/arch/nds32/include/asm/assembler.h b/arch/nds32/include/asm/assembler.h new file mode 100644 index 000..c385578 --- /dev/null +++ b/arch/nds32/include/asm/assembler.h @@ -0,0 +1,39 @@ +// SPDX-License-Identifier: GPL-2.0 +// Copyright (C) 2005-2017 Andes Technology Corporation + +#ifndef __NDS32_ASSEMBLER_H__ +#define __NDS32_ASSEMBLER_H__ + +.macro gie_disable + setgie.d + dsb +.endm + +.macro gie_enable + setgie.e + dsb +.endm + +.macro gie_save oldpsw + mfsr \oldpsw, $ir0 + setgie.d +dsb +.endm + +.macro gie_restore oldpsw + andi \oldpsw, \oldpsw, #0x1 + beqz \oldpsw, 7001f + setgie.e + dsb +7001: +.endm + + +#define USER(insn, reg, addr, opr)\ +: insn reg, addr, opr; \ + .section __ex_table,"a";\ + .align 3; \ + .long b, 9001f; \ + .previous + +#endif /* __NDS32_ASSEMBLER_H__ */ diff --git a/arch/nds32/include/asm/bitfield.h b/arch/nds32/include/asm/bitfield.h new file mode 100644 index 000..c73f71d --- /dev/null +++ b/arch/nds32/include/asm/bitfield.h @@ -0,0 +1,963 @@ +// SPDX-License-Identifier: GPL-2.0 +// Copyright (C) 2005-2017 Andes Technology Corporation + +#ifndef __NDS32_BITFIELD_H__ +#define __NDS32_BITFIELD_H__ +/** + * cr0: CPU_VER (CPU Version Register) + */ +#define CPU_VER_offCFGID 0 /* Minor configuration */ +#define CPU_VER_offREV 16 /* Revision of the CPU version */ +#define CPU_VER_offCPUID 24 /* Major CPU versions */ + +#define CPU_VER_mskCFGID ( 0x << CPU_VER_offCFGID ) +#define CPU_VER_mskREV ( 0xFF << CPU_VER_offREV ) +#define CPU_VER_mskCPUID ( 0xFF << CPU_VER_offCPUID ) + +/** + * cr1: ICM_CFG (Instruction Cache/Memory Configuration Register) + */ +#define ICM_CFG_offISET0 /* I-cache sets (# of cache lines) per way */ +#define ICM_CFG_offIWAY3 /* I-cache ways */ +#define ICM_CFG_offISZ 6 /* I-cache line size */ +#define ICM_CFG_offILCK9 /* I-cache locking support */ +#define ICM_CFG_offILMB10 /* On-chip ILM banks */ +#define ICM_CFG_offBSAV13 /* ILM base register alignment version */ +/* bit 15:31 reserved */ + +#define ICM_CFG_mskISET( 0x7 << ICM_CFG_offISET ) +#define ICM_CFG_mskIWAY( 0x7 << ICM_CFG_offIWAY ) +#define ICM_CFG_mskISZ ( 0x7 << ICM_CFG_offISZ ) +#define ICM_CFG_mskILCK( 0x1 << ICM_CFG_offILCK ) +#define ICM_CFG_mskILMB( 0x7 << ICM_CFG_offILMB ) +#define ICM_CFG_mskBSAV( 0x3 << ICM_CFG_offBSAV ) + +/** + * cr2: DCM_CFG (Data Cache/Memory Configuration Register) + */ +#define DCM_CFG_offDSET0 /* D-cache sets (# of cache lines) per way */ +#define DCM_CFG_offDWAY3 /* D-cache ways */ +#define DCM_CFG_offDSZ 6 /* D-cache line size */ +#define DCM_CFG_offDLCK9 /* D-cache locking support */ +#define DCM_CFG_offDLMB10 /* On-chip DLM banks */ +#define DCM_CFG_offBSAV13 /* DLM base register alignment version */ +/* bit 15:31 reserved */ + +#define DCM_CFG_mskDSET( 0x7 << DCM_CFG_offDSET ) +#define DCM_CFG_mskDWAY( 0x7 << DCM_CFG_offDWAY ) +#define DCM_CFG_mskDSZ ( 0x7 << DCM_CFG_offDSZ ) +#define DCM_CFG_mskDLCK( 0x1 << DCM_CFG_offDLCK ) +#define DCM_CFG_mskDLMB( 0x7 << DCM_CFG_offDLMB ) +#define DCM_CFG_mskBSAV( 0x3 << DCM_CFG_offBSAV ) + +/** + * cr3: MMU_CFG (MMU Configuration Register) +
[PATCH v4 05/36] nds32: Exception handling
From: Greentime HuThis patch includes the exception/interrupt entries, pt_reg structure and related accessors. Signed-off-by: Vincent Chen Signed-off-by: Greentime Hu --- arch/nds32/include/asm/ptrace.h | 66 + arch/nds32/kernel/ex-entry.S| 157 ++ arch/nds32/kernel/ex-exit.S | 193 + arch/nds32/kernel/stacktrace.c | 47 +++ arch/nds32/kernel/traps.c | 428 +++ arch/nds32/mm/alignment.c | 609 +++ 6 files changed, 1500 insertions(+) create mode 100644 arch/nds32/include/asm/ptrace.h create mode 100644 arch/nds32/kernel/ex-entry.S create mode 100644 arch/nds32/kernel/ex-exit.S create mode 100644 arch/nds32/kernel/stacktrace.c create mode 100644 arch/nds32/kernel/traps.c create mode 100644 arch/nds32/mm/alignment.c diff --git a/arch/nds32/include/asm/ptrace.h b/arch/nds32/include/asm/ptrace.h new file mode 100644 index 000..db7856c --- /dev/null +++ b/arch/nds32/include/asm/ptrace.h @@ -0,0 +1,66 @@ +// SPDX-License-Identifier: GPL-2.0 +// Copyright (C) 2005-2017 Andes Technology Corporation + +#ifndef __ASM_NDS32_PTRACE_H +#define __ASM_NDS32_PTRACE_H + +#define PTRACE_GETREGS 12 +#define PTRACE_SETREGS 13 +#define PTRACE_GETFPREGS 14 +#define PTRACE_SETFPREGS 15 + +#include + +#ifndef __ASSEMBLY__ + +struct pt_regs { + union { + struct user_pt_regs user_regs; + struct { + long uregs[26]; + long fp; + long gp; + long lp; + long sp; + long ipc; +#if defined(CONFIG_HWZOL) + long lb; + long le; + long lc; +#else + long dummy[3]; +#endif + long syscallno; + }; + }; + long orig_r0; + long ir0; + long ipsw; + long pipsw; + long pipc; + long pp0; + long pp1; + long fucop_ctl; + long osp; +}; + +#include +extern void show_regs(struct pt_regs *); +/* Avoid circular header include via sched.h */ +struct task_struct; +extern void send_sigtrap(struct task_struct *tsk, struct pt_regs *regs, +int error_code, int si_code); + +#define arch_has_single_step() (1) +#define user_mode(regs)(((regs)->ipsw & PSW_mskPOM) == 0) +#define interrupts_enabled(regs) (!!((regs)->ipsw & PSW_mskGIE)) +#define valid_user_regs(regs) (user_mode(regs) && interrupts_enabled(regs)) +#define regs_return_value(regs)((regs)->uregs[0]) +#define instruction_pointer(regs) ((regs)->ipc) +#define user_stack_pointer(regs)((regs)->sp) +#define profile_pc(regs) instruction_pointer(regs) + +#define ARCH_HAS_USER_SINGLE_STEP_INFO + +#endif /* __ASSEMBLY__ */ +#endif diff --git a/arch/nds32/kernel/ex-entry.S b/arch/nds32/kernel/ex-entry.S new file mode 100644 index 000..d2b3b8a --- /dev/null +++ b/arch/nds32/kernel/ex-entry.S @@ -0,0 +1,157 @@ +// SPDX-License-Identifier: GPL-2.0 +// Copyright (C) 2005-2017 Andes Technology Corporation + +#include +#include +#include +#include +#include +#include + +#ifdef CONFIG_HWZOL + .macro push_zol + mfusr $r14, $LB + mfusr $r15, $LE + mfusr $r16, $LC + .endm +#endif + + .macro save_user_regs + + smw.adm $sp, [$sp], $sp, #0x1 + /* move $SP to the bottom of pt_regs */ + addi$sp, $sp, -OSP_OFFSET + + /* push $r0 ~ $r25 */ + smw.bim $r0, [$sp], $r25 + /* push $fp, $gp, $lp */ + smw.bim $sp, [$sp], $sp, #0xe + + mfsr$r12, $SP_USR + mfsr$r13, $IPC +#ifdef CONFIG_HWZOL + push_zol +#endif + movi$r17, -1 + move$r18, $r0 + mfsr$r19, $PSW + mfsr$r20, $IPSW + mfsr$r21, $P_IPSW + mfsr$r22, $P_IPC + mfsr$r23, $P_P0 + mfsr$r24, $P_P1 + smw.bim $r12, [$sp], $r24, #0 + addi$sp, $sp, -FUCOP_CTL_OFFSET + + /* Initialize kernel space $fp */ + andi$p0, $r20, #PSW_mskPOM + movi$p1, #0x0 + cmovz $fp, $p1, $p0 + + andi$r16, $r19, #PSW_mskINTL + slti$r17, $r16, #4 + bnez$r17, 1f + addi$r17, $r19, #-2 + mtsr$r17, $PSW + isb +1: + /* If it was superuser mode, we don't need to update $r25 */ + bnez$p0, 2f + la $p0, __entry_task + lw $r25, [$p0] +2: + .endm + + .text + +/* + * Exception Vector + */ +exception_handlers: + .long unhandled_exceptions!Reset/NMI + .long unhandled_exceptions!TLB fill + .long do_page_fault !PTE not present + .long
[PATCH v4 05/36] nds32: Exception handling
From: Greentime Hu This patch includes the exception/interrupt entries, pt_reg structure and related accessors. Signed-off-by: Vincent Chen Signed-off-by: Greentime Hu --- arch/nds32/include/asm/ptrace.h | 66 + arch/nds32/kernel/ex-entry.S| 157 ++ arch/nds32/kernel/ex-exit.S | 193 + arch/nds32/kernel/stacktrace.c | 47 +++ arch/nds32/kernel/traps.c | 428 +++ arch/nds32/mm/alignment.c | 609 +++ 6 files changed, 1500 insertions(+) create mode 100644 arch/nds32/include/asm/ptrace.h create mode 100644 arch/nds32/kernel/ex-entry.S create mode 100644 arch/nds32/kernel/ex-exit.S create mode 100644 arch/nds32/kernel/stacktrace.c create mode 100644 arch/nds32/kernel/traps.c create mode 100644 arch/nds32/mm/alignment.c diff --git a/arch/nds32/include/asm/ptrace.h b/arch/nds32/include/asm/ptrace.h new file mode 100644 index 000..db7856c --- /dev/null +++ b/arch/nds32/include/asm/ptrace.h @@ -0,0 +1,66 @@ +// SPDX-License-Identifier: GPL-2.0 +// Copyright (C) 2005-2017 Andes Technology Corporation + +#ifndef __ASM_NDS32_PTRACE_H +#define __ASM_NDS32_PTRACE_H + +#define PTRACE_GETREGS 12 +#define PTRACE_SETREGS 13 +#define PTRACE_GETFPREGS 14 +#define PTRACE_SETFPREGS 15 + +#include + +#ifndef __ASSEMBLY__ + +struct pt_regs { + union { + struct user_pt_regs user_regs; + struct { + long uregs[26]; + long fp; + long gp; + long lp; + long sp; + long ipc; +#if defined(CONFIG_HWZOL) + long lb; + long le; + long lc; +#else + long dummy[3]; +#endif + long syscallno; + }; + }; + long orig_r0; + long ir0; + long ipsw; + long pipsw; + long pipc; + long pp0; + long pp1; + long fucop_ctl; + long osp; +}; + +#include +extern void show_regs(struct pt_regs *); +/* Avoid circular header include via sched.h */ +struct task_struct; +extern void send_sigtrap(struct task_struct *tsk, struct pt_regs *regs, +int error_code, int si_code); + +#define arch_has_single_step() (1) +#define user_mode(regs)(((regs)->ipsw & PSW_mskPOM) == 0) +#define interrupts_enabled(regs) (!!((regs)->ipsw & PSW_mskGIE)) +#define valid_user_regs(regs) (user_mode(regs) && interrupts_enabled(regs)) +#define regs_return_value(regs)((regs)->uregs[0]) +#define instruction_pointer(regs) ((regs)->ipc) +#define user_stack_pointer(regs)((regs)->sp) +#define profile_pc(regs) instruction_pointer(regs) + +#define ARCH_HAS_USER_SINGLE_STEP_INFO + +#endif /* __ASSEMBLY__ */ +#endif diff --git a/arch/nds32/kernel/ex-entry.S b/arch/nds32/kernel/ex-entry.S new file mode 100644 index 000..d2b3b8a --- /dev/null +++ b/arch/nds32/kernel/ex-entry.S @@ -0,0 +1,157 @@ +// SPDX-License-Identifier: GPL-2.0 +// Copyright (C) 2005-2017 Andes Technology Corporation + +#include +#include +#include +#include +#include +#include + +#ifdef CONFIG_HWZOL + .macro push_zol + mfusr $r14, $LB + mfusr $r15, $LE + mfusr $r16, $LC + .endm +#endif + + .macro save_user_regs + + smw.adm $sp, [$sp], $sp, #0x1 + /* move $SP to the bottom of pt_regs */ + addi$sp, $sp, -OSP_OFFSET + + /* push $r0 ~ $r25 */ + smw.bim $r0, [$sp], $r25 + /* push $fp, $gp, $lp */ + smw.bim $sp, [$sp], $sp, #0xe + + mfsr$r12, $SP_USR + mfsr$r13, $IPC +#ifdef CONFIG_HWZOL + push_zol +#endif + movi$r17, -1 + move$r18, $r0 + mfsr$r19, $PSW + mfsr$r20, $IPSW + mfsr$r21, $P_IPSW + mfsr$r22, $P_IPC + mfsr$r23, $P_P0 + mfsr$r24, $P_P1 + smw.bim $r12, [$sp], $r24, #0 + addi$sp, $sp, -FUCOP_CTL_OFFSET + + /* Initialize kernel space $fp */ + andi$p0, $r20, #PSW_mskPOM + movi$p1, #0x0 + cmovz $fp, $p1, $p0 + + andi$r16, $r19, #PSW_mskINTL + slti$r17, $r16, #4 + bnez$r17, 1f + addi$r17, $r19, #-2 + mtsr$r17, $PSW + isb +1: + /* If it was superuser mode, we don't need to update $r25 */ + bnez$p0, 2f + la $p0, __entry_task + lw $r25, [$p0] +2: + .endm + + .text + +/* + * Exception Vector + */ +exception_handlers: + .long unhandled_exceptions!Reset/NMI + .long unhandled_exceptions!TLB fill + .long do_page_fault !PTE not present + .long do_dispatch_tlb_misc!TLB misc + .long unhandled_exceptions!TLB VLPT +
[PATCH v4 07/36] nds32: MMU initialization
From: Greentime HuThis patch includes memory initializations and highmem supporting. Signed-off-by: Vincent Chen Signed-off-by: Greentime Hu --- arch/nds32/mm/highmem.c | 79 + arch/nds32/mm/init.c | 277 ++ arch/nds32/mm/mm-nds32.c | 90 +++ 3 files changed, 446 insertions(+) create mode 100644 arch/nds32/mm/highmem.c create mode 100644 arch/nds32/mm/init.c create mode 100644 arch/nds32/mm/mm-nds32.c diff --git a/arch/nds32/mm/highmem.c b/arch/nds32/mm/highmem.c new file mode 100644 index 000..e17cb8a --- /dev/null +++ b/arch/nds32/mm/highmem.c @@ -0,0 +1,79 @@ +// SPDX-License-Identifier: GPL-2.0 +// Copyright (C) 2005-2017 Andes Technology Corporation + +#include +#include +#include +#include +#include +#include +#include +#include + +void *kmap(struct page *page) +{ + unsigned long vaddr; + might_sleep(); + if (!PageHighMem(page)) + return page_address(page); + vaddr = (unsigned long)kmap_high(page); + return (void *)vaddr; +} + +EXPORT_SYMBOL(kmap); + +void kunmap(struct page *page) +{ + BUG_ON(in_interrupt()); + if (!PageHighMem(page)) + return; + kunmap_high(page); +} + +EXPORT_SYMBOL(kunmap); + +void *kmap_atomic(struct page *page) +{ + unsigned int idx; + unsigned long vaddr, pte; + int type; + pte_t *ptep; + + preempt_disable(); + pagefault_disable(); + if (!PageHighMem(page)) + return page_address(page); + + type = kmap_atomic_idx_push(); + + idx = type + KM_TYPE_NR * smp_processor_id(); + vaddr = __fix_to_virt(FIX_KMAP_BEGIN + idx); + pte = (page_to_pfn(page) << PAGE_SHIFT) | (PAGE_KERNEL); + ptep = pte_offset_kernel(pmd_off_k(vaddr), vaddr); + set_pte(ptep, pte); + + __nds32__tlbop_inv(vaddr); + __nds32__mtsr_dsb(vaddr, NDS32_SR_TLB_VPN); + __nds32__tlbop_rwr(pte); + __nds32__isb(); + return (void *)vaddr; +} + +EXPORT_SYMBOL(kmap_atomic); + +void __kunmap_atomic(void *kvaddr) +{ + if (kvaddr >= (void *)FIXADDR_START) { + unsigned long vaddr = (unsigned long)kvaddr; + pte_t *ptep; + kmap_atomic_idx_pop(); + __nds32__tlbop_inv(vaddr); + __nds32__isb(); + ptep = pte_offset_kernel(pmd_off_k(vaddr), vaddr); + set_pte(ptep, 0); + } + pagefault_enable(); + preempt_enable(); +} + +EXPORT_SYMBOL(__kunmap_atomic); diff --git a/arch/nds32/mm/init.c b/arch/nds32/mm/init.c new file mode 100644 index 000..93ee016 --- /dev/null +++ b/arch/nds32/mm/init.c @@ -0,0 +1,277 @@ +// SPDX-License-Identifier: GPL-2.0 +// Copyright (C) 1995-2005 Russell King +// Copyright (C) 2012 ARM Ltd. +// Copyright (C) 2013-2017 Andes Technology Corporation + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +DEFINE_PER_CPU(struct mmu_gather, mmu_gathers); +DEFINE_SPINLOCK(anon_alias_lock); +extern pgd_t swapper_pg_dir[PTRS_PER_PGD]; +extern unsigned long phys_initrd_start; +extern unsigned long phys_initrd_size; + +/* + * empty_zero_page is a special page that is used for + * zero-initialized data and COW. + */ +struct page *empty_zero_page; + +static void __init zone_sizes_init(void) +{ + unsigned long zones_size[MAX_NR_ZONES]; + + /* Clear the zone sizes */ + memset(zones_size, 0, sizeof(zones_size)); + + zones_size[ZONE_NORMAL] = max_low_pfn; +#ifdef CONFIG_HIGHMEM + zones_size[ZONE_HIGHMEM] = max_pfn; +#endif + free_area_init(zones_size); + +} + +/* + * Map all physical memory under high_memory into kernel's address space. + * + * This is explicitly coded for two-level page tables, so if you need + * something else then this needs to change. + */ +static void __init map_ram(void) +{ + unsigned long v, p, e; + pgd_t *pge; + pud_t *pue; + pmd_t *pme; + pte_t *pte; + /* These mark extents of read-only kernel pages... +* ...from vmlinux.lds.S +*/ + + p = (u32) memblock_start_of_DRAM() & PAGE_MASK; + e = min((u32) memblock_end_of_DRAM(), (u32) __pa(high_memory)); + + v = (u32) __va(p); + pge = pgd_offset_k(v); + + while (p < e) { + int j; + pue = pud_offset(pge, v); + pme = pmd_offset(pue, v); + + if ((u32) pue != (u32) pge || (u32) pme != (u32) pge) { + panic("%s: Kernel hardcoded for " + "two-level page tables", __func__); + } + + /* Alloc one page for holding PTE's... */ + pte = (pte_t *) __va(memblock_alloc(PAGE_SIZE, PAGE_SIZE)); + memset(pte, 0,
[PATCH v4 07/36] nds32: MMU initialization
From: Greentime Hu This patch includes memory initializations and highmem supporting. Signed-off-by: Vincent Chen Signed-off-by: Greentime Hu --- arch/nds32/mm/highmem.c | 79 + arch/nds32/mm/init.c | 277 ++ arch/nds32/mm/mm-nds32.c | 90 +++ 3 files changed, 446 insertions(+) create mode 100644 arch/nds32/mm/highmem.c create mode 100644 arch/nds32/mm/init.c create mode 100644 arch/nds32/mm/mm-nds32.c diff --git a/arch/nds32/mm/highmem.c b/arch/nds32/mm/highmem.c new file mode 100644 index 000..e17cb8a --- /dev/null +++ b/arch/nds32/mm/highmem.c @@ -0,0 +1,79 @@ +// SPDX-License-Identifier: GPL-2.0 +// Copyright (C) 2005-2017 Andes Technology Corporation + +#include +#include +#include +#include +#include +#include +#include +#include + +void *kmap(struct page *page) +{ + unsigned long vaddr; + might_sleep(); + if (!PageHighMem(page)) + return page_address(page); + vaddr = (unsigned long)kmap_high(page); + return (void *)vaddr; +} + +EXPORT_SYMBOL(kmap); + +void kunmap(struct page *page) +{ + BUG_ON(in_interrupt()); + if (!PageHighMem(page)) + return; + kunmap_high(page); +} + +EXPORT_SYMBOL(kunmap); + +void *kmap_atomic(struct page *page) +{ + unsigned int idx; + unsigned long vaddr, pte; + int type; + pte_t *ptep; + + preempt_disable(); + pagefault_disable(); + if (!PageHighMem(page)) + return page_address(page); + + type = kmap_atomic_idx_push(); + + idx = type + KM_TYPE_NR * smp_processor_id(); + vaddr = __fix_to_virt(FIX_KMAP_BEGIN + idx); + pte = (page_to_pfn(page) << PAGE_SHIFT) | (PAGE_KERNEL); + ptep = pte_offset_kernel(pmd_off_k(vaddr), vaddr); + set_pte(ptep, pte); + + __nds32__tlbop_inv(vaddr); + __nds32__mtsr_dsb(vaddr, NDS32_SR_TLB_VPN); + __nds32__tlbop_rwr(pte); + __nds32__isb(); + return (void *)vaddr; +} + +EXPORT_SYMBOL(kmap_atomic); + +void __kunmap_atomic(void *kvaddr) +{ + if (kvaddr >= (void *)FIXADDR_START) { + unsigned long vaddr = (unsigned long)kvaddr; + pte_t *ptep; + kmap_atomic_idx_pop(); + __nds32__tlbop_inv(vaddr); + __nds32__isb(); + ptep = pte_offset_kernel(pmd_off_k(vaddr), vaddr); + set_pte(ptep, 0); + } + pagefault_enable(); + preempt_enable(); +} + +EXPORT_SYMBOL(__kunmap_atomic); diff --git a/arch/nds32/mm/init.c b/arch/nds32/mm/init.c new file mode 100644 index 000..93ee016 --- /dev/null +++ b/arch/nds32/mm/init.c @@ -0,0 +1,277 @@ +// SPDX-License-Identifier: GPL-2.0 +// Copyright (C) 1995-2005 Russell King +// Copyright (C) 2012 ARM Ltd. +// Copyright (C) 2013-2017 Andes Technology Corporation + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +DEFINE_PER_CPU(struct mmu_gather, mmu_gathers); +DEFINE_SPINLOCK(anon_alias_lock); +extern pgd_t swapper_pg_dir[PTRS_PER_PGD]; +extern unsigned long phys_initrd_start; +extern unsigned long phys_initrd_size; + +/* + * empty_zero_page is a special page that is used for + * zero-initialized data and COW. + */ +struct page *empty_zero_page; + +static void __init zone_sizes_init(void) +{ + unsigned long zones_size[MAX_NR_ZONES]; + + /* Clear the zone sizes */ + memset(zones_size, 0, sizeof(zones_size)); + + zones_size[ZONE_NORMAL] = max_low_pfn; +#ifdef CONFIG_HIGHMEM + zones_size[ZONE_HIGHMEM] = max_pfn; +#endif + free_area_init(zones_size); + +} + +/* + * Map all physical memory under high_memory into kernel's address space. + * + * This is explicitly coded for two-level page tables, so if you need + * something else then this needs to change. + */ +static void __init map_ram(void) +{ + unsigned long v, p, e; + pgd_t *pge; + pud_t *pue; + pmd_t *pme; + pte_t *pte; + /* These mark extents of read-only kernel pages... +* ...from vmlinux.lds.S +*/ + + p = (u32) memblock_start_of_DRAM() & PAGE_MASK; + e = min((u32) memblock_end_of_DRAM(), (u32) __pa(high_memory)); + + v = (u32) __va(p); + pge = pgd_offset_k(v); + + while (p < e) { + int j; + pue = pud_offset(pge, v); + pme = pmd_offset(pue, v); + + if ((u32) pue != (u32) pge || (u32) pme != (u32) pge) { + panic("%s: Kernel hardcoded for " + "two-level page tables", __func__); + } + + /* Alloc one page for holding PTE's... */ + pte = (pte_t *) __va(memblock_alloc(PAGE_SIZE, PAGE_SIZE)); + memset(pte, 0, PAGE_SIZE); + set_pmd(pme, __pmd(__pa(pte) + _PAGE_KERNEL_TABLE));
[PATCH v4 09/36] nds32: Cache and TLB routines
From: Greentime HuThis patch contains cache and TLB maintenance functions. Signed-off-by: Vincent Chen Signed-off-by: Greentime Hu --- arch/nds32/include/asm/cache.h | 12 + arch/nds32/include/asm/cache_info.h| 13 + arch/nds32/include/asm/cacheflush.h| 44 +++ arch/nds32/include/asm/mmu_context.h | 68 arch/nds32/include/asm/proc-fns.h | 44 +++ arch/nds32/include/asm/tlb.h | 28 ++ arch/nds32/include/asm/tlbflush.h | 47 +++ arch/nds32/include/uapi/asm/cachectl.h | 14 + arch/nds32/kernel/cacheinfo.c | 49 +++ arch/nds32/mm/cacheflush.c | 322 +++ arch/nds32/mm/proc.c | 540 arch/nds32/mm/tlb.c| 50 +++ 12 files changed, 1231 insertions(+) create mode 100644 arch/nds32/include/asm/cache.h create mode 100644 arch/nds32/include/asm/cache_info.h create mode 100644 arch/nds32/include/asm/cacheflush.h create mode 100644 arch/nds32/include/asm/mmu_context.h create mode 100644 arch/nds32/include/asm/proc-fns.h create mode 100644 arch/nds32/include/asm/tlb.h create mode 100644 arch/nds32/include/asm/tlbflush.h create mode 100644 arch/nds32/include/uapi/asm/cachectl.h create mode 100644 arch/nds32/kernel/cacheinfo.c create mode 100644 arch/nds32/mm/cacheflush.c create mode 100644 arch/nds32/mm/proc.c create mode 100644 arch/nds32/mm/tlb.c diff --git a/arch/nds32/include/asm/cache.h b/arch/nds32/include/asm/cache.h new file mode 100644 index 000..347db48 --- /dev/null +++ b/arch/nds32/include/asm/cache.h @@ -0,0 +1,12 @@ +// SPDX-License-Identifier: GPL-2.0 +// Copyright (C) 2005-2017 Andes Technology Corporation + +#ifndef __NDS32_CACHE_H__ +#define __NDS32_CACHE_H__ + +#define L1_CACHE_BYTES 32 +#define L1_CACHE_SHIFT 5 + +#define ARCH_DMA_MINALIGN L1_CACHE_BYTES + +#endif /* __NDS32_CACHE_H__ */ diff --git a/arch/nds32/include/asm/cache_info.h b/arch/nds32/include/asm/cache_info.h new file mode 100644 index 000..38ec458 --- /dev/null +++ b/arch/nds32/include/asm/cache_info.h @@ -0,0 +1,13 @@ +// SPDX-License-Identifier: GPL-2.0 +// Copyright (C) 2005-2017 Andes Technology Corporation + +struct cache_info { + unsigned char ways; + unsigned char line_size; + unsigned short sets; + unsigned short size; +#if defined(CONFIG_CPU_CACHE_ALIASING) + unsigned short aliasing_num; + unsigned int aliasing_mask; +#endif +}; diff --git a/arch/nds32/include/asm/cacheflush.h b/arch/nds32/include/asm/cacheflush.h new file mode 100644 index 000..7b9b20a --- /dev/null +++ b/arch/nds32/include/asm/cacheflush.h @@ -0,0 +1,44 @@ +// SPDX-License-Identifier: GPL-2.0 +// Copyright (C) 2005-2017 Andes Technology Corporation + +#ifndef __NDS32_CACHEFLUSH_H__ +#define __NDS32_CACHEFLUSH_H__ + +#include + +#define PG_dcache_dirty PG_arch_1 + +#ifdef CONFIG_CPU_CACHE_ALIASING +void flush_cache_mm(struct mm_struct *mm); +void flush_cache_dup_mm(struct mm_struct *mm); +void flush_cache_range(struct vm_area_struct *vma, + unsigned long start, unsigned long end); +void flush_cache_page(struct vm_area_struct *vma, + unsigned long addr, unsigned long pfn); +void flush_cache_kmaps(void); +void flush_cache_vmap(unsigned long start, unsigned long end); +void flush_cache_vunmap(unsigned long start, unsigned long end); + +#define ARCH_IMPLEMENTS_FLUSH_DCACHE_PAGE 1 +void flush_dcache_page(struct page *page); +void copy_to_user_page(struct vm_area_struct *vma, struct page *page, + unsigned long vaddr, void *dst, void *src, int len); +void copy_from_user_page(struct vm_area_struct *vma, struct page *page, +unsigned long vaddr, void *dst, void *src, int len); + +#define ARCH_HAS_FLUSH_ANON_PAGE +void flush_anon_page(struct vm_area_struct *vma, +struct page *page, unsigned long vaddr); + +#define ARCH_HAS_FLUSH_KERNEL_DCACHE_PAGE +void flush_kernel_dcache_page(struct page *page); +void flush_icache_range(unsigned long start, unsigned long end); +void flush_icache_page(struct vm_area_struct *vma, struct page *page); +#define flush_dcache_mmap_lock(mapping) spin_lock_irq(&(mapping)->tree_lock) +#define flush_dcache_mmap_unlock(mapping) spin_unlock_irq(&(mapping)->tree_lock) + +#else +#include +#endif + +#endif /* __NDS32_CACHEFLUSH_H__ */ diff --git a/arch/nds32/include/asm/mmu_context.h b/arch/nds32/include/asm/mmu_context.h new file mode 100644 index 000..fd7d13c --- /dev/null +++ b/arch/nds32/include/asm/mmu_context.h @@ -0,0 +1,68 @@ +// SPDX-License-Identifier: GPL-2.0 +// Copyright (C) 2005-2017 Andes Technology Corporation + +#ifndef __ASM_NDS32_MMU_CONTEXT_H +#define __ASM_NDS32_MMU_CONTEXT_H + +#include +#include +#include +#include + +static inline int +init_new_context(struct task_struct *tsk, struct mm_struct *mm)
[PATCH v4 09/36] nds32: Cache and TLB routines
From: Greentime Hu This patch contains cache and TLB maintenance functions. Signed-off-by: Vincent Chen Signed-off-by: Greentime Hu --- arch/nds32/include/asm/cache.h | 12 + arch/nds32/include/asm/cache_info.h| 13 + arch/nds32/include/asm/cacheflush.h| 44 +++ arch/nds32/include/asm/mmu_context.h | 68 arch/nds32/include/asm/proc-fns.h | 44 +++ arch/nds32/include/asm/tlb.h | 28 ++ arch/nds32/include/asm/tlbflush.h | 47 +++ arch/nds32/include/uapi/asm/cachectl.h | 14 + arch/nds32/kernel/cacheinfo.c | 49 +++ arch/nds32/mm/cacheflush.c | 322 +++ arch/nds32/mm/proc.c | 540 arch/nds32/mm/tlb.c| 50 +++ 12 files changed, 1231 insertions(+) create mode 100644 arch/nds32/include/asm/cache.h create mode 100644 arch/nds32/include/asm/cache_info.h create mode 100644 arch/nds32/include/asm/cacheflush.h create mode 100644 arch/nds32/include/asm/mmu_context.h create mode 100644 arch/nds32/include/asm/proc-fns.h create mode 100644 arch/nds32/include/asm/tlb.h create mode 100644 arch/nds32/include/asm/tlbflush.h create mode 100644 arch/nds32/include/uapi/asm/cachectl.h create mode 100644 arch/nds32/kernel/cacheinfo.c create mode 100644 arch/nds32/mm/cacheflush.c create mode 100644 arch/nds32/mm/proc.c create mode 100644 arch/nds32/mm/tlb.c diff --git a/arch/nds32/include/asm/cache.h b/arch/nds32/include/asm/cache.h new file mode 100644 index 000..347db48 --- /dev/null +++ b/arch/nds32/include/asm/cache.h @@ -0,0 +1,12 @@ +// SPDX-License-Identifier: GPL-2.0 +// Copyright (C) 2005-2017 Andes Technology Corporation + +#ifndef __NDS32_CACHE_H__ +#define __NDS32_CACHE_H__ + +#define L1_CACHE_BYTES 32 +#define L1_CACHE_SHIFT 5 + +#define ARCH_DMA_MINALIGN L1_CACHE_BYTES + +#endif /* __NDS32_CACHE_H__ */ diff --git a/arch/nds32/include/asm/cache_info.h b/arch/nds32/include/asm/cache_info.h new file mode 100644 index 000..38ec458 --- /dev/null +++ b/arch/nds32/include/asm/cache_info.h @@ -0,0 +1,13 @@ +// SPDX-License-Identifier: GPL-2.0 +// Copyright (C) 2005-2017 Andes Technology Corporation + +struct cache_info { + unsigned char ways; + unsigned char line_size; + unsigned short sets; + unsigned short size; +#if defined(CONFIG_CPU_CACHE_ALIASING) + unsigned short aliasing_num; + unsigned int aliasing_mask; +#endif +}; diff --git a/arch/nds32/include/asm/cacheflush.h b/arch/nds32/include/asm/cacheflush.h new file mode 100644 index 000..7b9b20a --- /dev/null +++ b/arch/nds32/include/asm/cacheflush.h @@ -0,0 +1,44 @@ +// SPDX-License-Identifier: GPL-2.0 +// Copyright (C) 2005-2017 Andes Technology Corporation + +#ifndef __NDS32_CACHEFLUSH_H__ +#define __NDS32_CACHEFLUSH_H__ + +#include + +#define PG_dcache_dirty PG_arch_1 + +#ifdef CONFIG_CPU_CACHE_ALIASING +void flush_cache_mm(struct mm_struct *mm); +void flush_cache_dup_mm(struct mm_struct *mm); +void flush_cache_range(struct vm_area_struct *vma, + unsigned long start, unsigned long end); +void flush_cache_page(struct vm_area_struct *vma, + unsigned long addr, unsigned long pfn); +void flush_cache_kmaps(void); +void flush_cache_vmap(unsigned long start, unsigned long end); +void flush_cache_vunmap(unsigned long start, unsigned long end); + +#define ARCH_IMPLEMENTS_FLUSH_DCACHE_PAGE 1 +void flush_dcache_page(struct page *page); +void copy_to_user_page(struct vm_area_struct *vma, struct page *page, + unsigned long vaddr, void *dst, void *src, int len); +void copy_from_user_page(struct vm_area_struct *vma, struct page *page, +unsigned long vaddr, void *dst, void *src, int len); + +#define ARCH_HAS_FLUSH_ANON_PAGE +void flush_anon_page(struct vm_area_struct *vma, +struct page *page, unsigned long vaddr); + +#define ARCH_HAS_FLUSH_KERNEL_DCACHE_PAGE +void flush_kernel_dcache_page(struct page *page); +void flush_icache_range(unsigned long start, unsigned long end); +void flush_icache_page(struct vm_area_struct *vma, struct page *page); +#define flush_dcache_mmap_lock(mapping) spin_lock_irq(&(mapping)->tree_lock) +#define flush_dcache_mmap_unlock(mapping) spin_unlock_irq(&(mapping)->tree_lock) + +#else +#include +#endif + +#endif /* __NDS32_CACHEFLUSH_H__ */ diff --git a/arch/nds32/include/asm/mmu_context.h b/arch/nds32/include/asm/mmu_context.h new file mode 100644 index 000..fd7d13c --- /dev/null +++ b/arch/nds32/include/asm/mmu_context.h @@ -0,0 +1,68 @@ +// SPDX-License-Identifier: GPL-2.0 +// Copyright (C) 2005-2017 Andes Technology Corporation + +#ifndef __ASM_NDS32_MMU_CONTEXT_H +#define __ASM_NDS32_MMU_CONTEXT_H + +#include +#include +#include +#include + +static inline int +init_new_context(struct task_struct *tsk, struct mm_struct *mm) +{ + mm->context.id = 0; + return 0; +} + +#define
[PATCH v4 11/36] nds32: IRQ handling
From: Greentime HuThis patch includes irq related functions and irqchip_init(). Signed-off-by: Vincent Chen Signed-off-by: Greentime Hu --- arch/nds32/include/asm/irqflags.h | 36 arch/nds32/kernel/irq.c |9 + 2 files changed, 45 insertions(+) create mode 100644 arch/nds32/include/asm/irqflags.h create mode 100644 arch/nds32/kernel/irq.c diff --git a/arch/nds32/include/asm/irqflags.h b/arch/nds32/include/asm/irqflags.h new file mode 100644 index 000..2bfd00f --- /dev/null +++ b/arch/nds32/include/asm/irqflags.h @@ -0,0 +1,36 @@ +// SPDX-License-Identifier: GPL-2.0 +// Copyright (C) 2005-2017 Andes Technology Corporation + +#include +#include + +#define arch_local_irq_disable() \ + GIE_DISABLE(); + +#define arch_local_irq_enable()\ + GIE_ENABLE(); +static inline unsigned long arch_local_irq_save(void) +{ + unsigned long flags; + flags = __nds32__mfsr(NDS32_SR_PSW) & PSW_mskGIE; + GIE_DISABLE(); + return flags; +} + +static inline unsigned long arch_local_save_flags(void) +{ + unsigned long flags; + flags = __nds32__mfsr(NDS32_SR_PSW) & PSW_mskGIE; + return flags; +} + +static inline void arch_local_irq_restore(unsigned long flags) +{ + if(flags) + GIE_ENABLE(); +} + +static inline int arch_irqs_disabled_flags(unsigned long flags) +{ + return !flags; +} diff --git a/arch/nds32/kernel/irq.c b/arch/nds32/kernel/irq.c new file mode 100644 index 000..6ff5a67 --- /dev/null +++ b/arch/nds32/kernel/irq.c @@ -0,0 +1,9 @@ +// SPDX-License-Identifier: GPL-2.0 +// Copyright (C) 2005-2017 Andes Technology Corporation + +#include + +void __init init_IRQ(void) +{ + irqchip_init(); +} -- 1.7.9.5
[PATCH v4 11/36] nds32: IRQ handling
From: Greentime Hu This patch includes irq related functions and irqchip_init(). Signed-off-by: Vincent Chen Signed-off-by: Greentime Hu --- arch/nds32/include/asm/irqflags.h | 36 arch/nds32/kernel/irq.c |9 + 2 files changed, 45 insertions(+) create mode 100644 arch/nds32/include/asm/irqflags.h create mode 100644 arch/nds32/kernel/irq.c diff --git a/arch/nds32/include/asm/irqflags.h b/arch/nds32/include/asm/irqflags.h new file mode 100644 index 000..2bfd00f --- /dev/null +++ b/arch/nds32/include/asm/irqflags.h @@ -0,0 +1,36 @@ +// SPDX-License-Identifier: GPL-2.0 +// Copyright (C) 2005-2017 Andes Technology Corporation + +#include +#include + +#define arch_local_irq_disable() \ + GIE_DISABLE(); + +#define arch_local_irq_enable()\ + GIE_ENABLE(); +static inline unsigned long arch_local_irq_save(void) +{ + unsigned long flags; + flags = __nds32__mfsr(NDS32_SR_PSW) & PSW_mskGIE; + GIE_DISABLE(); + return flags; +} + +static inline unsigned long arch_local_save_flags(void) +{ + unsigned long flags; + flags = __nds32__mfsr(NDS32_SR_PSW) & PSW_mskGIE; + return flags; +} + +static inline void arch_local_irq_restore(unsigned long flags) +{ + if(flags) + GIE_ENABLE(); +} + +static inline int arch_irqs_disabled_flags(unsigned long flags) +{ + return !flags; +} diff --git a/arch/nds32/kernel/irq.c b/arch/nds32/kernel/irq.c new file mode 100644 index 000..6ff5a67 --- /dev/null +++ b/arch/nds32/kernel/irq.c @@ -0,0 +1,9 @@ +// SPDX-License-Identifier: GPL-2.0 +// Copyright (C) 2005-2017 Andes Technology Corporation + +#include + +void __init init_IRQ(void) +{ + irqchip_init(); +} -- 1.7.9.5
[PATCH v4 15/36] nds32: ELF definitions
From: Greentime HuThis patch adds definitions for the ELF format, relocation types, vdso locations and EXEC_PAGESIZE. Signed-off-by: Vincent Chen Signed-off-by: Greentime Hu --- arch/nds32/include/asm/elf.h | 179 ++ arch/nds32/include/uapi/asm/auxvec.h | 12 +++ arch/nds32/include/uapi/asm/param.h | 11 +++ 3 files changed, 202 insertions(+) create mode 100644 arch/nds32/include/asm/elf.h create mode 100644 arch/nds32/include/uapi/asm/auxvec.h create mode 100644 arch/nds32/include/uapi/asm/param.h diff --git a/arch/nds32/include/asm/elf.h b/arch/nds32/include/asm/elf.h new file mode 100644 index 000..99203f1 --- /dev/null +++ b/arch/nds32/include/asm/elf.h @@ -0,0 +1,179 @@ +// SPDX-License-Identifier: GPL-2.0 +// Copyright (C) 2005-2017 Andes Technology Corporation + +#ifndef __ASMNDS32_ELF_H +#define __ASMNDS32_ELF_H + +/* + * ELF register definitions.. + */ + +#include + +typedef unsigned long elf_greg_t; +typedef unsigned long elf_freg_t[3]; + +extern unsigned int elf_hwcap; + +#define EM_NDS32 167 + +#define R_NDS32_NONE 0 +#define R_NDS32_16_RELA19 +#define R_NDS32_32_RELA20 +#define R_NDS32_9_PCREL_RELA 22 +#define R_NDS32_15_PCREL_RELA 23 +#define R_NDS32_17_PCREL_RELA 24 +#define R_NDS32_25_PCREL_RELA 25 +#define R_NDS32_HI20_RELA 26 +#define R_NDS32_LO12S3_RELA27 +#define R_NDS32_LO12S2_RELA28 +#define R_NDS32_LO12S1_RELA29 +#define R_NDS32_LO12S0_RELA30 +#define R_NDS32_SDA15S3_RELA 31 +#define R_NDS32_SDA15S2_RELA 32 +#define R_NDS32_SDA15S1_RELA 33 +#define R_NDS32_SDA15S0_RELA 34 +#define R_NDS32_GOT20 37 +#define R_NDS32_25_PLTREL 38 +#define R_NDS32_COPY 39 +#define R_NDS32_GLOB_DAT 40 +#define R_NDS32_JMP_SLOT 41 +#define R_NDS32_RELATIVE 42 +#define R_NDS32_GOTOFF 43 +#define R_NDS32_GOTPC2044 +#define R_NDS32_GOT_HI20 45 +#define R_NDS32_GOT_LO12 46 +#define R_NDS32_GOTPC_HI20 47 +#define R_NDS32_GOTPC_LO12 48 +#define R_NDS32_GOTOFF_HI2049 +#define R_NDS32_GOTOFF_LO1250 +#define R_NDS32_INSN16 51 +#define R_NDS32_LABEL 52 +#define R_NDS32_LONGCALL1 53 +#define R_NDS32_LONGCALL2 54 +#define R_NDS32_LONGCALL3 55 +#define R_NDS32_LONGJUMP1 56 +#define R_NDS32_LONGJUMP2 57 +#define R_NDS32_LONGJUMP3 58 +#define R_NDS32_LOADSTORE 59 +#define R_NDS32_9_FIXED_RELA 60 +#define R_NDS32_15_FIXED_RELA 61 +#define R_NDS32_17_FIXED_RELA 62 +#define R_NDS32_25_FIXED_RELA 63 +#define R_NDS32_PLTREL_HI2064 +#define R_NDS32_PLTREL_LO1265 +#define R_NDS32_PLT_GOTREL_HI2066 +#define R_NDS32_PLT_GOTREL_LO1267 +#define R_NDS32_LO12S0_ORI_RELA72 +#define R_NDS32_DWARF2_OP1_RELA77 +#define R_NDS32_DWARF2_OP2_RELA78 +#define R_NDS32_DWARF2_LEB_RELA79 +#define R_NDS32_WORD_9_PCREL_RELA 94 +#define R_NDS32_LONGCALL4 107 +#define R_NDS32_RELA_NOP_MIX 192 +#define R_NDS32_RELA_NOP_MAX 255 + +#define ELF_NGREG (sizeof (struct pt_regs) / sizeof(elf_greg_t)) +typedef elf_greg_t elf_gregset_t[ELF_NGREG]; + +/* Core file format: The core file is written in such a way that gdb + can understand it and provide useful information to the user (under + linux we use the 'trad-core' bfd). There are quite a number of + obstacles to being able to view the contents of the floating point + registers, and until these are solved you will not be able to view the + contents of them. Actually, you can read in the core file and look at + the contents of the user struct to find out what the floating point + registers contain. + The actual file contents are as follows: + UPAGE: 1 page consisting of a user struct that tells gdb what is present + in the file. Directly after this is a copy of the task_struct, which + is currently not used by gdb, but it may come in useful at some point. + All of the registers are stored as part of the upage. The upage should + always be only one page. + DATA: The data area is stored. We use current->end_text to + current->brk to pick up all of the user variables, plus any memory + that may have been malloced. No attempt is made to determine if a page + is demand-zero or if a page is totally unused, we just cover the entire + range. All of the addresses are rounded in such a way that an integral + number of pages is
[PATCH v4 12/36] nds32: Atomic operations
From: Greentime HuThis patch includes the atomic and futex operations. Many atomic operations use the load-lock word(llw) and store-condition word(scw) operations. Signed-off-by: Vincent Chen Signed-off-by: Greentime Hu --- arch/nds32/include/asm/barrier.h | 15 ++ arch/nds32/include/asm/futex.h | 103 ++ 2 files changed, 118 insertions(+) create mode 100644 arch/nds32/include/asm/barrier.h create mode 100644 arch/nds32/include/asm/futex.h diff --git a/arch/nds32/include/asm/barrier.h b/arch/nds32/include/asm/barrier.h new file mode 100644 index 000..faafc37 --- /dev/null +++ b/arch/nds32/include/asm/barrier.h @@ -0,0 +1,15 @@ +// SPDX-License-Identifier: GPL-2.0 +// Copyright (C) 2005-2017 Andes Technology Corporation + +#ifndef __NDS32_ASM_BARRIER_H +#define __NDS32_ASM_BARRIER_H + +#ifndef __ASSEMBLY__ +#define mb() asm volatile("msync all":::"memory") +#define rmb() asm volatile("msync all":::"memory") +#define wmb() asm volatile("msync store":::"memory") +#include + +#endif /* __ASSEMBLY__ */ + +#endif /* __NDS32_ASM_BARRIER_H */ diff --git a/arch/nds32/include/asm/futex.h b/arch/nds32/include/asm/futex.h new file mode 100644 index 000..eab5e84 --- /dev/null +++ b/arch/nds32/include/asm/futex.h @@ -0,0 +1,103 @@ +// SPDX-License-Identifier: GPL-2.0 +// Copyright (C) 2005-2017 Andes Technology Corporation + +#ifndef __NDS32_FUTEX_H__ +#define __NDS32_FUTEX_H__ + +#include +#include +#include + +#define __futex_atomic_ex_table(err_reg) \ + " .pushsection __ex_table,\"a\"\n"\ + " .align 3\n"\ + " .long 1b, 4f\n" \ + " .long 2b, 4f\n" \ + " .popsection\n" \ + " .pushsection .fixup,\"ax\"\n" \ + "4: move%0, " err_reg "\n" \ + " j 3b\n" \ + " .popsection" + +#define __futex_atomic_op(insn, ret, oldval, tmp, uaddr, oparg)\ + smp_mb(); \ + asm volatile( \ + " movi$ta, #0\n" \ + "1: llw %1, [%2+$ta]\n" \ + " " insn "\n" \ + "2: scw %0, [%2+$ta]\n" \ + " beqz%0, 1b\n" \ + " movi%0, #0\n" \ + "3:\n" \ + __futex_atomic_ex_table("%4") \ + : "=" (ret), "=" (oldval) \ + : "r" (uaddr), "r" (oparg), "i" (-EFAULT) \ + : "cc", "memory") +static inline int +futex_atomic_cmpxchg_inatomic(u32 * uval, u32 __user * uaddr, + u32 oldval, u32 newval) +{ + int ret = 0; + u32 val, tmp, flags; + + if (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32))) + return -EFAULT; + + smp_mb(); + asm volatile (" movi$ta, #0\n" + "1: llw %1, [%6 + $ta]\n" + " sub %3, %1, %4\n" + " cmovz %2, %5, %3\n" + " cmovn %2, %1, %3\n" + "2: scw %2, [%6 + $ta]\n" + " beqz%2, 1b\n" + "3:\n " __futex_atomic_ex_table("%7") + :"+"(ret), "="(val), "="(tmp), "="(flags) + :"r"(oldval), "r"(newval), "r"(uaddr), "i"(-EFAULT) + :"$ta", "memory"); + smp_mb(); + + *uval = val; + return ret; +} + +static inline int +arch_futex_atomic_op_inuser(int op, int oparg, int *oval, u32 __user *uaddr) +{ + int oldval = 0, ret; + + + pagefault_disable(); + switch (op) { + case FUTEX_OP_SET: + __futex_atomic_op("move %0, %3", ret, oldval, tmp, uaddr, + oparg); + break; + case FUTEX_OP_ADD: + __futex_atomic_op("add %0, %1, %3", ret, oldval, tmp, uaddr, + oparg); + break; + case FUTEX_OP_OR: + __futex_atomic_op("or %0, %1, %3", ret, oldval, tmp, uaddr, + oparg); + break; + case FUTEX_OP_ANDN: + __futex_atomic_op("and %0, %1, %3", ret, oldval, tmp, uaddr, + ~oparg); + break; + case FUTEX_OP_XOR: +
[PATCH v4 13/36] nds32: Device specific operations
From: Greentime HuThis patch introduces ioremap implementations. Signed-off-by: Vincent Chen Signed-off-by: Greentime Hu --- arch/nds32/include/asm/io.h | 83 +++ arch/nds32/mm/ioremap.c | 62 2 files changed, 145 insertions(+) create mode 100644 arch/nds32/include/asm/io.h create mode 100644 arch/nds32/mm/ioremap.c diff --git a/arch/nds32/include/asm/io.h b/arch/nds32/include/asm/io.h new file mode 100644 index 000..81b4616 --- /dev/null +++ b/arch/nds32/include/asm/io.h @@ -0,0 +1,83 @@ +// SPDX-License-Identifier: GPL-2.0 +// Copyright (C) 2005-2017 Andes Technology Corporation + +#ifndef __ASM_NDS32_IO_H +#define __ASM_NDS32_IO_H + +extern void iounmap(void __iomem *addr); +#define __raw_writeb __raw_writeb +static inline void __raw_writeb(u8 val, volatile void __iomem *addr) +{ + asm volatile("sbi %0, [%1]" : : "r" (val), "r" (addr)); +} + +#define __raw_writew __raw_writew +static inline void __raw_writew(u16 val, volatile void __iomem *addr) +{ + asm volatile("shi %0, [%1]" : : "r" (val), "r" (addr)); +} + +#define __raw_writel __raw_writel +static inline void __raw_writel(u32 val, volatile void __iomem *addr) +{ + asm volatile("swi %0, [%1]" : : "r" (val), "r" (addr)); +} + +#define __raw_readb __raw_readb +static inline u8 __raw_readb(const volatile void __iomem *addr) +{ + u8 val; + + asm volatile("lbi %0, [%1]" : "=r" (val) : "r" (addr)); + return val; +} + +#define __raw_readw __raw_readw +static inline u16 __raw_readw(const volatile void __iomem *addr) +{ + u16 val; + + asm volatile("lhi %0, [%1]" : "=r" (val) : "r" (addr)); + return val; +} + +#define __raw_readl __raw_readl +static inline u32 __raw_readl(const volatile void __iomem *addr) +{ + u32 val; + + asm volatile("lwi %0, [%1]" : "=r" (val) : "r" (addr)); + return val; +} + +#define __iormb() rmb() +#define __iowmb() wmb() + +#define mmiowb()__asm__ __volatile__ ("msync all" : : : "memory"); + +/* + * {read,write}{b,w,l,q}_relaxed() are like the regular version, but + * are not guaranteed to provide ordering against spinlocks or memory + * accesses. + */ + +#define readb_relaxed(c) ({ u8 __v = __raw_readb(c); __v; }) +#define readw_relaxed(c) ({ u16 __v = le16_to_cpu((__force __le16)__raw_readw(c)); __v; }) +#define readl_relaxed(c) ({ u32 __v = le32_to_cpu((__force __le32)__raw_readl(c)); __v; }) +#define writeb_relaxed(v,c)((void)__raw_writeb((v),(c))) +#define writew_relaxed(v,c)((void)__raw_writew((__force u16)cpu_to_le16(v),(c))) +#define writel_relaxed(v,c)((void)__raw_writel((__force u32)cpu_to_le32(v),(c))) + +/* + * {read,write}{b,w,l,q}() access little endian memory and return result in + * native endianness. + */ +#define readb(c) ({ u8 __v = readb_relaxed(c); __iormb(); __v; }) +#define readw(c) ({ u16 __v = readw_relaxed(c); __iormb(); __v; }) +#define readl(c) ({ u32 __v = readl_relaxed(c); __iormb(); __v; }) + +#define writeb(v,c)({ __iowmb(); writeb_relaxed((v),(c)); }) +#define writew(v,c)({ __iowmb(); writew_relaxed((v),(c)); }) +#define writel(v,c)({ __iowmb(); writel_relaxed((v),(c)); }) +#include +#endif /* __ASM_NDS32_IO_H */ diff --git a/arch/nds32/mm/ioremap.c b/arch/nds32/mm/ioremap.c new file mode 100644 index 000..2f6741c --- /dev/null +++ b/arch/nds32/mm/ioremap.c @@ -0,0 +1,62 @@ +// SPDX-License-Identifier: GPL-2.0 +// Copyright (C) 2005-2017 Andes Technology Corporation + +#include +#include +#include +#include + +void __iomem *ioremap(phys_addr_t phys_addr, size_t size); + +static void __iomem *__ioremap_caller(phys_addr_t phys_addr, size_t size, + void *caller) +{ + struct vm_struct *area; + unsigned long addr, offset, last_addr; + pgprot_t prot; + + /* Don't allow wraparound or zero size */ + last_addr = phys_addr + size - 1; + if (!size || last_addr < phys_addr) + return NULL; + + /* +* Mappings have to be page-aligned +*/ + offset = phys_addr & ~PAGE_MASK; + phys_addr &= PAGE_MASK; + size = PAGE_ALIGN(last_addr + 1) - phys_addr; + + /* +* Ok, go for it.. +*/ + area = get_vm_area_caller(size, VM_IOREMAP, caller); + if (!area) + return NULL; + + area->phys_addr = phys_addr; + addr = (unsigned long)area->addr; + prot = __pgprot(_PAGE_V | _PAGE_M_KRW | _PAGE_D | + _PAGE_G | _PAGE_C_DEV); + if (ioremap_page_range(addr, addr + size, phys_addr, prot)) { + vunmap((void *)addr); + return NULL; + } + return (__force void __iomem *)(offset + (char *)addr); + +} + +void __iomem *ioremap(phys_addr_t phys_addr,
[PATCH v4 15/36] nds32: ELF definitions
From: Greentime Hu This patch adds definitions for the ELF format, relocation types, vdso locations and EXEC_PAGESIZE. Signed-off-by: Vincent Chen Signed-off-by: Greentime Hu --- arch/nds32/include/asm/elf.h | 179 ++ arch/nds32/include/uapi/asm/auxvec.h | 12 +++ arch/nds32/include/uapi/asm/param.h | 11 +++ 3 files changed, 202 insertions(+) create mode 100644 arch/nds32/include/asm/elf.h create mode 100644 arch/nds32/include/uapi/asm/auxvec.h create mode 100644 arch/nds32/include/uapi/asm/param.h diff --git a/arch/nds32/include/asm/elf.h b/arch/nds32/include/asm/elf.h new file mode 100644 index 000..99203f1 --- /dev/null +++ b/arch/nds32/include/asm/elf.h @@ -0,0 +1,179 @@ +// SPDX-License-Identifier: GPL-2.0 +// Copyright (C) 2005-2017 Andes Technology Corporation + +#ifndef __ASMNDS32_ELF_H +#define __ASMNDS32_ELF_H + +/* + * ELF register definitions.. + */ + +#include + +typedef unsigned long elf_greg_t; +typedef unsigned long elf_freg_t[3]; + +extern unsigned int elf_hwcap; + +#define EM_NDS32 167 + +#define R_NDS32_NONE 0 +#define R_NDS32_16_RELA19 +#define R_NDS32_32_RELA20 +#define R_NDS32_9_PCREL_RELA 22 +#define R_NDS32_15_PCREL_RELA 23 +#define R_NDS32_17_PCREL_RELA 24 +#define R_NDS32_25_PCREL_RELA 25 +#define R_NDS32_HI20_RELA 26 +#define R_NDS32_LO12S3_RELA27 +#define R_NDS32_LO12S2_RELA28 +#define R_NDS32_LO12S1_RELA29 +#define R_NDS32_LO12S0_RELA30 +#define R_NDS32_SDA15S3_RELA 31 +#define R_NDS32_SDA15S2_RELA 32 +#define R_NDS32_SDA15S1_RELA 33 +#define R_NDS32_SDA15S0_RELA 34 +#define R_NDS32_GOT20 37 +#define R_NDS32_25_PLTREL 38 +#define R_NDS32_COPY 39 +#define R_NDS32_GLOB_DAT 40 +#define R_NDS32_JMP_SLOT 41 +#define R_NDS32_RELATIVE 42 +#define R_NDS32_GOTOFF 43 +#define R_NDS32_GOTPC2044 +#define R_NDS32_GOT_HI20 45 +#define R_NDS32_GOT_LO12 46 +#define R_NDS32_GOTPC_HI20 47 +#define R_NDS32_GOTPC_LO12 48 +#define R_NDS32_GOTOFF_HI2049 +#define R_NDS32_GOTOFF_LO1250 +#define R_NDS32_INSN16 51 +#define R_NDS32_LABEL 52 +#define R_NDS32_LONGCALL1 53 +#define R_NDS32_LONGCALL2 54 +#define R_NDS32_LONGCALL3 55 +#define R_NDS32_LONGJUMP1 56 +#define R_NDS32_LONGJUMP2 57 +#define R_NDS32_LONGJUMP3 58 +#define R_NDS32_LOADSTORE 59 +#define R_NDS32_9_FIXED_RELA 60 +#define R_NDS32_15_FIXED_RELA 61 +#define R_NDS32_17_FIXED_RELA 62 +#define R_NDS32_25_FIXED_RELA 63 +#define R_NDS32_PLTREL_HI2064 +#define R_NDS32_PLTREL_LO1265 +#define R_NDS32_PLT_GOTREL_HI2066 +#define R_NDS32_PLT_GOTREL_LO1267 +#define R_NDS32_LO12S0_ORI_RELA72 +#define R_NDS32_DWARF2_OP1_RELA77 +#define R_NDS32_DWARF2_OP2_RELA78 +#define R_NDS32_DWARF2_LEB_RELA79 +#define R_NDS32_WORD_9_PCREL_RELA 94 +#define R_NDS32_LONGCALL4 107 +#define R_NDS32_RELA_NOP_MIX 192 +#define R_NDS32_RELA_NOP_MAX 255 + +#define ELF_NGREG (sizeof (struct pt_regs) / sizeof(elf_greg_t)) +typedef elf_greg_t elf_gregset_t[ELF_NGREG]; + +/* Core file format: The core file is written in such a way that gdb + can understand it and provide useful information to the user (under + linux we use the 'trad-core' bfd). There are quite a number of + obstacles to being able to view the contents of the floating point + registers, and until these are solved you will not be able to view the + contents of them. Actually, you can read in the core file and look at + the contents of the user struct to find out what the floating point + registers contain. + The actual file contents are as follows: + UPAGE: 1 page consisting of a user struct that tells gdb what is present + in the file. Directly after this is a copy of the task_struct, which + is currently not used by gdb, but it may come in useful at some point. + All of the registers are stored as part of the upage. The upage should + always be only one page. + DATA: The data area is stored. We use current->end_text to + current->brk to pick up all of the user variables, plus any memory + that may have been malloced. No attempt is made to determine if a page + is demand-zero or if a page is totally unused, we just cover the entire + range. All of the addresses are rounded in such a way that an integral + number of pages is written. + STACK: We need the stack information in order to get a
[PATCH v4 12/36] nds32: Atomic operations
From: Greentime Hu This patch includes the atomic and futex operations. Many atomic operations use the load-lock word(llw) and store-condition word(scw) operations. Signed-off-by: Vincent Chen Signed-off-by: Greentime Hu --- arch/nds32/include/asm/barrier.h | 15 ++ arch/nds32/include/asm/futex.h | 103 ++ 2 files changed, 118 insertions(+) create mode 100644 arch/nds32/include/asm/barrier.h create mode 100644 arch/nds32/include/asm/futex.h diff --git a/arch/nds32/include/asm/barrier.h b/arch/nds32/include/asm/barrier.h new file mode 100644 index 000..faafc37 --- /dev/null +++ b/arch/nds32/include/asm/barrier.h @@ -0,0 +1,15 @@ +// SPDX-License-Identifier: GPL-2.0 +// Copyright (C) 2005-2017 Andes Technology Corporation + +#ifndef __NDS32_ASM_BARRIER_H +#define __NDS32_ASM_BARRIER_H + +#ifndef __ASSEMBLY__ +#define mb() asm volatile("msync all":::"memory") +#define rmb() asm volatile("msync all":::"memory") +#define wmb() asm volatile("msync store":::"memory") +#include + +#endif /* __ASSEMBLY__ */ + +#endif /* __NDS32_ASM_BARRIER_H */ diff --git a/arch/nds32/include/asm/futex.h b/arch/nds32/include/asm/futex.h new file mode 100644 index 000..eab5e84 --- /dev/null +++ b/arch/nds32/include/asm/futex.h @@ -0,0 +1,103 @@ +// SPDX-License-Identifier: GPL-2.0 +// Copyright (C) 2005-2017 Andes Technology Corporation + +#ifndef __NDS32_FUTEX_H__ +#define __NDS32_FUTEX_H__ + +#include +#include +#include + +#define __futex_atomic_ex_table(err_reg) \ + " .pushsection __ex_table,\"a\"\n"\ + " .align 3\n"\ + " .long 1b, 4f\n" \ + " .long 2b, 4f\n" \ + " .popsection\n" \ + " .pushsection .fixup,\"ax\"\n" \ + "4: move%0, " err_reg "\n" \ + " j 3b\n" \ + " .popsection" + +#define __futex_atomic_op(insn, ret, oldval, tmp, uaddr, oparg)\ + smp_mb(); \ + asm volatile( \ + " movi$ta, #0\n" \ + "1: llw %1, [%2+$ta]\n" \ + " " insn "\n" \ + "2: scw %0, [%2+$ta]\n" \ + " beqz%0, 1b\n" \ + " movi%0, #0\n" \ + "3:\n" \ + __futex_atomic_ex_table("%4") \ + : "=" (ret), "=" (oldval) \ + : "r" (uaddr), "r" (oparg), "i" (-EFAULT) \ + : "cc", "memory") +static inline int +futex_atomic_cmpxchg_inatomic(u32 * uval, u32 __user * uaddr, + u32 oldval, u32 newval) +{ + int ret = 0; + u32 val, tmp, flags; + + if (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32))) + return -EFAULT; + + smp_mb(); + asm volatile (" movi$ta, #0\n" + "1: llw %1, [%6 + $ta]\n" + " sub %3, %1, %4\n" + " cmovz %2, %5, %3\n" + " cmovn %2, %1, %3\n" + "2: scw %2, [%6 + $ta]\n" + " beqz%2, 1b\n" + "3:\n " __futex_atomic_ex_table("%7") + :"+"(ret), "="(val), "="(tmp), "="(flags) + :"r"(oldval), "r"(newval), "r"(uaddr), "i"(-EFAULT) + :"$ta", "memory"); + smp_mb(); + + *uval = val; + return ret; +} + +static inline int +arch_futex_atomic_op_inuser(int op, int oparg, int *oval, u32 __user *uaddr) +{ + int oldval = 0, ret; + + + pagefault_disable(); + switch (op) { + case FUTEX_OP_SET: + __futex_atomic_op("move %0, %3", ret, oldval, tmp, uaddr, + oparg); + break; + case FUTEX_OP_ADD: + __futex_atomic_op("add %0, %1, %3", ret, oldval, tmp, uaddr, + oparg); + break; + case FUTEX_OP_OR: + __futex_atomic_op("or %0, %1, %3", ret, oldval, tmp, uaddr, + oparg); + break; + case FUTEX_OP_ANDN: + __futex_atomic_op("and %0, %1, %3", ret, oldval, tmp, uaddr, + ~oparg); + break; + case FUTEX_OP_XOR: + __futex_atomic_op("xor %0, %1, %3", ret, oldval, tmp, uaddr, +
[PATCH v4 13/36] nds32: Device specific operations
From: Greentime Hu This patch introduces ioremap implementations. Signed-off-by: Vincent Chen Signed-off-by: Greentime Hu --- arch/nds32/include/asm/io.h | 83 +++ arch/nds32/mm/ioremap.c | 62 2 files changed, 145 insertions(+) create mode 100644 arch/nds32/include/asm/io.h create mode 100644 arch/nds32/mm/ioremap.c diff --git a/arch/nds32/include/asm/io.h b/arch/nds32/include/asm/io.h new file mode 100644 index 000..81b4616 --- /dev/null +++ b/arch/nds32/include/asm/io.h @@ -0,0 +1,83 @@ +// SPDX-License-Identifier: GPL-2.0 +// Copyright (C) 2005-2017 Andes Technology Corporation + +#ifndef __ASM_NDS32_IO_H +#define __ASM_NDS32_IO_H + +extern void iounmap(void __iomem *addr); +#define __raw_writeb __raw_writeb +static inline void __raw_writeb(u8 val, volatile void __iomem *addr) +{ + asm volatile("sbi %0, [%1]" : : "r" (val), "r" (addr)); +} + +#define __raw_writew __raw_writew +static inline void __raw_writew(u16 val, volatile void __iomem *addr) +{ + asm volatile("shi %0, [%1]" : : "r" (val), "r" (addr)); +} + +#define __raw_writel __raw_writel +static inline void __raw_writel(u32 val, volatile void __iomem *addr) +{ + asm volatile("swi %0, [%1]" : : "r" (val), "r" (addr)); +} + +#define __raw_readb __raw_readb +static inline u8 __raw_readb(const volatile void __iomem *addr) +{ + u8 val; + + asm volatile("lbi %0, [%1]" : "=r" (val) : "r" (addr)); + return val; +} + +#define __raw_readw __raw_readw +static inline u16 __raw_readw(const volatile void __iomem *addr) +{ + u16 val; + + asm volatile("lhi %0, [%1]" : "=r" (val) : "r" (addr)); + return val; +} + +#define __raw_readl __raw_readl +static inline u32 __raw_readl(const volatile void __iomem *addr) +{ + u32 val; + + asm volatile("lwi %0, [%1]" : "=r" (val) : "r" (addr)); + return val; +} + +#define __iormb() rmb() +#define __iowmb() wmb() + +#define mmiowb()__asm__ __volatile__ ("msync all" : : : "memory"); + +/* + * {read,write}{b,w,l,q}_relaxed() are like the regular version, but + * are not guaranteed to provide ordering against spinlocks or memory + * accesses. + */ + +#define readb_relaxed(c) ({ u8 __v = __raw_readb(c); __v; }) +#define readw_relaxed(c) ({ u16 __v = le16_to_cpu((__force __le16)__raw_readw(c)); __v; }) +#define readl_relaxed(c) ({ u32 __v = le32_to_cpu((__force __le32)__raw_readl(c)); __v; }) +#define writeb_relaxed(v,c)((void)__raw_writeb((v),(c))) +#define writew_relaxed(v,c)((void)__raw_writew((__force u16)cpu_to_le16(v),(c))) +#define writel_relaxed(v,c)((void)__raw_writel((__force u32)cpu_to_le32(v),(c))) + +/* + * {read,write}{b,w,l,q}() access little endian memory and return result in + * native endianness. + */ +#define readb(c) ({ u8 __v = readb_relaxed(c); __iormb(); __v; }) +#define readw(c) ({ u16 __v = readw_relaxed(c); __iormb(); __v; }) +#define readl(c) ({ u32 __v = readl_relaxed(c); __iormb(); __v; }) + +#define writeb(v,c)({ __iowmb(); writeb_relaxed((v),(c)); }) +#define writew(v,c)({ __iowmb(); writew_relaxed((v),(c)); }) +#define writel(v,c)({ __iowmb(); writel_relaxed((v),(c)); }) +#include +#endif /* __ASM_NDS32_IO_H */ diff --git a/arch/nds32/mm/ioremap.c b/arch/nds32/mm/ioremap.c new file mode 100644 index 000..2f6741c --- /dev/null +++ b/arch/nds32/mm/ioremap.c @@ -0,0 +1,62 @@ +// SPDX-License-Identifier: GPL-2.0 +// Copyright (C) 2005-2017 Andes Technology Corporation + +#include +#include +#include +#include + +void __iomem *ioremap(phys_addr_t phys_addr, size_t size); + +static void __iomem *__ioremap_caller(phys_addr_t phys_addr, size_t size, + void *caller) +{ + struct vm_struct *area; + unsigned long addr, offset, last_addr; + pgprot_t prot; + + /* Don't allow wraparound or zero size */ + last_addr = phys_addr + size - 1; + if (!size || last_addr < phys_addr) + return NULL; + + /* +* Mappings have to be page-aligned +*/ + offset = phys_addr & ~PAGE_MASK; + phys_addr &= PAGE_MASK; + size = PAGE_ALIGN(last_addr + 1) - phys_addr; + + /* +* Ok, go for it.. +*/ + area = get_vm_area_caller(size, VM_IOREMAP, caller); + if (!area) + return NULL; + + area->phys_addr = phys_addr; + addr = (unsigned long)area->addr; + prot = __pgprot(_PAGE_V | _PAGE_M_KRW | _PAGE_D | + _PAGE_G | _PAGE_C_DEV); + if (ioremap_page_range(addr, addr + size, phys_addr, prot)) { + vunmap((void *)addr); + return NULL; + } + return (__force void __iomem *)(offset + (char *)addr); + +} + +void __iomem *ioremap(phys_addr_t phys_addr, size_t size) +{ + return __ioremap_caller(phys_addr, size, +
[PATCH v4 17/36] nds32: VDSO support
From: Greentime HuThis patch adds VDSO support. The VDSO code is currently used for sys_rt_sigreturn() and optimised gettimeofday() (using the SoC timer counter). Signed-off-by: Vincent Chen Signed-off-by: Greentime Hu --- arch/nds32/include/asm/vdso.h | 24 +++ arch/nds32/include/asm/vdso_datapage.h | 36 arch/nds32/include/asm/vdso_timer_info.h | 14 ++ arch/nds32/kernel/vdso.c | 233 arch/nds32/kernel/vdso/Makefile| 82 + arch/nds32/kernel/vdso/datapage.S | 21 +++ arch/nds32/kernel/vdso/gen_vdso_offsets.sh | 15 ++ arch/nds32/kernel/vdso/gettimeofday.c | 271 arch/nds32/kernel/vdso/note.S | 11 ++ arch/nds32/kernel/vdso/sigreturn.S | 19 ++ arch/nds32/kernel/vdso/vdso.S | 18 ++ arch/nds32/kernel/vdso/vdso.lds.S | 76 12 files changed, 820 insertions(+) create mode 100644 arch/nds32/include/asm/vdso.h create mode 100644 arch/nds32/include/asm/vdso_datapage.h create mode 100644 arch/nds32/include/asm/vdso_timer_info.h create mode 100644 arch/nds32/kernel/vdso.c create mode 100644 arch/nds32/kernel/vdso/Makefile create mode 100644 arch/nds32/kernel/vdso/datapage.S create mode 100755 arch/nds32/kernel/vdso/gen_vdso_offsets.sh create mode 100644 arch/nds32/kernel/vdso/gettimeofday.c create mode 100644 arch/nds32/kernel/vdso/note.S create mode 100644 arch/nds32/kernel/vdso/sigreturn.S create mode 100644 arch/nds32/kernel/vdso/vdso.S create mode 100644 arch/nds32/kernel/vdso/vdso.lds.S diff --git a/arch/nds32/include/asm/vdso.h b/arch/nds32/include/asm/vdso.h new file mode 100644 index 000..af2c6af --- /dev/null +++ b/arch/nds32/include/asm/vdso.h @@ -0,0 +1,24 @@ +/* + * SPDX-License-Identifier: GPL-2.0 + * Copyright (C) 2005-2017 Andes Technology Corporation + */ + +#ifndef __ASM_VDSO_H +#define __ASM_VDSO_H + +#ifdef __KERNEL__ + +#ifndef __ASSEMBLY__ + +#include + +#define VDSO_SYMBOL(base, name) \ +({\ + (unsigned long)(vdso_offset_##name + (unsigned long)(base)); \ +}) + +#endif /* !__ASSEMBLY__ */ + +#endif /* __KERNEL__ */ + +#endif /* __ASM_VDSO_H */ diff --git a/arch/nds32/include/asm/vdso_datapage.h b/arch/nds32/include/asm/vdso_datapage.h new file mode 100644 index 000..79db5a1 --- /dev/null +++ b/arch/nds32/include/asm/vdso_datapage.h @@ -0,0 +1,36 @@ +// SPDX-License-Identifier: GPL-2.0 +// Copyright (C) 2012 ARM Limited +// Copyright (C) 2005-2017 Andes Technology Corporation +#ifndef __ASM_VDSO_DATAPAGE_H +#define __ASM_VDSO_DATAPAGE_H + +#ifdef __KERNEL__ + +#ifndef __ASSEMBLY__ + +struct vdso_data { + bool cycle_count_down; /* timer cyclye counter is decrease with time */ + u32 cycle_count_offset; /* offset of timer cycle counter register */ + u32 seq_count; /* sequence count - odd during updates */ + u32 xtime_coarse_sec; /* coarse time */ + u32 xtime_coarse_nsec; + + u32 wtm_clock_sec; /* wall to monotonic offset */ + u32 wtm_clock_nsec; + u32 xtime_clock_sec;/* CLOCK_REALTIME - seconds */ + u32 cs_mult;/* clocksource multiplier */ + u32 cs_shift; /* Cycle to nanosecond divisor (power of two) */ + + u64 cs_cycle_last; /* last cycle value */ + u64 cs_mask;/* clocksource mask */ + + u64 xtime_clock_nsec; /* CLOCK_REALTIME sub-ns base */ + u32 tz_minuteswest; /* timezone info for gettimeofday(2) */ + u32 tz_dsttime; +}; + +#endif /* !__ASSEMBLY__ */ + +#endif /* __KERNEL__ */ + +#endif /* __ASM_VDSO_DATAPAGE_H */ diff --git a/arch/nds32/include/asm/vdso_timer_info.h b/arch/nds32/include/asm/vdso_timer_info.h new file mode 100644 index 000..50ba117 --- /dev/null +++ b/arch/nds32/include/asm/vdso_timer_info.h @@ -0,0 +1,14 @@ +// SPDX-License-Identifier: GPL-2.0 +// Copyright (C) 2005-2017 Andes Technology Corporation + +extern struct timer_info_t timer_info; +#define EMPTY_VALUE ~(0UL) +#define EMPTY_TIMER_MAPPING EMPTY_VALUE +#define EMPTY_REG_OFFSET EMPTY_VALUE + +struct timer_info_t +{ + bool cycle_count_down; + unsigned long mapping_base; + unsigned long cycle_count_reg_offset; +}; diff --git a/arch/nds32/kernel/vdso.c b/arch/nds32/kernel/vdso.c new file mode 100644 index 000..2eb01f4 --- /dev/null +++ b/arch/nds32/kernel/vdso.c @@ -0,0 +1,233 @@ +// SPDX-License-Identifier: GPL-2.0 +// Copyright (C) 2012 ARM Limited +// Copyright (C) 2005-2017 Andes Technology Corporation + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include
[PATCH v4 17/36] nds32: VDSO support
From: Greentime Hu This patch adds VDSO support. The VDSO code is currently used for sys_rt_sigreturn() and optimised gettimeofday() (using the SoC timer counter). Signed-off-by: Vincent Chen Signed-off-by: Greentime Hu --- arch/nds32/include/asm/vdso.h | 24 +++ arch/nds32/include/asm/vdso_datapage.h | 36 arch/nds32/include/asm/vdso_timer_info.h | 14 ++ arch/nds32/kernel/vdso.c | 233 arch/nds32/kernel/vdso/Makefile| 82 + arch/nds32/kernel/vdso/datapage.S | 21 +++ arch/nds32/kernel/vdso/gen_vdso_offsets.sh | 15 ++ arch/nds32/kernel/vdso/gettimeofday.c | 271 arch/nds32/kernel/vdso/note.S | 11 ++ arch/nds32/kernel/vdso/sigreturn.S | 19 ++ arch/nds32/kernel/vdso/vdso.S | 18 ++ arch/nds32/kernel/vdso/vdso.lds.S | 76 12 files changed, 820 insertions(+) create mode 100644 arch/nds32/include/asm/vdso.h create mode 100644 arch/nds32/include/asm/vdso_datapage.h create mode 100644 arch/nds32/include/asm/vdso_timer_info.h create mode 100644 arch/nds32/kernel/vdso.c create mode 100644 arch/nds32/kernel/vdso/Makefile create mode 100644 arch/nds32/kernel/vdso/datapage.S create mode 100755 arch/nds32/kernel/vdso/gen_vdso_offsets.sh create mode 100644 arch/nds32/kernel/vdso/gettimeofday.c create mode 100644 arch/nds32/kernel/vdso/note.S create mode 100644 arch/nds32/kernel/vdso/sigreturn.S create mode 100644 arch/nds32/kernel/vdso/vdso.S create mode 100644 arch/nds32/kernel/vdso/vdso.lds.S diff --git a/arch/nds32/include/asm/vdso.h b/arch/nds32/include/asm/vdso.h new file mode 100644 index 000..af2c6af --- /dev/null +++ b/arch/nds32/include/asm/vdso.h @@ -0,0 +1,24 @@ +/* + * SPDX-License-Identifier: GPL-2.0 + * Copyright (C) 2005-2017 Andes Technology Corporation + */ + +#ifndef __ASM_VDSO_H +#define __ASM_VDSO_H + +#ifdef __KERNEL__ + +#ifndef __ASSEMBLY__ + +#include + +#define VDSO_SYMBOL(base, name) \ +({\ + (unsigned long)(vdso_offset_##name + (unsigned long)(base)); \ +}) + +#endif /* !__ASSEMBLY__ */ + +#endif /* __KERNEL__ */ + +#endif /* __ASM_VDSO_H */ diff --git a/arch/nds32/include/asm/vdso_datapage.h b/arch/nds32/include/asm/vdso_datapage.h new file mode 100644 index 000..79db5a1 --- /dev/null +++ b/arch/nds32/include/asm/vdso_datapage.h @@ -0,0 +1,36 @@ +// SPDX-License-Identifier: GPL-2.0 +// Copyright (C) 2012 ARM Limited +// Copyright (C) 2005-2017 Andes Technology Corporation +#ifndef __ASM_VDSO_DATAPAGE_H +#define __ASM_VDSO_DATAPAGE_H + +#ifdef __KERNEL__ + +#ifndef __ASSEMBLY__ + +struct vdso_data { + bool cycle_count_down; /* timer cyclye counter is decrease with time */ + u32 cycle_count_offset; /* offset of timer cycle counter register */ + u32 seq_count; /* sequence count - odd during updates */ + u32 xtime_coarse_sec; /* coarse time */ + u32 xtime_coarse_nsec; + + u32 wtm_clock_sec; /* wall to monotonic offset */ + u32 wtm_clock_nsec; + u32 xtime_clock_sec;/* CLOCK_REALTIME - seconds */ + u32 cs_mult;/* clocksource multiplier */ + u32 cs_shift; /* Cycle to nanosecond divisor (power of two) */ + + u64 cs_cycle_last; /* last cycle value */ + u64 cs_mask;/* clocksource mask */ + + u64 xtime_clock_nsec; /* CLOCK_REALTIME sub-ns base */ + u32 tz_minuteswest; /* timezone info for gettimeofday(2) */ + u32 tz_dsttime; +}; + +#endif /* !__ASSEMBLY__ */ + +#endif /* __KERNEL__ */ + +#endif /* __ASM_VDSO_DATAPAGE_H */ diff --git a/arch/nds32/include/asm/vdso_timer_info.h b/arch/nds32/include/asm/vdso_timer_info.h new file mode 100644 index 000..50ba117 --- /dev/null +++ b/arch/nds32/include/asm/vdso_timer_info.h @@ -0,0 +1,14 @@ +// SPDX-License-Identifier: GPL-2.0 +// Copyright (C) 2005-2017 Andes Technology Corporation + +extern struct timer_info_t timer_info; +#define EMPTY_VALUE ~(0UL) +#define EMPTY_TIMER_MAPPING EMPTY_VALUE +#define EMPTY_REG_OFFSET EMPTY_VALUE + +struct timer_info_t +{ + bool cycle_count_down; + unsigned long mapping_base; + unsigned long cycle_count_reg_offset; +}; diff --git a/arch/nds32/kernel/vdso.c b/arch/nds32/kernel/vdso.c new file mode 100644 index 000..2eb01f4 --- /dev/null +++ b/arch/nds32/kernel/vdso.c @@ -0,0 +1,233 @@ +// SPDX-License-Identifier: GPL-2.0 +// Copyright (C) 2012 ARM Limited +// Copyright (C) 2005-2017 Andes Technology Corporation + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +extern struct cache_info L1_cache_info[2];
[PATCH v4 21/36] nds32: L2 cache support
From: Greentime HuThis patch adds L2 cache support. Signed-off-by: Vincent Chen Signed-off-by: Greentime Hu --- arch/nds32/include/asm/l2_cache.h | 142 + arch/nds32/kernel/atl2c.c | 64 + 2 files changed, 206 insertions(+) create mode 100644 arch/nds32/include/asm/l2_cache.h create mode 100644 arch/nds32/kernel/atl2c.c diff --git a/arch/nds32/include/asm/l2_cache.h b/arch/nds32/include/asm/l2_cache.h new file mode 100644 index 000..7706dd0 --- /dev/null +++ b/arch/nds32/include/asm/l2_cache.h @@ -0,0 +1,142 @@ +// SPDX-License-Identifier: GPL-2.0 +// Copyright (C) 2005-2017 Andes Technology Corporation + +#ifndef L2_CACHE_H +#define L2_CACHE_H + +/* CCTL_CMD_OP */ +#define L2_CA_CONF_OFF 0x0 +#define L2_IF_CONF_OFF 0x4 +#define L2CC_SETUP_OFF 0x8 +#define L2CC_PROT_OFF 0xC +#define L2CC_CTRL_OFF 0x10 +#define L2_INT_EN_OFF 0x20 +#define L2_STA_OFF 0x24 +#define RDERR_ADDR_OFF 0x28 +#define WRERR_ADDR_OFF 0x2c +#define EVDPTERR_ADDR_OFF 0x30 +#define IMPL3ERR_ADDR_OFF 0x34 +#define L2_CNT0_CTRL_OFF0x40 +#define L2_EVNT_CNT0_OFF0x44 +#define L2_CNT1_CTRL_OFF0x48 +#define L2_EVNT_CNT1_OFF0x4c +#define L2_CCTL_CMD_OFF0x60 +#define L2_CCTL_STATUS_OFF 0x64 +#define L2_LINE_TAG_OFF0x68 +#define L2_LINE_DPT_OFF0x70 + +#define CCTL_CMD_L2_IX_INVAL0x0 +#define CCTL_CMD_L2_PA_INVAL0x1 +#define CCTL_CMD_L2_IX_WB 0x2 +#define CCTL_CMD_L2_PA_WB 0x3 +#define CCTL_CMD_L2_PA_WBINVAL 0x5 +#define CCTL_CMD_L2_SYNC0xa + +/* CCTL_CMD_TYPE */ +#define CCTL_SINGLE_CMD 0 +#define CCTL_BLOCK_CMD 0x10 +#define CCTL_ALL_CMD 0x10 + +/** + * L2_CA_CONF (Cache architecture configuration) + */ +#define L2_CA_CONF_offL2SET0 +#define L2_CA_CONF_offL2WAY4 +#define L2_CA_CONF_offL2CLSZ8 +#define L2_CA_CONF_offL2DW 11 +#define L2_CA_CONF_offL2PT 14 +#define L2_CA_CONF_offL2VER16 + +#define L2_CA_CONF_mskL2SET(0xFUL << L2_CA_CONF_offL2SET) +#define L2_CA_CONF_mskL2WAY(0xFUL << L2_CA_CONF_offL2WAY) +#define L2_CA_CONF_mskL2CLSZ(0x7UL << L2_CA_CONF_offL2CLSZ) +#define L2_CA_CONF_mskL2DW (0x7UL << L2_CA_CONF_offL2DW) +#define L2_CA_CONF_mskL2PT (0x3UL << L2_CA_CONF_offL2PT) +#define L2_CA_CONF_mskL2VER(0xUL << L2_CA_CONF_offL2VER) + +/** + * L2CC_SETUP (L2CC Setup register) + */ +#define L2CC_SETUP_offPART 0 +#define L2CC_SETUP_mskPART (0x3UL << L2CC_SETUP_offPART) +#define L2CC_SETUP_offDDLATC4 +#define L2CC_SETUP_mskDDLATC(0x3UL << L2CC_SETUP_offDDLATC) +#define L2CC_SETUP_offTDLATC8 +#define L2CC_SETUP_mskTDLATC(0x3UL << L2CC_SETUP_offTDLATC) + +/** + * L2CC_PROT (L2CC Protect register) + */ +#define L2CC_PROT_offMRWEN 31 +#define L2CC_PROT_mskMRWEN (0x1UL << L2CC_PROT_offMRWEN) + +/** + * L2_CCTL_STATUS_Mn (The L2CCTL command working status for Master n) + */ +#define L2CC_CTRL_offEN 31 +#define L2CC_CTRL_mskEN (0x1UL << L2CC_CTRL_offEN) + +/** + * L2_CCTL_STATUS_Mn (The L2CCTL command working status for Master n) + */ +#define L2_CCTL_STATUS_offCMD_COMP 31 +#define L2_CCTL_STATUS_mskCMD_COMP (0x1 << L2_CCTL_STATUS_offCMD_COMP) + +#ifndef __ASSEMBLY__ +extern void __iomem *atl2c_base; + +#include +#include +#include + +#define L2C_R_REG(offset) readl(atl2c_base + offset) +#define L2C_W_REG(offset, value)writel(value, atl2c_base + offset) + +#define L2_CMD_RDY()\ +do{;}while((L2C_R_REG(L2_CCTL_STATUS_OFF) & L2_CCTL_STATUS_mskCMD_COMP) == 0) + +static inline unsigned long L2_CACHE_SET(void) +{ + return 64 << ((L2C_R_REG(L2_CA_CONF_OFF) & L2_CA_CONF_mskL2SET) >> + L2_CA_CONF_offL2SET); +} + +static inline unsigned long L2_CACHE_WAY(void) +{ + return 1 + + ((L2C_R_REG(L2_CA_CONF_OFF) & L2_CA_CONF_mskL2WAY) >> +
[PATCH v4 21/36] nds32: L2 cache support
From: Greentime Hu This patch adds L2 cache support. Signed-off-by: Vincent Chen Signed-off-by: Greentime Hu --- arch/nds32/include/asm/l2_cache.h | 142 + arch/nds32/kernel/atl2c.c | 64 + 2 files changed, 206 insertions(+) create mode 100644 arch/nds32/include/asm/l2_cache.h create mode 100644 arch/nds32/kernel/atl2c.c diff --git a/arch/nds32/include/asm/l2_cache.h b/arch/nds32/include/asm/l2_cache.h new file mode 100644 index 000..7706dd0 --- /dev/null +++ b/arch/nds32/include/asm/l2_cache.h @@ -0,0 +1,142 @@ +// SPDX-License-Identifier: GPL-2.0 +// Copyright (C) 2005-2017 Andes Technology Corporation + +#ifndef L2_CACHE_H +#define L2_CACHE_H + +/* CCTL_CMD_OP */ +#define L2_CA_CONF_OFF 0x0 +#define L2_IF_CONF_OFF 0x4 +#define L2CC_SETUP_OFF 0x8 +#define L2CC_PROT_OFF 0xC +#define L2CC_CTRL_OFF 0x10 +#define L2_INT_EN_OFF 0x20 +#define L2_STA_OFF 0x24 +#define RDERR_ADDR_OFF 0x28 +#define WRERR_ADDR_OFF 0x2c +#define EVDPTERR_ADDR_OFF 0x30 +#define IMPL3ERR_ADDR_OFF 0x34 +#define L2_CNT0_CTRL_OFF0x40 +#define L2_EVNT_CNT0_OFF0x44 +#define L2_CNT1_CTRL_OFF0x48 +#define L2_EVNT_CNT1_OFF0x4c +#define L2_CCTL_CMD_OFF0x60 +#define L2_CCTL_STATUS_OFF 0x64 +#define L2_LINE_TAG_OFF0x68 +#define L2_LINE_DPT_OFF0x70 + +#define CCTL_CMD_L2_IX_INVAL0x0 +#define CCTL_CMD_L2_PA_INVAL0x1 +#define CCTL_CMD_L2_IX_WB 0x2 +#define CCTL_CMD_L2_PA_WB 0x3 +#define CCTL_CMD_L2_PA_WBINVAL 0x5 +#define CCTL_CMD_L2_SYNC0xa + +/* CCTL_CMD_TYPE */ +#define CCTL_SINGLE_CMD 0 +#define CCTL_BLOCK_CMD 0x10 +#define CCTL_ALL_CMD 0x10 + +/** + * L2_CA_CONF (Cache architecture configuration) + */ +#define L2_CA_CONF_offL2SET0 +#define L2_CA_CONF_offL2WAY4 +#define L2_CA_CONF_offL2CLSZ8 +#define L2_CA_CONF_offL2DW 11 +#define L2_CA_CONF_offL2PT 14 +#define L2_CA_CONF_offL2VER16 + +#define L2_CA_CONF_mskL2SET(0xFUL << L2_CA_CONF_offL2SET) +#define L2_CA_CONF_mskL2WAY(0xFUL << L2_CA_CONF_offL2WAY) +#define L2_CA_CONF_mskL2CLSZ(0x7UL << L2_CA_CONF_offL2CLSZ) +#define L2_CA_CONF_mskL2DW (0x7UL << L2_CA_CONF_offL2DW) +#define L2_CA_CONF_mskL2PT (0x3UL << L2_CA_CONF_offL2PT) +#define L2_CA_CONF_mskL2VER(0xUL << L2_CA_CONF_offL2VER) + +/** + * L2CC_SETUP (L2CC Setup register) + */ +#define L2CC_SETUP_offPART 0 +#define L2CC_SETUP_mskPART (0x3UL << L2CC_SETUP_offPART) +#define L2CC_SETUP_offDDLATC4 +#define L2CC_SETUP_mskDDLATC(0x3UL << L2CC_SETUP_offDDLATC) +#define L2CC_SETUP_offTDLATC8 +#define L2CC_SETUP_mskTDLATC(0x3UL << L2CC_SETUP_offTDLATC) + +/** + * L2CC_PROT (L2CC Protect register) + */ +#define L2CC_PROT_offMRWEN 31 +#define L2CC_PROT_mskMRWEN (0x1UL << L2CC_PROT_offMRWEN) + +/** + * L2_CCTL_STATUS_Mn (The L2CCTL command working status for Master n) + */ +#define L2CC_CTRL_offEN 31 +#define L2CC_CTRL_mskEN (0x1UL << L2CC_CTRL_offEN) + +/** + * L2_CCTL_STATUS_Mn (The L2CCTL command working status for Master n) + */ +#define L2_CCTL_STATUS_offCMD_COMP 31 +#define L2_CCTL_STATUS_mskCMD_COMP (0x1 << L2_CCTL_STATUS_offCMD_COMP) + +#ifndef __ASSEMBLY__ +extern void __iomem *atl2c_base; + +#include +#include +#include + +#define L2C_R_REG(offset) readl(atl2c_base + offset) +#define L2C_W_REG(offset, value)writel(value, atl2c_base + offset) + +#define L2_CMD_RDY()\ +do{;}while((L2C_R_REG(L2_CCTL_STATUS_OFF) & L2_CCTL_STATUS_mskCMD_COMP) == 0) + +static inline unsigned long L2_CACHE_SET(void) +{ + return 64 << ((L2C_R_REG(L2_CA_CONF_OFF) & L2_CA_CONF_mskL2SET) >> + L2_CA_CONF_offL2SET); +} + +static inline unsigned long L2_CACHE_WAY(void) +{ + return 1 + + ((L2C_R_REG(L2_CA_CONF_OFF) & L2_CA_CONF_mskL2WAY) >> +L2_CA_CONF_offL2WAY); +} + +static inline unsigned long
[PATCH v4 19/36] nds32: Library functions
From: Greentime HuThis patch add support for various library functions. Signed-off-by: Vincent Chen Signed-off-by: Greentime Hu --- arch/nds32/include/asm/string.h | 17 +++ arch/nds32/include/asm/swab.h| 35 + arch/nds32/include/asm/uaccess.h | 283 ++ arch/nds32/kernel/nds32_ksyms.c | 31 + arch/nds32/lib/Makefile |3 + arch/nds32/lib/clear_user.S | 42 ++ arch/nds32/lib/copy_from_user.S | 45 ++ arch/nds32/lib/copy_template.S | 70 ++ arch/nds32/lib/copy_to_user.S| 45 ++ arch/nds32/lib/memcpy.S | 30 arch/nds32/lib/memmove.S | 70 ++ arch/nds32/lib/memset.S | 33 + arch/nds32/lib/memzero.S | 18 +++ 13 files changed, 722 insertions(+) create mode 100644 arch/nds32/include/asm/string.h create mode 100644 arch/nds32/include/asm/swab.h create mode 100644 arch/nds32/include/asm/uaccess.h create mode 100644 arch/nds32/kernel/nds32_ksyms.c create mode 100644 arch/nds32/lib/Makefile create mode 100644 arch/nds32/lib/clear_user.S create mode 100644 arch/nds32/lib/copy_from_user.S create mode 100644 arch/nds32/lib/copy_template.S create mode 100644 arch/nds32/lib/copy_to_user.S create mode 100644 arch/nds32/lib/memcpy.S create mode 100644 arch/nds32/lib/memmove.S create mode 100644 arch/nds32/lib/memset.S create mode 100644 arch/nds32/lib/memzero.S diff --git a/arch/nds32/include/asm/string.h b/arch/nds32/include/asm/string.h new file mode 100644 index 000..179272c --- /dev/null +++ b/arch/nds32/include/asm/string.h @@ -0,0 +1,17 @@ +// SPDX-License-Identifier: GPL-2.0 +// Copyright (C) 2005-2017 Andes Technology Corporation + +#ifndef __ASM_NDS32_STRING_H +#define __ASM_NDS32_STRING_H + +#define __HAVE_ARCH_MEMCPY +extern void *memcpy(void *, const void *, __kernel_size_t); + +#define __HAVE_ARCH_MEMMOVE +extern void *memmove(void *, const void *, __kernel_size_t); + +#define __HAVE_ARCH_MEMSET +extern void *memset(void *, int, __kernel_size_t); + +extern void *memzero(void *ptr, __kernel_size_t n); +#endif diff --git a/arch/nds32/include/asm/swab.h b/arch/nds32/include/asm/swab.h new file mode 100644 index 000..e01a755 --- /dev/null +++ b/arch/nds32/include/asm/swab.h @@ -0,0 +1,35 @@ +// SPDX-License-Identifier: GPL-2.0 +// Copyright (C) 2005-2017 Andes Technology Corporation + +#ifndef __NDS32_SWAB_H__ +#define __NDS32_SWAB_H__ + +#include +#include + +static __inline__ __attribute_const__ __u32 ___arch__swab32(__u32 x) +{ + __asm__("wsbh %0, %0\n\t" /* word swap byte within halfword */ + "rotri %0, %0, #16\n" + :"=r"(x) + :"0"(x)); + return x; +} + +static __inline__ __attribute_const__ __u16 ___arch__swab16(__u16 x) +{ + __asm__("wsbh %0, %0\n" /* word swap byte within halfword */ + :"=r"(x) + :"0"(x)); + return x; +} + +#define __arch_swab32(x) ___arch__swab32(x) +#define __arch_swab16(x) ___arch__swab16(x) + +#if !defined(__STRICT_ANSI__) || defined(__KERNEL__) +#define __BYTEORDER_HAS_U64__ +#define __SWAB_64_THRU_32__ +#endif + +#endif /* __NDS32_SWAB_H__ */ diff --git a/arch/nds32/include/asm/uaccess.h b/arch/nds32/include/asm/uaccess.h new file mode 100644 index 000..18a009f --- /dev/null +++ b/arch/nds32/include/asm/uaccess.h @@ -0,0 +1,283 @@ +// SPDX-License-Identifier: GPL-2.0 +// Copyright (C) 2005-2017 Andes Technology Corporation + +#ifndef _ASMANDES_UACCESS_H +#define _ASMANDES_UACCESS_H + +/* + * User space memory access functions + */ +#include +#include +#include +#include +#include + +#define VERIFY_READ0 +#define VERIFY_WRITE 1 + +#define __asmeq(x, y) ".ifnc " x "," y " ; .err ; .endif\n\t" + +/* + * The exception table consists of pairs of addresses: the first is the + * address of an instruction that is allowed to fault, and the second is + * the address at which the program should continue. No registers are + * modified, so it is entirely up to the continuation code to figure out + * what to do. + * + * All the routines below use bits of fixup code that are out of line + * with the main instruction path. This means when everything is well, + * we don't even have to jump over them. Further, they do not intrude + * on our cache or tlb entries. + */ + +struct exception_table_entry { + unsigned long insn, fixup; +}; + +extern int fixup_exception(struct pt_regs *regs); + +#define KERNEL_DS ((mm_segment_t) { ~0UL }) +#define USER_DS((mm_segment_t) {TASK_SIZE - 1}) + +#define get_ds() (KERNEL_DS) +#define get_fs() (current_thread_info()->addr_limit) +#define user_addr_max get_fs + +static inline void set_fs(mm_segment_t fs) +{ + current_thread_info()->addr_limit = fs; +} + +#define segment_eq(a, b)((a) == (b)) + +#define __range_ok(addr, size) (size <=
[PATCH v4 19/36] nds32: Library functions
From: Greentime Hu This patch add support for various library functions. Signed-off-by: Vincent Chen Signed-off-by: Greentime Hu --- arch/nds32/include/asm/string.h | 17 +++ arch/nds32/include/asm/swab.h| 35 + arch/nds32/include/asm/uaccess.h | 283 ++ arch/nds32/kernel/nds32_ksyms.c | 31 + arch/nds32/lib/Makefile |3 + arch/nds32/lib/clear_user.S | 42 ++ arch/nds32/lib/copy_from_user.S | 45 ++ arch/nds32/lib/copy_template.S | 70 ++ arch/nds32/lib/copy_to_user.S| 45 ++ arch/nds32/lib/memcpy.S | 30 arch/nds32/lib/memmove.S | 70 ++ arch/nds32/lib/memset.S | 33 + arch/nds32/lib/memzero.S | 18 +++ 13 files changed, 722 insertions(+) create mode 100644 arch/nds32/include/asm/string.h create mode 100644 arch/nds32/include/asm/swab.h create mode 100644 arch/nds32/include/asm/uaccess.h create mode 100644 arch/nds32/kernel/nds32_ksyms.c create mode 100644 arch/nds32/lib/Makefile create mode 100644 arch/nds32/lib/clear_user.S create mode 100644 arch/nds32/lib/copy_from_user.S create mode 100644 arch/nds32/lib/copy_template.S create mode 100644 arch/nds32/lib/copy_to_user.S create mode 100644 arch/nds32/lib/memcpy.S create mode 100644 arch/nds32/lib/memmove.S create mode 100644 arch/nds32/lib/memset.S create mode 100644 arch/nds32/lib/memzero.S diff --git a/arch/nds32/include/asm/string.h b/arch/nds32/include/asm/string.h new file mode 100644 index 000..179272c --- /dev/null +++ b/arch/nds32/include/asm/string.h @@ -0,0 +1,17 @@ +// SPDX-License-Identifier: GPL-2.0 +// Copyright (C) 2005-2017 Andes Technology Corporation + +#ifndef __ASM_NDS32_STRING_H +#define __ASM_NDS32_STRING_H + +#define __HAVE_ARCH_MEMCPY +extern void *memcpy(void *, const void *, __kernel_size_t); + +#define __HAVE_ARCH_MEMMOVE +extern void *memmove(void *, const void *, __kernel_size_t); + +#define __HAVE_ARCH_MEMSET +extern void *memset(void *, int, __kernel_size_t); + +extern void *memzero(void *ptr, __kernel_size_t n); +#endif diff --git a/arch/nds32/include/asm/swab.h b/arch/nds32/include/asm/swab.h new file mode 100644 index 000..e01a755 --- /dev/null +++ b/arch/nds32/include/asm/swab.h @@ -0,0 +1,35 @@ +// SPDX-License-Identifier: GPL-2.0 +// Copyright (C) 2005-2017 Andes Technology Corporation + +#ifndef __NDS32_SWAB_H__ +#define __NDS32_SWAB_H__ + +#include +#include + +static __inline__ __attribute_const__ __u32 ___arch__swab32(__u32 x) +{ + __asm__("wsbh %0, %0\n\t" /* word swap byte within halfword */ + "rotri %0, %0, #16\n" + :"=r"(x) + :"0"(x)); + return x; +} + +static __inline__ __attribute_const__ __u16 ___arch__swab16(__u16 x) +{ + __asm__("wsbh %0, %0\n" /* word swap byte within halfword */ + :"=r"(x) + :"0"(x)); + return x; +} + +#define __arch_swab32(x) ___arch__swab32(x) +#define __arch_swab16(x) ___arch__swab16(x) + +#if !defined(__STRICT_ANSI__) || defined(__KERNEL__) +#define __BYTEORDER_HAS_U64__ +#define __SWAB_64_THRU_32__ +#endif + +#endif /* __NDS32_SWAB_H__ */ diff --git a/arch/nds32/include/asm/uaccess.h b/arch/nds32/include/asm/uaccess.h new file mode 100644 index 000..18a009f --- /dev/null +++ b/arch/nds32/include/asm/uaccess.h @@ -0,0 +1,283 @@ +// SPDX-License-Identifier: GPL-2.0 +// Copyright (C) 2005-2017 Andes Technology Corporation + +#ifndef _ASMANDES_UACCESS_H +#define _ASMANDES_UACCESS_H + +/* + * User space memory access functions + */ +#include +#include +#include +#include +#include + +#define VERIFY_READ0 +#define VERIFY_WRITE 1 + +#define __asmeq(x, y) ".ifnc " x "," y " ; .err ; .endif\n\t" + +/* + * The exception table consists of pairs of addresses: the first is the + * address of an instruction that is allowed to fault, and the second is + * the address at which the program should continue. No registers are + * modified, so it is entirely up to the continuation code to figure out + * what to do. + * + * All the routines below use bits of fixup code that are out of line + * with the main instruction path. This means when everything is well, + * we don't even have to jump over them. Further, they do not intrude + * on our cache or tlb entries. + */ + +struct exception_table_entry { + unsigned long insn, fixup; +}; + +extern int fixup_exception(struct pt_regs *regs); + +#define KERNEL_DS ((mm_segment_t) { ~0UL }) +#define USER_DS((mm_segment_t) {TASK_SIZE - 1}) + +#define get_ds() (KERNEL_DS) +#define get_fs() (current_thread_info()->addr_limit) +#define user_addr_max get_fs + +static inline void set_fs(mm_segment_t fs) +{ + current_thread_info()->addr_limit = fs; +} + +#define segment_eq(a, b)((a) == (b)) + +#define __range_ok(addr, size) (size <= get_fs() && addr <= (get_fs() -size)) + +#define access_ok(type, addr,
[PATCH SERIES 5: 00/16] staging: lustre: use standard wait_event macros
Lustre has l_wait_event() which is a complex macro that does similar things to the wait_event macro family in Linux. This patch series converts all l_wait_event to something more familiar to Linux developers. Some of the conversions are subtle. I think I've understood the code and got the conversion correct, but I've quite possibly messed up. If you only review one series, this is the one that demands review. I haven't converted the single use of l_wait_event_exclusive_head(). That needs more thought. This is the last series for today. I do have some more patches, but that are all individual patches that I hope to send as a set of ad-hoc patches tomorrow. Thanks, NeilBrown --- NeilBrown (16): staging: lustre: discard SVC_SIGNAL and related functions staging: lustre: replace simple cases of l_wait_event() with wait_event(). staging: lustre: discard cfs_time_seconds() staging: lustre: use wait_event_timeout() where appropriate. staging: lustre: introduce and use l_wait_event_abortable() staging: lustre: simplify l_wait_event when intr handler but no timeout. staging: lustre: simplify waiting in ldlm_completion_ast() staging: lustre: open code polling loop instead of using l_wait_event() staging: lustre: simplify waiting in ptlrpc_invalidate_import() staging: lustre: remove back_to_sleep() and use loops. staging: lustre: make polling loop in ptlrpc_unregister_bulk more obvious staging: lustre: use wait_event_timeout in ptlrpcd() staging: lustre: improve waiting in sptlrpc_req_refresh_ctx staging: lustre: use explicit poll loop in ptlrpc_service_unlink_rqbd staging: lustre: use explicit poll loop in ptlrpc_unregister_reply staging: lustre: remove l_wait_event from ptlrpc_set_wait .../lustre/include/linux/libcfs/libcfs_debug.h |4 - .../lustre/include/linux/libcfs/libcfs_time.h |2 .../lustre/include/linux/libcfs/linux/linux-time.h |7 - .../staging/lustre/lnet/klnds/o2iblnd/o2iblnd.c|8 + .../staging/lustre/lnet/klnds/o2iblnd/o2iblnd_cb.c |4 - .../staging/lustre/lnet/klnds/socklnd/socklnd.c|6 - .../staging/lustre/lnet/klnds/socklnd/socklnd_cb.c | 22 ++- drivers/staging/lustre/lnet/libcfs/debug.c |2 drivers/staging/lustre/lnet/libcfs/fail.c |2 drivers/staging/lustre/lnet/libcfs/tracefile.c |4 - drivers/staging/lustre/lnet/lnet/acceptor.c|2 drivers/staging/lustre/lnet/lnet/api-ni.c |4 - drivers/staging/lustre/lnet/lnet/lib-move.c|4 - drivers/staging/lustre/lnet/lnet/net_fault.c | 14 +- drivers/staging/lustre/lnet/lnet/peer.c|2 drivers/staging/lustre/lnet/lnet/router.c |8 + drivers/staging/lustre/lnet/selftest/conrpc.c |4 - drivers/staging/lustre/lnet/selftest/rpc.c |2 drivers/staging/lustre/lnet/selftest/selftest.h|2 drivers/staging/lustre/lnet/selftest/timer.c |2 drivers/staging/lustre/lustre/include/lustre_dlm.h |2 drivers/staging/lustre/lustre/include/lustre_lib.h | 126 ++-- drivers/staging/lustre/lustre/include/lustre_mdc.h |2 drivers/staging/lustre/lustre/include/lustre_net.h |8 - drivers/staging/lustre/lustre/ldlm/ldlm_flock.c| 30 + drivers/staging/lustre/lustre/ldlm/ldlm_lock.c | 14 +- drivers/staging/lustre/lustre/ldlm/ldlm_lockd.c| 12 +- drivers/staging/lustre/lustre/ldlm/ldlm_pool.c | 17 +-- drivers/staging/lustre/lustre/ldlm/ldlm_request.c | 51 +++- drivers/staging/lustre/lustre/ldlm/ldlm_resource.c | 14 +- drivers/staging/lustre/lustre/llite/llite_lib.c| 23 +--- drivers/staging/lustre/lustre/llite/statahead.c| 60 -- drivers/staging/lustre/lustre/lov/lov_object.c |6 - drivers/staging/lustre/lustre/lov/lov_request.c| 12 +- drivers/staging/lustre/lustre/mdc/mdc_request.c|5 - drivers/staging/lustre/lustre/mgc/mgc_request.c| 19 +-- drivers/staging/lustre/lustre/obdclass/cl_io.c | 23 ++-- drivers/staging/lustre/lustre/obdclass/genops.c| 24 +--- drivers/staging/lustre/lustre/obdclass/llog_obd.c |5 - .../staging/lustre/lustre/obdecho/echo_client.c|2 drivers/staging/lustre/lustre/osc/osc_cache.c | 28 ++-- drivers/staging/lustre/lustre/osc/osc_object.c |6 - drivers/staging/lustre/lustre/osc/osc_page.c |6 - drivers/staging/lustre/lustre/osc/osc_request.c|6 - drivers/staging/lustre/lustre/ptlrpc/client.c | 101 +++- drivers/staging/lustre/lustre/ptlrpc/events.c |7 - drivers/staging/lustre/lustre/ptlrpc/import.c | 51 +++- drivers/staging/lustre/lustre/ptlrpc/niobuf.c | 14 +- .../staging/lustre/lustre/ptlrpc/pack_generic.c|9 + drivers/staging/lustre/lustre/ptlrpc/pinger.c | 28 ++-- .../staging/lustre/lustre/ptlrpc/ptlrpc_internal.h |2
[PATCH SERIES 5: 00/16] staging: lustre: use standard wait_event macros
Lustre has l_wait_event() which is a complex macro that does similar things to the wait_event macro family in Linux. This patch series converts all l_wait_event to something more familiar to Linux developers. Some of the conversions are subtle. I think I've understood the code and got the conversion correct, but I've quite possibly messed up. If you only review one series, this is the one that demands review. I haven't converted the single use of l_wait_event_exclusive_head(). That needs more thought. This is the last series for today. I do have some more patches, but that are all individual patches that I hope to send as a set of ad-hoc patches tomorrow. Thanks, NeilBrown --- NeilBrown (16): staging: lustre: discard SVC_SIGNAL and related functions staging: lustre: replace simple cases of l_wait_event() with wait_event(). staging: lustre: discard cfs_time_seconds() staging: lustre: use wait_event_timeout() where appropriate. staging: lustre: introduce and use l_wait_event_abortable() staging: lustre: simplify l_wait_event when intr handler but no timeout. staging: lustre: simplify waiting in ldlm_completion_ast() staging: lustre: open code polling loop instead of using l_wait_event() staging: lustre: simplify waiting in ptlrpc_invalidate_import() staging: lustre: remove back_to_sleep() and use loops. staging: lustre: make polling loop in ptlrpc_unregister_bulk more obvious staging: lustre: use wait_event_timeout in ptlrpcd() staging: lustre: improve waiting in sptlrpc_req_refresh_ctx staging: lustre: use explicit poll loop in ptlrpc_service_unlink_rqbd staging: lustre: use explicit poll loop in ptlrpc_unregister_reply staging: lustre: remove l_wait_event from ptlrpc_set_wait .../lustre/include/linux/libcfs/libcfs_debug.h |4 - .../lustre/include/linux/libcfs/libcfs_time.h |2 .../lustre/include/linux/libcfs/linux/linux-time.h |7 - .../staging/lustre/lnet/klnds/o2iblnd/o2iblnd.c|8 + .../staging/lustre/lnet/klnds/o2iblnd/o2iblnd_cb.c |4 - .../staging/lustre/lnet/klnds/socklnd/socklnd.c|6 - .../staging/lustre/lnet/klnds/socklnd/socklnd_cb.c | 22 ++- drivers/staging/lustre/lnet/libcfs/debug.c |2 drivers/staging/lustre/lnet/libcfs/fail.c |2 drivers/staging/lustre/lnet/libcfs/tracefile.c |4 - drivers/staging/lustre/lnet/lnet/acceptor.c|2 drivers/staging/lustre/lnet/lnet/api-ni.c |4 - drivers/staging/lustre/lnet/lnet/lib-move.c|4 - drivers/staging/lustre/lnet/lnet/net_fault.c | 14 +- drivers/staging/lustre/lnet/lnet/peer.c|2 drivers/staging/lustre/lnet/lnet/router.c |8 + drivers/staging/lustre/lnet/selftest/conrpc.c |4 - drivers/staging/lustre/lnet/selftest/rpc.c |2 drivers/staging/lustre/lnet/selftest/selftest.h|2 drivers/staging/lustre/lnet/selftest/timer.c |2 drivers/staging/lustre/lustre/include/lustre_dlm.h |2 drivers/staging/lustre/lustre/include/lustre_lib.h | 126 ++-- drivers/staging/lustre/lustre/include/lustre_mdc.h |2 drivers/staging/lustre/lustre/include/lustre_net.h |8 - drivers/staging/lustre/lustre/ldlm/ldlm_flock.c| 30 + drivers/staging/lustre/lustre/ldlm/ldlm_lock.c | 14 +- drivers/staging/lustre/lustre/ldlm/ldlm_lockd.c| 12 +- drivers/staging/lustre/lustre/ldlm/ldlm_pool.c | 17 +-- drivers/staging/lustre/lustre/ldlm/ldlm_request.c | 51 +++- drivers/staging/lustre/lustre/ldlm/ldlm_resource.c | 14 +- drivers/staging/lustre/lustre/llite/llite_lib.c| 23 +--- drivers/staging/lustre/lustre/llite/statahead.c| 60 -- drivers/staging/lustre/lustre/lov/lov_object.c |6 - drivers/staging/lustre/lustre/lov/lov_request.c| 12 +- drivers/staging/lustre/lustre/mdc/mdc_request.c|5 - drivers/staging/lustre/lustre/mgc/mgc_request.c| 19 +-- drivers/staging/lustre/lustre/obdclass/cl_io.c | 23 ++-- drivers/staging/lustre/lustre/obdclass/genops.c| 24 +--- drivers/staging/lustre/lustre/obdclass/llog_obd.c |5 - .../staging/lustre/lustre/obdecho/echo_client.c|2 drivers/staging/lustre/lustre/osc/osc_cache.c | 28 ++-- drivers/staging/lustre/lustre/osc/osc_object.c |6 - drivers/staging/lustre/lustre/osc/osc_page.c |6 - drivers/staging/lustre/lustre/osc/osc_request.c|6 - drivers/staging/lustre/lustre/ptlrpc/client.c | 101 +++- drivers/staging/lustre/lustre/ptlrpc/events.c |7 - drivers/staging/lustre/lustre/ptlrpc/import.c | 51 +++- drivers/staging/lustre/lustre/ptlrpc/niobuf.c | 14 +- .../staging/lustre/lustre/ptlrpc/pack_generic.c|9 + drivers/staging/lustre/lustre/ptlrpc/pinger.c | 28 ++-- .../staging/lustre/lustre/ptlrpc/ptlrpc_internal.h |2
[PATCH 16/16] staging: lustre: remove l_wait_event from ptlrpc_set_wait
This is the last remaining use of l_wait_event(). It is the only use of LWI_TIMEOUT_INTR_ALL() which has a meaning that timeouts can be interrupted. Only interrupts by "fatal" signals are allowed, so introduce l_wait_event_abortable_timeout() to support this. Signed-off-by: NeilBrown--- drivers/staging/lustre/lustre/include/lustre_lib.h | 10 ++ drivers/staging/lustre/lustre/ptlrpc/client.c | 86 .../staging/lustre/lustre/ptlrpc/ptlrpc_internal.h |2 3 files changed, 47 insertions(+), 51 deletions(-) diff --git a/drivers/staging/lustre/lustre/include/lustre_lib.h b/drivers/staging/lustre/lustre/include/lustre_lib.h index d157ed35a0bf..b23d3015b1c0 100644 --- a/drivers/staging/lustre/lustre/include/lustre_lib.h +++ b/drivers/staging/lustre/lustre/include/lustre_lib.h @@ -440,6 +440,16 @@ do { \ __ret; \ }) +#define l_wait_event_abortable_timeout(wq, condition, timeout) \ +({ \ + sigset_t __blocked; \ + int __ret = 0; \ + __blocked = cfs_block_sigsinv(LUSTRE_FATAL_SIGS); \ + __ret = wait_event_interruptible_timeout(wq, condition, timeout);\ + cfs_restore_sigs(__blocked);\ + __ret; \ +}) + #define l_wait_event_abortable_exclusive(wq, condition) \ ({ \ sigset_t __blocked; \ diff --git a/drivers/staging/lustre/lustre/ptlrpc/client.c b/drivers/staging/lustre/lustre/ptlrpc/client.c index bb8c9ab68f5f..95131a34a98f 100644 --- a/drivers/staging/lustre/lustre/ptlrpc/client.c +++ b/drivers/staging/lustre/lustre/ptlrpc/client.c @@ -1774,7 +1774,7 @@ int ptlrpc_check_set(const struct lu_env *env, struct ptlrpc_request_set *set) } /* -* ptlrpc_set_wait->l_wait_event sets lwi_allow_intr +* ptlrpc_set_wait allow signal to abort the timeout * so it sets rq_intr regardless of individual rpc * timeouts. The synchronous IO waiting path sets * rq_intr irrespective of whether ptlrpcd @@ -2122,10 +2122,9 @@ int ptlrpc_expire_one_request(struct ptlrpc_request *req, int async_unlink) /** * Time out all uncompleted requests in request set pointed by \a data - * Callback used when waiting on sets with l_wait_event. - * Always returns 1. + * Called when wait_event_timeout times out. */ -int ptlrpc_expired_set(struct ptlrpc_request_set *set) +void ptlrpc_expired_set(struct ptlrpc_request_set *set) { struct list_head *tmp; time64_t now = ktime_get_real_seconds(); @@ -2155,18 +2154,6 @@ int ptlrpc_expired_set(struct ptlrpc_request_set *set) */ ptlrpc_expire_one_request(req, 1); } - - /* -* When waiting for a whole set, we always break out of the -* sleep so we can recalculate the timeout, or enable interrupts -* if everyone's timed out. -*/ - return 1; -} -static int ptlrpc_expired_set_void(void *data) -{ - struct ptlrpc_request_set *set = data; - return ptlrpc_expired_set(set); } /** @@ -2182,11 +2169,10 @@ EXPORT_SYMBOL(ptlrpc_mark_interrupted); /** * Interrupts (sets interrupted flag) all uncompleted requests in - * a set \a data. Callback for l_wait_event for interruptible waits. + * a set \a data. Called when wait_event_timeout receives signal. */ -static void ptlrpc_interrupted_set(void *data) +static void ptlrpc_interrupted_set(struct ptlrpc_request_set *set) { - struct ptlrpc_request_set *set = data; struct list_head *tmp; CDEBUG(D_RPCTRACE, "INTERRUPTED SET %p\n", set); @@ -2256,7 +2242,6 @@ int ptlrpc_set_wait(struct ptlrpc_request_set *set) { struct list_head *tmp; struct ptlrpc_request *req; - struct l_wait_info lwi; int rc, timeout; if (set->set_producer) @@ -2282,46 +2267,47 @@ int ptlrpc_set_wait(struct ptlrpc_request_set *set) CDEBUG(D_RPCTRACE, "set %p going to sleep for %d seconds\n", set, timeout); - if (timeout == 0 && !signal_pending(current)) + if (timeout == 0 && !signal_pending(current)) { /* * No requests are in-flight (ether timed out * or delayed), so we can allow interrupts. * We still want to block for a limited time, * so we allow interrupts during the
[PATCH 16/16] staging: lustre: remove l_wait_event from ptlrpc_set_wait
This is the last remaining use of l_wait_event(). It is the only use of LWI_TIMEOUT_INTR_ALL() which has a meaning that timeouts can be interrupted. Only interrupts by "fatal" signals are allowed, so introduce l_wait_event_abortable_timeout() to support this. Signed-off-by: NeilBrown --- drivers/staging/lustre/lustre/include/lustre_lib.h | 10 ++ drivers/staging/lustre/lustre/ptlrpc/client.c | 86 .../staging/lustre/lustre/ptlrpc/ptlrpc_internal.h |2 3 files changed, 47 insertions(+), 51 deletions(-) diff --git a/drivers/staging/lustre/lustre/include/lustre_lib.h b/drivers/staging/lustre/lustre/include/lustre_lib.h index d157ed35a0bf..b23d3015b1c0 100644 --- a/drivers/staging/lustre/lustre/include/lustre_lib.h +++ b/drivers/staging/lustre/lustre/include/lustre_lib.h @@ -440,6 +440,16 @@ do { \ __ret; \ }) +#define l_wait_event_abortable_timeout(wq, condition, timeout) \ +({ \ + sigset_t __blocked; \ + int __ret = 0; \ + __blocked = cfs_block_sigsinv(LUSTRE_FATAL_SIGS); \ + __ret = wait_event_interruptible_timeout(wq, condition, timeout);\ + cfs_restore_sigs(__blocked);\ + __ret; \ +}) + #define l_wait_event_abortable_exclusive(wq, condition) \ ({ \ sigset_t __blocked; \ diff --git a/drivers/staging/lustre/lustre/ptlrpc/client.c b/drivers/staging/lustre/lustre/ptlrpc/client.c index bb8c9ab68f5f..95131a34a98f 100644 --- a/drivers/staging/lustre/lustre/ptlrpc/client.c +++ b/drivers/staging/lustre/lustre/ptlrpc/client.c @@ -1774,7 +1774,7 @@ int ptlrpc_check_set(const struct lu_env *env, struct ptlrpc_request_set *set) } /* -* ptlrpc_set_wait->l_wait_event sets lwi_allow_intr +* ptlrpc_set_wait allow signal to abort the timeout * so it sets rq_intr regardless of individual rpc * timeouts. The synchronous IO waiting path sets * rq_intr irrespective of whether ptlrpcd @@ -2122,10 +2122,9 @@ int ptlrpc_expire_one_request(struct ptlrpc_request *req, int async_unlink) /** * Time out all uncompleted requests in request set pointed by \a data - * Callback used when waiting on sets with l_wait_event. - * Always returns 1. + * Called when wait_event_timeout times out. */ -int ptlrpc_expired_set(struct ptlrpc_request_set *set) +void ptlrpc_expired_set(struct ptlrpc_request_set *set) { struct list_head *tmp; time64_t now = ktime_get_real_seconds(); @@ -2155,18 +2154,6 @@ int ptlrpc_expired_set(struct ptlrpc_request_set *set) */ ptlrpc_expire_one_request(req, 1); } - - /* -* When waiting for a whole set, we always break out of the -* sleep so we can recalculate the timeout, or enable interrupts -* if everyone's timed out. -*/ - return 1; -} -static int ptlrpc_expired_set_void(void *data) -{ - struct ptlrpc_request_set *set = data; - return ptlrpc_expired_set(set); } /** @@ -2182,11 +2169,10 @@ EXPORT_SYMBOL(ptlrpc_mark_interrupted); /** * Interrupts (sets interrupted flag) all uncompleted requests in - * a set \a data. Callback for l_wait_event for interruptible waits. + * a set \a data. Called when wait_event_timeout receives signal. */ -static void ptlrpc_interrupted_set(void *data) +static void ptlrpc_interrupted_set(struct ptlrpc_request_set *set) { - struct ptlrpc_request_set *set = data; struct list_head *tmp; CDEBUG(D_RPCTRACE, "INTERRUPTED SET %p\n", set); @@ -2256,7 +2242,6 @@ int ptlrpc_set_wait(struct ptlrpc_request_set *set) { struct list_head *tmp; struct ptlrpc_request *req; - struct l_wait_info lwi; int rc, timeout; if (set->set_producer) @@ -2282,46 +2267,47 @@ int ptlrpc_set_wait(struct ptlrpc_request_set *set) CDEBUG(D_RPCTRACE, "set %p going to sleep for %d seconds\n", set, timeout); - if (timeout == 0 && !signal_pending(current)) + if (timeout == 0 && !signal_pending(current)) { /* * No requests are in-flight (ether timed out * or delayed), so we can allow interrupts. * We still want to block for a limited time, * so we allow interrupts during the timeout.
[PATCH 14/16] staging: lustre: use explicit poll loop in ptlrpc_service_unlink_rqbd
Rather an using l_wait_event(), use wait_event_timeout() with an explicit loop so it is easier to see what is happening. Signed-off-by: NeilBrown--- drivers/staging/lustre/lustre/ptlrpc/service.c | 15 --- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/drivers/staging/lustre/lustre/ptlrpc/service.c b/drivers/staging/lustre/lustre/ptlrpc/service.c index c568baf8c28f..8c77693510a1 100644 --- a/drivers/staging/lustre/lustre/ptlrpc/service.c +++ b/drivers/staging/lustre/lustre/ptlrpc/service.c @@ -2617,7 +2617,7 @@ ptlrpc_service_unlink_rqbd(struct ptlrpc_service *svc) { struct ptlrpc_service_part *svcpt; struct ptlrpc_request_buffer_desc *rqbd; - struct l_wait_info lwi; + int cnt; int rc; int i; @@ -2657,12 +2657,13 @@ ptlrpc_service_unlink_rqbd(struct ptlrpc_service *svc) * the HUGE timeout lets us CWARN for visibility * of sluggish LNDs */ - lwi = LWI_TIMEOUT_INTERVAL( - LONG_UNLINK * HZ, - HZ, NULL, NULL); - rc = l_wait_event(svcpt->scp_waitq, - svcpt->scp_nrqbds_posted == 0, ); - if (rc == -ETIMEDOUT) { + cnt = 0; + while (cnt < LONG_UNLINK && + (rc = wait_event_timeout(svcpt->scp_waitq, + svcpt->scp_nrqbds_posted == 0, + HZ)) == 0) + cnt ++; + if (rc == 0) { CWARN("Service %s waiting for request buffers\n", svcpt->scp_service->srv_name); }
[PATCH 14/16] staging: lustre: use explicit poll loop in ptlrpc_service_unlink_rqbd
Rather an using l_wait_event(), use wait_event_timeout() with an explicit loop so it is easier to see what is happening. Signed-off-by: NeilBrown --- drivers/staging/lustre/lustre/ptlrpc/service.c | 15 --- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/drivers/staging/lustre/lustre/ptlrpc/service.c b/drivers/staging/lustre/lustre/ptlrpc/service.c index c568baf8c28f..8c77693510a1 100644 --- a/drivers/staging/lustre/lustre/ptlrpc/service.c +++ b/drivers/staging/lustre/lustre/ptlrpc/service.c @@ -2617,7 +2617,7 @@ ptlrpc_service_unlink_rqbd(struct ptlrpc_service *svc) { struct ptlrpc_service_part *svcpt; struct ptlrpc_request_buffer_desc *rqbd; - struct l_wait_info lwi; + int cnt; int rc; int i; @@ -2657,12 +2657,13 @@ ptlrpc_service_unlink_rqbd(struct ptlrpc_service *svc) * the HUGE timeout lets us CWARN for visibility * of sluggish LNDs */ - lwi = LWI_TIMEOUT_INTERVAL( - LONG_UNLINK * HZ, - HZ, NULL, NULL); - rc = l_wait_event(svcpt->scp_waitq, - svcpt->scp_nrqbds_posted == 0, ); - if (rc == -ETIMEDOUT) { + cnt = 0; + while (cnt < LONG_UNLINK && + (rc = wait_event_timeout(svcpt->scp_waitq, + svcpt->scp_nrqbds_posted == 0, + HZ)) == 0) + cnt ++; + if (rc == 0) { CWARN("Service %s waiting for request buffers\n", svcpt->scp_service->srv_name); }
[PATCH 15/16] staging: lustre: use explicit poll loop in ptlrpc_unregister_reply
replace l_wait_event() with wait_event_timeout() and explicit loop. This approach is easier to understand. Signed-off-by: NeilBrown--- drivers/staging/lustre/lustre/ptlrpc/client.c | 14 +++--- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/drivers/staging/lustre/lustre/ptlrpc/client.c b/drivers/staging/lustre/lustre/ptlrpc/client.c index 3e6d22beb9f5..bb8c9ab68f5f 100644 --- a/drivers/staging/lustre/lustre/ptlrpc/client.c +++ b/drivers/staging/lustre/lustre/ptlrpc/client.c @@ -2500,7 +2500,6 @@ static int ptlrpc_unregister_reply(struct ptlrpc_request *request, int async) { int rc; wait_queue_head_t *wq; - struct l_wait_info lwi; /* Might sleep. */ LASSERT(!in_interrupt()); @@ -2543,16 +2542,17 @@ static int ptlrpc_unregister_reply(struct ptlrpc_request *request, int async) * Network access will complete in finite time but the HUGE * timeout lets us CWARN for visibility of sluggish NALs */ - lwi = LWI_TIMEOUT_INTERVAL(LONG_UNLINK * HZ, - HZ, NULL, NULL); - rc = l_wait_event(*wq, !ptlrpc_client_recv_or_unlink(request), - ); - if (rc == 0) { + int cnt = 0; + while (cnt < LONG_UNLINK && + (rc = wait_event_timeout(*wq, + !ptlrpc_client_recv_or_unlink(request), + HZ)) == 0) + cnt += 1; + if (rc > 0) { ptlrpc_rqphase_move(request, request->rq_next_phase); return 1; } - LASSERT(rc == -ETIMEDOUT); DEBUG_REQ(D_WARNING, request, "Unexpectedly long timeout receiving_reply=%d req_ulinked=%d reply_unlinked=%d", request->rq_receiving_reply,
[PATCH 13/16] staging: lustre: improve waiting in sptlrpc_req_refresh_ctx
Replace l_wait_event with wait_event_timeout() and call the handler function explicitly. This makes it more clear what is happening. Signed-off-by: NeilBrown--- drivers/staging/lustre/lustre/ptlrpc/sec.c | 23 +-- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/drivers/staging/lustre/lustre/ptlrpc/sec.c b/drivers/staging/lustre/lustre/ptlrpc/sec.c index 617e004d00f8..6292840f1fca 100644 --- a/drivers/staging/lustre/lustre/ptlrpc/sec.c +++ b/drivers/staging/lustre/lustre/ptlrpc/sec.c @@ -554,9 +554,8 @@ int ctx_check_refresh(struct ptlrpc_cli_ctx *ctx) } static -int ctx_refresh_timeout(void *data) +int ctx_refresh_timeout(struct ptlrpc_request *req) { - struct ptlrpc_request *req = data; int rc; /* conn_cnt is needed in expire_one_request */ @@ -575,10 +574,8 @@ int ctx_refresh_timeout(void *data) } static -void ctx_refresh_interrupt(void *data) +void ctx_refresh_interrupt(struct ptlrpc_request *req) { - struct ptlrpc_request *req = data; - spin_lock(>rq_lock); req->rq_intr = 1; spin_unlock(>rq_lock); @@ -611,7 +608,6 @@ int sptlrpc_req_refresh_ctx(struct ptlrpc_request *req, long timeout) { struct ptlrpc_cli_ctx *ctx = req->rq_cli_ctx; struct ptlrpc_sec *sec; - struct l_wait_info lwi; int rc; LASSERT(ctx); @@ -743,10 +739,17 @@ int sptlrpc_req_refresh_ctx(struct ptlrpc_request *req, long timeout) req->rq_restart = 0; spin_unlock(>rq_lock); - lwi = LWI_TIMEOUT_INTR(msecs_to_jiffies(timeout * MSEC_PER_SEC), - ctx_refresh_timeout, ctx_refresh_interrupt, - req); - rc = l_wait_event(req->rq_reply_waitq, ctx_check_refresh(ctx), ); + rc = wait_event_timeout(req->rq_reply_waitq, + ctx_check_refresh(ctx), + timeout * HZ); + if (rc > 0) + rc = 0; + else if (ctx_refresh_timeout(req)) + rc = -ETIMEDOUT; + else if (l_fatal_signal_pending(current)) { + rc = -EINTR; + ctx_refresh_interrupt(req); + } /* * following cases could lead us here:
[PATCH 15/16] staging: lustre: use explicit poll loop in ptlrpc_unregister_reply
replace l_wait_event() with wait_event_timeout() and explicit loop. This approach is easier to understand. Signed-off-by: NeilBrown --- drivers/staging/lustre/lustre/ptlrpc/client.c | 14 +++--- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/drivers/staging/lustre/lustre/ptlrpc/client.c b/drivers/staging/lustre/lustre/ptlrpc/client.c index 3e6d22beb9f5..bb8c9ab68f5f 100644 --- a/drivers/staging/lustre/lustre/ptlrpc/client.c +++ b/drivers/staging/lustre/lustre/ptlrpc/client.c @@ -2500,7 +2500,6 @@ static int ptlrpc_unregister_reply(struct ptlrpc_request *request, int async) { int rc; wait_queue_head_t *wq; - struct l_wait_info lwi; /* Might sleep. */ LASSERT(!in_interrupt()); @@ -2543,16 +2542,17 @@ static int ptlrpc_unregister_reply(struct ptlrpc_request *request, int async) * Network access will complete in finite time but the HUGE * timeout lets us CWARN for visibility of sluggish NALs */ - lwi = LWI_TIMEOUT_INTERVAL(LONG_UNLINK * HZ, - HZ, NULL, NULL); - rc = l_wait_event(*wq, !ptlrpc_client_recv_or_unlink(request), - ); - if (rc == 0) { + int cnt = 0; + while (cnt < LONG_UNLINK && + (rc = wait_event_timeout(*wq, + !ptlrpc_client_recv_or_unlink(request), + HZ)) == 0) + cnt += 1; + if (rc > 0) { ptlrpc_rqphase_move(request, request->rq_next_phase); return 1; } - LASSERT(rc == -ETIMEDOUT); DEBUG_REQ(D_WARNING, request, "Unexpectedly long timeout receiving_reply=%d req_ulinked=%d reply_unlinked=%d", request->rq_receiving_reply,
[PATCH 13/16] staging: lustre: improve waiting in sptlrpc_req_refresh_ctx
Replace l_wait_event with wait_event_timeout() and call the handler function explicitly. This makes it more clear what is happening. Signed-off-by: NeilBrown --- drivers/staging/lustre/lustre/ptlrpc/sec.c | 23 +-- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/drivers/staging/lustre/lustre/ptlrpc/sec.c b/drivers/staging/lustre/lustre/ptlrpc/sec.c index 617e004d00f8..6292840f1fca 100644 --- a/drivers/staging/lustre/lustre/ptlrpc/sec.c +++ b/drivers/staging/lustre/lustre/ptlrpc/sec.c @@ -554,9 +554,8 @@ int ctx_check_refresh(struct ptlrpc_cli_ctx *ctx) } static -int ctx_refresh_timeout(void *data) +int ctx_refresh_timeout(struct ptlrpc_request *req) { - struct ptlrpc_request *req = data; int rc; /* conn_cnt is needed in expire_one_request */ @@ -575,10 +574,8 @@ int ctx_refresh_timeout(void *data) } static -void ctx_refresh_interrupt(void *data) +void ctx_refresh_interrupt(struct ptlrpc_request *req) { - struct ptlrpc_request *req = data; - spin_lock(>rq_lock); req->rq_intr = 1; spin_unlock(>rq_lock); @@ -611,7 +608,6 @@ int sptlrpc_req_refresh_ctx(struct ptlrpc_request *req, long timeout) { struct ptlrpc_cli_ctx *ctx = req->rq_cli_ctx; struct ptlrpc_sec *sec; - struct l_wait_info lwi; int rc; LASSERT(ctx); @@ -743,10 +739,17 @@ int sptlrpc_req_refresh_ctx(struct ptlrpc_request *req, long timeout) req->rq_restart = 0; spin_unlock(>rq_lock); - lwi = LWI_TIMEOUT_INTR(msecs_to_jiffies(timeout * MSEC_PER_SEC), - ctx_refresh_timeout, ctx_refresh_interrupt, - req); - rc = l_wait_event(req->rq_reply_waitq, ctx_check_refresh(ctx), ); + rc = wait_event_timeout(req->rq_reply_waitq, + ctx_check_refresh(ctx), + timeout * HZ); + if (rc > 0) + rc = 0; + else if (ctx_refresh_timeout(req)) + rc = -ETIMEDOUT; + else if (l_fatal_signal_pending(current)) { + rc = -EINTR; + ctx_refresh_interrupt(req); + } /* * following cases could lead us here:
[PATCH 06/16] staging: lustre: simplify l_wait_event when intr handler but no timeout.
If l_wait_event() is given a function to be called on a signal, but no timeout or timeout handler, then the intr function is simply called at the end if the wait was aborted by a signal. So a simpler way to write the code (in the one place this case is used) it to open-code the body of the function after the wait_event, if -ERESTARTSYS was returned. Signed-off-by: NeilBrown--- drivers/staging/lustre/lustre/ldlm/ldlm_flock.c | 30 +-- 1 file changed, 7 insertions(+), 23 deletions(-) diff --git a/drivers/staging/lustre/lustre/ldlm/ldlm_flock.c b/drivers/staging/lustre/lustre/ldlm/ldlm_flock.c index 657ab95091a0..411b540b96d9 100644 --- a/drivers/staging/lustre/lustre/ldlm/ldlm_flock.c +++ b/drivers/staging/lustre/lustre/ldlm/ldlm_flock.c @@ -310,24 +310,6 @@ static int ldlm_process_flock_lock(struct ldlm_lock *req) return LDLM_ITER_CONTINUE; } -struct ldlm_flock_wait_data { - struct ldlm_lock *fwd_lock; -}; - -static void -ldlm_flock_interrupted_wait(void *data) -{ - struct ldlm_lock *lock; - - lock = ((struct ldlm_flock_wait_data *)data)->fwd_lock; - - lock_res_and_lock(lock); - - /* client side - set flag to prevent lock from being put on LRU list */ - ldlm_set_cbpending(lock); - unlock_res_and_lock(lock); -} - /** * Flock completion callback function. * @@ -342,8 +324,6 @@ int ldlm_flock_completion_ast(struct ldlm_lock *lock, __u64 flags, void *data) { struct file_lock*getlk = lock->l_ast_data; - struct ldlm_flock_wait_data fwd; - struct l_wait_info lwi; int rc = 0; OBD_FAIL_TIMEOUT(OBD_FAIL_LDLM_CP_CB_WAIT2, 4); @@ -372,13 +352,17 @@ ldlm_flock_completion_ast(struct ldlm_lock *lock, __u64 flags, void *data) LDLM_DEBUG(lock, "client-side enqueue returned a blocked lock, sleeping"); - fwd.fwd_lock = lock; - lwi = LWI_TIMEOUT_INTR(0, NULL, ldlm_flock_interrupted_wait, ); /* Go to sleep until the lock is granted. */ - rc = l_wait_event(lock->l_waitq, is_granted_or_cancelled(lock), ); + rc = l_wait_event_abortable(lock->l_waitq, is_granted_or_cancelled(lock)); if (rc) { + lock_res_and_lock(lock); + + /* client side - set flag to prevent lock from being put on LRU list */ + ldlm_set_cbpending(lock); + unlock_res_and_lock(lock); + LDLM_DEBUG(lock, "client-side enqueue waking up: failed (%d)", rc); return rc;
[PATCH 11/16] staging: lustre: make polling loop in ptlrpc_unregister_bulk more obvious
This use of l_wait_event() is a polling loop that re-checks every second. Make this more obvious with a while loop and wait_event_timeout(). Signed-off-by: NeilBrown--- drivers/staging/lustre/lustre/ptlrpc/niobuf.c | 14 +++--- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/drivers/staging/lustre/lustre/ptlrpc/niobuf.c b/drivers/staging/lustre/lustre/ptlrpc/niobuf.c index 0c2ded721c49..5606c8f01b5b 100644 --- a/drivers/staging/lustre/lustre/ptlrpc/niobuf.c +++ b/drivers/staging/lustre/lustre/ptlrpc/niobuf.c @@ -229,7 +229,6 @@ int ptlrpc_unregister_bulk(struct ptlrpc_request *req, int async) { struct ptlrpc_bulk_desc *desc = req->rq_bulk; wait_queue_head_t *wq; - struct l_wait_info lwi; int rc; LASSERT(!in_interrupt()); /* might sleep */ @@ -246,7 +245,7 @@ int ptlrpc_unregister_bulk(struct ptlrpc_request *req, int async) /* the unlink ensures the callback happens ASAP and is the last * one. If it fails, it must be because completion just happened, -* but we must still l_wait_event() in this case to give liblustre +* but we must still wait_event() in this case to give liblustre * a chance to run client_bulk_callback() */ mdunlink_iterate_helper(desc->bd_mds, desc->bd_md_max_brw); @@ -270,15 +269,16 @@ int ptlrpc_unregister_bulk(struct ptlrpc_request *req, int async) /* Network access will complete in finite time but the HUGE * timeout lets us CWARN for visibility of sluggish LNDs */ - lwi = LWI_TIMEOUT_INTERVAL(LONG_UNLINK * HZ, - HZ, NULL, NULL); - rc = l_wait_event(*wq, !ptlrpc_client_bulk_active(req), ); - if (rc == 0) { + int cnt = 0; + while (cnt < LONG_UNLINK && + (rc = wait_event_timeout(*wq, !ptlrpc_client_bulk_active(req), + HZ)) == 0) + cnt += 1; + if (rc > 0) { ptlrpc_rqphase_move(req, req->rq_next_phase); return 1; } - LASSERT(rc == -ETIMEDOUT); DEBUG_REQ(D_WARNING, req, "Unexpectedly long timeout: desc %p", desc); }
[PATCH 06/16] staging: lustre: simplify l_wait_event when intr handler but no timeout.
If l_wait_event() is given a function to be called on a signal, but no timeout or timeout handler, then the intr function is simply called at the end if the wait was aborted by a signal. So a simpler way to write the code (in the one place this case is used) it to open-code the body of the function after the wait_event, if -ERESTARTSYS was returned. Signed-off-by: NeilBrown --- drivers/staging/lustre/lustre/ldlm/ldlm_flock.c | 30 +-- 1 file changed, 7 insertions(+), 23 deletions(-) diff --git a/drivers/staging/lustre/lustre/ldlm/ldlm_flock.c b/drivers/staging/lustre/lustre/ldlm/ldlm_flock.c index 657ab95091a0..411b540b96d9 100644 --- a/drivers/staging/lustre/lustre/ldlm/ldlm_flock.c +++ b/drivers/staging/lustre/lustre/ldlm/ldlm_flock.c @@ -310,24 +310,6 @@ static int ldlm_process_flock_lock(struct ldlm_lock *req) return LDLM_ITER_CONTINUE; } -struct ldlm_flock_wait_data { - struct ldlm_lock *fwd_lock; -}; - -static void -ldlm_flock_interrupted_wait(void *data) -{ - struct ldlm_lock *lock; - - lock = ((struct ldlm_flock_wait_data *)data)->fwd_lock; - - lock_res_and_lock(lock); - - /* client side - set flag to prevent lock from being put on LRU list */ - ldlm_set_cbpending(lock); - unlock_res_and_lock(lock); -} - /** * Flock completion callback function. * @@ -342,8 +324,6 @@ int ldlm_flock_completion_ast(struct ldlm_lock *lock, __u64 flags, void *data) { struct file_lock*getlk = lock->l_ast_data; - struct ldlm_flock_wait_data fwd; - struct l_wait_info lwi; int rc = 0; OBD_FAIL_TIMEOUT(OBD_FAIL_LDLM_CP_CB_WAIT2, 4); @@ -372,13 +352,17 @@ ldlm_flock_completion_ast(struct ldlm_lock *lock, __u64 flags, void *data) LDLM_DEBUG(lock, "client-side enqueue returned a blocked lock, sleeping"); - fwd.fwd_lock = lock; - lwi = LWI_TIMEOUT_INTR(0, NULL, ldlm_flock_interrupted_wait, ); /* Go to sleep until the lock is granted. */ - rc = l_wait_event(lock->l_waitq, is_granted_or_cancelled(lock), ); + rc = l_wait_event_abortable(lock->l_waitq, is_granted_or_cancelled(lock)); if (rc) { + lock_res_and_lock(lock); + + /* client side - set flag to prevent lock from being put on LRU list */ + ldlm_set_cbpending(lock); + unlock_res_and_lock(lock); + LDLM_DEBUG(lock, "client-side enqueue waking up: failed (%d)", rc); return rc;
[PATCH 11/16] staging: lustre: make polling loop in ptlrpc_unregister_bulk more obvious
This use of l_wait_event() is a polling loop that re-checks every second. Make this more obvious with a while loop and wait_event_timeout(). Signed-off-by: NeilBrown --- drivers/staging/lustre/lustre/ptlrpc/niobuf.c | 14 +++--- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/drivers/staging/lustre/lustre/ptlrpc/niobuf.c b/drivers/staging/lustre/lustre/ptlrpc/niobuf.c index 0c2ded721c49..5606c8f01b5b 100644 --- a/drivers/staging/lustre/lustre/ptlrpc/niobuf.c +++ b/drivers/staging/lustre/lustre/ptlrpc/niobuf.c @@ -229,7 +229,6 @@ int ptlrpc_unregister_bulk(struct ptlrpc_request *req, int async) { struct ptlrpc_bulk_desc *desc = req->rq_bulk; wait_queue_head_t *wq; - struct l_wait_info lwi; int rc; LASSERT(!in_interrupt()); /* might sleep */ @@ -246,7 +245,7 @@ int ptlrpc_unregister_bulk(struct ptlrpc_request *req, int async) /* the unlink ensures the callback happens ASAP and is the last * one. If it fails, it must be because completion just happened, -* but we must still l_wait_event() in this case to give liblustre +* but we must still wait_event() in this case to give liblustre * a chance to run client_bulk_callback() */ mdunlink_iterate_helper(desc->bd_mds, desc->bd_md_max_brw); @@ -270,15 +269,16 @@ int ptlrpc_unregister_bulk(struct ptlrpc_request *req, int async) /* Network access will complete in finite time but the HUGE * timeout lets us CWARN for visibility of sluggish LNDs */ - lwi = LWI_TIMEOUT_INTERVAL(LONG_UNLINK * HZ, - HZ, NULL, NULL); - rc = l_wait_event(*wq, !ptlrpc_client_bulk_active(req), ); - if (rc == 0) { + int cnt = 0; + while (cnt < LONG_UNLINK && + (rc = wait_event_timeout(*wq, !ptlrpc_client_bulk_active(req), + HZ)) == 0) + cnt += 1; + if (rc > 0) { ptlrpc_rqphase_move(req, req->rq_next_phase); return 1; } - LASSERT(rc == -ETIMEDOUT); DEBUG_REQ(D_WARNING, req, "Unexpectedly long timeout: desc %p", desc); }
[PATCH 12/16] staging: lustre: use wait_event_timeout in ptlrpcd()
We can replace l_wait_event() with wait_event_noload_timeout() here providing we call the timeout function when wait_event_timeout() returns zero. Signed-off-by: NeilBrown--- drivers/staging/lustre/lustre/ptlrpc/client.c | 12 .../staging/lustre/lustre/ptlrpc/ptlrpc_internal.h |2 +- drivers/staging/lustre/lustre/ptlrpc/ptlrpcd.c |9 + 3 files changed, 14 insertions(+), 9 deletions(-) diff --git a/drivers/staging/lustre/lustre/ptlrpc/client.c b/drivers/staging/lustre/lustre/ptlrpc/client.c index 81b7a7046d82..3e6d22beb9f5 100644 --- a/drivers/staging/lustre/lustre/ptlrpc/client.c +++ b/drivers/staging/lustre/lustre/ptlrpc/client.c @@ -2125,9 +2125,8 @@ int ptlrpc_expire_one_request(struct ptlrpc_request *req, int async_unlink) * Callback used when waiting on sets with l_wait_event. * Always returns 1. */ -int ptlrpc_expired_set(void *data) +int ptlrpc_expired_set(struct ptlrpc_request_set *set) { - struct ptlrpc_request_set *set = data; struct list_head *tmp; time64_t now = ktime_get_real_seconds(); @@ -2164,6 +2163,11 @@ int ptlrpc_expired_set(void *data) */ return 1; } +static int ptlrpc_expired_set_void(void *data) +{ + struct ptlrpc_request_set *set = data; + return ptlrpc_expired_set(set); +} /** * Sets rq_intr flag in \a req under spinlock. @@ -2286,7 +2290,7 @@ int ptlrpc_set_wait(struct ptlrpc_request_set *set) * so we allow interrupts during the timeout. */ lwi = LWI_TIMEOUT_INTR_ALL(HZ, - ptlrpc_expired_set, + ptlrpc_expired_set_void, ptlrpc_interrupted_set, set); else /* @@ -2295,7 +2299,7 @@ int ptlrpc_set_wait(struct ptlrpc_request_set *set) * complete, or an in-flight req times out. */ lwi = LWI_TIMEOUT((timeout ? timeout : 1) * HZ, - ptlrpc_expired_set, set); + ptlrpc_expired_set_void, set); rc = l_wait_event(set->set_waitq, ptlrpc_check_set(NULL, set), ); diff --git a/drivers/staging/lustre/lustre/ptlrpc/ptlrpc_internal.h b/drivers/staging/lustre/lustre/ptlrpc/ptlrpc_internal.h index f9decbd1459d..6dd52d99d454 100644 --- a/drivers/staging/lustre/lustre/ptlrpc/ptlrpc_internal.h +++ b/drivers/staging/lustre/lustre/ptlrpc/ptlrpc_internal.h @@ -68,7 +68,7 @@ void ptlrpc_request_cache_free(struct ptlrpc_request *req); void ptlrpc_init_xid(void); void ptlrpc_set_add_new_req(struct ptlrpcd_ctl *pc, struct ptlrpc_request *req); -int ptlrpc_expired_set(void *data); +int ptlrpc_expired_set(struct ptlrpc_request_set *set); int ptlrpc_set_next_timeout(struct ptlrpc_request_set *set); void ptlrpc_resend_req(struct ptlrpc_request *request); void ptlrpc_set_bulk_mbits(struct ptlrpc_request *req); diff --git a/drivers/staging/lustre/lustre/ptlrpc/ptlrpcd.c b/drivers/staging/lustre/lustre/ptlrpc/ptlrpcd.c index 0bdf1f54629b..b7df38e71946 100644 --- a/drivers/staging/lustre/lustre/ptlrpc/ptlrpcd.c +++ b/drivers/staging/lustre/lustre/ptlrpc/ptlrpcd.c @@ -434,16 +434,17 @@ static int ptlrpcd(void *arg) * new_req_list and ptlrpcd_check() moves them into the set. */ do { - struct l_wait_info lwi; int timeout; timeout = ptlrpc_set_next_timeout(set); - lwi = LWI_TIMEOUT((timeout ? timeout : 1) * HZ, - ptlrpc_expired_set, set); lu_context_enter(_ctx); lu_context_enter(env.le_ses); - l_wait_event(set->set_waitq, ptlrpcd_check(, pc), ); + if (wait_event_noload_timeout(set->set_waitq, + ptlrpcd_check(, pc), + (timeout ? timeout : 1) * HZ) == 0) + ptlrpc_expired_set(set); + lu_context_exit(_ctx); lu_context_exit(env.le_ses);
[PATCH 08/16] staging: lustre: open code polling loop instead of using l_wait_event()
Two places that LWI_TIMEOUT_INTERVAL() is used, the outcome is a simple polling loop that polls every second for some event (with a limit). So write a simple loop to make this more apparent. Signed-off-by: NeilBrown--- drivers/staging/lustre/lustre/llite/llite_lib.c | 11 +-- drivers/staging/lustre/lustre/lov/lov_request.c | 12 +--- 2 files changed, 10 insertions(+), 13 deletions(-) diff --git a/drivers/staging/lustre/lustre/llite/llite_lib.c b/drivers/staging/lustre/lustre/llite/llite_lib.c index 33dc15e9aebb..f6642fa30428 100644 --- a/drivers/staging/lustre/lustre/llite/llite_lib.c +++ b/drivers/staging/lustre/lustre/llite/llite_lib.c @@ -1984,8 +1984,7 @@ void ll_umount_begin(struct super_block *sb) struct ll_sb_info *sbi = ll_s2sbi(sb); struct obd_device *obd; struct obd_ioctl_data *ioc_data; - wait_queue_head_t waitq; - struct l_wait_info lwi; + int cnt = 0; CDEBUG(D_VFSTRACE, "VFS Op: superblock %p count %d active %d\n", sb, sb->s_count, atomic_read(>s_active)); @@ -2021,10 +2020,10 @@ void ll_umount_begin(struct super_block *sb) * and then continue. For now, we just periodically checking for vfs * to decrement mnt_cnt and hope to finish it within 10sec. */ - init_waitqueue_head(); - lwi = LWI_TIMEOUT_INTERVAL(10 * HZ, - HZ, NULL, NULL); - l_wait_event(waitq, may_umount(sbi->ll_mnt.mnt), ); + while (cnt < 10 && !may_umount(sbi->ll_mnt.mnt)) { + schedule_timeout_uninterruptible(HZ); + cnt ++; + } schedule(); } diff --git a/drivers/staging/lustre/lustre/lov/lov_request.c b/drivers/staging/lustre/lustre/lov/lov_request.c index fb3b7a7fa32a..c1e58fcc30b3 100644 --- a/drivers/staging/lustre/lustre/lov/lov_request.c +++ b/drivers/staging/lustre/lustre/lov/lov_request.c @@ -99,8 +99,7 @@ static int lov_check_set(struct lov_obd *lov, int idx) */ static int lov_check_and_wait_active(struct lov_obd *lov, int ost_idx) { - wait_queue_head_t waitq; - struct l_wait_info lwi; + int cnt = 0; struct lov_tgt_desc *tgt; int rc = 0; @@ -125,11 +124,10 @@ static int lov_check_and_wait_active(struct lov_obd *lov, int ost_idx) mutex_unlock(>lov_lock); - init_waitqueue_head(); - lwi = LWI_TIMEOUT_INTERVAL(obd_timeout * HZ, - HZ, NULL, NULL); - - rc = l_wait_event(waitq, lov_check_set(lov, ost_idx), ); + while (cnt < obd_timeout && !lov_check_set(lov, ost_idx)) { + schedule_timeout_uninterruptible(HZ); + cnt ++; + } if (tgt->ltd_active) return 1;
[PATCH 10/16] staging: lustre: remove back_to_sleep() and use loops.
When 'back_to_sleep()' is passed as the 'timeout' function, the effect is to wait indefinitely for the event, polling on the timeout in case we missed a wake_up. If LWI_ON_SIGNAL_NOOP is given, then also abort (at the timeout) if a "fatal" signal is pending. Make this more obvious is both places "back_to_sleep()" is used, adding l_fatal_signal_pending() to allow testing for "fatal" signals. Signed-off-by: NeilBrown--- drivers/staging/lustre/lustre/include/lustre_lib.h |8 drivers/staging/lustre/lustre/ptlrpc/import.c | 11 ++- drivers/staging/lustre/lustre/ptlrpc/ptlrpcd.c |8 3 files changed, 14 insertions(+), 13 deletions(-) diff --git a/drivers/staging/lustre/lustre/include/lustre_lib.h b/drivers/staging/lustre/lustre/include/lustre_lib.h index d64306291b47..d157ed35a0bf 100644 --- a/drivers/staging/lustre/lustre/include/lustre_lib.h +++ b/drivers/staging/lustre/lustre/include/lustre_lib.h @@ -140,10 +140,6 @@ void target_send_reply(struct ptlrpc_request *req, int rc, int fail_id); * XXX nikita: some ptlrpc daemon threads have races of that sort. * */ -static inline int back_to_sleep(void *arg) -{ - return 0; -} #define LWI_ON_SIGNAL_NOOP ((void (*)(void *))(-1)) @@ -200,6 +196,10 @@ struct l_wait_info { #define LUSTRE_FATAL_SIGS (sigmask(SIGKILL) | sigmask(SIGINT) | \ sigmask(SIGTERM) | sigmask(SIGQUIT) |\ sigmask(SIGALRM)) +static inline int l_fatal_signal_pending(struct task_struct *p) +{ + return signal_pending(p) && sigtestsetmask(>pending.signal, LUSTRE_FATAL_SIGS); +} /** * wait_queue_entry_t of Linux (version < 2.6.34) is a FIFO list for exclusively diff --git a/drivers/staging/lustre/lustre/ptlrpc/import.c b/drivers/staging/lustre/lustre/ptlrpc/import.c index b6cef8e97435..decaa9bccdc8 100644 --- a/drivers/staging/lustre/lustre/ptlrpc/import.c +++ b/drivers/staging/lustre/lustre/ptlrpc/import.c @@ -1496,7 +1496,6 @@ int ptlrpc_disconnect_import(struct obd_import *imp, int noclose) } if (ptlrpc_import_in_recovery(imp)) { - struct l_wait_info lwi; long timeout; if (AT_OFF) { @@ -1510,10 +1509,12 @@ int ptlrpc_disconnect_import(struct obd_import *imp, int noclose) timeout = at_get(>imp_at.iat_service_estimate[idx]) * HZ; } - lwi = LWI_TIMEOUT_INTR(cfs_timeout_cap(timeout), - back_to_sleep, LWI_ON_SIGNAL_NOOP, NULL); - rc = l_wait_event(imp->imp_recovery_waitq, - !ptlrpc_import_in_recovery(imp), ); + while (wait_event_timeout(imp->imp_recovery_waitq, + !ptlrpc_import_in_recovery(imp), + cfs_timeout_cap(timeout)) == 0) + if (l_fatal_signal_pending(current)) + break; + /* else just keep waiting */ } spin_lock(>imp_lock); diff --git a/drivers/staging/lustre/lustre/ptlrpc/ptlrpcd.c b/drivers/staging/lustre/lustre/ptlrpc/ptlrpcd.c index dad2f9290f70..0bdf1f54629b 100644 --- a/drivers/staging/lustre/lustre/ptlrpc/ptlrpcd.c +++ b/drivers/staging/lustre/lustre/ptlrpc/ptlrpcd.c @@ -230,12 +230,12 @@ void ptlrpcd_add_req(struct ptlrpc_request *req) spin_lock(>rq_lock); if (req->rq_invalid_rqset) { - struct l_wait_info lwi = LWI_TIMEOUT(5 * HZ, -back_to_sleep, NULL); - req->rq_invalid_rqset = 0; spin_unlock(>rq_lock); - l_wait_event(req->rq_set_waitq, !req->rq_set, ); + while (wait_event_timeout(req->rq_set_waitq, + !req->rq_set, + 5 * HZ) == 0) + ; } else if (req->rq_set) { /* If we have a valid "rq_set", just reuse it to avoid double * linked.
[PATCH 09/16] staging: lustre: simplify waiting in ptlrpc_invalidate_import()
This wait current wakes up every second to re-test if imp_flight is zero. If we ensure wakeup is called whenever imp_flight is decremented to zero, we can just have a simple wait_event_timeout(). So add a wake_up_all to the one place it is missing, and simplify the wait_event. Signed-off-by: NeilBrown--- drivers/staging/lustre/lustre/ptlrpc/client.c |3 ++- drivers/staging/lustre/lustre/ptlrpc/import.c | 21 - 2 files changed, 10 insertions(+), 14 deletions(-) diff --git a/drivers/staging/lustre/lustre/ptlrpc/client.c b/drivers/staging/lustre/lustre/ptlrpc/client.c index 0ab13f8e5993..81b7a7046d82 100644 --- a/drivers/staging/lustre/lustre/ptlrpc/client.c +++ b/drivers/staging/lustre/lustre/ptlrpc/client.c @@ -1588,7 +1588,8 @@ static int ptlrpc_send_new_req(struct ptlrpc_request *req) spin_lock(>imp_lock); if (!list_empty(>rq_list)) { list_del_init(>rq_list); - atomic_dec(>rq_import->imp_inflight); + if (atomic_dec_and_test(>rq_import->imp_inflight)) + wake_up_all(>rq_import->imp_recovery_waitq); } spin_unlock(>imp_lock); ptlrpc_rqphase_move(req, RQ_PHASE_NEW); diff --git a/drivers/staging/lustre/lustre/ptlrpc/import.c b/drivers/staging/lustre/lustre/ptlrpc/import.c index 34b4075fac42..b6cef8e97435 100644 --- a/drivers/staging/lustre/lustre/ptlrpc/import.c +++ b/drivers/staging/lustre/lustre/ptlrpc/import.c @@ -265,7 +265,6 @@ void ptlrpc_invalidate_import(struct obd_import *imp) { struct list_head *tmp, *n; struct ptlrpc_request *req; - struct l_wait_info lwi; unsigned int timeout; int rc; @@ -306,19 +305,15 @@ void ptlrpc_invalidate_import(struct obd_import *imp) * callbacks. Cap it at obd_timeout -- these should all * have been locally cancelled by ptlrpc_abort_inflight. */ - lwi = LWI_TIMEOUT_INTERVAL( - cfs_timeout_cap(timeout * HZ), - (timeout > 1) ? HZ : - HZ / 2, - NULL, NULL); - rc = l_wait_event(imp->imp_recovery_waitq, - (atomic_read(>imp_inflight) == 0), - ); - if (rc) { + rc = wait_event_timeout(imp->imp_recovery_waitq, + atomic_read(>imp_inflight) == 0, + obd_timeout * HZ); + + if (rc == 0) { const char *cli_tgt = obd2cli_tgt(imp->imp_obd); - CERROR("%s: rc = %d waiting for callback (%d != 0)\n", - cli_tgt, rc, + CERROR("%s: timeout waiting for callback (%d != 0)\n", + cli_tgt, atomic_read(>imp_inflight)); spin_lock(>imp_lock); @@ -365,7 +360,7 @@ void ptlrpc_invalidate_import(struct obd_import *imp) } spin_unlock(>imp_lock); } - } while (rc != 0); + } while (rc == 0); /* * Let's additionally check that no new rpcs added to import in
[PATCH 07/16] staging: lustre: simplify waiting in ldlm_completion_ast()
If a signal-callback (lwi_on_signal) is set without lwi_allow_intr, as is the case in ldlm_completion_ast(), the behavior depends on the timeout set. If a timeout is set, then signals are ignored. If the timeout is reached, the timeout handler is called. If no timeout is set, then "fatal" signals are not ignored. If one arrives the callback is run, but as the callback is empty in this case, that is not relevant. So treat the two cases separately. In one, use l_wait_event_abortable(). In the other, use wait_event_timeout(), and if the timeout happens - perform the timeout-call function (opencoded). Signed-off-by: NeilBrown--- drivers/staging/lustre/lustre/ldlm/ldlm_request.c | 51 +++-- 1 file changed, 17 insertions(+), 34 deletions(-) diff --git a/drivers/staging/lustre/lustre/ldlm/ldlm_request.c b/drivers/staging/lustre/lustre/ldlm/ldlm_request.c index a244fa717134..05bec9fd629b 100644 --- a/drivers/staging/lustre/lustre/ldlm/ldlm_request.c +++ b/drivers/staging/lustre/lustre/ldlm/ldlm_request.c @@ -72,15 +72,6 @@ MODULE_PARM_DESC(ldlm_enqueue_min, "lock enqueue timeout minimum"); /* in client side, whether the cached locks will be canceled before replay */ unsigned int ldlm_cancel_unused_locks_before_replay = 1; -static void interrupted_completion_wait(void *data) -{ -} - -struct lock_wait_data { - struct ldlm_lock *lwd_lock; - __u32lwd_conn_cnt; -}; - struct ldlm_async_args { struct lustre_handle lock_handle; }; @@ -112,10 +103,8 @@ static int ldlm_request_bufsize(int count, int type) return sizeof(struct ldlm_request) + avail; } -static int ldlm_expired_completion_wait(void *data) +static int ldlm_expired_completion_wait(struct ldlm_lock *lock, struct obd_import *imp2) { - struct lock_wait_data *lwd = data; - struct ldlm_lock *lock = lwd->lwd_lock; struct obd_import *imp; struct obd_device *obd; @@ -140,7 +129,7 @@ static int ldlm_expired_completion_wait(void *data) obd = lock->l_conn_export->exp_obd; imp = obd->u.cli.cl_import; - ptlrpc_fail_import(imp, lwd->lwd_conn_cnt); + ptlrpc_fail_import(imp, imp2 ? imp2->imp_conn_cnt : 0); LDLM_ERROR(lock, "lock timed out (enqueued at %lld, %llds ago), entering recovery for %s@%s", (s64)lock->l_last_activity, @@ -251,10 +240,8 @@ EXPORT_SYMBOL(ldlm_completion_ast_async); int ldlm_completion_ast(struct ldlm_lock *lock, __u64 flags, void *data) { /* XXX ALLOCATE - 160 bytes */ - struct lock_wait_data lwd; struct obd_device *obd; struct obd_import *imp = NULL; - struct l_wait_info lwi; __u32 timeout; int rc = 0; @@ -281,32 +268,28 @@ int ldlm_completion_ast(struct ldlm_lock *lock, __u64 flags, void *data) timeout = ldlm_cp_timeout(lock); - lwd.lwd_lock = lock; lock->l_last_activity = ktime_get_real_seconds(); - if (ldlm_is_no_timeout(lock)) { - LDLM_DEBUG(lock, "waiting indefinitely because of NO_TIMEOUT"); - lwi = LWI_INTR(interrupted_completion_wait, ); - } else { - lwi = LWI_TIMEOUT_INTR(timeout * HZ, - ldlm_expired_completion_wait, - interrupted_completion_wait, ); - } - - if (imp) { - spin_lock(>imp_lock); - lwd.lwd_conn_cnt = imp->imp_conn_cnt; - spin_unlock(>imp_lock); - } - if (OBD_FAIL_CHECK_RESET(OBD_FAIL_LDLM_INTR_CP_AST, OBD_FAIL_LDLM_CP_BL_RACE | OBD_FAIL_ONCE)) { ldlm_set_fail_loc(lock); rc = -EINTR; } else { - /* Go to sleep until the lock is granted or cancelled. */ - rc = l_wait_event(lock->l_waitq, - is_granted_or_cancelled(lock), ); + /* Go to sleep until the lock is granted or canceled. */ + if (ldlm_is_no_timeout(lock)) { + LDLM_DEBUG(lock, "waiting indefinitely because of NO_TIMEOUT"); + rc = l_wait_event_abortable(lock->l_waitq, + is_granted_or_cancelled(lock)); + } else { + rc = wait_event_timeout(lock->l_waitq, + is_granted_or_cancelled(lock), + timeout * HZ); + if (rc == 0) { + ldlm_expired_completion_wait(lock, imp); + rc = -ETIMEDOUT; + } else + rc = 0; + } } if (rc) {
[PATCH 10/16] staging: lustre: remove back_to_sleep() and use loops.
When 'back_to_sleep()' is passed as the 'timeout' function, the effect is to wait indefinitely for the event, polling on the timeout in case we missed a wake_up. If LWI_ON_SIGNAL_NOOP is given, then also abort (at the timeout) if a "fatal" signal is pending. Make this more obvious is both places "back_to_sleep()" is used, adding l_fatal_signal_pending() to allow testing for "fatal" signals. Signed-off-by: NeilBrown --- drivers/staging/lustre/lustre/include/lustre_lib.h |8 drivers/staging/lustre/lustre/ptlrpc/import.c | 11 ++- drivers/staging/lustre/lustre/ptlrpc/ptlrpcd.c |8 3 files changed, 14 insertions(+), 13 deletions(-) diff --git a/drivers/staging/lustre/lustre/include/lustre_lib.h b/drivers/staging/lustre/lustre/include/lustre_lib.h index d64306291b47..d157ed35a0bf 100644 --- a/drivers/staging/lustre/lustre/include/lustre_lib.h +++ b/drivers/staging/lustre/lustre/include/lustre_lib.h @@ -140,10 +140,6 @@ void target_send_reply(struct ptlrpc_request *req, int rc, int fail_id); * XXX nikita: some ptlrpc daemon threads have races of that sort. * */ -static inline int back_to_sleep(void *arg) -{ - return 0; -} #define LWI_ON_SIGNAL_NOOP ((void (*)(void *))(-1)) @@ -200,6 +196,10 @@ struct l_wait_info { #define LUSTRE_FATAL_SIGS (sigmask(SIGKILL) | sigmask(SIGINT) | \ sigmask(SIGTERM) | sigmask(SIGQUIT) |\ sigmask(SIGALRM)) +static inline int l_fatal_signal_pending(struct task_struct *p) +{ + return signal_pending(p) && sigtestsetmask(>pending.signal, LUSTRE_FATAL_SIGS); +} /** * wait_queue_entry_t of Linux (version < 2.6.34) is a FIFO list for exclusively diff --git a/drivers/staging/lustre/lustre/ptlrpc/import.c b/drivers/staging/lustre/lustre/ptlrpc/import.c index b6cef8e97435..decaa9bccdc8 100644 --- a/drivers/staging/lustre/lustre/ptlrpc/import.c +++ b/drivers/staging/lustre/lustre/ptlrpc/import.c @@ -1496,7 +1496,6 @@ int ptlrpc_disconnect_import(struct obd_import *imp, int noclose) } if (ptlrpc_import_in_recovery(imp)) { - struct l_wait_info lwi; long timeout; if (AT_OFF) { @@ -1510,10 +1509,12 @@ int ptlrpc_disconnect_import(struct obd_import *imp, int noclose) timeout = at_get(>imp_at.iat_service_estimate[idx]) * HZ; } - lwi = LWI_TIMEOUT_INTR(cfs_timeout_cap(timeout), - back_to_sleep, LWI_ON_SIGNAL_NOOP, NULL); - rc = l_wait_event(imp->imp_recovery_waitq, - !ptlrpc_import_in_recovery(imp), ); + while (wait_event_timeout(imp->imp_recovery_waitq, + !ptlrpc_import_in_recovery(imp), + cfs_timeout_cap(timeout)) == 0) + if (l_fatal_signal_pending(current)) + break; + /* else just keep waiting */ } spin_lock(>imp_lock); diff --git a/drivers/staging/lustre/lustre/ptlrpc/ptlrpcd.c b/drivers/staging/lustre/lustre/ptlrpc/ptlrpcd.c index dad2f9290f70..0bdf1f54629b 100644 --- a/drivers/staging/lustre/lustre/ptlrpc/ptlrpcd.c +++ b/drivers/staging/lustre/lustre/ptlrpc/ptlrpcd.c @@ -230,12 +230,12 @@ void ptlrpcd_add_req(struct ptlrpc_request *req) spin_lock(>rq_lock); if (req->rq_invalid_rqset) { - struct l_wait_info lwi = LWI_TIMEOUT(5 * HZ, -back_to_sleep, NULL); - req->rq_invalid_rqset = 0; spin_unlock(>rq_lock); - l_wait_event(req->rq_set_waitq, !req->rq_set, ); + while (wait_event_timeout(req->rq_set_waitq, + !req->rq_set, + 5 * HZ) == 0) + ; } else if (req->rq_set) { /* If we have a valid "rq_set", just reuse it to avoid double * linked.
[PATCH 09/16] staging: lustre: simplify waiting in ptlrpc_invalidate_import()
This wait current wakes up every second to re-test if imp_flight is zero. If we ensure wakeup is called whenever imp_flight is decremented to zero, we can just have a simple wait_event_timeout(). So add a wake_up_all to the one place it is missing, and simplify the wait_event. Signed-off-by: NeilBrown --- drivers/staging/lustre/lustre/ptlrpc/client.c |3 ++- drivers/staging/lustre/lustre/ptlrpc/import.c | 21 - 2 files changed, 10 insertions(+), 14 deletions(-) diff --git a/drivers/staging/lustre/lustre/ptlrpc/client.c b/drivers/staging/lustre/lustre/ptlrpc/client.c index 0ab13f8e5993..81b7a7046d82 100644 --- a/drivers/staging/lustre/lustre/ptlrpc/client.c +++ b/drivers/staging/lustre/lustre/ptlrpc/client.c @@ -1588,7 +1588,8 @@ static int ptlrpc_send_new_req(struct ptlrpc_request *req) spin_lock(>imp_lock); if (!list_empty(>rq_list)) { list_del_init(>rq_list); - atomic_dec(>rq_import->imp_inflight); + if (atomic_dec_and_test(>rq_import->imp_inflight)) + wake_up_all(>rq_import->imp_recovery_waitq); } spin_unlock(>imp_lock); ptlrpc_rqphase_move(req, RQ_PHASE_NEW); diff --git a/drivers/staging/lustre/lustre/ptlrpc/import.c b/drivers/staging/lustre/lustre/ptlrpc/import.c index 34b4075fac42..b6cef8e97435 100644 --- a/drivers/staging/lustre/lustre/ptlrpc/import.c +++ b/drivers/staging/lustre/lustre/ptlrpc/import.c @@ -265,7 +265,6 @@ void ptlrpc_invalidate_import(struct obd_import *imp) { struct list_head *tmp, *n; struct ptlrpc_request *req; - struct l_wait_info lwi; unsigned int timeout; int rc; @@ -306,19 +305,15 @@ void ptlrpc_invalidate_import(struct obd_import *imp) * callbacks. Cap it at obd_timeout -- these should all * have been locally cancelled by ptlrpc_abort_inflight. */ - lwi = LWI_TIMEOUT_INTERVAL( - cfs_timeout_cap(timeout * HZ), - (timeout > 1) ? HZ : - HZ / 2, - NULL, NULL); - rc = l_wait_event(imp->imp_recovery_waitq, - (atomic_read(>imp_inflight) == 0), - ); - if (rc) { + rc = wait_event_timeout(imp->imp_recovery_waitq, + atomic_read(>imp_inflight) == 0, + obd_timeout * HZ); + + if (rc == 0) { const char *cli_tgt = obd2cli_tgt(imp->imp_obd); - CERROR("%s: rc = %d waiting for callback (%d != 0)\n", - cli_tgt, rc, + CERROR("%s: timeout waiting for callback (%d != 0)\n", + cli_tgt, atomic_read(>imp_inflight)); spin_lock(>imp_lock); @@ -365,7 +360,7 @@ void ptlrpc_invalidate_import(struct obd_import *imp) } spin_unlock(>imp_lock); } - } while (rc != 0); + } while (rc == 0); /* * Let's additionally check that no new rpcs added to import in
[PATCH 07/16] staging: lustre: simplify waiting in ldlm_completion_ast()
If a signal-callback (lwi_on_signal) is set without lwi_allow_intr, as is the case in ldlm_completion_ast(), the behavior depends on the timeout set. If a timeout is set, then signals are ignored. If the timeout is reached, the timeout handler is called. If no timeout is set, then "fatal" signals are not ignored. If one arrives the callback is run, but as the callback is empty in this case, that is not relevant. So treat the two cases separately. In one, use l_wait_event_abortable(). In the other, use wait_event_timeout(), and if the timeout happens - perform the timeout-call function (opencoded). Signed-off-by: NeilBrown --- drivers/staging/lustre/lustre/ldlm/ldlm_request.c | 51 +++-- 1 file changed, 17 insertions(+), 34 deletions(-) diff --git a/drivers/staging/lustre/lustre/ldlm/ldlm_request.c b/drivers/staging/lustre/lustre/ldlm/ldlm_request.c index a244fa717134..05bec9fd629b 100644 --- a/drivers/staging/lustre/lustre/ldlm/ldlm_request.c +++ b/drivers/staging/lustre/lustre/ldlm/ldlm_request.c @@ -72,15 +72,6 @@ MODULE_PARM_DESC(ldlm_enqueue_min, "lock enqueue timeout minimum"); /* in client side, whether the cached locks will be canceled before replay */ unsigned int ldlm_cancel_unused_locks_before_replay = 1; -static void interrupted_completion_wait(void *data) -{ -} - -struct lock_wait_data { - struct ldlm_lock *lwd_lock; - __u32lwd_conn_cnt; -}; - struct ldlm_async_args { struct lustre_handle lock_handle; }; @@ -112,10 +103,8 @@ static int ldlm_request_bufsize(int count, int type) return sizeof(struct ldlm_request) + avail; } -static int ldlm_expired_completion_wait(void *data) +static int ldlm_expired_completion_wait(struct ldlm_lock *lock, struct obd_import *imp2) { - struct lock_wait_data *lwd = data; - struct ldlm_lock *lock = lwd->lwd_lock; struct obd_import *imp; struct obd_device *obd; @@ -140,7 +129,7 @@ static int ldlm_expired_completion_wait(void *data) obd = lock->l_conn_export->exp_obd; imp = obd->u.cli.cl_import; - ptlrpc_fail_import(imp, lwd->lwd_conn_cnt); + ptlrpc_fail_import(imp, imp2 ? imp2->imp_conn_cnt : 0); LDLM_ERROR(lock, "lock timed out (enqueued at %lld, %llds ago), entering recovery for %s@%s", (s64)lock->l_last_activity, @@ -251,10 +240,8 @@ EXPORT_SYMBOL(ldlm_completion_ast_async); int ldlm_completion_ast(struct ldlm_lock *lock, __u64 flags, void *data) { /* XXX ALLOCATE - 160 bytes */ - struct lock_wait_data lwd; struct obd_device *obd; struct obd_import *imp = NULL; - struct l_wait_info lwi; __u32 timeout; int rc = 0; @@ -281,32 +268,28 @@ int ldlm_completion_ast(struct ldlm_lock *lock, __u64 flags, void *data) timeout = ldlm_cp_timeout(lock); - lwd.lwd_lock = lock; lock->l_last_activity = ktime_get_real_seconds(); - if (ldlm_is_no_timeout(lock)) { - LDLM_DEBUG(lock, "waiting indefinitely because of NO_TIMEOUT"); - lwi = LWI_INTR(interrupted_completion_wait, ); - } else { - lwi = LWI_TIMEOUT_INTR(timeout * HZ, - ldlm_expired_completion_wait, - interrupted_completion_wait, ); - } - - if (imp) { - spin_lock(>imp_lock); - lwd.lwd_conn_cnt = imp->imp_conn_cnt; - spin_unlock(>imp_lock); - } - if (OBD_FAIL_CHECK_RESET(OBD_FAIL_LDLM_INTR_CP_AST, OBD_FAIL_LDLM_CP_BL_RACE | OBD_FAIL_ONCE)) { ldlm_set_fail_loc(lock); rc = -EINTR; } else { - /* Go to sleep until the lock is granted or cancelled. */ - rc = l_wait_event(lock->l_waitq, - is_granted_or_cancelled(lock), ); + /* Go to sleep until the lock is granted or canceled. */ + if (ldlm_is_no_timeout(lock)) { + LDLM_DEBUG(lock, "waiting indefinitely because of NO_TIMEOUT"); + rc = l_wait_event_abortable(lock->l_waitq, + is_granted_or_cancelled(lock)); + } else { + rc = wait_event_timeout(lock->l_waitq, + is_granted_or_cancelled(lock), + timeout * HZ); + if (rc == 0) { + ldlm_expired_completion_wait(lock, imp); + rc = -ETIMEDOUT; + } else + rc = 0; + } } if (rc) {
[PATCH 12/16] staging: lustre: use wait_event_timeout in ptlrpcd()
We can replace l_wait_event() with wait_event_noload_timeout() here providing we call the timeout function when wait_event_timeout() returns zero. Signed-off-by: NeilBrown --- drivers/staging/lustre/lustre/ptlrpc/client.c | 12 .../staging/lustre/lustre/ptlrpc/ptlrpc_internal.h |2 +- drivers/staging/lustre/lustre/ptlrpc/ptlrpcd.c |9 + 3 files changed, 14 insertions(+), 9 deletions(-) diff --git a/drivers/staging/lustre/lustre/ptlrpc/client.c b/drivers/staging/lustre/lustre/ptlrpc/client.c index 81b7a7046d82..3e6d22beb9f5 100644 --- a/drivers/staging/lustre/lustre/ptlrpc/client.c +++ b/drivers/staging/lustre/lustre/ptlrpc/client.c @@ -2125,9 +2125,8 @@ int ptlrpc_expire_one_request(struct ptlrpc_request *req, int async_unlink) * Callback used when waiting on sets with l_wait_event. * Always returns 1. */ -int ptlrpc_expired_set(void *data) +int ptlrpc_expired_set(struct ptlrpc_request_set *set) { - struct ptlrpc_request_set *set = data; struct list_head *tmp; time64_t now = ktime_get_real_seconds(); @@ -2164,6 +2163,11 @@ int ptlrpc_expired_set(void *data) */ return 1; } +static int ptlrpc_expired_set_void(void *data) +{ + struct ptlrpc_request_set *set = data; + return ptlrpc_expired_set(set); +} /** * Sets rq_intr flag in \a req under spinlock. @@ -2286,7 +2290,7 @@ int ptlrpc_set_wait(struct ptlrpc_request_set *set) * so we allow interrupts during the timeout. */ lwi = LWI_TIMEOUT_INTR_ALL(HZ, - ptlrpc_expired_set, + ptlrpc_expired_set_void, ptlrpc_interrupted_set, set); else /* @@ -2295,7 +2299,7 @@ int ptlrpc_set_wait(struct ptlrpc_request_set *set) * complete, or an in-flight req times out. */ lwi = LWI_TIMEOUT((timeout ? timeout : 1) * HZ, - ptlrpc_expired_set, set); + ptlrpc_expired_set_void, set); rc = l_wait_event(set->set_waitq, ptlrpc_check_set(NULL, set), ); diff --git a/drivers/staging/lustre/lustre/ptlrpc/ptlrpc_internal.h b/drivers/staging/lustre/lustre/ptlrpc/ptlrpc_internal.h index f9decbd1459d..6dd52d99d454 100644 --- a/drivers/staging/lustre/lustre/ptlrpc/ptlrpc_internal.h +++ b/drivers/staging/lustre/lustre/ptlrpc/ptlrpc_internal.h @@ -68,7 +68,7 @@ void ptlrpc_request_cache_free(struct ptlrpc_request *req); void ptlrpc_init_xid(void); void ptlrpc_set_add_new_req(struct ptlrpcd_ctl *pc, struct ptlrpc_request *req); -int ptlrpc_expired_set(void *data); +int ptlrpc_expired_set(struct ptlrpc_request_set *set); int ptlrpc_set_next_timeout(struct ptlrpc_request_set *set); void ptlrpc_resend_req(struct ptlrpc_request *request); void ptlrpc_set_bulk_mbits(struct ptlrpc_request *req); diff --git a/drivers/staging/lustre/lustre/ptlrpc/ptlrpcd.c b/drivers/staging/lustre/lustre/ptlrpc/ptlrpcd.c index 0bdf1f54629b..b7df38e71946 100644 --- a/drivers/staging/lustre/lustre/ptlrpc/ptlrpcd.c +++ b/drivers/staging/lustre/lustre/ptlrpc/ptlrpcd.c @@ -434,16 +434,17 @@ static int ptlrpcd(void *arg) * new_req_list and ptlrpcd_check() moves them into the set. */ do { - struct l_wait_info lwi; int timeout; timeout = ptlrpc_set_next_timeout(set); - lwi = LWI_TIMEOUT((timeout ? timeout : 1) * HZ, - ptlrpc_expired_set, set); lu_context_enter(_ctx); lu_context_enter(env.le_ses); - l_wait_event(set->set_waitq, ptlrpcd_check(, pc), ); + if (wait_event_noload_timeout(set->set_waitq, + ptlrpcd_check(, pc), + (timeout ? timeout : 1) * HZ) == 0) + ptlrpc_expired_set(set); + lu_context_exit(_ctx); lu_context_exit(env.le_ses);
[PATCH 08/16] staging: lustre: open code polling loop instead of using l_wait_event()
Two places that LWI_TIMEOUT_INTERVAL() is used, the outcome is a simple polling loop that polls every second for some event (with a limit). So write a simple loop to make this more apparent. Signed-off-by: NeilBrown --- drivers/staging/lustre/lustre/llite/llite_lib.c | 11 +-- drivers/staging/lustre/lustre/lov/lov_request.c | 12 +--- 2 files changed, 10 insertions(+), 13 deletions(-) diff --git a/drivers/staging/lustre/lustre/llite/llite_lib.c b/drivers/staging/lustre/lustre/llite/llite_lib.c index 33dc15e9aebb..f6642fa30428 100644 --- a/drivers/staging/lustre/lustre/llite/llite_lib.c +++ b/drivers/staging/lustre/lustre/llite/llite_lib.c @@ -1984,8 +1984,7 @@ void ll_umount_begin(struct super_block *sb) struct ll_sb_info *sbi = ll_s2sbi(sb); struct obd_device *obd; struct obd_ioctl_data *ioc_data; - wait_queue_head_t waitq; - struct l_wait_info lwi; + int cnt = 0; CDEBUG(D_VFSTRACE, "VFS Op: superblock %p count %d active %d\n", sb, sb->s_count, atomic_read(>s_active)); @@ -2021,10 +2020,10 @@ void ll_umount_begin(struct super_block *sb) * and then continue. For now, we just periodically checking for vfs * to decrement mnt_cnt and hope to finish it within 10sec. */ - init_waitqueue_head(); - lwi = LWI_TIMEOUT_INTERVAL(10 * HZ, - HZ, NULL, NULL); - l_wait_event(waitq, may_umount(sbi->ll_mnt.mnt), ); + while (cnt < 10 && !may_umount(sbi->ll_mnt.mnt)) { + schedule_timeout_uninterruptible(HZ); + cnt ++; + } schedule(); } diff --git a/drivers/staging/lustre/lustre/lov/lov_request.c b/drivers/staging/lustre/lustre/lov/lov_request.c index fb3b7a7fa32a..c1e58fcc30b3 100644 --- a/drivers/staging/lustre/lustre/lov/lov_request.c +++ b/drivers/staging/lustre/lustre/lov/lov_request.c @@ -99,8 +99,7 @@ static int lov_check_set(struct lov_obd *lov, int idx) */ static int lov_check_and_wait_active(struct lov_obd *lov, int ost_idx) { - wait_queue_head_t waitq; - struct l_wait_info lwi; + int cnt = 0; struct lov_tgt_desc *tgt; int rc = 0; @@ -125,11 +124,10 @@ static int lov_check_and_wait_active(struct lov_obd *lov, int ost_idx) mutex_unlock(>lov_lock); - init_waitqueue_head(); - lwi = LWI_TIMEOUT_INTERVAL(obd_timeout * HZ, - HZ, NULL, NULL); - - rc = l_wait_event(waitq, lov_check_set(lov, ost_idx), ); + while (cnt < obd_timeout && !lov_check_set(lov, ost_idx)) { + schedule_timeout_uninterruptible(HZ); + cnt ++; + } if (tgt->ltd_active) return 1;
[PATCH 01/16] staging: lustre: discard SVC_SIGNAL and related functions
This flag is never set, so remove checks and remove the flag. Signed-off-by: NeilBrown--- drivers/staging/lustre/lustre/include/lustre_net.h |6 -- drivers/staging/lustre/lustre/ptlrpc/sec_gc.c |4 +--- 2 files changed, 1 insertion(+), 9 deletions(-) diff --git a/drivers/staging/lustre/lustre/include/lustre_net.h b/drivers/staging/lustre/lustre/include/lustre_net.h index 3ff5de4770e8..4c665eca2467 100644 --- a/drivers/staging/lustre/lustre/include/lustre_net.h +++ b/drivers/staging/lustre/lustre/include/lustre_net.h @@ -1260,7 +1260,6 @@ enum { SVC_STARTING= 1 << 2, SVC_RUNNING = 1 << 3, SVC_EVENT = 1 << 4, - SVC_SIGNAL = 1 << 5, }; #define PTLRPC_THR_NAME_LEN32 @@ -1333,11 +1332,6 @@ static inline int thread_is_event(struct ptlrpc_thread *thread) return !!(thread->t_flags & SVC_EVENT); } -static inline int thread_is_signal(struct ptlrpc_thread *thread) -{ - return !!(thread->t_flags & SVC_SIGNAL); -} - static inline void thread_clear_flags(struct ptlrpc_thread *thread, __u32 flags) { thread->t_flags &= ~flags; diff --git a/drivers/staging/lustre/lustre/ptlrpc/sec_gc.c b/drivers/staging/lustre/lustre/ptlrpc/sec_gc.c index 8d1e0edfcede..d85c8638c009 100644 --- a/drivers/staging/lustre/lustre/ptlrpc/sec_gc.c +++ b/drivers/staging/lustre/lustre/ptlrpc/sec_gc.c @@ -153,7 +153,6 @@ static int sec_gc_main(void *arg) while (1) { struct ptlrpc_sec *sec; - thread_clear_flags(thread, SVC_SIGNAL); sec_process_ctx_list(); again: /* go through sec list do gc. @@ -184,8 +183,7 @@ static int sec_gc_main(void *arg) lwi = LWI_TIMEOUT(msecs_to_jiffies(SEC_GC_INTERVAL * MSEC_PER_SEC), NULL, NULL); l_wait_event(thread->t_ctl_waitq, -thread_is_stopping(thread) || -thread_is_signal(thread), +thread_is_stopping(thread), ); if (thread_test_and_clear_flags(thread, SVC_STOPPING))
[PATCH 05/16] staging: lustre: introduce and use l_wait_event_abortable()
lustre sometimes wants to wait for an event, but abort if one of a specific list of signals arrives. This is a little bit like wait_event_killable(), except that the signals are identified a different way. So introduce l_wait_event_abortable() which provides this functionality. Having separate functions for separate needs is more in line with the pattern set by include/linux/wait.h, than having a single function which tries to include all possible needs. Also introduce l_wait_event_abortable_exclusive(). Note that l_wait_event() return -EINTR on a signal, while Linux wait_event functions return -ERESTARTSYS. l_wait_event_abortable_exclusive follows the Linux pattern. Signed-off-by: NeilBrown--- drivers/staging/lustre/lustre/include/lustre_lib.h | 24 drivers/staging/lustre/lustre/ldlm/ldlm_resource.c | 12 +- drivers/staging/lustre/lustre/llite/llite_lib.c| 12 +++--- drivers/staging/lustre/lustre/obdclass/genops.c|9 +++- drivers/staging/lustre/lustre/obdclass/llog_obd.c |5 ++-- drivers/staging/lustre/lustre/osc/osc_page.c |6 ++--- drivers/staging/lustre/lustre/osc/osc_request.c|6 ++--- 7 files changed, 43 insertions(+), 31 deletions(-) diff --git a/drivers/staging/lustre/lustre/include/lustre_lib.h b/drivers/staging/lustre/lustre/include/lustre_lib.h index fcf31c779e98..d64306291b47 100644 --- a/drivers/staging/lustre/lustre/include/lustre_lib.h +++ b/drivers/staging/lustre/lustre/include/lustre_lib.h @@ -425,4 +425,28 @@ do { \ __ret = __wait_event_noload_timeout(wq_head, condition, timeout);\ __ret; \ }) + +/* l_wait_event_abortable() is a bit like wait_event_killable() + * except there is a fix set of signals which will abort: + * LUSTRE_FATAL_SIGS + */ +#define l_wait_event_abortable(wq, condition) \ +({ \ + sigset_t __blocked; \ + int __ret = 0; \ + __blocked = cfs_block_sigsinv(LUSTRE_FATAL_SIGS); \ + __ret = wait_event_interruptible(wq, condition);\ + cfs_restore_sigs(__blocked);\ + __ret; \ +}) + +#define l_wait_event_abortable_exclusive(wq, condition) \ +({ \ + sigset_t __blocked; \ + int __ret = 0; \ + __blocked = cfs_block_sigsinv(LUSTRE_FATAL_SIGS); \ + __ret = wait_event_interruptible_exclusive(wq, condition); \ + cfs_restore_sigs(__blocked);\ + __ret; \ +}) #endif /* _LUSTRE_LIB_H */ diff --git a/drivers/staging/lustre/lustre/ldlm/ldlm_resource.c b/drivers/staging/lustre/lustre/ldlm/ldlm_resource.c index 2e66825c8f4b..30044357616d 100644 --- a/drivers/staging/lustre/lustre/ldlm/ldlm_resource.c +++ b/drivers/staging/lustre/lustre/ldlm/ldlm_resource.c @@ -879,7 +879,6 @@ static int __ldlm_namespace_free(struct ldlm_namespace *ns, int force) ldlm_namespace_cleanup(ns, force ? LDLM_FL_LOCAL_ONLY : 0); if (atomic_read(>ns_bref) > 0) { - struct l_wait_info lwi = LWI_INTR(LWI_ON_SIGNAL_NOOP, NULL); int rc; CDEBUG(D_DLMTRACE, @@ -887,11 +886,12 @@ static int __ldlm_namespace_free(struct ldlm_namespace *ns, int force) ldlm_ns_name(ns), atomic_read(>ns_bref)); force_wait: if (force) - lwi = LWI_TIMEOUT(msecs_to_jiffies(obd_timeout * - MSEC_PER_SEC) / 4, NULL, NULL); - - rc = l_wait_event(ns->ns_waitq, - atomic_read(>ns_bref) == 0, ); + rc = wait_event_timeout(ns->ns_waitq, + atomic_read(>ns_bref) == 0, + obd_timeout * HZ / 4) ? 0 : -ETIMEDOUT; + else + rc = l_wait_event_abortable(ns->ns_waitq, + atomic_read(>ns_bref) == 0); /* Forced cleanups should be able to reclaim all references, * so it's safe to wait forever... we can't leak locks... diff --git a/drivers/staging/lustre/lustre/llite/llite_lib.c b/drivers/staging/lustre/lustre/llite/llite_lib.c index 0a9183f271f5..33dc15e9aebb 100644 ---
[PATCH 01/16] staging: lustre: discard SVC_SIGNAL and related functions
This flag is never set, so remove checks and remove the flag. Signed-off-by: NeilBrown --- drivers/staging/lustre/lustre/include/lustre_net.h |6 -- drivers/staging/lustre/lustre/ptlrpc/sec_gc.c |4 +--- 2 files changed, 1 insertion(+), 9 deletions(-) diff --git a/drivers/staging/lustre/lustre/include/lustre_net.h b/drivers/staging/lustre/lustre/include/lustre_net.h index 3ff5de4770e8..4c665eca2467 100644 --- a/drivers/staging/lustre/lustre/include/lustre_net.h +++ b/drivers/staging/lustre/lustre/include/lustre_net.h @@ -1260,7 +1260,6 @@ enum { SVC_STARTING= 1 << 2, SVC_RUNNING = 1 << 3, SVC_EVENT = 1 << 4, - SVC_SIGNAL = 1 << 5, }; #define PTLRPC_THR_NAME_LEN32 @@ -1333,11 +1332,6 @@ static inline int thread_is_event(struct ptlrpc_thread *thread) return !!(thread->t_flags & SVC_EVENT); } -static inline int thread_is_signal(struct ptlrpc_thread *thread) -{ - return !!(thread->t_flags & SVC_SIGNAL); -} - static inline void thread_clear_flags(struct ptlrpc_thread *thread, __u32 flags) { thread->t_flags &= ~flags; diff --git a/drivers/staging/lustre/lustre/ptlrpc/sec_gc.c b/drivers/staging/lustre/lustre/ptlrpc/sec_gc.c index 8d1e0edfcede..d85c8638c009 100644 --- a/drivers/staging/lustre/lustre/ptlrpc/sec_gc.c +++ b/drivers/staging/lustre/lustre/ptlrpc/sec_gc.c @@ -153,7 +153,6 @@ static int sec_gc_main(void *arg) while (1) { struct ptlrpc_sec *sec; - thread_clear_flags(thread, SVC_SIGNAL); sec_process_ctx_list(); again: /* go through sec list do gc. @@ -184,8 +183,7 @@ static int sec_gc_main(void *arg) lwi = LWI_TIMEOUT(msecs_to_jiffies(SEC_GC_INTERVAL * MSEC_PER_SEC), NULL, NULL); l_wait_event(thread->t_ctl_waitq, -thread_is_stopping(thread) || -thread_is_signal(thread), +thread_is_stopping(thread), ); if (thread_test_and_clear_flags(thread, SVC_STOPPING))
[PATCH 05/16] staging: lustre: introduce and use l_wait_event_abortable()
lustre sometimes wants to wait for an event, but abort if one of a specific list of signals arrives. This is a little bit like wait_event_killable(), except that the signals are identified a different way. So introduce l_wait_event_abortable() which provides this functionality. Having separate functions for separate needs is more in line with the pattern set by include/linux/wait.h, than having a single function which tries to include all possible needs. Also introduce l_wait_event_abortable_exclusive(). Note that l_wait_event() return -EINTR on a signal, while Linux wait_event functions return -ERESTARTSYS. l_wait_event_abortable_exclusive follows the Linux pattern. Signed-off-by: NeilBrown --- drivers/staging/lustre/lustre/include/lustre_lib.h | 24 drivers/staging/lustre/lustre/ldlm/ldlm_resource.c | 12 +- drivers/staging/lustre/lustre/llite/llite_lib.c| 12 +++--- drivers/staging/lustre/lustre/obdclass/genops.c|9 +++- drivers/staging/lustre/lustre/obdclass/llog_obd.c |5 ++-- drivers/staging/lustre/lustre/osc/osc_page.c |6 ++--- drivers/staging/lustre/lustre/osc/osc_request.c|6 ++--- 7 files changed, 43 insertions(+), 31 deletions(-) diff --git a/drivers/staging/lustre/lustre/include/lustre_lib.h b/drivers/staging/lustre/lustre/include/lustre_lib.h index fcf31c779e98..d64306291b47 100644 --- a/drivers/staging/lustre/lustre/include/lustre_lib.h +++ b/drivers/staging/lustre/lustre/include/lustre_lib.h @@ -425,4 +425,28 @@ do { \ __ret = __wait_event_noload_timeout(wq_head, condition, timeout);\ __ret; \ }) + +/* l_wait_event_abortable() is a bit like wait_event_killable() + * except there is a fix set of signals which will abort: + * LUSTRE_FATAL_SIGS + */ +#define l_wait_event_abortable(wq, condition) \ +({ \ + sigset_t __blocked; \ + int __ret = 0; \ + __blocked = cfs_block_sigsinv(LUSTRE_FATAL_SIGS); \ + __ret = wait_event_interruptible(wq, condition);\ + cfs_restore_sigs(__blocked);\ + __ret; \ +}) + +#define l_wait_event_abortable_exclusive(wq, condition) \ +({ \ + sigset_t __blocked; \ + int __ret = 0; \ + __blocked = cfs_block_sigsinv(LUSTRE_FATAL_SIGS); \ + __ret = wait_event_interruptible_exclusive(wq, condition); \ + cfs_restore_sigs(__blocked);\ + __ret; \ +}) #endif /* _LUSTRE_LIB_H */ diff --git a/drivers/staging/lustre/lustre/ldlm/ldlm_resource.c b/drivers/staging/lustre/lustre/ldlm/ldlm_resource.c index 2e66825c8f4b..30044357616d 100644 --- a/drivers/staging/lustre/lustre/ldlm/ldlm_resource.c +++ b/drivers/staging/lustre/lustre/ldlm/ldlm_resource.c @@ -879,7 +879,6 @@ static int __ldlm_namespace_free(struct ldlm_namespace *ns, int force) ldlm_namespace_cleanup(ns, force ? LDLM_FL_LOCAL_ONLY : 0); if (atomic_read(>ns_bref) > 0) { - struct l_wait_info lwi = LWI_INTR(LWI_ON_SIGNAL_NOOP, NULL); int rc; CDEBUG(D_DLMTRACE, @@ -887,11 +886,12 @@ static int __ldlm_namespace_free(struct ldlm_namespace *ns, int force) ldlm_ns_name(ns), atomic_read(>ns_bref)); force_wait: if (force) - lwi = LWI_TIMEOUT(msecs_to_jiffies(obd_timeout * - MSEC_PER_SEC) / 4, NULL, NULL); - - rc = l_wait_event(ns->ns_waitq, - atomic_read(>ns_bref) == 0, ); + rc = wait_event_timeout(ns->ns_waitq, + atomic_read(>ns_bref) == 0, + obd_timeout * HZ / 4) ? 0 : -ETIMEDOUT; + else + rc = l_wait_event_abortable(ns->ns_waitq, + atomic_read(>ns_bref) == 0); /* Forced cleanups should be able to reclaim all references, * so it's safe to wait forever... we can't leak locks... diff --git a/drivers/staging/lustre/lustre/llite/llite_lib.c b/drivers/staging/lustre/lustre/llite/llite_lib.c index 0a9183f271f5..33dc15e9aebb 100644 ---
[PATCH 02/16] staging: lustre: replace simple cases of l_wait_event() with wait_event().
When the lwi arg is full of zeros, l_wait_event() behaves almost identically to the standard wait_event() interface, so use that instead. The only difference in behavior is that l_wait_event() blocks all signals and uses an TASK_INTERRUPTIBLE wait, while wait_event() does not block signals, but waits in state TASK_UNINTERRUPTIBLE. This means that processes blocked in wait_event() will contribute to the load average. This behavior is (arguably) more correct - in most cases. In some cases, the wait is in a service thread waiting for work to do. In these case we should wait TASK_NOLOAD order with TASK_UNINTERRUPTIBLE. To facilitate this, add a "wait_event_noload()" macro. This should eventually be moved into include/linux/wait.h. There is one case where wait_event_exclusive_noload() is needed. So we add a macro for that too. Signed-off-by: NeilBrown--- drivers/staging/lustre/lustre/include/lustre_lib.h | 47 --- drivers/staging/lustre/lustre/ldlm/ldlm_lock.c |4 -- drivers/staging/lustre/lustre/ldlm/ldlm_lockd.c|8 +-- drivers/staging/lustre/lustre/ldlm/ldlm_pool.c |5 +- drivers/staging/lustre/lustre/llite/statahead.c| 50 drivers/staging/lustre/lustre/lov/lov_object.c |6 +- drivers/staging/lustre/lustre/mgc/mgc_request.c|4 -- drivers/staging/lustre/lustre/obdclass/cl_io.c |6 +- drivers/staging/lustre/lustre/obdclass/genops.c| 15 ++ drivers/staging/lustre/lustre/osc/osc_cache.c |5 +- drivers/staging/lustre/lustre/osc/osc_object.c |4 -- drivers/staging/lustre/lustre/ptlrpc/pinger.c | 10 ++-- drivers/staging/lustre/lustre/ptlrpc/sec_gc.c | 11 ++-- drivers/staging/lustre/lustre/ptlrpc/service.c | 13 ++--- 14 files changed, 93 insertions(+), 95 deletions(-) diff --git a/drivers/staging/lustre/lustre/include/lustre_lib.h b/drivers/staging/lustre/lustre/include/lustre_lib.h index ca1dce15337e..08bdd618ea7d 100644 --- a/drivers/staging/lustre/lustre/include/lustre_lib.h +++ b/drivers/staging/lustre/lustre/include/lustre_lib.h @@ -333,12 +333,6 @@ do { \ __ret;\ }) -#define l_wait_condition(wq, condition) \ -({ \ - struct l_wait_info lwi = { 0 }; \ - l_wait_event(wq, condition, );\ -}) - #define l_wait_condition_exclusive(wq, condition) \ ({ \ struct l_wait_info lwi = { 0 }; \ @@ -353,4 +347,45 @@ do { \ /** @} lib */ +#define __wait_event_noload(wq_head, condition) \ + (void)___wait_event(wq_head, condition, (TASK_UNINTERRUPTIBLE | TASK_NOLOAD), 0, 0, \ + schedule()) + +/** + * wait_event_noload - sleep, without registering load, until a condition gets true + * @wq_head: the waitqueue to wait on + * @condition: a C expression for the event to wait for + * + * The process is put to sleep (TASK_UNINTERRUPTIBLE|TASK_NOLOAD) until the + * @condition evaluates to true. The @condition is checked each time + * the waitqueue @wq_head is woken up. + * + * wake_up() has to be called after changing any variable that could + * change the result of the wait condition. + * + * This can be used instead of wait_event() when the event + * being waited for is does not imply load on the system, but + * when responding to signals is no appropriate, such as in + * a kernel service thread. + */ +#define wait_event_noload(wq_head, condition) \ +do { \ + might_sleep(); \ + if (condition) \ + break; \ + __wait_event_noload(wq_head, condition); \ +} while (0) + +/* + * Just like wait_event_noload(), except it sets exclusive flag + */ +#define wait_event_exclusive_noload(wq_head, condition) \ +do { \ + if (condition) \ + break; \ + (void)___wait_event(wq_head, condition, \ + (TASK_UNINTERRUPTIBLE | TASK_NOLOAD), 1, 0, \ + schedule()); \ +} while (0)
[PATCH 02/16] staging: lustre: replace simple cases of l_wait_event() with wait_event().
When the lwi arg is full of zeros, l_wait_event() behaves almost identically to the standard wait_event() interface, so use that instead. The only difference in behavior is that l_wait_event() blocks all signals and uses an TASK_INTERRUPTIBLE wait, while wait_event() does not block signals, but waits in state TASK_UNINTERRUPTIBLE. This means that processes blocked in wait_event() will contribute to the load average. This behavior is (arguably) more correct - in most cases. In some cases, the wait is in a service thread waiting for work to do. In these case we should wait TASK_NOLOAD order with TASK_UNINTERRUPTIBLE. To facilitate this, add a "wait_event_noload()" macro. This should eventually be moved into include/linux/wait.h. There is one case where wait_event_exclusive_noload() is needed. So we add a macro for that too. Signed-off-by: NeilBrown --- drivers/staging/lustre/lustre/include/lustre_lib.h | 47 --- drivers/staging/lustre/lustre/ldlm/ldlm_lock.c |4 -- drivers/staging/lustre/lustre/ldlm/ldlm_lockd.c|8 +-- drivers/staging/lustre/lustre/ldlm/ldlm_pool.c |5 +- drivers/staging/lustre/lustre/llite/statahead.c| 50 drivers/staging/lustre/lustre/lov/lov_object.c |6 +- drivers/staging/lustre/lustre/mgc/mgc_request.c|4 -- drivers/staging/lustre/lustre/obdclass/cl_io.c |6 +- drivers/staging/lustre/lustre/obdclass/genops.c| 15 ++ drivers/staging/lustre/lustre/osc/osc_cache.c |5 +- drivers/staging/lustre/lustre/osc/osc_object.c |4 -- drivers/staging/lustre/lustre/ptlrpc/pinger.c | 10 ++-- drivers/staging/lustre/lustre/ptlrpc/sec_gc.c | 11 ++-- drivers/staging/lustre/lustre/ptlrpc/service.c | 13 ++--- 14 files changed, 93 insertions(+), 95 deletions(-) diff --git a/drivers/staging/lustre/lustre/include/lustre_lib.h b/drivers/staging/lustre/lustre/include/lustre_lib.h index ca1dce15337e..08bdd618ea7d 100644 --- a/drivers/staging/lustre/lustre/include/lustre_lib.h +++ b/drivers/staging/lustre/lustre/include/lustre_lib.h @@ -333,12 +333,6 @@ do { \ __ret;\ }) -#define l_wait_condition(wq, condition) \ -({ \ - struct l_wait_info lwi = { 0 }; \ - l_wait_event(wq, condition, );\ -}) - #define l_wait_condition_exclusive(wq, condition) \ ({ \ struct l_wait_info lwi = { 0 }; \ @@ -353,4 +347,45 @@ do { \ /** @} lib */ +#define __wait_event_noload(wq_head, condition) \ + (void)___wait_event(wq_head, condition, (TASK_UNINTERRUPTIBLE | TASK_NOLOAD), 0, 0, \ + schedule()) + +/** + * wait_event_noload - sleep, without registering load, until a condition gets true + * @wq_head: the waitqueue to wait on + * @condition: a C expression for the event to wait for + * + * The process is put to sleep (TASK_UNINTERRUPTIBLE|TASK_NOLOAD) until the + * @condition evaluates to true. The @condition is checked each time + * the waitqueue @wq_head is woken up. + * + * wake_up() has to be called after changing any variable that could + * change the result of the wait condition. + * + * This can be used instead of wait_event() when the event + * being waited for is does not imply load on the system, but + * when responding to signals is no appropriate, such as in + * a kernel service thread. + */ +#define wait_event_noload(wq_head, condition) \ +do { \ + might_sleep(); \ + if (condition) \ + break; \ + __wait_event_noload(wq_head, condition); \ +} while (0) + +/* + * Just like wait_event_noload(), except it sets exclusive flag + */ +#define wait_event_exclusive_noload(wq_head, condition) \ +do { \ + if (condition) \ + break; \ + (void)___wait_event(wq_head, condition, \ + (TASK_UNINTERRUPTIBLE | TASK_NOLOAD), 1, 0, \ + schedule()); \ +} while (0) + #endif /*
[PATCH 03/16] staging: lustre: discard cfs_time_seconds()
cfs_time_seconds() converts a number of second to the matching number of jiffies. The standard way to do this in Linux is "* HZ". So discard cfs_time_seconds() and use "* HZ" instead. Signed-off-by: NeilBrown--- .../lustre/include/linux/libcfs/libcfs_debug.h |4 ++-- .../lustre/include/linux/libcfs/libcfs_time.h |2 +- .../lustre/include/linux/libcfs/linux/linux-time.h |7 +- .../staging/lustre/lnet/klnds/o2iblnd/o2iblnd.c|8 --- .../staging/lustre/lnet/klnds/o2iblnd/o2iblnd_cb.c |4 ++-- .../staging/lustre/lnet/klnds/socklnd/socklnd.c|6 +++-- .../staging/lustre/lnet/klnds/socklnd/socklnd_cb.c | 22 ++-- drivers/staging/lustre/lnet/libcfs/debug.c |2 +- drivers/staging/lustre/lnet/libcfs/fail.c |2 +- drivers/staging/lustre/lnet/libcfs/tracefile.c |4 ++-- drivers/staging/lustre/lnet/lnet/acceptor.c|2 +- drivers/staging/lustre/lnet/lnet/api-ni.c |4 ++-- drivers/staging/lustre/lnet/lnet/lib-move.c|4 ++-- drivers/staging/lustre/lnet/lnet/net_fault.c | 14 + drivers/staging/lustre/lnet/lnet/peer.c|2 +- drivers/staging/lustre/lnet/lnet/router.c |8 --- drivers/staging/lustre/lnet/selftest/conrpc.c |4 ++-- drivers/staging/lustre/lnet/selftest/rpc.c |2 +- drivers/staging/lustre/lnet/selftest/selftest.h|2 +- drivers/staging/lustre/lnet/selftest/timer.c |2 +- drivers/staging/lustre/lustre/include/lustre_dlm.h |2 +- drivers/staging/lustre/lustre/include/lustre_mdc.h |2 +- drivers/staging/lustre/lustre/include/lustre_net.h |2 +- drivers/staging/lustre/lustre/ldlm/ldlm_lock.c |2 +- drivers/staging/lustre/lustre/ldlm/ldlm_lockd.c|4 ++-- drivers/staging/lustre/lustre/ldlm/ldlm_pool.c |2 +- drivers/staging/lustre/lustre/ldlm/ldlm_request.c |2 +- drivers/staging/lustre/lustre/ldlm/ldlm_resource.c |2 +- drivers/staging/lustre/lustre/llite/llite_lib.c|4 ++-- drivers/staging/lustre/lustre/llite/statahead.c|2 +- drivers/staging/lustre/lustre/lov/lov_request.c|4 ++-- drivers/staging/lustre/lustre/mdc/mdc_request.c|2 +- drivers/staging/lustre/lustre/mgc/mgc_request.c|2 +- drivers/staging/lustre/lustre/obdclass/cl_io.c |2 +- .../staging/lustre/lustre/obdecho/echo_client.c|2 +- drivers/staging/lustre/lustre/osc/osc_cache.c |4 ++-- drivers/staging/lustre/lustre/osc/osc_object.c |2 +- drivers/staging/lustre/lustre/ptlrpc/client.c | 10 + drivers/staging/lustre/lustre/ptlrpc/events.c |2 +- drivers/staging/lustre/lustre/ptlrpc/import.c | 15 ++ drivers/staging/lustre/lustre/ptlrpc/niobuf.c |4 ++-- .../staging/lustre/lustre/ptlrpc/pack_generic.c|2 +- drivers/staging/lustre/lustre/ptlrpc/pinger.c |8 --- drivers/staging/lustre/lustre/ptlrpc/ptlrpcd.c |4 ++-- drivers/staging/lustre/lustre/ptlrpc/recover.c |2 +- drivers/staging/lustre/lustre/ptlrpc/service.c |8 --- 46 files changed, 96 insertions(+), 106 deletions(-) diff --git a/drivers/staging/lustre/include/linux/libcfs/libcfs_debug.h b/drivers/staging/lustre/include/linux/libcfs/libcfs_debug.h index 1b98f0953afb..9290a19429e7 100644 --- a/drivers/staging/lustre/include/linux/libcfs/libcfs_debug.h +++ b/drivers/staging/lustre/include/linux/libcfs/libcfs_debug.h @@ -66,8 +66,8 @@ extern unsigned int libcfs_panic_on_lbug; # define DEBUG_SUBSYSTEM S_UNDEFINED #endif -#define CDEBUG_DEFAULT_MAX_DELAY (cfs_time_seconds(600))/* jiffies */ -#define CDEBUG_DEFAULT_MIN_DELAY ((cfs_time_seconds(1) + 1) / 2) /* jiffies */ +#define CDEBUG_DEFAULT_MAX_DELAY (600 * HZ) /* jiffies */ +#define CDEBUG_DEFAULT_MIN_DELAY ((HZ + 1) / 2) /* jiffies */ #define CDEBUG_DEFAULT_BACKOFF 2 struct cfs_debug_limit_state { unsigned long cdls_next; diff --git a/drivers/staging/lustre/include/linux/libcfs/libcfs_time.h b/drivers/staging/lustre/include/linux/libcfs/libcfs_time.h index 9699646decb9..c4f25be78268 100644 --- a/drivers/staging/lustre/include/linux/libcfs/libcfs_time.h +++ b/drivers/staging/lustre/include/linux/libcfs/libcfs_time.h @@ -62,7 +62,7 @@ static inline int cfs_time_aftereq(unsigned long t1, unsigned long t2) static inline unsigned long cfs_time_shift(int seconds) { - return cfs_time_add(cfs_time_current(), cfs_time_seconds(seconds)); + return cfs_time_add(cfs_time_current(), seconds * HZ); } /* diff --git a/drivers/staging/lustre/include/linux/libcfs/linux/linux-time.h b/drivers/staging/lustre/include/linux/libcfs/linux/linux-time.h index aece13698eb4..805cb326af86 100644 --- a/drivers/staging/lustre/include/linux/libcfs/linux/linux-time.h +++ b/drivers/staging/lustre/include/linux/libcfs/linux/linux-time.h @@ -65,11 +65,6 @@ static inline
[PATCH 04/16] staging: lustre: use wait_event_timeout() where appropriate.
When the lwi arg has a timeout, but no timeout callback function, l_wait_event() acts much the same as wait_event_timeout() - the wait is not interruptible and simply waits for the event or the timeouts. The most noticable difference is that the return value is -ETIMEDOUT or 0, rather than 0 or non-zero. Another difference is that the process waiting is included in the load-average. This is probably more correct. A final difference is that if the timeout is zero, l_wait_event() will not time out at all. In the one case where that is possible we need to conditionally use wait_event_noload(). So replace all such calls with wait_event_timeout(), being careful of the return value. In one case, there is no event, so use schedule_timeout_uninterruptible(). Note that the presence or absence of LWI_ON_SIGNAL_NOOP has no effect in these cases. Signed-off-by: NeilBrown--- drivers/staging/lustre/lustre/include/lustre_lib.h | 37 drivers/staging/lustre/lustre/ldlm/ldlm_lock.c | 10 ++--- drivers/staging/lustre/lustre/ldlm/ldlm_pool.c | 12 ++ drivers/staging/lustre/lustre/llite/statahead.c| 14 +++- drivers/staging/lustre/lustre/mdc/mdc_request.c|5 +-- drivers/staging/lustre/lustre/mgc/mgc_request.c| 15 +++- drivers/staging/lustre/lustre/obdclass/cl_io.c | 17 + drivers/staging/lustre/lustre/osc/osc_cache.c | 25 ++ drivers/staging/lustre/lustre/ptlrpc/events.c |7 +--- drivers/staging/lustre/lustre/ptlrpc/import.c | 12 +++--- .../staging/lustre/lustre/ptlrpc/pack_generic.c|9 ++--- drivers/staging/lustre/lustre/ptlrpc/pinger.c | 12 ++ drivers/staging/lustre/lustre/ptlrpc/recover.c | 12 +++--- drivers/staging/lustre/lustre/ptlrpc/sec_gc.c | 10 ++--- drivers/staging/lustre/lustre/ptlrpc/service.c | 10 ++--- 15 files changed, 104 insertions(+), 103 deletions(-) diff --git a/drivers/staging/lustre/lustre/include/lustre_lib.h b/drivers/staging/lustre/lustre/include/lustre_lib.h index 08bdd618ea7d..fcf31c779e98 100644 --- a/drivers/staging/lustre/lustre/include/lustre_lib.h +++ b/drivers/staging/lustre/lustre/include/lustre_lib.h @@ -388,4 +388,41 @@ do { \ schedule()); \ } while (0) +#define __wait_event_noload_timeout(wq_head, condition, timeout) \ + ___wait_event(wq_head, ___wait_cond_timeout(condition), \ + (TASK_UNINTERRUPTIBLE | TASK_NOLOAD), 0, timeout, \ + __ret = schedule_timeout(__ret)) + +/** + * wait_event_noload_timeout - sleep until a condition gets true or a timeout elapses + * @wq_head: the waitqueue to wait on + * @condition: a C expression for the event to wait for + * @timeout: timeout, in jiffies + * + * The process is put to sleep (TASK_UNINTERRUPTIBLE | TASK_NOLOAD) until the + * @condition evaluates to true. The @condition is checked each time + * the waitqueue @wq_head is woken up. + * + * wake_up() has to be called after changing any variable that could + * change the result of the wait condition. + * + * This is suitable for service threads that are waiting for work to do + * where there is no implication that the event not being true yet implies + * any load on the system, and where it is not appropriate for the + * soft-lockup detector to warning if the wait is unusually long. + * + * Returns: + * 0 if the @condition evaluated to %false after the @timeout elapsed, + * 1 if the @condition evaluated to %true after the @timeout elapsed, + * or the remaining jiffies (at least 1) if the @condition evaluated + * to %true before the @timeout elapsed. + */ +#define wait_event_noload_timeout(wq_head, condition, timeout) \ +({ \ + long __ret = timeout; \ + might_sleep(); \ + if (!___wait_cond_timeout(condition)) \ + __ret = __wait_event_noload_timeout(wq_head, condition, timeout);\ + __ret; \ +}) #endif /* _LUSTRE_LIB_H */ diff --git a/drivers/staging/lustre/lustre/ldlm/ldlm_lock.c b/drivers/staging/lustre/lustre/ldlm/ldlm_lock.c index 53500883f243..ba720a888da3 100644 --- a/drivers/staging/lustre/lustre/ldlm/ldlm_lock.c +++ b/drivers/staging/lustre/lustre/ldlm/ldlm_lock.c @@ -1349,7 +1349,6 @@ enum ldlm_mode ldlm_lock_match(struct ldlm_namespace *ns, __u64 flags, if ((flags & LDLM_FL_LVB_READY) && !ldlm_is_lvb_ready(lock)) { __u64 wait_flags = LDLM_FL_LVB_READY |
[PATCH v4 23/36] nds32: Generic timers support
From: Greentime HuThis patch adds support for timer. Signed-off-by: Vincent Chen Signed-off-by: Greentime Hu Reviewed-by: Linus Walleij --- arch/nds32/kernel/time.c | 11 +++ 1 file changed, 11 insertions(+) create mode 100644 arch/nds32/kernel/time.c diff --git a/arch/nds32/kernel/time.c b/arch/nds32/kernel/time.c new file mode 100644 index 000..ac9d78c --- /dev/null +++ b/arch/nds32/kernel/time.c @@ -0,0 +1,11 @@ +// SPDX-License-Identifier: GPL-2.0 +// Copyright (C) 2005-2017 Andes Technology Corporation + +#include +#include + +void __init time_init(void) +{ + of_clk_init(NULL); + timer_probe(); +} -- 1.7.9.5
[PATCH 03/16] staging: lustre: discard cfs_time_seconds()
cfs_time_seconds() converts a number of second to the matching number of jiffies. The standard way to do this in Linux is "* HZ". So discard cfs_time_seconds() and use "* HZ" instead. Signed-off-by: NeilBrown --- .../lustre/include/linux/libcfs/libcfs_debug.h |4 ++-- .../lustre/include/linux/libcfs/libcfs_time.h |2 +- .../lustre/include/linux/libcfs/linux/linux-time.h |7 +- .../staging/lustre/lnet/klnds/o2iblnd/o2iblnd.c|8 --- .../staging/lustre/lnet/klnds/o2iblnd/o2iblnd_cb.c |4 ++-- .../staging/lustre/lnet/klnds/socklnd/socklnd.c|6 +++-- .../staging/lustre/lnet/klnds/socklnd/socklnd_cb.c | 22 ++-- drivers/staging/lustre/lnet/libcfs/debug.c |2 +- drivers/staging/lustre/lnet/libcfs/fail.c |2 +- drivers/staging/lustre/lnet/libcfs/tracefile.c |4 ++-- drivers/staging/lustre/lnet/lnet/acceptor.c|2 +- drivers/staging/lustre/lnet/lnet/api-ni.c |4 ++-- drivers/staging/lustre/lnet/lnet/lib-move.c|4 ++-- drivers/staging/lustre/lnet/lnet/net_fault.c | 14 + drivers/staging/lustre/lnet/lnet/peer.c|2 +- drivers/staging/lustre/lnet/lnet/router.c |8 --- drivers/staging/lustre/lnet/selftest/conrpc.c |4 ++-- drivers/staging/lustre/lnet/selftest/rpc.c |2 +- drivers/staging/lustre/lnet/selftest/selftest.h|2 +- drivers/staging/lustre/lnet/selftest/timer.c |2 +- drivers/staging/lustre/lustre/include/lustre_dlm.h |2 +- drivers/staging/lustre/lustre/include/lustre_mdc.h |2 +- drivers/staging/lustre/lustre/include/lustre_net.h |2 +- drivers/staging/lustre/lustre/ldlm/ldlm_lock.c |2 +- drivers/staging/lustre/lustre/ldlm/ldlm_lockd.c|4 ++-- drivers/staging/lustre/lustre/ldlm/ldlm_pool.c |2 +- drivers/staging/lustre/lustre/ldlm/ldlm_request.c |2 +- drivers/staging/lustre/lustre/ldlm/ldlm_resource.c |2 +- drivers/staging/lustre/lustre/llite/llite_lib.c|4 ++-- drivers/staging/lustre/lustre/llite/statahead.c|2 +- drivers/staging/lustre/lustre/lov/lov_request.c|4 ++-- drivers/staging/lustre/lustre/mdc/mdc_request.c|2 +- drivers/staging/lustre/lustre/mgc/mgc_request.c|2 +- drivers/staging/lustre/lustre/obdclass/cl_io.c |2 +- .../staging/lustre/lustre/obdecho/echo_client.c|2 +- drivers/staging/lustre/lustre/osc/osc_cache.c |4 ++-- drivers/staging/lustre/lustre/osc/osc_object.c |2 +- drivers/staging/lustre/lustre/ptlrpc/client.c | 10 + drivers/staging/lustre/lustre/ptlrpc/events.c |2 +- drivers/staging/lustre/lustre/ptlrpc/import.c | 15 ++ drivers/staging/lustre/lustre/ptlrpc/niobuf.c |4 ++-- .../staging/lustre/lustre/ptlrpc/pack_generic.c|2 +- drivers/staging/lustre/lustre/ptlrpc/pinger.c |8 --- drivers/staging/lustre/lustre/ptlrpc/ptlrpcd.c |4 ++-- drivers/staging/lustre/lustre/ptlrpc/recover.c |2 +- drivers/staging/lustre/lustre/ptlrpc/service.c |8 --- 46 files changed, 96 insertions(+), 106 deletions(-) diff --git a/drivers/staging/lustre/include/linux/libcfs/libcfs_debug.h b/drivers/staging/lustre/include/linux/libcfs/libcfs_debug.h index 1b98f0953afb..9290a19429e7 100644 --- a/drivers/staging/lustre/include/linux/libcfs/libcfs_debug.h +++ b/drivers/staging/lustre/include/linux/libcfs/libcfs_debug.h @@ -66,8 +66,8 @@ extern unsigned int libcfs_panic_on_lbug; # define DEBUG_SUBSYSTEM S_UNDEFINED #endif -#define CDEBUG_DEFAULT_MAX_DELAY (cfs_time_seconds(600))/* jiffies */ -#define CDEBUG_DEFAULT_MIN_DELAY ((cfs_time_seconds(1) + 1) / 2) /* jiffies */ +#define CDEBUG_DEFAULT_MAX_DELAY (600 * HZ) /* jiffies */ +#define CDEBUG_DEFAULT_MIN_DELAY ((HZ + 1) / 2) /* jiffies */ #define CDEBUG_DEFAULT_BACKOFF 2 struct cfs_debug_limit_state { unsigned long cdls_next; diff --git a/drivers/staging/lustre/include/linux/libcfs/libcfs_time.h b/drivers/staging/lustre/include/linux/libcfs/libcfs_time.h index 9699646decb9..c4f25be78268 100644 --- a/drivers/staging/lustre/include/linux/libcfs/libcfs_time.h +++ b/drivers/staging/lustre/include/linux/libcfs/libcfs_time.h @@ -62,7 +62,7 @@ static inline int cfs_time_aftereq(unsigned long t1, unsigned long t2) static inline unsigned long cfs_time_shift(int seconds) { - return cfs_time_add(cfs_time_current(), cfs_time_seconds(seconds)); + return cfs_time_add(cfs_time_current(), seconds * HZ); } /* diff --git a/drivers/staging/lustre/include/linux/libcfs/linux/linux-time.h b/drivers/staging/lustre/include/linux/libcfs/linux/linux-time.h index aece13698eb4..805cb326af86 100644 --- a/drivers/staging/lustre/include/linux/libcfs/linux/linux-time.h +++ b/drivers/staging/lustre/include/linux/libcfs/linux/linux-time.h @@ -65,11 +65,6 @@ static inline unsigned long
[PATCH 04/16] staging: lustre: use wait_event_timeout() where appropriate.
When the lwi arg has a timeout, but no timeout callback function, l_wait_event() acts much the same as wait_event_timeout() - the wait is not interruptible and simply waits for the event or the timeouts. The most noticable difference is that the return value is -ETIMEDOUT or 0, rather than 0 or non-zero. Another difference is that the process waiting is included in the load-average. This is probably more correct. A final difference is that if the timeout is zero, l_wait_event() will not time out at all. In the one case where that is possible we need to conditionally use wait_event_noload(). So replace all such calls with wait_event_timeout(), being careful of the return value. In one case, there is no event, so use schedule_timeout_uninterruptible(). Note that the presence or absence of LWI_ON_SIGNAL_NOOP has no effect in these cases. Signed-off-by: NeilBrown --- drivers/staging/lustre/lustre/include/lustre_lib.h | 37 drivers/staging/lustre/lustre/ldlm/ldlm_lock.c | 10 ++--- drivers/staging/lustre/lustre/ldlm/ldlm_pool.c | 12 ++ drivers/staging/lustre/lustre/llite/statahead.c| 14 +++- drivers/staging/lustre/lustre/mdc/mdc_request.c|5 +-- drivers/staging/lustre/lustre/mgc/mgc_request.c| 15 +++- drivers/staging/lustre/lustre/obdclass/cl_io.c | 17 + drivers/staging/lustre/lustre/osc/osc_cache.c | 25 ++ drivers/staging/lustre/lustre/ptlrpc/events.c |7 +--- drivers/staging/lustre/lustre/ptlrpc/import.c | 12 +++--- .../staging/lustre/lustre/ptlrpc/pack_generic.c|9 ++--- drivers/staging/lustre/lustre/ptlrpc/pinger.c | 12 ++ drivers/staging/lustre/lustre/ptlrpc/recover.c | 12 +++--- drivers/staging/lustre/lustre/ptlrpc/sec_gc.c | 10 ++--- drivers/staging/lustre/lustre/ptlrpc/service.c | 10 ++--- 15 files changed, 104 insertions(+), 103 deletions(-) diff --git a/drivers/staging/lustre/lustre/include/lustre_lib.h b/drivers/staging/lustre/lustre/include/lustre_lib.h index 08bdd618ea7d..fcf31c779e98 100644 --- a/drivers/staging/lustre/lustre/include/lustre_lib.h +++ b/drivers/staging/lustre/lustre/include/lustre_lib.h @@ -388,4 +388,41 @@ do { \ schedule()); \ } while (0) +#define __wait_event_noload_timeout(wq_head, condition, timeout) \ + ___wait_event(wq_head, ___wait_cond_timeout(condition), \ + (TASK_UNINTERRUPTIBLE | TASK_NOLOAD), 0, timeout, \ + __ret = schedule_timeout(__ret)) + +/** + * wait_event_noload_timeout - sleep until a condition gets true or a timeout elapses + * @wq_head: the waitqueue to wait on + * @condition: a C expression for the event to wait for + * @timeout: timeout, in jiffies + * + * The process is put to sleep (TASK_UNINTERRUPTIBLE | TASK_NOLOAD) until the + * @condition evaluates to true. The @condition is checked each time + * the waitqueue @wq_head is woken up. + * + * wake_up() has to be called after changing any variable that could + * change the result of the wait condition. + * + * This is suitable for service threads that are waiting for work to do + * where there is no implication that the event not being true yet implies + * any load on the system, and where it is not appropriate for the + * soft-lockup detector to warning if the wait is unusually long. + * + * Returns: + * 0 if the @condition evaluated to %false after the @timeout elapsed, + * 1 if the @condition evaluated to %true after the @timeout elapsed, + * or the remaining jiffies (at least 1) if the @condition evaluated + * to %true before the @timeout elapsed. + */ +#define wait_event_noload_timeout(wq_head, condition, timeout) \ +({ \ + long __ret = timeout; \ + might_sleep(); \ + if (!___wait_cond_timeout(condition)) \ + __ret = __wait_event_noload_timeout(wq_head, condition, timeout);\ + __ret; \ +}) #endif /* _LUSTRE_LIB_H */ diff --git a/drivers/staging/lustre/lustre/ldlm/ldlm_lock.c b/drivers/staging/lustre/lustre/ldlm/ldlm_lock.c index 53500883f243..ba720a888da3 100644 --- a/drivers/staging/lustre/lustre/ldlm/ldlm_lock.c +++ b/drivers/staging/lustre/lustre/ldlm/ldlm_lock.c @@ -1349,7 +1349,6 @@ enum ldlm_mode ldlm_lock_match(struct ldlm_namespace *ns, __u64 flags, if ((flags & LDLM_FL_LVB_READY) && !ldlm_is_lvb_ready(lock)) { __u64 wait_flags = LDLM_FL_LVB_READY | LDLM_FL_DESTROYED |
[PATCH v4 23/36] nds32: Generic timers support
From: Greentime Hu This patch adds support for timer. Signed-off-by: Vincent Chen Signed-off-by: Greentime Hu Reviewed-by: Linus Walleij --- arch/nds32/kernel/time.c | 11 +++ 1 file changed, 11 insertions(+) create mode 100644 arch/nds32/kernel/time.c diff --git a/arch/nds32/kernel/time.c b/arch/nds32/kernel/time.c new file mode 100644 index 000..ac9d78c --- /dev/null +++ b/arch/nds32/kernel/time.c @@ -0,0 +1,11 @@ +// SPDX-License-Identifier: GPL-2.0 +// Copyright (C) 2005-2017 Andes Technology Corporation + +#include +#include + +void __init time_init(void) +{ + of_clk_init(NULL); + timer_probe(); +} -- 1.7.9.5
[PATCH v4 24/36] nds32: Device tree support
From: Greentime HuThis patch adds support for device tree. Signed-off-by: Vincent Chen Signed-off-by: Greentime Hu --- arch/nds32/boot/dts/Makefile |8 + arch/nds32/boot/dts/ae3xx.dts | 65 + arch/nds32/kernel/devtree.c | 19 3 files changed, 92 insertions(+) create mode 100644 arch/nds32/boot/dts/Makefile create mode 100644 arch/nds32/boot/dts/ae3xx.dts create mode 100644 arch/nds32/kernel/devtree.c diff --git a/arch/nds32/boot/dts/Makefile b/arch/nds32/boot/dts/Makefile new file mode 100644 index 000..d31faa8 --- /dev/null +++ b/arch/nds32/boot/dts/Makefile @@ -0,0 +1,8 @@ +ifneq '$(CONFIG_NDS32_BUILTIN_DTB)' '""' +BUILTIN_DTB := $(patsubst "%",%,$(CONFIG_NDS32_BUILTIN_DTB)).dtb.o +else +BUILTIN_DTB := +endif +obj-$(CONFIG_OF) += $(BUILTIN_DTB) + +clean-files := *.dtb *.dtb.S diff --git a/arch/nds32/boot/dts/ae3xx.dts b/arch/nds32/boot/dts/ae3xx.dts new file mode 100644 index 000..0ef2c44 --- /dev/null +++ b/arch/nds32/boot/dts/ae3xx.dts @@ -0,0 +1,65 @@ +/dts-v1/; +/ { + compatible = "andestech,ae3xx"; + #address-cells = <1>; + #size-cells = <1>; + interrupt-parent = <>; + + chosen { + stdout-path = + }; + + memory@0 { + device_type = "memory"; + reg = <0x 0x4000>; + }; + + cpus { + #address-cells = <1>; + #size-cells = <0>; + cpu@0 { + device_type = "cpu"; + compatible = "andestech,n13", "andestech,nds32v3"; + reg = <0>; + clock-frequency = <6000>; + }; + }; + + apb: clk@0 { + #clock-cells = <0>; + compatible = "fixed-clock"; + clock-frequency = <3000>; + }; + + + intc: interrupt-controller { + compatible = "andestech,ativic32"; + #interrupt-cells = <1>; + interrupt-controller; + }; + + serial0: serial@f030 { + compatible = "andestech,uart16550", "ns16550a"; + reg = <0xf030 0x1000>; + interrupts = <8>; + clock-frequency = <14745600>; + reg-shift = <2>; + reg-offset = <32>; + no-loopback-test = <1>; + }; + + timer0: timer@f040 { + compatible = "andestech,atcpit100"; + reg = <0xf040 0x1000>; + interrupts = <2>; + clocks = <>; + clock-names = "PCLK"; + }; + + mac0: mac@e010 { + compatible = "andestech,atmac100"; + reg = <0xe010 0x1000>; + interrupts = <18>; + }; + +}; diff --git a/arch/nds32/kernel/devtree.c b/arch/nds32/kernel/devtree.c new file mode 100644 index 000..bdce0fe --- /dev/null +++ b/arch/nds32/kernel/devtree.c @@ -0,0 +1,19 @@ +// SPDX-License-Identifier: GPL-2.0 +// Copyright (C) 2005-2017 Andes Technology Corporation + +#include +#include +#include + +void __init early_init_devtree(void *params) +{ + if (!params || !early_init_dt_scan(params)) { + pr_crit("\n" + "Error: invalid device tree blob at (virtual address 0x%p)\n" + "\nPlease check your bootloader.", params); + + BUG_ON(1); + } + + dump_stack_set_arch_desc("%s (DT)", of_flat_dt_get_machine_name()); +} -- 1.7.9.5
[PATCH v4 24/36] nds32: Device tree support
From: Greentime Hu This patch adds support for device tree. Signed-off-by: Vincent Chen Signed-off-by: Greentime Hu --- arch/nds32/boot/dts/Makefile |8 + arch/nds32/boot/dts/ae3xx.dts | 65 + arch/nds32/kernel/devtree.c | 19 3 files changed, 92 insertions(+) create mode 100644 arch/nds32/boot/dts/Makefile create mode 100644 arch/nds32/boot/dts/ae3xx.dts create mode 100644 arch/nds32/kernel/devtree.c diff --git a/arch/nds32/boot/dts/Makefile b/arch/nds32/boot/dts/Makefile new file mode 100644 index 000..d31faa8 --- /dev/null +++ b/arch/nds32/boot/dts/Makefile @@ -0,0 +1,8 @@ +ifneq '$(CONFIG_NDS32_BUILTIN_DTB)' '""' +BUILTIN_DTB := $(patsubst "%",%,$(CONFIG_NDS32_BUILTIN_DTB)).dtb.o +else +BUILTIN_DTB := +endif +obj-$(CONFIG_OF) += $(BUILTIN_DTB) + +clean-files := *.dtb *.dtb.S diff --git a/arch/nds32/boot/dts/ae3xx.dts b/arch/nds32/boot/dts/ae3xx.dts new file mode 100644 index 000..0ef2c44 --- /dev/null +++ b/arch/nds32/boot/dts/ae3xx.dts @@ -0,0 +1,65 @@ +/dts-v1/; +/ { + compatible = "andestech,ae3xx"; + #address-cells = <1>; + #size-cells = <1>; + interrupt-parent = <>; + + chosen { + stdout-path = + }; + + memory@0 { + device_type = "memory"; + reg = <0x 0x4000>; + }; + + cpus { + #address-cells = <1>; + #size-cells = <0>; + cpu@0 { + device_type = "cpu"; + compatible = "andestech,n13", "andestech,nds32v3"; + reg = <0>; + clock-frequency = <6000>; + }; + }; + + apb: clk@0 { + #clock-cells = <0>; + compatible = "fixed-clock"; + clock-frequency = <3000>; + }; + + + intc: interrupt-controller { + compatible = "andestech,ativic32"; + #interrupt-cells = <1>; + interrupt-controller; + }; + + serial0: serial@f030 { + compatible = "andestech,uart16550", "ns16550a"; + reg = <0xf030 0x1000>; + interrupts = <8>; + clock-frequency = <14745600>; + reg-shift = <2>; + reg-offset = <32>; + no-loopback-test = <1>; + }; + + timer0: timer@f040 { + compatible = "andestech,atcpit100"; + reg = <0xf040 0x1000>; + interrupts = <2>; + clocks = <>; + clock-names = "PCLK"; + }; + + mac0: mac@e010 { + compatible = "andestech,atmac100"; + reg = <0xe010 0x1000>; + interrupts = <18>; + }; + +}; diff --git a/arch/nds32/kernel/devtree.c b/arch/nds32/kernel/devtree.c new file mode 100644 index 000..bdce0fe --- /dev/null +++ b/arch/nds32/kernel/devtree.c @@ -0,0 +1,19 @@ +// SPDX-License-Identifier: GPL-2.0 +// Copyright (C) 2005-2017 Andes Technology Corporation + +#include +#include +#include + +void __init early_init_devtree(void *params) +{ + if (!params || !early_init_dt_scan(params)) { + pr_crit("\n" + "Error: invalid device tree blob at (virtual address 0x%p)\n" + "\nPlease check your bootloader.", params); + + BUG_ON(1); + } + + dump_stack_set_arch_desc("%s (DT)", of_flat_dt_get_machine_name()); +} -- 1.7.9.5
[PATCH v4 26/36] nds32: defconfig
From: Greentime HuThis patch adds nds32 defconfig. Signed-off-by: Vincent Chen Signed-off-by: Greentime Hu --- arch/nds32/configs/defconfig | 108 ++ 1 file changed, 108 insertions(+) create mode 100644 arch/nds32/configs/defconfig diff --git a/arch/nds32/configs/defconfig b/arch/nds32/configs/defconfig new file mode 100644 index 000..4d79d2db --- /dev/null +++ b/arch/nds32/configs/defconfig @@ -0,0 +1,108 @@ +CONFIG_CROSS_COMPILE="nds32le-linux-" +CONFIG_SYSVIPC=y +CONFIG_POSIX_MQUEUE=y +CONFIG_HIGH_RES_TIMERS=y +CONFIG_BSD_PROCESS_ACCT=y +CONFIG_BSD_PROCESS_ACCT_V3=y +CONFIG_IKCONFIG=y +CONFIG_IKCONFIG_PROC=y +CONFIG_LOG_BUF_SHIFT=14 +CONFIG_USER_NS=y +CONFIG_RELAY=y +CONFIG_BLK_DEV_INITRD=y +CONFIG_KALLSYMS_ALL=y +CONFIG_PROFILING=y +CONFIG_MODULES=y +CONFIG_MODULE_UNLOAD=y +# CONFIG_BLK_DEV_BSG is not set +# CONFIG_CACHE_L2 is not set +CONFIG_VMSPLIT_3G_OPT=y +CONFIG_PREEMPT=y +# CONFIG_COMPACTION is not set +CONFIG_HZ_100=y +# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set +CONFIG_NET=y +CONFIG_PACKET=y +CONFIG_UNIX=y +CONFIG_NET_KEY=y +CONFIG_INET=y +CONFIG_IP_MULTICAST=y +# CONFIG_INET_XFRM_MODE_TRANSPORT is not set +# CONFIG_INET_XFRM_MODE_TUNNEL is not set +# CONFIG_INET_XFRM_MODE_BEET is not set +# CONFIG_INET_DIAG is not set +# CONFIG_IPV6 is not set +# CONFIG_BLK_DEV is not set +CONFIG_NETDEVICES=y +# CONFIG_NET_CADENCE is not set +# CONFIG_NET_VENDOR_BROADCOM is not set +CONFIG_FTMAC100=y +# CONFIG_NET_VENDOR_INTEL is not set +# CONFIG_NET_VENDOR_MARVELL is not set +# CONFIG_NET_VENDOR_MICREL is not set +# CONFIG_NET_VENDOR_NATSEMI is not set +# CONFIG_NET_VENDOR_SEEQ is not set +# CONFIG_NET_VENDOR_STMICRO is not set +# CONFIG_NET_VENDOR_WIZNET is not set +CONFIG_INPUT_EVDEV=y +# CONFIG_INPUT_KEYBOARD is not set +# CONFIG_INPUT_MOUSE is not set +CONFIG_INPUT_TOUCHSCREEN=y +# CONFIG_SERIO is not set +CONFIG_VT_HW_CONSOLE_BINDING=y +CONFIG_SERIAL_8250=y +# CONFIG_SERIAL_8250_DEPRECATED_OPTIONS is not set +CONFIG_SERIAL_8250_CONSOLE=y +CONFIG_SERIAL_8250_NR_UARTS=3 +CONFIG_SERIAL_8250_RUNTIME_UARTS=3 +CONFIG_SERIAL_OF_PLATFORM=y +# CONFIG_HW_RANDOM is not set +# CONFIG_HWMON is not set +# CONFIG_RC_CORE is not set +# CONFIG_VGA_CONSOLE is not set +# CONFIG_HID_A4TECH is not set +# CONFIG_HID_APPLE is not set +# CONFIG_HID_BELKIN is not set +# CONFIG_HID_CHERRY is not set +# CONFIG_HID_CHICONY is not set +# CONFIG_HID_CYPRESS is not set +# CONFIG_HID_EZKEY is not set +# CONFIG_HID_ITE is not set +# CONFIG_HID_KENSINGTON is not set +# CONFIG_HID_LOGITECH is not set +# CONFIG_HID_MICROSOFT is not set +# CONFIG_HID_MONTEREY is not set +# CONFIG_USB_SUPPORT is not set +CONFIG_TIMER_ATCPIT100=y +CONFIG_GENERIC_PHY=y +CONFIG_EXT4_FS=y +CONFIG_EXT4_FS_POSIX_ACL=y +CONFIG_EXT4_FS_SECURITY=y +CONFIG_EXT4_ENCRYPTION=y +CONFIG_FUSE_FS=y +CONFIG_MSDOS_FS=y +CONFIG_VFAT_FS=y +CONFIG_TMPFS=y +CONFIG_TMPFS_POSIX_ACL=y +CONFIG_CONFIGFS_FS=y +CONFIG_NFS_FS=y +CONFIG_NFS_V3_ACL=y +CONFIG_NFS_V4=y +CONFIG_NFS_V4_1=y +CONFIG_NFS_USE_LEGACY_DNS=y +CONFIG_NLS_CODEPAGE_437=y +CONFIG_NLS_ISO8859_1=y +CONFIG_DEBUG_INFO=y +CONFIG_DEBUG_INFO_DWARF4=y +CONFIG_GDB_SCRIPTS=y +CONFIG_READABLE_ASM=y +CONFIG_HEADERS_CHECK=y +CONFIG_DEBUG_SECTION_MISMATCH=y +CONFIG_MAGIC_SYSRQ=y +CONFIG_DEBUG_KERNEL=y +CONFIG_PANIC_ON_OOPS=y +# CONFIG_SCHED_DEBUG is not set +# CONFIG_DEBUG_PREEMPT is not set +CONFIG_STACKTRACE=y +CONFIG_RCU_CPU_STALL_TIMEOUT=300 +# CONFIG_CRYPTO_HW is not set -- 1.7.9.5
[PATCH v4 26/36] nds32: defconfig
From: Greentime Hu This patch adds nds32 defconfig. Signed-off-by: Vincent Chen Signed-off-by: Greentime Hu --- arch/nds32/configs/defconfig | 108 ++ 1 file changed, 108 insertions(+) create mode 100644 arch/nds32/configs/defconfig diff --git a/arch/nds32/configs/defconfig b/arch/nds32/configs/defconfig new file mode 100644 index 000..4d79d2db --- /dev/null +++ b/arch/nds32/configs/defconfig @@ -0,0 +1,108 @@ +CONFIG_CROSS_COMPILE="nds32le-linux-" +CONFIG_SYSVIPC=y +CONFIG_POSIX_MQUEUE=y +CONFIG_HIGH_RES_TIMERS=y +CONFIG_BSD_PROCESS_ACCT=y +CONFIG_BSD_PROCESS_ACCT_V3=y +CONFIG_IKCONFIG=y +CONFIG_IKCONFIG_PROC=y +CONFIG_LOG_BUF_SHIFT=14 +CONFIG_USER_NS=y +CONFIG_RELAY=y +CONFIG_BLK_DEV_INITRD=y +CONFIG_KALLSYMS_ALL=y +CONFIG_PROFILING=y +CONFIG_MODULES=y +CONFIG_MODULE_UNLOAD=y +# CONFIG_BLK_DEV_BSG is not set +# CONFIG_CACHE_L2 is not set +CONFIG_VMSPLIT_3G_OPT=y +CONFIG_PREEMPT=y +# CONFIG_COMPACTION is not set +CONFIG_HZ_100=y +# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set +CONFIG_NET=y +CONFIG_PACKET=y +CONFIG_UNIX=y +CONFIG_NET_KEY=y +CONFIG_INET=y +CONFIG_IP_MULTICAST=y +# CONFIG_INET_XFRM_MODE_TRANSPORT is not set +# CONFIG_INET_XFRM_MODE_TUNNEL is not set +# CONFIG_INET_XFRM_MODE_BEET is not set +# CONFIG_INET_DIAG is not set +# CONFIG_IPV6 is not set +# CONFIG_BLK_DEV is not set +CONFIG_NETDEVICES=y +# CONFIG_NET_CADENCE is not set +# CONFIG_NET_VENDOR_BROADCOM is not set +CONFIG_FTMAC100=y +# CONFIG_NET_VENDOR_INTEL is not set +# CONFIG_NET_VENDOR_MARVELL is not set +# CONFIG_NET_VENDOR_MICREL is not set +# CONFIG_NET_VENDOR_NATSEMI is not set +# CONFIG_NET_VENDOR_SEEQ is not set +# CONFIG_NET_VENDOR_STMICRO is not set +# CONFIG_NET_VENDOR_WIZNET is not set +CONFIG_INPUT_EVDEV=y +# CONFIG_INPUT_KEYBOARD is not set +# CONFIG_INPUT_MOUSE is not set +CONFIG_INPUT_TOUCHSCREEN=y +# CONFIG_SERIO is not set +CONFIG_VT_HW_CONSOLE_BINDING=y +CONFIG_SERIAL_8250=y +# CONFIG_SERIAL_8250_DEPRECATED_OPTIONS is not set +CONFIG_SERIAL_8250_CONSOLE=y +CONFIG_SERIAL_8250_NR_UARTS=3 +CONFIG_SERIAL_8250_RUNTIME_UARTS=3 +CONFIG_SERIAL_OF_PLATFORM=y +# CONFIG_HW_RANDOM is not set +# CONFIG_HWMON is not set +# CONFIG_RC_CORE is not set +# CONFIG_VGA_CONSOLE is not set +# CONFIG_HID_A4TECH is not set +# CONFIG_HID_APPLE is not set +# CONFIG_HID_BELKIN is not set +# CONFIG_HID_CHERRY is not set +# CONFIG_HID_CHICONY is not set +# CONFIG_HID_CYPRESS is not set +# CONFIG_HID_EZKEY is not set +# CONFIG_HID_ITE is not set +# CONFIG_HID_KENSINGTON is not set +# CONFIG_HID_LOGITECH is not set +# CONFIG_HID_MICROSOFT is not set +# CONFIG_HID_MONTEREY is not set +# CONFIG_USB_SUPPORT is not set +CONFIG_TIMER_ATCPIT100=y +CONFIG_GENERIC_PHY=y +CONFIG_EXT4_FS=y +CONFIG_EXT4_FS_POSIX_ACL=y +CONFIG_EXT4_FS_SECURITY=y +CONFIG_EXT4_ENCRYPTION=y +CONFIG_FUSE_FS=y +CONFIG_MSDOS_FS=y +CONFIG_VFAT_FS=y +CONFIG_TMPFS=y +CONFIG_TMPFS_POSIX_ACL=y +CONFIG_CONFIGFS_FS=y +CONFIG_NFS_FS=y +CONFIG_NFS_V3_ACL=y +CONFIG_NFS_V4=y +CONFIG_NFS_V4_1=y +CONFIG_NFS_USE_LEGACY_DNS=y +CONFIG_NLS_CODEPAGE_437=y +CONFIG_NLS_ISO8859_1=y +CONFIG_DEBUG_INFO=y +CONFIG_DEBUG_INFO_DWARF4=y +CONFIG_GDB_SCRIPTS=y +CONFIG_READABLE_ASM=y +CONFIG_HEADERS_CHECK=y +CONFIG_DEBUG_SECTION_MISMATCH=y +CONFIG_MAGIC_SYSRQ=y +CONFIG_DEBUG_KERNEL=y +CONFIG_PANIC_ON_OOPS=y +# CONFIG_SCHED_DEBUG is not set +# CONFIG_DEBUG_PREEMPT is not set +CONFIG_STACKTRACE=y +CONFIG_RCU_CPU_STALL_TIMEOUT=300 +# CONFIG_CRYPTO_HW is not set -- 1.7.9.5
[PATCH v4 28/36] MAINTAINERS: Add nds32
From: Greentime HuSigned-off-by: Greentime Hu --- MAINTAINERS | 11 +++ 1 file changed, 11 insertions(+) diff --git a/MAINTAINERS b/MAINTAINERS index 2f4e462..20284c8 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -857,6 +857,17 @@ X: drivers/iio/*/adjd* F: drivers/staging/iio/*/ad* F: drivers/staging/iio/trigger/iio-trig-bfin-timer.c +ANDES ARCHITECTURE +M: Greentime Hu +M: Vincent Chen +T: git https://github.com/andestech/linux.git +S: Supported +F: arch/nds32 +F: Documentation/devicetree/bindings/interrupt-controller/andestech,ativic32.txt +F: Documentation/devicetree/bindings/nds32 +K: nds32 +N: nds32 + ANDROID CONFIG FRAGMENTS M: Rob Herring S: Supported -- 1.7.9.5
[PATCH v4 28/36] MAINTAINERS: Add nds32
From: Greentime Hu Signed-off-by: Greentime Hu --- MAINTAINERS | 11 +++ 1 file changed, 11 insertions(+) diff --git a/MAINTAINERS b/MAINTAINERS index 2f4e462..20284c8 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -857,6 +857,17 @@ X: drivers/iio/*/adjd* F: drivers/staging/iio/*/ad* F: drivers/staging/iio/trigger/iio-trig-bfin-timer.c +ANDES ARCHITECTURE +M: Greentime Hu +M: Vincent Chen +T: git https://github.com/andestech/linux.git +S: Supported +F: arch/nds32 +F: Documentation/devicetree/bindings/interrupt-controller/andestech,ativic32.txt +F: Documentation/devicetree/bindings/nds32 +K: nds32 +N: nds32 + ANDROID CONFIG FRAGMENTS M: Rob Herring S: Supported -- 1.7.9.5
[PATCH v4 30/36] dt-bindings: nds32 SoC Bindings
From: Greentime HuThis patch adds nds32 SoC(AE3XX and AG101P) binding documents. Signed-off-by: Greentime Hu Reviewed-by: Rob Herring --- .../devicetree/bindings/nds32/andestech-boards | 40 1 file changed, 40 insertions(+) create mode 100644 Documentation/devicetree/bindings/nds32/andestech-boards diff --git a/Documentation/devicetree/bindings/nds32/andestech-boards b/Documentation/devicetree/bindings/nds32/andestech-boards new file mode 100644 index 000..f5d7569 --- /dev/null +++ b/Documentation/devicetree/bindings/nds32/andestech-boards @@ -0,0 +1,40 @@ +Andestech(nds32) AE3XX Platform +- +The AE3XX prototype demonstrates the AE3XX example platform on the FPGA. It +is composed of one Andestech(nds32) processor and AE3XX. + +Required properties (in root node): +- compatible = "andestech,ae3xx"; + +Example: +/dts-v1/; +/ { + compatible = "andestech,ae3xx"; + #address-cells = <1>; + #size-cells = <1>; + interrupt-parent = <>; +}; + +Andestech(nds32) AG101P Platform +- +AG101P is a generic SoC Platform IP that works with any of Andestech(nds32) +processors to provide a cost-effective and high performance solution for +majority of embedded systems in variety of application domains. Users may +simply attach their IP on one of the system buses together with certain glue +logics to complete a SoC solution for a specific application. With +comprehensive simulation and design environments, users may evaluate the +system performance of their applications and track bugs of their designs +efficiently. The optional hardware development platform further provides real +system environment for early prototyping and software/hardware co-development. + +Required properties (in root node): + compatible = "andestech,ag101p"; + +Example: +/dts-v1/; +/ { + compatible = "andestech,ag101p"; + #address-cells = <1>; + #size-cells = <1>; + interrupt-parent = <>; +}; -- 1.7.9.5
[PATCH v4 30/36] dt-bindings: nds32 SoC Bindings
From: Greentime Hu This patch adds nds32 SoC(AE3XX and AG101P) binding documents. Signed-off-by: Greentime Hu Reviewed-by: Rob Herring --- .../devicetree/bindings/nds32/andestech-boards | 40 1 file changed, 40 insertions(+) create mode 100644 Documentation/devicetree/bindings/nds32/andestech-boards diff --git a/Documentation/devicetree/bindings/nds32/andestech-boards b/Documentation/devicetree/bindings/nds32/andestech-boards new file mode 100644 index 000..f5d7569 --- /dev/null +++ b/Documentation/devicetree/bindings/nds32/andestech-boards @@ -0,0 +1,40 @@ +Andestech(nds32) AE3XX Platform +- +The AE3XX prototype demonstrates the AE3XX example platform on the FPGA. It +is composed of one Andestech(nds32) processor and AE3XX. + +Required properties (in root node): +- compatible = "andestech,ae3xx"; + +Example: +/dts-v1/; +/ { + compatible = "andestech,ae3xx"; + #address-cells = <1>; + #size-cells = <1>; + interrupt-parent = <>; +}; + +Andestech(nds32) AG101P Platform +- +AG101P is a generic SoC Platform IP that works with any of Andestech(nds32) +processors to provide a cost-effective and high performance solution for +majority of embedded systems in variety of application domains. Users may +simply attach their IP on one of the system buses together with certain glue +logics to complete a SoC solution for a specific application. With +comprehensive simulation and design environments, users may evaluate the +system performance of their applications and track bugs of their designs +efficiently. The optional hardware development platform further provides real +system environment for early prototyping and software/hardware co-development. + +Required properties (in root node): + compatible = "andestech,ag101p"; + +Example: +/dts-v1/; +/ { + compatible = "andestech,ag101p"; + #address-cells = <1>; + #size-cells = <1>; + interrupt-parent = <>; +}; -- 1.7.9.5
[PATCH v4 32/36] irqchip: Andestech Internal Vector Interrupt Controller driver
From: Greentime HuThis patch adds the Andestech Internal Vector Interrupt Controller driver. You can find the spec here. Ch4.9 of AndeStar SPA V3 Manual. http://www.andestech.com/product.php?cls=9 Signed-off-by: Rick Chen Signed-off-by: Greentime Hu Reviewed-by: Marc Zyngier --- drivers/irqchip/Makefile |1 + drivers/irqchip/irq-ativic32.c | 107 2 files changed, 108 insertions(+) create mode 100644 drivers/irqchip/irq-ativic32.c diff --git a/drivers/irqchip/Makefile b/drivers/irqchip/Makefile index b842dfd..201ca9f 100644 --- a/drivers/irqchip/Makefile +++ b/drivers/irqchip/Makefile @@ -80,3 +80,4 @@ obj-$(CONFIG_ARCH_ASPEED) += irq-aspeed-vic.o irq-aspeed-i2c-ic.o obj-$(CONFIG_STM32_EXTI) += irq-stm32-exti.o obj-$(CONFIG_QCOM_IRQ_COMBINER)+= qcom-irq-combiner.o obj-$(CONFIG_IRQ_UNIPHIER_AIDET) += irq-uniphier-aidet.o +obj-$(CONFIG_NDS32)+= irq-ativic32.o diff --git a/drivers/irqchip/irq-ativic32.c b/drivers/irqchip/irq-ativic32.c new file mode 100644 index 000..f69a858 --- /dev/null +++ b/drivers/irqchip/irq-ativic32.c @@ -0,0 +1,107 @@ +// SPDX-License-Identifier: GPL-2.0 +// Copyright (C) 2005-2017 Andes Technology Corporation + +#include +#include +#include +#include +#include +#include +#include +#include + +static void ativic32_ack_irq(struct irq_data *data) +{ + __nds32__mtsr_dsb(BIT(data->hwirq), NDS32_SR_INT_PEND2); +} + +static void ativic32_mask_irq(struct irq_data *data) +{ + unsigned long int_mask2 = __nds32__mfsr(NDS32_SR_INT_MASK2); + __nds32__mtsr_dsb(int_mask2 & (~(BIT(data->hwirq))), NDS32_SR_INT_MASK2); +} + +static void ativic32_unmask_irq(struct irq_data *data) +{ + unsigned long int_mask2 = __nds32__mfsr(NDS32_SR_INT_MASK2); + __nds32__mtsr_dsb(int_mask2 | (BIT(data->hwirq)), NDS32_SR_INT_MASK2); +} + +static struct irq_chip ativic32_chip = { + .name = "ativic32", + .irq_ack = ativic32_ack_irq, + .irq_mask = ativic32_mask_irq, + .irq_unmask = ativic32_unmask_irq, +}; + +static unsigned int __initdata nivic_map[6] = { 6, 2, 10, 16, 24, 32 }; + +static struct irq_domain *root_domain; +static int ativic32_irq_domain_map(struct irq_domain *id, unsigned int virq, + irq_hw_number_t hw) +{ + + unsigned long int_trigger_type; + u32 type; + struct irq_data *irq_data; + int_trigger_type = __nds32__mfsr(NDS32_SR_INT_TRIGGER); + irq_data = irq_get_irq_data(virq); + if (!irq_data) + return -EINVAL; + + if (int_trigger_type & (BIT(hw))) { + irq_set_chip_and_handler(virq, _chip, handle_edge_irq); + type = IRQ_TYPE_EDGE_RISING; + } else { + irq_set_chip_and_handler(virq, _chip, handle_level_irq); + type = IRQ_TYPE_LEVEL_HIGH; + } + + irqd_set_trigger_type(irq_data, type); + return 0; +} + +static struct irq_domain_ops ativic32_ops = { + .map = ativic32_irq_domain_map, + .xlate = irq_domain_xlate_onecell +}; + +static irq_hw_number_t get_intr_src(void) +{ + return ((__nds32__mfsr(NDS32_SR_ITYPE) & ITYPE_mskVECTOR) >> ITYPE_offVECTOR) + - NDS32_VECTOR_offINTERRUPT; +} + +asmlinkage void asm_do_IRQ(struct pt_regs *regs) +{ + irq_hw_number_t hwirq = get_intr_src(); + handle_domain_irq(root_domain, hwirq, regs); +} + +int __init ativic32_init_irq(struct device_node *node, struct device_node *parent) +{ + unsigned long int_vec_base, nivic, nr_ints; + + if (WARN(parent, "non-root ativic32 are not supported")) + return -EINVAL; + + int_vec_base = __nds32__mfsr(NDS32_SR_IVB); + + if (((int_vec_base & IVB_mskIVIC_VER) >> IVB_offIVIC_VER) == 0) + panic("Unable to use atcivic32 for this cpu.\n"); + + nivic = (int_vec_base & IVB_mskNIVIC) >> IVB_offNIVIC; + if (nivic >= ARRAY_SIZE(nivic_map)) + panic("The number of input for ativic32 is not supported.\n"); + + nr_ints = nivic_map[nivic]; + + root_domain = irq_domain_add_linear(node, nr_ints, + _ops, NULL); + + if (!root_domain) + panic("%s: unable to create IRQ domain\n", node->full_name); + + return 0; +} +IRQCHIP_DECLARE(ativic32, "andestech,ativic32", ativic32_init_irq); -- 1.7.9.5
[PATCH v4 32/36] irqchip: Andestech Internal Vector Interrupt Controller driver
From: Greentime Hu This patch adds the Andestech Internal Vector Interrupt Controller driver. You can find the spec here. Ch4.9 of AndeStar SPA V3 Manual. http://www.andestech.com/product.php?cls=9 Signed-off-by: Rick Chen Signed-off-by: Greentime Hu Reviewed-by: Marc Zyngier --- drivers/irqchip/Makefile |1 + drivers/irqchip/irq-ativic32.c | 107 2 files changed, 108 insertions(+) create mode 100644 drivers/irqchip/irq-ativic32.c diff --git a/drivers/irqchip/Makefile b/drivers/irqchip/Makefile index b842dfd..201ca9f 100644 --- a/drivers/irqchip/Makefile +++ b/drivers/irqchip/Makefile @@ -80,3 +80,4 @@ obj-$(CONFIG_ARCH_ASPEED) += irq-aspeed-vic.o irq-aspeed-i2c-ic.o obj-$(CONFIG_STM32_EXTI) += irq-stm32-exti.o obj-$(CONFIG_QCOM_IRQ_COMBINER)+= qcom-irq-combiner.o obj-$(CONFIG_IRQ_UNIPHIER_AIDET) += irq-uniphier-aidet.o +obj-$(CONFIG_NDS32)+= irq-ativic32.o diff --git a/drivers/irqchip/irq-ativic32.c b/drivers/irqchip/irq-ativic32.c new file mode 100644 index 000..f69a858 --- /dev/null +++ b/drivers/irqchip/irq-ativic32.c @@ -0,0 +1,107 @@ +// SPDX-License-Identifier: GPL-2.0 +// Copyright (C) 2005-2017 Andes Technology Corporation + +#include +#include +#include +#include +#include +#include +#include +#include + +static void ativic32_ack_irq(struct irq_data *data) +{ + __nds32__mtsr_dsb(BIT(data->hwirq), NDS32_SR_INT_PEND2); +} + +static void ativic32_mask_irq(struct irq_data *data) +{ + unsigned long int_mask2 = __nds32__mfsr(NDS32_SR_INT_MASK2); + __nds32__mtsr_dsb(int_mask2 & (~(BIT(data->hwirq))), NDS32_SR_INT_MASK2); +} + +static void ativic32_unmask_irq(struct irq_data *data) +{ + unsigned long int_mask2 = __nds32__mfsr(NDS32_SR_INT_MASK2); + __nds32__mtsr_dsb(int_mask2 | (BIT(data->hwirq)), NDS32_SR_INT_MASK2); +} + +static struct irq_chip ativic32_chip = { + .name = "ativic32", + .irq_ack = ativic32_ack_irq, + .irq_mask = ativic32_mask_irq, + .irq_unmask = ativic32_unmask_irq, +}; + +static unsigned int __initdata nivic_map[6] = { 6, 2, 10, 16, 24, 32 }; + +static struct irq_domain *root_domain; +static int ativic32_irq_domain_map(struct irq_domain *id, unsigned int virq, + irq_hw_number_t hw) +{ + + unsigned long int_trigger_type; + u32 type; + struct irq_data *irq_data; + int_trigger_type = __nds32__mfsr(NDS32_SR_INT_TRIGGER); + irq_data = irq_get_irq_data(virq); + if (!irq_data) + return -EINVAL; + + if (int_trigger_type & (BIT(hw))) { + irq_set_chip_and_handler(virq, _chip, handle_edge_irq); + type = IRQ_TYPE_EDGE_RISING; + } else { + irq_set_chip_and_handler(virq, _chip, handle_level_irq); + type = IRQ_TYPE_LEVEL_HIGH; + } + + irqd_set_trigger_type(irq_data, type); + return 0; +} + +static struct irq_domain_ops ativic32_ops = { + .map = ativic32_irq_domain_map, + .xlate = irq_domain_xlate_onecell +}; + +static irq_hw_number_t get_intr_src(void) +{ + return ((__nds32__mfsr(NDS32_SR_ITYPE) & ITYPE_mskVECTOR) >> ITYPE_offVECTOR) + - NDS32_VECTOR_offINTERRUPT; +} + +asmlinkage void asm_do_IRQ(struct pt_regs *regs) +{ + irq_hw_number_t hwirq = get_intr_src(); + handle_domain_irq(root_domain, hwirq, regs); +} + +int __init ativic32_init_irq(struct device_node *node, struct device_node *parent) +{ + unsigned long int_vec_base, nivic, nr_ints; + + if (WARN(parent, "non-root ativic32 are not supported")) + return -EINVAL; + + int_vec_base = __nds32__mfsr(NDS32_SR_IVB); + + if (((int_vec_base & IVB_mskIVIC_VER) >> IVB_offIVIC_VER) == 0) + panic("Unable to use atcivic32 for this cpu.\n"); + + nivic = (int_vec_base & IVB_mskNIVIC) >> IVB_offNIVIC; + if (nivic >= ARRAY_SIZE(nivic_map)) + panic("The number of input for ativic32 is not supported.\n"); + + nr_ints = nivic_map[nivic]; + + root_domain = irq_domain_add_linear(node, nr_ints, + _ops, NULL); + + if (!root_domain) + panic("%s: unable to create IRQ domain\n", node->full_name); + + return 0; +} +IRQCHIP_DECLARE(ativic32, "andestech,ativic32", ativic32_init_irq); -- 1.7.9.5