aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c')
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c100
1 files changed, 42 insertions, 58 deletions
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c
index f1404adc3a90..15a1192c1ec5 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c
@@ -606,40 +606,59 @@ static ssize_t amdgpu_get_pp_dpm_sclk(struct device *dev,
606 return snprintf(buf, PAGE_SIZE, "\n"); 606 return snprintf(buf, PAGE_SIZE, "\n");
607} 607}
608 608
609static ssize_t amdgpu_set_pp_dpm_sclk(struct device *dev, 609/*
610 struct device_attribute *attr, 610 * Worst case: 32 bits individually specified, in octal at 12 characters
611 const char *buf, 611 * per line (+1 for \n).
612 size_t count) 612 */
613#define AMDGPU_MASK_BUF_MAX (32 * 13)
614
615static ssize_t amdgpu_read_mask(const char *buf, size_t count, uint32_t *mask)
613{ 616{
614 struct drm_device *ddev = dev_get_drvdata(dev);
615 struct amdgpu_device *adev = ddev->dev_private;
616 int ret; 617 int ret;
617 long level; 618 long level;
618 uint32_t mask = 0;
619 char *sub_str = NULL; 619 char *sub_str = NULL;
620 char *tmp; 620 char *tmp;
621 char buf_cpy[count]; 621 char buf_cpy[AMDGPU_MASK_BUF_MAX + 1];
622 const char delimiter[3] = {' ', '\n', '\0'}; 622 const char delimiter[3] = {' ', '\n', '\0'};
623 size_t bytes;
623 624
624 memcpy(buf_cpy, buf, count+1); 625 *mask = 0;
626
627 bytes = min(count, sizeof(buf_cpy) - 1);
628 memcpy(buf_cpy, buf, bytes);
629 buf_cpy[bytes] = '\0';
625 tmp = buf_cpy; 630 tmp = buf_cpy;
626 while (tmp[0]) { 631 while (tmp[0]) {
627 sub_str = strsep(&tmp, delimiter); 632 sub_str = strsep(&tmp, delimiter);
628 if (strlen(sub_str)) { 633 if (strlen(sub_str)) {
629 ret = kstrtol(sub_str, 0, &level); 634 ret = kstrtol(sub_str, 0, &level);
630 635 if (ret)
631 if (ret) { 636 return -EINVAL;
632 count = -EINVAL; 637 *mask |= 1 << level;
633 goto fail;
634 }
635 mask |= 1 << level;
636 } else 638 } else
637 break; 639 break;
638 } 640 }
641
642 return 0;
643}
644
645static ssize_t amdgpu_set_pp_dpm_sclk(struct device *dev,
646 struct device_attribute *attr,
647 const char *buf,
648 size_t count)
649{
650 struct drm_device *ddev = dev_get_drvdata(dev);
651 struct amdgpu_device *adev = ddev->dev_private;
652 int ret;
653 uint32_t mask = 0;
654
655 ret = amdgpu_read_mask(buf, count, &mask);
656 if (ret)
657 return ret;
658
639 if (adev->powerplay.pp_funcs->force_clock_level) 659 if (adev->powerplay.pp_funcs->force_clock_level)
640 amdgpu_dpm_force_clock_level(adev, PP_SCLK, mask); 660 amdgpu_dpm_force_clock_level(adev, PP_SCLK, mask);
641 661
642fail:
643 return count; 662 return count;
644} 663}
645 664
@@ -664,32 +683,15 @@ static ssize_t amdgpu_set_pp_dpm_mclk(struct device *dev,
664 struct drm_device *ddev = dev_get_drvdata(dev); 683 struct drm_device *ddev = dev_get_drvdata(dev);
665 struct amdgpu_device *adev = ddev->dev_private; 684 struct amdgpu_device *adev = ddev->dev_private;
666 int ret; 685 int ret;
667 long level;
668 uint32_t mask = 0; 686 uint32_t mask = 0;
669 char *sub_str = NULL;
670 char *tmp;
671 char buf_cpy[count];
672 const char delimiter[3] = {' ', '\n', '\0'};
673 687
674 memcpy(buf_cpy, buf, count+1); 688 ret = amdgpu_read_mask(buf, count, &mask);
675 tmp = buf_cpy; 689 if (ret)
676 while (tmp[0]) { 690 return ret;
677 sub_str = strsep(&tmp, delimiter);
678 if (strlen(sub_str)) {
679 ret = kstrtol(sub_str, 0, &level);
680 691
681 if (ret) {
682 count = -EINVAL;
683 goto fail;
684 }
685 mask |= 1 << level;
686 } else
687 break;
688 }
689 if (adev->powerplay.pp_funcs->force_clock_level) 692 if (adev->powerplay.pp_funcs->force_clock_level)
690 amdgpu_dpm_force_clock_level(adev, PP_MCLK, mask); 693 amdgpu_dpm_force_clock_level(adev, PP_MCLK, mask);
691 694
692fail:
693 return count; 695 return count;
694} 696}
695 697
@@ -714,33 +716,15 @@ static ssize_t amdgpu_set_pp_dpm_pcie(struct device *dev,
714 struct drm_device *ddev = dev_get_drvdata(dev); 716 struct drm_device *ddev = dev_get_drvdata(dev);
715 struct amdgpu_device *adev = ddev->dev_private; 717 struct amdgpu_device *adev = ddev->dev_private;
716 int ret; 718 int ret;
717 long level;
718 uint32_t mask = 0; 719 uint32_t mask = 0;
719 char *sub_str = NULL;
720 char *tmp;
721 char buf_cpy[count];
722 const char delimiter[3] = {' ', '\n', '\0'};
723
724 memcpy(buf_cpy, buf, count+1);
725 tmp = buf_cpy;
726 720
727 while (tmp[0]) { 721 ret = amdgpu_read_mask(buf, count, &mask);
728 sub_str = strsep(&tmp, delimiter); 722 if (ret)
729 if (strlen(sub_str)) { 723 return ret;
730 ret = kstrtol(sub_str, 0, &level);
731 724
732 if (ret) {
733 count = -EINVAL;
734 goto fail;
735 }
736 mask |= 1 << level;
737 } else
738 break;
739 }
740 if (adev->powerplay.pp_funcs->force_clock_level) 725 if (adev->powerplay.pp_funcs->force_clock_level)
741 amdgpu_dpm_force_clock_level(adev, PP_PCIE, mask); 726 amdgpu_dpm_force_clock_level(adev, PP_PCIE, mask);
742 727
743fail:
744 return count; 728 return count;
745} 729}
746 730