Skip to content

Commit

Permalink
Merge branch 'drm-fixes' of git://git.kernel.org/pub/scm/linux/kernel…
Browse files Browse the repository at this point in the history
…/git/airlied/drm-2.6

* 'drm-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/airlied/drm-2.6:
  drm/i915: select framebuffer support automatically
  drm/i915: add get_vblank_counter function for GM45
  drm/i915: capture last_vblank count at IRQ uninstall time too
  drm/i915: Unlock mutex on i915_gem_fault() error path
  drm/i915: Quiet the message on get/setparam ioctl with an unknown value.
  drm/i915: skip LVDS initialization on Apple Mac Mini
  drm/i915: sync SDVO code with stable userland modesetting driver
  drm/i915: Unref the object after failing to set tiling mode.
  drm/i915: add fence register management to execbuf
  drm/i915: Return error from i915_gem_object_get_fence_reg() when failing.
  drm/i915: Set up an MTRR covering the GTT at driver load.
  drm/i915: Skip SDVO/HDMI init when the chipset tells us it's not present.
  drm/i915: Suppress GEM teardown on X Server exit in KMS mode.
  drm/radeon: fix ioremap conflict with AGP mappings
  i915: fix unneeded locking in i915 LVDS get modes code.
  • Loading branch information
Linus Torvalds committed Feb 9, 2009
2 parents d7c41b6 + d2f5935 commit ff74733
Show file tree
Hide file tree
Showing 18 changed files with 1,428 additions and 193 deletions.
2 changes: 1 addition & 1 deletion drivers/gpu/drm/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ config DRM_I915
select FB_CFB_FILLRECT
select FB_CFB_COPYAREA
select FB_CFB_IMAGEBLIT
depends on FB
select FB
tristate "i915 driver"
help
Choose this option if you have a system that has Intel 830M, 845G,
Expand Down
1 change: 1 addition & 0 deletions drivers/gpu/drm/drm_irq.c
Original file line number Diff line number Diff line change
Expand Up @@ -276,6 +276,7 @@ int drm_irq_uninstall(struct drm_device * dev)
for (i = 0; i < dev->num_crtcs; i++) {
DRM_WAKEUP(&dev->vbl_queue[i]);
dev->vblank_enabled[i] = 0;
dev->last_vblank[i] = dev->driver->get_vblank_counter(dev, i);
}
spin_unlock_irqrestore(&dev->vbl_lock, irqflags);

Expand Down
7 changes: 6 additions & 1 deletion drivers/gpu/drm/drm_memory.c
Original file line number Diff line number Diff line change
Expand Up @@ -171,9 +171,14 @@ EXPORT_SYMBOL(drm_core_ioremap);

void drm_core_ioremap_wc(struct drm_map *map, struct drm_device *dev)
{
map->handle = ioremap_wc(map->offset, map->size);
if (drm_core_has_AGP(dev) &&
dev->agp && dev->agp->cant_use_aperture && map->type == _DRM_AGP)
map->handle = agp_remap(map->offset, map->size, dev);
else
map->handle = ioremap_wc(map->offset, map->size);
}
EXPORT_SYMBOL(drm_core_ioremap_wc);

