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>
This commit is contained in:
committed by
Jeff Garzik
parent
5a4b61a95a
commit
6d4f3d182b
@@ -3356,10 +3356,12 @@ out_freeoutq:
|
|||||||
while (i > 0)
|
while (i > 0)
|
||||||
kfree(card->qdio.out_qs[--i]);
|
kfree(card->qdio.out_qs[--i]);
|
||||||
kfree(card->qdio.out_qs);
|
kfree(card->qdio.out_qs);
|
||||||
|
card->qdio.out_qs = NULL;
|
||||||
out_freepool:
|
out_freepool:
|
||||||
qeth_free_buffer_pool(card);
|
qeth_free_buffer_pool(card);
|
||||||
out_freeinq:
|
out_freeinq:
|
||||||
kfree(card->qdio.in_q);
|
kfree(card->qdio.in_q);
|
||||||
|
card->qdio.in_q = NULL;
|
||||||
out_nomem:
|
out_nomem:
|
||||||
atomic_set(&card->qdio.state, QETH_QDIO_UNINITIALIZED);
|
atomic_set(&card->qdio.state, QETH_QDIO_UNINITIALIZED);
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
@@ -3375,9 +3377,11 @@ qeth_free_qdio_buffers(struct qeth_card *card)
|
|||||||
QETH_QDIO_UNINITIALIZED)
|
QETH_QDIO_UNINITIALIZED)
|
||||||
return;
|
return;
|
||||||
kfree(card->qdio.in_q);
|
kfree(card->qdio.in_q);
|
||||||
|
card->qdio.in_q = NULL;
|
||||||
/* inbound buffer pool */
|
/* inbound buffer pool */
|
||||||
qeth_free_buffer_pool(card);
|
qeth_free_buffer_pool(card);
|
||||||
/* free outbound qdio_qs */
|
/* free outbound qdio_qs */
|
||||||
|
if (card->qdio.out_qs) {
|
||||||
for (i = 0; i < card->qdio.no_out_queues; ++i) {
|
for (i = 0; i < card->qdio.no_out_queues; ++i) {
|
||||||
for (j = 0; j < QDIO_MAX_BUFFERS_PER_Q; ++j)
|
for (j = 0; j < QDIO_MAX_BUFFERS_PER_Q; ++j)
|
||||||
qeth_clear_output_buffer(card->qdio.out_qs[i],
|
qeth_clear_output_buffer(card->qdio.out_qs[i],
|
||||||
@@ -3385,6 +3389,8 @@ qeth_free_qdio_buffers(struct qeth_card *card)
|
|||||||
kfree(card->qdio.out_qs[i]);
|
kfree(card->qdio.out_qs[i]);
|
||||||
}
|
}
|
||||||
kfree(card->qdio.out_qs);
|
kfree(card->qdio.out_qs);
|
||||||
|
card->qdio.out_qs = NULL;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@@ -3395,7 +3401,7 @@ qeth_clear_qdio_buffers(struct qeth_card *card)
|
|||||||
QETH_DBF_TEXT(trace, 2, "clearqdbf");
|
QETH_DBF_TEXT(trace, 2, "clearqdbf");
|
||||||
/* clear outbound buffers to free skbs */
|
/* clear outbound buffers to free skbs */
|
||||||
for (i = 0; i < card->qdio.no_out_queues; ++i)
|
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)
|
for (j = 0; j < QDIO_MAX_BUFFERS_PER_Q; ++j)
|
||||||
qeth_clear_output_buffer(card->qdio.out_qs[i],
|
qeth_clear_output_buffer(card->qdio.out_qs[i],
|
||||||
&card->qdio.out_qs[i]->bufs[j]);
|
&card->qdio.out_qs[i]->bufs[j]);
|
||||||
|
Reference in New Issue
Block a user