uap_cmd.c revision 12190c5d80bd3c880c76fdaee5a56314ff0bd256
1/* 2 * Marvell Wireless LAN device driver: AP specific command handling 3 * 4 * Copyright (C) 2012, Marvell International Ltd. 5 * 6 * This software file (the "File") is distributed by Marvell International 7 * Ltd. under the terms of the GNU General Public License Version 2, June 1991 8 * (the "License"). You may use, redistribute and/or modify this File in 9 * accordance with the terms and conditions of the License, a copy of which 10 * is available by writing to the Free Software Foundation, Inc., 11 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the 12 * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt. 13 * 14 * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE 15 * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE 16 * ARE EXPRESSLY DISCLAIMED. The License provides additional details about 17 * this warranty disclaimer. 18 */ 19 20#include "main.h" 21 22/* This function initializes some of mwifiex_uap_bss_param variables. 23 * This helps FW in ignoring invalid values. These values may or may not 24 * be get updated to valid ones at later stage. 25 */ 26void mwifiex_set_sys_config_invalid_data(struct mwifiex_uap_bss_param *config) 27{ 28 config->rts_threshold = 0x7FFF; 29 config->frag_threshold = 0x7FFF; 30 config->retry_limit = 0x7F; 31} 32 33/* Parse AP config structure and prepare TLV based command structure 34 * to be sent to FW for uAP configuration 35 */ 36static int mwifiex_cmd_uap_sys_config(struct host_cmd_ds_command *cmd, 37 u16 cmd_action, void *cmd_buf) 38{ 39 u8 *tlv; 40 struct host_cmd_ds_sys_config *sys_config = &cmd->params.uap_sys_config; 41 struct host_cmd_tlv_dtim_period *dtim_period; 42 struct host_cmd_tlv_beacon_period *beacon_period; 43 struct host_cmd_tlv_ssid *ssid; 44 struct host_cmd_tlv_channel_band *chan_band; 45 struct host_cmd_tlv_frag_threshold *frag_threshold; 46 struct host_cmd_tlv_rts_threshold *rts_threshold; 47 struct host_cmd_tlv_retry_limit *retry_limit; 48 struct mwifiex_uap_bss_param *bss_cfg = cmd_buf; 49 u16 cmd_size; 50 51 cmd->command = cpu_to_le16(HostCmd_CMD_UAP_SYS_CONFIG); 52 cmd_size = (u16)(sizeof(struct host_cmd_ds_sys_config) + S_DS_GEN); 53 54 sys_config->action = cpu_to_le16(cmd_action); 55 56 tlv = sys_config->tlv; 57 58 if (bss_cfg->ssid.ssid_len) { 59 ssid = (struct host_cmd_tlv_ssid *)tlv; 60 ssid->tlv.type = cpu_to_le16(TLV_TYPE_UAP_SSID); 61 ssid->tlv.len = cpu_to_le16((u16)bss_cfg->ssid.ssid_len); 62 memcpy(ssid->ssid, bss_cfg->ssid.ssid, bss_cfg->ssid.ssid_len); 63 cmd_size += sizeof(struct host_cmd_tlv) + 64 bss_cfg->ssid.ssid_len; 65 tlv += sizeof(struct host_cmd_tlv) + bss_cfg->ssid.ssid_len; 66 } 67 if (bss_cfg->channel && bss_cfg->channel <= MAX_CHANNEL_BAND_BG) { 68 chan_band = (struct host_cmd_tlv_channel_band *)tlv; 69 chan_band->tlv.type = cpu_to_le16(TLV_TYPE_CHANNELBANDLIST); 70 chan_band->tlv.len = 71 cpu_to_le16(sizeof(struct host_cmd_tlv_channel_band) - 72 sizeof(struct host_cmd_tlv)); 73 chan_band->band_config = bss_cfg->band_cfg; 74 chan_band->channel = bss_cfg->channel; 75 cmd_size += sizeof(struct host_cmd_tlv_channel_band); 76 tlv += sizeof(struct host_cmd_tlv_channel_band); 77 } 78 if (bss_cfg->beacon_period >= MIN_BEACON_PERIOD && 79 bss_cfg->beacon_period <= MAX_BEACON_PERIOD) { 80 beacon_period = (struct host_cmd_tlv_beacon_period *)tlv; 81 beacon_period->tlv.type = 82 cpu_to_le16(TLV_TYPE_UAP_BEACON_PERIOD); 83 beacon_period->tlv.len = 84 cpu_to_le16(sizeof(struct host_cmd_tlv_beacon_period) - 85 sizeof(struct host_cmd_tlv)); 86 beacon_period->period = cpu_to_le16(bss_cfg->beacon_period); 87 cmd_size += sizeof(struct host_cmd_tlv_beacon_period); 88 tlv += sizeof(struct host_cmd_tlv_beacon_period); 89 } 90 if (bss_cfg->dtim_period >= MIN_DTIM_PERIOD && 91 bss_cfg->dtim_period <= MAX_DTIM_PERIOD) { 92 dtim_period = (struct host_cmd_tlv_dtim_period *)tlv; 93 dtim_period->tlv.type = cpu_to_le16(TLV_TYPE_UAP_DTIM_PERIOD); 94 dtim_period->tlv.len = 95 cpu_to_le16(sizeof(struct host_cmd_tlv_dtim_period) - 96 sizeof(struct host_cmd_tlv)); 97 dtim_period->period = bss_cfg->dtim_period; 98 cmd_size += sizeof(struct host_cmd_tlv_dtim_period); 99 tlv += sizeof(struct host_cmd_tlv_dtim_period); 100 } 101 if (bss_cfg->rts_threshold <= MWIFIEX_RTS_MAX_VALUE) { 102 rts_threshold = (struct host_cmd_tlv_rts_threshold *)tlv; 103 rts_threshold->tlv.type = 104 cpu_to_le16(TLV_TYPE_UAP_RTS_THRESHOLD); 105 rts_threshold->tlv.len = 106 cpu_to_le16(sizeof(struct host_cmd_tlv_rts_threshold) - 107 sizeof(struct host_cmd_tlv)); 108 rts_threshold->rts_thr = cpu_to_le16(bss_cfg->rts_threshold); 109 cmd_size += sizeof(struct host_cmd_tlv_frag_threshold); 110 tlv += sizeof(struct host_cmd_tlv_frag_threshold); 111 } 112 if ((bss_cfg->frag_threshold >= MWIFIEX_FRAG_MIN_VALUE) && 113 (bss_cfg->frag_threshold <= MWIFIEX_FRAG_MAX_VALUE)) { 114 frag_threshold = (struct host_cmd_tlv_frag_threshold *)tlv; 115 frag_threshold->tlv.type = 116 cpu_to_le16(TLV_TYPE_UAP_FRAG_THRESHOLD); 117 frag_threshold->tlv.len = 118 cpu_to_le16(sizeof(struct host_cmd_tlv_frag_threshold) - 119 sizeof(struct host_cmd_tlv)); 120 frag_threshold->frag_thr = cpu_to_le16(bss_cfg->frag_threshold); 121 cmd_size += sizeof(struct host_cmd_tlv_frag_threshold); 122 tlv += sizeof(struct host_cmd_tlv_frag_threshold); 123 } 124 if (bss_cfg->retry_limit <= MWIFIEX_RETRY_LIMIT) { 125 retry_limit = (struct host_cmd_tlv_retry_limit *)tlv; 126 retry_limit->tlv.type = cpu_to_le16(TLV_TYPE_UAP_RETRY_LIMIT); 127 retry_limit->tlv.len = 128 cpu_to_le16(sizeof(struct host_cmd_tlv_retry_limit) - 129 sizeof(struct host_cmd_tlv)); 130 retry_limit->limit = (u8)bss_cfg->retry_limit; 131 cmd_size += sizeof(struct host_cmd_tlv_retry_limit); 132 tlv += sizeof(struct host_cmd_tlv_retry_limit); 133 } 134 135 cmd->size = cpu_to_le16(cmd_size); 136 return 0; 137} 138 139/* This function prepares the AP specific commands before sending them 140 * to the firmware. 141 * This is a generic function which calls specific command preparation 142 * routines based upon the command number. 143 */ 144int mwifiex_uap_prepare_cmd(struct mwifiex_private *priv, u16 cmd_no, 145 u16 cmd_action, u32 cmd_oid, 146 void *data_buf, void *cmd_buf) 147{ 148 struct host_cmd_ds_command *cmd = cmd_buf; 149 150 switch (cmd_no) { 151 case HostCmd_CMD_UAP_SYS_CONFIG: 152 if (mwifiex_cmd_uap_sys_config(cmd, cmd_action, data_buf)) 153 return -1; 154 break; 155 case HostCmd_CMD_UAP_BSS_START: 156 case HostCmd_CMD_UAP_BSS_STOP: 157 cmd->command = cpu_to_le16(cmd_no); 158 cmd->size = cpu_to_le16(S_DS_GEN); 159 break; 160 default: 161 dev_err(priv->adapter->dev, 162 "PREP_CMD: unknown cmd %#x\n", cmd_no); 163 return -1; 164 } 165 166 return 0; 167} 168 169/* This function sets the RF channel for AP. 170 * 171 * This function populates channel information in AP config structure 172 * and sends command to configure channel information in AP. 173 */ 174int mwifiex_uap_set_channel(struct mwifiex_private *priv, int channel) 175{ 176 struct mwifiex_uap_bss_param *bss_cfg; 177 struct wiphy *wiphy = priv->wdev->wiphy; 178 179 bss_cfg = kzalloc(sizeof(struct mwifiex_uap_bss_param), GFP_KERNEL); 180 if (!bss_cfg) 181 return -ENOMEM; 182 183 bss_cfg->band_cfg = BAND_CONFIG_MANUAL; 184 bss_cfg->channel = channel; 185 186 if (mwifiex_send_cmd_async(priv, HostCmd_CMD_UAP_SYS_CONFIG, 187 HostCmd_ACT_GEN_SET, 0, bss_cfg)) { 188 wiphy_err(wiphy, "Failed to set the uAP channel\n"); 189 kfree(bss_cfg); 190 return -1; 191 } 192 193 kfree(bss_cfg); 194 return 0; 195} 196