Module Name:    src
Committed By:   sborrill
Date:           Fri Feb 21 10:41:06 UTC 2014

Modified Files:
        src/sys/dev/usb [netbsd-6]: umass.c umassvar.h usb_mem.c

Log Message:
Pull up the following revisions(s) (requested by mlelstv in ticket #1032):
        sys/dev/usb/umass.c:    revision 1.148
        sys/dev/usb/umassvar.h: revision 1.35
        sys/dev/usb/usb_mem.c:  revision 1.64

Fix problem where umass might allocate buffers in interrupt context which
causes it to fail or a DIAGNOSTIC kernel to panic.


To generate a diff of this commit:
cvs rdiff -u -r1.141 -r1.141.10.1 src/sys/dev/usb/umass.c
cvs rdiff -u -r1.31 -r1.31.10.1 src/sys/dev/usb/umassvar.h
cvs rdiff -u -r1.51 -r1.51.2.1 src/sys/dev/usb/usb_mem.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/usb/umass.c
diff -u src/sys/dev/usb/umass.c:1.141 src/sys/dev/usb/umass.c:1.141.10.1
--- src/sys/dev/usb/umass.c:1.141	Wed Aug 24 11:28:50 2011
+++ src/sys/dev/usb/umass.c	Fri Feb 21 10:41:06 2014
@@ -1,4 +1,4 @@
-/*	$NetBSD: umass.c,v 1.141 2011/08/24 11:28:50 mbalmer Exp $	*/
+/*	$NetBSD: umass.c,v 1.141.10.1 2014/02/21 10:41:06 sborrill Exp $	*/
 
 /*
  * Copyright (c) 2003 The NetBSD Foundation, Inc.
@@ -124,7 +124,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: umass.c,v 1.141 2011/08/24 11:28:50 mbalmer Exp $");
+__KERNEL_RCSID(0, "$NetBSD: umass.c,v 1.141.10.1 2014/02/21 10:41:06 sborrill Exp $");
 
 #ifdef _KERNEL_OPT
 #include "opt_umass.h"
@@ -310,7 +310,7 @@ umass_attach(device_t parent, device_t s
 	const char *sWire, *sCommand;
 	char *devinfop;
 	usbd_status err;
-	int i, bno, error;
+	int i, error;
 
 	sc->sc_dev = self;
 
@@ -563,29 +563,54 @@ umass_attach(device_t parent, device_t s
 			return;
 		}
 	}
-	/* Allocate buffer for data transfer (it's huge). */
+	/* Allocate buffer for data transfer (it's huge), command and
+	   status data here as auto allocation cannot happen in interrupt
+	   context */
 	switch (sc->sc_wire) {
 	case UMASS_WPROTO_BBB:
-		bno = XFER_BBB_DATA;
-		goto dalloc;
+		sc->data_buffer = usbd_alloc_buffer(
+			sc->transfer_xfer[XFER_BBB_DATA],
+			UMASS_MAX_TRANSFER_SIZE);
+		sc->cmd_buffer = usbd_alloc_buffer(
+			sc->transfer_xfer[XFER_BBB_CBW],
+			UMASS_BBB_CBW_SIZE);
+		sc->s1_buffer = usbd_alloc_buffer(
+			sc->transfer_xfer[XFER_BBB_CSW1],
+			UMASS_BBB_CSW_SIZE);
+		sc->s2_buffer = usbd_alloc_buffer(
+			sc->transfer_xfer[XFER_BBB_CSW2],
+			UMASS_BBB_CSW_SIZE);
+		break;
 	case UMASS_WPROTO_CBI:
-		bno = XFER_CBI_DATA;
-		goto dalloc;
 	case UMASS_WPROTO_CBI_I:
-		bno = XFER_CBI_DATA;
-	dalloc:
-		sc->data_buffer = usbd_alloc_buffer(sc->transfer_xfer[bno],
-						    UMASS_MAX_TRANSFER_SIZE);
-		if (sc->data_buffer == NULL) {
-			aprint_error_dev(self, "no buffer memory\n");
-			umass_disco(sc);
-			return;
-		}
+		sc->data_buffer = usbd_alloc_buffer(
+			sc->transfer_xfer[XFER_CBI_DATA],
+			UMASS_MAX_TRANSFER_SIZE);
+		sc->cmd_buffer = usbd_alloc_buffer(
+			sc->transfer_xfer[XFER_CBI_CB],
+			sizeof(sc->cbl));
+		sc->s1_buffer = usbd_alloc_buffer(
+			sc->transfer_xfer[XFER_CBI_STATUS],
+			sizeof(sc->sbl));
+		sc->s2_buffer = usbd_alloc_buffer(
+			sc->transfer_xfer[XFER_CBI_RESET1],
+			sizeof(sc->cbl));
 		break;
 	default:
 		break;
 	}
 
+	if (sc->data_buffer == NULL || sc->cmd_buffer == NULL
+	    || sc->s1_buffer == NULL || sc->s2_buffer == NULL) {
+		/*
+		 * partially preallocated buffers are freed with
+		 * the xfer structures
+		 */
+		aprint_error_dev(self, "no buffer memory\n");
+		umass_disco(sc);
+		return;
+	}
+
 	/* Initialise the wire protocol specific methods */
 	switch (sc->sc_wire) {
 	case UMASS_WPROTO_BBB:

Index: src/sys/dev/usb/umassvar.h
diff -u src/sys/dev/usb/umassvar.h:1.31 src/sys/dev/usb/umassvar.h:1.31.10.1
--- src/sys/dev/usb/umassvar.h:1.31	Sun Jul 31 16:32:02 2011
+++ src/sys/dev/usb/umassvar.h	Fri Feb 21 10:41:06 2014
@@ -1,4 +1,4 @@
-/*	$NetBSD: umassvar.h,v 1.31 2011/07/31 16:32:02 jakllsch Exp $	*/
+/*	$NetBSD: umassvar.h,v 1.31.10.1 2014/02/21 10:41:06 sborrill Exp $	*/
 /*-
  * Copyright (c) 1999 MAEKAWA Masahide <bis...@rr.iij4u.or.jp>,
  *		      Nick Hibma <n_hi...@freebsd.org>
@@ -223,6 +223,9 @@ struct umass_softc {
 	usbd_xfer_handle	transfer_xfer[XFER_NR]; /* for ctrl xfers */
 
 	void			*data_buffer;
+	void			*cmd_buffer;
+	void			*s1_buffer;
+	void			*s2_buffer;
 
 	int			transfer_dir;		/* data direction */
 	void			*transfer_data;		/* data buffer */

Index: src/sys/dev/usb/usb_mem.c
diff -u src/sys/dev/usb/usb_mem.c:1.51 src/sys/dev/usb/usb_mem.c:1.51.2.1
--- src/sys/dev/usb/usb_mem.c:1.51	Fri Jan 27 18:53:09 2012
+++ src/sys/dev/usb/usb_mem.c	Fri Feb 21 10:41:06 2014
@@ -1,4 +1,4 @@
-/*	$NetBSD: usb_mem.c,v 1.51 2012/01/27 18:53:09 para Exp $	*/
+/*	$NetBSD: usb_mem.c,v 1.51.2.1 2014/02/21 10:41:06 sborrill Exp $	*/
 
 /*
  * Copyright (c) 1998 The NetBSD Foundation, Inc.
@@ -38,7 +38,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: usb_mem.c,v 1.51 2012/01/27 18:53:09 para Exp $");
+__KERNEL_RCSID(0, "$NetBSD: usb_mem.c,v 1.51.2.1 2014/02/21 10:41:06 sborrill Exp $");
 
 #ifdef _KERNEL_OPT
 #include "opt_usb.h"
@@ -115,7 +115,7 @@ usb_block_allocmem(bus_dma_tag_t tag, si
 	DPRINTFN(5, ("usb_block_allocmem: size=%zu align=%zu\n", size, align));
 
 #ifdef DIAGNOSTIC
-	if (cpu_intr_p()) {
+	if (cpu_softintr_p() || cpu_intr_p()) {
 		printf("usb_block_allocmem: in interrupt context, size=%lu\n",
 		    (unsigned long) size);
 	}
@@ -137,7 +137,7 @@ usb_block_allocmem(bus_dma_tag_t tag, si
 	splx(s);
 
 #ifdef DIAGNOSTIC
-	if (cpu_intr_p()) {
+	if (cpu_softintr_p() || cpu_intr_p()) {
 		printf("usb_block_allocmem: in interrupt context, failed\n");
 		return (USBD_NOMEM);
 	}
@@ -194,7 +194,7 @@ void
 usb_block_real_freemem(usb_dma_block_t *b)
 {
 #ifdef DIAGNOSTIC
-	if (cpu_intr_p()) {
+	if (cpu_softintr_p() || cpu_intr_p()) {
 		printf("usb_block_real_freemem: in interrupt context\n");
 		return;
 	}

Reply via email to