Subversion Repositories Kolibri OS

Rev

Rev 5060 | Show entire file | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 5060 Rev 6084
Line 1... Line 1...
1
/**************************************************************************
1
/**************************************************************************
2
 *
2
 *
3
 * Copyright 2006 Tungsten Graphics, Inc., Bismarck, ND., USA.
3
 * Copyright 2006 Tungsten Graphics, Inc., Bismarck, ND., USA.
4
 * All Rights Reserved.
4
 * All Rights Reserved.
5
 *
5
 *
6
 * Permission is hereby granted, free of charge, to any person obtaining a
6
 * Permission is hereby granted, free of charge, to any person obtaining a
Line 89... Line 89...
89
 * Finally iteration helpers to walk all nodes and all holes are provided as are
89
 * Finally iteration helpers to walk all nodes and all holes are provided as are
90
 * some basic allocator dumpers for debugging.
90
 * some basic allocator dumpers for debugging.
91
 */
91
 */
Line 92... Line 92...
92
 
92
 
93
static struct drm_mm_node *drm_mm_search_free_generic(const struct drm_mm *mm,
93
static struct drm_mm_node *drm_mm_search_free_generic(const struct drm_mm *mm,
94
						unsigned long size,
94
						u64 size,
95
						unsigned alignment,
95
						unsigned alignment,
96
						unsigned long color,
96
						unsigned long color,
97
						enum drm_mm_search_flags flags);
97
						enum drm_mm_search_flags flags);
98
static struct drm_mm_node *drm_mm_search_free_in_range_generic(const struct drm_mm *mm,
98
static struct drm_mm_node *drm_mm_search_free_in_range_generic(const struct drm_mm *mm,
99
						unsigned long size,
99
						u64 size,
100
						unsigned alignment,
100
						unsigned alignment,
101
						unsigned long color,
101
						unsigned long color,
102
						unsigned long start,
102
						u64 start,
103
						unsigned long end,
103
						u64 end,
Line 104... Line 104...
104
						enum drm_mm_search_flags flags);
104
						enum drm_mm_search_flags flags);
105
 
105
 
106
static void drm_mm_insert_helper(struct drm_mm_node *hole_node,
106
static void drm_mm_insert_helper(struct drm_mm_node *hole_node,
107
				 struct drm_mm_node *node,
107
				 struct drm_mm_node *node,
108
				 unsigned long size, unsigned alignment,
108
				 u64 size, unsigned alignment,
109
				 unsigned long color,
109
				 unsigned long color,
110
				 enum drm_mm_allocator_flags flags)
110
				 enum drm_mm_allocator_flags flags)
