diff options
Diffstat (limited to 'drivers/net/wireless/mwifiex')
-rw-r--r-- | drivers/net/wireless/mwifiex/11n.c | 38 | ||||
-rw-r--r-- | drivers/net/wireless/mwifiex/11n.h | 5 | ||||
-rw-r--r-- | drivers/net/wireless/mwifiex/cfg80211.c | 51 | ||||
-rw-r--r-- | drivers/net/wireless/mwifiex/cmdevt.c | 15 | ||||
-rw-r--r-- | drivers/net/wireless/mwifiex/fw.h | 8 | ||||
-rw-r--r-- | drivers/net/wireless/mwifiex/init.c | 6 | ||||
-rw-r--r-- | drivers/net/wireless/mwifiex/ioctl.h | 7 | ||||
-rw-r--r-- | drivers/net/wireless/mwifiex/main.c | 1 | ||||
-rw-r--r-- | drivers/net/wireless/mwifiex/main.h | 9 | ||||
-rw-r--r-- | drivers/net/wireless/mwifiex/scan.c | 4 | ||||
-rw-r--r-- | drivers/net/wireless/mwifiex/sta_cmd.c | 3 | ||||
-rw-r--r-- | drivers/net/wireless/mwifiex/sta_cmdresp.c | 38 | ||||
-rw-r--r-- | drivers/net/wireless/mwifiex/sta_ioctl.c | 40 | ||||
-rw-r--r-- | drivers/net/wireless/mwifiex/txrx.c | 6 | ||||
-rw-r--r-- | drivers/net/wireless/mwifiex/uap_cmd.c | 39 | ||||
-rw-r--r-- | drivers/net/wireless/mwifiex/uap_txrx.c | 70 | ||||
-rw-r--r-- | drivers/net/wireless/mwifiex/wmm.c | 9 |
17 files changed, 256 insertions, 93 deletions
diff --git a/drivers/net/wireless/mwifiex/11n.c b/drivers/net/wireless/mwifiex/11n.c index d2732736f864..245a371f1a43 100644 --- a/drivers/net/wireless/mwifiex/11n.c +++ b/drivers/net/wireless/mwifiex/11n.c @@ -176,23 +176,6 @@ int mwifiex_ret_11n_addba_req(struct mwifiex_private *priv, } /* - * This function handles the command response of 11n configuration request. - * - * Handling includes changing the header fields into CPU format. - */ -int mwifiex_ret_11n_cfg(struct host_cmd_ds_command *resp, - struct mwifiex_ds_11n_tx_cfg *tx_cfg) -{ - struct host_cmd_ds_11n_cfg *htcfg = &resp->params.htcfg; - - if (tx_cfg) { - tx_cfg->tx_htcap = le16_to_cpu(htcfg->ht_tx_cap); - tx_cfg->tx_htinfo = le16_to_cpu(htcfg->ht_tx_info); - } - return 0; -} - -/* * This function prepares command of reconfigure Tx buffer. * * Preparation includes - @@ -258,27 +241,6 @@ int mwifiex_cmd_amsdu_aggr_ctrl(struct host_cmd_ds_command *cmd, } /* - * This function handles the command response of AMSDU aggregation - * control request. - * - * Handling includes changing the header fields into CPU format. - */ -int mwifiex_ret_amsdu_aggr_ctrl(struct host_cmd_ds_command *resp, - struct mwifiex_ds_11n_amsdu_aggr_ctrl - *amsdu_aggr_ctrl) -{ - struct host_cmd_ds_amsdu_aggr_ctrl *amsdu_ctrl = - &resp->params.amsdu_aggr_ctrl; - - if (amsdu_aggr_ctrl) { - amsdu_aggr_ctrl->enable = le16_to_cpu(amsdu_ctrl->enable); - amsdu_aggr_ctrl->curr_buf_size = - le16_to_cpu(amsdu_ctrl->curr_buf_size); - } - return 0; -} - -/* * This function prepares 11n configuration command. * * Preparation includes - diff --git a/drivers/net/wireless/mwifiex/11n.h b/drivers/net/wireless/mwifiex/11n.h index 67c087cf9dc7..46006a54a656 100644 --- a/drivers/net/wireless/mwifiex/11n.h +++ b/drivers/net/wireless/mwifiex/11n.h @@ -28,8 +28,6 @@ int mwifiex_ret_11n_delba(struct mwifiex_private *priv, struct host_cmd_ds_command *resp); int mwifiex_ret_11n_addba_req(struct mwifiex_private *priv, struct host_cmd_ds_command *resp); -int mwifiex_ret_11n_cfg(struct host_cmd_ds_command *resp, - struct mwifiex_ds_11n_tx_cfg *tx_cfg); int mwifiex_cmd_11n_cfg(struct host_cmd_ds_command *cmd, u16 cmd_action, struct mwifiex_ds_11n_tx_cfg *txcfg); @@ -60,9 +58,6 @@ int mwifiex_get_rx_reorder_tbl(struct mwifiex_private *priv, struct mwifiex_ds_rx_reorder_tbl *buf); int mwifiex_get_tx_ba_stream_tbl(struct mwifiex_private *priv, struct mwifiex_ds_tx_ba_stream_tbl *buf); -int mwifiex_ret_amsdu_aggr_ctrl(struct host_cmd_ds_command *resp, - struct mwifiex_ds_11n_amsdu_aggr_ctrl - *amsdu_aggr_ctrl); int mwifiex_cmd_recfg_tx_buf(struct mwifiex_private *priv, struct host_cmd_ds_command *cmd, int cmd_action, u16 *buf_size); diff --git a/drivers/net/wireless/mwifiex/cfg80211.c b/drivers/net/wireless/mwifiex/cfg80211.c index e57f543413de..b9f7b3e6912d 100644 --- a/drivers/net/wireless/mwifiex/cfg80211.c +++ b/drivers/net/wireless/mwifiex/cfg80211.c @@ -37,6 +37,36 @@ static const struct ieee80211_iface_combination mwifiex_iface_comb_ap_sta = { .beacon_int_infra_match = true, }; +static const struct ieee80211_regdomain mwifiex_world_regdom_custom = { + .n_reg_rules = 7, + .alpha2 = "99", + .reg_rules = { + /* Channel 1 - 11 */ + REG_RULE(2412-10, 2462+10, 40, 3, 20, 0), + /* Channel 12 - 13 */ + REG_RULE(2467-10, 2472+10, 20, 3, 20, + NL80211_RRF_PASSIVE_SCAN | NL80211_RRF_NO_IBSS), + /* Channel 14 */ + REG_RULE(2484-10, 2484+10, 20, 3, 20, + NL80211_RRF_PASSIVE_SCAN | NL80211_RRF_NO_IBSS | + NL80211_RRF_NO_OFDM), + /* Channel 36 - 48 */ + REG_RULE(5180-10, 5240+10, 40, 3, 20, + NL80211_RRF_PASSIVE_SCAN | NL80211_RRF_NO_IBSS), + /* Channel 149 - 165 */ + REG_RULE(5745-10, 5825+10, 40, 3, 20, + NL80211_RRF_PASSIVE_SCAN | NL80211_RRF_NO_IBSS), + /* Channel 52 - 64 */ + REG_RULE(5260-10, 5320+10, 40, 3, 30, + NL80211_RRF_PASSIVE_SCAN | NL80211_RRF_NO_IBSS | + NL80211_RRF_DFS), + /* Channel 100 - 140 */ + REG_RULE(5500-10, 5700+10, 40, 3, 30, + NL80211_RRF_PASSIVE_SCAN | NL80211_RRF_NO_IBSS | + NL80211_RRF_DFS), + } +}; + /* * This function maps the nl802.11 channel type into driver channel type. * @@ -969,15 +999,18 @@ static int mwifiex_cfg80211_start_ap(struct wiphy *wiphy, bss_cfg->channel = (u8)ieee80211_frequency_to_channel(params->channel->center_freq); - bss_cfg->band_cfg = BAND_CONFIG_MANUAL; /* Set appropriate bands */ if (params->channel->band == IEEE80211_BAND_2GHZ) { + bss_cfg->band_cfg = BAND_CONFIG_BG; + if (params->channel_type == NL80211_CHAN_NO_HT) config_bands = BAND_B | BAND_G; else config_bands = BAND_B | BAND_G | BAND_GN; } else { + bss_cfg->band_cfg = BAND_CONFIG_A; + if (params->channel_type == NL80211_CHAN_NO_HT) config_bands = BAND_A; else @@ -988,6 +1021,7 @@ static int mwifiex_cfg80211_start_ap(struct wiphy *wiphy, ~priv->adapter->fw_bands)) priv->adapter->config_bands = config_bands; + mwifiex_set_uap_rates(bss_cfg, params); mwifiex_send_domain_info_cmd_fw(wiphy); if (mwifiex_set_secure_params(priv, bss_cfg, params)) { @@ -1153,7 +1187,6 @@ mwifiex_cfg80211_assoc(struct mwifiex_private *priv, size_t ssid_len, u8 *ssid, ~priv->adapter->fw_bands)) priv->adapter->config_bands = config_bands; } - mwifiex_send_domain_info_cmd_fw(priv->wdev->wiphy); } /* As this is new association, clear locally stored @@ -1637,7 +1670,7 @@ struct wireless_dev *mwifiex_add_virtual_intf(struct wiphy *wiphy, priv->bss_type = MWIFIEX_BSS_TYPE_STA; priv->frame_type = MWIFIEX_DATA_FRAME_TYPE_ETH_II; - priv->bss_priority = MWIFIEX_BSS_ROLE_STA; + priv->bss_priority = 0; priv->bss_role = MWIFIEX_BSS_ROLE_STA; priv->bss_num = 0; @@ -1660,7 +1693,7 @@ struct wireless_dev *mwifiex_add_virtual_intf(struct wiphy *wiphy, priv->bss_type = MWIFIEX_BSS_TYPE_UAP; priv->frame_type = MWIFIEX_DATA_FRAME_TYPE_ETH_II; - priv->bss_priority = MWIFIEX_BSS_ROLE_UAP; + priv->bss_priority = 0; priv->bss_role = MWIFIEX_BSS_ROLE_UAP; priv->bss_started = 0; priv->bss_num = 0; @@ -1830,7 +1863,10 @@ int mwifiex_register_cfg80211(struct mwifiex_adapter *adapter) memcpy(wiphy->perm_addr, priv->curr_addr, ETH_ALEN); wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM; wiphy->flags |= WIPHY_FLAG_HAVE_AP_SME | - WIPHY_FLAG_AP_PROBE_RESP_OFFLOAD; + WIPHY_FLAG_AP_PROBE_RESP_OFFLOAD | + WIPHY_FLAG_CUSTOM_REGULATORY; + + wiphy_apply_custom_regulatory(wiphy, &mwifiex_world_regdom_custom); wiphy->probe_resp_offload = NL80211_PROBE_RESP_OFFLOAD_SUPPORT_WPS | NL80211_PROBE_RESP_OFFLOAD_SUPPORT_WPS2; @@ -1859,8 +1895,9 @@ int mwifiex_register_cfg80211(struct mwifiex_adapter *adapter) return ret; } country_code = mwifiex_11d_code_2_region(priv->adapter->region_code); - if (country_code && regulatory_hint(wiphy, country_code)) - dev_err(adapter->dev, "regulatory_hint() failed\n"); + if (country_code) + dev_info(adapter->dev, + "ignoring F/W country code %2.2s\n", country_code); adapter->wiphy = wiphy; return ret; diff --git a/drivers/net/wireless/mwifiex/cmdevt.c b/drivers/net/wireless/mwifiex/cmdevt.c index c229dddcf1c2..225c1a4feeba 100644 --- a/drivers/net/wireless/mwifiex/cmdevt.c +++ b/drivers/net/wireless/mwifiex/cmdevt.c @@ -170,7 +170,20 @@ static int mwifiex_dnld_cmd_to_fw(struct mwifiex_private *priv, cmd_code = le16_to_cpu(host_cmd->command); cmd_size = le16_to_cpu(host_cmd->size); - skb_trim(cmd_node->cmd_skb, cmd_size); + /* Adjust skb length */ + if (cmd_node->cmd_skb->len > cmd_size) + /* + * cmd_size is less than sizeof(struct host_cmd_ds_command). + * Trim off the unused portion. + */ + skb_trim(cmd_node->cmd_skb, cmd_size); + else if (cmd_node->cmd_skb->len < cmd_size) + /* + * cmd_size is larger than sizeof(struct host_cmd_ds_command) + * because we have appended custom IE TLV. Increase skb length + * accordingly. + */ + skb_put(cmd_node->cmd_skb, cmd_size - cmd_node->cmd_skb->len); do_gettimeofday(&tstamp); dev_dbg(adapter->dev, "cmd: DNLD_CMD: (%lu.%lu): %#x, act %#x, len %d," diff --git a/drivers/net/wireless/mwifiex/fw.h b/drivers/net/wireless/mwifiex/fw.h index ae06f31c6838..b8ce78e2ba47 100644 --- a/drivers/net/wireless/mwifiex/fw.h +++ b/drivers/net/wireless/mwifiex/fw.h @@ -108,6 +108,7 @@ enum MWIFIEX_802_11_PRIVACY_FILTER { #define MGMT_MASK_BEACON 0x100 #define TLV_TYPE_UAP_SSID 0x0000 +#define TLV_TYPE_UAP_RATES 0x0001 #define PROPRIETARY_TLV_BASE_ID 0x0100 #define TLV_TYPE_KEY_MATERIAL (PROPRIETARY_TLV_BASE_ID + 0) @@ -309,7 +310,7 @@ enum ENH_PS_MODES { #define HostCmd_SCAN_RADIO_TYPE_A 1 #define HOST_SLEEP_CFG_CANCEL 0xffffffff -#define HOST_SLEEP_CFG_COND_DEF 0x0000000f +#define HOST_SLEEP_CFG_COND_DEF 0x00000000 #define HOST_SLEEP_CFG_GPIO_DEF 0xff #define HOST_SLEEP_CFG_GAP_DEF 0 @@ -1284,6 +1285,11 @@ struct host_cmd_tlv_ssid { u8 ssid[0]; } __packed; +struct host_cmd_tlv_rates { + struct host_cmd_tlv tlv; + u8 rates[0]; +} __packed; + struct host_cmd_tlv_bcast_ssid { struct host_cmd_tlv tlv; u8 bcast_ctl; diff --git a/drivers/net/wireless/mwifiex/init.c b/drivers/net/wireless/mwifiex/init.c index fad2c8d2bdde..9c1549ee4c09 100644 --- a/drivers/net/wireless/mwifiex/init.c +++ b/drivers/net/wireless/mwifiex/init.c @@ -73,7 +73,6 @@ static void scan_delay_timer_fn(unsigned long data) list_for_each_entry_safe(cmd_node, tmp_node, &adapter->scan_pending_q, list) { list_del(&cmd_node->list); - cmd_node->wait_q_enabled = false; mwifiex_insert_cmd_to_free_q(adapter, cmd_node); } spin_unlock_irqrestore(&adapter->scan_pending_q_lock, flags); @@ -92,6 +91,11 @@ static void scan_delay_timer_fn(unsigned long data) kfree(priv->user_scan_cfg); priv->user_scan_cfg = NULL; } + + if (priv->scan_pending_on_block) { + priv->scan_pending_on_block = false; + up(&priv->async_sem); + } goto done; } diff --git a/drivers/net/wireless/mwifiex/ioctl.h b/drivers/net/wireless/mwifiex/ioctl.h index 6a5eded3be10..8688535e95eb 100644 --- a/drivers/net/wireless/mwifiex/ioctl.h +++ b/drivers/net/wireless/mwifiex/ioctl.h @@ -81,7 +81,11 @@ struct wep_key { #define KEY_MGMT_ON_HOST 0x03 #define MWIFIEX_AUTH_MODE_AUTO 0xFF -#define BAND_CONFIG_MANUAL 0x00 +#define BAND_CONFIG_BG 0x00 +#define BAND_CONFIG_A 0x01 +#define MWIFIEX_SUPPORTED_RATES 14 +#define MWIFIEX_SUPPORTED_RATES_EXT 32 + struct mwifiex_uap_bss_param { u8 channel; u8 band_cfg; @@ -100,6 +104,7 @@ struct mwifiex_uap_bss_param { struct wpa_param wpa_cfg; struct wep_key wep_cfg[NUM_WEP_KEYS]; struct ieee80211_ht_cap ht_cap; + u8 rates[MWIFIEX_SUPPORTED_RATES]; }; enum { diff --git a/drivers/net/wireless/mwifiex/main.c b/drivers/net/wireless/mwifiex/main.c index cb1155286e0f..bfd6667be01e 100644 --- a/drivers/net/wireless/mwifiex/main.c +++ b/drivers/net/wireless/mwifiex/main.c @@ -72,7 +72,6 @@ static int mwifiex_register(void *card, struct mwifiex_if_ops *if_ops, goto error; adapter->priv[i]->adapter = adapter; - adapter->priv[i]->bss_priority = i; adapter->priv_num++; } mwifiex_init_lock_list(adapter); diff --git a/drivers/net/wireless/mwifiex/main.h b/drivers/net/wireless/mwifiex/main.h index 994bc4fc263e..12ceea47b4b4 100644 --- a/drivers/net/wireless/mwifiex/main.h +++ b/drivers/net/wireless/mwifiex/main.h @@ -116,6 +116,7 @@ enum { #define MAX_BITMAP_RATES_SIZE 10 #define MAX_CHANNEL_BAND_BG 14 +#define MAX_CHANNEL_BAND_A 165 #define MAX_FREQUENCY_BAND_BG 2484 @@ -249,10 +250,6 @@ struct ieee_types_header { u8 len; } __packed; -#define MWIFIEX_SUPPORTED_RATES 14 - -#define MWIFIEX_SUPPORTED_RATES_EXT 32 - struct ieee_types_vendor_specific { struct ieee_types_vendor_header vend_hdr; u8 data[IEEE_MAX_IE_SIZE - sizeof(struct ieee_types_vendor_header)]; @@ -487,6 +484,7 @@ struct mwifiex_private { s32 cqm_rssi_thold; u32 cqm_rssi_hyst; u8 subsc_evt_rssi_state; + struct mwifiex_ds_misc_subsc_evt async_subsc_evt_storage; struct mwifiex_ie mgmt_ie[MAX_MGMT_IE_INDEX]; u16 beacon_idx; u16 proberesp_idx; @@ -814,6 +812,7 @@ struct mwifiex_sta_node * mwifiex_get_sta_entry(struct mwifiex_private *priv, u8 *mac); void mwifiex_delete_all_station_list(struct mwifiex_private *priv); void *mwifiex_process_sta_txpd(struct mwifiex_private *, struct sk_buff *skb); +void *mwifiex_process_uap_txpd(struct mwifiex_private *, struct sk_buff *skb); int mwifiex_sta_init_cmd(struct mwifiex_private *, u8 first_sta); int mwifiex_cmd_802_11_scan(struct host_cmd_ds_command *cmd, struct mwifiex_scan_cmd_config *scan_cfg); @@ -872,6 +871,8 @@ int mwifiex_set_secure_params(struct mwifiex_private *priv, void mwifiex_set_ht_params(struct mwifiex_private *priv, struct mwifiex_uap_bss_param *bss_cfg, struct cfg80211_ap_settings *params); +void mwifiex_set_uap_rates(struct mwifiex_uap_bss_param *bss_cfg, + struct cfg80211_ap_settings *params); /* * This function checks if the queuing is RA based or not. diff --git a/drivers/net/wireless/mwifiex/scan.c b/drivers/net/wireless/mwifiex/scan.c index 215d07e6c462..9e077e5fc64a 100644 --- a/drivers/net/wireless/mwifiex/scan.c +++ b/drivers/net/wireless/mwifiex/scan.c @@ -726,7 +726,6 @@ mwifiex_config_scan(struct mwifiex_private *priv, struct mwifiex_ie_types_num_probes *num_probes_tlv; struct mwifiex_ie_types_wildcard_ssid_params *wildcard_ssid_tlv; struct mwifiex_ie_types_rates_param_set *rates_tlv; - const u8 zero_mac[ETH_ALEN] = { 0, 0, 0, 0, 0, 0 }; u8 *tlv_pos; u32 num_probes; u32 ssid_len; @@ -840,8 +839,7 @@ mwifiex_config_scan(struct mwifiex_private *priv, * or BSSID filter applied to the scan results in the firmware. */ if ((i && ssid_filter) || - memcmp(scan_cfg_out->specific_bssid, &zero_mac, - sizeof(zero_mac))) + !is_zero_ether_addr(scan_cfg_out->specific_bssid)) *filtered_scan = true; } else { scan_cfg_out->bss_mode = (u8) adapter->scan_mode; diff --git a/drivers/net/wireless/mwifiex/sta_cmd.c b/drivers/net/wireless/mwifiex/sta_cmd.c index 0cc3406050dc..3a4161cfeed7 100644 --- a/drivers/net/wireless/mwifiex/sta_cmd.c +++ b/drivers/net/wireless/mwifiex/sta_cmd.c @@ -551,7 +551,6 @@ mwifiex_cmd_802_11_key_material(struct mwifiex_private *priv, struct host_cmd_tlv_mac_addr *tlv_mac; u16 key_param_len = 0, cmd_size; int ret = 0; - const u8 bc_mac[] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; cmd->command = cpu_to_le16(HostCmd_CMD_802_11_KEY_MATERIAL); key_material->action = cpu_to_le16(cmd_action); @@ -593,7 +592,7 @@ mwifiex_cmd_802_11_key_material(struct mwifiex_private *priv, /* set 0 when re-key */ key_material->key_param_set.key[1] = 0; - if (0 != memcmp(enc_key->mac_addr, bc_mac, sizeof(bc_mac))) { + if (!is_broadcast_ether_addr(enc_key->mac_addr)) { /* WAPI pairwise key: unicast */ key_material->key_param_set.key_info |= cpu_to_le16(KEY_UNICAST); diff --git a/drivers/net/wireless/mwifiex/sta_cmdresp.c b/drivers/net/wireless/mwifiex/sta_cmdresp.c index 0b09004ebb25..31f80e10e29e 100644 --- a/drivers/net/wireless/mwifiex/sta_cmdresp.c +++ b/drivers/net/wireless/mwifiex/sta_cmdresp.c @@ -123,7 +123,8 @@ static int mwifiex_ret_802_11_rssi_info(struct mwifiex_private *priv, { struct host_cmd_ds_802_11_rssi_info_rsp *rssi_info_rsp = &resp->params.rssi_info_rsp; - struct mwifiex_ds_misc_subsc_evt subsc_evt; + struct mwifiex_ds_misc_subsc_evt *subsc_evt = + &priv->async_subsc_evt_storage; priv->data_rssi_last = le16_to_cpu(rssi_info_rsp->data_rssi_last); priv->data_nf_last = le16_to_cpu(rssi_info_rsp->data_nf_last); @@ -140,26 +141,27 @@ static int mwifiex_ret_802_11_rssi_info(struct mwifiex_private *priv, if (priv->subsc_evt_rssi_state == EVENT_HANDLED) return 0; + memset(subsc_evt, 0x00, sizeof(struct mwifiex_ds_misc_subsc_evt)); + /* Resubscribe low and high rssi events with new thresholds */ - memset(&subsc_evt, 0x00, sizeof(struct mwifiex_ds_misc_subsc_evt)); - subsc_evt.events = BITMASK_BCN_RSSI_LOW | BITMASK_BCN_RSSI_HIGH; - subsc_evt.action = HostCmd_ACT_BITWISE_SET; + subsc_evt->events = BITMASK_BCN_RSSI_LOW | BITMASK_BCN_RSSI_HIGH; + subsc_evt->action = HostCmd_ACT_BITWISE_SET; if (priv->subsc_evt_rssi_state == RSSI_LOW_RECVD) { - subsc_evt.bcn_l_rssi_cfg.abs_value = abs(priv->bcn_rssi_avg - + subsc_evt->bcn_l_rssi_cfg.abs_value = abs(priv->bcn_rssi_avg - priv->cqm_rssi_hyst); - subsc_evt.bcn_h_rssi_cfg.abs_value = abs(priv->cqm_rssi_thold); + subsc_evt->bcn_h_rssi_cfg.abs_value = abs(priv->cqm_rssi_thold); } else if (priv->subsc_evt_rssi_state == RSSI_HIGH_RECVD) { - subsc_evt.bcn_l_rssi_cfg.abs_value = abs(priv->cqm_rssi_thold); - subsc_evt.bcn_h_rssi_cfg.abs_value = abs(priv->bcn_rssi_avg + + subsc_evt->bcn_l_rssi_cfg.abs_value = abs(priv->cqm_rssi_thold); + subsc_evt->bcn_h_rssi_cfg.abs_value = abs(priv->bcn_rssi_avg + priv->cqm_rssi_hyst); } - subsc_evt.bcn_l_rssi_cfg.evt_freq = 1; - subsc_evt.bcn_h_rssi_cfg.evt_freq = 1; + subsc_evt->bcn_l_rssi_cfg.evt_freq = 1; + subsc_evt->bcn_h_rssi_cfg.evt_freq = 1; priv->subsc_evt_rssi_state = EVENT_HANDLED; mwifiex_send_cmd_async(priv, HostCmd_CMD_802_11_SUBSCRIBE_EVENT, - 0, 0, &subsc_evt); + 0, 0, subsc_evt); return 0; } @@ -736,7 +738,6 @@ static int mwifiex_ret_ibss_coalescing_status(struct mwifiex_private *priv, { struct host_cmd_ds_802_11_ibss_status *ibss_coal_resp = &(resp->params.ibss_coalescing); - u8 zero_mac[ETH_ALEN] = { 0, 0, 0, 0, 0, 0 }; if (le16_to_cpu(ibss_coal_resp->action) == HostCmd_ACT_GEN_SET) return 0; @@ -745,7 +746,7 @@ static int mwifiex_ret_ibss_coalescing_status(struct mwifiex_private *priv, "info: new BSSID %pM\n", ibss_coal_resp->bssid); /* If rsp has NULL BSSID, Just return..... No Action */ - if (!memcmp(ibss_coal_resp->bssid, zero_mac, ETH_ALEN)) { + if (is_zero_ether_addr(ibss_coal_resp->bssid)) { dev_warn(priv->adapter->dev, "new BSSID is NULL\n"); return 0; } @@ -775,8 +776,7 @@ static int mwifiex_ret_ibss_coalescing_status(struct mwifiex_private *priv, * This function handles the command response for subscribe event command. */ static int mwifiex_ret_subsc_evt(struct mwifiex_private *priv, - struct host_cmd_ds_command *resp, - struct mwifiex_ds_misc_subsc_evt *sub_event) + struct host_cmd_ds_command *resp) { struct host_cmd_ds_802_11_subsc_evt *cmd_sub_event = &resp->params.subsc_evt; @@ -786,10 +786,6 @@ static int mwifiex_ret_subsc_evt(struct mwifiex_private *priv, dev_dbg(priv->adapter->dev, "Bitmap of currently subscribed events: %16x\n", le16_to_cpu(cmd_sub_event->events)); - /*Return the subscribed event info for a Get request*/ - if (sub_event) - sub_event->events = le16_to_cpu(cmd_sub_event->events); - return 0; } @@ -913,7 +909,6 @@ int mwifiex_process_sta_cmdresp(struct mwifiex_private *priv, u16 cmdresp_no, le16_to_cpu(resp->params.tx_buf.mp_end_port)); break; case HostCmd_CMD_AMSDU_AGGR_CTRL: - ret = mwifiex_ret_amsdu_aggr_ctrl(resp, data_buf); break; case HostCmd_CMD_WMM_GET_STATUS: ret = mwifiex_ret_wmm_get_status(priv, resp); @@ -932,12 +927,11 @@ int mwifiex_process_sta_cmdresp(struct mwifiex_private *priv, u16 cmdresp_no, case HostCmd_CMD_SET_BSS_MODE: break; case HostCmd_CMD_11N_CFG: - ret = mwifiex_ret_11n_cfg(resp, data_buf); break; case HostCmd_CMD_PCIE_DESC_DETAILS: break; case HostCmd_CMD_802_11_SUBSCRIBE_EVENT: - ret = mwifiex_ret_subsc_evt(priv, resp, data_buf); + ret = mwifiex_ret_subsc_evt(priv, resp); break; case HostCmd_CMD_UAP_SYS_CONFIG: break; diff --git a/drivers/net/wireless/mwifiex/sta_ioctl.c b/drivers/net/wireless/mwifiex/sta_ioctl.c index 3f025976f79a..d7ad2d4a069f 100644 --- a/drivers/net/wireless/mwifiex/sta_ioctl.c +++ b/drivers/net/wireless/mwifiex/sta_ioctl.c @@ -192,6 +192,44 @@ int mwifiex_fill_new_bss_desc(struct mwifiex_private *priv, return ret; } +static int mwifiex_process_country_ie(struct mwifiex_private *priv, + struct cfg80211_bss *bss) +{ + u8 *country_ie, country_ie_len; + struct mwifiex_802_11d_domain_reg *domain_info = + &priv->adapter->domain_reg; + + country_ie = (u8 *)ieee80211_bss_get_ie(bss, WLAN_EID_COUNTRY); + + if (!country_ie) + return 0; + + country_ie_len = country_ie[1]; + if (country_ie_len < IEEE80211_COUNTRY_IE_MIN_LEN) + return 0; + + domain_info->country_code[0] = country_ie[2]; + domain_info->country_code[1] = country_ie[3]; + domain_info->country_code[2] = ' '; + + country_ie_len -= IEEE80211_COUNTRY_STRING_LEN; + + domain_info->no_of_triplet = + country_ie_len / sizeof(struct ieee80211_country_ie_triplet); + + memcpy((u8 *)domain_info->triplet, + &country_ie[2] + IEEE80211_COUNTRY_STRING_LEN, country_ie_len); + + if (mwifiex_send_cmd_async(priv, HostCmd_CMD_802_11D_DOMAIN_INFO, + HostCmd_ACT_GEN_SET, 0, NULL)) { + wiphy_err(priv->adapter->wiphy, + "11D: setting domain info in FW\n"); + return -1; + } + + return 0; +} + /* * In Ad-Hoc mode, the IBSS is created if not found in scan list. * In both Ad-Hoc and infra mode, an deauthentication is performed @@ -207,6 +245,8 @@ int mwifiex_bss_start(struct mwifiex_private *priv, struct cfg80211_bss *bss, priv->scan_block = false; if (bss) { + mwifiex_process_country_ie(priv, bss); + /* Allocate and fill new bss descriptor */ bss_desc = kzalloc(sizeof(struct mwifiex_bssdescriptor), GFP_KERNEL); diff --git a/drivers/net/wireless/mwifiex/txrx.c b/drivers/net/wireless/mwifiex/txrx.c index 985073d0df1a..2af263992e83 100644 --- a/drivers/net/wireless/mwifiex/txrx.c +++ b/drivers/net/wireless/mwifiex/txrx.c @@ -75,7 +75,11 @@ int mwifiex_process_tx(struct mwifiex_private *priv, struct sk_buff *skb, u8 *head_ptr; struct txpd *local_tx_pd = NULL; - head_ptr = mwifiex_process_sta_txpd(priv, skb); + if (priv->bss_role == MWIFIEX_BSS_ROLE_UAP) + head_ptr = mwifiex_process_uap_txpd(priv, skb); + else + head_ptr = mwifiex_process_sta_txpd(priv, skb); + if (head_ptr) { if (GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_STA) local_tx_pd = diff --git a/drivers/net/wireless/mwifiex/uap_cmd.c b/drivers/net/wireless/mwifiex/uap_cmd.c index c10aac04be6a..8a627d856d18 100644 --- a/drivers/net/wireless/mwifiex/uap_cmd.c +++ b/drivers/net/wireless/mwifiex/uap_cmd.c @@ -177,6 +177,25 @@ mwifiex_set_ht_params(struct mwifiex_private *priv, return; } +/* This function finds supported rates IE from beacon parameter and sets + * these rates into bss_config structure. + */ +void +mwifiex_set_uap_rates(struct mwifiex_uap_bss_param *bss_cfg, + struct cfg80211_ap_settings *params) +{ + struct ieee_types_header *rate_ie; + int var_offset = offsetof(struct ieee80211_mgmt, u.beacon.variable); + const u8 *var_pos = params->beacon.head + var_offset; + int len = params->beacon.head_len - var_offset; + + rate_ie = (void *)cfg80211_find_ie(WLAN_EID_SUPP_RATES, var_pos, len); + if (rate_ie) + memcpy(bss_cfg->rates, rate_ie + 1, rate_ie->len); + + return; +} + /* This function initializes some of mwifiex_uap_bss_param variables. * This helps FW in ignoring invalid values. These values may or may not * be get updated to valid ones at later stage. @@ -323,8 +342,10 @@ mwifiex_uap_bss_param_prepare(u8 *tlv, void *cmd_buf, u16 *param_size) struct host_cmd_tlv_retry_limit *retry_limit; struct host_cmd_tlv_encrypt_protocol *encrypt_protocol; struct host_cmd_tlv_auth_type *auth_type; + struct host_cmd_tlv_rates *tlv_rates; struct mwifiex_ie_types_htcap *htcap; struct mwifiex_uap_bss_param *bss_cfg = cmd_buf; + int i; u16 cmd_size = *param_size; if (bss_cfg->ssid.ssid_len) { @@ -344,7 +365,23 @@ mwifiex_uap_bss_param_prepare(u8 *tlv, void *cmd_buf, u16 *param_size) cmd_size += sizeof(struct host_cmd_tlv_bcast_ssid); tlv += sizeof(struct host_cmd_tlv_bcast_ssid); } - if (bss_cfg->channel && bss_cfg->channel <= MAX_CHANNEL_BAND_BG) { + if (bss_cfg->rates[0]) { + tlv_rates = (struct host_cmd_tlv_rates *)tlv; + tlv_rates->tlv.type = cpu_to_le16(TLV_TYPE_UAP_RATES); + + for (i = 0; i < MWIFIEX_SUPPORTED_RATES && bss_cfg->rates[i]; + i++) + tlv_rates->rates[i] = bss_cfg->rates[i]; + + tlv_rates->tlv.len = cpu_to_le16(i); + cmd_size += sizeof(struct host_cmd_tlv_rates) + i; + tlv += sizeof(struct host_cmd_tlv_rates) + i; + } + if (bss_cfg->channel && + ((bss_cfg->band_cfg == BAND_CONFIG_BG && + bss_cfg->channel <= MAX_CHANNEL_BAND_BG) || + (bss_cfg->band_cfg == BAND_CONFIG_A && + bss_cfg->channel <= MAX_CHANNEL_BAND_A))) { chan_band = (struct host_cmd_tlv_channel_band *)tlv; chan_band->tlv.type = cpu_to_le16(TLV_TYPE_CHANNELBANDLIST); chan_band->tlv.len = diff --git a/drivers/net/wireless/mwifiex/uap_txrx.c b/drivers/net/wireless/mwifiex/uap_txrx.c index 6d814f0f07f2..df17d08715fe 100644 --- a/drivers/net/wireless/mwifiex/uap_txrx.c +++ b/drivers/net/wireless/mwifiex/uap_txrx.c @@ -253,3 +253,73 @@ int mwifiex_process_uap_rx_packet(struct mwifiex_adapter *adapter, return ret; } + +/* + * This function fills the TxPD for AP tx packets. + * + * The Tx buffer received by this function should already have the + * header space allocated for TxPD. + * + * This function inserts the TxPD in between interface header and actual + * data and adjusts the buffer pointers accordingly. + * + * The following TxPD fields are set by this function, as required - + * - BSS number + * - Tx packet length and offset + * - Priority + * - Packet delay + * - Priority specific Tx control + * - Flags + */ +void *mwifiex_process_uap_txpd(struct mwifiex_private *priv, + struct sk_buff *skb) +{ + struct mwifiex_adapter *adapter = priv->adapter; + struct uap_txpd *txpd; + struct mwifiex_txinfo *tx_info = MWIFIEX_SKB_TXCB(skb); + int pad, len; + + if (!skb->len) { + dev_err(adapter->dev, "Tx: bad packet length: %d\n", skb->len); + tx_info->status_code = -1; + return skb->data; + } + + /* If skb->data is not aligned, add padding */ + pad = (4 - (((void *)skb->data - NULL) & 0x3)) % 4; + + len = sizeof(*txpd) + pad; + + BUG_ON(skb_headroom(skb) < len + INTF_HEADER_LEN); + + skb_push(skb, len); + + txpd = (struct uap_txpd *)skb->data; + memset(txpd, 0, sizeof(*txpd)); + txpd->bss_num = priv->bss_num; + txpd->bss_type = priv->bss_type; + txpd->tx_pkt_length = cpu_to_le16((u16)(skb->len - len)); + + txpd->priority = (u8)skb->priority; + txpd->pkt_delay_2ms = mwifiex_wmm_compute_drv_pkt_delay(priv, skb); + + if (txpd->priority < ARRAY_SIZE(priv->wmm.user_pri_pkt_tx_ctrl)) + /* + * Set the priority specific tx_control field, setting of 0 will + * cause the default value to be used later in this function. + */ + txpd->tx_control = + cpu_to_le32(priv->wmm.user_pri_pkt_tx_ctrl[txpd->priority]); + + /* Offset of actual data */ + txpd->tx_pkt_offset = cpu_to_le16(len); + + /* make space for INTF_HEADER_LEN */ + skb_push(skb, INTF_HEADER_LEN); + + if (!txpd->tx_control) + /* TxCtrl set by user or default */ + txpd->tx_control = cpu_to_le32(priv->pkt_tx_ctrl); + + return skb->data; +} diff --git a/drivers/net/wireless/mwifiex/wmm.c b/drivers/net/wireless/mwifiex/wmm.c index 8ccd6999fa9f..766d45294c86 100644 --- a/drivers/net/wireless/mwifiex/wmm.c +++ b/drivers/net/wireless/mwifiex/wmm.c @@ -907,17 +907,16 @@ mwifiex_wmm_get_highest_priolist_ptr(struct mwifiex_adapter *adapter, if (adapter->bss_prio_tbl[j].bss_prio_cur == (struct mwifiex_bss_prio_node *) &adapter->bss_prio_tbl[j].bss_prio_head) { - bssprio_node = + adapter->bss_prio_tbl[j].bss_prio_cur = list_first_entry(&adapter->bss_prio_tbl[j] .bss_prio_head, struct mwifiex_bss_prio_node, list); - bssprio_head = bssprio_node; - } else { - bssprio_node = adapter->bss_prio_tbl[j].bss_prio_cur; - bssprio_head = bssprio_node; } + bssprio_node = adapter->bss_prio_tbl[j].bss_prio_cur; + bssprio_head = bssprio_node; + do { priv_tmp = bssprio_node->priv; hqp = &priv_tmp->wmm.highest_queued_prio; |