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; }