Skip to content

Commit

Permalink
vmwgfx: vt-switch (master drop) fixes
Browse files Browse the repository at this point in the history
We add an option not to enable fbdev, this option is off (0) by default.
Not enabling fbdev at load time makes it possible to co-operate with
vga16fb and vga text mode when VT switching.

However, if 3D resources are active when VT switching, we're currently
not able to switch over to vga, due to device limitations.
This fixes a bug where we previously lost 3D state during VT switch.

Signed-off-by: Thomas Hellstrom <thellstrom@vmware.com>
Signed-off-by: Dave Airlie <airlied@redhat.com>
  • Loading branch information
thomashvmw authored and airlied committed Oct 1, 2010
1 parent 2854eed commit 30c78bb
Show file tree
Hide file tree
Showing 5 changed files with 115 additions and 13 deletions.
102 changes: 89 additions & 13 deletions drivers/gpu/drm/vmwgfx/vmwgfx_drv.c
Original file line number Diff line number Diff line change
Expand Up @@ -149,12 +149,16 @@ static struct pci_device_id vmw_pci_id_list[] = {
};

static char *vmw_devname = "vmwgfx";
static int enable_fbdev;

static int vmw_probe(struct pci_dev *, const struct pci_device_id *);
static void vmw_master_init(struct vmw_master *);
static int vmwgfx_pm_notifier(struct notifier_block *nb, unsigned long val,
void *ptr);

MODULE_PARM_DESC(enable_fbdev, "Enable vmwgfx fbdev");
module_param_named(enable_fbdev, enable_fbdev, int, 0600);

