1 /* $NetBSD: drm_dma.c,v 1.2 2018/08/27 04:58:19 riastradh Exp $ */ 2 3 /** 4 * \file drm_dma.c 5 * DMA IOCTL and function support 6 * 7 * \author Rickard E. (Rik) Faith <faith@valinux.com> 8 * \author Gareth Hughes <gareth@valinux.com> 9 */ 10 11 /* 12 * Created: Fri Mar 19 14:30:16 1999 by faith@valinux.com 13 * 14 * Copyright 1999, 2000 Precision Insight, Inc., Cedar Park, Texas. 15 * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California. 16 * All Rights Reserved. 17 * 18 * Permission is hereby granted, free of charge, to any person obtaining a 19 * copy of this software and associated documentation files (the "Software"), 20 * to deal in the Software without restriction, including without limitation 21 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 22 * and/or sell copies of the Software, and to permit persons to whom the 23 * Software is furnished to do so, subject to the following conditions: 24 * 25 * The above copyright notice and this permission notice (including the next 26 * paragraph) shall be included in all copies or substantial portions of the 27 * Software. 28 * 29 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 30 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 31 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 32 * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR 33 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 34 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 35 * OTHER DEALINGS IN THE SOFTWARE. 36 */ 37 38 #include <sys/cdefs.h> 39 __KERNEL_RCSID(0, "$NetBSD: drm_dma.c,v 1.2 2018/08/27 04:58:19 riastradh Exp $"); 40 41 #include <linux/export.h> 42 #include <drm/drmP.h> 43 #include "drm_legacy.h" 44 45 /** 46 * Initialize the DMA data. 47 * 48 * \param dev DRM device. 49 * \return zero on success or a negative value on failure. 50 * 51 * Allocate and initialize a drm_device_dma structure. 52 */ 53 int drm_legacy_dma_setup(struct drm_device *dev) 54 { 55 int i; 56 57 if (!drm_core_check_feature(dev, DRIVER_HAVE_DMA) || 58 drm_core_check_feature(dev, DRIVER_MODESET)) { 59 return 0; 60 } 61 62 dev->buf_use = 0; 63 atomic_set(&dev->buf_alloc, 0); 64 65 dev->dma = kzalloc(sizeof(*dev->dma), GFP_KERNEL); 66 if (!dev->dma) 67 return -ENOMEM; 68 69 for (i = 0; i <= DRM_MAX_ORDER; i++) 70 memset(&dev->dma->bufs[i], 0, sizeof(dev->dma->bufs[0])); 71 72 return 0; 73 } 74 75 /** 76 * Cleanup the DMA resources. 77 * 78 * \param dev DRM device. 79 * 80 * Free all pages associated with DMA buffers, the buffers and pages lists, and 81 * finally the drm_device::dma structure itself. 82 */ 83 void drm_legacy_dma_takedown(struct drm_device *dev) 84 { 85 struct drm_device_dma *dma = dev->dma; 86 int i, j; 87 88 if (!drm_core_check_feature(dev, DRIVER_HAVE_DMA) || 89 drm_core_check_feature(dev, DRIVER_MODESET)) { 90 return; 91 } 92 93 if (!dma) 94 return; 95 96 /* Clear dma buffers */ 97 for (i = 0; i <= DRM_MAX_ORDER; i++) { 98 if (dma->bufs[i].seg_count) { 99 DRM_DEBUG("order %d: buf_count = %d," 100 " seg_count = %d\n", 101 i, 102 dma->bufs[i].buf_count, 103 dma->bufs[i].seg_count); 104 for (j = 0; j < dma->bufs[i].seg_count; j++) { 105 if (dma->bufs[i].seglist[j]) { 106 drm_pci_free(dev, dma->bufs[i].seglist[j]); 107 } 108 } 109 kfree(dma->bufs[i].seglist); 110 } 111 if (dma->bufs[i].buf_count) { 112 for (j = 0; j < dma->bufs[i].buf_count; j++) { 113 kfree(dma->bufs[i].buflist[j].dev_private); 114 } 115 kfree(dma->bufs[i].buflist); 116 } 117 } 118 119 kfree(dma->buflist); 120 kfree(dma->pagelist); 121 kfree(dev->dma); 122 dev->dma = NULL; 123 } 124 125 /** 126 * Free a buffer. 127 * 128 * \param dev DRM device. 129 * \param buf buffer to free. 130 * 131 * Resets the fields of \p buf. 132 */ 133 void drm_legacy_free_buffer(struct drm_device *dev, struct drm_buf * buf) 134 { 135 if (!buf) 136 return; 137 138 buf->waiting = 0; 139 buf->pending = 0; 140 buf->file_priv = NULL; 141 buf->used = 0; 142 } 143 144 /** 145 * Reclaim the buffers. 146 * 147 * \param file_priv DRM file private. 148 * 149 * Frees each buffer associated with \p file_priv not already on the hardware. 150 */ 151 void drm_legacy_reclaim_buffers(struct drm_device *dev, 152 struct drm_file *file_priv) 153 { 154 struct drm_device_dma *dma = dev->dma; 155 int i; 156 157 if (!dma) 158 return; 159 for (i = 0; i < dma->buf_count; i++) { 160 if (dma->buflist[i]->file_priv == file_priv) { 161 switch (dma->buflist[i]->list) { 162 case DRM_LIST_NONE: 163 drm_legacy_free_buffer(dev, dma->buflist[i]); 164 break; 165 case DRM_LIST_WAIT: 166 dma->buflist[i]->list = DRM_LIST_RECLAIM; 167 break; 168 default: 169 /* Buffer already on hardware. */ 170 break; 171 } 172 } 173 } 174 } 175