Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

powerpc/pseries/dlpar: use RTAS work area API

Hold a work area object for the duration of the RTAS
ibm,configure-connector sequence, eliminating locking and copying
around each RTAS call.

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-13-26929c8cce78@linux.ibm.com

authored by

Nathan Lynch and committed by
Michael Ellerman
e27e1423 43033bc6

+9 -18
+9 -18
arch/powerpc/platforms/pseries/dlpar.c
··· 22 22 #include <asm/machdep.h> 23 23 #include <linux/uaccess.h> 24 24 #include <asm/rtas.h> 25 + #include <asm/rtas-work-area.h> 25 26 26 27 static struct workqueue_struct *pseries_hp_wq; 27 28 ··· 138 137 struct property *property; 139 138 struct property *last_property = NULL; 140 139 struct cc_workarea *ccwa; 140 + struct rtas_work_area *work_area; 141 141 char *data_buf; 142 142 int cc_token; 143 143 int rc = -1; ··· 147 145 if (cc_token == RTAS_UNKNOWN_SERVICE) 148 146 return NULL; 149 147 150 - data_buf = kzalloc(RTAS_DATA_BUF_SIZE, GFP_KERNEL); 151 - if (!data_buf) 152 - return NULL; 148 + work_area = rtas_work_area_alloc(SZ_4K); 149 + data_buf = rtas_work_area_raw_buf(work_area); 153 150 154 151 ccwa = (struct cc_workarea *)&data_buf[0]; 155 152 ccwa->drc_index = drc_index; 156 153 ccwa->zero = 0; 157 154 158 155 do { 159 - /* Since we release the rtas_data_buf lock between configure 160 - * connector calls we want to re-populate the rtas_data_buffer 161 - * with the contents of the previous call. 162 - */ 163 - spin_lock(&rtas_data_buf_lock); 164 - 165 - memcpy(rtas_data_buf, data_buf, RTAS_DATA_BUF_SIZE); 166 - rc = rtas_call(cc_token, 2, 1, NULL, rtas_data_buf, NULL); 167 - memcpy(data_buf, rtas_data_buf, RTAS_DATA_BUF_SIZE); 168 - 169 - spin_unlock(&rtas_data_buf_lock); 170 - 171 - if (rtas_busy_delay(rc)) 172 - continue; 156 + do { 157 + rc = rtas_call(cc_token, 2, 1, NULL, 158 + rtas_work_area_phys(work_area), NULL); 159 + } while (rtas_busy_delay(rc)); 173 160 174 161 switch (rc) { 175 162 case COMPLETE: ··· 218 227 } while (rc); 219 228 220 229 cc_error: 221 - kfree(data_buf); 230 + rtas_work_area_free(work_area); 222 231 223 232 if (rc) { 224 233 if (first_dn)