drm_scatter.c (183833) | drm_scatter.c (186295) |
---|---|
1/*- 2 * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California. 3 * All Rights Reserved. 4 * 5 * Permission is hereby granted, free of charge, to any person obtaining a 6 * copy of this software and associated documentation files (the "Software"), 7 * to deal in the Software without restriction, including without limitation 8 * the rights to use, copy, modify, merge, publish, distribute, sublicense, --- 14 unchanged lines hidden (view full) --- 23 * 24 * Authors: 25 * Gareth Hughes <gareth@valinux.com> 26 * Eric Anholt <anholt@FreeBSD.org> 27 * 28 */ 29 30#include <sys/cdefs.h> | 1/*- 2 * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California. 3 * All Rights Reserved. 4 * 5 * Permission is hereby granted, free of charge, to any person obtaining a 6 * copy of this software and associated documentation files (the "Software"), 7 * to deal in the Software without restriction, including without limitation 8 * the rights to use, copy, modify, merge, publish, distribute, sublicense, --- 14 unchanged lines hidden (view full) --- 23 * 24 * Authors: 25 * Gareth Hughes <gareth@valinux.com> 26 * Eric Anholt <anholt@FreeBSD.org> 27 * 28 */ 29 30#include <sys/cdefs.h> |
31__FBSDID("$FreeBSD: head/sys/dev/drm/drm_scatter.c 183833 2008-10-13 18:03:27Z rnoland $"); | 31__FBSDID("$FreeBSD: head/sys/dev/drm/drm_scatter.c 186295 2008-12-18 21:04:50Z rnoland $"); |
32 33/** @file drm_scatter.c 34 * Allocation of memory for scatter-gather mappings by the graphics chip. 35 * 36 * The memory allocated here is then made into an aperture in the card 37 * by drm_ati_pcigart_init(). 38 */ 39 40#include "dev/drm/drmP.h" 41 | 32 33/** @file drm_scatter.c 34 * Allocation of memory for scatter-gather mappings by the graphics chip. 35 * 36 * The memory allocated here is then made into an aperture in the card 37 * by drm_ati_pcigart_init(). 38 */ 39 40#include "dev/drm/drmP.h" 41 |
42#define DEBUG_SCATTER 0 | 42static void drm_sg_alloc_cb(void *arg, bus_dma_segment_t *segs, 43 int nsegs, int error); |
43 | 44 |
44void drm_sg_cleanup(drm_sg_mem_t *entry) | 45int 46drm_sg_alloc(struct drm_device *dev, struct drm_scatter_gather *request) |
45{ | 47{ |
46 free((void *)entry->handle, DRM_MEM_PAGES); 47 free(entry->busaddr, DRM_MEM_PAGES); 48 free(entry, DRM_MEM_SGLISTS); 49} 50 51int drm_sg_alloc(struct drm_device * dev, struct drm_scatter_gather * request) 52{ 53 drm_sg_mem_t *entry; | 48 struct drm_sg_mem *entry; 49 struct drm_dma_handle *dmah; |
54 unsigned long pages; | 50 unsigned long pages; |
55 int i; | 51 int ret; |
56 57 if (dev->sg) 58 return EINVAL; 59 60 entry = malloc(sizeof(*entry), DRM_MEM_SGLISTS, M_WAITOK | M_ZERO); 61 if (!entry) 62 return ENOMEM; 63 64 pages = round_page(request->size) / PAGE_SIZE; 65 DRM_DEBUG("sg size=%ld pages=%ld\n", request->size, pages); 66 67 entry->pages = pages; 68 69 entry->busaddr = malloc(pages * sizeof(*entry->busaddr), DRM_MEM_PAGES, 70 M_WAITOK | M_ZERO); 71 if (!entry->busaddr) { | 52 53 if (dev->sg) 54 return EINVAL; 55 56 entry = malloc(sizeof(*entry), DRM_MEM_SGLISTS, M_WAITOK | M_ZERO); 57 if (!entry) 58 return ENOMEM; 59 60 pages = round_page(request->size) / PAGE_SIZE; 61 DRM_DEBUG("sg size=%ld pages=%ld\n", request->size, pages); 62 63 entry->pages = pages; 64 65 entry->busaddr = malloc(pages * sizeof(*entry->busaddr), DRM_MEM_PAGES, 66 M_WAITOK | M_ZERO); 67 if (!entry->busaddr) { |
72 drm_sg_cleanup(entry); | 68 free(entry, DRM_MEM_SGLISTS); |
73 return ENOMEM; 74 } 75 | 69 return ENOMEM; 70 } 71 |
76 entry->handle = (long)malloc(pages << PAGE_SHIFT, DRM_MEM_PAGES, 77 M_WAITOK | M_ZERO); 78 if (entry->handle == 0) { 79 drm_sg_cleanup(entry); | 72 dmah = malloc(sizeof(struct drm_dma_handle), DRM_MEM_DMA, 73 M_ZERO | M_NOWAIT); 74 if (dmah == NULL) { 75 free(entry->busaddr, DRM_MEM_PAGES); 76 free(entry, DRM_MEM_SGLISTS); |
80 return ENOMEM; 81 } 82 | 77 return ENOMEM; 78 } 79 |
83 for (i = 0; i < pages; i++) { 84 entry->busaddr[i] = vtophys(entry->handle + i * PAGE_SIZE); | 80 ret = bus_dma_tag_create(NULL, PAGE_SIZE, 0, /* tag, align, boundary */ 81 BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, /* lowaddr, highaddr */ 82 NULL, NULL, /* filtfunc, filtfuncargs */ 83 request->size, pages, /* maxsize, nsegs */ 84 PAGE_SIZE, 0, /* maxsegsize, flags */ 85 NULL, NULL, /* lockfunc, lockfuncargs */ 86 &dmah->tag); 87 if (ret != 0) { 88 free(dmah, DRM_MEM_DMA); 89 free(entry->busaddr, DRM_MEM_PAGES); 90 free(entry, DRM_MEM_SGLISTS); 91 return ENOMEM; |
85 } 86 | 92 } 93 |
94 ret = bus_dmamem_alloc(dmah->tag, &dmah->vaddr, 95 BUS_DMA_NOWAIT | BUS_DMA_ZERO | BUS_DMA_NOCACHE, &dmah->map); 96 if (ret != 0) { 97 bus_dma_tag_destroy(dmah->tag); 98 free(dmah, DRM_MEM_DMA); 99 free(entry->busaddr, DRM_MEM_PAGES); 100 free(entry, DRM_MEM_SGLISTS); 101 return ENOMEM; 102 } 103 104 ret = bus_dmamap_load(dmah->tag, dmah->map, dmah->vaddr, 105 request->size, drm_sg_alloc_cb, entry, 0); 106 if (ret != 0) { 107 bus_dmamem_free(dmah->tag, dmah->vaddr, dmah->map); 108 bus_dma_tag_destroy(dmah->tag); 109 free(dmah, DRM_MEM_DMA); 110 free(entry->busaddr, DRM_MEM_PAGES); 111 free(entry, DRM_MEM_SGLISTS); 112 return ENOMEM; 113 } 114 115 entry->sg_dmah = dmah; 116 entry->handle = (unsigned long)dmah->vaddr; 117 |
|
87 DRM_DEBUG("sg alloc handle = %08lx\n", entry->handle); 88 89 entry->virtual = (void *)entry->handle; 90 request->handle = entry->handle; 91 92 DRM_LOCK(); 93 if (dev->sg) { 94 DRM_UNLOCK(); 95 drm_sg_cleanup(entry); 96 return EINVAL; 97 } 98 dev->sg = entry; 99 DRM_UNLOCK(); 100 101 return 0; 102} 103 | 118 DRM_DEBUG("sg alloc handle = %08lx\n", entry->handle); 119 120 entry->virtual = (void *)entry->handle; 121 request->handle = entry->handle; 122 123 DRM_LOCK(); 124 if (dev->sg) { 125 DRM_UNLOCK(); 126 drm_sg_cleanup(entry); 127 return EINVAL; 128 } 129 dev->sg = entry; 130 DRM_UNLOCK(); 131 132 return 0; 133} 134 |
104int drm_sg_alloc_ioctl(struct drm_device *dev, void *data, 105 struct drm_file *file_priv) | 135static void 136drm_sg_alloc_cb(void *arg, bus_dma_segment_t *segs, int nsegs, int error) |
106{ | 137{ |
138 struct drm_sg_mem *entry = arg; 139 int i; 140 141 if (error != 0) 142 return; 143 144 for(i = 0 ; i < nsegs ; i++) { 145 entry->busaddr[i] = segs[i].ds_addr; 146 } 147} 148 149int 150drm_sg_alloc_ioctl(struct drm_device *dev, void *data, 151 struct drm_file *file_priv) 152{ |
|
107 struct drm_scatter_gather *request = data; | 153 struct drm_scatter_gather *request = data; |
108 int ret; | |
109 | 154 |
110 DRM_DEBUG("%s\n", __FUNCTION__); | 155 DRM_DEBUG("\n"); |
111 | 156 |
112 ret = drm_sg_alloc(dev, request); 113 return ret; | 157 return drm_sg_alloc(dev, request); |
114} 115 | 158} 159 |
116int drm_sg_free(struct drm_device *dev, void *data, struct drm_file *file_priv) | 160void 161drm_sg_cleanup(struct drm_sg_mem *entry) |
117{ | 162{ |
163 struct drm_dma_handle *dmah = entry->sg_dmah; 164 165 bus_dmamap_unload(dmah->tag, dmah->map); 166 bus_dmamem_free(dmah->tag, dmah->vaddr, dmah->map); 167 bus_dma_tag_destroy(dmah->tag); 168 free(dmah, DRM_MEM_DMA); 169 free(entry->busaddr, DRM_MEM_PAGES); 170 free(entry, DRM_MEM_SGLISTS); 171} 172 173int 174drm_sg_free(struct drm_device *dev, void *data, struct drm_file *file_priv) 175{ |
|
118 struct drm_scatter_gather *request = data; | 176 struct drm_scatter_gather *request = data; |
119 drm_sg_mem_t *entry; | 177 struct drm_sg_mem *entry; |
120 121 DRM_LOCK(); 122 entry = dev->sg; 123 dev->sg = NULL; 124 DRM_UNLOCK(); 125 126 if (!entry || entry->handle != request->handle) 127 return EINVAL; 128 129 DRM_DEBUG("sg free virtual = 0x%lx\n", entry->handle); 130 131 drm_sg_cleanup(entry); 132 133 return 0; 134} | 178 179 DRM_LOCK(); 180 entry = dev->sg; 181 dev->sg = NULL; 182 DRM_UNLOCK(); 183 184 if (!entry || entry->handle != request->handle) 185 return EINVAL; 186 187 DRM_DEBUG("sg free virtual = 0x%lx\n", entry->handle); 188 189 drm_sg_cleanup(entry); 190 191 return 0; 192} |