lkml.org 
[lkml]   [2018]   [Apr]   [27]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH 4.16 48/81] s390/qeth: avoid control IO completion stalls
    Date
    4.16-stable review patch.  If anyone has any objections, please let me know.

    ------------------

    From: Julian Wiedmann <jwi@linux.vnet.ibm.com>


    [ Upstream commit 901e3f49facbd31b2b3d1786637b4a35e1022e9b ]

    For control IO, qeth currently tracks the index of the buffer that it
    expects to complete the next IO on each qeth_channel. If the channel
    presents an IRQ while this buffer has not yet completed, no completion
    processing for _any_ completed buffer takes place.
    So if the 'next buffer' is skipped for any sort of reason* (eg. when it
    is released due to error conditions, before the IO is started), the
    buffer obviously won't switch to PROCESSED until it is eventually
    allocated for a _different_ IO and completes.
    Until this happens, all completion processing on that channel stalls
    and pending requests possibly time out.

    As a fix, remove the whole 'next buffer' logic and simply process any
    IO buffer right when it completes. A channel will never have more than
    one IO pending, so there's no risk of processing out-of-sequence.

    *Note: currently just one location in the code really handles this problem,
    by advancing the 'next' index manually.

    Signed-off-by: Julian Wiedmann <jwi@linux.vnet.ibm.com>
    Signed-off-by: David S. Miller <davem@davemloft.net>
    Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
    ---
    drivers/s390/net/qeth_core.h | 2 --
    drivers/s390/net/qeth_core_main.c | 22 +++++-----------------
    2 files changed, 5 insertions(+), 19 deletions(-)

    --- a/drivers/s390/net/qeth_core.h
    +++ b/drivers/s390/net/qeth_core.h
    @@ -565,7 +565,6 @@ enum qeth_ip_types {
    enum qeth_cmd_buffer_state {
    BUF_STATE_FREE,
    BUF_STATE_LOCKED,
    - BUF_STATE_PROCESSED,
    };

    enum qeth_cq {
    @@ -609,7 +608,6 @@ struct qeth_channel {
    struct qeth_cmd_buffer iob[QETH_CMD_BUFFER_NO];
    atomic_t irq_pending;
    int io_buf_no;
    - int buf_no;
    };

    /**
    --- a/drivers/s390/net/qeth_core_main.c
    +++ b/drivers/s390/net/qeth_core_main.c
    @@ -821,7 +821,6 @@ void qeth_clear_cmd_buffers(struct qeth_

    for (cnt = 0; cnt < QETH_CMD_BUFFER_NO; cnt++)
    qeth_release_buffer(channel, &channel->iob[cnt]);
    - channel->buf_no = 0;
    channel->io_buf_no = 0;
    }
    EXPORT_SYMBOL_GPL(qeth_clear_cmd_buffers);
    @@ -927,7 +926,6 @@ static int qeth_setup_channel(struct qet
    kfree(channel->iob[cnt].data);
    return -ENOMEM;
    }
    - channel->buf_no = 0;
    channel->io_buf_no = 0;
    atomic_set(&channel->irq_pending, 0);
    spin_lock_init(&channel->iob_lock);
    @@ -1103,11 +1101,9 @@ static void qeth_irq(struct ccw_device *
    {
    int rc;
    int cstat, dstat;
    - struct qeth_cmd_buffer *buffer;
    struct qeth_channel *channel;
    struct qeth_card *card;
    struct qeth_cmd_buffer *iob;
    - __u8 index;

    if (__qeth_check_irb_error(cdev, intparm, irb))
    return;
    @@ -1185,25 +1181,18 @@ static void qeth_irq(struct ccw_device *
    channel->state = CH_STATE_RCD_DONE;
    goto out;
    }
    - if (intparm) {
    - buffer = (struct qeth_cmd_buffer *) __va((addr_t)intparm);
    - buffer->state = BUF_STATE_PROCESSED;
    - }
    if (channel == &card->data)
    return;
    if (channel == &card->read &&
    channel->state == CH_STATE_UP)
    __qeth_issue_next_read(card);

    - iob = channel->iob;
    - index = channel->buf_no;
    - while (iob[index].state == BUF_STATE_PROCESSED) {
    - if (iob[index].callback != NULL)
    - iob[index].callback(channel, iob + index);
    -
    - index = (index + 1) % QETH_CMD_BUFFER_NO;
    + if (intparm) {
    + iob = (struct qeth_cmd_buffer *) __va((addr_t)intparm);
    + if (iob->callback)
    + iob->callback(iob->channel, iob);
    }
    - channel->buf_no = index;
    +
    out:
    wake_up(&card->wait_q);
    return;
    @@ -2217,7 +2206,6 @@ time_err:
    error:
    atomic_set(&card->write.irq_pending, 0);
    qeth_release_buffer(iob->channel, iob);
    - card->write.buf_no = (card->write.buf_no + 1) % QETH_CMD_BUFFER_NO;
    rc = reply->rc;
    qeth_put_reply(reply);
    return rc;

    \
     
     \ /
      Last update: 2018-04-27 16:28    [W:4.084 / U:0.024 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site