static void vmw_print_capabilities(uint32_t capabilities)
{
DRM_INFO("Capabilities:\n");
Expand Down Expand Up @@ -192,8 +196,6 @@ static int vmw_request_device(struct vmw_private *dev_priv)
{
int ret;

vmw_kms_save_vga(dev_priv);

ret = vmw_fifo_init(dev_priv, &dev_priv->fifo);
if (unlikely(ret != 0)) {
DRM_ERROR("Unable to initialize FIFO.\n");
Expand All @@ -206,10 +208,36 @@ static int vmw_request_device(struct vmw_private *dev_priv)
static void vmw_release_device(struct vmw_private *dev_priv)
{
vmw_fifo_release(dev_priv, &dev_priv->fifo);
vmw_kms_restore_vga(dev_priv);
}

int vmw_3d_resource_inc(struct vmw_private *dev_priv)
{
int ret = 0;

mutex_lock(&dev_priv->release_mutex);
if (unlikely(dev_priv->num_3d_resources++ == 0)) {
ret = vmw_request_device(dev_priv);
if (unlikely(ret != 0))
--dev_priv->num_3d_resources;
}
mutex_unlock(&dev_priv->release_mutex);
return ret;
}


void vmw_3d_resource_dec(struct vmw_private *dev_priv)
{
int32_t n3d;

mutex_lock(&dev_priv->release_mutex);
if (unlikely(--dev_priv->num_3d_resources == 0))
vmw_release_device(dev_priv);
n3d = (int32_t) dev_priv->num_3d_resources;
mutex_unlock(&dev_priv->release_mutex);

BUG_ON(n3d < 0);
}

static int vmw_driver_load(struct drm_device *dev, unsigned long chipset)
{
struct vmw_private *dev_priv;
Expand All @@ -228,6 +256,7 @@ static int vmw_driver_load(struct drm_device *dev, unsigned long chipset)
dev_priv->last_read_sequence = (uint32_t) -100;
mutex_init(&dev_priv->hw_mutex);
mutex_init(&dev_priv->cmdbuf_mutex);
mutex_init(&dev_priv->release_mutex);
rwlock_init(&dev_priv->resource_lock);
idr_init(&dev_priv->context_idr);
idr_init(&dev_priv->surface_idr);
Expand All @@ -244,6 +273,8 @@ static int vmw_driver_load(struct drm_device *dev, unsigned long chipset)
dev_priv->vram_start = pci_resource_start(dev->pdev, 1);
dev_priv->mmio_start = pci_resource_start(dev->pdev, 2);

dev_priv->enable_fb = enable_fbdev;

mutex_lock(&dev_priv->hw_mutex);

vmw_write(dev_priv, SVGA_REG_ID, SVGA_ID_2);
Expand Down Expand Up @@ -369,20 +400,34 @@ static int vmw_driver_load(struct drm_device *dev, unsigned long chipset)
goto out_no_device;
}
}
ret = vmw_request_device(dev_priv);
if (unlikely(ret != 0))
goto out_no_device;
vmw_kms_init(dev_priv);
vmw_overlay_init(dev_priv);
vmw_fb_init(dev_priv);
if (dev_priv->enable_fb) {
ret = vmw_3d_resource_inc(dev_priv);
if (unlikely(ret != 0))
goto out_no_fifo;
vmw_kms_save_vga(dev_priv);
vmw_fb_init(dev_priv);
DRM_INFO("%s", vmw_fifo_have_3d(dev_priv) ?
"Detected device 3D availability.\n" :
"Detected no device 3D availability.\n");
} else {
DRM_INFO("Delayed 3D detection since we're not "
"running the device in SVGA mode yet.\n");
}

dev_priv->pm_nb.notifier_call = vmwgfx_pm_notifier;
register_pm_notifier(&dev_priv->pm_nb);

DRM_INFO("%s", vmw_fifo_have_3d(dev_priv) ? "Have 3D\n" : "No 3D\n");

return 0;

out_no_fifo:
vmw_overlay_close(dev_priv);
vmw_kms_close(dev_priv);
if (dev_priv->stealth)
pci_release_region(dev->pdev, 2);
else
pci_release_regions(dev->pdev);
out_no_device:
if (dev_priv->capabilities & SVGA_CAP_IRQMASK)
drm_irq_uninstall(dev_priv->dev);
Expand Down Expand Up @@ -415,10 +460,13 @@ static int vmw_driver_unload(struct drm_device *dev)

unregister_pm_notifier(&dev_priv->pm_nb);

vmw_fb_close(dev_priv);
if (dev_priv->enable_fb) {
vmw_fb_close(dev_priv);
vmw_kms_restore_vga(dev_priv);
vmw_3d_resource_dec(dev_priv);
}
vmw_kms_close(dev_priv);
vmw_overlay_close(dev_priv);
vmw_release_device(dev_priv);
if (dev_priv->stealth)
pci_release_region(dev->pdev, 2);
else
Expand Down Expand Up @@ -589,6 +637,16 @@ static int vmw_master_set(struct drm_device *dev,
struct vmw_master *vmaster = vmw_master(file_priv->master);
int ret = 0;

if (!dev_priv->enable_fb) {
ret = vmw_3d_resource_inc(dev_priv);
if (unlikely(ret != 0))
return ret;
vmw_kms_save_vga(dev_priv);
mutex_lock(&dev_priv->hw_mutex);
vmw_write(dev_priv, SVGA_REG_TRACES, 0);
mutex_unlock(&dev_priv->hw_mutex);
}

if (active) {
BUG_ON(active != &dev_priv->fbdev_master);
ret = ttm_vt_lock(&active->lock, false, vmw_fp->tfile);
Expand Down Expand Up @@ -617,7 +675,13 @@ static int vmw_master_set(struct drm_device *dev,
return 0;

out_no_active_lock:
vmw_release_device(dev_priv);
if (!dev_priv->enable_fb) {
mutex_lock(&dev_priv->hw_mutex);
vmw_write(dev_priv, SVGA_REG_TRACES, 1);
mutex_unlock(&dev_priv->hw_mutex);
vmw_kms_restore_vga(dev_priv);
vmw_3d_resource_dec(dev_priv);
}
return ret;
}

Expand Down Expand Up @@ -645,11 +709,23 @@ static void vmw_master_drop(struct drm_device *dev,

ttm_lock_set_kill(&vmaster->lock, true, SIGTERM);

if (!dev_priv->enable_fb) {
ret = ttm_bo_evict_mm(&dev_priv->bdev, TTM_PL_VRAM);
if (unlikely(ret != 0))
DRM_ERROR("Unable to clean VRAM on master drop.\n");
mutex_lock(&dev_priv->hw_mutex);
vmw_write(dev_priv, SVGA_REG_TRACES, 1);
mutex_unlock(&dev_priv->hw_mutex);
vmw_kms_restore_vga(dev_priv);
vmw_3d_resource_dec(dev_priv);
}

dev_priv->active_master = &dev_priv->fbdev_master;
ttm_lock_set_kill(&dev_priv->fbdev_master.lock, false, SIGTERM);
ttm_vt_unlock(&dev_priv->fbdev_master.lock);

vmw_fb_on(dev_priv);
if (dev_priv->enable_fb)
vmw_fb_on(dev_priv);
}


Expand Down
7 changes: 7 additions & 0 deletions drivers/gpu/drm/vmwgfx/vmwgfx_drv.h
Original file line number Diff line number Diff line change
Expand Up @@ -277,6 +277,7 @@ struct vmw_private {

bool stealth;
bool is_opened;
bool enable_fb;

/**
* Master management.
Expand All @@ -285,6 +286,9 @@ struct vmw_private {
struct vmw_master *active_master;
struct vmw_master fbdev_master;
struct notifier_block pm_nb;

struct mutex release_mutex;
uint32_t num_3d_resources;
};

static inline struct vmw_private *vmw_priv(struct drm_device *dev)
Expand Down Expand Up @@ -319,6 +323,9 @@ static inline uint32_t vmw_read(struct vmw_private *dev_priv,
return val;
}

int vmw_3d_resource_inc(struct vmw_private *dev_priv);
void vmw_3d_resource_dec(struct vmw_private *dev_priv);

/**
* GMR utilities - vmwgfx_gmr.c
*/
Expand Down
3 changes: 3 additions & 0 deletions drivers/gpu/drm/vmwgfx/vmwgfx_fifo.c
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,7 @@ int vmw_fifo_init(struct vmw_private *dev_priv, struct vmw_fifo_state *fifo)
mutex_lock(&dev_priv->hw_mutex);
dev_priv->enable_state = vmw_read(dev_priv, SVGA_REG_ENABLE);
dev_priv->config_done_state = vmw_read(dev_priv, SVGA_REG_CONFIG_DONE);
dev_priv->traces_state = vmw_read(dev_priv, SVGA_REG_TRACES);
vmw_write(dev_priv, SVGA_REG_ENABLE, 1);

min = 4;
Expand Down Expand Up @@ -175,6 +176,8 @@ void vmw_fifo_release(struct vmw_private *dev_priv, struct vmw_fifo_state *fifo)
dev_priv->config_done_state);
vmw_write(dev_priv, SVGA_REG_ENABLE,
dev_priv->enable_state);
vmw_write(dev_priv, SVGA_REG_TRACES,
dev_priv->traces_state);

mutex_unlock(&dev_priv->hw_mutex);
vmw_fence_queue_takedown(&fifo->fence_queue);
Expand Down
12 changes: 12 additions & 0 deletions drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
Original file line number Diff line number Diff line change
Expand Up @@ -898,7 +898,19 @@ int vmw_kms_save_vga(struct vmw_private *vmw_priv)
save->width = vmw_read(vmw_priv, SVGA_REG_DISPLAY_WIDTH);
save->height = vmw_read(vmw_priv, SVGA_REG_DISPLAY_HEIGHT);
vmw_write(vmw_priv, SVGA_REG_DISPLAY_ID, SVGA_ID_INVALID);
if (i == 0 && vmw_priv->num_displays == 1 &&
save->width == 0 && save->height == 0) {

/*
* It should be fairly safe to assume that these
* values are uninitialized.
*/

save->width = vmw_priv->vga_width - save->pos_x;
save->height = vmw_priv->vga_height - save->pos_y;
}
}

return 0;
}

Expand Down
4 changes: 4 additions & 0 deletions drivers/gpu/drm/vmwgfx/vmwgfx_resource.c
Original file line number Diff line number Diff line change
Expand Up @@ -211,6 +211,7 @@ static void vmw_hw_context_destroy(struct vmw_resource *res)
cmd->body.cid = cpu_to_le32(res->id);

vmw_fifo_commit(dev_priv, sizeof(*cmd));
vmw_3d_resource_dec(dev_priv);
}

static int vmw_context_init(struct vmw_private *dev_priv,
Expand Down Expand Up @@ -247,6 +248,7 @@ static int vmw_context_init(struct vmw_private *dev_priv,
cmd->body.cid = cpu_to_le32(res->id);

vmw_fifo_commit(dev_priv, sizeof(*cmd));
(void) vmw_3d_resource_inc(dev_priv);
vmw_resource_activate(res, vmw_hw_context_destroy);
return 0;
}
Expand Down Expand Up @@ -406,6 +408,7 @@ static void vmw_hw_surface_destroy(struct vmw_resource *res)
cmd->body.sid = cpu_to_le32(res->id);

vmw_fifo_commit(dev_priv, sizeof(*cmd));
vmw_3d_resource_dec(dev_priv);
}

void vmw_surface_res_free(struct vmw_resource *res)
Expand Down Expand Up @@ -473,6 +476,7 @@ int vmw_surface_init(struct vmw_private *dev_priv,
}

vmw_fifo_commit(dev_priv, submit_size);
(void) vmw_3d_resource_inc(dev_priv);
vmw_resource_activate(res, vmw_hw_surface_destroy);
return 0;
}
Expand Down

0 comments on commit 30c78bb

Please sign in to comment.