Commit eff73e16 authored by Julian Wiedmann's avatar Julian Wiedmann Committed by David S. Miller

s390/qeth: tolerate pre-filled RX buffer

When preparing a buffer for RX refill, tolerate that it already has a
pool_entry attached. Otherwise we could easily leak such a pool_entry
when re-driving the RX refill after an error (from eg. do_qdio()).

This needs some minor adjustment in the code that drains RX buffer(s)
prior to RX refill and during teardown, so that ->pool_entry is NULLed
accordingly.

Fixes: 4a71df50 ("qeth: new qeth device driver")
Signed-off-by: default avatarJulian Wiedmann <jwi@linux.ibm.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 9fc95f50
...@@ -204,12 +204,17 @@ EXPORT_SYMBOL_GPL(qeth_threads_running); ...@@ -204,12 +204,17 @@ EXPORT_SYMBOL_GPL(qeth_threads_running);
void qeth_clear_working_pool_list(struct qeth_card *card) void qeth_clear_working_pool_list(struct qeth_card *card)
{ {
struct qeth_buffer_pool_entry *pool_entry, *tmp; struct qeth_buffer_pool_entry *pool_entry, *tmp;
struct qeth_qdio_q *queue = card->qdio.in_q;
unsigned int i;
QETH_CARD_TEXT(card, 5, "clwrklst"); QETH_CARD_TEXT(card, 5, "clwrklst");
list_for_each_entry_safe(pool_entry, tmp, list_for_each_entry_safe(pool_entry, tmp,
&card->qdio.in_buf_pool.entry_list, list){ &card->qdio.in_buf_pool.entry_list, list){
list_del(&pool_entry->list); list_del(&pool_entry->list);
} }
for (i = 0; i < ARRAY_SIZE(queue->bufs); i++)
queue->bufs[i].pool_entry = NULL;
} }
EXPORT_SYMBOL_GPL(qeth_clear_working_pool_list); EXPORT_SYMBOL_GPL(qeth_clear_working_pool_list);
...@@ -2965,7 +2970,7 @@ static struct qeth_buffer_pool_entry *qeth_find_free_buffer_pool_entry( ...@@ -2965,7 +2970,7 @@ static struct qeth_buffer_pool_entry *qeth_find_free_buffer_pool_entry(
static int qeth_init_input_buffer(struct qeth_card *card, static int qeth_init_input_buffer(struct qeth_card *card,
struct qeth_qdio_buffer *buf) struct qeth_qdio_buffer *buf)
{ {
struct qeth_buffer_pool_entry *pool_entry; struct qeth_buffer_pool_entry *pool_entry = buf->pool_entry;
int i; int i;
if ((card->options.cq == QETH_CQ_ENABLED) && (!buf->rx_skb)) { if ((card->options.cq == QETH_CQ_ENABLED) && (!buf->rx_skb)) {
...@@ -2976,9 +2981,13 @@ static int qeth_init_input_buffer(struct qeth_card *card, ...@@ -2976,9 +2981,13 @@ static int qeth_init_input_buffer(struct qeth_card *card,
return -ENOMEM; return -ENOMEM;
} }
pool_entry = qeth_find_free_buffer_pool_entry(card); if (!pool_entry) {
if (!pool_entry) pool_entry = qeth_find_free_buffer_pool_entry(card);
return -ENOBUFS; if (!pool_entry)
return -ENOBUFS;
buf->pool_entry = pool_entry;
}
/* /*
* since the buffer is accessed only from the input_tasklet * since the buffer is accessed only from the input_tasklet
...@@ -2986,8 +2995,6 @@ static int qeth_init_input_buffer(struct qeth_card *card, ...@@ -2986,8 +2995,6 @@ static int qeth_init_input_buffer(struct qeth_card *card,
* the QETH_IN_BUF_REQUEUE_THRESHOLD we should never run out off * the QETH_IN_BUF_REQUEUE_THRESHOLD we should never run out off
* buffers * buffers
*/ */
buf->pool_entry = pool_entry;
for (i = 0; i < QETH_MAX_BUFFER_ELEMENTS(card); ++i) { for (i = 0; i < QETH_MAX_BUFFER_ELEMENTS(card); ++i) {
buf->buffer->element[i].length = PAGE_SIZE; buf->buffer->element[i].length = PAGE_SIZE;
buf->buffer->element[i].addr = buf->buffer->element[i].addr =
...@@ -5771,6 +5778,7 @@ static unsigned int qeth_rx_poll(struct qeth_card *card, int budget) ...@@ -5771,6 +5778,7 @@ static unsigned int qeth_rx_poll(struct qeth_card *card, int budget)
if (done) { if (done) {
QETH_CARD_STAT_INC(card, rx_bufs); QETH_CARD_STAT_INC(card, rx_bufs);
qeth_put_buffer_pool_entry(card, buffer->pool_entry); qeth_put_buffer_pool_entry(card, buffer->pool_entry);
buffer->pool_entry = NULL;
qeth_queue_input_buffer(card, card->rx.b_index); qeth_queue_input_buffer(card, card->rx.b_index);
card->rx.b_count--; card->rx.b_count--;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment