From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: From: Sasha Levin To: "stable@vger.kernel.org" , "linux-kernel@vger.kernel.org" CC: Jag Raman , "David S . Miller" , Sasha Levin Subject: [PATCH AUTOSEL for 3.18 012/101] sparc64: ldc abort during vds iso boot Date: Mon, 9 Apr 2018 00:35:19 +0000 Message-ID: <20180409003505.164715-12-alexander.levin@microsoft.com> References: <20180409003505.164715-1-alexander.levin@microsoft.com> In-Reply-To: <20180409003505.164715-1-alexander.levin@microsoft.com> Content-Language: en-US Content-Type: text/plain; charset="iso-8859-1" Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Sender: linux-kernel-owner@vger.kernel.org List-ID: From: Jag Raman [ Upstream commit 6c95483b768c62f8ee933ae08a1bdbcb78b5410f ] Orabug: 20902628 When an ldc control-only packet is received during data exchange in read_nonraw(), a new rx head is calculated but the rx queue head is not actually advanced (rx_set_head() is not called) and a branch is taken to 'no_data' at which point two things can happen depending on the value of the newly calculated rx head and the current rx tail: - If the rx queue is determined to be not empty, then the wrong packet is picked up. - If the rx queue is determined to be empty, then a read error (EAGAIN) is eventually returned since it is falsely assumed that more data was expected. The fix is to update the rx head and return in case of a control only packet during data exchange. Signed-off-by: Jagannathan Raman Reviewed-by: Aaron Young Reviewed-by: Alexandre Chartre Reviewed-by: Bijan Mottahedeh Reviewed-by: Liam Merwick Signed-off-by: David S. Miller Signed-off-by: Sasha Levin --- arch/sparc/kernel/ldc.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/arch/sparc/kernel/ldc.c b/arch/sparc/kernel/ldc.c index 71762565513e..8bca543977fe 100644 --- a/arch/sparc/kernel/ldc.c +++ b/arch/sparc/kernel/ldc.c @@ -1693,9 +1693,14 @@ static int read_nonraw(struct ldc_channel *lp, void = *buf, unsigned int size) =20 lp->rcv_nxt =3D p->seqid; =20 + /* + * If this is a control-only packet, there is nothing + * else to do but advance the rx queue since the packet + * was already processed above. + */ if (!(p->type & LDC_DATA)) { new =3D rx_advance(lp, new); - goto no_data; + break; } if (p->stype & (LDC_ACK | LDC_NACK)) { err =3D data_ack_nack(lp, p); --=20 2.15.1