Module Name: src
Committed By: mrg
Date: Mon Feb 20 03:25:33 UTC 2012
Modified Files:
src/sys/dev/usb [jmcneill-usbmp]: usb_mem.c
Log Message:
convert splusb() calls to using a new usb_blk_lock.
To generate a diff of this commit:
cvs rdiff -u -r1.50.6.1 -r1.50.6.2 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/usb_mem.c
diff -u src/sys/dev/usb/usb_mem.c:1.50.6.1 src/sys/dev/usb/usb_mem.c:1.50.6.2
--- src/sys/dev/usb/usb_mem.c:1.50.6.1 Sat Feb 18 07:35:11 2012
+++ src/sys/dev/usb/usb_mem.c Mon Feb 20 03:25:33 2012
@@ -1,4 +1,4 @@
-/* $NetBSD: usb_mem.c,v 1.50.6.1 2012/02/18 07:35:11 mrg Exp $ */
+/* $NetBSD: usb_mem.c,v 1.50.6.2 2012/02/20 03:25:33 mrg 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.50.6.1 2012/02/18 07:35:11 mrg Exp $");
+__KERNEL_RCSID(0, "$NetBSD: usb_mem.c,v 1.50.6.2 2012/02/20 03:25:33 mrg Exp $");
#ifdef _KERNEL_OPT
#include "opt_usb.h"
@@ -52,6 +52,7 @@ __KERNEL_RCSID(0, "$NetBSD: usb_mem.c,v
#include <sys/device.h> /* for usbdivar.h */
#include <sys/bus.h>
#include <sys/cpu.h>
+#include <sys/once.h>
#ifdef __NetBSD__
#include <sys/extent.h>
@@ -93,6 +94,8 @@ Static void usb_block_freemem(usb_dma_b
LIST_HEAD(usb_dma_block_qh, usb_dma_block);
Static struct usb_dma_block_qh usb_blk_freelist =
LIST_HEAD_INITIALIZER(usb_blk_freelist);
+kmutex_t usb_blk_lock;
+
#ifdef DEBUG
Static struct usb_dma_block_qh usb_blk_fraglist =
LIST_HEAD_INITIALIZER(usb_blk_fraglist);
@@ -104,13 +107,22 @@ Static u_int usb_blk_nfree = 0;
Static LIST_HEAD(, usb_frag_dma) usb_frag_freelist =
LIST_HEAD_INITIALIZER(usb_frag_freelist);
+Static int usb_mem_init(void);
+
+Static int
+usb_mem_init(void)
+{
+
+ mutex_init(&usb_blk_lock, MUTEX_DEFAULT, IPL_NONE);
+ return 0;
+}
+
Static usbd_status
usb_block_allocmem(bus_dma_tag_t tag, size_t size, size_t align,
usb_dma_block_t **dmap)
{
usb_dma_block_t *b;
int error;
- int s;
DPRINTFN(5, ("usb_block_allocmem: size=%zu align=%zu\n", size, align));
@@ -121,20 +133,19 @@ usb_block_allocmem(bus_dma_tag_t tag, si
}
#endif
- s = splusb();
+ KASSERT(mutex_owned(&usb_blk_lock));
+
/* First check the free list. */
LIST_FOREACH(b, &usb_blk_freelist, next) {
if (b->tag == tag && b->size >= size && b->align >= align) {
LIST_REMOVE(b, next);
usb_blk_nfree--;
- splx(s);
*dmap = b;
DPRINTFN(6,("usb_block_allocmem: free list size=%zu\n",
b->size));
return (USBD_NORMAL_COMPLETION);
}
}
- splx(s);
#ifdef DIAGNOSTIC
if (cpu_intr_p()) {
@@ -228,16 +239,15 @@ usb_valid_block_p(usb_dma_block_t *b, st
Static void
usb_block_freemem(usb_dma_block_t *b)
{
- int s;
+
+ KASSERT(mutex_owned(&usb_blk_lock));
DPRINTFN(6, ("usb_block_freemem: size=%zu\n", b->size));
- s = splusb();
#ifdef DEBUG
LIST_REMOVE(b, next);
#endif
LIST_INSERT_HEAD(&usb_blk_freelist, b, next);
usb_blk_nfree++;
- splx(s);
}
usbd_status
@@ -248,12 +258,15 @@ usb_allocmem(usbd_bus_handle bus, size_t
struct usb_frag_dma *f;
usb_dma_block_t *b;
int i;
- int s;
+ static ONCE_DECL(init_control);
+
+ RUN_ONCE(&init_control, usb_mem_init);
/* If the request is large then just use a full block. */
if (size > USB_MEM_SMALL || align > USB_MEM_SMALL) {
DPRINTFN(1, ("usb_allocmem: large alloc %d\n", (int)size));
size = (size + USB_MEM_BLOCK - 1) & ~(USB_MEM_BLOCK - 1);
+ mutex_enter(&usb_blk_lock);
err = usb_block_allocmem(tag, size, align, &p->block);
if (!err) {
#ifdef DEBUG
@@ -262,10 +275,11 @@ usb_allocmem(usbd_bus_handle bus, size_t
p->block->flags = USB_DMA_FULLBLOCK;
p->offs = 0;
}
+ mutex_exit(&usb_blk_lock);
return (err);
}
- s = splusb();
+ mutex_enter(&usb_blk_lock);
/* Check for free fragments. */
LIST_FOREACH(f, &usb_frag_freelist, next) {
KDASSERTMSG(usb_valid_block_p(f->block, &usb_blk_fraglist),
@@ -278,7 +292,7 @@ usb_allocmem(usbd_bus_handle bus, size_t
DPRINTFN(1, ("usb_allocmem: adding fragments\n"));
err = usb_block_allocmem(tag, USB_MEM_BLOCK, USB_MEM_SMALL,&b);
if (err) {
- splx(s);
+ mutex_exit(&usb_blk_lock);
return (err);
}
#ifdef DEBUG
@@ -303,7 +317,7 @@ usb_allocmem(usbd_bus_handle bus, size_t
#endif
p->block->flags &= ~USB_DMA_RESERVE;
LIST_REMOVE(f, next);
- splx(s);
+ mutex_exit(&usb_blk_lock);
DPRINTFN(5, ("usb_allocmem: use frag=%p size=%d\n", f, (int)size));
return (USBD_NORMAL_COMPLETION);
}
@@ -312,14 +326,15 @@ void
usb_freemem(usbd_bus_handle bus, usb_dma_t *p)
{
struct usb_frag_dma *f;
- int s;
+ mutex_enter(&usb_blk_lock);
if (p->block->flags & USB_DMA_FULLBLOCK) {
KDASSERTMSG(usb_valid_block_p(p->block, &usb_blk_fulllist),
"%s: dma %p: invalid block pointer %p",
__func__, p, p->block);
DPRINTFN(1, ("usb_freemem: large free\n"));
usb_block_freemem(p->block);
+ mutex_exit(&usb_blk_lock);
return;
}
KDASSERTMSG(usb_valid_block_p(p->block, &usb_blk_fraglist),
@@ -335,9 +350,8 @@ usb_freemem(usbd_bus_handle bus, usb_dma
#ifdef USB_FRAG_DMA_WORKAROUND
f->offs -= USB_MEM_SMALL;
#endif
- s = splusb();
LIST_INSERT_HEAD(&usb_frag_freelist, f, next);
- splx(s);
+ mutex_exit(&usb_blk_lock);
DPRINTFN(5, ("usb_freemem: frag=%p\n", f));
}