Commit 1ce4200d authored by Dave Airlie's avatar Dave Airlie
Browse files

Merge tag 'topic/drm-misc-2015-08-13' of git://anongit.freedesktop.org/drm-intel into drm-next

Final drm-misc pull for 4.3:
- fbdev emulation Kconfig option for everyone thanks to Archit. It's not
  everything yet bit this is fairly tricky since it spawns all drivers.
- vgaarb & vgaswitcheroo polish from Thierry
- some drm_irq.c cleanups (Thierry)
- struct_mutex crusade from me
- more fbdev panic handling removal
- various things all over in drm core&helpers

* tag 'topic/drm-misc-2015-08-13' of git://anongit.freedesktop.org/drm-intel: (65 commits)
  drm/atomic: Use KMS VBLANK API
  drm/irq: Document return values more consistently
  drm/irq: Make pipe unsigned and name consistent
  drm/irq: Check for valid VBLANK before dereference
  drm/irq: Remove negative CRTC index special-case
  drm/plane: Remove redundant extern
  drm/plane: Use consistent data types for format count
  vga_switcheroo: Remove unnecessary checks
  vga_switcheroo: Wrap overly long lines
  vga_switcheroo: Use pr_fmt()
  vga_switcheroo: Cleanup header comment
  vga_switcheroo: Use pr_*() instead of printk()
  vgaarb: Fix a few checkpatch errors and warnings
  vgaarb: Use vgaarb: prefix consistently in messages
  vgaarb: Stop complaining about absent devices
  drm/atomic: fix null pointer access to mode_fixup callback
  drm/i915: Use CONFIG_DRM_FBDEV_EMULATION
  drm/core: Set mode to NULL when connectors in a set drops to 0.
  drm/atomic: Call ww_acquire_done after check phase is complete
  drm/atomic: Paper over locking WARN in default_state_clear
  ...
