Received: by 2002:ad5:474a:0:0:0:0:0 with SMTP id i10csp5610402imu; Mon, 26 Nov 2018 02:59:14 -0800 (PST) X-Google-Smtp-Source: AFSGD/U7hE0ZFfldQH8vfsOVcVIqBKPfaHG7lyJro/AJ7kb8PtKEovHG/MJS7MOUSqK/AEJ75ZYT X-Received: by 2002:a63:c00b:: with SMTP id h11mr24833989pgg.429.1543229954925; Mon, 26 Nov 2018 02:59:14 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1543229954; cv=none; d=google.com; s=arc-20160816; b=PPKS4wNT+VvYlo+1EFUBF+sMsySCDAOpDYTtDv5VE7PLObZCN4PLLbF/fFGDTYkMHi 7FrnVA9VqVq/0dfw4xzVYpEaX6zMRC7Ri2H+6iHN9Cpp/kcupGrqnMzDLsZ1cYw99DDA bRNmDFzV95dNCDUvIDjXdsJuPR+4rmtrmODnEVuNu8aXWhTOyCPOTWKL0ajyFqSJc0hQ Qgkmjh78sz9RZ0QC5punqfOhQvAU+momlhp5WzpkAnD0gRT0YWU8pNoWxui62yZRjSmW 8tYaTazua3eaoxbp3zgnQkuNdACqBC4RIRsUvVRChrJhZfeeZL8HKxIqwKgo32Zr0A4j 5WlQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:content-transfer-encoding:mime-version :user-agent:references:in-reply-to:message-id:date:subject:cc:to :from:dkim-signature; bh=WPdL1tdt86h2ttmpVztS4I+uEqx7/RGpY2Y3MPCwBCI=; b=PMU5PRsdBMJHa5yOTu7e+RSfzRL6POfB8G00KnK4n9sGEkfOKYczrNp93YWqYnGuZa 6BOe2cCbfuUtOSE7hO99OIGfi07dCRg1DlC2xHxNj84Ql7WaTwcNspoSpoQsG9+NmKW3 +WWdvjaSDrl71V082kC3qZyi9MTrIO2njXuqlTMyhd33nY+y/cLL3c9DGHpJVg59/S2C j3kzZNHuWJxNdOn6W/rak1lOnxyDRJ+8r/7GImawkyHq4mKOBrwCk/9ZP2sqK5c0vEEG Ed9ps8tAcazhmvA/glMps3t+s5dIkjW2LzU8e+SDEoDpAEFuMqUcA3FlW+YBs8/vJ/lS s1jA== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@kernel.org header.s=default header.b=brVzJsJ9; 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 f32-v6si41148508plf.65.2018.11.26.02.58.59; Mon, 26 Nov 2018 02:59:14 -0800 (PST) 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; dkim=pass header.i=@kernel.org header.s=default header.b=brVzJsJ9; 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 S1728840AbeKZVvP (ORCPT + 99 others); Mon, 26 Nov 2018 16:51:15 -0500 Received: from mail.kernel.org ([198.145.29.99]:60582 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726200AbeKZVvO (ORCPT ); Mon, 26 Nov 2018 16:51:14 -0500 Received: from localhost (5356596B.cm-6-7b.dynamic.ziggo.nl [83.86.89.107]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPSA id 388E320817; Mon, 26 Nov 2018 10:57:29 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=default; t=1543229849; bh=t2Xv3J3qgAmSqUJHrbsiVuZQFCAmkT4d+EQRIFHp3Yg=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=brVzJsJ9g55kce+igtecSwoh0Rn5IbDyyCQWloBC30FOigSAZ3SXSHuJI256ii+BM fxqfx5Y3/1XyNvHG4l4DKNtNEilULmGFzu6978I/6fNYa+P3dLSwceU0GLK9EX9+xG sZjm0TRby2XAIpkykRPzDKW06o1iNtTkv7AfvECI= From: Greg Kroah-Hartman To: linux-kernel@vger.kernel.org Cc: Greg Kroah-Hartman , stable@vger.kernel.org, Denis Bolotin , Michal Kalderon , "David S. Miller" , Sasha Levin Subject: [PATCH 4.9 24/46] qed: Fix blocking/unlimited SPQ entries leak Date: Mon, 26 Nov 2018 11:51:13 +0100 Message-Id: <20181126105048.475077429@linuxfoundation.org> X-Mailer: git-send-email 2.19.2 In-Reply-To: <20181126105045.447291262@linuxfoundation.org> References: <20181126105045.447291262@linuxfoundation.org> User-Agent: quilt/0.65 X-stable: review MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org 4.9-stable review patch. If anyone has any objections, please let me know. ------------------ [ Upstream commit 2632f22ebd08da249c2017962a199a0cfb2324bf ] When there are no SPQ entries left in the free_pool, new entries are allocated and are added to the unlimited list. When an entry in the pool is available, the content is copied from the original entry, and the new entry is sent to the device. qed_spq_post() is not aware of that, so the additional entry is stored in the original entry as p_post_ent, which can later be returned to the pool. Signed-off-by: Denis Bolotin Signed-off-by: Michal Kalderon Signed-off-by: David S. Miller Signed-off-by: Sasha Levin --- drivers/net/ethernet/qlogic/qed/qed_sp.h | 3 ++ drivers/net/ethernet/qlogic/qed/qed_spq.c | 57 ++++++++++++----------- 2 files changed, 33 insertions(+), 27 deletions(-) diff --git a/drivers/net/ethernet/qlogic/qed/qed_sp.h b/drivers/net/ethernet/qlogic/qed/qed_sp.h index b2c08e4d2a9b..bae7b7f9b1cf 100644 --- a/drivers/net/ethernet/qlogic/qed/qed_sp.h +++ b/drivers/net/ethernet/qlogic/qed/qed_sp.h @@ -132,6 +132,9 @@ struct qed_spq_entry { enum spq_mode comp_mode; struct qed_spq_comp_cb comp_cb; struct qed_spq_comp_done comp_done; /* SPQ_MODE_EBLOCK */ + + /* Posted entry for unlimited list entry in EBLOCK mode */ + struct qed_spq_entry *post_ent; }; struct qed_eq { diff --git a/drivers/net/ethernet/qlogic/qed/qed_spq.c b/drivers/net/ethernet/qlogic/qed/qed_spq.c index 9fbaf9429fd0..80c8c7f0d932 100644 --- a/drivers/net/ethernet/qlogic/qed/qed_spq.c +++ b/drivers/net/ethernet/qlogic/qed/qed_spq.c @@ -595,6 +595,8 @@ static int qed_spq_add_entry(struct qed_hwfn *p_hwfn, /* EBLOCK responsible to free the allocated p_ent */ if (p_ent->comp_mode != QED_SPQ_MODE_EBLOCK) kfree(p_ent); + else + p_ent->post_ent = p_en2; p_ent = p_en2; } @@ -678,6 +680,25 @@ static int qed_spq_pend_post(struct qed_hwfn *p_hwfn) SPQ_HIGH_PRI_RESERVE_DEFAULT); } +/* Avoid overriding of SPQ entries when getting out-of-order completions, by + * marking the completions in a bitmap and increasing the chain consumer only + * for the first successive completed entries. + */ +static void qed_spq_comp_bmap_update(struct qed_hwfn *p_hwfn, __le16 echo) +{ + u16 pos = le16_to_cpu(echo) % SPQ_RING_SIZE; + struct qed_spq *p_spq = p_hwfn->p_spq; + + __set_bit(pos, p_spq->p_comp_bitmap); + while (test_bit(p_spq->comp_bitmap_idx, + p_spq->p_comp_bitmap)) { + __clear_bit(p_spq->comp_bitmap_idx, + p_spq->p_comp_bitmap); + p_spq->comp_bitmap_idx++; + qed_chain_return_produced(&p_spq->chain); + } +} + int qed_spq_post(struct qed_hwfn *p_hwfn, struct qed_spq_entry *p_ent, u8 *fw_return_code) { @@ -728,11 +749,12 @@ int qed_spq_post(struct qed_hwfn *p_hwfn, rc = qed_spq_block(p_hwfn, p_ent, fw_return_code); if (p_ent->queue == &p_spq->unlimited_pending) { - /* This is an allocated p_ent which does not need to - * return to pool. - */ + struct qed_spq_entry *p_post_ent = p_ent->post_ent; + kfree(p_ent); - return rc; + + /* Return the entry which was actually posted */ + p_ent = p_post_ent; } if (rc) @@ -746,7 +768,7 @@ int qed_spq_post(struct qed_hwfn *p_hwfn, spq_post_fail2: spin_lock_bh(&p_spq->lock); list_del(&p_ent->list); - qed_chain_return_produced(&p_spq->chain); + qed_spq_comp_bmap_update(p_hwfn, p_ent->elem.hdr.echo); spq_post_fail: /* return to the free pool */ @@ -778,25 +800,8 @@ int qed_spq_completion(struct qed_hwfn *p_hwfn, spin_lock_bh(&p_spq->lock); list_for_each_entry_safe(p_ent, tmp, &p_spq->completion_pending, list) { if (p_ent->elem.hdr.echo == echo) { - u16 pos = le16_to_cpu(echo) % SPQ_RING_SIZE; - list_del(&p_ent->list); - - /* Avoid overriding of SPQ entries when getting - * out-of-order completions, by marking the completions - * in a bitmap and increasing the chain consumer only - * for the first successive completed entries. - */ - __set_bit(pos, p_spq->p_comp_bitmap); - - while (test_bit(p_spq->comp_bitmap_idx, - p_spq->p_comp_bitmap)) { - __clear_bit(p_spq->comp_bitmap_idx, - p_spq->p_comp_bitmap); - p_spq->comp_bitmap_idx++; - qed_chain_return_produced(&p_spq->chain); - } - + qed_spq_comp_bmap_update(p_hwfn, echo); p_spq->comp_count++; found = p_ent; break; @@ -835,11 +840,9 @@ int qed_spq_completion(struct qed_hwfn *p_hwfn, QED_MSG_SPQ, "Got a completion without a callback function\n"); - if ((found->comp_mode != QED_SPQ_MODE_EBLOCK) || - (found->queue == &p_spq->unlimited_pending)) + if (found->comp_mode != QED_SPQ_MODE_EBLOCK) /* EBLOCK is responsible for returning its own entry into the - * free list, unless it originally added the entry into the - * unlimited pending list. + * free list. */ qed_spq_return_entry(p_hwfn, found); -- 2.17.1