summaryrefslogtreecommitdiff
path: root/bsd-core
AgeCommit message (Collapse)Author
2008-12-23[FreeBSD] Fix build on FreeBSD after modesetting import.Robert Noland
2008-10-23[FreeBSD] We should use dev2unit() rather than minor()Robert Noland
2008-10-23[FreeBSD] This check isn't correct and causes at least mga to lockup.Robert Noland
2008-10-10[FreeBSD] Plug memory leak in drm_rmdraw() and drm_drawable_free_all()Robert Noland
2008-10-10[FreeBSD] Rework all of the memory allocationsRobert Noland
Allocate memory from different pools. This allows the OS to track memory allocations for us, much like the linux memory debugging. This will ease tracking down memory leaks since the OS can track the number of allocations from each pool and help to point us in the right direction. Also replace drm_alloc and friends with static __inline__ versions while we are here.
2008-10-09[FreeBSD] Fix linux list compat list_for_each_safe()Robert Noland
linux_for_each_safe would not handle lists with a single entry.
2008-10-03[FreeBSD] Don't explicitly bzero driver softc.Robert Noland
This is already handled for us. Suggested by John Baldwin
2008-10-03[FreeBSD] Use M_WAITOK when allocating driver memory.Robert Noland
We don't explicitly check for error here and M_WAITOK will just put the process to sleep waiting on resources to become available. Suggested by John Baldwin
2008-10-03[FreeBSD] Do a bit of optimization on drm_order()Robert Noland
2008-10-01Use devfs_get_cdevpriv in mmap as well.Robert Noland
d_mmap gets called twice and we are only able to associate the file_priv during the first call. The second call will return EBADF and we need to assume that the call was succesful. d_mmap will not tolerate having an error returned for the second call.
2008-09-17[FreeBSD] Convert to using cdevpriv for file_priv trackingRobert Noland
2008-09-10Remove incomplete and obsolete free/net/open code.vehemens
Signed-off-by: Robert Noland <rnoland@2hip.net>
2008-09-08[FreeBSD] We need to call drm_detach before we free dev->driver.Robert Noland
The driver is in control of the show, so when you try and unload a module the driver detach routine is called first. It is what drives the whole unload process and so lots of panics occur if dev->driver is already free.
2008-09-07[FreeBSD] Implement drm_ioremap_wc() to set a range of mem to write-combiningRobert Noland
2008-09-06[FreeBSD] IGP gart needs to be un-cached.Robert Noland
Airlied inadvertently discovered that the IGP gart needs to be un-cached for radeon rs485 and rs690 to work. Initial tests by placing a wbinvd() after allocating the gart were successful. This is an attempt at a more appropriate method of achieving success.
2008-09-06Free temp_pagelist on error. Free in reverse order. Noticed by open.vehemens
Signed-off-by: Robert Noland <rnoland@2hip.net>
2008-09-06Pass lock data like linux and open.vehemens
Signed-off-by: Robert Noland <rnoland@2hip.net>
2008-09-06Move order to end like linux.vehemens
Signed-off-by: Robert Noland <rnoland@2hip.net>
2008-09-06Style white space cleanup part 2.vehemens
Signed-off-by: Robert Noland <rnoland@2hip.net>
2008-09-06[FreeBSD] Ensure that drm_pci_alloc is never called while locks are held.Robert Noland
2008-09-05Reorder lock functions like linux.vehemens
Signed-off-by: Robert Noland <rnoland@2hip.net>
2008-09-05Style white space cleanup.vehemens
Signed-off-by: Robert Noland <rnoland@2hip.net>
2008-09-05Need M_NOWAIT for malloc.vehemens
Signed-off-by: Robert Noland <rnoland@2hip.net>
2008-08-29[FreeBSD] Use driver features macros and flagsvehemens
Signed-off-by: Robert Noland <rnoland@2hip.net>
2008-08-29[FreeBSD] Convert drm_driver to a pointer like linux.vehemens
Signed-off-by: Robert Noland <rnoland@2hip.net>
2008-08-29[FreeBSD] Replace typedefs on bsd.vehemens
Signed-off-by: Robert Noland <rnoland@2hip.net>
2008-08-29[FreeBSD] Catch up to vblank rework for via.vehemens
(No, we don't build via right now.) Signed-off-by: Robert Noland <rnoland@2hip.net>
2008-08-29[FreeBSD] Correct debug messagevehemens
Signed-off-by: Robert Noland <rnoland@2hip.net>
2008-08-29[FreeBSD] Fix a couple of locking problems.Robert Noland
2008-08-29[FreeBSD] Increase debugging output for vblank code.Robert Noland
Doing my part to make DRM_DEBUG more chatty...
2008-08-29Fix drm_realloc when you're reallocing into something smaller.Tomas Carnecky
2008-08-24[FreeBSD] Add drm_drawable_free_all()Robert Noland
2008-08-24[FreeBSD] Fix long standing memory leak in drm_remove_magic.Robert Noland
We shuffled all the links around to disconnect the entry, but never free it. We would incorrectly free the last entry in the hash chain if nothing matched.
2008-08-24[FreeBSD] Move vblank bits into their own structure.vehemens
Signed-off-by: Robert Noland <rnoland@2hip.net>
2008-08-24[FreeBSD] Fix lock leak.vehemens
Signed-off-by: Robert Noland <rnoland@2hip.net>
2008-07-25[FreeBSD] Duh, we need to actually define the drm_modeset_ctl...Robert Noland
2008-07-24[FreeBSD] Catch up to linux on vblank-reworkRobert Noland
2008-07-21[FreeBSD] Improve upper_32_bits define.Robert Noland
Thanks to airlied.
2008-07-17[FreeBSD] drm_irq.c updates for vblank fixes.Robert Noland
2008-07-16FreeBSD: Fix radeon buildRobert Noland
2008-07-16BSD: change drm_locked_task*() to use the same scheme as linux.Owain Gordon Ainsworth
The current code can sleep in an interrupt handler, that is bad. So instead if we can't grab the lock, flag it and run the tasklet on unlock. Signed-off-by: Robert Noland <rnoland@2hip.net>
2008-07-15[FreeBSD] We aren't allowed to hold locks over bus_dma_tag_create or ↵Robert Noland
bus_dmamem_alloc.
2008-06-13[FreeBSD] Fix another lock leakRobert Noland
Reported by vehemens
2008-06-08I915 suspend/resume for FreeBSDRobert Noland
2008-06-08[FreeBSD] Rework ati_pcigart.cRobert Noland
This is mostly just a diff reduction with the linux version. I'm not convinced that it will make anything better.
2008-06-08[FreeBSD] We need to request busmastering support.Robert Noland
This seems to be the key to getting at least some radeon cards working. Most, if not all drivers need it enabled, so just request it once the driver has attached.
2008-06-08[FreeBSD] Incorporate vblank fixes for bsd.Robert Noland
2008-06-08[FreeBSD] Forgot to call mtx_destroy on all the locks at unload.Robert Noland
2008-06-08[FreeBSD] Remove the locks in the vblank_disable_fnRobert Noland
They are recursive and causing panics with witness enabled.
2008-06-08[FreeBSD] Go back to using vbl_lock and move init/destroy to load/unload.Robert Noland
ons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice (including the next * paragraph) shall be included in all copies or substantial portions of the * Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. */ /* * ChangeLog: * 2001-11-16 Torsten Duwe <duwe@caldera.de> * added context constructor/destructor hooks, * needed by SiS driver's memory management. */ #include "drmP.h" /******************************************************************/ /** \name Context bitmap support */ /*@{*/ /** * Free a handle from the context bitmap. * * \param dev DRM device. * \param ctx_handle context handle. * * Clears the bit specified by \p ctx_handle in drm_device::ctx_bitmap and the entry * in drm_device::context_sareas, while holding the drm_device::struct_sem * lock. */ void drm_ctxbitmap_free(drm_device_t * dev, int ctx_handle) { if (ctx_handle < 0) goto failed; if (!dev->ctx_bitmap) goto failed; if (ctx_handle < DRM_MAX_CTXBITMAP) { down(&dev->struct_sem); clear_bit(ctx_handle, dev->ctx_bitmap); dev->context_sareas[ctx_handle] = NULL; up(&dev->struct_sem); return; } failed: DRM_ERROR("Attempt to free invalid context handle: %d\n", ctx_handle); return; } /** * Context bitmap allocation. * * \param dev DRM device. * \return (non-negative) context handle on success or a negative number on failure. * * Find the first zero bit in drm_device::ctx_bitmap and (re)allocates * drm_device::context_sareas to accommodate the new entry while holding the * drm_device::struct_sem lock. */ static int drm_ctxbitmap_next(drm_device_t * dev) { int bit; if (!dev->ctx_bitmap) return -1; down(&dev->struct_sem); bit = find_first_zero_bit(dev->ctx_bitmap, DRM_MAX_CTXBITMAP); if (bit < DRM_MAX_CTXBITMAP) { set_bit(bit, dev->ctx_bitmap); DRM_DEBUG("drm_ctxbitmap_next bit : %d\n", bit); if ((bit + 1) > dev->max_context) { dev->max_context = (bit + 1); if (dev->context_sareas) { drm_map_t **ctx_sareas; ctx_sareas = drm_realloc(dev->context_sareas, (dev->max_context - 1) * sizeof(*dev-> context_sareas), dev->max_context * sizeof(*dev-> context_sareas), DRM_MEM_MAPS); if (!ctx_sareas) { clear_bit(bit, dev->ctx_bitmap); up(&dev->struct_sem); return -1; } dev->context_sareas = ctx_sareas; dev->context_sareas[bit] = NULL; } else { /* max_context == 1 at this point */ dev->context_sareas = drm_alloc(dev->max_context * sizeof(*dev->context_sareas), DRM_MEM_MAPS); if (!dev->context_sareas) { clear_bit(bit, dev->ctx_bitmap); up(&dev->struct_sem); return -1; } dev->context_sareas[bit] = NULL; } } up(&dev->struct_sem); return bit; } up(&dev->struct_sem); return -1; } /** * Context bitmap initialization. * * \param dev DRM device. * * Allocates and initialize drm_device::ctx_bitmap and drm_device::context_sareas, while holding * the drm_device::struct_sem lock. */ int drm_ctxbitmap_init(drm_device_t * dev) { int i; int temp; down(&dev->struct_sem); dev->ctx_bitmap = (unsigned long *)drm_alloc(PAGE_SIZE, DRM_MEM_CTXBITMAP); if (dev->ctx_bitmap == NULL) { up(&dev->struct_sem); return -ENOMEM; } memset((void *)dev->ctx_bitmap, 0, PAGE_SIZE); dev->context_sareas = NULL; dev->max_context = -1; up(&dev->struct_sem); for (i = 0; i < DRM_RESERVED_CONTEXTS; i++) { temp = drm_ctxbitmap_next(dev); DRM_DEBUG("drm_ctxbitmap_init : %d\n", temp); } return 0; } /** * Context bitmap cleanup. * * \param dev DRM device. * * Frees drm_device::ctx_bitmap and drm_device::context_sareas, while holding * the drm_device::struct_sem lock. */ void drm_ctxbitmap_cleanup(drm_device_t * dev) { down(&dev->struct_sem); if (dev->context_sareas) drm_free(dev->context_sareas, sizeof(*dev->context_sareas) * dev->max_context, DRM_MEM_MAPS); drm_free((void *)dev->ctx_bitmap, PAGE_SIZE, DRM_MEM_CTXBITMAP); up(&dev->struct_sem); } /*@}*/ /******************************************************************/ /** \name Per Context SAREA Support */ /*@{*/ /** * Get per-context SAREA. * * \param inode device inode. * \param filp file pointer. * \param cmd command. * \param arg user argument pointing to a drm_ctx_priv_map structure. * \return zero on success or a negative number on failure. * * Gets the map from drm_device::context_sareas with the handle specified and * returns its handle. */ int drm_getsareactx(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg) { drm_file_t *priv = filp->private_data; drm_device_t *dev = priv->head->dev; drm_ctx_priv_map_t __user *argp = (void __user *)arg; drm_ctx_priv_map_t request; drm_map_t *map; drm_map_list_t *_entry; if (copy_from_user(&request, argp, sizeof(request))) return -EFAULT; down(&dev->struct_sem); if (dev->max_context < 0 || request.ctx_id >= (unsigned)dev->max_context) { up(&dev->struct_sem); return -EINVAL; } map = dev->context_sareas[request.ctx_id]; up(&dev->struct_sem); request.handle = NULL; list_for_each_entry(_entry, &dev->maplist->head,head) { if (_entry->map == map) { request.handle = (void *)(unsigned long)_entry->user_token; break; } } if (request.handle == NULL) return -EINVAL; if (copy_to_user(argp, &request, sizeof(request))) return -EFAULT; return 0; } /** * Set per-context SAREA. * * \param inode device inode. * \param filp file pointer. * \param cmd command. * \param arg user argument pointing to a drm_ctx_priv_map structure. * \return zero on success or a negative number on failure. * * Searches the mapping specified in \p arg and update the entry in * drm_device::context_sareas with it. */ int drm_setsareactx(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg) { drm_file_t *priv = filp->private_data; drm_device_t *dev = priv->head->dev; drm_ctx_priv_map_t request; drm_map_t *map = NULL; drm_map_list_t *r_list = NULL; struct list_head *list; if (copy_from_user(&request, (drm_ctx_priv_map_t __user *) arg, sizeof(request))) return -EFAULT; down(&dev->struct_sem); list_for_each(list, &dev->maplist->head) { r_list = list_entry(list, drm_map_list_t, head); if (r_list->map && r_list->user_token == (unsigned long) request.handle) goto found; } bad: up(&dev->struct_sem); return -EINVAL; found: map = r_list->map; if (!map) goto bad; if (dev->max_context < 0) goto bad; if (request.ctx_id >= (unsigned)dev->max_context) goto bad; dev->context_sareas[request.ctx_id] = map; up(&dev->struct_sem); return 0; } /*@}*/ /******************************************************************/ /** \name The actual DRM context handling routines */ /*@{*/ /** * Switch context. * * \param dev DRM device. * \param old old context handle. * \param new new context handle. * \return zero on success or a negative number on failure. * * Attempt to set drm_device::context_flag. */ static int drm_context_switch(drm_device_t * dev, int old, int new) { if (test_and_set_bit(0, &dev->context_flag)) { DRM_ERROR("Reentering -- FIXME\n"); return -EBUSY; } DRM_DEBUG("Context switch from %d to %d\n", old, new); if (new == dev->last_context) { clear_bit(0, &dev->context_flag); return 0; } return 0; } /** * Complete context switch. * * \param dev DRM device. * \param new new context handle. * \return zero on success or a negative number on failure. * * Updates drm_device::last_context and drm_device::last_switch. Verifies the * hardware lock is held, clears the drm_device::context_flag and wakes up * drm_device::context_wait. */ static int drm_context_switch_complete(drm_device_t * dev, int new) { dev->last_context = new; /* PRE/POST: This is the _only_ writer. */ dev->last_switch = jiffies; if (!_DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock)) { DRM_ERROR("Lock isn't held after context switch\n"); } /* If a context switch is ever initiated when the kernel holds the lock, release that lock here. */ clear_bit(0, &dev->context_flag); wake_up(&dev->context_wait); return 0; } /** * Reserve contexts. * * \param inode device inode. * \param filp file pointer. * \param cmd command. * \param arg user argument pointing to a drm_ctx_res structure. * \return zero on success or a negative number on failure. */ int drm_resctx(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg) { drm_ctx_res_t res; drm_ctx_t __user *argp = (void __user *)arg; drm_ctx_t ctx; int i; if (copy_from_user(&res, argp, sizeof(res))) return -EFAULT; if (res.count >= DRM_RESERVED_CONTEXTS) { memset(&ctx, 0, sizeof(ctx)); for (i = 0; i < DRM_RESERVED_CONTEXTS; i++) { ctx.handle = i; if (copy_to_user(&res.contexts[i], &ctx, sizeof(ctx))) return -EFAULT; } } res.count = DRM_RESERVED_CONTEXTS; if (copy_to_user(argp, &res, sizeof(res))) return -EFAULT; return 0; } /** * Add context. * * \param inode device inode. * \param filp file pointer. * \param cmd command. * \param arg user argument pointing to a drm_ctx structure. * \return zero on success or a negative number on failure. * * Get a new handle for the context and copy to userspace. */ int drm_addctx(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg) { drm_file_t *priv = filp->private_data; drm_device_t *dev = priv->head->dev; drm_ctx_list_t *ctx_entry; drm_ctx_t __user *argp = (void __user *)arg; drm_ctx_t ctx; if (copy_from_user(&ctx, argp, sizeof(ctx))) return -EFAULT; ctx.handle = drm_ctxbitmap_next(dev); if (ctx.handle == DRM_KERNEL_CONTEXT) { /* Skip kernel's context and get a new one. */ ctx.handle = drm_ctxbitmap_next(dev); } DRM_DEBUG("%d\n", ctx.handle); if (ctx.handle == -1) { DRM_DEBUG("Not enough free contexts.\n"); /* Should this return -EBUSY instead? */ return -ENOMEM; } if (ctx.handle != DRM_KERNEL_CONTEXT) { if (dev->driver->context_ctor) if (!dev->driver->context_ctor(dev, ctx.handle)) { DRM_DEBUG("Running out of ctxs or memory.\n"); return -ENOMEM; } }