diff options
| author | Linus Torvalds <torvalds@g5.osdl.org> | 2006-09-30 14:29:54 -0400 |
|---|---|---|
| committer | Linus Torvalds <torvalds@g5.osdl.org> | 2006-09-30 14:29:54 -0400 |
| commit | e823aff2d6eb43083abcc75a32ddfb167c324089 (patch) | |
| tree | 60b67f3f2f088d6741a5af8488b4a565fb4c4cfe | |
| parent | 77ed74da26f50fa28471571ee7a2251b77526d84 (diff) | |
| parent | 3e14a2867d8ccf555fe6e318eac0f8200399fe1c (diff) | |
Merge branch 'drm-patches' of git://git.kernel.org/pub/scm/linux/kernel/git/airlied/drm-2.6
* 'drm-patches' of git://git.kernel.org/pub/scm/linux/kernel/git/airlied/drm-2.6: (36 commits)
drm: Use register writes instead of BITBLT_MULTI packets for buffer swap blits
drm: use radeon specific names for radeon flags
drm: add device/vendor id to drm_device_t for compat with FreeBSD drivers
drm: allow multiple addMaps with the same 32-bit map offsset.
drm: fd.o Bug #7595: Avoid u32 overflows in radeon_check_and_fixup_offset().
drm: Fix hashtab implementation leaking illegal error codes to user space.
drm: domain changes broke ppc r200
drm: fixup setversion return codes..
drm: fixup i915 error codes
drm: realign sosme radeon code with drm git tree
drm: realign via driver with drm git tree
drm: remove hash tables on drm exit
drm: cleanups
drm: i810_dma.c: fix pointer arithmetic for 64-bit target
drm: avoid kernel oops in some error paths calling drm_lastclose
drm: allow detection of new VIA chipsets
drm: fix i965 build bug
drm: remove FALSE/TRUE that snuck in with simple memory manager changes.
drm: Add support for Intel i965G chipsets.
drm: add better explanation for i830/i915
...
42 files changed, 1878 insertions, 1772 deletions
diff --git a/drivers/char/drm/Kconfig b/drivers/char/drm/Kconfig index 5278c388d3e7..ef833a1c27eb 100644 --- a/drivers/char/drm/Kconfig +++ b/drivers/char/drm/Kconfig | |||
| @@ -60,7 +60,9 @@ config DRM_I830 | |||
| 60 | Choose this option if you have a system that has Intel 830M, 845G, | 60 | Choose this option if you have a system that has Intel 830M, 845G, |
| 61 | 852GM, 855GM or 865G integrated graphics. If M is selected, the | 61 | 852GM, 855GM or 865G integrated graphics. If M is selected, the |
| 62 | module will be called i830. AGP support is required for this driver | 62 | module will be called i830. AGP support is required for this driver |
| 63 | to work. This driver will eventually be replaced by the i915 one. | 63 | to work. This driver is used by the older X releases X.org 6.7 and |
| 64 | XFree86 4.3. If unsure, build this and i915 as modules and the X server | ||
| 65 | will load the correct one. | ||
| 64 | 66 | ||
| 65 | config DRM_I915 | 67 | config DRM_I915 |
| 66 | tristate "i915 driver" | 68 | tristate "i915 driver" |
| @@ -68,8 +70,9 @@ config DRM_I915 | |||
| 68 | Choose this option if you have a system that has Intel 830M, 845G, | 70 | Choose this option if you have a system that has Intel 830M, 845G, |
| 69 | 852GM, 855GM 865G or 915G integrated graphics. If M is selected, the | 71 | 852GM, 855GM 865G or 915G integrated graphics. If M is selected, the |
| 70 | module will be called i915. AGP support is required for this driver | 72 | module will be called i915. AGP support is required for this driver |
| 71 | to work. This driver will eventually replace the I830 driver, when | 73 | to work. This driver is used by the Intel driver in X.org 6.8 and |
| 72 | later release of X start to use the new DDX and DRI. | 74 | XFree86 4.4 and above. If unsure, build this and i830 as modules and |
| 75 | the X server will load the correct one. | ||
| 73 | 76 | ||
| 74 | endchoice | 77 | endchoice |
| 75 | 78 | ||
diff --git a/drivers/char/drm/Makefile b/drivers/char/drm/Makefile index 9d180c42816c..3ad0f648c6b2 100644 --- a/drivers/char/drm/Makefile +++ b/drivers/char/drm/Makefile | |||
| @@ -6,7 +6,7 @@ drm-objs := drm_auth.o drm_bufs.o drm_context.o drm_dma.o drm_drawable.o \ | |||
| 6 | drm_drv.o drm_fops.o drm_ioctl.o drm_irq.o \ | 6 | drm_drv.o drm_fops.o drm_ioctl.o drm_irq.o \ |
| 7 | drm_lock.o drm_memory.o drm_proc.o drm_stub.o drm_vm.o \ | 7 | drm_lock.o drm_memory.o drm_proc.o drm_stub.o drm_vm.o \ |
| 8 | drm_agpsupport.o drm_scatter.o ati_pcigart.o drm_pci.o \ | 8 | drm_agpsupport.o drm_scatter.o ati_pcigart.o drm_pci.o \ |
| 9 | drm_sysfs.o | 9 | drm_sysfs.o drm_hashtab.o drm_sman.o drm_mm.o |
| 10 | 10 | ||
| 11 | tdfx-objs := tdfx_drv.o | 11 | tdfx-objs := tdfx_drv.o |
| 12 | r128-objs := r128_drv.o r128_cce.o r128_state.o r128_irq.o | 12 | r128-objs := r128_drv.o r128_cce.o r128_state.o r128_irq.o |
| @@ -16,9 +16,9 @@ i830-objs := i830_drv.o i830_dma.o i830_irq.o | |||
| 16 | i915-objs := i915_drv.o i915_dma.o i915_irq.o i915_mem.o | 16 | i915-objs := i915_drv.o i915_dma.o i915_irq.o i915_mem.o |
| 17 | radeon-objs := radeon_drv.o radeon_cp.o radeon_state.o radeon_mem.o radeon_irq.o r300_cmdbuf.o | 17 | radeon-objs := radeon_drv.o radeon_cp.o radeon_state.o radeon_mem.o radeon_irq.o r300_cmdbuf.o |
| 18 | ffb-objs := ffb_drv.o ffb_context.o | 18 | ffb-objs := ffb_drv.o ffb_context.o |
| 19 | sis-objs := sis_drv.o sis_ds.o sis_mm.o | 19 | sis-objs := sis_drv.o sis_mm.o |
| 20 | savage-objs := savage_drv.o savage_bci.o savage_state.o | 20 | savage-objs := savage_drv.o savage_bci.o savage_state.o |
| 21 | via-objs := via_irq.o via_drv.o via_ds.o via_map.o via_mm.o via_dma.o via_verifier.o via_video.o via_dmablit.o | 21 | via-objs := via_irq.o via_drv.o via_map.o via_mm.o via_dma.o via_verifier.o via_video.o via_dmablit.o |
| 22 | 22 | ||
| 23 | ifeq ($(CONFIG_COMPAT),y) | 23 | ifeq ($(CONFIG_COMPAT),y) |
| 24 | drm-objs += drm_ioc32.o | 24 | drm-objs += drm_ioc32.o |
diff --git a/drivers/char/drm/drmP.h b/drivers/char/drm/drmP.h index d2a56182bc35..7690a59ace04 100644 --- a/drivers/char/drm/drmP.h +++ b/drivers/char/drm/drmP.h | |||
| @@ -79,6 +79,7 @@ | |||
| 79 | #define __OS_HAS_MTRR (defined(CONFIG_MTRR)) | 79 | #define __OS_HAS_MTRR (defined(CONFIG_MTRR)) |
| 80 | 80 | ||
| 81 | #include "drm_os_linux.h" | 81 | #include "drm_os_linux.h" |
| 82 | #include "drm_hashtab.h" | ||
| 82 | 83 | ||
| 83 | /***********************************************************************/ | 84 | /***********************************************************************/ |
| 84 | /** \name DRM template customization defaults */ | 85 | /** \name DRM template customization defaults */ |
| @@ -104,7 +105,7 @@ | |||
| 104 | #define DRM_DEBUG_CODE 2 /**< Include debugging code if > 1, then | 105 | #define DRM_DEBUG_CODE 2 /**< Include debugging code if > 1, then |
| 105 | also include looping detection. */ | 106 | also include looping detection. */ |
| 106 | 107 | ||
| 107 | #define DRM_HASH_SIZE 16 /**< Size of key hash table. Must be power of 2. */ | 108 | #define DRM_MAGIC_HASH_ORDER 4 /**< Size of key hash table. Must be power of 2. */ |
| 108 | #define DRM_KERNEL_CONTEXT 0 /**< Change drm_resctx if changed */ | 109 | #define DRM_KERNEL_CONTEXT 0 /**< Change drm_resctx if changed */ |
| 109 | #define DRM_RESERVED_CONTEXTS 1 /**< Change drm_resctx if changed */ | 110 | #define DRM_RESERVED_CONTEXTS 1 /**< Change drm_resctx if changed */ |
| 110 | #define DRM_LOOPING_LIMIT 5000000 | 111 | #define DRM_LOOPING_LIMIT 5000000 |
| @@ -134,19 +135,12 @@ | |||
| 134 | #define DRM_MEM_CTXBITMAP 18 | 135 | #define DRM_MEM_CTXBITMAP 18 |
| 135 | #define DRM_MEM_STUB 19 | 136 | #define DRM_MEM_STUB 19 |
| 136 | #define DRM_MEM_SGLISTS 20 | 137 | #define DRM_MEM_SGLISTS 20 |
| 137 | #define DRM_MEM_CTXLIST 21 | 138 | #define DRM_MEM_CTXLIST 21 |
| 139 | #define DRM_MEM_MM 22 | ||
| 140 | #define DRM_MEM_HASHTAB 23 | ||
| 138 | 141 | ||
| 139 | #define DRM_MAX_CTXBITMAP (PAGE_SIZE * 8) | 142 | #define DRM_MAX_CTXBITMAP (PAGE_SIZE * 8) |
| 140 | 143 | #define DRM_MAP_HASH_OFFSET 0x10000000 | |
| 141 | /*@}*/ | ||
| 142 | |||
| 143 | /***********************************************************************/ | ||
| 144 | /** \name Backward compatibility section */ | ||
| 145 | /*@{*/ | ||
| 146 | |||
| 147 | #define DRM_RPR_ARG(vma) vma, | ||
| 148 | |||
| 149 | #define VM_OFFSET(vma) ((vma)->vm_pgoff << PAGE_SHIFT) | ||
| 150 | 144 | ||
| 151 | /*@}*/ | 145 | /*@}*/ |
| 152 | 146 | ||
| @@ -211,8 +205,6 @@ | |||
| 211 | /*@{*/ | 205 | /*@{*/ |
| 212 | 206 | ||
| 213 | #define DRM_ARRAY_SIZE(x) ARRAY_SIZE(x) | 207 | #define DRM_ARRAY_SIZE(x) ARRAY_SIZE(x) |
| 214 | #define DRM_MIN(a,b) min(a,b) | ||
| 215 | #define DRM_MAX(a,b) max(a,b) | ||
| 216 | 208 | ||
| 217 | #define DRM_LEFTCOUNT(x) (((x)->rp + (x)->count - (x)->wp) % ((x)->count + 1)) | 209 | #define DRM_LEFTCOUNT(x) (((x)->rp + (x)->count - (x)->wp) % ((x)->count + 1)) |
| 218 | #define DRM_BUFCOUNT(x) ((x)->count - DRM_LEFTCOUNT(x)) | 210 | #define DRM_BUFCOUNT(x) ((x)->count - DRM_LEFTCOUNT(x)) |
| @@ -286,7 +278,8 @@ typedef struct drm_devstate { | |||
| 286 | } drm_devstate_t; | 278 | } drm_devstate_t; |
| 287 | 279 | ||
| 288 | typedef struct drm_magic_entry { | 280 | typedef struct drm_magic_entry { |
| 289 | drm_magic_t magic; | 281 | drm_hash_item_t hash_item; |
| 282 | struct list_head head; | ||
| 290 | struct drm_file *priv; | 283 | struct drm_file *priv; |
| 291 | struct drm_magic_entry *next; | 284 | struct drm_magic_entry *next; |
| 292 | } drm_magic_entry_t; | 285 | } drm_magic_entry_t; |
| @@ -493,6 +486,7 @@ typedef struct drm_sigdata { | |||
| 493 | */ | 486 | */ |
| 494 | typedef struct drm_map_list { | 487 | typedef struct drm_map_list { |
| 495 | struct list_head head; /**< list head */ | 488 | struct list_head head; /**< list head */ |
| 489 | drm_hash_item_t hash; | ||
| 496 | drm_map_t *map; /**< mapping */ | 490 | drm_map_t *map; /**< mapping */ |
| 497 | unsigned int user_token; | 491 | unsigned int user_token; |
| 498 | } drm_map_list_t; | 492 | } drm_map_list_t; |
| @@ -527,6 +521,22 @@ typedef struct ati_pcigart_info { | |||
| 527 | drm_local_map_t mapping; | 521 | drm_local_map_t mapping; |
| 528 | } drm_ati_pcigart_info; | 522 | } drm_ati_pcigart_info; |
| 529 | 523 | ||
| 524 | /* | ||
| 525 | * Generic memory manager structs | ||
| 526 | */ | ||
| 527 | typedef struct drm_mm_node { | ||
| 528 | struct list_head fl_entry; | ||
| 529 | struct list_head ml_entry; | ||
| 530 | int free; | ||
| 531 | unsigned long start; | ||
| 532 | unsigned long size; | ||
| 533 | void *private; | ||
| 534 | } drm_mm_node_t; | ||
| 535 | |||
| 536 | typedef struct drm_mm { | ||
| 537 | drm_mm_node_t root_node; | ||
| 538 | } drm_mm_t; | ||
| 539 | |||
| 530 | /** | 540 | /** |
| 531 | * DRM driver structure. This structure represent the common code for | 541 | * DRM driver structure. This structure represent the common code for |
| 532 | * a family of cards. There will one drm_device for each card present | 542 | * a family of cards. There will one drm_device for each card present |
| @@ -646,13 +656,15 @@ typedef struct drm_device { | |||
| 646 | /*@{ */ | 656 | /*@{ */ |
| 647 | drm_file_t *file_first; /**< file list head */ | 657 | drm_file_t *file_first; /**< file list head */ |
| 648 | drm_file_t *file_last; /**< file list tail */ | 658 | drm_file_t *file_last; /**< file list tail */ |
| 649 | drm_magic_head_t magiclist[DRM_HASH_SIZE]; /**< magic hash table */ | 659 | drm_open_hash_t magiclist; /**< magic hash table */ |
| 660 | struct list_head magicfree; | ||
| 650 | /*@} */ | 661 | /*@} */ |
| 651 | 662 | ||
| 652 | /** \name Memory management */ | 663 | /** \name Memory management */ |
| 653 | /*@{ */ | 664 | /*@{ */ |
| 654 | drm_map_list_t *maplist; /**< Linked list of regions */ | 665 | drm_map_list_t *maplist; /**< Linked list of regions */ |
| 655 | int map_count; /**< Number of mappable regions */ | 666 | int map_count; /**< Number of mappable regions */ |
| 667 | drm_open_hash_t map_hash; /**< User token hash table for maps */ | ||
| 656 | 668 | ||
| 657 | /** \name Context handle management */ | 669 | /** \name Context handle management */ |
| 658 | /*@{ */ | 670 | /*@{ */ |
| @@ -711,10 +723,8 @@ typedef struct drm_device { | |||
| 711 | drm_agp_head_t *agp; /**< AGP data */ | 723 | drm_agp_head_t *agp; /**< AGP data */ |
| 712 | 724 | ||
| 713 | struct pci_dev *pdev; /**< PCI device structure */ | 725 | struct pci_dev *pdev; /**< PCI device structure */ |
| 714 | int pci_domain; /**< PCI bus domain number */ | 726 | int pci_vendor; /**< PCI vendor id */ |
| 715 | int pci_bus; /**< PCI bus number */ | 727 | int pci_device; /**< PCI device id */ |
| 716 | int pci_slot; /**< PCI slot number */ | ||
| 717 | int pci_func; /**< PCI function number */ | ||
| 718 | #ifdef __alpha__ | 728 | #ifdef __alpha__ |
| 719 | struct pci_controller *hose; | 729 | struct pci_controller *hose; |
| 720 | #endif | 730 | #endif |
| @@ -736,6 +746,12 @@ static __inline__ int drm_core_check_feature(struct drm_device *dev, | |||
| 736 | return ((dev->driver->driver_features & feature) ? 1 : 0); | 746 | return ((dev->driver->driver_features & feature) ? 1 : 0); |
| 737 | } | 747 | } |
| 738 | 748 | ||
| 749 | #ifdef __alpha__ | ||
| 750 | #define drm_get_pci_domain(dev) dev->hose->bus->number | ||
| 751 | #else | ||
| 752 | #define drm_get_pci_domain(dev) 0 | ||
| 753 | #endif | ||
| 754 | |||
| 739 | #if __OS_HAS_AGP | 755 | #if __OS_HAS_AGP |
| 740 | static inline int drm_core_has_AGP(struct drm_device *dev) | 756 | static inline int drm_core_has_AGP(struct drm_device *dev) |
| 741 | { | 757 | { |
| @@ -1011,6 +1027,18 @@ extern struct class_device *drm_sysfs_device_add(struct class *cs, | |||
| 1011 | drm_head_t *head); | 1027 | drm_head_t *head); |
| 1012 | extern void drm_sysfs_device_remove(struct class_device *class_dev); | 1028 | extern void drm_sysfs_device_remove(struct class_device *class_dev); |
| 1013 | 1029 | ||
| 1030 | /* | ||
| 1031 | * Basic memory manager support (drm_mm.c) | ||
| 1032 | */ | ||
| 1033 | extern drm_mm_node_t *drm_mm_get_block(drm_mm_node_t * parent, | ||
| 1034 | unsigned long size, | ||
| 1035 | unsigned alignment); | ||
| 1036 | extern void drm_mm_put_block(drm_mm_t *mm, drm_mm_node_t *cur); | ||
| 1037 | extern drm_mm_node_t *drm_mm_search_free(const drm_mm_t *mm, unsigned long size, | ||
| 1038 | unsigned alignment, int best_match); | ||
| 1039 | extern int drm_mm_init(drm_mm_t *mm, unsigned long start, unsigned long size); | ||
| 1040 | extern void drm_mm_takedown(drm_mm_t *mm); | ||
| 1041 | |||
| 1014 | /* Inline replacements for DRM_IOREMAP macros */ | 1042 | /* Inline replacements for DRM_IOREMAP macros */ |
| 1015 | static __inline__ void drm_core_ioremap(struct drm_map *map, | 1043 | static __inline__ void drm_core_ioremap(struct drm_map *map, |
| 1016 | struct drm_device *dev) | 1044 | struct drm_device *dev) |
diff --git a/drivers/char/drm/drm_auth.c b/drivers/char/drm/drm_auth.c index 2a37586a7ee8..c7b19d35bcd6 100644 --- a/drivers/char/drm/drm_auth.c +++ b/drivers/char/drm/drm_auth.c | |||
| @@ -36,20 +36,6 @@ | |||
| 36 | #include "drmP.h" | 36 | #include "drmP.h" |
| 37 | 37 | ||
| 38 | /** | 38 | /** |
| 39 | * Generate a hash key from a magic. | ||
| 40 | * | ||
| 41 | * \param magic magic. | ||
| 42 | * \return hash key. | ||
| 43 | * | ||
| 44 | * The key is the modulus of the hash table size, #DRM_HASH_SIZE, which must be | ||
| 45 | * a power of 2. | ||
| 46 | */ | ||
| 47 | static int drm_hash_magic(drm_magic_t magic) | ||
| 48 | { | ||
| 49 | return magic & (DRM_HASH_SIZE - 1); | ||
| 50 | } | ||
| 51 | |||
| 52 | /** | ||
| 53 | * Find the file with the given magic number. | 39 | * Find the file with the given magic number. |
| 54 | * | 40 | * |
| 55 | * \param dev DRM device. | 41 | * \param dev DRM device. |
| @@ -63,14 +49,12 @@ static drm_file_t *drm_find_file(drm_device_t * dev, drm_magic_t magic) | |||
| 63 | { | 49 | { |
| 64 | drm_file_t *retval = NULL; | 50 | drm_file_t *retval = NULL; |
| 65 | drm_magic_entry_t *pt; | 51 | drm_magic_entry_t *pt; |
| 66 | int hash = drm_hash_magic(magic); | 52 | drm_hash_item_t *hash; |
| 67 | 53 | ||
| 68 | mutex_lock(&dev->struct_mutex); | 54 | mutex_lock(&dev->struct_mutex); |
| 69 | for (pt = dev->magiclist[hash].head; pt; pt = pt->next) { | 55 | if (!drm_ht_find_item(&dev->magiclist, (unsigned long)magic, &hash)) { |
| 70 | if (pt->magic == magic) { | 56 | pt = drm_hash_entry(hash, drm_magic_entry_t, hash_item); |
| 71 | retval = pt->priv; | 57 | retval = pt->priv; |
| 72 | break; | ||
| 73 | } | ||
| 74 | } | 58 | } |
| 75 | mutex_unlock(&dev->struct_mutex); | 59 | mutex_unlock(&dev->struct_mutex); |
| 76 | return retval; | 60 | return retval; |
| @@ -90,28 +74,20 @@ static drm_file_t *drm_find_file(drm_device_t * dev, drm_magic_t magic) | |||
| 90 | static int drm_add_magic(drm_device_t * dev, drm_file_t * priv, | 74 | static int drm_add_magic(drm_device_t * dev, drm_file_t * priv, |
| 91 | drm_magic_t magic) | 75 | drm_magic_t magic) |
| 92 | { | 76 | { |
| 93 | int hash; | ||
| 94 | drm_magic_entry_t *entry; | 77 | drm_magic_entry_t *entry; |
| 95 | 78 | ||
| 96 | DRM_DEBUG("%d\n", magic); | 79 | DRM_DEBUG("%d\n", magic); |
| 97 | 80 | ||
| 98 | hash = drm_hash_magic(magic); | ||
| 99 | entry = drm_alloc(sizeof(*entry), DRM_MEM_MAGIC); | 81 | entry = drm_alloc(sizeof(*entry), DRM_MEM_MAGIC); |
| 100 | if (!entry) | 82 | if (!entry) |
| 101 | return -ENOMEM; | 83 | return -ENOMEM; |
| 102 | memset(entry, 0, sizeof(*entry)); | 84 | memset(entry, 0, sizeof(*entry)); |
| 103 | entry->magic = magic; | ||
| 104 | entry->priv = priv; | 85 | entry->priv = priv; |
| 105 | entry->next = NULL; | ||
| 106 | 86 | ||
| 87 | entry->hash_item.key = (unsigned long)magic; | ||
| 107 | mutex_lock(&dev->struct_mutex); | 88 | mutex_lock(&dev->struct_mutex); |
| 108 | if (dev->magiclist[hash].tail) { | 89 | drm_ht_insert_item(&dev->magiclist, &entry->hash_item); |
| 109 | dev->magiclist[hash].tail->next = entry; | 90 | list_add_tail(&entry->head, &dev->magicfree); |
| 110 | dev->magiclist[hash].tail = entry; | ||
| 111 | } else { | ||
| 112 | dev->magiclist[hash].head = entry; | ||
| 113 | dev->magiclist[hash].tail = entry; | ||
| 114 | } | ||
| 115 | mutex_unlock(&dev->struct_mutex); | 91 | mutex_unlock(&dev->struct_mutex); |
| 116 | 92 | ||
| 117 | return 0; | 93 | return 0; |
| @@ -128,34 +104,24 @@ static int drm_add_magic(drm_device_t * dev, drm_file_t * priv, | |||
| 128 | */ | 104 | */ |
| 129 | static int drm_remove_magic(drm_device_t * dev, drm_magic_t magic) | 105 | static int drm_remove_magic(drm_device_t * dev, drm_magic_t magic) |
| 130 | { | 106 | { |
| 131 | drm_magic_entry_t *prev = NULL; | ||
| 132 | drm_magic_entry_t *pt; | 107 | drm_magic_entry_t *pt; |
| 133 | int hash; | 108 | drm_hash_item_t *hash; |
| 134 | 109 | ||
| 135 | DRM_DEBUG("%d\n", magic); | 110 | DRM_DEBUG("%d\n", magic); |
| 136 | hash = drm_hash_magic(magic); | ||
| 137 | 111 | ||
| 138 | mutex_lock(&dev->struct_mutex); | 112 | mutex_lock(&dev->struct_mutex); |
| 139 | for (pt = dev->magiclist[hash].head; pt; prev = pt, pt = pt->next) { | 113 | if (drm_ht_find_item(&dev->magiclist, (unsigned long)magic, &hash)) { |
| 140 | if (pt->magic == magic) { | 114 | mutex_unlock(&dev->struct_mutex); |
| 141 | if (dev->magiclist[hash].head == pt) { | 115 | return -EINVAL; |
| 142 | dev->magiclist[hash].head = pt->next; | ||
| 143 | } | ||
| 144 | if (dev->magiclist[hash].tail == pt) { | ||
| 145 | dev->magiclist[hash].tail = prev; | ||
| 146 | } | ||
| 147 | if (prev) { | ||
| 148 | prev->next = pt->next; | ||
| 149 | } | ||
| 150 | mutex_unlock(&dev->struct_mutex); | ||
| 151 | return 0; | ||
| 152 | } | ||
| 153 | } | 116 | } |
| 117 | pt = drm_hash_entry(hash, drm_magic_entry_t, hash_item); | ||
| 118 | drm_ht_remove_item(&dev->magiclist, hash); | ||
| 119 | list_del(&pt->head); | ||
| 154 | mutex_unlock(&dev->struct_mutex); | 120 | mutex_unlock(&dev->struct_mutex); |
| 155 | 121 | ||
| 156 | drm_free(pt, sizeof(*pt), DRM_MEM_MAGIC); | 122 | drm_free(pt, sizeof(*pt), DRM_MEM_MAGIC); |
| 157 | 123 | ||
| 158 | return -EINVAL; | 124 | return 0; |
| 159 | } | 125 | } |
| 160 | 126 | ||
| 161 | /** | 127 | /** |
diff --git a/drivers/char/drm/drm_bufs.c b/drivers/char/drm/drm_bufs.c index 006b06d29727..029baea33b62 100644 --- a/drivers/char/drm/drm_bufs.c +++ b/drivers/char/drm/drm_bufs.c | |||
| @@ -65,43 +65,29 @@ static drm_map_list_t *drm_find_matching_map(drm_device_t *dev, | |||
| 65 | return NULL; | 65 | return NULL; |
| 66 | } | 66 | } |
| 67 | 67 | ||
| 68 | /* | 68 | static int drm_map_handle(drm_device_t *dev, drm_hash_item_t *hash, |
| 69 | * Used to allocate 32-bit handles for mappings. | 69 | unsigned long user_token, int hashed_handle) |
| 70 | */ | ||
| 71 | #define START_RANGE 0x10000000 | ||
| 72 | #define END_RANGE 0x40000000 | ||
| 73 | |||
| 74 | #ifdef _LP64 | ||
| 75 | static __inline__ unsigned int HandleID(unsigned long lhandle, | ||
| 76 | drm_device_t *dev) | ||
| 77 | { | 70 | { |
| 78 | static unsigned int map32_handle = START_RANGE; | 71 | int use_hashed_handle; |
| 79 | unsigned int hash; | 72 | #if (BITS_PER_LONG == 64) |
| 80 | 73 | use_hashed_handle = ((user_token & 0xFFFFFFFF00000000UL) || hashed_handle); | |
| 81 | if (lhandle & 0xffffffff00000000) { | 74 | #elif (BITS_PER_LONG == 32) |
| 82 | hash = map32_handle; | 75 | use_hashed_handle = hashed_handle; |
| 83 | map32_handle += PAGE_SIZE; | 76 | #else |
| 84 | if (map32_handle > END_RANGE) | 77 | #error Unsupported long size. Neither 64 nor 32 bits. |
| 85 | map32_handle = START_RANGE; | 78 | #endif |
| 86 | } else | ||
| 87 | hash = lhandle; | ||
| 88 | |||
| 89 | while (1) { | ||
| 90 | drm_map_list_t *_entry; | ||
| 91 | list_for_each_entry(_entry, &dev->maplist->head, head) { | ||
| 92 | if (_entry->user_token == hash) | ||
| 93 | break; | ||
| 94 | } | ||
| 95 | if (&_entry->head == &dev->maplist->head) | ||
| 96 | return hash; | ||
| 97 | 79 | ||
| 98 | hash += PAGE_SIZE; | 80 | if (!use_hashed_handle) { |
| 99 | map32_handle += PAGE_SIZE; | 81 | int ret; |
| 82 | hash->key = user_token; | ||
| 83 | ret = drm_ht_insert_item(&dev->map_hash, hash); | ||
| 84 | if (ret != -EINVAL) | ||
| 85 | return ret; | ||
| 100 | } | 86 | } |
| 87 | return drm_ht_just_insert_please(&dev->map_hash, hash, | ||
| 88 | user_token, 32 - PAGE_SHIFT - 3, | ||
| 89 | PAGE_SHIFT, DRM_MAP_HASH_OFFSET); | ||
| 101 | } | 90 | } |
| 102 | #else | ||
| 103 | # define HandleID(x,dev) (unsigned int)(x) | ||
| 104 | #endif | ||
| 105 | 91 | ||
| 106 | /** | 92 | /** |
| 107 | * Ioctl to specify a range of memory that is available for mapping by a non-root process. | 93 | * Ioctl to specify a range of memory that is available for mapping by a non-root process. |
| @@ -123,6 +109,8 @@ static int drm_addmap_core(drm_device_t * dev, unsigned int offset, | |||
| 123 | drm_map_t *map; | 109 | drm_map_t *map; |
| 124 | drm_map_list_t *list; | 110 | drm_map_list_t *list; |
| 125 | drm_dma_handle_t *dmah; | 111 | drm_dma_handle_t *dmah; |
| 112 | unsigned long user_token; | ||
| 113 | int ret; | ||
| 126 | 114 | ||
| 127 | map = drm_alloc(sizeof(*map), DRM_MEM_MAPS); | 115 | map = drm_alloc(sizeof(*map), DRM_MEM_MAPS); |
| 128 | if (!map) | 116 | if (!map) |
| @@ -257,11 +245,20 @@ static int drm_addmap_core(drm_device_t * dev, unsigned int offset, | |||
| 257 | 245 | ||
| 258 | mutex_lock(&dev->struct_mutex); | 246 | mutex_lock(&dev->struct_mutex); |
| 259 | list_add(&list->head, &dev->maplist->head); | 247 | list_add(&list->head, &dev->maplist->head); |
| 248 | |||
| 260 | /* Assign a 32-bit handle */ | 249 | /* Assign a 32-bit handle */ |
| 261 | /* We do it here so that dev->struct_mutex protects the increment */ | 250 | /* We do it here so that dev->struct_mutex protects the increment */ |
| 262 | list->user_token = HandleID(map->type == _DRM_SHM | 251 | user_token = (map->type == _DRM_SHM) ? (unsigned long)map->handle : |
| 263 | ? (unsigned long)map->handle | 252 | map->offset; |
| 264 | : map->offset, dev); | 253 | ret = drm_map_handle(dev, &list->hash, user_token, 0); |
| 254 | if (ret) { | ||
| 255 | drm_free(map, sizeof(*map), DRM_MEM_MAPS); | ||
| 256 | drm_free(list, sizeof(*list), DRM_MEM_MAPS); | ||
| 257 | mutex_unlock(&dev->struct_mutex); | ||
| 258 | return ret; | ||
| 259 | } | ||
| 260 | |||
| 261 | list->user_token = list->hash.key; | ||
| 265 | mutex_unlock(&dev->struct_mutex); | 262 | mutex_unlock(&dev->struct_mutex); |
| 266 | 263 | ||
| 267 | *maplist = list; | 264 | *maplist = list; |
| @@ -346,6 +343,7 @@ int drm_rmmap_locked(drm_device_t *dev, drm_local_map_t *map) | |||
| 346 | 343 | ||
| 347 | if (r_list->map == map) { | 344 | if (r_list->map == map) { |
| 348 | list_del(list); | 345 | list_del(list); |
| 346 | drm_ht_remove_key(&dev->map_hash, r_list->user_token); | ||
| 349 | drm_free(list, sizeof(*list), DRM_MEM_MAPS); | 347 | drm_free(list, sizeof(*list), DRM_MEM_MAPS); |
| 350 | break; | 348 | break; |
| 351 | } | 349 | } |
| @@ -441,8 +439,10 @@ int drm_rmmap_ioctl(struct inode *inode, struct file *filp, | |||
| 441 | return -EINVAL; | 439 | return -EINVAL; |
| 442 | } | 440 | } |
| 443 | 441 | ||
| 444 | if (!map) | 442 | if (!map) { |
| 443 | mutex_unlock(&dev->struct_mutex); | ||
| 445 | return -EINVAL; | 444 | return -EINVAL; |
| 445 | } | ||
| 446 | 446 | ||
| 447 | /* Register and framebuffer maps are permanent */ | 447 | /* Register and framebuffer maps are permanent */ |
| 448 | if ((map->type == _DRM_REGISTERS) || (map->type == _DRM_FRAME_BUFFER)) { | 448 | if ((map->type == _DRM_REGISTERS) || (map->type == _DRM_FRAME_BUFFER)) { |
diff --git a/drivers/char/drm/drm_drv.c b/drivers/char/drm/drm_drv.c index 3c0b882a8e72..b366c5b1bd16 100644 --- a/drivers/char/drm/drm_drv.c +++ b/drivers/char/drm/drm_drv.c | |||
| @@ -118,7 +118,7 @@ static drm_ioctl_desc_t drm_ioctls[] = { | |||
| 118 | [DRM_IOCTL_NR(DRM_IOCTL_WAIT_VBLANK)] = {drm_wait_vblank, 0}, | 118 | [DRM_IOCTL_NR(DRM_IOCTL_WAIT_VBLANK)] = {drm_wait_vblank, 0}, |
| 119 | }; | 119 | }; |
| 120 | 120 | ||
| 121 | #define DRIVER_IOCTL_COUNT DRM_ARRAY_SIZE( drm_ioctls ) | 121 | #define DRIVER_IOCTL_COUNT ARRAY_SIZE( drm_ioctls ) |
| 122 | 122 | ||
| 123 | /** | 123 | /** |
| 124 | * Take down the DRM device. | 124 | * Take down the DRM device. |
| @@ -155,12 +155,13 @@ int drm_lastclose(drm_device_t * dev) | |||
| 155 | del_timer(&dev->timer); | 155 | del_timer(&dev->timer); |
| 156 | 156 | ||
| 157 | /* Clear pid list */ | 157 | /* Clear pid list */ |
| 158 | for (i = 0; i < DRM_HASH_SIZE; i++) { | 158 | if (dev->magicfree.next) { |
| 159 | for (pt = dev->magiclist[i].head; pt; pt = next) { | 159 | list_for_each_entry_safe(pt, next, &dev->magicfree, head) { |
| 160 | next = pt->next; | 160 | list_del(&pt->head); |
| 161 | drm_ht_remove_item(&dev->magiclist, &pt->hash_item); | ||
| 161 | drm_free(pt, sizeof(*pt), DRM_MEM_MAGIC); | 162 | drm_free(pt, sizeof(*pt), DRM_MEM_MAGIC); |
| 162 | } | 163 | } |
| 163 | dev->magiclist[i].head = dev->magiclist[i].tail = NULL; | 164 | drm_ht_remove(&dev->magiclist); |
| 164 | } | 165 | } |
| 165 | 166 | ||
| 166 | /* Clear AGP information */ | 167 | /* Clear AGP information */ |
| @@ -299,6 +300,7 @@ static void drm_cleanup(drm_device_t * dev) | |||
| 299 | if (dev->maplist) { | 300 | if (dev->maplist) { |
| 300 | drm_free(dev->maplist, sizeof(*dev->maplist), DRM_MEM_MAPS); | 301 | drm_free(dev->maplist, sizeof(*dev->maplist), DRM_MEM_MAPS); |
| 301 | dev->maplist = NULL; | 302 | dev->maplist = NULL; |
| 303 | drm_ht_remove(&dev->map_hash); | ||
| 302 | } | 304 | } |
| 303 | 305 | ||
| 304 | drm_ctxbitmap_cleanup(dev); | 306 | drm_ctxbitmap_cleanup(dev); |
diff --git a/drivers/char/drm/drm_fops.c b/drivers/char/drm/drm_fops.c index b7f7951c4587..898f47dafec0 100644 --- a/drivers/char/drm/drm_fops.c +++ b/drivers/char/drm/drm_fops.c | |||
| @@ -53,6 +53,8 @@ static int drm_setup(drm_device_t * dev) | |||
| 53 | return ret; | 53 | return ret; |
| 54 | } | 54 | } |
| 55 | 55 | ||
| 56 | dev->magicfree.next = NULL; | ||
| 57 | |||
| 56 | /* prebuild the SAREA */ | 58 | /* prebuild the SAREA */ |
| 57 | i = drm_addmap(dev, 0, SAREA_MAX, _DRM_SHM, _DRM_CONTAINS_LOCK, &map); | 59 | i = drm_addmap(dev, 0, SAREA_MAX, _DRM_SHM, _DRM_CONTAINS_LOCK, &map); |
| 58 | if (i != 0) | 60 | if (i != 0) |
| @@ -69,13 +71,11 @@ static int drm_setup(drm_device_t * dev) | |||
| 69 | return i; | 71 | return i; |
| 70 | } | 72 | } |
| 71 | 73 | ||
| 72 | for (i = 0; i < DRM_ARRAY_SIZE(dev->counts); i++) | 74 | for (i = 0; i < ARRAY_SIZE(dev->counts); i++) |
| 73 | atomic_set(&dev->counts[i], 0); | 75 | atomic_set(&dev->counts[i], 0); |
| 74 | 76 | ||
| 75 | for (i = 0; i < DRM_HASH_SIZE; i++) { | 77 | drm_ht_create(&dev->magiclist, DRM_MAGIC_HASH_ORDER); |
| 76 | dev->magiclist[i].head = NULL; | 78 | INIT_LIST_HEAD(&dev->magicfree); |
| 77 | dev->magiclist[i].tail = NULL; | ||
| 78 | } | ||
| 79 | 79 | ||
| 80 | dev->ctxlist = drm_alloc(sizeof(*dev->ctxlist), DRM_MEM_CTXLIST); | 80 | dev->ctxlist = drm_alloc(sizeof(*dev->ctxlist), DRM_MEM_CTXLIST); |
| 81 | if (dev->ctxlist == NULL) | 81 | if (dev->ctxlist == NULL) |
diff --git a/drivers/char/drm/drm_hashtab.c b/drivers/char/drm/drm_hashtab.c new file mode 100644 index 000000000000..a0b2d6802ae4 --- /dev/null +++ b/drivers/char/drm/drm_hashtab.c | |||
| @@ -0,0 +1,190 @@ | |||
| 1 | /************************************************************************** | ||
| 2 | * | ||
| 3 | * Copyright 2006 Tungsten Graphics, Inc., Bismarck, ND. USA. | ||
| 4 | * All Rights Reserved. | ||
| 5 | * | ||
| 6 | * Permission is hereby granted, free of charge, to any person obtaining a | ||
| 7 | * copy of this software and associated documentation files (the | ||
| 8 | * "Software"), to deal in the Software without restriction, including | ||
| 9 | * without limitation the rights to use, copy, modify, merge, publish, | ||
| 10 | * distribute, sub license, and/or sell copies of the Software, and to | ||
| 11 | * permit persons to whom the Software is furnished to do so, subject to | ||
| 12 | * the following conditions: | ||
| 13 | * | ||
| 14 | * The above copyright notice and this permission notice (including the | ||
| 15 | * next paragraph) shall be included in all copies or substantial portions | ||
| 16 | * of the Software. | ||
| 17 | * | ||
| 18 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
| 19 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
| 20 | * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL | ||
| 21 | * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, | ||
| 22 | * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR | ||
| 23 | * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE | ||
| 24 | * USE OR OTHER DEALINGS IN THE SOFTWARE. | ||
| 25 | * | ||
| 26 | * | ||
| 27 | **************************************************************************/ | ||
| 28 | /* | ||
| 29 | * Simple open hash tab implementation. | ||
| 30 | * | ||
| 31 | * Authors: | ||
| 32 | * Thomas Hellström <thomas-at-tungstengraphics-dot-com> | ||
| 33 | */ | ||
| 34 | |||
| 35 | #include "drmP.h" | ||
| 36 | #include "drm_hashtab.h" | ||
| 37 | #include <linux/hash.h> | ||
| 38 | |||
| 39 | int drm_ht_create(drm_open_hash_t *ht, unsigned int order) | ||
| 40 | { | ||
| 41 | unsigned int i; | ||
| 42 | |||
| 43 | ht->size = 1 << order; | ||
| 44 | ht->order = order; | ||
| 45 | ht->fill = 0; | ||
| 46 | ht->table = vmalloc(ht->size*sizeof(*ht->table)); | ||
| 47 | if (!ht->table) { | ||
| 48 | DRM_ERROR("Out of memory for hash table\n"); | ||
| 49 | return -ENOMEM; | ||
| 50 | } | ||
| 51 | for (i=0; i< ht->size; ++i) { | ||
| 52 | INIT_HLIST_HEAD(&ht->table[i]); | ||
| 53 | } | ||
| 54 | return 0; | ||
| 55 | } | ||
| 56 | |||
| 57 | void drm_ht_verbose_list(drm_open_hash_t *ht, unsigned long key) | ||
| 58 | { | ||
| 59 | drm_hash_item_t *entry; | ||
| 60 | struct hlist_head *h_list; | ||
| 61 | struct hlist_node *list; | ||
| 62 | unsigned int hashed_key; | ||
| 63 | int count = 0; | ||
| 64 | |||
| 65 | hashed_key = hash_long(key, ht->order); | ||
| 66 | DRM_DEBUG("Key is 0x%08lx, Hashed key is 0x%08x\n", key, hashed_key); | ||
| 67 | h_list = &ht->table[hashed_key]; | ||
| 68 | hlist_for_each(list, h_list) { | ||
| 69 | entry = hlist_entry(list, drm_hash_item_t, head); | ||
| 70 | DRM_DEBUG("count %d, key: 0x%08lx\n", count++, entry->key); | ||
| 71 | } | ||
| 72 | } | ||
| 73 | |||
| 74 | static struct hlist_node *drm_ht_find_key(drm_open_hash_t *ht, | ||
| 75 | unsigned long key) | ||
| 76 | { | ||
| 77 | drm_hash_item_t *entry; | ||
| 78 | struct hlist_head *h_list; | ||
| 79 | struct hlist_node *list; | ||
| 80 | unsigned int hashed_key; | ||
| 81 | |||
| 82 | hashed_key = hash_long(key, ht->order); | ||
| 83 | h_list = &ht->table[hashed_key]; | ||
| 84 | hlist_for_each(list, h_list) { | ||
| 85 | entry = hlist_entry(list, drm_hash_item_t, head); | ||
| 86 | if (entry->key == key) | ||
| 87 | return list; | ||
| 88 | if (entry->key > key) | ||
| 89 | break; | ||
| 90 | } | ||
| 91 | return NULL; | ||
| 92 | } | ||
| 93 | |||
| 94 | |||
| 95 | int drm_ht_insert_item(drm_open_hash_t *ht, drm_hash_item_t *item) | ||
| 96 | { | ||
| 97 | drm_hash_item_t *entry; | ||
| 98 | struct hlist_head *h_list; | ||
| 99 | struct hlist_node *list, *parent; | ||
| 100 | unsigned int hashed_key; | ||
| 101 | unsigned long key = item->key; | ||
| 102 | |||
| 103 | hashed_key = hash_long(key, ht->order); | ||
| 104 | h_list = &ht->table[hashed_key]; | ||
| 105 | parent = NULL; | ||
| 106 | hlist_for_each(list, h_list) { | ||
| 107 | entry = hlist_entry(list, drm_hash_item_t, head); | ||
| 108 | if (entry->key == key) | ||
| 109 | return -EINVAL; | ||
| 110 | if (entry->key > key) | ||
| 111 | break; | ||
| 112 | parent = list; | ||
| 113 | } | ||
| 114 | if (parent) { | ||
| 115 | hlist_add_after(parent, &item->head); | ||
| 116 | } else { | ||
| 117 | hlist_add_head(&item->head, h_list); | ||
| 118 | } | ||
| 119 | return 0; | ||
| 120 | } | ||
| 121 | |||
| 122 | /* | ||
| 123 | * Just insert an item and return any "bits" bit key that hasn't been | ||
| 124 | * used before. | ||
| 125 | */ | ||
| 126 | int drm_ht_just_insert_please(drm_open_hash_t *ht, drm_hash_item_t *item, | ||
| 127 | unsigned long seed, int bits, int shift, | ||
| 128 | unsigned long add) | ||
| 129 | { | ||
| 130 | int ret; | ||
| 131 | unsigned long mask = (1 << bits) - 1; | ||
| 132 | unsigned long first, unshifted_key; | ||
| 133 | |||
| 134 | unshifted_key = hash_long(seed, bits); | ||
| 135 | first = unshifted_key; | ||
| 136 | do { | ||
| 137 | item->key = (unshifted_key << shift) + add; | ||
| 138 | ret = drm_ht_insert_item(ht, item); | ||
| 139 | if (ret) | ||
| 140 | unshifted_key = (unshifted_key + 1) & mask; | ||
| 141 | } while(ret && (unshifted_key != first)); | ||
| 142 | |||
| 143 | if (ret) { | ||
| 144 | DRM_ERROR("Available key bit space exhausted\n"); | ||
| 145 | return -EINVAL; | ||
| 146 | } | ||
| 147 | return 0; | ||
| 148 | } | ||
| 149 | |||
| 150 | int drm_ht_find_item(drm_open_hash_t *ht, unsigned long key, | ||
| 151 | drm_hash_item_t **item) | ||
| 152 | { | ||
| 153 | struct hlist_node *list; | ||
| 154 | |||
| 155 | list = drm_ht_find_key(ht, key); | ||
| 156 | if (!list) | ||
| 157 | return -EINVAL; | ||
| 158 | |||
| 159 | *item = hlist_entry(list, drm_hash_item_t, head); | ||
| 160 | return 0; | ||
| 161 | } | ||
| 162 | |||
| 163 | int drm_ht_remove_key(drm_open_hash_t *ht, unsigned long key) | ||
| 164 | { | ||
| 165 | struct hlist_node *list; | ||
| 166 | |||
| 167 | list = drm_ht_find_key(ht, key); | ||
| 168 | if (list) { | ||
| 169 | hlist_del_init(list); | ||
| 170 | ht->fill--; | ||
| 171 | return 0; | ||
| 172 | } | ||
| 173 | return -EINVAL; | ||
| 174 | } | ||
| 175 | |||
| 176 | int drm_ht_remove_item(drm_open_hash_t *ht, drm_hash_item_t *item) | ||
| 177 | { | ||
| 178 | hlist_del_init(&item->head); | ||
| 179 | ht->fill--; | ||
| 180 | return 0; | ||
| 181 | } | ||
| 182 | |||
| 183 | void drm_ht_remove(drm_open_hash_t *ht) | ||
| 184 | { | ||
| 185 | if (ht->table) { | ||
| 186 | vfree(ht->table); | ||
| 187 | ht->table = NULL; | ||
| 188 | } | ||
| 189 | } | ||
| 190 | |||
diff --git a/drivers/char/drm/drm_hashtab.h b/drivers/char/drm/drm_hashtab.h new file mode 100644 index 000000000000..40afec05bff8 --- /dev/null +++ b/drivers/char/drm/drm_hashtab.h | |||
| @@ -0,0 +1,67 @@ | |||
| 1 | /************************************************************************** | ||
| 2 | * | ||
| 3 | * Copyright 2006 Tungsten Graphics, Inc., Bismack, ND. USA. | ||
| 4 | * All Rights Reserved. | ||
| 5 | * | ||
| 6 | * Permission is hereby granted, free of charge, to any person obtaining a | ||
| 7 | * copy of this software and associated documentation files (the | ||
| 8 | * "Software"), to deal in the Software without restriction, including | ||
| 9 | * without limitation the rights to use, copy, modify, merge, publish, | ||
| 10 | * distribute, sub license, and/or sell copies of the Software, and to | ||
| 11 | * permit persons to whom the Software is furnished to do so, subject to | ||
| 12 | * the following conditions: | ||
| 13 | * | ||
| 14 | * The above copyright notice and this permission notice (including the | ||
| 15 | * next paragraph) shall be included in all copies or substantial portions | ||
| 16 | * of the Software. | ||
| 17 | * | ||
| 18 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
| 19 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
| 20 | * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL | ||
| 21 | * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, | ||
| 22 | * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR | ||
| 23 | * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE | ||
| 24 | * USE OR OTHER DEALINGS IN THE SOFTWARE. | ||
| 25 | * | ||
| 26 | * | ||
| 27 | **************************************************************************/ | ||
| 28 | /* | ||
| 29 | * Simple open hash tab implementation. | ||
| 30 | * | ||
| 31 | * Authors: | ||
| 32 | * Thomas Hellström <thomas-at-tungstengraphics-dot-com> | ||
| 33 | */ | ||
| 34 | |||
| 35 | #ifndef DRM_HASHTAB_H | ||
| 36 | #define DRM_HASHTAB_H | ||
| 37 | |||
| 38 | #define drm_hash_entry(_ptr, _type, _member) container_of(_ptr, _type, _member) | ||
| 39 | |||
| 40 | typedef struct drm_hash_item{ | ||
| 41 | struct hlist_node head; | ||
| 42 | unsigned long key; | ||
| 43 | } drm_hash_item_t; | ||
| 44 | |||
| 45 | typedef struct drm_open_hash{ | ||
| 46 | unsigned int size; | ||
| 47 | unsigned int order; | ||
| 48 | unsigned int fill; | ||
| 49 | struct hlist_head *table; | ||
| 50 | } drm_open_hash_t; | ||
| 51 | |||
| 52 | |||
| 53 | extern int drm_ht_create(drm_open_hash_t *ht, unsigned int order); | ||
| 54 | extern int drm_ht_insert_item(drm_open_hash_t *ht, drm_hash_item_t *item); | ||
| 55 | extern int drm_ht_just_insert_please(drm_open_hash_t *ht, drm_hash_item_t *item, | ||
| 56 | unsigned long seed, int bits, int shift, | ||
| 57 | unsigned long add); | ||
| 58 | extern int drm_ht_find_item(drm_open_hash_t *ht, unsigned long key, drm_hash_item_t **item); | ||
| 59 | |||
| 60 | extern void drm_ht_verbose_list(drm_open_hash_t *ht, unsigned long key); | ||
| 61 | extern int drm_ht_remove_key(drm_open_hash_t *ht, unsigned long key); | ||
| 62 | extern int drm_ht_remove_item(drm_open_hash_t *ht, drm_hash_item_t *item); | ||
| 63 | extern void drm_ht_remove(drm_open_hash_t *ht); | ||
| 64 | |||
| 65 | |||
| 66 | #endif | ||
| 67 | |||
diff --git a/drivers/char/drm/drm_ioc32.c b/drivers/char/drm/drm_ioc32.c index e9e2db18952d..d4f874520082 100644 --- a/drivers/char/drm/drm_ioc32.c +++ b/drivers/char/drm/drm_ioc32.c | |||
| @@ -1051,7 +1051,7 @@ long drm_compat_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) | |||
| 1051 | drm_ioctl_compat_t *fn; | 1051 | drm_ioctl_compat_t *fn; |
| 1052 | int ret; | 1052 | int ret; |
| 1053 | 1053 | ||
| 1054 | if (nr >= DRM_ARRAY_SIZE(drm_compat_ioctls)) | 1054 | if (nr >= ARRAY_SIZE(drm_compat_ioctls)) |
| 1055 | return -ENOTTY; | 1055 | return -ENOTTY; |
| 1056 | 1056 | ||
| 1057 | fn = drm_compat_ioctls[nr]; | 1057 | fn = drm_compat_ioctls[nr]; |
diff --git a/drivers/char/drm/drm_ioctl.c b/drivers/char/drm/drm_ioctl.c index 555f323b8a32..565895547d75 100644 --- a/drivers/char/drm/drm_ioctl.c +++ b/drivers/char/drm/drm_ioctl.c | |||
| @@ -127,9 +127,10 @@ int drm_setunique(struct inode *inode, struct file *filp, | |||
| 127 | domain = bus >> 8; | 127 | domain = bus >> 8; |
| 128 | bus &= 0xff; | 128 | bus &= 0xff; |
| 129 | 129 | ||
| 130 | if ((domain != dev->pci_domain) || | 130 | if ((domain != drm_get_pci_domain(dev)) || |
| 131 | (bus != dev->pci_bus) || | 131 | (bus != dev->pdev->bus->number) || |
| 132 | (slot != dev->pci_slot) || (func != dev->pci_func)) | 132 | (slot != PCI_SLOT(dev->pdev->devfn)) || |
| 133 | (func != PCI_FUNC(dev->pdev->devfn))) | ||
| 133 | return -EINVAL; | 134 | return -EINVAL; |
| 134 | 135 | ||
| 135 | return 0; | 136 | return 0; |
| @@ -140,15 +141,17 @@ static int drm_set_busid(drm_device_t * dev) | |||
| 140 | int len; | 141 | int len; |
| 141 | 142 | ||
| 142 | if (dev->unique != NULL) | 143 | if (dev->unique != NULL) |
| 143 | return EBUSY; | 144 | return 0; |
| 144 | 145 | ||
| 145 | dev->unique_len = 40; | 146 | dev->unique_len = 40; |
| 146 | dev->unique = drm_alloc(dev->unique_len + 1, DRM_MEM_DRIVER); | 147 | dev->unique = drm_alloc(dev->unique_len + 1, DRM_MEM_DRIVER); |
| 147 | if (dev->unique == NULL) | 148 | if (dev->unique == NULL) |
| 148 | return ENOMEM; | 149 | return -ENOMEM; |
| 149 | 150 | ||
| 150 | len = snprintf(dev->unique, dev->unique_len, "pci:%04x:%02x:%02x.%d", | 151 | len = snprintf(dev->unique, dev->unique_len, "pci:%04x:%02x:%02x.%d", |
| 151 | dev->pci_domain, dev->pci_bus, dev->pci_slot, dev->pci_func); | 152 | drm_get_pci_domain(dev), dev->pdev->bus->number, |
| 153 | PCI_SLOT(dev->pdev->devfn), | ||
| 154 | PCI_FUNC(dev->pdev->devfn)); | ||
| 152 | 155 | ||
| 153 | if (len > dev->unique_len) | 156 | if (len > dev->unique_len) |
| 154 | DRM_ERROR("Unique buffer overflowed\n"); | 157 | DRM_ERROR("Unique buffer overflowed\n"); |
| @@ -157,7 +160,7 @@ static int drm_set_busid(drm_device_t * dev) | |||
| 157 | drm_alloc(strlen(dev->driver->pci_driver.name) + dev->unique_len + | 160 | drm_alloc(strlen(dev->driver->pci_driver.name) + dev->unique_len + |
| 158 | 2, DRM_MEM_DRIVER); | 161 | 2, DRM_MEM_DRIVER); |
| 159 | if (dev->devname == NULL) | 162 | if (dev->devname == NULL) |
| 160 | return ENOMEM; | 163 | return -ENOMEM; |
| 161 | 164 | ||
| 162 | sprintf(dev->devname, "%s@%s", dev->driver->pci_driver.name, | 165 | sprintf(dev->devname, "%s@%s", dev->driver->pci_driver.name, |
| 163 | dev->unique); | 166 | dev->unique); |
| @@ -330,27 +333,32 @@ int drm_setversion(DRM_IOCTL_ARGS) | |||
| 330 | drm_set_version_t retv; | 333 | drm_set_version_t retv; |
| 331 | int if_version; | 334 | int if_version; |
| 332 | drm_set_version_t __user *argp = (void __user *)data; | 335 | drm_set_version_t __user *argp = (void __user *)data; |
| 336 | int ret; | ||
| 333 | 337 | ||
| 334 | DRM_COPY_FROM_USER_IOCTL(sv, argp, sizeof(sv)); | 338 | if (copy_from_user(&sv, argp, sizeof(sv))) |
| 339 | return -EFAULT; | ||
| 335 | 340 | ||
| 336 | retv.drm_di_major = DRM_IF_MAJOR; | 341 | retv.drm_di_major = DRM_IF_MAJOR; |
| 337 | retv.drm_di_minor = DRM_IF_MINOR; | 342 | retv.drm_di_minor = DRM_IF_MINOR; |
| 338 | retv.drm_dd_major = dev->driver->major; | 343 | retv.drm_dd_major = dev->driver->major; |
| 339 | retv.drm_dd_minor = dev->driver->minor; | 344 | retv.drm_dd_minor = dev->driver->minor; |
| 340 | 345 | ||
| 341 | DRM_COPY_TO_USER_IOCTL(argp, retv, sizeof(sv)); | 346 | if (copy_to_user(argp, &retv, sizeof(retv))) |
| 347 | return -EFAULT; | ||
| 342 | 348 | ||
| 343 | if (sv.drm_di_major != -1) { | 349 | if (sv.drm_di_major != -1) { |
| 344 | if (sv.drm_di_major != DRM_IF_MAJOR || | 350 | if (sv.drm_di_major != DRM_IF_MAJOR || |
| 345 | sv.drm_di_minor < 0 || sv.drm_di_minor > DRM_IF_MINOR) | 351 | sv.drm_di_minor < 0 || sv.drm_di_minor > DRM_IF_MINOR) |
| 346 | return EINVAL; | 352 | return -EINVAL; |
| 347 | if_version = DRM_IF_VERSION(sv.drm_di_major, sv.drm_di_minor); | 353 | if_version = DRM_IF_VERSION(sv.drm_di_major, sv.drm_di_minor); |
| 348 | dev->if_version = DRM_MAX(if_version, dev->if_version); | 354 | dev->if_version = max(if_version, dev->if_version); |
| 349 | if (sv.drm_di_minor >= 1) { | 355 | if (sv.drm_di_minor >= 1) { |
| 350 | /* | 356 | /* |
| 351 | * Version 1.1 includes tying of DRM to specific device | 357 | * Version 1.1 includes tying of DRM to specific device |
| 352 | */ | 358 | */ |
| 353 | drm_set_busid(dev); | 359 | ret = drm_set_busid(dev); |
| 360 | if (ret) | ||
| 361 | return ret; | ||
| 354 | } | 362 | } |
| 355 | } | 363 | } |
| 356 | 364 | ||
| @@ -358,7 +366,7 @@ int drm_setversion(DRM_IOCTL_ARGS) | |||
| 358 | if (sv.drm_dd_major != dev->driver->major || | 366 | if (sv.drm_dd_major != dev->driver->major || |
| 359 | sv.drm_dd_minor < 0 | 367 | sv.drm_dd_minor < 0 |
| 360 | || sv.drm_dd_minor > dev->driver->minor) | 368 | || sv.drm_dd_minor > dev->driver->minor) |
| 361 | return EINVAL; | 369 | return -EINVAL; |
| 362 | 370 | ||
| 363 | if (dev->driver->set_version) | 371 | if (dev->driver->set_version) |
| 364 | dev->driver->set_version(dev, &sv); | 372 | dev->driver->set_version(dev, &sv); |
diff --git a/drivers/char/drm/drm_irq.c b/drivers/char/drm/drm_irq.c index ebdb7182c4fd..4553a3a1e496 100644 --- a/drivers/char/drm/drm_irq.c +++ b/drivers/char/drm/drm_irq.c | |||
| @@ -64,9 +64,9 @@ int drm_irq_by_busid(struct inode *inode, struct file *filp, | |||
| 64 | if (copy_from_user(&p, argp, sizeof(p))) | 64 | if (copy_from_user(&p, argp, sizeof(p))) |
| 65 | return -EFAULT; | 65 | return -EFAULT; |
| 66 | 66 | ||
| 67 | if ((p.busnum >> 8) != dev->pci_domain || | 67 | if ((p.busnum >> 8) != drm_get_pci_domain(dev) || |
| 68 | (p.busnum & 0xff) != dev->pci_bus || | 68 | (p.busnum & 0xff) != dev->pdev->bus->number || |
| 69 | p.devnum != dev->pci_slot || p.funcnum != dev->pci_func) | 69 | p.devnum != PCI_SLOT(dev->pdev->devfn) || p.funcnum != PCI_FUNC(dev->pdev->devfn)) |
| 70 | return -EINVAL; | 70 | return -EINVAL; |
| 71 | 71 | ||
| 72 | p.irq = dev->irq; | 72 | p.irq = dev->irq; |
| @@ -255,7 +255,8 @@ int drm_wait_vblank(DRM_IOCTL_ARGS) | |||
| 255 | if (!dev->irq) | 255 | if (!dev->irq) |
| 256 | return -EINVAL; | 256 | return -EINVAL; |
| 257 | 257 | ||
| 258 | DRM_COPY_FROM_USER_IOCTL(vblwait, argp, sizeof(vblwait)); | 258 | if (copy_from_user(&vblwait, argp, sizeof(vblwait))) |
| 259 | return -EFAULT; | ||
| 259 | 260 | ||
| 260 | switch (vblwait.request.type & ~_DRM_VBLANK_FLAGS_MASK) { | 261 | switch (vblwait.request.type & ~_DRM_VBLANK_FLAGS_MASK) { |
| 261 | case _DRM_VBLANK_RELATIVE: | 262 | case _DRM_VBLANK_RELATIVE: |
| @@ -329,7 +330,8 @@ int drm_wait_vblank(DRM_IOCTL_ARGS) | |||
| 329 | } | 330 | } |
| 330 | 331 | ||
| 331 | done: | 332 | done: |
| 332 | DRM_COPY_TO_USER_IOCTL(argp, vblwait, sizeof(vblwait)); | 333 | if (copy_to_user(argp, &vblwait, sizeof(vblwait))) |
| 334 | return -EFAULT; | ||
| 333 | 335 | ||
| 334 | return ret; | 336 | return ret; |
| 335 | } | 337 | } |
diff --git a/drivers/char/drm/drm_mm.c b/drivers/char/drm/drm_mm.c new file mode 100644 index 000000000000..617526bd5b0c --- /dev/null +++ b/drivers/char/drm/drm_mm.c | |||
| @@ -0,0 +1,201 @@ | |||
| 1 | /************************************************************************** | ||
| 2 | * | ||
| 3 | * Copyright 2006 Tungsten Graphics, Inc., Bismarck, ND., USA. | ||
| 4 | * All Rights Reserved. | ||
| 5 | * | ||
| 6 | * Permission is hereby granted, free of charge, to any person obtaining a | ||
| 7 | * copy of this software and associated documentation files (the | ||
| 8 | * "Software"), to deal in the Software without restriction, including | ||
| 9 | * without limitation the rights to use, copy, modify, merge, publish, | ||
| 10 | * distribute, sub license, and/or sell copies of the Software, and to | ||
| 11 | * permit persons to whom the Software is furnished to do so, subject to | ||
| 12 | * the following conditions: | ||
| 13 | * | ||
| 14 | * The above copyright notice and this permission notice (including the | ||
| 15 | * next paragraph) shall be included in all copies or substantial portions | ||
| 16 | * of the Software. | ||
| 17 | * | ||
| 18 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
| 19 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
| 20 | * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL | ||
| 21 | * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, | ||
| 22 | * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR | ||
| 23 | * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE | ||
| 24 | * USE OR OTHER DEALINGS IN THE SOFTWARE. | ||
| 25 | * | ||
| 26 | * | ||
| 27 | **************************************************************************/ | ||
| 28 | |||
| 29 | /* | ||
| 30 | * Generic simple memory manager implementation. Intended to be used as a base | ||
| 31 | * class implementation for more advanced memory managers. | ||
| 32 | * | ||
| 33 | * Note that the algorithm used is quite simple and there might be substantial | ||
| 34 | * performance gains if a smarter free list is implemented. Currently it is just an | ||
| 35 | * unordered stack of free regions. This could easily be improved if an RB-tree | ||
| 36 | * is used instead. At least if we expect heavy fragmentation. | ||
| 37 | * | ||
| 38 | * Aligned allocations can also see improvement. | ||
| 39 | * | ||
| 40 | * Authors: | ||
| 41 | * Thomas Hellström <thomas-at-tungstengraphics-dot-com> | ||
| 42 | */ | ||
| 43 | |||
| 44 | #include "drmP.h" | ||
| 45 | |||
| 46 | drm_mm_node_t *drm_mm_get_block(drm_mm_node_t * parent, | ||
| 47 | unsigned long size, unsigned alignment) | ||
| 48 | { | ||
| 49 | |||
| 50 | drm_mm_node_t *child; | ||
| 51 | |||
| 52 | if (alignment) | ||
| 53 | size += alignment - 1; | ||
| 54 | |||
| 55 | if (parent->size == size) { | ||
| 56 | list_del_init(&parent->fl_entry); | ||
| 57 | parent->free = 0; | ||
| 58 | return parent; | ||
| 59 | } else { | ||
| 60 | child = (drm_mm_node_t *) drm_alloc(sizeof(*child), DRM_MEM_MM); | ||
| 61 | if (!child) | ||
| 62 | return NULL; | ||
| 63 | |||
| 64 | INIT_LIST_HEAD(&child->ml_entry); | ||
| 65 | INIT_LIST_HEAD(&child->fl_entry); | ||
| 66 | |||
| 67 | child->free = 0; | ||
| 68 | child->size = size; | ||
| 69 | child->start = parent->start; | ||
| 70 | |||
| 71 | list_add_tail(&child->ml_entry, &parent->ml_entry); | ||
| 72 | parent->size -= size; | ||
| 73 | parent->start += size; | ||
| 74 | } | ||
| 75 | return child; | ||
| 76 | } | ||
| 77 | |||
| 78 | /* | ||
| 79 | * Put a block. Merge with the previous and / or next block if they are free. | ||
| 80 | * Otherwise add to the free stack. | ||
| 81 | */ | ||
| 82 | |||
| 83 | void drm_mm_put_block(drm_mm_t * mm, drm_mm_node_t * cur) | ||
| 84 | { | ||
| 85 | |||
| 86 | drm_mm_node_t *list_root = &mm->root_node; | ||
| 87 | struct list_head *cur_head = &cur->ml_entry; | ||
| 88 | struct list_head *root_head = &list_root->ml_entry; | ||
| 89 | drm_mm_node_t *prev_node = NULL; | ||
| 90 | drm_mm_node_t *next_node; | ||
| 91 | |||
| 92 | int merged = 0; | ||
| 93 | |||
| 94 | if (cur_head->prev != root_head) { | ||
| 95 | prev_node = list_entry(cur_head->prev, drm_mm_node_t, ml_entry); | ||
| 96 | if (prev_node->free) { | ||
| 97 | prev_node->size += cur->size; | ||
| 98 | merged = 1; | ||
| 99 | } | ||
| 100 | } | ||
| 101 | if (cur_head->next != root_head) { | ||
| 102 | next_node = list_entry(cur_head->next, drm_mm_node_t, ml_entry); | ||
| 103 | if (next_node->free) { | ||
| 104 | if (merged) { | ||
| 105 | prev_node->size += next_node->size; | ||
| 106 | list_del(&next_node->ml_entry); | ||
| 107 | list_del(&next_node->fl_entry); | ||
| 108 | drm_free(next_node, sizeof(*next_node), | ||
| 109 | DRM_MEM_MM); | ||
| 110 | } else { | ||
| 111 | next_node->size += cur->size; | ||
| 112 | next_node->start = cur->start; | ||
| 113 | merged = 1; | ||
| 114 | } | ||
| 115 | } | ||
| 116 | } | ||
| 117 | if (!merged) { | ||
| 118 | cur->free = 1; | ||
| 119 | list_add(&cur->fl_entry, &list_root->fl_entry); | ||
| 120 | } else { | ||
| 121 | list_del(&cur->ml_entry); | ||
| 122 | drm_free(cur, sizeof(*cur), DRM_MEM_MM); | ||
| 123 | } | ||
| 124 | } | ||
| 125 | |||
| 126 | drm_mm_node_t *drm_mm_search_free(const drm_mm_t * mm, | ||
| 127 | unsigned long size, | ||
| 128 | unsigned alignment, int best_match) | ||
| 129 | { | ||
| 130 | struct list_head *list; | ||
| 131 | const struct list_head *free_stack = &mm->root_node.fl_entry; | ||
| 132 | drm_mm_node_t *entry; | ||
| 133 | drm_mm_node_t *best; | ||
| 134 | unsigned long best_size; | ||
| 135 | |||
| 136 | best = NULL; | ||
| 137 | best_size = ~0UL; | ||
| 138 | |||
| 139 | if (alignment) | ||
| 140 | size += alignment - 1; | ||
| 141 | |||
| 142 | list_for_each(list, free_stack) { | ||
| 143 | entry = list_entry(list, drm_mm_node_t, fl_entry); | ||
| 144 | if (entry->size >= size) { | ||
| 145 | if (!best_match) | ||
| 146 | return entry; | ||
| 147 | if (size < best_size) { | ||
| 148 | best = entry; | ||
| 149 | best_size = entry->size; | ||
| 150 | } | ||
| 151 | } | ||
| 152 | } | ||
| 153 | |||
| 154 | return best; | ||
| 155 | } | ||
| 156 | |||
| 157 | int drm_mm_init(drm_mm_t * mm, unsigned long start, unsigned long size) | ||
| 158 | { | ||
| 159 | drm_mm_node_t *child; | ||
| 160 | |||
| 161 | INIT_LIST_HEAD(&mm->root_node.ml_entry); | ||
| 162 | INIT_LIST_HEAD(&mm->root_node.fl_entry); | ||
| 163 | child = (drm_mm_node_t *) drm_alloc(sizeof(*child), DRM_MEM_MM); | ||
| 164 | if (!child) | ||
| 165 | return -ENOMEM; | ||
| 166 | |||
| 167 | INIT_LIST_HEAD(&child->ml_entry); | ||
| 168 | INIT_LIST_HEAD(&child->fl_entry); | ||
| 169 | |||
| 170 | child->start = start; | ||
| 171 | child->size = size; | ||
| 172 | child->free = 1; | ||
| 173 | |||
| 174 | list_add(&child->fl_entry, &mm->root_node.fl_entry); | ||
| 175 | list_add(&child->ml_entry, &mm->root_node.ml_entry); | ||
| 176 | |||
| 177 | return 0; | ||
| 178 | } | ||
| 179 | |||
| 180 | EXPORT_SYMBOL(drm_mm_init); | ||
| 181 | |||
| 182 | void drm_mm_takedown(drm_mm_t * mm) | ||
| 183 | { | ||
| 184 | struct list_head *bnode = mm->root_node.fl_entry.next; | ||
| 185 | drm_mm_node_t *entry; | ||
| 186 | |||
| 187 | entry = list_entry(bnode, drm_mm_node_t, fl_entry); | ||
| 188 | |||
| 189 | if (entry->ml_entry.next != &mm->root_node.ml_entry || | ||
| 190 | entry->fl_entry.next != &mm->root_node.fl_entry) { | ||
| 191 | DRM_ERROR("Memory manager not clean. Delaying takedown\n"); | ||
| 192 | return; | ||
| 193 | } | ||
| 194 | |||
| 195 | list_del(&entry->fl_entry); | ||
| 196 | list_del(&entry->ml_entry); | ||
| 197 | |||
| 198 | drm_free(entry, sizeof(*entry), DRM_MEM_MM); | ||
| 199 | } | ||
| 200 | |||
| 201 | EXPORT_SYMBOL(drm_mm_takedown); | ||
diff --git a/drivers/char/drm/drm_pciids.h b/drivers/char/drm/drm_pciids.h index b1bb3c7b568d..09398d5fbd3f 100644 --- a/drivers/char/drm/drm_pciids.h +++ b/drivers/char/drm/drm_pciids.h | |||
| @@ -3,13 +3,13 @@ | |||
| 3 | Please contact dri-devel@lists.sf.net to add new cards to this list | 3 | Please contact dri-devel@lists.sf.net to add new cards to this list |
| 4 | */ | 4 | */ |
| 5 | #define radeon_PCI_IDS \ | 5 | #define radeon_PCI_IDS \ |
| 6 | {0x1002, 0x3150, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV380|CHIP_IS_MOBILITY}, \ | 6 | {0x1002, 0x3150, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV380|RADEON_IS_MOBILITY}, \ |
| 7 | {0x1002, 0x3152, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV380|CHIP_IS_MOBILITY|CHIP_NEW_MEMMAP}, \ | 7 | {0x1002, 0x3152, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV380|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \ |
| 8 | {0x1002, 0x3154, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV380|CHIP_IS_MOBILITY|CHIP_NEW_MEMMAP}, \ | 8 | {0x1002, 0x3154, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV380|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \ |
| 9 | {0x1002, 0x3E50, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV380|CHIP_NEW_MEMMAP}, \ | 9 | {0x1002, 0x3E50, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV380|RADEON_NEW_MEMMAP}, \ |
| 10 | {0x1002, 0x3E54, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV380|CHIP_NEW_MEMMAP}, \ | 10 | {0x1002, 0x3E54, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV380|RADEON_NEW_MEMMAP}, \ |
| 11 | {0x1002, 0x4136, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS100|CHIP_IS_IGP}, \ | 11 | {0x1002, 0x4136, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS100|RADEON_IS_IGP}, \ |
| 12 | {0x1002, 0x4137, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS200|CHIP_IS_IGP}, \ | 12 | {0x1002, 0x4137, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS200|RADEON_IS_IGP}, \ |
| 13 | {0x1002, 0x4144, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R300}, \ | 13 | {0x1002, 0x4144, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R300}, \ |
| 14 | {0x1002, 0x4145, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R300}, \ | 14 | {0x1002, 0x4145, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R300}, \ |
| 15 | {0x1002, 0x4146, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R300}, \ | 15 | {0x1002, 0x4146, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R300}, \ |
| @@ -25,35 +25,35 @@ | |||
| 25 | {0x1002, 0x4154, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV350}, \ | 25 | {0x1002, 0x4154, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV350}, \ |
| 26 | {0x1002, 0x4155, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV350}, \ | 26 | {0x1002, 0x4155, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV350}, \ |
| 27 | {0x1002, 0x4156, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV350}, \ | 27 | {0x1002, 0x4156, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV350}, \ |
| 28 | {0x1002, 0x4237, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS200|CHIP_IS_IGP}, \ | 28 | {0x1002, 0x4237, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS200|RADEON_IS_IGP}, \ |
| 29 | {0x1002, 0x4242, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R200}, \ | 29 | {0x1002, 0x4242, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R200}, \ |
| 30 | {0x1002, 0x4243, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R200}, \ | 30 | {0x1002, 0x4243, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R200}, \ |
| 31 | {0x1002, 0x4336, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS100|CHIP_IS_IGP|CHIP_IS_MOBILITY}, \ | 31 | {0x1002, 0x4336, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS100|RADEON_IS_IGP|RADEON_IS_MOBILITY}, \ |
| 32 | {0x1002, 0x4337, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS200|CHIP_IS_IGP|CHIP_IS_MOBILITY}, \ | 32 | {0x1002, 0x4337, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS200|RADEON_IS_IGP|RADEON_IS_MOBILITY}, \ |
| 33 | {0x1002, 0x4437, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS200|CHIP_IS_IGP|CHIP_IS_MOBILITY}, \ | 33 | {0x1002, 0x4437, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS200|RADEON_IS_IGP|RADEON_IS_MOBILITY}, \ |
| 34 | {0x1002, 0x4966, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV250}, \ | 34 | {0x1002, 0x4966, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV250}, \ |
| 35 | {0x1002, 0x4967, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV250}, \ | 35 | {0x1002, 0x4967, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV250}, \ |
| 36 | {0x1002, 0x4A48, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|CHIP_NEW_MEMMAP}, \ | 36 | {0x1002, 0x4A48, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|RADEON_NEW_MEMMAP}, \ |
| 37 | {0x1002, 0x4A49, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|CHIP_NEW_MEMMAP}, \ | 37 | {0x1002, 0x4A49, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|RADEON_NEW_MEMMAP}, \ |
| 38 | {0x1002, 0x4A4A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|CHIP_NEW_MEMMAP}, \ | 38 | {0x1002, 0x4A4A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|RADEON_NEW_MEMMAP}, \ |
| 39 | {0x1002, 0x4A4B, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|CHIP_NEW_MEMMAP}, \ | 39 | {0x1002, 0x4A4B, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|RADEON_NEW_MEMMAP}, \ |
| 40 | {0x1002, 0x4A4C, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|CHIP_NEW_MEMMAP}, \ | 40 | {0x1002, 0x4A4C, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|RADEON_NEW_MEMMAP}, \ |
| 41 | {0x1002, 0x4A4D, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|CHIP_NEW_MEMMAP}, \ | 41 | {0x1002, 0x4A4D, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|RADEON_NEW_MEMMAP}, \ |
| 42 | {0x1002, 0x4A4E, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|CHIP_IS_MOBILITY|CHIP_NEW_MEMMAP}, \ | 42 | {0x1002, 0x4A4E, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \ |
| 43 | {0x1002, 0x4A4F, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|CHIP_NEW_MEMMAP}, \ | 43 | {0x1002, 0x4A4F, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|RADEON_NEW_MEMMAP}, \ |
| 44 | {0x1002, 0x4A50, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|CHIP_NEW_MEMMAP}, \ | 44 | {0x1002, 0x4A50, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|RADEON_NEW_MEMMAP}, \ |
| 45 | {0x1002, 0x4A54, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|CHIP_NEW_MEMMAP}, \ | 45 | {0x1002, 0x4A54, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|RADEON_NEW_MEMMAP}, \ |
| 46 | {0x1002, 0x4B49, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|CHIP_NEW_MEMMAP}, \ | 46 | {0x1002, 0x4B49, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|RADEON_NEW_MEMMAP}, \ |
| 47 | {0x1002, 0x4B4A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|CHIP_NEW_MEMMAP}, \ | 47 | {0x1002, 0x4B4A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|RADEON_NEW_MEMMAP}, \ |
| 48 | {0x1002, 0x4B4B, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|CHIP_NEW_MEMMAP}, \ | 48 | {0x1002, 0x4B4B, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|RADEON_NEW_MEMMAP}, \ |
| 49 | {0x1002, 0x4B4C, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|CHIP_NEW_MEMMAP}, \ | 49 | {0x1002, 0x4B4C, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|RADEON_NEW_MEMMAP}, \ |
| 50 | {0x1002, 0x4C57, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV200|CHIP_IS_MOBILITY}, \ | 50 | {0x1002, 0x4C57, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV200|RADEON_IS_MOBILITY}, \ |
| 51 | {0x1002, 0x4C58, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV200|CHIP_IS_MOBILITY}, \ | 51 | {0x1002, 0x4C58, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV200|RADEON_IS_MOBILITY}, \ |
| 52 | {0x1002, 0x4C59, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV100|CHIP_IS_MOBILITY}, \ | 52 | {0x1002, 0x4C59, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV100|RADEON_IS_MOBILITY}, \ |
| 53 | {0x1002, 0x4C5A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV100|CHIP_IS_MOBILITY}, \ | 53 | {0x1002, 0x4C5A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV100|RADEON_IS_MOBILITY}, \ |
| 54 | {0x1002, 0x4C64, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV250|CHIP_IS_MOBILITY}, \ | 54 | {0x1002, 0x4C64, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV250|RADEON_IS_MOBILITY}, \ |
| 55 | {0x1002, 0x4C66, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV250|CHIP_IS_MOBILITY}, \ | 55 | {0x1002, 0x4C66, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV250|RADEON_IS_MOBILITY}, \ |
| 56 | {0x1002, 0x4C67, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV250|CHIP_IS_MOBILITY}, \ | 56 | {0x1002, 0x4C67, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV250|RADEON_IS_MOBILITY}, \ |
| 57 | {0x1002, 0x4E44, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R300}, \ | 57 | {0x1002, 0x4E44, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R300}, \ |
| 58 | {0x1002, 0x4E45, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R300}, \ | 58 | {0x1002, 0x4E45, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R300}, \ |
| 59 | {0x1002, 0x4E46, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R300}, \ | 59 | {0x1002, 0x4E46, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R300}, \ |
| @@ -62,16 +62,16 @@ | |||
| 62 | {0x1002, 0x4E49, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R350}, \ | 62 | {0x1002, 0x4E49, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R350}, \ |
| 63 | {0x1002, 0x4E4A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R350}, \ | 63 | {0x1002, 0x4E4A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R350}, \ |
| 64 | {0x1002, 0x4E4B, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R350}, \ | 64 | {0x1002, 0x4E4B, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R350}, \ |
| 65 | {0x1002, 0x4E50, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV350|CHIP_IS_MOBILITY}, \ | 65 | {0x1002, 0x4E50, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV350|RADEON_IS_MOBILITY}, \ |
| 66 | {0x1002, 0x4E51, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV350|CHIP_IS_MOBILITY}, \ | 66 | {0x1002, 0x4E51, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV350|RADEON_IS_MOBILITY}, \ |
| 67 | {0x1002, 0x4E52, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV350|CHIP_IS_MOBILITY}, \ | 67 | {0x1002, 0x4E52, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV350|RADEON_IS_MOBILITY}, \ |
| 68 | {0x1002, 0x4E53, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV350|CHIP_IS_MOBILITY}, \ | 68 | {0x1002, 0x4E53, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV350|RADEON_IS_MOBILITY}, \ |
| 69 | {0x1002, 0x4E54, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV350|CHIP_IS_MOBILITY}, \ | 69 | {0x1002, 0x4E54, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV350|RADEON_IS_MOBILITY}, \ |
| 70 | {0x1002, 0x4E56, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV350|CHIP_IS_MOBILITY}, \ | 70 | {0x1002, 0x4E56, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV350|RADEON_IS_MOBILITY}, \ |
| 71 | {0x1002, 0x5144, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R100|CHIP_SINGLE_CRTC}, \ | 71 | {0x1002, 0x5144, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R100|RADEON_SINGLE_CRTC}, \ |
| 72 | {0x1002, 0x5145, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R100|CHIP_SINGLE_CRTC}, \ | 72 | {0x1002, 0x5145, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R100|RADEON_SINGLE_CRTC}, \ |
| 73 | {0x1002, 0x5146, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R100|CHIP_SINGLE_CRTC}, \ | 73 | {0x1002, 0x5146, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R100|RADEON_SINGLE_CRTC}, \ |
| 74 | {0x1002, 0x5147, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R100|CHIP_SINGLE_CRTC}, \ | 74 | {0x1002, 0x5147, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R100|RADEON_SINGLE_CRTC}, \ |
| 75 | {0x1002, 0x5148, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R200}, \ | 75 | {0x1002, 0x5148, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R200}, \ |
| 76 | {0x1002, 0x514C, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R200}, \ | 76 | {0x1002, 0x514C, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R200}, \ |
| 77 | {0x1002, 0x514D, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R200}, \ | 77 | {0x1002, 0x514D, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R200}, \ |
| @@ -80,59 +80,59 @@ | |||
| 80 | {0x1002, 0x5159, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV100}, \ | 80 | {0x1002, 0x5159, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV100}, \ |
| 81 | {0x1002, 0x515A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV100}, \ | 81 | {0x1002, 0x515A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV100}, \ |
| 82 | {0x1002, 0x515E, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV100}, \ | 82 | {0x1002, 0x515E, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV100}, \ |
| 83 | {0x1002, 0x5460, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV380|CHIP_IS_MOBILITY}, \ | 83 | {0x1002, 0x5460, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV380|RADEON_IS_MOBILITY}, \ |
| 84 | {0x1002, 0x5462, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV380|CHIP_IS_MOBILITY}, \ | 84 | {0x1002, 0x5462, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV380|RADEON_IS_MOBILITY}, \ |
| 85 | {0x1002, 0x5464, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV380|CHIP_IS_MOBILITY}, \ | 85 | {0x1002, 0x5464, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV380|RADEON_IS_MOBILITY}, \ |
| 86 | {0x1002, 0x5548, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|CHIP_NEW_MEMMAP}, \ | 86 | {0x1002, 0x5548, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|RADEON_NEW_MEMMAP}, \ |
| 87 | {0x1002, 0x5549, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|CHIP_NEW_MEMMAP}, \ | 87 | {0x1002, 0x5549, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|RADEON_NEW_MEMMAP}, \ |
| 88 | {0x1002, 0x554A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|CHIP_NEW_MEMMAP}, \ | 88 | {0x1002, 0x554A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|RADEON_NEW_MEMMAP}, \ |
| 89 | {0x1002, 0x554B, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|CHIP_NEW_MEMMAP}, \ | 89 | {0x1002, 0x554B, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|RADEON_NEW_MEMMAP}, \ |
| 90 | {0x1002, 0x554C, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|CHIP_NEW_MEMMAP}, \ | 90 | {0x1002, 0x554C, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|RADEON_NEW_MEMMAP}, \ |
| 91 | {0x1002, 0x554D, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|CHIP_NEW_MEMMAP}, \ | 91 | {0x1002, 0x554D, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|RADEON_NEW_MEMMAP}, \ |
| 92 | {0x1002, 0x554E, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|CHIP_NEW_MEMMAP}, \ | 92 | {0x1002, 0x554E, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|RADEON_NEW_MEMMAP}, \ |
| 93 | {0x1002, 0x554F, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|CHIP_NEW_MEMMAP}, \ | 93 | {0x1002, 0x554F, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|RADEON_NEW_MEMMAP}, \ |
| 94 | {0x1002, 0x5550, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|CHIP_NEW_MEMMAP}, \ | 94 | {0x1002, 0x5550, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|RADEON_NEW_MEMMAP}, \ |
| 95 | {0x1002, 0x5551, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|CHIP_NEW_MEMMAP}, \ | 95 | {0x1002, 0x5551, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|RADEON_NEW_MEMMAP}, \ |
| 96 | {0x1002, 0x5552, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|CHIP_NEW_MEMMAP}, \ | 96 | {0x1002, 0x5552, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|RADEON_NEW_MEMMAP}, \ |
| 97 | {0x1002, 0x5554, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|CHIP_NEW_MEMMAP}, \ | 97 | {0x1002, 0x5554, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|RADEON_NEW_MEMMAP}, \ |
| 98 | {0x1002, 0x564A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV410|CHIP_IS_MOBILITY|CHIP_NEW_MEMMAP}, \ | 98 | {0x1002, 0x564A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV410|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \ |
| 99 | {0x1002, 0x564B, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV410|CHIP_IS_MOBILITY|CHIP_NEW_MEMMAP}, \ | 99 | {0x1002, 0x564B, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV410|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \ |
| 100 | {0x1002, 0x564F, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV410|CHIP_IS_MOBILITY|CHIP_NEW_MEMMAP}, \ | 100 | {0x1002, 0x564F, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV410|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \ |
| 101 | {0x1002, 0x5652, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV410|CHIP_IS_MOBILITY|CHIP_NEW_MEMMAP}, \ | 101 | {0x1002, 0x5652, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV410|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \ |
| 102 | {0x1002, 0x5653, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV410|CHIP_IS_MOBILITY|CHIP_NEW_MEMMAP}, \ | 102 | {0x1002, 0x5653, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV410|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \ |
| 103 | {0x1002, 0x5834, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS300|CHIP_IS_IGP}, \ | 103 | {0x1002, 0x5834, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS300|RADEON_IS_IGP}, \ |
| 104 | {0x1002, 0x5835, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS300|CHIP_IS_IGP|CHIP_IS_MOBILITY}, \ | 104 | {0x1002, 0x5835, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS300|RADEON_IS_IGP|RADEON_IS_MOBILITY}, \ |
| 105 | {0x1002, 0x5960, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV280}, \ | 105 | {0x1002, 0x5960, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV280}, \ |
| 106 | {0x1002, 0x5961, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV280}, \ | 106 | {0x1002, 0x5961, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV280}, \ |
| 107 | {0x1002, 0x5962, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV280}, \ | 107 | {0x1002, 0x5962, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV280}, \ |
| 108 | {0x1002, 0x5964, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV280}, \ | 108 | {0x1002, 0x5964, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV280}, \ |
| 109 | {0x1002, 0x5965, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV280}, \ | 109 | {0x1002, 0x5965, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV280}, \ |
| 110 | {0x1002, 0x5969, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV100}, \ | 110 | {0x1002, 0x5969, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV100}, \ |
| 111 | {0x1002, 0x5b60, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV380|CHIP_NEW_MEMMAP}, \ | 111 | {0x1002, 0x5b60, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV380|RADEON_NEW_MEMMAP}, \ |
| 112 | {0x1002, 0x5b62, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV380|CHIP_NEW_MEMMAP}, \ | 112 | {0x1002, 0x5b62, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV380|RADEON_NEW_MEMMAP}, \ |
| 113 | {0x1002, 0x5b63, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV380|CHIP_NEW_MEMMAP}, \ | 113 | {0x1002, 0x5b63, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV380|RADEON_NEW_MEMMAP}, \ |
| 114 | {0x1002, 0x5b64, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV380|CHIP_NEW_MEMMAP}, \ | 114 | {0x1002, 0x5b64, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV380|RADEON_NEW_MEMMAP}, \ |
| 115 | {0x1002, 0x5b65, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV380|CHIP_NEW_MEMMAP}, \ | 115 | {0x1002, 0x5b65, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV380|RADEON_NEW_MEMMAP}, \ |
| 116 | {0x1002, 0x5c61, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV280|CHIP_IS_MOBILITY}, \ | 116 | {0x1002, 0x5c61, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV280|RADEON_IS_MOBILITY}, \ |
| 117 | {0x1002, 0x5c63, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV280|CHIP_IS_MOBILITY}, \ | 117 | {0x1002, 0x5c63, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV280|RADEON_IS_MOBILITY}, \ |
| 118 | {0x1002, 0x5d48, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|CHIP_IS_MOBILITY|CHIP_NEW_MEMMAP}, \ | 118 | {0x1002, 0x5d48, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \ |
| 119 | {0x1002, 0x5d49, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|CHIP_IS_MOBILITY|CHIP_NEW_MEMMAP}, \ | 119 | {0x1002, 0x5d49, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \ |
| 120 | {0x1002, 0x5d4a, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|CHIP_IS_MOBILITY|CHIP_NEW_MEMMAP}, \ | 120 | {0x1002, 0x5d4a, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \ |
| 121 | {0x1002, 0x5d4c, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|CHIP_NEW_MEMMAP}, \ | 121 | {0x1002, 0x5d4c, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|RADEON_NEW_MEMMAP}, \ |
| 122 | {0x1002, 0x5d4d, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|CHIP_NEW_MEMMAP}, \ | 122 | {0x1002, 0x5d4d, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|RADEON_NEW_MEMMAP}, \ |
| 123 | {0x1002, 0x5d4e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|CHIP_NEW_MEMMAP}, \ | 123 | {0x1002, 0x5d4e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|RADEON_NEW_MEMMAP}, \ |
| 124 | {0x1002, 0x5d4f, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|CHIP_NEW_MEMMAP}, \ | 124 | {0x1002, 0x5d4f, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|RADEON_NEW_MEMMAP}, \ |
| 125 | {0x1002, 0x5d50, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|CHIP_NEW_MEMMAP}, \ | 125 | {0x1002, 0x5d50, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|RADEON_NEW_MEMMAP}, \ |
| 126 | {0x1002, 0x5d52, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|CHIP_NEW_MEMMAP}, \ | 126 | {0x1002, 0x5d52, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|RADEON_NEW_MEMMAP}, \ |
| 127 | {0x1002, 0x5d57, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|CHIP_NEW_MEMMAP}, \ | 127 | {0x1002, 0x5d57, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|RADEON_NEW_MEMMAP}, \ |
| 128 | {0x1002, 0x5e48, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV410|CHIP_NEW_MEMMAP}, \ | 128 | {0x1002, 0x5e48, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV410|RADEON_NEW_MEMMAP}, \ |
| 129 | {0x1002, 0x5e4a, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV410|CHIP_NEW_MEMMAP}, \ | 129 | {0x1002, 0x5e4a, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV410|RADEON_NEW_MEMMAP}, \ |
| 130 | {0x1002, 0x5e4b, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV410|CHIP_NEW_MEMMAP}, \ | 130 | {0x1002, 0x5e4b, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV410|RADEON_NEW_MEMMAP}, \ |
| 131 | {0x1002, 0x5e4c, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV410|CHIP_NEW_MEMMAP}, \ | 131 | {0x1002, 0x5e4c, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV410|RADEON_NEW_MEMMAP}, \ |
| 132 | {0x1002, 0x5e4d, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV410|CHIP_NEW_MEMMAP}, \ | 132 | {0x1002, 0x5e4d, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV410|RADEON_NEW_MEMMAP}, \ |
| 133 | {0x1002, 0x5e4f, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV410|CHIP_NEW_MEMMAP}, \ | 133 | {0x1002, 0x5e4f, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV410|RADEON_NEW_MEMMAP}, \ |
| 134 | {0x1002, 0x7834, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS300|CHIP_IS_IGP|CHIP_NEW_MEMMAP}, \ | 134 | {0x1002, 0x7834, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS300|RADEON_IS_IGP|RADEON_NEW_MEMMAP}, \ |
| 135 | {0x1002, 0x7835, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS300|CHIP_IS_IGP|CHIP_IS_MOBILITY|CHIP_NEW_MEMMAP}, \ | 135 | {0x1002, 0x7835, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS300|RADEON_IS_IGP|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \ |
| 136 | {0, 0, 0} | 136 | {0, 0, 0} |
| 137 | 137 | ||
| 138 | #define r128_PCI_IDS \ | 138 | #define r128_PCI_IDS \ |
| @@ -209,6 +209,7 @@ | |||
| 209 | {0x1039, 0x0300, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ | 209 | {0x1039, 0x0300, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ |
| 210 | {0x1039, 0x5300, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ | 210 | {0x1039, 0x5300, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ |
| 211 | {0x1039, 0x6300, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ | 211 | {0x1039, 0x6300, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ |
| 212 | {0x1039, 0x6330, PCI_ANY_ID, PCI_ANY_ID, 0, 0, SIS_CHIP_315}, \ | ||
| 212 | {0x1039, 0x7300, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ | 213 | {0x1039, 0x7300, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ |
| 213 | {0, 0, 0} | 214 | {0, 0, 0} |
| 214 | 215 | ||
| @@ -227,6 +228,10 @@ | |||
| 227 | {0x1106, 0x3122, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ | 228 | {0x1106, 0x3122, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ |
| 228 | {0x1106, 0x7205, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ | 229 | {0x1106, 0x7205, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ |
| 229 | {0x1106, 0x3108, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ | 230 | {0x1106, 0x3108, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ |
| 231 | {0x1106, 0x3304, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ | ||
| 232 | {0x1106, 0x3157, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ | ||
| 233 | {0x1106, 0x3344, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ | ||
| 234 | {0x1106, 0x7204, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ | ||
| 230 | {0, 0, 0} | 235 | {0, 0, 0} |
| 231 | 236 | ||
| 232 | #define i810_PCI_IDS \ | 237 | #define i810_PCI_IDS \ |
| @@ -285,5 +290,9 @@ | |||
| 285 | {0x8086, 0x2592, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ | 290 | {0x8086, 0x2592, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ |
| 286 | {0x8086, 0x2772, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ | 291 | {0x8086, 0x2772, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ |
| 287 | {0x8086, 0x27a2, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ | 292 | {0x8086, 0x27a2, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ |
| 293 | {0x8086, 0x2972, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ | ||
| 294 | {0x8086, 0x2982, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ | ||
| 295 | {0x8086, 0x2992, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ | ||
| 296 | {0x8086, 0x29a2, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ | ||
| 288 | {0, 0, 0} | 297 | {0, 0, 0} |
| 289 | 298 | ||
diff --git a/drivers/char/drm/drm_proc.c b/drivers/char/drm/drm_proc.c index 362a270af0f1..62d5fe15f046 100644 --- a/drivers/char/drm/drm_proc.c +++ b/drivers/char/drm/drm_proc.c | |||
| @@ -510,7 +510,7 @@ static int drm__vma_info(char *buf, char **start, off_t offset, int request, | |||
| 510 | vma->vm_flags & VM_MAYSHARE ? 's' : 'p', | 510 | vma->vm_flags & VM_MAYSHARE ? 's' : 'p', |
| 511 | vma->vm_flags & VM_LOCKED ? 'l' : '-', | 511 | vma->vm_flags & VM_LOCKED ? 'l' : '-', |
| 512 | vma->vm_flags & VM_IO ? 'i' : '-', | 512 | vma->vm_flags & VM_IO ? 'i' : '-', |
| 513 | VM_OFFSET(vma)); | 513 | vma->vm_pgoff << PAGE_SHIFT); |
| 514 | 514 | ||
| 515 | #if defined(__i386__) | 515 | #if defined(__i386__) |
| 516 | pgprot = pgprot_val(vma->vm_page_prot); | 516 | pgprot = pgprot_val(vma->vm_page_prot); |
diff --git a/drivers/char/drm/drm_sman.c b/drivers/char/drm/drm_sman.c new file mode 100644 index 000000000000..425c82336ee0 --- /dev/null +++ b/drivers/char/drm/drm_sman.c | |||
| @@ -0,0 +1,352 @@ | |||
| 1 | /************************************************************************** | ||
| 2 | * | ||
| 3 | * Copyright 2006 Tungsten Graphics, Inc., Bismarck., ND., USA. | ||
| 4 | * All Rights Reserved. | ||
| 5 | * | ||
| 6 | * Permission is hereby granted, free of charge, to any person obtaining a | ||
| 7 | * copy of this software and associated documentation files (the | ||
| 8 | * "Software"), to deal in the Software without restriction, including | ||
| 9 | * without limitation the rights to use, copy, modify, merge, publish, | ||
| 10 | * distribute, sub license, and/or sell copies of the Software, and to | ||
| 11 | * permit persons to whom the Software is furnished to do so, subject to | ||
| 12 | * the following conditions: | ||
| 13 | * | ||
| 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
| 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
| 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL | ||
| 17 | * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, | ||
| 18 | * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR | ||
| 19 | * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE | ||
| 20 | * USE OR OTHER DEALINGS IN THE SOFTWARE. | ||
| 21 | * | ||
| 22 | * The above copyright notice and this permission notice (including the | ||
| 23 | * next paragraph) shall be included in all copies or substantial portions | ||
| 24 | * of the Software. | ||
| 25 | * | ||
| 26 | * | ||
| 27 | **************************************************************************/ | ||
| 28 | /* | ||
| 29 | * Simple memory manager interface that keeps track on allocate regions on a | ||
| 30 | * per "owner" basis. All regions associated with an "owner" can be released | ||
| 31 | * with a simple call. Typically if the "owner" exists. The owner is any | ||
| 32 | * "unsigned long" identifier. Can typically be a pointer to a file private | ||
| 33 | * struct or a context identifier. | ||
| 34 | * | ||
| 35 | * Authors: | ||
| 36 | * Thomas Hellström <thomas-at-tungstengraphics-dot-com> | ||
| 37 | */ | ||
| 38 | |||
| 39 | #include "drm_sman.h" | ||
| 40 | |||
| 41 | typedef struct drm_owner_item { | ||
| 42 | drm_hash_item_t owner_hash; | ||
| 43 | struct list_head sman_list; | ||
| 44 | struct list_head mem_blocks; | ||
| 45 | } drm_owner_item_t; | ||
| 46 | |||
| 47 | void drm_sman_takedown(drm_sman_t * sman) | ||
| 48 | { | ||
| 49 | drm_ht_remove(&sman->user_hash_tab); | ||
| 50 | drm_ht_remove(&sman->owner_hash_tab); | ||
| 51 | if (sman->mm) | ||
| 52 | drm_free(sman->mm, sman->num_managers * sizeof(*sman->mm), | ||
| 53 | DRM_MEM_MM); | ||
| 54 | } | ||
| 55 | |||
| 56 | EXPORT_SYMBOL(drm_sman_takedown); | ||
| 57 | |||
| 58 | int | ||
| 59 | drm_sman_init(drm_sman_t * sman, unsigned int num_managers, | ||
| 60 | unsigned int user_order, unsigned int owner_order) | ||
| 61 | { | ||
| 62 | int ret = 0; | ||
| 63 | |||
| 64 | sman->mm = (drm_sman_mm_t *) drm_calloc(num_managers, sizeof(*sman->mm), | ||
| 65 | DRM_MEM_MM); | ||
| 66 | if (!sman->mm) { | ||
| 67 | ret = -ENOMEM; | ||
| 68 | goto out; | ||
| 69 | } | ||
| 70 | sman->num_managers = num_managers; | ||
| 71 | INIT_LIST_HEAD(&sman->owner_items); | ||
| 72 | ret = drm_ht_create(&sman->owner_hash_tab, owner_order); | ||
| 73 | if (ret) | ||
| 74 | goto out1; | ||
| 75 | ret = drm_ht_create(&sman->user_hash_tab, user_order); | ||
| 76 | if (!ret) | ||
| 77 | goto out; | ||
| 78 | |||
| 79 | drm_ht_remove(&sman->owner_hash_tab); | ||
| 80 | out1: | ||
| 81 | drm_free(sman->mm, num_managers * sizeof(*sman->mm), DRM_MEM_MM); | ||
| 82 | out: | ||
| 83 | return ret; | ||
| 84 | } | ||
| 85 | |||
| 86 | EXPORT_SYMBOL(drm_sman_init); | ||
| 87 | |||
| 88 | static void *drm_sman_mm_allocate(void *private, unsigned long size, | ||
| 89 | unsigned alignment) | ||
| 90 | { | ||
| 91 | drm_mm_t *mm = (drm_mm_t *) private; | ||
| 92 | drm_mm_node_t *tmp; | ||
| 93 | |||
| 94 | tmp = drm_mm_search_free(mm, size, alignment, 1); | ||
| 95 | if (!tmp) { | ||
| 96 | return NULL; | ||
| 97 | } | ||
| 98 | tmp = drm_mm_get_block(tmp, size, alignment); | ||
| 99 | return tmp; | ||
| 100 | } | ||
| 101 | |||
| 102 | static void drm_sman_mm_free(void *private, void *ref) | ||
| 103 | { | ||
| 104 | drm_mm_t *mm = (drm_mm_t *) private; | ||
| 105 | drm_mm_node_t *node = (drm_mm_node_t *) ref; | ||
| 106 | |||
| 107 | drm_mm_put_block(mm, node); | ||
| 108 | } | ||
| 109 | |||
| 110 | static void drm_sman_mm_destroy(void *private) | ||
| 111 | { | ||
| 112 | drm_mm_t *mm = (drm_mm_t *) private; | ||
| 113 | drm_mm_takedown(mm); | ||
| 114 | drm_free(mm, sizeof(*mm), DRM_MEM_MM); | ||
| 115 | } | ||
| 116 | |||
| 117 | static unsigned long drm_sman_mm_offset(void *private, void *ref) | ||
| 118 | { | ||
| 119 | drm_mm_node_t *node = (drm_mm_node_t *) ref; | ||
| 120 | return node->start; | ||
| 121 | } | ||
| 122 | |||
| 123 | int | ||
| 124 | drm_sman_set_range(drm_sman_t * sman, unsigned int manager, | ||
| 125 | unsigned long start, unsigned long size) | ||
| 126 | { | ||
| 127 | drm_sman_mm_t *sman_mm; | ||
| 128 | drm_mm_t *mm; | ||
| 129 | int ret; | ||
| 130 | |||
| 131 | BUG_ON(manager >= sman->num_managers); | ||
| 132 | |||
| 133 | sman_mm = &sman->mm[manager]; | ||
| 134 | mm = drm_calloc(1, sizeof(*mm), DRM_MEM_MM); | ||
| 135 | if (!mm) { | ||
| 136 | return -ENOMEM; | ||
| 137 | } | ||
| 138 | sman_mm->private = mm; | ||
| 139 | ret = drm_mm_init(mm, start, size); | ||
| 140 | |||
| 141 | if (ret) { | ||
| 142 | drm_free(mm, sizeof(*mm), DRM_MEM_MM); | ||
| 143 | return ret; | ||
| 144 | } | ||
| 145 | |||
| 146 | sman_mm->allocate = drm_sman_mm_allocate; | ||
| 147 | sman_mm->free = drm_sman_mm_free; | ||
| 148 | sman_mm->destroy = drm_sman_mm_destroy; | ||
| 149 | sman_mm->offset = drm_sman_mm_offset; | ||
| 150 | |||
| 151 | return 0; | ||
| 152 | } | ||
| 153 | |||
| 154 | EXPORT_SYMBOL(drm_sman_set_range); | ||
| 155 | |||
| 156 | int | ||
| 157 | drm_sman_set_manager(drm_sman_t * sman, unsigned int manager, | ||
| 158 | drm_sman_mm_t * allocator) | ||
| 159 | { | ||
| 160 | BUG_ON(manager >= sman->num_managers); | ||
| 161 | sman->mm[manager] = *allocator; | ||
| 162 | |||
| 163 | return 0; | ||
| 164 | } | ||
| 165 | |||
| 166 | static drm_owner_item_t *drm_sman_get_owner_item(drm_sman_t * sman, | ||
| 167 | unsigned long owner) | ||
| 168 | { | ||
| 169 | int ret; | ||
| 170 | drm_hash_item_t *owner_hash_item; | ||
| 171 | drm_owner_item_t *owner_item; | ||
| 172 | |||
| 173 | ret = drm_ht_find_item(&sman->owner_hash_tab, owner, &owner_hash_item); | ||
| 174 | if (!ret) { | ||
| 175 | return drm_hash_entry(owner_hash_item, drm_owner_item_t, | ||
| 176 | owner_hash); | ||
| 177 | } | ||
| 178 | |||
| 179 | owner_item = drm_calloc(1, sizeof(*owner_item), DRM_MEM_MM); | ||
| 180 | if (!owner_item) | ||
| 181 | goto out; | ||
| 182 | |||
| 183 | INIT_LIST_HEAD(&owner_item->mem_blocks); | ||
| 184 | owner_item->owner_hash.key = owner; | ||
| 185 | if (drm_ht_insert_item(&sman->owner_hash_tab, &owner_item->owner_hash)) | ||
| 186 | goto out1; | ||
| 187 | |||
| 188 | list_add_tail(&owner_item->sman_list, &sman->owner_items); | ||
| 189 | return owner_item; | ||
| 190 | |||
| 191 | out1: | ||
| 192 | drm_free(owner_item, sizeof(*owner_item), DRM_MEM_MM); | ||
| 193 | out: | ||
| 194 | return NULL; | ||
| 195 | } | ||
| 196 | |||
| 197 | drm_memblock_item_t *drm_sman_alloc(drm_sman_t *sman, unsigned int manager, | ||
| 198 | unsigned long size, unsigned alignment, | ||
| 199 | unsigned long owner) | ||
| 200 | { | ||
| 201 | void *tmp; | ||
| 202 | drm_sman_mm_t *sman_mm; | ||
| 203 | drm_owner_item_t *owner_item; | ||
| 204 | drm_memblock_item_t *memblock; | ||
| 205 | |||
| 206 | BUG_ON(manager >= sman->num_managers); | ||
| 207 | |||
| 208 | sman_mm = &sman->mm[manager]; | ||
| 209 | tmp = sman_mm->allocate(sman_mm->private, size, alignment); | ||
| 210 | |||
| 211 | if (!tmp) { | ||
| 212 | return NULL; | ||
| 213 | } | ||
| 214 | |||
| 215 | memblock = drm_calloc(1, sizeof(*memblock), DRM_MEM_MM); | ||
| 216 | |||
| 217 | if (!memblock) | ||
| 218 | goto out; | ||
| 219 | |||
| 220 | memblock->mm_info = tmp; | ||
| 221 | memblock->mm = sman_mm; | ||
| 222 | memblock->sman = sman; | ||
| 223 | |||
| 224 | if (drm_ht_just_insert_please | ||
| 225 | (&sman->user_hash_tab, &memblock->user_hash, | ||
| 226 | (unsigned long)memblock, 32, 0, 0)) | ||
| 227 | goto out1; | ||
| 228 | |||
| 229 | owner_item = drm_sman_get_owner_item(sman, owner); | ||
| 230 | if (!owner_item) | ||
| 231 | goto out2; | ||
| 232 | |||
| 233 | list_add_tail(&memblock->owner_list, &owner_item->mem_blocks); | ||
| 234 | |||
| 235 | return memblock; | ||
| 236 | |||
| 237 | out2: | ||
| 238 | drm_ht_remove_item(&sman->user_hash_tab, &memblock->user_hash); | ||
| 239 | out1: | ||
| 240 | drm_free(memblock, sizeof(*memblock), DRM_MEM_MM); | ||
| 241 | out: | ||
| 242 | sman_mm->free(sman_mm->private, tmp); | ||
| 243 | |||
| 244 | return NULL; | ||
| 245 | } | ||
| 246 | |||
| 247 | EXPORT_SYMBOL(drm_sman_alloc); | ||
| 248 | |||
| 249 | static void drm_sman_free(drm_memblock_item_t *item) | ||
| 250 | { | ||
| 251 | drm_sman_t *sman = item->sman; | ||
| 252 | |||
| 253 | list_del(&item->owner_list); | ||
| 254 | drm_ht_remove_item(&sman->user_hash_tab, &item->user_hash); | ||
| 255 | item->mm->free(item->mm->private, item->mm_info); | ||
| 256 | drm_free(item, sizeof(*item), DRM_MEM_MM); | ||
| 257 | } | ||
| 258 | |||
| 259 | int drm_sman_free_key(drm_sman_t *sman, unsigned int key) | ||
| 260 | { | ||
| 261 | drm_hash_item_t *hash_item; | ||
| 262 | drm_memblock_item_t *memblock_item; | ||
| 263 | |||
| 264 | if (drm_ht_find_item(&sman->user_hash_tab, key, &hash_item)) | ||
| 265 | return -EINVAL; | ||
| 266 | |||
| 267 | memblock_item = drm_hash_entry(hash_item, drm_memblock_item_t, user_hash); | ||
| 268 | drm_sman_free(memblock_item); | ||
| 269 | return 0; | ||
| 270 | } | ||
| 271 | |||
| 272 | EXPORT_SYMBOL(drm_sman_free_key); | ||
| 273 | |||
| 274 | static void drm_sman_remove_owner(drm_sman_t *sman, | ||
| 275 | drm_owner_item_t *owner_item) | ||
| 276 | { | ||
| 277 | list_del(&owner_item->sman_list); | ||
| 278 | drm_ht_remove_item(&sman->owner_hash_tab, &owner_item->owner_hash); | ||
| 279 | drm_free(owner_item, sizeof(*owner_item), DRM_MEM_MM); | ||
| 280 | } | ||
| 281 | |||
| 282 | int drm_sman_owner_clean(drm_sman_t *sman, unsigned long owner) | ||
| 283 | { | ||
| 284 | |||
| 285 | drm_hash_item_t *hash_item; | ||
| 286 | drm_owner_item_t *owner_item; | ||
| 287 | |||
| 288 | if (drm_ht_find_item(&sman->owner_hash_tab, owner, &hash_item)) { | ||
| 289 | return -1; | ||
| 290 | } | ||
| 291 | |||
| 292 | owner_item = drm_hash_entry(hash_item, drm_owner_item_t, owner_hash); | ||
| 293 | if (owner_item->mem_blocks.next == &owner_item->mem_blocks) { | ||
| 294 | drm_sman_remove_owner(sman, owner_item); | ||
| 295 | return -1; | ||
| 296 | } | ||
| 297 | |||
| 298 | return 0; | ||
| 299 | } | ||
| 300 | |||
| 301 | EXPORT_SYMBOL(drm_sman_owner_clean); | ||
| 302 | |||
| 303 | static void drm_sman_do_owner_cleanup(drm_sman_t *sman, | ||
| 304 | drm_owner_item_t *owner_item) | ||
| 305 | { | ||
| 306 | drm_memblock_item_t *entry, *next; | ||
| 307 | |||
| 308 | list_for_each_entry_safe(entry, next, &owner_item->mem_blocks, | ||
| 309 | owner_list) { | ||
| 310 | drm_sman_free(entry); | ||
| 311 | } | ||
| 312 | drm_sman_remove_owner(sman, owner_item); | ||
| 313 | } | ||
| 314 | |||
| 315 | void drm_sman_owner_cleanup(drm_sman_t *sman, unsigned long owner) | ||
| 316 | { | ||
| 317 | |||
| 318 | drm_hash_item_t *hash_item; | ||
| 319 | drm_owner_item_t *owner_item; | ||
| 320 | |||
| 321 | if (drm_ht_find_item(&sman->owner_hash_tab, owner, &hash_item)) { | ||
| 322 | |||
| 323 | return; | ||
| 324 | } | ||
| 325 | |||
| 326 | owner_item = drm_hash_entry(hash_item, drm_owner_item_t, owner_hash); | ||
| 327 | drm_sman_do_owner_cleanup(sman, owner_item); | ||
| 328 | } | ||
| 329 | |||
| 330 | EXPORT_SYMBOL(drm_sman_owner_cleanup); | ||
| 331 | |||
| 332 | void drm_sman_cleanup(drm_sman_t *sman) | ||
| 333 | { | ||
| 334 | drm_owner_item_t *entry, *next; | ||
| 335 | unsigned int i; | ||
| 336 | drm_sman_mm_t *sman_mm; | ||
| 337 | |||
| 338 | list_for_each_entry_safe(entry, next, &sman->owner_items, sman_list) { | ||
| 339 | drm_sman_do_owner_cleanup(sman, entry); | ||
| 340 | } | ||
| 341 | if (sman->mm) { | ||
| 342 | for (i = 0; i < sman->num_managers; ++i) { | ||
| 343 | sman_mm = &sman->mm[i]; | ||
| 344 | if (sman_mm->private) { | ||
| 345 | sman_mm->destroy(sman_mm->private); | ||
| 346 | sman_mm->private = NULL; | ||
| 347 | } | ||
| 348 | } | ||
| 349 | } | ||
| 350 | } | ||
| 351 | |||
| 352 | EXPORT_SYMBOL(drm_sman_cleanup); | ||
diff --git a/drivers/char/drm/drm_sman.h b/drivers/char/drm/drm_sman.h new file mode 100644 index 000000000000..ddc732a1bf27 --- /dev/null +++ b/drivers/char/drm/drm_sman.h | |||
| @@ -0,0 +1,176 @@ | |||
| 1 | /************************************************************************** | ||
| 2 | * | ||
| 3 | * Copyright 2006 Tungsten Graphics, Inc., Bismarck, ND., USA. | ||
| 4 | * All Rights Reserved. | ||
| 5 | * | ||
| 6 | * Permission is hereby granted, free of charge, to any person obtaining a | ||
| 7 | * copy of this software and associated documentation files (the | ||
| 8 | * "Software"), to deal in the Software without restriction, including | ||
| 9 | * without limitation the rights to use, copy, modify, merge, publish, | ||
| 10 | * distribute, sub license, and/or sell copies of the Software, and to | ||
| 11 | * permit persons to whom the Software is furnished to do so, subject to | ||
| 12 | * the following conditions: | ||
| 13 | * | ||
| 14 | * The above copyright notice and this permission notice (including the | ||
| 15 | * next paragraph) shall be included in all copies or substantial portions | ||
| 16 | * of the Software. | ||
| 17 | * | ||
| 18 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
| 19 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
| 20 | * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL | ||
| 21 | * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, | ||
| 22 | * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR | ||
| 23 | * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE | ||
| 24 | * USE OR OTHER DEALINGS IN THE SOFTWARE. | ||
| 25 | * | ||
| 26 | * | ||
| 27 | **************************************************************************/ | ||
| 28 | /* | ||
| 29 | * Simple memory MANager interface that keeps track on allocate regions on a | ||
| 30 | * per "owner" basis. All regions associated with an "owner" can be released | ||
| 31 | * with a simple call. Typically if the "owner" exists. The owner is any | ||
| 32 | * "unsigned long" identifier. Can typically be a pointer to a file private | ||
| 33 | * struct or a context identifier. | ||
| 34 | * | ||
| 35 | * Authors: | ||
| 36 | * Thomas Hellström <thomas-at-tungstengraphics-dot-com> | ||
| 37 | */ | ||
| 38 | |||
| 39 | #ifndef DRM_SMAN_H | ||
| 40 | #define DRM_SMAN_H | ||
| 41 | |||
| 42 | #include "drmP.h" | ||
| 43 | #include "drm_hashtab.h" | ||
| 44 | |||
| 45 | /* | ||
| 46 | * A class that is an abstration of a simple memory allocator. | ||
| 47 | * The sman implementation provides a default such allocator | ||
| 48 | * using the drm_mm.c implementation. But the user can replace it. | ||
| 49 | * See the SiS implementation, which may use the SiS FB kernel module | ||
| 50 | * for memory management. | ||
| 51 | */ | ||
| 52 | |||
| 53 | typedef struct drm_sman_mm { | ||
| 54 | /* private info. If allocated, needs to be destroyed by the destroy | ||
| 55 | function */ | ||
| 56 | void *private; | ||
| 57 | |||
| 58 | /* Allocate a memory block with given size and alignment. | ||
| 59 | Return an opaque reference to the memory block */ | ||
| 60 | |||
| 61 | void *(*allocate) (void *private, unsigned long size, | ||
| 62 | unsigned alignment); | ||
| 63 | |||
| 64 | /* Free a memory block. "ref" is the opaque reference that we got from | ||
| 65 | the "alloc" function */ | ||
| 66 | |||
| 67 | void (*free) (void *private, void *ref); | ||
| 68 | |||
| 69 | /* Free all resources associated with this allocator */ | ||
| 70 | |||
| 71 | void (*destroy) (void *private); | ||
| 72 | |||
| 73 | /* Return a memory offset from the opaque reference returned from the | ||
| 74 | "alloc" function */ | ||
| 75 | |||
| 76 | unsigned long (*offset) (void *private, void *ref); | ||
| 77 | } drm_sman_mm_t; | ||
| 78 | |||
| 79 | typedef struct drm_memblock_item { | ||
| 80 | struct list_head owner_list; | ||
| 81 | drm_hash_item_t user_hash; | ||
| 82 | void *mm_info; | ||
| 83 | drm_sman_mm_t *mm; | ||
| 84 | struct drm_sman *sman; | ||
| 85 | } drm_memblock_item_t; | ||
| 86 | |||
| 87 | typedef struct drm_sman { | ||
| 88 | drm_sman_mm_t *mm; | ||
| 89 | int num_managers; | ||
| 90 | drm_open_hash_t owner_hash_tab; | ||
| 91 | drm_open_hash_t user_hash_tab; | ||
| 92 | struct list_head owner_items; | ||
| 93 | } drm_sman_t; | ||
| 94 | |||
| 95 | /* | ||
| 96 | * Take down a memory manager. This function should only be called after a | ||
| 97 | * successful init and after a call to drm_sman_cleanup. | ||
| 98 | */ | ||
| 99 | |||
| 100 | extern void drm_sman_takedown(drm_sman_t * sman); | ||
| 101 | |||
| 102 | /* | ||
| 103 | * Allocate structures for a manager. | ||
| 104 | * num_managers are the number of memory pools to manage. (VRAM, AGP, ....) | ||
| 105 | * user_order is the log2 of the number of buckets in the user hash table. | ||
| 106 | * set this to approximately log2 of the max number of memory regions | ||
| 107 | * that will be allocated for _all_ pools together. | ||
| 108 | * owner_order is the log2 of the number of buckets in the owner hash table. | ||
| 109 | * set this to approximately log2 of | ||
| 110 | * the number of client file connections that will | ||
| 111 | * be using the manager. | ||
| 112 | * | ||
| 113 | */ | ||
| 114 | |||
| 115 | extern int drm_sman_init(drm_sman_t * sman, unsigned int num_managers, | ||
| 116 | unsigned int user_order, unsigned int owner_order); | ||
| 117 | |||
| 118 | /* | ||
| 119 | * Initialize a drm_mm.c allocator. Should be called only once for each | ||
| 120 | * manager unless a customized allogator is used. | ||
| 121 | */ | ||
| 122 | |||
| 123 | extern int drm_sman_set_range(drm_sman_t * sman, unsigned int manager, | ||
| 124 | unsigned long start, unsigned long size); | ||
| 125 | |||
| 126 | /* | ||
| 127 | * Initialize a customized allocator for one of the managers. | ||
| 128 | * (See the SiS module). The object pointed to by "allocator" is copied, | ||
| 129 | * so it can be destroyed after this call. | ||
| 130 | */ | ||
| 131 | |||
| 132 | extern int drm_sman_set_manager(drm_sman_t * sman, unsigned int mananger, | ||
| 133 | drm_sman_mm_t * allocator); | ||
| 134 | |||
| 135 | /* | ||
| 136 | * Allocate a memory block. Aligment is not implemented yet. | ||
| 137 | */ | ||
| 138 | |||
| 139 | extern drm_memblock_item_t *drm_sman_alloc(drm_sman_t * sman, | ||
| 140 | unsigned int manager, | ||
| 141 | unsigned long size, | ||
| 142 | unsigned alignment, | ||
| 143 | unsigned long owner); | ||
| 144 | /* | ||
| 145 | * Free a memory block identified by its user hash key. | ||
| 146 | */ | ||
| 147 | |||
| 148 | extern int drm_sman_free_key(drm_sman_t * sman, unsigned int key); | ||
| 149 | |||
| 150 | /* | ||
| 151 | * returns 1 iff there are no stale memory blocks associated with this owner. | ||
| 152 | * Typically called to determine if we need to idle the hardware and call | ||
| 153 | * drm_sman_owner_cleanup. If there are no stale memory blocks, it removes all | ||
| 154 | * resources associated with owner. | ||
| 155 | */ | ||
| 156 | |||
| 157 | extern int drm_sman_owner_clean(drm_sman_t * sman, unsigned long owner); | ||
| 158 | |||
| 159 | /* | ||
| 160 | * Frees all stale memory blocks associated with this owner. Note that this | ||
| 161 | * requires that the hardware is finished with all blocks, so the graphics engine | ||
| 162 | * should be idled before this call is made. This function also frees | ||
| 163 | * any resources associated with "owner" and should be called when owner | ||
| 164 | * is not going to be referenced anymore. | ||
| 165 | */ | ||
| 166 | |||
| 167 | extern void drm_sman_owner_cleanup(drm_sman_t * sman, unsigned long owner); | ||
| 168 | |||
| 169 | /* | ||
| 170 | * Frees all stale memory blocks associated with the memory manager. | ||
| 171 | * See idling above. | ||
| 172 | */ | ||
| 173 | |||
| 174 | extern void drm_sman_cleanup(drm_sman_t * sman); | ||
| 175 | |||
| 176 | #endif | ||
diff --git a/drivers/char/drm/drm_stub.c b/drivers/char/drm/drm_stub.c index 9a842a36bb27..7b1d4e8659ba 100644 --- a/drivers/char/drm/drm_stub.c +++ b/drivers/char/drm/drm_stub.c | |||
| @@ -65,22 +65,22 @@ static int drm_fill_in_dev(drm_device_t * dev, struct pci_dev *pdev, | |||
| 65 | mutex_init(&dev->ctxlist_mutex); | 65 | mutex_init(&dev->ctxlist_mutex); |
| 66 | 66 | ||
| 67 | dev->pdev = pdev; | 67 | dev->pdev = pdev; |
| 68 | dev->pci_device = pdev->device; | ||
| 69 | dev->pci_vendor = pdev->vendor; | ||
| 68 | 70 | ||
| 69 | #ifdef __alpha__ | 71 | #ifdef __alpha__ |
| 70 | dev->hose = pdev->sysdata; | 72 | dev->hose = pdev->sysdata; |
| 71 | dev->pci_domain = dev->hose->bus->number; | ||
| 72 | #else | ||
| 73 | dev->pci_domain = 0; | ||
| 74 | #endif | 73 | #endif |
| 75 | dev->pci_bus = pdev->bus->number; | ||
| 76 | dev->pci_slot = PCI_SLOT(pdev->devfn); | ||
| 77 | dev->pci_func = PCI_FUNC(pdev->devfn); | ||
| 78 | dev->irq = pdev->irq; | 74 | dev->irq = pdev->irq; |
| 79 | 75 | ||
| 80 | dev->maplist = drm_calloc(1, sizeof(*dev->maplist), DRM_MEM_MAPS); | 76 | dev->maplist = drm_calloc(1, sizeof(*dev->maplist), DRM_MEM_MAPS); |
| 81 | if (dev->maplist == NULL) | 77 | if (dev->maplist == NULL) |
| 82 | return -ENOMEM; | 78 | return -ENOMEM; |
| 83 | INIT_LIST_HEAD(&dev->maplist->head); | 79 | INIT_LIST_HEAD(&dev->maplist->head); |
| 80 | if (drm_ht_create(&dev->map_hash, 12)) { | ||
| 81 | drm_free(dev->maplist, sizeof(*dev->maplist), DRM_MEM_MAPS); | ||
| 82 | return -ENOMEM; | ||
| 83 | } | ||
| 84 | 84 | ||
| 85 | /* the DRM has 6 basic counters */ | 85 | /* the DRM has 6 basic counters */ |
| 86 | dev->counters = 6; | 86 | dev->counters = 6; |
diff --git a/drivers/char/drm/drm_vm.c b/drivers/char/drm/drm_vm.c index ffd0800ed601..b40ae438f531 100644 --- a/drivers/char/drm/drm_vm.c +++ b/drivers/char/drm/drm_vm.c | |||
| @@ -59,7 +59,7 @@ static __inline__ struct page *drm_do_vm_nopage(struct vm_area_struct *vma, | |||
| 59 | drm_device_t *dev = priv->head->dev; | 59 | drm_device_t *dev = priv->head->dev; |
| 60 | drm_map_t *map = NULL; | 60 | drm_map_t *map = NULL; |
| 61 | drm_map_list_t *r_list; | 61 | drm_map_list_t *r_list; |
| 62 | struct list_head *list; | 62 | drm_hash_item_t *hash; |
| 63 | 63 | ||
| 64 | /* | 64 | /* |
| 65 | * Find the right map | 65 | * Find the right map |
| @@ -70,14 +70,11 @@ static __inline__ struct page *drm_do_vm_nopage(struct vm_area_struct *vma, | |||
| 70 | if (!dev->agp || !dev->agp->cant_use_aperture) | 70 | if (!dev->agp || !dev->agp->cant_use_aperture) |
| 71 | goto vm_nopage_error; | 71 | goto vm_nopage_error; |
| 72 | 72 | ||
| 73 | list_for_each(list, &dev->maplist->head) { | 73 | if (drm_ht_find_item(&dev->map_hash, vma->vm_pgoff << PAGE_SHIFT, &hash)) |
| 74 | r_list = list_entry(list, drm_map_list_t, head); | 74 | goto vm_nopage_error; |
| 75 | map = r_list->map; | 75 | |
| 76 | if (!map) | 76 | r_list = drm_hash_entry(hash, drm_map_list_t, hash); |
| 77 | continue; | 77 | map = r_list->map; |
| 78 | if (r_list->user_token == VM_OFFSET(vma)) | ||
| 79 | break; | ||
| 80 | } | ||
| 81 | 78 | ||
| 82 | if (map && map->type == _DRM_AGP) { | 79 | if (map && map->type == _DRM_AGP) { |
| 83 | unsigned long offset = address - vma->vm_start; | 80 | unsigned long offset = address - vma->vm_start; |
| @@ -467,7 +464,7 @@ static int drm_mmap_dma(struct file *filp, struct vm_area_struct *vma) | |||
| 467 | dev = priv->head->dev; | 464 | dev = priv->head->dev; |
| 468 | dma = dev->dma; | 465 | dma = dev->dma; |
| 469 | DRM_DEBUG("start = 0x%lx, end = 0x%lx, offset = 0x%lx\n", | 466 | DRM_DEBUG("start = 0x%lx, end = 0x%lx, offset = 0x%lx\n", |
| 470 | vma->vm_start, vma->vm_end, VM_OFFSET(vma)); | 467 | vma->vm_start, vma->vm_end, vma->vm_pgoff << PAGE_SHIFT); |
| 471 | 468 | ||
| 472 | /* Length must match exact page count */ | 469 | /* Length must match exact page count */ |
| 473 | if (!dma || (length >> PAGE_SHIFT) != dma->page_count) { | 470 | if (!dma || (length >> PAGE_SHIFT) != dma->page_count) { |
| @@ -521,12 +518,11 @@ int drm_mmap(struct file *filp, struct vm_area_struct *vma) | |||
| 521 | drm_file_t *priv = filp->private_data; | 518 | drm_file_t *priv = filp->private_data; |
| 522 | drm_device_t *dev = priv->head->dev; | 519 | drm_device_t *dev = priv->head->dev; |
| 523 | drm_map_t *map = NULL; | 520 | drm_map_t *map = NULL; |
| 524 | drm_map_list_t *r_list; | ||
| 525 | unsigned long offset = 0; | 521 | unsigned long offset = 0; |
| 526 | struct list_head *list; | 522 | drm_hash_item_t *hash; |
| 527 | 523 | ||
| 528 | DRM_DEBUG("start = 0x%lx, end = 0x%lx, offset = 0x%lx\n", | 524 | DRM_DEBUG("start = 0x%lx, end = 0x%lx, offset = 0x%lx\n", |
| 529 | vma->vm_start, vma->vm_end, VM_OFFSET(vma)); | 525 | vma->vm_start, vma->vm_end, vma->vm_pgoff << PAGE_SHIFT); |
| 530 | 526 | ||
| 531 | if (!priv->authenticated) | 527 | if (!priv->authenticated) |
| 532 | return -EACCES; | 528 | return -EACCES; |
| @@ -535,7 +531,7 @@ int drm_mmap(struct file *filp, struct vm_area_struct *vma) | |||
| 535 | * the AGP mapped at physical address 0 | 531 | * the AGP mapped at physical address 0 |
| 536 | * --BenH. | 532 | * --BenH. |
| 537 | */ | 533 | */ |
| 538 | if (!VM_OFFSET(vma) | 534 | if (!(vma->vm_pgoff << PAGE_SHIFT) |
| 539 | #if __OS_HAS_AGP | 535 | #if __OS_HAS_AGP |
| 540 | && (!dev->agp | 536 | && (!dev->agp |
| 541 | || dev->agp->agp_info.device->vendor != PCI_VENDOR_ID_APPLE) | 537 | || dev->agp->agp_info.device->vendor != PCI_VENDOR_ID_APPLE) |
| @@ -543,23 +539,12 @@ int drm_mmap(struct file *filp, struct vm_area_struct *vma) | |||
| 543 | ) | 539 | ) |
| 544 | return drm_mmap_dma(filp, vma); | 540 | return drm_mmap_dma(filp, vma); |
| 545 | 541 | ||
| 546 | /* A sequential search of a linked list is | 542 | if (drm_ht_find_item(&dev->map_hash, vma->vm_pgoff << PAGE_SHIFT, &hash)) { |
| 547 | fine here because: 1) there will only be | 543 | DRM_ERROR("Could not find map\n"); |
| 548 | about 5-10 entries in the list and, 2) a | 544 | return -EINVAL; |
| 549 | DRI client only has to do this mapping | ||
| 550 | once, so it doesn't have to be optimized | ||
| 551 | for performance, even if the list was a | ||
| 552 | bit longer. */ | ||
| 553 | list_for_each(list, &dev->maplist->head) { | ||
| 554 | |||
| 555 | r_list = list_entry(list, drm_map_list_t, head); | ||
| 556 | map = r_list->map; | ||
| 557 | if (!map) | ||
| 558 | continue; | ||
| 559 | if (r_list->user_token == VM_OFFSET(vma)) | ||
| 560 | break; | ||
| 561 | } | 545 | } |
| 562 | 546 | ||
| 547 | map = drm_hash_entry(hash, drm_map_list_t, hash)->map; | ||
| 563 | if (!map || ((map->flags & _DRM_RESTRICTED) && !capable(CAP_SYS_ADMIN))) | 548 | if (!map || ((map->flags & _DRM_RESTRICTED) && !capable(CAP_SYS_ADMIN))) |
| 564 | return -EPERM; | 549 | return -EPERM; |
| 565 | 550 | ||
| @@ -620,7 +605,7 @@ int drm_mmap(struct file *filp, struct vm_area_struct *vma) | |||
| 620 | offset = dev->driver->get_reg_ofs(dev); | 605 | offset = dev->driver->get_reg_ofs(dev); |
| 621 | #ifdef __sparc__ | 606 | #ifdef __sparc__ |
| 622 | vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); | 607 | vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); |
| 623 | if (io_remap_pfn_range(DRM_RPR_ARG(vma) vma->vm_start, | 608 | if (io_remap_pfn_range(vma, vma->vm_start, |
| 624 | (map->offset + offset) >> PAGE_SHIFT, | 609 | (map->offset + offset) >> PAGE_SHIFT, |
| 625 | vma->vm_end - vma->vm_start, | 610 | vma->vm_end - vma->vm_start, |
| 626 | vma->vm_page_prot)) | 611 | vma->vm_page_prot)) |
diff --git a/drivers/char/drm/i810_dma.c b/drivers/char/drm/i810_dma.c index c658dde3633b..fa2de70f7401 100644 --- a/drivers/char/drm/i810_dma.c +++ b/drivers/char/drm/i810_dma.c | |||
| @@ -106,7 +106,7 @@ static int i810_mmap_buffers(struct file *filp, struct vm_area_struct *vma) | |||
| 106 | unlock_kernel(); | 106 | unlock_kernel(); |
| 107 | 107 | ||
| 108 | if (io_remap_pfn_range(vma, vma->vm_start, | 108 | if (io_remap_pfn_range(vma, vma->vm_start, |
| 109 | VM_OFFSET(vma) >> PAGE_SHIFT, | 109 | vma->vm_pgoff, |
| 110 | vma->vm_end - vma->vm_start, vma->vm_page_prot)) | 110 | vma->vm_end - vma->vm_start, vma->vm_page_prot)) |
| 111 | return -EAGAIN; | 111 | return -EAGAIN; |
| 112 | return 0; | 112 | return 0; |
| @@ -141,10 +141,10 @@ static int i810_map_buffer(drm_buf_t * buf, struct file *filp) | |||
| 141 | MAP_SHARED, buf->bus_address); | 141 | MAP_SHARED, buf->bus_address); |
| 142 | dev_priv->mmap_buffer = NULL; | 142 | dev_priv->mmap_buffer = NULL; |
| 143 | filp->f_op = old_fops; | 143 | filp->f_op = old_fops; |
| 144 | if ((unsigned long)buf_priv->virtual > -1024UL) { | 144 | if (IS_ERR(buf_priv->virtual)) { |
| 145 | /* Real error */ | 145 | /* Real error */ |
| 146 | DRM_ERROR("mmap error\n"); | 146 | DRM_ERROR("mmap error\n"); |
| 147 | retcode = (signed int)buf_priv->virtual; | 147 | retcode = PTR_ERR(buf_priv->virtual); |
| 148 | buf_priv->virtual = NULL; | 148 | buf_priv->virtual = NULL; |
| 149 | } | 149 | } |
| 150 | up_write(¤t->mm->mmap_sem); | 150 | up_write(¤t->mm->mmap_sem); |
| @@ -808,7 +808,7 @@ static void i810_dma_dispatch_vertex(drm_device_t * dev, | |||
| 808 | ((GFX_OP_PRIMITIVE | prim | ((used / 4) - 2))); | 808 | ((GFX_OP_PRIMITIVE | prim | ((used / 4) - 2))); |
| 809 | 809 | ||
| 810 | if (used & 4) { | 810 | if (used & 4) { |
| 811 | *(u32 *) ((u32) buf_priv->kernel_virtual + used) = 0; | 811 | *(u32 *) ((char *) buf_priv->kernel_virtual + used) = 0; |
| 812 | used += 4; | 812 | used += 4; |
| 813 | } | 813 | } |
| 814 | 814 | ||
| @@ -1166,7 +1166,7 @@ static void i810_dma_dispatch_mc(drm_device_t * dev, drm_buf_t * buf, int used, | |||
| 1166 | 1166 | ||
| 1167 | if (buf_priv->currently_mapped == I810_BUF_MAPPED) { | 1167 | if (buf_priv->currently_mapped == I810_BUF_MAPPED) { |
| 1168 | if (used & 4) { | 1168 | if (used & 4) { |
| 1169 | *(u32 *) ((u32) buf_priv->virtual + used) = 0; | 1169 | *(u32 *) ((char *) buf_priv->virtual + used) = 0; |
| 1170 | used += 4; | 1170 | used += 4; |
| 1171 | } | 1171 | } |
| 1172 | 1172 | ||
diff --git a/drivers/char/drm/i830_dma.c b/drivers/char/drm/i830_dma.c index b0f815d8cea8..4f0e5746ab33 100644 --- a/drivers/char/drm/i830_dma.c +++ b/drivers/char/drm/i830_dma.c | |||
| @@ -108,7 +108,7 @@ static int i830_mmap_buffers(struct file *filp, struct vm_area_struct *vma) | |||
| 108 | unlock_kernel(); | 108 | unlock_kernel(); |
| 109 | 109 | ||
| 110 | if (io_remap_pfn_range(vma, vma->vm_start, | 110 | if (io_remap_pfn_range(vma, vma->vm_start, |
| 111 | VM_OFFSET(vma) >> PAGE_SHIFT, | 111 | vma->vm_pgoff, |
| 112 | vma->vm_end - vma->vm_start, vma->vm_page_prot)) | 112 | vma->vm_end - vma->vm_start, vma->vm_page_prot)) |
| 113 | return -EAGAIN; | 113 | return -EAGAIN; |
| 114 | return 0; | 114 | return 0; |
| @@ -146,7 +146,7 @@ static int i830_map_buffer(drm_buf_t * buf, struct file *filp) | |||
| 146 | if (IS_ERR((void *)virtual)) { /* ugh */ | 146 | if (IS_ERR((void *)virtual)) { /* ugh */ |
| 147 | /* Real error */ | 147 | /* Real error */ |
| 148 | DRM_ERROR("mmap error\n"); | 148 | DRM_ERROR("mmap error\n"); |
| 149 | retcode = virtual; | 149 | retcode = PTR_ERR((void *)virtual); |
| 150 | buf_priv->virtual = NULL; | 150 | buf_priv->virtual = NULL; |
| 151 | } else { | 151 | } else { |
| 152 | buf_priv->virtual = (void __user *)virtual; | 152 | buf_priv->virtual = (void __user *)virtual; |
diff --git a/drivers/char/drm/i915_dma.c b/drivers/char/drm/i915_dma.c index a94233bdbc0e..fb7913ff5286 100644 --- a/drivers/char/drm/i915_dma.c +++ b/drivers/char/drm/i915_dma.c | |||
| @@ -31,6 +31,11 @@ | |||
| 31 | #include "i915_drm.h" | 31 | #include "i915_drm.h" |
| 32 | #include "i915_drv.h" | 32 | #include "i915_drv.h" |
| 33 | 33 | ||
| 34 | #define IS_I965G(dev) (dev->pci_device == 0x2972 || \ | ||
| 35 | dev->pci_device == 0x2982 || \ | ||
| 36 | dev->pci_device == 0x2992 || \ | ||
| 37 | dev->pci_device == 0x29A2) | ||
| 38 | |||
| 34 | /* Really want an OS-independent resettable timer. Would like to have | 39 | /* Really want an OS-independent resettable timer. Would like to have |
| 35 | * this loop run for (eg) 3 sec, but have the timer reset every time | 40 | * this loop run for (eg) 3 sec, but have the timer reset every time |
| 36 | * the head pointer changes, so that EBUSY only happens if the ring | 41 | * the head pointer changes, so that EBUSY only happens if the ring |
| @@ -255,7 +260,7 @@ static int i915_dma_init(DRM_IOCTL_ARGS) | |||
| 255 | retcode = i915_dma_resume(dev); | 260 | retcode = i915_dma_resume(dev); |
| 256 | break; | 261 | break; |
| 257 | default: | 262 | default: |
| 258 | retcode = -EINVAL; | 263 | retcode = DRM_ERR(EINVAL); |
| 259 | break; | 264 | break; |
| 260 | } | 265 | } |
| 261 | 266 | ||
| @@ -347,7 +352,7 @@ static int i915_emit_cmds(drm_device_t * dev, int __user * buffer, int dwords) | |||
| 347 | if ((dwords+1) * sizeof(int) >= dev_priv->ring.Size - 8) | 352 | if ((dwords+1) * sizeof(int) >= dev_priv->ring.Size - 8) |
| 348 | return DRM_ERR(EINVAL); | 353 | return DRM_ERR(EINVAL); |
| 349 | 354 | ||
| 350 | BEGIN_LP_RING(((dwords+1)&~1)); | 355 | BEGIN_LP_RING((dwords+1)&~1); |
| 351 | 356 | ||
| 352 | for (i = 0; i < dwords;) { | 357 | for (i = 0; i < dwords;) { |
| 353 | int cmd, sz; | 358 | int cmd, sz; |
| @@ -386,7 +391,7 @@ static int i915_emit_box(drm_device_t * dev, | |||
| 386 | RING_LOCALS; | 391 | RING_LOCALS; |
| 387 | 392 | ||
| 388 | if (DRM_COPY_FROM_USER_UNCHECKED(&box, &boxes[i], sizeof(box))) { | 393 | if (DRM_COPY_FROM_USER_UNCHECKED(&box, &boxes[i], sizeof(box))) { |
| 389 | return EFAULT; | 394 | return DRM_ERR(EFAULT); |
| 390 | } | 395 | } |
| 391 | 396 | ||
| 392 | if (box.y2 <= box.y1 || box.x2 <= box.x1 || box.y2 <= 0 || box.x2 <= 0) { | 397 | if (box.y2 <= box.y1 || box.x2 <= box.x1 || box.y2 <= 0 || box.x2 <= 0) { |
| @@ -395,24 +400,40 @@ static int i915_emit_box(drm_device_t * dev, | |||
| 395 | return DRM_ERR(EINVAL); | 400 | return DRM_ERR(EINVAL); |
| 396 | } | 401 | } |
| 397 | 402 | ||
| 398 | BEGIN_LP_RING(6); | 403 | if (IS_I965G(dev)) { |
| 399 | OUT_RING(GFX_OP_DRAWRECT_INFO); | 404 | BEGIN_LP_RING(4); |
| 400 | OUT_RING(DR1); | 405 | OUT_RING(GFX_OP_DRAWRECT_INFO_I965); |
| 401 | OUT_RING((box.x1 & 0xffff) | (box.y1 << 16)); | 406 | OUT_RING((box.x1 & 0xffff) | (box.y1 << 16)); |
| 402 | OUT_RING(((box.x2 - 1) & 0xffff) | ((box.y2 - 1) << 16)); | 407 | OUT_RING(((box.x2 - 1) & 0xffff) | ((box.y2 - 1) << 16)); |
| 403 | OUT_RING(DR4); | 408 | OUT_RING(DR4); |
| 404 | OUT_RING(0); | 409 | ADVANCE_LP_RING(); |
| 405 | ADVANCE_LP_RING(); | 410 | } else { |
| 411 | BEGIN_LP_RING(6); | ||
| 412 | OUT_RING(GFX_OP_DRAWRECT_INFO); | ||
| 413 | OUT_RING(DR1); | ||
| 414 | OUT_RING((box.x1 & 0xffff) | (box.y1 << 16)); | ||
| 415 | OUT_RING(((box.x2 - 1) & 0xffff) | ((box.y2 - 1) << 16)); | ||
| 416 | OUT_RING(DR4); | ||
| 417 | OUT_RING(0); | ||
| 418 | ADVANCE_LP_RING(); | ||
| 419 | } | ||
| 406 | 420 | ||
| 407 | return 0; | 421 | return 0; |
| 408 | } | 422 | } |
| 409 | 423 | ||
| 424 | /* XXX: Emitting the counter should really be moved to part of the IRQ | ||
| 425 | * emit. For now, do it in both places: | ||
| 426 | */ | ||
| 427 | |||
| 410 | static void i915_emit_breadcrumb(drm_device_t *dev) | 428 | static void i915_emit_breadcrumb(drm_device_t *dev) |
| 411 | { | 429 | { |
| 412 | drm_i915_private_t *dev_priv = dev->dev_private; | 430 | drm_i915_private_t *dev_priv = dev->dev_private; |
| 413 | RING_LOCALS; | 431 | RING_LOCALS; |
| 414 | 432 | ||
| 415 | dev_priv->sarea_priv->last_enqueue = dev_priv->counter++; | 433 | dev_priv->sarea_priv->last_enqueue = ++dev_priv->counter; |
| 434 | |||
| 435 | if (dev_priv->counter > 0x7FFFFFFFUL) | ||
| 436 | dev_priv->sarea_priv->last_enqueue = dev_priv->counter = 1; | ||
| 416 | 437 | ||
| 417 | BEGIN_LP_RING(4); | 438 | BEGIN_LP_RING(4); |
| 418 | OUT_RING(CMD_STORE_DWORD_IDX); | 439 | OUT_RING(CMD_STORE_DWORD_IDX); |
diff --git a/drivers/char/drm/i915_drm.h b/drivers/char/drm/i915_drm.h index 5aa3e0e3bb45..6af83e613f27 100644 --- a/drivers/char/drm/i915_drm.h +++ b/drivers/char/drm/i915_drm.h | |||
| @@ -98,6 +98,12 @@ typedef struct _drm_i915_sarea { | |||
| 98 | int rotated_size; | 98 | int rotated_size; |
| 99 | int rotated_pitch; | 99 | int rotated_pitch; |
| 100 | int virtualX, virtualY; | 100 | int virtualX, virtualY; |
| 101 | |||
| 102 | unsigned int front_tiled; | ||
| 103 | unsigned int back_tiled; | ||
| 104 | unsigned int depth_tiled; | ||
| 105 | unsigned int rotated_tiled; | ||
| 106 | unsigned int rotated2_tiled; | ||
| 101 | } drm_i915_sarea_t; | 107 | } drm_i915_sarea_t; |
| 102 | 108 | ||
| 103 | /* Flags for perf_boxes | 109 | /* Flags for perf_boxes |
diff --git a/drivers/char/drm/i915_drv.h b/drivers/char/drm/i915_drv.h index 2d565031c002..fdc2bf192714 100644 --- a/drivers/char/drm/i915_drv.h +++ b/drivers/char/drm/i915_drv.h | |||
| @@ -146,9 +146,9 @@ extern void i915_mem_release(drm_device_t * dev, | |||
| 146 | #define BEGIN_LP_RING(n) do { \ | 146 | #define BEGIN_LP_RING(n) do { \ |
| 147 | if (I915_VERBOSE) \ | 147 | if (I915_VERBOSE) \ |
| 148 | DRM_DEBUG("BEGIN_LP_RING(%d) in %s\n", \ | 148 | DRM_DEBUG("BEGIN_LP_RING(%d) in %s\n", \ |
| 149 | n, __FUNCTION__); \ | 149 | (n), __FUNCTION__); \ |
| 150 | if (dev_priv->ring.space < n*4) \ | 150 | if (dev_priv->ring.space < (n)*4) \ |
| 151 | i915_wait_ring(dev, n*4, __FUNCTION__); \ | 151 | i915_wait_ring(dev, (n)*4, __FUNCTION__); \ |
| 152 | outcount = 0; \ | 152 | outcount = 0; \ |
| 153 | outring = dev_priv->ring.tail; \ | 153 | outring = dev_priv->ring.tail; \ |
| 154 | ringmask = dev_priv->ring.tail_mask; \ | 154 | ringmask = dev_priv->ring.tail_mask; \ |
| @@ -157,7 +157,7 @@ extern void i915_mem_release(drm_device_t * dev, | |||
| 157 | 157 | ||
| 158 | #define OUT_RING(n) do { \ | 158 | #define OUT_RING(n) do { \ |
| 159 | if (I915_VERBOSE) DRM_DEBUG(" OUT_RING %x\n", (int)(n)); \ | 159 | if (I915_VERBOSE) DRM_DEBUG(" OUT_RING %x\n", (int)(n)); \ |
| 160 | *(volatile unsigned int *)(virt + outring) = n; \ | 160 | *(volatile unsigned int *)(virt + outring) = (n); \ |
| 161 | outcount++; \ | 161 | outcount++; \ |
| 162 | outring += 4; \ | 162 | outring += 4; \ |
| 163 | outring &= ringmask; \ | 163 | outring &= ringmask; \ |
| @@ -254,6 +254,8 @@ extern int i915_wait_ring(drm_device_t * dev, int n, const char *caller); | |||
| 254 | #define GFX_OP_DESTBUFFER_VARS ((0x3<<29)|(0x1d<<24)|(0x85<<16)|0x0) | 254 | #define GFX_OP_DESTBUFFER_VARS ((0x3<<29)|(0x1d<<24)|(0x85<<16)|0x0) |
| 255 | #define GFX_OP_DRAWRECT_INFO ((0x3<<29)|(0x1d<<24)|(0x80<<16)|(0x3)) | 255 | #define GFX_OP_DRAWRECT_INFO ((0x3<<29)|(0x1d<<24)|(0x80<<16)|(0x3)) |
| 256 | 256 | ||
| 257 | #define GFX_OP_DRAWRECT_INFO_I965 ((0x7900<<16)|0x2) | ||
| 258 | |||
| 257 | #define MI_BATCH_BUFFER ((0x30<<23)|1) | 259 | #define MI_BATCH_BUFFER ((0x30<<23)|1) |
| 258 | #define MI_BATCH_BUFFER_START (0x31<<23) | 260 | #define MI_BATCH_BUFFER_START (0x31<<23) |
| 259 | #define MI_BATCH_BUFFER_END (0xA<<23) | 261 | #define MI_BATCH_BUFFER_END (0xA<<23) |
diff --git a/drivers/char/drm/i915_irq.c b/drivers/char/drm/i915_irq.c index cd96cfa430db..0d4a162aa385 100644 --- a/drivers/char/drm/i915_irq.c +++ b/drivers/char/drm/i915_irq.c | |||
| @@ -71,21 +71,27 @@ irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS) | |||
| 71 | static int i915_emit_irq(drm_device_t * dev) | 71 | static int i915_emit_irq(drm_device_t * dev) |
| 72 | { | 72 | { |
| 73 | drm_i915_private_t *dev_priv = dev->dev_private; | 73 | drm_i915_private_t *dev_priv = dev->dev_private; |
| 74 | u32 ret; | ||
| 75 | RING_LOCALS; | 74 | RING_LOCALS; |
| 76 | 75 | ||
| 77 | i915_kernel_lost_context(dev); | 76 | i915_kernel_lost_context(dev); |
| 78 | 77 | ||
| 79 | DRM_DEBUG("%s\n", __FUNCTION__); | 78 | DRM_DEBUG("%s\n", __FUNCTION__); |
| 80 | 79 | ||
| 81 | ret = dev_priv->counter; | 80 | dev_priv->sarea_priv->last_enqueue = ++dev_priv->counter; |
| 82 | 81 | ||
| 83 | BEGIN_LP_RING(2); | 82 | if (dev_priv->counter > 0x7FFFFFFFUL) |
| 83 | dev_priv->sarea_priv->last_enqueue = dev_priv->counter = 1; | ||
| 84 | |||
| 85 | BEGIN_LP_RING(6); | ||
| 86 | OUT_RING(CMD_STORE_DWORD_IDX); | ||
| 87 | OUT_RING(20); | ||
| 88 | OUT_RING(dev_priv->counter); | ||
| 89 | OUT_RING(0); | ||
| 84 | OUT_RING(0); | 90 | OUT_RING(0); |
| 85 | OUT_RING(GFX_OP_USER_INTERRUPT); | 91 | OUT_RING(GFX_OP_USER_INTERRUPT); |
| 86 | ADVANCE_LP_RING(); | 92 | ADVANCE_LP_RING(); |
| 87 | 93 | ||
| 88 | return ret; | 94 | return dev_priv->counter; |
| 89 | } | 95 | } |
| 90 | 96 | ||
| 91 | static int i915_wait_irq(drm_device_t * dev, int irq_nr) | 97 | static int i915_wait_irq(drm_device_t * dev, int irq_nr) |
diff --git a/drivers/char/drm/radeon_cp.c b/drivers/char/drm/radeon_cp.c index 5ad43ba7b5aa..5ed965688293 100644 --- a/drivers/char/drm/radeon_cp.c +++ b/drivers/char/drm/radeon_cp.c | |||
| @@ -864,13 +864,13 @@ static int radeon_do_pixcache_flush(drm_radeon_private_t * dev_priv) | |||
| 864 | 864 | ||
| 865 | dev_priv->stats.boxes |= RADEON_BOX_WAIT_IDLE; | 865 | dev_priv->stats.boxes |= RADEON_BOX_WAIT_IDLE; |
| 866 | 866 | ||
| 867 | tmp = RADEON_READ(RADEON_RB2D_DSTCACHE_CTLSTAT); | 867 | tmp = RADEON_READ(RADEON_RB3D_DSTCACHE_CTLSTAT); |
| 868 | tmp |= RADEON_RB2D_DC_FLUSH_ALL; | 868 | tmp |= RADEON_RB3D_DC_FLUSH_ALL; |
| 869 | RADEON_WRITE(RADEON_RB2D_DSTCACHE_CTLSTAT, tmp); | 869 | RADEON_WRITE(RADEON_RB3D_DSTCACHE_CTLSTAT, tmp); |
| 870 | 870 | ||
| 871 | for (i = 0; i < dev_priv->usec_timeout; i++) { | 871 | for (i = 0; i < dev_priv->usec_timeout; i++) { |
| 872 | if (!(RADEON_READ(RADEON_RB2D_DSTCACHE_CTLSTAT) | 872 | if (!(RADEON_READ(RADEON_RB3D_DSTCACHE_CTLSTAT) |
| 873 | & RADEON_RB2D_DC_BUSY)) { | 873 | & RADEON_RB3D_DC_BUSY)) { |
| 874 | return 0; | 874 | return 0; |
| 875 | } | 875 | } |
| 876 | DRM_UDELAY(1); | 876 | DRM_UDELAY(1); |
| @@ -1130,7 +1130,7 @@ static void radeon_cp_init_ring_buffer(drm_device_t * dev, | |||
| 1130 | | (dev_priv->fb_location >> 16)); | 1130 | | (dev_priv->fb_location >> 16)); |
| 1131 | 1131 | ||
| 1132 | #if __OS_HAS_AGP | 1132 | #if __OS_HAS_AGP |
| 1133 | if (dev_priv->flags & CHIP_IS_AGP) { | 1133 | if (dev_priv->flags & RADEON_IS_AGP) { |
| 1134 | RADEON_WRITE(RADEON_AGP_BASE, (unsigned int)dev->agp->base); | 1134 | RADEON_WRITE(RADEON_AGP_BASE, (unsigned int)dev->agp->base); |
| 1135 | RADEON_WRITE(RADEON_MC_AGP_LOCATION, | 1135 | RADEON_WRITE(RADEON_MC_AGP_LOCATION, |
| 1136 | (((dev_priv->gart_vm_start - 1 + | 1136 | (((dev_priv->gart_vm_start - 1 + |
| @@ -1158,7 +1158,7 @@ static void radeon_cp_init_ring_buffer(drm_device_t * dev, | |||
| 1158 | dev_priv->ring.tail = cur_read_ptr; | 1158 | dev_priv->ring.tail = cur_read_ptr; |
| 1159 | 1159 | ||
| 1160 | #if __OS_HAS_AGP | 1160 | #if __OS_HAS_AGP |
| 1161 | if (dev_priv->flags & CHIP_IS_AGP) { | 1161 | if (dev_priv->flags & RADEON_IS_AGP) { |
| 1162 | RADEON_WRITE(RADEON_CP_RB_RPTR_ADDR, | 1162 | RADEON_WRITE(RADEON_CP_RB_RPTR_ADDR, |
| 1163 | dev_priv->ring_rptr->offset | 1163 | dev_priv->ring_rptr->offset |
| 1164 | - dev->agp->base + dev_priv->gart_vm_start); | 1164 | - dev->agp->base + dev_priv->gart_vm_start); |
| @@ -1258,6 +1258,13 @@ static void radeon_test_writeback(drm_radeon_private_t * dev_priv) | |||
| 1258 | dev_priv->writeback_works = 0; | 1258 | dev_priv->writeback_works = 0; |
| 1259 | DRM_INFO("writeback forced off\n"); | 1259 | DRM_INFO("writeback forced off\n"); |
| 1260 | } | 1260 | } |
| 1261 | |||
| 1262 | if (!dev_priv->writeback_works) { | ||
| 1263 | /* Disable writeback to avoid unnecessary bus master transfer */ | ||
| 1264 | RADEON_WRITE(RADEON_CP_RB_CNTL, RADEON_READ(RADEON_CP_RB_CNTL) | | ||
| 1265 | RADEON_RB_NO_UPDATE); | ||
| 1266 | RADEON_WRITE(RADEON_SCRATCH_UMSK, 0); | ||
| 1267 | } | ||
| 1261 | } | 1268 | } |
| 1262 | 1269 | ||
| 1263 | /* Enable or disable PCI-E GART on the chip */ | 1270 | /* Enable or disable PCI-E GART on the chip */ |
| @@ -1295,7 +1302,7 @@ static void radeon_set_pcigart(drm_radeon_private_t * dev_priv, int on) | |||
| 1295 | { | 1302 | { |
| 1296 | u32 tmp; | 1303 | u32 tmp; |
| 1297 | 1304 | ||
| 1298 | if (dev_priv->flags & CHIP_IS_PCIE) { | 1305 | if (dev_priv->flags & RADEON_IS_PCIE) { |
| 1299 | radeon_set_pciegart(dev_priv, on); | 1306 | radeon_set_pciegart(dev_priv, on); |
| 1300 | return; | 1307 | return; |
| 1301 | } | 1308 | } |
| @@ -1333,20 +1340,22 @@ static int radeon_do_init_cp(drm_device_t * dev, drm_radeon_init_t * init) | |||
| 1333 | DRM_DEBUG("\n"); | 1340 | DRM_DEBUG("\n"); |
| 1334 | 1341 | ||
| 1335 | /* if we require new memory map but we don't have it fail */ | 1342 | /* if we require new memory map but we don't have it fail */ |
| 1336 | if ((dev_priv->flags & CHIP_NEW_MEMMAP) && !dev_priv->new_memmap) | 1343 | if ((dev_priv->flags & RADEON_NEW_MEMMAP) && !dev_priv->new_memmap) { |
| 1337 | { | 1344 | DRM_ERROR("Cannot initialise DRM on this card\nThis card requires a new X.org DDX for 3D\n"); |
| 1338 | DRM_ERROR("Cannot initialise DRM on this card\nThis card requires a new X.org DDX\n"); | ||
| 1339 | radeon_do_cleanup_cp(dev); | 1345 | radeon_do_cleanup_cp(dev); |
| 1340 | return DRM_ERR(EINVAL); | 1346 | return DRM_ERR(EINVAL); |
| 1341 | } | 1347 | } |
| 1342 | 1348 | ||
| 1343 | if (init->is_pci && (dev_priv->flags & CHIP_IS_AGP)) | 1349 | if (init->is_pci && (dev_priv->flags & RADEON_IS_AGP)) { |
| 1344 | { | ||
| 1345 | DRM_DEBUG("Forcing AGP card to PCI mode\n"); | 1350 | DRM_DEBUG("Forcing AGP card to PCI mode\n"); |
| 1346 | dev_priv->flags &= ~CHIP_IS_AGP; | 1351 | dev_priv->flags &= ~RADEON_IS_AGP; |
| 1352 | } else if (!(dev_priv->flags & (RADEON_IS_AGP | RADEON_IS_PCI | RADEON_IS_PCIE)) | ||
| 1353 | && !init->is_pci) { | ||
| 1354 | DRM_DEBUG("Restoring AGP flag\n"); | ||
| 1355 | dev_priv->flags |= RADEON_IS_AGP; | ||
| 1347 | } | 1356 | } |
| 1348 | 1357 | ||
| 1349 | if ((!(dev_priv->flags & CHIP_IS_AGP)) && !dev->sg) { | 1358 | if ((!(dev_priv->flags & RADEON_IS_AGP)) && !dev->sg) { |
| 1350 | DRM_ERROR("PCI GART memory not allocated!\n"); | 1359 | DRM_ERROR("PCI GART memory not allocated!\n"); |
| 1351 | radeon_do_cleanup_cp(dev); | 1360 | radeon_do_cleanup_cp(dev); |
| 1352 | return DRM_ERR(EINVAL); | 1361 | return DRM_ERR(EINVAL); |
| @@ -1489,7 +1498,7 @@ static int radeon_do_init_cp(drm_device_t * dev, drm_radeon_init_t * init) | |||
| 1489 | init->sarea_priv_offset); | 1498 | init->sarea_priv_offset); |
| 1490 | 1499 | ||
| 1491 | #if __OS_HAS_AGP | 1500 | #if __OS_HAS_AGP |
| 1492 | if (dev_priv->flags & CHIP_IS_AGP) { | 1501 | if (dev_priv->flags & RADEON_IS_AGP) { |
| 1493 | drm_core_ioremap(dev_priv->cp_ring, dev); | 1502 | drm_core_ioremap(dev_priv->cp_ring, dev); |
| 1494 | drm_core_ioremap(dev_priv->ring_rptr, dev); | 1503 | drm_core_ioremap(dev_priv->ring_rptr, dev); |
| 1495 | drm_core_ioremap(dev->agp_buffer_map, dev); | 1504 | drm_core_ioremap(dev->agp_buffer_map, dev); |
| @@ -1548,7 +1557,7 @@ static int radeon_do_init_cp(drm_device_t * dev, drm_radeon_init_t * init) | |||
| 1548 | * align it down. | 1557 | * align it down. |
| 1549 | */ | 1558 | */ |
| 1550 | #if __OS_HAS_AGP | 1559 | #if __OS_HAS_AGP |
| 1551 | if (dev_priv->flags & CHIP_IS_AGP) { | 1560 | if (dev_priv->flags & RADEON_IS_AGP) { |
| 1552 | base = dev->agp->base; | 1561 | base = dev->agp->base; |
| 1553 | /* Check if valid */ | 1562 | /* Check if valid */ |
| 1554 | if ((base + dev_priv->gart_size) > dev_priv->fb_location && | 1563 | if ((base + dev_priv->gart_size) > dev_priv->fb_location && |
| @@ -1578,7 +1587,7 @@ static int radeon_do_init_cp(drm_device_t * dev, drm_radeon_init_t * init) | |||
| 1578 | } | 1587 | } |
| 1579 | 1588 | ||
| 1580 | #if __OS_HAS_AGP | 1589 | #if __OS_HAS_AGP |
| 1581 | if (dev_priv->flags & CHIP_IS_AGP) | 1590 | if (dev_priv->flags & RADEON_IS_AGP) |
| 1582 | dev_priv->gart_buffers_offset = (dev->agp_buffer_map->offset | 1591 | dev_priv->gart_buffers_offset = (dev->agp_buffer_map->offset |
| 1583 | - dev->agp->base | 1592 | - dev->agp->base |
| 1584 | + dev_priv->gart_vm_start); | 1593 | + dev_priv->gart_vm_start); |
| @@ -1604,7 +1613,7 @@ static int radeon_do_init_cp(drm_device_t * dev, drm_radeon_init_t * init) | |||
| 1604 | dev_priv->ring.high_mark = RADEON_RING_HIGH_MARK; | 1613 | dev_priv->ring.high_mark = RADEON_RING_HIGH_MARK; |
| 1605 | 1614 | ||
| 1606 | #if __OS_HAS_AGP | 1615 | #if __OS_HAS_AGP |
| 1607 | if (dev_priv->flags & CHIP_IS_AGP) { | 1616 | if (dev_priv->flags & RADEON_IS_AGP) { |
| 1608 | /* Turn off PCI GART */ | 1617 | /* Turn off PCI GART */ |
| 1609 | radeon_set_pcigart(dev_priv, 0); | 1618 | radeon_set_pcigart(dev_priv, 0); |
| 1610 | } else | 1619 | } else |
| @@ -1624,7 +1633,7 @@ static int radeon_do_init_cp(drm_device_t * dev, drm_radeon_init_t * init) | |||
| 1624 | dev_priv->gart_info.mapping.handle; | 1633 | dev_priv->gart_info.mapping.handle; |
| 1625 | 1634 | ||
| 1626 | dev_priv->gart_info.is_pcie = | 1635 | dev_priv->gart_info.is_pcie = |
| 1627 | !!(dev_priv->flags & CHIP_IS_PCIE); | 1636 | !!(dev_priv->flags & RADEON_IS_PCIE); |
| 1628 | dev_priv->gart_info.gart_table_location = | 1637 | dev_priv->gart_info.gart_table_location = |
| 1629 | DRM_ATI_GART_FB; | 1638 | DRM_ATI_GART_FB; |
| 1630 | 1639 | ||
| @@ -1636,7 +1645,7 @@ static int radeon_do_init_cp(drm_device_t * dev, drm_radeon_init_t * init) | |||
| 1636 | DRM_ATI_GART_MAIN; | 1645 | DRM_ATI_GART_MAIN; |
| 1637 | dev_priv->gart_info.addr = NULL; | 1646 | dev_priv->gart_info.addr = NULL; |
| 1638 | dev_priv->gart_info.bus_addr = 0; | 1647 | dev_priv->gart_info.bus_addr = 0; |
| 1639 | if (dev_priv->flags & CHIP_IS_PCIE) { | 1648 | if (dev_priv->flags & RADEON_IS_PCIE) { |
| 1640 | DRM_ERROR | 1649 | DRM_ERROR |
| 1641 | ("Cannot use PCI Express without GART in FB memory\n"); | 1650 | ("Cannot use PCI Express without GART in FB memory\n"); |
| 1642 | radeon_do_cleanup_cp(dev); | 1651 | radeon_do_cleanup_cp(dev); |
| @@ -1678,7 +1687,7 @@ static int radeon_do_cleanup_cp(drm_device_t * dev) | |||
| 1678 | drm_irq_uninstall(dev); | 1687 | drm_irq_uninstall(dev); |
| 1679 | 1688 | ||
| 1680 | #if __OS_HAS_AGP | 1689 | #if __OS_HAS_AGP |
| 1681 | if (dev_priv->flags & CHIP_IS_AGP) { | 1690 | if (dev_priv->flags & RADEON_IS_AGP) { |
| 1682 | if (dev_priv->cp_ring != NULL) { | 1691 | if (dev_priv->cp_ring != NULL) { |
| 1683 | drm_core_ioremapfree(dev_priv->cp_ring, dev); | 1692 | drm_core_ioremapfree(dev_priv->cp_ring, dev); |
| 1684 | dev_priv->cp_ring = NULL; | 1693 | dev_priv->cp_ring = NULL; |
| @@ -1733,7 +1742,7 @@ static int radeon_do_resume_cp(drm_device_t * dev) | |||
| 1733 | DRM_DEBUG("Starting radeon_do_resume_cp()\n"); | 1742 | DRM_DEBUG("Starting radeon_do_resume_cp()\n"); |
| 1734 | 1743 | ||
| 1735 | #if __OS_HAS_AGP | 1744 | #if __OS_HAS_AGP |
| 1736 | if (dev_priv->flags & CHIP_IS_AGP) { | 1745 | if (dev_priv->flags & RADEON_IS_AGP) { |
| 1737 | /* Turn off PCI GART */ | 1746 | /* Turn off PCI GART */ |
| 1738 | radeon_set_pcigart(dev_priv, 0); | 1747 | radeon_set_pcigart(dev_priv, 0); |
| 1739 | } else | 1748 | } else |
| @@ -2177,13 +2186,15 @@ int radeon_driver_load(struct drm_device *dev, unsigned long flags) | |||
| 2177 | dev->dev_private = (void *)dev_priv; | 2186 | dev->dev_private = (void *)dev_priv; |
| 2178 | dev_priv->flags = flags; | 2187 | dev_priv->flags = flags; |
| 2179 | 2188 | ||
| 2180 | switch (flags & CHIP_FAMILY_MASK) { | 2189 | switch (flags & RADEON_FAMILY_MASK) { |
| 2181 | case CHIP_R100: | 2190 | case CHIP_R100: |
| 2182 | case CHIP_RV200: | 2191 | case CHIP_RV200: |
| 2183 | case CHIP_R200: | 2192 | case CHIP_R200: |
| 2184 | case CHIP_R300: | 2193 | case CHIP_R300: |
| 2194 | case CHIP_R350: | ||
| 2185 | case CHIP_R420: | 2195 | case CHIP_R420: |
| 2186 | dev_priv->flags |= CHIP_HAS_HIERZ; | 2196 | case CHIP_RV410: |
| 2197 | dev_priv->flags |= RADEON_HAS_HIERZ; | ||
| 2187 | break; | 2198 | break; |
| 2188 | default: | 2199 | default: |
| 2189 | /* all other chips have no hierarchical z buffer */ | 2200 | /* all other chips have no hierarchical z buffer */ |
| @@ -2191,13 +2202,14 @@ int radeon_driver_load(struct drm_device *dev, unsigned long flags) | |||
| 2191 | } | 2202 | } |
| 2192 | 2203 | ||
| 2193 | if (drm_device_is_agp(dev)) | 2204 | if (drm_device_is_agp(dev)) |
| 2194 | dev_priv->flags |= CHIP_IS_AGP; | 2205 | dev_priv->flags |= RADEON_IS_AGP; |
| 2195 | 2206 | else if (drm_device_is_pcie(dev)) | |
| 2196 | if (drm_device_is_pcie(dev)) | 2207 | dev_priv->flags |= RADEON_IS_PCIE; |
| 2197 | dev_priv->flags |= CHIP_IS_PCIE; | 2208 | else |
| 2209 | dev_priv->flags |= RADEON_IS_PCI; | ||
| 2198 | 2210 | ||
| 2199 | DRM_DEBUG("%s card detected\n", | 2211 | DRM_DEBUG("%s card detected\n", |
| 2200 | ((dev_priv->flags & CHIP_IS_AGP) ? "AGP" : (((dev_priv->flags & CHIP_IS_PCIE) ? "PCIE" : "PCI")))); | 2212 | ((dev_priv->flags & RADEON_IS_AGP) ? "AGP" : (((dev_priv->flags & RADEON_IS_PCIE) ? "PCIE" : "PCI")))); |
| 2201 | return ret; | 2213 | return ret; |
| 2202 | } | 2214 | } |
| 2203 | 2215 | ||
diff --git a/drivers/char/drm/radeon_drv.c b/drivers/char/drm/radeon_drv.c index eb985c2a31e9..2eb652ec6745 100644 --- a/drivers/char/drm/radeon_drv.c +++ b/drivers/char/drm/radeon_drv.c | |||
| @@ -44,7 +44,7 @@ module_param_named(no_wb, radeon_no_wb, int, 0444); | |||
| 44 | static int dri_library_name(struct drm_device *dev, char *buf) | 44 | static int dri_library_name(struct drm_device *dev, char *buf) |
| 45 | { | 45 | { |
| 46 | drm_radeon_private_t *dev_priv = dev->dev_private; | 46 | drm_radeon_private_t *dev_priv = dev->dev_private; |
| 47 | int family = dev_priv->flags & CHIP_FAMILY_MASK; | 47 | int family = dev_priv->flags & RADEON_FAMILY_MASK; |
| 48 | 48 | ||
| 49 | return snprintf(buf, PAGE_SIZE, "%s\n", | 49 | return snprintf(buf, PAGE_SIZE, "%s\n", |
| 50 | (family < CHIP_R200) ? "radeon" : | 50 | (family < CHIP_R200) ? "radeon" : |
diff --git a/drivers/char/drm/radeon_drv.h b/drivers/char/drm/radeon_drv.h index e5a256f5429c..f45cd7f147a5 100644 --- a/drivers/char/drm/radeon_drv.h +++ b/drivers/char/drm/radeon_drv.h | |||
| @@ -133,15 +133,16 @@ enum radeon_cp_microcode_version { | |||
| 133 | * Chip flags | 133 | * Chip flags |
| 134 | */ | 134 | */ |
| 135 | enum radeon_chip_flags { | 135 | enum radeon_chip_flags { |
| 136 | CHIP_FAMILY_MASK = 0x0000ffffUL, | 136 | RADEON_FAMILY_MASK = 0x0000ffffUL, |
| 137 | CHIP_FLAGS_MASK = 0xffff0000UL, | 137 | RADEON_FLAGS_MASK = 0xffff0000UL, |
| 138 | CHIP_IS_MOBILITY = 0x00010000UL, | 138 | RADEON_IS_MOBILITY = 0x00010000UL, |
| 139 | CHIP_IS_IGP = 0x00020000UL, | 139 | RADEON_IS_IGP = 0x00020000UL, |
| 140 | CHIP_SINGLE_CRTC = 0x00040000UL, | 140 | RADEON_SINGLE_CRTC = 0x00040000UL, |
| 141 | CHIP_IS_AGP = 0x00080000UL, | 141 | RADEON_IS_AGP = 0x00080000UL, |
| 142 | CHIP_HAS_HIERZ = 0x00100000UL, | 142 | RADEON_HAS_HIERZ = 0x00100000UL, |
| 143 | CHIP_IS_PCIE = 0x00200000UL, | 143 | RADEON_IS_PCIE = 0x00200000UL, |
| 144 | CHIP_NEW_MEMMAP = 0x00400000UL, | 144 | RADEON_NEW_MEMMAP = 0x00400000UL, |
| 145 | RADEON_IS_PCI = 0x00800000UL, | ||
| 145 | }; | 146 | }; |
| 146 | 147 | ||
| 147 | #define GET_RING_HEAD(dev_priv) (dev_priv->writeback_works ? \ | 148 | #define GET_RING_HEAD(dev_priv) (dev_priv->writeback_works ? \ |
| @@ -424,6 +425,8 @@ extern int r300_do_cp_cmdbuf(drm_device_t * dev, DRMFILE filp, | |||
| 424 | #define RADEON_RB3D_COLOROFFSET 0x1c40 | 425 | #define RADEON_RB3D_COLOROFFSET 0x1c40 |
| 425 | #define RADEON_RB3D_COLORPITCH 0x1c48 | 426 | #define RADEON_RB3D_COLORPITCH 0x1c48 |
| 426 | 427 | ||
| 428 | #define RADEON_SRC_X_Y 0x1590 | ||
| 429 | |||
| 427 | #define RADEON_DP_GUI_MASTER_CNTL 0x146c | 430 | #define RADEON_DP_GUI_MASTER_CNTL 0x146c |
| 428 | # define RADEON_GMC_SRC_PITCH_OFFSET_CNTL (1 << 0) | 431 | # define RADEON_GMC_SRC_PITCH_OFFSET_CNTL (1 << 0) |
| 429 | # define RADEON_GMC_DST_PITCH_OFFSET_CNTL (1 << 1) | 432 | # define RADEON_GMC_DST_PITCH_OFFSET_CNTL (1 << 1) |
| @@ -441,6 +444,7 @@ extern int r300_do_cp_cmdbuf(drm_device_t * dev, DRMFILE filp, | |||
| 441 | # define RADEON_ROP3_S 0x00cc0000 | 444 | # define RADEON_ROP3_S 0x00cc0000 |
| 442 | # define RADEON_ROP3_P 0x00f00000 | 445 | # define RADEON_ROP3_P 0x00f00000 |
| 443 | #define RADEON_DP_WRITE_MASK 0x16cc | 446 | #define RADEON_DP_WRITE_MASK 0x16cc |
| 447 | #define RADEON_SRC_PITCH_OFFSET 0x1428 | ||
| 444 | #define RADEON_DST_PITCH_OFFSET 0x142c | 448 | #define RADEON_DST_PITCH_OFFSET 0x142c |
| 445 | #define RADEON_DST_PITCH_OFFSET_C 0x1c80 | 449 | #define RADEON_DST_PITCH_OFFSET_C 0x1c80 |
| 446 | # define RADEON_DST_TILE_LINEAR (0 << 30) | 450 | # define RADEON_DST_TILE_LINEAR (0 << 30) |
| @@ -545,6 +549,11 @@ extern int r300_do_cp_cmdbuf(drm_device_t * dev, DRMFILE filp, | |||
| 545 | # define RADEON_RB3D_ZC_FREE (1 << 2) | 549 | # define RADEON_RB3D_ZC_FREE (1 << 2) |
| 546 | # define RADEON_RB3D_ZC_FLUSH_ALL 0x5 | 550 | # define RADEON_RB3D_ZC_FLUSH_ALL 0x5 |
| 547 | # define RADEON_RB3D_ZC_BUSY (1 << 31) | 551 | # define RADEON_RB3D_ZC_BUSY (1 << 31) |
| 552 | #define RADEON_RB3D_DSTCACHE_CTLSTAT 0x325c | ||
| 553 | # define RADEON_RB3D_DC_FLUSH (3 << 0) | ||
| 554 | # define RADEON_RB3D_DC_FREE (3 << 2) | ||
| 555 | # define RADEON_RB3D_DC_FLUSH_ALL 0xf | ||
| 556 | # define RADEON_RB3D_DC_BUSY (1 << 31) | ||
| 548 | #define RADEON_RB3D_ZSTENCILCNTL 0x1c2c | 557 | #define RADEON_RB3D_ZSTENCILCNTL 0x1c2c |
| 549 | # define RADEON_Z_TEST_MASK (7 << 4) | 558 | # define RADEON_Z_TEST_MASK (7 << 4) |
| 550 | # define RADEON_Z_TEST_ALWAYS (7 << 4) | 559 | # define RADEON_Z_TEST_ALWAYS (7 << 4) |
| @@ -681,6 +690,7 @@ extern int r300_do_cp_cmdbuf(drm_device_t * dev, DRMFILE filp, | |||
| 681 | #define RADEON_CP_RB_BASE 0x0700 | 690 | #define RADEON_CP_RB_BASE 0x0700 |
| 682 | #define RADEON_CP_RB_CNTL 0x0704 | 691 | #define RADEON_CP_RB_CNTL 0x0704 |
| 683 | # define RADEON_BUF_SWAP_32BIT (2 << 16) | 692 | # define RADEON_BUF_SWAP_32BIT (2 << 16) |
| 693 | # define RADEON_RB_NO_UPDATE (1 << 27) | ||
| 684 | #define RADEON_CP_RB_RPTR_ADDR 0x070c | 694 | #define RADEON_CP_RB_RPTR_ADDR 0x070c |
| 685 | #define RADEON_CP_RB_RPTR 0x0710 | 695 | #define RADEON_CP_RB_RPTR 0x0710 |
| 686 | #define RADEON_CP_RB_WPTR 0x0714 | 696 | #define RADEON_CP_RB_WPTR 0x0714 |
| @@ -986,13 +996,13 @@ do { \ | |||
| 986 | } while (0) | 996 | } while (0) |
| 987 | 997 | ||
| 988 | #define RADEON_FLUSH_CACHE() do { \ | 998 | #define RADEON_FLUSH_CACHE() do { \ |
| 989 | OUT_RING( CP_PACKET0( RADEON_RB2D_DSTCACHE_CTLSTAT, 0 ) ); \ | 999 | OUT_RING( CP_PACKET0( RADEON_RB3D_DSTCACHE_CTLSTAT, 0 ) ); \ |
| 990 | OUT_RING( RADEON_RB2D_DC_FLUSH ); \ | 1000 | OUT_RING( RADEON_RB3D_DC_FLUSH ); \ |
| 991 | } while (0) | 1001 | } while (0) |
| 992 | 1002 | ||
| 993 | #define RADEON_PURGE_CACHE() do { \ | 1003 | #define RADEON_PURGE_CACHE() do { \ |
| 994 | OUT_RING( CP_PACKET0( RADEON_RB2D_DSTCACHE_CTLSTAT, 0 ) ); \ | 1004 | OUT_RING( CP_PACKET0( RADEON_RB3D_DSTCACHE_CTLSTAT, 0 ) ); \ |
| 995 | OUT_RING( RADEON_RB2D_DC_FLUSH_ALL ); \ | 1005 | OUT_RING( RADEON_RB3D_DC_FLUSH_ALL ); \ |
| 996 | } while (0) | 1006 | } while (0) |
| 997 | 1007 | ||
| 998 | #define RADEON_FLUSH_ZCACHE() do { \ | 1008 | #define RADEON_FLUSH_ZCACHE() do { \ |
diff --git a/drivers/char/drm/radeon_state.c b/drivers/char/drm/radeon_state.c index 39a7f685e3fd..feac5f005d47 100644 --- a/drivers/char/drm/radeon_state.c +++ b/drivers/char/drm/radeon_state.c | |||
| @@ -42,7 +42,11 @@ static __inline__ int radeon_check_and_fixup_offset(drm_radeon_private_t * | |||
| 42 | drm_file_t * filp_priv, | 42 | drm_file_t * filp_priv, |
| 43 | u32 *offset) | 43 | u32 *offset) |
| 44 | { | 44 | { |
| 45 | u32 off = *offset; | 45 | u64 off = *offset; |
| 46 | u32 fb_start = dev_priv->fb_location; | ||
| 47 | u32 fb_end = fb_start + dev_priv->fb_size - 1; | ||
| 48 | u32 gart_start = dev_priv->gart_vm_start; | ||
| 49 | u32 gart_end = gart_start + dev_priv->gart_size - 1; | ||
| 46 | struct drm_radeon_driver_file_fields *radeon_priv; | 50 | struct drm_radeon_driver_file_fields *radeon_priv; |
| 47 | 51 | ||
| 48 | /* Hrm ... the story of the offset ... So this function converts | 52 | /* Hrm ... the story of the offset ... So this function converts |
| @@ -62,10 +66,8 @@ static __inline__ int radeon_check_and_fixup_offset(drm_radeon_private_t * | |||
| 62 | /* First, the best case, the offset already lands in either the | 66 | /* First, the best case, the offset already lands in either the |
| 63 | * framebuffer or the GART mapped space | 67 | * framebuffer or the GART mapped space |
| 64 | */ | 68 | */ |
| 65 | if ((off >= dev_priv->fb_location && | 69 | if ((off >= fb_start && off <= fb_end) || |
| 66 | off < (dev_priv->fb_location + dev_priv->fb_size)) || | 70 | (off >= gart_start && off <= gart_end)) |
| 67 | (off >= dev_priv->gart_vm_start && | ||
| 68 | off < (dev_priv->gart_vm_start + dev_priv->gart_size))) | ||
| 69 | return 0; | 71 | return 0; |
| 70 | 72 | ||
| 71 | /* Ok, that didn't happen... now check if we have a zero based | 73 | /* Ok, that didn't happen... now check if we have a zero based |
| @@ -78,16 +80,13 @@ static __inline__ int radeon_check_and_fixup_offset(drm_radeon_private_t * | |||
| 78 | } | 80 | } |
| 79 | 81 | ||
| 80 | /* Finally, assume we aimed at a GART offset if beyond the fb */ | 82 | /* Finally, assume we aimed at a GART offset if beyond the fb */ |
| 81 | if (off > (dev_priv->fb_location + dev_priv->fb_size)) | 83 | if (off > fb_end) |
| 82 | off = off - (dev_priv->fb_location + dev_priv->fb_size) + | 84 | off = off - fb_end - 1 + gart_start; |
| 83 | dev_priv->gart_vm_start; | ||
| 84 | 85 | ||
| 85 | /* Now recheck and fail if out of bounds */ | 86 | /* Now recheck and fail if out of bounds */ |
| 86 | if ((off >= dev_priv->fb_location && | 87 | if ((off >= fb_start && off <= fb_end) || |
| 87 | off < (dev_priv->fb_location + dev_priv->fb_size)) || | 88 | (off >= gart_start && off <= gart_end)) { |
| 88 | (off >= dev_priv->gart_vm_start && | 89 | DRM_DEBUG("offset fixed up to 0x%x\n", (unsigned int)off); |
| 89 | off < (dev_priv->gart_vm_start + dev_priv->gart_size))) { | ||
| 90 | DRM_DEBUG("offset fixed up to 0x%x\n", off); | ||
| 91 | *offset = off; | 90 | *offset = off; |
| 92 | return 0; | 91 | return 0; |
| 93 | } | 92 | } |
| @@ -869,7 +868,7 @@ static void radeon_cp_dispatch_clear(drm_device_t * dev, | |||
| 869 | */ | 868 | */ |
| 870 | dev_priv->sarea_priv->ctx_owner = 0; | 869 | dev_priv->sarea_priv->ctx_owner = 0; |
| 871 | 870 | ||
| 872 | if ((dev_priv->flags & CHIP_HAS_HIERZ) | 871 | if ((dev_priv->flags & RADEON_HAS_HIERZ) |
| 873 | && (flags & RADEON_USE_HIERZ)) { | 872 | && (flags & RADEON_USE_HIERZ)) { |
| 874 | /* FIXME : reverse engineer that for Rx00 cards */ | 873 | /* FIXME : reverse engineer that for Rx00 cards */ |
| 875 | /* FIXME : the mask supposedly contains low-res z values. So can't set | 874 | /* FIXME : the mask supposedly contains low-res z values. So can't set |
| @@ -914,7 +913,7 @@ static void radeon_cp_dispatch_clear(drm_device_t * dev, | |||
| 914 | for (i = 0; i < nbox; i++) { | 913 | for (i = 0; i < nbox; i++) { |
| 915 | int tileoffset, nrtilesx, nrtilesy, j; | 914 | int tileoffset, nrtilesx, nrtilesy, j; |
| 916 | /* it looks like r200 needs rv-style clears, at least if hierz is not enabled? */ | 915 | /* it looks like r200 needs rv-style clears, at least if hierz is not enabled? */ |
| 917 | if ((dev_priv->flags & CHIP_HAS_HIERZ) | 916 | if ((dev_priv->flags & RADEON_HAS_HIERZ) |
| 918 | && !(dev_priv->microcode_version == UCODE_R200)) { | 917 | && !(dev_priv->microcode_version == UCODE_R200)) { |
| 919 | /* FIXME : figure this out for r200 (when hierz is enabled). Or | 918 | /* FIXME : figure this out for r200 (when hierz is enabled). Or |
| 920 | maybe r200 actually doesn't need to put the low-res z value into | 919 | maybe r200 actually doesn't need to put the low-res z value into |
| @@ -998,7 +997,7 @@ static void radeon_cp_dispatch_clear(drm_device_t * dev, | |||
| 998 | } | 997 | } |
| 999 | 998 | ||
| 1000 | /* TODO don't always clear all hi-level z tiles */ | 999 | /* TODO don't always clear all hi-level z tiles */ |
| 1001 | if ((dev_priv->flags & CHIP_HAS_HIERZ) | 1000 | if ((dev_priv->flags & RADEON_HAS_HIERZ) |
| 1002 | && (dev_priv->microcode_version == UCODE_R200) | 1001 | && (dev_priv->microcode_version == UCODE_R200) |
| 1003 | && (flags & RADEON_USE_HIERZ)) | 1002 | && (flags & RADEON_USE_HIERZ)) |
| 1004 | /* r100 and cards without hierarchical z-buffer have no high-level z-buffer */ | 1003 | /* r100 and cards without hierarchical z-buffer have no high-level z-buffer */ |
| @@ -1270,9 +1269,9 @@ static void radeon_cp_dispatch_swap(drm_device_t * dev) | |||
| 1270 | 1269 | ||
| 1271 | DRM_DEBUG("dispatch swap %d,%d-%d,%d\n", x, y, w, h); | 1270 | DRM_DEBUG("dispatch swap %d,%d-%d,%d\n", x, y, w, h); |
| 1272 | 1271 | ||
| 1273 | BEGIN_RING(7); | 1272 | BEGIN_RING(9); |
| 1274 | 1273 | ||
| 1275 | OUT_RING(CP_PACKET3(RADEON_CNTL_BITBLT_MULTI, 5)); | 1274 | OUT_RING(CP_PACKET0(RADEON_DP_GUI_MASTER_CNTL, 0)); |
| 1276 | OUT_RING(RADEON_GMC_SRC_PITCH_OFFSET_CNTL | | 1275 | OUT_RING(RADEON_GMC_SRC_PITCH_OFFSET_CNTL | |
| 1277 | RADEON_GMC_DST_PITCH_OFFSET_CNTL | | 1276 | RADEON_GMC_DST_PITCH_OFFSET_CNTL | |
| 1278 | RADEON_GMC_BRUSH_NONE | | 1277 | RADEON_GMC_BRUSH_NONE | |
| @@ -1284,6 +1283,7 @@ static void radeon_cp_dispatch_swap(drm_device_t * dev) | |||
| 1284 | 1283 | ||
| 1285 | /* Make this work even if front & back are flipped: | 1284 | /* Make this work even if front & back are flipped: |
| 1286 | */ | 1285 | */ |
| 1286 | OUT_RING(CP_PACKET0(RADEON_SRC_PITCH_OFFSET, 1)); | ||
| 1287 | if (dev_priv->current_page == 0) { | 1287 | if (dev_priv->current_page == 0) { |
| 1288 | OUT_RING(dev_priv->back_pitch_offset); | 1288 | OUT_RING(dev_priv->back_pitch_offset); |
| 1289 | OUT_RING(dev_priv->front_pitch_offset); | 1289 | OUT_RING(dev_priv->front_pitch_offset); |
| @@ -1292,6 +1292,7 @@ static void radeon_cp_dispatch_swap(drm_device_t * dev) | |||
| 1292 | OUT_RING(dev_priv->back_pitch_offset); | 1292 | OUT_RING(dev_priv->back_pitch_offset); |
| 1293 | } | 1293 | } |
| 1294 | 1294 | ||
| 1295 | OUT_RING(CP_PACKET0(RADEON_SRC_X_Y, 2)); | ||
| 1295 | OUT_RING((x << 16) | y); | 1296 | OUT_RING((x << 16) | y); |
| 1296 | OUT_RING((x << 16) | y); | 1297 | OUT_RING((x << 16) | y); |
| 1297 | OUT_RING((w << 16) | h); | 1298 | OUT_RING((w << 16) | h); |
| @@ -2987,16 +2988,21 @@ static int radeon_cp_getparam(DRM_IOCTL_ARGS) | |||
| 2987 | case RADEON_PARAM_GART_TEX_HANDLE: | 2988 | case RADEON_PARAM_GART_TEX_HANDLE: |
| 2988 | value = dev_priv->gart_textures_offset; | 2989 | value = dev_priv->gart_textures_offset; |
| 2989 | break; | 2990 | break; |
| 2990 | 2991 | case RADEON_PARAM_SCRATCH_OFFSET: | |
| 2992 | if (!dev_priv->writeback_works) | ||
| 2993 | return DRM_ERR(EINVAL); | ||
| 2994 | value = RADEON_SCRATCH_REG_OFFSET; | ||
| 2995 | break; | ||
| 2991 | case RADEON_PARAM_CARD_TYPE: | 2996 | case RADEON_PARAM_CARD_TYPE: |
| 2992 | if (dev_priv->flags & CHIP_IS_PCIE) | 2997 | if (dev_priv->flags & RADEON_IS_PCIE) |
| 2993 | value = RADEON_CARD_PCIE; | 2998 | value = RADEON_CARD_PCIE; |
| 2994 | else if (dev_priv->flags & CHIP_IS_AGP) | 2999 | else if (dev_priv->flags & RADEON_IS_AGP) |
| 2995 | value = RADEON_CARD_AGP; | 3000 | value = RADEON_CARD_AGP; |
| 2996 | else | 3001 | else |
| 2997 | value = RADEON_CARD_PCI; | 3002 | value = RADEON_CARD_PCI; |
| 2998 | break; | 3003 | break; |
| 2999 | default: | 3004 | default: |
| 3005 | DRM_DEBUG("Invalid parameter %d\n", param.param); | ||
| 3000 | return DRM_ERR(EINVAL); | 3006 | return DRM_ERR(EINVAL); |
| 3001 | } | 3007 | } |
| 3002 | 3008 | ||
diff --git a/drivers/char/drm/sis_drv.c b/drivers/char/drm/sis_drv.c index 5e9dc86f2956..3d5b3218b6ff 100644 --- a/drivers/char/drm/sis_drv.c +++ b/drivers/char/drm/sis_drv.c | |||
| @@ -35,11 +35,44 @@ static struct pci_device_id pciidlist[] = { | |||
| 35 | sisdrv_PCI_IDS | 35 | sisdrv_PCI_IDS |
| 36 | }; | 36 | }; |
| 37 | 37 | ||
| 38 | static int sis_driver_load(drm_device_t *dev, unsigned long chipset) | ||
| 39 | { | ||
| 40 | drm_sis_private_t *dev_priv; | ||
| 41 | int ret; | ||
| 42 | |||
| 43 | dev_priv = drm_calloc(1, sizeof(drm_sis_private_t), DRM_MEM_DRIVER); | ||
| 44 | if (dev_priv == NULL) | ||
| 45 | return DRM_ERR(ENOMEM); | ||
| 46 | |||
| 47 | dev->dev_private = (void *)dev_priv; | ||
| 48 | dev_priv->chipset = chipset; | ||
| 49 | ret = drm_sman_init(&dev_priv->sman, 2, 12, 8); | ||
| 50 | if (ret) { | ||
| 51 | drm_free(dev_priv, sizeof(dev_priv), DRM_MEM_DRIVER); | ||
| 52 | } | ||
| 53 | |||
| 54 | return ret; | ||
| 55 | } | ||
| 56 | |||
| 57 | static int sis_driver_unload(drm_device_t *dev) | ||
| 58 | { | ||
| 59 | drm_sis_private_t *dev_priv = dev->dev_private; | ||
| 60 | |||
| 61 | drm_sman_takedown(&dev_priv->sman); | ||
| 62 | drm_free(dev_priv, sizeof(*dev_priv), DRM_MEM_DRIVER); | ||
| 63 | |||
| 64 | return 0; | ||
| 65 | } | ||
| 66 | |||
| 38 | static struct drm_driver driver = { | 67 | static struct drm_driver driver = { |
| 39 | .driver_features = DRIVER_USE_AGP | DRIVER_USE_MTRR, | 68 | .driver_features = DRIVER_USE_AGP | DRIVER_USE_MTRR, |
| 40 | .context_ctor = sis_init_context, | 69 | .load = sis_driver_load, |
| 41 | .context_dtor = sis_final_context, | 70 | .unload = sis_driver_unload, |
| 42 | .reclaim_buffers = drm_core_reclaim_buffers, | 71 | .context_dtor = NULL, |
| 72 | .dma_quiescent = sis_idle, | ||
| 73 | .reclaim_buffers = NULL, | ||
| 74 | .reclaim_buffers_locked = sis_reclaim_buffers_locked, | ||
| 75 | .lastclose = sis_lastclose, | ||
| 43 | .get_map_ofs = drm_core_get_map_ofs, | 76 | .get_map_ofs = drm_core_get_map_ofs, |
| 44 | .get_reg_ofs = drm_core_get_reg_ofs, | 77 | .get_reg_ofs = drm_core_get_reg_ofs, |
| 45 | .ioctls = sis_ioctls, | 78 | .ioctls = sis_ioctls, |
diff --git a/drivers/char/drm/sis_drv.h b/drivers/char/drm/sis_drv.h index e218e5269503..2b8d6f6ed7c0 100644 --- a/drivers/char/drm/sis_drv.h +++ b/drivers/char/drm/sis_drv.h | |||
| @@ -31,23 +31,39 @@ | |||
| 31 | /* General customization: | 31 | /* General customization: |
| 32 | */ | 32 | */ |
| 33 | 33 | ||
| 34 | #define DRIVER_AUTHOR "SIS" | 34 | #define DRIVER_AUTHOR "SIS, Tungsten Graphics" |
| 35 | #define DRIVER_NAME "sis" | 35 | #define DRIVER_NAME "sis" |
| 36 | #define DRIVER_DESC "SIS 300/630/540" | 36 | #define DRIVER_DESC "SIS 300/630/540" |
| 37 | #define DRIVER_DATE "20030826" | 37 | #define DRIVER_DATE "20060704" |
| 38 | #define DRIVER_MAJOR 1 | 38 | #define DRIVER_MAJOR 1 |
| 39 | #define DRIVER_MINOR 1 | 39 | #define DRIVER_MINOR 2 |
| 40 | #define DRIVER_PATCHLEVEL 0 | 40 | #define DRIVER_PATCHLEVEL 1 |
| 41 | 41 | ||
| 42 | #include "sis_ds.h" | 42 | enum sis_family { |
| 43 | SIS_OTHER = 0, | ||
| 44 | SIS_CHIP_315 = 1, | ||
| 45 | }; | ||
| 46 | |||
| 47 | #include "drm_sman.h" | ||
| 48 | |||
| 49 | #define SIS_BASE (dev_priv->mmio) | ||
| 50 | #define SIS_READ(reg) DRM_READ32(SIS_BASE, reg); | ||
| 51 | #define SIS_WRITE(reg, val) DRM_WRITE32(SIS_BASE, reg, val); | ||
| 43 | 52 | ||
| 44 | typedef struct drm_sis_private { | 53 | typedef struct drm_sis_private { |
| 45 | memHeap_t *AGPHeap; | 54 | drm_local_map_t *mmio; |
| 46 | memHeap_t *FBHeap; | 55 | unsigned int idle_fault; |
| 56 | drm_sman_t sman; | ||
| 57 | unsigned int chipset; | ||
| 58 | int vram_initialized; | ||
| 59 | int agp_initialized; | ||
| 60 | unsigned long vram_offset; | ||
| 61 | unsigned long agp_offset; | ||
| 47 | } drm_sis_private_t; | 62 | } drm_sis_private_t; |
| 48 | 63 | ||
| 49 | extern int sis_init_context(drm_device_t * dev, int context); | 64 | extern int sis_idle(drm_device_t *dev); |
| 50 | extern int sis_final_context(drm_device_t * dev, int context); | 65 | extern void sis_reclaim_buffers_locked(drm_device_t *dev, struct file *filp); |
| 66 | extern void sis_lastclose(drm_device_t *dev); | ||
| 51 | 67 | ||
| 52 | extern drm_ioctl_desc_t sis_ioctls[]; | 68 | extern drm_ioctl_desc_t sis_ioctls[]; |
| 53 | extern int sis_max_ioctl; | 69 | extern int sis_max_ioctl; |
diff --git a/drivers/char/drm/sis_ds.c b/drivers/char/drm/sis_ds.c deleted file mode 100644 index 2e485d482943..000000000000 --- a/drivers/char/drm/sis_ds.c +++ /dev/null | |||
| @@ -1,299 +0,0 @@ | |||
| 1 | /* sis_ds.c -- Private header for Direct Rendering Manager -*- linux-c -*- | ||
| 2 | * Created: Mon Jan 4 10:05:05 1999 by sclin@sis.com.tw | ||
| 3 | * | ||
| 4 | * Copyright 2000 Silicon Integrated Systems Corp, Inc., HsinChu, Taiwan. | ||
| 5 | * All rights reserved. | ||
| 6 | * | ||
| 7 | * Permission is hereby granted, free of charge, to any person obtaining a | ||
| 8 | * copy of this software and associated documentation files (the "Software"), | ||
| 9 | * to deal in the Software without restriction, including without limitation | ||
| 10 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, | ||
| 11 | * and/or sell copies of the Software, and to permit persons to whom the | ||
| 12 | * Software is furnished to do so, subject to the following conditions: | ||
| 13 | * | ||
| 14 | * The above copyright notice and this permission notice (including the next | ||
| 15 | * paragraph) shall be included in all copies or substantial portions of the | ||
| 16 | * Software. | ||
| 17 | * | ||
| 18 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
| 19 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
| 20 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | ||
| 21 | * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR | ||
| 22 | * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, | ||
| 23 | * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER | ||
| 24 | * DEALINGS IN THE SOFTWARE. | ||
| 25 | * | ||
| 26 | * Authors: | ||
| 27 | * Sung-Ching Lin <sclin@sis.com.tw> | ||
| 28 | * | ||
| 29 | */ | ||
| 30 | |||
| 31 | #include "drmP.h" | ||
| 32 | #include "drm.h" | ||
| 33 | #include "sis_ds.h" | ||
| 34 | |||
| 35 | /* Set Data Structure, not check repeated value | ||
| 36 | * temporarily used | ||
| 37 | */ | ||
| 38 | |||
| 39 | set_t *setInit(void) | ||
| 40 | { | ||
| 41 | int i; | ||
| 42 | set_t *set; | ||
| 43 | |||
| 44 | set = (set_t *) drm_alloc(sizeof(set_t), DRM_MEM_DRIVER); | ||
| 45 | if (set != NULL) { | ||
| 46 | for (i = 0; i < SET_SIZE; i++) { | ||
| 47 | set->list[i].free_next = i + 1; | ||
| 48 | set->list[i].alloc_next = -1; | ||
| 49 | } | ||
| 50 | set->list[SET_SIZE - 1].free_next = -1; | ||
| 51 | set->free = 0; | ||
| 52 | set->alloc = -1; | ||
| 53 | set->trace = -1; | ||
| 54 | } | ||
| 55 | return set; | ||
| 56 | } | ||
| 57 | |||
| 58 | int setAdd(set_t * set, ITEM_TYPE item) | ||
| 59 | { | ||
| 60 | int free = set->free; | ||
| 61 | |||
| 62 | if (free != -1) { | ||
| 63 | set->list[free].val = item; | ||
| 64 | set->free = set->list[free].free_next; | ||
| 65 | } else { | ||
| 66 | return 0; | ||
| 67 | } | ||
| 68 | |||
| 69 | set->list[free].alloc_next = set->alloc; | ||
| 70 | set->alloc = free; | ||
| 71 | set->list[free].free_next = -1; | ||
| 72 | |||
| 73 | return 1; | ||
| 74 | } | ||
| 75 | |||
| 76 | int setDel(set_t * set, ITEM_TYPE item) | ||
| 77 | { | ||
| 78 | int alloc = set->alloc; | ||
| 79 | int prev = -1; | ||
| 80 | |||
| 81 | while (alloc != -1) { | ||
| 82 | if (set->list[alloc].val == item) { | ||
| 83 | if (prev != -1) | ||
| 84 | set->list[prev].alloc_next = | ||
| 85 | set->list[alloc].alloc_next; | ||
| 86 | else | ||
| 87 | set->alloc = set->list[alloc].alloc_next; | ||
| 88 | break; | ||
| 89 | } | ||
| 90 | prev = alloc; | ||
| 91 | alloc = set->list[alloc].alloc_next; | ||
| 92 | } | ||
| 93 | |||
| 94 | if (alloc == -1) | ||
| 95 | return 0; | ||
| 96 | |||
| 97 | set->list[alloc].free_next = set->free; | ||
| 98 | set->free = alloc; | ||
| 99 | set->list[alloc].alloc_next = -1; | ||
| 100 | |||
| 101 | return 1; | ||
| 102 | } | ||
| 103 | |||
| 104 | /* setFirst -> setAdd -> setNext is wrong */ | ||
| 105 | |||
| 106 | int setFirst(set_t * set, ITEM_TYPE * item) | ||
| 107 | { | ||
| 108 | if (set->alloc == -1) | ||
| 109 | return 0; | ||
| 110 | |||
| 111 | *item = set->list[set->alloc].val; | ||
| 112 | set->trace = set->list[set->alloc].alloc_next; | ||
| 113 | |||
| 114 | return 1; | ||
| 115 | } | ||
| 116 | |||
| 117 | int setNext(set_t * set, ITEM_TYPE * item) | ||
| 118 | { | ||
| 119 | if (set->trace == -1) | ||
| 120 | return 0; | ||
| 121 | |||
| 122 | *item = set->list[set->trace].val; | ||
| 123 | set->trace = set->list[set->trace].alloc_next; | ||
| 124 | |||
| 125 | return 1; | ||
| 126 | } | ||
| 127 | |||
| 128 | int setDestroy(set_t * set) | ||
| 129 | { | ||
| 130 | drm_free(set, sizeof(set_t), DRM_MEM_DRIVER); | ||
| 131 | |||
| 132 | return 1; | ||
| 133 | } | ||
| 134 | |||
| 135 | /* | ||
| 136 | * GLX Hardware Device Driver common code | ||
| 137 | * Copyright (C) 1999 Wittawat Yamwong | ||
| 138 | * | ||
| 139 | * Permission is hereby granted, free of charge, to any person obtaining a | ||
| 140 | * copy of this software and associated documentation files (the "Software"), | ||
| 141 | * to deal in the Software without restriction, including without limitation | ||
| 142 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, | ||
| 143 | * and/or sell copies of the Software, and to permit persons to whom the | ||
| 144 | * Software is furnished to do so, subject to the following conditions: | ||
| 145 | * | ||
| 146 | * The above copyright notice and this permission notice shall be included | ||
| 147 | * in all copies or substantial portions of the Software. | ||
| 148 | * | ||
| 149 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS | ||
| 150 | * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
| 151 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | ||
| 152 | * WITTAWAT YAMWONG, OR ANY OTHER CONTRIBUTORS BE LIABLE FOR ANY CLAIM, | ||
| 153 | * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR | ||
| 154 | * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE | ||
| 155 | * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | ||
| 156 | * | ||
| 157 | */ | ||
| 158 | |||
| 159 | #define ISFREE(bptr) ((bptr)->free) | ||
| 160 | |||
| 161 | memHeap_t *mmInit(int ofs, int size) | ||
| 162 | { | ||
| 163 | PMemBlock blocks; | ||
| 164 | |||
| 165 | if (size <= 0) | ||
| 166 | return NULL; | ||
| 167 | |||
| 168 | blocks = (TMemBlock *) drm_calloc(1, sizeof(TMemBlock), DRM_MEM_DRIVER); | ||
| 169 | if (blocks != NULL) { | ||
| 170 | blocks->ofs = ofs; | ||
| 171 | blocks->size = size; | ||
| 172 | blocks->free = 1; | ||
| 173 | return (memHeap_t *) blocks; | ||
| 174 | } else | ||
| 175 | return NULL; | ||
| 176 | } | ||
| 177 | |||
| 178 | /* Checks if a pointer 'b' is part of the heap 'heap' */ | ||
| 179 | int mmBlockInHeap(memHeap_t * heap, PMemBlock b) | ||
| 180 | { | ||
| 181 | TMemBlock *p; | ||
| 182 | |||
| 183 | if (heap == NULL || b == NULL) | ||
| 184 | return 0; | ||
| 185 | |||
| 186 | p = heap; | ||
| 187 | while (p != NULL && p != b) { | ||
| 188 | p = p->next; | ||
| 189 | } | ||
| 190 | if (p == b) | ||
| 191 | return 1; | ||
| 192 | else | ||
| 193 | return 0; | ||
| 194 | } | ||
| 195 | |||
| 196 | static TMemBlock *SliceBlock(TMemBlock * p, | ||
| 197 | int startofs, int size, | ||
| 198 | int reserved, int alignment) | ||
| 199 | { | ||
| 200 | TMemBlock *newblock; | ||
| 201 | |||
| 202 | /* break left */ | ||
| 203 | if (startofs > p->ofs) { | ||
| 204 | newblock = (TMemBlock *) drm_calloc(1, sizeof(TMemBlock), | ||
| 205 | DRM_MEM_DRIVER); | ||
| 206 | newblock->ofs = startofs; | ||
| 207 | newblock->size = p->size - (startofs - p->ofs); | ||
| 208 | newblock->free = 1; | ||
| 209 | newblock->next = p->next; | ||
| 210 | p->size -= newblock->size; | ||
| 211 | p->next = newblock; | ||
| 212 | p = newblock; | ||
| 213 | } | ||
| 214 | |||
| 215 | /* break right */ | ||
| 216 | if (size < p->size) { | ||
| 217 | newblock = (TMemBlock *) drm_calloc(1, sizeof(TMemBlock), | ||
| 218 | DRM_MEM_DRIVER); | ||
| 219 | newblock->ofs = startofs + size; | ||
| 220 | newblock->size = p->size - size; | ||
| 221 | newblock->free = 1; | ||
| 222 | newblock->next = p->next; | ||
| 223 | p->size = size; | ||
| 224 | p->next = newblock; | ||
| 225 | } | ||
| 226 | |||
| 227 | /* p = middle block */ | ||
| 228 | p->align = alignment; | ||
| 229 | p->free = 0; | ||
| 230 | p->reserved = reserved; | ||
| 231 | return p; | ||
| 232 | } | ||
| 233 | |||
| 234 | PMemBlock mmAllocMem(memHeap_t * heap, int size, int align2, int startSearch) | ||
| 235 | { | ||
| 236 | int mask, startofs, endofs; | ||
| 237 | TMemBlock *p; | ||
| 238 | |||
| 239 | if (heap == NULL || align2 < 0 || size <= 0) | ||
| 240 | return NULL; | ||
| 241 | |||
| 242 | mask = (1 << align2) - 1; | ||
| 243 | startofs = 0; | ||
| 244 | p = (TMemBlock *) heap; | ||
| 245 | while (p != NULL) { | ||
| 246 | if (ISFREE(p)) { | ||
| 247 | startofs = (p->ofs + mask) & ~mask; | ||
| 248 | if (startofs < startSearch) { | ||
| 249 | startofs = startSearch; | ||
| 250 | } | ||
| 251 | endofs = startofs + size; | ||
| 252 | if (endofs <= (p->ofs + p->size)) | ||
| 253 | break; | ||
| 254 | } | ||
| 255 | p = p->next; | ||
| 256 | } | ||
| 257 | if (p == NULL) | ||
| 258 | return NULL; | ||
| 259 | p = SliceBlock(p, startofs, size, 0, mask + 1); | ||
| 260 | p->heap = heap; | ||
| 261 | return p; | ||
| 262 | } | ||
| 263 | |||
| 264 | static __inline__ int Join2Blocks(TMemBlock * p) | ||
| 265 | { | ||
| 266 | if (p->free && p->next && p->next->free) { | ||
| 267 | TMemBlock *q = p->next; | ||
| 268 | p->size += q->size; | ||
| 269 | p->next = q->next; | ||
| 270 | drm_free(q, sizeof(TMemBlock), DRM_MEM_DRIVER); | ||
| 271 | return 1; | ||
| 272 | } | ||
| 273 | return 0; | ||
| 274 | } | ||
| 275 | |||
| 276 | int mmFreeMem(PMemBlock b) | ||
| 277 | { | ||
| 278 | TMemBlock *p, *prev; | ||
| 279 | |||
| 280 | if (b == NULL) | ||
| 281 | return 0; | ||
| 282 | if (b->heap == NULL) | ||
| 283 | return -1; | ||
| 284 | |||
| 285 | p = b->heap; | ||
| 286 | prev = NULL; | ||
| 287 | while (p != NULL && p != b) { | ||
| 288 | prev = p; | ||
| 289 | p = p->next; | ||
| 290 | } | ||
| 291 | if (p == NULL || p->free || p->reserved) | ||
| 292 | return -1; | ||
| 293 | |||
| 294 | p->free = 1; | ||
| 295 | Join2Blocks(p); | ||
| 296 | if (prev) | ||
| 297 | Join2Blocks(prev); | ||
| 298 | return 0; | ||
| 299 | } | ||
diff --git a/drivers/char/drm/sis_ds.h b/drivers/char/drm/sis_ds.h deleted file mode 100644 index 94f2b4728b63..000000000000 --- a/drivers/char/drm/sis_ds.h +++ /dev/null | |||
| @@ -1,146 +0,0 @@ | |||
| 1 | /* sis_ds.h -- Private header for Direct Rendering Manager -*- linux-c -*- | ||
| 2 | * Created: Mon Jan 4 10:05:05 1999 by sclin@sis.com.tw | ||
| 3 | */ | ||
| 4 | /* | ||
| 5 | * Copyright 2000 Silicon Integrated Systems Corp, Inc., HsinChu, Taiwan. | ||
| 6 | * All rights reserved. | ||
| 7 | * | ||
| 8 | * Permission is hereby granted, free of charge, to any person obtaining a | ||
| 9 | * copy of this software and associated documentation files (the "Software"), | ||
| 10 | * to deal in the Software without restriction, including without limitation | ||
| 11 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, | ||
| 12 | * and/or sell copies of the Software, and to permit persons to whom the | ||
| 13 | * Software is furnished to do so, subject to the following conditions: | ||
| 14 | * | ||
| 15 | * The above copyright notice and this permission notice (including the next | ||
| 16 | * paragraph) shall be included in all copies or substantial portions of the | ||
| 17 | * Software. | ||
| 18 | * | ||
| 19 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
| 20 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
| 21 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | ||
| 22 | * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR | ||
| 23 | * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, | ||
| 24 | * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER | ||
| 25 | * DEALINGS IN THE SOFTWARE. | ||
| 26 | * | ||
| 27 | * Authors: | ||
| 28 | * Sung-Ching Lin <sclin@sis.com.tw> | ||
| 29 | * | ||
| 30 | */ | ||
| 31 | |||
| 32 | #ifndef __SIS_DS_H__ | ||
| 33 | #define __SIS_DS_H__ | ||
| 34 | |||
| 35 | /* Set Data Structure */ | ||
| 36 | |||
| 37 | #define SET_SIZE 5000 | ||
| 38 | |||
| 39 | typedef unsigned long ITEM_TYPE; | ||
| 40 | |||
| 41 | typedef struct { | ||
| 42 | ITEM_TYPE val; | ||
| 43 | int alloc_next, free_next; | ||
| 44 | } list_item_t; | ||
| 45 | |||
| 46 | typedef struct { | ||
| 47 | int alloc; | ||
| 48 | int free; | ||
| 49 | int trace; | ||
| 50 | list_item_t list[SET_SIZE]; | ||
| 51 | } set_t; | ||
| 52 | |||
| 53 | set_t *setInit(void); | ||
| 54 | int setAdd(set_t * set, ITEM_TYPE item); | ||
| 55 | int setDel(set_t * set, ITEM_TYPE item); | ||
| 56 | int setFirst(set_t * set, ITEM_TYPE * item); | ||
| 57 | int setNext(set_t * set, ITEM_TYPE * item); | ||
| 58 | int setDestroy(set_t * set); | ||
| 59 | |||
| 60 | /* | ||
| 61 | * GLX Hardware Device Driver common code | ||
| 62 | * Copyright (C) 1999 Wittawat Yamwong | ||
| 63 | * | ||
| 64 | * Permission is hereby granted, free of charge, to any person obtaining a | ||
| 65 | * copy of this software and associated documentation files (the "Software"), | ||
| 66 | * to deal in the Software without restriction, including without limitation | ||
| 67 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, | ||
| 68 | * and/or sell copies of the Software, and to permit persons to whom the | ||
| 69 | * Software is furnished to do so, subject to the following conditions: | ||
| 70 | * | ||
| 71 | * The above copyright notice and this permission notice shall be included | ||
| 72 | * in all copies or substantial portions of the Software. | ||
| 73 | * | ||
| 74 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS | ||
| 75 | * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
| 76 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | ||
| 77 | * WITTAWAT YAMWONG, OR ANY OTHER CONTRIBUTORS BE LIABLE FOR ANY CLAIM, | ||
| 78 | * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR | ||
| 79 | * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE | ||
| 80 | * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | ||
| 81 | * | ||
| 82 | */ | ||
| 83 | |||
| 84 | struct mem_block_t { | ||
| 85 | struct mem_block_t *next; | ||
| 86 | struct mem_block_t *heap; | ||
| 87 | int ofs, size; | ||
| 88 | int align; | ||
| 89 | unsigned int free:1; | ||
| 90 | unsigned int reserved:1; | ||
| 91 | }; | ||
| 92 | typedef struct mem_block_t TMemBlock; | ||
| 93 | typedef struct mem_block_t *PMemBlock; | ||
| 94 | |||
| 95 | /* a heap is just the first block in a chain */ | ||
| 96 | typedef struct mem_block_t memHeap_t; | ||
| 97 | |||
| 98 | static __inline__ int mmBlockSize(PMemBlock b) | ||
| 99 | { | ||
| 100 | return b->size; | ||
| 101 | } | ||
| 102 | |||
| 103 | static __inline__ int mmOffset(PMemBlock b) | ||
| 104 | { | ||
| 105 | return b->ofs; | ||
| 106 | } | ||
| 107 | |||
| 108 | static __inline__ void mmMarkReserved(PMemBlock b) | ||
| 109 | { | ||
| 110 | b->reserved = 1; | ||
| 111 | } | ||
| 112 | |||
| 113 | /* | ||
| 114 | * input: total size in bytes | ||
| 115 | * return: a heap pointer if OK, NULL if error | ||
| 116 | */ | ||
| 117 | memHeap_t *mmInit(int ofs, int size); | ||
| 118 | |||
| 119 | /* | ||
| 120 | * Allocate 'size' bytes with 2^align2 bytes alignment, | ||
| 121 | * restrict the search to free memory after 'startSearch' | ||
| 122 | * depth and back buffers should be in different 4mb banks | ||
| 123 | * to get better page hits if possible | ||
| 124 | * input: size = size of block | ||
| 125 | * align2 = 2^align2 bytes alignment | ||
| 126 | * startSearch = linear offset from start of heap to begin search | ||
| 127 | * return: pointer to the allocated block, 0 if error | ||
| 128 | */ | ||
| 129 | PMemBlock mmAllocMem(memHeap_t * heap, int size, int align2, int startSearch); | ||
| 130 | |||
| 131 | /* | ||
| 132 | * Returns 1 if the block 'b' is part of the heap 'heap' | ||
| 133 | */ | ||
| 134 | int mmBlockInHeap(PMemBlock heap, PMemBlock b); | ||
| 135 | |||
| 136 | /* | ||
| 137 | * Free block starts at offset | ||
| 138 | * input: pointer to a block | ||
| 139 | * return: 0 if OK, -1 if error | ||
| 140 | */ | ||
| 141 | int mmFreeMem(PMemBlock b); | ||
| 142 | |||
| 143 | /* For debuging purpose. */ | ||
| 144 | void mmDumpMemInfo(memHeap_t * mmInit); | ||
| 145 | |||
| 146 | #endif /* __SIS_DS_H__ */ | ||
diff --git a/drivers/char/drm/sis_mm.c b/drivers/char/drm/sis_mm.c index 5e9936bc307f..d26f5dbb7853 100644 --- a/drivers/char/drm/sis_mm.c +++ b/drivers/char/drm/sis_mm.c | |||
| @@ -1,414 +1,348 @@ | |||
| 1 | /* sis_mm.c -- Private header for Direct Rendering Manager -*- linux-c -*- | 1 | /************************************************************************** |
| 2 | * Created: Mon Jan 4 10:05:05 1999 by sclin@sis.com.tw | ||
| 3 | * | 2 | * |
| 4 | * Copyright 2000 Silicon Integrated Systems Corp, Inc., HsinChu, Taiwan. | 3 | * Copyright 2006 Tungsten Graphics, Inc., Bismarck, ND., USA. |
| 5 | * All rights reserved. | 4 | * All Rights Reserved. |
| 6 | * | 5 | * |
| 7 | * Permission is hereby granted, free of charge, to any person obtaining a | 6 | * Permission is hereby granted, free of charge, to any person obtaining a |
| 8 | * copy of this software and associated documentation files (the "Software"), | 7 | * copy of this software and associated documentation files (the |
| 9 | * to deal in the Software without restriction, including without limitation | 8 | * "Software"), to deal in the Software without restriction, including |
| 10 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, | 9 | * without limitation the rights to use, copy, modify, merge, publish, |
| 11 | * and/or sell copies of the Software, and to permit persons to whom the | 10 | * distribute, sub license, and/or sell copies of the Software, and to |
| 12 | * Software is furnished to do so, subject to the following conditions: | 11 | * permit persons to whom the Software is furnished to do so, subject to |
| 12 | * the following conditions: | ||
| 13 | * | 13 | * |
| 14 | * The above copyright notice and this permission notice (including the next | 14 | * The above copyright notice and this permission notice (including the |
| 15 | * paragraph) shall be included in all copies or substantial portions of the | 15 | * next paragraph) shall be included in all copies or substantial portions |
| 16 | * Software. | 16 | * of the Software. |
| 17 | * | 17 | * |
| 18 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | 18 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
| 19 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | 19 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
| 20 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | 20 | * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL |
| 21 | * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR | 21 | * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, |
| 22 | * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, | 22 | * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR |
| 23 | * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER | 23 | * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE |
| 24 | * DEALINGS IN THE SOFTWARE. | 24 | * USE OR OTHER DEALINGS IN THE SOFTWARE. |
| 25 | * | 25 | * |
| 26 | * Authors: | ||
| 27 | * Sung-Ching Lin <sclin@sis.com.tw> | ||
| 28 | * | 26 | * |
| 27 | **************************************************************************/ | ||
| 28 | |||
| 29 | /* | ||
| 30 | * Authors: | ||
| 31 | * Thomas Hellström <thomas-at-tungstengraphics-dot-com> | ||
| 29 | */ | 32 | */ |
| 30 | 33 | ||
| 31 | #include "drmP.h" | 34 | #include "drmP.h" |
| 32 | #include "sis_drm.h" | 35 | #include "sis_drm.h" |
| 33 | #include "sis_drv.h" | 36 | #include "sis_drv.h" |
| 34 | #include "sis_ds.h" | 37 | |
| 35 | #if defined(__linux__) && defined(CONFIG_FB_SIS) | ||
| 36 | #include <video/sisfb.h> | 38 | #include <video/sisfb.h> |
| 37 | #endif | ||
| 38 | 39 | ||
| 39 | #define MAX_CONTEXT 100 | ||
| 40 | #define VIDEO_TYPE 0 | 40 | #define VIDEO_TYPE 0 |
| 41 | #define AGP_TYPE 1 | 41 | #define AGP_TYPE 1 |
| 42 | 42 | ||
| 43 | typedef struct { | ||
| 44 | int used; | ||
| 45 | int context; | ||
| 46 | set_t *sets[2]; /* 0 for video, 1 for AGP */ | ||
| 47 | } sis_context_t; | ||
| 48 | 43 | ||
| 49 | static sis_context_t global_ppriv[MAX_CONTEXT]; | 44 | #if defined(CONFIG_FB_SIS) |
| 45 | /* fb management via fb device */ | ||
| 50 | 46 | ||
| 51 | static int add_alloc_set(int context, int type, unsigned int val) | 47 | #define SIS_MM_ALIGN_SHIFT 0 |
| 52 | { | 48 | #define SIS_MM_ALIGN_MASK 0 |
| 53 | int i, retval = 0; | ||
| 54 | 49 | ||
| 55 | for (i = 0; i < MAX_CONTEXT; i++) { | 50 | static void *sis_sman_mm_allocate(void *private, unsigned long size, |
| 56 | if (global_ppriv[i].used && global_ppriv[i].context == context) { | 51 | unsigned alignment) |
| 57 | retval = setAdd(global_ppriv[i].sets[type], val); | ||
| 58 | break; | ||
| 59 | } | ||
| 60 | } | ||
| 61 | return retval; | ||
| 62 | } | ||
| 63 | |||
| 64 | static int del_alloc_set(int context, int type, unsigned int val) | ||
| 65 | { | 52 | { |
| 66 | int i, retval = 0; | 53 | struct sis_memreq req; |
| 67 | 54 | ||
| 68 | for (i = 0; i < MAX_CONTEXT; i++) { | 55 | req.size = size; |
| 69 | if (global_ppriv[i].used && global_ppriv[i].context == context) { | 56 | sis_malloc(&req); |
| 70 | retval = setDel(global_ppriv[i].sets[type], val); | 57 | if (req.size == 0) |
| 71 | break; | 58 | return NULL; |
| 72 | } | 59 | else |
| 73 | } | 60 | return (void *)~req.offset; |
| 74 | return retval; | ||
| 75 | } | 61 | } |
| 76 | 62 | ||
| 77 | /* fb management via fb device */ | 63 | static void sis_sman_mm_free(void *private, void *ref) |
| 78 | #if defined(__linux__) && defined(CONFIG_FB_SIS) | ||
| 79 | |||
| 80 | static int sis_fb_init(DRM_IOCTL_ARGS) | ||
| 81 | { | 64 | { |
| 82 | return 0; | 65 | sis_free(~((unsigned long)ref)); |
| 83 | } | 66 | } |
| 84 | 67 | ||
| 85 | static int sis_fb_alloc(DRM_IOCTL_ARGS) | 68 | static void sis_sman_mm_destroy(void *private) |
| 86 | { | 69 | { |
| 87 | drm_sis_mem_t fb; | 70 | ; |
| 88 | struct sis_memreq req; | ||
| 89 | drm_sis_mem_t __user *argp = (drm_sis_mem_t __user *)data; | ||
| 90 | int retval = 0; | ||
| 91 | |||
| 92 | DRM_COPY_FROM_USER_IOCTL(fb, argp, sizeof(fb)); | ||
| 93 | |||
| 94 | req.size = fb.size; | ||
| 95 | sis_malloc(&req); | ||
| 96 | if (req.offset) { | ||
| 97 | /* TODO */ | ||
| 98 | fb.offset = req.offset; | ||
| 99 | fb.free = req.offset; | ||
| 100 | if (!add_alloc_set(fb.context, VIDEO_TYPE, fb.free)) { | ||
| 101 | DRM_DEBUG("adding to allocation set fails\n"); | ||
| 102 | sis_free(req.offset); | ||
| 103 | retval = DRM_ERR(EINVAL); | ||
| 104 | } | ||
| 105 | } else { | ||
| 106 | fb.offset = 0; | ||
| 107 | fb.size = 0; | ||
| 108 | fb.free = 0; | ||
| 109 | } | ||
| 110 | |||
| 111 | DRM_COPY_TO_USER_IOCTL(argp, fb, sizeof(fb)); | ||
| 112 | |||
| 113 | DRM_DEBUG("alloc fb, size = %d, offset = %d\n", fb.size, req.offset); | ||
| 114 | |||
| 115 | return retval; | ||
| 116 | } | 71 | } |
| 117 | 72 | ||
| 118 | static int sis_fb_free(DRM_IOCTL_ARGS) | 73 | static unsigned long sis_sman_mm_offset(void *private, void *ref) |
| 119 | { | 74 | { |
| 120 | drm_sis_mem_t fb; | 75 | return ~((unsigned long)ref); |
| 121 | int retval = 0; | 76 | } |
| 122 | |||
| 123 | DRM_COPY_FROM_USER_IOCTL(fb, (drm_sis_mem_t __user *) data, sizeof(fb)); | ||
| 124 | |||
| 125 | if (!fb.free) | ||
| 126 | return DRM_ERR(EINVAL); | ||
| 127 | 77 | ||
| 128 | if (!del_alloc_set(fb.context, VIDEO_TYPE, fb.free)) | 78 | #else /* CONFIG_FB_SIS */ |
| 129 | retval = DRM_ERR(EINVAL); | ||
| 130 | sis_free(fb.free); | ||
| 131 | 79 | ||
| 132 | DRM_DEBUG("free fb, offset = 0x%lx\n", fb.free); | 80 | #define SIS_MM_ALIGN_SHIFT 4 |
| 81 | #define SIS_MM_ALIGN_MASK ( (1 << SIS_MM_ALIGN_SHIFT) - 1) | ||
| 133 | 82 | ||
| 134 | return retval; | 83 | #endif /* CONFIG_FB_SIS */ |
| 135 | } | ||
| 136 | 84 | ||
| 137 | #else | ||
| 138 | |||
| 139 | /* Called by the X Server to initialize the FB heap. Allocations will fail | ||
| 140 | * unless this is called. Offset is the beginning of the heap from the | ||
| 141 | * framebuffer offset (MaxXFBMem in XFree86). | ||
| 142 | * | ||
| 143 | * Memory layout according to Thomas Winischofer: | ||
| 144 | * |------------------|DDDDDDDDDDDDDDDDDDDDDDDDDDDDD|HHHH|CCCCCCCCCCC| | ||
| 145 | * | ||
| 146 | * X driver/sisfb HW- Command- | ||
| 147 | * framebuffer memory DRI heap Cursor queue | ||
| 148 | */ | ||
| 149 | static int sis_fb_init(DRM_IOCTL_ARGS) | 85 | static int sis_fb_init(DRM_IOCTL_ARGS) |
| 150 | { | 86 | { |
| 151 | DRM_DEVICE; | 87 | DRM_DEVICE; |
| 152 | drm_sis_private_t *dev_priv = dev->dev_private; | 88 | drm_sis_private_t *dev_priv = dev->dev_private; |
| 153 | drm_sis_fb_t fb; | 89 | drm_sis_fb_t fb; |
| 90 | int ret; | ||
| 154 | 91 | ||
| 155 | DRM_COPY_FROM_USER_IOCTL(fb, (drm_sis_fb_t __user *) data, sizeof(fb)); | 92 | DRM_COPY_FROM_USER_IOCTL(fb, (drm_sis_fb_t __user *) data, sizeof(fb)); |
| 156 | 93 | ||
| 157 | if (dev_priv == NULL) { | 94 | mutex_lock(&dev->struct_mutex); |
| 158 | dev->dev_private = drm_calloc(1, sizeof(drm_sis_private_t), | 95 | #if defined(CONFIG_FB_SIS) |
| 159 | DRM_MEM_DRIVER); | 96 | { |
| 160 | dev_priv = dev->dev_private; | 97 | drm_sman_mm_t sman_mm; |
| 161 | if (dev_priv == NULL) | 98 | sman_mm.private = (void *)0xFFFFFFFF; |
| 162 | return ENOMEM; | 99 | sman_mm.allocate = sis_sman_mm_allocate; |
| 100 | sman_mm.free = sis_sman_mm_free; | ||
| 101 | sman_mm.destroy = sis_sman_mm_destroy; | ||
| 102 | sman_mm.offset = sis_sman_mm_offset; | ||
| 103 | ret = | ||
| 104 | drm_sman_set_manager(&dev_priv->sman, VIDEO_TYPE, &sman_mm); | ||
| 163 | } | 105 | } |
| 106 | #else | ||
| 107 | ret = drm_sman_set_range(&dev_priv->sman, VIDEO_TYPE, 0, | ||
| 108 | fb.size >> SIS_MM_ALIGN_SHIFT); | ||
| 109 | #endif | ||
| 164 | 110 | ||
| 165 | if (dev_priv->FBHeap != NULL) | 111 | if (ret) { |
| 166 | return DRM_ERR(EINVAL); | 112 | DRM_ERROR("VRAM memory manager initialisation error\n"); |
| 113 | mutex_unlock(&dev->struct_mutex); | ||
| 114 | return ret; | ||
| 115 | } | ||
| 167 | 116 | ||
| 168 | dev_priv->FBHeap = mmInit(fb.offset, fb.size); | 117 | dev_priv->vram_initialized = 1; |
| 118 | dev_priv->vram_offset = fb.offset; | ||
| 169 | 119 | ||
| 120 | mutex_unlock(&dev->struct_mutex); | ||
| 170 | DRM_DEBUG("offset = %u, size = %u", fb.offset, fb.size); | 121 | DRM_DEBUG("offset = %u, size = %u", fb.offset, fb.size); |
| 171 | 122 | ||
| 172 | return 0; | 123 | return 0; |
| 173 | } | 124 | } |
| 174 | 125 | ||
| 175 | static int sis_fb_alloc(DRM_IOCTL_ARGS) | 126 | static int sis_drm_alloc(drm_device_t * dev, drm_file_t * priv, |
| 127 | unsigned long data, int pool) | ||
| 176 | { | 128 | { |
| 177 | DRM_DEVICE; | ||
| 178 | drm_sis_private_t *dev_priv = dev->dev_private; | 129 | drm_sis_private_t *dev_priv = dev->dev_private; |
| 179 | drm_sis_mem_t __user *argp = (drm_sis_mem_t __user *)data; | 130 | drm_sis_mem_t __user *argp = (drm_sis_mem_t __user *) data; |
| 180 | drm_sis_mem_t fb; | 131 | drm_sis_mem_t mem; |
| 181 | PMemBlock block; | ||
| 182 | int retval = 0; | 132 | int retval = 0; |
| 133 | drm_memblock_item_t *item; | ||
| 134 | |||
| 135 | DRM_COPY_FROM_USER_IOCTL(mem, argp, sizeof(mem)); | ||
| 183 | 136 | ||
| 184 | if (dev_priv == NULL || dev_priv->FBHeap == NULL) | 137 | mutex_lock(&dev->struct_mutex); |
| 138 | |||
| 139 | if (0 == ((pool == 0) ? dev_priv->vram_initialized : | ||
| 140 | dev_priv->agp_initialized)) { | ||
| 141 | DRM_ERROR | ||
| 142 | ("Attempt to allocate from uninitialized memory manager.\n"); | ||
| 185 | return DRM_ERR(EINVAL); | 143 | return DRM_ERR(EINVAL); |
| 144 | } | ||
| 186 | 145 | ||
| 187 | DRM_COPY_FROM_USER_IOCTL(fb, argp, sizeof(fb)); | 146 | mem.size = (mem.size + SIS_MM_ALIGN_MASK) >> SIS_MM_ALIGN_SHIFT; |
| 188 | 147 | item = drm_sman_alloc(&dev_priv->sman, pool, mem.size, 0, | |
| 189 | block = mmAllocMem(dev_priv->FBHeap, fb.size, 0, 0); | 148 | (unsigned long)priv); |
| 190 | if (block) { | 149 | |
| 191 | /* TODO */ | 150 | mutex_unlock(&dev->struct_mutex); |
| 192 | fb.offset = block->ofs; | 151 | if (item) { |
| 193 | fb.free = (unsigned long)block; | 152 | mem.offset = ((pool == 0) ? |
| 194 | if (!add_alloc_set(fb.context, VIDEO_TYPE, fb.free)) { | 153 | dev_priv->vram_offset : dev_priv->agp_offset) + |
| 195 | DRM_DEBUG("adding to allocation set fails\n"); | 154 | (item->mm-> |
| 196 | mmFreeMem((PMemBlock) fb.free); | 155 | offset(item->mm, item->mm_info) << SIS_MM_ALIGN_SHIFT); |
| 197 | retval = DRM_ERR(EINVAL); | 156 | mem.free = item->user_hash.key; |
| 198 | } | 157 | mem.size = mem.size << SIS_MM_ALIGN_SHIFT; |
| 199 | } else { | 158 | } else { |
| 200 | fb.offset = 0; | 159 | mem.offset = 0; |
| 201 | fb.size = 0; | 160 | mem.size = 0; |
| 202 | fb.free = 0; | 161 | mem.free = 0; |
| 162 | retval = DRM_ERR(ENOMEM); | ||
| 203 | } | 163 | } |
| 204 | 164 | ||
| 205 | DRM_COPY_TO_USER_IOCTL(argp, fb, sizeof(fb)); | 165 | DRM_COPY_TO_USER_IOCTL(argp, mem, sizeof(mem)); |
| 206 | 166 | ||
| 207 | DRM_DEBUG("alloc fb, size = %d, offset = %d\n", fb.size, fb.offset); | 167 | DRM_DEBUG("alloc %d, size = %d, offset = %d\n", pool, mem.size, |
| 168 | mem.offset); | ||
| 208 | 169 | ||
| 209 | return retval; | 170 | return retval; |
| 210 | } | 171 | } |
| 211 | 172 | ||
| 212 | static int sis_fb_free(DRM_IOCTL_ARGS) | 173 | static int sis_drm_free(DRM_IOCTL_ARGS) |
| 213 | { | 174 | { |
| 214 | DRM_DEVICE; | 175 | DRM_DEVICE; |
| 215 | drm_sis_private_t *dev_priv = dev->dev_private; | 176 | drm_sis_private_t *dev_priv = dev->dev_private; |
| 216 | drm_sis_mem_t fb; | 177 | drm_sis_mem_t mem; |
| 178 | int ret; | ||
| 217 | 179 | ||
| 218 | if (dev_priv == NULL || dev_priv->FBHeap == NULL) | 180 | DRM_COPY_FROM_USER_IOCTL(mem, (drm_sis_mem_t __user *) data, |
| 219 | return DRM_ERR(EINVAL); | 181 | sizeof(mem)); |
| 220 | 182 | ||
| 221 | DRM_COPY_FROM_USER_IOCTL(fb, (drm_sis_mem_t __user *) data, sizeof(fb)); | 183 | mutex_lock(&dev->struct_mutex); |
| 184 | ret = drm_sman_free_key(&dev_priv->sman, mem.free); | ||
| 185 | mutex_unlock(&dev->struct_mutex); | ||
| 186 | DRM_DEBUG("free = 0x%lx\n", mem.free); | ||
| 222 | 187 | ||
| 223 | if (!mmBlockInHeap(dev_priv->FBHeap, (PMemBlock) fb.free)) | 188 | return ret; |
| 224 | return DRM_ERR(EINVAL); | ||
| 225 | |||
| 226 | if (!del_alloc_set(fb.context, VIDEO_TYPE, fb.free)) | ||
| 227 | return DRM_ERR(EINVAL); | ||
| 228 | mmFreeMem((PMemBlock) fb.free); | ||
| 229 | |||
| 230 | DRM_DEBUG("free fb, free = 0x%lx\n", fb.free); | ||
| 231 | |||
| 232 | return 0; | ||
| 233 | } | 189 | } |
| 234 | 190 | ||
| 235 | #endif | 191 | static int sis_fb_alloc(DRM_IOCTL_ARGS) |
| 236 | 192 | { | |
| 237 | /* agp memory management */ | 193 | DRM_DEVICE; |
| 194 | return sis_drm_alloc(dev, priv, data, VIDEO_TYPE); | ||
| 195 | } | ||
| 238 | 196 | ||
| 239 | static int sis_ioctl_agp_init(DRM_IOCTL_ARGS) | 197 | static int sis_ioctl_agp_init(DRM_IOCTL_ARGS) |
| 240 | { | 198 | { |
| 241 | DRM_DEVICE; | 199 | DRM_DEVICE; |
| 242 | drm_sis_private_t *dev_priv = dev->dev_private; | 200 | drm_sis_private_t *dev_priv = dev->dev_private; |
| 243 | drm_sis_agp_t agp; | 201 | drm_sis_agp_t agp; |
| 244 | 202 | int ret; | |
| 245 | if (dev_priv == NULL) { | 203 | dev_priv = dev->dev_private; |
| 246 | dev->dev_private = drm_calloc(1, sizeof(drm_sis_private_t), | ||
| 247 | DRM_MEM_DRIVER); | ||
| 248 | dev_priv = dev->dev_private; | ||
| 249 | if (dev_priv == NULL) | ||
| 250 | return ENOMEM; | ||
| 251 | } | ||
| 252 | |||
| 253 | if (dev_priv->AGPHeap != NULL) | ||
| 254 | return DRM_ERR(EINVAL); | ||
| 255 | 204 | ||
| 256 | DRM_COPY_FROM_USER_IOCTL(agp, (drm_sis_agp_t __user *) data, | 205 | DRM_COPY_FROM_USER_IOCTL(agp, (drm_sis_agp_t __user *) data, |
| 257 | sizeof(agp)); | 206 | sizeof(agp)); |
| 207 | mutex_lock(&dev->struct_mutex); | ||
| 208 | ret = drm_sman_set_range(&dev_priv->sman, AGP_TYPE, 0, | ||
| 209 | agp.size >> SIS_MM_ALIGN_SHIFT); | ||
| 210 | |||
| 211 | if (ret) { | ||
| 212 | DRM_ERROR("AGP memory manager initialisation error\n"); | ||
| 213 | mutex_unlock(&dev->struct_mutex); | ||
| 214 | return ret; | ||
| 215 | } | ||
| 258 | 216 | ||
| 259 | dev_priv->AGPHeap = mmInit(agp.offset, agp.size); | 217 | dev_priv->agp_initialized = 1; |
| 218 | dev_priv->agp_offset = agp.offset; | ||
| 219 | mutex_unlock(&dev->struct_mutex); | ||
| 260 | 220 | ||
| 261 | DRM_DEBUG("offset = %u, size = %u", agp.offset, agp.size); | 221 | DRM_DEBUG("offset = %u, size = %u", agp.offset, agp.size); |
| 262 | |||
| 263 | return 0; | 222 | return 0; |
| 264 | } | 223 | } |
| 265 | 224 | ||
| 266 | static int sis_ioctl_agp_alloc(DRM_IOCTL_ARGS) | 225 | static int sis_ioctl_agp_alloc(DRM_IOCTL_ARGS) |
| 267 | { | 226 | { |
| 268 | DRM_DEVICE; | 227 | DRM_DEVICE; |
| 269 | drm_sis_private_t *dev_priv = dev->dev_private; | ||
| 270 | drm_sis_mem_t __user *argp = (drm_sis_mem_t __user *)data; | ||
| 271 | drm_sis_mem_t agp; | ||
| 272 | PMemBlock block; | ||
| 273 | int retval = 0; | ||
| 274 | 228 | ||
| 275 | if (dev_priv == NULL || dev_priv->AGPHeap == NULL) | 229 | return sis_drm_alloc(dev, priv, data, AGP_TYPE); |
| 276 | return DRM_ERR(EINVAL); | 230 | } |
| 277 | 231 | ||
| 278 | DRM_COPY_FROM_USER_IOCTL(agp, argp, sizeof(agp)); | 232 | static drm_local_map_t *sis_reg_init(drm_device_t *dev) |
| 279 | 233 | { | |
| 280 | block = mmAllocMem(dev_priv->AGPHeap, agp.size, 0, 0); | 234 | drm_map_list_t *entry; |
| 281 | if (block) { | 235 | drm_local_map_t *map; |
| 282 | /* TODO */ | 236 | |
| 283 | agp.offset = block->ofs; | 237 | list_for_each_entry(entry, &dev->maplist->head, head) { |
| 284 | agp.free = (unsigned long)block; | 238 | map = entry->map; |
| 285 | if (!add_alloc_set(agp.context, AGP_TYPE, agp.free)) { | 239 | if (!map) |
| 286 | DRM_DEBUG("adding to allocation set fails\n"); | 240 | continue; |
| 287 | mmFreeMem((PMemBlock) agp.free); | 241 | if (map->type == _DRM_REGISTERS) { |
| 288 | retval = -1; | 242 | return map; |
| 289 | } | 243 | } |
| 290 | } else { | ||
| 291 | agp.offset = 0; | ||
| 292 | agp.size = 0; | ||
| 293 | agp.free = 0; | ||
| 294 | } | 244 | } |
| 295 | 245 | return NULL; | |
| 296 | DRM_COPY_TO_USER_IOCTL(argp, agp, sizeof(agp)); | ||
| 297 | |||
| 298 | DRM_DEBUG("alloc agp, size = %d, offset = %d\n", agp.size, agp.offset); | ||
| 299 | |||
| 300 | return retval; | ||
| 301 | } | 246 | } |
| 302 | 247 | ||
| 303 | static int sis_ioctl_agp_free(DRM_IOCTL_ARGS) | 248 | int sis_idle(drm_device_t *dev) |
| 304 | { | 249 | { |
| 305 | DRM_DEVICE; | ||
| 306 | drm_sis_private_t *dev_priv = dev->dev_private; | 250 | drm_sis_private_t *dev_priv = dev->dev_private; |
| 307 | drm_sis_mem_t agp; | 251 | uint32_t idle_reg; |
| 308 | 252 | unsigned long end; | |
| 309 | if (dev_priv == NULL || dev_priv->AGPHeap == NULL) | 253 | int i; |
| 310 | return DRM_ERR(EINVAL); | ||
| 311 | 254 | ||
| 312 | DRM_COPY_FROM_USER_IOCTL(agp, (drm_sis_mem_t __user *) data, | 255 | if (dev_priv->idle_fault) |
| 313 | sizeof(agp)); | 256 | return 0; |
| 314 | 257 | ||
| 315 | if (!mmBlockInHeap(dev_priv->AGPHeap, (PMemBlock) agp.free)) | 258 | if (dev_priv->mmio == NULL) { |
| 316 | return DRM_ERR(EINVAL); | 259 | dev_priv->mmio = sis_reg_init(dev); |
| 260 | if (dev_priv->mmio == NULL) { | ||
| 261 | DRM_ERROR("Could not find register map.\n"); | ||
| 262 | return 0; | ||
| 263 | } | ||
| 264 | } | ||
| 265 | |||
| 266 | /* | ||
| 267 | * Implement a device switch here if needed | ||
| 268 | */ | ||
| 269 | |||
| 270 | if (dev_priv->chipset != SIS_CHIP_315) | ||
| 271 | return 0; | ||
| 272 | |||
| 273 | /* | ||
| 274 | * Timeout after 3 seconds. We cannot use DRM_WAIT_ON here | ||
| 275 | * because its polling frequency is too low. | ||
| 276 | */ | ||
| 277 | |||
| 278 | end = jiffies + (DRM_HZ * 3); | ||
| 279 | |||
| 280 | for (i=0; i<4; ++i) { | ||
| 281 | do { | ||
| 282 | idle_reg = SIS_READ(0x85cc); | ||
| 283 | } while ( !time_after_eq(jiffies, end) && | ||
| 284 | ((idle_reg & 0x80000000) != 0x80000000)); | ||
| 285 | } | ||
| 317 | 286 | ||
| 318 | mmFreeMem((PMemBlock) agp.free); | 287 | if (time_after_eq(jiffies, end)) { |
| 319 | if (!del_alloc_set(agp.context, AGP_TYPE, agp.free)) | 288 | DRM_ERROR("Graphics engine idle timeout. " |
| 320 | return DRM_ERR(EINVAL); | 289 | "Disabling idle check\n"); |
| 290 | dev_priv->idle_fault = 1; | ||
| 291 | } | ||
| 321 | 292 | ||
| 322 | DRM_DEBUG("free agp, free = 0x%lx\n", agp.free); | 293 | /* |
| 294 | * The caller never sees an error code. It gets trapped | ||
| 295 | * in libdrm. | ||
| 296 | */ | ||
| 323 | 297 | ||
| 324 | return 0; | 298 | return 0; |
| 325 | } | 299 | } |
| 326 | 300 | ||
| 327 | int sis_init_context(struct drm_device *dev, int context) | ||
| 328 | { | ||
| 329 | int i; | ||
| 330 | 301 | ||
| 331 | for (i = 0; i < MAX_CONTEXT; i++) { | 302 | void sis_lastclose(struct drm_device *dev) |
| 332 | if (global_ppriv[i].used && | 303 | { |
| 333 | (global_ppriv[i].context == context)) | 304 | drm_sis_private_t *dev_priv = dev->dev_private; |
| 334 | break; | ||
| 335 | } | ||
| 336 | 305 | ||
| 337 | if (i >= MAX_CONTEXT) { | 306 | if (!dev_priv) |
| 338 | for (i = 0; i < MAX_CONTEXT; i++) { | 307 | return; |
| 339 | if (!global_ppriv[i].used) { | ||
| 340 | global_ppriv[i].context = context; | ||
| 341 | global_ppriv[i].used = 1; | ||
| 342 | global_ppriv[i].sets[0] = setInit(); | ||
| 343 | global_ppriv[i].sets[1] = setInit(); | ||
| 344 | DRM_DEBUG("init allocation set, socket=%d, " | ||
| 345 | "context = %d\n", i, context); | ||
| 346 | break; | ||
| 347 | } | ||
| 348 | } | ||
| 349 | if ((i >= MAX_CONTEXT) || (global_ppriv[i].sets[0] == NULL) || | ||
| 350 | (global_ppriv[i].sets[1] == NULL)) { | ||
| 351 | return 0; | ||
| 352 | } | ||
| 353 | } | ||
| 354 | 308 | ||
| 355 | return 1; | 309 | mutex_lock(&dev->struct_mutex); |
| 310 | drm_sman_cleanup(&dev_priv->sman); | ||
| 311 | dev_priv->vram_initialized = 0; | ||
| 312 | dev_priv->agp_initialized = 0; | ||
| 313 | dev_priv->mmio = NULL; | ||
| 314 | mutex_unlock(&dev->struct_mutex); | ||
| 356 | } | 315 | } |
| 357 | 316 | ||
| 358 | int sis_final_context(struct drm_device *dev, int context) | 317 | void sis_reclaim_buffers_locked(drm_device_t * dev, struct file *filp) |
| 359 | { | 318 | { |
| 360 | int i; | 319 | drm_sis_private_t *dev_priv = dev->dev_private; |
| 320 | drm_file_t *priv = filp->private_data; | ||
| 361 | 321 | ||
| 362 | for (i = 0; i < MAX_CONTEXT; i++) { | 322 | mutex_lock(&dev->struct_mutex); |
| 363 | if (global_ppriv[i].used && | 323 | if (drm_sman_owner_clean(&dev_priv->sman, (unsigned long)priv)) { |
| 364 | (global_ppriv[i].context == context)) | 324 | mutex_unlock(&dev->struct_mutex); |
| 365 | break; | 325 | return; |
| 366 | } | 326 | } |
| 367 | 327 | ||
| 368 | if (i < MAX_CONTEXT) { | 328 | if (dev->driver->dma_quiescent) { |
| 369 | set_t *set; | 329 | dev->driver->dma_quiescent(dev); |
| 370 | ITEM_TYPE item; | ||
| 371 | int retval; | ||
| 372 | |||
| 373 | DRM_DEBUG("find socket %d, context = %d\n", i, context); | ||
| 374 | |||
| 375 | /* Video Memory */ | ||
| 376 | set = global_ppriv[i].sets[0]; | ||
| 377 | retval = setFirst(set, &item); | ||
| 378 | while (retval) { | ||
| 379 | DRM_DEBUG("free video memory 0x%lx\n", item); | ||
| 380 | #if defined(__linux__) && defined(CONFIG_FB_SIS) | ||
| 381 | sis_free(item); | ||
| 382 | #else | ||
| 383 | mmFreeMem((PMemBlock) item); | ||
| 384 | #endif | ||
| 385 | retval = setNext(set, &item); | ||
| 386 | } | ||
| 387 | setDestroy(set); | ||
| 388 | |||
| 389 | /* AGP Memory */ | ||
| 390 | set = global_ppriv[i].sets[1]; | ||
| 391 | retval = setFirst(set, &item); | ||
| 392 | while (retval) { | ||
| 393 | DRM_DEBUG("free agp memory 0x%lx\n", item); | ||
| 394 | mmFreeMem((PMemBlock) item); | ||
| 395 | retval = setNext(set, &item); | ||
| 396 | } | ||
| 397 | setDestroy(set); | ||
| 398 | |||
| 399 | global_ppriv[i].used = 0; | ||
| 400 | } | 330 | } |
| 401 | 331 | ||
| 402 | return 1; | 332 | drm_sman_owner_cleanup(&dev_priv->sman, (unsigned long)priv); |
| 333 | mutex_unlock(&dev->struct_mutex); | ||
| 334 | return; | ||
| 403 | } | 335 | } |
| 404 | 336 | ||
| 405 | drm_ioctl_desc_t sis_ioctls[] = { | 337 | drm_ioctl_desc_t sis_ioctls[] = { |
| 406 | [DRM_IOCTL_NR(DRM_SIS_FB_ALLOC)] = {sis_fb_alloc, DRM_AUTH}, | 338 | [DRM_IOCTL_NR(DRM_SIS_FB_ALLOC)] = {sis_fb_alloc, DRM_AUTH}, |
| 407 | [DRM_IOCTL_NR(DRM_SIS_FB_FREE)] = {sis_fb_free, DRM_AUTH}, | 339 | [DRM_IOCTL_NR(DRM_SIS_FB_FREE)] = {sis_drm_free, DRM_AUTH}, |
| 408 | [DRM_IOCTL_NR(DRM_SIS_AGP_INIT)] = {sis_ioctl_agp_init, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY}, | 340 | [DRM_IOCTL_NR(DRM_SIS_AGP_INIT)] = |
| 341 | {sis_ioctl_agp_init, DRM_AUTH | DRM_MASTER | DRM_ROOT_ONLY}, | ||
| 409 | [DRM_IOCTL_NR(DRM_SIS_AGP_ALLOC)] = {sis_ioctl_agp_alloc, DRM_AUTH}, | 342 | [DRM_IOCTL_NR(DRM_SIS_AGP_ALLOC)] = {sis_ioctl_agp_alloc, DRM_AUTH}, |
| 410 | [DRM_IOCTL_NR(DRM_SIS_AGP_FREE)] = {sis_ioctl_agp_free, DRM_AUTH}, | 343 | [DRM_IOCTL_NR(DRM_SIS_AGP_FREE)] = {sis_drm_free, DRM_AUTH}, |
| 411 | [DRM_IOCTL_NR(DRM_SIS_FB_INIT)] = {sis_fb_init, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY} | 344 | [DRM_IOCTL_NR(DRM_SIS_FB_INIT)] = |
| 345 | {sis_fb_init, DRM_AUTH | DRM_MASTER | DRM_ROOT_ONLY} | ||
| 412 | }; | 346 | }; |
| 413 | 347 | ||
| 414 | int sis_max_ioctl = DRM_ARRAY_SIZE(sis_ioctls); | 348 | int sis_max_ioctl = DRM_ARRAY_SIZE(sis_ioctls); |
diff --git a/drivers/char/drm/via_dmablit.c b/drivers/char/drm/via_dmablit.c index 78a81a4a99c5..60c1695db300 100644 --- a/drivers/char/drm/via_dmablit.c +++ b/drivers/char/drm/via_dmablit.c | |||
| @@ -41,9 +41,9 @@ | |||
| 41 | 41 | ||
| 42 | #include <linux/pagemap.h> | 42 | #include <linux/pagemap.h> |
| 43 | 43 | ||
| 44 | #define VIA_PGDN(x) (((unsigned long)(x)) & PAGE_MASK) | 44 | #define VIA_PGDN(x) (((unsigned long)(x)) & PAGE_MASK) |
| 45 | #define VIA_PGOFF(x) (((unsigned long)(x)) & ~PAGE_MASK) | 45 | #define VIA_PGOFF(x) (((unsigned long)(x)) & ~PAGE_MASK) |
| 46 | #define VIA_PFN(x) ((unsigned long)(x) >> PAGE_SHIFT) | 46 | #define VIA_PFN(x) ((unsigned long)(x) >> PAGE_SHIFT) |
| 47 | 47 | ||
| 48 | typedef struct _drm_via_descriptor { | 48 | typedef struct _drm_via_descriptor { |
| 49 | uint32_t mem_addr; | 49 | uint32_t mem_addr; |
| @@ -121,19 +121,19 @@ via_map_blit_for_device(struct pci_dev *pdev, | |||
| 121 | 121 | ||
| 122 | while (line_len > 0) { | 122 | while (line_len > 0) { |
| 123 | 123 | ||
| 124 | remaining_len = min(PAGE_SIZE-VIA_PGOFF(cur_mem), line_len); | 124 | remaining_len = min(PAGE_SIZE-VIA_PGOFF(cur_mem), line_len); |
| 125 | line_len -= remaining_len; | 125 | line_len -= remaining_len; |
| 126 | 126 | ||
| 127 | if (mode == 1) { | 127 | if (mode == 1) { |
| 128 | desc_ptr->mem_addr = | 128 | desc_ptr->mem_addr = |
| 129 | dma_map_page(&pdev->dev, | 129 | dma_map_page(&pdev->dev, |
| 130 | vsg->pages[VIA_PFN(cur_mem) - | 130 | vsg->pages[VIA_PFN(cur_mem) - |
| 131 | VIA_PFN(first_addr)], | 131 | VIA_PFN(first_addr)], |
| 132 | VIA_PGOFF(cur_mem), remaining_len, | 132 | VIA_PGOFF(cur_mem), remaining_len, |
| 133 | vsg->direction); | 133 | vsg->direction); |
| 134 | desc_ptr->dev_addr = cur_fb; | 134 | desc_ptr->dev_addr = cur_fb; |
| 135 | 135 | ||
| 136 | desc_ptr->size = remaining_len; | 136 | desc_ptr->size = remaining_len; |
| 137 | desc_ptr->next = (uint32_t) next; | 137 | desc_ptr->next = (uint32_t) next; |
| 138 | next = dma_map_single(&pdev->dev, desc_ptr, sizeof(*desc_ptr), | 138 | next = dma_map_single(&pdev->dev, desc_ptr, sizeof(*desc_ptr), |
| 139 | DMA_TO_DEVICE); | 139 | DMA_TO_DEVICE); |
| @@ -162,7 +162,7 @@ via_map_blit_for_device(struct pci_dev *pdev, | |||
| 162 | 162 | ||
| 163 | /* | 163 | /* |
| 164 | * Function that frees up all resources for a blit. It is usable even if the | 164 | * Function that frees up all resources for a blit. It is usable even if the |
| 165 | * blit info has only be partially built as long as the status enum is consistent | 165 | * blit info has only been partially built as long as the status enum is consistent |
| 166 | * with the actual status of the used resources. | 166 | * with the actual status of the used resources. |
| 167 | */ | 167 | */ |
| 168 | 168 | ||
| @@ -238,8 +238,11 @@ via_lock_all_dma_pages(drm_via_sg_info_t *vsg, drm_via_dmablit_t *xfer) | |||
| 238 | return DRM_ERR(ENOMEM); | 238 | return DRM_ERR(ENOMEM); |
| 239 | memset(vsg->pages, 0, sizeof(struct page *) * vsg->num_pages); | 239 | memset(vsg->pages, 0, sizeof(struct page *) * vsg->num_pages); |
| 240 | down_read(¤t->mm->mmap_sem); | 240 | down_read(¤t->mm->mmap_sem); |
| 241 | ret = get_user_pages(current, current->mm, (unsigned long) xfer->mem_addr, | 241 | ret = get_user_pages(current, current->mm, |
| 242 | vsg->num_pages, vsg->direction, 0, vsg->pages, NULL); | 242 | (unsigned long)xfer->mem_addr, |
| 243 | vsg->num_pages, | ||
| 244 | (vsg->direction == DMA_FROM_DEVICE), | ||
| 245 | 0, vsg->pages, NULL); | ||
| 243 | 246 | ||
| 244 | up_read(¤t->mm->mmap_sem); | 247 | up_read(¤t->mm->mmap_sem); |
| 245 | if (ret != vsg->num_pages) { | 248 | if (ret != vsg->num_pages) { |
| @@ -475,9 +478,15 @@ via_dmablit_timer(unsigned long data) | |||
| 475 | if (!timer_pending(&blitq->poll_timer)) { | 478 | if (!timer_pending(&blitq->poll_timer)) { |
| 476 | blitq->poll_timer.expires = jiffies+1; | 479 | blitq->poll_timer.expires = jiffies+1; |
| 477 | add_timer(&blitq->poll_timer); | 480 | add_timer(&blitq->poll_timer); |
| 478 | } | ||
| 479 | via_dmablit_handler(dev, engine, 0); | ||
| 480 | 481 | ||
| 482 | /* | ||
| 483 | * Rerun handler to delete timer if engines are off, and | ||
| 484 | * to shorten abort latency. This is a little nasty. | ||
| 485 | */ | ||
| 486 | |||
| 487 | via_dmablit_handler(dev, engine, 0); | ||
| 488 | |||
| 489 | } | ||
| 481 | } | 490 | } |
| 482 | 491 | ||
| 483 | 492 | ||
| @@ -597,15 +606,27 @@ via_build_sg_info(drm_device_t *dev, drm_via_sg_info_t *vsg, drm_via_dmablit_t * | |||
| 597 | * (Not a big limitation anyway.) | 606 | * (Not a big limitation anyway.) |
| 598 | */ | 607 | */ |
| 599 | 608 | ||
| 600 | if (((xfer->mem_stride - xfer->line_length) >= PAGE_SIZE) || | 609 | if ((xfer->mem_stride - xfer->line_length) >= PAGE_SIZE) { |
| 601 | (xfer->mem_stride > 2048*4)) { | ||
| 602 | DRM_ERROR("Too large system memory stride. Stride: %d, " | 610 | DRM_ERROR("Too large system memory stride. Stride: %d, " |
| 603 | "Length: %d\n", xfer->mem_stride, xfer->line_length); | 611 | "Length: %d\n", xfer->mem_stride, xfer->line_length); |
| 604 | return DRM_ERR(EINVAL); | 612 | return DRM_ERR(EINVAL); |
| 605 | } | 613 | } |
| 606 | 614 | ||
| 607 | if (xfer->num_lines > 2048) { | 615 | if ((xfer->mem_stride == xfer->line_length) && |
| 608 | DRM_ERROR("Too many PCI DMA bitblt lines.\n"); | 616 | (xfer->fb_stride == xfer->line_length)) { |
| 617 | xfer->mem_stride *= xfer->num_lines; | ||
| 618 | xfer->line_length = xfer->mem_stride; | ||
| 619 | xfer->fb_stride = xfer->mem_stride; | ||
| 620 | xfer->num_lines = 1; | ||
| 621 | } | ||
| 622 | |||
| 623 | /* | ||
| 624 | * Don't lock an arbitrary large number of pages, since that causes a | ||
| 625 | * DOS security hole. | ||
| 626 | */ | ||
| 627 | |||
| 628 | if (xfer->num_lines > 2048 || (xfer->num_lines*xfer->mem_stride > (2048*2048*4))) { | ||
| 629 | DRM_ERROR("Too large PCI DMA bitblt.\n"); | ||
| 609 | return DRM_ERR(EINVAL); | 630 | return DRM_ERR(EINVAL); |
| 610 | } | 631 | } |
| 611 | 632 | ||
| @@ -628,16 +649,17 @@ via_build_sg_info(drm_device_t *dev, drm_via_sg_info_t *vsg, drm_via_dmablit_t * | |||
| 628 | 649 | ||
| 629 | #ifdef VIA_BUGFREE | 650 | #ifdef VIA_BUGFREE |
| 630 | if ((((unsigned long)xfer->mem_addr & 3) != ((unsigned long)xfer->fb_addr & 3)) || | 651 | if ((((unsigned long)xfer->mem_addr & 3) != ((unsigned long)xfer->fb_addr & 3)) || |
| 631 | ((xfer->mem_stride & 3) != (xfer->fb_stride & 3))) { | 652 | ((xfer->num_lines > 1) && ((xfer->mem_stride & 3) != (xfer->fb_stride & 3)))) { |
| 632 | DRM_ERROR("Invalid DRM bitblt alignment.\n"); | 653 | DRM_ERROR("Invalid DRM bitblt alignment.\n"); |
| 633 | return DRM_ERR(EINVAL); | 654 | return DRM_ERR(EINVAL); |
| 634 | } | 655 | } |
| 635 | #else | 656 | #else |
| 636 | if ((((unsigned long)xfer->mem_addr & 15) || | 657 | if ((((unsigned long)xfer->mem_addr & 15) || |
| 637 | ((unsigned long)xfer->fb_addr & 3)) || (xfer->mem_stride & 15) || | 658 | ((unsigned long)xfer->fb_addr & 3)) || |
| 638 | (xfer->fb_stride & 3)) { | 659 | ((xfer->num_lines > 1) && |
| 660 | ((xfer->mem_stride & 15) || (xfer->fb_stride & 3)))) { | ||
| 639 | DRM_ERROR("Invalid DRM bitblt alignment.\n"); | 661 | DRM_ERROR("Invalid DRM bitblt alignment.\n"); |
| 640 | return DRM_ERR(EINVAL); | 662 | return DRM_ERR(EINVAL); |
| 641 | } | 663 | } |
| 642 | #endif | 664 | #endif |
| 643 | 665 | ||
| @@ -715,7 +737,7 @@ via_dmablit(drm_device_t *dev, drm_via_dmablit_t *xfer) | |||
| 715 | drm_via_private_t *dev_priv = (drm_via_private_t *)dev->dev_private; | 737 | drm_via_private_t *dev_priv = (drm_via_private_t *)dev->dev_private; |
| 716 | drm_via_sg_info_t *vsg; | 738 | drm_via_sg_info_t *vsg; |
| 717 | drm_via_blitq_t *blitq; | 739 | drm_via_blitq_t *blitq; |
| 718 | int ret; | 740 | int ret; |
| 719 | int engine; | 741 | int engine; |
| 720 | unsigned long irqsave; | 742 | unsigned long irqsave; |
| 721 | 743 | ||
| @@ -756,7 +778,7 @@ via_dmablit(drm_device_t *dev, drm_via_dmablit_t *xfer) | |||
| 756 | 778 | ||
| 757 | /* | 779 | /* |
| 758 | * Sync on a previously submitted blit. Note that the X server use signals extensively, and | 780 | * Sync on a previously submitted blit. Note that the X server use signals extensively, and |
| 759 | * that there is a very big proability that this IOCTL will be interrupted by a signal. In that | 781 | * that there is a very big probability that this IOCTL will be interrupted by a signal. In that |
| 760 | * case it returns with -EAGAIN for the signal to be delivered. | 782 | * case it returns with -EAGAIN for the signal to be delivered. |
| 761 | * The caller should then reissue the IOCTL. This is similar to what is being done for drmGetLock(). | 783 | * The caller should then reissue the IOCTL. This is similar to what is being done for drmGetLock(). |
| 762 | */ | 784 | */ |
diff --git a/drivers/char/drm/via_drm.h b/drivers/char/drm/via_drm.h index 47f0b5b26379..e4ee97d7156f 100644 --- a/drivers/char/drm/via_drm.h +++ b/drivers/char/drm/via_drm.h | |||
| @@ -250,6 +250,12 @@ typedef struct drm_via_blitsync { | |||
| 250 | unsigned engine; | 250 | unsigned engine; |
| 251 | } drm_via_blitsync_t; | 251 | } drm_via_blitsync_t; |
| 252 | 252 | ||
| 253 | /* - * Below,"flags" is currently unused but will be used for possible future | ||
| 254 | * extensions like kernel space bounce buffers for bad alignments and | ||
| 255 | * blit engine busy-wait polling for better latency in the absence of | ||
| 256 | * interrupts. | ||
| 257 | */ | ||
| 258 | |||
| 253 | typedef struct drm_via_dmablit { | 259 | typedef struct drm_via_dmablit { |
| 254 | uint32_t num_lines; | 260 | uint32_t num_lines; |
| 255 | uint32_t line_length; | 261 | uint32_t line_length; |
| @@ -260,7 +266,7 @@ typedef struct drm_via_dmablit { | |||
| 260 | unsigned char *mem_addr; | 266 | unsigned char *mem_addr; |
| 261 | uint32_t mem_stride; | 267 | uint32_t mem_stride; |
| 262 | 268 | ||
| 263 | int bounce_buffer; | 269 | uint32_t flags; |
| 264 | int to_fb; | 270 | int to_fb; |
| 265 | 271 | ||
| 266 | drm_via_blitsync_t sync; | 272 | drm_via_blitsync_t sync; |
diff --git a/drivers/char/drm/via_drv.c b/drivers/char/drm/via_drv.c index b3d364d793d7..bb9dde8b1911 100644 --- a/drivers/char/drm/via_drv.c +++ b/drivers/char/drm/via_drv.c | |||
| @@ -43,7 +43,6 @@ static struct drm_driver driver = { | |||
| 43 | DRIVER_IRQ_SHARED | DRIVER_IRQ_VBL, | 43 | DRIVER_IRQ_SHARED | DRIVER_IRQ_VBL, |
| 44 | .load = via_driver_load, | 44 | .load = via_driver_load, |
| 45 | .unload = via_driver_unload, | 45 | .unload = via_driver_unload, |
| 46 | .context_ctor = via_init_context, | ||
| 47 | .context_dtor = via_final_context, | 46 | .context_dtor = via_final_context, |
| 48 | .vblank_wait = via_driver_vblank_wait, | 47 | .vblank_wait = via_driver_vblank_wait, |
| 49 | .irq_preinstall = via_driver_irq_preinstall, | 48 | .irq_preinstall = via_driver_irq_preinstall, |
| @@ -53,6 +52,8 @@ static struct drm_driver driver = { | |||
| 53 | .dma_quiescent = via_driver_dma_quiescent, | 52 | .dma_quiescent = via_driver_dma_quiescent, |
| 54 | .dri_library_name = dri_library_name, | 53 | .dri_library_name = dri_library_name, |
| 55 | .reclaim_buffers = drm_core_reclaim_buffers, | 54 | .reclaim_buffers = drm_core_reclaim_buffers, |
| 55 | .reclaim_buffers_locked = via_reclaim_buffers_locked, | ||
| 56 | .lastclose = via_lastclose, | ||
| 56 | .get_map_ofs = drm_core_get_map_ofs, | 57 | .get_map_ofs = drm_core_get_map_ofs, |
| 57 | .get_reg_ofs = drm_core_get_reg_ofs, | 58 | .get_reg_ofs = drm_core_get_reg_ofs, |
| 58 | .ioctls = via_ioctls, | 59 | .ioctls = via_ioctls, |
diff --git a/drivers/char/drm/via_drv.h b/drivers/char/drm/via_drv.h index 52bcc7b1ba45..d21b5b75da0f 100644 --- a/drivers/char/drm/via_drv.h +++ b/drivers/char/drm/via_drv.h | |||
| @@ -24,15 +24,16 @@ | |||
| 24 | #ifndef _VIA_DRV_H_ | 24 | #ifndef _VIA_DRV_H_ |
| 25 | #define _VIA_DRV_H_ | 25 | #define _VIA_DRV_H_ |
| 26 | 26 | ||
| 27 | #include "drm_sman.h" | ||
| 27 | #define DRIVER_AUTHOR "Various" | 28 | #define DRIVER_AUTHOR "Various" |
| 28 | 29 | ||
| 29 | #define DRIVER_NAME "via" | 30 | #define DRIVER_NAME "via" |
| 30 | #define DRIVER_DESC "VIA Unichrome / Pro" | 31 | #define DRIVER_DESC "VIA Unichrome / Pro" |
| 31 | #define DRIVER_DATE "20051116" | 32 | #define DRIVER_DATE "20060529" |
| 32 | 33 | ||
| 33 | #define DRIVER_MAJOR 2 | 34 | #define DRIVER_MAJOR 2 |
| 34 | #define DRIVER_MINOR 7 | 35 | #define DRIVER_MINOR 10 |
| 35 | #define DRIVER_PATCHLEVEL 4 | 36 | #define DRIVER_PATCHLEVEL 0 |
| 36 | 37 | ||
| 37 | #include "via_verifier.h" | 38 | #include "via_verifier.h" |
| 38 | 39 | ||
| @@ -85,6 +86,12 @@ typedef struct drm_via_private { | |||
| 85 | uint32_t irq_enable_mask; | 86 | uint32_t irq_enable_mask; |
| 86 | uint32_t irq_pending_mask; | 87 | uint32_t irq_pending_mask; |
| 87 | int *irq_map; | 88 | int *irq_map; |
| 89 | unsigned int idle_fault; | ||
| 90 | drm_sman_t sman; | ||
| 91 | int vram_initialized; | ||
| 92 | int agp_initialized; | ||
| 93 | unsigned long vram_offset; | ||
| 94 | unsigned long agp_offset; | ||
| 88 | drm_via_blitq_t blit_queues[VIA_NUM_BLIT_ENGINES]; | 95 | drm_via_blitq_t blit_queues[VIA_NUM_BLIT_ENGINES]; |
| 89 | } drm_via_private_t; | 96 | } drm_via_private_t; |
| 90 | 97 | ||
| @@ -135,6 +142,9 @@ extern void via_init_futex(drm_via_private_t * dev_priv); | |||
| 135 | extern void via_cleanup_futex(drm_via_private_t * dev_priv); | 142 | extern void via_cleanup_futex(drm_via_private_t * dev_priv); |
| 136 | extern void via_release_futex(drm_via_private_t * dev_priv, int context); | 143 | extern void via_release_futex(drm_via_private_t * dev_priv, int context); |
| 137 | 144 | ||
| 145 | extern void via_reclaim_buffers_locked(drm_device_t *dev, struct file *filp); | ||
| 146 | extern void via_lastclose(drm_device_t *dev); | ||
| 147 | |||
| 138 | extern void via_dmablit_handler(drm_device_t *dev, int engine, int from_irq); | 148 | extern void via_dmablit_handler(drm_device_t *dev, int engine, int from_irq); |
| 139 | extern void via_init_dmablit(drm_device_t *dev); | 149 | extern void via_init_dmablit(drm_device_t *dev); |
| 140 | 150 | ||
diff --git a/drivers/char/drm/via_ds.c b/drivers/char/drm/via_ds.c deleted file mode 100644 index 9429736b3b96..000000000000 --- a/drivers/char/drm/via_ds.c +++ /dev/null | |||
| @@ -1,273 +0,0 @@ | |||
| 1 | /* | ||
| 2 | * Copyright 1998-2003 VIA Technologies, Inc. All Rights Reserved. | ||
| 3 | * Copyright 2001-2003 S3 Graphics, Inc. All Rights Reserved. | ||
| 4 | * Copyright 2000 Silicon Integrated Systems Corp, Inc., HsinChu, Taiwan. | ||
| 5 | * | ||
| 6 | * Permission is hereby granted, free of charge, to any person obtaining a | ||
| 7 | * copy of this software and associated documentation files (the "Software"), | ||
| 8 | * to deal in the Software without restriction, including without limitation | ||
| 9 | * the rights to use, copy, modify, merge, publish, distribute, sub license, | ||
| 10 | * and/or sell copies of the Software, and to permit persons to whom the | ||
| 11 | * Software is furnished to do so, subject to the following conditions: | ||
| 12 | * | ||
| 13 | * The above copyright notice and this permission notice (including the | ||
| 14 | * next paragraph) shall be included in all copies or substantial portions | ||
| 15 | * of the Software. | ||
| 16 | * | ||
| 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
| 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
| 19 | * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL | ||
| 20 | * VIA, S3 GRAPHICS, AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR | ||
| 21 | * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, | ||
| 22 | * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER | ||
| 23 | * DEALINGS IN THE SOFTWARE. | ||
| 24 | */ | ||
| 25 | #include "drmP.h" | ||
| 26 | |||
| 27 | #include "via_ds.h" | ||
| 28 | extern unsigned int VIA_DEBUG; | ||
| 29 | |||
| 30 | set_t *via_setInit(void) | ||
| 31 | { | ||
| 32 | int i; | ||
| 33 | set_t *set; | ||
| 34 | set = (set_t *) drm_alloc(sizeof(set_t), DRM_MEM_DRIVER); | ||
| 35 | for (i = 0; i < SET_SIZE; i++) { | ||
| 36 | set->list[i].free_next = i + 1; | ||
| 37 | set->list[i].alloc_next = -1; | ||
| 38 | } | ||
| 39 | set->list[SET_SIZE - 1].free_next = -1; | ||
| 40 | set->free = 0; | ||
| 41 | set->alloc = -1; | ||
| 42 | set->trace = -1; | ||
| 43 | return set; | ||
| 44 | } | ||
| 45 | |||
| 46 | int via_setAdd(set_t * set, ITEM_TYPE item) | ||
| 47 | { | ||
| 48 | int free = set->free; | ||
| 49 | if (free != -1) { | ||
| 50 | set->list[free].val = item; | ||
| 51 | set->free = set->list[free].free_next; | ||
| 52 | } else { | ||
| 53 | return 0; | ||
| 54 | } | ||
| 55 | set->list[free].alloc_next = set->alloc; | ||
| 56 | set->alloc = free; | ||
| 57 | set->list[free].free_next = -1; | ||
| 58 | return 1; | ||
| 59 | } | ||
| 60 | |||
| 61 | int via_setDel(set_t * set, ITEM_TYPE item) | ||
| 62 | { | ||
| 63 | int alloc = set->alloc; | ||
| 64 | int prev = -1; | ||
| 65 | |||
| 66 | while (alloc != -1) { | ||
| 67 | if (set->list[alloc].val == item) { | ||
| 68 | if (prev != -1) | ||
| 69 | set->list[prev].alloc_next = | ||
| 70 | set->list[alloc].alloc_next; | ||
| 71 | else | ||
| 72 | set->alloc = set->list[alloc].alloc_next; | ||
| 73 | break; | ||
| 74 | } | ||
| 75 | prev = alloc; | ||
| 76 | alloc = set->list[alloc].alloc_next; | ||
| 77 | } | ||
| 78 | |||
| 79 | if (alloc == -1) | ||
| 80 | return 0; | ||
| 81 | |||
| 82 | set->list[alloc].free_next = set->free; | ||
| 83 | set->free = alloc; | ||
| 84 | set->list[alloc].alloc_next = -1; | ||
| 85 | |||
| 86 | return 1; | ||
| 87 | } | ||
| 88 | |||
| 89 | /* setFirst -> setAdd -> setNext is wrong */ | ||
| 90 | |||
| 91 | int via_setFirst(set_t * set, ITEM_TYPE * item) | ||
| 92 | { | ||
| 93 | if (set->alloc == -1) | ||
| 94 | return 0; | ||
| 95 | |||
| 96 | *item = set->list[set->alloc].val; | ||
| 97 | set->trace = set->list[set->alloc].alloc_next; | ||
| 98 | |||
| 99 | return 1; | ||
| 100 | } | ||
| 101 | |||
| 102 | int via_setNext(set_t * set, ITEM_TYPE * item) | ||
| 103 | { | ||
| 104 | if (set->trace == -1) | ||
| 105 | return 0; | ||
| 106 | |||
| 107 | *item = set->list[set->trace].val; | ||
| 108 | set->trace = set->list[set->trace].alloc_next; | ||
| 109 | |||
| 110 | return 1; | ||
| 111 | } | ||
| 112 | |||
| 113 | int via_setDestroy(set_t * set) | ||
| 114 | { | ||
| 115 | drm_free(set, sizeof(set_t), DRM_MEM_DRIVER); | ||
| 116 | |||
| 117 | return 1; | ||
| 118 | } | ||
| 119 | |||
| 120 | #define ISFREE(bptr) ((bptr)->free) | ||
| 121 | |||
| 122 | #define fprintf(fmt, arg...) do{}while(0) | ||
| 123 | |||
| 124 | memHeap_t *via_mmInit(int ofs, int size) | ||
| 125 | { | ||
| 126 | PMemBlock blocks; | ||
| 127 | |||
| 128 | if (size <= 0) | ||
| 129 | return NULL; | ||
| 130 | |||
| 131 | blocks = (TMemBlock *) drm_calloc(1, sizeof(TMemBlock), DRM_MEM_DRIVER); | ||
| 132 | |||
| 133 | if (blocks) { | ||
| 134 | blocks->ofs = ofs; | ||
| 135 | blocks->size = size; | ||
| 136 | blocks->free = 1; | ||
| 137 | return (memHeap_t *) blocks; | ||
| 138 | } else | ||
| 139 | return NULL; | ||
| 140 | } | ||
| 141 | |||
| 142 | static TMemBlock *SliceBlock(TMemBlock * p, | ||
| 143 | int startofs, int size, | ||
| 144 | int reserved, int alignment) | ||
| 145 | { | ||
| 146 | TMemBlock *newblock; | ||
| 147 | |||
| 148 | /* break left */ | ||
| 149 | if (startofs > p->ofs) { | ||
| 150 | newblock = | ||
| 151 | (TMemBlock *) drm_calloc(1, sizeof(TMemBlock), | ||
| 152 | DRM_MEM_DRIVER); | ||
| 153 | newblock->ofs = startofs; | ||
| 154 | newblock->size = p->size - (startofs - p->ofs); | ||
| 155 | newblock->free = 1; | ||
| 156 | newblock->next = p->next; | ||
| 157 | p->size -= newblock->size; | ||
| 158 | p->next = newblock; | ||
| 159 | p = newblock; | ||
| 160 | } | ||
| 161 | |||
| 162 | /* break right */ | ||
| 163 | if (size < p->size) { | ||
| 164 | newblock = | ||
| 165 | (TMemBlock *) drm_calloc(1, sizeof(TMemBlock), | ||
| 166 | DRM_MEM_DRIVER); | ||
| 167 | newblock->ofs = startofs + size; | ||
| 168 | newblock->size = p->size - size; | ||
| 169 | newblock->free = 1; | ||
| 170 | newblock->next = p->next; | ||
| 171 | p->size = size; | ||
| 172 | p->next = newblock; | ||
| 173 | } | ||
| 174 | |||
| 175 | /* p = middle block */ | ||
| 176 | p->align = alignment; | ||
| 177 | p->free = 0; | ||
| 178 | p->reserved = reserved; | ||
| 179 | return p; | ||
| 180 | } | ||
| 181 | |||
| 182 | PMemBlock via_mmAllocMem(memHeap_t * heap, int size, int align2, | ||
| 183 | int startSearch) | ||
| 184 | { | ||
| 185 | int mask, startofs, endofs; | ||
| 186 | TMemBlock *p; | ||
| 187 | |||
| 188 | if (!heap || align2 < 0 || size <= 0) | ||
| 189 | return NULL; | ||
| 190 | |||
| 191 | mask = (1 << align2) - 1; | ||
| 192 | startofs = 0; | ||
| 193 | p = (TMemBlock *) heap; | ||
| 194 | |||
| 195 | while (p) { | ||
| 196 | if (ISFREE(p)) { | ||
| 197 | startofs = (p->ofs + mask) & ~mask; | ||
| 198 | |||
| 199 | if (startofs < startSearch) | ||
| 200 | startofs = startSearch; | ||
| 201 | |||
| 202 | endofs = startofs + size; | ||
| 203 | |||
| 204 | if (endofs <= (p->ofs + p->size)) | ||
| 205 | break; | ||
| 206 | } | ||
| 207 | |||
| 208 | p = p->next; | ||
| 209 | } | ||
| 210 | |||
| 211 | if (!p) | ||
| 212 | return NULL; | ||
| 213 | |||
| 214 | p = SliceBlock(p, startofs, size, 0, mask + 1); | ||
| 215 | p->heap = heap; | ||
| 216 | |||
| 217 | return p; | ||
| 218 | } | ||
| 219 | |||
| 220 | static __inline__ int Join2Blocks(TMemBlock * p) | ||
| 221 | { | ||
| 222 | if (p->free && p->next && p->next->free) { | ||
| 223 | TMemBlock *q = p->next; | ||
| 224 | p->size += q->size; | ||
| 225 | p->next = q->next; | ||
| 226 | drm_free(q, sizeof(TMemBlock), DRM_MEM_DRIVER); | ||
| 227 | |||
| 228 | return 1; | ||
| 229 | } | ||
| 230 | |||
| 231 | return 0; | ||
| 232 | } | ||
| 233 | |||
| 234 | int via_mmFreeMem(PMemBlock b) | ||
| 235 | { | ||
| 236 | TMemBlock *p, *prev; | ||
| 237 | |||
| 238 | if (!b) | ||
| 239 | return 0; | ||
| 240 | |||
| 241 | if (!b->heap) { | ||
| 242 | fprintf(stderr, "no heap\n"); | ||
| 243 | |||
| 244 | return -1; | ||
| 245 | } | ||
| 246 | |||
| 247 | p = b->heap; | ||
| 248 | prev = NULL; | ||
| 249 | |||
| 250 | while (p && p != b) { | ||
| 251 | prev = p; | ||
| 252 | p = p->next; | ||
| 253 | } | ||
| 254 | |||
| 255 | if (!p || p->free || p->reserved) { | ||
| 256 | if (!p) | ||
| 257 | fprintf(stderr, "block not found in heap\n"); | ||
| 258 | else if (p->free) | ||
| 259 | fprintf(stderr, "block already free\n"); | ||
| 260 | else | ||
| 261 | fprintf(stderr, "block is reserved\n"); | ||
| 262 | |||
| 263 | return -1; | ||
| 264 | } | ||
| 265 | |||
| 266 | p->free = 1; | ||
| 267 | Join2Blocks(p); | ||
| 268 | |||
| 269 | if (prev) | ||
| 270 | Join2Blocks(prev); | ||
| 271 | |||
| 272 | return 0; | ||
| 273 | } | ||
diff --git a/drivers/char/drm/via_ds.h b/drivers/char/drm/via_ds.h deleted file mode 100644 index d2bb9f37ca38..000000000000 --- a/drivers/char/drm/via_ds.h +++ /dev/null | |||
| @@ -1,104 +0,0 @@ | |||
| 1 | /* | ||
| 2 | * Copyright 1998-2003 VIA Technologies, Inc. All Rights Reserved. | ||
| 3 | * Copyright 2001-2003 S3 Graphics, Inc. All Rights Reserved. | ||
| 4 | * Copyright 2000 Silicon Integrated Systems Corp, Inc., HsinChu, Taiwan. | ||
| 5 | * All rights reserved. | ||
| 6 | * | ||
| 7 | * Permission is hereby granted, free of charge, to any person obtaining a | ||
| 8 | * copy of this software and associated documentation files (the "Software"), | ||
| 9 | * to deal in the Software without restriction, including without limitation | ||
| 10 | * the rights to use, copy, modify, merge, publish, distribute, sub license, | ||
| 11 | * and/or sell copies of the Software, and to permit persons to whom the | ||
| 12 | * Software is furnished to do so, subject to the following conditions: | ||
| 13 | * | ||
| 14 | * The above copyright notice and this permission notice (including the | ||
| 15 | * next paragraph) shall be included in all copies or substantial portions | ||
| 16 | * of the Software. | ||
| 17 | * | ||
| 18 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
| 19 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
| 20 | * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL | ||
| 21 | * VIA, S3 GRAPHICS, AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR | ||
| 22 | * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, | ||
| 23 | * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER | ||
| 24 | * DEALINGS IN THE SOFTWARE. | ||
| 25 | */ | ||
| 26 | #ifndef _via_ds_h_ | ||
| 27 | #define _via_ds_h_ | ||
| 28 | |||
| 29 | #include "drmP.h" | ||
| 30 | |||
| 31 | /* Set Data Structure */ | ||
| 32 | #define SET_SIZE 5000 | ||
| 33 | typedef unsigned long ITEM_TYPE; | ||
| 34 | |||
| 35 | typedef struct { | ||
| 36 | ITEM_TYPE val; | ||
| 37 | int alloc_next, free_next; | ||
| 38 | } list_item_t; | ||
| 39 | |||
| 40 | typedef struct { | ||
| 41 | int alloc; | ||
| 42 | int free; | ||
| 43 | int trace; | ||
| 44 | list_item_t list[SET_SIZE]; | ||
| 45 | } set_t; | ||
| 46 | |||
| 47 | set_t *via_setInit(void); | ||
| 48 | int via_setAdd(set_t * set, ITEM_TYPE item); | ||
| 49 | int via_setDel(set_t * set, ITEM_TYPE item); | ||
| 50 | int via_setFirst(set_t * set, ITEM_TYPE * item); | ||
| 51 | int via_setNext(set_t * set, ITEM_TYPE * item); | ||
| 52 | int via_setDestroy(set_t * set); | ||
| 53 | |||
| 54 | #endif | ||
| 55 | |||
| 56 | #ifndef MM_INC | ||
| 57 | #define MM_INC | ||
| 58 | |||
| 59 | struct mem_block_t { | ||
| 60 | struct mem_block_t *next; | ||
| 61 | struct mem_block_t *heap; | ||
| 62 | int ofs, size; | ||
| 63 | int align; | ||
| 64 | unsigned int free:1; | ||
| 65 | unsigned int reserved:1; | ||
| 66 | }; | ||
| 67 | typedef struct mem_block_t TMemBlock; | ||
| 68 | typedef struct mem_block_t *PMemBlock; | ||
| 69 | |||
| 70 | /* a heap is just the first block in a chain */ | ||
| 71 | typedef struct mem_block_t memHeap_t; | ||
| 72 | |||
| 73 | static __inline__ int mmBlockSize(PMemBlock b) | ||
| 74 | { | ||
| 75 | return b->size; | ||
| 76 | } | ||
| 77 | |||
| 78 | static __inline__ int mmOffset(PMemBlock b) | ||
| 79 | { | ||
| 80 | return b->ofs; | ||
| 81 | } | ||
| 82 | |||
| 83 | static __inline__ void mmMarkReserved(PMemBlock b) | ||
| 84 | { | ||
| 85 | b->reserved = 1; | ||
| 86 | } | ||
| 87 | |||
| 88 | /* | ||
| 89 | * input: total size in bytes | ||
| 90 | * return: a heap pointer if OK, NULL if error | ||
| 91 | */ | ||
| 92 | memHeap_t *via_mmInit(int ofs, int size); | ||
| 93 | |||
| 94 | PMemBlock via_mmAllocMem(memHeap_t * heap, int size, int align2, | ||
| 95 | int startSearch); | ||
| 96 | |||
| 97 | /* | ||
| 98 | * Free block starts at offset | ||
| 99 | * input: pointer to a block | ||
| 100 | * return: 0 if OK, -1 if error | ||
| 101 | */ | ||
| 102 | int via_mmFreeMem(PMemBlock b); | ||
| 103 | |||
| 104 | #endif | ||
diff --git a/drivers/char/drm/via_map.c b/drivers/char/drm/via_map.c index c6a08e96285b..782011e0a58d 100644 --- a/drivers/char/drm/via_map.c +++ b/drivers/char/drm/via_map.c | |||
| @@ -98,6 +98,7 @@ int via_map_init(DRM_IOCTL_ARGS) | |||
| 98 | int via_driver_load(drm_device_t *dev, unsigned long chipset) | 98 | int via_driver_load(drm_device_t *dev, unsigned long chipset) |
| 99 | { | 99 | { |
| 100 | drm_via_private_t *dev_priv; | 100 | drm_via_private_t *dev_priv; |
| 101 | int ret = 0; | ||
| 101 | 102 | ||
| 102 | dev_priv = drm_calloc(1, sizeof(drm_via_private_t), DRM_MEM_DRIVER); | 103 | dev_priv = drm_calloc(1, sizeof(drm_via_private_t), DRM_MEM_DRIVER); |
| 103 | if (dev_priv == NULL) | 104 | if (dev_priv == NULL) |
| @@ -108,13 +109,19 @@ int via_driver_load(drm_device_t *dev, unsigned long chipset) | |||
| 108 | if (chipset == VIA_PRO_GROUP_A) | 109 | if (chipset == VIA_PRO_GROUP_A) |
| 109 | dev_priv->pro_group_a = 1; | 110 | dev_priv->pro_group_a = 1; |
| 110 | 111 | ||
| 111 | return 0; | 112 | ret = drm_sman_init(&dev_priv->sman, 2, 12, 8); |
| 113 | if (ret) { | ||
| 114 | drm_free(dev_priv, sizeof(*dev_priv), DRM_MEM_DRIVER); | ||
| 115 | } | ||
| 116 | return ret; | ||
| 112 | } | 117 | } |
| 113 | 118 | ||
| 114 | int via_driver_unload(drm_device_t *dev) | 119 | int via_driver_unload(drm_device_t *dev) |
| 115 | { | 120 | { |
| 116 | drm_via_private_t *dev_priv = dev->dev_private; | 121 | drm_via_private_t *dev_priv = dev->dev_private; |
| 117 | 122 | ||
| 123 | drm_sman_takedown(&dev_priv->sman); | ||
| 124 | |||
| 118 | drm_free(dev_priv, sizeof(drm_via_private_t), DRM_MEM_DRIVER); | 125 | drm_free(dev_priv, sizeof(drm_via_private_t), DRM_MEM_DRIVER); |
| 119 | 126 | ||
| 120 | return 0; | 127 | return 0; |
diff --git a/drivers/char/drm/via_mm.c b/drivers/char/drm/via_mm.c index 33e0cb12e4c3..2fcf0577a7aa 100644 --- a/drivers/char/drm/via_mm.c +++ b/drivers/char/drm/via_mm.c | |||
| @@ -1,6 +1,6 @@ | |||
| 1 | /* | 1 | /* |
| 2 | * Copyright 1998-2003 VIA Technologies, Inc. All Rights Reserved. | 2 | * Copyright 2006 Tungsten Graphics Inc., Bismarck, ND., USA. |
| 3 | * Copyright 2001-2003 S3 Graphics, Inc. All Rights Reserved. | 3 | * All rights reserved. |
| 4 | * | 4 | * |
| 5 | * Permission is hereby granted, free of charge, to any person obtaining a | 5 | * Permission is hereby granted, free of charge, to any person obtaining a |
| 6 | * copy of this software and associated documentation files (the "Software"), | 6 | * copy of this software and associated documentation files (the "Software"), |
| @@ -16,347 +16,194 @@ | |||
| 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
| 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
| 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL | 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL |
| 19 | * VIA, S3 GRAPHICS, AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR | 19 | * THE AUTHORS OR COPYRIGHT HOLDERS AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, |
| 20 | * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, | 20 | * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, |
| 21 | * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER | 21 | * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER |
| 22 | * DEALINGS IN THE SOFTWARE. | 22 | * DEALINGS IN THE SOFTWARE. |
| 23 | */ | 23 | */ |
| 24 | /* | ||
| 25 | * Authors: Thomas Hellström <thomas-at-tungstengraphics-dot-com> | ||
| 26 | */ | ||
| 27 | |||
| 24 | #include "drmP.h" | 28 | #include "drmP.h" |
| 25 | #include "via_drm.h" | 29 | #include "via_drm.h" |
| 26 | #include "via_drv.h" | 30 | #include "via_drv.h" |
| 27 | #include "via_ds.h" | 31 | #include "drm_sman.h" |
| 28 | #include "via_mm.h" | ||
| 29 | |||
| 30 | #define MAX_CONTEXT 100 | ||
| 31 | |||
| 32 | typedef struct { | ||
| 33 | int used; | ||
| 34 | int context; | ||
| 35 | set_t *sets[2]; /* 0 for frame buffer, 1 for AGP , 2 for System */ | ||
| 36 | } via_context_t; | ||
| 37 | |||
| 38 | static via_context_t global_ppriv[MAX_CONTEXT]; | ||
| 39 | 32 | ||
| 40 | static int via_agp_alloc(drm_via_mem_t * mem); | 33 | #define VIA_MM_ALIGN_SHIFT 4 |
| 41 | static int via_agp_free(drm_via_mem_t * mem); | 34 | #define VIA_MM_ALIGN_MASK ( (1 << VIA_MM_ALIGN_SHIFT) - 1) |
| 42 | static int via_fb_alloc(drm_via_mem_t * mem); | ||
| 43 | static int via_fb_free(drm_via_mem_t * mem); | ||
| 44 | |||
| 45 | static int add_alloc_set(int context, int type, unsigned long val) | ||
| 46 | { | ||
| 47 | int i, retval = 0; | ||
| 48 | |||
| 49 | for (i = 0; i < MAX_CONTEXT; i++) { | ||
| 50 | if (global_ppriv[i].used && global_ppriv[i].context == context) { | ||
| 51 | retval = via_setAdd(global_ppriv[i].sets[type], val); | ||
| 52 | break; | ||
| 53 | } | ||
| 54 | } | ||
| 55 | |||
| 56 | return retval; | ||
| 57 | } | ||
| 58 | |||
| 59 | static int del_alloc_set(int context, int type, unsigned long val) | ||
| 60 | { | ||
| 61 | int i, retval = 0; | ||
| 62 | |||
| 63 | for (i = 0; i < MAX_CONTEXT; i++) | ||
| 64 | if (global_ppriv[i].used && global_ppriv[i].context == context) { | ||
| 65 | retval = via_setDel(global_ppriv[i].sets[type], val); | ||
| 66 | break; | ||
| 67 | } | ||
| 68 | |||
| 69 | return retval; | ||
| 70 | } | ||
| 71 | |||
| 72 | /* agp memory management */ | ||
| 73 | static memHeap_t *AgpHeap = NULL; | ||
| 74 | 35 | ||
| 75 | int via_agp_init(DRM_IOCTL_ARGS) | 36 | int via_agp_init(DRM_IOCTL_ARGS) |
| 76 | { | 37 | { |
| 38 | DRM_DEVICE; | ||
| 77 | drm_via_agp_t agp; | 39 | drm_via_agp_t agp; |
| 40 | drm_via_private_t *dev_priv = (drm_via_private_t *) dev->dev_private; | ||
| 41 | int ret; | ||
| 78 | 42 | ||
| 79 | DRM_COPY_FROM_USER_IOCTL(agp, (drm_via_agp_t __user *) data, | 43 | DRM_COPY_FROM_USER_IOCTL(agp, (drm_via_agp_t __user *) data, |
| 80 | sizeof(agp)); | 44 | sizeof(agp)); |
| 45 | mutex_lock(&dev->struct_mutex); | ||
| 46 | ret = drm_sman_set_range(&dev_priv->sman, VIA_MEM_AGP, 0, | ||
| 47 | agp.size >> VIA_MM_ALIGN_SHIFT); | ||
| 48 | |||
| 49 | if (ret) { | ||
| 50 | DRM_ERROR("AGP memory manager initialisation error\n"); | ||
| 51 | mutex_unlock(&dev->struct_mutex); | ||
| 52 | return ret; | ||
| 53 | } | ||
| 81 | 54 | ||
| 82 | AgpHeap = via_mmInit(agp.offset, agp.size); | 55 | dev_priv->agp_initialized = 1; |
| 83 | 56 | dev_priv->agp_offset = agp.offset; | |
| 84 | DRM_DEBUG("offset = %lu, size = %lu", (unsigned long)agp.offset, | 57 | mutex_unlock(&dev->struct_mutex); |
| 85 | (unsigned long)agp.size); | ||
| 86 | 58 | ||
| 59 | DRM_DEBUG("offset = %u, size = %u", agp.offset, agp.size); | ||
| 87 | return 0; | 60 | return 0; |
| 88 | } | 61 | } |
| 89 | 62 | ||
| 90 | /* fb memory management */ | ||
| 91 | static memHeap_t *FBHeap = NULL; | ||
| 92 | |||
| 93 | int via_fb_init(DRM_IOCTL_ARGS) | 63 | int via_fb_init(DRM_IOCTL_ARGS) |
| 94 | { | 64 | { |
| 65 | DRM_DEVICE; | ||
| 95 | drm_via_fb_t fb; | 66 | drm_via_fb_t fb; |
| 67 | drm_via_private_t *dev_priv = (drm_via_private_t *) dev->dev_private; | ||
| 68 | int ret; | ||
| 96 | 69 | ||
| 97 | DRM_COPY_FROM_USER_IOCTL(fb, (drm_via_fb_t __user *) data, sizeof(fb)); | 70 | DRM_COPY_FROM_USER_IOCTL(fb, (drm_via_fb_t __user *) data, sizeof(fb)); |
| 98 | 71 | ||
| 99 | FBHeap = via_mmInit(fb.offset, fb.size); | 72 | mutex_lock(&dev->struct_mutex); |
| 73 | ret = drm_sman_set_range(&dev_priv->sman, VIA_MEM_VIDEO, 0, | ||
| 74 | fb.size >> VIA_MM_ALIGN_SHIFT); | ||
| 100 | 75 | ||
| 101 | DRM_DEBUG("offset = %lu, size = %lu", (unsigned long)fb.offset, | 76 | if (ret) { |
| 102 | (unsigned long)fb.size); | 77 | DRM_ERROR("VRAM memory manager initialisation error\n"); |
| 78 | mutex_unlock(&dev->struct_mutex); | ||
| 79 | return ret; | ||
| 80 | } | ||
| 103 | 81 | ||
| 104 | return 0; | 82 | dev_priv->vram_initialized = 1; |
| 105 | } | 83 | dev_priv->vram_offset = fb.offset; |
| 106 | 84 | ||
| 107 | int via_init_context(struct drm_device *dev, int context) | 85 | mutex_unlock(&dev->struct_mutex); |
| 108 | { | 86 | DRM_DEBUG("offset = %u, size = %u", fb.offset, fb.size); |
| 109 | int i; | 87 | |
| 110 | 88 | return 0; | |
| 111 | for (i = 0; i < MAX_CONTEXT; i++) | ||
| 112 | if (global_ppriv[i].used && | ||
| 113 | (global_ppriv[i].context == context)) | ||
| 114 | break; | ||
| 115 | |||
| 116 | if (i >= MAX_CONTEXT) { | ||
| 117 | for (i = 0; i < MAX_CONTEXT; i++) { | ||
| 118 | if (!global_ppriv[i].used) { | ||
| 119 | global_ppriv[i].context = context; | ||
| 120 | global_ppriv[i].used = 1; | ||
| 121 | global_ppriv[i].sets[0] = via_setInit(); | ||
| 122 | global_ppriv[i].sets[1] = via_setInit(); | ||
| 123 | DRM_DEBUG("init allocation set, socket=%d," | ||
| 124 | " context = %d\n", i, context); | ||
| 125 | break; | ||
| 126 | } | ||
| 127 | } | ||
| 128 | |||
| 129 | if ((i >= MAX_CONTEXT) || (global_ppriv[i].sets[0] == NULL) || | ||
| 130 | (global_ppriv[i].sets[1] == NULL)) { | ||
| 131 | return 0; | ||
| 132 | } | ||
| 133 | } | ||
| 134 | 89 | ||
| 135 | return 1; | ||
| 136 | } | 90 | } |
| 137 | 91 | ||
| 138 | int via_final_context(struct drm_device *dev, int context) | 92 | int via_final_context(struct drm_device *dev, int context) |
| 139 | { | 93 | { |
| 140 | int i; | ||
| 141 | drm_via_private_t *dev_priv = (drm_via_private_t *) dev->dev_private; | 94 | drm_via_private_t *dev_priv = (drm_via_private_t *) dev->dev_private; |
| 142 | 95 | ||
| 143 | for (i = 0; i < MAX_CONTEXT; i++) | ||
| 144 | if (global_ppriv[i].used && | ||
| 145 | (global_ppriv[i].context == context)) | ||
| 146 | break; | ||
| 147 | |||
| 148 | if (i < MAX_CONTEXT) { | ||
| 149 | set_t *set; | ||
| 150 | ITEM_TYPE item; | ||
| 151 | int retval; | ||
| 152 | |||
| 153 | DRM_DEBUG("find socket %d, context = %d\n", i, context); | ||
| 154 | |||
| 155 | /* Video Memory */ | ||
| 156 | set = global_ppriv[i].sets[0]; | ||
| 157 | retval = via_setFirst(set, &item); | ||
| 158 | while (retval) { | ||
| 159 | DRM_DEBUG("free video memory 0x%lx\n", item); | ||
| 160 | via_mmFreeMem((PMemBlock) item); | ||
| 161 | retval = via_setNext(set, &item); | ||
| 162 | } | ||
| 163 | via_setDestroy(set); | ||
| 164 | |||
| 165 | /* AGP Memory */ | ||
| 166 | set = global_ppriv[i].sets[1]; | ||
| 167 | retval = via_setFirst(set, &item); | ||
| 168 | while (retval) { | ||
| 169 | DRM_DEBUG("free agp memory 0x%lx\n", item); | ||
| 170 | via_mmFreeMem((PMemBlock) item); | ||
| 171 | retval = via_setNext(set, &item); | ||
| 172 | } | ||
| 173 | via_setDestroy(set); | ||
| 174 | global_ppriv[i].used = 0; | ||
| 175 | } | ||
| 176 | via_release_futex(dev_priv, context); | 96 | via_release_futex(dev_priv, context); |
| 177 | 97 | ||
| 178 | #if defined(__linux__) | ||
| 179 | /* Linux specific until context tracking code gets ported to BSD */ | 98 | /* Linux specific until context tracking code gets ported to BSD */ |
| 180 | /* Last context, perform cleanup */ | 99 | /* Last context, perform cleanup */ |
| 181 | if (dev->ctx_count == 1 && dev->dev_private) { | 100 | if (dev->ctx_count == 1 && dev->dev_private) { |
| 182 | DRM_DEBUG("Last Context\n"); | 101 | DRM_DEBUG("Last Context\n"); |
| 183 | if (dev->irq) | 102 | if (dev->irq) |
| 184 | drm_irq_uninstall(dev); | 103 | drm_irq_uninstall(dev); |
| 185 | |||
| 186 | via_cleanup_futex(dev_priv); | 104 | via_cleanup_futex(dev_priv); |
| 187 | via_do_cleanup_map(dev); | 105 | via_do_cleanup_map(dev); |
| 188 | } | 106 | } |
| 189 | #endif | ||
| 190 | |||
| 191 | return 1; | 107 | return 1; |
| 192 | } | 108 | } |
| 193 | 109 | ||
| 110 | void via_lastclose(struct drm_device *dev) | ||
| 111 | { | ||
| 112 | drm_via_private_t *dev_priv = (drm_via_private_t *) dev->dev_private; | ||
| 113 | |||
| 114 | if (!dev_priv) | ||
| 115 | return; | ||
| 116 | |||
| 117 | mutex_lock(&dev->struct_mutex); | ||
| 118 | drm_sman_cleanup(&dev_priv->sman); | ||
| 119 | dev_priv->vram_initialized = 0; | ||
| 120 | dev_priv->agp_initialized = 0; | ||
| 121 | mutex_unlock(&dev->struct_mutex); | ||
| 122 | } | ||
| 123 | |||
| 194 | int via_mem_alloc(DRM_IOCTL_ARGS) | 124 | int via_mem_alloc(DRM_IOCTL_ARGS) |
| 195 | { | 125 | { |
| 126 | DRM_DEVICE; | ||
| 127 | |||
| 196 | drm_via_mem_t mem; | 128 | drm_via_mem_t mem; |
| 129 | int retval = 0; | ||
| 130 | drm_memblock_item_t *item; | ||
| 131 | drm_via_private_t *dev_priv = (drm_via_private_t *) dev->dev_private; | ||
| 132 | unsigned long tmpSize; | ||
| 197 | 133 | ||
| 198 | DRM_COPY_FROM_USER_IOCTL(mem, (drm_via_mem_t __user *) data, | 134 | DRM_COPY_FROM_USER_IOCTL(mem, (drm_via_mem_t __user *) data, |
| 199 | sizeof(mem)); | 135 | sizeof(mem)); |
| 200 | 136 | ||
| 201 | switch (mem.type) { | 137 | if (mem.type > VIA_MEM_AGP) { |
| 202 | case VIA_MEM_VIDEO: | 138 | DRM_ERROR("Unknown memory type allocation\n"); |
| 203 | if (via_fb_alloc(&mem) < 0) | 139 | return DRM_ERR(EINVAL); |
| 204 | return -EFAULT; | ||
| 205 | DRM_COPY_TO_USER_IOCTL((drm_via_mem_t __user *) data, mem, | ||
| 206 | sizeof(mem)); | ||
| 207 | return 0; | ||
| 208 | case VIA_MEM_AGP: | ||
| 209 | if (via_agp_alloc(&mem) < 0) | ||
| 210 | return -EFAULT; | ||
| 211 | DRM_COPY_TO_USER_IOCTL((drm_via_mem_t __user *) data, mem, | ||
| 212 | sizeof(mem)); | ||
| 213 | return 0; | ||
| 214 | } | 140 | } |
| 215 | 141 | mutex_lock(&dev->struct_mutex); | |
| 216 | return -EFAULT; | 142 | if (0 == ((mem.type == VIA_MEM_VIDEO) ? dev_priv->vram_initialized : |
| 217 | } | 143 | dev_priv->agp_initialized)) { |
| 218 | 144 | DRM_ERROR | |
| 219 | static int via_fb_alloc(drm_via_mem_t * mem) | 145 | ("Attempt to allocate from uninitialized memory manager.\n"); |
| 220 | { | 146 | mutex_unlock(&dev->struct_mutex); |
| 221 | drm_via_mm_t fb; | 147 | return DRM_ERR(EINVAL); |
| 222 | PMemBlock block; | ||
| 223 | int retval = 0; | ||
| 224 | |||
| 225 | if (!FBHeap) | ||
| 226 | return -1; | ||
| 227 | |||
| 228 | fb.size = mem->size; | ||
| 229 | fb.context = mem->context; | ||
| 230 | |||
| 231 | block = via_mmAllocMem(FBHeap, fb.size, 5, 0); | ||
| 232 | if (block) { | ||
| 233 | fb.offset = block->ofs; | ||
| 234 | fb.free = (unsigned long)block; | ||
| 235 | if (!add_alloc_set(fb.context, VIA_MEM_VIDEO, fb.free)) { | ||
| 236 | DRM_DEBUG("adding to allocation set fails\n"); | ||
| 237 | via_mmFreeMem((PMemBlock) fb.free); | ||
| 238 | retval = -1; | ||
| 239 | } | ||
| 240 | } else { | ||
| 241 | fb.offset = 0; | ||
| 242 | fb.size = 0; | ||
| 243 | fb.free = 0; | ||
| 244 | retval = -1; | ||
| 245 | } | 148 | } |
| 246 | 149 | ||
| 247 | mem->offset = fb.offset; | 150 | tmpSize = (mem.size + VIA_MM_ALIGN_MASK) >> VIA_MM_ALIGN_SHIFT; |
| 248 | mem->index = fb.free; | 151 | item = drm_sman_alloc(&dev_priv->sman, mem.type, tmpSize, 0, |
| 249 | 152 | (unsigned long)priv); | |
| 250 | DRM_DEBUG("alloc fb, size = %d, offset = %d\n", fb.size, | 153 | mutex_unlock(&dev->struct_mutex); |
| 251 | (int)fb.offset); | 154 | if (item) { |
| 252 | 155 | mem.offset = ((mem.type == VIA_MEM_VIDEO) ? | |
| 253 | return retval; | 156 | dev_priv->vram_offset : dev_priv->agp_offset) + |
| 254 | } | 157 | (item->mm-> |
| 255 | 158 | offset(item->mm, item->mm_info) << VIA_MM_ALIGN_SHIFT); | |
| 256 | static int via_agp_alloc(drm_via_mem_t * mem) | 159 | mem.index = item->user_hash.key; |
| 257 | { | ||
| 258 | drm_via_mm_t agp; | ||
| 259 | PMemBlock block; | ||
| 260 | int retval = 0; | ||
| 261 | |||
| 262 | if (!AgpHeap) | ||
| 263 | return -1; | ||
| 264 | |||
| 265 | agp.size = mem->size; | ||
| 266 | agp.context = mem->context; | ||
| 267 | |||
| 268 | block = via_mmAllocMem(AgpHeap, agp.size, 5, 0); | ||
| 269 | if (block) { | ||
| 270 | agp.offset = block->ofs; | ||
| 271 | agp.free = (unsigned long)block; | ||
| 272 | if (!add_alloc_set(agp.context, VIA_MEM_AGP, agp.free)) { | ||
| 273 | DRM_DEBUG("adding to allocation set fails\n"); | ||
| 274 | via_mmFreeMem((PMemBlock) agp.free); | ||
| 275 | retval = -1; | ||
| 276 | } | ||
| 277 | } else { | 160 | } else { |
| 278 | agp.offset = 0; | 161 | mem.offset = 0; |
| 279 | agp.size = 0; | 162 | mem.size = 0; |
| 280 | agp.free = 0; | 163 | mem.index = 0; |
| 164 | DRM_DEBUG("Video memory allocation failed\n"); | ||
| 165 | retval = DRM_ERR(ENOMEM); | ||
| 281 | } | 166 | } |
| 167 | DRM_COPY_TO_USER_IOCTL((drm_via_mem_t __user *) data, mem, sizeof(mem)); | ||
| 282 | 168 | ||
| 283 | mem->offset = agp.offset; | ||
| 284 | mem->index = agp.free; | ||
| 285 | |||
| 286 | DRM_DEBUG("alloc agp, size = %d, offset = %d\n", agp.size, | ||
| 287 | (unsigned int)agp.offset); | ||
| 288 | return retval; | 169 | return retval; |
| 289 | } | 170 | } |
| 290 | 171 | ||
| 291 | int via_mem_free(DRM_IOCTL_ARGS) | 172 | int via_mem_free(DRM_IOCTL_ARGS) |
| 292 | { | 173 | { |
| 174 | DRM_DEVICE; | ||
| 175 | drm_via_private_t *dev_priv = dev->dev_private; | ||
| 293 | drm_via_mem_t mem; | 176 | drm_via_mem_t mem; |
| 177 | int ret; | ||
| 294 | 178 | ||
| 295 | DRM_COPY_FROM_USER_IOCTL(mem, (drm_via_mem_t __user *) data, | 179 | DRM_COPY_FROM_USER_IOCTL(mem, (drm_via_mem_t __user *) data, |
| 296 | sizeof(mem)); | 180 | sizeof(mem)); |
| 297 | 181 | ||
| 298 | switch (mem.type) { | 182 | mutex_lock(&dev->struct_mutex); |
| 183 | ret = drm_sman_free_key(&dev_priv->sman, mem.index); | ||
| 184 | mutex_unlock(&dev->struct_mutex); | ||
| 185 | DRM_DEBUG("free = 0x%lx\n", mem.index); | ||
| 299 | 186 | ||
| 300 | case VIA_MEM_VIDEO: | 187 | return ret; |
| 301 | if (via_fb_free(&mem) == 0) | ||
| 302 | return 0; | ||
| 303 | break; | ||
| 304 | case VIA_MEM_AGP: | ||
| 305 | if (via_agp_free(&mem) == 0) | ||
| 306 | return 0; | ||
| 307 | break; | ||
| 308 | } | ||
| 309 | |||
| 310 | return -EFAULT; | ||
| 311 | } | 188 | } |
| 312 | 189 | ||
| 313 | static int via_fb_free(drm_via_mem_t * mem) | ||
| 314 | { | ||
| 315 | drm_via_mm_t fb; | ||
| 316 | int retval = 0; | ||
| 317 | |||
| 318 | if (!FBHeap) { | ||
| 319 | return -1; | ||
| 320 | } | ||
| 321 | |||
| 322 | fb.free = mem->index; | ||
| 323 | fb.context = mem->context; | ||
| 324 | |||
| 325 | if (!fb.free) { | ||
| 326 | return -1; | ||
| 327 | |||
| 328 | } | ||
| 329 | |||
| 330 | via_mmFreeMem((PMemBlock) fb.free); | ||
| 331 | |||
| 332 | if (!del_alloc_set(fb.context, VIA_MEM_VIDEO, fb.free)) { | ||
| 333 | retval = -1; | ||
| 334 | } | ||
| 335 | |||
| 336 | DRM_DEBUG("free fb, free = %ld\n", fb.free); | ||
| 337 | 190 | ||
| 338 | return retval; | 191 | void via_reclaim_buffers_locked(drm_device_t * dev, struct file *filp) |
| 339 | } | ||
| 340 | |||
| 341 | static int via_agp_free(drm_via_mem_t * mem) | ||
| 342 | { | 192 | { |
| 343 | drm_via_mm_t agp; | 193 | drm_via_private_t *dev_priv = dev->dev_private; |
| 344 | 194 | drm_file_t *priv = filp->private_data; | |
| 345 | int retval = 0; | ||
| 346 | 195 | ||
| 347 | agp.free = mem->index; | 196 | mutex_lock(&dev->struct_mutex); |
| 348 | agp.context = mem->context; | 197 | if (drm_sman_owner_clean(&dev_priv->sman, (unsigned long)priv)) { |
| 349 | 198 | mutex_unlock(&dev->struct_mutex); | |
| 350 | if (!agp.free) | 199 | return; |
| 351 | return -1; | ||
| 352 | |||
| 353 | via_mmFreeMem((PMemBlock) agp.free); | ||
| 354 | |||
| 355 | if (!del_alloc_set(agp.context, VIA_MEM_AGP, agp.free)) { | ||
| 356 | retval = -1; | ||
| 357 | } | 200 | } |
| 358 | 201 | ||
| 359 | DRM_DEBUG("free agp, free = %ld\n", agp.free); | 202 | if (dev->driver->dma_quiescent) { |
| 203 | dev->driver->dma_quiescent(dev); | ||
| 204 | } | ||
| 360 | 205 | ||
| 361 | return retval; | 206 | drm_sman_owner_cleanup(&dev_priv->sman, (unsigned long)priv); |
| 207 | mutex_unlock(&dev->struct_mutex); | ||
| 208 | return; | ||
| 362 | } | 209 | } |
