Commit dfbbe89e authored by Linus Torvalds's avatar Linus Torvalds

Merge branch 'drm-next' of git://git.kernel.org/pub/scm/linux/kernel/git/airlied/drm-2.6

* 'drm-next' of git://git.kernel.org/pub/scm/linux/kernel/git/airlied/drm-2.6: (53 commits)
  drm: detect hdmi monitor by hdmi identifier (v3)
  drm: drm_fops.c unlock missing on error path
  drm: reorder struct drm_ioctl_desc to save space on 64 bit builds
  radeon: add some new pci ids
  drm: read EDID extensions from monitor
  drm: Use a little stash on the stack to avoid kmalloc in most DRM ioctls.
  drm/radeon: add regs required for occlusion queries support
  drm/i915: check the return value from the copy from user
  drm/radeon: fix logic in r600_page_table_init() to match ati_gart
  drm/radeon: r600 ptes are 64-bit, cleanup cleanup function.
  drm/radeon: don't call irq changes on r600 suspend/resume
  drm/radeon: fix r600 writeback across suspend/resume
  drm/radeon: fix r600 writeback setup.
  drm: fix warnings about new mappings in info code.
  drm/radeon: NULL noise: drivers/gpu/drm/radeon/radeon_*.c
  drm/radeon: fix r600 pci mapping calls.
  drm/radeon: r6xx/r7xx: fix possible oops in r600_page_table_cleanup()
  radeon: call the correct idle function, logic got inverted.
  drm/radeon: RS600: fix interrupt handling
  drm/r600: fix rptr address along lines of previous fixes to radeon.
  ...
