diff options
Diffstat (limited to 'drivers/char/drm')
57 files changed, 2940 insertions, 1902 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/drm.h b/drivers/char/drm/drm.h index 5642ac43e0f5..8db9041e306c 100644 --- a/drivers/char/drm/drm.h +++ b/drivers/char/drm/drm.h | |||
@@ -117,6 +117,14 @@ typedef struct drm_clip_rect { | |||
117 | } drm_clip_rect_t; | 117 | } drm_clip_rect_t; |
118 | 118 | ||
119 | /** | 119 | /** |
120 | * Drawable information. | ||
121 | */ | ||
122 | typedef struct drm_drawable_info { | ||
123 | unsigned int num_rects; | ||
124 | drm_clip_rect_t *rects; | ||
125 | } drm_drawable_info_t; | ||
126 | |||
127 | /** | ||
120 | * Texture region, | 128 | * Texture region, |
121 | */ | 129 | */ |
122 | typedef struct drm_tex_region { | 130 | typedef struct drm_tex_region { |
@@ -348,7 +356,8 @@ typedef struct drm_buf_desc { | |||
348 | _DRM_PAGE_ALIGN = 0x01, /**< Align on page boundaries for DMA */ | 356 | _DRM_PAGE_ALIGN = 0x01, /**< Align on page boundaries for DMA */ |
349 | _DRM_AGP_BUFFER = 0x02, /**< Buffer is in AGP space */ | 357 | _DRM_AGP_BUFFER = 0x02, /**< Buffer is in AGP space */ |
350 | _DRM_SG_BUFFER = 0x04, /**< Scatter/gather memory buffer */ | 358 | _DRM_SG_BUFFER = 0x04, /**< Scatter/gather memory buffer */ |
351 | _DRM_FB_BUFFER = 0x08 /**< Buffer is in frame buffer */ | 359 | _DRM_FB_BUFFER = 0x08, /**< Buffer is in frame buffer */ |
360 | _DRM_PCI_BUFFER_RO = 0x10 /**< Map PCI DMA buffer read-only */ | ||
352 | } flags; | 361 | } flags; |
353 | unsigned long agp_start; /**< | 362 | unsigned long agp_start; /**< |
354 | * Start address of where the AGP buffers are | 363 | * Start address of where the AGP buffers are |
@@ -444,6 +453,20 @@ typedef struct drm_draw { | |||
444 | } drm_draw_t; | 453 | } drm_draw_t; |
445 | 454 | ||
446 | /** | 455 | /** |
456 | * DRM_IOCTL_UPDATE_DRAW ioctl argument type. | ||
457 | */ | ||
458 | typedef enum { | ||
459 | DRM_DRAWABLE_CLIPRECTS, | ||
460 | } drm_drawable_info_type_t; | ||
461 | |||
462 | typedef struct drm_update_draw { | ||
463 | drm_drawable_t handle; | ||
464 | unsigned int type; | ||
465 | unsigned int num; | ||
466 | unsigned long long data; | ||
467 | } drm_update_draw_t; | ||
468 | |||
469 | /** | ||
447 | * DRM_IOCTL_GET_MAGIC and DRM_IOCTL_AUTH_MAGIC ioctl argument type. | 470 | * DRM_IOCTL_GET_MAGIC and DRM_IOCTL_AUTH_MAGIC ioctl argument type. |
448 | */ | 471 | */ |
449 | typedef struct drm_auth { | 472 | typedef struct drm_auth { |
@@ -465,10 +488,14 @@ typedef struct drm_irq_busid { | |||
465 | typedef enum { | 488 | typedef enum { |
466 | _DRM_VBLANK_ABSOLUTE = 0x0, /**< Wait for specific vblank sequence number */ | 489 | _DRM_VBLANK_ABSOLUTE = 0x0, /**< Wait for specific vblank sequence number */ |
467 | _DRM_VBLANK_RELATIVE = 0x1, /**< Wait for given number of vblanks */ | 490 | _DRM_VBLANK_RELATIVE = 0x1, /**< Wait for given number of vblanks */ |
491 | _DRM_VBLANK_NEXTONMISS = 0x10000000, /**< If missed, wait for next vblank */ | ||
492 | _DRM_VBLANK_SECONDARY = 0x20000000, /**< Secondary display controller */ | ||
468 | _DRM_VBLANK_SIGNAL = 0x40000000 /**< Send signal instead of blocking */ | 493 | _DRM_VBLANK_SIGNAL = 0x40000000 /**< Send signal instead of blocking */ |
469 | } drm_vblank_seq_type_t; | 494 | } drm_vblank_seq_type_t; |
470 | 495 | ||
471 | #define _DRM_VBLANK_FLAGS_MASK _DRM_VBLANK_SIGNAL | 496 | #define _DRM_VBLANK_TYPES_MASK (_DRM_VBLANK_ABSOLUTE | _DRM_VBLANK_RELATIVE) |
497 | #define _DRM_VBLANK_FLAGS_MASK (_DRM_VBLANK_SIGNAL | _DRM_VBLANK_SECONDARY | \ | ||
498 | _DRM_VBLANK_NEXTONMISS) | ||
472 | 499 | ||
473 | struct drm_wait_vblank_request { | 500 | struct drm_wait_vblank_request { |
474 | drm_vblank_seq_type_t type; | 501 | drm_vblank_seq_type_t type; |
@@ -623,6 +650,8 @@ typedef struct drm_set_version { | |||
623 | 650 | ||
624 | #define DRM_IOCTL_WAIT_VBLANK DRM_IOWR(0x3a, drm_wait_vblank_t) | 651 | #define DRM_IOCTL_WAIT_VBLANK DRM_IOWR(0x3a, drm_wait_vblank_t) |
625 | 652 | ||
653 | #define DRM_IOCTL_UPDATE_DRAW DRM_IOW(0x3f, drm_update_draw_t) | ||
654 | |||
626 | /** | 655 | /** |
627 | * Device specific ioctls should only be in their respective headers | 656 | * Device specific ioctls should only be in their respective headers |
628 | * The device specific ioctl range is from 0x40 to 0x79. | 657 | * The device specific ioctl range is from 0x40 to 0x79. |
diff --git a/drivers/char/drm/drmP.h b/drivers/char/drm/drmP.h index d2a56182bc35..0bbb04f2390f 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 */ |
@@ -96,6 +97,7 @@ | |||
96 | #define DRIVER_IRQ_VBL 0x100 | 97 | #define DRIVER_IRQ_VBL 0x100 |
97 | #define DRIVER_DMA_QUEUE 0x200 | 98 | #define DRIVER_DMA_QUEUE 0x200 |
98 | #define DRIVER_FB_DMA 0x400 | 99 | #define DRIVER_FB_DMA 0x400 |
100 | #define DRIVER_IRQ_VBL2 0x800 | ||
99 | 101 | ||
100 | /***********************************************************************/ | 102 | /***********************************************************************/ |
101 | /** \name Begin the DRM... */ | 103 | /** \name Begin the DRM... */ |
@@ -104,7 +106,7 @@ | |||
104 | #define DRM_DEBUG_CODE 2 /**< Include debugging code if > 1, then | 106 | #define DRM_DEBUG_CODE 2 /**< Include debugging code if > 1, then |
105 | also include looping detection. */ | 107 | also include looping detection. */ |
106 | 108 | ||
107 | #define DRM_HASH_SIZE 16 /**< Size of key hash table. Must be power of 2. */ | 109 | #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 */ | 110 | #define DRM_KERNEL_CONTEXT 0 /**< Change drm_resctx if changed */ |
109 | #define DRM_RESERVED_CONTEXTS 1 /**< Change drm_resctx if changed */ | 111 | #define DRM_RESERVED_CONTEXTS 1 /**< Change drm_resctx if changed */ |
110 | #define DRM_LOOPING_LIMIT 5000000 | 112 | #define DRM_LOOPING_LIMIT 5000000 |
@@ -134,19 +136,12 @@ | |||
134 | #define DRM_MEM_CTXBITMAP 18 | 136 | #define DRM_MEM_CTXBITMAP 18 |
135 | #define DRM_MEM_STUB 19 | 137 | #define DRM_MEM_STUB 19 |
136 | #define DRM_MEM_SGLISTS 20 | 138 | #define DRM_MEM_SGLISTS 20 |
137 | #define DRM_MEM_CTXLIST 21 | 139 | #define DRM_MEM_CTXLIST 21 |
140 | #define DRM_MEM_MM 22 | ||
141 | #define DRM_MEM_HASHTAB 23 | ||
138 | 142 | ||
139 | #define DRM_MAX_CTXBITMAP (PAGE_SIZE * 8) | 143 | #define DRM_MAX_CTXBITMAP (PAGE_SIZE * 8) |
140 | 144 | #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 | 145 | ||
151 | /*@}*/ | 146 | /*@}*/ |
152 | 147 | ||
@@ -211,8 +206,6 @@ | |||
211 | /*@{*/ | 206 | /*@{*/ |
212 | 207 | ||
213 | #define DRM_ARRAY_SIZE(x) ARRAY_SIZE(x) | 208 | #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 | 209 | ||
217 | #define DRM_LEFTCOUNT(x) (((x)->rp + (x)->count - (x)->wp) % ((x)->count + 1)) | 210 | #define DRM_LEFTCOUNT(x) (((x)->rp + (x)->count - (x)->wp) % ((x)->count + 1)) |
218 | #define DRM_BUFCOUNT(x) ((x)->count - DRM_LEFTCOUNT(x)) | 211 | #define DRM_BUFCOUNT(x) ((x)->count - DRM_LEFTCOUNT(x)) |
@@ -286,7 +279,8 @@ typedef struct drm_devstate { | |||
286 | } drm_devstate_t; | 279 | } drm_devstate_t; |
287 | 280 | ||
288 | typedef struct drm_magic_entry { | 281 | typedef struct drm_magic_entry { |
289 | drm_magic_t magic; | 282 | drm_hash_item_t hash_item; |
283 | struct list_head head; | ||
290 | struct drm_file *priv; | 284 | struct drm_file *priv; |
291 | struct drm_magic_entry *next; | 285 | struct drm_magic_entry *next; |
292 | } drm_magic_entry_t; | 286 | } drm_magic_entry_t; |
@@ -437,7 +431,8 @@ typedef struct drm_device_dma { | |||
437 | enum { | 431 | enum { |
438 | _DRM_DMA_USE_AGP = 0x01, | 432 | _DRM_DMA_USE_AGP = 0x01, |
439 | _DRM_DMA_USE_SG = 0x02, | 433 | _DRM_DMA_USE_SG = 0x02, |
440 | _DRM_DMA_USE_FB = 0x04 | 434 | _DRM_DMA_USE_FB = 0x04, |
435 | _DRM_DMA_USE_PCI_RO = 0x08 | ||
441 | } flags; | 436 | } flags; |
442 | 437 | ||
443 | } drm_device_dma_t; | 438 | } drm_device_dma_t; |
@@ -493,6 +488,7 @@ typedef struct drm_sigdata { | |||
493 | */ | 488 | */ |
494 | typedef struct drm_map_list { | 489 | typedef struct drm_map_list { |
495 | struct list_head head; /**< list head */ | 490 | struct list_head head; /**< list head */ |
491 | drm_hash_item_t hash; | ||
496 | drm_map_t *map; /**< mapping */ | 492 | drm_map_t *map; /**< mapping */ |
497 | unsigned int user_token; | 493 | unsigned int user_token; |
498 | } drm_map_list_t; | 494 | } drm_map_list_t; |
@@ -527,6 +523,22 @@ typedef struct ati_pcigart_info { | |||
527 | drm_local_map_t mapping; | 523 | drm_local_map_t mapping; |
528 | } drm_ati_pcigart_info; | 524 | } drm_ati_pcigart_info; |
529 | 525 | ||
526 | /* | ||
527 | * Generic memory manager structs | ||
528 | */ | ||
529 | typedef struct drm_mm_node { | ||
530 | struct list_head fl_entry; | ||
531 | struct list_head ml_entry; | ||
532 | int free; | ||
533 | unsigned long start; | ||
534 | unsigned long size; | ||
535 | void *private; | ||
536 | } drm_mm_node_t; | ||
537 | |||
538 | typedef struct drm_mm { | ||
539 | drm_mm_node_t root_node; | ||
540 | } drm_mm_t; | ||
541 | |||
530 | /** | 542 | /** |
531 | * DRM driver structure. This structure represent the common code for | 543 | * DRM driver structure. This structure represent the common code for |
532 | * a family of cards. There will one drm_device for each card present | 544 | * a family of cards. There will one drm_device for each card present |
@@ -552,6 +564,7 @@ struct drm_driver { | |||
552 | void (*kernel_context_switch_unlock) (struct drm_device * dev, | 564 | void (*kernel_context_switch_unlock) (struct drm_device * dev, |
553 | drm_lock_t *lock); | 565 | drm_lock_t *lock); |
554 | int (*vblank_wait) (struct drm_device * dev, unsigned int *sequence); | 566 | int (*vblank_wait) (struct drm_device * dev, unsigned int *sequence); |
567 | int (*vblank_wait2) (struct drm_device * dev, unsigned int *sequence); | ||
555 | int (*dri_library_name) (struct drm_device *dev, char *buf); | 568 | int (*dri_library_name) (struct drm_device *dev, char *buf); |
556 | 569 | ||
557 | /** | 570 | /** |
@@ -646,13 +659,15 @@ typedef struct drm_device { | |||
646 | /*@{ */ | 659 | /*@{ */ |
647 | drm_file_t *file_first; /**< file list head */ | 660 | drm_file_t *file_first; /**< file list head */ |
648 | drm_file_t *file_last; /**< file list tail */ | 661 | drm_file_t *file_last; /**< file list tail */ |
649 | drm_magic_head_t magiclist[DRM_HASH_SIZE]; /**< magic hash table */ | 662 | drm_open_hash_t magiclist; /**< magic hash table */ |
663 | struct list_head magicfree; | ||
650 | /*@} */ | 664 | /*@} */ |
651 | 665 | ||
652 | /** \name Memory management */ | 666 | /** \name Memory management */ |
653 | /*@{ */ | 667 | /*@{ */ |
654 | drm_map_list_t *maplist; /**< Linked list of regions */ | 668 | drm_map_list_t *maplist; /**< Linked list of regions */ |
655 | int map_count; /**< Number of mappable regions */ | 669 | int map_count; /**< Number of mappable regions */ |
670 | drm_open_hash_t map_hash; /**< User token hash table for maps */ | ||
656 | 671 | ||
657 | /** \name Context handle management */ | 672 | /** \name Context handle management */ |
658 | /*@{ */ | 673 | /*@{ */ |
@@ -696,9 +711,13 @@ typedef struct drm_device { | |||
696 | 711 | ||
697 | wait_queue_head_t vbl_queue; /**< VBLANK wait queue */ | 712 | wait_queue_head_t vbl_queue; /**< VBLANK wait queue */ |
698 | atomic_t vbl_received; | 713 | atomic_t vbl_received; |
714 | atomic_t vbl_received2; /**< number of secondary VBLANK interrupts */ | ||
699 | spinlock_t vbl_lock; | 715 | spinlock_t vbl_lock; |
700 | drm_vbl_sig_t vbl_sigs; /**< signal list to send on VBLANK */ | 716 | drm_vbl_sig_t vbl_sigs; /**< signal list to send on VBLANK */ |
717 | drm_vbl_sig_t vbl_sigs2; /**< signals to send on secondary VBLANK */ | ||
701 | unsigned int vbl_pending; | 718 | unsigned int vbl_pending; |
719 | spinlock_t tasklet_lock; /**< For drm_locked_tasklet */ | ||
720 | void (*locked_tasklet_func)(struct drm_device *dev); | ||
702 | 721 | ||
703 | /*@} */ | 722 | /*@} */ |
704 | cycles_t ctx_start; | 723 | cycles_t ctx_start; |
@@ -711,10 +730,8 @@ typedef struct drm_device { | |||
711 | drm_agp_head_t *agp; /**< AGP data */ | 730 | drm_agp_head_t *agp; /**< AGP data */ |
712 | 731 | ||
713 | struct pci_dev *pdev; /**< PCI device structure */ | 732 | struct pci_dev *pdev; /**< PCI device structure */ |
714 | int pci_domain; /**< PCI bus domain number */ | 733 | int pci_vendor; /**< PCI vendor id */ |
715 | int pci_bus; /**< PCI bus number */ | 734 | int pci_device; /**< PCI device id */ |
716 | int pci_slot; /**< PCI slot number */ | ||
717 | int pci_func; /**< PCI function number */ | ||
718 | #ifdef __alpha__ | 735 | #ifdef __alpha__ |
719 | struct pci_controller *hose; | 736 | struct pci_controller *hose; |
720 | #endif | 737 | #endif |
@@ -728,6 +745,15 @@ typedef struct drm_device { | |||
728 | drm_local_map_t *agp_buffer_map; | 745 | drm_local_map_t *agp_buffer_map; |
729 | unsigned int agp_buffer_token; | 746 | unsigned int agp_buffer_token; |
730 | drm_head_t primary; /**< primary screen head */ | 747 | drm_head_t primary; /**< primary screen head */ |
748 | |||
749 | /** \name Drawable information */ | ||
750 | /*@{ */ | ||
751 | spinlock_t drw_lock; | ||
752 | unsigned int drw_bitfield_length; | ||
753 | u32 *drw_bitfield; | ||
754 | unsigned int drw_info_length; | ||
755 | drm_drawable_info_t **drw_info; | ||
756 | /*@} */ | ||
731 | } drm_device_t; | 757 | } drm_device_t; |
732 | 758 | ||
733 | static __inline__ int drm_core_check_feature(struct drm_device *dev, | 759 | static __inline__ int drm_core_check_feature(struct drm_device *dev, |
@@ -736,6 +762,12 @@ static __inline__ int drm_core_check_feature(struct drm_device *dev, | |||
736 | return ((dev->driver->driver_features & feature) ? 1 : 0); | 762 | return ((dev->driver->driver_features & feature) ? 1 : 0); |
737 | } | 763 | } |
738 | 764 | ||
765 | #ifdef __alpha__ | ||
766 | #define drm_get_pci_domain(dev) dev->hose->bus->number | ||
767 | #else | ||
768 | #define drm_get_pci_domain(dev) 0 | ||
769 | #endif | ||
770 | |||
739 | #if __OS_HAS_AGP | 771 | #if __OS_HAS_AGP |
740 | static inline int drm_core_has_AGP(struct drm_device *dev) | 772 | static inline int drm_core_has_AGP(struct drm_device *dev) |
741 | { | 773 | { |
@@ -869,6 +901,10 @@ extern int drm_adddraw(struct inode *inode, struct file *filp, | |||
869 | unsigned int cmd, unsigned long arg); | 901 | unsigned int cmd, unsigned long arg); |
870 | extern int drm_rmdraw(struct inode *inode, struct file *filp, | 902 | extern int drm_rmdraw(struct inode *inode, struct file *filp, |
871 | unsigned int cmd, unsigned long arg); | 903 | unsigned int cmd, unsigned long arg); |
904 | extern int drm_update_drawable_info(struct inode *inode, struct file *filp, | ||
905 | unsigned int cmd, unsigned long arg); | ||
906 | extern drm_drawable_info_t *drm_get_drawable_info(drm_device_t *dev, | ||
907 | drm_drawable_t id); | ||
872 | 908 | ||
873 | /* Authentication IOCTL support (drm_auth.h) */ | 909 | /* Authentication IOCTL support (drm_auth.h) */ |
874 | extern int drm_getmagic(struct inode *inode, struct file *filp, | 910 | extern int drm_getmagic(struct inode *inode, struct file *filp, |
@@ -933,6 +969,7 @@ extern int drm_wait_vblank(struct inode *inode, struct file *filp, | |||
933 | unsigned int cmd, unsigned long arg); | 969 | unsigned int cmd, unsigned long arg); |
934 | extern int drm_vblank_wait(drm_device_t * dev, unsigned int *vbl_seq); | 970 | extern int drm_vblank_wait(drm_device_t * dev, unsigned int *vbl_seq); |
935 | extern void drm_vbl_send_signals(drm_device_t * dev); | 971 | extern void drm_vbl_send_signals(drm_device_t * dev); |
972 | extern void drm_locked_tasklet(drm_device_t *dev, void(*func)(drm_device_t*)); | ||
936 | 973 | ||
937 | /* AGP/GART support (drm_agpsupport.h) */ | 974 | /* AGP/GART support (drm_agpsupport.h) */ |
938 | extern drm_agp_head_t *drm_agp_init(drm_device_t * dev); | 975 | extern drm_agp_head_t *drm_agp_init(drm_device_t * dev); |
@@ -1011,6 +1048,18 @@ extern struct class_device *drm_sysfs_device_add(struct class *cs, | |||
1011 | drm_head_t *head); | 1048 | drm_head_t *head); |
1012 | extern void drm_sysfs_device_remove(struct class_device *class_dev); | 1049 | extern void drm_sysfs_device_remove(struct class_device *class_dev); |
1013 | 1050 | ||
1051 | /* | ||
1052 | * Basic memory manager support (drm_mm.c) | ||
1053 | */ | ||
1054 | extern drm_mm_node_t *drm_mm_get_block(drm_mm_node_t * parent, | ||
1055 | unsigned long size, | ||
1056 | unsigned alignment); | ||
1057 | extern void drm_mm_put_block(drm_mm_t *mm, drm_mm_node_t *cur); | ||
1058 | extern drm_mm_node_t *drm_mm_search_free(const drm_mm_t *mm, unsigned long size, | ||
1059 | unsigned alignment, int best_match); | ||
1060 | extern int drm_mm_init(drm_mm_t *mm, unsigned long start, unsigned long size); | ||
1061 | extern void drm_mm_takedown(drm_mm_t *mm); | ||
1062 | |||
1014 | /* Inline replacements for DRM_IOREMAP macros */ | 1063 | /* Inline replacements for DRM_IOREMAP macros */ |
1015 | static __inline__ void drm_core_ioremap(struct drm_map *map, | 1064 | static __inline__ void drm_core_ioremap(struct drm_map *map, |
1016 | struct drm_device *dev) | 1065 | 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..9f65f5697ba8 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) |
@@ -249,6 +237,8 @@ static int drm_addmap_core(drm_device_t * dev, unsigned int offset, | |||
249 | 237 | ||
250 | list = drm_alloc(sizeof(*list), DRM_MEM_MAPS); | 238 | list = drm_alloc(sizeof(*list), DRM_MEM_MAPS); |
251 | if (!list) { | 239 | if (!list) { |
240 | if (map->type == _DRM_REGISTERS) | ||
241 | drm_ioremapfree(map->handle, map->size, dev); | ||
252 | drm_free(map, sizeof(*map), DRM_MEM_MAPS); | 242 | drm_free(map, sizeof(*map), DRM_MEM_MAPS); |
253 | return -EINVAL; | 243 | return -EINVAL; |
254 | } | 244 | } |
@@ -257,11 +247,22 @@ static int drm_addmap_core(drm_device_t * dev, unsigned int offset, | |||
257 | 247 | ||
258 | mutex_lock(&dev->struct_mutex); | 248 | mutex_lock(&dev->struct_mutex); |
259 | list_add(&list->head, &dev->maplist->head); | 249 | list_add(&list->head, &dev->maplist->head); |
250 | |||
260 | /* Assign a 32-bit handle */ | 251 | /* Assign a 32-bit handle */ |
261 | /* We do it here so that dev->struct_mutex protects the increment */ | 252 | /* We do it here so that dev->struct_mutex protects the increment */ |
262 | list->user_token = HandleID(map->type == _DRM_SHM | 253 | user_token = (map->type == _DRM_SHM) ? (unsigned long)map->handle : |
263 | ? (unsigned long)map->handle | 254 | map->offset; |
264 | : map->offset, dev); | 255 | ret = drm_map_handle(dev, &list->hash, user_token, 0); |
256 | if (ret) { | ||
257 | if (map->type == _DRM_REGISTERS) | ||
258 | drm_ioremapfree(map->handle, map->size, dev); | ||
259 | drm_free(map, sizeof(*map), DRM_MEM_MAPS); | ||
260 | drm_free(list, sizeof(*list), DRM_MEM_MAPS); | ||
261 | mutex_unlock(&dev->struct_mutex); | ||
262 | return ret; | ||
263 | } | ||
264 | |||
265 | list->user_token = list->hash.key; | ||
265 | mutex_unlock(&dev->struct_mutex); | 266 | mutex_unlock(&dev->struct_mutex); |
266 | 267 | ||
267 | *maplist = list; | 268 | *maplist = list; |
@@ -346,6 +347,7 @@ int drm_rmmap_locked(drm_device_t *dev, drm_local_map_t *map) | |||
346 | 347 | ||
347 | if (r_list->map == map) { | 348 | if (r_list->map == map) { |
348 | list_del(list); | 349 | list_del(list); |
350 | drm_ht_remove_key(&dev->map_hash, r_list->user_token); | ||
349 | drm_free(list, sizeof(*list), DRM_MEM_MAPS); | 351 | drm_free(list, sizeof(*list), DRM_MEM_MAPS); |
350 | break; | 352 | break; |
351 | } | 353 | } |
@@ -441,8 +443,10 @@ int drm_rmmap_ioctl(struct inode *inode, struct file *filp, | |||
441 | return -EINVAL; | 443 | return -EINVAL; |
442 | } | 444 | } |
443 | 445 | ||
444 | if (!map) | 446 | if (!map) { |
447 | mutex_unlock(&dev->struct_mutex); | ||
445 | return -EINVAL; | 448 | return -EINVAL; |
449 | } | ||
446 | 450 | ||
447 | /* Register and framebuffer maps are permanent */ | 451 | /* Register and framebuffer maps are permanent */ |
448 | if ((map->type == _DRM_REGISTERS) || (map->type == _DRM_FRAME_BUFFER)) { | 452 | if ((map->type == _DRM_REGISTERS) || (map->type == _DRM_FRAME_BUFFER)) { |
@@ -883,6 +887,9 @@ int drm_addbufs_pci(drm_device_t * dev, drm_buf_desc_t * request) | |||
883 | request->count = entry->buf_count; | 887 | request->count = entry->buf_count; |
884 | request->size = size; | 888 | request->size = size; |
885 | 889 | ||
890 | if (request->flags & _DRM_PCI_BUFFER_RO) | ||
891 | dma->flags = _DRM_DMA_USE_PCI_RO; | ||
892 | |||
886 | atomic_dec(&dev->buf_alloc); | 893 | atomic_dec(&dev->buf_alloc); |
887 | return 0; | 894 | return 0; |
888 | 895 | ||
@@ -1467,9 +1474,10 @@ int drm_freebufs(struct inode *inode, struct file *filp, | |||
1467 | * \param arg pointer to a drm_buf_map structure. | 1474 | * \param arg pointer to a drm_buf_map structure. |
1468 | * \return zero on success or a negative number on failure. | 1475 | * \return zero on success or a negative number on failure. |
1469 | * | 1476 | * |
1470 | * Maps the AGP or SG buffer region with do_mmap(), and copies information | 1477 | * Maps the AGP, SG or PCI buffer region with do_mmap(), and copies information |
1471 | * about each buffer into user space. The PCI buffers are already mapped on the | 1478 | * about each buffer into user space. For PCI buffers, it calls do_mmap() with |
1472 | * addbufs_pci() call. | 1479 | * offset equal to 0, which drm_mmap() interpretes as PCI buffers and calls |
1480 | * drm_mmap_dma(). | ||
1473 | */ | 1481 | */ |
1474 | int drm_mapbufs(struct inode *inode, struct file *filp, | 1482 | int drm_mapbufs(struct inode *inode, struct file *filp, |
1475 | unsigned int cmd, unsigned long arg) | 1483 | unsigned int cmd, unsigned long arg) |
diff --git a/drivers/char/drm/drm_core.h b/drivers/char/drm/drm_core.h index f4f9db6c7ed4..316739036079 100644 --- a/drivers/char/drm/drm_core.h +++ b/drivers/char/drm/drm_core.h | |||
@@ -24,11 +24,11 @@ | |||
24 | 24 | ||
25 | #define CORE_NAME "drm" | 25 | #define CORE_NAME "drm" |
26 | #define CORE_DESC "DRM shared core routines" | 26 | #define CORE_DESC "DRM shared core routines" |
27 | #define CORE_DATE "20051102" | 27 | #define CORE_DATE "20060810" |
28 | 28 | ||
29 | #define DRM_IF_MAJOR 1 | 29 | #define DRM_IF_MAJOR 1 |
30 | #define DRM_IF_MINOR 2 | 30 | #define DRM_IF_MINOR 3 |
31 | 31 | ||
32 | #define CORE_MAJOR 1 | 32 | #define CORE_MAJOR 1 |
33 | #define CORE_MINOR 0 | 33 | #define CORE_MINOR 1 |
34 | #define CORE_PATCHLEVEL 1 | 34 | #define CORE_PATCHLEVEL 0 |
diff --git a/drivers/char/drm/drm_drawable.c b/drivers/char/drm/drm_drawable.c index 7857453c4f48..de37d5f74563 100644 --- a/drivers/char/drm/drm_drawable.c +++ b/drivers/char/drm/drm_drawable.c | |||
@@ -4,6 +4,7 @@ | |||
4 | * | 4 | * |
5 | * \author Rickard E. (Rik) Faith <faith@valinux.com> | 5 | * \author Rickard E. (Rik) Faith <faith@valinux.com> |
6 | * \author Gareth Hughes <gareth@valinux.com> | 6 | * \author Gareth Hughes <gareth@valinux.com> |
7 | * \author Michel Dänzer <michel@tungstengraphics.com> | ||
7 | */ | 8 | */ |
8 | 9 | ||
9 | /* | 10 | /* |
@@ -11,6 +12,7 @@ | |||
11 | * | 12 | * |
12 | * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas. | 13 | * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas. |
13 | * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California. | 14 | * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California. |
15 | * Copyright 2006 Tungsten Graphics, Inc., Bismarck, North Dakota. | ||
14 | * All Rights Reserved. | 16 | * All Rights Reserved. |
15 | * | 17 | * |
16 | * Permission is hereby granted, free of charge, to any person obtaining a | 18 | * Permission is hereby granted, free of charge, to any person obtaining a |
@@ -35,22 +37,294 @@ | |||
35 | 37 | ||
36 | #include "drmP.h" | 38 | #include "drmP.h" |
37 | 39 | ||
38 | /** No-op. */ | 40 | /** |
39 | int drm_adddraw(struct inode *inode, struct file *filp, | 41 | * Allocate drawable ID and memory to store information about it. |
40 | unsigned int cmd, unsigned long arg) | 42 | */ |
43 | int drm_adddraw(DRM_IOCTL_ARGS) | ||
41 | { | 44 | { |
45 | DRM_DEVICE; | ||
46 | unsigned long irqflags; | ||
47 | int i, j; | ||
48 | u32 *bitfield = dev->drw_bitfield; | ||
49 | unsigned int bitfield_length = dev->drw_bitfield_length; | ||
50 | drm_drawable_info_t **info = dev->drw_info; | ||
51 | unsigned int info_length = dev->drw_info_length; | ||
42 | drm_draw_t draw; | 52 | drm_draw_t draw; |
43 | 53 | ||
44 | draw.handle = 0; /* NOOP */ | 54 | for (i = 0, j = 0; i < bitfield_length; i++) { |
55 | if (bitfield[i] == ~0) | ||
56 | continue; | ||
57 | |||
58 | for (; j < 8 * sizeof(*bitfield); j++) | ||
59 | if (!(bitfield[i] & (1 << j))) | ||
60 | goto done; | ||
61 | } | ||
62 | done: | ||
63 | |||
64 | if (i == bitfield_length) { | ||
65 | bitfield_length++; | ||
66 | |||
67 | bitfield = drm_alloc(bitfield_length * sizeof(*bitfield), | ||
68 | DRM_MEM_BUFS); | ||
69 | |||
70 | if (!bitfield) { | ||
71 | DRM_ERROR("Failed to allocate new drawable bitfield\n"); | ||
72 | return DRM_ERR(ENOMEM); | ||
73 | } | ||
74 | |||
75 | if (8 * sizeof(*bitfield) * bitfield_length > info_length) { | ||
76 | info_length += 8 * sizeof(*bitfield); | ||
77 | |||
78 | info = drm_alloc(info_length * sizeof(*info), | ||
79 | DRM_MEM_BUFS); | ||
80 | |||
81 | if (!info) { | ||
82 | DRM_ERROR("Failed to allocate new drawable info" | ||
83 | " array\n"); | ||
84 | |||
85 | drm_free(bitfield, | ||
86 | bitfield_length * sizeof(*bitfield), | ||
87 | DRM_MEM_BUFS); | ||
88 | return DRM_ERR(ENOMEM); | ||
89 | } | ||
90 | } | ||
91 | |||
92 | bitfield[i] = 0; | ||
93 | } | ||
94 | |||
95 | draw.handle = i * 8 * sizeof(*bitfield) + j + 1; | ||
45 | DRM_DEBUG("%d\n", draw.handle); | 96 | DRM_DEBUG("%d\n", draw.handle); |
46 | if (copy_to_user((drm_draw_t __user *) arg, &draw, sizeof(draw))) | 97 | |
47 | return -EFAULT; | 98 | spin_lock_irqsave(&dev->drw_lock, irqflags); |
99 | |||
100 | bitfield[i] |= 1 << j; | ||
101 | info[draw.handle - 1] = NULL; | ||
102 | |||
103 | if (bitfield != dev->drw_bitfield) { | ||
104 | memcpy(bitfield, dev->drw_bitfield, dev->drw_bitfield_length * | ||
105 | sizeof(*bitfield)); | ||
106 | drm_free(dev->drw_bitfield, sizeof(*bitfield) * | ||
107 | dev->drw_bitfield_length, DRM_MEM_BUFS); | ||
108 | dev->drw_bitfield = bitfield; | ||
109 | dev->drw_bitfield_length = bitfield_length; | ||
110 | } | ||
111 | |||
112 | if (info != dev->drw_info) { | ||
113 | memcpy(info, dev->drw_info, dev->drw_info_length * | ||
114 | sizeof(*info)); | ||
115 | drm_free(dev->drw_info, sizeof(*info) * dev->drw_info_length, | ||
116 | DRM_MEM_BUFS); | ||
117 | dev->drw_info = info; | ||
118 | dev->drw_info_length = info_length; | ||
119 | } | ||
120 | |||
121 | spin_unlock_irqrestore(&dev->drw_lock, irqflags); | ||
122 | |||
123 | DRM_COPY_TO_USER_IOCTL((drm_draw_t __user *)data, draw, sizeof(draw)); | ||
124 | |||
48 | return 0; | 125 | return 0; |
49 | } | 126 | } |
50 | 127 | ||
51 | /** No-op. */ | 128 | /** |
52 | int drm_rmdraw(struct inode *inode, struct file *filp, | 129 | * Free drawable ID and memory to store information about it. |
53 | unsigned int cmd, unsigned long arg) | 130 | */ |
131 | int drm_rmdraw(DRM_IOCTL_ARGS) | ||
54 | { | 132 | { |
55 | return 0; /* NOOP */ | 133 | DRM_DEVICE; |
134 | drm_draw_t draw; | ||
135 | int id, idx; | ||
136 | unsigned int shift; | ||
137 | unsigned long irqflags; | ||
138 | u32 *bitfield = dev->drw_bitfield; | ||
139 | unsigned int bitfield_length = dev->drw_bitfield_length; | ||
140 | drm_drawable_info_t **info = dev->drw_info; | ||
141 | unsigned int info_length = dev->drw_info_length; | ||
142 | |||
143 | DRM_COPY_FROM_USER_IOCTL(draw, (drm_draw_t __user *) data, | ||
144 | sizeof(draw)); | ||
145 | |||
146 | id = draw.handle - 1; | ||
147 | idx = id / (8 * sizeof(*bitfield)); | ||
148 | shift = id % (8 * sizeof(*bitfield)); | ||
149 | |||
150 | if (idx < 0 || idx >= bitfield_length || | ||
151 | !(bitfield[idx] & (1 << shift))) { | ||
152 | DRM_DEBUG("No such drawable %d\n", draw.handle); | ||
153 | return 0; | ||
154 | } | ||
155 | |||
156 | spin_lock_irqsave(&dev->drw_lock, irqflags); | ||
157 | |||
158 | bitfield[idx] &= ~(1 << shift); | ||
159 | |||
160 | spin_unlock_irqrestore(&dev->drw_lock, irqflags); | ||
161 | |||
162 | if (info[id]) { | ||
163 | drm_free(info[id]->rects, info[id]->num_rects * | ||
164 | sizeof(drm_clip_rect_t), DRM_MEM_BUFS); | ||
165 | drm_free(info[id], sizeof(**info), DRM_MEM_BUFS); | ||
166 | } | ||
167 | |||
168 | /* Can we shrink the arrays? */ | ||
169 | if (idx == bitfield_length - 1) { | ||
170 | while (idx >= 0 && !bitfield[idx]) | ||
171 | --idx; | ||
172 | |||
173 | bitfield_length = idx + 1; | ||
174 | |||
175 | if (idx != id / (8 * sizeof(*bitfield))) | ||
176 | bitfield = drm_alloc(bitfield_length * | ||
177 | sizeof(*bitfield), DRM_MEM_BUFS); | ||
178 | |||
179 | if (!bitfield && bitfield_length) { | ||
180 | bitfield = dev->drw_bitfield; | ||
181 | bitfield_length = dev->drw_bitfield_length; | ||
182 | } | ||
183 | } | ||
184 | |||
185 | if (bitfield != dev->drw_bitfield) { | ||
186 | info_length = 8 * sizeof(*bitfield) * bitfield_length; | ||
187 | |||
188 | info = drm_alloc(info_length * sizeof(*info), DRM_MEM_BUFS); | ||
189 | |||
190 | if (!info && info_length) { | ||
191 | info = dev->drw_info; | ||
192 | info_length = dev->drw_info_length; | ||
193 | } | ||
194 | |||
195 | spin_lock_irqsave(&dev->drw_lock, irqflags); | ||
196 | |||
197 | memcpy(bitfield, dev->drw_bitfield, bitfield_length * | ||
198 | sizeof(*bitfield)); | ||
199 | drm_free(dev->drw_bitfield, sizeof(*bitfield) * | ||
200 | dev->drw_bitfield_length, DRM_MEM_BUFS); | ||
201 | dev->drw_bitfield = bitfield; | ||
202 | dev->drw_bitfield_length = bitfield_length; | ||
203 | |||
204 | if (info != dev->drw_info) { | ||
205 | memcpy(info, dev->drw_info, info_length * | ||
206 | sizeof(*info)); | ||
207 | drm_free(dev->drw_info, sizeof(*info) * | ||
208 | dev->drw_info_length, DRM_MEM_BUFS); | ||
209 | dev->drw_info = info; | ||
210 | dev->drw_info_length = info_length; | ||
211 | } | ||
212 | |||
213 | spin_unlock_irqrestore(&dev->drw_lock, irqflags); | ||
214 | } | ||
215 | |||
216 | DRM_DEBUG("%d\n", draw.handle); | ||
217 | return 0; | ||
218 | } | ||
219 | |||
220 | int drm_update_drawable_info(DRM_IOCTL_ARGS) { | ||
221 | DRM_DEVICE; | ||
222 | drm_update_draw_t update; | ||
223 | unsigned int id, idx, shift; | ||
224 | u32 *bitfield = dev->drw_bitfield; | ||
225 | unsigned long irqflags, bitfield_length = dev->drw_bitfield_length; | ||
226 | drm_drawable_info_t *info; | ||
227 | drm_clip_rect_t *rects; | ||
228 | int err; | ||
229 | |||
230 | DRM_COPY_FROM_USER_IOCTL(update, (drm_update_draw_t __user *) data, | ||
231 | sizeof(update)); | ||
232 | |||
233 | id = update.handle - 1; | ||
234 | idx = id / (8 * sizeof(*bitfield)); | ||
235 | shift = id % (8 * sizeof(*bitfield)); | ||
236 | |||
237 | if (idx < 0 || idx >= bitfield_length || | ||
238 | !(bitfield[idx] & (1 << shift))) { | ||
239 | DRM_ERROR("No such drawable %d\n", update.handle); | ||
240 | return DRM_ERR(EINVAL); | ||
241 | } | ||
242 | |||
243 | info = dev->drw_info[id]; | ||
244 | |||
245 | if (!info) { | ||
246 | info = drm_calloc(1, sizeof(drm_drawable_info_t), DRM_MEM_BUFS); | ||
247 | |||
248 | if (!info) { | ||
249 | DRM_ERROR("Failed to allocate drawable info memory\n"); | ||
250 | return DRM_ERR(ENOMEM); | ||
251 | } | ||
252 | } | ||
253 | |||
254 | switch (update.type) { | ||
255 | case DRM_DRAWABLE_CLIPRECTS: | ||
256 | if (update.num != info->num_rects) { | ||
257 | rects = drm_alloc(update.num * sizeof(drm_clip_rect_t), | ||
258 | DRM_MEM_BUFS); | ||
259 | } else | ||
260 | rects = info->rects; | ||
261 | |||
262 | if (update.num && !rects) { | ||
263 | DRM_ERROR("Failed to allocate cliprect memory\n"); | ||
264 | err = DRM_ERR(ENOMEM); | ||
265 | goto error; | ||
266 | } | ||
267 | |||
268 | if (update.num && DRM_COPY_FROM_USER(rects, | ||
269 | (drm_clip_rect_t __user *) | ||
270 | (unsigned long)update.data, | ||
271 | update.num * | ||
272 | sizeof(*rects))) { | ||
273 | DRM_ERROR("Failed to copy cliprects from userspace\n"); | ||
274 | err = DRM_ERR(EFAULT); | ||
275 | goto error; | ||
276 | } | ||
277 | |||
278 | spin_lock_irqsave(&dev->drw_lock, irqflags); | ||
279 | |||
280 | if (rects != info->rects) { | ||
281 | drm_free(info->rects, info->num_rects * | ||
282 | sizeof(drm_clip_rect_t), DRM_MEM_BUFS); | ||
283 | } | ||
284 | |||
285 | info->rects = rects; | ||
286 | info->num_rects = update.num; | ||
287 | dev->drw_info[id] = info; | ||
288 | |||
289 | spin_unlock_irqrestore(&dev->drw_lock, irqflags); | ||
290 | |||
291 | DRM_DEBUG("Updated %d cliprects for drawable %d\n", | ||
292 | info->num_rects, id); | ||
293 | break; | ||
294 | default: | ||
295 | DRM_ERROR("Invalid update type %d\n", update.type); | ||
296 | return DRM_ERR(EINVAL); | ||
297 | } | ||
298 | |||
299 | return 0; | ||
300 | |||
301 | error: | ||
302 | if (!dev->drw_info[id]) | ||
303 | drm_free(info, sizeof(*info), DRM_MEM_BUFS); | ||
304 | else if (rects != dev->drw_info[id]->rects) | ||
305 | drm_free(rects, update.num * | ||
306 | sizeof(drm_clip_rect_t), DRM_MEM_BUFS); | ||
307 | |||
308 | return err; | ||
309 | } | ||
310 | |||
311 | /** | ||
312 | * Caller must hold the drawable spinlock! | ||
313 | */ | ||
314 | drm_drawable_info_t *drm_get_drawable_info(drm_device_t *dev, drm_drawable_t id) { | ||
315 | u32 *bitfield = dev->drw_bitfield; | ||
316 | unsigned int idx, shift; | ||
317 | |||
318 | id--; | ||
319 | idx = id / (8 * sizeof(*bitfield)); | ||
320 | shift = id % (8 * sizeof(*bitfield)); | ||
321 | |||
322 | if (idx < 0 || idx >= dev->drw_bitfield_length || | ||
323 | !(bitfield[idx] & (1 << shift))) { | ||
324 | DRM_DEBUG("No such drawable %d\n", id); | ||
325 | return NULL; | ||
326 | } | ||
327 | |||
328 | return dev->drw_info[id]; | ||
56 | } | 329 | } |
330 | EXPORT_SYMBOL(drm_get_drawable_info); | ||
diff --git a/drivers/char/drm/drm_drv.c b/drivers/char/drm/drm_drv.c index 3c0b882a8e72..a70af0de4453 100644 --- a/drivers/char/drm/drm_drv.c +++ b/drivers/char/drm/drm_drv.c | |||
@@ -116,9 +116,11 @@ static drm_ioctl_desc_t drm_ioctls[] = { | |||
116 | [DRM_IOCTL_NR(DRM_IOCTL_SG_FREE)] = {drm_sg_free, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY}, | 116 | [DRM_IOCTL_NR(DRM_IOCTL_SG_FREE)] = {drm_sg_free, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY}, |
117 | 117 | ||
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 | |||
120 | [DRM_IOCTL_NR(DRM_IOCTL_UPDATE_DRAW)] = {drm_update_drawable_info, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY}, | ||
119 | }; | 121 | }; |
120 | 122 | ||
121 | #define DRIVER_IOCTL_COUNT DRM_ARRAY_SIZE( drm_ioctls ) | 123 | #define DRIVER_IOCTL_COUNT ARRAY_SIZE( drm_ioctls ) |
122 | 124 | ||
123 | /** | 125 | /** |
124 | * Take down the DRM device. | 126 | * Take down the DRM device. |
@@ -151,16 +153,29 @@ int drm_lastclose(drm_device_t * dev) | |||
151 | if (dev->irq_enabled) | 153 | if (dev->irq_enabled) |
152 | drm_irq_uninstall(dev); | 154 | drm_irq_uninstall(dev); |
153 | 155 | ||
156 | /* Free drawable information memory */ | ||
157 | for (i = 0; i < dev->drw_bitfield_length / sizeof(*dev->drw_bitfield); | ||
158 | i++) { | ||
159 | drm_drawable_info_t *info = drm_get_drawable_info(dev, i); | ||
160 | |||
161 | if (info) { | ||
162 | drm_free(info->rects, info->num_rects * | ||
163 | sizeof(drm_clip_rect_t), DRM_MEM_BUFS); | ||
164 | drm_free(info, sizeof(*info), DRM_MEM_BUFS); | ||
165 | } | ||
166 | } | ||
167 | |||
154 | mutex_lock(&dev->struct_mutex); | 168 | mutex_lock(&dev->struct_mutex); |
155 | del_timer(&dev->timer); | 169 | del_timer(&dev->timer); |
156 | 170 | ||
157 | /* Clear pid list */ | 171 | /* Clear pid list */ |
158 | for (i = 0; i < DRM_HASH_SIZE; i++) { | 172 | if (dev->magicfree.next) { |
159 | for (pt = dev->magiclist[i].head; pt; pt = next) { | 173 | list_for_each_entry_safe(pt, next, &dev->magicfree, head) { |
160 | next = pt->next; | 174 | list_del(&pt->head); |
175 | drm_ht_remove_item(&dev->magiclist, &pt->hash_item); | ||
161 | drm_free(pt, sizeof(*pt), DRM_MEM_MAGIC); | 176 | drm_free(pt, sizeof(*pt), DRM_MEM_MAGIC); |
162 | } | 177 | } |
163 | dev->magiclist[i].head = dev->magiclist[i].tail = NULL; | 178 | drm_ht_remove(&dev->magiclist); |
164 | } | 179 | } |
165 | 180 | ||
166 | /* Clear AGP information */ | 181 | /* Clear AGP information */ |
@@ -299,6 +314,7 @@ static void drm_cleanup(drm_device_t * dev) | |||
299 | if (dev->maplist) { | 314 | if (dev->maplist) { |
300 | drm_free(dev->maplist, sizeof(*dev->maplist), DRM_MEM_MAPS); | 315 | drm_free(dev->maplist, sizeof(*dev->maplist), DRM_MEM_MAPS); |
301 | dev->maplist = NULL; | 316 | dev->maplist = NULL; |
317 | drm_ht_remove(&dev->map_hash); | ||
302 | } | 318 | } |
303 | 319 | ||
304 | drm_ctxbitmap_cleanup(dev); | 320 | 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..fafeb34f89d5 100644 --- a/drivers/char/drm/drm_ioc32.c +++ b/drivers/char/drm/drm_ioc32.c | |||
@@ -102,7 +102,7 @@ static int compat_drm_version(struct file *file, unsigned int cmd, | |||
102 | &version->desc)) | 102 | &version->desc)) |
103 | return -EFAULT; | 103 | return -EFAULT; |
104 | 104 | ||
105 | err = drm_ioctl(file->f_dentry->d_inode, file, | 105 | err = drm_ioctl(file->f_path.dentry->d_inode, file, |
106 | DRM_IOCTL_VERSION, (unsigned long)version); | 106 | DRM_IOCTL_VERSION, (unsigned long)version); |
107 | if (err) | 107 | if (err) |
108 | return err; | 108 | return err; |
@@ -143,7 +143,7 @@ static int compat_drm_getunique(struct file *file, unsigned int cmd, | |||
143 | &u->unique)) | 143 | &u->unique)) |
144 | return -EFAULT; | 144 | return -EFAULT; |
145 | 145 | ||
146 | err = drm_ioctl(file->f_dentry->d_inode, file, | 146 | err = drm_ioctl(file->f_path.dentry->d_inode, file, |
147 | DRM_IOCTL_GET_UNIQUE, (unsigned long)u); | 147 | DRM_IOCTL_GET_UNIQUE, (unsigned long)u); |
148 | if (err) | 148 | if (err) |
149 | return err; | 149 | return err; |
@@ -172,7 +172,7 @@ static int compat_drm_setunique(struct file *file, unsigned int cmd, | |||
172 | &u->unique)) | 172 | &u->unique)) |
173 | return -EFAULT; | 173 | return -EFAULT; |
174 | 174 | ||
175 | return drm_ioctl(file->f_dentry->d_inode, file, | 175 | return drm_ioctl(file->f_path.dentry->d_inode, file, |
176 | DRM_IOCTL_SET_UNIQUE, (unsigned long)u); | 176 | DRM_IOCTL_SET_UNIQUE, (unsigned long)u); |
177 | } | 177 | } |
178 | 178 | ||
@@ -203,7 +203,7 @@ static int compat_drm_getmap(struct file *file, unsigned int cmd, | |||
203 | if (__put_user(idx, &map->offset)) | 203 | if (__put_user(idx, &map->offset)) |
204 | return -EFAULT; | 204 | return -EFAULT; |
205 | 205 | ||
206 | err = drm_ioctl(file->f_dentry->d_inode, file, | 206 | err = drm_ioctl(file->f_path.dentry->d_inode, file, |
207 | DRM_IOCTL_GET_MAP, (unsigned long)map); | 207 | DRM_IOCTL_GET_MAP, (unsigned long)map); |
208 | if (err) | 208 | if (err) |
209 | return err; | 209 | return err; |
@@ -244,7 +244,7 @@ static int compat_drm_addmap(struct file *file, unsigned int cmd, | |||
244 | || __put_user(m32.flags, &map->flags)) | 244 | || __put_user(m32.flags, &map->flags)) |
245 | return -EFAULT; | 245 | return -EFAULT; |
246 | 246 | ||
247 | err = drm_ioctl(file->f_dentry->d_inode, file, | 247 | err = drm_ioctl(file->f_path.dentry->d_inode, file, |
248 | DRM_IOCTL_ADD_MAP, (unsigned long)map); | 248 | DRM_IOCTL_ADD_MAP, (unsigned long)map); |
249 | if (err) | 249 | if (err) |
250 | return err; | 250 | return err; |
@@ -282,7 +282,7 @@ static int compat_drm_rmmap(struct file *file, unsigned int cmd, | |||
282 | if (__put_user((void *)(unsigned long)handle, &map->handle)) | 282 | if (__put_user((void *)(unsigned long)handle, &map->handle)) |
283 | return -EFAULT; | 283 | return -EFAULT; |
284 | 284 | ||
285 | return drm_ioctl(file->f_dentry->d_inode, file, | 285 | return drm_ioctl(file->f_path.dentry->d_inode, file, |
286 | DRM_IOCTL_RM_MAP, (unsigned long)map); | 286 | DRM_IOCTL_RM_MAP, (unsigned long)map); |
287 | } | 287 | } |
288 | 288 | ||
@@ -312,7 +312,7 @@ static int compat_drm_getclient(struct file *file, unsigned int cmd, | |||
312 | if (__put_user(idx, &client->idx)) | 312 | if (__put_user(idx, &client->idx)) |
313 | return -EFAULT; | 313 | return -EFAULT; |
314 | 314 | ||
315 | err = drm_ioctl(file->f_dentry->d_inode, file, | 315 | err = drm_ioctl(file->f_path.dentry->d_inode, file, |
316 | DRM_IOCTL_GET_CLIENT, (unsigned long)client); | 316 | DRM_IOCTL_GET_CLIENT, (unsigned long)client); |
317 | if (err) | 317 | if (err) |
318 | return err; | 318 | return err; |
@@ -349,7 +349,7 @@ static int compat_drm_getstats(struct file *file, unsigned int cmd, | |||
349 | if (!access_ok(VERIFY_WRITE, stats, sizeof(*stats))) | 349 | if (!access_ok(VERIFY_WRITE, stats, sizeof(*stats))) |
350 | return -EFAULT; | 350 | return -EFAULT; |
351 | 351 | ||
352 | err = drm_ioctl(file->f_dentry->d_inode, file, | 352 | err = drm_ioctl(file->f_path.dentry->d_inode, file, |
353 | DRM_IOCTL_GET_STATS, (unsigned long)stats); | 353 | DRM_IOCTL_GET_STATS, (unsigned long)stats); |
354 | if (err) | 354 | if (err) |
355 | return err; | 355 | return err; |
@@ -393,7 +393,7 @@ static int compat_drm_addbufs(struct file *file, unsigned int cmd, | |||
393 | || __put_user(agp_start, &buf->agp_start)) | 393 | || __put_user(agp_start, &buf->agp_start)) |
394 | return -EFAULT; | 394 | return -EFAULT; |
395 | 395 | ||
396 | err = drm_ioctl(file->f_dentry->d_inode, file, | 396 | err = drm_ioctl(file->f_path.dentry->d_inode, file, |
397 | DRM_IOCTL_ADD_BUFS, (unsigned long)buf); | 397 | DRM_IOCTL_ADD_BUFS, (unsigned long)buf); |
398 | if (err) | 398 | if (err) |
399 | return err; | 399 | return err; |
@@ -425,7 +425,7 @@ static int compat_drm_markbufs(struct file *file, unsigned int cmd, | |||
425 | || __put_user(b32.high_mark, &buf->high_mark)) | 425 | || __put_user(b32.high_mark, &buf->high_mark)) |
426 | return -EFAULT; | 426 | return -EFAULT; |
427 | 427 | ||
428 | return drm_ioctl(file->f_dentry->d_inode, file, | 428 | return drm_ioctl(file->f_path.dentry->d_inode, file, |
429 | DRM_IOCTL_MARK_BUFS, (unsigned long)buf); | 429 | DRM_IOCTL_MARK_BUFS, (unsigned long)buf); |
430 | } | 430 | } |
431 | 431 | ||
@@ -467,7 +467,7 @@ static int compat_drm_infobufs(struct file *file, unsigned int cmd, | |||
467 | || __put_user(list, &request->list)) | 467 | || __put_user(list, &request->list)) |
468 | return -EFAULT; | 468 | return -EFAULT; |
469 | 469 | ||
470 | err = drm_ioctl(file->f_dentry->d_inode, file, | 470 | err = drm_ioctl(file->f_path.dentry->d_inode, file, |
471 | DRM_IOCTL_INFO_BUFS, (unsigned long)request); | 471 | DRM_IOCTL_INFO_BUFS, (unsigned long)request); |
472 | if (err) | 472 | if (err) |
473 | return err; | 473 | return err; |
@@ -529,7 +529,7 @@ static int compat_drm_mapbufs(struct file *file, unsigned int cmd, | |||
529 | || __put_user(list, &request->list)) | 529 | || __put_user(list, &request->list)) |
530 | return -EFAULT; | 530 | return -EFAULT; |
531 | 531 | ||
532 | err = drm_ioctl(file->f_dentry->d_inode, file, | 532 | err = drm_ioctl(file->f_path.dentry->d_inode, file, |
533 | DRM_IOCTL_MAP_BUFS, (unsigned long)request); | 533 | DRM_IOCTL_MAP_BUFS, (unsigned long)request); |
534 | if (err) | 534 | if (err) |
535 | return err; | 535 | return err; |
@@ -576,7 +576,7 @@ static int compat_drm_freebufs(struct file *file, unsigned int cmd, | |||
576 | &request->list)) | 576 | &request->list)) |
577 | return -EFAULT; | 577 | return -EFAULT; |
578 | 578 | ||
579 | return drm_ioctl(file->f_dentry->d_inode, file, | 579 | return drm_ioctl(file->f_path.dentry->d_inode, file, |
580 | DRM_IOCTL_FREE_BUFS, (unsigned long)request); | 580 | DRM_IOCTL_FREE_BUFS, (unsigned long)request); |
581 | } | 581 | } |
582 | 582 | ||
@@ -603,7 +603,7 @@ static int compat_drm_setsareactx(struct file *file, unsigned int cmd, | |||
603 | &request->handle)) | 603 | &request->handle)) |
604 | return -EFAULT; | 604 | return -EFAULT; |
605 | 605 | ||
606 | return drm_ioctl(file->f_dentry->d_inode, file, | 606 | return drm_ioctl(file->f_path.dentry->d_inode, file, |
607 | DRM_IOCTL_SET_SAREA_CTX, (unsigned long)request); | 607 | DRM_IOCTL_SET_SAREA_CTX, (unsigned long)request); |
608 | } | 608 | } |
609 | 609 | ||
@@ -626,7 +626,7 @@ static int compat_drm_getsareactx(struct file *file, unsigned int cmd, | |||
626 | if (__put_user(ctx_id, &request->ctx_id)) | 626 | if (__put_user(ctx_id, &request->ctx_id)) |
627 | return -EFAULT; | 627 | return -EFAULT; |
628 | 628 | ||
629 | err = drm_ioctl(file->f_dentry->d_inode, file, | 629 | err = drm_ioctl(file->f_path.dentry->d_inode, file, |
630 | DRM_IOCTL_GET_SAREA_CTX, (unsigned long)request); | 630 | DRM_IOCTL_GET_SAREA_CTX, (unsigned long)request); |
631 | if (err) | 631 | if (err) |
632 | return err; | 632 | return err; |
@@ -662,7 +662,7 @@ static int compat_drm_resctx(struct file *file, unsigned int cmd, | |||
662 | &res->contexts)) | 662 | &res->contexts)) |
663 | return -EFAULT; | 663 | return -EFAULT; |
664 | 664 | ||
665 | err = drm_ioctl(file->f_dentry->d_inode, file, | 665 | err = drm_ioctl(file->f_path.dentry->d_inode, file, |
666 | DRM_IOCTL_RES_CTX, (unsigned long)res); | 666 | DRM_IOCTL_RES_CTX, (unsigned long)res); |
667 | if (err) | 667 | if (err) |
668 | return err; | 668 | return err; |
@@ -716,7 +716,7 @@ static int compat_drm_dma(struct file *file, unsigned int cmd, | |||
716 | &d->request_sizes)) | 716 | &d->request_sizes)) |
717 | return -EFAULT; | 717 | return -EFAULT; |
718 | 718 | ||
719 | err = drm_ioctl(file->f_dentry->d_inode, file, | 719 | err = drm_ioctl(file->f_path.dentry->d_inode, file, |
720 | DRM_IOCTL_DMA, (unsigned long)d); | 720 | DRM_IOCTL_DMA, (unsigned long)d); |
721 | if (err) | 721 | if (err) |
722 | return err; | 722 | return err; |
@@ -749,7 +749,7 @@ static int compat_drm_agp_enable(struct file *file, unsigned int cmd, | |||
749 | if (put_user(m32.mode, &mode->mode)) | 749 | if (put_user(m32.mode, &mode->mode)) |
750 | return -EFAULT; | 750 | return -EFAULT; |
751 | 751 | ||
752 | return drm_ioctl(file->f_dentry->d_inode, file, | 752 | return drm_ioctl(file->f_path.dentry->d_inode, file, |
753 | DRM_IOCTL_AGP_ENABLE, (unsigned long)mode); | 753 | DRM_IOCTL_AGP_ENABLE, (unsigned long)mode); |
754 | } | 754 | } |
755 | 755 | ||
@@ -779,7 +779,7 @@ static int compat_drm_agp_info(struct file *file, unsigned int cmd, | |||
779 | if (!access_ok(VERIFY_WRITE, info, sizeof(*info))) | 779 | if (!access_ok(VERIFY_WRITE, info, sizeof(*info))) |
780 | return -EFAULT; | 780 | return -EFAULT; |
781 | 781 | ||
782 | err = drm_ioctl(file->f_dentry->d_inode, file, | 782 | err = drm_ioctl(file->f_path.dentry->d_inode, file, |
783 | DRM_IOCTL_AGP_INFO, (unsigned long)info); | 783 | DRM_IOCTL_AGP_INFO, (unsigned long)info); |
784 | if (err) | 784 | if (err) |
785 | return err; | 785 | return err; |
@@ -825,7 +825,7 @@ static int compat_drm_agp_alloc(struct file *file, unsigned int cmd, | |||
825 | || __put_user(req32.type, &request->type)) | 825 | || __put_user(req32.type, &request->type)) |
826 | return -EFAULT; | 826 | return -EFAULT; |
827 | 827 | ||
828 | err = drm_ioctl(file->f_dentry->d_inode, file, | 828 | err = drm_ioctl(file->f_path.dentry->d_inode, file, |
829 | DRM_IOCTL_AGP_ALLOC, (unsigned long)request); | 829 | DRM_IOCTL_AGP_ALLOC, (unsigned long)request); |
830 | if (err) | 830 | if (err) |
831 | return err; | 831 | return err; |
@@ -833,7 +833,7 @@ static int compat_drm_agp_alloc(struct file *file, unsigned int cmd, | |||
833 | if (__get_user(req32.handle, &request->handle) | 833 | if (__get_user(req32.handle, &request->handle) |
834 | || __get_user(req32.physical, &request->physical) | 834 | || __get_user(req32.physical, &request->physical) |
835 | || copy_to_user(argp, &req32, sizeof(req32))) { | 835 | || copy_to_user(argp, &req32, sizeof(req32))) { |
836 | drm_ioctl(file->f_dentry->d_inode, file, | 836 | drm_ioctl(file->f_path.dentry->d_inode, file, |
837 | DRM_IOCTL_AGP_FREE, (unsigned long)request); | 837 | DRM_IOCTL_AGP_FREE, (unsigned long)request); |
838 | return -EFAULT; | 838 | return -EFAULT; |
839 | } | 839 | } |
@@ -854,7 +854,7 @@ static int compat_drm_agp_free(struct file *file, unsigned int cmd, | |||
854 | || __put_user(handle, &request->handle)) | 854 | || __put_user(handle, &request->handle)) |
855 | return -EFAULT; | 855 | return -EFAULT; |
856 | 856 | ||
857 | return drm_ioctl(file->f_dentry->d_inode, file, | 857 | return drm_ioctl(file->f_path.dentry->d_inode, file, |
858 | DRM_IOCTL_AGP_FREE, (unsigned long)request); | 858 | DRM_IOCTL_AGP_FREE, (unsigned long)request); |
859 | } | 859 | } |
860 | 860 | ||
@@ -879,7 +879,7 @@ static int compat_drm_agp_bind(struct file *file, unsigned int cmd, | |||
879 | || __put_user(req32.offset, &request->offset)) | 879 | || __put_user(req32.offset, &request->offset)) |
880 | return -EFAULT; | 880 | return -EFAULT; |
881 | 881 | ||
882 | return drm_ioctl(file->f_dentry->d_inode, file, | 882 | return drm_ioctl(file->f_path.dentry->d_inode, file, |
883 | DRM_IOCTL_AGP_BIND, (unsigned long)request); | 883 | DRM_IOCTL_AGP_BIND, (unsigned long)request); |
884 | } | 884 | } |
885 | 885 | ||
@@ -896,7 +896,7 @@ static int compat_drm_agp_unbind(struct file *file, unsigned int cmd, | |||
896 | || __put_user(handle, &request->handle)) | 896 | || __put_user(handle, &request->handle)) |
897 | return -EFAULT; | 897 | return -EFAULT; |
898 | 898 | ||
899 | return drm_ioctl(file->f_dentry->d_inode, file, | 899 | return drm_ioctl(file->f_path.dentry->d_inode, file, |
900 | DRM_IOCTL_AGP_UNBIND, (unsigned long)request); | 900 | DRM_IOCTL_AGP_UNBIND, (unsigned long)request); |
901 | } | 901 | } |
902 | #endif /* __OS_HAS_AGP */ | 902 | #endif /* __OS_HAS_AGP */ |
@@ -921,7 +921,7 @@ static int compat_drm_sg_alloc(struct file *file, unsigned int cmd, | |||
921 | || __put_user(x, &request->size)) | 921 | || __put_user(x, &request->size)) |
922 | return -EFAULT; | 922 | return -EFAULT; |
923 | 923 | ||
924 | err = drm_ioctl(file->f_dentry->d_inode, file, | 924 | err = drm_ioctl(file->f_path.dentry->d_inode, file, |
925 | DRM_IOCTL_SG_ALLOC, (unsigned long)request); | 925 | DRM_IOCTL_SG_ALLOC, (unsigned long)request); |
926 | if (err) | 926 | if (err) |
927 | return err; | 927 | return err; |
@@ -948,7 +948,7 @@ static int compat_drm_sg_free(struct file *file, unsigned int cmd, | |||
948 | || __put_user(x << PAGE_SHIFT, &request->handle)) | 948 | || __put_user(x << PAGE_SHIFT, &request->handle)) |
949 | return -EFAULT; | 949 | return -EFAULT; |
950 | 950 | ||
951 | return drm_ioctl(file->f_dentry->d_inode, file, | 951 | return drm_ioctl(file->f_path.dentry->d_inode, file, |
952 | DRM_IOCTL_SG_FREE, (unsigned long)request); | 952 | DRM_IOCTL_SG_FREE, (unsigned long)request); |
953 | } | 953 | } |
954 | 954 | ||
@@ -988,7 +988,7 @@ static int compat_drm_wait_vblank(struct file *file, unsigned int cmd, | |||
988 | || __put_user(req32.request.signal, &request->request.signal)) | 988 | || __put_user(req32.request.signal, &request->request.signal)) |
989 | return -EFAULT; | 989 | return -EFAULT; |
990 | 990 | ||
991 | err = drm_ioctl(file->f_dentry->d_inode, file, | 991 | err = drm_ioctl(file->f_path.dentry->d_inode, file, |
992 | DRM_IOCTL_WAIT_VBLANK, (unsigned long)request); | 992 | DRM_IOCTL_WAIT_VBLANK, (unsigned long)request); |
993 | if (err) | 993 | if (err) |
994 | return err; | 994 | return err; |
@@ -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]; |
@@ -1060,7 +1060,7 @@ long drm_compat_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) | |||
1060 | if (fn != NULL) | 1060 | if (fn != NULL) |
1061 | ret = (*fn) (filp, cmd, arg); | 1061 | ret = (*fn) (filp, cmd, arg); |
1062 | else | 1062 | else |
1063 | ret = drm_ioctl(filp->f_dentry->d_inode, filp, cmd, arg); | 1063 | ret = drm_ioctl(filp->f_path.dentry->d_inode, filp, cmd, arg); |
1064 | unlock_kernel(); | 1064 | unlock_kernel(); |
1065 | 1065 | ||
1066 | return ret; | 1066 | return ret; |
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..9d00c51fe2c4 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; |
@@ -121,6 +121,7 @@ static int drm_irq_install(drm_device_t * dev) | |||
121 | spin_lock_init(&dev->vbl_lock); | 121 | spin_lock_init(&dev->vbl_lock); |
122 | 122 | ||
123 | INIT_LIST_HEAD(&dev->vbl_sigs.head); | 123 | INIT_LIST_HEAD(&dev->vbl_sigs.head); |
124 | INIT_LIST_HEAD(&dev->vbl_sigs2.head); | ||
124 | 125 | ||
125 | dev->vbl_pending = 0; | 126 | dev->vbl_pending = 0; |
126 | } | 127 | } |
@@ -175,6 +176,8 @@ int drm_irq_uninstall(drm_device_t * dev) | |||
175 | 176 | ||
176 | free_irq(dev->irq, dev); | 177 | free_irq(dev->irq, dev); |
177 | 178 | ||
179 | dev->locked_tasklet_func = NULL; | ||
180 | |||
178 | return 0; | 181 | return 0; |
179 | } | 182 | } |
180 | 183 | ||
@@ -247,19 +250,34 @@ int drm_wait_vblank(DRM_IOCTL_ARGS) | |||
247 | drm_wait_vblank_t vblwait; | 250 | drm_wait_vblank_t vblwait; |
248 | struct timeval now; | 251 | struct timeval now; |
249 | int ret = 0; | 252 | int ret = 0; |
250 | unsigned int flags; | 253 | unsigned int flags, seq; |
251 | 254 | ||
252 | if (!drm_core_check_feature(dev, DRIVER_IRQ_VBL)) | 255 | if (!dev->irq) |
253 | return -EINVAL; | 256 | return -EINVAL; |
254 | 257 | ||
255 | if (!dev->irq) | 258 | if (copy_from_user(&vblwait, argp, sizeof(vblwait))) |
259 | return -EFAULT; | ||
260 | |||
261 | if (vblwait.request.type & | ||
262 | ~(_DRM_VBLANK_TYPES_MASK | _DRM_VBLANK_FLAGS_MASK)) { | ||
263 | DRM_ERROR("Unsupported type value 0x%x, supported mask 0x%x\n", | ||
264 | vblwait.request.type, | ||
265 | (_DRM_VBLANK_TYPES_MASK | _DRM_VBLANK_FLAGS_MASK)); | ||
256 | return -EINVAL; | 266 | return -EINVAL; |
267 | } | ||
257 | 268 | ||
258 | DRM_COPY_FROM_USER_IOCTL(vblwait, argp, sizeof(vblwait)); | 269 | flags = vblwait.request.type & _DRM_VBLANK_FLAGS_MASK; |
259 | 270 | ||
260 | switch (vblwait.request.type & ~_DRM_VBLANK_FLAGS_MASK) { | 271 | if (!drm_core_check_feature(dev, (flags & _DRM_VBLANK_SECONDARY) ? |
272 | DRIVER_IRQ_VBL2 : DRIVER_IRQ_VBL)) | ||
273 | return -EINVAL; | ||
274 | |||
275 | seq = atomic_read((flags & _DRM_VBLANK_SECONDARY) ? &dev->vbl_received2 | ||
276 | : &dev->vbl_received); | ||
277 | |||
278 | switch (vblwait.request.type & _DRM_VBLANK_TYPES_MASK) { | ||
261 | case _DRM_VBLANK_RELATIVE: | 279 | case _DRM_VBLANK_RELATIVE: |
262 | vblwait.request.sequence += atomic_read(&dev->vbl_received); | 280 | vblwait.request.sequence += seq; |
263 | vblwait.request.type &= ~_DRM_VBLANK_RELATIVE; | 281 | vblwait.request.type &= ~_DRM_VBLANK_RELATIVE; |
264 | case _DRM_VBLANK_ABSOLUTE: | 282 | case _DRM_VBLANK_ABSOLUTE: |
265 | break; | 283 | break; |
@@ -267,26 +285,30 @@ int drm_wait_vblank(DRM_IOCTL_ARGS) | |||
267 | return -EINVAL; | 285 | return -EINVAL; |
268 | } | 286 | } |
269 | 287 | ||
270 | flags = vblwait.request.type & _DRM_VBLANK_FLAGS_MASK; | 288 | if ((flags & _DRM_VBLANK_NEXTONMISS) && |
289 | (seq - vblwait.request.sequence) <= (1<<23)) { | ||
290 | vblwait.request.sequence = seq + 1; | ||
291 | } | ||
271 | 292 | ||
272 | if (flags & _DRM_VBLANK_SIGNAL) { | 293 | if (flags & _DRM_VBLANK_SIGNAL) { |
273 | unsigned long irqflags; | 294 | unsigned long irqflags; |
295 | drm_vbl_sig_t *vbl_sigs = (flags & _DRM_VBLANK_SECONDARY) | ||
296 | ? &dev->vbl_sigs2 : &dev->vbl_sigs; | ||
274 | drm_vbl_sig_t *vbl_sig; | 297 | drm_vbl_sig_t *vbl_sig; |
275 | 298 | ||
276 | vblwait.reply.sequence = atomic_read(&dev->vbl_received); | ||
277 | |||
278 | spin_lock_irqsave(&dev->vbl_lock, irqflags); | 299 | spin_lock_irqsave(&dev->vbl_lock, irqflags); |
279 | 300 | ||
280 | /* Check if this task has already scheduled the same signal | 301 | /* Check if this task has already scheduled the same signal |
281 | * for the same vblank sequence number; nothing to be done in | 302 | * for the same vblank sequence number; nothing to be done in |
282 | * that case | 303 | * that case |
283 | */ | 304 | */ |
284 | list_for_each_entry(vbl_sig, &dev->vbl_sigs.head, head) { | 305 | list_for_each_entry(vbl_sig, &vbl_sigs->head, head) { |
285 | if (vbl_sig->sequence == vblwait.request.sequence | 306 | if (vbl_sig->sequence == vblwait.request.sequence |
286 | && vbl_sig->info.si_signo == vblwait.request.signal | 307 | && vbl_sig->info.si_signo == vblwait.request.signal |
287 | && vbl_sig->task == current) { | 308 | && vbl_sig->task == current) { |
288 | spin_unlock_irqrestore(&dev->vbl_lock, | 309 | spin_unlock_irqrestore(&dev->vbl_lock, |
289 | irqflags); | 310 | irqflags); |
311 | vblwait.reply.sequence = seq; | ||
290 | goto done; | 312 | goto done; |
291 | } | 313 | } |
292 | } | 314 | } |
@@ -314,11 +336,16 @@ int drm_wait_vblank(DRM_IOCTL_ARGS) | |||
314 | 336 | ||
315 | spin_lock_irqsave(&dev->vbl_lock, irqflags); | 337 | spin_lock_irqsave(&dev->vbl_lock, irqflags); |
316 | 338 | ||
317 | list_add_tail((struct list_head *)vbl_sig, &dev->vbl_sigs.head); | 339 | list_add_tail((struct list_head *)vbl_sig, &vbl_sigs->head); |
318 | 340 | ||
319 | spin_unlock_irqrestore(&dev->vbl_lock, irqflags); | 341 | spin_unlock_irqrestore(&dev->vbl_lock, irqflags); |
342 | |||
343 | vblwait.reply.sequence = seq; | ||
320 | } else { | 344 | } else { |
321 | if (dev->driver->vblank_wait) | 345 | if (flags & _DRM_VBLANK_SECONDARY) { |
346 | if (dev->driver->vblank_wait2) | ||
347 | ret = dev->driver->vblank_wait2(dev, &vblwait.request.sequence); | ||
348 | } else if (dev->driver->vblank_wait) | ||
322 | ret = | 349 | ret = |
323 | dev->driver->vblank_wait(dev, | 350 | dev->driver->vblank_wait(dev, |
324 | &vblwait.request.sequence); | 351 | &vblwait.request.sequence); |
@@ -329,7 +356,8 @@ int drm_wait_vblank(DRM_IOCTL_ARGS) | |||
329 | } | 356 | } |
330 | 357 | ||
331 | done: | 358 | done: |
332 | DRM_COPY_TO_USER_IOCTL(argp, vblwait, sizeof(vblwait)); | 359 | if (copy_to_user(argp, &vblwait, sizeof(vblwait))) |
360 | return -EFAULT; | ||
333 | 361 | ||
334 | return ret; | 362 | return ret; |
335 | } | 363 | } |
@@ -345,25 +373,32 @@ int drm_wait_vblank(DRM_IOCTL_ARGS) | |||
345 | */ | 373 | */ |
346 | void drm_vbl_send_signals(drm_device_t * dev) | 374 | void drm_vbl_send_signals(drm_device_t * dev) |
347 | { | 375 | { |
348 | struct list_head *list, *tmp; | ||
349 | drm_vbl_sig_t *vbl_sig; | ||
350 | unsigned int vbl_seq = atomic_read(&dev->vbl_received); | ||
351 | unsigned long flags; | 376 | unsigned long flags; |
377 | int i; | ||
352 | 378 | ||
353 | spin_lock_irqsave(&dev->vbl_lock, flags); | 379 | spin_lock_irqsave(&dev->vbl_lock, flags); |
354 | 380 | ||
355 | list_for_each_safe(list, tmp, &dev->vbl_sigs.head) { | 381 | for (i = 0; i < 2; i++) { |
356 | vbl_sig = list_entry(list, drm_vbl_sig_t, head); | 382 | struct list_head *list, *tmp; |
357 | if ((vbl_seq - vbl_sig->sequence) <= (1 << 23)) { | 383 | drm_vbl_sig_t *vbl_sig; |
358 | vbl_sig->info.si_code = vbl_seq; | 384 | drm_vbl_sig_t *vbl_sigs = i ? &dev->vbl_sigs2 : &dev->vbl_sigs; |
359 | send_sig_info(vbl_sig->info.si_signo, &vbl_sig->info, | 385 | unsigned int vbl_seq = atomic_read(i ? &dev->vbl_received2 : |
360 | vbl_sig->task); | 386 | &dev->vbl_received); |
387 | |||
388 | list_for_each_safe(list, tmp, &vbl_sigs->head) { | ||
389 | vbl_sig = list_entry(list, drm_vbl_sig_t, head); | ||
390 | if ((vbl_seq - vbl_sig->sequence) <= (1 << 23)) { | ||
391 | vbl_sig->info.si_code = vbl_seq; | ||
392 | send_sig_info(vbl_sig->info.si_signo, | ||
393 | &vbl_sig->info, vbl_sig->task); | ||
361 | 394 | ||
362 | list_del(list); | 395 | list_del(list); |
363 | 396 | ||
364 | drm_free(vbl_sig, sizeof(*vbl_sig), DRM_MEM_DRIVER); | 397 | drm_free(vbl_sig, sizeof(*vbl_sig), |
398 | DRM_MEM_DRIVER); | ||
365 | 399 | ||
366 | dev->vbl_pending--; | 400 | dev->vbl_pending--; |
401 | } | ||
367 | } | 402 | } |
368 | } | 403 | } |
369 | 404 | ||
@@ -371,3 +406,77 @@ void drm_vbl_send_signals(drm_device_t * dev) | |||
371 | } | 406 | } |
372 | 407 | ||
373 | EXPORT_SYMBOL(drm_vbl_send_signals); | 408 | EXPORT_SYMBOL(drm_vbl_send_signals); |
409 | |||
410 | /** | ||
411 | * Tasklet wrapper function. | ||
412 | * | ||
413 | * \param data DRM device in disguise. | ||
414 | * | ||
415 | * Attempts to grab the HW lock and calls the driver callback on success. On | ||
416 | * failure, leave the lock marked as contended so the callback can be called | ||
417 | * from drm_unlock(). | ||
418 | */ | ||
419 | static void drm_locked_tasklet_func(unsigned long data) | ||
420 | { | ||
421 | drm_device_t *dev = (drm_device_t*)data; | ||
422 | unsigned long irqflags; | ||
423 | |||
424 | spin_lock_irqsave(&dev->tasklet_lock, irqflags); | ||
425 | |||
426 | if (!dev->locked_tasklet_func || | ||
427 | !drm_lock_take(&dev->lock.hw_lock->lock, | ||
428 | DRM_KERNEL_CONTEXT)) { | ||
429 | spin_unlock_irqrestore(&dev->tasklet_lock, irqflags); | ||
430 | return; | ||
431 | } | ||
432 | |||
433 | dev->lock.lock_time = jiffies; | ||
434 | atomic_inc(&dev->counts[_DRM_STAT_LOCKS]); | ||
435 | |||
436 | dev->locked_tasklet_func(dev); | ||
437 | |||
438 | drm_lock_free(dev, &dev->lock.hw_lock->lock, | ||
439 | DRM_KERNEL_CONTEXT); | ||
440 | |||
441 | dev->locked_tasklet_func = NULL; | ||
442 | |||
443 | spin_unlock_irqrestore(&dev->tasklet_lock, irqflags); | ||
444 | } | ||
445 | |||
446 | /** | ||
447 | * Schedule a tasklet to call back a driver hook with the HW lock held. | ||
448 | * | ||
449 | * \param dev DRM device. | ||
450 | * \param func Driver callback. | ||
451 | * | ||
452 | * This is intended for triggering actions that require the HW lock from an | ||
453 | * interrupt handler. The lock will be grabbed ASAP after the interrupt handler | ||
454 | * completes. Note that the callback may be called from interrupt or process | ||
455 | * context, it must not make any assumptions about this. Also, the HW lock will | ||
456 | * be held with the kernel context or any client context. | ||
457 | */ | ||
458 | void drm_locked_tasklet(drm_device_t *dev, void (*func)(drm_device_t*)) | ||
459 | { | ||
460 | unsigned long irqflags; | ||
461 | static DECLARE_TASKLET(drm_tasklet, drm_locked_tasklet_func, 0); | ||
462 | |||
463 | if (!drm_core_check_feature(dev, DRIVER_HAVE_IRQ) || | ||
464 | test_bit(TASKLET_STATE_SCHED, &drm_tasklet.state)) | ||
465 | return; | ||
466 | |||
467 | spin_lock_irqsave(&dev->tasklet_lock, irqflags); | ||
468 | |||
469 | if (dev->locked_tasklet_func) { | ||
470 | spin_unlock_irqrestore(&dev->tasklet_lock, irqflags); | ||
471 | return; | ||
472 | } | ||
473 | |||
474 | dev->locked_tasklet_func = func; | ||
475 | |||
476 | spin_unlock_irqrestore(&dev->tasklet_lock, irqflags); | ||
477 | |||
478 | drm_tasklet.data = (unsigned long)dev; | ||
479 | |||
480 | tasklet_hi_schedule(&drm_tasklet); | ||
481 | } | ||
482 | EXPORT_SYMBOL(drm_locked_tasklet); | ||
diff --git a/drivers/char/drm/drm_lock.c b/drivers/char/drm/drm_lock.c index f9e45303498d..116ed0f2ac09 100644 --- a/drivers/char/drm/drm_lock.c +++ b/drivers/char/drm/drm_lock.c | |||
@@ -155,6 +155,7 @@ int drm_unlock(struct inode *inode, struct file *filp, | |||
155 | drm_file_t *priv = filp->private_data; | 155 | drm_file_t *priv = filp->private_data; |
156 | drm_device_t *dev = priv->head->dev; | 156 | drm_device_t *dev = priv->head->dev; |
157 | drm_lock_t lock; | 157 | drm_lock_t lock; |
158 | unsigned long irqflags; | ||
158 | 159 | ||
159 | if (copy_from_user(&lock, (drm_lock_t __user *) arg, sizeof(lock))) | 160 | if (copy_from_user(&lock, (drm_lock_t __user *) arg, sizeof(lock))) |
160 | return -EFAULT; | 161 | return -EFAULT; |
@@ -165,6 +166,16 @@ int drm_unlock(struct inode *inode, struct file *filp, | |||
165 | return -EINVAL; | 166 | return -EINVAL; |
166 | } | 167 | } |
167 | 168 | ||
169 | spin_lock_irqsave(&dev->tasklet_lock, irqflags); | ||
170 | |||
171 | if (dev->locked_tasklet_func) { | ||
172 | dev->locked_tasklet_func(dev); | ||
173 | |||
174 | dev->locked_tasklet_func = NULL; | ||
175 | } | ||
176 | |||
177 | spin_unlock_irqrestore(&dev->tasklet_lock, irqflags); | ||
178 | |||
168 | atomic_inc(&dev->counts[_DRM_STAT_UNLOCKS]); | 179 | atomic_inc(&dev->counts[_DRM_STAT_UNLOCKS]); |
169 | 180 | ||
170 | /* kernel_context_switch isn't used by any of the x86 drm | 181 | /* kernel_context_switch isn't used by any of the x86 drm |
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_os_linux.h b/drivers/char/drm/drm_os_linux.h index 695115d70382..2908b72daa6e 100644 --- a/drivers/char/drm/drm_os_linux.h +++ b/drivers/char/drm/drm_os_linux.h | |||
@@ -38,7 +38,7 @@ | |||
38 | drm_device_t *dev = priv->head->dev | 38 | drm_device_t *dev = priv->head->dev |
39 | 39 | ||
40 | /** IRQ handler arguments and return type and values */ | 40 | /** IRQ handler arguments and return type and values */ |
41 | #define DRM_IRQ_ARGS int irq, void *arg, struct pt_regs *regs | 41 | #define DRM_IRQ_ARGS int irq, void *arg |
42 | 42 | ||
43 | /** AGP types */ | 43 | /** AGP types */ |
44 | #if __OS_HAS_AGP | 44 | #if __OS_HAS_AGP |
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..19c81d2e13d0 --- /dev/null +++ b/drivers/char/drm/drm_sman.c | |||
@@ -0,0 +1,353 @@ | |||
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 | EXPORT_SYMBOL(drm_sman_set_manager); | ||
166 | |||
167 | static drm_owner_item_t *drm_sman_get_owner_item(drm_sman_t * sman, | ||
168 | unsigned long owner) | ||
169 | { | ||
170 | int ret; | ||
171 | drm_hash_item_t *owner_hash_item; | ||
172 | drm_owner_item_t *owner_item; | ||
173 | |||
174 | ret = drm_ht_find_item(&sman->owner_hash_tab, owner, &owner_hash_item); | ||
175 | if (!ret) { | ||
176 | return drm_hash_entry(owner_hash_item, drm_owner_item_t, | ||
177 | owner_hash); | ||
178 | } | ||
179 | |||
180 | owner_item = drm_calloc(1, sizeof(*owner_item), DRM_MEM_MM); | ||
181 | if (!owner_item) | ||
182 | goto out; | ||
183 | |||
184 | INIT_LIST_HEAD(&owner_item->mem_blocks); | ||
185 | owner_item->owner_hash.key = owner; | ||
186 | if (drm_ht_insert_item(&sman->owner_hash_tab, &owner_item->owner_hash)) | ||
187 | goto out1; | ||
188 | |||
189 | list_add_tail(&owner_item->sman_list, &sman->owner_items); | ||
190 | return owner_item; | ||
191 | |||
192 | out1: | ||
193 | drm_free(owner_item, sizeof(*owner_item), DRM_MEM_MM); | ||
194 | out: | ||
195 | return NULL; | ||
196 | } | ||
197 | |||
198 | drm_memblock_item_t *drm_sman_alloc(drm_sman_t *sman, unsigned int manager, | ||
199 | unsigned long size, unsigned alignment, | ||
200 | unsigned long owner) | ||
201 | { | ||
202 | void *tmp; | ||
203 | drm_sman_mm_t *sman_mm; | ||
204 | drm_owner_item_t *owner_item; | ||
205 | drm_memblock_item_t *memblock; | ||
206 | |||
207 | BUG_ON(manager >= sman->num_managers); | ||
208 | |||
209 | sman_mm = &sman->mm[manager]; | ||
210 | tmp = sman_mm->allocate(sman_mm->private, size, alignment); | ||
211 | |||
212 | if (!tmp) { | ||
213 | return NULL; | ||
214 | } | ||
215 | |||
216 | memblock = drm_calloc(1, sizeof(*memblock), DRM_MEM_MM); | ||
217 | |||
218 | if (!memblock) | ||
219 | goto out; | ||
220 | |||
221 | memblock->mm_info = tmp; | ||
222 | memblock->mm = sman_mm; | ||
223 | memblock->sman = sman; | ||
224 | |||
225 | if (drm_ht_just_insert_please | ||
226 | (&sman->user_hash_tab, &memblock->user_hash, | ||
227 | (unsigned long)memblock, 32, 0, 0)) | ||
228 | goto out1; | ||
229 | |||
230 | owner_item = drm_sman_get_owner_item(sman, owner); | ||
231 | if (!owner_item) | ||
232 | goto out2; | ||
233 | |||
234 | list_add_tail(&memblock->owner_list, &owner_item->mem_blocks); | ||
235 | |||
236 | return memblock; | ||
237 | |||
238 | out2: | ||
239 | drm_ht_remove_item(&sman->user_hash_tab, &memblock->user_hash); | ||
240 | out1: | ||
241 | drm_free(memblock, sizeof(*memblock), DRM_MEM_MM); | ||
242 | out: | ||
243 | sman_mm->free(sman_mm->private, tmp); | ||
244 | |||
245 | return NULL; | ||
246 | } | ||
247 | |||
248 | EXPORT_SYMBOL(drm_sman_alloc); | ||
249 | |||
250 | static void drm_sman_free(drm_memblock_item_t *item) | ||
251 | { | ||
252 | drm_sman_t *sman = item->sman; | ||
253 | |||
254 | list_del(&item->owner_list); | ||
255 | drm_ht_remove_item(&sman->user_hash_tab, &item->user_hash); | ||
256 | item->mm->free(item->mm->private, item->mm_info); | ||
257 | drm_free(item, sizeof(*item), DRM_MEM_MM); | ||
258 | } | ||
259 | |||
260 | int drm_sman_free_key(drm_sman_t *sman, unsigned int key) | ||
261 | { | ||
262 | drm_hash_item_t *hash_item; | ||
263 | drm_memblock_item_t *memblock_item; | ||
264 | |||
265 | if (drm_ht_find_item(&sman->user_hash_tab, key, &hash_item)) | ||
266 | return -EINVAL; | ||
267 | |||
268 | memblock_item = drm_hash_entry(hash_item, drm_memblock_item_t, user_hash); | ||
269 | drm_sman_free(memblock_item); | ||
270 | return 0; | ||
271 | } | ||
272 | |||
273 | EXPORT_SYMBOL(drm_sman_free_key); | ||
274 | |||
275 | static void drm_sman_remove_owner(drm_sman_t *sman, | ||
276 | drm_owner_item_t *owner_item) | ||
277 | { | ||
278 | list_del(&owner_item->sman_list); | ||
279 | drm_ht_remove_item(&sman->owner_hash_tab, &owner_item->owner_hash); | ||
280 | drm_free(owner_item, sizeof(*owner_item), DRM_MEM_MM); | ||
281 | } | ||
282 | |||
283 | int drm_sman_owner_clean(drm_sman_t *sman, unsigned long owner) | ||
284 | { | ||
285 | |||
286 | drm_hash_item_t *hash_item; | ||
287 | drm_owner_item_t *owner_item; | ||
288 | |||
289 | if (drm_ht_find_item(&sman->owner_hash_tab, owner, &hash_item)) { | ||
290 | return -1; | ||
291 | } | ||
292 | |||
293 | owner_item = drm_hash_entry(hash_item, drm_owner_item_t, owner_hash); | ||
294 | if (owner_item->mem_blocks.next == &owner_item->mem_blocks) { | ||
295 | drm_sman_remove_owner(sman, owner_item); | ||
296 | return -1; | ||
297 | } | ||
298 | |||
299 | return 0; | ||
300 | } | ||
301 | |||
302 | EXPORT_SYMBOL(drm_sman_owner_clean); | ||
303 | |||
304 | static void drm_sman_do_owner_cleanup(drm_sman_t *sman, | ||
305 | drm_owner_item_t *owner_item) | ||
306 | { | ||
307 | drm_memblock_item_t *entry, *next; | ||
308 | |||
309 | list_for_each_entry_safe(entry, next, &owner_item->mem_blocks, | ||
310 | owner_list) { | ||
311 | drm_sman_free(entry); | ||
312 | } | ||
313 | drm_sman_remove_owner(sman, owner_item); | ||
314 | } | ||
315 | |||
316 | void drm_sman_owner_cleanup(drm_sman_t *sman, unsigned long owner) | ||
317 | { | ||
318 | |||
319 | drm_hash_item_t *hash_item; | ||
320 | drm_owner_item_t *owner_item; | ||
321 | |||
322 | if (drm_ht_find_item(&sman->owner_hash_tab, owner, &hash_item)) { | ||
323 | |||
324 | return; | ||
325 | } | ||
326 | |||
327 | owner_item = drm_hash_entry(hash_item, drm_owner_item_t, owner_hash); | ||
328 | drm_sman_do_owner_cleanup(sman, owner_item); | ||
329 | } | ||
330 | |||
331 | EXPORT_SYMBOL(drm_sman_owner_cleanup); | ||
332 | |||
333 | void drm_sman_cleanup(drm_sman_t *sman) | ||
334 | { | ||
335 | drm_owner_item_t *entry, *next; | ||
336 | unsigned int i; | ||
337 | drm_sman_mm_t *sman_mm; | ||
338 | |||
339 | list_for_each_entry_safe(entry, next, &sman->owner_items, sman_list) { | ||
340 | drm_sman_do_owner_cleanup(sman, entry); | ||
341 | } | ||
342 | if (sman->mm) { | ||
343 | for (i = 0; i < sman->num_managers; ++i) { | ||
344 | sman_mm = &sman->mm[i]; | ||
345 | if (sman_mm->private) { | ||
346 | sman_mm->destroy(sman_mm->private); | ||
347 | sman_mm->private = NULL; | ||
348 | } | ||
349 | } | ||
350 | } | ||
351 | } | ||
352 | |||
353 | 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..5fd6dc0870cf 100644 --- a/drivers/char/drm/drm_stub.c +++ b/drivers/char/drm/drm_stub.c | |||
@@ -60,27 +60,29 @@ static int drm_fill_in_dev(drm_device_t * dev, struct pci_dev *pdev, | |||
60 | int retcode; | 60 | int retcode; |
61 | 61 | ||
62 | spin_lock_init(&dev->count_lock); | 62 | spin_lock_init(&dev->count_lock); |
63 | spin_lock_init(&dev->drw_lock); | ||
64 | spin_lock_init(&dev->tasklet_lock); | ||
63 | init_timer(&dev->timer); | 65 | init_timer(&dev->timer); |
64 | mutex_init(&dev->struct_mutex); | 66 | mutex_init(&dev->struct_mutex); |
65 | mutex_init(&dev->ctxlist_mutex); | 67 | mutex_init(&dev->ctxlist_mutex); |
66 | 68 | ||
67 | dev->pdev = pdev; | 69 | dev->pdev = pdev; |
70 | dev->pci_device = pdev->device; | ||
71 | dev->pci_vendor = pdev->vendor; | ||
68 | 72 | ||
69 | #ifdef __alpha__ | 73 | #ifdef __alpha__ |
70 | dev->hose = pdev->sysdata; | 74 | dev->hose = pdev->sysdata; |
71 | dev->pci_domain = dev->hose->bus->number; | ||
72 | #else | ||
73 | dev->pci_domain = 0; | ||
74 | #endif | 75 | #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; | 76 | dev->irq = pdev->irq; |
79 | 77 | ||
80 | dev->maplist = drm_calloc(1, sizeof(*dev->maplist), DRM_MEM_MAPS); | 78 | dev->maplist = drm_calloc(1, sizeof(*dev->maplist), DRM_MEM_MAPS); |
81 | if (dev->maplist == NULL) | 79 | if (dev->maplist == NULL) |
82 | return -ENOMEM; | 80 | return -ENOMEM; |
83 | INIT_LIST_HEAD(&dev->maplist->head); | 81 | INIT_LIST_HEAD(&dev->maplist->head); |
82 | if (drm_ht_create(&dev->map_hash, 12)) { | ||
83 | drm_free(dev->maplist, sizeof(*dev->maplist), DRM_MEM_MAPS); | ||
84 | return -ENOMEM; | ||
85 | } | ||
84 | 86 | ||
85 | /* the DRM has 6 basic counters */ | 87 | /* the DRM has 6 basic counters */ |
86 | dev->counters = 6; | 88 | dev->counters = 6; |
diff --git a/drivers/char/drm/drm_sysfs.c b/drivers/char/drm/drm_sysfs.c index 51ad98c685c3..ba4b8de83cf0 100644 --- a/drivers/char/drm/drm_sysfs.c +++ b/drivers/char/drm/drm_sysfs.c | |||
@@ -42,13 +42,24 @@ static CLASS_ATTR(version, S_IRUGO, version_show, NULL); | |||
42 | struct class *drm_sysfs_create(struct module *owner, char *name) | 42 | struct class *drm_sysfs_create(struct module *owner, char *name) |
43 | { | 43 | { |
44 | struct class *class; | 44 | struct class *class; |
45 | int err; | ||
45 | 46 | ||
46 | class = class_create(owner, name); | 47 | class = class_create(owner, name); |
47 | if (!class) | 48 | if (!class) { |
48 | return class; | 49 | err = -ENOMEM; |
50 | goto err_out; | ||
51 | } | ||
52 | |||
53 | err = class_create_file(class, &class_attr_version); | ||
54 | if (err) | ||
55 | goto err_out_class; | ||
49 | 56 | ||
50 | class_create_file(class, &class_attr_version); | ||
51 | return class; | 57 | return class; |
58 | |||
59 | err_out_class: | ||
60 | class_destroy(class); | ||
61 | err_out: | ||
62 | return ERR_PTR(err); | ||
52 | } | 63 | } |
53 | 64 | ||
54 | /** | 65 | /** |
@@ -96,20 +107,36 @@ static struct class_device_attribute class_device_attrs[] = { | |||
96 | struct class_device *drm_sysfs_device_add(struct class *cs, drm_head_t *head) | 107 | struct class_device *drm_sysfs_device_add(struct class *cs, drm_head_t *head) |
97 | { | 108 | { |
98 | struct class_device *class_dev; | 109 | struct class_device *class_dev; |
99 | int i; | 110 | int i, j, err; |
100 | 111 | ||
101 | class_dev = class_device_create(cs, NULL, | 112 | class_dev = class_device_create(cs, NULL, |
102 | MKDEV(DRM_MAJOR, head->minor), | 113 | MKDEV(DRM_MAJOR, head->minor), |
103 | &(head->dev->pdev)->dev, | 114 | &(head->dev->pdev)->dev, |
104 | "card%d", head->minor); | 115 | "card%d", head->minor); |
105 | if (!class_dev) | 116 | if (!class_dev) { |
106 | return NULL; | 117 | err = -ENOMEM; |
118 | goto err_out; | ||
119 | } | ||
107 | 120 | ||
108 | class_set_devdata(class_dev, head); | 121 | class_set_devdata(class_dev, head); |
109 | 122 | ||
110 | for (i = 0; i < ARRAY_SIZE(class_device_attrs); i++) | 123 | for (i = 0; i < ARRAY_SIZE(class_device_attrs); i++) { |
111 | class_device_create_file(class_dev, &class_device_attrs[i]); | 124 | err = class_device_create_file(class_dev, |
125 | &class_device_attrs[i]); | ||
126 | if (err) | ||
127 | goto err_out_files; | ||
128 | } | ||
129 | |||
112 | return class_dev; | 130 | return class_dev; |
131 | |||
132 | err_out_files: | ||
133 | if (i > 0) | ||
134 | for (j = 0; j < i; j++) | ||
135 | class_device_remove_file(class_dev, | ||
136 | &class_device_attrs[i]); | ||
137 | class_device_unregister(class_dev); | ||
138 | err_out: | ||
139 | return ERR_PTR(err); | ||
113 | } | 140 | } |
114 | 141 | ||
115 | /** | 142 | /** |
diff --git a/drivers/char/drm/drm_vm.c b/drivers/char/drm/drm_vm.c index ffd0800ed601..b9cfc077f6bc 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; |
@@ -150,14 +147,14 @@ static __inline__ struct page *drm_do_vm_shm_nopage(struct vm_area_struct *vma, | |||
150 | if (address > vma->vm_end) | 147 | if (address > vma->vm_end) |
151 | return NOPAGE_SIGBUS; /* Disallow mremap */ | 148 | return NOPAGE_SIGBUS; /* Disallow mremap */ |
152 | if (!map) | 149 | if (!map) |
153 | return NOPAGE_OOM; /* Nothing allocated */ | 150 | return NOPAGE_SIGBUS; /* Nothing allocated */ |
154 | 151 | ||
155 | offset = address - vma->vm_start; | 152 | offset = address - vma->vm_start; |
156 | i = (unsigned long)map->handle + offset; | 153 | i = (unsigned long)map->handle + offset; |
157 | page = (map->type == _DRM_CONSISTENT) ? | 154 | page = (map->type == _DRM_CONSISTENT) ? |
158 | virt_to_page((void *)i) : vmalloc_to_page((void *)i); | 155 | virt_to_page((void *)i) : vmalloc_to_page((void *)i); |
159 | if (!page) | 156 | if (!page) |
160 | return NOPAGE_OOM; | 157 | return NOPAGE_SIGBUS; |
161 | get_page(page); | 158 | get_page(page); |
162 | 159 | ||
163 | DRM_DEBUG("shm_nopage 0x%lx\n", address); | 160 | DRM_DEBUG("shm_nopage 0x%lx\n", address); |
@@ -275,7 +272,7 @@ static __inline__ struct page *drm_do_vm_dma_nopage(struct vm_area_struct *vma, | |||
275 | if (address > vma->vm_end) | 272 | if (address > vma->vm_end) |
276 | return NOPAGE_SIGBUS; /* Disallow mremap */ | 273 | return NOPAGE_SIGBUS; /* Disallow mremap */ |
277 | if (!dma->pagelist) | 274 | if (!dma->pagelist) |
278 | return NOPAGE_OOM; /* Nothing allocated */ | 275 | return NOPAGE_SIGBUS; /* Nothing allocated */ |
279 | 276 | ||
280 | offset = address - vma->vm_start; /* vm_[pg]off[set] should be 0 */ | 277 | offset = address - vma->vm_start; /* vm_[pg]off[set] should be 0 */ |
281 | page_nr = offset >> PAGE_SHIFT; | 278 | page_nr = offset >> PAGE_SHIFT; |
@@ -313,7 +310,7 @@ static __inline__ struct page *drm_do_vm_sg_nopage(struct vm_area_struct *vma, | |||
313 | if (address > vma->vm_end) | 310 | if (address > vma->vm_end) |
314 | return NOPAGE_SIGBUS; /* Disallow mremap */ | 311 | return NOPAGE_SIGBUS; /* Disallow mremap */ |
315 | if (!entry->pagelist) | 312 | if (!entry->pagelist) |
316 | return NOPAGE_OOM; /* Nothing allocated */ | 313 | return NOPAGE_SIGBUS; /* Nothing allocated */ |
317 | 314 | ||
318 | offset = address - vma->vm_start; | 315 | offset = address - vma->vm_start; |
319 | map_offset = map->offset - (unsigned long)dev->sg->virtual; | 316 | map_offset = map->offset - (unsigned long)dev->sg->virtual; |
@@ -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) { |
@@ -476,6 +473,22 @@ static int drm_mmap_dma(struct file *filp, struct vm_area_struct *vma) | |||
476 | } | 473 | } |
477 | unlock_kernel(); | 474 | unlock_kernel(); |
478 | 475 | ||
476 | if (!capable(CAP_SYS_ADMIN) && | ||
477 | (dma->flags & _DRM_DMA_USE_PCI_RO)) { | ||
478 | vma->vm_flags &= ~(VM_WRITE | VM_MAYWRITE); | ||
479 | #if defined(__i386__) || defined(__x86_64__) | ||
480 | pgprot_val(vma->vm_page_prot) &= ~_PAGE_RW; | ||
481 | #else | ||
482 | /* Ye gads this is ugly. With more thought | ||
483 | we could move this up higher and use | ||
484 | `protection_map' instead. */ | ||
485 | vma->vm_page_prot = | ||
486 | __pgprot(pte_val | ||
487 | (pte_wrprotect | ||
488 | (__pte(pgprot_val(vma->vm_page_prot))))); | ||
489 | #endif | ||
490 | } | ||
491 | |||
479 | vma->vm_ops = &drm_vm_dma_ops; | 492 | vma->vm_ops = &drm_vm_dma_ops; |
480 | 493 | ||
481 | vma->vm_flags |= VM_RESERVED; /* Don't swap */ | 494 | vma->vm_flags |= VM_RESERVED; /* Don't swap */ |
@@ -521,12 +534,11 @@ int drm_mmap(struct file *filp, struct vm_area_struct *vma) | |||
521 | drm_file_t *priv = filp->private_data; | 534 | drm_file_t *priv = filp->private_data; |
522 | drm_device_t *dev = priv->head->dev; | 535 | drm_device_t *dev = priv->head->dev; |
523 | drm_map_t *map = NULL; | 536 | drm_map_t *map = NULL; |
524 | drm_map_list_t *r_list; | ||
525 | unsigned long offset = 0; | 537 | unsigned long offset = 0; |
526 | struct list_head *list; | 538 | drm_hash_item_t *hash; |
527 | 539 | ||
528 | DRM_DEBUG("start = 0x%lx, end = 0x%lx, offset = 0x%lx\n", | 540 | DRM_DEBUG("start = 0x%lx, end = 0x%lx, offset = 0x%lx\n", |
529 | vma->vm_start, vma->vm_end, VM_OFFSET(vma)); | 541 | vma->vm_start, vma->vm_end, vma->vm_pgoff << PAGE_SHIFT); |
530 | 542 | ||
531 | if (!priv->authenticated) | 543 | if (!priv->authenticated) |
532 | return -EACCES; | 544 | return -EACCES; |
@@ -535,7 +547,7 @@ int drm_mmap(struct file *filp, struct vm_area_struct *vma) | |||
535 | * the AGP mapped at physical address 0 | 547 | * the AGP mapped at physical address 0 |
536 | * --BenH. | 548 | * --BenH. |
537 | */ | 549 | */ |
538 | if (!VM_OFFSET(vma) | 550 | if (!(vma->vm_pgoff << PAGE_SHIFT) |
539 | #if __OS_HAS_AGP | 551 | #if __OS_HAS_AGP |
540 | && (!dev->agp | 552 | && (!dev->agp |
541 | || dev->agp->agp_info.device->vendor != PCI_VENDOR_ID_APPLE) | 553 | || dev->agp->agp_info.device->vendor != PCI_VENDOR_ID_APPLE) |
@@ -543,23 +555,12 @@ int drm_mmap(struct file *filp, struct vm_area_struct *vma) | |||
543 | ) | 555 | ) |
544 | return drm_mmap_dma(filp, vma); | 556 | return drm_mmap_dma(filp, vma); |
545 | 557 | ||
546 | /* A sequential search of a linked list is | 558 | if (drm_ht_find_item(&dev->map_hash, vma->vm_pgoff << PAGE_SHIFT, &hash)) { |
547 | fine here because: 1) there will only be | 559 | DRM_ERROR("Could not find map\n"); |
548 | about 5-10 entries in the list and, 2) a | 560 | 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 | } | 561 | } |
562 | 562 | ||
563 | map = drm_hash_entry(hash, drm_map_list_t, hash)->map; | ||
563 | if (!map || ((map->flags & _DRM_RESTRICTED) && !capable(CAP_SYS_ADMIN))) | 564 | if (!map || ((map->flags & _DRM_RESTRICTED) && !capable(CAP_SYS_ADMIN))) |
564 | return -EPERM; | 565 | return -EPERM; |
565 | 566 | ||
@@ -620,7 +621,7 @@ int drm_mmap(struct file *filp, struct vm_area_struct *vma) | |||
620 | offset = dev->driver->get_reg_ofs(dev); | 621 | offset = dev->driver->get_reg_ofs(dev); |
621 | #ifdef __sparc__ | 622 | #ifdef __sparc__ |
622 | vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); | 623 | vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); |
623 | if (io_remap_pfn_range(DRM_RPR_ARG(vma) vma->vm_start, | 624 | if (io_remap_pfn_range(vma, vma->vm_start, |
624 | (map->offset + offset) >> PAGE_SHIFT, | 625 | (map->offset + offset) >> PAGE_SHIFT, |
625 | vma->vm_end - vma->vm_start, | 626 | vma->vm_end - vma->vm_start, |
626 | vma->vm_page_prot)) | 627 | 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..9354ce3b0093 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 |
@@ -157,6 +162,7 @@ static int i915_initialize(drm_device_t * dev, | |||
157 | 162 | ||
158 | dev_priv->ring.virtual_start = dev_priv->ring.map.handle; | 163 | dev_priv->ring.virtual_start = dev_priv->ring.map.handle; |
159 | 164 | ||
165 | dev_priv->cpp = init->cpp; | ||
160 | dev_priv->back_offset = init->back_offset; | 166 | dev_priv->back_offset = init->back_offset; |
161 | dev_priv->front_offset = init->front_offset; | 167 | dev_priv->front_offset = init->front_offset; |
162 | dev_priv->current_page = 0; | 168 | dev_priv->current_page = 0; |
@@ -255,7 +261,7 @@ static int i915_dma_init(DRM_IOCTL_ARGS) | |||
255 | retcode = i915_dma_resume(dev); | 261 | retcode = i915_dma_resume(dev); |
256 | break; | 262 | break; |
257 | default: | 263 | default: |
258 | retcode = -EINVAL; | 264 | retcode = DRM_ERR(EINVAL); |
259 | break; | 265 | break; |
260 | } | 266 | } |
261 | 267 | ||
@@ -347,7 +353,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) | 353 | if ((dwords+1) * sizeof(int) >= dev_priv->ring.Size - 8) |
348 | return DRM_ERR(EINVAL); | 354 | return DRM_ERR(EINVAL); |
349 | 355 | ||
350 | BEGIN_LP_RING(((dwords+1)&~1)); | 356 | BEGIN_LP_RING((dwords+1)&~1); |
351 | 357 | ||
352 | for (i = 0; i < dwords;) { | 358 | for (i = 0; i < dwords;) { |
353 | int cmd, sz; | 359 | int cmd, sz; |
@@ -386,7 +392,7 @@ static int i915_emit_box(drm_device_t * dev, | |||
386 | RING_LOCALS; | 392 | RING_LOCALS; |
387 | 393 | ||
388 | if (DRM_COPY_FROM_USER_UNCHECKED(&box, &boxes[i], sizeof(box))) { | 394 | if (DRM_COPY_FROM_USER_UNCHECKED(&box, &boxes[i], sizeof(box))) { |
389 | return EFAULT; | 395 | return DRM_ERR(EFAULT); |
390 | } | 396 | } |
391 | 397 | ||
392 | if (box.y2 <= box.y1 || box.x2 <= box.x1 || box.y2 <= 0 || box.x2 <= 0) { | 398 | if (box.y2 <= box.y1 || box.x2 <= box.x1 || box.y2 <= 0 || box.x2 <= 0) { |
@@ -395,24 +401,40 @@ static int i915_emit_box(drm_device_t * dev, | |||
395 | return DRM_ERR(EINVAL); | 401 | return DRM_ERR(EINVAL); |
396 | } | 402 | } |
397 | 403 | ||
398 | BEGIN_LP_RING(6); | 404 | if (IS_I965G(dev)) { |
399 | OUT_RING(GFX_OP_DRAWRECT_INFO); | 405 | BEGIN_LP_RING(4); |
400 | OUT_RING(DR1); | 406 | OUT_RING(GFX_OP_DRAWRECT_INFO_I965); |
401 | OUT_RING((box.x1 & 0xffff) | (box.y1 << 16)); | 407 | OUT_RING((box.x1 & 0xffff) | (box.y1 << 16)); |
402 | OUT_RING(((box.x2 - 1) & 0xffff) | ((box.y2 - 1) << 16)); | 408 | OUT_RING(((box.x2 - 1) & 0xffff) | ((box.y2 - 1) << 16)); |
403 | OUT_RING(DR4); | 409 | OUT_RING(DR4); |
404 | OUT_RING(0); | 410 | ADVANCE_LP_RING(); |
405 | ADVANCE_LP_RING(); | 411 | } else { |
412 | BEGIN_LP_RING(6); | ||
413 | OUT_RING(GFX_OP_DRAWRECT_INFO); | ||
414 | OUT_RING(DR1); | ||
415 | OUT_RING((box.x1 & 0xffff) | (box.y1 << 16)); | ||
416 | OUT_RING(((box.x2 - 1) & 0xffff) | ((box.y2 - 1) << 16)); | ||
417 | OUT_RING(DR4); | ||
418 | OUT_RING(0); | ||
419 | ADVANCE_LP_RING(); | ||
420 | } | ||
406 | 421 | ||
407 | return 0; | 422 | return 0; |
408 | } | 423 | } |
409 | 424 | ||
425 | /* XXX: Emitting the counter should really be moved to part of the IRQ | ||
426 | * emit. For now, do it in both places: | ||
427 | */ | ||
428 | |||
410 | static void i915_emit_breadcrumb(drm_device_t *dev) | 429 | static void i915_emit_breadcrumb(drm_device_t *dev) |
411 | { | 430 | { |
412 | drm_i915_private_t *dev_priv = dev->dev_private; | 431 | drm_i915_private_t *dev_priv = dev->dev_private; |
413 | RING_LOCALS; | 432 | RING_LOCALS; |
414 | 433 | ||
415 | dev_priv->sarea_priv->last_enqueue = dev_priv->counter++; | 434 | dev_priv->sarea_priv->last_enqueue = ++dev_priv->counter; |
435 | |||
436 | if (dev_priv->counter > 0x7FFFFFFFUL) | ||
437 | dev_priv->sarea_priv->last_enqueue = dev_priv->counter = 1; | ||
416 | 438 | ||
417 | BEGIN_LP_RING(4); | 439 | BEGIN_LP_RING(4); |
418 | OUT_RING(CMD_STORE_DWORD_IDX); | 440 | OUT_RING(CMD_STORE_DWORD_IDX); |
@@ -761,6 +783,7 @@ drm_ioctl_desc_t i915_ioctls[] = { | |||
761 | [DRM_IOCTL_NR(DRM_I915_DESTROY_HEAP)] = { i915_mem_destroy_heap, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY }, | 783 | [DRM_IOCTL_NR(DRM_I915_DESTROY_HEAP)] = { i915_mem_destroy_heap, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY }, |
762 | [DRM_IOCTL_NR(DRM_I915_SET_VBLANK_PIPE)] = { i915_vblank_pipe_set, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY }, | 784 | [DRM_IOCTL_NR(DRM_I915_SET_VBLANK_PIPE)] = { i915_vblank_pipe_set, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY }, |
763 | [DRM_IOCTL_NR(DRM_I915_GET_VBLANK_PIPE)] = { i915_vblank_pipe_get, DRM_AUTH }, | 785 | [DRM_IOCTL_NR(DRM_I915_GET_VBLANK_PIPE)] = { i915_vblank_pipe_get, DRM_AUTH }, |
786 | [DRM_IOCTL_NR(DRM_I915_VBLANK_SWAP)] = {i915_vblank_swap, DRM_AUTH}, | ||
764 | }; | 787 | }; |
765 | 788 | ||
766 | int i915_max_ioctl = DRM_ARRAY_SIZE(i915_ioctls); | 789 | int i915_max_ioctl = DRM_ARRAY_SIZE(i915_ioctls); |
diff --git a/drivers/char/drm/i915_drm.h b/drivers/char/drm/i915_drm.h index 5aa3e0e3bb45..96a468886a7a 100644 --- a/drivers/char/drm/i915_drm.h +++ b/drivers/char/drm/i915_drm.h | |||
@@ -98,6 +98,21 @@ 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; | ||
107 | |||
108 | int pipeA_x; | ||
109 | int pipeA_y; | ||
110 | int pipeA_w; | ||
111 | int pipeA_h; | ||
112 | int pipeB_x; | ||
113 | int pipeB_y; | ||
114 | int pipeB_w; | ||
115 | int pipeB_h; | ||
101 | } drm_i915_sarea_t; | 116 | } drm_i915_sarea_t; |
102 | 117 | ||
103 | /* Flags for perf_boxes | 118 | /* Flags for perf_boxes |
@@ -126,6 +141,7 @@ typedef struct _drm_i915_sarea { | |||
126 | #define DRM_I915_DESTROY_HEAP 0x0c | 141 | #define DRM_I915_DESTROY_HEAP 0x0c |
127 | #define DRM_I915_SET_VBLANK_PIPE 0x0d | 142 | #define DRM_I915_SET_VBLANK_PIPE 0x0d |
128 | #define DRM_I915_GET_VBLANK_PIPE 0x0e | 143 | #define DRM_I915_GET_VBLANK_PIPE 0x0e |
144 | #define DRM_I915_VBLANK_SWAP 0x0f | ||
129 | 145 | ||
130 | #define DRM_IOCTL_I915_INIT DRM_IOW( DRM_COMMAND_BASE + DRM_I915_INIT, drm_i915_init_t) | 146 | #define DRM_IOCTL_I915_INIT DRM_IOW( DRM_COMMAND_BASE + DRM_I915_INIT, drm_i915_init_t) |
131 | #define DRM_IOCTL_I915_FLUSH DRM_IO ( DRM_COMMAND_BASE + DRM_I915_FLUSH) | 147 | #define DRM_IOCTL_I915_FLUSH DRM_IO ( DRM_COMMAND_BASE + DRM_I915_FLUSH) |
@@ -142,6 +158,7 @@ typedef struct _drm_i915_sarea { | |||
142 | #define DRM_IOCTL_I915_DESTROY_HEAP DRM_IOW( DRM_COMMAND_BASE + DRM_I915_DESTROY_HEAP, drm_i915_mem_destroy_heap_t) | 158 | #define DRM_IOCTL_I915_DESTROY_HEAP DRM_IOW( DRM_COMMAND_BASE + DRM_I915_DESTROY_HEAP, drm_i915_mem_destroy_heap_t) |
143 | #define DRM_IOCTL_I915_SET_VBLANK_PIPE DRM_IOW( DRM_COMMAND_BASE + DRM_I915_SET_VBLANK_PIPE, drm_i915_vblank_pipe_t) | 159 | #define DRM_IOCTL_I915_SET_VBLANK_PIPE DRM_IOW( DRM_COMMAND_BASE + DRM_I915_SET_VBLANK_PIPE, drm_i915_vblank_pipe_t) |
144 | #define DRM_IOCTL_I915_GET_VBLANK_PIPE DRM_IOR( DRM_COMMAND_BASE + DRM_I915_GET_VBLANK_PIPE, drm_i915_vblank_pipe_t) | 160 | #define DRM_IOCTL_I915_GET_VBLANK_PIPE DRM_IOR( DRM_COMMAND_BASE + DRM_I915_GET_VBLANK_PIPE, drm_i915_vblank_pipe_t) |
161 | #define DRM_IOCTL_I915_VBLANK_SWAP DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_VBLANK_SWAP, drm_i915_vblank_swap_t) | ||
145 | 162 | ||
146 | /* Allow drivers to submit batchbuffers directly to hardware, relying | 163 | /* Allow drivers to submit batchbuffers directly to hardware, relying |
147 | * on the security mechanisms provided by hardware. | 164 | * on the security mechanisms provided by hardware. |
@@ -237,4 +254,12 @@ typedef struct drm_i915_vblank_pipe { | |||
237 | int pipe; | 254 | int pipe; |
238 | } drm_i915_vblank_pipe_t; | 255 | } drm_i915_vblank_pipe_t; |
239 | 256 | ||
257 | /* Schedule buffer swap at given vertical blank: | ||
258 | */ | ||
259 | typedef struct drm_i915_vblank_swap { | ||
260 | drm_drawable_t drawable; | ||
261 | drm_vblank_seq_type_t seqtype; | ||
262 | unsigned int sequence; | ||
263 | } drm_i915_vblank_swap_t; | ||
264 | |||
240 | #endif /* _I915_DRM_H_ */ | 265 | #endif /* _I915_DRM_H_ */ |
diff --git a/drivers/char/drm/i915_drv.c b/drivers/char/drm/i915_drv.c index 8e2e6095c4b3..85bcc276f804 100644 --- a/drivers/char/drm/i915_drv.c +++ b/drivers/char/drm/i915_drv.c | |||
@@ -44,12 +44,14 @@ static struct drm_driver driver = { | |||
44 | */ | 44 | */ |
45 | .driver_features = | 45 | .driver_features = |
46 | DRIVER_USE_AGP | DRIVER_REQUIRE_AGP | /* DRIVER_USE_MTRR |*/ | 46 | DRIVER_USE_AGP | DRIVER_REQUIRE_AGP | /* DRIVER_USE_MTRR |*/ |
47 | DRIVER_HAVE_IRQ | DRIVER_IRQ_SHARED | DRIVER_IRQ_VBL, | 47 | DRIVER_HAVE_IRQ | DRIVER_IRQ_SHARED | DRIVER_IRQ_VBL | |
48 | DRIVER_IRQ_VBL2, | ||
48 | .load = i915_driver_load, | 49 | .load = i915_driver_load, |
49 | .lastclose = i915_driver_lastclose, | 50 | .lastclose = i915_driver_lastclose, |
50 | .preclose = i915_driver_preclose, | 51 | .preclose = i915_driver_preclose, |
51 | .device_is_agp = i915_driver_device_is_agp, | 52 | .device_is_agp = i915_driver_device_is_agp, |
52 | .vblank_wait = i915_driver_vblank_wait, | 53 | .vblank_wait = i915_driver_vblank_wait, |
54 | .vblank_wait2 = i915_driver_vblank_wait2, | ||
53 | .irq_preinstall = i915_driver_irq_preinstall, | 55 | .irq_preinstall = i915_driver_irq_preinstall, |
54 | .irq_postinstall = i915_driver_irq_postinstall, | 56 | .irq_postinstall = i915_driver_irq_postinstall, |
55 | .irq_uninstall = i915_driver_irq_uninstall, | 57 | .irq_uninstall = i915_driver_irq_uninstall, |
diff --git a/drivers/char/drm/i915_drv.h b/drivers/char/drm/i915_drv.h index 2d565031c002..93cdcfe6aa84 100644 --- a/drivers/char/drm/i915_drv.h +++ b/drivers/char/drm/i915_drv.h | |||
@@ -46,9 +46,11 @@ | |||
46 | * 1.3: Add vblank support | 46 | * 1.3: Add vblank support |
47 | * 1.4: Fix cmdbuffer path, add heap destroy | 47 | * 1.4: Fix cmdbuffer path, add heap destroy |
48 | * 1.5: Add vblank pipe configuration | 48 | * 1.5: Add vblank pipe configuration |
49 | * 1.6: - New ioctl for scheduling buffer swaps on vertical blank | ||
50 | * - Support vertical blank on secondary display pipe | ||
49 | */ | 51 | */ |
50 | #define DRIVER_MAJOR 1 | 52 | #define DRIVER_MAJOR 1 |
51 | #define DRIVER_MINOR 5 | 53 | #define DRIVER_MINOR 6 |
52 | #define DRIVER_PATCHLEVEL 0 | 54 | #define DRIVER_PATCHLEVEL 0 |
53 | 55 | ||
54 | typedef struct _drm_i915_ring_buffer { | 56 | typedef struct _drm_i915_ring_buffer { |
@@ -71,6 +73,13 @@ struct mem_block { | |||
71 | DRMFILE filp; /* 0: free, -1: heap, other: real files */ | 73 | DRMFILE filp; /* 0: free, -1: heap, other: real files */ |
72 | }; | 74 | }; |
73 | 75 | ||
76 | typedef struct _drm_i915_vbl_swap { | ||
77 | struct list_head head; | ||
78 | drm_drawable_t drw_id; | ||
79 | unsigned int pipe; | ||
80 | unsigned int sequence; | ||
81 | } drm_i915_vbl_swap_t; | ||
82 | |||
74 | typedef struct drm_i915_private { | 83 | typedef struct drm_i915_private { |
75 | drm_local_map_t *sarea; | 84 | drm_local_map_t *sarea; |
76 | drm_local_map_t *mmio_map; | 85 | drm_local_map_t *mmio_map; |
@@ -83,6 +92,7 @@ typedef struct drm_i915_private { | |||
83 | dma_addr_t dma_status_page; | 92 | dma_addr_t dma_status_page; |
84 | unsigned long counter; | 93 | unsigned long counter; |
85 | 94 | ||
95 | unsigned int cpp; | ||
86 | int back_offset; | 96 | int back_offset; |
87 | int front_offset; | 97 | int front_offset; |
88 | int current_page; | 98 | int current_page; |
@@ -98,6 +108,10 @@ typedef struct drm_i915_private { | |||
98 | struct mem_block *agp_heap; | 108 | struct mem_block *agp_heap; |
99 | unsigned int sr01, adpa, ppcr, dvob, dvoc, lvds; | 109 | unsigned int sr01, adpa, ppcr, dvob, dvoc, lvds; |
100 | int vblank_pipe; | 110 | int vblank_pipe; |
111 | |||
112 | spinlock_t swaps_lock; | ||
113 | drm_i915_vbl_swap_t vbl_swaps; | ||
114 | unsigned int swaps_pending; | ||
101 | } drm_i915_private_t; | 115 | } drm_i915_private_t; |
102 | 116 | ||
103 | extern drm_ioctl_desc_t i915_ioctls[]; | 117 | extern drm_ioctl_desc_t i915_ioctls[]; |
@@ -117,12 +131,14 @@ extern int i915_irq_emit(DRM_IOCTL_ARGS); | |||
117 | extern int i915_irq_wait(DRM_IOCTL_ARGS); | 131 | extern int i915_irq_wait(DRM_IOCTL_ARGS); |
118 | 132 | ||
119 | extern int i915_driver_vblank_wait(drm_device_t *dev, unsigned int *sequence); | 133 | extern int i915_driver_vblank_wait(drm_device_t *dev, unsigned int *sequence); |
134 | extern int i915_driver_vblank_wait2(drm_device_t *dev, unsigned int *sequence); | ||
120 | extern irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS); | 135 | extern irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS); |
121 | extern void i915_driver_irq_preinstall(drm_device_t * dev); | 136 | extern void i915_driver_irq_preinstall(drm_device_t * dev); |
122 | extern void i915_driver_irq_postinstall(drm_device_t * dev); | 137 | extern void i915_driver_irq_postinstall(drm_device_t * dev); |
123 | extern void i915_driver_irq_uninstall(drm_device_t * dev); | 138 | extern void i915_driver_irq_uninstall(drm_device_t * dev); |
124 | extern int i915_vblank_pipe_set(DRM_IOCTL_ARGS); | 139 | extern int i915_vblank_pipe_set(DRM_IOCTL_ARGS); |
125 | extern int i915_vblank_pipe_get(DRM_IOCTL_ARGS); | 140 | extern int i915_vblank_pipe_get(DRM_IOCTL_ARGS); |
141 | extern int i915_vblank_swap(DRM_IOCTL_ARGS); | ||
126 | 142 | ||
127 | /* i915_mem.c */ | 143 | /* i915_mem.c */ |
128 | extern int i915_mem_alloc(DRM_IOCTL_ARGS); | 144 | extern int i915_mem_alloc(DRM_IOCTL_ARGS); |
@@ -146,9 +162,9 @@ extern void i915_mem_release(drm_device_t * dev, | |||
146 | #define BEGIN_LP_RING(n) do { \ | 162 | #define BEGIN_LP_RING(n) do { \ |
147 | if (I915_VERBOSE) \ | 163 | if (I915_VERBOSE) \ |
148 | DRM_DEBUG("BEGIN_LP_RING(%d) in %s\n", \ | 164 | DRM_DEBUG("BEGIN_LP_RING(%d) in %s\n", \ |
149 | n, __FUNCTION__); \ | 165 | (n), __FUNCTION__); \ |
150 | if (dev_priv->ring.space < n*4) \ | 166 | if (dev_priv->ring.space < (n)*4) \ |
151 | i915_wait_ring(dev, n*4, __FUNCTION__); \ | 167 | i915_wait_ring(dev, (n)*4, __FUNCTION__); \ |
152 | outcount = 0; \ | 168 | outcount = 0; \ |
153 | outring = dev_priv->ring.tail; \ | 169 | outring = dev_priv->ring.tail; \ |
154 | ringmask = dev_priv->ring.tail_mask; \ | 170 | ringmask = dev_priv->ring.tail_mask; \ |
@@ -157,7 +173,7 @@ extern void i915_mem_release(drm_device_t * dev, | |||
157 | 173 | ||
158 | #define OUT_RING(n) do { \ | 174 | #define OUT_RING(n) do { \ |
159 | if (I915_VERBOSE) DRM_DEBUG(" OUT_RING %x\n", (int)(n)); \ | 175 | if (I915_VERBOSE) DRM_DEBUG(" OUT_RING %x\n", (int)(n)); \ |
160 | *(volatile unsigned int *)(virt + outring) = n; \ | 176 | *(volatile unsigned int *)(virt + outring) = (n); \ |
161 | outcount++; \ | 177 | outcount++; \ |
162 | outring += 4; \ | 178 | outring += 4; \ |
163 | outring &= ringmask; \ | 179 | outring &= ringmask; \ |
@@ -254,6 +270,12 @@ 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) | 270 | #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)) | 271 | #define GFX_OP_DRAWRECT_INFO ((0x3<<29)|(0x1d<<24)|(0x80<<16)|(0x3)) |
256 | 272 | ||
273 | #define GFX_OP_DRAWRECT_INFO_I965 ((0x7900<<16)|0x2) | ||
274 | |||
275 | #define XY_SRC_COPY_BLT_CMD ((2<<29)|(0x53<<22)|6) | ||
276 | #define XY_SRC_COPY_BLT_WRITE_ALPHA (1<<21) | ||
277 | #define XY_SRC_COPY_BLT_WRITE_RGB (1<<20) | ||
278 | |||
257 | #define MI_BATCH_BUFFER ((0x30<<23)|1) | 279 | #define MI_BATCH_BUFFER ((0x30<<23)|1) |
258 | #define MI_BATCH_BUFFER_START (0x31<<23) | 280 | #define MI_BATCH_BUFFER_START (0x31<<23) |
259 | #define MI_BATCH_BUFFER_END (0xA<<23) | 281 | #define MI_BATCH_BUFFER_END (0xA<<23) |
diff --git a/drivers/char/drm/i915_ioc32.c b/drivers/char/drm/i915_ioc32.c index 296248cdc767..1fe68a251b75 100644 --- a/drivers/char/drm/i915_ioc32.c +++ b/drivers/char/drm/i915_ioc32.c | |||
@@ -66,7 +66,7 @@ static int compat_i915_batchbuffer(struct file *file, unsigned int cmd, | |||
66 | &batchbuffer->cliprects)) | 66 | &batchbuffer->cliprects)) |
67 | return -EFAULT; | 67 | return -EFAULT; |
68 | 68 | ||
69 | return drm_ioctl(file->f_dentry->d_inode, file, | 69 | return drm_ioctl(file->f_path.dentry->d_inode, file, |
70 | DRM_IOCTL_I915_BATCHBUFFER, | 70 | DRM_IOCTL_I915_BATCHBUFFER, |
71 | (unsigned long)batchbuffer); | 71 | (unsigned long)batchbuffer); |
72 | } | 72 | } |
@@ -102,7 +102,7 @@ static int compat_i915_cmdbuffer(struct file *file, unsigned int cmd, | |||
102 | &cmdbuffer->cliprects)) | 102 | &cmdbuffer->cliprects)) |
103 | return -EFAULT; | 103 | return -EFAULT; |
104 | 104 | ||
105 | return drm_ioctl(file->f_dentry->d_inode, file, | 105 | return drm_ioctl(file->f_path.dentry->d_inode, file, |
106 | DRM_IOCTL_I915_CMDBUFFER, (unsigned long)cmdbuffer); | 106 | DRM_IOCTL_I915_CMDBUFFER, (unsigned long)cmdbuffer); |
107 | } | 107 | } |
108 | 108 | ||
@@ -125,7 +125,7 @@ static int compat_i915_irq_emit(struct file *file, unsigned int cmd, | |||
125 | &request->irq_seq)) | 125 | &request->irq_seq)) |
126 | return -EFAULT; | 126 | return -EFAULT; |
127 | 127 | ||
128 | return drm_ioctl(file->f_dentry->d_inode, file, | 128 | return drm_ioctl(file->f_path.dentry->d_inode, file, |
129 | DRM_IOCTL_I915_IRQ_EMIT, (unsigned long)request); | 129 | DRM_IOCTL_I915_IRQ_EMIT, (unsigned long)request); |
130 | } | 130 | } |
131 | typedef struct drm_i915_getparam32 { | 131 | typedef struct drm_i915_getparam32 { |
@@ -149,7 +149,7 @@ static int compat_i915_getparam(struct file *file, unsigned int cmd, | |||
149 | &request->value)) | 149 | &request->value)) |
150 | return -EFAULT; | 150 | return -EFAULT; |
151 | 151 | ||
152 | return drm_ioctl(file->f_dentry->d_inode, file, | 152 | return drm_ioctl(file->f_path.dentry->d_inode, file, |
153 | DRM_IOCTL_I915_GETPARAM, (unsigned long)request); | 153 | DRM_IOCTL_I915_GETPARAM, (unsigned long)request); |
154 | } | 154 | } |
155 | 155 | ||
@@ -178,7 +178,7 @@ static int compat_i915_alloc(struct file *file, unsigned int cmd, | |||
178 | &request->region_offset)) | 178 | &request->region_offset)) |
179 | return -EFAULT; | 179 | return -EFAULT; |
180 | 180 | ||
181 | return drm_ioctl(file->f_dentry->d_inode, file, | 181 | return drm_ioctl(file->f_path.dentry->d_inode, file, |
182 | DRM_IOCTL_I915_ALLOC, (unsigned long)request); | 182 | DRM_IOCTL_I915_ALLOC, (unsigned long)request); |
183 | } | 183 | } |
184 | 184 | ||
@@ -215,7 +215,7 @@ long i915_compat_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) | |||
215 | if (fn != NULL) | 215 | if (fn != NULL) |
216 | ret = (*fn) (filp, cmd, arg); | 216 | ret = (*fn) (filp, cmd, arg); |
217 | else | 217 | else |
218 | ret = drm_ioctl(filp->f_dentry->d_inode, filp, cmd, arg); | 218 | ret = drm_ioctl(filp->f_path.dentry->d_inode, filp, cmd, arg); |
219 | unlock_kernel(); | 219 | unlock_kernel(); |
220 | 220 | ||
221 | return ret; | 221 | return ret; |
diff --git a/drivers/char/drm/i915_irq.c b/drivers/char/drm/i915_irq.c index cd96cfa430db..e5463b111fc0 100644 --- a/drivers/char/drm/i915_irq.c +++ b/drivers/char/drm/i915_irq.c | |||
@@ -37,6 +37,99 @@ | |||
37 | 37 | ||
38 | #define MAX_NOPID ((u32)~0) | 38 | #define MAX_NOPID ((u32)~0) |
39 | 39 | ||
40 | /** | ||
41 | * Emit blits for scheduled buffer swaps. | ||
42 | * | ||
43 | * This function will be called with the HW lock held. | ||
44 | */ | ||
45 | static void i915_vblank_tasklet(drm_device_t *dev) | ||
46 | { | ||
47 | drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; | ||
48 | unsigned long irqflags; | ||
49 | struct list_head *list, *tmp; | ||
50 | |||
51 | DRM_DEBUG("\n"); | ||
52 | |||
53 | spin_lock_irqsave(&dev_priv->swaps_lock, irqflags); | ||
54 | |||
55 | list_for_each_safe(list, tmp, &dev_priv->vbl_swaps.head) { | ||
56 | drm_i915_vbl_swap_t *vbl_swap = | ||
57 | list_entry(list, drm_i915_vbl_swap_t, head); | ||
58 | atomic_t *counter = vbl_swap->pipe ? &dev->vbl_received2 : | ||
59 | &dev->vbl_received; | ||
60 | |||
61 | if ((atomic_read(counter) - vbl_swap->sequence) <= (1<<23)) { | ||
62 | drm_drawable_info_t *drw; | ||
63 | |||
64 | spin_unlock(&dev_priv->swaps_lock); | ||
65 | |||
66 | spin_lock(&dev->drw_lock); | ||
67 | |||
68 | drw = drm_get_drawable_info(dev, vbl_swap->drw_id); | ||
69 | |||
70 | if (drw) { | ||
71 | int i, num_rects = drw->num_rects; | ||
72 | drm_clip_rect_t *rect = drw->rects; | ||
73 | drm_i915_sarea_t *sarea_priv = | ||
74 | dev_priv->sarea_priv; | ||
75 | u32 cpp = dev_priv->cpp; | ||
76 | u32 cmd = (cpp == 4) ? (XY_SRC_COPY_BLT_CMD | | ||
77 | XY_SRC_COPY_BLT_WRITE_ALPHA | | ||
78 | XY_SRC_COPY_BLT_WRITE_RGB) | ||
79 | : XY_SRC_COPY_BLT_CMD; | ||
80 | u32 pitchropcpp = (sarea_priv->pitch * cpp) | | ||
81 | (0xcc << 16) | (cpp << 23) | | ||
82 | (1 << 24); | ||
83 | RING_LOCALS; | ||
84 | |||
85 | i915_kernel_lost_context(dev); | ||
86 | |||
87 | BEGIN_LP_RING(6); | ||
88 | |||
89 | OUT_RING(GFX_OP_DRAWRECT_INFO); | ||
90 | OUT_RING(0); | ||
91 | OUT_RING(0); | ||
92 | OUT_RING(sarea_priv->width | | ||
93 | sarea_priv->height << 16); | ||
94 | OUT_RING(sarea_priv->width | | ||
95 | sarea_priv->height << 16); | ||
96 | OUT_RING(0); | ||
97 | |||
98 | ADVANCE_LP_RING(); | ||
99 | |||
100 | sarea_priv->ctxOwner = DRM_KERNEL_CONTEXT; | ||
101 | |||
102 | for (i = 0; i < num_rects; i++, rect++) { | ||
103 | BEGIN_LP_RING(8); | ||
104 | |||
105 | OUT_RING(cmd); | ||
106 | OUT_RING(pitchropcpp); | ||
107 | OUT_RING((rect->y1 << 16) | rect->x1); | ||
108 | OUT_RING((rect->y2 << 16) | rect->x2); | ||
109 | OUT_RING(sarea_priv->front_offset); | ||
110 | OUT_RING((rect->y1 << 16) | rect->x1); | ||
111 | OUT_RING(pitchropcpp & 0xffff); | ||
112 | OUT_RING(sarea_priv->back_offset); | ||
113 | |||
114 | ADVANCE_LP_RING(); | ||
115 | } | ||
116 | } | ||
117 | |||
118 | spin_unlock(&dev->drw_lock); | ||
119 | |||
120 | spin_lock(&dev_priv->swaps_lock); | ||
121 | |||
122 | list_del(list); | ||
123 | |||
124 | drm_free(vbl_swap, sizeof(*vbl_swap), DRM_MEM_DRIVER); | ||
125 | |||
126 | dev_priv->swaps_pending--; | ||
127 | } | ||
128 | } | ||
129 | |||
130 | spin_unlock_irqrestore(&dev_priv->swaps_lock, irqflags); | ||
131 | } | ||
132 | |||
40 | irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS) | 133 | irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS) |
41 | { | 134 | { |
42 | drm_device_t *dev = (drm_device_t *) arg; | 135 | drm_device_t *dev = (drm_device_t *) arg; |
@@ -60,9 +153,26 @@ irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS) | |||
60 | DRM_WAKEUP(&dev_priv->irq_queue); | 153 | DRM_WAKEUP(&dev_priv->irq_queue); |
61 | 154 | ||
62 | if (temp & (VSYNC_PIPEA_FLAG | VSYNC_PIPEB_FLAG)) { | 155 | if (temp & (VSYNC_PIPEA_FLAG | VSYNC_PIPEB_FLAG)) { |
63 | atomic_inc(&dev->vbl_received); | 156 | int vblank_pipe = dev_priv->vblank_pipe; |
157 | |||
158 | if ((vblank_pipe & | ||
159 | (DRM_I915_VBLANK_PIPE_A | DRM_I915_VBLANK_PIPE_B)) | ||
160 | == (DRM_I915_VBLANK_PIPE_A | DRM_I915_VBLANK_PIPE_B)) { | ||
161 | if (temp & VSYNC_PIPEA_FLAG) | ||
162 | atomic_inc(&dev->vbl_received); | ||
163 | if (temp & VSYNC_PIPEB_FLAG) | ||
164 | atomic_inc(&dev->vbl_received2); | ||
165 | } else if (((temp & VSYNC_PIPEA_FLAG) && | ||
166 | (vblank_pipe & DRM_I915_VBLANK_PIPE_A)) || | ||
167 | ((temp & VSYNC_PIPEB_FLAG) && | ||
168 | (vblank_pipe & DRM_I915_VBLANK_PIPE_B))) | ||
169 | atomic_inc(&dev->vbl_received); | ||
170 | |||
64 | DRM_WAKEUP(&dev->vbl_queue); | 171 | DRM_WAKEUP(&dev->vbl_queue); |
65 | drm_vbl_send_signals(dev); | 172 | drm_vbl_send_signals(dev); |
173 | |||
174 | if (dev_priv->swaps_pending > 0) | ||
175 | drm_locked_tasklet(dev, i915_vblank_tasklet); | ||
66 | } | 176 | } |
67 | 177 | ||
68 | return IRQ_HANDLED; | 178 | return IRQ_HANDLED; |
@@ -71,21 +181,27 @@ irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS) | |||
71 | static int i915_emit_irq(drm_device_t * dev) | 181 | static int i915_emit_irq(drm_device_t * dev) |
72 | { | 182 | { |
73 | drm_i915_private_t *dev_priv = dev->dev_private; | 183 | drm_i915_private_t *dev_priv = dev->dev_private; |
74 | u32 ret; | ||
75 | RING_LOCALS; | 184 | RING_LOCALS; |
76 | 185 | ||
77 | i915_kernel_lost_context(dev); | 186 | i915_kernel_lost_context(dev); |
78 | 187 | ||
79 | DRM_DEBUG("%s\n", __FUNCTION__); | 188 | DRM_DEBUG("%s\n", __FUNCTION__); |
80 | 189 | ||
81 | ret = dev_priv->counter; | 190 | dev_priv->sarea_priv->last_enqueue = ++dev_priv->counter; |
82 | 191 | ||
83 | BEGIN_LP_RING(2); | 192 | if (dev_priv->counter > 0x7FFFFFFFUL) |
193 | dev_priv->sarea_priv->last_enqueue = dev_priv->counter = 1; | ||
194 | |||
195 | BEGIN_LP_RING(6); | ||
196 | OUT_RING(CMD_STORE_DWORD_IDX); | ||
197 | OUT_RING(20); | ||
198 | OUT_RING(dev_priv->counter); | ||
199 | OUT_RING(0); | ||
84 | OUT_RING(0); | 200 | OUT_RING(0); |
85 | OUT_RING(GFX_OP_USER_INTERRUPT); | 201 | OUT_RING(GFX_OP_USER_INTERRUPT); |
86 | ADVANCE_LP_RING(); | 202 | ADVANCE_LP_RING(); |
87 | 203 | ||
88 | return ret; | 204 | return dev_priv->counter; |
89 | } | 205 | } |
90 | 206 | ||
91 | static int i915_wait_irq(drm_device_t * dev, int irq_nr) | 207 | static int i915_wait_irq(drm_device_t * dev, int irq_nr) |
@@ -114,7 +230,8 @@ static int i915_wait_irq(drm_device_t * dev, int irq_nr) | |||
114 | return ret; | 230 | return ret; |
115 | } | 231 | } |
116 | 232 | ||
117 | int i915_driver_vblank_wait(drm_device_t *dev, unsigned int *sequence) | 233 | static int i915_driver_vblank_do_wait(drm_device_t *dev, unsigned int *sequence, |
234 | atomic_t *counter) | ||
118 | { | 235 | { |
119 | drm_i915_private_t *dev_priv = dev->dev_private; | 236 | drm_i915_private_t *dev_priv = dev->dev_private; |
120 | unsigned int cur_vblank; | 237 | unsigned int cur_vblank; |
@@ -126,7 +243,7 @@ int i915_driver_vblank_wait(drm_device_t *dev, unsigned int *sequence) | |||
126 | } | 243 | } |
127 | 244 | ||
128 | DRM_WAIT_ON(ret, dev->vbl_queue, 3 * DRM_HZ, | 245 | DRM_WAIT_ON(ret, dev->vbl_queue, 3 * DRM_HZ, |
129 | (((cur_vblank = atomic_read(&dev->vbl_received)) | 246 | (((cur_vblank = atomic_read(counter)) |
130 | - *sequence) <= (1<<23))); | 247 | - *sequence) <= (1<<23))); |
131 | 248 | ||
132 | *sequence = cur_vblank; | 249 | *sequence = cur_vblank; |
@@ -135,6 +252,16 @@ int i915_driver_vblank_wait(drm_device_t *dev, unsigned int *sequence) | |||
135 | } | 252 | } |
136 | 253 | ||
137 | 254 | ||
255 | int i915_driver_vblank_wait(drm_device_t *dev, unsigned int *sequence) | ||
256 | { | ||
257 | return i915_driver_vblank_do_wait(dev, sequence, &dev->vbl_received); | ||
258 | } | ||
259 | |||
260 | int i915_driver_vblank_wait2(drm_device_t *dev, unsigned int *sequence) | ||
261 | { | ||
262 | return i915_driver_vblank_do_wait(dev, sequence, &dev->vbl_received2); | ||
263 | } | ||
264 | |||
138 | /* Needs the lock as it touches the ring. | 265 | /* Needs the lock as it touches the ring. |
139 | */ | 266 | */ |
140 | int i915_irq_emit(DRM_IOCTL_ARGS) | 267 | int i915_irq_emit(DRM_IOCTL_ARGS) |
@@ -183,7 +310,7 @@ int i915_irq_wait(DRM_IOCTL_ARGS) | |||
183 | return i915_wait_irq(dev, irqwait.irq_seq); | 310 | return i915_wait_irq(dev, irqwait.irq_seq); |
184 | } | 311 | } |
185 | 312 | ||
186 | static int i915_enable_interrupt (drm_device_t *dev) | 313 | static void i915_enable_interrupt (drm_device_t *dev) |
187 | { | 314 | { |
188 | drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; | 315 | drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; |
189 | u16 flag; | 316 | u16 flag; |
@@ -193,13 +320,8 @@ static int i915_enable_interrupt (drm_device_t *dev) | |||
193 | flag |= VSYNC_PIPEA_FLAG; | 320 | flag |= VSYNC_PIPEA_FLAG; |
194 | if (dev_priv->vblank_pipe & DRM_I915_VBLANK_PIPE_B) | 321 | if (dev_priv->vblank_pipe & DRM_I915_VBLANK_PIPE_B) |
195 | flag |= VSYNC_PIPEB_FLAG; | 322 | flag |= VSYNC_PIPEB_FLAG; |
196 | if (dev_priv->vblank_pipe & ~(DRM_I915_VBLANK_PIPE_A|DRM_I915_VBLANK_PIPE_B)) { | 323 | |
197 | DRM_ERROR("%s called with invalid pipe 0x%x\n", | ||
198 | __FUNCTION__, dev_priv->vblank_pipe); | ||
199 | return DRM_ERR(EINVAL); | ||
200 | } | ||
201 | I915_WRITE16(I915REG_INT_ENABLE_R, USER_INT_FLAG | flag); | 324 | I915_WRITE16(I915REG_INT_ENABLE_R, USER_INT_FLAG | flag); |
202 | return 0; | ||
203 | } | 325 | } |
204 | 326 | ||
205 | /* Set the vblank monitor pipe | 327 | /* Set the vblank monitor pipe |
@@ -218,8 +340,17 @@ int i915_vblank_pipe_set(DRM_IOCTL_ARGS) | |||
218 | DRM_COPY_FROM_USER_IOCTL(pipe, (drm_i915_vblank_pipe_t __user *) data, | 340 | DRM_COPY_FROM_USER_IOCTL(pipe, (drm_i915_vblank_pipe_t __user *) data, |
219 | sizeof(pipe)); | 341 | sizeof(pipe)); |
220 | 342 | ||
343 | if (pipe.pipe & ~(DRM_I915_VBLANK_PIPE_A|DRM_I915_VBLANK_PIPE_B)) { | ||
344 | DRM_ERROR("%s called with invalid pipe 0x%x\n", | ||
345 | __FUNCTION__, pipe.pipe); | ||
346 | return DRM_ERR(EINVAL); | ||
347 | } | ||
348 | |||
221 | dev_priv->vblank_pipe = pipe.pipe; | 349 | dev_priv->vblank_pipe = pipe.pipe; |
222 | return i915_enable_interrupt (dev); | 350 | |
351 | i915_enable_interrupt (dev); | ||
352 | |||
353 | return 0; | ||
223 | } | 354 | } |
224 | 355 | ||
225 | int i915_vblank_pipe_get(DRM_IOCTL_ARGS) | 356 | int i915_vblank_pipe_get(DRM_IOCTL_ARGS) |
@@ -245,6 +376,118 @@ int i915_vblank_pipe_get(DRM_IOCTL_ARGS) | |||
245 | return 0; | 376 | return 0; |
246 | } | 377 | } |
247 | 378 | ||
379 | /** | ||
380 | * Schedule buffer swap at given vertical blank. | ||
381 | */ | ||
382 | int i915_vblank_swap(DRM_IOCTL_ARGS) | ||
383 | { | ||
384 | DRM_DEVICE; | ||
385 | drm_i915_private_t *dev_priv = dev->dev_private; | ||
386 | drm_i915_vblank_swap_t swap; | ||
387 | drm_i915_vbl_swap_t *vbl_swap; | ||
388 | unsigned int pipe, seqtype, curseq; | ||
389 | unsigned long irqflags; | ||
390 | struct list_head *list; | ||
391 | |||
392 | if (!dev_priv) { | ||
393 | DRM_ERROR("%s called with no initialization\n", __func__); | ||
394 | return DRM_ERR(EINVAL); | ||
395 | } | ||
396 | |||
397 | if (dev_priv->sarea_priv->rotation) { | ||
398 | DRM_DEBUG("Rotation not supported\n"); | ||
399 | return DRM_ERR(EINVAL); | ||
400 | } | ||
401 | |||
402 | DRM_COPY_FROM_USER_IOCTL(swap, (drm_i915_vblank_swap_t __user *) data, | ||
403 | sizeof(swap)); | ||
404 | |||
405 | if (swap.seqtype & ~(_DRM_VBLANK_RELATIVE | _DRM_VBLANK_ABSOLUTE | | ||
406 | _DRM_VBLANK_SECONDARY | _DRM_VBLANK_NEXTONMISS)) { | ||
407 | DRM_ERROR("Invalid sequence type 0x%x\n", swap.seqtype); | ||
408 | return DRM_ERR(EINVAL); | ||
409 | } | ||
410 | |||
411 | pipe = (swap.seqtype & _DRM_VBLANK_SECONDARY) ? 1 : 0; | ||
412 | |||
413 | seqtype = swap.seqtype & (_DRM_VBLANK_RELATIVE | _DRM_VBLANK_ABSOLUTE); | ||
414 | |||
415 | if (!(dev_priv->vblank_pipe & (1 << pipe))) { | ||
416 | DRM_ERROR("Invalid pipe %d\n", pipe); | ||
417 | return DRM_ERR(EINVAL); | ||
418 | } | ||
419 | |||
420 | spin_lock_irqsave(&dev->drw_lock, irqflags); | ||
421 | |||
422 | if (!drm_get_drawable_info(dev, swap.drawable)) { | ||
423 | spin_unlock_irqrestore(&dev->drw_lock, irqflags); | ||
424 | DRM_ERROR("Invalid drawable ID %d\n", swap.drawable); | ||
425 | return DRM_ERR(EINVAL); | ||
426 | } | ||
427 | |||
428 | spin_unlock_irqrestore(&dev->drw_lock, irqflags); | ||
429 | |||
430 | curseq = atomic_read(pipe ? &dev->vbl_received2 : &dev->vbl_received); | ||
431 | |||
432 | if (seqtype == _DRM_VBLANK_RELATIVE) | ||
433 | swap.sequence += curseq; | ||
434 | |||
435 | if ((curseq - swap.sequence) <= (1<<23)) { | ||
436 | if (swap.seqtype & _DRM_VBLANK_NEXTONMISS) { | ||
437 | swap.sequence = curseq + 1; | ||
438 | } else { | ||
439 | DRM_DEBUG("Missed target sequence\n"); | ||
440 | return DRM_ERR(EINVAL); | ||
441 | } | ||
442 | } | ||
443 | |||
444 | spin_lock_irqsave(&dev_priv->swaps_lock, irqflags); | ||
445 | |||
446 | list_for_each(list, &dev_priv->vbl_swaps.head) { | ||
447 | vbl_swap = list_entry(list, drm_i915_vbl_swap_t, head); | ||
448 | |||
449 | if (vbl_swap->drw_id == swap.drawable && | ||
450 | vbl_swap->pipe == pipe && | ||
451 | vbl_swap->sequence == swap.sequence) { | ||
452 | spin_unlock_irqrestore(&dev_priv->swaps_lock, irqflags); | ||
453 | DRM_DEBUG("Already scheduled\n"); | ||
454 | return 0; | ||
455 | } | ||
456 | } | ||
457 | |||
458 | spin_unlock_irqrestore(&dev_priv->swaps_lock, irqflags); | ||
459 | |||
460 | if (dev_priv->swaps_pending >= 100) { | ||
461 | DRM_DEBUG("Too many swaps queued\n"); | ||
462 | return DRM_ERR(EBUSY); | ||
463 | } | ||
464 | |||
465 | vbl_swap = drm_calloc(1, sizeof(vbl_swap), DRM_MEM_DRIVER); | ||
466 | |||
467 | if (!vbl_swap) { | ||
468 | DRM_ERROR("Failed to allocate memory to queue swap\n"); | ||
469 | return DRM_ERR(ENOMEM); | ||
470 | } | ||
471 | |||
472 | DRM_DEBUG("\n"); | ||
473 | |||
474 | vbl_swap->drw_id = swap.drawable; | ||
475 | vbl_swap->pipe = pipe; | ||
476 | vbl_swap->sequence = swap.sequence; | ||
477 | |||
478 | spin_lock_irqsave(&dev_priv->swaps_lock, irqflags); | ||
479 | |||
480 | list_add_tail((struct list_head *)vbl_swap, &dev_priv->vbl_swaps.head); | ||
481 | dev_priv->swaps_pending++; | ||
482 | |||
483 | spin_unlock_irqrestore(&dev_priv->swaps_lock, irqflags); | ||
484 | |||
485 | DRM_COPY_TO_USER_IOCTL((drm_i915_vblank_swap_t __user *) data, swap, | ||
486 | sizeof(swap)); | ||
487 | |||
488 | return 0; | ||
489 | } | ||
490 | |||
248 | /* drm_dma.h hooks | 491 | /* drm_dma.h hooks |
249 | */ | 492 | */ |
250 | void i915_driver_irq_preinstall(drm_device_t * dev) | 493 | void i915_driver_irq_preinstall(drm_device_t * dev) |
@@ -260,6 +503,12 @@ void i915_driver_irq_postinstall(drm_device_t * dev) | |||
260 | { | 503 | { |
261 | drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; | 504 | drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; |
262 | 505 | ||
506 | dev_priv->swaps_lock = SPIN_LOCK_UNLOCKED; | ||
507 | INIT_LIST_HEAD(&dev_priv->vbl_swaps.head); | ||
508 | dev_priv->swaps_pending = 0; | ||
509 | |||
510 | if (!dev_priv->vblank_pipe) | ||
511 | dev_priv->vblank_pipe = DRM_I915_VBLANK_PIPE_A; | ||
263 | i915_enable_interrupt(dev); | 512 | i915_enable_interrupt(dev); |
264 | DRM_INIT_WAITQUEUE(&dev_priv->irq_queue); | 513 | DRM_INIT_WAITQUEUE(&dev_priv->irq_queue); |
265 | } | 514 | } |
diff --git a/drivers/char/drm/mga_drv.c b/drivers/char/drm/mga_drv.c index e30f556b79f1..be49dbb9ec3f 100644 --- a/drivers/char/drm/mga_drv.c +++ b/drivers/char/drm/mga_drv.c | |||
@@ -47,6 +47,7 @@ static struct drm_driver driver = { | |||
47 | DRIVER_USE_AGP | DRIVER_USE_MTRR | DRIVER_PCI_DMA | | 47 | DRIVER_USE_AGP | DRIVER_USE_MTRR | DRIVER_PCI_DMA | |
48 | DRIVER_HAVE_DMA | DRIVER_HAVE_IRQ | DRIVER_IRQ_SHARED | | 48 | DRIVER_HAVE_DMA | DRIVER_HAVE_IRQ | DRIVER_IRQ_SHARED | |
49 | DRIVER_IRQ_VBL, | 49 | DRIVER_IRQ_VBL, |
50 | .dev_priv_size = sizeof(drm_mga_buf_priv_t), | ||
50 | .load = mga_driver_load, | 51 | .load = mga_driver_load, |
51 | .unload = mga_driver_unload, | 52 | .unload = mga_driver_unload, |
52 | .lastclose = mga_driver_lastclose, | 53 | .lastclose = mga_driver_lastclose, |
diff --git a/drivers/char/drm/mga_ioc32.c b/drivers/char/drm/mga_ioc32.c index 54a18eb2fc04..30d00478ddee 100644 --- a/drivers/char/drm/mga_ioc32.c +++ b/drivers/char/drm/mga_ioc32.c | |||
@@ -100,7 +100,7 @@ static int compat_mga_init(struct file *file, unsigned int cmd, | |||
100 | if (err) | 100 | if (err) |
101 | return -EFAULT; | 101 | return -EFAULT; |
102 | 102 | ||
103 | return drm_ioctl(file->f_dentry->d_inode, file, | 103 | return drm_ioctl(file->f_path.dentry->d_inode, file, |
104 | DRM_IOCTL_MGA_INIT, (unsigned long)init); | 104 | DRM_IOCTL_MGA_INIT, (unsigned long)init); |
105 | } | 105 | } |
106 | 106 | ||
@@ -125,7 +125,7 @@ static int compat_mga_getparam(struct file *file, unsigned int cmd, | |||
125 | &getparam->value)) | 125 | &getparam->value)) |
126 | return -EFAULT; | 126 | return -EFAULT; |
127 | 127 | ||
128 | return drm_ioctl(file->f_dentry->d_inode, file, | 128 | return drm_ioctl(file->f_path.dentry->d_inode, file, |
129 | DRM_IOCTL_MGA_GETPARAM, (unsigned long)getparam); | 129 | DRM_IOCTL_MGA_GETPARAM, (unsigned long)getparam); |
130 | } | 130 | } |
131 | 131 | ||
@@ -166,7 +166,7 @@ static int compat_mga_dma_bootstrap(struct file *file, unsigned int cmd, | |||
166 | || __put_user(dma_bootstrap32.agp_size, &dma_bootstrap->agp_size)) | 166 | || __put_user(dma_bootstrap32.agp_size, &dma_bootstrap->agp_size)) |
167 | return -EFAULT; | 167 | return -EFAULT; |
168 | 168 | ||
169 | err = drm_ioctl(file->f_dentry->d_inode, file, | 169 | err = drm_ioctl(file->f_path.dentry->d_inode, file, |
170 | DRM_IOCTL_MGA_DMA_BOOTSTRAP, | 170 | DRM_IOCTL_MGA_DMA_BOOTSTRAP, |
171 | (unsigned long)dma_bootstrap); | 171 | (unsigned long)dma_bootstrap); |
172 | if (err) | 172 | if (err) |
@@ -224,7 +224,7 @@ long mga_compat_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) | |||
224 | if (fn != NULL) | 224 | if (fn != NULL) |
225 | ret = (*fn) (filp, cmd, arg); | 225 | ret = (*fn) (filp, cmd, arg); |
226 | else | 226 | else |
227 | ret = drm_ioctl(filp->f_dentry->d_inode, filp, cmd, arg); | 227 | ret = drm_ioctl(filp->f_path.dentry->d_inode, filp, cmd, arg); |
228 | unlock_kernel(); | 228 | unlock_kernel(); |
229 | 229 | ||
230 | return ret; | 230 | return ret; |
diff --git a/drivers/char/drm/r128_ioc32.c b/drivers/char/drm/r128_ioc32.c index 9dd6d4116e47..d3cb676eee84 100644 --- a/drivers/char/drm/r128_ioc32.c +++ b/drivers/char/drm/r128_ioc32.c | |||
@@ -95,7 +95,7 @@ static int compat_r128_init(struct file *file, unsigned int cmd, | |||
95 | &init->agp_textures_offset)) | 95 | &init->agp_textures_offset)) |
96 | return -EFAULT; | 96 | return -EFAULT; |
97 | 97 | ||
98 | return drm_ioctl(file->f_dentry->d_inode, file, | 98 | return drm_ioctl(file->f_path.dentry->d_inode, file, |
99 | DRM_IOCTL_R128_INIT, (unsigned long)init); | 99 | DRM_IOCTL_R128_INIT, (unsigned long)init); |
100 | } | 100 | } |
101 | 101 | ||
@@ -129,7 +129,7 @@ static int compat_r128_depth(struct file *file, unsigned int cmd, | |||
129 | &depth->mask)) | 129 | &depth->mask)) |
130 | return -EFAULT; | 130 | return -EFAULT; |
131 | 131 | ||
132 | return drm_ioctl(file->f_dentry->d_inode, file, | 132 | return drm_ioctl(file->f_path.dentry->d_inode, file, |
133 | DRM_IOCTL_R128_DEPTH, (unsigned long)depth); | 133 | DRM_IOCTL_R128_DEPTH, (unsigned long)depth); |
134 | 134 | ||
135 | } | 135 | } |
@@ -153,7 +153,7 @@ static int compat_r128_stipple(struct file *file, unsigned int cmd, | |||
153 | &stipple->mask)) | 153 | &stipple->mask)) |
154 | return -EFAULT; | 154 | return -EFAULT; |
155 | 155 | ||
156 | return drm_ioctl(file->f_dentry->d_inode, file, | 156 | return drm_ioctl(file->f_path.dentry->d_inode, file, |
157 | DRM_IOCTL_R128_STIPPLE, (unsigned long)stipple); | 157 | DRM_IOCTL_R128_STIPPLE, (unsigned long)stipple); |
158 | } | 158 | } |
159 | 159 | ||
@@ -178,7 +178,7 @@ static int compat_r128_getparam(struct file *file, unsigned int cmd, | |||
178 | &getparam->value)) | 178 | &getparam->value)) |
179 | return -EFAULT; | 179 | return -EFAULT; |
180 | 180 | ||
181 | return drm_ioctl(file->f_dentry->d_inode, file, | 181 | return drm_ioctl(file->f_path.dentry->d_inode, file, |
182 | DRM_IOCTL_R128_GETPARAM, (unsigned long)getparam); | 182 | DRM_IOCTL_R128_GETPARAM, (unsigned long)getparam); |
183 | } | 183 | } |
184 | 184 | ||
@@ -214,7 +214,7 @@ long r128_compat_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) | |||
214 | if (fn != NULL) | 214 | if (fn != NULL) |
215 | ret = (*fn) (filp, cmd, arg); | 215 | ret = (*fn) (filp, cmd, arg); |
216 | else | 216 | else |
217 | ret = drm_ioctl(filp->f_dentry->d_inode, filp, cmd, arg); | 217 | ret = drm_ioctl(filp->f_path.dentry->d_inode, filp, cmd, arg); |
218 | unlock_kernel(); | 218 | unlock_kernel(); |
219 | 219 | ||
220 | return ret; | 220 | return ret; |
diff --git a/drivers/char/drm/r300_cmdbuf.c b/drivers/char/drm/r300_cmdbuf.c index 26bdf2ca59d7..d14477ba3679 100644 --- a/drivers/char/drm/r300_cmdbuf.c +++ b/drivers/char/drm/r300_cmdbuf.c | |||
@@ -538,6 +538,36 @@ static __inline__ int r300_emit_bitblt_multi(drm_radeon_private_t *dev_priv, | |||
538 | return 0; | 538 | return 0; |
539 | } | 539 | } |
540 | 540 | ||
541 | static __inline__ int r300_emit_indx_buffer(drm_radeon_private_t *dev_priv, | ||
542 | drm_radeon_kcmd_buffer_t *cmdbuf) | ||
543 | { | ||
544 | u32 *cmd = (u32 *) cmdbuf->buf; | ||
545 | int count, ret; | ||
546 | RING_LOCALS; | ||
547 | |||
548 | count=(cmd[0]>>16) & 0x3fff; | ||
549 | |||
550 | if ((cmd[1] & 0x8000ffff) != 0x80000810) { | ||
551 | DRM_ERROR("Invalid indx_buffer reg address %08X\n", cmd[1]); | ||
552 | return DRM_ERR(EINVAL); | ||
553 | } | ||
554 | ret = r300_check_offset(dev_priv, cmd[2]); | ||
555 | if (ret) { | ||
556 | DRM_ERROR("Invalid indx_buffer offset is %08X\n", cmd[2]); | ||
557 | return DRM_ERR(EINVAL); | ||
558 | } | ||
559 | |||
560 | BEGIN_RING(count+2); | ||
561 | OUT_RING(cmd[0]); | ||
562 | OUT_RING_TABLE((int *)(cmdbuf->buf + 4), count + 1); | ||
563 | ADVANCE_RING(); | ||
564 | |||
565 | cmdbuf->buf += (count+2)*4; | ||
566 | cmdbuf->bufsz -= (count+2)*4; | ||
567 | |||
568 | return 0; | ||
569 | } | ||
570 | |||
541 | static __inline__ int r300_emit_raw_packet3(drm_radeon_private_t *dev_priv, | 571 | static __inline__ int r300_emit_raw_packet3(drm_radeon_private_t *dev_priv, |
542 | drm_radeon_kcmd_buffer_t *cmdbuf) | 572 | drm_radeon_kcmd_buffer_t *cmdbuf) |
543 | { | 573 | { |
@@ -578,10 +608,11 @@ static __inline__ int r300_emit_raw_packet3(drm_radeon_private_t *dev_priv, | |||
578 | case RADEON_CNTL_BITBLT_MULTI: | 608 | case RADEON_CNTL_BITBLT_MULTI: |
579 | return r300_emit_bitblt_multi(dev_priv, cmdbuf); | 609 | return r300_emit_bitblt_multi(dev_priv, cmdbuf); |
580 | 610 | ||
611 | case RADEON_CP_INDX_BUFFER: /* DRAW_INDX_2 without INDX_BUFFER seems to lock up the gpu */ | ||
612 | return r300_emit_indx_buffer(dev_priv, cmdbuf); | ||
581 | case RADEON_CP_3D_DRAW_IMMD_2: /* triggers drawing using in-packet vertex data */ | 613 | case RADEON_CP_3D_DRAW_IMMD_2: /* triggers drawing using in-packet vertex data */ |
582 | case RADEON_CP_3D_DRAW_VBUF_2: /* triggers drawing of vertex buffers setup elsewhere */ | 614 | case RADEON_CP_3D_DRAW_VBUF_2: /* triggers drawing of vertex buffers setup elsewhere */ |
583 | case RADEON_CP_3D_DRAW_INDX_2: /* triggers drawing using indices to vertex buffer */ | 615 | case RADEON_CP_3D_DRAW_INDX_2: /* triggers drawing using indices to vertex buffer */ |
584 | case RADEON_CP_INDX_BUFFER: /* DRAW_INDX_2 without INDX_BUFFER seems to lock up the gpu */ | ||
585 | case RADEON_WAIT_FOR_IDLE: | 616 | case RADEON_WAIT_FOR_IDLE: |
586 | case RADEON_CP_NOP: | 617 | case RADEON_CP_NOP: |
587 | /* these packets are safe */ | 618 | /* these packets are safe */ |
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_ioc32.c b/drivers/char/drm/radeon_ioc32.c index 0ccfd3618ff1..1f1f9cc055a4 100644 --- a/drivers/char/drm/radeon_ioc32.c +++ b/drivers/char/drm/radeon_ioc32.c | |||
@@ -92,7 +92,7 @@ static int compat_radeon_cp_init(struct file *file, unsigned int cmd, | |||
92 | &init->gart_textures_offset)) | 92 | &init->gart_textures_offset)) |
93 | return -EFAULT; | 93 | return -EFAULT; |
94 | 94 | ||
95 | return drm_ioctl(file->f_dentry->d_inode, file, | 95 | return drm_ioctl(file->f_path.dentry->d_inode, file, |
96 | DRM_IOCTL_RADEON_CP_INIT, (unsigned long)init); | 96 | DRM_IOCTL_RADEON_CP_INIT, (unsigned long)init); |
97 | } | 97 | } |
98 | 98 | ||
@@ -125,7 +125,7 @@ static int compat_radeon_cp_clear(struct file *file, unsigned int cmd, | |||
125 | &clr->depth_boxes)) | 125 | &clr->depth_boxes)) |
126 | return -EFAULT; | 126 | return -EFAULT; |
127 | 127 | ||
128 | return drm_ioctl(file->f_dentry->d_inode, file, | 128 | return drm_ioctl(file->f_path.dentry->d_inode, file, |
129 | DRM_IOCTL_RADEON_CLEAR, (unsigned long)clr); | 129 | DRM_IOCTL_RADEON_CLEAR, (unsigned long)clr); |
130 | } | 130 | } |
131 | 131 | ||
@@ -149,7 +149,7 @@ static int compat_radeon_cp_stipple(struct file *file, unsigned int cmd, | |||
149 | &request->mask)) | 149 | &request->mask)) |
150 | return -EFAULT; | 150 | return -EFAULT; |
151 | 151 | ||
152 | return drm_ioctl(file->f_dentry->d_inode, file, | 152 | return drm_ioctl(file->f_path.dentry->d_inode, file, |
153 | DRM_IOCTL_RADEON_STIPPLE, (unsigned long)request); | 153 | DRM_IOCTL_RADEON_STIPPLE, (unsigned long)request); |
154 | } | 154 | } |
155 | 155 | ||
@@ -204,7 +204,7 @@ static int compat_radeon_cp_texture(struct file *file, unsigned int cmd, | |||
204 | &image->data)) | 204 | &image->data)) |
205 | return -EFAULT; | 205 | return -EFAULT; |
206 | 206 | ||
207 | return drm_ioctl(file->f_dentry->d_inode, file, | 207 | return drm_ioctl(file->f_path.dentry->d_inode, file, |
208 | DRM_IOCTL_RADEON_TEXTURE, (unsigned long)request); | 208 | DRM_IOCTL_RADEON_TEXTURE, (unsigned long)request); |
209 | } | 209 | } |
210 | 210 | ||
@@ -238,7 +238,7 @@ static int compat_radeon_cp_vertex2(struct file *file, unsigned int cmd, | |||
238 | &request->prim)) | 238 | &request->prim)) |
239 | return -EFAULT; | 239 | return -EFAULT; |
240 | 240 | ||
241 | return drm_ioctl(file->f_dentry->d_inode, file, | 241 | return drm_ioctl(file->f_path.dentry->d_inode, file, |
242 | DRM_IOCTL_RADEON_VERTEX2, (unsigned long)request); | 242 | DRM_IOCTL_RADEON_VERTEX2, (unsigned long)request); |
243 | } | 243 | } |
244 | 244 | ||
@@ -268,7 +268,7 @@ static int compat_radeon_cp_cmdbuf(struct file *file, unsigned int cmd, | |||
268 | &request->boxes)) | 268 | &request->boxes)) |
269 | return -EFAULT; | 269 | return -EFAULT; |
270 | 270 | ||
271 | return drm_ioctl(file->f_dentry->d_inode, file, | 271 | return drm_ioctl(file->f_path.dentry->d_inode, file, |
272 | DRM_IOCTL_RADEON_CMDBUF, (unsigned long)request); | 272 | DRM_IOCTL_RADEON_CMDBUF, (unsigned long)request); |
273 | } | 273 | } |
274 | 274 | ||
@@ -293,7 +293,7 @@ static int compat_radeon_cp_getparam(struct file *file, unsigned int cmd, | |||
293 | &request->value)) | 293 | &request->value)) |
294 | return -EFAULT; | 294 | return -EFAULT; |
295 | 295 | ||
296 | return drm_ioctl(file->f_dentry->d_inode, file, | 296 | return drm_ioctl(file->f_path.dentry->d_inode, file, |
297 | DRM_IOCTL_RADEON_GETPARAM, (unsigned long)request); | 297 | DRM_IOCTL_RADEON_GETPARAM, (unsigned long)request); |
298 | } | 298 | } |
299 | 299 | ||
@@ -322,7 +322,7 @@ static int compat_radeon_mem_alloc(struct file *file, unsigned int cmd, | |||
322 | &request->region_offset)) | 322 | &request->region_offset)) |
323 | return -EFAULT; | 323 | return -EFAULT; |
324 | 324 | ||
325 | return drm_ioctl(file->f_dentry->d_inode, file, | 325 | return drm_ioctl(file->f_path.dentry->d_inode, file, |
326 | DRM_IOCTL_RADEON_ALLOC, (unsigned long)request); | 326 | DRM_IOCTL_RADEON_ALLOC, (unsigned long)request); |
327 | } | 327 | } |
328 | 328 | ||
@@ -345,7 +345,7 @@ static int compat_radeon_irq_emit(struct file *file, unsigned int cmd, | |||
345 | &request->irq_seq)) | 345 | &request->irq_seq)) |
346 | return -EFAULT; | 346 | return -EFAULT; |
347 | 347 | ||
348 | return drm_ioctl(file->f_dentry->d_inode, file, | 348 | return drm_ioctl(file->f_path.dentry->d_inode, file, |
349 | DRM_IOCTL_RADEON_IRQ_EMIT, (unsigned long)request); | 349 | DRM_IOCTL_RADEON_IRQ_EMIT, (unsigned long)request); |
350 | } | 350 | } |
351 | 351 | ||
@@ -386,7 +386,7 @@ long radeon_compat_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) | |||
386 | if (fn != NULL) | 386 | if (fn != NULL) |
387 | ret = (*fn) (filp, cmd, arg); | 387 | ret = (*fn) (filp, cmd, arg); |
388 | else | 388 | else |
389 | ret = drm_ioctl(filp->f_dentry->d_inode, filp, cmd, arg); | 389 | ret = drm_ioctl(filp->f_path.dentry->d_inode, filp, cmd, arg); |
390 | unlock_kernel(); | 390 | unlock_kernel(); |
391 | 391 | ||
392 | return ret; | 392 | return ret; |
diff --git a/drivers/char/drm/radeon_state.c b/drivers/char/drm/radeon_state.c index 39a7f685e3fd..6e04fdd732ac 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 | } |
@@ -276,6 +275,8 @@ static __inline__ int radeon_check_and_fixup_packet3(drm_radeon_private_t * | |||
276 | unsigned int *cmdsz) | 275 | unsigned int *cmdsz) |
277 | { | 276 | { |
278 | u32 *cmd = (u32 *) cmdbuf->buf; | 277 | u32 *cmd = (u32 *) cmdbuf->buf; |
278 | u32 offset, narrays; | ||
279 | int count, i, k; | ||
279 | 280 | ||
280 | *cmdsz = 2 + ((cmd[0] & RADEON_CP_PACKET_COUNT_MASK) >> 16); | 281 | *cmdsz = 2 + ((cmd[0] & RADEON_CP_PACKET_COUNT_MASK) >> 16); |
281 | 282 | ||
@@ -289,10 +290,106 @@ static __inline__ int radeon_check_and_fixup_packet3(drm_radeon_private_t * | |||
289 | return DRM_ERR(EINVAL); | 290 | return DRM_ERR(EINVAL); |
290 | } | 291 | } |
291 | 292 | ||
292 | /* Check client state and fix it up if necessary */ | 293 | switch(cmd[0] & 0xff00) { |
293 | if (cmd[0] & 0x8000) { /* MSB of opcode: next DWORD GUI_CNTL */ | 294 | /* XXX Are there old drivers needing other packets? */ |
294 | u32 offset; | ||
295 | 295 | ||
296 | case RADEON_3D_DRAW_IMMD: | ||
297 | case RADEON_3D_DRAW_VBUF: | ||
298 | case RADEON_3D_DRAW_INDX: | ||
299 | case RADEON_WAIT_FOR_IDLE: | ||
300 | case RADEON_CP_NOP: | ||
301 | case RADEON_3D_CLEAR_ZMASK: | ||
302 | /* case RADEON_CP_NEXT_CHAR: | ||
303 | case RADEON_CP_PLY_NEXTSCAN: | ||
304 | case RADEON_CP_SET_SCISSORS: */ /* probably safe but will never need them? */ | ||
305 | /* these packets are safe */ | ||
306 | break; | ||
307 | |||
308 | case RADEON_CP_3D_DRAW_IMMD_2: | ||
309 | case RADEON_CP_3D_DRAW_VBUF_2: | ||
310 | case RADEON_CP_3D_DRAW_INDX_2: | ||
311 | case RADEON_3D_CLEAR_HIZ: | ||
312 | /* safe but r200 only */ | ||
313 | if (dev_priv->microcode_version != UCODE_R200) { | ||
314 | DRM_ERROR("Invalid 3d packet for r100-class chip\n"); | ||
315 | return DRM_ERR(EINVAL); | ||
316 | } | ||
317 | break; | ||
318 | |||
319 | case RADEON_3D_LOAD_VBPNTR: | ||
320 | count = (cmd[0] >> 16) & 0x3fff; | ||
321 | |||
322 | if (count > 18) { /* 12 arrays max */ | ||
323 | DRM_ERROR("Too large payload in 3D_LOAD_VBPNTR (count=%d)\n", | ||
324 | count); | ||
325 | return DRM_ERR(EINVAL); | ||
326 | } | ||
327 | |||
328 | /* carefully check packet contents */ | ||
329 | narrays = cmd[1] & ~0xc000; | ||
330 | k = 0; | ||
331 | i = 2; | ||
332 | while ((k < narrays) && (i < (count + 2))) { | ||
333 | i++; /* skip attribute field */ | ||
334 | if (radeon_check_and_fixup_offset(dev_priv, filp_priv, &cmd[i])) { | ||
335 | DRM_ERROR | ||
336 | ("Invalid offset (k=%d i=%d) in 3D_LOAD_VBPNTR packet.\n", | ||
337 | k, i); | ||
338 | return DRM_ERR(EINVAL); | ||
339 | } | ||
340 | k++; | ||
341 | i++; | ||
342 | if (k == narrays) | ||
343 | break; | ||
344 | /* have one more to process, they come in pairs */ | ||
345 | if (radeon_check_and_fixup_offset(dev_priv, filp_priv, &cmd[i])) { | ||
346 | DRM_ERROR | ||
347 | ("Invalid offset (k=%d i=%d) in 3D_LOAD_VBPNTR packet.\n", | ||
348 | k, i); | ||
349 | return DRM_ERR(EINVAL); | ||
350 | } | ||
351 | k++; | ||
352 | i++; | ||
353 | } | ||
354 | /* do the counts match what we expect ? */ | ||
355 | if ((k != narrays) || (i != (count + 2))) { | ||
356 | DRM_ERROR | ||
357 | ("Malformed 3D_LOAD_VBPNTR packet (k=%d i=%d narrays=%d count+1=%d).\n", | ||
358 | k, i, narrays, count + 1); | ||
359 | return DRM_ERR(EINVAL); | ||
360 | } | ||
361 | break; | ||
362 | |||
363 | case RADEON_3D_RNDR_GEN_INDX_PRIM: | ||
364 | if (dev_priv->microcode_version != UCODE_R100) { | ||
365 | DRM_ERROR("Invalid 3d packet for r200-class chip\n"); | ||
366 | return DRM_ERR(EINVAL); | ||
367 | } | ||
368 | if (radeon_check_and_fixup_offset(dev_priv, filp_priv, &cmd[1])) { | ||
369 | DRM_ERROR("Invalid rndr_gen_indx offset\n"); | ||
370 | return DRM_ERR(EINVAL); | ||
371 | } | ||
372 | break; | ||
373 | |||
374 | case RADEON_CP_INDX_BUFFER: | ||
375 | if (dev_priv->microcode_version != UCODE_R200) { | ||
376 | DRM_ERROR("Invalid 3d packet for r100-class chip\n"); | ||
377 | return DRM_ERR(EINVAL); | ||
378 | } | ||
379 | if ((cmd[1] & 0x8000ffff) != 0x80000810) { | ||
380 | DRM_ERROR("Invalid indx_buffer reg address %08X\n", cmd[1]); | ||
381 | return DRM_ERR(EINVAL); | ||
382 | } | ||
383 | if (radeon_check_and_fixup_offset(dev_priv, filp_priv, &cmd[2])) { | ||
384 | DRM_ERROR("Invalid indx_buffer offset is %08X\n", cmd[2]); | ||
385 | return DRM_ERR(EINVAL); | ||
386 | } | ||
387 | break; | ||
388 | |||
389 | case RADEON_CNTL_HOSTDATA_BLT: | ||
390 | case RADEON_CNTL_PAINT_MULTI: | ||
391 | case RADEON_CNTL_BITBLT_MULTI: | ||
392 | /* MSB of opcode: next DWORD GUI_CNTL */ | ||
296 | if (cmd[1] & (RADEON_GMC_SRC_PITCH_OFFSET_CNTL | 393 | if (cmd[1] & (RADEON_GMC_SRC_PITCH_OFFSET_CNTL |
297 | | RADEON_GMC_DST_PITCH_OFFSET_CNTL)) { | 394 | | RADEON_GMC_DST_PITCH_OFFSET_CNTL)) { |
298 | offset = cmd[2] << 10; | 395 | offset = cmd[2] << 10; |
@@ -314,6 +411,11 @@ static __inline__ int radeon_check_and_fixup_packet3(drm_radeon_private_t * | |||
314 | } | 411 | } |
315 | cmd[3] = (cmd[3] & 0xffc00000) | offset >> 10; | 412 | cmd[3] = (cmd[3] & 0xffc00000) | offset >> 10; |
316 | } | 413 | } |
414 | break; | ||
415 | |||
416 | default: | ||
417 | DRM_ERROR("Invalid packet type %x\n", cmd[0] & 0xff00); | ||
418 | return DRM_ERR(EINVAL); | ||
317 | } | 419 | } |
318 | 420 | ||
319 | return 0; | 421 | return 0; |
@@ -869,7 +971,7 @@ static void radeon_cp_dispatch_clear(drm_device_t * dev, | |||
869 | */ | 971 | */ |
870 | dev_priv->sarea_priv->ctx_owner = 0; | 972 | dev_priv->sarea_priv->ctx_owner = 0; |
871 | 973 | ||
872 | if ((dev_priv->flags & CHIP_HAS_HIERZ) | 974 | if ((dev_priv->flags & RADEON_HAS_HIERZ) |
873 | && (flags & RADEON_USE_HIERZ)) { | 975 | && (flags & RADEON_USE_HIERZ)) { |
874 | /* FIXME : reverse engineer that for Rx00 cards */ | 976 | /* FIXME : reverse engineer that for Rx00 cards */ |
875 | /* FIXME : the mask supposedly contains low-res z values. So can't set | 977 | /* FIXME : the mask supposedly contains low-res z values. So can't set |
@@ -914,7 +1016,7 @@ static void radeon_cp_dispatch_clear(drm_device_t * dev, | |||
914 | for (i = 0; i < nbox; i++) { | 1016 | for (i = 0; i < nbox; i++) { |
915 | int tileoffset, nrtilesx, nrtilesy, j; | 1017 | int tileoffset, nrtilesx, nrtilesy, j; |
916 | /* it looks like r200 needs rv-style clears, at least if hierz is not enabled? */ | 1018 | /* it looks like r200 needs rv-style clears, at least if hierz is not enabled? */ |
917 | if ((dev_priv->flags & CHIP_HAS_HIERZ) | 1019 | if ((dev_priv->flags & RADEON_HAS_HIERZ) |
918 | && !(dev_priv->microcode_version == UCODE_R200)) { | 1020 | && !(dev_priv->microcode_version == UCODE_R200)) { |
919 | /* FIXME : figure this out for r200 (when hierz is enabled). Or | 1021 | /* 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 | 1022 | maybe r200 actually doesn't need to put the low-res z value into |
@@ -998,7 +1100,7 @@ static void radeon_cp_dispatch_clear(drm_device_t * dev, | |||
998 | } | 1100 | } |
999 | 1101 | ||
1000 | /* TODO don't always clear all hi-level z tiles */ | 1102 | /* TODO don't always clear all hi-level z tiles */ |
1001 | if ((dev_priv->flags & CHIP_HAS_HIERZ) | 1103 | if ((dev_priv->flags & RADEON_HAS_HIERZ) |
1002 | && (dev_priv->microcode_version == UCODE_R200) | 1104 | && (dev_priv->microcode_version == UCODE_R200) |
1003 | && (flags & RADEON_USE_HIERZ)) | 1105 | && (flags & RADEON_USE_HIERZ)) |
1004 | /* r100 and cards without hierarchical z-buffer have no high-level z-buffer */ | 1106 | /* r100 and cards without hierarchical z-buffer have no high-level z-buffer */ |
@@ -1270,9 +1372,9 @@ static void radeon_cp_dispatch_swap(drm_device_t * dev) | |||
1270 | 1372 | ||
1271 | DRM_DEBUG("dispatch swap %d,%d-%d,%d\n", x, y, w, h); | 1373 | DRM_DEBUG("dispatch swap %d,%d-%d,%d\n", x, y, w, h); |
1272 | 1374 | ||
1273 | BEGIN_RING(7); | 1375 | BEGIN_RING(9); |
1274 | 1376 | ||
1275 | OUT_RING(CP_PACKET3(RADEON_CNTL_BITBLT_MULTI, 5)); | 1377 | OUT_RING(CP_PACKET0(RADEON_DP_GUI_MASTER_CNTL, 0)); |
1276 | OUT_RING(RADEON_GMC_SRC_PITCH_OFFSET_CNTL | | 1378 | OUT_RING(RADEON_GMC_SRC_PITCH_OFFSET_CNTL | |
1277 | RADEON_GMC_DST_PITCH_OFFSET_CNTL | | 1379 | RADEON_GMC_DST_PITCH_OFFSET_CNTL | |
1278 | RADEON_GMC_BRUSH_NONE | | 1380 | RADEON_GMC_BRUSH_NONE | |
@@ -1284,6 +1386,7 @@ static void radeon_cp_dispatch_swap(drm_device_t * dev) | |||
1284 | 1386 | ||
1285 | /* Make this work even if front & back are flipped: | 1387 | /* Make this work even if front & back are flipped: |
1286 | */ | 1388 | */ |
1389 | OUT_RING(CP_PACKET0(RADEON_SRC_PITCH_OFFSET, 1)); | ||
1287 | if (dev_priv->current_page == 0) { | 1390 | if (dev_priv->current_page == 0) { |
1288 | OUT_RING(dev_priv->back_pitch_offset); | 1391 | OUT_RING(dev_priv->back_pitch_offset); |
1289 | OUT_RING(dev_priv->front_pitch_offset); | 1392 | OUT_RING(dev_priv->front_pitch_offset); |
@@ -1292,6 +1395,7 @@ static void radeon_cp_dispatch_swap(drm_device_t * dev) | |||
1292 | OUT_RING(dev_priv->back_pitch_offset); | 1395 | OUT_RING(dev_priv->back_pitch_offset); |
1293 | } | 1396 | } |
1294 | 1397 | ||
1398 | OUT_RING(CP_PACKET0(RADEON_SRC_X_Y, 2)); | ||
1295 | OUT_RING((x << 16) | y); | 1399 | OUT_RING((x << 16) | y); |
1296 | OUT_RING((x << 16) | y); | 1400 | OUT_RING((x << 16) | y); |
1297 | OUT_RING((w << 16) | h); | 1401 | OUT_RING((w << 16) | h); |
@@ -2987,16 +3091,21 @@ static int radeon_cp_getparam(DRM_IOCTL_ARGS) | |||
2987 | case RADEON_PARAM_GART_TEX_HANDLE: | 3091 | case RADEON_PARAM_GART_TEX_HANDLE: |
2988 | value = dev_priv->gart_textures_offset; | 3092 | value = dev_priv->gart_textures_offset; |
2989 | break; | 3093 | break; |
2990 | 3094 | case RADEON_PARAM_SCRATCH_OFFSET: | |
3095 | if (!dev_priv->writeback_works) | ||
3096 | return DRM_ERR(EINVAL); | ||
3097 | value = RADEON_SCRATCH_REG_OFFSET; | ||
3098 | break; | ||
2991 | case RADEON_PARAM_CARD_TYPE: | 3099 | case RADEON_PARAM_CARD_TYPE: |
2992 | if (dev_priv->flags & CHIP_IS_PCIE) | 3100 | if (dev_priv->flags & RADEON_IS_PCIE) |
2993 | value = RADEON_CARD_PCIE; | 3101 | value = RADEON_CARD_PCIE; |
2994 | else if (dev_priv->flags & CHIP_IS_AGP) | 3102 | else if (dev_priv->flags & RADEON_IS_AGP) |
2995 | value = RADEON_CARD_AGP; | 3103 | value = RADEON_CARD_AGP; |
2996 | else | 3104 | else |
2997 | value = RADEON_CARD_PCI; | 3105 | value = RADEON_CARD_PCI; |
2998 | break; | 3106 | break; |
2999 | default: | 3107 | default: |
3108 | DRM_DEBUG("Invalid parameter %d\n", param.param); | ||
3000 | return DRM_ERR(EINVAL); | 3109 | return DRM_ERR(EINVAL); |
3001 | } | 3110 | } |
3002 | 3111 | ||
diff --git a/drivers/char/drm/savage_bci.c b/drivers/char/drm/savage_bci.c index 59c7520bf9a2..a9a84f88df5e 100644 --- a/drivers/char/drm/savage_bci.c +++ b/drivers/char/drm/savage_bci.c | |||
@@ -728,6 +728,7 @@ static int savage_do_init_bci(drm_device_t * dev, drm_savage_init_t * init) | |||
728 | dev_priv->status = NULL; | 728 | dev_priv->status = NULL; |
729 | } | 729 | } |
730 | if (dev_priv->dma_type == SAVAGE_DMA_AGP && init->buffers_offset) { | 730 | if (dev_priv->dma_type == SAVAGE_DMA_AGP && init->buffers_offset) { |
731 | dev->agp_buffer_token = init->buffers_offset; | ||
731 | dev->agp_buffer_map = drm_core_findmap(dev, | 732 | dev->agp_buffer_map = drm_core_findmap(dev, |
732 | init->buffers_offset); | 733 | init->buffers_offset); |
733 | if (!dev->agp_buffer_map) { | 734 | if (!dev->agp_buffer_map) { |
diff --git a/drivers/char/drm/savage_state.c b/drivers/char/drm/savage_state.c index ef2581d16146..1ca1e9cb5a33 100644 --- a/drivers/char/drm/savage_state.c +++ b/drivers/char/drm/savage_state.c | |||
@@ -994,7 +994,7 @@ int savage_bci_cmdbuf(DRM_IOCTL_ARGS) | |||
994 | if (cmdbuf.size) { | 994 | if (cmdbuf.size) { |
995 | kcmd_addr = drm_alloc(cmdbuf.size * 8, DRM_MEM_DRIVER); | 995 | kcmd_addr = drm_alloc(cmdbuf.size * 8, DRM_MEM_DRIVER); |
996 | if (kcmd_addr == NULL) | 996 | if (kcmd_addr == NULL) |
997 | return ENOMEM; | 997 | return DRM_ERR(ENOMEM); |
998 | 998 | ||
999 | if (DRM_COPY_FROM_USER(kcmd_addr, cmdbuf.cmd_addr, | 999 | if (DRM_COPY_FROM_USER(kcmd_addr, cmdbuf.cmd_addr, |
1000 | cmdbuf.size * 8)) | 1000 | cmdbuf.size * 8)) |
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..806f9ce5f47b 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 | ||
@@ -491,9 +500,9 @@ via_dmablit_timer(unsigned long data) | |||
491 | 500 | ||
492 | 501 | ||
493 | static void | 502 | static void |
494 | via_dmablit_workqueue(void *data) | 503 | via_dmablit_workqueue(struct work_struct *work) |
495 | { | 504 | { |
496 | drm_via_blitq_t *blitq = (drm_via_blitq_t *) data; | 505 | drm_via_blitq_t *blitq = container_of(work, drm_via_blitq_t, wq); |
497 | drm_device_t *dev = blitq->dev; | 506 | drm_device_t *dev = blitq->dev; |
498 | unsigned long irqsave; | 507 | unsigned long irqsave; |
499 | drm_via_sg_info_t *cur_sg; | 508 | drm_via_sg_info_t *cur_sg; |
@@ -562,7 +571,7 @@ via_init_dmablit(drm_device_t *dev) | |||
562 | DRM_INIT_WAITQUEUE(blitq->blit_queue + j); | 571 | DRM_INIT_WAITQUEUE(blitq->blit_queue + j); |
563 | } | 572 | } |
564 | DRM_INIT_WAITQUEUE(&blitq->busy_queue); | 573 | DRM_INIT_WAITQUEUE(&blitq->busy_queue); |
565 | INIT_WORK(&blitq->wq, via_dmablit_workqueue, blitq); | 574 | INIT_WORK(&blitq->wq, via_dmablit_workqueue); |
566 | init_timer(&blitq->poll_timer); | 575 | init_timer(&blitq->poll_timer); |
567 | blitq->poll_timer.function = &via_dmablit_timer; | 576 | blitq->poll_timer.function = &via_dmablit_timer; |
568 | blitq->poll_timer.data = (unsigned long) blitq; | 577 | blitq->poll_timer.data = (unsigned long) blitq; |
@@ -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 | } |