powerpc/pseries/setup: add missing RTAS retry status handling
authorNathan Lynch <nathanl@linux.ibm.com>
Fri, 10 Feb 2023 18:41:53 +0000 (12:41 -0600)
committerMichael Ellerman <mpe@ellerman.id.au>
Mon, 13 Feb 2023 11:35:01 +0000 (22:35 +1100)
The ibm,get-system-parameter RTAS function may return -2 or 990x,
which indicate that the caller should try again.

pSeries_cmo_feature_init() ignores this, making it possible to fail to
detect cooperative memory overcommit capabilities during boot.

Move the RTAS call into a conventional rtas_busy_delay()-based
loop, dropping unnecessary clearing of rtas_data_buf.

Signed-off-by: Nathan Lynch <nathanl@linux.ibm.com>
Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
Link: https://lore.kernel.org/r/20230125-b4-powerpc-rtas-queue-v3-5-26929c8cce78@linux.ibm.com
arch/powerpc/platforms/pseries/setup.c

index 8ef3270..74e50b6 100644 (file)
@@ -941,21 +941,25 @@ void pSeries_coalesce_init(void)
  */
 static void __init pSeries_cmo_feature_init(void)
 {
+       const s32 token = rtas_token("ibm,get-system-parameter");
        char *ptr, *key, *value, *end;
        int call_status;
        int page_order = IOMMU_PAGE_SHIFT_4K;
 
        pr_debug(" -> fw_cmo_feature_init()\n");
-       spin_lock(&rtas_data_buf_lock);
-       memset(rtas_data_buf, 0, RTAS_DATA_BUF_SIZE);
-       call_status = rtas_call(rtas_token("ibm,get-system-parameter"), 3, 1,
-                               NULL,
-                               CMO_CHARACTERISTICS_TOKEN,
-                               __pa(rtas_data_buf),
-                               RTAS_DATA_BUF_SIZE);
 
-       if (call_status != 0) {
+       do {
+               spin_lock(&rtas_data_buf_lock);
+               call_status = rtas_call(token, 3, 1, NULL,
+                                       CMO_CHARACTERISTICS_TOKEN,
+                                       __pa(rtas_data_buf),
+                                       RTAS_DATA_BUF_SIZE);
+               if (call_status == 0)
+                       break;
                spin_unlock(&rtas_data_buf_lock);
+       } while (rtas_busy_delay(call_status));
+
+       if (call_status != 0) {
                pr_debug("CMO not available\n");
                pr_debug(" <- fw_cmo_feature_init()\n");
                return;