From nobody Sat Feb 7 08:44:36 2026 Received: from mgamail.intel.com (mgamail.intel.com [192.198.163.16]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 0956D15FCE9; Fri, 5 Jul 2024 18:15:23 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=192.198.163.16 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1720203325; cv=none; b=fRVCaO80WLtDd50hvAvr6VzSzSUwS+ZQuaqRfYu+QV7tgrTMSNXgweqlCmKJ6Zh4yeBGFpeNwjcCQl/eI5jl47NqTn0FILoBq5CXV79zYlnl64bTz862dXNuIOz4wvu0hytFpxmnuBVmzuYT3zDFj/+WUWrA6XAynVSa+w0EHrA= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1720203325; c=relaxed/simple; bh=EZlEkzR6k7XGgV0+ZMZDFuYvwsVONhRSZrAAjdocq2w=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=rl0hv6Nxin4actcQX5D9dISMDs1PseR6ryA0U2igV/Yu5ciqlkZQzSjfNJchTttZm2txcXitzFVY3matibCauFfbhVHDz1zLTsDqOChjmP06EECFraJaj6JDgSfkxK/V0VgFPX6XSgGfQXXDMrHS6w8HGmpHiCTEUutgFCRoOOE= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=intel.com; spf=pass smtp.mailfrom=intel.com; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b=hLhon7mq; arc=none smtp.client-ip=192.198.163.16 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=intel.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=intel.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b="hLhon7mq" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1720203324; x=1751739324; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=EZlEkzR6k7XGgV0+ZMZDFuYvwsVONhRSZrAAjdocq2w=; b=hLhon7mqiHb1MbYklHoVOOVlE+m+UP0b5u9AIdZcRNJrrf5lukXN5xgo ufp2qHlsSsjbRNwzYKPujv6EyMD17XeF5S90AR49ATqf8HUGITqD3xJ0m SeWvlDo1YxDMyua7Gwlzo6sngfva+gTvCO/jYLscunxcrdHmTOsikeCdK zH22LGYDpLyy+VX4TViNNi3IfiEz4hotOMDiwFCYNtC5Vh7K8C4Oqlu96 kwwaE1s1kA0kHrIYNAAfhot9mjNGvhRRtpgEYE5kBZeEieKST3QLMx6kU 786Q4vHaIfWx/kskhNdPAw9IvGQiPpaqsrhtKio6EvsMCK9uUHbBBhDJN A==; X-CSE-ConnectionGUID: 9ahph7IQRx2FIuatQ0acWg== X-CSE-MsgGUID: kiBCil7vS2GCkD4uuAZ7cg== X-IronPort-AV: E=McAfee;i="6700,10204,11123"; a="12410721" X-IronPort-AV: E=Sophos;i="6.09,185,1716274800"; d="scan'208";a="12410721" Received: from orviesa008.jf.intel.com ([10.64.159.148]) by fmvoesa110.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 05 Jul 2024 11:15:20 -0700 X-CSE-ConnectionGUID: KRlqnAzuSy6VRy9sDfsRbg== X-CSE-MsgGUID: jzgzzgnqSByvc/wcDMhiUw== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.09,185,1716274800"; d="scan'208";a="47672701" Received: from fyu1.sc.intel.com ([172.25.103.126]) by orviesa008.jf.intel.com with ESMTP; 05 Jul 2024 11:15:20 -0700 From: Fenghua Yu To: "Vinod Koul" , "Dave Jiang" Cc: dmaengine@vger.kernel.org, "linux-kernel" , Fenghua Yu Subject: [PATCH 3/5] dmaengine: idxd: Add idxd_device_config_save() and idxd_device_config_restore() helpers Date: Fri, 5 Jul 2024 11:15:16 -0700 Message-Id: <20240705181519.4067507-4-fenghua.yu@intel.com> X-Mailer: git-send-email 2.37.1 In-Reply-To: <20240705181519.4067507-1-fenghua.yu@intel.com> References: <20240705181519.4067507-1-fenghua.yu@intel.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Add the helpers to save and restore IDXD device configurations. These helpers will be called during Function Level Reset (FLR) processing. Signed-off-by: Fenghua Yu --- drivers/dma/idxd/idxd.h | 11 ++ drivers/dma/idxd/init.c | 224 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 235 insertions(+) diff --git a/drivers/dma/idxd/idxd.h b/drivers/dma/idxd/idxd.h index 03f099518ec1..4f3e98720b45 100644 --- a/drivers/dma/idxd/idxd.h +++ b/drivers/dma/idxd/idxd.h @@ -377,6 +377,17 @@ struct idxd_device { struct dentry *dbgfs_evl_file; =20 bool user_submission_safe; + + struct idxd_saved_states *idxd_saved; +}; + +struct idxd_saved_states { + struct idxd_device saved_idxd; + struct idxd_evl saved_evl; + struct idxd_engine **saved_engines; + struct idxd_wq **saved_wqs; + struct idxd_group **saved_groups; + unsigned long *saved_wq_enable_map; }; =20 static inline unsigned int evl_ent_size(struct idxd_device *idxd) diff --git a/drivers/dma/idxd/init.c b/drivers/dma/idxd/init.c index a6d8097b2dcf..bb03d8cc5d32 100644 --- a/drivers/dma/idxd/init.c +++ b/drivers/dma/idxd/init.c @@ -749,6 +749,230 @@ static void idxd_unbind(struct device_driver *drv, co= nst char *buf) put_device(dev); } =20 +/* Free allocated saved wq enable map after saving wq configs. */ +static void free_saved_wq_enable_map(unsigned long *map) +{ + bitmap_free(map); +} + +DEFINE_FREE(free_saved_wq_enable_map, unsigned long *, if (!IS_ERR_OR_NULL= (_T)) + free_saved_wq_enable_map(_T)) + +#define idxd_free_saved_configs(saved_configs, count) \ + do { \ + int i; \ + \ + for (i =3D 0; i < (count); i++) \ + kfree(saved_configs[i]); \ + } while (0) + +/* + * Save IDXD device configurations including engines, groups, wqs etc. + * The saved configurations can be restored when needed. + */ +static int idxd_device_config_save(struct idxd_device *idxd, + struct idxd_saved_states *idxd_saved) +{ + struct device *dev =3D &idxd->pdev->dev; + int i; + + memcpy(&idxd_saved->saved_idxd, idxd, sizeof(*idxd)); + + if (idxd->evl) { + memcpy(&idxd_saved->saved_evl, idxd->evl, + sizeof(struct idxd_evl)); + } + + struct idxd_group **saved_groups __free(kfree) =3D + kcalloc_node(idxd->max_groups, + sizeof(struct idxd_group *), + GFP_KERNEL, dev_to_node(dev)); + if (!saved_groups) + return -ENOMEM; + + for (i =3D 0; i < idxd->max_groups; i++) { + struct idxd_group *saved_group __free(kfree) =3D + kzalloc_node(sizeof(*saved_group), GFP_KERNEL, + dev_to_node(dev)); + + if (!saved_group) { + idxd_free_saved_configs(saved_groups, i); + + return -ENOMEM; + } + + memcpy(saved_group, idxd->groups[i], sizeof(*saved_group)); + saved_groups[i] =3D no_free_ptr(saved_group); + } + + struct idxd_engine **saved_engines =3D + kcalloc_node(idxd->max_engines, + sizeof(struct idxd_engine *), + GFP_KERNEL, dev_to_node(dev)); + if (!saved_engines) { + /* Free saved groups */ + idxd_free_saved_configs(saved_groups, idxd->max_groups); + + return -ENOMEM; + } + for (i =3D 0; i < idxd->max_engines; i++) { + struct idxd_engine *saved_engine __free(kfree) =3D + kzalloc_node(sizeof(*saved_engine), GFP_KERNEL, + dev_to_node(dev)); + if (!saved_engine) { + /* Free saved groups and engines */ + idxd_free_saved_configs(saved_groups, idxd->max_groups); + idxd_free_saved_configs(saved_engines, i); + + return -ENOMEM; + } + + memcpy(saved_engine, idxd->engines[i], sizeof(*saved_engine)); + saved_engines[i] =3D no_free_ptr(saved_engine); + } + + unsigned long *saved_wq_enable_map __free(free_saved_wq_enable_map) =3D + bitmap_zalloc_node(idxd->max_wqs, GFP_KERNEL, + dev_to_node(dev)); + if (!saved_wq_enable_map) { + /* Free saved groups and engines */ + idxd_free_saved_configs(saved_groups, idxd->max_groups); + idxd_free_saved_configs(saved_engines, idxd->max_engines); + + return -ENOMEM; + } + + bitmap_copy(saved_wq_enable_map, idxd->wq_enable_map, idxd->max_wqs); + + struct idxd_wq **saved_wqs __free(kfree) =3D + kcalloc_node(idxd->max_wqs, sizeof(struct idxd_wq *), + GFP_KERNEL, dev_to_node(dev)); + if (!saved_wqs) { + /* Free saved groups and engines */ + idxd_free_saved_configs(saved_groups, idxd->max_groups); + idxd_free_saved_configs(saved_engines, idxd->max_engines); + + return -ENOMEM; + } + + for (i =3D 0; i < idxd->max_wqs; i++) { + struct idxd_wq *saved_wq __free(kfree) =3D + kzalloc_node(sizeof(*saved_wq), GFP_KERNEL, + dev_to_node(dev)); + struct idxd_wq *wq; + + if (!saved_wq) { + /* Free saved groups, engines, and wqs */ + idxd_free_saved_configs(saved_groups, idxd->max_groups); + idxd_free_saved_configs(saved_engines, + idxd->max_engines); + idxd_free_saved_configs(saved_wqs, i); + + return -ENOMEM; + } + + if (!test_bit(i, saved_wq_enable_map)) + continue; + + wq =3D idxd->wqs[i]; + mutex_lock(&wq->wq_lock); + memcpy(saved_wq, wq, sizeof(*saved_wq)); + saved_wqs[i] =3D no_free_ptr(saved_wq); + mutex_unlock(&wq->wq_lock); + } + + /* Save configurations */ + idxd_saved->saved_groups =3D no_free_ptr(saved_groups); + idxd_saved->saved_engines =3D no_free_ptr(saved_engines); + idxd_saved->saved_wq_enable_map =3D no_free_ptr(saved_wq_enable_map); + idxd_saved->saved_wqs =3D no_free_ptr(saved_wqs); + + return 0; +} + +/* + * Restore IDXD device configurations including engines, groups, wqs etc + * that were saved before. + */ +static void idxd_device_config_restore(struct idxd_device *idxd, + struct idxd_saved_states *idxd_saved) +{ + struct idxd_evl *saved_evl =3D &idxd_saved->saved_evl; + int i; + + idxd->rdbuf_limit =3D idxd_saved->saved_idxd.rdbuf_limit; + + if (saved_evl) + idxd->evl->size =3D saved_evl->size; + + for (i =3D 0; i < idxd->max_groups; i++) { + struct idxd_group *saved_group, *group; + + saved_group =3D idxd_saved->saved_groups[i]; + group =3D idxd->groups[i]; + + group->rdbufs_allowed =3D saved_group->rdbufs_allowed; + group->rdbufs_reserved =3D saved_group->rdbufs_reserved; + group->tc_a =3D saved_group->tc_a; + group->tc_b =3D saved_group->tc_b; + group->use_rdbuf_limit =3D saved_group->use_rdbuf_limit; + + kfree(saved_group); + } + kfree(idxd_saved->saved_groups); + + for (i =3D 0; i < idxd->max_engines; i++) { + struct idxd_engine *saved_engine, *engine; + + saved_engine =3D idxd_saved->saved_engines[i]; + engine =3D idxd->engines[i]; + + engine->group =3D saved_engine->group; + + kfree(saved_engine); + } + kfree(idxd_saved->saved_engines); + + bitmap_copy(idxd->wq_enable_map, idxd_saved->saved_wq_enable_map, + idxd->max_wqs); + bitmap_free(idxd_saved->saved_wq_enable_map); + + for (i =3D 0; i < idxd->max_wqs; i++) { + struct idxd_wq *saved_wq, *wq; + size_t len; + + if (!test_bit(i, idxd->wq_enable_map)) + continue; + + saved_wq =3D idxd_saved->saved_wqs[i]; + wq =3D idxd->wqs[i]; + + mutex_lock(&wq->wq_lock); + + wq->group =3D saved_wq->group; + wq->flags =3D saved_wq->flags; + wq->threshold =3D saved_wq->threshold; + wq->size =3D saved_wq->size; + wq->priority =3D saved_wq->priority; + wq->type =3D saved_wq->type; + len =3D strlen(saved_wq->name) + 1; + strscpy(wq->name, saved_wq->name, len); + wq->max_xfer_bytes =3D saved_wq->max_xfer_bytes; + wq->max_batch_size =3D saved_wq->max_batch_size; + wq->enqcmds_retries =3D saved_wq->enqcmds_retries; + wq->descs =3D saved_wq->descs; + wq->idxd_chan =3D saved_wq->idxd_chan; + len =3D strlen(saved_wq->driver_name) + 1; + strscpy(wq->driver_name, saved_wq->driver_name, len); + + mutex_unlock(&wq->wq_lock); + + kfree(saved_wq); + } + + kfree(idxd_saved->saved_wqs); +} + /* * Probe idxd PCI device. * If idxd is not given, need to allocate idxd and set up its data. --=20 2.37.1