parents 712b0006 f23c20c8
...@@ -77,7 +77,7 @@ int drm_ati_pcigart_cleanup(struct drm_device *dev, struct drm_ati_pcigart_info ...@@ -77,7 +77,7 @@ int drm_ati_pcigart_cleanup(struct drm_device *dev, struct drm_ati_pcigart_info
if (!entry->busaddr[i]) if (!entry->busaddr[i])
break; break;
pci_unmap_page(dev->pdev, entry->busaddr[i], pci_unmap_page(dev->pdev, entry->busaddr[i],
PAGE_SIZE, PCI_DMA_TODEVICE); PAGE_SIZE, PCI_DMA_BIDIRECTIONAL);
} }
if (gart_info->gart_table_location == DRM_ATI_GART_MAIN) if (gart_info->gart_table_location == DRM_ATI_GART_MAIN)
...@@ -95,13 +95,14 @@ EXPORT_SYMBOL(drm_ati_pcigart_cleanup); ...@@ -95,13 +95,14 @@ EXPORT_SYMBOL(drm_ati_pcigart_cleanup);
int drm_ati_pcigart_init(struct drm_device *dev, struct drm_ati_pcigart_info *gart_info) int drm_ati_pcigart_init(struct drm_device *dev, struct drm_ati_pcigart_info *gart_info)
{ {
struct drm_local_map *map = &gart_info->mapping;
struct drm_sg_mem *entry = dev->sg; struct drm_sg_mem *entry = dev->sg;
void *address = NULL; void *address = NULL;
unsigned long pages; unsigned long pages;
u32 *pci_gart, page_base; u32 *pci_gart = NULL, page_base, gart_idx;
dma_addr_t bus_address = 0; dma_addr_t bus_address = 0;
int i, j, ret = 0; int i, j, ret = 0;
int max_pages; int max_ati_pages, max_real_pages;
if (!entry) { if (!entry) {
DRM_ERROR("no scatter/gather memory!\n"); DRM_ERROR("no scatter/gather memory!\n");
...@@ -117,6 +118,7 @@ int drm_ati_pcigart_init(struct drm_device *dev, struct drm_ati_pcigart_info *ga ...@@ -117,6 +118,7 @@ int drm_ati_pcigart_init(struct drm_device *dev, struct drm_ati_pcigart_info *ga
goto done; goto done;
} }
pci_gart = gart_info->table_handle->vaddr;
address = gart_info->table_handle->vaddr; address = gart_info->table_handle->vaddr;
bus_address = gart_info->table_handle->busaddr; bus_address = gart_info->table_handle->busaddr;
} else { } else {
...@@ -127,18 +129,23 @@ int drm_ati_pcigart_init(struct drm_device *dev, struct drm_ati_pcigart_info *ga ...@@ -127,18 +129,23 @@ int drm_ati_pcigart_init(struct drm_device *dev, struct drm_ati_pcigart_info *ga
(unsigned long)address); (unsigned long)address);
} }
pci_gart = (u32 *) address;
max_pages = (gart_info->table_size / sizeof(u32)); max_ati_pages = (gart_info->table_size / sizeof(u32));
pages = (entry->pages <= max_pages) max_real_pages = max_ati_pages / (PAGE_SIZE / ATI_PCIGART_PAGE_SIZE);
? entry->pages : max_pages; pages = (entry->pages <= max_real_pages)
? entry->pages : max_real_pages;
memset(pci_gart, 0, max_pages * sizeof(u32)); if (gart_info->gart_table_location == DRM_ATI_GART_MAIN) {
memset(pci_gart, 0, max_ati_pages * sizeof(u32));
} else {
memset_io((void __iomem *)map->handle, 0, max_ati_pages * sizeof(u32));
}
gart_idx = 0;
for (i = 0; i < pages; i++) { for (i = 0; i < pages; i++) {
/* we need to support large memory configurations */ /* we need to support large memory configurations */
entry->busaddr[i] = pci_map_page(dev->pdev, entry->pagelist[i], entry->busaddr[i] = pci_map_page(dev->pdev, entry->pagelist[i],
0, PAGE_SIZE, PCI_DMA_TODEVICE); 0, PAGE_SIZE, PCI_DMA_BIDIRECTIONAL);
if (entry->busaddr[i] == 0) { if (entry->busaddr[i] == 0) {
DRM_ERROR("unable to map PCIGART pages!\n"); DRM_ERROR("unable to map PCIGART pages!\n");
drm_ati_pcigart_cleanup(dev, gart_info); drm_ati_pcigart_cleanup(dev, gart_info);
...@@ -149,19 +156,26 @@ int drm_ati_pcigart_init(struct drm_device *dev, struct drm_ati_pcigart_info *ga ...@@ -149,19 +156,26 @@ int drm_ati_pcigart_init(struct drm_device *dev, struct drm_ati_pcigart_info *ga
page_base = (u32) entry->busaddr[i]; page_base = (u32) entry->busaddr[i];
for (j = 0; j < (PAGE_SIZE / ATI_PCIGART_PAGE_SIZE); j++) { for (j = 0; j < (PAGE_SIZE / ATI_PCIGART_PAGE_SIZE); j++) {
u32 val;
switch(gart_info->gart_reg_if) { switch(gart_info->gart_reg_if) {
case DRM_ATI_GART_IGP: case DRM_ATI_GART_IGP:
*pci_gart = cpu_to_le32((page_base) | 0xc); val = page_base | 0xc;
break; break;
case DRM_ATI_GART_PCIE: case DRM_ATI_GART_PCIE:
*pci_gart = cpu_to_le32((page_base >> 8) | 0xc); val = (page_base >> 8) | 0xc;
break; break;
default: default:
case DRM_ATI_GART_PCI: case DRM_ATI_GART_PCI:
*pci_gart = cpu_to_le32(page_base); val = page_base;
break; break;
} }
pci_gart++; if (gart_info->gart_table_location ==
DRM_ATI_GART_MAIN)
pci_gart[gart_idx] = cpu_to_le32(val);
else
DRM_WRITE32(map, gart_idx * sizeof(u32), val);
gart_idx++;
page_base += ATI_PCIGART_PAGE_SIZE; page_base += ATI_PCIGART_PAGE_SIZE;
} }
} }
......
...@@ -34,15 +34,17 @@ ...@@ -34,15 +34,17 @@
*/ */
#include <linux/vmalloc.h> #include <linux/vmalloc.h>
#include <linux/log2.h>
#include <asm/shmparam.h>
#include "drmP.h" #include "drmP.h"
unsigned long drm_get_resource_start(struct drm_device *dev, unsigned int resource) resource_size_t drm_get_resource_start(struct drm_device *dev, unsigned int resource)
{ {
return pci_resource_start(dev->pdev, resource); return pci_resource_start(dev->pdev, resource);
} }
EXPORT_SYMBOL(drm_get_resource_start); EXPORT_SYMBOL(drm_get_resource_start);
unsigned long drm_get_resource_len(struct drm_device *dev, unsigned int resource) resource_size_t drm_get_resource_len(struct drm_device *dev, unsigned int resource)
{ {
return pci_resource_len(dev->pdev, resource); return pci_resource_len(dev->pdev, resource);
} }
...@@ -50,24 +52,44 @@ unsigned long drm_get_resource_len(struct drm_device *dev, unsigned int resource ...@@ -50,24 +52,44 @@ unsigned long drm_get_resource_len(struct drm_device *dev, unsigned int resource
EXPORT_SYMBOL(drm_get_resource_len); EXPORT_SYMBOL(drm_get_resource_len);
static struct drm_map_list *drm_find_matching_map(struct drm_device *dev, static struct drm_map_list *drm_find_matching_map(struct drm_device *dev,
drm_local_map_t *map) struct drm_local_map *map)
{ {
struct drm_map_list *entry; struct drm_map_list *entry;
list_for_each_entry(entry, &dev->maplist, head) { list_for_each_entry(entry, &dev->maplist, head) {
if (entry->map && (entry->master == dev->primary->master) && (map->type == entry->map->type) && /*
((entry->map->offset == map->offset) || * Because the kernel-userspace ABI is fixed at a 32-bit offset
((map->type == _DRM_SHM) && (map->flags&_DRM_CONTAINS_LOCK)))) { * while PCI resources may live above that, we ignore the map
* offset for maps of type _DRM_FRAMEBUFFER or _DRM_REGISTERS.
* It is assumed that each driver will have only one resource of
* each type.
*/
if (!entry->map ||
map->type != entry->map->type ||
entry->master != dev->primary->master)
continue;
switch (map->type) {
case _DRM_SHM:
if (map->flags != _DRM_CONTAINS_LOCK)
break;
case _DRM_REGISTERS:
case _DRM_FRAME_BUFFER:
return entry; return entry;
default: /* Make gcc happy */
;
} }
if (entry->map->offset == map->offset)
return entry;
} }
return NULL; return NULL;
} }
static int drm_map_handle(struct drm_device *dev, struct drm_hash_item *hash, static int drm_map_handle(struct drm_device *dev, struct drm_hash_item *hash,
unsigned long user_token, int hashed_handle) unsigned long user_token, int hashed_handle, int shm)
{ {
int use_hashed_handle; int use_hashed_handle, shift;
unsigned long add;
#if (BITS_PER_LONG == 64) #if (BITS_PER_LONG == 64)
use_hashed_handle = ((user_token & 0xFFFFFFFF00000000UL) || hashed_handle); use_hashed_handle = ((user_token & 0xFFFFFFFF00000000UL) || hashed_handle);
#elif (BITS_PER_LONG == 32) #elif (BITS_PER_LONG == 32)
...@@ -83,30 +105,47 @@ static int drm_map_handle(struct drm_device *dev, struct drm_hash_item *hash, ...@@ -83,30 +105,47 @@ static int drm_map_handle(struct drm_device *dev, struct drm_hash_item *hash,
if (ret != -EINVAL) if (ret != -EINVAL)
return ret; return ret;
} }
shift = 0;
add = DRM_MAP_HASH_OFFSET >> PAGE_SHIFT;
if (shm && (SHMLBA > PAGE_SIZE)) {
int bits = ilog2(SHMLBA >> PAGE_SHIFT) + 1;
/* For shared memory, we have to preserve the SHMLBA
* bits of the eventual vma->vm_pgoff value during
* mmap(). Otherwise we run into cache aliasing problems
* on some platforms. On these platforms, the pgoff of
* a mmap() request is used to pick a suitable virtual
* address for the mmap() region such that it will not
* cause cache aliasing problems.
*
* Therefore, make sure the SHMLBA relevant bits of the
* hash value we use are equal to those in the original
* kernel virtual address.
*/
shift = bits;
add |= ((user_token >> PAGE_SHIFT) & ((1UL << bits) - 1UL));
}
return drm_ht_just_insert_please(&dev->map_hash, hash, return drm_ht_just_insert_please(&dev->map_hash, hash,
user_token, 32 - PAGE_SHIFT - 3, user_token, 32 - PAGE_SHIFT - 3,
0, DRM_MAP_HASH_OFFSET >> PAGE_SHIFT); shift, add);
} }
/** /**
* Ioctl to specify a range of memory that is available for mapping by a non-root process. * Core function to create a range of memory available for mapping by a
* * non-root process.
* \param inode device inode.
* \param file_priv DRM file private.
* \param cmd command.
* \param arg pointer to a drm_map structure.
* \return zero on success or a negative value on error.
* *
* Adjusts the memory offset to its absolute value according to the mapping * Adjusts the memory offset to its absolute value according to the mapping
* type. Adds the map to the map list drm_device::maplist. Adds MTRR's where * type. Adds the map to the map list drm_device::maplist. Adds MTRR's where
* applicable and if supported by the kernel. * applicable and if supported by the kernel.
*/ */
static int drm_addmap_core(struct drm_device * dev, unsigned int offset, static int drm_addmap_core(struct drm_device * dev, resource_size_t offset,
unsigned int size, enum drm_map_type type, unsigned int size, enum drm_map_type type,
enum drm_map_flags flags, enum drm_map_flags flags,
struct drm_map_list ** maplist) struct drm_map_list ** maplist)
{ {
struct drm_map *map; struct drm_local_map *map;
struct drm_map_list *list; struct drm_map_list *list;
drm_dma_handle_t *dmah; drm_dma_handle_t *dmah;
unsigned long user_token; unsigned long user_token;
...@@ -129,9 +168,9 @@ static int drm_addmap_core(struct drm_device * dev, unsigned int offset, ...@@ -129,9 +168,9 @@ static int drm_addmap_core(struct drm_device * dev, unsigned int offset,
drm_free(map, sizeof(*map), DRM_MEM_MAPS); drm_free(map, sizeof(*map), DRM_MEM_MAPS);
return -EINVAL; return -EINVAL;
} }
DRM_DEBUG("offset = 0x%08lx, size = 0x%08lx, type = %d\n", DRM_DEBUG("offset = 0x%08llx, size = 0x%08lx, type = %d\n",
map->offset, map->size, map->type); (unsigned long long)map->offset, map->size, map->type);
if ((map->offset & (~PAGE_MASK)) || (map->size & (~PAGE_MASK))) { if ((map->offset & (~(resource_size_t)PAGE_MASK)) || (map->size & (~PAGE_MASK))) {
drm_free(map, sizeof(*map), DRM_MEM_MAPS); drm_free(map, sizeof(*map), DRM_MEM_MAPS);
return -EINVAL; return -EINVAL;
} }
...@@ -259,7 +298,8 @@ static int drm_addmap_core(struct drm_device * dev, unsigned int offset, ...@@ -259,7 +298,8 @@ static int drm_addmap_core(struct drm_device * dev, unsigned int offset,
drm_free(map, sizeof(*map), DRM_MEM_MAPS); drm_free(map, sizeof(*map), DRM_MEM_MAPS);
return -EPERM; return -EPERM;
} }
DRM_DEBUG("AGP offset = 0x%08lx, size = 0x%08lx\n", map->offset, map->size); DRM_DEBUG("AGP offset = 0x%08llx, size = 0x%08lx\n",
(unsigned long long)map->offset, map->size);
break; break;
case _DRM_GEM: case _DRM_GEM:
...@@ -309,7 +349,8 @@ static int drm_addmap_core(struct drm_device * dev, unsigned int offset, ...@@ -309,7 +349,8 @@ static int drm_addmap_core(struct drm_device * dev, unsigned int offset,
/* We do it here so that dev->struct_mutex protects the increment */ /* We do it here so that dev->struct_mutex protects the increment */
user_token = (map->type == _DRM_SHM) ? (unsigned long)map->handle : user_token = (map->type == _DRM_SHM) ? (unsigned long)map->handle :
map->offset; map->offset;
ret = drm_map_handle(dev, &list->hash, user_token, 0); ret = drm_map_handle(dev, &list->hash, user_token, 0,
(map->type == _DRM_SHM));
if (ret) { if (ret) {
if (map->type == _DRM_REGISTERS) if (map->type == _DRM_REGISTERS)
iounmap(map->handle); iounmap(map->handle);
...@@ -327,9 +368,9 @@ static int drm_addmap_core(struct drm_device * dev, unsigned int offset, ...@@ -327,9 +368,9 @@ static int drm_addmap_core(struct drm_device * dev, unsigned int offset,
return 0; return 0;
} }
int drm_addmap(struct drm_device * dev, unsigned int offset, int drm_addmap(struct drm_device * dev, resource_size_t offset,
unsigned int size, enum drm_map_type type, unsigned int size, enum drm_map_type type,
enum drm_map_flags flags, drm_local_map_t ** map_ptr) enum drm_map_flags flags, struct drm_local_map ** map_ptr)
{ {
struct drm_map_list *list; struct drm_map_list *list;
int rc; int rc;
...@@ -342,6 +383,17 @@ int drm_addmap(struct drm_device * dev, unsigned int offset, ...@@ -342,6 +383,17 @@ int drm_addmap(struct drm_device * dev, unsigned int offset,
EXPORT_SYMBOL(drm_addmap); EXPORT_SYMBOL(drm_addmap);
/**
* Ioctl to specify a range of memory that is available for mapping by a
* non-root process.
*
* \param inode device inode.
* \param file_priv DRM file private.
* \param cmd command.
* \param arg pointer to a drm_map structure.
* \return zero on success or a negative value on error.
*
*/
int drm_addmap_ioctl(struct drm_device *dev, void *data, int drm_addmap_ioctl(struct drm_device *dev, void *data,
struct drm_file *file_priv) struct drm_file *file_priv)
{ {
...@@ -367,19 +419,13 @@ int drm_addmap_ioctl(struct drm_device *dev, void *data, ...@@ -367,19 +419,13 @@ int drm_addmap_ioctl(struct drm_device *dev, void *data,
* Remove a map private from list and deallocate resources if the mapping * Remove a map private from list and deallocate resources if the mapping
* isn't in use. * isn't in use.
* *
* \param inode device inode.
* \param file_priv DRM file private.
* \param cmd command.
* \param arg pointer to a struct drm_map structure.
* \return zero on success or a negative value on error.
*
* Searches the map on drm_device::maplist, removes it from the list, see if * Searches the map on drm_device::maplist, removes it from the list, see if
* its being used, and free any associate resource (such as MTRR's) if it's not * its being used, and free any associate resource (such as MTRR's) if it's not
* being on use. * being on use.
* *
* \sa drm_addmap * \sa drm_addmap
*/ */
int drm_rmmap_locked(struct drm_device *dev, drm_local_map_t *map) int drm_rmmap_locked(struct drm_device *dev, struct drm_local_map *map)
{ {
struct drm_map_list *r_list = NULL, *list_t; struct drm_map_list *r_list = NULL, *list_t;
drm_dma_handle_t dmah; drm_dma_handle_t dmah;
...@@ -442,7 +488,7 @@ int drm_rmmap_locked(struct drm_device *dev, drm_local_map_t *map) ...@@ -442,7 +488,7 @@ int drm_rmmap_locked(struct drm_device *dev, drm_local_map_t *map)
} }
EXPORT_SYMBOL(drm_rmmap_locked); EXPORT_SYMBOL(drm_rmmap_locked);
int drm_rmmap(struct drm_device *dev, drm_local_map_t *map) int drm_rmmap(struct drm_device *dev, struct drm_local_map *map)
{ {
int ret; int ret;
...@@ -462,12 +508,18 @@ EXPORT_SYMBOL(drm_rmmap); ...@@ -462,12 +508,18 @@ EXPORT_SYMBOL(drm_rmmap);
* One use case might be after addmap is allowed for normal users for SHM and * One use case might be after addmap is allowed for normal users for SHM and
* gets used by drivers that the server doesn't need to care about. This seems * gets used by drivers that the server doesn't need to care about. This seems
* unlikely. * unlikely.
*
* \param inode device inode.
* \param file_priv DRM file private.
* \param cmd command.
* \param arg pointer to a struct drm_map structure.
* \return zero on success or a negative value on error.
*/ */
int drm_rmmap_ioctl(struct drm_device *dev, void *data, int drm_rmmap_ioctl(struct drm_device *dev, void *data,
struct drm_file *file_priv) struct drm_file *file_priv)
{ {
struct drm_map *request = data; struct drm_map *request = data;
drm_local_map_t *map = NULL; struct drm_local_map *map = NULL;
struct drm_map_list *r_list; struct drm_map_list *r_list;
int ret; int ret;
...@@ -1534,7 +1586,7 @@ int drm_mapbufs(struct drm_device *dev, void *data, ...@@ -1534,7 +1586,7 @@ int drm_mapbufs(struct drm_device *dev, void *data,
&& (dma->flags & _DRM_DMA_USE_SG)) && (dma->flags & _DRM_DMA_USE_SG))
|| (drm_core_check_feature(dev, DRIVER_FB_DMA) || (drm_core_check_feature(dev, DRIVER_FB_DMA)
&& (dma->flags & _DRM_DMA_USE_FB))) { && (dma->flags & _DRM_DMA_USE_FB))) {
struct drm_map *map = dev->agp_buffer_map; struct drm_local_map *map = dev->agp_buffer_map;
unsigned long token = dev->agp_buffer_token; unsigned long token = dev->agp_buffer_token;
if (!map) { if (!map) {
......
...@@ -143,7 +143,7 @@ int drm_getsareactx(struct drm_device *dev, void *data, ...@@ -143,7 +143,7 @@ int drm_getsareactx(struct drm_device *dev, void *data,
struct drm_file *file_priv) struct drm_file *file_priv)
{ {
struct drm_ctx_priv_map *request = data; struct drm_ctx_priv_map *request = data;
struct drm_map *map; struct drm_local_map *map;
struct drm_map_list *_entry; struct drm_map_list *_entry;
mutex_lock(&dev->struct_mutex); mutex_lock(&dev->struct_mutex);
...@@ -186,7 +186,7 @@ int drm_setsareactx(struct drm_device *dev, void *data, ...@@ -186,7 +186,7 @@ int drm_setsareactx(struct drm_device *dev, void *data,
struct drm_file *file_priv) struct drm_file *file_priv)
{ {
struct drm_ctx_priv_map *request = data; struct drm_ctx_priv_map *request = data;
struct drm_map *map = NULL; struct drm_local_map *map = NULL;
struct drm_map_list *r_list = NULL; struct drm_map_list *r_list = NULL;
mutex_lock(&dev->struct_mutex); mutex_lock(&dev->struct_mutex);
......
...@@ -254,15 +254,19 @@ int drm_lastclose(struct drm_device * dev) ...@@ -254,15 +254,19 @@ int drm_lastclose(struct drm_device * dev)
int drm_init(struct drm_driver *driver) int drm_init(struct drm_driver *driver)
{ {
struct pci_dev *pdev = NULL; struct pci_dev *pdev = NULL;
struct pci_device_id *pid; const struct pci_device_id *pid;
int i; int i;
DRM_DEBUG("\n"); DRM_DEBUG("\n");
INIT_LIST_HEAD(&driver->device_list); INIT_LIST_HEAD(&driver->device_list);
if (driver->driver_features & DRIVER_MODESET)
return pci_register_driver(&driver->pci_driver);
/* If not using KMS, fall back to stealth mode manual scanning. */
for (i = 0; driver->pci_driver.id_table[i].vendor != 0; i++) { for (i = 0; driver->pci_driver.id_table[i].vendor != 0; i++) {
pid = (struct pci_device_id *)&driver->pci_driver.id_table[i]; pid = &driver->pci_driver.id_table[i];
/* Loop around setting up a DRM device for each PCI device /* Loop around setting up a DRM device for each PCI device
* matching our ID and device class. If we had the internal * matching our ID and device class. If we had the internal
...@@ -287,68 +291,17 @@ int drm_init(struct drm_driver *driver) ...@@ -287,68 +291,17 @@ int drm_init(struct drm_driver *driver)
EXPORT_SYMBOL(drm_init); EXPORT_SYMBOL(drm_init);
/**
* Called via cleanup_module() at module unload time.
*
* Cleans up all DRM device, calling drm_lastclose().
*
* \sa drm_init
*/
static void drm_cleanup(struct drm_device * dev)
{
struct drm_map_list *r_list, *list_temp;
DRM_DEBUG("\n");
if (!dev) {
DRM_ERROR("cleanup called no dev\n");
return;
}
drm_vblank_cleanup(dev);
drm_lastclose(dev);
if (drm_core_has_MTRR(dev) && drm_core_has_AGP(dev) &&
dev->agp && dev->agp->agp_mtrr >= 0) {
int retval;
retval = mtrr_del(dev->agp->agp_mtrr,
dev->agp->agp_info.aper_base,
dev->agp->agp_info.aper_size * 1024 * 1024);
DRM_DEBUG("mtrr_del=%d\n", retval);
}
if (dev->driver->unload)
dev->driver->unload(dev);
if (drm_core_has_AGP(dev) && dev->agp) {
drm_free(dev->agp, sizeof(*dev->agp), DRM_MEM_AGPLISTS);
dev->agp = NULL;
}
drm_ht_remove(&dev->map_hash);
drm_ctxbitmap_cleanup(dev);
list_for_each_entry_safe(r_list, list_temp, &dev->maplist, head)
drm_rmmap(dev, r_list->map);
if (drm_core_check_feature(dev, DRIVER_MODESET))
drm_put_minor(&dev->control);
if (dev->driver->driver_features & DRIVER_GEM)
drm_gem_destroy(dev);
drm_put_minor(&dev->primary);
if (drm_put_dev(dev))
DRM_ERROR("Cannot unload module\n");
}
void drm_exit(struct drm_driver *driver) void drm_exit(struct drm_driver *driver)
{ {
struct drm_device *dev, *tmp; struct drm_device *dev, *tmp;
DRM_DEBUG("\n"); DRM_DEBUG("\n");
list_for_each_entry_safe(dev, tmp, &driver->device_list, driver_item) if (driver->driver_features & DRIVER_MODESET) {
drm_cleanup(dev); pci_unregister_driver(&driver->pci_driver);
} else {
list_for_each_entry_safe(dev, tmp, &driver->device_list, driver_item)
drm_put_dev(dev);
}
DRM_INFO("Module unloaded\n"); DRM_INFO("Module unloaded\n");
} }
...@@ -468,6 +421,7 @@ int drm_ioctl(struct inode *inode, struct file *filp, ...@@ -468,6 +421,7 @@ int drm_ioctl(struct inode *inode, struct file *filp,
drm_ioctl_t *func; drm_ioctl_t *func;
unsigned int nr = DRM_IOCTL_NR(cmd); unsigned int nr = DRM_IOCTL_NR(cmd);
int retcode = -EINVAL; int retcode = -EINVAL;
char stack_kdata[128];
char *kdata = NULL; char *kdata = NULL;
atomic_inc(&dev->ioctl_count); atomic_inc(&dev->ioctl_count);
...@@ -506,10 +460,14 @@ int drm_ioctl(struct inode *inode, struct file *filp, ...@@ -506,10 +460,14 @@ int drm_ioctl(struct inode *inode, struct file *filp,
retcode = -EACCES; retcode = -EACCES;
} else { } else {
if (cmd & (IOC_IN | IOC_OUT)) { if (cmd & (IOC_IN | IOC_OUT)) {
kdata = kmalloc(_IOC_SIZE(cmd), GFP_KERNEL); if (_IOC_SIZE(cmd) <= sizeof(stack_kdata)) {
if (!kdata) { kdata = stack_kdata;
retcode = -ENOMEM; } else {
goto err_i1; kdata = kmalloc(_IOC_SIZE(cmd), GFP_KERNEL);
if (!kdata) {
retcode = -ENOMEM;
goto err_i1;
}
} }
} }
...@@ -530,7 +488,7 @@ int drm_ioctl(struct inode *inode, struct file *filp, ...@@ -530,7 +488,7 @@ int drm_ioctl(struct inode *inode, struct file *filp,
} }
err_i1: err_i1:
if (kdata) if (kdata != stack_kdata)
kfree(kdata); kfree(kdata);
atomic_dec(&dev->ioctl_count); atomic_dec(&dev->ioctl_count);
if (retcode) if (retcode)
...@@ -540,7 +498,7 @@ int drm_ioctl(struct inode *inode, struct file *filp, ...@@ -540,7 +498,7 @@ int drm_ioctl(struct inode *inode, struct file *filp,
EXPORT_SYMBOL(drm_ioctl); EXPORT_SYMBOL(drm_ioctl);
drm_local_map_t *drm_getsarea(struct drm_device *dev) struct drm_local_map *drm_getsarea(struct drm_device *dev)
{ {
struct drm_map_list *entry; struct drm_map_list *entry;
......
...@@ -550,11 +550,20 @@ static int add_detailed_info(struct drm_connector *connector, ...@@ -550,11 +550,20 @@ static int add_detailed_info(struct drm_connector *connector,
} }
#define DDC_ADDR 0x50 #define DDC_ADDR 0x50
/**
unsigned char *drm_do_probe_ddc_edid(struct i2c_adapter *adapter) * Get EDID information via I2C.
*
* \param adapter : i2c device adaptor
* \param buf : EDID data buffer to be filled
* \param len : EDID data buffer length
* \return 0 on success or -1 on failure.
*
* Try to fetch EDID information by calling i2c driver function.
*/
int drm_do_probe_ddc_edid(struct i2c_adapter *adapter,
unsigned char *buf, int len)
{ {
unsigned char start = 0x0; unsigned char start = 0x0;
unsigned char *buf = kmalloc(EDID_LENGTH, GFP_KERNEL);
struct i2c_msg msgs[] = { struct i2c_msg msgs[] = {
{ {
.addr = DDC_ADDR, .addr = DDC_ADDR,
...@@ -564,31 +573,36 @@ unsigned char *drm_do_probe_ddc_edid(struct i2c_adapter *adapter) ...@@ -564,31 +573,36 @@ unsigned char *drm_do_probe_ddc_edid(struct i2c_adapter *adapter)
}, { }, {
.addr = DDC_ADDR, .addr = DDC_ADDR,
.flags = I2C_M_RD, .flags = I2C_M_RD,
.len = EDID_LENGTH, .len = len,
.buf = buf, .buf = buf,
} }
}; };
if (!buf) {
dev_warn(&adapter->dev, "unable to allocate memory for EDID "
"block.\n");
return NULL;
}
if (i2c_transfer(adapter, msgs, 2) == 2) if (i2c_transfer(adapter, msgs, 2) == 2)
return buf; return 0;
dev_info(&adapter->dev, "unable to read EDID block.\n"); dev_info(&adapter->dev, "unable to read EDID block.\n");
kfree(buf); return -1;
return NULL;
} }
EXPORT_SYMBOL(drm_do_probe_ddc_edid); EXPORT_SYMBOL(drm_do_probe_ddc_edid);
static unsigned char *drm_ddc_read(struct i2c_adapter *adapter) /**
* Get EDID information.
*
* \param adapter : i2c device adaptor.
* \param buf : EDID data buffer to be filled
* \param len : EDID data buffer length
* \return 0 on success or -1 on failure.
*
* Initialize DDC, then fetch EDID information
* by calling drm_do_probe_ddc_edid function.
*/
static int drm_ddc_read(struct i2c_adapter *adapter,
unsigned char *buf, int len)
{ {
struct i2c_algo_bit_data *algo_data = adapter->algo_data; struct i2c_algo_bit_data *algo_data = adapter->algo_data;
unsigned char *edid = NULL;
int i, j; int i, j;
int ret = -1;
algo_data->setscl(algo_data->data, 1); algo_data->setscl(algo_data->data, 1);
...@@ -616,7 +630,7 @@ static unsigned char *drm_ddc_read(struct i2c_adapter *adapter) ...@@ -616,7 +630,7 @@ static unsigned char *drm_ddc_read(struct i2c_adapter *adapter)
msleep(15); msleep(15);
/* Do the real work */ /* Do the real work */
edid = drm_do_probe_ddc_edid(adapter); ret = drm_do_probe_ddc_edid(adapter, buf, len);
algo_data->setsda(algo_data->data, 0); algo_data->setsda(algo_data->data, 0);
algo_data->setscl(algo_data->data, 0); algo_data->setscl(algo_data->data, 0);
msleep(15); msleep(15);
...@@ -632,7 +646,7 @@ static unsigned char *drm_ddc_read(struct i2c_adapter *adapter) ...@@ -632,7 +646,7 @@ static unsigned char *drm_ddc_read(struct i2c_adapter *adapter)
msleep(15); msleep(15);
algo_data->setscl(algo_data->data, 0); algo_data->setscl(algo_data->data, 0);
algo_data->setsda(algo_data->data, 0); algo_data->setsda(algo_data->data, 0);
if (edid) if (ret == 0)
break; break;
} }
/* Release the DDC lines when done or the Apple Cinema HD display /* Release the DDC lines when done or the Apple Cinema HD display
...@@ -641,9 +655,31 @@ static unsigned char *drm_ddc_read(struct i2c_adapter *adapter) ...@@ -641,9 +655,31 @@ static unsigned char *drm_ddc_read(struct i2c_adapter *adapter)
algo_data->setsda(algo_data->data, 1); algo_data->setsda(algo_data->data, 1);
algo_data->setscl(algo_data->data, 1); algo_data->setscl(algo_data->data, 1);
return edid; return ret;
} }
static int drm_ddc_read_edid(struct drm_connector *connector,
struct i2c_adapter *adapter,
char *buf, int len)
{
int ret;
ret = drm_ddc_read(adapter, buf, len);
if (ret != 0) {
dev_info(&connector->dev->pdev->dev, "%s: no EDID data\n",
drm_get_connector_name(connector));
goto end;
}
if (!edid_is_valid((struct edid *)buf)) {
dev_warn(&connector->dev->pdev->dev, "%s: EDID invalid.\n",
drm_get_connector_name(connector));
ret = -1;
}
end:
return ret;
}
#define MAX_EDID_EXT_NUM 4
/** /**
* drm_get_edid - get EDID data, if available * drm_get_edid - get EDID data, if available
* @connector: connector we're probing * @connector: connector we're probing
...@@ -656,27 +692,118 @@ static unsigned char *drm_ddc_read(struct i2c_adapter *adapter) ...@@ -656,27 +692,118 @@ static unsigned char *drm_ddc_read(struct i2c_adapter *adapter)
struct edid *drm_get_edid(struct drm_connector *connector, struct edid *drm_get_edid(struct drm_connector *connector,
struct i2c_adapter *adapter) struct i2c_adapter *adapter)
{ {
int ret;
struct edid *edid; struct edid *edid;
edid = (struct edid *)drm_ddc_read(adapter); edid = kmalloc(EDID_LENGTH * (MAX_EDID_EXT_NUM + 1),
if (!edid) { GFP_KERNEL);
dev_info(&connector->dev->pdev->dev, "%s: no EDID data\n", if (edid == NULL) {
drm_get_connector_name(connector)); dev_warn(&connector->dev->pdev->dev,
return NULL; "Failed to allocate EDID\n");
goto end;
} }
if (!edid_is_valid(edid)) {
dev_warn(&connector->dev->pdev->dev, "%s: EDID invalid.\n", /* Read first EDID block */
drm_get_connector_name(connector)); ret = drm_ddc_read_edid(connector, adapter,
kfree(edid); (unsigned char *)edid, EDID_LENGTH);
return NULL; if (ret != 0)
goto clean_up;
/* There are EDID extensions to be read */
if (edid->extensions != 0) {
int edid_ext_num = edid->extensions;
if (edid_ext_num > MAX_EDID_EXT_NUM) {
dev_warn(&connector->dev->pdev->dev,
"The number of extension(%d) is "
"over max (%d), actually read number (%d)\n",
edid_ext_num, MAX_EDID_EXT_NUM,
MAX_EDID_EXT_NUM);
/* Reset EDID extension number to be read */
edid_ext_num = MAX_EDID_EXT_NUM;
}
/* Read EDID including extensions too */
ret = drm_ddc_read_edid(connector, adapter, (char *)edid,
EDID_LENGTH * (edid_ext_num + 1));
if (ret != 0)
goto clean_up;
} }
connector->display_info.raw_edid = (char *)edid; connector->display_info.raw_edid = (char *)edid;
goto end;
clean_up:
kfree(edid);
edid = NULL;
end:
return edid; return edid;
} }
EXPORT_SYMBOL(drm_get_edid); EXPORT_SYMBOL(drm_get_edid);
#define HDMI_IDENTIFIER 0x000C03
#define VENDOR_BLOCK 0x03
/**
* drm_detect_hdmi_monitor - detect whether monitor is hdmi.
* @edid: monitor EDID information
*
* Parse the CEA extension according to CEA-861-B.
* Return true if HDMI, false if not or unknown.
*/
bool drm_detect_hdmi_monitor(struct edid *edid)
{
char *edid_ext = NULL;
int i, hdmi_id, edid_ext_num;
int start_offset, end_offset;
bool is_hdmi = false;
/* No EDID or EDID extensions */
if (edid == NULL || edid->extensions == 0)
goto end;
/* Chose real EDID extension number */
edid_ext_num = edid->extensions > MAX_EDID_EXT_NUM ?
MAX_EDID_EXT_NUM : edid->extensions;
/* Find CEA extension */
for (i = 0; i < edid_ext_num; i++) {
edid_ext = (char *)edid + EDID_LENGTH * (i + 1);
/* This block is CEA extension */
if (edid_ext[0] == 0x02)
break;
}
if (i == edid_ext_num)
goto end;
/* Data block offset in CEA extension block */
start_offset = 4;
end_offset = edid_ext[2];
/*
* Because HDMI identifier is in Vendor Specific Block,
* search it from all data blocks of CEA extension.
*/
for (i = start_offset; i < end_offset;
/* Increased by data block len */
i += ((edid_ext[i] & 0x1f) + 1)) {
/* Find vendor specific block */
if ((edid_ext[i] >> 5) == VENDOR_BLOCK) {
hdmi_id = edid_ext[i + 1] | (edid_ext[i + 2] << 8) |
edid_ext[i + 3] << 16;
/* Find HDMI identifier */
if (hdmi_id == HDMI_IDENTIFIER)
is_hdmi = true;
break;
}
}
end:
return is_hdmi;
}
EXPORT_SYMBOL(drm_detect_hdmi_monitor);
/** /**
* drm_add_edid_modes - add modes from EDID data, if available * drm_add_edid_modes - add modes from EDID data, if available
* @connector: connector we're probing * @connector: connector we're probing
......
...@@ -274,6 +274,7 @@ static int drm_open_helper(struct inode *inode, struct file *filp, ...@@ -274,6 +274,7 @@ static int drm_open_helper(struct inode *inode, struct file *filp,
/* create a new master */ /* create a new master */
priv->minor->master = drm_master_create(priv->minor); priv->minor->master = drm_master_create(priv->minor);
if (!priv->minor->master) { if (!priv->minor->master) {
mutex_unlock(&dev->struct_mutex);
ret = -ENOMEM; ret = -ENOMEM;
goto out_free; goto out_free;
} }
......
...@@ -502,7 +502,7 @@ int drm_gem_mmap(struct file *filp, struct vm_area_struct *vma) ...@@ -502,7 +502,7 @@ int drm_gem_mmap(struct file *filp, struct vm_area_struct *vma)
struct drm_file *priv = filp->private_data; struct drm_file *priv = filp->private_data;
struct drm_device *dev = priv->minor->dev; struct drm_device *dev = priv->minor->dev;
struct drm_gem_mm *mm = dev->mm_private; struct drm_gem_mm *mm = dev->mm_private;
struct drm_map *map = NULL; struct drm_local_map *map = NULL;
struct drm_gem_object *obj; struct drm_gem_object *obj;
struct drm_hash_item *hash; struct drm_hash_item *hash;
unsigned long prot; unsigned long prot;
......
...@@ -72,7 +72,7 @@ int drm_vm_info(struct seq_file *m, void *data) ...@@ -72,7 +72,7 @@ int drm_vm_info(struct seq_file *m, void *data)
{ {
struct drm_info_node *node = (struct drm_info_node *) m->private; struct drm_info_node *node = (struct drm_info_node *) m->private;
struct drm_device *dev = node->minor->dev; struct drm_device *dev = node->minor->dev;
struct drm_map *map; struct drm_local_map *map;
struct drm_map_list *r_list; struct drm_map_list *r_list;
/* Hardcoded from _DRM_FRAME_BUFFER, /* Hardcoded from _DRM_FRAME_BUFFER,
...@@ -94,9 +94,9 @@ int drm_vm_info(struct seq_file *m, void *data) ...@@ -94,9 +94,9 @@ int drm_vm_info(struct seq_file *m, void *data)
else else
type = types[map->type]; type = types[map->type];
seq_printf(m, "%4d 0x%08lx 0x%08lx %4.4s 0x%02x 0x%08lx ", seq_printf(m, "%4d 0x%016llx 0x%08lx %4.4s 0x%02x 0x%08lx ",
i, i,
map->offset, (unsigned long long)map->offset,
map->size, type, map->flags, map->size, type, map->flags,
(unsigned long) r_list->user_token); (unsigned long) r_list->user_token);
if (map->mtrr < 0) if (map->mtrr < 0)
......
...@@ -954,6 +954,7 @@ static int compat_drm_sg_free(struct file *file, unsigned int cmd, ...@@ -954,6 +954,7 @@ static int compat_drm_sg_free(struct file *file, unsigned int cmd,
DRM_IOCTL_SG_FREE, (unsigned long)request); DRM_IOCTL_SG_FREE, (unsigned long)request);
} }
#if defined(CONFIG_X86) || defined(CONFIG_IA64)
typedef struct drm_update_draw32 { typedef struct drm_update_draw32 {
drm_drawable_t handle; drm_drawable_t handle;
unsigned int type; unsigned int type;
...@@ -984,6 +985,7 @@ static int compat_drm_update_draw(struct file *file, unsigned int cmd, ...@@ -984,6 +985,7 @@ static int compat_drm_update_draw(struct file *file, unsigned int cmd,
DRM_IOCTL_UPDATE_DRAW, (unsigned long)request); DRM_IOCTL_UPDATE_DRAW, (unsigned long)request);
return err; return err;
} }
#endif
struct drm_wait_vblank_request32 { struct drm_wait_vblank_request32 {
enum drm_vblank_seq_type type; enum drm_vblank_seq_type type;
...@@ -1066,7 +1068,9 @@ drm_ioctl_compat_t *drm_compat_ioctls[] = { ...@@ -1066,7 +1068,9 @@ drm_ioctl_compat_t *drm_compat_ioctls[] = {
#endif #endif
[DRM_IOCTL_NR(DRM_IOCTL_SG_ALLOC32)] = compat_drm_sg_alloc, [DRM_IOCTL_NR(DRM_IOCTL_SG_ALLOC32)] = compat_drm_sg_alloc,
[DRM_IOCTL_NR(DRM_IOCTL_SG_FREE32)] = compat_drm_sg_free, [DRM_IOCTL_NR(DRM_IOCTL_SG_FREE32)] = compat_drm_sg_free,
#if defined(CONFIG_X86) || defined(CONFIG_IA64)
[DRM_IOCTL_NR(DRM_IOCTL_UPDATE_DRAW32)] = compat_drm_update_draw, [DRM_IOCTL_NR(DRM_IOCTL_UPDATE_DRAW32)] = compat_drm_update_draw,
#endif
[DRM_IOCTL_NR(DRM_IOCTL_WAIT_VBLANK32)] = compat_drm_wait_vblank, [DRM_IOCTL_NR(DRM_IOCTL_WAIT_VBLANK32)] = compat_drm_wait_vblank,
}; };
......
...@@ -159,7 +159,7 @@ static inline void *agp_remap(unsigned long offset, unsigned long size, ...@@ -159,7 +159,7 @@ static inline void *agp_remap(unsigned long offset, unsigned long size,
#endif /* debug_memory */ #endif /* debug_memory */
void drm_core_ioremap(struct drm_map *map, struct drm_device *dev) void drm_core_ioremap(struct drm_local_map *map, struct drm_device *dev)
{ {
if (drm_core_has_AGP(dev) && if (drm_core_has_AGP(dev) &&
dev->agp && dev->agp->cant_use_aperture && map->type == _DRM_AGP) dev->agp && dev->agp->cant_use_aperture && map->type == _DRM_AGP)
...@@ -169,7 +169,7 @@ void drm_core_ioremap(struct drm_map *map, struct drm_device *dev) ...@@ -169,7 +169,7 @@ void drm_core_ioremap(struct drm_map *map, struct drm_device *dev)
} }
EXPORT_SYMBOL(drm_core_ioremap); EXPORT_SYMBOL(drm_core_ioremap);
void drm_core_ioremap_wc(struct drm_map *map, struct drm_device *dev) void drm_core_ioremap_wc(struct drm_local_map *map, struct drm_device *dev)
{ {
if (drm_core_has_AGP(dev) && if (drm_core_has_AGP(dev) &&
dev->agp && dev->agp->cant_use_aperture && map->type == _DRM_AGP) dev->agp && dev->agp->cant_use_aperture && map->type == _DRM_AGP)
...@@ -179,7 +179,7 @@ void drm_core_ioremap_wc(struct drm_map *map, struct drm_device *dev) ...@@ -179,7 +179,7 @@ void drm_core_ioremap_wc(struct drm_map *map, struct drm_device *dev)
} }
EXPORT_SYMBOL(drm_core_ioremap_wc); EXPORT_SYMBOL(drm_core_ioremap_wc);
void drm_core_ioremapfree(struct drm_map *map, struct drm_device *dev) void drm_core_ioremapfree(struct drm_local_map *map, struct drm_device *dev)
{ {
if (!map->handle || !map->size) if (!map->handle || !map->size)
return; return;
......
...@@ -40,7 +40,6 @@ ...@@ -40,7 +40,6 @@
#include <linux/seq_file.h> #include <linux/seq_file.h>
#include "drmP.h" #include "drmP.h"
/*************************************************** /***************************************************
* Initialization, etc. * Initialization, etc.
**************************************************/ **************************************************/
......
...@@ -381,6 +381,7 @@ int drm_get_dev(struct pci_dev *pdev, const struct pci_device_id *ent, ...@@ -381,6 +381,7 @@ int drm_get_dev(struct pci_dev *pdev, const struct pci_device_id *ent,
} }
if (drm_core_check_feature(dev, DRIVER_MODESET)) { if (drm_core_check_feature(dev, DRIVER_MODESET)) {
pci_set_drvdata(pdev, dev);
ret = drm_get_minor(dev, &dev->control, DRM_MINOR_CONTROL); ret = drm_get_minor(dev, &dev->control, DRM_MINOR_CONTROL);
if (ret) if (ret)
goto err_g2; goto err_g2;
...@@ -404,9 +405,9 @@ int drm_get_dev(struct pci_dev *pdev, const struct pci_device_id *ent, ...@@ -404,9 +405,9 @@ int drm_get_dev(struct pci_dev *pdev, const struct pci_device_id *ent,
list_add_tail(&dev->driver_item, &driver->device_list); list_add_tail(&dev->driver_item, &driver->device_list);
DRM_INFO("Initialized %s %d.%d.%d %s on minor %d\n", DRM_INFO("Initialized %s %d.%d.%d %s for %s on minor %d\n",
driver->name, driver->major, driver->minor, driver->patchlevel, driver->name, driver->major, driver->minor, driver->patchlevel,
driver->date, dev->primary->index); driver->date, pci_name(pdev), dev->primary->index);
return 0; return 0;
...@@ -418,29 +419,7 @@ int drm_get_dev(struct pci_dev *pdev, const struct pci_device_id *ent, ...@@ -418,29 +419,7 @@ int drm_get_dev(struct pci_dev *pdev, const struct pci_device_id *ent,
drm_free(dev, sizeof(*dev), DRM_MEM_STUB); drm_free(dev, sizeof(*dev), DRM_MEM_STUB);
return ret; return ret;
} }
EXPORT_SYMBOL(drm_get_dev);
/**
* Put a device minor number.
*
* \param dev device data structure
* \return always zero
*
* Cleans up the proc resources. If it is the last minor then release the foreign
* "drm" data, otherwise unregisters the "drm" data, frees the dev list and
* unregisters the character device.
*/
int drm_put_dev(struct drm_device * dev)
{
DRM_DEBUG("release primary %s\n", dev->driver->pci_driver.name);
if (dev->devname) {
drm_free(dev->devname, strlen(dev->devname) + 1,
DRM_MEM_DRIVER);
dev->devname = NULL;
}
drm_free(dev, sizeof(*dev), DRM_MEM_STUB);
return 0;
}
/** /**
* Put a secondary minor number. * Put a secondary minor number.
...@@ -472,3 +451,67 @@ int drm_put_minor(struct drm_minor **minor_p) ...@@ -472,3 +451,67 @@ int drm_put_minor(struct drm_minor **minor_p)
*minor_p = NULL; *minor_p = NULL;
return 0; return 0;
} }
/**
* Called via drm_exit() at module unload time or when pci device is
* unplugged.
*
* Cleans up all DRM device, calling drm_lastclose().
*
* \sa drm_init
*/
void drm_put_dev(struct drm_device *dev)
{
struct drm_driver *driver = dev->driver;
struct drm_map_list *r_list, *list_temp;
DRM_DEBUG("\n");
if (!dev) {
DRM_ERROR("cleanup called no dev\n");
return;
}
drm_vblank_cleanup(dev);
drm_lastclose(dev);
if (drm_core_has_MTRR(dev) && drm_core_has_AGP(dev) &&
dev->agp && dev->agp->agp_mtrr >= 0) {
int retval;
retval = mtrr_del(dev->agp->agp_mtrr,
dev->agp->agp_info.aper_base,
dev->agp->agp_info.aper_size * 1024 * 1024);
DRM_DEBUG("mtrr_del=%d\n", retval);
}
if (dev->driver->unload)
dev->driver->unload(dev);
if (drm_core_has_AGP(dev) && dev->agp) {
drm_free(dev->agp, sizeof(*dev->agp), DRM_MEM_AGPLISTS);
dev->agp = NULL;
}
drm_ht_remove(&dev->map_hash);
drm_ctxbitmap_cleanup(dev);
list_for_each_entry_safe(r_list, list_temp, &dev->maplist, head)
drm_rmmap(dev, r_list->map);
if (drm_core_check_feature(dev, DRIVER_MODESET))
drm_put_minor(&dev->control);
if (driver->driver_features & DRIVER_GEM)
drm_gem_destroy(dev);
drm_put_minor(&dev->primary);
if (dev->devname) {
drm_free(dev->devname, strlen(dev->devname) + 1,
DRM_MEM_DRIVER);
dev->devname = NULL;
}
drm_free(dev, sizeof(*dev), DRM_MEM_STUB);
}
EXPORT_SYMBOL(drm_put_dev);
...@@ -35,7 +35,9 @@ static int drm_sysfs_suspend(struct device *dev, pm_message_t state) ...@@ -35,7 +35,9 @@ static int drm_sysfs_suspend(struct device *dev, pm_message_t state)
struct drm_minor *drm_minor = to_drm_minor(dev); struct drm_minor *drm_minor = to_drm_minor(dev);
struct drm_device *drm_dev = drm_minor->dev; struct drm_device *drm_dev = drm_minor->dev;
if (drm_minor->type == DRM_MINOR_LEGACY && drm_dev->driver->suspend) if (drm_minor->type == DRM_MINOR_LEGACY &&
!drm_core_check_feature(drm_dev, DRIVER_MODESET) &&
drm_dev->driver->suspend)
return drm_dev->driver->suspend(drm_dev, state); return drm_dev->driver->suspend(drm_dev, state);
return 0; return 0;
...@@ -53,7 +55,9 @@ static int drm_sysfs_resume(struct device *dev) ...@@ -53,7 +55,9 @@ static int drm_sysfs_resume(struct device *dev)
struct drm_minor *drm_minor = to_drm_minor(dev); struct drm_minor *drm_minor = to_drm_minor(dev);
struct drm_device *drm_dev = drm_minor->dev; struct drm_device *drm_dev = drm_minor->dev;
if (drm_minor->type == DRM_MINOR_LEGACY && drm_dev->driver->resume) if (drm_minor->type == DRM_MINOR_LEGACY &&
!drm_core_check_feature(drm_dev, DRIVER_MODESET) &&
drm_dev->driver->resume)
return drm_dev->driver->resume(drm_dev); return drm_dev->driver->resume(drm_dev);
return 0; return 0;
...@@ -118,20 +122,6 @@ void drm_sysfs_destroy(void) ...@@ -118,20 +122,6 @@ void drm_sysfs_destroy(void)
class_destroy(drm_class); class_destroy(drm_class);
} }
static ssize_t show_dri(struct device *device, struct device_attribute *attr,
char *buf)
{
struct drm_minor *drm_minor = to_drm_minor(device);
struct drm_device *drm_dev = drm_minor->dev;
if (drm_dev->driver->dri_library_name)
return drm_dev->driver->dri_library_name(drm_dev, buf);
return snprintf(buf, PAGE_SIZE, "%s\n", drm_dev->driver->pci_driver.name);
}
static struct device_attribute device_attrs[] = {
__ATTR(dri_library_name, S_IRUGO, show_dri, NULL),
};
/** /**
* drm_sysfs_device_release - do nothing * drm_sysfs_device_release - do nothing
* @dev: Linux device * @dev: Linux device
...@@ -474,7 +464,6 @@ void drm_sysfs_hotplug_event(struct drm_device *dev) ...@@ -474,7 +464,6 @@ void drm_sysfs_hotplug_event(struct drm_device *dev)
int drm_sysfs_device_add(struct drm_minor *minor) int drm_sysfs_device_add(struct drm_minor *minor)
{ {
int err; int err;
int i, j;
char *minor_str; char *minor_str;
minor->kdev.parent = &minor->dev->pdev->dev; minor->kdev.parent = &minor->dev->pdev->dev;
...@@ -496,18 +485,8 @@ int drm_sysfs_device_add(struct drm_minor *minor) ...@@ -496,18 +485,8 @@ int drm_sysfs_device_add(struct drm_minor *minor)
goto err_out; goto err_out;
} }
for (i = 0; i < ARRAY_SIZE(device_attrs); i++) {
err = device_create_file(&minor->kdev, &device_attrs[i]);
if (err)
goto err_out_files;
}
return 0; return 0;
err_out_files:
if (i > 0)
for (j = 0; j < i; j++)
device_remove_file(&minor->kdev, &device_attrs[j]);
device_unregister(&minor->kdev); device_unregister(&minor->kdev);
err_out: err_out:
...@@ -523,9 +502,5 @@ int drm_sysfs_device_add(struct drm_minor *minor) ...@@ -523,9 +502,5 @@ int drm_sysfs_device_add(struct drm_minor *minor)
*/ */
void drm_sysfs_device_remove(struct drm_minor *minor) void drm_sysfs_device_remove(struct drm_minor *minor)
{ {
int i;
for (i = 0; i < ARRAY_SIZE(device_attrs); i++)
device_remove_file(&minor->kdev, &device_attrs[i]);
device_unregister(&minor->kdev); device_unregister(&minor->kdev);
} }
...@@ -91,7 +91,7 @@ static int drm_do_vm_fault(struct vm_area_struct *vma, struct vm_fault *vmf) ...@@ -91,7 +91,7 @@ static int drm_do_vm_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
{ {
struct drm_file *priv = vma->vm_file->private_data; struct drm_file *priv = vma->vm_file->private_data;
struct drm_device *dev = priv->minor->dev; struct drm_device *dev = priv->minor->dev;
struct drm_map *map = NULL; struct drm_local_map *map = NULL;
struct drm_map_list *r_list; struct drm_map_list *r_list;
struct drm_hash_item *hash; struct drm_hash_item *hash;
...@@ -115,9 +115,9 @@ static int drm_do_vm_fault(struct vm_area_struct *vma, struct vm_fault *vmf) ...@@ -115,9 +115,9 @@ static int drm_do_vm_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
* Using vm_pgoff as a selector forces us to use this unusual * Using vm_pgoff as a selector forces us to use this unusual
* addressing scheme. * addressing scheme.
*/ */
unsigned long offset = (unsigned long)vmf->virtual_address - resource_size_t offset = (unsigned long)vmf->virtual_address -
vma->vm_start; vma->vm_start;
unsigned long baddr = map->offset + offset; resource_size_t baddr = map->offset + offset;
struct drm_agp_mem *agpmem; struct drm_agp_mem *agpmem;
struct page *page; struct page *page;
...@@ -149,8 +149,10 @@ static int drm_do_vm_fault(struct vm_area_struct *vma, struct vm_fault *vmf) ...@@ -149,8 +149,10 @@ static int drm_do_vm_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
vmf->page = page; vmf->page = page;
DRM_DEBUG DRM_DEBUG
("baddr = 0x%lx page = 0x%p, offset = 0x%lx, count=%d\n", ("baddr = 0x%llx page = 0x%p, offset = 0x%llx, count=%d\n",
baddr, __va(agpmem->memory->memory[offset]), offset, (unsigned long long)baddr,
__va(agpmem->memory->memory[offset]),
(unsigned long long)offset,
page_count(page)); page_count(page));
return 0; return 0;
} }
...@@ -176,7 +178,7 @@ static int drm_do_vm_fault(struct vm_area_struct *vma, struct vm_fault *vmf) ...@@ -176,7 +178,7 @@ static int drm_do_vm_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
*/ */
static int drm_do_vm_shm_fault(struct vm_area_struct *vma, struct vm_fault *vmf) static int drm_do_vm_shm_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
{ {
struct drm_map *map = (struct drm_map *) vma->vm_private_data; struct drm_local_map *map = vma->vm_private_data;
unsigned long offset; unsigned long offset;
unsigned long i; unsigned long i;
struct page *page; struct page *page;
...@@ -209,7 +211,7 @@ static void drm_vm_shm_close(struct vm_area_struct *vma) ...@@ -209,7 +211,7 @@ static void drm_vm_shm_close(struct vm_area_struct *vma)
struct drm_file *priv = vma->vm_file->private_data; struct drm_file *priv = vma->vm_file->private_data;
struct drm_device *dev = priv->minor->dev; struct drm_device *dev = priv->minor->dev;
struct drm_vma_entry *pt, *temp; struct drm_vma_entry *pt, *temp;
struct drm_map *map; struct drm_local_map *map;
struct drm_map_list *r_list; struct drm_map_list *r_list;
int found_maps = 0; int found_maps = 0;
...@@ -322,7 +324,7 @@ static int drm_do_vm_dma_fault(struct vm_area_struct *vma, struct vm_fault *vmf) ...@@ -322,7 +324,7 @@ static int drm_do_vm_dma_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
*/ */
static int drm_do_vm_sg_fault(struct vm_area_struct *vma, struct vm_fault *vmf) static int drm_do_vm_sg_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
{ {
struct drm_map *map = (struct drm_map *) vma->vm_private_data; struct drm_local_map *map = vma->vm_private_data;
struct drm_file *priv = vma->vm_file->private_data; struct drm_file *priv = vma->vm_file->private_data;
struct drm_device *dev = priv->minor->dev; struct drm_device *dev = priv->minor->dev;
struct drm_sg_mem *entry = dev->sg; struct drm_sg_mem *entry = dev->sg;
...@@ -512,14 +514,14 @@ static int drm_mmap_dma(struct file *filp, struct vm_area_struct *vma) ...@@ -512,14 +514,14 @@ static int drm_mmap_dma(struct file *filp, struct vm_area_struct *vma)
return 0; return 0;
} }
unsigned long drm_core_get_map_ofs(struct drm_map * map) resource_size_t drm_core_get_map_ofs(struct drm_local_map * map)
{ {
return map->offset; return map->offset;
} }
EXPORT_SYMBOL(drm_core_get_map_ofs); EXPORT_SYMBOL(drm_core_get_map_ofs);
unsigned long drm_core_get_reg_ofs(struct drm_device *dev) resource_size_t drm_core_get_reg_ofs(struct drm_device *dev)
{ {
#ifdef __alpha__ #ifdef __alpha__
return dev->hose->dense_mem_base - dev->hose->mem_space->start; return dev->hose->dense_mem_base - dev->hose->mem_space->start;
...@@ -547,8 +549,8 @@ int drm_mmap_locked(struct file *filp, struct vm_area_struct *vma) ...@@ -547,8 +549,8 @@ int drm_mmap_locked(struct file *filp, struct vm_area_struct *vma)
{ {
struct drm_file *priv = filp->private_data; struct drm_file *priv = filp->private_data;
struct drm_device *dev = priv->minor->dev; struct drm_device *dev = priv->minor->dev;
struct drm_map *map = NULL; struct drm_local_map *map = NULL;
unsigned long offset = 0; resource_size_t offset = 0;
struct drm_hash_item *hash; struct drm_hash_item *hash;
DRM_DEBUG("start = 0x%lx, end = 0x%lx, page offset = 0x%lx\n", DRM_DEBUG("start = 0x%lx, end = 0x%lx, page offset = 0x%lx\n",
...@@ -623,9 +625,9 @@ int drm_mmap_locked(struct file *filp, struct vm_area_struct *vma) ...@@ -623,9 +625,9 @@ int drm_mmap_locked(struct file *filp, struct vm_area_struct *vma)
vma->vm_page_prot)) vma->vm_page_prot))
return -EAGAIN; return -EAGAIN;
DRM_DEBUG(" Type = %d; start = 0x%lx, end = 0x%lx," DRM_DEBUG(" Type = %d; start = 0x%lx, end = 0x%lx,"
" offset = 0x%lx\n", " offset = 0x%llx\n",
map->type, map->type,
vma->vm_start, vma->vm_end, map->offset + offset); vma->vm_start, vma->vm_end, (unsigned long long)(map->offset + offset));
vma->vm_ops = &drm_vm_ops; vma->vm_ops = &drm_vm_ops;
break; break;
case _DRM_CONSISTENT: case _DRM_CONSISTENT:
......
...@@ -77,8 +77,8 @@ typedef struct _drm_i810_ring_buffer { ...@@ -77,8 +77,8 @@ typedef struct _drm_i810_ring_buffer {
} drm_i810_ring_buffer_t; } drm_i810_ring_buffer_t;
typedef struct drm_i810_private { typedef struct drm_i810_private {
struct drm_map *sarea_map; struct drm_local_map *sarea_map;
struct drm_map *mmio_map; struct drm_local_map *mmio_map;
drm_i810_sarea_t *sarea_priv; drm_i810_sarea_t *sarea_priv;
drm_i810_ring_buffer_t ring; drm_i810_ring_buffer_t ring;
......
...@@ -84,8 +84,8 @@ typedef struct _drm_i830_ring_buffer { ...@@ -84,8 +84,8 @@ typedef struct _drm_i830_ring_buffer {
} drm_i830_ring_buffer_t; } drm_i830_ring_buffer_t;
typedef struct drm_i830_private { typedef struct drm_i830_private {
struct drm_map *sarea_map; struct drm_local_map *sarea_map;
struct drm_map *mmio_map; struct drm_local_map *mmio_map;
drm_i830_sarea_t *sarea_priv; drm_i830_sarea_t *sarea_priv;
drm_i830_ring_buffer_t ring; drm_i830_ring_buffer_t ring;
......
...@@ -1099,7 +1099,7 @@ void i915_master_destroy(struct drm_device *dev, struct drm_master *master) ...@@ -1099,7 +1099,7 @@ void i915_master_destroy(struct drm_device *dev, struct drm_master *master)
int i915_driver_load(struct drm_device *dev, unsigned long flags) int i915_driver_load(struct drm_device *dev, unsigned long flags)
{ {
struct drm_i915_private *dev_priv = dev->dev_private; struct drm_i915_private *dev_priv = dev->dev_private;
unsigned long base, size; resource_size_t base, size;
int ret = 0, mmio_bar = IS_I9XX(dev) ? 0 : 1; int ret = 0, mmio_bar = IS_I9XX(dev) ? 0 : 1;
/* i915 has 4 more counters */ /* i915 has 4 more counters */
......
...@@ -42,6 +42,8 @@ module_param_named(modeset, i915_modeset, int, 0400); ...@@ -42,6 +42,8 @@ module_param_named(modeset, i915_modeset, int, 0400);
unsigned int i915_fbpercrtc = 0; unsigned int i915_fbpercrtc = 0;
module_param_named(fbpercrtc, i915_fbpercrtc, int, 0400); module_param_named(fbpercrtc, i915_fbpercrtc, int, 0400);
static struct drm_driver driver;
static struct pci_device_id pciidlist[] = { static struct pci_device_id pciidlist[] = {
i915_PCI_IDS i915_PCI_IDS
}; };
...@@ -117,6 +119,36 @@ static int i915_resume(struct drm_device *dev) ...@@ -117,6 +119,36 @@ static int i915_resume(struct drm_device *dev)
return ret; return ret;
} }
static int __devinit
i915_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
{
return drm_get_dev(pdev, ent, &driver);
}
static void
i915_pci_remove(struct pci_dev *pdev)
{
struct drm_device *dev = pci_get_drvdata(pdev);
drm_put_dev(dev);
}
static int
i915_pci_suspend(struct pci_dev *pdev, pm_message_t state)
{
struct drm_device *dev = pci_get_drvdata(pdev);
return i915_suspend(dev, state);
}
static int
i915_pci_resume(struct pci_dev *pdev)
{
struct drm_device *dev = pci_get_drvdata(pdev);
return i915_resume(dev);
}
static struct vm_operations_struct i915_gem_vm_ops = { static struct vm_operations_struct i915_gem_vm_ops = {
.fault = i915_gem_fault, .fault = i915_gem_fault,
.open = drm_gem_vm_open, .open = drm_gem_vm_open,
...@@ -174,6 +206,12 @@ static struct drm_driver driver = { ...@@ -174,6 +206,12 @@ static struct drm_driver driver = {
.pci_driver = { .pci_driver = {
.name = DRIVER_NAME, .name = DRIVER_NAME,
.id_table = pciidlist, .id_table = pciidlist,
.probe = i915_pci_probe,
.remove = i915_pci_remove,
#ifdef CONFIG_PM
.resume = i915_pci_resume,
.suspend = i915_pci_suspend,
#endif
}, },
.name = DRIVER_NAME, .name = DRIVER_NAME,
......
...@@ -446,13 +446,16 @@ fast_shmem_write(struct page **pages, ...@@ -446,13 +446,16 @@ fast_shmem_write(struct page **pages,
int length) int length)
{ {
char __iomem *vaddr; char __iomem *vaddr;
unsigned long unwritten;
vaddr = kmap_atomic(pages[page_base >> PAGE_SHIFT], KM_USER0); vaddr = kmap_atomic(pages[page_base >> PAGE_SHIFT], KM_USER0);
if (vaddr == NULL) if (vaddr == NULL)
return -ENOMEM; return -ENOMEM;
__copy_from_user_inatomic(vaddr + page_offset, data, length); unwritten = __copy_from_user_inatomic(vaddr + page_offset, data, length);
kunmap_atomic(vaddr, KM_USER0); kunmap_atomic(vaddr, KM_USER0);
if (unwritten)
return -EFAULT;
return 0; return 0;
} }
...@@ -1093,7 +1096,7 @@ i915_gem_create_mmap_offset(struct drm_gem_object *obj) ...@@ -1093,7 +1096,7 @@ i915_gem_create_mmap_offset(struct drm_gem_object *obj)
struct drm_gem_mm *mm = dev->mm_private; struct drm_gem_mm *mm = dev->mm_private;
struct drm_i915_gem_object *obj_priv = obj->driver_private; struct drm_i915_gem_object *obj_priv = obj->driver_private;
struct drm_map_list *list; struct drm_map_list *list;
struct drm_map *map; struct drm_local_map *map;
int ret = 0; int ret = 0;
/* Set the object up for mmap'ing */ /* Set the object up for mmap'ing */
......
...@@ -148,8 +148,8 @@ void mga_do_dma_flush(drm_mga_private_t * dev_priv) ...@@ -148,8 +148,8 @@ void mga_do_dma_flush(drm_mga_private_t * dev_priv)
primary->space = head - tail; primary->space = head - tail;
} }
DRM_DEBUG(" head = 0x%06lx\n", head - dev_priv->primary->offset); DRM_DEBUG(" head = 0x%06lx\n", (unsigned long)(head - dev_priv->primary->offset));
DRM_DEBUG(" tail = 0x%06lx\n", tail - dev_priv->primary->offset); DRM_DEBUG(" tail = 0x%06lx\n", (unsigned long)(tail - dev_priv->primary->offset));
DRM_DEBUG(" space = 0x%06x\n", primary->space); DRM_DEBUG(" space = 0x%06x\n", primary->space);
mga_flush_write_combine(); mga_flush_write_combine();
...@@ -187,7 +187,7 @@ void mga_do_dma_wrap_start(drm_mga_private_t * dev_priv) ...@@ -187,7 +187,7 @@ void mga_do_dma_wrap_start(drm_mga_private_t * dev_priv)
primary->space = head - dev_priv->primary->offset; primary->space = head - dev_priv->primary->offset;
} }
DRM_DEBUG(" head = 0x%06lx\n", head - dev_priv->primary->offset); DRM_DEBUG(" head = 0x%06lx\n", (unsigned long)(head - dev_priv->primary->offset));
DRM_DEBUG(" tail = 0x%06x\n", primary->tail); DRM_DEBUG(" tail = 0x%06x\n", primary->tail);
DRM_DEBUG(" wrap = %d\n", primary->last_wrap); DRM_DEBUG(" wrap = %d\n", primary->last_wrap);
DRM_DEBUG(" space = 0x%06x\n", primary->space); DRM_DEBUG(" space = 0x%06x\n", primary->space);
...@@ -239,7 +239,7 @@ static void mga_freelist_print(struct drm_device * dev) ...@@ -239,7 +239,7 @@ static void mga_freelist_print(struct drm_device * dev)
for (entry = dev_priv->head->next; entry; entry = entry->next) { for (entry = dev_priv->head->next; entry; entry = entry->next) {
DRM_INFO(" %p idx=%2d age=0x%x 0x%06lx\n", DRM_INFO(" %p idx=%2d age=0x%x 0x%06lx\n",
entry, entry->buf->idx, entry->age.head, entry, entry->buf->idx, entry->age.head,
entry->age.head - dev_priv->primary->offset); (unsigned long)(entry->age.head - dev_priv->primary->offset));
} }
DRM_INFO("\n"); DRM_INFO("\n");
} }
...@@ -340,10 +340,10 @@ static struct drm_buf *mga_freelist_get(struct drm_device * dev) ...@@ -340,10 +340,10 @@ static struct drm_buf *mga_freelist_get(struct drm_device * dev)
DRM_DEBUG(" tail=0x%06lx %d\n", DRM_DEBUG(" tail=0x%06lx %d\n",
tail->age.head ? tail->age.head ?
tail->age.head - dev_priv->primary->offset : 0, (unsigned long)(tail->age.head - dev_priv->primary->offset) : 0,
tail->age.wrap); tail->age.wrap);
DRM_DEBUG(" head=0x%06lx %d\n", DRM_DEBUG(" head=0x%06lx %d\n",
head - dev_priv->primary->offset, wrap); (unsigned long)(head - dev_priv->primary->offset), wrap);
if (TEST_AGE(&tail->age, head, wrap)) { if (TEST_AGE(&tail->age, head, wrap)) {
prev = dev_priv->tail->prev; prev = dev_priv->tail->prev;
...@@ -366,8 +366,9 @@ int mga_freelist_put(struct drm_device * dev, struct drm_buf * buf) ...@@ -366,8 +366,9 @@ int mga_freelist_put(struct drm_device * dev, struct drm_buf * buf)
drm_mga_freelist_t *head, *entry, *prev; drm_mga_freelist_t *head, *entry, *prev;
DRM_DEBUG("age=0x%06lx wrap=%d\n", DRM_DEBUG("age=0x%06lx wrap=%d\n",
buf_priv->list_entry->age.head - (unsigned long)(buf_priv->list_entry->age.head -
dev_priv->primary->offset, buf_priv->list_entry->age.wrap); dev_priv->primary->offset),
buf_priv->list_entry->age.wrap);
entry = buf_priv->list_entry; entry = buf_priv->list_entry;
head = dev_priv->head; head = dev_priv->head;
......
...@@ -113,8 +113,8 @@ typedef struct drm_mga_private { ...@@ -113,8 +113,8 @@ typedef struct drm_mga_private {
* \sa drm_mga_private_t::mmio * \sa drm_mga_private_t::mmio
*/ */
/*@{ */ /*@{ */
u32 mmio_base; /**< Bus address of base of MMIO. */ resource_size_t mmio_base; /**< Bus address of base of MMIO. */
u32 mmio_size; /**< Size of the MMIO region. */ resource_size_t mmio_size; /**< Size of the MMIO region. */
/*@} */ /*@} */
u32 clear_cmd; u32 clear_cmd;
...@@ -317,8 +317,8 @@ do { \ ...@@ -317,8 +317,8 @@ do { \
DRM_INFO( "\n" ); \ DRM_INFO( "\n" ); \
DRM_INFO( " tail=0x%06x head=0x%06lx\n", \ DRM_INFO( " tail=0x%06x head=0x%06lx\n", \
dev_priv->prim.tail, \ dev_priv->prim.tail, \
MGA_READ( MGA_PRIMADDRESS ) - \ (unsigned long)(MGA_READ(MGA_PRIMADDRESS) - \
dev_priv->primary->offset ); \ dev_priv->primary->offset)); \
} \ } \
if ( !test_bit( 0, &dev_priv->prim.wrapped ) ) { \ if ( !test_bit( 0, &dev_priv->prim.wrapped ) ) { \
if ( dev_priv->prim.space < \ if ( dev_priv->prim.space < \
......
...@@ -525,11 +525,12 @@ static int r128_do_init_cce(struct drm_device * dev, drm_r128_init_t * init) ...@@ -525,11 +525,12 @@ static int r128_do_init_cce(struct drm_device * dev, drm_r128_init_t * init)
} else } else
#endif #endif
{ {
dev_priv->cce_ring->handle = (void *)dev_priv->cce_ring->offset; dev_priv->cce_ring->handle =
(void *)(unsigned long)dev_priv->cce_ring->offset;
dev_priv->ring_rptr->handle = dev_priv->ring_rptr->handle =
(void *)dev_priv->ring_rptr->offset; (void *)(unsigned long)dev_priv->ring_rptr->offset;
dev->agp_buffer_map->handle = dev->agp_buffer_map->handle =
(void *)dev->agp_buffer_map->offset; (void *)(unsigned long)dev->agp_buffer_map->offset;
} }
#if __OS_HAS_AGP #if __OS_HAS_AGP
......
...@@ -3,7 +3,7 @@ ...@@ -3,7 +3,7 @@
# Direct Rendering Infrastructure (DRI) in XFree86 4.1.0 and higher. # Direct Rendering Infrastructure (DRI) in XFree86 4.1.0 and higher.
ccflags-y := -Iinclude/drm ccflags-y := -Iinclude/drm
radeon-y := radeon_drv.o radeon_cp.o radeon_state.o radeon_mem.o radeon_irq.o r300_cmdbuf.o radeon-y := radeon_drv.o radeon_cp.o radeon_state.o radeon_mem.o radeon_irq.o r300_cmdbuf.o r600_cp.o
radeon-$(CONFIG_COMPAT) += radeon_ioc32.o radeon-$(CONFIG_COMPAT) += radeon_ioc32.o
......
...@@ -37,6 +37,8 @@ ...@@ -37,6 +37,8 @@
#include "radeon_drv.h" #include "radeon_drv.h"
#include "r300_reg.h" #include "r300_reg.h"
#include <asm/unaligned.h>
#define R300_SIMULTANEOUS_CLIPRECTS 4 #define R300_SIMULTANEOUS_CLIPRECTS 4
/* Values for R300_RE_CLIPRECT_CNTL depending on the number of cliprects /* Values for R300_RE_CLIPRECT_CNTL depending on the number of cliprects
...@@ -205,6 +207,10 @@ void r300_init_reg_flags(struct drm_device *dev) ...@@ -205,6 +207,10 @@ void r300_init_reg_flags(struct drm_device *dev)
ADD_RANGE(0x42C0, 2); ADD_RANGE(0x42C0, 2);
ADD_RANGE(R300_RS_CNTL_0, 2); ADD_RANGE(R300_RS_CNTL_0, 2);
ADD_RANGE(R300_SU_REG_DEST, 1);
if ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV530)
ADD_RANGE(RV530_FG_ZBREG_DEST, 1);
ADD_RANGE(R300_SC_HYPERZ, 2); ADD_RANGE(R300_SC_HYPERZ, 2);
ADD_RANGE(0x43E8, 1); ADD_RANGE(0x43E8, 1);
...@@ -230,6 +236,7 @@ void r300_init_reg_flags(struct drm_device *dev) ...@@ -230,6 +236,7 @@ void r300_init_reg_flags(struct drm_device *dev)
ADD_RANGE(R300_ZB_DEPTHPITCH, 1); ADD_RANGE(R300_ZB_DEPTHPITCH, 1);
ADD_RANGE(R300_ZB_DEPTHCLEARVALUE, 1); ADD_RANGE(R300_ZB_DEPTHCLEARVALUE, 1);
ADD_RANGE(R300_ZB_ZMASK_OFFSET, 13); ADD_RANGE(R300_ZB_ZMASK_OFFSET, 13);
ADD_RANGE(R300_ZB_ZPASS_DATA, 2); /* ZB_ZPASS_DATA, ZB_ZPASS_ADDR */
ADD_RANGE(R300_TX_FILTER_0, 16); ADD_RANGE(R300_TX_FILTER_0, 16);
ADD_RANGE(R300_TX_FILTER1_0, 16); ADD_RANGE(R300_TX_FILTER1_0, 16);
...@@ -917,6 +924,7 @@ static int r300_scratch(drm_radeon_private_t *dev_priv, ...@@ -917,6 +924,7 @@ static int r300_scratch(drm_radeon_private_t *dev_priv,
{ {
u32 *ref_age_base; u32 *ref_age_base;
u32 i, buf_idx, h_pending; u32 i, buf_idx, h_pending;
u64 ptr_addr;
RING_LOCALS; RING_LOCALS;
if (cmdbuf->bufsz < if (cmdbuf->bufsz <
...@@ -930,7 +938,8 @@ static int r300_scratch(drm_radeon_private_t *dev_priv, ...@@ -930,7 +938,8 @@ static int r300_scratch(drm_radeon_private_t *dev_priv,
dev_priv->scratch_ages[header.scratch.reg]++; dev_priv->scratch_ages[header.scratch.reg]++;
ref_age_base = (u32 *)(unsigned long)*((uint64_t *)cmdbuf->buf); ptr_addr = get_unaligned((u64 *)cmdbuf->buf);
ref_age_base = (u32 *)(unsigned long)ptr_addr;
cmdbuf->buf += sizeof(u64); cmdbuf->buf += sizeof(u64);
cmdbuf->bufsz -= sizeof(u64); cmdbuf->bufsz -= sizeof(u64);
......
...@@ -1770,4 +1770,9 @@ USE OR OTHER DEALINGS IN THE SOFTWARE. ...@@ -1770,4 +1770,9 @@ USE OR OTHER DEALINGS IN THE SOFTWARE.
#define R500_RB3D_COLOR_CLEAR_VALUE_AR 0x46c0 #define R500_RB3D_COLOR_CLEAR_VALUE_AR 0x46c0
#define R500_RB3D_CONSTANT_COLOR_AR 0x4ef8 #define R500_RB3D_CONSTANT_COLOR_AR 0x4ef8
#define R300_SU_REG_DEST 0x42c8
#define RV530_FG_ZBREG_DEST 0x4be8
#define R300_ZB_ZPASS_DATA 0x4f58
#define R300_ZB_ZPASS_ADDR 0x4f5c
#endif /* _R300_REG_H */ #endif /* _R300_REG_H */
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
...@@ -41,23 +41,15 @@ int radeon_no_wb; ...@@ -41,23 +41,15 @@ int radeon_no_wb;
MODULE_PARM_DESC(no_wb, "Disable AGP writeback for scratch registers"); MODULE_PARM_DESC(no_wb, "Disable AGP writeback for scratch registers");
module_param_named(no_wb, radeon_no_wb, int, 0444); module_param_named(no_wb, radeon_no_wb, int, 0444);
static int dri_library_name(struct drm_device *dev, char *buf)
{
drm_radeon_private_t *dev_priv = dev->dev_private;
int family = dev_priv->flags & RADEON_FAMILY_MASK;
return snprintf(buf, PAGE_SIZE, "%s\n",
(family < CHIP_R200) ? "radeon" :
((family < CHIP_R300) ? "r200" :
"r300"));
}
static int radeon_suspend(struct drm_device *dev, pm_message_t state) static int radeon_suspend(struct drm_device *dev, pm_message_t state)
{ {
drm_radeon_private_t *dev_priv = dev->dev_private; drm_radeon_private_t *dev_priv = dev->dev_private;
if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_R600)
return 0;
/* Disable *all* interrupts */ /* Disable *all* interrupts */
if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_RS690) if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_RS600)
RADEON_WRITE(R500_DxMODE_INT_MASK, 0); RADEON_WRITE(R500_DxMODE_INT_MASK, 0);
RADEON_WRITE(RADEON_GEN_INT_CNTL, 0); RADEON_WRITE(RADEON_GEN_INT_CNTL, 0);
return 0; return 0;
...@@ -67,8 +59,11 @@ static int radeon_resume(struct drm_device *dev) ...@@ -67,8 +59,11 @@ static int radeon_resume(struct drm_device *dev)
{ {
drm_radeon_private_t *dev_priv = dev->dev_private; drm_radeon_private_t *dev_priv = dev->dev_private;
if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_R600)
return 0;
/* Restore interrupt registers */ /* Restore interrupt registers */
if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_RS690) if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_RS600)
RADEON_WRITE(R500_DxMODE_INT_MASK, dev_priv->r500_disp_irq_reg); RADEON_WRITE(R500_DxMODE_INT_MASK, dev_priv->r500_disp_irq_reg);
RADEON_WRITE(RADEON_GEN_INT_CNTL, dev_priv->irq_enable_reg); RADEON_WRITE(RADEON_GEN_INT_CNTL, dev_priv->irq_enable_reg);
return 0; return 0;
...@@ -95,7 +90,6 @@ static struct drm_driver driver = { ...@@ -95,7 +90,6 @@ static struct drm_driver driver = {
.get_vblank_counter = radeon_get_vblank_counter, .get_vblank_counter = radeon_get_vblank_counter,
.enable_vblank = radeon_enable_vblank, .enable_vblank = radeon_enable_vblank,
.disable_vblank = radeon_disable_vblank, .disable_vblank = radeon_disable_vblank,
.dri_library_name = dri_library_name,
.master_create = radeon_master_create, .master_create = radeon_master_create,
.master_destroy = radeon_master_destroy, .master_destroy = radeon_master_destroy,
.irq_preinstall = radeon_driver_irq_preinstall, .irq_preinstall = radeon_driver_irq_preinstall,
......
This diff is collapsed.
...@@ -65,7 +65,7 @@ int radeon_enable_vblank(struct drm_device *dev, int crtc) ...@@ -65,7 +65,7 @@ int radeon_enable_vblank(struct drm_device *dev, int crtc)
{ {
drm_radeon_private_t *dev_priv = dev->dev_private; drm_radeon_private_t *dev_priv = dev->dev_private;
if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_RS690) { if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_RS600) {
switch (crtc) { switch (crtc) {
case 0: case 0:
r500_vbl_irq_set_state(dev, R500_D1MODE_INT_MASK, 1); r500_vbl_irq_set_state(dev, R500_D1MODE_INT_MASK, 1);
...@@ -100,7 +100,7 @@ void radeon_disable_vblank(struct drm_device *dev, int crtc) ...@@ -100,7 +100,7 @@ void radeon_disable_vblank(struct drm_device *dev, int crtc)
{ {
drm_radeon_private_t *dev_priv = dev->dev_private; drm_radeon_private_t *dev_priv = dev->dev_private;
if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_RS690) { if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_RS600) {
switch (crtc) { switch (crtc) {
case 0: case 0:
r500_vbl_irq_set_state(dev, R500_D1MODE_INT_MASK, 0); r500_vbl_irq_set_state(dev, R500_D1MODE_INT_MASK, 0);
...@@ -135,7 +135,7 @@ static inline u32 radeon_acknowledge_irqs(drm_radeon_private_t *dev_priv, u32 *r ...@@ -135,7 +135,7 @@ static inline u32 radeon_acknowledge_irqs(drm_radeon_private_t *dev_priv, u32 *r
u32 irq_mask = RADEON_SW_INT_TEST; u32 irq_mask = RADEON_SW_INT_TEST;
*r500_disp_int = 0; *r500_disp_int = 0;
if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_RS690) { if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_RS600) {
/* vbl interrupts in a different place */ /* vbl interrupts in a different place */
if (irqs & R500_DISPLAY_INT_STATUS) { if (irqs & R500_DISPLAY_INT_STATUS) {
...@@ -202,7 +202,7 @@ irqreturn_t radeon_driver_irq_handler(DRM_IRQ_ARGS) ...@@ -202,7 +202,7 @@ irqreturn_t radeon_driver_irq_handler(DRM_IRQ_ARGS)
DRM_WAKEUP(&dev_priv->swi_queue); DRM_WAKEUP(&dev_priv->swi_queue);
/* VBLANK interrupt */ /* VBLANK interrupt */
if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_RS690) { if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_RS600) {
if (r500_disp_int & R500_D1_VBLANK_INTERRUPT) if (r500_disp_int & R500_D1_VBLANK_INTERRUPT)
drm_handle_vblank(dev, 0); drm_handle_vblank(dev, 0);
if (r500_disp_int & R500_D2_VBLANK_INTERRUPT) if (r500_disp_int & R500_D2_VBLANK_INTERRUPT)
...@@ -265,7 +265,7 @@ u32 radeon_get_vblank_counter(struct drm_device *dev, int crtc) ...@@ -265,7 +265,7 @@ u32 radeon_get_vblank_counter(struct drm_device *dev, int crtc)
return -EINVAL; return -EINVAL;
} }
if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_RS690) { if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_RS600) {
if (crtc == 0) if (crtc == 0)
return RADEON_READ(R500_D1CRTC_FRAME_COUNT); return RADEON_READ(R500_D1CRTC_FRAME_COUNT);
else else
...@@ -327,7 +327,7 @@ void radeon_driver_irq_preinstall(struct drm_device * dev) ...@@ -327,7 +327,7 @@ void radeon_driver_irq_preinstall(struct drm_device * dev)
u32 dummy; u32 dummy;
/* Disable *all* interrupts */ /* Disable *all* interrupts */
if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_RS690) if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_RS600)
RADEON_WRITE(R500_DxMODE_INT_MASK, 0); RADEON_WRITE(R500_DxMODE_INT_MASK, 0);
RADEON_WRITE(RADEON_GEN_INT_CNTL, 0); RADEON_WRITE(RADEON_GEN_INT_CNTL, 0);
...@@ -357,7 +357,7 @@ void radeon_driver_irq_uninstall(struct drm_device * dev) ...@@ -357,7 +357,7 @@ void radeon_driver_irq_uninstall(struct drm_device * dev)
if (!dev_priv) if (!dev_priv)
return; return;
if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_RS690) if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_RS600)
RADEON_WRITE(R500_DxMODE_INT_MASK, 0); RADEON_WRITE(R500_DxMODE_INT_MASK, 0);
/* Disable *all* interrupts */ /* Disable *all* interrupts */
RADEON_WRITE(RADEON_GEN_INT_CNTL, 0); RADEON_WRITE(RADEON_GEN_INT_CNTL, 0);
......
...@@ -1556,9 +1556,15 @@ static void radeon_cp_discard_buffer(struct drm_device *dev, struct drm_master * ...@@ -1556,9 +1556,15 @@ static void radeon_cp_discard_buffer(struct drm_device *dev, struct drm_master *
buf_priv->age = ++master_priv->sarea_priv->last_dispatch; buf_priv->age = ++master_priv->sarea_priv->last_dispatch;
/* Emit the vertex buffer age */ /* Emit the vertex buffer age */
BEGIN_RING(2); if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_R600) {
RADEON_DISPATCH_AGE(buf_priv->age); BEGIN_RING(3);
ADVANCE_RING(); R600_DISPATCH_AGE(buf_priv->age);
ADVANCE_RING();
} else {
BEGIN_RING(2);
RADEON_DISPATCH_AGE(buf_priv->age);
ADVANCE_RING();
}
buf->pending = 1; buf->pending = 1;
buf->used = 0; buf->used = 0;
...@@ -1980,7 +1986,7 @@ static int alloc_surface(drm_radeon_surface_alloc_t *new, ...@@ -1980,7 +1986,7 @@ static int alloc_surface(drm_radeon_surface_alloc_t *new,
/* find a virtual surface */ /* find a virtual surface */
for (i = 0; i < 2 * RADEON_MAX_SURFACES; i++) for (i = 0; i < 2 * RADEON_MAX_SURFACES; i++)
if (dev_priv->virt_surfaces[i].file_priv == 0) if (dev_priv->virt_surfaces[i].file_priv == NULL)
break; break;
if (i == 2 * RADEON_MAX_SURFACES) { if (i == 2 * RADEON_MAX_SURFACES) {
return -1; return -1;
...@@ -2473,24 +2479,25 @@ static int radeon_cp_indirect(struct drm_device *dev, void *data, struct drm_fil ...@@ -2473,24 +2479,25 @@ static int radeon_cp_indirect(struct drm_device *dev, void *data, struct drm_fil
buf->used = indirect->end; buf->used = indirect->end;
/* Wait for the 3D stream to idle before the indirect buffer
* containing 2D acceleration commands is processed.
*/
BEGIN_RING(2);
RADEON_WAIT_UNTIL_3D_IDLE();
ADVANCE_RING();
/* Dispatch the indirect buffer full of commands from the /* Dispatch the indirect buffer full of commands from the
* X server. This is insecure and is thus only available to * X server. This is insecure and is thus only available to
* privileged clients. * privileged clients.
*/ */
radeon_cp_dispatch_indirect(dev, buf, indirect->start, indirect->end); if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_R600)
if (indirect->discard) { r600_cp_dispatch_indirect(dev, buf, indirect->start, indirect->end);
radeon_cp_discard_buffer(dev, file_priv->master, buf); else {
/* Wait for the 3D stream to idle before the indirect buffer
* containing 2D acceleration commands is processed.
*/
BEGIN_RING(2);
RADEON_WAIT_UNTIL_3D_IDLE();
ADVANCE_RING();
radeon_cp_dispatch_indirect(dev, buf, indirect->start, indirect->end);
} }
if (indirect->discard)
radeon_cp_discard_buffer(dev, file_priv->master, buf);
COMMIT_RING(); COMMIT_RING();
return 0; return 0;
} }
...@@ -3010,14 +3017,14 @@ static int radeon_cp_getparam(struct drm_device *dev, void *data, struct drm_fil ...@@ -3010,14 +3017,14 @@ static int radeon_cp_getparam(struct drm_device *dev, void *data, struct drm_fil
break; break;
case RADEON_PARAM_LAST_FRAME: case RADEON_PARAM_LAST_FRAME:
dev_priv->stats.last_frame_reads++; dev_priv->stats.last_frame_reads++;
value = GET_SCRATCH(0); value = GET_SCRATCH(dev_priv, 0);
break; break;
case RADEON_PARAM_LAST_DISPATCH: case RADEON_PARAM_LAST_DISPATCH:
value = GET_SCRATCH(1); value = GET_SCRATCH(dev_priv, 1);
break; break;
case RADEON_PARAM_LAST_CLEAR: case RADEON_PARAM_LAST_CLEAR:
dev_priv->stats.last_clear_reads++; dev_priv->stats.last_clear_reads++;
value = GET_SCRATCH(2); value = GET_SCRATCH(dev_priv, 2);
break; break;
case RADEON_PARAM_IRQ_NR: case RADEON_PARAM_IRQ_NR:
value = drm_dev_to_irq(dev); value = drm_dev_to_irq(dev);
...@@ -3052,7 +3059,10 @@ static int radeon_cp_getparam(struct drm_device *dev, void *data, struct drm_fil ...@@ -3052,7 +3059,10 @@ static int radeon_cp_getparam(struct drm_device *dev, void *data, struct drm_fil
case RADEON_PARAM_SCRATCH_OFFSET: case RADEON_PARAM_SCRATCH_OFFSET:
if (!dev_priv->writeback_works) if (!dev_priv->writeback_works)
return -EINVAL; return -EINVAL;
value = RADEON_SCRATCH_REG_OFFSET; if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_R600)
value = R600_SCRATCH_REG_OFFSET;
else
value = RADEON_SCRATCH_REG_OFFSET;
break; break;
case RADEON_PARAM_CARD_TYPE: case RADEON_PARAM_CARD_TYPE:
if (dev_priv->flags & RADEON_IS_PCIE) if (dev_priv->flags & RADEON_IS_PCIE)
...@@ -3155,6 +3165,7 @@ void radeon_driver_preclose(struct drm_device *dev, struct drm_file *file_priv) ...@@ -3155,6 +3165,7 @@ void radeon_driver_preclose(struct drm_device *dev, struct drm_file *file_priv)
void radeon_driver_lastclose(struct drm_device *dev) void radeon_driver_lastclose(struct drm_device *dev)
{ {
radeon_surfaces_release(PCIGART_FILE_PRIV, dev->dev_private);
radeon_do_release(dev); radeon_do_release(dev);
} }
......
...@@ -599,8 +599,8 @@ int savage_driver_firstopen(struct drm_device *dev) ...@@ -599,8 +599,8 @@ int savage_driver_firstopen(struct drm_device *dev)
drm_mtrr_add(dev_priv->mtrr[2].base, drm_mtrr_add(dev_priv->mtrr[2].base,
dev_priv->mtrr[2].size, DRM_MTRR_WC); dev_priv->mtrr[2].size, DRM_MTRR_WC);
} else { } else {
DRM_ERROR("strange pci_resource_len %08lx\n", DRM_ERROR("strange pci_resource_len %08llx\n",
drm_get_resource_len(dev, 0)); (unsigned long long)drm_get_resource_len(dev, 0));
} }
} else if (dev_priv->chipset != S3_SUPERSAVAGE && } else if (dev_priv->chipset != S3_SUPERSAVAGE &&
dev_priv->chipset != S3_SAVAGE2000) { dev_priv->chipset != S3_SAVAGE2000) {
...@@ -620,8 +620,8 @@ int savage_driver_firstopen(struct drm_device *dev) ...@@ -620,8 +620,8 @@ int savage_driver_firstopen(struct drm_device *dev)
drm_mtrr_add(dev_priv->mtrr[0].base, drm_mtrr_add(dev_priv->mtrr[0].base,
dev_priv->mtrr[0].size, DRM_MTRR_WC); dev_priv->mtrr[0].size, DRM_MTRR_WC);
} else { } else {
DRM_ERROR("strange pci_resource_len %08lx\n", DRM_ERROR("strange pci_resource_len %08llx\n",
drm_get_resource_len(dev, 1)); (unsigned long long)drm_get_resource_len(dev, 1));
} }
} else { } else {
mmio_base = drm_get_resource_start(dev, 0); mmio_base = drm_get_resource_start(dev, 0);
......
...@@ -28,11 +28,6 @@ ...@@ -28,11 +28,6 @@
#include "drm_pciids.h" #include "drm_pciids.h"
static int dri_library_name(struct drm_device *dev, char *buf)
{
return snprintf(buf, PAGE_SIZE, "unichrome");
}
static struct pci_device_id pciidlist[] = { static struct pci_device_id pciidlist[] = {
viadrv_PCI_IDS viadrv_PCI_IDS
}; };
...@@ -52,7 +47,6 @@ static struct drm_driver driver = { ...@@ -52,7 +47,6 @@ static struct drm_driver driver = {
.irq_uninstall = via_driver_irq_uninstall, .irq_uninstall = via_driver_irq_uninstall,
.irq_handler = via_driver_irq_handler, .irq_handler = via_driver_irq_handler,
.dma_quiescent = via_driver_dma_quiescent, .dma_quiescent = via_driver_dma_quiescent,
.dri_library_name = dri_library_name,
.reclaim_buffers = drm_core_reclaim_buffers, .reclaim_buffers = drm_core_reclaim_buffers,
.reclaim_buffers_locked = NULL, .reclaim_buffers_locked = NULL,
.reclaim_buffers_idlelocked = via_reclaim_buffers_locked, .reclaim_buffers_idlelocked = via_reclaim_buffers_locked,
......
...@@ -281,16 +281,16 @@ typedef int drm_ioctl_compat_t(struct file *filp, unsigned int cmd, ...@@ -281,16 +281,16 @@ typedef int drm_ioctl_compat_t(struct file *filp, unsigned int cmd,
struct drm_ioctl_desc { struct drm_ioctl_desc {
unsigned int cmd; unsigned int cmd;
drm_ioctl_t *func;
int flags; int flags;
drm_ioctl_t *func;
}; };
/** /**
* Creates a driver or general drm_ioctl_desc array entry for the given * Creates a driver or general drm_ioctl_desc array entry for the given
* ioctl, for use by drm_ioctl(). * ioctl, for use by drm_ioctl().
*/ */
#define DRM_IOCTL_DEF(ioctl, func, flags) \ #define DRM_IOCTL_DEF(ioctl, _func, _flags) \
[DRM_IOCTL_NR(ioctl)] = {ioctl, func, flags} [DRM_IOCTL_NR(ioctl)] = {.cmd = ioctl, .func = _func, .flags = _flags}
struct drm_magic_entry { struct drm_magic_entry {
struct list_head head; struct list_head head;
...@@ -522,20 +522,33 @@ struct drm_mm { ...@@ -522,20 +522,33 @@ struct drm_mm {
}; };
/**
* Kernel side of a mapping
*/
struct drm_local_map {
resource_size_t offset; /**< Requested physical address (0 for SAREA)*/
unsigned long size; /**< Requested physical size (bytes) */
enum drm_map_type type; /**< Type of memory to map */
enum drm_map_flags flags; /**< Flags */
void *handle; /**< User-space: "Handle" to pass to mmap() */
/**< Kernel-space: kernel-virtual address */
int mtrr; /**< MTRR slot used */
};
typedef struct drm_local_map drm_local_map_t;
/** /**
* Mappings list * Mappings list
*/ */
struct drm_map_list { struct drm_map_list {
struct list_head head; /**< list head */ struct list_head head; /**< list head */
struct drm_hash_item hash; struct drm_hash_item hash;
struct drm_map *map; /**< mapping */ struct drm_local_map *map; /**< mapping */
uint64_t user_token; uint64_t user_token;
struct drm_master *master; struct drm_master *master;
struct drm_mm_node *file_offset_node; /**< fake offset */ struct drm_mm_node *file_offset_node; /**< fake offset */
}; };
typedef struct drm_map drm_local_map_t;
/** /**
* Context handle list * Context handle list
*/ */
...@@ -560,7 +573,7 @@ struct drm_ati_pcigart_info { ...@@ -560,7 +573,7 @@ struct drm_ati_pcigart_info {
dma_addr_t bus_addr; dma_addr_t bus_addr;
dma_addr_t table_mask; dma_addr_t table_mask;
struct drm_dma_handle *table_handle; struct drm_dma_handle *table_handle;
drm_local_map_t mapping; struct drm_local_map mapping;
int table_size; int table_size;
}; };
...@@ -675,7 +688,6 @@ struct drm_driver { ...@@ -675,7 +688,6 @@ struct drm_driver {
int (*kernel_context_switch) (struct drm_device *dev, int old, int (*kernel_context_switch) (struct drm_device *dev, int old,
int new); int new);
void (*kernel_context_switch_unlock) (struct drm_device *dev); void (*kernel_context_switch_unlock) (struct drm_device *dev);
int (*dri_library_name) (struct drm_device *dev, char *buf);
/** /**
* get_vblank_counter - get raw hardware vblank counter * get_vblank_counter - get raw hardware vblank counter
...@@ -747,8 +759,8 @@ struct drm_driver { ...@@ -747,8 +759,8 @@ struct drm_driver {
struct drm_file *file_priv); struct drm_file *file_priv);
void (*reclaim_buffers_idlelocked) (struct drm_device *dev, void (*reclaim_buffers_idlelocked) (struct drm_device *dev,
struct drm_file *file_priv); struct drm_file *file_priv);
unsigned long (*get_map_ofs) (struct drm_map * map); resource_size_t (*get_map_ofs) (struct drm_local_map * map);
unsigned long (*get_reg_ofs) (struct drm_device *dev); resource_size_t (*get_reg_ofs) (struct drm_device *dev);
void (*set_version) (struct drm_device *dev, void (*set_version) (struct drm_device *dev,
struct drm_set_version *sv); struct drm_set_version *sv);
...@@ -981,7 +993,7 @@ struct drm_device { ...@@ -981,7 +993,7 @@ struct drm_device {
sigset_t sigmask; sigset_t sigmask;
struct drm_driver *driver; struct drm_driver *driver;
drm_local_map_t *agp_buffer_map; struct drm_local_map *agp_buffer_map;
unsigned int agp_buffer_token; unsigned int agp_buffer_token;
struct drm_minor *control; /**< Control node for card */ struct drm_minor *control; /**< Control node for card */
struct drm_minor *primary; /**< render type primary screen head */ struct drm_minor *primary; /**< render type primary screen head */
...@@ -1098,8 +1110,8 @@ extern int drm_release(struct inode *inode, struct file *filp); ...@@ -1098,8 +1110,8 @@ extern int drm_release(struct inode *inode, struct file *filp);
extern int drm_mmap(struct file *filp, struct vm_area_struct *vma); extern int drm_mmap(struct file *filp, struct vm_area_struct *vma);
extern int drm_mmap_locked(struct file *filp, struct vm_area_struct *vma); extern int drm_mmap_locked(struct file *filp, struct vm_area_struct *vma);
extern void drm_vm_open_locked(struct vm_area_struct *vma); extern void drm_vm_open_locked(struct vm_area_struct *vma);
extern unsigned long drm_core_get_map_ofs(struct drm_map * map); extern resource_size_t drm_core_get_map_ofs(struct drm_local_map * map);
extern unsigned long drm_core_get_reg_ofs(struct drm_device *dev); extern resource_size_t drm_core_get_reg_ofs(struct drm_device *dev);
extern unsigned int drm_poll(struct file *filp, struct poll_table_struct *wait); extern unsigned int drm_poll(struct file *filp, struct poll_table_struct *wait);
/* Memory management support (drm_memory.h) */ /* Memory management support (drm_memory.h) */
...@@ -1202,13 +1214,13 @@ extern int drm_i_have_hw_lock(struct drm_device *dev, struct drm_file *file_priv ...@@ -1202,13 +1214,13 @@ extern int drm_i_have_hw_lock(struct drm_device *dev, struct drm_file *file_priv
/* Buffer management support (drm_bufs.h) */ /* Buffer management support (drm_bufs.h) */
extern int drm_addbufs_agp(struct drm_device *dev, struct drm_buf_desc * request); extern int drm_addbufs_agp(struct drm_device *dev, struct drm_buf_desc * request);
extern int drm_addbufs_pci(struct drm_device *dev, struct drm_buf_desc * request); extern int drm_addbufs_pci(struct drm_device *dev, struct drm_buf_desc * request);
extern int drm_addmap(struct drm_device *dev, unsigned int offset, extern int drm_addmap(struct drm_device *dev, resource_size_t offset,
unsigned int size, enum drm_map_type type, unsigned int size, enum drm_map_type type,
enum drm_map_flags flags, drm_local_map_t ** map_ptr); enum drm_map_flags flags, struct drm_local_map **map_ptr);
extern int drm_addmap_ioctl(struct drm_device *dev, void *data, extern int drm_addmap_ioctl(struct drm_device *dev, void *data,
struct drm_file *file_priv); struct drm_file *file_priv);
extern int drm_rmmap(struct drm_device *dev, drm_local_map_t *map); extern int drm_rmmap(struct drm_device *dev, struct drm_local_map *map);
extern int drm_rmmap_locked(struct drm_device *dev, drm_local_map_t *map); extern int drm_rmmap_locked(struct drm_device *dev, struct drm_local_map *map);
extern int drm_rmmap_ioctl(struct drm_device *dev, void *data, extern int drm_rmmap_ioctl(struct drm_device *dev, void *data,
struct drm_file *file_priv); struct drm_file *file_priv);
extern int drm_addbufs(struct drm_device *dev, void *data, extern int drm_addbufs(struct drm_device *dev, void *data,
...@@ -1222,10 +1234,10 @@ extern int drm_freebufs(struct drm_device *dev, void *data, ...@@ -1222,10 +1234,10 @@ extern int drm_freebufs(struct drm_device *dev, void *data,
extern int drm_mapbufs(struct drm_device *dev, void *data, extern int drm_mapbufs(struct drm_device *dev, void *data,
struct drm_file *file_priv); struct drm_file *file_priv);
extern int drm_order(unsigned long size); extern int drm_order(unsigned long size);
extern unsigned long drm_get_resource_start(struct drm_device *dev, extern resource_size_t drm_get_resource_start(struct drm_device *dev,
unsigned int resource);
extern resource_size_t drm_get_resource_len(struct drm_device *dev,
unsigned int resource); unsigned int resource);
extern unsigned long drm_get_resource_len(struct drm_device *dev,
unsigned int resource);
/* DMA support (drm_dma.h) */ /* DMA support (drm_dma.h) */
extern int drm_dma_setup(struct drm_device *dev); extern int drm_dma_setup(struct drm_device *dev);
...@@ -1301,7 +1313,7 @@ extern struct drm_master *drm_master_get(struct drm_master *master); ...@@ -1301,7 +1313,7 @@ extern struct drm_master *drm_master_get(struct drm_master *master);
extern void drm_master_put(struct drm_master **master); extern void drm_master_put(struct drm_master **master);
extern int drm_get_dev(struct pci_dev *pdev, const struct pci_device_id *ent, extern int drm_get_dev(struct pci_dev *pdev, const struct pci_device_id *ent,
struct drm_driver *driver); struct drm_driver *driver);
extern int drm_put_dev(struct drm_device *dev); extern void drm_put_dev(struct drm_device *dev);
extern int drm_put_minor(struct drm_minor **minor); extern int drm_put_minor(struct drm_minor **minor);
extern unsigned int drm_debug; extern unsigned int drm_debug;
...@@ -1311,7 +1323,7 @@ extern struct dentry *drm_debugfs_root; ...@@ -1311,7 +1323,7 @@ extern struct dentry *drm_debugfs_root;
extern struct idr drm_minors_idr; extern struct idr drm_minors_idr;
extern drm_local_map_t *drm_getsarea(struct drm_device *dev); extern struct drm_local_map *drm_getsarea(struct drm_device *dev);
/* Proc support (drm_proc.h) */ /* Proc support (drm_proc.h) */
extern int drm_proc_init(struct drm_minor *minor, int minor_id, extern int drm_proc_init(struct drm_minor *minor, int minor_id,
...@@ -1453,12 +1465,12 @@ int drm_gem_open_ioctl(struct drm_device *dev, void *data, ...@@ -1453,12 +1465,12 @@ int drm_gem_open_ioctl(struct drm_device *dev, void *data,
void drm_gem_open(struct drm_device *dev, struct drm_file *file_private); void drm_gem_open(struct drm_device *dev, struct drm_file *file_private);
void drm_gem_release(struct drm_device *dev, struct drm_file *file_private); void drm_gem_release(struct drm_device *dev, struct drm_file *file_private);
extern void drm_core_ioremap(struct drm_map *map, struct drm_device *dev); extern void drm_core_ioremap(struct drm_local_map *map, struct drm_device *dev);
extern void drm_core_ioremap_wc(struct drm_map *map, struct drm_device *dev); extern void drm_core_ioremap_wc(struct drm_local_map *map, struct drm_device *dev);
extern void drm_core_ioremapfree(struct drm_map *map, struct drm_device *dev); extern void drm_core_ioremapfree(struct drm_local_map *map, struct drm_device *dev);
static __inline__ struct drm_map *drm_core_findmap(struct drm_device *dev, static __inline__ struct drm_local_map *drm_core_findmap(struct drm_device *dev,
unsigned int token) unsigned int token)
{ {
struct drm_map_list *_entry; struct drm_map_list *_entry;
list_for_each_entry(_entry, &dev->maplist, head) list_for_each_entry(_entry, &dev->maplist, head)
...@@ -1485,7 +1497,7 @@ static __inline__ int drm_device_is_pcie(struct drm_device *dev) ...@@ -1485,7 +1497,7 @@ static __inline__ int drm_device_is_pcie(struct drm_device *dev)
return pci_find_capability(dev->pdev, PCI_CAP_ID_EXP); return pci_find_capability(dev->pdev, PCI_CAP_ID_EXP);
} }
static __inline__ void drm_core_dropmap(struct drm_map *map) static __inline__ void drm_core_dropmap(struct drm_local_map *map)
{ {
} }
......
...@@ -550,7 +550,7 @@ struct drm_mode_config { ...@@ -550,7 +550,7 @@ struct drm_mode_config {
int min_width, min_height; int min_width, min_height;
int max_width, max_height; int max_width, max_height;
struct drm_mode_config_funcs *funcs; struct drm_mode_config_funcs *funcs;
unsigned long fb_base; resource_size_t fb_base;
/* pointers to standard properties */ /* pointers to standard properties */
struct list_head property_blob_list; struct list_head property_blob_list;
...@@ -613,7 +613,8 @@ extern void drm_fb_release(struct drm_file *file_priv); ...@@ -613,7 +613,8 @@ extern void drm_fb_release(struct drm_file *file_priv);
extern int drm_mode_group_init_legacy_group(struct drm_device *dev, struct drm_mode_group *group); extern int drm_mode_group_init_legacy_group(struct drm_device *dev, struct drm_mode_group *group);
extern struct edid *drm_get_edid(struct drm_connector *connector, extern struct edid *drm_get_edid(struct drm_connector *connector,
struct i2c_adapter *adapter); struct i2c_adapter *adapter);
extern unsigned char *drm_do_probe_ddc_edid(struct i2c_adapter *adapter); extern int drm_do_probe_ddc_edid(struct i2c_adapter *adapter,
unsigned char *buf, int len);
extern int drm_add_edid_modes(struct drm_connector *connector, struct edid *edid); extern int drm_add_edid_modes(struct drm_connector *connector, struct edid *edid);
extern void drm_mode_probed_add(struct drm_connector *connector, struct drm_display_mode *mode); extern void drm_mode_probed_add(struct drm_connector *connector, struct drm_display_mode *mode);
extern void drm_mode_remove(struct drm_connector *connector, struct drm_display_mode *mode); extern void drm_mode_remove(struct drm_connector *connector, struct drm_display_mode *mode);
...@@ -731,4 +732,5 @@ extern int drm_mode_gamma_get_ioctl(struct drm_device *dev, ...@@ -731,4 +732,5 @@ extern int drm_mode_gamma_get_ioctl(struct drm_device *dev,
void *data, struct drm_file *file_priv); void *data, struct drm_file *file_priv);
extern int drm_mode_gamma_set_ioctl(struct drm_device *dev, extern int drm_mode_gamma_set_ioctl(struct drm_device *dev,
void *data, struct drm_file *file_priv); void *data, struct drm_file *file_priv);
extern bool drm_detect_hdmi_monitor(struct edid *edid);
#endif /* __DRM_CRTC_H__ */ #endif /* __DRM_CRTC_H__ */
...@@ -6,6 +6,19 @@ ...@@ -6,6 +6,19 @@
#include <linux/interrupt.h> /* For task queue support */ #include <linux/interrupt.h> /* For task queue support */
#include <linux/delay.h> #include <linux/delay.h>
#ifndef readq
static u64 readq(void __iomem *reg)
{
return ((u64) readl(reg)) | (((u64) readl(reg + 4UL)) << 32);
}
static void writeq(u64 val, void __iomem *reg)
{
writel(val & 0xffffffff, reg);
writel(val >> 32, reg + 0x4UL);
}
#endif
/** Current process ID */ /** Current process ID */
#define DRM_CURRENTPID task_pid_nr(current) #define DRM_CURRENTPID task_pid_nr(current)
#define DRM_SUSER(p) capable(CAP_SYS_ADMIN) #define DRM_SUSER(p) capable(CAP_SYS_ADMIN)
...@@ -23,6 +36,12 @@ ...@@ -23,6 +36,12 @@
/** Write a dword into a MMIO region */ /** Write a dword into a MMIO region */
#define DRM_WRITE32(map, offset, val) writel(val, ((void __iomem *)(map)->handle) + (offset)) #define DRM_WRITE32(map, offset, val) writel(val, ((void __iomem *)(map)->handle) + (offset))
/** Read memory barrier */ /** Read memory barrier */
/** Read a qword from a MMIO region - be careful using these unless you really understand them */
#define DRM_READ64(map, offset) readq(((void __iomem *)(map)->handle) + (offset))
/** Write a qword into a MMIO region */
#define DRM_WRITE64(map, offset, val) writeq(val, ((void __iomem *)(map)->handle) + (offset))
#define DRM_READMEMORYBARRIER() rmb() #define DRM_READMEMORYBARRIER() rmb()
/** Write memory barrier */ /** Write memory barrier */
#define DRM_WRITEMEMORYBARRIER() wmb() #define DRM_WRITEMEMORYBARRIER() wmb()
......
This diff is collapsed.
...@@ -306,6 +306,8 @@ typedef union { ...@@ -306,6 +306,8 @@ typedef union {
#define RADEON_SCRATCH_REG_OFFSET 32 #define RADEON_SCRATCH_REG_OFFSET 32
#define R600_SCRATCH_REG_OFFSET 256
#define RADEON_NR_SAREA_CLIPRECTS 12 #define RADEON_NR_SAREA_CLIPRECTS 12
/* There are 2 heaps (local/GART). Each region within a heap is a /* There are 2 heaps (local/GART). Each region within a heap is a
...@@ -528,7 +530,8 @@ typedef struct drm_radeon_init { ...@@ -528,7 +530,8 @@ typedef struct drm_radeon_init {
RADEON_INIT_CP = 0x01, RADEON_INIT_CP = 0x01,
RADEON_CLEANUP_CP = 0x02, RADEON_CLEANUP_CP = 0x02,
RADEON_INIT_R200_CP = 0x03, RADEON_INIT_R200_CP = 0x03,
RADEON_INIT_R300_CP = 0x04 RADEON_INIT_R300_CP = 0x04,
RADEON_INIT_R600_CP = 0x05
} func; } func;
unsigned long sarea_priv_offset; unsigned long sarea_priv_offset;
int is_pci; int is_pci;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment