On Thu, Jan 22, 2015 at 11:34:47AM -0500, John Merriam wrote:
> So, what could be the problem then?  Theoretically it did work as of the
> 1.35 if_bce.c revision which seems to have shipped in OpenBSD 5.0.  This
> message:
> 
> http://marc.info/?l=openbsd-tech&m=130217668909255
> 
> seems to verify that it did actually work at one point.

It looks as if some ring descriptor data is still being allocated with
bus_dmamem_alloc(). That function probably doesn't respect the mapping
constraints bce(4) hardware requires.

This diff makes bce use the same memory allocation APIs as bwi(4) is
using. Some bwi devices have the same 1GB problem and I know the bwi
code works fine with such devices. So perhaps applying the same approach
to bce will fix your issue.

Diff is compile-tested only due to lack of hardware at my end.

Index: if_bce.c
===================================================================
RCS file: /cvs/src/sys/dev/pci/if_bce.c,v
retrieving revision 1.40
diff -u -p -r1.40 if_bce.c
--- if_bce.c    22 Dec 2014 02:28:51 -0000      1.40
+++ if_bce.c    22 Jan 2015 17:02:05 -0000
@@ -185,6 +185,13 @@ bce_probe(struct device *parent, void *m
            nitems(bce_devices)));
 }
 
+struct uvm_constraint_range bce_constraint = { 0x0, (0x40000000 - 1) };
+struct kmem_pa_mode bce_pa_mode = {
+       .kp_align = 0x1000,
+       .kp_constraint = &bce_constraint,
+       .kp_zero = 1
+};
+
 void
 bce_attach(struct device *parent, struct device *self, void *aux)
 {
@@ -194,8 +201,6 @@ bce_attach(struct device *parent, struct
        pci_intr_handle_t ih;
        const char *intrstr = NULL;
        caddr_t kva;
-       bus_dma_segment_t seg;
-       int rseg;
        struct ifnet *ifp;
        pcireg_t memtype;
        bus_addr_t memaddr;
@@ -255,9 +260,9 @@ bce_attach(struct device *parent, struct
        bce_reset(sc);
 
        /* Create the data DMA region and maps. */
-       if ((sc->bce_data = (caddr_t)uvm_km_kmemalloc_pla(kernel_map,
-           uvm.kernel_object, (BCE_NTXDESC + BCE_NRXDESC) * MCLBYTES, 0,
-           UVM_KMF_NOWAIT, 0, (paddr_t)(0x40000000 - 1), 0, 0, 1)) == NULL) {
+       sc->bce_data = (caddr_t)km_alloc((BCE_NTXDESC + BCE_NRXDESC) * MCLBYTES,
+           &kv_intrsafe, &bce_pa_mode, &kd_nowait);
+       if (sc->bce_data == NULL) {
                printf(": unable to alloc space for ring");
                return;
        }
@@ -267,8 +272,8 @@ bce_attach(struct device *parent, struct
            1, BCE_NRXDESC * MCLBYTES, 0, BUS_DMA_NOWAIT | BUS_DMA_ALLOCNOW,
            &sc->bce_rxdata_map))) {
                printf(": unable to create ring DMA map, error = %d\n", error);
-               uvm_km_free(kernel_map, (vaddr_t)sc->bce_data,
-                   (BCE_NTXDESC + BCE_NRXDESC) * MCLBYTES);
+               km_free(sc->bce_data, (BCE_NTXDESC + BCE_NRXDESC) * MCLBYTES,
+                   &kv_intrsafe, &bce_pa_mode);
                return;
        }
 
@@ -276,9 +281,9 @@ bce_attach(struct device *parent, struct
        if (bus_dmamap_load(sc->bce_dmatag, sc->bce_rxdata_map, sc->bce_data,
            BCE_NRXDESC * MCLBYTES, NULL, BUS_DMA_READ | BUS_DMA_NOWAIT)) {
                printf(": unable to load rx ring DMA map\n");
-               uvm_km_free(kernel_map, (vaddr_t)sc->bce_data,
-                   (BCE_NTXDESC + BCE_NRXDESC) * MCLBYTES);
                bus_dmamap_destroy(sc->bce_dmatag, sc->bce_rxdata_map);
+               km_free(sc->bce_data, (BCE_NTXDESC + BCE_NRXDESC) * MCLBYTES,
+                   &kv_intrsafe, &bce_pa_mode);
                return;
        }
 
@@ -287,9 +292,9 @@ bce_attach(struct device *parent, struct
            1, BCE_NTXDESC * MCLBYTES, 0, BUS_DMA_NOWAIT | BUS_DMA_ALLOCNOW,
            &sc->bce_txdata_map))) {
                printf(": unable to create ring DMA map, error = %d\n", error);
-               uvm_km_free(kernel_map, (vaddr_t)sc->bce_data,
-                   (BCE_NTXDESC + BCE_NRXDESC) * MCLBYTES);
                bus_dmamap_destroy(sc->bce_dmatag, sc->bce_rxdata_map);
+               km_free(sc->bce_data, (BCE_NTXDESC + BCE_NRXDESC) * MCLBYTES,
+                   &kv_intrsafe, &bce_pa_mode);
                return;
        }
 
@@ -298,10 +303,10 @@ bce_attach(struct device *parent, struct
            sc->bce_data + BCE_NRXDESC * MCLBYTES,
            BCE_NTXDESC * MCLBYTES, NULL, BUS_DMA_WRITE | BUS_DMA_NOWAIT)) {
                printf(": unable to load tx ring DMA map\n");
-               uvm_km_free(kernel_map, (vaddr_t)sc->bce_data,
-                   (BCE_NTXDESC + BCE_NRXDESC) * MCLBYTES);
                bus_dmamap_destroy(sc->bce_dmatag, sc->bce_rxdata_map);
                bus_dmamap_destroy(sc->bce_dmatag, sc->bce_txdata_map);
+               km_free(sc->bce_data, (BCE_NTXDESC + BCE_NRXDESC) * MCLBYTES,
+                   &kv_intrsafe, &bce_pa_mode);
                return;
        }
 
