From owner-svn-src-all@FreeBSD.ORG Fri Apr 17 07:07:07 2015 Return-Path: Delivered-To: svn-src-all@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:1900:2254:206a::19:1]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by hub.freebsd.org (Postfix) with ESMTPS id 7D46FED9; Fri, 17 Apr 2015 07:07:07 +0000 (UTC) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:1900:2254:2068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mx1.freebsd.org (Postfix) with ESMTPS id 6B782CD9; Fri, 17 Apr 2015 07:07:07 +0000 (UTC) Received: from svn.freebsd.org ([127.0.1.70]) by svn.freebsd.org (8.14.9/8.14.9) with ESMTP id t3H777mc089367; Fri, 17 Apr 2015 07:07:07 GMT (envelope-from hselasky@FreeBSD.org) Received: (from hselasky@localhost) by svn.freebsd.org (8.14.9/8.14.9/Submit) id t3H777HV089365; Fri, 17 Apr 2015 07:07:07 GMT (envelope-from hselasky@FreeBSD.org) Message-Id: <201504170707.t3H777HV089365@svn.freebsd.org> X-Authentication-Warning: svn.freebsd.org: hselasky set sender to hselasky@FreeBSD.org using -f From: Hans Petter Selasky Date: Fri, 17 Apr 2015 07:07:07 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r281644 - head/sys/dev/usb/video X-SVN-Group: head MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-all@freebsd.org X-Mailman-Version: 2.1.20 Precedence: list List-Id: "SVN commit messages for the entire src tree \(except for " user" and " projects" \)" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Fri, 17 Apr 2015 07:07:07 -0000 Author: hselasky Date: Fri Apr 17 07:07:06 2015 New Revision: 281644 URL: https://svnweb.freebsd.org/changeset/base/281644 Log: Buffers which can be memory mapped into userspace should never be freed. Recycle the buffers instead. This patch also fixes a panic at reboot issue when an UDL adapter is attached to the system. Modified: head/sys/dev/usb/video/udl.c head/sys/dev/usb/video/udl.h Modified: head/sys/dev/usb/video/udl.c ============================================================================== --- head/sys/dev/usb/video/udl.c Fri Apr 17 06:39:15 2015 (r281643) +++ head/sys/dev/usb/video/udl.c Fri Apr 17 07:07:06 2015 (r281644) @@ -76,6 +76,11 @@ static int udl_fps = 25; SYSCTL_INT(_hw_usb_udl, OID_AUTO, fps, CTLFLAG_RWTUN, &udl_fps, 0, "Frames Per Second, 1-60"); +static struct mtx udl_buffer_mtx; +static struct udl_buffer_head udl_buffer_head; + +MALLOC_DEFINE(M_USB_DL, "USB", "USB DisplayLink"); + /* * Prototypes. */ @@ -175,6 +180,56 @@ static const STRUCT_USB_HOST_ID udl_devs {USB_VPI(USB_VENDOR_DISPLAYLINK, USB_PRODUCT_DISPLAYLINK_LT1421, DLUNK)} }; +static void +udl_buffer_init(void *arg) +{ + mtx_init(&udl_buffer_mtx, "USB", "UDL", MTX_DEF); + TAILQ_INIT(&udl_buffer_head); +} +SYSINIT(udl_buffer_init, SI_SUB_LOCK, SI_ORDER_FIRST, udl_buffer_init, NULL); + +CTASSERT(sizeof(struct udl_buffer) < PAGE_SIZE); + +static void * +udl_buffer_alloc(uint32_t size) +{ + struct udl_buffer *buf; + mtx_lock(&udl_buffer_mtx); + TAILQ_FOREACH(buf, &udl_buffer_head, entry) { + if (buf->size == size) { + TAILQ_REMOVE(&udl_buffer_head, buf, entry); + break; + } + } + mtx_unlock(&udl_buffer_mtx); + if (buf != NULL) { + /* wipe and recycle buffer */ + memset(buf, 0, size); + return (buf); + } + /* allocate new buffer */ + return (malloc(size, M_USB_DL, M_WAITOK | M_ZERO)); +} + +static void +udl_buffer_free(void *_buf, uint32_t size) +{ + struct udl_buffer *buf; + + buf = (struct udl_buffer *)_buf; + if (buf == NULL) + return; + + /* + * Memory mapped buffers should never be freed. + * Put display buffer into a recycle list. + */ + mtx_lock(&udl_buffer_mtx); + buf->size = size; + TAILQ_INSERT_TAIL(&udl_buffer_head, buf, entry); + mtx_unlock(&udl_buffer_mtx); +} + static uint32_t udl_get_fb_size(struct udl_softc *sc) { @@ -403,11 +458,11 @@ udl_detach(device_t dev) mtx_destroy(&sc->sc_mtx); cv_destroy(&sc->sc_cv); - /* - * Free framebuffer memory, if any. - */ - free(sc->sc_fb_addr, M_DEVBUF); - free(sc->sc_fb_copy, M_DEVBUF); + /* put main framebuffer into a recycle list, if any */ + udl_buffer_free(sc->sc_fb_addr, sc->sc_fb_size); + + /* free shadow framebuffer memory, if any */ + free(sc->sc_fb_copy, M_USB_DL); return (0); } @@ -782,13 +837,15 @@ udl_fbmem_alloc(struct udl_softc *sc) size = udl_get_fb_size(sc); size = round_page(size); - + /* check for zero size */ + if (size == 0) + size = PAGE_SIZE; /* * It is assumed that allocations above PAGE_SIZE bytes will * be PAGE_SIZE aligned for use with mmap() */ - sc->sc_fb_addr = malloc(size, M_DEVBUF, M_WAITOK | M_ZERO); - sc->sc_fb_copy = malloc(size, M_DEVBUF, M_WAITOK | M_ZERO); + sc->sc_fb_addr = udl_buffer_alloc(size); + sc->sc_fb_copy = malloc(size, M_USB_DL, M_WAITOK | M_ZERO); sc->sc_fb_size = size; } Modified: head/sys/dev/usb/video/udl.h ============================================================================== --- head/sys/dev/usb/video/udl.h Fri Apr 17 06:39:15 2015 (r281643) +++ head/sys/dev/usb/video/udl.h Fri Apr 17 07:07:06 2015 (r281644) @@ -34,6 +34,15 @@ #define UDL_FONT_HEIGHT 16 /* pixels */ #define UDL_MAX_MODES 25 /* units */ +MALLOC_DECLARE(M_USB_DL); + +struct udl_buffer { + TAILQ_ENTRY(udl_buffer) entry; + uint32_t size; +}; + +TAILQ_HEAD(udl_buffer_head, udl_buffer); + struct udl_cmd_buf { TAILQ_ENTRY(udl_cmd_buf) entry; uint32_t off;