mirror of https://github.com/hak5/openwrt.git
154 lines
4.4 KiB
Diff
154 lines
4.4 KiB
Diff
From ec6036a58f979c66bbd5cd9d0d1c783a98c2c644 Mon Sep 17 00:00:00 2001
|
|
From: Russell King <rmk+kernel@armlinux.org.uk>
|
|
Date: Tue, 5 Nov 2019 12:57:40 +0000
|
|
Subject: [PATCH 630/660] net: sfp: track upstream's attachment state in state
|
|
machine
|
|
|
|
Track the upstream's attachment state in the state machine rather than
|
|
maintaining a boolean, which ensures that we have a strict order of
|
|
ATTACH followed by an UP event - we can never believe that a newly
|
|
attached upstream will be anything but down.
|
|
|
|
Rearrange the order of state machines so we run the module state
|
|
machine after the upstream device's state machine, so the module state
|
|
machine can check the current state of the device and take action to
|
|
e.g. reset back to empty state when the upstream is detached.
|
|
|
|
This is to allow the module detection to run independently of the
|
|
network device becoming available.
|
|
|
|
Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk>
|
|
---
|
|
drivers/net/phy/sfp.c | 42 +++++++++++++++++++++++++++++-------------
|
|
1 file changed, 29 insertions(+), 13 deletions(-)
|
|
|
|
--- a/drivers/net/phy/sfp.c
|
|
+++ b/drivers/net/phy/sfp.c
|
|
@@ -36,6 +36,8 @@ enum {
|
|
|
|
SFP_E_INSERT = 0,
|
|
SFP_E_REMOVE,
|
|
+ SFP_E_DEV_ATTACH,
|
|
+ SFP_E_DEV_DETACH,
|
|
SFP_E_DEV_DOWN,
|
|
SFP_E_DEV_UP,
|
|
SFP_E_TX_FAULT,
|
|
@@ -50,7 +52,8 @@ enum {
|
|
SFP_MOD_PRESENT,
|
|
SFP_MOD_ERROR,
|
|
|
|
- SFP_DEV_DOWN = 0,
|
|
+ SFP_DEV_DETACHED = 0,
|
|
+ SFP_DEV_DOWN,
|
|
SFP_DEV_UP,
|
|
|
|
SFP_S_DOWN = 0,
|
|
@@ -80,6 +83,7 @@ static const char *mod_state_to_str(unsi
|
|
}
|
|
|
|
static const char * const dev_state_strings[] = {
|
|
+ [SFP_DEV_DETACHED] = "detached",
|
|
[SFP_DEV_DOWN] = "down",
|
|
[SFP_DEV_UP] = "up",
|
|
};
|
|
@@ -94,6 +98,8 @@ static const char *dev_state_to_str(unsi
|
|
static const char * const event_strings[] = {
|
|
[SFP_E_INSERT] = "insert",
|
|
[SFP_E_REMOVE] = "remove",
|
|
+ [SFP_E_DEV_ATTACH] = "dev_attach",
|
|
+ [SFP_E_DEV_DETACH] = "dev_detach",
|
|
[SFP_E_DEV_DOWN] = "dev_down",
|
|
[SFP_E_DEV_UP] = "dev_up",
|
|
[SFP_E_TX_FAULT] = "tx_fault",
|
|
@@ -188,7 +194,6 @@ struct sfp {
|
|
struct gpio_desc *gpio[GPIO_MAX];
|
|
int gpio_irq[GPIO_MAX];
|
|
|
|
- bool attached;
|
|
struct mutex st_mutex; /* Protects state */
|
|
unsigned int state;
|
|
struct delayed_work poll;
|
|
@@ -1559,17 +1564,26 @@ static void sfp_sm_mod_remove(struct sfp
|
|
dev_info(sfp->dev, "module removed\n");
|
|
}
|
|
|
|
-/* This state machine tracks the netdev up/down state */
|
|
+/* This state machine tracks the upstream's state */
|
|
static void sfp_sm_device(struct sfp *sfp, unsigned int event)
|
|
{
|
|
switch (sfp->sm_dev_state) {
|
|
default:
|
|
- if (event == SFP_E_DEV_UP)
|
|
+ if (event == SFP_E_DEV_ATTACH)
|
|
+ sfp->sm_dev_state = SFP_DEV_DOWN;
|
|
+ break;
|
|
+
|
|
+ case SFP_DEV_DOWN:
|
|
+ if (event == SFP_E_DEV_DETACH)
|
|
+ sfp->sm_dev_state = SFP_DEV_DETACHED;
|
|
+ else if (event == SFP_E_DEV_UP)
|
|
sfp->sm_dev_state = SFP_DEV_UP;
|
|
break;
|
|
|
|
case SFP_DEV_UP:
|
|
- if (event == SFP_E_DEV_DOWN)
|
|
+ if (event == SFP_E_DEV_DETACH)
|
|
+ sfp->sm_dev_state = SFP_DEV_DETACHED;
|
|
+ else if (event == SFP_E_DEV_DOWN)
|
|
sfp->sm_dev_state = SFP_DEV_DOWN;
|
|
break;
|
|
}
|
|
@@ -1580,17 +1594,20 @@ static void sfp_sm_device(struct sfp *sf
|
|
*/
|
|
static void sfp_sm_module(struct sfp *sfp, unsigned int event)
|
|
{
|
|
- /* Handle remove event globally, it resets this state machine */
|
|
- if (event == SFP_E_REMOVE) {
|
|
+ /* Handle remove event globally, it resets this state machine.
|
|
+ * Also deal with upstream detachment.
|
|
+ */
|
|
+ if (event == SFP_E_REMOVE || sfp->sm_dev_state < SFP_DEV_DOWN) {
|
|
if (sfp->sm_mod_state > SFP_MOD_PROBE)
|
|
sfp_sm_mod_remove(sfp);
|
|
- sfp_sm_mod_next(sfp, SFP_MOD_EMPTY, 0);
|
|
+ if (sfp->sm_mod_state != SFP_MOD_EMPTY)
|
|
+ sfp_sm_mod_next(sfp, SFP_MOD_EMPTY, 0);
|
|
return;
|
|
}
|
|
|
|
switch (sfp->sm_mod_state) {
|
|
default:
|
|
- if (event == SFP_E_INSERT && sfp->attached)
|
|
+ if (event == SFP_E_INSERT)
|
|
sfp_sm_mod_next(sfp, SFP_MOD_PROBE, T_SERIAL);
|
|
break;
|
|
|
|
@@ -1756,8 +1773,8 @@ static void sfp_sm_event(struct sfp *sfp
|
|
sm_state_to_str(sfp->sm_state),
|
|
event_to_str(event));
|
|
|
|
- sfp_sm_module(sfp, event);
|
|
sfp_sm_device(sfp, event);
|
|
+ sfp_sm_module(sfp, event);
|
|
sfp_sm_main(sfp, event);
|
|
|
|
dev_dbg(sfp->dev, "SM: exit %s:%s:%s\n",
|
|
@@ -1770,15 +1787,14 @@ static void sfp_sm_event(struct sfp *sfp
|
|
|
|
static void sfp_attach(struct sfp *sfp)
|
|
{
|
|
- sfp->attached = true;
|
|
+ sfp_sm_event(sfp, SFP_E_DEV_ATTACH);
|
|
if (sfp->state & SFP_F_PRESENT)
|
|
sfp_sm_event(sfp, SFP_E_INSERT);
|
|
}
|
|
|
|
static void sfp_detach(struct sfp *sfp)
|
|
{
|
|
- sfp->attached = false;
|
|
- sfp_sm_event(sfp, SFP_E_REMOVE);
|
|
+ sfp_sm_event(sfp, SFP_E_DEV_DETACH);
|
|
}
|
|
|
|
static void sfp_start(struct sfp *sfp)
|