@@ -315,26 +320,14 @@ bce_attach(struct device *parent, struct
         * XXX PAGE_SIZE is wasteful; we only need 1KB + 1KB, but
         * due to the limition above. ??
         */
-       if ((error = bus_dmamem_alloc(sc->bce_dmatag, 2 * PAGE_SIZE,
-           PAGE_SIZE, 2 * PAGE_SIZE, &seg, 1, &rseg, BUS_DMA_NOWAIT))) {
-               printf(": unable to alloc space for ring descriptors, "
-                   "error = %d\n", error);
-               uvm_km_free(kernel_map, (vaddr_t)sc->bce_data,
-                   (BCE_NTXDESC + BCE_NRXDESC) * MCLBYTES);
-               bus_dmamap_destroy(sc->bce_dmatag, sc->bce_rxdata_map);
-               bus_dmamap_destroy(sc->bce_dmatag, sc->bce_txdata_map);
-               return;
-       }
-
-       /* map ring space to kernel */
-       if ((error = bus_dmamem_map(sc->bce_dmatag, &seg, rseg,
-           2 * PAGE_SIZE, &kva, BUS_DMA_NOWAIT))) {
-               printf(": unable to map DMA buffers, error = %d\n", error);
-               uvm_km_free(kernel_map, (vaddr_t)sc->bce_data,
-                   (BCE_NTXDESC + BCE_NRXDESC) * MCLBYTES);
+       kva = (caddr_t)km_alloc(2 * PAGE_SIZE, &kv_intrsafe, &bce_pa_mode,
+           &kd_nowait);
+       if (kva == NULL) {
+               printf(": unable to alloc space for ring descriptors\b");
                bus_dmamap_destroy(sc->bce_dmatag, sc->bce_rxdata_map);
                bus_dmamap_destroy(sc->bce_dmatag, sc->bce_txdata_map);
-               bus_dmamem_free(sc->bce_dmatag, &seg, rseg);
+               km_free(sc->bce_data, (BCE_NTXDESC + BCE_NRXDESC) * MCLBYTES,
+                   &kv_intrsafe, &bce_pa_mode);
                return;
        }
 
@@ -342,11 +335,11 @@ bce_attach(struct device *parent, struct
        if ((error = bus_dmamap_create(sc->bce_dmatag, 2 * PAGE_SIZE, 1,
            2 * PAGE_SIZE, 0, BUS_DMA_NOWAIT, &sc->bce_ring_map))) {
                printf(": unable to create ring DMA map, error = %d\n", error);
-               uvm_km_free(kernel_map, (vaddr_t)sc->bce_data,
-                   (BCE_NTXDESC + BCE_NRXDESC) * MCLBYTES);
                bus_dmamap_destroy(sc->bce_dmatag, sc->bce_rxdata_map);
                bus_dmamap_destroy(sc->bce_dmatag, sc->bce_txdata_map);
-               bus_dmamem_free(sc->bce_dmatag, &seg, rseg);
+               km_free(sc->bce_data, (BCE_NTXDESC + BCE_NRXDESC) * MCLBYTES,
+                   &kv_intrsafe, &bce_pa_mode);
+               km_free(kva, 2 * PAGE_SIZE, &kv_intrsafe, &bce_pa_mode);
                return;
        }
 
@@ -354,12 +347,12 @@ bce_attach(struct device *parent, struct
        if (bus_dmamap_load(sc->bce_dmatag, sc->bce_ring_map, kva,
            2 * PAGE_SIZE, NULL, BUS_DMA_NOWAIT)) {
                printf(": unable to load ring DMA map\n");
-               uvm_km_free(kernel_map, (vaddr_t)sc->bce_data,
-                   (BCE_NTXDESC + BCE_NRXDESC) * MCLBYTES);
                bus_dmamap_destroy(sc->bce_dmatag, sc->bce_rxdata_map);
                bus_dmamap_destroy(sc->bce_dmatag, sc->bce_txdata_map);
                bus_dmamap_destroy(sc->bce_dmatag, sc->bce_ring_map);
-               bus_dmamem_free(sc->bce_dmatag, &seg, rseg);
+               km_free(sc->bce_data, (BCE_NTXDESC + BCE_NRXDESC) * MCLBYTES,
+                   &kv_intrsafe, &bce_pa_mode);
+               km_free(kva, 2 * PAGE_SIZE, &kv_intrsafe, &bce_pa_mode);
                return;
        }
 

Reply via email to