Commit 4b4bd048 authored by Kees Cook's avatar Kees Cook Committed by Alex Deucher

drm/amdgpu/pm: Remove VLA usage

In the quest to remove all stack VLA usage from the kernel[1], this
uses the maximum sane buffer size and removes copy/paste code.

[1] https://lkml.kernel.org/r/CA+55aFzCG-zNmZwX4A2FQpadafLfEzK6CC=qPXydAacU1RqZWA@mail.gmail.comReviewed-by: default avatarRex Zhu <rezhu@amd.com>
Signed-off-by: default avatarKees Cook <keescook@chromium.org>
Signed-off-by: default avatarAlex Deucher <alexander.deucher@amd.com>
parent 7eb80427
...@@ -606,40 +606,59 @@ static ssize_t amdgpu_get_pp_dpm_sclk(struct device *dev, ...@@ -606,40 +606,59 @@ static ssize_t amdgpu_get_pp_dpm_sclk(struct device *dev,
return snprintf(buf, PAGE_SIZE, "\n"); return snprintf(buf, PAGE_SIZE, "\n");
} }
static ssize_t amdgpu_set_pp_dpm_sclk(struct device *dev, /*
struct device_attribute *attr, * Worst case: 32 bits individually specified, in octal at 12 characters
const char *buf, * per line (+1 for \n).
size_t count) */
#define AMDGPU_MASK_BUF_MAX (32 * 13)
static ssize_t amdgpu_read_mask(const char *buf, size_t count, uint32_t *mask)
{ {
struct drm_device *ddev = dev_get_drvdata(dev);
struct amdgpu_device *adev = ddev->dev_private;
int ret; int ret;
long level; long level;
uint32_t mask = 0;
char *sub_str = NULL; char *sub_str = NULL;
char *tmp; char *tmp;
char buf_cpy[count]; char buf_cpy[AMDGPU_MASK_BUF_MAX + 1];
const char delimiter[3] = {' ', '\n', '\0'}; const char delimiter[3] = {' ', '\n', '\0'};
size_t bytes;
memcpy(buf_cpy, buf, count+1); *mask = 0;
bytes = min(count, sizeof(buf_cpy) - 1);
memcpy(buf_cpy, buf, bytes);
buf_cpy[bytes] = '\0';
tmp = buf_cpy; tmp = buf_cpy;
while (tmp[0]) { while (tmp[0]) {
sub_str = strsep(&tmp, delimiter); sub_str = strsep(&tmp, delimiter);
if (strlen(sub_str)) { if (strlen(sub_str)) {
ret = kstrtol(sub_str, 0, &level); ret = kstrtol(sub_str, 0, &level);
if (ret)
if (ret) { return -EINVAL;
count = -EINVAL; *mask |= 1 << level;
goto fail;
}
mask |= 1 << level;
} else } else
break; break;
} }
return 0;
}
static ssize_t amdgpu_set_pp_dpm_sclk(struct device *dev,
struct device_attribute *attr,
const char *buf,
size_t count)
{
struct drm_device *ddev = dev_get_drvdata(dev);
struct amdgpu_device *adev = ddev->dev_private;
int ret;
uint32_t mask = 0;
ret = amdgpu_read_mask(buf, count, &mask);
if (ret)
return ret;
if (adev->powerplay.pp_funcs->force_clock_level) if (adev->powerplay.pp_funcs->force_clock_level)
amdgpu_dpm_force_clock_level(adev, PP_SCLK, mask); amdgpu_dpm_force_clock_level(adev, PP_SCLK, mask);
fail:
return count; return count;
} }
...@@ -664,32 +683,15 @@ static ssize_t amdgpu_set_pp_dpm_mclk(struct device *dev, ...@@ -664,32 +683,15 @@ static ssize_t amdgpu_set_pp_dpm_mclk(struct device *dev,
struct drm_device *ddev = dev_get_drvdata(dev); struct drm_device *ddev = dev_get_drvdata(dev);
struct amdgpu_device *adev = ddev->dev_private; struct amdgpu_device *adev = ddev->dev_private;
int ret; int ret;
long level;
uint32_t mask = 0; uint32_t mask = 0;
char *sub_str = NULL;
char *tmp;
char buf_cpy[count];
const char delimiter[3] = {' ', '\n', '\0'};
memcpy(buf_cpy, buf, count+1); ret = amdgpu_read_mask(buf, count, &mask);
tmp = buf_cpy; if (ret)
while (tmp[0]) { return ret;
sub_str = strsep(&tmp, delimiter);
if (strlen(sub_str)) {
ret = kstrtol(sub_str, 0, &level);
if (ret) {
count = -EINVAL;
goto fail;
}
mask |= 1 << level;
} else
break;
}
if (adev->powerplay.pp_funcs->force_clock_level) if (adev->powerplay.pp_funcs->force_clock_level)
amdgpu_dpm_force_clock_level(adev, PP_MCLK, mask); amdgpu_dpm_force_clock_level(adev, PP_MCLK, mask);
fail:
return count; return count;
} }
...@@ -714,33 +716,15 @@ static ssize_t amdgpu_set_pp_dpm_pcie(struct device *dev, ...@@ -714,33 +716,15 @@ static ssize_t amdgpu_set_pp_dpm_pcie(struct device *dev,
struct drm_device *ddev = dev_get_drvdata(dev); struct drm_device *ddev = dev_get_drvdata(dev);
struct amdgpu_device *adev = ddev->dev_private; struct amdgpu_device *adev = ddev->dev_private;
int ret; int ret;
long level;
uint32_t mask = 0; uint32_t mask = 0;
char *sub_str = NULL;
char *tmp;
char buf_cpy[count];
const char delimiter[3] = {' ', '\n', '\0'};
memcpy(buf_cpy, buf, count+1);
tmp = buf_cpy;
while (tmp[0]) { ret = amdgpu_read_mask(buf, count, &mask);
sub_str = strsep(&tmp, delimiter); if (ret)
if (strlen(sub_str)) { return ret;
ret = kstrtol(sub_str, 0, &level);
if (ret) {
count = -EINVAL;
goto fail;
}
mask |= 1 << level;
} else
break;
}
if (adev->powerplay.pp_funcs->force_clock_level) if (adev->powerplay.pp_funcs->force_clock_level)
amdgpu_dpm_force_clock_level(adev, PP_PCIE, mask); amdgpu_dpm_force_clock_level(adev, PP_PCIE, mask);
fail:
return count; return count;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment