aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorKlaus D. Wacker <kdwacker@de.ibm.com>2007-10-05 10:45:47 -0400
committerDavid S. Miller <davem@sunset.davemloft.net>2007-10-10 19:54:41 -0400
commit59579da329b22bcddc5da0c22c61d6dc1f9eb96a (patch)
tree117eb93c9d50643a633018481ed68fc84063519d /drivers
parentd8fae9c2f2642ffe411424ed2e4677f959168152 (diff)
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 <kdwacker@de.ibm.com> Signed-off-by: Ursula Braun <braunu@de.ibm.com> Signed-off-by: Jeff Garzik <jeff@garzik.org>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/s390/net/lcs.c11
-rw-r--r--drivers/s390/net/lcs.h1
2 files changed, 9 insertions, 3 deletions
diff --git a/drivers/s390/net/lcs.c b/drivers/s390/net/lcs.c
index e4b11afbbc9f..0fd663b23d76 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)
1400 PRINT_WARN("check on device %s, dstat=0x%X, cstat=0x%X \n", 1400 PRINT_WARN("check on device %s, dstat=0x%X, cstat=0x%X \n",
1401 cdev->dev.bus_id, dstat, cstat); 1401 cdev->dev.bus_id, dstat, cstat);
1402 if (rc) { 1402 if (rc) {
1403 lcs_schedule_recovery(card); 1403 channel->state = LCS_CH_STATE_ERROR;
1404 wake_up(&card->wait_q);
1405 return;
1406 } 1404 }
1407 } 1405 }
1406 if (channel->state == LCS_CH_STATE_ERROR) {
1407 lcs_schedule_recovery(card);
1408 wake_up(&card->wait_q);
1409 return;
1410 }
1408 /* How far in the ccw chain have we processed? */ 1411 /* How far in the ccw chain have we processed? */
1409 if ((channel->state != LCS_CH_STATE_INIT) && 1412 if ((channel->state != LCS_CH_STATE_INIT) &&
1410 (irb->scsw.fctl & SCSW_FCTL_START_FUNC)) { 1413 (irb->scsw.fctl & SCSW_FCTL_START_FUNC)) {
@@ -1708,6 +1711,8 @@ lcs_stopcard(struct lcs_card *card)
1708 1711
1709 if (card->read.state != LCS_CH_STATE_STOPPED && 1712 if (card->read.state != LCS_CH_STATE_STOPPED &&
1710 card->write.state != LCS_CH_STATE_STOPPED && 1713 card->write.state != LCS_CH_STATE_STOPPED &&
1714 card->read.state != LCS_CH_STATE_ERROR &&
1715 card->write.state != LCS_CH_STATE_ERROR &&
1711 card->state == DEV_STATE_UP) { 1716 card->state == DEV_STATE_UP) {
1712 lcs_clear_multicast_list(card); 1717 lcs_clear_multicast_list(card);
1713 rc = lcs_send_stoplan(card,LCS_INITIATOR_TCPIP); 1718 rc = lcs_send_stoplan(card,LCS_INITIATOR_TCPIP);
diff --git a/drivers/s390/net/lcs.h b/drivers/s390/net/lcs.h
index 0e1e4a0a88f0..8976fb0b070a 100644
--- a/drivers/s390/net/lcs.h
+++ b/drivers/s390/net/lcs.h
@@ -138,6 +138,7 @@ enum lcs_channel_states {
138 LCS_CH_STATE_RUNNING, 138 LCS_CH_STATE_RUNNING,
139 LCS_CH_STATE_SUSPENDED, 139 LCS_CH_STATE_SUSPENDED,
140 LCS_CH_STATE_CLEARED, 140 LCS_CH_STATE_CLEARED,
141 LCS_CH_STATE_ERROR,
141}; 142};
142 143
143/** 144/**