/* * Return: 0 on success, -ENOKEY if some KLVs were not updated, -EPROTO if reply was malformed, * negative error code on failure.
*/ staticint pf_push_vf_buf_klvs(struct xe_gt *gt, unsignedint vfid, u32 num_klvs, struct xe_guc_buf buf, u32 num_dwords)
{ int ret;
ret = pf_send_vf_buf_klvs(gt, vfid, buf, num_dwords);
if (ret != num_klvs) { int err = ret < 0 ? ret : ret < num_klvs ? -ENOKEY : -EPROTO; void *klvs = xe_guc_buf_cpu_ptr(buf); struct drm_printer p = xe_gt_info_printer(gt); char name[8];
/* media-GT will never include a GGTT config */
xe_gt_assert(gt, !encode_config_ggtt(cfg + num_dwords, config, true));
/* the GGTT config must be taken from the primary-GT instead */
num_dwords += encode_config_ggtt(cfg + num_dwords, other, true);
}
xe_gt_assert(gt, num_dwords <= max_cfg_dwords);
if (tile->media_gt && !err)
err2 = pf_push_vf_cfg_ggtt(tile->media_gt, vfid, start, size);
return err ?: err2;
}
staticvoid pf_release_ggtt(struct xe_tile *tile, struct xe_ggtt_node *node)
{ if (xe_ggtt_node_allocated(node)) { /* * explicit GGTT PTE assignment to the PF using xe_ggtt_assign() * is redundant, as PTE will be implicitly re-assigned to PF by * the xe_ggtt_clear() called by below xe_ggtt_remove_node().
*/
xe_ggtt_node_remove(node, false);
} else {
xe_ggtt_node_fini(node);
}
}
/** * xe_gt_sriov_pf_config_get_ggtt - Query size of GGTT address space of the VF. * @gt: the &xe_gt * @vfid: the VF identifier * * This function can only be called on PF. * * Return: size of the VF's assigned (or PF's spare) GGTT address space.
*/
u64 xe_gt_sriov_pf_config_get_ggtt(struct xe_gt *gt, unsignedint vfid)
{
u64 size;
/* the actual value may have changed during provisioning */
string_get_size(actual, 1, STRING_UNITS_2, size, sizeof(size));
xe_gt_sriov_info(gt, "%s provisioned with %llu (%s) %s\n",
name, actual, size, what); return 0;
}
/** * xe_gt_sriov_pf_config_set_ggtt - Provision VF with GGTT space. * @gt: the &xe_gt (can't be media) * @vfid: the VF identifier * @size: requested GGTT size * * If &vfid represents PF, then function will change PF's spare GGTT config. * * This function can only be called on PF. * * Return: 0 on success or a negative error code on failure.
*/ int xe_gt_sriov_pf_config_set_ggtt(struct xe_gt *gt, unsignedint vfid, u64 size)
{ int err;
if (unlikely(err)) {
xe_gt_sriov_notice(gt, "Failed to bulk provision VF%u..VF%u with %s\n",
first, first + num_vfs - 1, what); if (last > first)
pf_config_bulk_set_u64_done(gt, first, last - first, value,
get, what, last, 0); return pf_config_set_u64_done(gt, last, value, get(gt, last), what, err);
}
/* pick actual value from first VF - bulk provisioning shall be equal across all VFs */
value = get(gt, first);
string_get_size(value, 1, STRING_UNITS_2, size, sizeof(size));
xe_gt_sriov_info(gt, "VF%u..VF%u provisioned with %llu (%s) %s\n",
first, first + num_vfs - 1, value, size, what); return 0;
}
/** * xe_gt_sriov_pf_config_bulk_set_ggtt - Provision many VFs with GGTT. * @gt: the &xe_gt (can't be media) * @vfid: starting VF identifier (can't be 0) * @num_vfs: number of VFs to provision * @size: requested GGTT size * * This function can only be called on PF. * * Return: 0 on success or a negative error code on failure.
*/ int xe_gt_sriov_pf_config_bulk_set_ggtt(struct xe_gt *gt, unsignedint vfid, unsignedint num_vfs, u64 size)
{ unsignedint n; int err = 0;
/* * To simplify the logic we only look at single largest GGTT region * as that will be always the best fit for 1 VF case, and most likely * will also nicely cover other cases where VFs are provisioned on the * fresh and idle PF driver, without any stale GGTT allocations spread * in the middle of the full GGTT range.
*/
/** * xe_gt_sriov_pf_config_set_fair_ggtt - Provision many VFs with fair GGTT. * @gt: the &xe_gt (can't be media) * @vfid: starting VF identifier (can't be 0) * @num_vfs: number of VFs to provision * * This function can only be called on PF. * * Return: 0 on success or a negative error code on failure.
*/ int xe_gt_sriov_pf_config_set_fair_ggtt(struct xe_gt *gt, unsignedint vfid, unsignedint num_vfs)
{
u64 fair;
/** * xe_gt_sriov_pf_config_get_ctxs - Get VF's GuC contexts IDs quota. * @gt: the &xe_gt * @vfid: the VF identifier * * This function can only be called on PF. * If &vfid represents a PF then number of PF's spare GuC context IDs is returned. * * Return: VF's quota (or PF's spare).
*/
u32 xe_gt_sriov_pf_config_get_ctxs(struct xe_gt *gt, unsignedint vfid)
{
u32 num_ctxs;
if (unlikely(err)) {
xe_gt_sriov_notice(gt, "Failed to provision %s with %u%s %s (%pe)\n",
name, value, unit(value), what, ERR_PTR(err));
xe_gt_sriov_info(gt, "%s provisioning remains at %u%s %s\n",
name, actual, unit(actual), what); return err;
}
/* the actual value may have changed during provisioning */
xe_gt_sriov_info(gt, "%s provisioned with %u%s %s\n",
name, actual, unit(actual), what); return 0;
}
/** * xe_gt_sriov_pf_config_set_ctxs - Configure GuC contexts IDs quota for the VF. * @gt: the &xe_gt * @vfid: the VF identifier * @num_ctxs: requested number of GuC contexts IDs (0 to release) * * This function can only be called on PF. * * Return: 0 on success or a negative error code on failure.
*/ int xe_gt_sriov_pf_config_set_ctxs(struct xe_gt *gt, unsignedint vfid, u32 num_ctxs)
{ int err;
staticint pf_config_bulk_set_u32_done(struct xe_gt *gt, unsignedint first, unsignedintnum_vfs,
u32 value, u32 (*get)(struct xe_gt*, unsignedint), constchar *what, constchar *(*unit)(u32), unsignedint last, int err)
{
xe_gt_assert(gt, first);
xe_gt_assert(gt, num_vfs);
xe_gt_assert(gt, first <= last);
if (num_vfs == 1) return pf_config_set_u32_done(gt, first, value, get(gt, first), what, unit, err);
if (unlikely(err)) {
xe_gt_sriov_notice(gt, "Failed to bulk provision VF%u..VF%u with %s\n",
first, first + num_vfs - 1, what); if (last > first)
pf_config_bulk_set_u32_done(gt, first, last - first, value,
get, what, unit, last, 0); return pf_config_set_u32_done(gt, last, value, get(gt, last), what, unit, err);
}
/* pick actual value from first VF - bulk provisioning shall be equal across all VFs */
value = get(gt, first);
xe_gt_sriov_info(gt, "VF%u..VF%u provisioned with %u%s %s\n",
first, first + num_vfs - 1, value, unit(value), what); return 0;
}
/** * xe_gt_sriov_pf_config_bulk_set_ctxs - Provision many VFs with GuC context IDs. * @gt: the &xe_gt * @vfid: starting VF identifier * @num_vfs: number of VFs to provision * @num_ctxs: requested number of GuC contexts IDs (0 to release) * * This function can only be called on PF. * * Return: 0 on success or a negative error code on failure.
*/ int xe_gt_sriov_pf_config_bulk_set_ctxs(struct xe_gt *gt, unsignedint vfid, unsignedint num_vfs, u32 num_ctxs)
{ unsignedint n; int err = 0;
xe_gt_assert(gt, vfid);
if (!num_vfs) return 0;
mutex_lock(xe_gt_sriov_pf_master_mutex(gt)); for (n = vfid; n < vfid + num_vfs; n++) {
err = pf_provision_vf_ctxs(gt, n, num_ctxs); if (err) break;
}
mutex_unlock(xe_gt_sriov_pf_master_mutex(gt));
for (; fair; --fair) {
ret = xe_guc_id_mgr_reserve(idm, fair * num_vfs, spare); if (ret < 0) continue;
xe_guc_id_mgr_release(idm, ret, fair * num_vfs); break;
}
xe_gt_sriov_dbg_verbose(gt, "contexts fair(%u x %u)\n", num_vfs, fair); return fair;
}
/** * xe_gt_sriov_pf_config_set_fair_ctxs - Provision many VFs with fair GuC context IDs. * @gt: the &xe_gt * @vfid: starting VF identifier (can't be 0) * @num_vfs: number of VFs to provision (can't be 0) * * This function can only be called on PF. * * Return: 0 on success or a negative error code on failure.
*/ int xe_gt_sriov_pf_config_set_fair_ctxs(struct xe_gt *gt, unsignedint vfid, unsignedint num_vfs)
{
u32 fair;
/** * xe_gt_sriov_pf_config_get_dbs - Get VF's GuC doorbells IDs quota. * @gt: the &xe_gt * @vfid: the VF identifier * * This function can only be called on PF. * If &vfid represents a PF then number of PF's spare GuC doorbells IDs is returned. * * Return: VF's quota (or PF's spare).
*/
u32 xe_gt_sriov_pf_config_get_dbs(struct xe_gt *gt, unsignedint vfid)
{
u32 num_dbs;
/** * xe_gt_sriov_pf_config_set_dbs - Configure GuC doorbells IDs quota for the VF. * @gt: the &xe_gt * @vfid: the VF identifier * @num_dbs: requested number of GuC doorbells IDs (0 to release) * * This function can only be called on PF. * * Return: 0 on success or a negative error code on failure.
*/ int xe_gt_sriov_pf_config_set_dbs(struct xe_gt *gt, unsignedint vfid, u32 num_dbs)
{ int err;
/** * xe_gt_sriov_pf_config_bulk_set_dbs - Provision many VFs with GuC context IDs. * @gt: the &xe_gt * @vfid: starting VF identifier (can't be 0) * @num_vfs: number of VFs to provision * @num_dbs: requested number of GuC doorbell IDs (0 to release) * * This function can only be called on PF. * * Return: 0 on success or a negative error code on failure.
*/ int xe_gt_sriov_pf_config_bulk_set_dbs(struct xe_gt *gt, unsignedint vfid, unsignedint num_vfs, u32 num_dbs)
{ unsignedint n; int err = 0;
xe_gt_assert(gt, vfid);
if (!num_vfs) return 0;
mutex_lock(xe_gt_sriov_pf_master_mutex(gt)); for (n = vfid; n < vfid + num_vfs; n++) {
err = pf_provision_vf_dbs(gt, n, num_dbs); if (err) break;
}
mutex_unlock(xe_gt_sriov_pf_master_mutex(gt));
for (; fair; --fair) {
ret = xe_guc_db_mgr_reserve_range(dbm, fair * num_vfs, spare); if (ret < 0) continue;
xe_guc_db_mgr_release_range(dbm, ret, fair * num_vfs); break;
}
xe_gt_sriov_dbg_verbose(gt, "doorbells fair(%u x %u)\n", num_vfs, fair); return fair;
}
/** * xe_gt_sriov_pf_config_set_fair_dbs - Provision many VFs with fair GuC doorbell IDs. * @gt: the &xe_gt * @vfid: starting VF identifier (can't be 0) * @num_vfs: number of VFs to provision (can't be 0) * * This function can only be called on PF. * * Return: 0 on success or a negative error code on failure.
*/ int xe_gt_sriov_pf_config_set_fair_dbs(struct xe_gt *gt, unsignedint vfid, unsignedint num_vfs)
{
u32 fair;
/** * xe_gt_sriov_pf_config_get_lmem - Get VF's LMEM quota. * @gt: the &xe_gt * @vfid: the VF identifier * * This function can only be called on PF. * * Return: VF's (or PF's spare) LMEM quota.
*/
u64 xe_gt_sriov_pf_config_get_lmem(struct xe_gt *gt, unsignedint vfid)
{
u64 size;
/** * xe_gt_sriov_pf_config_set_lmem - Provision VF with LMEM. * @gt: the &xe_gt (can't be media) * @vfid: the VF identifier * @size: requested LMEM size * * This function can only be called on PF.
*/ int xe_gt_sriov_pf_config_set_lmem(struct xe_gt *gt, unsignedint vfid, u64 size)
{ int err;
/** * xe_gt_sriov_pf_config_bulk_set_lmem - Provision many VFs with LMEM. * @gt: the &xe_gt (can't be media) * @vfid: starting VF identifier (can't be 0) * @num_vfs: number of VFs to provision * @size: requested LMEM size * * This function can only be called on PF. * * Return: 0 on success or a negative error code on failure.
*/ int xe_gt_sriov_pf_config_bulk_set_lmem(struct xe_gt *gt, unsignedint vfid, unsignedint num_vfs, u64 size)
{ unsignedint n; int err = 0;
/** * xe_gt_sriov_pf_config_set_fair_lmem - Provision many VFs with fair LMEM. * @gt: the &xe_gt (can't be media) * @vfid: starting VF identifier (can't be 0) * @num_vfs: number of VFs to provision (can't be 0) * * This function can only be called on PF. * * Return: 0 on success or a negative error code on failure.
*/ int xe_gt_sriov_pf_config_set_fair_lmem(struct xe_gt *gt, unsignedint vfid, unsignedint num_vfs)
{
u64 fair;
/** * xe_gt_sriov_pf_config_set_fair - Provision many VFs with fair resources. * @gt: the &xe_gt * @vfid: starting VF identifier (can't be 0) * @num_vfs: number of VFs to provision (can't be 0) * * This function can only be called on PF. * * Return: 0 on success or a negative error code on failure.
*/ int xe_gt_sriov_pf_config_set_fair(struct xe_gt *gt, unsignedint vfid, unsignedint num_vfs)
{ int result = 0; int err;
if (xe_gt_is_main_type(gt)) {
err = xe_gt_sriov_pf_config_set_fair_ggtt(gt, vfid, num_vfs);
result = result ?: err;
err = xe_gt_sriov_pf_config_set_fair_lmem(gt, vfid, num_vfs);
result = result ?: err;
}
err = xe_gt_sriov_pf_config_set_fair_ctxs(gt, vfid, num_vfs);
result = result ?: err;
err = xe_gt_sriov_pf_config_set_fair_dbs(gt, vfid, num_vfs);
result = result ?: err;
/** * xe_gt_sriov_pf_config_set_exec_quantum - Configure execution quantum for the VF. * @gt: the &xe_gt * @vfid: the VF identifier * @exec_quantum: requested execution quantum in milliseconds (0 is infinity) * * This function can only be called on PF. * * Return: 0 on success or a negative error code on failure.
*/ int xe_gt_sriov_pf_config_set_exec_quantum(struct xe_gt *gt, unsignedint vfid,
u32 exec_quantum)
{ int err;
/** * xe_gt_sriov_pf_config_get_exec_quantum - Get VF's execution quantum. * @gt: the &xe_gt * @vfid: the VF identifier * * This function can only be called on PF. * * Return: VF's (or PF's) execution quantum in milliseconds.
*/
u32 xe_gt_sriov_pf_config_get_exec_quantum(struct xe_gt *gt, unsignedint vfid)
{
u32 exec_quantum;
/** * xe_gt_sriov_pf_config_set_preempt_timeout - Configure preemption timeout for the VF. * @gt: the &xe_gt * @vfid: the VF identifier * @preempt_timeout: requested preemption timeout in microseconds (0 is infinity) * * This function can only be called on PF. * * Return: 0 on success or a negative error code on failure.
*/ int xe_gt_sriov_pf_config_set_preempt_timeout(struct xe_gt *gt, unsignedint vfid,
u32 preempt_timeout)
{ int err;
/** * xe_gt_sriov_pf_config_get_preempt_timeout - Get VF's preemption timeout. * @gt: the &xe_gt * @vfid: the VF identifier * * This function can only be called on PF. * * Return: VF's (or PF's) preemption timeout in microseconds.
*/
u32 xe_gt_sriov_pf_config_get_preempt_timeout(struct xe_gt *gt, unsignedint vfid)
{
u32 preempt_timeout;
/** * xe_gt_sriov_pf_config_set_sched_priority() - Configure scheduling priority. * @gt: the &xe_gt * @vfid: the VF identifier * @priority: requested scheduling priority * * This function can only be called on PF. * * Return: 0 on success or a negative error code on failure.
*/ int xe_gt_sriov_pf_config_set_sched_priority(struct xe_gt *gt, unsignedint vfid, u32 priority)
{ int err;
/** * xe_gt_sriov_pf_config_get_sched_priority - Get VF's scheduling priority. * @gt: the &xe_gt * @vfid: the VF identifier * * This function can only be called on PF. * * Return: VF's (or PF's) scheduling priority.
*/
u32 xe_gt_sriov_pf_config_get_sched_priority(struct xe_gt *gt, unsignedint vfid)
{
u32 priority;
/** * xe_gt_sriov_pf_config_set_threshold - Configure threshold for the VF. * @gt: the &xe_gt * @vfid: the VF identifier * @index: the threshold index * @value: requested value (0 means disabled) * * This function can only be called on PF. * * Return: 0 on success or a negative error code on failure.
*/ int xe_gt_sriov_pf_config_set_threshold(struct xe_gt *gt, unsignedint vfid, enum xe_guc_klv_threshold_index index, u32 value)
{
u32 key = xe_guc_klv_threshold_index_to_key(index); constchar *name = xe_guc_klv_key_to_string(key); int err;
/** * xe_gt_sriov_pf_config_get_threshold - Get VF's threshold. * @gt: the &xe_gt * @vfid: the VF identifier * @index: the threshold index * * This function can only be called on PF. * * Return: value of VF's (or PF's) threshold.
*/
u32 xe_gt_sriov_pf_config_get_threshold(struct xe_gt *gt, unsignedint vfid, enum xe_guc_klv_threshold_index index)
{
u32 value;
mutex_lock(xe_gt_sriov_pf_master_mutex(gt));
value = pf_get_threshold(gt, vfid, index);
mutex_unlock(xe_gt_sriov_pf_master_mutex(gt));
if (xe_gt_is_main_type(gt)) {
pf_release_vf_config_ggtt(gt, config); if (IS_DGFX(xe)) {
pf_release_vf_config_lmem(gt, config); if (xe_device_has_lmtt(xe))
pf_update_vf_lmtt(xe, vfid);
}
}
pf_release_config_ctxs(gt, config);
pf_release_config_dbs(gt, config);
pf_reset_config_sched(gt, config);
pf_reset_config_thresholds(gt, config);
}
/** * xe_gt_sriov_pf_config_release - Release and reset VF configuration. * @gt: the &xe_gt * @vfid: the VF identifier (can't be PF) * @force: force configuration release * * This function can only be called on PF. * * Return: 0 on success or a negative error code on failure.
*/ int xe_gt_sriov_pf_config_release(struct xe_gt *gt, unsignedint vfid, bool force)
{ int err;
if (unlikely(err)) {
xe_gt_sriov_notice(gt, "VF%u unprovisioning failed with error (%pe)%s\n",
vfid, ERR_PTR(err),
force ? " but all resources were released anyway!" : "");
}
/* * Only GGTT and LMEM requires to be cleared by the PF. * GuC doorbell IDs and context IDs do not need any clearing.
*/ if (xe_gt_is_main_type(gt)) {
pf_sanitize_ggtt(config->ggtt_region, vfid); if (IS_DGFX(xe))
err = pf_sanitize_lmem(tile, config->lmem_obj, timeout);
}
return err;
}
/** * xe_gt_sriov_pf_config_sanitize() - Sanitize VF's resources. * @gt: the &xe_gt * @vfid: the VF identifier (can't be PF) * @timeout: maximum timeout to wait for completion in jiffies * * This function can only be called on PF. * * Return: 0 on success or a negative error code on failure.
*/ int xe_gt_sriov_pf_config_sanitize(struct xe_gt *gt, unsignedint vfid, long timeout)
{ int err;
/** * xe_gt_sriov_pf_config_push - Reprovision VF's configuration. * @gt: the &xe_gt * @vfid: the VF identifier (can't be PF) * @refresh: explicit refresh * * This function can only be called on PF. * * Return: 0 on success or a negative error code on failure.
*/ int xe_gt_sriov_pf_config_push(struct xe_gt *gt, unsignedint vfid, bool refresh)
{ int err = 0;
/** * xe_gt_sriov_pf_config_is_empty - Check VF's configuration. * @gt: the &xe_gt * @vfid: the VF identifier (can't be PF) * * This function can only be called on PF. * * Return: true if VF mandatory configuration (GGTT, LMEM, ...) is empty.
*/ bool xe_gt_sriov_pf_config_is_empty(struct xe_gt *gt, unsignedint vfid)
{ bool empty;
/** * xe_gt_sriov_pf_config_save - Save a VF provisioning config as binary blob. * @gt: the &xe_gt * @vfid: the VF identifier (can't be PF) * @buf: the buffer to save a config to (or NULL if query the buf size) * @size: the size of the buffer (or 0 if query the buf size) * * This function can only be called on PF. * * Return: minimum size of the buffer or the number of bytes saved, * or a negative error code on failure.
*/
ssize_t xe_gt_sriov_pf_config_save(struct xe_gt *gt, unsignedint vfid, void *buf, size_t size)
{ struct xe_gt_sriov_config *config;
ssize_t ret;
if (err) {
xe_gt_sriov_dbg(gt, "restore failed on key %#x (%pe)\n", key, ERR_PTR(err)); return err;
}
klvs += len;
num_dwords -= len;
}
return pf_validate_vf_config(gt, vfid);
}
/** * xe_gt_sriov_pf_config_restore - Restore a VF provisioning config from binary blob. * @gt: the &xe_gt * @vfid: the VF identifier (can't be PF) * @buf: the buffer with config data * @size: the size of the config data * * This function can only be called on PF. * * Return: 0 on success or a negative error code on failure.
*/ int xe_gt_sriov_pf_config_restore(struct xe_gt *gt, unsignedint vfid, constvoid *buf, size_t size)
{ int err;
/* * We want PF to be allowed to use all of context ID, doorbells IDs * and whole usable GGTT area. While we can store ctxs/dbs numbers * directly in the config structure, can't do the same with the GGTT * configuration, so let it be prepared on demand while pushing KLVs.
*/
config->num_ctxs = GUC_ID_MAX;
config->num_dbs = GUC_NUM_DOORBELLS;
}
staticint pf_push_self_config(struct xe_gt *gt)
{ int err;
err = pf_push_full_vf_config(gt, PFID); if (err) {
xe_gt_sriov_err(gt, "Failed to push self configuration (%pe)\n",
ERR_PTR(err)); return err;
}
mutex_lock(xe_gt_sriov_pf_master_mutex(gt)); for (n = 1; n <= total_vfs; n++)
pf_release_vf_config(gt, n);
mutex_unlock(xe_gt_sriov_pf_master_mutex(gt));
}
/** * xe_gt_sriov_pf_config_init - Initialize SR-IOV configuration data. * @gt: the &xe_gt * * This function can only be called on PF. * * Return: 0 on success or a negative error code on failure.
*/ int xe_gt_sriov_pf_config_init(struct xe_gt *gt)
{ struct xe_device *xe = gt_to_xe(gt); int err;
/** * xe_gt_sriov_pf_config_restart - Restart SR-IOV configurations after a GT reset. * @gt: the &xe_gt * * Any prior configurations pushed to GuC are lost when the GT is reset. * Push again all non-empty VF configurations to the GuC. * * This function can only be called on PF.
*/ void xe_gt_sriov_pf_config_restart(struct xe_gt *gt)
{ unsignedint n, total_vfs = xe_sriov_pf_get_totalvfs(gt_to_xe(gt)); unsignedint fail = 0, skip = 0;
--> --------------------
--> maximum size reached
--> --------------------
Messung V0.5
¤ Dauer der Verarbeitung: 0.35 Sekunden
(vorverarbeitet)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.