summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEric Anholt <anholt@freebsd.org>2005-08-26 20:56:11 +0000
committerEric Anholt <anholt@freebsd.org>2005-08-26 20:56:11 +0000
commitc425ad1a34439d019edd589c32a7161d01b4d822 (patch)
treebbb5ce64e4b791cb01c62e144e3b3e7e4b86d829
parent5105f9ea59179c7129d3bf97734eb37e26ec68b0 (diff)
Previously, drm_get_resource_start() and drm_get_resource_len() would
allocate the resource RF_ACTIVE, pull out the appropriate value, and return it. However, allocating large framebuffers RF_ACTIVE would run the system out of KVA, and this also left open the possibility of the resource getting moved after getting the offset. Instead, when either of these are called, allocate the resource if it isn't allocated already (non-RF_ACTIVE) and store it in the DRM device, to be cleaned up on lastclose.
-rw-r--r--bsd-core/drmP.h7
-rw-r--r--bsd-core/drm_bufs.c55
-rw-r--r--bsd-core/drm_drv.c7
3 files changed, 42 insertions, 27 deletions
diff --git a/bsd-core/drmP.h b/bsd-core/drmP.h
index d5907355..751714b6 100644
--- a/bsd-core/drmP.h
+++ b/bsd-core/drmP.h
@@ -686,6 +686,9 @@ struct drm_driver_info {
unsigned use_mtrr :1;
};
+/* Length for the array of resource pointers for drm_get_resource_*. */
+#define DRM_MAX_PCI_RESOURCE 3
+
/**
* DRM device functions structure
*/
@@ -748,6 +751,10 @@ struct drm_device {
#endif
void *irqh; /* Handle from bus_setup_intr */
+ /* Storage of resource pointers for drm_get_resource_* */
+ struct resource *pcir[DRM_MAX_PCI_RESOURCE];
+ int pcirid[DRM_MAX_PCI_RESOURCE];
+
int pci_domain;
int pci_bus;
int pci_slot;
diff --git a/bsd-core/drm_bufs.c b/bsd-core/drm_bufs.c
index 5ce2d4de..1df0238d 100644
--- a/bsd-core/drm_bufs.c
+++ b/bsd-core/drm_bufs.c
@@ -31,6 +31,8 @@
*
*/
+#include "dev/pci/pcireg.h"
+
#include "drmP.h"
/*
@@ -49,46 +51,45 @@ int drm_order(unsigned long size)
return order;
}
-unsigned long drm_get_resource_start(drm_device_t *dev, unsigned int resource)
+/* Allocation of PCI memory resources (framebuffer, registers, etc.) for
+ * drm_get_resource_*. Note that they are not RF_ACTIVE, so there's no virtual
+ * address for accessing them. Cleaned up at lastclose.
+ */
+static int drm_alloc_resource(drm_device_t *dev, int resource)
{
- struct resource *bsr;
- unsigned long offset;
+ if (resource >= DRM_MAX_PCI_RESOURCE) {
+ DRM_ERROR("Resource %d too large\n", resource);
+ return 1;
+ }
+ if (dev->pcir[resource] != NULL)
+ return 0;
- resource = resource * 4 + 0x10;
+ dev->pcirid[resource] = PCIR_BAR(resource);
+ dev->pcir[resource] = bus_alloc_resource_any(dev->device,
+ SYS_RES_MEMORY, &dev->pcirid[resource], RF_SHAREABLE);
- bsr = bus_alloc_resource_any(dev->device, SYS_RES_MEMORY, &resource,
- RF_ACTIVE | RF_SHAREABLE);
- if (bsr == NULL) {
+ if (dev->pcir[resource] == NULL) {
DRM_ERROR("Couldn't find resource 0x%x\n", resource);
- return 0;
+ return 1;
}
- offset = rman_get_start(bsr);
+ return 0;
+}
- bus_release_resource(dev->device, SYS_RES_MEMORY, resource, bsr);
+unsigned long drm_get_resource_start(drm_device_t *dev, unsigned int resource)
+{
+ if (drm_alloc_resource(dev, resource) != 0)
+ return 0;
- return offset;
+ return rman_get_start(dev->pcir[resource]);
}
unsigned long drm_get_resource_len(drm_device_t *dev, unsigned int resource)
{
- struct resource *bsr;
- unsigned long len;
-
- resource = resource * 4 + 0x10;
-
- bsr = bus_alloc_resource_any(dev->device, SYS_RES_MEMORY, &resource,
- RF_ACTIVE | RF_SHAREABLE);
- if (bsr == NULL) {
- DRM_ERROR("Couldn't find resource 0x%x\n", resource);
- return ENOMEM;
- }
-
- len = rman_get_size(bsr);
-
- bus_release_resource(dev->device, SYS_RES_MEMORY, resource, bsr);
+ if (drm_alloc_resource(dev, resource) != 0)
+ return 0;
- return len;
+ return rman_get_size(dev->pcir[resource]);
}
int drm_addmap(drm_device_t * dev, unsigned long offset, unsigned long size,
diff --git a/bsd-core/drm_drv.c b/bsd-core/drm_drv.c
index c4ee39cb..63024132 100644
--- a/bsd-core/drm_drv.c
+++ b/bsd-core/drm_drv.c
@@ -474,6 +474,13 @@ static int drm_lastclose(drm_device_t *dev)
TAILQ_FOREACH_SAFE(map, &dev->maplist, link, mapsave) {
drm_rmmap(dev, map);
}
+ for (i = 0; i < DRM_MAX_PCI_RESOURCE; i++) {
+ if (dev->pcir[i] == NULL)
+ continue;
+ bus_release_resource(dev->device, SYS_RES_MEMORY,
+ dev->pcirid[i], dev->pcir[i]);
+ dev->pcir[i] = NULL;
+ }
drm_dma_takedown(dev);
if ( dev->lock.hw_lock ) {