Module Name: src
Committed By: yamaguchi
Date: Tue Dec 1 04:39:03 UTC 2020
Modified Files:
src/sys/dev/pci: if_iavf.c
Log Message:
Dequeue aqb from sc_atq_live even when the last command is failed
iavf(4) didn't dequeue aqb from sc_atq_live that is a list for
buffer in use when a command is failed by ETIMEDOUT.
This causes a panic in the following sequence:
1. enqueue an aqb to sc_atq_live at iavf_aqb_post()
2. the last command is failed by ETIMEDOUT
3. enqueue the aqb used in the failed command to sc_atq_idle
at an error handling in iavf_attach()
4. dequeue the same aqb from sc_atq_live and enqueue sc_atq_idle
again at iavf_cleanup_admin_queue()
- sc_atq_idle is broken at that time
5. free the aqb in sc_atq_idle more than once
Fix PR/55822
reviewed by [email protected].
To generate a diff of this commit:
cvs rdiff -u -r1.6 -r1.7 src/sys/dev/pci/if_iavf.c
Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.
Modified files:
Index: src/sys/dev/pci/if_iavf.c
diff -u src/sys/dev/pci/if_iavf.c:1.6 src/sys/dev/pci/if_iavf.c:1.7
--- src/sys/dev/pci/if_iavf.c:1.6 Thu Sep 17 06:34:43 2020
+++ src/sys/dev/pci/if_iavf.c Tue Dec 1 04:39:03 2020
@@ -1,4 +1,4 @@
-/* $NetBSD: if_iavf.c,v 1.6 2020/09/17 06:34:43 yamaguchi Exp $ */
+/* $NetBSD: if_iavf.c,v 1.7 2020/12/01 04:39:03 yamaguchi Exp $ */
/*
* Copyright (c) 2013-2015, Intel Corporation
@@ -75,7 +75,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: if_iavf.c,v 1.6 2020/09/17 06:34:43 yamaguchi Exp $");
+__KERNEL_RCSID(0, "$NetBSD: if_iavf.c,v 1.7 2020/12/01 04:39:03 yamaguchi Exp $");
#include <sys/param.h>
#include <sys/types.h>
@@ -4164,7 +4164,6 @@ iavf_atq_poll(struct iavf_softc *sc, uns
{
struct ixl_aq_desc *atq, *slot;
struct ixl_aq_desc iaq;
- struct ixl_aq_buf *aqb;
unsigned int prod;
unsigned int t;
int dbg;
@@ -4194,13 +4193,6 @@ iavf_atq_poll(struct iavf_softc *sc, uns
bus_dmamap_sync(sc->sc_dmat, IXL_DMA_MAP(&sc->sc_atq),
0, IXL_DMA_LEN(&sc->sc_atq), BUS_DMASYNC_PREREAD);
- aqb = iavf_aqb_get_locked(&sc->sc_atq_live);
- if (aqb != NULL) {
- bus_dmamap_sync(sc->sc_dmat, IXL_AQB_MAP(aqb),
- 0, IXL_AQB_LEN(aqb), BUS_DMASYNC_POSTWRITE);
- /* no need to do iavf_aqb_put(&sc->sc_atq_idle, aqb) */
- }
-
if (iaq.iaq_retval != htole16(IXL_AQ_RC_OK)) {
if (dbg >= 2) {
device_printf(sc->sc_dev,
@@ -4286,6 +4278,18 @@ iavf_adminq_poll_locked(struct iavf_soft
iavf_atq_post(sc, iaq, aqb);
error = iavf_atq_poll(sc, retry);
+
+ /*
+ * collect the aqb used in the current command and
+ * added to sc_atq_live at iavf_atq_post(),
+ * whether or not the command succeeded.
+ */
+ if (aqb != NULL) {
+ (void)iavf_aqb_get_locked(&sc->sc_atq_live);
+ bus_dmamap_sync(sc->sc_dmat, IXL_AQB_MAP(aqb),
+ 0, IXL_AQB_LEN(aqb), BUS_DMASYNC_POSTWRITE);
+ }
+
if (error)
return error;