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

Configure Feed

Select the types of activity you want to include in your feed.

crypto: qat - implement interface for live migration

Add logic to implement the interface for live migration defined in
qat/qat_mig_dev.h. This is specific for QAT GEN4 Virtual Functions
(VFs).

This introduces a migration data manager which is used to handle the
device state during migration. The manager ensures that the device state
is stored in a format that can be restored in the destination node.

The VF state is organized into a hierarchical structure that includes a
preamble, a general state section, a MISC bar section and an ETR bar
section. The latter contains the state of the 4 ring pairs contained on
a VF. Here is a graphical representation of the state:

preamble | general state section | leaf state
| MISC bar state section| leaf state
| ETR bar state section | bank0 state section | leaf state
| bank1 state section | leaf state
| bank2 state section | leaf state
| bank3 state section | leaf state

In addition to the implementation of the qat_migdev_ops interface and
the state manager framework, add a mutex in pfvf to avoid pf2vf messages
during migration.

Signed-off-by: Xin Zeng <xin.zeng@intel.com>
Reviewed-by: Giovanni Cabiddu <giovanni.cabiddu@intel.com>
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>

authored by

Xin Zeng and committed by
Herbert Xu
f0bbfc39 0fce55e5

+1445 -1
+2
drivers/crypto/intel/qat/qat_420xx/adf_420xx_hw_data.c
··· 17 17 #include <adf_gen4_ras.h> 18 18 #include <adf_gen4_timer.h> 19 19 #include <adf_gen4_tl.h> 20 + #include <adf_gen4_vf_mig.h> 20 21 #include "adf_420xx_hw_data.h" 21 22 #include "icp_qat_hw.h" 22 23 ··· 489 488 adf_gen4_init_dc_ops(&hw_data->dc_ops); 490 489 adf_gen4_init_ras_ops(&hw_data->ras_ops); 491 490 adf_gen4_init_tl_data(&hw_data->tl_data); 491 + adf_gen4_init_vf_mig_ops(&hw_data->vfmig_ops); 492 492 adf_init_rl_data(&hw_data->rl_data); 493 493 } 494 494
+2
drivers/crypto/intel/qat/qat_4xxx/adf_4xxx_hw_data.c
··· 17 17 #include "adf_gen4_ras.h" 18 18 #include <adf_gen4_timer.h> 19 19 #include <adf_gen4_tl.h> 20 + #include <adf_gen4_vf_mig.h> 20 21 #include "adf_4xxx_hw_data.h" 21 22 #include "icp_qat_hw.h" 22 23 ··· 473 472 adf_gen4_init_dc_ops(&hw_data->dc_ops); 474 473 adf_gen4_init_ras_ops(&hw_data->ras_ops); 475 474 adf_gen4_init_tl_data(&hw_data->tl_data); 475 + adf_gen4_init_vf_mig_ops(&hw_data->vfmig_ops); 476 476 adf_init_rl_data(&hw_data->rl_data); 477 477 } 478 478
+2
drivers/crypto/intel/qat/qat_common/Makefile
··· 20 20 adf_gen4_config.o \ 21 21 adf_gen4_hw_csr_data.o \ 22 22 adf_gen4_hw_data.o \ 23 + adf_gen4_vf_mig.o \ 23 24 adf_gen4_pm.o \ 24 25 adf_gen2_dc.o \ 25 26 adf_gen4_dc.o \ 26 27 adf_gen4_ras.o \ 27 28 adf_gen4_timer.o \ 28 29 adf_clock.o \ 30 + adf_mstate_mgr.o \ 29 31 qat_crypto.o \ 30 32 qat_compression.o \ 31 33 qat_comp_algs.o \
+6
drivers/crypto/intel/qat/qat_common/adf_accel_devices.h
··· 412 412 struct adf_accel_vf_info { 413 413 struct adf_accel_dev *accel_dev; 414 414 struct mutex pf2vf_lock; /* protect CSR access for PF2VF messages */ 415 + struct mutex pfvf_mig_lock; /* protects PFVF state for migration */ 415 416 struct ratelimit_state vf2pf_ratelimit; 416 417 u32 vf_nr; 417 418 bool init; 418 419 bool restarting; 419 420 u8 vf_compat_ver; 421 + /* 422 + * Private area used for device migration. 423 + * Memory allocation and free is managed by migration driver. 424 + */ 425 + void *mig_priv; 420 426 }; 421 427 422 428 struct adf_dc_data {
+10
drivers/crypto/intel/qat/qat_common/adf_gen4_hw_data.h
··· 86 86 #define ADF_RP_INT_SRC_SEL_F_RISE_MASK BIT(2) 87 87 #define ADF_RP_INT_SRC_SEL_F_FALL_MASK GENMASK(2, 0) 88 88 #define ADF_RP_INT_SRC_SEL_RANGE_WIDTH 4 89 + #define ADF_COALESCED_POLL_TIMEOUT_US (1 * USEC_PER_SEC) 89 90 #define ADF_COALESCED_POLL_DELAY_US 1000 90 91 #define ADF_WQM_CSR_RPINTSOU(bank) (0x200000 + ((bank) << 12)) 91 92 #define ADF_WQM_CSR_RP_IDX_RX 1 ··· 121 120 /* PF2VM communication channel */ 122 121 #define ADF_GEN4_PF2VM_OFFSET(i) (0x40B010 + (i) * 0x20) 123 122 #define ADF_GEN4_VM2PF_OFFSET(i) (0x40B014 + (i) * 0x20) 123 + #define ADF_GEN4_VINTMSKPF2VM_OFFSET(i) (0x40B00C + (i) * 0x20) 124 + #define ADF_GEN4_VINTSOUPF2VM_OFFSET(i) (0x40B008 + (i) * 0x20) 125 + #define ADF_GEN4_VINTMSK_OFFSET(i) (0x40B004 + (i) * 0x20) 126 + #define ADF_GEN4_VINTSOU_OFFSET(i) (0x40B000 + (i) * 0x20) 127 + 128 + struct adf_gen4_vfmig { 129 + struct adf_mstate_mgr *mstate_mgr; 130 + bool bank_stopped[ADF_GEN4_NUM_BANKS_PER_VF]; 131 + }; 124 132 125 133 void adf_gen4_set_ssm_wdtimer(struct adf_accel_dev *accel_dev); 126 134
+1010
drivers/crypto/intel/qat/qat_common/adf_gen4_vf_mig.c
··· 1 + // SPDX-License-Identifier: GPL-2.0-only 2 + /* Copyright(c) 2024 Intel Corporation */ 3 + #include <linux/delay.h> 4 + #include <linux/dev_printk.h> 5 + #include <linux/kernel.h> 6 + #include <linux/slab.h> 7 + #include <linux/string.h> 8 + #include <linux/types.h> 9 + #include <asm/errno.h> 10 + 11 + #include "adf_accel_devices.h" 12 + #include "adf_common_drv.h" 13 + #include "adf_gen4_hw_data.h" 14 + #include "adf_gen4_pfvf.h" 15 + #include "adf_pfvf_utils.h" 16 + #include "adf_mstate_mgr.h" 17 + #include "adf_gen4_vf_mig.h" 18 + 19 + #define ADF_GEN4_VF_MSTATE_SIZE 4096 20 + #define ADF_GEN4_PFVF_RSP_TIMEOUT_US 5000 21 + 22 + static int adf_gen4_vfmig_save_setup(struct qat_mig_dev *mdev); 23 + static int adf_gen4_vfmig_load_setup(struct qat_mig_dev *mdev, int len); 24 + 25 + static int adf_gen4_vfmig_init_device(struct qat_mig_dev *mdev) 26 + { 27 + u8 *state; 28 + 29 + state = kmalloc(ADF_GEN4_VF_MSTATE_SIZE, GFP_KERNEL); 30 + if (!state) 31 + return -ENOMEM; 32 + 33 + mdev->state = state; 34 + mdev->state_size = ADF_GEN4_VF_MSTATE_SIZE; 35 + mdev->setup_size = 0; 36 + mdev->remote_setup_size = 0; 37 + 38 + return 0; 39 + } 40 + 41 + static void adf_gen4_vfmig_cleanup_device(struct qat_mig_dev *mdev) 42 + { 43 + kfree(mdev->state); 44 + mdev->state = NULL; 45 + } 46 + 47 + static void adf_gen4_vfmig_reset_device(struct qat_mig_dev *mdev) 48 + { 49 + mdev->setup_size = 0; 50 + mdev->remote_setup_size = 0; 51 + } 52 + 53 + static int adf_gen4_vfmig_open_device(struct qat_mig_dev *mdev) 54 + { 55 + struct adf_accel_dev *accel_dev = mdev->parent_accel_dev; 56 + struct adf_accel_vf_info *vf_info; 57 + struct adf_gen4_vfmig *vfmig; 58 + 59 + vf_info = &accel_dev->pf.vf_info[mdev->vf_id]; 60 + 61 + vfmig = kzalloc(sizeof(*vfmig), GFP_KERNEL); 62 + if (!vfmig) 63 + return -ENOMEM; 64 + 65 + vfmig->mstate_mgr = adf_mstate_mgr_new(mdev->state, mdev->state_size); 66 + if (!vfmig->mstate_mgr) { 67 + kfree(vfmig); 68 + return -ENOMEM; 69 + } 70 + vf_info->mig_priv = vfmig; 71 + mdev->setup_size = 0; 72 + mdev->remote_setup_size = 0; 73 + 74 + return 0; 75 + } 76 + 77 + static void adf_gen4_vfmig_close_device(struct qat_mig_dev *mdev) 78 + { 79 + struct adf_accel_dev *accel_dev = mdev->parent_accel_dev; 80 + struct adf_accel_vf_info *vf_info; 81 + struct adf_gen4_vfmig *vfmig; 82 + 83 + vf_info = &accel_dev->pf.vf_info[mdev->vf_id]; 84 + if (vf_info->mig_priv) { 85 + vfmig = vf_info->mig_priv; 86 + adf_mstate_mgr_destroy(vfmig->mstate_mgr); 87 + kfree(vfmig); 88 + vf_info->mig_priv = NULL; 89 + } 90 + } 91 + 92 + static int adf_gen4_vfmig_suspend_device(struct qat_mig_dev *mdev) 93 + { 94 + struct adf_accel_dev *accel_dev = mdev->parent_accel_dev; 95 + struct adf_hw_device_data *hw_data = accel_dev->hw_device; 96 + struct adf_accel_vf_info *vf_info; 97 + struct adf_gen4_vfmig *vf_mig; 98 + u32 vf_nr = mdev->vf_id; 99 + int ret, i; 100 + 101 + vf_info = &accel_dev->pf.vf_info[vf_nr]; 102 + vf_mig = vf_info->mig_priv; 103 + 104 + /* Stop all inflight jobs */ 105 + for (i = 0; i < hw_data->num_banks_per_vf; i++) { 106 + u32 pf_bank_nr = i + vf_nr * hw_data->num_banks_per_vf; 107 + 108 + ret = adf_gen4_bank_drain_start(accel_dev, pf_bank_nr, 109 + ADF_RPRESET_POLL_TIMEOUT_US); 110 + if (ret) { 111 + dev_err(&GET_DEV(accel_dev), 112 + "Failed to drain bank %d for vf_nr %d\n", i, 113 + vf_nr); 114 + return ret; 115 + } 116 + vf_mig->bank_stopped[i] = true; 117 + 118 + adf_gen4_bank_quiesce_coal_timer(accel_dev, pf_bank_nr, 119 + ADF_COALESCED_POLL_TIMEOUT_US); 120 + } 121 + 122 + return 0; 123 + } 124 + 125 + static int adf_gen4_vfmig_resume_device(struct qat_mig_dev *mdev) 126 + { 127 + struct adf_accel_dev *accel_dev = mdev->parent_accel_dev; 128 + struct adf_hw_device_data *hw_data = accel_dev->hw_device; 129 + struct adf_accel_vf_info *vf_info; 130 + struct adf_gen4_vfmig *vf_mig; 131 + u32 vf_nr = mdev->vf_id; 132 + int i; 133 + 134 + vf_info = &accel_dev->pf.vf_info[vf_nr]; 135 + vf_mig = vf_info->mig_priv; 136 + 137 + for (i = 0; i < hw_data->num_banks_per_vf; i++) { 138 + u32 pf_bank_nr = i + vf_nr * hw_data->num_banks_per_vf; 139 + 140 + if (vf_mig->bank_stopped[i]) { 141 + adf_gen4_bank_drain_finish(accel_dev, pf_bank_nr); 142 + vf_mig->bank_stopped[i] = false; 143 + } 144 + } 145 + 146 + return 0; 147 + } 148 + 149 + struct adf_vf_bank_info { 150 + struct adf_accel_dev *accel_dev; 151 + u32 vf_nr; 152 + u32 bank_nr; 153 + }; 154 + 155 + struct mig_user_sla { 156 + enum adf_base_services srv; 157 + u64 rp_mask; 158 + u32 cir; 159 + u32 pir; 160 + }; 161 + 162 + static int adf_mstate_sla_check(struct adf_mstate_mgr *sub_mgr, u8 *src_buf, 163 + u32 src_size, void *opaque) 164 + { 165 + struct adf_mstate_vreginfo _sinfo = { src_buf, src_size }; 166 + struct adf_mstate_vreginfo *sinfo = &_sinfo, *dinfo = opaque; 167 + u32 src_sla_cnt = sinfo->size / sizeof(struct mig_user_sla); 168 + u32 dst_sla_cnt = dinfo->size / sizeof(struct mig_user_sla); 169 + struct mig_user_sla *src_slas = sinfo->addr; 170 + struct mig_user_sla *dst_slas = dinfo->addr; 171 + int i, j; 172 + 173 + for (i = 0; i < src_sla_cnt; i++) { 174 + for (j = 0; j < dst_sla_cnt; j++) { 175 + if (src_slas[i].srv != dst_slas[j].srv || 176 + src_slas[i].rp_mask != dst_slas[j].rp_mask) 177 + continue; 178 + 179 + if (src_slas[i].cir > dst_slas[j].cir || 180 + src_slas[i].pir > dst_slas[j].pir) { 181 + pr_err("QAT: DST VF rate limiting mismatch.\n"); 182 + return -EINVAL; 183 + } 184 + break; 185 + } 186 + 187 + if (j == dst_sla_cnt) { 188 + pr_err("QAT: SRC VF rate limiting mismatch - SRC srv %d and rp_mask 0x%llx.\n", 189 + src_slas[i].srv, src_slas[i].rp_mask); 190 + return -EINVAL; 191 + } 192 + } 193 + 194 + return 0; 195 + } 196 + 197 + static inline int adf_mstate_check_cap_size(u32 src_sz, u32 dst_sz, u32 max_sz) 198 + { 199 + if (src_sz > max_sz || dst_sz > max_sz) 200 + return -EINVAL; 201 + else 202 + return 0; 203 + } 204 + 205 + static int adf_mstate_compatver_check(struct adf_mstate_mgr *sub_mgr, 206 + u8 *src_buf, u32 src_sz, void *opaque) 207 + { 208 + struct adf_mstate_vreginfo *info = opaque; 209 + u8 compat = 0; 210 + u8 *pcompat; 211 + 212 + if (src_sz != info->size) { 213 + pr_debug("QAT: State mismatch (compat version size), current %u, expected %u\n", 214 + src_sz, info->size); 215 + return -EINVAL; 216 + } 217 + 218 + memcpy(info->addr, src_buf, info->size); 219 + pcompat = info->addr; 220 + if (*pcompat == 0) { 221 + pr_warn("QAT: Unable to determine the version of VF\n"); 222 + return 0; 223 + } 224 + 225 + compat = adf_vf_compat_checker(*pcompat); 226 + if (compat == ADF_PF2VF_VF_INCOMPATIBLE) { 227 + pr_debug("QAT: SRC VF driver (ver=%u) is incompatible with DST PF driver (ver=%u)\n", 228 + *pcompat, ADF_PFVF_COMPAT_THIS_VERSION); 229 + return -EINVAL; 230 + } 231 + 232 + if (compat == ADF_PF2VF_VF_COMPAT_UNKNOWN) 233 + pr_debug("QAT: SRC VF driver (ver=%u) is newer than DST PF driver (ver=%u)\n", 234 + *pcompat, ADF_PFVF_COMPAT_THIS_VERSION); 235 + 236 + return 0; 237 + } 238 + 239 + /* 240 + * adf_mstate_capmask_compare() - compare QAT device capability mask 241 + * @sinfo: Pointer to source capability info 242 + * @dinfo: Pointer to target capability info 243 + * 244 + * This function compares the capability mask between source VF and target VF 245 + * 246 + * Returns: 0 if target capability mask is identical to source capability mask, 247 + * 1 if target mask can represent all the capabilities represented by source mask, 248 + * -1 if target mask can't represent all the capabilities represented by source 249 + * mask. 250 + */ 251 + static int adf_mstate_capmask_compare(struct adf_mstate_vreginfo *sinfo, 252 + struct adf_mstate_vreginfo *dinfo) 253 + { 254 + u64 src = 0, dst = 0; 255 + 256 + if (adf_mstate_check_cap_size(sinfo->size, dinfo->size, sizeof(u64))) { 257 + pr_debug("QAT: Unexpected capability size %u %u %zu\n", 258 + sinfo->size, dinfo->size, sizeof(u64)); 259 + return -1; 260 + } 261 + 262 + memcpy(&src, sinfo->addr, sinfo->size); 263 + memcpy(&dst, dinfo->addr, dinfo->size); 264 + 265 + pr_debug("QAT: Check cap compatibility of cap %llu %llu\n", src, dst); 266 + 267 + if (src == dst) 268 + return 0; 269 + 270 + if ((src | dst) == dst) 271 + return 1; 272 + 273 + return -1; 274 + } 275 + 276 + static int adf_mstate_capmask_superset(struct adf_mstate_mgr *sub_mgr, u8 *buf, 277 + u32 size, void *opa) 278 + { 279 + struct adf_mstate_vreginfo sinfo = { buf, size }; 280 + 281 + if (adf_mstate_capmask_compare(&sinfo, opa) >= 0) 282 + return 0; 283 + 284 + return -EINVAL; 285 + } 286 + 287 + static int adf_mstate_capmask_equal(struct adf_mstate_mgr *sub_mgr, u8 *buf, 288 + u32 size, void *opa) 289 + { 290 + struct adf_mstate_vreginfo sinfo = { buf, size }; 291 + 292 + if (adf_mstate_capmask_compare(&sinfo, opa) == 0) 293 + return 0; 294 + 295 + return -EINVAL; 296 + } 297 + 298 + static int adf_mstate_set_vreg(struct adf_mstate_mgr *sub_mgr, u8 *buf, 299 + u32 size, void *opa) 300 + { 301 + struct adf_mstate_vreginfo *info = opa; 302 + 303 + if (size != info->size) { 304 + pr_debug("QAT: Unexpected cap size %u %u\n", size, info->size); 305 + return -EINVAL; 306 + } 307 + memcpy(info->addr, buf, info->size); 308 + 309 + return 0; 310 + } 311 + 312 + static u32 adf_gen4_vfmig_get_slas(struct adf_accel_dev *accel_dev, u32 vf_nr, 313 + struct mig_user_sla *pmig_slas) 314 + { 315 + struct adf_hw_device_data *hw_data = accel_dev->hw_device; 316 + struct adf_rl *rl_data = accel_dev->rate_limiting; 317 + struct rl_sla **sla_type_arr = NULL; 318 + u64 rp_mask, rp_index; 319 + u32 max_num_sla; 320 + u32 sla_cnt = 0; 321 + int i, j; 322 + 323 + if (!accel_dev->rate_limiting) 324 + return 0; 325 + 326 + rp_index = vf_nr * hw_data->num_banks_per_vf; 327 + max_num_sla = adf_rl_get_sla_arr_of_type(rl_data, RL_LEAF, &sla_type_arr); 328 + 329 + for (i = 0; i < max_num_sla; i++) { 330 + if (!sla_type_arr[i]) 331 + continue; 332 + 333 + rp_mask = 0; 334 + for (j = 0; j < sla_type_arr[i]->ring_pairs_cnt; j++) 335 + rp_mask |= BIT(sla_type_arr[i]->ring_pairs_ids[j]); 336 + 337 + if (rp_mask & GENMASK_ULL(rp_index + 3, rp_index)) { 338 + pmig_slas->rp_mask = rp_mask; 339 + pmig_slas->cir = sla_type_arr[i]->cir; 340 + pmig_slas->pir = sla_type_arr[i]->pir; 341 + pmig_slas->srv = sla_type_arr[i]->srv; 342 + pmig_slas++; 343 + sla_cnt++; 344 + } 345 + } 346 + 347 + return sla_cnt; 348 + } 349 + 350 + static int adf_gen4_vfmig_load_etr_regs(struct adf_mstate_mgr *sub_mgr, 351 + u8 *state, u32 size, void *opa) 352 + { 353 + struct adf_vf_bank_info *vf_bank_info = opa; 354 + struct adf_accel_dev *accel_dev = vf_bank_info->accel_dev; 355 + struct adf_hw_device_data *hw_data = accel_dev->hw_device; 356 + u32 pf_bank_nr; 357 + int ret; 358 + 359 + pf_bank_nr = vf_bank_info->bank_nr + vf_bank_info->vf_nr * hw_data->num_banks_per_vf; 360 + ret = hw_data->bank_state_restore(accel_dev, pf_bank_nr, 361 + (struct bank_state *)state); 362 + if (ret) { 363 + dev_err(&GET_DEV(accel_dev), 364 + "Failed to load regs for vf%d bank%d\n", 365 + vf_bank_info->vf_nr, vf_bank_info->bank_nr); 366 + return ret; 367 + } 368 + 369 + return 0; 370 + } 371 + 372 + static int adf_gen4_vfmig_load_etr_bank(struct adf_accel_dev *accel_dev, 373 + u32 vf_nr, u32 bank_nr, 374 + struct adf_mstate_mgr *mstate_mgr) 375 + { 376 + struct adf_vf_bank_info vf_bank_info = {accel_dev, vf_nr, bank_nr}; 377 + struct adf_mstate_sect_h *subsec, *l2_subsec; 378 + struct adf_mstate_mgr sub_sects_mgr; 379 + char bank_ids[ADF_MSTATE_ID_LEN]; 380 + 381 + snprintf(bank_ids, sizeof(bank_ids), ADF_MSTATE_BANK_IDX_IDS "%x", bank_nr); 382 + subsec = adf_mstate_sect_lookup(mstate_mgr, bank_ids, NULL, NULL); 383 + if (!subsec) { 384 + dev_err(&GET_DEV(accel_dev), 385 + "Failed to lookup sec %s for vf%d bank%d\n", 386 + ADF_MSTATE_BANK_IDX_IDS, vf_nr, bank_nr); 387 + return -EINVAL; 388 + } 389 + 390 + adf_mstate_mgr_init_from_psect(&sub_sects_mgr, subsec); 391 + l2_subsec = adf_mstate_sect_lookup(&sub_sects_mgr, ADF_MSTATE_ETR_REGS_IDS, 392 + adf_gen4_vfmig_load_etr_regs, 393 + &vf_bank_info); 394 + if (!l2_subsec) { 395 + dev_err(&GET_DEV(accel_dev), 396 + "Failed to add sec %s for vf%d bank%d\n", 397 + ADF_MSTATE_ETR_REGS_IDS, vf_nr, bank_nr); 398 + return -EINVAL; 399 + } 400 + 401 + return 0; 402 + } 403 + 404 + static int adf_gen4_vfmig_load_etr(struct adf_accel_dev *accel_dev, u32 vf_nr) 405 + { 406 + struct adf_accel_vf_info *vf_info = &accel_dev->pf.vf_info[vf_nr]; 407 + struct adf_hw_device_data *hw_data = accel_dev->hw_device; 408 + struct adf_gen4_vfmig *vfmig = vf_info->mig_priv; 409 + struct adf_mstate_mgr *mstate_mgr = vfmig->mstate_mgr; 410 + struct adf_mstate_mgr sub_sects_mgr; 411 + struct adf_mstate_sect_h *subsec; 412 + int ret, i; 413 + 414 + subsec = adf_mstate_sect_lookup(mstate_mgr, ADF_MSTATE_ETRB_IDS, NULL, 415 + NULL); 416 + if (!subsec) { 417 + dev_err(&GET_DEV(accel_dev), "Failed to load sec %s\n", 418 + ADF_MSTATE_ETRB_IDS); 419 + return -EINVAL; 420 + } 421 + 422 + adf_mstate_mgr_init_from_psect(&sub_sects_mgr, subsec); 423 + for (i = 0; i < hw_data->num_banks_per_vf; i++) { 424 + ret = adf_gen4_vfmig_load_etr_bank(accel_dev, vf_nr, i, 425 + &sub_sects_mgr); 426 + if (ret) 427 + return ret; 428 + } 429 + 430 + return 0; 431 + } 432 + 433 + static int adf_gen4_vfmig_load_misc(struct adf_accel_dev *accel_dev, u32 vf_nr) 434 + { 435 + struct adf_accel_vf_info *vf_info = &accel_dev->pf.vf_info[vf_nr]; 436 + struct adf_gen4_vfmig *vfmig = vf_info->mig_priv; 437 + void __iomem *csr = adf_get_pmisc_base(accel_dev); 438 + struct adf_mstate_mgr *mstate_mgr = vfmig->mstate_mgr; 439 + struct adf_mstate_sect_h *subsec, *l2_subsec; 440 + struct adf_mstate_mgr sub_sects_mgr; 441 + struct { 442 + char *id; 443 + u64 ofs; 444 + } misc_states[] = { 445 + {ADF_MSTATE_VINTMSK_IDS, ADF_GEN4_VINTMSK_OFFSET(vf_nr)}, 446 + {ADF_MSTATE_VINTMSK_PF2VM_IDS, ADF_GEN4_VINTMSKPF2VM_OFFSET(vf_nr)}, 447 + {ADF_MSTATE_PF2VM_IDS, ADF_GEN4_PF2VM_OFFSET(vf_nr)}, 448 + {ADF_MSTATE_VM2PF_IDS, ADF_GEN4_VM2PF_OFFSET(vf_nr)}, 449 + }; 450 + int i; 451 + 452 + subsec = adf_mstate_sect_lookup(mstate_mgr, ADF_MSTATE_MISCB_IDS, NULL, 453 + NULL); 454 + if (!subsec) { 455 + dev_err(&GET_DEV(accel_dev), "Failed to load sec %s\n", 456 + ADF_MSTATE_MISCB_IDS); 457 + return -EINVAL; 458 + } 459 + 460 + adf_mstate_mgr_init_from_psect(&sub_sects_mgr, subsec); 461 + for (i = 0; i < ARRAY_SIZE(misc_states); i++) { 462 + struct adf_mstate_vreginfo info; 463 + u32 regv; 464 + 465 + info.addr = &regv; 466 + info.size = sizeof(regv); 467 + l2_subsec = adf_mstate_sect_lookup(&sub_sects_mgr, 468 + misc_states[i].id, 469 + adf_mstate_set_vreg, 470 + &info); 471 + if (!l2_subsec) { 472 + dev_err(&GET_DEV(accel_dev), 473 + "Failed to load sec %s\n", misc_states[i].id); 474 + return -EINVAL; 475 + } 476 + ADF_CSR_WR(csr, misc_states[i].ofs, regv); 477 + } 478 + 479 + return 0; 480 + } 481 + 482 + static int adf_gen4_vfmig_load_generic(struct adf_accel_dev *accel_dev, u32 vf_nr) 483 + { 484 + struct adf_accel_vf_info *vf_info = &accel_dev->pf.vf_info[vf_nr]; 485 + struct mig_user_sla dst_slas[RL_RP_CNT_PER_LEAF_MAX] = { }; 486 + struct adf_gen4_vfmig *vfmig = vf_info->mig_priv; 487 + struct adf_mstate_mgr *mstate_mgr = vfmig->mstate_mgr; 488 + struct adf_mstate_sect_h *subsec, *l2_subsec; 489 + struct adf_mstate_mgr sub_sects_mgr; 490 + u32 dst_sla_cnt; 491 + struct { 492 + char *id; 493 + int (*action)(struct adf_mstate_mgr *sub_mgr, u8 *buf, u32 size, void *opa); 494 + struct adf_mstate_vreginfo info; 495 + } gen_states[] = { 496 + {ADF_MSTATE_IOV_INIT_IDS, adf_mstate_set_vreg, 497 + {&vf_info->init, sizeof(vf_info->init)}}, 498 + {ADF_MSTATE_COMPAT_VER_IDS, adf_mstate_compatver_check, 499 + {&vf_info->vf_compat_ver, sizeof(vf_info->vf_compat_ver)}}, 500 + {ADF_MSTATE_SLA_IDS, adf_mstate_sla_check, {dst_slas, 0}}, 501 + }; 502 + int i; 503 + 504 + subsec = adf_mstate_sect_lookup(mstate_mgr, ADF_MSTATE_GEN_IDS, NULL, NULL); 505 + if (!subsec) { 506 + dev_err(&GET_DEV(accel_dev), "Failed to load sec %s\n", 507 + ADF_MSTATE_GEN_IDS); 508 + return -EINVAL; 509 + } 510 + 511 + adf_mstate_mgr_init_from_psect(&sub_sects_mgr, subsec); 512 + for (i = 0; i < ARRAY_SIZE(gen_states); i++) { 513 + if (gen_states[i].info.addr == dst_slas) { 514 + dst_sla_cnt = adf_gen4_vfmig_get_slas(accel_dev, vf_nr, dst_slas); 515 + gen_states[i].info.size = dst_sla_cnt * sizeof(struct mig_user_sla); 516 + } 517 + 518 + l2_subsec = adf_mstate_sect_lookup(&sub_sects_mgr, 519 + gen_states[i].id, 520 + gen_states[i].action, 521 + &gen_states[i].info); 522 + if (!l2_subsec) { 523 + dev_err(&GET_DEV(accel_dev), "Failed to load sec %s\n", 524 + gen_states[i].id); 525 + return -EINVAL; 526 + } 527 + } 528 + 529 + return 0; 530 + } 531 + 532 + static int adf_gen4_vfmig_load_config(struct adf_accel_dev *accel_dev, u32 vf_nr) 533 + { 534 + struct adf_accel_vf_info *vf_info = &accel_dev->pf.vf_info[vf_nr]; 535 + struct adf_hw_device_data *hw_data = accel_dev->hw_device; 536 + struct adf_gen4_vfmig *vfmig = vf_info->mig_priv; 537 + struct adf_mstate_mgr *mstate_mgr = vfmig->mstate_mgr; 538 + struct adf_mstate_sect_h *subsec, *l2_subsec; 539 + struct adf_mstate_mgr sub_sects_mgr; 540 + struct { 541 + char *id; 542 + int (*action)(struct adf_mstate_mgr *sub_mgr, u8 *buf, u32 size, void *opa); 543 + struct adf_mstate_vreginfo info; 544 + } setups[] = { 545 + {ADF_MSTATE_GEN_CAP_IDS, adf_mstate_capmask_superset, 546 + {&hw_data->accel_capabilities_mask, sizeof(hw_data->accel_capabilities_mask)}}, 547 + {ADF_MSTATE_GEN_SVCMAP_IDS, adf_mstate_capmask_equal, 548 + {&hw_data->ring_to_svc_map, sizeof(hw_data->ring_to_svc_map)}}, 549 + {ADF_MSTATE_GEN_EXTDC_IDS, adf_mstate_capmask_superset, 550 + {&hw_data->extended_dc_capabilities, sizeof(hw_data->extended_dc_capabilities)}}, 551 + }; 552 + int i; 553 + 554 + subsec = adf_mstate_sect_lookup(mstate_mgr, ADF_MSTATE_CONFIG_IDS, NULL, NULL); 555 + if (!subsec) { 556 + dev_err(&GET_DEV(accel_dev), "Failed to load sec %s\n", 557 + ADF_MSTATE_CONFIG_IDS); 558 + return -EINVAL; 559 + } 560 + 561 + adf_mstate_mgr_init_from_psect(&sub_sects_mgr, subsec); 562 + for (i = 0; i < ARRAY_SIZE(setups); i++) { 563 + l2_subsec = adf_mstate_sect_lookup(&sub_sects_mgr, setups[i].id, 564 + setups[i].action, &setups[i].info); 565 + if (!l2_subsec) { 566 + dev_err(&GET_DEV(accel_dev), "Failed to load sec %s\n", 567 + setups[i].id); 568 + return -EINVAL; 569 + } 570 + } 571 + 572 + return 0; 573 + } 574 + 575 + static int adf_gen4_vfmig_save_etr_regs(struct adf_mstate_mgr *subs, u8 *state, 576 + u32 size, void *opa) 577 + { 578 + struct adf_vf_bank_info *vf_bank_info = opa; 579 + struct adf_accel_dev *accel_dev = vf_bank_info->accel_dev; 580 + struct adf_hw_device_data *hw_data = accel_dev->hw_device; 581 + u32 pf_bank_nr; 582 + int ret; 583 + 584 + pf_bank_nr = vf_bank_info->bank_nr; 585 + pf_bank_nr += vf_bank_info->vf_nr * hw_data->num_banks_per_vf; 586 + 587 + ret = hw_data->bank_state_save(accel_dev, pf_bank_nr, 588 + (struct bank_state *)state); 589 + if (ret) { 590 + dev_err(&GET_DEV(accel_dev), 591 + "Failed to save regs for vf%d bank%d\n", 592 + vf_bank_info->vf_nr, vf_bank_info->bank_nr); 593 + return ret; 594 + } 595 + 596 + return sizeof(struct bank_state); 597 + } 598 + 599 + static int adf_gen4_vfmig_save_etr_bank(struct adf_accel_dev *accel_dev, 600 + u32 vf_nr, u32 bank_nr, 601 + struct adf_mstate_mgr *mstate_mgr) 602 + { 603 + struct adf_mstate_sect_h *subsec, *l2_subsec; 604 + struct adf_vf_bank_info vf_bank_info; 605 + struct adf_mstate_mgr sub_sects_mgr; 606 + char bank_ids[ADF_MSTATE_ID_LEN]; 607 + 608 + snprintf(bank_ids, sizeof(bank_ids), ADF_MSTATE_BANK_IDX_IDS "%x", bank_nr); 609 + 610 + subsec = adf_mstate_sect_add(mstate_mgr, bank_ids, NULL, NULL); 611 + if (!subsec) { 612 + dev_err(&GET_DEV(accel_dev), 613 + "Failed to add sec %s for vf%d bank%d\n", 614 + ADF_MSTATE_BANK_IDX_IDS, vf_nr, bank_nr); 615 + return -EINVAL; 616 + } 617 + 618 + adf_mstate_mgr_init_from_parent(&sub_sects_mgr, mstate_mgr); 619 + vf_bank_info.accel_dev = accel_dev; 620 + vf_bank_info.vf_nr = vf_nr; 621 + vf_bank_info.bank_nr = bank_nr; 622 + l2_subsec = adf_mstate_sect_add(&sub_sects_mgr, ADF_MSTATE_ETR_REGS_IDS, 623 + adf_gen4_vfmig_save_etr_regs, 624 + &vf_bank_info); 625 + if (!l2_subsec) { 626 + dev_err(&GET_DEV(accel_dev), 627 + "Failed to add sec %s for vf%d bank%d\n", 628 + ADF_MSTATE_ETR_REGS_IDS, vf_nr, bank_nr); 629 + return -EINVAL; 630 + } 631 + adf_mstate_sect_update(mstate_mgr, &sub_sects_mgr, subsec); 632 + 633 + return 0; 634 + } 635 + 636 + static int adf_gen4_vfmig_save_etr(struct adf_accel_dev *accel_dev, u32 vf_nr) 637 + { 638 + struct adf_accel_vf_info *vf_info = &accel_dev->pf.vf_info[vf_nr]; 639 + struct adf_hw_device_data *hw_data = accel_dev->hw_device; 640 + struct adf_gen4_vfmig *vfmig = vf_info->mig_priv; 641 + struct adf_mstate_mgr *mstate_mgr = vfmig->mstate_mgr; 642 + struct adf_mstate_mgr sub_sects_mgr; 643 + struct adf_mstate_sect_h *subsec; 644 + int ret, i; 645 + 646 + subsec = adf_mstate_sect_add(mstate_mgr, ADF_MSTATE_ETRB_IDS, NULL, NULL); 647 + if (!subsec) { 648 + dev_err(&GET_DEV(accel_dev), "Failed to add sec %s\n", 649 + ADF_MSTATE_ETRB_IDS); 650 + return -EINVAL; 651 + } 652 + 653 + adf_mstate_mgr_init_from_parent(&sub_sects_mgr, mstate_mgr); 654 + for (i = 0; i < hw_data->num_banks_per_vf; i++) { 655 + ret = adf_gen4_vfmig_save_etr_bank(accel_dev, vf_nr, i, 656 + &sub_sects_mgr); 657 + if (ret) 658 + return ret; 659 + } 660 + adf_mstate_sect_update(mstate_mgr, &sub_sects_mgr, subsec); 661 + 662 + return 0; 663 + } 664 + 665 + static int adf_gen4_vfmig_save_misc(struct adf_accel_dev *accel_dev, u32 vf_nr) 666 + { 667 + struct adf_accel_vf_info *vf_info = &accel_dev->pf.vf_info[vf_nr]; 668 + struct adf_gen4_vfmig *vfmig = vf_info->mig_priv; 669 + struct adf_mstate_mgr *mstate_mgr = vfmig->mstate_mgr; 670 + void __iomem *csr = adf_get_pmisc_base(accel_dev); 671 + struct adf_mstate_sect_h *subsec, *l2_subsec; 672 + struct adf_mstate_mgr sub_sects_mgr; 673 + struct { 674 + char *id; 675 + u64 offset; 676 + } misc_states[] = { 677 + {ADF_MSTATE_VINTSRC_IDS, ADF_GEN4_VINTSOU_OFFSET(vf_nr)}, 678 + {ADF_MSTATE_VINTMSK_IDS, ADF_GEN4_VINTMSK_OFFSET(vf_nr)}, 679 + {ADF_MSTATE_VINTSRC_PF2VM_IDS, ADF_GEN4_VINTSOUPF2VM_OFFSET(vf_nr)}, 680 + {ADF_MSTATE_VINTMSK_PF2VM_IDS, ADF_GEN4_VINTMSKPF2VM_OFFSET(vf_nr)}, 681 + {ADF_MSTATE_PF2VM_IDS, ADF_GEN4_PF2VM_OFFSET(vf_nr)}, 682 + {ADF_MSTATE_VM2PF_IDS, ADF_GEN4_VM2PF_OFFSET(vf_nr)}, 683 + }; 684 + ktime_t time_exp; 685 + int i; 686 + 687 + subsec = adf_mstate_sect_add(mstate_mgr, ADF_MSTATE_MISCB_IDS, NULL, NULL); 688 + if (!subsec) { 689 + dev_err(&GET_DEV(accel_dev), "Failed to add sec %s\n", 690 + ADF_MSTATE_MISCB_IDS); 691 + return -EINVAL; 692 + } 693 + 694 + time_exp = ktime_add_us(ktime_get(), ADF_GEN4_PFVF_RSP_TIMEOUT_US); 695 + while (!mutex_trylock(&vf_info->pfvf_mig_lock)) { 696 + if (ktime_after(ktime_get(), time_exp)) { 697 + dev_err(&GET_DEV(accel_dev), "Failed to get pfvf mig lock\n"); 698 + return -ETIMEDOUT; 699 + } 700 + usleep_range(500, 1000); 701 + } 702 + 703 + adf_mstate_mgr_init_from_parent(&sub_sects_mgr, mstate_mgr); 704 + for (i = 0; i < ARRAY_SIZE(misc_states); i++) { 705 + struct adf_mstate_vreginfo info; 706 + u32 regv; 707 + 708 + info.addr = &regv; 709 + info.size = sizeof(regv); 710 + regv = ADF_CSR_RD(csr, misc_states[i].offset); 711 + 712 + l2_subsec = adf_mstate_sect_add_vreg(&sub_sects_mgr, 713 + misc_states[i].id, 714 + &info); 715 + if (!l2_subsec) { 716 + dev_err(&GET_DEV(accel_dev), "Failed to add sec %s\n", 717 + misc_states[i].id); 718 + mutex_unlock(&vf_info->pfvf_mig_lock); 719 + return -EINVAL; 720 + } 721 + } 722 + 723 + mutex_unlock(&vf_info->pfvf_mig_lock); 724 + adf_mstate_sect_update(mstate_mgr, &sub_sects_mgr, subsec); 725 + 726 + return 0; 727 + } 728 + 729 + static int adf_gen4_vfmig_save_generic(struct adf_accel_dev *accel_dev, u32 vf_nr) 730 + { 731 + struct adf_accel_vf_info *vf_info = &accel_dev->pf.vf_info[vf_nr]; 732 + struct adf_gen4_vfmig *vfmig = vf_info->mig_priv; 733 + struct adf_mstate_mgr *mstate_mgr = vfmig->mstate_mgr; 734 + struct adf_mstate_mgr sub_sects_mgr; 735 + struct adf_mstate_sect_h *subsec, *l2_subsec; 736 + struct mig_user_sla src_slas[RL_RP_CNT_PER_LEAF_MAX] = { }; 737 + u32 src_sla_cnt; 738 + struct { 739 + char *id; 740 + struct adf_mstate_vreginfo info; 741 + } gen_states[] = { 742 + {ADF_MSTATE_IOV_INIT_IDS, 743 + {&vf_info->init, sizeof(vf_info->init)}}, 744 + {ADF_MSTATE_COMPAT_VER_IDS, 745 + {&vf_info->vf_compat_ver, sizeof(vf_info->vf_compat_ver)}}, 746 + {ADF_MSTATE_SLA_IDS, {src_slas, 0}}, 747 + }; 748 + int i; 749 + 750 + subsec = adf_mstate_sect_add(mstate_mgr, ADF_MSTATE_GEN_IDS, NULL, NULL); 751 + if (!subsec) { 752 + dev_err(&GET_DEV(accel_dev), "Failed to add sec %s\n", 753 + ADF_MSTATE_GEN_IDS); 754 + return -EINVAL; 755 + } 756 + 757 + adf_mstate_mgr_init_from_parent(&sub_sects_mgr, mstate_mgr); 758 + for (i = 0; i < ARRAY_SIZE(gen_states); i++) { 759 + if (gen_states[i].info.addr == src_slas) { 760 + src_sla_cnt = adf_gen4_vfmig_get_slas(accel_dev, vf_nr, src_slas); 761 + gen_states[i].info.size = src_sla_cnt * sizeof(struct mig_user_sla); 762 + } 763 + 764 + l2_subsec = adf_mstate_sect_add_vreg(&sub_sects_mgr, 765 + gen_states[i].id, 766 + &gen_states[i].info); 767 + if (!l2_subsec) { 768 + dev_err(&GET_DEV(accel_dev), "Failed to add sec %s\n", 769 + gen_states[i].id); 770 + return -EINVAL; 771 + } 772 + } 773 + adf_mstate_sect_update(mstate_mgr, &sub_sects_mgr, subsec); 774 + 775 + return 0; 776 + } 777 + 778 + static int adf_gen4_vfmig_save_config(struct adf_accel_dev *accel_dev, u32 vf_nr) 779 + { 780 + struct adf_accel_vf_info *vf_info = &accel_dev->pf.vf_info[vf_nr]; 781 + struct adf_hw_device_data *hw_data = accel_dev->hw_device; 782 + struct adf_gen4_vfmig *vfmig = vf_info->mig_priv; 783 + struct adf_mstate_mgr *mstate_mgr = vfmig->mstate_mgr; 784 + struct adf_mstate_mgr sub_sects_mgr; 785 + struct adf_mstate_sect_h *subsec, *l2_subsec; 786 + struct { 787 + char *id; 788 + struct adf_mstate_vreginfo info; 789 + } setups[] = { 790 + {ADF_MSTATE_GEN_CAP_IDS, 791 + {&hw_data->accel_capabilities_mask, sizeof(hw_data->accel_capabilities_mask)}}, 792 + {ADF_MSTATE_GEN_SVCMAP_IDS, 793 + {&hw_data->ring_to_svc_map, sizeof(hw_data->ring_to_svc_map)}}, 794 + {ADF_MSTATE_GEN_EXTDC_IDS, 795 + {&hw_data->extended_dc_capabilities, sizeof(hw_data->extended_dc_capabilities)}}, 796 + }; 797 + int i; 798 + 799 + subsec = adf_mstate_sect_add(mstate_mgr, ADF_MSTATE_CONFIG_IDS, NULL, NULL); 800 + if (!subsec) { 801 + dev_err(&GET_DEV(accel_dev), "Failed to add sec %s\n", 802 + ADF_MSTATE_CONFIG_IDS); 803 + return -EINVAL; 804 + } 805 + 806 + adf_mstate_mgr_init_from_parent(&sub_sects_mgr, mstate_mgr); 807 + for (i = 0; i < ARRAY_SIZE(setups); i++) { 808 + l2_subsec = adf_mstate_sect_add_vreg(&sub_sects_mgr, setups[i].id, 809 + &setups[i].info); 810 + if (!l2_subsec) { 811 + dev_err(&GET_DEV(accel_dev), "Failed to add sec %s\n", 812 + setups[i].id); 813 + return -EINVAL; 814 + } 815 + } 816 + adf_mstate_sect_update(mstate_mgr, &sub_sects_mgr, subsec); 817 + 818 + return 0; 819 + } 820 + 821 + static int adf_gen4_vfmig_save_state(struct qat_mig_dev *mdev) 822 + { 823 + struct adf_accel_dev *accel_dev = mdev->parent_accel_dev; 824 + struct adf_accel_vf_info *vf_info; 825 + struct adf_gen4_vfmig *vfmig; 826 + u32 vf_nr = mdev->vf_id; 827 + int ret; 828 + 829 + vf_info = &accel_dev->pf.vf_info[vf_nr]; 830 + vfmig = vf_info->mig_priv; 831 + 832 + ret = adf_gen4_vfmig_save_setup(mdev); 833 + if (ret) { 834 + dev_err(&GET_DEV(accel_dev), 835 + "Failed to save setup for vf_nr %d\n", vf_nr); 836 + return ret; 837 + } 838 + 839 + adf_mstate_mgr_init(vfmig->mstate_mgr, mdev->state + mdev->setup_size, 840 + mdev->state_size - mdev->setup_size); 841 + if (!adf_mstate_preamble_add(vfmig->mstate_mgr)) 842 + return -EINVAL; 843 + 844 + ret = adf_gen4_vfmig_save_generic(accel_dev, vf_nr); 845 + if (ret) { 846 + dev_err(&GET_DEV(accel_dev), 847 + "Failed to save generic state for vf_nr %d\n", vf_nr); 848 + return ret; 849 + } 850 + 851 + ret = adf_gen4_vfmig_save_misc(accel_dev, vf_nr); 852 + if (ret) { 853 + dev_err(&GET_DEV(accel_dev), 854 + "Failed to save misc bar state for vf_nr %d\n", vf_nr); 855 + return ret; 856 + } 857 + 858 + ret = adf_gen4_vfmig_save_etr(accel_dev, vf_nr); 859 + if (ret) { 860 + dev_err(&GET_DEV(accel_dev), 861 + "Failed to save etr bar state for vf_nr %d\n", vf_nr); 862 + return ret; 863 + } 864 + 865 + adf_mstate_preamble_update(vfmig->mstate_mgr); 866 + 867 + return 0; 868 + } 869 + 870 + static int adf_gen4_vfmig_load_state(struct qat_mig_dev *mdev) 871 + { 872 + struct adf_accel_dev *accel_dev = mdev->parent_accel_dev; 873 + struct adf_accel_vf_info *vf_info; 874 + struct adf_gen4_vfmig *vfmig; 875 + u32 vf_nr = mdev->vf_id; 876 + int ret; 877 + 878 + vf_info = &accel_dev->pf.vf_info[vf_nr]; 879 + vfmig = vf_info->mig_priv; 880 + 881 + ret = adf_gen4_vfmig_load_setup(mdev, mdev->state_size); 882 + if (ret) { 883 + dev_err(&GET_DEV(accel_dev), "Failed to load setup for vf_nr %d\n", 884 + vf_nr); 885 + return ret; 886 + } 887 + 888 + ret = adf_mstate_mgr_init_from_remote(vfmig->mstate_mgr, 889 + mdev->state + mdev->remote_setup_size, 890 + mdev->state_size - mdev->remote_setup_size, 891 + NULL, NULL); 892 + if (ret) { 893 + dev_err(&GET_DEV(accel_dev), "Invalid state for vf_nr %d\n", 894 + vf_nr); 895 + return ret; 896 + } 897 + 898 + ret = adf_gen4_vfmig_load_generic(accel_dev, vf_nr); 899 + if (ret) { 900 + dev_err(&GET_DEV(accel_dev), 901 + "Failed to load general state for vf_nr %d\n", vf_nr); 902 + return ret; 903 + } 904 + 905 + ret = adf_gen4_vfmig_load_misc(accel_dev, vf_nr); 906 + if (ret) { 907 + dev_err(&GET_DEV(accel_dev), 908 + "Failed to load misc bar state for vf_nr %d\n", vf_nr); 909 + return ret; 910 + } 911 + 912 + ret = adf_gen4_vfmig_load_etr(accel_dev, vf_nr); 913 + if (ret) { 914 + dev_err(&GET_DEV(accel_dev), 915 + "Failed to load etr bar state for vf_nr %d\n", vf_nr); 916 + return ret; 917 + } 918 + 919 + return 0; 920 + } 921 + 922 + static int adf_gen4_vfmig_save_setup(struct qat_mig_dev *mdev) 923 + { 924 + struct adf_accel_dev *accel_dev = mdev->parent_accel_dev; 925 + struct adf_accel_vf_info *vf_info; 926 + struct adf_gen4_vfmig *vfmig; 927 + u32 vf_nr = mdev->vf_id; 928 + int ret; 929 + 930 + vf_info = &accel_dev->pf.vf_info[vf_nr]; 931 + vfmig = vf_info->mig_priv; 932 + 933 + if (mdev->setup_size) 934 + return 0; 935 + 936 + adf_mstate_mgr_init(vfmig->mstate_mgr, mdev->state, mdev->state_size); 937 + if (!adf_mstate_preamble_add(vfmig->mstate_mgr)) 938 + return -EINVAL; 939 + 940 + ret = adf_gen4_vfmig_save_config(accel_dev, mdev->vf_id); 941 + if (ret) 942 + return ret; 943 + 944 + adf_mstate_preamble_update(vfmig->mstate_mgr); 945 + mdev->setup_size = adf_mstate_state_size(vfmig->mstate_mgr); 946 + 947 + return 0; 948 + } 949 + 950 + static int adf_gen4_vfmig_load_setup(struct qat_mig_dev *mdev, int len) 951 + { 952 + struct adf_accel_dev *accel_dev = mdev->parent_accel_dev; 953 + struct adf_accel_vf_info *vf_info; 954 + struct adf_gen4_vfmig *vfmig; 955 + u32 vf_nr = mdev->vf_id; 956 + u32 setup_size; 957 + int ret; 958 + 959 + vf_info = &accel_dev->pf.vf_info[vf_nr]; 960 + vfmig = vf_info->mig_priv; 961 + 962 + if (mdev->remote_setup_size) 963 + return 0; 964 + 965 + if (len < sizeof(struct adf_mstate_preh)) 966 + return -EAGAIN; 967 + 968 + adf_mstate_mgr_init(vfmig->mstate_mgr, mdev->state, mdev->state_size); 969 + setup_size = adf_mstate_state_size_from_remote(vfmig->mstate_mgr); 970 + if (setup_size > mdev->state_size) 971 + return -EINVAL; 972 + 973 + if (len < setup_size) 974 + return -EAGAIN; 975 + 976 + ret = adf_mstate_mgr_init_from_remote(vfmig->mstate_mgr, mdev->state, 977 + setup_size, NULL, NULL); 978 + if (ret) { 979 + dev_err(&GET_DEV(accel_dev), "Invalide setup for vf_nr %d\n", 980 + vf_nr); 981 + return ret; 982 + } 983 + 984 + mdev->remote_setup_size = setup_size; 985 + 986 + ret = adf_gen4_vfmig_load_config(accel_dev, vf_nr); 987 + if (ret) { 988 + dev_err(&GET_DEV(accel_dev), 989 + "Failed to load config for vf_nr %d\n", vf_nr); 990 + return ret; 991 + } 992 + 993 + return 0; 994 + } 995 + 996 + void adf_gen4_init_vf_mig_ops(struct qat_migdev_ops *vfmig_ops) 997 + { 998 + vfmig_ops->init = adf_gen4_vfmig_init_device; 999 + vfmig_ops->cleanup = adf_gen4_vfmig_cleanup_device; 1000 + vfmig_ops->reset = adf_gen4_vfmig_reset_device; 1001 + vfmig_ops->open = adf_gen4_vfmig_open_device; 1002 + vfmig_ops->close = adf_gen4_vfmig_close_device; 1003 + vfmig_ops->suspend = adf_gen4_vfmig_suspend_device; 1004 + vfmig_ops->resume = adf_gen4_vfmig_resume_device; 1005 + vfmig_ops->save_state = adf_gen4_vfmig_save_state; 1006 + vfmig_ops->load_state = adf_gen4_vfmig_load_state; 1007 + vfmig_ops->load_setup = adf_gen4_vfmig_load_setup; 1008 + vfmig_ops->save_setup = adf_gen4_vfmig_save_setup; 1009 + } 1010 + EXPORT_SYMBOL_GPL(adf_gen4_init_vf_mig_ops);
+318
drivers/crypto/intel/qat/qat_common/adf_mstate_mgr.c
··· 1 + // SPDX-License-Identifier: GPL-2.0-only 2 + /* Copyright(c) 2024 Intel Corporation */ 3 + 4 + #include <linux/slab.h> 5 + #include <linux/types.h> 6 + #include "adf_mstate_mgr.h" 7 + 8 + #define ADF_MSTATE_MAGIC 0xADF5CAEA 9 + #define ADF_MSTATE_VERSION 0x1 10 + 11 + struct adf_mstate_sect_h { 12 + u8 id[ADF_MSTATE_ID_LEN]; 13 + u32 size; 14 + u32 sub_sects; 15 + u8 state[]; 16 + }; 17 + 18 + u32 adf_mstate_state_size(struct adf_mstate_mgr *mgr) 19 + { 20 + return mgr->state - mgr->buf; 21 + } 22 + 23 + static inline u32 adf_mstate_avail_room(struct adf_mstate_mgr *mgr) 24 + { 25 + return mgr->buf + mgr->size - mgr->state; 26 + } 27 + 28 + void adf_mstate_mgr_init(struct adf_mstate_mgr *mgr, u8 *buf, u32 size) 29 + { 30 + mgr->buf = buf; 31 + mgr->state = buf; 32 + mgr->size = size; 33 + mgr->n_sects = 0; 34 + }; 35 + 36 + struct adf_mstate_mgr *adf_mstate_mgr_new(u8 *buf, u32 size) 37 + { 38 + struct adf_mstate_mgr *mgr; 39 + 40 + mgr = kzalloc(sizeof(*mgr), GFP_KERNEL); 41 + if (!mgr) 42 + return NULL; 43 + 44 + adf_mstate_mgr_init(mgr, buf, size); 45 + 46 + return mgr; 47 + } 48 + 49 + void adf_mstate_mgr_destroy(struct adf_mstate_mgr *mgr) 50 + { 51 + kfree(mgr); 52 + } 53 + 54 + void adf_mstate_mgr_init_from_parent(struct adf_mstate_mgr *mgr, 55 + struct adf_mstate_mgr *p_mgr) 56 + { 57 + adf_mstate_mgr_init(mgr, p_mgr->state, 58 + p_mgr->size - adf_mstate_state_size(p_mgr)); 59 + } 60 + 61 + void adf_mstate_mgr_init_from_psect(struct adf_mstate_mgr *mgr, 62 + struct adf_mstate_sect_h *p_sect) 63 + { 64 + adf_mstate_mgr_init(mgr, p_sect->state, p_sect->size); 65 + mgr->n_sects = p_sect->sub_sects; 66 + } 67 + 68 + static void adf_mstate_preamble_init(struct adf_mstate_preh *preamble) 69 + { 70 + preamble->magic = ADF_MSTATE_MAGIC; 71 + preamble->version = ADF_MSTATE_VERSION; 72 + preamble->preh_len = sizeof(*preamble); 73 + preamble->size = 0; 74 + preamble->n_sects = 0; 75 + } 76 + 77 + /* default preambles checker */ 78 + static int adf_mstate_preamble_def_checker(struct adf_mstate_preh *preamble, 79 + void *opaque) 80 + { 81 + struct adf_mstate_mgr *mgr = opaque; 82 + 83 + if (preamble->magic != ADF_MSTATE_MAGIC || 84 + preamble->version > ADF_MSTATE_VERSION || 85 + preamble->preh_len > mgr->size) { 86 + pr_debug("QAT: LM - Invalid state (magic=%#x, version=%#x, hlen=%u), state_size=%u\n", 87 + preamble->magic, preamble->version, preamble->preh_len, 88 + mgr->size); 89 + return -EINVAL; 90 + } 91 + 92 + return 0; 93 + } 94 + 95 + struct adf_mstate_preh *adf_mstate_preamble_add(struct adf_mstate_mgr *mgr) 96 + { 97 + struct adf_mstate_preh *pre = (struct adf_mstate_preh *)mgr->buf; 98 + 99 + if (adf_mstate_avail_room(mgr) < sizeof(*pre)) { 100 + pr_err("QAT: LM - Not enough space for preamble\n"); 101 + return NULL; 102 + } 103 + 104 + adf_mstate_preamble_init(pre); 105 + mgr->state += pre->preh_len; 106 + 107 + return pre; 108 + } 109 + 110 + int adf_mstate_preamble_update(struct adf_mstate_mgr *mgr) 111 + { 112 + struct adf_mstate_preh *preamble = (struct adf_mstate_preh *)mgr->buf; 113 + 114 + preamble->size = adf_mstate_state_size(mgr) - preamble->preh_len; 115 + preamble->n_sects = mgr->n_sects; 116 + 117 + return 0; 118 + } 119 + 120 + static void adf_mstate_dump_sect(struct adf_mstate_sect_h *sect, 121 + const char *prefix) 122 + { 123 + pr_debug("QAT: LM - %s QAT state section %s\n", prefix, sect->id); 124 + print_hex_dump_debug("h-", DUMP_PREFIX_OFFSET, 16, 2, sect, 125 + sizeof(*sect), true); 126 + print_hex_dump_debug("s-", DUMP_PREFIX_OFFSET, 16, 2, sect->state, 127 + sect->size, true); 128 + } 129 + 130 + static inline void __adf_mstate_sect_update(struct adf_mstate_mgr *mgr, 131 + struct adf_mstate_sect_h *sect, 132 + u32 size, 133 + u32 n_subsects) 134 + { 135 + sect->size += size; 136 + sect->sub_sects += n_subsects; 137 + mgr->n_sects++; 138 + mgr->state += sect->size; 139 + 140 + adf_mstate_dump_sect(sect, "Add"); 141 + } 142 + 143 + void adf_mstate_sect_update(struct adf_mstate_mgr *p_mgr, 144 + struct adf_mstate_mgr *curr_mgr, 145 + struct adf_mstate_sect_h *sect) 146 + { 147 + __adf_mstate_sect_update(p_mgr, sect, adf_mstate_state_size(curr_mgr), 148 + curr_mgr->n_sects); 149 + } 150 + 151 + static struct adf_mstate_sect_h *adf_mstate_sect_add_header(struct adf_mstate_mgr *mgr, 152 + const char *id) 153 + { 154 + struct adf_mstate_sect_h *sect = (struct adf_mstate_sect_h *)(mgr->state); 155 + 156 + if (adf_mstate_avail_room(mgr) < sizeof(*sect)) { 157 + pr_debug("QAT: LM - Not enough space for header of QAT state sect %s\n", id); 158 + return NULL; 159 + } 160 + 161 + strscpy(sect->id, id, sizeof(sect->id)); 162 + sect->size = 0; 163 + sect->sub_sects = 0; 164 + mgr->state += sizeof(*sect); 165 + 166 + return sect; 167 + } 168 + 169 + struct adf_mstate_sect_h *adf_mstate_sect_add_vreg(struct adf_mstate_mgr *mgr, 170 + const char *id, 171 + struct adf_mstate_vreginfo *info) 172 + { 173 + struct adf_mstate_sect_h *sect; 174 + 175 + sect = adf_mstate_sect_add_header(mgr, id); 176 + if (!sect) 177 + return NULL; 178 + 179 + if (adf_mstate_avail_room(mgr) < info->size) { 180 + pr_debug("QAT: LM - Not enough space for QAT state sect %s, requires %u\n", 181 + id, info->size); 182 + return NULL; 183 + } 184 + 185 + memcpy(sect->state, info->addr, info->size); 186 + __adf_mstate_sect_update(mgr, sect, info->size, 0); 187 + 188 + return sect; 189 + } 190 + 191 + struct adf_mstate_sect_h *adf_mstate_sect_add(struct adf_mstate_mgr *mgr, 192 + const char *id, 193 + adf_mstate_populate populate, 194 + void *opaque) 195 + { 196 + struct adf_mstate_mgr sub_sects_mgr; 197 + struct adf_mstate_sect_h *sect; 198 + int avail_room, size; 199 + 200 + sect = adf_mstate_sect_add_header(mgr, id); 201 + if (!sect) 202 + return NULL; 203 + 204 + if (!populate) 205 + return sect; 206 + 207 + avail_room = adf_mstate_avail_room(mgr); 208 + adf_mstate_mgr_init_from_parent(&sub_sects_mgr, mgr); 209 + 210 + size = (*populate)(&sub_sects_mgr, sect->state, avail_room, opaque); 211 + if (size < 0) 212 + return NULL; 213 + 214 + size += adf_mstate_state_size(&sub_sects_mgr); 215 + if (avail_room < size) { 216 + pr_debug("QAT: LM - Not enough space for QAT state sect %s, requires %u\n", 217 + id, size); 218 + return NULL; 219 + } 220 + __adf_mstate_sect_update(mgr, sect, size, sub_sects_mgr.n_sects); 221 + 222 + return sect; 223 + } 224 + 225 + static int adf_mstate_sect_validate(struct adf_mstate_mgr *mgr) 226 + { 227 + struct adf_mstate_sect_h *start = (struct adf_mstate_sect_h *)mgr->state; 228 + struct adf_mstate_sect_h *sect = start; 229 + u64 end; 230 + int i; 231 + 232 + end = (uintptr_t)mgr->buf + mgr->size; 233 + for (i = 0; i < mgr->n_sects; i++) { 234 + uintptr_t s_start = (uintptr_t)sect->state; 235 + uintptr_t s_end = s_start + sect->size; 236 + 237 + if (s_end < s_start || s_end > end) { 238 + pr_debug("QAT: LM - Corrupted state section (index=%u, size=%u) in state_mgr (size=%u, secs=%u)\n", 239 + i, sect->size, mgr->size, mgr->n_sects); 240 + return -EINVAL; 241 + } 242 + sect = (struct adf_mstate_sect_h *)s_end; 243 + } 244 + 245 + pr_debug("QAT: LM - Scanned section (last child=%s, size=%lu) in state_mgr (size=%u, secs=%u)\n", 246 + start->id, sizeof(struct adf_mstate_sect_h) * (ulong)(sect - start), 247 + mgr->size, mgr->n_sects); 248 + 249 + return 0; 250 + } 251 + 252 + u32 adf_mstate_state_size_from_remote(struct adf_mstate_mgr *mgr) 253 + { 254 + struct adf_mstate_preh *preh = (struct adf_mstate_preh *)mgr->buf; 255 + 256 + return preh->preh_len + preh->size; 257 + } 258 + 259 + int adf_mstate_mgr_init_from_remote(struct adf_mstate_mgr *mgr, u8 *buf, u32 size, 260 + adf_mstate_preamble_checker pre_checker, 261 + void *opaque) 262 + { 263 + struct adf_mstate_preh *pre; 264 + int ret; 265 + 266 + adf_mstate_mgr_init(mgr, buf, size); 267 + pre = (struct adf_mstate_preh *)(mgr->buf); 268 + 269 + pr_debug("QAT: LM - Dump state preambles\n"); 270 + print_hex_dump_debug("", DUMP_PREFIX_OFFSET, 16, 2, pre, pre->preh_len, 0); 271 + 272 + if (pre_checker) 273 + ret = (*pre_checker)(pre, opaque); 274 + else 275 + ret = adf_mstate_preamble_def_checker(pre, mgr); 276 + if (ret) 277 + return ret; 278 + 279 + mgr->state = mgr->buf + pre->preh_len; 280 + mgr->n_sects = pre->n_sects; 281 + 282 + return adf_mstate_sect_validate(mgr); 283 + } 284 + 285 + struct adf_mstate_sect_h *adf_mstate_sect_lookup(struct adf_mstate_mgr *mgr, 286 + const char *id, 287 + adf_mstate_action action, 288 + void *opaque) 289 + { 290 + struct adf_mstate_sect_h *sect = (struct adf_mstate_sect_h *)mgr->state; 291 + struct adf_mstate_mgr sub_sects_mgr; 292 + int i, ret; 293 + 294 + for (i = 0; i < mgr->n_sects; i++) { 295 + if (!strncmp(sect->id, id, sizeof(sect->id))) 296 + goto found; 297 + 298 + sect = (struct adf_mstate_sect_h *)(sect->state + sect->size); 299 + } 300 + 301 + return NULL; 302 + 303 + found: 304 + adf_mstate_dump_sect(sect, "Found"); 305 + 306 + adf_mstate_mgr_init_from_psect(&sub_sects_mgr, sect); 307 + if (sect->sub_sects && adf_mstate_sect_validate(&sub_sects_mgr)) 308 + return NULL; 309 + 310 + if (!action) 311 + return sect; 312 + 313 + ret = (*action)(&sub_sects_mgr, sect->state, sect->size, opaque); 314 + if (ret) 315 + return NULL; 316 + 317 + return sect; 318 + }
+89
drivers/crypto/intel/qat/qat_common/adf_mstate_mgr.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0-only */ 2 + /* Copyright(c) 2024 Intel Corporation */ 3 + 4 + #ifndef ADF_MSTATE_MGR_H 5 + #define ADF_MSTATE_MGR_H 6 + 7 + #define ADF_MSTATE_ID_LEN 8 8 + 9 + #define ADF_MSTATE_ETRB_IDS "ETRBAR" 10 + #define ADF_MSTATE_MISCB_IDS "MISCBAR" 11 + #define ADF_MSTATE_EXTB_IDS "EXTBAR" 12 + #define ADF_MSTATE_GEN_IDS "GENER" 13 + #define ADF_MSTATE_CONFIG_IDS "CONFIG" 14 + #define ADF_MSTATE_SECTION_NUM 5 15 + 16 + #define ADF_MSTATE_BANK_IDX_IDS "bnk" 17 + 18 + #define ADF_MSTATE_ETR_REGS_IDS "mregs" 19 + #define ADF_MSTATE_VINTSRC_IDS "visrc" 20 + #define ADF_MSTATE_VINTMSK_IDS "vimsk" 21 + #define ADF_MSTATE_SLA_IDS "sla" 22 + #define ADF_MSTATE_IOV_INIT_IDS "iovinit" 23 + #define ADF_MSTATE_COMPAT_VER_IDS "compver" 24 + #define ADF_MSTATE_GEN_CAP_IDS "gencap" 25 + #define ADF_MSTATE_GEN_SVCMAP_IDS "svcmap" 26 + #define ADF_MSTATE_GEN_EXTDC_IDS "extdc" 27 + #define ADF_MSTATE_VINTSRC_PF2VM_IDS "vispv" 28 + #define ADF_MSTATE_VINTMSK_PF2VM_IDS "vimpv" 29 + #define ADF_MSTATE_VM2PF_IDS "vm2pf" 30 + #define ADF_MSTATE_PF2VM_IDS "pf2vm" 31 + 32 + struct adf_mstate_mgr { 33 + u8 *buf; 34 + u8 *state; 35 + u32 size; 36 + u32 n_sects; 37 + }; 38 + 39 + struct adf_mstate_preh { 40 + u32 magic; 41 + u32 version; 42 + u16 preh_len; 43 + u16 n_sects; 44 + u32 size; 45 + }; 46 + 47 + struct adf_mstate_vreginfo { 48 + void *addr; 49 + u32 size; 50 + }; 51 + 52 + struct adf_mstate_sect_h; 53 + 54 + typedef int (*adf_mstate_preamble_checker)(struct adf_mstate_preh *preamble, void *opa); 55 + typedef int (*adf_mstate_populate)(struct adf_mstate_mgr *sub_mgr, u8 *buf, 56 + u32 size, void *opa); 57 + typedef int (*adf_mstate_action)(struct adf_mstate_mgr *sub_mgr, u8 *buf, u32 size, 58 + void *opa); 59 + 60 + struct adf_mstate_mgr *adf_mstate_mgr_new(u8 *buf, u32 size); 61 + void adf_mstate_mgr_destroy(struct adf_mstate_mgr *mgr); 62 + void adf_mstate_mgr_init(struct adf_mstate_mgr *mgr, u8 *buf, u32 size); 63 + void adf_mstate_mgr_init_from_parent(struct adf_mstate_mgr *mgr, 64 + struct adf_mstate_mgr *p_mgr); 65 + void adf_mstate_mgr_init_from_psect(struct adf_mstate_mgr *mgr, 66 + struct adf_mstate_sect_h *p_sect); 67 + int adf_mstate_mgr_init_from_remote(struct adf_mstate_mgr *mgr, 68 + u8 *buf, u32 size, 69 + adf_mstate_preamble_checker checker, 70 + void *opaque); 71 + struct adf_mstate_preh *adf_mstate_preamble_add(struct adf_mstate_mgr *mgr); 72 + int adf_mstate_preamble_update(struct adf_mstate_mgr *mgr); 73 + u32 adf_mstate_state_size(struct adf_mstate_mgr *mgr); 74 + u32 adf_mstate_state_size_from_remote(struct adf_mstate_mgr *mgr); 75 + void adf_mstate_sect_update(struct adf_mstate_mgr *p_mgr, 76 + struct adf_mstate_mgr *curr_mgr, 77 + struct adf_mstate_sect_h *sect); 78 + struct adf_mstate_sect_h *adf_mstate_sect_add_vreg(struct adf_mstate_mgr *mgr, 79 + const char *id, 80 + struct adf_mstate_vreginfo *info); 81 + struct adf_mstate_sect_h *adf_mstate_sect_add(struct adf_mstate_mgr *mgr, 82 + const char *id, 83 + adf_mstate_populate populate, 84 + void *opaque); 85 + struct adf_mstate_sect_h *adf_mstate_sect_lookup(struct adf_mstate_mgr *mgr, 86 + const char *id, 87 + adf_mstate_action action, 88 + void *opaque); 89 + #endif
+6 -1
drivers/crypto/intel/qat/qat_common/adf_sriov.c
··· 26 26 u32 vf_nr = vf_info->vf_nr; 27 27 bool ret; 28 28 29 + mutex_lock(&vf_info->pfvf_mig_lock); 29 30 ret = adf_recv_and_handle_vf2pf_msg(accel_dev, vf_nr); 30 31 if (ret) 31 32 /* re-enable interrupt on PF from this VF */ 32 33 adf_enable_vf2pf_interrupts(accel_dev, 1 << vf_nr); 34 + mutex_unlock(&vf_info->pfvf_mig_lock); 33 35 34 36 kfree(pf2vf_resp); 35 37 } ··· 64 62 vf_info->vf_nr = i; 65 63 66 64 mutex_init(&vf_info->pf2vf_lock); 65 + mutex_init(&vf_info->pfvf_mig_lock); 67 66 ratelimit_state_init(&vf_info->vf2pf_ratelimit, 68 67 ADF_VF2PF_RATELIMIT_INTERVAL, 69 68 ADF_VF2PF_RATELIMIT_BURST); ··· 141 138 if (hw_data->configure_iov_threads) 142 139 hw_data->configure_iov_threads(accel_dev, false); 143 140 144 - for (i = 0, vf = accel_dev->pf.vf_info; i < totalvfs; i++, vf++) 141 + for (i = 0, vf = accel_dev->pf.vf_info; i < totalvfs; i++, vf++) { 145 142 mutex_destroy(&vf->pf2vf_lock); 143 + mutex_destroy(&vf->pfvf_mig_lock); 144 + } 146 145 147 146 if (!test_bit(ADF_STATUS_RESTARTING, &accel_dev->status)) { 148 147 kfree(accel_dev->pf.vf_info);