[PATCH 04/95] drm/amdgpu: Add sysfs API for UALink physical pod setup
Alex Deucher <[email protected]>
| Newsgroups | org.freedesktop.lists.amd-gfx |
|---|---|
| Message-ID | <[email protected]> |
From: Felix Kuehling <[email protected]> <device>/ualink/setup: Directory for staging physical pod setup attributes. Write "true" to commit to apply settings Signed-off-by: Felix Kuehling <[email protected]> Reviewed-by: Mukul Joshi <[email protected]> Signed-off-by: Alex Deucher <[email protected]> --- drivers/gpu/drm/amd/amdgpu/amdgpu_ualink.c | 201 +++++++++++++++++++++ drivers/gpu/drm/amd/amdgpu/amdgpu_ualink.h | 11 ++ 2 files changed, 212 insertions(+) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ualink.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ualink.c index 374242372eab7..6c9905b15e93d 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ualink.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ualink.c @@ -46,6 +46,19 @@ static ssize_t ualink_##prefix##_##name##_show(struct kobject *kobj, \ \ return sysfs_emit(buf, format"\n", info->field); \ } +#define UALINK_VALUE_STORE(prefix, name, field, type, base) \ +static ssize_t ualink_##prefix##_##name##_store(struct kobject *kobj, \ + struct kobj_attribute *attr,\ + const char *buf, size_t count)\ +{ \ + struct amdgpu_ualink_##prefix *info = to_ualink_##prefix(kobj); \ + int r; \ + \ + r = kstrto##type(buf, base, &info->field); \ + if (r < 0) \ + return r; \ + return count; \ +} static ssize_t show_idbits(unsigned long *bits, unsigned int nbits, char *buf) { @@ -89,6 +102,65 @@ static ssize_t ualink_##prefix##_##name##_show(struct kobject *kobj, \ return show_idarray(info->field, info->size, buf); \ } +static ssize_t store_idarray(u32 *array, u32 *size, u32 max_id, u32 max_size, + const char *buf, size_t count) +{ + char *dup_buf, *str, *tok; + unsigned int index = 0; + ssize_t r; + u32 id; + + *size = 0; + if (!count) + return 0; + + dup_buf = kstrndup(buf, count, GFP_KERNEL); + if (unlikely(!dup_buf)) + return -ENOMEM; + str = dup_buf; + do { + str += strspn(str, " "); + tok = strsep(&str, ", "); + r = kstrtou32(tok, 10, &id); + if (r < 0) + goto err; + if (index >= max_size) { + r = -ENOSPC; + goto err; + } + if (id >= max_id) { + r = -ERANGE; + goto err; + } + array[index++] = id; + } while (str); + kfree(dup_buf); + + *size = index; + return count; + +err: + kfree(dup_buf); + return r; +} +#define UALINK_IDARRAY_STORE(prefix, name, field, size, max_id) \ +static ssize_t ualink_##prefix##_##name##_store(struct kobject *kobj, \ + struct kobj_attribute *attr,\ + const char *buf, size_t count)\ +{ \ + struct amdgpu_ualink_##prefix *info = to_ualink_##prefix(kobj); \ + u32 new_array[ARRAY_SIZE(info->field)]; \ + u32 new_size; \ + ssize_t r = store_idarray(new_array, &new_size, max_id, \ + ARRAY_SIZE(new_array), buf, count); \ + \ + if (r >= 0) { \ + memcpy(info->field, new_array, sizeof(new_array)); \ + info->size = new_size; \ + } \ + return r; \ +} + #define UALINK_UUID_SHOW(prefix, name, field) \ static ssize_t ualink_##prefix##_##name##_show(struct kobject *kobj, \ struct kobj_attribute *attr,\ @@ -98,6 +170,17 @@ static ssize_t ualink_##prefix##_##name##_show(struct kobject *kobj, \ \ return sysfs_emit(buf, "%pU\n", &info->field); \ } +#define UALINK_UUID_STORE(prefix, name, field) \ +static ssize_t ualink_##prefix##_##name##_store(struct kobject *kobj, \ + struct kobj_attribute *attr,\ + const char *buf, size_t count)\ +{ \ + struct amdgpu_ualink_##prefix *info = to_ualink_##prefix(kobj); \ + int r; \ + \ + r = uuid_parse(buf, &info->field); \ + return r ? r : count; \ +} static ssize_t show_enum(u32 x, const char * const values[], unsigned int n, char *buf) @@ -180,8 +263,99 @@ static const struct kobj_type ualink_info_ktype = { .sysfs_ops = &kobj_sysfs_ops }; +UALINK_VALUE_SHOW(ppod_setup, accel_id, ppod.accel_id, "%u"); +UALINK_VALUE_SHOW(ppod_setup, bandwidth, ppod.bandwidth, "%u"); +UALINK_VALUE_SHOW(ppod_setup, latency, ppod.latency, "%u"); +UALINK_UUID_SHOW(ppod_setup, ppod_id, ppod.id); +UALINK_VALUE_SHOW(ppod_setup, ppod_size, ppod.size, "%u"); +UALINK_IDARRAY_SHOW(ppod_setup, local_accels, local_accels, n_local_accels); + +UALINK_VALUE_STORE(ppod_setup, accel_id, ppod.accel_id, u32, 10); +UALINK_VALUE_STORE(ppod_setup, bandwidth, ppod.bandwidth, u32, 10); +UALINK_VALUE_STORE(ppod_setup, latency, ppod.latency, u32, 10); +UALINK_UUID_STORE(ppod_setup, ppod_id, ppod.id); +UALINK_VALUE_STORE(ppod_setup, ppod_size, ppod.size, u32, 10); +UALINK_IDARRAY_STORE(ppod_setup, local_accels, local_accels, n_local_accels, + AMDGPU_UALINK_ACCEL_MAX); + +static enum amdgpu_ualink_accel_state +check_ppod_state(struct amdgpu_device *adev, + const struct amdgpu_ualink_ppod_setup *setup) +{ + if (setup->ppod.size <= 0 || setup->ppod.size > AMDGPU_UALINK_ACCEL_MAX) { + dev_dbg(adev->dev, "pPod size %u out of range [1..%u]\n", + setup->ppod.size, AMDGPU_UALINK_ACCEL_MAX); + return AMDGPU_UALINK_ACCEL_STATE_UNCONFIGURED; + } + if (setup->ppod.accel_id >= setup->ppod.size) { + dev_dbg(adev->dev, "Accelerator ID %u greater or equal pPod size %u\n", + setup->ppod.accel_id, setup->ppod.size); + return AMDGPU_UALINK_ACCEL_STATE_UNCONFIGURED; + } + return AMDGPU_UALINK_ACCEL_STATE_CONFIGURED; +} + +static ssize_t ualink_ppod_setup_commit_store(struct kobject *kobj, + struct kobj_attribute *attr, + const char *buf, size_t count) +{ + struct amdgpu_ualink_ppod_setup *setup = to_ualink_ppod_setup(kobj); + struct amdgpu_ualink_info *info = to_ualink_info(kobj->parent); + struct device *dev = kobj_to_dev(info->kobj.parent); + struct drm_device *ddev = dev_get_drvdata(dev); + struct amdgpu_device *adev = drm_to_adev(ddev); + + if (!sysfs_streq(buf, "true")) + return -EINVAL; + + /* TODO: Send configuration to ASP */ + + info->ppod = setup->ppod; + info->accel_state = check_ppod_state(adev, setup); + + /* TODO: If accel_state was ACTIVE, reset all connections */ + + return count; +} + +#define UALINK_PPOD_SETUP_ATTR(name) __ATTR(name, 0600, \ + ualink_ppod_setup_##name##_show, \ + ualink_ppod_setup_##name##_store) +static struct kobj_attribute ualink_ppod_setup_accel_id = UALINK_PPOD_SETUP_ATTR(accel_id); +static struct kobj_attribute ualink_ppod_setup_bandwidth = UALINK_PPOD_SETUP_ATTR(bandwidth); +static struct kobj_attribute ualink_ppod_setup_latency = UALINK_PPOD_SETUP_ATTR(latency); +static struct kobj_attribute ualink_ppod_setup_ppod_id = UALINK_PPOD_SETUP_ATTR(ppod_id); +static struct kobj_attribute ualink_ppod_setup_ppod_size = UALINK_PPOD_SETUP_ATTR(ppod_size); +static struct kobj_attribute ualink_ppod_setup_local_accels = UALINK_PPOD_SETUP_ATTR(local_accels); +static struct kobj_attribute ualink_ppod_setup_commit = __ATTR(commit, 0200, NULL, + ualink_ppod_setup_commit_store); + +static const struct attribute *ualink_ppod_setup_attrs[] = { + &ualink_ppod_setup_accel_id.attr, + &ualink_ppod_setup_bandwidth.attr, + &ualink_ppod_setup_latency.attr, + &ualink_ppod_setup_ppod_id.attr, + &ualink_ppod_setup_ppod_size.attr, + &ualink_ppod_setup_local_accels.attr, + &ualink_ppod_setup_commit.attr, + NULL +}; + +static void ualink_ppod_setup_release(struct kobject *kobj) +{ + struct amdgpu_ualink_ppod_setup *setup = to_ualink_ppod_setup(kobj); + + kfree(setup); +} + +static const struct kobj_type ualink_ppod_setup_ktype = { + .release = ualink_ppod_setup_release, + .sysfs_ops = &kobj_sysfs_ops +}; + int amdgpu_ualink_sysfs_init(struct amdgpu_device *adev) { + struct amdgpu_ualink_ppod_setup *ppod_setup = NULL; struct amdgpu_ualink_info *info = NULL; int r; @@ -203,10 +377,30 @@ int amdgpu_ualink_sysfs_init(struct amdgpu_device *adev) if (r) goto err_del_info; + ppod_setup = kzalloc(sizeof(*ppod_setup), GFP_KERNEL); + if (!ppod_setup) { + r = -ENOMEM; + goto err_remove_info_files; + } + r = kobject_init_and_add(&ppod_setup->kobj, &ualink_ppod_setup_ktype, + &info->kobj, "setup"); + if (r) + goto err_put_ppod_setup; + r = sysfs_create_files(&ppod_setup->kobj, ualink_ppod_setup_attrs); + if (r) + goto err_del_ppod_setup; + + adev->ualink.setup = ppod_setup; adev->ualink.info = info; return r; +err_del_ppod_setup: + kobject_del(&ppod_setup->kobj); +err_put_ppod_setup: + kobject_put(&ppod_setup->kobj); +err_remove_info_files: + sysfs_remove_files(&info->kobj, ualink_info_attrs); err_del_info: kobject_del(&info->kobj); err_put_info: @@ -216,6 +410,13 @@ int amdgpu_ualink_sysfs_init(struct amdgpu_device *adev) void amdgpu_ualink_sysfs_fini(struct amdgpu_device *adev) { + if (adev->ualink.setup) { + sysfs_remove_files(&adev->ualink.setup->kobj, + ualink_ppod_setup_attrs); + kobject_del(&adev->ualink.setup->kobj); + kobject_put(&adev->ualink.setup->kobj); + adev->ualink.setup = NULL; + } if (adev->ualink.info) { sysfs_remove_files(&adev->ualink.info->kobj, ualink_info_attrs); diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ualink.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_ualink.h index 390fb5653aaf5..ea52dcd44d088 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ualink.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ualink.h @@ -83,8 +83,19 @@ struct amdgpu_ualink_info { }; #define to_ualink_info(ko) container_of(ko, struct amdgpu_ualink_info, kobj) +/* UALink physical pod setup */ +struct amdgpu_ualink_ppod_setup { + struct kobject kobj; + struct amdgpu_ualink_ppod_info ppod; + /* Local accelerator array indexed by socket ID */ + u32 n_local_accels; + u32 local_accels[AMDGPU_UALINK_LOCAL_ACCELS_MAX]; +}; +#define to_ualink_ppod_setup(ko) container_of(ko, struct amdgpu_ualink_ppod_setup, kobj) + struct amdgpu_ualink_mgr { struct amdgpu_ualink_info *info; + struct amdgpu_ualink_ppod_setup *setup; }; int amdgpu_ualink_sysfs_init(struct amdgpu_device *adev); -- 2.55.0