forked from ~ljy/RK356X_SDK_RELEASE

hc
2023-12-08 01573e231f18eb2d99162747186f59511f56b64d
kernel/arch/powerpc/kernel/rtas.c
....@@ -1,14 +1,10 @@
1
+// SPDX-License-Identifier: GPL-2.0-or-later
12 /*
23 *
34 * Procedures for interfacing to the RTAS on CHRP machines.
45 *
56 * Peter Bergner, IBM March 2001.
67 * Copyright (C) 2001 IBM.
7
- *
8
- * This program is free software; you can redistribute it and/or
9
- * modify it under the terms of the GNU General Public License
10
- * as published by the Free Software Foundation; either version
11
- * 2 of the License, or (at your option) any later version.
128 */
139
1410 #include <stdarg.h>
....@@ -20,6 +16,7 @@
2016 #include <linux/capability.h>
2117 #include <linux/delay.h>
2218 #include <linux/cpu.h>
19
+#include <linux/sched.h>
2320 #include <linux/smp.h>
2421 #include <linux/completion.h>
2522 #include <linux/cpumask.h>
....@@ -44,6 +41,7 @@
4441 #include <asm/time.h>
4542 #include <asm/mmu.h>
4643 #include <asm/topology.h>
44
+#include <asm/paca.h>
4745
4846 /* This is here deliberately so it's only used in this file */
4947 void enter_rtas(unsigned long);
....@@ -845,97 +843,6 @@
845843 __rtas_suspend_cpu((struct rtas_suspend_me_data *)info, 1);
846844 }
847845
848
-enum rtas_cpu_state {
849
- DOWN,
850
- UP,
851
-};
852
-
853
-#ifndef CONFIG_SMP
854
-static int rtas_cpu_state_change_mask(enum rtas_cpu_state state,
855
- cpumask_var_t cpus)
856
-{
857
- if (!cpumask_empty(cpus)) {
858
- cpumask_clear(cpus);
859
- return -EINVAL;
860
- } else
861
- return 0;
862
-}
863
-#else
864
-/* On return cpumask will be altered to indicate CPUs changed.
865
- * CPUs with states changed will be set in the mask,
866
- * CPUs with status unchanged will be unset in the mask. */
867
-static int rtas_cpu_state_change_mask(enum rtas_cpu_state state,
868
- cpumask_var_t cpus)
869
-{
870
- int cpu;
871
- int cpuret = 0;
872
- int ret = 0;
873
-
874
- if (cpumask_empty(cpus))
875
- return 0;
876
-
877
- for_each_cpu(cpu, cpus) {
878
- struct device *dev = get_cpu_device(cpu);
879
-
880
- switch (state) {
881
- case DOWN:
882
- cpuret = device_offline(dev);
883
- break;
884
- case UP:
885
- cpuret = device_online(dev);
886
- break;
887
- }
888
- if (cpuret < 0) {
889
- pr_debug("%s: cpu_%s for cpu#%d returned %d.\n",
890
- __func__,
891
- ((state == UP) ? "up" : "down"),
892
- cpu, cpuret);
893
- if (!ret)
894
- ret = cpuret;
895
- if (state == UP) {
896
- /* clear bits for unchanged cpus, return */
897
- cpumask_shift_right(cpus, cpus, cpu);
898
- cpumask_shift_left(cpus, cpus, cpu);
899
- break;
900
- } else {
901
- /* clear bit for unchanged cpu, continue */
902
- cpumask_clear_cpu(cpu, cpus);
903
- }
904
- }
905
- }
906
-
907
- return ret;
908
-}
909
-#endif
910
-
911
-int rtas_online_cpus_mask(cpumask_var_t cpus)
912
-{
913
- int ret;
914
-
915
- ret = rtas_cpu_state_change_mask(UP, cpus);
916
-
917
- if (ret) {
918
- cpumask_var_t tmp_mask;
919
-
920
- if (!alloc_cpumask_var(&tmp_mask, GFP_KERNEL))
921
- return ret;
922
-
923
- /* Use tmp_mask to preserve cpus mask from first failure */
924
- cpumask_copy(tmp_mask, cpus);
925
- rtas_offline_cpus_mask(tmp_mask);
926
- free_cpumask_var(tmp_mask);
927
- }
928
-
929
- return ret;
930
-}
931
-EXPORT_SYMBOL(rtas_online_cpus_mask);
932
-
933
-int rtas_offline_cpus_mask(cpumask_var_t cpus)
934
-{
935
- return rtas_cpu_state_change_mask(DOWN, cpus);
936
-}
937
-EXPORT_SYMBOL(rtas_offline_cpus_mask);
938
-
939846 int rtas_ibm_suspend_me(u64 handle)
940847 {
941848 long state;
....@@ -943,8 +850,6 @@
943850 unsigned long retbuf[PLPAR_HCALL_BUFSIZE];
944851 struct rtas_suspend_me_data data;
945852 DECLARE_COMPLETION_ONSTACK(done);
946
- cpumask_var_t offline_mask;
947
- int cpuret;
948853
949854 if (!rtas_service_present("ibm,suspend-me"))
950855 return -ENOSYS;
....@@ -965,9 +870,6 @@
965870 return -EIO;
966871 }
967872
968
- if (!alloc_cpumask_var(&offline_mask, GFP_KERNEL))
969
- return -ENOMEM;
970
-
971873 atomic_set(&data.working, 0);
972874 atomic_set(&data.done, 0);
973875 atomic_set(&data.error, 0);
....@@ -976,43 +878,76 @@
976878
977879 lock_device_hotplug();
978880
979
- /* All present CPUs must be online */
980
- cpumask_andnot(offline_mask, cpu_present_mask, cpu_online_mask);
981
- cpuret = rtas_online_cpus_mask(offline_mask);
982
- if (cpuret) {
983
- pr_err("%s: Could not bring present CPUs online.\n", __func__);
984
- atomic_set(&data.error, cpuret);
985
- goto out;
986
- }
987
-
988881 cpu_hotplug_disable();
989
- stop_topology_update();
990882
991883 /* Call function on all CPUs. One of us will make the
992884 * rtas call
993885 */
994
- if (on_each_cpu(rtas_percpu_suspend_me, &data, 0))
995
- atomic_set(&data.error, -EINVAL);
886
+ on_each_cpu(rtas_percpu_suspend_me, &data, 0);
996887
997888 wait_for_completion(&done);
998889
999890 if (atomic_read(&data.error) != 0)
1000891 printk(KERN_ERR "Error doing global join\n");
1001892
1002
- start_topology_update();
893
+
1003894 cpu_hotplug_enable();
1004895
1005
- /* Take down CPUs not online prior to suspend */
1006
- cpuret = rtas_offline_cpus_mask(offline_mask);
1007
- if (cpuret)
1008
- pr_warn("%s: Could not restore CPUs to offline state.\n",
1009
- __func__);
1010
-
1011
-out:
1012896 unlock_device_hotplug();
1013
- free_cpumask_var(offline_mask);
897
+
1014898 return atomic_read(&data.error);
1015899 }
900
+
901
+/**
902
+ * rtas_call_reentrant() - Used for reentrant rtas calls
903
+ * @token: Token for desired reentrant RTAS call
904
+ * @nargs: Number of Input Parameters
905
+ * @nret: Number of Output Parameters
906
+ * @outputs: Array of outputs
907
+ * @...: Inputs for desired RTAS call
908
+ *
909
+ * According to LoPAR documentation, only "ibm,int-on", "ibm,int-off",
910
+ * "ibm,get-xive" and "ibm,set-xive" are currently reentrant.
911
+ * Reentrant calls need their own rtas_args buffer, so not using rtas.args, but
912
+ * PACA one instead.
913
+ *
914
+ * Return: -1 on error,
915
+ * First output value of RTAS call if (nret > 0),
916
+ * 0 otherwise,
917
+ */
918
+int rtas_call_reentrant(int token, int nargs, int nret, int *outputs, ...)
919
+{
920
+ va_list list;
921
+ struct rtas_args *args;
922
+ unsigned long flags;
923
+ int i, ret = 0;
924
+
925
+ if (!rtas.entry || token == RTAS_UNKNOWN_SERVICE)
926
+ return -1;
927
+
928
+ local_irq_save(flags);
929
+ preempt_disable();
930
+
931
+ /* We use the per-cpu (PACA) rtas args buffer */
932
+ args = local_paca->rtas_args_reentrant;
933
+
934
+ va_start(list, outputs);
935
+ va_rtas_call_unlocked(args, token, nargs, nret, list);
936
+ va_end(list);
937
+
938
+ if (nret > 1 && outputs)
939
+ for (i = 0; i < nret - 1; ++i)
940
+ outputs[i] = be32_to_cpu(args->rets[i + 1]);
941
+
942
+ if (nret > 0)
943
+ ret = be32_to_cpu(args->rets[0]);
944
+
945
+ local_irq_restore(flags);
946
+ preempt_enable();
947
+
948
+ return ret;
949
+}
950
+
1016951 #else /* CONFIG_PPC_PSERIES */
1017952 int rtas_ibm_suspend_me(u64 handle)
1018953 {
....@@ -1105,7 +1040,7 @@
11051040 { "get-time-of-day", -1, -1, -1, -1, -1 },
11061041 { "ibm,get-vpd", -1, 0, -1, 1, 2 },
11071042 { "ibm,lpar-perftools", -1, 2, 3, -1, -1 },
1108
- { "ibm,platform-dump", -1, 4, 5, -1, -1 },
1043
+ { "ibm,platform-dump", -1, 4, 5, -1, -1 }, /* Special cased */
11091044 { "ibm,read-slot-reset-state", -1, -1, -1, -1, -1 },
11101045 { "ibm,scan-log-dump", -1, 0, 1, -1, -1 },
11111046 { "ibm,set-dynamic-indicator", -1, 2, -1, -1, -1 },
....@@ -1152,6 +1087,15 @@
11521087 size = 1;
11531088
11541089 end = base + size - 1;
1090
+
1091
+ /*
1092
+ * Special case for ibm,platform-dump - NULL buffer
1093
+ * address is used to indicate end of dump processing
1094
+ */
1095
+ if (!strcmp(f->name, "ibm,platform-dump") &&
1096
+ base == 0)
1097
+ return false;
1098
+
11551099 if (!in_rmo_buf(base, end))
11561100 goto err;
11571101 }
....@@ -1332,7 +1276,11 @@
13321276 ibm_suspend_me_token = rtas_token("ibm,suspend-me");
13331277 }
13341278 #endif
1335
- rtas_rmo_buf = memblock_alloc_base(RTAS_RMOBUF_MAX, PAGE_SIZE, rtas_region);
1279
+ rtas_rmo_buf = memblock_phys_alloc_range(RTAS_RMOBUF_MAX, PAGE_SIZE,
1280
+ 0, rtas_region);
1281
+ if (!rtas_rmo_buf)
1282
+ panic("ERROR: RTAS: Failed to allocate %lx bytes below %pa\n",
1283
+ PAGE_SIZE, &rtas_region);
13361284
13371285 #ifdef CONFIG_RTAS_ERROR_LOGGING
13381286 rtas_last_error_token = rtas_token("rtas-last-error");
....@@ -1357,6 +1305,12 @@
13571305 entryp = of_get_flat_dt_prop(node, "linux,rtas-entry", NULL);
13581306 sizep = of_get_flat_dt_prop(node, "rtas-size", NULL);
13591307
1308
+#ifdef CONFIG_PPC64
1309
+ /* need this feature to decide the crashkernel offset */
1310
+ if (of_get_flat_dt_prop(node, "ibm,hypertas-functions", NULL))
1311
+ powerpc_firmware_features |= FW_FEATURE_LPAR;
1312
+#endif
1313
+
13601314 if (basep && entryp && sizep) {
13611315 rtas.base = *basep;
13621316 rtas.entry = *entryp;