Home Home > GIT Browse > SLE12-SP4
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPetr Tesarik <ptesarik@suse.cz>2019-08-08 18:42:47 +0200
committerPetr Tesarik <ptesarik@suse.cz>2019-08-08 18:42:58 +0200
commitcc12236f00fda3d3cf1e7cfb09bb341e2e89dd8b (patch)
tree0d3269387cbe8858afe2baf5748506c85c2233ed
parentafd9f94af352a7d0eba3c35af18ff2623c506efb (diff)
s390/qeth: avoid control IO completion stalls (bsc#1142109
LTC#179339).
-rw-r--r--patches.fixes/s390-qeth-avoid-control-io-completion-stalls120
-rw-r--r--series.conf1
2 files changed, 121 insertions, 0 deletions
diff --git a/patches.fixes/s390-qeth-avoid-control-io-completion-stalls b/patches.fixes/s390-qeth-avoid-control-io-completion-stalls
new file mode 100644
index 0000000000..e42be391b2
--- /dev/null
+++ b/patches.fixes/s390-qeth-avoid-control-io-completion-stalls
@@ -0,0 +1,120 @@
+From: Julian Wiedmann <jwi@linux.vnet.ibm.com>
+Date: Thu, 19 Apr 2018 12:52:07 +0200
+Subject: s390/qeth: avoid control IO completion stalls
+Git-commit: 901e3f49facbd31b2b3d1786637b4a35e1022e9b
+Patch-mainline: v4.17-rc3
+References: bsc#1142109 LTC#179339
+
+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>
+Acked-by: Petr Tesarik <ptesarik@suse.com>
+---
+ 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
+@@ -568,7 +568,6 @@ enum qeth_ip_types {
+ enum qeth_cmd_buffer_state {
+ BUF_STATE_FREE,
+ BUF_STATE_LOCKED,
+- BUF_STATE_PROCESSED,
+ };
+
+ enum qeth_cq {
+@@ -612,7 +611,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
+@@ -819,7 +819,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);
+@@ -925,7 +924,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);
+@@ -1101,11 +1099,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;
+@@ -1183,25 +1179,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;
+@@ -2166,7 +2155,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;
diff --git a/series.conf b/series.conf
index 4b71651883..53b06646a0 100644
--- a/series.conf
+++ b/series.conf
@@ -15876,6 +15876,7 @@
patches.drm/drm-i915-Call-i915_perf_fini-on-init_hw-error-unwind
patches.drm/drm-i915-audio-Fix-audio-detection-issue-on-GLK
patches.drivers/s390-qeth-fix-error-handling-in-adapter-command-callbacks.patch
+ patches.fixes/s390-qeth-avoid-control-io-completion-stalls
patches.arch/s390-qeth-handle-failure-on-workqueue-creation.patch
patches.arch/s390-qeth-fix-MAC-address-update-sequence.patch
patches.suse/llc-delete-timers-synchronously-in-llc_sk_free.patch