[PATCH] net/ncsi: Reset state fixes, single-channel LSC

From: Samuel Mendoza-Jonas
Date: Thu Nov 08 2018 - 21:11:03 EST


---
net/ncsi/ncsi-aen.c | 8 +++++---
net/ncsi/ncsi-manage.c | 19 +++++++++++++++----
2 files changed, 20 insertions(+), 7 deletions(-)

diff --git a/net/ncsi/ncsi-aen.c b/net/ncsi/ncsi-aen.c
index 39c2e9eea2ba..034cb1dc5566 100644
--- a/net/ncsi/ncsi-aen.c
+++ b/net/ncsi/ncsi-aen.c
@@ -93,14 +93,16 @@ static int ncsi_aen_handler_lsc(struct ncsi_dev_priv *ndp,
if ((had_link == has_link) || chained)
return 0;

- if (!ndp->multi_package && !nc->package->multi_channel) {
- if (had_link)
- ndp->flags |= NCSI_DEV_RESHUFFLE;
+ if (!ndp->multi_package && !nc->package->multi_channel && had_link) {
+ ndp->flags |= NCSI_DEV_RESHUFFLE;
ncsi_stop_channel_monitor(nc);
spin_lock_irqsave(&ndp->lock, flags);
list_add_tail_rcu(&nc->link, &ndp->channel_queue);
spin_unlock_irqrestore(&ndp->lock, flags);
return ncsi_process_next_channel(ndp);
+ } else {
+ /* Configured channel came up */
+ return 0;
}

if (had_link) {
diff --git a/net/ncsi/ncsi-manage.c b/net/ncsi/ncsi-manage.c
index fa3c2144f5ba..92e59f07f9a7 100644
--- a/net/ncsi/ncsi-manage.c
+++ b/net/ncsi/ncsi-manage.c
@@ -1063,17 +1063,17 @@ static void ncsi_configure_channel(struct ncsi_dev_priv *ndp)
case ncsi_dev_state_config_done:
netdev_dbg(ndp->ndev.dev, "NCSI: channel %u config done\n",
nc->id);
+ spin_lock_irqsave(&nc->lock, flags);
+ nc->state = NCSI_CHANNEL_ACTIVE;
+
if (ndp->flags & NCSI_DEV_RESET) {
/* A reset event happened during config, start it now */
- spin_lock_irqsave(&nc->lock, flags);
nc->reconfigure_needed = false;
spin_unlock_irqrestore(&nc->lock, flags);
- nd->state = ncsi_dev_state_functional;
ncsi_reset_dev(nd);
break;
}

- spin_lock_irqsave(&nc->lock, flags);
if (nc->reconfigure_needed) {
/* This channel's configuration has been updated
* part-way during the config state - start the
@@ -1092,7 +1092,6 @@ static void ncsi_configure_channel(struct ncsi_dev_priv *ndp)
break;
}

- nc->state = NCSI_CHANNEL_ACTIVE;
if (nc->modes[NCSI_MODE_LINK].data[2] & 0x1) {
hot_nc = nc;
} else {
@@ -1803,6 +1802,18 @@ int ncsi_reset_dev(struct ncsi_dev *nd)
spin_unlock_irqrestore(&ndp->lock, flags);
return 0;
}
+ } else {
+ switch (nd->state) {
+ case ncsi_dev_state_suspend_done:
+ case ncsi_dev_state_config_done:
+ case ncsi_dev_state_functional:
+ /* Ok */
+ break;
+ default:
+ /* Current reset operation happening */
+ spin_unlock_irqrestore(&ndp->lock, flags);
+ return 0;
+ }
}

if (!list_empty(&ndp->channel_queue)) {
--
2.19.1