summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRussell King <rmk+kernel@armlinux.org.uk>2017-05-09 16:43:35 +0100
committerRussell King <rmk+kernel@armlinux.org.uk>2017-05-09 18:08:27 +0100
commitb782030fcf3e0fd790f0972a439d4431a2fa0224 (patch)
treec2587d0c11fb65726088fc49c7a8fc135d06b806
parent2546b8933d66fdec4ece43606d46f395b6e550e3 (diff)
sfp: hold the rtnetlink lock while calling phylink
Hold the rtnetlink lock while causing phylink to prevent changes to the networking configuration. This will allow us to eliminate the configuration locking in phylink, and thus simplify the locking strategy. This will also allow phylink to attach the phy directly to the net device, so allowing a reduction in veneer code. Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk>
-rw-r--r--drivers/net/phy/sfp.c9
1 files changed, 9 insertions, 0 deletions
diff --git a/drivers/net/phy/sfp.c b/drivers/net/phy/sfp.c
index 294f59e140b0..e8ab34879a96 100644
--- a/drivers/net/phy/sfp.c
+++ b/drivers/net/phy/sfp.c
@@ -10,6 +10,7 @@
#include <linux/of_net.h>
#include <linux/phylink.h>
#include <linux/platform_device.h>
+#include <linux/rtnetlink.h>
#include <linux/sfp.h>
#include <linux/slab.h>
#include <linux/workqueue.h>
@@ -1045,7 +1046,9 @@ static void sfp_timeout(struct work_struct *work)
{
struct sfp *sfp = container_of(work, struct sfp, timeout.work);
+ rtnl_lock();
sfp_sm_event(sfp, SFP_E_TIMEOUT);
+ rtnl_unlock();
}
static void sfp_check_state(struct sfp *sfp)
@@ -1064,6 +1067,7 @@ static void sfp_check_state(struct sfp *sfp)
state |= sfp->state & (SFP_F_TX_DISABLE | SFP_F_RATE_SELECT);
sfp->state = state;
+ rtnl_lock();
if (changed & SFP_F_PRESENT)
sfp_sm_event(sfp, state & SFP_F_PRESENT ?
SFP_E_INSERT : SFP_E_REMOVE);
@@ -1075,6 +1079,7 @@ static void sfp_check_state(struct sfp *sfp)
if (changed & SFP_F_LOS)
sfp_sm_event(sfp, state & SFP_F_LOS ?
SFP_E_LOS_HIGH : SFP_E_LOS_LOW);
+ rtnl_unlock();
}
static irqreturn_t sfp_irq(int irq, void *data)
@@ -1232,8 +1237,10 @@ static int sfp_probe(struct platform_device *pdev)
return -EPROBE_DEFER;
}
+ rtnl_lock();
phylink_disable(sfp->phylink);
phylink_register_module(sfp->phylink, sfp, &sfp_module_ops);
+ rtnl_unlock();
}
/* Get the initial state, and always signal TX disable,
@@ -1246,8 +1253,10 @@ static int sfp_probe(struct platform_device *pdev)
sfp->state |= SFP_F_RATE_SELECT;
sfp_set_state(sfp, sfp->state);
sfp_module_tx_disable(sfp);
+ rtnl_lock();
if (sfp->state & SFP_F_PRESENT)
sfp_sm_event(sfp, SFP_E_INSERT);
+ rtnl_unlock();
for (i = 0; i < GPIO_MAX; i++) {
if (gpio_flags[i] != GPIOD_IN || !sfp->gpio[i])