Gitweb:     
http://git.kernel.org/git/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commit;h=59579da329b22bcddc5da0c22c61d6dc1f9eb96a
Commit:     59579da329b22bcddc5da0c22c61d6dc1f9eb96a
Parent:     d8fae9c2f2642ffe411424ed2e4677f959168152
Author:     Klaus D. Wacker <[EMAIL PROTECTED]>
AuthorDate: Fri Oct 5 16:45:47 2007 +0200
Committer:  David S. Miller <[EMAIL PROTECTED]>
CommitDate: Wed Oct 10 16:54:41 2007 -0700

    lcs: Channel errors drive lcs_recovery which leads to kernel panic.
    
    When the lcs irq routine detects channel failures it drives device recovery.
    After this event the device is no longer usable for shutdown requests,
    because the lcs_irq routine may get wrong channel status information.
    In such a case the lcs_irq routine marks the channel in 'error' state.
    The channel state comes back to 'running' after restarting the channels.
    
    Signed-off-by: Klaus D. Wacker <[EMAIL PROTECTED]>
    Signed-off-by: Ursula Braun <[EMAIL PROTECTED]>
    Signed-off-by: Jeff Garzik <[EMAIL PROTECTED]>
---
 drivers/s390/net/lcs.c |   11 ++++++++---
 drivers/s390/net/lcs.h |    1 +
 2 files changed, 9 insertions(+), 3 deletions(-)

diff --git a/drivers/s390/net/lcs.c b/drivers/s390/net/lcs.c
index e4b11af..0fd663b 100644
--- a/drivers/s390/net/lcs.c
+++ b/drivers/s390/net/lcs.c
@@ -1400,11 +1400,14 @@ lcs_irq(struct ccw_device *cdev, unsigned long intparm, 
struct irb *irb)
                PRINT_WARN("check on device %s, dstat=0x%X, cstat=0x%X \n",
                            cdev->dev.bus_id, dstat, cstat);
                if (rc) {
-                       lcs_schedule_recovery(card);
-                       wake_up(&card->wait_q);
-                       return;
+                       channel->state = LCS_CH_STATE_ERROR;
                }
        }
+       if (channel->state == LCS_CH_STATE_ERROR) {
+               lcs_schedule_recovery(card);
+               wake_up(&card->wait_q);
+               return;
+       }
        /* How far in the ccw chain have we processed? */
        if ((channel->state != LCS_CH_STATE_INIT) &&
            (irb->scsw.fctl & SCSW_FCTL_START_FUNC)) {
@@ -1708,6 +1711,8 @@ lcs_stopcard(struct lcs_card *card)
 
        if (card->read.state != LCS_CH_STATE_STOPPED &&
            card->write.state != LCS_CH_STATE_STOPPED &&
+           card->read.state != LCS_CH_STATE_ERROR &&
+           card->write.state != LCS_CH_STATE_ERROR &&
            card->state == DEV_STATE_UP) {
                lcs_clear_multicast_list(card);
                rc = lcs_send_stoplan(card,LCS_INITIATOR_TCPIP);
diff --git a/drivers/s390/net/lcs.h b/drivers/s390/net/lcs.h
index 0e1e4a0..8976fb0 100644
--- a/drivers/s390/net/lcs.h
+++ b/drivers/s390/net/lcs.h
@@ -138,6 +138,7 @@ enum lcs_channel_states {
        LCS_CH_STATE_RUNNING,
        LCS_CH_STATE_SUSPENDED,
        LCS_CH_STATE_CLEARED,
+       LCS_CH_STATE_ERROR,
 };
 
 /**
-
To unsubscribe from this list: send the line "unsubscribe git-commits-head" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to