#include <sys/stat.h>
#include <unistd.h>
+#ifndef RADEON_INFO_ACTIVE_CU_COUNT
+#define RADEON_INFO_ACTIVE_CU_COUNT 0x20
+#endif
+
static struct util_hash_table *fd_tab = NULL;
pipe_static_mutex(fd_tab_mutex);
case CHIP_KAVERI:
case CHIP_KABINI:
case CHIP_HAWAII:
+ case CHIP_MULLINS:
ws->info.chip_class = CIK;
break;
}
/* Check for dma */
ws->info.r600_has_dma = FALSE;
- if (ws->info.chip_class >= R700 && ws->info.drm_minor >= 27) {
+ /* DMA is disabled on R700. There is IB corruption and hangs. */
+ if (ws->info.chip_class >= EVERGREEN && ws->info.drm_minor >= 27) {
ws->info.r600_has_dma = TRUE;
}
ws->info.gart_size = gem_info.gart_size;
ws->info.vram_size = gem_info.vram_size;
+ /* Get max clock frequency info and convert it to MHz */
+ radeon_get_drm_value(ws->fd, RADEON_INFO_MAX_SCLK, NULL,
+ &ws->info.max_sclk);
+ ws->info.max_sclk /= 1000;
+
ws->num_cpus = sysconf(_SC_NPROCESSORS_ONLN);
/* Generation-specific queries. */
radeon_get_drm_value(ws->fd, RADEON_INFO_MAX_PIPES, NULL,
&ws->info.r600_max_pipes);
+ radeon_get_drm_value(ws->fd, RADEON_INFO_ACTIVE_CU_COUNT, NULL,
+ &ws->info.max_compute_units);
+
+ radeon_get_drm_value(ws->fd, RADEON_INFO_MAX_SE, NULL,
+ &ws->info.max_se);
+
+ radeon_get_drm_value(ws->fd, RADEON_INFO_MAX_SH_PER_SE, NULL,
+ &ws->info.max_sh_per_se);
+
if (radeon_get_drm_value(ws->fd, RADEON_INFO_SI_TILE_MODE_ARRAY, NULL,
ws->info.si_tile_mode_array)) {
ws->info.si_tile_mode_array_valid = TRUE;
{
struct radeon_drm_winsys *ws = (struct radeon_drm_winsys*)rws;
- pipe_mutex_lock(fd_tab_mutex);
- if (fd_tab) {
- util_hash_table_remove(fd_tab, intptr_to_pointer(ws->fd));
- }
- pipe_mutex_unlock(fd_tab_mutex);
-
if (ws->thread) {
ws->kill_thread = 1;
pipe_semaphore_signal(&ws->cs_queued);
DEBUG_GET_ONCE_BOOL_OPTION(thread, "RADEON_THREAD", TRUE)
static PIPE_THREAD_ROUTINE(radeon_drm_cs_emit_ioctl, param);
-PUBLIC struct radeon_winsys *radeon_drm_winsys_create(int fd)
+static bool radeon_winsys_unref(struct radeon_winsys *ws)
+{
+ struct radeon_drm_winsys *rws = (struct radeon_drm_winsys*)ws;
+ bool destroy;
+
+ /* When the reference counter drops to zero, remove the fd from the table.
+ * This must happen while the mutex is locked, so that
+ * radeon_drm_winsys_create in another thread doesn't get the winsys
+ * from the table when the counter drops to 0. */
+ pipe_mutex_lock(fd_tab_mutex);
+
+ destroy = pipe_reference(&rws->reference, NULL);
+ if (destroy && fd_tab)
+ util_hash_table_remove(fd_tab, intptr_to_pointer(rws->fd));
+
+ pipe_mutex_unlock(fd_tab_mutex);
+ return destroy;
+}
+
+PUBLIC struct radeon_winsys *
+radeon_drm_winsys_create(int fd, radeon_screen_create_t screen_create)
{
struct radeon_drm_winsys *ws;
ws = util_hash_table_get(fd_tab, intptr_to_pointer(fd));
if (ws) {
+ pipe_reference(NULL, &ws->reference);
pipe_mutex_unlock(fd_tab_mutex);
- pipe_reference(NULL, &ws->base.reference);
return &ws->base;
}
}
ws->fd = fd;
- util_hash_table_set(fd_tab, intptr_to_pointer(fd), ws);
if (!do_winsys_init(ws))
goto fail;
}
/* init reference */
- pipe_reference_init(&ws->base.reference, 1);
+ pipe_reference_init(&ws->reference, 1);
/* Set functions. */
+ ws->base.unref = radeon_winsys_unref;
ws->base.destroy = radeon_winsys_destroy;
ws->base.query_info = radeon_query_info;
ws->base.cs_request_feature = radeon_cs_request_feature;
if (ws->num_cpus > 1 && debug_get_option_thread())
ws->thread = pipe_thread_create(radeon_drm_cs_emit_ioctl, ws);
+ /* Create the screen at the end. The winsys must be initialized
+ * completely.
+ *
+ * Alternatively, we could create the screen based on "ws->gen"
+ * and link all drivers into one binary blob. */
+ ws->base.screen = screen_create(&ws->base);
+ if (!ws->base.screen) {
+ radeon_winsys_destroy(&ws->base);
+ pipe_mutex_unlock(fd_tab_mutex);
+ return NULL;
+ }
+
+ util_hash_table_set(fd_tab, intptr_to_pointer(fd), ws);
+
/* We must unlock the mutex once the winsys is fully initialized, so that
* other threads attempting to create the winsys from the same fd will
* get a fully initialized winsys and not just half-way initialized. */