summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSam Ravnborg <sam@ravnborg.org>2020-07-09 22:30:16 +0300
committerSam Ravnborg <sam@ravnborg.org>2020-07-27 17:47:46 +0300
commit2a1658bf922ffd9b7907e270a7d9cdc9643fc45d (patch)
tree6519b0e8c4b08dfe3ca96e6e8abdb13e6f15f4eb
parentaa7bf898d4bf921f61fab078040e8baec3f28126 (diff)
downloadlinux-2a1658bf922ffd9b7907e270a7d9cdc9643fc45d.tar.xz
drm/drm_fb_helper: fix fbdev with sparc64
Recent kernels have been reported to panic using the bochs_drm framebuffer under qemu-system-sparc64 which was bisected to commit 7a0483ac4ffc ("drm/bochs: switch to generic drm fbdev emulation"). The backtrace indicates that the shadow framebuffer copy in drm_fb_helper_dirty_blit_real() is trying to access the real framebuffer using a virtual address rather than use an IO access typically implemented using a physical (ASI_PHYS) access on SPARC. The fix is to replace the memcpy with memcpy_toio() from io.h. memcpy_toio() uses writeb() where the original fbdev code used sbus_memcpy_toio(). The latter uses sbus_writeb(). The difference between writeb() and sbus_memcpy_toio() is that writeb() writes bytes in little-endian, where sbus_writeb() writes bytes in big-endian. As endian does not matter for byte writes they are the same. So we can safely use memcpy_toio() here. Note that this only fixes bochs, in general fbdev helpers still have issues with mixing up system memory and __iomem space. Fixing that will require a lot more work. v3: - Improved changelog (Daniel) - Added FIXME to fbdev_use_iomem (Daniel) v2: - Added missing __iomem cast (kernel test robot) - Made changelog readable and fix typos (Mark) - Add flag to select iomem - and set it in the bochs driver Signed-off-by: Sam Ravnborg <sam@ravnborg.org> Reported-by: Mark Cave-Ayland <mark.cave-ayland@ilande.co.uk> Reported-by: kernel test robot <lkp@intel.com> Tested-by: Mark Cave-Ayland <mark.cave-ayland@ilande.co.uk> Reviewed-by: Daniel Vetter <daniel.vetter@ffwll.ch> Cc: Mark Cave-Ayland <mark.cave-ayland@ilande.co.uk> Cc: Thomas Zimmermann <tzimmermann@suse.de> Cc: Gerd Hoffmann <kraxel@redhat.com> Cc: "David S. Miller" <davem@davemloft.net> Cc: sparclinux@vger.kernel.org Link: https://patchwork.freedesktop.org/patch/msgid/20200709193016.291267-1-sam@ravnborg.org Link: https://patchwork.freedesktop.org/patch/msgid/20200725191012.GA434957@ravnborg.org
-rw-r--r--drivers/gpu/drm/bochs/bochs_kms.c1
-rw-r--r--drivers/gpu/drm/drm_fb_helper.c6
-rw-r--r--include/drm/drm_mode_config.h12
3 files changed, 18 insertions, 1 deletions
diff --git a/drivers/gpu/drm/bochs/bochs_kms.c b/drivers/gpu/drm/bochs/bochs_kms.c
index 05d8373888e8..079f46f5cdb6 100644
--- a/drivers/gpu/drm/bochs/bochs_kms.c
+++ b/drivers/gpu/drm/bochs/bochs_kms.c
@@ -146,6 +146,7 @@ int bochs_kms_init(struct bochs_device *bochs)
bochs->dev->mode_config.preferred_depth = 24;
bochs->dev->mode_config.prefer_shadow = 0;
bochs->dev->mode_config.prefer_shadow_fbdev = 1;
+ bochs->dev->mode_config.fbdev_use_iomem = true;
bochs->dev->mode_config.quirk_addfb_prefer_host_byte_order = true;
bochs->dev->mode_config.funcs = &bochs_mode_funcs;
diff --git a/drivers/gpu/drm/drm_fb_helper.c b/drivers/gpu/drm/drm_fb_helper.c
index 5609e164805f..89cfd68ef400 100644
--- a/drivers/gpu/drm/drm_fb_helper.c
+++ b/drivers/gpu/drm/drm_fb_helper.c
@@ -399,7 +399,11 @@ static void drm_fb_helper_dirty_blit_real(struct drm_fb_helper *fb_helper,
unsigned int y;
for (y = clip->y1; y < clip->y2; y++) {
- memcpy(dst, src, len);
+ if (!fb_helper->dev->mode_config.fbdev_use_iomem)
+ memcpy(dst, src, len);
+ else
+ memcpy_toio((void __iomem *)dst, src, len);
+
src += fb->pitches[0];
dst += fb->pitches[0];
}
diff --git a/include/drm/drm_mode_config.h b/include/drm/drm_mode_config.h
index 6c3ef49b46b3..e73dea5c7333 100644
--- a/include/drm/drm_mode_config.h
+++ b/include/drm/drm_mode_config.h
@@ -866,6 +866,18 @@ struct drm_mode_config {
bool prefer_shadow_fbdev;
/**
+ * @fbdev_use_iomem:
+ *
+ * Set to true if framebuffer reside in iomem.
+ * When set to true memcpy_toio() is used when copying the framebuffer in
+ * drm_fb_helper.drm_fb_helper_dirty_blit_real().
+ *
+ * FIXME: This should be replaced with a per-mapping is_iomem
+ * flag (like ttm does), and then used everywhere in fbdev code.
+ */
+ bool fbdev_use_iomem;
+
+ /**
* @quirk_addfb_prefer_xbgr_30bpp:
*
* Special hack for legacy ADDFB to keep nouveau userspace happy. Should