Module Name:    src
Committed By:   christos
Date:           Fri Apr 23 20:56:20 UTC 2010

Modified Files:
        src/sys/dev/pci: if_iwn.c if_iwnvar.h

Log Message:
Align usage of *free and *alloc and clean up the firmware read code.
This fixes two panics that occur for kernels compiled with DIAGNOSTIC and
DEBUG. From Sverre Froyen


To generate a diff of this commit:
cvs rdiff -u -r1.41 -r1.42 src/sys/dev/pci/if_iwn.c
cvs rdiff -u -r1.9 -r1.10 src/sys/dev/pci/if_iwnvar.h

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_iwn.c
diff -u src/sys/dev/pci/if_iwn.c:1.41 src/sys/dev/pci/if_iwn.c:1.42
--- src/sys/dev/pci/if_iwn.c:1.41	Sat Apr 17 11:57:22 2010
+++ src/sys/dev/pci/if_iwn.c	Fri Apr 23 16:56:20 2010
@@ -1,4 +1,4 @@
-/*	$NetBSD: if_iwn.c,v 1.41 2010/04/17 15:57:22 christos Exp $	*/
+/*	$NetBSD: if_iwn.c,v 1.42 2010/04/23 20:56:20 christos Exp $	*/
 /*	$OpenBSD: if_iwn.c,v 1.88 2010/04/10 08:37:36 damien Exp $	*/
 
 /*-
@@ -22,7 +22,7 @@
  * adapters.
  */
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: if_iwn.c,v 1.41 2010/04/17 15:57:22 christos Exp $");
+__KERNEL_RCSID(0, "$NetBSD: if_iwn.c,v 1.42 2010/04/23 20:56:20 christos Exp $");
 
 #define IWN_USE_RBUF	/* Use local storage for RX */
 #undef IWN_HWCRYPTO	/* XXX does not even compile yet */
@@ -1764,7 +1764,7 @@
 static struct ieee80211_node *
 iwn_node_alloc(struct ieee80211_node_table *ic __unused)
 {
-	return malloc(sizeof (struct iwn_node), M_DEVBUF, M_NOWAIT | M_ZERO);
+	return malloc(sizeof (struct iwn_node), M_80211_NODE, M_NOWAIT | M_ZERO);
 }
 
 static void
@@ -5577,6 +5577,10 @@
 	size_t size;
 	int error;
 
+	/* Initialize for error returns */
+	fw->data = NULL;
+	fw->datasz = 0;
+
 	/* Open firmware image. */
 	if ((error = firmware_open("if_iwn", sc->fwname, &fwh)) != 0) {
 		aprint_error_dev(sc->sc_dev,
@@ -5587,7 +5591,6 @@
 	if (size < 28) {
 		aprint_error_dev(sc->sc_dev,
 		    "truncated firmware header: %zu bytes\n", size);
-		free(fw->data, M_DEVBUF);
 		firmware_close(fwh);
 		return EINVAL;
 	}
@@ -5600,12 +5603,13 @@
 		firmware_close(fwh);
 		return ENOMEM;
 	}
-	if ((error = firmware_read(fwh, 0, fw->data, size)) != 0) {
+	error = firmware_read(fwh, 0, fw->data, size);
+	firmware_close(fwh);
+	fw->datasz = size;
+	if (error != 0) {
 		aprint_error_dev(sc->sc_dev,
 		    "could not read firmware %s\n", sc->fwname);
-		firmware_free(fw->data, size);
-		firmware_close(fwh);
-		return error;
+		goto out;
 	}
 
 	/* Process firmware header. */
@@ -5615,9 +5619,8 @@
 	if (IWN_FW_API(rev) <= 1) {
 		aprint_error_dev(sc->sc_dev,
 		    "bad firmware, need API version >=2\n");
-		firmware_free(fw->data, size);
-		firmware_close(fwh);
-		return EINVAL;
+		firmware_free(fw->data, fw->datasz);
+		goto out;
 	}
 	if (IWN_FW_API(rev) >= 3) {
 		/* Skip build number (version 2 header). */
@@ -5640,9 +5643,7 @@
 	    (fw->boot.textsz & 3) != 0) {
 		aprint_error_dev(sc->sc_dev,
 		    "invalid firmware header\n");
-		firmware_free(fw->data, size);
-		firmware_close(fwh);
-		return EINVAL;
+		goto out;
 	}
 
 	/* Check that all firmware sections fit. */
@@ -5650,9 +5651,7 @@
 	    fw->init.datasz + fw->boot.textsz > size) {
 		aprint_error_dev(sc->sc_dev,
 		    "firmware file too short: %zu bytes\n", size);
-		firmware_free(fw->data, size);
-		firmware_close(fwh);
-		return EINVAL;
+		goto out;
 	}
 
 	/* Get pointers to firmware sections. */
@@ -5663,6 +5662,11 @@
 	fw->boot.text = fw->init.data + fw->init.datasz;
 
 	return 0;
+out:
+	firmware_free(fw->data, fw->datasz);
+	fw->data = NULL;
+	fw->datasz = 0;
+	return error ? error : EINVAL;
 }
 
 static int
@@ -6054,8 +6058,11 @@
 	sc->sc_flags &= ~IWN_FLAG_USE_ICT;
 
 	/* Initialize hardware and upload firmware. */
+	KASSERT(sc->fw.data != NULL && sc->fw.datasz > 0);
 	error = iwn_hw_init(sc);
-	free(sc->fw.data, M_DEVBUF);
+	firmware_free(sc->fw.data, sc->fw.datasz);
+	sc->fw.data = NULL;
+	sc->fw.datasz = 0;
 	if (error != 0) {
 		aprint_error_dev(sc->sc_dev,
 		    "could not initialize hardware\n");

Index: src/sys/dev/pci/if_iwnvar.h
diff -u src/sys/dev/pci/if_iwnvar.h:1.9 src/sys/dev/pci/if_iwnvar.h:1.10
--- src/sys/dev/pci/if_iwnvar.h:1.9	Thu Apr 15 21:40:41 2010
+++ src/sys/dev/pci/if_iwnvar.h	Fri Apr 23 16:56:20 2010
@@ -1,4 +1,4 @@
-/*	$NetBSD: if_iwnvar.h,v 1.9 2010/04/16 01:40:41 christos Exp $	*/
+/*	$NetBSD: if_iwnvar.h,v 1.10 2010/04/23 20:56:20 christos Exp $	*/
 /*	$OpenBSD: if_iwnvar.h,v 1.17 2010/02/17 18:23:00 damien Exp $	*/
 
 /*-
@@ -168,6 +168,7 @@
 
 struct iwn_fw_info {
 	u_char			*data;
+	uint32_t		datasz;
 	struct iwn_fw_part	init;
 	struct iwn_fw_part	main;
 	struct iwn_fw_part	boot;

Reply via email to