void drm_core_ioremapfree(struct drm_map *map, struct drm_device *dev)
{
if (!map->handle || !map->size)
Expand Down
47 changes: 40 additions & 7 deletions drivers/gpu/drm/i915/i915_dma.c
Original file line number Diff line number Diff line change
Expand Up @@ -731,8 +731,11 @@ static int i915_getparam(struct drm_device *dev, void *data,
case I915_PARAM_HAS_GEM:
value = dev_priv->has_gem;
break;
case I915_PARAM_NUM_FENCES_AVAIL:
value = dev_priv->num_fence_regs - dev_priv->fence_reg_start;
break;
default:
DRM_ERROR("Unknown parameter %d\n", param->param);
DRM_DEBUG("Unknown parameter %d\n", param->param);
return -EINVAL;
}

Expand Down Expand Up @@ -764,8 +767,15 @@ static int i915_setparam(struct drm_device *dev, void *data,
case I915_SETPARAM_ALLOW_BATCHBUFFER:
dev_priv->allow_batchbuffer = param->value;
break;
case I915_SETPARAM_NUM_USED_FENCES:
if (param->value > dev_priv->num_fence_regs ||
param->value < 0)
return -EINVAL;
/* Userspace can use first N regs */
dev_priv->fence_reg_start = param->value;
break;
default:
DRM_ERROR("unknown parameter %d\n", param->param);
DRM_DEBUG("unknown parameter %d\n", param->param);
return -EINVAL;
}

Expand Down Expand Up @@ -966,10 +976,6 @@ static int i915_load_modeset_init(struct drm_device *dev)
if (ret)
goto kfree_devname;

dev_priv->mm.gtt_mapping =
io_mapping_create_wc(dev->agp->base,
dev->agp->agp_info.aper_size * 1024*1024);

/* Allow hardware batchbuffers unless told otherwise.
*/
dev_priv->allow_batchbuffer = 1;
Expand Down Expand Up @@ -1081,6 +1087,23 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags)
goto free_priv;
}

dev_priv->mm.gtt_mapping =
io_mapping_create_wc(dev->agp->base,
dev->agp->agp_info.aper_size * 1024*1024);
/* Set up a WC MTRR for non-PAT systems. This is more common than
* one would think, because the kernel disables PAT on first
* generation Core chips because WC PAT gets overridden by a UC
* MTRR if present. Even if a UC MTRR isn't present.
*/
dev_priv->mm.gtt_mtrr = mtrr_add(dev->agp->base,
dev->agp->agp_info.aper_size *
1024 * 1024,
MTRR_TYPE_WRCOMB, 1);
if (dev_priv->mm.gtt_mtrr < 0) {
DRM_INFO("MTRR allocation failed\n. Graphics "
"performance may suffer.\n");
}

#ifdef CONFIG_HIGHMEM64G
/* don't enable GEM on PAE - needs agp + set_memory_* interface fixes */
dev_priv->has_gem = 0;
Expand All @@ -1089,6 +1112,10 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags)
dev_priv->has_gem = 1;
#endif

dev->driver->get_vblank_counter = i915_get_vblank_counter;
if (IS_GM45(dev))
dev->driver->get_vblank_counter = gm45_get_vblank_counter;

i915_gem_load(dev);

/* Init HWS */
Expand Down Expand Up @@ -1145,8 +1172,14 @@ int i915_driver_unload(struct drm_device *dev)
{
struct drm_i915_private *dev_priv = dev->dev_private;

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,
dev->agp->agp_info.aper_size * 1024 * 1024);
dev_priv->mm.gtt_mtrr = -1;
}

if (drm_core_check_feature(dev, DRIVER_MODESET)) {
io_mapping_free(dev_priv->mm.gtt_mapping);
drm_irq_uninstall(dev);
}