parents e5dafc0d d4853630
...@@ -37,9 +37,29 @@ config DRM_KMS_FB_HELPER ...@@ -37,9 +37,29 @@ config DRM_KMS_FB_HELPER
select FB select FB
select FRAMEBUFFER_CONSOLE if !EXPERT select FRAMEBUFFER_CONSOLE if !EXPERT
select FRAMEBUFFER_CONSOLE_DETECT_PRIMARY if FRAMEBUFFER_CONSOLE select FRAMEBUFFER_CONSOLE_DETECT_PRIMARY if FRAMEBUFFER_CONSOLE
select FB_SYS_FOPS
select FB_SYS_FILLRECT
select FB_SYS_COPYAREA
select FB_SYS_IMAGEBLIT
select FB_CFB_FILLRECT
select FB_CFB_COPYAREA
select FB_CFB_IMAGEBLIT
help help
FBDEV helpers for KMS drivers. FBDEV helpers for KMS drivers.
config DRM_FBDEV_EMULATION
bool "Enable legacy fbdev support for your modesetting driver"
depends on DRM
select DRM_KMS_HELPER
select DRM_KMS_FB_HELPER
default y
help
Choose this option if you have a need for the legacy fbdev
support. Note that this support also provides the linux console
support on top of your modesetting driver.
If in doubt, say "Y".
config DRM_LOAD_EDID_FIRMWARE config DRM_LOAD_EDID_FIRMWARE
bool "Allow to specify an EDID data set instead of probing for it" bool "Allow to specify an EDID data set instead of probing for it"
depends on DRM_KMS_HELPER depends on DRM_KMS_HELPER
......
...@@ -23,7 +23,7 @@ drm-$(CONFIG_OF) += drm_of.o ...@@ -23,7 +23,7 @@ drm-$(CONFIG_OF) += drm_of.o
drm_kms_helper-y := drm_crtc_helper.o drm_dp_helper.o drm_probe_helper.o \ drm_kms_helper-y := drm_crtc_helper.o drm_dp_helper.o drm_probe_helper.o \
drm_plane_helper.o drm_dp_mst_topology.o drm_atomic_helper.o drm_plane_helper.o drm_dp_mst_topology.o drm_atomic_helper.o
drm_kms_helper-$(CONFIG_DRM_LOAD_EDID_FIRMWARE) += drm_edid_load.o drm_kms_helper-$(CONFIG_DRM_LOAD_EDID_FIRMWARE) += drm_edid_load.o
drm_kms_helper-$(CONFIG_DRM_KMS_FB_HELPER) += drm_fb_helper.o drm_kms_helper-$(CONFIG_DRM_FBDEV_EMULATION) += drm_fb_helper.o
drm_kms_helper-$(CONFIG_DRM_KMS_CMA_HELPER) += drm_fb_cma_helper.o drm_kms_helper-$(CONFIG_DRM_KMS_CMA_HELPER) += drm_fb_cma_helper.o
obj-$(CONFIG_DRM_KMS_HELPER) += drm_kms_helper.o obj-$(CONFIG_DRM_KMS_HELPER) += drm_kms_helper.o
......
...@@ -53,9 +53,9 @@ static struct fb_ops amdgpufb_ops = { ...@@ -53,9 +53,9 @@ static struct fb_ops amdgpufb_ops = {
.owner = THIS_MODULE, .owner = THIS_MODULE,
.fb_check_var = drm_fb_helper_check_var, .fb_check_var = drm_fb_helper_check_var,
.fb_set_par = drm_fb_helper_set_par, .fb_set_par = drm_fb_helper_set_par,
.fb_fillrect = cfb_fillrect, .fb_fillrect = drm_fb_helper_cfb_fillrect,
.fb_copyarea = cfb_copyarea, .fb_copyarea = drm_fb_helper_cfb_copyarea,
.fb_imageblit = cfb_imageblit, .fb_imageblit = drm_fb_helper_cfb_imageblit,
.fb_pan_display = drm_fb_helper_pan_display, .fb_pan_display = drm_fb_helper_pan_display,
.fb_blank = drm_fb_helper_blank, .fb_blank = drm_fb_helper_blank,
.fb_setcmap = drm_fb_helper_setcmap, .fb_setcmap = drm_fb_helper_setcmap,
...@@ -179,7 +179,6 @@ static int amdgpufb_create(struct drm_fb_helper *helper, ...@@ -179,7 +179,6 @@ static int amdgpufb_create(struct drm_fb_helper *helper,
struct drm_mode_fb_cmd2 mode_cmd; struct drm_mode_fb_cmd2 mode_cmd;
struct drm_gem_object *gobj = NULL; struct drm_gem_object *gobj = NULL;
struct amdgpu_bo *rbo = NULL; struct amdgpu_bo *rbo = NULL;
struct device *device = &adev->pdev->dev;
int ret; int ret;
unsigned long tmp; unsigned long tmp;
...@@ -201,9 +200,9 @@ static int amdgpufb_create(struct drm_fb_helper *helper, ...@@ -201,9 +200,9 @@ static int amdgpufb_create(struct drm_fb_helper *helper,
rbo = gem_to_amdgpu_bo(gobj); rbo = gem_to_amdgpu_bo(gobj);
/* okay we have an object now allocate the framebuffer */ /* okay we have an object now allocate the framebuffer */
info = framebuffer_alloc(0, device); info = drm_fb_helper_alloc_fbi(helper);
if (info == NULL) { if (IS_ERR(info)) {
ret = -ENOMEM; ret = PTR_ERR(info);
goto out_unref; goto out_unref;
} }
...@@ -212,14 +211,13 @@ static int amdgpufb_create(struct drm_fb_helper *helper, ...@@ -212,14 +211,13 @@ static int amdgpufb_create(struct drm_fb_helper *helper,
ret = amdgpu_framebuffer_init(adev->ddev, &rfbdev->rfb, &mode_cmd, gobj); ret = amdgpu_framebuffer_init(adev->ddev, &rfbdev->rfb, &mode_cmd, gobj);
if (ret) { if (ret) {
DRM_ERROR("failed to initialize framebuffer %d\n", ret); DRM_ERROR("failed to initialize framebuffer %d\n", ret);
goto out_unref; goto out_destroy_fbi;
} }
fb = &rfbdev->rfb.base; fb = &rfbdev->rfb.base;
/* setup helper */ /* setup helper */
rfbdev->helper.fb = fb; rfbdev->helper.fb = fb;
rfbdev->helper.fbdev = info;
memset_io(rbo->kptr, 0x0, amdgpu_bo_size(rbo)); memset_io(rbo->kptr, 0x0, amdgpu_bo_size(rbo));
...@@ -239,11 +237,6 @@ static int amdgpufb_create(struct drm_fb_helper *helper, ...@@ -239,11 +237,6 @@ static int amdgpufb_create(struct drm_fb_helper *helper,
drm_fb_helper_fill_var(info, &rfbdev->helper, sizes->fb_width, sizes->fb_height); drm_fb_helper_fill_var(info, &rfbdev->helper, sizes->fb_width, sizes->fb_height);
/* setup aperture base/size for vesafb takeover */ /* setup aperture base/size for vesafb takeover */
info->apertures = alloc_apertures(1);
if (!info->apertures) {
ret = -ENOMEM;
goto out_unref;
}
info->apertures->ranges[0].base = adev->ddev->mode_config.fb_base; info->apertures->ranges[0].base = adev->ddev->mode_config.fb_base;
info->apertures->ranges[0].size = adev->mc.aper_size; info->apertures->ranges[0].size = adev->mc.aper_size;
...@@ -251,13 +244,7 @@ static int amdgpufb_create(struct drm_fb_helper *helper, ...@@ -251,13 +244,7 @@ static int amdgpufb_create(struct drm_fb_helper *helper,
if (info->screen_base == NULL) { if (info->screen_base == NULL) {
ret = -ENOSPC; ret = -ENOSPC;
goto out_unref; goto out_destroy_fbi;
}
ret = fb_alloc_cmap(&info->cmap, 256, 0);
if (ret) {
ret = -ENOMEM;
goto out_unref;
} }
DRM_INFO("fb mappable at 0x%lX\n", info->fix.smem_start); DRM_INFO("fb mappable at 0x%lX\n", info->fix.smem_start);
...@@ -269,6 +256,8 @@ static int amdgpufb_create(struct drm_fb_helper *helper, ...@@ -269,6 +256,8 @@ static int amdgpufb_create(struct drm_fb_helper *helper,
vga_switcheroo_client_fb_set(adev->ddev->pdev, info); vga_switcheroo_client_fb_set(adev->ddev->pdev, info);
return 0; return 0;
out_destroy_fbi:
drm_fb_helper_release_fbi(helper);
out_unref: out_unref:
if (rbo) { if (rbo) {
...@@ -290,17 +279,10 @@ void amdgpu_fb_output_poll_changed(struct amdgpu_device *adev) ...@@ -290,17 +279,10 @@ void amdgpu_fb_output_poll_changed(struct amdgpu_device *adev)
static int amdgpu_fbdev_destroy(struct drm_device *dev, struct amdgpu_fbdev *rfbdev) static int amdgpu_fbdev_destroy(struct drm_device *dev, struct amdgpu_fbdev *rfbdev)
{ {
struct fb_info *info;
struct amdgpu_framebuffer *rfb = &rfbdev->rfb; struct amdgpu_framebuffer *rfb = &rfbdev->rfb;
if (rfbdev->helper.fbdev) { drm_fb_helper_unregister_fbi(&rfbdev->helper);
info = rfbdev->helper.fbdev; drm_fb_helper_release_fbi(&rfbdev->helper);
unregister_framebuffer(info);
if (info->cmap.len)
fb_dealloc_cmap(&info->cmap);
framebuffer_release(info);
}
if (rfb->obj) { if (rfb->obj) {
amdgpufb_destroy_pinned_object(rfb->obj); amdgpufb_destroy_pinned_object(rfb->obj);
...@@ -395,7 +377,8 @@ void amdgpu_fbdev_fini(struct amdgpu_device *adev) ...@@ -395,7 +377,8 @@ void amdgpu_fbdev_fini(struct amdgpu_device *adev)
void amdgpu_fbdev_set_suspend(struct amdgpu_device *adev, int state) void amdgpu_fbdev_set_suspend(struct amdgpu_device *adev, int state)
{ {
if (adev->mode_info.rfbdev) if (adev->mode_info.rfbdev)
fb_set_suspend(adev->mode_info.rfbdev->helper.fbdev, state); drm_fb_helper_set_suspend(&adev->mode_info.rfbdev->helper,
state);
} }
int amdgpu_fbdev_total_size(struct amdgpu_device *adev) int amdgpu_fbdev_total_size(struct amdgpu_device *adev)
......
...@@ -22,9 +22,9 @@ static /*const*/ struct fb_ops armada_fb_ops = { ...@@ -22,9 +22,9 @@ static /*const*/ struct fb_ops armada_fb_ops = {
.owner = THIS_MODULE, .owner = THIS_MODULE,
.fb_check_var = drm_fb_helper_check_var, .fb_check_var = drm_fb_helper_check_var,
.fb_set_par = drm_fb_helper_set_par, .fb_set_par = drm_fb_helper_set_par,
.fb_fillrect = cfb_fillrect, .fb_fillrect = drm_fb_helper_cfb_fillrect,
.fb_copyarea = cfb_copyarea, .fb_copyarea = drm_fb_helper_cfb_copyarea,
.fb_imageblit = cfb_imageblit, .fb_imageblit = drm_fb_helper_cfb_imageblit,
.fb_pan_display = drm_fb_helper_pan_display, .fb_pan_display = drm_fb_helper_pan_display,
.fb_blank = drm_fb_helper_blank, .fb_blank = drm_fb_helper_blank,
.fb_setcmap = drm_fb_helper_setcmap, .fb_setcmap = drm_fb_helper_setcmap,
...@@ -80,18 +80,12 @@ static int armada_fb_create(struct drm_fb_helper *fbh, ...@@ -80,18 +80,12 @@ static int armada_fb_create(struct drm_fb_helper *fbh,
if (IS_ERR(dfb)) if (IS_ERR(dfb))
return PTR_ERR(dfb); return PTR_ERR(dfb);
info = framebuffer_alloc(0, dev->dev); info = drm_fb_helper_alloc_fbi(fbh);
if (!info) { if (IS_ERR(info)) {
ret = -ENOMEM; ret = PTR_ERR(info);
goto err_fballoc; goto err_fballoc;
} }
ret = fb_alloc_cmap(&info->cmap, 256, 0);
if (ret) {
ret = -ENOMEM;
goto err_fbcmap;
}
strlcpy(info->fix.id, "armada-drmfb", sizeof(info->fix.id)); strlcpy(info->fix.id, "armada-drmfb", sizeof(info->fix.id));
info->par = fbh; info->par = fbh;
info->flags = FBINFO_DEFAULT | FBINFO_CAN_FORCE_OUTPUT; info->flags = FBINFO_DEFAULT | FBINFO_CAN_FORCE_OUTPUT;
...@@ -101,7 +95,7 @@ static int armada_fb_create(struct drm_fb_helper *fbh, ...@@ -101,7 +95,7 @@ static int armada_fb_create(struct drm_fb_helper *fbh,
info->screen_size = obj->obj.size; info->screen_size = obj->obj.size;
info->screen_base = ptr; info->screen_base = ptr;
fbh->fb = &dfb->fb; fbh->fb = &dfb->fb;
fbh->fbdev = info;
drm_fb_helper_fill_fix(info, dfb->fb.pitches[0], dfb->fb.depth); drm_fb_helper_fill_fix(info, dfb->fb.pitches[0], dfb->fb.depth);
drm_fb_helper_fill_var(info, fbh, sizes->fb_width, sizes->fb_height); drm_fb_helper_fill_var(info, fbh, sizes->fb_width, sizes->fb_height);
...@@ -111,8 +105,6 @@ static int armada_fb_create(struct drm_fb_helper *fbh, ...@@ -111,8 +105,6 @@ static int armada_fb_create(struct drm_fb_helper *fbh,
return 0; return 0;
err_fbcmap:
framebuffer_release(info);
err_fballoc: err_fballoc:
dfb->fb.funcs->destroy(&dfb->fb); dfb->fb.funcs->destroy(&dfb->fb);
return ret; return ret;
...@@ -171,6 +163,7 @@ int armada_fbdev_init(struct drm_device *dev) ...@@ -171,6 +163,7 @@ int armada_fbdev_init(struct drm_device *dev)
return 0; return 0;
err_fb_setup: err_fb_setup:
drm_fb_helper_release_fbi(fbh);
drm_fb_helper_fini(fbh); drm_fb_helper_fini(fbh);
err_fb_helper: err_fb_helper:
priv->fbdev = NULL; priv->fbdev = NULL;
...@@ -191,14 +184,8 @@ void armada_fbdev_fini(struct drm_device *dev) ...@@ -191,14 +184,8 @@ void armada_fbdev_fini(struct drm_device *dev)
struct drm_fb_helper *fbh = priv->fbdev; struct drm_fb_helper *fbh = priv->fbdev;
if (fbh) { if (fbh) {
struct fb_info *info = fbh->fbdev; drm_fb_helper_unregister_fbi(fbh);
drm_fb_helper_release_fbi(fbh);
if (info) {
unregister_framebuffer(info);
if (info->cmap.len)
fb_dealloc_cmap(&info->cmap);
framebuffer_release(info);
}
drm_fb_helper_fini(fbh); drm_fb_helper_fini(fbh);
......
...@@ -125,7 +125,7 @@ static void ast_fillrect(struct fb_info *info, ...@@ -125,7 +125,7 @@ static void ast_fillrect(struct fb_info *info,
const struct fb_fillrect *rect) const struct fb_fillrect *rect)
{ {
struct ast_fbdev *afbdev = info->par; struct ast_fbdev *afbdev = info->par;
sys_fillrect(info, rect); drm_fb_helper_sys_fillrect(info, rect);
ast_dirty_update(afbdev, rect->dx, rect->dy, rect->width, ast_dirty_update(afbdev, rect->dx, rect->dy, rect->width,
rect->height); rect->height);
} }
...@@ -134,7 +134,7 @@ static void ast_copyarea(struct fb_info *info, ...@@ -134,7 +134,7 @@ static void ast_copyarea(struct fb_info *info,
const struct fb_copyarea *area) const struct fb_copyarea *area)
{ {
struct ast_fbdev *afbdev = info->par; struct ast_fbdev *afbdev = info->par;
sys_copyarea(info, area); drm_fb_helper_sys_copyarea(info, area);
ast_dirty_update(afbdev, area->dx, area->dy, area->width, ast_dirty_update(afbdev, area->dx, area->dy, area->width,
area->height); area->height);
} }
...@@ -143,7 +143,7 @@ static void ast_imageblit(struct fb_info *info, ...@@ -143,7 +143,7 @@ static void ast_imageblit(struct fb_info *info,
const struct fb_image *image) const struct fb_image *image)
{ {
struct ast_fbdev *afbdev = info->par; struct ast_fbdev *afbdev = info->par;
sys_imageblit(info, image); drm_fb_helper_sys_imageblit(info, image);
ast_dirty_update(afbdev, image->dx, image->dy, image->width, ast_dirty_update(afbdev, image->dx, image->dy, image->width,
image->height); image->height);
} }
...@@ -193,7 +193,6 @@ static int astfb_create(struct drm_fb_helper *helper, ...@@ -193,7 +193,6 @@ static int astfb_create(struct drm_fb_helper *helper,
struct drm_framebuffer *fb; struct drm_framebuffer *fb;
struct fb_info *info; struct fb_info *info;
int size, ret; int size, ret;
struct device *device = &dev->pdev->dev;
void *sysram; void *sysram;
struct drm_gem_object *gobj = NULL; struct drm_gem_object *gobj = NULL;
struct ast_bo *bo = NULL; struct ast_bo *bo = NULL;
...@@ -217,40 +216,28 @@ static int astfb_create(struct drm_fb_helper *helper, ...@@ -217,40 +216,28 @@ static int astfb_create(struct drm_fb_helper *helper,
if (!sysram) if (!sysram)
return -ENOMEM; return -ENOMEM;
info = framebuffer_alloc(0, device); info = drm_fb_helper_alloc_fbi(helper);
if (!info) { if (IS_ERR(info)) {
ret = -ENOMEM; ret = PTR_ERR(info);
goto out; goto err_free_vram;
} }
info->par = afbdev; info->par = afbdev;
ret = ast_framebuffer_init(dev, &afbdev->afb, &mode_cmd, gobj); ret = ast_framebuffer_init(dev, &afbdev->afb, &mode_cmd, gobj);
if (ret) if (ret)
goto out; goto err_release_fbi;
afbdev->sysram = sysram; afbdev->sysram = sysram;
afbdev->size = size; afbdev->size = size;
fb = &afbdev->afb.base; fb = &afbdev->afb.base;
afbdev->helper.fb = fb; afbdev->helper.fb = fb;
afbdev->helper.fbdev = info;
strcpy(info->fix.id, "astdrmfb"); strcpy(info->fix.id, "astdrmfb");
info->flags = FBINFO_DEFAULT | FBINFO_CAN_FORCE_OUTPUT; info->flags = FBINFO_DEFAULT | FBINFO_CAN_FORCE_OUTPUT;
info->fbops = &astfb_ops; info->fbops = &astfb_ops;
ret = fb_alloc_cmap(&info->cmap, 256, 0);
if (ret) {
ret = -ENOMEM;
goto out;
}
info->apertures = alloc_apertures(1);
if (!info->apertures) {
ret = -ENOMEM;
goto out;
}
info->apertures->ranges[0].base = pci_resource_start(dev->pdev, 0); info->apertures->ranges[0].base = pci_resource_start(dev->pdev, 0);
info->apertures->ranges[0].size = pci_resource_len(dev->pdev, 0); info->apertures->ranges[0].size = pci_resource_len(dev->pdev, 0);
...@@ -266,7 +253,11 @@ static int astfb_create(struct drm_fb_helper *helper, ...@@ -266,7 +253,11 @@ static int astfb_create(struct drm_fb_helper *helper,
fb->width, fb->height); fb->width, fb->height);
return 0; return 0;
out:
err_release_fbi:
drm_fb_helper_release_fbi(helper);
err_free_vram:
vfree(afbdev->sysram);
return ret; return ret;
} }
...@@ -297,15 +288,10 @@ static const struct drm_fb_helper_funcs ast_fb_helper_funcs = { ...@@ -297,15 +288,10 @@ static const struct drm_fb_helper_funcs ast_fb_helper_funcs = {
static void ast_fbdev_destroy(struct drm_device *dev, static void ast_fbdev_destroy(struct drm_device *dev,
struct ast_fbdev *afbdev) struct ast_fbdev *afbdev)
{ {
struct fb_info *info;
struct ast_framebuffer *afb = &afbdev->afb; struct ast_framebuffer *afb = &afbdev->afb;
if (afbdev->helper.fbdev) {
info = afbdev->helper.fbdev; drm_fb_helper_unregister_fbi(&afbdev->helper);
unregister_framebuffer(info); drm_fb_helper_release_fbi(&afbdev->helper);
if (info->cmap.len)
fb_dealloc_cmap(&info->cmap);
framebuffer_release(info);
}
if (afb->obj) { if (afb->obj) {
drm_gem_object_unreference_unlocked(afb->obj); drm_gem_object_unreference_unlocked(afb->obj);
...@@ -377,5 +363,5 @@ void ast_fbdev_set_suspend(struct drm_device *dev, int state) ...@@ -377,5 +363,5 @@ void ast_fbdev_set_suspend(struct drm_device *dev, int state)
if (!ast->fbdev) if (!ast->fbdev)
return; return;
fb_set_suspend(ast->fbdev->helper.fbdev, state); drm_fb_helper_set_suspend(&ast->fbdev->helper, state);
} }
...@@ -571,24 +571,18 @@ ast_dumb_mmap_offset(struct drm_file *file, ...@@ -571,24 +571,18 @@ ast_dumb_mmap_offset(struct drm_file *file,
uint64_t *offset) uint64_t *offset)
{ {
struct drm_gem_object *obj; struct drm_gem_object *obj;
int ret;
struct ast_bo *bo; struct ast_bo *bo;
mutex_lock(&dev->struct_mutex);
obj = drm_gem_object_lookup(dev, file, handle); obj = drm_gem_object_lookup(dev, file, handle);
if (obj == NULL) { if (obj == NULL)
ret = -ENOENT; return -ENOENT;
goto out_unlock;
}
bo = gem_to_ast_bo(obj); bo = gem_to_ast_bo(obj);
*offset = ast_bo_mmap_offset(bo); *offset = ast_bo_mmap_offset(bo);
drm_gem_object_unreference(obj); drm_gem_object_unreference_unlocked(obj);
ret = 0;
out_unlock: return 0;
mutex_unlock(&dev->struct_mutex);
return ret;
} }
...@@ -109,7 +109,7 @@ static int bochs_pm_suspend(struct device *dev) ...@@ -109,7 +109,7 @@ static int bochs_pm_suspend(struct device *dev)
if (bochs->fb.initialized) { if (bochs->fb.initialized) {
console_lock(); console_lock();
fb_set_suspend(bochs->fb.helper.fbdev, 1); drm_fb_helper_set_suspend(&bochs->fb.helper, 1);
console_unlock(); console_unlock();
} }
...@@ -126,7 +126,7 @@ static int bochs_pm_resume(struct device *dev) ...@@ -126,7 +126,7 @@ static int bochs_pm_resume(struct device *dev)
if (bochs->fb.initialized) { if (bochs->fb.initialized) {
console_lock(); console_lock();
fb_set_suspend(bochs->fb.helper.fbdev, 0); drm_fb_helper_set_suspend(&bochs->fb.helper, 0);
console_unlock(); console_unlock();
} }
......
...@@ -24,9 +24,9 @@ static struct fb_ops bochsfb_ops = { ...@@ -24,9 +24,9 @@ static struct fb_ops bochsfb_ops = {
.owner = THIS_MODULE, .owner = THIS_MODULE,
.fb_check_var = drm_fb_helper_check_var, .fb_check_var = drm_fb_helper_check_var,
.fb_set_par = drm_fb_helper_set_par, .fb_set_par = drm_fb_helper_set_par,
.fb_fillrect = sys_fillrect, .fb_fillrect = drm_fb_helper_sys_fillrect,
.fb_copyarea = sys_copyarea, .fb_copyarea = drm_fb_helper_sys_copyarea,
.fb_imageblit = sys_imageblit, .fb_imageblit = drm_fb_helper_sys_imageblit,
.fb_pan_display = drm_fb_helper_pan_display, .fb_pan_display = drm_fb_helper_pan_display,
.fb_blank = drm_fb_helper_blank, .fb_blank = drm_fb_helper_blank,
.fb_setcmap = drm_fb_helper_setcmap, .fb_setcmap = drm_fb_helper_setcmap,
...@@ -56,11 +56,9 @@ static int bochsfb_create(struct drm_fb_helper *helper, ...@@ -56,11 +56,9 @@ static int bochsfb_create(struct drm_fb_helper *helper,
{ {
struct bochs_device *bochs = struct bochs_device *bochs =
container_of(helper, struct bochs_device, fb.helper); container_of(helper, struct bochs_device, fb.helper);
struct drm_device *dev = bochs->dev;
struct fb_info *info; struct fb_info *info;
struct drm_framebuffer *fb; struct drm_framebuffer *fb;
struct drm_mode_fb_cmd2 mode_cmd; struct drm_mode_fb_cmd2 mode_cmd;
struct device *device = &dev->pdev->dev;
struct drm_gem_object *gobj = NULL; struct drm_gem_object *gobj = NULL;
struct bochs_bo *bo = NULL; struct bochs_bo *bo = NULL;
int size, ret; int size, ret;
...@@ -106,22 +104,23 @@ static int bochsfb_create(struct drm_fb_helper *helper, ...@@ -106,22 +104,23 @@ static int bochsfb_create(struct drm_fb_helper *helper,
ttm_bo_unreserve(&bo->bo); ttm_bo_unreserve(&bo->bo);
/* init fb device */ /* init fb device */
info = framebuffer_alloc(0, device); info = drm_fb_helper_alloc_fbi(helper);
if (info == NULL) if (IS_ERR(info))
return -ENOMEM; return PTR_ERR(info);
info->par = &bochs->fb.helper; info->par = &bochs->fb.helper;
ret = bochs_framebuffer_init(bochs->dev, &bochs->fb.gfb, &mode_cmd, gobj); ret = bochs_framebuffer_init(bochs->dev, &bochs->fb.gfb, &mode_cmd, gobj);
if (ret) if (ret) {
drm_fb_helper_release_fbi(helper);
return ret; return ret;
}
bochs->fb.size = size; bochs->fb.size = size;
/* setup helper */ /* setup helper */
fb = &bochs->fb.gfb.base; fb = &bochs->fb.gfb.base;
bochs->fb.helper.fb = fb; bochs->fb.helper.fb = fb;
bochs->fb.helper.fbdev = info;
strcpy(info->fix.id, "bochsdrmfb"); strcpy(info->fix.id, "bochsdrmfb");
...@@ -139,30 +138,17 @@ static int bochsfb_create(struct drm_fb_helper *helper, ...@@ -139,30 +138,17 @@ static int bochsfb_create(struct drm_fb_helper *helper,
info->fix.smem_start = 0; info->fix.smem_start = 0;
info->fix.smem_len = size; info->fix.smem_len = size;
ret = fb_alloc_cmap(&info->cmap, 256, 0);
if (ret) {
DRM_ERROR("%s: can't allocate color map\n", info->fix.id);
return -ENOMEM;
}
return 0; return 0;
} }
static int bochs_fbdev_destroy(struct bochs_device *bochs) static int bochs_fbdev_destroy(struct bochs_device *bochs)
{ {
struct bochs_framebuffer *gfb = &bochs->fb.gfb; struct bochs_framebuffer *gfb = &bochs->fb.gfb;
struct fb_info *info;
DRM_DEBUG_DRIVER("\n"); DRM_DEBUG_DRIVER("\n");
if (bochs->fb.helper.fbdev) { drm_fb_helper_unregister_fbi(&bochs->fb.helper);
info = bochs->fb.helper.fbdev; drm_fb_helper_release_fbi(&bochs->fb.helper);
unregister_framebuffer(info);
if (info->cmap.len)
fb_dealloc_cmap(&info->cmap);
framebuffer_release(info);
}
if (gfb->obj) { if (gfb->obj) {
drm_gem_object_unreference_unlocked(gfb->obj); drm_gem_object_unreference_unlocked(gfb->obj);
......
...@@ -454,25 +454,17 @@ int bochs_dumb_mmap_offset(struct drm_file *file, struct drm_device *dev, ...@@ -454,25 +454,17 @@ int bochs_dumb_mmap_offset(struct drm_file *file, struct drm_device *dev,
uint32_t handle, uint64_t *offset) uint32_t handle, uint64_t *offset)
{ {
struct drm_gem_object *obj; struct drm_gem_object *obj;
int ret;
struct bochs_bo *bo; struct bochs_bo *bo;
mutex_lock(&dev->struct_mutex);
obj = drm_gem_object_lookup(dev, file, handle); obj = drm_gem_object_lookup(dev, file, handle);
if (obj == NULL) { if (obj == NULL)
ret = -ENOENT; return -ENOENT;
goto out_unlock;
}
bo = gem_to_bochs_bo(obj); bo = gem_to_bochs_bo(obj);
*offset = bochs_bo_mmap_offset(bo); *offset = bochs_bo_mmap_offset(bo);
drm_gem_object_unreference(obj); drm_gem_object_unreference_unlocked(obj);
ret = 0; return 0;
out_unlock:
mutex_unlock(&dev->struct_mutex);
return ret;
} }
/* ---------------------------------------------------------------------- */ /* ---------------------------------------------------------------------- */
......
...@@ -92,7 +92,7 @@ static int cirrus_pm_suspend(struct device *dev) ...@@ -92,7 +92,7 @@ static int cirrus_pm_suspend(struct device *dev)
if (cdev->mode_info.gfbdev) { if (cdev->mode_info.gfbdev) {
console_lock(); console_lock();
fb_set_suspend(cdev->mode_info.gfbdev->helper.fbdev, 1); drm_fb_helper_set_suspend(&cdev->mode_info.gfbdev->helper, 1);
console_unlock(); console_unlock();
} }
...@@ -109,7 +109,7 @@ static int cirrus_pm_resume(struct device *dev) ...@@ -109,7 +109,7 @@ static int cirrus_pm_resume(struct device *dev)
if (cdev->mode_info.gfbdev) { if (cdev->mode_info.gfbdev) {
console_lock(); console_lock();
fb_set_suspend(cdev->mode_info.gfbdev->helper.fbdev, 0); drm_fb_helper_set_suspend(&cdev->mode_info.gfbdev->helper, 0);
console_unlock(); console_unlock();
} }
......
...@@ -98,7 +98,7 @@ static void cirrus_fillrect(struct fb_info *info, ...@@ -98,7 +98,7 @@ static void cirrus_fillrect(struct fb_info *info,
const struct fb_fillrect *rect) const struct fb_fillrect *rect)
{ {
struct cirrus_fbdev *afbdev = info->par; struct cirrus_fbdev *afbdev = info->par;
sys_fillrect(info, rect); drm_fb_helper_sys_fillrect(info, rect);
cirrus_dirty_update(afbdev, rect->dx, rect->dy, rect->width, cirrus_dirty_update(afbdev, rect->dx, rect->dy, rect->width,
rect->height); rect->height);
} }
...@@ -107,7 +107,7 @@ static void cirrus_copyarea(struct fb_info *info, ...@@ -107,7 +107,7 @@ static void cirrus_copyarea(struct fb_info *info,
const struct fb_copyarea *area) const struct fb_copyarea *area)
{ {
struct cirrus_fbdev *afbdev = info->par; struct cirrus_fbdev *afbdev = info->par;
sys_copyarea(info, area); drm_fb_helper_sys_copyarea(info, area);
cirrus_dirty_update(afbdev, area->dx, area->dy, area->width, cirrus_dirty_update(afbdev, area->dx, area->dy, area->width,
area->height); area->height);
} }
...@@ -116,7 +116,7 @@ static void cirrus_imageblit(struct fb_info *info, ...@@ -116,7 +116,7 @@ static void cirrus_imageblit(struct fb_info *info,
const struct fb_image *image) const struct fb_image *image)
{ {
struct cirrus_fbdev *afbdev = info->par; struct cirrus_fbdev *afbdev = info->par;
sys_imageblit(info, image); drm_fb_helper_sys_imageblit(info, image);
cirrus_dirty_update(afbdev, image->dx, image->dy, image->width, cirrus_dirty_update(afbdev, image->dx, image->dy, image->width,
image->height); image->height);
} }
...@@ -165,12 +165,10 @@ static int cirrusfb_create(struct drm_fb_helper *helper, ...@@ -165,12 +165,10 @@ static int cirrusfb_create(struct drm_fb_helper *helper,
{ {
struct cirrus_fbdev *gfbdev = struct cirrus_fbdev *gfbdev =
container_of(helper, struct cirrus_fbdev, helper); container_of(helper, struct cirrus_fbdev, helper);
struct drm_device *dev = gfbdev->helper.dev;
struct cirrus_device *cdev = gfbdev->helper.dev->dev_private; struct cirrus_device *cdev = gfbdev->helper.dev->dev_private;
struct fb_info *info; struct fb_info *info;
struct drm_framebuffer *fb; struct drm_framebuffer *fb;
struct drm_mode_fb_cmd2 mode_cmd; struct drm_mode_fb_cmd2 mode_cmd;
struct device *device = &dev->pdev->dev;
void *sysram; void *sysram;
struct drm_gem_object *gobj = NULL; struct drm_gem_object *gobj = NULL;
struct cirrus_bo *bo = NULL; struct cirrus_bo *bo = NULL;
...@@ -195,9 +193,9 @@ static int cirrusfb_create(struct drm_fb_helper *helper, ...@@ -195,9 +193,9 @@ static int cirrusfb_create(struct drm_fb_helper *helper,
if (!sysram) if (!sysram)
return -ENOMEM; return -ENOMEM;
info = framebuffer_alloc(0, device); info = drm_fb_helper_alloc_fbi(helper);
if (info == NULL) if (IS_ERR(info))
return -ENOMEM; return PTR_ERR(info);
info->par = gfbdev; info->par = gfbdev;
...@@ -216,11 +214,9 @@ static int cirrusfb_create(struct drm_fb_helper *helper, ...@@ -216,11 +214,9 @@ static int cirrusfb_create(struct drm_fb_helper *helper,
/* setup helper */ /* setup helper */
gfbdev->helper.fb = fb; gfbdev->helper.fb = fb;
gfbdev->helper.fbdev = info;
strcpy(info->fix.id, "cirrusdrmfb"); strcpy(info->fix.id, "cirrusdrmfb");
info->flags = FBINFO_DEFAULT; info->flags = FBINFO_DEFAULT;
info->fbops = &cirrusfb_ops; info->fbops = &cirrusfb_ops;
...@@ -229,11 +225,6 @@ static int cirrusfb_create(struct drm_fb_helper *helper, ...@@ -229,11 +225,6 @@ static int cirrusfb_create(struct drm_fb_helper *helper,
sizes->fb_height); sizes->fb_height);
/* setup aperture base/size for vesafb takeover */ /* setup aperture base/size for vesafb takeover */
info->apertures = alloc_apertures(1);
if (!info->apertures) {
ret = -ENOMEM;
goto out_iounmap;
}
info->apertures->ranges[0].base = cdev->dev->mode_config.fb_base; info->apertures->ranges[0].base = cdev->dev->mode_config.fb_base;
info->apertures->ranges[0].size = cdev->mc.vram_size; info->apertures->ranges[0].size = cdev->mc.vram_size;
...@@ -246,13 +237,6 @@ static int cirrusfb_create(struct drm_fb_helper *helper, ...@@ -246,13 +237,6 @@ static int cirrusfb_create(struct drm_fb_helper *helper,
info->fix.mmio_start = 0; info->fix.mmio_start = 0;
info->fix.mmio_len = 0; info->fix.mmio_len = 0;
ret = fb_alloc_cmap(&info->cmap, 256, 0);
if (ret) {
DRM_ERROR("%s: can't allocate color map\n", info->fix.id);
ret = -ENOMEM;
goto out_iounmap;
}
DRM_INFO("fb mappable at 0x%lX\n", info->fix.smem_start); DRM_INFO("fb mappable at 0x%lX\n", info->fix.smem_start);
DRM_INFO("vram aper at 0x%lX\n", (unsigned long)info->fix.smem_start); DRM_INFO("vram aper at 0x%lX\n", (unsigned long)info->fix.smem_start);
DRM_INFO("size %lu\n", (unsigned long)info->fix.smem_len); DRM_INFO("size %lu\n", (unsigned long)info->fix.smem_len);
...@@ -260,24 +244,15 @@ static int cirrusfb_create(struct drm_fb_helper *helper, ...@@ -260,24 +244,15 @@ static int cirrusfb_create(struct drm_fb_helper *helper,
DRM_INFO(" pitch is %d\n", fb->pitches[0]); DRM_INFO(" pitch is %d\n", fb->pitches[0]);
return 0; return 0;
out_iounmap:
return ret;
} }
static int cirrus_fbdev_destroy(struct drm_device *dev, static int cirrus_fbdev_destroy(struct drm_device *dev,
struct cirrus_fbdev *gfbdev) struct cirrus_fbdev *gfbdev)
{ {
struct fb_info *info;
struct cirrus_framebuffer *gfb = &gfbdev->gfb; struct cirrus_framebuffer *gfb = &gfbdev->gfb;
if (gfbdev->helper.fbdev) { drm_fb_helper_unregister_fbi(&gfbdev->helper);
info = gfbdev->helper.fbdev; drm_fb_helper_release_fbi(&gfbdev->helper);
unregister_framebuffer(info);
if (info->cmap.len)
fb_dealloc_cmap(&info->cmap);
framebuffer_release(info);
}
if (gfb->obj) { if (gfb->obj) {
drm_gem_object_unreference_unlocked(gfb->obj); drm_gem_object_unreference_unlocked(gfb->obj);
......
...@@ -293,25 +293,18 @@ cirrus_dumb_mmap_offset(struct drm_file *file, ...@@ -293,25 +293,18 @@ cirrus_dumb_mmap_offset(struct drm_file *file,
uint64_t *offset) uint64_t *offset)
{ {
struct drm_gem_object *obj; struct drm_gem_object *obj;
int ret;
struct cirrus_bo *bo; struct cirrus_bo *bo;
mutex_lock(&dev->struct_mutex);
obj = drm_gem_object_lookup(dev, file, handle); obj = drm_gem_object_lookup(dev, file, handle);
if (obj == NULL) { if (obj == NULL)
ret = -ENOENT; return -ENOENT;
goto out_unlock;
}
bo = gem_to_cirrus_bo(obj); bo = gem_to_cirrus_bo(obj);
*offset = cirrus_bo_mmap_offset(bo); *offset = cirrus_bo_mmap_offset(bo);
drm_gem_object_unreference(obj); drm_gem_object_unreference_unlocked(obj);
ret = 0;
out_unlock:
mutex_unlock(&dev->struct_mutex);
return ret;
return 0;
} }
bool cirrus_check_framebuffer(struct cirrus_device *cdev, int width, int height, bool cirrus_check_framebuffer(struct cirrus_device *cdev, int width, int height,
......
...@@ -153,9 +153,15 @@ void drm_atomic_state_default_clear(struct drm_atomic_state *state) ...@@ -153,9 +153,15 @@ void drm_atomic_state_default_clear(struct drm_atomic_state *state)
if (!connector) if (!connector)
continue; continue;
WARN_ON(!drm_modeset_is_locked(&config->connection_mutex)); /*
* FIXME: Async commits can race with connector unplugging and
connector->funcs->atomic_destroy_state(connector, * there's currently nothing that prevents cleanup up state for
* deleted connectors. As long as the callback doesn't look at
* the connector we'll be fine though, so make sure that's the
* case by setting all connector pointers to NULL.
*/
state->connector_states[i]->connector = NULL;
connector->funcs->atomic_destroy_state(NULL,
state->connector_states[i]); state->connector_states[i]);
state->connectors[i] = NULL; state->connectors[i] = NULL;
state->connector_states[i] = NULL; state->connector_states[i] = NULL;
...@@ -1224,6 +1230,9 @@ int drm_atomic_check_only(struct drm_atomic_state *state) ...@@ -1224,6 +1230,9 @@ int drm_atomic_check_only(struct drm_atomic_state *state)
} }
} }
if (ret == 0)
ww_acquire_done(&state->acquire_ctx->ww_ctx);
return ret; return ret;
} }
EXPORT_SYMBOL(drm_atomic_check_only); EXPORT_SYMBOL(drm_atomic_check_only);
......
...@@ -299,7 +299,7 @@ mode_fixup(struct drm_atomic_state *state) ...@@ -299,7 +299,7 @@ mode_fixup(struct drm_atomic_state *state)
encoder->base.id, encoder->name); encoder->base.id, encoder->name);
return ret; return ret;
} }
} else { } else if (funcs->mode_fixup) {
ret = funcs->mode_fixup(encoder, &crtc_state->mode, ret = funcs->mode_fixup(encoder, &crtc_state->mode,
&crtc_state->adjusted_mode); &crtc_state->adjusted_mode);
if (!ret) { if (!ret) {
...@@ -958,7 +958,7 @@ drm_atomic_helper_wait_for_vblanks(struct drm_device *dev, ...@@ -958,7 +958,7 @@ drm_atomic_helper_wait_for_vblanks(struct drm_device *dev,
continue; continue;
old_crtc_state->enable = true; old_crtc_state->enable = true;
old_crtc_state->last_vblank_count = drm_vblank_count(dev, i); old_crtc_state->last_vblank_count = drm_crtc_vblank_count(crtc);
} }
for_each_crtc_in_state(old_state, crtc, old_crtc_state, i) { for_each_crtc_in_state(old_state, crtc, old_crtc_state, i) {
...@@ -967,7 +967,7 @@ drm_atomic_helper_wait_for_vblanks(struct drm_device *dev, ...@@ -967,7 +967,7 @@ drm_atomic_helper_wait_for_vblanks(struct drm_device *dev,
ret = wait_event_timeout(dev->vblank[i].queue, ret = wait_event_timeout(dev->vblank[i].queue,
old_crtc_state->last_vblank_count != old_crtc_state->last_vblank_count !=
drm_vblank_count(dev, i), drm_crtc_vblank_count(crtc),
msecs_to_jiffies(50)); msecs_to_jiffies(50));
drm_crtc_vblank_put(crtc); drm_crtc_vblank_put(crtc);
......
...@@ -1151,7 +1151,7 @@ EXPORT_SYMBOL(drm_encoder_cleanup); ...@@ -1151,7 +1151,7 @@ EXPORT_SYMBOL(drm_encoder_cleanup);
int drm_universal_plane_init(struct drm_device *dev, struct drm_plane *plane, int drm_universal_plane_init(struct drm_device *dev, struct drm_plane *plane,
unsigned long possible_crtcs, unsigned long possible_crtcs,
const struct drm_plane_funcs *funcs, const struct drm_plane_funcs *funcs,
const uint32_t *formats, uint32_t format_count, const uint32_t *formats, unsigned int format_count,
enum drm_plane_type type) enum drm_plane_type type)
{ {
struct drm_mode_config *config = &dev->mode_config; struct drm_mode_config *config = &dev->mode_config;
...@@ -1225,7 +1225,7 @@ EXPORT_SYMBOL(drm_universal_plane_init); ...@@ -1225,7 +1225,7 @@ EXPORT_SYMBOL(drm_universal_plane_init);
int drm_plane_init(struct drm_device *dev, struct drm_plane *plane, int drm_plane_init(struct drm_device *dev, struct drm_plane *plane,
unsigned long possible_crtcs, unsigned long possible_crtcs,
const struct drm_plane_funcs *funcs, const struct drm_plane_funcs *funcs,
const uint32_t *formats, uint32_t format_count, const uint32_t *formats, unsigned int format_count,
bool is_primary) bool is_primary)
{ {
enum drm_plane_type type; enum drm_plane_type type;
...@@ -5273,12 +5273,14 @@ void drm_mode_config_reset(struct drm_device *dev) ...@@ -5273,12 +5273,14 @@ void drm_mode_config_reset(struct drm_device *dev)
if (encoder->funcs->reset) if (encoder->funcs->reset)
encoder->funcs->reset(encoder); encoder->funcs->reset(encoder);
mutex_lock(&dev->mode_config.mutex);
drm_for_each_connector(connector, dev) { drm_for_each_connector(connector, dev) {
connector->status = connector_status_unknown; connector->status = connector_status_unknown;
if (connector->funcs->reset) if (connector->funcs->reset)
connector->funcs->reset(connector); connector->funcs->reset(connector);
} }
mutex_unlock(&dev->mode_config.mutex);
} }
EXPORT_SYMBOL(drm_mode_config_reset); EXPORT_SYMBOL(drm_mode_config_reset);
......
...@@ -3802,7 +3802,7 @@ int drm_add_modes_noedid(struct drm_connector *connector, ...@@ -3802,7 +3802,7 @@ int drm_add_modes_noedid(struct drm_connector *connector,
struct drm_display_mode *mode; struct drm_display_mode *mode;
struct drm_device *dev = connector->dev; struct drm_device *dev = connector->dev;
count = sizeof(drm_dmt_modes) / sizeof(struct drm_display_mode); count = ARRAY_SIZE(drm_dmt_modes);
if (hdisplay < 0) if (hdisplay < 0)
hdisplay = 0; hdisplay = 0;
if (vdisplay < 0) if (vdisplay < 0)
......
...@@ -222,9 +222,9 @@ EXPORT_SYMBOL_GPL(drm_fb_cma_debugfs_show); ...@@ -222,9 +222,9 @@ EXPORT_SYMBOL_GPL(drm_fb_cma_debugfs_show);
static struct fb_ops drm_fbdev_cma_ops = { static struct fb_ops drm_fbdev_cma_ops = {
.owner = THIS_MODULE, .owner = THIS_MODULE,
.fb_fillrect = sys_fillrect, .fb_fillrect = drm_fb_helper_sys_fillrect,
.fb_copyarea = sys_copyarea, .fb_copyarea = drm_fb_helper_sys_copyarea,
.fb_imageblit = sys_imageblit, .fb_imageblit = drm_fb_helper_sys_imageblit,
.fb_check_var = drm_fb_helper_check_var, .fb_check_var = drm_fb_helper_check_var,
.fb_set_par = drm_fb_helper_set_par, .fb_set_par = drm_fb_helper_set_par,
.fb_blank = drm_fb_helper_blank, .fb_blank = drm_fb_helper_blank,
...@@ -263,10 +263,9 @@ static int drm_fbdev_cma_create(struct drm_fb_helper *helper, ...@@ -263,10 +263,9 @@ static int drm_fbdev_cma_create(struct drm_fb_helper *helper,
if (IS_ERR(obj)) if (IS_ERR(obj))
return -ENOMEM; return -ENOMEM;
fbi = framebuffer_alloc(0, dev->dev); fbi = drm_fb_helper_alloc_fbi(helper);
if (!fbi) { if (IS_ERR(fbi)) {
dev_err(dev->dev, "Failed to allocate framebuffer info.\n"); ret = PTR_ERR(fbi);
ret = -ENOMEM;
goto err_drm_gem_cma_free_object; goto err_drm_gem_cma_free_object;
} }
...@@ -274,23 +273,16 @@ static int drm_fbdev_cma_create(struct drm_fb_helper *helper, ...@@ -274,23 +273,16 @@ static int drm_fbdev_cma_create(struct drm_fb_helper *helper,
if (IS_ERR(fbdev_cma->fb)) { if (IS_ERR(fbdev_cma->fb)) {
dev_err(dev->dev, "Failed to allocate DRM framebuffer.\n"); dev_err(dev->dev, "Failed to allocate DRM framebuffer.\n");
ret = PTR_ERR(fbdev_cma->fb); ret = PTR_ERR(fbdev_cma->fb);
goto err_framebuffer_release; goto err_fb_info_destroy;
} }
fb = &fbdev_cma->fb->fb; fb = &fbdev_cma->fb->fb;
helper->fb = fb; helper->fb = fb;
helper->fbdev = fbi;
fbi->par = helper; fbi->par = helper;
fbi->flags = FBINFO_FLAG_DEFAULT; fbi->flags = FBINFO_FLAG_DEFAULT;
fbi->fbops = &drm_fbdev_cma_ops; fbi->fbops = &drm_fbdev_cma_ops;
ret = fb_alloc_cmap(&fbi->cmap, 256, 0);
if (ret) {
dev_err(dev->dev, "Failed to allocate color map.\n");
goto err_drm_fb_cma_destroy;
}
drm_fb_helper_fill_fix(fbi, fb->pitches[0], fb->depth); drm_fb_helper_fill_fix(fbi, fb->pitches[0], fb->depth);
drm_fb_helper_fill_var(fbi, helper, sizes->fb_width, sizes->fb_height); drm_fb_helper_fill_var(fbi, helper, sizes->fb_width, sizes->fb_height);
...@@ -305,11 +297,8 @@ static int drm_fbdev_cma_create(struct drm_fb_helper *helper, ...@@ -305,11 +297,8 @@ static int drm_fbdev_cma_create(struct drm_fb_helper *helper,
return 0; return 0;
err_drm_fb_cma_destroy: err_fb_info_destroy:
drm_framebuffer_unregister_private(fb); drm_fb_helper_release_fbi(helper);
drm_fb_cma_destroy(fb);
err_framebuffer_release:
framebuffer_release(fbi);
err_drm_gem_cma_free_object: err_drm_gem_cma_free_object:
drm_gem_cma_free_object(&obj->base); drm_gem_cma_free_object(&obj->base);
return ret; return ret;
...@@ -385,20 +374,8 @@ EXPORT_SYMBOL_GPL(drm_fbdev_cma_init); ...@@ -385,20 +374,8 @@ EXPORT_SYMBOL_GPL(drm_fbdev_cma_init);
*/ */
void drm_fbdev_cma_fini(struct drm_fbdev_cma *fbdev_cma) void drm_fbdev_cma_fini(struct drm_fbdev_cma *fbdev_cma)
{ {
if (fbdev_cma->fb_helper.fbdev) { drm_fb_helper_unregister_fbi(&fbdev_cma->fb_helper);
struct fb_info *info; drm_fb_helper_release_fbi(&fbdev_cma->fb_helper);
int ret;
info = fbdev_cma->fb_helper.fbdev;
ret = unregister_framebuffer(info);
if (ret < 0)
DRM_DEBUG_KMS("failed unregister_framebuffer()\n");
if (info->cmap.len)
fb_dealloc_cmap(&info->cmap);
framebuffer_release(info);
}
if (fbdev_cma->fb) { if (fbdev_cma->fb) {
drm_framebuffer_unregister_private(&fbdev_cma->fb->fb); drm_framebuffer_unregister_private(&fbdev_cma->fb->fb);
......
...@@ -56,8 +56,8 @@ static LIST_HEAD(kernel_fb_helper_list); ...@@ -56,8 +56,8 @@ static LIST_HEAD(kernel_fb_helper_list);
* Teardown is done with drm_fb_helper_fini(). * Teardown is done with drm_fb_helper_fini().
* *
* At runtime drivers should restore the fbdev console by calling * At runtime drivers should restore the fbdev console by calling
* drm_fb_helper_restore_fbdev_mode() from their ->lastclose callback. They * drm_fb_helper_restore_fbdev_mode_unlocked() from their ->lastclose callback.
* should also notify the fb helper code from updates to the output * They should also notify the fb helper code from updates to the output
* configuration by calling drm_fb_helper_hotplug_event(). For easier * configuration by calling drm_fb_helper_hotplug_event(). For easier
* integration with the output polling code in drm_crtc_helper.c the modeset * integration with the output polling code in drm_crtc_helper.c the modeset
* code provides a ->output_poll_changed callback. * code provides a ->output_poll_changed callback.
...@@ -168,11 +168,14 @@ static void remove_from_modeset(struct drm_mode_set *set, ...@@ -168,11 +168,14 @@ static void remove_from_modeset(struct drm_mode_set *set,
} }
set->num_connectors--; set->num_connectors--;
/* because i915 is pissy about this.. /*
* TODO maybe need to makes sure we set it back to !=NULL somewhere? * TODO maybe need to makes sure we set it back to !=NULL somewhere?
*/ */
if (set->num_connectors == 0) if (set->num_connectors == 0) {
set->fb = NULL; set->fb = NULL;
drm_mode_destroy(connector->dev, set->mode);
set->mode = NULL;
}
} }
int drm_fb_helper_remove_one_connector(struct drm_fb_helper *fb_helper, int drm_fb_helper_remove_one_connector(struct drm_fb_helper *fb_helper,
...@@ -354,21 +357,6 @@ static bool restore_fbdev_mode(struct drm_fb_helper *fb_helper) ...@@ -354,21 +357,6 @@ static bool restore_fbdev_mode(struct drm_fb_helper *fb_helper)
} }
return error; return error;
} }
/**
* drm_fb_helper_restore_fbdev_mode - restore fbdev configuration
* @fb_helper: fbcon to restore
*
* This should be called from driver's drm ->lastclose callback
* when implementing an fbcon on top of kms using this helper. This ensures that
* the user isn't greeted with a black screen when e.g. X dies.
*
* Use this variant if you need to bypass locking (panic), or already
* hold all modeset locks. Otherwise use drm_fb_helper_restore_fbdev_mode_unlocked()
*/
static bool drm_fb_helper_restore_fbdev_mode(struct drm_fb_helper *fb_helper)
{
return restore_fbdev_mode(fb_helper);
}
/** /**
* drm_fb_helper_restore_fbdev_mode_unlocked - restore fbdev configuration * drm_fb_helper_restore_fbdev_mode_unlocked - restore fbdev configuration
...@@ -398,42 +386,6 @@ bool drm_fb_helper_restore_fbdev_mode_unlocked(struct drm_fb_helper *fb_helper) ...@@ -398,42 +386,6 @@ bool drm_fb_helper_restore_fbdev_mode_unlocked(struct drm_fb_helper *fb_helper)
} }
EXPORT_SYMBOL(drm_fb_helper_restore_fbdev_mode_unlocked); EXPORT_SYMBOL(drm_fb_helper_restore_fbdev_mode_unlocked);
/*
* restore fbcon display for all kms driver's using this helper, used for sysrq
* and panic handling.
*/
static bool drm_fb_helper_force_kernel_mode(void)
{
bool ret, error = false;
struct drm_fb_helper *helper;
if (list_empty(&kernel_fb_helper_list))
return false;
list_for_each_entry(helper, &kernel_fb_helper_list, kernel_fb_list) {
struct drm_device *dev = helper->dev;
if (dev->switch_power_state == DRM_SWITCH_POWER_OFF)
continue;
/*
* NOTE: Use trylock mode to avoid deadlocks and sleeping in
* panic context.
*/
if (__drm_modeset_lock_all(dev, true) != 0) {
error = true;
continue;
}
ret = drm_fb_helper_restore_fbdev_mode(helper);
if (ret)
error = true;
drm_modeset_unlock_all(dev);
}
return error;
}
static bool drm_fb_helper_is_bound(struct drm_fb_helper *fb_helper) static bool drm_fb_helper_is_bound(struct drm_fb_helper *fb_helper)
{ {
struct drm_device *dev = fb_helper->dev; struct drm_device *dev = fb_helper->dev;
...@@ -459,6 +411,33 @@ static bool drm_fb_helper_is_bound(struct drm_fb_helper *fb_helper) ...@@ -459,6 +411,33 @@ static bool drm_fb_helper_is_bound(struct drm_fb_helper *fb_helper)
} }
#ifdef CONFIG_MAGIC_SYSRQ #ifdef CONFIG_MAGIC_SYSRQ
/*
* restore fbcon display for all kms driver's using this helper, used for sysrq
* and panic handling.
*/
static bool drm_fb_helper_force_kernel_mode(void)
{
bool ret, error = false;
struct drm_fb_helper *helper;
if (list_empty(&kernel_fb_helper_list))
return false;
list_for_each_entry(helper, &kernel_fb_helper_list, kernel_fb_list) {
struct drm_device *dev = helper->dev;
if (dev->switch_power_state == DRM_SWITCH_POWER_OFF)
continue;
drm_modeset_lock_all(dev);
ret = restore_fbdev_mode(helper);
if (ret)
error = true;
drm_modeset_unlock_all(dev);
}
return error;
}
static void drm_fb_helper_restore_work_fn(struct work_struct *ignored) static void drm_fb_helper_restore_work_fn(struct work_struct *ignored)
{ {
bool ret; bool ret;
...@@ -490,14 +469,6 @@ static void drm_fb_helper_dpms(struct fb_info *info, int dpms_mode) ...@@ -490,14 +469,6 @@ static void drm_fb_helper_dpms(struct fb_info *info, int dpms_mode)
struct drm_connector *connector; struct drm_connector *connector;
int i, j; int i, j;
/*
* fbdev->blank can be called from irq context in case of a panic.
* Since we already have our own special panic handler which will
* restore the fbdev console mode completely, just bail out early.
*/
if (oops_in_progress)
return;
/* /*
* For each CRTC in this fb, turn the connectors on/off. * For each CRTC in this fb, turn the connectors on/off.
*/ */
...@@ -531,6 +502,9 @@ static void drm_fb_helper_dpms(struct fb_info *info, int dpms_mode) ...@@ -531,6 +502,9 @@ static void drm_fb_helper_dpms(struct fb_info *info, int dpms_mode)
*/ */
int drm_fb_helper_blank(int blank, struct fb_info *info) int drm_fb_helper_blank(int blank, struct fb_info *info)
{ {
if (oops_in_progress)
return -EBUSY;
switch (blank) { switch (blank) {
/* Display: On; HSync: On, VSync: On */ /* Display: On; HSync: On, VSync: On */
case FB_BLANK_UNBLANK: case FB_BLANK_UNBLANK:
...@@ -654,6 +628,86 @@ int drm_fb_helper_init(struct drm_device *dev, ...@@ -654,6 +628,86 @@ int drm_fb_helper_init(struct drm_device *dev,
} }
EXPORT_SYMBOL(drm_fb_helper_init); EXPORT_SYMBOL(drm_fb_helper_init);
/**
* drm_fb_helper_alloc_fbi - allocate fb_info and some of its members
* @fb_helper: driver-allocated fbdev helper
*
* A helper to alloc fb_info and the members cmap and apertures. Called
* by the driver within the fb_probe fb_helper callback function.
*
* RETURNS:
* fb_info pointer if things went okay, pointer containing error code
* otherwise
*/
struct fb_info *drm_fb_helper_alloc_fbi(struct drm_fb_helper *fb_helper)
{
struct device *dev = fb_helper->dev->dev;
struct fb_info *info;
int ret;
info = framebuffer_alloc(0, dev);
if (!info)
return ERR_PTR(-ENOMEM);
ret = fb_alloc_cmap(&info->cmap, 256, 0);
if (ret)
goto err_release;
info->apertures = alloc_apertures(1);
if (!info->apertures) {
ret = -ENOMEM;
goto err_free_cmap;
}
fb_helper->fbdev = info;
return info;
err_free_cmap:
fb_dealloc_cmap(&info->cmap);
err_release:
framebuffer_release(info);
return ERR_PTR(ret);
}
EXPORT_SYMBOL(drm_fb_helper_alloc_fbi);
/**
* drm_fb_helper_unregister_fbi - unregister fb_info framebuffer device
* @fb_helper: driver-allocated fbdev helper
*
* A wrapper around unregister_framebuffer, to release the fb_info
* framebuffer device
*/
void drm_fb_helper_unregister_fbi(struct drm_fb_helper *fb_helper)
{
if (fb_helper && fb_helper->fbdev)
unregister_framebuffer(fb_helper->fbdev);
}
EXPORT_SYMBOL(drm_fb_helper_unregister_fbi);
/**
* drm_fb_helper_release_fbi - dealloc fb_info and its members
* @fb_helper: driver-allocated fbdev helper
*
* A helper to free memory taken by fb_info and the members cmap and
* apertures
*/
void drm_fb_helper_release_fbi(struct drm_fb_helper *fb_helper)
{
if (fb_helper) {
struct fb_info *info = fb_helper->fbdev;
if (info) {
if (info->cmap.len)
fb_dealloc_cmap(&info->cmap);
framebuffer_release(info);
}
fb_helper->fbdev = NULL;
}
}
EXPORT_SYMBOL(drm_fb_helper_release_fbi);
void drm_fb_helper_fini(struct drm_fb_helper *fb_helper) void drm_fb_helper_fini(struct drm_fb_helper *fb_helper)
{ {
if (!list_empty(&fb_helper->kernel_fb_list)) { if (!list_empty(&fb_helper->kernel_fb_list)) {
...@@ -668,6 +722,149 @@ void drm_fb_helper_fini(struct drm_fb_helper *fb_helper) ...@@ -668,6 +722,149 @@ void drm_fb_helper_fini(struct drm_fb_helper *fb_helper)
} }
EXPORT_SYMBOL(drm_fb_helper_fini); EXPORT_SYMBOL(drm_fb_helper_fini);
/**
* drm_fb_helper_unlink_fbi - wrapper around unlink_framebuffer
* @fb_helper: driver-allocated fbdev helper
*
* A wrapper around unlink_framebuffer implemented by fbdev core
*/
void drm_fb_helper_unlink_fbi(struct drm_fb_helper *fb_helper)
{
if (fb_helper && fb_helper->fbdev)
unlink_framebuffer(fb_helper->fbdev);
}
EXPORT_SYMBOL(drm_fb_helper_unlink_fbi);
/**
* drm_fb_helper_sys_read - wrapper around fb_sys_read
* @info: fb_info struct pointer
* @buf: userspace buffer to read from framebuffer memory
* @count: number of bytes to read from framebuffer memory
* @ppos: read offset within framebuffer memory
*
* A wrapper around fb_sys_read implemented by fbdev core
*/
ssize_t drm_fb_helper_sys_read(struct fb_info *info, char __user *buf,
size_t count, loff_t *ppos)
{
return fb_sys_read(info, buf, count, ppos);
}
EXPORT_SYMBOL(drm_fb_helper_sys_read);
/**
* drm_fb_helper_sys_write - wrapper around fb_sys_write
* @info: fb_info struct pointer
* @buf: userspace buffer to write to framebuffer memory
* @count: number of bytes to write to framebuffer memory
* @ppos: write offset within framebuffer memory
*
* A wrapper around fb_sys_write implemented by fbdev core
*/
ssize_t drm_fb_helper_sys_write(struct fb_info *info, const char __user *buf,
size_t count, loff_t *ppos)
{
return fb_sys_write(info, buf, count, ppos);
}
EXPORT_SYMBOL(drm_fb_helper_sys_write);
/**
* drm_fb_helper_sys_fillrect - wrapper around sys_fillrect
* @info: fbdev registered by the helper
* @rect: info about rectangle to fill
*
* A wrapper around sys_fillrect implemented by fbdev core
*/
void drm_fb_helper_sys_fillrect(struct fb_info *info,
const struct fb_fillrect *rect)
{
sys_fillrect(info, rect);
}
EXPORT_SYMBOL(drm_fb_helper_sys_fillrect);
/**
* drm_fb_helper_sys_copyarea - wrapper around sys_copyarea
* @info: fbdev registered by the helper
* @area: info about area to copy
*
* A wrapper around sys_copyarea implemented by fbdev core
*/
void drm_fb_helper_sys_copyarea(struct fb_info *info,
const struct fb_copyarea *area)
{
sys_copyarea(info, area);
}
EXPORT_SYMBOL(drm_fb_helper_sys_copyarea);
/**
* drm_fb_helper_sys_imageblit - wrapper around sys_imageblit
* @info: fbdev registered by the helper
* @image: info about image to blit
*
* A wrapper around sys_imageblit implemented by fbdev core
*/
void drm_fb_helper_sys_imageblit(struct fb_info *info,
const struct fb_image *image)
{
sys_imageblit(info, image);
}
EXPORT_SYMBOL(drm_fb_helper_sys_imageblit);
/**
* drm_fb_helper_cfb_fillrect - wrapper around cfb_fillrect
* @info: fbdev registered by the helper
* @rect: info about rectangle to fill
*
* A wrapper around cfb_imageblit implemented by fbdev core
*/
void drm_fb_helper_cfb_fillrect(struct fb_info *info,
const struct fb_fillrect *rect)
{
cfb_fillrect(info, rect);
}
EXPORT_SYMBOL(drm_fb_helper_cfb_fillrect);
/**
* drm_fb_helper_cfb_copyarea - wrapper around cfb_copyarea
* @info: fbdev registered by the helper
* @area: info about area to copy
*
* A wrapper around cfb_copyarea implemented by fbdev core
*/
void drm_fb_helper_cfb_copyarea(struct fb_info *info,
const struct fb_copyarea *area)
{
cfb_copyarea(info, area);
}
EXPORT_SYMBOL(drm_fb_helper_cfb_copyarea);
/**
* drm_fb_helper_cfb_imageblit - wrapper around cfb_imageblit
* @info: fbdev registered by the helper
* @image: info about image to blit
*
* A wrapper around cfb_imageblit implemented by fbdev core
*/
void drm_fb_helper_cfb_imageblit(struct fb_info *info,
const struct fb_image *image)
{
cfb_imageblit(info, image);
}
EXPORT_SYMBOL(drm_fb_helper_cfb_imageblit);
/**
* drm_fb_helper_set_suspend - wrapper around fb_set_suspend
* @fb_helper: driver-allocated fbdev helper
* @state: desired state, zero to resume, non-zero to suspend
*
* A wrapper around fb_set_suspend implemented by fbdev core
*/
void drm_fb_helper_set_suspend(struct drm_fb_helper *fb_helper, int state)
{
if (fb_helper && fb_helper->fbdev)
fb_set_suspend(fb_helper->fbdev, state);
}
EXPORT_SYMBOL(drm_fb_helper_set_suspend);
static int setcolreg(struct drm_crtc *crtc, u16 red, u16 green, static int setcolreg(struct drm_crtc *crtc, u16 red, u16 green,
u16 blue, u16 regno, struct fb_info *info) u16 blue, u16 regno, struct fb_info *info)
{ {
...@@ -755,9 +952,10 @@ int drm_fb_helper_setcmap(struct fb_cmap *cmap, struct fb_info *info) ...@@ -755,9 +952,10 @@ int drm_fb_helper_setcmap(struct fb_cmap *cmap, struct fb_info *info)
int i, j, rc = 0; int i, j, rc = 0;
int start; int start;
if (__drm_modeset_lock_all(dev, !!oops_in_progress)) { if (oops_in_progress)
return -EBUSY; return -EBUSY;
}
drm_modeset_lock_all(dev);
if (!drm_fb_helper_is_bound(fb_helper)) { if (!drm_fb_helper_is_bound(fb_helper)) {
drm_modeset_unlock_all(dev); drm_modeset_unlock_all(dev);
return -EBUSY; return -EBUSY;
...@@ -906,6 +1104,9 @@ int drm_fb_helper_set_par(struct fb_info *info) ...@@ -906,6 +1104,9 @@ int drm_fb_helper_set_par(struct fb_info *info)
struct drm_fb_helper *fb_helper = info->par; struct drm_fb_helper *fb_helper = info->par;
struct fb_var_screeninfo *var = &info->var; struct fb_var_screeninfo *var = &info->var;
if (oops_in_progress)
return -EBUSY;
if (var->pixclock != 0) { if (var->pixclock != 0) {
DRM_ERROR("PIXEL CLOCK SET\n"); DRM_ERROR("PIXEL CLOCK SET\n");
return -EINVAL; return -EINVAL;
...@@ -931,9 +1132,10 @@ int drm_fb_helper_pan_display(struct fb_var_screeninfo *var, ...@@ -931,9 +1132,10 @@ int drm_fb_helper_pan_display(struct fb_var_screeninfo *var,
int ret = 0; int ret = 0;
int i; int i;
if (__drm_modeset_lock_all(dev, !!oops_in_progress)) { if (oops_in_progress)
return -EBUSY; return -EBUSY;
}
drm_modeset_lock_all(dev);
if (!drm_fb_helper_is_bound(fb_helper)) { if (!drm_fb_helper_is_bound(fb_helper)) {
drm_modeset_unlock_all(dev); drm_modeset_unlock_all(dev);
return -EBUSY; return -EBUSY;
......
...@@ -766,7 +766,7 @@ drm_gem_object_free(struct kref *kref) ...@@ -766,7 +766,7 @@ drm_gem_object_free(struct kref *kref)
struct drm_gem_object *obj = (struct drm_gem_object *) kref; struct drm_gem_object *obj = (struct drm_gem_object *) kref;
struct drm_device *dev = obj->dev; struct drm_device *dev = obj->dev;
BUG_ON(!mutex_is_locked(&dev->struct_mutex)); WARN_ON(!mutex_is_locked(&dev->struct_mutex));
if (dev->driver->gem_free_object != NULL) if (dev->driver->gem_free_object != NULL)
dev->driver->gem_free_object(obj); dev->driver->gem_free_object(obj);
......
...@@ -289,20 +289,15 @@ int drm_gem_cma_dumb_map_offset(struct drm_file *file_priv, ...@@ -289,20 +289,15 @@ int drm_gem_cma_dumb_map_offset(struct drm_file *file_priv,
{ {
struct drm_gem_object *gem_obj; struct drm_gem_object *gem_obj;
mutex_lock(&drm->struct_mutex);
gem_obj = drm_gem_object_lookup(drm, file_priv, handle); gem_obj = drm_gem_object_lookup(drm, file_priv, handle);
if (!gem_obj) { if (!gem_obj) {
dev_err(drm->dev, "failed to lookup GEM object\n"); dev_err(drm->dev, "failed to lookup GEM object\n");
mutex_unlock(&drm->struct_mutex);
return -EINVAL; return -EINVAL;
} }
*offset = drm_vma_node_offset_addr(&gem_obj->vma_node); *offset = drm_vma_node_offset_addr(&gem_obj->vma_node);
drm_gem_object_unreference(gem_obj); drm_gem_object_unreference_unlocked(gem_obj);
mutex_unlock(&drm->struct_mutex);
return 0; return 0;
} }
......
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