~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/arch/powerpc/mm/drmem.c

Version: ~ [ linux-6.11.5 ] ~ [ linux-6.10.14 ] ~ [ linux-6.9.12 ] ~ [ linux-6.8.12 ] ~ [ linux-6.7.12 ] ~ [ linux-6.6.58 ] ~ [ linux-6.5.13 ] ~ [ linux-6.4.16 ] ~ [ linux-6.3.13 ] ~ [ linux-6.2.16 ] ~ [ linux-6.1.114 ] ~ [ linux-6.0.19 ] ~ [ linux-5.19.17 ] ~ [ linux-5.18.19 ] ~ [ linux-5.17.15 ] ~ [ linux-5.16.20 ] ~ [ linux-5.15.169 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.228 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.284 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.322 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.336 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.337 ] ~ [ linux-4.4.302 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.9 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

Diff markup

Differences between /arch/powerpc/mm/drmem.c (Version linux-6.11.5) and /arch/ppc/mm/drmem.c (Version linux-5.0.21)


  1 // SPDX-License-Identifier: GPL-2.0-or-later        1 
  2 /*                                                
  3  * Dynamic reconfiguration memory support         
  4  *                                                
  5  * Copyright 2017 IBM Corporation                 
  6  */                                               
  7                                                   
  8 #define pr_fmt(fmt) "drmem: " fmt                 
  9                                                   
 10 #include <linux/kernel.h>                         
 11 #include <linux/of.h>                             
 12 #include <linux/of_fdt.h>                         
 13 #include <linux/memblock.h>                       
 14 #include <linux/slab.h>                           
 15 #include <asm/drmem.h>                            
 16                                                   
 17 static int n_root_addr_cells, n_root_size_cell    
 18                                                   
 19 static struct drmem_lmb_info __drmem_info;        
 20 struct drmem_lmb_info *drmem_info = &__drmem_i    
 21 static bool in_drmem_update;                      
 22                                                   
 23 u64 drmem_lmb_memory_max(void)                    
 24 {                                                 
 25         struct drmem_lmb *last_lmb;               
 26                                                   
 27         last_lmb = &drmem_info->lmbs[drmem_inf    
 28         return last_lmb->base_addr + drmem_lmb    
 29 }                                                 
 30                                                   
 31 static u32 drmem_lmb_flags(struct drmem_lmb *l    
 32 {                                                 
 33         /*                                        
 34          * Return the value of the lmb flags f    
 35          * bit used internally for hotplug pro    
 36          */                                       
 37         return lmb->flags & ~DRMEM_LMB_RESERVE    
 38 }                                                 
 39                                                   
 40 static struct property *clone_property(struct     
 41 {                                                 
 42         struct property *new_prop;                
 43                                                   
 44         new_prop = kzalloc(sizeof(*new_prop),     
 45         if (!new_prop)                            
 46                 return NULL;                      
 47                                                   
 48         new_prop->name = kstrdup(prop->name, G    
 49         new_prop->value = kzalloc(prop_sz, GFP    
 50         if (!new_prop->name || !new_prop->valu    
 51                 kfree(new_prop->name);            
 52                 kfree(new_prop->value);           
 53                 kfree(new_prop);                  
 54                 return NULL;                      
 55         }                                         
 56                                                   
 57         new_prop->length = prop_sz;               
 58 #if defined(CONFIG_OF_DYNAMIC)                    
 59         of_property_set_flag(new_prop, OF_DYNA    
 60 #endif                                            
 61         return new_prop;                          
 62 }                                                 
 63                                                   
 64 static int drmem_update_dt_v1(struct device_no    
 65                               struct property     
 66 {                                                 
 67         struct property *new_prop;                
 68         struct of_drconf_cell_v1 *dr_cell;        
 69         struct drmem_lmb *lmb;                    
 70         __be32 *p;                                
 71                                                   
 72         new_prop = clone_property(prop, prop->    
 73         if (!new_prop)                            
 74                 return -1;                        
 75                                                   
 76         p = new_prop->value;                      
 77         *p++ = cpu_to_be32(drmem_info->n_lmbs)    
 78                                                   
 79         dr_cell = (struct of_drconf_cell_v1 *)    
 80                                                   
 81         for_each_drmem_lmb(lmb) {                 
 82                 dr_cell->base_addr = cpu_to_be    
 83                 dr_cell->drc_index = cpu_to_be    
 84                 dr_cell->aa_index = cpu_to_be3    
 85                 dr_cell->flags = cpu_to_be32(d    
 86                                                   
 87                 dr_cell++;                        
 88         }                                         
 89                                                   
 90         of_update_property(memory, new_prop);     
 91         return 0;                                 
 92 }                                                 
 93                                                   
 94 static void init_drconf_v2_cell(struct of_drco    
 95                                 struct drmem_l    
 96 {                                                 
 97         dr_cell->base_addr = cpu_to_be64(lmb->    
 98         dr_cell->drc_index = cpu_to_be32(lmb->    
 99         dr_cell->aa_index = cpu_to_be32(lmb->a    
100         dr_cell->flags = cpu_to_be32(drmem_lmb    
101 }                                                 
102                                                   
103 static int drmem_update_dt_v2(struct device_no    
104                               struct property     
105 {                                                 
106         struct property *new_prop;                
107         struct of_drconf_cell_v2 *dr_cell;        
108         struct drmem_lmb *lmb, *prev_lmb;         
109         u32 lmb_sets, prop_sz, seq_lmbs;          
110         u32 *p;                                   
111                                                   
112         /* First pass, determine how many LMB     
113         lmb_sets = 0;                             
114         prev_lmb = NULL;                          
115         for_each_drmem_lmb(lmb) {                 
116                 if (!prev_lmb) {                  
117                         prev_lmb = lmb;           
118                         lmb_sets++;               
119                         continue;                 
120                 }                                 
121                                                   
122                 if (prev_lmb->aa_index != lmb-    
123                     drmem_lmb_flags(prev_lmb)     
124                         lmb_sets++;               
125                                                   
126                 prev_lmb = lmb;                   
127         }                                         
128                                                   
129         prop_sz = lmb_sets * sizeof(*dr_cell)     
130         new_prop = clone_property(prop, prop_s    
131         if (!new_prop)                            
132                 return -1;                        
133                                                   
134         p = new_prop->value;                      
135         *p++ = cpu_to_be32(lmb_sets);             
136                                                   
137         dr_cell = (struct of_drconf_cell_v2 *)    
138                                                   
139         /* Second pass, populate the LMB set d    
140         prev_lmb = NULL;                          
141         seq_lmbs = 0;                             
142         for_each_drmem_lmb(lmb) {                 
143                 if (prev_lmb == NULL) {           
144                         /* Start of first LMB     
145                         prev_lmb = lmb;           
146                         init_drconf_v2_cell(dr    
147                         seq_lmbs++;               
148                         continue;                 
149                 }                                 
150                                                   
151                 if (prev_lmb->aa_index != lmb-    
152                     drmem_lmb_flags(prev_lmb)     
153                         /* end of one set, sta    
154                         dr_cell->seq_lmbs = cp    
155                         dr_cell++;                
156                                                   
157                         init_drconf_v2_cell(dr    
158                         seq_lmbs = 1;             
159                 } else {                          
160                         seq_lmbs++;               
161                 }                                 
162                                                   
163                 prev_lmb = lmb;                   
164         }                                         
165                                                   
166         /* close out last LMB set */              
167         dr_cell->seq_lmbs = cpu_to_be32(seq_lm    
168         of_update_property(memory, new_prop);     
169         return 0;                                 
170 }                                                 
171                                                   
172 int drmem_update_dt(void)                         
173 {                                                 
174         struct device_node *memory;               
175         struct property *prop;                    
176         int rc = -1;                              
177                                                   
178         memory = of_find_node_by_path("/ibm,dy    
179         if (!memory)                              
180                 return -1;                        
181                                                   
182         /*                                        
183          * Set in_drmem_update to prevent the     
184          * DT property back since the change i    
185          */                                       
186         in_drmem_update = true;                   
187         prop = of_find_property(memory, "ibm,d    
188         if (prop) {                               
189                 rc = drmem_update_dt_v1(memory    
190         } else {                                  
191                 prop = of_find_property(memory    
192                 if (prop)                         
193                         rc = drmem_update_dt_v    
194         }                                         
195         in_drmem_update = false;                  
196                                                   
197         of_node_put(memory);                      
198         return rc;                                
199 }                                                 
200                                                   
201 static void read_drconf_v1_cell(struct drmem_l    
202                                        const _    
203 {                                                 
204         const __be32 *p = *prop;                  
205                                                   
206         lmb->base_addr = of_read_number(p, n_r    
207         p += n_root_addr_cells;                   
208         lmb->drc_index = of_read_number(p++, 1    
209                                                   
210         p++; /* skip reserved field */            
211                                                   
212         lmb->aa_index = of_read_number(p++, 1)    
213         lmb->flags = of_read_number(p++, 1);      
214                                                   
215         *prop = p;                                
216 }                                                 
217                                                   
218 static int                                        
219 __walk_drmem_v1_lmbs(const __be32 *prop, const    
220                      int (*func)(struct drmem_    
221 {                                                 
222         struct drmem_lmb lmb;                     
223         u32 i, n_lmbs;                            
224         int ret = 0;                              
225                                                   
226         n_lmbs = of_read_number(prop++, 1);       
227         for (i = 0; i < n_lmbs; i++) {            
228                 read_drconf_v1_cell(&lmb, &pro    
229                 ret = func(&lmb, &usm, data);     
230                 if (ret)                          
231                         break;                    
232         }                                         
233                                                   
234         return ret;                               
235 }                                                 
236                                                   
237 static void read_drconf_v2_cell(struct of_drco    
238                                        const _    
239 {                                                 
240         const __be32 *p = *prop;                  
241                                                   
242         dr_cell->seq_lmbs = of_read_number(p++    
243         dr_cell->base_addr = of_read_number(p,    
244         p += n_root_addr_cells;                   
245         dr_cell->drc_index = of_read_number(p+    
246         dr_cell->aa_index = of_read_number(p++    
247         dr_cell->flags = of_read_number(p++, 1    
248                                                   
249         *prop = p;                                
250 }                                                 
251                                                   
252 static int                                        
253 __walk_drmem_v2_lmbs(const __be32 *prop, const    
254                      int (*func)(struct drmem_    
255 {                                                 
256         struct of_drconf_cell_v2 dr_cell;         
257         struct drmem_lmb lmb;                     
258         u32 i, j, lmb_sets;                       
259         int ret = 0;                              
260                                                   
261         lmb_sets = of_read_number(prop++, 1);     
262         for (i = 0; i < lmb_sets; i++) {          
263                 read_drconf_v2_cell(&dr_cell,     
264                                                   
265                 for (j = 0; j < dr_cell.seq_lm    
266                         lmb.base_addr = dr_cel    
267                         dr_cell.base_addr += d    
268                                                   
269                         lmb.drc_index = dr_cel    
270                         dr_cell.drc_index++;      
271                                                   
272                         lmb.aa_index = dr_cell    
273                         lmb.flags = dr_cell.fl    
274                                                   
275                         ret = func(&lmb, &usm,    
276                         if (ret)                  
277                                 break;            
278                 }                                 
279         }                                         
280                                                   
281         return ret;                               
282 }                                                 
283                                                   
284 #ifdef CONFIG_PPC_PSERIES                         
285 int __init walk_drmem_lmbs_early(unsigned long    
286                 int (*func)(struct drmem_lmb *    
287 {                                                 
288         const __be32 *prop, *usm;                 
289         int len, ret = -ENODEV;                   
290                                                   
291         prop = of_get_flat_dt_prop(node, "ibm,    
292         if (!prop || len < dt_root_size_cells     
293                 return ret;                       
294                                                   
295         /* Get the address & size cells */        
296         n_root_addr_cells = dt_root_addr_cells    
297         n_root_size_cells = dt_root_size_cells    
298                                                   
299         drmem_info->lmb_size = dt_mem_next_cel    
300                                                   
301         usm = of_get_flat_dt_prop(node, "linux    
302                                                   
303         prop = of_get_flat_dt_prop(node, "ibm,    
304         if (prop) {                               
305                 ret = __walk_drmem_v1_lmbs(pro    
306         } else {                                  
307                 prop = of_get_flat_dt_prop(nod    
308                                            &le    
309                 if (prop)                         
310                         ret = __walk_drmem_v2_    
311         }                                         
312                                                   
313         memblock_dump_all();                      
314         return ret;                               
315 }                                                 
316                                                   
317 /*                                                
318  * Update the LMB associativity index.            
319  */                                               
320 static int update_lmb(struct drmem_lmb *update    
321                       __maybe_unused const __b    
322                       __maybe_unused void *dat    
323 {                                                 
324         struct drmem_lmb *lmb;                    
325                                                   
326         for_each_drmem_lmb(lmb) {                 
327                 if (lmb->drc_index != updated_    
328                         continue;                 
329                                                   
330                 lmb->aa_index = updated_lmb->a    
331                 break;                            
332         }                                         
333         return 0;                                 
334 }                                                 
335                                                   
336 /*                                                
337  * Update the LMB associativity index.            
338  *                                                
339  * This needs to be called when the hypervisor    
340  * dynamic-reconfiguration-memory node propert    
341  */                                               
342 void drmem_update_lmbs(struct property *prop)     
343 {                                                 
344         /*                                        
345          * Don't update the LMBs if triggered     
346          * drmem_update_dt(), the LMB values h    
347          * property in that case.                 
348          */                                       
349         if (in_drmem_update)                      
350                 return;                           
351         if (!strcmp(prop->name, "ibm,dynamic-m    
352                 __walk_drmem_v1_lmbs(prop->val    
353         else if (!strcmp(prop->name, "ibm,dyna    
354                 __walk_drmem_v2_lmbs(prop->val    
355 }                                                 
356 #endif                                            
357                                                   
358 static int init_drmem_lmb_size(struct device_n    
359 {                                                 
360         const __be32 *prop;                       
361         int len;                                  
362                                                   
363         if (drmem_info->lmb_size)                 
364                 return 0;                         
365                                                   
366         prop = of_get_property(dn, "ibm,lmb-si    
367         if (!prop || len < n_root_size_cells *    
368                 pr_info("Could not determine L    
369                 return -1;                        
370         }                                         
371                                                   
372         drmem_info->lmb_size = of_read_number(    
373         return 0;                                 
374 }                                                 
375                                                   
376 /*                                                
377  * Returns the property linux,drconf-usable-me    
378  * it exists (the property exists only in kexe    
379  * added by kexec-tools)                          
380  */                                               
381 static const __be32 *of_get_usable_memory(stru    
382 {                                                 
383         const __be32 *prop;                       
384         u32 len;                                  
385                                                   
386         prop = of_get_property(dn, "linux,drco    
387         if (!prop || len < sizeof(unsigned int    
388                 return NULL;                      
389                                                   
390         return prop;                              
391 }                                                 
392                                                   
393 int walk_drmem_lmbs(struct device_node *dn, vo    
394                     int (*func)(struct drmem_l    
395 {                                                 
396         struct device_node *root = of_find_nod    
397         const __be32 *prop, *usm;                 
398         int ret = -ENODEV;                        
399                                                   
400         if (!root)                                
401                 return ret;                       
402                                                   
403         /* Get the address & size cells */        
404         n_root_addr_cells = of_n_addr_cells(ro    
405         n_root_size_cells = of_n_size_cells(ro    
406         of_node_put(root);                        
407                                                   
408         if (init_drmem_lmb_size(dn))              
409                 return ret;                       
410                                                   
411         usm = of_get_usable_memory(dn);           
412                                                   
413         prop = of_get_property(dn, "ibm,dynami    
414         if (prop) {                               
415                 ret = __walk_drmem_v1_lmbs(pro    
416         } else {                                  
417                 prop = of_get_property(dn, "ib    
418                 if (prop)                         
419                         ret = __walk_drmem_v2_    
420         }                                         
421                                                   
422         return ret;                               
423 }                                                 
424                                                   
425 static void __init init_drmem_v1_lmbs(const __    
426 {                                                 
427         struct drmem_lmb *lmb;                    
428                                                   
429         drmem_info->n_lmbs = of_read_number(pr    
430         if (drmem_info->n_lmbs == 0)              
431                 return;                           
432                                                   
433         drmem_info->lmbs = kcalloc(drmem_info-    
434                                    GFP_KERNEL)    
435         if (!drmem_info->lmbs)                    
436                 return;                           
437                                                   
438         for_each_drmem_lmb(lmb)                   
439                 read_drconf_v1_cell(lmb, &prop    
440 }                                                 
441                                                   
442 static void __init init_drmem_v2_lmbs(const __    
443 {                                                 
444         struct drmem_lmb *lmb;                    
445         struct of_drconf_cell_v2 dr_cell;         
446         const __be32 *p;                          
447         u32 i, j, lmb_sets;                       
448         int lmb_index;                            
449                                                   
450         lmb_sets = of_read_number(prop++, 1);     
451         if (lmb_sets == 0)                        
452                 return;                           
453                                                   
454         /* first pass, calculate the number of    
455         p = prop;                                 
456         for (i = 0; i < lmb_sets; i++) {          
457                 read_drconf_v2_cell(&dr_cell,     
458                 drmem_info->n_lmbs += dr_cell.    
459         }                                         
460                                                   
461         drmem_info->lmbs = kcalloc(drmem_info-    
462                                    GFP_KERNEL)    
463         if (!drmem_info->lmbs)                    
464                 return;                           
465                                                   
466         /* second pass, read in the LMB inform    
467         lmb_index = 0;                            
468         p = prop;                                 
469                                                   
470         for (i = 0; i < lmb_sets; i++) {          
471                 read_drconf_v2_cell(&dr_cell,     
472                                                   
473                 for (j = 0; j < dr_cell.seq_lm    
474                         lmb = &drmem_info->lmb    
475                                                   
476                         lmb->base_addr = dr_ce    
477                         dr_cell.base_addr += d    
478                                                   
479                         lmb->drc_index = dr_ce    
480                         dr_cell.drc_index++;      
481                                                   
482                         lmb->aa_index = dr_cel    
483                         lmb->flags = dr_cell.f    
484                 }                                 
485         }                                         
486 }                                                 
487                                                   
488 static int __init drmem_init(void)                
489 {                                                 
490         struct device_node *dn;                   
491         const __be32 *prop;                       
492                                                   
493         dn = of_find_node_by_path("/ibm,dynami    
494         if (!dn)                                  
495                 return 0;                         
496                                                   
497         if (init_drmem_lmb_size(dn)) {            
498                 of_node_put(dn);                  
499                 return 0;                         
500         }                                         
501                                                   
502         prop = of_get_property(dn, "ibm,dynami    
503         if (prop) {                               
504                 init_drmem_v1_lmbs(prop);         
505         } else {                                  
506                 prop = of_get_property(dn, "ib    
507                 if (prop)                         
508                         init_drmem_v2_lmbs(pro    
509         }                                         
510                                                   
511         of_node_put(dn);                          
512         return 0;                                 
513 }                                                 
514 late_initcall(drmem_init);                        
515                                                   

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

sflogo.php