root/drivers/gpu/drm/drm_agpsupport.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. drm_agp_info
  2. drm_agp_info_ioctl
  3. drm_agp_acquire
  4. drm_agp_acquire_ioctl
  5. drm_agp_release
  6. drm_agp_release_ioctl
  7. drm_agp_enable
  8. drm_agp_enable_ioctl
  9. drm_agp_alloc
  10. drm_agp_alloc_ioctl
  11. drm_agp_lookup_entry
  12. drm_agp_unbind
  13. drm_agp_unbind_ioctl
  14. drm_agp_bind
  15. drm_agp_bind_ioctl
  16. drm_agp_free
  17. drm_agp_free_ioctl
  18. drm_agp_init
  19. drm_legacy_agp_clear

   1 /*
   2  * \file drm_agpsupport.c
   3  * DRM support for AGP/GART backend
   4  *
   5  * \author Rickard E. (Rik) Faith <faith@valinux.com>
   6  * \author Gareth Hughes <gareth@valinux.com>
   7  */
   8 
   9 /*
  10  * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
  11  * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
  12  * All Rights Reserved.
  13  *
  14  * Permission is hereby granted, free of charge, to any person obtaining a
  15  * copy of this software and associated documentation files (the "Software"),
  16  * to deal in the Software without restriction, including without limitation
  17  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  18  * and/or sell copies of the Software, and to permit persons to whom the
  19  * Software is furnished to do so, subject to the following conditions:
  20  *
  21  * The above copyright notice and this permission notice (including the next
  22  * paragraph) shall be included in all copies or substantial portions of the
  23  * Software.
  24  *
  25  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  26  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  27  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
  28  * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
  29  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
  30  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
  31  * OTHER DEALINGS IN THE SOFTWARE.
  32  */
  33 
  34 #include <linux/module.h>
  35 #include <linux/pci.h>
  36 #include <linux/slab.h>
  37 
  38 #include <asm/agp.h>
  39 
  40 #include <drm/drm_agpsupport.h>
  41 #include <drm/drm_device.h>
  42 #include <drm/drm_drv.h>
  43 #include <drm/drm_file.h>
  44 #include <drm/drm_print.h>
  45 
  46 #include "drm_legacy.h"
  47 
  48 /**
  49  * Get AGP information.
  50  *
  51  * \param inode device inode.
  52  * \param file_priv DRM file private.
  53  * \param cmd command.
  54  * \param arg pointer to a (output) drm_agp_info structure.
  55  * \return zero on success or a negative number on failure.
  56  *
  57  * Verifies the AGP device has been initialized and acquired and fills in the
  58  * drm_agp_info structure with the information in drm_agp_head::agp_info.
  59  */
  60 int drm_agp_info(struct drm_device *dev, struct drm_agp_info *info)
  61 {
  62         struct agp_kern_info *kern;
  63 
  64         if (!dev->agp || !dev->agp->acquired)
  65                 return -EINVAL;
  66 
  67         kern = &dev->agp->agp_info;
  68         info->agp_version_major = kern->version.major;
  69         info->agp_version_minor = kern->version.minor;
  70         info->mode = kern->mode;
  71         info->aperture_base = kern->aper_base;
  72         info->aperture_size = kern->aper_size * 1024 * 1024;
  73         info->memory_allowed = kern->max_memory << PAGE_SHIFT;
  74         info->memory_used = kern->current_memory << PAGE_SHIFT;
  75         info->id_vendor = kern->device->vendor;
  76         info->id_device = kern->device->device;
  77 
  78         return 0;
  79 }
  80 EXPORT_SYMBOL(drm_agp_info);
  81 
  82 int drm_agp_info_ioctl(struct drm_device *dev, void *data,
  83                        struct drm_file *file_priv)
  84 {
  85         struct drm_agp_info *info = data;
  86         int err;
  87 
  88         err = drm_agp_info(dev, info);
  89         if (err)
  90                 return err;
  91 
  92         return 0;
  93 }
  94 
  95 /**
  96  * Acquire the AGP device.
  97  *
  98  * \param dev DRM device that is to acquire AGP.
  99  * \return zero on success or a negative number on failure.
 100  *
 101  * Verifies the AGP device hasn't been acquired before and calls
 102  * \c agp_backend_acquire.
 103  */
 104 int drm_agp_acquire(struct drm_device *dev)
 105 {
 106         if (!dev->agp)
 107                 return -ENODEV;
 108         if (dev->agp->acquired)
 109                 return -EBUSY;
 110         dev->agp->bridge = agp_backend_acquire(dev->pdev);
 111         if (!dev->agp->bridge)
 112                 return -ENODEV;
 113         dev->agp->acquired = 1;
 114         return 0;
 115 }
 116 EXPORT_SYMBOL(drm_agp_acquire);
 117 
 118 /**
 119  * Acquire the AGP device (ioctl).
 120  *
 121  * \param inode device inode.
 122  * \param file_priv DRM file private.
 123  * \param cmd command.
 124  * \param arg user argument.
 125  * \return zero on success or a negative number on failure.
 126  *
 127  * Verifies the AGP device hasn't been acquired before and calls
 128  * \c agp_backend_acquire.
 129  */
 130 int drm_agp_acquire_ioctl(struct drm_device *dev, void *data,
 131                           struct drm_file *file_priv)
 132 {
 133         return drm_agp_acquire((struct drm_device *) file_priv->minor->dev);
 134 }
 135 
 136 /**
 137  * Release the AGP device.
 138  *
 139  * \param dev DRM device that is to release AGP.
 140  * \return zero on success or a negative number on failure.
 141  *
 142  * Verifies the AGP device has been acquired and calls \c agp_backend_release.
 143  */
 144 int drm_agp_release(struct drm_device *dev)
 145 {
 146         if (!dev->agp || !dev->agp->acquired)
 147                 return -EINVAL;
 148         agp_backend_release(dev->agp->bridge);
 149         dev->agp->acquired = 0;
 150         return 0;
 151 }
 152 EXPORT_SYMBOL(drm_agp_release);
 153 
 154 int drm_agp_release_ioctl(struct drm_device *dev, void *data,
 155                           struct drm_file *file_priv)
 156 {
 157         return drm_agp_release(dev);
 158 }
 159 
 160 /**
 161  * Enable the AGP bus.
 162  *
 163  * \param dev DRM device that has previously acquired AGP.
 164  * \param mode Requested AGP mode.
 165  * \return zero on success or a negative number on failure.
 166  *
 167  * Verifies the AGP device has been acquired but not enabled, and calls
 168  * \c agp_enable.
 169  */
 170 int drm_agp_enable(struct drm_device *dev, struct drm_agp_mode mode)
 171 {
 172         if (!dev->agp || !dev->agp->acquired)
 173                 return -EINVAL;
 174 
 175         dev->agp->mode = mode.mode;
 176         agp_enable(dev->agp->bridge, mode.mode);
 177         dev->agp->enabled = 1;
 178         return 0;
 179 }
 180 EXPORT_SYMBOL(drm_agp_enable);
 181 
 182 int drm_agp_enable_ioctl(struct drm_device *dev, void *data,
 183                          struct drm_file *file_priv)
 184 {
 185         struct drm_agp_mode *mode = data;
 186 
 187         return drm_agp_enable(dev, *mode);
 188 }
 189 
 190 /**
 191  * Allocate AGP memory.
 192  *
 193  * \param inode device inode.
 194  * \param file_priv file private pointer.
 195  * \param cmd command.
 196  * \param arg pointer to a drm_agp_buffer structure.
 197  * \return zero on success or a negative number on failure.
 198  *
 199  * Verifies the AGP device is present and has been acquired, allocates the
 200  * memory via agp_allocate_memory() and creates a drm_agp_mem entry for it.
 201  */
 202 int drm_agp_alloc(struct drm_device *dev, struct drm_agp_buffer *request)
 203 {
 204         struct drm_agp_mem *entry;
 205         struct agp_memory *memory;
 206         unsigned long pages;
 207         u32 type;
 208 
 209         if (!dev->agp || !dev->agp->acquired)
 210                 return -EINVAL;
 211         entry = kzalloc(sizeof(*entry), GFP_KERNEL);
 212         if (!entry)
 213                 return -ENOMEM;
 214 
 215         pages = (request->size + PAGE_SIZE - 1) / PAGE_SIZE;
 216         type = (u32) request->type;
 217         memory = agp_allocate_memory(dev->agp->bridge, pages, type);
 218         if (!memory) {
 219                 kfree(entry);
 220                 return -ENOMEM;
 221         }
 222 
 223         entry->handle = (unsigned long)memory->key + 1;
 224         entry->memory = memory;
 225         entry->bound = 0;
 226         entry->pages = pages;
 227         list_add(&entry->head, &dev->agp->memory);
 228 
 229         request->handle = entry->handle;
 230         request->physical = memory->physical;
 231 
 232         return 0;
 233 }
 234 EXPORT_SYMBOL(drm_agp_alloc);
 235 
 236 
 237 int drm_agp_alloc_ioctl(struct drm_device *dev, void *data,
 238                         struct drm_file *file_priv)
 239 {
 240         struct drm_agp_buffer *request = data;
 241 
 242         return drm_agp_alloc(dev, request);
 243 }
 244 
 245 /**
 246  * Search for the AGP memory entry associated with a handle.
 247  *
 248  * \param dev DRM device structure.
 249  * \param handle AGP memory handle.
 250  * \return pointer to the drm_agp_mem structure associated with \p handle.
 251  *
 252  * Walks through drm_agp_head::memory until finding a matching handle.
 253  */
 254 static struct drm_agp_mem *drm_agp_lookup_entry(struct drm_device *dev,
 255                                                 unsigned long handle)
 256 {
 257         struct drm_agp_mem *entry;
 258 
 259         list_for_each_entry(entry, &dev->agp->memory, head) {
 260                 if (entry->handle == handle)
 261                         return entry;
 262         }
 263         return NULL;
 264 }
 265 
 266 /**
 267  * Unbind AGP memory from the GATT (ioctl).
 268  *
 269  * \param inode device inode.
 270  * \param file_priv DRM file private.
 271  * \param cmd command.
 272  * \param arg pointer to a drm_agp_binding structure.
 273  * \return zero on success or a negative number on failure.
 274  *
 275  * Verifies the AGP device is present and acquired, looks-up the AGP memory
 276  * entry and passes it to the unbind_agp() function.
 277  */
 278 int drm_agp_unbind(struct drm_device *dev, struct drm_agp_binding *request)
 279 {
 280         struct drm_agp_mem *entry;
 281         int ret;
 282 
 283         if (!dev->agp || !dev->agp->acquired)
 284                 return -EINVAL;
 285         entry = drm_agp_lookup_entry(dev, request->handle);
 286         if (!entry || !entry->bound)
 287                 return -EINVAL;
 288         ret = drm_unbind_agp(entry->memory);
 289         if (ret == 0)
 290                 entry->bound = 0;
 291         return ret;
 292 }
 293 EXPORT_SYMBOL(drm_agp_unbind);
 294 
 295 
 296 int drm_agp_unbind_ioctl(struct drm_device *dev, void *data,
 297                          struct drm_file *file_priv)
 298 {
 299         struct drm_agp_binding *request = data;
 300 
 301         return drm_agp_unbind(dev, request);
 302 }
 303 
 304 /**
 305  * Bind AGP memory into the GATT (ioctl)
 306  *
 307  * \param inode device inode.
 308  * \param file_priv DRM file private.
 309  * \param cmd command.
 310  * \param arg pointer to a drm_agp_binding structure.
 311  * \return zero on success or a negative number on failure.
 312  *
 313  * Verifies the AGP device is present and has been acquired and that no memory
 314  * is currently bound into the GATT. Looks-up the AGP memory entry and passes
 315  * it to bind_agp() function.
 316  */
 317 int drm_agp_bind(struct drm_device *dev, struct drm_agp_binding *request)
 318 {
 319         struct drm_agp_mem *entry;
 320         int retcode;
 321         int page;
 322 
 323         if (!dev->agp || !dev->agp->acquired)
 324                 return -EINVAL;
 325         entry = drm_agp_lookup_entry(dev, request->handle);
 326         if (!entry || entry->bound)
 327                 return -EINVAL;
 328         page = (request->offset + PAGE_SIZE - 1) / PAGE_SIZE;
 329         retcode = drm_bind_agp(entry->memory, page);
 330         if (retcode)
 331                 return retcode;
 332         entry->bound = dev->agp->base + (page << PAGE_SHIFT);
 333         DRM_DEBUG("base = 0x%lx entry->bound = 0x%lx\n",
 334                   dev->agp->base, entry->bound);
 335         return 0;
 336 }
 337 EXPORT_SYMBOL(drm_agp_bind);
 338 
 339 
 340 int drm_agp_bind_ioctl(struct drm_device *dev, void *data,
 341                        struct drm_file *file_priv)
 342 {
 343         struct drm_agp_binding *request = data;
 344 
 345         return drm_agp_bind(dev, request);
 346 }
 347 
 348 /**
 349  * Free AGP memory (ioctl).
 350  *
 351  * \param inode device inode.
 352  * \param file_priv DRM file private.
 353  * \param cmd command.
 354  * \param arg pointer to a drm_agp_buffer structure.
 355  * \return zero on success or a negative number on failure.
 356  *
 357  * Verifies the AGP device is present and has been acquired and looks up the
 358  * AGP memory entry. If the memory is currently bound, unbind it via
 359  * unbind_agp(). Frees it via free_agp() as well as the entry itself
 360  * and unlinks from the doubly linked list it's inserted in.
 361  */
 362 int drm_agp_free(struct drm_device *dev, struct drm_agp_buffer *request)
 363 {
 364         struct drm_agp_mem *entry;
 365 
 366         if (!dev->agp || !dev->agp->acquired)
 367                 return -EINVAL;
 368         entry = drm_agp_lookup_entry(dev, request->handle);
 369         if (!entry)
 370                 return -EINVAL;
 371         if (entry->bound)
 372                 drm_unbind_agp(entry->memory);
 373 
 374         list_del(&entry->head);
 375 
 376         drm_free_agp(entry->memory, entry->pages);
 377         kfree(entry);
 378         return 0;
 379 }
 380 EXPORT_SYMBOL(drm_agp_free);
 381 
 382 
 383 int drm_agp_free_ioctl(struct drm_device *dev, void *data,
 384                        struct drm_file *file_priv)
 385 {
 386         struct drm_agp_buffer *request = data;
 387 
 388         return drm_agp_free(dev, request);
 389 }
 390 
 391 /**
 392  * Initialize the AGP resources.
 393  *
 394  * \return pointer to a drm_agp_head structure.
 395  *
 396  * Gets the drm_agp_t structure which is made available by the agpgart module
 397  * via the inter_module_* functions. Creates and initializes a drm_agp_head
 398  * structure.
 399  *
 400  * Note that final cleanup of the kmalloced structure is directly done in
 401  * drm_pci_agp_destroy.
 402  */
 403 struct drm_agp_head *drm_agp_init(struct drm_device *dev)
 404 {
 405         struct drm_agp_head *head = NULL;
 406 
 407         head = kzalloc(sizeof(*head), GFP_KERNEL);
 408         if (!head)
 409                 return NULL;
 410         head->bridge = agp_find_bridge(dev->pdev);
 411         if (!head->bridge) {
 412                 head->bridge = agp_backend_acquire(dev->pdev);
 413                 if (!head->bridge) {
 414                         kfree(head);
 415                         return NULL;
 416                 }
 417                 agp_copy_info(head->bridge, &head->agp_info);
 418                 agp_backend_release(head->bridge);
 419         } else {
 420                 agp_copy_info(head->bridge, &head->agp_info);
 421         }
 422         if (head->agp_info.chipset == NOT_SUPPORTED) {
 423                 kfree(head);
 424                 return NULL;
 425         }
 426         INIT_LIST_HEAD(&head->memory);
 427         head->cant_use_aperture = head->agp_info.cant_use_aperture;
 428         head->page_mask = head->agp_info.page_mask;
 429         head->base = head->agp_info.aper_base;
 430         return head;
 431 }
 432 /* Only exported for i810.ko */
 433 EXPORT_SYMBOL(drm_agp_init);
 434 
 435 /**
 436  * drm_legacy_agp_clear - Clear AGP resource list
 437  * @dev: DRM device
 438  *
 439  * Iterate over all AGP resources and remove them. But keep the AGP head
 440  * intact so it can still be used. It is safe to call this if AGP is disabled or
 441  * was already removed.
 442  *
 443  * Cleanup is only done for drivers who have DRIVER_LEGACY set.
 444  */
 445 void drm_legacy_agp_clear(struct drm_device *dev)
 446 {
 447         struct drm_agp_mem *entry, *tempe;
 448 
 449         if (!dev->agp)
 450                 return;
 451         if (!drm_core_check_feature(dev, DRIVER_LEGACY))
 452                 return;
 453 
 454         list_for_each_entry_safe(entry, tempe, &dev->agp->memory, head) {
 455                 if (entry->bound)
 456                         drm_unbind_agp(entry->memory);
 457                 drm_free_agp(entry->memory, entry->pages);
 458                 kfree(entry);
 459         }
 460         INIT_LIST_HEAD(&dev->agp->memory);
 461 
 462         if (dev->agp->acquired)
 463                 drm_agp_release(dev);
 464 
 465         dev->agp->acquired = 0;
 466         dev->agp->enabled = 0;
 467 }

/* [<][>][^][v][top][bottom][index][help] */