From: Julian Wiedmann <j...@linux.ibm.com>

[ Upstream commit eff73e16ee116f6eafa2be48fab42659a27cb453 ]

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: 4a71df50047f ("qeth: new qeth device driver")
Signed-off-by: Julian Wiedmann <j...@linux.ibm.com>
Signed-off-by: David S. Miller <da...@davemloft.net>
Signed-off-by: Sasha Levin <sas...@kernel.org>
---
 drivers/s390/net/qeth_core_main.c | 20 ++++++++++++++------
 1 file changed, 14 insertions(+), 6 deletions(-)

diff --git a/drivers/s390/net/qeth_core_main.c 
b/drivers/s390/net/qeth_core_main.c
index 60d675fefac7d..40ddd17864304 100644
--- a/drivers/s390/net/qeth_core_main.c
+++ b/drivers/s390/net/qeth_core_main.c
@@ -202,12 +202,17 @@ EXPORT_SYMBOL_GPL(qeth_threads_running);
 void qeth_clear_working_pool_list(struct qeth_card *card)
 {
        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");
        list_for_each_entry_safe(pool_entry, tmp,
                            &card->qdio.in_buf_pool.entry_list, 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);
 
@@ -2671,7 +2676,7 @@ static struct qeth_buffer_pool_entry 
*qeth_find_free_buffer_pool_entry(
 static int qeth_init_input_buffer(struct qeth_card *card,
                struct qeth_qdio_buffer *buf)
 {
-       struct qeth_buffer_pool_entry *pool_entry;
+       struct qeth_buffer_pool_entry *pool_entry = buf->pool_entry;
        int i;
 
        if ((card->options.cq == QETH_CQ_ENABLED) && (!buf->rx_skb)) {
@@ -2682,9 +2687,13 @@ static int qeth_init_input_buffer(struct qeth_card *card,
                        return -ENOMEM;
        }
 
-       pool_entry = qeth_find_free_buffer_pool_entry(card);
-       if (!pool_entry)
-               return -ENOBUFS;
+       if (!pool_entry) {
+               pool_entry = qeth_find_free_buffer_pool_entry(card);
+               if (!pool_entry)
+                       return -ENOBUFS;
+
+               buf->pool_entry = pool_entry;
+       }
 
        /*
         * since the buffer is accessed only from the input_tasklet
@@ -2692,8 +2701,6 @@ static int qeth_init_input_buffer(struct qeth_card *card,
         * the QETH_IN_BUF_REQUEUE_THRESHOLD we should never run  out off
         * buffers
         */
-
-       buf->pool_entry = pool_entry;
        for (i = 0; i < QETH_MAX_BUFFER_ELEMENTS(card); ++i) {
                buf->buffer->element[i].length = PAGE_SIZE;
                buf->buffer->element[i].addr =
@@ -5521,6 +5528,7 @@ static unsigned int qeth_rx_poll(struct qeth_card *card, 
int budget)
                if (done) {
                        QETH_CARD_STAT_INC(card, rx_bufs);
                        qeth_put_buffer_pool_entry(card, buffer->pool_entry);
+                       buffer->pool_entry = NULL;
                        qeth_queue_input_buffer(card, card->rx.b_index);
                        card->rx.b_count--;
 
-- 
2.25.1



Reply via email to