~ubuntu-branches/ubuntu/trusty/libdrm/trusty-proposed

« back to all changes in this revision

Viewing changes to intel/intel_bufmgr_gem.c

  • Committer: Package Import Robot
  • Author(s): Robert Hooker
  • Date: 2011-12-19 21:33:42 UTC
  • mfrom: (2.3.14 sid)
  • Revision ID: package-import@ubuntu.com-20111219213342-75t0g23vx5hbrzv3
Tags: 2.4.29-1ubuntu1
* Merge from Debian unstable, remaining changes:
  - debian/rules
  - debian/control:
    + Build libdrm-intel1 everywhere rather than just {i386,amd64}
      for Plymouth

Show diffs side-by-side

added added

removed removed

Lines of Context:
97
97
        time_t time;
98
98
 
99
99
        drmMMListHead named;
 
100
        drmMMListHead vma_cache;
 
101
        int vma_count, vma_open, vma_max;
100
102
 
101
103
        uint64_t gtt_size;
102
104
        int available_fences;
156
158
        void *mem_virtual;
157
159
        /** GTT virtual address for the buffer, saved across map/unmap cycles */
158
160
        void *gtt_virtual;
 
161
        int map_count;
 
162
        drmMMListHead vma_list;
159
163
 
160
164
        /** BO cache list */
161
165
        drmMMListHead head;
700
704
                }
701
705
 
702
706
                DRMINITLISTHEAD(&bo_gem->name_list);
 
707
                DRMINITLISTHEAD(&bo_gem->vma_list);
703
708
        }
704
709
 
705
710
        bo_gem->name = name;
865
870
        /* XXX stride is unknown */
866
871
        drm_intel_bo_gem_set_in_aperture_size(bufmgr_gem, bo_gem);
867
872
 
 
873
        DRMINITLISTHEAD(&bo_gem->vma_list);
868
874
        DRMLISTADDTAIL(&bo_gem->name_list, &bufmgr_gem->named);
869
875
        DBG("bo_create_from_handle: %d (%s)\n", handle, bo_gem->name);
870
876
 
879
885
        struct drm_gem_close close;
880
886
        int ret;
881
887
 
882
 
        if (bo_gem->mem_virtual)
 
888
        DRMLISTDEL(&bo_gem->vma_list);
 
889
        if (bo_gem->mem_virtual) {
883
890
                munmap(bo_gem->mem_virtual, bo_gem->bo.size);
884
 
        if (bo_gem->gtt_virtual)
 
891
                bufmgr_gem->vma_count--;
 
892
        }
 
893
        if (bo_gem->gtt_virtual) {
885
894
                munmap(bo_gem->gtt_virtual, bo_gem->bo.size);
 
895
                bufmgr_gem->vma_count--;
 
896
        }
886
897
 
887
898
        /* Close this object */
888
899
        memset(&close, 0, sizeof(close));
925
936
        bufmgr_gem->time = time;
926
937
}
927
938
 
 
939
static void drm_intel_gem_bo_purge_vma_cache(drm_intel_bufmgr_gem *bufmgr_gem)
 
940
{
 
941
        int limit;
 
942
 
 
943
        DBG("%s: cached=%d, open=%d, limit=%d\n", __FUNCTION__,
 
944
            bufmgr_gem->vma_count, bufmgr_gem->vma_open, bufmgr_gem->vma_max);
 
945
 
 
946
        if (bufmgr_gem->vma_max < 0)
 
947
                return;
 
948
 
 
949
        /* We may need to evict a few entries in order to create new mmaps */
 
950
        limit = bufmgr_gem->vma_max - 2*bufmgr_gem->vma_open;
 
951
        if (limit < 0)
 
952
                limit = 0;
 
953
 
 
954
        while (bufmgr_gem->vma_count > limit) {
 
955
                drm_intel_bo_gem *bo_gem;
 
956
 
 
957
                bo_gem = DRMLISTENTRY(drm_intel_bo_gem,
 
958
                                      bufmgr_gem->vma_cache.next,
 
959
                                      vma_list);
 
960
                assert(bo_gem->map_count == 0);
 
961
                DRMLISTDEL(&bo_gem->vma_list);
 
962
 
 
963
                if (bo_gem->mem_virtual) {
 
964
                        munmap(bo_gem->mem_virtual, bo_gem->bo.size);
 
965
                        bo_gem->mem_virtual = NULL;
 
966
                        bufmgr_gem->vma_count--;
 
967
                }
 
968
                if (bo_gem->gtt_virtual) {
 
969
                        munmap(bo_gem->gtt_virtual, bo_gem->bo.size);
 
970
                        bo_gem->gtt_virtual = NULL;
 
971
                        bufmgr_gem->vma_count--;
 
972
                }
 
973
        }
 
974
}
 
