Skip to content

Commit

Permalink
qeth: avoid loop if ipa command response is missing
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Ursula Braun authored and David S. Miller committed Jul 23, 2010
1 parent 9dc48cc commit 908abbb
Show file tree
Hide file tree
Showing 2 changed files with 16 additions and 0 deletions.
1 change: 1 addition & 0 deletions drivers/s390/net/qeth_core.h
Original file line number Diff line number Diff line change
Expand Up @@ -740,6 +740,7 @@ struct qeth_card {
struct qeth_qdio_info qdio;
struct qeth_perf_stats perf_stats;
int use_hard_stop;
int read_or_write_problem;
struct qeth_osn_info osn_info;
struct qeth_discipline discipline;
atomic_t force_alloc_skb;
Expand Down
15 changes: 15 additions & 0 deletions drivers/s390/net/qeth_core_main.c
Original file line number Diff line number Diff line change
Expand Up @@ -262,6 +262,7 @@ static int qeth_issue_next_read(struct qeth_card *card)
QETH_DBF_MESSAGE(2, "%s error in starting next read ccw! "
"rc=%i\n", dev_name(&card->gdev->dev), rc);
atomic_set(&card->read.irq_pending, 0);
card->read_or_write_problem = 1;
qeth_schedule_recovery(card);
wake_up(&card->wait_q);
}
Expand Down Expand Up @@ -382,6 +383,7 @@ void qeth_clear_ipacmd_list(struct qeth_card *card)
qeth_put_reply(reply);
}
spin_unlock_irqrestore(&card->lock, flags);
atomic_set(&card->write.irq_pending, 0);
}
EXPORT_SYMBOL_GPL(qeth_clear_ipacmd_list);

Expand Down Expand Up @@ -1076,6 +1078,7 @@ static int qeth_setup_card(struct qeth_card *card)
card->state = CARD_STATE_DOWN;
card->lan_online = 0;
card->use_hard_stop = 0;
card->read_or_write_problem = 0;
card->dev = NULL;
spin_lock_init(&card->vlanlock);
spin_lock_init(&card->mclock);
Expand Down Expand Up @@ -1658,6 +1661,10 @@ int qeth_send_control_data(struct qeth_card *card, int len,

QETH_CARD_TEXT(card, 2, "sendctl");

if (card->read_or_write_problem) {
qeth_release_buffer(iob->channel, iob);
return -EIO;
}
reply = qeth_alloc_reply(card);
if (!reply) {
return -ENOMEM;
Expand Down Expand Up @@ -1729,6 +1736,9 @@ int qeth_send_control_data(struct qeth_card *card, int len,
spin_unlock_irqrestore(&reply->card->lock, flags);
reply->rc = -ETIME;
atomic_inc(&reply->received);
atomic_set(&card->write.irq_pending, 0);
qeth_release_buffer(iob->channel, iob);
card->write.buf_no = (card->write.buf_no + 1) % QETH_CMD_BUFFER_NO;
wake_up(&reply->wait_q);
rc = reply->rc;
qeth_put_reply(reply);
Expand Down Expand Up @@ -2485,6 +2495,10 @@ int qeth_send_ipa_cmd(struct qeth_card *card, struct qeth_cmd_buffer *iob,
qeth_prepare_ipa_cmd(card, iob, prot_type);
rc = qeth_send_control_data(card, IPA_CMD_LENGTH,
iob, reply_cb, reply_param);
if (rc == -ETIME) {
qeth_clear_ipacmd_list(card);
qeth_schedule_recovery(card);
}
return rc;
}
EXPORT_SYMBOL_GPL(qeth_send_ipa_cmd);
Expand Down Expand Up @@ -3967,6 +3981,7 @@ int qeth_core_hardsetup_card(struct qeth_card *card)
else
goto retry;
}
card->read_or_write_problem = 0;
rc = qeth_mpc_initialize(card);
if (rc) {
QETH_DBF_TEXT_(SETUP, 2, "5err%d", rc);
Expand Down

0 comments on commit 908abbb

Please sign in to comment.