From fd2f09689d2f6b519b477ed5412c6f01bf0d5d62 Mon Sep 17 00:00:00 2001 From: Michael Ellerman Date: Thu, 1 Sep 2005 11:29:00 +1000 Subject: [PATCH] --- yaml --- r: 6682 b: refs/heads/master c: 58c5900bdaffbf76afd7ad5e053410cb95eb3169 h: refs/heads/master v: v3 --- [refs] | 2 +- trunk/drivers/net/iseries_veth.c | 25 +++++++++++++++++++++++-- 2 files changed, 24 insertions(+), 3 deletions(-) diff --git a/[refs] b/[refs] index b9a6c41d961a..0a2770a142d6 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: abfda4719c61550be4efaf277d4a904a7930d410 +refs/heads/master: 58c5900bdaffbf76afd7ad5e053410cb95eb3169 diff --git a/trunk/drivers/net/iseries_veth.c b/trunk/drivers/net/iseries_veth.c index c19b32e0a5ad..db83b0d31327 100644 --- a/trunk/drivers/net/iseries_veth.c +++ b/trunk/drivers/net/iseries_veth.c @@ -324,8 +324,14 @@ static void veth_take_monitor_ack(struct veth_lpar_connection *cnx, spin_lock_irqsave(&cnx->lock, flags); veth_debug("cnx %d: lost connection.\n", cnx->remote_lp); - cnx->state |= VETH_STATE_RESET; - veth_kick_statemachine(cnx); + + /* Avoid kicking the statemachine once we're shutdown. + * It's unnecessary and it could break veth_stop_connection(). */ + + if (! (cnx->state & VETH_STATE_SHUTDOWN)) { + cnx->state |= VETH_STATE_RESET; + veth_kick_statemachine(cnx); + } spin_unlock_irqrestore(&cnx->lock, flags); } @@ -483,6 +489,12 @@ static void veth_statemachine(void *p) if (cnx->state & VETH_STATE_RESET) goto restart; + + /* Hack, wait for the other end to reset itself. */ + if (! (cnx->state & VETH_STATE_SHUTDOWN)) { + schedule_delayed_work(&cnx->statemachine_wq, 5 * HZ); + goto out; + } } if (cnx->state & VETH_STATE_SHUTDOWN) @@ -667,6 +679,15 @@ static void veth_stop_connection(u8 rlp) veth_kick_statemachine(cnx); spin_unlock_irq(&cnx->lock); + /* There's a slim chance the reset code has just queued the + * statemachine to run in five seconds. If so we need to cancel + * that and requeue the work to run now. */ + if (cancel_delayed_work(&cnx->statemachine_wq)) { + spin_lock_irq(&cnx->lock); + veth_kick_statemachine(cnx); + spin_unlock_irq(&cnx->lock); + } + /* Wait for the state machine to run. */ flush_scheduled_work();