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