Back to home page

OSCL-LXR

 
 

    


0001 /*
0002  * \file drm_dma.c
0003  * DMA IOCTL and function support
0004  *
0005  * \author Rickard E. (Rik) Faith <faith@valinux.com>
0006  * \author Gareth Hughes <gareth@valinux.com>
0007  */
0008 
0009 /*
0010  * Created: Fri Mar 19 14:30:16 1999 by faith@valinux.com
0011  *
0012  * Copyright 1999, 2000 Precision Insight, Inc., Cedar Park, Texas.
0013  * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
0014  * All Rights Reserved.
0015  *
0016  * Permission is hereby granted, free of charge, to any person obtaining a
0017  * copy of this software and associated documentation files (the "Software"),
0018  * to deal in the Software without restriction, including without limitation
0019  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
0020  * and/or sell copies of the Software, and to permit persons to whom the
0021  * Software is furnished to do so, subject to the following conditions:
0022  *
0023  * The above copyright notice and this permission notice (including the next
0024  * paragraph) shall be included in all copies or substantial portions of the
0025  * Software.
0026  *
0027  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
0028  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
0029  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
0030  * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
0031  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
0032  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
0033  * OTHER DEALINGS IN THE SOFTWARE.
0034  */
0035 
0036 #include <linux/export.h>
0037 #include <linux/pci.h>
0038 
0039 #include <drm/drm_drv.h>
0040 #include <drm/drm_print.h>
0041 
0042 #include "drm_legacy.h"
0043 
0044 /**
0045  * drm_legacy_dma_setup() - Initialize the DMA data.
0046  *
0047  * @dev: DRM device.
0048  * Return: zero on success or a negative value on failure.
0049  *
0050  * Allocate and initialize a drm_device_dma structure.
0051  */
0052 int drm_legacy_dma_setup(struct drm_device *dev)
0053 {
0054     int i;
0055 
0056     if (!drm_core_check_feature(dev, DRIVER_HAVE_DMA) ||
0057         !drm_core_check_feature(dev, DRIVER_LEGACY))
0058         return 0;
0059 
0060     dev->buf_use = 0;
0061     atomic_set(&dev->buf_alloc, 0);
0062 
0063     dev->dma = kzalloc(sizeof(*dev->dma), GFP_KERNEL);
0064     if (!dev->dma)
0065         return -ENOMEM;
0066 
0067     for (i = 0; i <= DRM_MAX_ORDER; i++)
0068         memset(&dev->dma->bufs[i], 0, sizeof(dev->dma->bufs[0]));
0069 
0070     return 0;
0071 }
0072 
0073 /**
0074  * drm_legacy_dma_takedown() - Cleanup the DMA resources.
0075  *
0076  * @dev: DRM device.
0077  *
0078  * Free all pages associated with DMA buffers, the buffers and pages lists, and
0079  * finally the drm_device::dma structure itself.
0080  */
0081 void drm_legacy_dma_takedown(struct drm_device *dev)
0082 {
0083     struct drm_device_dma *dma = dev->dma;
0084     drm_dma_handle_t *dmah;
0085     int i, j;
0086 
0087     if (!drm_core_check_feature(dev, DRIVER_HAVE_DMA) ||
0088         !drm_core_check_feature(dev, DRIVER_LEGACY))
0089         return;
0090 
0091     if (!dma)
0092         return;
0093 
0094     /* Clear dma buffers */
0095     for (i = 0; i <= DRM_MAX_ORDER; i++) {
0096         if (dma->bufs[i].seg_count) {
0097             DRM_DEBUG("order %d: buf_count = %d,"
0098                   " seg_count = %d\n",
0099                   i,
0100                   dma->bufs[i].buf_count,
0101                   dma->bufs[i].seg_count);
0102             for (j = 0; j < dma->bufs[i].seg_count; j++) {
0103                 if (dma->bufs[i].seglist[j]) {
0104                     dmah = dma->bufs[i].seglist[j];
0105                     dma_free_coherent(dev->dev,
0106                               dmah->size,
0107                               dmah->vaddr,
0108                               dmah->busaddr);
0109                     kfree(dmah);
0110                 }
0111             }
0112             kfree(dma->bufs[i].seglist);
0113         }
0114         if (dma->bufs[i].buf_count) {
0115             for (j = 0; j < dma->bufs[i].buf_count; j++) {
0116                 kfree(dma->bufs[i].buflist[j].dev_private);
0117             }
0118             kfree(dma->bufs[i].buflist);
0119         }
0120     }
0121 
0122     kfree(dma->buflist);
0123     kfree(dma->pagelist);
0124     kfree(dev->dma);
0125     dev->dma = NULL;
0126 }
0127 
0128 /**
0129  * drm_legacy_free_buffer() - Free a buffer.
0130  *
0131  * @dev: DRM device.
0132  * @buf: buffer to free.
0133  *
0134  * Resets the fields of \p buf.
0135  */
0136 void drm_legacy_free_buffer(struct drm_device *dev, struct drm_buf * buf)
0137 {
0138     if (!buf)
0139         return;
0140 
0141     buf->waiting = 0;
0142     buf->pending = 0;
0143     buf->file_priv = NULL;
0144     buf->used = 0;
0145 }
0146 
0147 /**
0148  * drm_legacy_reclaim_buffers() - Reclaim the buffers.
0149  *
0150  * @dev: DRM device.
0151  * @file_priv: DRM file private.
0152  *
0153  * Frees each buffer associated with \p file_priv not already on the hardware.
0154  */
0155 void drm_legacy_reclaim_buffers(struct drm_device *dev,
0156                 struct drm_file *file_priv)
0157 {
0158     struct drm_device_dma *dma = dev->dma;
0159     int i;
0160 
0161     if (!dma)
0162         return;
0163     for (i = 0; i < dma->buf_count; i++) {
0164         if (dma->buflist[i]->file_priv == file_priv) {
0165             switch (dma->buflist[i]->list) {
0166             case DRM_LIST_NONE:
0167                 drm_legacy_free_buffer(dev, dma->buflist[i]);
0168                 break;
0169             case DRM_LIST_WAIT:
0170                 dma->buflist[i]->list = DRM_LIST_RECLAIM;
0171                 break;
0172             default:
0173                 /* Buffer already on hardware. */
0174                 break;
0175             }
0176         }
0177     }
0178 }