fpga: region: Move spinlock for bridge_list into region
Moritz Fischer
maintainerRFC 1/1 fpga: region: Move spinlock for bridge_list into region
Instead of using a single (global) spinlock for all bridge lists use a spinlock per list inside the containing fpga region.
---
Hi all,
maybe I do misunderstand something fundamental here ;-) In that case, please explain. In my understanding the current version works, because it is more defensive, but is there a reason we need to make access to any of the bridge lists exclusive?
Cheers,
Moritz
PS: Not fully happy with this patch, but wanted to figure out first if this I'm wrong conceptually
--- drivers/fpga/fpga-bridge.c | 5 ++--- drivers/fpga/fpga-region.c | 6 ++++++ 2 files changed, 8 insertions(+), 3 deletions(-)
drivers/fpga/fpga-bridge.c +2 -3
@@ -214,6 +214,8 @@ EXPORT_SYMBOL_GPL(fpga_bridges_put);* * Get an exclusive reference to the bridge and and it to the list. * +* Must be called with list lock held. +* * Return 0 for success, error code from of_fpga_bridge_get() othewise. */ int fpga_bridge_get_to_list(struct device_node *np,
@@ -221,15 +223,12 @@ int fpga_bridge_get_to_list(struct device_node *np, struct list_head *bridge_list) {struct fpga_bridge *bridge; -unsigned long flags; bridge =of_fpga_bridge_get (np, info);if (IS_ERR (bridge))return PTR_ERR (bridge); -spin_lock_irqsave (&bridge_list_lock, flags);list_add (&bridge->node, bridge_list); -spin_unlock_irqrestore (&bridge_list_lock, flags);return 0 ; }
drivers/fpga/fpga-region.c +6 -0
@@ -37,6 +37,7 @@ struct fpga_region {struct device dev;struct mutex mutex;/* for exclusive reference to region */ struct list_head bridge_list; +spinlock_t bridge_list_lock;/* protects access to bridge list */ struct fpga_image_info *info; };
@@ -180,11 +181,15 @@ static int fpga_region_get_bridges(struct fpga_region *region,struct device *dev = ®ion->dev;struct device_node *region_np = dev->of_node;struct device_node *br, *np, *parent_br =NULL ; +unsigned long flags;int i, ret;/* If parent is a bridge, add to list */ +spin_lock_irqsave (®ion->bridge_list_lock, flags); ret =fpga_bridge_get_to_list (region_np->parent, region->info, ®ion->bridge_list); +spin_unlock_irqrestore (®ion->bridge_list_lock, flags); +if (ret == -EBUSY )return ret;
@@ -508,6 +513,7 @@ static int fpga_region_probe(struct platform_device *pdev)mutex_init (®ion->mutex);INIT_LIST_HEAD (®ion->bridge_list); +spin_lock_init (®ion->bridge_list_lock);device_initialize (®ion->dev); region->dev.class = fpga_region_class;
Signature · 1 line
2.14.1
On Mon, Sep 18, 2017 at 3:34 PM, Moritz Fischer <[email protected]> wrote:
Hi Moritz,
Quoted 4 lines
Instead of using a single (global) spinlock for all bridge lists use a spinlock per list inside the containing fpga region.
Signed-off-by Moritz Fischer <[email protected]>
Quoted 8 lines
---
Hi all,
maybe I do misunderstand something fundamental here ;-) In that case, please explain. In my understanding the current version works, because it is more defensive, but is there a reason we need to make access to any of the bridge lists exclusive?
I think you are basically right here. Moving the spinlock to the region is correct. When you do your final version of this, could you just have it apply on top of this current patchset? That will save me a lot of rebasing.
Alan
Quoted 80 lines
Cheers,
MoritzPS: Not fully happy with this patch, but wanted to figure out first if this I'm wrong conceptually
--- drivers/fpga/fpga-bridge.c | 5 ++--- drivers/fpga/fpga-region.c | 6 ++++++ 2 files changed, 8 insertions(+), 3 deletions(-)drivers/fpga/fpga-bridge.c +2
-3@@ -214,6 +214,8 @@ EXPORT_SYMBOL_GPL(fpga_bridges_put);* * Get an exclusive reference to the bridge and and it to the list. * +* Must be called with list lock held. +* * Return 0 for success, error code from of_fpga_bridge_get() othewise. */ int fpga_bridge_get_to_list(struct device_node *np,@@ -221,15 +223,12 @@ int fpga_bridge_get_to_list(struct device_node *np, struct list_head *bridge_list) {struct fpga_bridge *bridge; -unsigned long flags; bridge =of_fpga_bridge_get (np, info);if (IS_ERR (bridge))return PTR_ERR (bridge); -spin_lock_irqsave (&bridge_list_lock, flags);list_add (&bridge->node, bridge_list); -spin_unlock_irqrestore (&bridge_list_lock, flags);return 0 ; }drivers/fpga/fpga-region.c +6
-1@@ -37,6 +37,7 @@ struct fpga_region {struct device dev;struct mutex mutex;/* for exclusive reference to region */ struct list_head bridge_list; +spinlock_t bridge_list_lock;/* protects access to bridge list */ struct fpga_image_info *info; };@@ -180,11 +181,15 @@ static int fpga_region_get_bridges(struct fpga_region *region,struct device *dev = ®ion->dev;struct device_node *region_np = dev->of_node;struct device_node *br, *np, *parent_br =NULL ; +unsigned long flags;int i, ret;/* If parent is a bridge, add to list */ +spin_lock_irqsave (®ion->bridge_list_lock, flags); ret =fpga_bridge_get_to_list (region_np->parent, region->info, ®ion->bridge_list); +spin_unlock_irqrestore (®ion->bridge_list_lock, flags); +if (ret == -EBUSY )return ret;@@ -508,6 +513,7 @@ static int fpga_region_probe(struct platform_device *pdev)mutex_init (®ion->mutex);INIT_LIST_HEAD (®ion->bridge_list); +spin_lock_init (®ion->bridge_list_lock);device_initialize (®ion->dev); region->dev.class = fpga_region_class; --2.14.1
Moritz Fischer
maintainerQuoted 17 lines · Alan Tull
On Mon, Sep 18, 2017 at 3:34 PM, Moritz Fischer <[email protected]> wrote:
Hi Moritz,
Quoted 4 lines
Instead of using a single (global) spinlock for all bridge lists use a spinlock per list inside the containing fpga region.
Signed-off-by Moritz Fischer <[email protected]>Quoted 8 lines
---
Hi all,
maybe I do misunderstand something fundamental here ;-) In that case, please explain. In my understanding the current version works, because it is more defensive, but is there a reason we need to make access to any of the bridge lists exclusive?
Quoted 4 lines
I think you are basically right here. Moving the spinlock to the region is correct. When you do your final version of this, could you just have it apply on top of this current patchset? That will save me a lot of rebasing.
Yeah can resubmit on top of your current series if you prefer that.
Moritz
Quoted 83 lines
Alan
Quoted 80 lines
Cheers,
MoritzPS: Not fully happy with this patch, but wanted to figure out first if this I'm wrong conceptually
--- drivers/fpga/fpga-bridge.c | 5 ++--- drivers/fpga/fpga-region.c | 6 ++++++ 2 files changed, 8 insertions(+), 3 deletions(-)drivers/fpga/fpga-bridge.c +2
-3@@ -214,6 +214,8 @@ EXPORT_SYMBOL_GPL(fpga_bridges_put);* * Get an exclusive reference to the bridge and and it to the list. * +* Must be called with list lock held. +* * Return 0 for success, error code from of_fpga_bridge_get() othewise. */ int fpga_bridge_get_to_list(struct device_node *np,@@ -221,15 +223,12 @@ int fpga_bridge_get_to_list(struct device_node *np, struct list_head *bridge_list) {struct fpga_bridge *bridge; -unsigned long flags; bridge =of_fpga_bridge_get (np, info);if (IS_ERR (bridge))return PTR_ERR (bridge); -spin_lock_irqsave (&bridge_list_lock, flags);list_add (&bridge->node, bridge_list); -spin_unlock_irqrestore (&bridge_list_lock, flags);return 0 ; }drivers/fpga/fpga-region.c +6
-1@@ -37,6 +37,7 @@ struct fpga_region {struct device dev;struct mutex mutex;/* for exclusive reference to region */ struct list_head bridge_list; +spinlock_t bridge_list_lock;/* protects access to bridge list */ struct fpga_image_info *info; };@@ -180,11 +181,15 @@ static int fpga_region_get_bridges(struct fpga_region *region,struct device *dev = ®ion->dev;struct device_node *region_np = dev->of_node;struct device_node *br, *np, *parent_br =NULL ; +unsigned long flags;int i, ret;/* If parent is a bridge, add to list */ +spin_lock_irqsave (®ion->bridge_list_lock, flags); ret =fpga_bridge_get_to_list (region_np->parent, region->info, ®ion->bridge_list); +spin_unlock_irqrestore (®ion->bridge_list_lock, flags); +if (ret == -EBUSY )return ret;@@ -508,6 +513,7 @@ static int fpga_region_probe(struct platform_device *pdev)mutex_init (®ion->mutex);INIT_LIST_HEAD (®ion->bridge_list); +spin_lock_init (®ion->bridge_list_lock);device_initialize (®ion->dev); region->dev.class = fpga_region_class; --2.14.1