Expand Down
1 change: 0 additions & 1 deletion drivers/gpu/drm/i915/i915_drv.c
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,6 @@ static struct drm_driver driver = {
.suspend = i915_suspend,
.resume = i915_resume,
.device_is_agp = i915_driver_device_is_agp,
.get_vblank_counter = i915_get_vblank_counter,
.enable_vblank = i915_enable_vblank,
.disable_vblank = i915_disable_vblank,
.irq_preinstall = i915_driver_irq_preinstall,
Expand Down
8 changes: 8 additions & 0 deletions drivers/gpu/drm/i915/i915_drv.h
Original file line number Diff line number Diff line change
Expand Up @@ -284,6 +284,7 @@ typedef struct drm_i915_private {
struct drm_mm gtt_space;

struct io_mapping *gtt_mapping;
int gtt_mtrr;

/**
* List of objects currently involved in rendering from the
Expand Down Expand Up @@ -534,6 +535,7 @@ extern int i915_vblank_pipe_get(struct drm_device *dev, void *data,
extern int i915_enable_vblank(struct drm_device *dev, int crtc);
extern void i915_disable_vblank(struct drm_device *dev, int crtc);
extern u32 i915_get_vblank_counter(struct drm_device *dev, int crtc);
extern u32 gm45_get_vblank_counter(struct drm_device *dev, int crtc);
extern int i915_vblank_swap(struct drm_device *dev, void *data,
struct drm_file *file_priv);
extern void i915_enable_irq(drm_i915_private_t *dev_priv, u32 mask);
Expand Down Expand Up @@ -601,6 +603,7 @@ int i915_gem_init_object(struct drm_gem_object *obj);
void i915_gem_free_object(struct drm_gem_object *obj);
int i915_gem_object_pin(struct drm_gem_object *obj, uint32_t alignment);
void i915_gem_object_unpin(struct drm_gem_object *obj);
int i915_gem_object_unbind(struct drm_gem_object *obj);
void i915_gem_lastclose(struct drm_device *dev);
uint32_t i915_get_gem_seqno(struct drm_device *dev);
void i915_gem_retire_requests(struct drm_device *dev);
Expand Down Expand Up @@ -784,6 +787,11 @@ extern int i915_wait_ring(struct drm_device * dev, int n, const char *caller);
IS_I945GM(dev) || IS_I965GM(dev) || IS_GM45(dev))

#define I915_NEED_GFX_HWS(dev) (IS_G33(dev) || IS_GM45(dev) || IS_G4X(dev))
/* With the 945 and later, Y tiling got adjusted so that it was 32 128-byte
* rows, which changed the alignment requirements and fence programming.
*/
#define HAS_128_BYTE_Y_TILING(dev) (IS_I9XX(dev) && !(IS_I915G(dev) || \
IS_I915GM(dev)))
#define SUPPORTS_INTEGRATED_HDMI(dev) (IS_G4X(dev))

#define PRIMARY_RINGBUFFER_SIZE (128*1024)
Expand Down
83 changes: 55 additions & 28 deletions drivers/gpu/drm/i915/i915_gem.c
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ static void i915_gem_object_free_page_list(struct drm_gem_object *obj);
static int i915_gem_object_wait_rendering(struct drm_gem_object *obj);
static int i915_gem_object_bind_to_gtt(struct drm_gem_object *obj,
unsigned alignment);
static void i915_gem_object_get_fence_reg(struct drm_gem_object *obj);
static int i915_gem_object_get_fence_reg(struct drm_gem_object *obj, bool write);
static void i915_gem_clear_fence_reg(struct drm_gem_object *obj);
static int i915_gem_evict_something(struct drm_device *dev);
static int i915_gem_phys_pwrite(struct drm_device *dev, struct drm_gem_object *obj,
Expand Down Expand Up @@ -567,6 +567,7 @@ int i915_gem_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
pgoff_t page_offset;
unsigned long pfn;
int ret = 0;
bool write = !!(vmf->flags & FAULT_FLAG_WRITE);

/* We don't use vmf->pgoff since that has the fake offset */
page_offset = ((unsigned long)vmf->virtual_address - vma->vm_start) >>
Expand All @@ -585,8 +586,13 @@ int i915_gem_fault(struct vm_area_struct *vma, struct vm_fault *vmf)

/* Need a new fence register? */
if (obj_priv->fence_reg == I915_FENCE_REG_NONE &&
obj_priv->tiling_mode != I915_TILING_NONE)
i915_gem_object_get_fence_reg(obj);
obj_priv->tiling_mode != I915_TILING_NONE) {
ret = i915_gem_object_get_fence_reg(obj, write);
if (ret) {
mutex_unlock(&dev->struct_mutex);
return VM_FAULT_SIGBUS;
}
}

