Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys/dev/pci Dequeue aqb from sc_atq_live even when the last ...



details:   https://anonhg.NetBSD.org/src/rev/62ce4f7149ea
branches:  trunk
changeset: 946564:62ce4f7149ea
user:      yamaguchi <yamaguchi%NetBSD.org@localhost>
date:      Tue Dec 01 04:39:03 2020 +0000

description:
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 knakahara@n.o.

diffstat:

 sys/dev/pci/if_iavf.c |  24 ++++++++++++++----------
 1 files changed, 14 insertions(+), 10 deletions(-)

diffs (59 lines):

diff -r 92b090037959 -r 62ce4f7149ea sys/dev/pci/if_iavf.c
--- a/sys/dev/pci/if_iavf.c     Tue Dec 01 04:36:05 2020 +0000
+++ b/sys/dev/pci/if_iavf.c     Tue Dec 01 04:39:03 2020 +0000
@@ -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 @@
 {
        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 @@
        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_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;
 



Home | Main Index | Thread Index | Old Index