111
{
111
{
112
	struct drm_mm *mm = hole_node->mm;
112
	struct drm_mm *mm = hole_node->mm;
113
	unsigned long hole_start = drm_mm_hole_node_start(hole_node);
113
	u64 hole_start = drm_mm_hole_node_start(hole_node);
114
	unsigned long hole_end = drm_mm_hole_node_end(hole_node);
114
	u64 hole_end = drm_mm_hole_node_end(hole_node);
Line 115... Line 115...
115
	unsigned long adj_start = hole_start;
115
	u64 adj_start = hole_start;
Line 116... Line 116...
116
	unsigned long adj_end = hole_end;
116
	u64 adj_end = hole_end;
117
 
117
 
Line 118... Line 118...
118
	BUG_ON(node->allocated);
118
	BUG_ON(node->allocated);
119
 
119
 
Line 120... Line 120...
120
	if (mm->color_adjust)
120
	if (mm->color_adjust)
-
 
121
		mm->color_adjust(hole_node, color, &adj_start, &adj_end);
-
 
122
 
-
 
123
	if (flags & DRM_MM_CREATE_TOP)
121
		mm->color_adjust(hole_node, color, &adj_start, &adj_end);
124
		adj_start = adj_end - size;
122
 
125
 
123
	if (flags & DRM_MM_CREATE_TOP)
126
	if (alignment) {
124
		adj_start = adj_end - size;
127
		u64 tmp = adj_start;
125
 
128
		unsigned rem;
126
	if (alignment) {
129
 
127
		unsigned tmp = adj_start % alignment;
130
		rem = do_div(tmp, alignment);
128
		if (tmp) {
131
		if (rem) {
Line 129... Line 132...
129
			if (flags & DRM_MM_CREATE_TOP)
132
			if (flags & DRM_MM_CREATE_TOP)
130
				adj_start -= tmp;
133
				adj_start -= rem;
Line 174... Line 177...
174
 * 0 on success, -ENOSPC if there's no hole where @node is.
177
 * 0 on success, -ENOSPC if there's no hole where @node is.
175
 */
178
 */
176
int drm_mm_reserve_node(struct drm_mm *mm, struct drm_mm_node *node)
179
int drm_mm_reserve_node(struct drm_mm *mm, struct drm_mm_node *node)
177
{
180
{
178
	struct drm_mm_node *hole;
181
	struct drm_mm_node *hole;
179
	unsigned long end = node->start + node->size;
182
	u64 end = node->start + node->size;
180
	unsigned long hole_start;
183
	u64 hole_start;
181
	unsigned long hole_end;
184
	u64 hole_end;
Line 182... Line 185...
182
 
185
 
Line 183... Line 186...
183
	BUG_ON(node == NULL);
186
	BUG_ON(node == NULL);
184
 
187
 
Line 225... Line 228...
225
 *
228
 *
226
 * Returns:
229
 * Returns:
227
 * 0 on success, -ENOSPC if there's no suitable hole.
230
 * 0 on success, -ENOSPC if there's no suitable hole.
228
 */
231
 */
229
int drm_mm_insert_node_generic(struct drm_mm *mm, struct drm_mm_node *node,
232
int drm_mm_insert_node_generic(struct drm_mm *mm, struct drm_mm_node *node,
230
			       unsigned long size, unsigned alignment,
233
			       u64 size, unsigned alignment,
231
			       unsigned long color,
234
			       unsigned long color,
232
			       enum drm_mm_search_flags sflags,
235
			       enum drm_mm_search_flags sflags,
233
			       enum drm_mm_allocator_flags aflags)
236
			       enum drm_mm_allocator_flags aflags)
234
{
237
{
235
	struct drm_mm_node *hole_node;
238
	struct drm_mm_node *hole_node;
Line 244... Line 247...
244
}
247
}
245
EXPORT_SYMBOL(drm_mm_insert_node_generic);
248
EXPORT_SYMBOL(drm_mm_insert_node_generic);
Line 246... Line 249...
246
 
249
 
247
static void drm_mm_insert_helper_range(struct drm_mm_node *hole_node,
250
static void drm_mm_insert_helper_range(struct drm_mm_node *hole_node,
248
				       struct drm_mm_node *node,
251
				       struct drm_mm_node *node,
249
				       unsigned long size, unsigned alignment,
252
				       u64 size, unsigned alignment,
250
				       unsigned long color,
253
				       unsigned long color,
251
				       unsigned long start, unsigned long end,
254
				       u64 start, u64 end,
252
				       enum drm_mm_allocator_flags flags)
255
				       enum drm_mm_allocator_flags flags)
253
{
256
{
254
	struct drm_mm *mm = hole_node->mm;
257
	struct drm_mm *mm = hole_node->mm;
255
	unsigned long hole_start = drm_mm_hole_node_start(hole_node);
258
	u64 hole_start = drm_mm_hole_node_start(hole_node);
256
	unsigned long hole_end = drm_mm_hole_node_end(hole_node);
259
	u64 hole_end = drm_mm_hole_node_end(hole_node);
257
	unsigned long adj_start = hole_start;
260
	u64 adj_start = hole_start;
Line 258... Line 261...
258
	unsigned long adj_end = hole_end;
261
	u64 adj_end = hole_end;
Line 259... Line 262...
259
 
262
 
260
	BUG_ON(!hole_node->hole_follows || node->allocated);
263
	BUG_ON(!hole_node->hole_follows || node->allocated);
261
 
264
 
262
	if (adj_start < start)
265
	if (adj_start < start)
Line 263... Line -...
263
		adj_start = start;
-
 
264
	if (adj_end > end)
-
 
265
		adj_end = end;
-
 
266
 
266
		adj_start = start;
267
	if (flags & DRM_MM_CREATE_TOP)
267
	if (adj_end > end)
Line -... Line 268...
-
 
268
		adj_end = end;
-
 
269
 
-
 
270
	if (mm->color_adjust)
268
		adj_start = adj_end - size;
271
		mm->color_adjust(hole_node, color, &adj_start, &adj_end);
-
 
272
 
-
 
273
	if (flags & DRM_MM_CREATE_TOP)
-
 
274
		adj_start = adj_end - size;
269
 
275
 
270
	if (mm->color_adjust)
276
	if (alignment) {
271
		mm->color_adjust(hole_node, color, &adj_start, &adj_end);
277
		u64 tmp = adj_start;
272
 
278
		unsigned rem;
273
	if (alignment) {
279
 
274
		unsigned tmp = adj_start % alignment;
280
		rem = do_div(tmp, alignment);
275
		if (tmp) {
281
		if (rem) {
276
			if (flags & DRM_MM_CREATE_TOP)
282
			if (flags & DRM_MM_CREATE_TOP)
Line 277... Line 283...
277
				adj_start -= tmp;
283
				adj_start -= rem;
278
			else
284
			else
Line 322... Line 328...
322
 *
328
 *
323
 * Returns:
329
 * Returns:
324
 * 0 on success, -ENOSPC if there's no suitable hole.
330
 * 0 on success, -ENOSPC if there's no suitable hole.
325
 */
331
 */
326
int drm_mm_insert_node_in_range_generic(struct drm_mm *mm, struct drm_mm_node *node,
332
int drm_mm_insert_node_in_range_generic(struct drm_mm *mm, struct drm_mm_node *node,
327
					unsigned long size, unsigned alignment,
333
					u64 size, unsigned alignment,
328
					unsigned long color,
334
					unsigned long color,
329
					unsigned long start, unsigned long end,
335
					u64 start, u64 end,
330
					enum drm_mm_search_flags sflags,
336
					enum drm_mm_search_flags sflags,
331
					enum drm_mm_allocator_flags aflags)
337
					enum drm_mm_allocator_flags aflags)
332
{
338
{
333
	struct drm_mm_node *hole_node;
339
	struct drm_mm_node *hole_node;
Line 385... Line 391...
385
	list_del(&node->node_list);
391
	list_del(&node->node_list);
386
	node->allocated = 0;
392
	node->allocated = 0;
387
}
393
}
388
EXPORT_SYMBOL(drm_mm_remove_node);
394
EXPORT_SYMBOL(drm_mm_remove_node);
Line 389... Line 395...
389
 
395
 
390
static int check_free_hole(unsigned long start, unsigned long end,
-
 
391
			   unsigned long size, unsigned alignment)
396
static int check_free_hole(u64 start, u64 end, u64 size, unsigned alignment)
392
{
397
{
393
	if (end - start < size)
398
	if (end - start < size)
Line 394... Line 399...
394
		return 0;
399
		return 0;
-
 
400
 
-
 
401
	if (alignment) {
-
 
402
		u64 tmp = start;
395
 
403
		unsigned rem;
396
	if (alignment) {
404
 
397
		unsigned tmp = start % alignment;
405
		rem = do_div(tmp, alignment);
398
		if (tmp)
406
		if (rem)
Line 399... Line 407...
399
			start += alignment - tmp;
407
			start += alignment - rem;
400
	}
408
	}
Line 401... Line 409...
401
 
409
 
402
	return end >= start + size;
410
	return end >= start + size;
403
}
411
}
404
 
412
 
405
static struct drm_mm_node *drm_mm_search_free_generic(const struct drm_mm *mm,
413
static struct drm_mm_node *drm_mm_search_free_generic(const struct drm_mm *mm,
406
				       unsigned long size,
414
						      u64 size,
407
					       unsigned alignment,
415
						      unsigned alignment,
408
					       unsigned long color,
416
						      unsigned long color,
409
						      enum drm_mm_search_flags flags)
417
						      enum drm_mm_search_flags flags)
410
{
418
{
411
	struct drm_mm_node *entry;
419
	struct drm_mm_node *entry;
Line 412... Line 420...
412
	struct drm_mm_node *best;
420
	struct drm_mm_node *best;
Line 413... Line 421...
413
	unsigned long adj_start;
421
	u64 adj_start;
414
	unsigned long adj_end;
422
	u64 adj_end;
Line 415... Line 423...
415
	unsigned long best_size;
423
	u64 best_size;
416
 
424
 
417
	BUG_ON(mm->scanned_blocks);
425
	BUG_ON(mm->scanned_blocks);
Line 418... Line 426...
418
 
426
 
419
	best = NULL;
427
	best = NULL;
420
	best_size = ~0UL;
428
	best_size = ~0UL;
421
 
429
 
Line 443... Line 451...
443
 
451
 
444
	return best;
452
	return best;
Line 445... Line 453...
445
}
453
}
446
 
454
 
447
static struct drm_mm_node *drm_mm_search_free_in_range_generic(const struct drm_mm *mm,
455
static struct drm_mm_node *drm_mm_search_free_in_range_generic(const struct drm_mm *mm,
448
						unsigned long size,
456
							u64 size,
449
						unsigned alignment,
457
							unsigned alignment,
450
							unsigned long color,
458
							unsigned long color,
451
						unsigned long start,
459
							u64 start,
452
						unsigned long end,
460
							u64 end,
453
							enum drm_mm_search_flags flags)
461
							enum drm_mm_search_flags flags)
454
{
462
{
455
	struct drm_mm_node *entry;
463
	struct drm_mm_node *entry;
456
	struct drm_mm_node *best;
464
	struct drm_mm_node *best;
457
	unsigned long adj_start;
465
	u64 adj_start;
Line 458... Line 466...
458
	unsigned long adj_end;
466
	u64 adj_end;
Line 459... Line 467...
459
	unsigned long best_size;
467
	u64 best_size;
460
 
468
 
Line 461... Line 469...
461
	BUG_ON(mm->scanned_blocks);
469
	BUG_ON(mm->scanned_blocks);
462
 
470
 
463
	best = NULL;
471
	best = NULL;
Line 464... Line 472...
464
	best_size = ~0UL;
472
	best_size = ~0UL;
465
 
473
 
466
	__drm_mm_for_each_hole(entry, mm, adj_start, adj_end,
474
	__drm_mm_for_each_hole(entry, mm, adj_start, adj_end,
467
			       flags & DRM_MM_SEARCH_BELOW) {
475
			       flags & DRM_MM_SEARCH_BELOW) {
Line 559... Line 567...
559
 * Warning:
567
 * Warning:
560
 * As long as the scan list is non-empty, no other operations than
568
 * As long as the scan list is non-empty, no other operations than
561
 * adding/removing nodes to/from the scan list are allowed.
569
 * adding/removing nodes to/from the scan list are allowed.
562
 */
570
 */
563
void drm_mm_init_scan(struct drm_mm *mm,
571
void drm_mm_init_scan(struct drm_mm *mm,
564
		      unsigned long size,
572
		      u64 size,
565
		      unsigned alignment,
573
		      unsigned alignment,
566
		      unsigned long color)
574
		      unsigned long color)
567
{
575
{
568
	mm->scan_color = color;
576
	mm->scan_color = color;
569
	mm->scan_alignment = alignment;
577
	mm->scan_alignment = alignment;
Line 592... Line 600...
592
 * Warning:
600
 * Warning:
593
 * As long as the scan list is non-empty, no other operations than
601
 * As long as the scan list is non-empty, no other operations than
594
 * adding/removing nodes to/from the scan list are allowed.
602
 * adding/removing nodes to/from the scan list are allowed.
595
 */
603
 */
596
void drm_mm_init_scan_with_range(struct drm_mm *mm,
604
void drm_mm_init_scan_with_range(struct drm_mm *mm,
597
				 unsigned long size,
605
				 u64 size,
598
				 unsigned alignment,
606
				 unsigned alignment,
599
				 unsigned long color,
607
				 unsigned long color,
600
				 unsigned long start,
608
				 u64 start,
601
				 unsigned long end)
609
				 u64 end)
602
{
610
{
603
	mm->scan_color = color;
611
	mm->scan_color = color;
604
	mm->scan_alignment = alignment;
612
	mm->scan_alignment = alignment;
605
	mm->scan_size = size;
613
	mm->scan_size = size;
606
	mm->scanned_blocks = 0;
614
	mm->scanned_blocks = 0;
Line 625... Line 633...
625
 */
633
 */
626
bool drm_mm_scan_add_block(struct drm_mm_node *node)
634
bool drm_mm_scan_add_block(struct drm_mm_node *node)
627
{
635
{
628
	struct drm_mm *mm = node->mm;
636
	struct drm_mm *mm = node->mm;
629
	struct drm_mm_node *prev_node;
637
	struct drm_mm_node *prev_node;
630
	unsigned long hole_start, hole_end;
638
	u64 hole_start, hole_end;
631
	unsigned long adj_start, adj_end;
639
	u64 adj_start, adj_end;
Line 632... Line 640...
632
 
640
 
Line 633... Line 641...
633
	mm->scanned_blocks++;
641
	mm->scanned_blocks++;
634
 
642
 
Line 729... Line 737...
729
 * @start: start of the range managed by @mm
737
 * @start: start of the range managed by @mm
730
 * @size: end of the range managed by @mm
738
 * @size: end of the range managed by @mm
731
 *
739
 *
732
 * Note that @mm must be cleared to 0 before calling this function.
740
 * Note that @mm must be cleared to 0 before calling this function.
733
 */
741
 */
734
void drm_mm_init(struct drm_mm * mm, unsigned long start, unsigned long size)
742
void drm_mm_init(struct drm_mm * mm, u64 start, u64 size)
735
{
743
{
736
	INIT_LIST_HEAD(&mm->hole_stack);
744
	INIT_LIST_HEAD(&mm->hole_stack);
737
	mm->scanned_blocks = 0;
745
	mm->scanned_blocks = 0;
Line 738... Line 746...
738
 
746
 
Line 764... Line 772...
764
	WARN(!list_empty(&mm->head_node.node_list),
772
	WARN(!list_empty(&mm->head_node.node_list),
765
	     "Memory manager not clean during takedown.\n");
773
	     "Memory manager not clean during takedown.\n");
766
}
774
}
767
EXPORT_SYMBOL(drm_mm_takedown);
775
EXPORT_SYMBOL(drm_mm_takedown);
Line 768... Line 776...
768
 
776
 
769
static unsigned long drm_mm_debug_hole(struct drm_mm_node *entry,
777
static u64 drm_mm_debug_hole(struct drm_mm_node *entry,
770
				       const char *prefix)
778
				     const char *prefix)
771
{
779
{
Line 772... Line 780...
772
	unsigned long hole_start, hole_end, hole_size;
780
	u64 hole_start, hole_end, hole_size;
773
 
781
 
774
	if (entry->hole_follows) {
782
	if (entry->hole_follows) {
775
		hole_start = drm_mm_hole_node_start(entry);
783
		hole_start = drm_mm_hole_node_start(entry);
776
		hole_end = drm_mm_hole_node_end(entry);
784
		hole_end = drm_mm_hole_node_end(entry);
777
	hole_size = hole_end - hole_start;
-
 
778
		printk(KERN_DEBUG "%s 0x%08lx-0x%08lx: %8lu: free\n",
785
		hole_size = hole_end - hole_start;
779
			prefix, hole_start, hole_end,
786
		pr_debug("%s %#llx-%#llx: %llu: free\n", prefix, hole_start,
780
			hole_size);
787
			 hole_end, hole_size);
Line 781... Line 788...
781
		return hole_size;
788
		return hole_size;
782
	}
789
	}
Line 790... Line 797...
790
 * @prefix: prefix to use for dumping to dmesg
797
 * @prefix: prefix to use for dumping to dmesg
791
 */
798
 */
792
void drm_mm_debug_table(struct drm_mm *mm, const char *prefix)
799
void drm_mm_debug_table(struct drm_mm *mm, const char *prefix)
793
{
800
{
794
	struct drm_mm_node *entry;
801
	struct drm_mm_node *entry;
795
	unsigned long total_used = 0, total_free = 0, total = 0;
802
	u64 total_used = 0, total_free = 0, total = 0;
Line 796... Line 803...
796
 
803
 
Line 797... Line 804...
797
	total_free += drm_mm_debug_hole(&mm->head_node, prefix);
804
	total_free += drm_mm_debug_hole(&mm->head_node, prefix);
798
 
805
 
799
	drm_mm_for_each_node(entry, mm) {
806
	drm_mm_for_each_node(entry, mm) {
800
		printk(KERN_DEBUG "%s 0x%08lx-0x%08lx: %8lu: used\n",
-
 
801
			prefix, entry->start, entry->start + entry->size,
807
		pr_debug("%s %#llx-%#llx: %llu: used\n", prefix, entry->start,
802
			entry->size);
808
			 entry->start + entry->size, entry->size);
803
		total_used += entry->size;
809
		total_used += entry->size;
804
		total_free += drm_mm_debug_hole(entry, prefix);
810
		total_free += drm_mm_debug_hole(entry, prefix);
Line 805... Line 811...
805
		}
811
	}
806
	total = total_free + total_used;
812
	total = total_free + total_used;
807
 
813
 
808
	printk(KERN_DEBUG "%s total: %lu, used %lu free %lu\n", prefix, total,
814
	pr_debug("%s total: %llu, used %llu free %llu\n", prefix, total,
Line 809... Line 815...
809
		total_used, total_free);
815
		 total_used, total_free);
810
}
816
}
811
EXPORT_SYMBOL(drm_mm_debug_table);
817
EXPORT_SYMBOL(drm_mm_debug_table);
812
 
818
 
Line 813... Line 819...
813
#if defined(CONFIG_DEBUG_FS)
819
#if defined(CONFIG_DEBUG_FS)
814
static unsigned long drm_mm_dump_hole(struct seq_file *m, struct drm_mm_node *entry)
820
static u64 drm_mm_dump_hole(struct seq_file *m, struct drm_mm_node *entry)
815
{
821
{
816
	unsigned long hole_start, hole_end, hole_size;
822
	u64 hole_start, hole_end, hole_size;
817
 
823
 
818
	if (entry->hole_follows) {
824
	if (entry->hole_follows) {
819
		hole_start = drm_mm_hole_node_start(entry);
825
		hole_start = drm_mm_hole_node_start(entry);
820
		hole_end = drm_mm_hole_node_end(entry);
826
		hole_end = drm_mm_hole_node_end(entry);
Line 821... Line 827...
821
	hole_size = hole_end - hole_start;
827
		hole_size = hole_end - hole_start;
822
		seq_printf(m, "0x%08lx-0x%08lx: 0x%08lx: free\n",
828
		seq_printf(m, "%#018llx-%#018llx: %llu: free\n", hole_start,
Line 833... Line 839...
833
 * @mm: drm_mm allocator to dump
839
 * @mm: drm_mm allocator to dump
834
 */
840
 */
835
int drm_mm_dump_table(struct seq_file *m, struct drm_mm *mm)
841
int drm_mm_dump_table(struct seq_file *m, struct drm_mm *mm)
836
{
842
{
837
	struct drm_mm_node *entry;
843
	struct drm_mm_node *entry;
838
	unsigned long total_used = 0, total_free = 0, total = 0;
844
	u64 total_used = 0, total_free = 0, total = 0;
Line 839... Line 845...
839
 
845
 
Line 840... Line 846...
840
	total_free += drm_mm_dump_hole(m, &mm->head_node);
846
	total_free += drm_mm_dump_hole(m, &mm->head_node);
841
 
847
 
842
	drm_mm_for_each_node(entry, mm) {
848
	drm_mm_for_each_node(entry, mm) {
843
		seq_printf(m, "0x%08lx-0x%08lx: 0x%08lx: used\n",
-
 
844
				entry->start, entry->start + entry->size,
849
		seq_printf(m, "%#018llx-%#018llx: %llu: used\n", entry->start,
845
				entry->size);
850
			   entry->start + entry->size, entry->size);
846
		total_used += entry->size;
851
		total_used += entry->size;
847
		total_free += drm_mm_dump_hole(m, entry);
852
		total_free += drm_mm_dump_hole(m, entry);
Line 848... Line 853...
848
		}
853
	}
-
 
854
	total = total_free + total_used;
849
	total = total_free + total_used;
855
 
850
 
856
	seq_printf(m, "total: %llu, used %llu free %llu\n", total,
851
	seq_printf(m, "total: %lu, used %lu free %lu\n", total, total_used, total_free);
857
		   total_used, total_free);
852
	return 0;
858
	return 0;