diff options
author | Dan Williams <dcbw@redhat.com> | 2010-07-27 15:56:05 -0400 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2010-07-27 15:07:30 -0400 |
commit | cc4b9d3928d682c4a15690c2bd9ed11c2eac5921 (patch) | |
tree | 36bb70576b32bbdd148f4c71e54c09a0ed500042 /drivers/net/wireless/libertas/cmd.c | |
parent | 9fb7663d2b832183ec7558a19426666819636a64 (diff) |
libertas: convert 11D_DOMAIN_INFO to a direct command
Signed-off-by: Dan Williams <dcbw@redhat.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net/wireless/libertas/cmd.c')
-rw-r--r-- | drivers/net/wireless/libertas/cmd.c | 188 |
1 files changed, 123 insertions, 65 deletions
diff --git a/drivers/net/wireless/libertas/cmd.c b/drivers/net/wireless/libertas/cmd.c index e95f80de7c50..2aa362fd1a96 100644 --- a/drivers/net/wireless/libertas/cmd.c +++ b/drivers/net/wireless/libertas/cmd.c | |||
@@ -725,6 +725,129 @@ int lbs_get_rssi(struct lbs_private *priv, s8 *rssi, s8 *nf) | |||
725 | return ret; | 725 | return ret; |
726 | } | 726 | } |
727 | 727 | ||
728 | /** | ||
729 | * @brief Send regulatory and 802.11d domain information to the firmware | ||
730 | * | ||
731 | * @param priv pointer to struct lbs_private | ||
732 | * @param request cfg80211 regulatory request structure | ||
733 | * @param bands the device's supported bands and channels | ||
734 | * | ||
735 | * @return 0 on success, error code on failure | ||
736 | */ | ||
737 | int lbs_set_11d_domain_info(struct lbs_private *priv, | ||
738 | struct regulatory_request *request, | ||
739 | struct ieee80211_supported_band **bands) | ||
740 | { | ||
741 | struct cmd_ds_802_11d_domain_info cmd; | ||
742 | struct mrvl_ie_domain_param_set *domain = &cmd.domain; | ||
743 | struct ieee80211_country_ie_triplet *t; | ||
744 | enum ieee80211_band band; | ||
745 | struct ieee80211_channel *ch; | ||
746 | u8 num_triplet = 0; | ||
747 | u8 num_parsed_chan = 0; | ||
748 | u8 first_channel = 0, next_chan = 0, max_pwr = 0; | ||
749 | u8 i, flag = 0; | ||
750 | size_t triplet_size; | ||
751 | int ret; | ||
752 | |||
753 | lbs_deb_enter(LBS_DEB_11D); | ||
754 | |||
755 | memset(&cmd, 0, sizeof(cmd)); | ||
756 | cmd.action = cpu_to_le16(CMD_ACT_SET); | ||
757 | |||
758 | lbs_deb_11d("Setting country code '%c%c'\n", | ||
759 | request->alpha2[0], request->alpha2[1]); | ||
760 | |||
761 | domain->header.type = cpu_to_le16(TLV_TYPE_DOMAIN); | ||
762 | |||
763 | /* Set country code */ | ||
764 | domain->country_code[0] = request->alpha2[0]; | ||
765 | domain->country_code[1] = request->alpha2[1]; | ||
766 | domain->country_code[2] = ' '; | ||
767 | |||
768 | /* Now set up the channel triplets; firmware is somewhat picky here | ||
769 | * and doesn't validate channel numbers and spans; hence it would | ||
770 | * interpret a triplet of (36, 4, 20) as channels 36, 37, 38, 39. Since | ||
771 | * the last 3 aren't valid channels, the driver is responsible for | ||
772 | * splitting that up into 4 triplet pairs of (36, 1, 20) + (40, 1, 20) | ||
773 | * etc. | ||
774 | */ | ||
775 | for (band = 0; | ||
776 | (band < IEEE80211_NUM_BANDS) && (num_triplet < MAX_11D_TRIPLETS); | ||
777 | band++) { | ||
778 | |||
779 | if (!bands[band]) | ||
780 | continue; | ||
781 | |||
782 | for (i = 0; | ||
783 | (i < bands[band]->n_channels) && (num_triplet < MAX_11D_TRIPLETS); | ||
784 | i++) { | ||
785 | ch = &bands[band]->channels[i]; | ||
786 | if (ch->flags & IEEE80211_CHAN_DISABLED) | ||
787 | continue; | ||
788 | |||
789 | if (!flag) { | ||
790 | flag = 1; | ||
791 | next_chan = first_channel = (u32) ch->hw_value; | ||
792 | max_pwr = ch->max_power; | ||
793 | num_parsed_chan = 1; | ||
794 | continue; | ||
795 | } | ||
796 | |||
797 | if ((ch->hw_value == next_chan + 1) && | ||
798 | (ch->max_power == max_pwr)) { | ||
799 | /* Consolidate adjacent channels */ | ||
800 | next_chan++; | ||
801 | num_parsed_chan++; | ||
802 | } else { | ||
803 | /* Add this triplet */ | ||
804 | lbs_deb_11d("11D triplet (%d, %d, %d)\n", | ||
805 | first_channel, num_parsed_chan, | ||
806 | max_pwr); | ||
807 | t = &domain->triplet[num_triplet]; | ||
808 | t->chans.first_channel = first_channel; | ||
809 | t->chans.num_channels = num_parsed_chan; | ||
810 | t->chans.max_power = max_pwr; | ||
811 | num_triplet++; | ||
812 | flag = 0; | ||
813 | } | ||
814 | } | ||
815 | |||
816 | if (flag) { | ||
817 | /* Add last triplet */ | ||
818 | lbs_deb_11d("11D triplet (%d, %d, %d)\n", first_channel, | ||
819 | num_parsed_chan, max_pwr); | ||
820 | t = &domain->triplet[num_triplet]; | ||
821 | t->chans.first_channel = first_channel; | ||
822 | t->chans.num_channels = num_parsed_chan; | ||
823 | t->chans.max_power = max_pwr; | ||
824 | num_triplet++; | ||
825 | } | ||
826 | } | ||
827 | |||
828 | lbs_deb_11d("# triplets %d\n", num_triplet); | ||
829 | |||
830 | /* Set command header sizes */ | ||
831 | triplet_size = num_triplet * sizeof(struct ieee80211_country_ie_triplet); | ||
832 | domain->header.len = cpu_to_le16(sizeof(domain->country_code) + | ||
833 | triplet_size); | ||
834 | |||
835 | lbs_deb_hex(LBS_DEB_11D, "802.11D domain param set", | ||
836 | (u8 *) &cmd.domain.country_code, | ||
837 | le16_to_cpu(domain->header.len)); | ||
838 | |||
839 | cmd.hdr.size = cpu_to_le16(sizeof(cmd.hdr) + | ||
840 | sizeof(cmd.action) + | ||
841 | sizeof(cmd.domain.header) + | ||
842 | sizeof(cmd.domain.country_code) + | ||
843 | triplet_size); | ||
844 | |||
845 | ret = lbs_cmd_with_response(priv, CMD_802_11D_DOMAIN_INFO, &cmd); | ||
846 | |||
847 | lbs_deb_leave_args(LBS_DEB_11D, "ret %d", ret); | ||
848 | return ret; | ||
849 | } | ||
850 | |||
728 | static int lbs_cmd_reg_access(struct cmd_ds_command *cmdptr, | 851 | static int lbs_cmd_reg_access(struct cmd_ds_command *cmdptr, |
729 | u8 cmd_action, void *pdata_buf) | 852 | u8 cmd_action, void *pdata_buf) |
730 | { | 853 | { |
@@ -1006,66 +1129,6 @@ void lbs_set_mac_control(struct lbs_private *priv) | |||
1006 | } | 1129 | } |
1007 | 1130 | ||
1008 | /** | 1131 | /** |
1009 | * @brief This function implements command CMD_802_11D_DOMAIN_INFO | ||
1010 | * @param priv pointer to struct lbs_private | ||
1011 | * @param cmd pointer to cmd buffer | ||
1012 | * @param cmdno cmd ID | ||
1013 | * @param cmdOption cmd action | ||
1014 | * @return 0 | ||
1015 | */ | ||
1016 | int lbs_cmd_802_11d_domain_info(struct lbs_private *priv, | ||
1017 | struct cmd_ds_command *cmd, | ||
1018 | u16 cmdoption) | ||
1019 | { | ||
1020 | struct cmd_ds_802_11d_domain_info *pdomaininfo = | ||
1021 | &cmd->params.domaininfo; | ||
1022 | struct mrvl_ie_domain_param_set *domain = &pdomaininfo->domain; | ||
1023 | u8 nr_triplet = priv->domain_reg.no_triplet; | ||
1024 | |||
1025 | lbs_deb_enter(LBS_DEB_11D); | ||
1026 | |||
1027 | lbs_deb_11d("nr_triplet=%x\n", nr_triplet); | ||
1028 | |||
1029 | pdomaininfo->action = cpu_to_le16(cmdoption); | ||
1030 | if (cmdoption == CMD_ACT_GET) { | ||
1031 | cmd->size = cpu_to_le16(sizeof(pdomaininfo->action) + | ||
1032 | sizeof(struct cmd_header)); | ||
1033 | lbs_deb_hex(LBS_DEB_11D, "802_11D_DOMAIN_INFO", (u8 *) cmd, | ||
1034 | le16_to_cpu(cmd->size)); | ||
1035 | goto done; | ||
1036 | } | ||
1037 | |||
1038 | domain->header.type = cpu_to_le16(TLV_TYPE_DOMAIN); | ||
1039 | memcpy(domain->countrycode, priv->domain_reg.country_code, | ||
1040 | sizeof(domain->countrycode)); | ||
1041 | |||
1042 | domain->header.len = cpu_to_le16(nr_triplet | ||
1043 | * sizeof(struct ieee80211_country_ie_triplet) | ||
1044 | + sizeof(domain->countrycode)); | ||
1045 | |||
1046 | if (nr_triplet) { | ||
1047 | memcpy(domain->triplet, priv->domain_reg.triplet, | ||
1048 | nr_triplet * | ||
1049 | sizeof(struct ieee80211_country_ie_triplet)); | ||
1050 | |||
1051 | cmd->size = cpu_to_le16(sizeof(pdomaininfo->action) + | ||
1052 | le16_to_cpu(domain->header.len) + | ||
1053 | sizeof(struct mrvl_ie_header) + | ||
1054 | sizeof(struct cmd_header)); | ||
1055 | } else { | ||
1056 | cmd->size = cpu_to_le16(sizeof(pdomaininfo->action) + | ||
1057 | sizeof(struct cmd_header)); | ||
1058 | } | ||
1059 | |||
1060 | lbs_deb_hex(LBS_DEB_11D, "802_11D_DOMAIN_INFO", (u8 *) cmd, | ||
1061 | le16_to_cpu(cmd->size)); | ||
1062 | |||
1063 | done: | ||
1064 | lbs_deb_enter(LBS_DEB_11D); | ||
1065 | return 0; | ||
1066 | } | ||
1067 | |||
1068 | /** | ||
1069 | * @brief This function prepare the command before send to firmware. | 1132 | * @brief This function prepare the command before send to firmware. |
1070 | * | 1133 | * |
1071 | * @param priv A pointer to struct lbs_private structure | 1134 | * @param priv A pointer to struct lbs_private structure |
@@ -1154,11 +1217,6 @@ int lbs_prepare_and_send_command(struct lbs_private *priv, | |||
1154 | ret = 0; | 1217 | ret = 0; |
1155 | goto done; | 1218 | goto done; |
1156 | 1219 | ||
1157 | case CMD_802_11D_DOMAIN_INFO: | ||
1158 | cmdptr->command = cpu_to_le16(cmd_no); | ||
1159 | ret = lbs_cmd_802_11d_domain_info(priv, cmdptr, cmd_action); | ||
1160 | break; | ||
1161 | |||
1162 | case CMD_802_11_TPC_CFG: | 1220 | case CMD_802_11_TPC_CFG: |
1163 | cmdptr->command = cpu_to_le16(CMD_802_11_TPC_CFG); | 1221 | cmdptr->command = cpu_to_le16(CMD_802_11_TPC_CFG); |
1164 | cmdptr->size = | 1222 | cmdptr->size = |