From 2b405ec0e1c4b4c490b95da7ac3c9934c7675da6 Mon Sep 17 00:00:00 2001 From: Jonathan Neuschäfer Date: Fri, 1 Jan 2021 22:18:17 +0100 Subject: drm/mipi-dbi: Switch to new kerneldoc syntax for named variable macro argument MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The syntax without dots is available since commit 43756e347f21 ("scripts/kernel-doc: Add support for named variable macro arguments"). The same HTML output is produced with and without this patch. Signed-off-by: Jonathan Neuschäfer Signed-off-by: Daniel Vetter Link: https://patchwork.freedesktop.org/patch/msgid/20210101211818.1023919-1-j.neuschaefer@gmx.net --- include/drm/drm_mipi_dbi.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'include') diff --git a/include/drm/drm_mipi_dbi.h b/include/drm/drm_mipi_dbi.h index c2827ceaba0d..f543d6e3e822 100644 --- a/include/drm/drm_mipi_dbi.h +++ b/include/drm/drm_mipi_dbi.h @@ -172,7 +172,7 @@ int mipi_dbi_buf_copy(void *dst, struct drm_framebuffer *fb, * mipi_dbi_command - MIPI DCS command with optional parameter(s) * @dbi: MIPI DBI structure * @cmd: Command - * @seq...: Optional parameter(s) + * @seq: Optional parameter(s) * * Send MIPI DCS command to the controller. Use mipi_dbi_command_read() for * get/read. -- cgit v1.2.3 From 8fbdbb66f8c10bb359ad20fff95628e5deac88f4 Mon Sep 17 00:00:00 2001 From: Darren Salt Date: Tue, 5 Jan 2021 14:44:01 +0100 Subject: PCI: Export pci_rebar_get_possible_sizes() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Export pci_rebar_get_possible_sizes() for use by modular drivers. Signed-off-by: Darren Salt Signed-off-by: Nirmoy Das Signed-off-by: Christian König Acked-by: Bjorn Helgaas Link: https://patchwork.kernel.org/project/dri-devel/patch/20210107175017.15893-2-nirmoy.das@amd.com --- drivers/pci/pci.c | 1 + drivers/pci/pci.h | 1 - include/linux/pci.h | 1 + 3 files changed, 2 insertions(+), 1 deletion(-) (limited to 'include') diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index b9fecc25d213..8d1aec39ecc8 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c @@ -3605,6 +3605,7 @@ u32 pci_rebar_get_possible_sizes(struct pci_dev *pdev, int bar) pci_read_config_dword(pdev, pos + PCI_REBAR_CAP, &cap); return (cap & PCI_REBAR_CAP_SIZES) >> 4; } +EXPORT_SYMBOL(pci_rebar_get_possible_sizes); /** * pci_rebar_get_current_size - get the current size of a BAR diff --git a/drivers/pci/pci.h b/drivers/pci/pci.h index 5c59365092fa..8f130f9531b3 100644 --- a/drivers/pci/pci.h +++ b/drivers/pci/pci.h @@ -630,7 +630,6 @@ int acpi_get_rc_resources(struct device *dev, const char *hid, u16 segment, struct resource *res); #endif -u32 pci_rebar_get_possible_sizes(struct pci_dev *pdev, int bar); int pci_rebar_get_current_size(struct pci_dev *pdev, int bar); int pci_rebar_set_size(struct pci_dev *pdev, int bar, int size); static inline u64 pci_rebar_size_to_bytes(int size) diff --git a/include/linux/pci.h b/include/linux/pci.h index b32126d26997..5f25a0ec48c1 100644 --- a/include/linux/pci.h +++ b/include/linux/pci.h @@ -1232,6 +1232,7 @@ void pci_update_resource(struct pci_dev *dev, int resno); int __must_check pci_assign_resource(struct pci_dev *dev, int i); int __must_check pci_reassign_resource(struct pci_dev *dev, int i, resource_size_t add_size, resource_size_t align); void pci_release_resource(struct pci_dev *dev, int resno); +u32 pci_rebar_get_possible_sizes(struct pci_dev *pdev, int bar); int __must_check pci_resize_resource(struct pci_dev *dev, int i, int size); int pci_select_bars(struct pci_dev *dev, unsigned long flags); bool pci_device_is_present(struct pci_dev *pdev); -- cgit v1.2.3 From 192f1bf7559e895d51f81c3976c5892c8b1e0601 Mon Sep 17 00:00:00 2001 From: Nirmoy Das Date: Thu, 7 Jan 2021 14:30:34 +0100 Subject: PCI: Add pci_rebar_bytes_to_size() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Users of pci_resize_resource() need a way to calculate BAR size from desired bytes. Add a helper function and export it so that modular drivers can use it. Signed-off-by: Darren Salt Signed-off-by: Christian König Signed-off-by: Nirmoy Das Acked-by: Bjorn Helgaas Link: https://patchwork.kernel.org/project/dri-devel/patch/20210107175017.15893-3-nirmoy.das@amd.com --- drivers/pci/pci.c | 2 +- include/linux/pci.h | 8 ++++++++ 2 files changed, 9 insertions(+), 1 deletion(-) (limited to 'include') diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index 8d1aec39ecc8..99ef2774b9d0 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c @@ -1644,7 +1644,7 @@ static void pci_restore_rebar_state(struct pci_dev *pdev) pci_read_config_dword(pdev, pos + PCI_REBAR_CTRL, &ctrl); bar_idx = ctrl & PCI_REBAR_CTRL_BAR_IDX; res = pdev->resource + bar_idx; - size = ilog2(resource_size(res)) - 20; + size = pci_rebar_bytes_to_size(resource_size(res)); ctrl &= ~PCI_REBAR_CTRL_BAR_SIZE; ctrl |= size << PCI_REBAR_CTRL_BAR_SHIFT; pci_write_config_dword(pdev, pos + PCI_REBAR_CTRL, ctrl); diff --git a/include/linux/pci.h b/include/linux/pci.h index 5f25a0ec48c1..53f4904ee83d 100644 --- a/include/linux/pci.h +++ b/include/linux/pci.h @@ -1232,6 +1232,14 @@ void pci_update_resource(struct pci_dev *dev, int resno); int __must_check pci_assign_resource(struct pci_dev *dev, int i); int __must_check pci_reassign_resource(struct pci_dev *dev, int i, resource_size_t add_size, resource_size_t align); void pci_release_resource(struct pci_dev *dev, int resno); +static inline int pci_rebar_bytes_to_size(u64 bytes) +{ + bytes = roundup_pow_of_two(bytes); + + /* Return BAR size as defined in the resizable BAR specification */ + return max(ilog2(bytes), 20) - 20; +} + u32 pci_rebar_get_possible_sizes(struct pci_dev *pdev, int bar); int __must_check pci_resize_resource(struct pci_dev *dev, int i, int size); int pci_select_bars(struct pci_dev *dev, unsigned long flags); -- cgit v1.2.3 From 7e60bdeb91ef7914a667be266ac0a0e6ea335475 Mon Sep 17 00:00:00 2001 From: Zhaoge Zhang Date: Tue, 12 Jan 2021 09:54:39 +0800 Subject: drm: Fix macro name DRM_MODE_PROP_OBJECT in code comment Signed-off-by: Zhaoge Zhang Signed-off-by: Daniel Vetter Link: https://patchwork.freedesktop.org/patch/msgid/1610416479-32736-1-git-send-email-zhangzhaoge@loongson.cn --- include/drm/drm_property.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'include') diff --git a/include/drm/drm_property.h b/include/drm/drm_property.h index 4a0a80d658c7..bbf5c1fdd7b0 100644 --- a/include/drm/drm_property.h +++ b/include/drm/drm_property.h @@ -114,7 +114,7 @@ struct drm_property { * by the property. Bitmask properties are created using * drm_property_create_bitmask(). * - * DRM_MODE_PROB_OBJECT + * DRM_MODE_PROP_OBJECT * Object properties are used to link modeset objects. This is used * extensively in the atomic support to create the display pipeline, * by linking &drm_framebuffer to &drm_plane, &drm_plane to -- cgit v1.2.3 From cc3283f8f41f741fbaef63d0503d8fb4a7919100 Mon Sep 17 00:00:00 2001 From: Simon Ser Date: Sun, 10 Jan 2021 13:51:03 +0100 Subject: drm/fourcc: fix Amlogic format modifier masks The comment says the layout and options use 8 bits, and the shift uses 8 bits. However the mask is 0xf, ie. 0b00001111 (4 bits). This could be surprising when introducing new layouts or options that take more than 4 bits, as this would silently drop the high bits. Make the masks consistent with the comment and the shift. Found when writing a drm_info patch [1]. [1]: https://github.com/ascent12/drm_info/pull/67 Signed-off-by: Simon Ser Fixes: d6528ec88309 ("drm/fourcc: Add modifier definitions for describing Amlogic Video Framebuffer Compression") Cc: Neil Armstrong Cc: Sam Ravnborg Cc: Kevin Hilman Cc: Daniel Vetter Acked-by: Neil Armstrong Link: https://patchwork.freedesktop.org/patch/msgid/20210110125103.15447-1-contact@emersion.fr --- include/uapi/drm/drm_fourcc.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'include') diff --git a/include/uapi/drm/drm_fourcc.h b/include/uapi/drm/drm_fourcc.h index 723c8e23ca87..5f42a14481bd 100644 --- a/include/uapi/drm/drm_fourcc.h +++ b/include/uapi/drm/drm_fourcc.h @@ -1036,9 +1036,9 @@ drm_fourcc_canonicalize_nvidia_format_mod(__u64 modifier) * Not all combinations are valid, and different SoCs may support different * combinations of layout and options. */ -#define __fourcc_mod_amlogic_layout_mask 0xf +#define __fourcc_mod_amlogic_layout_mask 0xff #define __fourcc_mod_amlogic_options_shift 8 -#define __fourcc_mod_amlogic_options_mask 0xf +#define __fourcc_mod_amlogic_options_mask 0xff #define DRM_FORMAT_MOD_AMLOGIC_FBC(__layout, __options) \ fourcc_mod_code(AMLOGIC, \ -- cgit v1.2.3 From ff28a9f8d3b4e2e6d07e37e0f5e15119ee4aff55 Mon Sep 17 00:00:00 2001 From: Thomas Zimmermann Date: Tue, 12 Jan 2021 09:10:30 +0100 Subject: drm: Inline AGP wrappers into their only callers MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The AGP wrapper functions serve no purpose. They used to handle builds that have CONFIG_AGP unset. But their callers are all in drm_agpsupport.c, which only gets build with CONFIG_AGP. v2: * clarify CONFIG_AGP in commit description (Daniel) Signed-off-by: Thomas Zimmermann Reviewed-by: Christian König Reviewed-by: Daniel Vetter Link: https://patchwork.freedesktop.org/patch/msgid/20210112081035.6882-2-tzimmermann@suse.de --- drivers/gpu/drm/drm_agpsupport.c | 12 ++++++------ drivers/gpu/drm/drm_memory.c | 18 ------------------ include/drm/drm_agpsupport.h | 18 ------------------ 3 files changed, 6 insertions(+), 42 deletions(-) (limited to 'include') diff --git a/drivers/gpu/drm/drm_agpsupport.c b/drivers/gpu/drm/drm_agpsupport.c index 4c7ad46fdd21..8b690ef306de 100644 --- a/drivers/gpu/drm/drm_agpsupport.c +++ b/drivers/gpu/drm/drm_agpsupport.c @@ -285,7 +285,7 @@ int drm_agp_unbind(struct drm_device *dev, struct drm_agp_binding *request) entry = drm_agp_lookup_entry(dev, request->handle); if (!entry || !entry->bound) return -EINVAL; - ret = drm_unbind_agp(entry->memory); + ret = agp_unbind_memory(entry->memory); if (ret == 0) entry->bound = 0; return ret; @@ -326,7 +326,7 @@ int drm_agp_bind(struct drm_device *dev, struct drm_agp_binding *request) if (!entry || entry->bound) return -EINVAL; page = DIV_ROUND_UP(request->offset, PAGE_SIZE); - retcode = drm_bind_agp(entry->memory, page); + retcode = agp_bind_memory(entry->memory, page); if (retcode) return retcode; entry->bound = dev->agp->base + (page << PAGE_SHIFT); @@ -369,11 +369,11 @@ int drm_agp_free(struct drm_device *dev, struct drm_agp_buffer *request) if (!entry) return -EINVAL; if (entry->bound) - drm_unbind_agp(entry->memory); + agp_unbind_memory(entry->memory); list_del(&entry->head); - drm_free_agp(entry->memory, entry->pages); + agp_free_memory(entry->memory); kfree(entry); return 0; } @@ -453,8 +453,8 @@ void drm_legacy_agp_clear(struct drm_device *dev) list_for_each_entry_safe(entry, tempe, &dev->agp->memory, head) { if (entry->bound) - drm_unbind_agp(entry->memory); - drm_free_agp(entry->memory, entry->pages); + agp_unbind_memory(entry->memory); + agp_free_memory(entry->memory); kfree(entry); } INIT_LIST_HEAD(&dev->agp->memory); diff --git a/drivers/gpu/drm/drm_memory.c b/drivers/gpu/drm/drm_memory.c index fbea69d6f909..f4f2bffdd5bd 100644 --- a/drivers/gpu/drm/drm_memory.c +++ b/drivers/gpu/drm/drm_memory.c @@ -100,24 +100,6 @@ static void *agp_remap(unsigned long offset, unsigned long size, return addr; } -/** Wrapper around agp_free_memory() */ -void drm_free_agp(struct agp_memory *handle, int pages) -{ - agp_free_memory(handle); -} - -/** Wrapper around agp_bind_memory() */ -int drm_bind_agp(struct agp_memory *handle, unsigned int start) -{ - return agp_bind_memory(handle, start); -} - -/** Wrapper around agp_unbind_memory() */ -int drm_unbind_agp(struct agp_memory *handle) -{ - return agp_unbind_memory(handle); -} - #else /* CONFIG_AGP */ static inline void *agp_remap(unsigned long offset, unsigned long size, struct drm_device *dev) diff --git a/include/drm/drm_agpsupport.h b/include/drm/drm_agpsupport.h index 664e120b93e6..f3136750c490 100644 --- a/include/drm/drm_agpsupport.h +++ b/include/drm/drm_agpsupport.h @@ -28,10 +28,6 @@ struct drm_agp_head { #if IS_ENABLED(CONFIG_AGP) -void drm_free_agp(struct agp_memory * handle, int pages); -int drm_bind_agp(struct agp_memory * handle, unsigned int start); -int drm_unbind_agp(struct agp_memory * handle); - struct drm_agp_head *drm_agp_init(struct drm_device *dev); void drm_legacy_agp_clear(struct drm_device *dev); int drm_agp_acquire(struct drm_device *dev); @@ -61,20 +57,6 @@ int drm_agp_bind_ioctl(struct drm_device *dev, void *data, #else /* CONFIG_AGP */ -static inline void drm_free_agp(struct agp_memory * handle, int pages) -{ -} - -static inline int drm_bind_agp(struct agp_memory * handle, unsigned int start) -{ - return -ENODEV; -} - -static inline int drm_unbind_agp(struct agp_memory * handle) -{ - return -ENODEV; -} - static inline struct drm_agp_head *drm_agp_init(struct drm_device *dev) { return NULL; -- cgit v1.2.3 From 14054f2afcd6fcef8270a32cbd7570b4992994c5 Mon Sep 17 00:00:00 2001 From: Thomas Zimmermann Date: Tue, 12 Jan 2021 09:10:35 +0100 Subject: drm: Move struct drm_device.hose to legacy section MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The field is only relevant for legacy DRM drivers. Its only non-legacy user in the DRM core is in drm_file.c. This code is now protected by CONFIG_DRM_LEGACY. Radeon, the only driver that used the field, has been changed to maintain it's own copy. Signed-off-by: Thomas Zimmermann Reviewed-by: Christian König Link: https://patchwork.freedesktop.org/patch/msgid/20210112081035.6882-7-tzimmermann@suse.de --- drivers/gpu/drm/drm_file.c | 2 ++ include/drm/drm_device.h | 9 +++++---- 2 files changed, 7 insertions(+), 4 deletions(-) (limited to 'include') diff --git a/drivers/gpu/drm/drm_file.c b/drivers/gpu/drm/drm_file.c index 99403e49caf4..6b116bfd747c 100644 --- a/drivers/gpu/drm/drm_file.c +++ b/drivers/gpu/drm/drm_file.c @@ -367,6 +367,7 @@ static int drm_open_helper(struct file *filp, struct drm_minor *minor) list_add(&priv->lhead, &dev->filelist); mutex_unlock(&dev->filelist_mutex); +#ifdef CONFIG_DRM_LEGACY #ifdef __alpha__ /* * Default the hose @@ -386,6 +387,7 @@ static int drm_open_helper(struct file *filp, struct drm_minor *minor) dev->hose = b->sysdata; } } +#endif #endif return 0; diff --git a/include/drm/drm_device.h b/include/drm/drm_device.h index 939904ae88fc..d647223e8390 100644 --- a/include/drm/drm_device.h +++ b/include/drm/drm_device.h @@ -282,10 +282,6 @@ struct drm_device { /** @pdev: PCI device structure */ struct pci_dev *pdev; -#ifdef __alpha__ - /** @hose: PCI hose, only used on ALPHA platforms. */ - struct pci_controller *hose; -#endif /** @num_crtcs: Number of CRTCs on this device */ unsigned int num_crtcs; @@ -328,6 +324,11 @@ struct drm_device { /* List of devices per driver for stealth attach cleanup */ struct list_head legacy_dev_list; +#ifdef __alpha__ + /** @hose: PCI hose, only used on ALPHA platforms. */ + struct pci_controller *hose; +#endif + /* Context handle management - linked list of context handles */ struct list_head ctxlist; -- cgit v1.2.3 From 7569c6051fc44a54333c086be35347081b521025 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Thu, 14 Jan 2021 09:04:51 +0100 Subject: drm: drm_crc: fix a kernel-doc markup A function has a different name between their prototype and its kernel-doc markup: ../include/drm/drm_crtc.h:1257: warning: expecting prototype for drm_crtc_alloc_with_planes(). Prototype was for drmm_crtc_alloc_with_planes() instead Signed-off-by: Mauro Carvalho Chehab Acked-by: Simon Ser Signed-off-by: Simon Ser Link: https://patchwork.freedesktop.org/patch/msgid/2439fb6713e9b2aa27a81f3269a4b0e8e7dfcd36.1610610937.git.mchehab+huawei@kernel.org --- include/drm/drm_crtc.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'include') diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h index 540e2e43ec93..13eeba2a750a 100644 --- a/include/drm/drm_crtc.h +++ b/include/drm/drm_crtc.h @@ -1232,7 +1232,7 @@ void *__drmm_crtc_alloc_with_planes(struct drm_device *dev, const char *name, ...); /** - * drm_crtc_alloc_with_planes - Allocate and initialize a new CRTC object with + * drmm_crtc_alloc_with_planes - Allocate and initialize a new CRTC object with * specified primary and cursor planes. * @dev: DRM device * @type: the type of the struct which contains struct &drm_crtc -- cgit v1.2.3 From 61712a5f8271ebdbb9d34d28279b77a452db9d5c Mon Sep 17 00:00:00 2001 From: Yue Zou Date: Mon, 18 Jan 2021 01:03:55 +0000 Subject: vgaarb: Remove unneeded semicolons Remove superfluous semicolons after function definitions. Signed-off-by: Yue Zou Signed-off-by: Daniel Vetter Link: https://patchwork.freedesktop.org/patch/msgid/20210118010356.214491-1-zouyue3@huawei.com --- include/linux/vgaarb.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'include') diff --git a/include/linux/vgaarb.h b/include/linux/vgaarb.h index 977caf96c8d2..fc6dfeba04a5 100644 --- a/include/linux/vgaarb.h +++ b/include/linux/vgaarb.h @@ -121,9 +121,9 @@ extern struct pci_dev *vga_default_device(void); extern void vga_set_default_device(struct pci_dev *pdev); extern int vga_remove_vgacon(struct pci_dev *pdev); #else -static inline struct pci_dev *vga_default_device(void) { return NULL; }; -static inline void vga_set_default_device(struct pci_dev *pdev) { }; -static inline int vga_remove_vgacon(struct pci_dev *pdev) { return 0; }; +static inline struct pci_dev *vga_default_device(void) { return NULL; } +static inline void vga_set_default_device(struct pci_dev *pdev) { } +static inline int vga_remove_vgacon(struct pci_dev *pdev) { return 0; } #endif /* -- cgit v1.2.3 From 72fec10c17d95bcb99371f5b29f6947e67d7493b Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Fri, 11 Dec 2020 17:29:42 +0100 Subject: drm/ttm: WARN_ON non-empty lru when disabling a resource manager MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ttm_resource_manager->use_type is only used for runtime changes by vmwgfx. I think ideally we'd push this functionality into drivers - ttm itself does not provide any locking to guarantee this is safe, so the only way this can work at runtime is if the driver does provide additional guarantees. vwmgfx does that through the vmw_private->reservation_sem. Therefore supporting this feature in shared code feels a bit misplaced. As a first step add a WARN_ON to make sure the resource manager is empty. This is just to make sure I actually understand correctly what vmwgfx is doing, and to make sure an eventual subsequent refactor doesn't break anything. This check should also be useful for other drivers, to make sure they haven't leaked anything. Reviewed-by: Roland Scheidegger Reviewed-by: Christian König Signed-off-by: Daniel Vetter Cc: Christian Koenig Cc: Huang Rui Link: https://patchwork.freedesktop.org/patch/msgid/20201211162942.3399050-3-daniel.vetter@ffwll.ch --- include/drm/ttm/ttm_resource.h | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'include') diff --git a/include/drm/ttm/ttm_resource.h b/include/drm/ttm/ttm_resource.h index ad6da99770e9..da0ed7e8c915 100644 --- a/include/drm/ttm/ttm_resource.h +++ b/include/drm/ttm/ttm_resource.h @@ -190,6 +190,10 @@ struct ttm_resource { static inline void ttm_resource_manager_set_used(struct ttm_resource_manager *man, bool used) { + int i; + + for (i = 0; i < TTM_MAX_BO_PRIORITY; i++) + WARN_ON(!list_empty(&man->lru[i])); man->use_type = used; } -- cgit v1.2.3 From 84335675f2223cbd25d0de7d38ecc7d40b95bd4a Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Fri, 15 Jan 2021 17:47:39 +0100 Subject: dma-buf: Add debug option MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We have too many people abusing the struct page they can get at but really shouldn't in importers. Aside from that the backing page might simply not exist (for dynamic p2p mappings) looking at it and using it e.g. for mmap can also wreak the page handling of the exporter completely. Importers really must go through the proper interface like dma_buf_mmap for everything. I'm semi-tempted to enforce this for dynamic importers since those really have no excuse at all to break the rules. Unfortuantely we can't store the right pointers somewhere safe to make sure we oops on something recognizable, so best is to just wrangle them a bit by flipping all the bits. At least on x86 kernel addresses have all their high bits sets and the struct page array is fairly low in the kernel mapping, so flipping all the bits gives us a very high pointer in userspace and hence excellent chances for an invalid dereference. v2: Add a note to the @map_dma_buf hook that exporters shouldn't do fancy caching tricks, which would blow up with this address scrambling trick here (Chris) Enable by default when CONFIG_DMA_API_DEBUG is enabled. v3: Only one copy of the mangle/unmangle code (Christian) v4: #ifdef, not #if (0day) v5: sg_table can also be an ERR_PTR (Chris, Christian) Reviewed-by: Chris Wilson Reviewed-by: Christian König Signed-off-by: Daniel Vetter Cc: Chris Wilson Cc: Sumit Semwal Cc: "Christian König" Cc: David Stevens Cc: linux-media@vger.kernel.org Cc: linaro-mm-sig@lists.linaro.org Link: https://patchwork.freedesktop.org/patch/msgid/20210115164739.3958206-1-daniel.vetter@ffwll.ch --- drivers/dma-buf/Kconfig | 8 ++++++++ drivers/dma-buf/dma-buf.c | 46 ++++++++++++++++++++++++++++++++++++++++++---- include/linux/dma-buf.h | 6 ++++++ 3 files changed, 56 insertions(+), 4 deletions(-) (limited to 'include') diff --git a/drivers/dma-buf/Kconfig b/drivers/dma-buf/Kconfig index 4f8224a6ac95..4e16c71c24b7 100644 --- a/drivers/dma-buf/Kconfig +++ b/drivers/dma-buf/Kconfig @@ -50,6 +50,14 @@ config DMABUF_MOVE_NOTIFY This is marked experimental because we don't yet have a consistent execution context and memory management between drivers. +config DMABUF_DEBUG + bool "DMA-BUF debug checks" + default y if DMA_API_DEBUG + help + This option enables additional checks for DMA-BUF importers and + exporters. Specifically it validates that importers do not peek at the + underlying struct page when they import a buffer. + config DMABUF_SELFTESTS tristate "Selftests for the dma-buf interfaces" default n diff --git a/drivers/dma-buf/dma-buf.c b/drivers/dma-buf/dma-buf.c index b8465243eca2..3948b88aa123 100644 --- a/drivers/dma-buf/dma-buf.c +++ b/drivers/dma-buf/dma-buf.c @@ -653,6 +653,34 @@ void dma_buf_put(struct dma_buf *dmabuf) } EXPORT_SYMBOL_GPL(dma_buf_put); +static void mangle_sg_table(struct sg_table *sg_table) +{ +#ifdef CONFIG_DMABUF_DEBUG + int i; + struct scatterlist *sg; + + /* To catch abuse of the underlying struct page by importers mix + * up the bits, but take care to preserve the low SG_ bits to + * not corrupt the sgt. The mixing is undone in __unmap_dma_buf + * before passing the sgt back to the exporter. */ + for_each_sgtable_sg(sg_table, sg, i) + sg->page_link ^= ~0xffUL; +#endif + +} +static struct sg_table * __map_dma_buf(struct dma_buf_attachment *attach, + enum dma_data_direction direction) +{ + struct sg_table *sg_table; + + sg_table = attach->dmabuf->ops->map_dma_buf(attach, direction); + + if (!IS_ERR_OR_NULL(sg_table)) + mangle_sg_table(sg_table); + + return sg_table; +} + /** * dma_buf_dynamic_attach - Add the device to dma_buf's attachments list * @dmabuf: [in] buffer to attach device to. @@ -724,7 +752,7 @@ dma_buf_dynamic_attach(struct dma_buf *dmabuf, struct device *dev, goto err_unlock; } - sgt = dmabuf->ops->map_dma_buf(attach, DMA_BIDIRECTIONAL); + sgt = __map_dma_buf(attach, DMA_BIDIRECTIONAL); if (!sgt) sgt = ERR_PTR(-ENOMEM); if (IS_ERR(sgt)) { @@ -771,6 +799,16 @@ struct dma_buf_attachment *dma_buf_attach(struct dma_buf *dmabuf, } EXPORT_SYMBOL_GPL(dma_buf_attach); +static void __unmap_dma_buf(struct dma_buf_attachment *attach, + struct sg_table *sg_table, + enum dma_data_direction direction) +{ + /* uses XOR, hence this unmangles */ + mangle_sg_table(sg_table); + + attach->dmabuf->ops->unmap_dma_buf(attach, sg_table, direction); +} + /** * dma_buf_detach - Remove the given attachment from dmabuf's attachments list * @dmabuf: [in] buffer to detach from. @@ -789,7 +827,7 @@ void dma_buf_detach(struct dma_buf *dmabuf, struct dma_buf_attachment *attach) if (dma_buf_is_dynamic(attach->dmabuf)) dma_resv_lock(attach->dmabuf->resv, NULL); - dmabuf->ops->unmap_dma_buf(attach, attach->sgt, attach->dir); + __unmap_dma_buf(attach, attach->sgt, attach->dir); if (dma_buf_is_dynamic(attach->dmabuf)) { dma_buf_unpin(attach); @@ -911,7 +949,7 @@ struct sg_table *dma_buf_map_attachment(struct dma_buf_attachment *attach, } } - sg_table = attach->dmabuf->ops->map_dma_buf(attach, direction); + sg_table = __map_dma_buf(attach, direction); if (!sg_table) sg_table = ERR_PTR(-ENOMEM); @@ -974,7 +1012,7 @@ void dma_buf_unmap_attachment(struct dma_buf_attachment *attach, if (dma_buf_is_dynamic(attach->dmabuf)) dma_resv_assert_held(attach->dmabuf->resv); - attach->dmabuf->ops->unmap_dma_buf(attach, sg_table, direction); + __unmap_dma_buf(attach, sg_table, direction); if (dma_buf_is_dynamic(attach->dmabuf) && !IS_ENABLED(CONFIG_DMABUF_MOVE_NOTIFY)) diff --git a/include/linux/dma-buf.h b/include/linux/dma-buf.h index 628681bf6c99..efdc56b9d95f 100644 --- a/include/linux/dma-buf.h +++ b/include/linux/dma-buf.h @@ -154,6 +154,12 @@ struct dma_buf_ops { * On failure, returns a negative error value wrapped into a pointer. * May also return -EINTR when a signal was received while being * blocked. + * + * Note that exporters should not try to cache the scatter list, or + * return the same one for multiple calls. Caching is done either by the + * DMA-BUF code (for non-dynamic importers) or the importer. Ownership + * of the scatter list is transferred to the caller, and returned by + * @unmap_dma_buf. */ struct sg_table * (*map_dma_buf)(struct dma_buf_attachment *, enum dma_data_direction); -- cgit v1.2.3