HSI: hsi_char: Delete an error message for a failed memory allocation in hsc_probe()
[sfrench/cifs-2.6.git] / arch / cris / arch-v32 / mm / intmem.c
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * Simple allocator for internal RAM in ETRAX FS
4  *
5  * Copyright (c) 2004 Axis Communications AB.
6  */
7
8 #include <linux/list.h>
9 #include <linux/slab.h>
10 #include <asm/io.h>
11 #include <memmap.h>
12
13 #define STATUS_FREE 0
14 #define STATUS_ALLOCATED 1
15
16 #ifdef CONFIG_ETRAX_L2CACHE
17 #define RESERVED_SIZE 66*1024
18 #else
19 #define RESERVED_SIZE 0
20 #endif
21
22 struct intmem_allocation {
23         struct list_head entry;
24         unsigned int size;
25         unsigned offset;
26         char status;
27 };
28
29
30 static struct list_head intmem_allocations;
31 static void* intmem_virtual;
32
33 static void crisv32_intmem_init(void)
34 {
35         static int initiated = 0;
36         if (!initiated) {
37                 struct intmem_allocation* alloc;
38                 alloc = kmalloc(sizeof *alloc, GFP_KERNEL);
39                 INIT_LIST_HEAD(&intmem_allocations);
40                 intmem_virtual = ioremap(MEM_INTMEM_START + RESERVED_SIZE,
41                                          MEM_INTMEM_SIZE - RESERVED_SIZE);
42                 initiated = 1;
43                 alloc->size = MEM_INTMEM_SIZE - RESERVED_SIZE;
44                 alloc->offset = 0;
45                 alloc->status = STATUS_FREE;
46                 list_add_tail(&alloc->entry, &intmem_allocations);
47         }
48 }
49
50 void* crisv32_intmem_alloc(unsigned size, unsigned align)
51 {
52         struct intmem_allocation* allocation;
53         struct intmem_allocation* tmp;
54         void* ret = NULL;
55
56         preempt_disable();
57         crisv32_intmem_init();
58
59         list_for_each_entry_safe(allocation, tmp, &intmem_allocations, entry) {
60                 int alignment = allocation->offset % align;
61                 alignment = alignment ? align - alignment : alignment;
62
63                 if (allocation->status == STATUS_FREE &&
64                     allocation->size >= size + alignment) {
65                         if (allocation->size > size + alignment) {
66                                 struct intmem_allocation* alloc;
67                                 alloc = kmalloc(sizeof *alloc, GFP_ATOMIC);
68                                 alloc->status = STATUS_FREE;
69                                 alloc->size = allocation->size - size -
70                                         alignment;
71                                 alloc->offset = allocation->offset + size +
72                                         alignment;
73                                 list_add(&alloc->entry, &allocation->entry);
74
75                                 if (alignment) {
76                                         struct intmem_allocation *tmp;
77                                         tmp = kmalloc(sizeof *tmp, GFP_ATOMIC);
78                                         tmp->offset = allocation->offset;
79                                         tmp->size = alignment;
80                                         tmp->status = STATUS_FREE;
81                                         allocation->offset += alignment;
82                                         list_add_tail(&tmp->entry,
83                                                 &allocation->entry);
84                                 }
85                         }
86                         allocation->status = STATUS_ALLOCATED;
87                         allocation->size = size;
88                         ret = (void*)((int)intmem_virtual + allocation->offset);
89                 }
90         }
91         preempt_enable();
92         return ret;
93 }
94
95 void crisv32_intmem_free(void* addr)
96 {
97         struct intmem_allocation* allocation;
98         struct intmem_allocation* tmp;
99
100         if (addr == NULL)
101                 return;
102
103         preempt_disable();
104         crisv32_intmem_init();
105
106         list_for_each_entry_safe(allocation, tmp, &intmem_allocations, entry) {
107                 if (allocation->offset == (int)(addr - intmem_virtual)) {
108                         struct intmem_allocation *prev =
109                           list_entry(allocation->entry.prev,
110                                      struct intmem_allocation, entry);
111                         struct intmem_allocation *next =
112                           list_entry(allocation->entry.next,
113                                      struct intmem_allocation, entry);
114
115                         allocation->status = STATUS_FREE;
116                         /* Join with prev and/or next if also free */
117                         if ((&prev->entry != &intmem_allocations) &&
118                                         (prev->status == STATUS_FREE)) {
119                                 prev->size += allocation->size;
120                                 list_del(&allocation->entry);
121                                 kfree(allocation);
122                                 allocation = prev;
123                         }
124                         if ((&next->entry != &intmem_allocations) &&
125                                         (next->status == STATUS_FREE)) {
126                                 allocation->size += next->size;
127                                 list_del(&next->entry);
128                                 kfree(next);
129                         }
130                         preempt_enable();
131                         return;
132                 }
133         }
134         preempt_enable();
135 }
136
137 void* crisv32_intmem_phys_to_virt(unsigned long addr)
138 {
139         return (void *)(addr - (MEM_INTMEM_START + RESERVED_SIZE) +
140                 (unsigned long)intmem_virtual);
141 }
142
143 unsigned long crisv32_intmem_virt_to_phys(void* addr)
144 {
145         return (unsigned long)((unsigned long )addr -
146                 (unsigned long)intmem_virtual + MEM_INTMEM_START +
147                 RESERVED_SIZE);
148 }
149
150 static int __init crisv32_intmem_setup(void)
151 {
152         crisv32_intmem_init();
153
154         return 0;
155 }
156 device_initcall(crisv32_intmem_setup);
157