975
 
 
976
static void drm_intel_gem_bo_close_vma(drm_intel_bufmgr_gem *bufmgr_gem,
 
977
                                       drm_intel_bo_gem *bo_gem)
 
978
{
 
979
        bufmgr_gem->vma_open--;
 
980
        DRMLISTADDTAIL(&bo_gem->vma_list, &bufmgr_gem->vma_cache);
 
981
        if (bo_gem->mem_virtual)
 
982
                bufmgr_gem->vma_count++;
 
983
        if (bo_gem->gtt_virtual)
 
984
                bufmgr_gem->vma_count++;
 
985
        drm_intel_gem_bo_purge_vma_cache(bufmgr_gem);
 
986
}
 
987
 
 
988
static void drm_intel_gem_bo_open_vma(drm_intel_bufmgr_gem *bufmgr_gem,
 
989
                                      drm_intel_bo_gem *bo_gem)
 
990
{
 
991
        bufmgr_gem->vma_open++;
 
992
        DRMLISTDEL(&bo_gem->vma_list);
 
993
        if (bo_gem->mem_virtual)
 
994
                bufmgr_gem->vma_count--;
 
995
        if (bo_gem->gtt_virtual)
 
996
                bufmgr_gem->vma_count--;
 
997
        drm_intel_gem_bo_purge_vma_cache(bufmgr_gem);
 
998
}
 
999
 
928
1000
static void
929
1001
drm_intel_gem_bo_unreference_final(drm_intel_bo *bo, time_t time)
930
1002
{
957
1029
                bo_gem->relocs = NULL;
958
1030
        }
959
1031
 
 
1032
        /* Clear any left-over mappings */
 
1033
        if (bo_gem->map_count) {
 
1034
                DBG("bo freed with non-zero map-count %d\n", bo_gem->map_count);
 
1035
                bo_gem->map_count = 0;
 
1036
                drm_intel_gem_bo_close_vma(bufmgr_gem, bo_gem);
 
1037
        }
 
1038
 
960
1039
        DRMLISTDEL(&bo_gem->name_list);
961
1040
 
962
1041
        bucket = drm_intel_gem_bo_bucket_for_size(bufmgr_gem, bo->size);
1013
1092
 
1014
1093
        pthread_mutex_lock(&bufmgr_gem->lock);
1015
1094
 
 
1095
        if (bo_gem->map_count++ == 0)
 
1096
                drm_intel_gem_bo_open_vma(bufmgr_gem, bo_gem);
 
1097
 
1016
1098
        if (!bo_gem->mem_virtual) {
1017
1099
                struct drm_i915_gem_mmap mmap_arg;
1018
1100
 
1019
 
                DBG("bo_map: %d (%s)\n", bo_gem->gem_handle, bo_gem->name);
 
1101
                DBG("bo_map: %d (%s), map_count=%d\n",
 
1102
                    bo_gem->gem_handle, bo_gem->name, bo_gem->map_count);
1020
1103
 
1021
1104
                memset(&mmap_arg, 0, sizeof(mmap_arg));
1022
1105
                mmap_arg.handle = bo_gem->gem_handle;
1030
1113
                        DBG("%s:%d: Error mapping buffer %d (%s): %s .\n",
1031
1114
                            __FILE__, __LINE__, bo_gem->gem_handle,
1032
1115
                            bo_gem->name, strerror(errno));
 
1116
                        if (--bo_gem->map_count == 0)
 
1117
                                drm_intel_gem_bo_close_vma(bufmgr_gem, bo_gem);
1033
1118
                        pthread_mutex_unlock(&bufmgr_gem->lock);
1034
1119
                        return ret;
1035
1120
                }
1071
1156
 
1072
1157
        pthread_mutex_lock(&bufmgr_gem->lock);
1073
1158
 
 
1159
        if (bo_gem->map_count++ == 0)
 
1160
                drm_intel_gem_bo_open_vma(bufmgr_gem, bo_gem);
 
1161
 
1074
1162
        /* Get a mapping of the buffer if we haven't before. */