pfn = ((dev->agp->base + obj_priv->gtt_offset) >> PAGE_SHIFT) +
page_offset;
Expand Down Expand Up @@ -1211,7 +1217,7 @@ i915_gem_object_wait_rendering(struct drm_gem_object *obj)
/**
* Unbinds an object from the GTT aperture.
*/
static int
int
i915_gem_object_unbind(struct drm_gem_object *obj)
{
struct drm_device *dev = obj->dev;
Expand Down Expand Up @@ -1445,21 +1451,26 @@ static void i915_write_fence_reg(struct drm_i915_fence_reg *reg)
drm_i915_private_t *dev_priv = dev->dev_private;
struct drm_i915_gem_object *obj_priv = obj->driver_private;
int regnum = obj_priv->fence_reg;
int tile_width;
uint32_t val;
uint32_t pitch_val;

if ((obj_priv->gtt_offset & ~I915_FENCE_START_MASK) ||
(obj_priv->gtt_offset & (obj->size - 1))) {
WARN(1, "%s: object not 1M or size aligned\n", __func__);
WARN(1, "%s: object 0x%08x not 1M or size (0x%x) aligned\n",
__func__, obj_priv->gtt_offset, obj->size);
return;
}

if (obj_priv->tiling_mode == I915_TILING_Y && (IS_I945G(dev) ||
IS_I945GM(dev) ||
IS_G33(dev)))
pitch_val = (obj_priv->stride / 128) - 1;
if (obj_priv->tiling_mode == I915_TILING_Y &&
HAS_128_BYTE_Y_TILING(dev))
tile_width = 128;
else
pitch_val = (obj_priv->stride / 512) - 1;
tile_width = 512;

/* Note: pitch better be a power of two tile widths */
pitch_val = obj_priv->stride / tile_width;
pitch_val = ffs(pitch_val) - 1;

val = obj_priv->gtt_offset;
if (obj_priv->tiling_mode == I915_TILING_Y)
Expand All @@ -1483,7 +1494,8 @@ static void i830_write_fence_reg(struct drm_i915_fence_reg *reg)

if ((obj_priv->gtt_offset & ~I915_FENCE_START_MASK) ||
(obj_priv->gtt_offset & (obj->size - 1))) {
WARN(1, "%s: object not 1M or size aligned\n", __func__);
WARN(1, "%s: object 0x%08x not 1M or size aligned\n",
__func__, obj_priv->gtt_offset);
return;
}

Expand All @@ -1503,6 +1515,7 @@ static void i830_write_fence_reg(struct drm_i915_fence_reg *reg)
/**
* i915_gem_object_get_fence_reg - set up a fence reg for an object
* @obj: object to map through a fence reg
* @write: object is about to be written
*
* When mapping objects through the GTT, userspace wants to be able to write
* to them without having to worry about swizzling if the object is tiled.
Expand All @@ -1513,8 +1526,8 @@ static void i830_write_fence_reg(struct drm_i915_fence_reg *reg)
* It then sets up the reg based on the object's properties: address, pitch
* and tiling format.
*/
static void
i915_gem_object_get_fence_reg(struct drm_gem_object *obj)
static int
i915_gem_object_get_fence_reg(struct drm_gem_object *obj, bool write)
{
struct drm_device *dev = obj->dev;
struct drm_i915_private *dev_priv = dev->dev_private;
Expand All @@ -1527,12 +1540,18 @@ i915_gem_object_get_fence_reg(struct drm_gem_object *obj)
WARN(1, "allocating a fence for non-tiled object?\n");
break;
case I915_TILING_X:
WARN(obj_priv->stride & (512 - 1),
"object is X tiled but has non-512B pitch\n");
if (!obj_priv->stride)
return -EINVAL;
WARN((obj_priv->stride & (512 - 1)),
"object 0x%08x is X tiled but has non-512B pitch\n",
obj_priv->gtt_offset);
break;
case I915_TILING_Y:
WARN(obj_priv->stride & (128 - 1),
"object is Y tiled but has non-128B pitch\n");
if (!obj_priv->stride)
return -EINVAL;
WARN((obj_priv->stride & (128 - 1)),
"object 0x%08x is Y tiled but has non-128B pitch\n",
obj_priv->gtt_offset);
break;
}

Expand Down Expand Up @@ -1563,10 +1582,11 @@ i915_gem_object_get_fence_reg(struct drm_gem_object *obj)
* objects to finish before trying again.
*/
if (i == dev_priv->num_fence_regs) {
ret = i915_gem_object_wait_rendering(reg->obj);
ret = i915_gem_object_set_to_gtt_domain(reg->obj, 0);
if (ret) {
WARN(ret, "wait_rendering failed: %d\n", ret);
return;
WARN(ret != -ERESTARTSYS,
"switch to GTT domain failed: %d\n", ret);
return ret;
}
goto try_again;
}
Expand All @@ -1591,6 +1611,8 @@ i915_gem_object_get_fence_reg(struct drm_gem_object *obj)
i915_write_fence_reg(reg);
else
i830_write_fence_reg(reg);

return 0;
}

