aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/s390
diff options
context:
space:
mode:
authorUrsula Braun <braunu@de.ibm.com>2007-08-29 05:26:56 -0400
committerJeff Garzik <jeff@garzik.org>2007-08-31 06:52:58 -0400
commit6d4f3d182b1c6074b84feaadd84a0957059a5940 (patch)
tree0a9506423e06a70fc420b16420f6c038649f8f93 /drivers/s390
parent5a4b61a95a9b742d8a966950d23f386c34a733f2 (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>
Diffstat (limited to 'drivers/s390')
-rw-r--r--drivers/s390/net/qeth_main.c20
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;
3359out_freepool: 3360out_freepool:
3360 qeth_free_buffer_pool(card); 3361 qeth_free_buffer_pool(card);
3361out_freeinq: 3362out_freeinq:
3362 kfree(card->qdio.in_q); 3363 kfree(card->qdio.in_q);
3364 card->qdio.in_q = NULL;
3363out_nomem: 3365out_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
3390static void 3396static 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]);