Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | RSS feed

  1. /*
  2.  * Copyright © 2009 Corbin Simpson
  3.  * Copyright © 2011 Marek Olšák <maraeo@gmail.com>
  4.  * All Rights Reserved.
  5.  *
  6.  * Permission is hereby granted, free of charge, to any person obtaining
  7.  * a copy of this software and associated documentation files (the
  8.  * "Software"), to deal in the Software without restriction, including
  9.  * without limitation the rights to use, copy, modify, merge, publish,
  10.  * distribute, sub license, and/or sell copies of the Software, and to
  11.  * permit persons to whom the Software is furnished to do so, subject to
  12.  * the following conditions:
  13.  *
  14.  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  15.  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
  16.  * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  17.  * NON-INFRINGEMENT. IN NO EVENT SHALL THE COPYRIGHT HOLDERS, AUTHORS
  18.  * AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  19.  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
  20.  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
  21.  * USE OR OTHER DEALINGS IN THE SOFTWARE.
  22.  *
  23.  * The above copyright notice and this permission notice (including the
  24.  * next paragraph) shall be included in all copies or substantial portions
  25.  * of the Software.
  26.  */
  27. /*
  28.  * Authors:
  29.  *      Corbin Simpson <MostAwesomeDude@gmail.com>
  30.  *      Joakim Sindholt <opensource@zhasha.com>
  31.  *      Marek Olšák <maraeo@gmail.com>
  32.  */
  33.  
  34. #include "radeon_drm_bo.h"
  35. #include "radeon_drm_cs.h"
  36. #include "radeon_drm_public.h"
  37.  
  38. #include "pipebuffer/pb_bufmgr.h"
  39. #include "util/u_memory.h"
  40. #include "util/u_hash_table.h"
  41.  
  42. #include <xf86drm.h>
  43. #include <stdio.h>
  44. #include <sys/types.h>
  45. #include <sys/stat.h>
  46. #include <unistd.h>
  47. #include <radeon_surface.h>
  48.  
  49. #ifndef RADEON_INFO_ACTIVE_CU_COUNT
  50. #define RADEON_INFO_ACTIVE_CU_COUNT 0x20
  51. #endif
  52.  
  53. #ifndef RADEON_INFO_CURRENT_GPU_TEMP
  54. #define RADEON_INFO_CURRENT_GPU_TEMP    0x21
  55. #define RADEON_INFO_CURRENT_GPU_SCLK    0x22
  56. #define RADEON_INFO_CURRENT_GPU_MCLK    0x23
  57. #define RADEON_INFO_READ_REG            0x24
  58. #endif
  59.  
  60. static struct util_hash_table *fd_tab = NULL;
  61. pipe_static_mutex(fd_tab_mutex);
  62.  
  63. /* Enable/disable feature access for one command stream.
  64.  * If enable == TRUE, return TRUE on success.
  65.  * Otherwise, return FALSE.
  66.  *
  67.  * We basically do the same thing kernel does, because we have to deal
  68.  * with multiple contexts (here command streams) backed by one winsys. */
  69. static boolean radeon_set_fd_access(struct radeon_drm_cs *applier,
  70.                                     struct radeon_drm_cs **owner,
  71.                                     pipe_mutex *mutex,
  72.                                     unsigned request, const char *request_name,
  73.                                     boolean enable)
  74. {
  75.     struct drm_radeon_info info;
  76.     unsigned value = enable ? 1 : 0;
  77.  
  78.     memset(&info, 0, sizeof(info));
  79.  
  80.     pipe_mutex_lock(*mutex);
  81.  
  82.     /* Early exit if we are sure the request will fail. */
  83.     if (enable) {
  84.         if (*owner) {
  85.             pipe_mutex_unlock(*mutex);
  86.             return FALSE;
  87.         }
  88.     } else {
  89.         if (*owner != applier) {
  90.             pipe_mutex_unlock(*mutex);
  91.             return FALSE;
  92.         }
  93.     }
  94.  
  95.     /* Pass through the request to the kernel. */
  96.     info.value = (unsigned long)&value;
  97.     info.request = request;
  98.     if (drmCommandWriteRead(applier->ws->fd, DRM_RADEON_INFO,
  99.                             &info, sizeof(info)) != 0) {
  100.         pipe_mutex_unlock(*mutex);
  101.         return FALSE;
  102.     }
  103.  
  104.     /* Update the rights in the winsys. */
  105.     if (enable) {
  106.         if (value) {
  107.             *owner = applier;
  108.             pipe_mutex_unlock(*mutex);
  109.             return TRUE;
  110.         }
  111.     } else {
  112.         *owner = NULL;
  113.     }
  114.  
  115.     pipe_mutex_unlock(*mutex);
  116.     return FALSE;
  117. }
  118.  
  119. static boolean radeon_get_drm_value(int fd, unsigned request,
  120.                                     const char *errname, uint32_t *out)
  121. {
  122.     struct drm_radeon_info info;
  123.     int retval;
  124.  
  125.     memset(&info, 0, sizeof(info));
  126.  
  127.     info.value = (unsigned long)out;
  128.     info.request = request;
  129.  
  130.     retval = drmCommandWriteRead(fd, DRM_RADEON_INFO, &info, sizeof(info));
  131.     if (retval) {
  132.         if (errname) {
  133.             fprintf(stderr, "radeon: Failed to get %s, error number %d\n",
  134.                     errname, retval);
  135.         }
  136.         return FALSE;
  137.     }
  138.     return TRUE;
  139. }
  140.  
  141. /* Helper function to do the ioctls needed for setup and init. */
  142. static boolean do_winsys_init(struct radeon_drm_winsys *ws)
  143. {
  144.     struct drm_radeon_gem_info gem_info;
  145.     int retval;
  146.     drmVersionPtr version;
  147.  
  148.     memset(&gem_info, 0, sizeof(gem_info));
  149.  
  150.     /* We do things in a specific order here.
  151.      *
  152.      * DRM version first. We need to be sure we're running on a KMS chipset.
  153.      * This is also for some features.
  154.      *
  155.      * Then, the PCI ID. This is essential and should return usable numbers
  156.      * for all Radeons. If this fails, we probably got handed an FD for some
  157.      * non-Radeon card.
  158.      *
  159.      * The GEM info is actually bogus on the kernel side, as well as our side
  160.      * (see radeon_gem_info_ioctl in radeon_gem.c) but that's alright because
  161.      * we don't actually use the info for anything yet.
  162.      *
  163.      * The GB and Z pipe requests should always succeed, but they might not
  164.      * return sensical values for all chipsets, but that's alright because
  165.      * the pipe drivers already know that.
  166.      */
  167.  
  168.     /* Get DRM version. */
  169.     version = drmGetVersion(ws->fd);
  170.     if (version->version_major != 2 ||
  171.         version->version_minor < 3) {
  172.         fprintf(stderr, "%s: DRM version is %d.%d.%d but this driver is "
  173.                 "only compatible with 2.3.x (kernel 2.6.34) or later.\n",
  174.                 __FUNCTION__,
  175.                 version->version_major,
  176.                 version->version_minor,
  177.                 version->version_patchlevel);
  178.         drmFreeVersion(version);
  179.         return FALSE;
  180.     }
  181.  
  182.     ws->info.drm_major = version->version_major;
  183.     ws->info.drm_minor = version->version_minor;
  184.     ws->info.drm_patchlevel = version->version_patchlevel;
  185.     drmFreeVersion(version);
  186.  
  187.     /* Get PCI ID. */
  188.     if (!radeon_get_drm_value(ws->fd, RADEON_INFO_DEVICE_ID, "PCI ID",
  189.                               &ws->info.pci_id))
  190.         return FALSE;
  191.  
  192.     /* Check PCI ID. */
  193.     switch (ws->info.pci_id) {
  194. #define CHIPSET(pci_id, name, cfamily) case pci_id: ws->info.family = CHIP_##cfamily; ws->gen = DRV_R300; break;
  195. #include "pci_ids/r300_pci_ids.h"
  196. #undef CHIPSET
  197.  
  198. #define CHIPSET(pci_id, name, cfamily) case pci_id: ws->info.family = CHIP_##cfamily; ws->gen = DRV_R600; break;
  199. #include "pci_ids/r600_pci_ids.h"
  200. #undef CHIPSET
  201.  
  202. #define CHIPSET(pci_id, name, cfamily) case pci_id: ws->info.family = CHIP_##cfamily; ws->gen = DRV_SI; break;
  203. #include "pci_ids/radeonsi_pci_ids.h"
  204. #undef CHIPSET
  205.  
  206.     default:
  207.         fprintf(stderr, "radeon: Invalid PCI ID.\n");
  208.         return FALSE;
  209.     }
  210.  
  211.     switch (ws->info.family) {
  212.     default:
  213.     case CHIP_UNKNOWN:
  214.         fprintf(stderr, "radeon: Unknown family.\n");
  215.         return FALSE;
  216.     case CHIP_R300:
  217.     case CHIP_R350:
  218.     case CHIP_RV350:
  219.     case CHIP_RV370:
  220.     case CHIP_RV380:
  221.     case CHIP_RS400:
  222.     case CHIP_RC410:
  223.     case CHIP_RS480:
  224.         ws->info.chip_class = R300;
  225.         break;
  226.     case CHIP_R420:     /* R4xx-based cores. */
  227.     case CHIP_R423:
  228.     case CHIP_R430:
  229.     case CHIP_R480:
  230.     case CHIP_R481:
  231.     case CHIP_RV410:
  232.     case CHIP_RS600:
  233.     case CHIP_RS690:
  234.     case CHIP_RS740:
  235.         ws->info.chip_class = R400;
  236.         break;
  237.     case CHIP_RV515:    /* R5xx-based cores. */
  238.     case CHIP_R520:
  239.     case CHIP_RV530:
  240.     case CHIP_R580:
  241.     case CHIP_RV560:
  242.     case CHIP_RV570:
  243.         ws->info.chip_class = R500;
  244.         break;
  245.     case CHIP_R600:
  246.     case CHIP_RV610:
  247.     case CHIP_RV630:
  248.     case CHIP_RV670:
  249.     case CHIP_RV620:
  250.     case CHIP_RV635:
  251.     case CHIP_RS780:
  252.     case CHIP_RS880:
  253.         ws->info.chip_class = R600;
  254.         break;
  255.     case CHIP_RV770:
  256.     case CHIP_RV730:
  257.     case CHIP_RV710:
  258.     case CHIP_RV740:
  259.         ws->info.chip_class = R700;
  260.         break;
  261.     case CHIP_CEDAR:
  262.     case CHIP_REDWOOD:
  263.     case CHIP_JUNIPER:
  264.     case CHIP_CYPRESS:
  265.     case CHIP_HEMLOCK:
  266.     case CHIP_PALM:
  267.     case CHIP_SUMO:
  268.     case CHIP_SUMO2:
  269.     case CHIP_BARTS:
  270.     case CHIP_TURKS:
  271.     case CHIP_CAICOS:
  272.         ws->info.chip_class = EVERGREEN;
  273.         break;
  274.     case CHIP_CAYMAN:
  275.     case CHIP_ARUBA:
  276.         ws->info.chip_class = CAYMAN;
  277.         break;
  278.     case CHIP_TAHITI:
  279.     case CHIP_PITCAIRN:
  280.     case CHIP_VERDE:
  281.     case CHIP_OLAND:
  282.     case CHIP_HAINAN:
  283.         ws->info.chip_class = SI;
  284.         break;
  285.     case CHIP_BONAIRE:
  286.     case CHIP_KAVERI:
  287.     case CHIP_KABINI:
  288.     case CHIP_HAWAII:
  289.     case CHIP_MULLINS:
  290.         ws->info.chip_class = CIK;
  291.         break;
  292.     }
  293.  
  294.     /* Check for dma */
  295.     ws->info.r600_has_dma = FALSE;
  296.     /* DMA is disabled on R700. There is IB corruption and hangs. */
  297.     if (ws->info.chip_class >= EVERGREEN && ws->info.drm_minor >= 27) {
  298.         ws->info.r600_has_dma = TRUE;
  299.     }
  300.  
  301.     /* Check for UVD and VCE */
  302.     ws->info.has_uvd = FALSE;
  303.     ws->info.vce_fw_version = 0x00000000;
  304.     if (ws->info.drm_minor >= 32) {
  305.         uint32_t value = RADEON_CS_RING_UVD;
  306.         if (radeon_get_drm_value(ws->fd, RADEON_INFO_RING_WORKING,
  307.                                  "UVD Ring working", &value))
  308.             ws->info.has_uvd = value;
  309.  
  310.         value = RADEON_CS_RING_VCE;
  311.         if (radeon_get_drm_value(ws->fd, RADEON_INFO_RING_WORKING,
  312.                                  NULL, &value) && value) {
  313.  
  314.             if (radeon_get_drm_value(ws->fd, RADEON_INFO_VCE_FW_VERSION,
  315.                                      "VCE FW version", &value))
  316.                 ws->info.vce_fw_version = value;
  317.         }
  318.     }
  319.  
  320.     /* Check for userptr support. */
  321.     {
  322.         struct drm_radeon_gem_userptr args = {0};
  323.  
  324.         /* If the ioctl doesn't exist, -EINVAL is returned.
  325.          *
  326.          * If the ioctl exists, it should return -EACCES
  327.          * if RADEON_GEM_USERPTR_READONLY or RADEON_GEM_USERPTR_REGISTER
  328.          * aren't set.
  329.          */
  330.         ws->info.has_userptr =
  331.             drmCommandWriteRead(ws->fd, DRM_RADEON_GEM_USERPTR,
  332.                                 &args, sizeof(args)) == -EACCES;
  333.     }
  334.  
  335.     /* Get GEM info. */
  336.     retval = drmCommandWriteRead(ws->fd, DRM_RADEON_GEM_INFO,
  337.             &gem_info, sizeof(gem_info));
  338.     if (retval) {
  339.         fprintf(stderr, "radeon: Failed to get MM info, error number %d\n",
  340.                 retval);
  341.         return FALSE;
  342.     }
  343.     ws->info.gart_size = gem_info.gart_size;
  344.     ws->info.vram_size = gem_info.vram_size;
  345.  
  346.     /* Get max clock frequency info and convert it to MHz */
  347.     radeon_get_drm_value(ws->fd, RADEON_INFO_MAX_SCLK, NULL,
  348.                          &ws->info.max_sclk);
  349.     ws->info.max_sclk /= 1000;
  350.  
  351.     radeon_get_drm_value(ws->fd, RADEON_INFO_SI_BACKEND_ENABLED_MASK, NULL,
  352.                          &ws->info.si_backend_enabled_mask);
  353.  
  354.     ws->num_cpus = sysconf(_SC_NPROCESSORS_ONLN);
  355.  
  356.     /* Generation-specific queries. */
  357.     if (ws->gen == DRV_R300) {
  358.         if (!radeon_get_drm_value(ws->fd, RADEON_INFO_NUM_GB_PIPES,
  359.                                   "GB pipe count",
  360.                                   &ws->info.r300_num_gb_pipes))
  361.             return FALSE;
  362.  
  363.         if (!radeon_get_drm_value(ws->fd, RADEON_INFO_NUM_Z_PIPES,
  364.                                   "Z pipe count",
  365.                                   &ws->info.r300_num_z_pipes))
  366.             return FALSE;
  367.     }
  368.     else if (ws->gen >= DRV_R600) {
  369.         if (ws->info.drm_minor >= 9 &&
  370.             !radeon_get_drm_value(ws->fd, RADEON_INFO_NUM_BACKENDS,
  371.                                   "num backends",
  372.                                   &ws->info.r600_num_backends))
  373.             return FALSE;
  374.  
  375.         /* get the GPU counter frequency, failure is not fatal */
  376.         radeon_get_drm_value(ws->fd, RADEON_INFO_CLOCK_CRYSTAL_FREQ, NULL,
  377.                              &ws->info.r600_clock_crystal_freq);
  378.  
  379.         radeon_get_drm_value(ws->fd, RADEON_INFO_TILING_CONFIG, NULL,
  380.                              &ws->info.r600_tiling_config);
  381.  
  382.         if (ws->info.drm_minor >= 11) {
  383.             radeon_get_drm_value(ws->fd, RADEON_INFO_NUM_TILE_PIPES, NULL,
  384.                                  &ws->info.r600_num_tile_pipes);
  385.  
  386.             if (radeon_get_drm_value(ws->fd, RADEON_INFO_BACKEND_MAP, NULL,
  387.                                       &ws->info.r600_backend_map))
  388.                 ws->info.r600_backend_map_valid = TRUE;
  389.         }
  390.  
  391.         ws->info.r600_virtual_address = FALSE;
  392.         if (ws->info.drm_minor >= 13) {
  393.             uint32_t ib_vm_max_size;
  394.  
  395.             ws->info.r600_virtual_address = TRUE;
  396.             if (!radeon_get_drm_value(ws->fd, RADEON_INFO_VA_START, NULL,
  397.                                       &ws->va_start))
  398.                 ws->info.r600_virtual_address = FALSE;
  399.             if (!radeon_get_drm_value(ws->fd, RADEON_INFO_IB_VM_MAX_SIZE, NULL,
  400.                                       &ib_vm_max_size))
  401.                 ws->info.r600_virtual_address = FALSE;
  402.         }
  403.         if (ws->gen == DRV_R600 && !debug_get_bool_option("RADEON_VA", FALSE))
  404.                 ws->info.r600_virtual_address = FALSE;
  405.     }
  406.  
  407.     /* Get max pipes, this is only needed for compute shaders.  All evergreen+
  408.      * chips have at least 2 pipes, so we use 2 as a default. */
  409.     ws->info.r600_max_pipes = 2;
  410.     radeon_get_drm_value(ws->fd, RADEON_INFO_MAX_PIPES, NULL,
  411.                          &ws->info.r600_max_pipes);
  412.  
  413.     /* All GPUs have at least one compute unit */
  414.     ws->info.max_compute_units = 1;
  415.     radeon_get_drm_value(ws->fd, RADEON_INFO_ACTIVE_CU_COUNT, NULL,
  416.                          &ws->info.max_compute_units);
  417.  
  418.     radeon_get_drm_value(ws->fd, RADEON_INFO_MAX_SE, NULL,
  419.                          &ws->info.max_se);
  420.  
  421.     if (!ws->info.max_se) {
  422.         switch (ws->info.family) {
  423.         default:
  424.             ws->info.max_se = 1;
  425.             break;
  426.         case CHIP_CYPRESS:
  427.         case CHIP_HEMLOCK:
  428.         case CHIP_BARTS:
  429.         case CHIP_CAYMAN:
  430.         case CHIP_TAHITI:
  431.         case CHIP_PITCAIRN:
  432.         case CHIP_BONAIRE:
  433.             ws->info.max_se = 2;
  434.             break;
  435.         case CHIP_HAWAII:
  436.             ws->info.max_se = 4;
  437.             break;
  438.         }
  439.     }
  440.  
  441.     radeon_get_drm_value(ws->fd, RADEON_INFO_MAX_SH_PER_SE, NULL,
  442.                          &ws->info.max_sh_per_se);
  443.  
  444.     radeon_get_drm_value(ws->fd, RADEON_INFO_ACCEL_WORKING2, NULL,
  445.                          &ws->accel_working2);
  446.     if (ws->info.family == CHIP_HAWAII && ws->accel_working2 < 2) {
  447.         fprintf(stderr, "radeon: GPU acceleration for Hawaii disabled, "
  448.                 "returned accel_working2 value %u is smaller than 2. "
  449.                 "Please install a newer kernel.\n",
  450.                 ws->accel_working2);
  451.         return FALSE;
  452.     }
  453.  
  454.     if (radeon_get_drm_value(ws->fd, RADEON_INFO_SI_TILE_MODE_ARRAY, NULL,
  455.                              ws->info.si_tile_mode_array)) {
  456.         ws->info.si_tile_mode_array_valid = TRUE;
  457.     }
  458.  
  459.     if (radeon_get_drm_value(ws->fd, RADEON_INFO_CIK_MACROTILE_MODE_ARRAY, NULL,
  460.                              ws->info.cik_macrotile_mode_array)) {
  461.         ws->info.cik_macrotile_mode_array_valid = TRUE;
  462.     }
  463.  
  464.     return TRUE;
  465. }
  466.  
  467. static void radeon_winsys_destroy(struct radeon_winsys *rws)
  468. {
  469.     struct radeon_drm_winsys *ws = (struct radeon_drm_winsys*)rws;
  470.  
  471.     if (ws->thread) {
  472.         ws->kill_thread = 1;
  473.         pipe_semaphore_signal(&ws->cs_queued);
  474.         pipe_thread_wait(ws->thread);
  475.     }
  476.     pipe_semaphore_destroy(&ws->cs_queued);
  477.  
  478.     pipe_mutex_destroy(ws->hyperz_owner_mutex);
  479.     pipe_mutex_destroy(ws->cmask_owner_mutex);
  480.     pipe_mutex_destroy(ws->cs_stack_lock);
  481.  
  482.     ws->cman->destroy(ws->cman);
  483.     ws->kman->destroy(ws->kman);
  484.     if (ws->gen >= DRV_R600) {
  485.         radeon_surface_manager_free(ws->surf_man);
  486.     }
  487.     FREE(rws);
  488. }
  489.  
  490. static void radeon_query_info(struct radeon_winsys *rws,
  491.                               struct radeon_info *info)
  492. {
  493.     *info = ((struct radeon_drm_winsys *)rws)->info;
  494. }
  495.  
  496. static boolean radeon_cs_request_feature(struct radeon_winsys_cs *rcs,
  497.                                          enum radeon_feature_id fid,
  498.                                          boolean enable)
  499. {
  500.     struct radeon_drm_cs *cs = radeon_drm_cs(rcs);
  501.  
  502.     switch (fid) {
  503.     case RADEON_FID_R300_HYPERZ_ACCESS:
  504.         return radeon_set_fd_access(cs, &cs->ws->hyperz_owner,
  505.                                     &cs->ws->hyperz_owner_mutex,
  506.                                     RADEON_INFO_WANT_HYPERZ, "Hyper-Z",
  507.                                     enable);
  508.  
  509.     case RADEON_FID_R300_CMASK_ACCESS:
  510.         return radeon_set_fd_access(cs, &cs->ws->cmask_owner,
  511.                                     &cs->ws->cmask_owner_mutex,
  512.                                     RADEON_INFO_WANT_CMASK, "AA optimizations",
  513.                                     enable);
  514.     }
  515.     return FALSE;
  516. }
  517.  
  518. static uint64_t radeon_query_value(struct radeon_winsys *rws,
  519.                                    enum radeon_value_id value)
  520. {
  521.     struct radeon_drm_winsys *ws = (struct radeon_drm_winsys*)rws;
  522.     uint64_t retval = 0;
  523.  
  524.     switch (value) {
  525.     case RADEON_REQUESTED_VRAM_MEMORY:
  526.         return ws->allocated_vram;
  527.     case RADEON_REQUESTED_GTT_MEMORY:
  528.         return ws->allocated_gtt;
  529.     case RADEON_BUFFER_WAIT_TIME_NS:
  530.         return ws->buffer_wait_time;
  531.     case RADEON_TIMESTAMP:
  532.         if (ws->info.drm_minor < 20 || ws->gen < DRV_R600) {
  533.             assert(0);
  534.             return 0;
  535.         }
  536.  
  537.         radeon_get_drm_value(ws->fd, RADEON_INFO_TIMESTAMP, "timestamp",
  538.                              (uint32_t*)&retval);
  539.         return retval;
  540.     case RADEON_NUM_CS_FLUSHES:
  541.         return ws->num_cs_flushes;
  542.     case RADEON_NUM_BYTES_MOVED:
  543.         radeon_get_drm_value(ws->fd, RADEON_INFO_NUM_BYTES_MOVED,
  544.                              "num-bytes-moved", (uint32_t*)&retval);
  545.         return retval;
  546.     case RADEON_VRAM_USAGE:
  547.         radeon_get_drm_value(ws->fd, RADEON_INFO_VRAM_USAGE,
  548.                              "vram-usage", (uint32_t*)&retval);
  549.         return retval;
  550.     case RADEON_GTT_USAGE:
  551.         radeon_get_drm_value(ws->fd, RADEON_INFO_GTT_USAGE,
  552.                              "gtt-usage", (uint32_t*)&retval);
  553.         return retval;
  554.     case RADEON_GPU_TEMPERATURE:
  555.         radeon_get_drm_value(ws->fd, RADEON_INFO_CURRENT_GPU_TEMP,
  556.                              "gpu-temp", (uint32_t*)&retval);
  557.         return retval;
  558.     case RADEON_CURRENT_SCLK:
  559.         radeon_get_drm_value(ws->fd, RADEON_INFO_CURRENT_GPU_SCLK,
  560.                              "current-gpu-sclk", (uint32_t*)&retval);
  561.         return retval;
  562.     case RADEON_CURRENT_MCLK:
  563.         radeon_get_drm_value(ws->fd, RADEON_INFO_CURRENT_GPU_MCLK,
  564.                              "current-gpu-mclk", (uint32_t*)&retval);
  565.         return retval;
  566.     }
  567.     return 0;
  568. }
  569.  
  570. static void radeon_read_registers(struct radeon_winsys *rws,
  571.                                   unsigned reg_offset,
  572.                                   unsigned num_registers, uint32_t *out)
  573. {
  574.     struct radeon_drm_winsys *ws = (struct radeon_drm_winsys*)rws;
  575.     unsigned i;
  576.  
  577.     for (i = 0; i < num_registers; i++) {
  578.         uint32_t reg = reg_offset + i*4;
  579.  
  580.         radeon_get_drm_value(ws->fd, RADEON_INFO_READ_REG, "read-reg", &reg);
  581.         out[i] = reg;
  582.     }
  583. }
  584.  
  585. static unsigned hash_fd(void *key)
  586. {
  587.     int fd = pointer_to_intptr(key);
  588.     struct stat stat;
  589.     fstat(fd, &stat);
  590.  
  591.     return stat.st_dev ^ stat.st_ino ^ stat.st_rdev;
  592. }
  593.  
  594. static int compare_fd(void *key1, void *key2)
  595. {
  596.     int fd1 = pointer_to_intptr(key1);
  597.     int fd2 = pointer_to_intptr(key2);
  598.     struct stat stat1, stat2;
  599.     fstat(fd1, &stat1);
  600.     fstat(fd2, &stat2);
  601.  
  602.     return stat1.st_dev != stat2.st_dev ||
  603.            stat1.st_ino != stat2.st_ino ||
  604.            stat1.st_rdev != stat2.st_rdev;
  605. }
  606.  
  607. void radeon_drm_ws_queue_cs(struct radeon_drm_winsys *ws, struct radeon_drm_cs *cs)
  608. {
  609. retry:
  610.     pipe_mutex_lock(ws->cs_stack_lock);
  611.     if (ws->ncs >= RING_LAST) {
  612.         /* no room left for a flush */
  613.         pipe_mutex_unlock(ws->cs_stack_lock);
  614.         goto retry;
  615.     }
  616.     ws->cs_stack[ws->ncs++] = cs;
  617.     pipe_mutex_unlock(ws->cs_stack_lock);
  618.     pipe_semaphore_signal(&ws->cs_queued);
  619. }
  620.  
  621. static PIPE_THREAD_ROUTINE(radeon_drm_cs_emit_ioctl, param)
  622. {
  623.     struct radeon_drm_winsys *ws = (struct radeon_drm_winsys *)param;
  624.     struct radeon_drm_cs *cs;
  625.     unsigned i;
  626.  
  627.     while (1) {
  628.         pipe_semaphore_wait(&ws->cs_queued);
  629.         if (ws->kill_thread)
  630.             break;
  631.  
  632.         pipe_mutex_lock(ws->cs_stack_lock);
  633.         cs = ws->cs_stack[0];
  634.         for (i = 1; i < ws->ncs; i++)
  635.             ws->cs_stack[i - 1] = ws->cs_stack[i];
  636.         ws->cs_stack[--ws->ncs] = NULL;
  637.         pipe_mutex_unlock(ws->cs_stack_lock);
  638.  
  639.         if (cs) {
  640.             radeon_drm_cs_emit_ioctl_oneshot(cs, cs->cst);
  641.             pipe_semaphore_signal(&cs->flush_completed);
  642.         }
  643.     }
  644.     pipe_mutex_lock(ws->cs_stack_lock);
  645.     for (i = 0; i < ws->ncs; i++) {
  646.         pipe_semaphore_signal(&ws->cs_stack[i]->flush_completed);
  647.         ws->cs_stack[i] = NULL;
  648.     }
  649.     ws->ncs = 0;
  650.     pipe_mutex_unlock(ws->cs_stack_lock);
  651.     return 0;
  652. }
  653.  
  654. DEBUG_GET_ONCE_BOOL_OPTION(thread, "RADEON_THREAD", TRUE)
  655. static PIPE_THREAD_ROUTINE(radeon_drm_cs_emit_ioctl, param);
  656.  
  657. static bool radeon_winsys_unref(struct radeon_winsys *ws)
  658. {
  659.     struct radeon_drm_winsys *rws = (struct radeon_drm_winsys*)ws;
  660.     bool destroy;
  661.  
  662.     /* When the reference counter drops to zero, remove the fd from the table.
  663.      * This must happen while the mutex is locked, so that
  664.      * radeon_drm_winsys_create in another thread doesn't get the winsys
  665.      * from the table when the counter drops to 0. */
  666.     pipe_mutex_lock(fd_tab_mutex);
  667.  
  668.     destroy = pipe_reference(&rws->reference, NULL);
  669.     if (destroy && fd_tab)
  670.         util_hash_table_remove(fd_tab, intptr_to_pointer(rws->fd));
  671.  
  672.     pipe_mutex_unlock(fd_tab_mutex);
  673.     return destroy;
  674. }
  675.  
  676. PUBLIC struct radeon_winsys *
  677. radeon_drm_winsys_create(int fd, radeon_screen_create_t screen_create)
  678. {
  679.     struct radeon_drm_winsys *ws;
  680.  
  681.     pipe_mutex_lock(fd_tab_mutex);
  682.     if (!fd_tab) {
  683.         fd_tab = util_hash_table_create(hash_fd, compare_fd);
  684.     }
  685.  
  686.     ws = util_hash_table_get(fd_tab, intptr_to_pointer(fd));
  687.     if (ws) {
  688.         pipe_reference(NULL, &ws->reference);
  689.         pipe_mutex_unlock(fd_tab_mutex);
  690.         return &ws->base;
  691.     }
  692.  
  693.     ws = CALLOC_STRUCT(radeon_drm_winsys);
  694.     if (!ws) {
  695.         pipe_mutex_unlock(fd_tab_mutex);
  696.         return NULL;
  697.     }
  698.  
  699.     ws->fd = fd;
  700.  
  701.     if (!do_winsys_init(ws))
  702.         goto fail;
  703.  
  704.     /* Create managers. */
  705.     ws->kman = radeon_bomgr_create(ws);
  706.     if (!ws->kman)
  707.         goto fail;
  708.  
  709.     ws->cman = pb_cache_manager_create(ws->kman, 1000000, 2.0f, 0,
  710.                                        MIN2(ws->info.vram_size, ws->info.gart_size));
  711.     if (!ws->cman)
  712.         goto fail;
  713.  
  714.     if (ws->gen >= DRV_R600) {
  715.         ws->surf_man = radeon_surface_manager_new(fd);
  716.         if (!ws->surf_man)
  717.             goto fail;
  718.     }
  719.  
  720.     /* init reference */
  721.     pipe_reference_init(&ws->reference, 1);
  722.  
  723.     /* Set functions. */
  724.     ws->base.unref = radeon_winsys_unref;
  725.     ws->base.destroy = radeon_winsys_destroy;
  726.     ws->base.query_info = radeon_query_info;
  727.     ws->base.cs_request_feature = radeon_cs_request_feature;
  728.     ws->base.query_value = radeon_query_value;
  729.     ws->base.read_registers = radeon_read_registers;
  730.  
  731.     radeon_bomgr_init_functions(ws);
  732.     radeon_drm_cs_init_functions(ws);
  733.     radeon_surface_init_functions(ws);
  734.  
  735.     pipe_mutex_init(ws->hyperz_owner_mutex);
  736.     pipe_mutex_init(ws->cmask_owner_mutex);
  737.     pipe_mutex_init(ws->cs_stack_lock);
  738.  
  739.     ws->ncs = 0;
  740.     pipe_semaphore_init(&ws->cs_queued, 0);
  741.     if (ws->num_cpus > 1 && debug_get_option_thread())
  742.         ws->thread = pipe_thread_create(radeon_drm_cs_emit_ioctl, ws);
  743.  
  744.     /* Create the screen at the end. The winsys must be initialized
  745.      * completely.
  746.      *
  747.      * Alternatively, we could create the screen based on "ws->gen"
  748.      * and link all drivers into one binary blob. */
  749.     ws->base.screen = screen_create(&ws->base);
  750.     if (!ws->base.screen) {
  751.         radeon_winsys_destroy(&ws->base);
  752.         pipe_mutex_unlock(fd_tab_mutex);
  753.         return NULL;
  754.     }
  755.  
  756.     util_hash_table_set(fd_tab, intptr_to_pointer(fd), ws);
  757.  
  758.     /* We must unlock the mutex once the winsys is fully initialized, so that
  759.      * other threads attempting to create the winsys from the same fd will
  760.      * get a fully initialized winsys and not just half-way initialized. */
  761.     pipe_mutex_unlock(fd_tab_mutex);
  762.  
  763.     return &ws->base;
  764.  
  765. fail:
  766.     pipe_mutex_unlock(fd_tab_mutex);
  767.     if (ws->cman)
  768.         ws->cman->destroy(ws->cman);
  769.     if (ws->kman)
  770.         ws->kman->destroy(ws->kman);
  771.     if (ws->surf_man)
  772.         radeon_surface_manager_free(ws->surf_man);
  773.     FREE(ws);
  774.     return NULL;
  775. }
  776.