Commit e0da9686 authored by Dave Airlie's avatar Dave Airlie

Merge tag 'drm-misc-fixes-2021-03-11' of git://anongit.freedesktop.org/drm/drm-misc into drm-fixes

drm-misc-fixes for rc3, rebased on rc2:
- Fix oops in drm_fbdev_cleanup()
- unpin qxl bos created as pinned when freeing them,
  and make ttm only warn once on this behavior.
- Use LCD management for atyfb on PPC_MAC.
- Use gitlab for drm bugzilla now.
- Fix ttm page pool accounting.
- Zero head.surface_id correctly in qxl.
- Assorted fixes for shmem helpers.
- Shutdown kms poll helper in meson correctly.
- Clear holes when converting compat ioctl's between 32-bits and 64-bits.
Signed-off-by: default avatarDave Airlie <airlied@redhat.com>

From: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/4606f08e-d0e8-c543-5e96-cee2fd728a41@linux.intel.com
parents a38fd874 de066e11
...@@ -613,6 +613,27 @@ Some of these date from the very introduction of KMS in 2008 ... ...@@ -613,6 +613,27 @@ Some of these date from the very introduction of KMS in 2008 ...
Level: Intermediate Level: Intermediate
Remove automatic page mapping from dma-buf importing
----------------------------------------------------
When importing dma-bufs, the dma-buf and PRIME frameworks automatically map
imported pages into the importer's DMA area. drm_gem_prime_fd_to_handle() and
drm_gem_prime_handle_to_fd() require that importers call dma_buf_attach()
even if they never do actual device DMA, but only CPU access through
dma_buf_vmap(). This is a problem for USB devices, which do not support DMA
operations.
To fix the issue, automatic page mappings should be removed from the
buffer-sharing code. Fixing this is a bit more involved, since the import/export
cache is also tied to &drm_gem_object.import_attach. Meanwhile we paper over
this problem for USB devices by fishing out the USB host controller device, as
long as that supports DMA. Otherwise importing can still needlessly fail.
Contact: Thomas Zimmermann <tzimmermann@suse.de>, Daniel Vetter
Level: Advanced
Better Testing Better Testing
============== ==============
......
...@@ -5835,7 +5835,7 @@ M: David Airlie <airlied@linux.ie> ...@@ -5835,7 +5835,7 @@ M: David Airlie <airlied@linux.ie>
M: Daniel Vetter <daniel@ffwll.ch> M: Daniel Vetter <daniel@ffwll.ch>
L: dri-devel@lists.freedesktop.org L: dri-devel@lists.freedesktop.org
S: Maintained S: Maintained
B: https://bugs.freedesktop.org/ B: https://gitlab.freedesktop.org/drm
C: irc://chat.freenode.net/dri-devel C: irc://chat.freenode.net/dri-devel
T: git git://anongit.freedesktop.org/drm/drm T: git git://anongit.freedesktop.org/drm/drm
F: Documentation/devicetree/bindings/display/ F: Documentation/devicetree/bindings/display/
......
...@@ -2048,7 +2048,7 @@ static void drm_fbdev_cleanup(struct drm_fb_helper *fb_helper) ...@@ -2048,7 +2048,7 @@ static void drm_fbdev_cleanup(struct drm_fb_helper *fb_helper)
if (shadow) if (shadow)
vfree(shadow); vfree(shadow);
else else if (fb_helper->buffer)
drm_client_buffer_vunmap(fb_helper->buffer); drm_client_buffer_vunmap(fb_helper->buffer);
drm_client_framebuffer_delete(fb_helper->buffer); drm_client_framebuffer_delete(fb_helper->buffer);
......
...@@ -357,13 +357,14 @@ static void drm_gem_shmem_vunmap_locked(struct drm_gem_shmem_object *shmem, ...@@ -357,13 +357,14 @@ static void drm_gem_shmem_vunmap_locked(struct drm_gem_shmem_object *shmem,
if (--shmem->vmap_use_count > 0) if (--shmem->vmap_use_count > 0)
return; return;
if (obj->import_attach) if (obj->import_attach) {
dma_buf_vunmap(obj->import_attach->dmabuf, map); dma_buf_vunmap(obj->import_attach->dmabuf, map);
else } else {
vunmap(shmem->vaddr); vunmap(shmem->vaddr);
drm_gem_shmem_put_pages(shmem);
}
shmem->vaddr = NULL; shmem->vaddr = NULL;
drm_gem_shmem_put_pages(shmem);
} }
/* /*
...@@ -525,14 +526,28 @@ static vm_fault_t drm_gem_shmem_fault(struct vm_fault *vmf) ...@@ -525,14 +526,28 @@ static vm_fault_t drm_gem_shmem_fault(struct vm_fault *vmf)
struct drm_gem_object *obj = vma->vm_private_data; struct drm_gem_object *obj = vma->vm_private_data;
struct drm_gem_shmem_object *shmem = to_drm_gem_shmem_obj(obj); struct drm_gem_shmem_object *shmem = to_drm_gem_shmem_obj(obj);
loff_t num_pages = obj->size >> PAGE_SHIFT; loff_t num_pages = obj->size >> PAGE_SHIFT;
vm_fault_t ret;
struct page *page; struct page *page;
pgoff_t page_offset;
if (vmf->pgoff >= num_pages || WARN_ON_ONCE(!shmem->pages)) /* We don't use vmf->pgoff since that has the fake offset */
return VM_FAULT_SIGBUS; page_offset = (vmf->address - vma->vm_start) >> PAGE_SHIFT;
page = shmem->pages[vmf->pgoff]; mutex_lock(&shmem->pages_lock);
return vmf_insert_page(vma, vmf->address, page); if (page_offset >= num_pages ||
WARN_ON_ONCE(!shmem->pages) ||
shmem->madv < 0) {
ret = VM_FAULT_SIGBUS;
} else {
page = shmem->pages[page_offset];
ret = vmf_insert_page(vma, vmf->address, page);
}
mutex_unlock(&shmem->pages_lock);
return ret;
} }
static void drm_gem_shmem_vm_open(struct vm_area_struct *vma) static void drm_gem_shmem_vm_open(struct vm_area_struct *vma)
...@@ -581,9 +596,6 @@ int drm_gem_shmem_mmap(struct drm_gem_object *obj, struct vm_area_struct *vma) ...@@ -581,9 +596,6 @@ int drm_gem_shmem_mmap(struct drm_gem_object *obj, struct vm_area_struct *vma)
struct drm_gem_shmem_object *shmem; struct drm_gem_shmem_object *shmem;
int ret; int ret;
/* Remove the fake offset */
vma->vm_pgoff -= drm_vma_node_start(&obj->vma_node);
if (obj->import_attach) { if (obj->import_attach) {
/* Drop the reference drm_gem_mmap_obj() acquired.*/ /* Drop the reference drm_gem_mmap_obj() acquired.*/
drm_gem_object_put(obj); drm_gem_object_put(obj);
......
...@@ -99,6 +99,8 @@ static int compat_drm_version(struct file *file, unsigned int cmd, ...@@ -99,6 +99,8 @@ static int compat_drm_version(struct file *file, unsigned int cmd,
if (copy_from_user(&v32, (void __user *)arg, sizeof(v32))) if (copy_from_user(&v32, (void __user *)arg, sizeof(v32)))
return -EFAULT; return -EFAULT;
memset(&v, 0, sizeof(v));
v = (struct drm_version) { v = (struct drm_version) {
.name_len = v32.name_len, .name_len = v32.name_len,
.name = compat_ptr(v32.name), .name = compat_ptr(v32.name),
...@@ -137,6 +139,9 @@ static int compat_drm_getunique(struct file *file, unsigned int cmd, ...@@ -137,6 +139,9 @@ static int compat_drm_getunique(struct file *file, unsigned int cmd,
if (copy_from_user(&uq32, (void __user *)arg, sizeof(uq32))) if (copy_from_user(&uq32, (void __user *)arg, sizeof(uq32)))
return -EFAULT; return -EFAULT;
memset(&uq, 0, sizeof(uq));
uq = (struct drm_unique){ uq = (struct drm_unique){
.unique_len = uq32.unique_len, .unique_len = uq32.unique_len,
.unique = compat_ptr(uq32.unique), .unique = compat_ptr(uq32.unique),
...@@ -265,6 +270,8 @@ static int compat_drm_getclient(struct file *file, unsigned int cmd, ...@@ -265,6 +270,8 @@ static int compat_drm_getclient(struct file *file, unsigned int cmd,
if (copy_from_user(&c32, argp, sizeof(c32))) if (copy_from_user(&c32, argp, sizeof(c32)))
return -EFAULT; return -EFAULT;
memset(&client, 0, sizeof(client));
client.idx = c32.idx; client.idx = c32.idx;
err = drm_ioctl_kernel(file, drm_getclient, &client, 0); err = drm_ioctl_kernel(file, drm_getclient, &client, 0);
...@@ -852,6 +859,8 @@ static int compat_drm_wait_vblank(struct file *file, unsigned int cmd, ...@@ -852,6 +859,8 @@ static int compat_drm_wait_vblank(struct file *file, unsigned int cmd,
if (copy_from_user(&req32, argp, sizeof(req32))) if (copy_from_user(&req32, argp, sizeof(req32)))
return -EFAULT; return -EFAULT;
memset(&req, 0, sizeof(req));
req.request.type = req32.request.type; req.request.type = req32.request.type;
req.request.sequence = req32.request.sequence; req.request.sequence = req32.request.sequence;
req.request.signal = req32.request.signal; req.request.signal = req32.request.signal;
...@@ -889,6 +898,8 @@ static int compat_drm_mode_addfb2(struct file *file, unsigned int cmd, ...@@ -889,6 +898,8 @@ static int compat_drm_mode_addfb2(struct file *file, unsigned int cmd,
struct drm_mode_fb_cmd2 req64; struct drm_mode_fb_cmd2 req64;
int err; int err;
memset(&req64, 0, sizeof(req64));
if (copy_from_user(&req64, argp, if (copy_from_user(&req64, argp,
offsetof(drm_mode_fb_cmd232_t, modifier))) offsetof(drm_mode_fb_cmd232_t, modifier)))
return -EFAULT; return -EFAULT;
......
...@@ -482,6 +482,16 @@ static int meson_probe_remote(struct platform_device *pdev, ...@@ -482,6 +482,16 @@ static int meson_probe_remote(struct platform_device *pdev,
return count; return count;
} }
static void meson_drv_shutdown(struct platform_device *pdev)
{
struct meson_drm *priv = dev_get_drvdata(&pdev->dev);
struct drm_device *drm = priv->drm;
DRM_DEBUG_DRIVER("\n");
drm_kms_helper_poll_fini(drm);
drm_atomic_helper_shutdown(drm);
}
static int meson_drv_probe(struct platform_device *pdev) static int meson_drv_probe(struct platform_device *pdev)
{ {
struct component_match *match = NULL; struct component_match *match = NULL;
...@@ -553,6 +563,7 @@ static const struct dev_pm_ops meson_drv_pm_ops = { ...@@ -553,6 +563,7 @@ static const struct dev_pm_ops meson_drv_pm_ops = {
static struct platform_driver meson_drm_platform_driver = { static struct platform_driver meson_drm_platform_driver = {
.probe = meson_drv_probe, .probe = meson_drv_probe,
.shutdown = meson_drv_shutdown,
.driver = { .driver = {
.name = "meson-drm", .name = "meson-drm",
.of_match_table = dt_match, .of_match_table = dt_match,
......
...@@ -328,6 +328,7 @@ static void qxl_crtc_update_monitors_config(struct drm_crtc *crtc, ...@@ -328,6 +328,7 @@ static void qxl_crtc_update_monitors_config(struct drm_crtc *crtc,
head.id = i; head.id = i;
head.flags = 0; head.flags = 0;
head.surface_id = 0;
oldcount = qdev->monitors_config->count; oldcount = qdev->monitors_config->count;
if (crtc->state->active) { if (crtc->state->active) {
struct drm_display_mode *mode = &crtc->mode; struct drm_display_mode *mode = &crtc->mode;
......
...@@ -321,7 +321,7 @@ int qxl_alloc_release_reserved(struct qxl_device *qdev, unsigned long size, ...@@ -321,7 +321,7 @@ int qxl_alloc_release_reserved(struct qxl_device *qdev, unsigned long size,
int type, struct qxl_release **release, int type, struct qxl_release **release,
struct qxl_bo **rbo) struct qxl_bo **rbo)
{ {
struct qxl_bo *bo; struct qxl_bo *bo, *free_bo = NULL;
int idr_ret; int idr_ret;
int ret = 0; int ret = 0;
union qxl_release_info *info; union qxl_release_info *info;
...@@ -347,7 +347,7 @@ int qxl_alloc_release_reserved(struct qxl_device *qdev, unsigned long size, ...@@ -347,7 +347,7 @@ int qxl_alloc_release_reserved(struct qxl_device *qdev, unsigned long size,
mutex_lock(&qdev->release_mutex); mutex_lock(&qdev->release_mutex);
if (qdev->current_release_bo_offset[cur_idx] + 1 >= releases_per_bo[cur_idx]) { if (qdev->current_release_bo_offset[cur_idx] + 1 >= releases_per_bo[cur_idx]) {
qxl_bo_unref(&qdev->current_release_bo[cur_idx]); free_bo = qdev->current_release_bo[cur_idx];
qdev->current_release_bo_offset[cur_idx] = 0; qdev->current_release_bo_offset[cur_idx] = 0;
qdev->current_release_bo[cur_idx] = NULL; qdev->current_release_bo[cur_idx] = NULL;
} }
...@@ -355,6 +355,10 @@ int qxl_alloc_release_reserved(struct qxl_device *qdev, unsigned long size, ...@@ -355,6 +355,10 @@ int qxl_alloc_release_reserved(struct qxl_device *qdev, unsigned long size,
ret = qxl_release_bo_alloc(qdev, &qdev->current_release_bo[cur_idx]); ret = qxl_release_bo_alloc(qdev, &qdev->current_release_bo[cur_idx]);
if (ret) { if (ret) {
mutex_unlock(&qdev->release_mutex); mutex_unlock(&qdev->release_mutex);
if (free_bo) {
qxl_bo_unpin(free_bo);
qxl_bo_unref(&free_bo);
}
qxl_release_free(qdev, *release); qxl_release_free(qdev, *release);
return ret; return ret;
} }
...@@ -370,6 +374,10 @@ int qxl_alloc_release_reserved(struct qxl_device *qdev, unsigned long size, ...@@ -370,6 +374,10 @@ int qxl_alloc_release_reserved(struct qxl_device *qdev, unsigned long size,
*rbo = bo; *rbo = bo;
mutex_unlock(&qdev->release_mutex); mutex_unlock(&qdev->release_mutex);
if (free_bo) {
qxl_bo_unpin(free_bo);
qxl_bo_unref(&free_bo);
}
ret = qxl_release_list_add(*release, bo); ret = qxl_release_list_add(*release, bo);
qxl_bo_unref(&bo); qxl_bo_unref(&bo);
......
...@@ -83,6 +83,7 @@ MODULE_PARM_DESC(eco_mode, "Turn on Eco mode (less bright, more silent)"); ...@@ -83,6 +83,7 @@ MODULE_PARM_DESC(eco_mode, "Turn on Eco mode (less bright, more silent)");
struct gm12u320_device { struct gm12u320_device {
struct drm_device dev; struct drm_device dev;
struct device *dmadev;
struct drm_simple_display_pipe pipe; struct drm_simple_display_pipe pipe;
struct drm_connector conn; struct drm_connector conn;
unsigned char *cmd_buf; unsigned char *cmd_buf;
...@@ -601,6 +602,22 @@ static const uint64_t gm12u320_pipe_modifiers[] = { ...@@ -601,6 +602,22 @@ static const uint64_t gm12u320_pipe_modifiers[] = {
DRM_FORMAT_MOD_INVALID DRM_FORMAT_MOD_INVALID
}; };
/*
* FIXME: Dma-buf sharing requires DMA support by the importing device.
* This function is a workaround to make USB devices work as well.
* See todo.rst for how to fix the issue in the dma-buf framework.
*/
static struct drm_gem_object *gm12u320_gem_prime_import(struct drm_device *dev,
struct dma_buf *dma_buf)
{
struct gm12u320_device *gm12u320 = to_gm12u320(dev);
if (!gm12u320->dmadev)
return ERR_PTR(-ENODEV);
return drm_gem_prime_import_dev(dev, dma_buf, gm12u320->dmadev);
}
DEFINE_DRM_GEM_FOPS(gm12u320_fops); DEFINE_DRM_GEM_FOPS(gm12u320_fops);
static const struct drm_driver gm12u320_drm_driver = { static const struct drm_driver gm12u320_drm_driver = {
...@@ -614,6 +631,7 @@ static const struct drm_driver gm12u320_drm_driver = { ...@@ -614,6 +631,7 @@ static const struct drm_driver gm12u320_drm_driver = {
.fops = &gm12u320_fops, .fops = &gm12u320_fops,
DRM_GEM_SHMEM_DRIVER_OPS, DRM_GEM_SHMEM_DRIVER_OPS,
.gem_prime_import = gm12u320_gem_prime_import,
}; };
static const struct drm_mode_config_funcs gm12u320_mode_config_funcs = { static const struct drm_mode_config_funcs gm12u320_mode_config_funcs = {
...@@ -640,15 +658,18 @@ static int gm12u320_usb_probe(struct usb_interface *interface, ...@@ -640,15 +658,18 @@ static int gm12u320_usb_probe(struct usb_interface *interface,
struct gm12u320_device, dev); struct gm12u320_device, dev);
if (IS_ERR(gm12u320)) if (IS_ERR(gm12u320))
return PTR_ERR(gm12u320); return PTR_ERR(gm12u320);
dev = &gm12u320->dev;
gm12u320->dmadev = usb_intf_get_dma_device(to_usb_interface(dev->dev));
if (!gm12u320->dmadev)
drm_warn(dev, "buffer sharing not supported"); /* not an error */
INIT_DELAYED_WORK(&gm12u320->fb_update.work, gm12u320_fb_update_work); INIT_DELAYED_WORK(&gm12u320->fb_update.work, gm12u320_fb_update_work);
mutex_init(&gm12u320->fb_update.lock); mutex_init(&gm12u320->fb_update.lock);
dev = &gm12u320->dev;
ret = drmm_mode_config_init(dev); ret = drmm_mode_config_init(dev);
if (ret) if (ret)
return ret; goto err_put_device;
dev->mode_config.min_width = GM12U320_USER_WIDTH; dev->mode_config.min_width = GM12U320_USER_WIDTH;
dev->mode_config.max_width = GM12U320_USER_WIDTH; dev->mode_config.max_width = GM12U320_USER_WIDTH;
...@@ -658,15 +679,15 @@ static int gm12u320_usb_probe(struct usb_interface *interface, ...@@ -658,15 +679,15 @@ static int gm12u320_usb_probe(struct usb_interface *interface,
ret = gm12u320_usb_alloc(gm12u320); ret = gm12u320_usb_alloc(gm12u320);
if (ret) if (ret)
return ret; goto err_put_device;
ret = gm12u320_set_ecomode(gm12u320); ret = gm12u320_set_ecomode(gm12u320);
if (ret) if (ret)
return ret; goto err_put_device;
ret = gm12u320_conn_init(gm12u320); ret = gm12u320_conn_init(gm12u320);
if (ret) if (ret)
return ret; goto err_put_device;
ret = drm_simple_display_pipe_init(&gm12u320->dev, ret = drm_simple_display_pipe_init(&gm12u320->dev,
&gm12u320->pipe, &gm12u320->pipe,
...@@ -676,24 +697,31 @@ static int gm12u320_usb_probe(struct usb_interface *interface, ...@@ -676,24 +697,31 @@ static int gm12u320_usb_probe(struct usb_interface *interface,
gm12u320_pipe_modifiers, gm12u320_pipe_modifiers,
&gm12u320->conn); &gm12u320->conn);
if (ret) if (ret)
return ret; goto err_put_device;
drm_mode_config_reset(dev); drm_mode_config_reset(dev);
usb_set_intfdata(interface, dev); usb_set_intfdata(interface, dev);
ret = drm_dev_register(dev, 0); ret = drm_dev_register(dev, 0);
if (ret) if (ret)
return ret; goto err_put_device;
drm_fbdev_generic_setup(dev, 0); drm_fbdev_generic_setup(dev, 0);
return 0; return 0;
err_put_device:
put_device(gm12u320->dmadev);
return ret;
} }
static void gm12u320_usb_disconnect(struct usb_interface *interface) static void gm12u320_usb_disconnect(struct usb_interface *interface)
{ {
struct drm_device *dev = usb_get_intfdata(interface); struct drm_device *dev = usb_get_intfdata(interface);
struct gm12u320_device *gm12u320 = to_gm12u320(dev);
put_device(gm12u320->dmadev);
gm12u320->dmadev = NULL;
drm_dev_unplug(dev); drm_dev_unplug(dev);
drm_atomic_helper_shutdown(dev); drm_atomic_helper_shutdown(dev);
} }
......
...@@ -136,7 +136,8 @@ void ttm_bo_move_to_lru_tail(struct ttm_buffer_object *bo, ...@@ -136,7 +136,8 @@ void ttm_bo_move_to_lru_tail(struct ttm_buffer_object *bo,
struct ttm_bo_device *bdev = bo->bdev; struct ttm_bo_device *bdev = bo->bdev;
struct ttm_resource_manager *man; struct ttm_resource_manager *man;
dma_resv_assert_held(bo->base.resv); if (!bo->deleted)
dma_resv_assert_held(bo->base.resv);
if (bo->pin_count) { if (bo->pin_count) {
ttm_bo_del_from_lru(bo); ttm_bo_del_from_lru(bo);
...@@ -508,8 +509,11 @@ static void ttm_bo_release(struct kref *kref) ...@@ -508,8 +509,11 @@ static void ttm_bo_release(struct kref *kref)
* Make pinned bos immediately available to * Make pinned bos immediately available to
* shrinkers, now that they are queued for * shrinkers, now that they are queued for
* destruction. * destruction.
*
* FIXME: QXL is triggering this. Can be removed when the
* driver is fixed.
*/ */
if (WARN_ON(bo->pin_count)) { if (WARN_ON_ONCE(bo->pin_count)) {
bo->pin_count = 0; bo->pin_count = 0;
ttm_bo_move_to_lru_tail(bo, &bo->mem, NULL); ttm_bo_move_to_lru_tail(bo, &bo->mem, NULL);
} }
......
...@@ -268,13 +268,13 @@ static void ttm_pool_type_init(struct ttm_pool_type *pt, struct ttm_pool *pool, ...@@ -268,13 +268,13 @@ static void ttm_pool_type_init(struct ttm_pool_type *pt, struct ttm_pool *pool,
/* Remove a pool_type from the global shrinker list and free all pages */ /* Remove a pool_type from the global shrinker list and free all pages */
static void ttm_pool_type_fini(struct ttm_pool_type *pt) static void ttm_pool_type_fini(struct ttm_pool_type *pt)
{ {
struct page *p, *tmp; struct page *p;
mutex_lock(&shrinker_lock); mutex_lock(&shrinker_lock);
list_del(&pt->shrinker_list); list_del(&pt->shrinker_list);
mutex_unlock(&shrinker_lock); mutex_unlock(&shrinker_lock);
list_for_each_entry_safe(p, tmp, &pt->pages, lru) while ((p = ttm_pool_type_take(pt)))
ttm_pool_free_page(pt->pool, pt->caching, pt->order, p); ttm_pool_free_page(pt->pool, pt->caching, pt->order, p);
} }
......
...@@ -32,6 +32,22 @@ static int udl_usb_resume(struct usb_interface *interface) ...@@ -32,6 +32,22 @@ static int udl_usb_resume(struct usb_interface *interface)
return drm_mode_config_helper_resume(dev); return drm_mode_config_helper_resume(dev);
} }
/*
* FIXME: Dma-buf sharing requires DMA support by the importing device.
* This function is a workaround to make USB devices work as well.
* See todo.rst for how to fix the issue in the dma-buf framework.
*/
static struct drm_gem_object *udl_driver_gem_prime_import(struct drm_device *dev,
struct dma_buf *dma_buf)
{
struct udl_device *udl = to_udl(dev);
if (!udl->dmadev)
return ERR_PTR(-ENODEV);
return drm_gem_prime_import_dev(dev, dma_buf, udl->dmadev);
}
DEFINE_DRM_GEM_FOPS(udl_driver_fops); DEFINE_DRM_GEM_FOPS(udl_driver_fops);
static const struct drm_driver driver = { static const struct drm_driver driver = {
...@@ -40,6 +56,7 @@ static const struct drm_driver driver = { ...@@ -40,6 +56,7 @@ static const struct drm_driver driver = {
/* GEM hooks */ /* GEM hooks */
.fops = &udl_driver_fops, .fops = &udl_driver_fops,
DRM_GEM_SHMEM_DRIVER_OPS, DRM_GEM_SHMEM_DRIVER_OPS,
.gem_prime_import = udl_driver_gem_prime_import,
.name = DRIVER_NAME, .name = DRIVER_NAME,
.desc = DRIVER_DESC, .desc = DRIVER_DESC,
......
...@@ -50,6 +50,7 @@ struct urb_list { ...@@ -50,6 +50,7 @@ struct urb_list {
struct udl_device { struct udl_device {
struct drm_device drm; struct drm_device drm;
struct device *dev; struct device *dev;
struct device *dmadev;
struct drm_simple_display_pipe display_pipe; struct drm_simple_display_pipe display_pipe;
......
...@@ -315,6 +315,10 @@ int udl_init(struct udl_device *udl) ...@@ -315,6 +315,10 @@ int udl_init(struct udl_device *udl)
DRM_DEBUG("\n"); DRM_DEBUG("\n");
udl->dmadev = usb_intf_get_dma_device(to_usb_interface(dev->dev));
if (!udl->dmadev)
drm_warn(dev, "buffer sharing not supported"); /* not an error */
mutex_init(&udl->gem_lock); mutex_init(&udl->gem_lock);
if (!udl_parse_vendor_descriptor(udl)) { if (!udl_parse_vendor_descriptor(udl)) {
...@@ -343,12 +347,18 @@ int udl_init(struct udl_device *udl) ...@@ -343,12 +347,18 @@ int udl_init(struct udl_device *udl)
err: err:
if (udl->urbs.count) if (udl->urbs.count)
udl_free_urb_list(dev); udl_free_urb_list(dev);
put_device(udl->dmadev);
DRM_ERROR("%d\n", ret); DRM_ERROR("%d\n", ret);
return ret; return ret;
} }
int udl_drop_usb(struct drm_device *dev) int udl_drop_usb(struct drm_device *dev)
{ {
struct udl_device *udl = to_udl(dev);
udl_free_urb_list(dev); udl_free_urb_list(dev);
put_device(udl->dmadev);
udl->dmadev = NULL;
return 0; return 0;
} }
...@@ -748,6 +748,38 @@ void usb_put_intf(struct usb_interface *intf) ...@@ -748,6 +748,38 @@ void usb_put_intf(struct usb_interface *intf)
} }
EXPORT_SYMBOL_GPL(usb_put_intf); EXPORT_SYMBOL_GPL(usb_put_intf);
/**
* usb_intf_get_dma_device - acquire a reference on the usb interface's DMA endpoint
* @intf: the usb interface
*
* While a USB device cannot perform DMA operations by itself, many USB
* controllers can. A call to usb_intf_get_dma_device() returns the DMA endpoint
* for the given USB interface, if any. The returned device structure must be
* released with put_device().
*
* See also usb_get_dma_device().
*
* Returns: A reference to the usb interface's DMA endpoint; or NULL if none
* exists.
*/
struct device *usb_intf_get_dma_device(struct usb_interface *intf)
{
struct usb_device *udev = interface_to_usbdev(intf);
struct device *dmadev;
if (!udev->bus)
return NULL;
dmadev = get_device(udev->bus->sysdev);
if (!dmadev || !dmadev->dma_mask) {
put_device(dmadev);
return NULL;
}
return dmadev;
}
EXPORT_SYMBOL_GPL(usb_intf_get_dma_device);
/* USB device locking /* USB device locking
* *
* USB devices and interfaces are locked using the semaphore in their * USB devices and interfaces are locked using the semaphore in their
......
...@@ -287,11 +287,8 @@ static inline void aty_st_8(int regindex, u8 val, const struct atyfb_par *par) ...@@ -287,11 +287,8 @@ static inline void aty_st_8(int regindex, u8 val, const struct atyfb_par *par)
#endif #endif
} }
#if defined(CONFIG_PMAC_BACKLIGHT) || defined (CONFIG_FB_ATY_GENERIC_LCD) || \
defined (CONFIG_FB_ATY_BACKLIGHT)
extern void aty_st_lcd(int index, u32 val, const struct atyfb_par *par); extern void aty_st_lcd(int index, u32 val, const struct atyfb_par *par);
extern u32 aty_ld_lcd(int index, const struct atyfb_par *par); extern u32 aty_ld_lcd(int index, const struct atyfb_par *par);
#endif
/* /*
* DAC operations * DAC operations
......
...@@ -133,7 +133,7 @@ ...@@ -133,7 +133,7 @@
#define PRINTKE(fmt, args...) printk(KERN_ERR "atyfb: " fmt, ## args) #define PRINTKE(fmt, args...) printk(KERN_ERR "atyfb: " fmt, ## args)
#if defined(CONFIG_PMAC_BACKLIGHT) || defined(CONFIG_FB_ATY_GENERIC_LCD) || \ #if defined(CONFIG_PMAC_BACKLIGHT) || defined(CONFIG_FB_ATY_GENERIC_LCD) || \
defined(CONFIG_FB_ATY_BACKLIGHT) defined(CONFIG_FB_ATY_BACKLIGHT) || defined (CONFIG_PPC_PMAC)
static const u32 lt_lcd_regs[] = { static const u32 lt_lcd_regs[] = {
CNFG_PANEL_LG, CNFG_PANEL_LG,
LCD_GEN_CNTL_LG, LCD_GEN_CNTL_LG,
...@@ -175,8 +175,8 @@ u32 aty_ld_lcd(int index, const struct atyfb_par *par) ...@@ -175,8 +175,8 @@ u32 aty_ld_lcd(int index, const struct atyfb_par *par)
return aty_ld_le32(LCD_DATA, par); return aty_ld_le32(LCD_DATA, par);
} }
} }
#else /* defined(CONFIG_PMAC_BACKLIGHT) || defined(CONFIG_FB_ATY_BACKLIGHT) \ #else /* defined(CONFIG_PMAC_BACKLIGHT) || defined(CONFIG_FB_ATY_BACKLIGHT) ||
defined(CONFIG_FB_ATY_GENERIC_LCD) */ defined(CONFIG_FB_ATY_GENERIC_LCD) || defined(CONFIG_PPC_PMAC) */
void aty_st_lcd(int index, u32 val, const struct atyfb_par *par) void aty_st_lcd(int index, u32 val, const struct atyfb_par *par)
{ } { }
...@@ -184,7 +184,8 @@ u32 aty_ld_lcd(int index, const struct atyfb_par *par) ...@@ -184,7 +184,8 @@ u32 aty_ld_lcd(int index, const struct atyfb_par *par)
{ {
return 0; return 0;
} }
#endif /* defined(CONFIG_PMAC_BACKLIGHT) || defined (CONFIG_FB_ATY_GENERIC_LCD) */ #endif /* defined(CONFIG_PMAC_BACKLIGHT) || defined(CONFIG_FB_ATY_BACKLIGHT) ||
defined (CONFIG_FB_ATY_GENERIC_LCD) || defined(CONFIG_PPC_PMAC) */
#ifdef CONFIG_FB_ATY_GENERIC_LCD #ifdef CONFIG_FB_ATY_GENERIC_LCD
/* /*
......
...@@ -746,6 +746,8 @@ extern int usb_lock_device_for_reset(struct usb_device *udev, ...@@ -746,6 +746,8 @@ extern int usb_lock_device_for_reset(struct usb_device *udev,
extern int usb_reset_device(struct usb_device *dev); extern int usb_reset_device(struct usb_device *dev);
extern void usb_queue_reset_device(struct usb_interface *dev); extern void usb_queue_reset_device(struct usb_interface *dev);
extern struct device *usb_intf_get_dma_device(struct usb_interface *intf);
#ifdef CONFIG_ACPI #ifdef CONFIG_ACPI
extern int usb_acpi_set_power_state(struct usb_device *hdev, int index, extern int usb_acpi_set_power_state(struct usb_device *hdev, int index,
bool enable); bool enable);
......
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