Lines 678-691
static int iwl_mvm_config_ltr(struct iwl_mvm *mvm)
Link Here
|
678 |
} |
678 |
} |
679 |
|
679 |
|
680 |
#ifdef CONFIG_ACPI |
680 |
#ifdef CONFIG_ACPI |
|
|
681 |
static inline int iwl_mvm_sar_set_profile(struct iwl_mvm *mvm, |
682 |
union acpi_object *table, |
683 |
struct iwl_mvm_sar_profile *profile, |
684 |
bool enabled) |
685 |
{ |
686 |
int i; |
687 |
|
688 |
profile->enabled = enabled; |
689 |
|
690 |
for (i = 0; i < ACPI_SAR_TABLE_SIZE; i++) { |
691 |
if ((table[i].type != ACPI_TYPE_INTEGER) || |
692 |
(table[i].integer.value > U8_MAX)) |
693 |
return -EINVAL; |
694 |
|
695 |
profile->table[i] = table[i].integer.value; |
696 |
} |
697 |
|
698 |
return 0; |
699 |
} |
700 |
|
701 |
static int iwl_mvm_sar_get_wrds_table(struct iwl_mvm *mvm) |
702 |
{ |
703 |
union acpi_object *wifi_pkg, *table, *data; |
704 |
bool enabled; |
705 |
int ret, tbl_rev; |
706 |
|
707 |
data = iwl_acpi_get_object(mvm->dev, ACPI_WRDS_METHOD); |
708 |
if (IS_ERR(data)) |
709 |
return PTR_ERR(data); |
710 |
|
711 |
wifi_pkg = iwl_acpi_get_wifi_pkg(mvm->dev, data, |
712 |
ACPI_WRDS_WIFI_DATA_SIZE, &tbl_rev); |
713 |
if (IS_ERR(wifi_pkg)) { |
714 |
ret = PTR_ERR(wifi_pkg); |
715 |
goto out_free; |
716 |
} |
717 |
|
718 |
if (wifi_pkg->package.elements[1].type != ACPI_TYPE_INTEGER || |
719 |
tbl_rev != 0) { |
720 |
ret = -EINVAL; |
721 |
goto out_free; |
722 |
} |
723 |
|
724 |
enabled = !!(wifi_pkg->package.elements[1].integer.value); |
725 |
|
726 |
/* position of the actual table */ |
727 |
table = &wifi_pkg->package.elements[2]; |
728 |
|
729 |
/* The profile from WRDS is officially profile 1, but goes |
730 |
* into sar_profiles[0] (because we don't have a profile 0). |
731 |
*/ |
732 |
ret = iwl_mvm_sar_set_profile(mvm, table, &mvm->sar_profiles[0], |
733 |
enabled); |
734 |
out_free: |
735 |
kfree(data); |
736 |
return ret; |
737 |
} |
738 |
|
739 |
static int iwl_mvm_sar_get_ewrd_table(struct iwl_mvm *mvm) |
740 |
{ |
741 |
union acpi_object *wifi_pkg, *data; |
742 |
bool enabled; |
743 |
int i, n_profiles, ret, tbl_rev; |
744 |
|
745 |
data = iwl_acpi_get_object(mvm->dev, ACPI_EWRD_METHOD); |
746 |
if (IS_ERR(data)) |
747 |
return PTR_ERR(data); |
748 |
|
749 |
wifi_pkg = iwl_acpi_get_wifi_pkg(mvm->dev, data, |
750 |
ACPI_EWRD_WIFI_DATA_SIZE, &tbl_rev); |
751 |
if (IS_ERR(wifi_pkg)) { |
752 |
ret = PTR_ERR(wifi_pkg); |
753 |
goto out_free; |
754 |
} |
755 |
|
756 |
if ((wifi_pkg->package.elements[1].type != ACPI_TYPE_INTEGER) || |
757 |
(wifi_pkg->package.elements[2].type != ACPI_TYPE_INTEGER) || |
758 |
tbl_rev != 0) { |
759 |
ret = -EINVAL; |
760 |
goto out_free; |
761 |
} |
762 |
|
763 |
enabled = !!(wifi_pkg->package.elements[1].integer.value); |
764 |
n_profiles = wifi_pkg->package.elements[2].integer.value; |
765 |
|
766 |
/* |
767 |
* Check the validity of n_profiles. The EWRD profiles start |
768 |
* from index 1, so the maximum value allowed here is |
769 |
* ACPI_SAR_PROFILES_NUM - 1. |
770 |
*/ |
771 |
if (n_profiles <= 0 || n_profiles >= ACPI_SAR_PROFILE_NUM) { |
772 |
ret = -EINVAL; |
773 |
goto out_free; |
774 |
} |
775 |
|
776 |
for (i = 0; i < n_profiles; i++) { |
777 |
/* the tables start at element 3 */ |
778 |
int pos = 3; |
779 |
|
780 |
/* The EWRD profiles officially go from 2 to 4, but we |
781 |
* save them in sar_profiles[1-3] (because we don't |
782 |
* have profile 0). So in the array we start from 1. |
783 |
*/ |
784 |
ret = iwl_mvm_sar_set_profile(mvm, |
785 |
&wifi_pkg->package.elements[pos], |
786 |
&mvm->sar_profiles[i + 1], |
787 |
enabled); |
788 |
if (ret < 0) |
789 |
break; |
790 |
|
791 |
/* go to the next table */ |
792 |
pos += ACPI_SAR_TABLE_SIZE; |
793 |
} |
794 |
|
795 |
out_free: |
796 |
kfree(data); |
797 |
return ret; |
798 |
} |
799 |
|
800 |
static int iwl_mvm_sar_get_wgds_table(struct iwl_mvm *mvm) |
801 |
{ |
802 |
union acpi_object *wifi_pkg, *data; |
803 |
int i, j, ret, tbl_rev; |
804 |
int idx = 1; |
805 |
|
806 |
data = iwl_acpi_get_object(mvm->dev, ACPI_WGDS_METHOD); |
807 |
if (IS_ERR(data)) |
808 |
return PTR_ERR(data); |
809 |
|
810 |
wifi_pkg = iwl_acpi_get_wifi_pkg(mvm->dev, data, |
811 |
ACPI_WGDS_WIFI_DATA_SIZE, &tbl_rev); |
812 |
if (IS_ERR(wifi_pkg)) { |
813 |
ret = PTR_ERR(wifi_pkg); |
814 |
goto out_free; |
815 |
} |
816 |
|
817 |
if (tbl_rev != 0) { |
818 |
ret = -EINVAL; |
819 |
goto out_free; |
820 |
} |
821 |
|
822 |
mvm->geo_rev = tbl_rev; |
823 |
for (i = 0; i < ACPI_NUM_GEO_PROFILES; i++) { |
824 |
for (j = 0; j < ACPI_GEO_TABLE_SIZE; j++) { |
825 |
union acpi_object *entry; |
826 |
|
827 |
entry = &wifi_pkg->package.elements[idx++]; |
828 |
if ((entry->type != ACPI_TYPE_INTEGER) || |
829 |
(entry->integer.value > U8_MAX)) { |
830 |
ret = -EINVAL; |
831 |
goto out_free; |
832 |
} |
833 |
|
834 |
mvm->geo_profiles[i].values[j] = entry->integer.value; |
835 |
} |
836 |
} |
837 |
ret = 0; |
838 |
out_free: |
839 |
kfree(data); |
840 |
return ret; |
841 |
} |
842 |
|
681 |
int iwl_mvm_sar_select_profile(struct iwl_mvm *mvm, int prof_a, int prof_b) |
843 |
int iwl_mvm_sar_select_profile(struct iwl_mvm *mvm, int prof_a, int prof_b) |
682 |
{ |
844 |
{ |
683 |
union { |
845 |
union { |
684 |
struct iwl_dev_tx_power_cmd v5; |
846 |
struct iwl_dev_tx_power_cmd v5; |
685 |
struct iwl_dev_tx_power_cmd_v4 v4; |
847 |
struct iwl_dev_tx_power_cmd_v4 v4; |
686 |
} cmd; |
848 |
} cmd; |
|
|
849 |
int i, j, idx; |
850 |
int profs[ACPI_SAR_NUM_CHAIN_LIMITS] = { prof_a, prof_b }; |
851 |
int len; |
687 |
|
852 |
|
688 |
u16 len = 0; |
853 |
BUILD_BUG_ON(ACPI_SAR_NUM_CHAIN_LIMITS < 2); |
|
|
854 |
BUILD_BUG_ON(ACPI_SAR_NUM_CHAIN_LIMITS * ACPI_SAR_NUM_SUB_BANDS != |
855 |
ACPI_SAR_TABLE_SIZE); |
689 |
|
856 |
|
690 |
cmd.v5.v3.set_mode = cpu_to_le32(IWL_TX_POWER_MODE_SET_CHAINS); |
857 |
cmd.v5.v3.set_mode = cpu_to_le32(IWL_TX_POWER_MODE_SET_CHAINS); |
691 |
|
858 |
|
Lines 694-769
int iwl_mvm_sar_select_profile(struct iwl_mvm *mvm, int prof_a, int prof_b)
Link Here
|
694 |
len = sizeof(cmd.v5); |
861 |
len = sizeof(cmd.v5); |
695 |
else if (fw_has_capa(&mvm->fw->ucode_capa, |
862 |
else if (fw_has_capa(&mvm->fw->ucode_capa, |
696 |
IWL_UCODE_TLV_CAPA_TX_POWER_ACK)) |
863 |
IWL_UCODE_TLV_CAPA_TX_POWER_ACK)) |
697 |
len = sizeof(struct iwl_dev_tx_power_cmd_v4); |
864 |
len = sizeof(cmd.v4); |
698 |
else |
865 |
else |
699 |
len = sizeof(cmd.v4.v3); |
866 |
len = sizeof(cmd.v4.v3); |
700 |
|
867 |
|
|
|
868 |
for (i = 0; i < ACPI_SAR_NUM_CHAIN_LIMITS; i++) { |
869 |
struct iwl_mvm_sar_profile *prof; |
870 |
|
871 |
/* don't allow SAR to be disabled (profile 0 means disable) */ |
872 |
if (profs[i] == 0) |
873 |
return -EPERM; |
874 |
|
875 |
/* we are off by one, so allow up to ACPI_SAR_PROFILE_NUM */ |
876 |
if (profs[i] > ACPI_SAR_PROFILE_NUM) |
877 |
return -EINVAL; |
878 |
|
879 |
/* profiles go from 1 to 4, so decrement to access the array */ |
880 |
prof = &mvm->sar_profiles[profs[i] - 1]; |
881 |
|
882 |
/* if the profile is disabled, do nothing */ |
883 |
if (!prof->enabled) { |
884 |
IWL_DEBUG_RADIO(mvm, "SAR profile %d is disabled.\n", |
885 |
profs[i]); |
886 |
/* if one of the profiles is disabled, we fail all */ |
887 |
return -ENOENT; |
888 |
} |
889 |
|
890 |
IWL_DEBUG_INFO(mvm, |
891 |
"SAR EWRD: chain %d profile index %d\n", |
892 |
i, profs[i]); |
893 |
IWL_DEBUG_RADIO(mvm, " Chain[%d]:\n", i); |
894 |
for (j = 0; j < ACPI_SAR_NUM_SUB_BANDS; j++) { |
895 |
idx = (i * ACPI_SAR_NUM_SUB_BANDS) + j; |
896 |
cmd.v5.v3.per_chain_restriction[i][j] = |
897 |
cpu_to_le16(prof->table[idx]); |
898 |
IWL_DEBUG_RADIO(mvm, " Band[%d] = %d * .125dBm\n", |
899 |
j, prof->table[idx]); |
900 |
} |
901 |
} |
701 |
|
902 |
|
702 |
if (iwl_sar_select_profile(&mvm->fwrt, cmd.v5.v3.per_chain_restriction, |
|
|
703 |
prof_a, prof_b)) |
704 |
return -ENOENT; |
705 |
IWL_DEBUG_RADIO(mvm, "Sending REDUCE_TX_POWER_CMD per chain\n"); |
903 |
IWL_DEBUG_RADIO(mvm, "Sending REDUCE_TX_POWER_CMD per chain\n"); |
|
|
904 |
|
706 |
return iwl_mvm_send_cmd_pdu(mvm, REDUCE_TX_POWER_CMD, 0, len, &cmd); |
905 |
return iwl_mvm_send_cmd_pdu(mvm, REDUCE_TX_POWER_CMD, 0, len, &cmd); |
707 |
} |
906 |
} |
708 |
|
907 |
|
|
|
908 |
static bool iwl_mvm_sar_geo_support(struct iwl_mvm *mvm) |
909 |
{ |
910 |
/* |
911 |
* The GEO_TX_POWER_LIMIT command is not supported on earlier |
912 |
* firmware versions. Unfortunately, we don't have a TLV API |
913 |
* flag to rely on, so rely on the major version which is in |
914 |
* the first byte of ucode_ver. This was implemented |
915 |
* initially on version 38 and then backported to 17. It was |
916 |
* also backported to 29, but only for 7265D devices. The |
917 |
* intention was to have it in 36 as well, but not all 8000 |
918 |
* family got this feature enabled. The 8000 family is the |
919 |
* only one using version 36, so skip this version entirely. |
920 |
*/ |
921 |
return IWL_UCODE_SERIAL(mvm->fw->ucode_ver) >= 38 || |
922 |
IWL_UCODE_SERIAL(mvm->fw->ucode_ver) == 17 || |
923 |
(IWL_UCODE_SERIAL(mvm->fw->ucode_ver) == 29 && |
924 |
((mvm->trans->hw_rev & CSR_HW_REV_TYPE_MSK) == |
925 |
CSR_HW_REV_TYPE_7265D)); |
926 |
} |
927 |
|
709 |
int iwl_mvm_get_sar_geo_profile(struct iwl_mvm *mvm) |
928 |
int iwl_mvm_get_sar_geo_profile(struct iwl_mvm *mvm) |
710 |
{ |
929 |
{ |
711 |
union geo_tx_power_profiles_cmd geo_tx_cmd; |
930 |
struct iwl_geo_tx_power_profiles_resp *resp; |
712 |
u16 len; |
|
|
713 |
int ret; |
931 |
int ret; |
|
|
932 |
u16 len; |
933 |
void *data; |
934 |
struct iwl_geo_tx_power_profiles_cmd geo_cmd; |
935 |
struct iwl_geo_tx_power_profiles_cmd_v1 geo_cmd_v1; |
714 |
struct iwl_host_cmd cmd; |
936 |
struct iwl_host_cmd cmd; |
715 |
|
937 |
|
716 |
if (fw_has_api(&mvm->fwrt.fw->ucode_capa, |
938 |
if (fw_has_api(&mvm->fw->ucode_capa, IWL_UCODE_TLV_API_SAR_TABLE_VER)) { |
717 |
IWL_UCODE_TLV_API_SAR_TABLE_VER)) { |
939 |
geo_cmd.ops = |
718 |
geo_tx_cmd.geo_cmd.ops = |
|
|
719 |
cpu_to_le32(IWL_PER_CHAIN_OFFSET_GET_CURRENT_TABLE); |
940 |
cpu_to_le32(IWL_PER_CHAIN_OFFSET_GET_CURRENT_TABLE); |
720 |
len = sizeof(geo_tx_cmd.geo_cmd); |
941 |
len = sizeof(geo_cmd); |
|
|
942 |
data = &geo_cmd; |
721 |
} else { |
943 |
} else { |
722 |
geo_tx_cmd.geo_cmd_v1.ops = |
944 |
geo_cmd_v1.ops = |
723 |
cpu_to_le32(IWL_PER_CHAIN_OFFSET_GET_CURRENT_TABLE); |
945 |
cpu_to_le32(IWL_PER_CHAIN_OFFSET_GET_CURRENT_TABLE); |
724 |
len = sizeof(geo_tx_cmd.geo_cmd_v1); |
946 |
len = sizeof(geo_cmd_v1); |
|
|
947 |
data = &geo_cmd_v1; |
725 |
} |
948 |
} |
726 |
|
949 |
|
727 |
if (!iwl_sar_geo_support(&mvm->fwrt)) |
|
|
728 |
return -EOPNOTSUPP; |
729 |
|
730 |
cmd = (struct iwl_host_cmd){ |
950 |
cmd = (struct iwl_host_cmd){ |
731 |
.id = WIDE_ID(PHY_OPS_GROUP, GEO_TX_POWER_LIMIT), |
951 |
.id = WIDE_ID(PHY_OPS_GROUP, GEO_TX_POWER_LIMIT), |
732 |
.len = { len, }, |
952 |
.len = { len, }, |
733 |
.flags = CMD_WANT_SKB, |
953 |
.flags = CMD_WANT_SKB, |
734 |
.data = { &geo_tx_cmd }, |
954 |
.data = { data }, |
735 |
}; |
955 |
}; |
736 |
|
956 |
|
|
|
957 |
if (!iwl_mvm_sar_geo_support(mvm)) |
958 |
return -EOPNOTSUPP; |
959 |
|
737 |
ret = iwl_mvm_send_cmd(mvm, &cmd); |
960 |
ret = iwl_mvm_send_cmd(mvm, &cmd); |
738 |
if (ret) { |
961 |
if (ret) { |
739 |
IWL_ERR(mvm, "Failed to get geographic profile info %d\n", ret); |
962 |
IWL_ERR(mvm, "Failed to get geographic profile info %d\n", ret); |
740 |
return ret; |
963 |
return ret; |
741 |
} |
964 |
} |
742 |
ret = iwl_validate_sar_geo_profile(&mvm->fwrt, &cmd); |
965 |
|
|
|
966 |
resp = (void *)cmd.resp_pkt->data; |
967 |
ret = le32_to_cpu(resp->profile_idx); |
968 |
if (WARN_ON(ret > ACPI_NUM_GEO_PROFILES)) { |
969 |
ret = -EIO; |
970 |
IWL_WARN(mvm, "Invalid geographic profile idx (%d)\n", ret); |
971 |
} |
972 |
|
743 |
iwl_free_resp(&cmd); |
973 |
iwl_free_resp(&cmd); |
744 |
return ret; |
974 |
return ret; |
745 |
} |
975 |
} |
746 |
|
976 |
|
747 |
static int iwl_mvm_sar_geo_init(struct iwl_mvm *mvm) |
977 |
static int iwl_mvm_sar_geo_init(struct iwl_mvm *mvm) |
748 |
{ |
978 |
{ |
|
|
979 |
struct iwl_geo_tx_power_profiles_cmd cmd = { |
980 |
.ops = cpu_to_le32(IWL_PER_CHAIN_OFFSET_SET_TABLES), |
981 |
}; |
982 |
int ret, i, j; |
749 |
u16 cmd_wide_id = WIDE_ID(PHY_OPS_GROUP, GEO_TX_POWER_LIMIT); |
983 |
u16 cmd_wide_id = WIDE_ID(PHY_OPS_GROUP, GEO_TX_POWER_LIMIT); |
750 |
union geo_tx_power_profiles_cmd cmd; |
|
|
751 |
u16 len; |
752 |
|
984 |
|
753 |
cmd.geo_cmd.ops = cpu_to_le32(IWL_PER_CHAIN_OFFSET_SET_TABLES); |
985 |
if (!iwl_mvm_sar_geo_support(mvm)) |
|
|
986 |
return 0; |
754 |
|
987 |
|
755 |
iwl_sar_geo_init(&mvm->fwrt, cmd.geo_cmd.table); |
988 |
ret = iwl_mvm_sar_get_wgds_table(mvm); |
|
|
989 |
if (ret < 0) { |
990 |
IWL_DEBUG_RADIO(mvm, |
991 |
"Geo SAR BIOS table invalid or unavailable. (%d)\n", |
992 |
ret); |
993 |
/* we don't fail if the table is not available */ |
994 |
return 0; |
995 |
} |
756 |
|
996 |
|
757 |
cmd.geo_cmd.table_revision = cpu_to_le32(mvm->fwrt.geo_rev); |
997 |
IWL_DEBUG_RADIO(mvm, "Sending GEO_TX_POWER_LIMIT\n"); |
758 |
|
998 |
|
759 |
if (!fw_has_api(&mvm->fwrt.fw->ucode_capa, |
999 |
BUILD_BUG_ON(ACPI_NUM_GEO_PROFILES * ACPI_WGDS_NUM_BANDS * |
760 |
IWL_UCODE_TLV_API_SAR_TABLE_VER)) { |
1000 |
ACPI_WGDS_TABLE_SIZE + 1 != ACPI_WGDS_WIFI_DATA_SIZE); |
761 |
len = sizeof(struct iwl_geo_tx_power_profiles_cmd_v1); |
1001 |
|
762 |
} else { |
1002 |
BUILD_BUG_ON(ACPI_NUM_GEO_PROFILES > IWL_NUM_GEO_PROFILES); |
763 |
len = sizeof(cmd.geo_cmd); |
1003 |
|
|
|
1004 |
for (i = 0; i < ACPI_NUM_GEO_PROFILES; i++) { |
1005 |
struct iwl_per_chain_offset *chain = |
1006 |
(struct iwl_per_chain_offset *)&cmd.table[i]; |
1007 |
|
1008 |
for (j = 0; j < ACPI_WGDS_NUM_BANDS; j++) { |
1009 |
u8 *value; |
1010 |
|
1011 |
value = &mvm->geo_profiles[i].values[j * |
1012 |
ACPI_GEO_PER_CHAIN_SIZE]; |
1013 |
chain[j].max_tx_power = cpu_to_le16(value[0]); |
1014 |
chain[j].chain_a = value[1]; |
1015 |
chain[j].chain_b = value[2]; |
1016 |
IWL_DEBUG_RADIO(mvm, |
1017 |
"SAR geographic profile[%d] Band[%d]: chain A = %d chain B = %d max_tx_power = %d\n", |
1018 |
i, j, value[1], value[2], value[0]); |
1019 |
} |
764 |
} |
1020 |
} |
765 |
|
1021 |
|
766 |
return iwl_mvm_send_cmd_pdu(mvm, cmd_wide_id, 0, len, &cmd); |
1022 |
cmd.table_revision = cpu_to_le32(mvm->geo_rev); |
|
|
1023 |
|
1024 |
if (!fw_has_api(&mvm->fw->ucode_capa, |
1025 |
IWL_UCODE_TLV_API_SAR_TABLE_VER)) { |
1026 |
return iwl_mvm_send_cmd_pdu(mvm, cmd_wide_id, 0, |
1027 |
sizeof(struct iwl_geo_tx_power_profiles_cmd_v1), |
1028 |
&cmd); |
1029 |
} |
1030 |
|
1031 |
return iwl_mvm_send_cmd_pdu(mvm, cmd_wide_id, 0, sizeof(cmd), &cmd); |
767 |
} |
1032 |
} |
768 |
|
1033 |
|
769 |
static int iwl_mvm_get_ppag_table(struct iwl_mvm *mvm) |
1034 |
static int iwl_mvm_get_ppag_table(struct iwl_mvm *mvm) |
Lines 772-778
static int iwl_mvm_get_ppag_table(struct iwl_mvm *mvm)
Link Here
|
772 |
int i, j, ret, tbl_rev; |
1037 |
int i, j, ret, tbl_rev; |
773 |
int idx = 2; |
1038 |
int idx = 2; |
774 |
|
1039 |
|
775 |
mvm->fwrt.ppag_table.enabled = cpu_to_le32(0); |
1040 |
mvm->ppag_table.enabled = cpu_to_le32(0); |
776 |
data = iwl_acpi_get_object(mvm->dev, ACPI_PPAG_METHOD); |
1041 |
data = iwl_acpi_get_object(mvm->dev, ACPI_PPAG_METHOD); |
777 |
if (IS_ERR(data)) |
1042 |
if (IS_ERR(data)) |
778 |
return PTR_ERR(data); |
1043 |
return PTR_ERR(data); |
Lines 797-804
static int iwl_mvm_get_ppag_table(struct iwl_mvm *mvm)
Link Here
|
797 |
goto out_free; |
1062 |
goto out_free; |
798 |
} |
1063 |
} |
799 |
|
1064 |
|
800 |
mvm->fwrt.ppag_table.enabled = cpu_to_le32(enabled->integer.value); |
1065 |
mvm->ppag_table.enabled = cpu_to_le32(enabled->integer.value); |
801 |
if (!mvm->fwrt.ppag_table.enabled) { |
1066 |
if (!mvm->ppag_table.enabled) { |
802 |
ret = 0; |
1067 |
ret = 0; |
803 |
goto out_free; |
1068 |
goto out_free; |
804 |
} |
1069 |
} |
Lines 818-828
static int iwl_mvm_get_ppag_table(struct iwl_mvm *mvm)
Link Here
|
818 |
(j == 0 && ent->integer.value < ACPI_PPAG_MIN_LB) || |
1083 |
(j == 0 && ent->integer.value < ACPI_PPAG_MIN_LB) || |
819 |
(j != 0 && ent->integer.value > ACPI_PPAG_MAX_HB) || |
1084 |
(j != 0 && ent->integer.value > ACPI_PPAG_MAX_HB) || |
820 |
(j != 0 && ent->integer.value < ACPI_PPAG_MIN_HB)) { |
1085 |
(j != 0 && ent->integer.value < ACPI_PPAG_MIN_HB)) { |
821 |
mvm->fwrt.ppag_table.enabled = cpu_to_le32(0); |
1086 |
mvm->ppag_table.enabled = cpu_to_le32(0); |
822 |
ret = -EINVAL; |
1087 |
ret = -EINVAL; |
823 |
goto out_free; |
1088 |
goto out_free; |
824 |
} |
1089 |
} |
825 |
mvm->fwrt.ppag_table.gain[i][j] = ent->integer.value; |
1090 |
mvm->ppag_table.gain[i][j] = ent->integer.value; |
826 |
} |
1091 |
} |
827 |
} |
1092 |
} |
828 |
ret = 0; |
1093 |
ret = 0; |
Lines 841-847
int iwl_mvm_ppag_send_cmd(struct iwl_mvm *mvm)
Link Here
|
841 |
return 0; |
1106 |
return 0; |
842 |
} |
1107 |
} |
843 |
|
1108 |
|
844 |
if (!mvm->fwrt.ppag_table.enabled) { |
1109 |
if (!mvm->ppag_table.enabled) { |
845 |
IWL_DEBUG_RADIO(mvm, |
1110 |
IWL_DEBUG_RADIO(mvm, |
846 |
"PPAG not enabled, command not sent.\n"); |
1111 |
"PPAG not enabled, command not sent.\n"); |
847 |
return 0; |
1112 |
return 0; |
Lines 853-866
int iwl_mvm_ppag_send_cmd(struct iwl_mvm *mvm)
Link Here
|
853 |
for (j = 0; j < ACPI_PPAG_NUM_SUB_BANDS; j++) { |
1118 |
for (j = 0; j < ACPI_PPAG_NUM_SUB_BANDS; j++) { |
854 |
IWL_DEBUG_RADIO(mvm, |
1119 |
IWL_DEBUG_RADIO(mvm, |
855 |
"PPAG table: chain[%d] band[%d]: gain = %d\n", |
1120 |
"PPAG table: chain[%d] band[%d]: gain = %d\n", |
856 |
i, j, mvm->fwrt.ppag_table.gain[i][j]); |
1121 |
i, j, mvm->ppag_table.gain[i][j]); |
857 |
} |
1122 |
} |
858 |
} |
1123 |
} |
859 |
|
1124 |
|
860 |
ret = iwl_mvm_send_cmd_pdu(mvm, WIDE_ID(PHY_OPS_GROUP, |
1125 |
ret = iwl_mvm_send_cmd_pdu(mvm, WIDE_ID(PHY_OPS_GROUP, |
861 |
PER_PLATFORM_ANT_GAIN_CMD), |
1126 |
PER_PLATFORM_ANT_GAIN_CMD), |
862 |
0, sizeof(mvm->fwrt.ppag_table), |
1127 |
0, sizeof(mvm->ppag_table), |
863 |
&mvm->fwrt.ppag_table); |
1128 |
&mvm->ppag_table); |
864 |
if (ret < 0) |
1129 |
if (ret < 0) |
865 |
IWL_ERR(mvm, "failed to send PER_PLATFORM_ANT_GAIN_CMD (%d)\n", |
1130 |
IWL_ERR(mvm, "failed to send PER_PLATFORM_ANT_GAIN_CMD (%d)\n", |
866 |
ret); |
1131 |
ret); |
Lines 883-896
static int iwl_mvm_ppag_init(struct iwl_mvm *mvm)
Link Here
|
883 |
} |
1148 |
} |
884 |
|
1149 |
|
885 |
#else /* CONFIG_ACPI */ |
1150 |
#else /* CONFIG_ACPI */ |
|
|
1151 |
static int iwl_mvm_sar_get_wrds_table(struct iwl_mvm *mvm) |
1152 |
{ |
1153 |
return -ENOENT; |
1154 |
} |
886 |
|
1155 |
|
887 |
inline int iwl_mvm_sar_select_profile(struct iwl_mvm *mvm, |
1156 |
static int iwl_mvm_sar_get_ewrd_table(struct iwl_mvm *mvm) |
888 |
int prof_a, int prof_b) |
|
|
889 |
{ |
1157 |
{ |
890 |
return -ENOENT; |
1158 |
return -ENOENT; |
891 |
} |
1159 |
} |
892 |
|
1160 |
|
893 |
inline int iwl_mvm_get_sar_geo_profile(struct iwl_mvm *mvm) |
1161 |
static int iwl_mvm_sar_get_wgds_table(struct iwl_mvm *mvm) |
894 |
{ |
1162 |
{ |
895 |
return -ENOENT; |
1163 |
return -ENOENT; |
896 |
} |
1164 |
} |
Lines 900-905
static int iwl_mvm_sar_geo_init(struct iwl_mvm *mvm)
Link Here
|
900 |
return 0; |
1168 |
return 0; |
901 |
} |
1169 |
} |
902 |
|
1170 |
|
|
|
1171 |
int iwl_mvm_sar_select_profile(struct iwl_mvm *mvm, int prof_a, |
1172 |
int prof_b) |
1173 |
{ |
1174 |
return -ENOENT; |
1175 |
} |
1176 |
|
1177 |
int iwl_mvm_get_sar_geo_profile(struct iwl_mvm *mvm) |
1178 |
{ |
1179 |
return -ENOENT; |
1180 |
} |
1181 |
|
903 |
int iwl_mvm_ppag_send_cmd(struct iwl_mvm *mvm) |
1182 |
int iwl_mvm_ppag_send_cmd(struct iwl_mvm *mvm) |
904 |
{ |
1183 |
{ |
905 |
return -ENOENT; |
1184 |
return -ENOENT; |
Lines 907-913
int iwl_mvm_ppag_send_cmd(struct iwl_mvm *mvm)
Link Here
|
907 |
|
1186 |
|
908 |
static int iwl_mvm_ppag_init(struct iwl_mvm *mvm) |
1187 |
static int iwl_mvm_ppag_init(struct iwl_mvm *mvm) |
909 |
{ |
1188 |
{ |
910 |
return 0; |
1189 |
return -ENOENT; |
911 |
} |
1190 |
} |
912 |
#endif /* CONFIG_ACPI */ |
1191 |
#endif /* CONFIG_ACPI */ |
913 |
|
1192 |
|
Lines 966-972
static int iwl_mvm_sar_init(struct iwl_mvm *mvm)
Link Here
|
966 |
{ |
1245 |
{ |
967 |
int ret; |
1246 |
int ret; |
968 |
|
1247 |
|
969 |
ret = iwl_sar_get_wrds_table(&mvm->fwrt); |
1248 |
ret = iwl_mvm_sar_get_wrds_table(mvm); |
970 |
if (ret < 0) { |
1249 |
if (ret < 0) { |
971 |
IWL_DEBUG_RADIO(mvm, |
1250 |
IWL_DEBUG_RADIO(mvm, |
972 |
"WRDS SAR BIOS table invalid or unavailable. (%d)\n", |
1251 |
"WRDS SAR BIOS table invalid or unavailable. (%d)\n", |
Lines 978-991
static int iwl_mvm_sar_init(struct iwl_mvm *mvm)
Link Here
|
978 |
return 1; |
1257 |
return 1; |
979 |
} |
1258 |
} |
980 |
|
1259 |
|
981 |
ret = iwl_sar_get_ewrd_table(&mvm->fwrt); |
1260 |
ret = iwl_mvm_sar_get_ewrd_table(mvm); |
982 |
/* if EWRD is not available, we can still use WRDS, so don't fail */ |
1261 |
/* if EWRD is not available, we can still use WRDS, so don't fail */ |
983 |
if (ret < 0) |
1262 |
if (ret < 0) |
984 |
IWL_DEBUG_RADIO(mvm, |
1263 |
IWL_DEBUG_RADIO(mvm, |
985 |
"EWRD SAR BIOS table invalid or unavailable. (%d)\n", |
1264 |
"EWRD SAR BIOS table invalid or unavailable. (%d)\n", |
986 |
ret); |
1265 |
ret); |
987 |
|
1266 |
|
|
|
1267 |
/* choose profile 1 (WRDS) as default for both chains */ |
988 |
ret = iwl_mvm_sar_select_profile(mvm, 1, 1); |
1268 |
ret = iwl_mvm_sar_select_profile(mvm, 1, 1); |
|
|
1269 |
|
989 |
/* |
1270 |
/* |
990 |
* If we don't have profile 0 from BIOS, just skip it. This |
1271 |
* If we don't have profile 0 from BIOS, just skip it. This |
991 |
* means that SAR Geo will not be enabled either, even if we |
1272 |
* means that SAR Geo will not be enabled either, even if we |
Lines 1216-1222
int iwl_mvm_up(struct iwl_mvm *mvm)
Link Here
|
1216 |
ret = iwl_mvm_sar_init(mvm); |
1497 |
ret = iwl_mvm_sar_init(mvm); |
1217 |
if (ret == 0) { |
1498 |
if (ret == 0) { |
1218 |
ret = iwl_mvm_sar_geo_init(mvm); |
1499 |
ret = iwl_mvm_sar_geo_init(mvm); |
1219 |
} else if (ret > 0 && !iwl_sar_get_wgds_table(&mvm->fwrt)) { |
1500 |
} else if (ret > 0 && !iwl_mvm_sar_get_wgds_table(mvm)) { |
1220 |
/* |
1501 |
/* |
1221 |
* If basic SAR is not available, we check for WGDS, |
1502 |
* If basic SAR is not available, we check for WGDS, |
1222 |
* which should *not* be available either. If it is |
1503 |
* which should *not* be available either. If it is |