diff options
author | Ursula Braun <braunu@de.ibm.com> | 2007-08-29 05:26:56 -0400 |
---|---|---|
committer | Jeff Garzik <jeff@garzik.org> | 2007-08-31 06:52:58 -0400 |
commit | 6d4f3d182b1c6074b84feaadd84a0957059a5940 (patch) | |
tree | 0a9506423e06a70fc420b16420f6c038649f8f93 | |
parent | 5a4b61a95a9b742d8a966950d23f386c34a733f2 (diff) |
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 <braunu@de.ibm.com>
Signed-off-by: Jeff Garzik <jeff@garzik.org>
-rw-r--r-- | drivers/s390/net/qeth_main.c | 20 |
1 files changed, 13 insertions, 7 deletions
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: | |||
3356 | while (i > 0) | 3356 | while (i > 0) |
3357 | kfree(card->qdio.out_qs[--i]); | 3357 | kfree(card->qdio.out_qs[--i]); |
3358 | kfree(card->qdio.out_qs); | 3358 | kfree(card->qdio.out_qs); |
3359 | card->qdio.out_qs = NULL; | ||
3359 | out_freepool: | 3360 | out_freepool: |
3360 | qeth_free_buffer_pool(card); | 3361 | qeth_free_buffer_pool(card); |
3361 | out_freeinq: | 3362 | out_freeinq: |
3362 | kfree(card->qdio.in_q); | 3363 | kfree(card->qdio.in_q); |
3364 | card->qdio.in_q = NULL; | ||
3363 | out_nomem: | 3365 | out_nomem: |
3364 | atomic_set(&card->qdio.state, QETH_QDIO_UNINITIALIZED); | 3366 | atomic_set(&card->qdio.state, QETH_QDIO_UNINITIALIZED); |
3365 | return -ENOMEM; | 3367 | return -ENOMEM; |
@@ -3375,16 +3377,20 @@ qeth_free_qdio_buffers(struct qeth_card *card) | |||
3375 | QETH_QDIO_UNINITIALIZED) | 3377 | QETH_QDIO_UNINITIALIZED) |
3376 | return; | 3378 | return; |
3377 | kfree(card->qdio.in_q); | 3379 | kfree(card->qdio.in_q); |
3380 | card->qdio.in_q = NULL; | ||
3378 | /* inbound buffer pool */ | 3381 | /* inbound buffer pool */ |
3379 | qeth_free_buffer_pool(card); | 3382 | qeth_free_buffer_pool(card); |
3380 | /* free outbound qdio_qs */ | 3383 | /* free outbound qdio_qs */ |
3381 | for (i = 0; i < card->qdio.no_out_queues; ++i){ | 3384 | if (card->qdio.out_qs) { |
3382 | for (j = 0; j < QDIO_MAX_BUFFERS_PER_Q; ++j) | 3385 | for (i = 0; i < card->qdio.no_out_queues; ++i) { |
3383 | qeth_clear_output_buffer(card->qdio.out_qs[i], | 3386 | for (j = 0; j < QDIO_MAX_BUFFERS_PER_Q; ++j) |
3384 | &card->qdio.out_qs[i]->bufs[j]); | 3387 | qeth_clear_output_buffer(card->qdio.out_qs[i], |
3385 | kfree(card->qdio.out_qs[i]); | 3388 | &card->qdio.out_qs[i]->bufs[j]); |
3389 | kfree(card->qdio.out_qs[i]); | ||
3390 | } | ||
3391 | kfree(card->qdio.out_qs); | ||
3392 | card->qdio.out_qs = NULL; | ||
3386 | } | 3393 | } |
3387 | kfree(card->qdio.out_qs); | ||
3388 | } | 3394 | } |
3389 | 3395 | ||
3390 | static void | 3396 | static void |
@@ -3395,7 +3401,7 @@ qeth_clear_qdio_buffers(struct qeth_card *card) | |||
3395 | QETH_DBF_TEXT(trace, 2, "clearqdbf"); | 3401 | QETH_DBF_TEXT(trace, 2, "clearqdbf"); |
3396 | /* clear outbound buffers to free skbs */ | 3402 | /* clear outbound buffers to free skbs */ |
3397 | for (i = 0; i < card->qdio.no_out_queues; ++i) | 3403 | for (i = 0; i < card->qdio.no_out_queues; ++i) |
3398 | if (card->qdio.out_qs[i]){ | 3404 | if (card->qdio.out_qs && card->qdio.out_qs[i]) { |
3399 | for (j = 0; j < QDIO_MAX_BUFFERS_PER_Q; ++j) | 3405 | for (j = 0; j < QDIO_MAX_BUFFERS_PER_Q; ++j) |
3400 | qeth_clear_output_buffer(card->qdio.out_qs[i], | 3406 | qeth_clear_output_buffer(card->qdio.out_qs[i], |
3401 | &card->qdio.out_qs[i]->bufs[j]); | 3407 | &card->qdio.out_qs[i]->bufs[j]); |