From 6d4f3d182b1c6074b84feaadd84a0957059a5940 Mon Sep 17 00:00:00 2001 From: Ursula Braun Date: Wed, 29 Aug 2007 11:26:56 +0200 Subject: qeth: crash during reboot after failing online setting Online setting of a qeth device may fail for instance because of: - out-of-memory condition when allocating qdio queues - IDX ACTIVATE problem - ... Such a device is still returned in a driver_for_each_device loop processed in qeth_reboot_event(), which calls qeth_clear_qdio_buffers(). Make sure qeth_clear_output_buffer() is called only, if the qdio queues have been successfully allocated during initialization of a qeth device. Signed-off-by: Ursula Braun Signed-off-by: Jeff Garzik --- drivers/s390/net/qeth_main.c | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/s390/net/qeth_main.c b/drivers/s390/net/qeth_main.c index 443cde10353e..45a8b9f78b16 100644 --- a/drivers/s390/net/qeth_main.c +++ b/drivers/s390/net/qeth_main.c @@ -3356,10 +3356,12 @@ out_freeoutq: while (i > 0) kfree(card->qdio.out_qs[--i]); kfree(card->qdio.out_qs); + card->qdio.out_qs = NULL; out_freepool: qeth_free_buffer_pool(card); out_freeinq: kfree(card->qdio.in_q); + card->qdio.in_q = NULL; out_nomem: atomic_set(&card->qdio.state, QETH_QDIO_UNINITIALIZED); return -ENOMEM; @@ -3375,16 +3377,20 @@ qeth_free_qdio_buffers(struct qeth_card *card) QETH_QDIO_UNINITIALIZED) return; kfree(card->qdio.in_q); + card->qdio.in_q = NULL; /* inbound buffer pool */ qeth_free_buffer_pool(card); /* free outbound qdio_qs */ - for (i = 0; i < card->qdio.no_out_queues; ++i){ - for (j = 0; j < QDIO_MAX_BUFFERS_PER_Q; ++j) - qeth_clear_output_buffer(card->qdio.out_qs[i], - &card->qdio.out_qs[i]->bufs[j]); - kfree(card->qdio.out_qs[i]); + if (card->qdio.out_qs) { + for (i = 0; i < card->qdio.no_out_queues; ++i) { + for (j = 0; j < QDIO_MAX_BUFFERS_PER_Q; ++j) + qeth_clear_output_buffer(card->qdio.out_qs[i], + &card->qdio.out_qs[i]->bufs[j]); + kfree(card->qdio.out_qs[i]); + } + kfree(card->qdio.out_qs); + card->qdio.out_qs = NULL; } - kfree(card->qdio.out_qs); } static void @@ -3395,7 +3401,7 @@ qeth_clear_qdio_buffers(struct qeth_card *card) QETH_DBF_TEXT(trace, 2, "clearqdbf"); /* clear outbound buffers to free skbs */ for (i = 0; i < card->qdio.no_out_queues; ++i) - if (card->qdio.out_qs[i]){ + if (card->qdio.out_qs && card->qdio.out_qs[i]) { for (j = 0; j < QDIO_MAX_BUFFERS_PER_Q; ++j) qeth_clear_output_buffer(card->qdio.out_qs[i], &card->qdio.out_qs[i]->bufs[j]); -- cgit v1.2.3-59-g8ed1b