[PATCH 2/2] drm: add an fb creation ioctl that takes a pixel format
Hello, all. I am trying to implement multi planer using your plane patch and I think it's good but I am still warried about that drm_mode_fb_cmd2 structure has only one handle. I know this handle is sent to framebuffer module to create new framebuffer. and the framebuffer would cover entire a image. as you know, the image could be consisted of one more planes. so I think now drm_mode_fb_cmd2 structure doesn't support multi planer because it has only one handle. with update_plane callback, a buffer of the framebuffer would be set to a hardware overlay. how we could set two planes or three planes to the hardware overlay? but there might be my missing point so please give me any comments. in addition, have you been looked into gem flink and open functions for memory sharing between processes? gem object basically has one buffer so we can't modify it because of compatibility. so I think it's right way that gem object manages only one buffer. for such a reason, maybe drm_mode_fb_cmd2 structure should include one more handles and plane count. each handle has a gem object to one plane and plane count means how many planes are requested and when update_plane callback is called by setplane(), we could set them of the specific framebuffer to a hardware overlay. another one, and also I have tried to implement the way sharing the memory between v4l2 based drivers and drm based drivers through application and this works fine. this feature had been introduced by v4l2 framework as user ptr. my way also is similar to it. the difference is that application could get new gem handle from specific gem framework of kernel side if user application requests user ptr import with the user space address(mmaped memory). the new gem handle means a gem object to the memory mapped to the user space address. this way makes different applications to be possible to share the memory between v4l2 based driver and drm based driver. and also this feature is considered for IOMMU so it would support non continuous memory also. I will introduce this feature soon. Thank you, Inki Dae. 2011/11/9 Jesse Barnes : > To properly support the various plane formats supported by different > hardware, the kernel must know the pixel format of a framebuffer object. > So add a new ioctl taking a format argument corresponding to a fourcc > name from videodev2.h. ?Implement the fb creation hooks in terms of the > new mode_fb_cmd2 using helpers where the old bpp/depth values are > needed. > > Acked-by: Alan Cox > Reviewed-by: Rob Clark > Signed-off-by: Jesse Barnes > --- > ?drivers/gpu/drm/drm_crtc.c ? ? ? ? ? ? ? ?| ?108 +++- > ?drivers/gpu/drm/drm_crtc_helper.c ? ? ? ? | ? 50 - > ?drivers/gpu/drm/drm_drv.c ? ? ? ? ? ? ? ? | ? ?1 + > ?drivers/gpu/drm/i915/intel_display.c ? ? ?| ? 36 +- > ?drivers/gpu/drm/i915/intel_drv.h ? ? ? ? ?| ? ?2 +- > ?drivers/gpu/drm/i915/intel_fb.c ? ? ? ? ? | ? 11 ++-- > ?drivers/gpu/drm/nouveau/nouveau_display.c | ? ?4 +- > ?drivers/gpu/drm/nouveau/nouveau_fb.h ? ? ?| ? ?2 +- > ?drivers/gpu/drm/nouveau/nouveau_fbcon.c ? | ? 13 ++-- > ?drivers/gpu/drm/radeon/radeon_display.c ? | ? ?4 +- > ?drivers/gpu/drm/radeon/radeon_fb.c ? ? ? ?| ? 18 +++-- > ?drivers/gpu/drm/radeon/radeon_mode.h ? ? ?| ? ?2 +- > ?drivers/gpu/drm/vmwgfx/vmwgfx_kms.c ? ? ? | ? 22 -- > ?drivers/gpu/drm/vmwgfx/vmwgfx_kms.h ? ? ? | ? ?1 + > ?drivers/staging/gma500/framebuffer.c ? ? ?| ? ?2 +- > ?include/drm/drm.h ? ? ? ? ? ? ? ? ? ? ? ? | ? ?1 + > ?include/drm/drm_crtc.h ? ? ? ? ? ? ? ? ? ?| ? ?7 ++- > ?include/drm/drm_crtc_helper.h ? ? ? ? ? ? | ? ?4 +- > ?include/drm/drm_mode.h ? ? ? ? ? ? ? ? ? ?| ? 28 +++- > ?include/linux/videodev2.h ? ? ? ? ? ? ? ? | ? ?1 + > ?20 files changed, 256 insertions(+), 61 deletions(-) > > diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c > index 804ef12..39cccb4 100644 > --- a/drivers/gpu/drm/drm_crtc.c > +++ b/drivers/gpu/drm/drm_crtc.c > @@ -1910,6 +1910,42 @@ out: > ? ? ? ?return ret; > ?} > > +/* Original addfb only supported RGB formats, so figure out which one */ > +uint32_t drm_mode_legacy_fb_format(uint32_t bpp, uint32_t depth) > +{ > + ? ? ? uint32_t fmt; > + > + ? ? ? switch (bpp) { > + ? ? ? case 8: > + ? ? ? ? ? ? ? fmt = V4L2_PIX_FMT_RGB332; > + ? ? ? ? ? ? ? break; > + ? ? ? case 16: > + ? ? ? ? ? ? ? if (depth == 15) > + ? ? ? ? ? ? ? ? ? ? ? fmt = V4L2_PIX_FMT_RGB555; > + ? ? ? ? ? ? ? else > + ? ? ? ? ? ? ? ? ? ? ? fmt = V4L2_PIX_FMT_RGB565; > + ? ? ? ? ? ? ? break; > + ? ? ? case 24: > + ? ? ? ? ? ? ? fmt = V4L2_PIX_FMT_RGB24; > + ? ? ? ? ? ? ? break; > + ? ? ? case 32: > + ? ? ? ? ? ? ? if (depth == 24) > + ? ? ? ? ? ? ? ? ? ? ? fmt = V4L2_PIX_FMT_RGB24; > + ? ? ? ? ? ? ? else if (depth == 30) > + ? ? ? ? ? ? ? ? ? ? ? fmt = V4L2_PIX_FMT_INTC_RGB30; > + ? ? ? ? ? ? ? else > + ? ? ? ? ? ? ? ? ? ? ? fmt = V4L2_PIX_FMT_RGB32; > + ? ? ? ? ? ? ? break; > + ? ? ? default: > + ? ? ? ? ? ? ? DRM_ERROR("bad bpp, assuming RGB24 pixel format\n"); > +
[PATCH] drm: serialize access to list of debugfs files
Nouveau, when configured with debugfs, creates debugfs files for every channel, so structure holding list of files needs to be protected from simultaneous changes by multiple threads. Without this patch it's possible to hit kernel oops in drm_debugfs_remove_files just by running a couple of xterms with looped glxinfo. Signed-off-by: Marcin Slusarz Reviewed-by: Daniel Vetter --- Updated changelog. --- drivers/gpu/drm/drm_debugfs.c | 12 +--- drivers/gpu/drm/i915/i915_debugfs.c |5 - include/drm/drmP.h |4 +++- 3 files changed, 16 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/drm_debugfs.c b/drivers/gpu/drm/drm_debugfs.c index d067c12..1c7a1c0 100644 --- a/drivers/gpu/drm/drm_debugfs.c +++ b/drivers/gpu/drm/drm_debugfs.c @@ -118,7 +118,10 @@ int drm_debugfs_create_files(struct drm_info_list *files, int count, tmp->minor = minor; tmp->dent = ent; tmp->info_ent = [i]; - list_add(&(tmp->list), &(minor->debugfs_nodes.list)); + + mutex_lock(>debugfs_lock); + list_add(>list, >debugfs_list); + mutex_unlock(>debugfs_lock); } return 0; @@ -146,7 +149,8 @@ int drm_debugfs_init(struct drm_minor *minor, int minor_id, char name[64]; int ret; - INIT_LIST_HEAD(>debugfs_nodes.list); + INIT_LIST_HEAD(>debugfs_list); + mutex_init(>debugfs_lock); sprintf(name, "%d", minor_id); minor->debugfs_root = debugfs_create_dir(name, root); if (!minor->debugfs_root) { @@ -192,8 +196,9 @@ int drm_debugfs_remove_files(struct drm_info_list *files, int count, struct drm_info_node *tmp; int i; + mutex_lock(>debugfs_lock); for (i = 0; i < count; i++) { - list_for_each_safe(pos, q, >debugfs_nodes.list) { + list_for_each_safe(pos, q, >debugfs_list) { tmp = list_entry(pos, struct drm_info_node, list); if (tmp->info_ent == [i]) { debugfs_remove(tmp->dent); @@ -202,6 +207,7 @@ int drm_debugfs_remove_files(struct drm_info_list *files, int count, } } } + mutex_unlock(>debugfs_lock); return 0; } EXPORT_SYMBOL(drm_debugfs_remove_files); diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index d14b44e..4f40f1c 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c @@ -1506,7 +1506,10 @@ drm_add_fake_info_node(struct drm_minor *minor, node->minor = minor; node->dent = ent; node->info_ent = (void *) key; - list_add(>list, >debugfs_nodes.list); + + mutex_lock(>debugfs_lock); + list_add(>list, >debugfs_list); + mutex_unlock(>debugfs_lock); return 0; } diff --git a/include/drm/drmP.h b/include/drm/drmP.h index cf39949..1f9e951 100644 --- a/include/drm/drmP.h +++ b/include/drm/drmP.h @@ -990,7 +990,9 @@ struct drm_minor { struct proc_dir_entry *proc_root; /**< proc directory entry */ struct drm_info_node proc_nodes; struct dentry *debugfs_root; - struct drm_info_node debugfs_nodes; + + struct list_head debugfs_list; + struct mutex debugfs_lock; /* Protects debugfs_list. */ struct drm_master *master; /* currently active master for this node */ struct list_head master_list; -- 1.7.7.2
ttm: merge ttm_backend & ttm_tt, introduce ttm dma allocator
On 11/09/2011 09:22 PM, j.glisse at gmail.com wrote: > So i did an overhaul of ttm_memory, i believe the simplification i did > make sense. See patch 5 for a longer explanation. > > > Thomas with the ttm_memory change the allocation of pages won't happen > if the accounting report that we are going over the limit and bo shrinker > failed to free any memory to make room. > > The handling of dma32 zone is done as post pass of ttm memory accounting. > OK. I'll take a deeper look into this. > Regarding the pagefault comment i removed, it doesn't make sense anymore > because now we populate the whole page table in one shot. So there is > no more prefaulting few pages but a full prefaulting. Thought i can > add a comment stating that if you like. > It's important that we distinguish between populating, which populates pages, and faulting, which add ptes pointing to those pages. Previously populating happened as a side effect of faulting, but now that populating is done in a single step, faulting (adding ptes) is still not. Usually a fault() handler adds a single pte, but TTM is different and tries to prefault more, but it is important that we only error on the first pte, so that's why the comment should stay. > For the ttm_tt_dma struct to hold page allocator specific informations > i think it can be done as an followup patch but if you prefer to have > that in this patchset let me know i will respin with such changes. > > I'm fine with having it as a separate patchset as long as it gets done :). > I am in the process of retesting this whole serie and especialy the > while memory accounting. > > Cheers, > Jerome > /Thomas
Linux 3.2-rc1
On Wed, Nov 09, 2011 at 03:40:19PM +0800, Takashi Iwai wrote: > At Tue, 8 Nov 2011 12:23:30 -0800, > Linus Torvalds wrote: > > > > Hmm, I don't know what caused this to trigger, but I'm adding both the > > i915 people and the HDA people to the cc, and they can fight to the > > death about this in the HDMI Thunderdome. > > It must be the new addition of ELD-passing code. Yes, it's my fault. > Fengguang, can the drm or i915 driver check whether ELD is changed or > not? Writing ELD at each time even when unchanged confuses the audio > side, as if the monitor is hotplugged. It's sure possible to mask out the extra events. I'll work out a patch tomorrow. > > Guys: One.. Two.. Three.. FIGHT! > > Round two! Three to fight! Thanks, Fengguang > > On Tue, Nov 8, 2011 at 6:55 AM, Nick Bowler > > wrote: > > > > > > Mode switches are very noisy on an Intel G45 in 3.2-rc1: > > > > > > ?HDMI hot plug event: Codec=3 Pin=3 Presence_Detect=1 ELD_Valid=1 > > > ?HDMI status: Codec=3 Pin=3 Presence_Detect=1 ELD_Valid=1 > > > ?HDMI: detected monitor W2253 at connection type HDMI > > > ?HDMI: available speakers: FL/FR > > > ?HDMI: supports coding type LPCM: channels = 2, rates = 32000 44100 > > > 48000, bits = 16 20 24 > > > > > > These lines get printed every single switch; previously only a single > > > line was printed once at boot (the "HDMI status" line). > > > > > > Cheers, > > > -- > > > Nick Bowler, Elliptic Technologies (http://www.elliptictech.com/) > > > > >
[PATCH 1/5] drm: add plane support
IVER_MODESET)) > + return -EINVAL; > + > + mutex_lock(>mode_config.mutex); > + > + /* > +* First, find the plane, crtc, and fb objects. If not available, > +* we don't bother to call the driver. > +*/ > + obj = drm_mode_object_find(dev, plane_req->plane_id, > + DRM_MODE_OBJECT_PLANE); > + if (!obj) { > + DRM_DEBUG_KMS("Unknown plane ID %d\n", > + plane_req->plane_id); > + ret = -ENOENT; > + goto out; > + } > + plane = obj_to_plane(obj); > + > + /* No fb means shut it down */ > + if (!plane_req->fb_id) { > + plane->funcs->disable_plane(plane); > + goto out; > + } > + > + obj = drm_mode_object_find(dev, plane_req->crtc_id, > + DRM_MODE_OBJECT_CRTC); > + if (!obj) { > + DRM_DEBUG_KMS("Unknown crtc ID %d\n", > + plane_req->crtc_id); > + ret = -ENOENT; > + goto out; > + } > + crtc = obj_to_crtc(obj); > + > + obj = drm_mode_object_find(dev, plane_req->fb_id, > + DRM_MODE_OBJECT_FB); > + if (!obj) { > + DRM_DEBUG_KMS("Unknown framebuffer ID %d\n", > + plane_req->fb_id); > + ret = -ENOENT; > + goto out; > + } > + fb = obj_to_fb(obj); > + > + ret = plane->funcs->update_plane(plane, crtc, fb, > +plane_req->crtc_x, plane_req->crtc_y, > +plane_req->crtc_w, plane_req->crtc_h, > +plane_req->src_x, plane_req->src_y, > +plane_req->src_w, plane_req->src_h); > + if (!ret) { > + plane->crtc = crtc; > + plane->fb = fb; > + } > + > +out: > + mutex_unlock(>mode_config.mutex); > + > + return ret; > +} > + > +/** > * drm_mode_setcrtc - set CRTC configuration > * @inode: inode from the ioctl > * @filp: file * from the ioctl > @@ -1688,11 +1939,13 @@ int drm_mode_addfb(struct drm_device *dev, >return -EINVAL; > >if ((config->min_width > r->width) || (r->width > config->max_width)) { > - DRM_ERROR("mode new framebuffer width not within limits\n"); > + DRM_ERROR("bad framebuffer width %d, should be >= %d && <= %d\n", > + r->width, config->min_width, config->max_width); >return -EINVAL; > index 8020798..e20867e 100644 > --- a/include/drm/drm_crtc.h > +++ b/include/drm/drm_crtc.h > @@ -44,6 +44,7 @@ struct drm_framebuffer; > #define DRM_MODE_OBJECT_PROPERTY 0xb0b0b0b0 > #define DRM_MODE_OBJECT_+extern int drm_pl -- - Joonyoung Shim -- next part -- An HTML attachment was scrubbed... URL: <http://lists.freedesktop.org/archives/dri-devel/attachments/2009/f1f1ea33/attachment-0001.htm>
[Bug 42678] Dual Screen Monitor Gnome-shell 3 hard lock ups - ATI open source Radeon
https://bugs.freedesktop.org/show_bug.cgi?id=42678 --- Comment #13 from Filip 2011-11-09 10:56:34 PST --- So, after I ran the following on my system: sudo sh /usr/share/ati/fglrx-uninstall.sh sudo apt-get remove --purge fglrx fglrx_* fglrx-amdcccle* fglrx-dev* sudo apt-get remove --purge xserver-xorg-video-ati xserver-xorg-video-radeon sudo apt-get install xserver-xorg-video-ati sudo apt-get install --reinstall libgl1-mesa-glx:amd64 libgl1-mesa-glx:i386 libgl1-mesa-dri xserver-xorg-core sudo mv /etc/X11/xorg.conf /etc/X11/xorg.conf.backup sudo rm -rf /etc/ati I still get the occasional hard freeze (the frequency was reduced to 2 - 4 times a day, which is a lot better than it was before). Is it possible that the old fglrx driver touched some other libraries which I need to install? if yes, which one would those be? As a next step, I will try the option per Xorg config -- Configure bugmail: https://bugs.freedesktop.org/userprefs.cgi?tab=email --- You are receiving this mail because: --- You are the assignee for the bug.
[PATCH 14/14] drm/ttm: isolate dma data from ttm_tt
From: Jerome GlisseMove dma data to a superset ttm_dma_tt structure which herit from ttm_tt. This allow driver that don't use dma functionalities to not have to waste memory for it. Signed-off-by: Jerome Glisse --- drivers/gpu/drm/nouveau/nouveau_bo.c | 18 + drivers/gpu/drm/nouveau/nouveau_sgdma.c | 22 +++ drivers/gpu/drm/radeon/radeon_ttm.c | 43 +++--- drivers/gpu/drm/ttm/ttm_page_alloc.c | 10 +++--- drivers/gpu/drm/ttm/ttm_page_alloc_dma.c | 38 +++- drivers/gpu/drm/ttm/ttm_tt.c | 58 - drivers/gpu/drm/vmwgfx/vmwgfx_buffer.c |2 + include/drm/ttm/ttm_bo_driver.h | 31 +++- include/drm/ttm/ttm_page_alloc.h | 12 ++ 9 files changed, 155 insertions(+), 79 deletions(-) diff --git a/drivers/gpu/drm/nouveau/nouveau_bo.c b/drivers/gpu/drm/nouveau/nouveau_bo.c index 36234a7..df3f19c 100644 --- a/drivers/gpu/drm/nouveau/nouveau_bo.c +++ b/drivers/gpu/drm/nouveau/nouveau_bo.c @@ -1052,6 +1052,7 @@ nouveau_bo_fence(struct nouveau_bo *nvbo, struct nouveau_fence *fence) static int nouveau_ttm_tt_populate(struct ttm_tt *ttm) { + struct ttm_dma_tt *ttm_dma = (void *)ttm; struct drm_nouveau_private *dev_priv; struct drm_device *dev; unsigned i; @@ -1065,7 +1066,7 @@ nouveau_ttm_tt_populate(struct ttm_tt *ttm) #ifdef CONFIG_SWIOTLB if ((dma_get_mask(dev->dev) <= DMA_BIT_MASK(32)) && swiotlb_nr_tbl()) { - return ttm_dma_populate(ttm, dev->dev); + return ttm_dma_populate((void *)ttm, dev->dev); } #endif @@ -1075,14 +1076,14 @@ nouveau_ttm_tt_populate(struct ttm_tt *ttm) } for (i = 0; i < ttm->num_pages; i++) { - ttm->dma_address[i] = pci_map_page(dev->pdev, ttm->pages[i], + ttm_dma->dma_address[i] = pci_map_page(dev->pdev, ttm->pages[i], 0, PAGE_SIZE, PCI_DMA_BIDIRECTIONAL); - if (pci_dma_mapping_error(dev->pdev, ttm->dma_address[i])) { + if (pci_dma_mapping_error(dev->pdev, ttm_dma->dma_address[i])) { while (--i) { - pci_unmap_page(dev->pdev, ttm->dma_address[i], + pci_unmap_page(dev->pdev, ttm_dma->dma_address[i], PAGE_SIZE, PCI_DMA_BIDIRECTIONAL); - ttm->dma_address[i] = 0; + ttm_dma->dma_address[i] = 0; } ttm_page_alloc_ttm_tt_unpopulate(ttm); return -EFAULT; @@ -1094,6 +1095,7 @@ nouveau_ttm_tt_populate(struct ttm_tt *ttm) static void nouveau_ttm_tt_unpopulate(struct ttm_tt *ttm) { + struct ttm_dma_tt *ttm_dma = (void *)ttm; struct drm_nouveau_private *dev_priv; struct drm_device *dev; unsigned i; @@ -1103,14 +1105,14 @@ nouveau_ttm_tt_unpopulate(struct ttm_tt *ttm) #ifdef CONFIG_SWIOTLB if ((dma_get_mask(dev->dev) <= DMA_BIT_MASK(32)) && swiotlb_nr_tbl()) { - ttm_dma_unpopulate(ttm, dev->dev); + ttm_dma_unpopulate((void *)ttm, dev->dev); return; } #endif for (i = 0; i < ttm->num_pages; i++) { - if (ttm->dma_address[i]) { - pci_unmap_page(dev->pdev, ttm->dma_address[i], + if (ttm_dma->dma_address[i]) { + pci_unmap_page(dev->pdev, ttm_dma->dma_address[i], PAGE_SIZE, PCI_DMA_BIDIRECTIONAL); } } diff --git a/drivers/gpu/drm/nouveau/nouveau_sgdma.c b/drivers/gpu/drm/nouveau/nouveau_sgdma.c index ee1eb7c..47f245e 100644 --- a/drivers/gpu/drm/nouveau/nouveau_sgdma.c +++ b/drivers/gpu/drm/nouveau/nouveau_sgdma.c @@ -8,7 +8,10 @@ #define NV_CTXDMA_PAGE_MASK (NV_CTXDMA_PAGE_SIZE - 1) struct nouveau_sgdma_be { - struct ttm_tt ttm; + /* this has to be the first field so populate/unpopulated in +* nouve_bo.c works properly, otherwise have to move them here +*/ + struct ttm_dma_tt ttm; struct drm_device *dev; u64 offset; }; @@ -20,6 +23,7 @@ nouveau_sgdma_destroy(struct ttm_tt *ttm) if (ttm) { NV_DEBUG(nvbe->dev, "\n"); + ttm_dma_tt_fini(>ttm); kfree(nvbe); } } @@ -38,7 +42,7 @@ nv04_sgdma_bind(struct ttm_tt *ttm, struct ttm_mem_reg *mem) nvbe->offset = mem->start << PAGE_SHIFT; pte = (nvbe->offset >> NV_CTXDMA_PAGE_SHIFT) + 2; for (i = 0; i < ttm->num_pages; i++) { - dma_addr_t dma_offset = ttm->dma_address[i]; + dma_addr_t dma_offset = nvbe->ttm.dma_address[i]; uint32_t offset_l = lower_32_bits(dma_offset);
Isolate dma information from ttm_tt
This apply on top of the ttm_tt & backend merge patchset. Cheers, Jerome
r600 hdmi sound issue
2011/11/9 Rafa? Mi?ecki : > 2011/11/9 Greg Dietsche : >> Hi, >> I have a ASUS M4A89GTD motherboard and when I play back music in Rhythmbox, >> there is no sound (hdmi connection). Also, the playback speed is in a sort >> of fast forward (for example, after a few seconds of real time, rhythmbox >> shows something like 30 seconds into the song). This seems to be a kernel >> regression. I know that it started with 3.0, is present in 3.1, and is not >> working in 3.2-rc1, so it is still a problem. >> >> I bisected and found my self here: fe6f0bd03d697835e76dd18d232ba476c65b8282. >> However due to some graphical issues, I'm not actually able to test that >> commit. I tried reverting that commit, but the problem wasn't fixed. >> >> I'd like to see this problem fixed and can compile and test patches as >> necessary. Please let me know if you need more information - I'm happy to >> provide it :) > > fe6f0bd03d697835e76dd18d232ba476c65b8282 is not likely. I suspect you > just experience results of so-called-fix: > > 805c22168da76a65c978017d0fe0d59cd048e995 > > drm/radeon/kms: disable hdmi audio by default > > I'm trying to get in contact with ppl affected by issues when enabling > audio. Hopefully we can fix audio support and enable it by default > again. > > For now, please load radeon module with "audio=1", or simply boot with > radeon.audio=1 > > -- > Rafa? > Thanks Rafa? that fixed it for me. (Wish I'd noticed that commit earler). Anyway, if you need any testers at some point for this driver, just let me know. I'd be happy to try them out. Greg
[Bug 28426] hardware cursor corruption with radeon+kms
https://bugs.freedesktop.org/show_bug.cgi?id=28426 --- Comment #11 from J?rg Billeter 2011-11-09 08:51:09 PST --- My Linux 3.1 system has been running for over 6 days now without issues. Seems like it may finally be fixed for good :) Thanks! -- Configure bugmail: https://bugs.freedesktop.org/userprefs.cgi?tab=email --- You are receiving this mail because: --- You are the assignee for the bug.
ttm: merge ttm_backend & ttm_tt, introduce ttm dma allocator
On Wed, Nov 09, 2011 at 09:25:20PM +0100, Thomas Hellstrom wrote: > On 11/09/2011 09:22 PM, j.glisse at gmail.com wrote: > >So i did an overhaul of ttm_memory, i believe the simplification i did > >make sense. See patch 5 for a longer explanation. > > > >Thomas with the ttm_memory change the allocation of pages won't happen > >if the accounting report that we are going over the limit and bo shrinker > >failed to free any memory to make room. > > > >The handling of dma32 zone is done as post pass of ttm memory accounting. > > OK. I'll take a deeper look into this. > > >Regarding the pagefault comment i removed, it doesn't make sense anymore > >because now we populate the whole page table in one shot. So there is > >no more prefaulting few pages but a full prefaulting. Thought i can > >add a comment stating that if you like. > It's important that we distinguish between populating, which > populates pages, > and faulting, which add ptes pointing to those pages. > > Previously populating happened as a side effect of faulting, but now > that populating is done > in a single step, faulting (adding ptes) is still not. Usually a > fault() handler adds a single pte, > but TTM is different and tries to prefault more, but it is important > that we only error on the first > pte, so that's why the comment should stay. > Well yes it only fill numprefault pte, but no error can happen in the prefault loop except for vm_insert_mixed failure, it's why i kept the report error only if it fails on the first page. I actually did a full pte populate at one point while working on that, dunno if that would make sense. > >For the ttm_tt_dma struct to hold page allocator specific informations > >i think it can be done as an followup patch but if you prefer to have > >that in this patchset let me know i will respin with such changes. > > > > I'm fine with having it as a separate patchset as long as it gets done :). > I will spin a patch for that on top of the patchset. Cheers, Jerome
[PATCH 01/12] drm/ttm: remove userspace backed ttm object support
On Tue, Nov 08, 2011 at 08:22:48AM +0100, Thomas Hellstrom wrote: > On 11/08/2011 12:40 AM, j.glisse at gmail.com wrote: > >From: Jerome Glisse > > > >This was never use in none of the driver, properly using userspace > >page for bo would need more code (vma interaction mostly). Removing > >this dead code in preparation of ttm_tt& backend merge. > > > > Jerome, > I actually have using user-space TTMs in the pipe for vmwgfx, and it > doesn't need more code > (it was used by the psb driver). There are extra requirements, > though: It only supports cached memory and user-space CPU-access > needs to be done using existing VMAs. > > Anyway, I'll try to figure out a way to do this in the context of > the unified tt / tt_backends. > Issue, and i might be wrong here, is that you need to mark the user vma as reserved and you need to split the vma to covert only the portion you want. linux kernel a no helper for that. omap people use mlock on the range they want to use to make sure that page associated to the vma are lock and that the vma is split to only cover the range. I don't think it's safe/enough as userspace can unlock the vma in our back and things might fall apart at that point. My idea was to use mlock to split the vma and then set the reserved flags on the vma. This will forbid userspace to munlock. When memory is no longer needed you have to go back to locked flag and then munlock. Also we might want to do things with page of the vma, for instance if the object move to vram we might want to free those pages, but here i fear i need to take a closer look at linux mm to see what we can do safely on those page to not break any of the kernel assumptions on those pages. Anyway, from my inspection this whole things is fragile in regards of other mm activities that might happen. Cheers, Jerome
[PATCH v2] radeon: Make sure CS mutex is held across GPU reset.
On Tue, Nov 08, 2011 at 06:50:19PM +0100, Michel D?nzer wrote: > From: Michel D?nzer > > This was only the case if the GPU reset was triggered from the CS ioctl, > otherwise other processes could happily enter the CS ioctl and wreak havoc > during the GPU reset. > > This is a little complicated because the GPU reset can be triggered from the > CS ioctl, in which case we're already holding the mutex, or from other call > paths, in which case we need to lock the mutex. AFAICT the mutex API doesn't > allow recursive locking or finding out the mutex owner, so we need to handle > this with helper functions which allow recursive locking from the same > process. > > Signed-off-by: Michel D?nzer Beside not so important comment below Reviewed-by: Jerome Glisse > --- > > v2: Use generic radeon_mutex_(un)lock helpers which allow recursive locking > from the same process. Eliminates int vs. bool return type issue in v1, and > maybe these helpers can be used similarly for more locks in the future. > > drivers/gpu/drm/radeon/radeon.h| 45 > +++- > drivers/gpu/drm/radeon/radeon_cs.c | 14 +- > drivers/gpu/drm/radeon/radeon_device.c | 16 --- > 3 files changed, 63 insertions(+), 12 deletions(-) > > diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h > index c1e056b..671d5a5 100644 > --- a/drivers/gpu/drm/radeon/radeon.h > +++ b/drivers/gpu/drm/radeon/radeon.h > @@ -1151,6 +1151,48 @@ struct r700_vram_scratch { > volatile uint32_t *ptr; > }; > > + > +/* > + * Mutex which allows recursive locking from the same process. > + */ > +struct radeon_mutex { > + struct mutexmutex; > + struct task_struct *owner; > + int level; > +}; > + > +static inline void radeon_mutex_init(struct radeon_mutex *mutex) > +{ > + mutex_init(>mutex); > + mutex->owner = NULL; > + mutex->level = 0; > +} > + > +static inline void radeon_mutex_lock(struct radeon_mutex *mutex) > +{ > + if (mutex_trylock(>mutex)) { > + /* The mutex was unlocked before, so it's ours now */ > + mutex->owner = current; > + } else if (mutex->owner != current) { > + /* Another process locked the mutex, take it */ > + mutex_lock(>mutex); > + mutex->owner = current; > + } > + /* Otherwise the mutex was already locked by this process */ > + > + mutex->level++; > +} > + > +static inline void radeon_mutex_unlock(struct radeon_mutex *mutex) > +{ > + if (--mutex->level > 0) > + return; > + > + mutex->owner = NULL; > + mutex_unlock(>mutex); > +} > + > + > /* > * Core structure, functions and helpers. > */ > @@ -1206,7 +1248,7 @@ struct radeon_device { > struct radeon_gem gem; > struct radeon_pmpm; > uint32_tbios_scratch[RADEON_BIOS_NUM_SCRATCH]; > - struct mutexcs_mutex; > + struct radeon_mutex cs_mutex; > struct radeon_wbwb; > struct radeon_dummy_pagedummy_page; > boolgpu_lockup; > @@ -1245,6 +1287,7 @@ struct radeon_device { > struct radeon_i2c_chan *i2c_bus[RADEON_MAX_I2C_BUS]; > }; > > + Adding empty line ? > int radeon_device_init(struct radeon_device *rdev, > struct drm_device *ddev, > struct pci_dev *pdev, > diff --git a/drivers/gpu/drm/radeon/radeon_cs.c > b/drivers/gpu/drm/radeon/radeon_cs.c > index fae00c0..ccaa243 100644 > --- a/drivers/gpu/drm/radeon/radeon_cs.c > +++ b/drivers/gpu/drm/radeon/radeon_cs.c > @@ -222,7 +222,7 @@ int radeon_cs_ioctl(struct drm_device *dev, void *data, > struct drm_file *filp) > struct radeon_cs_chunk *ib_chunk; > int r; > > - mutex_lock(>cs_mutex); > + radeon_mutex_lock(>cs_mutex); > /* initialize parser */ > memset(, 0, sizeof(struct radeon_cs_parser)); > parser.filp = filp; > @@ -233,14 +233,14 @@ int radeon_cs_ioctl(struct drm_device *dev, void *data, > struct drm_file *filp) > if (r) { > DRM_ERROR("Failed to initialize parser !\n"); > radeon_cs_parser_fini(, r); > - mutex_unlock(>cs_mutex); > + radeon_mutex_unlock(>cs_mutex); > return r; > } > r = radeon_ib_get(rdev, ); > if (r) { > DRM_ERROR("Failed to get ib !\n"); > radeon_cs_parser_fini(, r); > - mutex_unlock(>cs_mutex); > + radeon_mutex_unlock(>cs_mutex); > return r; > } > r = radeon_cs_parser_relocs(); > @@ -248,7 +248,7 @@ int radeon_cs_ioctl(struct drm_device *dev, void *data, > struct drm_file *filp) > if (r != -ERESTARTSYS) > DRM_ERROR("Failed to parse relocation %d!\n", r); > radeon_cs_parser_fini(, r);
[PATCH 13/13] drm/nouveau: enable the TTM DMA pool on 32-bit DMA only device V2
From: Konrad Rzeszutek WilkIf the card is capable of more than 32-bit, then use the default TTM page pool code which allocates from anywhere in the memory. Note: If the 'ttm.no_dma' parameter is set, the override is ignored and the default TTM pool is used. V2 use pci_set_consistent_dma_mask CC: Ben Skeggs CC: Francisco Jerez CC: Dave Airlie Signed-off-by: Konrad Rzeszutek Wilk Reviewed-by: Jerome Glisse --- drivers/gpu/drm/nouveau/nouveau_bo.c | 73 - drivers/gpu/drm/nouveau/nouveau_debugfs.c |1 + drivers/gpu/drm/nouveau/nouveau_mem.c |6 ++ drivers/gpu/drm/nouveau/nouveau_sgdma.c | 60 +--- 4 files changed, 79 insertions(+), 61 deletions(-) diff --git a/drivers/gpu/drm/nouveau/nouveau_bo.c b/drivers/gpu/drm/nouveau/nouveau_bo.c index 7e5ca3f..36234a7 100644 --- a/drivers/gpu/drm/nouveau/nouveau_bo.c +++ b/drivers/gpu/drm/nouveau/nouveau_bo.c @@ -1049,10 +1049,79 @@ nouveau_bo_fence(struct nouveau_bo *nvbo, struct nouveau_fence *fence) nouveau_fence_unref(_fence); } +static int +nouveau_ttm_tt_populate(struct ttm_tt *ttm) +{ + struct drm_nouveau_private *dev_priv; + struct drm_device *dev; + unsigned i; + int r; + + if (ttm->state != tt_unpopulated) + return 0; + + dev_priv = nouveau_bdev(ttm->bdev); + dev = dev_priv->dev; + +#ifdef CONFIG_SWIOTLB + if ((dma_get_mask(dev->dev) <= DMA_BIT_MASK(32)) && swiotlb_nr_tbl()) { + return ttm_dma_populate(ttm, dev->dev); + } +#endif + + r = ttm_page_alloc_ttm_tt_populate(ttm); + if (r) { + return r; + } + + for (i = 0; i < ttm->num_pages; i++) { + ttm->dma_address[i] = pci_map_page(dev->pdev, ttm->pages[i], + 0, PAGE_SIZE, + PCI_DMA_BIDIRECTIONAL); + if (pci_dma_mapping_error(dev->pdev, ttm->dma_address[i])) { + while (--i) { + pci_unmap_page(dev->pdev, ttm->dma_address[i], + PAGE_SIZE, PCI_DMA_BIDIRECTIONAL); + ttm->dma_address[i] = 0; + } + ttm_page_alloc_ttm_tt_unpopulate(ttm); + return -EFAULT; + } + } + return 0; +} + +static void +nouveau_ttm_tt_unpopulate(struct ttm_tt *ttm) +{ + struct drm_nouveau_private *dev_priv; + struct drm_device *dev; + unsigned i; + + dev_priv = nouveau_bdev(ttm->bdev); + dev = dev_priv->dev; + +#ifdef CONFIG_SWIOTLB + if ((dma_get_mask(dev->dev) <= DMA_BIT_MASK(32)) && swiotlb_nr_tbl()) { + ttm_dma_unpopulate(ttm, dev->dev); + return; + } +#endif + + for (i = 0; i < ttm->num_pages; i++) { + if (ttm->dma_address[i]) { + pci_unmap_page(dev->pdev, ttm->dma_address[i], + PAGE_SIZE, PCI_DMA_BIDIRECTIONAL); + } + } + + ttm_page_alloc_ttm_tt_unpopulate(ttm); +} + struct ttm_bo_driver nouveau_bo_driver = { .ttm_tt_create = _ttm_tt_create, - .ttm_tt_populate = _page_alloc_ttm_tt_populate, - .ttm_tt_unpopulate = _page_alloc_ttm_tt_unpopulate, + .ttm_tt_populate = _ttm_tt_populate, + .ttm_tt_unpopulate = _ttm_tt_unpopulate, .invalidate_caches = nouveau_bo_invalidate_caches, .init_mem_type = nouveau_bo_init_mem_type, .evict_flags = nouveau_bo_evict_flags, diff --git a/drivers/gpu/drm/nouveau/nouveau_debugfs.c b/drivers/gpu/drm/nouveau/nouveau_debugfs.c index 8e15923..f52c2db 100644 --- a/drivers/gpu/drm/nouveau/nouveau_debugfs.c +++ b/drivers/gpu/drm/nouveau/nouveau_debugfs.c @@ -178,6 +178,7 @@ static struct drm_info_list nouveau_debugfs_list[] = { { "memory", nouveau_debugfs_memory_info, 0, NULL }, { "vbios.rom", nouveau_debugfs_vbios_image, 0, NULL }, { "ttm_page_pool", ttm_page_alloc_debugfs, 0, NULL }, + { "ttm_dma_page_pool", ttm_dma_page_alloc_debugfs, 0, NULL }, }; #define NOUVEAU_DEBUGFS_ENTRIES ARRAY_SIZE(nouveau_debugfs_list) diff --git a/drivers/gpu/drm/nouveau/nouveau_mem.c b/drivers/gpu/drm/nouveau/nouveau_mem.c index 36bec48..37fcaa2 100644 --- a/drivers/gpu/drm/nouveau/nouveau_mem.c +++ b/drivers/gpu/drm/nouveau/nouveau_mem.c @@ -407,6 +407,12 @@ nouveau_mem_vram_init(struct drm_device *dev) ret = pci_set_dma_mask(dev->pdev, DMA_BIT_MASK(dma_bits)); if (ret) return ret; + ret = pci_set_consistent_dma_mask(dev->pdev, DMA_BIT_MASK(dma_bits)); + if (ret) { + /* Reset to default value. */ + pci_set_consistent_dma_mask(dev->pdev, DMA_BIT_MASK(32)); + } + ret = nouveau_ttm_global_init(dev_priv); if
[PATCH 12/13] drm/radeon/kms: Enable the TTM DMA pool if swiotlb is on V2
From: Konrad Rzeszutek WilkWith the exception that we do not handle the AGP case. We only deal with PCIe cards such as ATI ES1000 or HD3200 that have been detected to only do DMA up to 32-bits. V2 force dma32 if we fail to set bigger dma mask CC: Dave Airlie CC: Alex Deucher Signed-off-by: Konrad Rzeszutek Wilk Reviewed-by: Jerome Glisse --- drivers/gpu/drm/radeon/radeon.h|1 - drivers/gpu/drm/radeon/radeon_device.c |6 ++ drivers/gpu/drm/radeon/radeon_gart.c | 29 +--- drivers/gpu/drm/radeon/radeon_ttm.c| 83 +-- 4 files changed, 84 insertions(+), 35 deletions(-) diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h index e3170c7..63257ba 100644 --- a/drivers/gpu/drm/radeon/radeon.h +++ b/drivers/gpu/drm/radeon/radeon.h @@ -332,7 +332,6 @@ struct radeon_gart { union radeon_gart_table table; struct page **pages; dma_addr_t *pages_addr; - bool*ttm_alloced; boolready; }; diff --git a/drivers/gpu/drm/radeon/radeon_device.c b/drivers/gpu/drm/radeon/radeon_device.c index c33bc91..7c31321 100644 --- a/drivers/gpu/drm/radeon/radeon_device.c +++ b/drivers/gpu/drm/radeon/radeon_device.c @@ -765,8 +765,14 @@ int radeon_device_init(struct radeon_device *rdev, r = pci_set_dma_mask(rdev->pdev, DMA_BIT_MASK(dma_bits)); if (r) { rdev->need_dma32 = true; + dma_bits = 32; printk(KERN_WARNING "radeon: No suitable DMA available.\n"); } + r = pci_set_consistent_dma_mask(rdev->pdev, DMA_BIT_MASK(dma_bits)); + if (r) { + pci_set_consistent_dma_mask(rdev->pdev, DMA_BIT_MASK(32)); + printk(KERN_WARNING "radeon: No coherent DMA available.\n"); + } /* Registers mapping */ /* TODO: block userspace mapping of io register */ diff --git a/drivers/gpu/drm/radeon/radeon_gart.c b/drivers/gpu/drm/radeon/radeon_gart.c index fdc3a9a..18f496c 100644 --- a/drivers/gpu/drm/radeon/radeon_gart.c +++ b/drivers/gpu/drm/radeon/radeon_gart.c @@ -149,9 +149,6 @@ void radeon_gart_unbind(struct radeon_device *rdev, unsigned offset, p = t / (PAGE_SIZE / RADEON_GPU_PAGE_SIZE); for (i = 0; i < pages; i++, p++) { if (rdev->gart.pages[p]) { - if (!rdev->gart.ttm_alloced[p]) - pci_unmap_page(rdev->pdev, rdev->gart.pages_addr[p], - PAGE_SIZE, PCI_DMA_BIDIRECTIONAL); rdev->gart.pages[p] = NULL; rdev->gart.pages_addr[p] = rdev->dummy_page.addr; page_base = rdev->gart.pages_addr[p]; @@ -181,23 +178,7 @@ int radeon_gart_bind(struct radeon_device *rdev, unsigned offset, p = t / (PAGE_SIZE / RADEON_GPU_PAGE_SIZE); for (i = 0; i < pages; i++, p++) { - /* we reverted the patch using dma_addr in TTM for now but this -* code stops building on alpha so just comment it out for now */ - if (0) { /*dma_addr[i] != DMA_ERROR_CODE) */ - rdev->gart.ttm_alloced[p] = true; - rdev->gart.pages_addr[p] = dma_addr[i]; - } else { - /* we need to support large memory configurations */ - /* assume that unbind have already been call on the range */ - rdev->gart.pages_addr[p] = pci_map_page(rdev->pdev, pagelist[i], - 0, PAGE_SIZE, - PCI_DMA_BIDIRECTIONAL); - if (pci_dma_mapping_error(rdev->pdev, rdev->gart.pages_addr[p])) { - /* FIXME: failed to map page (return -ENOMEM?) */ - radeon_gart_unbind(rdev, offset, pages); - return -ENOMEM; - } - } + rdev->gart.pages_addr[p] = dma_addr[i]; rdev->gart.pages[p] = pagelist[i]; page_base = rdev->gart.pages_addr[p]; for (j = 0; j < (PAGE_SIZE / RADEON_GPU_PAGE_SIZE); j++, t++) { @@ -259,12 +240,6 @@ int radeon_gart_init(struct radeon_device *rdev) radeon_gart_fini(rdev); return -ENOMEM; } - rdev->gart.ttm_alloced = kzalloc(sizeof(bool) * -rdev->gart.num_cpu_pages, GFP_KERNEL); - if (rdev->gart.ttm_alloced == NULL) { - radeon_gart_fini(rdev); - return -ENOMEM; - } /* set GART entry to point to the dummy page by default */ for (i = 0; i < rdev->gart.num_cpu_pages; i++) { rdev->gart.pages_addr[i] =
[PATCH 11/13] swiotlb: Expose swiotlb_nr_tlb function to modules
From: Konrad Rzeszutek WilkAs a mechanism to detect whether SWIOTLB is enabled or not. We also fix the spelling - it was swioltb instead of swiotlb. CC: FUJITA Tomonori [v1: Ripped out swiotlb_enabled] Signed-off-by: Konrad Rzeszutek Wilk --- drivers/xen/swiotlb-xen.c |2 +- include/linux/swiotlb.h |2 +- lib/swiotlb.c |5 +++-- 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/drivers/xen/swiotlb-xen.c b/drivers/xen/swiotlb-xen.c index c984768..c50fb0b 100644 --- a/drivers/xen/swiotlb-xen.c +++ b/drivers/xen/swiotlb-xen.c @@ -152,7 +152,7 @@ void __init xen_swiotlb_init(int verbose) char *m = NULL; unsigned int repeat = 3; - nr_tbl = swioltb_nr_tbl(); + nr_tbl = swiotlb_nr_tbl(); if (nr_tbl) xen_io_tlb_nslabs = nr_tbl; else { diff --git a/include/linux/swiotlb.h b/include/linux/swiotlb.h index 445702c..e872526 100644 --- a/include/linux/swiotlb.h +++ b/include/linux/swiotlb.h @@ -24,7 +24,7 @@ extern int swiotlb_force; extern void swiotlb_init(int verbose); extern void swiotlb_init_with_tbl(char *tlb, unsigned long nslabs, int verbose); -extern unsigned long swioltb_nr_tbl(void); +extern unsigned long swiotlb_nr_tbl(void); /* * Enumeration for sync targets diff --git a/lib/swiotlb.c b/lib/swiotlb.c index 99093b3..058935e 100644 --- a/lib/swiotlb.c +++ b/lib/swiotlb.c @@ -110,11 +110,11 @@ setup_io_tlb_npages(char *str) __setup("swiotlb=", setup_io_tlb_npages); /* make io_tlb_overflow tunable too? */ -unsigned long swioltb_nr_tbl(void) +unsigned long swiotlb_nr_tbl(void) { return io_tlb_nslabs; } - +EXPORT_SYMBOL_GPL(swiotlb_nr_tbl); /* Note that this doesn't work with highmem page */ static dma_addr_t swiotlb_virt_to_bus(struct device *hwdev, volatile void *address) @@ -321,6 +321,7 @@ void __init swiotlb_free(void) free_bootmem_late(__pa(io_tlb_start), PAGE_ALIGN(io_tlb_nslabs << IO_TLB_SHIFT)); } + io_tlb_nslabs = 0; } static int is_swiotlb_buffer(phys_addr_t paddr) -- 1.7.7.1
[PATCH 10/13] ttm: Provide DMA aware TTM page pool code. V5
From: Konrad Rzeszutek WilkIn TTM world the pages for the graphic drivers are kept in three different pools: write combined, uncached, and cached (write-back). When the pages are used by the graphic driver the graphic adapter via its built in MMU (or AGP) programs these pages in. The programming requires the virtual address (from the graphic adapter perspective) and the physical address (either System RAM or the memory on the card) which is obtained using the pci_map_* calls (which does the virtual to physical - or bus address translation). During the graphic application's "life" those pages can be shuffled around, swapped out to disk, moved from the VRAM to System RAM or vice-versa. This all works with the existing TTM pool code - except when we want to use the software IOTLB (SWIOTLB) code to "map" the physical addresses to the graphic adapter MMU. We end up programming the bounce buffer's physical address instead of the TTM pool memory's and get a non-worky driver. There are two solutions: 1) using the DMA API to allocate pages that are screened by the DMA API, or 2) using the pci_sync_* calls to copy the pages from the bounce-buffer and back. This patch fixes the issue by allocating pages using the DMA API. The second is a viable option - but it has performance drawbacks and potential correctness issues - think of the write cache page being bounced (SWIOTLB->TTM), the WC is set on the TTM page and the copy from SWIOTLB not making it to the TTM page until the page has been recycled in the pool (and used by another application). The bounce buffer does not get activated often - only in cases where we have a 32-bit capable card and we want to use a page that is allocated above the 4GB limit. The bounce buffer offers the solution of copying the contents of that 4GB page to an location below 4GB and then back when the operation has been completed (or vice-versa). This is done by using the 'pci_sync_*' calls. Note: If you look carefully enough in the existing TTM page pool code you will notice the GFP_DMA32 flag is used - which should guarantee that the provided page is under 4GB. It certainly is the case, except this gets ignored in two cases: - If user specifies 'swiotlb=force' which bounces _every_ page. - If user is using a Xen's PV Linux guest (which uses the SWIOTLB and the underlaying PFN's aren't necessarily under 4GB). To not have this extra copying done the other option is to allocate the pages using the DMA API so that there is not need to map the page and perform the expensive 'pci_sync_*' calls. This DMA API capable TTM pool requires for this the 'struct device' to properly call the DMA API. It also has to track the virtual and bus address of the page being handed out in case it ends up being swapped out or de-allocated - to make sure it is de-allocated using the proper's 'struct device'. Implementation wise the code keeps two lists: one that is attached to the 'struct device' (via the dev->dma_pools list) and a global one to be used when the 'struct device' is unavailable (think shrinker code). The global list can iterate over all of the 'struct device' and its associated dma_pool. The list in dev->dma_pools can only iterate the device's dma_pool. /[struct device_pool]\ /---| dev | /+---| dma_pool | /-+--\/ \/ |struct device| /-->[struct dma_pool for WC][struct dma_pool for uncached]<-/--| dma_pool | \-+--/ / \/ \--/ [Two pools associated with the device (WC and UC), and the parallel list containing the 'struct dev' and 'struct dma_pool' entries] The maximum amount of dma pools a device can have is six: write-combined, uncached, and cached; then there are the DMA32 variants which are: write-combined dma32, uncached dma32, and cached dma32. Currently this code only gets activated when any variant of the SWIOTLB IOMMU code is running (Intel without VT-d, AMD without GART, IBM Calgary and Xen PV with PCI devices). Tested-by: Michel D?nzer [v1: Using swiotlb_nr_tbl instead of swiotlb_enabled] [v2: Major overhaul - added 'inuse_list' to seperate used from inuse and reorder the order of lists to get better performance.] [v3: Added comments/and some logic based on review, Added Jerome tag] [v4: rebase on top of ttm_tt & ttm_backend merge] [v5: rebase on top of ttm memory accounting overhaul] Reviewed-by: Jerome Glisse Signed-off-by: Konrad Rzeszutek Wilk --- drivers/gpu/drm/ttm/Makefile |4 + drivers/gpu/drm/ttm/ttm_memory.c |2 + drivers/gpu/drm/ttm/ttm_page_alloc_dma.c | 1235 ++
[PATCH 09/13] drm/ttm: introduce callback for ttm_tt populate & unpopulate V2
From: Jerome GlisseMove the page allocation and freeing to driver callback and provide ttm code helper function for those. Most intrusive change, is the fact that we now only fully populate an object this simplify some of code designed around the page fault design. V2 Rebase on top of memory accounting overhaul Signed-off-by: Jerome Glisse Reviewed-by: Konrad Rzeszutek Wilk --- drivers/gpu/drm/nouveau/nouveau_bo.c |3 + drivers/gpu/drm/radeon/radeon_ttm.c|2 + drivers/gpu/drm/ttm/ttm_bo_util.c | 31 ++- drivers/gpu/drm/ttm/ttm_bo_vm.c| 13 +++-- drivers/gpu/drm/ttm/ttm_page_alloc.c | 45 + drivers/gpu/drm/ttm/ttm_tt.c | 86 ++-- drivers/gpu/drm/vmwgfx/vmwgfx_buffer.c |3 + include/drm/ttm/ttm_bo_driver.h| 41 +--- include/drm/ttm/ttm_page_alloc.h | 18 +++ 9 files changed, 123 insertions(+), 119 deletions(-) diff --git a/drivers/gpu/drm/nouveau/nouveau_bo.c b/drivers/gpu/drm/nouveau/nouveau_bo.c index b060fa4..7e5ca3f 100644 --- a/drivers/gpu/drm/nouveau/nouveau_bo.c +++ b/drivers/gpu/drm/nouveau/nouveau_bo.c @@ -28,6 +28,7 @@ */ #include "drmP.h" +#include "ttm/ttm_page_alloc.h" #include "nouveau_drm.h" #include "nouveau_drv.h" @@ -1050,6 +1051,8 @@ nouveau_bo_fence(struct nouveau_bo *nvbo, struct nouveau_fence *fence) struct ttm_bo_driver nouveau_bo_driver = { .ttm_tt_create = _ttm_tt_create, + .ttm_tt_populate = _page_alloc_ttm_tt_populate, + .ttm_tt_unpopulate = _page_alloc_ttm_tt_unpopulate, .invalidate_caches = nouveau_bo_invalidate_caches, .init_mem_type = nouveau_bo_init_mem_type, .evict_flags = nouveau_bo_evict_flags, diff --git a/drivers/gpu/drm/radeon/radeon_ttm.c b/drivers/gpu/drm/radeon/radeon_ttm.c index 53ff62b..490afce 100644 --- a/drivers/gpu/drm/radeon/radeon_ttm.c +++ b/drivers/gpu/drm/radeon/radeon_ttm.c @@ -584,6 +584,8 @@ struct ttm_tt *radeon_ttm_tt_create(struct ttm_bo_device *bdev, static struct ttm_bo_driver radeon_bo_driver = { .ttm_tt_create = _ttm_tt_create, + .ttm_tt_populate = _page_alloc_ttm_tt_populate, + .ttm_tt_unpopulate = _page_alloc_ttm_tt_unpopulate, .invalidate_caches = _invalidate_caches, .init_mem_type = _init_mem_type, .evict_flags = _evict_flags, diff --git a/drivers/gpu/drm/ttm/ttm_bo_util.c b/drivers/gpu/drm/ttm/ttm_bo_util.c index 082fcae..60f204d 100644 --- a/drivers/gpu/drm/ttm/ttm_bo_util.c +++ b/drivers/gpu/drm/ttm/ttm_bo_util.c @@ -244,7 +244,7 @@ static int ttm_copy_io_ttm_page(struct ttm_tt *ttm, void *src, unsigned long page, pgprot_t prot) { - struct page *d = ttm_tt_get_page(ttm, page); + struct page *d = ttm->pages[page]; void *dst; if (!d) @@ -281,7 +281,7 @@ static int ttm_copy_ttm_io_page(struct ttm_tt *ttm, void *dst, unsigned long page, pgprot_t prot) { - struct page *s = ttm_tt_get_page(ttm, page); + struct page *s = ttm->pages[page]; void *src; if (!s) @@ -342,6 +342,12 @@ int ttm_bo_move_memcpy(struct ttm_buffer_object *bo, if (old_iomap == NULL && ttm == NULL) goto out2; + if (ttm->state == tt_unpopulated) { + ret = ttm->bdev->driver->ttm_tt_populate(ttm); + if (ret) + goto out1; + } + add = 0; dir = 1; @@ -502,10 +508,16 @@ static int ttm_bo_kmap_ttm(struct ttm_buffer_object *bo, { struct ttm_mem_reg *mem = >mem; pgprot_t prot; struct ttm_tt *ttm = bo->ttm; - struct page *d; - int i; + int ret; BUG_ON(!ttm); + + if (ttm->state == tt_unpopulated) { + ret = ttm->bdev->driver->ttm_tt_populate(ttm); + if (ret) + return ret; + } + if (num_pages == 1 && (mem->placement & TTM_PL_FLAG_CACHED)) { /* * We're mapping a single page, and the desired @@ -513,18 +525,9 @@ static int ttm_bo_kmap_ttm(struct ttm_buffer_object *bo, */ map->bo_kmap_type = ttm_bo_map_kmap; - map->page = ttm_tt_get_page(ttm, start_page); + map->page = ttm->pages[start_page]; map->virtual = kmap(map->page); } else { - /* -* Populate the part we're mapping; -*/ - for (i = start_page; i < start_page + num_pages; ++i) { - d = ttm_tt_get_page(ttm, i); - if (!d) - return -ENOMEM; - } - /* * We need to use vmap to get the desired page protection * or to make the buffer object look contiguous. diff --git
[PATCH 08/13] drm/ttm: merge ttm_backend and ttm_tt V2
From: Jerome Glissettm_backend will exist only and only with a ttm_tt, and ttm_tt will be of interesting use only when bind to a backend. Thus to avoid code & data duplication btw the two merge them. V2 Rebase on top of memory accountign overhaul Signed-off-by: Jerome Glisse Reviewed-by: Konrad Rzeszutek Wilk --- drivers/gpu/drm/nouveau/nouveau_bo.c| 14 ++- drivers/gpu/drm/nouveau/nouveau_drv.h |5 +- drivers/gpu/drm/nouveau/nouveau_sgdma.c | 188 -- drivers/gpu/drm/radeon/radeon_ttm.c | 222 --- drivers/gpu/drm/ttm/ttm_agp_backend.c | 88 + drivers/gpu/drm/ttm/ttm_bo.c|9 +- drivers/gpu/drm/ttm/ttm_tt.c| 60 ++--- drivers/gpu/drm/vmwgfx/vmwgfx_buffer.c | 66 +++-- include/drm/ttm/ttm_bo_driver.h | 104 ++- 9 files changed, 295 insertions(+), 461 deletions(-) diff --git a/drivers/gpu/drm/nouveau/nouveau_bo.c b/drivers/gpu/drm/nouveau/nouveau_bo.c index 7226f41..b060fa4 100644 --- a/drivers/gpu/drm/nouveau/nouveau_bo.c +++ b/drivers/gpu/drm/nouveau/nouveau_bo.c @@ -343,8 +343,10 @@ nouveau_bo_wr32(struct nouveau_bo *nvbo, unsigned index, u32 val) *mem = val; } -static struct ttm_backend * -nouveau_bo_create_ttm_backend_entry(struct ttm_bo_device *bdev) +static struct ttm_tt * +nouveau_ttm_tt_create(struct ttm_bo_device *bdev, + unsigned long size, uint32_t page_flags, + struct page *dummy_read_page) { struct drm_nouveau_private *dev_priv = nouveau_bdev(bdev); struct drm_device *dev = dev_priv->dev; @@ -352,11 +354,13 @@ nouveau_bo_create_ttm_backend_entry(struct ttm_bo_device *bdev) switch (dev_priv->gart_info.type) { #if __OS_HAS_AGP case NOUVEAU_GART_AGP: - return ttm_agp_backend_init(bdev, dev->agp->bridge); + return ttm_agp_tt_create(bdev, dev->agp->bridge, +size, page_flags, dummy_read_page); #endif case NOUVEAU_GART_PDMA: case NOUVEAU_GART_HW: - return nouveau_sgdma_init_ttm(dev); + return nouveau_sgdma_create_ttm(bdev, size, page_flags, + dummy_read_page); default: NV_ERROR(dev, "Unknown GART type %d\n", dev_priv->gart_info.type); @@ -1045,7 +1049,7 @@ nouveau_bo_fence(struct nouveau_bo *nvbo, struct nouveau_fence *fence) } struct ttm_bo_driver nouveau_bo_driver = { - .create_ttm_backend_entry = nouveau_bo_create_ttm_backend_entry, + .ttm_tt_create = _ttm_tt_create, .invalidate_caches = nouveau_bo_invalidate_caches, .init_mem_type = nouveau_bo_init_mem_type, .evict_flags = nouveau_bo_evict_flags, diff --git a/drivers/gpu/drm/nouveau/nouveau_drv.h b/drivers/gpu/drm/nouveau/nouveau_drv.h index 29837da..0c53e39 100644 --- a/drivers/gpu/drm/nouveau/nouveau_drv.h +++ b/drivers/gpu/drm/nouveau/nouveau_drv.h @@ -1000,7 +1000,10 @@ extern int nouveau_sgdma_init(struct drm_device *); extern void nouveau_sgdma_takedown(struct drm_device *); extern uint32_t nouveau_sgdma_get_physical(struct drm_device *, uint32_t offset); -extern struct ttm_backend *nouveau_sgdma_init_ttm(struct drm_device *); +extern struct ttm_tt *nouveau_sgdma_create_ttm(struct ttm_bo_device *bdev, + unsigned long size, + uint32_t page_flags, + struct page *dummy_read_page); /* nouveau_debugfs.c */ #if defined(CONFIG_DRM_NOUVEAU_DEBUG) diff --git a/drivers/gpu/drm/nouveau/nouveau_sgdma.c b/drivers/gpu/drm/nouveau/nouveau_sgdma.c index b75258a..bc2ab90 100644 --- a/drivers/gpu/drm/nouveau/nouveau_sgdma.c +++ b/drivers/gpu/drm/nouveau/nouveau_sgdma.c @@ -8,44 +8,23 @@ #define NV_CTXDMA_PAGE_MASK (NV_CTXDMA_PAGE_SIZE - 1) struct nouveau_sgdma_be { - struct ttm_backend backend; + struct ttm_tt ttm; struct drm_device *dev; - - dma_addr_t *pages; - unsigned nr_pages; - bool unmap_pages; - u64 offset; - bool bound; }; static int -nouveau_sgdma_populate(struct ttm_backend *be, unsigned long num_pages, - struct page **pages, struct page *dummy_read_page, - dma_addr_t *dma_addrs) +nouveau_sgdma_dma_map(struct ttm_tt *ttm) { - struct nouveau_sgdma_be *nvbe = (struct nouveau_sgdma_be *)be; + struct nouveau_sgdma_be *nvbe = (struct nouveau_sgdma_be *)ttm; struct drm_device *dev = nvbe->dev; int i; - NV_DEBUG(nvbe->dev, "num_pages = %ld\n", num_pages); - - nvbe->pages = dma_addrs; - nvbe->nr_pages = num_pages; - nvbe->unmap_pages = true; - - /* this code path isn't called and is incorrect anyways */ -
[PATCH 07/13] drm/ttm: test for dma_address array allocation failure
From: Jerome GlisseSigned-off-by: Jerome Glisse Reviewed-by: Konrad Rzeszutek Wilk Reviewed-by: Thomas Hellstrom --- drivers/gpu/drm/ttm/ttm_tt.c |2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/drivers/gpu/drm/ttm/ttm_tt.c b/drivers/gpu/drm/ttm/ttm_tt.c index 303bbba..2dab08b 100644 --- a/drivers/gpu/drm/ttm/ttm_tt.c +++ b/drivers/gpu/drm/ttm/ttm_tt.c @@ -293,7 +293,7 @@ struct ttm_tt *ttm_tt_create(struct ttm_bo_device *bdev, unsigned long size, ttm->dummy_read_page = dummy_read_page; ttm_tt_alloc_page_directory(ttm); - if (!ttm->pages) { + if (!ttm->pages || !ttm->dma_address) { ttm_tt_destroy(ttm); printk(KERN_ERR TTM_PFX "Failed allocating page table\n"); return NULL; -- 1.7.7.1
[PATCH 06/13] drm/ttm: convert page allocation to use page ptr array instead of list V4
From: Jerome GlisseUse the ttm_tt page ptr array for page allocation, move the list to array unwinding into the page allocation functions. V2 split the fix to use ttm put page as a separate fix properly fill pages array when TTM_PAGE_FLAG_ZERO_ALLOC is not set V3 Added back page_count()==1 check when freeing page V4 Rebase on top of memory accounting overhaul Signed-off-by: Jerome Glisse --- drivers/gpu/drm/ttm/ttm_memory.c | 47 +++-- drivers/gpu/drm/ttm/ttm_page_alloc.c | 90 -- drivers/gpu/drm/ttm/ttm_tt.c | 68 -- include/drm/ttm/ttm_memory.h | 13 +++-- include/drm/ttm/ttm_page_alloc.h | 17 +++--- 5 files changed, 120 insertions(+), 115 deletions(-) diff --git a/drivers/gpu/drm/ttm/ttm_memory.c b/drivers/gpu/drm/ttm/ttm_memory.c index b550baf..98f6899 100644 --- a/drivers/gpu/drm/ttm/ttm_memory.c +++ b/drivers/gpu/drm/ttm/ttm_memory.c @@ -326,32 +326,45 @@ int ttm_mem_global_alloc(struct ttm_mem_global *glob, } EXPORT_SYMBOL(ttm_mem_global_alloc); -int ttm_mem_global_alloc_page(struct ttm_mem_global *glob, - struct page *page, - bool no_wait) +int ttm_mem_global_alloc_pages(struct ttm_mem_global *glob, + unsigned npages, + bool no_wait) { - - if (ttm_mem_global_alloc(glob, PAGE_SIZE, no_wait)) + if (ttm_mem_global_alloc(glob, PAGE_SIZE * npages, no_wait)) return -ENOMEM; + ttm_check_swapping(glob); + return 0; +} + +void ttm_mem_global_account_pages(struct ttm_mem_global *glob, + struct page **pages, + unsigned npages) +{ + unsigned i; /* check if page is dma32 */ - if (page_to_pfn(page) > 0x0010UL) { - spin_lock(>lock); - glob->used_mem -= PAGE_SIZE; - glob->used_dma32_mem += PAGE_SIZE; - spin_unlock(>lock); + spin_lock(>lock); + for (i = 0; i < npages; i++) { + if (page_to_pfn(pages[i]) > 0x0010UL) { + glob->used_mem -= PAGE_SIZE; + glob->used_dma32_mem += PAGE_SIZE; + } } - ttm_check_swapping(glob); - return 0; + spin_unlock(>lock); } -void ttm_mem_global_free_page(struct ttm_mem_global *glob, struct page *page) +void ttm_mem_global_free_pages(struct ttm_mem_global *glob, + struct page **pages, unsigned npages) { + unsigned i; + spin_lock(>lock); - if (page_to_pfn(page) > 0x0010UL) { - glob->used_dma32_mem -= PAGE_SIZE; - } else { - glob->used_mem -= PAGE_SIZE; + for (i = 0; i < npages; i++) { + if (page_to_pfn(pages[i]) > 0x0010UL) { + glob->used_dma32_mem -= PAGE_SIZE; + } else { + glob->used_mem -= PAGE_SIZE; + } } spin_unlock(>lock); } diff --git a/drivers/gpu/drm/ttm/ttm_page_alloc.c b/drivers/gpu/drm/ttm/ttm_page_alloc.c index 727e93d..c4f18b9 100644 --- a/drivers/gpu/drm/ttm/ttm_page_alloc.c +++ b/drivers/gpu/drm/ttm/ttm_page_alloc.c @@ -619,8 +619,10 @@ static void ttm_page_pool_fill_locked(struct ttm_page_pool *pool, * @return count of pages still required to fulfill the request. */ static unsigned ttm_page_pool_get_pages(struct ttm_page_pool *pool, - struct list_head *pages, int ttm_flags, - enum ttm_caching_state cstate, unsigned count) + struct list_head *pages, + int ttm_flags, + enum ttm_caching_state cstate, + unsigned count) { unsigned long irq_flags; struct list_head *p; @@ -664,13 +666,14 @@ out: * On success pages list will hold count number of correctly * cached pages. */ -int ttm_get_pages(struct list_head *pages, int flags, - enum ttm_caching_state cstate, unsigned count, - dma_addr_t *dma_address) +int ttm_get_pages(struct page **pages, unsigned npages, int flags, + enum ttm_caching_state cstate, dma_addr_t *dma_address) { struct ttm_page_pool *pool = ttm_get_pool(flags, cstate); struct page *p = NULL; + struct list_head plist; gfp_t gfp_flags = GFP_USER; + unsigned count = 0; int r; /* set zero flag for page allocation if required */ @@ -684,94 +687,107 @@ int ttm_get_pages(struct list_head *pages, int flags, else gfp_flags |= GFP_HIGHUSER; - for (r = 0; r < count; ++r) { - p = alloc_page(gfp_flags); - if (!p) { - + for
[PATCH 05/13] drm/ttm: overhaul memory accounting
From: Jerome GlisseThis is an overhaul of the ttm memory accounting. This tries to keep the same global behavior while removing the whole zone concept. It keeps a distrinction for dma32 so that we make sure that ttm don't starve the dma32 zone. There is 3 threshold for memory allocation : - max_mem is the maximum memory the whole ttm infrastructure is going to allow allocation for (exception of system process see below) - emer_mem is the maximum memory allowed for system process, this limit is > to max_mem - swap_limit is the threshold at which point ttm will start to try to swap object because ttm is getting close the max_mem limit - swap_dma32_limit is the threshold at which point ttm will start swap object to try to reduce the pressure on the dma32 zone. Note that we don't specificly target object to swap to it might very well free more memory from highmem rather than from dma32 Accounting is done through used_mem & used_dma32_mem, which sum give the total amount of memory actually accounted by ttm. Idea is that allocation will fail if (used_mem + used_dma32_mem) > max_mem and if swapping fail to make enough room. The used_dma32_mem can be updated as a later stage, allowing to perform accounting test before allocating a whole batch of pages. Signed-off-by: Jerome Glisse --- drivers/gpu/drm/ttm/ttm_bo.c |2 +- drivers/gpu/drm/ttm/ttm_memory.c | 517 +- drivers/gpu/drm/ttm/ttm_object.c |3 +- drivers/gpu/drm/ttm/ttm_tt.c |2 +- drivers/gpu/drm/vmwgfx/vmwgfx_fence.c|8 +- drivers/gpu/drm/vmwgfx/vmwgfx_resource.c |8 +- include/drm/ttm/ttm_memory.h | 23 +- 7 files changed, 168 insertions(+), 395 deletions(-) diff --git a/drivers/gpu/drm/ttm/ttm_bo.c b/drivers/gpu/drm/ttm/ttm_bo.c index 4bde335..92712798 100644 --- a/drivers/gpu/drm/ttm/ttm_bo.c +++ b/drivers/gpu/drm/ttm/ttm_bo.c @@ -1252,7 +1252,7 @@ int ttm_bo_create(struct ttm_bo_device *bdev, size_t acc_size = ttm_bo_size(bdev->glob, (size + PAGE_SIZE - 1) >> PAGE_SHIFT); - ret = ttm_mem_global_alloc(mem_glob, acc_size, false, false); + ret = ttm_mem_global_alloc(mem_glob, acc_size, false); if (unlikely(ret != 0)) return ret; diff --git a/drivers/gpu/drm/ttm/ttm_memory.c b/drivers/gpu/drm/ttm/ttm_memory.c index e70ddd8..b550baf 100644 --- a/drivers/gpu/drm/ttm/ttm_memory.c +++ b/drivers/gpu/drm/ttm/ttm_memory.c @@ -35,21 +35,10 @@ #include #include -#define TTM_MEMORY_ALLOC_RETRIES 4 - -struct ttm_mem_zone { - struct kobject kobj; - struct ttm_mem_global *glob; - const char *name; - uint64_t zone_mem; - uint64_t emer_mem; - uint64_t max_mem; - uint64_t swap_limit; - uint64_t used_mem; -}; +#define TTM_MEMORY_RETRIES 4 static struct attribute ttm_mem_sys = { - .name = "zone_memory", + .name = "memory", .mode = S_IRUGO }; static struct attribute ttm_mem_emer = { @@ -64,140 +53,141 @@ static struct attribute ttm_mem_swap = { .name = "swap_limit", .mode = S_IRUGO | S_IWUSR }; +static struct attribute ttm_mem_dma32_swap = { + .name = "swap_dma32_limit", + .mode = S_IRUGO | S_IWUSR +}; static struct attribute ttm_mem_used = { .name = "used_memory", .mode = S_IRUGO }; +static struct attribute ttm_mem_dma32_used = { + .name = "used_dma32_memory", + .mode = S_IRUGO +}; -static void ttm_mem_zone_kobj_release(struct kobject *kobj) -{ - struct ttm_mem_zone *zone = - container_of(kobj, struct ttm_mem_zone, kobj); - - printk(KERN_INFO TTM_PFX - "Zone %7s: Used memory at exit: %llu kiB.\n", - zone->name, (unsigned long long) zone->used_mem >> 10); - kfree(zone); -} - -static ssize_t ttm_mem_zone_show(struct kobject *kobj, -struct attribute *attr, -char *buffer) +static ssize_t ttm_mem_global_show(struct kobject *kobj, + struct attribute *attr, + char *buffer) { - struct ttm_mem_zone *zone = - container_of(kobj, struct ttm_mem_zone, kobj); - uint64_t val = 0; + struct ttm_mem_global *glob = + container_of(kobj, struct ttm_mem_global, kobj); + unsigned long val = 0; - spin_lock(>glob->lock); + spin_lock(>lock); if (attr == _mem_sys) - val = zone->zone_mem; + val = glob->mem; else if (attr == _mem_emer) - val = zone->emer_mem; + val = glob->emer_mem; else if (attr == _mem_max) - val = zone->max_mem; + val = glob->max_mem; else if (attr == _mem_swap) - val = zone->swap_limit; + val = glob->swap_limit; else if (attr == _mem_used) -
[PATCH 04/13] drm/ttm: use ttm put pages function to properly restore cache attribute
From: Jerome GlisseOn failure we need to make sure the page we free has wb cache attribute. Do this pas call the proper ttm page helper function. Signed-off-by: Jerome Glisse Reviewed-by: Konrad Rzeszutek Wilk Reviewed-by: Thomas Hellstrom --- drivers/gpu/drm/ttm/ttm_tt.c |5 - 1 files changed, 4 insertions(+), 1 deletions(-) diff --git a/drivers/gpu/drm/ttm/ttm_tt.c b/drivers/gpu/drm/ttm/ttm_tt.c index 8b7a6d0..3fb4c6d 100644 --- a/drivers/gpu/drm/ttm/ttm_tt.c +++ b/drivers/gpu/drm/ttm/ttm_tt.c @@ -89,7 +89,10 @@ static struct page *__ttm_tt_get_page(struct ttm_tt *ttm, int index) } return p; out_err: - put_page(p); + INIT_LIST_HEAD(); + list_add(>lru, ); + ttm_put_pages(, 1, ttm->page_flags, + ttm->caching_state, >dma_address[index]); return NULL; } -- 1.7.7.1
[PATCH 03/13] drm/ttm: remove unused backend flags field
From: Jerome GlisseThis field is not use by any of the driver just drop it. Signed-off-by: Jerome Glisse Reviewed-by: Konrad Rzeszutek Wilk Reviewed-by: Thomas Hellstrom --- drivers/gpu/drm/radeon/radeon_ttm.c |1 - include/drm/ttm/ttm_bo_driver.h |2 -- 2 files changed, 0 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/radeon/radeon_ttm.c b/drivers/gpu/drm/radeon/radeon_ttm.c index 0b5468b..97c76ae 100644 --- a/drivers/gpu/drm/radeon/radeon_ttm.c +++ b/drivers/gpu/drm/radeon/radeon_ttm.c @@ -787,7 +787,6 @@ struct ttm_backend *radeon_ttm_backend_create(struct radeon_device *rdev) return NULL; } gtt->backend.bdev = >mman.bdev; - gtt->backend.flags = 0; gtt->backend.func = _backend_func; gtt->rdev = rdev; gtt->pages = NULL; diff --git a/include/drm/ttm/ttm_bo_driver.h b/include/drm/ttm/ttm_bo_driver.h index 9da182b..6d17140 100644 --- a/include/drm/ttm/ttm_bo_driver.h +++ b/include/drm/ttm/ttm_bo_driver.h @@ -106,7 +106,6 @@ struct ttm_backend_func { * struct ttm_backend * * @bdev: Pointer to a struct ttm_bo_device. - * @flags: For driver use. * @func: Pointer to a struct ttm_backend_func that describes * the backend methods. * @@ -114,7 +113,6 @@ struct ttm_backend_func { struct ttm_backend { struct ttm_bo_device *bdev; - uint32_t flags; struct ttm_backend_func *func; }; -- 1.7.7.1
[PATCH 02/13] drm/ttm: remove split btw highmen and lowmem page
From: Jerome GlisseSplit btw highmem and lowmem page was rendered useless by the pool code. Remove it. Note further cleanup would change the ttm page allocation helper to actualy take an array instead of relying on list this could drasticly reduce the number of function call in the common case of allocation whole buffer. Signed-off-by: Jerome Glisse Reviewed-by: Konrad Rzeszutek Wilk Reviewed-by: Thomas Hellstrom --- drivers/gpu/drm/ttm/ttm_tt.c| 11 ++- include/drm/ttm/ttm_bo_driver.h |7 --- 2 files changed, 2 insertions(+), 16 deletions(-) diff --git a/drivers/gpu/drm/ttm/ttm_tt.c b/drivers/gpu/drm/ttm/ttm_tt.c index 82a1161..8b7a6d0 100644 --- a/drivers/gpu/drm/ttm/ttm_tt.c +++ b/drivers/gpu/drm/ttm/ttm_tt.c @@ -69,7 +69,7 @@ static struct page *__ttm_tt_get_page(struct ttm_tt *ttm, int index) struct ttm_mem_global *mem_glob = ttm->glob->mem_glob; int ret; - while (NULL == (p = ttm->pages[index])) { + if (NULL == (p = ttm->pages[index])) { INIT_LIST_HEAD(); @@ -85,10 +85,7 @@ static struct page *__ttm_tt_get_page(struct ttm_tt *ttm, int index) if (unlikely(ret != 0)) goto out_err; - if (PageHighMem(p)) - ttm->pages[--ttm->first_himem_page] = p; - else - ttm->pages[++ttm->last_lomem_page] = p; + ttm->pages[index] = p; } return p; out_err: @@ -270,8 +267,6 @@ static void ttm_tt_free_alloced_pages(struct ttm_tt *ttm) ttm_put_pages(, count, ttm->page_flags, ttm->caching_state, ttm->dma_address); ttm->state = tt_unpopulated; - ttm->first_himem_page = ttm->num_pages; - ttm->last_lomem_page = -1; } void ttm_tt_destroy(struct ttm_tt *ttm) @@ -315,8 +310,6 @@ struct ttm_tt *ttm_tt_create(struct ttm_bo_device *bdev, unsigned long size, ttm->glob = bdev->glob; ttm->num_pages = (size + PAGE_SIZE - 1) >> PAGE_SHIFT; - ttm->first_himem_page = ttm->num_pages; - ttm->last_lomem_page = -1; ttm->caching_state = tt_cached; ttm->page_flags = page_flags; diff --git a/include/drm/ttm/ttm_bo_driver.h b/include/drm/ttm/ttm_bo_driver.h index 37527d6..9da182b 100644 --- a/include/drm/ttm/ttm_bo_driver.h +++ b/include/drm/ttm/ttm_bo_driver.h @@ -136,11 +136,6 @@ enum ttm_caching_state { * @dummy_read_page: Page to map where the ttm_tt page array contains a NULL * pointer. * @pages: Array of pages backing the data. - * @first_himem_page: Himem pages are put last in the page array, which - * enables us to run caching attribute changes on only the first part - * of the page array containing lomem pages. This is the index of the - * first himem page. - * @last_lomem_page: Index of the last lomem page in the page array. * @num_pages: Number of pages in the page array. * @bdev: Pointer to the current struct ttm_bo_device. * @be: Pointer to the ttm backend. @@ -157,8 +152,6 @@ enum ttm_caching_state { struct ttm_tt { struct page *dummy_read_page; struct page **pages; - long first_himem_page; - long last_lomem_page; uint32_t page_flags; unsigned long num_pages; struct ttm_bo_global *glob; -- 1.7.7.1
[PATCH 01/13] drm/ttm: remove userspace backed ttm object support
From: Jerome GlisseThis was never use in none of the driver, properly using userspace page for bo would need more code (vma interaction mostly). Removing this dead code in preparation of ttm_tt & backend merge. Signed-off-by: Jerome Glisse Reviewed-by: Konrad Rzeszutek Wilk Reviewed-by: Thomas Hellstrom --- drivers/gpu/drm/ttm/ttm_bo.c| 22 drivers/gpu/drm/ttm/ttm_tt.c| 105 +-- include/drm/ttm/ttm_bo_api.h|5 -- include/drm/ttm/ttm_bo_driver.h | 24 - 4 files changed, 1 insertions(+), 155 deletions(-) diff --git a/drivers/gpu/drm/ttm/ttm_bo.c b/drivers/gpu/drm/ttm/ttm_bo.c index 617b646..4bde335 100644 --- a/drivers/gpu/drm/ttm/ttm_bo.c +++ b/drivers/gpu/drm/ttm/ttm_bo.c @@ -342,22 +342,6 @@ static int ttm_bo_add_ttm(struct ttm_buffer_object *bo, bool zero_alloc) if (unlikely(bo->ttm == NULL)) ret = -ENOMEM; break; - case ttm_bo_type_user: - bo->ttm = ttm_tt_create(bdev, bo->num_pages << PAGE_SHIFT, - page_flags | TTM_PAGE_FLAG_USER, - glob->dummy_read_page); - if (unlikely(bo->ttm == NULL)) { - ret = -ENOMEM; - break; - } - - ret = ttm_tt_set_user(bo->ttm, current, - bo->buffer_start, bo->num_pages); - if (unlikely(ret != 0)) { - ttm_tt_destroy(bo->ttm); - bo->ttm = NULL; - } - break; default: printk(KERN_ERR TTM_PFX "Illegal buffer object type\n"); ret = -EINVAL; @@ -907,16 +891,12 @@ static uint32_t ttm_bo_select_caching(struct ttm_mem_type_manager *man, } static bool ttm_bo_mt_compatible(struct ttm_mem_type_manager *man, -bool disallow_fixed, uint32_t mem_type, uint32_t proposed_placement, uint32_t *masked_placement) { uint32_t cur_flags = ttm_bo_type_flags(mem_type); - if ((man->flags & TTM_MEMTYPE_FLAG_FIXED) && disallow_fixed) - return false; - if ((cur_flags & proposed_placement & TTM_PL_MASK_MEM) == 0) return false; @@ -961,7 +941,6 @@ int ttm_bo_mem_space(struct ttm_buffer_object *bo, man = >man[mem_type]; type_ok = ttm_bo_mt_compatible(man, - bo->type == ttm_bo_type_user, mem_type, placement->placement[i], _flags); @@ -1009,7 +988,6 @@ int ttm_bo_mem_space(struct ttm_buffer_object *bo, if (!man->has_type) continue; if (!ttm_bo_mt_compatible(man, - bo->type == ttm_bo_type_user, mem_type, placement->busy_placement[i], _flags)) diff --git a/drivers/gpu/drm/ttm/ttm_tt.c b/drivers/gpu/drm/ttm/ttm_tt.c index 58c271e..82a1161 100644 --- a/drivers/gpu/drm/ttm/ttm_tt.c +++ b/drivers/gpu/drm/ttm/ttm_tt.c @@ -62,43 +62,6 @@ static void ttm_tt_free_page_directory(struct ttm_tt *ttm) ttm->dma_address = NULL; } -static void ttm_tt_free_user_pages(struct ttm_tt *ttm) -{ - int write; - int dirty; - struct page *page; - int i; - struct ttm_backend *be = ttm->be; - - BUG_ON(!(ttm->page_flags & TTM_PAGE_FLAG_USER)); - write = ((ttm->page_flags & TTM_PAGE_FLAG_WRITE) != 0); - dirty = ((ttm->page_flags & TTM_PAGE_FLAG_USER_DIRTY) != 0); - - if (be) - be->func->clear(be); - - for (i = 0; i < ttm->num_pages; ++i) { - page = ttm->pages[i]; - if (page == NULL) - continue; - - if (page == ttm->dummy_read_page) { - BUG_ON(write); - continue; - } - - if (write && dirty && !PageReserved(page)) - set_page_dirty_lock(page); - - ttm->pages[i] = NULL; - ttm_mem_global_free(ttm->glob->mem_glob, PAGE_SIZE); - put_page(page); - } - ttm->state = tt_unpopulated; - ttm->first_himem_page = ttm->num_pages; - ttm->last_lomem_page = -1; -} - static struct page *__ttm_tt_get_page(struct ttm_tt *ttm, int index) { struct page *p; @@ -325,10 +288,7 @@ void ttm_tt_destroy(struct ttm_tt *ttm) } if (likely(ttm->pages != NULL)) { - if (ttm->page_flags &
ttm: merge ttm_backend & ttm_tt, introduce ttm dma allocator
So i did an overhaul of ttm_memory, i believe the simplification i did make sense. See patch 5 for a longer explanation. Thomas with the ttm_memory change the allocation of pages won't happen if the accounting report that we are going over the limit and bo shrinker failed to free any memory to make room. The handling of dma32 zone is done as post pass of ttm memory accounting. Regarding the pagefault comment i removed, it doesn't make sense anymore because now we populate the whole page table in one shot. So there is no more prefaulting few pages but a full prefaulting. Thought i can add a comment stating that if you like. For the ttm_tt_dma struct to hold page allocator specific informations i think it can be done as an followup patch but if you prefer to have that in this patchset let me know i will respin with such changes. I am in the process of retesting this whole serie and especialy the while memory accounting. Cheers, Jerome
[Bug 27314] displayport link training fails on certain panels (channel equalization fails)
https://bugs.freedesktop.org/show_bug.cgi?id=27314 --- Comment #59 from Alex Deucher 2011-11-09 06:44:37 PST --- (In reply to comment #57) > Created attachment 53309 [details] > xorg log with the ati driver in fedora16 > > I have just installed fedora 16 on an "imac11,1", and I still have the same > problem. I have attached the xorg log, let me know if there is anything else I > could do to help. > > I checked that the patch pointed by Comment 55 is include in the linux 3.1 > shipping with fedora. > > I am going to try the current linus tree and let you know if that helps. Why are you using UMS? All of the relevant fixes have been in KMS. -- Configure bugmail: https://bugs.freedesktop.org/userprefs.cgi?tab=email --- You are receiving this mail because: --- You are the assignee for the bug.
[PATCH 3/3] vmwgfx: Only allow 64x64 cursors
From: Jakob BornecrantzSnooping code expects this to be the case. Signed-off-by: Jakob Bornecrantz Reviewed-by: Thomas Hellstrom --- drivers/gpu/drm/vmwgfx/vmwgfx_kms.c |4 1 files changed, 4 insertions(+), 0 deletions(-) diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c index 40c7e61..880e285 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c @@ -105,6 +105,10 @@ int vmw_du_crtc_cursor_set(struct drm_crtc *crtc, struct drm_file *file_priv, struct vmw_dma_buffer *dmabuf = NULL; int ret; + /* A lot of the code assumes this */ + if (handle && (width != 64 || height != 64)) + return -EINVAL; + if (handle) { ret = vmw_user_surface_lookup_handle(dev_priv, tfile, handle, ); -- 1.7.4.4
[PATCH 2/3] vmwgfx: Initialize clip rect loop correctly in surface dirty
From: Jakob BornecrantzSigned-off-by: Jakob Bornecrantz Reviewed-by: Thomas Hellstrom --- drivers/gpu/drm/vmwgfx/vmwgfx_kms.c |5 +++-- 1 files changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c index f3ab1fe..40c7e61 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c @@ -410,8 +410,9 @@ static int do_surface_dirty_sou(struct vmw_private *dev_priv, top = clips->y1; bottom = clips->y2; - clips_ptr = clips; - for (i = 1; i < num_clips; i++, clips_ptr += inc) { + /* skip the first clip rect */ + for (i = 1, clips_ptr = clips + inc; +i < num_clips; i++, clips_ptr += inc) { left = min_t(int, left, (int)clips_ptr->x1); right = max_t(int, right, (int)clips_ptr->x2); top = min_t(int, top, (int)clips_ptr->y1); -- 1.7.4.4
[PATCH 1/3] vmwgfx: Close screen object system
From: Jakob BornecrantzSigned-off-by: Jakob Bornecrantz Reviewed-by: Thomas Hellstrom --- drivers/gpu/drm/vmwgfx/vmwgfx_kms.c |5 - 1 files changed, 4 insertions(+), 1 deletions(-) diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c index 03daefa..f3ab1fe 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c @@ -1323,7 +1323,10 @@ int vmw_kms_close(struct vmw_private *dev_priv) * drm_encoder_cleanup which takes the lock we deadlock. */ drm_mode_config_cleanup(dev_priv->dev); - vmw_kms_close_legacy_display_system(dev_priv); + if (dev_priv->sou_priv) + vmw_kms_close_screen_object_display(dev_priv); + else + vmw_kms_close_legacy_display_system(dev_priv); return 0; } -- 1.7.4.4
[PATCH -fixes 0/3] vmwgfx fixes
A couple of bugfixes for vmwgfx kms.
r600 hdmi sound issue
2011/11/9 Greg Dietsche : > Hi, > I have a ASUS M4A89GTD motherboard and when I play back music in Rhythmbox, > there is no sound (hdmi connection). Also, the playback speed is in a sort > of fast forward (for example, after a few seconds of real time, rhythmbox > shows something like 30 seconds into the song). This seems to be a kernel > regression. I know that it started with 3.0, is present in 3.1, and is not > working in 3.2-rc1, so it is still a problem. > > I bisected and found my self here: fe6f0bd03d697835e76dd18d232ba476c65b8282. > However due to some graphical issues, I'm not actually able to test that > commit. I tried reverting that commit, but the problem wasn't fixed. > > I'd like to see this problem fixed and can compile and test patches as > necessary. Please let me know if you need more information - I'm happy to > provide it :) fe6f0bd03d697835e76dd18d232ba476c65b8282 is not likely. I suspect you just experience results of so-called-fix: 805c22168da76a65c978017d0fe0d59cd048e995 drm/radeon/kms: disable hdmi audio by default I'm trying to get in contact with ppl affected by issues when enabling audio. Hopefully we can fix audio support and enable it by default again. For now, please load radeon module with "audio=1", or simply boot with radeon.audio=1 -- Rafa?
Linux 3.2-rc1
At Tue, 8 Nov 2011 12:23:30 -0800, Linus Torvalds wrote: > > Hmm, I don't know what caused this to trigger, but I'm adding both the > i915 people and the HDA people to the cc, and they can fight to the > death about this in the HDMI Thunderdome. It must be the new addition of ELD-passing code. Fengguang, can the drm or i915 driver check whether ELD is changed or not? Writing ELD at each time even when unchanged confuses the audio side, as if the monitor is hotplugged. > > Guys: One.. Two.. Three.. FIGHT! Round two! Takashi > Linus > > On Tue, Nov 8, 2011 at 6:55 AM, Nick Bowler > wrote: > > > > Mode switches are very noisy on an Intel G45 in 3.2-rc1: > > > > ?HDMI hot plug event: Codec=3 Pin=3 Presence_Detect=1 ELD_Valid=1 > > ?HDMI status: Codec=3 Pin=3 Presence_Detect=1 ELD_Valid=1 > > ?HDMI: detected monitor W2253 at connection type HDMI > > ?HDMI: available speakers: FL/FR > > ?HDMI: supports coding type LPCM: channels = 2, rates = 32000 44100 48000, > > bits = 16 20 24 > > > > These lines get printed every single switch; previously only a single > > line was printed once at boot (the "HDMI status" line). > > > > Cheers, > > -- > > Nick Bowler, Elliptic Technologies (http://www.elliptictech.com/) > > >
[PATCH] drm/ttm: overhaul memory accounting V2
This is an overhaul of the ttm memory accounting. This tries to keep the same global behavior while removing the whole zone concept. It keeps a distrinction for dma32 so that we make sure that ttm don't starve the dma32 zone. There is 3 threshold for memory allocation : - max_mem is the maximum memory the whole ttm infrastructure is going to allow allocation for (exception of system process see below) - emer_mem is the maximum memory allowed for system process, this limit is > to max_mem - swap_limit is the threshold at which point ttm will start to try to swap object because ttm is getting close the max_mem limit - swap_dma32_limit is the threshold at which point ttm will start swap object to try to reduce the pressure on the dma32 zone. Note that we don't specificly target object to swap to it might very well free more memory from highmem rather than from dma32 Accounting is done through used_mem & used_dma32_mem, which sum give the total amount of memory actually accounted by ttm. Idea is that allocation will fail if (used_mem + used_dma32_mem) > max_mem and if swapping fail to make enough room. The used_dma32_mem can be updated as a later stage, allowing to perform accounting test before allocating a whole batch of pages. V2 Move accouting before page allocation instead of leaving that to a later patch. Always account first against dma32 zone and only as a post pass rebalance accouting to highmem if pages allow it. Signed-off-by: Jerome Glisse --- drivers/gpu/drm/ttm/ttm_bo.c |9 +- drivers/gpu/drm/ttm/ttm_memory.c | 554 ++ drivers/gpu/drm/ttm/ttm_object.c | 10 +- drivers/gpu/drm/ttm/ttm_tt.c | 14 +- drivers/gpu/drm/vmwgfx/vmwgfx_fence.c| 30 +- drivers/gpu/drm/vmwgfx/vmwgfx_resource.c | 51 ++-- include/drm/ttm/ttm_memory.h | 27 +- 7 files changed, 263 insertions(+), 432 deletions(-) diff --git a/drivers/gpu/drm/ttm/ttm_bo.c b/drivers/gpu/drm/ttm/ttm_bo.c index 4bde335..b3674ba 100644 --- a/drivers/gpu/drm/ttm/ttm_bo.c +++ b/drivers/gpu/drm/ttm/ttm_bo.c @@ -1248,13 +1248,16 @@ int ttm_bo_create(struct ttm_bo_device *bdev, { struct ttm_buffer_object *bo; struct ttm_mem_global *mem_glob = bdev->glob->mem_glob; + unsigned long available; int ret; size_t acc_size = ttm_bo_size(bdev->glob, (size + PAGE_SIZE - 1) >> PAGE_SHIFT); - ret = ttm_mem_global_alloc(mem_glob, acc_size, false, false); - if (unlikely(ret != 0)) - return ret; + available = ttm_mem_global_alloc(mem_glob, acc_size, false); + if (available != acc_size) { + ttm_mem_global_free(mem_glob, available); + return -ENOMEM; + } bo = kzalloc(sizeof(*bo), GFP_KERNEL); diff --git a/drivers/gpu/drm/ttm/ttm_memory.c b/drivers/gpu/drm/ttm/ttm_memory.c index e70ddd8..2aa08a7 100644 --- a/drivers/gpu/drm/ttm/ttm_memory.c +++ b/drivers/gpu/drm/ttm/ttm_memory.c @@ -35,21 +35,10 @@ #include #include -#define TTM_MEMORY_ALLOC_RETRIES 4 - -struct ttm_mem_zone { - struct kobject kobj; - struct ttm_mem_global *glob; - const char *name; - uint64_t zone_mem; - uint64_t emer_mem; - uint64_t max_mem; - uint64_t swap_limit; - uint64_t used_mem; -}; +#define TTM_MEMORY_RETRIES 4 static struct attribute ttm_mem_sys = { - .name = "zone_memory", + .name = "memory", .mode = S_IRUGO }; static struct attribute ttm_mem_emer = { @@ -60,144 +49,156 @@ static struct attribute ttm_mem_max = { .name = "available_memory", .mode = S_IRUGO | S_IWUSR }; +static struct attribute ttm_mem_dma32_max = { + .name = "available_dma32_memory", + .mode = S_IRUGO | S_IWUSR +}; static struct attribute ttm_mem_swap = { .name = "swap_limit", .mode = S_IRUGO | S_IWUSR }; +static struct attribute ttm_mem_dma32_swap = { + .name = "swap_dma32_limit", + .mode = S_IRUGO | S_IWUSR +}; static struct attribute ttm_mem_used = { .name = "used_memory", .mode = S_IRUGO }; +static struct attribute ttm_mem_dma32_used = { + .name = "used_dma32_memory", + .mode = S_IRUGO +}; -static void ttm_mem_zone_kobj_release(struct kobject *kobj) -{ - struct ttm_mem_zone *zone = - container_of(kobj, struct ttm_mem_zone, kobj); - - printk(KERN_INFO TTM_PFX - "Zone %7s: Used memory at exit: %llu kiB.\n", - zone->name, (unsigned long long) zone->used_mem >> 10); - kfree(zone); -} - -static ssize_t ttm_mem_zone_show(struct kobject *kobj, -struct attribute *attr, -char *buffer) +static ssize_t ttm_mem_global_show(struct kobject *kobj, + struct attribute *attr, + char *buffer) { - struct ttm_mem_zone *zone = -
[PATCH 2/2] drm: add an fb creation ioctl that takes a pixel format
On Wed, Nov 9, 2011 at 7:25 AM, InKi Dae wrote: > Hello, all. > > I am trying to implement multi planer using your plane patch and I > think it's good but I am still warried about that drm_mode_fb_cmd2 > structure has only one handle. I know this handle is sent to > framebuffer module to create new framebuffer. and the framebuffer > would cover entire a image. as you know, the image could be consisted > of one more planes. so I think now drm_mode_fb_cmd2 structure doesn't > support multi planer because it has only one handle. with update_plane > callback, a buffer of the framebuffer would be set to a hardware > overlay. how we could set two planes or three planes to the hardware > overlay? but there might be my missing point so please give me any > comments. in addition, have you been looked into gem flink and open > functions for memory sharing between processes? gem object basically > has one buffer so we can't modify it because of compatibility. so I > think it's right way that gem object manages only one buffer. for such > a reason, maybe drm_mode_fb_cmd2 structure should include one more > handles and plane count. each handle has a gem object to one plane and > plane count means how many planes are requested and when update_plane > callback is called by setplane(), we could set them of the specific > framebuffer to a hardware overlay. The current plan is to add a 3rd ioctl, for adding multi-planar fb.. I guess it is a good thing that I'm not the only one who wants this :-) > another one, and also I have tried to implement the way sharing the > memory between v4l2 based drivers and drm based drivers through > application and this works fine. this feature had been introduced by > v4l2 framework as user ptr. my way also is similar to it. the > difference is that application could get new gem handle from specific > gem framework of kernel side if user application requests user ptr > import with the user space address(mmaped memory). the new gem handle > means a gem object to the memory mapped to the user space address. > this way makes different applications to be possible to share the > memory between v4l2 based driver and drm based driver. and also this > feature is considered for IOMMU so it would support non continuous > memory also. I will introduce this feature soon. btw, there was an RFC a little while back for "dmabuf" buffer sharing mechanism.. the idea would be to export a (for example) GEM buffer to a dmabuf handle which could be passed in to other devices, including for example v4l2 (although without necessarily requiring a userspace mapping).. http://www.spinics.net/lists/dri-devel/msg15077.html It sounds like you are looking for a similar thing.. BR, -R > Thank you, > Inki Dae. > > 2011/11/9 Jesse Barnes : >> To properly support the various plane formats supported by different >> hardware, the kernel must know the pixel format of a framebuffer object. >> So add a new ioctl taking a format argument corresponding to a fourcc >> name from videodev2.h. ?Implement the fb creation hooks in terms of the >> new mode_fb_cmd2 using helpers where the old bpp/depth values are >> needed. >> >> Acked-by: Alan Cox >> Reviewed-by: Rob Clark >> Signed-off-by: Jesse Barnes >> --- >> ?drivers/gpu/drm/drm_crtc.c ? ? ? ? ? ? ? ?| ?108 >> +++- >> ?drivers/gpu/drm/drm_crtc_helper.c ? ? ? ? | ? 50 - >> ?drivers/gpu/drm/drm_drv.c ? ? ? ? ? ? ? ? | ? ?1 + >> ?drivers/gpu/drm/i915/intel_display.c ? ? ?| ? 36 +- >> ?drivers/gpu/drm/i915/intel_drv.h ? ? ? ? ?| ? ?2 +- >> ?drivers/gpu/drm/i915/intel_fb.c ? ? ? ? ? | ? 11 ++-- >> ?drivers/gpu/drm/nouveau/nouveau_display.c | ? ?4 +- >> ?drivers/gpu/drm/nouveau/nouveau_fb.h ? ? ?| ? ?2 +- >> ?drivers/gpu/drm/nouveau/nouveau_fbcon.c ? | ? 13 ++-- >> ?drivers/gpu/drm/radeon/radeon_display.c ? | ? ?4 +- >> ?drivers/gpu/drm/radeon/radeon_fb.c ? ? ? ?| ? 18 +++-- >> ?drivers/gpu/drm/radeon/radeon_mode.h ? ? ?| ? ?2 +- >> ?drivers/gpu/drm/vmwgfx/vmwgfx_kms.c ? ? ? | ? 22 -- >> ?drivers/gpu/drm/vmwgfx/vmwgfx_kms.h ? ? ? | ? ?1 + >> ?drivers/staging/gma500/framebuffer.c ? ? ?| ? ?2 +- >> ?include/drm/drm.h ? ? ? ? ? ? ? ? ? ? ? ? | ? ?1 + >> ?include/drm/drm_crtc.h ? ? ? ? ? ? ? ? ? ?| ? ?7 ++- >> ?include/drm/drm_crtc_helper.h ? ? ? ? ? ? | ? ?4 +- >> ?include/drm/drm_mode.h ? ? ? ? ? ? ? ? ? ?| ? 28 +++- >> ?include/linux/videodev2.h ? ? ? ? ? ? ? ? | ? ?1 + >> ?20 files changed, 256 insertions(+), 61 deletions(-) >> >> diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c >> index 804ef12..39cccb4 100644 >> --- a/drivers/gpu/drm/drm_crtc.c >> +++ b/drivers/gpu/drm/drm_crtc.c >> @@ -1910,6 +1910,42 @@ out: >> ? ? ? ?return ret; >> ?} >> >> +/* Original addfb only supported RGB formats, so figure out which one */ >> +uint32_t drm_mode_legacy_fb_format(uint32_t bpp, uint32_t depth) >> +{ >> + ? ? ? uint32_t fmt; >> + >> + ? ? ? switch (bpp) { >> + ? ? ? case 8: >> + ? ? ? ? ? ? ? fmt =
[Bug 27314] displayport link training fails on certain panels (channel equalization fails)
https://bugs.freedesktop.org/show_bug.cgi?id=27314 --- Comment #57 from Rafael ?vila de Esp?ndola 2011-11-08 17:43:24 PST --- Created attachment 53309 --> https://bugs.freedesktop.org/attachment.cgi?id=53309 xorg log with the ati driver in fedora16 I have just installed fedora 16 on an "imac11,1", and I still have the same problem. I have attached the xorg log, let me know if there is anything else I could do to help. I checked that the patch pointed by Comment 55 is include in the linux 3.1 shipping with fedora. I am going to try the current linus tree and let you know if that helps. -- Configure bugmail: https://bugs.freedesktop.org/userprefs.cgi?tab=email --- You are receiving this mail because: --- You are the assignee for the bug.
[PATCH 4/5] drm/i915: add destination color key support
On Tue, Nov 08, 2011 at 05:36:11PM -0500, Alex Deucher wrote: > On Tue, Nov 8, 2011 at 5:06 PM, Daniel Vetter wrote: > > On Mon, Nov 07, 2011 at 10:02:55AM -0800, Jesse Barnes wrote: > >> Add new ioctls for getting and setting the current destination color > >> key. ?This allows for simple overlay display control by matching a color > >> key value in the primary plane before blending the overlay on top. > >> > >> Signed-off-by: Jesse Barnes > > > > A few comments below and a snide-y one here: If the goal is simply to keep > > the bubble intact, this is fine by me. If we want something that has the > > chance to be useable by a generic driver I think we want a drm interface > > for plane/crtc properties (you could wire up set_gamma on planes in the > > same series ... ;-) Again, I don't really care ... > > Even further off topic, the panel scaler support should ideally be a > property of crtcs/planes rather than a connector property. However, > that would be a bit of pain to implement and keep backwards > compatibility. I think we could just internally route the output pannel-fitter prop to the crtc one. After all if the hw has the fitter really on the crtc, moving it also logically to the crtc won't make anything previously possibel impossible ... -Daniel -- Daniel Vetter Mail: daniel at ffwll.ch Mobile: +41 (0)79 365 57 48
Re: r600 hdmi sound issue
2011/11/9 Greg Dietsche g...@gregd.org: Hi, I have a ASUS M4A89GTD motherboard and when I play back music in Rhythmbox, there is no sound (hdmi connection). Also, the playback speed is in a sort of fast forward (for example, after a few seconds of real time, rhythmbox shows something like 30 seconds into the song). This seems to be a kernel regression. I know that it started with 3.0, is present in 3.1, and is not working in 3.2-rc1, so it is still a problem. I bisected and found my self here: fe6f0bd03d697835e76dd18d232ba476c65b8282. However due to some graphical issues, I'm not actually able to test that commit. I tried reverting that commit, but the problem wasn't fixed. I'd like to see this problem fixed and can compile and test patches as necessary. Please let me know if you need more information - I'm happy to provide it :) fe6f0bd03d697835e76dd18d232ba476c65b8282 is not likely. I suspect you just experience results of so-called-fix: 805c22168da76a65c978017d0fe0d59cd048e995 drm/radeon/kms: disable hdmi audio by default I'm trying to get in contact with ppl affected by issues when enabling audio. Hopefully we can fix audio support and enable it by default again. For now, please load radeon module with audio=1, or simply boot with radeon.audio=1 -- Rafał ___ dri-devel mailing list dri-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH -fixes 0/3] vmwgfx fixes
A couple of bugfixes for vmwgfx kms. ___ dri-devel mailing list dri-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH 1/3] vmwgfx: Close screen object system
From: Jakob Bornecrantz ja...@vmware.com Signed-off-by: Jakob Bornecrantz ja...@vmware.com Reviewed-by: Thomas Hellstrom thellst...@vmware.com --- drivers/gpu/drm/vmwgfx/vmwgfx_kms.c |5 - 1 files changed, 4 insertions(+), 1 deletions(-) diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c index 03daefa..f3ab1fe 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c @@ -1323,7 +1323,10 @@ int vmw_kms_close(struct vmw_private *dev_priv) * drm_encoder_cleanup which takes the lock we deadlock. */ drm_mode_config_cleanup(dev_priv-dev); - vmw_kms_close_legacy_display_system(dev_priv); + if (dev_priv-sou_priv) + vmw_kms_close_screen_object_display(dev_priv); + else + vmw_kms_close_legacy_display_system(dev_priv); return 0; } -- 1.7.4.4 ___ dri-devel mailing list dri-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH 2/3] vmwgfx: Initialize clip rect loop correctly in surface dirty
From: Jakob Bornecrantz ja...@vmware.com Signed-off-by: Jakob Bornecrantz ja...@vmware.com Reviewed-by: Thomas Hellstrom thellst...@vmware.com --- drivers/gpu/drm/vmwgfx/vmwgfx_kms.c |5 +++-- 1 files changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c index f3ab1fe..40c7e61 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c @@ -410,8 +410,9 @@ static int do_surface_dirty_sou(struct vmw_private *dev_priv, top = clips-y1; bottom = clips-y2; - clips_ptr = clips; - for (i = 1; i num_clips; i++, clips_ptr += inc) { + /* skip the first clip rect */ + for (i = 1, clips_ptr = clips + inc; +i num_clips; i++, clips_ptr += inc) { left = min_t(int, left, (int)clips_ptr-x1); right = max_t(int, right, (int)clips_ptr-x2); top = min_t(int, top, (int)clips_ptr-y1); -- 1.7.4.4 ___ dri-devel mailing list dri-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH 3/3] vmwgfx: Only allow 64x64 cursors
From: Jakob Bornecrantz ja...@vmware.com Snooping code expects this to be the case. Signed-off-by: Jakob Bornecrantz ja...@vmware.com Reviewed-by: Thomas Hellstrom thellst...@vmware.com --- drivers/gpu/drm/vmwgfx/vmwgfx_kms.c |4 1 files changed, 4 insertions(+), 0 deletions(-) diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c index 40c7e61..880e285 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c @@ -105,6 +105,10 @@ int vmw_du_crtc_cursor_set(struct drm_crtc *crtc, struct drm_file *file_priv, struct vmw_dma_buffer *dmabuf = NULL; int ret; + /* A lot of the code assumes this */ + if (handle (width != 64 || height != 64)) + return -EINVAL; + if (handle) { ret = vmw_user_surface_lookup_handle(dev_priv, tfile, handle, surface); -- 1.7.4.4 ___ dri-devel mailing list dri-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/dri-devel
Re: [PATCH 1/5] drm: add plane support
2011년 11월 9일 수요일에 Jesse Barnesjbar...@virtuousgeek.org님이 작성: Planes are a bit like half-CRTCs. They have a location and fb, but don't drive outputs directly. Add support for handling them to the core KMS code. Acked-by: Alan Cox a...@lxorguk.ukuu.org.uk Reviewed-by: Rob Clark rob.cl...@linaro.org Reviewed-by: Daniel Vetter daniel.vet...@ffwll.ch Signed-off-by: Jesse Barnes jbar...@virtuousgeek.org Reviewed-by: Joonyoung Shim jy0922.s...@samsung.com Thanks. --- drivers/gpu/drm/drm_crtc.c | 257 +++- drivers/gpu/drm/drm_drv.c |3 + include/drm/drm.h |3 + include/drm/drm_crtc.h | 75 +- include/drm/drm_mode.h | 33 ++ 5 files changed, 368 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c index fe738f0..804ef12 100644 --- a/drivers/gpu/drm/drm_crtc.c +++ b/drivers/gpu/drm/drm_crtc.c @@ -321,6 +321,7 @@ void drm_framebuffer_cleanup(struct drm_framebuffer *fb) { struct drm_device *dev = fb-dev; struct drm_crtc *crtc; + struct drm_plane *plane; struct drm_mode_set set; int ret; @@ -337,6 +338,15 @@ void drm_framebuffer_cleanup(struct drm_framebuffer *fb) } } + list_for_each_entry(plane, dev-mode_config.plane_list, head) { + if (plane-fb == fb) { + /* should turn off the crtc */ + ret = plane-funcs-disable_plane(plane); + if (ret) + DRM_ERROR(failed to disable plane with busy fb\n); + } + } + drm_mode_object_put(dev, fb-base); list_del(fb-head); dev-mode_config.num_fb--; @@ -535,6 +545,50 @@ void drm_encoder_cleanup(struct drm_encoder *encoder) } EXPORT_SYMBOL(drm_encoder_cleanup); +int drm_plane_init(struct drm_device *dev, struct drm_plane *plane, + unsigned long possible_crtcs, + const struct drm_plane_funcs *funcs, + uint32_t *formats, uint32_t format_count) +{ + mutex_lock(dev-mode_config.mutex); + + plane-dev = dev; + drm_mode_object_get(dev, plane-base, DRM_MODE_OBJECT_PLANE); + plane-funcs = funcs; + plane-format_types = kmalloc(sizeof(uint32_t) * format_count, + GFP_KERNEL); + if (!plane-format_types) { + DRM_DEBUG_KMS(out of memory when allocating plane\n); + drm_mode_object_put(dev, plane-base); + return -ENOMEM; + } + + memcpy(plane-format_types, formats, format_count); + plane-format_count = format_count; + plane-possible_crtcs = possible_crtcs; + + list_add_tail(plane-head, dev-mode_config.plane_list); + dev-mode_config.num_plane++; + + mutex_unlock(dev-mode_config.mutex); + + return 0; +} +EXPORT_SYMBOL(drm_plane_init); + +void drm_plane_cleanup(struct drm_plane *plane) +{ + struct drm_device *dev = plane-dev; + + mutex_lock(dev-mode_config.mutex); + kfree(plane-format_types); + drm_mode_object_put(dev, plane-base); + list_del(plane-head); + dev-mode_config.num_plane--; + mutex_unlock(dev-mode_config.mutex); +} +EXPORT_SYMBOL(drm_plane_cleanup); + /** * drm_mode_create - create a new display mode * @dev: DRM device @@ -866,6 +920,7 @@ void drm_mode_config_init(struct drm_device *dev) INIT_LIST_HEAD(dev-mode_config.encoder_list); INIT_LIST_HEAD(dev-mode_config.property_list); INIT_LIST_HEAD(dev-mode_config.property_blob_list); + INIT_LIST_HEAD(dev-mode_config.plane_list); idr_init(dev-mode_config.crtc_idr); mutex_lock(dev-mode_config.mutex); @@ -942,6 +997,7 @@ void drm_mode_config_cleanup(struct drm_device *dev) struct drm_encoder *encoder, *enct; struct drm_framebuffer *fb, *fbt; struct drm_property *property, *pt; + struct drm_plane *plane, *plt; list_for_each_entry_safe(encoder, enct, dev-mode_config.encoder_list, head) { @@ -966,6 +1022,10 @@ void drm_mode_config_cleanup(struct drm_device *dev) crtc-funcs-destroy(crtc); } + list_for_each_entry_safe(plane, plt, dev-mode_config.plane_list, +head) { + plane-funcs-destroy(plane); + } } EXPORT_SYMBOL(drm_mode_config_cleanup); @@ -1466,6 +1526,197 @@ out: } /** + * drm_mode_getplane_res - get plane info + * @dev: DRM device + * @data: ioctl data + * @file_priv: DRM file info + * + * Return an plane count and set of IDs. + */ +int drm_mode_getplane_res(struct drm_device *dev, void *data, + struct drm_file *file_priv) +{ + struct drm_mode_get_plane_res *plane_resp = data; + struct
Re: Linux 3.2-rc1
On Wed, Nov 09, 2011 at 03:40:19PM +0800, Takashi Iwai wrote: At Tue, 8 Nov 2011 12:23:30 -0800, Linus Torvalds wrote: Hmm, I don't know what caused this to trigger, but I'm adding both the i915 people and the HDA people to the cc, and they can fight to the death about this in the HDMI Thunderdome. It must be the new addition of ELD-passing code. Yes, it's my fault. Fengguang, can the drm or i915 driver check whether ELD is changed or not? Writing ELD at each time even when unchanged confuses the audio side, as if the monitor is hotplugged. It's sure possible to mask out the extra events. I'll work out a patch tomorrow. Guys: One.. Two.. Three.. FIGHT! Round two! Three to fight! Thanks, Fengguang On Tue, Nov 8, 2011 at 6:55 AM, Nick Bowler nbow...@elliptictech.com wrote: Mode switches are very noisy on an Intel G45 in 3.2-rc1: HDMI hot plug event: Codec=3 Pin=3 Presence_Detect=1 ELD_Valid=1 HDMI status: Codec=3 Pin=3 Presence_Detect=1 ELD_Valid=1 HDMI: detected monitor W2253 at connection type HDMI HDMI: available speakers: FL/FR HDMI: supports coding type LPCM: channels = 2, rates = 32000 44100 48000, bits = 16 20 24 These lines get printed every single switch; previously only a single line was printed once at boot (the HDMI status line). Cheers, -- Nick Bowler, Elliptic Technologies (http://www.elliptictech.com/) ___ dri-devel mailing list dri-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/dri-devel
Re: [PATCH 2/2] drm: add an fb creation ioctl that takes a pixel format
Hello, all. I am trying to implement multi planer using your plane patch and I think it's good but I am still warried about that drm_mode_fb_cmd2 structure has only one handle. I know this handle is sent to framebuffer module to create new framebuffer. and the framebuffer would cover entire a image. as you know, the image could be consisted of one more planes. so I think now drm_mode_fb_cmd2 structure doesn't support multi planer because it has only one handle. with update_plane callback, a buffer of the framebuffer would be set to a hardware overlay. how we could set two planes or three planes to the hardware overlay? but there might be my missing point so please give me any comments. in addition, have you been looked into gem flink and open functions for memory sharing between processes? gem object basically has one buffer so we can't modify it because of compatibility. so I think it's right way that gem object manages only one buffer. for such a reason, maybe drm_mode_fb_cmd2 structure should include one more handles and plane count. each handle has a gem object to one plane and plane count means how many planes are requested and when update_plane callback is called by setplane(), we could set them of the specific framebuffer to a hardware overlay. another one, and also I have tried to implement the way sharing the memory between v4l2 based drivers and drm based drivers through application and this works fine. this feature had been introduced by v4l2 framework as user ptr. my way also is similar to it. the difference is that application could get new gem handle from specific gem framework of kernel side if user application requests user ptr import with the user space address(mmaped memory). the new gem handle means a gem object to the memory mapped to the user space address. this way makes different applications to be possible to share the memory between v4l2 based driver and drm based driver. and also this feature is considered for IOMMU so it would support non continuous memory also. I will introduce this feature soon. Thank you, Inki Dae. 2011/11/9 Jesse Barnes jbar...@virtuousgeek.org: To properly support the various plane formats supported by different hardware, the kernel must know the pixel format of a framebuffer object. So add a new ioctl taking a format argument corresponding to a fourcc name from videodev2.h. Implement the fb creation hooks in terms of the new mode_fb_cmd2 using helpers where the old bpp/depth values are needed. Acked-by: Alan Cox a...@lxorguk.ukuu.org.uk Reviewed-by: Rob Clark rob.cl...@linaro.org Signed-off-by: Jesse Barnes jbar...@virtuousgeek.org --- drivers/gpu/drm/drm_crtc.c | 108 +++- drivers/gpu/drm/drm_crtc_helper.c | 50 - drivers/gpu/drm/drm_drv.c | 1 + drivers/gpu/drm/i915/intel_display.c | 36 +- drivers/gpu/drm/i915/intel_drv.h | 2 +- drivers/gpu/drm/i915/intel_fb.c | 11 ++-- drivers/gpu/drm/nouveau/nouveau_display.c | 4 +- drivers/gpu/drm/nouveau/nouveau_fb.h | 2 +- drivers/gpu/drm/nouveau/nouveau_fbcon.c | 13 ++-- drivers/gpu/drm/radeon/radeon_display.c | 4 +- drivers/gpu/drm/radeon/radeon_fb.c | 18 +++-- drivers/gpu/drm/radeon/radeon_mode.h | 2 +- drivers/gpu/drm/vmwgfx/vmwgfx_kms.c | 22 -- drivers/gpu/drm/vmwgfx/vmwgfx_kms.h | 1 + drivers/staging/gma500/framebuffer.c | 2 +- include/drm/drm.h | 1 + include/drm/drm_crtc.h | 7 ++- include/drm/drm_crtc_helper.h | 4 +- include/drm/drm_mode.h | 28 +++- include/linux/videodev2.h | 1 + 20 files changed, 256 insertions(+), 61 deletions(-) diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c index 804ef12..39cccb4 100644 --- a/drivers/gpu/drm/drm_crtc.c +++ b/drivers/gpu/drm/drm_crtc.c @@ -1910,6 +1910,42 @@ out: return ret; } +/* Original addfb only supported RGB formats, so figure out which one */ +uint32_t drm_mode_legacy_fb_format(uint32_t bpp, uint32_t depth) +{ + uint32_t fmt; + + switch (bpp) { + case 8: + fmt = V4L2_PIX_FMT_RGB332; + break; + case 16: + if (depth == 15) + fmt = V4L2_PIX_FMT_RGB555; + else + fmt = V4L2_PIX_FMT_RGB565; + break; + case 24: + fmt = V4L2_PIX_FMT_RGB24; + break; + case 32: + if (depth == 24) + fmt = V4L2_PIX_FMT_RGB24; + else if (depth == 30) + fmt = V4L2_PIX_FMT_INTC_RGB30; + else + fmt = V4L2_PIX_FMT_RGB32; + break; + default: + DRM_ERROR(bad bpp, assuming RGB24
Re: [PATCH 2/2] drm: add an fb creation ioctl that takes a pixel format
On Wed, Nov 9, 2011 at 7:25 AM, InKi Dae daei...@gmail.com wrote: Hello, all. I am trying to implement multi planer using your plane patch and I think it's good but I am still warried about that drm_mode_fb_cmd2 structure has only one handle. I know this handle is sent to framebuffer module to create new framebuffer. and the framebuffer would cover entire a image. as you know, the image could be consisted of one more planes. so I think now drm_mode_fb_cmd2 structure doesn't support multi planer because it has only one handle. with update_plane callback, a buffer of the framebuffer would be set to a hardware overlay. how we could set two planes or three planes to the hardware overlay? but there might be my missing point so please give me any comments. in addition, have you been looked into gem flink and open functions for memory sharing between processes? gem object basically has one buffer so we can't modify it because of compatibility. so I think it's right way that gem object manages only one buffer. for such a reason, maybe drm_mode_fb_cmd2 structure should include one more handles and plane count. each handle has a gem object to one plane and plane count means how many planes are requested and when update_plane callback is called by setplane(), we could set them of the specific framebuffer to a hardware overlay. The current plan is to add a 3rd ioctl, for adding multi-planar fb.. I guess it is a good thing that I'm not the only one who wants this :-) another one, and also I have tried to implement the way sharing the memory between v4l2 based drivers and drm based drivers through application and this works fine. this feature had been introduced by v4l2 framework as user ptr. my way also is similar to it. the difference is that application could get new gem handle from specific gem framework of kernel side if user application requests user ptr import with the user space address(mmaped memory). the new gem handle means a gem object to the memory mapped to the user space address. this way makes different applications to be possible to share the memory between v4l2 based driver and drm based driver. and also this feature is considered for IOMMU so it would support non continuous memory also. I will introduce this feature soon. btw, there was an RFC a little while back for dmabuf buffer sharing mechanism.. the idea would be to export a (for example) GEM buffer to a dmabuf handle which could be passed in to other devices, including for example v4l2 (although without necessarily requiring a userspace mapping).. http://www.spinics.net/lists/dri-devel/msg15077.html It sounds like you are looking for a similar thing.. BR, -R Thank you, Inki Dae. 2011/11/9 Jesse Barnes jbar...@virtuousgeek.org: To properly support the various plane formats supported by different hardware, the kernel must know the pixel format of a framebuffer object. So add a new ioctl taking a format argument corresponding to a fourcc name from videodev2.h. Implement the fb creation hooks in terms of the new mode_fb_cmd2 using helpers where the old bpp/depth values are needed. Acked-by: Alan Cox a...@lxorguk.ukuu.org.uk Reviewed-by: Rob Clark rob.cl...@linaro.org Signed-off-by: Jesse Barnes jbar...@virtuousgeek.org --- drivers/gpu/drm/drm_crtc.c | 108 +++- drivers/gpu/drm/drm_crtc_helper.c | 50 - drivers/gpu/drm/drm_drv.c | 1 + drivers/gpu/drm/i915/intel_display.c | 36 +- drivers/gpu/drm/i915/intel_drv.h | 2 +- drivers/gpu/drm/i915/intel_fb.c | 11 ++-- drivers/gpu/drm/nouveau/nouveau_display.c | 4 +- drivers/gpu/drm/nouveau/nouveau_fb.h | 2 +- drivers/gpu/drm/nouveau/nouveau_fbcon.c | 13 ++-- drivers/gpu/drm/radeon/radeon_display.c | 4 +- drivers/gpu/drm/radeon/radeon_fb.c | 18 +++-- drivers/gpu/drm/radeon/radeon_mode.h | 2 +- drivers/gpu/drm/vmwgfx/vmwgfx_kms.c | 22 -- drivers/gpu/drm/vmwgfx/vmwgfx_kms.h | 1 + drivers/staging/gma500/framebuffer.c | 2 +- include/drm/drm.h | 1 + include/drm/drm_crtc.h | 7 ++- include/drm/drm_crtc_helper.h | 4 +- include/drm/drm_mode.h | 28 +++- include/linux/videodev2.h | 1 + 20 files changed, 256 insertions(+), 61 deletions(-) diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c index 804ef12..39cccb4 100644 --- a/drivers/gpu/drm/drm_crtc.c +++ b/drivers/gpu/drm/drm_crtc.c @@ -1910,6 +1910,42 @@ out: return ret; } +/* Original addfb only supported RGB formats, so figure out which one */ +uint32_t drm_mode_legacy_fb_format(uint32_t bpp, uint32_t depth) +{ + uint32_t fmt; + + switch (bpp) { + case 8: + fmt = V4L2_PIX_FMT_RGB332; + break;
[Bug 27314] displayport link training fails on certain panels (channel equalization fails)
https://bugs.freedesktop.org/show_bug.cgi?id=27314 --- Comment #59 from Alex Deucher ag...@yahoo.com 2011-11-09 06:44:37 PST --- (In reply to comment #57) Created attachment 53309 [details] xorg log with the ati driver in fedora16 I have just installed fedora 16 on an imac11,1, and I still have the same problem. I have attached the xorg log, let me know if there is anything else I could do to help. I checked that the patch pointed by Comment 55 is include in the linux 3.1 shipping with fedora. I am going to try the current linus tree and let you know if that helps. Why are you using UMS? All of the relevant fixes have been in KMS. -- Configure bugmail: https://bugs.freedesktop.org/userprefs.cgi?tab=email --- You are receiving this mail because: --- You are the assignee for the bug. ___ dri-devel mailing list dri-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/dri-devel
[Bug 28426] hardware cursor corruption with radeon+kms
https://bugs.freedesktop.org/show_bug.cgi?id=28426 --- Comment #11 from Jürg Billeter j...@bitron.ch 2011-11-09 08:51:09 PST --- My Linux 3.1 system has been running for over 6 days now without issues. Seems like it may finally be fixed for good :) Thanks! -- Configure bugmail: https://bugs.freedesktop.org/userprefs.cgi?tab=email --- You are receiving this mail because: --- You are the assignee for the bug. ___ dri-devel mailing list dri-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/dri-devel
[Bug 42678] Dual Screen Monitor Gnome-shell 3 hard lock ups - ATI open source Radeon
https://bugs.freedesktop.org/show_bug.cgi?id=42678 --- Comment #13 from Filip wat...@gmail.com 2011-11-09 10:56:34 PST --- So, after I ran the following on my system: sudo sh /usr/share/ati/fglrx-uninstall.sh sudo apt-get remove --purge fglrx fglrx_* fglrx-amdcccle* fglrx-dev* sudo apt-get remove --purge xserver-xorg-video-ati xserver-xorg-video-radeon sudo apt-get install xserver-xorg-video-ati sudo apt-get install --reinstall libgl1-mesa-glx:amd64 libgl1-mesa-glx:i386 libgl1-mesa-dri xserver-xorg-core sudo mv /etc/X11/xorg.conf /etc/X11/xorg.conf.backup sudo rm -rf /etc/ati I still get the occasional hard freeze (the frequency was reduced to 2 - 4 times a day, which is a lot better than it was before). Is it possible that the old fglrx driver touched some other libraries which I need to install? if yes, which one would those be? As a next step, I will try the option per Xorg config -- Configure bugmail: https://bugs.freedesktop.org/userprefs.cgi?tab=email --- You are receiving this mail because: --- You are the assignee for the bug. ___ dri-devel mailing list dri-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/dri-devel
ttm: merge ttm_backend ttm_tt, introduce ttm dma allocator
So i did an overhaul of ttm_memory, i believe the simplification i did make sense. See patch 5 for a longer explanation. Thomas with the ttm_memory change the allocation of pages won't happen if the accounting report that we are going over the limit and bo shrinker failed to free any memory to make room. The handling of dma32 zone is done as post pass of ttm memory accounting. Regarding the pagefault comment i removed, it doesn't make sense anymore because now we populate the whole page table in one shot. So there is no more prefaulting few pages but a full prefaulting. Thought i can add a comment stating that if you like. For the ttm_tt_dma struct to hold page allocator specific informations i think it can be done as an followup patch but if you prefer to have that in this patchset let me know i will respin with such changes. I am in the process of retesting this whole serie and especialy the while memory accounting. Cheers, Jerome ___ dri-devel mailing list dri-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH 01/13] drm/ttm: remove userspace backed ttm object support
From: Jerome Glisse jgli...@redhat.com This was never use in none of the driver, properly using userspace page for bo would need more code (vma interaction mostly). Removing this dead code in preparation of ttm_tt backend merge. Signed-off-by: Jerome Glisse jgli...@redhat.com Reviewed-by: Konrad Rzeszutek Wilk konrad.w...@oracle.com Reviewed-by: Thomas Hellstrom thellst...@vmware.com --- drivers/gpu/drm/ttm/ttm_bo.c| 22 drivers/gpu/drm/ttm/ttm_tt.c| 105 +-- include/drm/ttm/ttm_bo_api.h|5 -- include/drm/ttm/ttm_bo_driver.h | 24 - 4 files changed, 1 insertions(+), 155 deletions(-) diff --git a/drivers/gpu/drm/ttm/ttm_bo.c b/drivers/gpu/drm/ttm/ttm_bo.c index 617b646..4bde335 100644 --- a/drivers/gpu/drm/ttm/ttm_bo.c +++ b/drivers/gpu/drm/ttm/ttm_bo.c @@ -342,22 +342,6 @@ static int ttm_bo_add_ttm(struct ttm_buffer_object *bo, bool zero_alloc) if (unlikely(bo-ttm == NULL)) ret = -ENOMEM; break; - case ttm_bo_type_user: - bo-ttm = ttm_tt_create(bdev, bo-num_pages PAGE_SHIFT, - page_flags | TTM_PAGE_FLAG_USER, - glob-dummy_read_page); - if (unlikely(bo-ttm == NULL)) { - ret = -ENOMEM; - break; - } - - ret = ttm_tt_set_user(bo-ttm, current, - bo-buffer_start, bo-num_pages); - if (unlikely(ret != 0)) { - ttm_tt_destroy(bo-ttm); - bo-ttm = NULL; - } - break; default: printk(KERN_ERR TTM_PFX Illegal buffer object type\n); ret = -EINVAL; @@ -907,16 +891,12 @@ static uint32_t ttm_bo_select_caching(struct ttm_mem_type_manager *man, } static bool ttm_bo_mt_compatible(struct ttm_mem_type_manager *man, -bool disallow_fixed, uint32_t mem_type, uint32_t proposed_placement, uint32_t *masked_placement) { uint32_t cur_flags = ttm_bo_type_flags(mem_type); - if ((man-flags TTM_MEMTYPE_FLAG_FIXED) disallow_fixed) - return false; - if ((cur_flags proposed_placement TTM_PL_MASK_MEM) == 0) return false; @@ -961,7 +941,6 @@ int ttm_bo_mem_space(struct ttm_buffer_object *bo, man = bdev-man[mem_type]; type_ok = ttm_bo_mt_compatible(man, - bo-type == ttm_bo_type_user, mem_type, placement-placement[i], cur_flags); @@ -1009,7 +988,6 @@ int ttm_bo_mem_space(struct ttm_buffer_object *bo, if (!man-has_type) continue; if (!ttm_bo_mt_compatible(man, - bo-type == ttm_bo_type_user, mem_type, placement-busy_placement[i], cur_flags)) diff --git a/drivers/gpu/drm/ttm/ttm_tt.c b/drivers/gpu/drm/ttm/ttm_tt.c index 58c271e..82a1161 100644 --- a/drivers/gpu/drm/ttm/ttm_tt.c +++ b/drivers/gpu/drm/ttm/ttm_tt.c @@ -62,43 +62,6 @@ static void ttm_tt_free_page_directory(struct ttm_tt *ttm) ttm-dma_address = NULL; } -static void ttm_tt_free_user_pages(struct ttm_tt *ttm) -{ - int write; - int dirty; - struct page *page; - int i; - struct ttm_backend *be = ttm-be; - - BUG_ON(!(ttm-page_flags TTM_PAGE_FLAG_USER)); - write = ((ttm-page_flags TTM_PAGE_FLAG_WRITE) != 0); - dirty = ((ttm-page_flags TTM_PAGE_FLAG_USER_DIRTY) != 0); - - if (be) - be-func-clear(be); - - for (i = 0; i ttm-num_pages; ++i) { - page = ttm-pages[i]; - if (page == NULL) - continue; - - if (page == ttm-dummy_read_page) { - BUG_ON(write); - continue; - } - - if (write dirty !PageReserved(page)) - set_page_dirty_lock(page); - - ttm-pages[i] = NULL; - ttm_mem_global_free(ttm-glob-mem_glob, PAGE_SIZE); - put_page(page); - } - ttm-state = tt_unpopulated; - ttm-first_himem_page = ttm-num_pages; - ttm-last_lomem_page = -1; -} - static struct page *__ttm_tt_get_page(struct ttm_tt *ttm, int index) { struct page *p; @@ -325,10 +288,7 @@ void ttm_tt_destroy(struct ttm_tt *ttm) } if (likely(ttm-pages != NULL)) { - if
[PATCH 02/13] drm/ttm: remove split btw highmen and lowmem page
From: Jerome Glisse jgli...@redhat.com Split btw highmem and lowmem page was rendered useless by the pool code. Remove it. Note further cleanup would change the ttm page allocation helper to actualy take an array instead of relying on list this could drasticly reduce the number of function call in the common case of allocation whole buffer. Signed-off-by: Jerome Glisse jgli...@redhat.com Reviewed-by: Konrad Rzeszutek Wilk konrad.w...@oracle.com Reviewed-by: Thomas Hellstrom thellst...@vmware.com --- drivers/gpu/drm/ttm/ttm_tt.c| 11 ++- include/drm/ttm/ttm_bo_driver.h |7 --- 2 files changed, 2 insertions(+), 16 deletions(-) diff --git a/drivers/gpu/drm/ttm/ttm_tt.c b/drivers/gpu/drm/ttm/ttm_tt.c index 82a1161..8b7a6d0 100644 --- a/drivers/gpu/drm/ttm/ttm_tt.c +++ b/drivers/gpu/drm/ttm/ttm_tt.c @@ -69,7 +69,7 @@ static struct page *__ttm_tt_get_page(struct ttm_tt *ttm, int index) struct ttm_mem_global *mem_glob = ttm-glob-mem_glob; int ret; - while (NULL == (p = ttm-pages[index])) { + if (NULL == (p = ttm-pages[index])) { INIT_LIST_HEAD(h); @@ -85,10 +85,7 @@ static struct page *__ttm_tt_get_page(struct ttm_tt *ttm, int index) if (unlikely(ret != 0)) goto out_err; - if (PageHighMem(p)) - ttm-pages[--ttm-first_himem_page] = p; - else - ttm-pages[++ttm-last_lomem_page] = p; + ttm-pages[index] = p; } return p; out_err: @@ -270,8 +267,6 @@ static void ttm_tt_free_alloced_pages(struct ttm_tt *ttm) ttm_put_pages(h, count, ttm-page_flags, ttm-caching_state, ttm-dma_address); ttm-state = tt_unpopulated; - ttm-first_himem_page = ttm-num_pages; - ttm-last_lomem_page = -1; } void ttm_tt_destroy(struct ttm_tt *ttm) @@ -315,8 +310,6 @@ struct ttm_tt *ttm_tt_create(struct ttm_bo_device *bdev, unsigned long size, ttm-glob = bdev-glob; ttm-num_pages = (size + PAGE_SIZE - 1) PAGE_SHIFT; - ttm-first_himem_page = ttm-num_pages; - ttm-last_lomem_page = -1; ttm-caching_state = tt_cached; ttm-page_flags = page_flags; diff --git a/include/drm/ttm/ttm_bo_driver.h b/include/drm/ttm/ttm_bo_driver.h index 37527d6..9da182b 100644 --- a/include/drm/ttm/ttm_bo_driver.h +++ b/include/drm/ttm/ttm_bo_driver.h @@ -136,11 +136,6 @@ enum ttm_caching_state { * @dummy_read_page: Page to map where the ttm_tt page array contains a NULL * pointer. * @pages: Array of pages backing the data. - * @first_himem_page: Himem pages are put last in the page array, which - * enables us to run caching attribute changes on only the first part - * of the page array containing lomem pages. This is the index of the - * first himem page. - * @last_lomem_page: Index of the last lomem page in the page array. * @num_pages: Number of pages in the page array. * @bdev: Pointer to the current struct ttm_bo_device. * @be: Pointer to the ttm backend. @@ -157,8 +152,6 @@ enum ttm_caching_state { struct ttm_tt { struct page *dummy_read_page; struct page **pages; - long first_himem_page; - long last_lomem_page; uint32_t page_flags; unsigned long num_pages; struct ttm_bo_global *glob; -- 1.7.7.1 ___ dri-devel mailing list dri-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH 04/13] drm/ttm: use ttm put pages function to properly restore cache attribute
From: Jerome Glisse jgli...@redhat.com On failure we need to make sure the page we free has wb cache attribute. Do this pas call the proper ttm page helper function. Signed-off-by: Jerome Glisse jgli...@redhat.com Reviewed-by: Konrad Rzeszutek Wilk konrad.w...@oracle.com Reviewed-by: Thomas Hellstrom thellst...@vmware.com --- drivers/gpu/drm/ttm/ttm_tt.c |5 - 1 files changed, 4 insertions(+), 1 deletions(-) diff --git a/drivers/gpu/drm/ttm/ttm_tt.c b/drivers/gpu/drm/ttm/ttm_tt.c index 8b7a6d0..3fb4c6d 100644 --- a/drivers/gpu/drm/ttm/ttm_tt.c +++ b/drivers/gpu/drm/ttm/ttm_tt.c @@ -89,7 +89,10 @@ static struct page *__ttm_tt_get_page(struct ttm_tt *ttm, int index) } return p; out_err: - put_page(p); + INIT_LIST_HEAD(h); + list_add(p-lru, h); + ttm_put_pages(h, 1, ttm-page_flags, + ttm-caching_state, ttm-dma_address[index]); return NULL; } -- 1.7.7.1 ___ dri-devel mailing list dri-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH 05/13] drm/ttm: overhaul memory accounting
From: Jerome Glisse jgli...@redhat.com This is an overhaul of the ttm memory accounting. This tries to keep the same global behavior while removing the whole zone concept. It keeps a distrinction for dma32 so that we make sure that ttm don't starve the dma32 zone. There is 3 threshold for memory allocation : - max_mem is the maximum memory the whole ttm infrastructure is going to allow allocation for (exception of system process see below) - emer_mem is the maximum memory allowed for system process, this limit is to max_mem - swap_limit is the threshold at which point ttm will start to try to swap object because ttm is getting close the max_mem limit - swap_dma32_limit is the threshold at which point ttm will start swap object to try to reduce the pressure on the dma32 zone. Note that we don't specificly target object to swap to it might very well free more memory from highmem rather than from dma32 Accounting is done through used_mem used_dma32_mem, which sum give the total amount of memory actually accounted by ttm. Idea is that allocation will fail if (used_mem + used_dma32_mem) max_mem and if swapping fail to make enough room. The used_dma32_mem can be updated as a later stage, allowing to perform accounting test before allocating a whole batch of pages. Signed-off-by: Jerome Glisse jgli...@redhat.com --- drivers/gpu/drm/ttm/ttm_bo.c |2 +- drivers/gpu/drm/ttm/ttm_memory.c | 517 +- drivers/gpu/drm/ttm/ttm_object.c |3 +- drivers/gpu/drm/ttm/ttm_tt.c |2 +- drivers/gpu/drm/vmwgfx/vmwgfx_fence.c|8 +- drivers/gpu/drm/vmwgfx/vmwgfx_resource.c |8 +- include/drm/ttm/ttm_memory.h | 23 +- 7 files changed, 168 insertions(+), 395 deletions(-) diff --git a/drivers/gpu/drm/ttm/ttm_bo.c b/drivers/gpu/drm/ttm/ttm_bo.c index 4bde335..92712798 100644 --- a/drivers/gpu/drm/ttm/ttm_bo.c +++ b/drivers/gpu/drm/ttm/ttm_bo.c @@ -1252,7 +1252,7 @@ int ttm_bo_create(struct ttm_bo_device *bdev, size_t acc_size = ttm_bo_size(bdev-glob, (size + PAGE_SIZE - 1) PAGE_SHIFT); - ret = ttm_mem_global_alloc(mem_glob, acc_size, false, false); + ret = ttm_mem_global_alloc(mem_glob, acc_size, false); if (unlikely(ret != 0)) return ret; diff --git a/drivers/gpu/drm/ttm/ttm_memory.c b/drivers/gpu/drm/ttm/ttm_memory.c index e70ddd8..b550baf 100644 --- a/drivers/gpu/drm/ttm/ttm_memory.c +++ b/drivers/gpu/drm/ttm/ttm_memory.c @@ -35,21 +35,10 @@ #include linux/module.h #include linux/slab.h -#define TTM_MEMORY_ALLOC_RETRIES 4 - -struct ttm_mem_zone { - struct kobject kobj; - struct ttm_mem_global *glob; - const char *name; - uint64_t zone_mem; - uint64_t emer_mem; - uint64_t max_mem; - uint64_t swap_limit; - uint64_t used_mem; -}; +#define TTM_MEMORY_RETRIES 4 static struct attribute ttm_mem_sys = { - .name = zone_memory, + .name = memory, .mode = S_IRUGO }; static struct attribute ttm_mem_emer = { @@ -64,140 +53,141 @@ static struct attribute ttm_mem_swap = { .name = swap_limit, .mode = S_IRUGO | S_IWUSR }; +static struct attribute ttm_mem_dma32_swap = { + .name = swap_dma32_limit, + .mode = S_IRUGO | S_IWUSR +}; static struct attribute ttm_mem_used = { .name = used_memory, .mode = S_IRUGO }; +static struct attribute ttm_mem_dma32_used = { + .name = used_dma32_memory, + .mode = S_IRUGO +}; -static void ttm_mem_zone_kobj_release(struct kobject *kobj) -{ - struct ttm_mem_zone *zone = - container_of(kobj, struct ttm_mem_zone, kobj); - - printk(KERN_INFO TTM_PFX - Zone %7s: Used memory at exit: %llu kiB.\n, - zone-name, (unsigned long long) zone-used_mem 10); - kfree(zone); -} - -static ssize_t ttm_mem_zone_show(struct kobject *kobj, -struct attribute *attr, -char *buffer) +static ssize_t ttm_mem_global_show(struct kobject *kobj, + struct attribute *attr, + char *buffer) { - struct ttm_mem_zone *zone = - container_of(kobj, struct ttm_mem_zone, kobj); - uint64_t val = 0; + struct ttm_mem_global *glob = + container_of(kobj, struct ttm_mem_global, kobj); + unsigned long val = 0; - spin_lock(zone-glob-lock); + spin_lock(glob-lock); if (attr == ttm_mem_sys) - val = zone-zone_mem; + val = glob-mem; else if (attr == ttm_mem_emer) - val = zone-emer_mem; + val = glob-emer_mem; else if (attr == ttm_mem_max) - val = zone-max_mem; + val = glob-max_mem; else if (attr == ttm_mem_swap) - val = zone-swap_limit; + val = glob-swap_limit;
[PATCH 06/13] drm/ttm: convert page allocation to use page ptr array instead of list V4
From: Jerome Glisse jgli...@redhat.com Use the ttm_tt page ptr array for page allocation, move the list to array unwinding into the page allocation functions. V2 split the fix to use ttm put page as a separate fix properly fill pages array when TTM_PAGE_FLAG_ZERO_ALLOC is not set V3 Added back page_count()==1 check when freeing page V4 Rebase on top of memory accounting overhaul Signed-off-by: Jerome Glisse jgli...@redhat.com --- drivers/gpu/drm/ttm/ttm_memory.c | 47 +++-- drivers/gpu/drm/ttm/ttm_page_alloc.c | 90 -- drivers/gpu/drm/ttm/ttm_tt.c | 68 -- include/drm/ttm/ttm_memory.h | 13 +++-- include/drm/ttm/ttm_page_alloc.h | 17 +++--- 5 files changed, 120 insertions(+), 115 deletions(-) diff --git a/drivers/gpu/drm/ttm/ttm_memory.c b/drivers/gpu/drm/ttm/ttm_memory.c index b550baf..98f6899 100644 --- a/drivers/gpu/drm/ttm/ttm_memory.c +++ b/drivers/gpu/drm/ttm/ttm_memory.c @@ -326,32 +326,45 @@ int ttm_mem_global_alloc(struct ttm_mem_global *glob, } EXPORT_SYMBOL(ttm_mem_global_alloc); -int ttm_mem_global_alloc_page(struct ttm_mem_global *glob, - struct page *page, - bool no_wait) +int ttm_mem_global_alloc_pages(struct ttm_mem_global *glob, + unsigned npages, + bool no_wait) { - - if (ttm_mem_global_alloc(glob, PAGE_SIZE, no_wait)) + if (ttm_mem_global_alloc(glob, PAGE_SIZE * npages, no_wait)) return -ENOMEM; + ttm_check_swapping(glob); + return 0; +} + +void ttm_mem_global_account_pages(struct ttm_mem_global *glob, + struct page **pages, + unsigned npages) +{ + unsigned i; /* check if page is dma32 */ - if (page_to_pfn(page) 0x0010UL) { - spin_lock(glob-lock); - glob-used_mem -= PAGE_SIZE; - glob-used_dma32_mem += PAGE_SIZE; - spin_unlock(glob-lock); + spin_lock(glob-lock); + for (i = 0; i npages; i++) { + if (page_to_pfn(pages[i]) 0x0010UL) { + glob-used_mem -= PAGE_SIZE; + glob-used_dma32_mem += PAGE_SIZE; + } } - ttm_check_swapping(glob); - return 0; + spin_unlock(glob-lock); } -void ttm_mem_global_free_page(struct ttm_mem_global *glob, struct page *page) +void ttm_mem_global_free_pages(struct ttm_mem_global *glob, + struct page **pages, unsigned npages) { + unsigned i; + spin_lock(glob-lock); - if (page_to_pfn(page) 0x0010UL) { - glob-used_dma32_mem -= PAGE_SIZE; - } else { - glob-used_mem -= PAGE_SIZE; + for (i = 0; i npages; i++) { + if (page_to_pfn(pages[i]) 0x0010UL) { + glob-used_dma32_mem -= PAGE_SIZE; + } else { + glob-used_mem -= PAGE_SIZE; + } } spin_unlock(glob-lock); } diff --git a/drivers/gpu/drm/ttm/ttm_page_alloc.c b/drivers/gpu/drm/ttm/ttm_page_alloc.c index 727e93d..c4f18b9 100644 --- a/drivers/gpu/drm/ttm/ttm_page_alloc.c +++ b/drivers/gpu/drm/ttm/ttm_page_alloc.c @@ -619,8 +619,10 @@ static void ttm_page_pool_fill_locked(struct ttm_page_pool *pool, * @return count of pages still required to fulfill the request. */ static unsigned ttm_page_pool_get_pages(struct ttm_page_pool *pool, - struct list_head *pages, int ttm_flags, - enum ttm_caching_state cstate, unsigned count) + struct list_head *pages, + int ttm_flags, + enum ttm_caching_state cstate, + unsigned count) { unsigned long irq_flags; struct list_head *p; @@ -664,13 +666,14 @@ out: * On success pages list will hold count number of correctly * cached pages. */ -int ttm_get_pages(struct list_head *pages, int flags, - enum ttm_caching_state cstate, unsigned count, - dma_addr_t *dma_address) +int ttm_get_pages(struct page **pages, unsigned npages, int flags, + enum ttm_caching_state cstate, dma_addr_t *dma_address) { struct ttm_page_pool *pool = ttm_get_pool(flags, cstate); struct page *p = NULL; + struct list_head plist; gfp_t gfp_flags = GFP_USER; + unsigned count = 0; int r; /* set zero flag for page allocation if required */ @@ -684,94 +687,107 @@ int ttm_get_pages(struct list_head *pages, int flags, else gfp_flags |= GFP_HIGHUSER; - for (r = 0; r count; ++r) { - p = alloc_page(gfp_flags); - if
[PATCH 07/13] drm/ttm: test for dma_address array allocation failure
From: Jerome Glisse jgli...@redhat.com Signed-off-by: Jerome Glisse jgli...@redhat.com Reviewed-by: Konrad Rzeszutek Wilk konrad.w...@oracle.com Reviewed-by: Thomas Hellstrom thellst...@vmware.com --- drivers/gpu/drm/ttm/ttm_tt.c |2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/drivers/gpu/drm/ttm/ttm_tt.c b/drivers/gpu/drm/ttm/ttm_tt.c index 303bbba..2dab08b 100644 --- a/drivers/gpu/drm/ttm/ttm_tt.c +++ b/drivers/gpu/drm/ttm/ttm_tt.c @@ -293,7 +293,7 @@ struct ttm_tt *ttm_tt_create(struct ttm_bo_device *bdev, unsigned long size, ttm-dummy_read_page = dummy_read_page; ttm_tt_alloc_page_directory(ttm); - if (!ttm-pages) { + if (!ttm-pages || !ttm-dma_address) { ttm_tt_destroy(ttm); printk(KERN_ERR TTM_PFX Failed allocating page table\n); return NULL; -- 1.7.7.1 ___ dri-devel mailing list dri-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH 08/13] drm/ttm: merge ttm_backend and ttm_tt V2
From: Jerome Glisse jgli...@redhat.com ttm_backend will exist only and only with a ttm_tt, and ttm_tt will be of interesting use only when bind to a backend. Thus to avoid code data duplication btw the two merge them. V2 Rebase on top of memory accountign overhaul Signed-off-by: Jerome Glisse jgli...@redhat.com Reviewed-by: Konrad Rzeszutek Wilk konrad.w...@oracle.com --- drivers/gpu/drm/nouveau/nouveau_bo.c| 14 ++- drivers/gpu/drm/nouveau/nouveau_drv.h |5 +- drivers/gpu/drm/nouveau/nouveau_sgdma.c | 188 -- drivers/gpu/drm/radeon/radeon_ttm.c | 222 --- drivers/gpu/drm/ttm/ttm_agp_backend.c | 88 + drivers/gpu/drm/ttm/ttm_bo.c|9 +- drivers/gpu/drm/ttm/ttm_tt.c| 60 ++--- drivers/gpu/drm/vmwgfx/vmwgfx_buffer.c | 66 +++-- include/drm/ttm/ttm_bo_driver.h | 104 ++- 9 files changed, 295 insertions(+), 461 deletions(-) diff --git a/drivers/gpu/drm/nouveau/nouveau_bo.c b/drivers/gpu/drm/nouveau/nouveau_bo.c index 7226f41..b060fa4 100644 --- a/drivers/gpu/drm/nouveau/nouveau_bo.c +++ b/drivers/gpu/drm/nouveau/nouveau_bo.c @@ -343,8 +343,10 @@ nouveau_bo_wr32(struct nouveau_bo *nvbo, unsigned index, u32 val) *mem = val; } -static struct ttm_backend * -nouveau_bo_create_ttm_backend_entry(struct ttm_bo_device *bdev) +static struct ttm_tt * +nouveau_ttm_tt_create(struct ttm_bo_device *bdev, + unsigned long size, uint32_t page_flags, + struct page *dummy_read_page) { struct drm_nouveau_private *dev_priv = nouveau_bdev(bdev); struct drm_device *dev = dev_priv-dev; @@ -352,11 +354,13 @@ nouveau_bo_create_ttm_backend_entry(struct ttm_bo_device *bdev) switch (dev_priv-gart_info.type) { #if __OS_HAS_AGP case NOUVEAU_GART_AGP: - return ttm_agp_backend_init(bdev, dev-agp-bridge); + return ttm_agp_tt_create(bdev, dev-agp-bridge, +size, page_flags, dummy_read_page); #endif case NOUVEAU_GART_PDMA: case NOUVEAU_GART_HW: - return nouveau_sgdma_init_ttm(dev); + return nouveau_sgdma_create_ttm(bdev, size, page_flags, + dummy_read_page); default: NV_ERROR(dev, Unknown GART type %d\n, dev_priv-gart_info.type); @@ -1045,7 +1049,7 @@ nouveau_bo_fence(struct nouveau_bo *nvbo, struct nouveau_fence *fence) } struct ttm_bo_driver nouveau_bo_driver = { - .create_ttm_backend_entry = nouveau_bo_create_ttm_backend_entry, + .ttm_tt_create = nouveau_ttm_tt_create, .invalidate_caches = nouveau_bo_invalidate_caches, .init_mem_type = nouveau_bo_init_mem_type, .evict_flags = nouveau_bo_evict_flags, diff --git a/drivers/gpu/drm/nouveau/nouveau_drv.h b/drivers/gpu/drm/nouveau/nouveau_drv.h index 29837da..0c53e39 100644 --- a/drivers/gpu/drm/nouveau/nouveau_drv.h +++ b/drivers/gpu/drm/nouveau/nouveau_drv.h @@ -1000,7 +1000,10 @@ extern int nouveau_sgdma_init(struct drm_device *); extern void nouveau_sgdma_takedown(struct drm_device *); extern uint32_t nouveau_sgdma_get_physical(struct drm_device *, uint32_t offset); -extern struct ttm_backend *nouveau_sgdma_init_ttm(struct drm_device *); +extern struct ttm_tt *nouveau_sgdma_create_ttm(struct ttm_bo_device *bdev, + unsigned long size, + uint32_t page_flags, + struct page *dummy_read_page); /* nouveau_debugfs.c */ #if defined(CONFIG_DRM_NOUVEAU_DEBUG) diff --git a/drivers/gpu/drm/nouveau/nouveau_sgdma.c b/drivers/gpu/drm/nouveau/nouveau_sgdma.c index b75258a..bc2ab90 100644 --- a/drivers/gpu/drm/nouveau/nouveau_sgdma.c +++ b/drivers/gpu/drm/nouveau/nouveau_sgdma.c @@ -8,44 +8,23 @@ #define NV_CTXDMA_PAGE_MASK (NV_CTXDMA_PAGE_SIZE - 1) struct nouveau_sgdma_be { - struct ttm_backend backend; + struct ttm_tt ttm; struct drm_device *dev; - - dma_addr_t *pages; - unsigned nr_pages; - bool unmap_pages; - u64 offset; - bool bound; }; static int -nouveau_sgdma_populate(struct ttm_backend *be, unsigned long num_pages, - struct page **pages, struct page *dummy_read_page, - dma_addr_t *dma_addrs) +nouveau_sgdma_dma_map(struct ttm_tt *ttm) { - struct nouveau_sgdma_be *nvbe = (struct nouveau_sgdma_be *)be; + struct nouveau_sgdma_be *nvbe = (struct nouveau_sgdma_be *)ttm; struct drm_device *dev = nvbe-dev; int i; - NV_DEBUG(nvbe-dev, num_pages = %ld\n, num_pages); - - nvbe-pages = dma_addrs; - nvbe-nr_pages = num_pages; - nvbe-unmap_pages = true; - - /* this code path isn't
[PATCH 09/13] drm/ttm: introduce callback for ttm_tt populate unpopulate V2
From: Jerome Glisse jgli...@redhat.com Move the page allocation and freeing to driver callback and provide ttm code helper function for those. Most intrusive change, is the fact that we now only fully populate an object this simplify some of code designed around the page fault design. V2 Rebase on top of memory accounting overhaul Signed-off-by: Jerome Glisse jgli...@redhat.com Reviewed-by: Konrad Rzeszutek Wilk konrad.w...@oracle.com --- drivers/gpu/drm/nouveau/nouveau_bo.c |3 + drivers/gpu/drm/radeon/radeon_ttm.c|2 + drivers/gpu/drm/ttm/ttm_bo_util.c | 31 ++- drivers/gpu/drm/ttm/ttm_bo_vm.c| 13 +++-- drivers/gpu/drm/ttm/ttm_page_alloc.c | 45 + drivers/gpu/drm/ttm/ttm_tt.c | 86 ++-- drivers/gpu/drm/vmwgfx/vmwgfx_buffer.c |3 + include/drm/ttm/ttm_bo_driver.h| 41 +--- include/drm/ttm/ttm_page_alloc.h | 18 +++ 9 files changed, 123 insertions(+), 119 deletions(-) diff --git a/drivers/gpu/drm/nouveau/nouveau_bo.c b/drivers/gpu/drm/nouveau/nouveau_bo.c index b060fa4..7e5ca3f 100644 --- a/drivers/gpu/drm/nouveau/nouveau_bo.c +++ b/drivers/gpu/drm/nouveau/nouveau_bo.c @@ -28,6 +28,7 @@ */ #include drmP.h +#include ttm/ttm_page_alloc.h #include nouveau_drm.h #include nouveau_drv.h @@ -1050,6 +1051,8 @@ nouveau_bo_fence(struct nouveau_bo *nvbo, struct nouveau_fence *fence) struct ttm_bo_driver nouveau_bo_driver = { .ttm_tt_create = nouveau_ttm_tt_create, + .ttm_tt_populate = ttm_page_alloc_ttm_tt_populate, + .ttm_tt_unpopulate = ttm_page_alloc_ttm_tt_unpopulate, .invalidate_caches = nouveau_bo_invalidate_caches, .init_mem_type = nouveau_bo_init_mem_type, .evict_flags = nouveau_bo_evict_flags, diff --git a/drivers/gpu/drm/radeon/radeon_ttm.c b/drivers/gpu/drm/radeon/radeon_ttm.c index 53ff62b..490afce 100644 --- a/drivers/gpu/drm/radeon/radeon_ttm.c +++ b/drivers/gpu/drm/radeon/radeon_ttm.c @@ -584,6 +584,8 @@ struct ttm_tt *radeon_ttm_tt_create(struct ttm_bo_device *bdev, static struct ttm_bo_driver radeon_bo_driver = { .ttm_tt_create = radeon_ttm_tt_create, + .ttm_tt_populate = ttm_page_alloc_ttm_tt_populate, + .ttm_tt_unpopulate = ttm_page_alloc_ttm_tt_unpopulate, .invalidate_caches = radeon_invalidate_caches, .init_mem_type = radeon_init_mem_type, .evict_flags = radeon_evict_flags, diff --git a/drivers/gpu/drm/ttm/ttm_bo_util.c b/drivers/gpu/drm/ttm/ttm_bo_util.c index 082fcae..60f204d 100644 --- a/drivers/gpu/drm/ttm/ttm_bo_util.c +++ b/drivers/gpu/drm/ttm/ttm_bo_util.c @@ -244,7 +244,7 @@ static int ttm_copy_io_ttm_page(struct ttm_tt *ttm, void *src, unsigned long page, pgprot_t prot) { - struct page *d = ttm_tt_get_page(ttm, page); + struct page *d = ttm-pages[page]; void *dst; if (!d) @@ -281,7 +281,7 @@ static int ttm_copy_ttm_io_page(struct ttm_tt *ttm, void *dst, unsigned long page, pgprot_t prot) { - struct page *s = ttm_tt_get_page(ttm, page); + struct page *s = ttm-pages[page]; void *src; if (!s) @@ -342,6 +342,12 @@ int ttm_bo_move_memcpy(struct ttm_buffer_object *bo, if (old_iomap == NULL ttm == NULL) goto out2; + if (ttm-state == tt_unpopulated) { + ret = ttm-bdev-driver-ttm_tt_populate(ttm); + if (ret) + goto out1; + } + add = 0; dir = 1; @@ -502,10 +508,16 @@ static int ttm_bo_kmap_ttm(struct ttm_buffer_object *bo, { struct ttm_mem_reg *mem = bo-mem; pgprot_t prot; struct ttm_tt *ttm = bo-ttm; - struct page *d; - int i; + int ret; BUG_ON(!ttm); + + if (ttm-state == tt_unpopulated) { + ret = ttm-bdev-driver-ttm_tt_populate(ttm); + if (ret) + return ret; + } + if (num_pages == 1 (mem-placement TTM_PL_FLAG_CACHED)) { /* * We're mapping a single page, and the desired @@ -513,18 +525,9 @@ static int ttm_bo_kmap_ttm(struct ttm_buffer_object *bo, */ map-bo_kmap_type = ttm_bo_map_kmap; - map-page = ttm_tt_get_page(ttm, start_page); + map-page = ttm-pages[start_page]; map-virtual = kmap(map-page); } else { - /* -* Populate the part we're mapping; -*/ - for (i = start_page; i start_page + num_pages; ++i) { - d = ttm_tt_get_page(ttm, i); - if (!d) - return -ENOMEM; - } - /* * We need to use vmap to get the desired page protection * or to make
[PATCH 11/13] swiotlb: Expose swiotlb_nr_tlb function to modules
From: Konrad Rzeszutek Wilk konrad.w...@oracle.com As a mechanism to detect whether SWIOTLB is enabled or not. We also fix the spelling - it was swioltb instead of swiotlb. CC: FUJITA Tomonori fujita.tomon...@lab.ntt.co.jp [v1: Ripped out swiotlb_enabled] Signed-off-by: Konrad Rzeszutek Wilk konrad.w...@oracle.com --- drivers/xen/swiotlb-xen.c |2 +- include/linux/swiotlb.h |2 +- lib/swiotlb.c |5 +++-- 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/drivers/xen/swiotlb-xen.c b/drivers/xen/swiotlb-xen.c index c984768..c50fb0b 100644 --- a/drivers/xen/swiotlb-xen.c +++ b/drivers/xen/swiotlb-xen.c @@ -152,7 +152,7 @@ void __init xen_swiotlb_init(int verbose) char *m = NULL; unsigned int repeat = 3; - nr_tbl = swioltb_nr_tbl(); + nr_tbl = swiotlb_nr_tbl(); if (nr_tbl) xen_io_tlb_nslabs = nr_tbl; else { diff --git a/include/linux/swiotlb.h b/include/linux/swiotlb.h index 445702c..e872526 100644 --- a/include/linux/swiotlb.h +++ b/include/linux/swiotlb.h @@ -24,7 +24,7 @@ extern int swiotlb_force; extern void swiotlb_init(int verbose); extern void swiotlb_init_with_tbl(char *tlb, unsigned long nslabs, int verbose); -extern unsigned long swioltb_nr_tbl(void); +extern unsigned long swiotlb_nr_tbl(void); /* * Enumeration for sync targets diff --git a/lib/swiotlb.c b/lib/swiotlb.c index 99093b3..058935e 100644 --- a/lib/swiotlb.c +++ b/lib/swiotlb.c @@ -110,11 +110,11 @@ setup_io_tlb_npages(char *str) __setup(swiotlb=, setup_io_tlb_npages); /* make io_tlb_overflow tunable too? */ -unsigned long swioltb_nr_tbl(void) +unsigned long swiotlb_nr_tbl(void) { return io_tlb_nslabs; } - +EXPORT_SYMBOL_GPL(swiotlb_nr_tbl); /* Note that this doesn't work with highmem page */ static dma_addr_t swiotlb_virt_to_bus(struct device *hwdev, volatile void *address) @@ -321,6 +321,7 @@ void __init swiotlb_free(void) free_bootmem_late(__pa(io_tlb_start), PAGE_ALIGN(io_tlb_nslabs IO_TLB_SHIFT)); } + io_tlb_nslabs = 0; } static int is_swiotlb_buffer(phys_addr_t paddr) -- 1.7.7.1 ___ dri-devel mailing list dri-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH 12/13] drm/radeon/kms: Enable the TTM DMA pool if swiotlb is on V2
From: Konrad Rzeszutek Wilk konrad.w...@oracle.com With the exception that we do not handle the AGP case. We only deal with PCIe cards such as ATI ES1000 or HD3200 that have been detected to only do DMA up to 32-bits. V2 force dma32 if we fail to set bigger dma mask CC: Dave Airlie airl...@redhat.com CC: Alex Deucher alexdeuc...@gmail.com Signed-off-by: Konrad Rzeszutek Wilk konrad.w...@oracle.com Reviewed-by: Jerome Glisse jgli...@redhat.com --- drivers/gpu/drm/radeon/radeon.h|1 - drivers/gpu/drm/radeon/radeon_device.c |6 ++ drivers/gpu/drm/radeon/radeon_gart.c | 29 +--- drivers/gpu/drm/radeon/radeon_ttm.c| 83 +-- 4 files changed, 84 insertions(+), 35 deletions(-) diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h index e3170c7..63257ba 100644 --- a/drivers/gpu/drm/radeon/radeon.h +++ b/drivers/gpu/drm/radeon/radeon.h @@ -332,7 +332,6 @@ struct radeon_gart { union radeon_gart_table table; struct page **pages; dma_addr_t *pages_addr; - bool*ttm_alloced; boolready; }; diff --git a/drivers/gpu/drm/radeon/radeon_device.c b/drivers/gpu/drm/radeon/radeon_device.c index c33bc91..7c31321 100644 --- a/drivers/gpu/drm/radeon/radeon_device.c +++ b/drivers/gpu/drm/radeon/radeon_device.c @@ -765,8 +765,14 @@ int radeon_device_init(struct radeon_device *rdev, r = pci_set_dma_mask(rdev-pdev, DMA_BIT_MASK(dma_bits)); if (r) { rdev-need_dma32 = true; + dma_bits = 32; printk(KERN_WARNING radeon: No suitable DMA available.\n); } + r = pci_set_consistent_dma_mask(rdev-pdev, DMA_BIT_MASK(dma_bits)); + if (r) { + pci_set_consistent_dma_mask(rdev-pdev, DMA_BIT_MASK(32)); + printk(KERN_WARNING radeon: No coherent DMA available.\n); + } /* Registers mapping */ /* TODO: block userspace mapping of io register */ diff --git a/drivers/gpu/drm/radeon/radeon_gart.c b/drivers/gpu/drm/radeon/radeon_gart.c index fdc3a9a..18f496c 100644 --- a/drivers/gpu/drm/radeon/radeon_gart.c +++ b/drivers/gpu/drm/radeon/radeon_gart.c @@ -149,9 +149,6 @@ void radeon_gart_unbind(struct radeon_device *rdev, unsigned offset, p = t / (PAGE_SIZE / RADEON_GPU_PAGE_SIZE); for (i = 0; i pages; i++, p++) { if (rdev-gart.pages[p]) { - if (!rdev-gart.ttm_alloced[p]) - pci_unmap_page(rdev-pdev, rdev-gart.pages_addr[p], - PAGE_SIZE, PCI_DMA_BIDIRECTIONAL); rdev-gart.pages[p] = NULL; rdev-gart.pages_addr[p] = rdev-dummy_page.addr; page_base = rdev-gart.pages_addr[p]; @@ -181,23 +178,7 @@ int radeon_gart_bind(struct radeon_device *rdev, unsigned offset, p = t / (PAGE_SIZE / RADEON_GPU_PAGE_SIZE); for (i = 0; i pages; i++, p++) { - /* we reverted the patch using dma_addr in TTM for now but this -* code stops building on alpha so just comment it out for now */ - if (0) { /*dma_addr[i] != DMA_ERROR_CODE) */ - rdev-gart.ttm_alloced[p] = true; - rdev-gart.pages_addr[p] = dma_addr[i]; - } else { - /* we need to support large memory configurations */ - /* assume that unbind have already been call on the range */ - rdev-gart.pages_addr[p] = pci_map_page(rdev-pdev, pagelist[i], - 0, PAGE_SIZE, - PCI_DMA_BIDIRECTIONAL); - if (pci_dma_mapping_error(rdev-pdev, rdev-gart.pages_addr[p])) { - /* FIXME: failed to map page (return -ENOMEM?) */ - radeon_gart_unbind(rdev, offset, pages); - return -ENOMEM; - } - } + rdev-gart.pages_addr[p] = dma_addr[i]; rdev-gart.pages[p] = pagelist[i]; page_base = rdev-gart.pages_addr[p]; for (j = 0; j (PAGE_SIZE / RADEON_GPU_PAGE_SIZE); j++, t++) { @@ -259,12 +240,6 @@ int radeon_gart_init(struct radeon_device *rdev) radeon_gart_fini(rdev); return -ENOMEM; } - rdev-gart.ttm_alloced = kzalloc(sizeof(bool) * -rdev-gart.num_cpu_pages, GFP_KERNEL); - if (rdev-gart.ttm_alloced == NULL) { - radeon_gart_fini(rdev); - return -ENOMEM; - } /* set GART entry to point to the dummy page by default */ for (i = 0; i rdev-gart.num_cpu_pages; i++) {
[PATCH 13/13] drm/nouveau: enable the TTM DMA pool on 32-bit DMA only device V2
From: Konrad Rzeszutek Wilk konrad.w...@oracle.com If the card is capable of more than 32-bit, then use the default TTM page pool code which allocates from anywhere in the memory. Note: If the 'ttm.no_dma' parameter is set, the override is ignored and the default TTM pool is used. V2 use pci_set_consistent_dma_mask CC: Ben Skeggs bske...@redhat.com CC: Francisco Jerez curroje...@riseup.net CC: Dave Airlie airl...@redhat.com Signed-off-by: Konrad Rzeszutek Wilk konrad.w...@oracle.com Reviewed-by: Jerome Glisse jgli...@redhat.com --- drivers/gpu/drm/nouveau/nouveau_bo.c | 73 - drivers/gpu/drm/nouveau/nouveau_debugfs.c |1 + drivers/gpu/drm/nouveau/nouveau_mem.c |6 ++ drivers/gpu/drm/nouveau/nouveau_sgdma.c | 60 +--- 4 files changed, 79 insertions(+), 61 deletions(-) diff --git a/drivers/gpu/drm/nouveau/nouveau_bo.c b/drivers/gpu/drm/nouveau/nouveau_bo.c index 7e5ca3f..36234a7 100644 --- a/drivers/gpu/drm/nouveau/nouveau_bo.c +++ b/drivers/gpu/drm/nouveau/nouveau_bo.c @@ -1049,10 +1049,79 @@ nouveau_bo_fence(struct nouveau_bo *nvbo, struct nouveau_fence *fence) nouveau_fence_unref(old_fence); } +static int +nouveau_ttm_tt_populate(struct ttm_tt *ttm) +{ + struct drm_nouveau_private *dev_priv; + struct drm_device *dev; + unsigned i; + int r; + + if (ttm-state != tt_unpopulated) + return 0; + + dev_priv = nouveau_bdev(ttm-bdev); + dev = dev_priv-dev; + +#ifdef CONFIG_SWIOTLB + if ((dma_get_mask(dev-dev) = DMA_BIT_MASK(32)) swiotlb_nr_tbl()) { + return ttm_dma_populate(ttm, dev-dev); + } +#endif + + r = ttm_page_alloc_ttm_tt_populate(ttm); + if (r) { + return r; + } + + for (i = 0; i ttm-num_pages; i++) { + ttm-dma_address[i] = pci_map_page(dev-pdev, ttm-pages[i], + 0, PAGE_SIZE, + PCI_DMA_BIDIRECTIONAL); + if (pci_dma_mapping_error(dev-pdev, ttm-dma_address[i])) { + while (--i) { + pci_unmap_page(dev-pdev, ttm-dma_address[i], + PAGE_SIZE, PCI_DMA_BIDIRECTIONAL); + ttm-dma_address[i] = 0; + } + ttm_page_alloc_ttm_tt_unpopulate(ttm); + return -EFAULT; + } + } + return 0; +} + +static void +nouveau_ttm_tt_unpopulate(struct ttm_tt *ttm) +{ + struct drm_nouveau_private *dev_priv; + struct drm_device *dev; + unsigned i; + + dev_priv = nouveau_bdev(ttm-bdev); + dev = dev_priv-dev; + +#ifdef CONFIG_SWIOTLB + if ((dma_get_mask(dev-dev) = DMA_BIT_MASK(32)) swiotlb_nr_tbl()) { + ttm_dma_unpopulate(ttm, dev-dev); + return; + } +#endif + + for (i = 0; i ttm-num_pages; i++) { + if (ttm-dma_address[i]) { + pci_unmap_page(dev-pdev, ttm-dma_address[i], + PAGE_SIZE, PCI_DMA_BIDIRECTIONAL); + } + } + + ttm_page_alloc_ttm_tt_unpopulate(ttm); +} + struct ttm_bo_driver nouveau_bo_driver = { .ttm_tt_create = nouveau_ttm_tt_create, - .ttm_tt_populate = ttm_page_alloc_ttm_tt_populate, - .ttm_tt_unpopulate = ttm_page_alloc_ttm_tt_unpopulate, + .ttm_tt_populate = nouveau_ttm_tt_populate, + .ttm_tt_unpopulate = nouveau_ttm_tt_unpopulate, .invalidate_caches = nouveau_bo_invalidate_caches, .init_mem_type = nouveau_bo_init_mem_type, .evict_flags = nouveau_bo_evict_flags, diff --git a/drivers/gpu/drm/nouveau/nouveau_debugfs.c b/drivers/gpu/drm/nouveau/nouveau_debugfs.c index 8e15923..f52c2db 100644 --- a/drivers/gpu/drm/nouveau/nouveau_debugfs.c +++ b/drivers/gpu/drm/nouveau/nouveau_debugfs.c @@ -178,6 +178,7 @@ static struct drm_info_list nouveau_debugfs_list[] = { { memory, nouveau_debugfs_memory_info, 0, NULL }, { vbios.rom, nouveau_debugfs_vbios_image, 0, NULL }, { ttm_page_pool, ttm_page_alloc_debugfs, 0, NULL }, + { ttm_dma_page_pool, ttm_dma_page_alloc_debugfs, 0, NULL }, }; #define NOUVEAU_DEBUGFS_ENTRIES ARRAY_SIZE(nouveau_debugfs_list) diff --git a/drivers/gpu/drm/nouveau/nouveau_mem.c b/drivers/gpu/drm/nouveau/nouveau_mem.c index 36bec48..37fcaa2 100644 --- a/drivers/gpu/drm/nouveau/nouveau_mem.c +++ b/drivers/gpu/drm/nouveau/nouveau_mem.c @@ -407,6 +407,12 @@ nouveau_mem_vram_init(struct drm_device *dev) ret = pci_set_dma_mask(dev-pdev, DMA_BIT_MASK(dma_bits)); if (ret) return ret; + ret = pci_set_consistent_dma_mask(dev-pdev, DMA_BIT_MASK(dma_bits)); + if (ret) { + /* Reset to default value. */ + pci_set_consistent_dma_mask(dev-pdev,
Re: [PATCH v2] radeon: Make sure CS mutex is held across GPU reset.
On Tue, Nov 08, 2011 at 06:50:19PM +0100, Michel Dänzer wrote: From: Michel Dänzer michel.daen...@amd.com This was only the case if the GPU reset was triggered from the CS ioctl, otherwise other processes could happily enter the CS ioctl and wreak havoc during the GPU reset. This is a little complicated because the GPU reset can be triggered from the CS ioctl, in which case we're already holding the mutex, or from other call paths, in which case we need to lock the mutex. AFAICT the mutex API doesn't allow recursive locking or finding out the mutex owner, so we need to handle this with helper functions which allow recursive locking from the same process. Signed-off-by: Michel Dänzer michel.daen...@amd.com Beside not so important comment below Reviewed-by: Jerome Glisse jgli...@redhat.com --- v2: Use generic radeon_mutex_(un)lock helpers which allow recursive locking from the same process. Eliminates int vs. bool return type issue in v1, and maybe these helpers can be used similarly for more locks in the future. drivers/gpu/drm/radeon/radeon.h| 45 +++- drivers/gpu/drm/radeon/radeon_cs.c | 14 +- drivers/gpu/drm/radeon/radeon_device.c | 16 --- 3 files changed, 63 insertions(+), 12 deletions(-) diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h index c1e056b..671d5a5 100644 --- a/drivers/gpu/drm/radeon/radeon.h +++ b/drivers/gpu/drm/radeon/radeon.h @@ -1151,6 +1151,48 @@ struct r700_vram_scratch { volatile uint32_t *ptr; }; + +/* + * Mutex which allows recursive locking from the same process. + */ +struct radeon_mutex { + struct mutexmutex; + struct task_struct *owner; + int level; +}; + +static inline void radeon_mutex_init(struct radeon_mutex *mutex) +{ + mutex_init(mutex-mutex); + mutex-owner = NULL; + mutex-level = 0; +} + +static inline void radeon_mutex_lock(struct radeon_mutex *mutex) +{ + if (mutex_trylock(mutex-mutex)) { + /* The mutex was unlocked before, so it's ours now */ + mutex-owner = current; + } else if (mutex-owner != current) { + /* Another process locked the mutex, take it */ + mutex_lock(mutex-mutex); + mutex-owner = current; + } + /* Otherwise the mutex was already locked by this process */ + + mutex-level++; +} + +static inline void radeon_mutex_unlock(struct radeon_mutex *mutex) +{ + if (--mutex-level 0) + return; + + mutex-owner = NULL; + mutex_unlock(mutex-mutex); +} + + /* * Core structure, functions and helpers. */ @@ -1206,7 +1248,7 @@ struct radeon_device { struct radeon_gem gem; struct radeon_pmpm; uint32_tbios_scratch[RADEON_BIOS_NUM_SCRATCH]; - struct mutexcs_mutex; + struct radeon_mutex cs_mutex; struct radeon_wbwb; struct radeon_dummy_pagedummy_page; boolgpu_lockup; @@ -1245,6 +1287,7 @@ struct radeon_device { struct radeon_i2c_chan *i2c_bus[RADEON_MAX_I2C_BUS]; }; + Adding empty line ? int radeon_device_init(struct radeon_device *rdev, struct drm_device *ddev, struct pci_dev *pdev, diff --git a/drivers/gpu/drm/radeon/radeon_cs.c b/drivers/gpu/drm/radeon/radeon_cs.c index fae00c0..ccaa243 100644 --- a/drivers/gpu/drm/radeon/radeon_cs.c +++ b/drivers/gpu/drm/radeon/radeon_cs.c @@ -222,7 +222,7 @@ int radeon_cs_ioctl(struct drm_device *dev, void *data, struct drm_file *filp) struct radeon_cs_chunk *ib_chunk; int r; - mutex_lock(rdev-cs_mutex); + radeon_mutex_lock(rdev-cs_mutex); /* initialize parser */ memset(parser, 0, sizeof(struct radeon_cs_parser)); parser.filp = filp; @@ -233,14 +233,14 @@ int radeon_cs_ioctl(struct drm_device *dev, void *data, struct drm_file *filp) if (r) { DRM_ERROR(Failed to initialize parser !\n); radeon_cs_parser_fini(parser, r); - mutex_unlock(rdev-cs_mutex); + radeon_mutex_unlock(rdev-cs_mutex); return r; } r = radeon_ib_get(rdev, parser.ib); if (r) { DRM_ERROR(Failed to get ib !\n); radeon_cs_parser_fini(parser, r); - mutex_unlock(rdev-cs_mutex); + radeon_mutex_unlock(rdev-cs_mutex); return r; } r = radeon_cs_parser_relocs(parser); @@ -248,7 +248,7 @@ int radeon_cs_ioctl(struct drm_device *dev, void *data, struct drm_file *filp) if (r != -ERESTARTSYS) DRM_ERROR(Failed to parse relocation %d!\n, r); radeon_cs_parser_fini(parser, r); -
Re: ttm: merge ttm_backend ttm_tt, introduce ttm dma allocator
On 11/09/2011 09:22 PM, j.gli...@gmail.com wrote: So i did an overhaul of ttm_memory, i believe the simplification i did make sense. See patch 5 for a longer explanation. Thomas with the ttm_memory change the allocation of pages won't happen if the accounting report that we are going over the limit and bo shrinker failed to free any memory to make room. The handling of dma32 zone is done as post pass of ttm memory accounting. OK. I'll take a deeper look into this. Regarding the pagefault comment i removed, it doesn't make sense anymore because now we populate the whole page table in one shot. So there is no more prefaulting few pages but a full prefaulting. Thought i can add a comment stating that if you like. It's important that we distinguish between populating, which populates pages, and faulting, which add ptes pointing to those pages. Previously populating happened as a side effect of faulting, but now that populating is done in a single step, faulting (adding ptes) is still not. Usually a fault() handler adds a single pte, but TTM is different and tries to prefault more, but it is important that we only error on the first pte, so that's why the comment should stay. For the ttm_tt_dma struct to hold page allocator specific informations i think it can be done as an followup patch but if you prefer to have that in this patchset let me know i will respin with such changes. I'm fine with having it as a separate patchset as long as it gets done :). I am in the process of retesting this whole serie and especialy the while memory accounting. Cheers, Jerome /Thomas ___ dri-devel mailing list dri-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/dri-devel
Re: [PATCH 01/12] drm/ttm: remove userspace backed ttm object support
On Tue, Nov 08, 2011 at 08:22:48AM +0100, Thomas Hellstrom wrote: On 11/08/2011 12:40 AM, j.gli...@gmail.com wrote: From: Jerome Glissejgli...@redhat.com This was never use in none of the driver, properly using userspace page for bo would need more code (vma interaction mostly). Removing this dead code in preparation of ttm_tt backend merge. Jerome, I actually have using user-space TTMs in the pipe for vmwgfx, and it doesn't need more code (it was used by the psb driver). There are extra requirements, though: It only supports cached memory and user-space CPU-access needs to be done using existing VMAs. Anyway, I'll try to figure out a way to do this in the context of the unified tt / tt_backends. Issue, and i might be wrong here, is that you need to mark the user vma as reserved and you need to split the vma to covert only the portion you want. linux kernel a no helper for that. omap people use mlock on the range they want to use to make sure that page associated to the vma are lock and that the vma is split to only cover the range. I don't think it's safe/enough as userspace can unlock the vma in our back and things might fall apart at that point. My idea was to use mlock to split the vma and then set the reserved flags on the vma. This will forbid userspace to munlock. When memory is no longer needed you have to go back to locked flag and then munlock. Also we might want to do things with page of the vma, for instance if the object move to vram we might want to free those pages, but here i fear i need to take a closer look at linux mm to see what we can do safely on those page to not break any of the kernel assumptions on those pages. Anyway, from my inspection this whole things is fragile in regards of other mm activities that might happen. Cheers, Jerome ___ dri-devel mailing list dri-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/dri-devel
Re: ttm: merge ttm_backend ttm_tt, introduce ttm dma allocator
On Wed, Nov 09, 2011 at 09:25:20PM +0100, Thomas Hellstrom wrote: On 11/09/2011 09:22 PM, j.gli...@gmail.com wrote: So i did an overhaul of ttm_memory, i believe the simplification i did make sense. See patch 5 for a longer explanation. Thomas with the ttm_memory change the allocation of pages won't happen if the accounting report that we are going over the limit and bo shrinker failed to free any memory to make room. The handling of dma32 zone is done as post pass of ttm memory accounting. OK. I'll take a deeper look into this. Regarding the pagefault comment i removed, it doesn't make sense anymore because now we populate the whole page table in one shot. So there is no more prefaulting few pages but a full prefaulting. Thought i can add a comment stating that if you like. It's important that we distinguish between populating, which populates pages, and faulting, which add ptes pointing to those pages. Previously populating happened as a side effect of faulting, but now that populating is done in a single step, faulting (adding ptes) is still not. Usually a fault() handler adds a single pte, but TTM is different and tries to prefault more, but it is important that we only error on the first pte, so that's why the comment should stay. Well yes it only fill numprefault pte, but no error can happen in the prefault loop except for vm_insert_mixed failure, it's why i kept the report error only if it fails on the first page. I actually did a full pte populate at one point while working on that, dunno if that would make sense. For the ttm_tt_dma struct to hold page allocator specific informations i think it can be done as an followup patch but if you prefer to have that in this patchset let me know i will respin with such changes. I'm fine with having it as a separate patchset as long as it gets done :). I will spin a patch for that on top of the patchset. Cheers, Jerome ___ dri-devel mailing list dri-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH] drm: serialize access to list of debugfs files
Nouveau, when configured with debugfs, creates debugfs files for every channel, so structure holding list of files needs to be protected from simultaneous changes by multiple threads. Without this patch it's possible to hit kernel oops in drm_debugfs_remove_files just by running a couple of xterms with looped glxinfo. Signed-off-by: Marcin Slusarz marcin.slus...@gmail.com Reviewed-by: Daniel Vetter daniel.vet...@ffwll.ch --- Updated changelog. --- drivers/gpu/drm/drm_debugfs.c | 12 +--- drivers/gpu/drm/i915/i915_debugfs.c |5 - include/drm/drmP.h |4 +++- 3 files changed, 16 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/drm_debugfs.c b/drivers/gpu/drm/drm_debugfs.c index d067c12..1c7a1c0 100644 --- a/drivers/gpu/drm/drm_debugfs.c +++ b/drivers/gpu/drm/drm_debugfs.c @@ -118,7 +118,10 @@ int drm_debugfs_create_files(struct drm_info_list *files, int count, tmp-minor = minor; tmp-dent = ent; tmp-info_ent = files[i]; - list_add((tmp-list), (minor-debugfs_nodes.list)); + + mutex_lock(minor-debugfs_lock); + list_add(tmp-list, minor-debugfs_list); + mutex_unlock(minor-debugfs_lock); } return 0; @@ -146,7 +149,8 @@ int drm_debugfs_init(struct drm_minor *minor, int minor_id, char name[64]; int ret; - INIT_LIST_HEAD(minor-debugfs_nodes.list); + INIT_LIST_HEAD(minor-debugfs_list); + mutex_init(minor-debugfs_lock); sprintf(name, %d, minor_id); minor-debugfs_root = debugfs_create_dir(name, root); if (!minor-debugfs_root) { @@ -192,8 +196,9 @@ int drm_debugfs_remove_files(struct drm_info_list *files, int count, struct drm_info_node *tmp; int i; + mutex_lock(minor-debugfs_lock); for (i = 0; i count; i++) { - list_for_each_safe(pos, q, minor-debugfs_nodes.list) { + list_for_each_safe(pos, q, minor-debugfs_list) { tmp = list_entry(pos, struct drm_info_node, list); if (tmp-info_ent == files[i]) { debugfs_remove(tmp-dent); @@ -202,6 +207,7 @@ int drm_debugfs_remove_files(struct drm_info_list *files, int count, } } } + mutex_unlock(minor-debugfs_lock); return 0; } EXPORT_SYMBOL(drm_debugfs_remove_files); diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index d14b44e..4f40f1c 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c @@ -1506,7 +1506,10 @@ drm_add_fake_info_node(struct drm_minor *minor, node-minor = minor; node-dent = ent; node-info_ent = (void *) key; - list_add(node-list, minor-debugfs_nodes.list); + + mutex_lock(minor-debugfs_lock); + list_add(node-list, minor-debugfs_list); + mutex_unlock(minor-debugfs_lock); return 0; } diff --git a/include/drm/drmP.h b/include/drm/drmP.h index cf39949..1f9e951 100644 --- a/include/drm/drmP.h +++ b/include/drm/drmP.h @@ -990,7 +990,9 @@ struct drm_minor { struct proc_dir_entry *proc_root; /** proc directory entry */ struct drm_info_node proc_nodes; struct dentry *debugfs_root; - struct drm_info_node debugfs_nodes; + + struct list_head debugfs_list; + struct mutex debugfs_lock; /* Protects debugfs_list. */ struct drm_master *master; /* currently active master for this node */ struct list_head master_list; -- 1.7.7.2 ___ dri-devel mailing list dri-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/dri-devel
Isolate dma information from ttm_tt
This apply on top of the ttm_tt backend merge patchset. Cheers, Jerome ___ dri-devel mailing list dri-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH 14/14] drm/ttm: isolate dma data from ttm_tt
From: Jerome Glisse jgli...@redhat.com Move dma data to a superset ttm_dma_tt structure which herit from ttm_tt. This allow driver that don't use dma functionalities to not have to waste memory for it. Signed-off-by: Jerome Glisse jgli...@redhat.com --- drivers/gpu/drm/nouveau/nouveau_bo.c | 18 + drivers/gpu/drm/nouveau/nouveau_sgdma.c | 22 +++ drivers/gpu/drm/radeon/radeon_ttm.c | 43 +++--- drivers/gpu/drm/ttm/ttm_page_alloc.c | 10 +++--- drivers/gpu/drm/ttm/ttm_page_alloc_dma.c | 38 +++- drivers/gpu/drm/ttm/ttm_tt.c | 58 - drivers/gpu/drm/vmwgfx/vmwgfx_buffer.c |2 + include/drm/ttm/ttm_bo_driver.h | 31 +++- include/drm/ttm/ttm_page_alloc.h | 12 ++ 9 files changed, 155 insertions(+), 79 deletions(-) diff --git a/drivers/gpu/drm/nouveau/nouveau_bo.c b/drivers/gpu/drm/nouveau/nouveau_bo.c index 36234a7..df3f19c 100644 --- a/drivers/gpu/drm/nouveau/nouveau_bo.c +++ b/drivers/gpu/drm/nouveau/nouveau_bo.c @@ -1052,6 +1052,7 @@ nouveau_bo_fence(struct nouveau_bo *nvbo, struct nouveau_fence *fence) static int nouveau_ttm_tt_populate(struct ttm_tt *ttm) { + struct ttm_dma_tt *ttm_dma = (void *)ttm; struct drm_nouveau_private *dev_priv; struct drm_device *dev; unsigned i; @@ -1065,7 +1066,7 @@ nouveau_ttm_tt_populate(struct ttm_tt *ttm) #ifdef CONFIG_SWIOTLB if ((dma_get_mask(dev-dev) = DMA_BIT_MASK(32)) swiotlb_nr_tbl()) { - return ttm_dma_populate(ttm, dev-dev); + return ttm_dma_populate((void *)ttm, dev-dev); } #endif @@ -1075,14 +1076,14 @@ nouveau_ttm_tt_populate(struct ttm_tt *ttm) } for (i = 0; i ttm-num_pages; i++) { - ttm-dma_address[i] = pci_map_page(dev-pdev, ttm-pages[i], + ttm_dma-dma_address[i] = pci_map_page(dev-pdev, ttm-pages[i], 0, PAGE_SIZE, PCI_DMA_BIDIRECTIONAL); - if (pci_dma_mapping_error(dev-pdev, ttm-dma_address[i])) { + if (pci_dma_mapping_error(dev-pdev, ttm_dma-dma_address[i])) { while (--i) { - pci_unmap_page(dev-pdev, ttm-dma_address[i], + pci_unmap_page(dev-pdev, ttm_dma-dma_address[i], PAGE_SIZE, PCI_DMA_BIDIRECTIONAL); - ttm-dma_address[i] = 0; + ttm_dma-dma_address[i] = 0; } ttm_page_alloc_ttm_tt_unpopulate(ttm); return -EFAULT; @@ -1094,6 +1095,7 @@ nouveau_ttm_tt_populate(struct ttm_tt *ttm) static void nouveau_ttm_tt_unpopulate(struct ttm_tt *ttm) { + struct ttm_dma_tt *ttm_dma = (void *)ttm; struct drm_nouveau_private *dev_priv; struct drm_device *dev; unsigned i; @@ -1103,14 +1105,14 @@ nouveau_ttm_tt_unpopulate(struct ttm_tt *ttm) #ifdef CONFIG_SWIOTLB if ((dma_get_mask(dev-dev) = DMA_BIT_MASK(32)) swiotlb_nr_tbl()) { - ttm_dma_unpopulate(ttm, dev-dev); + ttm_dma_unpopulate((void *)ttm, dev-dev); return; } #endif for (i = 0; i ttm-num_pages; i++) { - if (ttm-dma_address[i]) { - pci_unmap_page(dev-pdev, ttm-dma_address[i], + if (ttm_dma-dma_address[i]) { + pci_unmap_page(dev-pdev, ttm_dma-dma_address[i], PAGE_SIZE, PCI_DMA_BIDIRECTIONAL); } } diff --git a/drivers/gpu/drm/nouveau/nouveau_sgdma.c b/drivers/gpu/drm/nouveau/nouveau_sgdma.c index ee1eb7c..47f245e 100644 --- a/drivers/gpu/drm/nouveau/nouveau_sgdma.c +++ b/drivers/gpu/drm/nouveau/nouveau_sgdma.c @@ -8,7 +8,10 @@ #define NV_CTXDMA_PAGE_MASK (NV_CTXDMA_PAGE_SIZE - 1) struct nouveau_sgdma_be { - struct ttm_tt ttm; + /* this has to be the first field so populate/unpopulated in +* nouve_bo.c works properly, otherwise have to move them here +*/ + struct ttm_dma_tt ttm; struct drm_device *dev; u64 offset; }; @@ -20,6 +23,7 @@ nouveau_sgdma_destroy(struct ttm_tt *ttm) if (ttm) { NV_DEBUG(nvbe-dev, \n); + ttm_dma_tt_fini(nvbe-ttm); kfree(nvbe); } } @@ -38,7 +42,7 @@ nv04_sgdma_bind(struct ttm_tt *ttm, struct ttm_mem_reg *mem) nvbe-offset = mem-start PAGE_SHIFT; pte = (nvbe-offset NV_CTXDMA_PAGE_SHIFT) + 2; for (i = 0; i ttm-num_pages; i++) { - dma_addr_t dma_offset = ttm-dma_address[i]; + dma_addr_t dma_offset = nvbe-ttm.dma_address[i]; uint32_t offset_l = lower_32_bits(dma_offset); for (j =