aboutsummaryrefslogtreecommitdiff
path: root/drivers/gpu/drm/i915/i915_dma.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/drm/i915/i915_dma.c')
-rw-r--r--drivers/gpu/drm/i915/i915_dma.c132
1 files changed, 91 insertions, 41 deletions
diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c
index 1a60626f680..50d1f782768 100644
--- a/drivers/gpu/drm/i915/i915_dma.c
+++ b/drivers/gpu/drm/i915/i915_dma.c
@@ -643,9 +643,9 @@ static int i915_batchbuffer(struct drm_device *dev, void *data,
return -EINVAL;
if (batch->num_cliprects) {
- cliprects = drm_calloc(batch->num_cliprects,
- sizeof(struct drm_clip_rect),
- DRM_MEM_DRIVER);
+ cliprects = kcalloc(batch->num_cliprects,
+ sizeof(struct drm_clip_rect),
+ GFP_KERNEL);
if (cliprects == NULL)
return -ENOMEM;
@@ -664,9 +664,7 @@ static int i915_batchbuffer(struct drm_device *dev, void *data,
sarea_priv->last_dispatch = READ_BREADCRUMB(dev_priv);
fail_free:
- drm_free(cliprects,
- batch->num_cliprects * sizeof(struct drm_clip_rect),
- DRM_MEM_DRIVER);
+ kfree(cliprects);
return ret;
}
@@ -692,7 +690,7 @@ static int i915_cmdbuffer(struct drm_device *dev, void *data,
if (cmdbuf->num_cliprects < 0)
return -EINVAL;
- batch_data = drm_alloc(cmdbuf->sz, DRM_MEM_DRIVER);
+ batch_data = kmalloc(cmdbuf->sz, GFP_KERNEL);
if (batch_data == NULL)
return -ENOMEM;
@@ -701,9 +699,8 @@ static int i915_cmdbuffer(struct drm_device *dev, void *data,
goto fail_batch_free;
if (cmdbuf->num_cliprects) {
- cliprects = drm_calloc(cmdbuf->num_cliprects,
- sizeof(struct drm_clip_rect),
- DRM_MEM_DRIVER);
+ cliprects = kcalloc(cmdbuf->num_cliprects,
+ sizeof(struct drm_clip_rect), GFP_KERNEL);
if (cliprects == NULL)
goto fail_batch_free;
@@ -726,11 +723,9 @@ static int i915_cmdbuffer(struct drm_device *dev, void *data,
sarea_priv->last_dispatch = READ_BREADCRUMB(dev_priv);
fail_clip_free:
- drm_free(cliprects,
- cmdbuf->num_cliprects * sizeof(struct drm_clip_rect),
- DRM_MEM_DRIVER);
+ kfree(cliprects);
fail_batch_free:
- drm_free(batch_data, cmdbuf->sz, DRM_MEM_DRIVER);
+ kfree(batch_data);
return ret;
}
@@ -851,7 +846,7 @@ static int i915_set_status_page(struct drm_device *dev, void *data,
return 0;
}
- printk(KERN_DEBUG "set status page addr 0x%08x\n", (u32)hws->addr);
+ DRM_DEBUG("set status page addr 0x%08x\n", (u32)hws->addr);
dev_priv->status_gfx_addr = hws->addr & (0x1ffff<<12);
@@ -890,8 +885,8 @@ static int i915_set_status_page(struct drm_device *dev, void *data,
* some RAM for the framebuffer at early boot. This code figures out
* how much was set aside so we can use it for our own purposes.
*/
-static int i915_probe_agp(struct drm_device *dev, unsigned long *aperture_size,
- unsigned long *preallocated_size)
+static int i915_probe_agp(struct drm_device *dev, uint32_t *aperture_size,
+ uint32_t *preallocated_size)
{
struct pci_dev *bridge_dev;
u16 tmp = 0;
@@ -989,10 +984,11 @@ static int i915_probe_agp(struct drm_device *dev, unsigned long *aperture_size,
return 0;
}
-static int i915_load_modeset_init(struct drm_device *dev)
+static int i915_load_modeset_init(struct drm_device *dev,
+ unsigned long prealloc_size,
+ unsigned long agp_size)
{
struct drm_i915_private *dev_priv = dev->dev_private;
- unsigned long agp_size, prealloc_size;
int fb_bar = IS_I9XX(dev) ? 2 : 0;
int ret = 0;
@@ -1007,10 +1003,6 @@ static int i915_load_modeset_init(struct drm_device *dev)
if (IS_I965G(dev) || IS_G33(dev))
dev_priv->cursor_needs_physical = false;
- ret = i915_probe_agp(dev, &agp_size, &prealloc_size);
- if (ret)
- goto out;
-
/* Basic memrange allocator for stolen space (aka vram) */
drm_mm_init(&dev_priv->vram, 0, prealloc_size);
@@ -1067,7 +1059,7 @@ int i915_master_create(struct drm_device *dev, struct drm_master *master)
{
struct drm_i915_master_private *master_priv;
- master_priv = drm_calloc(1, sizeof(*master_priv), DRM_MEM_DRIVER);
+ master_priv = kzalloc(sizeof(*master_priv), GFP_KERNEL);
if (!master_priv)
return -ENOMEM;
@@ -1082,11 +1074,49 @@ void i915_master_destroy(struct drm_device *dev, struct drm_master *master)
if (!master_priv)
return;
- drm_free(master_priv, sizeof(*master_priv), DRM_MEM_DRIVER);
+ kfree(master_priv);
master->driver_priv = NULL;
}
+static void i915_get_mem_freq(struct drm_device *dev)
+{
+ drm_i915_private_t *dev_priv = dev->dev_private;
+ u32 tmp;
+
+ if (!IS_IGD(dev))
+ return;
+
+ tmp = I915_READ(CLKCFG);
+
+ switch (tmp & CLKCFG_FSB_MASK) {
+ case CLKCFG_FSB_533:
+ dev_priv->fsb_freq = 533; /* 133*4 */
+ break;
+ case CLKCFG_FSB_800:
+ dev_priv->fsb_freq = 800; /* 200*4 */
+ break;
+ case CLKCFG_FSB_667:
+ dev_priv->fsb_freq = 667; /* 167*4 */
+ break;
+ case CLKCFG_FSB_400:
+ dev_priv->fsb_freq = 400; /* 100*4 */
+ break;
+ }
+
+ switch (tmp & CLKCFG_MEM_MASK) {
+ case CLKCFG_MEM_533:
+ dev_priv->mem_freq = 533;
+ break;
+ case CLKCFG_MEM_667:
+ dev_priv->mem_freq = 667;
+ break;
+ case CLKCFG_MEM_800:
+ dev_priv->mem_freq = 800;
+ break;
+ }
+}
+
/**
* i915_driver_load - setup chip and create an initial config
* @dev: DRM device
@@ -1103,6 +1133,7 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags)
struct drm_i915_private *dev_priv = dev->dev_private;
resource_size_t base, size;
int ret = 0, mmio_bar = IS_I9XX(dev) ? 0 : 1;
+ uint32_t agp_size, prealloc_size;
/* i915 has 4 more counters */
dev->counters += 4;
@@ -1111,12 +1142,10 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags)
dev->types[8] = _DRM_STAT_SECONDARY;
dev->types[9] = _DRM_STAT_DMA;
- dev_priv = drm_alloc(sizeof(drm_i915_private_t), DRM_MEM_DRIVER);
+ dev_priv = kzalloc(sizeof(drm_i915_private_t), GFP_KERNEL);
if (dev_priv == NULL)
return -ENOMEM;
- memset(dev_priv, 0, sizeof(drm_i915_private_t));
-
dev->dev_private = (void *)dev_priv;
dev_priv->dev = dev;
@@ -1153,13 +1182,28 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags)
"performance may suffer.\n");
}
-#ifdef CONFIG_HIGHMEM64G
- /* don't enable GEM on PAE - needs agp + set_memory_* interface fixes */
- dev_priv->has_gem = 0;
-#else
+ ret = i915_probe_agp(dev, &agp_size, &prealloc_size);
+ if (ret)
+ goto out_iomapfree;
+
+ dev_priv->wq = create_workqueue("i915");
+ if (dev_priv->wq == NULL) {
+ DRM_ERROR("Failed to create our workqueue.\n");
+ ret = -ENOMEM;
+ goto out_iomapfree;
+ }
+
/* enable GEM by default */
dev_priv->has_gem = 1;
-#endif
+
+ if (prealloc_size > agp_size * 3 / 4) {
+ DRM_ERROR("Detected broken video BIOS with %d/%dkB of video "
+ "memory stolen.\n",
+ prealloc_size / 1024, agp_size / 1024);
+ DRM_ERROR("Disabling GEM. (try reducing stolen memory or "
+ "updating the BIOS to fix).\n");
+ dev_priv->has_gem = 0;
+ }
dev->driver->get_vblank_counter = i915_get_vblank_counter;
dev->max_vblank_count = 0xffffff; /* only 24 bits of frame count */
@@ -1174,9 +1218,11 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags)
if (!I915_NEED_GFX_HWS(dev)) {
ret = i915_init_phys_hws(dev);
if (ret != 0)
- goto out_iomapfree;
+ goto out_workqueue_free;
}
+ i915_get_mem_freq(dev);
+
/* On the 945G/GM, the chipset reports the MSI capability on the
* integrated graphics even though the support isn't actually there
* according to the published specs. It doesn't appear to function
@@ -1192,6 +1238,7 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags)
pci_enable_msi(dev->pdev);
spin_lock_init(&dev_priv->user_irq_lock);
+ spin_lock_init(&dev_priv->error_lock);
dev_priv->user_irq_refcount = 0;
ret = drm_vblank_init(dev, I915_NUM_PIPE);
@@ -1202,10 +1249,10 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags)
}
if (drm_core_check_feature(dev, DRIVER_MODESET)) {
- ret = i915_load_modeset_init(dev);
+ ret = i915_load_modeset_init(dev, prealloc_size, agp_size);
if (ret < 0) {
DRM_ERROR("failed to init modeset\n");
- goto out_rmmap;
+ goto out_workqueue_free;
}
}
@@ -1216,12 +1263,14 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags)
return 0;
+out_workqueue_free:
+ destroy_workqueue(dev_priv->wq);
out_iomapfree:
io_mapping_free(dev_priv->mm.gtt_mapping);
out_rmmap:
iounmap(dev_priv->regs);
free_priv:
- drm_free(dev_priv, sizeof(struct drm_i915_private), DRM_MEM_DRIVER);
+ kfree(dev_priv);
return ret;
}
@@ -1229,6 +1278,8 @@ int i915_driver_unload(struct drm_device *dev)
{
struct drm_i915_private *dev_priv = dev->dev_private;
+ destroy_workqueue(dev_priv->wq);
+
io_mapping_free(dev_priv->mm.gtt_mapping);
if (dev_priv->mm.gtt_mtrr >= 0) {
mtrr_del(dev_priv->mm.gtt_mtrr, dev->agp->base,
@@ -1261,8 +1312,7 @@ int i915_driver_unload(struct drm_device *dev)
i915_gem_lastclose(dev);
}
- drm_free(dev->dev_private, sizeof(drm_i915_private_t),
- DRM_MEM_DRIVER);
+ kfree(dev->dev_private);
return 0;
}
@@ -1273,7 +1323,7 @@ int i915_driver_open(struct drm_device *dev, struct drm_file *file_priv)
DRM_DEBUG_DRIVER(I915_DRV, "\n");
i915_file_priv = (struct drm_i915_file_private *)
- drm_alloc(sizeof(*i915_file_priv), DRM_MEM_FILES);
+ kmalloc(sizeof(*i915_file_priv), GFP_KERNEL);
if (!i915_file_priv)
return -ENOMEM;
@@ -1326,7 +1376,7 @@ void i915_driver_postclose(struct drm_device *dev, struct drm_file *file_priv)
{
struct drm_i915_file_private *i915_file_priv = file_priv->driver_priv;
- drm_free(i915_file_priv, sizeof(*i915_file_priv), DRM_MEM_FILES);
+ kfree(i915_file_priv);
}
struct drm_ioctl_desc i915_ioctls[] = {