Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F164150329
D58394.id182463.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
8 KB
Referenced Files
None
Subscribers
None
D58394.id182463.diff
View Options
diff --git a/sys/dev/usb/video/uvideo.c b/sys/dev/usb/video/uvideo.c
--- a/sys/dev/usb/video/uvideo.c
+++ b/sys/dev/usb/video/uvideo.c
@@ -46,10 +46,14 @@
#include <sys/rwlock.h>
#include <vm/vm.h>
-#include <vm/pmap.h>
-#include <vm/vm_page.h>
+#include <vm/vm_extern.h>
+#include <vm/vm_kern.h>
#include <vm/vm_object.h>
+#include <vm/vm_page.h>
#include <vm/vm_pager.h>
+#include <vm/vm_param.h>
+#include <vm/pmap.h>
+#include <vm/vm_map.h>
#include <dev/usb/usb.h>
#include <dev/usb/usbdi.h>
@@ -168,25 +172,6 @@
static d_poll_t uvideo_cdev_poll;
static d_kqfilter_t uvideo_cdev_kqfilter;
static d_mmap_single_t uvideo_cdev_mmap_single;
-static int uvideo_pg_ctor(void *, vm_ooffset_t, vm_prot_t,
- vm_ooffset_t, struct ucred *, u_short *);
-static void uvideo_pg_dtor(void *);
-static int uvideo_pg_fault(vm_object_t, vm_ooffset_t, int,
- vm_page_t *);
-
-/*
- * Per-buffer state for mmap lifetime management. Allocated together
- * with the contig buffer at REQBUFS time and attached to a single
- * shared vm_object whose reference count tracks the active mappings.
- * The buffer is freed by cdev_pg_dtor() when the last reference (the
- * softc's own or a user mapping) is dropped. Lives independently of
- * the softc so the pager dtor can safely free the buffer even after
- * device detach.
- */
-struct uvideo_mmap_state {
- uint8_t *ms_buffer;
- size_t ms_buffer_size;
-};
static int uvideo_querycap(struct uvideo_softc *, struct v4l2_capability *);
static int uvideo_enum_fmt(struct uvideo_softc *, struct v4l2_fmtdesc *);
@@ -258,6 +243,7 @@
struct uvideo_mmap *sc_mmap_cur;
uint8_t *sc_mmap_buffer;
size_t sc_mmap_buffer_size;
+ vm_offset_t sc_mmap_kva;
int sc_mmap_buffer_idx;
q_mmap sc_mmap_q;
int sc_mmap_count;
@@ -745,12 +731,6 @@
},
};
-static const struct cdev_pager_ops uvideo_pager_ops = {
- .cdev_pg_ctor = uvideo_pg_ctor,
- .cdev_pg_dtor = uvideo_pg_dtor,
- .cdev_pg_fault = uvideo_pg_fault,
-};
-
/*
* Character device switch
*/
@@ -940,6 +920,7 @@
/* Init mmap queue */
STAILQ_INIT(&sc->sc_mmap_q);
sc->sc_mmap_count = 0;
+ sc->sc_mmap_kva = 0;
sc->sc_mmap_object = NULL;
/* Allocate unit number and create character device */
@@ -2296,18 +2277,14 @@
fb->buf = NULL;
}
- if (sc->sc_mmap_object != NULL) {
- /*
- * Drop the softc's reference to the shared mmap object.
- * If user-space mappings still exist, the object and its
- * backing contig buffer stay alive until the last mapping
- * is dropped, at which point uvideo_pg_dtor() frees them.
- */
- vm_object_deallocate(sc->sc_mmap_object);
- sc->sc_mmap_object = NULL;
+ if (sc->sc_mmap_kva != 0) {
+ vm_map_remove(kernel_map, sc->sc_mmap_kva,
+ sc->sc_mmap_kva + sc->sc_mmap_buffer_size);
sc->sc_mmap_buffer = NULL;
+ sc->sc_mmap_kva = 0;
sc->sc_mmap_buffer_size = 0;
}
+ sc->sc_mmap_object = NULL;
while (!STAILQ_EMPTY(&sc->sc_mmap_q))
STAILQ_REMOVE_HEAD(&sc->sc_mmap_q, q_frames);
@@ -2896,11 +2873,6 @@
uvideo_vs_close(sc);
}
- /*
- * Release mmap buffer. If there are still active mmap
- * mappings, the actual contigfree() is deferred to the
- * last uvideo_pg_dtor() invocation.
- */
uvideo_vs_free_frame(sc);
if (sc->sc_fbuffer != NULL) {
@@ -3157,79 +3129,6 @@
return (0);
}
-static int
-uvideo_pg_ctor(void *handle, vm_ooffset_t size, vm_prot_t prot,
- vm_ooffset_t foff, struct ucred *cred, u_short *color)
-{
- struct uvideo_mmap_state *ms = handle;
-
- if (ms->ms_buffer == NULL || foff + size > ms->ms_buffer_size)
- return (EINVAL);
-
- *color = 0;
- return (0);
-}
-
-static void
-uvideo_pg_dtor(void *handle)
-{
- struct uvideo_mmap_state *ms = handle;
-
- /*
- * The last reference to the shared mmap object is gone (either the
- * softc released it, or the final user mapping was dropped). Free
- * the backing contig buffer and the state.
- */
- if (ms->ms_buffer != NULL)
- contigfree(ms->ms_buffer, ms->ms_buffer_size, M_USBDEV);
- free(ms, M_USBDEV);
-}
-
-static int
-uvideo_pg_fault(vm_object_t object, vm_ooffset_t offset, int prot,
- vm_page_t *mres)
-{
- struct uvideo_mmap_state *ms = object->un_pager.devp.handle;
- vm_paddr_t paddr;
- vm_page_t m;
-
- if (ms->ms_buffer == NULL)
- return (VM_PAGER_FAIL);
-
- if (offset >= ms->ms_buffer_size)
- return (VM_PAGER_FAIL);
-
- paddr = vtophys(ms->ms_buffer + offset);
- if (paddr == 0)
- return (VM_PAGER_FAIL);
-
- if (((*mres)->flags & PG_FICTITIOUS) != 0) {
- /*
- * The passed-in page is already a fake page: just update
- * its physical address in place.
- */
- m = *mres;
- vm_page_updatefake(m, paddr, object->memattr);
- } else {
- /*
- * Replace the placeholder page allocated by the generic
- * fault path with our own fake page. vm_page_getfake() can
- * allocate and must not be called with the object lock held;
- * vm_page_replace() then swaps the new page into the object
- * and frees the placeholder. Without this the busy
- * placeholder stays in the object and dev_pager_dealloc()
- * dead-locks trying to acquire it.
- */
- VM_OBJECT_WUNLOCK(object);
- m = vm_page_getfake(paddr, object->memattr);
- VM_OBJECT_WLOCK(object);
- vm_page_replace(m, object, (*mres)->pindex, *mres);
- *mres = m;
- }
- m->valid = VM_PAGE_BITS_ALL;
- return (VM_PAGER_OK);
-}
-
/* ---------------------------------------------------------------- */
/* V4L2 Ioctl Handlers */
/* ---------------------------------------------------------------- */
@@ -3633,7 +3532,9 @@
uvideo_reqbufs(struct uvideo_softc *sc, struct v4l2_requestbuffers *rb)
{
int i, buf_size, buf_size_total;
- struct uvideo_mmap_state *ms;
+ vm_object_t obj;
+ vm_offset_t kva;
+ int error;
DPRINTFN(1, "reqbufs: count=%d\n", rb->count);
@@ -3654,39 +3555,48 @@
buf_size_total = sc->sc_mmap_count * buf_size;
buf_size_total = round_page(buf_size_total);
- sc->sc_mmap_buffer = contigmalloc(buf_size_total, M_USBDEV,
- M_WAITOK | M_ZERO, 0, ~0UL, PAGE_SIZE, 0);
- if (sc->sc_mmap_buffer == NULL) {
- device_printf(sc->sc_dev, "can't allocate mmap buffer!\n");
+ /*
+ * Allocate a physical vm_object of the requested size. Use
+ * phys_pager_allocate() so that un_pager.phys.ops is properly
+ * initialised: a bare vm_object_allocate(OBJT_PHYS, ...)
+ * leaves ops NULL and causes a page fault when the VM system
+ * calls phys_pager_getpages() during vm_map_wire() or a
+ * userspace fault on the mmap mapping.
+ */
+ obj = phys_pager_allocate(NULL, &default_phys_pg_ops, NULL,
+ buf_size_total, VM_PROT_ALL, 0, curthread->td_ucred);
+ if (obj == NULL) {
+ device_printf(sc->sc_dev, "can't allocate mmap vm_object!\n");
sc->sc_mmap_count = 0;
return (ENOMEM);
}
- sc->sc_mmap_buffer_size = buf_size_total;
- /*
- * Create a single shared vm_object backing the whole mmap buffer.
- * Its reference count (bumped by each mmap() and held by the softc)
- * tracks the lifetime of the mappings; the contig buffer is freed
- * by uvideo_pg_dtor() when the last reference goes away, which may
- * be after device detach.
- */
- ms = malloc(sizeof(*ms), M_USBDEV, M_WAITOK | M_ZERO);
- ms->ms_buffer = sc->sc_mmap_buffer;
- ms->ms_buffer_size = sc->sc_mmap_buffer_size;
- sc->sc_mmap_object = cdev_pager_allocate(ms, OBJT_DEVICE,
- &uvideo_pager_ops, sc->sc_mmap_buffer_size, VM_PROT_ALL,
- 0, curthread->td_ucred);
- if (sc->sc_mmap_object == NULL) {
- free(ms, M_USBDEV);
- contigfree(sc->sc_mmap_buffer, sc->sc_mmap_buffer_size,
- M_USBDEV);
- sc->sc_mmap_buffer = NULL;
- sc->sc_mmap_buffer_size = 0;
+ kva = vm_map_min(kernel_map);
+ error = vm_map_find(kernel_map, obj, 0, &kva, buf_size_total, 0,
+ VMFS_OPTIMAL_SPACE, VM_PROT_READ | VM_PROT_WRITE,
+ VM_PROT_READ | VM_PROT_WRITE, 0);
+ if (error != KERN_SUCCESS) {
+ vm_object_deallocate(obj);
+ device_printf(sc->sc_dev, "vm_map_find failed: %d\n", error);
sc->sc_mmap_count = 0;
- return (ENOMEM);
+ return (vm_mmap_to_errno(error));
}
+ error = vm_map_wire(kernel_map, kva, kva + buf_size_total,
+ VM_MAP_WIRE_SYSTEM | VM_MAP_WIRE_NOHOLES);
+ if (error != KERN_SUCCESS) {
+ vm_map_remove(kernel_map, kva, kva + buf_size_total);
+ device_printf(sc->sc_dev, "vm_map_wire failed: %d\n", error);
+ sc->sc_mmap_count = 0;
+ return (vm_mmap_to_errno(error));
+ }
+
+ sc->sc_mmap_object = obj;
+ sc->sc_mmap_buffer = (uint8_t *)kva;
+ sc->sc_mmap_kva = kva;
+ sc->sc_mmap_buffer_size = buf_size_total;
- DPRINTFN(1, "allocated %d bytes mmap buffer\n", buf_size_total);
+ DPRINTFN(1, "allocated %d bytes mmap buffer at kva %#jx\n",
+ buf_size_total, (uintmax_t)kva);
for (i = 0; i < sc->sc_mmap_count; i++) {
sc->sc_mmap[i].buf = sc->sc_mmap_buffer + (i * buf_size);
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Thu, Jul 30, 4:27 AM (5 h, 9 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
35403762
Default Alt Text
D58394.id182463.diff (8 KB)
Attached To
Mode
D58394: uvideo: replace contigmalloc with OBJT_PHYS vm_object for mmap buffer
Attached
Detach File
Event Timeline
Log In to Comment