diff --git a/src/freedreno/vulkan/tu_shader.cc b/src/freedreno/vulkan/tu_shader.cc
index edc0ce1f6fe..e5b8e9bc44d 100644
--- a/src/freedreno/vulkan/tu_shader.cc
+++ b/src/freedreno/vulkan/tu_shader.cc
@@ -2556,10 +2556,10 @@ tu_upload_shader(struct tu_device *dev,
       size += vpc_size;
    }
 
-   pthread_mutex_lock(&dev->pipeline_mutex);
+   mtx_lock(&dev->pipeline_mutex);
    VkResult result = tu_suballoc_bo_alloc(&shader->bo, &dev->pipeline_suballoc,
                                           size * 4, 128);
-   pthread_mutex_unlock(&dev->pipeline_mutex);
+   mtx_unlock(&dev->pipeline_mutex);
 
    if (result != VK_SUCCESS)
       return result;
@@ -2589,9 +2589,9 @@ tu_upload_shader(struct tu_device *dev,
 
    result = tu_setup_pvtmem(dev, shader, &pvtmem_config, pvtmem_size, per_wave);
    if (result != VK_SUCCESS) {
-      pthread_mutex_lock(&dev->pipeline_mutex);
+      mtx_lock(&dev->pipeline_mutex);
       tu_suballoc_bo_free(&dev->pipeline_suballoc, &shader->bo);
-      pthread_mutex_unlock(&dev->pipeline_mutex);
+      mtx_unlock(&dev->pipeline_mutex);
       return result;
    }
 
@@ -3427,10 +3427,10 @@ tu_empty_shader_create(struct tu_device *dev,
    if (!shader)
       return VK_ERROR_OUT_OF_HOST_MEMORY;
 
-   pthread_mutex_lock(&dev->pipeline_mutex);
+   mtx_lock(&dev->pipeline_mutex);
    VkResult result = tu_suballoc_bo_alloc(&shader->bo, &dev->pipeline_suballoc,
                                           32 * 4, 128);
-   pthread_mutex_unlock(&dev->pipeline_mutex);
+   mtx_unlock(&dev->pipeline_mutex);
 
    if (result != VK_SUCCESS) {
       vk_free(&dev->vk.alloc, shader);
@@ -3541,9 +3541,9 @@ tu_shader_destroy(struct tu_device *dev,
    tu_cs_finish(&shader->cs);
    TU_RMV(resource_destroy, dev, &shader->bo);
 
-   pthread_mutex_lock(&dev->pipeline_mutex);
+   mtx_lock(&dev->pipeline_mutex);
    tu_suballoc_bo_free(&dev->pipeline_suballoc, &shader->bo);
-   pthread_mutex_unlock(&dev->pipeline_mutex);
+   mtx_unlock(&dev->pipeline_mutex);
 
    if (shader->pvtmem_bo)
       tu_bo_finish(dev, shader->pvtmem_bo);
diff --git a/src/freedreno/vulkan/tu_wsi.cc b/src/freedreno/vulkan/tu_wsi.cc
index 57cf9048b07..246a95dd894 100644
--- a/src/freedreno/vulkan/tu_wsi.cc
+++ b/src/freedreno/vulkan/tu_wsi.cc
@@ -47,6 +47,10 @@ tu_wsi_init(struct tu_physical_device *physical_device)
                             &options);
    if (result != VK_SUCCESS)
       return result;
+      
+   if (strcmp(physical_device->instance->knl->name, "kgsl") == 0) {
+      physical_device->wsi_device.is_tu_kgsl = true;
+   }
 
    physical_device->wsi_device.supports_modifiers = true;
    physical_device->wsi_device.can_present_on_device =
diff --git a/src/util/anon_file.c b/src/util/anon_file.c
index a9ad2a2aad8..f5dcd5b3b48 100644
--- a/src/util/anon_file.c
+++ b/src/util/anon_file.c
@@ -117,6 +117,11 @@ get_or_create_user_temp_dir(char* buf, size_t len) {
     int uid = getuid();
 
     env = os_get_option("XDG_RUNTIME_DIR");
+#ifdef __linux__
+    if (!env) {
+        env = "/tmp";
+    }
+#endif
     if (env && env[0] != '\0') {
         snprintf(buf, len, "%s", env);
         return buf;
diff --git a/src/util/u_process.c b/src/util/u_process.c
index 6846acd2e0b..8551c227b88 100644
--- a/src/util/u_process.c
+++ b/src/util/u_process.c
@@ -101,7 +101,7 @@ __getProgramName()
 {
    return strdup(program_invocation_short_name);
 }
-#elif defined(__FreeBSD__) || defined(__DragonFly__) || defined(__APPLE__) || DETECT_OS_ANDROID || defined(__NetBSD__)
+#elif defined(__FreeBSD__) || defined(__DragonFly__) || defined(__APPLE__) || DETECT_OS_ANDROID || defined(__NetBSD__) || defined(__linux__)
 #if defined(__NetBSD__)
 #    include <sys/param.h>
 #endif
diff --git a/src/vulkan/wsi/wsi_common.c b/src/vulkan/wsi/wsi_common.c
index 6783fbd6efb..3a81c200c2a 100644
--- a/src/vulkan/wsi/wsi_common.c
+++ b/src/vulkan/wsi/wsi_common.c
@@ -2491,7 +2491,7 @@ wsi_common_queue_present(const struct wsi_device *wsi,
 #endif
       }
 
-      if (wsi->sw) {
+      if (wsi->sw || (wsi->is_tu_kgsl && (swapchain->dma_buf_semaphore == VK_NULL_HANDLE))) {
          wsi->WaitForFences(vk_device_to_handle(dev),
                             1, &swapchain->fences[image_index], true, ~0ull);
       }
@@ -3217,7 +3217,7 @@ wsi_configure_cpu_image(const struct wsi_swapchain *chain,
                         const struct wsi_cpu_image_params *params,
                         struct wsi_image_info *info)
 {
-   assert(params->base.image_type == WSI_IMAGE_TYPE_CPU);
+   // assert(params->base.image_type == WSI_IMAGE_TYPE_CPU);
    assert(chain->blit.type == WSI_SWAPCHAIN_NO_BLIT ||
           chain->blit.type == WSI_SWAPCHAIN_BUFFER_BLIT);
 
diff --git a/src/vulkan/wsi/wsi_common.h b/src/vulkan/wsi/wsi_common.h
index c17a79c6b13..20c480babbc 100644
--- a/src/vulkan/wsi/wsi_common.h
+++ b/src/vulkan/wsi/wsi_common.h
@@ -152,6 +152,7 @@ struct wsi_device {
 
 
    bool sw;
+   bool is_tu_kgsl;
 
    /* Set to true if the implementation is ok with linear WSI images. */
    bool wants_linear;
diff --git a/src/vulkan/wsi/wsi_common_display.c b/src/vulkan/wsi/wsi_common_display.c
index f72e85c5e66..ac83c92236a 100644
--- a/src/vulkan/wsi/wsi_common_display.c
+++ b/src/vulkan/wsi/wsi_common_display.c
@@ -516,6 +516,12 @@ struct wsi_display_sync {
 
 static uint64_t fence_sequence;
 
+#ifdef __linux__
+static void thread_signal_handler (int signum) {
+   pthread_exit (0);
+}
+#endif
+
 static void
 _wsi_display_cleanup_state(struct wsi_display_swapchain *chain);
 
@@ -2024,7 +2030,9 @@ wsi_display_wait_thread(void *data)
       .events = POLLIN
    };
 
+#ifndef __linux__
    pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL);
+#endif
    for (;;) {
       int ret = poll(&pollfd, 1, -1);
       if (ret > 0) {
@@ -2052,9 +2060,21 @@ wsi_display_start_wait_thread(struct wsi_display *wsi)
 static void
 wsi_display_stop_wait_thread(struct wsi_display *wsi)
 {
+#ifdef __linux__
+   struct sigaction actions;
+   memset (&actions, 0, sizeof (actions));
+   sigemptyset (&actions.sa_mask);
+   actions.sa_flags = 0;
+   actions.sa_handler = thread_signal_handler;
+   sigaction (SIGUSR2, &actions, NULL);
+#endif
    mtx_lock(&wsi->wait_mutex);
    if (wsi->wait_thread) {
+#ifndef __linux__
       pthread_cancel(wsi->wait_thread);
+#else
+      pthread_kill(wsi->wait_thread, SIGUSR2);
+#endif
       pthread_join(wsi->wait_thread, NULL);
       wsi->wait_thread = 0;
    }
@@ -3456,7 +3476,9 @@ udev_event_listener_thread(void *data)
 
    int udev_fd = udev_monitor_get_fd(mon);
 
+#ifndef __linux__
    pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL);
+#endif
 
    for (;;) {
       nfds_t nfds = 1;
@@ -3603,6 +3625,15 @@ wsi_display_finish_wsi(struct wsi_device *wsi_device,
    struct wsi_display *wsi =
       (struct wsi_display *) wsi_device->wsi[VK_ICD_WSI_PLATFORM_DISPLAY];
 
+#ifdef __linux__
+   struct sigaction actions;
+   memset (&actions, 0, sizeof (actions));
+   sigemptyset (&actions.sa_mask);
+   actions.sa_flags = 0;
+   actions.sa_handler = thread_signal_handler;
+   sigaction (SIGUSR2, &actions, NULL);
+#endif
+
    if (wsi) {
       wsi_for_each_connector(connector, wsi)
          wsi_display_free_connector(wsi, connector);
@@ -3610,7 +3641,11 @@ wsi_display_finish_wsi(struct wsi_device *wsi_device,
       wsi_display_stop_wait_thread(wsi);
 
       if (wsi->hotplug_thread) {
+#ifndef __linux__
          pthread_cancel(wsi->hotplug_thread);
+#else
+         pthread_kill(wsi->hotplug_thread, SIGUSR2);
+#endif
          pthread_join(wsi->hotplug_thread, NULL);
       }
 
diff --git a/src/vulkan/wsi/wsi_common_drm.c b/src/vulkan/wsi/wsi_common_drm.c
index fe297d3ca01..8c48b29d733 100644
--- a/src/vulkan/wsi/wsi_common_drm.c
+++ b/src/vulkan/wsi/wsi_common_drm.c
@@ -47,6 +47,9 @@
 static VkResult
 wsi_dma_buf_export_sync_file(int dma_buf_fd, int *sync_file_fd)
 {
+   #if defined (__linux__)
+      return VK_ERROR_FEATURE_NOT_PRESENT;
+   #else
    struct dma_buf_export_sync_file export = {
       .flags = DMA_BUF_SYNC_RW,
       .fd = -1,
@@ -64,11 +67,15 @@ wsi_dma_buf_export_sync_file(int dma_buf_fd, int *sync_file_fd)
    *sync_file_fd = export.fd;
 
    return VK_SUCCESS;
+   #endif
 }
 
 static VkResult
 wsi_dma_buf_import_sync_file(int dma_buf_fd, int sync_file_fd)
 {
+   #if defined (__linux__)
+      return VK_ERROR_FEATURE_NOT_PRESENT;
+   #else
    struct dma_buf_import_sync_file import = {
       .flags = DMA_BUF_SYNC_RW,
       .fd = sync_file_fd,
@@ -84,6 +91,7 @@ wsi_dma_buf_import_sync_file(int dma_buf_fd, int sync_file_fd)
    }
 
    return VK_SUCCESS;
+   #endif
 }
 
 /**
diff --git a/src/vulkan/wsi/wsi_common_x11.c b/src/vulkan/wsi/wsi_common_x11.c
index 5e4b3a68d07..d19b8faa196 100644
--- a/src/vulkan/wsi/wsi_common_x11.c
+++ b/src/vulkan/wsi/wsi_common_x11.c
@@ -149,22 +149,7 @@ static bool
 wsi_x11_check_dri3_compatible(const struct wsi_device *wsi_dev,
                               xcb_connection_t *conn)
 {
-   xcb_screen_iterator_t screen_iter =
-      xcb_setup_roots_iterator(xcb_get_setup(conn));
-   xcb_screen_t *screen = screen_iter.data;
-
-   /* Open the DRI3 device from the X server. If we do not retrieve one we
-    * assume our local device is compatible.
-    */
-   int dri3_fd = wsi_dri3_open(conn, screen->root, None);
-   if (dri3_fd == -1)
-      return true;
-
-   bool match = wsi_dev->can_present_on_device(wsi_dev->pdevice, dri3_fd);
-
-   close(dri3_fd);
-
-   return match;
+   return true;
 }
 #endif
 
@@ -1453,8 +1438,6 @@ x11_present_to_x11_dri3(struct x11_swapchain *chain, uint32_t image_index,
        !wsi_device->x11.ignore_suboptimal)
       options |= XCB_PRESENT_OPTION_SUBOPTIMAL;
 
-   xshmfence_reset(image->shm_fence);
-
    if (!chain->base.image_info.explicit_sync) {
       ++chain->sent_image_count;
       assert(chain->sent_image_count <= chain->base.image_count);
@@ -1832,11 +1815,6 @@ x11_acquire_next_image(struct wsi_swapchain *wsi_chain,
       return result;
 
    assert(*image_index < chain->base.image_count);
-#ifdef HAVE_X11_DRM
-   if (chain->images[*image_index].shm_fence &&
-       !chain->base.image_info.explicit_sync)
-      xshmfence_await(chain->images[*image_index].shm_fence);
-#endif
 
    return result;
 }
@@ -2201,15 +2179,24 @@ x11_image_init(VkDevice device_h, struct x11_swapchain *chain,
       if (fd == -1)
          return VK_ERROR_OUT_OF_HOST_MEMORY;
 
-      cookie =
-         xcb_dri3_pixmap_from_buffer_checked(chain->conn,
-                                             image->pixmap,
-                                             chain->window,
-                                             image->base.sizes[0],
-                                             pCreateInfo->imageExtent.width,
-                                             pCreateInfo->imageExtent.height,
-                                             image->base.row_pitches[0],
-                                             chain->depth, bpp, fd);
+      cookie = xcb_dri3_pixmap_from_buffers_checked(chain->conn,
+                                                    image->pixmap,
+                                                    chain->window,
+                                                    image->base.num_planes,
+                                                    pCreateInfo->imageExtent.width,
+                                                    pCreateInfo->imageExtent.height,
+                                                    image->base.row_pitches[0],
+                                                    image->base.offsets[0],
+                                                    0,
+                                                    0,
+                                                    0,
+                                                    0,
+                                                    0,
+                                                    0,
+                                                    chain->depth,
+                                                    bpp,
+                                                    1274,
+                                                    &fd);
    }
 
    error = xcb_request_check(chain->conn, cookie);
@@ -2239,6 +2226,9 @@ x11_image_init(VkDevice device_h, struct x11_swapchain *chain,
    }
 #endif
 
+   image->sync_fence = 0;
+   return VK_SUCCESS;
+
 out_fence:
    fence_fd = xshmfence_alloc_shm();
    if (fence_fd < 0)
@@ -2281,12 +2271,6 @@ x11_image_finish(struct x11_swapchain *chain,
 {
    xcb_void_cookie_t cookie;
    if (!chain->base.wsi->sw || chain->has_mit_shm) {
-#ifdef HAVE_X11_DRM
-      cookie = xcb_sync_destroy_fence(chain->conn, image->sync_fence);
-      xcb_discard_reply(chain->conn, cookie.sequence);
-      xshmfence_unmap_shm(image->shm_fence);
-#endif
-
       cookie = xcb_free_pixmap(chain->conn, image->pixmap);
       xcb_discard_reply(chain->conn, cookie.sequence);
 #ifdef HAVE_X11_DRM