/**
Expand Down Expand Up @@ -1631,7 +1653,7 @@ i915_gem_object_bind_to_gtt(struct drm_gem_object *obj, unsigned alignment)
if (dev_priv->mm.suspended)
return -EBUSY;
if (alignment == 0)
alignment = PAGE_SIZE;
alignment = i915_gem_get_gtt_alignment(obj);
if (alignment & (PAGE_SIZE - 1)) {
DRM_ERROR("Invalid object alignment requested %u\n", alignment);
return -EINVAL;
Expand Down Expand Up @@ -2652,6 +2674,14 @@ i915_gem_object_pin(struct drm_gem_object *obj, uint32_t alignment)
DRM_ERROR("Failure to bind: %d", ret);
return ret;
}
/*
* Pre-965 chips need a fence register set up in order to
* properly handle tiled surfaces.
*/
if (!IS_I965G(dev) &&
obj_priv->fence_reg == I915_FENCE_REG_NONE &&
obj_priv->tiling_mode != I915_TILING_NONE)
i915_gem_object_get_fence_reg(obj, true);
}
obj_priv->pin_count++;

Expand Down Expand Up @@ -3229,10 +3259,6 @@ i915_gem_entervt_ioctl(struct drm_device *dev, void *data,
dev_priv->mm.wedged = 0;
}

dev_priv->mm.gtt_mapping = io_mapping_create_wc(dev->agp->base,
dev->agp->agp_info.aper_size
* 1024 * 1024);

mutex_lock(&dev->struct_mutex);
dev_priv->mm.suspended = 0;

Expand All @@ -3255,7 +3281,6 @@ int
i915_gem_leavevt_ioctl(struct drm_device *dev, void *data,
struct drm_file *file_priv)
{
drm_i915_private_t *dev_priv = dev->dev_private;
int ret;

if (drm_core_check_feature(dev, DRIVER_MODESET))
Expand All @@ -3264,7 +3289,6 @@ i915_gem_leavevt_ioctl(struct drm_device *dev, void *data,
ret = i915_gem_idle(dev);
drm_irq_uninstall(dev);

io_mapping_free(dev_priv->mm.gtt_mapping);
return ret;
}

Expand All @@ -3273,6 +3297,9 @@ i915_gem_lastclose(struct drm_device *dev)
{
int ret;

if (drm_core_check_feature(dev, DRIVER_MODESET))
return;

ret = i915_gem_idle(dev);
if (ret)
DRM_ERROR("failed to idle hardware: %d\n", ret);
Expand All @@ -3294,7 +3321,7 @@ i915_gem_load(struct drm_device *dev)
/* Old X drivers will take 0-2 for front, back, depth buffers */
dev_priv->fence_reg_start = 3;

if (IS_I965G(dev))
if (IS_I965G(dev) || IS_I945G(dev) || IS_I945GM(dev) || IS_G33(dev))
dev_priv->num_fence_regs = 16;
else
dev_priv->num_fence_regs = 8;
Expand Down
Loading

0 comments on commit ff74733

Please sign in to comment.