diff options
author | Ursula Braun <ursula.braun@de.ibm.com> | 2010-07-22 19:15:06 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2010-07-23 15:36:23 -0400 |
commit | 908abbb5773213288c8ed033c3313440b31cfbf3 (patch) | |
tree | 0636237a9398ff6939708cc68f53dacf12d2d5aa /drivers/s390/net | |
parent | 9dc48ccc68b9dfc01c2beee2d4317fb3df3fdce9 (diff) |
qeth: avoid loop if ipa command response is missing
If qeth issues an ipa command, but for some reasons the response
never comes back, qeth reaches a timeout.
Reset the irq_pending flag of the write channel in timeout handling
code and trigger a recovery to avoid endless looping for the following
ipa command.
Signed-off-by: Ursula Braun <ursula.braun@de.ibm.com>
Signed-off-by: Frank Blaschka <frank.blaschka@de.ibm.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/s390/net')
-rw-r--r-- | drivers/s390/net/qeth_core.h | 1 | ||||
-rw-r--r-- | drivers/s390/net/qeth_core_main.c | 15 |
2 files changed, 16 insertions, 0 deletions
diff --git a/drivers/s390/net/qeth_core.h b/drivers/s390/net/qeth_core.h index 41ddf86c342..d1257768be9 100644 --- a/drivers/s390/net/qeth_core.h +++ b/drivers/s390/net/qeth_core.h | |||
@@ -740,6 +740,7 @@ struct qeth_card { | |||
740 | struct qeth_qdio_info qdio; | 740 | struct qeth_qdio_info qdio; |
741 | struct qeth_perf_stats perf_stats; | 741 | struct qeth_perf_stats perf_stats; |
742 | int use_hard_stop; | 742 | int use_hard_stop; |
743 | int read_or_write_problem; | ||
743 | struct qeth_osn_info osn_info; | 744 | struct qeth_osn_info osn_info; |
744 | struct qeth_discipline discipline; | 745 | struct qeth_discipline discipline; |
745 | atomic_t force_alloc_skb; | 746 | atomic_t force_alloc_skb; |
diff --git a/drivers/s390/net/qeth_core_main.c b/drivers/s390/net/qeth_core_main.c index f33da45c35e..7f3ea77551e 100644 --- a/drivers/s390/net/qeth_core_main.c +++ b/drivers/s390/net/qeth_core_main.c | |||
@@ -262,6 +262,7 @@ static int qeth_issue_next_read(struct qeth_card *card) | |||
262 | QETH_DBF_MESSAGE(2, "%s error in starting next read ccw! " | 262 | QETH_DBF_MESSAGE(2, "%s error in starting next read ccw! " |
263 | "rc=%i\n", dev_name(&card->gdev->dev), rc); | 263 | "rc=%i\n", dev_name(&card->gdev->dev), rc); |
264 | atomic_set(&card->read.irq_pending, 0); | 264 | atomic_set(&card->read.irq_pending, 0); |
265 | card->read_or_write_problem = 1; | ||
265 | qeth_schedule_recovery(card); | 266 | qeth_schedule_recovery(card); |
266 | wake_up(&card->wait_q); | 267 | wake_up(&card->wait_q); |
267 | } | 268 | } |
@@ -382,6 +383,7 @@ void qeth_clear_ipacmd_list(struct qeth_card *card) | |||
382 | qeth_put_reply(reply); | 383 | qeth_put_reply(reply); |
383 | } | 384 | } |
384 | spin_unlock_irqrestore(&card->lock, flags); | 385 | spin_unlock_irqrestore(&card->lock, flags); |
386 | atomic_set(&card->write.irq_pending, 0); | ||
385 | } | 387 | } |
386 | EXPORT_SYMBOL_GPL(qeth_clear_ipacmd_list); | 388 | EXPORT_SYMBOL_GPL(qeth_clear_ipacmd_list); |
387 | 389 | ||
@@ -1076,6 +1078,7 @@ static int qeth_setup_card(struct qeth_card *card) | |||
1076 | card->state = CARD_STATE_DOWN; | 1078 | card->state = CARD_STATE_DOWN; |
1077 | card->lan_online = 0; | 1079 | card->lan_online = 0; |
1078 | card->use_hard_stop = 0; | 1080 | card->use_hard_stop = 0; |
1081 | card->read_or_write_problem = 0; | ||
1079 | card->dev = NULL; | 1082 | card->dev = NULL; |
1080 | spin_lock_init(&card->vlanlock); | 1083 | spin_lock_init(&card->vlanlock); |
1081 | spin_lock_init(&card->mclock); | 1084 | spin_lock_init(&card->mclock); |
@@ -1658,6 +1661,10 @@ int qeth_send_control_data(struct qeth_card *card, int len, | |||
1658 | 1661 | ||
1659 | QETH_CARD_TEXT(card, 2, "sendctl"); | 1662 | QETH_CARD_TEXT(card, 2, "sendctl"); |
1660 | 1663 | ||
1664 | if (card->read_or_write_problem) { | ||
1665 | qeth_release_buffer(iob->channel, iob); | ||
1666 | return -EIO; | ||
1667 | } | ||
1661 | reply = qeth_alloc_reply(card); | 1668 | reply = qeth_alloc_reply(card); |
1662 | if (!reply) { | 1669 | if (!reply) { |
1663 | return -ENOMEM; | 1670 | return -ENOMEM; |
@@ -1729,6 +1736,9 @@ time_err: | |||
1729 | spin_unlock_irqrestore(&reply->card->lock, flags); | 1736 | spin_unlock_irqrestore(&reply->card->lock, flags); |
1730 | reply->rc = -ETIME; | 1737 | reply->rc = -ETIME; |
1731 | atomic_inc(&reply->received); | 1738 | atomic_inc(&reply->received); |
1739 | atomic_set(&card->write.irq_pending, 0); | ||
1740 | qeth_release_buffer(iob->channel, iob); | ||
1741 | card->write.buf_no = (card->write.buf_no + 1) % QETH_CMD_BUFFER_NO; | ||
1732 | wake_up(&reply->wait_q); | 1742 | wake_up(&reply->wait_q); |
1733 | rc = reply->rc; | 1743 | rc = reply->rc; |
1734 | qeth_put_reply(reply); | 1744 | qeth_put_reply(reply); |
@@ -2485,6 +2495,10 @@ int qeth_send_ipa_cmd(struct qeth_card *card, struct qeth_cmd_buffer *iob, | |||
2485 | qeth_prepare_ipa_cmd(card, iob, prot_type); | 2495 | qeth_prepare_ipa_cmd(card, iob, prot_type); |
2486 | rc = qeth_send_control_data(card, IPA_CMD_LENGTH, | 2496 | rc = qeth_send_control_data(card, IPA_CMD_LENGTH, |
2487 | iob, reply_cb, reply_param); | 2497 | iob, reply_cb, reply_param); |
2498 | if (rc == -ETIME) { | ||
2499 | qeth_clear_ipacmd_list(card); | ||
2500 | qeth_schedule_recovery(card); | ||
2501 | } | ||
2488 | return rc; | 2502 | return rc; |
2489 | } | 2503 | } |
2490 | EXPORT_SYMBOL_GPL(qeth_send_ipa_cmd); | 2504 | EXPORT_SYMBOL_GPL(qeth_send_ipa_cmd); |
@@ -3967,6 +3981,7 @@ retriable: | |||
3967 | else | 3981 | else |
3968 | goto retry; | 3982 | goto retry; |
3969 | } | 3983 | } |
3984 | card->read_or_write_problem = 0; | ||
3970 | rc = qeth_mpc_initialize(card); | 3985 | rc = qeth_mpc_initialize(card); |
3971 | if (rc) { | 3986 | if (rc) { |
3972 | QETH_DBF_TEXT_(SETUP, 2, "5err%d", rc); | 3987 | QETH_DBF_TEXT_(SETUP, 2, "5err%d", rc); |