Received: by 10.192.165.156 with SMTP id m28csp283937imm; Tue, 17 Apr 2018 10:04:30 -0700 (PDT) X-Google-Smtp-Source: AIpwx4+vKSYWVAipiM2N+uBg04NHYoS3ct4K6eq9MKlM1zfMZpxaAMM1yWycVpQjIOLyH5kyY2a9 X-Received: by 2002:a17:902:694a:: with SMTP id k10-v6mr2690753plt.161.1523984670486; Tue, 17 Apr 2018 10:04:30 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1523984670; cv=none; d=google.com; s=arc-20160816; b=Ir8mVmhhTuWE+Fqu4s9pBkiKEhN90aNcMVaIYse1UqFA3eFVcF/Oufy8iPY0yYi06o 3eS6NV+kSByRQpwbx9DHN9URpDpKL8N3La/HdSG2cxWO8J1Ktdz9cI43BAmnGlwC6LGw pOO8yUF1pWq7tgcdz4YsvzUU33zjJh4qwHZ1hUb/GKbI5BAk5u0hIo7hYvyzMxir1HSf a9s7coL9iUzjl366a5/nsy9jipVI+3eU0g1m7GzcEmlWUmZZEYcEI+/SUaDsd8Otu6gX gxKKi9+VXtZy9DrlsQbCY3fUBuHdk9d3XaIdn+L6KrIAH0ALICuRUxNHgbh0OFpKzmNy JIng== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:mime-version:user-agent:references :in-reply-to:message-id:date:subject:cc:to:from :arc-authentication-results; bh=59OXcnODn4PHZPWFOZS0D4HsMt45ImkqHYmEI7FrUbQ=; b=0HmjfPbYXytaFnEaEUvIRw6wbs221taWPiaArWG09SbH2slJD2QFTvqO5ZCJnH9b0S L9HO3agxYP+x2qIQoARjBiV/+G2+PIHsrQkWhpDGd38LNMC6diAVqSDzorV0SDqL5xMM EFj8IJkP7Hr7c2kpGK5Xes+iUW1ifsd0HWHJgUVaiXgxrdUCQv4MUluAGCPCsF6pubie Bfx5A0vJ1LV/ISYbBFFN4p5qYZwPW3Gf+VzAhDEMJ426iFvbIQE7tjli7cmeLEhyXYGh n1W3bOPwXMhXOpp9PPgWgQ2mjjKoOx2G2k3TzxnWwqLclt8APfENvbbDm7nrvNH+hQUU 8yfg== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id 85si13093889pfz.271.2018.04.17.10.04.15; Tue, 17 Apr 2018 10:04:30 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1754180AbeDQQ76 (ORCPT + 99 others); Tue, 17 Apr 2018 12:59:58 -0400 Received: from mail.linuxfoundation.org ([140.211.169.12]:60772 "EHLO mail.linuxfoundation.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1754022AbeDQQC0 (ORCPT ); Tue, 17 Apr 2018 12:02:26 -0400 Received: from localhost (unknown [46.44.180.42]) by mail.linuxfoundation.org (Postfix) with ESMTPSA id 01FEDDF7; Tue, 17 Apr 2018 16:02:25 +0000 (UTC) From: Greg Kroah-Hartman To: linux-kernel@vger.kernel.org Cc: Greg Kroah-Hartman , stable@vger.kernel.org, Julian Wiedmann , Ursula Braun , Benjamin Block , Martin Schwidefsky Subject: [PATCH 4.16 60/68] s390/qdio: dont merge ERROR output buffers Date: Tue, 17 Apr 2018 17:58:13 +0200 Message-Id: <20180417155751.777071670@linuxfoundation.org> X-Mailer: git-send-email 2.17.0 In-Reply-To: <20180417155749.341779147@linuxfoundation.org> References: <20180417155749.341779147@linuxfoundation.org> User-Agent: quilt/0.65 X-stable: review MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org 4.16-stable review patch. If anyone has any objections, please let me know. ------------------ From: Julian Wiedmann commit 0cf1e05157b9e5530dcc3ca9fec9bf617fc93375 upstream. On an Output queue, both EMPTY and PENDING buffer states imply that the buffer is ready for completion-processing by the upper-layer drivers. So for a non-QEBSM Output queue, get_buf_states() merges mixed batches of PENDING and EMPTY buffers into one large batch of EMPTY buffers. The upper-layer driver (ie. qeth) later distuingishes PENDING from EMPTY by inspecting the slsb_state for QDIO_OUTBUF_STATE_FLAG_PENDING. But the merge logic in get_buf_states() contains a bug that causes us to erronously also merge ERROR buffers into such a batch of EMPTY buffers (ERROR is 0xaf, EMPTY is 0xa1; so ERROR & EMPTY == EMPTY). Effectively, most outbound ERROR buffers are currently discarded silently and processed as if they had succeeded. Note that this affects _all_ non-QEBSM device types, not just IQD with CQ. Fix it by explicitly spelling out the exact conditions for merging. For extracting the "get initial state" part out of the loop, this relies on the fact that get_buf_states() is never called with a count of 0. The QEBSM path already strictly requires this, and the two callers with variable 'count' make sure of it. Fixes: 104ea556ee7f ("qdio: support asynchronous delivery of storage blocks") Cc: #v3.2+ Signed-off-by: Julian Wiedmann Reviewed-by: Ursula Braun Reviewed-by: Benjamin Block Signed-off-by: Martin Schwidefsky Signed-off-by: Greg Kroah-Hartman --- drivers/s390/cio/qdio_main.c | 31 ++++++++++++++++++++----------- 1 file changed, 20 insertions(+), 11 deletions(-) --- a/drivers/s390/cio/qdio_main.c +++ b/drivers/s390/cio/qdio_main.c @@ -207,7 +207,10 @@ again: return 0; } -/* returns number of examined buffers and their common state in *state */ +/* + * Returns number of examined buffers and their common state in *state. + * Requested number of buffers-to-examine must be > 0. + */ static inline int get_buf_states(struct qdio_q *q, unsigned int bufnr, unsigned char *state, unsigned int count, int auto_ack, int merge_pending) @@ -218,17 +221,23 @@ static inline int get_buf_states(struct if (is_qebsm(q)) return qdio_do_eqbs(q, state, bufnr, count, auto_ack); - for (i = 0; i < count; i++) { - if (!__state) { - __state = q->slsb.val[bufnr]; - if (merge_pending && __state == SLSB_P_OUTPUT_PENDING) - __state = SLSB_P_OUTPUT_EMPTY; - } else if (merge_pending) { - if ((q->slsb.val[bufnr] & __state) != __state) - break; - } else if (q->slsb.val[bufnr] != __state) - break; + /* get initial state: */ + __state = q->slsb.val[bufnr]; + if (merge_pending && __state == SLSB_P_OUTPUT_PENDING) + __state = SLSB_P_OUTPUT_EMPTY; + + for (i = 1; i < count; i++) { bufnr = next_buf(bufnr); + + /* merge PENDING into EMPTY: */ + if (merge_pending && + q->slsb.val[bufnr] == SLSB_P_OUTPUT_PENDING && + __state == SLSB_P_OUTPUT_EMPTY) + continue; + + /* stop if next state differs from initial state: */ + if (q->slsb.val[bufnr] != __state) + break; } *state = __state; return i;