kernel - Replace broken mp lock in bounce pages swi_vm() with spinlock
authorMatthew Dillon <dillon@apollo.backplane.com>
Wed, 1 Dec 2010 06:01:15 +0000 (22:01 -0800)
committerMatthew Dillon <dillon@apollo.backplane.com>
Wed, 1 Dec 2010 06:01:15 +0000 (22:01 -0800)
* Replace old non-MPSAFE crit section and mplock code with a spinlock

* x86-64 was not registering swi_vm(), add that code in.

Reported-by: Venkatesh Srinivas <me@endeavour.zapto.org>
sys/platform/pc32/i386/busdma_machdep.c
sys/platform/pc64/x86_64/busdma_machdep.c
sys/platform/pc64/x86_64/vm_machdep.c

index 386c4b0..c656159 100644 (file)
@@ -166,6 +166,8 @@ struct bus_dmamap {
 
 static STAILQ_HEAD(, bus_dmamap) bounce_map_callbacklist =
        STAILQ_HEAD_INITIALIZER(bounce_map_callbacklist);
+static struct spinlock bounce_map_list_spin =
+       SPINLOCK_INITIALIZER(&bounce_map_list_spin);
 
 static struct bus_dmamap nobounce_dmamap;
 
@@ -1334,14 +1336,11 @@ get_map_waiting(bus_dma_tag_t dmat)
 static void
 add_map_callback(bus_dmamap_t map)
 {
-       /* XXX callbacklist is not MPSAFE */
-       crit_enter();
-       get_mplock();
+       spin_lock(&bounce_map_list_spin);
        STAILQ_INSERT_TAIL(&bounce_map_callbacklist, map, links);
        busdma_swi_pending = 1;
        setsoftvm();
-       rel_mplock();
-       crit_exit();
+       spin_unlock(&bounce_map_list_spin);
 }
 
 void
@@ -1349,13 +1348,13 @@ busdma_swi(void)
 {
        bus_dmamap_t map;
 
-       crit_enter();
+       spin_lock(&bounce_map_list_spin);
        while ((map = STAILQ_FIRST(&bounce_map_callbacklist)) != NULL) {
                STAILQ_REMOVE_HEAD(&bounce_map_callbacklist, links);
-               crit_exit();
+               spin_unlock(&bounce_map_list_spin);
                bus_dmamap_load(map->dmat, map, map->buf, map->buflen,
                                map->callback, map->callback_arg, /*flags*/0);
-               crit_enter();
+               spin_lock(&bounce_map_list_spin);
        }
-       crit_exit();
+       spin_unlock(&bounce_map_list_spin);
 }
index 10d4c5e..9f3f557 100644 (file)
@@ -166,6 +166,8 @@ struct bus_dmamap {
 
 static STAILQ_HEAD(, bus_dmamap) bounce_map_callbacklist =
        STAILQ_HEAD_INITIALIZER(bounce_map_callbacklist);
+static struct spinlock bounce_map_list_spin =
+       SPINLOCK_INITIALIZER(&bounce_map_list_spin);
 
 static struct bus_dmamap nobounce_dmamap;
 
@@ -1334,14 +1336,11 @@ get_map_waiting(bus_dma_tag_t dmat)
 static void
 add_map_callback(bus_dmamap_t map)
 {
-       /* XXX callbacklist is not MPSAFE */
-       crit_enter();
-       get_mplock();
+       spin_lock(&bounce_map_list_spin);
        STAILQ_INSERT_TAIL(&bounce_map_callbacklist, map, links);
        busdma_swi_pending = 1;
        setsoftvm();
-       rel_mplock();
-       crit_exit();
+       spin_unlock(&bounce_map_list_spin);
 }
 
 void
@@ -1349,13 +1348,13 @@ busdma_swi(void)
 {
        bus_dmamap_t map;
 
-       crit_enter();
+       spin_lock(&bounce_map_list_spin);
        while ((map = STAILQ_FIRST(&bounce_map_callbacklist)) != NULL) {
                STAILQ_REMOVE_HEAD(&bounce_map_callbacklist, links);
-               crit_exit();
+               spin_unlock(&bounce_map_list_spin);
                bus_dmamap_load(map->dmat, map, map->buf, map->buflen,
                                map->callback, map->callback_arg, /*flags*/0);
-               crit_enter();
+               spin_lock(&bounce_map_list_spin);
        }
-       crit_exit();
+       spin_unlock(&bounce_map_list_spin);
 }
index ec48299..772f567 100644 (file)
@@ -351,6 +351,22 @@ kvtop(void *addr)
        return (pa);
 }
 
+static void
+swi_vm(void *arg, void *frame)
+{
+       if (busdma_swi_pending != 0)
+               busdma_swi();
+}
+
+static void
+swi_vm_setup(void *arg)
+{
+       register_swi(SWI_VM, swi_vm, NULL, "swi_vm", NULL);
+}
+
+SYSINIT(vm_setup, SI_BOOT2_MACHDEP, SI_ORDER_ANY, swi_vm_setup, NULL);
+
+
 /*
  * Tell whether this address is in some physical memory region.
  * Currently used by the kernel coredump code in order to avoid