Module Name:    src
Committed By:   riastradh
Date:           Wed Jun 11 17:15:18 UTC 2014

Modified Files:
        src/sys/dev/pci: agp_i810.c

Log Message:
Fix various mistakes in yesterday's commit.

- Set mem->am_nseg, particularly before trying to use it.
- Avoid error-prone local copies in agp_i810_bind_memory_main.
- Omit missing DMA unload/free in agp_i810_unbind_memory.


To generate a diff of this commit:
cvs rdiff -u -r1.93 -r1.94 src/sys/dev/pci/agp_i810.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/agp_i810.c
diff -u src/sys/dev/pci/agp_i810.c:1.93 src/sys/dev/pci/agp_i810.c:1.94
--- src/sys/dev/pci/agp_i810.c:1.93	Wed Jun 11 17:02:09 2014
+++ src/sys/dev/pci/agp_i810.c	Wed Jun 11 17:15:18 2014
@@ -1,4 +1,4 @@
-/*	$NetBSD: agp_i810.c,v 1.93 2014/06/11 17:02:09 riastradh Exp $	*/
+/*	$NetBSD: agp_i810.c,v 1.94 2014/06/11 17:15:18 riastradh Exp $	*/
 
 /*-
  * Copyright (c) 2000 Doug Rabson
@@ -30,7 +30,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: agp_i810.c,v 1.93 2014/06/11 17:02:09 riastradh Exp $");
+__KERNEL_RCSID(0, "$NetBSD: agp_i810.c,v 1.94 2014/06/11 17:15:18 riastradh Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -1266,8 +1266,7 @@ agp_i810_bind_memory_main(struct agp_sof
     off_t offset)
 {
 	struct agp_i810_softc *const isc = sc->as_chipc;
-	bus_dma_segment_t *segs;
-	int nseg_alloc, nseg;
+	int nseg;
 	uint32_t i, j;
 	unsigned seg;
 	bus_addr_t addr;
@@ -1286,29 +1285,30 @@ agp_i810_bind_memory_main(struct agp_sof
 		return EINVAL;
 
 	/* Allocate an array of DMA segments.  */
-	nseg_alloc = (mem->am_size >> AGP_PAGE_SHIFT);
-	if (nseg_alloc > (SIZE_MAX / sizeof(*segs))) {
+	nseg = (mem->am_size >> AGP_PAGE_SHIFT);
+	if (nseg > (SIZE_MAX / sizeof(*mem->am_dmaseg))) {
 		error = ENOMEM;
 		goto fail0;
 	}
-	segs = malloc(nseg_alloc * sizeof(*segs), M_AGP, M_WAITOK);
+	mem->am_dmaseg = malloc(nseg*sizeof(*mem->am_dmaseg), M_AGP, M_WAITOK);
 
 	/* Allocate DMA-safe physical segments.  */
 	error = bus_dmamem_alloc(sc->as_dmat, mem->am_size, PAGE_SIZE,
-	    0, segs, nseg_alloc, &nseg, BUS_DMA_WAITOK);
+	    0, mem->am_dmaseg, nseg, &mem->am_nseg, BUS_DMA_WAITOK);
 	if (error)
 		goto fail1;
-	KASSERT(nseg <= nseg_alloc);
+	KASSERT(mem->am_nseg <= nseg);
 
 	/* Shrink the array of DMA segments if we can.  */
-	if (nseg < nseg_alloc) {
-		segs = realloc(segs, nseg, M_AGP, M_WAITOK);
-		nseg_alloc = nseg;
+	if (mem->am_nseg < nseg) {
+		mem->am_dmaseg = realloc(mem->am_dmaseg, mem->am_nseg, M_AGP,
+		    M_WAITOK);
+		nseg = mem->am_nseg;
 	}
 
 	/* Load the DMA map.  */
 	error = bus_dmamap_load_raw(sc->as_dmat, mem->am_dmamap,
-	    segs, mem->am_nseg, mem->am_size, BUS_DMA_WAITOK);
+	    mem->am_dmaseg, mem->am_nseg, mem->am_size, BUS_DMA_WAITOK);
 	if (error)
 		goto fail2;
 
@@ -1334,15 +1334,16 @@ agp_i810_bind_memory_main(struct agp_sof
 	}
 
 	/* Success!  */
-	mem->am_dmaseg = segs;
 	mem->am_offset = offset;
 	return 0;
 
 fail3:	for (j = 0; j < i; j += AGP_PAGE_SIZE)
 		(void)agp_i810_unbind_page(sc, offset + j);
 	bus_dmamap_unload(sc->as_dmat, mem->am_dmamap);
-fail2:	bus_dmamem_free(sc->as_dmat, segs, nseg_alloc);
-fail1:	free(segs, M_AGP);
+fail2:	bus_dmamem_free(sc->as_dmat, mem->am_dmaseg, mem->am_nseg);
+fail1:	free(mem->am_dmaseg, M_AGP);
+	mem->am_dmaseg = NULL;
+	mem->am_nseg = 0;
 fail0:	KASSERT(error);
 	return error;
 }
@@ -1412,15 +1413,23 @@ agp_i810_unbind_memory(struct agp_softc 
 
 	switch (mem->am_type) {
 	case AGP_I810_MEMTYPE_MAIN:
-	case AGP_I810_MEMTYPE_HWCURSOR:
 		for (i = 0; i < mem->am_size; i += AGP_PAGE_SIZE)
 			(void)agp_i810_unbind_page(sc, mem->am_offset + i);
+		bus_dmamap_unload(sc->as_dmat, mem->am_dmamap);
+		bus_dmamem_free(sc->as_dmat, mem->am_dmaseg, mem->am_nseg);
+		free(mem->am_dmaseg, M_AGP);
+		mem->am_offset = 0;
 		break;
 	case AGP_I810_MEMTYPE_DCACHE:
 		KASSERT(isc->chiptype == CHIP_I810);
 		for (i = 0; i < mem->am_size; i += AGP_PAGE_SIZE)
 			(void)agp_i810_write_gtt_entry(isc, i, 0);
 		break;
+	case AGP_I810_MEMTYPE_HWCURSOR:
+		for (i = 0; i < mem->am_size; i += AGP_PAGE_SIZE)
+			(void)agp_i810_unbind_page(sc, mem->am_offset + i);
+		mem->am_offset = 0;
+		break;
 	default:
 		panic("invalid agp i810 memory type: %d", mem->am_type);
 	}

Reply via email to