1075
1163
        if (bo_gem->gtt_virtual == NULL) {
1076
1164
                struct drm_i915_gem_mmap_gtt mmap_arg;
1077
1165
 
1078
 
                DBG("bo_map_gtt: mmap %d (%s)\n", bo_gem->gem_handle,
1079
 
                    bo_gem->name);
 
1166
                DBG("bo_map_gtt: mmap %d (%s), map_count=%d\n",
 
1167
                    bo_gem->gem_handle, bo_gem->name, bo_gem->map_count);
1080
1168
 
1081
1169
                memset(&mmap_arg, 0, sizeof(mmap_arg));
1082
1170
                mmap_arg.handle = bo_gem->gem_handle;
1091
1179
                            __FILE__, __LINE__,
1092
1180
                            bo_gem->gem_handle, bo_gem->name,
1093
1181
                            strerror(errno));
 
1182
                        if (--bo_gem->map_count == 0)
 
1183
                                drm_intel_gem_bo_close_vma(bufmgr_gem, bo_gem);
1094
1184
                        pthread_mutex_unlock(&bufmgr_gem->lock);
1095
1185
                        return ret;
1096
1186
                }
1106
1196
                            __FILE__, __LINE__,
1107
1197
                            bo_gem->gem_handle, bo_gem->name,
1108
1198
                            strerror(errno));
 
1199
                        if (--bo_gem->map_count == 0)
 
1200
                                drm_intel_gem_bo_close_vma(bufmgr_gem, bo_gem);
1109
1201
                        pthread_mutex_unlock(&bufmgr_gem->lock);
1110
1202
                        return ret;
1111
1203
                }
1146
1238
 
1147
1239
        pthread_mutex_lock(&bufmgr_gem->lock);
1148
1240
 
 
1241
        if (bo_gem->map_count <= 0) {
 
1242
                DBG("attempted to unmap an unmapped bo\n");
 
1243
                pthread_mutex_unlock(&bufmgr_gem->lock);
 
1244
                /* Preserve the old behaviour of just treating this as a
 
1245
                 * no-op rather than reporting the error.
 
1246
                 */
 
1247
                return 0;
 
1248
        }
 
1249
 
1149
1250
        if (bo_gem->mapped_cpu_write) {
1150
1251
                /* Cause a flush to happen if the buffer's pinned for
1151
1252
                 * scanout, so the results show up in a timely manner.
1161
1262
                bo_gem->mapped_cpu_write = false;
1162
1263
        }
1163
1264
 
1164
 
        bo->virtual = NULL;
 
1265
        /* We need to unmap after every innovation as we cannot track
 
1266
         * an open vma for every bo as that will exhaasut the system
 
1267
         * limits and cause later failures.
 
1268
         */
 
1269
        if (--bo_gem->map_count == 0) {
 
1270
                drm_intel_gem_bo_close_vma(bufmgr_gem, bo_gem);
 
1271
                bo->virtual = NULL;
 
1272
        }
1165
1273
        pthread_mutex_unlock(&bufmgr_gem->lock);
1166
1274
 
1167
1275
        return ret;
2145
2253
        }
2146
2254
}
2147
2255
 
 
2256
void
 
2257
drm_intel_bufmgr_gem_set_vma_cache_size(drm_intel_bufmgr *bufmgr, int limit)
 
2258
{
 
2259
        drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *)bufmgr;
 
2260
 
 
2261
        bufmgr_gem->vma_max = limit;
 
2262
 
 
2263
        drm_intel_gem_bo_purge_vma_cache(bufmgr_gem);
 
2264
}
 
2265
 
2148
2266
/**
2149
2267
 * Initializes the GEM buffer manager, which uses the kernel to allocate, map,
2150
2268
 * and manage map buffer objections.
2204
2322
        else
2205
2323
                bufmgr_gem->gen = 6;
2206
2324
 
 
2325
        if (IS_GEN3(bufmgr_gem) && bufmgr_gem->gtt_size > 256*1024*1024) {
 
2326
                /* The unmappable part of gtt on gen 3 (i.e. above 256MB) can't
 
2327
                 * be used for tiled blits. To simplify the accounting, just
 
2328
                 * substract the unmappable part (fixed to 256MB on all known
 
2329
                 * gen3 devices) if the kernel advertises it. */
 
2330
                bufmgr_gem->gtt_size -= 256*1024*1024;
 
2331
        }
 
2332
 
2207
2333
        gp.value = &tmp;
2208
2334
 
2209
2335
        gp.param = I915_PARAM_HAS_EXECBUF2;
2296
2422
        DRMINITLISTHEAD(&bufmgr_gem->named);
2297
2423
        init_cache_buckets(bufmgr_gem);
2298
2424
 
 
2425
        DRMINITLISTHEAD(&bufmgr_gem->vma_cache);
 
2426
        bufmgr_gem->vma_max = -1; /* unlimited by default */
 
2427
 
2299
2428
        return &bufmgr_gem->bufmgr;
2300
2429
}