From 1aed8b0aad50077c193beee5be4174a23a2f46d9 Mon Sep 17 00:00:00 2001 From: Mohan T Date: Mon, 14 May 2012 12:07:54 +0530 Subject: net: wireless: sd8797: Integrate M2614311 Release Integrate Marvell SD8797 M2614311-GPL driver release Package Ver: T3T-14.69.11.p122-M2614311_A0B0-MGPL Bug 954218 Change-Id: Ic4c110cc06f45cf3f612df323e68c75edeb46e11 Signed-off-by: Mohan T Reviewed-on: http://git-master/r/100052 Reviewed-by: Rakesh Kumar GVS: Gerrit_Virtual_Submit Reviewed-by: Bharat Nihalani --- drivers/net/wireless/sd8797/Makefile | 1 + drivers/net/wireless/sd8797/mlan/mlan_11d.c | 3 +- drivers/net/wireless/sd8797/mlan/mlan_11h.c | 42 +- drivers/net/wireless/sd8797/mlan/mlan_11n.c | 9 +- drivers/net/wireless/sd8797/mlan/mlan_11n_aggr.c | 5 +- .../net/wireless/sd8797/mlan/mlan_11n_rxreorder.c | 5 +- drivers/net/wireless/sd8797/mlan/mlan_cfp.c | 368 ++- drivers/net/wireless/sd8797/mlan/mlan_cmdevt.c | 29 +- drivers/net/wireless/sd8797/mlan/mlan_decl.h | 18 +- drivers/net/wireless/sd8797/mlan/mlan_fw.h | 46 +- drivers/net/wireless/sd8797/mlan/mlan_ieee.h | 4 + drivers/net/wireless/sd8797/mlan/mlan_init.c | 13 +- drivers/net/wireless/sd8797/mlan/mlan_ioctl.h | 69 +- drivers/net/wireless/sd8797/mlan/mlan_main.h | 95 +- drivers/net/wireless/sd8797/mlan/mlan_misc.c | 93 +- drivers/net/wireless/sd8797/mlan/mlan_scan.c | 84 +- drivers/net/wireless/sd8797/mlan/mlan_sdio.c | 4 +- drivers/net/wireless/sd8797/mlan/mlan_shim.c | 7 + drivers/net/wireless/sd8797/mlan/mlan_sta_cmd.c | 116 +- .../net/wireless/sd8797/mlan/mlan_sta_cmdresp.c | 94 +- drivers/net/wireless/sd8797/mlan/mlan_sta_event.c | 10 +- drivers/net/wireless/sd8797/mlan/mlan_sta_ioctl.c | 264 +- drivers/net/wireless/sd8797/mlan/mlan_sta_rx.c | 4 +- drivers/net/wireless/sd8797/mlan/mlan_sta_tx.c | 5 +- drivers/net/wireless/sd8797/mlan/mlan_txrx.c | 10 +- .../net/wireless/sd8797/mlan/mlan_uap_cmdevent.c | 2 +- drivers/net/wireless/sd8797/mlan/mlan_uap_ioctl.c | 6 +- drivers/net/wireless/sd8797/mlan/mlan_uap_txrx.c | 2 +- drivers/net/wireless/sd8797/mlan/mlan_wmm.c | 55 +- drivers/net/wireless/sd8797/mlinux/mlan.h | 35 + drivers/net/wireless/sd8797/mlinux/mlan_decl.h | 893 ++++++ drivers/net/wireless/sd8797/mlinux/mlan_ieee.h | 1322 +++++++++ drivers/net/wireless/sd8797/mlinux/mlan_ioctl.h | 2981 ++++++++++++++++++++ drivers/net/wireless/sd8797/mlinux/moal_cfg80211.c | 630 ++++- drivers/net/wireless/sd8797/mlinux/moal_cfg80211.h | 16 +- .../net/wireless/sd8797/mlinux/moal_eth_ioctl.c | 1246 +++++++- .../net/wireless/sd8797/mlinux/moal_eth_ioctl.h | 23 +- drivers/net/wireless/sd8797/mlinux/moal_ioctl.c | 272 +- drivers/net/wireless/sd8797/mlinux/moal_main.c | 323 ++- drivers/net/wireless/sd8797/mlinux/moal_main.h | 74 +- drivers/net/wireless/sd8797/mlinux/moal_priv.c | 188 +- drivers/net/wireless/sd8797/mlinux/moal_priv.h | 14 + drivers/net/wireless/sd8797/mlinux/moal_proc.c | 6 +- drivers/net/wireless/sd8797/mlinux/moal_sdio_mmc.c | 6 + drivers/net/wireless/sd8797/mlinux/moal_shim.c | 83 +- .../net/wireless/sd8797/mlinux/moal_sta_cfg80211.c | 358 +-- .../net/wireless/sd8797/mlinux/moal_uap_cfg80211.c | 482 +--- drivers/net/wireless/sd8797/mlinux/moal_wext.c | 17 +- drivers/net/wireless/sd8797/mlinux/moal_wext.h | 1 - 49 files changed, 9153 insertions(+), 1280 deletions(-) create mode 100644 drivers/net/wireless/sd8797/mlinux/mlan.h create mode 100644 drivers/net/wireless/sd8797/mlinux/mlan_decl.h create mode 100644 drivers/net/wireless/sd8797/mlinux/mlan_ieee.h create mode 100644 drivers/net/wireless/sd8797/mlinux/mlan_ioctl.h (limited to 'drivers/net') diff --git a/drivers/net/wireless/sd8797/Makefile b/drivers/net/wireless/sd8797/Makefile index d5eb7872a232..3ef70380dd82 100644 --- a/drivers/net/wireless/sd8797/Makefile +++ b/drivers/net/wireless/sd8797/Makefile @@ -52,6 +52,7 @@ EXTRA_CFLAGS += -DPROC_DEBUG EXTRA_CFLAGS += -DSDIO_MULTI_PORT_TX_AGGR EXTRA_CFLAGS += -DSDIO_MULTI_PORT_RX_AGGR EXTRA_CFLAGS += -DSDIO_SUSPEND_RESUME +EXTRA_CFLAGS += -DMMC_PM_KEEP_POWER EXTRA_CFLAGS += -DDFS_TESTING_SUPPORT EXTRA_CFLAGS += -DMFG_CMD_SUPPORT diff --git a/drivers/net/wireless/sd8797/mlan/mlan_11d.c b/drivers/net/wireless/sd8797/mlan/mlan_11d.c index 1727c5890fc8..fdc0d993e381 100644 --- a/drivers/net/wireless/sd8797/mlan/mlan_11d.c +++ b/drivers/net/wireless/sd8797/mlan/mlan_11d.c @@ -2,7 +2,7 @@ * * @brief This file contains functions for 802.11D. * - * Copyright (C) 2008-2011, Marvell International Ltd. + * Copyright (C) 2008-2012, Marvell International Ltd. * * This software file (the "File") is distributed by Marvell International * Ltd. under the terms of the GNU General Public License Version 2, June 1991 @@ -55,6 +55,7 @@ static region_code_mapping_t region_code_mapping[] = { {"JP ", 0x40}, /* Japan */ {"JP ", 0x41}, /* Japan */ {"CN ", 0x50}, /* China */ + {"JP ", 0xFE}, /* Japan */ {"JP ", 0xFF}, /* Japan special */ }; diff --git a/drivers/net/wireless/sd8797/mlan/mlan_11h.c b/drivers/net/wireless/sd8797/mlan/mlan_11h.c index 7e08f4cd5d8a..3a38979a8dd2 100644 --- a/drivers/net/wireless/sd8797/mlan/mlan_11h.c +++ b/drivers/net/wireless/sd8797/mlan/mlan_11h.c @@ -2,7 +2,7 @@ * * @brief This file contains functions for 802.11H. * - * Copyright (C) 2008-2011, Marvell International Ltd. + * Copyright (C) 2008-2012, Marvell International Ltd. * * This software file (the "File") is distributed by Marvell International * Ltd. under the terms of the GNU General Public License Version 2, June 1991 @@ -298,6 +298,11 @@ wlan_11h_set_supp_channels_ie(mlan_private * priv, sizeof(IEEEtypes_SupportedChannels_t)); cfp_bg = cfp_a = priv->adapter->region_code; + if (!priv->adapter->region_code) { + /* Invalid region code, use CFP code */ + cfp_bg = priv->adapter->cfp_code_bg; + cfp_a = priv->adapter->cfp_code_a; + } if ((band & BAND_B) || (band & BAND_G)) { /* @@ -355,6 +360,23 @@ wlan_11h_set_supp_channels_ie(mlan_private * priv, psup_chan->subband[num_subbands++] = wlan_11h_unii_middle_band; psup_chan->subband[num_subbands++] = wlan_11h_unii_mid_upper_band; break; + case 0x1: /* Low band (5150-5250 MHz) channels */ + psup_chan->subband[num_subbands++] = wlan_11h_unii_lower_band; + break; + case 0x2: /* Lower middle band (5250-5350 MHz) channels */ + psup_chan->subband[num_subbands++] = wlan_11h_unii_middle_band; + break; + case 0x3: /* Upper middle band (5470-5725 MHz) channels */ + psup_chan->subband[num_subbands++] = wlan_11h_unii_mid_upper_band; + break; + case 0x4: /* High band (5725-5850 MHz) channels */ + psup_chan->subband[num_subbands++] = wlan_11h_unii_upper_band; + break; + case 0x5: /* Low band (5150-5250 MHz) and High band + (5725-5850 MHz) channels */ + psup_chan->subband[num_subbands++] = wlan_11h_unii_lower_band; + psup_chan->subband[num_subbands++] = wlan_11h_unii_upper_band; + break; } } @@ -1799,9 +1821,15 @@ wlan_11h_radar_detect_required(mlan_private * priv, t_u8 channel) required = wlan_get_cfp_radar_detect(priv, channel); - PRINTM(MINFO, "11h: Radar detection in region %#02x " - "is %srequired for channel %d\n", - priv->adapter->region_code, (required ? "" : "not "), channel); + if (!priv->adapter->region_code) + PRINTM(MINFO, "11h: Radar detection in CFP code[BG:%#x, A:%#x] " + "is %srequired for channel %d\n", + priv->adapter->cfp_code_bg, priv->adapter->cfp_code_a, + (required ? "" : "not "), channel); + else + PRINTM(MINFO, "11h: Radar detection in region %#02x " + "is %srequired for channel %d\n", + priv->adapter->region_code, (required ? "" : "not "), channel); if (required == MTRUE && priv->media_connected == MTRUE && priv->curr_bss_params.bss_descriptor.channel == channel) { @@ -3153,13 +3181,13 @@ wlan_11h_switch_non_dfs_chan(mlan_private * priv, t_u8 * chan) def_chan = (t_u8) chn_tbl->pcfp[rand_entry].channel; rand_tries++; } while ((wlan_11h_is_channel_under_nop(pmadapter, def_chan) || - chn_tbl->pcfp[rand_entry].radar_detect == MTRUE) && - (rand_tries < MAX_SWITCH_CHANNEL_RETRIES)); + chn_tbl->pcfp[rand_entry].passive_scan_or_radar_detect == MTRUE) + && (rand_tries < MAX_SWITCH_CHANNEL_RETRIES)); /* meet max retries, use the lowest non-dfs channel */ if (rand_tries == MAX_SWITCH_CHANNEL_RETRIES) { for (i = 0; i < chn_tbl->num_cfp; i++) { - if (chn_tbl->pcfp[i].radar_detect == MFALSE && + if (chn_tbl->pcfp[i].passive_scan_or_radar_detect == MFALSE && !wlan_11h_is_channel_under_nop(pmadapter, (t_u8) chn_tbl->pcfp[i]. channel)) { diff --git a/drivers/net/wireless/sd8797/mlan/mlan_11n.c b/drivers/net/wireless/sd8797/mlan/mlan_11n.c index 48b51a5bf7e0..5e78748e4a3b 100644 --- a/drivers/net/wireless/sd8797/mlan/mlan_11n.c +++ b/drivers/net/wireless/sd8797/mlan/mlan_11n.c @@ -1335,6 +1335,7 @@ wlan_ret_tx_bf_cfg(IN pmlan_private pmpriv, } #ifdef STA_SUPPORT + /** * @brief This function append the 802_11N tlv * @@ -1426,12 +1427,12 @@ wlan_cmd_append_11n_tlv(IN mlan_private * pmpriv, pbss_desc->pht_info->ht_info.pri_chan; pchan_list->chan_scan_param[0].radio_type = wlan_band_to_radio_type((t_u8) pbss_desc->bss_band); - if (ISSUPP_CHANWIDTH40(usr_dot_11n_dev_cap) && - ISALLOWED_CHANWIDTH40(pbss_desc->pht_info->ht_info.field2)) + ISALLOWED_CHANWIDTH40(pbss_desc->pht_info->ht_info.field2)) { SET_SECONDARYCHAN(pchan_list->chan_scan_param[0].radio_type, GET_SECONDARYCHAN(pbss_desc->pht_info->ht_info. field2)); + } HEXDUMP("ChanList", (t_u8 *) pchan_list, sizeof(MrvlIEtypes_ChanListParamSet_t)); @@ -1467,15 +1468,13 @@ wlan_cmd_append_11n_tlv(IN mlan_private * pmpriv, memcpy(pmadapter, (t_u8 *) pext_cap + sizeof(MrvlIEtypesHeader_t), (t_u8 *) pbss_desc->pext_cap + sizeof(IEEEtypes_Header_t), - pext_cap->header.len); - + pbss_desc->pext_cap->ieee_hdr.len); HEXDUMP("Extended Capabilities IE", (t_u8 *) pext_cap, sizeof(MrvlIETypes_ExtCap_t)); *ppbuffer += sizeof(MrvlIETypes_ExtCap_t); ret_len += sizeof(MrvlIETypes_ExtCap_t); pext_cap->header.len = wlan_cpu_to_le16(pext_cap->header.len); } - LEAVE(); return ret_len; } diff --git a/drivers/net/wireless/sd8797/mlan/mlan_11n_aggr.c b/drivers/net/wireless/sd8797/mlan/mlan_11n_aggr.c index 6af4b6a698e8..6125262d5b7a 100644 --- a/drivers/net/wireless/sd8797/mlan/mlan_11n_aggr.c +++ b/drivers/net/wireless/sd8797/mlan/mlan_11n_aggr.c @@ -333,7 +333,9 @@ wlan_11n_aggregate_pkt(mlan_private * priv, raListTbl * pra_list, t_u8 *data; int pad = 0; mlan_status ret = MLAN_STATUS_SUCCESS; +#ifdef DEBUG_LEVEL1 t_u32 sec, usec; +#endif mlan_tx_param tx_param; #ifdef STA_SUPPORT TxPD *ptx_pd = MNULL; @@ -497,8 +499,7 @@ wlan_11n_aggregate_pkt(mlan_private * priv, raListTbl * pra_list, pmadapter->callbacks.moal_spin_unlock(pmadapter->pmoal_handle, priv->wmm.ra_list_spinlock); } - pmadapter->callbacks.moal_get_system_time(pmadapter->pmoal_handle, &sec, - &usec); + PRINTM_GET_SYS_TIME(MDATA, &sec, &usec); PRINTM_NETINTF(MDATA, priv); PRINTM(MDATA, "%lu.%06lu : Data => FW\n", sec, usec); diff --git a/drivers/net/wireless/sd8797/mlan/mlan_11n_rxreorder.c b/drivers/net/wireless/sd8797/mlan/mlan_11n_rxreorder.c index 870081799c07..af689b7bab49 100644 --- a/drivers/net/wireless/sd8797/mlan/mlan_11n_rxreorder.c +++ b/drivers/net/wireless/sd8797/mlan/mlan_11n_rxreorder.c @@ -4,7 +4,7 @@ * driver. * * Copyright (C) 2008-2011, Marvell International Ltd. - * + * * This software file (the "File") is distributed by Marvell International * Ltd. under the terms of the GNU General Public License Version 2, June 1991 * (the "License"). You may use, redistribute and/or modify this File in @@ -639,6 +639,9 @@ wlan_cmd_11n_addba_rspgen(mlan_private * priv, BLOCKACKPARAM_WINSIZE_POS); win_size = (padd_ba_rsp->block_ack_param_set & BLOCKACKPARAM_WINSIZE_MASK) >> BLOCKACKPARAM_WINSIZE_POS; + if (win_size == 0) + padd_ba_rsp->status_code = wlan_cpu_to_le16(ADDBA_RSP_STATUS_DECLINED); + padd_ba_rsp->block_ack_param_set = wlan_cpu_to_le16(padd_ba_rsp->block_ack_param_set); diff --git a/drivers/net/wireless/sd8797/mlan/mlan_cfp.c b/drivers/net/wireless/sd8797/mlan/mlan_cfp.c index 23e849f04b63..ccbb5aa1f666 100644 --- a/drivers/net/wireless/sd8797/mlan/mlan_cfp.c +++ b/drivers/net/wireless/sd8797/mlan/mlan_cfp.c @@ -4,7 +4,7 @@ * @brief This file contains WLAN client mode channel, frequency and power * related code * - * Copyright (C) 2009-2011, Marvell International Ltd. + * Copyright (C) 2009-2012, Marvell International Ltd. * * This software file (the "File") is distributed by Marvell International * Ltd. under the terms of the GNU General Public License Version 2, June 1991 @@ -52,6 +52,30 @@ Change Log: /** 2000mW */ #define WLAN_TX_PWR_CN_2000MW 33 +/** Region code mapping */ +typedef struct _country_code_mapping +{ + /** Region */ + t_u8 country_code[COUNTRY_CODE_LEN]; + /** Code for B/G CFP table */ + t_u8 cfp_code_bg; + /** Code for A CFP table */ + t_u8 cfp_code_a; +} country_code_mapping_t; + +/** Region code mapping table */ +static country_code_mapping_t country_code_mapping[] = { + {"US", 0x10, 0x10}, /* US FCC */ + {"CA", 0x10, 0x20}, /* IC Canada */ + {"SG", 0x10, 0x10}, /* Singapore */ + {"EU", 0x30, 0x30}, /* ETSI */ + {"AU", 0x30, 0x30}, /* Australia */ + {"KR", 0x30, 0x30}, /* Republic Of Korea */ + {"FR", 0x32, 0x32}, /* France */ + {"JP", 0xFF, 0x40}, /* Japan */ + {"CN", 0x30, 0x50}, /* China */ +}; + /** * The structure for Channel-Frequency-Power table */ @@ -68,91 +92,108 @@ typedef struct _cfp_table /* Format { Channel, Frequency (MHz), MaxTxPower } */ /** Band: 'B/G', Region: USA FCC/Canada IC */ static chan_freq_power_t channel_freq_power_US_BG[] = { - {1, 2412, WLAN_TX_PWR_US_DEFAULT}, - {2, 2417, WLAN_TX_PWR_US_DEFAULT}, - {3, 2422, WLAN_TX_PWR_US_DEFAULT}, - {4, 2427, WLAN_TX_PWR_US_DEFAULT}, - {5, 2432, WLAN_TX_PWR_US_DEFAULT}, - {6, 2437, WLAN_TX_PWR_US_DEFAULT}, - {7, 2442, WLAN_TX_PWR_US_DEFAULT}, - {8, 2447, WLAN_TX_PWR_US_DEFAULT}, - {9, 2452, WLAN_TX_PWR_US_DEFAULT}, - {10, 2457, WLAN_TX_PWR_US_DEFAULT}, - {11, 2462, WLAN_TX_PWR_US_DEFAULT} + {1, 2412, WLAN_TX_PWR_US_DEFAULT, MFALSE}, + {2, 2417, WLAN_TX_PWR_US_DEFAULT, MFALSE}, + {3, 2422, WLAN_TX_PWR_US_DEFAULT, MFALSE}, + {4, 2427, WLAN_TX_PWR_US_DEFAULT, MFALSE}, + {5, 2432, WLAN_TX_PWR_US_DEFAULT, MFALSE}, + {6, 2437, WLAN_TX_PWR_US_DEFAULT, MFALSE}, + {7, 2442, WLAN_TX_PWR_US_DEFAULT, MFALSE}, + {8, 2447, WLAN_TX_PWR_US_DEFAULT, MFALSE}, + {9, 2452, WLAN_TX_PWR_US_DEFAULT, MFALSE}, + {10, 2457, WLAN_TX_PWR_US_DEFAULT, MFALSE}, + {11, 2462, WLAN_TX_PWR_US_DEFAULT, MFALSE} }; /** Band: 'B/G', Region: Europe ETSI/China */ static chan_freq_power_t channel_freq_power_EU_BG[] = { - {1, 2412, WLAN_TX_PWR_EMEA_DEFAULT}, - {2, 2417, WLAN_TX_PWR_EMEA_DEFAULT}, - {3, 2422, WLAN_TX_PWR_EMEA_DEFAULT}, - {4, 2427, WLAN_TX_PWR_EMEA_DEFAULT}, - {5, 2432, WLAN_TX_PWR_EMEA_DEFAULT}, - {6, 2437, WLAN_TX_PWR_EMEA_DEFAULT}, - {7, 2442, WLAN_TX_PWR_EMEA_DEFAULT}, - {8, 2447, WLAN_TX_PWR_EMEA_DEFAULT}, - {9, 2452, WLAN_TX_PWR_EMEA_DEFAULT}, - {10, 2457, WLAN_TX_PWR_EMEA_DEFAULT}, - {11, 2462, WLAN_TX_PWR_EMEA_DEFAULT}, - {12, 2467, WLAN_TX_PWR_EMEA_DEFAULT}, - {13, 2472, WLAN_TX_PWR_EMEA_DEFAULT} + {1, 2412, WLAN_TX_PWR_EMEA_DEFAULT, MFALSE}, + {2, 2417, WLAN_TX_PWR_EMEA_DEFAULT, MFALSE}, + {3, 2422, WLAN_TX_PWR_EMEA_DEFAULT, MFALSE}, + {4, 2427, WLAN_TX_PWR_EMEA_DEFAULT, MFALSE}, + {5, 2432, WLAN_TX_PWR_EMEA_DEFAULT, MFALSE}, + {6, 2437, WLAN_TX_PWR_EMEA_DEFAULT, MFALSE}, + {7, 2442, WLAN_TX_PWR_EMEA_DEFAULT, MFALSE}, + {8, 2447, WLAN_TX_PWR_EMEA_DEFAULT, MFALSE}, + {9, 2452, WLAN_TX_PWR_EMEA_DEFAULT, MFALSE}, + {10, 2457, WLAN_TX_PWR_EMEA_DEFAULT, MFALSE}, + {11, 2462, WLAN_TX_PWR_EMEA_DEFAULT, MFALSE}, + {12, 2467, WLAN_TX_PWR_EMEA_DEFAULT, MFALSE}, + {13, 2472, WLAN_TX_PWR_EMEA_DEFAULT, MFALSE} }; /** Band: 'B/G', Region: France */ static chan_freq_power_t channel_freq_power_FR_BG[] = { - {1, 2412, WLAN_TX_PWR_FR_100MW}, - {2, 2417, WLAN_TX_PWR_FR_100MW}, - {3, 2422, WLAN_TX_PWR_FR_100MW}, - {4, 2427, WLAN_TX_PWR_FR_100MW}, - {5, 2432, WLAN_TX_PWR_FR_100MW}, - {6, 2437, WLAN_TX_PWR_FR_100MW}, - {7, 2442, WLAN_TX_PWR_FR_100MW}, - {8, 2447, WLAN_TX_PWR_FR_100MW}, - {9, 2452, WLAN_TX_PWR_FR_100MW}, - {10, 2457, WLAN_TX_PWR_FR_10MW}, - {11, 2462, WLAN_TX_PWR_FR_10MW}, - {12, 2467, WLAN_TX_PWR_FR_10MW}, - {13, 2472, WLAN_TX_PWR_FR_10MW} + {1, 2412, WLAN_TX_PWR_FR_100MW, MFALSE}, + {2, 2417, WLAN_TX_PWR_FR_100MW, MFALSE}, + {3, 2422, WLAN_TX_PWR_FR_100MW, MFALSE}, + {4, 2427, WLAN_TX_PWR_FR_100MW, MFALSE}, + {5, 2432, WLAN_TX_PWR_FR_100MW, MFALSE}, + {6, 2437, WLAN_TX_PWR_FR_100MW, MFALSE}, + {7, 2442, WLAN_TX_PWR_FR_100MW, MFALSE}, + {8, 2447, WLAN_TX_PWR_FR_100MW, MFALSE}, + {9, 2452, WLAN_TX_PWR_FR_100MW, MFALSE}, + {10, 2457, WLAN_TX_PWR_FR_10MW, MFALSE}, + {11, 2462, WLAN_TX_PWR_FR_10MW, MFALSE}, + {12, 2467, WLAN_TX_PWR_FR_10MW, MFALSE}, + {13, 2472, WLAN_TX_PWR_FR_10MW, MFALSE} }; /** Band: 'B/G', Region: Japan */ static chan_freq_power_t channel_freq_power_JPN41_BG[] = { - {1, 2412, WLAN_TX_PWR_JP_BG_DEFAULT}, - {2, 2417, WLAN_TX_PWR_JP_BG_DEFAULT}, - {3, 2422, WLAN_TX_PWR_JP_BG_DEFAULT}, - {4, 2427, WLAN_TX_PWR_JP_BG_DEFAULT}, - {5, 2432, WLAN_TX_PWR_JP_BG_DEFAULT}, - {6, 2437, WLAN_TX_PWR_JP_BG_DEFAULT}, - {7, 2442, WLAN_TX_PWR_JP_BG_DEFAULT}, - {8, 2447, WLAN_TX_PWR_JP_BG_DEFAULT}, - {9, 2452, WLAN_TX_PWR_JP_BG_DEFAULT}, - {10, 2457, WLAN_TX_PWR_JP_BG_DEFAULT}, - {11, 2462, WLAN_TX_PWR_JP_BG_DEFAULT}, - {12, 2467, WLAN_TX_PWR_JP_BG_DEFAULT}, - {13, 2472, WLAN_TX_PWR_JP_BG_DEFAULT} + {1, 2412, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE}, + {2, 2417, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE}, + {3, 2422, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE}, + {4, 2427, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE}, + {5, 2432, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE}, + {6, 2437, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE}, + {7, 2442, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE}, + {8, 2447, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE}, + {9, 2452, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE}, + {10, 2457, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE}, + {11, 2462, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE}, + {12, 2467, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE}, + {13, 2472, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE} }; /** Band: 'B/G', Region: Japan */ static chan_freq_power_t channel_freq_power_JPN40_BG[] = { - {14, 2484, WLAN_TX_PWR_JP_BG_DEFAULT} + {14, 2484, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE} +}; + +/** Band: 'B/G', Region: Japan */ +static chan_freq_power_t channel_freq_power_JPNFE_BG[] = { + {1, 2412, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE}, + {2, 2417, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE}, + {3, 2422, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE}, + {4, 2427, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE}, + {5, 2432, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE}, + {6, 2437, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE}, + {7, 2442, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE}, + {8, 2447, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE}, + {9, 2452, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE}, + {10, 2457, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE}, + {11, 2462, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE}, + {12, 2467, WLAN_TX_PWR_JP_BG_DEFAULT, MTRUE}, + {13, 2472, WLAN_TX_PWR_JP_BG_DEFAULT, MTRUE} }; /** Band : 'B/G', Region: Special */ static chan_freq_power_t channel_freq_power_SPECIAL_BG[] = { - {1, 2412, WLAN_TX_PWR_JP_BG_DEFAULT}, - {2, 2417, WLAN_TX_PWR_JP_BG_DEFAULT}, - {3, 2422, WLAN_TX_PWR_JP_BG_DEFAULT}, - {4, 2427, WLAN_TX_PWR_JP_BG_DEFAULT}, - {5, 2432, WLAN_TX_PWR_JP_BG_DEFAULT}, - {6, 2437, WLAN_TX_PWR_JP_BG_DEFAULT}, - {7, 2442, WLAN_TX_PWR_JP_BG_DEFAULT}, - {8, 2447, WLAN_TX_PWR_JP_BG_DEFAULT}, - {9, 2452, WLAN_TX_PWR_JP_BG_DEFAULT}, - {10, 2457, WLAN_TX_PWR_JP_BG_DEFAULT}, - {11, 2462, WLAN_TX_PWR_JP_BG_DEFAULT}, - {12, 2467, WLAN_TX_PWR_JP_BG_DEFAULT}, - {13, 2472, WLAN_TX_PWR_JP_BG_DEFAULT}, - {14, 2484, WLAN_TX_PWR_JP_BG_DEFAULT} + {1, 2412, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE}, + {2, 2417, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE}, + {3, 2422, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE}, + {4, 2427, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE}, + {5, 2432, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE}, + {6, 2437, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE}, + {7, 2442, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE}, + {8, 2447, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE}, + {9, 2452, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE}, + {10, 2457, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE}, + {11, 2462, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE}, + {12, 2467, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE}, + {13, 2472, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE}, + {14, 2484, WLAN_TX_PWR_JP_BG_DEFAULT, MFALSE} }; /** @@ -194,6 +235,12 @@ static cfp_table_t cfp_table_BG[] = { sizeof(channel_freq_power_EU_BG) / sizeof(chan_freq_power_t), } , + { + 0xfe, /* JAPAN */ + channel_freq_power_JPNFE_BG, + sizeof(channel_freq_power_JPNFE_BG) / sizeof(chan_freq_power_t), + } + , {0xff, /* Special */ channel_freq_power_SPECIAL_BG, sizeof(channel_freq_power_SPECIAL_BG) / sizeof(chan_freq_power_t), @@ -317,6 +364,64 @@ static chan_freq_power_t channel_freq_power_CN_A[] = { {165, 5825, WLAN_TX_PWR_CN_2000MW, MFALSE} }; +/** Band: 'A', NULL */ +static chan_freq_power_t channel_freq_power_NULL_A[] = { +}; + +/** Band: 'A', Code: 1, Low band (5150-5250 MHz) channels */ +static chan_freq_power_t channel_freq_power_low_band[] = { + {36, 5180, WLAN_TX_PWR_DEFAULT, MFALSE}, + {40, 5200, WLAN_TX_PWR_DEFAULT, MFALSE}, + {44, 5220, WLAN_TX_PWR_DEFAULT, MFALSE}, + {48, 5240, WLAN_TX_PWR_DEFAULT, MFALSE}, +}; + +/** Band: 'A', Code: 2, Lower middle band (5250-5350 MHz) channels */ +static chan_freq_power_t channel_freq_power_lower_middle_band[] = { + {52, 5260, WLAN_TX_PWR_DEFAULT, MTRUE}, + {56, 5280, WLAN_TX_PWR_DEFAULT, MTRUE}, + {60, 5300, WLAN_TX_PWR_DEFAULT, MTRUE}, + {64, 5320, WLAN_TX_PWR_DEFAULT, MTRUE}, +}; + +/** Band: 'A', Code: 3, Upper middle band (5470-5725 MHz) channels */ +static chan_freq_power_t channel_freq_power_upper_middle_band[] = { + {100, 5500, WLAN_TX_PWR_DEFAULT, MTRUE}, + {104, 5520, WLAN_TX_PWR_DEFAULT, MTRUE}, + {108, 5540, WLAN_TX_PWR_DEFAULT, MTRUE}, + {112, 5560, WLAN_TX_PWR_DEFAULT, MTRUE}, + {116, 5580, WLAN_TX_PWR_DEFAULT, MTRUE}, + {120, 5600, WLAN_TX_PWR_DEFAULT, MTRUE}, + {124, 5620, WLAN_TX_PWR_DEFAULT, MTRUE}, + {128, 5640, WLAN_TX_PWR_DEFAULT, MTRUE}, + {132, 5660, WLAN_TX_PWR_DEFAULT, MTRUE}, + {136, 5680, WLAN_TX_PWR_DEFAULT, MTRUE}, + {140, 5700, WLAN_TX_PWR_DEFAULT, MTRUE}, +}; + +/** Band: 'A', Code: 4, High band (5725-5850 MHz) channels */ +static chan_freq_power_t channel_freq_power_high_band[] = { + {149, 5745, WLAN_TX_PWR_DEFAULT, MFALSE}, + {153, 5765, WLAN_TX_PWR_DEFAULT, MFALSE}, + {157, 5785, WLAN_TX_PWR_DEFAULT, MFALSE}, + {161, 5805, WLAN_TX_PWR_DEFAULT, MFALSE}, + {165, 5825, WLAN_TX_PWR_DEFAULT, MFALSE} +}; + +/** Band: 'A', Code: 5, Low band (5150-5250 MHz) and + * High band (5725-5850 MHz) channels */ +static chan_freq_power_t channel_freq_power_low_high_band[] = { + {36, 5180, WLAN_TX_PWR_DEFAULT, MFALSE}, + {40, 5200, WLAN_TX_PWR_DEFAULT, MFALSE}, + {44, 5220, WLAN_TX_PWR_DEFAULT, MFALSE}, + {48, 5240, WLAN_TX_PWR_DEFAULT, MFALSE}, + {149, 5745, WLAN_TX_PWR_DEFAULT, MFALSE}, + {153, 5765, WLAN_TX_PWR_DEFAULT, MFALSE}, + {157, 5785, WLAN_TX_PWR_DEFAULT, MFALSE}, + {161, 5805, WLAN_TX_PWR_DEFAULT, MFALSE}, + {165, 5825, WLAN_TX_PWR_DEFAULT, MFALSE} +}; + /** * The 5GHz CFP tables */ @@ -356,11 +461,42 @@ static cfp_table_t cfp_table_A[] = { sizeof(channel_freq_power_CN_A) / sizeof(chan_freq_power_t), } , + {0xfe, /* JAPAN */ + channel_freq_power_NULL_A, + sizeof(channel_freq_power_NULL_A) / sizeof(chan_freq_power_t), + } + , {0xff, /* Special */ channel_freq_power_JPN_A, sizeof(channel_freq_power_JPN_A) / sizeof(chan_freq_power_t), } , + {0x1, /* Low band (5150-5250 MHz) channels */ + channel_freq_power_low_band, + sizeof(channel_freq_power_low_band) / sizeof(chan_freq_power_t) + } + , + {0x2, /* Lower middle band (5250-5350 MHz) channels */ + channel_freq_power_lower_middle_band, + sizeof(channel_freq_power_lower_middle_band) / sizeof(chan_freq_power_t) + } + , + {0x3, /* Upper middle band (5470-5725 MHz) channels */ + channel_freq_power_upper_middle_band, + sizeof(channel_freq_power_upper_middle_band) / sizeof(chan_freq_power_t) + } + , + {0x4, /* High band (5725-5850 MHz) channels */ + channel_freq_power_high_band, + sizeof(channel_freq_power_high_band) / sizeof(chan_freq_power_t) + } + , + {0x5, /* Low band (5150-5250 MHz) and High band + (5725-5850 MHz) channels */ + channel_freq_power_low_high_band, + sizeof(channel_freq_power_low_high_band) / sizeof(chan_freq_power_t) + } + , /* Add new region here */ }; @@ -374,7 +510,13 @@ static cfp_table_t cfp_table_A[] = { * The table to keep region code */ t_u16 region_code_index[MRVDRV_MAX_REGION_CODE] = - { 0x10, 0x20, 0x30, 0x32, 0x40, 0x41, 0x50, 0xff }; + { 0x10, 0x20, 0x30, 0x32, 0x40, 0x41, 0x50, 0xfe, 0xff }; + +/** The table to keep CFP code for BG */ +t_u16 cfp_code_index_bg[MRVDRV_MAX_CFP_CODE_BG] = { }; + +/** The table to keep CFP code for A */ +t_u16 cfp_code_index_a[MRVDRV_MAX_CFP_CODE_A] = { 0x1, 0x2, 0x3, 0x4, 0x5 }; /** * The rates supported for ad-hoc B mode @@ -494,6 +636,11 @@ wlan_get_region_cfp_table(pmlan_adapter pmadapter, t_u8 region, t_u8 band, ENTER(); cfp_bg = cfp_a = region; + if (!region) { + /* Invalid region code, use CFP code */ + cfp_bg = pmadapter->cfp_code_bg; + cfp_a = pmadapter->cfp_code_a; + } if (band & (BAND_B | BAND_G | BAND_GN)) { for (i = 0; i < MLAN_CFP_TABLE_SIZE_BG; i++) { @@ -521,7 +668,11 @@ wlan_get_region_cfp_table(pmlan_adapter pmadapter, t_u8 region, t_u8 band, } } - PRINTM(MERROR, "Error Band[0x%x] or region[%#x]\n", band, region); + if (!region) + PRINTM(MERROR, "Error Band[0x%x] or code[BG:%#x, A:%#x]\n", + band, cfp_bg, cfp_a); + else + PRINTM(MERROR, "Error Band[0x%x] or region[%#x]\n", band, region); LEAVE(); return MNULL; @@ -530,6 +681,38 @@ wlan_get_region_cfp_table(pmlan_adapter pmadapter, t_u8 region, t_u8 band, /******************************************************** Global Functions ********************************************************/ +/** + * @brief This function converts region string to integer code + * + * @param pmadapter A pointer to mlan_adapter structure + * @param country_code Country string + * @param cfp_bg Pointer to buffer + * @param cfp_a Pointer to buffer + * + * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE + */ +mlan_status +wlan_misc_country_2_cfp_table_code(pmlan_adapter pmadapter, t_u8 * country_code, + t_u8 * cfp_bg, t_u8 * cfp_a) +{ + t_u8 i; + + ENTER(); + + /* Look for code in mapping table */ + for (i = 0; i < NELEMENTS(country_code_mapping); i++) { + if (!memcmp(pmadapter, country_code_mapping[i].country_code, + country_code, COUNTRY_CODE_LEN - 1)) { + *cfp_bg = country_code_mapping[i].cfp_code_bg; + *cfp_a = country_code_mapping[i].cfp_code_a; + LEAVE(); + return MLAN_STATUS_SUCCESS; + } + } + + LEAVE(); + return MLAN_STATUS_FAILURE; +} #ifdef STA_SUPPORT #endif /* STA_SUPPORT */ @@ -1137,7 +1320,7 @@ wlan_get_cfp_radar_detect(mlan_private * priv, t_u8 chnl) /* get the radar detection requirements according to chan num */ for (j = 0; j < priv->adapter->region_channel[i].num_cfp; j++) { if (pcfp[j].channel == chnl) { - required = pcfp[j].radar_detect; + required = pcfp[j].passive_scan_or_radar_detect; break; } } @@ -1146,3 +1329,50 @@ wlan_get_cfp_radar_detect(mlan_private * priv, t_u8 chnl) LEAVE(); return required; } + +/** + * @brief Get if scan type is passive or not on a certain channel for b/g band + * + * @param priv Private driver information structure + * @param chnl Channel to determine scan type + * + * @return + * - MTRUE if scan type is passive + * - MFALSE otherwise + */ + +t_bool +wlan_bg_scan_type_is_passive(mlan_private * priv, t_u8 chnl) +{ + int i, j; + t_bool passive = MFALSE; + chan_freq_power_t *pcfp = MNULL; + + ENTER(); + + /* get the cfp table first */ + for (i = 0; i < MAX_REGION_CHANNEL_NUM; i++) { + if (priv->adapter->region_channel[i].band & (BAND_B | BAND_G)) { + pcfp = priv->adapter->region_channel[i].pcfp; + break; + } + } + + if (!pcfp) { + /* This means operation in BAND-B or BAND_G is not support, we can + just return false here */ + goto done; + } + + /* get the bg scan type according to chan num */ + for (j = 0; j < priv->adapter->region_channel[i].num_cfp; j++) { + if (pcfp[j].channel == chnl) { + passive = pcfp[j].passive_scan_or_radar_detect; + break; + } + } + + done: + LEAVE(); + return passive; +} diff --git a/drivers/net/wireless/sd8797/mlan/mlan_cmdevt.c b/drivers/net/wireless/sd8797/mlan/mlan_cmdevt.c index f3db9e662565..a3e5ef0517f0 100644 --- a/drivers/net/wireless/sd8797/mlan/mlan_cmdevt.c +++ b/drivers/net/wireless/sd8797/mlan/mlan_cmdevt.c @@ -344,7 +344,9 @@ wlan_dnld_cmd_to_fw(IN mlan_private * pmpriv, IN cmd_ctrl_node * pcmd_node) mlan_ioctl_req *pioctl_buf = MNULL; t_u16 cmd_code; t_u16 cmd_size; +#ifdef DEBUG_LEVEL1 t_u32 sec, usec; +#endif ENTER(); @@ -389,8 +391,7 @@ wlan_dnld_cmd_to_fw(IN mlan_private * pmpriv, IN cmd_ctrl_node * pcmd_node) pcmd_node->cmdbuf->data_len = cmd_size; - pmadapter->callbacks.moal_get_system_time(pmadapter->pmoal_handle, &sec, - &usec); + PRINTM_GET_SYS_TIME(MCMND, &sec, &usec); PRINTM_NETINTF(MCMND, pmpriv); PRINTM(MCMND, "DNLD_CMD (%lu.%06lu): 0x%x, act 0x%x, len %d, seqno 0x%x\n", sec, usec, cmd_code, @@ -690,8 +691,9 @@ wlan_process_event(pmlan_adapter pmadapter) pmlan_private priv = wlan_get_priv(pmadapter, MLAN_BSS_ROLE_ANY); pmlan_buffer pmbuf = pmadapter->pmlan_buffer_event; t_u32 eventcause = pmadapter->event_cause; - t_u32 in_ts_sec; - t_u32 in_ts_usec; +#ifdef DEBUG_LEVEL1 + t_u32 in_ts_sec, in_ts_usec; +#endif ENTER(); /* Save the last event to debug log */ @@ -726,8 +728,7 @@ wlan_process_event(pmlan_adapter pmadapter) if (MTRUE && (eventcause != EVENT_PS_SLEEP && eventcause != EVENT_PS_AWAKE) ) { - pmadapter->callbacks.moal_get_system_time(pmadapter->pmoal_handle, - &in_ts_sec, &in_ts_usec); + PRINTM_GET_SYS_TIME(MEVENT, &in_ts_sec, &in_ts_usec); PRINTM_NETINTF(MEVENT, priv); PRINTM(MEVENT, "%lu.%06lu : Event: 0x%x\n", in_ts_sec, in_ts_usec, eventcause); @@ -1109,7 +1110,10 @@ wlan_process_cmdresp(mlan_adapter * pmadapter) t_u16 cmdresp_result; mlan_ioctl_req *pioctl_buf = MNULL; mlan_callbacks *pcb = (mlan_callbacks *) & pmadapter->callbacks; - t_u32 sec, usec, i; +#ifdef DEBUG_LEVEL1 + t_u32 sec, usec; +#endif + t_u32 i; ENTER(); @@ -1189,8 +1193,7 @@ wlan_process_cmdresp(mlan_adapter * pmadapter) pmadapter->dbg.last_cmd_resp_id[pmadapter->dbg.last_cmd_resp_index] = orig_cmdresp_no; - pmadapter->callbacks.moal_get_system_time(pmadapter->pmoal_handle, &sec, - &usec); + PRINTM_GET_SYS_TIME(MCMND, &sec, &usec); PRINTM_NETINTF(MCMND, pmadapter->curr_cmd->priv); PRINTM(MCMND, "CMD_RESP (%lu.%06lu): 0x%x, result %d, len %d, seqno 0x%x\n", sec, usec, orig_cmdresp_no, cmdresp_result, resp->size, @@ -1301,7 +1304,9 @@ wlan_cmd_timeout_func(t_void * function_context) mlan_adapter *pmadapter = (mlan_adapter *) function_context; cmd_ctrl_node *pcmd_node = MNULL; mlan_ioctl_req *pioctl_buf = MNULL; +#ifdef DEBUG_LEVEL1 t_u32 sec, usec; +#endif t_u8 i; mlan_private *pmpriv = MNULL; @@ -1325,8 +1330,7 @@ wlan_cmd_timeout_func(t_void * function_context) pmadapter->dbg.last_cmd_id[pmadapter->dbg.last_cmd_index]; pmadapter->dbg.timeout_cmd_act = pmadapter->dbg.last_cmd_act[pmadapter->dbg.last_cmd_index]; - pmadapter->callbacks.moal_get_system_time(pmadapter->pmoal_handle, &sec, - &usec); + PRINTM_GET_SYS_TIME(MERROR, &sec, &usec); PRINTM(MERROR, "Timeout cmd id (%lu.%06lu) = 0x%x, act = 0x%x \n", sec, usec, pmadapter->dbg.timeout_cmd_id, pmadapter->dbg.timeout_cmd_act); @@ -2719,6 +2723,9 @@ wlan_ret_get_hw_spec(IN pmlan_private pmpriv, PRINTM(MWARN, "unidentified region code, use the default (0x%02x)\n", MRVDRV_DEFAULT_REGION_CODE); } + /* Synchronize CFP code with region code */ + pmadapter->cfp_code_bg = pmadapter->region_code; + pmadapter->cfp_code_a = pmadapter->region_code; if (wlan_set_regiontable(pmpriv, (t_u8) pmadapter->region_code, pmadapter->fw_bands)) { diff --git a/drivers/net/wireless/sd8797/mlan/mlan_decl.h b/drivers/net/wireless/sd8797/mlan/mlan_decl.h index d0ca7acae937..41cf2bf5f2f1 100644 --- a/drivers/net/wireless/sd8797/mlan/mlan_decl.h +++ b/drivers/net/wireless/sd8797/mlan/mlan_decl.h @@ -27,7 +27,7 @@ Change log: #define _MLAN_DECL_H_ /** MLAN release version */ -#define MLAN_RELEASE_VERSION "303" +#define MLAN_RELEASE_VERSION "311" /** Re-define generic data types for MLAN/MOAL */ /** Signed char (1-byte) */ @@ -136,10 +136,18 @@ typedef t_s32 t_sval; /** This is current limit on Maximum Rx AMPDU allowed */ #define MLAN_MAX_RX_BASTREAM_SUPPORTED 16 +#ifdef STA_SUPPORT /** Default Win size attached during ADDBA request */ -#define MLAN_AMPDU_DEF_TXWINSIZE 32 +#define MLAN_STA_AMPDU_DEF_TXWINSIZE 16 /** Default Win size attached during ADDBA response */ -#define MLAN_AMPDU_DEF_RXWINSIZE 16 +#define MLAN_STA_AMPDU_DEF_RXWINSIZE 32 +#endif /* STA_SUPPORT */ +#ifdef UAP_SUPPORT +/** Default Win size attached during ADDBA request */ +#define MLAN_UAP_AMPDU_DEF_TXWINSIZE 32 +/** Default Win size attached during ADDBA response */ +#define MLAN_UAP_AMPDU_DEF_RXWINSIZE 16 +#endif /* UAP_SUPPORT */ /** Block ack timeout value */ #define MLAN_DEFAULT_BLOCK_ACK_TIMEOUT 0xffff /** Maximum Tx Win size configured for ADDBA request [10 bits] */ @@ -626,6 +634,8 @@ typedef MLAN_PACK_START struct _custom_ie t_u8 ie_buffer[MAX_IE_SIZE]; } MLAN_PACK_END custom_ie; +/** Max IE index to FW */ +#define MAX_MGMT_IE_INDEX_TO_FW 4 /** Max IE index per BSS */ #define MAX_MGMT_IE_INDEX 16 @@ -659,7 +669,7 @@ typedef MLAN_PACK_START struct _tlvbuf_custom_ie /** Length */ t_u16 len; /** IE data */ - custom_ie ie_data_list[MAX_MGMT_IE_INDEX]; + custom_ie ie_data_list[MAX_MGMT_IE_INDEX_TO_FW]; /** Max mgmt IE TLV */ tlvbuf_max_mgmt_ie max_mgmt_ie; } MLAN_PACK_END mlan_ds_misc_custom_ie; diff --git a/drivers/net/wireless/sd8797/mlan/mlan_fw.h b/drivers/net/wireless/sd8797/mlan/mlan_fw.h index 1b0af8d8c0ea..fda2e7285dfd 100644 --- a/drivers/net/wireless/sd8797/mlan/mlan_fw.h +++ b/drivers/net/wireless/sd8797/mlan/mlan_fw.h @@ -148,6 +148,11 @@ typedef enum _KEY_TYPE_ID KEY_TYPE_ID_WAPI, } KEY_TYPE_ID; +/** Key Info flag for multicast key */ +#define KEY_INFO_MCAST_KEY 0x01 +/** Key Info flag for unicast key */ +#define KEY_INFO_UCAST_KEY 0x02 + /** KEY_INFO_WEP*/ typedef enum _KEY_INFO_WEP { @@ -311,9 +316,10 @@ typedef enum _WLAN_802_11_WEP_STATUS #define TLV_TYPE_RSSI_HIGH (PROPRIETARY_TLV_BASE_ID + 0x16) // 0x0116 /** TLV type : Beacon SNR high */ #define TLV_TYPE_SNR_HIGH (PROPRIETARY_TLV_BASE_ID + 0x17) // 0x0117 - /** TLV type : Start BG scan later */ #define TLV_TYPE_STARTBGSCANLATER (PROPRIETARY_TLV_BASE_ID + 0x1e) // 0x011e +/** TLV type: BG scan repeat count */ +#define TLV_TYPE_REPEAT_COUNT (PROPRIETARY_TLV_BASE_ID + 0xb0) // 0x01b0 /** TLV type : Authentication type */ #define TLV_TYPE_AUTH_TYPE (PROPRIETARY_TLV_BASE_ID + 0x1f) // 0x011f /** TLV type : BSSID */ @@ -397,7 +403,7 @@ typedef enum _WLAN_802_11_WEP_STATUS #define BA_STREAM_NOT_ALLOWED 0xff /** Test if 11n is enabled by checking the HTCap IE */ -#define IS_11N_ENABLED(priv) ((priv->adapter->config_bands & BAND_GN ||priv->adapter->config_bands & BAND_AN) \ +#define IS_11N_ENABLED(priv) ((priv->config_bands & BAND_GN ||priv->config_bands & BAND_AN) \ && priv->curr_bss_params.bss_descriptor.pht_cap) /** Find out if we are the initiator or not */ #define INITIATOR_BIT(DelBAParamSet) (((DelBAParamSet) & \ @@ -848,6 +854,9 @@ typedef enum _WLAN_802_11_WEP_STATUS #define HostCmd_CMD_802_11_REMAIN_ON_CHANNEL 0x010d #endif +/** Host Command ID : OTP user data */ +#define HostCmd_CMD_OTP_READ_USER_DATA 0x0114 + /** Enhanced PS modes */ typedef enum _ENH_PS_MODES { @@ -2806,6 +2815,25 @@ typedef MLAN_PACK_START struct _HostCmd_DS_802_11_BG_SCAN_QUERY_RSP HostCmd_DS_802_11_SCAN_RSP scan_resp; } MLAN_PACK_END HostCmd_DS_802_11_BG_SCAN_QUERY_RSP; +/** MrvlIEtypes_StartLater_t */ +typedef MLAN_PACK_START struct _MrvlIEtypes_StartLater_t +{ + /** Header */ + MrvlIEtypesHeader_t header; + /* 0 - BGScan start immediately, 1 - BGScan will start later after "Scan + Interval" */ + t_u16 value; +} MLAN_PACK_END MrvlIEtypes_StartLater_t; + +/** MrvlIEtypes_RepeatCount_t */ +typedef MLAN_PACK_START struct _MrvlIEtypes_RepeatCount_t +{ + /** Header */ + MrvlIEtypesHeader_t header; + /* Repeat count */ + t_u16 repeat_count; +} MLAN_PACK_END MrvlIEtypes_RepeatCount_t; + /** MrvlIEtypes_DomainParamSet_t */ typedef MLAN_PACK_START struct _MrvlIEtypes_DomainParamSet { @@ -3540,6 +3568,19 @@ typedef MLAN_PACK_START struct _HostCmd_DS_SUBSCRIBE_EVENT t_u16 event_bitmap; } MLAN_PACK_END HostCmd_DS_SUBSCRIBE_EVENT; +/** HostCmd_DS_OTP_USER_DATA */ +typedef MLAN_PACK_START struct _HostCmd_DS_OTP_USER_DATA +{ + /** Action */ + t_u16 action; + /** Reserved field */ + t_u16 reserved; + /** User data length */ + t_u16 user_data_length; + /** User data */ + t_u8 user_data[1]; +} MLAN_PACK_END HostCmd_DS_OTP_USER_DATA; + /** HostCmd_DS_INACTIVITY_TIMEOUT_EXT */ typedef MLAN_PACK_START struct _HostCmd_DS_INACTIVITY_TIMEOUT_EXT { @@ -4495,6 +4536,7 @@ typedef struct MLAN_PACK_START _HostCmd_DS_COMMAND HostCmd_DS_802_11_BG_SCAN_QUERY bg_scan_query; HostCmd_DS_802_11_BG_SCAN_QUERY_RSP bg_scan_query_resp; HostCmd_DS_SUBSCRIBE_EVENT subscribe_event; + HostCmd_DS_OTP_USER_DATA otp_user_data; /** Associate */ HostCmd_DS_802_11_ASSOCIATE associate; diff --git a/drivers/net/wireless/sd8797/mlan/mlan_ieee.h b/drivers/net/wireless/sd8797/mlan/mlan_ieee.h index 9473c498b973..2431e06f48fa 100644 --- a/drivers/net/wireless/sd8797/mlan/mlan_ieee.h +++ b/drivers/net/wireless/sd8797/mlan/mlan_ieee.h @@ -27,6 +27,8 @@ Change log: #ifndef _MLAN_IEEE_H_ #define _MLAN_IEEE_H_ +/** FIX IES size in beacon buffer */ +#define WLAN_802_11_FIXED_IE_SIZE 12 /** WLAN supported rates */ #define WLAN_SUPPORTED_RATES 14 @@ -1179,6 +1181,8 @@ typedef MLAN_PACK_START struct t_u8 rssi_threshold; /** SNR threshold */ t_u8 snr_threshold; + /** repeat count */ + t_u16 repeat_count; /** SSID filter list used in the to limit the scan results */ wlan_user_scan_ssid ssid_list[MRVDRV_MAX_SSID_LIST_LENGTH]; /** Variable number (fixed maximum) of channels to scan up */ diff --git a/drivers/net/wireless/sd8797/mlan/mlan_init.c b/drivers/net/wireless/sd8797/mlan/mlan_init.c index 563f74cd3980..48681b3e3ed9 100644 --- a/drivers/net/wireless/sd8797/mlan/mlan_init.c +++ b/drivers/net/wireless/sd8797/mlan/mlan_init.c @@ -312,10 +312,17 @@ wlan_init_priv(pmlan_private priv) priv->bcn_rssi_avg = 0; priv->bcn_nf_avg = 0; priv->bcn_nf_last = 0; + + priv->sec_info.ewpa_enabled = MFALSE; + priv->sec_info.wpa_enabled = MFALSE; + priv->sec_info.wpa2_enabled = MFALSE; memset(pmadapter, &priv->wpa_ie, 0, sizeof(priv->wpa_ie)); memset(pmadapter, &priv->aes_key, 0, sizeof(priv->aes_key)); priv->wpa_ie_len = 0; priv->wpa_is_gtk_set = MFALSE; + priv->sec_info.wapi_enabled = MFALSE; + priv->wapi_ie_len = 0; + priv->sec_info.wapi_key_on = MFALSE; memset(pmadapter, &priv->wps, 0, sizeof(priv->wps)); memset(pmadapter, &priv->gen_ie_buf, 0, sizeof(priv->gen_ie_buf)); @@ -362,7 +369,6 @@ wlan_init_priv(pmlan_private priv) t_void wlan_init_adapter(pmlan_adapter pmadapter) { - int i; opt_sleep_confirm_buffer *sleep_cfm_buf = MNULL; ENTER(); @@ -391,9 +397,6 @@ wlan_init_adapter(pmlan_adapter pmadapter) pmadapter->mp_wr_bitmap = 0; pmadapter->curr_rd_port = 1; pmadapter->curr_wr_port = 1; - for (i = 0; i < MAX_NUM_TID; i++) { - pmadapter->tx_eligibility[i] = 1; - } pmadapter->mp_data_port_mask = DATA_PORT_MASK; #ifdef SDIO_MULTI_PORT_TX_AGGR @@ -559,6 +562,8 @@ wlan_init_adapter(pmlan_adapter pmadapter) memset(pmadapter, &pmadapter->region_channel, 0, sizeof(pmadapter->region_channel)); pmadapter->region_code = 0; + memcpy(pmadapter, pmadapter->country_code, MRVDRV_DEFAULT_COUNTRY_CODE, + COUNTRY_CODE_LEN); pmadapter->bcn_miss_time_out = DEFAULT_BCN_MISS_TIMEOUT; pmadapter->adhoc_awake_period = 0; #ifdef STA_SUPPORT diff --git a/drivers/net/wireless/sd8797/mlan/mlan_ioctl.h b/drivers/net/wireless/sd8797/mlan/mlan_ioctl.h index 15e88e631067..964de9197ffe 100644 --- a/drivers/net/wireless/sd8797/mlan/mlan_ioctl.h +++ b/drivers/net/wireless/sd8797/mlan/mlan_ioctl.h @@ -82,6 +82,7 @@ enum _mlan_ioctl_req_id MLAN_OID_SNMP_MIB_DOT11D, MLAN_OID_SNMP_MIB_DOT11H, #endif + MLAN_OID_SNMP_MIB_DTIM_PERIOD, /* Status Information Group */ MLAN_IOCTL_GET_INFO = 0x00050000, @@ -204,12 +205,15 @@ enum _mlan_ioctl_req_id MLAN_OID_MISC_IP_ADDR, MLAN_OID_MISC_MAC_CONTROL, MLAN_OID_MISC_MEF_CFG, + MLAN_OID_MISC_CFP_CODE, + MLAN_OID_MISC_COUNTRY_CODE, MLAN_OID_MISC_THERMAL, MLAN_OID_MISC_RX_MGMT_IND, MLAN_OID_MISC_SUBSCRIBE_EVENT, #ifdef DEBUG_LEVEL1 MLAN_OID_MISC_DRVDBG, #endif + MLAN_OID_MISC_OTP_USER_DATA, }; /** Sub command size */ @@ -1041,6 +1045,8 @@ typedef struct _mlan_ds_snmp_mib /** OID value for MLAN_OID_SNMP_MIB_DOT11D/H */ t_u32 oid_value; #endif + /** DTIM period for MLAN_OID_SNMP_MIB_DTIM_PERIOD */ + t_u32 dtim_period; } param; } mlan_ds_snmp_mib, *pmlan_ds_snmp_mib; @@ -1266,6 +1272,8 @@ typedef struct _mlan_bss_info #ifdef STA_SUPPORT /** Capability Info */ t_u16 capability_info; + /** Beacon Interval */ + t_u16 beacon_interval; /** Listen Interval */ t_u16 listen_interval; /** Association Id */ @@ -1442,7 +1450,7 @@ typedef struct _mlan_debug_info #ifdef UAP_SUPPORT /** Maximum number of clients supported by AP */ -#define MAX_NUM_CLIENTS 16 +#define MAX_NUM_CLIENTS MAX_STA_COUNT /** station info */ typedef struct _sta_info @@ -1553,7 +1561,7 @@ enum _mlan_psk_type /** key flag for rx_seq */ #define KEY_FLAG_RX_SEQ_VALID 0x00000002 /** key flag for group key */ -#define KEY_FLAG_GROUP_KEY 0x00000004 +#define KEY_FLAG_GROUP_KEY 0x00000004 /** key flag for tx and rx */ #define KEY_FLAG_SET_TX_KEY 0x00000008 /** key flag for remove key */ @@ -1600,6 +1608,24 @@ typedef struct _mlan_pmk_t t_u8 pmk[MLAN_MAX_KEY_LENGTH]; } mlan_pmk_t; +/** Embedded supplicant RSN type: No RSN */ +#define RSN_TYPE_NO_RSN MBIT(0) +/** Embedded supplicant RSN type: WPA */ +#define RSN_TYPE_WPA MBIT(3) +/** Embedded supplicant RSN type: WPA-NONE */ +#define RSN_TYPE_WPANONE MBIT(4) +/** Embedded supplicant RSN type: WPA2 */ +#define RSN_TYPE_WPA2 MBIT(5) +/** Embedded supplicant RSN type: RFU */ +#define RSN_TYPE_VALID_BITS (RSN_TYPE_NO_RSN | RSN_TYPE_WPA | RSN_TYPE_WPANONE | RSN_TYPE_WPA2) + +/** Embedded supplicant cipher type: TKIP */ +#define EMBED_CIPHER_TKIP MBIT(2) +/** Embedded supplicant cipher type: AES */ +#define EMBED_CIPHER_AES MBIT(3) +/** Embedded supplicant cipher type: RFU */ +#define EMBED_CIPHER_VALID_BITS (EMBED_CIPHER_TKIP | EMBED_CIPHER_AES) + /** Type definition of mlan_ds_passphrase for MLAN_OID_SEC_CFG_PASSPHRASE */ typedef struct _mlan_ds_passphrase { @@ -2545,7 +2571,7 @@ enum _mlan_reg_type MLAN_REG_MAC = 1, MLAN_REG_BBP, MLAN_REG_RF, - MLAN_REG_CAU, + MLAN_REG_CAU = 5, }; /** Type definition of mlan_ds_reg_rw for MLAN_OID_REG_RW */ @@ -2782,6 +2808,22 @@ typedef struct _mlan_ds_misc_mef_cfg } param; } mlan_ds_misc_mef_cfg; +/** Type definition of mlan_ds_misc_cfp_code for MLAN_OID_MISC_CFP_CODE */ +typedef struct _mlan_ds_misc_cfp_code +{ + /** CFP table code for 2.4GHz */ + t_u32 cfp_code_bg; + /** CFP table code for 5GHz */ + t_u32 cfp_code_a; +} mlan_ds_misc_cfp_code; + +/** Type definition of mlan_ds_misc_country_code for MLAN_OID_MISC_COUNTRY_CODE */ +typedef struct _mlan_ds_misc_country_code +{ + /** Country Code */ + t_u8 country_code[COUNTRY_CODE_LEN]; +} mlan_ds_misc_country_code; + /** BITMAP for subscribe event rssi low */ #define SUBSCRIBE_EVT_RSSI_LOW MBIT(0) /** BITMAP for subscribe event snr low */ @@ -2806,6 +2848,8 @@ typedef struct _mlan_ds_misc_mef_cfg #define SUBSCRIBE_EVT_LINK_QUALITY MBIT(10) /** BITMAP for subscribe event pre_beacon_lost */ #define SUBSCRIBE_EVT_PRE_BEACON_LOST MBIT(11) +/** default PRE_BEACON_MISS_COUNT */ +#define DEFAULT_PRE_BEACON_MISS 30 /** Type definition of mlan_ds_subscribe_evt for MLAN_OID_MISC_CFP_CODE */ typedef struct _mlan_ds_subscribe_evt @@ -2868,6 +2912,20 @@ typedef struct _mlan_ds_subscribe_evt t_u8 pre_beacon_miss; } mlan_ds_subscribe_evt; +/** Max OTP user data length */ +#define MAX_OTP_USER_DATA_LEN 252 + +/** Type definition of mlan_ds_misc_otp_user_data for MLAN_OID_MISC_OTP_USER_DATA */ +typedef struct _mlan_ds_misc_otp_user_data +{ + /** Reserved */ + t_u16 reserved; + /** OTP user data length */ + t_u16 user_data_length; + /** User data buffer */ + t_u8 user_data[MAX_OTP_USER_DATA_LEN]; +} mlan_ds_misc_otp_user_data; + /** Type definition of mlan_ds_misc_cfg for MLAN_IOCTL_MISC_CFG */ typedef struct _mlan_ds_misc_cfg { @@ -2902,6 +2960,10 @@ typedef struct _mlan_ds_misc_cfg t_u32 mac_ctrl; /** MEF configuration for MLAN_OID_MISC_MEF_CFG */ mlan_ds_misc_mef_cfg mef_cfg; + /** CFP code for MLAN_OID_MISC_CFP_CODE */ + mlan_ds_misc_cfp_code cfp_code; + /** Country code for MLAN_OID_MISC_COUNTRY_CODE */ + mlan_ds_misc_country_code country_code; /** Thermal reading for MLAN_OID_MISC_THERMAL */ t_u32 thermal; /** Mgmt subtype mask for MLAN_OID_MISC_RX_MGMT_IND */ @@ -2912,6 +2974,7 @@ typedef struct _mlan_ds_misc_cfg /** Driver debug bit masks */ t_u32 drvdbg; #endif + mlan_ds_misc_otp_user_data otp_user_data; } param; } mlan_ds_misc_cfg, *pmlan_ds_misc_cfg; diff --git a/drivers/net/wireless/sd8797/mlan/mlan_main.h b/drivers/net/wireless/sd8797/mlan/mlan_main.h index fb15c7226c38..44e4f8001201 100644 --- a/drivers/net/wireless/sd8797/mlan/mlan_main.h +++ b/drivers/net/wireless/sd8797/mlan/mlan_main.h @@ -4,7 +4,7 @@ * structures and declares global function prototypes used * in MLAN module. * - * Copyright (C) 2008-2011, Marvell International Ltd. + * Copyright (C) 2008-2012, Marvell International Ltd. * * This software file (the "File") is distributed by Marvell International * Ltd. under the terms of the GNU General Public License Version 2, June 1991 @@ -31,6 +31,11 @@ Change log: #ifdef DEBUG_LEVEL1 extern t_void(*print_callback) (IN t_void * pmoal_handle, IN t_u32 level, IN t_s8 * pformat, IN ...); + +extern mlan_status(*get_sys_time_callback) (IN t_void * pmoal_handle, + OUT t_u32 * psec, + OUT t_u32 * pusec); + extern t_u32 drvdbg; #ifdef DEBUG_LEVEL2 @@ -40,10 +45,35 @@ extern t_u32 drvdbg; print_callback(MNULL, MWARN, msg);} while(0) #define PRINTM_MENTRY(msg...) do {if ((drvdbg & MENTRY) && (print_callback)) \ print_callback(MNULL, MENTRY, msg);} while(0) +#define PRINTM_GET_SYS_TIME(level, psec, pusec) \ +do { \ + if ((level & drvdbg) && (get_sys_time_callback)) \ + get_sys_time_callback(MNULL, psec, pusec); \ +} while (0) + +/** Hexdump for level-2 debugging */ +#define HEXDUMP(x,y,z) \ +do { \ + if ((drvdbg & (MHEX_DUMP | MINFO)) && (print_callback)) \ + print_callback(MNULL, MHEX_DUMP | MINFO, x, y, z); \ +} while (0) + #else + #define PRINTM_MINFO(msg...) do {} while (0) #define PRINTM_MWARN(msg...) do {} while (0) #define PRINTM_MENTRY(msg...) do {} while (0) + +#define PRINTM_GET_SYS_TIME(level, psec, pusec) \ +do { \ + if ((level & drvdbg) && (get_sys_time_callback) \ + && (level != MINFO) && (level != MWARN)) \ + get_sys_time_callback(MNULL, psec, pusec); \ +} while (0) + +/** Hexdump for debugging */ +#define HEXDUMP(x,y,z) do {} while (0) + #endif /* DEBUG_LEVEL2 */ #define PRINTM_MFW_D(msg...) do {if ((drvdbg & MFW_D) && (print_callback)) \ @@ -74,20 +104,6 @@ extern t_u32 drvdbg; #define PRINTM(level,msg...) PRINTM_##level(msg) -#ifdef DEBUG_LEVEL2 - -/** Hexdump for level-2 debugging */ -#define HEXDUMP(x,y,z) \ -do { \ - if ((drvdbg & (MHEX_DUMP | MINFO)) && (print_callback)) \ - print_callback(MNULL, MHEX_DUMP | MINFO, x, y, z); \ -} while (0) -#else - -/** Hexdump for debugging */ -#define HEXDUMP(x,y,z) do {} while (0) -#endif /* DEBUG_LEVEL2 */ - /** Log debug message */ #ifdef __GNUC__ #define PRINTM_NETINTF(level, pmpriv) \ @@ -122,6 +138,8 @@ do { \ /** Hexdump for debugging */ #define HEXDUMP(x,y,z) do {} while (0) +#define PRINTM_GET_SYS_TIME(level, psec, pusec) do { } while(0) + #endif /* DEBUG_LEVEL1 */ /** Log entry point for debugging */ @@ -330,11 +348,19 @@ do { \ #define MLAN_DEFAULT_LISTEN_INTERVAL 10 /** Maximum number of region codes */ -#define MRVDRV_MAX_REGION_CODE 8 +#define MRVDRV_MAX_REGION_CODE 9 + +/** Maximum number of CFP codes for BG */ +#define MRVDRV_MAX_CFP_CODE_BG 0 +/** Maximum number of CFP codes for A */ +#define MRVDRV_MAX_CFP_CODE_A 5 /** Default region code */ #define MRVDRV_DEFAULT_REGION_CODE 0x10 +/** Default country code */ +#define MRVDRV_DEFAULT_COUNTRY_CODE "US" + /** Default factor for calculating beacon average */ #define DEFAULT_BCN_AVG_FACTOR 8 /** Default factor for calculating data average */ @@ -722,8 +748,9 @@ typedef struct _chan_freq_power_t t_u32 freq; /** Max allowed Tx power level */ t_u16 max_tx_power; - /** TRUE:radar detect required; FALSE:radar detect not required*/ - t_bool radar_detect; + /** TRUE:radar detect required for BAND A or passive scan for BAND B/G; + * FALSE:radar detect not required for BAND A or active scan for BAND B/G*/ + t_bool passive_scan_or_radar_detect; /** TRUE:channel unsupported; FALSE:supported */ t_u8 unsupported; } chan_freq_power_t; @@ -1368,7 +1395,7 @@ typedef struct _sdio_mpa_tx /** multiport tx aggregation packet count */ t_u32 pkt_cnt; /** multiport tx aggregation ports */ - t_u16 ports; + t_u32 ports; /** multiport tx aggregation starting port */ t_u16 start_port; /** multiport tx aggregation enable/disable flag */ @@ -1393,7 +1420,7 @@ typedef struct _sdio_mpa_rx /** multiport rx aggregation packet count */ t_u32 pkt_cnt; /** multiport rx aggregation ports */ - t_u16 ports; + t_u32 ports; /** multiport rx aggregation starting port */ t_u16 start_port; @@ -1511,8 +1538,6 @@ typedef struct _mlan_adapter t_u8 *mp_regs; /** allocated buf to read SDIO multiple port group registers */ t_u8 *mp_regs_buf; - /** Array to store data transfer eligibility based on tid (QoS-over-SDIO) */ - t_u8 tx_eligibility[MAX_NUM_TID]; #ifdef SDIO_MULTI_PORT_TX_AGGR /** data structure for SDIO MPA TX */ @@ -1596,6 +1621,10 @@ typedef struct _mlan_adapter t_u16 region_code; /** Region Channel data */ region_chan_t region_channel[MAX_REGION_CHANNEL_NUM]; + /** CFP table code for 2.4GHz */ + t_u8 cfp_code_bg; + /** CFP table code for 5GHz */ + t_u8 cfp_code_a; #ifdef STA_SUPPORT /** Universal Channel data */ region_chan_t universal_channel[MAX_REGION_CHANNEL_NUM]; @@ -1604,6 +1633,8 @@ typedef struct _mlan_adapter #endif /* STA_SUPPORT */ /** 11D and Domain Regulatory Data */ wlan_802_11d_domain_reg_t domain_reg; + /** Country Code */ + t_u8 country_code[COUNTRY_CODE_LEN]; /** FSM variable for 11h support */ wlan_11h_device_state_t state_11h; /** FSM variable for DFS support */ @@ -1620,6 +1651,7 @@ typedef struct _mlan_adapter BSSDescriptor_t *pscan_table; /** scan age in secs */ t_u32 age_in_secs; + t_u8 bgscan_reported; /** Number of records in the scan table */ t_u32 num_in_scan_table; @@ -2177,6 +2209,9 @@ mlan_status wlan_cmd_bgscan_config(IN mlan_private * pmpriv, mlan_status wlan_ret_bgscan_config(IN mlan_private * pmpriv, IN HostCmd_DS_COMMAND * resp, IN mlan_ioctl_req * pioctl_buf); +mlan_status wlan_ret_802_11_bgscan_query(IN mlan_private * pmpriv, + IN HostCmd_DS_COMMAND * resp, + IN mlan_ioctl_req * pioctl_buf); /** Get Channel-Frequency-Power by band and channel */ chan_freq_power_t *wlan_get_cfp_by_band_and_channel(pmlan_adapter pmadapter, @@ -2221,10 +2256,16 @@ int wlan_get_rate_index(pmlan_adapter pmadapter, t_u16 * rateBitmap, int size); /* CFP related functions */ /** Region code index table */ extern t_u16 region_code_index[MRVDRV_MAX_REGION_CODE]; +/** The table to keep CFP code for BG */ +extern t_u16 cfp_code_index_bg[MRVDRV_MAX_CFP_CODE_BG]; +/** The table to keep CFP code for A */ +extern t_u16 cfp_code_index_a[MRVDRV_MAX_CFP_CODE_A]; /** Set region table */ mlan_status wlan_set_regiontable(mlan_private * pmpriv, t_u8 region, t_u8 band); /** Get radar detection requirements*/ t_bool wlan_get_cfp_radar_detect(mlan_private * priv, t_u8 chnl); +/** check if scan type is passive for b/g band*/ +t_bool wlan_bg_scan_type_is_passive(mlan_private * priv, t_u8 chnl); /* 802.11D related functions */ /** Initialize 11D */ @@ -2280,6 +2321,12 @@ mlan_status wlan_11d_handle_uap_domain_info(mlan_private * pmpriv, t_void * pioctl_buf); #endif +/** This function converts region string to CFP table code */ +mlan_status wlan_misc_country_2_cfp_table_code(IN pmlan_adapter pmadapter, + IN t_u8 * country_code, + OUT t_u8 * cfp_bg, + OUT t_u8 * cfp_a); + /** check if station list is empty */ t_u8 wlan_is_station_list_empty(mlan_private * priv); /** get station node */ @@ -2316,7 +2363,6 @@ wlan_is_tx_pause(mlan_private * priv, t_u8 * ra) t_void wlan_updata_ralist_tx_pause(pmlan_private priv, t_u8 * mac, t_u8 tx_pause); -sta_node *wlan_get_tx_pause_station_entry(mlan_private * priv); #ifdef UAP_SUPPORT mlan_status wlan_process_uap_rx_packet(IN mlan_private * priv, @@ -2366,6 +2412,9 @@ mlan_status wlan_set_drvdbg(IN pmlan_adapter pmadapter, IN pmlan_ioctl_req pioctl_req); #endif +mlan_status wlan_misc_otp_user_data(IN pmlan_adapter pmadapter, + IN pmlan_ioctl_req pioctl_req); + /** * @brief RA based queueing * diff --git a/drivers/net/wireless/sd8797/mlan/mlan_misc.c b/drivers/net/wireless/sd8797/mlan/mlan_misc.c index 929a38ab33f6..f41dcea3d206 100644 --- a/drivers/net/wireless/sd8797/mlan/mlan_misc.c +++ b/drivers/net/wireless/sd8797/mlan/mlan_misc.c @@ -970,7 +970,7 @@ wlan_misc_ioctl_custom_ie_list(IN pmlan_adapter pmadapter, goto done; } memset(pmadapter, ie_data, 0, - sizeof(custom_ie) * MAX_MGMT_IE_INDEX); + sizeof(custom_ie) * MAX_MGMT_IE_INDEX_TO_FW); len = 0; for (i = 0; i < pmadapter->max_mgmt_ie_index; i++) { memcpy(pmadapter, (t_u8 *) ie_data + len, &i, @@ -1042,7 +1042,7 @@ wlan_misc_ioctl_custom_ie_list(IN pmlan_adapter pmadapter, goto done; } memset(pmadapter, ie_data, 0, - sizeof(custom_ie) * MAX_MGMT_IE_INDEX); + sizeof(custom_ie) * MAX_MGMT_IE_INDEX_TO_FW); memcpy(pmadapter, (t_u8 *) ie_data, &pmpriv->mgmt_ie[index], pmpriv->mgmt_ie[index].ie_length + MLAN_CUSTOM_IE_HDR_SIZE); @@ -1280,41 +1280,6 @@ wlan_delete_station_list(pmlan_private priv) return; } -/** - * @brief This function will return the pointer to station entry in station list - * table which in tx_pause state - * - * @param priv A pointer to mlan_private - * - * @return A pointer to structure sta_node - */ -sta_node * -wlan_get_tx_pause_station_entry(mlan_private * priv) -{ - sta_node *sta_ptr; - - ENTER(); - - if (!(sta_ptr = (sta_node *) util_peek_list(priv->adapter->pmoal_handle, - &priv->sta_list, - priv->adapter->callbacks. - moal_spin_lock, - priv->adapter->callbacks. - moal_spin_unlock))) { - LEAVE(); - return MNULL; - } - while (sta_ptr != (sta_node *) & priv->sta_list) { - if (sta_ptr->tx_pause) { - LEAVE(); - return sta_ptr; - } - sta_ptr = sta_ptr->pnext; - } - LEAVE(); - return MNULL; -} - /** * @brief Get extended version information * @@ -1495,6 +1460,44 @@ wlan_process_802dot11_mgmt_pkt(IN mlan_private * priv, return MLAN_STATUS_SUCCESS; } +/** + * @brief Get OTP user data + * + * @param pmadapter A pointer to mlan_adapter structure + * @param pioctl_req A pointer to ioctl request buffer + * + * @return MLAN_STATUS_PENDING --success, otherwise fail + */ +mlan_status +wlan_misc_otp_user_data(IN pmlan_adapter pmadapter, + IN pmlan_ioctl_req pioctl_req) +{ + pmlan_private pmpriv = pmadapter->priv[pioctl_req->bss_index]; + mlan_ds_misc_cfg *misc = (mlan_ds_misc_cfg *) pioctl_req->pbuf; + mlan_status ret = MLAN_STATUS_FAILURE; + + ENTER(); + + if (misc->param.otp_user_data.user_data_length > MAX_OTP_USER_DATA_LEN) { + PRINTM(MERROR, "Invalid OTP user data length\n"); + pioctl_req->status_code = MLAN_ERROR_INVALID_PARAMETER; + LEAVE(); + return ret; + } + + ret = wlan_prepare_cmd(pmpriv, + HostCmd_CMD_OTP_READ_USER_DATA, + HostCmd_ACT_GEN_GET, + 0, + (t_void *) pioctl_req, &misc->param.otp_user_data); + + if (ret == MLAN_STATUS_SUCCESS) + ret = MLAN_STATUS_PENDING; + + LEAVE(); + return ret; +} + /** * @brief This function will search for the specific ie * @@ -1718,26 +1721,26 @@ wlan_rate_ioctl_get_rate_value(IN pmlan_adapter pmadapter, /* If not connected, set rate to the lowest in each band */ if (pmpriv->media_connected != MTRUE) { - if (pmadapter->config_bands & (BAND_B | BAND_G)) { + if (pmpriv->config_bands & (BAND_B | BAND_G)) { /* Return the lowest supported rate for BG band */ rate->param.rate_cfg.rate = SupportedRates_BG[0] & 0x7f; - } else if (pmadapter->config_bands & (BAND_A | BAND_B)) { + } else if (pmpriv->config_bands & (BAND_A | BAND_B)) { /* Return the lowest supported rate for A band */ rate->param.rate_cfg.rate = SupportedRates_BG[0] & 0x7f; - } else if (pmadapter->config_bands & BAND_A) { + } else if (pmpriv->config_bands & BAND_A) { /* Return the lowest supported rate for A band */ rate->param.rate_cfg.rate = SupportedRates_A[0] & 0x7f; - } else if (pmadapter->config_bands & BAND_G) { + } else if (pmpriv->config_bands & BAND_G) { /* Return the lowest supported rate for G band */ rate->param.rate_cfg.rate = SupportedRates_G[0] & 0x7f; - } else if (pmadapter->config_bands & BAND_B) { + } else if (pmpriv->config_bands & BAND_B) { /* Return the lowest supported rate for B band */ rate->param.rate_cfg.rate = SupportedRates_B[0] & 0x7f; - } else if (pmadapter->config_bands & BAND_GN) { + } else if (pmpriv->config_bands & BAND_GN) { /* Return the lowest supported rate for N band */ rate->param.rate_cfg.rate = SupportedRates_N[0] & 0x7f; } else { - PRINTM(MMSG, "Invalid Band 0x%x\n", pmadapter->config_bands); + PRINTM(MMSG, "Invalid Band 0x%x\n", pmpriv->config_bands); } } else { @@ -1793,7 +1796,7 @@ wlan_rate_ioctl_set_rate_value(IN pmlan_adapter pmadapter, memset(pmadapter, rates, 0, sizeof(rates)); wlan_get_active_data_rates(pmpriv, pmpriv->bss_mode, (pmpriv->bss_mode == MLAN_BSS_MODE_INFRA) ? - pmadapter->config_bands : pmadapter-> + pmpriv->config_bands : pmadapter-> adhoc_start_band, rates); rate = rates; for (i = 0; (rate[i] && i < WLAN_SUPPORTED_RATES); i++) { diff --git a/drivers/net/wireless/sd8797/mlan/mlan_scan.c b/drivers/net/wireless/sd8797/mlan/mlan_scan.c index 2c4eadf04a2e..895fb38a5786 100644 --- a/drivers/net/wireless/sd8797/mlan/mlan_scan.c +++ b/drivers/net/wireless/sd8797/mlan/mlan_scan.c @@ -5,7 +5,7 @@ * IOCTL handlers as well as command preparation and response routines * for sending scan commands to the firmware. * - * Copyright (C) 2008-2011, Marvell International Ltd. + * Copyright (C) 2008-2012, Marvell International Ltd. * * This software file (the "File") is distributed by Marvell International * Ltd. under the terms of the GNU General Public License Version 2, June 1991 @@ -378,6 +378,9 @@ wlan_scan_create_channel_list(IN mlan_private * pmpriv, break; case BAND_B: case BAND_G: + if (wlan_bg_scan_type_is_passive(pmpriv, (t_u8) cfp->channel)) { + scan_type = MLAN_SCAN_TYPE_PASSIVE; + } default: pscan_chan_list[chan_idx].radio_type = HostCmd_SCAN_RADIO_TYPE_BG; @@ -825,7 +828,7 @@ wlan_scan_setup_scan_config(IN mlan_private * pmpriv, rates_size = wlan_get_supported_rates(pmpriv, pmpriv->bss_mode, (pmpriv->bss_mode == - MLAN_BSS_MODE_INFRA) ? pmadapter-> + MLAN_BSS_MODE_INFRA) ? pmpriv-> config_bands : pmadapter-> adhoc_start_band, rates); @@ -838,13 +841,12 @@ wlan_scan_setup_scan_config(IN mlan_private * pmpriv, PRINTM(MINFO, "SCAN_CMD: Rates size = %d\n", rates_size); if (ISSUPP_11NENABLED(pmpriv->adapter->fw_cap_info) - && (pmpriv->adapter->config_bands & BAND_GN - || pmpriv->adapter->config_bands & BAND_AN)) { + && (pmpriv->config_bands & BAND_GN || pmpriv->config_bands & BAND_AN)) { pht_cap = (MrvlIETypes_HTCap_t *) ptlv_pos; memset(pmadapter, pht_cap, 0, sizeof(MrvlIETypes_HTCap_t)); pht_cap->header.type = wlan_cpu_to_le16(HT_CAPABILITY); pht_cap->header.len = sizeof(HTCap_t); - wlan_fill_ht_cap_tlv(pmpriv, pht_cap, pmpriv->adapter->config_bands); + wlan_fill_ht_cap_tlv(pmpriv, pht_cap, pmpriv->config_bands); HEXDUMP("SCAN: HT_CAPABILITIES IE", (t_u8 *) pht_cap, sizeof(MrvlIETypes_HTCap_t)); ptlv_pos += sizeof(MrvlIETypes_HTCap_t); @@ -898,6 +900,11 @@ wlan_scan_setup_scan_config(IN mlan_private * pmpriv, scan_type = MLAN_SCAN_TYPE_PASSIVE; } } + if (radio_type == HostCmd_SCAN_RADIO_TYPE_BG) { + if (wlan_bg_scan_type_is_passive(pmpriv, channel)) { + scan_type = MLAN_SCAN_TYPE_PASSIVE; + } + } if (scan_type == MLAN_SCAN_TYPE_PASSIVE) { (pscan_chan_list + chan_idx)->chan_scan_mode.passive_scan = MTRUE; @@ -2938,7 +2945,8 @@ wlan_ret_802_11_scan(IN mlan_private * pmpriv, pmadapter->callbacks.moal_get_system_time(pmadapter->pmoal_handle, &pmadapter->age_in_secs, &age_ts_usec); - + if (is_bgscan_resp) + goto done; if (!util_peek_list (pmadapter->pmoal_handle, &pmadapter->scan_pending_q, pcb->moal_spin_lock, pcb->moal_spin_unlock)) { @@ -2961,6 +2969,7 @@ wlan_ret_802_11_scan(IN mlan_private * pmpriv, (pmlan_ioctl_req) pioctl_buf, MLAN_STATUS_SUCCESS); } + pmadapter->bgscan_reported = MFALSE; wlan_recv_event(pmpriv, MLAN_EVENT_ID_DRV_SCAN_REPORT, MNULL); } else { /* If firmware not ready, do not issue any more scan commands */ @@ -3360,6 +3369,7 @@ wlan_handle_event_ext_scan_report(IN mlan_private * pmpriv, (pmlan_ioctl_req) pioctl_req, MLAN_STATUS_SUCCESS); } + pmadapter->bgscan_reported = MFALSE; wlan_recv_event(pmpriv, MLAN_EVENT_ID_DRV_SCAN_REPORT, MNULL); } else { /* If firmware not ready, do not issue any more scan commands */ @@ -3508,6 +3518,8 @@ wlan_bgscan_create_channel_list(IN mlan_private * pmpriv, break; case BAND_B: case BAND_G: + if (wlan_bg_scan_type_is_passive(pmpriv, (t_u8) cfp->channel)) + scan_type = MLAN_SCAN_TYPE_PASSIVE; default: tlv_chan_list->chan_scan_param[chan_idx].radio_type = HostCmd_SCAN_RADIO_TYPE_BG; @@ -3575,6 +3587,8 @@ wlan_cmd_bgscan_config(IN mlan_private * pmpriv, MrvlIEtypes_BeaconLowSnrThreshold_t *snr_tlv = MNULL; MrvlIEtypes_WildCardSsIdParamSet_t *pwildcard_ssid_tlv = MNULL; MrvlIEtypes_ChanListParamSet_t *tlv_chan_list = MNULL; + MrvlIEtypes_StartLater_t *tlv_start_later = MNULL; + MrvlIEtypes_RepeatCount_t *tlv_repeat = MNULL; t_u8 *tlv = MNULL; t_u16 num_probes = 0; t_u32 ssid_idx; @@ -3640,6 +3654,16 @@ wlan_cmd_bgscan_config(IN mlan_private * pmpriv, tlv += sizeof(MrvlIEtypes_BeaconLowRssiThreshold_t); cmd_size += sizeof(MrvlIEtypes_BeaconLowRssiThreshold_t); } + if (bg_scan_in->repeat_count) { + tlv_repeat = (MrvlIEtypes_RepeatCount_t *) tlv; + tlv_repeat->header.type = wlan_cpu_to_le16(TLV_TYPE_REPEAT_COUNT); + tlv_repeat->header.len = + wlan_cpu_to_le16(sizeof(MrvlIEtypes_RepeatCount_t) - + sizeof(MrvlIEtypesHeader_t)); + tlv_repeat->repeat_count = wlan_cpu_to_le16(bg_scan_in->repeat_count); + tlv += sizeof(MrvlIEtypes_RepeatCount_t); + cmd_size += sizeof(MrvlIEtypes_RepeatCount_t); + } for (ssid_idx = 0; ((ssid_idx < NELEMENTS(bg_scan_in->ssid_list)) && (*bg_scan_in->ssid_list[ssid_idx].ssid || bg_scan_in->ssid_list[ssid_idx].max_len)); @@ -3683,6 +3707,12 @@ wlan_cmd_bgscan_config(IN mlan_private * pmpriv, scan_type = MLAN_SCAN_TYPE_PASSIVE; } } + if (radio_type == HostCmd_SCAN_RADIO_TYPE_BG) { + if (wlan_bg_scan_type_is_passive + (pmpriv, bg_scan_in->chan_list[chan_idx].chan_number)) { + scan_type = MLAN_SCAN_TYPE_PASSIVE; + } + } tlv_chan_list->chan_scan_param[chan_num].chan_number = bg_scan_in->chan_list[chan_idx].chan_number; tlv_chan_list->chan_scan_param[chan_num].radio_type = @@ -3729,6 +3759,14 @@ wlan_cmd_bgscan_config(IN mlan_private * pmpriv, cmd_size += sizeof(MrvlIEtypesHeader_t) + sizeof(ChanScanParamSet_t) * chan_num; } + tlv_start_later = (MrvlIEtypes_StartLater_t *) tlv; + tlv_start_later->header.type = wlan_cpu_to_le16(TLV_TYPE_STARTBGSCANLATER); + tlv_start_later->header.len = + wlan_cpu_to_le16(sizeof(MrvlIEtypes_StartLater_t) - + sizeof(MrvlIEtypesHeader_t)); + tlv_start_later->value = 0; + tlv += sizeof(MrvlIEtypes_StartLater_t); + cmd_size += sizeof(MrvlIEtypes_StartLater_t); done: pcmd->size = wlan_cpu_to_le16(cmd_size); LEAVE(); @@ -3775,6 +3813,36 @@ wlan_ret_bgscan_config(IN mlan_private * pmpriv, return MLAN_STATUS_SUCCESS; } +/** + * @brief This function handles the command response of bgscan_query + * @param pmpriv A pointer to mlan_private structure + * @param resp A pointer to HostCmd_DS_COMMAND + * @param pioctl_buf A pointer to mlan_ioctl_req structure + * + * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE + */ +mlan_status +wlan_ret_802_11_bgscan_query(IN mlan_private * pmpriv, + IN HostCmd_DS_COMMAND * resp, + IN mlan_ioctl_req * pioctl_buf) +{ + mlan_ds_scan *pscan = MNULL; + mlan_adapter *pmadapter = pmpriv->adapter; + ENTER(); + wlan_ret_802_11_scan(pmpriv, resp, MNULL); + if (pioctl_buf) { + pscan = (mlan_ds_scan *) pioctl_buf->pbuf; + pscan->param.scan_resp.pscan_table = (t_u8 *) pmadapter->pscan_table; + pscan->param.scan_resp.num_in_scan_table = pmadapter->num_in_scan_table; + pscan->param.scan_resp.age_in_secs = pmadapter->age_in_secs; + pioctl_buf->data_read_written = sizeof(mlan_scan_resp) + + MLAN_SUB_COMMAND_SIZE; + + } + LEAVE(); + return MLAN_STATUS_SUCCESS; +} + /** * @brief This function finds ssid in ssid list. * @@ -3812,7 +3880,7 @@ wlan_find_ssid_in_list(IN mlan_private * pmpriv, MLAN_MAC_ADDR_LENGTH))) { if (((mode == MLAN_BSS_MODE_INFRA) && - !wlan_is_band_compatible(pmadapter->config_bands, + !wlan_is_band_compatible(pmpriv->config_bands, pmadapter->pscan_table[i].bss_band)) || (wlan_find_cfp_by_band_and_channel @@ -3896,7 +3964,7 @@ wlan_find_bssid_in_list(IN mlan_private * pmpriv, (pmadapter, pmadapter->pscan_table[i].mac_address, bssid, MLAN_MAC_ADDR_LENGTH)) { if (((mode == MLAN_BSS_MODE_INFRA) && - !wlan_is_band_compatible(pmadapter->config_bands, + !wlan_is_band_compatible(pmpriv->config_bands, pmadapter->pscan_table[i].bss_band)) || (wlan_find_cfp_by_band_and_channel diff --git a/drivers/net/wireless/sd8797/mlan/mlan_sdio.c b/drivers/net/wireless/sd8797/mlan/mlan_sdio.c index 0718cec12ee2..02e73477b619 100644 --- a/drivers/net/wireless/sd8797/mlan/mlan_sdio.c +++ b/drivers/net/wireless/sd8797/mlan/mlan_sdio.c @@ -218,8 +218,9 @@ wlan_get_wr_port_data(mlan_adapter * pmadapter, t_u8 * pport) PRINTM(MIF_D, "wlan_get_wr_port_data: mp_wr_bitmap=0x%08x\n", wr_bitmap); if (!(wr_bitmap & pmadapter->mp_data_port_mask)) { + pmadapter->data_sent = MTRUE; LEAVE(); - return MLAN_STATUS_FAILURE; + return MLAN_STATUS_RESOURCE; } if (pmadapter->mp_wr_bitmap & (1 << pmadapter->curr_wr_port)) { @@ -1431,7 +1432,6 @@ wlan_sdio_host_to_card(mlan_adapter * pmadapter, t_u8 type, mlan_buffer * pmbuf, ret = wlan_get_wr_port_data(pmadapter, &port); if (ret != MLAN_STATUS_SUCCESS) { PRINTM(MERROR, "no wr_port available: %d\n", ret); - pmbuf->status_code = MLAN_ERROR_PKT_INVALID; goto exit; } /* Transfer data to card */ diff --git a/drivers/net/wireless/sd8797/mlan/mlan_shim.c b/drivers/net/wireless/sd8797/mlan/mlan_shim.c index 1e06a52b87cb..07f7db5c7227 100644 --- a/drivers/net/wireless/sd8797/mlan/mlan_shim.c +++ b/drivers/net/wireless/sd8797/mlan/mlan_shim.c @@ -108,6 +108,12 @@ t_void(*assert_callback) (IN t_void * pmoal_handle, IN t_u32 cond) = MNULL; /** Global moal_print callback */ t_void(*print_callback) (IN t_void * pmoal_handle, IN t_u32 level, IN t_s8 * pformat, IN ...) = MNULL; + +/** Global moal_get_system_time callback */ +mlan_status(*get_sys_time_callback) (IN t_void * pmoal_handle, + OUT t_u32 * psec, + OUT t_u32 * pusec) = MNULL; + /** Global driver debug mit masks */ t_u32 drvdbg = DEFAULT_DEBUG_MASK; #endif @@ -161,6 +167,7 @@ mlan_register(IN pmlan_device pmdevice, OUT t_void ** ppmlan_adapter) MASSERT(pmdevice->callbacks.moal_print); #ifdef DEBUG_LEVEL1 print_callback = pmdevice->callbacks.moal_print; + get_sys_time_callback = pmdevice->callbacks.moal_get_system_time; #endif assert_callback = pmdevice->callbacks.moal_assert; diff --git a/drivers/net/wireless/sd8797/mlan/mlan_sta_cmd.c b/drivers/net/wireless/sd8797/mlan/mlan_sta_cmd.c index c91fcc9f6e12..7c426595117e 100644 --- a/drivers/net/wireless/sd8797/mlan/mlan_sta_cmd.c +++ b/drivers/net/wireless/sd8797/mlan/mlan_sta_cmd.c @@ -151,6 +151,16 @@ wlan_cmd_802_11_snmp_mib(IN pmlan_private pmpriv, } switch (cmd_oid) { + case DtimPeriod_i: + psnmp_mib->oid = wlan_cpu_to_le16((t_u16) DtimPeriod_i); + if (cmd_action == HostCmd_ACT_GEN_SET) { + psnmp_mib->query_type = wlan_cpu_to_le16(HostCmd_ACT_GEN_SET); + psnmp_mib->buf_size = wlan_cpu_to_le16(sizeof(t_u8)); + ul_temp = *((t_u32 *) pdata_buf); + psnmp_mib->value[0] = (t_u8) ul_temp; + cmd->size += sizeof(t_u8); + } + break; case FragThresh_i: psnmp_mib->oid = wlan_cpu_to_le16((t_u16) FragThresh_i); if (cmd_action == HostCmd_ACT_GEN_SET) { @@ -712,7 +722,22 @@ wlan_cmd_802_11_key_material(IN pmlan_private pmpriv, pkey_material->action = wlan_cpu_to_le16(cmd_action); if (cmd_action == HostCmd_ACT_GEN_GET) { - cmd->size = wlan_cpu_to_le16(sizeof(pkey_material->action) + S_DS_GEN); + cmd->size = + wlan_cpu_to_le16(sizeof(pkey_material->action) + S_DS_GEN + + KEYPARAMSET_FIXED_LEN + + sizeof(MrvlIEtypesHeader_t)); + memset(pmpriv->adapter, &pkey_material->key_param_set, 0, + sizeof(MrvlIEtype_KeyParamSet_t)); + pkey_material->key_param_set.type = + wlan_cpu_to_le16(TLV_TYPE_KEY_MATERIAL); + pkey_material->key_param_set.length = + wlan_cpu_to_le16(KEYPARAMSET_FIXED_LEN); + if (pkey->key_flags & KEY_FLAG_GROUP_KEY) + pkey_material->key_param_set.key_info |= KEY_INFO_MCAST_KEY; + else + pkey_material->key_param_set.key_info |= KEY_INFO_UCAST_KEY; + pkey_material->key_param_set.key_info = + wlan_cpu_to_le16(pkey_material->key_param_set.key_info); goto done; } @@ -963,10 +988,14 @@ wlan_cmd_802_11_supplicant_pmk(IN pmlan_private pmpriv, static mlan_status wlan_cmd_802_11_supplicant_profile(IN pmlan_private pmpriv, IN HostCmd_DS_COMMAND * cmd, - IN t_u16 cmd_action) + IN t_u16 cmd_action, IN t_void * pdata_buf) { HostCmd_DS_802_11_SUPPLICANT_PROFILE *sup_profile = &cmd->params.esupplicant_profile; + MrvlIEtypes_EncrProto_t *encr_proto_tlv = MNULL; + MrvlIEtypes_Cipher_t *pcipher_tlv = MNULL; + t_u8 *ptlv_buffer = (t_u8 *) sup_profile->tlv_buf; + mlan_ds_esupp_mode *esupp = MNULL; ENTER(); @@ -975,6 +1004,44 @@ wlan_cmd_802_11_supplicant_profile(IN pmlan_private pmpriv, S_DS_GEN - 1); cmd->command = wlan_cpu_to_le16(HostCmd_CMD_SUPPLICANT_PROFILE); sup_profile->action = wlan_cpu_to_le16(cmd_action); + if ((cmd_action == HostCmd_ACT_GEN_SET) && pdata_buf) { + esupp = (mlan_ds_esupp_mode *) pdata_buf; + if (esupp->rsn_mode) { + encr_proto_tlv = (MrvlIEtypes_EncrProto_t *) ptlv_buffer; + encr_proto_tlv->header.type = + wlan_cpu_to_le16(TLV_TYPE_ENCRYPTION_PROTO); + encr_proto_tlv->header.len = + (t_u16) sizeof(encr_proto_tlv->rsn_mode); + encr_proto_tlv->rsn_mode = wlan_cpu_to_le16(esupp->rsn_mode); + ptlv_buffer += + (encr_proto_tlv->header.len + sizeof(MrvlIEtypesHeader_t)); + cmd->size += + (encr_proto_tlv->header.len + sizeof(MrvlIEtypesHeader_t)); + encr_proto_tlv->header.len = + wlan_cpu_to_le16(encr_proto_tlv->header.len); + } + if (esupp->act_paircipher || esupp->act_groupcipher) { + pcipher_tlv = (MrvlIEtypes_Cipher_t *) ptlv_buffer; + pcipher_tlv->header.type = wlan_cpu_to_le16(TLV_TYPE_CIPHER); + pcipher_tlv->header.len = + (t_u16) (sizeof(pcipher_tlv->pair_cipher) + + sizeof(pcipher_tlv->group_cipher)); + if (esupp->act_paircipher) { + pcipher_tlv->pair_cipher = + wlan_cpu_to_le16(esupp->act_paircipher); + } + if (esupp->act_groupcipher) { + pcipher_tlv->group_cipher = + wlan_cpu_to_le16(esupp->act_groupcipher); + } + ptlv_buffer += + (pcipher_tlv->header.len + sizeof(MrvlIEtypesHeader_t)); + cmd->size += + (pcipher_tlv->header.len + sizeof(MrvlIEtypesHeader_t)); + pcipher_tlv->header.len = wlan_cpu_to_le16(pcipher_tlv->header.len); + } + } + cmd->size = wlan_cpu_to_le16(cmd->size); LEAVE(); return MLAN_STATUS_SUCCESS; } @@ -1113,7 +1180,8 @@ wlan_cmd_mgmt_ie_list(IN pmlan_private pmpriv, } cmd->size -= - (MAX_MGMT_IE_INDEX * sizeof(custom_ie)) + sizeof(tlvbuf_max_mgmt_ie); + (MAX_MGMT_IE_INDEX_TO_FW * sizeof(custom_ie)) + + sizeof(tlvbuf_max_mgmt_ie); cmd->size += cust_ie->len; cmd->size = wlan_cpu_to_le16(cmd->size); @@ -1459,6 +1527,42 @@ wlan_cmd_subscribe_event(IN pmlan_private pmpriv, return MLAN_STATUS_SUCCESS; } +/** + * @brief This function prepares command of OTP user data. + * + * @param pmpriv A pointer to mlan_private structure + * @param cmd A pointer to HostCmd_DS_COMMAND structure + * @param cmd_action the action: GET or SET + * @param pdata_buf A pointer to data buffer + * @return MLAN_STATUS_SUCCESS + */ +static mlan_status +wlan_cmd_otp_user_data(IN pmlan_private pmpriv, + IN HostCmd_DS_COMMAND * cmd, + IN t_u16 cmd_action, IN t_void * pdata_buf) +{ + mlan_ds_misc_otp_user_data *user_data = + (mlan_ds_misc_otp_user_data *) pdata_buf; + HostCmd_DS_OTP_USER_DATA *cmd_user_data = + (HostCmd_DS_OTP_USER_DATA *) & cmd->params.otp_user_data; + t_u16 cmd_size = 0; + + ENTER(); + + cmd->command = wlan_cpu_to_le16(HostCmd_CMD_OTP_READ_USER_DATA); + cmd_size = sizeof(HostCmd_DS_OTP_USER_DATA) + S_DS_GEN - 1; + + cmd_user_data->action = wlan_cpu_to_le16(cmd_action); + cmd_user_data->reserved = 0; + cmd_user_data->user_data_length = + wlan_cpu_to_le16(user_data->user_data_length); + cmd_size += user_data->user_data_length; + cmd->size = wlan_cpu_to_le16(cmd_size); + + LEAVE(); + return MLAN_STATUS_SUCCESS; +} + /** * @brief This function prepares inactivity timeout command * @@ -1679,7 +1783,8 @@ wlan_ops_sta_prepare_cmd(IN t_void * priv, pdata_buf); break; case HostCmd_CMD_SUPPLICANT_PROFILE: - ret = wlan_cmd_802_11_supplicant_profile(pmpriv, cmd_ptr, cmd_action); + ret = wlan_cmd_802_11_supplicant_profile(pmpriv, cmd_ptr, cmd_action, + pdata_buf); break; case HostCmd_CMD_802_11D_DOMAIN_INFO: @@ -1786,6 +1891,9 @@ wlan_ops_sta_prepare_cmd(IN t_void * priv, case HostCmd_CMD_802_11_SUBSCRIBE_EVENT: ret = wlan_cmd_subscribe_event(pmpriv, cmd_ptr, cmd_action, pdata_buf); break; + case HostCmd_CMD_OTP_READ_USER_DATA: + ret = wlan_cmd_otp_user_data(pmpriv, cmd_ptr, cmd_action, pdata_buf); + break; default: PRINTM(MERROR, "PREP_CMD: unknown command- %#x\n", cmd_no); ret = MLAN_STATUS_FAILURE; diff --git a/drivers/net/wireless/sd8797/mlan/mlan_sta_cmdresp.c b/drivers/net/wireless/sd8797/mlan/mlan_sta_cmdresp.c index be56a16615b9..086d16ae5a62 100644 --- a/drivers/net/wireless/sd8797/mlan/mlan_sta_cmdresp.c +++ b/drivers/net/wireless/sd8797/mlan/mlan_sta_cmdresp.c @@ -3,7 +3,7 @@ * @brief This file contains the handling of command * responses generated by firmware. * - * Copyright (C) 2008-2011, Marvell International Ltd. + * Copyright (C) 2008-2012, Marvell International Ltd. * * This software file (the "File") is distributed by Marvell International * Ltd. under the terms of the GNU General Public License Version 2, June 1991 @@ -231,6 +231,12 @@ wlan_ret_802_11_snmp_mib(IN pmlan_private pmpriv, wlan_le16_to_cpu(psmib->buf_size)); if (query_type == HostCmd_ACT_GEN_GET) { switch (oid) { + case DtimPeriod_i: + ul_temp = psmib->value[0]; + PRINTM(MINFO, "SNMP_RESP: DTIM Period =%u\n", ul_temp); + if (mib) + mib->param.dtim_period = ul_temp; + break; case FragThresh_i: ul_temp = wlan_le16_to_cpu(*((t_u16 *) (psmib->value))); PRINTM(MINFO, "SNMP_RESP: FragThsd =%u\n", ul_temp); @@ -765,6 +771,7 @@ wlan_ret_802_11_key_material(IN pmlan_private pmpriv, IN mlan_ioctl_req * pioctl_buf) { HostCmd_DS_802_11_KEY_MATERIAL *pkey = &resp->params.key_material; + mlan_ds_sec_cfg *sec = MNULL; ENTER(); @@ -780,8 +787,50 @@ wlan_ret_802_11_key_material(IN pmlan_private pmpriv, } pmpriv->scan_block = MFALSE; } + } else { + if (pioctl_buf && + (wlan_le16_to_cpu(pkey->key_param_set.type) == + TLV_TYPE_KEY_MATERIAL)) { + PRINTM(MIOCTL, "key_type_id=%d, key_len=%d, key_info=0x%x\n", + wlan_le16_to_cpu(pkey->key_param_set.key_type_id), + wlan_le16_to_cpu(pkey->key_param_set.key_len), + wlan_le16_to_cpu(pkey->key_param_set.key_info)); + sec = (mlan_ds_sec_cfg *) pioctl_buf->pbuf; +#define WAPI_KEY_SIZE 32 + switch (wlan_le16_to_cpu(pkey->key_param_set.key_type_id)) { + case KEY_TYPE_ID_WEP: + sec->param.encrypt_key.key_index = pkey->key_param_set.key[0]; + sec->param.encrypt_key.key_len = + wlan_le16_to_cpu(pkey->key_param_set.key_len); + memcpy(pmpriv->adapter, sec->param.encrypt_key.key_material, + &pkey->key_param_set.key[2], + sec->param.encrypt_key.key_len); + break; + case KEY_TYPE_ID_TKIP: + sec->param.encrypt_key.key_len = + wlan_le16_to_cpu(pkey->key_param_set.key_len); + memcpy(pmpriv->adapter, sec->param.encrypt_key.key_material, + pkey->key_param_set.key, sec->param.encrypt_key.key_len); + break; + case KEY_TYPE_ID_AES: + sec->param.encrypt_key.key_len = + wlan_le16_to_cpu(pkey->key_param_set.key_len); + memcpy(pmpriv->adapter, sec->param.encrypt_key.key_material, + pkey->key_param_set.key, sec->param.encrypt_key.key_len); + break; + case KEY_TYPE_ID_WAPI: + sec->param.encrypt_key.is_wapi_key = MTRUE; + sec->param.encrypt_key.key_index = pkey->key_param_set.key[0]; + sec->param.encrypt_key.key_len = WAPI_KEY_SIZE; + memcpy(pmpriv->adapter, sec->param.encrypt_key.key_material, + &pkey->key_param_set.key[2], + sec->param.encrypt_key.key_len); + memcpy(pmpriv->adapter, sec->param.encrypt_key.pn, + &pkey->key_param_set.key[2 + WAPI_KEY_SIZE], PN_SIZE); + break; + } + } } - LEAVE(); return MLAN_STATUS_SUCCESS; } @@ -1374,6 +1423,41 @@ wlan_ret_subscribe_event(IN pmlan_private pmpriv, return MLAN_STATUS_SUCCESS; } +/** + * @brief This function handles the command response of + * OTP user data + * + * @param pmpriv A pointer to mlan_private structure + * @param resp A pointer to HostCmd_DS_COMMAND + * @param pioctl_buf A pointer to command buffer + * + * @return MLAN_STATUS_SUCCESS + */ +static mlan_status +wlan_ret_otp_user_data(IN pmlan_private pmpriv, + IN HostCmd_DS_COMMAND * resp, + IN mlan_ioctl_req * pioctl_buf) +{ + + HostCmd_DS_OTP_USER_DATA *cmd_user_data = + (HostCmd_DS_OTP_USER_DATA *) & resp->params.otp_user_data; + mlan_ds_misc_otp_user_data *user_data = MNULL; + + ENTER(); + if (pioctl_buf && (pioctl_buf->action == MLAN_ACT_GET)) { + user_data = (mlan_ds_misc_otp_user_data *) pioctl_buf->pbuf; + user_data->user_data_length = MIN(MAX_OTP_USER_DATA_LEN, + wlan_le16_to_cpu(cmd_user_data-> + user_data_length)); + memcpy(pmpriv->adapter, user_data->user_data, cmd_user_data->user_data, + user_data->user_data_length); + pioctl_buf->data_read_written = + sizeof(mlan_ds_misc_otp_user_data) + user_data->user_data_length; + } + LEAVE(); + return MLAN_STATUS_SUCCESS; +} + /******************************************************** Global Functions ********************************************************/ @@ -1442,8 +1526,7 @@ wlan_ops_sta_process_cmdresp(IN t_void * priv, ret = wlan_ret_bgscan_config(pmpriv, resp, pioctl_buf); break; case HostCmd_CMD_802_11_BG_SCAN_QUERY: - ret = wlan_ret_802_11_scan(pmpriv, resp, pioctl_buf); - wlan_recv_event(pmpriv, MLAN_EVENT_ID_FW_BG_SCAN, MNULL); + ret = wlan_ret_802_11_bgscan_query(pmpriv, resp, pioctl_buf); PRINTM(MINFO, "CMD_RESP: BG_SCAN result is ready!\n"); break; case HostCmd_CMD_TXPWR_CFG: @@ -1629,6 +1712,9 @@ wlan_ops_sta_process_cmdresp(IN t_void * priv, case HostCmd_CMD_802_11_SUBSCRIBE_EVENT: ret = wlan_ret_subscribe_event(pmpriv, resp, pioctl_buf); break; + case HostCmd_CMD_OTP_READ_USER_DATA: + ret = wlan_ret_otp_user_data(pmpriv, resp, pioctl_buf); + break; default: PRINTM(MERROR, "CMD_RESP: Unknown command response %#x\n", resp->command); diff --git a/drivers/net/wireless/sd8797/mlan/mlan_sta_event.c b/drivers/net/wireless/sd8797/mlan/mlan_sta_event.c index f638241f9632..1ad77818995f 100644 --- a/drivers/net/wireless/sd8797/mlan/mlan_sta_event.c +++ b/drivers/net/wireless/sd8797/mlan/mlan_sta_event.c @@ -341,14 +341,8 @@ wlan_ops_sta_process_event(IN t_void * priv) case EVENT_BG_SCAN_REPORT: PRINTM(MEVENT, "EVENT: BGS_REPORT\n"); - /* Clear the previous scan result */ - memset(pmadapter, pmadapter->pscan_table, 0x00, - sizeof(BSSDescriptor_t) * MRVDRV_MAX_BSSID_LIST); - pmadapter->num_in_scan_table = 0; - pmadapter->pbcn_buf_end = pmadapter->bcn_buf; - ret = wlan_prepare_cmd(pmpriv, - HostCmd_CMD_802_11_BG_SCAN_QUERY, - HostCmd_ACT_GEN_GET, 0, MNULL, MNULL); + pmadapter->bgscan_reported = MTRUE; + wlan_recv_event(pmpriv, MLAN_EVENT_ID_FW_BG_SCAN, MNULL); break; case EVENT_PORT_RELEASE: diff --git a/drivers/net/wireless/sd8797/mlan/mlan_sta_ioctl.c b/drivers/net/wireless/sd8797/mlan/mlan_sta_ioctl.c index 72dd525ca4af..eb715cb804c8 100644 --- a/drivers/net/wireless/sd8797/mlan/mlan_sta_ioctl.c +++ b/drivers/net/wireless/sd8797/mlan/mlan_sta_ioctl.c @@ -222,6 +222,9 @@ wlan_get_info_bss_info(IN pmlan_adapter pmadapter, /* Channel */ info->param.bss_info.bss_chan = pbss_desc->channel; + /* Beacon interval */ + info->param.bss_info.beacon_interval = pbss_desc->beacon_period; + /* Band */ info->param.bss_info.bss_band = (t_u8) pbss_desc->bss_band; @@ -396,6 +399,10 @@ wlan_snmp_mib_ioctl(IN pmlan_adapter pmadapter, IN pmlan_ioctl_req pioctl_req) value = mib->param.retry_count; cmd_oid = ShortRetryLim_i; break; + case MLAN_OID_SNMP_MIB_DTIM_PERIOD: + value = mib->param.dtim_period; + cmd_oid = DtimPeriod_i; + break; } /* Send request to firmware */ @@ -509,6 +516,7 @@ wlan_radio_ioctl_band_cfg(IN pmlan_adapter pmadapter, } pmpriv->adhoc_channel = (t_u8) adhoc_channel; } + if ((adhoc_band & BAND_GN) || (adhoc_band & BAND_AN) ) { @@ -993,6 +1001,7 @@ wlan_bss_ioctl_start(IN pmlan_adapter pmadapter, IN pmlan_ioctl_req pioctl_req) CLOSED state */ if (pmpriv->port_ctrl_mode == MTRUE) { PRINTM(MINFO, "bss_ioctl_start(): port_state=CLOSED\n"); + pmpriv->prior_port_status = pmpriv->port_open; pmpriv->port_open = MFALSE; } pmpriv->scan_block = MFALSE; @@ -1437,7 +1446,7 @@ wlan_rate_ioctl_get_supported_rate(IN pmlan_adapter pmadapter, else wlan_get_active_data_rates(pmpriv, pmpriv->bss_mode, (pmpriv->bss_mode == MLAN_BSS_MODE_INFRA) ? - pmadapter->config_bands : pmadapter-> + pmpriv->config_bands : pmadapter-> adhoc_start_band, rate->param.rates); pioctl_req->data_read_written = MLAN_SUPPORTED_RATES + MLAN_SUB_COMMAND_SIZE; @@ -3306,20 +3315,61 @@ wlan_sec_ioctl_esupp_mode(IN pmlan_adapter pmadapter, { mlan_status ret = MLAN_STATUS_SUCCESS; mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index]; + t_u16 cmd_action = 0; + mlan_ds_sec_cfg *sec = MNULL; ENTER(); - if (pmpriv->media_connected != MTRUE) { - pioctl_req->status_code = MLAN_ERROR_IOCTL_INVALID; - ret = MLAN_STATUS_FAILURE; - goto exit; + sec = (mlan_ds_sec_cfg *) pioctl_req->pbuf; + if (pioctl_req->action == MLAN_ACT_SET) { + cmd_action = HostCmd_ACT_GEN_SET; + if (pmpriv->media_connected == MTRUE) { + PRINTM(MERROR, + "Cannot set esupplicant mode configuration while connected.\n"); + pioctl_req->status_code = MLAN_ERROR_IOCTL_INVALID; + ret = MLAN_STATUS_FAILURE; + goto exit; + } + if (!sec->param.esupp_mode.rsn_mode || + (sec->param.esupp_mode.rsn_mode & RSN_TYPE_VALID_BITS) + != sec->param.esupp_mode.rsn_mode) { + PRINTM(MERROR, "Invalid RSN mode\n"); + pioctl_req->status_code = MLAN_ERROR_IOCTL_INVALID; + ret = MLAN_STATUS_FAILURE; + goto exit; + } + if (!sec->param.esupp_mode.act_paircipher || + (sec->param.esupp_mode.act_paircipher & EMBED_CIPHER_VALID_BITS) + != sec->param.esupp_mode.act_paircipher) { + PRINTM(MERROR, "Invalid pairwise cipher\n"); + pioctl_req->status_code = MLAN_ERROR_IOCTL_INVALID; + ret = MLAN_STATUS_FAILURE; + goto exit; + } + if (!sec->param.esupp_mode.act_groupcipher || + (sec->param.esupp_mode.act_groupcipher & EMBED_CIPHER_VALID_BITS) + != sec->param.esupp_mode.act_groupcipher) { + PRINTM(MERROR, "Invalid group cipher\n"); + pioctl_req->status_code = MLAN_ERROR_IOCTL_INVALID; + ret = MLAN_STATUS_FAILURE; + goto exit; + } + } else { + cmd_action = HostCmd_ACT_GEN_GET_CURRENT; } /* Send request to firmware */ - ret = wlan_prepare_cmd(pmpriv, - HostCmd_CMD_SUPPLICANT_PROFILE, - HostCmd_ACT_GEN_GET_CURRENT, - 0, (t_void *) pioctl_req, MNULL); + if (sec) { + ret = wlan_prepare_cmd(pmpriv, + HostCmd_CMD_SUPPLICANT_PROFILE, + cmd_action, + 0, + (t_void *) pioctl_req, &sec->param.esupp_mode); + } else { + ret = wlan_prepare_cmd(pmpriv, + HostCmd_CMD_SUPPLICANT_PROFILE, + cmd_action, 0, (t_void *) pioctl_req, MNULL); + } if (ret == MLAN_STATUS_SUCCESS) ret = MLAN_STATUS_PENDING; @@ -4137,6 +4187,8 @@ wlan_misc_ioctl_region(IN pmlan_adapter pmadapter, LEAVE(); return MLAN_STATUS_FAILURE; } + pmadapter->cfp_code_bg = misc->param.region_code; + pmadapter->cfp_code_a = misc->param.region_code; if (wlan_set_regiontable(pmpriv, (t_u8) pmadapter->region_code, pmadapter->config_bands | pmadapter-> adhoc_start_band)) { @@ -4826,6 +4878,158 @@ wlan_misc_ioctl_ipaddr_cfg(IN pmlan_adapter pmadapter, return ret; } +/** + * @brief CFP code configuration + * + * @param pmadapter A pointer to mlan_adapter structure + * @param pioctl_req A pointer to ioctl request buffer + * + * @return MLAN_STATUS_PENDING --success, otherwise fail + */ +mlan_status +wlan_misc_ioctl_cfp_code_cfg(IN pmlan_adapter pmadapter, + IN pmlan_ioctl_req pioctl_req) +{ + mlan_status ret = MLAN_STATUS_SUCCESS; + mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index]; + mlan_ds_misc_cfg *misc = (mlan_ds_misc_cfg *) pioctl_req->pbuf; + mlan_ds_misc_cfp_code *cfp_code = MNULL; + t_u32 region_bg = 0; + t_u32 region_a = 0; + int i; + + ENTER(); + + cfp_code = &misc->param.cfp_code; + if (pioctl_req->action == MLAN_ACT_SET) { + /* Save the values in MLAN */ + if (!cfp_code->cfp_code_bg) + cfp_code->cfp_code_bg = pmadapter->cfp_code_bg; + for (i = 0; i < MRVDRV_MAX_REGION_CODE; i++) { + /* Use the region code to search for the index */ + if (cfp_code->cfp_code_bg == region_code_index[i]) { + region_bg = cfp_code->cfp_code_bg; + break; + } + } + if (!region_bg) { + for (i = 0; i < MRVDRV_MAX_CFP_CODE_BG; i++) { + /* Use the CFP code to search for the index */ + if (cfp_code->cfp_code_bg == cfp_code_index_bg[i]) + break; + } + if (i >= MRVDRV_MAX_CFP_CODE_BG) { + PRINTM(MERROR, "CFP Code not identified for BG\n"); + pioctl_req->status_code = MLAN_ERROR_INVALID_PARAMETER; + ret = MLAN_STATUS_FAILURE; + goto done; + } + } + if (!cfp_code->cfp_code_a) + cfp_code->cfp_code_a = pmadapter->cfp_code_a; + for (i = 0; i < MRVDRV_MAX_REGION_CODE; i++) { + /* Use the region code to search for the index */ + if (cfp_code->cfp_code_a == region_code_index[i]) { + region_a = cfp_code->cfp_code_a; + break; + } + } + if (!region_a) { + for (i = 0; i < MRVDRV_MAX_CFP_CODE_A; i++) { + /* Use the CFP code to search for the index */ + if (cfp_code->cfp_code_a == cfp_code_index_a[i]) + break; + } + if (i >= MRVDRV_MAX_CFP_CODE_A) { + PRINTM(MERROR, "CFP Code not identified for A\n"); + pioctl_req->status_code = MLAN_ERROR_INVALID_PARAMETER; + ret = MLAN_STATUS_FAILURE; + goto done; + } + } + pmadapter->cfp_code_bg = (t_u8) cfp_code->cfp_code_bg; + pmadapter->cfp_code_a = (t_u8) cfp_code->cfp_code_a; + if (region_bg && region_a && (region_bg == region_a)) + pmadapter->region_code = pmadapter->cfp_code_a; + else + pmadapter->region_code = 0; + if (wlan_set_regiontable(pmpriv, (t_u8) pmadapter->region_code, + pmadapter->config_bands | pmadapter-> + adhoc_start_band)) { + pioctl_req->status_code = MLAN_ERROR_INVALID_PARAMETER; + ret = MLAN_STATUS_FAILURE; + goto done; + } + } else { + /* GET operation */ + cfp_code->cfp_code_bg = pmadapter->cfp_code_bg; + cfp_code->cfp_code_a = pmadapter->cfp_code_a; + } + + done: + LEAVE(); + return ret; +} + +/** + * @brief This function sets up country code and downloads CMD to FW + * + * @param pmadapter A pointer to mlan_adapter structure + * @param pioctl_req Pointer to the IOCTL request buffer + * + * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE + */ +mlan_status +wlan_misc_ioctl_country_code(IN pmlan_adapter pmadapter, + IN mlan_ioctl_req * pioctl_req) +{ + mlan_status ret = MLAN_STATUS_SUCCESS; + mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index]; + mlan_ds_misc_country_code *country_code = MNULL; + mlan_ds_misc_cfg *cfg_misc = MNULL; + t_u8 cfp_bg = 0, cfp_a = 0; + + ENTER(); + + cfg_misc = (mlan_ds_misc_cfg *) pioctl_req->pbuf; + country_code = &cfg_misc->param.country_code; + + if (pioctl_req->action == MLAN_ACT_SET) { + /* Update region code and table based on country code */ + if (wlan_misc_country_2_cfp_table_code(pmadapter, + country_code->country_code, + &cfp_bg, &cfp_a)) { + PRINTM(MERROR, "Country code not found!\n"); + pioctl_req->status_code = MLAN_ERROR_INVALID_PARAMETER; + ret = MLAN_STATUS_FAILURE; + goto done; + } + pmadapter->cfp_code_bg = cfp_bg; + pmadapter->cfp_code_a = cfp_a; + if (cfp_bg && cfp_a && (cfp_bg == cfp_a)) + pmadapter->region_code = cfp_a; + else + pmadapter->region_code = 0; + if (wlan_set_regiontable(pmpriv, pmadapter->region_code, + pmadapter->config_bands | pmadapter-> + adhoc_start_band)) { + pioctl_req->status_code = MLAN_ERROR_INVALID_PARAMETER; + ret = MLAN_STATUS_FAILURE; + goto done; + } + memcpy(pmadapter, pmadapter->country_code, + country_code->country_code, COUNTRY_CODE_LEN); + } else { + /* GET operation */ + memcpy(pmadapter, country_code->country_code, + pmadapter->country_code, COUNTRY_CODE_LEN); + } + + done: + LEAVE(); + return ret; +} + /** * @brief Miscellaneous configuration handler * @@ -4906,12 +5110,21 @@ wlan_misc_cfg_ioctl(IN pmlan_adapter pmadapter, IN pmlan_ioctl_req pioctl_req) case MLAN_OID_MISC_IP_ADDR: status = wlan_misc_ioctl_ipaddr_cfg(pmadapter, pioctl_req); break; + case MLAN_OID_MISC_CFP_CODE: + status = wlan_misc_ioctl_cfp_code_cfg(pmadapter, pioctl_req); + break; + case MLAN_OID_MISC_COUNTRY_CODE: + status = wlan_misc_ioctl_country_code(pmadapter, pioctl_req); + break; case MLAN_OID_MISC_THERMAL: status = wlan_misc_ioctl_thermal(pmadapter, pioctl_req); break; case MLAN_OID_MISC_SUBSCRIBE_EVENT: status = wlan_misc_ioctl_subscribe_evt(pmadapter, pioctl_req); break; + case MLAN_OID_MISC_OTP_USER_DATA: + status = wlan_misc_otp_user_data(pmadapter, pioctl_req); + break; default: if (pioctl_req) pioctl_req->status_code = MLAN_ERROR_IOCTL_INVALID; @@ -5070,13 +5283,31 @@ wlan_scan_ioctl(IN pmlan_adapter pmadapter, IN pmlan_ioctl_req pioctl_req) pioctl_req->data_read_written = sizeof(mlan_scan_resp) + MLAN_SUB_COMMAND_SIZE; } else { - pscan->param.scan_resp.pscan_table = - (t_u8 *) pmadapter->pscan_table; - pscan->param.scan_resp.num_in_scan_table = - pmadapter->num_in_scan_table; - pscan->param.scan_resp.age_in_secs = pmadapter->age_in_secs; - pioctl_req->data_read_written = sizeof(mlan_scan_resp) + - MLAN_SUB_COMMAND_SIZE; + if (pmadapter->bgscan_reported) { + pmadapter->bgscan_reported = MFALSE; + /* Clear the previous scan result */ + memset(pmadapter, pmadapter->pscan_table, 0x00, + sizeof(BSSDescriptor_t) * MRVDRV_MAX_BSSID_LIST); + pmadapter->num_in_scan_table = 0; + pmadapter->pbcn_buf_end = pmadapter->bcn_buf; + status = wlan_prepare_cmd(pmpriv, + HostCmd_CMD_802_11_BG_SCAN_QUERY, + HostCmd_ACT_GEN_GET, + 0, (t_void *) pioctl_req, MNULL); + if (status == MLAN_STATUS_SUCCESS) { + PRINTM(MINFO, + "wlan_scan_ioctl: return MLAN_STATUS_PENDING\n"); + status = MLAN_STATUS_PENDING; + } + } else { + pscan->param.scan_resp.pscan_table = + (t_u8 *) pmadapter->pscan_table; + pscan->param.scan_resp.num_in_scan_table = + pmadapter->num_in_scan_table; + pscan->param.scan_resp.age_in_secs = pmadapter->age_in_secs; + pioctl_req->data_read_written = sizeof(mlan_scan_resp) + + MLAN_SUB_COMMAND_SIZE; + } } } @@ -5198,6 +5429,7 @@ wlan_ops_sta_ioctl(t_void * adapter, pmlan_ioctl_req pioctl_req) mlan_status status = MLAN_STATUS_SUCCESS; ENTER(); + switch (pioctl_req->req_id) { case MLAN_IOCTL_SCAN: status = wlan_scan_ioctl(pmadapter, pioctl_req); diff --git a/drivers/net/wireless/sd8797/mlan/mlan_sta_rx.c b/drivers/net/wireless/sd8797/mlan/mlan_sta_rx.c index 2ad9a810afcf..5e5c68e2a108 100644 --- a/drivers/net/wireless/sd8797/mlan/mlan_sta_rx.c +++ b/drivers/net/wireless/sd8797/mlan/mlan_sta_rx.c @@ -2,7 +2,7 @@ * * @brief This file contains the handling of RX in MLAN * module. - * + * * Copyright (C) 2008-2011, Marvell International Ltd. * * This software file (the "File") is distributed by Marvell International @@ -59,6 +59,7 @@ typedef struct /******************************************************** Global functions ********************************************************/ + /** * @brief This function processes received packet and forwards it * to kernel/upper layer @@ -174,6 +175,7 @@ wlan_process_rx_packet(pmlan_adapter pmadapter, pmlan_buffer pmbuf) PRINTM(MDATA, "%lu.%06lu : Data => kernel seq_num=%d tid=%d\n", pmbuf->out_ts_sec, pmbuf->out_ts_usec, prx_pd->seq_num, prx_pd->priority); + ret = pmadapter->callbacks.moal_recv_packet(pmadapter->pmoal_handle, pmbuf); if (ret == MLAN_STATUS_FAILURE) { pmbuf->status_code = MLAN_ERROR_PKT_INVALID; diff --git a/drivers/net/wireless/sd8797/mlan/mlan_sta_tx.c b/drivers/net/wireless/sd8797/mlan/mlan_sta_tx.c index 06c1a4de064e..2258853a4089 100644 --- a/drivers/net/wireless/sd8797/mlan/mlan_sta_tx.c +++ b/drivers/net/wireless/sd8797/mlan/mlan_sta_tx.c @@ -166,7 +166,9 @@ wlan_send_null_packet(pmlan_private priv, t_u8 flags) pmlan_buffer pmbuf = MNULL; t_u8 *ptr; mlan_status ret = MLAN_STATUS_SUCCESS; +#ifdef DEBUG_LEVEL1 t_u32 sec, usec; +#endif ENTER(); @@ -228,8 +230,7 @@ wlan_send_null_packet(pmlan_private priv, t_u8 flags) break; } - pmadapter->callbacks.moal_get_system_time(pmadapter->pmoal_handle, &sec, - &usec); + PRINTM_GET_SYS_TIME(MDATA, &sec, &usec); PRINTM(MDATA, "%lu.%06lu : Null data => FW\n", sec, usec); DBG_HEXDUMP(MDAT_D, "Null data", ptr, sizeof(TxPD) + INTF_HEADER_LEN); done: diff --git a/drivers/net/wireless/sd8797/mlan/mlan_txrx.c b/drivers/net/wireless/sd8797/mlan/mlan_txrx.c index e15dd14f0443..93dea9e284f8 100644 --- a/drivers/net/wireless/sd8797/mlan/mlan_txrx.c +++ b/drivers/net/wireless/sd8797/mlan/mlan_txrx.c @@ -63,7 +63,9 @@ wlan_handle_rx_packet(pmlan_adapter pmadapter, pmlan_buffer pmbuf) mlan_status ret = MLAN_STATUS_SUCCESS; pmlan_private priv = wlan_get_priv(pmadapter, MLAN_BSS_ROLE_ANY); RxPD *prx_pd; +#ifdef DEBUG_LEVEL1 t_u32 sec, usec; +#endif ENTER(); @@ -75,8 +77,7 @@ wlan_handle_rx_packet(pmlan_adapter pmadapter, pmlan_buffer pmbuf) if (!priv) priv = wlan_get_priv(pmadapter, MLAN_BSS_ROLE_ANY); pmbuf->bss_index = priv->bss_index; - pmadapter->callbacks.moal_get_system_time(pmadapter->pmoal_handle, &sec, - &usec); + PRINTM_GET_SYS_TIME(MDATA, &sec, &usec); PRINTM_NETINTF(MDATA, priv); PRINTM(MDATA, "%lu.%06lu : Data <= FW\n", sec, usec); ret = priv->ops.process_rx_packet(pmadapter, pmbuf); @@ -101,7 +102,9 @@ wlan_process_tx(pmlan_private priv, pmlan_buffer pmbuf, mlan_status ret = MLAN_STATUS_SUCCESS; pmlan_adapter pmadapter = priv->adapter; t_u8 *head_ptr = MNULL; +#ifdef DEBUG_LEVEL1 t_u32 sec, usec; +#endif #ifdef STA_SUPPORT TxPD *plocal_tx_pd = MNULL; #endif @@ -153,8 +156,7 @@ wlan_process_tx(pmlan_private priv, pmlan_buffer pmbuf, } if ((ret == MLAN_STATUS_SUCCESS) || (ret == MLAN_STATUS_PENDING)) { - pmadapter->callbacks.moal_get_system_time(pmadapter->pmoal_handle, &sec, - &usec); + PRINTM_GET_SYS_TIME(MDATA, &sec, &usec); PRINTM_NETINTF(MDATA, priv); PRINTM(MDATA, "%lu.%06lu : Data => FW\n", sec, usec); } diff --git a/drivers/net/wireless/sd8797/mlan/mlan_uap_cmdevent.c b/drivers/net/wireless/sd8797/mlan/mlan_uap_cmdevent.c index ed79dcfaaf68..7d7d5510433c 100644 --- a/drivers/net/wireless/sd8797/mlan/mlan_uap_cmdevent.c +++ b/drivers/net/wireless/sd8797/mlan/mlan_uap_cmdevent.c @@ -3,7 +3,7 @@ * @brief This file contains the handling of AP mode command and event * * Copyright (C) 2009-2011, Marvell International Ltd. - * + * * This software file (the "File") is distributed by Marvell International * Ltd. under the terms of the GNU General Public License Version 2, June 1991 * (the "License"). You may use, redistribute and/or modify this File in diff --git a/drivers/net/wireless/sd8797/mlan/mlan_uap_ioctl.c b/drivers/net/wireless/sd8797/mlan/mlan_uap_ioctl.c index 5081d9e4aabc..f71a222f4f48 100644 --- a/drivers/net/wireless/sd8797/mlan/mlan_uap_ioctl.c +++ b/drivers/net/wireless/sd8797/mlan/mlan_uap_ioctl.c @@ -3,7 +3,7 @@ * @brief This file contains the handling of AP mode ioctls * * Copyright (C) 2009-2011, Marvell International Ltd. - * + * * This software file (the "File") is distributed by Marvell International * Ltd. under the terms of the GNU General Public License Version 2, June 1991 * (the "License"). You may use, redistribute and/or modify this File in @@ -230,8 +230,8 @@ wlan_uap_bss_ioctl_reset(IN pmlan_adapter pmadapter, memset(pmadapter, &pmpriv->mgmt_ie[i], 0, sizeof(custom_ie)); } pmpriv->add_ba_param.timeout = MLAN_DEFAULT_BLOCK_ACK_TIMEOUT; - pmpriv->add_ba_param.tx_win_size = MLAN_AMPDU_DEF_TXWINSIZE; - pmpriv->add_ba_param.rx_win_size = MLAN_AMPDU_DEF_RXWINSIZE; + pmpriv->add_ba_param.tx_win_size = MLAN_UAP_AMPDU_DEF_TXWINSIZE; + pmpriv->add_ba_param.rx_win_size = MLAN_UAP_AMPDU_DEF_RXWINSIZE; for (i = 0; i < MAX_NUM_TID; i++) { pmpriv->aggr_prio_tbl[i].ampdu_user = tos_to_tid_inv[i]; pmpriv->aggr_prio_tbl[i].amsdu = BA_STREAM_NOT_ALLOWED; diff --git a/drivers/net/wireless/sd8797/mlan/mlan_uap_txrx.c b/drivers/net/wireless/sd8797/mlan/mlan_uap_txrx.c index 0abd1ecd1c2a..590def325f27 100644 --- a/drivers/net/wireless/sd8797/mlan/mlan_uap_txrx.c +++ b/drivers/net/wireless/sd8797/mlan/mlan_uap_txrx.c @@ -3,7 +3,7 @@ * @brief This file contains AP mode transmit and receive functions * * Copyright (C) 2009-2011, Marvell International Ltd. - * + * * This software file (the "File") is distributed by Marvell International * Ltd. under the terms of the GNU General Public License Version 2, June 1991 * (the "License"). You may use, redistribute and/or modify this File in diff --git a/drivers/net/wireless/sd8797/mlan/mlan_wmm.c b/drivers/net/wireless/sd8797/mlan/mlan_wmm.c index d2c3227aca87..4b72c9193e27 100644 --- a/drivers/net/wireless/sd8797/mlan/mlan_wmm.c +++ b/drivers/net/wireless/sd8797/mlan/mlan_wmm.c @@ -946,8 +946,6 @@ wlan_dequeue_tx_packet(pmlan_adapter pmadapter) t_u8 ra[MLAN_MAC_ADDR_LENGTH]; int tid_del = 0; int tid = 0; - t_u8 avail_ports = 0; - int i; ENTER(); @@ -975,24 +973,6 @@ wlan_dequeue_tx_packet(pmlan_adapter pmadapter) if (tid >= MAX_NUM_TID) tid = wlan_wmm_downgrade_tid(priv, tid); - for (i = 1; i < pmadapter->mp_end_port; i++) { - if ((pmadapter->mp_wr_bitmap >> i) & 1) - avail_ports++; - } - - PRINTM(MINFO, - "mp_wr_bitmap=0x%08x avail_ports=%d tid=%d tx_eligibility[%d]=%d\n", - pmadapter->mp_wr_bitmap, avail_ports, - tid, tid, pmadapter->tx_eligibility[tid]); - - if (avail_ports < pmadapter->tx_eligibility[tid]) { - pmadapter->callbacks.moal_spin_unlock(pmadapter->pmoal_handle, - priv->wmm.ra_list_spinlock); - pmadapter->data_sent = MTRUE; - LEAVE(); - return MLAN_STATUS_FAILURE; - } - if (wlan_is_ptr_processed(priv, ptr)) { wlan_send_processed_packet(priv, ptr, ptrindex); LEAVE(); @@ -1407,8 +1387,22 @@ wlan_wmm_init(pmlan_adapter pmadapter) = priv->aggr_prio_tbl[7].ampdu_user = BA_STREAM_NOT_ALLOWED; priv->add_ba_param.timeout = MLAN_DEFAULT_BLOCK_ACK_TIMEOUT; - priv->add_ba_param.tx_win_size = MLAN_AMPDU_DEF_TXWINSIZE; - priv->add_ba_param.rx_win_size = MLAN_AMPDU_DEF_RXWINSIZE; +#ifdef STA_SUPPORT + if (priv->bss_type == MLAN_BSS_TYPE_STA) { + priv->add_ba_param.tx_win_size = MLAN_STA_AMPDU_DEF_TXWINSIZE; + priv->add_ba_param.rx_win_size = MLAN_STA_AMPDU_DEF_RXWINSIZE; + } +#endif +#ifdef UAP_SUPPORT + if (priv->bss_type == MLAN_BSS_TYPE_UAP +#ifdef WIFI_DIRECT_SUPPORT + || priv->bss_type == MLAN_BSS_TYPE_WIFIDIRECT +#endif + ) { + priv->add_ba_param.tx_win_size = MLAN_UAP_AMPDU_DEF_TXWINSIZE; + priv->add_ba_param.rx_win_size = MLAN_UAP_AMPDU_DEF_RXWINSIZE; + } +#endif priv->add_ba_param.tx_amsdu = MTRUE; priv->add_ba_param.rx_amsdu = MTRUE; memset(priv->adapter, priv->rx_seq, 0xff, sizeof(priv->rx_seq)); @@ -1885,8 +1879,7 @@ wlan_wmm_process_association_req(pmlan_private priv, if ((priv->wmm_required || (pHTCap && (pHTCap->ieee_hdr.element_id == HT_CAPABILITY) - && (priv->adapter->config_bands & BAND_GN - || priv->adapter->config_bands & BAND_AN)) + && (priv->config_bands & BAND_GN || priv->config_bands & BAND_AN)) ) && pWmmIE->vend_hdr.element_id == WMM_IE) { pwmm_tlv = (MrvlIEtypes_WmmParamSet_t *) * ppAssocBuf; @@ -2015,14 +2008,12 @@ wlan_wmm_select_queue(mlan_private * pmpriv, t_u8 tid) * @param priv Pointer to the mlan_private driver data struct * @param ra_list_head ra list header * @param tid tid - * @param tx_pause tx_pause flag * * @return N/A */ static INLINE t_u8 wlan_del_tx_pkts_in_ralist(pmlan_private priv, - mlan_list_head * ra_list_head, - int tid, t_u8 tx_pause) + mlan_list_head * ra_list_head, int tid) { raListTbl *ra_list = MNULL; pmlan_adapter pmadapter = priv->adapter; @@ -2034,15 +2025,14 @@ wlan_del_tx_pkts_in_ralist(pmlan_private priv, MNULL, MNULL); while (ra_list && ra_list != (raListTbl *) ra_list_head) { if (ra_list->total_pkts && (ra_list->tx_pause || - (!tx_pause && - ra_list->total_pkts > RX_LOW_THRESHOLD))) { + (ra_list->total_pkts > RX_LOW_THRESHOLD))) { if ((pmbuf = (pmlan_buffer) util_dequeue_list(pmadapter->pmoal_handle, &ra_list->buf_head, MNULL, MNULL))) { PRINTM(MDATA, "Drop pkts: tid=%d tx_pause=%d pkts=%d brd_pkts=%d %02x:%02x:%02x:%02x:%02x:%02x\n", - tid, tx_pause, ra_list->total_pkts, + tid, ra_list->tx_pause, ra_list->total_pkts, pmadapter->pending_bridge_pkts, ra_list->ra[0], ra_list->ra[1], ra_list->ra[2], ra_list->ra[3], ra_list->ra[4], ra_list->ra[5]); @@ -2077,17 +2067,14 @@ wlan_drop_tx_pkts(pmlan_private priv) { int j; static int i = 0; - t_u8 tx_pause = 0; pmlan_adapter pmadapter = priv->adapter; pmadapter->callbacks.moal_spin_lock(pmadapter->pmoal_handle, priv->wmm.ra_list_spinlock); - if (wlan_get_tx_pause_station_entry(priv)) - tx_pause = 1; for (j = 0; j < MAX_NUM_TID; j++, i++) { if (i == MAX_NUM_TID) i = 0; if (wlan_del_tx_pkts_in_ralist - (priv, &priv->wmm.tid_tbl_ptr[i].ra_list, i, tx_pause)) { + (priv, &priv->wmm.tid_tbl_ptr[i].ra_list, i)) { i++; break; } diff --git a/drivers/net/wireless/sd8797/mlinux/mlan.h b/drivers/net/wireless/sd8797/mlinux/mlan.h new file mode 100644 index 000000000000..a341e1547099 --- /dev/null +++ b/drivers/net/wireless/sd8797/mlinux/mlan.h @@ -0,0 +1,35 @@ +/** @file mlan.h + * + * @brief This file declares all APIs that will be called from MOAL module. + * It also defines the data structures used for APIs between MLAN and MOAL. + * + * Copyright (C) 2008-2011, Marvell International Ltd. + * + * This software file (the "File") is distributed by Marvell International + * Ltd. under the terms of the GNU General Public License Version 2, June 1991 + * (the "License"). You may use, redistribute and/or modify this File in + * accordance with the terms and conditions of the License, a copy of which + * is available by writing to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the + * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt. + * + * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE + * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE + * ARE EXPRESSLY DISCLAIMED. The License provides additional details about + * this warranty disclaimer. + */ + +/****************************************************** +Change log: + 10/13/2008: initial version + 11/07/2008: split mlan.h into mlan_decl.h & mlan_ioctl.h +******************************************************/ + +#ifndef _MLAN_H_ +#define _MLAN_H_ + +#include "mlan_decl.h" +#include "mlan_ioctl.h" +#include "mlan_ieee.h" + +#endif /* !_MLAN_H_ */ diff --git a/drivers/net/wireless/sd8797/mlinux/mlan_decl.h b/drivers/net/wireless/sd8797/mlinux/mlan_decl.h new file mode 100644 index 000000000000..41cf2bf5f2f1 --- /dev/null +++ b/drivers/net/wireless/sd8797/mlinux/mlan_decl.h @@ -0,0 +1,893 @@ +/** @file mlan_decl.h + * + * @brief This file declares the generic data structures and APIs. + * + * Copyright (C) 2008-2011, Marvell International Ltd. + * + * This software file (the "File") is distributed by Marvell International + * Ltd. under the terms of the GNU General Public License Version 2, June 1991 + * (the "License"). You may use, redistribute and/or modify this File in + * accordance with the terms and conditions of the License, a copy of which + * is available by writing to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the + * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt. + * + * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE + * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE + * ARE EXPRESSLY DISCLAIMED. The License provides additional details about + * this warranty disclaimer. + */ + +/****************************************************** +Change log: + 11/07/2008: initial version +******************************************************/ + +#ifndef _MLAN_DECL_H_ +#define _MLAN_DECL_H_ + +/** MLAN release version */ +#define MLAN_RELEASE_VERSION "311" + +/** Re-define generic data types for MLAN/MOAL */ +/** Signed char (1-byte) */ +typedef char t_s8; +/** Unsigned char (1-byte) */ +typedef unsigned char t_u8; +/** Signed short (2-bytes) */ +typedef short t_s16; +/** Unsigned short (2-bytes) */ +typedef unsigned short t_u16; +/** Signed long (4-bytes) */ +typedef int t_s32; +/** Unsigned long (4-bytes) */ +typedef unsigned int t_u32; +/** Signed long long 8-bytes) */ +typedef long long t_s64; +/** Unsigned long long 8-bytes) */ +typedef unsigned long long t_u64; +/** Void pointer (4-bytes) */ +typedef void t_void; +/** Size type */ +typedef t_u32 t_size; +/** Boolean type */ +typedef t_u8 t_bool; + +#ifdef MLAN_64BIT +/** Pointer type (64-bit) */ +typedef t_u64 t_ptr; +/** Signed value (64-bit) */ +typedef t_s64 t_sval; +#else +/** Pointer type (32-bit) */ +typedef t_u32 t_ptr; +/** Signed value (32-bit) */ +typedef t_s32 t_sval; +#endif + +/** Constants below */ + +#ifdef __GNUC__ +/** Structure packing begins */ +#define MLAN_PACK_START +/** Structure packeing end */ +#define MLAN_PACK_END __attribute__ ((packed)) +#else /* !__GNUC__ */ +#ifdef PRAGMA_PACK +/** Structure packing begins */ +#define MLAN_PACK_START +/** Structure packeing end */ +#define MLAN_PACK_END +#else /* !PRAGMA_PACK */ +/** Structure packing begins */ +#define MLAN_PACK_START __packed +/** Structure packing end */ +#define MLAN_PACK_END +#endif /* PRAGMA_PACK */ +#endif /* __GNUC__ */ + +#ifndef INLINE +#ifdef __GNUC__ +/** inline directive */ +#define INLINE inline +#else +/** inline directive */ +#define INLINE __inline +#endif +#endif + +/** MLAN TRUE */ +#define MTRUE (1) +/** MLAN FALSE */ +#define MFALSE (0) + +/** Macros for Data Alignment : size */ +#define ALIGN_SZ(p, a) \ + (((p) + ((a) - 1)) & ~((a) - 1)) + +/** Macros for Data Alignment : address */ +#define ALIGN_ADDR(p, a) \ + ((((t_ptr)(p)) + (((t_ptr)(a)) - 1)) & ~(((t_ptr)(a)) - 1)) + +/** Return the byte offset of a field in the given structure */ +#define MLAN_FIELD_OFFSET(type, field) ((t_u32)(t_ptr)&(((type *)0)->field)) +/** Return aligned offset */ +#define OFFSET_ALIGN_ADDR(p, a) (t_u32)(ALIGN_ADDR(p, a) - (t_ptr)p) + +/** Maximum BSS numbers */ +#define MLAN_MAX_BSS_NUM (16) + +/** NET IP alignment */ +#define MLAN_NET_IP_ALIGN 0 + +/** DMA alignment */ +#define DMA_ALIGNMENT 64 +/** max size of TxPD */ +#define MAX_TXPD_SIZE 32 + +/** Minimum data header length */ +#define MLAN_MIN_DATA_HEADER_LEN (DMA_ALIGNMENT+MAX_TXPD_SIZE) + +/** rx data header length */ +#define MLAN_RX_HEADER_LEN MLAN_MIN_DATA_HEADER_LEN + +/** This is current limit on Maximum Tx AMPDU allowed */ +#define MLAN_MAX_TX_BASTREAM_SUPPORTED 2 +/** This is current limit on Maximum Rx AMPDU allowed */ +#define MLAN_MAX_RX_BASTREAM_SUPPORTED 16 + +#ifdef STA_SUPPORT +/** Default Win size attached during ADDBA request */ +#define MLAN_STA_AMPDU_DEF_TXWINSIZE 16 +/** Default Win size attached during ADDBA response */ +#define MLAN_STA_AMPDU_DEF_RXWINSIZE 32 +#endif /* STA_SUPPORT */ +#ifdef UAP_SUPPORT +/** Default Win size attached during ADDBA request */ +#define MLAN_UAP_AMPDU_DEF_TXWINSIZE 32 +/** Default Win size attached during ADDBA response */ +#define MLAN_UAP_AMPDU_DEF_RXWINSIZE 16 +#endif /* UAP_SUPPORT */ +/** Block ack timeout value */ +#define MLAN_DEFAULT_BLOCK_ACK_TIMEOUT 0xffff +/** Maximum Tx Win size configured for ADDBA request [10 bits] */ +#define MLAN_AMPDU_MAX_TXWINSIZE 0x3ff +/** Maximum Rx Win size configured for ADDBA request [10 bits] */ +#define MLAN_AMPDU_MAX_RXWINSIZE 0x3ff + +/** Rate index for HR/DSSS 0 */ +#define MLAN_RATE_INDEX_HRDSSS0 0 +/** Rate index for HR/DSSS 3 */ +#define MLAN_RATE_INDEX_HRDSSS3 3 +/** Rate index for OFDM 0 */ +#define MLAN_RATE_INDEX_OFDM0 4 +/** Rate index for OFDM 7 */ +#define MLAN_RATE_INDEX_OFDM7 11 +/** Rate index for MCS 0 */ +#define MLAN_RATE_INDEX_MCS0 12 +/** Rate index for MCS 7 */ +#define MLAN_RATE_INDEX_MCS7 19 +/** Rate index for MCS 9 */ +#define MLAN_RATE_INDEX_MCS9 21 +/** Rate index for MCS15 */ +#define MLAN_RATE_INDEX_MCS15 27 +/** Rate index for MCS 32 */ +#define MLAN_RATE_INDEX_MCS32 44 +/** Rate index for MCS 127 */ +#define MLAN_RATE_INDEX_MCS127 139 + +/** Rate bitmap for OFDM 0 */ +#define MLAN_RATE_BITMAP_OFDM0 16 +/** Rate bitmap for OFDM 7 */ +#define MLAN_RATE_BITMAP_OFDM7 23 +/** Rate bitmap for MCS 0 */ +#define MLAN_RATE_BITMAP_MCS0 32 +/** Rate bitmap for MCS 127 */ +#define MLAN_RATE_BITMAP_MCS127 159 + +/** Size of rx data buffer */ +#define MLAN_RX_DATA_BUF_SIZE (4 * 1024) +/** Size of rx command buffer */ +#define MLAN_RX_CMD_BUF_SIZE (2 * 1024) + +/** MLAN MAC Address Length */ +#define MLAN_MAC_ADDR_LENGTH (6) +/** MLAN 802.11 MAC Address */ +typedef t_u8 mlan_802_11_mac_addr[MLAN_MAC_ADDR_LENGTH]; + +/** MLAN Maximum SSID Length */ +#define MLAN_MAX_SSID_LENGTH (32) + +/** RTS/FRAG related defines */ +/** Minimum RTS value */ +#define MLAN_RTS_MIN_VALUE (0) +/** Maximum RTS value */ +#define MLAN_RTS_MAX_VALUE (2347) +/** Minimum FRAG value */ +#define MLAN_FRAG_MIN_VALUE (256) +/** Maximum FRAG value */ +#define MLAN_FRAG_MAX_VALUE (2346) + +/** Minimum tx retry count */ +#define MLAN_TX_RETRY_MIN (0) +/** Maximum tx retry count */ +#define MLAN_TX_RETRY_MAX (14) + +/** define SDIO block size for data Tx/Rx */ +/* We support up to 480-byte block size due to FW buffer limitation. */ +#define MLAN_SDIO_BLOCK_SIZE 256 + +/** define SDIO block size for firmware download */ +#define MLAN_SDIO_BLOCK_SIZE_FW_DNLD MLAN_SDIO_BLOCK_SIZE + +/** define allocated buffer size */ +#define ALLOC_BUF_SIZE (4 * 1024) + +/** SDIO IO Port mask */ +#define MLAN_SDIO_IO_PORT_MASK 0xfffff +/** SDIO Block/Byte mode mask */ +#define MLAN_SDIO_BYTE_MODE_MASK 0x80000000 + +/** Max retry number of IO write */ +#define MAX_WRITE_IOMEM_RETRY 2 + +/** IN parameter */ +#define IN +/** OUT parameter */ +#define OUT + +/** BIT value */ +#define MBIT(x) (((t_u32)1) << (x)) + +/** Buffer flag for requeued packet */ +#define MLAN_BUF_FLAG_REQUEUED_PKT MBIT(0) +/** Buffer flag for transmit buf from moal */ +#define MLAN_BUF_FLAG_MOAL_TX_BUF MBIT(1) +/** Buffer flag for malloc mlan_buffer */ +#define MLAN_BUF_FLAG_MALLOC_BUF MBIT(2) + +/** Buffer flag for bridge packet */ +#define MLAN_BUF_FLAG_BRIDGE_BUF MBIT(3) + +#ifdef DEBUG_LEVEL1 +/** Debug level bit definition */ +#define MMSG MBIT(0) +#define MFATAL MBIT(1) +#define MERROR MBIT(2) +#define MDATA MBIT(3) +#define MCMND MBIT(4) +#define MEVENT MBIT(5) +#define MINTR MBIT(6) +#define MIOCTL MBIT(7) + +#define MDAT_D MBIT(16) +#define MCMD_D MBIT(17) +#define MEVT_D MBIT(18) +#define MFW_D MBIT(19) +#define MIF_D MBIT(20) + +#define MENTRY MBIT(28) +#define MWARN MBIT(29) +#define MINFO MBIT(30) +#define MHEX_DUMP MBIT(31) +#endif /* DEBUG_LEVEL1 */ + +/** Memory allocation type: DMA */ +#define MLAN_MEM_DMA MBIT(0) + +/** Default memory allocation flag */ +#define MLAN_MEM_DEF 0 + +/** mlan_status */ +typedef enum _mlan_status +{ + MLAN_STATUS_FAILURE = 0xffffffff, + MLAN_STATUS_SUCCESS = 0, + MLAN_STATUS_PENDING, + MLAN_STATUS_RESOURCE, +} mlan_status; + +/** mlan_error_code */ +typedef enum _mlan_error_code +{ + /** No error */ + MLAN_ERROR_NO_ERROR = 0, + /** Firmware/device errors below (MSB=0) */ + MLAN_ERROR_FW_NOT_READY = 0x00000001, + MLAN_ERROR_FW_BUSY, + MLAN_ERROR_FW_CMDRESP, + MLAN_ERROR_DATA_TX_FAIL, + MLAN_ERROR_DATA_RX_FAIL, + /** Driver errors below (MSB=1) */ + MLAN_ERROR_PKT_SIZE_INVALID = 0x80000001, + MLAN_ERROR_PKT_TIMEOUT, + MLAN_ERROR_PKT_INVALID, + MLAN_ERROR_CMD_INVALID, + MLAN_ERROR_CMD_TIMEOUT, + MLAN_ERROR_CMD_DNLD_FAIL, + MLAN_ERROR_CMD_CANCEL, + MLAN_ERROR_CMD_RESP_FAIL, + MLAN_ERROR_CMD_ASSOC_FAIL, + MLAN_ERROR_CMD_SCAN_FAIL, + MLAN_ERROR_IOCTL_INVALID, + MLAN_ERROR_IOCTL_FAIL, + MLAN_ERROR_EVENT_UNKNOWN, + MLAN_ERROR_INVALID_PARAMETER, + MLAN_ERROR_NO_MEM, + /** More to add */ +} mlan_error_code; + +/** mlan_buf_type */ +typedef enum _mlan_buf_type +{ + MLAN_BUF_TYPE_CMD = 1, + MLAN_BUF_TYPE_DATA, + MLAN_BUF_TYPE_EVENT, + MLAN_BUF_TYPE_RAW_DATA, +} mlan_buf_type; + +/** MLAN BSS type */ +typedef enum _mlan_bss_type +{ + MLAN_BSS_TYPE_STA = 0, + MLAN_BSS_TYPE_UAP = 1, +#ifdef WIFI_DIRECT_SUPPORT + MLAN_BSS_TYPE_WIFIDIRECT = 2, +#endif + MLAN_BSS_TYPE_ANY = 0xff, +} mlan_bss_type; + +/** MLAN BSS role */ +typedef enum _mlan_bss_role +{ + MLAN_BSS_ROLE_STA = 0, + MLAN_BSS_ROLE_UAP = 1, + MLAN_BSS_ROLE_ANY = 0xff, +} mlan_bss_role; + +/** BSS role bit mask */ +#define BSS_ROLE_BIT_MASK MBIT(0) + +/** Get BSS role */ +#define GET_BSS_ROLE(priv) ((priv)->bss_role & BSS_ROLE_BIT_MASK) + +/** mlan_data_frame_type */ +typedef enum _mlan_data_frame_type +{ + MLAN_DATA_FRAME_TYPE_ETH_II = 0, + MLAN_DATA_FRAME_TYPE_802_11, +} mlan_data_frame_type; + +/** mlan_event_id */ +typedef enum _mlan_event_id +{ + /* Event generated by firmware (MSB=0) */ + MLAN_EVENT_ID_FW_UNKNOWN = 0x00000001, + MLAN_EVENT_ID_FW_ADHOC_LINK_SENSED, + MLAN_EVENT_ID_FW_ADHOC_LINK_LOST, + MLAN_EVENT_ID_FW_DISCONNECTED, + MLAN_EVENT_ID_FW_MIC_ERR_UNI, + MLAN_EVENT_ID_FW_MIC_ERR_MUL, + MLAN_EVENT_ID_FW_BCN_RSSI_LOW, + MLAN_EVENT_ID_FW_BCN_RSSI_HIGH, + MLAN_EVENT_ID_FW_BCN_SNR_LOW, + MLAN_EVENT_ID_FW_BCN_SNR_HIGH, + MLAN_EVENT_ID_FW_MAX_FAIL, + MLAN_EVENT_ID_FW_DATA_RSSI_LOW, + MLAN_EVENT_ID_FW_DATA_RSSI_HIGH, + MLAN_EVENT_ID_FW_DATA_SNR_LOW, + MLAN_EVENT_ID_FW_DATA_SNR_HIGH, + MLAN_EVENT_ID_FW_LINK_QUALITY, + MLAN_EVENT_ID_FW_PORT_RELEASE, + MLAN_EVENT_ID_FW_PRE_BCN_LOST, + MLAN_EVENT_ID_FW_WMM_CONFIG_CHANGE, + MLAN_EVENT_ID_FW_HS_WAKEUP, + MLAN_EVENT_ID_FW_BG_SCAN, + MLAN_EVENT_ID_FW_WEP_ICV_ERR, + MLAN_EVENT_ID_FW_STOP_TX, + MLAN_EVENT_ID_FW_START_TX, + MLAN_EVENT_ID_FW_CHANNEL_SWITCH_ANN, + MLAN_EVENT_ID_FW_RADAR_DETECTED, + MLAN_EVENT_ID_FW_CHANNEL_REPORT_RDY, + MLAN_EVENT_ID_FW_BW_CHANGED, +#ifdef WIFI_DIRECT_SUPPORT + MLAN_EVENT_ID_FW_REMAIN_ON_CHAN_EXPIRED, +#endif +#ifdef UAP_SUPPORT + MLAN_EVENT_ID_UAP_FW_BSS_START, + MLAN_EVENT_ID_UAP_FW_BSS_ACTIVE, + MLAN_EVENT_ID_UAP_FW_BSS_IDLE, + MLAN_EVENT_ID_UAP_FW_STA_CONNECT, + MLAN_EVENT_ID_UAP_FW_STA_DISCONNECT, +#endif + + /* Event generated by MLAN driver (MSB=1) */ + MLAN_EVENT_ID_DRV_CONNECTED = 0x80000001, + MLAN_EVENT_ID_DRV_DEFER_HANDLING, + MLAN_EVENT_ID_DRV_HS_ACTIVATED, + MLAN_EVENT_ID_DRV_HS_DEACTIVATED, + MLAN_EVENT_ID_DRV_MGMT_FRAME, + MLAN_EVENT_ID_DRV_OBSS_SCAN_PARAM, + MLAN_EVENT_ID_DRV_PASSTHRU, + MLAN_EVENT_ID_DRV_SCAN_REPORT, + MLAN_EVENT_ID_DRV_MEAS_REPORT, + MLAN_EVENT_ID_DRV_REPORT_STRING, + MLAN_EVENT_ID_DRV_DBG_DUMP, +} mlan_event_id; + +/** Data Structures */ +/** mlan_image data structure */ +typedef struct _mlan_fw_image +{ + /** Helper image buffer pointer */ + t_u8 *phelper_buf; + /** Helper image length */ + t_u32 helper_len; + /** Firmware image buffer pointer */ + t_u8 *pfw_buf; + /** Firmware image length */ + t_u32 fw_len; +} mlan_fw_image, *pmlan_fw_image; + +/** Custom data structure */ +typedef struct _mlan_init_param +{ + /** Cal data buffer pointer */ + t_u8 *pcal_data_buf; + /** Cal data length */ + t_u32 cal_data_len; + /** Other custom data */ +} mlan_init_param, *pmlan_init_param; + +/** mlan_event data structure */ +typedef struct _mlan_event +{ + /** BSS index number for multiple BSS support */ + t_u32 bss_index; + /** Event ID */ + mlan_event_id event_id; + /** Event length */ + t_u32 event_len; + /** Event buffer */ + t_u8 event_buf[1]; +} mlan_event, *pmlan_event; + +/** mlan_event_scan_result data structure */ +typedef MLAN_PACK_START struct _mlan_event_scan_result +{ + /** Event ID */ + t_u16 event_id; + /** BSS index number for multiple BSS support */ + t_u8 bss_index; + /** BSS type */ + t_u8 bss_type; + /** More event available or not */ + t_u8 more_event; + /** Reserved */ + t_u8 reserved[3]; + /** Size of the response buffer */ + t_u16 buf_size; + /** Number of BSS in scan response */ + t_u8 num_of_set; +} MLAN_PACK_END mlan_event_scan_result, *pmlan_event_scan_result; + +/** mlan_ioctl_req data structure */ +typedef struct _mlan_ioctl_req +{ + /** Status code from firmware/driver */ + t_u32 status_code; + /** BSS index number for multiple BSS support */ + t_u32 bss_index; + /** Request id */ + t_u32 req_id; + /** Action: set or get */ + t_u32 action; + /** Pointer to buffer */ + t_u8 *pbuf; + /** Length of buffer */ + t_u32 buf_len; + /** Length of the data read/written in buffer */ + t_u32 data_read_written; + /** Length of buffer needed */ + t_u32 buf_len_needed; + /** Reserved for MOAL module */ + t_ptr reserved_1; +} mlan_ioctl_req, *pmlan_ioctl_req; + +/** mlan_buffer data structure */ +typedef struct _mlan_buffer +{ + /** Pointer to previous mlan_buffer */ + struct _mlan_buffer *pprev; + /** Pointer to next mlan_buffer */ + struct _mlan_buffer *pnext; + /** Status code from firmware/driver */ + t_u32 status_code; + /** Flags for this buffer */ + t_u32 flags; + /** BSS index number for multiple BSS support */ + t_u32 bss_index; + /** Buffer descriptor, e.g. skb in Linux */ + t_void *pdesc; + /** Pointer to buffer */ + t_u8 *pbuf; + /** Offset to data */ + t_u32 data_offset; + /** Data length */ + t_u32 data_len; + /** Buffer type: data, cmd, event etc. */ + mlan_buf_type buf_type; + + /** Fields below are valid for data packet only */ + /** QoS priority */ + t_u32 priority; + /** Time stamp when packet is received (seconds) */ + t_u32 in_ts_sec; + /** Time stamp when packet is received (micro seconds) */ + t_u32 in_ts_usec; + /** Time stamp when packet is processed (seconds) */ + t_u32 out_ts_sec; + /** Time stamp when packet is processed (micro seconds) */ + t_u32 out_ts_usec; + + /** Fields below are valid for MLAN module only */ + /** Pointer to parent mlan_buffer */ + struct _mlan_buffer *pparent; + /** Use count for this buffer */ + t_u32 use_count; +} mlan_buffer, *pmlan_buffer; + +/** mlan_bss_attr data structure */ +typedef struct _mlan_bss_attr +{ + /** BSS type */ + t_u32 bss_type; + /** Data frame type: Ethernet II, 802.11, etc. */ + t_u32 frame_type; + /** The BSS is active (non-0) or not (0). */ + t_u32 active; + /** BSS Priority */ + t_u32 bss_priority; + /** BSS number */ + t_u32 bss_num; +} mlan_bss_attr, *pmlan_bss_attr; + +#ifdef PRAGMA_PACK +#pragma pack(push, 1) +#endif + +/** Type enumeration for the command result */ +typedef MLAN_PACK_START enum _mlan_cmd_result_e +{ + MLAN_CMD_RESULT_SUCCESS = 0, + MLAN_CMD_RESULT_FAILURE = 1, + MLAN_CMD_RESULT_TIMEOUT = 2, + MLAN_CMD_RESULT_INVALID_DATA = 3 +} MLAN_PACK_END mlan_cmd_result_e; + +/** Type enumeration of WMM AC_QUEUES */ +typedef MLAN_PACK_START enum _mlan_wmm_ac_e +{ + WMM_AC_BK, + WMM_AC_BE, + WMM_AC_VI, + WMM_AC_VO +} MLAN_PACK_END mlan_wmm_ac_e; + +/** Type enumeration for the action field in the Queue Config command */ +typedef MLAN_PACK_START enum _mlan_wmm_queue_config_action_e +{ + MLAN_WMM_QUEUE_CONFIG_ACTION_GET = 0, + MLAN_WMM_QUEUE_CONFIG_ACTION_SET = 1, + MLAN_WMM_QUEUE_CONFIG_ACTION_DEFAULT = 2, + MLAN_WMM_QUEUE_CONFIG_ACTION_MAX +} MLAN_PACK_END mlan_wmm_queue_config_action_e; + +/** Type enumeration for the action field in the queue stats command */ +typedef MLAN_PACK_START enum _mlan_wmm_queue_stats_action_e +{ + MLAN_WMM_STATS_ACTION_START = 0, + MLAN_WMM_STATS_ACTION_STOP = 1, + MLAN_WMM_STATS_ACTION_GET_CLR = 2, + MLAN_WMM_STATS_ACTION_SET_CFG = 3, /* Not currently used */ + MLAN_WMM_STATS_ACTION_GET_CFG = 4, /* Not currently used */ + MLAN_WMM_STATS_ACTION_MAX +} MLAN_PACK_END mlan_wmm_queue_stats_action_e; + +/** + * @brief IOCTL structure for a Traffic stream status. + * + */ +typedef MLAN_PACK_START struct +{ + /** TSID: Range: 0->7 */ + t_u8 tid; + /** TSID specified is valid */ + t_u8 valid; + /** AC TSID is active on */ + t_u8 access_category; + /** UP specified for the TSID */ + t_u8 user_priority; + /** Power save mode for TSID: 0 (legacy), 1 (UAPSD) */ + t_u8 psb; + /** Upstream(0), Downlink(1), Bidirectional(3) */ + t_u8 flow_dir; + /** Medium time granted for the TSID */ + t_u16 medium_time; +} MLAN_PACK_END wlan_ioctl_wmm_ts_status_t, +/** Type definition of mlan_ds_wmm_ts_status for MLAN_OID_WMM_CFG_TS_STATUS */ + mlan_ds_wmm_ts_status, *pmlan_ds_wmm_ts_status; + +/** Max Ie length */ +#define MAX_IE_SIZE 256 + +/** custom IE */ +typedef MLAN_PACK_START struct _custom_ie +{ + /** IE Index */ + t_u16 ie_index; + /** Mgmt Subtype Mask */ + t_u16 mgmt_subtype_mask; + /** IE Length */ + t_u16 ie_length; + /** IE buffer */ + t_u8 ie_buffer[MAX_IE_SIZE]; +} MLAN_PACK_END custom_ie; + +/** Max IE index to FW */ +#define MAX_MGMT_IE_INDEX_TO_FW 4 +/** Max IE index per BSS */ +#define MAX_MGMT_IE_INDEX 16 + +/** custom IE info */ +typedef MLAN_PACK_START struct _custom_ie_info +{ + /** size of buffer */ + t_u16 buf_size; + /** no of buffers of buf_size */ + t_u16 buf_count; +} MLAN_PACK_END custom_ie_info; + +/** TLV buffer : Max Mgmt IE */ +typedef MLAN_PACK_START struct _tlvbuf_max_mgmt_ie +{ + /** Type */ + t_u16 type; + /** Length */ + t_u16 len; + /** No of tuples */ + t_u16 count; + /** custom IE info tuples */ + custom_ie_info info[MAX_MGMT_IE_INDEX]; +} MLAN_PACK_END tlvbuf_max_mgmt_ie; + +/** TLV buffer : custom IE */ +typedef MLAN_PACK_START struct _tlvbuf_custom_ie +{ + /** Type */ + t_u16 type; + /** Length */ + t_u16 len; + /** IE data */ + custom_ie ie_data_list[MAX_MGMT_IE_INDEX_TO_FW]; + /** Max mgmt IE TLV */ + tlvbuf_max_mgmt_ie max_mgmt_ie; +} MLAN_PACK_END mlan_ds_misc_custom_ie; + +#ifdef PRAGMA_PACK +#pragma pack(pop) +#endif + +/** mlan_callbacks data structure */ +typedef struct _mlan_callbacks +{ + /** moal_get_fw_data */ + mlan_status(*moal_get_fw_data) (IN t_void * pmoal_handle, + IN t_u32 offset, + IN t_u32 len, OUT t_u8 * pbuf); + /** moal_init_fw_complete */ + mlan_status(*moal_init_fw_complete) (IN t_void * pmoal_handle, + IN mlan_status status); + /** moal_shutdown_fw_complete */ + mlan_status(*moal_shutdown_fw_complete) (IN t_void * pmoal_handle, + IN mlan_status status); + /** moal_send_packet_complete */ + mlan_status(*moal_send_packet_complete) (IN t_void * pmoal_handle, + IN pmlan_buffer pmbuf, + IN mlan_status status); + /** moal_recv_complete */ + mlan_status(*moal_recv_complete) (IN t_void * pmoal_handle, + IN pmlan_buffer pmbuf, + IN t_u32 port, IN mlan_status status); + /** moal_recv_packet */ + mlan_status(*moal_recv_packet) (IN t_void * pmoal_handle, + IN pmlan_buffer pmbuf); + /** moal_recv_event */ + mlan_status(*moal_recv_event) (IN t_void * pmoal_handle, + IN pmlan_event pmevent); + /** moal_ioctl_complete */ + mlan_status(*moal_ioctl_complete) (IN t_void * pmoal_handle, + IN pmlan_ioctl_req pioctl_req, + IN mlan_status status); + /** moal_alloc_mlan_buffer */ + mlan_status(*moal_alloc_mlan_buffer) (IN t_void * pmoal_handle, + IN t_u32 size, + OUT pmlan_buffer * pmbuf); + /** moal_free_mlan_buffer */ + mlan_status(*moal_free_mlan_buffer) (IN t_void * pmoal_handle, + IN pmlan_buffer pmbuf); + /** moal_write_reg */ + mlan_status(*moal_write_reg) (IN t_void * pmoal_handle, + IN t_u32 reg, IN t_u32 data); + /** moal_read_reg */ + mlan_status(*moal_read_reg) (IN t_void * pmoal_handle, + IN t_u32 reg, OUT t_u32 * data); + /** moal_write_data_sync */ + mlan_status(*moal_write_data_sync) (IN t_void * pmoal_handle, + IN pmlan_buffer pmbuf, + IN t_u32 port, IN t_u32 timeout); + /** moal_read_data_sync */ + mlan_status(*moal_read_data_sync) (IN t_void * pmoal_handle, + IN OUT pmlan_buffer pmbuf, + IN t_u32 port, IN t_u32 timeout); + /** moal_malloc */ + mlan_status(*moal_malloc) (IN t_void * pmoal_handle, + IN t_u32 size, IN t_u32 flag, OUT t_u8 ** ppbuf); + /** moal_mfree */ + mlan_status(*moal_mfree) (IN t_void * pmoal_handle, IN t_u8 * pbuf); + /** moal_memset */ + t_void *(*moal_memset) (IN t_void * pmoal_handle, + IN t_void * pmem, IN t_u8 byte, IN t_u32 num); + /** moal_memcpy */ + t_void *(*moal_memcpy) (IN t_void * pmoal_handle, + IN t_void * pdest, + IN const t_void * psrc, IN t_u32 num); + /** moal_memmove */ + t_void *(*moal_memmove) (IN t_void * pmoal_handle, + IN t_void * pdest, + IN const t_void * psrc, IN t_u32 num); + /** moal_memcmp */ + t_s32(*moal_memcmp) (IN t_void * pmoal_handle, + IN const t_void * pmem1, + IN const t_void * pmem2, IN t_u32 num); + /** moal_udelay */ + t_void(*moal_udelay) (IN t_void * pmoal_handle, IN t_u32 udelay); + /** moal_get_system_time */ + mlan_status(*moal_get_system_time) (IN t_void * pmoal_handle, + OUT t_u32 * psec, OUT t_u32 * pusec); + /** moal_init_timer*/ + mlan_status(*moal_init_timer) (IN t_void * pmoal_handle, + OUT t_void ** pptimer, + IN t_void(*callback) (t_void * pcontext), + IN t_void * pcontext); + /** moal_free_timer */ + mlan_status(*moal_free_timer) (IN t_void * pmoal_handle, + IN t_void * ptimer); + /** moal_start_timer*/ + mlan_status(*moal_start_timer) (IN t_void * pmoal_handle, + IN t_void * ptimer, + IN t_u8 periodic, IN t_u32 msec); + /** moal_stop_timer*/ + mlan_status(*moal_stop_timer) (IN t_void * pmoal_handle, + IN t_void * ptimer); + /** moal_init_lock */ + mlan_status(*moal_init_lock) (IN t_void * pmoal_handle, + OUT t_void ** pplock); + /** moal_free_lock */ + mlan_status(*moal_free_lock) (IN t_void * pmoal_handle, + IN t_void * plock); + /** moal_spin_lock */ + mlan_status(*moal_spin_lock) (IN t_void * pmoal_handle, + IN t_void * plock); + /** moal_spin_unlock */ + mlan_status(*moal_spin_unlock) (IN t_void * pmoal_handle, + IN t_void * plock); + /** moal_print */ + t_void(*moal_print) (IN t_void * pmoal_handle, + IN t_u32 level, IN t_s8 * pformat, IN ...); + /** moal_print_netintf */ + t_void(*moal_print_netintf) (IN t_void * pmoal_handle, + IN t_u32 bss_index, IN t_u32 level); + /** moal_assert */ + t_void(*moal_assert) (IN t_void * pmoal_handle, IN t_u32 cond); +} mlan_callbacks, *pmlan_callbacks; + +/** Interrupt Mode SDIO */ +#define INT_MODE_SDIO 0 +/** Interrupt Mode GPIO */ +#define INT_MODE_GPIO 1 + +/** Parameter unchanged, use MLAN default setting */ +#define MLAN_INIT_PARA_UNCHANGED 0 +/** Parameter enabled, override MLAN default setting */ +#define MLAN_INIT_PARA_ENABLED 1 +/** Parameter disabled, override MLAN default setting */ +#define MLAN_INIT_PARA_DISABLED 2 + +/** mlan_device data structure */ +typedef struct _mlan_device +{ + /** MOAL Handle */ + t_void *pmoal_handle; + /** BSS Attributes */ + mlan_bss_attr bss_attr[MLAN_MAX_BSS_NUM]; + /** Callbacks */ + mlan_callbacks callbacks; +#ifdef MFG_CMD_SUPPORT + /** MFG mode */ + t_u32 mfg_mode; +#endif + /** SDIO interrupt mode (0: INT_MODE_SDIO, 1: INT_MODE_GPIO) */ + t_u32 int_mode; + /** GPIO interrupt pin number */ + t_u32 gpio_pin; +#ifdef DEBUG_LEVEL1 + /** Driver debug bit masks */ + t_u32 drvdbg; +#endif +#ifdef SDIO_MULTI_PORT_TX_AGGR + /** SDIO MPA Tx */ + t_u32 mpa_tx_cfg; +#endif +#ifdef SDIO_MULTI_PORT_RX_AGGR + /** SDIO MPA Rx */ + t_u32 mpa_rx_cfg; +#endif + /** Auto deep sleep */ + t_u32 auto_ds; + /** IEEE PS mode */ + t_u32 ps_mode; + /** Max Tx buffer size */ + t_u32 max_tx_buf; +#if defined(STA_SUPPORT) + /** 802.11d configuration */ + t_u32 cfg_11d; +#endif +} mlan_device, *pmlan_device; + +/** MLAN API function prototype */ +#define MLAN_API + +/** Registration */ +MLAN_API mlan_status mlan_register(IN pmlan_device pmdevice, + OUT t_void ** ppmlan_adapter); + +/** Un-registration */ +MLAN_API mlan_status mlan_unregister(IN t_void * pmlan_adapter); + +/** Firmware Downloading */ +MLAN_API mlan_status mlan_dnld_fw(IN t_void * pmlan_adapter, + IN pmlan_fw_image pmfw); + +/** Custom data pass API */ +MLAN_API mlan_status mlan_set_init_param(IN t_void * pmlan_adapter, + IN pmlan_init_param pparam); + +/** Firmware Initialization */ +MLAN_API mlan_status mlan_init_fw(IN t_void * pmlan_adapter); + +/** Firmware Shutdown */ +MLAN_API mlan_status mlan_shutdown_fw(IN t_void * pmlan_adapter); + +/** Main Process */ +MLAN_API mlan_status mlan_main_process(IN t_void * pmlan_adapter); + +/** Packet Transmission */ +MLAN_API mlan_status mlan_send_packet(IN t_void * pmlan_adapter, + IN pmlan_buffer pmbuf); + +/** Packet Reception complete callback */ +MLAN_API mlan_status mlan_recv_packet_complete(IN t_void * pmlan_adapter, + IN pmlan_buffer pmbuf, + IN mlan_status status); + +/** interrupt handler */ +MLAN_API t_void mlan_interrupt(IN t_void * pmlan_adapter); + +/** mlan ioctl */ +MLAN_API mlan_status mlan_ioctl(IN t_void * pmlan_adapter, + IN pmlan_ioctl_req pioctl_req); +/** mlan select wmm queue */ +MLAN_API t_u8 mlan_select_wmm_queue(IN t_void * pmlan_adapter, + IN t_u8 bss_num, IN t_u8 tid); +#endif /* !_MLAN_DECL_H_ */ diff --git a/drivers/net/wireless/sd8797/mlinux/mlan_ieee.h b/drivers/net/wireless/sd8797/mlinux/mlan_ieee.h new file mode 100644 index 000000000000..2431e06f48fa --- /dev/null +++ b/drivers/net/wireless/sd8797/mlinux/mlan_ieee.h @@ -0,0 +1,1322 @@ +/** @file mlan_ieee.h + * + * @brief This file contains IEEE information element related + * definitions used in MLAN and MOAL module. + * + * Copyright (C) 2008-2011, Marvell International Ltd. + * + * This software file (the "File") is distributed by Marvell International + * Ltd. under the terms of the GNU General Public License Version 2, June 1991 + * (the "License"). You may use, redistribute and/or modify this File in + * accordance with the terms and conditions of the License, a copy of which + * is available by writing to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the + * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt. + * + * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE + * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE + * ARE EXPRESSLY DISCLAIMED. The License provides additional details about + * this warranty disclaimer. + */ + +/****************************************************** +Change log: + 11/03/2008: initial version +******************************************************/ + +#ifndef _MLAN_IEEE_H_ +#define _MLAN_IEEE_H_ + +/** FIX IES size in beacon buffer */ +#define WLAN_802_11_FIXED_IE_SIZE 12 +/** WLAN supported rates */ +#define WLAN_SUPPORTED_RATES 14 + +/** WLAN supported rates extension*/ +#define WLAN_SUPPORTED_RATES_EXT 32 + +/** Enumeration definition*/ +/** WLAN_802_11_NETWORK_TYPE */ +typedef enum _WLAN_802_11_NETWORK_TYPE +{ + Wlan802_11FH, + Wlan802_11DS, + /* Defined as upper bound */ + Wlan802_11NetworkTypeMax +} WLAN_802_11_NETWORK_TYPE; + +/** Maximum size of IEEE Information Elements */ +#define IEEE_MAX_IE_SIZE 256 + +#ifdef BIG_ENDIAN_SUPPORT +/** Frame control: Type Mgmt frame */ +#define IEEE80211_FC_MGMT_FRAME_TYPE_MASK 0x3000 +/** Frame control: SubType Mgmt frame */ +#define IEEE80211_GET_FC_MGMT_FRAME_SUBTYPE(fc) (((fc) & 0xF000) >> 12) +#else +/** Frame control: Type Mgmt frame */ +#define IEEE80211_FC_MGMT_FRAME_TYPE_MASK 0x000C +/** Frame control: SubType Mgmt frame */ +#define IEEE80211_GET_FC_MGMT_FRAME_SUBTYPE(fc) (((fc) & 0x00F0) >> 4) +#endif + +#ifdef PRAGMA_PACK +#pragma pack(push, 1) +#endif + +/** IEEE Type definitions */ +typedef MLAN_PACK_START enum _IEEEtypes_ElementId_e +{ + SSID = 0, + SUPPORTED_RATES = 1, + + FH_PARAM_SET = 2, + DS_PARAM_SET = 3, + CF_PARAM_SET = 4, + + IBSS_PARAM_SET = 6, + +#ifdef STA_SUPPORT + COUNTRY_INFO = 7, +#endif /* STA_SUPPORT */ + + POWER_CONSTRAINT = 32, + POWER_CAPABILITY = 33, + TPC_REQUEST = 34, + TPC_REPORT = 35, + SUPPORTED_CHANNELS = 36, + CHANNEL_SWITCH_ANN = 37, + QUIET = 40, + IBSS_DFS = 41, + HT_CAPABILITY = 45, + HT_OPERATION = 61, + BSSCO_2040 = 72, + OVERLAPBSSSCANPARAM = 74, + EXT_CAPABILITY = 127, + + ERP_INFO = 42, + + EXTENDED_SUPPORTED_RATES = 50, + + VENDOR_SPECIFIC_221 = 221, + WMM_IE = VENDOR_SPECIFIC_221, + + WPS_IE = VENDOR_SPECIFIC_221, + + WPA_IE = VENDOR_SPECIFIC_221, + RSN_IE = 48, + VS_IE = VENDOR_SPECIFIC_221, + WAPI_IE = 68, +} MLAN_PACK_END IEEEtypes_ElementId_e; + +/** IEEE IE header */ +typedef MLAN_PACK_START struct _IEEEtypes_Header_t +{ + /** Element ID */ + t_u8 element_id; + /** Length */ + t_u8 len; +} MLAN_PACK_END IEEEtypes_Header_t, *pIEEEtypes_Header_t; + +/** Vendor specific IE header */ +typedef MLAN_PACK_START struct _IEEEtypes_VendorHeader_t +{ + /** Element ID */ + t_u8 element_id; + /** Length */ + t_u8 len; + /** OUI */ + t_u8 oui[3]; + /** OUI type */ + t_u8 oui_type; + /** OUI subtype */ + t_u8 oui_subtype; + /** Version */ + t_u8 version; +} MLAN_PACK_END IEEEtypes_VendorHeader_t, *pIEEEtypes_VendorHeader_t; + +/** Vendor specific IE */ +typedef MLAN_PACK_START struct _IEEEtypes_VendorSpecific_t +{ + /** Vendor specific IE header */ + IEEEtypes_VendorHeader_t vend_hdr; + /** IE Max - size of previous fields */ + t_u8 data[IEEE_MAX_IE_SIZE - sizeof(IEEEtypes_VendorHeader_t)]; +} +MLAN_PACK_END IEEEtypes_VendorSpecific_t, *pIEEEtypes_VendorSpecific_t; + +/** IEEE IE */ +typedef MLAN_PACK_START struct _IEEEtypes_Generic_t +{ + /** Generic IE header */ + IEEEtypes_Header_t ieee_hdr; + /** IE Max - size of previous fields */ + t_u8 data[IEEE_MAX_IE_SIZE - sizeof(IEEEtypes_Header_t)]; +} +MLAN_PACK_END IEEEtypes_Generic_t, *pIEEEtypes_Generic_t; + +/** Capability information mask */ +#define CAPINFO_MASK (~(MBIT(15) | MBIT(14) | \ + MBIT(12) | MBIT(11) | MBIT(9))) + +/** Capability Bit Map*/ +#ifdef BIG_ENDIAN_SUPPORT +typedef MLAN_PACK_START struct _IEEEtypes_CapInfo_t +{ + t_u8 rsrvd1:2; + t_u8 dsss_ofdm:1; + t_u8 rsvrd2:2; + t_u8 short_slot_time:1; + t_u8 rsrvd3:1; + t_u8 spectrum_mgmt:1; + t_u8 chan_agility:1; + t_u8 pbcc:1; + t_u8 short_preamble:1; + t_u8 privacy:1; + t_u8 cf_poll_rqst:1; + t_u8 cf_pollable:1; + t_u8 ibss:1; + t_u8 ess:1; +} MLAN_PACK_END IEEEtypes_CapInfo_t, *pIEEEtypes_CapInfo_t; +#else +typedef MLAN_PACK_START struct _IEEEtypes_CapInfo_t +{ + /** Capability Bit Map : ESS */ + t_u8 ess:1; + /** Capability Bit Map : IBSS */ + t_u8 ibss:1; + /** Capability Bit Map : CF pollable */ + t_u8 cf_pollable:1; + /** Capability Bit Map : CF poll request */ + t_u8 cf_poll_rqst:1; + /** Capability Bit Map : privacy */ + t_u8 privacy:1; + /** Capability Bit Map : Short preamble */ + t_u8 short_preamble:1; + /** Capability Bit Map : PBCC */ + t_u8 pbcc:1; + /** Capability Bit Map : Channel agility */ + t_u8 chan_agility:1; + /** Capability Bit Map : Spectrum management */ + t_u8 spectrum_mgmt:1; + /** Capability Bit Map : Reserved */ + t_u8 rsrvd3:1; + /** Capability Bit Map : Short slot time */ + t_u8 short_slot_time:1; + /** Capability Bit Map : APSD */ + t_u8 Apsd:1; + /** Capability Bit Map : Reserved */ + t_u8 rsvrd2:1; + /** Capability Bit Map : DSS OFDM */ + t_u8 dsss_ofdm:1; + /** Capability Bit Map : Reserved */ + t_u8 rsrvd1:2; +} MLAN_PACK_END IEEEtypes_CapInfo_t, *pIEEEtypes_CapInfo_t; +#endif /* BIG_ENDIAN_SUPPORT */ + +/** IEEEtypes_CfParamSet_t */ +typedef MLAN_PACK_START struct _IEEEtypes_CfParamSet_t +{ + /** CF peremeter : Element ID */ + t_u8 element_id; + /** CF peremeter : Length */ + t_u8 len; + /** CF peremeter : Count */ + t_u8 cfp_cnt; + /** CF peremeter : Period */ + t_u8 cfp_period; + /** CF peremeter : Maximum duration */ + t_u16 cfp_max_duration; + /** CF peremeter : Remaining duration */ + t_u16 cfp_duration_remaining; +} MLAN_PACK_END IEEEtypes_CfParamSet_t, *pIEEEtypes_CfParamSet_t; + +/** IEEEtypes_IbssParamSet_t */ +typedef MLAN_PACK_START struct _IEEEtypes_IbssParamSet_t +{ + /** Element ID */ + t_u8 element_id; + /** Length */ + t_u8 len; + /** ATIM window value in milliseconds */ + t_u16 atim_window; +} MLAN_PACK_END IEEEtypes_IbssParamSet_t, *pIEEEtypes_IbssParamSet_t; + +/** IEEEtypes_SsParamSet_t */ +typedef MLAN_PACK_START union _IEEEtypes_SsParamSet_t +{ + /** SS parameter : CF parameter set */ + IEEEtypes_CfParamSet_t cf_param_set; + /** SS parameter : IBSS parameter set */ + IEEEtypes_IbssParamSet_t ibss_param_set; +} MLAN_PACK_END IEEEtypes_SsParamSet_t, *pIEEEtypes_SsParamSet_t; + +/** IEEEtypes_FhParamSet_t */ +typedef MLAN_PACK_START struct _IEEEtypes_FhParamSet_t +{ + /** FH parameter : Element ID */ + t_u8 element_id; + /** FH parameter : Length */ + t_u8 len; + /** FH parameter : Dwell time in milliseconds */ + t_u16 dwell_time; + /** FH parameter : Hop set */ + t_u8 hop_set; + /** FH parameter : Hop pattern */ + t_u8 hop_pattern; + /** FH parameter : Hop index */ + t_u8 hop_index; +} MLAN_PACK_END IEEEtypes_FhParamSet_t, *pIEEEtypes_FhParamSet_t; + +/** IEEEtypes_DsParamSet_t */ +typedef MLAN_PACK_START struct _IEEEtypes_DsParamSet_t +{ + /** DS parameter : Element ID */ + t_u8 element_id; + /** DS parameter : Length */ + t_u8 len; + /** DS parameter : Current channel */ + t_u8 current_chan; +} MLAN_PACK_END IEEEtypes_DsParamSet_t, *pIEEEtypes_DsParamSet_t; + +/** IEEEtypes_PhyParamSet_t */ +typedef MLAN_PACK_START union _IEEEtypes_PhyParamSet_t +{ + /** FH parameter set */ + IEEEtypes_FhParamSet_t fh_param_set; + /** DS parameter set */ + IEEEtypes_DsParamSet_t ds_param_set; +} MLAN_PACK_END IEEEtypes_PhyParamSet_t, *pIEEEtypes_PhyParamSet_t; + +/** IEEEtypes_ERPInfo_t */ +typedef MLAN_PACK_START struct _IEEEtypes_ERPInfo_t +{ + /** Element ID */ + t_u8 element_id; + /** Length */ + t_u8 len; + /** ERP flags */ + t_u8 erp_flags; +} MLAN_PACK_END IEEEtypes_ERPInfo_t, *pIEEEtypes_ERPInfo_t; + +/** IEEEtypes_AId_t */ +typedef t_u16 IEEEtypes_AId_t; + +/** IEEEtypes_StatusCode_t */ +typedef t_u16 IEEEtypes_StatusCode_t; + +/** IEEEtypes_AssocRsp_t */ +typedef MLAN_PACK_START struct _IEEEtypes_AssocRsp_t +{ + /** Capability information */ + IEEEtypes_CapInfo_t capability; + /** Association response status code */ + IEEEtypes_StatusCode_t status_code; + /** Association ID */ + IEEEtypes_AId_t a_id; + /** IE data buffer */ + t_u8 ie_buffer[1]; +} MLAN_PACK_END IEEEtypes_AssocRsp_t, *pIEEEtypes_AssocRsp_t; + +/** 802.11 supported rates */ +typedef t_u8 WLAN_802_11_RATES[WLAN_SUPPORTED_RATES]; + +/** cipher TKIP */ +#define WPA_CIPHER_TKIP 2 +/** cipher AES */ +#define WPA_CIPHER_AES_CCM 4 +/** AKM: 8021x */ +#define RSN_AKM_8021X 1 +/** AKM: PSK */ +#define RSN_AKM_PSK 2 + +/** wpa_suite_t */ +typedef MLAN_PACK_START struct _wpa_suite_t +{ + /** OUI */ + t_u8 oui[3]; + /** tyep */ + t_u8 type; +} MLAN_PACK_END wpa_suite, wpa_suite_mcast_t; + +/** wpa_suite_ucast_t */ +typedef MLAN_PACK_START struct +{ + /* count */ + t_u16 count; + /** wpa_suite list */ + wpa_suite list[1]; +} MLAN_PACK_END wpa_suite_ucast_t, wpa_suite_auth_key_mgmt_t; + +/** IEEEtypes_Rsn_t */ +typedef MLAN_PACK_START struct _IEEEtypes_Rsn_t +{ + /** Rsn : Element ID */ + t_u8 element_id; + /** Rsn : Length */ + t_u8 len; + /** Rsn : version */ + t_u16 version; + /** Rsn : group cipher */ + wpa_suite_mcast_t group_cipher; + /** Rsn : pairwise cipher */ + wpa_suite_ucast_t pairwise_cipher; +} MLAN_PACK_END IEEEtypes_Rsn_t, *pIEEEtypes_Rsn_t; + +/** IEEEtypes_Wpa_t */ +typedef MLAN_PACK_START struct _IEEEtypes_Wpa_t +{ + /** Wpa : Element ID */ + t_u8 element_id; + /** Wpa : Length */ + t_u8 len; + /** Wpa : oui */ + t_u8 oui[4]; + /** version */ + t_u16 version; + /** Wpa : group cipher */ + wpa_suite_mcast_t group_cipher; + /** Wpa : pairwise cipher */ + wpa_suite_ucast_t pairwise_cipher; +} MLAN_PACK_END IEEEtypes_Wpa_t, *pIEEEtypes_Wpa_t; + +/** Maximum number of AC QOS queues available in the driver/firmware */ +#define MAX_AC_QUEUES 4 + +/** Data structure of WMM QoS information */ +typedef MLAN_PACK_START struct _IEEEtypes_WmmQosInfo_t +{ +#ifdef BIG_ENDIAN_SUPPORT + /** QoS UAPSD */ + t_u8 qos_uapsd:1; + /** Reserved */ + t_u8 reserved:3; + /** Parameter set count */ + t_u8 para_set_count:4; +#else + /** Parameter set count */ + t_u8 para_set_count:4; + /** Reserved */ + t_u8 reserved:3; + /** QoS UAPSD */ + t_u8 qos_uapsd:1; +#endif /* BIG_ENDIAN_SUPPORT */ +} MLAN_PACK_END IEEEtypes_WmmQosInfo_t, *pIEEEtypes_WmmQosInfo_t; + +/** Data structure of WMM Aci/Aifsn */ +typedef MLAN_PACK_START struct _IEEEtypes_WmmAciAifsn_t +{ +#ifdef BIG_ENDIAN_SUPPORT + /** Reserved */ + t_u8 reserved:1; + /** Aci */ + t_u8 aci:2; + /** Acm */ + t_u8 acm:1; + /** Aifsn */ + t_u8 aifsn:4; +#else + /** Aifsn */ + t_u8 aifsn:4; + /** Acm */ + t_u8 acm:1; + /** Aci */ + t_u8 aci:2; + /** Reserved */ + t_u8 reserved:1; +#endif /* BIG_ENDIAN_SUPPORT */ +} MLAN_PACK_END IEEEtypes_WmmAciAifsn_t, *pIEEEtypes_WmmAciAifsn_t; + +/** Data structure of WMM ECW */ +typedef MLAN_PACK_START struct _IEEEtypes_WmmEcw_t +{ +#ifdef BIG_ENDIAN_SUPPORT + /** Maximum Ecw */ + t_u8 ecw_max:4; + /** Minimum Ecw */ + t_u8 ecw_min:4; +#else + /** Minimum Ecw */ + t_u8 ecw_min:4; + /** Maximum Ecw */ + t_u8 ecw_max:4; +#endif /* BIG_ENDIAN_SUPPORT */ +} MLAN_PACK_END IEEEtypes_WmmEcw_t, *pIEEEtypes_WmmEcw_t; + +/** Data structure of WMM AC parameters */ +typedef MLAN_PACK_START struct _IEEEtypes_WmmAcParameters_t +{ + IEEEtypes_WmmAciAifsn_t aci_aifsn; /**< AciAifSn */ + IEEEtypes_WmmEcw_t ecw; /**< Ecw */ + t_u16 tx_op_limit; /**< Tx op limit */ +} MLAN_PACK_END IEEEtypes_WmmAcParameters_t, *pIEEEtypes_WmmAcParameters_t; + +/** Data structure of WMM Info IE */ +typedef MLAN_PACK_START struct _IEEEtypes_WmmInfo_t +{ + + /** + * WMM Info IE - Vendor Specific Header: + * element_id [221/0xdd] + * Len [7] + * Oui [00:50:f2] + * OuiType [2] + * OuiSubType [0] + * Version [1] + */ + IEEEtypes_VendorHeader_t vend_hdr; + + /** QoS information */ + IEEEtypes_WmmQosInfo_t qos_info; + +} MLAN_PACK_END IEEEtypes_WmmInfo_t, *pIEEEtypes_WmmInfo_t; + +/** Data structure of WMM parameter IE */ +typedef MLAN_PACK_START struct _IEEEtypes_WmmParameter_t +{ + /** + * WMM Parameter IE - Vendor Specific Header: + * element_id [221/0xdd] + * Len [24] + * Oui [00:50:f2] + * OuiType [2] + * OuiSubType [1] + * Version [1] + */ + IEEEtypes_VendorHeader_t vend_hdr; + + /** QoS information */ + IEEEtypes_WmmQosInfo_t qos_info; + /** Reserved */ + t_u8 reserved; + + /** AC Parameters Record WMM_AC_BE, WMM_AC_BK, WMM_AC_VI, WMM_AC_VO */ + IEEEtypes_WmmAcParameters_t ac_params[MAX_AC_QUEUES]; +} MLAN_PACK_END IEEEtypes_WmmParameter_t, *pIEEEtypes_WmmParameter_t; + +/** Enumerator for TSPEC direction */ +typedef MLAN_PACK_START enum _IEEEtypes_WMM_TSPEC_TS_Info_Direction_e +{ + + TSPEC_DIR_UPLINK = 0, + TSPEC_DIR_DOWNLINK = 1, + /* 2 is a reserved value */ + TSPEC_DIR_BIDIRECT = 3, + +} MLAN_PACK_END IEEEtypes_WMM_TSPEC_TS_Info_Direction_e; + +/** Enumerator for TSPEC PSB */ +typedef MLAN_PACK_START enum _IEEEtypes_WMM_TSPEC_TS_Info_PSB_e +{ + + TSPEC_PSB_LEGACY = 0, + TSPEC_PSB_TRIG = 1, + +} MLAN_PACK_END IEEEtypes_WMM_TSPEC_TS_Info_PSB_e; + +/** Enumerator for TSPEC Ack Policy */ +typedef MLAN_PACK_START enum _IEEEtypes_WMM_TSPEC_TS_Info_AckPolicy_e +{ + + TSPEC_ACKPOLICY_NORMAL = 0, + TSPEC_ACKPOLICY_NOACK = 1, + /* 2 is reserved */ + TSPEC_ACKPOLICY_BLOCKACK = 3, + +} MLAN_PACK_END IEEEtypes_WMM_TSPEC_TS_Info_AckPolicy_e; + +/** Enumerator for TSPEC Trafffice type */ +typedef MLAN_PACK_START enum _IEEEtypes_WMM_TSPEC_TS_TRAFFIC_TYPE_e +{ + + TSPEC_TRAFFIC_APERIODIC = 0, + TSPEC_TRAFFIC_PERIODIC = 1, + +} MLAN_PACK_END IEEEtypes_WMM_TSPEC_TS_TRAFFIC_TYPE_e; + +/** Data structure of WMM TSPEC information */ +typedef MLAN_PACK_START struct +{ +#ifdef BIG_ENDIAN_SUPPORT + t_u8 Reserved17_23:7; // ! Reserved + t_u8 Schedule:1; + IEEEtypes_WMM_TSPEC_TS_Info_AckPolicy_e AckPolicy:2; + t_u8 UserPri:3; // ! 802.1d User Priority + IEEEtypes_WMM_TSPEC_TS_Info_PSB_e PowerSaveBehavior:1; // ! + // Legacy/Trigg + t_u8 Aggregation:1; // ! Reserved + t_u8 AccessPolicy2:1; // ! + t_u8 AccessPolicy1:1; // ! + IEEEtypes_WMM_TSPEC_TS_Info_Direction_e Direction:2; + t_u8 TID:4; // ! Unique identifier + IEEEtypes_WMM_TSPEC_TS_TRAFFIC_TYPE_e TrafficType:1; +#else + IEEEtypes_WMM_TSPEC_TS_TRAFFIC_TYPE_e TrafficType:1; + t_u8 TID:4; // ! Unique identifier + IEEEtypes_WMM_TSPEC_TS_Info_Direction_e Direction:2; + t_u8 AccessPolicy1:1; // ! + t_u8 AccessPolicy2:1; // ! + t_u8 Aggregation:1; // ! Reserved + IEEEtypes_WMM_TSPEC_TS_Info_PSB_e PowerSaveBehavior:1; // ! + // Legacy/Trigg + t_u8 UserPri:3; // ! 802.1d User Priority + IEEEtypes_WMM_TSPEC_TS_Info_AckPolicy_e AckPolicy:2; + t_u8 Schedule:1; + t_u8 Reserved17_23:7; // ! Reserved +#endif +} MLAN_PACK_END IEEEtypes_WMM_TSPEC_TS_Info_t; + +/** Data structure of WMM TSPEC Nominal Size */ +typedef MLAN_PACK_START struct +{ +#ifdef BIG_ENDIAN_SUPPORT + t_u16 Fixed:1; // ! 1: Fixed size given in Size, 0: Var, size + // is nominal + t_u16 Size:15; // ! Nominal size in octets +#else + t_u16 Size:15; // ! Nominal size in octets + t_u16 Fixed:1; // ! 1: Fixed size given in Size, 0: Var, size + // is nominal +#endif +} MLAN_PACK_END IEEEtypes_WMM_TSPEC_NomMSDUSize_t; + +/** Data structure of WMM TSPEC SBWA */ +typedef MLAN_PACK_START struct +{ +#ifdef BIG_ENDIAN_SUPPORT + t_u16 Whole:3; // ! Whole portion + t_u16 Fractional:13; // ! Fractional portion +#else + t_u16 Fractional:13; // ! Fractional portion + t_u16 Whole:3; // ! Whole portion +#endif +} MLAN_PACK_END IEEEtypes_WMM_TSPEC_SBWA; + +/** Data structure of WMM TSPEC Body */ +typedef MLAN_PACK_START struct +{ + + IEEEtypes_WMM_TSPEC_TS_Info_t TSInfo; + IEEEtypes_WMM_TSPEC_NomMSDUSize_t NomMSDUSize; + t_u16 MaximumMSDUSize; + t_u32 MinServiceInterval; + t_u32 MaxServiceInterval; + t_u32 InactivityInterval; + t_u32 SuspensionInterval; + t_u32 ServiceStartTime; + t_u32 MinimumDataRate; + t_u32 MeanDataRate; + t_u32 PeakDataRate; + t_u32 MaxBurstSize; + t_u32 DelayBound; + t_u32 MinPHYRate; + IEEEtypes_WMM_TSPEC_SBWA SurplusBWAllowance; + t_u16 MediumTime; +} MLAN_PACK_END IEEEtypes_WMM_TSPEC_Body_t; + +/** Data structure of WMM TSPEC all elements */ +typedef MLAN_PACK_START struct +{ + t_u8 ElementId; + t_u8 Len; + t_u8 OuiType[4]; /* 00:50:f2:02 */ + t_u8 OuiSubType; /* 01 */ + t_u8 Version; + + IEEEtypes_WMM_TSPEC_Body_t TspecBody; + +} MLAN_PACK_END IEEEtypes_WMM_TSPEC_t; + +/** WMM Action Category values */ +typedef MLAN_PACK_START enum _IEEEtypes_ActionCategory_e +{ + + IEEE_MGMT_ACTION_CATEGORY_SPECTRUM_MGMT = 0, + IEEE_MGMT_ACTION_CATEGORY_QOS = 1, + IEEE_MGMT_ACTION_CATEGORY_DLS = 2, + IEEE_MGMT_ACTION_CATEGORY_BLOCK_ACK = 3, + IEEE_MGMT_ACTION_CATEGORY_PUBLIC = 4, + IEEE_MGMT_ACTION_CATEGORY_RADIO_RSRC = 5, + IEEE_MGMT_ACTION_CATEGORY_FAST_BSS_TRANS = 6, + IEEE_MGMT_ACTION_CATEGORY_HT = 7, + + IEEE_MGMT_ACTION_CATEGORY_WNM = 10, + IEEE_MGMT_ACTION_CATEGORY_UNPROTECT_WNM = 11, + + IEEE_MGMT_ACTION_CATEGORY_WMM_TSPEC = 17 +} MLAN_PACK_END IEEEtypes_ActionCategory_e; + +/** WMM TSPEC operations */ +typedef MLAN_PACK_START enum _IEEEtypes_WMM_Tspec_Action_e +{ + + TSPEC_ACTION_CODE_ADDTS_REQ = 0, + TSPEC_ACTION_CODE_ADDTS_RSP = 1, + TSPEC_ACTION_CODE_DELTS = 2, + +} MLAN_PACK_END IEEEtypes_WMM_Tspec_Action_e; + +/** WMM TSPEC Category Action Base */ +typedef MLAN_PACK_START struct +{ + + IEEEtypes_ActionCategory_e category; + IEEEtypes_WMM_Tspec_Action_e action; + t_u8 dialogToken; + +} MLAN_PACK_END IEEEtypes_WMM_Tspec_Action_Base_Tspec_t; + +/** WMM TSPEC AddTS request structure */ +typedef MLAN_PACK_START struct +{ + + IEEEtypes_WMM_Tspec_Action_Base_Tspec_t tspecAct; + t_u8 statusCode; + IEEEtypes_WMM_TSPEC_t tspecIE; + + /* Place holder for additional elements after the TSPEC */ + t_u8 subElem[256]; + +} MLAN_PACK_END IEEEtypes_Action_WMM_AddTsReq_t; + +/** WMM TSPEC AddTS response structure */ +typedef MLAN_PACK_START struct +{ + IEEEtypes_WMM_Tspec_Action_Base_Tspec_t tspecAct; + t_u8 statusCode; + IEEEtypes_WMM_TSPEC_t tspecIE; + + /* Place holder for additional elements after the TSPEC */ + t_u8 subElem[256]; + +} MLAN_PACK_END IEEEtypes_Action_WMM_AddTsRsp_t; + +/** WMM TSPEC DelTS structure */ +typedef MLAN_PACK_START struct +{ + IEEEtypes_WMM_Tspec_Action_Base_Tspec_t tspecAct; + t_u8 reasonCode; + IEEEtypes_WMM_TSPEC_t tspecIE; + +} MLAN_PACK_END IEEEtypes_Action_WMM_DelTs_t; + +/** union of WMM TSPEC structures */ +typedef MLAN_PACK_START union +{ + IEEEtypes_WMM_Tspec_Action_Base_Tspec_t tspecAct; + + IEEEtypes_Action_WMM_AddTsReq_t addTsReq; + IEEEtypes_Action_WMM_AddTsRsp_t addTsRsp; + IEEEtypes_Action_WMM_DelTs_t delTs; + +} MLAN_PACK_END IEEEtypes_Action_WMMAC_t; + +/** union of WMM TSPEC & Action category */ +typedef MLAN_PACK_START union +{ + IEEEtypes_ActionCategory_e category; + + IEEEtypes_Action_WMMAC_t wmmAc; + +} MLAN_PACK_END IEEEtypes_ActionFrame_t; + +/** Data structure for subband set */ +typedef MLAN_PACK_START struct _IEEEtypes_SubbandSet_t +{ + /** First channel */ + t_u8 first_chan; + /** Number of channels */ + t_u8 no_of_chan; + /** Maximum Tx power in dBm */ + t_u8 max_tx_pwr; +} MLAN_PACK_END IEEEtypes_SubbandSet_t, *pIEEEtypes_SubbandSet_t; + +#ifdef STA_SUPPORT +/** Data structure for Country IE */ +typedef MLAN_PACK_START struct _IEEEtypes_CountryInfoSet_t +{ + /** Element ID */ + t_u8 element_id; + /** Length */ + t_u8 len; + /** Country code */ + t_u8 country_code[COUNTRY_CODE_LEN]; + /** Set of subbands */ + IEEEtypes_SubbandSet_t sub_band[1]; +} MLAN_PACK_END IEEEtypes_CountryInfoSet_t, *pIEEEtypes_CountryInfoSet_t; + +/** Data structure for Country IE full set */ +typedef MLAN_PACK_START struct _IEEEtypes_CountryInfoFullSet_t +{ + /** Element ID */ + t_u8 element_id; + /** Length */ + t_u8 len; + /** Country code */ + t_u8 country_code[COUNTRY_CODE_LEN]; + /** Set of subbands */ + IEEEtypes_SubbandSet_t sub_band[MRVDRV_MAX_SUBBAND_802_11D]; +} MLAN_PACK_END IEEEtypes_CountryInfoFullSet_t, + *pIEEEtypes_CountryInfoFullSet_t; + +#endif /* STA_SUPPORT */ + +/** HT Capabilities Data */ +typedef struct MLAN_PACK_START _HTCap_t +{ + /** HT Capabilities Info field */ + t_u16 ht_cap_info; + /** A-MPDU Parameters field */ + t_u8 ampdu_param; + /** Supported MCS Set field */ + t_u8 supported_mcs_set[16]; + /** HT Extended Capabilities field */ + t_u16 ht_ext_cap; + /** Transmit Beamforming Capabilities field */ + t_u32 tx_bf_cap; + /** Antenna Selection Capability field */ + t_u8 asel; +} MLAN_PACK_END HTCap_t, *pHTCap_t; + +/** HT Information Data */ +typedef struct MLAN_PACK_START _HTInfo_t +{ + /** Primary channel */ + t_u8 pri_chan; + /** Field 2 */ + t_u8 field2; + /** Field 3 */ + t_u16 field3; + /** Field 4 */ + t_u16 field4; + /** Bitmap indicating MCSs supported by all HT STAs in the BSS */ + t_u8 basic_mcs_set[16]; +} MLAN_PACK_END HTInfo_t, *pHTInfo_t; + +/** 20/40 BSS Coexistence Data */ +typedef struct MLAN_PACK_START _BSSCo2040_t +{ + /** 20/40 BSS Coexistence value */ + t_u8 bss_co_2040_value; +} MLAN_PACK_END BSSCo2040_t, *pBSSCo2040_t; + +/** Extended Capabilities Data */ +typedef struct MLAN_PACK_START _ExtCap_t +{ + /** Extended Capabilities value */ + t_u8 ext_cap_value; +} MLAN_PACK_END ExtCap_t, *pExtCap_t; + +/** Overlapping BSS Scan Parameters Data */ +typedef struct MLAN_PACK_START _OverlapBSSScanParam_t +{ + /** OBSS Scan Passive Dwell in milliseconds */ + t_u16 obss_scan_passive_dwell; + /** OBSS Scan Active Dwell in milliseconds */ + t_u16 obss_scan_active_dwell; + /** BSS Channel Width Trigger Scan Interval in seconds */ + t_u16 bss_chan_width_trigger_scan_int; + /** OBSS Scan Passive Total Per Channel */ + t_u16 obss_scan_passive_total; + /** OBSS Scan Active Total Per Channel */ + t_u16 obss_scan_active_total; + /** BSS Width Channel Transition Delay Factor */ + t_u16 bss_width_chan_trans_delay; + /** OBSS Scan Activity Threshold */ + t_u16 obss_scan_active_threshold; +} MLAN_PACK_END OBSSScanParam_t, *pOBSSScanParam_t; + +/** HT Capabilities IE */ +typedef MLAN_PACK_START struct _IEEEtypes_HTCap_t +{ + /** Generic IE header */ + IEEEtypes_Header_t ieee_hdr; + /** HTCap struct */ + HTCap_t ht_cap; +} MLAN_PACK_END IEEEtypes_HTCap_t, *pIEEEtypes_HTCap_t; + +/** HT Information IE */ +typedef MLAN_PACK_START struct _IEEEtypes_HTInfo_t +{ + /** Generic IE header */ + IEEEtypes_Header_t ieee_hdr; + /** HTInfo struct */ + HTInfo_t ht_info; +} MLAN_PACK_END IEEEtypes_HTInfo_t, *pIEEEtypes_HTInfo_t; + +/** 20/40 BSS Coexistence IE */ +typedef MLAN_PACK_START struct _IEEEtypes_2040BSSCo_t +{ + /** Generic IE header */ + IEEEtypes_Header_t ieee_hdr; + /** BSSCo2040_t struct */ + BSSCo2040_t bss_co_2040; +} MLAN_PACK_END IEEEtypes_2040BSSCo_t, *pIEEEtypes_2040BSSCo_t; + +/** Extended Capabilities IE */ +typedef MLAN_PACK_START struct _IEEEtypes_ExtCap_t +{ + /** Generic IE header */ + IEEEtypes_Header_t ieee_hdr; + /** ExtCap_t struct */ + ExtCap_t ext_cap; +} MLAN_PACK_END IEEEtypes_ExtCap_t, *pIEEEtypes_ExtCap_t; + +/** Overlapping BSS Scan Parameters IE */ +typedef MLAN_PACK_START struct _IEEEtypes_OverlapBSSScanParam_t +{ + /** Generic IE header */ + IEEEtypes_Header_t ieee_hdr; + /** OBSSScanParam_t struct */ + OBSSScanParam_t obss_scan_param; +} MLAN_PACK_END IEEEtypes_OverlapBSSScanParam_t, + *pIEEEtypes_OverlapBSSScanParam_t; + +/** Maximum number of subbands in the IEEEtypes_SupportedChannels_t structure */ +#define WLAN_11H_MAX_SUBBANDS 5 + +/** Maximum number of DFS channels configured in IEEEtypes_IBSS_DFS_t */ +#define WLAN_11H_MAX_IBSS_DFS_CHANNELS 25 + +/** IEEE Power Constraint element (7.3.2.15) */ +typedef MLAN_PACK_START struct +{ + t_u8 element_id; /**< IEEE Element ID = 32 */ + t_u8 len; /**< Element length after id and len */ + t_u8 local_constraint; /**< Local power constraint applied to 11d chan info */ +} MLAN_PACK_END IEEEtypes_PowerConstraint_t; + +/** IEEE Power Capability element (7.3.2.16) */ +typedef MLAN_PACK_START struct +{ + t_u8 element_id; /**< IEEE Element ID = 33 */ + t_u8 len; /**< Element length after id and len */ + t_s8 min_tx_power_capability; /**< Minimum Transmit power (dBm) */ + t_s8 max_tx_power_capability; /**< Maximum Transmit power (dBm) */ +} MLAN_PACK_END IEEEtypes_PowerCapability_t; + +/** IEEE TPC Report element (7.3.2.18) */ +typedef MLAN_PACK_START struct +{ + t_u8 element_id; /**< IEEE Element ID = 35 */ + t_u8 len; /**< Element length after id and len */ + t_s8 tx_power; /**< Max power used to transmit the TPC Report frame (dBm) */ + t_s8 link_margin; /**< Link margin when TPC Request received (dB) */ +} MLAN_PACK_END IEEEtypes_TPCReport_t; + +/* IEEE Supported Channel sub-band description (7.3.2.19) */ +/** + * Sub-band description used in the supported channels element. + */ +typedef MLAN_PACK_START struct +{ + t_u8 start_chan; /**< Starting channel in the subband */ + t_u8 num_chans; /**< Number of channels in the subband */ + +} MLAN_PACK_END IEEEtypes_SupportChan_Subband_t; + +/* IEEE Supported Channel element (7.3.2.19) */ +/** + * Sent in association requests. Details the sub-bands and number + * of channels supported in each subband + */ +typedef MLAN_PACK_START struct +{ + t_u8 element_id; /**< IEEE Element ID = 36 */ + t_u8 len; /**< Element length after id and len */ + + /** Configured sub-bands information in the element */ + IEEEtypes_SupportChan_Subband_t subband[WLAN_11H_MAX_SUBBANDS]; + +} MLAN_PACK_END IEEEtypes_SupportedChannels_t; + +/* IEEE Channel Switch Announcement Element (7.3.2.20) */ +/** + * Provided in beacons and probe responses. Used to advertise when + * and to which channel it is changing to. Only starting STAs in + * an IBSS and APs are allowed to originate a chan switch element. + */ +typedef MLAN_PACK_START struct +{ + t_u8 element_id; /**< IEEE Element ID = 37 */ + t_u8 len; /**< Element length after id and len */ + t_u8 chan_switch_mode; /**< STA should not transmit any frames if 1 */ + t_u8 new_channel_num; /**< Channel # that AP/IBSS is moving to */ + t_u8 chan_switch_count; /**< # of TBTTs before channel switch */ + +} MLAN_PACK_END IEEEtypes_ChanSwitchAnn_t; + +/* IEEE Quiet Period Element (7.3.2.23) */ +/** + * Provided in beacons and probe responses. Indicates times during + * which the STA should not be transmitting data. Only starting STAs in + * an IBSS and APs are allowed to originate a quiet element. + */ +typedef MLAN_PACK_START struct +{ + t_u8 element_id; /**< IEEE Element ID = 40 */ + t_u8 len; /**< Element length after id and len */ + t_u8 quiet_count; /**< Number of TBTTs until beacon with the quiet period */ + t_u8 quiet_period; /**< Regular quiet period, # of TBTTS between periods */ + t_u16 quiet_duration; /**< Duration of the quiet period in TUs */ + t_u16 quiet_offset; /**< Offset in TUs from the TBTT for the quiet period */ + +} MLAN_PACK_END IEEEtypes_Quiet_t; + +/** +*** @brief Map octet of the basic measurement report (7.3.2.22.1) +**/ +typedef MLAN_PACK_START struct +{ +#ifdef BIG_ENDIAN_SUPPORT + t_u8 rsvd5_7:3; /**< Reserved */ + t_u8 unmeasured:1; /**< Channel is unmeasured */ + t_u8 radar:1; /**< Radar detected on channel */ + t_u8 unidentified_sig:1; /**< Unidentified signal found on channel */ + t_u8 ofdm_preamble:1; /**< OFDM preamble detected on channel */ + t_u8 bss:1; /**< At least one valid MPDU received on channel */ +#else + t_u8 bss:1; /**< At least one valid MPDU received on channel */ + t_u8 ofdm_preamble:1; /**< OFDM preamble detected on channel */ + t_u8 unidentified_sig:1; /**< Unidentified signal found on channel */ + t_u8 radar:1; /**< Radar detected on channel */ + t_u8 unmeasured:1; /**< Channel is unmeasured */ + t_u8 rsvd5_7:3; /**< Reserved */ +#endif /* BIG_ENDIAN_SUPPORT */ + +} MLAN_PACK_END MeasRptBasicMap_t; + +/* IEEE DFS Channel Map field (7.3.2.24) */ +/** + * Used to list supported channels and provide a octet "map" field which + * contains a basic measurement report for that channel in the + * IEEEtypes_IBSS_DFS_t element + */ +typedef MLAN_PACK_START struct +{ + t_u8 channel_number; /**< Channel number */ + MeasRptBasicMap_t rpt_map; /**< Basic measurement report for the channel */ + +} MLAN_PACK_END IEEEtypes_ChannelMap_t; + +/* IEEE IBSS DFS Element (7.3.2.24) */ +/** + * IBSS DFS element included in ad hoc beacons and probe responses. + * Provides information regarding the IBSS DFS Owner as well as the + * originating STAs supported channels and basic measurement results. + */ +typedef MLAN_PACK_START struct +{ + t_u8 element_id; /**< IEEE Element ID = 41 */ + t_u8 len; /**< Element length after id and len */ + t_u8 dfs_owner[MLAN_MAC_ADDR_LENGTH]; /**< DFS Owner STA Address */ + t_u8 dfs_recovery_interval; /**< DFS Recovery time in TBTTs */ + + /** Variable length map field, one Map entry for each supported channel */ + IEEEtypes_ChannelMap_t channel_map[WLAN_11H_MAX_IBSS_DFS_CHANNELS]; + +} MLAN_PACK_END IEEEtypes_IBSS_DFS_t; + +/* 802.11h BSS information kept for each BSSID received in scan results */ +/** + * IEEE BSS information needed from scan results for later processing in + * join commands + */ +typedef struct +{ + t_u8 sensed_11h; /**< Capability bit set or 11h IE found in this BSS */ + + IEEEtypes_PowerConstraint_t power_constraint; /**< Power Constraint IE */ + IEEEtypes_PowerCapability_t power_capability; /**< Power Capability IE */ + IEEEtypes_TPCReport_t tpc_report; /**< TPC Report IE */ + IEEEtypes_ChanSwitchAnn_t chan_switch_ann; /**< Channel Switch Announcement IE */ + IEEEtypes_Quiet_t quiet; /**< Quiet IE */ + IEEEtypes_IBSS_DFS_t ibss_dfs; /**< IBSS DFS Element IE */ + +} wlan_11h_bss_info_t; + +#ifdef STA_SUPPORT +/** Macro for maximum size of scan response buffer */ +#define MAX_SCAN_RSP_BUF (16 * 1024) + +/** Maximum number of channels that can be sent in user scan config */ +#define WLAN_USER_SCAN_CHAN_MAX 50 + +/** Maximum length of SSID list */ +#define MRVDRV_MAX_SSID_LIST_LENGTH 10 + +/** Scan all the channels in specified band */ +#define BAND_SPECIFIED 0x80 + +/** + * IOCTL SSID List sub-structure sent in wlan_ioctl_user_scan_cfg + * + * Used to specify SSID specific filters as well as SSID pattern matching + * filters for scan result processing in firmware. + */ +typedef MLAN_PACK_START struct _wlan_user_scan_ssid +{ + /** SSID */ + t_u8 ssid[MLAN_MAX_SSID_LENGTH + 1]; + /** Maximum length of SSID */ + t_u8 max_len; +} MLAN_PACK_END wlan_user_scan_ssid; + +/** + * @brief IOCTL channel sub-structure sent in wlan_ioctl_user_scan_cfg + * + * Multiple instances of this structure are included in the IOCTL command + * to configure a instance of a scan on the specific channel. + */ +typedef MLAN_PACK_START struct _wlan_user_scan_chan +{ + /** Channel Number to scan */ + t_u8 chan_number; + /** Radio type: 'B/G' Band = 0, 'A' Band = 1 */ + t_u8 radio_type; + /** Scan type: Active = 1, Passive = 2 */ + t_u8 scan_type; + /** Reserved */ + t_u8 reserved; + /** Scan duration in milliseconds; if 0 default used */ + t_u32 scan_time; +} MLAN_PACK_END wlan_user_scan_chan; + +/** + * Input structure to configure an immediate scan cmd to firmware + * + * Specifies a number of parameters to be used in general for the scan + * as well as a channel list (wlan_user_scan_chan) for each scan period + * desired. + */ +typedef MLAN_PACK_START struct +{ + /** + * Flag set to keep the previous scan table intact + * + * If set, the scan results will accumulate, replacing any previous + * matched entries for a BSS with the new scan data + */ + t_u8 keep_previous_scan; + /** + * BSS mode to be sent in the firmware command + * + * Field can be used to restrict the types of networks returned in the + * scan. Valid settings are: + * + * - MLAN_SCAN_MODE_BSS (infrastructure) + * - MLAN_SCAN_MODE_IBSS (adhoc) + * - MLAN_SCAN_MODE_ANY (unrestricted, adhoc and infrastructure) + */ + t_u8 bss_mode; + /** + * Configure the number of probe requests for active chan scans + */ + t_u8 num_probes; + /** + * @brief Reserved + */ + t_u8 reserved; + /** + * @brief BSSID filter sent in the firmware command to limit the results + */ + t_u8 specific_bssid[MLAN_MAC_ADDR_LENGTH]; + /** + * SSID filter list used in the to limit the scan results + */ + wlan_user_scan_ssid ssid_list[MRVDRV_MAX_SSID_LIST_LENGTH]; + /** + * Variable number (fixed maximum) of channels to scan up + */ + wlan_user_scan_chan chan_list[WLAN_USER_SCAN_CHAN_MAX]; +} MLAN_PACK_END wlan_user_scan_cfg; + +/** Default scan interval in millisecond*/ +#define DEFAULT_BGSCAN_INTERVAL 30000 + +/** action get all, except pps/uapsd config */ +#define BG_SCAN_ACT_GET 0x0000 +/** action set all, except pps/uapsd config */ +#define BG_SCAN_ACT_SET 0x0001 +/** action get pps/uapsd config */ +#define BG_SCAN_ACT_GET_PPS_UAPSD 0x0100 +/** action set pps/uapsd config */ +#define BG_SCAN_ACT_SET_PPS_UAPSD 0x0101 +/** action set all */ +#define BG_SCAN_ACT_SET_ALL 0xff01 +/** ssid match */ +#define BG_SCAN_SSID_MATCH 0x0001 +/** ssid match and RSSI exceeded */ +#define BG_SCAN_SSID_RSSI_MATCH 0x0004 +/** Maximum number of channels that can be sent in bg scan config */ +#define WLAN_BG_SCAN_CHAN_MAX 32 + +/** + * Input structure to configure bs scan cmd to firmware + */ +typedef MLAN_PACK_START struct +{ + /** action */ + t_u16 action; + /** enable/disable */ + t_u8 enable; + /** BSS type: + * MLAN_SCAN_MODE_BSS (infrastructure) + * MLAN_SCAN_MODE_IBSS (adhoc) + * MLAN_SCAN_MODE_ANY (unrestricted, adhoc and infrastructure) + */ + t_u8 bss_type; + /** number of channel scanned during each scan */ + t_u8 chan_per_scan; + /** interval between consecutive scan */ + t_u32 scan_interval; + /** bit 0: ssid match bit 1: ssid match and SNR exceeded + * bit 2: ssid match and RSSI exceeded + * bit 31: wait for all channel scan to complete to report scan result + */ + t_u32 report_condition; + /* Configure the number of probe requests for active chan scans */ + t_u8 num_probes; + /** RSSI threshold */ + t_u8 rssi_threshold; + /** SNR threshold */ + t_u8 snr_threshold; + /** repeat count */ + t_u16 repeat_count; + /** SSID filter list used in the to limit the scan results */ + wlan_user_scan_ssid ssid_list[MRVDRV_MAX_SSID_LIST_LENGTH]; + /** Variable number (fixed maximum) of channels to scan up */ + wlan_user_scan_chan chan_list[WLAN_BG_SCAN_CHAN_MAX]; +} MLAN_PACK_END wlan_bgscan_cfg; +#endif /* STA_SUPPORT */ + +#ifdef PRAGMA_PACK +#pragma pack(pop) +#endif + +/** BSSDescriptor_t + * Structure used to store information for beacon/probe response + */ +typedef struct _BSSDescriptor_t +{ + /** MAC address */ + mlan_802_11_mac_addr mac_address; + + /** SSID */ + mlan_802_11_ssid ssid; + + /** WEP encryption requirement */ + t_u32 privacy; + + /** Receive signal strength in dBm */ + t_s32 rssi; + + /** Channel */ + t_u32 channel; + + /** Freq */ + t_u32 freq; + + /** Beacon period */ + t_u16 beacon_period; + + /** ATIM window */ + t_u32 atim_window; + + /** ERP flags */ + t_u8 erp_flags; + + /** Type of network in use */ + WLAN_802_11_NETWORK_TYPE network_type_use; + + /** Network infrastructure mode */ + t_u32 bss_mode; + + /** Network supported rates */ + WLAN_802_11_RATES supported_rates; + + /** Supported data rates */ + t_u8 data_rates[WLAN_SUPPORTED_RATES]; + + /** Network band. + * BAND_B(0x01): 'b' band + * BAND_G(0x02): 'g' band + * BAND_A(0X04): 'a' band + */ + t_u16 bss_band; + + /** TSF timestamp from the current firmware TSF */ + t_u64 network_tsf; + + /** TSF value included in the beacon/probe response */ + t_u8 time_stamp[8]; + + /** PHY parameter set */ + IEEEtypes_PhyParamSet_t phy_param_set; + + /** SS parameter set */ + IEEEtypes_SsParamSet_t ss_param_set; + + /** Capability information */ + IEEEtypes_CapInfo_t cap_info; + + /** WMM IE */ + IEEEtypes_WmmParameter_t wmm_ie; + + /** 802.11h BSS information */ + wlan_11h_bss_info_t wlan_11h_bss_info; + + /** Indicate disabling 11n when associate with AP */ + t_u8 disable_11n; + /** 802.11n BSS information */ + /** HT Capabilities IE */ + IEEEtypes_HTCap_t *pht_cap; + /** HT Capabilities Offset */ + t_u16 ht_cap_offset; + /** HT Information IE */ + IEEEtypes_HTInfo_t *pht_info; + /** HT Information Offset */ + t_u16 ht_info_offset; + /** 20/40 BSS Coexistence IE */ + IEEEtypes_2040BSSCo_t *pbss_co_2040; + /** 20/40 BSS Coexistence Offset */ + t_u16 bss_co_2040_offset; + /** Extended Capabilities IE */ + IEEEtypes_ExtCap_t *pext_cap; + /** Extended Capabilities Offset */ + t_u16 ext_cap_offset; + /** Overlapping BSS Scan Parameters IE */ + IEEEtypes_OverlapBSSScanParam_t *poverlap_bss_scan_param; + /** Overlapping BSS Scan Parameters Offset */ + t_u16 overlap_bss_offset; + +#ifdef STA_SUPPORT + /** Country information set */ + IEEEtypes_CountryInfoFullSet_t country_info; +#endif /* STA_SUPPORT */ + + /** WPA IE */ + IEEEtypes_VendorSpecific_t *pwpa_ie; + /** WPA IE offset in the beacon buffer */ + t_u16 wpa_offset; + /** RSN IE */ + IEEEtypes_Generic_t *prsn_ie; + /** RSN IE offset in the beacon buffer */ + t_u16 rsn_offset; +#ifdef STA_SUPPORT + /** WAPI IE */ + IEEEtypes_Generic_t *pwapi_ie; + /** WAPI IE offset in the beacon buffer */ + t_u16 wapi_offset; +#endif + + /** Pointer to the returned scan response */ + t_u8 *pbeacon_buf; + /** Length of the stored scan response */ + t_u32 beacon_buf_size; + /** Max allocated size for updated scan response */ + t_u32 beacon_buf_size_max; + +} BSSDescriptor_t, *pBSSDescriptor_t; + +#endif /* !_MLAN_IEEE_H_ */ diff --git a/drivers/net/wireless/sd8797/mlinux/mlan_ioctl.h b/drivers/net/wireless/sd8797/mlinux/mlan_ioctl.h new file mode 100644 index 000000000000..964de9197ffe --- /dev/null +++ b/drivers/net/wireless/sd8797/mlinux/mlan_ioctl.h @@ -0,0 +1,2981 @@ +/** @file mlan_ioctl.h + * + * @brief This file declares the IOCTL data structures and APIs. + * + * Copyright (C) 2008-2011, Marvell International Ltd. + * + * This software file (the "File") is distributed by Marvell International + * Ltd. under the terms of the GNU General Public License Version 2, June 1991 + * (the "License"). You may use, redistribute and/or modify this File in + * accordance with the terms and conditions of the License, a copy of which + * is available by writing to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the + * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt. + * + * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE + * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE + * ARE EXPRESSLY DISCLAIMED. The License provides additional details about + * this warranty disclaimer. + */ + +/****************************************************** +Change log: + 11/07/2008: initial version +******************************************************/ + +#ifndef _MLAN_IOCTL_H_ +#define _MLAN_IOCTL_H_ + +/** Enumeration for IOCTL request ID */ +enum _mlan_ioctl_req_id +{ + /* Scan Group */ + MLAN_IOCTL_SCAN = 0x00010000, + MLAN_OID_SCAN_NORMAL, + MLAN_OID_SCAN_SPECIFIC_SSID, + MLAN_OID_SCAN_USER_CONFIG, + MLAN_OID_SCAN_CONFIG, + MLAN_OID_SCAN_GET_CURRENT_BSS, + MLAN_OID_SCAN_CANCEL, + MLAN_OID_SCAN_TABLE_FLUSH, + MLAN_OID_SCAN_BGSCAN_CONFIG, + /* BSS Configuration Group */ + MLAN_IOCTL_BSS = 0x00020000, + MLAN_OID_BSS_START, + MLAN_OID_BSS_STOP, + MLAN_OID_BSS_MODE, + MLAN_OID_BSS_CHANNEL, + MLAN_OID_BSS_CHANNEL_LIST, + MLAN_OID_BSS_MAC_ADDR, + MLAN_OID_BSS_MULTICAST_LIST, + MLAN_OID_BSS_FIND_BSS, + MLAN_OID_IBSS_BCN_INTERVAL, + MLAN_OID_IBSS_ATIM_WINDOW, + MLAN_OID_IBSS_CHANNEL, +#ifdef UAP_SUPPORT + MLAN_OID_UAP_BSS_CONFIG, + MLAN_OID_UAP_DEAUTH_STA, + MLAN_OID_UAP_BSS_RESET, +#endif +#if defined(STA_SUPPORT) && defined(UAP_SUPPORT) + MLAN_OID_BSS_ROLE, +#endif +#ifdef WIFI_DIRECT_SUPPORT + MLAN_OID_WIFI_DIRECT_MODE, +#endif + + /* Radio Configuration Group */ + MLAN_IOCTL_RADIO_CFG = 0x00030000, + MLAN_OID_RADIO_CTRL, + MLAN_OID_BAND_CFG, + MLAN_OID_ANT_CFG, +#ifdef WIFI_DIRECT_SUPPORT + MLAN_OID_REMAIN_CHAN_CFG, +#endif + + /* SNMP MIB Group */ + MLAN_IOCTL_SNMP_MIB = 0x00040000, + MLAN_OID_SNMP_MIB_RTS_THRESHOLD, + MLAN_OID_SNMP_MIB_FRAG_THRESHOLD, + MLAN_OID_SNMP_MIB_RETRY_COUNT, +#if defined(UAP_SUPPORT) + MLAN_OID_SNMP_MIB_DOT11D, + MLAN_OID_SNMP_MIB_DOT11H, +#endif + MLAN_OID_SNMP_MIB_DTIM_PERIOD, + + /* Status Information Group */ + MLAN_IOCTL_GET_INFO = 0x00050000, + MLAN_OID_GET_STATS, + MLAN_OID_GET_SIGNAL, + MLAN_OID_GET_FW_INFO, + MLAN_OID_GET_VER_EXT, + MLAN_OID_GET_BSS_INFO, + MLAN_OID_GET_DEBUG_INFO, +#ifdef UAP_SUPPORT + MLAN_OID_UAP_STA_LIST, +#endif + + /* Security Configuration Group */ + MLAN_IOCTL_SEC_CFG = 0x00060000, + MLAN_OID_SEC_CFG_AUTH_MODE, + MLAN_OID_SEC_CFG_ENCRYPT_MODE, + MLAN_OID_SEC_CFG_WPA_ENABLED, + MLAN_OID_SEC_CFG_ENCRYPT_KEY, + MLAN_OID_SEC_CFG_PASSPHRASE, + MLAN_OID_SEC_CFG_EWPA_ENABLED, + MLAN_OID_SEC_CFG_ESUPP_MODE, + MLAN_OID_SEC_CFG_WAPI_ENABLED, + MLAN_OID_SEC_CFG_PORT_CTRL_ENABLED, + + /* Rate Group */ + MLAN_IOCTL_RATE = 0x00070000, + MLAN_OID_RATE_CFG, + MLAN_OID_GET_DATA_RATE, + MLAN_OID_SUPPORTED_RATES, + + /* Power Configuration Group */ + MLAN_IOCTL_POWER_CFG = 0x00080000, + MLAN_OID_POWER_CFG, + MLAN_OID_POWER_CFG_EXT, + + /* Power Management Configuration Group */ + MLAN_IOCTL_PM_CFG = 0x00090000, + MLAN_OID_PM_CFG_IEEE_PS, + MLAN_OID_PM_CFG_HS_CFG, + MLAN_OID_PM_CFG_INACTIVITY_TO, + MLAN_OID_PM_CFG_DEEP_SLEEP, + MLAN_OID_PM_CFG_SLEEP_PD, + MLAN_OID_PM_CFG_PS_CFG, + MLAN_OID_PM_CFG_SLEEP_PARAMS, +#ifdef UAP_SUPPORT + MLAN_OID_PM_CFG_PS_MODE, +#endif /* UAP_SUPPORT */ + MLAN_OID_PM_INFO, + + /* WMM Configuration Group */ + MLAN_IOCTL_WMM_CFG = 0x000A0000, + MLAN_OID_WMM_CFG_ENABLE, + MLAN_OID_WMM_CFG_QOS, + MLAN_OID_WMM_CFG_ADDTS, + MLAN_OID_WMM_CFG_DELTS, + MLAN_OID_WMM_CFG_QUEUE_CONFIG, + MLAN_OID_WMM_CFG_QUEUE_STATS, + MLAN_OID_WMM_CFG_QUEUE_STATUS, + MLAN_OID_WMM_CFG_TS_STATUS, + + /* WPS Configuration Group */ + MLAN_IOCTL_WPS_CFG = 0x000B0000, + MLAN_OID_WPS_CFG_SESSION, + + /* 802.11n Configuration Group */ + MLAN_IOCTL_11N_CFG = 0x000C0000, + MLAN_OID_11N_CFG_TX, + MLAN_OID_11N_HTCAP_CFG, + MLAN_OID_11N_CFG_ADDBA_REJECT, + MLAN_OID_11N_CFG_AGGR_PRIO_TBL, + MLAN_OID_11N_CFG_ADDBA_PARAM, + MLAN_OID_11N_CFG_MAX_TX_BUF_SIZE, + MLAN_OID_11N_CFG_AMSDU_AGGR_CTRL, + MLAN_OID_11N_CFG_SUPPORTED_MCS_SET, + MLAN_OID_11N_CFG_TX_BF_CAP, + MLAN_OID_11N_CFG_TX_BF_CFG, + MLAN_OID_11N_CFG_STREAM_CFG, + + /* 802.11d Configuration Group */ + MLAN_IOCTL_11D_CFG = 0x000D0000, +#ifdef STA_SUPPORT + MLAN_OID_11D_CFG_ENABLE, + MLAN_OID_11D_CLR_CHAN_TABLE, +#endif /* STA_SUPPORT */ + MLAN_OID_11D_DOMAIN_INFO, + + /* Register Memory Access Group */ + MLAN_IOCTL_REG_MEM = 0x000E0000, + MLAN_OID_REG_RW, + MLAN_OID_EEPROM_RD, + MLAN_OID_MEM_RW, + + /* Multi-Radio Configuration Group */ + MLAN_IOCTL_MFR_CFG = 0x00100000, + + /* 802.11h Configuration Group */ + MLAN_IOCTL_11H_CFG = 0x00110000, + MLAN_OID_11H_CHANNEL_CHECK, + MLAN_OID_11H_LOCAL_POWER_CONSTRAINT, +#if defined(DFS_TESTING_SUPPORT) + MLAN_OID_11H_DFS_TESTING, +#endif + + /* Miscellaneous Configuration Group */ + MLAN_IOCTL_MISC_CFG = 0x00200000, + MLAN_OID_MISC_GEN_IE, + MLAN_OID_MISC_REGION, + MLAN_OID_MISC_WARM_RESET, +#if defined(SDIO_MULTI_PORT_TX_AGGR) || defined(SDIO_MULTI_PORT_RX_AGGR) + MLAN_OID_MISC_SDIO_MPA_CTRL, +#endif + MLAN_OID_MISC_HOST_CMD, + MLAN_OID_MISC_SYS_CLOCK, + MLAN_OID_MISC_SOFT_RESET, + MLAN_OID_MISC_WWS, + MLAN_OID_MISC_INIT_SHUTDOWN, + MLAN_OID_MISC_CUSTOM_IE, + MLAN_OID_MISC_TX_DATAPAUSE, + MLAN_OID_MISC_IP_ADDR, + MLAN_OID_MISC_MAC_CONTROL, + MLAN_OID_MISC_MEF_CFG, + MLAN_OID_MISC_CFP_CODE, + MLAN_OID_MISC_COUNTRY_CODE, + MLAN_OID_MISC_THERMAL, + MLAN_OID_MISC_RX_MGMT_IND, + MLAN_OID_MISC_SUBSCRIBE_EVENT, +#ifdef DEBUG_LEVEL1 + MLAN_OID_MISC_DRVDBG, +#endif + MLAN_OID_MISC_OTP_USER_DATA, +}; + +/** Sub command size */ +#define MLAN_SUB_COMMAND_SIZE 4 + +/** Enumeration for the action of IOCTL request */ +enum _mlan_act_ioctl +{ + MLAN_ACT_SET = 1, + MLAN_ACT_GET, + MLAN_ACT_CANCEL +}; + +/** Enumeration for generic enable/disable */ +enum _mlan_act_generic +{ + MLAN_ACT_DISABLE = 0, + MLAN_ACT_ENABLE = 1 +}; + +/** Enumeration for scan mode */ +enum _mlan_scan_mode +{ + MLAN_SCAN_MODE_UNCHANGED = 0, + MLAN_SCAN_MODE_BSS, + MLAN_SCAN_MODE_IBSS, + MLAN_SCAN_MODE_ANY +}; + +/** Enumeration for scan type */ +enum _mlan_scan_type +{ + MLAN_SCAN_TYPE_UNCHANGED = 0, + MLAN_SCAN_TYPE_ACTIVE, + MLAN_SCAN_TYPE_PASSIVE +}; + +/** Max number of supported rates */ +#define MLAN_SUPPORTED_RATES 32 + +/** RSSI scan */ +#define SCAN_RSSI(RSSI) (0x100 - ((t_u8)(RSSI))) + +/** Max passive scan time for each channel in milliseconds */ +#define MRVDRV_MAX_PASSIVE_SCAN_CHAN_TIME 2000 + +/** Max active scan time for each channel in milliseconds */ +#define MRVDRV_MAX_ACTIVE_SCAN_CHAN_TIME 500 + +/** Maximum number of probes to send on each channel */ +#define MAX_PROBES 4 + +/** Default number of probes to send on each channel */ +#define DEFAULT_PROBES 4 + +/** + * @brief Sub-structure passed in wlan_ioctl_get_scan_table_entry for each BSS + * + * Fixed field information returned for the scan response in the IOCTL + * response. + */ +typedef struct _wlan_get_scan_table_fixed +{ + /** BSSID of this network */ + t_u8 bssid[MLAN_MAC_ADDR_LENGTH]; + /** Channel this beacon/probe response was detected */ + t_u8 channel; + /** RSSI for the received packet */ + t_u8 rssi; + /** TSF value in microseconds from the firmware at packet reception */ + t_u64 network_tsf; +} wlan_get_scan_table_fixed; + +/** mlan_802_11_ssid data structure */ +typedef struct _mlan_802_11_ssid +{ + /** SSID Length */ + t_u32 ssid_len; + /** SSID information field */ + t_u8 ssid[MLAN_MAX_SSID_LENGTH]; +} mlan_802_11_ssid, *pmlan_802_11_ssid; + +/** + * Sructure to retrieve the scan table + */ +typedef struct +{ + /** + * - Zero based scan entry to start retrieval in command request + * - Number of scans entries returned in command response + */ + t_u32 scan_number; + /** + * Buffer marker for multiple wlan_ioctl_get_scan_table_entry structures. + * Each struct is padded to the nearest 32 bit boundary. + */ + t_u8 scan_table_entry_buf[1]; +} wlan_ioctl_get_scan_table_info; + +/** + * Structure passed in the wlan_ioctl_get_scan_table_info for each + * BSS returned in the WLAN_GET_SCAN_RESP IOCTL + */ +typedef struct _wlan_ioctl_get_scan_table_entry +{ + /** + * Fixed field length included in the response. + * + * Length value is included so future fixed fields can be added to the + * response without breaking backwards compatibility. Use the length + * to find the offset for the bssInfoLength field, not a sizeof() calc. + */ + t_u32 fixed_field_length; + + /** + * Length of the BSS Information (probe resp or beacon) that + * follows after the fixed_field_length + */ + t_u32 bss_info_length; + + /** + * Always present, fixed length data fields for the BSS + */ + wlan_get_scan_table_fixed fixed_fields; + + /* + * Probe response or beacon scanned for the BSS. + * + * Field layout: + * - TSF 8 octets + * - Beacon Interval 2 octets + * - Capability Info 2 octets + * + * - IEEE Infomation Elements; variable number & length per 802.11 spec + */ + /* t_u8 bss_info_buffer[0]; */ +} wlan_ioctl_get_scan_table_entry; + +/** Type definition of mlan_scan_time_params */ +typedef struct _mlan_scan_time_params +{ + /** Scan channel time for specific scan in milliseconds */ + t_u32 specific_scan_time; + /** Scan channel time for active scan in milliseconds */ + t_u32 active_scan_time; + /** Scan channel time for passive scan in milliseconds */ + t_u32 passive_scan_time; +} mlan_scan_time_params, *pmlan_scan_time_params; + +/** Type definition of mlan_user_scan */ +typedef struct _mlan_user_scan +{ + /** Length of scan_cfg_buf */ + t_u32 scan_cfg_len; + /** Buffer of scan config */ + t_u8 scan_cfg_buf[1]; +} mlan_user_scan, *pmlan_user_scan; + +/** Type definition of mlan_scan_req */ +typedef struct _mlan_scan_req +{ + /** BSS mode for scanning */ + t_u32 scan_mode; + /** Scan type */ + t_u32 scan_type; + /** SSID */ + mlan_802_11_ssid scan_ssid; + /** Scan time parameters */ + mlan_scan_time_params scan_time; + /** Scan config parameters in user scan */ + mlan_user_scan user_scan; +} mlan_scan_req, *pmlan_scan_req; + +/** Type defnition of mlan_scan_resp */ +typedef struct _mlan_scan_resp +{ + /** Number of scan result */ + t_u32 num_in_scan_table; + /** Scan table */ + t_u8 *pscan_table; + /* Age in seconds */ + t_u32 age_in_secs; +} mlan_scan_resp, *pmlan_scan_resp; + +/** Type definition of mlan_scan_cfg */ +typedef struct _mlan_scan_cfg +{ + /** Scan type */ + t_u32 scan_type; + /** BSS mode for scanning */ + t_u32 scan_mode; + /** Scan probe */ + t_u32 scan_probe; + /** Scan time parameters */ + mlan_scan_time_params scan_time; + /** Extended Scan */ + t_u32 ext_scan; +} mlan_scan_cfg, *pmlan_scan_cfg; + +/** Type defnition of mlan_ds_scan for MLAN_IOCTL_SCAN */ +typedef struct _mlan_ds_scan +{ + /** Sub-command */ + t_u32 sub_command; + /** Scan request/response */ + union + { + /** Scan request */ + mlan_scan_req scan_req; + /** Scan response */ + mlan_scan_resp scan_resp; + /** Scan config parameters in user scan */ + mlan_user_scan user_scan; + /** Scan config parameters */ + mlan_scan_cfg scan_cfg; + } param; +} mlan_ds_scan, *pmlan_ds_scan; + +/*-----------------------------------------------------------------*/ +/** BSS Configuration Group */ +/*-----------------------------------------------------------------*/ +/** Enumeration for BSS mode */ +enum _mlan_bss_mode +{ + MLAN_BSS_MODE_INFRA = 1, + MLAN_BSS_MODE_IBSS, + MLAN_BSS_MODE_AUTO +}; + +/** Maximum key length */ +#define MLAN_MAX_KEY_LENGTH 32 + +/** max Wmm AC queues */ +#define MAX_AC_QUEUES 4 + +/** Maximum atim window in milliseconds */ +#define MLAN_MAX_ATIM_WINDOW 50 + +/** Minimum beacon interval */ +#define MLAN_MIN_BEACON_INTERVAL 20 +/** Maximum beacon interval */ +#define MLAN_MAX_BEACON_INTERVAL 1000 +/** Default beacon interval */ +#define MLAN_BEACON_INTERVAL 100 + +/** Receive all packets */ +#define MLAN_PROMISC_MODE 1 +/** Receive multicast packets in multicast list */ +#define MLAN_MULTICAST_MODE 2 +/** Receive all multicast packets */ +#define MLAN_ALL_MULTI_MODE 4 + +/** Maximum size of multicast list */ +#define MLAN_MAX_MULTICAST_LIST_SIZE 32 + +/** mlan_multicast_list data structure for MLAN_OID_BSS_MULTICAST_LIST */ +typedef struct _mlan_multicast_list +{ + /** Multicast mode */ + t_u32 mode; + /** Number of multicast addresses in the list */ + t_u32 num_multicast_addr; + /** Multicast address list */ + mlan_802_11_mac_addr mac_list[MLAN_MAX_MULTICAST_LIST_SIZE]; +} mlan_multicast_list, *pmlan_multicast_list; + +/** Max channel */ +#define MLAN_MAX_CHANNEL 165 + +/** Maximum number of channels in table */ +#define MLAN_MAX_CHANNEL_NUM 128 + +/** Channel/frequence for MLAN_OID_BSS_CHANNEL */ +typedef struct _chan_freq +{ + /** Channel Number */ + t_u32 channel; + /** Frequency of this Channel */ + t_u32 freq; +} chan_freq; + +/** mlan_chan_list data structure for MLAN_OID_BSS_CHANNEL_LIST */ +typedef struct _mlan_chan_list +{ + /** Number of channel */ + t_u32 num_of_chan; + /** Channel-Frequency table */ + chan_freq cf[MLAN_MAX_CHANNEL_NUM]; +} mlan_chan_list; + +/** mlan_ssid_bssid data structure for MLAN_OID_BSS_START and MLAN_OID_BSS_FIND_BSS */ +typedef struct _mlan_ssid_bssid +{ + /** SSID */ + mlan_802_11_ssid ssid; + /** BSSID */ + mlan_802_11_mac_addr bssid; + /** index in BSSID list, start from 1 */ + t_u32 idx; +} mlan_ssid_bssid; + +#ifdef UAP_SUPPORT +/** Maximum packet forward control value */ +#define MAX_PKT_FWD_CTRL 15 +/** Maximum BEACON period */ +#define MAX_BEACON_PERIOD 4000 +/** Minimum BEACON period */ +#define MIN_BEACON_PERIOD 50 +/** Maximum DTIM period */ +#define MAX_DTIM_PERIOD 100 +/** Minimum DTIM period */ +#define MIN_DTIM_PERIOD 1 +/** Maximum TX Power Limit */ +#define MAX_TX_POWER 20 +/** Minimum TX Power Limit */ +#define MIN_TX_POWER 0 +/** MAX station count */ +#define MAX_STA_COUNT 10 +/** Maximum RTS threshold */ +#define MAX_RTS_THRESHOLD 2347 +/** Maximum fragmentation threshold */ +#define MAX_FRAG_THRESHOLD 2346 +/** Minimum fragmentation threshold */ +#define MIN_FRAG_THRESHOLD 256 +/** data rate 54 M */ +#define DATA_RATE_54M 108 +/** antenna A */ +#define ANTENNA_MODE_A 0 +/** antenna B */ +#define ANTENNA_MODE_B 1 +/** transmit antenna */ +#define TX_ANTENNA 1 +/** receive antenna */ +#define RX_ANTENNA 0 +/** Maximum stage out time */ +#define MAX_STAGE_OUT_TIME 864000 +/** Minimum stage out time */ +#define MIN_STAGE_OUT_TIME 300 +/** Maximum Retry Limit */ +#define MAX_RETRY_LIMIT 14 + +/** Maximum group key timer in seconds */ +#define MAX_GRP_TIMER 86400 + +/** Maximum value of 4 byte configuration */ +#define MAX_VALID_DWORD 0x7FFFFFFF /* (1 << 31) - 1 */ + +/** Band config ACS mode */ +#define BAND_CONFIG_ACS_MODE 0x40 +/** Band config manual */ +#define BAND_CONFIG_MANUAL 0x00 + +/** Maximum data rates */ +#define MAX_DATA_RATES 14 + +/** auto data rate */ +#define DATA_RATE_AUTO 0 + +/**filter mode: disable */ +#define MAC_FILTER_MODE_DISABLE 0 +/**filter mode: block mac address */ +#define MAC_FILTER_MODE_ALLOW_MAC 1 +/**filter mode: block mac address */ +#define MAC_FILTER_MODE_BLOCK_MAC 2 +/** Maximum mac filter num */ +#define MAX_MAC_FILTER_NUM 16 + +/* Bitmap for protocol to use */ +/** No security */ +#define PROTOCOL_NO_SECURITY 0x01 +/** Static WEP */ +#define PROTOCOL_STATIC_WEP 0x02 +/** WPA */ +#define PROTOCOL_WPA 0x08 +/** WPA2 */ +#define PROTOCOL_WPA2 0x20 +/** WP2 Mixed */ +#define PROTOCOL_WPA2_MIXED 0x28 +/** EAP */ +#define PROTOCOL_EAP 0x40 +/** WAPI */ +#define PROTOCOL_WAPI 0x80 + +/** Key_mgmt_psk */ +#define KEY_MGMT_NONE 0x04 +/** Key_mgmt_none */ +#define KEY_MGMT_PSK 0x02 +/** Key_mgmt_eap */ +#define KEY_MGMT_EAP 0x01 + +/** TKIP */ +#define CIPHER_TKIP 0x04 +/** AES CCMP */ +#define CIPHER_AES_CCMP 0x08 + +/** Valid cipher bitmap */ +#define VALID_CIPHER_BITMAP 0x0c + +/** Channel List Entry */ +typedef struct _channel_list +{ + /** Channel Number */ + t_u8 chan_number; + /** Band Config */ + t_u8 band_config_type; +} scan_chan_list; + +/** mac_filter data structure */ +typedef struct _mac_filter +{ + /** mac filter mode */ + t_u16 filter_mode; + /** mac adress count */ + t_u16 mac_count; + /** mac address list */ + mlan_802_11_mac_addr mac_list[MAX_MAC_FILTER_NUM]; +} mac_filter; + +/** wpa parameter */ +typedef struct _wpa_param +{ + /** Pairwise cipher WPA */ + t_u8 pairwise_cipher_wpa; + /** Pairwise cipher WPA2 */ + t_u8 pairwise_cipher_wpa2; + /** group cipher */ + t_u8 group_cipher; + /** RSN replay protection */ + t_u8 rsn_protection; + /** passphrase length */ + t_u32 length; + /** passphrase */ + t_u8 passphrase[64]; + /**group key rekey time in seconds */ + t_u32 gk_rekey_time; +} wpa_param; + +/** wep key */ +typedef struct _wep_key +{ + /** key index 0-3 */ + t_u8 key_index; + /** is default */ + t_u8 is_default; + /** length */ + t_u16 length; + /** key data */ + t_u8 key[26]; +} wep_key; + +/** wep param */ +typedef struct _wep_param +{ + /** key 0 */ + wep_key key0; + /** key 1 */ + wep_key key1; + /** key 2 */ + wep_key key2; + /** key 3 */ + wep_key key3; +} wep_param; + +/** Data structure of WMM QoS information */ +typedef struct _wmm_qos_info_t +{ +#ifdef BIG_ENDIAN_SUPPORT + /** QoS UAPSD */ + t_u8 qos_uapsd:1; + /** Reserved */ + t_u8 reserved:3; + /** Parameter set count */ + t_u8 para_set_count:4; +#else + /** Parameter set count */ + t_u8 para_set_count:4; + /** Reserved */ + t_u8 reserved:3; + /** QoS UAPSD */ + t_u8 qos_uapsd:1; +#endif /* BIG_ENDIAN_SUPPORT */ +} wmm_qos_info_t, *pwmm_qos_info_t; + +/** Data structure of WMM ECW */ +typedef struct _wmm_ecw_t +{ +#ifdef BIG_ENDIAN_SUPPORT + /** Maximum Ecw */ + t_u8 ecw_max:4; + /** Minimum Ecw */ + t_u8 ecw_min:4; +#else + /** Minimum Ecw */ + t_u8 ecw_min:4; + /** Maximum Ecw */ + t_u8 ecw_max:4; +#endif /* BIG_ENDIAN_SUPPORT */ +} wmm_ecw_t, *pwmm_ecw_t; + +/** Data structure of WMM Aci/Aifsn */ +typedef struct _wmm_aci_aifsn_t +{ +#ifdef BIG_ENDIAN_SUPPORT + /** Reserved */ + t_u8 reserved:1; + /** Aci */ + t_u8 aci:2; + /** Acm */ + t_u8 acm:1; + /** Aifsn */ + t_u8 aifsn:4; +#else + /** Aifsn */ + t_u8 aifsn:4; + /** Acm */ + t_u8 acm:1; + /** Aci */ + t_u8 aci:2; + /** Reserved */ + t_u8 reserved:1; +#endif /* BIG_ENDIAN_SUPPORT */ +} wmm_aci_aifsn_t, *pwmm_aci_aifsn_t; + +/** Data structure of WMM AC parameters */ +typedef struct _wmm_ac_parameters_t +{ + wmm_aci_aifsn_t aci_aifsn; /**< AciAifSn */ + wmm_ecw_t ecw; /**< Ecw */ + t_u16 tx_op_limit; /**< Tx op limit */ +} wmm_ac_parameters_t, *pwmm_ac_parameters_t; + +/** Data structure of WMM parameter IE */ +typedef struct _wmm_parameter_t +{ + /** OuiType: 00:50:f2:02 */ + t_u8 ouitype[4]; + /** Oui subtype: 01 */ + t_u8 ouisubtype; + /** version: 01 */ + t_u8 version; + /** QoS information */ + t_u8 qos_info; + /** Reserved */ + t_u8 reserved; + /** AC Parameters Record WMM_AC_BE, WMM_AC_BK, WMM_AC_VI, WMM_AC_VO */ + wmm_ac_parameters_t ac_params[MAX_AC_QUEUES]; +} wmm_parameter_t, *pwmm_parameter_t; + +/** mlan_bss_param + * Note: For each entry you must enter an invalid value + * in the MOAL function woal_set_sys_config_invalid_data(). + * Otherwise for a valid data an unwanted TLV will be + * added to that command. + */ +typedef struct _mlan_uap_bss_param +{ + /** AP mac addr */ + mlan_802_11_mac_addr mac_addr; + /** SSID */ + mlan_802_11_ssid ssid; + /** Broadcast ssid control */ + t_u8 bcast_ssid_ctl; + /** Radio control: on/off */ + t_u8 radio_ctl; + /** dtim period */ + t_u8 dtim_period; + /** beacon period */ + t_u16 beacon_period; + /** rates */ + t_u8 rates[MAX_DATA_RATES]; + /** Tx data rate */ + t_u16 tx_data_rate; + /** multicast/broadcast data rate */ + t_u16 mcbc_data_rate; + /** Tx power level in dBm */ + t_u8 tx_power_level; + /** Tx antenna */ + t_u8 tx_antenna; + /** Rx antenna */ + t_u8 rx_antenna; + /** packet forward control */ + t_u8 pkt_forward_ctl; + /** max station count */ + t_u16 max_sta_count; + /** mac filter */ + mac_filter filter; + /** station ageout timer in unit of 100ms */ + t_u32 sta_ageout_timer; + /** PS station ageout timer in unit of 100ms */ + t_u32 ps_sta_ageout_timer; + /** RTS threshold */ + t_u16 rts_threshold; + /** fragmentation threshold */ + t_u16 frag_threshold; + /** retry_limit */ + t_u16 retry_limit; + /** pairwise update timeout in milliseconds */ + t_u32 pairwise_update_timeout; + /** pairwise handshake retries */ + t_u32 pwk_retries; + /** groupwise update timeout in milliseconds */ + t_u32 groupwise_update_timeout; + /** groupwise handshake retries */ + t_u32 gwk_retries; + /** preamble type */ + t_u8 preamble_type; + /** band cfg */ + t_u8 band_cfg; + /** channel */ + t_u8 channel; + /** auth mode */ + t_u16 auth_mode; + /** encryption protocol */ + t_u16 protocol; + /** key managment type */ + t_u16 key_mgmt; + /** wep param */ + wep_param wep_cfg; + /** wpa param */ + wpa_param wpa_cfg; + /** Mgmt IE passthru mask */ + t_u32 mgmt_ie_passthru_mask; + /* + * 11n HT Cap HTCap_t ht_cap + */ + /** HT Capabilities Info field */ + t_u16 ht_cap_info; + /** A-MPDU Parameters field */ + t_u8 ampdu_param; + /** Supported MCS Set field */ + t_u8 supported_mcs_set[16]; + /** HT Extended Capabilities field */ + t_u16 ht_ext_cap; + /** Transmit Beamforming Capabilities field */ + t_u32 tx_bf_cap; + /** Antenna Selection Capability field */ + t_u8 asel; + /** Enable 2040 Coex */ + t_u8 enable_2040coex; + /** key management operation */ + t_u16 key_mgmt_operation; + /** BSS status */ + t_u16 bss_status; +#ifdef WIFI_DIRECT_SUPPORT + /* pre shared key */ + t_u8 psk[MLAN_MAX_KEY_LENGTH]; +#endif /* WIFI_DIRECT_SUPPORT */ + /** Number of channels in scan_channel_list */ + t_u32 num_of_chan; + /** scan channel list in ACS mode */ + scan_chan_list chan_list[MLAN_MAX_CHANNEL]; + /** Wmm parameters */ + wmm_parameter_t wmm_para; +} mlan_uap_bss_param; + +/** mlan_deauth_param */ +typedef struct _mlan_deauth_param +{ + /** STA mac addr */ + t_u8 mac_addr[MLAN_MAC_ADDR_LENGTH]; + /** deauth reason */ + t_u16 reason_code; +} mlan_deauth_param; +#endif + +#ifdef WIFI_DIRECT_SUPPORT +/** mode: disable wifi direct */ +#define WIFI_DIRECT_MODE_DISABLE 0 +/** mode: listen */ +#define WIFI_DIRECT_MODE_LISTEN 1 +/** mode: GO */ +#define WIFI_DIRECT_MODE_GO 2 +/** mode: client */ +#define WIFI_DIRECT_MODE_CLIENT 3 +/** mode: find */ +#define WIFI_DIRECT_MODE_FIND 4 +/** mode: stop find */ +#define WIFI_DIRECT_MODE_STOP_FIND 5 +#endif + +/** Type definition of mlan_ds_bss for MLAN_IOCTL_BSS */ +typedef struct _mlan_ds_bss +{ + /** Sub-command */ + t_u32 sub_command; + /** BSS parameter */ + union + { + /** SSID-BSSID for MLAN_OID_BSS_START */ + mlan_ssid_bssid ssid_bssid; + /** BSSID for MLAN_OID_BSS_STOP */ + mlan_802_11_mac_addr bssid; + /** BSS mode for MLAN_OID_BSS_MODE */ + t_u32 bss_mode; + /** BSS channel/frequency for MLAN_OID_BSS_CHANNEL */ + chan_freq bss_chan; + /** BSS channel list for MLAN_OID_BSS_CHANNEL_LIST */ + mlan_chan_list chanlist; + /** MAC address for MLAN_OID_BSS_MAC_ADDR */ + mlan_802_11_mac_addr mac_addr; + /** Multicast list for MLAN_OID_BSS_MULTICAST_LIST */ + mlan_multicast_list multicast_list; + /** Beacon interval for MLAN_OID_IBSS_BCN_INTERVAL */ + t_u32 bcn_interval; + /** ATIM window for MLAN_OID_IBSS_ATIM_WINDOW */ + t_u32 atim_window; +#ifdef UAP_SUPPORT + /** BSS param for AP mode */ + mlan_uap_bss_param bss_config; + /** deauth param for MLAN_OID_UAP_DEAUTH_STA */ + mlan_deauth_param deauth_param; +#endif +#if defined(STA_SUPPORT) && defined(UAP_SUPPORT) + /** BSS role */ + t_u8 bss_role; +#endif +#ifdef WIFI_DIRECT_SUPPORT + t_u16 wfd_mode; +#endif + } param; +} mlan_ds_bss, *pmlan_ds_bss; + +/*-----------------------------------------------------------------*/ +/** Radio Control Group */ +/*-----------------------------------------------------------------*/ +/** Enumeration for band */ +enum _mlan_band_def +{ + BAND_B = 1, + BAND_G = 2, + BAND_A = 4, + BAND_GN = 8, + BAND_AN = 16, +}; + +/** NO secondary channel */ +#define NO_SEC_CHANNEL 0 +/** secondary channel is above primary channel */ +#define SEC_CHANNEL_ABOVE 1 +/** secondary channel is below primary channel */ +#define SEC_CHANNEL_BELOW 3 +/** Channel bandwidth */ +#define CHANNEL_BW_20MHZ 0 +#define CHANNEL_BW_40MHZ_ABOVE 1 +#define CHANNEL_BW_40MHZ_BELOW 3 + +/** Type definition of mlan_ds_band_cfg for MLAN_OID_BAND_CFG */ +typedef struct _mlan_ds_band_cfg +{ + /** Infra band */ + t_u32 config_bands; + /** Ad-hoc start band */ + t_u32 adhoc_start_band; + /** Ad-hoc start channel */ + t_u32 adhoc_channel; + /** Ad-hoc channel bandwidth */ + t_u32 sec_chan_offset; + /** fw supported band */ + t_u32 fw_bands; +} mlan_ds_band_cfg; + +/** Type definition of mlan_ds_ant_cfg for MLAN_OID_ANT_CFG */ +typedef struct _mlan_ds_ant_cfg +{ + /** Tx antenna mode */ + t_u32 tx_antenna; + /** Rx antenna mode */ + t_u32 rx_antenna; +} mlan_ds_ant_cfg, *pmlan_ds_ant_cfg; + +#ifdef WIFI_DIRECT_SUPPORT +/** Type definition of mlan_ds_remain_chan for MLAN_OID_REMAIN_CHAN_CFG */ +typedef struct _mlan_ds_remain_chan +{ + /** remove flag */ + t_u16 remove; + /** status */ + t_u8 status; + /** Band cfg */ + t_u8 bandcfg; + /** channel */ + t_u8 channel; + /** remain time: Unit ms*/ + t_u32 remain_period; +} mlan_ds_remain_chan, *pmlan_ds_remain_chan; +#endif + +/** Type definition of mlan_ds_radio_cfg for MLAN_IOCTL_RADIO_CFG */ +typedef struct _mlan_ds_radio_cfg +{ + /** Sub-command */ + t_u32 sub_command; + /** Radio control parameter */ + union + { + /** Radio on/off for MLAN_OID_RADIO_CTRL */ + t_u32 radio_on_off; + /** Band info for MLAN_OID_BAND_CFG */ + mlan_ds_band_cfg band_cfg; + /** Antenna info for MLAN_OID_ANT_CFG */ + mlan_ds_ant_cfg ant_cfg; + /** Antenna info for MLAN_OID_ANT_CFG */ + t_u32 antenna; +#ifdef WIFI_DIRECT_SUPPORT + /** remain on channel for MLAN_OID_REMAIN_CHAN_CFG */ + mlan_ds_remain_chan remain_chan; +#endif + } param; +} mlan_ds_radio_cfg, *pmlan_ds_radio_cfg; + +/*-----------------------------------------------------------------*/ +/** SNMP MIB Group */ +/*-----------------------------------------------------------------*/ +/** Type definition of mlan_ds_snmp_mib for MLAN_IOCTL_SNMP_MIB */ +typedef struct _mlan_ds_snmp_mib +{ + /** Sub-command */ + t_u32 sub_command; + /** SNMP MIB parameter */ + union + { + /** RTS threshold for MLAN_OID_SNMP_MIB_RTS_THRESHOLD */ + t_u32 rts_threshold; + /** Fragment threshold for MLAN_OID_SNMP_MIB_FRAG_THRESHOLD */ + t_u32 frag_threshold; + /** Retry count for MLAN_OID_SNMP_MIB_RETRY_COUNT */ + t_u32 retry_count; +#if defined(UAP_SUPPORT) + /** OID value for MLAN_OID_SNMP_MIB_DOT11D/H */ + t_u32 oid_value; +#endif + /** DTIM period for MLAN_OID_SNMP_MIB_DTIM_PERIOD */ + t_u32 dtim_period; + } param; +} mlan_ds_snmp_mib, *pmlan_ds_snmp_mib; + +/*-----------------------------------------------------------------*/ +/** Status Information Group */ +/*-----------------------------------------------------------------*/ +/** Enumeration for ad-hoc status */ +enum _mlan_adhoc_status +{ + ADHOC_IDLE, + ADHOC_STARTED, + ADHOC_JOINED, + ADHOC_COALESCED, ADHOC_STARTING +}; + +/** Type definition of mlan_ds_get_stats for MLAN_OID_GET_STATS */ +typedef struct _mlan_ds_get_stats +{ + /** Statistics counter */ + /** Multicast transmitted frame count */ + t_u32 mcast_tx_frame; + /** Failure count */ + t_u32 failed; + /** Retry count */ + t_u32 retry; + /** Multi entry count */ + t_u32 multi_retry; + /** Duplicate frame count */ + t_u32 frame_dup; + /** RTS success count */ + t_u32 rts_success; + /** RTS failure count */ + t_u32 rts_failure; + /** Ack failure count */ + t_u32 ack_failure; + /** Rx fragmentation count */ + t_u32 rx_frag; + /** Multicast Tx frame count */ + t_u32 mcast_rx_frame; + /** FCS error count */ + t_u32 fcs_error; + /** Tx frame count */ + t_u32 tx_frame; + /** WEP ICV error count */ + t_u32 wep_icv_error[4]; +} mlan_ds_get_stats, *pmlan_ds_get_stats; + +/** Type definition of mlan_ds_uap_stats for MLAN_OID_GET_STATS */ +typedef struct _mlan_ds_uap_stats +{ + /** tkip mic failures */ + t_u32 tkip_mic_failures; + /** ccmp decrypt errors */ + t_u32 ccmp_decrypt_errors; + /** wep undecryptable count */ + t_u32 wep_undecryptable_count; + /** wep icv error count */ + t_u32 wep_icv_error_count; + /** decrypt failure count */ + t_u32 decrypt_failure_count; + /** dot11 multicast tx count */ + t_u32 mcast_tx_count; + /** dot11 failed count */ + t_u32 failed_count; + /** dot11 retry count */ + t_u32 retry_count; + /** dot11 multi retry count */ + t_u32 multi_retry_count; + /** dot11 frame duplicate count */ + t_u32 frame_dup_count; + /** dot11 rts success count */ + t_u32 rts_success_count; + /** dot11 rts failure count */ + t_u32 rts_failure_count; + /** dot11 ack failure count */ + t_u32 ack_failure_count; + /** dot11 rx ragment count */ + t_u32 rx_fragment_count; + /** dot11 mcast rx frame count */ + t_u32 mcast_rx_frame_count; + /** dot11 fcs error count */ + t_u32 fcs_error_count; + /** dot11 tx frame count */ + t_u32 tx_frame_count; + /** dot11 rsna tkip cm invoked */ + t_u32 rsna_tkip_cm_invoked; + /** dot11 rsna 4way handshake failures */ + t_u32 rsna_4way_hshk_failures; +} mlan_ds_uap_stats, *pmlan_ds_uap_stats; + +/** Mask of last beacon RSSI */ +#define BCN_RSSI_LAST_MASK 0x00000001 +/** Mask of average beacon RSSI */ +#define BCN_RSSI_AVG_MASK 0x00000002 +/** Mask of last data RSSI */ +#define DATA_RSSI_LAST_MASK 0x00000004 +/** Mask of average data RSSI */ +#define DATA_RSSI_AVG_MASK 0x00000008 +/** Mask of last beacon SNR */ +#define BCN_SNR_LAST_MASK 0x00000010 +/** Mask of average beacon SNR */ +#define BCN_SNR_AVG_MASK 0x00000020 +/** Mask of last data SNR */ +#define DATA_SNR_LAST_MASK 0x00000040 +/** Mask of average data SNR */ +#define DATA_SNR_AVG_MASK 0x00000080 +/** Mask of last beacon NF */ +#define BCN_NF_LAST_MASK 0x00000100 +/** Mask of average beacon NF */ +#define BCN_NF_AVG_MASK 0x00000200 +/** Mask of last data NF */ +#define DATA_NF_LAST_MASK 0x00000400 +/** Mask of average data NF */ +#define DATA_NF_AVG_MASK 0x00000800 +/** Mask of all RSSI_INFO */ +#define ALL_RSSI_INFO_MASK 0x00000fff + +/** Type definition of mlan_ds_get_signal for MLAN_OID_GET_SIGNAL */ +typedef struct _mlan_ds_get_signal +{ + /** Selector of get operation */ + /* + * Bit0: Last Beacon RSSI, Bit1: Average Beacon RSSI, + * Bit2: Last Data RSSI, Bit3: Average Data RSSI, + * Bit4: Last Beacon SNR, Bit5: Average Beacon SNR, + * Bit6: Last Data SNR, Bit7: Average Data SNR, + * Bit8: Last Beacon NF, Bit9: Average Beacon NF, + * Bit10: Last Data NF, Bit11: Average Data NF + */ + t_u16 selector; + + /** RSSI */ + /** RSSI of last beacon */ + t_s16 bcn_rssi_last; + /** RSSI of beacon average */ + t_s16 bcn_rssi_avg; + /** RSSI of last data packet */ + t_s16 data_rssi_last; + /** RSSI of data packet average */ + t_s16 data_rssi_avg; + + /** SNR */ + /** SNR of last beacon */ + t_s16 bcn_snr_last; + /** SNR of beacon average */ + t_s16 bcn_snr_avg; + /** SNR of last data packet */ + t_s16 data_snr_last; + /** SNR of data packet average */ + t_s16 data_snr_avg; + + /** NF */ + /** NF of last beacon */ + t_s16 bcn_nf_last; + /** NF of beacon average */ + t_s16 bcn_nf_avg; + /** NF of last data packet */ + t_s16 data_nf_last; + /** NF of data packet average */ + t_s16 data_nf_avg; +} mlan_ds_get_signal, *pmlan_ds_get_signal; + +/** mlan_fw_info data structure for MLAN_OID_GET_FW_INFO */ +typedef struct _mlan_fw_info +{ + /** Firmware version */ + t_u32 fw_ver; + /** MAC address */ + mlan_802_11_mac_addr mac_addr; + /** Device support for MIMO abstraction of MCSs */ + t_u8 hw_dev_mcs_support; + /** fw supported band */ + t_u8 fw_bands; +} mlan_fw_info, *pmlan_fw_info; + +/** Version string buffer length */ +#define MLAN_MAX_VER_STR_LEN 128 + +/** mlan_ver_ext data structure for MLAN_OID_GET_VER_EXT */ +typedef struct _mlan_ver_ext +{ + /** Selected version string */ + t_u32 version_str_sel; + /** Version string */ + char version_str[MLAN_MAX_VER_STR_LEN]; +} mlan_ver_ext, *pmlan_ver_ext; + +/** mlan_bss_info data structure for MLAN_OID_GET_BSS_INFO */ +typedef struct _mlan_bss_info +{ + /** BSS mode */ + t_u32 bss_mode; + /** SSID */ + mlan_802_11_ssid ssid; + /** Table index */ + t_u32 scan_table_idx; + /** Channel */ + t_u32 bss_chan; + /** Band */ + t_u8 bss_band; + /** Region code */ + t_u32 region_code; + /** Connection status */ + t_u32 media_connected; + /** Radio on */ + t_u32 radio_on; + /** Max power level in dBm */ + t_u32 max_power_level; + /** Min power level in dBm */ + t_u32 min_power_level; + /** Adhoc state */ + t_u32 adhoc_state; + /** NF of last beacon */ + t_s32 bcn_nf_last; + /** wep status */ + t_u32 wep_status; + /** Host Sleep configured flag */ + t_u32 is_hs_configured; + /** Deep Sleep flag */ + t_u32 is_deep_sleep; + /** BSSID */ + mlan_802_11_mac_addr bssid; +#ifdef STA_SUPPORT + /** Capability Info */ + t_u16 capability_info; + /** Beacon Interval */ + t_u16 beacon_interval; + /** Listen Interval */ + t_u16 listen_interval; + /** Association Id */ + t_u16 assoc_id; + /** AP/Peer supported rates */ + t_u8 peer_supp_rates[MLAN_SUPPORTED_RATES]; +#endif /* STA_SUPPORT */ +} mlan_bss_info, *pmlan_bss_info; + +/** MAXIMUM number of TID */ +#define MAX_NUM_TID 8 + +/** Max RX Win size */ +#define MAX_RX_WINSIZE 64 + +/** rx_reorder_tbl */ +typedef struct +{ + /** TID */ + t_u16 tid; + /** TA */ + t_u8 ta[MLAN_MAC_ADDR_LENGTH]; + /** Start window */ + t_u32 start_win; + /** Window size */ + t_u32 win_size; + /** amsdu flag */ + t_u8 amsdu; + /** buffer status */ + t_u32 buffer[MAX_RX_WINSIZE]; +} rx_reorder_tbl; + +/** tx_ba_stream_tbl */ +typedef struct +{ + /** TID */ + t_u16 tid; + /** RA */ + t_u8 ra[MLAN_MAC_ADDR_LENGTH]; + /** amsdu flag */ + t_u8 amsdu; +} tx_ba_stream_tbl; + +/** Debug command number */ +#define DBG_CMD_NUM 5 + +/** mlan_debug_info data structure for MLAN_OID_GET_DEBUG_INFO */ +typedef struct _mlan_debug_info +{ + /* WMM AC_BK count */ + t_u32 wmm_ac_bk; + /* WMM AC_BE count */ + t_u32 wmm_ac_be; + /* WMM AC_VI count */ + t_u32 wmm_ac_vi; + /* WMM AC_VO count */ + t_u32 wmm_ac_vo; + /** Corresponds to max_tx_buf_size member of mlan_adapter*/ + t_u32 max_tx_buf_size; + /** Corresponds to tx_buf_size member of mlan_adapter*/ + t_u32 tx_buf_size; + /** Corresponds to curr_tx_buf_size member of mlan_adapter*/ + t_u32 curr_tx_buf_size; + /** Tx table num */ + t_u32 tx_tbl_num; + /** Tx ba stream table */ + tx_ba_stream_tbl tx_tbl[MLAN_MAX_TX_BASTREAM_SUPPORTED]; + /** Rx table num */ + t_u32 rx_tbl_num; + /** Rx reorder table*/ + rx_reorder_tbl rx_tbl[MLAN_MAX_RX_BASTREAM_SUPPORTED]; + /** Corresponds to ps_mode member of mlan_adapter */ + t_u16 ps_mode; + /** Corresponds to ps_state member of mlan_adapter */ + t_u32 ps_state; +#ifdef STA_SUPPORT + /** Corresponds to is_deep_sleep member of mlan_adapter */ + t_u8 is_deep_sleep; +#endif /** STA_SUPPORT */ + /** Corresponds to pm_wakeup_card_req member of mlan_adapter */ + t_u8 pm_wakeup_card_req; + /** Corresponds to pm_wakeup_fw_try member of mlan_adapter */ + t_u32 pm_wakeup_fw_try; + /** Corresponds to is_hs_configured member of mlan_adapter */ + t_u8 is_hs_configured; + /** Corresponds to hs_activated member of mlan_adapter */ + t_u8 hs_activated; + /** Corresponds to pps_uapsd_mode member of mlan_adapter */ + t_u16 pps_uapsd_mode; + /** Corresponds to sleep_period.period member of mlan_adapter */ + t_u16 sleep_pd; + /** Corresponds to wmm_qosinfo member of mlan_private */ + t_u8 qos_cfg; + /** Corresponds to tx_lock_flag member of mlan_adapter */ + t_u8 tx_lock_flag; + /** Corresponds to port_open member of mlan_private */ + t_u8 port_open; + /** Corresponds to scan_processing member of mlan_adapter */ + t_u32 scan_processing; + /** Number of host to card command failures */ + t_u32 num_cmd_host_to_card_failure; + /** Number of host to card sleep confirm failures */ + t_u32 num_cmd_sleep_cfm_host_to_card_failure; + /** Number of host to card Tx failures */ + t_u32 num_tx_host_to_card_failure; + /** Number of card to host command/event failures */ + t_u32 num_cmdevt_card_to_host_failure; + /** Number of card to host Rx failures */ + t_u32 num_rx_card_to_host_failure; + /** Number of interrupt read failures */ + t_u32 num_int_read_failure; + /** Last interrupt status */ + t_u32 last_int_status; + /** Number of deauthentication events */ + t_u32 num_event_deauth; + /** Number of disassosiation events */ + t_u32 num_event_disassoc; + /** Number of link lost events */ + t_u32 num_event_link_lost; + /** Number of deauthentication commands */ + t_u32 num_cmd_deauth; + /** Number of association comamnd successes */ + t_u32 num_cmd_assoc_success; + /** Number of association command failures */ + t_u32 num_cmd_assoc_failure; + /** Number of Tx timeouts */ + t_u32 num_tx_timeout; + /** Number of command timeouts */ + t_u32 num_cmd_timeout; + /** Timeout command ID */ + t_u16 timeout_cmd_id; + /** Timeout command action */ + t_u16 timeout_cmd_act; + /** List of last command IDs */ + t_u16 last_cmd_id[DBG_CMD_NUM]; + /** List of last command actions */ + t_u16 last_cmd_act[DBG_CMD_NUM]; + /** Last command index */ + t_u16 last_cmd_index; + /** List of last command response IDs */ + t_u16 last_cmd_resp_id[DBG_CMD_NUM]; + /** Last command response index */ + t_u16 last_cmd_resp_index; + /** List of last events */ + t_u16 last_event[DBG_CMD_NUM]; + /** Last event index */ + t_u16 last_event_index; + + /** Corresponds to data_sent member of mlan_adapter */ + t_u8 data_sent; + /** Corresponds to cmd_sent member of mlan_adapter */ + t_u8 cmd_sent; + /** SDIO multiple port read bitmap */ + t_u32 mp_rd_bitmap; + /** SDIO multiple port write bitmap */ + t_u32 mp_wr_bitmap; + /** Current available port for read */ + t_u8 curr_rd_port; + /** Current available port for write */ + t_u8 curr_wr_port; + /** Corresponds to cmdresp_received member of mlan_adapter */ + t_u8 cmd_resp_received; + /** Corresponds to event_received member of mlan_adapter */ + t_u8 event_received; + /** pendig tx pkts */ + t_u32 tx_pkts_queued; +#ifdef UAP_SUPPORT + /** pending bridge pkts */ + t_u16 num_bridge_pkts; + /** dropped pkts */ + t_u32 num_drop_pkts; +#endif +} mlan_debug_info, *pmlan_debug_info; + +#ifdef UAP_SUPPORT +/** Maximum number of clients supported by AP */ +#define MAX_NUM_CLIENTS MAX_STA_COUNT + +/** station info */ +typedef struct _sta_info +{ + /** STA MAC address */ + t_u8 mac_address[MLAN_MAC_ADDR_LENGTH]; + /** Power mfg status */ + t_u8 power_mfg_status; + /** RSSI */ + t_s8 rssi; +} sta_info; + +/** mlan_ds_sta_list structure for MLAN_OID_UAP_STA_LIST */ +typedef struct _mlan_ds_sta_list +{ + /** station count */ + t_u16 sta_count; + /** station list */ + sta_info info[MAX_NUM_CLIENTS]; +} mlan_ds_sta_list, *pmlan_ds_sta_list; +#endif + +/** Type definition of mlan_ds_get_info for MLAN_IOCTL_GET_INFO */ +typedef struct _mlan_ds_get_info +{ + /** Sub-command */ + t_u32 sub_command; + + /** Status information parameter */ + union + { + /** Signal information for MLAN_OID_GET_SIGNAL */ + mlan_ds_get_signal signal; + /** Statistics information for MLAN_OID_GET_STATS */ + mlan_ds_get_stats stats; + /** Firmware information for MLAN_OID_GET_FW_INFO */ + mlan_fw_info fw_info; + /** Extended version information for MLAN_OID_GET_VER_EXT */ + mlan_ver_ext ver_ext; + /** BSS information for MLAN_OID_GET_BSS_INFO */ + mlan_bss_info bss_info; + /** Debug information for MLAN_OID_GET_DEBUG_INFO */ + mlan_debug_info debug_info; +#ifdef UAP_SUPPORT + /** UAP Statistics information for MLAN_OID_GET_STATS */ + mlan_ds_uap_stats ustats; + /** UAP station list for MLAN_OID_UAP_STA_LIST */ + mlan_ds_sta_list sta_list; +#endif + } param; +} mlan_ds_get_info, *pmlan_ds_get_info; + +/*-----------------------------------------------------------------*/ +/** Security Configuration Group */ +/*-----------------------------------------------------------------*/ +/** Enumeration for authentication mode */ +enum _mlan_auth_mode +{ + MLAN_AUTH_MODE_OPEN = 0x00, + MLAN_AUTH_MODE_SHARED = 0x01, + MLAN_AUTH_MODE_NETWORKEAP = 0x80, + MLAN_AUTH_MODE_AUTO = 0xFF, +}; + +/** Enumeration for encryption mode */ +enum _mlan_encryption_mode +{ + MLAN_ENCRYPTION_MODE_NONE = 0, + MLAN_ENCRYPTION_MODE_WEP40 = 1, + MLAN_ENCRYPTION_MODE_TKIP = 2, + MLAN_ENCRYPTION_MODE_CCMP = 3, + MLAN_ENCRYPTION_MODE_WEP104 = 4, +}; + +/** Enumeration for PSK */ +enum _mlan_psk_type +{ + MLAN_PSK_PASSPHRASE = 1, + MLAN_PSK_PMK, + MLAN_PSK_CLEAR, + MLAN_PSK_QUERY, +}; + +/** The bit to indicate the key is for unicast */ +#define MLAN_KEY_INDEX_UNICAST 0x40000000 +/** The key index to indicate default key */ +#define MLAN_KEY_INDEX_DEFAULT 0x000000ff +/** Maximum key length */ +// #define MLAN_MAX_KEY_LENGTH 32 +/** Minimum passphrase length */ +#define MLAN_MIN_PASSPHRASE_LENGTH 8 +/** Maximum passphrase length */ +#define MLAN_MAX_PASSPHRASE_LENGTH 63 +/** PMK length */ +#define MLAN_PMK_HEXSTR_LENGTH 64 +/* A few details needed for WEP (Wireless Equivalent Privacy) */ +/** 104 bits */ +#define MAX_WEP_KEY_SIZE 13 +/** 40 bits RC4 - WEP */ +#define MIN_WEP_KEY_SIZE 5 +/** packet number size */ +#define PN_SIZE 16 +/** max seq size of wpa/wpa2 key */ +#define SEQ_MAX_SIZE 8 + +/** key flag for tx_seq */ +#define KEY_FLAG_TX_SEQ_VALID 0x00000001 +/** key flag for rx_seq */ +#define KEY_FLAG_RX_SEQ_VALID 0x00000002 +/** key flag for group key */ +#define KEY_FLAG_GROUP_KEY 0x00000004 +/** key flag for tx and rx */ +#define KEY_FLAG_SET_TX_KEY 0x00000008 +/** key flag for remove key */ +#define KEY_FLAG_REMOVE_KEY 0x80000000 + +/** Type definition of mlan_ds_encrypt_key for MLAN_OID_SEC_CFG_ENCRYPT_KEY */ +typedef struct _mlan_ds_encrypt_key +{ + /** Key disabled, all other fields will be ignore when this flag set to MTRUE */ + t_u32 key_disable; + /** key removed flag, when this flag is set to MTRUE, only key_index will be check */ + t_u32 key_remove; + /** Key index, used as current tx key index when is_current_wep_key is set to MTRUE */ + t_u32 key_index; + /** Current Tx key flag */ + t_u32 is_current_wep_key; + /** Key length */ + t_u32 key_len; + /** Key */ + t_u8 key_material[MLAN_MAX_KEY_LENGTH]; + /** mac address */ + t_u8 mac_addr[MLAN_MAC_ADDR_LENGTH]; + /** wapi key flag */ + t_u32 is_wapi_key; + /** Initial packet number */ + t_u8 pn[PN_SIZE]; + /** key flags */ + t_u32 key_flags; +} mlan_ds_encrypt_key, *pmlan_ds_encrypt_key; + +/** Type definition of mlan_passphrase_t */ +typedef struct _mlan_passphrase_t +{ + /** Length of passphrase */ + t_u32 passphrase_len; + /** Passphrase */ + t_u8 passphrase[MLAN_MAX_PASSPHRASE_LENGTH]; +} mlan_passphrase_t; + +/** Type defnition of mlan_pmk_t */ +typedef struct _mlan_pmk_t +{ + /** PMK */ + t_u8 pmk[MLAN_MAX_KEY_LENGTH]; +} mlan_pmk_t; + +/** Embedded supplicant RSN type: No RSN */ +#define RSN_TYPE_NO_RSN MBIT(0) +/** Embedded supplicant RSN type: WPA */ +#define RSN_TYPE_WPA MBIT(3) +/** Embedded supplicant RSN type: WPA-NONE */ +#define RSN_TYPE_WPANONE MBIT(4) +/** Embedded supplicant RSN type: WPA2 */ +#define RSN_TYPE_WPA2 MBIT(5) +/** Embedded supplicant RSN type: RFU */ +#define RSN_TYPE_VALID_BITS (RSN_TYPE_NO_RSN | RSN_TYPE_WPA | RSN_TYPE_WPANONE | RSN_TYPE_WPA2) + +/** Embedded supplicant cipher type: TKIP */ +#define EMBED_CIPHER_TKIP MBIT(2) +/** Embedded supplicant cipher type: AES */ +#define EMBED_CIPHER_AES MBIT(3) +/** Embedded supplicant cipher type: RFU */ +#define EMBED_CIPHER_VALID_BITS (EMBED_CIPHER_TKIP | EMBED_CIPHER_AES) + +/** Type definition of mlan_ds_passphrase for MLAN_OID_SEC_CFG_PASSPHRASE */ +typedef struct _mlan_ds_passphrase +{ + /** SSID may be used */ + mlan_802_11_ssid ssid; + /** BSSID may be used */ + mlan_802_11_mac_addr bssid; + /** Flag for passphrase or pmk used */ + t_u16 psk_type; + /** Passphrase or PMK */ + union + { + /** Passphrase */ + mlan_passphrase_t passphrase; + /** PMK */ + mlan_pmk_t pmk; + } psk; +} mlan_ds_passphrase, *pmlan_ds_passphrase; + +/** Type definition of mlan_ds_esupp_mode for MLAN_OID_SEC_CFG_ESUPP_MODE */ +typedef struct _mlan_ds_ewpa_mode +{ + /** RSN mode */ + t_u32 rsn_mode; + /** Active pairwise cipher */ + t_u32 act_paircipher; + /** Active pairwise cipher */ + t_u32 act_groupcipher; +} mlan_ds_esupp_mode, *pmlan_ds_esupp_mode; + +/** Type definition of mlan_ds_sec_cfg for MLAN_IOCTL_SEC_CFG */ +typedef struct _mlan_ds_sec_cfg +{ + /** Sub-command */ + t_u32 sub_command; + /** Security configuration parameter */ + union + { + /** Authentication mode for MLAN_OID_SEC_CFG_AUTH_MODE */ + t_u32 auth_mode; + /** Encryption mode for MLAN_OID_SEC_CFG_ENCRYPT_MODE */ + t_u32 encrypt_mode; + /** WPA enabled flag for MLAN_OID_SEC_CFG_WPA_ENABLED */ + t_u32 wpa_enabled; + /** WAPI enabled flag for MLAN_OID_SEC_CFG_WAPI_ENABLED */ + t_u32 wapi_enabled; + /** Port Control enabled flag for MLAN_OID_SEC_CFG_PORT_CTRL */ + t_u32 port_ctrl_enabled; + /** Encryption key for MLAN_OID_SEC_CFG_ENCRYPT_KEY */ + mlan_ds_encrypt_key encrypt_key; + /** Passphrase for MLAN_OID_SEC_CFG_PASSPHRASE */ + mlan_ds_passphrase passphrase; + /** Embedded supplicant WPA enabled flag for MLAN_OID_SEC_CFG_EWPA_ENABLED */ + t_u32 ewpa_enabled; + /** Embedded supplicant mode for MLAN_OID_SEC_CFG_ESUPP_MODE */ + mlan_ds_esupp_mode esupp_mode; + } param; +} mlan_ds_sec_cfg, *pmlan_ds_sec_cfg; + +/*-----------------------------------------------------------------*/ +/** Rate Configuration Group */ +/*-----------------------------------------------------------------*/ +/** Enumeration for rate type */ +enum _mlan_rate_type +{ + MLAN_RATE_INDEX, + MLAN_RATE_VALUE +}; + +/** Enumeration for rate format */ +enum _mlan_rate_format +{ + MLAN_RATE_FORMAT_LG = 0, + MLAN_RATE_FORMAT_HT, + MLAN_RATE_FORMAT_AUTO = 0xFF, +}; +/** Max bitmap rates size */ +#define MAX_BITMAP_RATES_SIZE 10 + +/** Type definition of mlan_rate_cfg_t for MLAN_OID_RATE_CFG */ +typedef struct _mlan_rate_cfg_t +{ + /** Fixed rate: 0, auto rate: 1 */ + t_u32 is_rate_auto; + /** Rate type. 0: index; 1: valude */ + t_u32 rate_type; + /** Rate/MCS index or rate value if fixed rate */ + t_u32 rate; + /** Rate Bitmap */ + t_u16 bitmap_rates[MAX_BITMAP_RATES_SIZE]; +} mlan_rate_cfg_t; + +/** HT channel bandwidth */ +typedef enum _mlan_ht_bw +{ + MLAN_HT_BW20, + MLAN_HT_BW40, +} mlan_ht_bw; + +/** HT guard interval */ +typedef enum _mlan_ht_gi +{ + MLAN_HT_LGI, + MLAN_HT_SGI, +} mlan_ht_gi; + +/** Band and BSS mode */ +typedef struct _mlan_band_data_rate +{ + /** Band configuration */ + t_u8 config_bands; + /** BSS mode (Infra or IBSS) */ + t_u8 bss_mode; +} mlan_band_data_rate; + +/** Type definition of mlan_data_rate for MLAN_OID_GET_DATA_RATE */ +typedef struct _mlan_data_rate +{ + /** Tx data rate */ + t_u32 tx_data_rate; + /** Rx data rate */ + t_u32 rx_data_rate; + + /** Tx channel bandwidth */ + t_u32 tx_ht_bw; + /** Tx guard interval */ + t_u32 tx_ht_gi; + /** Rx channel bandwidth */ + t_u32 rx_ht_bw; + /** Rx guard interval */ + t_u32 rx_ht_gi; +} mlan_data_rate; + +/** Type definition of mlan_ds_rate for MLAN_IOCTL_RATE */ +typedef struct _mlan_ds_rate +{ + /** Sub-command */ + t_u32 sub_command; + /** Rate configuration parameter */ + union + { + /** Rate configuration for MLAN_OID_RATE_CFG */ + mlan_rate_cfg_t rate_cfg; + /** Data rate for MLAN_OID_GET_DATA_RATE */ + mlan_data_rate data_rate; + /** Supported rates for MLAN_OID_SUPPORTED_RATES */ + t_u8 rates[MLAN_SUPPORTED_RATES]; + /** Band/BSS mode for getting supported rates */ + mlan_band_data_rate rate_band_cfg; + } param; +} mlan_ds_rate, *pmlan_ds_rate; + +/*-----------------------------------------------------------------*/ +/** Power Configuration Group */ +/*-----------------------------------------------------------------*/ + +/** Type definition of mlan_power_cfg_t for MLAN_OID_POWER_CFG */ +typedef struct _mlan_power_cfg_t +{ + /** Is power auto */ + t_u32 is_power_auto; + /** Power level in dBm */ + t_u32 power_level; +} mlan_power_cfg_t; + +/** max power table size */ +#define MAX_POWER_TABLE_SIZE 128 + +/** The HT BW40 bit in Tx rate index */ +#define TX_RATE_HT_BW40_BIT MBIT(7) + +/** Type definition of mlan_power_cfg_ext for MLAN_OID_POWER_CFG_EXT */ +typedef struct _mlan_power_cfg_ext +{ + /** Length of power_data */ + t_u32 len; + /** Buffer of power configuration data */ + t_u32 power_data[MAX_POWER_TABLE_SIZE]; +} mlan_power_cfg_ext; + +/** Type definition of mlan_ds_power_cfg for MLAN_IOCTL_POWER_CFG */ +typedef struct _mlan_ds_power_cfg +{ + /** Sub-command */ + t_u32 sub_command; + /** Power configuration parameter */ + union + { + /** Power configuration for MLAN_OID_POWER_CFG */ + mlan_power_cfg_t power_cfg; + /** Extended power configuration for MLAN_OID_POWER_CFG_EXT */ + mlan_power_cfg_ext power_ext; + } param; +} mlan_ds_power_cfg, *pmlan_ds_power_cfg; + +/*-----------------------------------------------------------------*/ +/** Power Management Configuration Group */ +/*-----------------------------------------------------------------*/ +/** Host sleep config conditions : Cancel */ +#define HOST_SLEEP_CFG_CANCEL 0xffffffff + +/** Host sleep config condition: broadcast data */ +#define HOST_SLEEP_COND_BROADCAST_DATA MBIT(0) +/** Host sleep config condition: unicast data */ +#define HOST_SLEEP_COND_UNICAST_DATA MBIT(1) +/** Host sleep config condition: mac event */ +#define HOST_SLEEP_COND_MAC_EVENT MBIT(2) +/** Host sleep config condition: multicast data */ +#define HOST_SLEEP_COND_MULTICAST_DATA MBIT(3) + +/** Host sleep config conditions: Default */ +#define HOST_SLEEP_DEF_COND (HOST_SLEEP_COND_BROADCAST_DATA | HOST_SLEEP_COND_UNICAST_DATA | HOST_SLEEP_COND_MAC_EVENT) +/** Host sleep config GPIO : Default */ +#define HOST_SLEEP_DEF_GPIO 0xff +/** Host sleep config gap : Default */ +#define HOST_SLEEP_DEF_GAP 200 + +/** Type definition of mlan_ds_hs_cfg for MLAN_OID_PM_CFG_HS_CFG */ +typedef struct _mlan_ds_hs_cfg +{ + /** MTRUE to invoke the HostCmd, MFALSE otherwise */ + t_u32 is_invoke_hostcmd; + /** Host sleep config condition */ + /** Bit0: broadcast data + * Bit1: unicast data + * Bit2: mac event + * Bit3: multicast data + */ + t_u32 conditions; + /** GPIO pin or 0xff for interface */ + t_u32 gpio; + /** Gap in milliseconds or or 0xff for special setting when GPIO is used to wakeup host */ + t_u32 gap; +} mlan_ds_hs_cfg, *pmlan_ds_hs_cfg; + +/** Enable deep sleep mode */ +#define DEEP_SLEEP_ON 1 +/** Disable deep sleep mode */ +#define DEEP_SLEEP_OFF 0 + +/** Default idle time in milliseconds for auto deep sleep */ +#define DEEP_SLEEP_IDLE_TIME 100 + +typedef struct _mlan_ds_auto_ds +{ + /** auto ds mode, 0 - disable, 1 - enable */ + t_u16 auto_ds; + /** auto ds idle time in milliseconds */ + t_u16 idletime; +} mlan_ds_auto_ds; + +/** Type definition of mlan_ds_inactivity_to for MLAN_OID_PM_CFG_INACTIVITY_TO */ +typedef struct _mlan_ds_inactivity_to +{ + /** Timeout unit in microsecond, 0 means 1000us (1ms) */ + t_u32 timeout_unit; + /** Inactivity timeout for unicast data */ + t_u32 unicast_timeout; + /** Inactivity timeout for multicast data */ + t_u32 mcast_timeout; + /** Timeout for additional Rx traffic after Null PM1 packet exchange */ + t_u32 ps_entry_timeout; +} mlan_ds_inactivity_to, *pmlan_ds_inactivity_to; + +/** Minimum sleep period in milliseconds */ +#define MIN_SLEEP_PERIOD 10 +/** Maximum sleep period in milliseconds */ +#define MAX_SLEEP_PERIOD 60 +/** Special setting for UPSD certification tests */ +#define SLEEP_PERIOD_RESERVED_FF 0xFF + +/** PS null interval disable */ +#define PS_NULL_DISABLE (-1) + +/** Local listen interval disable */ +#define MRVDRV_LISTEN_INTERVAL_DISABLE (-1) +/** Minimum listen interval */ +#define MRVDRV_MIN_LISTEN_INTERVAL 0 + +/** Minimum multiple DTIM */ +#define MRVDRV_MIN_MULTIPLE_DTIM 0 +/** Maximum multiple DTIM */ +#define MRVDRV_MAX_MULTIPLE_DTIM 5 +/** Ignore multiple DTIM */ +#define MRVDRV_IGNORE_MULTIPLE_DTIM 0xfffe +/** Match listen interval to closest DTIM */ +#define MRVDRV_MATCH_CLOSEST_DTIM 0xfffd + +/** Minimum adhoc awake period */ +#define MIN_ADHOC_AWAKE_PD 0 +/** Maximum adhoc awake period */ +#define MAX_ADHOC_AWAKE_PD 31 +/** Special adhoc awake period */ +#define SPECIAL_ADHOC_AWAKE_PD 255 + +/** Minimum beacon miss timeout in milliseconds */ +#define MIN_BCN_MISS_TO 0 +/** Maximum beacon miss timeout in milliseconds */ +#define MAX_BCN_MISS_TO 50 +/** Disable beacon miss timeout */ +#define DISABLE_BCN_MISS_TO 65535 + +/** Minimum delay to PS in milliseconds */ +#define MIN_DELAY_TO_PS 0 +/** Maximum delay to PS in milliseconds */ +#define MAX_DELAY_TO_PS 65535 +/** Delay to PS unchanged */ +#define DELAY_TO_PS_UNCHANGED (-1) +/** Default delay to PS in milliseconds */ +#define DELAY_TO_PS_DEFAULT 1000 + +/** PS mode: Unchanged */ +#define PS_MODE_UNCHANGED 0 +/** PS mode: Auto */ +#define PS_MODE_AUTO 1 +/** PS mode: Poll */ +#define PS_MODE_POLL 2 +/** PS mode: Null */ +#define PS_MODE_NULL 3 + +/** Type definition of mlan_ds_ps_cfg for MLAN_OID_PM_CFG_PS_CFG */ +typedef struct _mlan_ds_ps_cfg +{ + /** PS null interval in seconds */ + t_u32 ps_null_interval; + /** Multiple DTIM interval */ + t_u32 multiple_dtim_interval; + /** Listen interval */ + t_u32 listen_interval; + /** Adhoc awake period */ + t_u32 adhoc_awake_period; + /** Beacon miss timeout in milliseconds */ + t_u32 bcn_miss_timeout; + /** Delay to PS in milliseconds */ + t_s32 delay_to_ps; + /** PS mode */ + t_u32 ps_mode; +} mlan_ds_ps_cfg, *pmlan_ds_ps_cfg; + +/** Type definition of mlan_ds_sleep_params for MLAN_OID_PM_CFG_SLEEP_PARAMS */ +typedef struct _mlan_ds_sleep_params +{ + /** Error */ + t_u32 error; + /** Offset in microseconds */ + t_u32 offset; + /** Stable time in microseconds */ + t_u32 stable_time; + /** Calibration control */ + t_u32 cal_control; + /** External sleep clock */ + t_u32 ext_sleep_clk; + /** Reserved */ + t_u32 reserved; +} mlan_ds_sleep_params, *pmlan_ds_sleep_params; + +/** sleep_param */ +typedef struct _ps_sleep_param +{ + /** control bitmap */ + t_u32 ctrl_bitmap; + /** minimum sleep period (micro second) */ + t_u32 min_sleep; + /** maximum sleep period (micro second) */ + t_u32 max_sleep; +} ps_sleep_param; + +/** inactivity sleep_param */ +typedef struct _inact_sleep_param +{ + /** inactivity timeout (micro second) */ + t_u32 inactivity_to; + /** miniumu awake period (micro second) */ + t_u32 min_awake; + /** maximum awake period (micro second) */ + t_u32 max_awake; +} inact_sleep_param; + +/** flag for ps mode */ +#define PS_FLAG_PS_MODE 1 +/** flag for sleep param */ +#define PS_FLAG_SLEEP_PARAM 2 +/** flag for inactivity sleep param */ +#define PS_FLAG_INACT_SLEEP_PARAM 4 + +/** Disable power mode */ +#define PS_MODE_DISABLE 0 +/** Enable periodic dtim ps */ +#define PS_MODE_PERIODIC_DTIM 1 +/** Enable inactivity ps */ +#define PS_MODE_INACTIVITY 2 + +/** mlan_ds_ps_mgmt */ +typedef struct _mlan_ds_ps_mgmt +{ + /** flags for valid field */ + t_u16 flags; + /** power mode */ + t_u16 ps_mode; + /** sleep param */ + ps_sleep_param sleep_param; + /** inactivity sleep param */ + inact_sleep_param inact_param; +} mlan_ds_ps_mgmt; + +/** mlan_ds_ps_info */ +typedef struct _mlan_ds_ps_info +{ + /** suspend allowed flag */ + t_u32 is_suspend_allowed; +} mlan_ds_ps_info; + +/** Type definition of mlan_ds_pm_cfg for MLAN_IOCTL_PM_CFG */ +typedef struct _mlan_ds_pm_cfg +{ + /** Sub-command */ + t_u32 sub_command; + /** Power management parameter */ + union + { + /** Power saving mode for MLAN_OID_PM_CFG_IEEE_PS */ + t_u32 ps_mode; + /** Host Sleep configuration for MLAN_OID_PM_CFG_HS_CFG */ + mlan_ds_hs_cfg hs_cfg; + /** Deep sleep mode for MLAN_OID_PM_CFG_DEEP_SLEEP */ + mlan_ds_auto_ds auto_deep_sleep; + /** Inactivity timeout for MLAN_OID_PM_CFG_INACTIVITY_TO */ + mlan_ds_inactivity_to inactivity_to; + /** Sleep period for MLAN_OID_PM_CFG_SLEEP_PD */ + t_u32 sleep_period; + /** PS configuration parameters for MLAN_OID_PM_CFG_PS_CFG */ + mlan_ds_ps_cfg ps_cfg; + /** PS configuration parameters for MLAN_OID_PM_CFG_SLEEP_PARAMS */ + mlan_ds_sleep_params sleep_params; + /** PS configuration parameters for MLAN_OID_PM_CFG_PS_MODE */ + mlan_ds_ps_mgmt ps_mgmt; + /** power info for MLAN_OID_PM_INFO */ + mlan_ds_ps_info ps_info; + } param; +} mlan_ds_pm_cfg, *pmlan_ds_pm_cfg; + +/*-----------------------------------------------------------------*/ +/** WMM Configuration Group */ +/*-----------------------------------------------------------------*/ + +/** WMM TSpec size */ +#define MLAN_WMM_TSPEC_SIZE 63 +/** WMM Add TS extra IE bytes */ +#define MLAN_WMM_ADDTS_EXTRA_IE_BYTES 256 +/** WMM statistics for packets hist bins */ +#define MLAN_WMM_STATS_PKTS_HIST_BINS 7 +/** Maximum number of AC QOS queues available */ +#define MLAN_WMM_MAX_AC_QUEUES 4 + +/** + * @brief IOCTL structure to send an ADDTS request and retrieve the response. + * + * IOCTL structure from the application layer relayed to firmware to + * instigate an ADDTS management frame with an appropriate TSPEC IE as well + * as any additional IEs appended in the ADDTS Action frame. + * + * @sa woal_wmm_addts_req_ioctl + */ +typedef struct +{ + mlan_cmd_result_e cmd_result; /**< Firmware execution result */ + + t_u32 timeout_ms; /**< Timeout value in milliseconds */ + t_u8 ieee_status_code; /**< IEEE status code */ + + t_u32 ie_data_len; /**< Length of ie block in ie_data */ + t_u8 ie_data[MLAN_WMM_TSPEC_SIZE /**< TSPEC to send in the ADDTS */ + + MLAN_WMM_ADDTS_EXTRA_IE_BYTES]; /**< Extra IE buf*/ +} wlan_ioctl_wmm_addts_req_t; + +/** + * @brief IOCTL structure to send a DELTS request. + * + * IOCTL structure from the application layer relayed to firmware to + * instigate an DELTS management frame with an appropriate TSPEC IE. + * + * @sa woal_wmm_delts_req_ioctl + */ +typedef struct +{ + mlan_cmd_result_e cmd_result; /**< Firmware execution result */ + t_u8 ieee_reason_code; /**< IEEE reason code sent, unused for WMM */ + t_u32 ie_data_len; /**< Length of ie block in ie_data */ + t_u8 ie_data[MLAN_WMM_TSPEC_SIZE]; /**< TSPEC to send in the DELTS */ +} wlan_ioctl_wmm_delts_req_t; + +/** + * @brief IOCTL structure to configure a specific AC Queue's parameters + * + * IOCTL structure from the application layer relayed to firmware to + * get, set, or default the WMM AC queue parameters. + * + * - msdu_lifetime_expiry is ignored if set to 0 on a set command + * + * @sa woal_wmm_queue_config_ioctl + */ +typedef struct +{ + mlan_wmm_queue_config_action_e action; /**< Set, Get, or Default */ + mlan_wmm_ac_e access_category; /**< WMM_AC_BK(0) to WMM_AC_VO(3) */ + t_u16 msdu_lifetime_expiry; /**< lifetime expiry in TUs */ + t_u8 supported_rates[10]; /**< Not supported yet */ +} wlan_ioctl_wmm_queue_config_t; + +/** + * @brief IOCTL structure to start, stop, and get statistics for a WMM AC + * + * IOCTL structure from the application layer relayed to firmware to + * start or stop statistical collection for a given AC. Also used to + * retrieve and clear the collected stats on a given AC. + * + * @sa woal_wmm_queue_stats_ioctl + */ +typedef struct +{ + /** Action of Queue Config : Start, Stop, or Get */ + mlan_wmm_queue_stats_action_e action; + /** User Priority */ + t_u8 user_priority; + /** Number of successful packets transmitted */ + t_u16 pkt_count; + /** Packets lost; not included in pkt_count */ + t_u16 pkt_loss; + /** Average Queue delay in microseconds */ + t_u32 avg_queue_delay; + /** Average Transmission delay in microseconds */ + t_u32 avg_tx_delay; + /** Calculated used time in units of 32 microseconds */ + t_u16 used_time; + /** Calculated policed time in units of 32 microseconds */ + t_u16 policed_time; + /** Queue Delay Histogram; number of packets per queue delay range + * + * [0] - 0ms <= delay < 5ms + * [1] - 5ms <= delay < 10ms + * [2] - 10ms <= delay < 20ms + * [3] - 20ms <= delay < 30ms + * [4] - 30ms <= delay < 40ms + * [5] - 40ms <= delay < 50ms + * [6] - 50ms <= delay < msduLifetime (TUs) + */ + t_u16 delay_histogram[MLAN_WMM_STATS_PKTS_HIST_BINS]; +} wlan_ioctl_wmm_queue_stats_t, +/** Type definition of mlan_ds_wmm_queue_stats for MLAN_OID_WMM_CFG_QUEUE_STATS */ + mlan_ds_wmm_queue_stats, *pmlan_ds_wmm_queue_stats; + +/** + * @brief IOCTL sub structure for a specific WMM AC Status + */ +typedef struct +{ + /** WMM Acm */ + t_u8 wmm_acm; + /** Flow required flag */ + t_u8 flow_required; + /** Flow created flag */ + t_u8 flow_created; + /** Disabled flag */ + t_u8 disabled; +} wlan_ioctl_wmm_queue_status_ac_t; + +/** + * @brief IOCTL structure to retrieve the WMM AC Queue status + * + * IOCTL structure from the application layer to retrieve: + * - ACM bit setting for the AC + * - Firmware status (flow required, flow created, flow disabled) + * + * @sa woal_wmm_queue_status_ioctl + */ +typedef struct +{ + /** WMM AC queue status */ + wlan_ioctl_wmm_queue_status_ac_t ac_status[MLAN_WMM_MAX_AC_QUEUES]; +} wlan_ioctl_wmm_queue_status_t, +/** Type definition of mlan_ds_wmm_queue_status for MLAN_OID_WMM_CFG_QUEUE_STATUS */ + mlan_ds_wmm_queue_status, *pmlan_ds_wmm_queue_status; + +/** Type definition of mlan_ds_wmm_addts for MLAN_OID_WMM_CFG_ADDTS */ +typedef struct _mlan_ds_wmm_addts +{ + /** Result of ADDTS request */ + mlan_cmd_result_e result; + /** Timeout value in milliseconds */ + t_u32 timeout; + /** IEEE status code */ + t_u32 status_code; + /** Dialog token */ + t_u8 dialog_tok; + /** TSPEC data length */ + t_u8 ie_data_len; + /** TSPEC to send in the ADDTS + buffering for any extra IEs */ + t_u8 ie_data[MLAN_WMM_TSPEC_SIZE + MLAN_WMM_ADDTS_EXTRA_IE_BYTES]; +} mlan_ds_wmm_addts, *pmlan_ds_wmm_addts; + +/** Type definition of mlan_ds_wmm_delts for MLAN_OID_WMM_CFG_DELTS */ +typedef struct _mlan_ds_wmm_delts +{ + /** Result of DELTS request */ + mlan_cmd_result_e result; + /** IEEE status code */ + t_u32 status_code; + /** TSPEC data length */ + t_u8 ie_data_len; + /** TSPEC to send in the DELTS */ + t_u8 ie_data[MLAN_WMM_TSPEC_SIZE]; +} mlan_ds_wmm_delts, *pmlan_ds_wmm_delts; + +/** Type definition of mlan_ds_wmm_queue_config for MLAN_OID_WMM_CFG_QUEUE_CONFIG */ +typedef struct _mlan_ds_wmm_queue_config +{ + /** Action of Queue Config : Set, Get, or Default */ + mlan_wmm_queue_config_action_e action; + /** WMM Access Category: WMM_AC_BK(0) to WMM_AC_VO(3) */ + mlan_wmm_ac_e access_category; + /** Lifetime expiry in TUs */ + t_u16 msdu_lifetime_expiry; + /** Reserve for future use */ + t_u8 reserved[10]; +} mlan_ds_wmm_queue_config, *pmlan_ds_wmm_queue_config; + +/** Type definition of mlan_ds_wmm_cfg for MLAN_IOCTL_WMM_CFG */ +typedef struct _mlan_ds_wmm_cfg +{ + /** Sub-command */ + t_u32 sub_command; + /** WMM configuration parameter */ + union + { + /** WMM enable for MLAN_OID_WMM_CFG_ENABLE */ + t_u32 wmm_enable; + /** QoS configuration for MLAN_OID_WMM_CFG_QOS */ + t_u8 qos_cfg; + /** WMM add TS for MLAN_OID_WMM_CFG_ADDTS */ + mlan_ds_wmm_addts addts; + /** WMM delete TS for MLAN_OID_WMM_CFG_DELTS */ + mlan_ds_wmm_delts delts; + /** WMM queue configuration for MLAN_OID_WMM_CFG_QUEUE_CONFIG */ + mlan_ds_wmm_queue_config q_cfg; + /** WMM queue status for MLAN_OID_WMM_CFG_QUEUE_STATS */ + mlan_ds_wmm_queue_stats q_stats; + /** WMM queue status for MLAN_OID_WMM_CFG_QUEUE_STATUS */ + mlan_ds_wmm_queue_status q_status; + /** WMM TS status for MLAN_OID_WMM_CFG_TS_STATUS */ + mlan_ds_wmm_ts_status ts_status; + } param; +} mlan_ds_wmm_cfg, *pmlan_ds_wmm_cfg; + +/*-----------------------------------------------------------------*/ +/** WPS Configuration Group */ +/*-----------------------------------------------------------------*/ +/** Enumeration for WPS session */ +enum _mlan_wps_status +{ + MLAN_WPS_CFG_SESSION_START = 1, + MLAN_WPS_CFG_SESSION_END = 0 +}; + +/** Type definition of mlan_ds_wps_cfg for MLAN_IOCTL_WPS_CFG */ +typedef struct _mlan_ds_wps_cfg +{ + /** Sub-command */ + t_u32 sub_command; + /** WPS configuration parameter */ + union + { + /** WPS session for MLAN_OID_WPS_CFG_SESSION */ + t_u32 wps_session; + } param; +} mlan_ds_wps_cfg, *pmlan_ds_wps_cfg; + +/*-----------------------------------------------------------------*/ +/** 802.11n Configuration Group */ +/*-----------------------------------------------------------------*/ +/** Maximum MCS */ +#define NUM_MCS_FIELD 16 + +/** Supported stream modes */ +#define HT_STREAM_MODE_1X1 0x11 +#define HT_STREAM_MODE_2X2 0x22 + +/* Both 2.4G and 5G band selected */ +#define BAND_SELECT_BOTH 0 +/* Band 2.4G selected */ +#define BAND_SELECT_BG 1 +/* Band 5G selected */ +#define BAND_SELECT_A 2 + +/** Type definition of mlan_ds_11n_htcap_cfg for MLAN_OID_11N_HTCAP_CFG */ +typedef struct _mlan_ds_11n_htcap_cfg +{ + /** HT Capability information */ + t_u32 htcap; + /** Band selection */ + t_u32 misc_cfg; + /** Hardware HT cap information required */ + t_u32 hw_cap_req; +} mlan_ds_11n_htcap_cfg, *pmlan_ds_11n_htcap_cfg; + +/** Type definition of mlan_ds_11n_addba_param for MLAN_OID_11N_CFG_ADDBA_PARAM */ +typedef struct _mlan_ds_11n_addba_param +{ + /** Timeout */ + t_u32 timeout; + /** Buffer size for ADDBA request */ + t_u32 txwinsize; + /** Buffer size for ADDBA response */ + t_u32 rxwinsize; + /** amsdu for ADDBA request */ + t_u8 txamsdu; + /** amsdu for ADDBA response */ + t_u8 rxamsdu; +} mlan_ds_11n_addba_param, *pmlan_ds_11n_addba_param; + +/** Type definition of mlan_ds_11n_tx_cfg for MLAN_OID_11N_CFG_TX */ +typedef struct _mlan_ds_11n_tx_cfg +{ + /** HTTxCap */ + t_u16 httxcap; + /** HTTxInfo */ + t_u16 httxinfo; + /** Band selection */ + t_u32 misc_cfg; +} mlan_ds_11n_tx_cfg, *pmlan_ds_11n_tx_cfg; + +/** BF Global Configuration */ +#define BF_GLOBAL_CONFIGURATION 0x00 +/** Performs NDP sounding for PEER specified */ +#define TRIGGER_SOUNDING_FOR_PEER 0x01 +/** TX BF interval for channel sounding */ +#define SET_GET_BF_PERIODICITY 0x02 +/** Tell FW not to perform any sounding for peer */ +#define TX_BF_FOR_PEER_ENBL 0x03 +/** TX BF SNR threshold for peer */ +#define SET_SNR_THR_PEER 0x04 + +/* Maximum number of peer MAC and status/SNR tuples */ +#define MAX_PEER_MAC_TUPLES 10 + +/** Any new subcommand structure should be declare here */ + +/** bf global cfg args */ +typedef struct _mlan_bf_global_cfg_args +{ + /** Global enable/disable bf */ + t_u8 bf_enbl; + /** Global enable/disable sounding */ + t_u8 sounding_enbl; + /** FB Type */ + t_u8 fb_type; + /** SNR Threshold */ + t_u8 snr_threshold; + /** Sounding interval in milliseconds */ + t_u16 sounding_interval; + /** BF mode */ + t_u8 bf_mode; + /** Reserved */ + t_u8 reserved; +} mlan_bf_global_cfg_args; + +/** trigger sounding args */ +typedef struct _mlan_trigger_sound_args +{ + /** Peer MAC address */ + t_u8 peer_mac[MLAN_MAC_ADDR_LENGTH]; + /** Status */ + t_u8 status; +} mlan_trigger_sound_args; + +/** bf periodicity args */ +typedef struct _mlan_bf_periodicity_args +{ + /** Peer MAC address */ + t_u8 peer_mac[MLAN_MAC_ADDR_LENGTH]; + /** Current Tx BF Interval in milliseconds */ + t_u16 interval; + /** Status */ + t_u8 status; +} mlan_bf_periodicity_args; + +/** tx bf peer args */ +typedef struct _mlan_tx_bf_peer_args +{ + /** Peer MAC address */ + t_u8 peer_mac[MLAN_MAC_ADDR_LENGTH]; + /** Reserved */ + t_u16 reserved; + /** Enable/Disable Beamforming */ + t_u8 bf_enbl; + /** Enable/Disable sounding */ + t_u8 sounding_enbl; + /** FB Type */ + t_u8 fb_type; +} mlan_tx_bf_peer_args; + +/** SNR threshold args */ +typedef struct _mlan_snr_thr_args +{ + /** Peer MAC address */ + t_u8 peer_mac[MLAN_MAC_ADDR_LENGTH]; + /** SNR for peer */ + t_u8 snr; +} mlan_snr_thr_args; + +/** Type definition of mlan_ds_11n_tx_bf_cfg for MLAN_OID_11N_CFG_TX_BF_CFG */ +typedef struct _mlan_ds_11n_tx_bf_cfg +{ + /** BF Action */ + t_u16 bf_action; + /** Action */ + t_u16 action; + /** Number of peers */ + t_u32 no_of_peers; + union + { + mlan_bf_global_cfg_args bf_global_cfg; + mlan_trigger_sound_args bf_sound[MAX_PEER_MAC_TUPLES]; + mlan_bf_periodicity_args bf_periodicity[MAX_PEER_MAC_TUPLES]; + mlan_tx_bf_peer_args tx_bf_peer[MAX_PEER_MAC_TUPLES]; + mlan_snr_thr_args bf_snr[MAX_PEER_MAC_TUPLES]; + } body; +} mlan_ds_11n_tx_bf_cfg, *pmlan_ds_11n_tx_bf_cfg; + +/** Type definition of mlan_ds_11n_amsdu_aggr_ctrl for + * MLAN_OID_11N_AMSDU_AGGR_CTRL*/ +typedef struct _mlan_ds_11n_amsdu_aggr_ctrl +{ + /** Enable/Disable */ + t_u16 enable; + /** Current AMSDU size valid */ + t_u16 curr_buf_size; +} mlan_ds_11n_amsdu_aggr_ctrl, *pmlan_ds_11n_amsdu_aggr_ctrl; + +/** Type definition of mlan_ds_11n_aggr_prio_tbl for MLAN_OID_11N_CFG_AGGR_PRIO_TBL */ +typedef struct _mlan_ds_11n_aggr_prio_tbl +{ + /** ampdu priority table */ + t_u8 ampdu[MAX_NUM_TID]; + /** amsdu priority table */ + t_u8 amsdu[MAX_NUM_TID]; +} mlan_ds_11n_aggr_prio_tbl, *pmlan_ds_11n_aggr_prio_tbl; + +/** Type definition of mlan_ds_11n_cfg for MLAN_IOCTL_11N_CFG */ +typedef struct _mlan_ds_11n_cfg +{ + /** Sub-command */ + t_u32 sub_command; + /** 802.11n configuration parameter */ + union + { + /** Tx param for 11n for MLAN_OID_11N_CFG_TX */ + mlan_ds_11n_tx_cfg tx_cfg; + /** Aggr priority table for MLAN_OID_11N_CFG_AGGR_PRIO_TBL */ + mlan_ds_11n_aggr_prio_tbl aggr_prio_tbl; + /** Add BA param for MLAN_OID_11N_CFG_ADDBA_PARAM */ + mlan_ds_11n_addba_param addba_param; + /** Add BA Reject paramters for MLAN_OID_11N_CFG_ADDBA_REJECT */ + t_u8 addba_reject[MAX_NUM_TID]; + /** Tx buf size for MLAN_OID_11N_CFG_MAX_TX_BUF_SIZE */ + t_u32 tx_buf_size; + /** HT cap info configuration for MLAN_OID_11N_HTCAP_CFG */ + mlan_ds_11n_htcap_cfg htcap_cfg; + /** Tx param for 11n for MLAN_OID_11N_AMSDU_AGGR_CTRL */ + mlan_ds_11n_amsdu_aggr_ctrl amsdu_aggr_ctrl; + /** Supported MCS Set field */ + t_u8 supported_mcs_set[NUM_MCS_FIELD]; + /** Transmit Beamforming Capabilities field */ + t_u32 tx_bf_cap; + /** Transmit Beamforming configuration */ + mlan_ds_11n_tx_bf_cfg tx_bf; + /** HT stream configuration */ + t_u32 stream_cfg; + } param; +} mlan_ds_11n_cfg, *pmlan_ds_11n_cfg; + +/** Country code length */ +#define COUNTRY_CODE_LEN 3 + +/*-----------------------------------------------------------------*/ +/** 802.11d Configuration Group */ +/*-----------------------------------------------------------------*/ +/** Maximum subbands for 11d */ +#define MRVDRV_MAX_SUBBAND_802_11D 83 + +#ifdef STA_SUPPORT +/** Data structure for subband set */ +typedef struct _mlan_ds_subband_set_t +{ + /** First channel */ + t_u8 first_chan; + /** Number of channels */ + t_u8 no_of_chan; + /** Maximum Tx power in dBm */ + t_u8 max_tx_pwr; +} mlan_ds_subband_set_t; + +/** Domain regulatory information */ +typedef struct _mlan_ds_11d_domain_info +{ + /** Country Code */ + t_u8 country_code[COUNTRY_CODE_LEN]; + /** Band that channels in sub_band belong to */ + t_u8 band; + /** No. of subband in below */ + t_u8 no_of_sub_band; + /** Subband data to send/last sent */ + mlan_ds_subband_set_t sub_band[MRVDRV_MAX_SUBBAND_802_11D]; +} mlan_ds_11d_domain_info; +#endif + +/** Type definition of mlan_ds_11d_cfg for MLAN_IOCTL_11D_CFG */ +typedef struct _mlan_ds_11d_cfg +{ + /** Sub-command */ + t_u32 sub_command; + /** 802.11d configuration parameter */ + union + { +#ifdef STA_SUPPORT + /** Enable for MLAN_OID_11D_CFG_ENABLE */ + t_u32 enable_11d; + /** Domain info for MLAN_OID_11D_DOMAIN_INFO */ + mlan_ds_11d_domain_info domain_info; +#endif /* STA_SUPPORT */ +#ifdef UAP_SUPPORT + /** tlv data for MLAN_OID_11D_DOMAIN_INFO */ + t_u8 domain_tlv[MAX_IE_SIZE]; +#endif /* UAP_SUPPORT */ + } param; +} mlan_ds_11d_cfg, *pmlan_ds_11d_cfg; + +/*-----------------------------------------------------------------*/ +/** Register Memory Access Group */ +/*-----------------------------------------------------------------*/ +/** Enumeration for register type */ +enum _mlan_reg_type +{ + MLAN_REG_MAC = 1, + MLAN_REG_BBP, + MLAN_REG_RF, + MLAN_REG_CAU = 5, +}; + +/** Type definition of mlan_ds_reg_rw for MLAN_OID_REG_RW */ +typedef struct _mlan_ds_reg_rw +{ + /** Register type */ + t_u32 type; + /** Offset */ + t_u32 offset; + /** Value */ + t_u32 value; +} mlan_ds_reg_rw; + +/** Maximum EEPROM data */ +#define MAX_EEPROM_DATA 256 + +/** Type definition of mlan_ds_read_eeprom for MLAN_OID_EEPROM_RD */ +typedef struct _mlan_ds_read_eeprom +{ + /** Multiples of 4 */ + t_u16 offset; + /** Number of bytes */ + t_u16 byte_count; + /** Value */ + t_u8 value[MAX_EEPROM_DATA]; +} mlan_ds_read_eeprom; + +/** Type definition of mlan_ds_mem_rw for MLAN_OID_MEM_RW */ +typedef struct _mlan_ds_mem_rw +{ + /** Address */ + t_u32 addr; + /** Value */ + t_u32 value; +} mlan_ds_mem_rw; + +/** Type definition of mlan_ds_reg_mem for MLAN_IOCTL_REG_MEM */ +typedef struct _mlan_ds_reg_mem +{ + /** Sub-command */ + t_u32 sub_command; + /** Register memory access parameter */ + union + { + /** Register access for MLAN_OID_REG_RW */ + mlan_ds_reg_rw reg_rw; + /** EEPROM access for MLAN_OID_EEPROM_RD */ + mlan_ds_read_eeprom rd_eeprom; + /** Memory access for MLAN_OID_MEM_RW */ + mlan_ds_mem_rw mem_rw; + } param; +} mlan_ds_reg_mem, *pmlan_ds_reg_mem; + +/*-----------------------------------------------------------------*/ +/** Multi-Radio Configuration Group */ +/*-----------------------------------------------------------------*/ + +/*-----------------------------------------------------------------*/ +/** 802.11h Configuration Group */ +/*-----------------------------------------------------------------*/ +#if defined(DFS_TESTING_SUPPORT) +/** Type definition of mlan_ds_11h_dfs_testing for MLAN_OID_11H_DFS_TESTING */ +typedef struct _mlan_ds_11h_dfs_testing +{ + /** User-configured CAC period in milliseconds, 0 to use default */ + t_u16 usr_cac_period_msec; + /** User-configured NOP period in seconds, 0 to use default */ + t_u16 usr_nop_period_sec; + /** User-configured skip channel change, 0 to disable */ + t_u8 usr_no_chan_change; + /** User-configured fixed channel to change to, 0 to use random channel */ + t_u8 usr_fixed_new_chan; +} mlan_ds_11h_dfs_testing, *pmlan_ds_11h_dfs_testing; +#endif + +/** Type definition of mlan_ds_11h_cfg for MLAN_IOCTL_11H_CFG */ +typedef struct _mlan_ds_11h_cfg +{ + /** Sub-command */ + t_u32 sub_command; + union + { + /** Local power constraint for MLAN_OID_11H_LOCAL_POWER_CONSTRAINT */ + t_s8 usr_local_power_constraint; +#if defined(DFS_TESTING_SUPPORT) + /** User-configuation for MLAN_OID_11H_DFS_TESTING */ + mlan_ds_11h_dfs_testing dfs_testing; +#endif + } param; +} mlan_ds_11h_cfg, *pmlan_ds_11h_cfg; + +/*-----------------------------------------------------------------*/ +/** Miscellaneous Configuration Group */ +/*-----------------------------------------------------------------*/ + +/** CMD buffer size */ +#define MLAN_SIZE_OF_CMD_BUFFER 2048 + +/** LDO Internal */ +#define LDO_INTERNAL 0 +/** LDO External */ +#define LDO_EXTERNAL 1 + +/** Enumeration for IE type */ +enum _mlan_ie_type +{ + MLAN_IE_TYPE_GEN_IE = 0, +#ifdef STA_SUPPORT + MLAN_IE_TYPE_ARP_FILTER, +#endif /* STA_SUPPORT */ +}; + +/** Type definition of mlan_ds_misc_gen_ie for MLAN_OID_MISC_GEN_IE */ +typedef struct _mlan_ds_misc_gen_ie +{ + /** IE type */ + t_u32 type; + /** IE length */ + t_u32 len; + /** IE buffer */ + t_u8 ie_data[MAX_IE_SIZE]; +} mlan_ds_misc_gen_ie; + +#if defined(SDIO_MULTI_PORT_TX_AGGR) || defined(SDIO_MULTI_PORT_RX_AGGR) +/** Type definition of mlan_ds_misc_sdio_mpa_ctrl for MLAN_OID_MISC_SDIO_MPA_CTRL */ +typedef struct _mlan_ds_misc_sdio_mpa_ctrl +{ + /** SDIO MP-A TX enable/disable */ + t_u16 tx_enable; + /** SDIO MP-A RX enable/disable */ + t_u16 rx_enable; + /** SDIO MP-A TX buf size */ + t_u16 tx_buf_size; + /** SDIO MP-A RX buf size */ + t_u16 rx_buf_size; + /** SDIO MP-A TX Max Ports */ + t_u16 tx_max_ports; + /** SDIO MP-A RX Max Ports */ + t_u16 rx_max_ports; +} mlan_ds_misc_sdio_mpa_ctrl; +#endif + +/** Type definition of mlan_ds_misc_cmd for MLAN_OID_MISC_HOST_CMD */ +typedef struct _mlan_ds_misc_cmd +{ + /** Command length */ + t_u32 len; + /** Command buffer */ + t_u8 cmd[MLAN_SIZE_OF_CMD_BUFFER]; +} mlan_ds_misc_cmd; + +/** Maximum number of system clocks */ +#define MLAN_MAX_CLK_NUM 16 + +/** Clock type : Configurable */ +#define MLAN_CLK_CONFIGURABLE 0 +/** Clock type : Supported */ +#define MLAN_CLK_SUPPORTED 1 + +/** Type definition of mlan_ds_misc_sys_clock for MLAN_OID_MISC_SYS_CLOCK */ +typedef struct _mlan_ds_misc_sys_clock +{ + /** Current system clock */ + t_u16 cur_sys_clk; + /** Clock type */ + t_u16 sys_clk_type; + /** Number of clocks */ + t_u16 sys_clk_num; + /** System clocks */ + t_u16 sys_clk[MLAN_MAX_CLK_NUM]; +} mlan_ds_misc_sys_clock; + +/** Enumeration for function init/shutdown */ +enum _mlan_func_cmd +{ + MLAN_FUNC_INIT = 1, + MLAN_FUNC_SHUTDOWN, +}; + +/** Type definition of mlan_ds_misc_tx_datapause for MLAN_OID_MISC_TX_DATAPAUSE */ +typedef struct _mlan_ds_misc_tx_datapause +{ + /** Tx data pause flag */ + t_u16 tx_pause; + /** Max number of Tx buffers for all PS clients */ + t_u16 tx_buf_cnt; +} mlan_ds_misc_tx_datapause; + +/** IP address length */ +#define IPADDR_LEN (16) +/** Max number of ip */ +#define MAX_IPADDR (4) +/** IP address type - IPv4*/ +#define IPADDR_TYPE_IPV4 (1) +/** IP operation remove */ +#define MLAN_IPADDR_OP_IP_REMOVE (0) +/** IP operation ARP filter */ +#define MLAN_IPADDR_OP_ARP_FILTER MBIT(0) +/** IP operation ARP response */ +#define MLAN_IPADDR_OP_AUTO_ARP_RESP MBIT(1) + +/** Type definition of mlan_ds_misc_ipaddr_cfg for MLAN_OID_MISC_IP_ADDR */ +typedef struct _mlan_ds_misc_ipaddr_cfg +{ + /** Operation code */ + t_u32 op_code; + /** IP address type */ + t_u32 ip_addr_type; + /** Number of IP */ + t_u32 ip_addr_num; + /** IP address */ + t_u8 ip_addr[MAX_IPADDR][IPADDR_LEN]; +} mlan_ds_misc_ipaddr_cfg; + +/* MEF configuration disable */ +#define MEF_CFG_DISABLE 0 +/* MEF configuration Rx filter enable */ +#define MEF_CFG_RX_FILTER_ENABLE 1 +/* MEF configuration auto ARP response */ +#define MEF_CFG_AUTO_ARP_RESP 2 +/* MEF configuration host command */ +#define MEF_CFG_HOSTCMD 0xFFFF + +/** Type definition of mlan_ds_misc_mef_cfg for MLAN_OID_MISC_MEF_CFG */ +typedef struct _mlan_ds_misc_mef_cfg +{ + /** Sub-ID for operation */ + t_u32 sub_id; + /** Parameter according to sub-ID */ + union + { + /** MEF command buffer for MEF_CFG_HOSTCMD */ + mlan_ds_misc_cmd cmd_buf; + } param; +} mlan_ds_misc_mef_cfg; + +/** Type definition of mlan_ds_misc_cfp_code for MLAN_OID_MISC_CFP_CODE */ +typedef struct _mlan_ds_misc_cfp_code +{ + /** CFP table code for 2.4GHz */ + t_u32 cfp_code_bg; + /** CFP table code for 5GHz */ + t_u32 cfp_code_a; +} mlan_ds_misc_cfp_code; + +/** Type definition of mlan_ds_misc_country_code for MLAN_OID_MISC_COUNTRY_CODE */ +typedef struct _mlan_ds_misc_country_code +{ + /** Country Code */ + t_u8 country_code[COUNTRY_CODE_LEN]; +} mlan_ds_misc_country_code; + +/** BITMAP for subscribe event rssi low */ +#define SUBSCRIBE_EVT_RSSI_LOW MBIT(0) +/** BITMAP for subscribe event snr low */ +#define SUBSCRIBE_EVT_SNR_LOW MBIT(1) +/** BITMAP for subscribe event max fail */ +#define SUBSCRIBE_EVT_MAX_FAIL MBIT(2) +/** BITMAP for subscribe event beacon missed */ +#define SUBSCRIBE_EVT_BEACON_MISSED MBIT(3) +/** BITMAP for subscribe event rssi high */ +#define SUBSCRIBE_EVT_RSSI_HIGH MBIT(4) +/** BITMAP for subscribe event snr high */ +#define SUBSCRIBE_EVT_SNR_HIGH MBIT(5) +/** BITMAP for subscribe event data rssi low */ +#define SUBSCRIBE_EVT_DATA_RSSI_LOW MBIT(6) +/** BITMAP for subscribe event data snr low */ +#define SUBSCRIBE_EVT_DATA_SNR_LOW MBIT(7) +/** BITMAP for subscribe event data rssi high */ +#define SUBSCRIBE_EVT_DATA_RSSI_HIGH MBIT(8) +/** BITMAP for subscribe event data snr high */ +#define SUBSCRIBE_EVT_DATA_SNR_HIGH MBIT(9) +/** BITMAP for subscribe event link quality */ +#define SUBSCRIBE_EVT_LINK_QUALITY MBIT(10) +/** BITMAP for subscribe event pre_beacon_lost */ +#define SUBSCRIBE_EVT_PRE_BEACON_LOST MBIT(11) +/** default PRE_BEACON_MISS_COUNT */ +#define DEFAULT_PRE_BEACON_MISS 30 + +/** Type definition of mlan_ds_subscribe_evt for MLAN_OID_MISC_CFP_CODE */ +typedef struct _mlan_ds_subscribe_evt +{ + /** bitmap for subscribe event */ + t_u16 evt_bitmap; + /** Absolute value of RSSI threshold value (dBm) */ + t_u8 low_rssi; + /** 0--report once, 1--report everytime happen, N -- report only happend > N consecutive times */ + t_u8 low_rssi_freq; + /** SNR threshold value (dB) */ + t_u8 low_snr; + /** 0--report once, 1--report everytime happen, N -- report only happend > N consecutive times */ + t_u8 low_snr_freq; + /** Failure count threshold */ + t_u8 failure_count; + /** 0--report once, 1--report everytime happen, N -- report only happend > N consecutive times */ + t_u8 failure_count_freq; + /** num of missed beacons */ + t_u8 beacon_miss; + /** 0--report once, 1--report everytime happen, N -- report only happend > N consecutive times */ + t_u8 beacon_miss_freq; + /** Absolute value of RSSI threshold value (dBm) */ + t_u8 high_rssi; + /** 0--report once, 1--report everytime happen, N -- report only happend > N consecutive times */ + t_u8 high_rssi_freq; + /** SNR threshold value (dB) */ + t_u8 high_snr; + /** 0--report once, 1--report everytime happen, N -- report only happend > N consecutive times */ + t_u8 high_snr_freq; + /** Absolute value of data RSSI threshold value (dBm) */ + t_u8 data_low_rssi; + /** 0--report once, 1--report everytime happen, N -- report only happend > N consecutive times */ + t_u8 data_low_rssi_freq; + /** Absolute value of data SNR threshold value (dBm) */ + t_u8 data_low_snr; + /** 0--report once, 1--report everytime happen, N -- report only happend > N consecutive times */ + t_u8 data_low_snr_freq; + /** Absolute value of data RSSI threshold value (dBm) */ + t_u8 data_high_rssi; + /** 0--report once, 1--report everytime happen, N -- report only happend > N consecutive times */ + t_u8 data_high_rssi_freq; + /** Absolute value of data SNR threshold value (dBm) */ + t_u8 data_high_snr; + /** 0--report once, 1--report everytime happen, N -- report only happend > N consecutive times */ + t_u8 data_high_snr_freq; + /* Link SNR threshold (dB) */ + t_u16 link_snr; + /* Link SNR frequency */ + t_u16 link_snr_freq; + /* Second minimum rate value as per the rate table below */ + t_u16 link_rate; + /* Second minimum rate frequency */ + t_u16 link_rate_freq; + /* Tx latency value (us) */ + t_u16 link_tx_latency; + /* Tx latency frequency */ + t_u16 link_tx_lantency_freq; + /* Number of pre missed beacons */ + t_u8 pre_beacon_miss; +} mlan_ds_subscribe_evt; + +/** Max OTP user data length */ +#define MAX_OTP_USER_DATA_LEN 252 + +/** Type definition of mlan_ds_misc_otp_user_data for MLAN_OID_MISC_OTP_USER_DATA */ +typedef struct _mlan_ds_misc_otp_user_data +{ + /** Reserved */ + t_u16 reserved; + /** OTP user data length */ + t_u16 user_data_length; + /** User data buffer */ + t_u8 user_data[MAX_OTP_USER_DATA_LEN]; +} mlan_ds_misc_otp_user_data; + +/** Type definition of mlan_ds_misc_cfg for MLAN_IOCTL_MISC_CFG */ +typedef struct _mlan_ds_misc_cfg +{ + /** Sub-command */ + t_u32 sub_command; + /** Miscellaneous configuration parameter */ + union + { + /** Generic IE for MLAN_OID_MISC_GEN_IE */ + mlan_ds_misc_gen_ie gen_ie; + /** Region code for MLAN_OID_MISC_REGION */ + t_u32 region_code; +#if defined(SDIO_MULTI_PORT_TX_AGGR) || defined(SDIO_MULTI_PORT_RX_AGGR) + /** SDIO MP-A Ctrl command for MLAN_OID_MISC_SDIO_MPA_CTRL */ + mlan_ds_misc_sdio_mpa_ctrl mpa_ctrl; +#endif + /** Hostcmd for MLAN_OID_MISC_HOST_CMD */ + mlan_ds_misc_cmd hostcmd; + /** System clock for MLAN_OID_MISC_SYS_CLOCK */ + mlan_ds_misc_sys_clock sys_clock; + /** WWS set/get for MLAN_OID_MISC_WWS */ + t_u32 wws_cfg; + /** Function init/shutdown for MLAN_OID_MISC_INIT_SHUTDOWN */ + t_u32 func_init_shutdown; + /** Custom IE for MLAN_OID_MISC_CUSTOM_IE */ + mlan_ds_misc_custom_ie cust_ie; + /** Tx data pause for MLAN_OID_MISC_TX_DATAPAUSE */ + mlan_ds_misc_tx_datapause tx_datapause; + /** IP address configuration */ + mlan_ds_misc_ipaddr_cfg ipaddr_cfg; + /** MAC control for MLAN_OID_MISC_MAC_CONTROL */ + t_u32 mac_ctrl; + /** MEF configuration for MLAN_OID_MISC_MEF_CFG */ + mlan_ds_misc_mef_cfg mef_cfg; + /** CFP code for MLAN_OID_MISC_CFP_CODE */ + mlan_ds_misc_cfp_code cfp_code; + /** Country code for MLAN_OID_MISC_COUNTRY_CODE */ + mlan_ds_misc_country_code country_code; + /** Thermal reading for MLAN_OID_MISC_THERMAL */ + t_u32 thermal; + /** Mgmt subtype mask for MLAN_OID_MISC_RX_MGMT_IND */ + t_u32 mgmt_subtype_mask; + /** subscribe event for MLAN_OID_MISC_SUBSCRIBE_EVENT */ + mlan_ds_subscribe_evt subscribe_event; +#ifdef DEBUG_LEVEL1 + /** Driver debug bit masks */ + t_u32 drvdbg; +#endif + mlan_ds_misc_otp_user_data otp_user_data; + } param; +} mlan_ds_misc_cfg, *pmlan_ds_misc_cfg; + +#endif /* !_MLAN_IOCTL_H_ */ diff --git a/drivers/net/wireless/sd8797/mlinux/moal_cfg80211.c b/drivers/net/wireless/sd8797/mlinux/moal_cfg80211.c index 1b04db6b4da0..6b2a01f5c218 100644 --- a/drivers/net/wireless/sd8797/mlinux/moal_cfg80211.c +++ b/drivers/net/wireless/sd8797/mlinux/moal_cfg80211.c @@ -163,6 +163,19 @@ woal_get_wiphy_priv(struct wiphy *wiphy) return (void *) (*(unsigned long *) wiphy_priv(wiphy)); } +/** + * @brief Get the private structure from net device + * + * @param wiphy A pointer to net_device structure + * + * @return Pointer to moal_private + */ +void * +woal_get_netdev_priv(struct net_device *dev) +{ + return (void *) netdev_priv(dev); +} + /** * @brief Set/Enable encryption key * @@ -270,8 +283,12 @@ woal_cfg80211_set_key(moal_private * priv, t_u8 is_enable_wep, } } } else { - sec->param.encrypt_key.key_remove = MTRUE; - sec->param.encrypt_key.key_index = key_index; + if (key_index == KEY_INDEX_CLEAR_ALL) + sec->param.encrypt_key.key_disable = MTRUE; + else { + sec->param.encrypt_key.key_remove = MTRUE; + sec->param.encrypt_key.key_index = key_index; + } sec->param.encrypt_key.key_flags = KEY_FLAG_REMOVE_KEY; if (addr) memcpy(sec->param.encrypt_key.mac_addr, addr, ETH_ALEN); @@ -343,96 +360,30 @@ static int woal_cfg80211_bss_role_cfg(moal_private * priv, t_u16 action, t_u8 * bss_role) { int ret = 0; - mlan_ds_bss *bss = NULL; - mlan_ioctl_req *req = NULL; - struct net_device *dev = priv->netdev; ENTER(); - req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_bss)); - if (req == NULL) { - ret = -ENOMEM; - goto done; - } - bss = (mlan_ds_bss *) req->pbuf; - bss->sub_command = MLAN_OID_BSS_ROLE; - req->req_id = MLAN_IOCTL_BSS; - req->action = action; - bss->param.bss_role = *bss_role; - - if (req->action == MLAN_ACT_SET) { + if (action == MLAN_ACT_SET) { /* Reset interface */ woal_reset_intf(priv, MOAL_IOCTL_WAIT, MFALSE); } - if (MLAN_STATUS_SUCCESS != woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT)) { + + if (MLAN_STATUS_SUCCESS != + woal_bss_role_cfg(priv, action, MOAL_IOCTL_WAIT, bss_role)) { ret = -EFAULT; goto done; } - if (req->action == MLAN_ACT_GET) { - *bss_role = bss->param.bss_role; - } else { - /* Update moal_private */ - priv->bss_role = *bss_role; - if (priv->bss_type == MLAN_BSS_TYPE_UAP) - priv->bss_type = MLAN_BSS_TYPE_STA; - else if (priv->bss_type == MLAN_BSS_TYPE_STA) - priv->bss_type = MLAN_BSS_TYPE_UAP; - + if (action == MLAN_ACT_SET) { /* Initialize private structures */ woal_init_priv(priv, MOAL_IOCTL_WAIT); - if (*bss_role == MLAN_BSS_ROLE_UAP) { - /* Switch: STA -> uAP */ - /* Setup the OS Interface to our functions */ -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,29) - dev->do_ioctl = woal_uap_do_ioctl; - dev->set_multicast_list = woal_uap_set_multicast_list; -#else - dev->netdev_ops = &woal_uap_netdev_ops; -#endif -#ifdef WIRELESS_EXT -#ifdef UAP_WEXT - if (IS_UAP_WEXT(cfg80211_wext)) { -#if WIRELESS_EXT < 21 - dev->get_wireless_stats = woal_get_uap_wireless_stats; -#endif - dev->wireless_handlers = - (struct iw_handler_def *) &woal_uap_handler_def; - init_waitqueue_head(&priv->w_stats_wait_q); - } -#endif /* UAP_WEXT */ -#endif /* WIRELESS_EXT */ - } else if (*bss_role == MLAN_BSS_ROLE_STA) { - /* Switch: uAP -> STA */ - /* Setup the OS Interface to our functions */ -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,29) - dev->do_ioctl = woal_do_ioctl; - dev->set_multicast_list = woal_set_multicast_list; -#else - dev->netdev_ops = &woal_netdev_ops; -#endif -#ifdef WIRELESS_EXT -#ifdef STA_WEXT - if (IS_STA_WEXT(cfg80211_wext)) { -#if WIRELESS_EXT < 21 - dev->get_wireless_stats = woal_get_wireless_stats; -#endif - dev->wireless_handlers = - (struct iw_handler_def *) &woal_handler_def; - init_waitqueue_head(&priv->w_stats_wait_q); - } -#endif /* STA_WEXT */ -#endif - } /* Enable interfaces */ - netif_device_attach(dev); - woal_start_queue(dev); + netif_device_attach(priv->netdev); + woal_start_queue(priv->netdev); } done: - if (req) - kfree(req); LEAVE(); return ret; } @@ -478,8 +429,7 @@ woal_cfg80211_init_p2p_client(moal_private * priv) wifi_direct_mode = WIFI_DIRECT_MODE_DISABLE; if (MLAN_STATUS_SUCCESS != - woal_cfg80211_wifi_direct_mode_cfg(priv, - MLAN_ACT_SET, &wifi_direct_mode)) { + woal_wifi_direct_mode_cfg(priv, MLAN_ACT_SET, &wifi_direct_mode)) { ret = -EFAULT; goto done; } @@ -487,8 +437,7 @@ woal_cfg80211_init_p2p_client(moal_private * priv) /* first, init wifi direct to listen mode */ wifi_direct_mode = WIFI_DIRECT_MODE_LISTEN; if (MLAN_STATUS_SUCCESS != - woal_cfg80211_wifi_direct_mode_cfg(priv, MLAN_ACT_SET, - &wifi_direct_mode)) { + woal_wifi_direct_mode_cfg(priv, MLAN_ACT_SET, &wifi_direct_mode)) { ret = -EFAULT; goto done; } @@ -496,8 +445,7 @@ woal_cfg80211_init_p2p_client(moal_private * priv) /* second, init wifi direct client */ wifi_direct_mode = WIFI_DIRECT_MODE_CLIENT; if (MLAN_STATUS_SUCCESS != - woal_cfg80211_wifi_direct_mode_cfg(priv, - MLAN_ACT_SET, &wifi_direct_mode)) { + woal_wifi_direct_mode_cfg(priv, MLAN_ACT_SET, &wifi_direct_mode)) { ret = -EFAULT; goto done; } @@ -531,8 +479,7 @@ woal_cfg80211_init_p2p_go(moal_private * priv) wifi_direct_mode = WIFI_DIRECT_MODE_DISABLE; if (MLAN_STATUS_SUCCESS != - woal_cfg80211_wifi_direct_mode_cfg(priv, - MLAN_ACT_SET, &wifi_direct_mode)) { + woal_wifi_direct_mode_cfg(priv, MLAN_ACT_SET, &wifi_direct_mode)) { ret = -EFAULT; goto done; } @@ -540,8 +487,7 @@ woal_cfg80211_init_p2p_go(moal_private * priv) /* first, init wifi direct to listen mode */ wifi_direct_mode = WIFI_DIRECT_MODE_LISTEN; if (MLAN_STATUS_SUCCESS != - woal_cfg80211_wifi_direct_mode_cfg(priv, MLAN_ACT_SET, - &wifi_direct_mode)) { + woal_wifi_direct_mode_cfg(priv, MLAN_ACT_SET, &wifi_direct_mode)) { ret = -EFAULT; goto done; } @@ -549,8 +495,7 @@ woal_cfg80211_init_p2p_go(moal_private * priv) /* second, init wifi direct to GO mode */ wifi_direct_mode = WIFI_DIRECT_MODE_GO; if (MLAN_STATUS_SUCCESS != - woal_cfg80211_wifi_direct_mode_cfg(priv, - MLAN_ACT_SET, &wifi_direct_mode)) { + woal_wifi_direct_mode_cfg(priv, MLAN_ACT_SET, &wifi_direct_mode)) { ret = -EFAULT; goto done; } @@ -603,8 +548,7 @@ woal_cfg80211_deinit_p2p(moal_private * priv) /* cancel previous remain on channel */ if (priv->phandle->remain_on_channel) { if (woal_cfg80211_remain_on_channel_cfg - (priv->wdev->wiphy, MOAL_IOCTL_WAIT, MTRUE, &channel_status, NULL, - 0, 0)) { + (priv, MOAL_IOCTL_WAIT, MTRUE, &channel_status, NULL, 0, 0)) { PRINTM(MERROR, "Fail to cancel remain on channel\n"); ret = -EFAULT; goto done; @@ -640,8 +584,7 @@ woal_cfg80211_deinit_p2p(moal_private * priv) wifi_direct_mode = WIFI_DIRECT_MODE_DISABLE; if (MLAN_STATUS_SUCCESS != - woal_cfg80211_wifi_direct_mode_cfg(priv, - MLAN_ACT_SET, &wifi_direct_mode)) { + woal_wifi_direct_mode_cfg(priv, MLAN_ACT_SET, &wifi_direct_mode)) { ret = -EFAULT; goto done; } @@ -670,7 +613,7 @@ woal_cfg80211_change_virtual_intf(struct wiphy *wiphy, struct vif_params *params) { int ret = 0; - moal_private *priv = (moal_private *) woal_get_wiphy_priv(wiphy); + moal_private *priv = (moal_private *) woal_get_netdev_priv(dev); mlan_ds_bss *bss = NULL; mlan_ioctl_req *req = NULL; @@ -687,7 +630,7 @@ woal_cfg80211_change_virtual_intf(struct wiphy *wiphy, if (priv->phandle->remain_on_channel) { t_u8 channel_status; if (woal_cfg80211_remain_on_channel_cfg - (wiphy, MOAL_IOCTL_WAIT, MTRUE, &channel_status, NULL, 0, 0)) { + (priv, MOAL_IOCTL_WAIT, MTRUE, &channel_status, NULL, 0, 0)) { PRINTM(MERROR, "Fail to cancel remain on channel\n"); ret = -EFAULT; goto done; @@ -908,7 +851,7 @@ woal_cfg80211_add_key(struct wiphy *wiphy, struct net_device *netdev, #endif const t_u8 * mac_addr, struct key_params *params) { - moal_private *priv = (moal_private *) woal_get_wiphy_priv(wiphy); + moal_private *priv = (moal_private *) woal_get_netdev_priv(netdev); ENTER(); @@ -945,7 +888,7 @@ woal_cfg80211_del_key(struct wiphy *wiphy, struct net_device *netdev, #endif const t_u8 * mac_addr) { - moal_private *priv = (moal_private *) woal_get_wiphy_priv(wiphy); + moal_private *priv = (moal_private *) woal_get_netdev_priv(netdev); ENTER(); @@ -981,7 +924,7 @@ woal_cfg80211_set_default_key(struct wiphy *wiphy, ) { int ret = 0; - moal_private *priv = (moal_private *) woal_get_wiphy_priv(wiphy); + moal_private *priv = (moal_private *) woal_get_netdev_priv(netdev); mlan_bss_info bss_info; ENTER(); @@ -1019,9 +962,15 @@ woal_cfg80211_set_channel(struct wiphy *wiphy, enum nl80211_channel_type channel_type) { int ret = 0; - moal_private *priv = (moal_private *) woal_get_wiphy_priv(wiphy); + moal_private *priv = NULL; ENTER(); +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,34) || defined(COMPAT_WIRELESS) + if (dev) + priv = woal_get_netdev_priv(dev); + else +#endif + priv = (moal_private *) woal_get_wiphy_priv(wiphy); #ifdef STA_CFG80211 #ifdef STA_SUPPORT if (GET_BSS_ROLE(priv) == MLAN_BSS_ROLE_STA) { @@ -1031,7 +980,7 @@ woal_cfg80211_set_channel(struct wiphy *wiphy, LEAVE(); return -EINVAL; } - ret = woal_set_rf_channel(wiphy, chan, channel_type); + ret = woal_set_rf_channel(priv, chan, channel_type); } #endif #endif @@ -1055,7 +1004,7 @@ woal_cfg80211_mgmt_frame_register(struct wiphy *wiphy, struct net_device *dev, u16 frame_type, bool reg) { - moal_private *priv = (moal_private *) woal_get_wiphy_priv(wiphy); + moal_private *priv = (moal_private *) woal_get_netdev_priv(dev); mlan_status status = MLAN_STATUS_SUCCESS; t_u32 mgmt_subtype_mask = 0x0; static t_u32 last_mgmt_subtype_mask = 0x0; @@ -1112,7 +1061,7 @@ woal_cfg80211_mgmt_tx(struct wiphy *wiphy, #endif u64 * cookie) { - moal_private *priv = (moal_private *) woal_get_wiphy_priv(wiphy); + moal_private *priv = (moal_private *) woal_get_netdev_priv(dev); int ret = 0; pmlan_buffer pmbuf = NULL; mlan_status status = MLAN_STATUS_SUCCESS; @@ -1151,7 +1100,7 @@ woal_cfg80211_mgmt_tx(struct wiphy *wiphy, /** cancel previous remain on channel */ if (priv->phandle->remain_on_channel) { if (woal_cfg80211_remain_on_channel_cfg - (wiphy, MOAL_IOCTL_WAIT, MTRUE, &channel_status, NULL, 0, 0)) { + (priv, MOAL_IOCTL_WAIT, MTRUE, &channel_status, NULL, 0, 0)) { PRINTM(MERROR, "Fail to cancel remain on channel\n"); ret = -EFAULT; goto done; @@ -1171,13 +1120,13 @@ woal_cfg80211_mgmt_tx(struct wiphy *wiphy, duration = MGMT_TX_DEFAULT_WAIT_TIME; if (channel_type_valid) ret = - woal_cfg80211_remain_on_channel_cfg(wiphy, MOAL_IOCTL_WAIT, + woal_cfg80211_remain_on_channel_cfg(priv, MOAL_IOCTL_WAIT, MFALSE, &channel_status, chan, channel_type, duration); else ret = - woal_cfg80211_remain_on_channel_cfg(wiphy, MOAL_IOCTL_WAIT, + woal_cfg80211_remain_on_channel_cfg(priv, MOAL_IOCTL_WAIT, MFALSE, &channel_status, chan, 0, duration); if (ret) { @@ -1261,3 +1210,478 @@ woal_cfg80211_mgmt_tx(struct wiphy *wiphy, LEAVE(); return ret; } + +/** + * @brief Look up specific IE in a buf + * + * @param ie Pointer to IEs + * @param len Total length of ie + * @param id Element id to lookup + * + * @return Pointer of the specific IE -- success, NULL -- fail + */ +const t_u8 * +woal_parse_ie_tlv(const t_u8 * ie, int len, t_u8 id) +{ + int left_len = len; + const t_u8 *pos = ie; + int length; + + /* IE format: | u8 | id | | u8 | len | | var | data | */ + while (left_len >= 2) { + length = *(pos + 1); + if ((*pos == id) && (length + 2) <= left_len) + return pos; + pos += (length + 2); + left_len -= (length + 2); + } + + return NULL; +} + +/** + * @brief This function returns priv + * based on mgmt ie index + * + * @param handle A pointer to moal_handle + * @param index mgmt ie index + * + * @return Pointer to moal_private + */ +static moal_private * +woal_get_priv_by_mgmt_index(moal_handle * handle, t_u16 index) +{ + int i; + + for (i = 0; i < MIN(handle->priv_num, MLAN_MAX_BSS_NUM); i++) { + if (handle->priv[i]) { + if (handle->priv[i]->probereq_index == index) + return (handle->priv[i]); + } + } + return NULL; +} + +/** + * @brief Add custom ie to mgmt frames. + * + * @param priv A pointer to moal private structure + * @param beacon_ies_data Beacon ie + * @param beacon_index The index for beacon when auto index + * @param proberesp_ies_data Probe resp ie + * @param proberesp_index The index for probe resp when auto index + * @param assocresp_ies_data Assoc resp ie + * @param assocresp_index The index for assoc resp when auto index + * @param probereq_ies_data Probe req ie + * @param probereq_index The index for probe req when auto index * + * + * @return 0 -- success, otherwise fail + */ +static int +woal_cfg80211_custom_ie(moal_private * priv, + custom_ie * beacon_ies_data, t_u16 * beacon_index, + custom_ie * proberesp_ies_data, t_u16 * proberesp_index, + custom_ie * assocresp_ies_data, t_u16 * assocresp_index, + custom_ie * probereq_ies_data, t_u16 * probereq_index) +{ + mlan_ioctl_req *ioctl_req = NULL; + mlan_ds_misc_cfg *misc = NULL; + mlan_ds_misc_custom_ie *custom_ie = NULL; + t_u8 *pos = NULL; + t_u16 len = 0; + int ret = 0; + + ENTER(); + + if (!(custom_ie = kmalloc(sizeof(mlan_ds_misc_custom_ie), GFP_KERNEL))) { + ret = -ENOMEM; + goto done; + } + + memset(custom_ie, 0x00, sizeof(mlan_ds_misc_custom_ie)); + custom_ie->type = TLV_TYPE_MGMT_IE; + + pos = (t_u8 *) custom_ie->ie_data_list; + if (beacon_ies_data) { + len = sizeof(*beacon_ies_data) - MAX_IE_SIZE + + beacon_ies_data->ie_length; + memcpy(pos, beacon_ies_data, len); + pos += len; + custom_ie->len += len; + } + + if (proberesp_ies_data) { + len = sizeof(*proberesp_ies_data) - MAX_IE_SIZE + + proberesp_ies_data->ie_length; + memcpy(pos, proberesp_ies_data, len); + pos += len; + custom_ie->len += len; + } + + if (assocresp_ies_data) { + len = sizeof(*assocresp_ies_data) - MAX_IE_SIZE + + assocresp_ies_data->ie_length; + memcpy(pos, assocresp_ies_data, len); + custom_ie->len += len; + } + + if (probereq_ies_data) { + len = sizeof(*probereq_ies_data) - MAX_IE_SIZE + + probereq_ies_data->ie_length; + memcpy(pos, probereq_ies_data, len); + pos += len; + custom_ie->len += len; + } + + ioctl_req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_misc_cfg)); + if (ioctl_req == NULL) { + ret = -ENOMEM; + goto done; + } + + misc = (mlan_ds_misc_cfg *) ioctl_req->pbuf; + misc->sub_command = MLAN_OID_MISC_CUSTOM_IE; + ioctl_req->req_id = MLAN_IOCTL_MISC_CFG; + ioctl_req->action = MLAN_ACT_SET; + + memcpy(&misc->param.cust_ie, custom_ie, sizeof(mlan_ds_misc_custom_ie)); + + if (MLAN_STATUS_SUCCESS != + woal_request_ioctl(priv, ioctl_req, MOAL_IOCTL_WAIT)) { + ret = -EFAULT; + goto done; + } + + /* get the assigned index */ + pos = (t_u8 *) (&misc->param.cust_ie.ie_data_list[0].ie_index); + if (beacon_ies_data && beacon_ies_data->ie_length + && beacon_ies_data->ie_index == MLAN_CUSTOM_IE_AUTO_IDX_MASK) { + /* save beacon ie index after auto-indexing */ + *beacon_index = misc->param.cust_ie.ie_data_list[0].ie_index; + len = sizeof(*beacon_ies_data) - MAX_IE_SIZE + + beacon_ies_data->ie_length; + pos += len; + } + + if (proberesp_ies_data && proberesp_ies_data->ie_length + && proberesp_ies_data->ie_index == MLAN_CUSTOM_IE_AUTO_IDX_MASK) { + /* save probe resp ie index after auto-indexing */ + *proberesp_index = *((t_u16 *) pos); + len = sizeof(*proberesp_ies_data) - MAX_IE_SIZE + + proberesp_ies_data->ie_length; + pos += len; + } + + if (assocresp_ies_data && assocresp_ies_data->ie_length + && assocresp_ies_data->ie_index == MLAN_CUSTOM_IE_AUTO_IDX_MASK) { + /* save assoc resp ie index after auto-indexing */ + *assocresp_index = *((t_u16 *) pos); + len = sizeof(*assocresp_ies_data) - MAX_IE_SIZE + + assocresp_ies_data->ie_length; + pos += len; + } + if (probereq_ies_data && probereq_ies_data->ie_length + && probereq_ies_data->ie_index == MLAN_CUSTOM_IE_AUTO_IDX_MASK) { + /* save probe resp ie index after auto-indexing */ + *probereq_index = *((t_u16 *) pos); + len = sizeof(*probereq_ies_data) - MAX_IE_SIZE + + probereq_ies_data->ie_length; + pos += len; + } + + if (ioctl_req->status_code == MLAN_ERROR_IOCTL_FAIL) + ret = -EFAULT; + + done: + if (ioctl_req) + kfree(ioctl_req); + if (custom_ie) + kfree(custom_ie); + LEAVE(); + return ret; +} + +/** + * @brief Filter specific IE in ie buf + * + * @param ie Pointer to IEs + * @param len Total length of ie + * @param ie_out Pointer to out IE buf + * + * @return out IE length + */ +static t_u16 +woal_filter_beacon_ies(const t_u8 * ie, int len, t_u8 * ie_out) +{ + int left_len = len; + const t_u8 *pos = ie; + int length; + t_u8 id = 0; + t_u16 out_len = 0; + + /* ERP_INFO and RSN IE will be fileter out */ + while (left_len >= 2) { + length = *(pos + 1); + id = *pos; + if ((length + 2) > left_len) + break; + switch (id) { + case WLAN_EID_ERP_INFO: + case RSN_IE: + break; + default: + memcpy(ie_out + out_len, pos, length + 2); + out_len += length + 2; + break; + } + pos += (length + 2); + left_len -= (length + 2); + } + return out_len; +} + +/** + * @brief config AP or GO for mgmt frame ies. + * + * @param priv A pointer to moal private structure + * @param beacon_ies A pointer to beacon ies + * @param beacon_ies_len Beacon ies length + * @param proberesp_ies A pointer to probe resp ies + * @param proberesp_ies_len Probe resp ies length + * @param assocresp_ies A pointer to probe resp ies + * @param assocresp_ies_len Assoc resp ies length + * @param probereq_ies A pointer to probe req ies + * @param probereq_ies_len Probe req ies length * + * @param mask Mgmt frame mask + * + * @return 0 -- success, otherwise fail + */ +int +woal_cfg80211_mgmt_frame_ie(moal_private * priv, + const t_u8 * beacon_ies, size_t beacon_ies_len, + const t_u8 * proberesp_ies, + size_t proberesp_ies_len, + const t_u8 * assocresp_ies, + size_t assocresp_ies_len, const t_u8 * probereq_ies, + size_t probereq_ies_len, t_u16 mask) +{ + int ret = 0; + t_u8 *pos = NULL; + custom_ie *beacon_ies_data = NULL; + custom_ie *proberesp_ies_data = NULL; + custom_ie *assocresp_ies_data = NULL; + custom_ie *probereq_ies_data = NULL; + + /* static variables for mgmt frame ie auto-indexing */ + static t_u16 beacon_index = MLAN_CUSTOM_IE_AUTO_IDX_MASK; + static t_u16 proberesp_index = MLAN_CUSTOM_IE_AUTO_IDX_MASK; + static t_u16 assocresp_index = MLAN_CUSTOM_IE_AUTO_IDX_MASK; + static t_u16 probereq_index = MLAN_CUSTOM_IE_AUTO_IDX_MASK; + moal_private *pmpriv = NULL; + static t_u16 rsn_index = MLAN_CUSTOM_IE_AUTO_IDX_MASK; + const t_u8 *rsn_ie; + + ENTER(); + + if (mask & MGMT_MASK_BEACON) { + if (!(beacon_ies_data = kmalloc(sizeof(custom_ie), GFP_KERNEL))) { + ret = -ENOMEM; + goto done; + } + if (beacon_ies && beacon_ies_len) { + rsn_ie = + woal_parse_ie_tlv((t_u8 *) beacon_ies, (int) beacon_ies_len, + RSN_IE); + if (rsn_ie) { + beacon_ies_data->ie_index = rsn_index; + beacon_ies_data->mgmt_subtype_mask = + MGMT_MASK_BEACON | MGMT_MASK_PROBE_RESP | + MGMT_MASK_ASSOC_RESP; + beacon_ies_data->ie_length = rsn_ie[1] + 2; + memcpy(beacon_ies_data->ie_buffer, rsn_ie, rsn_ie[1] + 2); + if (MLAN_STATUS_SUCCESS != + woal_cfg80211_custom_ie(priv, beacon_ies_data, &rsn_index, + NULL, &proberesp_index, NULL, + &assocresp_index, NULL, + &probereq_index)) { + ret = -EFAULT; + goto done; + } + } + } else { + /* clear rsn_ie */ + if (rsn_index <= MAX_MGMT_IE_INDEX) { + beacon_ies_data->ie_index = rsn_index; + beacon_ies_data->mgmt_subtype_mask = MLAN_CUSTOM_IE_DELETE_MASK; + beacon_ies_data->ie_length = 0; + rsn_index = MLAN_CUSTOM_IE_AUTO_IDX_MASK; + if (MLAN_STATUS_SUCCESS != + woal_cfg80211_custom_ie(priv, beacon_ies_data, &rsn_index, + NULL, &proberesp_index, NULL, + &assocresp_index, NULL, + &probereq_index)) { + ret = -EFAULT; + goto done; + } + } + } + } + + if (mask & MGMT_MASK_PROBE_RESP) { + if (!(proberesp_ies_data = kmalloc(sizeof(custom_ie), GFP_KERNEL))) { + ret = -ENOMEM; + goto done; + } + } + + if (mask & MGMT_MASK_ASSOC_RESP) { + if (!(assocresp_ies_data = kmalloc(sizeof(custom_ie), GFP_KERNEL))) { + ret = -ENOMEM; + goto done; + } + } + if (mask & MGMT_MASK_PROBE_REQ) { + if (!(probereq_ies_data = kmalloc(sizeof(custom_ie), GFP_KERNEL))) { + ret = -ENOMEM; + goto done; + } + } + + if (beacon_ies_data) { + memset(beacon_ies_data, 0x00, sizeof(custom_ie)); + if (beacon_ies && beacon_ies_len) { + /* set the beacon ies */ + beacon_ies_data->ie_index = beacon_index; + beacon_ies_data->mgmt_subtype_mask = MGMT_MASK_BEACON; + beacon_ies_data->mgmt_subtype_mask |= MGMT_MASK_ASSOC_RESP; + beacon_ies_data->ie_length = woal_filter_beacon_ies(beacon_ies, + beacon_ies_len, + beacon_ies_data-> + ie_buffer); + } else { + /* clear the beacon ies */ + if (beacon_index > MAX_MGMT_IE_INDEX) { + PRINTM(MERROR, "Invalid beacon index for mgmt frame ie.\n"); + goto done; + } + + beacon_ies_data->ie_index = beacon_index; + beacon_ies_data->mgmt_subtype_mask = MLAN_CUSTOM_IE_DELETE_MASK; + beacon_ies_data->ie_length = 0; + beacon_index = MLAN_CUSTOM_IE_AUTO_IDX_MASK; + } + } + + if (proberesp_ies_data) { + memset(proberesp_ies_data, 0x00, sizeof(custom_ie)); + if (proberesp_ies && proberesp_ies_len) { + /* set the probe response ies */ + // proberesp_ies_data->ie_index = MLAN_CUSTOM_IE_AUTO_IDX_MASK; + proberesp_ies_data->ie_index = proberesp_index; + proberesp_ies_data->mgmt_subtype_mask = MGMT_MASK_PROBE_RESP; + proberesp_ies_data->ie_length = proberesp_ies_len; + pos = proberesp_ies_data->ie_buffer; + memcpy(pos, proberesp_ies, proberesp_ies_len); + } else { + /* clear the probe response ies */ + if (proberesp_index > MAX_MGMT_IE_INDEX) { + PRINTM(MERROR, "Invalid probe resp index for mgmt frame ie.\n"); + goto done; + } + + proberesp_ies_data->ie_index = proberesp_index; + proberesp_ies_data->mgmt_subtype_mask = MLAN_CUSTOM_IE_DELETE_MASK; + proberesp_ies_data->ie_length = 0; + proberesp_index = MLAN_CUSTOM_IE_AUTO_IDX_MASK; + } + } + if (assocresp_ies_data) { + memset(assocresp_ies_data, 0x00, sizeof(custom_ie)); + if (assocresp_ies && assocresp_ies_len) { + /* set the assoc response ies */ + assocresp_ies_data->ie_index = assocresp_index; + assocresp_ies_data->mgmt_subtype_mask = MGMT_MASK_ASSOC_RESP; + assocresp_ies_data->ie_length = assocresp_ies_len; + pos = assocresp_ies_data->ie_buffer; + memcpy(pos, assocresp_ies, assocresp_ies_len); + } else { + /* clear the assoc response ies */ + if (assocresp_index > MAX_MGMT_IE_INDEX) { + PRINTM(MERROR, "Invalid assoc resp index for mgmt frame ie.\n"); + goto done; + } + + assocresp_ies_data->ie_index = assocresp_index; + assocresp_ies_data->mgmt_subtype_mask = MLAN_CUSTOM_IE_DELETE_MASK; + assocresp_ies_data->ie_length = 0; + assocresp_index = MLAN_CUSTOM_IE_AUTO_IDX_MASK; + } + } + + if (probereq_ies_data) { + memset(probereq_ies_data, 0x00, sizeof(custom_ie)); + if ((probereq_index != MLAN_CUSTOM_IE_AUTO_IDX_MASK) && + (priv->probereq_index != probereq_index)) { + pmpriv = woal_get_priv_by_mgmt_index(priv->phandle, probereq_index); + if (pmpriv) { + probereq_ies_data->ie_index = probereq_index; + probereq_ies_data->mgmt_subtype_mask = + MLAN_CUSTOM_IE_DELETE_MASK; + probereq_ies_data->ie_length = 0; + probereq_index = MLAN_CUSTOM_IE_AUTO_IDX_MASK; + pmpriv->probereq_index = MLAN_CUSTOM_IE_AUTO_IDX_MASK; + if (MLAN_STATUS_SUCCESS != + woal_cfg80211_custom_ie(pmpriv, NULL, &beacon_index, + NULL, &proberesp_index, + NULL, &assocresp_index, + probereq_ies_data, + &probereq_index)) { + ret = -EFAULT; + goto done; + } + memset(probereq_ies_data, 0x00, sizeof(custom_ie)); + } + } + if (probereq_ies && probereq_ies_len) { + /* set the probe req ies */ + probereq_ies_data->ie_index = probereq_index; + probereq_ies_data->mgmt_subtype_mask = MGMT_MASK_PROBE_REQ; + probereq_ies_data->ie_length = probereq_ies_len; + pos = probereq_ies_data->ie_buffer; + memcpy(pos, probereq_ies, probereq_ies_len); + } else { + /* clear the probe req ies */ + if (probereq_index > MAX_MGMT_IE_INDEX) { + PRINTM(MERROR, "Invalid probe resp index for mgmt frame ie.\n"); + goto done; + } + probereq_ies_data->ie_index = probereq_index; + probereq_ies_data->mgmt_subtype_mask = MLAN_CUSTOM_IE_DELETE_MASK; + probereq_ies_data->ie_length = 0; + probereq_index = MLAN_CUSTOM_IE_AUTO_IDX_MASK; + } + } + + if (MLAN_STATUS_SUCCESS != + woal_cfg80211_custom_ie(priv, beacon_ies_data, &beacon_index, + proberesp_ies_data, &proberesp_index, + assocresp_ies_data, &assocresp_index, + probereq_ies_data, &probereq_index)) { + ret = -EFAULT; + goto done; + } + if (probereq_ies_data) + priv->probereq_index = probereq_index; + + done: + if (beacon_ies_data) + kfree(beacon_ies_data); + if (proberesp_ies_data) + kfree(proberesp_ies_data); + if (assocresp_ies_data) + kfree(assocresp_ies_data); + + LEAVE(); + + return ret; +} diff --git a/drivers/net/wireless/sd8797/mlinux/moal_cfg80211.h b/drivers/net/wireless/sd8797/mlinux/moal_cfg80211.h index e1683ed08a89..f58fc18829fa 100644 --- a/drivers/net/wireless/sd8797/mlinux/moal_cfg80211.h +++ b/drivers/net/wireless/sd8797/mlinux/moal_cfg80211.h @@ -24,8 +24,11 @@ #include "moal_main.h" +/* Clear all key indexes */ +#define KEY_INDEX_CLEAR_ALL (0x0000000F) + /** RTS/FRAG disabled value */ -#define MLAN_FRAG_RTS_DISABLED (0xFFFFFFFF) +#define MLAN_FRAG_RTS_DISABLED (0xFFFFFFFF) #ifndef WLAN_CIPHER_SUITE_WAPI #define WLAN_CIPHER_SUITE_WAPI 0x00000020 @@ -55,6 +58,9 @@ static const void *const mrvl_wiphy_privid = &mrvl_wiphy_privid; /* Get the private structure from wiphy */ void *woal_get_wiphy_priv(struct wiphy *wiphy); +/* Get the private structure from net device */ +void *woal_get_netdev_priv(struct net_device *dev); + int woal_cfg80211_change_virtual_intf(struct wiphy *wiphy, struct net_device *dev, enum nl80211_iftype type, @@ -78,7 +84,7 @@ int woal_cfg80211_del_key(struct wiphy *wiphy, #ifdef STA_CFG80211 #ifdef STA_SUPPORT -int woal_set_rf_channel(struct wiphy *wiphy, +int woal_set_rf_channel(moal_private * priv, struct ieee80211_channel *chan, enum nl80211_channel_type channel_type); mlan_status woal_inform_bss_from_scan_result(moal_private * priv, @@ -149,7 +155,7 @@ int woal_cfg80211_del_virtual_intf(struct wiphy *wiphy, struct net_device *dev); #if defined(WIFI_DIRECT_SUPPORT) /** Define kernel version for wifi direct */ #if !defined(COMPAT_WIRELESS) -#define WIFI_DIRECT_KERNEL_VERSION KERNEL_VERSION(3,0,0) +#define WIFI_DIRECT_KERNEL_VERSION KERNEL_VERSION(2,6,39) #else #define WIFI_DIRECT_KERNEL_VERSION KERNEL_VERSION(2,6,33) #endif /* COMPAT_WIRELESS */ @@ -173,7 +179,7 @@ int woal_cfg80211_init_p2p_go(moal_private * priv); int woal_cfg80211_deinit_p2p(moal_private * priv); -int woal_cfg80211_remain_on_channel_cfg(struct wiphy *wiphy, +int woal_cfg80211_remain_on_channel_cfg(moal_private * priv, t_u8 wait_option, t_u8 remove, t_u8 * status, struct ieee80211_channel *chan, @@ -184,6 +190,8 @@ int woal_uap_cfg80211_get_station(struct wiphy *wiphy, struct net_device *dev, #endif /* KERNEL_VERSION */ #endif /* WIFI_DIRECT_SUPPORT && V14_FEATURE */ +const t_u8 *woal_parse_ie_tlv(const t_u8 * ie, int len, t_u8 id); + int woal_cfg80211_mgmt_frame_ie(moal_private * priv, const t_u8 * beacon_ies, size_t beacon_ies_len, const t_u8 * proberesp_ies, diff --git a/drivers/net/wireless/sd8797/mlinux/moal_eth_ioctl.c b/drivers/net/wireless/sd8797/mlinux/moal_eth_ioctl.c index 2282216f7d55..31040a29ceec 100644 --- a/drivers/net/wireless/sd8797/mlinux/moal_eth_ioctl.c +++ b/drivers/net/wireless/sd8797/mlinux/moal_eth_ioctl.c @@ -50,10 +50,29 @@ Change log: #define PRIV_CMD_BANDCFG "bandcfg" /** Private command: Host cmd */ #define PRIV_CMD_HOSTCMD "hostcmd" +/** Private command: Custom IE config*/ +#define PRIV_CMD_CUSTOMIE "customie" /** Private command: HT Tx Cfg */ #define PRIV_CMD_HTTXCFG "httxcfg" #define PRIV_CMD_DATARATE "getdatarate" #define PRIV_CMD_TXRATECFG "txratecfg" +#define PRIV_CMD_ESUPPMODE "esuppmode" +#define PRIV_CMD_PASSPHRASE "passphrase" +#define PRIV_CMD_DEAUTH "deauth" +#if defined(WIFI_DIRECT_SUPPORT) +#if defined(STA_SUPPORT) && defined(UAP_SUPPORT) +#define PRIV_CMD_BSSROLE "bssrole" +#endif +#endif +#ifdef STA_SUPPORT +#define PRIV_CMD_SETUSERSCAN "setuserscan" +#endif +#define PRIV_CMD_DEEPSLEEP "deepsleep" +#define PRIV_CMD_IPADDR "ipaddr" +#define PRIV_CMD_WPSSESSION "wpssession" +#define PRIV_CMD_OTPUSERDATA "otpuserdata" +#define PRIV_CMD_COUNTRYCODE "countrycode" +#define PRIV_CMD_TCPACKENH "tcpackenh" /** Bands supported in Infra mode */ static t_u8 SupportedInfraBand[] = { @@ -76,6 +95,17 @@ static t_u8 SupportedAdhocBand[] = { /******************************************************** Global Variables ********************************************************/ +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,29) +#ifdef UAP_SUPPORT +/** Network device handlers for uAP */ +extern const struct net_device_ops woal_uap_netdev_ops; +#endif +#ifdef STA_SUPPORT +/** Network device handlers for STA */ +extern const struct net_device_ops woal_netdev_ops; +#endif +#endif +extern int cfg80211_wext; /******************************************************** Local Functions @@ -85,7 +115,7 @@ static t_u8 SupportedAdhocBand[] = { * * @param pos Pointer to the arguments string * @param data Pointer to the arguments buffer - * @param len Pointer to the number of arguments extracted + * @param user_data_len Pointer to the number of arguments extracted * * @return MLAN_STATUS_SUCCESS * @@ -246,7 +276,6 @@ woal_get_priv_driver_version(moal_private * priv, t_u8 * respbuf, return ret; } -#ifdef WIFI_DIRECT_SUPPORT /** * @brief Hostcmd interface from application * @@ -296,8 +325,12 @@ woal_priv_hostcmd(moal_private * priv, t_u8 * respbuf, t_u32 respbuflen) ret = -EFAULT; goto error; } - sprintf(respbuf, "OK"); - ret = 3; + memcpy(data_ptr + sizeof(buf_len), misc_cfg->param.hostcmd.cmd, + misc_cfg->param.hostcmd.len); + ret = + misc_cfg->param.hostcmd.len + sizeof(buf_len) + strlen(CMD_MARVELL) + + strlen(PRIV_CMD_HOSTCMD); + memcpy(data_ptr, (t_u8 *) & ret, sizeof(t_u32)); error: if (req) @@ -306,7 +339,65 @@ woal_priv_hostcmd(moal_private * priv, t_u8 * respbuf, t_u32 respbuflen) LEAVE(); return ret; } -#endif + +/** + * @brief Custom IE setting + * + * @param priv A pointer to moal_private structure + * @param respbuf A pointer to response buffer + * @param respbuflen Available length of response buffer + * + * @return Number of bytes written, negative for failure. + */ +int +woal_priv_customie(moal_private * priv, t_u8 * respbuf, t_u32 respbuflen) +{ + int ret = 0; + t_u8 *data_ptr; + mlan_ioctl_req *ioctl_req = NULL; + mlan_ds_misc_cfg *misc = NULL; + mlan_ds_misc_custom_ie *custom_ie = NULL; + + ENTER(); + data_ptr = respbuf + (strlen(CMD_MARVELL) + strlen(PRIV_CMD_CUSTOMIE)); + + custom_ie = (mlan_ds_misc_custom_ie *) data_ptr; + ioctl_req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_misc_cfg)); + if (ioctl_req == NULL) { + ret = -ENOMEM; + goto done; + } + + misc = (mlan_ds_misc_cfg *) ioctl_req->pbuf; + misc->sub_command = MLAN_OID_MISC_CUSTOM_IE; + ioctl_req->req_id = MLAN_IOCTL_MISC_CFG; + if ((custom_ie->len == 0) || + (custom_ie->len == sizeof(custom_ie->ie_data_list[0].ie_index))) + ioctl_req->action = MLAN_ACT_GET; + else + ioctl_req->action = MLAN_ACT_SET; + + memcpy(&misc->param.cust_ie, custom_ie, sizeof(mlan_ds_misc_custom_ie)); + + if (MLAN_STATUS_SUCCESS != + woal_request_ioctl(priv, ioctl_req, MOAL_IOCTL_WAIT)) { + ret = -EFAULT; + goto done; + } + custom_ie = (mlan_ds_misc_custom_ie *) data_ptr; + memcpy(custom_ie, &misc->param.cust_ie, sizeof(mlan_ds_misc_custom_ie)); + ret = sizeof(mlan_ds_misc_custom_ie); + if (ioctl_req->status_code == MLAN_ERROR_IOCTL_FAIL) { + /* send a separate error code to indicate error from driver */ + ret = EFAULT; + } + done: + if (ioctl_req) { + kfree(ioctl_req); + } + LEAVE(); + return ret; +} /** * @brief Set/Get Band and Adhoc-band setting @@ -728,129 +819,1042 @@ woal_setget_priv_txratecfg(moal_private * priv, t_u8 * respbuf, } /** - * @brief Set priv command for Android - * @param dev A pointer to net_device structure - * @param req A pointer to ifreq structure + * @brief Set/Get esupplicant mode configurations * - * @return 0 --success, otherwise fail + * @param priv A pointer to moal_private structure + * @param respbuf A pointer to response buffer + * @param respbuflen Available length of response buffer + * + * @return Number of bytes written, negative for failure. */ int -woal_android_priv_cmd(struct net_device *dev, struct ifreq *req) +woal_setget_priv_esuppmode(moal_private * priv, t_u8 * respbuf, + t_u32 respbuflen) { + t_u32 data[3]; + mlan_ioctl_req *req = NULL; + mlan_ds_sec_cfg *sec = NULL; + woal_esuppmode_cfg *esupp_mode = NULL; int ret = 0; - android_wifi_priv_cmd priv_cmd; - moal_private *priv = (moal_private *) netdev_priv(dev); - char *buf = NULL; - char *pdata; -#ifdef STA_SUPPORT - int power_mode = 0; - int band = 0; - char *pband = NULL; - mlan_bss_info bss_info; - mlan_ds_get_signal signal; - mlan_rate_cfg_t rate; - t_u8 country_code[COUNTRY_CODE_LEN]; -#endif - int len = 0; + int user_data_len = 0; ENTER(); - if (copy_from_user(&priv_cmd, req->ifr_data, sizeof(android_wifi_priv_cmd))) { - ret = -EFAULT; + + if (strlen(respbuf) == (strlen(CMD_MARVELL) + strlen(PRIV_CMD_ESUPPMODE))) { + /* GET operation */ + user_data_len = 0; + } else { + /* SET operation */ + memset((char *) data, 0, sizeof(data)); + parse_arguments(respbuf + strlen(CMD_MARVELL) + + strlen(PRIV_CMD_ESUPPMODE), data, &user_data_len); + } + + if (user_data_len >= 4 || user_data_len == 1 || user_data_len == 2) { + PRINTM(MERROR, "Invalid number of arguments\n"); + ret = -EINVAL; goto done; } - buf = kzalloc(priv_cmd.total_len, GFP_KERNEL); - if (!buf) { - PRINTM(MERROR, "%s: failed to allocate memory\n", __FUNCTION__); + + req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_sec_cfg)); + if (req == NULL) { ret = -ENOMEM; goto done; } - if (copy_from_user(buf, priv_cmd.buf, priv_cmd.total_len)) { + + req->req_id = MLAN_IOCTL_SEC_CFG; + sec = (mlan_ds_sec_cfg *) req->pbuf; + sec->sub_command = MLAN_OID_SEC_CFG_ESUPP_MODE; + + if (user_data_len == 0) { + /* Get operation */ + req->action = MLAN_ACT_GET; + } else { + /* Set operation */ + req->action = MLAN_ACT_SET; + /* RSN mode */ + sec->param.esupp_mode.rsn_mode = data[0]; + /* Pairwise cipher */ + sec->param.esupp_mode.act_paircipher = (data[1] & 0xFF); + /* Group cipher */ + sec->param.esupp_mode.act_groupcipher = (data[2] & 0xFF); + } + + if (MLAN_STATUS_SUCCESS != woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT)) { ret = -EFAULT; goto done; } - PRINTM(MIOCTL, "Android priv cmd: [%s] on [%s]\n", buf, req->ifr_name); + esupp_mode = (woal_esuppmode_cfg *) respbuf; + esupp_mode->rsn_mode = (t_u16) ((sec->param.esupp_mode.rsn_mode) & 0xFFFF); + esupp_mode->pairwise_cipher = + (t_u8) ((sec->param.esupp_mode.act_paircipher) & 0xFF); + esupp_mode->group_cipher = + (t_u8) ((sec->param.esupp_mode.act_groupcipher) & 0xFF); - if (strncmp(buf, CMD_MARVELL, strlen(CMD_MARVELL)) == 0) { - /* This command has come from mlanutl app */ + ret = sizeof(woal_esuppmode_cfg); + done: + if (req) + kfree(req); + LEAVE(); + return ret; - /* Check command */ - if (strnicmp - (buf + strlen(CMD_MARVELL), PRIV_CMD_VERSION, - strlen(PRIV_CMD_VERSION)) == 0) { - /* Get version */ - len = woal_get_priv_driver_version(priv, buf, priv_cmd.total_len); - goto handled; - } else - if (strnicmp - (buf + strlen(CMD_MARVELL), PRIV_CMD_BANDCFG, - strlen(PRIV_CMD_BANDCFG)) == 0) { - /* Set/Get band configuration */ - len = woal_setget_priv_bandcfg(priv, buf, priv_cmd.total_len); - goto handled; -#ifdef WIFI_DIRECT_SUPPORT - } else - if (strnicmp - (buf + strlen(CMD_MARVELL), PRIV_CMD_HOSTCMD, - strlen(PRIV_CMD_HOSTCMD)) == 0) { - /* hostcmd configuration */ - len = woal_priv_hostcmd(priv, buf, priv_cmd.total_len); - goto handled; -#endif - } else - if (strnicmp - (buf + strlen(CMD_MARVELL), PRIV_CMD_HTTXCFG, - strlen(PRIV_CMD_HTTXCFG)) == 0) { - /* Set/Get HT Tx configuration */ - len = woal_setget_priv_httxcfg(priv, buf, priv_cmd.total_len); - goto handled; - } else - if (strnicmp - (buf + strlen(CMD_MARVELL), PRIV_CMD_DATARATE, - strlen(PRIV_CMD_DATARATE)) == 0) { - /* Get data rate */ - len = woal_get_priv_datarate(priv, buf, priv_cmd.total_len); - goto handled; - } else - if (strnicmp - (buf + strlen(CMD_MARVELL), PRIV_CMD_TXRATECFG, - strlen(PRIV_CMD_TXRATECFG)) == 0) { - /* Set/Get tx rate cfg */ - len = woal_setget_priv_txratecfg(priv, buf, priv_cmd.total_len); - goto handled; - } else { - /* Fall through, after stripping off the custom header */ - buf += strlen(CMD_MARVELL); - } +} + +/** + * @brief Set/Get esupplicant passphrase configurations + * + * @param priv A pointer to moal_private structure + * @param respbuf A pointer to response buffer + * @param respbuflen Available length of response buffer + * + * @return Number of bytes written, negative for failure. + */ +int +woal_setget_priv_passphrase(moal_private * priv, t_u8 * respbuf, + t_u32 respbuflen) +{ + mlan_ioctl_req *req = NULL; + mlan_ds_sec_cfg *sec = NULL; + int ret = 0, action = -1, i = 0; + char *begin, *end, *opt; + t_u16 len = 0; + t_u8 zero_mac[] = { 0, 0, 0, 0, 0, 0 }; + t_u8 *mac = NULL; + + ENTER(); + + if (strlen(respbuf) == (strlen(CMD_MARVELL) + strlen(PRIV_CMD_PASSPHRASE))) { + PRINTM(MERROR, "No arguments provided\n"); + ret = -EINVAL; + goto done; } -#ifdef STA_SUPPORT - if (strncmp(buf, "RSSI", strlen("RSSI")) == 0) { - if (MLAN_STATUS_SUCCESS != woal_get_bss_info(priv, - MOAL_IOCTL_WAIT, - &bss_info)) { - ret = -EFAULT; - goto done; - } - if (bss_info.media_connected) { - if (MLAN_STATUS_SUCCESS != woal_get_signal_info(priv, - MOAL_IOCTL_WAIT, - &signal)) { + + /* Parse the buf to get the cmd_action */ + begin = respbuf + strlen(CMD_MARVELL) + strlen(PRIV_CMD_PASSPHRASE); + end = woal_strsep(&begin, ';', '/'); + if (end) + action = woal_atox(end); + if (action < 0 || action > 2 || end[1] != '\0') { + PRINTM(MERROR, "Invalid action argument %s\n", end); + ret = -EINVAL; + goto done; + } + + req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_sec_cfg)); + if (req == NULL) { + ret = -ENOMEM; + goto done; + } + + req->req_id = MLAN_IOCTL_SEC_CFG; + sec = (mlan_ds_sec_cfg *) req->pbuf; + sec->sub_command = MLAN_OID_SEC_CFG_PASSPHRASE; + if (action == 0) + req->action = MLAN_ACT_GET; + else + req->action = MLAN_ACT_SET; + + while (begin) { + end = woal_strsep(&begin, ';', '/'); + opt = woal_strsep(&end, '=', '/'); + if (!opt || !end || !end[0]) { + PRINTM(MERROR, "Invalid option\n"); + ret = -EINVAL; + break; + } else if (!strnicmp(opt, "ssid", strlen(opt))) { + if (strlen(end) > MLAN_MAX_SSID_LENGTH) { + PRINTM(MERROR, "SSID length exceeds max length\n"); ret = -EFAULT; - goto done; + break; } - len = sprintf(buf, "%s rssi %d\n", bss_info.ssid.ssid, - signal.bcn_rssi_avg) + 1; + sec->param.passphrase.ssid.ssid_len = strlen(end); + strncpy((char *) sec->param.passphrase.ssid.ssid, end, strlen(end)); + PRINTM(MINFO, "ssid=%s, len=%d\n", sec->param.passphrase.ssid.ssid, + (int) sec->param.passphrase.ssid.ssid_len); + } else if (!strnicmp(opt, "bssid", strlen(opt))) { + woal_mac2u8((t_u8 *) & sec->param.passphrase.bssid, end); + } else if (!strnicmp(opt, "psk", strlen(opt)) && + req->action == MLAN_ACT_SET) { + if (strlen(end) != MLAN_PMK_HEXSTR_LENGTH) { + PRINTM(MERROR, "Invalid PMK length\n"); + ret = -EINVAL; + break; + } + woal_ascii2hex((t_u8 *) (sec->param.passphrase.psk.pmk.pmk), end, + MLAN_PMK_HEXSTR_LENGTH / 2); + sec->param.passphrase.psk_type = MLAN_PSK_PMK; + } else if (!strnicmp(opt, "passphrase", strlen(opt)) && + req->action == MLAN_ACT_SET) { + if (strlen(end) < MLAN_MIN_PASSPHRASE_LENGTH || + strlen(end) > MLAN_MAX_PASSPHRASE_LENGTH) { + PRINTM(MERROR, "Invalid length for passphrase\n"); + ret = -EINVAL; + break; + } + sec->param.passphrase.psk_type = MLAN_PSK_PASSPHRASE; + strncpy(sec->param.passphrase.psk.passphrase.passphrase, end, + sizeof(sec->param.passphrase.psk.passphrase.passphrase)); + sec->param.passphrase.psk.passphrase.passphrase_len = strlen(end); + PRINTM(MINFO, "passphrase=%s, len=%d\n", + sec->param.passphrase.psk.passphrase.passphrase, + (int) sec->param.passphrase.psk.passphrase.passphrase_len); } else { - len = sprintf(buf, "OK\n") + 1; + PRINTM(MERROR, "Invalid option %s\n", opt); + ret = -EINVAL; + break; } - } else if (strncmp(buf, "LINKSPEED", strlen("LINKSPEED")) == 0) { - if (MLAN_STATUS_SUCCESS != woal_set_get_data_rate(priv, MLAN_ACT_GET, - &rate)) { + } + if (ret) + goto done; + + if (action == 2) + sec->param.passphrase.psk_type = MLAN_PSK_CLEAR; + + if (MLAN_STATUS_SUCCESS != woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT)) { + ret = -EFAULT; + goto done; + } + + memset(respbuf, 0, respbuflen); + if (sec->param.passphrase.ssid.ssid_len) { + len += sprintf(respbuf + len, "ssid:"); + memcpy(respbuf + len, sec->param.passphrase.ssid.ssid, + sec->param.passphrase.ssid.ssid_len); + len += sec->param.passphrase.ssid.ssid_len; + len += sprintf(respbuf + len, " "); + } + if (memcmp(&sec->param.passphrase.bssid, zero_mac, sizeof(zero_mac))) { + mac = (t_u8 *) & sec->param.passphrase.bssid; + len += sprintf(respbuf + len, "bssid:"); + for (i = 0; i < ETH_ALEN - 1; ++i) + len += sprintf(respbuf + len, "%02x:", mac[i]); + len += sprintf(respbuf + len, "%02x ", mac[i]); + } + if (sec->param.passphrase.psk_type == MLAN_PSK_PMK) { + len += sprintf(respbuf + len, "psk:"); + for (i = 0; i < MLAN_MAX_KEY_LENGTH; ++i) + len += + sprintf(respbuf + len, "%02x", + sec->param.passphrase.psk.pmk.pmk[i]); + len += sprintf(respbuf + len, "\n"); + } + if (sec->param.passphrase.psk_type == MLAN_PSK_PASSPHRASE) { + len += + sprintf(respbuf + len, "passphrase:%s \n", + sec->param.passphrase.psk.passphrase.passphrase); + } + + ret = len; + done: + if (req) + kfree(req); + LEAVE(); + return ret; + +} + +/** + * @brief Deauthenticate + * + * @param priv A pointer to moal_private structure + * @param respbuf A pointer to response buffer + * @param respbuflen Available length of response buffer + * + * @return Number of bytes written, negative for failure. + */ +int +woal_priv_deauth(moal_private * priv, t_u8 * respbuf, t_u32 respbuflen) +{ + mlan_ioctl_req *req = NULL; + int ret = 0; + t_u8 mac[ETH_ALEN]; + + ENTER(); + + if (strlen(respbuf) > (strlen(CMD_MARVELL) + strlen(PRIV_CMD_DEAUTH))) { + /* Deauth mentioned BSSID */ + woal_mac2u8(mac, + respbuf + strlen(CMD_MARVELL) + strlen(PRIV_CMD_DEAUTH)); + if (MLAN_STATUS_SUCCESS != woal_disconnect(priv, MOAL_IOCTL_WAIT, mac)) { ret = -EFAULT; goto done; } - PRINTM(MIOCTL, "tx rate=%d\n", (int) rate.rate); - len = + } else { + if (MLAN_STATUS_SUCCESS != woal_disconnect(priv, MOAL_IOCTL_WAIT, NULL)) + ret = -EFAULT; + } + + done: + if (req) + kfree(req); + LEAVE(); + return ret; +} + +#if defined(WIFI_DIRECT_SUPPORT) +#if defined(STA_SUPPORT) && defined(UAP_SUPPORT) +/** + * @brief Set/Get BSS role + * + * @param priv A pointer to moal_private structure + * @param respbuf A pointer to response buffer + * @param respbuflen Available length of response buffer + * + * @return Number of bytes written, negative for failure. + */ +int +woal_priv_bssrole(moal_private * priv, t_u8 * respbuf, t_u32 respbuflen) +{ + t_u32 data[1]; + int ret = 0; + int user_data_len = 0; + t_u8 action = MLAN_ACT_GET; + + ENTER(); + + if (strlen(respbuf) == (strlen(CMD_MARVELL) + strlen(PRIV_CMD_BSSROLE))) { + /* GET operation */ + user_data_len = 0; + } else { + /* SET operation */ + memset((char *) data, 0, sizeof(data)); + parse_arguments(respbuf + strlen(CMD_MARVELL) + + strlen(PRIV_CMD_BSSROLE), data, &user_data_len); + } + + if (user_data_len >= 2) { + PRINTM(MERROR, "Invalid number of arguments\n"); + ret = -EINVAL; + goto error; + } + + if (user_data_len == 0) { + action = MLAN_ACT_GET; + } else { + if ((data[0] != MLAN_BSS_ROLE_STA && + data[0] != MLAN_BSS_ROLE_UAP) || + priv->bss_type != MLAN_BSS_TYPE_WIFIDIRECT) { + PRINTM(MWARN, "Invalid BSS role\n"); + ret = -EINVAL; + goto error; + } + if (data[0] == GET_BSS_ROLE(priv)) { + PRINTM(MWARN, "Already BSS is in desired role\n"); + goto done; + } + action = MLAN_ACT_SET; + /* Reset interface */ + woal_reset_intf(priv, MOAL_IOCTL_WAIT, MFALSE); + } + + if (MLAN_STATUS_SUCCESS != woal_bss_role_cfg(priv, + action, MOAL_IOCTL_WAIT, + (t_u8 *) data)) { + ret = -EFAULT; + goto error; + } + + if (user_data_len) { + /* Initialize private structures */ + woal_init_priv(priv, MOAL_IOCTL_WAIT); + /* Enable interfaces */ + netif_device_attach(priv->netdev); + woal_start_queue(priv->netdev); + } + + done: + memset(respbuf, 0, respbuflen); + respbuf[0] = (t_u8) data[0]; + ret = 1; + + error: + LEAVE(); + return ret; +} +#endif /* STA_SUPPORT && UAP_SUPPORT */ +#endif /* WIFI_DIRECT_SUPPORT && V14_FEATURE */ + +#ifdef STA_SUPPORT +/** + * @brief Set user scan + * + * @param priv A pointer to moal_private structure + * @param respbuf A pointer to response buffer + * @param respbuflen Available length of response buffer + * + * @return Number of bytes written, negative for failure. + */ +int +woal_priv_setuserscan(moal_private * priv, t_u8 * respbuf, t_u32 respbuflen) +{ + wlan_user_scan_cfg scan_cfg; + int ret = 0; + + ENTER(); + + /* Create the scan_cfg structure */ + memset(&scan_cfg, 0, sizeof(scan_cfg)); + + /* We expect the scan_cfg structure to be passed in respbuf */ + memcpy((char *) &scan_cfg, + respbuf + strlen(CMD_MARVELL) + strlen(PRIV_CMD_SETUSERSCAN), + sizeof(wlan_user_scan_cfg)); + + /* Call for scan */ + if (MLAN_STATUS_FAILURE == woal_do_scan(priv, &scan_cfg)) + ret = -EFAULT; + + LEAVE(); + return ret; +} +#endif + +/** + * @brief Set/Get deep sleep mode configurations + * + * @param priv A pointer to moal_private structure + * @param respbuf A pointer to response buffer + * @param respbuflen Available length of response buffer + * + * @return Number of bytes written, negative for failure. + */ +int +woal_priv_setgetdeepsleep(moal_private * priv, t_u8 * respbuf, t_u32 respbuflen) +{ + t_u32 data[2]; + int ret = 0; + int user_data_len = 0; + + ENTER(); + + if (strlen(respbuf) == (strlen(CMD_MARVELL) + strlen(PRIV_CMD_DEEPSLEEP))) { + /* GET operation */ + user_data_len = 0; + } else { + /* SET operation */ + memset((char *) data, 0, sizeof(data)); + parse_arguments(respbuf + strlen(CMD_MARVELL) + + strlen(PRIV_CMD_DEEPSLEEP), data, &user_data_len); + } + + if (user_data_len >= 3) { + PRINTM(MERROR, "Invalid number of arguments\n"); + ret = -EINVAL; + goto done; + } + + if (user_data_len == 0) { + if (MLAN_STATUS_SUCCESS != woal_get_deep_sleep(priv, data)) { + ret = -EFAULT; + goto done; + } + sprintf(respbuf, "%d %d", data[0], data[1]); + ret = strlen(respbuf) + 1; + } else { + if (data[0] == DEEP_SLEEP_OFF) { + PRINTM(MINFO, "Exit Deep Sleep Mode\n"); + ret = woal_set_deep_sleep(priv, MOAL_IOCTL_WAIT, MFALSE, 0); + if (ret != MLAN_STATUS_SUCCESS) { + ret = -EINVAL; + goto done; + } + } else if (data[0] == DEEP_SLEEP_ON) { + PRINTM(MINFO, "Enter Deep Sleep Mode\n"); + if (user_data_len != 2) + data[1] = 0; + ret = woal_set_deep_sleep(priv, MOAL_IOCTL_WAIT, MTRUE, data[1]); + if (ret != MLAN_STATUS_SUCCESS) { + ret = -EINVAL; + goto done; + } + } else { + PRINTM(MERROR, "Unknown option = %u\n", data[0]); + ret = -EINVAL; + goto done; + } + ret = sprintf(respbuf, "OK\n") + 1; + } + + done: + LEAVE(); + return ret; + +} + +/** + * @brief Set/Get IP address configurations + * + * @param priv A pointer to moal_private structure + * @param respbuf A pointer to response buffer + * @param respbuflen Available length of response buffer + * + * @return Number of bytes written, negative for failure. + */ +int +woal_priv_setgetipaddr(moal_private * priv, t_u8 * respbuf, t_u32 respbuflen) +{ + mlan_ioctl_req *req = NULL; + mlan_ds_misc_cfg *misc = NULL; + int ret = 0, op_code = 0, data_length = 0, header = 0; + + ENTER(); + + header = strlen(CMD_MARVELL) + strlen(PRIV_CMD_IPADDR); + data_length = strlen(respbuf) - header; + + req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_misc_cfg)); + if (req == NULL) { + ret = -ENOMEM; + goto done; + } + misc = (mlan_ds_misc_cfg *) req->pbuf; + + if (data_length < 1) { /* GET */ + req->action = MLAN_ACT_GET; + } else { + /* Make sure we have the operation argument */ + if (data_length > 2 && respbuf[header + 1] != ';') { + PRINTM(MERROR, "No operation argument. Separate with ';'\n"); + ret = -EINVAL; + goto done; + } else { + respbuf[header + 1] = '\0'; + } + req->action = MLAN_ACT_SET; + + /* Only one IP is supported in current firmware */ + memset(misc->param.ipaddr_cfg.ip_addr[0], 0, IPADDR_LEN); + in4_pton(&respbuf[header + 2], + MIN((IPADDR_MAX_BUF - 3), (data_length - 2)), + misc->param.ipaddr_cfg.ip_addr[0], ' ', NULL); + misc->param.ipaddr_cfg.ip_addr_num = 1; + misc->param.ipaddr_cfg.ip_addr_type = IPADDR_TYPE_IPV4; + + if (woal_atoi(&op_code, &respbuf[header]) != MLAN_STATUS_SUCCESS) { + ret = -EINVAL; + goto done; + } + misc->param.ipaddr_cfg.op_code = (t_u32) op_code; + } + + req->req_id = MLAN_IOCTL_MISC_CFG; + misc->sub_command = MLAN_OID_MISC_IP_ADDR; + + if (MLAN_STATUS_SUCCESS != woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT)) { + ret = -EFAULT; + goto done; + } + + if (req->action == MLAN_ACT_GET) { + snprintf(respbuf, IPADDR_MAX_BUF, "%d;%d.%d.%d.%d", + misc->param.ipaddr_cfg.op_code, + misc->param.ipaddr_cfg.ip_addr[0][0], + misc->param.ipaddr_cfg.ip_addr[0][1], + misc->param.ipaddr_cfg.ip_addr[0][2], + misc->param.ipaddr_cfg.ip_addr[0][3]); + ret = IPADDR_MAX_BUF + 1; + } else { + ret = sprintf(respbuf, "OK\n") + 1; + } + + done: + if (req) + kfree(req); + LEAVE(); + return ret; +} + +/** + * @brief Set/Get WPS session configurations + * + * @param priv A pointer to moal_private structure + * @param respbuf A pointer to response buffer + * @param respbuflen Available length of response buffer + * + * @return Number of bytes written, negative for failure. + */ +int +woal_priv_setwpssession(moal_private * priv, t_u8 * respbuf, t_u32 respbuflen) +{ + mlan_ioctl_req *req = NULL; + mlan_ds_wps_cfg *pwps = NULL; + t_u32 data[1]; + int ret = 0; + int user_data_len = 0; + + ENTER(); + + if (strlen(respbuf) == (strlen(CMD_MARVELL) + strlen(PRIV_CMD_WPSSESSION))) { + /* GET operation */ + user_data_len = 0; + } else { + /* SET operation */ + memset((char *) data, 0, sizeof(data)); + parse_arguments(respbuf + strlen(CMD_MARVELL) + + strlen(PRIV_CMD_WPSSESSION), data, &user_data_len); + } + + if (user_data_len != 1) { + PRINTM(MERROR, "Invalid number of arguments\n"); + ret = -EINVAL; + goto done; + } + + req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_wps_cfg)); + if (req == NULL) { + ret = -ENOMEM; + goto done; + } + pwps = (mlan_ds_wps_cfg *) req->pbuf; + + req->req_id = MLAN_IOCTL_WPS_CFG; + req->action = MLAN_ACT_SET; + pwps->sub_command = MLAN_OID_WPS_CFG_SESSION; + + if (data[0] == 1) + pwps->param.wps_session = MLAN_WPS_CFG_SESSION_START; + else + pwps->param.wps_session = MLAN_WPS_CFG_SESSION_END; + + if (MLAN_STATUS_SUCCESS != woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT)) { + ret = -EFAULT; + goto done; + } + + ret = sprintf(respbuf, "OK\n") + 1; + done: + if (req) + kfree(req); + LEAVE(); + return ret; +} + +/** + * @brief Get OTP user data + * + * @param priv A pointer to moal_private structure + * @param respbuf A pointer to response buffer + * @param respbuflen Available length of response buffer + * + * @return Number of bytes written, negative for failure. + */ +int +woal_priv_otpuserdata(moal_private * priv, t_u8 * respbuf, t_u32 respbuflen) +{ + int data[1]; + int user_data_len = 0; + mlan_ioctl_req *req = NULL; + mlan_ds_misc_cfg *misc = NULL; + mlan_ds_misc_otp_user_data *otp = NULL; + int ret = 0; + + ENTER(); + + memset((char *) data, 0, sizeof(data)); + parse_arguments(respbuf + strlen(CMD_MARVELL) + + strlen(PRIV_CMD_OTPUSERDATA), data, &user_data_len); + + if (user_data_len > 1) { + PRINTM(MERROR, "Too many arguments\n"); + LEAVE(); + return -EINVAL; + } + + req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_misc_cfg)); + if (req == NULL) { + ret = -ENOMEM; + goto done; + } + req->action = MLAN_ACT_GET; + req->req_id = MLAN_IOCTL_MISC_CFG; + + misc = (mlan_ds_misc_cfg *) req->pbuf; + misc->sub_command = MLAN_OID_MISC_OTP_USER_DATA; + misc->param.otp_user_data.user_data_length = data[0]; + + if (MLAN_STATUS_SUCCESS != woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT)) { + ret = -EFAULT; + goto done; + } + otp = (mlan_ds_misc_otp_user_data *) req->pbuf; + + if (req->action == MLAN_ACT_GET) { + ret = MIN(otp->user_data_length, data[0]); + memcpy(respbuf, otp->user_data, ret); + } + + done: + if (req) + kfree(req); + LEAVE(); + return ret; +} + +/** + * @brief Set / Get country code + * + * @param priv A pointer to moal_private structure + * @param respbuf A pointer to response buffer + * @param respbuflen Available length of response buffer + * + * @return Number of bytes written, negative for failure. + */ +int +woal_priv_set_get_countrycode(moal_private * priv, t_u8 * respbuf, + t_u32 respbuflen) +{ + int ret = 0; + // char data[COUNTRY_CODE_LEN] = {0, 0, 0}; + int header = 0, data_length = 0; // wrq->u.data.length; + mlan_ioctl_req *req = NULL; + mlan_ds_misc_cfg *pcfg_misc = NULL; + mlan_ds_misc_country_code *country_code = NULL; + + ENTER(); + + header = strlen(CMD_MARVELL) + strlen(PRIV_CMD_COUNTRYCODE); + data_length = strlen(respbuf) - header; + + if (data_length > COUNTRY_CODE_LEN) { + PRINTM(MERROR, "Invalid argument!\n"); + ret = -EINVAL; + goto done; + } + + /* Allocate an IOCTL request buffer */ + req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_misc_cfg)); + if (req == NULL) { + ret = -ENOMEM; + goto done; + } + + /* Fill request buffer */ + pcfg_misc = (mlan_ds_misc_cfg *) req->pbuf; + country_code = &pcfg_misc->param.country_code; + pcfg_misc->sub_command = MLAN_OID_MISC_COUNTRY_CODE; + req->req_id = MLAN_IOCTL_MISC_CFG; + + if (data_length <= 1) { + req->action = MLAN_ACT_GET; + } else { + memset(country_code->country_code, 0, COUNTRY_CODE_LEN); + memcpy(country_code->country_code, respbuf + header, COUNTRY_CODE_LEN); + req->action = MLAN_ACT_SET; + } + + /* Send IOCTL request to MLAN */ + if (woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT) != MLAN_STATUS_SUCCESS) { + ret = -EFAULT; + goto done; + } + + if (req->action == MLAN_ACT_GET) { + ret = data_length = COUNTRY_CODE_LEN; + memset(respbuf + header, 0, COUNTRY_CODE_LEN); + memcpy(respbuf, country_code->country_code, COUNTRY_CODE_LEN); + } + + done: + if (req) + kfree(req); + + LEAVE(); + return ret; +} + +/** + * @brief Set/Get TCP Ack enhancement configurations + * + * @param priv A pointer to moal_private structure + * @param respbuf A pointer to response buffer + * @param respbuflen Available length of response buffer + * + * @return Number of bytes written, negative for failure. + */ +int +woal_priv_setgettcpackenh(moal_private * priv, t_u8 * respbuf, t_u32 respbuflen) +{ + t_u32 data[1]; + int ret = 0; + int user_data_len = 0; + struct list_head *link = NULL; + struct tcp_sess *tcp_sess = NULL; + + ENTER(); + + if (strlen(respbuf) == (strlen(CMD_MARVELL) + strlen(PRIV_CMD_TCPACKENH))) { + /* GET operation */ + user_data_len = 0; + } else { + /* SET operation */ + memset((char *) data, 0, sizeof(data)); + parse_arguments(respbuf + strlen(CMD_MARVELL) + + strlen(PRIV_CMD_TCPACKENH), data, &user_data_len); + } + + if (user_data_len >= 2) { + PRINTM(MERROR, "Invalid number of arguments\n"); + ret = -EINVAL; + goto done; + } + + if (user_data_len == 0) { + /* get operation */ + respbuf[0] = priv->enable_tcp_ack_enh; + } else { + /* set operation */ + if (data[0] == MTRUE) { + PRINTM(MINFO, "Enabling TCP Ack enhancement\n"); + priv->enable_tcp_ack_enh = MTRUE; + } else if (data[0] == MFALSE) { + PRINTM(MINFO, "Disabling TCP Ack enhancement\n"); + priv->enable_tcp_ack_enh = MFALSE; + /* release the tcp sessions if any */ + while (!list_empty(&priv->tcp_sess_queue)) { + link = priv->tcp_sess_queue.next; + tcp_sess = list_entry(link, struct tcp_sess, link); + PRINTM(MINFO, + "Disable TCP ACK Enh: release a tcp session in dl. (src: ipaddr 0x%08x, port: %d. dst: ipaddr 0x%08x, port: %d\n", + tcp_sess->src_ip_addr, tcp_sess->src_tcp_port, + tcp_sess->dst_ip_addr, tcp_sess->dst_tcp_port); + list_del(link); + kfree(tcp_sess); + } + } else { + PRINTM(MERROR, "Unknown option = %u\n", data[0]); + ret = -EINVAL; + goto done; + } + respbuf[0] = priv->enable_tcp_ack_enh; + } + ret = 1; + + done: + LEAVE(); + return ret; + +} + +/** + * @brief Set priv command for Android + * @param dev A pointer to net_device structure + * @param req A pointer to ifreq structure + * + * @return 0 --success, otherwise fail + */ +int +woal_android_priv_cmd(struct net_device *dev, struct ifreq *req) +{ + int ret = 0; + android_wifi_priv_cmd priv_cmd; + moal_private *priv = (moal_private *) netdev_priv(dev); + char *buf = NULL; + char *pdata; +#ifdef STA_SUPPORT + int power_mode = 0; + int band = 0; + char *pband = NULL; + mlan_bss_info bss_info; + mlan_ds_get_signal signal; + mlan_rate_cfg_t rate; + t_u8 country_code[COUNTRY_CODE_LEN]; +#endif + int len = 0; + + ENTER(); + if (copy_from_user(&priv_cmd, req->ifr_data, sizeof(android_wifi_priv_cmd))) { + ret = -EFAULT; + goto done; + } + buf = kzalloc(priv_cmd.total_len, GFP_KERNEL); + if (!buf) { + PRINTM(MERROR, "%s: failed to allocate memory\n", __FUNCTION__); + ret = -ENOMEM; + goto done; + } + if (copy_from_user(buf, priv_cmd.buf, priv_cmd.total_len)) { + ret = -EFAULT; + goto done; + } + + PRINTM(MIOCTL, "Android priv cmd: [%s] on [%s]\n", buf, req->ifr_name); + + if (strncmp(buf, CMD_MARVELL, strlen(CMD_MARVELL)) == 0) { + /* This command has come from mlanutl app */ + + /* Check command */ + if (strnicmp + (buf + strlen(CMD_MARVELL), PRIV_CMD_VERSION, + strlen(PRIV_CMD_VERSION)) == 0) { + /* Get version */ + len = woal_get_priv_driver_version(priv, buf, priv_cmd.total_len); + goto handled; + } else + if (strnicmp + (buf + strlen(CMD_MARVELL), PRIV_CMD_BANDCFG, + strlen(PRIV_CMD_BANDCFG)) == 0) { + /* Set/Get band configuration */ + len = woal_setget_priv_bandcfg(priv, buf, priv_cmd.total_len); + goto handled; + } else + if (strnicmp + (buf + strlen(CMD_MARVELL), PRIV_CMD_HOSTCMD, + strlen(PRIV_CMD_HOSTCMD)) == 0) { + /* hostcmd configuration */ + len = woal_priv_hostcmd(priv, buf, priv_cmd.total_len); + goto handled; + } else + if (strnicmp + (buf + strlen(CMD_MARVELL), PRIV_CMD_HTTXCFG, + strlen(PRIV_CMD_HTTXCFG)) == 0) { + /* Set/Get HT Tx configuration */ + len = woal_setget_priv_httxcfg(priv, buf, priv_cmd.total_len); + goto handled; + } else + if (strnicmp + (buf + strlen(CMD_MARVELL), PRIV_CMD_DATARATE, + strlen(PRIV_CMD_DATARATE)) == 0) { + /* Get data rate */ + len = woal_get_priv_datarate(priv, buf, priv_cmd.total_len); + goto handled; + } else + if (strnicmp + (buf + strlen(CMD_MARVELL), PRIV_CMD_TXRATECFG, + strlen(PRIV_CMD_TXRATECFG)) == 0) { + /* Set/Get tx rate cfg */ + len = woal_setget_priv_txratecfg(priv, buf, priv_cmd.total_len); + goto handled; + } else + if (strnicmp + (buf + strlen(CMD_MARVELL), PRIV_CMD_CUSTOMIE, + strlen(PRIV_CMD_CUSTOMIE)) == 0) { + /* Custom IE configuration */ + len = woal_priv_customie(priv, buf, priv_cmd.total_len); + goto handled; + } else + if (strnicmp + (buf + strlen(CMD_MARVELL), PRIV_CMD_ESUPPMODE, + strlen(PRIV_CMD_ESUPPMODE)) == 0) { + /* Esupplicant mode configuration */ + len = woal_setget_priv_esuppmode(priv, buf, priv_cmd.total_len); + goto handled; + } else + if (strnicmp + (buf + strlen(CMD_MARVELL), PRIV_CMD_PASSPHRASE, + strlen(PRIV_CMD_PASSPHRASE)) == 0) { + /* Esupplicant passphrase configuration */ + len = woal_setget_priv_passphrase(priv, buf, priv_cmd.total_len); + goto handled; + } else + if (strnicmp + (buf + strlen(CMD_MARVELL), PRIV_CMD_DEAUTH, + strlen(PRIV_CMD_DEAUTH)) == 0) { + /* Deauth */ + len = woal_priv_deauth(priv, buf, priv_cmd.total_len); + goto handled; +#if defined(WIFI_DIRECT_SUPPORT) +#if defined(STA_SUPPORT) && defined(UAP_SUPPORT) + } else + if (strnicmp + (buf + strlen(CMD_MARVELL), PRIV_CMD_BSSROLE, + strlen(PRIV_CMD_BSSROLE)) == 0) { + /* BSS Role */ + len = woal_priv_bssrole(priv, buf, priv_cmd.total_len); + goto handled; +#endif +#endif +#ifdef STA_SUPPORT + } else + if (strnicmp + (buf + strlen(CMD_MARVELL), PRIV_CMD_SETUSERSCAN, + strlen(PRIV_CMD_SETUSERSCAN)) == 0) { + /* Set user scan */ + len = woal_priv_setuserscan(priv, buf, priv_cmd.total_len); + goto handled; +#endif + } else + if (strnicmp + (buf + strlen(CMD_MARVELL), PRIV_CMD_DEEPSLEEP, + strlen(PRIV_CMD_DEEPSLEEP)) == 0) { + /* Deep sleep */ + len = woal_priv_setgetdeepsleep(priv, buf, priv_cmd.total_len); + goto handled; + } else + if (strnicmp + (buf + strlen(CMD_MARVELL), PRIV_CMD_IPADDR, + strlen(PRIV_CMD_IPADDR)) == 0) { + /* IP address */ + len = woal_priv_setgetipaddr(priv, buf, priv_cmd.total_len); + goto handled; + } else + if (strnicmp + (buf + strlen(CMD_MARVELL), PRIV_CMD_WPSSESSION, + strlen(PRIV_CMD_WPSSESSION)) == 0) { + /* WPS Session */ + len = woal_priv_setwpssession(priv, buf, priv_cmd.total_len); + goto handled; + } else + if (strnicmp + (buf + strlen(CMD_MARVELL), PRIV_CMD_OTPUSERDATA, + strlen(PRIV_CMD_OTPUSERDATA)) == 0) { + /* OTP user data */ + len = woal_priv_otpuserdata(priv, buf, priv_cmd.total_len); + goto handled; + } else + if (strnicmp + (buf + strlen(CMD_MARVELL), PRIV_CMD_COUNTRYCODE, + strlen(PRIV_CMD_COUNTRYCODE)) == 0) { + /* OTP user data */ + len = woal_priv_set_get_countrycode(priv, buf, priv_cmd.total_len); + goto handled; + } else + if (strnicmp + (buf + strlen(CMD_MARVELL), PRIV_CMD_TCPACKENH, + strlen(PRIV_CMD_TCPACKENH)) == 0) { + /* OTP user data */ + len = woal_priv_setgettcpackenh(priv, buf, priv_cmd.total_len); + goto handled; + } else { + /* Fall through, after stripping off the custom header */ + buf += strlen(CMD_MARVELL); + } + } +#ifdef STA_SUPPORT + if (strncmp(buf, "RSSILOW-THRESHOLD", strlen("RSSILOW-THRESHOLD")) == 0) { + pdata = buf + strlen("RSSILOW-THRESHOLD") + 1; + if (MLAN_STATUS_SUCCESS != woal_set_rssi_low_threshold(priv, pdata)) { + ret = -EFAULT; + goto done; + } + len = sprintf(buf, "OK\n") + 1; + } else if (strncmp(buf, "RSSI", strlen("RSSI")) == 0) { + if (MLAN_STATUS_SUCCESS != woal_get_bss_info(priv, + MOAL_IOCTL_WAIT, + &bss_info)) { + ret = -EFAULT; + goto done; + } + if (bss_info.media_connected) { + if (MLAN_STATUS_SUCCESS != woal_get_signal_info(priv, + MOAL_IOCTL_WAIT, + &signal)) { + ret = -EFAULT; + goto done; + } + len = sprintf(buf, "%s rssi %d\n", bss_info.ssid.ssid, + signal.bcn_rssi_avg) + 1; + } else { + len = sprintf(buf, "OK\n") + 1; + } + } else if (strncmp(buf, "LINKSPEED", strlen("LINKSPEED")) == 0) { + if (MLAN_STATUS_SUCCESS != woal_set_get_data_rate(priv, MLAN_ACT_GET, + &rate)) { + ret = -EFAULT; + goto done; + } + PRINTM(MIOCTL, "tx rate=%d\n", (int) rate.rate); + len = sprintf(buf, "LinkSpeed %d\n", (int) (rate.rate * 500000 / 1000000)) + 1; } else @@ -983,12 +1987,14 @@ woal_android_priv_cmd(struct net_device *dev, struct ifreq *req) priv->bg_scan_reported = MFALSE; len = sprintf(buf, "OK\n") + 1; } else if (strncmp(buf, "BGSCAN-STOP", strlen("BGSCAN-STOP")) == 0) { - if (MLAN_STATUS_SUCCESS != woal_stop_bg_scan(priv)) { - ret = -EFAULT; - goto done; + if (priv->bg_scan_start && !priv->scan_cfg.rssi_threshold) { + if (MLAN_STATUS_SUCCESS != woal_stop_bg_scan(priv)) { + ret = -EFAULT; + goto done; + } + priv->bg_scan_start = MFALSE; + priv->bg_scan_reported = MFALSE; } - priv->bg_scan_start = MFALSE; - priv->bg_scan_reported = MFALSE; len = sprintf(buf, "OK\n") + 1; } else if (strncmp(buf, "RXFILTER-START", strlen("RXFILTER-START")) == 0) { #ifdef MEF_CFG_RX_FILTER @@ -1004,7 +2010,19 @@ woal_android_priv_cmd(struct net_device *dev, struct ifreq *req) } #endif len = sprintf(buf, "OK\n") + 1; - } else if (strncmp(buf, "RXFILTER-ADD", strlen("RXFILTER-ADD")) == 0) { + } +#ifdef STA_CFG80211 + else if (strncmp(buf, "GET_RSSI_STATUS", strlen("GET_RSSI_STATUS")) == 0) { + if (priv->rssi_status == MLAN_EVENT_ID_FW_BCN_RSSI_LOW) + len = sprintf(buf, "EVENT=BEACON_RSSI_LOW\n"); + else if (priv->rssi_status == MLAN_EVENT_ID_FW_PRE_BCN_LOST) + len = sprintf(buf, "EVENT=PRE_BEACON_LOST\n"); + else + len = sprintf(buf, "OK\n") + 1; + priv->rssi_status = 0; + } +#endif + else if (strncmp(buf, "RXFILTER-ADD", strlen("RXFILTER-ADD")) == 0) { pdata = buf + strlen("RXFILTER-ADD") + 1; if (MLAN_STATUS_SUCCESS != woal_add_rxfilter(priv, pdata)) { ret = -EFAULT; @@ -1071,10 +2089,20 @@ woal_android_priv_cmd(struct net_device *dev, struct ifreq *req) if (len > 0) { priv_cmd.used_len = len; - if (copy_to_user(priv_cmd.buf, buf, len)) { + if (priv_cmd.used_len < priv_cmd.total_len) + memset(priv_cmd.buf + priv_cmd.used_len, 0, + priv_cmd.total_len - priv_cmd.used_len); + if (copy_to_user(priv_cmd.buf, buf, priv_cmd.used_len)) { PRINTM(MERROR, "%s: failed to copy data to user buffer\n", __FUNCTION__); ret = -EFAULT; + goto done; + } + if (copy_to_user + (req->ifr_data, &priv_cmd, sizeof(android_wifi_priv_cmd))) { + PRINTM(MERROR, "%s: failed to copy command header to user buffer\n", + __FUNCTION__); + ret = -EFAULT; } } else { ret = len; diff --git a/drivers/net/wireless/sd8797/mlinux/moal_eth_ioctl.h b/drivers/net/wireless/sd8797/mlinux/moal_eth_ioctl.h index a1481e88ff21..a68991694a9d 100644 --- a/drivers/net/wireless/sd8797/mlinux/moal_eth_ioctl.h +++ b/drivers/net/wireless/sd8797/mlinux/moal_eth_ioctl.h @@ -44,12 +44,23 @@ Change log: /** Private command ID to get BSS type */ #define WOAL_GET_BSS_TYPE (SIOCDEVPRIVATE + 15) -int woal_do_ioctl(struct net_device *dev, struct ifreq *req, int i); +int woal_do_ioctl(struct net_device *dev, struct ifreq *req, int cmd); +/* + * For android private commands, fixed value of ioctl is used. + * Internally commands are differentiated using strings. + * + * application needs to specify "total_len" of data for copy_from_user + * kernel updates "used_len" during copy_to_user + */ +/** Private command structure from app */ typedef struct _android_wifi_priv_cmd { + /** Buffer pointer */ char *buf; + /** buffer updated by driver */ int used_len; + /** buffer sent by application */ int total_len; } android_wifi_priv_cmd; @@ -62,6 +73,16 @@ typedef struct woal_priv_tx_rate_cfg t_u32 rate_index; } woal_tx_rate_cfg; +typedef struct woal_priv_esuppmode_cfg +{ + /* RSN mode */ + t_u16 rsn_mode; + /* Pairwise cipher */ + t_u8 pairwise_cipher; + /* Group cipher */ + t_u8 group_cipher; +} woal_esuppmode_cfg; + mlan_status woal_set_ap_wps_p2p_ie(moal_private * priv, t_u8 * ie, size_t len); int woal_android_priv_cmd(struct net_device *dev, struct ifreq *req); diff --git a/drivers/net/wireless/sd8797/mlinux/moal_ioctl.c b/drivers/net/wireless/sd8797/mlinux/moal_ioctl.c index efe6e7ddcea1..94fe7e11669e 100644 --- a/drivers/net/wireless/sd8797/mlinux/moal_ioctl.c +++ b/drivers/net/wireless/sd8797/mlinux/moal_ioctl.c @@ -2,7 +2,7 @@ * * @brief This file contains ioctl function to MLAN * - * Copyright (C) 2008-2011, Marvell International Ltd. + * Copyright (C) 2008-2012, Marvell International Ltd. * * This software file (the "File") is distributed by Marvell International * Ltd. under the terms of the GNU General Public License Version 2, June 1991 @@ -792,7 +792,7 @@ woal_set_get_retry(moal_private * priv, t_u32 action, #ifdef STA_CFG80211 /* If set is invoked from other than iw i.e iwconfig, wiphy retry count should be updated as well */ - if (IS_STA_CFG80211(cfg80211_wext) && + if (IS_STA_CFG80211(cfg80211_wext) && priv->wdev && priv->wdev->wiphy && (GET_BSS_ROLE(priv) == MLAN_BSS_ROLE_STA) && (action == MLAN_ACT_SET)) { priv->wdev->wiphy->retry_long = (t_u8) * value; priv->wdev->wiphy->retry_short = (t_u8) * value; @@ -854,7 +854,7 @@ woal_set_get_rts(moal_private * priv, t_u32 action, #ifdef STA_CFG80211 /* If set is invoked from other than iw i.e iwconfig, wiphy RTS threshold should be updated as well */ - if (IS_STA_CFG80211(cfg80211_wext) && + if (IS_STA_CFG80211(cfg80211_wext) && priv->wdev && priv->wdev->wiphy && (GET_BSS_ROLE(priv) == MLAN_BSS_ROLE_STA) && (action == MLAN_ACT_SET)) priv->wdev->wiphy->rts_threshold = *value; #endif @@ -914,7 +914,7 @@ woal_set_get_frag(moal_private * priv, t_u32 action, #ifdef STA_CFG80211 /* If set is invoked from other than iw i.e iwconfig, wiphy fragment threshold should be updated as well */ - if (IS_STA_CFG80211(cfg80211_wext) && + if (IS_STA_CFG80211(cfg80211_wext) && priv->wdev && priv->wdev->wiphy && (GET_BSS_ROLE(priv) == MLAN_BSS_ROLE_STA) && (action == MLAN_ACT_SET)) priv->wdev->wiphy->frag_threshold = *value; #endif @@ -1096,7 +1096,7 @@ woal_set_get_power_mgmt(moal_private * priv, #ifdef STA_CFG80211 /* If set is invoked from other than iw i.e iwconfig, wiphy IEEE power save mode should be updated */ - if (IS_STA_CFG80211(cfg80211_wext) && + if (IS_STA_CFG80211(cfg80211_wext) && priv->wdev && (GET_BSS_ROLE(priv) == MLAN_BSS_ROLE_STA) && (action == MLAN_ACT_SET)) { if (*disabled) priv->wdev->ps = MFALSE; @@ -1780,20 +1780,22 @@ woal_get_bss_type(struct net_device *dev, struct ifreq *req) #if defined(STA_SUPPORT) && defined(UAP_SUPPORT) #if defined(STA_WEXT) || defined(UAP_WEXT) /** - * @brief Set/Get BSS role + * @brief Swithces BSS role of WFD interface * - * @param priv A pointer to moal_private structure - * @param wrq A pointer to iwreq structure + * @param priv A pointer to moal_private structure + * @param action Action: set or get + * @param wait_option Wait option (MOAL_WAIT or MOAL_NO_WAIT) + * @param bss_role A pointer to bss role * * @return 0 --success, otherwise fail */ -int -woal_set_get_bss_role(moal_private * priv, struct iwreq *wrq) +mlan_status +woal_bss_role_cfg(moal_private * priv, t_u8 action, + t_u8 wait_option, t_u8 * bss_role) { int ret = 0; mlan_ds_bss *bss = NULL; mlan_ioctl_req *req = NULL; - int bss_role = 0; struct net_device *dev = priv->netdev; ENTER(); @@ -1812,55 +1814,26 @@ woal_set_get_bss_role(moal_private * priv, struct iwreq *wrq) bss = (mlan_ds_bss *) req->pbuf; bss->sub_command = MLAN_OID_BSS_ROLE; req->req_id = MLAN_IOCTL_BSS; - if (wrq->u.data.length) { - if (copy_from_user(&bss_role, wrq->u.data.pointer, sizeof(int))) { - PRINTM(MERROR, "Copy from user failed\n"); - ret = -EFAULT; - goto done; - } - if (bss_role != MLAN_BSS_ROLE_STA && bss_role != MLAN_BSS_ROLE_UAP) { - PRINTM(MWARN, "Invalid BSS role\n"); - ret = -EINVAL; - goto done; - } - if (bss_role == GET_BSS_ROLE(priv)) { - PRINTM(MWARN, "Already BSS is in desired role\n"); - ret = -EINVAL; - goto done; - } - req->action = MLAN_ACT_SET; - bss->param.bss_role = (t_u8) bss_role; - } else { - req->action = MLAN_ACT_GET; - } - - if (req->action == MLAN_ACT_SET) { - /* Reset interface */ - woal_reset_intf(priv, MOAL_IOCTL_WAIT, MFALSE); + req->action = action; + if (action == MLAN_ACT_SET) { + bss->param.bss_role = *bss_role; } - if (MLAN_STATUS_SUCCESS != woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT)) { + if (MLAN_STATUS_SUCCESS != woal_request_ioctl(priv, req, wait_option)) { ret = -EFAULT; goto done; } - if (!wrq->u.data.length) { - bss_role = (int) bss->param.bss_role; - if (copy_to_user(wrq->u.data.pointer, &bss_role, sizeof(int))) { - ret = -EFAULT; - goto done; - } - wrq->u.data.length = 1; + + if (action == MLAN_ACT_GET) { + *bss_role = bss->param.bss_role; } else { /* Update moal_private */ - priv->bss_role = bss_role; + priv->bss_role = *bss_role; if (priv->bss_type == MLAN_BSS_TYPE_UAP) priv->bss_type = MLAN_BSS_TYPE_STA; else if (priv->bss_type == MLAN_BSS_TYPE_STA) priv->bss_type = MLAN_BSS_TYPE_UAP; - /* Initialize private structures */ - woal_init_priv(priv, MOAL_IOCTL_WAIT); - - if (bss_role == MLAN_BSS_ROLE_UAP) { + if (*bss_role == MLAN_BSS_ROLE_UAP) { /* Switch: STA -> uAP */ /* Setup the OS Interface to our functions */ #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,29) @@ -1881,7 +1854,7 @@ woal_set_get_bss_role(moal_private * priv, struct iwreq *wrq) init_waitqueue_head(&priv->w_stats_wait_q); } #endif /* UAP_WEXT */ - } else if (bss_role == MLAN_BSS_ROLE_STA) { + } else if (*bss_role == MLAN_BSS_ROLE_STA) { /* Switch: uAP -> STA */ /* Setup the OS Interface to our functions */ #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,29) @@ -1903,9 +1876,6 @@ woal_set_get_bss_role(moal_private * priv, struct iwreq *wrq) } #endif /* STA_WEXT */ } - /* Enable interfaces */ - netif_device_attach(dev); - woal_start_queue(dev); } done: @@ -1914,8 +1884,75 @@ woal_set_get_bss_role(moal_private * priv, struct iwreq *wrq) LEAVE(); return ret; } -#endif -#endif + +/** + * @brief Set/Get BSS role + * + * @param priv A pointer to moal_private structure + * @param wrq A pointer to iwreq structure + * + * @return 0 --success, otherwise fail + */ +int +woal_set_get_bss_role(moal_private * priv, struct iwreq *wrq) +{ + int ret = 0; + int bss_role = 0; + t_u8 action = MLAN_ACT_GET; + + ENTER(); + + if (wrq->u.data.length) { + if (copy_from_user(&bss_role, wrq->u.data.pointer, sizeof(int))) { + PRINTM(MERROR, "Copy from user failed\n"); + ret = -EFAULT; + goto done; + } + if ((bss_role != MLAN_BSS_ROLE_STA && + bss_role != MLAN_BSS_ROLE_UAP) || + (priv->bss_type != MLAN_BSS_TYPE_WIFIDIRECT)) { + PRINTM(MWARN, "Invalid BSS role\n"); + ret = -EINVAL; + goto done; + } + if (bss_role == GET_BSS_ROLE(priv)) { + PRINTM(MWARN, "Already BSS is in desired role\n"); + ret = -EINVAL; + goto done; + } + action = MLAN_ACT_SET; + /* Reset interface */ + woal_reset_intf(priv, MOAL_IOCTL_WAIT, MFALSE); + } + + if (MLAN_STATUS_SUCCESS != woal_bss_role_cfg(priv, + action, MOAL_IOCTL_WAIT, + (t_u8 *) & bss_role)) { + ret = -EFAULT; + goto done; + } + + if (!wrq->u.data.length) { + if (copy_to_user(wrq->u.data.pointer, &bss_role, sizeof(int))) { + ret = -EFAULT; + goto done; + } + wrq->u.data.length = 1; + } else { + /* Initialize private structures */ + woal_init_priv(priv, MOAL_IOCTL_WAIT); + + /* Enable interfaces */ + netif_device_attach(priv->netdev); + woal_start_queue(priv->netdev); + } + + done: + LEAVE(); + return ret; +} +#endif /* STA_WEXT || UAP_WEXT */ +#endif /* STA_SUPPORT && UAP_SUPPORT */ #endif /* WIFI_DIRECT_SUPPORT && V14_FEATURE */ /** @@ -1993,6 +2030,7 @@ woal_cancel_hs(moal_private * priv, t_u8 wait_option) return ret; } +#if defined(SDIO_SUSPEND_RESUME) /** @brief This function enables the host sleep * * @param priv A Pointer to the moal_private structure @@ -2074,6 +2112,7 @@ woal_enable_hs(moal_private * priv) LEAVE(); return hs_actived; } +#endif /** * @brief This function send soft_reset command to firmware @@ -2524,6 +2563,48 @@ woal_get_pm_info(moal_private * priv, mlan_ds_ps_info * pm_info) return ret; } +/** + * @brief Get Deep Sleep + * + * @param priv Pointer to the moal_private driver data struct + * @param data Pointer to return deep_sleep setting + * + * @return 0 --success, otherwise fail + */ +int +woal_get_deep_sleep(moal_private * priv, t_u32 * data) +{ + int ret = 0; + mlan_ioctl_req *req = NULL; + mlan_ds_pm_cfg *pm = NULL; + + ENTER(); + + req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_pm_cfg)); + if (req == NULL) { + LEAVE(); + return -ENOMEM; + } + pm = (mlan_ds_pm_cfg *) req->pbuf; + pm->sub_command = MLAN_OID_PM_CFG_DEEP_SLEEP; + req->req_id = MLAN_IOCTL_PM_CFG; + + req->action = MLAN_ACT_GET; + if (MLAN_STATUS_SUCCESS != woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT)) { + ret = -EFAULT; + goto done; + } + *data = pm->param.auto_deep_sleep.auto_ds; + *(data + 1) = pm->param.auto_deep_sleep.idletime; + + done: + if (req) + kfree(req); + + LEAVE(); + return ret; +} + /** * @brief Set Deep Sleep * @@ -2665,8 +2746,7 @@ woal_11h_channel_check_ioctl(moal_private * priv) * @return MLAN_STATUS_SUCCESS -- success, otherwise fail */ mlan_status -woal_cfg80211_wifi_direct_mode_cfg(moal_private * priv, t_u16 action, - t_u16 * mode) +woal_wifi_direct_mode_cfg(moal_private * priv, t_u16 action, t_u16 * mode) { mlan_status ret = MLAN_STATUS_SUCCESS; mlan_ioctl_req *req = NULL; @@ -3640,6 +3720,13 @@ woal_set_bg_scan(moal_private * priv, char *buf, int length) ptr += 2; buf_left -= 2; break; + case WEXT_BGSCAN_REPEAT_SECTION: + priv->scan_cfg.repeat_count = (t_u16) ptr[1]; + PRINTM(MIOCTL, "BG scan: repeat_count=%d\n", + (int) priv->scan_cfg.repeat_count); + ptr += 2; + buf_left -= 2; + break; case WEXT_BGSCAN_INTERVAL_SECTION: priv->scan_cfg.scan_interval = (ptr[2] << 8 | ptr[1]) * 1000; PRINTM(MIOCTL, "BG scan: scan_interval=%d\n", @@ -3728,7 +3815,7 @@ woal_reconfig_bgscan(moal_handle * handle) * @brief set rssi low threshold * * @param priv A pointer to moal_private structure - * @param scan_type MLAN_SCAN_TYPE_ACTIVE/MLAN_SCAN_TYPE_PASSIVE + * @param rssi A pointer to low rssi * * @return MLAN_STATUS_SUCCESS -- success, otherwise fail */ @@ -3754,10 +3841,16 @@ woal_set_rssi_low_threshold(moal_private * priv, char *rssi) misc->sub_command = MLAN_OID_MISC_SUBSCRIBE_EVENT; req->action = MLAN_ACT_SET; misc->param.subscribe_event.evt_bitmap = SUBSCRIBE_EVT_RSSI_LOW; + misc->param.subscribe_event.evt_bitmap |= SUBSCRIBE_EVT_PRE_BEACON_LOST; + misc->param.subscribe_event.pre_beacon_miss = DEFAULT_PRE_BEACON_MISS; + if (MLAN_STATUS_SUCCESS != woal_atoi(&low_rssi, rssi)) { ret = -EFAULT; goto done; } +#ifdef STA_CFG80211 + priv->mrvl_rssi_low = low_rssi; +#endif misc->param.subscribe_event.low_rssi = low_rssi; misc->param.subscribe_event.low_rssi_freq = 0; if (MLAN_STATUS_SUCCESS != woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT)) { @@ -3771,6 +3864,69 @@ woal_set_rssi_low_threshold(moal_private * priv, char *rssi) return ret; } +#ifdef STA_CFG80211 +/** + * @brief set rssi low threshold + * + * @param priv A pointer to moal_private structure + * @param event_id event id. + * + * @return MLAN_STATUS_SUCCESS -- success, otherwise fail + */ +mlan_status +woal_set_rssi_threshold(moal_private * priv, t_u32 event_id) +{ + mlan_status ret = MLAN_STATUS_SUCCESS; + mlan_ioctl_req *req = NULL; + mlan_ds_misc_cfg *misc = NULL; + + ENTER(); + if (priv->media_connected == MFALSE) + goto done; + if (priv->mrvl_rssi_low) + goto done; + if (event_id == MLAN_EVENT_ID_FW_BCN_RSSI_LOW) { + if (priv->last_rssi_low < 100) + priv->last_rssi_low += priv->cqm_rssi_hyst; + priv->last_rssi_high = abs(priv->cqm_rssi_thold); + } else if (event_id == MLAN_EVENT_ID_FW_BCN_RSSI_HIGH) { + priv->last_rssi_low = abs(priv->cqm_rssi_thold); + if (priv->last_rssi_high > priv->cqm_rssi_hyst) + priv->last_rssi_high -= priv->cqm_rssi_hyst; + } else { + priv->last_rssi_low = abs(priv->cqm_rssi_thold); + priv->last_rssi_high = abs(priv->cqm_rssi_thold); + } + + req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_misc_cfg)); + if (req == NULL) { + ret = -ENOMEM; + goto done; + } + misc = (mlan_ds_misc_cfg *) req->pbuf; + req->req_id = MLAN_IOCTL_MISC_CFG; + misc->sub_command = MLAN_OID_MISC_SUBSCRIBE_EVENT; + req->action = MLAN_ACT_SET; + misc->param.subscribe_event.evt_bitmap = + SUBSCRIBE_EVT_RSSI_LOW | SUBSCRIBE_EVT_RSSI_HIGH; + misc->param.subscribe_event.low_rssi_freq = 0; + misc->param.subscribe_event.low_rssi = priv->last_rssi_low; + misc->param.subscribe_event.high_rssi_freq = 0; + misc->param.subscribe_event.high_rssi = priv->last_rssi_high; + PRINTM(MIOCTL, "rssi_low=%d, rssi_high=%d\n", (int) priv->last_rssi_low, + (int) priv->last_rssi_high); + if (MLAN_STATUS_SUCCESS != woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT)) { + ret = -EFAULT; + goto done; + } + done: + if (req) + kfree(req); + LEAVE(); + return ret; +} +#endif + /** * @brief Get power mode * diff --git a/drivers/net/wireless/sd8797/mlinux/moal_main.c b/drivers/net/wireless/sd8797/mlinux/moal_main.c index eac248b70129..d5bed42fa73d 100644 --- a/drivers/net/wireless/sd8797/mlinux/moal_main.c +++ b/drivers/net/wireless/sd8797/mlinux/moal_main.c @@ -47,6 +47,11 @@ Change log: #include #include "moal_eth_ioctl.h" +#include +#include +#include +#include + /******************************************************** Local Variables ********************************************************/ @@ -205,7 +210,7 @@ int woal_close(struct net_device *dev); int woal_set_mac_address(struct net_device *dev, void *addr); void woal_tx_timeout(struct net_device *dev); struct net_device_stats *woal_get_stats(struct net_device *dev); -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,34) +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,29) u16 woal_select_queue(struct net_device *dev, struct sk_buff *skb); #endif @@ -404,7 +409,7 @@ woal_init_sw(moal_handle * handle) /* PnP and power profile */ handle->surprise_removed = MFALSE; init_waitqueue_head(&handle->init_wait_q); -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,34) +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,29) spin_lock_init(&handle->queue_lock); #endif @@ -1215,9 +1220,7 @@ const struct net_device_ops woal_netdev_ops = { #else .ndo_set_multicast_list = woal_set_multicast_list, #endif -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,34) .ndo_select_queue = woal_select_queue, -#endif }; #endif @@ -1292,9 +1295,7 @@ const struct net_device_ops woal_uap_netdev_ops = { #else .ndo_set_multicast_list = woal_uap_set_multicast_list, #endif -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,34) .ndo_select_queue = woal_select_queue, -#endif }; #endif @@ -1373,7 +1374,7 @@ woal_add_interface(moal_handle * handle, t_u8 bss_index, t_u8 bss_type) moal_private *priv = NULL; ENTER(); -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,34) +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,29) #define MAX_WMM_QUEUE 4 /* Allocate an Ethernet device */ if (!(dev = alloc_etherdev_mq(sizeof(moal_private), MAX_WMM_QUEUE))) { @@ -1420,11 +1421,8 @@ woal_add_interface(moal_handle * handle, t_u8 bss_index, t_u8 bss_type) else if (bss_type == MLAN_BSS_TYPE_WIFIDIRECT) priv->bss_role = MLAN_BSS_ROLE_STA; #endif -#if defined(STA_CFG80211) || defined(UAP_CFG80211) - priv->probereq_index = MLAN_CUSTOM_IE_AUTO_IDX_MASK; -#endif -#ifdef STA_SUPPORT -#endif + + INIT_LIST_HEAD(&priv->tcp_sess_queue); #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24) SET_MODULE_OWNER(dev); @@ -1448,7 +1446,7 @@ woal_add_interface(moal_handle * handle, t_u8 bss_index, t_u8 bss_type) if ((priv->bss_role == MLAN_BSS_ROLE_STA) && IS_STA_CFG80211(cfg80211_wext)) { if (bss_type == MLAN_BSS_TYPE_STA #if defined(WIFI_DIRECT_SUPPORT) -#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,0,0) || defined(COMPAT_WIRELESS) +#if LINUX_VERSION_CODE >= WIFI_DIRECT_KERNEL_VERSION || bss_type == MLAN_BSS_TYPE_WIFIDIRECT #endif #endif @@ -1883,7 +1881,14 @@ woal_close(struct net_device *dev) moal_private *priv = (moal_private *) netdev_priv(dev); ENTER(); - +#ifdef STA_SUPPORT +#ifdef STA_CFG80211 + if (IS_STA_CFG80211(cfg80211_wext) && priv->scan_request) { + cfg80211_scan_done(priv->scan_request, MTRUE); + priv->scan_request = NULL; + } +#endif +#endif woal_stop_queue(priv->netdev); MODULE_PUT; @@ -2066,7 +2071,7 @@ woal_get_stats(struct net_device *dev) return &priv->stats; } -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,34) +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,29) /** * @brief This function handles wmm queue select * @@ -2108,6 +2113,233 @@ woal_select_queue(struct net_device * dev, struct sk_buff * skb) } #endif +/** + * @brief This function gets tcp session from the tcp session queue + * + * @param priv A pointer to moal_private structure + * @param src_ip IP address of the device + * @param src_port TCP port of the device + * @param dst_ip IP address of the client + * @param src_port TCP port of the client + * + * @return A pointer to the tcp session data structure, if found. + * Otherwise, null + */ +struct tcp_sess * +woal_get_tcp_sess(moal_private * priv, + t_u32 src_ip, t_u16 src_port, t_u32 dst_ip, t_u16 dst_port) +{ + struct tcp_sess *tcp_sess = NULL; + ENTER(); + + list_for_each_entry(tcp_sess, &priv->tcp_sess_queue, link) { + if ((tcp_sess->src_ip_addr == src_ip) && + (tcp_sess->src_tcp_port == src_port) && + (tcp_sess->dst_ip_addr == dst_ip) && + (tcp_sess->dst_tcp_port == dst_port)) { + LEAVE(); + return tcp_sess; + } + } + LEAVE(); + return NULL; +} + +/** + * @brief This function checks received tcp packet for FIN + * and release the tcp session if received + * + * @param priv A pointer to moal_private structure + * @param skb A pointer to sk_buff structure + * + * @return None + */ +void +woal_check_tcp_fin(moal_private * priv, struct sk_buff *skb) +{ + struct ethhdr *ethh = NULL; + struct iphdr *iph = NULL; + struct tcphdr *tcph = NULL; + struct tcp_sess *tcp_sess = NULL; + + ENTER(); + + ethh = eth_hdr(skb); + if (ntohs(ethh->h_proto) == ETH_P_IP) { + iph = (struct iphdr *) ((t_u8 *) ethh + sizeof(struct ethhdr)); + if (iph->protocol == IPPROTO_TCP) { + tcph = (struct tcphdr *) ((t_u8 *) iph + iph->ihl * 4); + if (tcph->fin) { + tcp_sess = woal_get_tcp_sess(priv, iph->daddr, + tcph->dest, iph->saddr, + tcph->source); + if (tcp_sess != NULL) { + PRINTM(MINFO, + "TX: release a tcp session in dl. (src: ipaddr 0x%08x, port: %d. dst: ipaddr 0x%08x, port: %d\n", + iph->daddr, tcph->dest, iph->saddr, tcph->source); + /* remove the tcp session from the queue */ + list_del(&tcp_sess->link); + kfree(tcp_sess); + } else { + PRINTM(MINFO, "Tx: released TCP session is not found.\n "); + } + } + } + } + LEAVE(); +} + +/** + * @brief This function process tcp ack packets + * + * @param priv A pointer to moal_private structure + * @param pmbuf A pointer to the mlan buffer associated with the skb + * + * @return 1, if a tcp ack packet has been dropped. Otherwise, 0. + */ +int +woal_process_tcp_ack(moal_private * priv, mlan_buffer * pmbuf) +{ + int ret = 0; + struct ethhdr *ethh = NULL; + struct iphdr *iph = NULL; + struct tcphdr *tcph = NULL; + struct tcp_sess *tcp_sess = NULL; + struct sk_buff *skb = NULL; + t_u32 ack_seq = 0; + t_u32 len = 0; + t_u8 opt = 0; + t_u8 opt_len = 0; + t_u8 *pos = NULL; + t_u32 win_size = 0; + +#define TCP_ACK_DELAY 3 +#define TCP_ACK_INIT_WARMING_UP 1000 /* initial */ +#define TCP_ACK_RECV_WARMING_UP 1000 /* recovery */ + + ENTER(); + + /** check the tcp packet */ + ethh = (struct ethhdr *) (pmbuf->pbuf + pmbuf->data_offset); + if (ntohs(ethh->h_proto) != ETH_P_IP) { + return 0; + } + iph = (struct iphdr *) ((t_u8 *) ethh + sizeof(struct ethhdr)); + if (iph->protocol != IPPROTO_TCP) { + return 0; + } + tcph = (struct tcphdr *) ((t_u8 *) iph + iph->ihl * 4); + + if (tcph->syn & tcph->ack) { + /* respond to a TCP request. create a tcp session */ + if (!(tcp_sess = kmalloc(sizeof(struct tcp_sess), GFP_ATOMIC))) { + PRINTM(MERROR, "Fail to allocate tcp_sess.\n"); + return 0; + } + memset(tcp_sess, 0, sizeof(struct tcp_sess)); + tcp_sess->src_ip_addr = iph->saddr; /* my ip addr */ + tcp_sess->dst_ip_addr = iph->daddr; + tcp_sess->src_tcp_port = tcph->source; + tcp_sess->dst_tcp_port = tcph->dest; + tcp_sess->start_cnt = TCP_ACK_INIT_WARMING_UP; + + INIT_LIST_HEAD(&tcp_sess->link); + list_add_tail(&tcp_sess->link, &priv->tcp_sess_queue); + PRINTM(MINFO, + "create a tcp session. (src: ipaddr 0x%08x, port: %d. dst: ipaddr 0x%08x, port: %d\n", + iph->saddr, tcph->source, iph->daddr, tcph->dest); + + /* parse tcp options for the window scale */ + len = (tcph->doff * 4) - sizeof(struct tcphdr); + pos = (t_u8 *) (tcph + 1); + while (len > 0) { + opt = *pos++; + switch (opt) { + case TCPOPT_EOL: + len = 0; + continue; + case TCPOPT_NOP: + len--; + continue; + case TCPOPT_WINDOW: + opt_len = *pos++; + if (opt_len == TCPOLEN_WINDOW) { + tcp_sess->rx_win_scale = *pos; + tcp_sess->rx_win_opt = 1; + if (tcp_sess->rx_win_scale > 14) + tcp_sess->rx_win_scale = 14; + PRINTM(MINFO, "TCP Window Scale: %d \n", + tcp_sess->rx_win_scale); + } + break; + default: + opt_len = *pos++; + } + len -= opt_len; + pos += opt_len - 2; + } + } else if (tcph->ack && !(tcph->syn) && + (ntohs(iph->tot_len) == (iph->ihl * 4 + tcph->doff * 4))) { + /** it is an ack packet, not a piggyback ack */ + tcp_sess = woal_get_tcp_sess(priv, iph->saddr, tcph->source, + iph->daddr, tcph->dest); + if (tcp_sess == NULL) { + return 0; + } + /** do not drop the ack packets initially */ + if (tcp_sess->start_cnt) { + tcp_sess->start_cnt--; + return 0; + } + + /* check the window size. */ + win_size = ntohs(tcph->window); + if (tcp_sess->rx_win_opt) { + win_size <<= tcp_sess->rx_win_scale; + /* Note: it may depend on the rtd */ + if ((win_size > 1500 * (TCP_ACK_DELAY + 5)) && + (tcp_sess->ack_cnt < TCP_ACK_DELAY)) { + /* if windiow is big enough, drop the ack packet */ + if (tcp_sess->ack_seq != ntohl(tcph->ack_seq)) { + ack_seq = tcp_sess->ack_seq; + tcp_sess->ack_seq = ntohl(tcph->ack_seq); + tcp_sess->ack_cnt++; + skb = (struct sk_buff *) pmbuf->pdesc; + if (skb) + dev_kfree_skb_any(skb); + ret = 1; + } else { + /* the ack packet is retransmitted. thus, stop dropping + the ack packets */ + tcp_sess->start_cnt = TCP_ACK_RECV_WARMING_UP; + PRINTM(MINFO, "Recover the TCP session.\n "); + } + } else { + /* send the current ack pacekt */ + ack_seq = tcp_sess->ack_seq; + tcp_sess->ack_seq = ntohl(tcph->ack_seq); + tcp_sess->ack_cnt = 0; + ret = 0; + } + } + } else if (tcph->fin) { + tcp_sess = woal_get_tcp_sess(priv, iph->saddr, tcph->source, + iph->daddr, tcph->dest); + if (tcp_sess != NULL) { + /* remove the tcp session from the queue */ + PRINTM(MINFO, + "Rx: release a tcp session in ul. (src: ipaddr 0x%08x, port: %d. dst: ipaddr 0x%08x, port: %d\n", + iph->saddr, tcph->source, iph->daddr, tcph->dest); + list_del(&tcp_sess->link); + kfree(tcp_sess); + } else { + PRINTM(MINFO, "released TCP session is not found.\n "); + } + } + LEAVE(); + return ret; +} + /** * @brief This function handles packet transmission * @@ -2165,6 +2397,13 @@ woal_hard_start_xmit(struct sk_buff *skb, struct net_device *dev) memset((t_u8 *) pmbuf, 0, sizeof(mlan_buffer)); pmbuf->bss_index = priv->bss_index; woal_fill_mlan_buffer(priv, pmbuf, skb); + if (priv->enable_tcp_ack_enh == MTRUE) { + if (woal_process_tcp_ack(priv, pmbuf)) { + /* the ack packet has been dropped */ + goto done; + } + } + status = mlan_send_packet(priv->phandle->pmlan_adapter, pmbuf); switch (status) { case MLAN_STATUS_PENDING: @@ -2394,6 +2633,8 @@ woal_set_multicast_list(struct net_device *dev) void woal_init_priv(moal_private * priv, t_u8 wait_option) { + struct list_head *link = NULL; + struct tcp_sess *tcp_sess = NULL; ENTER(); #ifdef STA_SUPPORT if (GET_BSS_ROLE(priv) == MLAN_BSS_ROLE_STA) { @@ -2414,7 +2655,7 @@ woal_init_priv(moal_private * priv, t_u8 wait_option) if (IS_STA_CFG80211(cfg80211_wext)) { if (priv->bss_type == MLAN_BSS_TYPE_STA #if defined(WIFI_DIRECT_SUPPORT) -#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,0,0) || defined(COMPAT_WIRELESS) +#if LINUX_VERSION_CODE >= WIFI_DIRECT_KERNEL_VERSION || priv->bss_type == MLAN_BSS_TYPE_WIFIDIRECT #endif #endif @@ -2434,6 +2675,25 @@ woal_init_priv(moal_private * priv, t_u8 wait_option) } #endif priv->media_connected = MFALSE; + +#if defined(STA_CFG80211) || defined(UAP_CFG80211) + priv->probereq_index = MLAN_CUSTOM_IE_AUTO_IDX_MASK; +#endif +#ifdef STA_SUPPORT +#endif + + priv->enable_tcp_ack_enh = MTRUE; + while (!list_empty(&priv->tcp_sess_queue)) { + link = priv->tcp_sess_queue.next; + tcp_sess = list_entry(link, struct tcp_sess, link); + PRINTM(MINFO, + "warm reset: release a tcp session in dl. (src: ipaddr 0x%08x, port: %d. dst: ipaddr 0x%08x, port: %d\n", + tcp_sess->src_ip_addr, tcp_sess->src_tcp_port, + tcp_sess->dst_ip_addr, tcp_sess->dst_tcp_port); + list_del(link); + kfree(tcp_sess); + } + woal_request_get_fw_info(priv, wait_option, NULL); LEAVE(); @@ -2805,8 +3065,9 @@ woal_reassociation_thread(void *data) for (i = 0; i < handle->priv_num && (priv = handle->priv[i]); i++) { - if (priv->reassoc_required == MFALSE) + if (priv->reassoc_required == MFALSE) { continue; + } memset(&bss_info, 0x00, sizeof(bss_info)); @@ -2892,7 +3153,6 @@ woal_reassociation_thread(void *data) mlan_ioctl_req *req = NULL; reassoc_timer_req = MFALSE; - if (priv->rate_index != AUTO_RATE) { req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_rate)); @@ -2928,11 +3188,13 @@ woal_reassociation_thread(void *data) break; if (reassoc_timer_req == MTRUE) { - PRINTM(MEVENT, - "Reassoc: No AP found or assoc failed. " - "Restarting re-assoc Timer: %d\n", (int) timer_val); handle->is_reassoc_timer_set = MTRUE; - woal_mod_timer(&handle->reassoc_timer, timer_val); + { + PRINTM(MEVENT, + "Reassoc: No AP found or assoc failed. " + "Restarting re-assoc Timer: %d\n", (int) timer_val); + woal_mod_timer(&handle->reassoc_timer, timer_val); + } } } woal_deactivate_thread(pmoal_thread); @@ -3083,7 +3345,7 @@ woal_moal_debug_info(moal_private * priv, moal_handle * handle, u8 flag) { moal_handle *phandle = NULL; char buf[MLAN_MAX_VER_STR_LEN]; -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,34) +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,29) int i = 0; #endif @@ -3122,7 +3384,7 @@ woal_moal_debug_info(moal_private * priv, moal_handle * handle, u8 flag) MFALSE) ? "Disconnected" : "Connected")); PRINTM(MERROR, "carrier %s\n", ((netif_carrier_ok(priv->netdev)) ? "on" : "off")); -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,34) +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,29) for (i = 0; i < (priv->netdev->num_tx_queues); i++) { PRINTM(MERROR, "tx queue %d: %s\n", i, ((netif_tx_queue_stopped @@ -3599,11 +3861,11 @@ woal_init_module(void) /* Init mutex */ MOAL_INIT_SEMAPHORE(&AddRemoveCardSem); + wifi_add_dev(); + /* Register with bus */ ret = woal_bus_register(); - wifi_add_dev(); - LEAVE(); return ret; } @@ -3645,7 +3907,8 @@ woal_cleanup_module(void) if (handle->priv[i]->media_connected == MTRUE) woal_disconnect(handle->priv[i], MOAL_CMD_WAIT, NULL); #ifdef STA_CFG80211 - if (handle->priv[i]->scan_request) { + if (IS_STA_CFG80211(cfg80211_wext) && + handle->priv[i]->scan_request) { cfg80211_scan_done(handle->priv[i]->scan_request, MTRUE); handle->priv[i]->scan_request = NULL; } @@ -3681,13 +3944,13 @@ woal_cleanup_module(void) MOAL_CMD_WAIT); } - wifi_del_dev(); - exit: MOAL_REL_SEMAPHORE(&AddRemoveCardSem); exit_sem_err: /* Unregister from bus */ woal_bus_unregister(); + wifi_del_dev(); + LEAVE(); } @@ -3749,7 +4012,7 @@ module_param(init_cfg, charp, 0); MODULE_PARM_DESC(init_cfg, "Init config file name"); module_param(cal_data_cfg, charp, 0); MODULE_PARM_DESC(cal_data_cfg, "Calibration data file name"); -module_param(minicard_pwrup, int, 0); +module_param(minicard_pwrup, int, 1); MODULE_PARM_DESC(minicard_pwrup, "1: Driver load clears PDn/Rst, unload sets (default); 0: Don't do this."); module_param(cfg80211_wext, int, 0); diff --git a/drivers/net/wireless/sd8797/mlinux/moal_main.h b/drivers/net/wireless/sd8797/mlinux/moal_main.h index cd1fdd8244c1..32426a149779 100644 --- a/drivers/net/wireless/sd8797/mlinux/moal_main.h +++ b/drivers/net/wireless/sd8797/mlinux/moal_main.h @@ -2,7 +2,7 @@ * * @brief This file contains wlan driver specific defines etc. * - * Copyright (C) 2008-2011, Marvell International Ltd. + * Copyright (C) 2008-2012, Marvell International Ltd. * * This software file (the "File") is distributed by Marvell International * Ltd. under the terms of the GNU General Public License Version 2, June 1991 @@ -49,8 +49,9 @@ Change log: #include #include #include -#include -#include +#include +#include +#include #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,18) #include @@ -654,6 +655,24 @@ struct debug_data_priv /** IP address operation: Remove */ #define IPADDR_OP_REMOVE 0 +struct tcp_sess +{ + struct list_head link; + /** tcp session info */ + t_u32 src_ip_addr; + t_u32 dst_ip_addr; + t_u16 src_tcp_port; + t_u16 dst_tcp_port; + /** tcp window info */ + t_u8 rx_win_opt; + t_u32 rx_win_scale; + /** warming up counter */ + t_u32 start_cnt; + /** tx ack packet info */ + t_u32 ack_seq; + t_u32 ack_cnt; +}; + /** Private structure for MOAL */ struct _moal_private { @@ -715,6 +734,18 @@ struct _moal_private t_u8 cfg_bssid[ETH_ALEN]; /** Disconnect request from CFG80211 */ bool cfg_disconnect; + /** rssi_threshold */ + s32 cqm_rssi_thold; + /** rssi hysteresis */ + u32 cqm_rssi_hyst; + /** last rssi_low */ + u8 last_rssi_low; + /** last rssi_high */ + u8 last_rssi_high; + /** mrvl rssi threshold */ + u8 mrvl_rssi_low; + /** rssi status */ + u32 rssi_status; #endif /* STA_SUPPORT */ #endif /* STA_CFG80211 */ /** IOCTL wait queue */ @@ -779,6 +810,11 @@ struct _moal_private /** MLAN debug info */ struct debug_data_priv items_priv; #endif + + /** tcp session queue */ + struct list_head tcp_sess_queue; + /** TCP Ack enhance flag */ + t_u8 enable_tcp_ack_enh; }; /** Handle data structure for MOAL */ @@ -818,6 +854,7 @@ struct _moal_handle t_u16 init_wait_q_woken; /** Init wait queue */ wait_queue_head_t init_wait_q __ATTRIB_ALIGN__; +#if defined(SDIO_SUSPEND_RESUME) /** Device suspend flag */ BOOLEAN is_suspended; #ifdef SDIO_SUSPEND_RESUME @@ -830,6 +867,7 @@ struct _moal_handle t_u16 hs_activate_wait_q_woken; /** Host Sleep activated event wait queue */ wait_queue_head_t hs_activate_wait_q __ATTRIB_ALIGN__; +#endif /** Card pointer */ t_void *card; /** Rx pending in MLAN */ @@ -844,12 +882,14 @@ struct _moal_handle t_u32 lock_count; /** mlan buffer alloc count */ t_u32 mbufalloc_count; +#if defined(SDIO_SUSPEND_RESUME) /** hs skip count */ t_u32 hs_skip_count; /** hs force count */ t_u32 hs_force_count; /** suspend_fail flag */ BOOLEAN suspend_fail; +#endif #ifdef REASSOCIATION /** Re-association thread */ moal_thread reassoc_thread; @@ -923,7 +963,7 @@ struct _moal_handle t_u8 cmd52_reg; /** cmd52 value */ t_u8 cmd52_val; -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,34) +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,29) /** spinlock to stop_queue/wake_queue*/ spinlock_t queue_lock; #endif @@ -939,7 +979,7 @@ struct _moal_handle static inline void woal_set_trans_start(struct net_device *dev) { -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,34) +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,31) unsigned int i; for (i = 0; i < dev->num_tx_queues; i++) { netdev_get_tx_queue(dev, i)->trans_start = jiffies; @@ -958,7 +998,7 @@ woal_set_trans_start(struct net_device *dev) static inline void woal_start_queue(struct net_device *dev) { -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,34) +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,29) netif_start_queue(dev); #else netif_tx_start_all_queues(dev); @@ -975,7 +1015,7 @@ woal_start_queue(struct net_device *dev) static inline void woal_stop_queue(struct net_device *dev) { -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,34) +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,29) unsigned long flags; moal_private *priv = (moal_private *) netdev_priv(dev); spin_lock_irqsave(&priv->phandle->queue_lock, flags); @@ -1000,7 +1040,7 @@ woal_stop_queue(struct net_device *dev) static inline void woal_wake_queue(struct net_device *dev) { -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,34) +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,29) unsigned long flags; moal_private *priv = (moal_private *) netdev_priv(dev); spin_lock_irqsave(&priv->phandle->queue_lock, flags); @@ -1217,6 +1257,8 @@ typedef struct _HostCmd_DS_802_11_CFG_DATA #define WEXT_BGSCAN_RSSI_SECTION 'R' /** BGSCAN SCAN INTERVAL SECTION */ #define WEXT_BGSCAN_INTERVAL_SECTION 'T' +/** BGSCAN REPEAT SECTION */ +#define WEXT_BGSCAN_REPEAT_SECTION 'E' /** band AUTO */ #define WIFI_FREQUENCY_BAND_AUTO 0 @@ -1316,11 +1358,15 @@ mlan_status woal_set_get_hs_params(moal_private * priv, t_u16 action, t_u8 wait_option, mlan_ds_hs_cfg * hscfg); /** Cancel Host Sleep configuration */ mlan_status woal_cancel_hs(moal_private * priv, t_u8 wait_option); +#if defined(SDIO_SUSPEND_RESUME) /** Enable Host Sleep configuration */ int woal_enable_hs(moal_private * priv); /** hs active timeout 2 second */ #define HS_ACTIVE_TIMEOUT (2 * HZ) +#endif +/** get deep sleep */ +int woal_get_deep_sleep(moal_private * priv, t_u32 * data); /** set deep sleep */ int woal_set_deep_sleep(moal_private * priv, t_u8 wait_option, BOOLEAN bdeep_sleep, t_u16 idletime); @@ -1431,6 +1477,8 @@ int woal_host_command(moal_private * priv, struct iwreq *wrq); #if defined(WIFI_DIRECT_SUPPORT) #if defined(STA_SUPPORT) && defined(UAP_SUPPORT) #if defined(STA_WEXT) || defined(UAP_WEXT) +mlan_status woal_bss_role_cfg(moal_private * priv, t_u8 action, + t_u8 wait_option, t_u8 * bss_role); int woal_set_get_bss_role(moal_private * priv, struct iwreq *wrq); #endif #endif @@ -1443,8 +1491,8 @@ int woal_hostcmd_ioctl(struct net_device *dev, struct ifreq *req); #if defined(WIFI_DIRECT_SUPPORT) mlan_status woal_set_remain_channel_ioctl(moal_private * priv, t_u8 wait_option, mlan_ds_remain_chan * pchan); -mlan_status woal_cfg80211_wifi_direct_mode_cfg(moal_private * priv, - t_u16 action, t_u16 * mode); +mlan_status woal_wifi_direct_mode_cfg(moal_private * priv, t_u16 action, + t_u16 * mode); #endif /* WIFI_DIRECT_SUPPORT */ #ifdef CONFIG_PROC_FS @@ -1502,9 +1550,15 @@ mlan_status woal_remove_rxfilter(moal_private * priv, char *rxfilter); mlan_status woal_set_qos_cfg(moal_private * priv, char *qos_cfg); int woal_set_sleeppd(moal_private * priv, char *psleeppd); mlan_status woal_set_rssi_low_threshold(moal_private * priv, char *rssi); +mlan_status woal_set_rssi_threshold(moal_private * priv, t_u32 event_id); mlan_status woal_set_bg_scan(moal_private * priv, char *buf, int length); mlan_status woal_stop_bg_scan(moal_private * priv); void woal_reconfig_bgscan(moal_handle * handle); #endif +struct tcp_sess *woal_get_tcp_sess(moal_private * priv, + t_u32 src_ip, t_u16 src_port, + t_u32 dst_ip, t_u16 dst_port); +void woal_check_tcp_fin(moal_private * priv, struct sk_buff *skb); + #endif /* _MOAL_MAIN_H */ diff --git a/drivers/net/wireless/sd8797/mlinux/moal_priv.c b/drivers/net/wireless/sd8797/mlinux/moal_priv.c index e3e4b844e11b..9a5173ddfb3f 100644 --- a/drivers/net/wireless/sd8797/mlinux/moal_priv.c +++ b/drivers/net/wireless/sd8797/mlinux/moal_priv.c @@ -101,6 +101,13 @@ woal_warm_reset(moal_private * priv) moal_handle *handle = priv->phandle; mlan_ioctl_req *req = NULL; mlan_ds_misc_cfg *misc = NULL; +#if defined(WIFI_DIRECT_SUPPORT) +#if defined(STA_SUPPORT) && defined(UAP_SUPPORT) +#if defined(STA_WEXT) || defined(UAP_WEXT) + t_u8 bss_role = MLAN_BSS_ROLE_STA; +#endif +#endif +#endif /* WIFI_DIRECT_SUPPORT && V14_FEATURE */ ENTER(); @@ -110,8 +117,24 @@ woal_warm_reset(moal_private * priv) ret = woal_reset_intf(priv, MOAL_IOCTL_WAIT, MTRUE); /* Initialize private structures */ - for (intf_num = 0; intf_num < handle->priv_num; intf_num++) + for (intf_num = 0; intf_num < handle->priv_num; intf_num++) { woal_init_priv(handle->priv[intf_num], MOAL_IOCTL_WAIT); +#if defined(WIFI_DIRECT_SUPPORT) +#if defined(STA_SUPPORT) && defined(UAP_SUPPORT) +#if defined(STA_WEXT) || defined(UAP_WEXT) + if (handle->priv[intf_num]->bss_type == MLAN_BSS_TYPE_WIFIDIRECT) { + if (MLAN_STATUS_SUCCESS != woal_bss_role_cfg(handle->priv[intf_num], + MLAN_ACT_SET, + MOAL_IOCTL_WAIT, + &bss_role)) { + ret = -EFAULT; + goto done; + } + } +#endif /* STA_WEXT || UAP_WEXT */ +#endif /* STA_SUPPORT && UAP_SUPPORT */ +#endif /* WIFI_DIRECT_SUPPORT && V14_FEATURE */ + } /* Restart the firmware */ req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_misc_cfg)); @@ -333,48 +356,6 @@ woal_get_signal(moal_private * priv, struct iwreq *wrq) return ret; } -/** - * @brief Get Deep Sleep - * - * @param priv Pointer to the moal_private driver data struct - * @param deep_sleep Pointer to return deep_sleep setting - * - * @return 0 --success, otherwise fail - */ -static int -woal_get_deep_sleep(moal_private * priv, t_u32 * data) -{ - int ret = 0; - mlan_ioctl_req *req = NULL; - mlan_ds_pm_cfg *pm = NULL; - - ENTER(); - - req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_pm_cfg)); - if (req == NULL) { - LEAVE(); - return -ENOMEM; - } - pm = (mlan_ds_pm_cfg *) req->pbuf; - pm->sub_command = MLAN_OID_PM_CFG_DEEP_SLEEP; - req->req_id = MLAN_IOCTL_PM_CFG; - - req->action = MLAN_ACT_GET; - if (MLAN_STATUS_SUCCESS != woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT)) { - ret = -EFAULT; - goto done; - } - *data = pm->param.auto_deep_sleep.auto_ds; - *(data + 1) = pm->param.auto_deep_sleep.idletime; - - done: - if (req) - kfree(req); - - LEAVE(); - return ret; -} - /** * @brief Get/Set DeepSleep mode * @@ -3692,7 +3673,6 @@ static int woal_set_get_ip_addr(moal_private * priv, struct iwreq *wrq) { char buf[IPADDR_MAX_BUF]; - struct iwreq *wreq = (struct iwreq *) wrq; mlan_ioctl_req *ioctl_req = NULL; mlan_ds_misc_cfg *misc = NULL; int ret = 0, op_code = 0, data_length = wrq->u.data.length; @@ -3710,8 +3690,8 @@ woal_set_get_ip_addr(moal_private * priv, struct iwreq *wrq) if (data_length <= 1) { /* GET */ ioctl_req->action = MLAN_ACT_GET; } else { - if (copy_from_user(buf, wreq->u.data.pointer, - MIN(IPADDR_MAX_BUF - 1, wreq->u.data.length))) { + if (copy_from_user(buf, wrq->u.data.pointer, + MIN(IPADDR_MAX_BUF - 1, wrq->u.data.length))) { PRINTM(MERROR, "Copy from user failed\n"); ret = -EFAULT; goto done; @@ -3727,7 +3707,7 @@ woal_set_get_ip_addr(moal_private * priv, struct iwreq *wrq) ioctl_req->action = MLAN_ACT_SET; /* only one IP is supported in current firmware */ memset(misc->param.ipaddr_cfg.ip_addr[0], 0, IPADDR_LEN); - in4_pton(&buf[2], MIN((IPADDR_MAX_BUF - 3), (wreq->u.data.length - 2)), + in4_pton(&buf[2], MIN((IPADDR_MAX_BUF - 3), (wrq->u.data.length - 2)), misc->param.ipaddr_cfg.ip_addr[0], ' ', NULL); /* only one IP is supported in current firmware */ misc->param.ipaddr_cfg.ip_addr_num = 1; @@ -4524,6 +4504,34 @@ woal_get_scan_table_ioctl(moal_private * priv, struct iwreq *wrq) return status; } +/** + * @brief Set user scan ext -- Async mode, without wait + * + * @param priv A pointer to moal_private structure + * @param wrq A pointer to iwreq structure + * + * @return 0 -- success, otherwise fail + */ +static int +woal_set_user_scan_ext_ioctl(moal_private * priv, struct iwreq *wrq) +{ + int ret = 0; + wlan_user_scan_cfg scan_req; + ENTER(); + memset(&scan_req, 0x00, sizeof(scan_req)); + if (copy_from_user + (&scan_req, wrq->u.data.pointer, + MIN(wrq->u.data.length, sizeof(scan_req)))) { + PRINTM(MINFO, "Copy from user failed\n"); + LEAVE(); + return -EFAULT; + } + if (MLAN_STATUS_FAILURE == woal_do_scan(priv, &scan_req)) + ret = -EFAULT; + LEAVE(); + return ret; +} + /** * @brief Set user scan * @@ -5911,6 +5919,86 @@ woal_mgmt_frame_passthru_ctrl(moal_private * priv, struct iwreq *wrq) return ret; } +/** + * @brief Set/Get CFP table codes + * + * @param priv Pointer to the moal_private driver data struct + * @param wrq A pointer to iwreq structure + * + * @return 0 --success, otherwise fail + */ +static int +woal_cfp_code(moal_private * priv, struct iwreq *wrq) +{ + int ret = 0; + int data[2]; + int data_length = wrq->u.data.length; + mlan_ioctl_req *req = NULL; + mlan_ds_misc_cfg *misc_cfg = NULL; + mlan_ds_misc_cfp_code *cfp_code = NULL; + + ENTER(); + + if (data_length > 2) { + PRINTM(MERROR, "Invalid number of argument!\n"); + ret = -EINVAL; + goto done; + } + + /* Allocate an IOCTL request buffer */ + req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_misc_cfg)); + if (req == NULL) { + ret = -ENOMEM; + goto done; + } + + /* Fill request buffer */ + misc_cfg = (mlan_ds_misc_cfg *) req->pbuf; + cfp_code = &misc_cfg->param.cfp_code; + misc_cfg->sub_command = MLAN_OID_MISC_CFP_CODE; + req->req_id = MLAN_IOCTL_MISC_CFG; + + if (!data_length) { + req->action = MLAN_ACT_GET; + } else { + if (copy_from_user + (data, wrq->u.data.pointer, sizeof(int) * data_length)) { + PRINTM(MERROR, "Copy from user failed\n"); + ret = -EFAULT; + goto done; + } + cfp_code->cfp_code_bg = data[0]; + if (data_length == 2) + cfp_code->cfp_code_a = data[1]; + req->action = MLAN_ACT_SET; + } + + /* Send IOCTL request to MLAN */ + if (woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT) != MLAN_STATUS_SUCCESS) { + ret = -EFAULT; + goto done; + } + + if (!data_length) { + data[0] = cfp_code->cfp_code_bg; + data[1] = cfp_code->cfp_code_a; + data_length = 2; + if (copy_to_user(wrq->u.data.pointer, &data, sizeof(int) * data_length)) { + PRINTM(MERROR, "Copy to user failed\n"); + ret = -EFAULT; + goto done; + } + wrq->u.data.length = data_length; + } + + done: + if (req) + kfree(req); + + LEAVE(); + return ret; +} + /** * @brief Set/Get Tx/Rx antenna * @@ -6183,6 +6271,9 @@ woal_wext_do_ioctl(struct net_device *dev, struct ifreq *req, int cmd) case WOAL_MGMT_FRAME_CTRL: ret = woal_mgmt_frame_passthru_ctrl(priv, wrq); break; + case WOAL_CFP_CODE: + ret = woal_cfp_code(priv, wrq); + break; case WOAL_SET_GET_TX_RX_ANT: ret = woal_set_get_tx_rx_ant(priv, wrq); break; @@ -6296,6 +6387,9 @@ woal_wext_do_ioctl(struct net_device *dev, struct ifreq *req, int cmd) case WOAL_GET_SCAN_TABLE: ret = woal_get_scan_table_ioctl(priv, wrq); break; + case WOAL_SET_USER_SCAN_EXT: + ret = woal_set_user_scan_ext_ioctl(priv, wrq); + break; case WOAL_WMM_ADDTS: ret = woal_wmm_addts_req_ioctl(priv, wrq); break; diff --git a/drivers/net/wireless/sd8797/mlinux/moal_priv.h b/drivers/net/wireless/sd8797/mlinux/moal_priv.h index de491f6d6a29..1c24f30502f6 100644 --- a/drivers/net/wireless/sd8797/mlinux/moal_priv.h +++ b/drivers/net/wireless/sd8797/mlinux/moal_priv.h @@ -115,6 +115,8 @@ Change log: /** Private command ID to set/get dfs testing settings */ #define WOAL_DFS_TESTING 33 #endif +/** Private command ID to set/get CFP table codes */ +#define WOAL_CFP_CODE 34 /** Private command ID to set/get tx/rx antenna */ #define WOAL_SET_GET_TX_RX_ANT 35 /** Private command ID to set/get management frame passthru mask */ @@ -226,6 +228,8 @@ Change log: #define WOAL_SET_USER_SCAN 3 /** Private command ID for getscantable */ #define WOAL_GET_SCAN_TABLE 4 +/** Private command ID for setuserscanext: async without wait */ +#define WOAL_SET_USER_SCAN_EXT 5 /** Private command ID to request ADDTS */ #define WOAL_WMM_ADDTS 7 @@ -525,6 +529,11 @@ static const struct iw_priv_args woal_private_args[] = { IW_PRIV_TYPE_INT | 16, IW_PRIV_TYPE_INT | 16, "mgmtframectrl"}, + { + WOAL_CFP_CODE, + IW_PRIV_TYPE_INT | 16, + IW_PRIV_TYPE_INT | 16, + "cfpcode"}, { WOAL_SET_GET_TX_RX_ANT, IW_PRIV_TYPE_INT | 16, @@ -655,6 +664,11 @@ static const struct iw_priv_args woal_private_args[] = { IW_PRIV_TYPE_BYTE | WOAL_2K_BYTES, IW_PRIV_TYPE_BYTE | WOAL_2K_BYTES, "getscantable"}, + { + WOAL_SET_USER_SCAN_EXT, + IW_PRIV_TYPE_BYTE | WOAL_2K_BYTES, + IW_PRIV_TYPE_BYTE | WOAL_2K_BYTES, + "setuserscanext"}, { WOAL_WMM_ADDTS, IW_PRIV_TYPE_BYTE | WOAL_2K_BYTES, diff --git a/drivers/net/wireless/sd8797/mlinux/moal_proc.c b/drivers/net/wireless/sd8797/mlinux/moal_proc.c index e98803c2e3fb..fb7c63a29cab 100644 --- a/drivers/net/wireless/sd8797/mlinux/moal_proc.c +++ b/drivers/net/wireless/sd8797/mlinux/moal_proc.c @@ -95,9 +95,9 @@ woal_info_proc_read(char *page, char **start, off_t offset, int mc_count = netdev_mc_count(netdev); #endif /* < 2.6.35 */ #else -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,34) +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,29) int i = 0; -#endif /* >= 2.6.34 */ +#endif /* >= 2.6.29 */ #endif #ifdef UAP_SUPPORT mlan_ds_uap_stats ustats; @@ -199,7 +199,7 @@ woal_info_proc_read(char *page, char **start, off_t offset, p += sprintf(p, "num_rx_pkts_err = %lu\n", priv->stats.rx_errors); p += sprintf(p, "carrier %s\n", ((netif_carrier_ok(priv->netdev)) ? "on" : "off")); -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,34) +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,29) for (i = 0; i < netdev->num_tx_queues; i++) { p += sprintf(p, "tx queue %d: %s\n", i, ((netif_tx_queue_stopped(netdev_get_tx_queue(netdev, 0))) ? diff --git a/drivers/net/wireless/sd8797/mlinux/moal_sdio_mmc.c b/drivers/net/wireless/sd8797/mlinux/moal_sdio_mmc.c index 96e3e971936f..f09f33e6435d 100644 --- a/drivers/net/wireless/sd8797/mlinux/moal_sdio_mmc.c +++ b/drivers/net/wireless/sd8797/mlinux/moal_sdio_mmc.c @@ -315,6 +315,12 @@ woal_sdio_suspend(struct device *dev) } handle = cardp->handle; + if (handle->is_suspended == MTRUE) { + PRINTM(MWARN, "Device already suspended\n"); + LEAVE(); + return MLAN_STATUS_SUCCESS; + } + handle->suspend_fail = MFALSE; memset(&pm_info, 0, sizeof(pm_info)); if (MLAN_STATUS_SUCCESS == diff --git a/drivers/net/wireless/sd8797/mlinux/moal_shim.c b/drivers/net/wireless/sd8797/mlinux/moal_shim.c index e33a6e38067a..25cfdc549f3d 100644 --- a/drivers/net/wireless/sd8797/mlinux/moal_shim.c +++ b/drivers/net/wireless/sd8797/mlinux/moal_shim.c @@ -745,6 +745,11 @@ moal_recv_packet(IN t_void * pmoal_handle, IN pmlan_buffer pmbuf) skb->dev = priv->netdev; skb->protocol = eth_type_trans(skb, priv->netdev); skb->ip_summed = CHECKSUM_NONE; + + if (priv->enable_tcp_ack_enh == MTRUE) { + woal_check_tcp_fin(priv, skb); + } + priv->stats.rx_bytes += skb->len; priv->stats.rx_packets++; if (in_interrupt()) @@ -950,6 +955,13 @@ moal_recv_event(IN t_void * pmoal_handle, IN pmlan_event pmevent) #endif } #endif /* STA_WEXT */ +#ifdef STA_CFG80211 + if (IS_STA_CFG80211(cfg80211_wext)) { + cfg80211_michael_mic_failure(priv->netdev, priv->cfg_bssid, + NL80211_KEYTYPE_PAIRWISE, -1, NULL, + GFP_KERNEL); + } +#endif break; case MLAN_EVENT_ID_FW_MIC_ERR_MUL: #ifdef STA_WEXT @@ -961,17 +973,47 @@ moal_recv_event(IN t_void * pmoal_handle, IN pmlan_event pmevent) #endif } #endif /* STA_WEXT */ +#ifdef STA_CFG80211 + if (IS_STA_CFG80211(cfg80211_wext)) { + cfg80211_michael_mic_failure(priv->netdev, priv->cfg_bssid, + NL80211_KEYTYPE_GROUP, -1, NULL, + GFP_KERNEL); + } +#endif break; case MLAN_EVENT_ID_FW_BCN_RSSI_LOW: #ifdef STA_WEXT if (IS_STA_WEXT(cfg80211_wext)) woal_send_iwevcustom_event(priv, CUS_EVT_BEACON_RSSI_LOW); +#endif +#ifdef STA_CFG80211 + if (IS_STA_CFG80211(cfg80211_wext)) { +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,35) || defined(COMPAT_WIRELESS) + cfg80211_cqm_rssi_notify(priv->netdev, + NL80211_CQM_RSSI_THRESHOLD_EVENT_LOW, + GFP_KERNEL); + priv->rssi_status = MLAN_EVENT_ID_FW_BCN_RSSI_LOW; +#endif + woal_set_rssi_threshold(priv, MLAN_EVENT_ID_FW_BCN_RSSI_LOW); + } #endif break; case MLAN_EVENT_ID_FW_BCN_RSSI_HIGH: #ifdef STA_WEXT if (IS_STA_WEXT(cfg80211_wext)) woal_send_iwevcustom_event(priv, CUS_EVT_BEACON_RSSI_HIGH); +#endif +#ifdef STA_CFG80211 + if (IS_STA_CFG80211(cfg80211_wext)) { + if (!priv->mrvl_rssi_low) { +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,35) || defined(COMPAT_WIRELESS) + cfg80211_cqm_rssi_notify(priv->netdev, + NL80211_CQM_RSSI_THRESHOLD_EVENT_HIGH, + GFP_KERNEL); +#endif + woal_set_rssi_threshold(priv, MLAN_EVENT_ID_FW_BCN_RSSI_HIGH); + } + } #endif break; case MLAN_EVENT_ID_FW_BCN_SNR_LOW: @@ -1032,6 +1074,22 @@ moal_recv_event(IN t_void * pmoal_handle, IN pmlan_event pmevent) #ifdef STA_WEXT if (IS_STA_WEXT(cfg80211_wext)) woal_send_iwevcustom_event(priv, CUS_EVT_PRE_BEACON_LOST); +#endif +#ifdef STA_CFG80211 +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,35) || defined(COMPAT_WIRELESS) + if (IS_STA_CFG80211(cfg80211_wext)) { + struct cfg80211_bss *bss = NULL; + bss = + cfg80211_get_bss(priv->wdev->wiphy, NULL, priv->cfg_bssid, NULL, + 0, WLAN_CAPABILITY_ESS, WLAN_CAPABILITY_ESS); + if (bss) + cfg80211_unlink_bss(priv->wdev->wiphy, bss); + cfg80211_cqm_rssi_notify(priv->netdev, + NL80211_CQM_RSSI_THRESHOLD_EVENT_LOW, + GFP_KERNEL); + priv->rssi_status = MLAN_EVENT_ID_FW_PRE_BCN_LOST; + } +#endif #endif break; case MLAN_EVENT_ID_FW_WMM_CONFIG_CHANGE: @@ -1069,10 +1127,21 @@ moal_recv_event(IN t_void * pmoal_handle, IN pmlan_event pmevent) priv->bg_scan_reported = MTRUE; #ifdef STA_WEXT if (IS_STA_WEXT(cfg80211_wext)) { - woal_send_iwevcustom_event(priv, CUS_EVT_BG_SCAN); memset(&wrqu, 0, sizeof(union iwreq_data)); wireless_send_event(priv->netdev, SIOCGIWSCAN, &wrqu, NULL); } +#endif +#ifdef STA_CFG80211 + if (IS_STA_CFG80211(cfg80211_wext)) { + woal_inform_bss_from_scan_result(priv, NULL); +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,35) || defined(COMPAT_WIRELESS) + if (priv->mrvl_rssi_low) { + cfg80211_cqm_rssi_notify(priv->netdev, + NL80211_CQM_RSSI_THRESHOLD_EVENT_HIGH, + GFP_KERNEL); + } +#endif + } #endif break; case MLAN_EVENT_ID_FW_CHANNEL_SWITCH_ANN: @@ -1285,10 +1354,15 @@ moal_recv_event(IN t_void * pmoal_handle, IN pmlan_event pmevent) #endif /* UAP_WEXT */ break; case MLAN_EVENT_ID_DRV_MGMT_FRAME: +#ifdef UAP_WEXT + if (IS_UAP_WEXT(cfg80211_wext)) { + woal_broadcast_event(priv, pmevent->event_buf, pmevent->event_len); + } +#endif /* UAP_WEXT */ #ifdef WIFI_DIRECT_SUPPORT #if defined(STA_CFG80211) || defined(UAP_CFG80211) if (IS_STA_OR_UAP_CFG80211(cfg80211_wext)) { -#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,0,0) || defined(COMPAT_WIRELESS) +#if LINUX_VERSION_CODE >= WIFI_DIRECT_KERNEL_VERSION if (priv->netdev && priv->netdev->ieee80211_ptr->wiphy->mgmt_stypes) { /* frmctl + durationid + addr1 + addr2 + addr3 + seqctl */ #define PACKET_ADDR4_POS (2 + 2 + 6 + 6 + 6 + 2) @@ -1310,11 +1384,6 @@ moal_recv_event(IN t_void * pmoal_handle, IN pmlan_event pmevent) } #endif /* STA_CFG80211 || UAP_CFG80211 */ #endif /* WIFI_DIRECT_SUPPORT */ -#ifdef UAP_WEXT - if (IS_UAP_WEXT(cfg80211_wext)) { - woal_broadcast_event(priv, pmevent->event_buf, pmevent->event_len); - } -#endif /* UAP_WEXT */ break; #endif /* UAP_SUPPORT */ case MLAN_EVENT_ID_DRV_PASSTHRU: diff --git a/drivers/net/wireless/sd8797/mlinux/moal_sta_cfg80211.c b/drivers/net/wireless/sd8797/mlinux/moal_sta_cfg80211.c index d6768a3bd647..ed44cdefe43b 100644 --- a/drivers/net/wireless/sd8797/mlinux/moal_sta_cfg80211.c +++ b/drivers/net/wireless/sd8797/mlinux/moal_sta_cfg80211.c @@ -44,6 +44,11 @@ static int woal_cfg80211_dump_station(struct wiphy *wiphy, static int woal_cfg80211_set_power_mgmt(struct wiphy *wiphy, struct net_device *dev, bool enabled, int timeout); +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,35) || defined(COMPAT_WIRELESS) +static int woal_cfg80211_set_cqm_rssi_config(struct wiphy *wiphy, + struct net_device *dev, + s32 rssi_thold, u32 rssi_hyst); +#endif static int woal_cfg80211_set_tx_power(struct wiphy *wiphy, #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,36) && !defined(COMPAT_WIRELESS) @@ -98,6 +103,9 @@ static struct cfg80211_ops woal_cfg80211_sta_ops = { .set_default_key = woal_cfg80211_set_default_key, .set_power_mgmt = woal_cfg80211_set_power_mgmt, .set_tx_power = woal_cfg80211_set_tx_power, +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,35) || defined(COMPAT_WIRELESS) + .set_cqm_rssi_config = woal_cfg80211_set_cqm_rssi_config, +#endif }; #if defined(WIFI_DIRECT_SUPPORT) @@ -518,14 +526,13 @@ woal_cfg80211_assoc_ies_cfg(moal_private * priv, t_u8 * ie, int ie_len) /** * @brief Send domain info command to FW * - * @param wiphy A pointer to wiphy structure + * @param priv A pointer to moal_private structure * * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE */ static mlan_status -woal_send_domain_info_cmd_fw(struct wiphy *wiphy) +woal_send_domain_info_cmd_fw(moal_private * priv) { - moal_private *priv = (moal_private *) woal_get_wiphy_priv(wiphy); mlan_status ret = MLAN_STATUS_SUCCESS; enum ieee80211_band band; struct ieee80211_supported_band *sband = NULL; @@ -540,6 +547,12 @@ woal_send_domain_info_cmd_fw(struct wiphy *wiphy) ENTER(); + if (!priv->wdev || !priv->wdev->wiphy) { + PRINTM(MERROR, "No wdev or wiphy in priv\n"); + ret = MLAN_STATUS_FAILURE; + goto done; + } + /* Allocate an IOCTL request buffer */ req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_radio_cfg)); if (req == NULL) { @@ -556,7 +569,7 @@ woal_send_domain_info_cmd_fw(struct wiphy *wiphy) goto done; } band = woal_band_cfg_to_ieee_band(radio_cfg->param.band_cfg.config_bands); - if (!wiphy->bands[band]) { + if (!priv->wdev->wiphy->bands[band]) { PRINTM(MERROR, "11D: setting domain info in FW failed"); ret = MLAN_STATUS_FAILURE; goto done; @@ -580,7 +593,7 @@ woal_send_domain_info_cmd_fw(struct wiphy *wiphy) cfg_11d->param.domain_info.country_code[2] = ' '; cfg_11d->param.domain_info.band = band; - sband = wiphy->bands[band]; + sband = priv->wdev->wiphy->bands[band]; for (i = 0; (i < sband->n_channels) && (no_of_sub_band < MRVDRV_MAX_SUBBAND_802_11D); i++) { channel = &sband->channels[i]; @@ -641,18 +654,17 @@ woal_send_domain_info_cmd_fw(struct wiphy *wiphy) * @brief Request the driver to change the channel and * change domain info according to that channel * - * @param wiphy A pointer to wiphy structure + * @param priv A pointer to moal_private structure * @param chan A pointer to ieee80211_channel structure * @param channel_type Channel type of nl80211_channel_type * * @return 0 -- success, otherwise fail */ int -woal_set_rf_channel(struct wiphy *wiphy, +woal_set_rf_channel(moal_private * priv, struct ieee80211_channel *chan, enum nl80211_channel_type channel_type) { - moal_private *priv = (moal_private *) woal_get_wiphy_priv(wiphy); int ret = 0; t_u32 mode, config_bands = 0; mlan_ioctl_req *req1 = NULL, *req2 = NULL; @@ -692,7 +704,7 @@ woal_set_rf_channel(struct wiphy *wiphy, ret = -EFAULT; goto done; } - woal_send_domain_info_cmd_fw(wiphy); + woal_send_domain_info_cmd_fw(priv); } PRINTM(MINFO, "Setting band %d, channel bandwidth %d and mode = %d\n", @@ -864,17 +876,15 @@ woal_inform_bss_from_scan_result(moal_private * priv, mlan_802_11_ssid * ssid) struct ieee80211_channel *chan; mlan_scan_resp scan_resp; BSSDescriptor_t *scan_table; - t_u8 *ie, *tmp, *ie_buf; - __le32 ie_len; t_u64 ts = 0; - t_u8 *cap; - t_u8 *beacon; - int beacon_size, i, j; - IEEEtypes_ElementId_e element_id; - t_u8 element_len; + u16 cap_info = 0; + int i = 0; struct cfg80211_bss *pub = NULL; - ENTER(); + if (!priv->wdev || !priv->wdev->wiphy) { + LEAVE(); + return MLAN_STATUS_FAILURE; + } memset(&scan_resp, 0, sizeof(scan_resp)); if (MLAN_STATUS_SUCCESS != woal_get_scan_table(priv, @@ -885,14 +895,6 @@ woal_inform_bss_from_scan_result(moal_private * priv, mlan_802_11_ssid * ssid) } if (scan_resp.num_in_scan_table) { -#define MAX_IE_BUF 2048 - ie_buf = kzalloc(MAX_IE_BUF, GFP_KERNEL); - if (ie_buf == NULL) { - PRINTM(MERROR, "%s: failed to allocate ie_buf\n", __func__); - ret = MLAN_STATUS_FAILURE; - goto done; - } - scan_table = (BSSDescriptor_t *) scan_resp.pscan_table; for (i = 0; i < scan_resp.num_in_scan_table; i++) { if (ssid) { @@ -905,105 +907,31 @@ woal_inform_bss_from_scan_result(moal_private * priv, mlan_802_11_ssid * ssid) (int) scan_table[i].channel); continue; } - memset(ie_buf, 0, MAX_IE_BUF); - ie_buf[0] = WLAN_EID_SSID; - ie_buf[1] = scan_table[i].ssid.ssid_len; - memcpy(&ie_buf[sizeof(IEEEtypes_Header_t)], - scan_table[i].ssid.ssid, ie_buf[1]); - - ie = ie_buf + ie_buf[1] + sizeof(IEEEtypes_Header_t); - ie_len = ie_buf[1] + sizeof(IEEEtypes_Header_t); - - ie[0] = WLAN_EID_SUPP_RATES; - - for (j = 0; j < sizeof(scan_table[i].supported_rates); j++) { - if (!scan_table[i].supported_rates[j]) - break; - else { - ie[j + sizeof(IEEEtypes_Header_t)] = - scan_table[i].supported_rates[j]; - } - } - - ie[1] = j; - ie_len += ie[1] + sizeof(IEEEtypes_Header_t); - - beacon = scan_table[i].pbeacon_buf; - beacon_size = scan_table[i].beacon_buf_size; - - /* Skip time stamp, beacon interval and capability */ - - if (beacon) { - beacon += sizeof(scan_table[i].beacon_period) - + sizeof(scan_table[i].time_stamp) + - +sizeof(scan_table[i].cap_info); - - beacon_size -= sizeof(scan_table[i].beacon_period) - + sizeof(scan_table[i].time_stamp) - + sizeof(scan_table[i].cap_info); - } - - while (beacon_size >= sizeof(IEEEtypes_Header_t)) { - ie = ie_buf + ie_len; - element_id = *beacon; - element_len = *(beacon + 1); - if (beacon_size < (int) element_len + - sizeof(IEEEtypes_Header_t)) { - PRINTM(MERROR, - "Get scan: Error in processing IE, " - "bytes left < IE length\n"); - break; - } - switch (element_id) { - case WLAN_EID_FH_PARAMS: - case WLAN_EID_DS_PARAMS: - case WLAN_EID_CF_PARAMS: - case WLAN_EID_IBSS_PARAMS: - case WLAN_EID_COUNTRY: - case WLAN_EID_PWR_CONSTRAINT: - case WLAN_EID_PWR_CAPABILITY: - case WLAN_EID_TPC_REQUEST: - case WLAN_EID_TPC_REPORT: - case WLAN_EID_CHANNEL_SWITCH: - case WLAN_EID_QUIET: - case WLAN_EID_IBSS_DFS: - case WLAN_EID_SUPPORTED_CHANNELS: - case WLAN_EID_ERP_INFO: - case WLAN_EID_EXT_SUPP_RATES: - case WLAN_EID_HT_CAPABILITY: - case WLAN_EID_HT_INFORMATION: - case EXT_CAPABILITY: // TODO: Replace when kernel macro - // available - case WLAN_EID_RSN: - case WAPI_IE: // TODO: Replace when kernel macro available - case WLAN_EID_VENDOR_SPECIFIC: - ie[0] = element_id; - ie[1] = element_len; - tmp = (t_u8 *) beacon; - memcpy(&ie[sizeof(IEEEtypes_Header_t)], - tmp + sizeof(IEEEtypes_Header_t), element_len); - ie_len += ie[1] + sizeof(IEEEtypes_Header_t); - break; - default: - break; - } - beacon += element_len + sizeof(IEEEtypes_Header_t); - beacon_size -= (element_len + sizeof(IEEEtypes_Header_t)); - } chan = ieee80211_get_channel(priv->wdev->wiphy, scan_table[i].freq); - cap = (t_u8 *) & scan_table[i].cap_info; + if (!chan) { + PRINTM(MERROR, + "Fail to get chan with freq: channel=%d freq=%d\n", + (int) scan_table[i].channel, (int) scan_table[i].freq); + continue; + } + memcpy(&ts, scan_table[i].time_stamp, sizeof(ts)); + memcpy(&cap_info, &scan_table[i].cap_info, sizeof(cap_info)); pub = cfg80211_inform_bss(priv->wdev->wiphy, chan, scan_table[i].mac_address, - ts, (__le16) (*cap), - scan_table[i].beacon_period, ie_buf, - ie_len, + ts, cap_info, + scan_table[i].beacon_period, + scan_table[i].pbeacon_buf + + WLAN_802_11_FIXED_IE_SIZE, + scan_table[i].beacon_buf_size - + WLAN_802_11_FIXED_IE_SIZE, -RSSI_DBM_TO_MDM(scan_table[i].rssi), GFP_KERNEL); - pub->len_information_elements = pub->len_beacon_ies; + if (pub) { + pub->len_information_elements = pub->len_beacon_ies; + cfg80211_put_bss(pub); + } } - kfree(ie_buf); } - done: LEAVE(); return ret; @@ -1044,6 +972,7 @@ woal_cfg80211_inform_ibss_bss(moal_private * priv, mlan_ds_get_signal signal; t_u8 ie_buf[MLAN_MAX_SSID_LENGTH + sizeof(IEEEtypes_Header_t)]; int ie_len = 0; + struct cfg80211_bss *bss = NULL; ENTER(); @@ -1068,11 +997,12 @@ woal_cfg80211_inform_ibss_bss(moal_private * priv, goto done; } - cfg80211_inform_bss(priv->wdev->wiphy, chan, - bss_info.bssid, 0, WLAN_CAPABILITY_IBSS, - beacon_interval, ie_buf, ie_len, signal.bcn_rssi_avg, - GFP_KERNEL); - + bss = cfg80211_inform_bss(priv->wdev->wiphy, chan, + bss_info.bssid, 0, WLAN_CAPABILITY_IBSS, + beacon_interval, ie_buf, ie_len, + signal.bcn_rssi_avg, GFP_KERNEL); + if (bss) + cfg80211_put_bss(bss); done: LEAVE(); return ret; @@ -1081,15 +1011,14 @@ woal_cfg80211_inform_ibss_bss(moal_private * priv, /** * @brief Request the driver for (re)association * - * @param wiphy A pointer to wiphy structure + * @param priv A pointer to moal_private structure * @param sme A pointer to connect parameters * * @return 0 -- success, otherwise fail */ static int -woal_cfg80211_assoc(struct wiphy *wiphy, void *sme) +woal_cfg80211_assoc(moal_private * priv, void *sme) { - moal_private *priv = (moal_private *) woal_get_wiphy_priv(wiphy); struct cfg80211_ibss_params *ibss_param = NULL; struct cfg80211_connect_params *conn_param = NULL; mlan_802_11_ssid req_ssid; @@ -1170,7 +1099,7 @@ woal_cfg80211_assoc(struct wiphy *wiphy, void *sme) ret = -EFAULT; goto done; } - if (MLAN_STATUS_SUCCESS != woal_set_rf_channel(wiphy, + if (MLAN_STATUS_SUCCESS != woal_set_rf_channel(priv, channel, woal_channel_to_nl80211_channel_type (radio_cfg->param. @@ -1188,8 +1117,9 @@ woal_cfg80211_assoc(struct wiphy *wiphy, void *sme) } if (MLAN_STATUS_SUCCESS != - woal_cfg80211_set_key(priv, 0, 0, NULL, 0, NULL, 0, 0, NULL, 1)) { - /* Disable keys */ + woal_cfg80211_set_key(priv, 0, 0, NULL, 0, NULL, 0, + KEY_INDEX_CLEAR_ALL, NULL, 1)) { + /* Disable keys and clear all previous security settings */ ret = -EFAULT; goto done; } @@ -1386,6 +1316,58 @@ woal_cfg80211_assoc(struct wiphy *wiphy, void *sme) return ret; } +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,0,0) || defined(COMPAT_WIRELESS) +/** + * @brief Set/Get DTIM period + * + * @param priv A pointer to moal_private structure + * @param action Action set or get + * @param wait_option Wait option + * @param value DTIM period + * + * @return MLAN_STATUS_SUCCESS/MLAN_STATUS_PENDING -- success, otherwise fail + */ +static mlan_status +woal_set_get_dtim_period(moal_private * priv, + t_u32 action, t_u8 wait_option, t_u8 * value) +{ + mlan_ioctl_req *req = NULL; + mlan_ds_snmp_mib *mib = NULL; + mlan_status ret = MLAN_STATUS_SUCCESS; + + ENTER(); + + /* Allocate an IOCTL request buffer */ + req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_snmp_mib)); + if (req == NULL) { + ret = MLAN_STATUS_FAILURE; + goto done; + } + + /* Fill request buffer */ + mib = (mlan_ds_snmp_mib *) req->pbuf; + mib->sub_command = MLAN_OID_SNMP_MIB_DTIM_PERIOD; + req->req_id = MLAN_IOCTL_SNMP_MIB; + req->action = action; + + if (action == MLAN_ACT_SET) { + mib->param.dtim_period = *value; + } + + /* Send IOCTL request to MLAN */ + ret = woal_request_ioctl(priv, req, wait_option); + if (ret == MLAN_STATUS_SUCCESS && action == MLAN_ACT_GET) { + *value = (t_u8) mib->param.dtim_period; + } + + done: + if (req && (ret != MLAN_STATUS_PENDING)) + kfree(req); + LEAVE(); + return ret; +} +#endif + /** * @brief Request the driver to dump the station information * @@ -1397,10 +1379,14 @@ woal_cfg80211_assoc(struct wiphy *wiphy, void *sme) static mlan_status woal_cfg80211_dump_station_info(moal_private * priv, struct station_info *sinfo) { + mlan_status ret = MLAN_STATUS_SUCCESS; mlan_ds_get_signal signal; mlan_ioctl_req *req = NULL; mlan_ds_rate *rate = NULL; - mlan_status ret = MLAN_STATUS_SUCCESS; +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,0,0) || defined(COMPAT_WIRELESS) + mlan_bss_info bss_info; + t_u8 dtim_period = 0; +#endif ENTER(); sinfo->filled = STATION_INFO_RX_BYTES | STATION_INFO_TX_BYTES | @@ -1443,6 +1429,28 @@ woal_cfg80211_dump_station_info(moal_private * priv, struct station_info *sinfo) sinfo->tx_packets = priv->stats.tx_packets; sinfo->signal = signal.bcn_rssi_avg; +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,0,0) || defined(COMPAT_WIRELESS) + /* Update BSS information */ + sinfo->filled |= STATION_INFO_BSS_PARAM; + sinfo->bss_param.flags = 0; + ret = woal_get_bss_info(priv, MOAL_IOCTL_WAIT, &bss_info); + if (ret) + goto done; + if (bss_info.capability_info & WLAN_CAPABILITY_SHORT_PREAMBLE) + sinfo->bss_param.flags |= BSS_PARAM_FLAGS_SHORT_PREAMBLE; + if (bss_info.capability_info & WLAN_CAPABILITY_SHORT_SLOT_TIME) + sinfo->bss_param.flags |= BSS_PARAM_FLAGS_SHORT_SLOT_TIME; + sinfo->bss_param.beacon_interval = bss_info.beacon_interval; + /* Get DTIM period */ + ret = woal_set_get_dtim_period(priv, MLAN_ACT_GET, + MOAL_IOCTL_WAIT, &dtim_period); + if (ret) { + PRINTM(MERROR, "Get DTIM period failed\n"); + goto done; + } + sinfo->bss_param.dtim_period = dtim_period; +#endif + done: if (req) kfree(req); @@ -1472,6 +1480,12 @@ woal_cfg80211_reg_notifier(struct wiphy *wiphy, ENTER(); + if (!priv) { + PRINTM(MFATAL, "Unable to get priv in %s()\n", __FUNCTION__); + LEAVE(); + return -EINVAL; + } + PRINTM(MINFO, "cfg80211 regulatory domain callback " "%c%c\n", request->alpha2[0], request->alpha2[1]); @@ -1496,7 +1510,7 @@ woal_cfg80211_reg_notifier(struct wiphy *wiphy, break; } - if (MLAN_STATUS_SUCCESS != woal_send_domain_info_cmd_fw(wiphy)) + if (MLAN_STATUS_SUCCESS != woal_send_domain_info_cmd_fw(priv)) ret = -EFAULT; LEAVE(); @@ -1519,7 +1533,7 @@ static int woal_cfg80211_scan(struct wiphy *wiphy, struct net_device *dev, struct cfg80211_scan_request *request) { - moal_private *priv = (moal_private *) woal_get_wiphy_priv(wiphy); + moal_private *priv = (moal_private *) woal_get_netdev_priv(dev); wlan_user_scan_cfg scan_req; struct ieee80211_channel *chan; int ret = 0, i; @@ -1604,10 +1618,11 @@ static int woal_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev, struct cfg80211_connect_params *sme) { - moal_private *priv = (moal_private *) woal_get_wiphy_priv(wiphy); + moal_private *priv = (moal_private *) woal_get_netdev_priv(dev); int ret = 0; ENTER(); + PRINTM(MINFO, "Received association request on %s\n", dev->name); if (priv->wdev->iftype != NL80211_IFTYPE_STATION @@ -1645,7 +1660,7 @@ woal_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev, if (priv->scan_type == MLAN_SCAN_TYPE_PASSIVE) woal_set_scan_type(priv, MLAN_SCAN_TYPE_ACTIVE); - ret = woal_cfg80211_assoc(wiphy, (void *) sme); + ret = woal_cfg80211_assoc(priv, (void *) sme); if (priv->scan_type == MLAN_SCAN_TYPE_PASSIVE) woal_set_scan_type(priv, MLAN_SCAN_TYPE_PASSIVE); @@ -1680,7 +1695,7 @@ static int woal_cfg80211_disconnect(struct wiphy *wiphy, struct net_device *dev, t_u16 reason_code) { - moal_private *priv = (moal_private *) woal_get_wiphy_priv(wiphy); + moal_private *priv = (moal_private *) woal_get_netdev_priv(dev); ENTER(); PRINTM(MINFO, "Received disassociation request on %s\n", dev->name); @@ -1729,7 +1744,7 @@ woal_cfg80211_get_station(struct wiphy *wiphy, t_u8 * mac, struct station_info *sinfo) { mlan_status ret = MLAN_STATUS_SUCCESS; - moal_private *priv = (moal_private *) woal_get_wiphy_priv(wiphy); + moal_private *priv = (moal_private *) woal_get_netdev_priv(dev); ENTER(); @@ -1778,7 +1793,7 @@ woal_cfg80211_dump_station(struct wiphy *wiphy, t_u8 * mac, struct station_info *sinfo) { mlan_status ret = MLAN_STATUS_SUCCESS; - moal_private *priv = (moal_private *) woal_get_wiphy_priv(wiphy); + moal_private *priv = (moal_private *) woal_get_netdev_priv(dev); ENTER(); @@ -1814,7 +1829,7 @@ static int woal_cfg80211_join_ibss(struct wiphy *wiphy, struct net_device *dev, struct cfg80211_ibss_params *params) { - moal_private *priv = (moal_private *) woal_get_wiphy_priv(wiphy); + moal_private *priv = (moal_private *) woal_get_netdev_priv(dev); int ret = 0; ENTER(); @@ -1826,7 +1841,7 @@ woal_cfg80211_join_ibss(struct wiphy *wiphy, struct net_device *dev, return -EINVAL; } - ret = woal_cfg80211_assoc(wiphy, (void *) params); + ret = woal_cfg80211_assoc(priv, (void *) params); if (!ret) { cfg80211_ibss_joined(priv->netdev, priv->cfg_bssid, GFP_KERNEL); @@ -1852,7 +1867,7 @@ woal_cfg80211_join_ibss(struct wiphy *wiphy, struct net_device *dev, static int woal_cfg80211_leave_ibss(struct wiphy *wiphy, struct net_device *dev) { - moal_private *priv = (moal_private *) woal_get_wiphy_priv(wiphy); + moal_private *priv = (moal_private *) woal_get_netdev_priv(dev); ENTER(); @@ -1898,7 +1913,7 @@ woal_cfg80211_set_power_mgmt(struct wiphy *wiphy, struct net_device *dev, bool enabled, int timeout) { int ret = 0, disabled; - moal_private *priv = (moal_private *) woal_get_wiphy_priv(wiphy); + moal_private *priv = (moal_private *) woal_get_netdev_priv(dev); ENTER(); @@ -1940,6 +1955,12 @@ woal_cfg80211_set_tx_power(struct wiphy *wiphy, ENTER(); + if (!priv) { + PRINTM(MFATAL, "Unable to get priv in %s()\n", __FUNCTION__); + LEAVE(); + return -EFAULT; + } + if (type) { power_cfg.is_power_auto = 0; power_cfg.power_level = dbm; @@ -1954,6 +1975,33 @@ woal_cfg80211_set_tx_power(struct wiphy *wiphy, return ret; } +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,35) || defined(COMPAT_WIRELESS) +/** + * CFG802.11 operation handler for connection quality monitoring. + * + * @param wiphy A pointer to wiphy structure + * @param dev A pointer to net_device structure + * @param rssi_thold rssi threshold + * @param rssi_hyst rssi hysteresis + */ +static int +woal_cfg80211_set_cqm_rssi_config(struct wiphy *wiphy, + struct net_device *dev, + s32 rssi_thold, u32 rssi_hyst) +{ + moal_private *priv = (moal_private *) woal_get_netdev_priv(dev); + ENTER(); + priv->cqm_rssi_thold = rssi_thold; + priv->cqm_rssi_hyst = rssi_hyst; + + PRINTM(MIOCTL, "rssi_thold=%d rssi_hyst=%d\n", + (int) rssi_thold, (int) rssi_hyst); + woal_set_rssi_threshold(priv, 0); + LEAVE(); + return 0; +} +#endif + /** * @brief Sets up the CFG802.11 specific HT capability fields * with default values @@ -2010,7 +2058,7 @@ woal_cfg80211_setup_sta_ht_cap(struct ieee80211_sta_ht_cap *ht_info, /** * @brief remain on channel config * - * @param wiphy A pointer to wiphy structure + * @param priv A pointer to moal_private structure * @param wait_option Wait option * @param cancel cancel remain on channel flag * @param status A pointer to status, success, in process or reject @@ -2021,7 +2069,7 @@ woal_cfg80211_setup_sta_ht_cap(struct ieee80211_sta_ht_cap *ht_info, * @return 0 -- success, otherwise fail */ int -woal_cfg80211_remain_on_channel_cfg(struct wiphy *wiphy, +woal_cfg80211_remain_on_channel_cfg(moal_private * priv, t_u8 wait_option, t_u8 remove, t_u8 * status, struct ieee80211_channel *chan, @@ -2029,8 +2077,6 @@ woal_cfg80211_remain_on_channel_cfg(struct wiphy *wiphy, t_u32 duration) { mlan_ds_remain_chan chan_cfg; - moal_private *priv = (moal_private *) woal_get_wiphy_priv(wiphy); - int ret = 0; ENTER(); @@ -2042,10 +2088,6 @@ woal_cfg80211_remain_on_channel_cfg(struct wiphy *wiphy, chan_cfg.bandcfg = 0; else if (chan->band == IEEE80211_BAND_5GHZ) chan_cfg.bandcfg = 1; -/** secondary channel is below */ -#define SEC_CHAN_BELOW 0x30 -/** secondary channel is above */ -#define SEC_CHAN_ABOVE 0x10 switch (channel_type) { case NL80211_CHAN_HT40MINUS: chan_cfg.bandcfg |= SEC_CHANNEL_BELOW; @@ -2084,14 +2126,14 @@ static int woal_cfg80211_mgmt_tx_cancel_wait(struct wiphy *wiphy, struct net_device *dev, u64 cookie) { - moal_private *priv = (moal_private *) woal_get_wiphy_priv(wiphy); + moal_private *priv = (moal_private *) woal_get_netdev_priv(dev); int ret = 0; t_u8 status = 1; ENTER(); if (priv->phandle->remain_on_channel) { - if (woal_cfg80211_remain_on_channel_cfg(priv->wdev->wiphy, + if (woal_cfg80211_remain_on_channel_cfg(priv, MOAL_IOCTL_WAIT, MTRUE, &status, NULL, 0, 0)) { PRINTM(MERROR, "Fail to cancel remain on channel\n"); @@ -2133,7 +2175,7 @@ woal_cfg80211_remain_on_channel(struct wiphy *wiphy, enum nl80211_channel_type channel_type, unsigned int duration, u64 * cookie) { - moal_private *priv = (moal_private *) woal_get_wiphy_priv(wiphy); + moal_private *priv = (moal_private *) woal_get_netdev_priv(dev); int ret = 0; t_u8 status = 1; @@ -2146,8 +2188,9 @@ woal_cfg80211_remain_on_channel(struct wiphy *wiphy, } /** cancel previous remain on channel */ if (priv->phandle->remain_on_channel) { - if (woal_cfg80211_remain_on_channel_cfg - (wiphy, MOAL_IOCTL_WAIT, MTRUE, &status, NULL, 0, 0)) { + if (woal_cfg80211_remain_on_channel_cfg(priv, + MOAL_IOCTL_WAIT, MTRUE, &status, + NULL, 0, 0)) { PRINTM(MERROR, "Fail to cancel remain on channel\n"); ret = -EFAULT; goto done; @@ -2156,7 +2199,7 @@ woal_cfg80211_remain_on_channel(struct wiphy *wiphy, priv->phandle->remain_on_channel = MFALSE; } if (MLAN_STATUS_SUCCESS != - woal_cfg80211_remain_on_channel_cfg(wiphy, MOAL_IOCTL_WAIT, + woal_cfg80211_remain_on_channel_cfg(priv, MOAL_IOCTL_WAIT, MFALSE, &status, chan, channel_type, (t_u32) duration)) { ret = -EFAULT; @@ -2195,14 +2238,15 @@ static int woal_cfg80211_cancel_remain_on_channel(struct wiphy *wiphy, struct net_device *dev, u64 cookie) { - moal_private *priv = (moal_private *) woal_get_wiphy_priv(wiphy); + moal_private *priv = (moal_private *) woal_get_netdev_priv(dev); int ret = 0; t_u8 status = 1; ENTER(); PRINTM(MIOCTL, "Cancel remain on Channel: cookie = %#llx\n", cookie); - if (woal_cfg80211_remain_on_channel_cfg - (wiphy, MOAL_IOCTL_WAIT, MTRUE, &status, NULL, 0, 0)) { + if (woal_cfg80211_remain_on_channel_cfg(priv, + MOAL_IOCTL_WAIT, MTRUE, &status, + NULL, 0, 0)) { PRINTM(MERROR, "Fail to cancel remain on channel\n"); ret = -EFAULT; goto done; diff --git a/drivers/net/wireless/sd8797/mlinux/moal_uap_cfg80211.c b/drivers/net/wireless/sd8797/mlinux/moal_uap_cfg80211.c index 7f7528216282..18d18328d0ed 100644 --- a/drivers/net/wireless/sd8797/mlinux/moal_uap_cfg80211.c +++ b/drivers/net/wireless/sd8797/mlinux/moal_uap_cfg80211.c @@ -124,44 +124,6 @@ static struct cfg80211_ops woal_cfg80211_uap_ops = { /******************************************************** Global Functions ********************************************************/ -/** - * @brief Filter specific IE in ie buf - * - * @param ie Pointer to IEs - * @param len Total length of ie - * @param ie_out Pointer to out IE buf - * - * @return out IE length - */ -static t_u16 -woal_filter_beacon_ies(const t_u8 * ie, int len, t_u8 * ie_out) -{ - int left_len = len; - const t_u8 *pos = ie; - int length; - t_u8 id = 0; - t_u16 out_len = 0; - - /* ERP_INFO and RSN IE will be fileter out */ - while (left_len >= 2) { - length = *(pos + 1); - id = *pos; - if ((length + 2) > left_len) - break; - switch (id) { - case ERP_INFO: - case RSN_IE: - break; - default: - memcpy(ie_out + out_len, pos, length + 2); - out_len += length + 2; - break; - } - pos += (length + 2); - left_len -= (length + 2); - } - return out_len; -} #if LINUX_VERSION_CODE < KERNEL_VERSION(3,2,0) && !defined(COMPAT_WIRELESS) /** @@ -363,442 +325,6 @@ woal_find_wpa_ies(t_u8 * ie, int len, mlan_uap_bss_param * sys_config) } #endif -/** - * @brief Look up specific IE in a buf - * - * @param ie Pointer to IEs - * @param len Total length of ie - * @param id Element id to lookup - * - * @return Pointer of the specific IE -- success, NULL -- fail - */ -static const t_u8 * -woal_parse_ie_tlv(const t_u8 * ie, int len, t_u8 id) -{ - int left_len = len; - const t_u8 *pos = ie; - int length; - - /* IE format: | u8 | id | | u8 | len | | var | data | */ - while (left_len >= 2) { - length = *(pos + 1); - if ((*pos == id) && (length + 2) <= left_len) - return pos; - pos += (length + 2); - left_len -= (length + 2); - } - - return NULL; -} - -/** - * @brief Add custom ie to mgmt frames. - * - * @param priv A pointer to moal private structure - * @param beacon_ies_data Beacon ie - * @param beacon_index The index for beacon when auto index - * @param proberesp_ies_data Probe resp ie - * @param proberesp_index The index for probe resp when auto index - * @param assocresp_ies_data Assoc resp ie - * @param assocresp_index The index for assoc resp when auto index - * @param probereq_ies_data Probe req ie - * @param probereq_index The index for probe req when auto index * - * - * @return 0 -- success, otherwise fail - */ -static int -woal_cfg80211_custom_ie(moal_private * priv, - custom_ie * beacon_ies_data, t_u16 * beacon_index, - custom_ie * proberesp_ies_data, t_u16 * proberesp_index, - custom_ie * assocresp_ies_data, t_u16 * assocresp_index, - custom_ie * probereq_ies_data, t_u16 * probereq_index) -{ - mlan_ioctl_req *ioctl_req = NULL; - mlan_ds_misc_cfg *misc = NULL; - mlan_ds_misc_custom_ie *custom_ie = NULL; - t_u8 *pos = NULL; - t_u16 len = 0; - int ret = 0; - - ENTER(); - - if (!(custom_ie = kmalloc(sizeof(mlan_ds_misc_custom_ie), GFP_KERNEL))) { - ret = -ENOMEM; - goto done; - } - - memset(custom_ie, 0x00, sizeof(mlan_ds_misc_custom_ie)); - custom_ie->type = TLV_TYPE_MGMT_IE; - - pos = (t_u8 *) custom_ie->ie_data_list; - if (beacon_ies_data) { - len = sizeof(*beacon_ies_data) - MAX_IE_SIZE - + beacon_ies_data->ie_length; - memcpy(pos, beacon_ies_data, len); - pos += len; - custom_ie->len += len; - } - - if (proberesp_ies_data) { - len = sizeof(*proberesp_ies_data) - MAX_IE_SIZE - + proberesp_ies_data->ie_length; - memcpy(pos, proberesp_ies_data, len); - pos += len; - custom_ie->len += len; - } - - if (assocresp_ies_data) { - len = sizeof(*assocresp_ies_data) - MAX_IE_SIZE - + assocresp_ies_data->ie_length; - memcpy(pos, assocresp_ies_data, len); - custom_ie->len += len; - } - - if (probereq_ies_data) { - len = sizeof(*probereq_ies_data) - MAX_IE_SIZE - + probereq_ies_data->ie_length; - memcpy(pos, probereq_ies_data, len); - pos += len; - custom_ie->len += len; - } - - ioctl_req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_misc_cfg)); - if (ioctl_req == NULL) { - ret = -ENOMEM; - goto done; - } - - misc = (mlan_ds_misc_cfg *) ioctl_req->pbuf; - misc->sub_command = MLAN_OID_MISC_CUSTOM_IE; - ioctl_req->req_id = MLAN_IOCTL_MISC_CFG; - ioctl_req->action = MLAN_ACT_SET; - - memcpy(&misc->param.cust_ie, custom_ie, sizeof(mlan_ds_misc_custom_ie)); - - if (MLAN_STATUS_SUCCESS != - woal_request_ioctl(priv, ioctl_req, MOAL_IOCTL_WAIT)) { - ret = -EFAULT; - goto done; - } - - /* get the assigned index */ - pos = (t_u8 *) (&misc->param.cust_ie.ie_data_list[0].ie_index); - if (beacon_ies_data && beacon_ies_data->ie_length - && beacon_ies_data->ie_index == MLAN_CUSTOM_IE_AUTO_IDX_MASK) { - /* save beacon ie index after auto-indexing */ - *beacon_index = misc->param.cust_ie.ie_data_list[0].ie_index; - len = sizeof(*beacon_ies_data) - MAX_IE_SIZE - + beacon_ies_data->ie_length; - pos += len; - } - - if (proberesp_ies_data && proberesp_ies_data->ie_length - && proberesp_ies_data->ie_index == MLAN_CUSTOM_IE_AUTO_IDX_MASK) { - /* save probe resp ie index after auto-indexing */ - *proberesp_index = *((t_u16 *) pos); - len = sizeof(*proberesp_ies_data) - MAX_IE_SIZE - + proberesp_ies_data->ie_length; - pos += len; - } - - if (assocresp_ies_data && assocresp_ies_data->ie_length - && assocresp_ies_data->ie_index == MLAN_CUSTOM_IE_AUTO_IDX_MASK) { - /* save assoc resp ie index after auto-indexing */ - *assocresp_index = *((t_u16 *) pos); - len = sizeof(*assocresp_ies_data) - MAX_IE_SIZE - + assocresp_ies_data->ie_length; - pos += len; - } - if (probereq_ies_data && probereq_ies_data->ie_length - && probereq_ies_data->ie_index == MLAN_CUSTOM_IE_AUTO_IDX_MASK) { - /* save probe resp ie index after auto-indexing */ - *probereq_index = *((t_u16 *) pos); - len = sizeof(*probereq_ies_data) - MAX_IE_SIZE - + probereq_ies_data->ie_length; - pos += len; - } - - if (ioctl_req->status_code == MLAN_ERROR_IOCTL_FAIL) - ret = -EFAULT; - - done: - if (ioctl_req) - kfree(ioctl_req); - if (custom_ie) - kfree(custom_ie); - LEAVE(); - return ret; -} - -/** - * @brief This function returns priv - * based on mgmt ie index - * - * @param handle A pointer to moal_handle - * @param index mgmt ie index - * - * @return Pointer to moal_private - */ -static moal_private * -woal_get_priv_by_mgmt_index(moal_handle * handle, t_u16 index) -{ - int i; - - for (i = 0; i < MIN(handle->priv_num, MLAN_MAX_BSS_NUM); i++) { - if (handle->priv[i]) { - if (handle->priv[i]->probereq_index == index) - return (handle->priv[i]); - } - } - return NULL; -} - -/** - * @brief config AP or GO for mgmt frame ies. - * - * @param priv A pointer to moal private structure - * @param beacon_ies A pointer to beacon ies - * @param beacon_ies_len Beacon ies length - * @param proberesp_ies A pointer to probe resp ies - * @param proberesp_ies_len Probe resp ies length - * @param assocresp_ies A pointer to probe resp ies - * @param assocresp_ies_len Assoc resp ies length - * @param probereq_ies A pointer to probe req ies - * @param probereq_ies_len Probe req ies length * - * @param mask Mgmt frame mask - * - * @return 0 -- success, otherwise fail - */ -int -woal_cfg80211_mgmt_frame_ie(moal_private * priv, - const t_u8 * beacon_ies, size_t beacon_ies_len, - const t_u8 * proberesp_ies, - size_t proberesp_ies_len, - const t_u8 * assocresp_ies, - size_t assocresp_ies_len, const t_u8 * probereq_ies, - size_t probereq_ies_len, t_u16 mask) -{ - int ret = 0; - t_u8 *pos = NULL; - custom_ie *beacon_ies_data = NULL; - custom_ie *proberesp_ies_data = NULL; - custom_ie *assocresp_ies_data = NULL; - custom_ie *probereq_ies_data = NULL; - - /* static variables for mgmt frame ie auto-indexing */ - static t_u16 beacon_index = MLAN_CUSTOM_IE_AUTO_IDX_MASK; - static t_u16 proberesp_index = MLAN_CUSTOM_IE_AUTO_IDX_MASK; - static t_u16 assocresp_index = MLAN_CUSTOM_IE_AUTO_IDX_MASK; - static t_u16 probereq_index = MLAN_CUSTOM_IE_AUTO_IDX_MASK; - moal_private *pmpriv = NULL; - static t_u16 rsn_index = MLAN_CUSTOM_IE_AUTO_IDX_MASK; - const t_u8 *rsn_ie; - - ENTER(); - - if (mask & MGMT_MASK_BEACON) { - if (!(beacon_ies_data = kmalloc(sizeof(custom_ie), GFP_KERNEL))) { - ret = -ENOMEM; - goto done; - } - if (beacon_ies && beacon_ies_len) { - rsn_ie = - woal_parse_ie_tlv((t_u8 *) beacon_ies, (int) beacon_ies_len, - RSN_IE); - if (rsn_ie) { - beacon_ies_data->ie_index = rsn_index; - beacon_ies_data->mgmt_subtype_mask = - MGMT_MASK_BEACON | MGMT_MASK_PROBE_RESP | - MGMT_MASK_ASSOC_RESP; - beacon_ies_data->ie_length = rsn_ie[1] + 2; - memcpy(beacon_ies_data->ie_buffer, rsn_ie, rsn_ie[1] + 2); - if (MLAN_STATUS_SUCCESS != - woal_cfg80211_custom_ie(priv, beacon_ies_data, &rsn_index, - NULL, &proberesp_index, NULL, - &assocresp_index, NULL, - &probereq_index)) { - ret = -EFAULT; - goto done; - } - } - } else { - /* clear rsn_ie */ - if (rsn_index <= MAX_MGMT_IE_INDEX) { - beacon_ies_data->ie_index = rsn_index; - beacon_ies_data->mgmt_subtype_mask = MLAN_CUSTOM_IE_DELETE_MASK; - beacon_ies_data->ie_length = 0; - rsn_index = MLAN_CUSTOM_IE_AUTO_IDX_MASK; - if (MLAN_STATUS_SUCCESS != - woal_cfg80211_custom_ie(priv, beacon_ies_data, &rsn_index, - NULL, &proberesp_index, NULL, - &assocresp_index, NULL, - &probereq_index)) { - ret = -EFAULT; - goto done; - } - } - } - } - - if (mask & MGMT_MASK_PROBE_RESP) { - if (!(proberesp_ies_data = kmalloc(sizeof(custom_ie), GFP_KERNEL))) { - ret = -ENOMEM; - goto done; - } - } - - if (mask & MGMT_MASK_ASSOC_RESP) { - if (!(assocresp_ies_data = kmalloc(sizeof(custom_ie), GFP_KERNEL))) { - ret = -ENOMEM; - goto done; - } - } - if (mask & MGMT_MASK_PROBE_REQ) { - if (!(probereq_ies_data = kmalloc(sizeof(custom_ie), GFP_KERNEL))) { - ret = -ENOMEM; - goto done; - } - } - - if (beacon_ies_data) { - memset(beacon_ies_data, 0x00, sizeof(custom_ie)); - if (beacon_ies && beacon_ies_len) { - /* set the beacon ies */ - beacon_ies_data->ie_index = beacon_index; - beacon_ies_data->mgmt_subtype_mask = MGMT_MASK_BEACON; - beacon_ies_data->mgmt_subtype_mask |= MGMT_MASK_ASSOC_RESP; - beacon_ies_data->ie_length = woal_filter_beacon_ies(beacon_ies, - beacon_ies_len, - beacon_ies_data-> - ie_buffer); - } else { - /* clear the beacon ies */ - if (beacon_index > MAX_MGMT_IE_INDEX) { - PRINTM(MERROR, "Invalid beacon index for mgmt frame ie.\n"); - goto done; - } - - beacon_ies_data->ie_index = beacon_index; - beacon_ies_data->mgmt_subtype_mask = MLAN_CUSTOM_IE_DELETE_MASK; - beacon_ies_data->ie_length = 0; - beacon_index = MLAN_CUSTOM_IE_AUTO_IDX_MASK; - } - } - - if (proberesp_ies_data) { - memset(proberesp_ies_data, 0x00, sizeof(custom_ie)); - if (proberesp_ies && proberesp_ies_len) { - /* set the probe response ies */ - // proberesp_ies_data->ie_index = MLAN_CUSTOM_IE_AUTO_IDX_MASK; - proberesp_ies_data->ie_index = proberesp_index; - proberesp_ies_data->mgmt_subtype_mask = MGMT_MASK_PROBE_RESP; - proberesp_ies_data->ie_length = proberesp_ies_len; - pos = proberesp_ies_data->ie_buffer; - memcpy(pos, proberesp_ies, proberesp_ies_len); - } else { - /* clear the probe response ies */ - if (proberesp_index > MAX_MGMT_IE_INDEX) { - PRINTM(MERROR, "Invalid probe resp index for mgmt frame ie.\n"); - goto done; - } - - proberesp_ies_data->ie_index = proberesp_index; - proberesp_ies_data->mgmt_subtype_mask = MLAN_CUSTOM_IE_DELETE_MASK; - proberesp_ies_data->ie_length = 0; - proberesp_index = MLAN_CUSTOM_IE_AUTO_IDX_MASK; - } - } - if (assocresp_ies_data) { - memset(assocresp_ies_data, 0x00, sizeof(custom_ie)); - if (assocresp_ies && assocresp_ies_len) { - /* set the assoc response ies */ - assocresp_ies_data->ie_index = assocresp_index; - assocresp_ies_data->mgmt_subtype_mask = MGMT_MASK_ASSOC_RESP; - assocresp_ies_data->ie_length = assocresp_ies_len; - pos = assocresp_ies_data->ie_buffer; - memcpy(pos, assocresp_ies, assocresp_ies_len); - } else { - /* clear the assoc response ies */ - if (assocresp_index > MAX_MGMT_IE_INDEX) { - PRINTM(MERROR, "Invalid assoc resp index for mgmt frame ie.\n"); - goto done; - } - - assocresp_ies_data->ie_index = assocresp_index; - assocresp_ies_data->mgmt_subtype_mask = MLAN_CUSTOM_IE_DELETE_MASK; - assocresp_ies_data->ie_length = 0; - assocresp_index = MLAN_CUSTOM_IE_AUTO_IDX_MASK; - } - } - - if (probereq_ies_data) { - memset(probereq_ies_data, 0x00, sizeof(custom_ie)); - if ((probereq_index != MLAN_CUSTOM_IE_AUTO_IDX_MASK) && - (priv->probereq_index != probereq_index)) { - pmpriv = woal_get_priv_by_mgmt_index(priv->phandle, probereq_index); - if (pmpriv) { - probereq_ies_data->ie_index = probereq_index; - probereq_ies_data->mgmt_subtype_mask = - MLAN_CUSTOM_IE_DELETE_MASK; - probereq_ies_data->ie_length = 0; - probereq_index = MLAN_CUSTOM_IE_AUTO_IDX_MASK; - pmpriv->probereq_index = MLAN_CUSTOM_IE_AUTO_IDX_MASK; - if (MLAN_STATUS_SUCCESS != - woal_cfg80211_custom_ie(pmpriv, NULL, &beacon_index, - NULL, &proberesp_index, - NULL, &assocresp_index, - probereq_ies_data, - &probereq_index)) { - ret = -EFAULT; - goto done; - } - memset(probereq_ies_data, 0x00, sizeof(custom_ie)); - } - } - if (probereq_ies && probereq_ies_len) { - /* set the probe req ies */ - probereq_ies_data->ie_index = probereq_index; - probereq_ies_data->mgmt_subtype_mask = MGMT_MASK_PROBE_REQ; - probereq_ies_data->ie_length = probereq_ies_len; - pos = probereq_ies_data->ie_buffer; - memcpy(pos, probereq_ies, probereq_ies_len); - } else { - /* clear the probe req ies */ - if (probereq_index > MAX_MGMT_IE_INDEX) { - PRINTM(MERROR, "Invalid probe resp index for mgmt frame ie.\n"); - goto done; - } - probereq_ies_data->ie_index = probereq_index; - probereq_ies_data->mgmt_subtype_mask = MLAN_CUSTOM_IE_DELETE_MASK; - probereq_ies_data->ie_length = 0; - probereq_index = MLAN_CUSTOM_IE_AUTO_IDX_MASK; - } - } - - if (MLAN_STATUS_SUCCESS != - woal_cfg80211_custom_ie(priv, beacon_ies_data, &beacon_index, - proberesp_ies_data, &proberesp_index, - assocresp_ies_data, &assocresp_index, - probereq_ies_data, &probereq_index)) { - ret = -EFAULT; - goto done; - } - if (probereq_ies_data) - priv->probereq_index = probereq_index; - - done: - if (beacon_ies_data) - kfree(beacon_ies_data); - if (proberesp_ies_data) - kfree(proberesp_ies_data); - if (assocresp_ies_data) - kfree(assocresp_ies_data); - - LEAVE(); - - return ret; -} - /** * @brief initialize AP or GO bss config * @@ -1330,7 +856,7 @@ woal_cfg80211_add_beacon(struct wiphy *wiphy, struct net_device *dev, struct beacon_parameters *params) { - moal_private *priv = (moal_private *) woal_get_wiphy_priv(wiphy); + moal_private *priv = (moal_private *) woal_get_netdev_priv(dev); int ret = 0; ENTER(); @@ -1402,7 +928,7 @@ woal_cfg80211_set_beacon(struct wiphy *wiphy, struct net_device *dev, struct beacon_parameters *params) { - moal_private *priv = (moal_private *) woal_get_wiphy_priv(wiphy); + moal_private *priv = (moal_private *) woal_get_netdev_priv(dev); int ret = 0; ENTER(); @@ -1471,7 +997,7 @@ woal_cfg80211_set_beacon(struct wiphy *wiphy, int woal_cfg80211_del_beacon(struct wiphy *wiphy, struct net_device *dev) { - moal_private *priv = (moal_private *) woal_get_wiphy_priv(wiphy); + moal_private *priv = (moal_private *) woal_get_netdev_priv(dev); int ret = 0; ENTER(); @@ -1521,7 +1047,7 @@ int woal_uap_cfg80211_get_station(struct wiphy *wiphy, struct net_device *dev, u8 * mac, struct station_info *stainfo) { - moal_private *priv = (moal_private *) woal_get_wiphy_priv(wiphy); + moal_private *priv = (moal_private *) woal_get_netdev_priv(dev); int ret = -EFAULT; int i = 0; mlan_ds_get_info *info = NULL; diff --git a/drivers/net/wireless/sd8797/mlinux/moal_wext.c b/drivers/net/wireless/sd8797/mlinux/moal_wext.c index 8595892090fb..a967c939f009 100644 --- a/drivers/net/wireless/sd8797/mlinux/moal_wext.c +++ b/drivers/net/wireless/sd8797/mlinux/moal_wext.c @@ -2124,12 +2124,14 @@ woal_set_priv(struct net_device *dev, struct iw_request_info *info, priv->bg_scan_reported = MFALSE; len = sprintf(buf, "OK\n") + 1; } else if (strncmp(buf, "BGSCAN-STOP", strlen("BGSCAN-STOP")) == 0) { - if (MLAN_STATUS_SUCCESS != woal_stop_bg_scan(priv)) { - ret = -EFAULT; - goto done; + if (priv->bg_scan_start && !priv->scan_cfg.rssi_threshold) { + if (MLAN_STATUS_SUCCESS != woal_stop_bg_scan(priv)) { + ret = -EFAULT; + goto done; + } + priv->bg_scan_start = MFALSE; + priv->bg_scan_reported = MFALSE; } - priv->bg_scan_start = MFALSE; - priv->bg_scan_reported = MFALSE; len = sprintf(buf, "OK\n") + 1; } else if (strncmp(buf, "RXFILTER-START", strlen("RXFILTER-START")) == 0) { #ifdef MEF_CFG_RX_FILTER @@ -2326,13 +2328,13 @@ woal_set_essid(struct net_device *dev, struct iw_request_info *info, * Check if we asked for `any' or 'particular' */ if (!dwrq->flags) { - +#ifdef REASSOCIATION if (!req_ssid.ssid_len) { memset(&priv->prev_ssid_bssid.ssid, 0x00, sizeof(mlan_802_11_ssid)); memset(&priv->prev_ssid_bssid.bssid, 0x00, MLAN_MAC_ADDR_LENGTH); goto setessid_ret; } - +#endif /* Do normal SSID scanning */ if (MLAN_STATUS_SUCCESS != woal_request_scan(priv, MOAL_IOCTL_WAIT, NULL)) { @@ -2351,6 +2353,7 @@ woal_set_essid(struct net_device *dev, struct iw_request_info *info, PRINTM(MINFO, "Requested new SSID = %s\n", (char *) req_ssid.ssid); memcpy(&ssid_bssid.ssid, &req_ssid, sizeof(mlan_802_11_ssid)); + if (dwrq->flags != 0xFFFF) { if (MLAN_STATUS_SUCCESS != woal_find_essid(priv, &ssid_bssid)) { /* Do specific SSID scanning */ diff --git a/drivers/net/wireless/sd8797/mlinux/moal_wext.h b/drivers/net/wireless/sd8797/mlinux/moal_wext.h index 91f918e1b130..dfafff866b96 100644 --- a/drivers/net/wireless/sd8797/mlinux/moal_wext.h +++ b/drivers/net/wireless/sd8797/mlinux/moal_wext.h @@ -45,7 +45,6 @@ Change log: #define CUS_EVT_BEACON_SNR_HIGH "EVENT=BEACON_SNR_HIGH" /** Custom event : Max fail */ #define CUS_EVT_MAX_FAIL "EVENT=MAX_FAIL" -#define CUS_EVT_BG_SCAN "EVENT=BG_SCAN_REPORT" /** Custom event : Data RSSI low */ #define CUS_EVT_DATA_RSSI_LOW "EVENT=DATA_RSSI_LOW" /** Custom event : Data SNR low */ -- cgit v1.2.3 From 3a8779385b7d191287f2e6e81fcc2dbcc1188869 Mon Sep 17 00:00:00 2001 From: Dan Willemsen Date: Wed, 7 Mar 2012 18:11:54 -0800 Subject: net: wireless: bcm4329: Fix GCC 4.6 warning This module has -Werror turned on, so this was causing the build to break on GCC 4.6: drivers/net/wireless/bcm4329/wl_iw.c: In function 'wl_iw_set_pmksa': drivers/net/wireless/bcm4329/wl_iw.c:5149:5: error: array subscript is above array bounds [-Werror=array-bounds] drivers/net/wireless/bcm4329/wl_iw.c:5152:5: error: array subscript is above array bounds [-Werror=array-bounds] It's a partial 'backport' of a change made to the bcmdhd driver: commit 09a8dc7361d0e603d9935ec7f736fabaa2e6dc7a net: wireless: bcmdhd: Combined P2P fix Change-Id: Ie62ad82f884c213553772ac91eaf85e17a807503 Signed-off-by: Dan Willemsen Reviewed-on: http://git-master/r/88694 GVS: Gerrit_Virtual_Submit Reviewed-by: Stephen Warren --- drivers/net/wireless/bcm4329/wl_iw.c | 27 ++++++++++++++------------- 1 file changed, 14 insertions(+), 13 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/bcm4329/wl_iw.c b/drivers/net/wireless/bcm4329/wl_iw.c index 434e584f830c..e71ab64c2caa 100644 --- a/drivers/net/wireless/bcm4329/wl_iw.c +++ b/drivers/net/wireless/bcm4329/wl_iw.c @@ -5109,6 +5109,7 @@ wl_iw_set_pmksa( uint i; int ret = 0; char eabuf[ETHER_ADDR_STR_LEN]; + pmkid_t * pmkid_array = pmkid_list.pmkids.pmkid; WL_WSEC(("%s: SIOCSIWPMKSA\n", dev->name)); CHECK_EXTRA_FOR_NULL(extra); @@ -5139,18 +5140,18 @@ wl_iw_set_pmksa( } for (i = 0; i < pmkid_list.pmkids.npmkid; i++) - if (!bcmp(&iwpmksa->bssid.sa_data[0], &pmkid_list.pmkids.pmkid[i].BSSID, + if (!bcmp(&iwpmksa->bssid.sa_data[0], &pmkid_array[i].BSSID, ETHER_ADDR_LEN)) break; if ((pmkid_list.pmkids.npmkid > 0) && (i < pmkid_list.pmkids.npmkid)) { - bzero(&pmkid_list.pmkids.pmkid[i], sizeof(pmkid_t)); + bzero(&pmkid_array[i], sizeof(pmkid_t)); for (; i < (pmkid_list.pmkids.npmkid - 1); i++) { - bcopy(&pmkid_list.pmkids.pmkid[i+1].BSSID, - &pmkid_list.pmkids.pmkid[i].BSSID, + bcopy(&pmkid_array[i+1].BSSID, + &pmkid_array[i].BSSID, ETHER_ADDR_LEN); - bcopy(&pmkid_list.pmkids.pmkid[i+1].PMKID, - &pmkid_list.pmkids.pmkid[i].PMKID, + bcopy(&pmkid_array[i+1].PMKID, + &pmkid_array[i].PMKID, WPA2_PMKID_LEN); } pmkid_list.pmkids.npmkid--; @@ -5161,14 +5162,14 @@ wl_iw_set_pmksa( else if (iwpmksa->cmd == IW_PMKSA_ADD) { for (i = 0; i < pmkid_list.pmkids.npmkid; i++) - if (!bcmp(&iwpmksa->bssid.sa_data[0], &pmkid_list.pmkids.pmkid[i].BSSID, + if (!bcmp(&iwpmksa->bssid.sa_data[0], &pmkid_array[i].BSSID, ETHER_ADDR_LEN)) break; if (i < MAXPMKID) { bcopy(&iwpmksa->bssid.sa_data[0], - &pmkid_list.pmkids.pmkid[i].BSSID, + &pmkid_array[i].BSSID, ETHER_ADDR_LEN); - bcopy(&iwpmksa->pmkid[0], &pmkid_list.pmkids.pmkid[i].PMKID, + bcopy(&iwpmksa->pmkid[0], &pmkid_array[i].PMKID, WPA2_PMKID_LEN); if (i == pmkid_list.pmkids.npmkid) pmkid_list.pmkids.npmkid++; @@ -5181,10 +5182,10 @@ wl_iw_set_pmksa( uint k; k = pmkid_list.pmkids.npmkid; WL_WSEC(("wl_iw_set_pmksa,IW_PMKSA_ADD - PMKID: %s = ", - bcm_ether_ntoa(&pmkid_list.pmkids.pmkid[k].BSSID, + bcm_ether_ntoa(&pmkid_array[k].BSSID, eabuf))); for (j = 0; j < WPA2_PMKID_LEN; j++) - WL_WSEC(("%02x ", pmkid_list.pmkids.pmkid[k].PMKID[j])); + WL_WSEC(("%02x ", pmkid_array[k].PMKID[j])); WL_WSEC(("\n")); } } @@ -5192,10 +5193,10 @@ wl_iw_set_pmksa( for (i = 0; i < pmkid_list.pmkids.npmkid; i++) { uint j; WL_WSEC(("PMKID[%d]: %s = ", i, - bcm_ether_ntoa(&pmkid_list.pmkids.pmkid[i].BSSID, + bcm_ether_ntoa(&pmkid_array[i].BSSID, eabuf))); for (j = 0; j < WPA2_PMKID_LEN; j++) - WL_WSEC(("%02x ", pmkid_list.pmkids.pmkid[i].PMKID[j])); + WL_WSEC(("%02x ", pmkid_array[i].PMKID[j])); WL_WSEC(("\n")); } WL_WSEC(("\n")); -- cgit v1.2.3 From 1452f874713a224c1e7f5fb6f203325d0fb0a815 Mon Sep 17 00:00:00 2001 From: Nitin Bindal Date: Thu, 24 May 2012 19:45:28 +0530 Subject: net: wireless: sd8797: Fix (re)association issue Fix the issue - When device connects to 2GHz AP, it does not scan APs in 5GHz and vice-versa. Bug 968022 Change-Id: I5dfddf4e73260cb1e03bd3d28c029503507cd898 Signed-off-by: Nitin Bindal Reviewed-on: http://git-master/r/104482 Reviewed-by: Automatic_Commit_Validation_User GVS: Gerrit_Virtual_Submit Reviewed-by: Rakesh Kumar Reviewed-by: Bharat Nihalani --- drivers/net/wireless/sd8797/mlinux/moal_sta_cfg80211.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/sd8797/mlinux/moal_sta_cfg80211.c b/drivers/net/wireless/sd8797/mlinux/moal_sta_cfg80211.c index ed44cdefe43b..8a60be2298c8 100644 --- a/drivers/net/wireless/sd8797/mlinux/moal_sta_cfg80211.c +++ b/drivers/net/wireless/sd8797/mlinux/moal_sta_cfg80211.c @@ -1082,7 +1082,7 @@ woal_cfg80211_assoc(moal_private * priv, void *sme) goto done; } - if (channel) { + if (mode == MLAN_BSS_MODE_IBSS && channel) { /* Get the secondary channel offset */ req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_radio_cfg)); if (req == NULL) { -- cgit v1.2.3 From 0ae1f6fa449f8d2becd04df6d7348b42ab67e594 Mon Sep 17 00:00:00 2001 From: Manoj Chourasia Date: Sun, 12 Feb 2012 19:48:06 +0530 Subject: smsc95xx: Add module params to read MAC address This patch adds support for mac_addr module param mac_addr : MAC address which will be assigned to the above device. example mac_addr=0x0,0x2,0x2,0x3,0x3,0x4 If EEPROM read fails for MAC address for a smsc interface and if the mac_addr module param is set then driver will set that device MAC address provided in mac_addr. This can be set for only one device bug 719410, bug 921146 Change-Id: I6eb0363951d91fad857b76af8a4a097cd0fb7623 Signed-off-by: Manoj Chourasia Reviewed-on: http://git-master/r/108237 Reviewed-by: Automatic_Commit_Validation_User Reviewed-by: Varun Wadekar --- drivers/net/usb/smsc95xx.c | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/usb/smsc95xx.c b/drivers/net/usb/smsc95xx.c index 7b4687974987..370846911800 100644 --- a/drivers/net/usb/smsc95xx.c +++ b/drivers/net/usb/smsc95xx.c @@ -1,7 +1,7 @@ /*************************************************************************** * * Copyright (C) 2007-2008 SMSC - * + * Copyright (C) 2012 NVIDIA Corporation. * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 @@ -63,6 +63,11 @@ static int turbo_mode = true; module_param(turbo_mode, bool, 0644); MODULE_PARM_DESC(turbo_mode, "Enable multiple frames per Rx transaction"); +static u8 mac_addr[6] = {0}; +static bool smsc_mac_addr_set; +module_param_array_named(mac_addr, mac_addr, byte, NULL, 0); +MODULE_PARM_DESC(mac_addr, "SMSC command line MAC address"); + static int smsc95xx_read_reg(struct usbnet *dev, u32 index, u32 *data) { u32 *buf = kmalloc(4, GFP_KERNEL); @@ -612,6 +617,15 @@ static void smsc95xx_init_mac_address(struct usbnet *dev) } } + /* try reading mac address from command line */ + if (is_valid_ether_addr(mac_addr) && !smsc_mac_addr_set) { + memcpy(dev->net->dev_addr, mac_addr, sizeof(mac_addr)); + smsc_mac_addr_set = true; + netif_dbg(dev, ifup, dev->net, + "MAC address read from command line"); + return; + } + /* no eeprom, or eeprom values are invalid. generate random MAC */ random_ether_addr(dev->net->dev_addr); netif_dbg(dev, ifup, dev->net, "MAC address set to random_ether_addr\n"); -- cgit v1.2.3 From b909aa43a5e95536d31895eae5b36499ff3cc67f Mon Sep 17 00:00:00 2001 From: Dmitry Shmidt Date: Fri, 11 Nov 2011 16:04:12 -0800 Subject: net: wireless: bcmdhd: Use CONFIG_DHD_USE_STATIC_BUF for preallocated memory Signed-off-by: Dmitry Shmidt --- drivers/net/wireless/bcmdhd/Kconfig | 7 ++++ drivers/net/wireless/bcmdhd/bcmsdh_sdmmc.c | 16 ++++---- drivers/net/wireless/bcmdhd/dhd.h | 4 +- drivers/net/wireless/bcmdhd/dhd_cdc.c | 4 +- drivers/net/wireless/bcmdhd/dhd_linux.c | 4 +- drivers/net/wireless/bcmdhd/dhd_sdio.c | 4 +- drivers/net/wireless/bcmdhd/include/linux_osl.h | 2 +- drivers/net/wireless/bcmdhd/linux_osl.c | 52 ++++++++++++++----------- drivers/net/wireless/bcmdhd/wl_android.c | 7 ++-- 9 files changed, 57 insertions(+), 43 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/bcmdhd/Kconfig b/drivers/net/wireless/bcmdhd/Kconfig index 427cd9911569..d66bc996dfdc 100644 --- a/drivers/net/wireless/bcmdhd/Kconfig +++ b/drivers/net/wireless/bcmdhd/Kconfig @@ -36,6 +36,13 @@ config BCMDHD_WEXT help Enables WEXT support +config DHD_USE_STATIC_BUF + bool "Enable memory preallocation" + depends on BCMDHD + default n + ---help--- + Use memory preallocated in platform + config BCMDHD_CFG80211 bool "Enable CFG80211 support" depends on CFG80211 diff --git a/drivers/net/wireless/bcmdhd/bcmsdh_sdmmc.c b/drivers/net/wireless/bcmdhd/bcmsdh_sdmmc.c index 7499a1ec55fd..49906acfb2fc 100644 --- a/drivers/net/wireless/bcmdhd/bcmsdh_sdmmc.c +++ b/drivers/net/wireless/bcmdhd/bcmsdh_sdmmc.c @@ -1013,11 +1013,11 @@ sdioh_request_buffer(sdioh_info_t *sd, uint pio_dma, uint fix_inc, uint write, u if (pkt == NULL) { sd_data(("%s: Creating new %s Packet, len=%d\n", __FUNCTION__, write ? "TX" : "RX", buflen_u)); -#ifdef DHD_USE_STATIC_BUF +#ifdef CONFIG_DHD_USE_STATIC_BUF if (!(mypkt = PKTGET_STATIC(sd->osh, buflen_u, write ? TRUE : FALSE))) { #else if (!(mypkt = PKTGET(sd->osh, buflen_u, write ? TRUE : FALSE))) { -#endif /* DHD_USE_STATIC_BUF */ +#endif /* CONFIG_DHD_USE_STATIC_BUF */ sd_err(("%s: PKTGET failed: len %d\n", __FUNCTION__, buflen_u)); return SDIOH_API_RC_FAIL; @@ -1034,11 +1034,11 @@ sdioh_request_buffer(sdioh_info_t *sd, uint pio_dma, uint fix_inc, uint write, u if (!write) { bcopy(PKTDATA(sd->osh, mypkt), buffer, buflen_u); } -#ifdef DHD_USE_STATIC_BUF +#ifdef CONFIG_DHD_USE_STATIC_BUF PKTFREE_STATIC(sd->osh, mypkt, write ? TRUE : FALSE); #else PKTFREE(sd->osh, mypkt, write ? TRUE : FALSE); -#endif /* DHD_USE_STATIC_BUF */ +#endif /* CONFIG_DHD_USE_STATIC_BUF */ } else if (((uint32)(PKTDATA(sd->osh, pkt)) & DMA_ALIGN_MASK) != 0) { /* Case 2: We have a packet, but it is unaligned. */ @@ -1047,11 +1047,11 @@ sdioh_request_buffer(sdioh_info_t *sd, uint pio_dma, uint fix_inc, uint write, u sd_data(("%s: Creating aligned %s Packet, len=%d\n", __FUNCTION__, write ? "TX" : "RX", PKTLEN(sd->osh, pkt))); -#ifdef DHD_USE_STATIC_BUF +#ifdef CONFIG_DHD_USE_STATIC_BUF if (!(mypkt = PKTGET_STATIC(sd->osh, PKTLEN(sd->osh, pkt), write ? TRUE : FALSE))) { #else if (!(mypkt = PKTGET(sd->osh, PKTLEN(sd->osh, pkt), write ? TRUE : FALSE))) { -#endif /* DHD_USE_STATIC_BUF */ +#endif /* CONFIG_DHD_USE_STATIC_BUF */ sd_err(("%s: PKTGET failed: len %d\n", __FUNCTION__, PKTLEN(sd->osh, pkt))); return SDIOH_API_RC_FAIL; @@ -1072,11 +1072,11 @@ sdioh_request_buffer(sdioh_info_t *sd, uint pio_dma, uint fix_inc, uint write, u PKTDATA(sd->osh, pkt), PKTLEN(sd->osh, mypkt)); } -#ifdef DHD_USE_STATIC_BUF +#ifdef CONFIG_DHD_USE_STATIC_BUF PKTFREE_STATIC(sd->osh, mypkt, write ? TRUE : FALSE); #else PKTFREE(sd->osh, mypkt, write ? TRUE : FALSE); -#endif /* DHD_USE_STATIC_BUF */ +#endif /* CONFIG_DHD_USE_STATIC_BUF */ } else { /* case 3: We have a packet and it is aligned. */ sd_data(("%s: Aligned %s Packet, direct DMA\n", __FUNCTION__, write ? "Tx" : "Rx")); diff --git a/drivers/net/wireless/bcmdhd/dhd.h b/drivers/net/wireless/bcmdhd/dhd.h index 1b7242d48280..4ad5ad038cc6 100644 --- a/drivers/net/wireless/bcmdhd/dhd.h +++ b/drivers/net/wireless/bcmdhd/dhd.h @@ -116,7 +116,7 @@ typedef enum { } dhd_if_state_t; -#if defined(DHD_USE_STATIC_BUF) +#if defined(CONFIG_DHD_USE_STATIC_BUF) uint8* dhd_os_prealloc(void *osh, int section, uint size); void dhd_os_prefree(void *osh, void *addr, uint size); @@ -128,7 +128,7 @@ void dhd_os_prefree(void *osh, void *addr, uint size); #define DHD_OS_PREALLOC(osh, section, size) MALLOC(osh, size) #define DHD_OS_PREFREE(osh, addr, size) MFREE(osh, addr, size) -#endif /* defined(DHD_USE_STATIC_BUF) */ +#endif /* defined(CONFIG_DHD_USE_STATIC_BUF) */ /* Packet alignment for most efficient SDIO (can change based on platform) */ #ifndef DHD_SDALIGN diff --git a/drivers/net/wireless/bcmdhd/dhd_cdc.c b/drivers/net/wireless/bcmdhd/dhd_cdc.c index 3a4de96c0028..846099206030 100644 --- a/drivers/net/wireless/bcmdhd/dhd_cdc.c +++ b/drivers/net/wireless/bcmdhd/dhd_cdc.c @@ -2460,7 +2460,7 @@ dhd_prot_attach(dhd_pub_t *dhd) return 0; fail: -#ifndef DHD_USE_STATIC_BUF +#ifndef CONFIG_DHD_USE_STATIC_BUF if (cdc != NULL) MFREE(dhd->osh, cdc, sizeof(dhd_prot_t)); #endif @@ -2474,7 +2474,7 @@ dhd_prot_detach(dhd_pub_t *dhd) #ifdef PROP_TXSTATUS dhd_wlfc_deinit(dhd); #endif -#ifndef DHD_USE_STATIC_BUF +#ifndef CONFIG_DHD_USE_STATIC_BUF MFREE(dhd->osh, dhd->prot, sizeof(dhd_prot_t)); #endif dhd->prot = NULL; diff --git a/drivers/net/wireless/bcmdhd/dhd_linux.c b/drivers/net/wireless/bcmdhd/dhd_linux.c index 80a75699e270..5ce510ac8b66 100644 --- a/drivers/net/wireless/bcmdhd/dhd_linux.c +++ b/drivers/net/wireless/bcmdhd/dhd_linux.c @@ -3917,7 +3917,7 @@ dhd_os_sdtxunlock(dhd_pub_t *pub) dhd_os_sdunlock(pub); } -#if defined(DHD_USE_STATIC_BUF) +#if defined(CONFIG_DHD_USE_STATIC_BUF) uint8* dhd_os_prealloc(void *osh, int section, uint size) { return (uint8*)wl_android_prealloc(section, size); @@ -3926,7 +3926,7 @@ uint8* dhd_os_prealloc(void *osh, int section, uint size) void dhd_os_prefree(void *osh, void *addr, uint size) { } -#endif /* defined(CONFIG_WIFI_CONTROL_FUNC) */ +#endif /* defined(CONFIG_DHD_USE_STATIC_BUF) */ #if defined(CONFIG_BCMDHD_WEXT) struct iw_statistics * diff --git a/drivers/net/wireless/bcmdhd/dhd_sdio.c b/drivers/net/wireless/bcmdhd/dhd_sdio.c index 57aee5705454..b5e10e0037ef 100644 --- a/drivers/net/wireless/bcmdhd/dhd_sdio.c +++ b/drivers/net/wireless/bcmdhd/dhd_sdio.c @@ -5736,7 +5736,7 @@ dhdsdio_release_malloc(dhd_bus_t *bus, osl_t *osh) return; if (bus->rxbuf) { -#ifndef DHD_USE_STATIC_BUF +#ifndef CONFIG_DHD_USE_STATIC_BUF MFREE(osh, bus->rxbuf, bus->rxblen); #endif bus->rxctl = bus->rxbuf = NULL; @@ -5744,7 +5744,7 @@ dhdsdio_release_malloc(dhd_bus_t *bus, osl_t *osh) } if (bus->databuf) { -#ifndef DHD_USE_STATIC_BUF +#ifndef CONFIG_DHD_USE_STATIC_BUF MFREE(osh, bus->databuf, MAX_DATA_BUF); #endif bus->databuf = NULL; diff --git a/drivers/net/wireless/bcmdhd/include/linux_osl.h b/drivers/net/wireless/bcmdhd/include/linux_osl.h index 1ec136eb70dc..38de2982f137 100644 --- a/drivers/net/wireless/bcmdhd/include/linux_osl.h +++ b/drivers/net/wireless/bcmdhd/include/linux_osl.h @@ -268,7 +268,7 @@ extern int osl_error(int bcmerror); #define PKTLIST_DUMP(osh, buf) #define PKTDBG_TRACE(osh, pkt, bit) #define PKTFREE(osh, skb, send) osl_pktfree((osh), (skb), (send)) -#ifdef DHD_USE_STATIC_BUF +#ifdef CONFIG_DHD_USE_STATIC_BUF #define PKTGET_STATIC(osh, len, send) osl_pktget_static((osh), (len)) #define PKTFREE_STATIC(osh, skb, send) osl_pktfree_static((osh), (skb), (send)) #endif diff --git a/drivers/net/wireless/bcmdhd/linux_osl.c b/drivers/net/wireless/bcmdhd/linux_osl.c index 1a544378c1e6..b3fcdd2f1ade 100644 --- a/drivers/net/wireless/bcmdhd/linux_osl.c +++ b/drivers/net/wireless/bcmdhd/linux_osl.c @@ -47,7 +47,7 @@ #define OS_HANDLE_MAGIC 0x1234abcd #define BCM_MEM_FILENAME_LEN 24 -#ifdef DHD_USE_STATIC_BUF +#ifdef CONFIG_DHD_USE_STATIC_BUF #define STATIC_BUF_MAX_NUM 16 #define STATIC_BUF_SIZE (PAGE_SIZE * 2) #define STATIC_BUF_TOTAL_LEN (STATIC_BUF_MAX_NUM * STATIC_BUF_SIZE) @@ -70,7 +70,7 @@ typedef struct bcm_static_pkt { } bcm_static_pkt_t; static bcm_static_pkt_t *bcm_static_skb = 0; -#endif +#endif typedef struct bcm_mem_link { struct bcm_mem_link *prev; @@ -211,7 +211,7 @@ osl_attach(void *pdev, uint bustype, bool pkttag) break; } -#if defined(DHD_USE_STATIC_BUF) +#if defined(CONFIG_DHD_USE_STATIC_BUF) if (!bcm_static_buf) { if (!(bcm_static_buf = (bcm_static_buf_t *)dhd_os_prealloc(osh, 3, STATIC_BUF_SIZE+ STATIC_BUF_TOTAL_LEN))) { @@ -220,25 +220,25 @@ osl_attach(void *pdev, uint bustype, bool pkttag) else printk("alloc static buf at %x!\n", (unsigned int)bcm_static_buf); - sema_init(&bcm_static_buf->static_sem, 1); bcm_static_buf->buf_ptr = (unsigned char *)bcm_static_buf + STATIC_BUF_SIZE; } if (!bcm_static_skb) { - int i; - void *skb_buff_ptr = 0; - bcm_static_skb = (bcm_static_pkt_t *)((char *)bcm_static_buf + 2048); - skb_buff_ptr = dhd_os_prealloc(osh, 4, 0); - - bcopy(skb_buff_ptr, bcm_static_skb, sizeof(struct sk_buff *) * 16); - for (i = 0; i < STATIC_PKT_MAX_NUM * 2; i++) - bcm_static_skb->pkt_use[i] = 0; - - sema_init(&bcm_static_skb->osl_pkt_sem, 1); + void *skb_buff_ptr = dhd_os_prealloc(osh, 4, 0); + + if (skb_buff_ptr) { + bcm_static_skb = (bcm_static_pkt_t *)((char *)bcm_static_buf + 2048); + bcopy(skb_buff_ptr, bcm_static_skb, sizeof(struct sk_buff *) * 16); + for (i = 0; i < STATIC_PKT_MAX_NUM * 2; i++) + bcm_static_skb->pkt_use[i] = 0; + sema_init(&bcm_static_skb->osl_pkt_sem, 1); + } else { + printk("can not alloc static skb buffers\n"); + } } -#endif +#endif return osh; } @@ -388,7 +388,7 @@ osl_ctfpool_stats(osl_t *osh, void *b) if ((osh == NULL) || (osh->ctfpool == NULL)) return; -#ifdef DHD_USE_STATIC_BUF +#ifdef CONFIG_DHD_USE_STATIC_BUF if (bcm_static_buf) { bcm_static_buf = 0; } @@ -548,14 +548,14 @@ osl_pktfree(osl_t *osh, void *p, bool send) } } -#ifdef DHD_USE_STATIC_BUF +#ifdef CONFIG_DHD_USE_STATIC_BUF void * osl_pktget_static(osl_t *osh, uint len) { int i; struct sk_buff *skb; - if (len > (PAGE_SIZE * 2)) { + if (!bcm_static_skb || (len > (PAGE_SIZE * 2))) { printk("%s: attempt to allocate huge packet (0x%x)\n", __FUNCTION__, len); return osl_pktget(osh, len); } @@ -570,10 +570,10 @@ osl_pktget_static(osl_t *osh, uint len) if (i != STATIC_PKT_MAX_NUM) { bcm_static_skb->pkt_use[i] = 1; - up(&bcm_static_skb->osl_pkt_sem); skb = bcm_static_skb->skb_4k[i]; skb->tail = skb->data + len; skb->len = len; + up(&bcm_static_skb->osl_pkt_sem); return skb; } } @@ -586,10 +586,10 @@ osl_pktget_static(osl_t *osh, uint len) if (i != STATIC_PKT_MAX_NUM) { bcm_static_skb->pkt_use[i+STATIC_PKT_MAX_NUM] = 1; - up(&bcm_static_skb->osl_pkt_sem); skb = bcm_static_skb->skb_8k[i]; skb->tail = skb->data + len; skb->len = len; + up(&bcm_static_skb->osl_pkt_sem); return skb; } @@ -603,9 +603,14 @@ osl_pktfree_static(osl_t *osh, void *p, bool send) { int i; + if (!bcm_static_skb) { + osl_pktfree(osh, p, send); + return; + } + + down(&bcm_static_skb->osl_pkt_sem); for (i = 0; i < STATIC_PKT_MAX_NUM; i++) { if (p == bcm_static_skb->skb_4k[i]) { - down(&bcm_static_skb->osl_pkt_sem); bcm_static_skb->pkt_use[i] = 0; up(&bcm_static_skb->osl_pkt_sem); return; @@ -614,14 +619,15 @@ osl_pktfree_static(osl_t *osh, void *p, bool send) for (i = 0; i < STATIC_PKT_MAX_NUM; i++) { if (p == bcm_static_skb->skb_8k[i]) { - down(&bcm_static_skb->osl_pkt_sem); bcm_static_skb->pkt_use[i + STATIC_PKT_MAX_NUM] = 0; up(&bcm_static_skb->osl_pkt_sem); return; } } + up(&bcm_static_skb->osl_pkt_sem); - return osl_pktfree(osh, p, send); + osl_pktfree(osh, p, send); + return; } #endif diff --git a/drivers/net/wireless/bcmdhd/wl_android.c b/drivers/net/wireless/bcmdhd/wl_android.c index 9ca3d6020239..67f7d9fca53a 100644 --- a/drivers/net/wireless/bcmdhd/wl_android.c +++ b/drivers/net/wireless/bcmdhd/wl_android.c @@ -675,20 +675,21 @@ void wl_android_wifictrl_func_del(void) } } -void* wl_android_prealloc(int section, unsigned long size) +void *wl_android_prealloc(int section, unsigned long size) { void *alloc_ptr = NULL; if (wifi_control_data && wifi_control_data->mem_prealloc) { alloc_ptr = wifi_control_data->mem_prealloc(section, size); if (alloc_ptr) { DHD_INFO(("success alloc section %d\n", section)); - bzero(alloc_ptr, size); + if (size != 0L) + bzero(alloc_ptr, size); return alloc_ptr; } } DHD_ERROR(("can't alloc section %d\n", section)); - return 0; + return NULL; } int wifi_get_irq_number(unsigned long *irq_flags_ptr) -- cgit v1.2.3 From c35858b53ac0411fb0cfa18736af49045774b7a5 Mon Sep 17 00:00:00 2001 From: Dmitry Shmidt Date: Wed, 30 Nov 2011 12:49:02 -0800 Subject: net: wireless: bcmdhd: Update to Version 5.90.125.94.1 - Return zeroed private command buffer - Fix memory leak in wl_inform_single_bss() Signed-off-by: Dmitry Shmidt --- drivers/net/wireless/bcmdhd/dhd_common.c | 5 +++-- drivers/net/wireless/bcmdhd/dhd_linux_mon.c | 10 ++++++---- drivers/net/wireless/bcmdhd/include/epivers.h | 2 +- drivers/net/wireless/bcmdhd/wl_android.c | 9 ++++++--- drivers/net/wireless/bcmdhd/wl_cfg80211.c | 9 ++++++--- 5 files changed, 22 insertions(+), 13 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/bcmdhd/dhd_common.c b/drivers/net/wireless/bcmdhd/dhd_common.c index 372ec80c866a..07f2124516a2 100644 --- a/drivers/net/wireless/bcmdhd/dhd_common.c +++ b/drivers/net/wireless/bcmdhd/dhd_common.c @@ -1907,6 +1907,7 @@ dhd_pno_set(dhd_pub_t *dhd, wlc_ssid_t* ssids_local, int nssid, ushort scan_fr, if ((!dhd) && (!ssids_local)) { DHD_ERROR(("%s error exit\n", __FUNCTION__)); err = -1; + return err; } if (dhd_check_ap_wfd_mode_set(dhd) == TRUE) @@ -2160,14 +2161,14 @@ wl_iw_parse_channel_list_tlv(char** list_str, uint16* channel_list, int wl_iw_parse_ssid_list_tlv(char** list_str, wlc_ssid_t* ssid, int max, int *bytes_left) { - char* str = *list_str; + char* str; int idx = 0; if ((list_str == NULL) || (*list_str == NULL) || (*bytes_left < 0)) { DHD_ERROR(("%s error paramters\n", __FUNCTION__)); return -1; } - + str = *list_str; while (*bytes_left > 0) { if (str[0] != CSCAN_TLV_TYPE_SSID_IE) { diff --git a/drivers/net/wireless/bcmdhd/dhd_linux_mon.c b/drivers/net/wireless/bcmdhd/dhd_linux_mon.c index dd9c71f75be6..ce94ff9993db 100644 --- a/drivers/net/wireless/bcmdhd/dhd_linux_mon.c +++ b/drivers/net/wireless/bcmdhd/dhd_linux_mon.c @@ -225,9 +225,10 @@ static void dhd_mon_if_set_multicast_list(struct net_device *ndev) mon_if = ndev_to_monif(ndev); if (mon_if == NULL || mon_if->real_ndev == NULL) { MON_PRINT(" cannot find matched net dev, skip the packet\n"); + } else { + MON_PRINT("enter, if name: %s, matched if name %s\n", + ndev->name, mon_if->real_ndev->name); } - - MON_PRINT("enter, if name: %s, matched if name %s\n", ndev->name, mon_if->real_ndev->name); } static int dhd_mon_if_change_mac(struct net_device *ndev, void *addr) @@ -238,9 +239,10 @@ static int dhd_mon_if_change_mac(struct net_device *ndev, void *addr) mon_if = ndev_to_monif(ndev); if (mon_if == NULL || mon_if->real_ndev == NULL) { MON_PRINT(" cannot find matched net dev, skip the packet\n"); + } else { + MON_PRINT("enter, if name: %s, matched if name %s\n", + ndev->name, mon_if->real_ndev->name); } - - MON_PRINT("enter, if name: %s, matched if name %s\n", ndev->name, mon_if->real_ndev->name); return ret; } diff --git a/drivers/net/wireless/bcmdhd/include/epivers.h b/drivers/net/wireless/bcmdhd/include/epivers.h index ae1f975bdb64..fe71e166a7d9 100644 --- a/drivers/net/wireless/bcmdhd/include/epivers.h +++ b/drivers/net/wireless/bcmdhd/include/epivers.h @@ -44,6 +44,6 @@ #define EPI_VERSION_DEV 5.90.125 -#define EPI_VERSION_STR "5.90.125.94" +#define EPI_VERSION_STR "5.90.125.94.1" #endif diff --git a/drivers/net/wireless/bcmdhd/wl_android.c b/drivers/net/wireless/bcmdhd/wl_android.c index 67f7d9fca53a..b6804817240a 100644 --- a/drivers/net/wireless/bcmdhd/wl_android.c +++ b/drivers/net/wireless/bcmdhd/wl_android.c @@ -559,8 +559,10 @@ int wl_android_priv_cmd(struct net_device *net, struct ifreq *ifr, int cmd) bytes_written = strlen("OK"); } - if (bytes_written > 0) { - if (bytes_written > priv_cmd.total_len) { + if (bytes_written >= 0) { + if ((bytes_written == 0) && (priv_cmd.total_len > 0)) + command[0] = '\0'; + if (bytes_written >= priv_cmd.total_len) { DHD_ERROR(("%s: bytes_written = %d\n", __FUNCTION__, bytes_written)); bytes_written = priv_cmd.total_len; } else { @@ -571,7 +573,8 @@ int wl_android_priv_cmd(struct net_device *net, struct ifreq *ifr, int cmd) DHD_ERROR(("%s: failed to copy data to user buffer\n", __FUNCTION__)); ret = -EFAULT; } - } else { + } + else { ret = bytes_written; } diff --git a/drivers/net/wireless/bcmdhd/wl_cfg80211.c b/drivers/net/wireless/bcmdhd/wl_cfg80211.c index 04affb50b18b..17ed972f2d73 100644 --- a/drivers/net/wireless/bcmdhd/wl_cfg80211.c +++ b/drivers/net/wireless/bcmdhd/wl_cfg80211.c @@ -4157,6 +4157,7 @@ static s32 wl_inform_single_bss(struct wl_priv *wl, struct wl_bss_info *bi) struct wl_cfg80211_bss_info *notif_bss_info; struct wl_scan_req *sr = wl_to_sr(wl); struct beacon_proberesp *beacon_proberesp; + struct cfg80211_bss *cbss = NULL; s32 mgmt_type; s32 signal; u32 freq; @@ -4215,13 +4216,15 @@ static s32 wl_inform_single_bss(struct wl_priv *wl, struct wl_bss_info *bi) signal = notif_bss_info->rssi * 100; - if (unlikely(!cfg80211_inform_bss_frame(wiphy, channel, mgmt, - le16_to_cpu(notif_bss_info->frame_len), - signal, GFP_KERNEL))) { + cbss = cfg80211_inform_bss_frame(wiphy, channel, mgmt, + le16_to_cpu(notif_bss_info->frame_len), signal, GFP_KERNEL); + if (unlikely(!cbss)) { WL_ERR(("cfg80211_inform_bss_frame error\n")); kfree(notif_bss_info); return -EINVAL; } + + cfg80211_put_bss(cbss); kfree(notif_bss_info); return err; -- cgit v1.2.3 From 515c34d76f5abdf7664a8349adde90a28f4ba6e2 Mon Sep 17 00:00:00 2001 From: Dmitry Shmidt Date: Fri, 2 Dec 2011 13:10:47 -0800 Subject: net: wireless: bcmdhd: Add FW reloading in case of FW hang Signed-off-by: Dmitry Shmidt --- drivers/net/wireless/bcmdhd/dhd_linux.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/bcmdhd/dhd_linux.c b/drivers/net/wireless/bcmdhd/dhd_linux.c index 5ce510ac8b66..7afd0b8872e7 100644 --- a/drivers/net/wireless/bcmdhd/dhd_linux.c +++ b/drivers/net/wireless/bcmdhd/dhd_linux.c @@ -2297,7 +2297,6 @@ dhd_stop(struct net_device *net) if (ifidx == 0 && !dhd_download_fw_on_driverload) wl_android_wifi_off(net); #endif - dhd->pub.hang_was_sent = 0; dhd->pub.rxcnt_timeout = 0; dhd->pub.txcnt_timeout = 0; OLD_MOD_DEC_USE_COUNT; @@ -2326,6 +2325,8 @@ dhd_open(struct net_device *net) firmware_path[0] = '\0'; } + dhd->pub.hang_was_sent = 0; + #if !defined(WL_CFG80211) /* * Force start if ifconfig_up gets called before START command @@ -4284,6 +4285,8 @@ int net_os_send_hang_message(struct net_device *dev) #endif #if defined(WL_CFG80211) ret = wl_cfg80211_hang(dev, WLAN_REASON_UNSPECIFIED); + dev_close(dev); + dev_open(dev); #endif } } -- cgit v1.2.3 From 219f9f95b62851737b8be34c8f733c1891e8eb1a Mon Sep 17 00:00:00 2001 From: Dmitry Shmidt Date: Fri, 2 Dec 2011 13:24:01 -0800 Subject: net: wireless: bcmdhd: Fix scan crash in ibss mode Signed-off-by: Dmitry Shmidt --- drivers/net/wireless/bcmdhd/wl_cfg80211.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/bcmdhd/wl_cfg80211.c b/drivers/net/wireless/bcmdhd/wl_cfg80211.c index 17ed972f2d73..16de42239cff 100644 --- a/drivers/net/wireless/bcmdhd/wl_cfg80211.c +++ b/drivers/net/wireless/bcmdhd/wl_cfg80211.c @@ -1461,7 +1461,7 @@ __wl_cfg80211_scan(struct wiphy *wiphy, struct net_device *ndev, (int)wl->status)); return -EAGAIN; } - if (request->n_ssids > WL_SCAN_PARAMS_SSID_MAX) { + if (request && request->n_ssids > WL_SCAN_PARAMS_SSID_MAX) { WL_ERR(("n_ssids > WL_SCAN_PARAMS_SSID_MAX\n")); return -EOPNOTSUPP; } -- cgit v1.2.3 From 5147e369d36cbfd3aa3bb53f8b231cd39f0e4f7a Mon Sep 17 00:00:00 2001 From: Dmitry Shmidt Date: Tue, 6 Dec 2011 16:27:37 -0800 Subject: net: wireless: bcmdhd: Allow to push more packets to FW for Tx Signed-off-by: Dmitry Shmidt --- drivers/net/wireless/bcmdhd/dhd_sdio.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/bcmdhd/dhd_sdio.c b/drivers/net/wireless/bcmdhd/dhd_sdio.c index b5e10e0037ef..e5ffc4f44e17 100644 --- a/drivers/net/wireless/bcmdhd/dhd_sdio.c +++ b/drivers/net/wireless/bcmdhd/dhd_sdio.c @@ -382,7 +382,7 @@ static bool dhd_readahead; /* To check if there's window offered */ #define DATAOK(bus) \ - (((uint8)(bus->tx_max - bus->tx_seq) > 2) && \ + (((uint8)(bus->tx_max - bus->tx_seq) > 1) && \ (((uint8)(bus->tx_max - bus->tx_seq) & 0x80) == 0)) /* To check if there's window offered for ctrl frame */ -- cgit v1.2.3 From 11a0366bec822acca01aef4fba0d9b6a6b15a653 Mon Sep 17 00:00:00 2001 From: Dmitry Shmidt Date: Mon, 12 Dec 2011 15:40:33 -0800 Subject: net: wireless: bcmdhd: Fix getting arp_hostip table Signed-off-by: Dmitry Shmidt --- drivers/net/wireless/bcmdhd/dhd_common.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/bcmdhd/dhd_common.c b/drivers/net/wireless/bcmdhd/dhd_common.c index 07f2124516a2..6035a9542638 100644 --- a/drivers/net/wireless/bcmdhd/dhd_common.c +++ b/drivers/net/wireless/bcmdhd/dhd_common.c @@ -1494,7 +1494,7 @@ dhd_arp_get_arp_hostip_table(dhd_pub_t *dhd, void *buf, int buflen) return -1; iov_len = bcm_mkiovar("arp_hostip", 0, 0, buf, buflen); - retcode = dhd_wl_ioctl_cmd(dhd, WLC_GET_VAR, buf, buflen, TRUE, 0); + retcode = dhd_wl_ioctl_cmd(dhd, WLC_GET_VAR, buf, buflen, FALSE, 0); if (retcode) { DHD_TRACE(("%s: ioctl WLC_GET_VAR error %d\n", -- cgit v1.2.3 From bd6f8f7fb18e40c1e09ee55fe5f6b59ab61f7862 Mon Sep 17 00:00:00 2001 From: Dmitry Shmidt Date: Tue, 13 Dec 2011 12:27:49 -0800 Subject: net: wireless: bcmdhd: Decrease event wake_lock timeout to 1500 ms Signed-off-by: Dmitry Shmidt --- drivers/net/wireless/bcmdhd/dhd.h | 4 ++-- drivers/net/wireless/bcmdhd/dhd_linux.c | 8 ++++---- drivers/net/wireless/bcmdhd/wl_iw.c | 2 +- 3 files changed, 7 insertions(+), 7 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/bcmdhd/dhd.h b/drivers/net/wireless/bcmdhd/dhd.h index 4ad5ad038cc6..420e6e4ec017 100644 --- a/drivers/net/wireless/bcmdhd/dhd.h +++ b/drivers/net/wireless/bcmdhd/dhd.h @@ -314,8 +314,8 @@ inline static void MUTEX_UNLOCK_SOFTAP_SET(dhd_pub_t * dhdp) #define DHD_OS_WAKE_LOCK_TIMEOUT(pub) dhd_os_wake_lock_timeout(pub) #define DHD_OS_WAKE_LOCK_TIMEOUT_ENABLE(pub, val) dhd_os_wake_lock_timeout_enable(pub, val) -#define DHD_PACKET_TIMEOUT 1 -#define DHD_EVENT_TIMEOUT 2 +#define DHD_PACKET_TIMEOUT_MS 1000 +#define DHD_EVENT_TIMEOUT_MS 1500 /* interface operations (register, remove) should be atomic, use this lock to prevent race * condition among wifi on/off and interface operation functions diff --git a/drivers/net/wireless/bcmdhd/dhd_linux.c b/drivers/net/wireless/bcmdhd/dhd_linux.c index 7afd0b8872e7..f41a284ca37d 100644 --- a/drivers/net/wireless/bcmdhd/dhd_linux.c +++ b/drivers/net/wireless/bcmdhd/dhd_linux.c @@ -1398,7 +1398,7 @@ dhd_rx_frame(dhd_pub_t *dhdp, int ifidx, void *pktbuf, int numpkt, uint8 chan) int i; dhd_if_t *ifp; wl_event_msg_t event; - int tout = DHD_PACKET_TIMEOUT; + int tout = DHD_PACKET_TIMEOUT_MS; DHD_TRACE(("%s: Enter\n", __FUNCTION__)); @@ -1502,7 +1502,7 @@ dhd_rx_frame(dhd_pub_t *dhdp, int ifidx, void *pktbuf, int numpkt, uint8 chan) if (event.event_type == WLC_E_BTA_HCI_EVENT) { dhd_bta_doevt(dhdp, data, event.datalen); } - tout = DHD_EVENT_TIMEOUT; + tout = DHD_EVENT_TIMEOUT_MS; } ASSERT(ifidx < DHD_MAX_IFS && dhd->iflist[ifidx]); @@ -2030,7 +2030,7 @@ dhd_ioctl_entry(struct net_device *net, struct ifreq *ifr, int cmd) /* send to dongle only if we are not waiting for reload already */ if (dhd->pub.hang_was_sent) { DHD_ERROR(("%s: HANG was sent up earlier\n", __FUNCTION__)); - DHD_OS_WAKE_LOCK_TIMEOUT_ENABLE(&dhd->pub, DHD_EVENT_TIMEOUT); + DHD_OS_WAKE_LOCK_TIMEOUT_ENABLE(&dhd->pub, DHD_EVENT_TIMEOUT_MS); DHD_OS_WAKE_UNLOCK(&dhd->pub); return OSL_ERROR(BCME_DONGLE_DOWN); } @@ -4426,7 +4426,7 @@ int dhd_os_wake_lock_timeout(dhd_pub_t *pub) #ifdef CONFIG_HAS_WAKELOCK if (dhd->wakelock_timeout_enable) wake_lock_timeout(&dhd->wl_rxwake, - dhd->wakelock_timeout_enable * HZ); + msecs_to_jiffies(dhd->wakelock_timeout_enable)); #endif dhd->wakelock_timeout_enable = 0; spin_unlock_irqrestore(&dhd->wakelock_spinlock, flags); diff --git a/drivers/net/wireless/bcmdhd/wl_iw.c b/drivers/net/wireless/bcmdhd/wl_iw.c index 457372b62b3a..d6aa56f858f4 100644 --- a/drivers/net/wireless/bcmdhd/wl_iw.c +++ b/drivers/net/wireless/bcmdhd/wl_iw.c @@ -1626,7 +1626,7 @@ wl_iw_send_priv_event( strcpy(extra, flag); wrqu.data.length = strlen(extra); wireless_send_event(dev, cmd, &wrqu, extra); - net_os_wake_lock_timeout_enable(dev, DHD_EVENT_TIMEOUT); + net_os_wake_lock_timeout_enable(dev, DHD_EVENT_TIMEOUT_MS); WL_TRACE(("Send IWEVCUSTOM Event as %s\n", extra)); return 0; -- cgit v1.2.3 From 95f2a420420a36d42b3be4eb59d0cdd376873f69 Mon Sep 17 00:00:00 2001 From: Dmitry Shmidt Date: Tue, 13 Dec 2011 17:39:48 -0800 Subject: net: wireless: bcmdhd: Fix proper scan command even if request is NULL Signed-off-by: Dmitry Shmidt --- drivers/net/wireless/bcmdhd/wl_cfg80211.c | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/bcmdhd/wl_cfg80211.c b/drivers/net/wireless/bcmdhd/wl_cfg80211.c index 16de42239cff..07200221ff12 100644 --- a/drivers/net/wireless/bcmdhd/wl_cfg80211.c +++ b/drivers/net/wireless/bcmdhd/wl_cfg80211.c @@ -1130,8 +1130,8 @@ wl_cfg80211_notify_ifchange(void) static void wl_scan_prep(struct wl_scan_params *params, struct cfg80211_scan_request *request) { - u32 n_ssids = request->n_ssids; - u32 n_channels = request->n_channels; + u32 n_ssids; + u32 n_channels; u16 channel; chanspec_t chanspec; s32 i, offset; @@ -1160,6 +1160,12 @@ static void wl_scan_prep(struct wl_scan_params *params, struct cfg80211_scan_req params->passive_time = htod32(params->passive_time); params->home_time = htod32(params->home_time); + if (!request) + return; + + n_ssids = request->n_ssids; + n_channels = request->n_channels; + /* Copy channel array if applicable */ WL_SCAN(("### List of channelspecs to scan ###\n")); if (n_channels > 0) { @@ -1248,8 +1254,7 @@ wl_run_iscan(struct wl_iscan_ctrl *iscan, struct cfg80211_scan_request *request, return -ENOMEM; } - if (request != NULL) - wl_scan_prep(¶ms->params, request); + wl_scan_prep(¶ms->params, request); params->version = htod32(ISCAN_REQ_VERSION); params->action = htod16(action); @@ -1340,8 +1345,7 @@ wl_run_escan(struct wl_priv *wl, struct net_device *ndev, goto exit; } - if (request != NULL) - wl_scan_prep(¶ms->params, request); + wl_scan_prep(¶ms->params, request); params->version = htod32(ESCAN_REQ_VERSION); params->action = htod16(action); params->sync_id = htod16(0x1234); -- cgit v1.2.3 From 7329d57bb986d6a290076e3abdc105c2037288c6 Mon Sep 17 00:00:00 2001 From: Dmitry Shmidt Date: Fri, 16 Dec 2011 12:54:51 -0800 Subject: net: wireless: bcmdhd: Fix P2P interface removal Signed-off-by: Dmitry Shmidt --- drivers/net/wireless/bcmdhd/dhd_linux.c | 3 +++ drivers/net/wireless/bcmdhd/wl_cfg80211.c | 43 ++++++++++++++++++++++++------- drivers/net/wireless/bcmdhd/wl_cfg80211.h | 9 ++++--- 3 files changed, 42 insertions(+), 13 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/bcmdhd/dhd_linux.c b/drivers/net/wireless/bcmdhd/dhd_linux.c index f41a284ca37d..32dcc079ade3 100644 --- a/drivers/net/wireless/bcmdhd/dhd_linux.c +++ b/drivers/net/wireless/bcmdhd/dhd_linux.c @@ -1033,6 +1033,9 @@ dhd_op_if(dhd_if_t *ifp) if (ret < 0) { ifp->set_multicast = FALSE; if (ifp->net) { +#ifdef WL_CFG80211 + wl_cfg80211_post_del((void*)(ifp->net)); +#endif free_netdev(ifp->net); } dhd->iflist[ifp->idx] = NULL; diff --git a/drivers/net/wireless/bcmdhd/wl_cfg80211.c b/drivers/net/wireless/bcmdhd/wl_cfg80211.c index 07200221ff12..11f14bba3167 100644 --- a/drivers/net/wireless/bcmdhd/wl_cfg80211.c +++ b/drivers/net/wireless/bcmdhd/wl_cfg80211.c @@ -16,7 +16,7 @@ * the license of that module. An independent module is a module which is not * derived from this software. The special exception does not apply to any * modifications of the software. - * + * * Notwithstanding the above, under no circumstances may you combine this * software in any way with any other Broadcom software provided under a license * other than the GPL, without Broadcom's express prior written consent. @@ -589,7 +589,7 @@ static const u32 __wl_cipher_suites[] = { WLAN_CIPHER_SUITE_WEP104, WLAN_CIPHER_SUITE_TKIP, WLAN_CIPHER_SUITE_CCMP, - WLAN_CIPHER_SUITE_AES_CMAC, + WLAN_CIPHER_SUITE_AES_CMAC }; /* There isn't a lot of sense in it, but you can transmit anything you like */ @@ -844,8 +844,10 @@ wl_cfg80211_add_virtual_iface(struct wiphy *wiphy, char *name, wl_set_p2p_status(wl, IF_ADD); err = wl_cfgp2p_ifadd(wl, &wl->p2p->int_addr, htod32(wlif_type), chspec); - if (unlikely(err)) + if (unlikely(err)) { + WL_ERR((" virtual iface add failed (%d) \n", err)); return ERR_PTR(-ENOMEM); + } timeout = wait_event_interruptible_timeout(wl->dongle_event_wait, (wl_get_p2p_status(wl, IF_ADD) == false), @@ -860,7 +862,7 @@ wl_cfg80211_add_virtual_iface(struct wiphy *wiphy, char *name, } vwdev->wiphy = wl->wdev->wiphy; WL_INFO((" virtual interface(%s) is created memalloc done \n", - wl->p2p->vir_ifname)); + wl->p2p->vir_ifname)); index = alloc_idx_vwdev(wl); wl->vwdev[index] = vwdev; vwdev->iftype = @@ -873,6 +875,8 @@ wl_cfg80211_add_virtual_iface(struct wiphy *wiphy, char *name, wl_set_drv_status(wl, READY); wl->p2p->vif_created = true; set_mode_by_netdev(wl, _ndev, mode); + WL_DBG((" virtual interface(%s) wl->wdev %p wl->wdev->netdev %p vwdev %p vwdev->netdev %p\n", + wl->p2p->vir_ifname, wl->wdev, wl->wdev->netdev, vwdev, vwdev->netdev)); net_attach = wl_to_p2p_bss_private(wl, P2PAPI_BSSCFG_CONNECTION); if (rtnl_is_locked()) { rtnl_unlock(); @@ -927,10 +931,14 @@ wl_cfg80211_del_virtual_iface(struct wiphy *wiphy, struct net_device *dev) * ifconfig down and up sequnce, which will reload the fw * however we should cleanup the linux network virtual interfaces */ - dhd_pub_t *dhd = (dhd_pub_t *)(wl->pub); - WL_ERR(("Firmware returned an error from p2p_ifdel\n")); - WL_ERR(("try to remove linux virtual interface %s\n", dev->name)); - dhd_del_if(dhd->info, dhd_net2idx(dhd->info, dev)); + /* Request framework to RESET and clean up */ + struct net_device *ndev = wl_to_prmry_ndev(wl); + WL_ERR(("Firmware returned an error (%d) from p2p_ifdel" + "HANG Notification sent to %s dev %p wdev %p ndev %p\n", ret, ndev->name, dev, wl->wdev, wl_to_prmry_ndev(wl))); + wl_cfg80211_hang(ndev, WLAN_REASON_UNSPECIFIED); + } + else { + WL_ERR(("Firmware success from p2p_ifdel dev %p wdev %p ndev %p", dev, wl->wdev, wl_to_prmry_ndev(wl))); } /* Wait for any pending scan req to get aborted from the sysioc context */ @@ -1035,7 +1043,7 @@ int (*_net_attach)(dhd_pub_t *dhdp, int ifidx)) WL_ERR(("net is NULL\n")); return 0; } - if (wl->p2p_supported) { + if (wl->p2p_supported && wl_get_p2p_status(wl, IF_ADD)) { WL_DBG(("IF_ADD event called from dongle, old interface name: %s," "new name: %s\n", ndev->name, wl->p2p->vir_ifname)); /* Assign the net device to CONNECT BSSCFG */ @@ -1047,6 +1055,8 @@ int (*_net_attach)(dhd_pub_t *dhdp, int ifidx)) wl_clr_p2p_status(wl, IF_ADD); wake_up_interruptible(&wl->dongle_event_wait); + } else { + ret = BCME_NOTREADY; } return ret; } @@ -1063,7 +1073,8 @@ wl_cfg80211_notify_ifdel(struct net_device *ndev) return 0; } - if (p2p_is_on(wl) && wl->p2p->vif_created) { + if (p2p_is_on(wl) && wl->p2p->vif_created && + wl_get_p2p_status(wl, IF_DELETING)) { if (wl->scan_request) { /* Abort any pending scan requests */ wl->escan_info.escan_state = WL_ESCAN_STATE_IDLE; @@ -1096,6 +1107,18 @@ wl_cfg80211_notify_ifdel(struct net_device *ndev) return 0; } +s32 wl_cfg80211_post_del(void* ndev) +{ + int index; + struct wl_priv *wl = wlcfg_drv_priv; + index = get_idx_vwdev_by_netdev(wl, (struct net_device *)ndev); + WL_DBG(("index : %d\n", index)); + if (index >= 0) { + free_vwdev_by_index(wl, index); + } + return 0; +} + s32 wl_cfg80211_is_progress_ifadd(void) { diff --git a/drivers/net/wireless/bcmdhd/wl_cfg80211.h b/drivers/net/wireless/bcmdhd/wl_cfg80211.h index 262335ef99c2..232db1b1f830 100644 --- a/drivers/net/wireless/bcmdhd/wl_cfg80211.h +++ b/drivers/net/wireless/bcmdhd/wl_cfg80211.h @@ -2,13 +2,13 @@ * Linux cfg80211 driver * * Copyright (C) 1999-2011, Broadcom Corporation - * + * * Unless you and Broadcom execute a separate written software license * agreement governing use of this software, this software is licensed to you * under the terms of the GNU General Public License version 2 (the "GPL"), * available at http://www.broadcom.com/licenses/GPLv2.php, with the * following added to such license: - * + * * As a special exception, the copyright holders of this software give you * permission to link this software with independent modules, and to copy and * distribute the resulting executable under terms of your choice, provided that @@ -16,7 +16,7 @@ * the license of that module. An independent module is a module which is not * derived from this software. The special exception does not apply to any * modifications of the software. - * + * * Notwithstanding the above, under no circumstances may you combine this * software in any way with any other Broadcom software provided under a license * other than the GPL, without Broadcom's express prior written consent. @@ -452,6 +452,7 @@ static inline s32 alloc_idx_vwdev(struct wl_priv *wl) if (wl->vwdev[i] == NULL) return i; } + WL_ERR((" *********alloc_idx_vwdev failed (%d) \n", -1)); return -1; } @@ -462,6 +463,7 @@ static inline s32 get_idx_vwdev_by_netdev(struct wl_priv *wl, struct net_device if ((wl->vwdev[i] != NULL) && (wl->vwdev[i]->netdev == ndev)) return i; } + WL_ERR((" *********get_idx_vwdev_by_netdev failed (%d) \n", -1)); return -1; } @@ -531,6 +533,7 @@ extern s32 wl_cfg80211_down(void); /* dongle down */ extern s32 wl_cfg80211_notify_ifadd(struct net_device *net, s32 idx, s32 bssidx, int (*_net_attach)(dhd_pub_t *dhdp, int ifidx)); extern s32 wl_cfg80211_notify_ifdel(struct net_device *ndev); +extern s32 wl_cfg80211_post_del(void *ndev); extern s32 wl_cfg80211_is_progress_ifadd(void); extern s32 wl_cfg80211_is_progress_ifchange(void); extern s32 wl_cfg80211_is_progress_ifadd(void); -- cgit v1.2.3 From e9a392aa44312b9235047af3718dc356758a74ae Mon Sep 17 00:00:00 2001 From: Dmitry Shmidt Date: Mon, 19 Dec 2011 10:24:09 -0800 Subject: net: wireless: bcmdhd: Enable wlan access on resume for all sdio functions Signed-off-by: Dmitry Shmidt --- drivers/net/wireless/bcmdhd/bcmsdh_sdmmc_linux.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/bcmdhd/bcmsdh_sdmmc_linux.c b/drivers/net/wireless/bcmdhd/bcmsdh_sdmmc_linux.c index 1a370862b334..af2a3700e5d9 100644 --- a/drivers/net/wireless/bcmdhd/bcmsdh_sdmmc_linux.c +++ b/drivers/net/wireless/bcmdhd/bcmsdh_sdmmc_linux.c @@ -200,11 +200,9 @@ static int bcmsdh_sdmmc_resume(struct device *pdev) { struct sdio_func *func = dev_to_sdio_func(pdev); - if (func->num != 2) - return 0; dhd_mmc_suspend = FALSE; #if defined(OOB_INTR_ONLY) - if (dhd_os_check_if_up(bcmsdh_get_drvdata())) + if ((func->num == 2) && dhd_os_check_if_up(bcmsdh_get_drvdata())) bcmsdh_oob_intr_set(1); #endif smp_mb(); -- cgit v1.2.3 From aa8b391d41cb81ab0e66a7062cd65387f33edeb6 Mon Sep 17 00:00:00 2001 From: Dmitry Shmidt Date: Fri, 20 Jan 2012 14:15:05 -0800 Subject: net: wireless: bcmdhd: Fake PNO event to wake up the wpa_supplicant Signed-off-by: Dmitry Shmidt --- drivers/net/wireless/bcmdhd/dhd_linux.c | 4 +++- drivers/net/wireless/bcmdhd/wl_cfg80211.c | 20 ++++++++++++++++---- 2 files changed, 19 insertions(+), 5 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/bcmdhd/dhd_linux.c b/drivers/net/wireless/bcmdhd/dhd_linux.c index 32dcc079ade3..6fbb5445846d 100644 --- a/drivers/net/wireless/bcmdhd/dhd_linux.c +++ b/drivers/net/wireless/bcmdhd/dhd_linux.c @@ -1502,10 +1502,12 @@ dhd_rx_frame(dhd_pub_t *dhdp, int ifidx, void *pktbuf, int numpkt, uint8 chan) &data); wl_event_to_host_order(&event); + tout = DHD_EVENT_TIMEOUT_MS; if (event.event_type == WLC_E_BTA_HCI_EVENT) { dhd_bta_doevt(dhdp, data, event.datalen); + } else if (event.event_type == WLC_E_PFN_NET_FOUND) { + tout *= 2; } - tout = DHD_EVENT_TIMEOUT_MS; } ASSERT(ifidx < DHD_MAX_IFS && dhd->iflist[ifidx]); diff --git a/drivers/net/wireless/bcmdhd/wl_cfg80211.c b/drivers/net/wireless/bcmdhd/wl_cfg80211.c index 11f14bba3167..26d7ef120ff0 100644 --- a/drivers/net/wireless/bcmdhd/wl_cfg80211.c +++ b/drivers/net/wireless/bcmdhd/wl_cfg80211.c @@ -256,6 +256,8 @@ static s32 wl_bss_roaming_done(struct wl_priv *wl, struct net_device *ndev, const wl_event_msg_t *e, void *data); static s32 wl_notify_mic_status(struct wl_priv *wl, struct net_device *ndev, const wl_event_msg_t *e, void *data); +static s32 wl_notify_pfn_status(struct wl_priv *wl, struct net_device *ndev, + const wl_event_msg_t *e, void *data); /* * register/deregister sdio function */ @@ -4789,6 +4791,19 @@ wl_notify_mic_status(struct wl_priv *wl, struct net_device *ndev, return 0; } +static s32 +wl_notify_pfn_status(struct wl_priv *wl, struct net_device *ndev, + const wl_event_msg_t *e, void *data) +{ + WL_ERR((" PNO Event\n")); + + mutex_lock(&wl->usr_sync); + /* TODO: Use cfg80211_sched_scan_results(wiphy); */ + cfg80211_disconnected(ndev, 0, NULL, 0, GFP_KERNEL); + mutex_unlock(&wl->usr_sync); + return 0; +} + static s32 wl_notify_scan_status(struct wl_priv *wl, struct net_device *ndev, const wl_event_msg_t *e, void *data) @@ -4999,7 +5014,7 @@ static void wl_init_event_handler(struct wl_priv *wl) wl->evt_handler[WLC_E_P2P_DISC_LISTEN_COMPLETE] = wl_cfgp2p_listen_complete; wl->evt_handler[WLC_E_ACTION_FRAME_COMPLETE] = wl_cfgp2p_action_tx_complete; wl->evt_handler[WLC_E_ACTION_FRAME_OFF_CHAN_COMPLETE] = wl_cfgp2p_action_tx_complete; - + wl->evt_handler[WLC_E_PFN_NET_FOUND] = wl_notify_pfn_status; } static s32 wl_init_priv_mem(struct wl_priv *wl) @@ -5761,9 +5776,6 @@ wl_cfg80211_event(struct net_device *ndev, const wl_event_msg_t * e, void *data) WL_DBG(("event_type (%d):" "WLC_E_" "%s\n", event_type, estr)); #endif /* (WL_DBG_LEVEL > 0) */ - if (event_type == WLC_E_PFN_NET_FOUND) - WL_ERR((" PNO Event\n")); - if (likely(!wl_enq_event(wl, ndev, event_type, e, data))) wl_wakeup_event(wl); } -- cgit v1.2.3 From b9a1eece16daa1e06356d6166e88860882c1f5b2 Mon Sep 17 00:00:00 2001 From: Dmitry Shmidt Date: Mon, 23 Jan 2012 12:47:21 -0800 Subject: net: wireless: bcmdhd: Add WIPHY_FLAG_SUPPORTS_FW_ROAM flag Adding this flag will allow NL80211_ATTR_ROAM_SUPPORT, and will set WPA_DRIVER_FLAGS_BSS_SELECTION flag in wpa_supplicant Signed-off-by: Dmitry Shmidt --- drivers/net/wireless/bcmdhd/wl_cfg80211.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers/net') diff --git a/drivers/net/wireless/bcmdhd/wl_cfg80211.c b/drivers/net/wireless/bcmdhd/wl_cfg80211.c index 26d7ef120ff0..b7696eb2036b 100644 --- a/drivers/net/wireless/bcmdhd/wl_cfg80211.c +++ b/drivers/net/wireless/bcmdhd/wl_cfg80211.c @@ -4114,6 +4114,9 @@ static struct wireless_dev *wl_alloc_wdev(struct device *sdiofunc_dev) WIPHY_FLAG_SUPPORTS_SEPARATE_DEFAULT_KEYS | #endif WIPHY_FLAG_4ADDR_STATION; +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 2, 0) + wdev->wiphy->flags |= WIPHY_FLAG_SUPPORTS_FW_ROAM; +#endif #ifdef ENABLE_CUSTOM_REGULATORY_DOMAIN WL_DBG(("Registering custom regulatory)\n")); -- cgit v1.2.3 From 8369c36255c594c282cc715394c0df0fc7023498 Mon Sep 17 00:00:00 2001 From: Dmitry Shmidt Date: Tue, 24 Jan 2012 13:37:34 -0800 Subject: net: wireless: bcmdhd: Update to Version 5.90.195.15 - Add WFD concurrent mode support Signed-off-by: Dmitry Shmidt --- drivers/net/wireless/bcmdhd/bcmevent.c | 8 +- drivers/net/wireless/bcmdhd/bcmsdh_sdmmc_linux.c | 9 +- drivers/net/wireless/bcmdhd/bcmutils.c | 4 +- drivers/net/wireless/bcmdhd/dhd.h | 26 +- drivers/net/wireless/bcmdhd/dhd_cdc.c | 9 +- drivers/net/wireless/bcmdhd/dhd_common.c | 4 +- drivers/net/wireless/bcmdhd/dhd_linux.c | 148 ++-- drivers/net/wireless/bcmdhd/dhd_linux_mon.c | 28 +- drivers/net/wireless/bcmdhd/dhd_sdio.c | 27 +- drivers/net/wireless/bcmdhd/dhd_wlfc.h | 12 +- drivers/net/wireless/bcmdhd/hndpmu.c | 44 +- drivers/net/wireless/bcmdhd/include/Makefile | 2 +- drivers/net/wireless/bcmdhd/include/aidmp.h | 2 +- drivers/net/wireless/bcmdhd/include/bcmcdc.h | 2 +- drivers/net/wireless/bcmdhd/include/bcmdefs.h | 37 +- drivers/net/wireless/bcmdhd/include/bcmdevs.h | 573 +++++++++++++- drivers/net/wireless/bcmdhd/include/bcmendian.h | 2 +- drivers/net/wireless/bcmdhd/include/bcmpcispi.h | 2 +- drivers/net/wireless/bcmdhd/include/bcmperf.h | 2 +- drivers/net/wireless/bcmdhd/include/bcmsdbus.h | 10 +- drivers/net/wireless/bcmdhd/include/bcmsdh.h | 10 +- drivers/net/wireless/bcmdhd/include/bcmsdh_sdmmc.h | 2 +- drivers/net/wireless/bcmdhd/include/bcmsdpcm.h | 2 +- drivers/net/wireless/bcmdhd/include/bcmsdspi.h | 2 +- drivers/net/wireless/bcmdhd/include/bcmsdstd.h | 34 +- drivers/net/wireless/bcmdhd/include/bcmspi.h | 2 +- drivers/net/wireless/bcmdhd/include/bcmutils.h | 14 +- drivers/net/wireless/bcmdhd/include/bcmwifi.h | 2 +- drivers/net/wireless/bcmdhd/include/dhdioctl.h | 2 +- drivers/net/wireless/bcmdhd/include/epivers.h | 14 +- drivers/net/wireless/bcmdhd/include/hndpmu.h | 2 +- .../net/wireless/bcmdhd/include/hndrte_armtrap.h | 2 +- drivers/net/wireless/bcmdhd/include/hndrte_cons.h | 2 +- drivers/net/wireless/bcmdhd/include/hndsoc.h | 2 +- drivers/net/wireless/bcmdhd/include/htsf.h | 2 +- drivers/net/wireless/bcmdhd/include/linux_osl.h | 2 +- drivers/net/wireless/bcmdhd/include/linuxver.h | 6 +- drivers/net/wireless/bcmdhd/include/miniopt.h | 2 +- drivers/net/wireless/bcmdhd/include/msgtrace.h | 2 +- drivers/net/wireless/bcmdhd/include/osl.h | 2 +- .../wireless/bcmdhd/include/packed_section_end.h | 2 +- .../wireless/bcmdhd/include/packed_section_start.h | 2 +- drivers/net/wireless/bcmdhd/include/pcicfg.h | 28 +- drivers/net/wireless/bcmdhd/include/proto/802.11.h | 317 +++++++- .../net/wireless/bcmdhd/include/proto/802.11_bta.h | 2 +- .../net/wireless/bcmdhd/include/proto/802.11e.h | 2 +- drivers/net/wireless/bcmdhd/include/proto/802.1d.h | 2 +- drivers/net/wireless/bcmdhd/include/proto/bcmeth.h | 2 +- .../net/wireless/bcmdhd/include/proto/bcmevent.h | 9 +- drivers/net/wireless/bcmdhd/include/proto/bcmip.h | 2 +- .../net/wireless/bcmdhd/include/proto/bt_amp_hci.h | 2 +- drivers/net/wireless/bcmdhd/include/proto/eapol.h | 2 +- .../net/wireless/bcmdhd/include/proto/ethernet.h | 3 +- drivers/net/wireless/bcmdhd/include/proto/p2p.h | 2 +- drivers/net/wireless/bcmdhd/include/proto/sdspi.h | 2 +- drivers/net/wireless/bcmdhd/include/proto/vlan.h | 2 +- drivers/net/wireless/bcmdhd/include/proto/wpa.h | 12 +- drivers/net/wireless/bcmdhd/include/sbchipc.h | 168 +++- drivers/net/wireless/bcmdhd/include/sbconfig.h | 2 +- drivers/net/wireless/bcmdhd/include/sbhnddma.h | 6 +- drivers/net/wireless/bcmdhd/include/sbpcmcia.h | 2 +- drivers/net/wireless/bcmdhd/include/sbsdio.h | 2 +- drivers/net/wireless/bcmdhd/include/sbsdpcmdev.h | 2 +- drivers/net/wireless/bcmdhd/include/sbsocram.h | 2 +- drivers/net/wireless/bcmdhd/include/sdio.h | 5 +- drivers/net/wireless/bcmdhd/include/sdioh.h | 32 +- drivers/net/wireless/bcmdhd/include/sdiovar.h | 2 +- drivers/net/wireless/bcmdhd/include/siutils.h | 30 +- drivers/net/wireless/bcmdhd/include/trxhdr.h | 3 +- drivers/net/wireless/bcmdhd/include/typedefs.h | 5 +- drivers/net/wireless/bcmdhd/include/wlfc_proto.h | 2 +- drivers/net/wireless/bcmdhd/include/wlioctl.h | 87 +- drivers/net/wireless/bcmdhd/linux_osl.c | 23 +- drivers/net/wireless/bcmdhd/siutils.c | 195 ++++- drivers/net/wireless/bcmdhd/wl_android.c | 6 +- drivers/net/wireless/bcmdhd/wl_cfg80211.c | 875 +++++++++++++-------- drivers/net/wireless/bcmdhd/wl_cfg80211.h | 282 ++++--- drivers/net/wireless/bcmdhd/wl_cfgp2p.c | 165 +++- drivers/net/wireless/bcmdhd/wl_cfgp2p.h | 12 +- drivers/net/wireless/bcmdhd/wl_iw.c | 110 ++- drivers/net/wireless/bcmdhd/wl_iw.h | 17 +- 81 files changed, 2735 insertions(+), 752 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/bcmdhd/bcmevent.c b/drivers/net/wireless/bcmdhd/bcmevent.c index 24581ddd353c..6a25d9a5a57f 100644 --- a/drivers/net/wireless/bcmdhd/bcmevent.c +++ b/drivers/net/wireless/bcmdhd/bcmevent.c @@ -20,7 +20,7 @@ * Notwithstanding the above, under no circumstances may you combine this * software in any way with any other Broadcom software provided under a license * other than the GPL, without Broadcom's express prior written consent. - * $Id: bcmevent.c,v 1.8.2.7 2011-02-01 06:23:39 Exp $ + * $Id: bcmevent.c,v 1.8.2.7 2011-02-01 06:23:39 $ */ #include @@ -29,7 +29,7 @@ #include #include -#if WLC_E_LAST != 85 +#if WLC_E_LAST != 87 #error "You need to add an entry to bcmevent_names[] for the new event" #endif @@ -117,8 +117,10 @@ const bcmevent_name_t bcmevent_names[] = { { WLC_E_PFN_SCAN_NONE, "PFN_SCAN_NONE" }, { WLC_E_PFN_SCAN_ALLGONE, "PFN_SCAN_ALLGONE" }, #ifdef SOFTAP - { WLC_E_GTK_PLUMBED, "GTK_PLUMBED" } + { WLC_E_GTK_PLUMBED, "GTK_PLUMBED" }, #endif + { WLC_E_ASSOC_REQ_IE, "ASSOC_REQ_IE" }, + { WLC_E_ASSOC_RESP_IE, "ASSOC_RESP_IE" } }; diff --git a/drivers/net/wireless/bcmdhd/bcmsdh_sdmmc_linux.c b/drivers/net/wireless/bcmdhd/bcmsdh_sdmmc_linux.c index af2a3700e5d9..08b1f492ed8b 100644 --- a/drivers/net/wireless/bcmdhd/bcmsdh_sdmmc_linux.c +++ b/drivers/net/wireless/bcmdhd/bcmsdh_sdmmc_linux.c @@ -21,7 +21,7 @@ * software in any way with any other Broadcom software provided under a license * other than the GPL, without Broadcom's express prior written consent. * - * $Id: bcmsdh_sdmmc_linux.c,v 1.8.6.2 2011-02-01 18:38:36 Exp $ + * $Id: bcmsdh_sdmmc_linux.c 300908 2011-12-06 10:32:01Z $ */ #include @@ -61,7 +61,7 @@ #include #ifdef WL_CFG80211 -extern void wl_cfg80211_set_sdio_func(void *func); +extern void wl_cfg80211_set_parent_dev(void *dev); #endif extern void sdioh_sdmmc_devintr_off(sdioh_info_t *sd); @@ -118,7 +118,7 @@ static int bcmsdh_sdmmc_probe(struct sdio_func *func, if (func->num == 2) { #ifdef WL_CFG80211 - wl_cfg80211_set_sdio_func(func); + wl_cfg80211_set_parent_dev(&func->dev); #endif sd_trace(("F2 found, calling bcmsdh_probe_bcmdhd...\n")); ret = bcmsdh_probe_bcmdhd(&func->dev); @@ -153,6 +153,9 @@ static const struct sdio_device_id bcmsdh_sdmmc_ids[] = { { SDIO_DEVICE(SDIO_VENDOR_ID_BROADCOM, SDIO_DEVICE_ID_BROADCOM_4325) }, { SDIO_DEVICE(SDIO_VENDOR_ID_BROADCOM, SDIO_DEVICE_ID_BROADCOM_4319) }, { SDIO_DEVICE(SDIO_VENDOR_ID_BROADCOM, SDIO_DEVICE_ID_BROADCOM_4330) }, +#ifndef BOARD_PANDA + { SDIO_DEVICE_CLASS(SDIO_CLASS_NONE) }, +#endif { /* end: all zeroes */ }, }; diff --git a/drivers/net/wireless/bcmdhd/bcmutils.c b/drivers/net/wireless/bcmdhd/bcmutils.c index fbdd7cd2d19b..6b578e653648 100644 --- a/drivers/net/wireless/bcmdhd/bcmutils.c +++ b/drivers/net/wireless/bcmdhd/bcmutils.c @@ -20,7 +20,7 @@ * Notwithstanding the above, under no circumstances may you combine this * software in any way with any other Broadcom software provided under a license * other than the GPL, without Broadcom's express prior written consent. - * $Id: bcmutils.c,v 1.277.2.18 2011-01-26 02:32:08 Exp $ + * $Id: bcmutils.c,v 1.277.2.18 2011-01-26 02:32:08 $ */ #include @@ -987,7 +987,6 @@ pktsetprio(void *pkt, bool update_vtag) return (rc | priority); } -#ifndef BCM_BOOTLOADER static char bcm_undeferrstr[32]; static const char *bcmerrorstrtable[] = BCMERRSTRINGTABLE; @@ -1009,7 +1008,6 @@ bcmerrorstr(int bcmerror) return bcmerrorstrtable[-bcmerror]; } -#endif /* !BCM_BOOTLOADER */ diff --git a/drivers/net/wireless/bcmdhd/dhd.h b/drivers/net/wireless/bcmdhd/dhd.h index 420e6e4ec017..50eb94d0c26b 100644 --- a/drivers/net/wireless/bcmdhd/dhd.h +++ b/drivers/net/wireless/bcmdhd/dhd.h @@ -24,7 +24,7 @@ * software in any way with any other Broadcom software provided under a license * other than the GPL, without Broadcom's express prior written consent. * - * $Id: dhd.h 290844 2011-10-20 08:54:39Z $ + * $Id: dhd.h 301794 2011-12-08 20:41:35Z $ */ /**************** @@ -83,6 +83,9 @@ enum dhd_bus_state { /* max sequential rxcntl timeouts to set HANG event */ #define MAX_CNTL_TIMEOUT 2 +#define DHD_SCAN_ACTIVE_TIME 40 /* ms : Embedded default Active setting from DHD Driver */ +#define DHD_SCAN_PASSIVE_TIME 130 /* ms: Embedded default Passive setting from DHD Driver */ + enum dhd_bus_wake_state { WAKE_LOCK_OFF, WAKE_LOCK_PRIV, @@ -369,6 +372,12 @@ extern int dhd_net_attach(dhd_pub_t *dhdp, int idx); /* Indication from bus module regarding removal/absence of dongle */ extern void dhd_detach(dhd_pub_t *dhdp); +#if defined(WLP2P) && defined(WL_CFG80211) +/* To allow attach/detach calls corresponding to p2p0 interface */ +extern int dhd_attach_p2p(dhd_pub_t *); +extern int dhd_detach_p2p(dhd_pub_t *); +#endif /* WLP2P && WL_CFG80211 */ + extern void dhd_free(dhd_pub_t *dhdp); /* Indication from bus module to change flow-control state */ @@ -411,6 +420,8 @@ extern int dhd_custom_get_mac_address(unsigned char *buf); extern void dhd_os_sdunlock_sndup_rxq(dhd_pub_t * pub); extern void dhd_os_sdlock_eventq(dhd_pub_t * pub); extern void dhd_os_sdunlock_eventq(dhd_pub_t * pub); + +#ifdef PNO_SUPPORT extern int dhd_pno_enable(dhd_pub_t *dhd, int pfn_enabled); extern int dhd_pno_clean(dhd_pub_t *dhd); extern int dhd_pno_set(dhd_pub_t *dhd, wlc_ssid_t* ssids_local, int nssid, @@ -421,9 +432,9 @@ extern int dhd_dev_pno_set(struct net_device *dev, wlc_ssid_t* ssids_local, int nssid, ushort scan_fr, int pno_repeat, int pno_freq_expo_max); extern int dhd_dev_pno_enable(struct net_device *dev, int pfn_enabled); extern int dhd_dev_get_pno_status(struct net_device *dev); -extern int dhd_get_dtim_skip(dhd_pub_t *dhd); +#endif /* PNO_SUPPORT */ + extern bool dhd_check_ap_wfd_mode_set(dhd_pub_t *dhd); -extern bool dhd_os_check_hang(dhd_pub_t *dhdp, int ifidx, int ret); #define DHD_UNICAST_FILTER_NUM 0 #define DHD_BROADCAST_FILTER_NUM 1 @@ -432,6 +443,9 @@ extern bool dhd_os_check_hang(dhd_pub_t *dhdp, int ifidx, int ret); extern int net_os_set_packet_filter(struct net_device *dev, int val); extern int net_os_rxfilter_add_remove(struct net_device *dev, int val, int num); +extern int dhd_get_dtim_skip(dhd_pub_t *dhd); +extern bool dhd_os_check_hang(dhd_pub_t *dhdp, int ifidx, int ret); + #ifdef DHD_DEBUG extern int write_to_file(dhd_pub_t *dhd, uint8 *buf, int size); #endif /* DHD_DEBUG */ @@ -701,12 +715,6 @@ typedef struct dhd_pkttag { #define DHD_PKTTAG_DSTN(tag) ((dhd_pkttag_t*)(tag))->dstn_ether typedef int (*f_commitpkt_t)(void* ctx, void* p); -int dhd_wlfc_enable(dhd_pub_t *dhd); -int dhd_wlfc_interface_event(struct dhd_info *, uint8 action, uint8 ifid, uint8 iftype, uint8* ea); -int dhd_wlfc_FIFOcreditmap_event(struct dhd_info *dhd, uint8* event_data); -int dhd_wlfc_event(struct dhd_info *dhd); -int dhd_os_wlfc_block(dhd_pub_t *pub); -int dhd_os_wlfc_unblock(dhd_pub_t *pub); #ifdef PROP_TXSTATUS_DEBUG #define DHD_WLFC_CTRINC_MAC_CLOSE(entry) do { (entry)->closed_ct++; } while (0) diff --git a/drivers/net/wireless/bcmdhd/dhd_cdc.c b/drivers/net/wireless/bcmdhd/dhd_cdc.c index 846099206030..50e275a4ae23 100644 --- a/drivers/net/wireless/bcmdhd/dhd_cdc.c +++ b/drivers/net/wireless/bcmdhd/dhd_cdc.c @@ -21,7 +21,7 @@ * software in any way with any other Broadcom software provided under a license * other than the GPL, without Broadcom's express prior written consent. * - * $Id: dhd_cdc.c,v 1.51.6.31 2011-02-09 14:31:43 Exp $ + * $Id: dhd_cdc.c 301794 2011-12-08 20:41:35Z $ * * BDC is like CDC, except it includes a header for data packets to convey * packet priority over the bus, and flags (e.g. to indicate checksum status @@ -78,6 +78,8 @@ typedef struct dhd_prot { unsigned char buf[WLC_IOCTL_MAXLEN + ROUND_UP_MARGIN]; } dhd_prot_t; +extern int dhd_dbus_txdata(dhd_pub_t *dhdp, void *pktbuf); + static int dhdcdc_msg(dhd_pub_t *dhd) { @@ -2174,6 +2176,7 @@ dhd_wlfc_init(dhd_pub_t *dhd) WLFC_FLAGS_CREDIT_STATUS_SIGNALS | WLFC_FLAGS_HOST_PROPTXSTATUS_ACTIVE : 0; + dhd->wlfc_state = NULL; /* try to enable/disable signaling by sending "tlv" iovar. if that fails, @@ -2463,7 +2466,7 @@ fail: #ifndef CONFIG_DHD_USE_STATIC_BUF if (cdc != NULL) MFREE(dhd->osh, cdc, sizeof(dhd_prot_t)); -#endif +#endif /* CONFIG_DHD_USE_STATIC_BUF */ return BCME_NOMEM; } @@ -2476,7 +2479,7 @@ dhd_prot_detach(dhd_pub_t *dhd) #endif #ifndef CONFIG_DHD_USE_STATIC_BUF MFREE(dhd->osh, dhd->prot, sizeof(dhd_prot_t)); -#endif +#endif /* CONFIG_DHD_USE_STATIC_BUF */ dhd->prot = NULL; } diff --git a/drivers/net/wireless/bcmdhd/dhd_common.c b/drivers/net/wireless/bcmdhd/dhd_common.c index 6035a9542638..c77242639044 100644 --- a/drivers/net/wireless/bcmdhd/dhd_common.c +++ b/drivers/net/wireless/bcmdhd/dhd_common.c @@ -21,7 +21,7 @@ * software in any way with any other Broadcom software provided under a license * other than the GPL, without Broadcom's express prior written consent. * - * $Id: dhd_common.c 290546 2011-10-19 01:55:21Z $ + * $Id: dhd_common.c 297563 2011-11-20 15:38:29Z $ */ #include #include @@ -862,6 +862,8 @@ wl_show_host_event(wl_event_msg_t *event, void *event_data) break; case WLC_E_SCAN_COMPLETE: + case WLC_E_ASSOC_REQ_IE: + case WLC_E_ASSOC_RESP_IE: case WLC_E_PMKID_CACHE: DHD_EVENT(("MACEVENT: %s\n", event_name)); break; diff --git a/drivers/net/wireless/bcmdhd/dhd_linux.c b/drivers/net/wireless/bcmdhd/dhd_linux.c index 6fbb5445846d..7018e7ac5e91 100644 --- a/drivers/net/wireless/bcmdhd/dhd_linux.c +++ b/drivers/net/wireless/bcmdhd/dhd_linux.c @@ -22,7 +22,7 @@ * software in any way with any other Broadcom software provided under a license * other than the GPL, without Broadcom's express prior written consent. * - * $Id: dhd_linux.c 291449 2011-10-22 12:16:26Z $ + * $Id: dhd_linux.c 301794 2011-12-08 20:41:35Z $ */ #include @@ -110,6 +110,7 @@ extern bool ap_fw_loaded; #include #ifdef ARP_OFFLOAD_SUPPORT +void aoe_update_host_ipv4_table(dhd_pub_t *dhd_pub, u32 ipa, bool add); static int dhd_device_event(struct notifier_block *this, unsigned long event, void *ptr); @@ -274,6 +275,10 @@ typedef struct dhd_info { #ifdef CONFIG_HAS_EARLYSUSPEND struct early_suspend early_suspend; #endif /* CONFIG_HAS_EARLYSUSPEND */ + +#ifdef ARP_OFFLOAD_SUPPORT + u32 pend_ipaddr; +#endif /* ARP_OFFLOAD_SUPPORT */ } dhd_info_t; /* Definitions to provide path to the firmware and nvram @@ -942,8 +947,9 @@ dhd_op_if(dhd_if_t *ifp) unsigned long flags; #endif + if (!ifp || !ifp->info || !ifp->idx) + return; ASSERT(ifp && ifp->info && ifp->idx); /* Virtual interfaces only */ - dhd = ifp->info; DHD_TRACE(("%s: idx %d, state %d\n", __FUNCTION__, ifp->idx, ifp->state)); @@ -1033,10 +1039,8 @@ dhd_op_if(dhd_if_t *ifp) if (ret < 0) { ifp->set_multicast = FALSE; if (ifp->net) { -#ifdef WL_CFG80211 - wl_cfg80211_post_del((void*)(ifp->net)); -#endif free_netdev(ifp->net); + ifp->net = NULL; } dhd->iflist[ifp->idx] = NULL; #ifdef SOFTAP @@ -1167,6 +1171,7 @@ dhd_os_wlfc_block(dhd_pub_t *pub) { dhd_info_t *di = (dhd_info_t *)(pub->info); ASSERT(di != NULL); + spin_lock_bh(&di->wlfc_spinlock); return 1; } @@ -1200,7 +1205,7 @@ dhd_sendpkt(dhd_pub_t *dhdp, int ifidx, void *pktbuf) } /* Update multicast statistic */ - if (PKTLEN(dhdp->osh, pktbuf) >= ETHER_ADDR_LEN) { + if (PKTLEN(dhdp->osh, pktbuf) >= ETHER_HDR_LEN) { uint8 *pktdata = (uint8 *)PKTDATA(dhdp->osh, pktbuf); eh = (struct ether_header *)pktdata; @@ -1208,6 +1213,9 @@ dhd_sendpkt(dhd_pub_t *dhdp, int ifidx, void *pktbuf) dhdp->tx_multicast++; if (ntoh16(eh->ether_type) == ETHER_TYPE_802_1X) atomic_inc(&dhd->pend_8021x_cnt); + } else { + PKTFREE(dhd->pub.osh, pktbuf, TRUE); + return BCME_ERROR; } /* Look into the packet and update the packet priority */ @@ -1594,8 +1602,10 @@ dhd_get_stats(struct net_device *net) DHD_TRACE(("%s: Enter\n", __FUNCTION__)); ifidx = dhd_net2idx(dhd, net); - if (ifidx == DHD_BAD_IF) + if (ifidx == DHD_BAD_IF) { + DHD_ERROR(("%s: BAD_IF\n", __FUNCTION__)); return NULL; + } ifp = dhd->iflist[ifidx]; ASSERT(dhd && ifp); @@ -2044,6 +2054,7 @@ dhd_ioctl_entry(struct net_device *net, struct ifreq *ifr, int cmd) DHD_TRACE(("%s: ifidx %d, cmd 0x%04x\n", __FUNCTION__, ifidx, cmd)); if (ifidx == DHD_BAD_IF) { + DHD_ERROR(("%s: BAD IF\n", __FUNCTION__)); DHD_OS_WAKE_UNLOCK(&dhd->pub); return -1; } @@ -2241,6 +2252,7 @@ dhd_cleanup_virt_ifaces(dhd_info_t *dhd) #endif for (i = 1; i < DHD_MAX_IFS; i++) { + dhd_net_if_lock_local(dhd); if (dhd->iflist[i]) { DHD_TRACE(("Deleting IF: %d \n", i)); if ((dhd->iflist[i]->state != DHD_IF_DEL) && @@ -2250,6 +2262,7 @@ dhd_cleanup_virt_ifaces(dhd_info_t *dhd) dhd_op_if(dhd->iflist[i]); } } + dhd_net_if_unlock_local(dhd); } #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) @@ -2365,7 +2378,6 @@ dhd_open(struct net_device *net) #endif /* defined(WL_CFG80211) */ if (dhd->pub.busstate != DHD_BUS_DATA) { - int ret; /* try to bring up bus */ if ((ret = dhd_bus_start(&dhd->pub)) != 0) { @@ -2491,6 +2503,26 @@ dhd_del_if(dhd_info_t *dhd, int ifidx) up(&dhd->thr_sysioc_ctl.sema); } +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 31)) +static struct net_device_ops dhd_ops_pri = { + .ndo_open = dhd_open, + .ndo_stop = dhd_stop, + .ndo_get_stats = dhd_get_stats, + .ndo_do_ioctl = dhd_ioctl_entry, + .ndo_start_xmit = dhd_start_xmit, + .ndo_set_mac_address = dhd_set_mac_address, + .ndo_set_multicast_list = dhd_set_multicast_list, +}; + +static struct net_device_ops dhd_ops_virt = { + .ndo_get_stats = dhd_get_stats, + .ndo_do_ioctl = dhd_ioctl_entry, + .ndo_start_xmit = dhd_start_xmit, + .ndo_set_mac_address = dhd_set_mac_address, + .ndo_set_multicast_list = dhd_set_multicast_list, +}; +#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 31)) */ + dhd_pub_t * dhd_attach(osl_t *osh, struct dhd_bus *bus, uint bus_hdrlen, void *dev) { @@ -2684,6 +2716,7 @@ dhd_attach(osl_t *osh, struct dhd_bus *bus, uint bus_hdrlen, void *dev) #endif #ifdef ARP_OFFLOAD_SUPPORT + dhd->pend_ipaddr = 0; register_inetaddr_notifier(&dhd_notifier); #endif /* ARP_OFFLOAD_SUPPORT */ @@ -2717,7 +2750,8 @@ dhd_bus_start(dhd_pub_t *dhdp) DHD_TRACE(("Enter %s:\n", __FUNCTION__)); #ifdef DHDTHREAD - dhd_os_sdlock(dhdp); + if (dhd->threads_only) + dhd_os_sdlock(dhdp); #endif /* DHDTHREAD */ /* try to download image and nvram to the dongle */ @@ -2730,14 +2764,16 @@ dhd_bus_start(dhd_pub_t *dhdp) DHD_ERROR(("%s: dhdsdio_probe_download failed. firmware = %s nvram = %s\n", __FUNCTION__, fw_path, nv_path)); #ifdef DHDTHREAD - dhd_os_sdunlock(dhdp); + if (dhd->threads_only) + dhd_os_sdunlock(dhdp); #endif /* DHDTHREAD */ return -1; } } if (dhd->pub.busstate != DHD_BUS_LOAD) { #ifdef DHDTHREAD - dhd_os_sdunlock(dhdp); + if (dhd->threads_only) + dhd_os_sdunlock(dhdp); #endif /* DHDTHREAD */ return -ENETDOWN; } @@ -2751,7 +2787,8 @@ dhd_bus_start(dhd_pub_t *dhdp) DHD_ERROR(("%s, dhd_bus_init failed %d\n", __FUNCTION__, ret)); #ifdef DHDTHREAD - dhd_os_sdunlock(dhdp); + if (dhd->threads_only) + dhd_os_sdunlock(dhdp); #endif /* DHDTHREAD */ return ret; } @@ -2767,7 +2804,8 @@ dhd_bus_start(dhd_pub_t *dhdp) DHD_ERROR(("%s Host failed to register for OOB\n", __FUNCTION__)); #ifdef DHDTHREAD - dhd_os_sdunlock(dhdp); + if (dhd->threads_only) + dhd_os_sdunlock(dhdp); #endif /* DHDTHREAD */ return -ENODEV; } @@ -2784,13 +2822,15 @@ dhd_bus_start(dhd_pub_t *dhdp) del_timer_sync(&dhd->timer); DHD_ERROR(("%s failed bus is not ready\n", __FUNCTION__)); #ifdef DHDTHREAD - dhd_os_sdunlock(dhdp); + if (dhd->threads_only) + dhd_os_sdunlock(dhdp); #endif /* DHDTHREAD */ return -ENODEV; } #ifdef DHDTHREAD - dhd_os_sdunlock(dhdp); + if (dhd->threads_only) + dhd_os_sdunlock(dhdp); #endif /* DHDTHREAD */ #ifdef READ_MACADDR @@ -2805,6 +2845,15 @@ dhd_bus_start(dhd_pub_t *dhdp) dhd_write_macaddr(dhd->pub.mac.octet); #endif +#ifdef ARP_OFFLOAD_SUPPORT + if (dhd->pend_ipaddr) { +#ifdef AOE_IP_ALIAS_SUPPORT + aoe_update_host_ipv4_table(&dhd->pub, dhd->pend_ipaddr, TRUE); +#endif /* AOE_IP_ALIAS_SUPPORT */ + dhd->pend_ipaddr = 0; + } +#endif /* ARP_OFFLOAD_SUPPORT */ + return 0; } @@ -2824,9 +2873,9 @@ dhd_preinit_ioctls(dhd_pub_t *dhd) #if defined(ARP_OFFLOAD_SUPPORT) int arpoe = 1; #endif - int scan_assoc_time = 40; + int scan_assoc_time = DHD_SCAN_ACTIVE_TIME; int scan_unassoc_time = 40; - int scan_passive_time = 130; + int scan_passive_time = DHD_SCAN_PASSIVE_TIME; char buf[WLC_IOCTL_SMLEN]; char *ptr; uint32 listen_interval = LISTEN_INTERVAL; /* Default Listen Interval in Beacons */ @@ -3025,6 +3074,8 @@ dhd_preinit_ioctls(dhd_pub_t *dhd) setbit(eventmask, WLC_E_LINK); setbit(eventmask, WLC_E_NDIS_LINK); setbit(eventmask, WLC_E_MIC_ERROR); + setbit(eventmask, WLC_E_ASSOC_REQ_IE); + setbit(eventmask, WLC_E_ASSOC_RESP_IE); setbit(eventmask, WLC_E_PMKID_CACHE); setbit(eventmask, WLC_E_JOIN_START); setbit(eventmask, WLC_E_SCAN_COMPLETE); @@ -3144,26 +3195,6 @@ dhd_iovar(dhd_pub_t *pub, int ifidx, char *name, char *cmd_buf, uint cmd_len, in return ret; } -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 31)) -static struct net_device_ops dhd_ops_pri = { - .ndo_open = dhd_open, - .ndo_stop = dhd_stop, - .ndo_get_stats = dhd_get_stats, - .ndo_do_ioctl = dhd_ioctl_entry, - .ndo_start_xmit = dhd_start_xmit, - .ndo_set_mac_address = dhd_set_mac_address, - .ndo_set_multicast_list = dhd_set_multicast_list, -}; - -static struct net_device_ops dhd_ops_virt = { - .ndo_get_stats = dhd_get_stats, - .ndo_do_ioctl = dhd_ioctl_entry, - .ndo_start_xmit = dhd_start_xmit, - .ndo_set_mac_address = dhd_set_mac_address, - .ndo_set_multicast_list = dhd_set_multicast_list, -}; -#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 31)) */ - int dhd_change_mtu(dhd_pub_t *dhdp, int new_mtu, int ifidx) { struct dhd_info *dhd = dhdp->info; @@ -3267,9 +3298,13 @@ static int dhd_device_event(struct notifier_block *this, DHD_ARPOE(("%s: [%s] Up IP: 0x%x\n", __FUNCTION__, ifa->ifa_label, ifa->ifa_address)); - /* firmware not downloaded, do nothing */ - if (dhd->pub.busstate == DHD_BUS_DOWN) { - DHD_ERROR(("%s: bus is down, exit\n", __FUNCTION__)); + if (dhd->pub.busstate != DHD_BUS_DATA) { + DHD_ERROR(("%s: bus not ready, exit\n", __FUNCTION__)); + if (dhd->pend_ipaddr) { + DHD_ERROR(("%s: overwrite pending ipaddr: 0x%x\n", + __FUNCTION__, dhd->pend_ipaddr)); + } + dhd->pend_ipaddr = ifa->ifa_address; break; } @@ -3287,7 +3322,7 @@ static int dhd_device_event(struct notifier_block *this, case NETDEV_DOWN: DHD_ARPOE(("%s: [%s] Down IP: 0x%x\n", __FUNCTION__, ifa->ifa_label, ifa->ifa_address)); - + dhd->pend_ipaddr = 0; #ifdef AOE_IP_ALIAS_SUPPORT if (!(ifa->ifa_label[strlen(ifa->ifa_label)-2] == 0x3a)) { DHD_ARPOE(("%s: primary interface is down, AOE clr all\n", @@ -3361,7 +3396,8 @@ dhd_net_attach(dhd_pub_t *dhdp, int ifidx) * portable hotspot. This will not work in simultaneous AP/STA mode, * nor with P2P. Need to set the Donlge's MAC address, and then use that. */ - if (ifidx > 0) { + if (!memcmp(temp_addr, dhd->iflist[0]->mac_addr, + ETHER_ADDR_LEN)) { DHD_ERROR(("%s interface [%s]: set locally administered bit in MAC\n", __func__, net->name)); temp_addr[0] |= 0x02; @@ -3498,13 +3534,15 @@ void dhd_detach(dhd_pub_t *dhdp) dhd_if_t *ifp; /* Cleanup virtual interfaces */ - for (i = 1; i < DHD_MAX_IFS; i++) + for (i = 1; i < DHD_MAX_IFS; i++) { + dhd_net_if_lock_local(dhd); if (dhd->iflist[i]) { dhd->iflist[i]->state = DHD_IF_DEL; dhd->iflist[i]->idx = i; dhd_op_if(dhd->iflist[i]); } - + dhd_net_if_unlock_local(dhd); + } /* delete primary interface 0 */ ifp = dhd->iflist[0]; ASSERT(ifp); @@ -4540,15 +4578,6 @@ int dhd_os_check_wakelock(void *dhdp) return 0; } -int dhd_os_check_if_up(void *dhdp) -{ - dhd_pub_t *pub = (dhd_pub_t *)dhdp; - - if (!pub) - return 0; - return pub->up; -} - int net_os_wake_unlock(struct net_device *dev) { dhd_info_t *dhd = *(dhd_info_t **)netdev_priv(dev); @@ -4559,6 +4588,15 @@ int net_os_wake_unlock(struct net_device *dev) return ret; } +int dhd_os_check_if_up(void *dhdp) +{ + dhd_pub_t *pub = (dhd_pub_t *)dhdp; + + if (!pub) + return 0; + return pub->up; +} + int dhd_ioctl_entry_local(struct net_device *net, wl_ioctl_t *ioc, int cmd) { int ifidx; @@ -4598,8 +4636,8 @@ extern int dhd_wlfc_interface_entry_update(void* state, ewlfc_mac_entry_action_t uint8 iftype, uint8* ea); extern int dhd_wlfc_FIFOcreditmap_update(void* state, uint8* credits); -int dhd_wlfc_interface_event(struct dhd_info *dhd, uint8 action, uint8 ifid, uint8 iftype, - uint8* ea) +int dhd_wlfc_interface_event(struct dhd_info *dhd, + ewlfc_mac_entry_action_t action, uint8 ifid, uint8 iftype, uint8* ea) { if (dhd->pub.wlfc_state == NULL) return BCME_OK; diff --git a/drivers/net/wireless/bcmdhd/dhd_linux_mon.c b/drivers/net/wireless/bcmdhd/dhd_linux_mon.c index ce94ff9993db..d4dca2607212 100644 --- a/drivers/net/wireless/bcmdhd/dhd_linux_mon.c +++ b/drivers/net/wireless/bcmdhd/dhd_linux_mon.c @@ -2,13 +2,13 @@ * Broadcom Dongle Host Driver (DHD), Linux monitor network interface * * Copyright (C) 1999-2011, Broadcom Corporation - * + * * Unless you and Broadcom execute a separate written software license * agreement governing use of this software, this software is licensed to you * under the terms of the GNU General Public License version 2 (the "GPL"), * available at http://www.broadcom.com/licenses/GPLv2.php, with the * following added to such license: - * + * * As a special exception, the copyright holders of this software give you * permission to link this software with independent modules, and to copy and * distribute the resulting executable under terms of your choice, provided that @@ -16,12 +16,12 @@ * the license of that module. An independent module is a module which is not * derived from this software. The special exception does not apply to any * modifications of the software. - * + * * Notwithstanding the above, under no circumstances may you combine this * software in any way with any other Broadcom software provided under a license * other than the GPL, without Broadcom's express prior written consent. * - * $Id: dhd_linux_mon.c,v 1.131.2.55 2011-02-09 05:31:56 Exp $ + * $Id: dhd_linux_mon.c 297563 2011-11-20 15:38:29Z $ */ #include @@ -96,16 +96,30 @@ static const struct net_device_ops dhd_mon_if_ops = { static struct net_device* lookup_real_netdev(char *name) { int i; + int len = 0; int last_name_len = 0; struct net_device *ndev; struct net_device *ndev_found = NULL; - /* We want to find interface "p2p-eth0-0" for monitor interface "mon.p2p-eth0-0", so - * we skip "eth0" even if "mon.p2p-eth0-0" contains "eth0" + /* We need to find interface "p2p-p2p-0" corresponding to monitor interface "mon-p2p-0", + * Once mon iface name reaches IFNAMSIZ, it is reset to p2p0-0 and corresponding mon + * iface would be mon-p2p0-0. */ for (i = 0; i < DHD_MAX_IFS; i++) { ndev = dhd_idx2net(g_monitor.dhd_pub, i); - if (ndev && strstr(name, ndev->name)) { + + /* Skip "p2p" and look for "-p2p0-x" in monitor interface name. If it + * it matches, then this netdev is the corresponding real_netdev. + */ + if (ndev && strstr(ndev->name, "p2p-p2p0")) { + len = strlen("p2p"); + } else { + /* if p2p- is not present, then the IFNAMSIZ have reached and name + * would have got reset. In this casse,look for p2p0-x in mon-p2p0-x + */ + len = 0; + } + if (ndev && strstr(name, (ndev->name + len))) { if (strlen(ndev->name) > last_name_len) { ndev_found = ndev; last_name_len = strlen(ndev->name); diff --git a/drivers/net/wireless/bcmdhd/dhd_sdio.c b/drivers/net/wireless/bcmdhd/dhd_sdio.c index e5ffc4f44e17..404a649a9f41 100644 --- a/drivers/net/wireless/bcmdhd/dhd_sdio.c +++ b/drivers/net/wireless/bcmdhd/dhd_sdio.c @@ -21,7 +21,7 @@ * software in any way with any other Broadcom software provided under a license * other than the GPL, without Broadcom's express prior written consent. * - * $Id: dhd_sdio.c 288105 2011-10-06 01:58:02Z $ + * $Id: dhd_sdio.c 301794 2011-12-08 20:41:35Z $ */ #include @@ -1366,9 +1366,7 @@ dhd_bus_txctl(struct dhd_bus *bus, uchar *msg, uint msglen) /* Send from dpc */ bus->ctrl_frame_buf = frame; bus->ctrl_frame_len = len; - dhd_wait_for_event(bus->dhd, &bus->ctrl_frame_stat); - if (bus->ctrl_frame_stat == FALSE) { DHD_INFO(("%s: ctrl_frame_stat == FALSE\n", __FUNCTION__)); ret = 0; @@ -3565,7 +3563,7 @@ dhdsdio_rxglom(dhd_bus_t *bus, uint8 rxseq) if ((uint8)(txmax - bus->tx_seq) > 0x40) { DHD_ERROR(("%s: got unlikely tx max %d with tx_seq %d\n", __FUNCTION__, txmax, bus->tx_seq)); - txmax = bus->tx_seq; + txmax = bus->tx_max; } bus->tx_max = txmax; @@ -3766,6 +3764,14 @@ dhdsdio_readframes(dhd_bus_t *bus, uint maxframes, bool *finished) !bus->rxskip && rxleft && bus->dhd->busstate != DHD_BUS_DOWN; rxseq++, rxleft--) { +#ifdef DHDTHREAD + /* tx more to improve rx performance */ + if ((bus->clkstate == CLK_AVAIL) && !bus->fcstate && + pktq_mlen(&bus->txq, ~bus->flowcontrol) && DATAOK(bus)) { + dhdsdio_sendfromq(bus, dhd_txbound); + } +#endif /* DHDTHREAD */ + /* Handle glomming separately */ if (bus->glom || bus->glomd) { uint8 cnt; @@ -3986,7 +3992,7 @@ dhdsdio_readframes(dhd_bus_t *bus, uint maxframes, bool *finished) if ((uint8)(txmax - bus->tx_seq) > 0x40) { DHD_ERROR(("%s: got unlikely tx max %d with tx_seq %d\n", __FUNCTION__, txmax, bus->tx_seq)); - txmax = bus->tx_seq; + txmax = bus->tx_max; } bus->tx_max = txmax; @@ -4143,7 +4149,7 @@ dhdsdio_readframes(dhd_bus_t *bus, uint maxframes, bool *finished) if ((uint8)(txmax - bus->tx_seq) > 0x40) { DHD_ERROR(("%s: got unlikely tx max %d with tx_seq %d\n", __FUNCTION__, txmax, bus->tx_seq)); - txmax = bus->tx_seq; + txmax = bus->tx_max; } bus->tx_max = txmax; @@ -5183,16 +5189,8 @@ dhdsdio_chipmatch(uint16 chipid) return TRUE; if (chipid == BCM4319_CHIP_ID) return TRUE; - if (chipid == BCM4336_CHIP_ID) - return TRUE; if (chipid == BCM4330_CHIP_ID) return TRUE; - if (chipid == BCM43237_CHIP_ID) - return TRUE; - if (chipid == BCM43362_CHIP_ID) - return TRUE; - if (chipid == BCM43239_CHIP_ID) - return TRUE; return FALSE; } @@ -5369,6 +5367,7 @@ dhdsdio_probe(uint16 venid, uint16 devid, uint16 bus_no, uint16 slot, if (ret == BCME_NOTUP) goto fail; } + /* Ok, have the per-port tell the stack we're open for business */ if (dhd_net_attach(bus->dhd, 0) != 0) { DHD_ERROR(("%s: Net attach failed!!\n", __FUNCTION__)); diff --git a/drivers/net/wireless/bcmdhd/dhd_wlfc.h b/drivers/net/wireless/bcmdhd/dhd_wlfc.h index 59d018b64c6f..c4d251806d78 100644 --- a/drivers/net/wireless/bcmdhd/dhd_wlfc.h +++ b/drivers/net/wireless/bcmdhd/dhd_wlfc.h @@ -18,7 +18,7 @@ * Notwithstanding the above, under no circumstances may you combine this * software in any way with any other Broadcom software provided under a license * other than the GPL, without Broadcom's express prior written consent. -* $Id: dhd_wlfc.h,v 1.1.8.1 2010-09-09 22:41:08 Exp $ +* $Id: dhd_wlfc.h 286994 2011-09-29 21:27:44Z $ * */ #ifndef __wlfc_host_driver_definitions_h__ @@ -201,6 +201,7 @@ typedef struct athost_wl_stat_counters { #define WLFC_FCMODE_IMPLIED_CREDIT 1 #define WLFC_FCMODE_EXPLICIT_CREDIT 2 +/* How long to defer borrowing in milliseconds */ #define WLFC_BORROW_DEFER_PERIOD_MS 100 /* Mask to represent available ACs (note: BC/MC is ignored */ @@ -261,6 +262,15 @@ typedef struct athost_wl_status_info { /* Timestamp to compute how long to defer borrowing for */ uint32 borrow_defer_timestamp; + } athost_wl_status_info_t; +int dhd_wlfc_enable(dhd_pub_t *dhd); +int dhd_wlfc_interface_event(struct dhd_info *, + ewlfc_mac_entry_action_t action, uint8 ifid, uint8 iftype, uint8* ea); +int dhd_wlfc_FIFOcreditmap_event(struct dhd_info *dhd, uint8* event_data); +int dhd_wlfc_event(struct dhd_info *dhd); +int dhd_os_wlfc_block(dhd_pub_t *pub); +int dhd_os_wlfc_unblock(dhd_pub_t *pub); + #endif /* __wlfc_host_driver_definitions_h__ */ diff --git a/drivers/net/wireless/bcmdhd/hndpmu.c b/drivers/net/wireless/bcmdhd/hndpmu.c index b9586e40d0c2..111b5be9cbf9 100644 --- a/drivers/net/wireless/bcmdhd/hndpmu.c +++ b/drivers/net/wireless/bcmdhd/hndpmu.c @@ -22,7 +22,7 @@ * software in any way with any other Broadcom software provided under a license * other than the GPL, without Broadcom's express prior written consent. * - * $Id: hndpmu.c,v 1.228.2.56 2011-02-11 22:49:07 Exp $ + * $Id: hndpmu.c,v 1.228.2.56 2011-02-11 22:49:07 $ */ #include @@ -93,26 +93,8 @@ static const sdiod_drive_str_t sdiod_drive_strength_tab4_1v8[] = { {0, 0x1} }; /* SDIO Drive Strength to sel value table for PMU Rev 11 (1.2v) */ -static const sdiod_drive_str_t sdiod_drive_strength_tab4_1v2[] = { - {16, 0x3}, - {13, 0x2}, - {11, 0x1}, - {8, 0x0}, - {6, 0x7}, - {4, 0x6}, - {2, 0x5}, - {0, 0x4} }; /* SDIO Drive Strength to sel value table for PMU Rev 11 (2.5v) */ -static const sdiod_drive_str_t sdiod_drive_strength_tab4_2v5[] = { - {80, 0x5}, - {65, 0x4}, - {55, 0x7}, - {40, 0x6}, - {30, 0x1}, - {20, 0x0}, - {10, 0x3}, - {0, 0x2} }; /* SDIO Drive Strength to sel value table for PMU Rev 13 (1.8v) */ static const sdiod_drive_str_t sdiod_drive_strength_tab5_1v8[] = { @@ -125,14 +107,6 @@ static const sdiod_drive_str_t sdiod_drive_strength_tab5_1v8[] = { {0, 0x0} }; /* SDIO Drive Strength to sel value table for PMU Rev 13 (3.3v) */ -static const sdiod_drive_str_t sdiod_drive_strength_tab5_3v3[] = { - {12, 0x7}, - {10, 0x6}, - {8, 0x5}, - {6, 0x4}, - {4, 0x2}, - {2, 0x1}, - {0, 0x0} }; #define SDIOD_DRVSTR_KEY(chip, pmu) (((chip) << 16) | (pmu)) @@ -166,27 +140,11 @@ si_sdiod_drive_strength_init(si_t *sih, osl_t *osh, uint32 drivestrength) str_mask = 0x00003800; str_shift = 11; break; - case SDIOD_DRVSTR_KEY(BCM4336_CHIP_ID, 8): - case SDIOD_DRVSTR_KEY(BCM4336_CHIP_ID, 11): - if (sih->pmurev == 8) { - str_tab = (sdiod_drive_str_t *)&sdiod_drive_strength_tab3; - } - else if (sih->pmurev == 11) { - str_tab = (sdiod_drive_str_t *)&sdiod_drive_strength_tab4_1v8; - } - str_mask = 0x00003800; - str_shift = 11; - break; case SDIOD_DRVSTR_KEY(BCM4330_CHIP_ID, 12): str_tab = (sdiod_drive_str_t *)&sdiod_drive_strength_tab4_1v8; str_mask = 0x00003800; str_shift = 11; break; - case SDIOD_DRVSTR_KEY(BCM43362_CHIP_ID, 13): - str_tab = (sdiod_drive_str_t *)&sdiod_drive_strength_tab5_1v8; - str_mask = 0x00003800; - str_shift = 11; - break; default: PMU_MSG(("No SDIO Drive strength init done for chip %s rev %d pmurev %d\n", bcm_chipname(sih->chip, chn, 8), sih->chiprev, sih->pmurev)); diff --git a/drivers/net/wireless/bcmdhd/include/Makefile b/drivers/net/wireless/bcmdhd/include/Makefile index c07266fd6fdc..67c4906f5889 100644 --- a/drivers/net/wireless/bcmdhd/include/Makefile +++ b/drivers/net/wireless/bcmdhd/include/Makefile @@ -10,7 +10,7 @@ # # Copyright 2005, Broadcom, Inc. # -# $Id: Makefile 241702 2011-02-19 00:41:03Z automrgr $ +# $Id: Makefile 241702 2011-02-19 00:41:03Z $ # SRCBASE := .. diff --git a/drivers/net/wireless/bcmdhd/include/aidmp.h b/drivers/net/wireless/bcmdhd/include/aidmp.h index 375df443a29a..b993a033abc2 100644 --- a/drivers/net/wireless/bcmdhd/include/aidmp.h +++ b/drivers/net/wireless/bcmdhd/include/aidmp.h @@ -21,7 +21,7 @@ * software in any way with any other Broadcom software provided under a license * other than the GPL, without Broadcom's express prior written consent. * - * $Id: aidmp.h,v 13.4.14.1 2010-03-09 18:40:06 Exp $ + * $Id: aidmp.h 277737 2011-08-16 17:54:59Z $ */ diff --git a/drivers/net/wireless/bcmdhd/include/bcmcdc.h b/drivers/net/wireless/bcmdhd/include/bcmcdc.h index ce45c50d9641..77a20f87b7ea 100644 --- a/drivers/net/wireless/bcmdhd/include/bcmcdc.h +++ b/drivers/net/wireless/bcmdhd/include/bcmcdc.h @@ -24,7 +24,7 @@ * software in any way with any other Broadcom software provided under a license * other than the GPL, without Broadcom's express prior written consent. * - * $Id: bcmcdc.h,v 13.25.10.3 2010-12-22 23:47:26 Exp $ + * $Id: bcmcdc.h 277737 2011-08-16 17:54:59Z $ */ #ifndef _bcmcdc_h_ diff --git a/drivers/net/wireless/bcmdhd/include/bcmdefs.h b/drivers/net/wireless/bcmdhd/include/bcmdefs.h index da1fd5e4eac4..17cc0e955f62 100644 --- a/drivers/net/wireless/bcmdhd/include/bcmdefs.h +++ b/drivers/net/wireless/bcmdhd/include/bcmdefs.h @@ -21,7 +21,7 @@ * software in any way with any other Broadcom software provided under a license * other than the GPL, without Broadcom's express prior written consent. * - * $Id: bcmdefs.h,v 13.68.2.8 2011-01-08 04:04:19 Exp $ + * $Id: bcmdefs.h 279282 2011-08-23 22:44:02Z $ */ @@ -30,12 +30,26 @@ + +#define BCM_REFERENCE(data) ((void)(data)) + + + #define bcmreclaimed 0 #define _data _data #define _fn _fn +#define BCMPREATTACHDATA(_data) _data +#define BCMPREATTACHFN(_fn) _fn #define _data _data #define _fn _fn #define _fn _fn +#define BCMNMIATTACHFN(_fn) _fn +#define BCMNMIATTACHDATA(_data) _data +#define BCMOVERLAY0DATA(_sym) _sym +#define BCMOVERLAY0FN(_fn) _fn +#define BCMOVERLAY1DATA(_sym) _sym +#define BCMOVERLAY1FN(_fn) _fn +#define BCMOVERLAYERRFN(_fn) _fn #define CONST const #define BCMFASTPATH @@ -43,9 +57,30 @@ #define _data _data +#define BCMROMDAT_NAME(_data) _data #define _fn _fn #define _fn _fn #define STATIC static +#define BCMROMDAT_ARYSIZ(data) ARRAYSIZE(data) +#define BCMROMDAT_SIZEOF(data) sizeof(data) +#define BCMROMDAT_APATCH(data) +#define BCMROMDAT_SPATCH(data) + + + +#define OVERLAY_INLINE +#define OSTATIC static +#define BCMOVERLAYDATA(_ovly, _sym) _sym +#define BCMOVERLAYFN(_ovly, _fn) _fn +#define BCMOVERLAYERRFN(_fn) _fn +#define BCMROMOVERLAYDATA(_ovly, _data) _data +#define BCMROMOVERLAYFN(_ovly, _fn) _fn +#define BCMATTACHOVERLAYDATA(_ovly, _sym) _sym +#define BCMATTACHOVERLAYFN(_ovly, _fn) _fn +#define BCMINITOVERLAYDATA(_ovly, _sym) _sym +#define BCMINITOVERLAYFN(_ovly, _fn) _fn +#define BCMUNINITOVERLAYFN(_ovly, _fn) _fn + #define SI_BUS 0 diff --git a/drivers/net/wireless/bcmdhd/include/bcmdevs.h b/drivers/net/wireless/bcmdhd/include/bcmdevs.h index 4f707c0c6920..f0542f2ac11b 100644 --- a/drivers/net/wireless/bcmdhd/include/bcmdevs.h +++ b/drivers/net/wireless/bcmdhd/include/bcmdevs.h @@ -21,7 +21,7 @@ * software in any way with any other Broadcom software provided under a license * other than the GPL, without Broadcom's express prior written consent. * - * $Id: bcmdevs.h,v 13.285.2.39 2011-02-04 05:03:16 Exp $ + * $Id: bcmdevs.h 295140 2011-11-09 17:22:01Z $ */ @@ -31,7 +31,16 @@ #define VENDOR_EPIGRAM 0xfeda #define VENDOR_BROADCOM 0x14e4 +#define VENDOR_3COM 0x10b7 +#define VENDOR_NETGEAR 0x1385 +#define VENDOR_DIAMOND 0x1092 +#define VENDOR_INTEL 0x8086 +#define VENDOR_DELL 0x1028 +#define VENDOR_HP 0x103c +#define VENDOR_HP_COMPAQ 0x0e11 +#define VENDOR_APPLE 0x106b #define VENDOR_SI_IMAGE 0x1095 +#define VENDOR_BUFFALO 0x1154 #define VENDOR_TI 0x104c #define VENDOR_RICOH 0x1180 #define VENDOR_JMICRON 0x197b @@ -48,15 +57,41 @@ #define BCM_DNGL_BL_PID_4328 0xbd12 #define BCM_DNGL_BL_PID_4322 0xbd13 #define BCM_DNGL_BL_PID_4319 0xbd16 -#define BCM_DNGL_BL_PID_43236 0xbd17 #define BCM_DNGL_BL_PID_4332 0xbd18 #define BCM_DNGL_BL_PID_4330 0xbd19 -#define BCM_DNGL_BL_PID_43239 0xbd1b #define BCM_DNGL_BDC_PID 0x0bdc #define BCM_DNGL_JTAG_PID 0x4a44 + + +#define BCM_HWUSB_PID_43239 43239 + + +#define BCM4210_DEVICE_ID 0x1072 +#define BCM4230_DEVICE_ID 0x1086 +#define BCM4401_ENET_ID 0x170c +#define BCM3352_DEVICE_ID 0x3352 +#define BCM3360_DEVICE_ID 0x3360 +#define BCM4211_DEVICE_ID 0x4211 +#define BCM4231_DEVICE_ID 0x4231 +#define BCM4303_D11B_ID 0x4303 +#define BCM4311_D11G_ID 0x4311 +#define BCM4311_D11DUAL_ID 0x4312 +#define BCM4311_D11A_ID 0x4313 +#define BCM4328_D11DUAL_ID 0x4314 +#define BCM4328_D11G_ID 0x4315 +#define BCM4328_D11A_ID 0x4316 +#define BCM4318_D11G_ID 0x4318 +#define BCM4318_D11DUAL_ID 0x4319 +#define BCM4318_D11A_ID 0x431a #define BCM4325_D11DUAL_ID 0x431b #define BCM4325_D11G_ID 0x431c #define BCM4325_D11A_ID 0x431d +#define BCM4306_D11G_ID 0x4320 +#define BCM4306_D11A_ID 0x4321 +#define BCM4306_UART_ID 0x4322 +#define BCM4306_V90_ID 0x4323 +#define BCM4306_D11DUAL_ID 0x4324 +#define BCM4306_D11G_ID2 0x4325 #define BCM4321_D11N_ID 0x4328 #define BCM4321_D11N2G_ID 0x4329 #define BCM4321_D11N5G_ID 0x432a @@ -98,17 +133,58 @@ #define BCM43237_D11N5G_ID 0x4356 #define BCM43227_D11N2G_ID 0x4358 #define BCM43228_D11N_ID 0x4359 -#define BCM43228_D11N5G_ID 0x435a +#define BCM43228_D11N5G_ID 0x435a #define BCM43362_D11N_ID 0x4363 #define BCM43239_D11N_ID 0x4370 +#define BCM4324_D11N_ID 0x4374 +#define BCM43217_D11N2G_ID 0x43a9 +#define BCM43131_D11N2G_ID 0x43aa +#define BCM4314_D11N2G_ID 0x4364 +#define BCM43142_D11N2G_ID 0x4365 +#define BCMGPRS_UART_ID 0x4333 +#define BCMGPRS2_UART_ID 0x4344 +#define FPGA_JTAGM_ID 0x43f0 +#define BCM_JTAGM_ID 0x43f1 #define SDIOH_FPGA_ID 0x43f2 +#define BCM_SDIOH_ID 0x43f3 +#define SDIOD_FPGA_ID 0x43f4 #define SPIH_FPGA_ID 0x43f5 +#define BCM_SPIH_ID 0x43f6 +#define MIMO_FPGA_ID 0x43f8 +#define BCM_JTAGM2_ID 0x43f9 +#define SDHCI_FPGA_ID 0x43fa +#define BCM4402_ENET_ID 0x4402 +#define BCM4402_V90_ID 0x4403 +#define BCM4410_DEVICE_ID 0x4410 +#define BCM4412_DEVICE_ID 0x4412 +#define BCM4430_DEVICE_ID 0x4430 +#define BCM4432_DEVICE_ID 0x4432 +#define BCM4704_ENET_ID 0x4706 #define BCM4710_DEVICE_ID 0x4710 +#define BCM47XX_AUDIO_ID 0x4711 +#define BCM47XX_V90_ID 0x4712 +#define BCM47XX_ENET_ID 0x4713 +#define BCM47XX_EXT_ID 0x4714 +#define BCM47XX_GMAC_ID 0x4715 +#define BCM47XX_USBH_ID 0x4716 +#define BCM47XX_USBD_ID 0x4717 +#define BCM47XX_IPSEC_ID 0x4718 +#define BCM47XX_ROBO_ID 0x4719 +#define BCM47XX_USB20H_ID 0x471a +#define BCM47XX_USB20D_ID 0x471b +#define BCM47XX_ATA100_ID 0x471d +#define BCM47XX_SATAXOR_ID 0x471e +#define BCM47XX_GIGETH_ID 0x471f +#define BCM4712_MIPS_ID 0x4720 +#define BCM4716_DEVICE_ID 0x4722 +#define BCM47XX_SMBUS_EMU_ID 0x47fe +#define BCM47XX_XOR_EMU_ID 0x47ff +#define EPI41210_DEVICE_ID 0xa0fa +#define EPI41230_DEVICE_ID 0xa10e +#define JINVANI_SDIOH_ID 0x4743 #define BCM27XX_SDIOH_ID 0x2702 -#define PCIXX21_FLASHMEDIA0_ID 0x8033 -#define PCIXX21_SDIOH0_ID 0x8034 #define PCIXX21_FLASHMEDIA_ID 0x803b #define PCIXX21_SDIOH_ID 0x803c #define R5C822_SDIOH_ID 0x0822 @@ -121,11 +197,13 @@ #define BCM43112_CHIP_ID 43112 #define BCM4312_CHIP_ID 0x4312 #define BCM4313_CHIP_ID 0x4313 +#define BCM43131_CHIP_ID 43131 #define BCM4315_CHIP_ID 0x4315 #define BCM4318_CHIP_ID 0x4318 #define BCM4319_CHIP_ID 0x4319 #define BCM4320_CHIP_ID 0x4320 #define BCM4321_CHIP_ID 0x4321 +#define BCM43217_CHIP_ID 43217 #define BCM4322_CHIP_ID 0x4322 #define BCM43221_CHIP_ID 43221 #define BCM43222_CHIP_ID 43222 @@ -152,15 +230,28 @@ #define BCM4336_CHIP_ID 0x4336 #define BCM43362_CHIP_ID 43362 #define BCM4330_CHIP_ID 0x4330 +#define BCM6362_CHIP_ID 0x6362 +#define BCM4314_CHIP_ID 0x4314 +#define BCM43142_CHIP_ID 43142 +#define BCM4324_CHIP_ID 0x4324 + +#define BCM4342_CHIP_ID 4342 #define BCM4402_CHIP_ID 0x4402 #define BCM4704_CHIP_ID 0x4704 #define BCM4710_CHIP_ID 0x4710 #define BCM4712_CHIP_ID 0x4712 +#define BCM4716_CHIP_ID 0x4716 +#define BCM47162_CHIP_ID 47162 +#define BCM4748_CHIP_ID 0x4748 +#define BCM4749_CHIP_ID 0x4749 #define BCM4785_CHIP_ID 0x4785 #define BCM5350_CHIP_ID 0x5350 #define BCM5352_CHIP_ID 0x5352 #define BCM5354_CHIP_ID 0x5354 #define BCM5365_CHIP_ID 0x5365 +#define BCM5356_CHIP_ID 0x5356 +#define BCM5357_CHIP_ID 0x5357 +#define BCM53572_CHIP_ID 53572 #define BCM4303_PKG_ID 2 @@ -175,8 +266,478 @@ #define BCM4329_289PIN_PKG_ID 0 #define BCM4329_182PIN_PKG_ID 1 #define BCM5354E_PKG_ID 1 +#define BCM4716_PKG_ID 8 +#define BCM4717_PKG_ID 9 +#define BCM4718_PKG_ID 10 +#define BCM5356_PKG_NONMODE 1 +#define BCM5358U_PKG_ID 8 +#define BCM5358_PKG_ID 9 +#define BCM47186_PKG_ID 10 +#define BCM5357_PKG_ID 11 +#define BCM5356U_PKG_ID 12 +#define BCM53572_PKG_ID 8 +#define BCM47188_PKG_ID 9 +#define BCM4331TT_PKG_ID 8 +#define BCM4331TN_PKG_ID 9 +#define BCM4331TNA0_PKG_ID 0xb + + #define HDLSIM5350_PKG_ID 1 #define HDLSIM_PKG_ID 14 #define HWSIM_PKG_ID 15 +#define BCM43224_FAB_CSM 0x8 +#define BCM43224_FAB_SMIC 0xa +#define BCM4336_WLBGA_PKG_ID 0x8 +#define BCM4330_WLBGA_PKG_ID 0x0 +#define BCM4314PCIE_ARM_PKG_ID (8 | 0) +#define BCM4314SDIO_PKG_ID (8 | 1) +#define BCM4314PCIE_PKG_ID (8 | 2) +#define BCM4314SDIO_ARM_PKG_ID (8 | 3) +#define BCM4314SDIO_FPBGA_PKG_ID (8 | 4) +#define BCM4314DEV_PKG_ID (8 | 6) + +#define PCIXX21_FLASHMEDIA0_ID 0x8033 +#define PCIXX21_SDIOH0_ID 0x8034 + + +#define BFL_BTC2WIRE 0x00000001 +#define BFL_BTCOEX 0x00000001 +#define BFL_PACTRL 0x00000002 +#define BFL_AIRLINEMODE 0x00000004 +#define BFL_ADCDIV 0x00000008 +#define BFL_ENETROBO 0x00000010 +#define BFL_NOPLLDOWN 0x00000020 +#define BFL_CCKHIPWR 0x00000040 +#define BFL_ENETADM 0x00000080 +#define BFL_ENETVLAN 0x00000100 +#ifdef WLAFTERBURNER +#define BFL_AFTERBURNER 0x00000200 +#endif +#define BFL_NOPCI 0x00000400 +#define BFL_FEM 0x00000800 +#define BFL_EXTLNA 0x00001000 +#define BFL_HGPA 0x00002000 +#define BFL_BTC2WIRE_ALTGPIO 0x00004000 +#define BFL_ALTIQ 0x00008000 +#define BFL_NOPA 0x00010000 +#define BFL_RSSIINV 0x00020000 +#define BFL_PAREF 0x00040000 +#define BFL_3TSWITCH 0x00080000 +#define BFL_PHASESHIFT 0x00100000 +#define BFL_BUCKBOOST 0x00200000 +#define BFL_FEM_BT 0x00400000 +#define BFL_NOCBUCK 0x00800000 +#define BFL_CCKFAVOREVM 0x01000000 +#define BFL_PALDO 0x02000000 +#define BFL_LNLDO2_2P5 0x04000000 +#define BFL_FASTPWR 0x08000000 +#define BFL_UCPWRCTL_MININDX 0x08000000 +#define BFL_EXTLNA_5GHz 0x10000000 +#define BFL_TRSW_1by2 0x20000000 +#define BFL_LO_TRSW_R_5GHz 0x40000000 +#define BFL_ELNA_GAINDEF 0x80000000 +#define BFL_EXTLNA_TX 0x20000000 + + +#define BFL2_RXBB_INT_REG_DIS 0x00000001 +#define BFL2_APLL_WAR 0x00000002 +#define BFL2_TXPWRCTRL_EN 0x00000004 +#define BFL2_2X4_DIV 0x00000008 +#define BFL2_5G_PWRGAIN 0x00000010 +#define BFL2_PCIEWAR_OVR 0x00000020 +#define BFL2_CAESERS_BRD 0x00000040 +#define BFL2_BTC3WIRE 0x00000080 +#define BFL2_BTCLEGACY 0x00000080 +#define BFL2_SKWRKFEM_BRD 0x00000100 +#define BFL2_SPUR_WAR 0x00000200 +#define BFL2_GPLL_WAR 0x00000400 +#define BFL2_TRISTATE_LED 0x00000800 +#define BFL2_SINGLEANT_CCK 0x00001000 +#define BFL2_2G_SPUR_WAR 0x00002000 +#define BFL2_BPHY_ALL_TXCORES 0x00004000 +#define BFL2_FCC_BANDEDGE_WAR 0x00008000 +#define BFL2_GPLL_WAR2 0x00010000 +#define BFL2_IPALVLSHIFT_3P3 0x00020000 +#define BFL2_INTERNDET_TXIQCAL 0x00040000 +#define BFL2_XTALBUFOUTEN 0x00080000 +#define BFL2_ANAPACTRL_2G 0x00100000 +#define BFL2_ANAPACTRL_5G 0x00200000 +#define BFL2_ELNACTRL_TRSW_2G 0x00400000 +#define BFL2_BT_SHARE_ANT0 0x00800000 +#define BFL2_TEMPSENSE_HIGHER 0x01000000 +#define BFL2_BTC3WIREONLY 0x02000000 +#define BFL2_PWR_NOMINAL 0x04000000 +#define BFL2_EXTLNA_TX 0x08000000 + +#define BFL2_4313_RADIOREG 0x10000000 + + + +#define BOARD_GPIO_BTC3W_IN 0x850 +#define BOARD_GPIO_BTC3W_OUT 0x020 +#define BOARD_GPIO_BTCMOD_IN 0x010 +#define BOARD_GPIO_BTCMOD_OUT 0x020 +#define BOARD_GPIO_BTC_IN 0x080 +#define BOARD_GPIO_BTC_OUT 0x100 +#define BOARD_GPIO_PACTRL 0x200 +#define BOARD_GPIO_12 0x1000 +#define BOARD_GPIO_13 0x2000 +#define BOARD_GPIO_BTC4_IN 0x0800 +#define BOARD_GPIO_BTC4_BT 0x2000 +#define BOARD_GPIO_BTC4_STAT 0x4000 +#define BOARD_GPIO_BTC4_WLAN 0x8000 +#define BOARD_GPIO_1_WLAN_PWR 0x2 +#define BOARD_GPIO_4_WLAN_PWR 0x10 + +#define GPIO_BTC4W_OUT_4312 0x010 +#define GPIO_BTC4W_OUT_43224 0x020 +#define GPIO_BTC4W_OUT_43224_SHARED 0x0e0 +#define GPIO_BTC4W_OUT_43225 0x0e0 +#define GPIO_BTC4W_OUT_43421 0x020 +#define GPIO_BTC4W_OUT_4313 0x060 + +#define PCI_CFG_GPIO_SCS 0x10 +#define PCI_CFG_GPIO_HWRAD 0x20 +#define PCI_CFG_GPIO_XTAL 0x40 +#define PCI_CFG_GPIO_PLL 0x80 + + +#define PLL_DELAY 150 +#define FREF_DELAY 200 +#define MIN_SLOW_CLK 32 +#define XTAL_ON_DELAY 1000 + + +#define BU4710_BOARD 0x0400 +#define VSIM4710_BOARD 0x0401 +#define QT4710_BOARD 0x0402 + +#define BU4309_BOARD 0x040a +#define BCM94309CB_BOARD 0x040b +#define BCM94309MP_BOARD 0x040c +#define BCM4309AP_BOARD 0x040d + +#define BCM94302MP_BOARD 0x040e + +#define BU4306_BOARD 0x0416 +#define BCM94306CB_BOARD 0x0417 +#define BCM94306MP_BOARD 0x0418 + +#define BCM94710D_BOARD 0x041a +#define BCM94710R1_BOARD 0x041b +#define BCM94710R4_BOARD 0x041c +#define BCM94710AP_BOARD 0x041d + +#define BU2050_BOARD 0x041f + +#define BCM94306P50_BOARD 0x0420 + +#define BCM94309G_BOARD 0x0421 + +#define BU4704_BOARD 0x0423 +#define BU4702_BOARD 0x0424 + +#define BCM94306PC_BOARD 0x0425 + +#define MPSG4306_BOARD 0x0427 + +#define BCM94702MN_BOARD 0x0428 + + +#define BCM94702CPCI_BOARD 0x0429 + + +#define BCM95380RR_BOARD 0x042a + + +#define BCM94306CBSG_BOARD 0x042b + + +#define PCSG94306_BOARD 0x042d + + +#define BU4704SD_BOARD 0x042e + + +#define BCM94704AGR_BOARD 0x042f + + +#define BCM94308MP_BOARD 0x0430 + + +#define BCM94306GPRS_BOARD 0x0432 + + +#define BU5365_FPGA_BOARD 0x0433 + +#define BU4712_BOARD 0x0444 +#define BU4712SD_BOARD 0x045d +#define BU4712L_BOARD 0x045f + + +#define BCM94712AP_BOARD 0x0445 +#define BCM94712P_BOARD 0x0446 + + +#define BU4318_BOARD 0x0447 +#define CB4318_BOARD 0x0448 +#define MPG4318_BOARD 0x0449 +#define MP4318_BOARD 0x044a +#define SD4318_BOARD 0x044b + + +#define BCM94313BU_BOARD 0x050f +#define BCM94313HM_BOARD 0x0510 +#define BCM94313EPA_BOARD 0x0511 +#define BCM94313HMG_BOARD 0x051C + + +#define BCM96338_BOARD 0x6338 +#define BCM96348_BOARD 0x6348 +#define BCM96358_BOARD 0x6358 +#define BCM96368_BOARD 0x6368 + + +#define BCM94306P_BOARD 0x044c + + +#define BCM94303MP_BOARD 0x044e + + +#define BCM94306MPSGH_BOARD 0x044f + + +#define BCM94306MPM 0x0450 +#define BCM94306MPL 0x0453 + + +#define BCM94712AGR_BOARD 0x0451 + + +#define PC4303_BOARD 0x0454 + + +#define BCM95350K_BOARD 0x0455 + + +#define BCM95350R_BOARD 0x0456 + + +#define BCM94306MPLNA_BOARD 0x0457 + + +#define BU4320_BOARD 0x0458 +#define BU4320S_BOARD 0x0459 +#define BCM94320PH_BOARD 0x045a + + +#define BCM94306MPH_BOARD 0x045b + + +#define BCM94306PCIV_BOARD 0x045c + +#define BU4712SD_BOARD 0x045d + +#define BCM94320PFLSH_BOARD 0x045e + +#define BU4712L_BOARD 0x045f +#define BCM94712LGR_BOARD 0x0460 +#define BCM94320R_BOARD 0x0461 + +#define BU5352_BOARD 0x0462 + +#define BCM94318MPGH_BOARD 0x0463 + +#define BU4311_BOARD 0x0464 +#define BCM94311MC_BOARD 0x0465 +#define BCM94311MCAG_BOARD 0x0466 + +#define BCM95352GR_BOARD 0x0467 + + +#define BCM95351AGR_BOARD 0x0470 + + +#define BCM94704MPCB_BOARD 0x0472 + + +#define BU4785_BOARD 0x0478 + + +#define BU4321_BOARD 0x046b +#define BU4321E_BOARD 0x047c +#define MP4321_BOARD 0x046c +#define CB2_4321_BOARD 0x046d +#define CB2_4321_AG_BOARD 0x0066 +#define MC4321_BOARD 0x046e + + +#define BU4328_BOARD 0x0481 +#define BCM4328SDG_BOARD 0x0482 +#define BCM4328SDAG_BOARD 0x0483 +#define BCM4328UG_BOARD 0x0484 +#define BCM4328UAG_BOARD 0x0485 +#define BCM4328PC_BOARD 0x0486 +#define BCM4328CF_BOARD 0x0487 + + +#define BCM94325DEVBU_BOARD 0x0490 +#define BCM94325BGABU_BOARD 0x0491 + +#define BCM94325SDGWB_BOARD 0x0492 + +#define BCM94325SDGMDL_BOARD 0x04aa +#define BCM94325SDGMDL2_BOARD 0x04c6 +#define BCM94325SDGMDL3_BOARD 0x04c9 + +#define BCM94325SDABGWBA_BOARD 0x04e1 + + +#define BCM94322MC_SSID 0x04a4 +#define BCM94322USB_SSID 0x04a8 +#define BCM94322HM_SSID 0x04b0 +#define BCM94322USB2D_SSID 0x04bf + + +#define BCM4312MCGSG_BOARD 0x04b5 + + +#define BCM94315DEVBU_SSID 0x04c2 +#define BCM94315USBGP_SSID 0x04c7 +#define BCM94315BGABU_SSID 0x04ca +#define BCM94315USBGP41_SSID 0x04cb + + +#define BCM94319DEVBU_SSID 0X04e5 +#define BCM94319USB_SSID 0X04e6 +#define BCM94319SD_SSID 0X04e7 + + +#define BCM94716NR2_SSID 0x04cd + + +#define BCM94319DEVBU_SSID 0X04e5 +#define BCM94319USBNP4L_SSID 0X04e6 +#define BCM94319WLUSBN4L_SSID 0X04e7 +#define BCM94319SDG_SSID 0X04ea +#define BCM94319LCUSBSDN4L_SSID 0X04eb +#define BCM94319USBB_SSID 0x04ee +#define BCM94319LCSDN4L_SSID 0X0507 +#define BCM94319LSUSBN4L_SSID 0X0508 +#define BCM94319SDNA4L_SSID 0X0517 +#define BCM94319SDELNA4L_SSID 0X0518 +#define BCM94319SDELNA6L_SSID 0X0539 +#define BCM94319ARCADYAN_SSID 0X0546 +#define BCM94319WINDSOR_SSID 0x0561 +#define BCM94319MLAP_SSID 0x0562 +#define BCM94319SDNA_SSID 0x058b +#define BCM94319BHEMU3_SSID 0x0563 +#define BCM94319SDHMB_SSID 0x058c +#define BCM94319SDBREF_SSID 0x05a1 +#define BCM94319USBSDB_SSID 0x05a2 + + + +#define BCM94329AGB_SSID 0X04b9 +#define BCM94329TDKMDL1_SSID 0X04ba +#define BCM94329TDKMDL11_SSID 0X04fc +#define BCM94329OLYMPICN18_SSID 0X04fd +#define BCM94329OLYMPICN90_SSID 0X04fe +#define BCM94329OLYMPICN90U_SSID 0X050c +#define BCM94329OLYMPICN90M_SSID 0X050b +#define BCM94329AGBF_SSID 0X04ff +#define BCM94329OLYMPICX17_SSID 0X0504 +#define BCM94329OLYMPICX17M_SSID 0X050a +#define BCM94329OLYMPICX17U_SSID 0X0509 +#define BCM94329OLYMPICUNO_SSID 0X0564 +#define BCM94329MOTOROLA_SSID 0X0565 +#define BCM94329OLYMPICLOCO_SSID 0X0568 + +#define BCM94336SD_WLBGABU_SSID 0x0511 +#define BCM94336SD_WLBGAREF_SSID 0x0519 +#define BCM94336SDGP_SSID 0x0538 +#define BCM94336SDG_SSID 0x0519 +#define BCM94336SDGN_SSID 0x0538 +#define BCM94336SDGFC_SSID 0x056B + + +#define BCM94330SDG_SSID 0x0528 +#define BCM94330SD_FCBGABU_SSID 0x052e +#define BCM94330SD_WLBGABU_SSID 0x052f +#define BCM94330SD_FCBGA_SSID 0x0530 +#define BCM94330FCSDAGB_SSID 0x0532 +#define BCM94330OLYMPICAMG_SSID 0x0549 +#define BCM94330OLYMPICAMGEPA_SSID 0x054F +#define BCM94330OLYMPICUNO3_SSID 0x0551 +#define BCM94330WLSDAGB_SSID 0x0547 +#define BCM94330CSPSDAGBB_SSID 0x054A + + +#define BCM943224X21 0x056e +#define BCM943224X21_FCC 0x00d1 + + +#define BCM943228BU8_SSID 0x0540 +#define BCM943228BU9_SSID 0x0541 +#define BCM943228BU_SSID 0x0542 +#define BCM943227HM4L_SSID 0x0543 +#define BCM943227HMB_SSID 0x0544 +#define BCM943228HM4L_SSID 0x0545 +#define BCM943228SD_SSID 0x0573 + + +#define BCM943239MOD_SSID 0x05ac +#define BCM943239REF_SSID 0x05aa + + +#define BCM94331X19 0x00D6 +#define BCM94331PCIEBT3Ax_SSID 0x00E4 +#define BCM94331X12_2G_SSID 0x00EC +#define BCM94331X12_5G_SSID 0x00ED +#define BCM94331X29B 0x00EF +#define BCM94331BU_SSID 0x0523 +#define BCM94331S9BU_SSID 0x0524 +#define BCM94331MC_SSID 0x0525 +#define BCM94331MCI_SSID 0x0526 +#define BCM94331PCIEBT4_SSID 0x0527 +#define BCM94331HM_SSID 0x0574 +#define BCM94331PCIEDUAL_SSID 0x059B +#define BCM94331MCH5_SSID 0x05A9 +#define BCM94331PCIEDUALV2_SSID 0x05B7 +#define BCM94331CS_SSID 0x05C6 +#define BCM94331CSAX_SSID 0x00EF + + +#define BCM953572BU_SSID 0x058D +#define BCM953572NR2_SSID 0x058E +#define BCM947188NR2_SSID 0x058F +#define BCM953572SDRNR2_SSID 0x0590 + + +#define BCM943236OLYMPICSULLEY_SSID 0x594 +#define BCM943236PREPROTOBLU2O3_SSID 0x5b9 +#define BCM943236USBELNA_SSID 0x5f8 + + +#define GPIO_NUMPINS 32 + + +#define RDL_RAM_BASE_4319 0x60000000 +#define RDL_RAM_BASE_4329 0x60000000 +#define RDL_RAM_SIZE_4319 0x48000 +#define RDL_RAM_SIZE_4329 0x48000 +#define RDL_RAM_SIZE_43236 0x70000 +#define RDL_RAM_BASE_43236 0x60000000 +#define RDL_RAM_SIZE_4328 0x60000 +#define RDL_RAM_BASE_4328 0x80000000 +#define RDL_RAM_SIZE_4322 0x60000 +#define RDL_RAM_BASE_4322 0x60000000 + + +#define MUXENAB_UART 0x00000001 +#define MUXENAB_GPIO 0x00000002 +#define MUXENAB_ERCX 0x00000004 +#define MUXENAB_JTAG 0x00000008 +#define MUXENAB_HOST_WAKE 0x00000010 #endif diff --git a/drivers/net/wireless/bcmdhd/include/bcmendian.h b/drivers/net/wireless/bcmdhd/include/bcmendian.h index 04b07ecb8043..f3356a724b44 100644 --- a/drivers/net/wireless/bcmdhd/include/bcmendian.h +++ b/drivers/net/wireless/bcmdhd/include/bcmendian.h @@ -21,7 +21,7 @@ * software in any way with any other Broadcom software provided under a license * other than the GPL, without Broadcom's express prior written consent. * - * $Id: bcmendian.h,v 1.36 2009-11-09 05:29:43 Exp $ + * $Id: bcmendian.h 277737 2011-08-16 17:54:59Z $ * * This file by default provides proper behavior on little-endian architectures. * On big-endian architectures, IL_BIGENDIAN should be defined. diff --git a/drivers/net/wireless/bcmdhd/include/bcmpcispi.h b/drivers/net/wireless/bcmdhd/include/bcmpcispi.h index fd148c591d88..51e0427e7f60 100644 --- a/drivers/net/wireless/bcmdhd/include/bcmpcispi.h +++ b/drivers/net/wireless/bcmdhd/include/bcmpcispi.h @@ -21,7 +21,7 @@ * software in any way with any other Broadcom software provided under a license * other than the GPL, without Broadcom's express prior written consent. * - * $Id: bcmpcispi.h,v 13.15.112.1 2010-11-15 18:22:12 Exp $ + * $Id: bcmpcispi.h 277737 2011-08-16 17:54:59Z $ */ #ifndef _BCM_PCI_SPI_H #define _BCM_PCI_SPI_H diff --git a/drivers/net/wireless/bcmdhd/include/bcmperf.h b/drivers/net/wireless/bcmdhd/include/bcmperf.h index a3985cf29375..a503edbd6226 100644 --- a/drivers/net/wireless/bcmdhd/include/bcmperf.h +++ b/drivers/net/wireless/bcmdhd/include/bcmperf.h @@ -21,7 +21,7 @@ * software in any way with any other Broadcom software provided under a license * other than the GPL, without Broadcom's express prior written consent. * - * $Id: bcmperf.h,v 13.5 2007-09-14 22:00:59 Exp $ + * $Id: bcmperf.h 277737 2011-08-16 17:54:59Z $ */ /* essai */ #ifndef _BCMPERF_H_ diff --git a/drivers/net/wireless/bcmdhd/include/bcmsdbus.h b/drivers/net/wireless/bcmdhd/include/bcmsdbus.h index 5fda5e9b5df4..21a58b473e91 100644 --- a/drivers/net/wireless/bcmdhd/include/bcmsdbus.h +++ b/drivers/net/wireless/bcmdhd/include/bcmsdbus.h @@ -22,7 +22,7 @@ * software in any way with any other Broadcom software provided under a license * other than the GPL, without Broadcom's express prior written consent. * - * $Id: bcmsdbus.h,v 13.17.86.2 2010-12-23 01:13:20 Exp $ + * $Id: bcmsdbus.h 300017 2011-12-01 20:30:27Z $ */ #ifndef _sdio_api_h_ @@ -117,4 +117,12 @@ void *bcmsdh_get_sdioh(bcmsdh_info_t *sdh); +extern SDIOH_API_RC sdioh_sleep(sdioh_info_t *si, bool enab); + +/* GPIO support */ +extern SDIOH_API_RC sdioh_gpio_init(sdioh_info_t *sd); +extern bool sdioh_gpioin(sdioh_info_t *sd, uint32 gpio); +extern SDIOH_API_RC sdioh_gpioouten(sdioh_info_t *sd, uint32 gpio); +extern SDIOH_API_RC sdioh_gpioout(sdioh_info_t *sd, uint32 gpio, bool enab); + #endif /* _sdio_api_h_ */ diff --git a/drivers/net/wireless/bcmdhd/include/bcmsdh.h b/drivers/net/wireless/bcmdhd/include/bcmsdh.h index 4e3affde6b06..72ee65da8874 100644 --- a/drivers/net/wireless/bcmdhd/include/bcmsdh.h +++ b/drivers/net/wireless/bcmdhd/include/bcmsdh.h @@ -23,7 +23,7 @@ * software in any way with any other Broadcom software provided under a license * other than the GPL, without Broadcom's express prior written consent. * - * $Id: bcmsdh.h,v 13.46.52.3 2010-10-19 00:41:44 Exp $ + * $Id: bcmsdh.h 300017 2011-12-01 20:30:27Z $ */ #ifndef _bcmsdh_h_ @@ -208,4 +208,12 @@ extern uint32 bcmsdh_cur_sbwad(void *sdh); extern void bcmsdh_chipinfo(void *sdh, uint32 chip, uint32 chiprev); +extern int bcmsdh_sleep(void *sdh, bool enab); + +/* GPIO support */ +extern int bcmsdh_gpio_init(void *sd); +extern bool bcmsdh_gpioin(void *sd, uint32 gpio); +extern int bcmsdh_gpioouten(void *sd, uint32 gpio); +extern int bcmsdh_gpioout(void *sd, uint32 gpio, bool enab); + #endif /* _bcmsdh_h_ */ diff --git a/drivers/net/wireless/bcmdhd/include/bcmsdh_sdmmc.h b/drivers/net/wireless/bcmdhd/include/bcmsdh_sdmmc.h index d188c4ec7d5a..bea97b610a8e 100644 --- a/drivers/net/wireless/bcmdhd/include/bcmsdh_sdmmc.h +++ b/drivers/net/wireless/bcmdhd/include/bcmsdh_sdmmc.h @@ -21,7 +21,7 @@ * software in any way with any other Broadcom software provided under a license * other than the GPL, without Broadcom's express prior written consent. * - * $Id: bcmsdh_sdmmc.h,v 13.5.88.1 2010-12-23 01:13:20 Exp $ + * $Id: bcmsdh_sdmmc.h 277737 2011-08-16 17:54:59Z $ */ #ifndef __BCMSDH_SDMMC_H__ diff --git a/drivers/net/wireless/bcmdhd/include/bcmsdpcm.h b/drivers/net/wireless/bcmdhd/include/bcmsdpcm.h index ee29b5c08a5c..1b9d39fee8fc 100644 --- a/drivers/net/wireless/bcmdhd/include/bcmsdpcm.h +++ b/drivers/net/wireless/bcmdhd/include/bcmsdpcm.h @@ -22,7 +22,7 @@ * software in any way with any other Broadcom software provided under a license * other than the GPL, without Broadcom's express prior written consent. * - * $Id: bcmsdpcm.h,v 13.4.90.2 2010-05-12 04:14:25 Exp $ + * $Id: bcmsdpcm.h 277737 2011-08-16 17:54:59Z $ */ #ifndef _bcmsdpcm_h_ diff --git a/drivers/net/wireless/bcmdhd/include/bcmsdspi.h b/drivers/net/wireless/bcmdhd/include/bcmsdspi.h index 0bff355f8ffd..a62bee42b2ba 100644 --- a/drivers/net/wireless/bcmdhd/include/bcmsdspi.h +++ b/drivers/net/wireless/bcmdhd/include/bcmsdspi.h @@ -21,7 +21,7 @@ * software in any way with any other Broadcom software provided under a license * other than the GPL, without Broadcom's express prior written consent. * - * $Id: bcmsdspi.h,v 13.11.86.1 2010-11-15 18:14:56 Exp $ + * $Id: bcmsdspi.h 277737 2011-08-16 17:54:59Z $ */ #ifndef _BCM_SD_SPI_H #define _BCM_SD_SPI_H diff --git a/drivers/net/wireless/bcmdhd/include/bcmsdstd.h b/drivers/net/wireless/bcmdhd/include/bcmsdstd.h index 0f4c0267dbc8..c14444c57d36 100644 --- a/drivers/net/wireless/bcmdhd/include/bcmsdstd.h +++ b/drivers/net/wireless/bcmdhd/include/bcmsdstd.h @@ -21,7 +21,7 @@ * software in any way with any other Broadcom software provided under a license * other than the GPL, without Broadcom's express prior written consent. * - * $Id: bcmsdstd.h,v 13.21.2.6 2010-11-15 18:14:01 Exp $ + * $Id: bcmsdstd.h 281604 2011-09-02 18:58:49Z $ */ #ifndef _BCM_SD_STD_H #define _BCM_SD_STD_H @@ -78,6 +78,7 @@ extern void sdstd_osfree(sdioh_info_t *sd); #define SDIOH_CMD7_EXP_STATUS 0x00001E00 #define RETRIES_LARGE 100000 +#define sdstd_os_yield(sd) do {} while (0) #define RETRIES_SMALL 100 @@ -148,8 +149,8 @@ struct sdioh_info { bool got_hcint; /* local interrupt flag */ uint16 last_intrstatus; /* to cache intrstatus */ int host_UHSISupported; /* whether UHSI is supported for HC. */ - int card_UHSI_voltage_Supported; /* whether UHSI is supported for - * Card in terms of Voltage [1.8 or 3.3]. + int card_UHSI_voltage_Supported; /* whether UHSI is supported for + * Card in terms of Voltage [1.8 or 3.3]. */ int global_UHSI_Supp; /* type of UHSI support in both host and card. * HOST_SDR_UNSUPP: capabilities not supported/matched @@ -171,21 +172,6 @@ struct sdioh_info { #define USE_DMA(sd) ((bool)((sd->sd_dma_mode > 0) ? TRUE : FALSE)) -/* SDIO Host Control Register DMA Mode Definitions */ -#define SDIOH_SDMA_MODE 0 -#define SDIOH_ADMA1_MODE 1 -#define SDIOH_ADMA2_MODE 2 -#define SDIOH_ADMA2_64_MODE 3 - -#define ADMA2_ATTRIBUTE_VALID (1 << 0) /* ADMA Descriptor line valid */ -#define ADMA2_ATTRIBUTE_END (1 << 1) /* End of Descriptor */ -#define ADMA2_ATTRIBUTE_INT (1 << 2) /* Interrupt when line is done */ -#define ADMA2_ATTRIBUTE_ACT_NOP (0 << 4) /* Skip current line, go to next. */ -#define ADMA2_ATTRIBUTE_ACT_RSV (1 << 4) /* Same as NOP */ -#define ADMA1_ATTRIBUTE_ACT_SET (1 << 4) /* ADMA1 Only - set transfer length */ -#define ADMA2_ATTRIBUTE_ACT_TRAN (2 << 4) /* Transfer Data of one descriptor line. */ -#define ADMA2_ATTRIBUTE_ACT_LINK (3 << 4) /* Link Descriptor */ - /* States for Tuning and corr data */ #define TUNING_IDLE 0 #define TUNING_START 1 @@ -195,17 +181,6 @@ struct sdioh_info { #define DATA_TRANSFER_IDLE 0 #define DATA_TRANSFER_ONGOING 1 -/* ADMA2 Descriptor Table Entry for 32-bit Address */ -typedef struct adma2_dscr_32b { - uint32 len_attr; - uint32 phys_addr; -} adma2_dscr_32b_t; - -/* ADMA1 Descriptor Table Entry */ -typedef struct adma1_dscr { - uint32 phys_addr_attr; -} adma1_dscr_t; - /************************************************************ * Internal interfaces: per-port references into bcmsdstd.c */ @@ -254,6 +229,7 @@ extern void sdstd_3_disable_retuning_int(sdioh_info_t *sd); extern bool sdstd_3_is_retuning_int_set(sdioh_info_t *sd); extern bool sdstd_3_check_and_set_retuning(sdioh_info_t *sd); extern int sdstd_3_get_tune_state(sdioh_info_t *sd); +extern int sdstd_3_get_data_state(sdioh_info_t *sd); extern void sdstd_3_set_tune_state(sdioh_info_t *sd, int state); extern uint8 sdstd_3_get_tuning_exp(sdioh_info_t *sd); extern uint32 sdstd_3_get_uhsi_clkmode(sdioh_info_t *sd); diff --git a/drivers/net/wireless/bcmdhd/include/bcmspi.h b/drivers/net/wireless/bcmdhd/include/bcmspi.h index 0eb2a30c9a84..34a02d00c6bd 100644 --- a/drivers/net/wireless/bcmdhd/include/bcmspi.h +++ b/drivers/net/wireless/bcmdhd/include/bcmspi.h @@ -21,7 +21,7 @@ * software in any way with any other Broadcom software provided under a license * other than the GPL, without Broadcom's express prior written consent. * - * $Id: bcmspi.h,v 13.5.112.1 2010-11-15 18:13:09 Exp $ + * $Id: bcmspi.h 277737 2011-08-16 17:54:59Z $ */ #ifndef _BCM_SPI_H #define _BCM_SPI_H diff --git a/drivers/net/wireless/bcmdhd/include/bcmutils.h b/drivers/net/wireless/bcmdhd/include/bcmutils.h index 530036f0ba77..6849c26da837 100644 --- a/drivers/net/wireless/bcmdhd/include/bcmutils.h +++ b/drivers/net/wireless/bcmdhd/include/bcmutils.h @@ -21,7 +21,7 @@ * software in any way with any other Broadcom software provided under a license * other than the GPL, without Broadcom's express prior written consent. * - * $Id: bcmutils.h,v 13.236.2.16 2011-01-26 00:45:06 Exp $ + * $Id: bcmutils.h 294991 2011-11-09 00:17:28Z $ */ @@ -221,7 +221,9 @@ extern uint16 pktpool_avail(pktpool_t *pktp); extern int pktpool_avail_register(pktpool_t *pktp, pktpool_cb_t cb, void *arg); extern int pktpool_empty_register(pktpool_t *pktp, pktpool_cb_t cb, void *arg); extern int pktpool_setmaxlen(pktpool_t *pktp, uint16 maxlen); +extern int pktpool_setmaxlen_strict(osl_t *osh, pktpool_t *pktp, uint16 maxlen); extern void pktpool_emptycb_disable(pktpool_t *pktp, bool disable); +extern bool pktpool_emptycb_disabled(pktpool_t *pktp); #define POOLPTR(pp) ((pktpool_t *)(pp)) #define pktpool_len(pp) (POOLPTR(pp)->len - 1) @@ -330,6 +332,8 @@ extern char *bcm_ip_ntoa(struct ipv4_addr *ia, char *buf); extern void bcm_mdelay(uint ms); +#define NVRAM_RECLAIM_CHECK(name) + extern char *getvar(char *vars, const char *name); extern int getintvar(char *vars, const char *name); extern int getintvararray(char *vars, const char *name, int index); @@ -534,9 +538,17 @@ extern int bcm_format_ssid(char* buf, const uchar ssid[], uint ssid_len); & ~((boundary) - 1)) #define ISPOWEROF2(x) ((((x)-1)&(x)) == 0) #define VALID_MASK(mask) !((mask) & ((mask) + 1)) + #ifndef OFFSETOF +#ifdef __ARMCC_VERSION + +#include +#define OFFSETOF(type, member) offsetof(type, member) +#else #define OFFSETOF(type, member) ((uint)(uintptr)&((type *)0)->member) #endif +#endif + #ifndef ARRAYSIZE #define ARRAYSIZE(a) (sizeof(a)/sizeof(a[0])) #endif diff --git a/drivers/net/wireless/bcmdhd/include/bcmwifi.h b/drivers/net/wireless/bcmdhd/include/bcmwifi.h index 45f3c0312dcc..e5207e9c4086 100644 --- a/drivers/net/wireless/bcmdhd/include/bcmwifi.h +++ b/drivers/net/wireless/bcmdhd/include/bcmwifi.h @@ -23,7 +23,7 @@ * software in any way with any other Broadcom software provided under a license * other than the GPL, without Broadcom's express prior written consent. * - * $Id: bcmwifi.h,v 1.29.6.3 2010-08-03 17:47:04 Exp $ + * $Id: bcmwifi.h 277737 2011-08-16 17:54:59Z $ */ diff --git a/drivers/net/wireless/bcmdhd/include/dhdioctl.h b/drivers/net/wireless/bcmdhd/include/dhdioctl.h index 9661dac2603f..3f3755b53b09 100644 --- a/drivers/net/wireless/bcmdhd/include/dhdioctl.h +++ b/drivers/net/wireless/bcmdhd/include/dhdioctl.h @@ -25,7 +25,7 @@ * software in any way with any other Broadcom software provided under a license * other than the GPL, without Broadcom's express prior written consent. * - * $Id: dhdioctl.h,v 13.11.10.1 2010-12-22 23:47:26 Exp $ + * $Id: dhdioctl.h 277737 2011-08-16 17:54:59Z $ */ #ifndef _dhdioctl_h_ diff --git a/drivers/net/wireless/bcmdhd/include/epivers.h b/drivers/net/wireless/bcmdhd/include/epivers.h index fe71e166a7d9..41a078c42a03 100644 --- a/drivers/net/wireless/bcmdhd/include/epivers.h +++ b/drivers/net/wireless/bcmdhd/include/epivers.h @@ -19,7 +19,7 @@ * software in any way with any other Broadcom software provided under a license * other than the GPL, without Broadcom's express prior written consent. * - * $Id: epivers.h.in,v 13.32.4.1 2010-09-17 00:39:18 $ + * $Id: epivers.h.in 277737 2011-08-16 17:54:59Z $ * */ @@ -31,19 +31,19 @@ #define EPI_MINOR_VERSION 90 -#define EPI_RC_NUMBER 125 +#define EPI_RC_NUMBER 195 -#define EPI_INCREMENTAL_NUMBER 94 +#define EPI_INCREMENTAL_NUMBER 15 #define EPI_BUILD_NUMBER 0 -#define EPI_VERSION 5, 90, 125, 94 +#define EPI_VERSION 5, 90, 195, 15 -#define EPI_VERSION_NUM 0x055a7d5e +#define EPI_VERSION_NUM 0x055ac30f -#define EPI_VERSION_DEV 5.90.125 +#define EPI_VERSION_DEV 5.90.195 -#define EPI_VERSION_STR "5.90.125.94.1" +#define EPI_VERSION_STR "5.90.195.15" #endif diff --git a/drivers/net/wireless/bcmdhd/include/hndpmu.h b/drivers/net/wireless/bcmdhd/include/hndpmu.h index 51c51b9734a2..69a834c6b7eb 100644 --- a/drivers/net/wireless/bcmdhd/include/hndpmu.h +++ b/drivers/net/wireless/bcmdhd/include/hndpmu.h @@ -21,7 +21,7 @@ * software in any way with any other Broadcom software provided under a license * other than the GPL, without Broadcom's express prior written consent. * - * $Id: hndpmu.h,v 13.35.8.5 2011-02-11 00:56:32 Exp $ + * $Id: hndpmu.h 277737 2011-08-16 17:54:59Z $ */ #ifndef _hndpmu_h_ diff --git a/drivers/net/wireless/bcmdhd/include/hndrte_armtrap.h b/drivers/net/wireless/bcmdhd/include/hndrte_armtrap.h index 8b9615c35f35..7d862c4deb21 100644 --- a/drivers/net/wireless/bcmdhd/include/hndrte_armtrap.h +++ b/drivers/net/wireless/bcmdhd/include/hndrte_armtrap.h @@ -21,7 +21,7 @@ * software in any way with any other Broadcom software provided under a license * other than the GPL, without Broadcom's express prior written consent. * - * $Id: hndrte_armtrap.h,v 13.4.14.1 2011-02-05 00:04:30 Exp $ + * $Id: hndrte_armtrap.h 277737 2011-08-16 17:54:59Z $ */ #ifndef _hndrte_armtrap_h diff --git a/drivers/net/wireless/bcmdhd/include/hndrte_cons.h b/drivers/net/wireless/bcmdhd/include/hndrte_cons.h index b9ede53af701..859ddc8953a8 100644 --- a/drivers/net/wireless/bcmdhd/include/hndrte_cons.h +++ b/drivers/net/wireless/bcmdhd/include/hndrte_cons.h @@ -21,7 +21,7 @@ * software in any way with any other Broadcom software provided under a license * other than the GPL, without Broadcom's express prior written consent. * - * $Id: hndrte_cons.h,v 13.4.10.4 2011-02-05 00:08:20 Exp $ + * $Id: hndrte_cons.h 277737 2011-08-16 17:54:59Z $ */ #ifndef _HNDRTE_CONS_H diff --git a/drivers/net/wireless/bcmdhd/include/hndsoc.h b/drivers/net/wireless/bcmdhd/include/hndsoc.h index 4e26121c3881..34f927c6af80 100644 --- a/drivers/net/wireless/bcmdhd/include/hndsoc.h +++ b/drivers/net/wireless/bcmdhd/include/hndsoc.h @@ -21,7 +21,7 @@ * software in any way with any other Broadcom software provided under a license * other than the GPL, without Broadcom's express prior written consent. * - * $Id: hndsoc.h,v 13.11 2009-12-03 23:52:31 Exp $ + * $Id: hndsoc.h 277737 2011-08-16 17:54:59Z $ */ #ifndef _HNDSOC_H diff --git a/drivers/net/wireless/bcmdhd/include/htsf.h b/drivers/net/wireless/bcmdhd/include/htsf.h index 379fbbe37dbc..d875edb816c9 100644 --- a/drivers/net/wireless/bcmdhd/include/htsf.h +++ b/drivers/net/wireless/bcmdhd/include/htsf.h @@ -21,7 +21,7 @@ * software in any way with any other Broadcom software provided under a license * other than the GPL, without Broadcom's express prior written consent. * - * $Id: htsf.h,v 1.1.2.4 2011-01-21 08:27:03 Exp $ + * $Id: htsf.h 277737 2011-08-16 17:54:59Z $ */ #ifndef _HTSF_H_ #define _HTSF_H_ diff --git a/drivers/net/wireless/bcmdhd/include/linux_osl.h b/drivers/net/wireless/bcmdhd/include/linux_osl.h index 38de2982f137..830d351d882b 100644 --- a/drivers/net/wireless/bcmdhd/include/linux_osl.h +++ b/drivers/net/wireless/bcmdhd/include/linux_osl.h @@ -21,7 +21,7 @@ * software in any way with any other Broadcom software provided under a license * other than the GPL, without Broadcom's express prior written consent. * - * $Id: linux_osl.h,v 13.158.6.3 2010-12-22 23:47:26 Exp $ + * $Id: linux_osl.h 301794 2011-12-08 20:41:35Z $ */ diff --git a/drivers/net/wireless/bcmdhd/include/linuxver.h b/drivers/net/wireless/bcmdhd/include/linuxver.h index 96844db2f059..e5189821b4cb 100644 --- a/drivers/net/wireless/bcmdhd/include/linuxver.h +++ b/drivers/net/wireless/bcmdhd/include/linuxver.h @@ -22,7 +22,7 @@ * software in any way with any other Broadcom software provided under a license * other than the GPL, without Broadcom's express prior written consent. * - * $Id: linuxver.h,v 13.53.2.2 2010-12-22 23:47:26 Exp $ + * $Id: linuxver.h 280266 2011-08-28 04:18:20Z $ */ @@ -482,7 +482,11 @@ typedef struct { #define DBG_THR(x) #endif +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0)) +#define SMP_RD_BARRIER_DEPENDS(x) smp_read_barrier_depends(x) +#else #define SMP_RD_BARRIER_DEPENDS(x) smp_rmb(x) +#endif #define PROC_START(thread_func, owner, tsk_ctl, flags) \ diff --git a/drivers/net/wireless/bcmdhd/include/miniopt.h b/drivers/net/wireless/bcmdhd/include/miniopt.h index f468420f5346..77eace6252d7 100644 --- a/drivers/net/wireless/bcmdhd/include/miniopt.h +++ b/drivers/net/wireless/bcmdhd/include/miniopt.h @@ -20,7 +20,7 @@ * Notwithstanding the above, under no circumstances may you combine this * software in any way with any other Broadcom software provided under a license * other than the GPL, without Broadcom's express prior written consent. - * $Id: miniopt.h,v 1.3 2009-01-15 00:06:54 Exp $ + * $Id: miniopt.h 277737 2011-08-16 17:54:59Z $ */ diff --git a/drivers/net/wireless/bcmdhd/include/msgtrace.h b/drivers/net/wireless/bcmdhd/include/msgtrace.h index 721d42100f2a..088f1e845a43 100644 --- a/drivers/net/wireless/bcmdhd/include/msgtrace.h +++ b/drivers/net/wireless/bcmdhd/include/msgtrace.h @@ -21,7 +21,7 @@ * software in any way with any other Broadcom software provided under a license * other than the GPL, without Broadcom's express prior written consent. * - * $Id: msgtrace.h,v 1.4 2009-04-10 04:15:32 Exp $ + * $Id: msgtrace.h 277737 2011-08-16 17:54:59Z $ */ #ifndef _MSGTRACE_H diff --git a/drivers/net/wireless/bcmdhd/include/osl.h b/drivers/net/wireless/bcmdhd/include/osl.h index 80248ee7604e..b8cc2569f506 100644 --- a/drivers/net/wireless/bcmdhd/include/osl.h +++ b/drivers/net/wireless/bcmdhd/include/osl.h @@ -21,7 +21,7 @@ * software in any way with any other Broadcom software provided under a license * other than the GPL, without Broadcom's express prior written consent. * - * $Id: osl.h,v 13.44.96.1 2010-05-20 11:09:18 Exp $ + * $Id: osl.h 277737 2011-08-16 17:54:59Z $ */ diff --git a/drivers/net/wireless/bcmdhd/include/packed_section_end.h b/drivers/net/wireless/bcmdhd/include/packed_section_end.h index 5d4a87678071..71f8b2e13b3b 100644 --- a/drivers/net/wireless/bcmdhd/include/packed_section_end.h +++ b/drivers/net/wireless/bcmdhd/include/packed_section_end.h @@ -34,7 +34,7 @@ * Notwithstanding the above, under no circumstances may you combine this * software in any way with any other Broadcom software provided under a license * other than the GPL, without Broadcom's express prior written consent. - * $Id: packed_section_end.h,v 1.4 2008-12-09 23:43:22 Exp $ + * $Id: packed_section_end.h 277737 2011-08-16 17:54:59Z $ */ diff --git a/drivers/net/wireless/bcmdhd/include/packed_section_start.h b/drivers/net/wireless/bcmdhd/include/packed_section_start.h index da2fed68afac..afc2ba32fd93 100644 --- a/drivers/net/wireless/bcmdhd/include/packed_section_start.h +++ b/drivers/net/wireless/bcmdhd/include/packed_section_start.h @@ -34,7 +34,7 @@ * Notwithstanding the above, under no circumstances may you combine this * software in any way with any other Broadcom software provided under a license * other than the GPL, without Broadcom's express prior written consent. - * $Id: packed_section_start.h,v 1.4.124.1 2010-09-17 00:47:03 Exp $ + * $Id: packed_section_start.h 277737 2011-08-16 17:54:59Z $ */ diff --git a/drivers/net/wireless/bcmdhd/include/pcicfg.h b/drivers/net/wireless/bcmdhd/include/pcicfg.h index fae063a72f18..66199431fb92 100644 --- a/drivers/net/wireless/bcmdhd/include/pcicfg.h +++ b/drivers/net/wireless/bcmdhd/include/pcicfg.h @@ -21,7 +21,7 @@ * software in any way with any other Broadcom software provided under a license * other than the GPL, without Broadcom's express prior written consent. * - * $Id: pcicfg.h,v 1.50 2009-12-07 21:56:06 Exp $ + * $Id: pcicfg.h 277737 2011-08-16 17:54:59Z $ */ @@ -39,6 +39,19 @@ #define PCI_INT_MASK 0x94 #define PCIE_EXTCFG_OFFSET 0x100 +#define PCI_SPROM_CONTROL 0x88 +#define PCI_BAR1_CONTROL 0x8c +#define PCI_TO_SB_MB 0x98 +#define PCI_BACKPLANE_ADDR 0xa0 +#define PCI_BACKPLANE_DATA 0xa4 +#define PCI_CLK_CTL_ST 0xa8 +#define PCI_BAR0_WIN2 0xac +#define PCI_GPIO_IN 0xb0 +#define PCI_GPIO_OUT 0xb4 +#define PCI_GPIO_OUTEN 0xb8 + +#define PCI_BAR0_SHADOW_OFFSET (2 * 1024) +#define PCI_BAR0_SPROM_OFFSET (4 * 1024) #define PCI_BAR0_PCIREGS_OFFSET (6 * 1024) #define PCI_BAR0_PCISBR_OFFSET (4 * 1024) @@ -49,4 +62,17 @@ #define PCI_16KB0_CCREGS_OFFSET (12 * 1024) #define PCI_16KBB0_WINSZ (16 * 1024) + +#define PCI_16KB0_WIN2_OFFSET (4 * 1024) + + + +#define SPROM_SZ_MSK 0x02 +#define SPROM_LOCKED 0x08 +#define SPROM_BLANK 0x04 +#define SPROM_WRITEEN 0x10 +#define SPROM_BOOTROM_WE 0x20 +#define SPROM_BACKPLANE_EN 0x40 +#define SPROM_OTPIN_USE 0x80 + #endif diff --git a/drivers/net/wireless/bcmdhd/include/proto/802.11.h b/drivers/net/wireless/bcmdhd/include/proto/802.11.h index 2342cb383147..8850b2ded236 100644 --- a/drivers/net/wireless/bcmdhd/include/proto/802.11.h +++ b/drivers/net/wireless/bcmdhd/include/proto/802.11.h @@ -21,7 +21,7 @@ * * Fundamental types and constants relating to 802.11 * - * $Id: 802.11.h,v 9.260.2.6 2010-12-15 21:41:14 Exp $ + * $Id: 802.11.h 289520 2011-10-13 04:44:55Z $ */ @@ -429,10 +429,26 @@ typedef struct dot11_obss_chanlist dot11_obss_chanlist_t; BWL_PRE_PACKED_STRUCT struct dot11_extcap_ie { uint8 id; uint8 len; - uint8 cap; + uint8 cap[1]; } BWL_POST_PACKED_STRUCT; typedef struct dot11_extcap_ie dot11_extcap_ie_t; #define DOT11_EXTCAP_LEN 1 +#define DOT11_EXTCAP_LEN_TDLS 5 + +BWL_PRE_PACKED_STRUCT struct dot11_extcap { + uint8 extcap[DOT11_EXTCAP_LEN_TDLS]; +} BWL_POST_PACKED_STRUCT; +typedef struct dot11_extcap dot11_extcap_t; + + +#define TDLS_CAP_TDLS 37 +#define TDLS_CAP_PU_BUFFER_STA 28 +#define TDLS_CAP_PEER_PSM 20 +#define TDLS_CAP_CH_SW 30 +#define TDLS_CAP_PROH 38 +#define TDLS_CAP_CH_SW_PROH 39 + +#define TDLS_CAP_MAX_BIT 39 @@ -545,6 +561,9 @@ typedef struct dot11_ibss_dfs dot11_ibss_dfs_t; #define WME_SUBTYPE_IE 0 #define WME_SUBTYPE_PARAM_IE 1 #define WME_SUBTYPE_TSPEC 2 +#define WME_VERSION_LEN 1 +#define WME_PARAMETER_IE_LEN 24 + #define AC_BE 0 @@ -709,6 +728,15 @@ BWL_PRE_PACKED_STRUCT struct dot11_management_notification { #define DOT11_MGMT_NOTIFICATION_LEN 4 +BWL_PRE_PACKED_STRUCT struct ti_ie { + uint8 ti_type; + uint32 ti_val; +} BWL_POST_PACKED_STRUCT; +typedef struct ti_ie ti_ie_t; +#define TI_TYPE_REASSOC_DEADLINE 1 +#define TI_TYPE_KEY_LIFETIME 2 + + #define WME_ADDTS_REQUEST 0 #define WME_ADDTS_RESPONSE 1 #define WME_DELTS_REQUEST 2 @@ -724,8 +752,7 @@ BWL_PRE_PACKED_STRUCT struct dot11_management_notification { #define DOT11_OPEN_SYSTEM 0 #define DOT11_SHARED_KEY 1 -#define DOT11_OPEN_SHARED 2 -#define DOT11_FAST_BSS 3 +#define DOT11_FAST_BSS 2 #define DOT11_CHALLENGE_LEN 128 @@ -926,9 +953,18 @@ BWL_PRE_PACKED_STRUCT struct dot11_management_notification { #define DOT11_RC_MAX 23 +#define DOT11_RC_TDLS_PEER_UNREACH 25 +#define DOT11_RC_TDLS_DOWN_UNSPECIFIED 26 + #define DOT11_SC_SUCCESS 0 #define DOT11_SC_FAILURE 1 +#define DOT11_SC_TDLS_WAKEUP_SCH_ALT 2 + +#define DOT11_SC_TDLS_WAKEUP_SCH_REJ 3 +#define DOT11_SC_TDLS_SEC_DISABLED 5 +#define DOT11_SC_LIFETIME_REJ 6 +#define DOT11_SC_NOT_SAME_BSS 7 #define DOT11_SC_CAP_MISMATCH 10 #define DOT11_SC_REASSOC_FAIL 11 #define DOT11_SC_ASSOC_FAIL 12 @@ -947,13 +983,22 @@ BWL_PRE_PACKED_STRUCT struct dot11_management_notification { #define DOT11_SC_ASSOC_SHORTSLOT_REQUIRED 25 #define DOT11_SC_ASSOC_ERPBCC_REQUIRED 26 #define DOT11_SC_ASSOC_DSSOFDM_REQUIRED 27 - -#define DOT11_SC_DECLINED 37 -#define DOT11_SC_INVALID_PARAMS 38 -#define DOT11_SC_INVALID_AKMP 43 -#define DOT11_SC_INVALID_MDID 54 -#define DOT11_SC_INVALID_FTIE 55 - +#define DOT11_SC_ASSOC_R0KH_UNREACHABLE 28 +#define DOT11_SC_ASSOC_TRY_LATER 30 +#define DOT11_SC_ASSOC_MFP_VIOLATION 31 + +#define DOT11_SC_DECLINED 37 +#define DOT11_SC_INVALID_PARAMS 38 +#define DOT11_SC_INVALID_PAIRWISE_CIPHER 42 +#define DOT11_SC_INVALID_AKMP 43 +#define DOT11_SC_INVALID_RSNIE_CAP 45 +#define DOT11_SC_INVALID_PMKID 53 +#define DOT11_SC_INVALID_MDID 54 +#define DOT11_SC_INVALID_FTIE 55 + +#define DOT11_SC_UNEXP_MSG 70 +#define DOT11_SC_INVALID_SNONCE 71 +#define DOT11_SC_INVALID_RSNIE 72 #define DOT11_MNG_DS_PARAM_LEN 1 #define DOT11_MNG_IBSS_PARAM_LEN 2 @@ -1008,6 +1053,7 @@ BWL_PRE_PACKED_STRUCT struct dot11_management_notification { #define DOT11_MNG_MDIE_ID 54 #define DOT11_MNG_FTIE_ID 55 #define DOT11_MNG_FT_TI_ID 56 +#define DOT11_MNG_RDE_ID 57 #define DOT11_MNG_REGCLASS_ID 59 #define DOT11_MNG_EXT_CSA_ID 60 #define DOT11_MNG_HT_ADD 61 @@ -1018,7 +1064,13 @@ BWL_PRE_PACKED_STRUCT struct dot11_management_notification { #define DOT11_MNG_HT_BSS_COEXINFO_ID 72 #define DOT11_MNG_HT_BSS_CHANNEL_REPORT_ID 73 #define DOT11_MNG_HT_OBSS_ID 74 -#define DOT11_MNG_EXT_CAP 127 +#define DOT11_MNG_CHANNEL_USAGE 97 +#define DOT11_MNG_LINK_IDENTIFIER_ID 101 +#define DOT11_MNG_WAKEUP_SCHEDULE_ID 102 +#define DOT11_MNG_CHANNEL_SWITCH_TIMING_ID 104 +#define DOT11_MNG_PTI_CONTROL_ID 105 +#define DOT11_MNG_PU_BUFFER_STATUS_ID 106 +#define DOT11_MNG_EXT_CAP_ID 127 #define DOT11_MNG_WPA_ID 221 #define DOT11_MNG_PROPR_ID 221 @@ -1070,8 +1122,14 @@ BWL_PRE_PACKED_STRUCT struct dot11_management_notification { #define DOT11_ACTION_CAT_RRM 5 #define DOT11_ACTION_CAT_FBT 6 #define DOT11_ACTION_CAT_HT 7 +#if defined(MFP) || defined(WLFBT) || defined(WLWNM) +#define DOT11_ACTION_CAT_SA_QUERY 8 +#define DOT11_ACTION_CAT_PDPA 9 #define DOT11_ACTION_CAT_BSSMGMT 10 #define DOT11_ACTION_NOTIFICATION 17 +#define DOT11_ACTION_CAT_VSP 126 +#endif +#define DOT11_ACTION_NOTIFICATION 17 #define DOT11_ACTION_CAT_VS 127 @@ -1107,6 +1165,121 @@ BWL_PRE_PACKED_STRUCT struct dot11_management_notification { #define DOT11_ADDBA_POLICY_DELAYED 0 #define DOT11_ADDBA_POLICY_IMMEDIATE 1 + +#define DOT11_FT_ACTION_FT_RESERVED 0 +#define DOT11_FT_ACTION_FT_REQ 1 +#define DOT11_FT_ACTION_FT_RES 2 +#define DOT11_FT_ACTION_FT_CON 3 +#define DOT11_FT_ACTION_FT_ACK 4 + + + +#define DOT11_WNM_ACTION_EVENT_REQ 0 +#define DOT11_WNM_ACTION_EVENT_REP 1 +#define DOT11_WNM_ACTION_DIAG_REQ 2 +#define DOT11_WNM_ACTION_DIAG_REP 3 +#define DOT11_WNM_ACTION_LOC_CFG_REQ 4 +#define DOT11_WNM_ACTION_LOC_RFG_RESP 5 +#define DOT11_WNM_ACTION_BSS_TRANS_QURY 6 +#define DOT11_WNM_ACTION_BSS_TRANS_REQ 7 +#define DOT11_WNM_ACTION_BSS_TRANS_RESP 8 +#define DOT11_WNM_ACTION_FMS_REQ 9 +#define DOT11_WNM_ACTION_FMS_RESP 10 +#define DOT11_WNM_ACTION_COL_INTRFRNCE_REQ 11 +#define DOT11_WNM_ACTION_COL_INTRFRNCE_REP 12 +#define DOT11_WNM_ACTION_TFS_REQ 13 +#define DOT11_WNM_ACTION_TFS_RESP 14 +#define DOT11_WNM_ACTION_TFS_NOTIFY 15 +#define DOT11_WNM_ACTION_WNM_SLEEP_REQ 16 +#define DOT11_WNM_ACTION_WNM_SLEEP_RESP 17 +#define DOT11_WNM_ACTION_TIM_BCAST_REQ 18 +#define DOT11_WNM_ACTION_TIM_BCAST_RESP 19 +#define DOT11_WNM_ACTION_QOS_TRFC_CAP_UPD 20 +#define DOT11_WNM_ACTION_CHAN_USAGE_REQ 21 +#define DOT11_WNM_ACTION_CHAN_USAGE_RESP 22 +#define DOT11_WNM_ACTION_DMS_REQ 23 +#define DOT11_WNM_ACTION_DMS_RESP 24 +#define DOT11_WNM_ACTION_TMNG_MEASUR_REQ 25 +#define DOT11_WNM_ACTION_NOTFCTN_REQ 26 +#define DOT11_WNM_ACTION_NOTFCTN_RES 27 + + + +BWL_PRE_PACKED_STRUCT struct dot11_bss_trans_query { + uint8 category; + uint8 action; + uint8 token; + uint8 reason; + uint8 data[1]; +} BWL_POST_PACKED_STRUCT; +typedef struct dot11_bss_trans_query dot11_bss_trans_query_t; +#define DOT11_BSS_TRANS_QUERY_LEN 4 + + +BWL_PRE_PACKED_STRUCT struct dot11_bss_trans_req { + uint8 category; + uint8 action; + uint8 token; + uint8 reqmode; + uint16 disassoc_tmr; + uint8 validity_intrvl; + uint8 data[1]; + +} BWL_POST_PACKED_STRUCT; +typedef struct dot11_bss_trans_req dot11_bss_trans_req_t; +#define DOT11_BSS_TRANS_REQ_LEN 7 + +#define DOT11_BSS_TERM_DUR_LEN 12 + + + +#define DOT11_BSS_TRNS_REQMODE_PREF_LIST_INCL 0x01 +#define DOT11_BSS_TRNS_REQMODE_ABRIDGED 0x02 +#define DOT11_BSS_TRNS_REQMODE_DISASSOC_IMMINENT 0x04 +#define DOT11_BSS_TRNS_REQMODE_BSS_TERM_INCL 0x08 +#define DOT11_BSS_TRNS_REQMODE_ESS_DISASSOC_IMNT 0x10 + + + +BWL_PRE_PACKED_STRUCT struct dot11_bss_trans_res { + uint8 category; + uint8 action; + uint8 token; + uint8 status; + uint8 term_delay; + uint8 data[1]; + +} BWL_POST_PACKED_STRUCT; +typedef struct dot11_bss_trans_res dot11_bss_trans_res_t; +#define DOT11_BSS_TRANS_RES_LEN 5 + + +#define DOT11_BSS_TRNS_RES_STATUS_ACCEPT 0 +#define DOT11_BSS_TRNS_RES_STATUS_REJECT 1 +#define DOT11_BSS_TRNS_RES_STATUS_REJ_INSUFF_BCN 2 +#define DOT11_BSS_TRNS_RES_STATUS_REJ_INSUFF_CAP 3 +#define DOT11_BSS_TRNS_RES_STATUS_REJ_TERM_UNDESIRED 4 +#define DOT11_BSS_TRNS_RES_STATUS_REJ_TERM_DELAY_REQ 5 +#define DOT11_BSS_TRNS_RES_STATUS_REJ_BSS_LIST_PROVIDED 6 +#define DOT11_BSS_TRNS_RES_STATUS_REJ_NO_SUITABLE_BSS 7 +#define DOT11_BSS_TRNS_RES_STATUS_REJ_LEAVING_ESS 8 + + + +#define DOT11_NBR_RPRT_BSSID_INFO_REACHABILTY 0x0003 +#define DOT11_NBR_RPRT_BSSID_INFO_SEC 0x0004 +#define DOT11_NBR_RPRT_BSSID_INFO_KEY_SCOPE 0x0008 +#define DOT11_NBR_RPRT_BSSID_INFO_CAP 0x03f0 + +#define DOT11_NBR_RPRT_BSSID_INFO_CAP_SPEC_MGMT 0x0010 +#define DOT11_NBR_RPRT_BSSID_INFO_CAP_QOS 0x0020 +#define DOT11_NBR_RPRT_BSSID_INFO_CAP_APSD 0x0040 +#define DOT11_NBR_RPRT_BSSID_INFO_CAP_RDIO_MSMT 0x0080 +#define DOT11_NBR_RPRT_BSSID_INFO_CAP_DEL_BA 0x0100 +#define DOT11_NBR_RPRT_BSSID_INFO_CAP_IMM_BA 0x0200 + + +#define DOT11_NBR_RPRT_SUBELEM_BSS_CANDDT_PREF_ID 3 BWL_PRE_PACKED_STRUCT struct dot11_addba_req { uint8 category; uint8 action; @@ -1145,6 +1318,48 @@ typedef struct dot11_delba dot11_delba_t; #define DOT11_DELBA_LEN 6 +#define SA_QUERY_REQUEST 0 +#define SA_QUERY_RESPONSE 1 + + + + +BWL_PRE_PACKED_STRUCT struct dot11_ft_req { + uint8 category; + uint8 action; + uint8 sta_addr[ETHER_ADDR_LEN]; + uint8 tgt_ap_addr[ETHER_ADDR_LEN]; + uint8 data[1]; +} BWL_POST_PACKED_STRUCT; +typedef struct dot11_ft_req dot11_ft_req_t; +#define DOT11_FT_REQ_FIXED_LEN 14 + + +BWL_PRE_PACKED_STRUCT struct dot11_ft_res { + uint8 category; + uint8 action; + uint8 sta_addr[ETHER_ADDR_LEN]; + uint8 tgt_ap_addr[ETHER_ADDR_LEN]; + uint16 status; + uint8 data[1]; +} BWL_POST_PACKED_STRUCT; +typedef struct dot11_ft_res dot11_ft_res_t; +#define DOT11_FT_RES_FIXED_LEN 16 + + +BWL_PRE_PACKED_STRUCT struct dot11_rde_ie { + uint8 id; + uint8 length; + uint8 rde_id; + uint8 rd_count; + uint16 status; +} BWL_POST_PACKED_STRUCT; +typedef struct dot11_rde_ie dot11_rde_ie_t; + + +#define DOT11_MNG_RDE_IE_LEN sizeof(dot11_rde_ie_t) + + @@ -1166,6 +1381,20 @@ typedef struct dot11_rrm_cap_ie dot11_rrm_cap_ie_t; #define DOT11_RRM_CAP_AP_CHANREP 16 + +#define DOT11_EXT_CAP_LEN 4 +BWL_PRE_PACKED_STRUCT struct dot11_ext_cap_ie { + uint8 cap[DOT11_EXT_CAP_LEN]; +} BWL_POST_PACKED_STRUCT; +typedef struct dot11_ext_cap_ie dot11_ext_cap_ie_t; + + +#define DOT11_EXT_CAP_BSS_TRANSITION_MGMT 19 + + +#define DOT11_OP_CLASS_NONE 255 + + #define DOT11_RM_ACTION_RM_REQ 0 #define DOT11_RM_ACTION_RM_REP 1 #define DOT11_RM_ACTION_LM_REQ 2 @@ -1272,6 +1501,7 @@ BWL_PRE_PACKED_STRUCT struct dot11_rmrep_nbr { uint8 reg; uint8 channel; uint8 phytype; + uchar sub_elements[1]; } BWL_POST_PACKED_STRUCT; typedef struct dot11_rmrep_nbr dot11_rmrep_nbr_t; #define DOT11_RMREP_NBR_LEN 13 @@ -1660,6 +1890,9 @@ typedef struct dot11_obss_ie dot11_obss_ie_t; #define RSN_AKM_PSK 2 #define RSN_AKM_FBT_1X 3 #define RSN_AKM_FBT_PSK 4 +#define RSN_AKM_MFP_1X 5 +#define RSN_AKM_MFP_PSK 6 +#define RSN_AKM_TPK 7 #define DOT11_MAX_DEFAULT_KEYS 4 @@ -1724,6 +1957,66 @@ BWL_PRE_PACKED_STRUCT struct dot11_gtk_ie { } BWL_POST_PACKED_STRUCT; typedef struct dot11_gtk_ie dot11_gtk_ie_t; +#define BSSID_INVALID "\x00\x00\x00\x00\x00\x00" +#define BSSID_BROADCAST "\xFF\xFF\xFF\xFF\xFF\xFF" + + + +BWL_PRE_PACKED_STRUCT struct link_id_ie { + uint8 id; + uint8 len; + struct ether_addr bssid; + struct ether_addr tdls_init_mac; + struct ether_addr tdls_resp_mac; +} BWL_POST_PACKED_STRUCT; +typedef struct link_id_ie link_id_ie_t; +#define TDLS_LINK_ID_IE_LEN 18 + + +BWL_PRE_PACKED_STRUCT struct wakeup_sch_ie { + uint8 id; + uint8 len; + uint32 offset; + uint32 interval; + uint32 awake_win_slots; + uint32 max_wake_win; + uint16 idle_cnt; +} BWL_POST_PACKED_STRUCT; +typedef struct wakeup_sch_ie wakeup_sch_ie_t; +#define TDLS_WAKEUP_SCH_IE_LEN 18 + + +BWL_PRE_PACKED_STRUCT struct channel_switch_timing_ie { + uint8 id; + uint8 len; + uint16 switch_time; + uint16 switch_timeout; +} BWL_POST_PACKED_STRUCT; +typedef struct channel_switch_timing_ie channel_switch_timing_ie_t; +#define TDLS_CHANNEL_SWITCH_TIMING_IE_LEN 4 + + +BWL_PRE_PACKED_STRUCT struct pti_control_ie { + uint8 id; + uint8 len; + uint8 tid; + uint16 seq_control; +} BWL_POST_PACKED_STRUCT; +typedef struct pti_control_ie pti_control_ie_t; +#define TDLS_PTI_CONTROL_IE_LEN 3 + + +BWL_PRE_PACKED_STRUCT struct pu_buffer_status_ie { + uint8 id; + uint8 len; + uint8 status; +} BWL_POST_PACKED_STRUCT; +typedef struct pu_buffer_status_ie pu_buffer_status_ie_t; +#define TDLS_PU_BUFFER_STATUS_IE_LEN 1 +#define TDLS_PU_BUFFER_STATUS_AC_BK 1 +#define TDLS_PU_BUFFER_STATUS_AC_BE 2 +#define TDLS_PU_BUFFER_STATUS_AC_VI 4 +#define TDLS_PU_BUFFER_STATUS_AC_VO 8 #include diff --git a/drivers/net/wireless/bcmdhd/include/proto/802.11_bta.h b/drivers/net/wireless/bcmdhd/include/proto/802.11_bta.h index 4ccfab02056b..cbdd05e624bc 100644 --- a/drivers/net/wireless/bcmdhd/include/proto/802.11_bta.h +++ b/drivers/net/wireless/bcmdhd/include/proto/802.11_bta.h @@ -21,7 +21,7 @@ * software in any way with any other Broadcom software provided under a license * other than the GPL, without Broadcom's express prior written consent. * - * $Id: 802.11_bta.h,v 9.2 2008-10-28 23:27:13 Exp $ + * $Id: 802.11_bta.h 277737 2011-08-16 17:54:59Z $ */ #ifndef _802_11_BTA_H_ diff --git a/drivers/net/wireless/bcmdhd/include/proto/802.11e.h b/drivers/net/wireless/bcmdhd/include/proto/802.11e.h index ce8ad083f286..0e070a475b64 100644 --- a/drivers/net/wireless/bcmdhd/include/proto/802.11e.h +++ b/drivers/net/wireless/bcmdhd/include/proto/802.11e.h @@ -21,7 +21,7 @@ * software in any way with any other Broadcom software provided under a license * other than the GPL, without Broadcom's express prior written consent. * - * $Id: 802.11e.h,v 1.6 2008-12-01 22:55:11 Exp $ + * $Id: 802.11e.h 277737 2011-08-16 17:54:59Z $ */ #ifndef _802_11e_H_ diff --git a/drivers/net/wireless/bcmdhd/include/proto/802.1d.h b/drivers/net/wireless/bcmdhd/include/proto/802.1d.h index cf206250246f..c7e07bd5e7c3 100644 --- a/drivers/net/wireless/bcmdhd/include/proto/802.1d.h +++ b/drivers/net/wireless/bcmdhd/include/proto/802.1d.h @@ -21,7 +21,7 @@ * * Fundamental types and constants relating to 802.1D * - * $Id: 802.1d.h,v 9.3 2007-04-10 21:33:06 Exp $ + * $Id: 802.1d.h 277737 2011-08-16 17:54:59Z $ */ diff --git a/drivers/net/wireless/bcmdhd/include/proto/bcmeth.h b/drivers/net/wireless/bcmdhd/include/proto/bcmeth.h index 46fa4c9f89e8..0f75d3c8f1d6 100644 --- a/drivers/net/wireless/bcmdhd/include/proto/bcmeth.h +++ b/drivers/net/wireless/bcmdhd/include/proto/bcmeth.h @@ -21,7 +21,7 @@ * software in any way with any other Broadcom software provided under a license * other than the GPL, without Broadcom's express prior written consent. * - * $Id: bcmeth.h,v 9.12 2009-12-29 19:57:18 Exp $ + * $Id: bcmeth.h 277737 2011-08-16 17:54:59Z $ */ diff --git a/drivers/net/wireless/bcmdhd/include/proto/bcmevent.h b/drivers/net/wireless/bcmdhd/include/proto/bcmevent.h index 30ec848c40ae..e8c2387dd10b 100644 --- a/drivers/net/wireless/bcmdhd/include/proto/bcmevent.h +++ b/drivers/net/wireless/bcmdhd/include/proto/bcmevent.h @@ -23,7 +23,7 @@ * * Dependencies: proto/bcmeth.h * - * $Id: bcmevent.h,v 9.64.2.9 2011-02-01 06:24:21 Exp $ + * $Id: bcmevent.h 288077 2011-10-06 00:08:47Z $ * */ @@ -182,7 +182,10 @@ typedef BWL_PRE_PACKED_STRUCT struct bcm_event { #define WLC_E_PFN_SCAN_NONE 82 #define WLC_E_PFN_SCAN_ALLGONE 83 #define WLC_E_GTK_PLUMBED 84 -#define WLC_E_LAST 85 +#define WLC_E_ASSOC_REQ_IE 85 +#define WLC_E_ASSOC_RESP_IE 86 +#define WLC_E_LAST 87 + typedef struct { @@ -226,6 +229,8 @@ extern const int bcmevent_names_size; #define WLC_E_REASON_TSPEC_REJECTED 7 #define WLC_E_REASON_BETTER_AP 8 +#define WLC_E_REASON_REQUESTED_ROAM 11 + #define WLC_E_PRUNE_ENCR_MISMATCH 1 #define WLC_E_PRUNE_BCAST_BSSID 2 diff --git a/drivers/net/wireless/bcmdhd/include/proto/bcmip.h b/drivers/net/wireless/bcmdhd/include/proto/bcmip.h index 8a8f3146d56b..55eff247c492 100644 --- a/drivers/net/wireless/bcmdhd/include/proto/bcmip.h +++ b/drivers/net/wireless/bcmdhd/include/proto/bcmip.h @@ -21,7 +21,7 @@ * * Fundamental constants relating to IP Protocol * - * $Id: bcmip.h,v 9.19 2009-11-10 20:08:33 Exp $ + * $Id: bcmip.h 277737 2011-08-16 17:54:59Z $ */ diff --git a/drivers/net/wireless/bcmdhd/include/proto/bt_amp_hci.h b/drivers/net/wireless/bcmdhd/include/proto/bt_amp_hci.h index 89c118179159..91ab4fe538f2 100644 --- a/drivers/net/wireless/bcmdhd/include/proto/bt_amp_hci.h +++ b/drivers/net/wireless/bcmdhd/include/proto/bt_amp_hci.h @@ -21,7 +21,7 @@ * software in any way with any other Broadcom software provided under a license * other than the GPL, without Broadcom's express prior written consent. * - * $Id: bt_amp_hci.h,v 9.14.8.2 2010-09-10 18:37:47 Exp $ + * $Id: bt_amp_hci.h 277737 2011-08-16 17:54:59Z $ */ #ifndef _bt_amp_hci_h diff --git a/drivers/net/wireless/bcmdhd/include/proto/eapol.h b/drivers/net/wireless/bcmdhd/include/proto/eapol.h index 5781d1312e35..92634c1221a6 100644 --- a/drivers/net/wireless/bcmdhd/include/proto/eapol.h +++ b/drivers/net/wireless/bcmdhd/include/proto/eapol.h @@ -7,7 +7,7 @@ * * Copyright (C) 2002 Broadcom Corporation * - * $Id: eapol.h,v 9.23.86.1 2010-09-02 18:09:39 Exp $ + * $Id: eapol.h 277737 2011-08-16 17:54:59Z $ */ #ifndef _eapol_h_ diff --git a/drivers/net/wireless/bcmdhd/include/proto/ethernet.h b/drivers/net/wireless/bcmdhd/include/proto/ethernet.h index 6a6dd14c1bbb..20865dc5a231 100644 --- a/drivers/net/wireless/bcmdhd/include/proto/ethernet.h +++ b/drivers/net/wireless/bcmdhd/include/proto/ethernet.h @@ -21,7 +21,7 @@ * software in any way with any other Broadcom software provided under a license * other than the GPL, without Broadcom's express prior written consent. * - * $Id: ethernet.h,v 9.56 2009-10-15 22:54:58 Exp $ + * $Id: ethernet.h 285437 2011-09-21 22:16:56Z $ */ @@ -69,6 +69,7 @@ #define ETHER_TYPE_802_1X 0x888e #define ETHER_TYPE_802_1X_PREAUTH 0x88c7 #define ETHER_TYPE_WAI 0x88b4 +#define ETHER_TYPE_89_0D 0x890d diff --git a/drivers/net/wireless/bcmdhd/include/proto/p2p.h b/drivers/net/wireless/bcmdhd/include/proto/p2p.h index 4a0c9d1ddc37..d2bf3f20688c 100644 --- a/drivers/net/wireless/bcmdhd/include/proto/p2p.h +++ b/drivers/net/wireless/bcmdhd/include/proto/p2p.h @@ -21,7 +21,7 @@ * * Fundamental types and constants relating to WFA P2P (aka WiFi Direct) * - * $Id: p2p.h,v 9.17.2.4 2010-12-15 21:41:21 Exp $ + * $Id: p2p.h 277737 2011-08-16 17:54:59Z $ */ #ifndef _P2P_H_ diff --git a/drivers/net/wireless/bcmdhd/include/proto/sdspi.h b/drivers/net/wireless/bcmdhd/include/proto/sdspi.h index 7fe4fbce310e..7353ff0d7c73 100644 --- a/drivers/net/wireless/bcmdhd/include/proto/sdspi.h +++ b/drivers/net/wireless/bcmdhd/include/proto/sdspi.h @@ -21,7 +21,7 @@ * software in any way with any other Broadcom software provided under a license * other than the GPL, without Broadcom's express prior written consent. * - * $Id: sdspi.h,v 9.2.120.1 2010-11-15 17:56:25 Exp $ + * $Id: sdspi.h 277737 2011-08-16 17:54:59Z $ */ #ifndef _SD_SPI_H diff --git a/drivers/net/wireless/bcmdhd/include/proto/vlan.h b/drivers/net/wireless/bcmdhd/include/proto/vlan.h index 07fa7e499c23..27f005537604 100644 --- a/drivers/net/wireless/bcmdhd/include/proto/vlan.h +++ b/drivers/net/wireless/bcmdhd/include/proto/vlan.h @@ -21,7 +21,7 @@ * software in any way with any other Broadcom software provided under a license * other than the GPL, without Broadcom's express prior written consent. * - * $Id: vlan.h,v 9.7 2009-03-13 01:11:50 Exp $ + * $Id: vlan.h 277737 2011-08-16 17:54:59Z $ */ diff --git a/drivers/net/wireless/bcmdhd/include/proto/wpa.h b/drivers/net/wireless/bcmdhd/include/proto/wpa.h index 1ff06dc79423..7361cbf20b06 100644 --- a/drivers/net/wireless/bcmdhd/include/proto/wpa.h +++ b/drivers/net/wireless/bcmdhd/include/proto/wpa.h @@ -21,7 +21,7 @@ * software in any way with any other Broadcom software provided under a license * other than the GPL, without Broadcom's express prior written consent. * - * $Id: wpa.h,v 1.19 2009-07-13 08:29:58 Exp $ + * $Id: wpa.h 285437 2011-09-21 22:16:56Z $ */ @@ -114,6 +114,8 @@ typedef BWL_PRE_PACKED_STRUCT struct #define WPA_CIPHER_AES_OCB 3 #define WPA_CIPHER_AES_CCM 4 #define WPA_CIPHER_WEP_104 5 +#define WPA_CIPHER_BIP 6 +#define WPA_CIPHER_TPK 7 #define IS_WPA_CIPHER(cipher) ((cipher) == WPA_CIPHER_NONE || \ @@ -121,7 +123,9 @@ typedef BWL_PRE_PACKED_STRUCT struct (cipher) == WPA_CIPHER_WEP_104 || \ (cipher) == WPA_CIPHER_TKIP || \ (cipher) == WPA_CIPHER_AES_OCB || \ - (cipher) == WPA_CIPHER_AES_CCM) + (cipher) == WPA_CIPHER_AES_CCM || \ + (cipher) == WPA_CIPHER_TPK) + #define WPA_TKIP_CM_DETECT 60 @@ -149,7 +153,11 @@ typedef BWL_PRE_PACKED_STRUCT struct #define WPA_CAP_REPLAY_CNTR_MASK RSN_CAP_PTK_REPLAY_CNTR_MASK +#define WPA_CAP_PEER_KEY_ENABLE (0x1 << 1) + + #define WPA_CAP_LEN RSN_CAP_LEN +#define WPA_PMKID_CNT_LEN 2 #define WPA_CAP_WPA2_PREAUTH RSN_CAP_PREAUTH diff --git a/drivers/net/wireless/bcmdhd/include/sbchipc.h b/drivers/net/wireless/bcmdhd/include/sbchipc.h index cbd37490f1cb..3fe2a5a49d30 100644 --- a/drivers/net/wireless/bcmdhd/include/sbchipc.h +++ b/drivers/net/wireless/bcmdhd/include/sbchipc.h @@ -5,7 +5,7 @@ * JTAG, 0/1/2 UARTs, clock frequency control, a watchdog interrupt timer, * GPIO interface, extbus, and support for serial and parallel flashes. * - * $Id: sbchipc.h,v 13.169.2.14 2011-02-10 23:43:55 Exp $ + * $Id: sbchipc.h 277737 2011-08-16 17:54:59Z $ * * Copyright (C) 1999-2011, Broadcom Corporation * @@ -41,6 +41,50 @@ #define PAD _XSTR(__LINE__) #endif +typedef struct eci_prerev35 { + uint32 eci_output; + uint32 eci_control; + uint32 eci_inputlo; + uint32 eci_inputmi; + uint32 eci_inputhi; + uint32 eci_inputintpolaritylo; + uint32 eci_inputintpolaritymi; + uint32 eci_inputintpolarityhi; + uint32 eci_intmasklo; + uint32 eci_intmaskmi; + uint32 eci_intmaskhi; + uint32 eci_eventlo; + uint32 eci_eventmi; + uint32 eci_eventhi; + uint32 eci_eventmasklo; + uint32 eci_eventmaskmi; + uint32 eci_eventmaskhi; + uint32 PAD[3]; +} eci_prerev35_t; + +typedef struct eci_rev35 { + uint32 eci_outputlo; + uint32 eci_outputhi; + uint32 eci_controllo; + uint32 eci_controlhi; + uint32 eci_inputlo; + uint32 eci_inputhi; + uint32 eci_inputintpolaritylo; + uint32 eci_inputintpolarityhi; + uint32 eci_intmasklo; + uint32 eci_intmaskhi; + uint32 eci_eventlo; + uint32 eci_eventhi; + uint32 eci_eventmasklo; + uint32 eci_eventmaskhi; + uint32 eci_auxtx; + uint32 eci_auxrx; + uint32 eci_datatag; + uint32 eci_uartescvalue; + uint32 eci_autobaudctr; + uint32 eci_uartfifolevel; +} eci_rev35_t; + typedef volatile struct { uint32 chipid; uint32 capabilities; @@ -153,10 +197,26 @@ typedef volatile struct { uint32 prog_waitcount; uint32 flash_config; uint32 flash_waitcount; - uint32 PAD[4]; - uint32 PAD[40]; + uint32 SECI_config; + uint32 SECI_status; + uint32 SECI_statusmask; + uint32 SECI_rxnibchanged; + + uint32 PAD[20]; + uint32 sromcontrol; + uint32 sromaddress; + uint32 sromdata; + uint32 PAD[9]; + uint32 seci_uart_data; + uint32 seci_uart_bauddiv; + uint32 seci_uart_fcr; + uint32 seci_uart_lcr; + uint32 seci_uart_mcr; + uint32 seci_uart_lsr; + uint32 seci_uart_msr; + uint32 seci_uart_baudadj; uint32 clk_ctl_st; uint32 hw_war; @@ -1332,9 +1392,27 @@ typedef volatile struct { #define CST43237_BOOT_FROM_INVALID 3 +#define RES43239_CBUCK_LPOM 0 +#define RES43239_CBUCK_BURST 1 +#define RES43239_CBUCK_LP_PWM 2 +#define RES43239_CBUCK_PWM 3 +#define RES43239_CLDO_PU 4 +#define RES43239_DIS_INT_RESET_PD 5 +#define RES43239_ILP_REQUEST 6 +#define RES43239_LNLDO_PU 7 +#define RES43239_LDO3P3_PU 8 #define RES43239_OTP_PU 9 +#define RES43239_XTAL_PU 10 +#define RES43239_ALP_AVAIL 11 +#define RES43239_RADIO_PU 12 #define RES43239_MACPHY_CLKAVAIL 23 #define RES43239_HT_AVAIL 24 +#define RES43239_XOLDO_PU 25 +#define RES43239_WL_XTAL_CTL_SEL 26 +#define RES43239_SR_CLK_STABLE 27 +#define RES43239_SR_SAVE_RESTORE 28 +#define RES43239_SR_PHY_PIC 29 +#define RES43239_SR_PHY_PWR_SW 30 #define CST43239_SPROM_MASK 0x00000002 @@ -1342,7 +1420,7 @@ typedef volatile struct { #define CST43239_RES_INIT_MODE_SHIFT 7 #define CST43239_RES_INIT_MODE_MASK 0x000001f0 #define CST43239_CHIPMODE_SDIOD(cs) ((cs) & (1 << 15)) -#define CST43239_CHIPMODE_USB20D(cs) ((cs) & !(1 << 15)) +#define CST43239_CHIPMODE_USB20D(cs) (~(cs) & (1 << 15)) #define CST43239_CHIPMODE_SDIO(cs) (((cs) & (1 << 0)) == 0) #define CST43239_CHIPMODE_GSPI(cs) (((cs) & (1 << 0)) == (1 << 0)) @@ -1350,6 +1428,40 @@ typedef volatile struct { #define CCTRL43239_XTAL_STRENGTH(ctl) ((ctl & 0x3F) << 12) +#define RES4331_REGULATOR 0 +#define RES4331_ILP_REQUEST 1 +#define RES4331_XTAL_PU 2 +#define RES4331_ALP_AVAIL 3 +#define RES4331_SI_PLL_ON 4 +#define RES4331_HT_SI_AVAIL 5 + + +#define CCTRL4331_BT_COEXIST (1<<0) +#define CCTRL4331_SECI (1<<1) +#define CCTRL4331_EXT_LNA_G (1<<2) +#define CCTRL4331_SPROM_GPIO13_15 (1<<3) +#define CCTRL4331_EXTPA_EN (1<<4) +#define CCTRL4331_GPIOCLK_ON_SPROMCS <1<<5) +#define CCTRL4331_PCIE_MDIO_ON_SPROMCS (1<<6) +#define CCTRL4331_EXTPA_ON_GPIO2_5 (1<<7) +#define CCTRL4331_OVR_PIPEAUXCLKEN (1<<8) +#define CCTRL4331_OVR_PIPEAUXPWRDOWN (1<<9) +#define CCTRL4331_PCIE_AUXCLKEN <1<<10) +#define CCTRL4331_PCIE_PIPE_PLLDOWN <1<<11) +#define CCTRL4331_EXTPA_EN2 (1<<12) +#define CCTRL4331_EXT_LNA_A (1<<13) +#define CCTRL4331_BT_SHD0_ON_GPIO4 <1<<16) +#define CCTRL4331_BT_SHD1_ON_GPIO5 <1<<17) +#define CCTRL4331_EXTPA_ANA_EN (1<<24) + + +#define CST4331_XTAL_FREQ 0x00000001 +#define CST4331_SPROM_OTP_SEL_MASK 0x00000006 +#define CST4331_SPROM_OTP_SEL_SHIFT 1 +#define CST4331_SPROM_PRESENT 0x00000002 +#define CST4331_OTP_PRESENT 0x00000004 +#define CST4331_LDO_RF 0x00000008 +#define CST4331_LDO_PAR 0x00000010 #define RES4315_CBUCK_LPOM 1 @@ -1597,6 +1709,54 @@ typedef volatile struct { +#define SECI_MODE_UART 0x0 +#define SECI_MODE_SECI 0x1 +#define SECI_MODE_LEGACY_3WIRE_BT 0x2 +#define SECI_MODE_LEGACY_3WIRE_WLAN 0x3 +#define SECI_MODE_HALF_SECI 0x4 + +#define SECI_RESET (1 << 0) +#define SECI_RESET_BAR_UART (1 << 1) +#define SECI_ENAB_SECI_ECI (1 << 2) +#define SECI_ENAB_SECIOUT_DIS (1 << 3) +#define SECI_MODE_MASK 0x7 +#define SECI_MODE_SHIFT 4 +#define SECI_UPD_SECI (1 << 7) + + +#define CLKCTL_STS_SECI_CLK_REQ (1 << 8) +#define CLKCTL_STS_SECI_CLK_AVAIL (1 << 24) + +#define SECI_UART_MSR_CTS_STATE (1 << 0) +#define SECI_UART_MSR_RTS_STATE (1 << 1) +#define SECI_UART_SECI_IN_STATE (1 << 2) +#define SECI_UART_SECI_IN2_STATE (1 << 3) + + +#define SECI_UART_LCR_STOP_BITS (1 << 0) +#define SECI_UART_LCR_PARITY_EN (1 << 1) +#define SECI_UART_LCR_PARITY (1 << 2) +#define SECI_UART_LCR_RX_EN (1 << 3) +#define SECI_UART_LCR_LBRK_CTRL (1 << 4) +#define SECI_UART_LCR_TXO_EN (1 << 5) +#define SECI_UART_LCR_RTSO_EN (1 << 6) +#define SECI_UART_LCR_SLIPMODE_EN (1 << 7) +#define SECI_UART_LCR_RXCRC_CHK (1 << 8) +#define SECI_UART_LCR_TXCRC_INV (1 << 9) +#define SECI_UART_LCR_TXCRC_LSBF (1 << 10) +#define SECI_UART_LCR_TXCRC_EN (1 << 11) + +#define SECI_UART_MCR_TX_EN (1 << 0) +#define SECI_UART_MCR_PRTS (1 << 1) +#define SECI_UART_MCR_SWFLCTRL_EN (1 << 2) +#define SECI_UART_MCR_HIGHRATE_EN (1 << 3) +#define SECI_UART_MCR_LOOPBK_EN (1 << 4) +#define SECI_UART_MCR_AUTO_RTS (1 << 5) +#define SECI_UART_MCR_AUTO_TX_DIS (1 << 6) +#define SECI_UART_MCR_BAUD_ADJ_EN (1 << 7) +#define SECI_UART_MCR_XONOFF_RPT (1 << 9) + + #define ECI_BW_20 0x0 diff --git a/drivers/net/wireless/bcmdhd/include/sbconfig.h b/drivers/net/wireless/bcmdhd/include/sbconfig.h index 76f05ae34bd5..f45351a586cb 100644 --- a/drivers/net/wireless/bcmdhd/include/sbconfig.h +++ b/drivers/net/wireless/bcmdhd/include/sbconfig.h @@ -21,7 +21,7 @@ * software in any way with any other Broadcom software provided under a license * other than the GPL, without Broadcom's express prior written consent. * - * $Id: sbconfig.h,v 13.70 2008-03-28 19:17:04 Exp $ + * $Id: sbconfig.h 277737 2011-08-16 17:54:59Z $ */ diff --git a/drivers/net/wireless/bcmdhd/include/sbhnddma.h b/drivers/net/wireless/bcmdhd/include/sbhnddma.h index 05d0587bc205..77c413f75f0d 100644 --- a/drivers/net/wireless/bcmdhd/include/sbhnddma.h +++ b/drivers/net/wireless/bcmdhd/include/sbhnddma.h @@ -22,7 +22,7 @@ * software in any way with any other Broadcom software provided under a license * other than the GPL, without Broadcom's express prior written consent. * - * $Id: sbhnddma.h,v 13.20.2.3 2010-10-14 22:21:29 Exp $ + * $Id: sbhnddma.h 278779 2011-08-19 22:07:18Z $ */ @@ -217,7 +217,7 @@ typedef volatile struct { #define D64_XC_BL_SHIFT 18 -#define D64_XP_LD_MASK 0x00000fff +#define D64_XP_LD_MASK 0x00001fff #define D64_XS0_CD_MASK 0x00001fff @@ -260,7 +260,7 @@ typedef volatile struct { #define DMA_CTRL_USB_BOUNDRY4KB_WAR (1 << 4) -#define D64_RP_LD_MASK 0x00000fff +#define D64_RP_LD_MASK 0x00001fff #define D64_RS0_CD_MASK 0x00001fff diff --git a/drivers/net/wireless/bcmdhd/include/sbpcmcia.h b/drivers/net/wireless/bcmdhd/include/sbpcmcia.h index aba914bd014f..d84f69ab5617 100644 --- a/drivers/net/wireless/bcmdhd/include/sbpcmcia.h +++ b/drivers/net/wireless/bcmdhd/include/sbpcmcia.h @@ -21,7 +21,7 @@ * software in any way with any other Broadcom software provided under a license * other than the GPL, without Broadcom's express prior written consent. * - * $Id: sbpcmcia.h,v 13.48.12.6 2010-11-04 09:39:42 Exp $ + * $Id: sbpcmcia.h 277737 2011-08-16 17:54:59Z $ */ diff --git a/drivers/net/wireless/bcmdhd/include/sbsdio.h b/drivers/net/wireless/bcmdhd/include/sbsdio.h index 4280d5bf9c1f..7aaeb73f0100 100644 --- a/drivers/net/wireless/bcmdhd/include/sbsdio.h +++ b/drivers/net/wireless/bcmdhd/include/sbsdio.h @@ -24,7 +24,7 @@ * software in any way with any other Broadcom software provided under a license * other than the GPL, without Broadcom's express prior written consent. * - * $Id: sbsdio.h,v 13.34 2009-03-11 20:27:16 Exp $ + * $Id: sbsdio.h 277737 2011-08-16 17:54:59Z $ */ #ifndef _SBSDIO_H diff --git a/drivers/net/wireless/bcmdhd/include/sbsdpcmdev.h b/drivers/net/wireless/bcmdhd/include/sbsdpcmdev.h index 107a8b07c9e6..e5176483e9a1 100644 --- a/drivers/net/wireless/bcmdhd/include/sbsdpcmdev.h +++ b/drivers/net/wireless/bcmdhd/include/sbsdpcmdev.h @@ -22,7 +22,7 @@ * software in any way with any other Broadcom software provided under a license * other than the GPL, without Broadcom's express prior written consent. * - * $Id: sbsdpcmdev.h,v 13.38 2009-09-22 22:56:45 Exp $ + * $Id: sbsdpcmdev.h 282638 2011-09-08 21:18:10Z $ */ #ifndef _sbsdpcmdev_h_ diff --git a/drivers/net/wireless/bcmdhd/include/sbsocram.h b/drivers/net/wireless/bcmdhd/include/sbsocram.h index 1cba42238905..45c4dc208bda 100644 --- a/drivers/net/wireless/bcmdhd/include/sbsocram.h +++ b/drivers/net/wireless/bcmdhd/include/sbsocram.h @@ -21,7 +21,7 @@ * software in any way with any other Broadcom software provided under a license * other than the GPL, without Broadcom's express prior written consent. * - * $Id: sbsocram.h,v 13.15 2009-10-02 16:55:44 Exp $ + * $Id: sbsocram.h 277737 2011-08-16 17:54:59Z $ */ diff --git a/drivers/net/wireless/bcmdhd/include/sdio.h b/drivers/net/wireless/bcmdhd/include/sdio.h index ca932266a1b2..c8ac7b773fb9 100644 --- a/drivers/net/wireless/bcmdhd/include/sdio.h +++ b/drivers/net/wireless/bcmdhd/include/sdio.h @@ -22,7 +22,7 @@ * software in any way with any other Broadcom software provided under a license * other than the GPL, without Broadcom's express prior written consent. * - * $Id: sdio.h,v 13.27.14.1 2010-09-07 13:37:45 Exp $ + * $Id: sdio.h 277737 2011-08-16 17:54:59Z $ */ #ifndef _SDIO_H @@ -366,7 +366,7 @@ typedef volatile struct { * SDIO Commands and responses * * I/O only commands are: - * CMD0, CMD3, CMD5, CMD7, CMD15, CMD52, CMD53 + * CMD0, CMD3, CMD5, CMD7, CMD14, CMD15, CMD52, CMD53 * ------------------------------------------------ */ @@ -412,6 +412,7 @@ typedef volatile struct { #define CMD7_RCA_M BITFIELD_MASK(16) #define CMD7_RCA_S 16 + #define CMD14_RCA_M BITFIELD_MASK(16) #define CMD14_RCA_S 16 #define CMD14_SLEEP_M BITFIELD_MASK(1) diff --git a/drivers/net/wireless/bcmdhd/include/sdioh.h b/drivers/net/wireless/bcmdhd/include/sdioh.h index 3d37c7a7e30b..5f47d6f88cea 100644 --- a/drivers/net/wireless/bcmdhd/include/sdioh.h +++ b/drivers/net/wireless/bcmdhd/include/sdioh.h @@ -22,7 +22,7 @@ * software in any way with any other Broadcom software provided under a license * other than the GPL, without Broadcom's express prior written consent. * - * $Id: sdioh.h,v 13.17.2.3 2011-01-08 05:28:21 Exp $ + * $Id: sdioh.h 300017 2011-12-01 20:30:27Z $ */ #ifndef _SDIOH_H @@ -68,6 +68,10 @@ #define SD_ADMA_SysAddr 0x58 #define SD_SlotInterruptStatus 0x0FC #define SD_HostControllerVersion 0x0FE +#define SD_GPIO_Reg 0x100 +#define SD_GPIO_OE 0x104 +#define SD_GPIO_Enable 0x108 + /* SD specific registers in PCI config space */ #define SD_SlotInfo 0x40 @@ -409,4 +413,30 @@ /* SD_SlotInterruptStatus: Offset 0x0FC , size = bytes */ /* SD_HostControllerVersion : Offset 0x0FE , size = bytes */ +/* SDIO Host Control Register DMA Mode Definitions */ +#define SDIOH_SDMA_MODE 0 +#define SDIOH_ADMA1_MODE 1 +#define SDIOH_ADMA2_MODE 2 +#define SDIOH_ADMA2_64_MODE 3 + +#define ADMA2_ATTRIBUTE_VALID (1 << 0) /* ADMA Descriptor line valid */ +#define ADMA2_ATTRIBUTE_END (1 << 1) /* End of Descriptor */ +#define ADMA2_ATTRIBUTE_INT (1 << 2) /* Interrupt when line is done */ +#define ADMA2_ATTRIBUTE_ACT_NOP (0 << 4) /* Skip current line, go to next. */ +#define ADMA2_ATTRIBUTE_ACT_RSV (1 << 4) /* Same as NOP */ +#define ADMA1_ATTRIBUTE_ACT_SET (1 << 4) /* ADMA1 Only - set transfer length */ +#define ADMA2_ATTRIBUTE_ACT_TRAN (2 << 4) /* Transfer Data of one descriptor line. */ +#define ADMA2_ATTRIBUTE_ACT_LINK (3 << 4) /* Link Descriptor */ + +/* ADMA2 Descriptor Table Entry for 32-bit Address */ +typedef struct adma2_dscr_32b { + uint32 len_attr; + uint32 phys_addr; +} adma2_dscr_32b_t; + +/* ADMA1 Descriptor Table Entry */ +typedef struct adma1_dscr { + uint32 phys_addr_attr; +} adma1_dscr_t; + #endif /* _SDIOH_H */ diff --git a/drivers/net/wireless/bcmdhd/include/sdiovar.h b/drivers/net/wireless/bcmdhd/include/sdiovar.h index 2c5bcf97e910..55a3d3490c30 100644 --- a/drivers/net/wireless/bcmdhd/include/sdiovar.h +++ b/drivers/net/wireless/bcmdhd/include/sdiovar.h @@ -22,7 +22,7 @@ * software in any way with any other Broadcom software provided under a license * other than the GPL, without Broadcom's express prior written consent. * - * $Id: sdiovar.h,v 13.9 2009-12-08 22:30:15 Exp $ + * $Id: sdiovar.h 277737 2011-08-16 17:54:59Z $ */ #ifndef _sdiovar_h_ diff --git a/drivers/net/wireless/bcmdhd/include/siutils.h b/drivers/net/wireless/bcmdhd/include/siutils.h index c5a33832b585..6a7b93c7b977 100644 --- a/drivers/net/wireless/bcmdhd/include/siutils.h +++ b/drivers/net/wireless/bcmdhd/include/siutils.h @@ -22,7 +22,7 @@ * software in any way with any other Broadcom software provided under a license * other than the GPL, without Broadcom's express prior written consent. * - * $Id: siutils.h,v 13.251.2.10 2011-02-04 05:06:32 Exp $ + * $Id: siutils.h 285387 2011-09-21 18:38:37Z $ */ @@ -60,6 +60,7 @@ struct si_pub { typedef const struct si_pub si_t; + #define SI_OSH NULL #define BADIDX (SI_MAXCORES + 1) @@ -213,8 +214,34 @@ extern int si_corepciid(si_t *sih, uint func, uint16 *pcivendor, uint16 *pcidevi #define si_eci(sih) 0 #define si_eci_init(sih) (0) #define si_eci_notify_bt(sih, type, val) (0) +#define si_seci(sih) 0 +static INLINE void * si_seci_init(si_t *sih, uint8 use_seci) {return NULL;} +#define si_seci_down(sih) do { } while (0) + + +extern bool si_is_otp_disabled(si_t *sih); +extern bool si_is_otp_powered(si_t *sih); +extern void si_otp_power(si_t *sih, bool on); + + +extern bool si_is_sprom_available(si_t *sih); +extern bool si_is_sprom_enabled(si_t *sih); +extern void si_sprom_enable(si_t *sih, bool enable); +extern int si_cis_source(si_t *sih); +#define CIS_DEFAULT 0 +#define CIS_SROM 1 +#define CIS_OTP 2 + + +#define DEFAULT_FAB 0x0 +#define CSM_FAB7 0x1 +#define TSMC_FAB12 0x2 +#define SMIC_FAB4 0x3 +extern int si_otp_fabid(si_t *sih, uint16 *fabid, bool rw); +extern uint16 si_fabid(si_t *sih); + extern int si_devpath(si_t *sih, char *path, int size); @@ -244,4 +271,5 @@ extern uint32 si_pcieserdesreg(si_t *sih, uint32 mdioslave, uint32 offset, uint3 char *si_getnvramflvar(si_t *sih, const char *name); + #endif diff --git a/drivers/net/wireless/bcmdhd/include/trxhdr.h b/drivers/net/wireless/bcmdhd/include/trxhdr.h index 397006ab005a..b52fb15ba5c0 100644 --- a/drivers/net/wireless/bcmdhd/include/trxhdr.h +++ b/drivers/net/wireless/bcmdhd/include/trxhdr.h @@ -21,7 +21,7 @@ * software in any way with any other Broadcom software provided under a license * other than the GPL, without Broadcom's express prior written consent. * - * $Id: trxhdr.h,v 13.15.108.2 2010-11-15 17:57:30 Exp $ + * $Id: trxhdr.h 286295 2011-09-27 06:39:43Z $ */ #ifndef _TRX_HDR_H_ @@ -37,6 +37,7 @@ #define TRX_OVERLAYS 0x4 /* Contains an overlay header after the trx header */ #define TRX_MAX_OFFSET 3 /* Max number of individual files */ #define TRX_UNCOMP_IMAGE 0x20 /* Trx contains uncompressed rtecdc.bin image */ +#define TRX_ROMSIM_IMAGE 0x10 /* Trx contains ROM simulation image */ struct trx_header { uint32 magic; /* "HDR0" */ diff --git a/drivers/net/wireless/bcmdhd/include/typedefs.h b/drivers/net/wireless/bcmdhd/include/typedefs.h index 228b5dcf11c7..d0902fe80891 100644 --- a/drivers/net/wireless/bcmdhd/include/typedefs.h +++ b/drivers/net/wireless/bcmdhd/include/typedefs.h @@ -18,7 +18,7 @@ * Notwithstanding the above, under no circumstances may you combine this * software in any way with any other Broadcom software provided under a license * other than the GPL, without Broadcom's express prior written consent. - * $Id: typedefs.h,v 1.103.2.1 2010-05-11 18:19:28 Exp $ + * $Id: typedefs.h 290055 2011-10-15 21:26:26Z $ */ @@ -305,5 +305,8 @@ typedef float64 float_t; #define UNUSED_PARAMETER(x) (void)(x) +#define DISCARD_QUAL(ptr, type) ((type *)(uintptr)(ptr)) + + #include #endif diff --git a/drivers/net/wireless/bcmdhd/include/wlfc_proto.h b/drivers/net/wireless/bcmdhd/include/wlfc_proto.h index 7230d3b67ab0..d37105165bab 100644 --- a/drivers/net/wireless/bcmdhd/include/wlfc_proto.h +++ b/drivers/net/wireless/bcmdhd/include/wlfc_proto.h @@ -18,7 +18,7 @@ * Notwithstanding the above, under no circumstances may you combine this * software in any way with any other Broadcom software provided under a license * other than the GPL, without Broadcom's express prior written consent. -* $Id: wlfc_proto.h,v 1.1.6.2 2010-05-08 01:30:41 Exp $ +* $Id: wlfc_proto.h 277737 2011-08-16 17:54:59Z $ * */ #ifndef __wlfc_proto_definitions_h__ diff --git a/drivers/net/wireless/bcmdhd/include/wlioctl.h b/drivers/net/wireless/bcmdhd/include/wlioctl.h index 9357552c9194..676068c0b387 100644 --- a/drivers/net/wireless/bcmdhd/include/wlioctl.h +++ b/drivers/net/wireless/bcmdhd/include/wlioctl.h @@ -24,7 +24,7 @@ * software in any way with any other Broadcom software provided under a license * other than the GPL, without Broadcom's express prior written consent. * - * $Id: wlioctl.h,v 1.767.2.38 2011-02-01 23:04:28 Exp $ + * $Id: wlioctl.h 302303 2011-12-10 07:51:07Z $ */ @@ -65,8 +65,8 @@ typedef struct wl_action_frame { typedef struct ssid_info { - uint8 ssid_len; - uint8 ssid[32]; + uint8 ssid_len; + uint8 ssid[32]; } ssid_info_t; typedef struct wl_af_params { @@ -191,6 +191,7 @@ typedef struct wlc_ssid { #define WL_SCANFLAGS_PROHIBITED 0x04 #define WL_SCAN_PARAMS_SSID_MAX 10 + typedef struct wl_scan_params { wlc_ssid_t ssid; struct ether_addr bssid; @@ -376,6 +377,8 @@ typedef struct { #define NRATE_SGI_SHIFT 23 #define NRATE_LDPC_CODING 0x00400000 #define NRATE_LDPC_SHIFT 22 +#define NRATE_BCMC_OVERRIDE 0x00200000 +#define NRATE_BCMC_SHIFT 21 #define NRATE_STF_SISO 0 #define NRATE_STF_CDD 1 @@ -555,7 +558,7 @@ typedef enum sup_auth_status { #define CRYPTO_ALGO_AES_OCB_MSDU 5 #define CRYPTO_ALGO_AES_OCB_MPDU 6 #define CRYPTO_ALGO_NALG 7 -#define CRYPTO_ALGO_PMK 12 +#define CRYPTO_ALGO_PMK 12 #define WSEC_GEN_MIC_ERROR 0x0001 #define WSEC_GEN_REPLAY 0x0002 @@ -617,9 +620,9 @@ typedef struct { #define WPA2_AUTH_PSK 0x0080 #define BRCM_AUTH_PSK 0x0100 #define BRCM_AUTH_DPT 0x0200 -#define WPA2_AUTH_MFP 0x1000 -#define WPA2_AUTH_TPK 0x2000 -#define WPA2_AUTH_FT 0x4000 +#define WPA2_AUTH_MFP 0x1000 +#define WPA2_AUTH_TPK 0x2000 +#define WPA2_AUTH_FT 0x4000 #define MAXPMKID 16 @@ -649,12 +652,12 @@ typedef struct wl_assoc_info { uint32 resp_len; uint32 flags; struct dot11_assoc_req req; - struct ether_addr reassoc_bssid; + struct ether_addr reassoc_bssid; struct dot11_assoc_resp resp; } wl_assoc_info_t; -#define WLC_ASSOC_REQ_IS_REASSOC 0x01 +#define WLC_ASSOC_REQ_IS_REASSOC 0x01 typedef struct { @@ -851,6 +854,7 @@ typedef struct wlc_iov_trx_s { #define WLC_GET_SSID 25 #define WLC_SET_SSID 26 #define WLC_RESTART 27 +#define WLC_TERMINATED 28 #define WLC_GET_CHANNEL 29 #define WLC_SET_CHANNEL 30 @@ -1203,7 +1207,7 @@ typedef struct { #define WL_AUTH_OPEN_SYSTEM 0 #define WL_AUTH_SHARED_KEY 1 -#define WL_AUTH_OPEN_SHARED 2 +#define WL_AUTH_OPEN_SHARED 3 #define WL_RADIO_SW_DISABLE (1<<0) @@ -1280,18 +1284,17 @@ typedef struct wl_po { #define WL_CHAN_FREQ_RANGE_5GM 2 #define WL_CHAN_FREQ_RANGE_5GH 3 -#define WL_CHAN_FREQ_RANGE_5GLL_VER2 4 -#define WL_CHAN_FREQ_RANGE_5GLH_VER2 5 -#define WL_CHAN_FREQ_RANGE_5GML_VER2 6 -#define WL_CHAN_FREQ_RANGE_5GMH_VER2 7 -#define WL_CHAN_FREQ_RANGE_5GH_VER2 8 - #define WL_CHAN_FREQ_RANGE_5GLL_5BAND 4 #define WL_CHAN_FREQ_RANGE_5GLH_5BAND 5 #define WL_CHAN_FREQ_RANGE_5GML_5BAND 6 #define WL_CHAN_FREQ_RANGE_5GMH_5BAND 7 #define WL_CHAN_FREQ_RANGE_5GH_5BAND 8 +#define WL_CHAN_FREQ_RANGE_5G_BAND0 1 +#define WL_CHAN_FREQ_RANGE_5G_BAND1 2 +#define WL_CHAN_FREQ_RANGE_5G_BAND2 3 +#define WL_CHAN_FREQ_RANGE_5G_BAND3 4 + #define WLC_PHY_TYPE_A 0 #define WLC_PHY_TYPE_B 1 @@ -1363,7 +1366,7 @@ typedef struct wl_po { #define PM_MAX 1 #define PM_FAST 2 -#define LISTEN_INTERVAL 10 +#define LISTEN_INTERVAL 10 #define INTERFERE_OVRRIDE_OFF -1 #define INTERFERE_NONE 0 @@ -1493,6 +1496,7 @@ typedef struct wl_sampledata { #define WL_P2P_VAL 0x00000200 #define WL_TXRX_VAL 0x00000400 #define WL_MCHAN_VAL 0x00000800 +#define WL_TDLS_VAL 0x00001000 #define WL_LED_NUMGPIO 16 @@ -1546,7 +1550,7 @@ typedef struct wl_sampledata { #define WL_JOIN_PREF_WPA 2 #define WL_JOIN_PREF_BAND 3 #define WL_JOIN_PREF_RSSI_DELTA 4 -#define WL_JOIN_PREF_TRANS_PREF 5 +#define WL_JOIN_PREF_TRANS_PREF 5 #define WLJP_BAND_ASSOC_PREF 255 @@ -1797,17 +1801,19 @@ struct wl_msglevel2 { }; typedef struct wl_mkeep_alive_pkt { - uint16 version; - uint16 length; + uint16 version; + uint16 length; uint32 period_msec; uint16 len_bytes; - uint8 keep_alive_id; + uint8 keep_alive_id; uint8 data[1]; } wl_mkeep_alive_pkt_t; -#define WL_MKEEP_ALIVE_VERSION 1 -#define WL_MKEEP_ALIVE_FIXED_LEN OFFSETOF(wl_mkeep_alive_pkt_t, data) -#define WL_MKEEP_ALIVE_PRECISION 500 +#define WL_MKEEP_ALIVE_VERSION 1 +#define WL_MKEEP_ALIVE_FIXED_LEN OFFSETOF(wl_mkeep_alive_pkt_t, data) +#define WL_MKEEP_ALIVE_PRECISION 500 + + #define WLC_ROAM_TRIGGER_DEFAULT 0 #define WLC_ROAM_TRIGGER_BANDWIDTH 1 @@ -1897,7 +1903,7 @@ typedef struct wl_pfn_param { uint8 mscan; uint8 repeat; uint8 exp; - int32 slow_freq; + int32 slow_freq; } wl_pfn_param_t; typedef struct wl_pfn_bssid { @@ -2016,8 +2022,31 @@ typedef struct wl_keep_alive_pkt { +#define MAX_WAKE_PACKET_BYTES 128 + + +typedef struct pm_wake_packet { + uint32 status; + uint32 pattern_id; + uint32 original_packet_size; + uint32 saved_packet_size; + uchar packet[MAX_WAKE_PACKET_BYTES]; +} pm_wake_packet_t; + + + +#define PKT_FILTER_MODE_FORWARD_ON_MATCH 1 + +#define PKT_FILTER_MODE_DISABLE 2 + +#define PKT_FILTER_MODE_PKT_CACHE_ON_MATCH 4 + +#define PKT_FILTER_MODE_PKT_FORWARD_OFF_DEFAULT 8 + + typedef enum wl_pkt_filter_type { - WL_PKT_FILTER_TYPE_PATTERN_MATCH + WL_PKT_FILTER_TYPE_PATTERN_MATCH, + WL_PKT_FILTER_TYPE_MAGIC_PATTERN_MATCH } wl_pkt_filter_type_t; #define WL_PKT_FILTER_TYPE wl_pkt_filter_type_t @@ -2550,6 +2579,12 @@ typedef struct wl_phycal_state { #define WL_PHYCAL_STAT_FIXED_LEN OFFSETOF(wl_phycal_state_t, phycal_core) #endif +#ifdef WLDSTA +typedef struct wl_dsta_if { + struct ether_addr addr; +} wl_dsta_if_t; +#endif + #ifdef WLP2P typedef struct wl_p2p_disc_st { diff --git a/drivers/net/wireless/bcmdhd/linux_osl.c b/drivers/net/wireless/bcmdhd/linux_osl.c index b3fcdd2f1ade..4ef7bf7b24dc 100644 --- a/drivers/net/wireless/bcmdhd/linux_osl.c +++ b/drivers/net/wireless/bcmdhd/linux_osl.c @@ -21,7 +21,7 @@ * software in any way with any other Broadcom software provided under a license * other than the GPL, without Broadcom's express prior written consent. * - * $Id: linux_osl.c,v 1.168.2.7 2011-01-27 17:01:13 Exp $ + * $Id: linux_osl.c,v 1.168.2.7 2011-01-27 17:01:13 $ */ @@ -226,17 +226,16 @@ osl_attach(void *pdev, uint bustype, bool pkttag) } if (!bcm_static_skb) { - void *skb_buff_ptr = dhd_os_prealloc(osh, 4, 0); - - if (skb_buff_ptr) { - bcm_static_skb = (bcm_static_pkt_t *)((char *)bcm_static_buf + 2048); - bcopy(skb_buff_ptr, bcm_static_skb, sizeof(struct sk_buff *) * 16); - for (i = 0; i < STATIC_PKT_MAX_NUM * 2; i++) - bcm_static_skb->pkt_use[i] = 0; - sema_init(&bcm_static_skb->osl_pkt_sem, 1); - } else { - printk("can not alloc static skb buffers\n"); - } + int i; + void *skb_buff_ptr = 0; + bcm_static_skb = (bcm_static_pkt_t *)((char *)bcm_static_buf + 2048); + skb_buff_ptr = dhd_os_prealloc(osh, 4, 0); + + bcopy(skb_buff_ptr, bcm_static_skb, sizeof(struct sk_buff *) * 16); + for (i = 0; i < STATIC_PKT_MAX_NUM * 2; i++) + bcm_static_skb->pkt_use[i] = 0; + + sema_init(&bcm_static_skb->osl_pkt_sem, 1); } #endif diff --git a/drivers/net/wireless/bcmdhd/siutils.c b/drivers/net/wireless/bcmdhd/siutils.c index 22aa41265763..4b7156303553 100644 --- a/drivers/net/wireless/bcmdhd/siutils.c +++ b/drivers/net/wireless/bcmdhd/siutils.c @@ -22,7 +22,7 @@ * software in any way with any other Broadcom software provided under a license * other than the GPL, without Broadcom's express prior written consent. * - * $Id: siutils.c,v 1.813.2.36 2011-02-10 23:43:55 Exp $ + * $Id: siutils.c,v 1.813.2.36 2011-02-10 23:43:55 $ */ #include @@ -213,11 +213,11 @@ si_buscore_setup(si_info_t *sii, chipcregs_t *cc, uint bustype, uint32 savewin, /* figure out bus/orignal core idx */ sii->pub.buscoretype = NODEV_CORE_ID; - sii->pub.buscorerev = NOREV; + sii->pub.buscorerev = (uint)NOREV; sii->pub.buscoreidx = BADIDX; pci = pcie = FALSE; - pcirev = pcierev = NOREV; + pcirev = pcierev = (uint)NOREV; pciidx = pcieidx = BADIDX; for (i = 0; i < sii->numcores; i++) { @@ -365,6 +365,19 @@ si_doattach(si_info_t *sii, uint devid, osl_t *osh, void *regs, return NULL; } +#if defined(HW_OOB) + if (CHIPID(sih->chip) == BCM43362_CHIP_ID) { + uint32 gpiocontrol, addr; + addr = SI_ENUM_BASE + OFFSETOF(chipcregs_t, gpiocontrol); + gpiocontrol = bcmsdh_reg_read(sdh, addr, 4); + gpiocontrol |= 0x2; + bcmsdh_reg_write(sdh, addr, 4, gpiocontrol); + bcmsdh_cfg_write(sdh, SDIO_FUNC_1, 0x10005, 0xf, NULL); + bcmsdh_cfg_write(sdh, SDIO_FUNC_1, 0x10006, 0x0, NULL); + bcmsdh_cfg_write(sdh, SDIO_FUNC_1, 0x10007, 0x2, NULL); + } +#endif + if ((CHIPID(sih->chip) == BCM4329_CHIP_ID) && (sih->chiprev == 0) && (sih->chippkg != BCM4329_289PIN_PKG_ID)) { sih->chippkg = BCM4329_182PIN_PKG_ID; @@ -401,8 +414,9 @@ si_doattach(si_info_t *sii, uint devid, osl_t *osh, void *regs, } /* assume current core is CC */ - if ((sii->pub.ccrev == 0x25) && ((CHIPID(sih->chip) == BCM43236_CHIP_ID || + if ((sii->pub.ccrev == 0x25) && ((CHIPID(sih->chip) == BCM43234_CHIP_ID || CHIPID(sih->chip) == BCM43235_CHIP_ID || + CHIPID(sih->chip) == BCM43236_CHIP_ID || CHIPID(sih->chip) == BCM43238_CHIP_ID) && (CHIPREV(sii->pub.chiprev) == 0))) { @@ -1093,6 +1107,126 @@ si_watchdog_ms(si_t *sih, uint32 ms) +/* return the slow clock source - LPO, XTAL, or PCI */ +static uint +si_slowclk_src(si_info_t *sii) +{ + chipcregs_t *cc; + + ASSERT(SI_FAST(sii) || si_coreid(&sii->pub) == CC_CORE_ID); + + if (sii->pub.ccrev < 6) { + if ((BUSTYPE(sii->pub.bustype) == PCI_BUS) && + (OSL_PCI_READ_CONFIG(sii->osh, PCI_GPIO_OUT, sizeof(uint32)) & + PCI_CFG_GPIO_SCS)) + return (SCC_SS_PCI); + else + return (SCC_SS_XTAL); + } else if (sii->pub.ccrev < 10) { + cc = (chipcregs_t *)si_setcoreidx(&sii->pub, sii->curidx); + return (R_REG(sii->osh, &cc->slow_clk_ctl) & SCC_SS_MASK); + } else /* Insta-clock */ + return (SCC_SS_XTAL); +} + +/* return the ILP (slowclock) min or max frequency */ +static uint +si_slowclk_freq(si_info_t *sii, bool max_freq, chipcregs_t *cc) +{ + uint32 slowclk; + uint div; + + ASSERT(SI_FAST(sii) || si_coreid(&sii->pub) == CC_CORE_ID); + + /* shouldn't be here unless we've established the chip has dynamic clk control */ + ASSERT(R_REG(sii->osh, &cc->capabilities) & CC_CAP_PWR_CTL); + + slowclk = si_slowclk_src(sii); + if (sii->pub.ccrev < 6) { + if (slowclk == SCC_SS_PCI) + return (max_freq ? (PCIMAXFREQ / 64) : (PCIMINFREQ / 64)); + else + return (max_freq ? (XTALMAXFREQ / 32) : (XTALMINFREQ / 32)); + } else if (sii->pub.ccrev < 10) { + div = 4 * + (((R_REG(sii->osh, &cc->slow_clk_ctl) & SCC_CD_MASK) >> SCC_CD_SHIFT) + 1); + if (slowclk == SCC_SS_LPO) + return (max_freq ? LPOMAXFREQ : LPOMINFREQ); + else if (slowclk == SCC_SS_XTAL) + return (max_freq ? (XTALMAXFREQ / div) : (XTALMINFREQ / div)); + else if (slowclk == SCC_SS_PCI) + return (max_freq ? (PCIMAXFREQ / div) : (PCIMINFREQ / div)); + else + ASSERT(0); + } else { + /* Chipc rev 10 is InstaClock */ + div = R_REG(sii->osh, &cc->system_clk_ctl) >> SYCC_CD_SHIFT; + div = 4 * (div + 1); + return (max_freq ? XTALMAXFREQ : (XTALMINFREQ / div)); + } + return (0); +} + +static void +si_clkctl_setdelay(si_info_t *sii, void *chipcregs) +{ + chipcregs_t *cc = (chipcregs_t *)chipcregs; + uint slowmaxfreq, pll_delay, slowclk; + uint pll_on_delay, fref_sel_delay; + + pll_delay = PLL_DELAY; + + /* If the slow clock is not sourced by the xtal then add the xtal_on_delay + * since the xtal will also be powered down by dynamic clk control logic. + */ + + slowclk = si_slowclk_src(sii); + if (slowclk != SCC_SS_XTAL) + pll_delay += XTAL_ON_DELAY; + + /* Starting with 4318 it is ILP that is used for the delays */ + slowmaxfreq = si_slowclk_freq(sii, (sii->pub.ccrev >= 10) ? FALSE : TRUE, cc); + + pll_on_delay = ((slowmaxfreq * pll_delay) + 999999) / 1000000; + fref_sel_delay = ((slowmaxfreq * FREF_DELAY) + 999999) / 1000000; + + W_REG(sii->osh, &cc->pll_on_delay, pll_on_delay); + W_REG(sii->osh, &cc->fref_sel_delay, fref_sel_delay); +} + +/* initialize power control delay registers */ +void +si_clkctl_init(si_t *sih) +{ + si_info_t *sii; + uint origidx = 0; + chipcregs_t *cc; + bool fast; + + if (!CCCTL_ENAB(sih)) + return; + + sii = SI_INFO(sih); + fast = SI_FAST(sii); + if (!fast) { + origidx = sii->curidx; + if ((cc = (chipcregs_t *)si_setcore(sih, CC_CORE_ID, 0)) == NULL) + return; + } else if ((cc = (chipcregs_t *)CCREGS_FAST(sii)) == NULL) + return; + ASSERT(cc != NULL); + + /* set all Instaclk chip ILP to 1 MHz */ + if (sih->ccrev >= 10) + SET_REG(sii->osh, &cc->system_clk_ctl, SYCC_CD_MASK, + (ILP_DIV_1MHZ << SYCC_CD_SHIFT)); + + si_clkctl_setdelay(sii, (void *)(uintptr)cc); + + if (!fast) + si_setcoreidx(sih, origidx); +} + /* change logical "focus" to the gpio core for optimized access */ void * si_gpiosetcore(si_t *sih) @@ -1718,3 +1852,56 @@ si_deviceremoved(si_t *sih) } return FALSE; } + +bool +si_is_sprom_available(si_t *sih) +{ + if (sih->ccrev >= 31) { + si_info_t *sii; + uint origidx; + chipcregs_t *cc; + uint32 sromctrl; + + if ((sih->cccaps & CC_CAP_SROM) == 0) + return FALSE; + + sii = SI_INFO(sih); + origidx = sii->curidx; + cc = si_setcoreidx(sih, SI_CC_IDX); + sromctrl = R_REG(sii->osh, &cc->sromcontrol); + si_setcoreidx(sih, origidx); + return (sromctrl & SRC_PRESENT); + } + + switch (CHIPID(sih->chip)) { + case BCM4312_CHIP_ID: + return ((sih->chipst & CST4312_SPROM_OTP_SEL_MASK) != CST4312_OTP_SEL); + case BCM4325_CHIP_ID: + return (sih->chipst & CST4325_SPROM_SEL) != 0; + case BCM4322_CHIP_ID: + case BCM43221_CHIP_ID: + case BCM43231_CHIP_ID: + case BCM43222_CHIP_ID: + case BCM43111_CHIP_ID: + case BCM43112_CHIP_ID: + case BCM4342_CHIP_ID: + { + uint32 spromotp; + spromotp = (sih->chipst & CST4322_SPROM_OTP_SEL_MASK) >> + CST4322_SPROM_OTP_SEL_SHIFT; + return (spromotp & CST4322_SPROM_PRESENT) != 0; + } + case BCM4329_CHIP_ID: + return (sih->chipst & CST4329_SPROM_SEL) != 0; + case BCM4315_CHIP_ID: + return (sih->chipst & CST4315_SPROM_SEL) != 0; + case BCM4319_CHIP_ID: + return (sih->chipst & CST4319_SPROM_SEL) != 0; + case BCM4330_CHIP_ID: + return (sih->chipst & CST4330_SPROM_PRESENT) != 0; + case BCM4313_CHIP_ID: + return (sih->chipst & CST4313_SPROM_PRESENT) != 0; + default: + return TRUE; + } +} diff --git a/drivers/net/wireless/bcmdhd/wl_android.c b/drivers/net/wireless/bcmdhd/wl_android.c index b6804817240a..dc32f17a91fa 100644 --- a/drivers/net/wireless/bcmdhd/wl_android.c +++ b/drivers/net/wireless/bcmdhd/wl_android.c @@ -2,13 +2,13 @@ * Linux cfg80211 driver - Android related functions * * Copyright (C) 1999-2011, Broadcom Corporation - * + * * Unless you and Broadcom execute a separate written software license * agreement governing use of this software, this software is licensed to you * under the terms of the GNU General Public License version 2 (the "GPL"), * available at http://www.broadcom.com/licenses/GPLv2.php, with the * following added to such license: - * + * * As a special exception, the copyright holders of this software give you * permission to link this software with independent modules, and to copy and * distribute the resulting executable under terms of your choice, provided that @@ -16,7 +16,7 @@ * the license of that module. An independent module is a module which is not * derived from this software. The special exception does not apply to any * modifications of the software. - * + * * Notwithstanding the above, under no circumstances may you combine this * software in any way with any other Broadcom software provided under a license * other than the GPL, without Broadcom's express prior written consent. diff --git a/drivers/net/wireless/bcmdhd/wl_cfg80211.c b/drivers/net/wireless/bcmdhd/wl_cfg80211.c index b7696eb2036b..c0857b6d95b4 100644 --- a/drivers/net/wireless/bcmdhd/wl_cfg80211.c +++ b/drivers/net/wireless/bcmdhd/wl_cfg80211.c @@ -2,13 +2,13 @@ * Linux cfg80211 driver * * Copyright (C) 1999-2011, Broadcom Corporation - * + * * Unless you and Broadcom execute a separate written software license * agreement governing use of this software, this software is licensed to you * under the terms of the GNU General Public License version 2 (the "GPL"), * available at http://www.broadcom.com/licenses/GPLv2.php, with the * following added to such license: - * + * * As a special exception, the copyright holders of this software give you * permission to link this software with independent modules, and to copy and * distribute the resulting executable under terms of your choice, provided that @@ -16,7 +16,7 @@ * the license of that module. An independent module is a module which is not * derived from this software. The special exception does not apply to any * modifications of the software. - * + * * Notwithstanding the above, under no circumstances may you combine this * software in any way with any other Broadcom software provided under a license * other than the GPL, without Broadcom's express prior written consent. @@ -65,8 +65,8 @@ #include #include -static struct sdio_func *cfg80211_sdio_func; -static struct wl_priv *wlcfg_drv_priv; +static struct device *cfg80211_parent_dev = NULL; +static struct wl_priv *wlcfg_drv_priv = NULL; u32 wl_dbg_level = WL_DBG_ERR; @@ -103,6 +103,11 @@ static int wl_cfg80211_btcoex_init(struct wl_priv *wl); static void wl_cfg80211_btcoex_deinit(struct wl_priv *wl); #endif +/* Set this to 1 to use a seperate interface (p2p0) + * for p2p operations. + */ +#define ENABLE_P2P_INTERFACE 1 + /* This is to override regulatory domains defined in cfg80211 module (reg.c) * By default world regulatory domain defined in reg.c puts the flags NL80211_RRF_PASSIVE_SCAN * and NL80211_RRF_NO_IBSS for 5GHz channels (for 36..48 and 149..165). @@ -224,7 +229,7 @@ static s32 wl_cfg80211_del_pmksa(struct wiphy *wiphy, struct net_device *dev, struct cfg80211_pmksa *pmksa); static s32 wl_cfg80211_flush_pmksa(struct wiphy *wiphy, struct net_device *dev); -static void wl_notify_escan_complete(struct wl_priv *wl, bool aborted); +static void wl_notify_escan_complete(struct wl_priv *wl, struct net_device *ndev, bool aborted); /* * event & event Q handlers for cfg80211 interfaces */ @@ -261,8 +266,7 @@ static s32 wl_notify_pfn_status(struct wl_priv *wl, struct net_device *ndev, /* * register/deregister sdio function */ -struct sdio_func *wl_cfg80211_get_sdio_func(void); -static void wl_clear_sdio_func(void); +static void wl_cfg80211_clear_parent_dev(void); /* * ioctl utilites @@ -285,10 +289,10 @@ static s32 wl_set_retry(struct net_device *dev, u32 retry, bool l); /* * wl profile utilities */ -static s32 wl_update_prof(struct wl_priv *wl, const wl_event_msg_t *e, - void *data, s32 item); -static void *wl_read_prof(struct wl_priv *wl, s32 item); -static void wl_init_prof(struct wl_priv *wl); +static s32 wl_update_prof(struct wl_priv *wl, struct net_device *ndev, + const wl_event_msg_t *e, void *data, s32 item); +static void *wl_read_prof(struct wl_priv *wl, struct net_device *ndev, s32 item); +static void wl_init_prof(struct wl_priv *wl, struct net_device *ndev); /* * cfg80211 connect utilites @@ -316,7 +320,6 @@ static s32 wl_mrg_ie(struct wl_priv *wl, u8 *ie_stream, u16 ie_size); static s32 wl_cp_ie(struct wl_priv *wl, u8 *dst, u16 dst_size); static u32 wl_get_ielen(struct wl_priv *wl); -static s32 wl_mode_to_nl80211_iftype(s32 mode); static struct wireless_dev *wl_alloc_wdev(struct device *sdiofunc_dev); static void wl_free_wdev(struct wl_priv *wl); @@ -324,6 +327,7 @@ static void wl_free_wdev(struct wl_priv *wl); static s32 wl_inform_bss(struct wl_priv *wl); static s32 wl_inform_single_bss(struct wl_priv *wl, struct wl_bss_info *bi); static s32 wl_update_bss_info(struct wl_priv *wl, struct net_device *ndev); +static chanspec_t wl_cfg80211_get_shared_freq(struct wiphy *wiphy); static s32 wl_add_keyext(struct wiphy *wiphy, struct net_device *dev, u8 key_idx, const u8 *mac_addr, @@ -426,7 +430,7 @@ static __used s32 wl_update_pmklist(struct net_device *dev, /* * debufs support */ -static int wl_debugfs_add_netdev_params(struct wl_priv *wl); +static int wl_debugfs_add_netdev_params(struct wl_priv *wl, struct net_device *ndev); static void wl_debugfs_remove_netdev(struct wl_priv *wl); /* @@ -446,10 +450,10 @@ int dhd_start_xmit(struct sk_buff *skb, struct net_device *net); #define CHECK_SYS_UP(wlpriv) \ do { \ - if (unlikely(!wl_get_drv_status(wlpriv, READY))) { \ - WL_INFO(("device is not ready : status (%d)\n", \ - (int)wlpriv->status)); \ - return -EIO; \ + struct net_device *ndev = wl_to_prmry_ndev(wlpriv); \ + if (unlikely(!wl_get_drv_status(wlpriv, READY, ndev))) { \ + WL_INFO(("device is not ready\n")); \ + return -EIO; \ } \ } while (0) @@ -591,7 +595,7 @@ static const u32 __wl_cipher_suites[] = { WLAN_CIPHER_SUITE_WEP104, WLAN_CIPHER_SUITE_TKIP, WLAN_CIPHER_SUITE_CCMP, - WLAN_CIPHER_SUITE_AES_CMAC + WLAN_CIPHER_SUITE_AES_CMAC, }; /* There isn't a lot of sense in it, but you can transmit anything you like */ @@ -742,6 +746,40 @@ wl_validate_wps_ie(char *wps_ie, bool *pbc) } } +static chanspec_t wl_cfg80211_get_shared_freq(struct wiphy *wiphy) +{ + chanspec_t chspec; + int err = 0; + struct wl_priv *wl = wiphy_priv(wiphy); + struct net_device *dev = wl_to_prmry_ndev(wl); + struct ether_addr bssid; + struct wl_bss_info *bss = NULL; + + if ((err = wldev_ioctl(dev, WLC_GET_BSSID, &bssid, sizeof(bssid), false))) { + /* STA interface is not associated. So start the new interface on a temp + * channel . Later proper channel will be applied by the above framework + * via set_channel (cfg80211 API). + */ + WL_DBG(("Not associated. Return a temp channel. \n")); + return wf_chspec_aton(WL_P2P_TEMP_CHAN); + } + + + *(u32 *) wl->extra_buf = htod32(WL_EXTRA_BUF_MAX); + if ((err = wldev_ioctl(dev, WLC_GET_BSS_INFO, wl->extra_buf, + sizeof(WL_EXTRA_BUF_MAX), false))) { + WL_ERR(("Failed to get associated bss info, use temp channel \n")); + chspec = wf_chspec_aton(WL_P2P_TEMP_CHAN); + } + else { + bss = (struct wl_bss_info *) (wl->extra_buf + 4); + chspec = bss->chanspec; + WL_DBG(("Valid BSS Found. chanspec:%d \n", bss->chanspec)); + } + + return chspec; +} + static struct net_device* wl_cfg80211_add_monitor_if(char *name) { int ret = 0; @@ -760,7 +798,6 @@ wl_cfg80211_add_virtual_iface(struct wiphy *wiphy, char *name, s32 err; s32 timeout = -1; s32 wlif_type = -1; - s32 index = 0; s32 mode = 0; chanspec_t chspec; struct wl_priv *wl = wiphy_priv(wiphy); @@ -768,6 +805,8 @@ wl_cfg80211_add_virtual_iface(struct wiphy *wiphy, char *name, dhd_pub_t *dhd = (dhd_pub_t *)(wl->pub); int (*net_attach)(dhd_pub_t *dhdp, int ifidx); bool rollback_lock = false; + /* Use primary I/F for sending cmds down to firmware */ + _ndev = wl_to_prmry_ndev(wl); WL_DBG(("if name: %s, type: %d\n", name, type)); switch (type) { @@ -800,6 +839,8 @@ wl_cfg80211_add_virtual_iface(struct wiphy *wiphy, char *name, WL_ERR(("name is NULL\n")); return NULL; } + if (wl->iface_cnt == IFACE_MAX_CNT) + return ERR_PTR(-ENOMEM); if (wl->p2p_supported && (wlif_type != -1)) { if (wl_get_p2p_status(wl, IF_DELETING)) { /* wait till IF_DEL is complete @@ -828,7 +869,7 @@ wl_cfg80211_add_virtual_iface(struct wiphy *wiphy, char *name, return ERR_PTR(-EAGAIN); } } - if (!p2p_on(wl) && strstr(name, WL_P2P_INTERFACE_PREFIX)) { + if (!p2p_is_on(wl) && strstr(name, WL_P2P_INTERFACE_PREFIX)) { p2p_on(wl) = true; wl_cfgp2p_set_firm_p2p(wl); wl_cfgp2p_init_discovery(wl); @@ -837,8 +878,11 @@ wl_cfg80211_add_virtual_iface(struct wiphy *wiphy, char *name, strncpy(wl->p2p->vir_ifname, name, IFNAMSIZ - 1); wl_cfgp2p_generate_bss_mac(&dhd->mac, &wl->p2p->dev_addr, &wl->p2p->int_addr); - /* Temporary use channel 11, in case GO will be changed with set_channel API */ - chspec = wf_chspec_aton(WL_P2P_TEMP_CHAN); + /* In concurrency case, STA may be already associated in a particular channel. + * so retrieve the current channel of primary interface and then start the virtual + * interface on that. + */ + chspec = wl_cfg80211_get_shared_freq(wiphy); /* For P2P mode, use P2P-specific driver features to create the * bss: "wl p2p_ifadd" @@ -865,26 +909,21 @@ wl_cfg80211_add_virtual_iface(struct wiphy *wiphy, char *name, vwdev->wiphy = wl->wdev->wiphy; WL_INFO((" virtual interface(%s) is created memalloc done \n", wl->p2p->vir_ifname)); - index = alloc_idx_vwdev(wl); - wl->vwdev[index] = vwdev; - vwdev->iftype = - (wlif_type == WL_P2P_IF_CLIENT) ? NL80211_IFTYPE_STATION - : NL80211_IFTYPE_AP; + vwdev->iftype = type; _ndev = wl_to_p2p_bss_ndev(wl, P2PAPI_BSSCFG_CONNECTION); _ndev->ieee80211_ptr = vwdev; SET_NETDEV_DEV(_ndev, wiphy_dev(vwdev->wiphy)); vwdev->netdev = _ndev; - wl_set_drv_status(wl, READY); + wl_set_drv_status(wl, READY, _ndev); wl->p2p->vif_created = true; - set_mode_by_netdev(wl, _ndev, mode); - WL_DBG((" virtual interface(%s) wl->wdev %p wl->wdev->netdev %p vwdev %p vwdev->netdev %p\n", - wl->p2p->vir_ifname, wl->wdev, wl->wdev->netdev, vwdev, vwdev->netdev)); + wl_set_mode_by_netdev(wl, _ndev, mode); net_attach = wl_to_p2p_bss_private(wl, P2PAPI_BSSCFG_CONNECTION); if (rtnl_is_locked()) { rtnl_unlock(); rollback_lock = true; } if (net_attach && !net_attach(dhd, _ndev->ifindex)) { + wl_alloc_netinfo(wl, _ndev, vwdev, mode); WL_DBG((" virtual interface(%s) is " "created net attach done\n", wl->p2p->vir_ifname)); } else { @@ -917,10 +956,18 @@ wl_cfg80211_del_virtual_iface(struct wiphy *wiphy, struct net_device *dev) s32 timeout = -1; s32 ret = 0; WL_DBG(("Enter\n")); + + if (wl->p2p_net == dev) { + /* Since there is no ifidx corresponding to p2p0, cmds to + * firmware should be routed through primary I/F + */ + dev = wl_to_prmry_ndev(wl); + } + if (wl->p2p_supported) { memcpy(p2p_mac.octet, wl->p2p->int_addr.octet, ETHER_ADDR_LEN); if (wl->p2p->vif_created) { - if (wl_get_drv_status(wl, SCANNING)) { + if (wl_get_drv_status(wl, SCANNING, dev)) { wl_cfg80211_scan_abort(wl, dev); } wldev_iovar_setint(dev, "mpc", 1); @@ -933,14 +980,10 @@ wl_cfg80211_del_virtual_iface(struct wiphy *wiphy, struct net_device *dev) * ifconfig down and up sequnce, which will reload the fw * however we should cleanup the linux network virtual interfaces */ - /* Request framework to RESET and clean up */ - struct net_device *ndev = wl_to_prmry_ndev(wl); - WL_ERR(("Firmware returned an error (%d) from p2p_ifdel" - "HANG Notification sent to %s dev %p wdev %p ndev %p\n", ret, ndev->name, dev, wl->wdev, wl_to_prmry_ndev(wl))); - wl_cfg80211_hang(ndev, WLAN_REASON_UNSPECIFIED); - } - else { - WL_ERR(("Firmware success from p2p_ifdel dev %p wdev %p ndev %p", dev, wl->wdev, wl_to_prmry_ndev(wl))); + dhd_pub_t *dhd = (dhd_pub_t *)(wl->pub); + WL_ERR(("Firmware returned an error from p2p_ifdel\n")); + WL_ERR(("try to remove linux virtual interface %s\n", dev->name)); + dhd_del_if(dhd->info, dhd_net2idx(dhd->info, dev)); } /* Wait for any pending scan req to get aborted from the sysioc context */ @@ -998,13 +1041,18 @@ wl_cfg80211_change_virtual_iface(struct wiphy *wiphy, struct net_device *ndev, return -EINVAL; } - if (ap) { - set_mode_by_netdev(wl, ndev, mode); + wl_set_mode_by_netdev(wl, ndev, mode); if (wl->p2p_supported && wl->p2p->vif_created) { WL_DBG(("p2p_vif_created (%d) p2p_on (%d)\n", wl->p2p->vif_created, p2p_on(wl))); - chspec = wf_chspec_aton(WL_P2P_TEMP_CHAN); + + /* In concurrency case, STA may be already associated in a particular + * channel. so retrieve the current channel of primary interface and + * then start the virtual interface on that. + */ + chspec = wl_cfg80211_get_shared_freq(wiphy); + wlif_type = ap ? WL_P2P_IF_GO : WL_P2P_IF_CLIENT; WL_ERR(("%s : ap (%d), infra (%d), iftype: (%d)\n", ndev->name, ap, infra, type)); @@ -1014,12 +1062,12 @@ wl_cfg80211_change_virtual_iface(struct wiphy *wiphy, struct net_device *ndev, timeout = wait_event_interruptible_timeout(wl->dongle_event_wait, (wl_get_p2p_status(wl, IF_CHANGED) == true), msecs_to_jiffies(MAX_WAIT_TIME)); - set_mode_by_netdev(wl, ndev, mode); + wl_set_mode_by_netdev(wl, ndev, mode); wl_clr_p2p_status(wl, IF_CHANGING); wl_clr_p2p_status(wl, IF_CHANGED); } else if (ndev == wl_to_prmry_ndev(wl) && - !wl_get_drv_status(wl, AP_CREATED)) { - wl_set_drv_status(wl, AP_CREATING); + !wl_get_drv_status(wl, AP_CREATED, ndev)) { + wl_set_drv_status(wl, AP_CREATING, ndev); if (!wl->ap_info && !(wl->ap_info = kzalloc(sizeof(struct ap_info), GFP_KERNEL))) { WL_ERR(("struct ap_saved_ie allocation failed\n")); @@ -1077,7 +1125,8 @@ wl_cfg80211_notify_ifdel(struct net_device *ndev) if (p2p_is_on(wl) && wl->p2p->vif_created && wl_get_p2p_status(wl, IF_DELETING)) { - if (wl->scan_request) { + if (wl->scan_request && + (wl->escan_info.ndev == ndev)) { /* Abort any pending scan requests */ wl->escan_info.escan_state = WL_ESCAN_STATE_IDLE; if (!rtnl_is_locked()) { @@ -1085,7 +1134,7 @@ wl_cfg80211_notify_ifdel(struct net_device *ndev) rollback_lock = true; } WL_DBG(("ESCAN COMPLETED\n")); - wl_notify_escan_complete(wl, true); + wl_notify_escan_complete(wl, ndev, true); if (rollback_lock) rtnl_unlock(); } @@ -1109,18 +1158,6 @@ wl_cfg80211_notify_ifdel(struct net_device *ndev) return 0; } -s32 wl_cfg80211_post_del(void* ndev) -{ - int index; - struct wl_priv *wl = wlcfg_drv_priv; - index = get_idx_vwdev_by_netdev(wl, (struct net_device *)ndev); - WL_DBG(("index : %d\n", index)); - if (index >= 0) { - free_vwdev_by_index(wl, index); - } - return 0; -} - s32 wl_cfg80211_is_progress_ifadd(void) { @@ -1386,7 +1423,7 @@ wl_run_escan(struct wl_priv *wl, struct net_device *ndev, WL_ERR((" Escan set error (%d)\n", err)); kfree(params); } - else if (p2p_on(wl) && p2p_scan(wl)) { + else if (p2p_is_on(wl) && p2p_scan(wl)) { /* P2P SCAN TRIGGER */ if (scan_request && scan_request->n_channels) { num_chans = scan_request->n_channels; @@ -1412,7 +1449,7 @@ wl_run_escan(struct wl_priv *wl, struct net_device *ndev, search_state = WL_P2P_DISC_ST_SEARCH; WL_INFO(("P2P SEARCH PHASE START \n")); } else if ((dev = wl_to_p2p_bss_ndev(wl, P2PAPI_BSSCFG_CONNECTION)) && - (get_mode_by_netdev(wl, dev) == WL_MODE_AP)) { + (wl_get_mode_by_netdev(wl, dev) == WL_MODE_AP)) { /* If you are already a GO, then do SEARCH only */ WL_INFO(("Already a GO. Do SEARCH Only")); search_state = WL_P2P_DISC_ST_SEARCH; @@ -1442,7 +1479,7 @@ wl_do_escan(struct wl_priv *wl, struct wiphy *wiphy, struct net_device *ndev, s32 passive_scan; wl_scan_results_t *results; WL_SCAN(("Enter \n")); - + wl->escan_info.ndev = ndev; wl->escan_info.wiphy = wiphy; wl->escan_info.escan_state = WL_ESCAN_STATE_SCANING; passive_scan = wl->active_scan ? 0 : 1; @@ -1473,21 +1510,27 @@ __wl_cfg80211_scan(struct wiphy *wiphy, struct net_device *ndev, s32 passive_scan; bool iscan_req; bool escan_req; - bool spec_scan; bool p2p_ssid; s32 err = 0; s32 i; u32 wpsie_len = 0; u8 wpsie[IE_MAX_LEN]; + /* If scan req comes for p2p0, send it over primary I/F as there + * there is no firmware interface corresponding to p2p0. + * Scan results will be delivered corresponding to cfg80211_scan_request + */ + if (ndev == wl->p2p_net) { + ndev = wl_to_prmry_ndev(wl); + } + WL_DBG(("Enter wiphy (%p)\n", wiphy)); - if (unlikely(wl_get_drv_status(wl, SCANNING))) { - WL_ERR(("Scanning already : status (%d)\n", (int)wl->status)); + if (wl_get_drv_status_all(wl, SCANNING)) { + WL_ERR(("Scanning already\n")); return -EAGAIN; } - if (unlikely(wl_get_drv_status(wl, SCAN_ABORTING))) { - WL_ERR(("Scanning being aborted : status (%d)\n", - (int)wl->status)); + if (wl_get_drv_status(wl, SCAN_ABORTING, ndev)) { + WL_ERR(("Scanning being aborted\n")); return -EAGAIN; } if (request && request->n_ssids > WL_SCAN_PARAMS_SSID_MAX) { @@ -1498,7 +1541,6 @@ __wl_cfg80211_scan(struct wiphy *wiphy, struct net_device *ndev, /* Arm scan timeout timer */ mod_timer(&wl->scan_timeout, jiffies + WL_SCAN_TIMER_INTERVAL_MS * HZ / 1000); iscan_req = false; - spec_scan = false; if (request) { /* scan bss */ ssids = request->ssids; if (wl->iscan_on && (!ssids || !ssids->ssid_len || request->n_ssids != 1)) { @@ -1572,7 +1614,7 @@ __wl_cfg80211_scan(struct wiphy *wiphy, struct net_device *ndev, ssids = this_ssid; } wl->scan_request = request; - wl_set_drv_status(wl, SCANNING); + wl_set_drv_status(wl, SCANNING, ndev); if (iscan_req) { err = wl_do_iscan(wl, request); if (likely(!err)) @@ -1607,7 +1649,6 @@ __wl_cfg80211_scan(struct wiphy *wiphy, struct net_device *ndev, sr->ssid.SSID_len = htod32(sr->ssid.SSID_len); WL_SCAN(("Specific scan ssid=\"%s\" len=%d\n", sr->ssid.SSID, sr->ssid.SSID_len)); - spec_scan = true; } else { WL_SCAN(("Broadcast scan\n")); } @@ -1635,7 +1676,7 @@ __wl_cfg80211_scan(struct wiphy *wiphy, struct net_device *ndev, return 0; scan_out: - wl_clr_drv_status(wl, SCANNING); + wl_clr_drv_status(wl, SCANNING, ndev); wl->scan_request = NULL; return err; } @@ -1891,7 +1932,7 @@ wl_set_wpa_version(struct net_device *dev, struct cfg80211_connect_params *sme) WL_ERR(("set wpa_auth failed (%d)\n", err)); return err; } - sec = wl_read_prof(wl, WL_PROF_SEC); + sec = wl_read_prof(wl, dev, WL_PROF_SEC); sec->wpa_versions = sme->crypto.wpa_versions; return err; } @@ -1930,7 +1971,7 @@ wl_set_auth_type(struct net_device *dev, struct cfg80211_connect_params *sme) WL_ERR(("set auth failed (%d)\n", err)); return err; } - sec = wl_read_prof(wl, WL_PROF_SEC); + sec = wl_read_prof(wl, dev, WL_PROF_SEC); sec->auth_type = sme->auth_type; return err; } @@ -2002,7 +2043,7 @@ wl_set_set_cipher(struct net_device *dev, struct cfg80211_connect_params *sme) return err; } - sec = wl_read_prof(wl, WL_PROF_SEC); + sec = wl_read_prof(wl, dev, WL_PROF_SEC); sec->cipher_pairwise = sme->crypto.ciphers_pairwise[0]; sec->cipher_group = sme->crypto.cipher_group; @@ -2059,7 +2100,7 @@ wl_set_key_mgmt(struct net_device *dev, struct cfg80211_connect_params *sme) return err; } } - sec = wl_read_prof(wl, WL_PROF_SEC); + sec = wl_read_prof(wl, dev, WL_PROF_SEC); sec->wpa_auth = sme->crypto.akm_suites[0]; return err; @@ -2078,7 +2119,7 @@ wl_set_set_sharedkey(struct net_device *dev, WL_DBG(("key len (%d)\n", sme->key_len)); if (sme->key_len) { - sec = wl_read_prof(wl, WL_PROF_SEC); + sec = wl_read_prof(wl, dev, WL_PROF_SEC); WL_DBG(("wpa_versions 0x%x cipher_pairwise 0x%x\n", sec->wpa_versions, sec->cipher_pairwise)); if (!(sec->wpa_versions & (NL80211_WPA_VERSION_1 | @@ -2162,11 +2203,11 @@ wl_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev, } /* Clean BSSID */ bzero(&bssid, sizeof(bssid)); - wl_update_prof(wl, NULL, (void *)&bssid, WL_PROF_BSSID); + wl_update_prof(wl, dev, NULL, (void *)&bssid, WL_PROF_BSSID); if (IS_P2P_SSID(sme->ssid) && (dev != wl_to_prmry_ndev(wl))) { /* we only allow to connect using virtual interface in case of P2P */ - if (p2p_on(wl) && is_wps_conn(sme)) { + if (p2p_is_on(wl) && is_wps_conn(sme)) { WL_DBG(("ASSOC1 p2p index : %d sme->ie_len %d\n", wl_cfgp2p_find_idx(wl, dev), sme->ie_len)); /* Have to apply WPS IE + P2P IE in assoc req frame */ @@ -2177,7 +2218,7 @@ wl_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev, P2PAPI_BSSCFG_DEVICE).p2p_probe_req_ie_len); wl_cfgp2p_set_management_ie(wl, dev, wl_cfgp2p_find_idx(wl, dev), VNDR_IE_ASSOCREQ_FLAG, sme->ie, sme->ie_len); - } else if (p2p_on(wl) && (sme->crypto.wpa_versions & NL80211_WPA_VERSION_2)) { + } else if (p2p_is_on(wl) && (sme->crypto.wpa_versions & NL80211_WPA_VERSION_2)) { /* This is the connect req after WPS is done [credentials exchanged] * currently identified with WPA_VERSION_2 . * Update the previously set IEs with @@ -2278,7 +2319,7 @@ wl_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev, ext_join_params = (wl_extjoin_params_t*)kzalloc(join_params_size, GFP_KERNEL); if (ext_join_params == NULL) { err = -ENOMEM; - wl_clr_drv_status(wl, CONNECTING); + wl_clr_drv_status(wl, CONNECTING, dev); goto exit; } ext_join_params->ssid.SSID_len = min(sizeof(ext_join_params->ssid.SSID), sme->ssid_len); @@ -2287,12 +2328,13 @@ wl_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev, /* Set up join scan parameters */ ext_join_params->scan.scan_type = -1; ext_join_params->scan.nprobes = 2; - /* increate dwell time to receive probe response - * from target AP at a noisy air + /* increate dwell time to receive probe response or detect Beacon + * from target AP at a noisy air only during connect command */ - ext_join_params->scan.active_time = 150; - ext_join_params->scan.passive_time = 300; + ext_join_params->scan.active_time = DHD_SCAN_ACTIVE_TIME*3; + ext_join_params->scan.passive_time = DHD_SCAN_PASSIVE_TIME*3; ext_join_params->scan.home_time = -1; + if (sme->bssid) memcpy(&ext_join_params->assoc.bssid, sme->bssid, ETH_ALEN); else @@ -2317,12 +2359,12 @@ wl_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev, WL_INFO(("ssid \"%s\", len (%d)\n", ext_join_params->ssid.SSID, ext_join_params->ssid.SSID_len)); } - wl_set_drv_status(wl, CONNECTING); + wl_set_drv_status(wl, CONNECTING, dev); err = wldev_iovar_setbuf_bsscfg(dev, "join", ext_join_params, join_params_size, ioctlbuf, sizeof(ioctlbuf), wl_cfgp2p_find_idx(wl, dev)); kfree(ext_join_params); if (err) { - wl_clr_drv_status(wl, CONNECTING); + wl_clr_drv_status(wl, CONNECTING, dev); if (err == BCME_UNSUPPORTED) { WL_DBG(("join iovar is not supported\n")); goto set_ssid; @@ -2338,7 +2380,7 @@ set_ssid: join_params.ssid.SSID_len = min(sizeof(join_params.ssid.SSID), sme->ssid_len); memcpy(&join_params.ssid.SSID, sme->ssid, join_params.ssid.SSID_len); join_params.ssid.SSID_len = htod32(join_params.ssid.SSID_len); - wl_update_prof(wl, NULL, &join_params.ssid, WL_PROF_SSID); + wl_update_prof(wl, dev, NULL, &join_params.ssid, WL_PROF_SSID); if (sme->bssid) memcpy(&join_params.params.bssid, sme->bssid, ETH_ALEN); else @@ -2351,11 +2393,11 @@ set_ssid: WL_INFO(("ssid \"%s\", len (%d)\n", join_params.ssid.SSID, join_params.ssid.SSID_len)); } - wl_set_drv_status(wl, CONNECTING); + wl_set_drv_status(wl, CONNECTING, dev); err = wldev_ioctl(dev, WLC_SET_SSID, &join_params, join_params_size, true); if (err) { WL_ERR(("error (%d)\n", err)); - wl_clr_drv_status(wl, CONNECTING); + wl_clr_drv_status(wl, CONNECTING, dev); } exit: return err; @@ -2372,23 +2414,23 @@ wl_cfg80211_disconnect(struct wiphy *wiphy, struct net_device *dev, u8 *curbssid; WL_ERR(("Reason %d\n", reason_code)); CHECK_SYS_UP(wl); - act = *(bool *) wl_read_prof(wl, WL_PROF_ACT); - curbssid = wl_read_prof(wl, WL_PROF_BSSID); - if (likely(act)) { + act = *(bool *) wl_read_prof(wl, dev, WL_PROF_ACT); + curbssid = wl_read_prof(wl, dev, WL_PROF_BSSID); + if (act) { /* * Cancel ongoing scan to sync up with sme state machine of cfg80211. */ if (wl->scan_request) { wl_cfg80211_scan_abort(wl, dev); } - wl_set_drv_status(wl, DISCONNECTING); + wl_set_drv_status(wl, DISCONNECTING, dev); scbval.val = reason_code; memcpy(&scbval.ea, curbssid, ETHER_ADDR_LEN); scbval.val = htod32(scbval.val); err = wldev_ioctl(dev, WLC_DISASSOC, &scbval, sizeof(scb_val_t), true); if (unlikely(err)) { - wl_clr_drv_status(wl, DISCONNECTING); + wl_clr_drv_status(wl, DISCONNECTING, dev); WL_ERR(("error (%d)\n", err)); return err; } @@ -2507,7 +2549,7 @@ wl_add_keyext(struct wiphy *wiphy, struct net_device *dev, struct wl_wsec_key key; s32 err = 0; s32 bssidx = wl_cfgp2p_find_idx(wl, dev); - s32 mode = get_mode_by_netdev(wl, dev); + s32 mode = wl_get_mode_by_netdev(wl, dev); memset(&key, 0, sizeof(key)); key.index = (u32) key_idx; @@ -2603,7 +2645,7 @@ wl_cfg80211_add_key(struct wiphy *wiphy, struct net_device *dev, u8 keybuf[8]; s32 bssidx = 0; struct wl_priv *wl = wiphy_priv(wiphy); - s32 mode = get_mode_by_netdev(wl, dev); + s32 mode = wl_get_mode_by_netdev(wl, dev); WL_DBG(("key index (%d)\n", key_idx)); CHECK_SYS_UP(wl); @@ -2753,7 +2795,7 @@ wl_cfg80211_get_key(struct wiphy *wiphy, struct net_device *dev, } switch (wsec & ~SES_OW_ENABLED) { case WEP_ENABLED: - sec = wl_read_prof(wl, WL_PROF_SEC); + sec = wl_read_prof(wl, dev, WL_PROF_SEC); if (sec->cipher_pairwise & WLAN_CIPHER_SUITE_WEP40) { params.cipher = WLAN_CIPHER_SUITE_WEP40; WL_DBG(("WLAN_CIPHER_SUITE_WEP40\n")); @@ -2803,7 +2845,7 @@ wl_cfg80211_get_station(struct wiphy *wiphy, struct net_device *dev, dhd_pub_t *dhd = (dhd_pub_t *)(wl->pub); CHECK_SYS_UP(wl); - if (get_mode_by_netdev(wl, dev) == WL_MODE_AP) { + if (wl_get_mode_by_netdev(wl, dev) == WL_MODE_AP) { err = wldev_iovar_getbuf(dev, "sta_info", (struct ether_addr *)mac, ETHER_ADDR_LEN, ioctlbuf, sizeof(ioctlbuf)); if (err < 0) { @@ -2827,10 +2869,9 @@ wl_cfg80211_get_station(struct wiphy *wiphy, struct net_device *dev, bcm_ether_ntoa((const struct ether_addr *)mac, eabuf), sinfo->inactive_time, sta->idle * 1000)); #endif - } else if (get_mode_by_netdev(wl, dev) == WL_MODE_BSS) { - u8 *curmacp = wl_read_prof(wl, WL_PROF_BSSID); - - if (!wl_get_drv_status(wl, CONNECTED) || + } else if (wl_get_mode_by_netdev(wl, dev) == WL_MODE_BSS) { + u8 *curmacp = wl_read_prof(wl, dev, WL_PROF_BSSID); + if (!wl_get_drv_status(wl, CONNECTED, dev) || (dhd_is_associated(dhd, NULL) == FALSE)) { WL_ERR(("NOT assoc\n")); err = -ENODEV; @@ -2870,7 +2911,7 @@ get_station_err: if (err) { /* Disconnect due to zero BSSID or error to get RSSI */ WL_ERR(("force cfg80211_disconnected\n")); - wl_clr_drv_status(wl, CONNECTED); + wl_clr_drv_status(wl, CONNECTED, dev); cfg80211_disconnected(dev, 0, NULL, 0, GFP_KERNEL); wl_link_down(wl); } @@ -2888,6 +2929,14 @@ wl_cfg80211_set_power_mgmt(struct wiphy *wiphy, struct net_device *dev, struct wl_priv *wl = wiphy_priv(wiphy); CHECK_SYS_UP(wl); + + if (wl->p2p_net == dev) { + /* Since p2p0 is a hidden interface in firmware, power + * mgmt doesn't apply. + */ + return err; + } + pm = enabled ? PM_FAST : PM_OFF; /* Do not enable the power save after assoc if it is p2p interface */ if (wl->p2p && wl->p2p->vif_created) { @@ -2937,11 +2986,11 @@ static __used u32 wl_find_msb(u16 bit16) static s32 wl_cfg80211_resume(struct wiphy *wiphy) { struct wl_priv *wl = wiphy_priv(wiphy); + struct net_device *ndev = wl_to_prmry_ndev(wl); s32 err = 0; - if (unlikely(!wl_get_drv_status(wl, READY))) { - WL_INFO(("device is not ready : status (%d)\n", - (int)wl->status)); + if (unlikely(!wl_get_drv_status(wl, READY, ndev))) { + WL_INFO(("device is not ready\n")); return 0; } @@ -2958,29 +3007,34 @@ static s32 wl_cfg80211_suspend(struct wiphy *wiphy) { #ifdef DHD_CLEAR_ON_SUSPEND struct wl_priv *wl = wiphy_priv(wiphy); + struct net_info *iter, *next; struct net_device *ndev = wl_to_prmry_ndev(wl); unsigned long flags; - if (unlikely(!wl_get_drv_status(wl, READY))) { + if (unlikely(!wl_get_drv_status(wl, READY, ndev))) { WL_INFO(("device is not ready : status (%d)\n", (int)wl->status)); return 0; } - - wl_set_drv_status(wl, SCAN_ABORTING); + for_each_ndev(wl, iter, next) + wl_set_drv_status(wl, SCAN_ABORTING, iter->ndev); wl_term_iscan(wl); flags = dhd_os_spin_lock((dhd_pub_t *)(wl->pub)); if (wl->scan_request) { cfg80211_scan_done(wl->scan_request, true); wl->scan_request = NULL; } - wl_clr_drv_status(wl, SCANNING); - wl_clr_drv_status(wl, SCAN_ABORTING); + for_each_ndev(wl, iter, next) { + wl_clr_drv_status(wl, SCANNING, iter->ndev); + wl_clr_drv_status(wl, SCAN_ABORTING, iter->ndev); + } dhd_os_spin_unlock((dhd_pub_t *)(wl->pub), flags); - if (wl_get_drv_status(wl, CONNECTING)) { - wl_bss_connect_done(wl, ndev, NULL, NULL, false); + for_each_ndev(wl, iter, next) { + if (wl_get_drv_status(wl, CONNECTING, iter->ndev)) { + wl_bss_connect_done(wl, iter->ndev, NULL, NULL, false); + } } -#endif +#endif /* DHD_CLEAR_ON_SUSPEND */ return 0; } @@ -3179,7 +3233,7 @@ wl_cfg80211_scan_abort(struct wl_priv *wl, struct net_device *ndev) cfg80211_scan_done(wl->scan_request, true); wl->scan_request = NULL; } - wl_clr_drv_status(wl, SCANNING); + wl_clr_drv_status(wl, SCANNING, ndev); dhd_os_spin_unlock((dhd_pub_t *)(wl->pub), flags); if (params) kfree(params); @@ -3193,22 +3247,36 @@ wl_cfg80211_remain_on_channel(struct wiphy *wiphy, struct net_device *dev, unsigned int duration, u64 *cookie) { s32 target_channel; - + u32 id; + struct net_device *ndev = NULL; s32 err = BCME_OK; struct wl_priv *wl = wiphy_priv(wiphy); dhd_pub_t *dhd = (dhd_pub_t *)(wl->pub); WL_DBG(("Enter, netdev_ifidx: %d \n", dev->ifindex)); - if (likely(wl_get_drv_status(wl, SCANNING))) { + + if (wl->p2p_net == dev) { + /* Since there is no ifidx corresponding to p2p0, cmds to + * firmware should be routed through primary I/F + */ + ndev = wl_to_prmry_ndev(wl); + } else { + ndev = dev; + } + + if (wl_get_drv_status(wl, SCANNING, dev)) { wl_cfg80211_scan_abort(wl, dev); } target_channel = ieee80211_frequency_to_channel(channel->center_freq); memcpy(&wl->remain_on_chan, channel, sizeof(struct ieee80211_channel)); wl->remain_on_chan_type = channel_type; - wl->cache_cookie = *cookie; + id = ++wl->last_roc_id; + if (id == 0) + id = ++wl->last_roc_id; + *cookie = id; cfg80211_ready_on_channel(dev, *cookie, channel, channel_type, duration, GFP_KERNEL); - if (!p2p_on(wl)) { + if (!p2p_is_on(wl)) { wl_cfgp2p_generate_bss_mac(&dhd->mac, &wl->p2p->dev_addr, &wl->p2p->int_addr); /* In case of p2p_listen command, supplicant send remain_on_channel @@ -3222,7 +3290,7 @@ wl_cfg80211_remain_on_channel(struct wiphy *wiphy, struct net_device *dev, goto exit; } } - if (p2p_on(wl)) + if (p2p_is_on(wl)) wl_cfgp2p_discover_listen(wl, target_channel, duration); @@ -3240,7 +3308,7 @@ wl_cfg80211_cancel_remain_on_channel(struct wiphy *wiphy, struct net_device *dev } static s32 -wl_cfg80211_mgmt_tx(struct wiphy *wiphy, struct net_device *dev, +wl_cfg80211_mgmt_tx(struct wiphy *wiphy, struct net_device *ndev, struct ieee80211_channel *channel, bool offchan, enum nl80211_channel_type channel_type, bool channel_type_valid, unsigned int wait, @@ -3252,6 +3320,7 @@ wl_cfg80211_mgmt_tx(struct wiphy *wiphy, struct net_device *dev, wpa_ie_fixed_t *wps_ie; const struct ieee80211_mgmt *mgmt; struct wl_priv *wl = wiphy_priv(wiphy); + struct net_device *dev = NULL; dhd_pub_t *dhd = (dhd_pub_t *)(wl->pub); s32 err = BCME_OK; s32 bssidx = 0; @@ -3260,7 +3329,20 @@ wl_cfg80211_mgmt_tx(struct wiphy *wiphy, struct net_device *dev, u16 fc; bool ack = false; wifi_p2p_pub_act_frame_t *act_frm; + WL_DBG(("Enter \n")); + + if (ndev == wl->p2p_net) { + /* Firmware doesn't have an ifidx corresponding to p2p0 interface. + * so divert commands received on p2p0 to wlan0. Note that the TX status + * will be sent back to the interface(ndev) on which request is received + */ + dev = wl_to_prmry_ndev(wl); + } else { + /* If TX req is for any valid ifidx. Use as is */ + dev = ndev; + } + /* find bssidx based on ndev */ bssidx = wl_cfgp2p_find_idx(wl, dev); /* cookie generation */ @@ -3271,7 +3353,7 @@ wl_cfg80211_mgmt_tx(struct wiphy *wiphy, struct net_device *dev, WL_ERR(("Can not find the bssidx for dev( %p )\n", dev)); return -ENODEV; } - if (wl->p2p_supported && p2p_on(wl)) { + if (p2p_is_on(wl)) { wl_cfgp2p_generate_bss_mac(&dhd->mac, &wl->p2p->dev_addr, &wl->p2p->int_addr); /* Suspend P2P discovery search-listen to prevent it from changing the * channel. @@ -3292,13 +3374,6 @@ wl_cfg80211_mgmt_tx(struct wiphy *wiphy, struct net_device *dev, != NULL) { /* Total length of P2P Information Element */ p2pie_len = p2p_ie->len + sizeof(p2p_ie->len) + sizeof(p2p_ie->id); - /* Have to change p2p device address in dev_info attribute - * because Supplicant use primary eth0 address - */ - #ifdef ENABLE_DRIVER_CHANGE_IFADDR /* We are now doing this in supplicant */ - wl_cfg80211_change_ifaddr((u8 *)p2p_ie, - &wl->p2p_dev_addr, P2P_SEID_DEV_INFO); - #endif } if ((wps_ie = wl_cfgp2p_find_wpsie((u8 *)(buf + ie_offset), ie_len)) != NULL) { @@ -3314,7 +3389,7 @@ wl_cfg80211_mgmt_tx(struct wiphy *wiphy, struct net_device *dev, (u8 *)wps_ie, wpsie_len + p2pie_len); } } - cfg80211_mgmt_tx_status(dev, *cookie, buf, len, true, GFP_KERNEL); + cfg80211_mgmt_tx_status(ndev, *cookie, buf, len, true, GFP_KERNEL); goto exit; } else { /* Abort the dwell time of any previous off-channel action frame that may @@ -3350,6 +3425,14 @@ wl_cfg80211_mgmt_tx(struct wiphy *wiphy, struct net_device *dev, af_params->channel = ieee80211_frequency_to_channel(channel->center_freq); + if (channel->band == IEEE80211_BAND_5GHZ) { + err = wldev_ioctl(dev, WLC_SET_CHANNEL, + &af_params->channel, sizeof(af_params->channel), true); + if (err < 0) { + WL_ERR(("WLC_SET_CHANNEL error %d\n", err)); + } + } + /* Add the dwell time * Dwell time to stay off-channel to wait for a response action frame * after transmitting an GO Negotiation action frame @@ -3377,7 +3460,7 @@ wl_cfg80211_mgmt_tx(struct wiphy *wiphy, struct net_device *dev, } ack = (wl_cfgp2p_tx_action_frame(wl, dev, af_params, bssidx)) ? false : true; - cfg80211_mgmt_tx_status(dev, *cookie, buf, len, ack, GFP_KERNEL); + cfg80211_mgmt_tx_status(ndev, *cookie, buf, len, ack, GFP_KERNEL); kfree(af_params); exit: @@ -3432,7 +3515,14 @@ wl_cfg80211_set_channel(struct wiphy *wiphy, struct net_device *dev, { s32 channel; s32 err = BCME_OK; + struct wl_priv *wl = wiphy_priv(wiphy); + if (wl->p2p_net == dev) { + /* Since there is no ifidx corresponding to p2p0, cmds to + * firmware should be routed through primary I/F + */ + dev = wl_to_prmry_ndev(wl); + } channel = ieee80211_frequency_to_channel(chan->center_freq); WL_DBG(("netdev_ifidx(%d), chan_type(%d) target channel(%d) \n", dev->ifindex, channel_type, channel)); @@ -3713,13 +3803,22 @@ wl_cfg80211_add_set_beacon(struct wiphy *wiphy, struct net_device *dev, u16 p2pie_len = 0; u8 beacon_ie[IE_MAX_LEN]; s32 ie_offset = 0; - s32 bssidx = wl_cfgp2p_find_idx(wl, dev); + s32 bssidx = 0; s32 infra = 1; s32 join_params_size = 0; s32 ap = 0; WL_DBG(("interval (%d) dtim_period (%d) head_len (%d) tail_len (%d)\n", info->interval, info->dtim_period, info->head_len, info->tail_len)); - if (wl->p2p_supported && p2p_on(wl) && + + if (wl->p2p_net == dev) { + /* Since there is no ifidx corresponding to p2p0, cmds to + * firmware should be routed through primary I/F + */ + dev = wl_to_prmry_ndev(wl); + } + + bssidx = wl_cfgp2p_find_idx(wl, dev); + if (p2p_is_on(wl) && (bssidx == wl_to_p2p_bss_bssidx(wl, P2PAPI_BSSCFG_CONNECTION))) { memset(beacon_ie, 0, sizeof(beacon_ie)); @@ -3757,12 +3856,6 @@ wl_cfg80211_add_set_beacon(struct wiphy *wiphy, struct net_device *dev, if ((p2p_ie = wl_cfgp2p_find_p2pie((u8 *)info->tail, info->tail_len)) != NULL) { /* Total length of P2P Information Element */ p2pie_len = p2p_ie->len + sizeof(p2p_ie->len) + sizeof(p2p_ie->id); - #ifdef ENABLE_DRIVER_CHANGE_IFADDR /* We are now doing this in supplicant */ - /* Have to change device address in dev_id attribute because Supplicant - * use primary eth0 address - */ - wl_cfg80211_change_ifaddr((u8 *)p2p_ie, &wl->p2p_dev_addr, P2P_SEID_DEV_ID); - #endif memcpy(&beacon_ie[wpsie_len], p2p_ie, p2pie_len); } else { @@ -3802,7 +3895,7 @@ wl_cfg80211_add_set_beacon(struct wiphy *wiphy, struct net_device *dev, goto exit; } } - } else if (wl_get_drv_status(wl, AP_CREATING)) { + } else if (wl_get_drv_status(wl, AP_CREATING, dev)) { ie_offset = DOT11_MGMT_HDR_LEN + DOT11_BCN_PRB_FIXED_LEN; ap = 1; /* find the SSID */ @@ -3908,11 +4001,11 @@ wl_cfg80211_add_set_beacon(struct wiphy *wiphy, struct net_device *dev, /* create softap */ if ((err = wldev_ioctl(dev, WLC_SET_SSID, &join_params, join_params_size, true)) == 0) { - wl_clr_drv_status(wl, AP_CREATING); - wl_set_drv_status(wl, AP_CREATED); + wl_clr_drv_status(wl, AP_CREATING, dev); + wl_set_drv_status(wl, AP_CREATED, dev); } } - } else if (wl_get_drv_status(wl, AP_CREATED)) { + } else if (wl_get_drv_status(wl, AP_CREATED, dev)) { ap = 1; /* find the WPSIE */ if ((wps_ie = wl_cfgp2p_find_wpsie((u8 *)info->tail, info->tail_len)) != NULL) { @@ -4053,7 +4146,7 @@ static struct cfg80211_ops wl_cfg80211_ops = { .add_beacon = wl_cfg80211_add_set_beacon, }; -static s32 wl_mode_to_nl80211_iftype(s32 mode) +s32 wl_mode_to_nl80211_iftype(s32 mode) { s32 err = 0; @@ -4142,24 +4235,15 @@ wiphy_new_out: static void wl_free_wdev(struct wl_priv *wl) { - int i; struct wireless_dev *wdev = wl->wdev; - - if (unlikely(!wdev)) { + if (!wdev) { WL_ERR(("wdev is invalid\n")); return; } - - for (i = 0; i < VWDEV_CNT; i++) { - if ((wl->vwdev[i] != NULL)) { - kfree(wl->vwdev[i]); - wl->vwdev[i] = NULL; - } - } wiphy_unregister(wdev->wiphy); wdev->wiphy->dev.parent = NULL; wiphy_free(wdev->wiphy); - kfree(wdev); + wl_delete_all_netinfo(wl); } static s32 wl_inform_bss(struct wl_priv *wl) @@ -4339,8 +4423,10 @@ wl_notify_connect_status(struct wl_priv *wl, struct net_device *ndev, memset(body, 0, sizeof(body)); memset(&bssid, 0, ETHER_ADDR_LEN); WL_DBG(("Enter \n")); + if (wl_get_mode_by_netdev(wl, ndev) == WL_INVALID) + return WL_INVALID; - if (get_mode_by_netdev(wl, ndev) == WL_MODE_AP) { + if (wl_get_mode_by_netdev(wl, ndev) == WL_MODE_AP) { memcpy(body, data, len); wldev_iovar_getbuf_bsscfg(ndev, "cur_etheraddr", NULL, 0, ioctlbuf, sizeof(ioctlbuf), bsscfgidx); @@ -4401,21 +4487,20 @@ wl_notify_connect_status(struct wl_priv *wl, struct net_device *ndev, if (wl_is_linkup(wl, e, ndev)) { wl_link_up(wl); act = true; - wl_update_prof(wl, e, &act, WL_PROF_ACT); - wl_update_prof(wl, NULL, (void *)(e->addr.octet), WL_PROF_BSSID); + wl_update_prof(wl, ndev, e, &act, WL_PROF_ACT); + wl_update_prof(wl, ndev, NULL, (void *)&e->addr, WL_PROF_BSSID); if (wl_is_ibssmode(wl, ndev)) { printk("cfg80211_ibss_joined\n"); cfg80211_ibss_joined(ndev, (s8 *)&e->addr, GFP_KERNEL); WL_DBG(("joined in IBSS network\n")); } else { - if (!wl_get_drv_status(wl, DISCONNECTING)) { - printk("wl_bss_connect_done succeeded status=(0x%x)\n", - (int)wl->status); + if (!wl_get_drv_status(wl, DISCONNECTING, ndev)) { + printk("wl_bss_connect_done succeeded\n"); wl_bss_connect_done(wl, ndev, e, data, true); WL_DBG(("joined in BSS network \"%s\"\n", ((struct wlc_ssid *) - wl_read_prof(wl, WL_PROF_SSID))->SSID)); + wl_read_prof(wl, ndev, WL_PROF_SSID))->SSID)); } } @@ -4423,15 +4508,15 @@ wl_notify_connect_status(struct wl_priv *wl, struct net_device *ndev, if (wl->scan_request) { del_timer_sync(&wl->scan_timeout); if (wl->escan_on) { - wl_notify_escan_complete(wl, true); + wl_notify_escan_complete(wl, ndev, true); } else wl_iscan_aborted(wl); } - if (wl_get_drv_status(wl, CONNECTED)) { + if (wl_get_drv_status(wl, CONNECTED, ndev)) { scb_val_t scbval; - u8 *curbssid = wl_read_prof(wl, WL_PROF_BSSID); + u8 *curbssid = wl_read_prof(wl, ndev, WL_PROF_BSSID); printk("link down, call cfg80211_disconnected\n"); - wl_clr_drv_status(wl, CONNECTED); + wl_clr_drv_status(wl, CONNECTED, ndev); /* To make sure disconnect, explictly send dissassoc * for BSSID 00:00:00:00:00:00 issue */ @@ -4443,12 +4528,12 @@ wl_notify_connect_status(struct wl_priv *wl, struct net_device *ndev, sizeof(scb_val_t), true); cfg80211_disconnected(ndev, 0, NULL, 0, GFP_KERNEL); wl_link_down(wl); - wl_init_prof(wl); - } else if (wl_get_drv_status(wl, CONNECTING)) { + wl_init_prof(wl, ndev); + } else if (wl_get_drv_status(wl, CONNECTING, ndev)) { printk("link down, during connecting\n"); wl_bss_connect_done(wl, ndev, e, data, false); } - wl_clr_drv_status(wl, DISCONNECTING); + wl_clr_drv_status(wl, DISCONNECTING, ndev); } else if (wl_is_nonetwork(wl, e)) { printk("connect failed event=%d e->status 0x%x\n", @@ -4457,11 +4542,11 @@ wl_notify_connect_status(struct wl_priv *wl, struct net_device *ndev, if (wl->scan_request) { del_timer_sync(&wl->scan_timeout); if (wl->escan_on) { - wl_notify_escan_complete(wl, true); + wl_notify_escan_complete(wl, ndev, true); } else wl_iscan_aborted(wl); } - if (wl_get_drv_status(wl, CONNECTING)) + if (wl_get_drv_status(wl, CONNECTING, ndev)) wl_bss_connect_done(wl, ndev, e, data, false); } else { printk("%s nothing\n", __FUNCTION__); @@ -4483,13 +4568,13 @@ wl_notify_roaming_status(struct wl_priv *wl, struct net_device *ndev, u32 status = be32_to_cpu(e->status); WL_DBG(("Enter \n")); if (event == WLC_E_ROAM && status == WLC_E_STATUS_SUCCESS) { - if (wl_get_drv_status(wl, CONNECTED)) + if (wl_get_drv_status(wl, CONNECTED, ndev)) wl_bss_roaming_done(wl, ndev, e, data); else wl_bss_connect_done(wl, ndev, e, data, true); act = true; - wl_update_prof(wl, e, &act, WL_PROF_ACT); - wl_update_prof(wl, NULL, (void *)(e->addr.octet), WL_PROF_BSSID); + wl_update_prof(wl, ndev, e, &act, WL_PROF_ACT); + wl_update_prof(wl, ndev, NULL, (void *)&e->addr, WL_PROF_BSSID); } return err; } @@ -4649,14 +4734,14 @@ static s32 wl_update_bss_info(struct wl_priv *wl, struct net_device *ndev) if (wl_is_ibssmode(wl, ndev)) return err; - ssid = (struct wlc_ssid *)wl_read_prof(wl, WL_PROF_SSID); - curbssid = wl_read_prof(wl, WL_PROF_BSSID); + ssid = (struct wlc_ssid *)wl_read_prof(wl, ndev, WL_PROF_SSID); + curbssid = wl_read_prof(wl, ndev, WL_PROF_BSSID); bss = cfg80211_get_bss(wiphy, NULL, curbssid, ssid->SSID, ssid->SSID_len, WLAN_CAPABILITY_ESS, WLAN_CAPABILITY_ESS); mutex_lock(&wl->usr_sync); - if (unlikely(!bss)) { + if (!bss) { WL_DBG(("Could not find the AP\n")); *(u32 *) wl->extra_buf = htod32(WL_EXTRA_BUF_MAX); err = wldev_ioctl(ndev, WLC_GET_BSS_INFO, @@ -4702,8 +4787,8 @@ static s32 wl_update_bss_info(struct wl_priv *wl, struct net_device *ndev) } } - wl_update_prof(wl, NULL, &beacon_interval, WL_PROF_BEACONINT); - wl_update_prof(wl, NULL, &dtim_period, WL_PROF_DTIMPERIOD); + wl_update_prof(wl, ndev, NULL, &beacon_interval, WL_PROF_BEACONINT); + wl_update_prof(wl, ndev, NULL, &dtim_period, WL_PROF_DTIMPERIOD); update_bss_info_out: mutex_unlock(&wl->usr_sync); @@ -4719,8 +4804,8 @@ wl_bss_roaming_done(struct wl_priv *wl, struct net_device *ndev, u8 *curbssid; wl_get_assoc_ies(wl, ndev); - wl_update_prof(wl, NULL, (void *)(e->addr.octet), WL_PROF_BSSID); - curbssid = wl_read_prof(wl, WL_PROF_BSSID); + wl_update_prof(wl, ndev, NULL, (void *)(e->addr.octet), WL_PROF_BSSID); + curbssid = wl_read_prof(wl, ndev, WL_PROF_BSSID); wl_update_bss_info(wl, ndev); wl_update_pmklist(ndev, wl->pmk_list, err); cfg80211_roamed(ndev, @@ -4732,7 +4817,7 @@ wl_bss_roaming_done(struct wl_priv *wl, struct net_device *ndev, conn_info->resp_ie, conn_info->resp_ie_len, GFP_KERNEL); WL_DBG(("Report roaming result\n")); - wl_set_drv_status(wl, CONNECTED); + wl_set_drv_status(wl, CONNECTED, ndev); return err; } @@ -4743,20 +4828,20 @@ wl_bss_connect_done(struct wl_priv *wl, struct net_device *ndev, { struct wl_connect_info *conn_info = wl_to_conn(wl); s32 err = 0; - u8 *curbssid = wl_read_prof(wl, WL_PROF_BSSID); + u8 *curbssid = wl_read_prof(wl, ndev, WL_PROF_BSSID); WL_DBG((" enter\n")); if (wl->scan_request) { wl_cfg80211_scan_abort(wl, ndev); } - if (wl_get_drv_status(wl, CONNECTING)) { - wl_clr_drv_status(wl, CONNECTING); + if (wl_get_drv_status(wl, CONNECTING, ndev)) { + wl_clr_drv_status(wl, CONNECTING, ndev); if (completed) { wl_get_assoc_ies(wl, ndev); - wl_update_prof(wl, NULL, (void *)(e->addr.octet), WL_PROF_BSSID); - curbssid = wl_read_prof(wl, WL_PROF_BSSID); + wl_update_prof(wl, ndev, NULL, (void *)(e->addr.octet), WL_PROF_BSSID); + curbssid = wl_read_prof(wl, ndev, WL_PROF_BSSID); wl_update_bss_info(wl, ndev); wl_update_pmklist(ndev, wl->pmk_list, err); - wl_set_drv_status(wl, CONNECTED); + wl_set_drv_status(wl, CONNECTED, ndev); } cfg80211_connect_result(ndev, curbssid, @@ -4818,11 +4903,15 @@ wl_notify_scan_status(struct wl_priv *wl, struct net_device *ndev, unsigned long flags; WL_DBG(("Enter \n")); + if (!wl_get_drv_status(wl, SCANNING, ndev)) { + WL_ERR(("scan is not ready \n")); + return err; + } if (wl->iscan_on && wl->iscan_kickstart) return wl_wakeup_iscan(wl_to_iscan(wl)); mutex_lock(&wl->usr_sync); - wl_clr_drv_status(wl, SCANNING); + wl_clr_drv_status(wl, SCANNING, ndev); err = wldev_ioctl(ndev, WLC_GET_CHANNEL, &channel_inform, sizeof(channel_inform), false); if (unlikely(err)) { @@ -4915,6 +5004,7 @@ wl_notify_rx_mgmt_frame(struct wl_priv *wl, struct net_device *ndev, bool isfree = false; s32 err = 0; s32 freq; + struct net_device *dev = NULL; wifi_p2p_pub_act_frame_t *act_frm; wl_event_rx_frame_data_t *rxframe = (wl_event_rx_frame_data_t*)data; @@ -4925,6 +5015,16 @@ wl_notify_rx_mgmt_frame(struct wl_priv *wl, struct net_device *ndev, u16 channel = ((ntoh16(rxframe->channel) & WL_CHANSPEC_CHAN_MASK)); memset(&bssid, 0, ETHER_ADDR_LEN); + + if (wl->p2p_net == ndev) { + /* Since there is no ifidx corresponding to p2p0, cmds to + * firmware should be routed through primary I/F + */ + dev = wl_to_prmry_ndev(wl); + } else { + dev = ndev; + } + if (channel <= CH_MAX_2G_CHANNEL) band = wiphy->bands[IEEE80211_BAND_2GHZ]; else @@ -4936,10 +5036,10 @@ wl_notify_rx_mgmt_frame(struct wl_priv *wl, struct net_device *ndev, freq = ieee80211_channel_to_frequency(channel, band->band); #endif if (event == WLC_E_ACTION_FRAME_RX) { - wldev_iovar_getbuf_bsscfg(ndev, "cur_etheraddr", + wldev_iovar_getbuf_bsscfg(dev, "cur_etheraddr", NULL, 0, ioctlbuf, sizeof(ioctlbuf), bsscfgidx); - wldev_ioctl(ndev, WLC_GET_BSSID, &bssid, ETHER_ADDR_LEN, false); + wldev_ioctl(dev, WLC_GET_BSSID, &bssid, ETHER_ADDR_LEN, false); memcpy(da.octet, ioctlbuf, ETHER_ADDR_LEN); err = wl_frame_get_mgmt(FC_ACTION, &da, &e->addr, &bssid, &mgmt_frame, &mgmt_frame_len, @@ -4956,7 +5056,7 @@ wl_notify_rx_mgmt_frame(struct wl_priv *wl, struct net_device *ndev, * After complete GO Negotiation, roll back to mpc mode */ if (act_frm->subtype == P2P_PAF_GON_CONF) { - wldev_iovar_setint(ndev, "mpc", 1); + wldev_iovar_setint(dev, "mpc", 1); } } else { mgmt_frame = (u8 *)((wl_event_rx_frame_data_t *)rxframe + 1); @@ -4975,12 +5075,7 @@ exit: static void wl_init_conf(struct wl_conf *conf) { - s32 i = 0; WL_DBG(("Enter \n")); - for (i = 0; i <= VWDEV_CNT; i++) { - conf->mode[i].type = -1; - conf->mode[i].ndev = NULL; - } conf->frag_threshold = (u32)-1; conf->rts_threshold = (u32)-1; conf->retry_short = (u32)-1; @@ -4988,12 +5083,12 @@ static void wl_init_conf(struct wl_conf *conf) conf->tx_power = -1; } -static void wl_init_prof(struct wl_priv *wl) +static void wl_init_prof(struct wl_priv *wl, struct net_device *ndev) { unsigned long flags; - + struct wl_profile *profile = wl_get_profile_by_netdev(wl, ndev); flags = dhd_os_spin_lock((dhd_pub_t *)(wl->pub)); - memset(wl->profile, 0, sizeof(struct wl_profile)); + memset(profile, 0, sizeof(struct wl_profile)); dhd_os_spin_unlock((dhd_pub_t *)(wl->pub), flags); } @@ -5033,16 +5128,6 @@ static s32 wl_init_priv_mem(struct wl_priv *wl) WL_ERR(("wl_conf alloc failed\n")); goto init_priv_mem_out; } - wl->profile = (void *)kzalloc(sizeof(*wl->profile), GFP_KERNEL); - if (unlikely(!wl->profile)) { - WL_ERR(("wl_profile alloc failed\n")); - goto init_priv_mem_out; - } - wl->bss_info = (void *)kzalloc(WL_BSS_INFO_MAX, GFP_KERNEL); - if (unlikely(!wl->bss_info)) { - WL_ERR(("Bss information alloc failed\n")); - goto init_priv_mem_out; - } wl->scan_req_int = (void *)kzalloc(sizeof(*wl->scan_req_int), GFP_KERNEL); if (unlikely(!wl->scan_req_int)) { @@ -5096,12 +5181,8 @@ static void wl_deinit_priv_mem(struct wl_priv *wl) { kfree(wl->scan_results); wl->scan_results = NULL; - kfree(wl->bss_info); - wl->bss_info = NULL; kfree(wl->conf); wl->conf = NULL; - kfree(wl->profile); - wl->profile = NULL; kfree(wl->scan_req_int); wl->scan_req_int = NULL; kfree(wl->ioctl_buf); @@ -5162,16 +5243,17 @@ static void wl_term_iscan(struct wl_priv *wl) static void wl_notify_iscan_complete(struct wl_iscan_ctrl *iscan, bool aborted) { struct wl_priv *wl = iscan_to_wl(iscan); + struct net_device *ndev = wl_to_prmry_ndev(wl); unsigned long flags; WL_DBG(("Enter \n")); - if (unlikely(!wl_get_drv_status(wl, SCANNING))) { - wl_clr_drv_status(wl, SCANNING); + if (!wl_get_drv_status(wl, SCANNING, ndev)) { + wl_clr_drv_status(wl, SCANNING, ndev); WL_ERR(("Scan complete while device not scanning\n")); return; } flags = dhd_os_spin_lock((dhd_pub_t *)(wl->pub)); - wl_clr_drv_status(wl, SCANNING); + wl_clr_drv_status(wl, SCANNING, ndev); if (likely(wl->scan_request)) { cfg80211_scan_done(wl->scan_request, aborted); wl->scan_request = NULL; @@ -5326,7 +5408,7 @@ static void wl_scan_timeout(unsigned long data) if (wl->scan_request) { WL_ERR(("timer expired\n")); if (wl->escan_on) - wl_notify_escan_complete(wl, true); + wl_notify_escan_complete(wl, wl->escan_info.ndev, true); else wl_notify_iscan_complete(wl_to_iscan(wl), true); } @@ -5372,13 +5454,39 @@ static void wl_init_iscan_handler(struct wl_iscan_ctrl *iscan) iscan->iscan_handler[WL_SCAN_RESULTS_NO_MEM] = wl_iscan_aborted; } -static void wl_notify_escan_complete(struct wl_priv *wl, bool aborted) +static s32 +wl_cfg80211_netdev_notifier_call(struct notifier_block * nb, + unsigned long state, + void *ndev) +{ + struct net_device *dev = ndev; + struct wireless_dev *wdev = dev->ieee80211_ptr; + struct wl_priv *wl = wlcfg_drv_priv; + + WL_DBG(("Enter \n")); + if (!wdev || dev == wl_to_prmry_ndev(wl)) + return NOTIFY_DONE; + switch (state) { + case NETDEV_UNREGISTER: + /* after calling list_del_rcu(&wdev->list) */ + wl_dealloc_netinfo(wl, ndev); + break; + } + return NOTIFY_DONE; +} +static struct notifier_block wl_cfg80211_netdev_notifier = { + .notifier_call = wl_cfg80211_netdev_notifier_call, +}; + +static void wl_notify_escan_complete(struct wl_priv *wl, + struct net_device *ndev, + bool aborted) { unsigned long flags; WL_DBG(("Enter \n")); - wl_clr_drv_status(wl, SCANNING); - if (wl->p2p_supported && p2p_on(wl)) + wl_clr_drv_status(wl, SCANNING, ndev); + if (p2p_is_on(wl)) wl_clr_p2p_status(wl, SCANNING); flags = dhd_os_spin_lock((dhd_pub_t *)(wl->pub)); @@ -5403,8 +5511,11 @@ static s32 wl_escan_handler(struct wl_priv *wl, u32 i; WL_DBG((" enter event type : %d, status : %d \n", ntoh32(e->event_type), ntoh32(e->status))); - if (!wl->escan_on && - !wl_get_drv_status(wl, SCANNING)) { + /* P2P SCAN is coming from primary interface */ + if (wl_get_p2p_status(wl, SCANNING)) + ndev = wl->escan_info.ndev; + if (!ndev || !wl->escan_on || + !wl_get_drv_status(wl, SCANNING, ndev)) { WL_ERR(("escan is not ready \n")); return err; } @@ -5476,7 +5587,7 @@ static s32 wl_escan_handler(struct wl_priv *wl, WL_INFO(("ESCAN COMPLETED\n")); wl->bss_list = (wl_scan_results_t *)wl->escan_info.escan_buf; wl_inform_bss(wl); - wl_notify_escan_complete(wl, false); + wl_notify_escan_complete(wl, ndev, false); mutex_unlock(&wl->usr_sync); } } @@ -5488,7 +5599,7 @@ static s32 wl_escan_handler(struct wl_priv *wl, WL_INFO(("ESCAN ABORTED\n")); wl->bss_list = (wl_scan_results_t *)wl->escan_info.escan_buf; wl_inform_bss(wl); - wl_notify_escan_complete(wl, true); + wl_notify_escan_complete(wl, ndev, true); mutex_unlock(&wl->usr_sync); } } @@ -5500,7 +5611,7 @@ static s32 wl_escan_handler(struct wl_priv *wl, del_timer_sync(&wl->scan_timeout); wl->bss_list = (wl_scan_results_t *)wl->escan_info.escan_buf; wl_inform_bss(wl); - wl_notify_escan_complete(wl, true); + wl_notify_escan_complete(wl, ndev, true); mutex_unlock(&wl->usr_sync); } } @@ -5549,9 +5660,8 @@ static void wl_init_fw(struct wl_fw_ctrl *fw) static s32 wl_init_priv(struct wl_priv *wl) { struct wiphy *wiphy = wl_to_wiphy(wl); + struct net_device *ndev = wl_to_prmry_ndev(wl); s32 err = 0; - s32 i = 0; - wl->scan_request = NULL; wl->pwr_save = !!(wiphy->flags & WIPHY_FLAG_PS_ON_BY_DEFAULT); wl->iscan_on = false; @@ -5562,24 +5672,21 @@ static s32 wl_init_priv(struct wl_priv *wl) wl->dongle_up = false; wl->rf_blocked = false; - for (i = 0; i < VWDEV_CNT; i++) - wl->vwdev[i] = NULL; - init_waitqueue_head(&wl->dongle_event_wait); wl_init_eq(wl); err = wl_init_priv_mem(wl); - if (unlikely(err)) + if (err) return err; - if (unlikely(wl_create_event_handler(wl))) + if (wl_create_event_handler(wl)) return -ENOMEM; wl_init_event_handler(wl); mutex_init(&wl->usr_sync); err = wl_init_scan(wl); - if (unlikely(err)) + if (err) return err; wl_init_fw(wl->fw); wl_init_conf(wl->conf); - wl_init_prof(wl); + wl_init_prof(wl, ndev); wl_link_down(wl); return err; @@ -5594,25 +5701,45 @@ static void wl_deinit_priv(struct wl_priv *wl) del_timer_sync(&wl->scan_timeout); wl_term_iscan(wl); wl_deinit_priv_mem(wl); + unregister_netdevice_notifier(&wl_cfg80211_netdev_notifier); } -#if defined(DHD_P2P_DEV_ADDR_FROM_SYSFS) && defined(CONFIG_SYSCTL) -s32 wl_cfg80211_sysctl_export_devaddr(void *data) +#if defined(WLP2P) && ENABLE_P2P_INTERFACE +static s32 wl_cfg80211_attach_p2p(void) +{ + struct wl_priv *wl = wlcfg_drv_priv; + + WL_TRACE(("Enter \n")); + + if (wl_cfgp2p_register_ndev(wl) < 0) { + WL_ERR(("%s: P2P attach failed. \n", __func__)); + return -ENODEV; + } + + return 0; +} + +static s32 wl_cfg80211_detach_p2p(void) { - /* Export the p2p_dev_addr via sysctl interface - * so that wpa_supplicant can access it - */ - dhd_pub_t *dhd = (dhd_pub_t *)data; struct wl_priv *wl = wlcfg_drv_priv; + struct wireless_dev *wdev = wl->p2p_wdev; + + WL_TRACE(("Enter \n")); + if (!wdev || !wl) { + WL_ERR(("Invalid Ptr\n")); + return -EINVAL; + } + + wl_cfgp2p_unregister_ndev(wl); - wl_cfgp2p_generate_bss_mac(&dhd->mac, &wl->p2p->dev_addr, &wl->p2p->int_addr); + wl->p2p_wdev = NULL; + wl->p2p_net = NULL; - sprintf((char *)&wl_sysctl_macstring[0], MACSTR, MAC2STR(wl->p2p->dev_addr.octet)); - sprintf((char *)&wl_sysctl_macstring[1], MACSTR, MAC2STR(wl->p2p->int_addr.octet)); + kfree(wdev); return 0; } -#endif /* CONFIG_SYSCTL */ +#endif /* defined(WLP2P) && (ENABLE_P2P_INTERFACE) */ s32 wl_cfg80211_attach_post(struct net_device *ndev) { @@ -5624,7 +5751,7 @@ s32 wl_cfg80211_attach_post(struct net_device *ndev) return -ENODEV; } wl = wlcfg_drv_priv; - if (wl && !wl_get_drv_status(wl, READY)) { + if (wl && !wl_get_drv_status(wl, READY, ndev)) { if (wl->wdev && wl_cfgp2p_supported(wl, ndev)) { wl->wdev->wiphy->interface_modes |= @@ -5632,67 +5759,90 @@ s32 wl_cfg80211_attach_post(struct net_device *ndev) BIT(NL80211_IFTYPE_P2P_GO)); if ((err = wl_cfgp2p_init_priv(wl)) != 0) goto fail; -#if defined(DHD_P2P_DEV_ADDR_FROM_SYSFS) && defined(CONFIG_SYSCTL) - wl_cfg80211_sysctl_export_devaddr(wl->pub); -#endif + +#if defined(WLP2P) && ENABLE_P2P_INTERFACE + if (wl->p2p_net) { + /* Update MAC addr for p2p0 interface here. */ + memcpy(wl->p2p_net->dev_addr, ndev->dev_addr, ETH_ALEN); + wl->p2p_net->dev_addr[0] |= 0x02; + printk("%s: p2p_dev_addr="MACSTR "\n", + wl->p2p_net->name, MAC2STR(wl->p2p_net->dev_addr)); + } else { + WL_ERR(("p2p_net not yet populated." + " Couldn't update the MAC Address for p2p0 \n")); + return -ENODEV; + } +#endif /* defined(WLP2P) && (ENABLE_P2P_INTERFACE) */ + wl->p2p_supported = true; } } else return -ENODEV; - - wl_set_drv_status(wl, READY); + wl_set_drv_status(wl, READY, ndev); fail: return err; } + s32 wl_cfg80211_attach(struct net_device *ndev, void *data) { struct wireless_dev *wdev; struct wl_priv *wl; s32 err = 0; + struct device *dev; WL_TRACE(("In\n")); - if (unlikely(!ndev)) { + if (!ndev) { WL_ERR(("ndev is invaild\n")); return -ENODEV; } - WL_DBG(("func %p\n", wl_cfg80211_get_sdio_func())); - wdev = wl_alloc_wdev(&wl_cfg80211_get_sdio_func()->dev); - if (unlikely(IS_ERR(wdev))) + WL_DBG(("func %p\n", wl_cfg80211_get_parent_dev())); + dev = wl_cfg80211_get_parent_dev(); + wdev = wl_alloc_wdev(dev); + if (IS_ERR(wdev)) return -ENOMEM; wdev->iftype = wl_mode_to_nl80211_iftype(WL_MODE_BSS); wl = (struct wl_priv *)wiphy_priv(wdev->wiphy); wl->wdev = wdev; wl->pub = data; - + INIT_LIST_HEAD(&wl->net_list); ndev->ieee80211_ptr = wdev; SET_NETDEV_DEV(ndev, wiphy_dev(wdev->wiphy)); wdev->netdev = ndev; - + err = wl_alloc_netinfo(wl, ndev, wdev, WL_MODE_BSS); + if (err) { + WL_ERR(("Failed to alloc net_info (%d)\n", err)); + goto cfg80211_attach_out; + } err = wl_init_priv(wl); - if (unlikely(err)) { + if (err) { WL_ERR(("Failed to init iwm_priv (%d)\n", err)); goto cfg80211_attach_out; } err = wl_setup_rfkill(wl, TRUE); - if (unlikely(err)) { + if (err) { WL_ERR(("Failed to setup rfkill %d\n", err)); goto cfg80211_attach_out; } - -#if defined(DHD_P2P_DEV_ADDR_FROM_SYSFS) && defined(CONFIG_SYSCTL) - if (!(wl_sysctl_hdr = register_sysctl_table(wl_sysctl_table))) { - WL_ERR(("%s: sysctl register failed!! \n", __func__)); + err = register_netdevice_notifier(&wl_cfg80211_netdev_notifier); + if (err) { + WL_ERR(("Failed to register notifierl %d\n", err)); goto cfg80211_attach_out; } -#endif #if defined(COEX_DHCP) if (wl_cfg80211_btcoex_init(wl)) goto cfg80211_attach_out; #endif /* COEX_DHCP */ wlcfg_drv_priv = wl; + +#if defined(WLP2P) && ENABLE_P2P_INTERFACE + err = wl_cfg80211_attach_p2p(); + if (err) + goto cfg80211_attach_out; +#endif + return err; cfg80211_attach_out: @@ -5713,16 +5863,15 @@ void wl_cfg80211_detach(void) wl_cfg80211_btcoex_deinit(wl); #endif /* COEX_DHCP */ -#if defined(DHD_P2P_DEV_ADDR_FROM_SYSFS) && defined(CONFIG_SYSCTL) - if (wl_sysctl_hdr) - unregister_sysctl_table(wl_sysctl_hdr); +#if defined(WLP2P) && ENABLE_P2P_INTERFACE + wl_cfg80211_detach_p2p(); #endif wl_setup_rfkill(wl, FALSE); if (wl->p2p_supported) wl_cfgp2p_deinit_priv(wl); wl_deinit_priv(wl); wlcfg_drv_priv = NULL; - wl_clear_sdio_func(); + wl_cfg80211_clear_parent_dev(); wl_free_wdev(wl); } @@ -5734,6 +5883,42 @@ static void wl_wakeup_event(struct wl_priv *wl) } } +static int wl_is_p2p_event(struct wl_event_q *e) +{ + switch (e->etype) { + /* We have to seperate out the P2P events received + * on primary interface so that it can be send up + * via p2p0 interface. + */ + case WLC_E_P2P_PROBREQ_MSG: + case WLC_E_P2P_DISC_LISTEN_COMPLETE: + case WLC_E_ACTION_FRAME_RX: + case WLC_E_ACTION_FRAME_OFF_CHAN_COMPLETE: + case WLC_E_ACTION_FRAME_COMPLETE: + + if (e->emsg.ifidx != 0) { + WL_TRACE(("P2P Event on Virtual I/F (ifidx:%d) \n", + e->emsg.ifidx)); + /* We are only bothered about the P2P events received + * on primary interface. For rest of them return false + * so that it is sent over the interface corresponding + * to the ifidx. + */ + return FALSE; + } else { + WL_TRACE(("P2P Event on Primary I/F (ifidx:%d)." + " Sent it to p2p0 \n", e->emsg.ifidx)); + return TRUE; + } + break; + + default: + WL_TRACE(("NON-P2P Event %d on ifidx (ifidx:%d) \n", + e->etype, e->emsg.ifidx)); + return FALSE; + } +} + static s32 wl_event_handler(void *data) { struct net_device *netdev; @@ -5750,9 +5935,20 @@ static s32 wl_event_handler(void *data) break; while ((e = wl_deq_event(wl))) { WL_DBG(("event type (%d), if idx: %d\n", e->etype, e->emsg.ifidx)); - netdev = dhd_idx2net((struct dhd_pub *)(wl->pub), e->emsg.ifidx); - if (!netdev) - netdev = wl_to_prmry_ndev(wl); + + /* All P2P device address related events comes on primary interface since + * there is no corresponding interface in the firmware. Map it to p2p0 + * interface. + */ + if ((wl_is_p2p_event(e) == TRUE) && (wl->p2p_net)) { + netdev = wl->p2p_net; + } else { + netdev = dhd_idx2net((struct dhd_pub *)(wl->pub), e->emsg.ifidx); + if (!netdev) { + netdev = wl_to_prmry_ndev(wl); + } + } + if (e->etype < WLC_E_LAST && wl->evt_handler[e->etype]) { wl->evt_handler[e->etype] (wl, netdev, &e->emsg, e->edata); } else { @@ -5863,21 +6059,6 @@ static void wl_put_event(struct wl_event_q *e) kfree(e); } -void wl_cfg80211_set_sdio_func(void *func) -{ - cfg80211_sdio_func = (struct sdio_func *)func; -} - -static void wl_clear_sdio_func(void) -{ - cfg80211_sdio_func = NULL; -} - -struct sdio_func *wl_cfg80211_get_sdio_func(void) -{ - return cfg80211_sdio_func; -} - static s32 wl_dongle_mode(struct wl_priv *wl, struct net_device *ndev, s32 iftype) { s32 infra = 0; @@ -5915,7 +6096,7 @@ static s32 wl_dongle_mode(struct wl_priv *wl, struct net_device *ndev, s32 iftyp return err; } - set_mode_by_netdev(wl, ndev, mode); + wl_set_mode_by_netdev(wl, ndev, mode); return 0; } @@ -6279,14 +6460,11 @@ s32 wl_config_dongle(struct wl_priv *wl, bool need_lock) goto default_conf_out; } - /* -EINPROGRESS: Call commit handler */ - + wl->dongle_up = true; default_conf_out: if (need_lock) rtnl_unlock(); - wl->dongle_up = true; - return err; } @@ -6318,16 +6496,16 @@ static s32 wl_update_wiphybands(struct wl_priv *wl) static s32 __wl_cfg80211_up(struct wl_priv *wl) { s32 err = 0; - + struct net_device *ndev = wl_to_prmry_ndev(wl); WL_TRACE(("In\n")); - wl_debugfs_add_netdev_params(wl); + wl_debugfs_add_netdev_params(wl, ndev); err = wl_config_dongle(wl, false); if (unlikely(err)) return err; dhd_monitor_init(wl->pub); wl_invoke_iscan(wl); - wl_set_drv_status(wl, READY); + wl_set_drv_status(wl, READY, ndev); return err; } @@ -6335,13 +6513,14 @@ static s32 __wl_cfg80211_down(struct wl_priv *wl) { s32 err = 0; unsigned long flags; - + struct net_info *iter, *next; + struct net_device *ndev = wl_to_prmry_ndev(wl); WL_TRACE(("In\n")); /* Check if cfg80211 interface is already down */ - if (!wl_get_drv_status(wl, READY)) + if (!wl_get_drv_status(wl, READY, ndev)) return err; /* it is even not ready */ - - wl_set_drv_status(wl, SCAN_ABORTING); + for_each_ndev(wl, iter, next) + wl_set_drv_status(wl, SCAN_ABORTING, iter->ndev); wl_term_iscan(wl); flags = dhd_os_spin_lock((dhd_pub_t *)(wl->pub)); @@ -6349,15 +6528,15 @@ static s32 __wl_cfg80211_down(struct wl_priv *wl) cfg80211_scan_done(wl->scan_request, true); wl->scan_request = NULL; } - wl_clr_drv_status(wl, READY); - wl_clr_drv_status(wl, SCANNING); - wl_clr_drv_status(wl, SCAN_ABORTING); - wl_clr_drv_status(wl, CONNECTING); - wl_clr_drv_status(wl, CONNECTED); - wl_clr_drv_status(wl, DISCONNECTING); - if (wl_get_drv_status(wl, AP_CREATED)) { - wl_clr_drv_status(wl, AP_CREATED); - wl_clr_drv_status(wl, AP_CREATING); + for_each_ndev(wl, iter, next) { + wl_clr_drv_status(wl, READY, iter->ndev); + wl_clr_drv_status(wl, SCANNING, iter->ndev); + wl_clr_drv_status(wl, SCAN_ABORTING, iter->ndev); + wl_clr_drv_status(wl, CONNECTING, iter->ndev); + wl_clr_drv_status(wl, CONNECTED, iter->ndev); + wl_clr_drv_status(wl, DISCONNECTING, iter->ndev); + wl_clr_drv_status(wl, AP_CREATED, iter->ndev); + wl_clr_drv_status(wl, AP_CREATING, iter->ndev); } wl_to_prmry_ndev(wl)->ieee80211_ptr->iftype = NL80211_IFTYPE_STATION; @@ -6431,24 +6610,26 @@ static s32 wl_dongle_probecap(struct wl_priv *wl) return err; } -static void *wl_read_prof(struct wl_priv *wl, s32 item) +static void *wl_read_prof(struct wl_priv *wl, struct net_device *ndev, s32 item) { unsigned long flags; void *rptr = NULL; - + struct wl_profile *profile = wl_get_profile_by_netdev(wl, ndev); + if (!profile) + return NULL; flags = dhd_os_spin_lock((dhd_pub_t *)(wl->pub)); switch (item) { case WL_PROF_SEC: - rptr = &wl->profile->sec; + rptr = &profile->sec; break; case WL_PROF_ACT: - rptr = &wl->profile->active; + rptr = &profile->active; break; case WL_PROF_BSSID: - rptr = &wl->profile->bssid; + rptr = profile->bssid; break; case WL_PROF_SSID: - rptr = &wl->profile->ssid; + rptr = &profile->ssid; break; } dhd_os_spin_unlock((dhd_pub_t *)(wl->pub), flags); @@ -6458,39 +6639,41 @@ static void *wl_read_prof(struct wl_priv *wl, s32 item) } static s32 -wl_update_prof(struct wl_priv *wl, const wl_event_msg_t *e, void *data, - s32 item) +wl_update_prof(struct wl_priv *wl, struct net_device *ndev, + const wl_event_msg_t *e, void *data, s32 item) { s32 err = 0; struct wlc_ssid *ssid; unsigned long flags; - + struct wl_profile *profile = wl_get_profile_by_netdev(wl, ndev); + if (!profile) + return WL_INVALID; flags = dhd_os_spin_lock((dhd_pub_t *)(wl->pub)); switch (item) { case WL_PROF_SSID: ssid = (wlc_ssid_t *) data; - memset(wl->profile->ssid.SSID, 0, - sizeof(wl->profile->ssid.SSID)); - memcpy(wl->profile->ssid.SSID, ssid->SSID, ssid->SSID_len); - wl->profile->ssid.SSID_len = ssid->SSID_len; + memset(profile->ssid.SSID, 0, + sizeof(profile->ssid.SSID)); + memcpy(profile->ssid.SSID, ssid->SSID, ssid->SSID_len); + profile->ssid.SSID_len = ssid->SSID_len; break; case WL_PROF_BSSID: if (data) - memcpy(wl->profile->bssid, data, ETHER_ADDR_LEN); + memcpy(profile->bssid, data, ETHER_ADDR_LEN); else - memset(wl->profile->bssid, 0, ETHER_ADDR_LEN); + memset(profile->bssid, 0, ETHER_ADDR_LEN); break; case WL_PROF_SEC: - memcpy(&wl->profile->sec, data, sizeof(wl->profile->sec)); + memcpy(&profile->sec, data, sizeof(profile->sec)); break; case WL_PROF_ACT: - wl->profile->active = *(bool *)data; + profile->active = *(bool *)data; break; case WL_PROF_BEACONINT: - wl->profile->beacon_interval = *(u16 *)data; + profile->beacon_interval = *(u16 *)data; break; case WL_PROF_DTIMPERIOD: - wl->profile->dtim_period = *(u8 *)data; + profile->dtim_period = *(u8 *)data; break; default: WL_ERR(("unsupported item (%d)\n", item)); @@ -6514,7 +6697,7 @@ void wl_cfg80211_dbg_level(u32 level) static bool wl_is_ibssmode(struct wl_priv *wl, struct net_device *ndev) { - return get_mode_by_netdev(wl, ndev) == WL_MODE_IBSS; + return wl_get_mode_by_netdev(wl, ndev) == WL_MODE_IBSS; } static __used bool wl_is_ibssstarter(struct wl_priv *wl) @@ -6663,7 +6846,7 @@ void *wl_cfg80211_request_fw(s8 *file_name) if (!test_bit(WL_FW_LOADING_DONE, &wl->fw->status)) { err = request_firmware(&wl->fw->fw_entry, file_name, - &wl_cfg80211_get_sdio_func()->dev); + wl_cfg80211_get_parent_dev()); if (unlikely(err)) { WL_ERR(("Could not download fw (%d)\n", err)); goto req_fw_out; @@ -6676,7 +6859,7 @@ void *wl_cfg80211_request_fw(s8 *file_name) } } else if (!test_bit(WL_NVRAM_LOADING_DONE, &wl->fw->status)) { err = request_firmware(&wl->fw->fw_entry, file_name, - &wl_cfg80211_get_sdio_func()->dev); + wl_cfg80211_get_parent_dev()); if (unlikely(err)) { WL_ERR(("Could not download nvram (%d)\n", err)); goto req_fw_out; @@ -6766,8 +6949,8 @@ s32 wl_cfg80211_set_wps_p2p_ie(struct net_device *net, char *buf, int len, if (wl->p2p && wl->p2p->vif_created) { ndev = wl_to_p2p_bss_ndev(wl, P2PAPI_BSSCFG_CONNECTION); bssidx = wl_to_p2p_bss_bssidx(wl, P2PAPI_BSSCFG_CONNECTION); - } else if (wl_get_drv_status(wl, AP_CREATING) || - wl_get_drv_status(wl, AP_CREATED)) { + } else if (wl_get_drv_status(wl, AP_CREATING, net) || + wl_get_drv_status(wl, AP_CREATED, net)) { ndev = net; bssidx = 0; } @@ -6820,10 +7003,11 @@ static __used void wl_dongle_poweroff(struct wl_priv *wl) dhd_customer_gpio_wlan_ctrl(WLAN_RESET_OFF); } -static int wl_debugfs_add_netdev_params(struct wl_priv *wl) +static int wl_debugfs_add_netdev_params(struct wl_priv *wl, struct net_device *ndev) { char buf[10+IFNAMSIZ]; struct dentry *fd; + struct wl_profile *profile = wl_get_profile_by_netdev(wl, ndev); s32 err = 0; WL_TRACE(("In\n")); @@ -6831,14 +7015,14 @@ static int wl_debugfs_add_netdev_params(struct wl_priv *wl) wl->debugfsdir = debugfs_create_dir(buf, wl_to_wiphy(wl)->debugfsdir); fd = debugfs_create_u16("beacon_int", S_IRUGO, wl->debugfsdir, - (u16 *)&wl->profile->beacon_interval); + (u16 *)&profile->beacon_interval); if (!fd) { err = -ENOMEM; goto err_out; } fd = debugfs_create_u8("dtim_period", S_IRUGO, wl->debugfsdir, - (u8 *)&wl->profile->dtim_period); + (u8 *)&profile->dtim_period); if (!fd) { err = -ENOMEM; goto err_out; @@ -6881,7 +7065,7 @@ static int wl_setup_rfkill(struct wl_priv *wl, bool setup) return -EINVAL; if (setup) { wl->rfkill = rfkill_alloc("brcmfmac-wifi", - &wl_cfg80211_get_sdio_func()->dev, + wl_cfg80211_get_parent_dev(), RFKILL_TYPE_WLAN, &wl_rfkill_ops, (void *)wl); if (!wl->rfkill) { @@ -7375,3 +7559,18 @@ int wl_cfg80211_set_btcoex_dhcp(struct net_device *dev, char *command) return (strlen("OK")); } + +struct device *wl_cfg80211_get_parent_dev(void) +{ + return cfg80211_parent_dev; +} + +void wl_cfg80211_set_parent_dev(void *dev) +{ + cfg80211_parent_dev = dev; +} + +static void wl_cfg80211_clear_parent_dev(void) +{ + cfg80211_parent_dev = NULL; +} diff --git a/drivers/net/wireless/bcmdhd/wl_cfg80211.h b/drivers/net/wireless/bcmdhd/wl_cfg80211.h index 232db1b1f830..18ff27680cb0 100644 --- a/drivers/net/wireless/bcmdhd/wl_cfg80211.h +++ b/drivers/net/wireless/bcmdhd/wl_cfg80211.h @@ -2,13 +2,13 @@ * Linux cfg80211 driver * * Copyright (C) 1999-2011, Broadcom Corporation - * + * * Unless you and Broadcom execute a separate written software license * agreement governing use of this software, this software is licensed to you * under the terms of the GNU General Public License version 2 (the "GPL"), * available at http://www.broadcom.com/licenses/GPLv2.php, with the * following added to such license: - * + * * As a special exception, the copyright holders of this software give you * permission to link this software with independent modules, and to copy and * distribute the resulting executable under terms of your choice, provided that @@ -16,7 +16,7 @@ * the license of that module. An independent module is a module which is not * derived from this software. The special exception does not apply to any * modifications of the software. - * + * * Notwithstanding the above, under no circumstances may you combine this * software in any way with any other Broadcom software provided under a license * other than the GPL, without Broadcom's express prior written consent. @@ -130,10 +130,11 @@ do { \ #define WL_FILE_NAME_MAX 256 #define WL_DWELL_TIME 200 #define WL_LONG_DWELL_TIME 1000 -#define VWDEV_CNT 3 +#define IFACE_MAX_CNT 2 #define WL_SCAN_TIMER_INTERVAL_MS 8000 /* Scan timeout */ +#define WL_INVALID -1 /* dongle status */ enum wl_status { WL_STATUS_READY = 0, @@ -198,10 +199,6 @@ struct beacon_proberesp { /* dongle configuration */ struct wl_conf { - struct net_mode { - struct net_device *ndev; - s32 type; - } mode [VWDEV_CNT + 1]; /* adhoc , infrastructure or ap */ u32 frag_threshold; u32 rts_threshold; u32 retry_short; @@ -262,16 +259,24 @@ struct wl_ibss { /* dongle profile */ struct wl_profile { u32 mode; + s32 band; struct wlc_ssid ssid; + struct wl_security sec; + struct wl_ibss ibss; u8 bssid[ETHER_ADDR_LEN]; u16 beacon_interval; u8 dtim_period; - struct wl_security sec; - struct wl_ibss ibss; - s32 band; bool active; }; +struct net_info { + struct net_device *ndev; + struct wireless_dev *wdev; + struct wl_profile profile; /* holding dongle profile */ + s32 mode; + unsigned long sme_state; + struct list_head list; /* list of all net_info structure */ +}; typedef s32(*ISCAN_HANDLER) (struct wl_priv *wl); /* dongle iscan controller */ @@ -323,9 +328,10 @@ struct wl_pmk_list { #define ESCAN_BUF_SIZE (64 * 1024) struct escan_info { - u32 escan_state; - u8 escan_buf[ESCAN_BUF_SIZE]; - struct wiphy *wiphy; + u32 escan_state; + u8 escan_buf[ESCAN_BUF_SIZE]; + struct wiphy *wiphy; + struct net_device *ndev; }; struct ap_info { @@ -341,14 +347,14 @@ struct ap_info { }; struct btcoex_info { struct timer_list timer; - uint32 timer_ms; - uint32 timer_on; - uint32 ts_dhcp_start; /* ms ts ecord time stats */ - uint32 ts_dhcp_ok; /* ms ts ecord time stats */ - bool dhcp_done; /* flag, indicates that host done with - * dhcp before t1/t2 expiration - */ - int bt_state; + u32 timer_ms; + u32 timer_on; + u32 ts_dhcp_start; /* ms ts ecord time stats */ + u32 ts_dhcp_ok; /* ms ts ecord time stats */ + bool dhcp_done; /* flag, indicates that host done with + * dhcp before t1/t2 expiration + */ + s32 bt_state; struct work_struct work; struct net_device *dev; }; @@ -363,11 +369,15 @@ struct sta_info { /* dongle private data of cfg80211 interface */ struct wl_priv { struct wireless_dev *wdev; /* representing wl cfg80211 device */ - struct wireless_dev *vwdev[VWDEV_CNT]; + + struct wireless_dev *p2p_wdev; /* representing wl cfg80211 device for P2P */ + struct net_device *p2p_net; /* reference to p2p0 interface */ + struct wl_conf *conf; /* dongle configuration */ struct cfg80211_scan_request *scan_request; /* scan request object */ EVENT_HANDLER evt_handler[WLC_E_LAST]; struct list_head eq_list; /* used for event queue */ + struct list_head net_list; /* used for struct net_info */ spinlock_t eq_lock; /* for event queue synchronization */ struct mutex usr_sync; /* maily for dongle up/down synchronization */ struct wl_scan_results *bss_list; @@ -375,14 +385,8 @@ struct wl_priv { /* scan request object for internal purpose */ struct wl_scan_req *scan_req_int; - - /* bss information for cfg80211 layer */ - struct wl_cfg80211_bss_info *bss_info; /* information element object for internal purpose */ struct wl_ie ie; - - /* for synchronization of main event thread */ - struct wl_profile *profile; /* holding dongle profile */ struct wl_iscan_ctrl *iscan; /* iscan controller */ /* association information container */ @@ -392,8 +396,8 @@ struct wl_priv { struct wl_fw_ctrl *fw; struct wl_pmk_list *pmk_list; /* wpa2 pmk list */ tsk_ctl_t event_tsk; /* task of main event handler thread */ - unsigned long status; /* current dongle status */ void *pub; + u32 iface_cnt; u32 channel; /* current channel */ bool iscan_on; /* iscan on/off switch */ bool iscan_kickstart; /* indicate iscan already started */ @@ -416,7 +420,7 @@ struct wl_priv { bool rf_blocked; struct ieee80211_channel remain_on_chan; enum nl80211_channel_type remain_on_chan_type; - u64 cache_cookie; + u64 last_roc_id; wait_queue_head_t dongle_event_wait; struct ap_info *ap_info; struct sta_info *sta_info; @@ -426,98 +430,183 @@ struct wl_priv { struct timer_list scan_timeout; /* Timer for catch scan event timeout */ }; -#define wl_to_wiphy(w) (w->wdev->wiphy) -#define wl_to_prmry_ndev(w) (w->wdev->netdev) -#define ndev_to_wl(n) (wdev_to_wl(n->ieee80211_ptr)) -#define wl_to_sr(w) (w->scan_req_int) -#define wl_to_ie(w) (&w->ie) -#define iscan_to_wl(i) ((struct wl_priv *)(i->data)) -#define wl_to_iscan(w) (w->iscan) -#define wl_to_conn(w) (&w->conn_info) -#define wiphy_from_scan(w) (w->escan_info.wiphy) -#define wl_get_drv_status(wl, stat) (test_bit(WL_STATUS_ ## stat, &(wl)->status)) -#define wl_set_drv_status(wl, stat) (set_bit(WL_STATUS_ ## stat, &(wl)->status)) -#define wl_clr_drv_status(wl, stat) (clear_bit(WL_STATUS_ ## stat, &(wl)->status)) -#define wl_chg_drv_status(wl, stat) (change_bit(WL_STATUS_ ## stat, &(wl)->status)) - static inline struct wl_bss_info *next_bss(struct wl_scan_results *list, struct wl_bss_info *bss) { return bss = bss ? (struct wl_bss_info *)((uintptr) bss + dtoh32(bss->length)) : list->bss_info; } -static inline s32 alloc_idx_vwdev(struct wl_priv *wl) + +static inline s32 +wl_alloc_netinfo(struct wl_priv *wl, struct net_device *ndev, + struct wireless_dev * wdev, s32 mode) { - s32 i = 0; - for (i = 0; i < VWDEV_CNT; i++) { - if (wl->vwdev[i] == NULL) - return i; + struct net_info *_net_info; + s32 err = 0; + if (wl->iface_cnt == IFACE_MAX_CNT) + return -ENOMEM; + _net_info = kzalloc(sizeof(struct net_info), GFP_KERNEL); + if (!_net_info) + err = -ENOMEM; + else { + _net_info->mode = mode; + _net_info->ndev = ndev; + _net_info->wdev = wdev; + wl->iface_cnt++; + list_add(&_net_info->list, &wl->net_list); } - WL_ERR((" *********alloc_idx_vwdev failed (%d) \n", -1)); - return -1; + return err; } -static inline s32 get_idx_vwdev_by_netdev(struct wl_priv *wl, struct net_device *ndev) +static inline void +wl_dealloc_netinfo(struct wl_priv *wl, struct net_device *ndev) { - s32 i = 0; - for (i = 0; i < VWDEV_CNT; i++) { - if ((wl->vwdev[i] != NULL) && (wl->vwdev[i]->netdev == ndev)) - return i; + struct net_info *_net_info, *next; + + list_for_each_entry_safe(_net_info, next, &wl->net_list, list) { + if (ndev && (_net_info->ndev == ndev)) { + list_del(&_net_info->list); + wl->iface_cnt--; + if (_net_info->wdev) { + kfree(_net_info->wdev); + ndev->ieee80211_ptr = NULL; + } + kfree(_net_info); + } } - WL_ERR((" *********get_idx_vwdev_by_netdev failed (%d) \n", -1)); - return -1; } +static inline void +wl_delete_all_netinfo(struct wl_priv *wl) +{ + struct net_info *_net_info, *next; + + list_for_each_entry_safe(_net_info, next, &wl->net_list, list) { + list_del(&_net_info->list); + if (_net_info->wdev) + kfree(_net_info->wdev); + kfree(_net_info); + } + wl->iface_cnt = 0; +} + +static inline bool +wl_get_status_all(struct wl_priv *wl, s32 status) -static inline s32 get_mode_by_netdev(struct wl_priv *wl, struct net_device *ndev) { - s32 i = 0; - for (i = 0; i <= VWDEV_CNT; i++) { - if (wl->conf->mode[i].ndev != NULL && (wl->conf->mode[i].ndev == ndev)) - return wl->conf->mode[i].type; + struct net_info *_net_info, *next; + u32 cnt = 0; + list_for_each_entry_safe(_net_info, next, &wl->net_list, list) { + if (_net_info->ndev && + test_bit(status, &_net_info->sme_state)) + cnt++; } - return -1; + return cnt? true: false; } -static inline void set_mode_by_netdev(struct wl_priv *wl, struct net_device *ndev, s32 type) + +static inline void +wl_set_status_by_netdev(struct wl_priv *wl, s32 status, + struct net_device *ndev, u32 op) { - s32 i = 0; - for (i = 0; i <= VWDEV_CNT; i++) { - if (type == -1) { - /* free the info of netdev */ - if (wl->conf->mode[i].ndev == ndev) { - wl->conf->mode[i].ndev = NULL; - wl->conf->mode[i].type = -1; - break; - } - } else { - if ((wl->conf->mode[i].ndev != NULL)&& - (wl->conf->mode[i].ndev == ndev)) { - /* update type of ndev */ - wl->conf->mode[i].type = type; - break; - } - else if ((wl->conf->mode[i].ndev == NULL)&& - (wl->conf->mode[i].type == -1)) { - wl->conf->mode[i].ndev = ndev; - wl->conf->mode[i].type = type; - break; + struct net_info *_net_info, *next; + + list_for_each_entry_safe(_net_info, next, &wl->net_list, list) { + if (ndev && (_net_info->ndev == ndev)) { + switch (op) { + case 1: + set_bit(status, &_net_info->sme_state); + break; + case 2: + clear_bit(status, &_net_info->sme_state); + break; + case 4: + change_bit(status, &_net_info->sme_state); + break; } } + + } +} + +static inline u32 +wl_get_status_by_netdev(struct wl_priv *wl, s32 status, + struct net_device *ndev) +{ + struct net_info *_net_info, *next; + + list_for_each_entry_safe(_net_info, next, &wl->net_list, list) { + if (ndev && (_net_info->ndev == ndev)) + return test_bit(status, &_net_info->sme_state); } + return 0; } -#define free_vwdev_by_index(wl, __i) do { \ - if (wl->vwdev[__i] != NULL) \ - kfree(wl->vwdev[__i]); \ - wl->vwdev[__i] = NULL; \ - } while (0) + +static inline s32 +wl_get_mode_by_netdev(struct wl_priv *wl, struct net_device *ndev) +{ + struct net_info *_net_info, *next; + + list_for_each_entry_safe(_net_info, next, &wl->net_list, list) { + if (ndev && (_net_info->ndev == ndev)) + return _net_info->mode; + } + return -1; +} + +static inline void +wl_set_mode_by_netdev(struct wl_priv *wl, struct net_device *ndev, + s32 mode) +{ + struct net_info *_net_info, *next; + + list_for_each_entry_safe(_net_info, next, &wl->net_list, list) { + if (ndev && (_net_info->ndev == ndev)) + _net_info->mode = mode; + } +} + +static inline struct wl_profile * +wl_get_profile_by_netdev(struct wl_priv *wl, struct net_device *ndev) +{ + struct net_info *_net_info, *next; + + list_for_each_entry_safe(_net_info, next, &wl->net_list, list) { + if (ndev && (_net_info->ndev == ndev)) + return &_net_info->profile; + } + return NULL; +} +#define wl_to_wiphy(w) (w->wdev->wiphy) +#define wl_to_prmry_ndev(w) (w->wdev->netdev) +#define ndev_to_wl(n) (wdev_to_wl(n->ieee80211_ptr)) +#define wl_to_sr(w) (w->scan_req_int) +#define wl_to_ie(w) (&w->ie) +#define iscan_to_wl(i) ((struct wl_priv *)(i->data)) +#define wl_to_iscan(w) (w->iscan) +#define wl_to_conn(w) (&w->conn_info) +#define wiphy_from_scan(w) (w->escan_info.wiphy) +#define wl_get_drv_status_all(wl, stat) \ + (wl_get_status_all(wl, WL_STATUS_ ## stat)) +#define wl_get_drv_status(wl, stat, ndev) \ + (wl_get_status_by_netdev(wl, WL_STATUS_ ## stat, ndev)) +#define wl_set_drv_status(wl, stat, ndev) \ + (wl_set_status_by_netdev(wl, WL_STATUS_ ## stat, ndev, 1)) +#define wl_clr_drv_status(wl, stat, ndev) \ + (wl_set_status_by_netdev(wl, WL_STATUS_ ## stat, ndev, 2)) +#define wl_chg_drv_status(wl, stat, ndev) \ + (wl_set_status_by_netdev(wl, WL_STATUS_ ## stat, ndev, 4)) #define for_each_bss(list, bss, __i) \ for (__i = 0; __i < list->count && __i < WL_AP_MAX; __i++, bss = next_bss(list, bss)) +#define for_each_ndev(wl, iter, next) \ + list_for_each_entry_safe(iter, next, &wl->net_list, list) + + /* In case of WPS from wpa_supplicant, pairwise siute and group suite is 0. * In addtion to that, wpa_version is WPA_VERSION_1 */ #define is_wps_conn(_sme) \ - ((_sme->crypto.wpa_versions & NL80211_WPA_VERSION_1) && \ + ((wl_cfgp2p_find_wpsie((u8 *)_sme->ie, _sme->ie_len) != NULL) && \ (!_sme->crypto.n_ciphers_pairwise) && \ (!_sme->crypto.cipher_group)) extern s32 wl_cfg80211_attach(struct net_device *ndev, void *data); @@ -526,14 +615,14 @@ extern void wl_cfg80211_detach(void); /* event handler from dongle */ extern void wl_cfg80211_event(struct net_device *ndev, const wl_event_msg_t *e, void *data); -extern void wl_cfg80211_set_sdio_func(void *func); /* set sdio function info */ -extern struct sdio_func *wl_cfg80211_get_sdio_func(void); /* set sdio function info */ +void wl_cfg80211_set_parent_dev(void *dev); +struct device *wl_cfg80211_get_parent_dev(void); + extern s32 wl_cfg80211_up(void); /* dongle up */ extern s32 wl_cfg80211_down(void); /* dongle down */ extern s32 wl_cfg80211_notify_ifadd(struct net_device *net, s32 idx, s32 bssidx, int (*_net_attach)(dhd_pub_t *dhdp, int ifidx)); extern s32 wl_cfg80211_notify_ifdel(struct net_device *ndev); -extern s32 wl_cfg80211_post_del(void *ndev); extern s32 wl_cfg80211_is_progress_ifadd(void); extern s32 wl_cfg80211_is_progress_ifchange(void); extern s32 wl_cfg80211_is_progress_ifadd(void); @@ -551,6 +640,7 @@ extern s32 wl_cfg80211_set_wps_p2p_ie(struct net_device *net, char *buf, int len enum wl_management_type type); extern s32 wl_cfg80211_set_p2p_ps(struct net_device *net, char* buf, int len); extern int wl_cfg80211_hang(struct net_device *dev, u16 reason); +extern s32 wl_mode_to_nl80211_iftype(s32 mode); /* do scan abort */ extern s32 diff --git a/drivers/net/wireless/bcmdhd/wl_cfgp2p.c b/drivers/net/wireless/bcmdhd/wl_cfgp2p.c index 4ee6557e17dd..85c36101ab41 100644 --- a/drivers/net/wireless/bcmdhd/wl_cfgp2p.c +++ b/drivers/net/wireless/bcmdhd/wl_cfgp2p.c @@ -47,7 +47,7 @@ #include #include #include - +#include static s8 ioctlbuf[WLC_IOCTL_MAXLEN]; static s8 scanparambuf[WLC_IOCTL_SMLEN]; @@ -59,6 +59,19 @@ wl_cfgp2p_has_ie(u8 *ie, u8 **tlvs, u32 *tlvs_len, const u8 *oui, u32 oui_len, u static s32 wl_cfgp2p_vndr_ie(struct net_device *ndev, s32 bssidx, s32 pktflag, s8 *oui, s32 ie_id, s8 *data, s32 data_len, s32 delete); + +static int wl_cfgp2p_start_xmit(struct sk_buff *skb, struct net_device *ndev); +static int wl_cfgp2p_do_ioctl(struct net_device *net, struct ifreq *ifr, int cmd); +static int wl_cfgp2p_if_open(struct net_device *net); +static int wl_cfgp2p_if_stop(struct net_device *net); + +static const struct net_device_ops wl_cfgp2p_if_ops = { + .ndo_open = wl_cfgp2p_if_open, + .ndo_stop = wl_cfgp2p_if_stop, + .ndo_do_ioctl = wl_cfgp2p_do_ioctl, + .ndo_start_xmit = wl_cfgp2p_start_xmit, +}; + /* * Initialize variables related to P2P * @@ -569,7 +582,7 @@ wl_cfgp2p_escan(struct wl_priv *wl, struct net_device *dev, u16 active, eparams->params.nprobes = htod32(P2PAPI_SCAN_NPROBES); eparams->params.home_time = htod32(P2PAPI_SCAN_HOME_TIME_MS); - if (wl_get_drv_status(wl, CONNECTED)) + if (wl_get_drv_status_all(wl, CONNECTED)) eparams->params.active_time = htod32(-1); else if (num_chans == 3) eparams->params.active_time = htod32(P2PAPI_SCAN_SOCIAL_DWELL_TIME_MS); @@ -670,7 +683,7 @@ wl_cfgp2p_set_management_ie(struct wl_priv *wl, struct net_device *ndev, s32 bss CFGP2P_ERR(("not suitable type\n")); return -1; } - } else if (get_mode_by_netdev(wl, ndev) == WL_MODE_AP) { + } else if (wl_get_mode_by_netdev(wl, ndev) == WL_MODE_AP) { switch (pktflag) { case VNDR_IE_PRBRSP_FLAG : mgmt_ie_buf = wl->ap_info->probe_res_ie; @@ -689,7 +702,7 @@ wl_cfgp2p_set_management_ie(struct wl_priv *wl, struct net_device *ndev, s32 bss return -1; } bssidx = 0; - } else if (bssidx == -1 && get_mode_by_netdev(wl, ndev) == WL_MODE_BSS) { + } else if (bssidx == -1 && wl_get_mode_by_netdev(wl, ndev) == WL_MODE_BSS) { switch (pktflag) { case VNDR_IE_PRBREQ_FLAG : mgmt_ie_buf = wl->sta_info->probe_req_ie; @@ -964,7 +977,7 @@ wl_cfgp2p_listen_complete(struct wl_priv *wl, struct net_device *ndev, del_timer_sync(&wl->p2p->listen_timer); spin_unlock_bh(&wl->p2p->timer_lock); } - cfg80211_remain_on_channel_expired(ndev, wl->cache_cookie, &wl->remain_on_chan, + cfg80211_remain_on_channel_expired(ndev, wl->last_roc_id, &wl->remain_on_chan, wl->remain_on_chan_type, GFP_KERNEL); } else wl_clr_p2p_status(wl, LISTEN_EXPIRED); @@ -1467,3 +1480,145 @@ s32 wl_cfgp2p_set_p2p_ps(struct wl_priv *wl, struct net_device *ndev, char* buf, } return ret; } + +s32 +wl_cfgp2p_register_ndev(struct wl_priv *wl) +{ + int ret = 0; + struct net_device* net = NULL; + struct wireless_dev *wdev; + uint8 temp_addr[ETHER_ADDR_LEN] = { 0x00, 0x90, 0x4c, 0x33, 0x22, 0x11 }; + + /* Allocate etherdev, including space for private structure */ + if (!(net = alloc_etherdev(sizeof(wl)))) { + CFGP2P_ERR(("%s: OOM - alloc_etherdev\n", __FUNCTION__)); + goto fail; + } + + strcpy(net->name, "p2p%d"); + net->name[IFNAMSIZ - 1] = '\0'; + + /* Copy the reference to wl_priv */ + memcpy((void *)netdev_priv(net), &wl, sizeof(wl)); + +#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 31)) + ASSERT(!net->open); + net->do_ioctl = wl_cfgp2p_do_ioctl; + net->hard_start_xmit = wl_cfgp2p_start_xmit; + net->open = wl_cfgp2p_if_open; + net->stop = wl_cfgp2p_if_stop; +#else + ASSERT(!net->netdev_ops); + net->netdev_ops = &wl_cfgp2p_if_ops; +#endif + + /* Register with a dummy MAC addr */ + memcpy(net->dev_addr, temp_addr, ETHER_ADDR_LEN); + + wdev = kzalloc(sizeof(*wdev), GFP_KERNEL); + if (unlikely(!wdev)) { + WL_ERR(("Could not allocate wireless device\n")); + return -ENOMEM; + } + + wdev->wiphy = wl->wdev->wiphy; + + wdev->iftype = wl_mode_to_nl80211_iftype(WL_MODE_BSS); + + net->ieee80211_ptr = wdev; + + SET_NETDEV_DEV(net, wiphy_dev(wdev->wiphy)); + + /* Associate p2p0 network interface with new wdev */ + wdev->netdev = net; + + /* store p2p net ptr for further reference. Note that iflist won't have this + * entry as there corresponding firmware interface is a "Hidden" interface. + */ + if (wl->p2p_net) { + CFGP2P_ERR(("p2p_net defined already.\n")); + return -EINVAL; + } else { + wl->p2p_wdev = wdev; + wl->p2p_net = net; + } + + ret = register_netdev(net); + if (ret) { + CFGP2P_ERR((" register_netdevice failed (%d)\n", ret)); + goto fail; + } + + printk("%s: P2P Interface Registered\n", net->name); + + return ret; +fail: + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 31) + net->open = NULL; +#else + net->netdev_ops = NULL; +#endif + + if (net) { + unregister_netdev(net); + free_netdev(net); + } + + return -ENODEV; +} + +s32 +wl_cfgp2p_unregister_ndev(struct wl_priv *wl) +{ + + if (!wl || !wl->p2p_net) { + CFGP2P_ERR(("Invalid Ptr\n")); + return -EINVAL; + } + + unregister_netdev(wl->p2p_net); + free_netdev(wl->p2p_net); + + return 0; +} + +static int wl_cfgp2p_start_xmit(struct sk_buff *skb, struct net_device *ndev) +{ + CFGP2P_DBG(("(%s) is not used for data operations. Droping the packet. \n", ndev->name)); + return 0; +} + +static int wl_cfgp2p_do_ioctl(struct net_device *net, struct ifreq *ifr, int cmd) +{ + int ret = 0; + struct wl_priv *wl = *(struct wl_priv **)netdev_priv(net); + struct net_device *ndev = wl_to_prmry_ndev(wl); + + /* There is no ifidx corresponding to p2p0 in our firmware. So we should + * not Handle any IOCTL cmds on p2p0 other than ANDROID PRIVATE CMDs. + * For Android PRIV CMD handling map it to primary I/F + */ + if (cmd == SIOCDEVPRIVATE+1) { + ret = wl_android_priv_cmd(ndev, ifr, cmd); + + } else { + CFGP2P_ERR(("%s: IOCTL req 0x%x on p2p0 I/F. Ignoring. \n", + __FUNCTION__, cmd)); + return -1; + } + + return ret; +} + +static int wl_cfgp2p_if_open(struct net_device *net) +{ + CFGP2P_DBG(("Do Nothing \n")); + return 0; +} + +static int wl_cfgp2p_if_stop(struct net_device *net) +{ + CFGP2P_DBG(("Do Nothing \n")); + return 0; +} diff --git a/drivers/net/wireless/bcmdhd/wl_cfgp2p.h b/drivers/net/wireless/bcmdhd/wl_cfgp2p.h index 5a69168c6a3a..6934d8f1c9be 100644 --- a/drivers/net/wireless/bcmdhd/wl_cfgp2p.h +++ b/drivers/net/wireless/bcmdhd/wl_cfgp2p.h @@ -103,11 +103,11 @@ enum wl_cfgp2p_status { #define wl_to_p2p_bss(wl, type) ((wl)->p2p->bss_idx[type]) #define wl_get_p2p_status(wl, stat) ((!(wl)->p2p_supported) ? 0 : test_bit(WLP2P_STATUS_ ## stat, \ &(wl)->p2p->status)) -#define wl_set_p2p_status(wl, stat) ((!(wl)->p2p_supported) ? : set_bit(WLP2P_STATUS_ ## stat, \ +#define wl_set_p2p_status(wl, stat) ((!(wl)->p2p_supported) ? 0 : set_bit(WLP2P_STATUS_ ## stat, \ &(wl)->p2p->status)) -#define wl_clr_p2p_status(wl, stat) ((!(wl)->p2p_supported) ? : clear_bit(WLP2P_STATUS_ ## stat, \ +#define wl_clr_p2p_status(wl, stat) ((!(wl)->p2p_supported) ? 0 : clear_bit(WLP2P_STATUS_ ## stat, \ &(wl)->p2p->status)) -#define wl_chg_p2p_status(wl, stat) ((!(wl)->p2p_supported) ? : change_bit(WLP2P_STATUS_ ## stat, \ +#define wl_chg_p2p_status(wl, stat) ((!(wl)->p2p_supported) ? 0 : change_bit(WLP2P_STATUS_ ## stat, \ &(wl)->p2p->status)) #define p2p_on(wl) ((wl)->p2p->on) #define p2p_scan(wl) ((wl)->p2p->scan) @@ -235,6 +235,12 @@ wl_cfgp2p_get_p2p_noa(struct wl_priv *wl, struct net_device *ndev, char* buf, in extern s32 wl_cfgp2p_set_p2p_ps(struct wl_priv *wl, struct net_device *ndev, char* buf, int len); +extern s32 +wl_cfgp2p_register_ndev(struct wl_priv *wl); + +extern s32 +wl_cfgp2p_unregister_ndev(struct wl_priv *wl); + /* WiFi Direct */ #define SOCIAL_CHAN_1 1 #define SOCIAL_CHAN_2 6 diff --git a/drivers/net/wireless/bcmdhd/wl_iw.c b/drivers/net/wireless/bcmdhd/wl_iw.c index d6aa56f858f4..2537c2b6ba65 100644 --- a/drivers/net/wireless/bcmdhd/wl_iw.c +++ b/drivers/net/wireless/bcmdhd/wl_iw.c @@ -21,7 +21,7 @@ * software in any way with any other Broadcom software provided under a license * other than the GPL, without Broadcom's express prior written consent. * - * $Id: wl_iw.c,v 1.132.2.18 2011-02-05 01:44:47 Exp $ + * $Id: wl_iw.c,v 1.132.2.18 2011-02-05 01:44:47 $ */ #include @@ -1564,6 +1564,63 @@ exit_proc: net_os_wake_unlock(dev); return res; } + +static int +wl_iw_set_pno_setadd( + struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, + char *extra +) +{ + int ret = -1; + char *tmp_ptr; + int size, tmp_size; + + net_os_wake_lock(dev); + WL_ERROR(("\n### %s: info->cmd:%x, info->flags:%x, u.data=0x%p, u.len=%d\n", + __FUNCTION__, info->cmd, info->flags, + wrqu->data.pointer, wrqu->data.length)); + + if (g_onoff == G_WLAN_SET_OFF) { + WL_TRACE(("%s: driver is not up yet after START\n", __FUNCTION__)); + goto exit_proc; + } + + if (wrqu->data.length <= strlen(PNOSETADD_SET_CMD) + sizeof(cmd_tlv_t)) { + WL_ERROR(("%s argument=%d less than %d\n", __FUNCTION__, + wrqu->data.length, (int)(strlen(PNOSETADD_SET_CMD) + sizeof(cmd_tlv_t)))); + goto exit_proc; + } + + + bcopy(PNOSETUP_SET_CMD, extra, strlen(PNOSETUP_SET_CMD)); + + tmp_ptr = extra + strlen(PNOSETUP_SET_CMD); + size = wrqu->data.length - strlen(PNOSETUP_SET_CMD); + tmp_size = size; + + while (*tmp_ptr && tmp_size > 0) { + if ((*tmp_ptr == 'S') && (size - tmp_size) >= sizeof(cmd_tlv_t)) { + *(tmp_ptr + 1) = ((*(tmp_ptr + 1) - '0') << 4) + (*(tmp_ptr + 2) - '0'); + memmove(tmp_ptr + 2, tmp_ptr + 3, tmp_size - 3); + tmp_size -= 2 + *(tmp_ptr + 1); + tmp_ptr += 2 + *(tmp_ptr + 1); + size--; + } else { + tmp_ptr++; + tmp_size--; + } + } + + wrqu->data.length = strlen(PNOSETUP_SET_CMD) + size; + ret = wl_iw_set_pno_set(dev, info, wrqu, extra); + +exit_proc: + net_os_wake_unlock(dev); + return ret; + +} #endif static int @@ -2567,6 +2624,8 @@ wl_iw_get_range( IW_EVENT_CAPA_SET(range->event_capa, SIOCGIWSCAN); IW_EVENT_CAPA_SET(range->event_capa, IWEVTXDROP); IW_EVENT_CAPA_SET(range->event_capa, IWEVMICHAELMICFAILURE); + IW_EVENT_CAPA_SET(range->event_capa, IWEVASSOCREQIE); + IW_EVENT_CAPA_SET(range->event_capa, IWEVASSOCRESPIE); IW_EVENT_CAPA_SET(range->event_capa, IWEVPMKIDCAND); #endif @@ -5473,7 +5532,15 @@ wl_iw_set_wpaauth( switch (paramid) { case IW_AUTH_WPA_VERSION: - iw->wpaversion = paramval; + if (paramval & IW_AUTH_WPA_VERSION_DISABLED) + val = WPA_AUTH_DISABLED; + else if (paramval & (IW_AUTH_WPA_VERSION_WPA)) + val = WPA_AUTH_PSK | WPA_AUTH_UNSPECIFIED; + else if (paramval & IW_AUTH_WPA_VERSION_WPA2) + val = WPA2_AUTH_PSK | WPA2_AUTH_UNSPECIFIED; + WL_ERROR(("%s: %d: setting wpa_auth to 0x%0x\n", __FUNCTION__, __LINE__, val)); + if ((error = dev_wlc_intvar_set(dev, "wpa_auth", val))) + return error; break; case IW_AUTH_CIPHER_PAIRWISE: @@ -5491,7 +5558,27 @@ wl_iw_set_wpaauth( break; case IW_AUTH_KEY_MGMT: - if (paramval & IW_AUTH_KEY_MGMT_PSK) { + if ((error = dev_wlc_intvar_get(dev, "wpa_auth", &val))) + return error; + + if (val & (WPA_AUTH_PSK | WPA_AUTH_UNSPECIFIED)) { + if (paramval & IW_AUTH_KEY_MGMT_PSK) + val = WPA_AUTH_PSK; + else + val = WPA_AUTH_UNSPECIFIED; + if (paramval & 0x04) + val |= WPA2_AUTH_FT; + } + else if (val & (WPA2_AUTH_PSK | WPA2_AUTH_UNSPECIFIED)) { + if (paramval & IW_AUTH_KEY_MGMT_PSK) + val = WPA2_AUTH_PSK; + else + val = WPA2_AUTH_UNSPECIFIED; + if (paramval & 0x04) + val |= WPA2_AUTH_FT; + } + + else if (paramval & IW_AUTH_KEY_MGMT_PSK) { if (iw->wpaversion == IW_AUTH_WPA_VERSION_WPA) val = WPA_AUTH_PSK; else if (iw->wpaversion == IW_AUTH_WPA_VERSION_WPA2) @@ -7526,6 +7613,8 @@ wl_iw_set_priv( ret = wl_iw_set_pno_reset(dev, info, (union iwreq_data *)dwrq, extra); else if (strnicmp(extra, PNOSETUP_SET_CMD, strlen(PNOSETUP_SET_CMD)) == 0) ret = wl_iw_set_pno_set(dev, info, (union iwreq_data *)dwrq, extra); + else if (strnicmp(extra, PNOSETADD_SET_CMD, strlen(PNOSETADD_SET_CMD)) == 0) + ret = wl_iw_set_pno_setadd(dev, info, (union iwreq_data *)dwrq, extra); else if (strnicmp(extra, PNOENABLE_SET_CMD, strlen(PNOENABLE_SET_CMD)) == 0) ret = wl_iw_set_pno_enable(dev, info, (union iwreq_data *)dwrq, extra); #endif @@ -8251,6 +8340,21 @@ wl_iw_event(struct net_device *dev, wl_event_msg_t *e, void* data) break; } + + case WLC_E_ASSOC_REQ_IE: + cmd = IWEVASSOCREQIE; + wrqu.data.length = datalen; + if (datalen < sizeof(extra)) + memcpy(extra, data, datalen); + break; + + case WLC_E_ASSOC_RESP_IE: + cmd = IWEVASSOCRESPIE; + wrqu.data.length = datalen; + if (datalen < sizeof(extra)) + memcpy(extra, data, datalen); + break; + case WLC_E_PMKID_CACHE: { if (data) { diff --git a/drivers/net/wireless/bcmdhd/wl_iw.h b/drivers/net/wireless/bcmdhd/wl_iw.h index c0cc14bdde4e..faca5f72e223 100644 --- a/drivers/net/wireless/bcmdhd/wl_iw.h +++ b/drivers/net/wireless/bcmdhd/wl_iw.h @@ -21,7 +21,7 @@ * software in any way with any other Broadcom software provided under a license * other than the GPL, without Broadcom's express prior written consent. * - * $Id: wl_iw.h,v 1.15.80.6 2010-12-23 01:13:23 Exp $ + * $Id: wl_iw.h,v 1.15.80.6 2010-12-23 01:13:23 $ */ @@ -51,9 +51,10 @@ #define PNOSSIDCLR_SET_CMD "PNOSSIDCLR" #define PNOSETUP_SET_CMD "PNOSETUP " +#define PNOSETADD_SET_CMD "PNOSETADD" #define PNOENABLE_SET_CMD "PNOFORCE" #define PNODEBUG_SET_CMD "PNODEBUG" -#define TXPOWER_SET_CMD "TXPOWER" +#define TXPOWER_SET_CMD "TXPOWER" #define MAC2STR(a) (a)[0], (a)[1], (a)[2], (a)[3], (a)[4], (a)[5] #define MACSTR "%02x:%02x:%02x:%02x:%02x:%02x" @@ -226,6 +227,18 @@ extern void get_customized_country_code(char *country_iso_code, wl_country_t *cs iwe_stream_add_point(stream, ends, iwe, extra) #endif +extern int dhd_pno_enable(dhd_pub_t *dhd, int pfn_enabled); +extern int dhd_pno_clean(dhd_pub_t *dhd); +extern int dhd_pno_set(dhd_pub_t *dhd, wlc_ssid_t* ssids_local, int nssid, + ushort scan_fr, int pno_repeat, int pno_freq_expo_max); +extern int dhd_pno_get_status(dhd_pub_t *dhd); +extern int dhd_dev_pno_reset(struct net_device *dev); +extern int dhd_dev_pno_set(struct net_device *dev, wlc_ssid_t* ssids_local, + int nssid, ushort scan_fr, int pno_repeat, int pno_freq_expo_max); +extern int dhd_dev_pno_enable(struct net_device *dev, int pfn_enabled); +extern int dhd_dev_get_pno_status(struct net_device *dev); +extern int dhd_get_dtim_skip(dhd_pub_t *dhd); + void dhd_bus_country_set(struct net_device *dev, wl_country_t *cspec); #define PNO_TLV_PREFIX 'S' -- cgit v1.2.3 From f886f69c2e3a878ce955d710e0699de0244c614b Mon Sep 17 00:00:00 2001 From: Dmitry Shmidt Date: Tue, 24 Jan 2012 13:47:47 -0800 Subject: net: wireless: bcmdhd: Update to Version 5.90.195.19 - Add WFD changes - Add extra locking for internal ioctl operations Signed-off-by: Dmitry Shmidt --- drivers/net/wireless/bcmdhd/Makefile | 4 +- drivers/net/wireless/bcmdhd/bcmsdh_linux.c | 23 +- drivers/net/wireless/bcmdhd/bcmsdh_sdmmc.c | 4 +- drivers/net/wireless/bcmdhd/dhd.h | 10 +- drivers/net/wireless/bcmdhd/dhd_cdc.c | 7 +- drivers/net/wireless/bcmdhd/dhd_cfg80211.c | 862 ++++++++ drivers/net/wireless/bcmdhd/dhd_cfg80211.h | 42 + drivers/net/wireless/bcmdhd/dhd_common.c | 7 +- drivers/net/wireless/bcmdhd/dhd_linux.c | 103 +- drivers/net/wireless/bcmdhd/dhd_sdio.c | 4 +- drivers/net/wireless/bcmdhd/include/dhdioctl.h | 3 +- drivers/net/wireless/bcmdhd/include/epivers.h | 8 +- drivers/net/wireless/bcmdhd/include/proto/802.11.h | 12 +- drivers/net/wireless/bcmdhd/include/wlioctl.h | 19 +- drivers/net/wireless/bcmdhd/wl_android.c | 22 +- drivers/net/wireless/bcmdhd/wl_android.h | 2 +- drivers/net/wireless/bcmdhd/wl_cfg80211.c | 2142 ++++++-------------- drivers/net/wireless/bcmdhd/wl_cfg80211.h | 125 +- drivers/net/wireless/bcmdhd/wl_cfgp2p.c | 245 ++- drivers/net/wireless/bcmdhd/wl_cfgp2p.h | 27 +- drivers/net/wireless/bcmdhd/wl_linux_mon.c | 409 ++++ drivers/net/wireless/bcmdhd/wldev_common.c | 69 +- drivers/net/wireless/bcmdhd/wldev_common.h | 20 +- 23 files changed, 2484 insertions(+), 1685 deletions(-) create mode 100644 drivers/net/wireless/bcmdhd/dhd_cfg80211.c create mode 100644 drivers/net/wireless/bcmdhd/dhd_cfg80211.h create mode 100644 drivers/net/wireless/bcmdhd/wl_linux_mon.c (limited to 'drivers/net') diff --git a/drivers/net/wireless/bcmdhd/Makefile b/drivers/net/wireless/bcmdhd/Makefile index 85e93f7a56c3..14c041dcc2b1 100644 --- a/drivers/net/wireless/bcmdhd/Makefile +++ b/drivers/net/wireless/bcmdhd/Makefile @@ -37,7 +37,7 @@ endif DHDOFILES = aiutils.o bcmsdh_sdmmc_linux.o dhd_linux.o siutils.o bcmutils.o \ dhd_linux_sched.o bcmwifi.o dhd_sdio.o bcmevent.o dhd_bta.o hndpmu.o \ bcmsdh.o dhd_cdc.o bcmsdh_linux.o dhd_common.o linux_osl.o \ - bcmsdh_sdmmc.o dhd_custom_gpio.o sbutils.o wldev_common.o wl_android.o + bcmsdh_sdmmc.o dhd_custom_gpio.o sbutils.o wldev_common.o wl_android.o dhd_cfg80211.o obj-$(CONFIG_BCMDHD) += bcmdhd.o bcmdhd-objs += $(DHDOFILES) @@ -48,7 +48,7 @@ DHDCFLAGS += -DSOFTAP endif ifeq ($(CONFIG_BCMDHD_CFG80211),y) -bcmdhd-objs += wl_cfg80211.o wl_cfgp2p.o dhd_linux_mon.o +bcmdhd-objs += wl_cfg80211.o wl_cfgp2p.o wl_linux_mon.o DHDCFLAGS += -DWL_CFG80211 endif diff --git a/drivers/net/wireless/bcmdhd/bcmsdh_linux.c b/drivers/net/wireless/bcmdhd/bcmsdh_linux.c index d467e4b5630e..8d38a9a98012 100644 --- a/drivers/net/wireless/bcmdhd/bcmsdh_linux.c +++ b/drivers/net/wireless/bcmdhd/bcmsdh_linux.c @@ -21,7 +21,7 @@ * software in any way with any other Broadcom software provided under a license * other than the GPL, without Broadcom's express prior written consent. * - * $Id: bcmsdh_linux.c,v 1.72.6.5 2010-12-23 01:13:15 Exp $ + * $Id: bcmsdh_linux.c 294990 2011-11-09 00:13:10Z $ */ /** @@ -277,6 +277,7 @@ int bcmsdh_remove_bcmdhd(struct device *dev) sdhc = sdhcinfo; drvinfo.detach(sdhc->ch); bcmsdh_detach(sdhc->osh, sdhc->sdh); + /* find the SDIO Host Controller state for this pdev and take it out from the list */ for (sdhc = sdhcinfo, prev = NULL; sdhc; sdhc = sdhc->next) { if (sdhc->dev == (void *)dev) { @@ -293,7 +294,6 @@ int bcmsdh_remove_bcmdhd(struct device *dev) return 0; } - /* release SDIO Host Controller info */ osh = sdhc->osh; MFREE(osh, sdhc, sizeof(bcmsdh_hc_t)); @@ -614,13 +614,6 @@ static irqreturn_t wlan_oob_irq(int irq, void *dev_id) return IRQ_HANDLED; } -void *bcmsdh_get_drvdata(void) -{ - if (!sdhcinfo) - return NULL; - return dev_get_drvdata(sdhcinfo->dev); -} - int bcmsdh_register_oob_intr(void * dhdp) { int error = 0; @@ -648,6 +641,13 @@ int bcmsdh_register_oob_intr(void * dhdp) return 0; } +void *bcmsdh_get_drvdata(void) +{ + if (!sdhcinfo) + return NULL; + return dev_get_drvdata(sdhcinfo->dev); +} + void bcmsdh_set_irq(int flag) { if (sdhcinfo->oob_irq_registered && sdhcinfo->oob_irq_enable_flag != flag) { @@ -674,6 +674,7 @@ void bcmsdh_unregister_oob_intr(void) } } #endif /* defined(OOB_INTR_ONLY) */ + /* Module parameters specific to each host-controller driver */ extern uint sd_msglevel; /* Debug message level */ @@ -697,6 +698,10 @@ module_param(sd_hiok, uint, 0); extern uint sd_f2_blocksize; module_param(sd_f2_blocksize, int, 0); +#ifdef BCMSDIOH_STD +extern int sd_uhsimode; +module_param(sd_uhsimode, int, 0); +#endif #ifdef BCMSDH_MODULE EXPORT_SYMBOL(bcmsdh_attach); diff --git a/drivers/net/wireless/bcmdhd/bcmsdh_sdmmc.c b/drivers/net/wireless/bcmdhd/bcmsdh_sdmmc.c index 49906acfb2fc..d890f2fa31e8 100644 --- a/drivers/net/wireless/bcmdhd/bcmsdh_sdmmc.c +++ b/drivers/net/wireless/bcmdhd/bcmsdh_sdmmc.c @@ -21,7 +21,7 @@ * software in any way with any other Broadcom software provided under a license * other than the GPL, without Broadcom's express prior written consent. * - * $Id: bcmsdh_sdmmc.c 282820 2011-09-09 15:40:35Z $ + * $Id: bcmsdh_sdmmc.c 301794 2011-12-08 20:41:35Z $ */ #include @@ -459,6 +459,7 @@ sdioh_iovar_op(sdioh_info_t *si, const char *name, bcopy(params, &int_val, sizeof(int_val)); bool_val = (int_val != 0) ? TRUE : FALSE; + BCM_REFERENCE(bool_val); actionid = set ? IOV_SVAL(vi->varid) : IOV_GVAL(vi->varid); switch (actionid) { @@ -1190,6 +1191,7 @@ static void IRQHandlerF2(struct sdio_func *func) sd = gInstance->sd; ASSERT(sd != NULL); + BCM_REFERENCE(sd); } #endif /* !defined(OOB_INTR_ONLY) */ diff --git a/drivers/net/wireless/bcmdhd/dhd.h b/drivers/net/wireless/bcmdhd/dhd.h index 50eb94d0c26b..cb27e291c0d7 100644 --- a/drivers/net/wireless/bcmdhd/dhd.h +++ b/drivers/net/wireless/bcmdhd/dhd.h @@ -24,7 +24,7 @@ * software in any way with any other Broadcom software provided under a license * other than the GPL, without Broadcom's express prior written consent. * - * $Id: dhd.h 301794 2011-12-08 20:41:35Z $ + * $Id: dhd.h 306879 2012-01-09 21:33:03Z $ */ /**************** @@ -420,6 +420,7 @@ extern int dhd_custom_get_mac_address(unsigned char *buf); extern void dhd_os_sdunlock_sndup_rxq(dhd_pub_t * pub); extern void dhd_os_sdlock_eventq(dhd_pub_t * pub); extern void dhd_os_sdunlock_eventq(dhd_pub_t * pub); +extern bool dhd_os_check_hang(dhd_pub_t *dhdp, int ifidx, int ret); #ifdef PNO_SUPPORT extern int dhd_pno_enable(dhd_pub_t *dhd, int pfn_enabled); @@ -434,8 +435,6 @@ extern int dhd_dev_pno_enable(struct net_device *dev, int pfn_enabled); extern int dhd_dev_get_pno_status(struct net_device *dev); #endif /* PNO_SUPPORT */ -extern bool dhd_check_ap_wfd_mode_set(dhd_pub_t *dhd); - #define DHD_UNICAST_FILTER_NUM 0 #define DHD_BROADCAST_FILTER_NUM 1 #define DHD_MULTICAST4_FILTER_NUM 2 @@ -444,7 +443,7 @@ extern int net_os_set_packet_filter(struct net_device *dev, int val); extern int net_os_rxfilter_add_remove(struct net_device *dev, int val, int num); extern int dhd_get_dtim_skip(dhd_pub_t *dhd); -extern bool dhd_os_check_hang(dhd_pub_t *dhdp, int ifidx, int ret); +extern bool dhd_check_ap_wfd_mode_set(dhd_pub_t *dhd); #ifdef DHD_DEBUG extern int write_to_file(dhd_pub_t *dhd, uint8 *buf, int size); @@ -467,7 +466,7 @@ extern int dhd_timeout_expired(dhd_timeout_t *tmo); extern int dhd_ifname2idx(struct dhd_info *dhd, char *name); extern int dhd_net2idx(struct dhd_info *dhd, struct net_device *net); -extern struct net_device * dhd_idx2net(struct dhd_pub *dhd_pub, int ifidx); +extern struct net_device * dhd_idx2net(void *pub, int ifidx); extern int wl_host_event(dhd_pub_t *dhd_pub, int *idx, void *pktdata, wl_event_msg_t *, void **data_ptr); extern void wl_event_to_host_order(wl_event_msg_t * evt); @@ -479,6 +478,7 @@ extern int dhd_wl_ioctl_cmd(dhd_pub_t *dhd_pub, int cmd, void *arg, int len, uin extern struct dhd_cmn *dhd_common_init(uint16 devid, osl_t *osh); extern void dhd_common_deinit(dhd_pub_t *dhd_pub, dhd_cmn_t *sa_cmn); +extern int dhd_do_driver_init(struct net_device *net); extern int dhd_add_if(struct dhd_info *dhd, int ifidx, void *handle, char *name, uint8 *mac_addr, uint32 flags, uint8 bssidx); extern void dhd_del_if(struct dhd_info *dhd, int ifidx); diff --git a/drivers/net/wireless/bcmdhd/dhd_cdc.c b/drivers/net/wireless/bcmdhd/dhd_cdc.c index 50e275a4ae23..d01853c71a2e 100644 --- a/drivers/net/wireless/bcmdhd/dhd_cdc.c +++ b/drivers/net/wireless/bcmdhd/dhd_cdc.c @@ -21,7 +21,7 @@ * software in any way with any other Broadcom software provided under a license * other than the GPL, without Broadcom's express prior written consent. * - * $Id: dhd_cdc.c 301794 2011-12-08 20:41:35Z $ + * $Id: dhd_cdc.c 303389 2011-12-16 09:30:48Z $ * * BDC is like CDC, except it includes a header for data packets to convey * packet priority over the bus, and flags (e.g. to indicate checksum status @@ -2515,9 +2515,10 @@ dhd_prot_init(dhd_pub_t *dhd) ret = dhd_wlfc_init(dhd); #endif -#if !defined(WL_CFG80211) +#if defined(WL_CFG80211) + if (dhd_download_fw_on_driverload) +#endif /* defined(WL_CFG80211) */ ret = dhd_preinit_ioctls(dhd); -#endif /* WL_CFG80211 */ /* Always assumes wl for now */ dhd->iswl = TRUE; diff --git a/drivers/net/wireless/bcmdhd/dhd_cfg80211.c b/drivers/net/wireless/bcmdhd/dhd_cfg80211.c new file mode 100644 index 000000000000..058749deba3d --- /dev/null +++ b/drivers/net/wireless/bcmdhd/dhd_cfg80211.c @@ -0,0 +1,862 @@ +/* + * Linux cfg80211 driver - Dongle Host Driver (DHD) related + * + * Copyright (C) 1999-2011, Broadcom Corporation + * + * Unless you and Broadcom execute a separate written software license + * agreement governing use of this software, this software is licensed to you + * under the terms of the GNU General Public License version 2 (the "GPL"), + * available at http://www.broadcom.com/licenses/GPLv2.php, with the + * following added to such license: + * + * As a special exception, the copyright holders of this software give you + * permission to link this software with independent modules, and to copy and + * distribute the resulting executable under terms of your choice, provided that + * you also meet, for each linked independent module, the terms and conditions of + * the license of that module. An independent module is a module which is not + * derived from this software. The special exception does not apply to any + * modifications of the software. + * + * Notwithstanding the above, under no circumstances may you combine this + * software in any way with any other Broadcom software provided under a license + * other than the GPL, without Broadcom's express prior written consent. + * + * $Id: wl_cfg80211.c,v 1.1.4.1.2.14 2011/02/09 01:40:07 Exp $ + */ + +#include + +#include +#include +#include +#include +extern struct wl_priv *wlcfg_drv_priv; +static int dhd_dongle_up = FALSE; + +static s32 wl_dongle_up(struct net_device *ndev, u32 up); +static s32 wl_dongle_power(struct net_device *ndev, u32 power_mode); +static s32 wl_dongle_glom(struct net_device *ndev, u32 glom, u32 dongle_align); +static s32 wl_dongle_roam(struct net_device *ndev, u32 roamvar, u32 bcn_timeout); +static s32 wl_dongle_scantime(struct net_device *ndev, s32 scan_assoc_time, s32 scan_unassoc_time); +static s32 wl_dongle_offload(struct net_device *ndev, s32 arpoe, s32 arp_ol); +static s32 wl_pattern_atoh(s8 *src, s8 *dst); +static s32 wl_dongle_filter(struct net_device *ndev, u32 filter_mode); + +/** + * Function implementations + */ + +s32 dhd_cfg80211_init(struct wl_priv *wl) +{ + dhd_dongle_up = FALSE; + return 0; +} + +s32 dhd_cfg80211_deinit(struct wl_priv *wl) +{ + dhd_dongle_up = FALSE; + return 0; +} + +s32 dhd_cfg80211_down(struct wl_priv *wl) +{ + dhd_dongle_up = FALSE; + return 0; +} + +static s32 wl_dongle_up(struct net_device *ndev, u32 up) +{ + s32 err = 0; + + err = wldev_ioctl(ndev, WLC_UP, &up, sizeof(up), true); + if (unlikely(err)) { + WL_ERR(("WLC_UP error (%d)\n", err)); + } + return err; +} + +static s32 wl_dongle_power(struct net_device *ndev, u32 power_mode) +{ + s32 err = 0; + + WL_TRACE(("In\n")); + err = wldev_ioctl(ndev, WLC_SET_PM, &power_mode, sizeof(power_mode), true); + if (unlikely(err)) { + WL_ERR(("WLC_SET_PM error (%d)\n", err)); + } + return err; +} + +static s32 +wl_dongle_glom(struct net_device *ndev, u32 glom, u32 dongle_align) +{ + s8 iovbuf[WL_EVENTING_MASK_LEN + 12]; + + s32 err = 0; + + /* Match Host and Dongle rx alignment */ + bcm_mkiovar("bus:txglomalign", (char *)&dongle_align, 4, iovbuf, + sizeof(iovbuf)); + err = wldev_ioctl(ndev, WLC_SET_VAR, iovbuf, sizeof(iovbuf), true); + if (unlikely(err)) { + WL_ERR(("txglomalign error (%d)\n", err)); + goto dongle_glom_out; + } + /* disable glom option per default */ + bcm_mkiovar("bus:txglom", (char *)&glom, 4, iovbuf, sizeof(iovbuf)); + err = wldev_ioctl(ndev, WLC_SET_VAR, iovbuf, sizeof(iovbuf), true); + if (unlikely(err)) { + WL_ERR(("txglom error (%d)\n", err)); + goto dongle_glom_out; + } +dongle_glom_out: + return err; +} + +static s32 +wl_dongle_roam(struct net_device *ndev, u32 roamvar, u32 bcn_timeout) +{ + s8 iovbuf[WL_EVENTING_MASK_LEN + 12]; + + s32 err = 0; + + /* Setup timeout if Beacons are lost and roam is off to report link down */ + if (roamvar) { + bcm_mkiovar("bcn_timeout", (char *)&bcn_timeout, 4, iovbuf, + sizeof(iovbuf)); + err = wldev_ioctl(ndev, WLC_SET_VAR, iovbuf, sizeof(iovbuf), true); + if (unlikely(err)) { + WL_ERR(("bcn_timeout error (%d)\n", err)); + goto dongle_rom_out; + } + } + /* Enable/Disable built-in roaming to allow supplicant to take care of roaming */ + bcm_mkiovar("roam_off", (char *)&roamvar, 4, iovbuf, sizeof(iovbuf)); + err = wldev_ioctl(ndev, WLC_SET_VAR, iovbuf, sizeof(iovbuf), true); + if (unlikely(err)) { + WL_ERR(("roam_off error (%d)\n", err)); + goto dongle_rom_out; + } +dongle_rom_out: + return err; +} + +static s32 +wl_dongle_scantime(struct net_device *ndev, s32 scan_assoc_time, + s32 scan_unassoc_time) +{ + s32 err = 0; + + err = wldev_ioctl(ndev, WLC_SET_SCAN_CHANNEL_TIME, &scan_assoc_time, + sizeof(scan_assoc_time), true); + if (err) { + if (err == -EOPNOTSUPP) { + WL_INFO(("Scan assoc time is not supported\n")); + } else { + WL_ERR(("Scan assoc time error (%d)\n", err)); + } + goto dongle_scantime_out; + } + err = wldev_ioctl(ndev, WLC_SET_SCAN_UNASSOC_TIME, &scan_unassoc_time, + sizeof(scan_unassoc_time), true); + if (err) { + if (err == -EOPNOTSUPP) { + WL_INFO(("Scan unassoc time is not supported\n")); + } else { + WL_ERR(("Scan unassoc time error (%d)\n", err)); + } + goto dongle_scantime_out; + } + +dongle_scantime_out: + return err; +} + +static s32 +wl_dongle_offload(struct net_device *ndev, s32 arpoe, s32 arp_ol) +{ + /* Room for "event_msgs" + '\0' + bitvec */ + s8 iovbuf[WL_EVENTING_MASK_LEN + 12]; + + s32 err = 0; + + /* Set ARP offload */ + bcm_mkiovar("arpoe", (char *)&arpoe, 4, iovbuf, sizeof(iovbuf)); + err = wldev_ioctl(ndev, WLC_SET_VAR, iovbuf, sizeof(iovbuf), true); + if (err) { + if (err == -EOPNOTSUPP) + WL_INFO(("arpoe is not supported\n")); + else + WL_ERR(("arpoe error (%d)\n", err)); + + goto dongle_offload_out; + } + bcm_mkiovar("arp_ol", (char *)&arp_ol, 4, iovbuf, sizeof(iovbuf)); + err = wldev_ioctl(ndev, WLC_SET_VAR, iovbuf, sizeof(iovbuf), true); + if (err) { + if (err == -EOPNOTSUPP) + WL_INFO(("arp_ol is not supported\n")); + else + WL_ERR(("arp_ol error (%d)\n", err)); + + goto dongle_offload_out; + } + +dongle_offload_out: + return err; +} + +static s32 wl_pattern_atoh(s8 *src, s8 *dst) +{ + int i; + if (strncmp(src, "0x", 2) != 0 && strncmp(src, "0X", 2) != 0) { + WL_ERR(("Mask invalid format. Needs to start with 0x\n")); + return -1; + } + src = src + 2; /* Skip past 0x */ + if (strlen(src) % 2 != 0) { + WL_ERR(("Mask invalid format. Needs to be of even length\n")); + return -1; + } + for (i = 0; *src != '\0'; i++) { + char num[3]; + strncpy(num, src, 2); + num[2] = '\0'; + dst[i] = (u8) simple_strtoul(num, NULL, 16); + src += 2; + } + return i; +} + +static s32 wl_dongle_filter(struct net_device *ndev, u32 filter_mode) +{ + /* Room for "event_msgs" + '\0' + bitvec */ + s8 iovbuf[WL_EVENTING_MASK_LEN + 12]; + + const s8 *str; + struct wl_pkt_filter pkt_filter; + struct wl_pkt_filter *pkt_filterp; + s32 buf_len; + s32 str_len; + u32 mask_size; + u32 pattern_size; + s8 buf[256]; + s32 err = 0; + + /* add a default packet filter pattern */ + str = "pkt_filter_add"; + str_len = strlen(str); + strncpy(buf, str, str_len); + buf[str_len] = '\0'; + buf_len = str_len + 1; + + pkt_filterp = (struct wl_pkt_filter *)(buf + str_len + 1); + + /* Parse packet filter id. */ + pkt_filter.id = htod32(100); + + /* Parse filter polarity. */ + pkt_filter.negate_match = htod32(0); + + /* Parse filter type. */ + pkt_filter.type = htod32(0); + + /* Parse pattern filter offset. */ + pkt_filter.u.pattern.offset = htod32(0); + + /* Parse pattern filter mask. */ + mask_size = htod32(wl_pattern_atoh("0xff", + (char *)pkt_filterp->u.pattern. + mask_and_pattern)); + + /* Parse pattern filter pattern. */ + pattern_size = htod32(wl_pattern_atoh("0x00", + (char *)&pkt_filterp->u.pattern.mask_and_pattern[mask_size])); + + if (mask_size != pattern_size) { + WL_ERR(("Mask and pattern not the same size\n")); + err = -EINVAL; + goto dongle_filter_out; + } + + pkt_filter.u.pattern.size_bytes = mask_size; + buf_len += WL_PKT_FILTER_FIXED_LEN; + buf_len += (WL_PKT_FILTER_PATTERN_FIXED_LEN + 2 * mask_size); + + /* Keep-alive attributes are set in local + * variable (keep_alive_pkt), and + * then memcpy'ed into buffer (keep_alive_pktp) since there is no + * guarantee that the buffer is properly aligned. + */ + memcpy((char *)pkt_filterp, &pkt_filter, + WL_PKT_FILTER_FIXED_LEN + WL_PKT_FILTER_PATTERN_FIXED_LEN); + + err = wldev_ioctl(ndev, WLC_SET_VAR, buf, buf_len, true); + if (err) { + if (err == -EOPNOTSUPP) { + WL_INFO(("filter not supported\n")); + } else { + WL_ERR(("filter (%d)\n", err)); + } + goto dongle_filter_out; + } + + /* set mode to allow pattern */ + bcm_mkiovar("pkt_filter_mode", (char *)&filter_mode, 4, iovbuf, + sizeof(iovbuf)); + err = wldev_ioctl(ndev, WLC_SET_VAR, iovbuf, sizeof(iovbuf), true); + if (err) { + if (err == -EOPNOTSUPP) { + WL_INFO(("filter_mode not supported\n")); + } else { + WL_ERR(("filter_mode (%d)\n", err)); + } + goto dongle_filter_out; + } + +dongle_filter_out: + return err; +} + +s32 dhd_config_dongle(struct wl_priv *wl, bool need_lock) +{ +#ifndef DHD_SDALIGN +#define DHD_SDALIGN 32 +#endif + struct net_device *ndev; + s32 err = 0; + + WL_TRACE(("In\n")); + if (dhd_dongle_up) { + WL_ERR(("Dongle is already up\n")); + return err; + } + + ndev = wl_to_prmry_ndev(wl); + + if (need_lock) + rtnl_lock(); + + err = wl_dongle_up(ndev, 0); + if (unlikely(err)) { + WL_ERR(("wl_dongle_up failed\n")); + goto default_conf_out; + } + err = wl_dongle_power(ndev, PM_FAST); + if (unlikely(err)) { + WL_ERR(("wl_dongle_power failed\n")); + goto default_conf_out; + } + err = wl_dongle_glom(ndev, 0, DHD_SDALIGN); + if (unlikely(err)) { + WL_ERR(("wl_dongle_glom failed\n")); + goto default_conf_out; + } + err = wl_dongle_roam(ndev, (wl->roam_on ? 0 : 1), 3); + if (unlikely(err)) { + WL_ERR(("wl_dongle_roam failed\n")); + goto default_conf_out; + } + wl_dongle_scantime(ndev, 40, 80); + wl_dongle_offload(ndev, 1, 0xf); + wl_dongle_filter(ndev, 1); + dhd_dongle_up = true; + +default_conf_out: + if (need_lock) + rtnl_unlock(); + return err; + +} + + +/* TODO: clean up the BT-Coex code, it still have some legacy ioctl/iovar functions */ +#define COEX_DHCP + +#if defined(COEX_DHCP) + +/* use New SCO/eSCO smart YG suppression */ +#define BT_DHCP_eSCO_FIX +/* this flag boost wifi pkt priority to max, caution: -not fair to sco */ +#define BT_DHCP_USE_FLAGS +/* T1 start SCO/ESCo priority suppression */ +#define BT_DHCP_OPPR_WIN_TIME 2500 +/* T2 turn off SCO/SCO supperesion is (timeout) */ +#define BT_DHCP_FLAG_FORCE_TIME 5500 + +enum wl_cfg80211_btcoex_status { + BT_DHCP_IDLE, + BT_DHCP_START, + BT_DHCP_OPPR_WIN, + BT_DHCP_FLAG_FORCE_TIMEOUT +}; + +/* + * get named driver variable to uint register value and return error indication + * calling example: dev_wlc_intvar_get_reg(dev, "btc_params",66, ®_value) + */ +static int +dev_wlc_intvar_get_reg(struct net_device *dev, char *name, + uint reg, int *retval) +{ + union { + char buf[WLC_IOCTL_SMLEN]; + int val; + } var; + int error; + + bcm_mkiovar(name, (char *)(®), sizeof(reg), + (char *)(&var), sizeof(var.buf)); + error = wldev_ioctl(dev, WLC_GET_VAR, (char *)(&var), sizeof(var.buf), false); + + *retval = dtoh32(var.val); + return (error); +} + +static int +dev_wlc_bufvar_set(struct net_device *dev, char *name, char *buf, int len) +{ +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 31) + char ioctlbuf_local[1024]; +#else + static char ioctlbuf_local[1024]; +#endif /* LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 31) */ + + bcm_mkiovar(name, buf, len, ioctlbuf_local, sizeof(ioctlbuf_local)); + + return (wldev_ioctl(dev, WLC_SET_VAR, ioctlbuf_local, sizeof(ioctlbuf_local), true)); +} +/* +get named driver variable to uint register value and return error indication +calling example: dev_wlc_intvar_set_reg(dev, "btc_params",66, value) +*/ +static int +dev_wlc_intvar_set_reg(struct net_device *dev, char *name, char *addr, char * val) +{ + char reg_addr[8]; + + memset(reg_addr, 0, sizeof(reg_addr)); + memcpy((char *)®_addr[0], (char *)addr, 4); + memcpy((char *)®_addr[4], (char *)val, 4); + + return (dev_wlc_bufvar_set(dev, name, (char *)®_addr[0], sizeof(reg_addr))); +} + +static bool btcoex_is_sco_active(struct net_device *dev) +{ + int ioc_res = 0; + bool res = FALSE; + int sco_id_cnt = 0; + int param27; + int i; + + for (i = 0; i < 12; i++) { + + ioc_res = dev_wlc_intvar_get_reg(dev, "btc_params", 27, ¶m27); + + WL_TRACE(("%s, sample[%d], btc params: 27:%x\n", + __FUNCTION__, i, param27)); + + if (ioc_res < 0) { + WL_ERR(("%s ioc read btc params error\n", __FUNCTION__)); + break; + } + + if ((param27 & 0x6) == 2) { /* count both sco & esco */ + sco_id_cnt++; + } + + if (sco_id_cnt > 2) { + WL_TRACE(("%s, sco/esco detected, pkt id_cnt:%d samples:%d\n", + __FUNCTION__, sco_id_cnt, i)); + res = TRUE; + break; + } + + msleep(5); + } + + return res; +} + +#if defined(BT_DHCP_eSCO_FIX) +/* Enhanced BT COEX settings for eSCO compatibility during DHCP window */ +static int set_btc_esco_params(struct net_device *dev, bool trump_sco) +{ + static bool saved_status = FALSE; + + char buf_reg50va_dhcp_on[8] = + { 50, 00, 00, 00, 0x22, 0x80, 0x00, 0x00 }; + char buf_reg51va_dhcp_on[8] = + { 51, 00, 00, 00, 0x00, 0x00, 0x00, 0x00 }; + char buf_reg64va_dhcp_on[8] = + { 64, 00, 00, 00, 0x00, 0x00, 0x00, 0x00 }; + char buf_reg65va_dhcp_on[8] = + { 65, 00, 00, 00, 0x00, 0x00, 0x00, 0x00 }; + char buf_reg71va_dhcp_on[8] = + { 71, 00, 00, 00, 0x00, 0x00, 0x00, 0x00 }; + uint32 regaddr; + static uint32 saved_reg50; + static uint32 saved_reg51; + static uint32 saved_reg64; + static uint32 saved_reg65; + static uint32 saved_reg71; + + if (trump_sco) { + /* this should reduce eSCO agressive retransmit + * w/o breaking it + */ + + /* 1st save current */ + WL_TRACE(("Do new SCO/eSCO coex algo {save &" + "override}\n")); + if ((!dev_wlc_intvar_get_reg(dev, "btc_params", 50, &saved_reg50)) && + (!dev_wlc_intvar_get_reg(dev, "btc_params", 51, &saved_reg51)) && + (!dev_wlc_intvar_get_reg(dev, "btc_params", 64, &saved_reg64)) && + (!dev_wlc_intvar_get_reg(dev, "btc_params", 65, &saved_reg65)) && + (!dev_wlc_intvar_get_reg(dev, "btc_params", 71, &saved_reg71))) { + saved_status = TRUE; + WL_TRACE(("%s saved bt_params[50,51,64,65,71]:" + "0x%x 0x%x 0x%x 0x%x 0x%x\n", + __FUNCTION__, saved_reg50, saved_reg51, + saved_reg64, saved_reg65, saved_reg71)); + } else { + WL_ERR((":%s: save btc_params failed\n", + __FUNCTION__)); + saved_status = FALSE; + return -1; + } + + WL_TRACE(("override with [50,51,64,65,71]:" + "0x%x 0x%x 0x%x 0x%x 0x%x\n", + *(u32 *)(buf_reg50va_dhcp_on+4), + *(u32 *)(buf_reg51va_dhcp_on+4), + *(u32 *)(buf_reg64va_dhcp_on+4), + *(u32 *)(buf_reg65va_dhcp_on+4), + *(u32 *)(buf_reg71va_dhcp_on+4))); + + dev_wlc_bufvar_set(dev, "btc_params", + (char *)&buf_reg50va_dhcp_on[0], 8); + dev_wlc_bufvar_set(dev, "btc_params", + (char *)&buf_reg51va_dhcp_on[0], 8); + dev_wlc_bufvar_set(dev, "btc_params", + (char *)&buf_reg64va_dhcp_on[0], 8); + dev_wlc_bufvar_set(dev, "btc_params", + (char *)&buf_reg65va_dhcp_on[0], 8); + dev_wlc_bufvar_set(dev, "btc_params", + (char *)&buf_reg71va_dhcp_on[0], 8); + + saved_status = TRUE; + } else if (saved_status) { + /* restore previously saved bt params */ + WL_TRACE(("Do new SCO/eSCO coex algo {save &" + "override}\n")); + + regaddr = 50; + dev_wlc_intvar_set_reg(dev, "btc_params", + (char *)®addr, (char *)&saved_reg50); + regaddr = 51; + dev_wlc_intvar_set_reg(dev, "btc_params", + (char *)®addr, (char *)&saved_reg51); + regaddr = 64; + dev_wlc_intvar_set_reg(dev, "btc_params", + (char *)®addr, (char *)&saved_reg64); + regaddr = 65; + dev_wlc_intvar_set_reg(dev, "btc_params", + (char *)®addr, (char *)&saved_reg65); + regaddr = 71; + dev_wlc_intvar_set_reg(dev, "btc_params", + (char *)®addr, (char *)&saved_reg71); + + WL_TRACE(("restore bt_params[50,51,64,65,71]:" + "0x%x 0x%x 0x%x 0x%x 0x%x\n", + saved_reg50, saved_reg51, saved_reg64, + saved_reg65, saved_reg71)); + + saved_status = FALSE; + } else { + WL_ERR((":%s att to restore not saved BTCOEX params\n", + __FUNCTION__)); + return -1; + } + return 0; +} +#endif /* BT_DHCP_eSCO_FIX */ + +static void +wl_cfg80211_bt_setflag(struct net_device *dev, bool set) +{ +#if defined(BT_DHCP_USE_FLAGS) + char buf_flag7_dhcp_on[8] = { 7, 00, 00, 00, 0x1, 0x0, 0x00, 0x00 }; + char buf_flag7_default[8] = { 7, 00, 00, 00, 0x0, 0x00, 0x00, 0x00}; +#endif + + +#if defined(BT_DHCP_eSCO_FIX) + /* set = 1, save & turn on 0 - off & restore prev settings */ + set_btc_esco_params(dev, set); +#endif + +#if defined(BT_DHCP_USE_FLAGS) + WL_TRACE(("WI-FI priority boost via bt flags, set:%d\n", set)); + if (set == TRUE) + /* Forcing bt_flag7 */ + dev_wlc_bufvar_set(dev, "btc_flags", + (char *)&buf_flag7_dhcp_on[0], + sizeof(buf_flag7_dhcp_on)); + else + /* Restoring default bt flag7 */ + dev_wlc_bufvar_set(dev, "btc_flags", + (char *)&buf_flag7_default[0], + sizeof(buf_flag7_default)); +#endif +} + +static void wl_cfg80211_bt_timerfunc(ulong data) +{ + struct btcoex_info *bt_local = (struct btcoex_info *)data; + WL_TRACE(("%s\n", __FUNCTION__)); + bt_local->timer_on = 0; + schedule_work(&bt_local->work); +} + +static void wl_cfg80211_bt_handler(struct work_struct *work) +{ + struct btcoex_info *btcx_inf; + + btcx_inf = container_of(work, struct btcoex_info, work); + + if (btcx_inf->timer_on) { + btcx_inf->timer_on = 0; + del_timer_sync(&btcx_inf->timer); + } + + switch (btcx_inf->bt_state) { + case BT_DHCP_START: + /* DHCP started + * provide OPPORTUNITY window to get DHCP address + */ + WL_TRACE(("%s bt_dhcp stm: started \n", + __FUNCTION__)); + btcx_inf->bt_state = BT_DHCP_OPPR_WIN; + mod_timer(&btcx_inf->timer, + jiffies + BT_DHCP_OPPR_WIN_TIME*HZ/1000); + btcx_inf->timer_on = 1; + break; + + case BT_DHCP_OPPR_WIN: + if (btcx_inf->dhcp_done) { + WL_TRACE(("%s DHCP Done before T1 expiration\n", + __FUNCTION__)); + goto btc_coex_idle; + } + + /* DHCP is not over yet, start lowering BT priority + * enforce btc_params + flags if necessary + */ + WL_TRACE(("%s DHCP T1:%d expired\n", __FUNCTION__, + BT_DHCP_OPPR_WIN_TIME)); + if (btcx_inf->dev) + wl_cfg80211_bt_setflag(btcx_inf->dev, TRUE); + btcx_inf->bt_state = BT_DHCP_FLAG_FORCE_TIMEOUT; + mod_timer(&btcx_inf->timer, + jiffies + BT_DHCP_FLAG_FORCE_TIME*HZ/1000); + btcx_inf->timer_on = 1; + break; + + case BT_DHCP_FLAG_FORCE_TIMEOUT: + if (btcx_inf->dhcp_done) { + WL_TRACE(("%s DHCP Done before T2 expiration\n", + __FUNCTION__)); + } else { + /* Noo dhcp during T1+T2, restore BT priority */ + WL_TRACE(("%s DHCP wait interval T2:%d" + "msec expired\n", __FUNCTION__, + BT_DHCP_FLAG_FORCE_TIME)); + } + + /* Restoring default bt priority */ + if (btcx_inf->dev) + wl_cfg80211_bt_setflag(btcx_inf->dev, FALSE); +btc_coex_idle: + btcx_inf->bt_state = BT_DHCP_IDLE; + btcx_inf->timer_on = 0; + break; + + default: + WL_ERR(("%s error g_status=%d !!!\n", __FUNCTION__, + btcx_inf->bt_state)); + if (btcx_inf->dev) + wl_cfg80211_bt_setflag(btcx_inf->dev, FALSE); + btcx_inf->bt_state = BT_DHCP_IDLE; + btcx_inf->timer_on = 0; + break; + } + + net_os_wake_unlock(btcx_inf->dev); +} + +int wl_cfg80211_btcoex_init(struct wl_priv *wl) +{ + struct btcoex_info *btco_inf = NULL; + + btco_inf = kmalloc(sizeof(struct btcoex_info), GFP_KERNEL); + if (!btco_inf) + return -ENOMEM; + + btco_inf->bt_state = BT_DHCP_IDLE; + btco_inf->ts_dhcp_start = 0; + btco_inf->ts_dhcp_ok = 0; + /* Set up timer for BT */ + btco_inf->timer_ms = 10; + init_timer(&btco_inf->timer); + btco_inf->timer.data = (ulong)btco_inf; + btco_inf->timer.function = wl_cfg80211_bt_timerfunc; + + btco_inf->dev = wl->wdev->netdev; + + INIT_WORK(&btco_inf->work, wl_cfg80211_bt_handler); + + wl->btcoex_info = btco_inf; + return 0; +} + +void wl_cfg80211_btcoex_deinit(struct wl_priv *wl) +{ + if (!wl->btcoex_info) + return; + + if (!wl->btcoex_info->timer_on) { + wl->btcoex_info->timer_on = 0; + del_timer_sync(&wl->btcoex_info->timer); + } + + cancel_work_sync(&wl->btcoex_info->work); + + kfree(wl->btcoex_info); + wl->btcoex_info = NULL; +} +#endif + +int wl_cfg80211_set_btcoex_dhcp(struct net_device *dev, char *command) +{ + + struct wl_priv *wl = wlcfg_drv_priv; + char powermode_val = 0; + char buf_reg66va_dhcp_on[8] = { 66, 00, 00, 00, 0x10, 0x27, 0x00, 0x00 }; + char buf_reg41va_dhcp_on[8] = { 41, 00, 00, 00, 0x33, 0x00, 0x00, 0x00 }; + char buf_reg68va_dhcp_on[8] = { 68, 00, 00, 00, 0x90, 0x01, 0x00, 0x00 }; + + uint32 regaddr; + static uint32 saved_reg66; + static uint32 saved_reg41; + static uint32 saved_reg68; + static bool saved_status = FALSE; + +#ifdef COEX_DHCP + char buf_flag7_default[8] = { 7, 00, 00, 00, 0x0, 0x00, 0x00, 0x00}; + struct btcoex_info *btco_inf = wl->btcoex_info; +#endif /* COEX_DHCP */ + + /* Figure out powermode 1 or o command */ + strncpy((char *)&powermode_val, command + strlen("BTCOEXMODE") +1, 1); + + if (strnicmp((char *)&powermode_val, "1", strlen("1")) == 0) { + + WL_TRACE(("%s: DHCP session starts\n", __FUNCTION__)); + + /* Retrieve and saved orig regs value */ + if ((saved_status == FALSE) && + (!dev_wlc_intvar_get_reg(dev, "btc_params", 66, &saved_reg66)) && + (!dev_wlc_intvar_get_reg(dev, "btc_params", 41, &saved_reg41)) && + (!dev_wlc_intvar_get_reg(dev, "btc_params", 68, &saved_reg68))) { + saved_status = TRUE; + WL_TRACE(("Saved 0x%x 0x%x 0x%x\n", + saved_reg66, saved_reg41, saved_reg68)); + + /* Disable PM mode during dhpc session */ + + /* Disable PM mode during dhpc session */ +#ifdef COEX_DHCP + /* Start BT timer only for SCO connection */ + if (btcoex_is_sco_active(dev)) { + /* btc_params 66 */ + dev_wlc_bufvar_set(dev, "btc_params", + (char *)&buf_reg66va_dhcp_on[0], + sizeof(buf_reg66va_dhcp_on)); + /* btc_params 41 0x33 */ + dev_wlc_bufvar_set(dev, "btc_params", + (char *)&buf_reg41va_dhcp_on[0], + sizeof(buf_reg41va_dhcp_on)); + /* btc_params 68 0x190 */ + dev_wlc_bufvar_set(dev, "btc_params", + (char *)&buf_reg68va_dhcp_on[0], + sizeof(buf_reg68va_dhcp_on)); + saved_status = TRUE; + + btco_inf->bt_state = BT_DHCP_START; + btco_inf->timer_on = 1; + mod_timer(&btco_inf->timer, btco_inf->timer.expires); + WL_TRACE(("%s enable BT DHCP Timer\n", + __FUNCTION__)); + } +#endif /* COEX_DHCP */ + } + else if (saved_status == TRUE) { + WL_ERR(("%s was called w/o DHCP OFF. Continue\n", __FUNCTION__)); + } + } + else if (strnicmp((char *)&powermode_val, "2", strlen("2")) == 0) { + + + /* Restoring PM mode */ + +#ifdef COEX_DHCP + /* Stop any bt timer because DHCP session is done */ + WL_TRACE(("%s disable BT DHCP Timer\n", __FUNCTION__)); + if (btco_inf->timer_on) { + btco_inf->timer_on = 0; + del_timer_sync(&btco_inf->timer); + + if (btco_inf->bt_state != BT_DHCP_IDLE) { + /* need to restore original btc flags & extra btc params */ + WL_TRACE(("%s bt->bt_state:%d\n", + __FUNCTION__, btco_inf->bt_state)); + /* wake up btcoex thread to restore btlags+params */ + schedule_work(&btco_inf->work); + } + } + + /* Restoring btc_flag paramter anyway */ + if (saved_status == TRUE) + dev_wlc_bufvar_set(dev, "btc_flags", + (char *)&buf_flag7_default[0], sizeof(buf_flag7_default)); +#endif /* COEX_DHCP */ + + /* Restore original values */ + if (saved_status == TRUE) { + regaddr = 66; + dev_wlc_intvar_set_reg(dev, "btc_params", + (char *)®addr, (char *)&saved_reg66); + regaddr = 41; + dev_wlc_intvar_set_reg(dev, "btc_params", + (char *)®addr, (char *)&saved_reg41); + regaddr = 68; + dev_wlc_intvar_set_reg(dev, "btc_params", + (char *)®addr, (char *)&saved_reg68); + + WL_TRACE(("restore regs {66,41,68} <- 0x%x 0x%x 0x%x\n", + saved_reg66, saved_reg41, saved_reg68)); + } + saved_status = FALSE; + + } + else { + WL_ERR(("%s Unkwown yet power setting, ignored\n", + __FUNCTION__)); + } + + snprintf(command, 3, "OK"); + + return (strlen("OK")); +} diff --git a/drivers/net/wireless/bcmdhd/dhd_cfg80211.h b/drivers/net/wireless/bcmdhd/dhd_cfg80211.h new file mode 100644 index 000000000000..8dab652c1a2c --- /dev/null +++ b/drivers/net/wireless/bcmdhd/dhd_cfg80211.h @@ -0,0 +1,42 @@ +/* + * Linux cfg80211 driver - Dongle Host Driver (DHD) related + * + * Copyright (C) 1999-2011, Broadcom Corporation + * + * Unless you and Broadcom execute a separate written software license + * agreement governing use of this software, this software is licensed to you + * under the terms of the GNU General Public License version 2 (the "GPL"), + * available at http://www.broadcom.com/licenses/GPLv2.php, with the + * following added to such license: + * + * As a special exception, the copyright holders of this software give you + * permission to link this software with independent modules, and to copy and + * distribute the resulting executable under terms of your choice, provided that + * you also meet, for each linked independent module, the terms and conditions of + * the license of that module. An independent module is a module which is not + * derived from this software. The special exception does not apply to any + * modifications of the software. + * + * Notwithstanding the above, under no circumstances may you combine this + * software in any way with any other Broadcom software provided under a license + * other than the GPL, without Broadcom's express prior written consent. + * + * $Id: wl_cfg80211.c,v 1.1.4.1.2.14 2011/02/09 01:40:07 Exp $ + */ + + +#ifndef __DHD_CFG80211__ +#define __DHD_CFG80211__ + +#include +#include + +s32 dhd_cfg80211_init(struct wl_priv *wl); +s32 dhd_cfg80211_deinit(struct wl_priv *wl); +s32 dhd_cfg80211_down(struct wl_priv *wl); +s32 dhd_config_dongle(struct wl_priv *wl, bool need_lock); + +int wl_cfg80211_btcoex_init(struct wl_priv *wl); +void wl_cfg80211_btcoex_deinit(struct wl_priv *wl); + +#endif /* __DHD_CFG80211__ */ diff --git a/drivers/net/wireless/bcmdhd/dhd_common.c b/drivers/net/wireless/bcmdhd/dhd_common.c index c77242639044..1a8d3e08cf5e 100644 --- a/drivers/net/wireless/bcmdhd/dhd_common.c +++ b/drivers/net/wireless/bcmdhd/dhd_common.c @@ -21,7 +21,7 @@ * software in any way with any other Broadcom software provided under a license * other than the GPL, without Broadcom's express prior written consent. * - * $Id: dhd_common.c 297563 2011-11-20 15:38:29Z $ + * $Id: dhd_common.c 307573 2012-01-12 00:04:39Z $ */ #include #include @@ -341,6 +341,11 @@ dhd_doiovar(dhd_pub_t *dhd_pub, const bcm_iovar_t *vi, uint32 actionid, const ch case IOV_SVAL(IOV_MSGLEVEL): dhd_msg_level = int_val; +#ifdef WL_CFG80211 + /* Enable DHD and WL logs in oneshot */ + if (dhd_msg_level & DHD_WL_VAL) + wl_cfg80211_enable_trace(dhd_msg_level); +#endif break; case IOV_GVAL(IOV_BCMERRORSTR): bcm_strncpy_s((char *)arg, len, bcmerrorstr(dhd_pub->bcmerror), BCME_STRLEN); diff --git a/drivers/net/wireless/bcmdhd/dhd_linux.c b/drivers/net/wireless/bcmdhd/dhd_linux.c index 7018e7ac5e91..0ebd4c2af705 100644 --- a/drivers/net/wireless/bcmdhd/dhd_linux.c +++ b/drivers/net/wireless/bcmdhd/dhd_linux.c @@ -22,7 +22,7 @@ * software in any way with any other Broadcom software provided under a license * other than the GPL, without Broadcom's express prior written consent. * - * $Id: dhd_linux.c 301794 2011-12-08 20:41:35Z $ + * $Id: dhd_linux.c 307603 2012-01-12 01:32:01Z $ */ #include @@ -287,6 +287,8 @@ typedef struct dhd_info { char firmware_path[MOD_PARAM_PATHLEN]; char nvram_path[MOD_PARAM_PATHLEN]; +int op_mode = 0; +module_param(op_mode, int, 0644); extern int wl_control_wl_start(struct net_device *dev); extern int net_os_send_hang_message(struct net_device *dev); #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) @@ -442,6 +444,9 @@ static char dhd_version[] = "Dongle Host Driver, version " EPI_VERSION_STR ; static void dhd_net_if_lock_local(dhd_info_t *dhd); static void dhd_net_if_unlock_local(dhd_info_t *dhd); +#if !defined(AP) && defined(WLP2P) +static u32 dhd_concurrent_fw(dhd_pub_t *dhd); +#endif #ifdef WLMEDIA_HTSF void htsf_update(dhd_info_t *dhd, void *data); @@ -699,8 +704,9 @@ dhd_net2idx(dhd_info_t *dhd, struct net_device *net) return DHD_BAD_IF; } -struct net_device * dhd_idx2net(struct dhd_pub *dhd_pub, int ifidx) +struct net_device * dhd_idx2net(void *pub, int ifidx) { + struct dhd_pub *dhd_pub = (struct dhd_pub *)pub; struct dhd_info *dhd_info; if (!dhd_pub || ifidx < 0 || ifidx >= DHD_MAX_IFS) @@ -928,6 +934,7 @@ _dhd_set_mac_address(dhd_info_t *dhd, int ifidx, struct ether_addr *addr) DHD_ERROR(("%s: set cur_etheraddr failed\n", dhd_ifname(&dhd->pub, ifidx))); } else { memcpy(dhd->iflist[ifidx]->net->dev_addr, addr, ETHER_ADDR_LEN); + memcpy(dhd->pub.mac.octet, addr, ETHER_ADDR_LEN); } return ret; @@ -984,7 +991,7 @@ dhd_op_if(dhd_if_t *ifp) #ifdef WL_CFG80211 if (dhd->dhd_state & DHD_ATTACH_STATE_CFG80211) if (!wl_cfg80211_notify_ifadd(ifp->net, ifp->idx, ifp->bssidx, - dhd_net_attach)) { + (void*)dhd_net_attach)) { ifp->state = DHD_IF_NONE; return; } @@ -1426,7 +1433,7 @@ dhd_rx_frame(dhd_pub_t *dhdp, int ifidx, void *pktbuf, int numpkt, uint8 chan) PKTFREE(dhdp->osh, pktbuf, TRUE); continue; } - +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0) /* Dropping packets before registering net device to avoid kernel panic */ if (!ifp->net || ifp->net->reg_state != NETREG_REGISTERED || !dhd->pub.up) { @@ -1435,6 +1442,7 @@ dhd_rx_frame(dhd_pub_t *dhdp, int ifidx, void *pktbuf, int numpkt, uint8 chan) PKTFREE(dhdp->osh, pktbuf, TRUE); continue; } +#endif pnext = PKTNEXT(dhdp->osh, pktbuf); PKTSETNEXT(wl->sh.osh, pktbuf, NULL); @@ -2280,7 +2288,7 @@ dhd_stop(struct net_device *net) int ifidx; dhd_info_t *dhd = *(dhd_info_t **)netdev_priv(net); DHD_OS_WAKE_LOCK(&dhd->pub); - DHD_TRACE(("%s: Enter\n", __FUNCTION__)); + DHD_TRACE(("%s: Enter %p\n", __FUNCTION__, net)); if (dhd->pub.up == 0) { goto exit; } @@ -2288,7 +2296,7 @@ dhd_stop(struct net_device *net) #ifdef WL_CFG80211 if (ifidx == 0) { - wl_cfg80211_down(); + wl_cfg80211_down(NULL); /* * For CFG80211: Clean up all the left over virtual interfaces @@ -2400,7 +2408,7 @@ dhd_open(struct net_device *net) #endif /* TOE */ #if defined(WL_CFG80211) - if (unlikely(wl_cfg80211_up())) { + if (unlikely(wl_cfg80211_up(NULL))) { DHD_ERROR(("%s: failed to bring up cfg80211\n", __FUNCTION__)); ret = -1; goto exit; @@ -2422,6 +2430,32 @@ exit: return ret; } +int dhd_do_driver_init(struct net_device *net) +{ + dhd_info_t *dhd = NULL; + + if (!net) { + DHD_ERROR(("Primary Interface not initialized \n")); + return -EINVAL; + } + + dhd = *(dhd_info_t **)netdev_priv(net); + + /* If driver is already initialized, do nothing + */ + if (dhd->pub.busstate == DHD_BUS_DATA) { + DHD_TRACE(("Driver already Inititalized. Nothing to do")); + return 0; + } + + if (dhd_open(net) < 0) { + DHD_ERROR(("Driver Init Failed \n")); + return -1; + } + + return 0; +} + osl_t * dhd_osl_attach(void *pdev, uint bustype) { @@ -2857,6 +2891,37 @@ dhd_bus_start(dhd_pub_t *dhdp) return 0; } +#if !defined(AP) && defined(WLP2P) +/* For Android ICS MR2 release, the concurrent mode is enabled by default and the firmware + * name would be fw_bcmdhd.bin. So we need to determine whether P2P is enabled in the STA + * firmware and accordingly enable concurrent mode (Apply P2P settings). SoftAP firmware + * would still be named as fw_bcmdhd_apsta. + */ +static u32 +dhd_concurrent_fw(dhd_pub_t *dhd) +{ + int ret = 0; + char buf[WLC_IOCTL_SMLEN]; + + if ((!op_mode) && (strstr(fw_path, "_p2p") == NULL) && + (strstr(fw_path, "_apsta") == NULL)) { + /* Given path is for the STA firmware. Check whether P2P support is present in + * the firmware. If so, set mode as P2P (concurrent support). + */ + memset(buf, 0, sizeof(buf)); + bcm_mkiovar("p2p", 0, 0, buf, sizeof(buf)); + if ((ret = dhd_wl_ioctl_cmd(dhd, WLC_GET_VAR, buf, sizeof(buf), + FALSE, 0)) < 0) { + DHD_TRACE(("%s: Get P2P failed (error=%d)\n", __FUNCTION__, ret)); + } else if (buf[0] == 1) { + DHD_TRACE(("%s: P2P is supported\n", __FUNCTION__)); + return 1; + } + } + return 0; +} +#endif + int dhd_preinit_ioctls(dhd_pub_t *dhd) { @@ -2922,7 +2987,7 @@ dhd_preinit_ioctls(dhd_pub_t *dhd) #endif /* GET_CUSTOM_MAC_ENABLE */ #ifdef SET_RANDOM_MAC_SOFTAP - if (strstr(fw_path, "_apsta") != NULL) { + if ((!op_mode && strstr(fw_path, "_apsta") != NULL) || (op_mode == 0x02)) { uint rand_mac; srandom32((uint)jiffies); @@ -2946,7 +3011,8 @@ dhd_preinit_ioctls(dhd_pub_t *dhd) DHD_TRACE(("Firmware = %s\n", fw_path)); #if !defined(AP) && defined(WLP2P) /* Check if firmware with WFD support used */ - if (strstr(fw_path, "_p2p") != NULL) { + if ((!op_mode && strstr(fw_path, "_p2p") != NULL) || (op_mode == 0x04) || + (dhd_concurrent_fw(dhd))) { bcm_mkiovar("apsta", (char *)&apsta, 4, iovbuf, sizeof(iovbuf)); if ((ret = dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, sizeof(iovbuf), TRUE, 0)) < 0) { @@ -2963,7 +3029,7 @@ dhd_preinit_ioctls(dhd_pub_t *dhd) #if !defined(AP) && defined(WL_CFG80211) /* Check if firmware with HostAPD support used */ - if (strstr(fw_path, "_apsta") != NULL) { + if ((!op_mode && strstr(fw_path, "_apsta") != NULL) || (op_mode == 0x02)) { /* Turn off MPC in AP mode */ bcm_mkiovar("mpc", (char *)&mpc, 4, iovbuf, sizeof(iovbuf)); if ((ret = dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, @@ -3593,7 +3659,7 @@ void dhd_detach(dhd_pub_t *dhdp) #ifdef WL_CFG80211 if (dhd->dhd_state & DHD_ATTACH_STATE_CFG80211) { - wl_cfg80211_detach(); + wl_cfg80211_detach(NULL); dhd_monitor_uninit(); } #endif @@ -3640,7 +3706,6 @@ dhd_module_cleanup(void) dhd_customer_gpio_wlan_ctrl(WLAN_POWER_OFF); } - static int __init dhd_module_init(void) { @@ -3699,7 +3764,7 @@ dhd_module_init(void) } #endif #if defined(WL_CFG80211) - error = wl_android_post_init(); + wl_android_post_init(); #endif return error; @@ -3718,7 +3783,11 @@ fail_1: return error; } +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0) late_initcall(dhd_module_init); +#else +module_init(dhd_module_init); +#endif module_exit(dhd_module_cleanup); /* @@ -4019,7 +4088,13 @@ dhd_wl_host_event(dhd_info_t *dhd, int *ifidx, void *pktdata, #endif /* defined(CONFIG_BCMDHD_WEXT) */ #ifdef WL_CFG80211 - + if ((ntoh32(event->event_type) == WLC_E_IF) && + (((dhd_if_event_t *)*data)->action == WLC_E_IF_ADD)) + /* If ADD_IF has been called directly by wl utility then we + * should not report this. In case if ADD_IF was called from + * CFG stack, then too this event need not be reported back + */ + return (BCME_OK); if ((wl_cfg80211_is_progress_ifchange() || wl_cfg80211_is_progress_ifadd()) && (*ifidx != 0)) { /* diff --git a/drivers/net/wireless/bcmdhd/dhd_sdio.c b/drivers/net/wireless/bcmdhd/dhd_sdio.c index 404a649a9f41..5806c66239ae 100644 --- a/drivers/net/wireless/bcmdhd/dhd_sdio.c +++ b/drivers/net/wireless/bcmdhd/dhd_sdio.c @@ -21,7 +21,7 @@ * software in any way with any other Broadcom software provided under a license * other than the GPL, without Broadcom's express prior written consent. * - * $Id: dhd_sdio.c 301794 2011-12-08 20:41:35Z $ + * $Id: dhd_sdio.c 303389 2011-12-16 09:30:48Z $ */ #include @@ -1518,7 +1518,7 @@ enum { #ifdef DHD_DEBUG IOV_CHECKDIED, IOV_SERIALCONS, -#endif +#endif /* DHD_DEBUG */ IOV_DOWNLOAD, IOV_SOCRAM_STATE, IOV_FORCEEVEN, diff --git a/drivers/net/wireless/bcmdhd/include/dhdioctl.h b/drivers/net/wireless/bcmdhd/include/dhdioctl.h index 3f3755b53b09..0312d2206013 100644 --- a/drivers/net/wireless/bcmdhd/include/dhdioctl.h +++ b/drivers/net/wireless/bcmdhd/include/dhdioctl.h @@ -25,7 +25,7 @@ * software in any way with any other Broadcom software provided under a license * other than the GPL, without Broadcom's express prior written consent. * - * $Id: dhdioctl.h 277737 2011-08-16 17:54:59Z $ + * $Id: dhdioctl.h 307573 2012-01-12 00:04:39Z $ */ #ifndef _dhdioctl_h_ @@ -87,6 +87,7 @@ enum { #define DHD_BTA_VAL 0x1000 #define DHD_ISCAN_VAL 0x2000 #define DHD_ARPOE_VAL 0x4000 +#define DHD_WL_VAL 0x8000 #ifdef SDTEST /* For pktgen iovar */ diff --git a/drivers/net/wireless/bcmdhd/include/epivers.h b/drivers/net/wireless/bcmdhd/include/epivers.h index 41a078c42a03..a0e9ed12b88e 100644 --- a/drivers/net/wireless/bcmdhd/include/epivers.h +++ b/drivers/net/wireless/bcmdhd/include/epivers.h @@ -33,17 +33,17 @@ #define EPI_RC_NUMBER 195 -#define EPI_INCREMENTAL_NUMBER 15 +#define EPI_INCREMENTAL_NUMBER 19 #define EPI_BUILD_NUMBER 0 -#define EPI_VERSION 5, 90, 195, 15 +#define EPI_VERSION 5, 90, 195, 19 -#define EPI_VERSION_NUM 0x055ac30f +#define EPI_VERSION_NUM 0x055ac313 #define EPI_VERSION_DEV 5.90.195 -#define EPI_VERSION_STR "5.90.195.15" +#define EPI_VERSION_STR "5.90.195.19" #endif diff --git a/drivers/net/wireless/bcmdhd/include/proto/802.11.h b/drivers/net/wireless/bcmdhd/include/proto/802.11.h index 8850b2ded236..fd69aac41309 100644 --- a/drivers/net/wireless/bcmdhd/include/proto/802.11.h +++ b/drivers/net/wireless/bcmdhd/include/proto/802.11.h @@ -21,7 +21,7 @@ * * Fundamental types and constants relating to 802.11 * - * $Id: 802.11.h 289520 2011-10-13 04:44:55Z $ + * $Id: 802.11.h 304058 2011-12-21 00:39:12Z $ */ @@ -1394,6 +1394,14 @@ typedef struct dot11_ext_cap_ie dot11_ext_cap_ie_t; #define DOT11_OP_CLASS_NONE 255 +BWL_PRE_PACKED_STRUCT struct do11_ap_chrep { + uint8 id; + uint8 len; + uint8 reg; + uint8 chanlist[1]; +} BWL_POST_PACKED_STRUCT; +typedef struct do11_ap_chrep dot11_ap_chrep_t; + #define DOT11_RM_ACTION_RM_REQ 0 #define DOT11_RM_ACTION_RM_REP 1 @@ -1484,7 +1492,7 @@ typedef struct dot11_rmrep_bcn dot11_rmrep_bcn_t; #define DOT11_RMREQ_BCN_REPINFO_ID 1 #define DOT11_RMREQ_BCN_REPDET_ID 2 #define DOT11_RMREQ_BCN_REQUEST_ID 10 -#define DOT11_RMREQ_BCN_APCHREP_ID 51 +#define DOT11_RMREQ_BCN_APCHREP_ID DOT11_MNG_AP_CHREP_ID #define DOT11_RMREQ_BCN_REPDET_FIXED 0 diff --git a/drivers/net/wireless/bcmdhd/include/wlioctl.h b/drivers/net/wireless/bcmdhd/include/wlioctl.h index 676068c0b387..e31bfa94c006 100644 --- a/drivers/net/wireless/bcmdhd/include/wlioctl.h +++ b/drivers/net/wireless/bcmdhd/include/wlioctl.h @@ -24,7 +24,7 @@ * software in any way with any other Broadcom software provided under a license * other than the GPL, without Broadcom's express prior written consent. * - * $Id: wlioctl.h 302303 2011-12-10 07:51:07Z $ + * $Id: wlioctl.h 307468 2012-01-11 18:29:27Z $ */ @@ -821,8 +821,14 @@ typedef struct wlc_iov_trx_s { #define WLC_IOCTL_MEDLEN 1536 #ifdef WLC_HIGH_ONLY #define WLC_SAMPLECOLLECT_MAXLEN 1024 +#define WLC_SAMPLECOLLECT_MAXLEN_LCN40 1024 #else -#define WLC_SAMPLECOLLECT_MAXLEN 10240 +#if defined(LCNCONF) || defined(LCN40CONF) +#define WLC_SAMPLECOLLECT_MAXLEN 8192 +#else +#define WLC_SAMPLECOLLECT_MAXLEN 10240 +#endif +#define WLC_SAMPLECOLLECT_MAXLEN_LCN40 8192 #endif @@ -1411,7 +1417,7 @@ typedef struct wl_aci_args { #define TRIGGER_BADPLCP 0x10 #define TRIGGER_CRSGLITCH 0x20 #define WL_ACI_ARGS_LEGACY_LENGTH 16 -#define WL_SAMPLECOLLECT_T_VERSION 1 +#define WL_SAMPLECOLLECT_T_VERSION 2 typedef struct wl_samplecollect_args { uint8 coll_us; @@ -1419,7 +1425,7 @@ typedef struct wl_samplecollect_args { uint16 version; uint16 length; - uint8 trigger; + int8 trigger; uint16 timeout; uint16 mode; uint32 pre_dur; @@ -1429,6 +1435,11 @@ typedef struct wl_samplecollect_args { bool be_deaf; bool agc; bool filter; + + uint8 trigger_state; + uint8 module_sel1; + uint8 module_sel2; + uint16 nsamps; } wl_samplecollect_args_t; #define WL_SAMPLEDATA_HEADER_TYPE 1 diff --git a/drivers/net/wireless/bcmdhd/wl_android.c b/drivers/net/wireless/bcmdhd/wl_android.c index dc32f17a91fa..2cbe333b0dd6 100644 --- a/drivers/net/wireless/bcmdhd/wl_android.c +++ b/drivers/net/wireless/bcmdhd/wl_android.c @@ -73,7 +73,6 @@ #define CMD_GETBAND "GETBAND" #define CMD_COUNTRY "COUNTRY" #define CMD_P2P_SET_NOA "P2P_SET_NOA" -#define CMD_P2P_GET_NOA "P2P_GET_NOA" #define CMD_P2P_SET_PS "P2P_SET_PS" #define CMD_SET_AP_WPS_P2P_IE "SET_AP_WPS_P2P_IE" @@ -537,9 +536,6 @@ int wl_android_priv_cmd(struct net_device *net, struct ifreq *ifr, int cmd) bytes_written = wl_cfg80211_set_p2p_noa(net, command + skip, priv_cmd.total_len - skip); } - else if (strnicmp(command, CMD_P2P_GET_NOA, strlen(CMD_P2P_GET_NOA)) == 0) { - bytes_written = wl_cfg80211_get_p2p_noa(net, command, priv_cmd.total_len); - } else if (strnicmp(command, CMD_P2P_SET_PS, strlen(CMD_P2P_SET_PS)) == 0) { int skip = strlen(CMD_P2P_SET_PS) + 1; bytes_written = wl_cfg80211_set_p2p_ps(net, command + skip, @@ -611,30 +607,14 @@ int wl_android_exit(void) return ret; } -int wl_android_post_init(void) +void wl_android_post_init(void) { - struct net_device *ndev; - int ret = 0; - char buf[IFNAMSIZ]; if (!dhd_download_fw_on_driverload) { /* Call customer gpio to turn off power with WL_REG_ON signal */ dhd_customer_gpio_wlan_ctrl(WLAN_RESET_OFF); g_wifi_on = 0; - } else { - memset(buf, 0, IFNAMSIZ); -#ifdef CUSTOMER_HW2 - snprintf(buf, IFNAMSIZ, "%s%d", iface_name, 0); -#else - snprintf(buf, IFNAMSIZ, "%s%d", "eth", 0); -#endif - if ((ndev = dev_get_by_name (&init_net, buf)) != NULL) { - dhd_dev_init_ioctl(ndev); - dev_put(ndev); - } } - return ret; } - /** * Functions for Android WiFi card detection */ diff --git a/drivers/net/wireless/bcmdhd/wl_android.h b/drivers/net/wireless/bcmdhd/wl_android.h index 17373b7f6d5b..3983306cfe38 100644 --- a/drivers/net/wireless/bcmdhd/wl_android.h +++ b/drivers/net/wireless/bcmdhd/wl_android.h @@ -40,7 +40,7 @@ */ int wl_android_init(void); int wl_android_exit(void); -int wl_android_post_init(void); +void wl_android_post_init(void); int wl_android_wifi_on(struct net_device *dev); int wl_android_wifi_off(struct net_device *dev); int wl_android_priv_cmd(struct net_device *net, struct ifreq *ifr, int cmd); diff --git a/drivers/net/wireless/bcmdhd/wl_cfg80211.c b/drivers/net/wireless/bcmdhd/wl_cfg80211.c index c0857b6d95b4..b84d1e890c1b 100644 --- a/drivers/net/wireless/bcmdhd/wl_cfg80211.c +++ b/drivers/net/wireless/bcmdhd/wl_cfg80211.c @@ -41,10 +41,9 @@ #include #include #include +#include #include -#include -#include #include #include #include @@ -54,11 +53,7 @@ #include #include #include - #include -#include -#include -#include #include #include @@ -66,42 +61,20 @@ #include static struct device *cfg80211_parent_dev = NULL; -static struct wl_priv *wlcfg_drv_priv = NULL; +static int vsdb_supported = 0; +struct wl_priv *wlcfg_drv_priv = NULL; u32 wl_dbg_level = WL_DBG_ERR; -#define WL_4329_FW_FILE "brcm/bcm4329-fullmac-4-218-248-5.bin" -#define WL_4329_NVRAM_FILE "brcm/bcm4329-fullmac-4-218-248-5.txt" #define MAC2STR(a) (a)[0], (a)[1], (a)[2], (a)[3], (a)[4], (a)[5] #define MACSTR "%02x:%02x:%02x:%02x:%02x:%02x" #define MAX_WAIT_TIME 1500 -static s8 ioctlbuf[WLC_IOCTL_MAXLEN]; +#define WL_SCAN_ACTIVE_TIME 40 +#define WL_SCAN_PASSIVE_TIME 130 +#define DNGL_FUNC(func, parameters) func parameters; #define COEX_DHCP -#if defined(COEX_DHCP) -#define BT_DHCP_eSCO_FIX /* use New SCO/eSCO smart YG - * suppression - */ -#define BT_DHCP_USE_FLAGS /* this flag boost wifi pkt priority - * to max, caution: -not fair to sco - */ -#define BT_DHCP_OPPR_WIN_TIME 2500 /* T1 start SCO/ESCo priority - * suppression - */ -#define BT_DHCP_FLAG_FORCE_TIME 5500 /* T2 turn off SCO/SCO supperesion - * is (timeout) - */ -enum wl_cfg80211_btcoex_status { - BT_DHCP_IDLE, - BT_DHCP_START, - BT_DHCP_OPPR_WIN, - BT_DHCP_FLAG_FORCE_TIMEOUT -}; - -static int wl_cfg80211_btcoex_init(struct wl_priv *wl); -static void wl_cfg80211_btcoex_deinit(struct wl_priv *wl); -#endif /* Set this to 1 to use a seperate interface (p2p0) * for p2p operations. @@ -247,6 +220,8 @@ static s32 wl_enq_event(struct wl_priv *wl, struct net_device *ndev, u32 type, const wl_event_msg_t *msg, void *data); static void wl_put_event(struct wl_event_q *e); static void wl_wakeup_event(struct wl_priv *wl); +static s32 wl_notify_connect_status_ap(struct wl_priv *wl, struct net_device *ndev, + const wl_event_msg_t *e, void *data); static s32 wl_notify_connect_status(struct wl_priv *wl, struct net_device *ndev, const wl_event_msg_t *e, void *data); @@ -264,21 +239,10 @@ static s32 wl_notify_mic_status(struct wl_priv *wl, struct net_device *ndev, static s32 wl_notify_pfn_status(struct wl_priv *wl, struct net_device *ndev, const wl_event_msg_t *e, void *data); /* - * register/deregister sdio function + * register/deregister parent device */ static void wl_cfg80211_clear_parent_dev(void); -/* - * ioctl utilites - */ -static s32 wl_dev_bufvar_get(struct net_device *dev, s8 *name, s8 *buf, - s32 buf_len); -static __used s32 wl_dev_bufvar_set(struct net_device *dev, s8 *name, - s8 *buf, s32 len); -static s32 wl_dev_intvar_set(struct net_device *dev, s8 *name, s32 val); -static s32 wl_dev_intvar_get(struct net_device *dev, s8 *name, - s32 *retval); - /* * cfg80211 set_wiphy_params utilities */ @@ -321,7 +285,7 @@ static s32 wl_cp_ie(struct wl_priv *wl, u8 *dst, u16 dst_size); static u32 wl_get_ielen(struct wl_priv *wl); -static struct wireless_dev *wl_alloc_wdev(struct device *sdiofunc_dev); +static s32 wl_setup_wiphy(struct wireless_dev *wdev, struct device *dev); static void wl_free_wdev(struct wl_priv *wl); static s32 wl_inform_bss(struct wl_priv *wl); @@ -353,42 +317,19 @@ static bool wl_is_ibssmode(struct wl_priv *wl, struct net_device *ndev); static __used bool wl_is_ibssstarter(struct wl_priv *wl); /* - * dongle up/down , default configuration utilities + * link up/down , default configuration utilities */ +static s32 __wl_cfg80211_up(struct wl_priv *wl); +static s32 __wl_cfg80211_down(struct wl_priv *wl); +static s32 wl_add_remove_eventmsg(struct net_device *ndev, u16 event, bool add); static bool wl_is_linkdown(struct wl_priv *wl, const wl_event_msg_t *e); static bool wl_is_linkup(struct wl_priv *wl, const wl_event_msg_t *e, struct net_device *ndev); static bool wl_is_nonetwork(struct wl_priv *wl, const wl_event_msg_t *e); static void wl_link_up(struct wl_priv *wl); static void wl_link_down(struct wl_priv *wl); -static s32 wl_dongle_mode(struct wl_priv *wl, struct net_device *ndev, s32 iftype); -static s32 __wl_cfg80211_up(struct wl_priv *wl); -static s32 __wl_cfg80211_down(struct wl_priv *wl); -static s32 wl_dongle_probecap(struct wl_priv *wl); +static s32 wl_config_ifmode(struct wl_priv *wl, struct net_device *ndev, s32 iftype); static void wl_init_conf(struct wl_conf *conf); -static s32 wl_dongle_add_remove_eventmsg(struct net_device *ndev, u16 event, bool add); - -/* - * dongle configuration utilities - */ -#ifndef EMBEDDED_PLATFORM -static s32 wl_dongle_country(struct net_device *ndev, u8 ccode); -static s32 wl_dongle_up(struct net_device *ndev, u32 up); -static s32 wl_dongle_power(struct net_device *ndev, u32 power_mode); -static s32 wl_dongle_glom(struct net_device *ndev, u32 glom, - u32 dongle_align); -static s32 wl_dongle_roam(struct net_device *ndev, u32 roamvar, - u32 bcn_timeout); -static s32 wl_dongle_scantime(struct net_device *ndev, s32 scan_assoc_time, - s32 scan_unassoc_time); -static s32 wl_dongle_offload(struct net_device *ndev, s32 arpoe, - s32 arp_ol); -static s32 wl_pattern_atoh(s8 *src, s8 *dst); -static s32 wl_dongle_filter(struct net_device *ndev, u32 filter_mode); static s32 wl_update_wiphybands(struct wl_priv *wl); -#endif /* !EMBEDDED_PLATFORM */ -static __used void wl_dongle_poweron(struct wl_priv *wl); -static __used void wl_dongle_poweroff(struct wl_priv *wl); -static s32 wl_config_dongle(struct wl_priv *wl, bool need_lock); /* * iscan handler @@ -411,34 +352,21 @@ static s32 wl_iscan_pending(struct wl_priv *wl); static s32 wl_iscan_inprogress(struct wl_priv *wl); static s32 wl_iscan_aborted(struct wl_priv *wl); -/* - * fw/nvram downloading handler - */ -static void wl_init_fw(struct wl_fw_ctrl *fw); - /* * find most significant bit set */ static __used u32 wl_find_msb(u16 bit16); -/* - * update pmklist to dongle - */ -static __used s32 wl_update_pmklist(struct net_device *dev, - struct wl_pmk_list *pmk_list, s32 err); - -/* - * debufs support - */ -static int wl_debugfs_add_netdev_params(struct wl_priv *wl, struct net_device *ndev); -static void wl_debugfs_remove_netdev(struct wl_priv *wl); - /* * rfkill support */ static int wl_setup_rfkill(struct wl_priv *wl, bool setup); static int wl_rfkill_set(void *data, bool blocked); +static wl_scan_params_t *wl_cfg80211_scan_alloc_params(int channel, + int nprobes, int *out_params_size); +static void get_primary_mac(struct wl_priv *wl, struct ether_addr *mac); + /* * Some external functions, TODO: move them to dhd_linux.h */ @@ -579,7 +507,22 @@ static struct ieee80211_supported_band __wl_band_2ghz = { .channels = __wl_2ghz_channels, .n_channels = ARRAY_SIZE(__wl_2ghz_channels), .bitrates = wl_g_rates, - .n_bitrates = wl_g_rates_size + .n_bitrates = wl_g_rates_size, +#if ENABLE_P2P_INTERFACE + /* wpa_supplicant sets wmm_enabled based on whether ht_cap + * is present or not. The wmm_enabled is inturn used to + * set the replay counters in the RSN IE. Without this + * the 4way handshake will fail complaining that IE in beacon + * doesn't match with the IE present in the 3/4 EAPOL msg. + */ + .ht_cap = { + IEEE80211_HT_CAP_SGI_20 | + IEEE80211_HT_CAP_DSSSCCK40 | IEEE80211_HT_CAP_MAX_AMSDU, + .ht_supported = TRUE, + .ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K, + .ampdu_density = IEEE80211_HT_MPDU_DENSITY_16 + } +#endif }; static struct ieee80211_supported_band __wl_band_5ghz_a = { @@ -748,36 +691,39 @@ wl_validate_wps_ie(char *wps_ie, bool *pbc) static chanspec_t wl_cfg80211_get_shared_freq(struct wiphy *wiphy) { - chanspec_t chspec; - int err = 0; - struct wl_priv *wl = wiphy_priv(wiphy); - struct net_device *dev = wl_to_prmry_ndev(wl); - struct ether_addr bssid; - struct wl_bss_info *bss = NULL; - - if ((err = wldev_ioctl(dev, WLC_GET_BSSID, &bssid, sizeof(bssid), false))) { - /* STA interface is not associated. So start the new interface on a temp - * channel . Later proper channel will be applied by the above framework - * via set_channel (cfg80211 API). - */ - WL_DBG(("Not associated. Return a temp channel. \n")); + if (vsdb_supported) { return wf_chspec_aton(WL_P2P_TEMP_CHAN); } + else { + chanspec_t chspec; + int err = 0; + struct wl_priv *wl = wiphy_priv(wiphy); + struct net_device *dev = wl_to_prmry_ndev(wl); + struct ether_addr bssid; + struct wl_bss_info *bss = NULL; + if ((err = wldev_ioctl(dev, WLC_GET_BSSID, &bssid, sizeof(bssid), false))) { + /* STA interface is not associated. So start the new interface on a temp + * channel . Later proper channel will be applied by the above framework + * via set_channel (cfg80211 API). + */ + WL_DBG(("Not associated. Return a temp channel. \n")); + return wf_chspec_aton(WL_P2P_TEMP_CHAN); + } - *(u32 *) wl->extra_buf = htod32(WL_EXTRA_BUF_MAX); - if ((err = wldev_ioctl(dev, WLC_GET_BSS_INFO, wl->extra_buf, - sizeof(WL_EXTRA_BUF_MAX), false))) { - WL_ERR(("Failed to get associated bss info, use temp channel \n")); - chspec = wf_chspec_aton(WL_P2P_TEMP_CHAN); - } - else { - bss = (struct wl_bss_info *) (wl->extra_buf + 4); - chspec = bss->chanspec; - WL_DBG(("Valid BSS Found. chanspec:%d \n", bss->chanspec)); + *(u32 *) wl->extra_buf = htod32(WL_EXTRA_BUF_MAX); + if ((err = wldev_ioctl(dev, WLC_GET_BSS_INFO, wl->extra_buf, + sizeof(WL_EXTRA_BUF_MAX), false))) { + WL_ERR(("Failed to get associated bss info, use temp channel \n")); + chspec = wf_chspec_aton(WL_P2P_TEMP_CHAN); + } + else { + bss = (struct wl_bss_info *) (wl->extra_buf + 4); + chspec = bss->chanspec; + WL_DBG(("Valid BSS Found. chanspec:%d \n", bss->chanspec)); + } + return chspec; } - - return chspec; } static struct net_device* wl_cfg80211_add_monitor_if(char *name) @@ -802,9 +748,10 @@ wl_cfg80211_add_virtual_iface(struct wiphy *wiphy, char *name, chanspec_t chspec; struct wl_priv *wl = wiphy_priv(wiphy); struct net_device *_ndev; - dhd_pub_t *dhd = (dhd_pub_t *)(wl->pub); - int (*net_attach)(dhd_pub_t *dhdp, int ifidx); + struct ether_addr primary_mac; + int (*net_attach)(void *dhdp, int ifidx); bool rollback_lock = false; + /* Use primary I/F for sending cmds down to firmware */ _ndev = wl_to_prmry_ndev(wl); @@ -852,7 +799,7 @@ wl_cfg80211_add_virtual_iface(struct wiphy *wiphy, char *name, } WL_INFO(("%s: Released the lock and wait till IF_DEL is complete\n", __func__)); - timeout = wait_event_interruptible_timeout(wl->dongle_event_wait, + timeout = wait_event_interruptible_timeout(wl->netif_change_event, (wl_get_p2p_status(wl, IF_DELETING) == false), msecs_to_jiffies(MAX_WAIT_TIME)); @@ -874,9 +821,11 @@ wl_cfg80211_add_virtual_iface(struct wiphy *wiphy, char *name, wl_cfgp2p_set_firm_p2p(wl); wl_cfgp2p_init_discovery(wl); } + memset(wl->p2p->vir_ifname, 0, IFNAMSIZ); strncpy(wl->p2p->vir_ifname, name, IFNAMSIZ - 1); - wl_cfgp2p_generate_bss_mac(&dhd->mac, &wl->p2p->dev_addr, &wl->p2p->int_addr); + get_primary_mac(wl, &primary_mac); + wl_cfgp2p_generate_bss_mac(&primary_mac, &wl->p2p->dev_addr, &wl->p2p->int_addr); /* In concurrency case, STA may be already associated in a particular channel. * so retrieve the current channel of primary interface and then start the virtual @@ -895,7 +844,7 @@ wl_cfg80211_add_virtual_iface(struct wiphy *wiphy, char *name, return ERR_PTR(-ENOMEM); } - timeout = wait_event_interruptible_timeout(wl->dongle_event_wait, + timeout = wait_event_interruptible_timeout(wl->netif_change_event, (wl_get_p2p_status(wl, IF_ADD) == false), msecs_to_jiffies(MAX_WAIT_TIME)); if (timeout > 0 && (!wl_get_p2p_status(wl, IF_ADD))) { @@ -922,7 +871,7 @@ wl_cfg80211_add_virtual_iface(struct wiphy *wiphy, char *name, rtnl_unlock(); rollback_lock = true; } - if (net_attach && !net_attach(dhd, _ndev->ifindex)) { + if (net_attach && !net_attach(wl->pub, _ndev->ifindex)) { wl_alloc_netinfo(wl, _ndev, vwdev, mode); WL_DBG((" virtual interface(%s) is " "created net attach done\n", wl->p2p->vir_ifname)); @@ -973,21 +922,22 @@ wl_cfg80211_del_virtual_iface(struct wiphy *wiphy, struct net_device *dev) wldev_iovar_setint(dev, "mpc", 1); wl_set_p2p_status(wl, IF_DELETING); ret = wl_cfgp2p_ifdel(wl, &p2p_mac); - if (ret) { /* Firmware could not delete the interface so we will not get WLC_E_IF * event for cleaning the dhd virtual nw interace * So lets do it here. Failures from fw will ensure the application to do * ifconfig down and up sequnce, which will reload the fw * however we should cleanup the linux network virtual interfaces */ - dhd_pub_t *dhd = (dhd_pub_t *)(wl->pub); - WL_ERR(("Firmware returned an error from p2p_ifdel\n")); - WL_ERR(("try to remove linux virtual interface %s\n", dev->name)); - dhd_del_if(dhd->info, dhd_net2idx(dhd->info, dev)); + /* Request framework to RESET and clean up */ + if (ret) { + struct net_device *ndev = wl_to_prmry_ndev(wl); + WL_ERR(("Firmware returned an error (%d) from p2p_ifdel" + "HANG Notification sent to %s\n", ret, ndev->name)); + wl_cfg80211_hang(ndev, WLAN_REASON_UNSPECIFIED); } /* Wait for any pending scan req to get aborted from the sysioc context */ - timeout = wait_event_interruptible_timeout(wl->dongle_event_wait, + timeout = wait_event_interruptible_timeout(wl->netif_change_event, (wl_get_p2p_status(wl, IF_DELETING) == false), msecs_to_jiffies(MAX_WAIT_TIME)); if (timeout > 0 && !wl_get_p2p_status(wl, IF_DELETING)) { @@ -1014,6 +964,7 @@ wl_cfg80211_change_virtual_iface(struct wiphy *wiphy, struct net_device *ndev, s32 mode = 0; chanspec_t chspec; struct wl_priv *wl = wiphy_priv(wiphy); + WL_DBG(("Enter \n")); switch (type) { case NL80211_IFTYPE_MONITOR: @@ -1046,7 +997,7 @@ wl_cfg80211_change_virtual_iface(struct wiphy *wiphy, struct net_device *ndev, if (wl->p2p_supported && wl->p2p->vif_created) { WL_DBG(("p2p_vif_created (%d) p2p_on (%d)\n", wl->p2p->vif_created, p2p_on(wl))); - + wldev_iovar_setint(ndev, "mpc", 0); /* In concurrency case, STA may be already associated in a particular * channel. so retrieve the current channel of primary interface and * then start the virtual interface on that. @@ -1059,7 +1010,7 @@ wl_cfg80211_change_virtual_iface(struct wiphy *wiphy, struct net_device *ndev, wl_set_p2p_status(wl, IF_CHANGING); wl_clr_p2p_status(wl, IF_CHANGED); err = wl_cfgp2p_ifchange(wl, &wl->p2p->int_addr, htod32(wlif_type), chspec); - timeout = wait_event_interruptible_timeout(wl->dongle_event_wait, + timeout = wait_event_interruptible_timeout(wl->netif_change_event, (wl_get_p2p_status(wl, IF_CHANGED) == true), msecs_to_jiffies(MAX_WAIT_TIME)); wl_set_mode_by_netdev(wl, ndev, mode); @@ -1085,10 +1036,11 @@ wl_cfg80211_change_virtual_iface(struct wiphy *wiphy, struct net_device *ndev, s32 wl_cfg80211_notify_ifadd(struct net_device *ndev, s32 idx, s32 bssidx, -int (*_net_attach)(dhd_pub_t *dhdp, int ifidx)) + void* _net_attach) { struct wl_priv *wl = wlcfg_drv_priv; s32 ret = BCME_OK; + WL_DBG(("Enter")); if (!ndev) { WL_ERR(("net is NULL\n")); return 0; @@ -1104,7 +1056,7 @@ int (*_net_attach)(dhd_pub_t *dhdp, int ifidx)) ndev->ifindex = idx; wl_clr_p2p_status(wl, IF_ADD); - wake_up_interruptible(&wl->dongle_event_wait); + wake_up_interruptible(&wl->netif_change_event); } else { ret = BCME_NOTREADY; } @@ -1153,7 +1105,7 @@ wl_cfg80211_notify_ifdel(struct net_device *ndev) } /* Wake up any waiting thread */ - wake_up_interruptible(&wl->dongle_event_wait); + wake_up_interruptible(&wl->netif_change_event); return 0; } @@ -1185,7 +1137,7 @@ wl_cfg80211_notify_ifchange(void) struct wl_priv *wl = wlcfg_drv_priv; if (wl_get_p2p_status(wl, IF_CHANGING)) { wl_set_p2p_status(wl, IF_CHANGED); - wake_up_interruptible(&wl->dongle_event_wait); + wake_up_interruptible(&wl->netif_change_event); } return 0; } @@ -1222,6 +1174,7 @@ static void wl_scan_prep(struct wl_scan_params *params, struct cfg80211_scan_req params->passive_time = htod32(params->passive_time); params->home_time = htod32(params->home_time); + /* if request is null just exit so it will be all channel broadcast scan */ if (!request) return; @@ -1328,7 +1281,7 @@ wl_run_iscan(struct wl_iscan_ctrl *iscan, struct cfg80211_scan_request *request, goto done; } err = wldev_iovar_setbuf(iscan->dev, "iscan", params, params_size, - iscan->ioctl_buf, WLC_IOCTL_MEDLEN); + iscan->ioctl_buf, WLC_IOCTL_MEDLEN, NULL); if (unlikely(err)) { if (err == -EBUSY) { WL_ERR(("system busy : iscan canceled\n")); @@ -1418,7 +1371,7 @@ wl_run_escan(struct wl_priv *wl, struct net_device *ndev, goto exit; } err = wldev_iovar_setbuf(ndev, "escan", params, params_size, - wl->escan_ioctl_buf, WLC_IOCTL_MEDLEN); + wl->escan_ioctl_buf, WLC_IOCTL_MEDLEN, NULL); if (unlikely(err)) WL_ERR((" Escan set error (%d)\n", err)); kfree(params); @@ -1516,8 +1469,7 @@ __wl_cfg80211_scan(struct wiphy *wiphy, struct net_device *ndev, u32 wpsie_len = 0; u8 wpsie[IE_MAX_LEN]; - /* If scan req comes for p2p0, send it over primary I/F as there - * there is no firmware interface corresponding to p2p0. + /* If scan req comes for p2p0, send it over primary I/F * Scan results will be delivered corresponding to cfg80211_scan_request */ if (ndev == wl->p2p_net) { @@ -1534,7 +1486,7 @@ __wl_cfg80211_scan(struct wiphy *wiphy, struct net_device *ndev, return -EAGAIN; } if (request && request->n_ssids > WL_SCAN_PARAMS_SSID_MAX) { - WL_ERR(("n_ssids > WL_SCAN_PARAMS_SSID_MAX\n")); + WL_ERR(("request null or n_ssids > WL_SCAN_PARAMS_SSID_MAX\n")); return -EOPNOTSUPP; } @@ -1700,52 +1652,11 @@ wl_cfg80211_scan(struct wiphy *wiphy, struct net_device *ndev, return err; } -static s32 wl_dev_intvar_set(struct net_device *dev, s8 *name, s32 val) -{ - s8 buf[WLC_IOCTL_SMLEN]; - u32 len; - s32 err = 0; - - val = htod32(val); - len = bcm_mkiovar(name, (char *)(&val), sizeof(val), buf, sizeof(buf)); - BUG_ON(unlikely(!len)); - - err = wldev_ioctl(dev, WLC_SET_VAR, buf, len, false); - if (unlikely(err)) { - WL_ERR(("error (%d)\n", err)); - } - - return err; -} - -static s32 -wl_dev_intvar_get(struct net_device *dev, s8 *name, s32 *retval) -{ - union { - s8 buf[WLC_IOCTL_SMLEN]; - s32 val; - } var; - u32 len; - u32 data_null; - s32 err = 0; - - len = bcm_mkiovar(name, (char *)(&data_null), 0, - (char *)(&var), sizeof(var.buf)); - BUG_ON(unlikely(!len)); - err = wldev_ioctl(dev, WLC_GET_VAR, &var, len, false); - if (unlikely(err)) { - WL_ERR(("error (%d)\n", err)); - } - *retval = dtoh32(var.val); - - return err; -} - static s32 wl_set_rts(struct net_device *dev, u32 rts_threshold) { s32 err = 0; - err = wl_dev_intvar_set(dev, "rtsthresh", rts_threshold); + err = wldev_iovar_setint(dev, "rtsthresh", rts_threshold); if (unlikely(err)) { WL_ERR(("Error (%d)\n", err)); return err; @@ -1757,7 +1668,7 @@ static s32 wl_set_frag(struct net_device *dev, u32 frag_threshold) { s32 err = 0; - err = wl_dev_intvar_set(dev, "fragthresh", frag_threshold); + err = wldev_iovar_setint_bsscfg(dev, "fragthresh", frag_threshold, 0); if (unlikely(err)) { WL_ERR(("Error (%d)\n", err)); return err; @@ -1786,6 +1697,7 @@ static s32 wl_cfg80211_set_wiphy_params(struct wiphy *wiphy, u32 changed) s32 err = 0; CHECK_SYS_UP(wl); + WL_DBG(("Enter\n")); if (changed & WIPHY_PARAM_RTS_THRESHOLD && (wl->conf->rts_threshold != wiphy->rts_threshold)) { wl->conf->rts_threshold = wiphy->rts_threshold; @@ -1815,7 +1727,6 @@ static s32 wl_cfg80211_set_wiphy_params(struct wiphy *wiphy, u32 changed) return err; } } - return err; } @@ -2060,7 +1971,7 @@ wl_set_key_mgmt(struct net_device *dev, struct cfg80211_connect_params *sme) s32 bssidx = wl_cfgp2p_find_idx(wl, dev); if (sme->crypto.n_akm_suites) { - err = wl_dev_intvar_get(dev, "wpa_auth", &val); + err = wldev_iovar_getint(dev, "wpa_auth", &val); if (unlikely(err)) { WL_ERR(("could not get wpa_auth (%d)\n", err)); return err; @@ -2125,7 +2036,8 @@ wl_set_set_sharedkey(struct net_device *dev, if (!(sec->wpa_versions & (NL80211_WPA_VERSION_1 | NL80211_WPA_VERSION_2)) && (sec->cipher_pairwise & (WLAN_CIPHER_SUITE_WEP40 | - WLAN_CIPHER_SUITE_WEP104))) { + WLAN_CIPHER_SUITE_WEP104))) + { memset(&key, 0, sizeof(key)); key.len = (u32) sme->key_len; key.index = (u32) sme->key_idx; @@ -2153,7 +2065,7 @@ wl_set_set_sharedkey(struct net_device *dev, WL_DBG(("key \"%s\"\n", key.data)); swap_key_from_BE(&key); err = wldev_iovar_setbuf_bsscfg(dev, "wsec_key", &key, sizeof(key), - ioctlbuf, sizeof(ioctlbuf), bssidx); + wl->ioctl_buf, WLC_IOCTL_MAXLEN, bssidx, &wl->ioctl_buf_sync); if (unlikely(err)) { WL_ERR(("WLC_SET_KEY error (%d)\n", err)); return err; @@ -2247,10 +2159,10 @@ wl_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev, wpaie_len = (wpa_ie != NULL) ? wpa_ie->length : wpa2_ie->len; wpaie_len += WPA_RSN_IE_TAG_FIXED_LEN; wldev_iovar_setbuf(dev, "wpaie", wpaie, wpaie_len, - ioctlbuf, sizeof(ioctlbuf)); + wl->ioctl_buf, WLC_IOCTL_MAXLEN, &wl->ioctl_buf_sync); } else { wldev_iovar_setbuf(dev, "wpaie", NULL, 0, - ioctlbuf, sizeof(ioctlbuf)); + wl->ioctl_buf, WLC_IOCTL_MAXLEN, &wl->ioctl_buf_sync); } /* find the WPSIE */ @@ -2331,8 +2243,8 @@ wl_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev, /* increate dwell time to receive probe response or detect Beacon * from target AP at a noisy air only during connect command */ - ext_join_params->scan.active_time = DHD_SCAN_ACTIVE_TIME*3; - ext_join_params->scan.passive_time = DHD_SCAN_PASSIVE_TIME*3; + ext_join_params->scan.active_time = WL_SCAN_ACTIVE_TIME*3; + ext_join_params->scan.passive_time = WL_SCAN_PASSIVE_TIME*3; ext_join_params->scan.home_time = -1; if (sme->bssid) @@ -2360,8 +2272,8 @@ wl_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev, ext_join_params->ssid.SSID_len)); } wl_set_drv_status(wl, CONNECTING, dev); - err = wldev_iovar_setbuf_bsscfg(dev, "join", ext_join_params, join_params_size, ioctlbuf, - sizeof(ioctlbuf), wl_cfgp2p_find_idx(wl, dev)); + err = wldev_iovar_setbuf_bsscfg(dev, "join", ext_join_params, join_params_size, + wl->ioctl_buf, WLC_IOCTL_MAXLEN, wl_cfgp2p_find_idx(wl, dev), &wl->ioctl_buf_sync); kfree(ext_join_params); if (err) { wl_clr_drv_status(wl, CONNECTING, dev); @@ -2480,7 +2392,7 @@ wl_cfg80211_set_tx_power(struct wiphy *wiphy, txpwrmw = 0xffff; else txpwrmw = (u16) dbm; - err = wl_dev_intvar_set(ndev, "qtxpower", + err = wldev_iovar_setint(ndev, "qtxpower", (s32) (bcm_mw_to_qdbm(txpwrmw))); if (unlikely(err)) { WL_ERR(("qtxpower error (%d)\n", err)); @@ -2500,7 +2412,7 @@ static s32 wl_cfg80211_get_tx_power(struct wiphy *wiphy, s32 *dbm) s32 err = 0; CHECK_SYS_UP(wl); - err = wl_dev_intvar_get(ndev, "qtxpower", &txpwrdbm); + err = wldev_iovar_getint(ndev, "qtxpower", &txpwrdbm); if (unlikely(err)) { WL_ERR(("error (%d)\n", err)); return err; @@ -2561,8 +2473,8 @@ wl_add_keyext(struct wiphy *wiphy, struct net_device *dev, if (key.len == 0) { /* key delete */ swap_key_from_BE(&key); - wldev_iovar_setbuf_bsscfg(dev, "wsec_key", &key, sizeof(key), ioctlbuf, - sizeof(ioctlbuf), bssidx); + wldev_iovar_setbuf_bsscfg(dev, "wsec_key", &key, sizeof(key), + wl->ioctl_buf, WLC_IOCTL_MAXLEN, bssidx, &wl->ioctl_buf_sync); if (unlikely(err)) { WL_ERR(("key delete error (%d)\n", err)); return err; @@ -2620,11 +2532,11 @@ wl_add_keyext(struct wiphy *wiphy, struct net_device *dev, return -EINVAL; } swap_key_from_BE(&key); -#ifdef CONFIG_WIRELESS_EXT +#if defined(CONFIG_WIRELESS_EXT) dhd_wait_pend8021x(dev); #endif - wldev_iovar_setbuf_bsscfg(dev, "wsec_key", &key, sizeof(key), ioctlbuf, - sizeof(ioctlbuf), bssidx); + wldev_iovar_setbuf_bsscfg(dev, "wsec_key", &key, sizeof(key), + wl->ioctl_buf, WLC_IOCTL_MAXLEN, bssidx, &wl->ioctl_buf_sync); if (unlikely(err)) { WL_ERR(("WLC_SET_KEY error (%d)\n", err)); return err; @@ -2706,8 +2618,8 @@ wl_cfg80211_add_key(struct wiphy *wiphy, struct net_device *dev, /* Set the new key/index */ swap_key_from_BE(&key); - err = wldev_iovar_setbuf_bsscfg(dev, "wsec_key", &key, sizeof(key), ioctlbuf, - sizeof(ioctlbuf), bssidx); + err = wldev_iovar_setbuf_bsscfg(dev, "wsec_key", &key, sizeof(key), wl->ioctl_buf, + WLC_IOCTL_MAXLEN, bssidx, &wl->ioctl_buf_sync); if (unlikely(err)) { WL_ERR(("WLC_SET_KEY error (%d)\n", err)); return err; @@ -2750,8 +2662,8 @@ wl_cfg80211_del_key(struct wiphy *wiphy, struct net_device *dev, WL_DBG(("key index (%d)\n", key_idx)); /* Set the new key/index */ swap_key_from_BE(&key); - wldev_iovar_setbuf_bsscfg(dev, "wsec_key", &key, sizeof(key), ioctlbuf, - sizeof(ioctlbuf), bssidx); + wldev_iovar_setbuf_bsscfg(dev, "wsec_key", &key, sizeof(key), wl->ioctl_buf, + WLC_IOCTL_MAXLEN, bssidx, &wl->ioctl_buf_sync); if (unlikely(err)) { if (err == -EINVAL) { if (key.index >= DOT11_MAX_DEFAULT_KEYS) { @@ -2847,13 +2759,13 @@ wl_cfg80211_get_station(struct wiphy *wiphy, struct net_device *dev, CHECK_SYS_UP(wl); if (wl_get_mode_by_netdev(wl, dev) == WL_MODE_AP) { err = wldev_iovar_getbuf(dev, "sta_info", (struct ether_addr *)mac, - ETHER_ADDR_LEN, ioctlbuf, sizeof(ioctlbuf)); + ETHER_ADDR_LEN, wl->ioctl_buf, WLC_IOCTL_MAXLEN, &wl->ioctl_buf_sync); if (err < 0) { WL_ERR(("GET STA INFO failed, %d\n", err)); return err; } sinfo->filled = STATION_INFO_INACTIVE_TIME; - sta = (sta_info_t *)ioctlbuf; + sta = (sta_info_t *)wl->ioctl_buf; sta->len = dtoh16(sta->len); sta->cap = dtoh16(sta->cap); sta->flags = dtoh32(sta->flags); @@ -2931,9 +2843,6 @@ wl_cfg80211_set_power_mgmt(struct wiphy *wiphy, struct net_device *dev, CHECK_SYS_UP(wl); if (wl->p2p_net == dev) { - /* Since p2p0 is a hidden interface in firmware, power - * mgmt doesn't apply. - */ return err; } @@ -3019,7 +2928,7 @@ static s32 wl_cfg80211_suspend(struct wiphy *wiphy) for_each_ndev(wl, iter, next) wl_set_drv_status(wl, SCAN_ABORTING, iter->ndev); wl_term_iscan(wl); - flags = dhd_os_spin_lock((dhd_pub_t *)(wl->pub)); + spin_lock_irqsave(&wl->cfgdrv_lock, flags); if (wl->scan_request) { cfg80211_scan_done(wl->scan_request, true); wl->scan_request = NULL; @@ -3028,7 +2937,7 @@ static s32 wl_cfg80211_suspend(struct wiphy *wiphy) wl_clr_drv_status(wl, SCANNING, iter->ndev); wl_clr_drv_status(wl, SCAN_ABORTING, iter->ndev); } - dhd_os_spin_unlock((dhd_pub_t *)(wl->pub), flags); + spin_unlock_irqrestore(&wl->cfgdrv_lock, flags); for_each_ndev(wl, iter, next) { if (wl_get_drv_status(wl, CONNECTING, iter->ndev)) { wl_bss_connect_done(wl, iter->ndev, NULL, NULL, false); @@ -3038,7 +2947,7 @@ static s32 wl_cfg80211_suspend(struct wiphy *wiphy) return 0; } -static __used s32 +static s32 wl_update_pmklist(struct net_device *dev, struct wl_pmk_list *pmk_list, s32 err) { @@ -3046,9 +2955,12 @@ wl_update_pmklist(struct net_device *dev, struct wl_pmk_list *pmk_list, struct wl_priv *wl = wlcfg_drv_priv; struct net_device *primary_dev = wl_to_prmry_ndev(wl); - /* Firmware is supporting pmk list only for STA interface i.e. primary interface + if (!pmk_list) { + printk("pmk_list is NULL\n"); + return -EINVAL; + } + /* pmk list is supported only for STA interface i.e. primary interface * Refer code wlc_bsscfg.c->wlc_bsscfg_sta_init - * Do we really need to support PMK cache in P2P in firmware? */ if (primary_dev != dev) { WL_INFO(("Not supporting Flushing pmklist on virtual" @@ -3065,8 +2977,8 @@ wl_update_pmklist(struct net_device *dev, struct wl_pmk_list *pmk_list, } } if (likely(!err)) { - err = wl_dev_bufvar_set(dev, "pmkid_info", (char *)pmk_list, - sizeof(*pmk_list)); + err = wldev_iovar_setbuf(dev, "pmkid_info", (char *)pmk_list, + sizeof(*pmk_list), wl->ioctl_buf, WLC_IOCTL_MAXLEN, NULL); } return err; @@ -3167,7 +3079,7 @@ wl_cfg80211_flush_pmksa(struct wiphy *wiphy, struct net_device *dev) } -wl_scan_params_t * +static wl_scan_params_t * wl_cfg80211_scan_alloc_params(int channel, int nprobes, int *out_params_size) { wl_scan_params_t *params; @@ -3228,13 +3140,13 @@ wl_cfg80211_scan_abort(struct wl_priv *wl, struct net_device *ndev) } } del_timer_sync(&wl->scan_timeout); - flags = dhd_os_spin_lock((dhd_pub_t *)(wl->pub)); + spin_lock_irqsave(&wl->cfgdrv_lock, flags); if (wl->scan_request) { cfg80211_scan_done(wl->scan_request, true); wl->scan_request = NULL; } wl_clr_drv_status(wl, SCANNING, ndev); - dhd_os_spin_unlock((dhd_pub_t *)(wl->pub), flags); + spin_unlock_irqrestore(&wl->cfgdrv_lock, flags); if (params) kfree(params); return err; @@ -3248,23 +3160,21 @@ wl_cfg80211_remain_on_channel(struct wiphy *wiphy, struct net_device *dev, { s32 target_channel; u32 id; + struct ether_addr primary_mac; struct net_device *ndev = NULL; + s32 err = BCME_OK; struct wl_priv *wl = wiphy_priv(wiphy); - dhd_pub_t *dhd = (dhd_pub_t *)(wl->pub); WL_DBG(("Enter, netdev_ifidx: %d \n", dev->ifindex)); if (wl->p2p_net == dev) { - /* Since there is no ifidx corresponding to p2p0, cmds to - * firmware should be routed through primary I/F - */ ndev = wl_to_prmry_ndev(wl); } else { ndev = dev; } - if (wl_get_drv_status(wl, SCANNING, dev)) { - wl_cfg80211_scan_abort(wl, dev); + if (wl_get_drv_status(wl, SCANNING, ndev)) { + wl_cfg80211_scan_abort(wl, ndev); } target_channel = ieee80211_frequency_to_channel(channel->center_freq); @@ -3277,14 +3187,15 @@ wl_cfg80211_remain_on_channel(struct wiphy *wiphy, struct net_device *dev, cfg80211_ready_on_channel(dev, *cookie, channel, channel_type, duration, GFP_KERNEL); if (!p2p_is_on(wl)) { - wl_cfgp2p_generate_bss_mac(&dhd->mac, &wl->p2p->dev_addr, &wl->p2p->int_addr); + get_primary_mac(wl, &primary_mac); + wl_cfgp2p_generate_bss_mac(&primary_mac, &wl->p2p->dev_addr, &wl->p2p->int_addr); /* In case of p2p_listen command, supplicant send remain_on_channel * without turning on P2P */ p2p_on(wl) = true; - err = wl_cfgp2p_enable_discovery(wl, dev, NULL, 0); + err = wl_cfgp2p_enable_discovery(wl, ndev, NULL, 0); if (unlikely(err)) { goto exit; @@ -3307,6 +3218,93 @@ wl_cfg80211_cancel_remain_on_channel(struct wiphy *wiphy, struct net_device *dev return err; } +static s32 +wl_cfg80211_send_pending_tx_act_frm(struct wl_priv *wl) +{ + wl_af_params_t *tx_act_frm; + struct net_device *dev = wl->afx_hdl->dev; + if (!p2p_is_on(wl)) + return -1; + + if (dev == wl->p2p_net) { + dev = wl_to_prmry_ndev(wl); + } + + tx_act_frm = wl->afx_hdl->pending_tx_act_frm; + WL_DBG(("Sending the action frame\n")); + wl->afx_hdl->pending_tx_act_frm = NULL; + if (tx_act_frm != NULL) { + /* Suspend P2P discovery's search-listen to prevent it from + * starting a scan or changing the channel. + */ + wl_clr_drv_status(wl, SENDING_ACT_FRM, wl->afx_hdl->dev); + wl_clr_drv_status(wl, SCANNING, wl->afx_hdl->dev); + wl_cfg80211_scan_abort(wl, dev); + wl_cfgp2p_discover_enable_search(wl, false); + tx_act_frm->channel = wl->afx_hdl->peer_chan; + wl->afx_hdl->ack_recv = (wl_cfgp2p_tx_action_frame(wl, dev, + tx_act_frm, wl->afx_hdl->bssidx)) ? false : true; + } + return 0; +} +static void +wl_cfg80211_afx_handler(struct work_struct *work) +{ + + struct afx_hdl *afx_instance; + struct wl_priv *wl = wlcfg_drv_priv; + afx_instance = container_of(work, struct afx_hdl, work); + if (afx_instance != NULL) { + wl_cfgp2p_act_frm_search(wl, wl->afx_hdl->dev, + wl->afx_hdl->bssidx, 0); + } +} + +static bool +wl_cfg80211_send_at_common_channel(struct wl_priv *wl, + struct net_device *dev, + wl_af_params_t *af_params) +{ + WL_DBG((" enter ) \n")); + /* initialize afx_hdl */ + wl->afx_hdl->pending_tx_act_frm = af_params; + wl->afx_hdl->bssidx = wl_cfgp2p_find_idx(wl, dev); + wl->afx_hdl->dev = dev; + wl->afx_hdl->retry = 0; + wl->afx_hdl->peer_chan = WL_INVALID; + wl->afx_hdl->ack_recv = false; + memcpy(wl->afx_hdl->pending_tx_dst_addr.octet, + af_params->action_frame.da.octet, + sizeof(wl->afx_hdl->pending_tx_dst_addr.octet)); + /* Loop to wait until we have sent the pending tx action frame or the + * pending action frame tx is cancelled. + */ + while ((wl->afx_hdl->retry < WL_CHANNEL_SYNC_RETRY) && + (wl->afx_hdl->peer_chan == WL_INVALID)) { + wl_set_drv_status(wl, SENDING_ACT_FRM, dev); + wl_set_drv_status(wl, SCANNING, dev); + WL_DBG(("Scheduling the action frame for sending.. retry %d\n", + wl->afx_hdl->retry)); + /* Do find_peer_for_action */ + schedule_work(&wl->afx_hdl->work); + wait_for_completion(&wl->act_frm_scan); + wl->afx_hdl->retry++; + } + if (wl->afx_hdl->peer_chan != WL_INVALID) + wl_cfg80211_send_pending_tx_act_frm(wl); + else { + WL_ERR(("Couldn't find the peer after %d retries\n", + wl->afx_hdl->retry)); + } + wl->afx_hdl->dev = NULL; + wl->afx_hdl->bssidx = WL_INVALID; + wl_clr_drv_status(wl, SENDING_ACT_FRM, dev); + if (wl->afx_hdl->ack_recv) + return true; /* ACK */ + else + return false; /* NO ACK */ +} + static s32 wl_cfg80211_mgmt_tx(struct wiphy *wiphy, struct net_device *ndev, struct ieee80211_channel *channel, bool offchan, @@ -3314,29 +3312,28 @@ wl_cfg80211_mgmt_tx(struct wiphy *wiphy, struct net_device *ndev, bool channel_type_valid, unsigned int wait, const u8* buf, size_t len, u64 *cookie) { + struct ether_addr primary_mac; wl_action_frame_t *action_frame; wl_af_params_t *af_params; wifi_p2p_ie_t *p2p_ie; wpa_ie_fixed_t *wps_ie; + scb_val_t scb_val; const struct ieee80211_mgmt *mgmt; struct wl_priv *wl = wiphy_priv(wiphy); struct net_device *dev = NULL; - dhd_pub_t *dhd = (dhd_pub_t *)(wl->pub); s32 err = BCME_OK; s32 bssidx = 0; u32 p2pie_len = 0; u32 wpsie_len = 0; - u16 fc; + u32 id; + u32 retry = 0; bool ack = false; wifi_p2p_pub_act_frame_t *act_frm; + s8 eabuf[ETHER_ADDR_STR_LEN]; WL_DBG(("Enter \n")); if (ndev == wl->p2p_net) { - /* Firmware doesn't have an ifidx corresponding to p2p0 interface. - * so divert commands received on p2p0 to wlan0. Note that the TX status - * will be sent back to the interface(ndev) on which request is received - */ dev = wl_to_prmry_ndev(wl); } else { /* If TX req is for any valid ifidx. Use as is */ @@ -3345,16 +3342,14 @@ wl_cfg80211_mgmt_tx(struct wiphy *wiphy, struct net_device *ndev, /* find bssidx based on ndev */ bssidx = wl_cfgp2p_find_idx(wl, dev); - /* cookie generation */ - *cookie = (unsigned long) buf; - if (bssidx == -1) { WL_ERR(("Can not find the bssidx for dev( %p )\n", dev)); return -ENODEV; } if (p2p_is_on(wl)) { - wl_cfgp2p_generate_bss_mac(&dhd->mac, &wl->p2p->dev_addr, &wl->p2p->int_addr); + get_primary_mac(wl, &primary_mac); + wl_cfgp2p_generate_bss_mac(&primary_mac, &wl->p2p->dev_addr, &wl->p2p->int_addr); /* Suspend P2P discovery search-listen to prevent it from changing the * channel. */ @@ -3363,11 +3358,14 @@ wl_cfg80211_mgmt_tx(struct wiphy *wiphy, struct net_device *ndev, return -EFAULT; } } - - mgmt = (const struct ieee80211_mgmt *) buf; - fc = mgmt->frame_control; - if (fc != IEEE80211_STYPE_ACTION) { - if (fc == IEEE80211_STYPE_PROBE_RESP) { + *cookie = 0; + id = wl->send_action_id++; + if (id == 0) + id = wl->send_action_id++; + *cookie = id; + mgmt = (const struct ieee80211_mgmt *)buf; + if (ieee80211_is_mgmt(mgmt->frame_control)) { + if (ieee80211_is_probe_resp(mgmt->frame_control)) { s32 ie_offset = DOT11_MGMT_HDR_LEN + DOT11_BCN_PRB_FIXED_LEN; s32 ie_len = len - ie_offset; if ((p2p_ie = wl_cfgp2p_find_p2pie((u8 *)(buf + ie_offset), ie_len)) @@ -3380,7 +3378,7 @@ wl_cfg80211_mgmt_tx(struct wiphy *wiphy, struct net_device *ndev, /* Order of Vendor IE is 1) WPS IE + * 2) P2P IE created by supplicant * So, it is ok to find start address of WPS IE - * to save IEs to firmware + * to save IEs */ wpsie_len = wps_ie->length + sizeof(wps_ie->length) + sizeof(wps_ie->tag); @@ -3388,18 +3386,35 @@ wl_cfg80211_mgmt_tx(struct wiphy *wiphy, struct net_device *ndev, VNDR_IE_PRBRSP_FLAG, (u8 *)wps_ie, wpsie_len + p2pie_len); } + cfg80211_mgmt_tx_status(ndev, *cookie, buf, len, true, GFP_KERNEL); + goto exit; + } else if (ieee80211_is_disassoc(mgmt->frame_control) || + ieee80211_is_deauth(mgmt->frame_control)) { + memcpy(scb_val.ea.octet, mgmt->da, ETH_ALEN); + scb_val.val = mgmt->u.disassoc.reason_code; + wldev_ioctl(dev, WLC_SCB_DEAUTHENTICATE_FOR_REASON, &scb_val, + sizeof(scb_val_t), true); + WL_DBG(("Disconnect STA : %s\n", + bcm_ether_ntoa((const struct ether_addr *)mgmt->da, eabuf))); + cfg80211_mgmt_tx_status(ndev, *cookie, buf, len, true, GFP_KERNEL); + goto exit; + + } else if (ieee80211_is_action(mgmt->frame_control)) { + /* Abort the dwell time of any previous off-channel action frame that may + * be still in effect. Sending off-channel action frames relies on the + * driver's scan engine. If a previous off-channel action frame tx is + * still in progress (including the dwell time), then this new action + * frame will not be sent out. + */ + wl_cfg80211_scan_abort(wl, dev); + } - cfg80211_mgmt_tx_status(ndev, *cookie, buf, len, true, GFP_KERNEL); - goto exit; + } else { - /* Abort the dwell time of any previous off-channel action frame that may - * be still in effect. Sending off-channel action frames relies on the - * driver's scan engine. If a previous off-channel action frame tx is - * still in progress (including the dwell time), then this new action - * frame will not be sent out. - */ - wl_cfg80211_scan_abort(wl, dev); + WL_ERR(("Driver only allows MGMT packet type\n")); + goto exit; } + af_params = (wl_af_params_t *) kzalloc(WL_WIFI_AF_PARAMS_SIZE, GFP_KERNEL); if (af_params == NULL) @@ -3411,7 +3426,7 @@ wl_cfg80211_mgmt_tx(struct wiphy *wiphy, struct net_device *ndev, action_frame = &af_params->action_frame; /* Add the packet Id */ - action_frame->packetId = (u32) action_frame; + action_frame->packetId = *cookie; WL_DBG(("action frame %d\n", action_frame->packetId)); /* Add BSSID */ memcpy(&action_frame->da, &mgmt->da[0], ETHER_ADDR_LEN); @@ -3445,23 +3460,47 @@ wl_cfg80211_mgmt_tx(struct wiphy *wiphy, struct net_device *ndev, WL_DBG(("action_frame->len: %d chan %d category %d subtype %d\n", action_frame->len, af_params->channel, act_frm->category, act_frm->subtype)); - if (wl->p2p->vif_created) { - /* - * To make sure to send successfully action frame, we have to turn off mpc - */ - if ((act_frm->subtype == P2P_PAF_GON_REQ)|| - (act_frm->subtype == P2P_PAF_GON_RSP)) { - wldev_iovar_setint(dev, "mpc", 0); - } else if (act_frm->subtype == P2P_PAF_GON_CONF) { - wldev_iovar_setint(dev, "mpc", 1); - } else if (act_frm->subtype == P2P_PAF_DEVDIS_REQ) { + /* + * To make sure to send successfully action frame, we have to turn off mpc + */ + if ((IS_PUB_ACT_FRAME(act_frm->category)) && + ((act_frm->subtype == P2P_PAF_GON_REQ) || + (act_frm->subtype == P2P_PAF_GON_RSP) || + (act_frm->subtype == P2P_PAF_GON_CONF) || + (act_frm->subtype == P2P_PAF_PROVDIS_REQ))) { + wldev_iovar_setint(dev, "mpc", 0); + } + + if (IS_PUB_ACT_FRAME(act_frm->category)) { + if (act_frm->subtype == P2P_PAF_DEVDIS_REQ) { af_params->dwell_time = WL_LONG_DWELL_TIME; + } else if ((act_frm->subtype == P2P_PAF_PROVDIS_REQ) || + (act_frm->subtype == P2P_PAF_PROVDIS_RSP)) { + af_params->dwell_time = WL_MED_DWELL_TIME; + } + } + if (IS_P2P_SOCIAL(af_params->channel) && + (IS_P2P_ACT_REQ(act_frm->category, act_frm->subtype) || + IS_GAS_REQ(act_frm->category, act_frm->action)) && + wl_to_p2p_bss_saved_ie(wl, P2PAPI_BSSCFG_DEVICE).p2p_probe_req_ie_len) { + /* channel offload require P2P IE for Probe request + * otherwise, we will use wl_cfgp2p_tx_action_frame directly. + * channel offload for action request frame + */ + ack = wl_cfg80211_send_at_common_channel(wl, dev, af_params); + } else { + for (retry = 0; retry < WL_CHANNEL_SYNC_RETRY; retry++) { + ack = (wl_cfgp2p_tx_action_frame(wl, dev, af_params, bssidx)) ? + false : true; + if (ack) + break; } } - - ack = (wl_cfgp2p_tx_action_frame(wl, dev, af_params, bssidx)) ? false : true; cfg80211_mgmt_tx_status(ndev, *cookie, buf, len, ack, GFP_KERNEL); - + if (IS_PUB_ACT_FRAME(act_frm->category) && + (act_frm->subtype == P2P_PAF_GON_CONF)) { + wldev_iovar_setint(dev, "mpc", 1); + } kfree(af_params); exit: return err; @@ -3518,9 +3557,6 @@ wl_cfg80211_set_channel(struct wiphy *wiphy, struct net_device *dev, struct wl_priv *wl = wiphy_priv(wiphy); if (wl->p2p_net == dev) { - /* Since there is no ifidx corresponding to p2p0, cmds to - * firmware should be routed through primary I/F - */ dev = wl_to_prmry_ndev(wl); } channel = ieee80211_frequency_to_channel(chan->center_freq); @@ -3539,7 +3575,6 @@ wl_validate_wpa2ie(struct net_device *dev, bcm_tlv_t *wpa2ie, s32 bssidx) s32 len = 0; s32 err = BCME_OK; u16 auth = 0; /* d11 open authentication */ - u16 count; u32 wsec; u32 pval = 0; u32 gval = 0; @@ -3577,7 +3612,7 @@ wl_validate_wpa2ie(struct net_device *dev, bcm_tlv_t *wpa2ie, s32 bssidx) len -= WPA_SUITE_LEN; /* check the unicast cipher */ ucast = (wpa_suite_ucast_t *)&mcast[1]; - count = ltoh16_ua(&ucast->count); + ltoh16_ua(&ucast->count); tmp = ucast->list[0].oui; switch (tmp[DOT11_OUI_LEN]) { case WPA_CIPHER_NONE: @@ -3600,7 +3635,7 @@ wl_validate_wpa2ie(struct net_device *dev, bcm_tlv_t *wpa2ie, s32 bssidx) wsec = (pval | gval | SES_OW_ENABLED); /* check the AKM */ mgmt = (wpa_suite_auth_key_mgmt_t *)&ucast->list[1]; - count = ltoh16_ua(&mgmt->count); + ltoh16_ua(&mgmt->count); tmp = (u8 *)&mgmt->list[0]; switch (tmp[DOT11_OUI_LEN]) { case RSN_AKM_NONE: @@ -3811,9 +3846,6 @@ wl_cfg80211_add_set_beacon(struct wiphy *wiphy, struct net_device *dev, info->interval, info->dtim_period, info->head_len, info->tail_len)); if (wl->p2p_net == dev) { - /* Since there is no ifidx corresponding to p2p0, cmds to - * firmware should be routed through primary I/F - */ dev = wl_to_prmry_ndev(wl); } @@ -3862,7 +3894,7 @@ wl_cfg80211_add_set_beacon(struct wiphy *wiphy, struct net_device *dev, WL_ERR(("No P2PIE in beacon \n")); } /* add WLC_E_PROBREQ_MSG event to respose probe_request from STA */ - wl_dongle_add_remove_eventmsg(dev, WLC_E_PROBREQ_MSG, pbc); + wl_add_remove_eventmsg(dev, WLC_E_PROBREQ_MSG, pbc); wl_cfgp2p_set_management_ie(wl, dev, bssidx, VNDR_IE_BEACON_FLAG, beacon_ie, wpsie_len + p2pie_len); @@ -3885,12 +3917,13 @@ wl_cfg80211_add_set_beacon(struct wiphy *wiphy, struct net_device *dev, goto exit; } err = wldev_iovar_setbuf_bsscfg(dev, "ssid", &wl->p2p->ssid, - sizeof(wl->p2p->ssid), ioctlbuf, sizeof(ioctlbuf), bssidx); + sizeof(wl->p2p->ssid), wl->ioctl_buf, WLC_IOCTL_MAXLEN, + bssidx, &wl->ioctl_buf_sync); if (err < 0) { WL_ERR(("GO SSID setting error %d\n", err)); goto exit; } - if ((err = wl_cfgp2p_bss(dev, bssidx, 1)) < 0) { + if ((err = wl_cfgp2p_bss(wl, dev, bssidx, 1)) < 0) { WL_ERR(("GO Bring up error %d\n", err)); goto exit; } @@ -3970,7 +4003,7 @@ wl_cfg80211_add_set_beacon(struct wiphy *wiphy, struct net_device *dev, beacon_ie, wpsie_len); wl->ap_info->wps_ie = kmemdup(wps_ie, wpsie_len, GFP_KERNEL); /* add WLC_E_PROBREQ_MSG event to respose probe_request from STA */ - wl_dongle_add_remove_eventmsg(dev, WLC_E_PROBREQ_MSG, pbc); + wl_add_remove_eventmsg(dev, WLC_E_PROBREQ_MSG, pbc); } else { WL_DBG(("No WPSIE in beacon \n")); } @@ -4023,12 +4056,12 @@ wl_cfg80211_add_set_beacon(struct wiphy *wiphy, struct net_device *dev, kfree(wl->ap_info->wps_ie); wl->ap_info->wps_ie = kmemdup(wps_ie, wpsie_len, GFP_KERNEL); /* add WLC_E_PROBREQ_MSG event to respose probe_request from STA */ - wl_dongle_add_remove_eventmsg(dev, WLC_E_PROBREQ_MSG, pbc); + wl_add_remove_eventmsg(dev, WLC_E_PROBREQ_MSG, pbc); } else if (wl->ap_info->wps_ie == NULL) { WL_DBG((" WPS IE is added\n")); wl->ap_info->wps_ie = kmemdup(wps_ie, wpsie_len, GFP_KERNEL); /* add WLC_E_PROBREQ_MSG event to respose probe_request from STA */ - wl_dongle_add_remove_eventmsg(dev, WLC_E_PROBREQ_MSG, pbc); + wl_add_remove_eventmsg(dev, WLC_E_PROBREQ_MSG, pbc); } /* find the RSN_IE */ if ((wpa2_ie = bcm_parse_tlvs((u8 *)info->tail, info->tail_len, @@ -4094,12 +4127,12 @@ wl_cfg80211_add_set_beacon(struct wiphy *wiphy, struct net_device *dev, } if (update_bss) { wl->ap_info->security_mode = true; - wl_cfgp2p_bss(dev, bssidx, 0); + wl_cfgp2p_bss(wl, dev, bssidx, 0); if (wl_validate_wpa2ie(dev, wpa2_ie, bssidx) < 0 || wl_validate_wpaie(dev, wpa_ie, bssidx) < 0) { return BCME_ERROR; } - wl_cfgp2p_bss(dev, bssidx, 1); + wl_cfgp2p_bss(wl, dev, bssidx, 1); } } } else { @@ -4164,21 +4197,15 @@ s32 wl_mode_to_nl80211_iftype(s32 mode) return err; } -static struct wireless_dev *wl_alloc_wdev(struct device *sdiofunc_dev) +static s32 wl_setup_wiphy(struct wireless_dev *wdev, struct device *sdiofunc_dev) { - struct wireless_dev *wdev; s32 err = 0; - wdev = kzalloc(sizeof(*wdev), GFP_KERNEL); - if (unlikely(!wdev)) { - WL_ERR(("Could not allocate wireless device\n")); - return ERR_PTR(-ENOMEM); - } wdev->wiphy = wiphy_new(&wl_cfg80211_ops, sizeof(struct wl_priv)); if (unlikely(!wdev->wiphy)) { WL_ERR(("Couldn not allocate wiphy device\n")); err = -ENOMEM; - goto wiphy_new_out; + return err; } set_wiphy_dev(wdev->wiphy, sdiofunc_dev); wdev->wiphy->max_scan_ie_len = WL_SCAN_IE_LEN_MAX; @@ -4220,30 +4247,28 @@ static struct wireless_dev *wl_alloc_wdev(struct device *sdiofunc_dev) err = wiphy_register(wdev->wiphy); if (unlikely(err < 0)) { WL_ERR(("Couldn not register wiphy device (%d)\n", err)); - goto wiphy_register_out; + wiphy_free(wdev->wiphy); } - return wdev; - -wiphy_register_out: - wiphy_free(wdev->wiphy); - -wiphy_new_out: - kfree(wdev); - - return ERR_PTR(err); + return err; } static void wl_free_wdev(struct wl_priv *wl) { struct wireless_dev *wdev = wl->wdev; + struct wiphy *wiphy; if (!wdev) { WL_ERR(("wdev is invalid\n")); return; } + wiphy = wdev->wiphy; wiphy_unregister(wdev->wiphy); wdev->wiphy->dev.parent = NULL; - wiphy_free(wdev->wiphy); + wl_delete_all_netinfo(wl); + wiphy_free(wiphy); + /* PLEASE do NOT call any function after wiphy_free, the driver's private structure "wl", + * which is the private part of wiphy, has been freed in wiphy_free !!!!!!!!!!! + */ } static s32 wl_inform_bss(struct wl_priv *wl) @@ -4332,6 +4357,21 @@ static s32 wl_inform_single_bss(struct wl_priv *wl, struct wl_bss_info *bi) signal = notif_bss_info->rssi * 100; +#if defined(WLP2P) && ENABLE_P2P_INTERFACE + if (wl->p2p_net && wl->scan_request && wl->scan_request->dev == wl->p2p_net) { +#else + if (p2p_is_on(wl) && p2p_scan(wl)) { +#endif + /* find the P2PIE, if we do not find it, we will discard this frame */ + wifi_p2p_ie_t * p2p_ie; + if ((p2p_ie = wl_cfgp2p_find_p2pie((u8 *)beacon_proberesp->variable, + wl_get_ielen(wl))) == NULL) { + WL_ERR(("Couldn't find P2PIE in probe response/beacon\n")); + kfree(notif_bss_info); + return err; + } + } + cbss = cfg80211_inform_bss_frame(wiphy, channel, mgmt, le16_to_cpu(notif_bss_info->frame_len), signal, GFP_KERNEL); if (unlikely(!cbss)) { @@ -4398,89 +4438,136 @@ static bool wl_is_nonetwork(struct wl_priv *wl, const wl_event_msg_t *e) return false; } +/* The mainline kernel >= 3.2.0 has support for indicating new/del station + * to AP/P2P GO via events. If this change is backported to kernel for which + * this driver is being built, set CFG80211_STA_EVENT_AVAILABLE to 1. You + * should use this new/del sta event mechanism for BRCM supplicant from BRANCH + * HOSTAP_BRANCH_0_15 (ver >= 15_1). + */ +#define CFG80211_STA_EVENT_AVAILABLE 0 static s32 -wl_notify_connect_status(struct wl_priv *wl, struct net_device *ndev, +wl_notify_connect_status_ap(struct wl_priv *wl, struct net_device *ndev, const wl_event_msg_t *e, void *data) { - bool act; - bool isfree = false; s32 err = 0; - s32 freq; - s32 channel; - u8 body[200]; u32 event = ntoh32(e->event_type); u32 reason = ntoh32(e->reason); u32 len = ntoh32(e->datalen); - u16 fc = 0; + +#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 2, 0)) && !CFG80211_STA_EVENT_AVAILABLE + bool isfree = false; u8 *mgmt_frame; u8 bsscfgidx = e->bsscfgidx; + s32 freq; + s32 channel; + u8 body[200]; + u16 fc = 0; struct ieee80211_supported_band *band; struct ether_addr da; struct ether_addr bssid; struct wiphy *wiphy = wl_to_wiphy(wl); channel_info_t ci; +#else + struct station_info sinfo; +#endif /* (LINUX_VERSION_CODE < KERNEL_VERSION(3, 2, 0)) && !CFG80211_STA_EVENT_AVAILABLE */ + +#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 2, 0)) && !CFG80211_STA_EVENT_AVAILABLE memset(body, 0, sizeof(body)); memset(&bssid, 0, ETHER_ADDR_LEN); WL_DBG(("Enter \n")); if (wl_get_mode_by_netdev(wl, ndev) == WL_INVALID) return WL_INVALID; - if (wl_get_mode_by_netdev(wl, ndev) == WL_MODE_AP) { - memcpy(body, data, len); - wldev_iovar_getbuf_bsscfg(ndev, "cur_etheraddr", - NULL, 0, ioctlbuf, sizeof(ioctlbuf), bsscfgidx); - memcpy(da.octet, ioctlbuf, ETHER_ADDR_LEN); - err = wldev_ioctl(ndev, WLC_GET_BSSID, &bssid, ETHER_ADDR_LEN, false); - switch (event) { - case WLC_E_ASSOC_IND: - fc = FC_ASSOC_REQ; - break; - case WLC_E_REASSOC_IND: - fc = FC_REASSOC_REQ; - break; - case WLC_E_DISASSOC_IND: - fc = FC_DISASSOC; - break; - case WLC_E_DEAUTH_IND: - fc = FC_DISASSOC; - break; - case WLC_E_DEAUTH: - fc = FC_DISASSOC; - break; - default: - fc = 0; - goto exit; - } - if ((err = wldev_ioctl(ndev, WLC_GET_CHANNEL, &ci, sizeof(ci), false))) - return err; + memcpy(body, data, len); + wldev_iovar_getbuf_bsscfg(ndev, "cur_etheraddr", + NULL, 0, wl->ioctl_buf, WLC_IOCTL_MAXLEN, bsscfgidx, &wl->ioctl_buf_sync); + memcpy(da.octet, wl->ioctl_buf, ETHER_ADDR_LEN); + err = wldev_ioctl(ndev, WLC_GET_BSSID, &bssid, ETHER_ADDR_LEN, false); + switch (event) { + case WLC_E_ASSOC_IND: + fc = FC_ASSOC_REQ; + break; + case WLC_E_REASSOC_IND: + fc = FC_REASSOC_REQ; + break; + case WLC_E_DISASSOC_IND: + fc = FC_DISASSOC; + break; + case WLC_E_DEAUTH_IND: + fc = FC_DISASSOC; + break; + case WLC_E_DEAUTH: + fc = FC_DISASSOC; + break; + default: + fc = 0; + goto exit; + } + if ((err = wldev_ioctl(ndev, WLC_GET_CHANNEL, &ci, sizeof(ci), false))) + return err; - channel = dtoh32(ci.hw_channel); - if (channel <= CH_MAX_2G_CHANNEL) - band = wiphy->bands[IEEE80211_BAND_2GHZ]; - else - band = wiphy->bands[IEEE80211_BAND_5GHZ]; + channel = dtoh32(ci.hw_channel); + if (channel <= CH_MAX_2G_CHANNEL) + band = wiphy->bands[IEEE80211_BAND_2GHZ]; + else + band = wiphy->bands[IEEE80211_BAND_5GHZ]; #if LINUX_VERSION_CODE == KERNEL_VERSION(2, 6, 38) && !defined(WL_COMPAT_WIRELESS) - freq = ieee80211_channel_to_frequency(channel); + freq = ieee80211_channel_to_frequency(channel); #else - freq = ieee80211_channel_to_frequency(channel, band->band); + freq = ieee80211_channel_to_frequency(channel, band->band); #endif - err = wl_frame_get_mgmt(fc, &da, &e->addr, &bssid, + err = wl_frame_get_mgmt(fc, &da, &e->addr, &bssid, &mgmt_frame, &len, body); - if (err < 0) - goto exit; - isfree = true; + if (err < 0) + goto exit; + isfree = true; - if (event == WLC_E_ASSOC_IND && reason == DOT11_SC_SUCCESS) { - cfg80211_rx_mgmt(ndev, freq, mgmt_frame, len, GFP_ATOMIC); - } else if (event == WLC_E_DISASSOC_IND) { - cfg80211_rx_mgmt(ndev, freq, mgmt_frame, len, GFP_ATOMIC); - } else if ((event == WLC_E_DEAUTH_IND) || (event == WLC_E_DEAUTH)) { - cfg80211_rx_mgmt(ndev, freq, mgmt_frame, len, GFP_ATOMIC); + if (event == WLC_E_ASSOC_IND && reason == DOT11_SC_SUCCESS) { + cfg80211_rx_mgmt(ndev, freq, mgmt_frame, len, GFP_ATOMIC); + } else if (event == WLC_E_DISASSOC_IND) { + cfg80211_rx_mgmt(ndev, freq, mgmt_frame, len, GFP_ATOMIC); + } else if ((event == WLC_E_DEAUTH_IND) || (event == WLC_E_DEAUTH)) { + cfg80211_rx_mgmt(ndev, freq, mgmt_frame, len, GFP_ATOMIC); + } + +exit: + if (isfree) + kfree(mgmt_frame); + return err; +#else /* LINUX_VERSION_CODE < KERNEL_VERSION(3, 2, 0) && !CFG80211_STA_EVENT_AVAILABLE */ + sinfo.filled = 0; + if (((event == WLC_E_ASSOC_IND) || (event == WLC_E_REASSOC_IND)) && + reason == DOT11_SC_SUCCESS) { + sinfo.filled = STATION_INFO_ASSOC_REQ_IES; + if (!data) { + WL_ERR(("No IEs present in ASSOC/REASSOC_IND")); + return -EINVAL; } + sinfo.assoc_req_ies = data; + sinfo.assoc_req_ies_len = len; + cfg80211_new_sta(ndev, e->addr.octet, &sinfo, GFP_ATOMIC); + } else if (event == WLC_E_DISASSOC_IND) { + cfg80211_del_sta(ndev, e->addr.octet, GFP_ATOMIC); + } else if ((event == WLC_E_DEAUTH_IND) || (event == WLC_E_DEAUTH)) { + cfg80211_del_sta(ndev, e->addr.octet, GFP_ATOMIC); + } +#endif /* LINUX_VERSION_CODE < KERNEL_VERSION(3, 2, 0) && !CFG80211_STA_EVENT_AVAILABLE */ + return err; +} + +static s32 +wl_notify_connect_status(struct wl_priv *wl, struct net_device *ndev, + const wl_event_msg_t *e, void *data) +{ + bool act; + s32 err = 0; + u32 event = ntoh32(e->event_type); + if (wl_get_mode_by_netdev(wl, ndev) == WL_MODE_AP) { + wl_notify_connect_status_ap(wl, ndev, e, data); } else { WL_DBG(("wl_notify_connect_status : event %d status : %d \n", ntoh32(e->event_type), ntoh32(e->status))); @@ -4552,9 +4639,6 @@ wl_notify_connect_status(struct wl_priv *wl, struct net_device *ndev, printk("%s nothing\n", __FUNCTION__); } } -exit: - if (isfree) - kfree(mgmt_frame); return err; } @@ -4579,48 +4663,15 @@ wl_notify_roaming_status(struct wl_priv *wl, struct net_device *ndev, return err; } -static __used s32 -wl_dev_bufvar_set(struct net_device *dev, s8 *name, s8 *buf, s32 len) -{ - struct wl_priv *wl = wlcfg_drv_priv; - u32 buflen; - - buflen = bcm_mkiovar(name, buf, len, wl->ioctl_buf, WL_IOCTL_LEN_MAX); - BUG_ON(unlikely(!buflen)); - - return wldev_ioctl(dev, WLC_SET_VAR, wl->ioctl_buf, buflen, true); -} - -static s32 -wl_dev_bufvar_get(struct net_device *dev, s8 *name, s8 *buf, - s32 buf_len) +static s32 wl_get_assoc_ies(struct wl_priv *wl, struct net_device *ndev) { - struct wl_priv *wl = wlcfg_drv_priv; - u32 len; - s32 err = 0; - - len = bcm_mkiovar(name, NULL, 0, wl->ioctl_buf, WL_IOCTL_LEN_MAX); - BUG_ON(unlikely(!len)); - err = wldev_ioctl(dev, WLC_GET_VAR, (void *)wl->ioctl_buf, - WL_IOCTL_LEN_MAX, false); - if (unlikely(err)) { - WL_ERR(("error (%d)\n", err)); - return err; - } - memcpy(buf, wl->ioctl_buf, buf_len); - - return err; -} - -static s32 wl_get_assoc_ies(struct wl_priv *wl, struct net_device *ndev) -{ - wl_assoc_info_t assoc_info; - struct wl_connect_info *conn_info = wl_to_conn(wl); + wl_assoc_info_t assoc_info; + struct wl_connect_info *conn_info = wl_to_conn(wl); s32 err = 0; WL_DBG(("Enter \n")); - err = wl_dev_bufvar_get(ndev, "assoc_info", wl->extra_buf, - WL_ASSOC_INFO_MAX); + err = wldev_iovar_getbuf(ndev, "assoc_info", NULL, 0, wl->extra_buf, + WL_ASSOC_INFO_MAX, NULL); if (unlikely(err)) { WL_ERR(("could not get assoc info (%d)\n", err)); return err; @@ -4638,8 +4689,8 @@ static s32 wl_get_assoc_ies(struct wl_priv *wl, struct net_device *ndev) bzero(conn_info->resp_ie, sizeof(conn_info->resp_ie)); } if (assoc_info.req_len) { - err = wl_dev_bufvar_get(ndev, "assoc_req_ies", wl->extra_buf, - WL_ASSOC_INFO_MAX); + err = wldev_iovar_getbuf(ndev, "assoc_req_ies", NULL, 0, wl->extra_buf, + WL_ASSOC_INFO_MAX, NULL); if (unlikely(err)) { WL_ERR(("could not get assoc req (%d)\n", err)); return err; @@ -4659,8 +4710,8 @@ static s32 wl_get_assoc_ies(struct wl_priv *wl, struct net_device *ndev) conn_info->req_ie_len = 0; } if (assoc_info.resp_len) { - err = wl_dev_bufvar_get(ndev, "assoc_resp_ies", wl->extra_buf, - WL_ASSOC_INFO_MAX); + err = wldev_iovar_getbuf(ndev, "assoc_resp_ies", NULL, 0, wl->extra_buf, + WL_ASSOC_INFO_MAX, NULL); if (unlikely(err)) { WL_ERR(("could not get assoc resp (%d)\n", err)); return err; @@ -4722,8 +4773,8 @@ static s32 wl_update_bss_info(struct wl_priv *wl, struct net_device *ndev) struct wl_bss_info *bi; struct wlc_ssid *ssid; struct bcm_tlv *tim; - u16 beacon_interval; - u8 dtim_period; + s32 beacon_interval; + s32 dtim_period; size_t ie_len; u8 *ie; u8 *curbssid; @@ -4777,7 +4828,7 @@ static s32 wl_update_bss_info(struct wl_priv *wl, struct net_device *ndev) /* * active scan was done so we could not get dtim * information out of probe response. - * so we speficially query dtim information to dongle. + * so we speficially query dtim information. */ err = wldev_ioctl(ndev, WLC_GET_DTIMPRD, &dtim_period, sizeof(dtim_period), false); @@ -4829,6 +4880,7 @@ wl_bss_connect_done(struct wl_priv *wl, struct net_device *ndev, struct wl_connect_info *conn_info = wl_to_conn(wl); s32 err = 0; u8 *curbssid = wl_read_prof(wl, ndev, WL_PROF_BSSID); + WL_DBG((" enter\n")); if (wl->scan_request) { wl_cfg80211_scan_abort(wl, ndev); @@ -4942,13 +4994,13 @@ wl_notify_scan_status(struct wl_priv *wl, struct net_device *ndev, scan_done_out: del_timer_sync(&wl->scan_timeout); - flags = dhd_os_spin_lock((dhd_pub_t *)(wl->pub)); + spin_lock_irqsave(&wl->cfgdrv_lock, flags); if (wl->scan_request) { WL_DBG(("cfg80211_scan_done\n")); cfg80211_scan_done(wl->scan_request, false); wl->scan_request = NULL; } - dhd_os_spin_unlock((dhd_pub_t *)(wl->pub), flags); + spin_unlock_irqrestore(&wl->cfgdrv_lock, flags); mutex_unlock(&wl->usr_sync); return err; } @@ -5017,9 +5069,6 @@ wl_notify_rx_mgmt_frame(struct wl_priv *wl, struct net_device *ndev, memset(&bssid, 0, ETHER_ADDR_LEN); if (wl->p2p_net == ndev) { - /* Since there is no ifidx corresponding to p2p0, cmds to - * firmware should be routed through primary I/F - */ dev = wl_to_prmry_ndev(wl); } else { dev = ndev; @@ -5037,10 +5086,10 @@ wl_notify_rx_mgmt_frame(struct wl_priv *wl, struct net_device *ndev, #endif if (event == WLC_E_ACTION_FRAME_RX) { wldev_iovar_getbuf_bsscfg(dev, "cur_etheraddr", - NULL, 0, ioctlbuf, sizeof(ioctlbuf), bsscfgidx); + NULL, 0, wl->ioctl_buf, WLC_IOCTL_MAXLEN, bsscfgidx, &wl->ioctl_buf_sync); wldev_ioctl(dev, WLC_GET_BSSID, &bssid, ETHER_ADDR_LEN, false); - memcpy(da.octet, ioctlbuf, ETHER_ADDR_LEN); + memcpy(da.octet, wl->ioctl_buf, ETHER_ADDR_LEN); err = wl_frame_get_mgmt(FC_ACTION, &da, &e->addr, &bssid, &mgmt_frame, &mgmt_frame_len, (u8 *)((wl_event_rx_frame_data_t *)rxframe + 1)); @@ -5055,9 +5104,18 @@ wl_notify_rx_mgmt_frame(struct wl_priv *wl, struct net_device *ndev, /* * After complete GO Negotiation, roll back to mpc mode */ - if (act_frm->subtype == P2P_PAF_GON_CONF) { + if (IS_PUB_ACT_FRAME(act_frm->category) && + ((act_frm->subtype == P2P_PAF_GON_CONF)|| + (act_frm->subtype == P2P_PAF_PROVDIS_RSP))) { wldev_iovar_setint(dev, "mpc", 1); } + + if (IS_P2P_ACT_FRAME(act_frm->category) && + (act_frm->subtype == P2P_AF_PRESENCE_REQ)) { + /* TODO Do not submit these frames to supplicant, + * we will handle it in the driver + */ + } } else { mgmt_frame = (u8 *)((wl_event_rx_frame_data_t *)rxframe + 1); } @@ -5087,9 +5145,10 @@ static void wl_init_prof(struct wl_priv *wl, struct net_device *ndev) { unsigned long flags; struct wl_profile *profile = wl_get_profile_by_netdev(wl, ndev); - flags = dhd_os_spin_lock((dhd_pub_t *)(wl->pub)); + + spin_lock_irqsave(&wl->cfgdrv_lock, flags); memset(profile, 0, sizeof(struct wl_profile)); - dhd_os_spin_unlock((dhd_pub_t *)(wl->pub), flags); + spin_unlock_irqrestore(&wl->cfgdrv_lock, flags); } static void wl_init_event_handler(struct wl_priv *wl) @@ -5134,7 +5193,7 @@ static s32 wl_init_priv_mem(struct wl_priv *wl) WL_ERR(("Scan req alloc failed\n")); goto init_priv_mem_out; } - wl->ioctl_buf = (void *)kzalloc(WL_IOCTL_LEN_MAX, GFP_KERNEL); + wl->ioctl_buf = (void *)kzalloc(WLC_IOCTL_MAXLEN, GFP_KERNEL); if (unlikely(!wl->ioctl_buf)) { WL_ERR(("Ioctl buf alloc failed\n")); goto init_priv_mem_out; @@ -5154,11 +5213,6 @@ static s32 wl_init_priv_mem(struct wl_priv *wl) WL_ERR(("Iscan buf alloc failed\n")); goto init_priv_mem_out; } - wl->fw = (void *)kzalloc(sizeof(*wl->fw), GFP_KERNEL); - if (unlikely(!wl->fw)) { - WL_ERR(("fw object alloc failed\n")); - goto init_priv_mem_out; - } wl->pmk_list = (void *)kzalloc(sizeof(*wl->pmk_list), GFP_KERNEL); if (unlikely(!wl->pmk_list)) { WL_ERR(("pmk list alloc failed\n")); @@ -5169,6 +5223,14 @@ static s32 wl_init_priv_mem(struct wl_priv *wl) WL_ERR(("sta info alloc failed\n")); goto init_priv_mem_out; } + wl->afx_hdl = (void *)kzalloc(sizeof(*wl->afx_hdl), GFP_KERNEL); + if (unlikely(!wl->afx_hdl)) { + WL_ERR(("afx hdl alloc failed\n")); + goto init_priv_mem_out; + } else { + init_completion(&wl->act_frm_scan); + INIT_WORK(&wl->afx_hdl->work, wl_cfg80211_afx_handler); + } return 0; init_priv_mem_out: @@ -5193,12 +5255,16 @@ static void wl_deinit_priv_mem(struct wl_priv *wl) wl->extra_buf = NULL; kfree(wl->iscan); wl->iscan = NULL; - kfree(wl->fw); - wl->fw = NULL; kfree(wl->pmk_list); wl->pmk_list = NULL; kfree(wl->sta_info); wl->sta_info = NULL; + if (wl->afx_hdl) { + cancel_work_sync(&wl->afx_hdl->work); + kfree(wl->afx_hdl); + wl->afx_hdl = NULL; + } + if (wl->ap_info) { kfree(wl->ap_info->wpa_ie); kfree(wl->ap_info->rsn_ie); @@ -5213,7 +5279,8 @@ static s32 wl_create_event_handler(struct wl_priv *wl) int ret = 0; WL_DBG(("Enter \n")); - wl->event_tsk.thr_pid = DHD_PID_KT_INVALID; + /* Do not use DHD in cfg driver */ + wl->event_tsk.thr_pid = -1; PROC_START(wl_event_handler, wl, &wl->event_tsk, 0); if (wl->event_tsk.thr_pid < 0) ret = -ENOMEM; @@ -5252,13 +5319,13 @@ static void wl_notify_iscan_complete(struct wl_iscan_ctrl *iscan, bool aborted) WL_ERR(("Scan complete while device not scanning\n")); return; } - flags = dhd_os_spin_lock((dhd_pub_t *)(wl->pub)); + spin_lock_irqsave(&wl->cfgdrv_lock, flags); wl_clr_drv_status(wl, SCANNING, ndev); if (likely(wl->scan_request)) { cfg80211_scan_done(wl->scan_request, aborted); wl->scan_request = NULL; } - dhd_os_spin_unlock((dhd_pub_t *)(wl->pub), flags); + spin_unlock_irqrestore(&wl->cfgdrv_lock, flags); wl->iscan_kickstart = false; } @@ -5294,7 +5361,7 @@ wl_get_iscan_results(struct wl_iscan_ctrl *iscan, u32 *status, list.results.buflen = htod32(WL_ISCAN_BUF_MAX); err = wldev_iovar_getbuf(iscan->dev, "iscanresults", &list, WL_ISCAN_RESULTS_FIXED_SIZE, iscan->scan_buf, - WL_ISCAN_BUF_MAX); + WL_ISCAN_BUF_MAX, NULL); if (unlikely(err)) { WL_ERR(("error (%d)\n", err)); return err; @@ -5367,13 +5434,11 @@ static s32 wl_iscan_aborted(struct wl_priv *wl) static s32 wl_iscan_thread(void *data) { - struct sched_param param = {.sched_priority = MAX_RT_PRIO - 1 }; struct wl_iscan_ctrl *iscan = (struct wl_iscan_ctrl *)data; struct wl_priv *wl = iscan_to_wl(iscan); u32 status; int err = 0; - sched_setscheduler(current, SCHED_FIFO, ¶m); allow_signal(SIGTERM); status = WL_SCAN_RESULTS_PARTIAL; while (likely(!down_interruptible(&iscan->sync))) { @@ -5489,12 +5554,12 @@ static void wl_notify_escan_complete(struct wl_priv *wl, if (p2p_is_on(wl)) wl_clr_p2p_status(wl, SCANNING); - flags = dhd_os_spin_lock((dhd_pub_t *)(wl->pub)); + spin_lock_irqsave(&wl->cfgdrv_lock, flags); if (likely(wl->scan_request)) { cfg80211_scan_done(wl->scan_request, aborted); wl->scan_request = NULL; } - dhd_os_spin_unlock((dhd_pub_t *)(wl->pub), flags); + spin_unlock_irqrestore(&wl->cfgdrv_lock, flags); } static s32 wl_escan_handler(struct wl_priv *wl, @@ -5509,14 +5574,22 @@ static s32 wl_escan_handler(struct wl_priv *wl, wl_scan_results_t *list; u32 bi_length; u32 i; + u8 *p2p_dev_addr = NULL; + WL_DBG((" enter event type : %d, status : %d \n", ntoh32(e->event_type), ntoh32(e->status))); /* P2P SCAN is coming from primary interface */ - if (wl_get_p2p_status(wl, SCANNING)) - ndev = wl->escan_info.ndev; + if (wl_get_p2p_status(wl, SCANNING)) { + if (wl_get_drv_status_all(wl, SENDING_ACT_FRM)) + ndev = wl->afx_hdl->dev; + else + ndev = wl->escan_info.ndev; + + } if (!ndev || !wl->escan_on || !wl_get_drv_status(wl, SCANNING, ndev)) { - WL_ERR(("escan is not ready \n")); + WL_ERR(("escan is not ready ndev %p wl->escan_on %d drv_status 0x%x\n", + ndev, wl->escan_on, wl_get_drv_status(wl, SCANNING, ndev))); return err; } @@ -5541,47 +5614,69 @@ static s32 wl_escan_handler(struct wl_priv *wl, WL_ERR(("Invalid bss_info length %d: ignoring\n", bi_length)); goto exit; } - list = (wl_scan_results_t *)wl->escan_info.escan_buf; - if (bi_length > ESCAN_BUF_SIZE - list->buflen) { - WL_ERR(("Buffer is too small: ignoring\n")); - goto exit; - } -#define WLC_BSS_RSSI_ON_CHANNEL 0x0002 - for (i = 0; i < list->count; i++) { - bss = bss ? (wl_bss_info_t *)((uintptr)bss + dtoh32(bss->length)) - : list->bss_info; - - if (!bcmp(&bi->BSSID, &bss->BSSID, ETHER_ADDR_LEN) && - CHSPEC_BAND(bi->chanspec) == CHSPEC_BAND(bss->chanspec) && - bi->SSID_len == bss->SSID_len && - !bcmp(bi->SSID, bss->SSID, bi->SSID_len)) { - if ((bss->flags & WLC_BSS_RSSI_ON_CHANNEL) == - (bi->flags & WLC_BSS_RSSI_ON_CHANNEL)) { - /* preserve max RSSI if the measurements are - * both on-channel or both off-channel - */ - bss->RSSI = MAX(bss->RSSI, bi->RSSI); - } else if ((bss->flags & WLC_BSS_RSSI_ON_CHANNEL) && - (bi->flags & WLC_BSS_RSSI_ON_CHANNEL) == 0) { - /* preserve the on-channel rssi measurement - * if the new measurement is off channel - */ - bss->RSSI = bi->RSSI; - bss->flags |= WLC_BSS_RSSI_ON_CHANNEL; - } + if (wl_get_drv_status_all(wl, SENDING_ACT_FRM)) { + p2p_dev_addr = wl_cfgp2p_retreive_p2p_dev_addr(bi, bi_length); + if (p2p_dev_addr && !memcmp(p2p_dev_addr, + wl->afx_hdl->pending_tx_dst_addr.octet, ETHER_ADDR_LEN)) { + s32 channel = CHSPEC_CHANNEL(dtohchanspec(bi->chanspec)); + WL_DBG(("ACTION FRAME SCAN : Peer found, channel : %d\n", channel)); + wl_clr_p2p_status(wl, SCANNING); + wl->afx_hdl->peer_chan = channel; + complete(&wl->act_frm_scan); goto exit; } + + } else { + list = (wl_scan_results_t *)wl->escan_info.escan_buf; + if (bi_length > ESCAN_BUF_SIZE - list->buflen) { + WL_ERR(("Buffer is too small: ignoring\n")); + goto exit; + } +#define WLC_BSS_RSSI_ON_CHANNEL 0x0002 + for (i = 0; i < list->count; i++) { + bss = bss ? (wl_bss_info_t *)((uintptr)bss + dtoh32(bss->length)) + : list->bss_info; + + if (!bcmp(&bi->BSSID, &bss->BSSID, ETHER_ADDR_LEN) && + CHSPEC_BAND(bi->chanspec) == CHSPEC_BAND(bss->chanspec) && + bi->SSID_len == bss->SSID_len && + !bcmp(bi->SSID, bss->SSID, bi->SSID_len)) { + if ((bss->flags & WLC_BSS_RSSI_ON_CHANNEL) == + (bi->flags & WLC_BSS_RSSI_ON_CHANNEL)) { + /* preserve max RSSI if the measurements are + * both on-channel or both off-channel + */ + bss->RSSI = MAX(bss->RSSI, bi->RSSI); + } else if ((bss->flags & WLC_BSS_RSSI_ON_CHANNEL) && + (bi->flags & WLC_BSS_RSSI_ON_CHANNEL) == 0) { + /* preserve the on-channel rssi measurement + * if the new measurement is off channel + */ + bss->RSSI = bi->RSSI; + bss->flags |= WLC_BSS_RSSI_ON_CHANNEL; + } + + goto exit; + } + } + memcpy(&(wl->escan_info.escan_buf[list->buflen]), bi, bi_length); + list->version = dtoh32(bi->version); + list->buflen += bi_length; + list->count++; + } - memcpy(&(wl->escan_info.escan_buf[list->buflen]), bi, bi_length); - list->version = dtoh32(bi->version); - list->buflen += bi_length; - list->count++; } else if (status == WLC_E_STATUS_SUCCESS) { wl->escan_info.escan_state = WL_ESCAN_STATE_IDLE; - if (likely(wl->scan_request)) { + if (wl_get_drv_status_all(wl, SENDING_ACT_FRM)) { + WL_INFO(("ACTION FRAME SCAN DONE\n")); + wl_clr_p2p_status(wl, SCANNING); + wl_clr_drv_status(wl, SCANNING, wl->afx_hdl->dev); + if (wl->afx_hdl->peer_chan == WL_INVALID) + complete(&wl->act_frm_scan); + } else if (likely(wl->scan_request)) { mutex_lock(&wl->usr_sync); del_timer_sync(&wl->scan_timeout); WL_INFO(("ESCAN COMPLETED\n")); @@ -5593,7 +5688,13 @@ static s32 wl_escan_handler(struct wl_priv *wl, } else if (status == WLC_E_STATUS_ABORT) { wl->escan_info.escan_state = WL_ESCAN_STATE_IDLE; - if (likely(wl->scan_request)) { + if (wl_get_drv_status_all(wl, SENDING_ACT_FRM)) { + WL_INFO(("ACTION FRAME SCAN DONE\n")); + wl_clr_drv_status(wl, SCANNING, wl->afx_hdl->dev); + wl_clr_p2p_status(wl, SCANNING); + if (wl->afx_hdl->peer_chan == WL_INVALID) + complete(&wl->act_frm_scan); + } else if (likely(wl->scan_request)) { mutex_lock(&wl->usr_sync); del_timer_sync(&wl->scan_timeout); WL_INFO(("ESCAN ABORTED\n")); @@ -5606,7 +5707,13 @@ static s32 wl_escan_handler(struct wl_priv *wl, else { WL_ERR(("unexpected Escan Event %d : abort\n", status)); wl->escan_info.escan_state = WL_ESCAN_STATE_IDLE; - if (likely(wl->scan_request)) { + if (wl_get_drv_status_all(wl, SENDING_ACT_FRM)) { + WL_INFO(("ACTION FRAME SCAN DONE\n")); + wl_clr_p2p_status(wl, SCANNING); + wl_clr_drv_status(wl, SCANNING, wl->afx_hdl->dev); + if (wl->afx_hdl->peer_chan == WL_INVALID) + complete(&wl->act_frm_scan); + } else if (likely(wl->scan_request)) { mutex_lock(&wl->usr_sync); del_timer_sync(&wl->scan_timeout); wl->bss_list = (wl_scan_results_t *)wl->escan_info.escan_buf; @@ -5652,16 +5759,12 @@ static s32 wl_init_scan(struct wl_priv *wl) return err; } -static void wl_init_fw(struct wl_fw_ctrl *fw) -{ - fw->status = 0; -} - static s32 wl_init_priv(struct wl_priv *wl) { struct wiphy *wiphy = wl_to_wiphy(wl); struct net_device *ndev = wl_to_prmry_ndev(wl); s32 err = 0; + wl->scan_request = NULL; wl->pwr_save = !!(wiphy->flags & WIPHY_FLAG_PS_ON_BY_DEFAULT); wl->iscan_on = false; @@ -5669,10 +5772,10 @@ static s32 wl_init_priv(struct wl_priv *wl) wl->roam_on = false; wl->iscan_kickstart = false; wl->active_scan = true; - wl->dongle_up = false; wl->rf_blocked = false; - - init_waitqueue_head(&wl->dongle_event_wait); + spin_lock_init(&wl->cfgdrv_lock); + mutex_init(&wl->ioctl_buf_sync); + init_waitqueue_head(&wl->netif_change_event); wl_init_eq(wl); err = wl_init_priv_mem(wl); if (err) @@ -5684,18 +5787,18 @@ static s32 wl_init_priv(struct wl_priv *wl) err = wl_init_scan(wl); if (err) return err; - wl_init_fw(wl->fw); wl_init_conf(wl->conf); wl_init_prof(wl, ndev); wl_link_down(wl); + DNGL_FUNC(dhd_cfg80211_init, (wl)); return err; } static void wl_deinit_priv(struct wl_priv *wl) { + DNGL_FUNC(dhd_cfg80211_deinit, (wl)); wl_destroy_event_handler(wl); - wl->dongle_up = false; /* dongle down */ wl_flush_eq(wl); wl_link_down(wl); del_timer_sync(&wl->scan_timeout); @@ -5724,7 +5827,7 @@ static s32 wl_cfg80211_detach_p2p(void) struct wl_priv *wl = wlcfg_drv_priv; struct wireless_dev *wdev = wl->p2p_wdev; - WL_TRACE(("Enter \n")); + WL_DBG(("Enter \n")); if (!wdev || !wl) { WL_ERR(("Invalid Ptr\n")); return -EINVAL; @@ -5734,7 +5837,7 @@ static s32 wl_cfg80211_detach_p2p(void) wl->p2p_wdev = NULL; wl->p2p_net = NULL; - + WL_DBG(("Freeing 0x%08x \n", (unsigned int)wdev)); kfree(wdev); return 0; @@ -5754,9 +5857,11 @@ s32 wl_cfg80211_attach_post(struct net_device *ndev) if (wl && !wl_get_drv_status(wl, READY, ndev)) { if (wl->wdev && wl_cfgp2p_supported(wl, ndev)) { +#if !ENABLE_P2P_INTERFACE wl->wdev->wiphy->interface_modes |= (BIT(NL80211_IFTYPE_P2P_CLIENT)| BIT(NL80211_IFTYPE_P2P_GO)); +#endif if ((err = wl_cfgp2p_init_priv(wl)) != 0) goto fail; @@ -5797,10 +5902,17 @@ s32 wl_cfg80211_attach(struct net_device *ndev, void *data) } WL_DBG(("func %p\n", wl_cfg80211_get_parent_dev())); dev = wl_cfg80211_get_parent_dev(); - wdev = wl_alloc_wdev(dev); - if (IS_ERR(wdev)) - return -ENOMEM; + wdev = kzalloc(sizeof(*wdev), GFP_KERNEL); + if (unlikely(!wdev)) { + WL_ERR(("Could not allocate wireless device\n")); + return -ENOMEM; + } + err = wl_setup_wiphy(wdev, dev); + if (unlikely(err)) { + kfree(wdev); + return -ENOMEM; + } wdev->iftype = wl_mode_to_nl80211_iftype(WL_MODE_BSS); wl = (struct wl_priv *)wiphy_priv(wdev->wiphy); wl->wdev = wdev; @@ -5833,7 +5945,7 @@ s32 wl_cfg80211_attach(struct net_device *ndev, void *data) #if defined(COEX_DHCP) if (wl_cfg80211_btcoex_init(wl)) goto cfg80211_attach_out; -#endif /* COEX_DHCP */ +#endif wlcfg_drv_priv = wl; @@ -5851,7 +5963,7 @@ cfg80211_attach_out: return err; } -void wl_cfg80211_detach(void) +void wl_cfg80211_detach(void *para) { struct wl_priv *wl; @@ -5861,7 +5973,7 @@ void wl_cfg80211_detach(void) #if defined(COEX_DHCP) wl_cfg80211_btcoex_deinit(wl); -#endif /* COEX_DHCP */ +#endif #if defined(WLP2P) && ENABLE_P2P_INTERFACE wl_cfg80211_detach_p2p(); @@ -5873,6 +5985,9 @@ void wl_cfg80211_detach(void) wlcfg_drv_priv = NULL; wl_cfg80211_clear_parent_dev(); wl_free_wdev(wl); + /* PLEASE do NOT call any function after wl_free_wdev, the driver's private structure "wl", + * which is the private part of wiphy, has been freed in wl_free_wdev !!!!!!!!!!! + */ } static void wl_wakeup_event(struct wl_priv *wl) @@ -5935,20 +6050,17 @@ static s32 wl_event_handler(void *data) break; while ((e = wl_deq_event(wl))) { WL_DBG(("event type (%d), if idx: %d\n", e->etype, e->emsg.ifidx)); - /* All P2P device address related events comes on primary interface since - * there is no corresponding interface in the firmware. Map it to p2p0 + * there is no corresponding bsscfg for P2P interface. Map it to p2p0 * interface. */ if ((wl_is_p2p_event(e) == TRUE) && (wl->p2p_net)) { netdev = wl->p2p_net; } else { netdev = dhd_idx2net((struct dhd_pub *)(wl->pub), e->emsg.ifidx); - if (!netdev) { - netdev = wl_to_prmry_ndev(wl); - } } - + if (!netdev) + netdev = wl_to_prmry_ndev(wl); if (e->etype < WLC_E_LAST && wl->evt_handler[e->etype]) { wl->evt_handler[e->etype] (wl, netdev, &e->emsg, e->edata); } else { @@ -6059,7 +6171,7 @@ static void wl_put_event(struct wl_event_q *e) kfree(e); } -static s32 wl_dongle_mode(struct wl_priv *wl, struct net_device *ndev, s32 iftype) +static s32 wl_config_ifmode(struct wl_priv *wl, struct net_device *ndev, s32 iftype) { s32 infra = 0; s32 err = 0; @@ -6100,7 +6212,8 @@ static s32 wl_dongle_mode(struct wl_priv *wl, struct net_device *ndev, s32 iftyp return 0; } -static s32 wl_dongle_add_remove_eventmsg(struct net_device *ndev, u16 event, bool add) + +static s32 wl_add_remove_eventmsg(struct net_device *ndev, u16 event, bool add) { s8 iovbuf[WL_EVENTING_MASK_LEN + 12]; @@ -6113,7 +6226,7 @@ static s32 wl_dongle_add_remove_eventmsg(struct net_device *ndev, u16 event, boo err = wldev_ioctl(ndev, WLC_GET_VAR, iovbuf, sizeof(iovbuf), false); if (unlikely(err)) { WL_ERR(("Get event_msgs error (%d)\n", err)); - goto dongle_eventmsg_out; + goto eventmsg_out; } memcpy(eventmask, iovbuf, WL_EVENTING_MASK_LEN); if (add) { @@ -6126,350 +6239,15 @@ static s32 wl_dongle_add_remove_eventmsg(struct net_device *ndev, u16 event, boo err = wldev_ioctl(ndev, WLC_SET_VAR, iovbuf, sizeof(iovbuf), true); if (unlikely(err)) { WL_ERR(("Set event_msgs error (%d)\n", err)); - goto dongle_eventmsg_out; - } - -dongle_eventmsg_out: - return err; - -} - - -#ifndef EMBEDDED_PLATFORM -static s32 wl_dongle_country(struct net_device *ndev, u8 ccode) -{ - - s32 err = 0; - - return err; -} - -static s32 wl_dongle_up(struct net_device *ndev, u32 up) -{ - s32 err = 0; - - err = wldev_ioctl(ndev, WLC_UP, &up, sizeof(up), true); - if (unlikely(err)) { - WL_ERR(("WLC_UP error (%d)\n", err)); - } - return err; -} - -static s32 wl_dongle_power(struct net_device *ndev, u32 power_mode) -{ - s32 err = 0; - - WL_TRACE(("In\n")); - err = wldev_ioctl(ndev, WLC_SET_PM, &power_mode, sizeof(power_mode), true); - if (unlikely(err)) { - WL_ERR(("WLC_SET_PM error (%d)\n", err)); - } - return err; -} - -static s32 -wl_dongle_glom(struct net_device *ndev, u32 glom, u32 dongle_align) -{ - s8 iovbuf[WL_EVENTING_MASK_LEN + 12]; - - s32 err = 0; - - /* Match Host and Dongle rx alignment */ - bcm_mkiovar("bus:txglomalign", (char *)&dongle_align, 4, iovbuf, - sizeof(iovbuf)); - err = wldev_ioctl(ndev, WLC_SET_VAR, iovbuf, sizeof(iovbuf), true); - if (unlikely(err)) { - WL_ERR(("txglomalign error (%d)\n", err)); - goto dongle_glom_out; - } - /* disable glom option per default */ - bcm_mkiovar("bus:txglom", (char *)&glom, 4, iovbuf, sizeof(iovbuf)); - err = wldev_ioctl(ndev, WLC_SET_VAR, iovbuf, sizeof(iovbuf), true); - if (unlikely(err)) { - WL_ERR(("txglom error (%d)\n", err)); - goto dongle_glom_out; - } -dongle_glom_out: - return err; -} - -static s32 -wl_dongle_roam(struct net_device *ndev, u32 roamvar, u32 bcn_timeout) -{ - s8 iovbuf[WL_EVENTING_MASK_LEN + 12]; - - s32 err = 0; - - /* Setup timeout if Beacons are lost and roam is off to report link down */ - if (roamvar) { - bcm_mkiovar("bcn_timeout", (char *)&bcn_timeout, 4, iovbuf, - sizeof(iovbuf)); - err = wldev_ioctl(ndev, WLC_SET_VAR, iovbuf, sizeof(iovbuf), true); - if (unlikely(err)) { - WL_ERR(("bcn_timeout error (%d)\n", err)); - goto dongle_rom_out; - } - } - /* Enable/Disable built-in roaming to allow supplicant to take care of roaming */ - bcm_mkiovar("roam_off", (char *)&roamvar, 4, iovbuf, sizeof(iovbuf)); - err = wldev_ioctl(ndev, WLC_SET_VAR, iovbuf, sizeof(iovbuf), true); - if (unlikely(err)) { - WL_ERR(("roam_off error (%d)\n", err)); - goto dongle_rom_out; - } -dongle_rom_out: - return err; -} - -static s32 -wl_dongle_scantime(struct net_device *ndev, s32 scan_assoc_time, - s32 scan_unassoc_time) -{ - s32 err = 0; - - err = wldev_ioctl(ndev, WLC_SET_SCAN_CHANNEL_TIME, &scan_assoc_time, - sizeof(scan_assoc_time), true); - if (err) { - if (err == -EOPNOTSUPP) { - WL_INFO(("Scan assoc time is not supported\n")); - } else { - WL_ERR(("Scan assoc time error (%d)\n", err)); - } - goto dongle_scantime_out; + goto eventmsg_out; } - err = wldev_ioctl(ndev, WLC_SET_SCAN_UNASSOC_TIME, &scan_unassoc_time, - sizeof(scan_unassoc_time), true); - if (err) { - if (err == -EOPNOTSUPP) { - WL_INFO(("Scan unassoc time is not supported\n")); - } else { - WL_ERR(("Scan unassoc time error (%d)\n", err)); - } - goto dongle_scantime_out; - } - -dongle_scantime_out: - return err; -} - -static s32 -wl_dongle_offload(struct net_device *ndev, s32 arpoe, s32 arp_ol) -{ - /* Room for "event_msgs" + '\0' + bitvec */ - s8 iovbuf[WL_EVENTING_MASK_LEN + 12]; - - s32 err = 0; - - /* Set ARP offload */ - bcm_mkiovar("arpoe", (char *)&arpoe, 4, iovbuf, sizeof(iovbuf)); - err = wldev_ioctl(ndev, WLC_SET_VAR, iovbuf, sizeof(iovbuf), true); - if (err) { - if (err == -EOPNOTSUPP) - WL_INFO(("arpoe is not supported\n")); - else - WL_ERR(("arpoe error (%d)\n", err)); - - goto dongle_offload_out; - } - bcm_mkiovar("arp_ol", (char *)&arp_ol, 4, iovbuf, sizeof(iovbuf)); - err = wldev_ioctl(ndev, WLC_SET_VAR, iovbuf, sizeof(iovbuf), true); - if (err) { - if (err == -EOPNOTSUPP) - WL_INFO(("arp_ol is not supported\n")); - else - WL_ERR(("arp_ol error (%d)\n", err)); - - goto dongle_offload_out; - } - -dongle_offload_out: - return err; -} - -static s32 wl_pattern_atoh(s8 *src, s8 *dst) -{ - int i; - if (strncmp(src, "0x", 2) != 0 && strncmp(src, "0X", 2) != 0) { - WL_ERR(("Mask invalid format. Needs to start with 0x\n")); - return -1; - } - src = src + 2; /* Skip past 0x */ - if (strlen(src) % 2 != 0) { - WL_ERR(("Mask invalid format. Needs to be of even length\n")); - return -1; - } - for (i = 0; *src != '\0'; i++) { - char num[3]; - strncpy(num, src, 2); - num[2] = '\0'; - dst[i] = (u8) simple_strtoul(num, NULL, 16); - src += 2; - } - return i; -} - -static s32 wl_dongle_filter(struct net_device *ndev, u32 filter_mode) -{ - /* Room for "event_msgs" + '\0' + bitvec */ - s8 iovbuf[WL_EVENTING_MASK_LEN + 12]; - - const s8 *str; - struct wl_pkt_filter pkt_filter; - struct wl_pkt_filter *pkt_filterp; - s32 buf_len; - s32 str_len; - u32 mask_size; - u32 pattern_size; - s8 buf[256]; - s32 err = 0; - - /* add a default packet filter pattern */ - str = "pkt_filter_add"; - str_len = strlen(str); - strncpy(buf, str, str_len); - buf[str_len] = '\0'; - buf_len = str_len + 1; - - pkt_filterp = (struct wl_pkt_filter *)(buf + str_len + 1); - - /* Parse packet filter id. */ - pkt_filter.id = htod32(100); - - /* Parse filter polarity. */ - pkt_filter.negate_match = htod32(0); - - /* Parse filter type. */ - pkt_filter.type = htod32(0); - - /* Parse pattern filter offset. */ - pkt_filter.u.pattern.offset = htod32(0); - - /* Parse pattern filter mask. */ - mask_size = htod32(wl_pattern_atoh("0xff", - (char *)pkt_filterp->u.pattern. - mask_and_pattern)); - - /* Parse pattern filter pattern. */ - pattern_size = htod32(wl_pattern_atoh("0x00", - (char *)&pkt_filterp->u.pattern.mask_and_pattern[mask_size])); - - if (mask_size != pattern_size) { - WL_ERR(("Mask and pattern not the same size\n")); - err = -EINVAL; - goto dongle_filter_out; - } - - pkt_filter.u.pattern.size_bytes = mask_size; - buf_len += WL_PKT_FILTER_FIXED_LEN; - buf_len += (WL_PKT_FILTER_PATTERN_FIXED_LEN + 2 * mask_size); - - /* Keep-alive attributes are set in local - * variable (keep_alive_pkt), and - * then memcpy'ed into buffer (keep_alive_pktp) since there is no - * guarantee that the buffer is properly aligned. - */ - memcpy((char *)pkt_filterp, &pkt_filter, - WL_PKT_FILTER_FIXED_LEN + WL_PKT_FILTER_PATTERN_FIXED_LEN); - - err = wldev_ioctl(ndev, WLC_SET_VAR, buf, buf_len, true); - if (err) { - if (err == -EOPNOTSUPP) { - WL_INFO(("filter not supported\n")); - } else { - WL_ERR(("filter (%d)\n", err)); - } - goto dongle_filter_out; - } - - /* set mode to allow pattern */ - bcm_mkiovar("pkt_filter_mode", (char *)&filter_mode, 4, iovbuf, - sizeof(iovbuf)); - err = wldev_ioctl(ndev, WLC_SET_VAR, iovbuf, sizeof(iovbuf), true); - if (err) { - if (err == -EOPNOTSUPP) { - WL_INFO(("filter_mode not supported\n")); - } else { - WL_ERR(("filter_mode (%d)\n", err)); - } - goto dongle_filter_out; - } - -dongle_filter_out: - return err; -} -#endif /* !EMBEDDED_PLATFORM */ - -s32 wl_config_dongle(struct wl_priv *wl, bool need_lock) -{ -#ifndef DHD_SDALIGN -#define DHD_SDALIGN 32 -#endif - struct net_device *ndev; - struct wireless_dev *wdev; - s32 err = 0; - - WL_TRACE(("In\n")); - if (wl->dongle_up) { - WL_ERR(("Dongle is already up\n")); - return err; - } - - ndev = wl_to_prmry_ndev(wl); - wdev = ndev->ieee80211_ptr; - if (need_lock) - rtnl_lock(); -#ifndef EMBEDDED_PLATFORM - err = wl_dongle_up(ndev, 0); - if (unlikely(err)) { - WL_ERR(("wl_dongle_up failed\n")); - goto default_conf_out; - } - err = wl_dongle_country(ndev, 0); - if (unlikely(err)) { - WL_ERR(("wl_dongle_country failed\n")); - goto default_conf_out; - } - err = wl_dongle_power(ndev, PM_FAST); - if (unlikely(err)) { - WL_ERR(("wl_dongle_power failed\n")); - goto default_conf_out; - } - err = wl_dongle_glom(ndev, 0, DHD_SDALIGN); - if (unlikely(err)) { - WL_ERR(("wl_dongle_glom failed\n")); - goto default_conf_out; - } - err = wl_dongle_roam(ndev, (wl->roam_on ? 0 : 1), 3); - if (unlikely(err)) { - WL_ERR(("wl_dongle_roam failed\n")); - goto default_conf_out; - } - wl_dongle_scantime(ndev, 40, 80); - wl_dongle_offload(ndev, 1, 0xf); - wl_dongle_filter(ndev, 1); -#endif /* !EMBEDDED_PLATFORM */ - - err = wl_dongle_mode(wl, ndev, wdev->iftype); - if (unlikely(err && err != -EINPROGRESS)) { - WL_ERR(("wl_dongle_mode failed\n")); - goto default_conf_out; - } - err = wl_dongle_probecap(wl); - if (unlikely(err)) { - WL_ERR(("wl_dongle_probecap failed\n")); - goto default_conf_out; - } - - wl->dongle_up = true; -default_conf_out: - if (need_lock) - rtnl_unlock(); +eventmsg_out: return err; } -static s32 wl_update_wiphybands(struct wl_priv *wl) +s32 wl_update_wiphybands(struct wl_priv *wl) { struct wiphy *wiphy; s8 phylist_buf[128]; @@ -6497,14 +6275,25 @@ static s32 __wl_cfg80211_up(struct wl_priv *wl) { s32 err = 0; struct net_device *ndev = wl_to_prmry_ndev(wl); + struct wireless_dev *wdev = ndev->ieee80211_ptr; + WL_TRACE(("In\n")); - wl_debugfs_add_netdev_params(wl, ndev); - err = wl_config_dongle(wl, false); + err = dhd_config_dongle(wl, false); if (unlikely(err)) return err; - dhd_monitor_init(wl->pub); - wl_invoke_iscan(wl); + + err = wl_config_ifmode(wl, ndev, wdev->iftype); + if (unlikely(err && err != -EINPROGRESS)) { + WL_ERR(("wl_config_ifmode failed\n")); + } + err = wl_update_wiphybands(wl); + if (unlikely(err)) { + WL_ERR(("wl_update_wiphybands failed\n")); + } + + err = dhd_monitor_init(wl->pub); + err = wl_invoke_iscan(wl); wl_set_drv_status(wl, READY, ndev); return err; } @@ -6515,6 +6304,7 @@ static s32 __wl_cfg80211_down(struct wl_priv *wl) unsigned long flags; struct net_info *iter, *next; struct net_device *ndev = wl_to_prmry_ndev(wl); + WL_TRACE(("In\n")); /* Check if cfg80211 interface is already down */ if (!wl_get_drv_status(wl, READY, ndev)) @@ -6523,7 +6313,7 @@ static s32 __wl_cfg80211_down(struct wl_priv *wl) wl_set_drv_status(wl, SCAN_ABORTING, iter->ndev); wl_term_iscan(wl); - flags = dhd_os_spin_lock((dhd_pub_t *)(wl->pub)); + spin_lock_irqsave(&wl->cfgdrv_lock, flags); if (wl->scan_request) { cfg80211_scan_done(wl->scan_request, true); wl->scan_request = NULL; @@ -6540,21 +6330,19 @@ static s32 __wl_cfg80211_down(struct wl_priv *wl) } wl_to_prmry_ndev(wl)->ieee80211_ptr->iftype = NL80211_IFTYPE_STATION; - dhd_os_spin_unlock((dhd_pub_t *)(wl->pub), flags); + spin_unlock_irqrestore(&wl->cfgdrv_lock, flags); - wl->dongle_up = false; + DNGL_FUNC(dhd_cfg80211_down, (wl)); wl_flush_eq(wl); wl_link_down(wl); if (wl->p2p_supported) wl_cfgp2p_down(wl); dhd_monitor_uninit(); - wl_debugfs_remove_netdev(wl); - return err; } -s32 wl_cfg80211_up(void) +s32 wl_cfg80211_up(void *para) { struct wl_priv *wl; s32 err = 0; @@ -6567,17 +6355,16 @@ s32 wl_cfg80211_up(void) if (err) WL_ERR(("__wl_cfg80211_up failed\n")); mutex_unlock(&wl->usr_sync); - return err; } -/* Private Event to Supplicant with indication that FW hangs */ +/* Private Event to Supplicant with indication that chip hangs */ int wl_cfg80211_hang(struct net_device *dev, u16 reason) { struct wl_priv *wl; wl = wlcfg_drv_priv; - WL_ERR(("In : FW crash Eventing\n")); + WL_ERR(("In : chip crash eventing\n")); cfg80211_disconnected(dev, reason, NULL, 0, GFP_KERNEL); if (wl != NULL) { wl_link_down(wl); @@ -6585,7 +6372,7 @@ int wl_cfg80211_hang(struct net_device *dev, u16 reason) return 0; } -s32 wl_cfg80211_down(void) +s32 wl_cfg80211_down(void *para) { struct wl_priv *wl; s32 err = 0; @@ -6599,25 +6386,15 @@ s32 wl_cfg80211_down(void) return err; } -static s32 wl_dongle_probecap(struct wl_priv *wl) -{ - s32 err = 0; - - err = wl_update_wiphybands(wl); - if (unlikely(err)) - return err; - - return err; -} - static void *wl_read_prof(struct wl_priv *wl, struct net_device *ndev, s32 item) { unsigned long flags; void *rptr = NULL; struct wl_profile *profile = wl_get_profile_by_netdev(wl, ndev); + if (!profile) return NULL; - flags = dhd_os_spin_lock((dhd_pub_t *)(wl->pub)); + spin_lock_irqsave(&wl->cfgdrv_lock, flags); switch (item) { case WL_PROF_SEC: rptr = &profile->sec; @@ -6632,7 +6409,7 @@ static void *wl_read_prof(struct wl_priv *wl, struct net_device *ndev, s32 item) rptr = &profile->ssid; break; } - dhd_os_spin_unlock((dhd_pub_t *)(wl->pub), flags); + spin_unlock_irqrestore(&wl->cfgdrv_lock, flags); if (!rptr) WL_ERR(("invalid item (%d)\n", item)); return rptr; @@ -6646,9 +6423,10 @@ wl_update_prof(struct wl_priv *wl, struct net_device *ndev, struct wlc_ssid *ssid; unsigned long flags; struct wl_profile *profile = wl_get_profile_by_netdev(wl, ndev); + if (!profile) return WL_INVALID; - flags = dhd_os_spin_lock((dhd_pub_t *)(wl->pub)); + spin_lock_irqsave(&wl->cfgdrv_lock, flags); switch (item) { case WL_PROF_SSID: ssid = (wlc_ssid_t *) data; @@ -6680,7 +6458,7 @@ wl_update_prof(struct wl_priv *wl, struct net_device *ndev, err = -EOPNOTSUPP; break; } - dhd_os_spin_unlock((dhd_pub_t *)(wl->pub), flags); + spin_unlock_irqrestore(&wl->cfgdrv_lock, flags); return err; } @@ -6808,114 +6586,22 @@ static void wl_delay(u32 ms) } } -s32 wl_cfg80211_read_fw(s8 *buf, u32 size) -{ - const struct firmware *fw_entry; - struct wl_priv *wl; - - wl = wlcfg_drv_priv; - - fw_entry = wl->fw->fw_entry; - - if (fw_entry->size < wl->fw->ptr + size) - size = fw_entry->size - wl->fw->ptr; - - memcpy(buf, &fw_entry->data[wl->fw->ptr], size); - wl->fw->ptr += size; - return size; -} - -void wl_cfg80211_release_fw(void) -{ - struct wl_priv *wl; - - wl = wlcfg_drv_priv; - release_firmware(wl->fw->fw_entry); - wl->fw->ptr = 0; -} - -void *wl_cfg80211_request_fw(s8 *file_name) -{ - struct wl_priv *wl; - const struct firmware *fw_entry = NULL; - s32 err = 0; - - WL_TRACE(("In\n")); - WL_DBG(("file name : \"%s\"\n", file_name)); - wl = wlcfg_drv_priv; - - if (!test_bit(WL_FW_LOADING_DONE, &wl->fw->status)) { - err = request_firmware(&wl->fw->fw_entry, file_name, - wl_cfg80211_get_parent_dev()); - if (unlikely(err)) { - WL_ERR(("Could not download fw (%d)\n", err)); - goto req_fw_out; - } - set_bit(WL_FW_LOADING_DONE, &wl->fw->status); - fw_entry = wl->fw->fw_entry; - if (fw_entry) { - WL_DBG(("fw size (%zd), data (%p)\n", fw_entry->size, - fw_entry->data)); - } - } else if (!test_bit(WL_NVRAM_LOADING_DONE, &wl->fw->status)) { - err = request_firmware(&wl->fw->fw_entry, file_name, - wl_cfg80211_get_parent_dev()); - if (unlikely(err)) { - WL_ERR(("Could not download nvram (%d)\n", err)); - goto req_fw_out; - } - set_bit(WL_NVRAM_LOADING_DONE, &wl->fw->status); - fw_entry = wl->fw->fw_entry; - if (fw_entry) { - WL_DBG(("nvram size (%zd), data (%p)\n", fw_entry->size, - fw_entry->data)); - } - } else { - WL_DBG(("Downloading already done. Nothing to do more\n")); - err = -EPERM; - } - -req_fw_out: - if (unlikely(err)) { - return NULL; - } - wl->fw->ptr = 0; - return (void *)fw_entry->data; -} - -s8 *wl_cfg80211_get_fwname(void) -{ - struct wl_priv *wl; - - wl = wlcfg_drv_priv; - strcpy(wl->fw->fw_name, WL_4329_FW_FILE); - return wl->fw->fw_name; -} - -s8 *wl_cfg80211_get_nvramname(void) -{ - struct wl_priv *wl; - - wl = wlcfg_drv_priv; - strcpy(wl->fw->nvram_name, WL_4329_NVRAM_FILE); - return wl->fw->nvram_name; -} - s32 wl_cfg80211_get_p2p_dev_addr(struct net_device *net, struct ether_addr *p2pdev_addr) { struct wl_priv *wl; - dhd_pub_t *dhd_pub; struct ether_addr p2pif_addr; + struct ether_addr primary_mac; wl = wlcfg_drv_priv; - dhd_pub = (dhd_pub_t *)wl->pub; - wl_cfgp2p_generate_bss_mac(&dhd_pub->mac, p2pdev_addr, &p2pif_addr); + get_primary_mac(wl, &primary_mac); + wl_cfgp2p_generate_bss_mac(&primary_mac, p2pdev_addr, &p2pif_addr); return 0; } s32 wl_cfg80211_set_p2p_noa(struct net_device *net, char* buf, int len) { struct wl_priv *wl; + wl = wlcfg_drv_priv; return wl_cfgp2p_set_p2p_noa(wl, net, buf, len); @@ -6973,70 +6659,6 @@ s32 wl_cfg80211_set_wps_p2p_ie(struct net_device *net, char *buf, int len, return ret; } -static __used void wl_dongle_poweron(struct wl_priv *wl) -{ - WL_DBG(("Enter \n")); - dhd_customer_gpio_wlan_ctrl(WLAN_RESET_ON); - -#if defined(BCMLXSDMMC) - sdioh_start(NULL, 0); -#endif -#if defined(BCMLXSDMMC) - sdioh_start(NULL, 1); -#endif - wl_cfg80211_resume(wl_to_wiphy(wl)); -} - -static __used void wl_dongle_poweroff(struct wl_priv *wl) -{ - WL_DBG(("Enter \n")); -#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 39) - wl_cfg80211_suspend(wl_to_wiphy(wl), NULL); -#else - wl_cfg80211_suspend(wl_to_wiphy(wl)); -#endif - -#if defined(BCMLXSDMMC) - sdioh_stop(NULL); -#endif - /* clean up dtim_skip setting */ - dhd_customer_gpio_wlan_ctrl(WLAN_RESET_OFF); -} - -static int wl_debugfs_add_netdev_params(struct wl_priv *wl, struct net_device *ndev) -{ - char buf[10+IFNAMSIZ]; - struct dentry *fd; - struct wl_profile *profile = wl_get_profile_by_netdev(wl, ndev); - s32 err = 0; - - WL_TRACE(("In\n")); - sprintf(buf, "netdev:%s", wl_to_prmry_ndev(wl)->name); - wl->debugfsdir = debugfs_create_dir(buf, wl_to_wiphy(wl)->debugfsdir); - - fd = debugfs_create_u16("beacon_int", S_IRUGO, wl->debugfsdir, - (u16 *)&profile->beacon_interval); - if (!fd) { - err = -ENOMEM; - goto err_out; - } - - fd = debugfs_create_u8("dtim_period", S_IRUGO, wl->debugfsdir, - (u8 *)&profile->dtim_period); - if (!fd) { - err = -ENOMEM; - goto err_out; - } - -err_out: - return err; -} - -static void wl_debugfs_remove_netdev(struct wl_priv *wl) -{ - WL_DBG(("Enter \n")); -} - static const struct rfkill_ops wl_rfkill_ops = { .set_block = wl_rfkill_set }; @@ -7091,486 +6713,42 @@ err_out: return err; } -#if defined(COEX_DHCP) -/* - * get named driver variable to uint register value and return error indication - * calling example: dev_wlc_intvar_get_reg(dev, "btc_params",66, ®_value) - */ -static int -dev_wlc_intvar_get_reg(struct net_device *dev, char *name, - uint reg, int *retval) -{ - union { - char buf[WLC_IOCTL_SMLEN]; - int val; - } var; - int error; - - bcm_mkiovar(name, (char *)(®), sizeof(reg), - (char *)(&var), sizeof(var.buf)); - error = wldev_ioctl(dev, WLC_GET_VAR, (char *)(&var), sizeof(var.buf), false); - - *retval = dtoh32(var.val); - return (error); -} - -static int -dev_wlc_bufvar_set(struct net_device *dev, char *name, char *buf, int len) -{ -#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 31) - char ioctlbuf[1024]; -#else - static char ioctlbuf[1024]; -#endif /* LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 31) */ - - bcm_mkiovar(name, buf, len, ioctlbuf, sizeof(ioctlbuf)); - - return (wldev_ioctl(dev, WLC_SET_VAR, ioctlbuf, sizeof(ioctlbuf), true)); -} -/* -get named driver variable to uint register value and return error indication -calling example: dev_wlc_intvar_set_reg(dev, "btc_params",66, value) -*/ -static int -dev_wlc_intvar_set_reg(struct net_device *dev, char *name, char *addr, char * val) -{ - char reg_addr[8]; - - memset(reg_addr, 0, sizeof(reg_addr)); - memcpy((char *)®_addr[0], (char *)addr, 4); - memcpy((char *)®_addr[4], (char *)val, 4); - - return (dev_wlc_bufvar_set(dev, name, (char *)®_addr[0], sizeof(reg_addr))); -} - -static bool btcoex_is_sco_active(struct net_device *dev) -{ - int ioc_res = 0; - bool res = FALSE; - int sco_id_cnt = 0; - int param27; - int i; - - for (i = 0; i < 12; i++) { - - ioc_res = dev_wlc_intvar_get_reg(dev, "btc_params", 27, ¶m27); - - WL_TRACE(("%s, sample[%d], btc params: 27:%x\n", - __FUNCTION__, i, param27)); - - if (ioc_res < 0) { - WL_ERR(("%s ioc read btc params error\n", __FUNCTION__)); - break; - } - - if ((param27 & 0x6) == 2) { /* count both sco & esco */ - sco_id_cnt++; - } - - if (sco_id_cnt > 2) { - WL_TRACE(("%s, sco/esco detected, pkt id_cnt:%d samples:%d\n", - __FUNCTION__, sco_id_cnt, i)); - res = TRUE; - break; - } - - msleep(5); - } - - return res; -} - -#if defined(BT_DHCP_eSCO_FIX) -/* Enhanced BT COEX settings for eSCO compatibility during DHCP window */ -static int set_btc_esco_params(struct net_device *dev, bool trump_sco) +struct device *wl_cfg80211_get_parent_dev(void) { - static bool saved_status = FALSE; - - char buf_reg50va_dhcp_on[8] = - { 50, 00, 00, 00, 0x22, 0x80, 0x00, 0x00 }; - char buf_reg51va_dhcp_on[8] = - { 51, 00, 00, 00, 0x00, 0x00, 0x00, 0x00 }; - char buf_reg64va_dhcp_on[8] = - { 64, 00, 00, 00, 0x00, 0x00, 0x00, 0x00 }; - char buf_reg65va_dhcp_on[8] = - { 65, 00, 00, 00, 0x00, 0x00, 0x00, 0x00 }; - char buf_reg71va_dhcp_on[8] = - { 71, 00, 00, 00, 0x00, 0x00, 0x00, 0x00 }; - uint32 regaddr; - static uint32 saved_reg50; - static uint32 saved_reg51; - static uint32 saved_reg64; - static uint32 saved_reg65; - static uint32 saved_reg71; - - if (trump_sco) { - /* this should reduce eSCO agressive retransmit - * w/o breaking it - */ - - /* 1st save current */ - WL_TRACE(("Do new SCO/eSCO coex algo {save &" - "override}\n")); - if ((!dev_wlc_intvar_get_reg(dev, "btc_params", 50, &saved_reg50)) && - (!dev_wlc_intvar_get_reg(dev, "btc_params", 51, &saved_reg51)) && - (!dev_wlc_intvar_get_reg(dev, "btc_params", 64, &saved_reg64)) && - (!dev_wlc_intvar_get_reg(dev, "btc_params", 65, &saved_reg65)) && - (!dev_wlc_intvar_get_reg(dev, "btc_params", 71, &saved_reg71))) { - saved_status = TRUE; - WL_TRACE(("%s saved bt_params[50,51,64,65,71]:" - "0x%x 0x%x 0x%x 0x%x 0x%x\n", - __FUNCTION__, saved_reg50, saved_reg51, - saved_reg64, saved_reg65, saved_reg71)); - } else { - WL_ERR((":%s: save btc_params failed\n", - __FUNCTION__)); - saved_status = FALSE; - return -1; - } - - WL_TRACE(("override with [50,51,64,65,71]:" - "0x%x 0x%x 0x%x 0x%x 0x%x\n", - *(u32 *)(buf_reg50va_dhcp_on+4), - *(u32 *)(buf_reg51va_dhcp_on+4), - *(u32 *)(buf_reg64va_dhcp_on+4), - *(u32 *)(buf_reg65va_dhcp_on+4), - *(u32 *)(buf_reg71va_dhcp_on+4))); - - dev_wlc_bufvar_set(dev, "btc_params", - (char *)&buf_reg50va_dhcp_on[0], 8); - dev_wlc_bufvar_set(dev, "btc_params", - (char *)&buf_reg51va_dhcp_on[0], 8); - dev_wlc_bufvar_set(dev, "btc_params", - (char *)&buf_reg64va_dhcp_on[0], 8); - dev_wlc_bufvar_set(dev, "btc_params", - (char *)&buf_reg65va_dhcp_on[0], 8); - dev_wlc_bufvar_set(dev, "btc_params", - (char *)&buf_reg71va_dhcp_on[0], 8); - - saved_status = TRUE; - } else if (saved_status) { - /* restore previously saved bt params */ - WL_TRACE(("Do new SCO/eSCO coex algo {save &" - "override}\n")); - - regaddr = 50; - dev_wlc_intvar_set_reg(dev, "btc_params", - (char *)®addr, (char *)&saved_reg50); - regaddr = 51; - dev_wlc_intvar_set_reg(dev, "btc_params", - (char *)®addr, (char *)&saved_reg51); - regaddr = 64; - dev_wlc_intvar_set_reg(dev, "btc_params", - (char *)®addr, (char *)&saved_reg64); - regaddr = 65; - dev_wlc_intvar_set_reg(dev, "btc_params", - (char *)®addr, (char *)&saved_reg65); - regaddr = 71; - dev_wlc_intvar_set_reg(dev, "btc_params", - (char *)®addr, (char *)&saved_reg71); - - WL_TRACE(("restore bt_params[50,51,64,65,71]:" - "0x%x 0x%x 0x%x 0x%x 0x%x\n", - saved_reg50, saved_reg51, saved_reg64, - saved_reg65, saved_reg71)); - - saved_status = FALSE; - } else { - WL_ERR((":%s att to restore not saved BTCOEX params\n", - __FUNCTION__)); - return -1; - } - return 0; + return cfg80211_parent_dev; } -#endif /* BT_DHCP_eSCO_FIX */ -static void -wl_cfg80211_bt_setflag(struct net_device *dev, bool set) +void wl_cfg80211_set_parent_dev(void *dev) { -#if defined(BT_DHCP_USE_FLAGS) - char buf_flag7_dhcp_on[8] = { 7, 00, 00, 00, 0x1, 0x0, 0x00, 0x00 }; - char buf_flag7_default[8] = { 7, 00, 00, 00, 0x0, 0x00, 0x00, 0x00}; -#endif - -#if defined(BT_DHCP_eSCO_FIX) - /* set = 1, save & turn on 0 - off & restore prev settings */ - set_btc_esco_params(dev, set); -#endif - -#if defined(BT_DHCP_USE_FLAGS) - WL_TRACE(("WI-FI priority boost via bt flags, set:%d\n", set)); - if (set == TRUE) - /* Forcing bt_flag7 */ - dev_wlc_bufvar_set(dev, "btc_flags", - (char *)&buf_flag7_dhcp_on[0], - sizeof(buf_flag7_dhcp_on)); - else - /* Restoring default bt flag7 */ - dev_wlc_bufvar_set(dev, "btc_flags", - (char *)&buf_flag7_default[0], - sizeof(buf_flag7_default)); -#endif + cfg80211_parent_dev = dev; } -static void wl_cfg80211_bt_timerfunc(ulong data) +static void wl_cfg80211_clear_parent_dev(void) { - struct btcoex_info *bt_local = (struct btcoex_info *)data; - WL_TRACE(("%s\n", __FUNCTION__)); - bt_local->timer_on = 0; - schedule_work(&bt_local->work); + cfg80211_parent_dev = NULL; } -static void wl_cfg80211_bt_handler(struct work_struct *work) +static void get_primary_mac(struct wl_priv *wl, struct ether_addr *mac) { - struct btcoex_info *btcx_inf; - - btcx_inf = container_of(work, struct btcoex_info, work); - - if (btcx_inf->timer_on) { - btcx_inf->timer_on = 0; - del_timer_sync(&btcx_inf->timer); - } - - switch (btcx_inf->bt_state) { - case BT_DHCP_START: - /* DHCP started - * provide OPPORTUNITY window to get DHCP address - */ - WL_TRACE(("%s bt_dhcp stm: started \n", - __FUNCTION__)); - btcx_inf->bt_state = BT_DHCP_OPPR_WIN; - mod_timer(&btcx_inf->timer, - jiffies + BT_DHCP_OPPR_WIN_TIME*HZ/1000); - btcx_inf->timer_on = 1; - break; - - case BT_DHCP_OPPR_WIN: - if (btcx_inf->dhcp_done) { - WL_TRACE(("%s DHCP Done before T1 expiration\n", - __FUNCTION__)); - goto btc_coex_idle; - } - - /* DHCP is not over yet, start lowering BT priority - * enforce btc_params + flags if necessary - */ - WL_TRACE(("%s DHCP T1:%d expired\n", __FUNCTION__, - BT_DHCP_OPPR_WIN_TIME)); - if (btcx_inf->dev) - wl_cfg80211_bt_setflag(btcx_inf->dev, TRUE); - btcx_inf->bt_state = BT_DHCP_FLAG_FORCE_TIMEOUT; - mod_timer(&btcx_inf->timer, - jiffies + BT_DHCP_FLAG_FORCE_TIME*HZ/1000); - btcx_inf->timer_on = 1; - break; - - case BT_DHCP_FLAG_FORCE_TIMEOUT: - if (btcx_inf->dhcp_done) { - WL_TRACE(("%s DHCP Done before T2 expiration\n", - __FUNCTION__)); - } else { - /* Noo dhcp during T1+T2, restore BT priority */ - WL_TRACE(("%s DHCP wait interval T2:%d" - "msec expired\n", __FUNCTION__, - BT_DHCP_FLAG_FORCE_TIME)); - } - - /* Restoring default bt priority */ - if (btcx_inf->dev) - wl_cfg80211_bt_setflag(btcx_inf->dev, FALSE); -btc_coex_idle: - btcx_inf->bt_state = BT_DHCP_IDLE; - btcx_inf->timer_on = 0; - break; - - default: - WL_ERR(("%s error g_status=%d !!!\n", __FUNCTION__, - btcx_inf->bt_state)); - if (btcx_inf->dev) - wl_cfg80211_bt_setflag(btcx_inf->dev, FALSE); - btcx_inf->bt_state = BT_DHCP_IDLE; - btcx_inf->timer_on = 0; - break; - } - - net_os_wake_unlock(btcx_inf->dev); + wldev_iovar_getbuf_bsscfg(wl_to_prmry_ndev(wl), "cur_etheraddr", NULL, + 0, wl->ioctl_buf, WLC_IOCTL_MAXLEN, 0, &wl->ioctl_buf_sync); + memcpy(mac->octet, wl->ioctl_buf, ETHER_ADDR_LEN); } -static int wl_cfg80211_btcoex_init(struct wl_priv *wl) +int wl_cfg80211_do_driver_init(struct net_device *net) { - struct btcoex_info *btco_inf = NULL; - - btco_inf = kmalloc(sizeof(struct btcoex_info), GFP_KERNEL); - if (!btco_inf) - return -ENOMEM; + struct wl_priv *wl = *(struct wl_priv **)netdev_priv(net); - btco_inf->bt_state = BT_DHCP_IDLE; - btco_inf->ts_dhcp_start = 0; - btco_inf->ts_dhcp_ok = 0; - /* Set up timer for BT */ - btco_inf->timer_ms = 10; - init_timer(&btco_inf->timer); - btco_inf->timer.data = (ulong)btco_inf; - btco_inf->timer.function = wl_cfg80211_bt_timerfunc; - - btco_inf->dev = wl->wdev->netdev; + if (!wl || !wl->wdev) + return -EINVAL; - INIT_WORK(&btco_inf->work, wl_cfg80211_bt_handler); + if (dhd_do_driver_init(wl->wdev->netdev) < 0) + return -1; - wl->btcoex_info = btco_inf; return 0; } -static void -wl_cfg80211_btcoex_deinit(struct wl_priv *wl) -{ - if (!wl->btcoex_info) - return; - - if (!wl->btcoex_info->timer_on) { - wl->btcoex_info->timer_on = 0; - del_timer_sync(&wl->btcoex_info->timer); - } - - cancel_work_sync(&wl->btcoex_info->work); - - kfree(wl->btcoex_info); - wl->btcoex_info = NULL; -} -#endif /* COEX_DHCP */ - -int wl_cfg80211_set_btcoex_dhcp(struct net_device *dev, char *command) -{ - char powermode_val = 0; - char buf_reg66va_dhcp_on[8] = { 66, 00, 00, 00, 0x10, 0x27, 0x00, 0x00 }; - char buf_reg41va_dhcp_on[8] = { 41, 00, 00, 00, 0x33, 0x00, 0x00, 0x00 }; - char buf_reg68va_dhcp_on[8] = { 68, 00, 00, 00, 0x90, 0x01, 0x00, 0x00 }; - - uint32 regaddr; - static uint32 saved_reg66; - static uint32 saved_reg41; - static uint32 saved_reg68; - static bool saved_status = FALSE; - -#ifdef COEX_DHCP - char buf_flag7_default[8] = { 7, 00, 00, 00, 0x0, 0x00, 0x00, 0x00}; - struct btcoex_info *btco_inf = wlcfg_drv_priv->btcoex_info; -#endif /* COEX_DHCP */ - - /* Figure out powermode 1 or o command */ - strncpy((char *)&powermode_val, command + strlen("BTCOEXMODE") +1, 1); - - if (strnicmp((char *)&powermode_val, "1", strlen("1")) == 0) { - - WL_TRACE(("%s: DHCP session starts\n", __FUNCTION__)); - - /* Retrieve and saved orig regs value */ - if ((saved_status == FALSE) && - (!dev_wlc_intvar_get_reg(dev, "btc_params", 66, &saved_reg66)) && - (!dev_wlc_intvar_get_reg(dev, "btc_params", 41, &saved_reg41)) && - (!dev_wlc_intvar_get_reg(dev, "btc_params", 68, &saved_reg68))) { - saved_status = TRUE; - WL_TRACE(("Saved 0x%x 0x%x 0x%x\n", - saved_reg66, saved_reg41, saved_reg68)); - - /* Disable PM mode during dhpc session */ - - /* Disable PM mode during dhpc session */ -#ifdef COEX_DHCP - /* Start BT timer only for SCO connection */ - if (btcoex_is_sco_active(dev)) { - /* btc_params 66 */ - dev_wlc_bufvar_set(dev, "btc_params", - (char *)&buf_reg66va_dhcp_on[0], - sizeof(buf_reg66va_dhcp_on)); - /* btc_params 41 0x33 */ - dev_wlc_bufvar_set(dev, "btc_params", - (char *)&buf_reg41va_dhcp_on[0], - sizeof(buf_reg41va_dhcp_on)); - /* btc_params 68 0x190 */ - dev_wlc_bufvar_set(dev, "btc_params", - (char *)&buf_reg68va_dhcp_on[0], - sizeof(buf_reg68va_dhcp_on)); - saved_status = TRUE; - - btco_inf->bt_state = BT_DHCP_START; - btco_inf->timer_on = 1; - mod_timer(&btco_inf->timer, btco_inf->timer.expires); - WL_TRACE(("%s enable BT DHCP Timer\n", - __FUNCTION__)); - } -#endif /* COEX_DHCP */ - } - else if (saved_status == TRUE) { - WL_ERR(("%s was called w/o DHCP OFF. Continue\n", __FUNCTION__)); - } - } - else if (strnicmp((char *)&powermode_val, "2", strlen("2")) == 0) { - - - /* Restoring PM mode */ - -#ifdef COEX_DHCP - /* Stop any bt timer because DHCP session is done */ - WL_TRACE(("%s disable BT DHCP Timer\n", __FUNCTION__)); - if (btco_inf->timer_on) { - btco_inf->timer_on = 0; - del_timer_sync(&btco_inf->timer); - - if (btco_inf->bt_state != BT_DHCP_IDLE) { - /* need to restore original btc flags & extra btc params */ - WL_TRACE(("%s bt->bt_state:%d\n", - __FUNCTION__, btco_inf->bt_state)); - /* wake up btcoex thread to restore btlags+params */ - schedule_work(&btco_inf->work); - } - } - - /* Restoring btc_flag paramter anyway */ - if (saved_status == TRUE) - dev_wlc_bufvar_set(dev, "btc_flags", - (char *)&buf_flag7_default[0], sizeof(buf_flag7_default)); -#endif /* COEX_DHCP */ - - /* Restore original values */ - if (saved_status == TRUE) { - regaddr = 66; - dev_wlc_intvar_set_reg(dev, "btc_params", - (char *)®addr, (char *)&saved_reg66); - regaddr = 41; - dev_wlc_intvar_set_reg(dev, "btc_params", - (char *)®addr, (char *)&saved_reg41); - regaddr = 68; - dev_wlc_intvar_set_reg(dev, "btc_params", - (char *)®addr, (char *)&saved_reg68); - - WL_TRACE(("restore regs {66,41,68} <- 0x%x 0x%x 0x%x\n", - saved_reg66, saved_reg41, saved_reg68)); - } - saved_status = FALSE; - - } - else { - WL_ERR(("%s Unkwown yet power setting, ignored\n", - __FUNCTION__)); - } - - snprintf(command, 3, "OK"); - - return (strlen("OK")); -} - -struct device *wl_cfg80211_get_parent_dev(void) -{ - return cfg80211_parent_dev; -} - -void wl_cfg80211_set_parent_dev(void *dev) +void wl_cfg80211_enable_trace(int level) { - cfg80211_parent_dev = dev; -} - -static void wl_cfg80211_clear_parent_dev(void) -{ - cfg80211_parent_dev = NULL; + wl_dbg_level |= WL_DBG_DBG; } diff --git a/drivers/net/wireless/bcmdhd/wl_cfg80211.h b/drivers/net/wireless/bcmdhd/wl_cfg80211.h index 18ff27680cb0..2b8e66413f23 100644 --- a/drivers/net/wireless/bcmdhd/wl_cfg80211.h +++ b/drivers/net/wireless/bcmdhd/wl_cfg80211.h @@ -68,6 +68,9 @@ do { \ printk args; \ } \ } while (0) +#ifdef WL_INFO +#undef WL_INFO +#endif #define WL_INFO(args) \ do { \ if (wl_dbg_level & WL_DBG_INFO) { \ @@ -75,6 +78,9 @@ do { \ printk args; \ } \ } while (0) +#ifdef WL_SCAN +#undef WL_SCAN +#endif #define WL_SCAN(args) \ do { \ if (wl_dbg_level & WL_DBG_SCAN) { \ @@ -82,6 +88,9 @@ do { \ printk args; \ } \ } while (0) +#ifdef WL_TRACE +#undef WL_TRACE +#endif #define WL_TRACE(args) \ do { \ if (wl_dbg_level & WL_DBG_TRACE) { \ @@ -102,40 +111,30 @@ do { \ #endif /* (WL_DBG_LEVEL > 0) */ -#define WL_SCAN_RETRY_MAX 3 /* used for ibss scan */ -#define WL_NUM_PMKIDS_MAX MAXPMKID /* will be used - * for 2.6.33 kernel - * or later - */ -#define WL_SCAN_BUF_MAX (1024 * 8) -#define WL_TLV_INFO_MAX 1024 +#define WL_SCAN_RETRY_MAX 3 +#define WL_NUM_PMKIDS_MAX MAXPMKID +#define WL_SCAN_BUF_MAX (1024 * 8) +#define WL_TLV_INFO_MAX 1024 #define WL_SCAN_IE_LEN_MAX 2048 -#define WL_BSS_INFO_MAX 2048 -#define WL_ASSOC_INFO_MAX 512 /* - * needs to grab assoc info from dongle to - * report it to cfg80211 through "connect" - * event - */ +#define WL_BSS_INFO_MAX 2048 +#define WL_ASSOC_INFO_MAX 512 #define WL_IOCTL_LEN_MAX 1024 #define WL_EXTRA_BUF_MAX 2048 -#define WL_ISCAN_BUF_MAX 2048 /* - * the buf lengh can be WLC_IOCTL_MAXLEN (8K) - * to reduce iteration - */ +#define WL_ISCAN_BUF_MAX 2048 #define WL_ISCAN_TIMER_INTERVAL_MS 3000 #define WL_SCAN_ERSULTS_LAST (WL_SCAN_RESULTS_NO_MEM+1) -#define WL_AP_MAX 256 /* virtually unlimitted as long - * as kernel memory allows - */ +#define WL_AP_MAX 256 #define WL_FILE_NAME_MAX 256 -#define WL_DWELL_TIME 200 -#define WL_LONG_DWELL_TIME 1000 -#define IFACE_MAX_CNT 2 +#define WL_DWELL_TIME 200 +#define WL_MED_DWELL_TIME 400 +#define WL_LONG_DWELL_TIME 1000 +#define IFACE_MAX_CNT 2 #define WL_SCAN_TIMER_INTERVAL_MS 8000 /* Scan timeout */ +#define WL_CHANNEL_SYNC_RETRY 5 +#define WL_INVALID -1 -#define WL_INVALID -1 -/* dongle status */ +/* driver status */ enum wl_status { WL_STATUS_READY = 0, WL_STATUS_SCANNING, @@ -144,7 +143,8 @@ enum wl_status { WL_STATUS_CONNECTED, WL_STATUS_DISCONNECTING, WL_STATUS_AP_CREATING, - WL_STATUS_AP_CREATED + WL_STATUS_AP_CREATED, + WL_STATUS_SENDING_ACT_FRM }; /* wi-fi mode */ @@ -154,7 +154,7 @@ enum wl_mode { WL_MODE_AP }; -/* dongle profile list */ +/* driver profile list */ enum wl_prof_list { WL_PROF_MODE, WL_PROF_SSID, @@ -167,7 +167,7 @@ enum wl_prof_list { WL_PROF_DTIMPERIOD }; -/* dongle iscan state */ +/* driver iscan state */ enum wl_iscan_state { WL_ISCAN_STATE_IDLE, WL_ISCAN_STATE_SCANING @@ -197,7 +197,7 @@ struct beacon_proberesp { u8 variable[0]; } __attribute__ ((packed)); -/* dongle configuration */ +/* driver configuration */ struct wl_conf { u32 frag_threshold; u32 rts_threshold; @@ -256,7 +256,7 @@ struct wl_ibss { u8 channel; }; -/* dongle profile */ +/* wl driver profile */ struct wl_profile { u32 mode; s32 band; @@ -272,14 +272,14 @@ struct wl_profile { struct net_info { struct net_device *ndev; struct wireless_dev *wdev; - struct wl_profile profile; /* holding dongle profile */ + struct wl_profile profile; s32 mode; unsigned long sme_state; struct list_head list; /* list of all net_info structure */ }; typedef s32(*ISCAN_HANDLER) (struct wl_priv *wl); -/* dongle iscan controller */ +/* iscan controller */ struct wl_iscan_ctrl { struct net_device *dev; struct timer_list timer; @@ -366,20 +366,34 @@ struct sta_info { u32 probe_req_ie_len; u32 assoc_req_ie_len; }; -/* dongle private data of cfg80211 interface */ + +struct afx_hdl { + wl_af_params_t *pending_tx_act_frm; + struct ether_addr pending_tx_dst_addr; + struct net_device *dev; + struct work_struct work; + u32 bssidx; + u32 retry; + s32 peer_chan; + bool ack_recv; +}; + +/* private data of cfg80211 interface */ struct wl_priv { struct wireless_dev *wdev; /* representing wl cfg80211 device */ struct wireless_dev *p2p_wdev; /* representing wl cfg80211 device for P2P */ struct net_device *p2p_net; /* reference to p2p0 interface */ - struct wl_conf *conf; /* dongle configuration */ + struct wl_conf *conf; struct cfg80211_scan_request *scan_request; /* scan request object */ EVENT_HANDLER evt_handler[WLC_E_LAST]; struct list_head eq_list; /* used for event queue */ struct list_head net_list; /* used for struct net_info */ spinlock_t eq_lock; /* for event queue synchronization */ - struct mutex usr_sync; /* maily for dongle up/down synchronization */ + spinlock_t cfgdrv_lock; /* to protect scan status (and others if needed) */ + struct completion act_frm_scan; + struct mutex usr_sync; /* maily for up/down synchronization */ struct wl_scan_results *bss_list; struct wl_scan_results *scan_results; @@ -392,8 +406,6 @@ struct wl_priv { /* association information container */ struct wl_connect_info conn_info; - /* control firwmare and nvram paramter downloading */ - struct wl_fw_ctrl *fw; struct wl_pmk_list *pmk_list; /* wpa2 pmk list */ tsk_ctl_t event_tsk; /* task of main event handler thread */ void *pub; @@ -407,12 +419,12 @@ struct wl_priv { bool ibss_starter; /* indicates this sta is ibss starter */ bool link_up; /* link/connection up flag */ - /* indicate whether dongle to support power save mode */ + /* indicate whether chip to support power save mode */ bool pwr_save; - bool dongle_up; /* indicate whether dongle up or not */ - bool roam_on; /* on/off switch for dongle self-roaming */ + bool roam_on; /* on/off switch for self-roaming */ bool scan_tried; /* indicates if first scan attempted */ - u8 *ioctl_buf; /* ioctl buffer */ + u8 *ioctl_buf; /* ioctl buffer */ + struct mutex ioctl_buf_sync; u8 *escan_ioctl_buf; u8 *extra_buf; /* maily to grab assoc information */ struct dentry *debugfsdir; @@ -420,8 +432,10 @@ struct wl_priv { bool rf_blocked; struct ieee80211_channel remain_on_chan; enum nl80211_channel_type remain_on_chan_type; + u64 send_action_id; u64 last_roc_id; - wait_queue_head_t dongle_event_wait; + wait_queue_head_t netif_change_event; + struct afx_hdl *afx_hdl; struct ap_info *ap_info; struct sta_info *sta_info; struct p2p_info *p2p; @@ -474,6 +488,7 @@ wl_dealloc_netinfo(struct wl_priv *wl, struct net_device *ndev) } } } + static inline void wl_delete_all_netinfo(struct wl_priv *wl) { @@ -611,28 +626,24 @@ wl_get_profile_by_netdev(struct wl_priv *wl, struct net_device *ndev) (!_sme->crypto.cipher_group)) extern s32 wl_cfg80211_attach(struct net_device *ndev, void *data); extern s32 wl_cfg80211_attach_post(struct net_device *ndev); -extern void wl_cfg80211_detach(void); -/* event handler from dongle */ +extern void wl_cfg80211_detach(void *para); + extern void wl_cfg80211_event(struct net_device *ndev, const wl_event_msg_t *e, void *data); void wl_cfg80211_set_parent_dev(void *dev); struct device *wl_cfg80211_get_parent_dev(void); -extern s32 wl_cfg80211_up(void); /* dongle up */ -extern s32 wl_cfg80211_down(void); /* dongle down */ -extern s32 wl_cfg80211_notify_ifadd(struct net_device *net, s32 idx, s32 bssidx, -int (*_net_attach)(dhd_pub_t *dhdp, int ifidx)); +extern s32 wl_cfg80211_up(void *para); +extern s32 wl_cfg80211_down(void *para); +extern s32 wl_cfg80211_notify_ifadd(struct net_device *ndev, s32 idx, s32 bssidx, + void* _net_attach); +extern s32 wl_cfg80211_ifdel_ops(struct net_device *net); extern s32 wl_cfg80211_notify_ifdel(struct net_device *ndev); extern s32 wl_cfg80211_is_progress_ifadd(void); extern s32 wl_cfg80211_is_progress_ifchange(void); extern s32 wl_cfg80211_is_progress_ifadd(void); extern s32 wl_cfg80211_notify_ifchange(void); extern void wl_cfg80211_dbg_level(u32 level); -extern void *wl_cfg80211_request_fw(s8 *file_name); -extern s32 wl_cfg80211_read_fw(s8 *buf, u32 size); -extern void wl_cfg80211_release_fw(void); -extern s8 *wl_cfg80211_get_fwname(void); -extern s8 *wl_cfg80211_get_nvramname(void); extern s32 wl_cfg80211_get_p2p_dev_addr(struct net_device *net, struct ether_addr *p2pdev_addr); extern s32 wl_cfg80211_set_p2p_noa(struct net_device *net, char* buf, int len); extern s32 wl_cfg80211_get_p2p_noa(struct net_device *net, char* buf, int len); @@ -641,11 +652,11 @@ extern s32 wl_cfg80211_set_wps_p2p_ie(struct net_device *net, char *buf, int len extern s32 wl_cfg80211_set_p2p_ps(struct net_device *net, char* buf, int len); extern int wl_cfg80211_hang(struct net_device *dev, u16 reason); extern s32 wl_mode_to_nl80211_iftype(s32 mode); +int wl_cfg80211_do_driver_init(struct net_device *net); +void wl_cfg80211_enable_trace(int level); /* do scan abort */ -extern s32 -wl_cfg80211_scan_abort(struct wl_priv *wl, struct net_device *ndev); +extern s32 wl_cfg80211_scan_abort(struct wl_priv *wl, struct net_device *ndev); -extern s32 -wl_cfg80211_if_is_group_owner(void); +extern s32 wl_cfg80211_if_is_group_owner(void); #endif /* _wl_cfg80211_h_ */ diff --git a/drivers/net/wireless/bcmdhd/wl_cfgp2p.c b/drivers/net/wireless/bcmdhd/wl_cfgp2p.c index 85c36101ab41..6991a9d78559 100644 --- a/drivers/net/wireless/bcmdhd/wl_cfgp2p.c +++ b/drivers/net/wireless/bcmdhd/wl_cfgp2p.c @@ -30,6 +30,7 @@ #include #include #include +#include #include #include #include @@ -39,25 +40,19 @@ #include #include #include -#include -#include -#include -#include #include #include #include #include -static s8 ioctlbuf[WLC_IOCTL_MAXLEN]; static s8 scanparambuf[WLC_IOCTL_SMLEN]; -static s8 *smbuf = ioctlbuf; static bool wl_cfgp2p_has_ie(u8 *ie, u8 **tlvs, u32 *tlvs_len, const u8 *oui, u32 oui_len, u8 type); static s32 -wl_cfgp2p_vndr_ie(struct net_device *ndev, s32 bssidx, s32 pktflag, +wl_cfgp2p_vndr_ie(struct wl_priv *wl, struct net_device *ndev, s32 bssidx, s32 pktflag, s8 *oui, s32 ie_id, s8 *data, s32 data_len, s32 delete); static int wl_cfgp2p_start_xmit(struct sk_buff *skb, struct net_device *ndev); @@ -123,6 +118,8 @@ wl_cfgp2p_init_priv(struct wl_priv *wl) void wl_cfgp2p_deinit_priv(struct wl_priv *wl) { + CFGP2P_DBG(("In\n")); + if (wl->p2p) { kfree(wl->p2p); wl->p2p = NULL; @@ -155,7 +152,7 @@ wl_cfgp2p_set_firm_p2p(struct wl_priv *wl) * firmware for P2P device address */ ret = wldev_iovar_setbuf_bsscfg(ndev, "p2p_da_override", &null_eth_addr, - sizeof(null_eth_addr), ioctlbuf, sizeof(ioctlbuf), 0); + sizeof(null_eth_addr), wl->ioctl_buf, WLC_IOCTL_MAXLEN, 0, &wl->ioctl_buf_sync); if (ret && ret != BCME_UNSUPPORTED) { CFGP2P_ERR(("failed to update device address\n")); } @@ -181,14 +178,14 @@ wl_cfgp2p_ifadd(struct wl_priv *wl, struct ether_addr *mac, u8 if_type, ifreq.chspec = chspec; memcpy(ifreq.addr.octet, mac->octet, sizeof(ifreq.addr.octet)); - CFGP2P_INFO(("---wl p2p_ifadd %02x:%02x:%02x:%02x:%02x:%02x %s %u\n", + CFGP2P_DBG(("---wl p2p_ifadd %02x:%02x:%02x:%02x:%02x:%02x %s %u\n", ifreq.addr.octet[0], ifreq.addr.octet[1], ifreq.addr.octet[2], ifreq.addr.octet[3], ifreq.addr.octet[4], ifreq.addr.octet[5], (if_type == WL_P2P_IF_GO) ? "go" : "client", (chspec & WL_CHANSPEC_CHAN_MASK) >> WL_CHANSPEC_CHAN_SHIFT)); err = wldev_iovar_setbuf(ndev, "p2p_ifadd", &ifreq, sizeof(ifreq), - ioctlbuf, sizeof(ioctlbuf)); + wl->ioctl_buf, WLC_IOCTL_MAXLEN, &wl->ioctl_buf_sync); return err; } @@ -207,7 +204,7 @@ wl_cfgp2p_ifdel(struct wl_priv *wl, struct ether_addr *mac) netdev->ifindex, mac->octet[0], mac->octet[1], mac->octet[2], mac->octet[3], mac->octet[4], mac->octet[5])); ret = wldev_iovar_setbuf(netdev, "p2p_ifdel", mac, sizeof(*mac), - ioctlbuf, sizeof(ioctlbuf)); + wl->ioctl_buf, WLC_IOCTL_MAXLEN, &wl->ioctl_buf_sync); if (unlikely(ret < 0)) { printk("'wl p2p_ifdel' error %d\n", ret); } @@ -238,7 +235,7 @@ wl_cfgp2p_ifchange(struct wl_priv *wl, struct ether_addr *mac, u8 if_type, (chspec & WL_CHANSPEC_CHAN_MASK) >> WL_CHANSPEC_CHAN_SHIFT)); err = wldev_iovar_setbuf(netdev, "p2p_ifupd", &ifreq, sizeof(ifreq), - ioctlbuf, sizeof(ioctlbuf)); + wl->ioctl_buf, WLC_IOCTL_MAXLEN, &wl->ioctl_buf_sync); if (unlikely(err < 0)) { printk("'wl p2p_ifupd' error %d\n", err); @@ -264,8 +261,8 @@ wl_cfgp2p_ifidx(struct wl_priv *wl, struct ether_addr *mac, s32 *index) mac->octet[0], mac->octet[1], mac->octet[2], mac->octet[3], mac->octet[4], mac->octet[5])); - ret = wldev_iovar_getbuf_bsscfg(dev, "p2p_if", mac, sizeof(*mac), - getbuf, sizeof(getbuf), wl_to_p2p_bss_bssidx(wl, P2PAPI_BSSCFG_PRIMARY)); + ret = wldev_iovar_getbuf_bsscfg(dev, "p2p_if", mac, sizeof(*mac), getbuf, + sizeof(getbuf), wl_to_p2p_bss_bssidx(wl, P2PAPI_BSSCFG_PRIMARY), NULL); if (ret == 0) { memcpy(index, getbuf, sizeof(index)); @@ -275,7 +272,7 @@ wl_cfgp2p_ifidx(struct wl_priv *wl, struct ether_addr *mac, s32 *index) return ret; } -s32 +static s32 wl_cfgp2p_set_discovery(struct wl_priv *wl, s32 on) { s32 ret = BCME_OK; @@ -324,13 +321,14 @@ wl_cfgp2p_set_p2p_mode(struct wl_priv *wl, u8 mode, u32 channel, u16 listen_ms, discovery_mode.chspec = CH20MHZ_CHSPEC(channel); discovery_mode.dwell = listen_ms; ret = wldev_iovar_setbuf_bsscfg(dev, "p2p_state", &discovery_mode, - sizeof(discovery_mode), ioctlbuf, sizeof(ioctlbuf), bssidx); + sizeof(discovery_mode), wl->ioctl_buf, WLC_IOCTL_MAXLEN, + bssidx, &wl->ioctl_buf_sync); return ret; } /* Get the index of the P2P Discovery BSS */ -s32 +static s32 wl_cfgp2p_get_disc_idx(struct wl_priv *wl, s32 *index) { s32 ret; @@ -394,7 +392,7 @@ wl_cfgp2p_init_discovery(struct wl_priv *wl) * @wl : wl_private data * Returns 0 if succes */ -s32 +static s32 wl_cfgp2p_deinit_discovery(struct wl_priv *wl) { s32 ret = BCME_OK; @@ -432,7 +430,8 @@ wl_cfgp2p_deinit_discovery(struct wl_priv *wl) * Returns 0 if success. */ s32 -wl_cfgp2p_enable_discovery(struct wl_priv *wl, struct net_device *dev, const u8 *ie, u32 ie_len) +wl_cfgp2p_enable_discovery(struct wl_priv *wl, struct net_device *dev, + const u8 *ie, u32 ie_len) { s32 ret = BCME_OK; if (wl_get_p2p_status(wl, DISCOVERY_ON)) { @@ -524,9 +523,9 @@ wl_cfgp2p_escan(struct wl_priv *wl, struct net_device *dev, u16 active, wl_escan_params_t *eparams; wlc_ssid_t ssid; /* Scan parameters */ -#define P2PAPI_SCAN_NPROBES 4 -#define P2PAPI_SCAN_DWELL_TIME_MS 80 -#define P2PAPI_SCAN_SOCIAL_DWELL_TIME_MS 100 +#define P2PAPI_SCAN_NPROBES 1 +#define P2PAPI_SCAN_DWELL_TIME_MS 50 +#define P2PAPI_SCAN_SOCIAL_DWELL_TIME_MS 40 #define P2PAPI_SCAN_HOME_TIME_MS 10 struct net_device *pri_dev = wl_to_p2p_bss_ndev(wl, P2PAPI_BSSCFG_PRIMARY); wl_set_p2p_status(wl, SCANNING); @@ -543,7 +542,7 @@ wl_cfgp2p_escan(struct wl_priv *wl, struct net_device *dev, u16 active, return -1; } memset(memblk, 0, memsize); - memset(ioctlbuf, 0, sizeof(ioctlbuf)); + memset(wl->ioctl_buf, 0, WLC_IOCTL_MAXLEN); if (search_state == WL_P2P_DISC_ST_SEARCH) { /* * If we in SEARCH STATE, we don't need to set SSID explictly @@ -608,9 +607,54 @@ wl_cfgp2p_escan(struct wl_priv *wl, struct net_device *dev, u16 active, CFGP2P_INFO(("\n")); ret = wldev_iovar_setbuf_bsscfg(pri_dev, "p2p_scan", - memblk, memsize, smbuf, sizeof(ioctlbuf), bssidx); + memblk, memsize, wl->ioctl_buf, WLC_IOCTL_MAXLEN, bssidx, &wl->ioctl_buf_sync); + return ret; +} + +/* search function to reach at common channel to send action frame + * Parameters: + * @wl : wl_private data + * @ndev : net device for bssidx + * @bssidx : bssidx for BSS + * Returns 0 if success. + */ +s32 +wl_cfgp2p_act_frm_search(struct wl_priv *wl, struct net_device *ndev, + s32 bssidx, s32 channel) +{ + s32 ret = 0; + u32 chan_cnt = 0; + u16 *default_chan_list = NULL; + if (!p2p_is_on(wl)) + return -BCME_ERROR; + CFGP2P_ERR((" Enter\n")); + if (bssidx == P2PAPI_BSSCFG_PRIMARY) + bssidx = wl_to_p2p_bss_bssidx(wl, P2PAPI_BSSCFG_DEVICE); + if (channel) + chan_cnt = 1; + else + chan_cnt = SOCIAL_CHAN_CNT; + default_chan_list = kzalloc(chan_cnt * sizeof(*default_chan_list), GFP_KERNEL); + if (default_chan_list == NULL) { + CFGP2P_ERR(("channel list allocation failed \n")); + ret = -ENOMEM; + goto exit; + } + if (channel) { + default_chan_list[0] = channel; + } else { + default_chan_list[0] = SOCIAL_CHAN_1; + default_chan_list[1] = SOCIAL_CHAN_2; + default_chan_list[2] = SOCIAL_CHAN_3; + } + ret = wl_cfgp2p_escan(wl, ndev, true, SOCIAL_CHAN_CNT, + default_chan_list, WL_P2P_DISC_ST_SEARCH, + WL_SCAN_ACTION_START, bssidx); + kfree(default_chan_list); +exit: return ret; } + /* Check whether pointed-to IE looks like WPA. */ #define wl_cfgp2p_is_wpa_ie(ie, tlvs, len) wl_cfgp2p_has_ie(ie, tlvs, len, \ (const uint8 *)WPS_OUI, WPS_OUI_LEN, WPA_OUI_TYPE) @@ -648,7 +692,7 @@ wl_cfgp2p_set_management_ie(struct wl_priv *wl, struct net_device *ndev, s32 bss u8 delete = 0; #define IE_TYPE(type, bsstype) (wl_to_p2p_bss_saved_ie(wl, bsstype).p2p_ ## type ## _ie) #define IE_TYPE_LEN(type, bsstype) (wl_to_p2p_bss_saved_ie(wl, bsstype).p2p_ ## type ## _ie_len) - if (wl->p2p_supported && p2p_on(wl) && bssidx != -1) { + if (p2p_is_on(wl) && bssidx != -1) { if (bssidx == P2PAPI_BSSCFG_PRIMARY) bssidx = wl_to_p2p_bss_bssidx(wl, P2PAPI_BSSCFG_DEVICE); switch (pktflag) { @@ -748,8 +792,9 @@ wl_cfgp2p_set_management_ie(struct wl_priv *wl, struct net_device *ndev, s32 bss CFGP2P_INFO(("DELELED ID : %d, Len : %d , OUI :" "%02x:%02x:%02x\n", ie_id, ie_len, ie_buf[pos], ie_buf[pos+1], ie_buf[pos+2])); - ret = wl_cfgp2p_vndr_ie(ndev, bssidx, pktflag, ie_buf+pos, - VNDR_SPEC_ELEMENT_ID, ie_buf+pos+3, ie_len-3, delete); + ret = wl_cfgp2p_vndr_ie(wl, ndev, bssidx, pktflag, + ie_buf+pos, VNDR_SPEC_ELEMENT_ID, ie_buf+pos+3, + ie_len-3, delete); } pos += ie_len; } @@ -773,8 +818,9 @@ wl_cfgp2p_set_management_ie(struct wl_priv *wl, struct net_device *ndev, s32 bss CFGP2P_INFO(("ADDED ID : %d, Len : %d , OUI :" "%02x:%02x:%02x\n", ie_id, ie_len, ie_buf[pos], ie_buf[pos+1], ie_buf[pos+2])); - ret = wl_cfgp2p_vndr_ie(ndev, bssidx, pktflag, ie_buf+pos, - VNDR_SPEC_ELEMENT_ID, ie_buf+pos+3, ie_len-3, delete); + ret = wl_cfgp2p_vndr_ie(wl, ndev, bssidx, pktflag, + ie_buf+pos, VNDR_SPEC_ELEMENT_ID, ie_buf+pos+3, + ie_len-3, delete); } pos += ie_len; } @@ -880,7 +926,7 @@ wl_cfgp2p_find_p2pie(u8 *parse, u32 len) } static s32 -wl_cfgp2p_vndr_ie(struct net_device *ndev, s32 bssidx, s32 pktflag, +wl_cfgp2p_vndr_ie(struct wl_priv *wl, struct net_device *ndev, s32 bssidx, s32 pktflag, s8 *oui, s32 ie_id, s8 *data, s32 data_len, s32 delete) { s32 err = BCME_OK; @@ -922,7 +968,7 @@ wl_cfgp2p_vndr_ie(struct net_device *ndev, s32 bssidx, s32 pktflag, memcpy(ie_setbuf->vndr_ie_buffer.vndr_ie_list[0].vndr_ie_data.oui, oui, 3); memcpy(ie_setbuf->vndr_ie_buffer.vndr_ie_list[0].vndr_ie_data.data, data, data_len); err = wldev_iovar_setbuf_bsscfg(ndev, "vndr_ie", ie_setbuf, buf_len, - ioctlbuf, sizeof(ioctlbuf), bssidx); + wl->ioctl_buf, WLC_IOCTL_MAXLEN, bssidx, &wl->ioctl_buf_sync); CFGP2P_INFO(("vndr_ie iovar returns %d\n", err)); kfree(ie_setbuf); @@ -1106,10 +1152,10 @@ wl_cfgp2p_action_tx_complete(struct wl_priv *wl, struct net_device *ndev, wl_set_p2p_status(wl, ACTION_TX_NOACK); CFGP2P_ERR(("WLC_E_ACTION_FRAME_COMPLETE : NO ACK\n")); } - wake_up_interruptible(&wl->dongle_event_wait); } else { CFGP2P_INFO((" WLC_E_ACTION_FRAME_OFFCHAN_COMPLETE is received," "status : %d\n", status)); + wake_up_interruptible(&wl->netif_change_event); } return ret; } @@ -1139,15 +1185,15 @@ wl_cfgp2p_tx_action_frame(struct wl_priv *wl, struct net_device *dev, if (bssidx == P2PAPI_BSSCFG_PRIMARY) bssidx = wl_to_p2p_bss_bssidx(wl, P2PAPI_BSSCFG_DEVICE); - ret = wldev_iovar_setbuf_bsscfg(dev, "actframe", - af_params, sizeof(*af_params), ioctlbuf, sizeof(ioctlbuf), bssidx); + ret = wldev_iovar_setbuf_bsscfg(dev, "actframe", af_params, sizeof(*af_params), + wl->ioctl_buf, WLC_IOCTL_MAXLEN, bssidx, &wl->ioctl_buf_sync); if (ret < 0) { CFGP2P_ERR((" sending action frame is failed\n")); goto exit; } - timeout = wait_event_interruptible_timeout(wl->dongle_event_wait, + timeout = wait_event_interruptible_timeout(wl->netif_change_event, (wl_get_p2p_status(wl, ACTION_TX_COMPLETED) || wl_get_p2p_status(wl, ACTION_TX_NOACK)), msecs_to_jiffies(MAX_WAIT_TIME)); @@ -1256,7 +1302,7 @@ wl_cfgp2p_bss_isup(struct net_device *ndev, int bsscfg_idx) /* Check if the BSS is up */ *(int*)getbuf = -1; result = wldev_iovar_getbuf_bsscfg(ndev, "bss", &bsscfg_idx, - sizeof(bsscfg_idx), getbuf, sizeof(getbuf), 0); + sizeof(bsscfg_idx), getbuf, sizeof(getbuf), 0, NULL); if (result != 0) { CFGP2P_ERR(("'wl bss -C %d' failed: %d\n", bsscfg_idx, result)); CFGP2P_ERR(("NOTE: this ioctl error is normal " @@ -1273,7 +1319,7 @@ wl_cfgp2p_bss_isup(struct net_device *ndev, int bsscfg_idx) /* Bring up or down a BSS */ s32 -wl_cfgp2p_bss(struct net_device *ndev, s32 bsscfg_idx, s32 up) +wl_cfgp2p_bss(struct wl_priv *wl, struct net_device *ndev, s32 bsscfg_idx, s32 up) { s32 ret = BCME_OK; s32 val = up ? 1 : 0; @@ -1287,7 +1333,7 @@ wl_cfgp2p_bss(struct net_device *ndev, s32 bsscfg_idx, s32 up) bss_setbuf.val = htod32(val); CFGP2P_INFO(("---wl bss -C %d %s\n", bsscfg_idx, up ? "up" : "down")); ret = wldev_iovar_setbuf(ndev, "bss", &bss_setbuf, sizeof(bss_setbuf), - ioctlbuf, sizeof(ioctlbuf)); + wl->ioctl_buf, WLC_IOCTL_MAXLEN, &wl->ioctl_buf_sync); if (ret != 0) { CFGP2P_ERR(("'bss %d' failed with %d\n", up, ret)); @@ -1343,7 +1389,7 @@ s32 wl_cfgp2p_set_p2p_noa(struct wl_priv *wl, struct net_device *ndev, char* buf sscanf(buf, "%d %d %d", &count, &start, &duration); CFGP2P_DBG(("set_p2p_noa count %d start %d duration %d\n", - count, start, duration)); + count, start, duration)); if (count != -1) wl->p2p->noa.desc[0].count = count; @@ -1387,7 +1433,8 @@ s32 wl_cfgp2p_set_p2p_noa(struct wl_priv *wl, struct net_device *ndev, char* buf dongle_noa.desc[0].interval = htod32(wl->p2p->noa.desc[0].interval*1000); ret = wldev_iovar_setbuf(wl_to_p2p_bss_ndev(wl, P2PAPI_BSSCFG_CONNECTION), - "p2p_noa", &dongle_noa, sizeof(dongle_noa), ioctlbuf, sizeof(ioctlbuf)); + "p2p_noa", &dongle_noa, sizeof(dongle_noa), wl->ioctl_buf, WLC_IOCTL_MAXLEN, + &wl->ioctl_buf_sync); if (ret < 0) { CFGP2P_ERR(("fw set p2p_noa failed %d\n", ret)); @@ -1459,7 +1506,7 @@ s32 wl_cfgp2p_set_p2p_ps(struct wl_priv *wl, struct net_device *ndev, char* buf, wl->p2p->ops.ops = ps; ret = wldev_iovar_setbuf(wl_to_p2p_bss_ndev(wl, P2PAPI_BSSCFG_CONNECTION), "p2p_ops", &wl->p2p->ops, sizeof(wl->p2p->ops), - ioctlbuf, sizeof(ioctlbuf)); + wl->ioctl_buf, WLC_IOCTL_MAXLEN, &wl->ioctl_buf_sync); if (ret < 0) { CFGP2P_ERR(("fw set p2p_ops failed %d\n", ret)); } @@ -1481,6 +1528,96 @@ s32 wl_cfgp2p_set_p2p_ps(struct wl_priv *wl, struct net_device *ndev, char* buf, return ret; } +u8 * +wl_cfgp2p_retreive_p2pattrib(void *buf, u8 element_id) +{ + wifi_p2p_ie_t *ie = NULL; + u16 len = 0; + u8 *subel; + u8 subelt_id; + u16 subelt_len; + + if (!buf) { + WL_ERR(("P2P IE not present")); + return 0; + } + + ie = (wifi_p2p_ie_t*) buf; + len = ie->len; + + /* Point subel to the P2P IE's subelt field. + * Subtract the preceding fields (id, len, OUI, oui_type) from the length. + */ + subel = ie->subelts; + len -= 4; /* exclude OUI + OUI_TYPE */ + + while (len >= 3) { + /* attribute id */ + subelt_id = *subel; + subel += 1; + len -= 1; + + /* 2-byte little endian */ + subelt_len = *subel++; + subelt_len |= *subel++ << 8; + + len -= 2; + len -= subelt_len; /* for the remaining subelt fields */ + + if (subelt_id == element_id) { + /* This will point to start of subelement attrib after + * attribute id & len + */ + return subel; + } + + /* Go to next subelement */ + subel += subelt_len; + } + + /* Not Found */ + return NULL; +} + +#define P2P_GROUP_CAPAB_GO_BIT 0x01 +u8 * +wl_cfgp2p_retreive_p2p_dev_addr(wl_bss_info_t *bi, u32 bi_length) +{ + wifi_p2p_ie_t * p2p_ie = NULL; + u8 *capability = NULL; + bool p2p_go = 0; + u8 *ptr = NULL; + + if (!(p2p_ie = wl_cfgp2p_find_p2pie(((u8 *) bi) + bi->ie_offset, bi->ie_length))) { + WL_ERR(("P2P IE not found")); + return NULL; + } + + if (!(capability = wl_cfgp2p_retreive_p2pattrib(p2p_ie, P2P_SEID_P2P_INFO))) { + WL_ERR(("P2P Capability attribute not found")); + return NULL; + } + + /* Check Group capability for Group Owner bit */ + p2p_go = capability[1] & P2P_GROUP_CAPAB_GO_BIT; + if (!p2p_go) { + return bi->BSSID.octet; + } + + /* In probe responses, DEVICE INFO attribute will be present */ + if (!(ptr = wl_cfgp2p_retreive_p2pattrib(p2p_ie, P2P_SEID_DEV_INFO))) { + /* If DEVICE_INFO is not found, this might be a beacon frame. + * check for DEVICE_ID in the beacon frame. + */ + ptr = wl_cfgp2p_retreive_p2pattrib(p2p_ie, P2P_SEID_DEV_ID); + } + + if (!ptr) + WL_ERR((" Both DEVICE_ID & DEVICE_INFO attribute not present in P2P IE ")); + + return ptr; +} + s32 wl_cfgp2p_register_ndev(struct wl_priv *wl) { @@ -1613,12 +1750,34 @@ static int wl_cfgp2p_do_ioctl(struct net_device *net, struct ifreq *ifr, int cmd static int wl_cfgp2p_if_open(struct net_device *net) { - CFGP2P_DBG(("Do Nothing \n")); + struct wireless_dev *wdev = net->ieee80211_ptr; + + if (!wdev) + return -EINVAL; + + /* If suppose F/W download (ifconfig wlan0 up) hasn't been done by now, + * do it here. This will make sure that in concurrent mode, supplicant + * is not dependent on a particular order of interface initialization. + * i.e you may give wpa_supp -iwlan0 -N -ip2p0 or wpa_supp -ip2p0 -N + * -iwlan0. + */ + wl_cfg80211_do_driver_init(net); + + wdev->wiphy->interface_modes |= (BIT(NL80211_IFTYPE_P2P_CLIENT) + | BIT(NL80211_IFTYPE_P2P_GO)); + return 0; } static int wl_cfgp2p_if_stop(struct net_device *net) { - CFGP2P_DBG(("Do Nothing \n")); + struct wireless_dev *wdev = net->ieee80211_ptr; + + if (!wdev) + return -EINVAL; + + wdev->wiphy->interface_modes = (wdev->wiphy->interface_modes) + & (~(BIT(NL80211_IFTYPE_P2P_CLIENT)| + BIT(NL80211_IFTYPE_P2P_GO))); return 0; } diff --git a/drivers/net/wireless/bcmdhd/wl_cfgp2p.h b/drivers/net/wireless/bcmdhd/wl_cfgp2p.h index 6934d8f1c9be..d50b00f8394c 100644 --- a/drivers/net/wireless/bcmdhd/wl_cfgp2p.h +++ b/drivers/net/wireless/bcmdhd/wl_cfgp2p.h @@ -107,7 +107,7 @@ enum wl_cfgp2p_status { &(wl)->p2p->status)) #define wl_clr_p2p_status(wl, stat) ((!(wl)->p2p_supported) ? 0 : clear_bit(WLP2P_STATUS_ ## stat, \ &(wl)->p2p->status)) -#define wl_chg_p2p_status(wl, stat) ((!(wl)->p2p_supported) ? 0 : change_bit(WLP2P_STATUS_ ## stat, \ +#define wl_chg_p2p_status(wl, stat) ((!(wl)->p2p_supported) ? 0: change_bit(WLP2P_STATUS_ ## stat, \ &(wl)->p2p->status)) #define p2p_on(wl) ((wl)->p2p->on) #define p2p_scan(wl) ((wl)->p2p->scan) @@ -172,6 +172,10 @@ wl_cfgp2p_escan(struct wl_priv *wl, struct net_device *dev, u16 active, u32 num_ u16 *channels, s32 search_state, u16 action, u32 bssidx); +extern s32 +wl_cfgp2p_act_frm_search(struct wl_priv *wl, struct net_device *ndev, + s32 bssidx, s32 channel); + extern wpa_ie_fixed_t * wl_cfgp2p_find_wpaie(u8 *parse, u32 len); @@ -217,7 +221,7 @@ extern bool wl_cfgp2p_bss_isup(struct net_device *ndev, int bsscfg_idx); extern s32 -wl_cfgp2p_bss(struct net_device *ndev, s32 bsscfg_idx, s32 up); +wl_cfgp2p_bss(struct wl_priv *wl, struct net_device *ndev, s32 bsscfg_idx, s32 up); extern s32 @@ -235,6 +239,12 @@ wl_cfgp2p_get_p2p_noa(struct wl_priv *wl, struct net_device *ndev, char* buf, in extern s32 wl_cfgp2p_set_p2p_ps(struct wl_priv *wl, struct net_device *ndev, char* buf, int len); +extern u8 * +wl_cfgp2p_retreive_p2pattrib(void *buf, u8 element_id); + +extern u8 * +wl_cfgp2p_retreive_p2p_dev_addr(wl_bss_info_t *bi, u32 bi_length); + extern s32 wl_cfgp2p_register_ndev(struct wl_priv *wl); @@ -245,9 +255,22 @@ wl_cfgp2p_unregister_ndev(struct wl_priv *wl); #define SOCIAL_CHAN_1 1 #define SOCIAL_CHAN_2 6 #define SOCIAL_CHAN_3 11 +#define SOCIAL_CHAN_CNT 3 #define WL_P2P_WILDCARD_SSID "DIRECT-" #define WL_P2P_WILDCARD_SSID_LEN 7 #define WL_P2P_INTERFACE_PREFIX "p2p" #define WL_P2P_TEMP_CHAN "11" +#define IS_PUB_ACT_FRAME(category) ((category == P2P_PUB_AF_CATEGORY)) +#define IS_P2P_ACT_FRAME(category) ((category == P2P_AF_CATEGORY)) + +#define IS_P2P_ACTION(categry, action) (IS_PUB_ACT_FRAME(category) && (action == P2P_PUB_AF_ACTION)) +#define IS_GAS_REQ(category, action) (IS_PUB_ACT_FRAME(category) && \ + ((action == P2PSD_ACTION_ID_GAS_IREQ) || \ + (action == P2PSD_ACTION_ID_GAS_CREQ))) +#define IS_P2P_ACT_REQ(category, subtype) (IS_PUB_ACT_FRAME(category) && \ + ((subtype == P2P_PAF_GON_REQ) || \ + (subtype == P2P_PAF_INVITE_REQ) || \ + (subtype == P2P_PAF_PROVDIS_REQ))) +#define IS_P2P_SOCIAL(ch) ((ch == SOCIAL_CHAN_1) || (ch == SOCIAL_CHAN_2) || (ch == SOCIAL_CHAN_3)) #define IS_P2P_SSID(ssid) (memcmp(ssid, WL_P2P_WILDCARD_SSID, WL_P2P_WILDCARD_SSID_LEN) == 0) #endif /* _wl_cfgp2p_h_ */ diff --git a/drivers/net/wireless/bcmdhd/wl_linux_mon.c b/drivers/net/wireless/bcmdhd/wl_linux_mon.c new file mode 100644 index 000000000000..f44b4b04bb96 --- /dev/null +++ b/drivers/net/wireless/bcmdhd/wl_linux_mon.c @@ -0,0 +1,409 @@ +/* + * Broadcom Dongle Host Driver (DHD), Linux monitor network interface + * + * Copyright (C) 1999-2011, Broadcom Corporation + * + * Unless you and Broadcom execute a separate written software license + * agreement governing use of this software, this software is licensed to you + * under the terms of the GNU General Public License version 2 (the "GPL"), + * available at http://www.broadcom.com/licenses/GPLv2.php, with the + * following added to such license: + * + * As a special exception, the copyright holders of this software give you + * permission to link this software with independent modules, and to copy and + * distribute the resulting executable under terms of your choice, provided that + * you also meet, for each linked independent module, the terms and conditions of + * the license of that module. An independent module is a module which is not + * derived from this software. The special exception does not apply to any + * modifications of the software. + * + * Notwithstanding the above, under no circumstances may you combine this + * software in any way with any other Broadcom software provided under a license + * other than the GPL, without Broadcom's express prior written consent. + * + * $Id: wl_linux_mon.c 303266 2011-12-16 00:15:23Z $ + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +typedef enum monitor_states +{ + MONITOR_STATE_DEINIT = 0x0, + MONITOR_STATE_INIT = 0x1, + MONITOR_STATE_INTERFACE_ADDED = 0x2, + MONITOR_STATE_INTERFACE_DELETED = 0x4 +} monitor_states_t; +extern int dhd_start_xmit(struct sk_buff *skb, struct net_device *net); + +/** + * Local declarations and defintions (not exposed) + */ +#define MON_PRINT(format, ...) printk("DHD-MON: %s " format, __func__, ##__VA_ARGS__) +#define MON_TRACE MON_PRINT + +typedef struct monitor_interface { + int radiotap_enabled; + struct net_device* real_ndev; /* The real interface that the monitor is on */ + struct net_device* mon_ndev; +} monitor_interface; + +typedef struct dhd_linux_monitor { + void *dhd_pub; + monitor_states_t monitor_state; + monitor_interface mon_if[DHD_MAX_IFS]; + struct mutex lock; /* lock to protect mon_if */ +} dhd_linux_monitor_t; + +static dhd_linux_monitor_t g_monitor; + +static struct net_device* lookup_real_netdev(char *name); +static monitor_interface* ndev_to_monif(struct net_device *ndev); +static int dhd_mon_if_open(struct net_device *ndev); +static int dhd_mon_if_stop(struct net_device *ndev); +static int dhd_mon_if_subif_start_xmit(struct sk_buff *skb, struct net_device *ndev); +static void dhd_mon_if_set_multicast_list(struct net_device *ndev); +static int dhd_mon_if_change_mac(struct net_device *ndev, void *addr); + +static const struct net_device_ops dhd_mon_if_ops = { + .ndo_open = dhd_mon_if_open, + .ndo_stop = dhd_mon_if_stop, + .ndo_start_xmit = dhd_mon_if_subif_start_xmit, + .ndo_set_multicast_list = dhd_mon_if_set_multicast_list, + .ndo_set_mac_address = dhd_mon_if_change_mac, +}; + +/** + * Local static function defintions + */ + +/* Look up dhd's net device table to find a match (e.g. interface "eth0" is a match for "mon.eth0" + * "p2p-eth0-0" is a match for "mon.p2p-eth0-0") + */ +static struct net_device* lookup_real_netdev(char *name) +{ + int i; + int len = 0; + int last_name_len = 0; + struct net_device *ndev; + struct net_device *ndev_found = NULL; + + /* We need to find interface "p2p-p2p-0" corresponding to monitor interface "mon-p2p-0", + * Once mon iface name reaches IFNAMSIZ, it is reset to p2p0-0 and corresponding mon + * iface would be mon-p2p0-0. + */ + for (i = 0; i < DHD_MAX_IFS; i++) { + ndev = dhd_idx2net(g_monitor.dhd_pub, i); + + /* Skip "p2p" and look for "-p2p0-x" in monitor interface name. If it + * it matches, then this netdev is the corresponding real_netdev. + */ + if (ndev && strstr(ndev->name, "p2p-p2p0")) { + len = strlen("p2p"); + } else { + /* if p2p- is not present, then the IFNAMSIZ have reached and name + * would have got reset. In this casse,look for p2p0-x in mon-p2p0-x + */ + len = 0; + } + if (ndev && strstr(name, (ndev->name + len))) { + if (strlen(ndev->name) > last_name_len) { + ndev_found = ndev; + last_name_len = strlen(ndev->name); + } + } + } + + return ndev_found; +} + +static monitor_interface* ndev_to_monif(struct net_device *ndev) +{ + int i; + + for (i = 0; i < DHD_MAX_IFS; i++) { + if (g_monitor.mon_if[i].mon_ndev == ndev) + return &g_monitor.mon_if[i]; + } + + return NULL; +} + +static int dhd_mon_if_open(struct net_device *ndev) +{ + int ret = 0; + + MON_PRINT("enter\n"); + return ret; +} + +static int dhd_mon_if_stop(struct net_device *ndev) +{ + int ret = 0; + + MON_PRINT("enter\n"); + return ret; +} + +static int dhd_mon_if_subif_start_xmit(struct sk_buff *skb, struct net_device *ndev) +{ + int ret = 0; + int rtap_len; + int qos_len = 0; + int dot11_hdr_len = 24; + int snap_len = 6; + unsigned char *pdata; + unsigned short frame_ctl; + unsigned char src_mac_addr[6]; + unsigned char dst_mac_addr[6]; + struct ieee80211_hdr *dot11_hdr; + struct ieee80211_radiotap_header *rtap_hdr; + monitor_interface* mon_if; + + MON_PRINT("enter\n"); + + mon_if = ndev_to_monif(ndev); + if (mon_if == NULL || mon_if->real_ndev == NULL) { + MON_PRINT(" cannot find matched net dev, skip the packet\n"); + goto fail; + } + + if (unlikely(skb->len < sizeof(struct ieee80211_radiotap_header))) + goto fail; + + rtap_hdr = (struct ieee80211_radiotap_header *)skb->data; + if (unlikely(rtap_hdr->it_version)) + goto fail; + + rtap_len = ieee80211_get_radiotap_len(skb->data); + if (unlikely(skb->len < rtap_len)) + goto fail; + + MON_PRINT("radiotap len (should be 14): %d\n", rtap_len); + + /* Skip the ratio tap header */ + skb_pull(skb, rtap_len); + + dot11_hdr = (struct ieee80211_hdr *)skb->data; + frame_ctl = le16_to_cpu(dot11_hdr->frame_control); + /* Check if the QoS bit is set */ + if ((frame_ctl & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_DATA) { + /* Check if this ia a Wireless Distribution System (WDS) frame + * which has 4 MAC addresses + */ + if (dot11_hdr->frame_control & 0x0080) + qos_len = 2; + if ((dot11_hdr->frame_control & 0x0300) == 0x0300) + dot11_hdr_len += 6; + + memcpy(dst_mac_addr, dot11_hdr->addr1, sizeof(dst_mac_addr)); + memcpy(src_mac_addr, dot11_hdr->addr2, sizeof(src_mac_addr)); + + /* Skip the 802.11 header, QoS (if any) and SNAP, but leave spaces for + * for two MAC addresses + */ + skb_pull(skb, dot11_hdr_len + qos_len + snap_len - sizeof(src_mac_addr) * 2); + pdata = (unsigned char*)skb->data; + memcpy(pdata, dst_mac_addr, sizeof(dst_mac_addr)); + memcpy(pdata + sizeof(dst_mac_addr), src_mac_addr, sizeof(src_mac_addr)); + + MON_PRINT("if name: %s, matched if name %s\n", ndev->name, mon_if->real_ndev->name); + + /* Use the real net device to transmit the packet */ + ret = dhd_start_xmit(skb, mon_if->real_ndev); + + return ret; + } +fail: + dev_kfree_skb(skb); + return 0; +} + +static void dhd_mon_if_set_multicast_list(struct net_device *ndev) +{ + monitor_interface* mon_if; + + mon_if = ndev_to_monif(ndev); + if (mon_if == NULL || mon_if->real_ndev == NULL) { + MON_PRINT(" cannot find matched net dev, skip the packet\n"); + } else { + MON_PRINT("enter, if name: %s, matched if name %s\n", + ndev->name, mon_if->real_ndev->name); + } +} + +static int dhd_mon_if_change_mac(struct net_device *ndev, void *addr) +{ + int ret = 0; + monitor_interface* mon_if; + + mon_if = ndev_to_monif(ndev); + if (mon_if == NULL || mon_if->real_ndev == NULL) { + MON_PRINT(" cannot find matched net dev, skip the packet\n"); + } else { + MON_PRINT("enter, if name: %s, matched if name %s\n", + ndev->name, mon_if->real_ndev->name); + } + return ret; +} + +/** + * Global function definitions (declared in dhd_linux_mon.h) + */ + +int dhd_add_monitor(char *name, struct net_device **new_ndev) +{ + int i; + int idx = -1; + int ret = 0; + struct net_device* ndev = NULL; + dhd_linux_monitor_t **dhd_mon; + + mutex_lock(&g_monitor.lock); + + MON_TRACE("enter, if name: %s\n", name); + if (!name || !new_ndev) { + MON_PRINT("invalid parameters\n"); + ret = -EINVAL; + goto out; + } + + /* + * Find a vacancy + */ + for (i = 0; i < DHD_MAX_IFS; i++) + if (g_monitor.mon_if[i].mon_ndev == NULL) { + idx = i; + break; + } + if (idx == -1) { + MON_PRINT("exceeds maximum interfaces\n"); + ret = -EFAULT; + goto out; + } + + ndev = alloc_etherdev(sizeof(dhd_linux_monitor_t*)); + if (!ndev) { + MON_PRINT("failed to allocate memory\n"); + ret = -ENOMEM; + goto out; + } + + ndev->type = ARPHRD_IEEE80211_RADIOTAP; + strncpy(ndev->name, name, IFNAMSIZ); + ndev->name[IFNAMSIZ - 1] = 0; + ndev->netdev_ops = &dhd_mon_if_ops; + + ret = register_netdevice(ndev); + if (ret) { + MON_PRINT(" register_netdevice failed (%d)\n", ret); + goto out; + } + + *new_ndev = ndev; + g_monitor.mon_if[idx].radiotap_enabled = TRUE; + g_monitor.mon_if[idx].mon_ndev = ndev; + g_monitor.mon_if[idx].real_ndev = lookup_real_netdev(name); + dhd_mon = (dhd_linux_monitor_t **)netdev_priv(ndev); + *dhd_mon = &g_monitor; + g_monitor.monitor_state = MONITOR_STATE_INTERFACE_ADDED; + MON_PRINT("net device returned: 0x%p\n", ndev); + MON_PRINT("found a matched net device, name %s\n", g_monitor.mon_if[idx].real_ndev->name); + +out: + if (ret && ndev) + free_netdev(ndev); + + mutex_unlock(&g_monitor.lock); + return ret; + +} + +int dhd_del_monitor(struct net_device *ndev) +{ + int i; + bool rollback_lock = false; + if (!ndev) + return -EINVAL; + mutex_lock(&g_monitor.lock); + for (i = 0; i < DHD_MAX_IFS; i++) { + if (g_monitor.mon_if[i].mon_ndev == ndev || + g_monitor.mon_if[i].real_ndev == ndev) { + g_monitor.mon_if[i].real_ndev = NULL; + if (rtnl_is_locked()) { + rtnl_unlock(); + rollback_lock = true; + } + unregister_netdev(g_monitor.mon_if[i].mon_ndev); + free_netdev(g_monitor.mon_if[i].mon_ndev); + g_monitor.mon_if[i].mon_ndev = NULL; + g_monitor.monitor_state = MONITOR_STATE_INTERFACE_DELETED; + break; + } + } + if (rollback_lock) { + rtnl_lock(); + rollback_lock = false; + } + + if (g_monitor.monitor_state != + MONITOR_STATE_INTERFACE_DELETED) + MON_PRINT("interface not found in monitor IF array, is this a monitor IF? 0x%p\n", + ndev); + mutex_unlock(&g_monitor.lock); + + return 0; +} + +int dhd_monitor_init(void *dhd_pub) +{ + if (g_monitor.monitor_state == MONITOR_STATE_DEINIT) { + g_monitor.dhd_pub = dhd_pub; + mutex_init(&g_monitor.lock); + g_monitor.monitor_state = MONITOR_STATE_INIT; + } + return 0; +} + +int dhd_monitor_uninit(void) +{ + int i; + struct net_device *ndev; + bool rollback_lock = false; + mutex_lock(&g_monitor.lock); + if (g_monitor.monitor_state != MONITOR_STATE_DEINIT) { + for (i = 0; i < DHD_MAX_IFS; i++) { + ndev = g_monitor.mon_if[i].mon_ndev; + if (ndev) { + if (rtnl_is_locked()) { + rtnl_unlock(); + rollback_lock = true; + } + unregister_netdev(ndev); + free_netdev(ndev); + g_monitor.mon_if[i].real_ndev = NULL; + g_monitor.mon_if[i].mon_ndev = NULL; + if (rollback_lock) { + rtnl_lock(); + rollback_lock = false; + } + } + } + g_monitor.monitor_state = MONITOR_STATE_DEINIT; + } + mutex_unlock(&g_monitor.lock); + return 0; +} diff --git a/drivers/net/wireless/bcmdhd/wldev_common.c b/drivers/net/wireless/bcmdhd/wldev_common.c index bb3eaea90d0f..d9a0b93d689f 100644 --- a/drivers/net/wireless/bcmdhd/wldev_common.c +++ b/drivers/net/wireless/bcmdhd/wldev_common.c @@ -24,12 +24,13 @@ * $Id: wldev_common.c,v 1.1.4.1.2.14 2011-02-09 01:40:07 $ */ -#include +#include +#include +#include #include #include #include -#include #define htod32(i) i #define htod16(i) i @@ -37,6 +38,13 @@ #define dtoh16(i) i #define htodchanspec(i) i #define dtohchanspec(i) i + +#define WLDEV_ERROR(args) \ + do { \ + printk(KERN_ERR "WLDEV-ERROR) %s : ", __func__); \ + printk args; \ + } while (0) + extern int dhd_ioctl_entry_local(struct net_device *net, wl_ioctl_t *ioc, int cmd); s32 wldev_ioctl( @@ -71,26 +79,34 @@ static s32 wldev_mkiovar( s32 wldev_iovar_getbuf( struct net_device *dev, s8 *iovar_name, - void *param, s32 paramlen, void *buf, s32 buflen) + void *param, s32 paramlen, void *buf, s32 buflen, struct mutex* buf_sync) { s32 ret = 0; s32 iovar_len = 0; - + if (buf_sync) { + mutex_lock(buf_sync); + } iovar_len = wldev_mkiovar(iovar_name, param, paramlen, buf, buflen); ret = wldev_ioctl(dev, WLC_GET_VAR, buf, buflen, FALSE); + if (buf_sync) + mutex_unlock(buf_sync); return ret; } s32 wldev_iovar_setbuf( struct net_device *dev, s8 *iovar_name, - void *param, s32 paramlen, void *buf, s32 buflen) + void *param, s32 paramlen, void *buf, s32 buflen, struct mutex* buf_sync) { s32 ret = 0; s32 iovar_len; - + if (buf_sync) { + mutex_lock(buf_sync); + } iovar_len = wldev_mkiovar(iovar_name, param, paramlen, buf, buflen); ret = wldev_ioctl(dev, WLC_SET_VAR, buf, iovar_len, TRUE); + if (buf_sync) + mutex_unlock(buf_sync); return ret; } @@ -102,7 +118,7 @@ s32 wldev_iovar_setint( val = htod32(val); memset(iovar_buf, 0, sizeof(iovar_buf)); return wldev_iovar_setbuf(dev, iovar, &val, sizeof(val), iovar_buf, - sizeof(iovar_buf)); + sizeof(iovar_buf), NULL); } @@ -114,7 +130,7 @@ s32 wldev_iovar_getint( memset(iovar_buf, 0, sizeof(iovar_buf)); err = wldev_iovar_getbuf(dev, iovar, pval, sizeof(*pval), iovar_buf, - sizeof(iovar_buf)); + sizeof(iovar_buf), NULL); if (err == 0) { memcpy(pval, iovar_buf, sizeof(*pval)); @@ -148,7 +164,7 @@ s32 wldev_mkiovar_bsscfg( if (buflen < 0 || iolen > (u32)buflen) { - DHD_ERROR(("%s: buffer is too short\n", __FUNCTION__)); + WLDEV_ERROR(("%s: buffer is too short\n", __FUNCTION__)); return BCME_BUFTOOSHORT; } @@ -177,26 +193,37 @@ s32 wldev_mkiovar_bsscfg( s32 wldev_iovar_getbuf_bsscfg( struct net_device *dev, s8 *iovar_name, - void *param, s32 paramlen, void *buf, s32 buflen, s32 bsscfg_idx) + void *param, s32 paramlen, void *buf, s32 buflen, s32 bsscfg_idx, struct mutex* buf_sync) { s32 ret = 0; s32 iovar_len = 0; - + if (buf_sync) { + mutex_lock(buf_sync); + } iovar_len = wldev_mkiovar_bsscfg(iovar_name, param, paramlen, buf, buflen, bsscfg_idx); ret = wldev_ioctl(dev, WLC_GET_VAR, buf, buflen, FALSE); + if (buf_sync) { + mutex_unlock(buf_sync); + } return ret; } s32 wldev_iovar_setbuf_bsscfg( struct net_device *dev, s8 *iovar_name, - void *param, s32 paramlen, void *buf, s32 buflen, s32 bsscfg_idx) + void *param, s32 paramlen, void *buf, s32 buflen, s32 bsscfg_idx, struct mutex* buf_sync) { s32 ret = 0; s32 iovar_len; - + if (buf_sync) { + mutex_lock(buf_sync); + } iovar_len = wldev_mkiovar_bsscfg(iovar_name, param, paramlen, buf, buflen, bsscfg_idx); + ret = wldev_ioctl(dev, WLC_SET_VAR, buf, iovar_len, TRUE); + if (buf_sync) { + mutex_unlock(buf_sync); + } return ret; } @@ -208,7 +235,7 @@ s32 wldev_iovar_setint_bsscfg( val = htod32(val); memset(iovar_buf, 0, sizeof(iovar_buf)); return wldev_iovar_setbuf_bsscfg(dev, iovar, &val, sizeof(val), iovar_buf, - sizeof(iovar_buf), bssidx); + sizeof(iovar_buf), bssidx, NULL); } @@ -220,7 +247,7 @@ s32 wldev_iovar_getint_bsscfg( memset(iovar_buf, 0, sizeof(iovar_buf)); err = wldev_iovar_getbuf_bsscfg(dev, iovar, pval, sizeof(*pval), iovar_buf, - sizeof(iovar_buf), bssidx); + sizeof(iovar_buf), bssidx, NULL); if (err == 0) { memcpy(pval, iovar_buf, sizeof(*pval)); @@ -309,16 +336,16 @@ int wldev_set_country( return error; error = wldev_iovar_getbuf(dev, "country", &cspec, sizeof(cspec), - smbuf, sizeof(smbuf)); + smbuf, sizeof(smbuf), NULL); if (error < 0) - DHD_ERROR(("%s: get country failed = %d\n", __FUNCTION__, error)); + WLDEV_ERROR(("%s: get country failed = %d\n", __FUNCTION__, error)); if ((error < 0) || (strncmp(country_code, smbuf, WLC_CNTRY_BUF_SZ) != 0)) { bzero(&scbval, sizeof(scb_val_t)); error = wldev_ioctl(dev, WLC_DISASSOC, &scbval, sizeof(scb_val_t), 1); if (error < 0) { - DHD_ERROR(("%s: set country failed due to Disassoc error %d\n", + WLDEV_ERROR(("%s: set country failed due to Disassoc error %d\n", __FUNCTION__, error)); return error; } @@ -328,14 +355,14 @@ int wldev_set_country( memcpy(cspec.ccode, country_code, WLC_CNTRY_BUF_SZ); get_customized_country_code((char *)&cspec.country_abbrev, &cspec); error = wldev_iovar_setbuf(dev, "country", &cspec, sizeof(cspec), - smbuf, sizeof(smbuf)); + smbuf, sizeof(smbuf), NULL); if (error < 0) { - DHD_ERROR(("%s: set country for %s as %s rev %d failed\n", + WLDEV_ERROR(("%s: set country for %s as %s rev %d failed\n", __FUNCTION__, country_code, cspec.ccode, cspec.rev)); return error; } dhd_bus_country_set(dev, &cspec); - DHD_INFO(("%s: set country for %s as %s rev %d\n", + WLDEV_ERROR(("%s: set country for %s as %s rev %d\n", __FUNCTION__, country_code, cspec.ccode, cspec.rev)); return 0; } diff --git a/drivers/net/wireless/bcmdhd/wldev_common.h b/drivers/net/wireless/bcmdhd/wldev_common.h index 46326803e216..6a1ba1533600 100644 --- a/drivers/net/wireless/bcmdhd/wldev_common.h +++ b/drivers/net/wireless/bcmdhd/wldev_common.h @@ -21,33 +21,33 @@ * software in any way with any other Broadcom software provided under a license * other than the GPL, without Broadcom's express prior written consent. * - * $Id: wldev_common.h,v 1.1.4.1.2.14 2011-02-09 01:40:07 Exp $ + * $Id: wldev_common.h,v 1.1.4.1.2.14 2011-02-09 01:40:07 $ */ #ifndef __WLDEV_COMMON_H__ #define __WLDEV_COMMON_H__ #include -/** wl_dev_ioctl - get/set IOCTLs, will call net_device's do_ioctl (or +/* wl_dev_ioctl - get/set IOCTLs, will call net_device's do_ioctl (or * netdev_ops->ndo_do_ioctl in new kernels) * @dev: the net_device handle */ s32 wldev_ioctl( struct net_device *dev, u32 cmd, void *arg, u32 len, u32 set); -/** Retrieve named IOVARs, this function calls wl_dev_ioctl with +/** Retrieve named IOVARs, this function calls wl_dev_ioctl with * WLC_GET_VAR IOCTL code */ s32 wldev_iovar_getbuf( struct net_device *dev, s8 *iovar_name, - void *param, s32 paramlen, void *buf, s32 buflen); + void *param, s32 paramlen, void *buf, s32 buflen, struct mutex* buf_sync); /** Set named IOVARs, this function calls wl_dev_ioctl with * WLC_SET_VAR IOCTL code */ s32 wldev_iovar_setbuf( struct net_device *dev, s8 *iovar_name, - void *param, s32 paramlen, void *buf, s32 buflen); + void *param, s32 paramlen, void *buf, s32 buflen, struct mutex* buf_sync); s32 wldev_iovar_setint( struct net_device *dev, s8 *iovar, s32 val); @@ -67,15 +67,15 @@ s32 wldev_mkiovar_bsscfg( * WLC_GET_VAR IOCTL code */ s32 wldev_iovar_getbuf_bsscfg( - struct net_device *dev, s8 *iovar_name, - void *param, s32 paramlen, void *buf, s32 buflen, s32 bsscfg_idx); + struct net_device *dev, s8 *iovar_name, void *param, s32 paramlen, + void *buf, s32 buflen, s32 bsscfg_idx, struct mutex* buf_sync); /** Set named and bsscfg indexed IOVARs, this function calls wl_dev_ioctl with * WLC_SET_VAR IOCTL code */ s32 wldev_iovar_setbuf_bsscfg( - struct net_device *dev, s8 *iovar_name, - void *param, s32 paramlen, void *buf, s32 buflen, s32 bsscfg_idx); + struct net_device *dev, s8 *iovar_name, void *param, s32 paramlen, + void *buf, s32 buflen, s32 bsscfg_idx, struct mutex* buf_sync); s32 wldev_iovar_getint_bsscfg( struct net_device *dev, s8 *iovar, s32 *pval, s32 bssidx); @@ -94,7 +94,7 @@ extern int net_os_set_dtim_skip(struct net_device *dev, int val); extern int net_os_set_suspend_disable(struct net_device *dev, int val); extern int net_os_set_suspend(struct net_device *dev, int val); extern int wl_iw_parse_ssid_list_tlv(char** list_str, wlc_ssid_t* ssid, - int max, int *bytes_left); + int max, int *bytes_left); /* Get the link speed from dongle, speed is in kpbs */ int wldev_get_link_speed(struct net_device *dev, int *plink_speed); -- cgit v1.2.3 From 72f92ebe408c394d14c07b4e7c5eaca8525e5341 Mon Sep 17 00:00:00 2001 From: Dmitry Shmidt Date: Tue, 24 Jan 2012 13:55:00 -0800 Subject: net: wireless: bcmdhd: Update to Version 5.90.195.22 - Disable Ad-hoc support for cfg80211 - dhd_linux.c: Fix incorrect pid check - Merge Android changes from Android tree Signed-off-by: Dmitry Shmidt --- drivers/net/wireless/bcmdhd/bcmsdh_linux.c | 24 +++-------------------- drivers/net/wireless/bcmdhd/bcmsdh_sdmmc_linux.c | 25 +++++++++++++++++------- drivers/net/wireless/bcmdhd/dhd_linux.c | 10 +++++----- drivers/net/wireless/bcmdhd/dhd_sdio.c | 11 ++++++++--- drivers/net/wireless/bcmdhd/hndpmu.c | 16 +++++++++++++++ drivers/net/wireless/bcmdhd/include/bcmdevs.h | 2 ++ drivers/net/wireless/bcmdhd/include/epivers.h | 8 ++++---- drivers/net/wireless/bcmdhd/siutils.c | 3 +++ drivers/net/wireless/bcmdhd/wl_cfg80211.c | 11 +++++++++-- 9 files changed, 68 insertions(+), 42 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/bcmdhd/bcmsdh_linux.c b/drivers/net/wireless/bcmdhd/bcmsdh_linux.c index 8d38a9a98012..90f554888c79 100644 --- a/drivers/net/wireless/bcmdhd/bcmsdh_linux.c +++ b/drivers/net/wireless/bcmdhd/bcmsdh_linux.c @@ -21,7 +21,7 @@ * software in any way with any other Broadcom software provided under a license * other than the GPL, without Broadcom's express prior written consent. * - * $Id: bcmsdh_linux.c 294990 2011-11-09 00:13:10Z $ + * $Id: bcmsdh_linux.c 308641 2012-01-17 02:18:02Z $ */ /** @@ -147,17 +147,6 @@ static int __devinit bcmsdh_probe_bcmdhd(struct device *dev); static int __devexit bcmsdh_remove_bcmdhd(struct device *dev); #endif /* BCMLXSDMMC */ -#ifndef BCMLXSDMMC -static struct device_driver bcmsdh_driver = { - .name = "pxa2xx-mci", - .bus = &platform_bus_type, - .probe = bcmsdh_probe_bcmdhd, - .remove = bcmsdh_remove_bcmdhd, - .suspend = NULL, - .resume = NULL, - }; -#endif /* BCMLXSDMMC */ - #ifndef BCMLXSDMMC static #endif /* BCMLXSDMMC */ @@ -534,13 +523,8 @@ bcmsdh_register(bcmsdh_driver_t *driver) drvinfo = *driver; #if defined(BCMPLATFORM_BUS) -#if defined(BCMLXSDMMC) SDLX_MSG(("Linux Kernel SDIO/MMC Driver\n")); error = sdio_function_init(); -#else - SDLX_MSG(("Intel PXA270 SDIO Driver\n")); - error = driver_register(&bcmsdh_driver); -#endif /* defined(BCMLXSDMMC) */ return error; #endif /* defined(BCMPLATFORM_BUS) */ @@ -568,14 +552,12 @@ bcmsdh_unregister(void) if (bcmsdh_pci_driver.node.next) #endif -#if defined(BCMPLATFORM_BUS) && !defined(BCMLXSDMMC) - driver_unregister(&bcmsdh_driver); -#endif #if defined(BCMLXSDMMC) sdio_function_cleanup(); #endif /* BCMLXSDMMC */ + #if !defined(BCMPLATFORM_BUS) && !defined(BCMLXSDMMC) - pci_unregister_driver(&bcmsdh_pci_driver); + pci_unregister_driver(&bcmsdh_pci_driver); #endif /* BCMPLATFORM_BUS */ } diff --git a/drivers/net/wireless/bcmdhd/bcmsdh_sdmmc_linux.c b/drivers/net/wireless/bcmdhd/bcmsdh_sdmmc_linux.c index 08b1f492ed8b..22343784cb57 100644 --- a/drivers/net/wireless/bcmdhd/bcmsdh_sdmmc_linux.c +++ b/drivers/net/wireless/bcmdhd/bcmsdh_sdmmc_linux.c @@ -21,7 +21,7 @@ * software in any way with any other Broadcom software provided under a license * other than the GPL, without Broadcom's express prior written consent. * - * $Id: bcmsdh_sdmmc_linux.c 300908 2011-12-06 10:32:01Z $ + * $Id: bcmsdh_sdmmc_linux.c 308645 2012-01-17 02:33:26Z $ */ #include @@ -55,6 +55,12 @@ #if !defined(SDIO_DEVICE_ID_BROADCOM_4330) #define SDIO_DEVICE_ID_BROADCOM_4330 0x4330 #endif /* !defined(SDIO_DEVICE_ID_BROADCOM_4330) */ +#if !defined(SDIO_DEVICE_ID_BROADCOM_4334) +#define SDIO_DEVICE_ID_BROADCOM_4334 0x4334 +#endif /* !defined(SDIO_DEVICE_ID_BROADCOM_4334) */ +#if !defined(SDIO_DEVICE_ID_BROADCOM_43239) +#define SDIO_DEVICE_ID_BROADCOM_43239 43239 +#endif /* !defined(SDIO_DEVICE_ID_BROADCOM_43239) */ #include @@ -153,9 +159,9 @@ static const struct sdio_device_id bcmsdh_sdmmc_ids[] = { { SDIO_DEVICE(SDIO_VENDOR_ID_BROADCOM, SDIO_DEVICE_ID_BROADCOM_4325) }, { SDIO_DEVICE(SDIO_VENDOR_ID_BROADCOM, SDIO_DEVICE_ID_BROADCOM_4319) }, { SDIO_DEVICE(SDIO_VENDOR_ID_BROADCOM, SDIO_DEVICE_ID_BROADCOM_4330) }, -#ifndef BOARD_PANDA + { SDIO_DEVICE(SDIO_VENDOR_ID_BROADCOM, SDIO_DEVICE_ID_BROADCOM_4334) }, + { SDIO_DEVICE(SDIO_VENDOR_ID_BROADCOM, SDIO_DEVICE_ID_BROADCOM_43239) }, { SDIO_DEVICE_CLASS(SDIO_CLASS_NONE) }, -#endif { /* end: all zeroes */ }, }; @@ -170,11 +176,14 @@ static int bcmsdh_sdmmc_suspend(struct device *pdev) if (func->num != 2) return 0; + + sd_trace(("%s Enter\n", __FUNCTION__)); + if (dhd_os_check_wakelock(bcmsdh_get_drvdata())) return -EBUSY; #if defined(OOB_INTR_ONLY) bcmsdh_oob_intr_set(0); -#endif +#endif /* defined(OOB_INTR_ONLY) */ smp_mb(); sdio_flags = sdio_get_host_pm_caps(func); @@ -203,11 +212,13 @@ static int bcmsdh_sdmmc_resume(struct device *pdev) { struct sdio_func *func = dev_to_sdio_func(pdev); + sd_trace(("%s Enter\n", __FUNCTION__)); dhd_mmc_suspend = FALSE; #if defined(OOB_INTR_ONLY) if ((func->num == 2) && dhd_os_check_if_up(bcmsdh_get_drvdata())) bcmsdh_oob_intr_set(1); -#endif +#endif /* (OOB_INTR_ONLY) */ + smp_mb(); return 0; } @@ -216,7 +227,7 @@ static const struct dev_pm_ops bcmsdh_sdmmc_pm_ops = { .suspend = bcmsdh_sdmmc_suspend, .resume = bcmsdh_sdmmc_resume, }; -#endif +#endif /* (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 39)) && defined(CONFIG_PM) */ static struct sdio_driver bcmsdh_sdmmc_driver = { .probe = bcmsdh_sdmmc_probe, @@ -227,7 +238,7 @@ static struct sdio_driver bcmsdh_sdmmc_driver = { .drv = { .pm = &bcmsdh_sdmmc_pm_ops, }, -#endif +#endif /* (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 39)) && defined(CONFIG_PM) */ }; struct sdos_info { diff --git a/drivers/net/wireless/bcmdhd/dhd_linux.c b/drivers/net/wireless/bcmdhd/dhd_linux.c index 0ebd4c2af705..4bd2e39656ff 100644 --- a/drivers/net/wireless/bcmdhd/dhd_linux.c +++ b/drivers/net/wireless/bcmdhd/dhd_linux.c @@ -1149,7 +1149,7 @@ dhd_set_mac_address(struct net_device *dev, void *addr) if (ifidx == DHD_BAD_IF) return -1; - ASSERT(&dhd->thr_sysioc_ctl.thr_pid >= 0); + ASSERT(dhd->thr_sysioc_ctl.thr_pid >= 0); memcpy(&dhd->macvalue, sa->sa_data, ETHER_ADDR_LEN); dhd->set_macaddress = TRUE; up(&dhd->thr_sysioc_ctl.sema); @@ -1167,7 +1167,7 @@ dhd_set_multicast_list(struct net_device *dev) if (ifidx == DHD_BAD_IF) return; - ASSERT(&dhd->thr_sysioc_ctl.thr_pid >= 0); + ASSERT(dhd->thr_sysioc_ctl.thr_pid >= 0); dhd->iflist[ifidx]->set_multicast = TRUE; up(&dhd->thr_sysioc_ctl.sema); } @@ -2509,7 +2509,7 @@ dhd_add_if(dhd_info_t *dhd, int ifidx, void *handle, char *name, ifp->state = DHD_IF_ADD; ifp->idx = ifidx; ifp->bssidx = bssidx; - ASSERT(&dhd->thr_sysioc_ctl.thr_pid >= 0); + ASSERT(dhd->thr_sysioc_ctl.thr_pid >= 0); up(&dhd->thr_sysioc_ctl.sema); } else ifp->net = (struct net_device *)handle; @@ -2533,7 +2533,7 @@ dhd_del_if(dhd_info_t *dhd, int ifidx) ifp->state = DHD_IF_DEL; ifp->idx = ifidx; - ASSERT(&dhd->thr_sysioc_ctl.thr_pid >= 0); + ASSERT(dhd->thr_sysioc_ctl.thr_pid >= 0); up(&dhd->thr_sysioc_ctl.sema); } @@ -3590,7 +3590,7 @@ void dhd_detach(dhd_pub_t *dhdp) } #endif /* defined(CONFIG_BCMDHD_WEXT) */ - if (&dhd->thr_sysioc_ctl.thr_pid >= 0) { + if (dhd->thr_sysioc_ctl.thr_pid >= 0) { PROC_STOP(&dhd->thr_sysioc_ctl); } diff --git a/drivers/net/wireless/bcmdhd/dhd_sdio.c b/drivers/net/wireless/bcmdhd/dhd_sdio.c index 5806c66239ae..a89195a9158c 100644 --- a/drivers/net/wireless/bcmdhd/dhd_sdio.c +++ b/drivers/net/wireless/bcmdhd/dhd_sdio.c @@ -21,7 +21,7 @@ * software in any way with any other Broadcom software provided under a license * other than the GPL, without Broadcom's express prior written consent. * - * $Id: dhd_sdio.c 303389 2011-12-16 09:30:48Z $ + * $Id: dhd_sdio.c 308574 2012-01-16 22:56:40Z $ */ #include @@ -851,8 +851,10 @@ dhdsdio_bussleep(dhd_bus_t *bus, bool sleep) SBSDIO_FORCE_HW_CLKREQ_OFF, NULL); /* Isolate the bus */ - bcmsdh_cfg_write(sdh, SDIO_FUNC_1, SBSDIO_DEVICE_CTL, - SBSDIO_DEVCTL_PADS_ISO, NULL); + if (bus->sih->chip != BCM4329_CHIP_ID && bus->sih->chip != BCM4319_CHIP_ID) { + bcmsdh_cfg_write(sdh, SDIO_FUNC_1, SBSDIO_DEVICE_CTL, + SBSDIO_DEVCTL_PADS_ISO, NULL); + } /* Change state */ bus->sleeping = TRUE; @@ -5191,6 +5193,9 @@ dhdsdio_chipmatch(uint16 chipid) return TRUE; if (chipid == BCM4330_CHIP_ID) return TRUE; + if (chipid == BCM43239_CHIP_ID) + return TRUE; + return FALSE; } diff --git a/drivers/net/wireless/bcmdhd/hndpmu.c b/drivers/net/wireless/bcmdhd/hndpmu.c index 111b5be9cbf9..0e493343c806 100644 --- a/drivers/net/wireless/bcmdhd/hndpmu.c +++ b/drivers/net/wireless/bcmdhd/hndpmu.c @@ -140,11 +140,27 @@ si_sdiod_drive_strength_init(si_t *sih, osl_t *osh, uint32 drivestrength) str_mask = 0x00003800; str_shift = 11; break; + case SDIOD_DRVSTR_KEY(BCM4336_CHIP_ID, 8): + case SDIOD_DRVSTR_KEY(BCM4336_CHIP_ID, 11): + if (sih->pmurev == 8) { + str_tab = (sdiod_drive_str_t *)&sdiod_drive_strength_tab3; + } + else if (sih->pmurev == 11) { + str_tab = (sdiod_drive_str_t *)&sdiod_drive_strength_tab4_1v8; + } + str_mask = 0x00003800; + str_shift = 11; + break; case SDIOD_DRVSTR_KEY(BCM4330_CHIP_ID, 12): str_tab = (sdiod_drive_str_t *)&sdiod_drive_strength_tab4_1v8; str_mask = 0x00003800; str_shift = 11; break; + case SDIOD_DRVSTR_KEY(BCM43362_CHIP_ID, 13): + str_tab = (sdiod_drive_str_t *)&sdiod_drive_strength_tab5_1v8; + str_mask = 0x00003800; + str_shift = 11; + break; default: PMU_MSG(("No SDIO Drive strength init done for chip %s rev %d pmurev %d\n", bcm_chipname(sih->chip, chn, 8), sih->chiprev, sih->pmurev)); diff --git a/drivers/net/wireless/bcmdhd/include/bcmdevs.h b/drivers/net/wireless/bcmdhd/include/bcmdevs.h index f0542f2ac11b..ee01d8b45675 100644 --- a/drivers/net/wireless/bcmdhd/include/bcmdevs.h +++ b/drivers/net/wireless/bcmdhd/include/bcmdevs.h @@ -57,8 +57,10 @@ #define BCM_DNGL_BL_PID_4328 0xbd12 #define BCM_DNGL_BL_PID_4322 0xbd13 #define BCM_DNGL_BL_PID_4319 0xbd16 +#define BCM_DNGL_BL_PID_43236 0xbd17 #define BCM_DNGL_BL_PID_4332 0xbd18 #define BCM_DNGL_BL_PID_4330 0xbd19 +#define BCM_DNGL_BL_PID_43239 0xbd1b #define BCM_DNGL_BDC_PID 0x0bdc #define BCM_DNGL_JTAG_PID 0x4a44 diff --git a/drivers/net/wireless/bcmdhd/include/epivers.h b/drivers/net/wireless/bcmdhd/include/epivers.h index a0e9ed12b88e..f82ee1025749 100644 --- a/drivers/net/wireless/bcmdhd/include/epivers.h +++ b/drivers/net/wireless/bcmdhd/include/epivers.h @@ -33,17 +33,17 @@ #define EPI_RC_NUMBER 195 -#define EPI_INCREMENTAL_NUMBER 19 +#define EPI_INCREMENTAL_NUMBER 22 #define EPI_BUILD_NUMBER 0 -#define EPI_VERSION 5, 90, 195, 19 +#define EPI_VERSION 5, 90, 195, 22 -#define EPI_VERSION_NUM 0x055ac313 +#define EPI_VERSION_NUM 0x055ac316 #define EPI_VERSION_DEV 5.90.195 -#define EPI_VERSION_STR "5.90.195.19" +#define EPI_VERSION_STR "5.90.195.22" #endif diff --git a/drivers/net/wireless/bcmdhd/siutils.c b/drivers/net/wireless/bcmdhd/siutils.c index 4b7156303553..1cc977f51ee3 100644 --- a/drivers/net/wireless/bcmdhd/siutils.c +++ b/drivers/net/wireless/bcmdhd/siutils.c @@ -1901,6 +1901,9 @@ si_is_sprom_available(si_t *sih) return (sih->chipst & CST4330_SPROM_PRESENT) != 0; case BCM4313_CHIP_ID: return (sih->chipst & CST4313_SPROM_PRESENT) != 0; + case BCM43239_CHIP_ID: + return ((sih->chipst & CST43239_SPROM_MASK) && + !(sih->chipst & CST43239_SFLASH_MASK)); default: return TRUE; } diff --git a/drivers/net/wireless/bcmdhd/wl_cfg80211.c b/drivers/net/wireless/bcmdhd/wl_cfg80211.c index b84d1e890c1b..79016b588fca 100644 --- a/drivers/net/wireless/bcmdhd/wl_cfg80211.c +++ b/drivers/net/wireless/bcmdhd/wl_cfg80211.c @@ -4213,8 +4213,8 @@ static s32 wl_setup_wiphy(struct wireless_dev *wdev, struct device *sdiofunc_dev wdev->wiphy->max_scan_ssids = WL_SCAN_PARAMS_SSID_MAX; wdev->wiphy->max_num_pmkids = WL_NUM_PMKIDS_MAX; wdev->wiphy->interface_modes = - BIT(NL80211_IFTYPE_STATION) | BIT(NL80211_IFTYPE_ADHOC) - | BIT(NL80211_IFTYPE_AP) | BIT(NL80211_IFTYPE_MONITOR); + BIT(NL80211_IFTYPE_STATION) + | BIT(NL80211_IFTYPE_AP) | BIT(NL80211_IFTYPE_MONITOR); wdev->wiphy->bands[IEEE80211_BAND_2GHZ] = &__wl_band_2ghz; wdev->wiphy->bands[IEEE80211_BAND_5GHZ] = &__wl_band_5ghz_a; @@ -5615,6 +5615,13 @@ static s32 wl_escan_handler(struct wl_priv *wl, goto exit; } + if (!(wl_to_wiphy(wl)->interface_modes & BIT(NL80211_IFTYPE_ADHOC))) { + if (dtoh16(bi->capability) & DOT11_CAP_IBSS) { + WL_ERR(("Ignoring IBSS result\n")); + goto exit; + } + } + if (wl_get_drv_status_all(wl, SENDING_ACT_FRM)) { p2p_dev_addr = wl_cfgp2p_retreive_p2p_dev_addr(bi, bi_length); if (p2p_dev_addr && !memcmp(p2p_dev_addr, -- cgit v1.2.3 From 0867dd2f02e825483a4ac115366f3cb680bf9f80 Mon Sep 17 00:00:00 2001 From: Dmitry Shmidt Date: Tue, 24 Jan 2012 13:59:40 -0800 Subject: net: wireless: bcmdhd: Update to Version 5.90.195.23 - WFD fixes Signed-off-by: Dmitry Shmidt --- drivers/net/wireless/bcmdhd/dhd_cfg80211.c | 269 -------------------------- drivers/net/wireless/bcmdhd/dhd_linux.c | 2 +- drivers/net/wireless/bcmdhd/dhd_sdio.c | 8 +- drivers/net/wireless/bcmdhd/include/epivers.h | 8 +- drivers/net/wireless/bcmdhd/siutils.c | 5 + drivers/net/wireless/bcmdhd/wl_cfg80211.c | 223 +++++++++++++++------ drivers/net/wireless/bcmdhd/wl_cfgp2p.c | 175 ++++++++++++++++- drivers/net/wireless/bcmdhd/wl_cfgp2p.h | 37 ++-- 8 files changed, 368 insertions(+), 359 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/bcmdhd/dhd_cfg80211.c b/drivers/net/wireless/bcmdhd/dhd_cfg80211.c index 058749deba3d..800590cca653 100644 --- a/drivers/net/wireless/bcmdhd/dhd_cfg80211.c +++ b/drivers/net/wireless/bcmdhd/dhd_cfg80211.c @@ -34,13 +34,6 @@ extern struct wl_priv *wlcfg_drv_priv; static int dhd_dongle_up = FALSE; static s32 wl_dongle_up(struct net_device *ndev, u32 up); -static s32 wl_dongle_power(struct net_device *ndev, u32 power_mode); -static s32 wl_dongle_glom(struct net_device *ndev, u32 glom, u32 dongle_align); -static s32 wl_dongle_roam(struct net_device *ndev, u32 roamvar, u32 bcn_timeout); -static s32 wl_dongle_scantime(struct net_device *ndev, s32 scan_assoc_time, s32 scan_unassoc_time); -static s32 wl_dongle_offload(struct net_device *ndev, s32 arpoe, s32 arp_ol); -static s32 wl_pattern_atoh(s8 *src, s8 *dst); -static s32 wl_dongle_filter(struct net_device *ndev, u32 filter_mode); /** * Function implementations @@ -74,250 +67,6 @@ static s32 wl_dongle_up(struct net_device *ndev, u32 up) } return err; } - -static s32 wl_dongle_power(struct net_device *ndev, u32 power_mode) -{ - s32 err = 0; - - WL_TRACE(("In\n")); - err = wldev_ioctl(ndev, WLC_SET_PM, &power_mode, sizeof(power_mode), true); - if (unlikely(err)) { - WL_ERR(("WLC_SET_PM error (%d)\n", err)); - } - return err; -} - -static s32 -wl_dongle_glom(struct net_device *ndev, u32 glom, u32 dongle_align) -{ - s8 iovbuf[WL_EVENTING_MASK_LEN + 12]; - - s32 err = 0; - - /* Match Host and Dongle rx alignment */ - bcm_mkiovar("bus:txglomalign", (char *)&dongle_align, 4, iovbuf, - sizeof(iovbuf)); - err = wldev_ioctl(ndev, WLC_SET_VAR, iovbuf, sizeof(iovbuf), true); - if (unlikely(err)) { - WL_ERR(("txglomalign error (%d)\n", err)); - goto dongle_glom_out; - } - /* disable glom option per default */ - bcm_mkiovar("bus:txglom", (char *)&glom, 4, iovbuf, sizeof(iovbuf)); - err = wldev_ioctl(ndev, WLC_SET_VAR, iovbuf, sizeof(iovbuf), true); - if (unlikely(err)) { - WL_ERR(("txglom error (%d)\n", err)); - goto dongle_glom_out; - } -dongle_glom_out: - return err; -} - -static s32 -wl_dongle_roam(struct net_device *ndev, u32 roamvar, u32 bcn_timeout) -{ - s8 iovbuf[WL_EVENTING_MASK_LEN + 12]; - - s32 err = 0; - - /* Setup timeout if Beacons are lost and roam is off to report link down */ - if (roamvar) { - bcm_mkiovar("bcn_timeout", (char *)&bcn_timeout, 4, iovbuf, - sizeof(iovbuf)); - err = wldev_ioctl(ndev, WLC_SET_VAR, iovbuf, sizeof(iovbuf), true); - if (unlikely(err)) { - WL_ERR(("bcn_timeout error (%d)\n", err)); - goto dongle_rom_out; - } - } - /* Enable/Disable built-in roaming to allow supplicant to take care of roaming */ - bcm_mkiovar("roam_off", (char *)&roamvar, 4, iovbuf, sizeof(iovbuf)); - err = wldev_ioctl(ndev, WLC_SET_VAR, iovbuf, sizeof(iovbuf), true); - if (unlikely(err)) { - WL_ERR(("roam_off error (%d)\n", err)); - goto dongle_rom_out; - } -dongle_rom_out: - return err; -} - -static s32 -wl_dongle_scantime(struct net_device *ndev, s32 scan_assoc_time, - s32 scan_unassoc_time) -{ - s32 err = 0; - - err = wldev_ioctl(ndev, WLC_SET_SCAN_CHANNEL_TIME, &scan_assoc_time, - sizeof(scan_assoc_time), true); - if (err) { - if (err == -EOPNOTSUPP) { - WL_INFO(("Scan assoc time is not supported\n")); - } else { - WL_ERR(("Scan assoc time error (%d)\n", err)); - } - goto dongle_scantime_out; - } - err = wldev_ioctl(ndev, WLC_SET_SCAN_UNASSOC_TIME, &scan_unassoc_time, - sizeof(scan_unassoc_time), true); - if (err) { - if (err == -EOPNOTSUPP) { - WL_INFO(("Scan unassoc time is not supported\n")); - } else { - WL_ERR(("Scan unassoc time error (%d)\n", err)); - } - goto dongle_scantime_out; - } - -dongle_scantime_out: - return err; -} - -static s32 -wl_dongle_offload(struct net_device *ndev, s32 arpoe, s32 arp_ol) -{ - /* Room for "event_msgs" + '\0' + bitvec */ - s8 iovbuf[WL_EVENTING_MASK_LEN + 12]; - - s32 err = 0; - - /* Set ARP offload */ - bcm_mkiovar("arpoe", (char *)&arpoe, 4, iovbuf, sizeof(iovbuf)); - err = wldev_ioctl(ndev, WLC_SET_VAR, iovbuf, sizeof(iovbuf), true); - if (err) { - if (err == -EOPNOTSUPP) - WL_INFO(("arpoe is not supported\n")); - else - WL_ERR(("arpoe error (%d)\n", err)); - - goto dongle_offload_out; - } - bcm_mkiovar("arp_ol", (char *)&arp_ol, 4, iovbuf, sizeof(iovbuf)); - err = wldev_ioctl(ndev, WLC_SET_VAR, iovbuf, sizeof(iovbuf), true); - if (err) { - if (err == -EOPNOTSUPP) - WL_INFO(("arp_ol is not supported\n")); - else - WL_ERR(("arp_ol error (%d)\n", err)); - - goto dongle_offload_out; - } - -dongle_offload_out: - return err; -} - -static s32 wl_pattern_atoh(s8 *src, s8 *dst) -{ - int i; - if (strncmp(src, "0x", 2) != 0 && strncmp(src, "0X", 2) != 0) { - WL_ERR(("Mask invalid format. Needs to start with 0x\n")); - return -1; - } - src = src + 2; /* Skip past 0x */ - if (strlen(src) % 2 != 0) { - WL_ERR(("Mask invalid format. Needs to be of even length\n")); - return -1; - } - for (i = 0; *src != '\0'; i++) { - char num[3]; - strncpy(num, src, 2); - num[2] = '\0'; - dst[i] = (u8) simple_strtoul(num, NULL, 16); - src += 2; - } - return i; -} - -static s32 wl_dongle_filter(struct net_device *ndev, u32 filter_mode) -{ - /* Room for "event_msgs" + '\0' + bitvec */ - s8 iovbuf[WL_EVENTING_MASK_LEN + 12]; - - const s8 *str; - struct wl_pkt_filter pkt_filter; - struct wl_pkt_filter *pkt_filterp; - s32 buf_len; - s32 str_len; - u32 mask_size; - u32 pattern_size; - s8 buf[256]; - s32 err = 0; - - /* add a default packet filter pattern */ - str = "pkt_filter_add"; - str_len = strlen(str); - strncpy(buf, str, str_len); - buf[str_len] = '\0'; - buf_len = str_len + 1; - - pkt_filterp = (struct wl_pkt_filter *)(buf + str_len + 1); - - /* Parse packet filter id. */ - pkt_filter.id = htod32(100); - - /* Parse filter polarity. */ - pkt_filter.negate_match = htod32(0); - - /* Parse filter type. */ - pkt_filter.type = htod32(0); - - /* Parse pattern filter offset. */ - pkt_filter.u.pattern.offset = htod32(0); - - /* Parse pattern filter mask. */ - mask_size = htod32(wl_pattern_atoh("0xff", - (char *)pkt_filterp->u.pattern. - mask_and_pattern)); - - /* Parse pattern filter pattern. */ - pattern_size = htod32(wl_pattern_atoh("0x00", - (char *)&pkt_filterp->u.pattern.mask_and_pattern[mask_size])); - - if (mask_size != pattern_size) { - WL_ERR(("Mask and pattern not the same size\n")); - err = -EINVAL; - goto dongle_filter_out; - } - - pkt_filter.u.pattern.size_bytes = mask_size; - buf_len += WL_PKT_FILTER_FIXED_LEN; - buf_len += (WL_PKT_FILTER_PATTERN_FIXED_LEN + 2 * mask_size); - - /* Keep-alive attributes are set in local - * variable (keep_alive_pkt), and - * then memcpy'ed into buffer (keep_alive_pktp) since there is no - * guarantee that the buffer is properly aligned. - */ - memcpy((char *)pkt_filterp, &pkt_filter, - WL_PKT_FILTER_FIXED_LEN + WL_PKT_FILTER_PATTERN_FIXED_LEN); - - err = wldev_ioctl(ndev, WLC_SET_VAR, buf, buf_len, true); - if (err) { - if (err == -EOPNOTSUPP) { - WL_INFO(("filter not supported\n")); - } else { - WL_ERR(("filter (%d)\n", err)); - } - goto dongle_filter_out; - } - - /* set mode to allow pattern */ - bcm_mkiovar("pkt_filter_mode", (char *)&filter_mode, 4, iovbuf, - sizeof(iovbuf)); - err = wldev_ioctl(ndev, WLC_SET_VAR, iovbuf, sizeof(iovbuf), true); - if (err) { - if (err == -EOPNOTSUPP) { - WL_INFO(("filter_mode not supported\n")); - } else { - WL_ERR(("filter_mode (%d)\n", err)); - } - goto dongle_filter_out; - } - -dongle_filter_out: - return err; -} - s32 dhd_config_dongle(struct wl_priv *wl, bool need_lock) { #ifndef DHD_SDALIGN @@ -342,24 +91,6 @@ s32 dhd_config_dongle(struct wl_priv *wl, bool need_lock) WL_ERR(("wl_dongle_up failed\n")); goto default_conf_out; } - err = wl_dongle_power(ndev, PM_FAST); - if (unlikely(err)) { - WL_ERR(("wl_dongle_power failed\n")); - goto default_conf_out; - } - err = wl_dongle_glom(ndev, 0, DHD_SDALIGN); - if (unlikely(err)) { - WL_ERR(("wl_dongle_glom failed\n")); - goto default_conf_out; - } - err = wl_dongle_roam(ndev, (wl->roam_on ? 0 : 1), 3); - if (unlikely(err)) { - WL_ERR(("wl_dongle_roam failed\n")); - goto default_conf_out; - } - wl_dongle_scantime(ndev, 40, 80); - wl_dongle_offload(ndev, 1, 0xf); - wl_dongle_filter(ndev, 1); dhd_dongle_up = true; default_conf_out: diff --git a/drivers/net/wireless/bcmdhd/dhd_linux.c b/drivers/net/wireless/bcmdhd/dhd_linux.c index 4bd2e39656ff..c639110c1b50 100644 --- a/drivers/net/wireless/bcmdhd/dhd_linux.c +++ b/drivers/net/wireless/bcmdhd/dhd_linux.c @@ -22,7 +22,7 @@ * software in any way with any other Broadcom software provided under a license * other than the GPL, without Broadcom's express prior written consent. * - * $Id: dhd_linux.c 307603 2012-01-12 01:32:01Z $ + * $Id: dhd_linux.c 308879 2012-01-17 22:03:47Z $ */ #include diff --git a/drivers/net/wireless/bcmdhd/dhd_sdio.c b/drivers/net/wireless/bcmdhd/dhd_sdio.c index a89195a9158c..3886297d631e 100644 --- a/drivers/net/wireless/bcmdhd/dhd_sdio.c +++ b/drivers/net/wireless/bcmdhd/dhd_sdio.c @@ -21,7 +21,7 @@ * software in any way with any other Broadcom software provided under a license * other than the GPL, without Broadcom's express prior written consent. * - * $Id: dhd_sdio.c 308574 2012-01-16 22:56:40Z $ + * $Id: dhd_sdio.c 309234 2012-01-19 01:44:16Z $ */ #include @@ -5195,6 +5195,12 @@ dhdsdio_chipmatch(uint16 chipid) return TRUE; if (chipid == BCM43239_CHIP_ID) return TRUE; + if (chipid == BCM4336_CHIP_ID) + return TRUE; + if (chipid == BCM43237_CHIP_ID) + return TRUE; + if (chipid == BCM43362_CHIP_ID) + return TRUE; return FALSE; } diff --git a/drivers/net/wireless/bcmdhd/include/epivers.h b/drivers/net/wireless/bcmdhd/include/epivers.h index f82ee1025749..53dd2f736734 100644 --- a/drivers/net/wireless/bcmdhd/include/epivers.h +++ b/drivers/net/wireless/bcmdhd/include/epivers.h @@ -33,17 +33,17 @@ #define EPI_RC_NUMBER 195 -#define EPI_INCREMENTAL_NUMBER 22 +#define EPI_INCREMENTAL_NUMBER 23 #define EPI_BUILD_NUMBER 0 -#define EPI_VERSION 5, 90, 195, 22 +#define EPI_VERSION 5, 90, 195, 23 -#define EPI_VERSION_NUM 0x055ac316 +#define EPI_VERSION_NUM 0x055ac317 #define EPI_VERSION_DEV 5.90.195 -#define EPI_VERSION_STR "5.90.195.22" +#define EPI_VERSION_STR "5.90.195.23" #endif diff --git a/drivers/net/wireless/bcmdhd/siutils.c b/drivers/net/wireless/bcmdhd/siutils.c index 1cc977f51ee3..a655ac4ef141 100644 --- a/drivers/net/wireless/bcmdhd/siutils.c +++ b/drivers/net/wireless/bcmdhd/siutils.c @@ -1897,6 +1897,11 @@ si_is_sprom_available(si_t *sih) return (sih->chipst & CST4315_SPROM_SEL) != 0; case BCM4319_CHIP_ID: return (sih->chipst & CST4319_SPROM_SEL) != 0; + + case BCM4336_CHIP_ID: + case BCM43362_CHIP_ID: + return (sih->chipst & CST4336_SPROM_PRESENT) != 0; + case BCM4330_CHIP_ID: return (sih->chipst & CST4330_SPROM_PRESENT) != 0; case BCM4313_CHIP_ID: diff --git a/drivers/net/wireless/bcmdhd/wl_cfg80211.c b/drivers/net/wireless/bcmdhd/wl_cfg80211.c index 79016b588fca..850c7241b6d6 100644 --- a/drivers/net/wireless/bcmdhd/wl_cfg80211.c +++ b/drivers/net/wireless/bcmdhd/wl_cfg80211.c @@ -820,12 +820,14 @@ wl_cfg80211_add_virtual_iface(struct wiphy *wiphy, char *name, p2p_on(wl) = true; wl_cfgp2p_set_firm_p2p(wl); wl_cfgp2p_init_discovery(wl); + get_primary_mac(wl, &primary_mac); + wl_cfgp2p_generate_bss_mac(&primary_mac, + &wl->p2p->dev_addr, &wl->p2p->int_addr); } memset(wl->p2p->vir_ifname, 0, IFNAMSIZ); strncpy(wl->p2p->vir_ifname, name, IFNAMSIZ - 1); - get_primary_mac(wl, &primary_mac); - wl_cfgp2p_generate_bss_mac(&primary_mac, &wl->p2p->dev_addr, &wl->p2p->int_addr); + /* In concurrency case, STA may be already associated in a particular channel. * so retrieve the current channel of primary interface and then start the virtual @@ -1318,6 +1320,25 @@ static s32 wl_do_iscan(struct wl_priv *wl, struct cfg80211_scan_request *request return err; } +static s32 +wl_get_valid_channels(struct net_device *ndev, u8 *valid_chan_list, s32 size) +{ + wl_uint32_list_t *list; + s32 err = BCME_OK; + if (valid_chan_list == NULL || size <= 0) + return -ENOMEM; + + memset(valid_chan_list, 0, size); + list = (wl_uint32_list_t *)(void *) valid_chan_list; + list->count = htod32(WL_NUMCHANNELS); + err = wldev_ioctl(ndev, WLC_GET_VALID_CHANNELS, valid_chan_list, size, false); + if (err != 0) { + WL_ERR(("get channels failed with %d\n", err)); + } + + return err; +} + static s32 wl_run_escan(struct wl_priv *wl, struct net_device *ndev, struct cfg80211_scan_request *request, uint16 action) @@ -1326,12 +1347,16 @@ wl_run_escan(struct wl_priv *wl, struct net_device *ndev, u32 n_channels; u32 n_ssids; s32 params_size = (WL_SCAN_PARAMS_FIXED_SIZE + OFFSETOF(wl_escan_params_t, params)); - wl_escan_params_t *params; + wl_escan_params_t *params = NULL; struct cfg80211_scan_request *scan_request = wl->scan_request; + u8 chan_buf[sizeof(u32)*(WL_NUMCHANNELS + 1)]; u32 num_chans = 0; + s32 channel; + s32 n_valid_chan; s32 search_state = WL_P2P_DISC_ST_SCAN; - u32 i; + u32 i, j, n_nodfs = 0; u16 *default_chan_list = NULL; + wl_uint32_list_t *list; struct net_device *dev = NULL; WL_DBG(("Enter \n")); @@ -1378,6 +1403,8 @@ wl_run_escan(struct wl_priv *wl, struct net_device *ndev, } else if (p2p_is_on(wl) && p2p_scan(wl)) { /* P2P SCAN TRIGGER */ + s32 _freq = 0; + n_nodfs = 0; if (scan_request && scan_request->n_channels) { num_chans = scan_request->n_channels; WL_SCAN((" chann number : %d\n", num_chans)); @@ -1388,11 +1415,26 @@ wl_run_escan(struct wl_priv *wl, struct net_device *ndev, err = -ENOMEM; goto exit; } - for (i = 0; i < num_chans; i++) - { - default_chan_list[i] = - ieee80211_frequency_to_channel( - scan_request->channels[i]->center_freq); + if (!wl_get_valid_channels(ndev, chan_buf, sizeof(chan_buf))) { + list = (wl_uint32_list_t *) chan_buf; + n_valid_chan = dtoh32(list->count); + for (i = 0; i < num_chans; i++) + { + _freq = scan_request->channels[i]->center_freq; + channel = ieee80211_frequency_to_channel(_freq); + /* remove DFS channels */ + if (channel < 52 || channel > 140) { + for (j = 0; j < n_valid_chan; j++) { + /* allows only supported channel on + * current reguatory + */ + if (channel == (dtoh32(list->element[j]))) + default_chan_list[n_nodfs++] = + channel; + } + } + + } } if (num_chans == 3 && ( (default_chan_list[0] == SOCIAL_CHAN_1) && @@ -1406,8 +1448,11 @@ wl_run_escan(struct wl_priv *wl, struct net_device *ndev, /* If you are already a GO, then do SEARCH only */ WL_INFO(("Already a GO. Do SEARCH Only")); search_state = WL_P2P_DISC_ST_SEARCH; + num_chans = n_nodfs; + } else { WL_INFO(("P2P SCAN STATE START \n")); + num_chans = n_nodfs; } } @@ -1459,6 +1504,7 @@ __wl_cfg80211_scan(struct wiphy *wiphy, struct net_device *ndev, struct wl_priv *wl = wiphy_priv(wiphy); struct cfg80211_ssid *ssids; struct wl_scan_req *sr = wl_to_sr(wl); + struct ether_addr primary_mac; wpa_ie_fixed_t *wps_ie; s32 passive_scan; bool iscan_req; @@ -1513,6 +1559,9 @@ __wl_cfg80211_scan(struct wiphy *wiphy, struct net_device *ndev, /* p2p on at the first time */ p2p_on(wl) = true; wl_cfgp2p_set_firm_p2p(wl); + get_primary_mac(wl, &primary_mac); + wl_cfgp2p_generate_bss_mac(&primary_mac, + &wl->p2p->dev_addr, &wl->p2p->int_addr); } p2p_scan(wl) = true; } @@ -2655,9 +2704,9 @@ wl_cfg80211_del_key(struct wiphy *wiphy, struct net_device *dev, CHECK_SYS_UP(wl); memset(&key, 0, sizeof(key)); - key.index = (u32) key_idx; key.flags = WL_PRIMARY_KEY; key.algo = CRYPTO_ALGO_OFF; + key.index = (u32) key_idx; WL_DBG(("key index (%d)\n", key_idx)); /* Set the new key/index */ @@ -3312,7 +3361,6 @@ wl_cfg80211_mgmt_tx(struct wiphy *wiphy, struct net_device *ndev, bool channel_type_valid, unsigned int wait, const u8* buf, size_t len, u64 *cookie) { - struct ether_addr primary_mac; wl_action_frame_t *action_frame; wl_af_params_t *af_params; wifi_p2p_ie_t *p2p_ie; @@ -3328,7 +3376,9 @@ wl_cfg80211_mgmt_tx(struct wiphy *wiphy, struct net_device *ndev, u32 id; u32 retry = 0; bool ack = false; - wifi_p2p_pub_act_frame_t *act_frm; + wifi_p2p_pub_act_frame_t *act_frm = NULL; + wifi_p2p_action_frame_t *p2p_act_frm = NULL; + wifi_p2psd_gas_pub_act_frame_t *sd_act_frm = NULL; s8 eabuf[ETHER_ADDR_STR_LEN]; WL_DBG(("Enter \n")); @@ -3348,8 +3398,6 @@ wl_cfg80211_mgmt_tx(struct wiphy *wiphy, struct net_device *ndev, return -ENODEV; } if (p2p_is_on(wl)) { - get_primary_mac(wl, &primary_mac); - wl_cfgp2p_generate_bss_mac(&primary_mac, &wl->p2p->dev_addr, &wl->p2p->int_addr); /* Suspend P2P discovery search-listen to prevent it from changing the * channel. */ @@ -3400,11 +3448,12 @@ wl_cfg80211_mgmt_tx(struct wiphy *wiphy, struct net_device *ndev, goto exit; } else if (ieee80211_is_action(mgmt->frame_control)) { - /* Abort the dwell time of any previous off-channel action frame that may - * be still in effect. Sending off-channel action frames relies on the - * driver's scan engine. If a previous off-channel action frame tx is - * still in progress (including the dwell time), then this new action - * frame will not be sent out. + /* Abort the dwell time of any previous off-channel + * action frame that may be still in effect. Sending + * off-channel action frames relies on the driver's + * scan engine. If a previous off-channel action frame + * tx is still in progress (including the dwell time), + * then this new action frame will not be sent out. */ wl_cfg80211_scan_abort(wl, dev); @@ -3455,50 +3504,80 @@ wl_cfg80211_mgmt_tx(struct wiphy *wiphy, struct net_device *ndev, af_params->dwell_time = WL_DWELL_TIME; memcpy(action_frame->data, &buf[DOT11_MGMT_HDR_LEN], action_frame->len); + if (wl_cfgp2p_is_pub_action(action_frame->data, action_frame->len)) { + act_frm = (wifi_p2p_pub_act_frame_t *) (action_frame->data); + WL_DBG(("P2P PUB action_frame->len: %d chan %d category %d subtype %d\n", + action_frame->len, af_params->channel, + act_frm->category, act_frm->subtype)); + } else if (wl_cfgp2p_is_p2p_action(action_frame->data, action_frame->len)) { + p2p_act_frm = (wifi_p2p_action_frame_t *) (action_frame->data); + WL_DBG(("P2P action_frame->len: %d chan %d category %d subtype %d\n", + action_frame->len, af_params->channel, + p2p_act_frm->category, p2p_act_frm->subtype)); + } else if (wl_cfgp2p_is_gas_action(action_frame->data, action_frame->len)) { + sd_act_frm = (wifi_p2psd_gas_pub_act_frame_t *) (action_frame->data); + WL_DBG(("Service Discovery action_frame->len: %d chan %d category %d action %d\n", + action_frame->len, af_params->channel, + sd_act_frm->category, sd_act_frm->action)); + + } + wl_cfgp2p_print_actframe(true, action_frame->data, action_frame->len); + /* + * To make sure to send successfully action frame, we have to turn off mpc + */ - act_frm = (wifi_p2p_pub_act_frame_t *) (action_frame->data); - WL_DBG(("action_frame->len: %d chan %d category %d subtype %d\n", - action_frame->len, af_params->channel, - act_frm->category, act_frm->subtype)); - /* - * To make sure to send successfully action frame, we have to turn off mpc - */ - if ((IS_PUB_ACT_FRAME(act_frm->category)) && - ((act_frm->subtype == P2P_PAF_GON_REQ) || + if (act_frm && ((act_frm->subtype == P2P_PAF_GON_REQ) || (act_frm->subtype == P2P_PAF_GON_RSP) || (act_frm->subtype == P2P_PAF_GON_CONF) || (act_frm->subtype == P2P_PAF_PROVDIS_REQ))) { wldev_iovar_setint(dev, "mpc", 0); } - if (IS_PUB_ACT_FRAME(act_frm->category)) { - if (act_frm->subtype == P2P_PAF_DEVDIS_REQ) { - af_params->dwell_time = WL_LONG_DWELL_TIME; - } else if ((act_frm->subtype == P2P_PAF_PROVDIS_REQ) || - (act_frm->subtype == P2P_PAF_PROVDIS_RSP)) { - af_params->dwell_time = WL_MED_DWELL_TIME; - } + if (act_frm && act_frm->subtype == P2P_PAF_DEVDIS_REQ) { + af_params->dwell_time = WL_LONG_DWELL_TIME; + } else if (act_frm && + (act_frm->subtype == P2P_PAF_PROVDIS_REQ || + act_frm->subtype == P2P_PAF_PROVDIS_RSP || + act_frm->subtype == P2P_PAF_GON_RSP)) { + af_params->dwell_time = WL_MED_DWELL_TIME; } + if (IS_P2P_SOCIAL(af_params->channel) && - (IS_P2P_ACT_REQ(act_frm->category, act_frm->subtype) || - IS_GAS_REQ(act_frm->category, act_frm->action)) && + (IS_P2P_PUB_ACT_REQ(act_frm, action_frame->len) || + IS_GAS_REQ(sd_act_frm, action_frame->len)) && wl_to_p2p_bss_saved_ie(wl, P2PAPI_BSSCFG_DEVICE).p2p_probe_req_ie_len) { /* channel offload require P2P IE for Probe request * otherwise, we will use wl_cfgp2p_tx_action_frame directly. * channel offload for action request frame - */ + */ + + /* channel offload for action request frame */ ack = wl_cfg80211_send_at_common_channel(wl, dev, af_params); } else { - for (retry = 0; retry < WL_CHANNEL_SYNC_RETRY; retry++) { - ack = (wl_cfgp2p_tx_action_frame(wl, dev, af_params, bssidx)) ? - false : true; - if (ack) - break; + ack = (wl_cfgp2p_tx_action_frame(wl, dev, af_params, bssidx)) ? false : true; + if (!ack) { + if (wl_to_p2p_bss_saved_ie(wl, P2PAPI_BSSCFG_DEVICE).p2p_probe_req_ie_len) { + /* if the NO ACK occurs, the peer device will be on + * listen channel of the peer + * So, we have to find the peer and send action frame on + * that channel. + */ + ack = wl_cfg80211_send_at_common_channel(wl, dev, af_params); + } else { + for (retry = 0; retry < WL_CHANNEL_SYNC_RETRY; retry++) { + ack = (wl_cfgp2p_tx_action_frame(wl, dev, + af_params, bssidx)) ? false : true; + if (ack) + break; + } + + } + } + } cfg80211_mgmt_tx_status(ndev, *cookie, buf, len, ack, GFP_KERNEL); - if (IS_PUB_ACT_FRAME(act_frm->category) && - (act_frm->subtype == P2P_PAF_GON_CONF)) { + if (act_frm && act_frm->subtype == P2P_PAF_GON_CONF) { wldev_iovar_setint(dev, "mpc", 1); } kfree(af_params); @@ -4235,7 +4314,7 @@ static s32 wl_setup_wiphy(struct wireless_dev *wdev, struct device *sdiofunc_dev #endif WIPHY_FLAG_4ADDR_STATION; #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 2, 0) - wdev->wiphy->flags |= WIPHY_FLAG_SUPPORTS_FW_ROAM; + wdev->wiphy->flags |= WIPHY_FLAG_SUPPORTS_FW_ROAM; #endif #ifdef ENABLE_CUSTOM_REGULATORY_DOMAIN @@ -4358,7 +4437,8 @@ static s32 wl_inform_single_bss(struct wl_priv *wl, struct wl_bss_info *bi) signal = notif_bss_info->rssi * 100; #if defined(WLP2P) && ENABLE_P2P_INTERFACE - if (wl->p2p_net && wl->scan_request && wl->scan_request->dev == wl->p2p_net) { + if (wl->p2p_net && wl->scan_request && + wl->scan_request->dev == wl->p2p_net) { #else if (p2p_is_on(wl) && p2p_scan(wl)) { #endif @@ -5057,7 +5137,9 @@ wl_notify_rx_mgmt_frame(struct wl_priv *wl, struct net_device *ndev, s32 err = 0; s32 freq; struct net_device *dev = NULL; - wifi_p2p_pub_act_frame_t *act_frm; + wifi_p2p_pub_act_frame_t *act_frm = NULL; + wifi_p2p_action_frame_t *p2p_act_frm = NULL; + wifi_p2psd_gas_pub_act_frame_t *sd_act_frm = NULL; wl_event_rx_frame_data_t *rxframe = (wl_event_rx_frame_data_t*)data; u32 event = ntoh32(e->event_type); @@ -5099,23 +5181,30 @@ wl_notify_rx_mgmt_frame(struct wl_priv *wl, struct net_device *ndev, goto exit; } isfree = true; - act_frm = - (wifi_p2p_pub_act_frame_t *) (&mgmt_frame[DOT11_MGMT_HDR_LEN]); + if (wl_cfgp2p_is_pub_action(&mgmt_frame[DOT11_MGMT_HDR_LEN], + mgmt_frame_len - DOT11_MGMT_HDR_LEN)) { + act_frm = (wifi_p2p_pub_act_frame_t *) + (&mgmt_frame[DOT11_MGMT_HDR_LEN]); + } else if (wl_cfgp2p_is_p2p_action(&mgmt_frame[DOT11_MGMT_HDR_LEN], + mgmt_frame_len - DOT11_MGMT_HDR_LEN)) { + p2p_act_frm = (wifi_p2p_action_frame_t *) + (&mgmt_frame[DOT11_MGMT_HDR_LEN]); + (void) p2p_act_frm; + } else if (wl_cfgp2p_is_gas_action(&mgmt_frame[DOT11_MGMT_HDR_LEN], + mgmt_frame_len - DOT11_MGMT_HDR_LEN)) { + sd_act_frm = (wifi_p2psd_gas_pub_act_frame_t *) + (&mgmt_frame[DOT11_MGMT_HDR_LEN]); + (void) sd_act_frm; + } + wl_cfgp2p_print_actframe(false, &mgmt_frame[DOT11_MGMT_HDR_LEN], + mgmt_frame_len - DOT11_MGMT_HDR_LEN); /* * After complete GO Negotiation, roll back to mpc mode */ - if (IS_PUB_ACT_FRAME(act_frm->category) && - ((act_frm->subtype == P2P_PAF_GON_CONF)|| - (act_frm->subtype == P2P_PAF_PROVDIS_RSP))) { + if (act_frm && ((act_frm->subtype == P2P_PAF_GON_CONF) || + (act_frm->subtype == P2P_PAF_PROVDIS_RSP))) { wldev_iovar_setint(dev, "mpc", 1); } - - if (IS_P2P_ACT_FRAME(act_frm->category) && - (act_frm->subtype == P2P_AF_PRESENCE_REQ)) { - /* TODO Do not submit these frames to supplicant, - * we will handle it in the driver - */ - } } else { mgmt_frame = (u8 *)((wl_event_rx_frame_data_t *)rxframe + 1); } @@ -6595,13 +6684,19 @@ static void wl_delay(u32 ms) s32 wl_cfg80211_get_p2p_dev_addr(struct net_device *net, struct ether_addr *p2pdev_addr) { - struct wl_priv *wl; + struct wl_priv *wl = wlcfg_drv_priv; struct ether_addr p2pif_addr; struct ether_addr primary_mac; - wl = wlcfg_drv_priv; - get_primary_mac(wl, &primary_mac); - wl_cfgp2p_generate_bss_mac(&primary_mac, p2pdev_addr, &p2pif_addr); + if (!wl->p2p) + return -1; + if (!p2p_is_on(wl)) { + get_primary_mac(wl, &primary_mac); + wl_cfgp2p_generate_bss_mac(&primary_mac, p2pdev_addr, &p2pif_addr); + } else { + memcpy(p2pdev_addr->octet, + wl->p2p->dev_addr.octet, ETHER_ADDR_LEN); + } return 0; } diff --git a/drivers/net/wireless/bcmdhd/wl_cfgp2p.c b/drivers/net/wireless/bcmdhd/wl_cfgp2p.c index 6991a9d78559..880123e067dc 100644 --- a/drivers/net/wireless/bcmdhd/wl_cfgp2p.c +++ b/drivers/net/wireless/bcmdhd/wl_cfgp2p.c @@ -67,6 +67,170 @@ static const struct net_device_ops wl_cfgp2p_if_ops = { .ndo_start_xmit = wl_cfgp2p_start_xmit, }; +bool wl_cfgp2p_is_pub_action(void *frame, u32 frame_len) +{ + wifi_p2p_pub_act_frame_t *pact_frm; + + if (frame == NULL) + return false; + pact_frm = (wifi_p2p_pub_act_frame_t *)frame; + if (frame_len < sizeof(wifi_p2p_pub_act_frame_t) -1) + return false; + + if (pact_frm->category == P2P_PUB_AF_CATEGORY && + pact_frm->action == P2P_PUB_AF_ACTION && + pact_frm->oui_type == P2P_VER && + memcmp(pact_frm->oui, P2P_OUI, sizeof(pact_frm->oui)) == 0) { + return true; + } + + return false; +} + +bool wl_cfgp2p_is_p2p_action(void *frame, u32 frame_len) +{ + wifi_p2p_action_frame_t *act_frm; + + if (frame == NULL) + return false; + act_frm = (wifi_p2p_action_frame_t *)frame; + if (frame_len < sizeof(wifi_p2p_action_frame_t) -1) + return false; + + if (act_frm->category == P2P_AF_CATEGORY && + act_frm->type == P2P_VER && + memcmp(act_frm->OUI, P2P_OUI, DOT11_OUI_LEN) == 0) { + return true; + } + + return false; +} +bool wl_cfgp2p_is_gas_action(void *frame, u32 frame_len) +{ + + wifi_p2psd_gas_pub_act_frame_t *sd_act_frm; + + if (frame == NULL) + return false; + + sd_act_frm = (wifi_p2psd_gas_pub_act_frame_t *)frame; + if (frame_len < sizeof(wifi_p2psd_gas_pub_act_frame_t) - 1) + return false; + if (sd_act_frm->category != P2PSD_ACTION_CATEGORY) + return false; + + if (sd_act_frm->action == P2PSD_ACTION_ID_GAS_IREQ || + sd_act_frm->action == P2PSD_ACTION_ID_GAS_IRESP || + sd_act_frm->action == P2PSD_ACTION_ID_GAS_CREQ || + sd_act_frm->action == P2PSD_ACTION_ID_GAS_CRESP) + return true; + else + return false; + +} +void wl_cfgp2p_print_actframe(bool tx, void *frame, u32 frame_len) +{ + wifi_p2p_pub_act_frame_t *pact_frm; + wifi_p2p_action_frame_t *act_frm; + wifi_p2psd_gas_pub_act_frame_t *sd_act_frm; + if (!frame || frame_len <= 2) + return; + + if (wl_cfgp2p_is_pub_action(frame, frame_len)) { + pact_frm = (wifi_p2p_pub_act_frame_t *)frame; + switch (pact_frm->subtype) { + case P2P_PAF_GON_REQ: + CFGP2P_DBG(("%s P2P Group Owner Negotiation Req Frame\n", + (tx)? "TX": "RX")); + break; + case P2P_PAF_GON_RSP: + CFGP2P_DBG(("%s P2P Group Owner Negotiation Rsp Frame\n", + (tx)? "TX": "RX")); + break; + case P2P_PAF_GON_CONF: + CFGP2P_DBG(("%s P2P Group Owner Negotiation Confirm Frame\n", + (tx)? "TX": "RX")); + break; + case P2P_PAF_INVITE_REQ: + CFGP2P_DBG(("%s P2P Invitation Request Frame\n", + (tx)? "TX": "RX")); + break; + case P2P_PAF_INVITE_RSP: + CFGP2P_DBG(("%s P2P Invitation Response Frame\n", + (tx)? "TX": "RX")); + break; + case P2P_PAF_DEVDIS_REQ: + CFGP2P_DBG(("%s P2P Device Discoverability Request Frame\n", + (tx)? "TX": "RX")); + break; + case P2P_PAF_DEVDIS_RSP: + CFGP2P_DBG(("%s P2P Device Discoverability Response Frame\n", + (tx)? "TX": "RX")); + break; + case P2P_PAF_PROVDIS_REQ: + CFGP2P_DBG(("%s P2P Provision Discovery Request Frame\n", + (tx)? "TX": "RX")); + break; + case P2P_PAF_PROVDIS_RSP: + CFGP2P_DBG(("%s P2P Provision Discovery Response Frame\n", + (tx)? "TX": "RX")); + break; + default: + CFGP2P_DBG(("%s Unknown P2P Public Action Frame\n", + (tx)? "TX": "RX")); + + } + + } else if (wl_cfgp2p_is_p2p_action(frame, frame_len)) { + act_frm = (wifi_p2p_action_frame_t *)frame; + switch (act_frm->subtype) { + case P2P_AF_NOTICE_OF_ABSENCE: + CFGP2P_DBG(("%s P2P Notice of Absence Frame\n", + (tx)? "TX": "RX")); + break; + case P2P_AF_PRESENCE_REQ: + CFGP2P_DBG(("%s P2P Presence Request Frame\n", + (tx)? "TX": "RX")); + break; + case P2P_AF_PRESENCE_RSP: + CFGP2P_DBG(("%s P2P Presence Response Frame\n", + (tx)? "TX": "RX")); + break; + case P2P_AF_GO_DISC_REQ: + CFGP2P_DBG(("%s P2P Discoverability Request Frame\n", + (tx)? "TX": "RX")); + break; + default: + CFGP2P_DBG(("%s Unknown P2P Action Frame\n", + (tx)? "TX": "RX")); + } + + } else if (wl_cfgp2p_is_gas_action(frame, frame_len)) { + sd_act_frm = (wifi_p2psd_gas_pub_act_frame_t *)frame; + switch (sd_act_frm->action) { + case P2PSD_ACTION_ID_GAS_IREQ: + CFGP2P_DBG(("%s P2P GAS Initial Request\n", + (tx)? "TX" : "RX")); + break; + case P2PSD_ACTION_ID_GAS_IRESP: + CFGP2P_DBG(("%s P2P GAS Initial Response\n", + (tx)? "TX" : "RX")); + break; + case P2PSD_ACTION_ID_GAS_CREQ: + CFGP2P_DBG(("%s P2P GAS Comback Request\n", + (tx)? "TX" : "RX")); + break; + case P2PSD_ACTION_ID_GAS_CRESP: + CFGP2P_DBG(("%s P2P GAS Comback Response\n", + (tx)? "TX" : "RX")); + break; + default: + CFGP2P_DBG(("%s Unknown P2P GAS Frame\n", + (tx)? "TX" : "RX")); + } + } +} + /* * Initialize variables related to P2P * @@ -1373,7 +1537,8 @@ wl_cfgp2p_down(struct wl_priv *wl) return 0; } -s32 wl_cfgp2p_set_p2p_noa(struct wl_priv *wl, struct net_device *ndev, char* buf, int len) +s32 +wl_cfgp2p_set_p2p_noa(struct wl_priv *wl, struct net_device *ndev, char* buf, int len) { s32 ret = -1; int count, start, duration; @@ -1446,7 +1611,8 @@ s32 wl_cfgp2p_set_p2p_noa(struct wl_priv *wl, struct net_device *ndev, char* buf return ret; } -s32 wl_cfgp2p_get_p2p_noa(struct wl_priv *wl, struct net_device *ndev, char* buf, int buf_len) +s32 +wl_cfgp2p_get_p2p_noa(struct wl_priv *wl, struct net_device *ndev, char* buf, int buf_len) { wifi_p2p_noa_desc_t *noa_desc; int len = 0, i; @@ -1488,7 +1654,8 @@ s32 wl_cfgp2p_get_p2p_noa(struct wl_priv *wl, struct net_device *ndev, char* buf return len * 2; } -s32 wl_cfgp2p_set_p2p_ps(struct wl_priv *wl, struct net_device *ndev, char* buf, int len) +s32 +wl_cfgp2p_set_p2p_ps(struct wl_priv *wl, struct net_device *ndev, char* buf, int len) { int ps, ctw; int ret = -1; @@ -1552,7 +1719,7 @@ wl_cfgp2p_retreive_p2pattrib(void *buf, u8 element_id) len -= 4; /* exclude OUI + OUI_TYPE */ while (len >= 3) { - /* attribute id */ + /* attribute id */ subelt_id = *subel; subel += 1; len -= 1; diff --git a/drivers/net/wireless/bcmdhd/wl_cfgp2p.h b/drivers/net/wireless/bcmdhd/wl_cfgp2p.h index d50b00f8394c..1e5b1197e92d 100644 --- a/drivers/net/wireless/bcmdhd/wl_cfgp2p.h +++ b/drivers/net/wireless/bcmdhd/wl_cfgp2p.h @@ -101,13 +101,13 @@ enum wl_cfgp2p_status { #define wl_to_p2p_bss_saved_ie(w, type) ((wl)->p2p->bss_idx[type].saved_ie) #define wl_to_p2p_bss_private(w, type) ((wl)->p2p->bss_idx[type].private_data) #define wl_to_p2p_bss(wl, type) ((wl)->p2p->bss_idx[type]) -#define wl_get_p2p_status(wl, stat) ((!(wl)->p2p_supported) ? 0 : test_bit(WLP2P_STATUS_ ## stat, \ +#define wl_get_p2p_status(wl, stat) ((!(wl)->p2p_supported) ? 0:test_bit(WLP2P_STATUS_ ## stat, \ &(wl)->p2p->status)) -#define wl_set_p2p_status(wl, stat) ((!(wl)->p2p_supported) ? 0 : set_bit(WLP2P_STATUS_ ## stat, \ +#define wl_set_p2p_status(wl, stat) ((!(wl)->p2p_supported) ? 0:set_bit(WLP2P_STATUS_ ## stat, \ &(wl)->p2p->status)) -#define wl_clr_p2p_status(wl, stat) ((!(wl)->p2p_supported) ? 0 : clear_bit(WLP2P_STATUS_ ## stat, \ +#define wl_clr_p2p_status(wl, stat) ((!(wl)->p2p_supported) ? 0:clear_bit(WLP2P_STATUS_ ## stat, \ &(wl)->p2p->status)) -#define wl_chg_p2p_status(wl, stat) ((!(wl)->p2p_supported) ? 0: change_bit(WLP2P_STATUS_ ## stat, \ +#define wl_chg_p2p_status(wl, stat) ((!(wl)->p2p_supported) ? 0:change_bit(WLP2P_STATUS_ ## stat, \ &(wl)->p2p->status)) #define p2p_on(wl) ((wl)->p2p->on) #define p2p_scan(wl) ((wl)->p2p->scan) @@ -140,7 +140,14 @@ enum wl_cfgp2p_status { } \ } while (0) - +extern bool +wl_cfgp2p_is_pub_action(void *frame, u32 frame_len); +extern bool +wl_cfgp2p_is_p2p_action(void *frame, u32 frame_len); +extern bool +wl_cfgp2p_is_gas_action(void *frame, u32 frame_len); +extern void +wl_cfgp2p_print_actframe(bool tx, void *frame, u32 frame_len); extern s32 wl_cfgp2p_init_priv(struct wl_priv *wl); extern void @@ -260,17 +267,15 @@ wl_cfgp2p_unregister_ndev(struct wl_priv *wl); #define WL_P2P_WILDCARD_SSID_LEN 7 #define WL_P2P_INTERFACE_PREFIX "p2p" #define WL_P2P_TEMP_CHAN "11" -#define IS_PUB_ACT_FRAME(category) ((category == P2P_PUB_AF_CATEGORY)) -#define IS_P2P_ACT_FRAME(category) ((category == P2P_AF_CATEGORY)) - -#define IS_P2P_ACTION(categry, action) (IS_PUB_ACT_FRAME(category) && (action == P2P_PUB_AF_ACTION)) -#define IS_GAS_REQ(category, action) (IS_PUB_ACT_FRAME(category) && \ - ((action == P2PSD_ACTION_ID_GAS_IREQ) || \ - (action == P2PSD_ACTION_ID_GAS_CREQ))) -#define IS_P2P_ACT_REQ(category, subtype) (IS_PUB_ACT_FRAME(category) && \ - ((subtype == P2P_PAF_GON_REQ) || \ - (subtype == P2P_PAF_INVITE_REQ) || \ - (subtype == P2P_PAF_PROVDIS_REQ))) + + +#define IS_GAS_REQ(frame, len) (wl_cfgp2p_is_gas_action(frame, len) && \ + ((frame->action == P2PSD_ACTION_ID_GAS_IREQ) || \ + (frame->action == P2PSD_ACTION_ID_GAS_CREQ))) +#define IS_P2P_PUB_ACT_REQ(frame, len) (wl_cfgp2p_is_pub_action(frame, len) && \ + ((frame->subtype == P2P_PAF_GON_REQ) || \ + (frame->subtype == P2P_PAF_INVITE_REQ) || \ + (frame->subtype == P2P_PAF_PROVDIS_REQ))) #define IS_P2P_SOCIAL(ch) ((ch == SOCIAL_CHAN_1) || (ch == SOCIAL_CHAN_2) || (ch == SOCIAL_CHAN_3)) #define IS_P2P_SSID(ssid) (memcmp(ssid, WL_P2P_WILDCARD_SSID, WL_P2P_WILDCARD_SSID_LEN) == 0) #endif /* _wl_cfgp2p_h_ */ -- cgit v1.2.3 From 348c1c0eba7adc2fa9aa387eb1bcb3a1199a20be Mon Sep 17 00:00:00 2001 From: Dmitry Shmidt Date: Mon, 30 Jan 2012 13:03:19 -0800 Subject: net: wireless: bcmdhd: Daemonize wl_event_handler Daemonizing makes thread (besides other things) NON-FREEZABLE, and it will not get fake signal on suspend to quicl down_interruptible() Signed-off-by: Dmitry Shmidt --- drivers/net/wireless/bcmdhd/dhd_linux.c | 13 ------------- drivers/net/wireless/bcmdhd/include/linuxver.h | 12 ++++++++++++ drivers/net/wireless/bcmdhd/wl_cfg80211.c | 3 +++ 3 files changed, 15 insertions(+), 13 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/bcmdhd/dhd_linux.c b/drivers/net/wireless/bcmdhd/dhd_linux.c index c639110c1b50..a73d48da4a42 100644 --- a/drivers/net/wireless/bcmdhd/dhd_linux.c +++ b/drivers/net/wireless/bcmdhd/dhd_linux.c @@ -360,19 +360,6 @@ uint dhd_radio_up = 1; char iface_name[IFNAMSIZ] = {'\0'}; module_param_string(iface_name, iface_name, IFNAMSIZ, 0); -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0)) -#define DAEMONIZE(a) daemonize(a); \ - allow_signal(SIGKILL); \ - allow_signal(SIGTERM); -#else /* Linux 2.4 (w/o preemption patch) */ -#define RAISE_RX_SOFTIRQ() \ - cpu_raise_softirq(smp_processor_id(), NET_RX_SOFTIRQ) -#define DAEMONIZE(a) daemonize(); \ - do { if (a) \ - strncpy(current->comm, a, MIN(sizeof(current->comm), (strlen(a) + 1))); \ - } while (0); -#endif /* LINUX_VERSION_CODE */ - #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0)) #define BLOCKABLE() (!in_atomic()) #else diff --git a/drivers/net/wireless/bcmdhd/include/linuxver.h b/drivers/net/wireless/bcmdhd/include/linuxver.h index e5189821b4cb..d269e66f7fb8 100644 --- a/drivers/net/wireless/bcmdhd/include/linuxver.h +++ b/drivers/net/wireless/bcmdhd/include/linuxver.h @@ -511,6 +511,18 @@ typedef struct { (tsk_ctl)->thr_pid = -1; \ } +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0)) +#define DAEMONIZE(a) daemonize(a); \ + allow_signal(SIGKILL); \ + allow_signal(SIGTERM); +#else /* Linux 2.4 (w/o preemption patch) */ +#define RAISE_RX_SOFTIRQ() \ + cpu_raise_softirq(smp_processor_id(), NET_RX_SOFTIRQ) +#define DAEMONIZE(a) daemonize(); \ + do { if (a) \ + strncpy(current->comm, a, MIN(sizeof(current->comm), (strlen(a) + 1))); \ + } while (0); +#endif /* LINUX_VERSION_CODE */ #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 31)) diff --git a/drivers/net/wireless/bcmdhd/wl_cfg80211.c b/drivers/net/wireless/bcmdhd/wl_cfg80211.c index 850c7241b6d6..fea69cf4244c 100644 --- a/drivers/net/wireless/bcmdhd/wl_cfg80211.c +++ b/drivers/net/wireless/bcmdhd/wl_cfg80211.c @@ -6138,6 +6138,9 @@ static s32 wl_event_handler(void *data) tsk_ctl_t *tsk = (tsk_ctl_t *)data; wl = (struct wl_priv *)tsk->parent; + + DAEMONIZE("wl_event_handler"); + complete(&tsk->completed); while (down_interruptible (&tsk->sema) == 0) { -- cgit v1.2.3 From 8443906ad4d452f9c2e2d03a3ab51a9123ffd718 Mon Sep 17 00:00:00 2001 From: Dmitry Shmidt Date: Mon, 30 Jan 2012 15:43:31 -0800 Subject: net: wireless: bcmdhd: Fix crash on dhdsdio_probe_attach() failure Signed-off-by: Dmitry Shmidt --- drivers/net/wireless/bcmdhd/dhd_linux.c | 17 ++++++++++++++--- drivers/net/wireless/bcmdhd/dhd_sdio.c | 8 +++++++- 2 files changed, 21 insertions(+), 4 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/bcmdhd/dhd_linux.c b/drivers/net/wireless/bcmdhd/dhd_linux.c index a73d48da4a42..886c082ed618 100644 --- a/drivers/net/wireless/bcmdhd/dhd_linux.c +++ b/drivers/net/wireless/bcmdhd/dhd_linux.c @@ -2346,7 +2346,12 @@ dhd_open(struct net_device *net) * We keep WEXT's wl_control_wl_start to provide backward compatibility * This should be removed in the future */ - wl_control_wl_start(net); + ret = wl_control_wl_start(net); + if (ret != 0) { + DHD_ERROR(("%s: failed with code %d\n", __FUNCTION__, ret)); + ret = -1; + goto exit; + } #endif ifidx = dhd_net2idx(dhd, net); @@ -2368,8 +2373,14 @@ dhd_open(struct net_device *net) atomic_set(&dhd->pend_8021x_cnt, 0); #if defined(WL_CFG80211) DHD_ERROR(("\n%s\n", dhd_version)); - if (!dhd_download_fw_on_driverload) - wl_android_wifi_on(net); + if (!dhd_download_fw_on_driverload) { + ret = wl_android_wifi_on(net); + if (ret != 0) { + DHD_ERROR(("%s: failed with code %d\n", __FUNCTION__, ret)); + ret = -1; + goto exit; + } + } #endif /* defined(WL_CFG80211) */ if (dhd->pub.busstate != DHD_BUS_DATA) { diff --git a/drivers/net/wireless/bcmdhd/dhd_sdio.c b/drivers/net/wireless/bcmdhd/dhd_sdio.c index 3886297d631e..196dc7acd762 100644 --- a/drivers/net/wireless/bcmdhd/dhd_sdio.c +++ b/drivers/net/wireless/bcmdhd/dhd_sdio.c @@ -2785,6 +2785,9 @@ dhdsdio_download_state(dhd_bus_t *bus, bool enter) uint retries; int bcmerror = 0; + if (!bus->sih) + return BCME_ERROR; + /* To enter download state, disable ARM and reset SOCRAM. * To exit download state, simply reset ARM (default is RAM boot). */ @@ -5555,8 +5558,10 @@ dhdsdio_probe_attach(struct dhd_bus *bus, osl_t *osh, void *sdh, void *regsva, return TRUE; fail: - if (bus->sih != NULL) + if (bus->sih != NULL) { si_detach(bus->sih); + bus->sih = NULL; + } return FALSE; } @@ -5789,6 +5794,7 @@ dhdsdio_release_dongle(dhd_bus_t *bus, osl_t *osh, bool dongle_isolation, bool r dhdsdio_clkctl(bus, CLK_NONE, FALSE); } si_detach(bus->sih); + bus->sih = NULL; if (bus->vars && bus->varsz) MFREE(osh, bus->vars, bus->varsz); bus->vars = NULL; -- cgit v1.2.3 From 1534f1150e79d34315fbb3dff91bbf496d8d1483 Mon Sep 17 00:00:00 2001 From: Dmitry Shmidt Date: Tue, 31 Jan 2012 11:06:23 -0800 Subject: net: wireless: bcmdhd: Increase pm_notify callback priority Make pm_notify callback to be called the first on suspend/resume path to ensure it will always be called. Signed-off-by: Dmitry Shmidt --- drivers/net/wireless/bcmdhd/dhd_linux.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/bcmdhd/dhd_linux.c b/drivers/net/wireless/bcmdhd/dhd_linux.c index 886c082ed618..a04c88f6524f 100644 --- a/drivers/net/wireless/bcmdhd/dhd_linux.c +++ b/drivers/net/wireless/bcmdhd/dhd_linux.c @@ -496,7 +496,7 @@ static int dhd_sleep_pm_callback(struct notifier_block *nfb, unsigned long actio static struct notifier_block dhd_sleep_pm_notifier = { .notifier_call = dhd_sleep_pm_callback, - .priority = 0 + .priority = 10 }; extern int register_pm_notifier(struct notifier_block *nb); extern int unregister_pm_notifier(struct notifier_block *nb); -- cgit v1.2.3 From 9053d7de1602c2f3bedee02fe49274dc5ecd23ba Mon Sep 17 00:00:00 2001 From: "Mike J. Chen" Date: Wed, 15 Feb 2012 21:54:57 -0800 Subject: net: wireless: bcmdhd: Fix driver hang when resetting bus->tx_max was not being initialized when we do a reset and the driver is statically linked. this led to about a 50% chance that it would be considered an illegal value when we send the mac address to the FW. add code to initialize it to a safe value until we receive the right value from the fw. Bug: 5974574 Change-Id: I28ab25d97203ef075e5354c25f85a25daaff5594 Signed-off-by: Mike J. Chen Signed-off-by: Dmitry Shmidt --- drivers/net/wireless/bcmdhd/dhd_sdio.c | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'drivers/net') diff --git a/drivers/net/wireless/bcmdhd/dhd_sdio.c b/drivers/net/wireless/bcmdhd/dhd_sdio.c index 196dc7acd762..05316635144a 100644 --- a/drivers/net/wireless/bcmdhd/dhd_sdio.c +++ b/drivers/net/wireless/bcmdhd/dhd_sdio.c @@ -3061,6 +3061,13 @@ dhd_bus_stop(struct dhd_bus *bus, bool enforce_mutex) bus->rxskip = FALSE; bus->tx_seq = bus->rx_seq = 0; + /* Set to a safe default. It gets updated when we + * receive a packet from the fw but when we reset, + * we need a safe default to be able to send the + * initial mac address. + */ + bus->tx_max = 4; + if (enforce_mutex) dhd_os_sdunlock(bus->dhd); } -- cgit v1.2.3 From 471e510735fd972e44f7d303c2b51a847702695b Mon Sep 17 00:00:00 2001 From: Dmitry Shmidt Date: Thu, 23 Feb 2012 10:36:40 -0800 Subject: net: wireless: bcmdhd: Turn interface down (only) in case of FW crash Signed-off-by: Dmitry Shmidt --- drivers/net/wireless/bcmdhd/dhd_linux.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/bcmdhd/dhd_linux.c b/drivers/net/wireless/bcmdhd/dhd_linux.c index a04c88f6524f..bd479acfc382 100644 --- a/drivers/net/wireless/bcmdhd/dhd_linux.c +++ b/drivers/net/wireless/bcmdhd/dhd_linux.c @@ -4392,17 +4392,23 @@ int net_os_send_hang_message(struct net_device *dev) { dhd_info_t *dhd = *(dhd_info_t **)netdev_priv(dev); int ret = 0; + int need_unlock = 0; if (dhd) { if (!dhd->pub.hang_was_sent) { dhd->pub.hang_was_sent = 1; + if (!rtnl_is_locked()) { + need_unlock = 1; + rtnl_lock(); + } + dev_close(dev); + if (need_unlock) + rtnl_unlock(); #if defined(CONFIG_BCMDHD_WEXT) ret = wl_iw_send_priv_event(dev, "HANG"); #endif #if defined(WL_CFG80211) ret = wl_cfg80211_hang(dev, WLAN_REASON_UNSPECIFIED); - dev_close(dev); - dev_open(dev); #endif } } -- cgit v1.2.3 From 70180a701b86c939904d778f109fc6911e667002 Mon Sep 17 00:00:00 2001 From: Dmitry Shmidt Date: Mon, 27 Feb 2012 12:35:15 -0800 Subject: net: wireless: bcmdhd: Update to Version 5.90.195.28 - Improve scan for p2p - Use use_rxchain support - Use WL_WIRELESS_EXT instead of CONFIG_WIRELESS_EXT - Initial sched_scan support Signed-off-by: Dmitry Shmidt --- drivers/net/wireless/bcmdhd/Makefile | 2 +- drivers/net/wireless/bcmdhd/aiutils.c | 2 +- drivers/net/wireless/bcmdhd/bcmsdh.c | 2 +- drivers/net/wireless/bcmdhd/bcmsdh_linux.c | 18 +- drivers/net/wireless/bcmdhd/bcmsdh_sdmmc.c | 204 +++++-- drivers/net/wireless/bcmdhd/bcmsdh_sdmmc_linux.c | 5 +- drivers/net/wireless/bcmdhd/dhd_cfg80211.c | 2 +- drivers/net/wireless/bcmdhd/dhd_linux.c | 36 +- drivers/net/wireless/bcmdhd/dhd_sdio.c | 2 +- drivers/net/wireless/bcmdhd/include/bcmsdh_sdmmc.h | 9 +- drivers/net/wireless/bcmdhd/include/epivers.h | 8 +- drivers/net/wireless/bcmdhd/include/linuxver.h | 7 +- drivers/net/wireless/bcmdhd/include/sbchipc.h | 5 +- drivers/net/wireless/bcmdhd/include/wlioctl.h | 4 +- drivers/net/wireless/bcmdhd/wl_android.c | 6 +- drivers/net/wireless/bcmdhd/wl_cfg80211.c | 597 ++++++++++++++++----- drivers/net/wireless/bcmdhd/wl_cfg80211.h | 4 + drivers/net/wireless/bcmdhd/wl_iw.c | 3 - 18 files changed, 674 insertions(+), 242 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/bcmdhd/Makefile b/drivers/net/wireless/bcmdhd/Makefile index 14c041dcc2b1..ef5e3d5e5f72 100644 --- a/drivers/net/wireless/bcmdhd/Makefile +++ b/drivers/net/wireless/bcmdhd/Makefile @@ -44,7 +44,7 @@ bcmdhd-objs += $(DHDOFILES) ifeq ($(CONFIG_BCMDHD_WEXT),y) bcmdhd-objs += wl_iw.o -DHDCFLAGS += -DSOFTAP +DHDCFLAGS += -DSOFTAP -DWL_WIRELESS_EXT endif ifeq ($(CONFIG_BCMDHD_CFG80211),y) diff --git a/drivers/net/wireless/bcmdhd/aiutils.c b/drivers/net/wireless/bcmdhd/aiutils.c index 059df8907928..5ca0993c9333 100644 --- a/drivers/net/wireless/bcmdhd/aiutils.c +++ b/drivers/net/wireless/bcmdhd/aiutils.c @@ -22,7 +22,7 @@ * software in any way with any other Broadcom software provided under a license * other than the GPL, without Broadcom's express prior written consent. * - * $Id: aiutils.c,v 1.26.2.1 2010-03-09 18:41:21 Exp $ + * $Id: aiutils.c,v 1.26.2.1 2010-03-09 18:41:21 $ */ diff --git a/drivers/net/wireless/bcmdhd/bcmsdh.c b/drivers/net/wireless/bcmdhd/bcmsdh.c index 918c8e648f13..f67b13a03a1c 100644 --- a/drivers/net/wireless/bcmdhd/bcmsdh.c +++ b/drivers/net/wireless/bcmdhd/bcmsdh.c @@ -22,7 +22,7 @@ * software in any way with any other Broadcom software provided under a license * other than the GPL, without Broadcom's express prior written consent. * - * $Id: bcmsdh.c 275784 2011-08-04 22:41:49Z $ + * $Id: bcmsdh.c 300445 2011-12-03 05:37:20Z $ */ /** diff --git a/drivers/net/wireless/bcmdhd/bcmsdh_linux.c b/drivers/net/wireless/bcmdhd/bcmsdh_linux.c index 90f554888c79..237af4ae8417 100644 --- a/drivers/net/wireless/bcmdhd/bcmsdh_linux.c +++ b/drivers/net/wireless/bcmdhd/bcmsdh_linux.c @@ -21,7 +21,7 @@ * software in any way with any other Broadcom software provided under a license * other than the GPL, without Broadcom's express prior written consent. * - * $Id: bcmsdh_linux.c 308641 2012-01-17 02:18:02Z $ + * $Id: bcmsdh_linux.c 312788 2012-02-03 23:06:32Z $ */ /** @@ -623,13 +623,6 @@ int bcmsdh_register_oob_intr(void * dhdp) return 0; } -void *bcmsdh_get_drvdata(void) -{ - if (!sdhcinfo) - return NULL; - return dev_get_drvdata(sdhcinfo->dev); -} - void bcmsdh_set_irq(int flag) { if (sdhcinfo->oob_irq_registered && sdhcinfo->oob_irq_enable_flag != flag) { @@ -657,6 +650,15 @@ void bcmsdh_unregister_oob_intr(void) } #endif /* defined(OOB_INTR_ONLY) */ +#if defined(BCMLXSDMMC) +void *bcmsdh_get_drvdata(void) +{ + if (!sdhcinfo) + return NULL; + return dev_get_drvdata(sdhcinfo->dev); +} +#endif + /* Module parameters specific to each host-controller driver */ extern uint sd_msglevel; /* Debug message level */ diff --git a/drivers/net/wireless/bcmdhd/bcmsdh_sdmmc.c b/drivers/net/wireless/bcmdhd/bcmsdh_sdmmc.c index d890f2fa31e8..b47c9423b635 100644 --- a/drivers/net/wireless/bcmdhd/bcmsdh_sdmmc.c +++ b/drivers/net/wireless/bcmdhd/bcmsdh_sdmmc.c @@ -21,7 +21,7 @@ * software in any way with any other Broadcom software provided under a license * other than the GPL, without Broadcom's express prior written consent. * - * $Id: bcmsdh_sdmmc.c 301794 2011-12-08 20:41:35Z $ + * $Id: bcmsdh_sdmmc.c 314904 2012-02-14 21:36:04Z $ */ #include @@ -35,6 +35,7 @@ #include /* ioctl/iovars */ #include +#include #include #include @@ -148,6 +149,7 @@ sdioh_attach(osl_t *osh, void *bar0, uint irq) sd->sd_blockmode = TRUE; sd->use_client_ints = TRUE; sd->client_block_size[0] = 64; + sd->use_rxchain = FALSE; gInstance->sd = sd; @@ -523,7 +525,7 @@ sdioh_iovar_op(sdioh_info_t *si, const char *name, } case IOV_GVAL(IOV_RXCHAIN): - int_val = FALSE; + int_val = (int32)si->use_rxchain; bcopy(&int_val, arg, val_size); break; @@ -913,8 +915,12 @@ sdioh_request_packet(sdioh_info_t *sd, uint fix_inc, uint write, uint func, bool fifo = (fix_inc == SDIOH_DATA_FIX); uint32 SGCount = 0; int err_ret = 0; - - void *pnext; + void *pnext, *pprev; + uint ttl_len, dma_len, lft_len, xfred_len, pkt_len; + uint blk_num; + struct mmc_request mmc_req; + struct mmc_command mmc_cmd; + struct mmc_data mmc_dat; sd_trace(("%s: Enter\n", __FUNCTION__)); @@ -922,66 +928,148 @@ sdioh_request_packet(sdioh_info_t *sd, uint fix_inc, uint write, uint func, DHD_PM_RESUME_WAIT(sdioh_request_packet_wait); DHD_PM_RESUME_RETURN_ERROR(SDIOH_API_RC_FAIL); - /* Claim host controller */ - sdio_claim_host(gInstance->func[func]); - for (pnext = pkt; pnext; pnext = PKTNEXT(sd->osh, pnext)) { - uint pkt_len = PKTLEN(sd->osh, pnext); - pkt_len += 3; - pkt_len &= 0xFFFFFFFC; + ttl_len = xfred_len = 0; + /* at least 4 bytes alignment of skb buff is guaranteed */ + for (pnext = pkt; pnext; pnext = PKTNEXT(sd->osh, pnext)) + ttl_len += PKTLEN(sd->osh, pnext); -#ifdef CONFIG_MMC_MSM7X00A - if ((pkt_len % 64) == 32) { - sd_trace(("%s: Rounding up TX packet +=32\n", __FUNCTION__)); - pkt_len += 32; - } -#endif /* CONFIG_MMC_MSM7X00A */ - /* Make sure the packet is aligned properly. If it isn't, then this - * is the fault of sdioh_request_buffer() which is supposed to give - * us something we can work with. - */ - ASSERT(((uint32)(PKTDATA(sd->osh, pkt)) & DMA_ALIGN_MASK) == 0); - - if ((write) && (!fifo)) { - err_ret = sdio_memcpy_toio(gInstance->func[func], addr, - ((uint8*)PKTDATA(sd->osh, pnext)), - pkt_len); - } else if (write) { - err_ret = sdio_memcpy_toio(gInstance->func[func], addr, - ((uint8*)PKTDATA(sd->osh, pnext)), - pkt_len); - } else if (fifo) { - err_ret = sdio_readsb(gInstance->func[func], - ((uint8*)PKTDATA(sd->osh, pnext)), - addr, - pkt_len); - } else { - err_ret = sdio_memcpy_fromio(gInstance->func[func], - ((uint8*)PKTDATA(sd->osh, pnext)), - addr, + if (!sd->use_rxchain || ttl_len <= sd->client_block_size[func]) { + blk_num = 0; + dma_len = 0; + } else { + blk_num = ttl_len / sd->client_block_size[func]; + dma_len = blk_num * sd->client_block_size[func]; + } + lft_len = ttl_len - dma_len; + + sd_trace(("%s: %s %dB to func%d:%08x, %d blks with DMA, %dB leftover\n", + __FUNCTION__, write ? "W" : "R", + ttl_len, func, addr, blk_num, lft_len)); + + if (0 != dma_len) { + memset(&mmc_req, 0, sizeof(struct mmc_request)); + memset(&mmc_cmd, 0, sizeof(struct mmc_command)); + memset(&mmc_dat, 0, sizeof(struct mmc_data)); + + /* Set up DMA descriptors */ + pprev = pkt; + for (pnext = pkt; + pnext && dma_len; + pnext = PKTNEXT(sd->osh, pnext)) { + pkt_len = PKTLEN(sd->osh, pnext); + + if (dma_len > pkt_len) + dma_len -= pkt_len; + else { + pkt_len = xfred_len = dma_len; + dma_len = 0; + pkt = pnext; + } + + sg_set_buf(&sd->sg_list[SGCount++], + (uint8*)PKTDATA(sd->osh, pnext), pkt_len); - } - if (err_ret) { - sd_err(("%s: %s FAILED %p[%d], addr=0x%05x, pkt_len=%d, ERR=0x%08x\n", - __FUNCTION__, - (write) ? "TX" : "RX", - pnext, SGCount, addr, pkt_len, err_ret)); - } else { - sd_trace(("%s: %s xfr'd %p[%d], addr=0x%05x, len=%d\n", - __FUNCTION__, - (write) ? "TX" : "RX", - pnext, SGCount, addr, pkt_len)); + if (SGCount >= SDIOH_SDMMC_MAX_SG_ENTRIES) { + sd_err(("%s: sg list entries exceed limit\n", + __FUNCTION__)); + return (SDIOH_API_RC_FAIL); + } } - if (!fifo) { - addr += pkt_len; - } - SGCount ++; + mmc_dat.sg = sd->sg_list; + mmc_dat.sg_len = SGCount; + mmc_dat.blksz = sd->client_block_size[func]; + mmc_dat.blocks = blk_num; + mmc_dat.flags = write ? MMC_DATA_WRITE : MMC_DATA_READ; + mmc_cmd.opcode = 53; /* SD_IO_RW_EXTENDED */ + mmc_cmd.arg = write ? 1<<31 : 0; + mmc_cmd.arg |= (func & 0x7) << 28; + mmc_cmd.arg |= 1<<27; + mmc_cmd.arg |= fifo ? 0 : 1<<26; + mmc_cmd.arg |= (addr & 0x1FFFF) << 9; + mmc_cmd.arg |= blk_num & 0x1FF; + mmc_cmd.flags = MMC_RSP_SPI_R5 | MMC_RSP_R5 | MMC_CMD_ADTC; + + mmc_req.cmd = &mmc_cmd; + mmc_req.data = &mmc_dat; + + sdio_claim_host(gInstance->func[func]); + mmc_set_data_timeout(&mmc_dat, gInstance->func[func]->card); + mmc_wait_for_req(gInstance->func[func]->card->host, &mmc_req); + sdio_release_host(gInstance->func[func]); + + err_ret = mmc_cmd.error? mmc_cmd.error : mmc_dat.error; + if (0 != err_ret) { + sd_err(("%s:CMD53 %s failed with code %d\n", + __FUNCTION__, + write ? "write" : "read", + err_ret)); + sd_err(("%s:Disabling rxchain and fire it with PIO\n", + __FUNCTION__)); + sd->use_rxchain = FALSE; + pkt = pprev; + lft_len = ttl_len; + } else if (!fifo) { + addr = addr + ttl_len - lft_len - dma_len; + } } - /* Release host controller */ - sdio_release_host(gInstance->func[func]); + /* PIO mode */ + if (0 != lft_len) { + /* Claim host controller */ + sdio_claim_host(gInstance->func[func]); + for (pnext = pkt; pnext; pnext = PKTNEXT(sd->osh, pnext)) { + uint8 *buf = (uint8*)PKTDATA(sd->osh, pnext) + + xfred_len; + pkt_len = PKTLEN(sd->osh, pnext); + if (0 != xfred_len) { + pkt_len -= xfred_len; + xfred_len = 0; + } + pkt_len = (pkt_len + 3) & 0xFFFFFFFC; +#ifdef CONFIG_MMC_MSM7X00A + if ((pkt_len % 64) == 32) { + sd_trace(("%s: Rounding up TX packet +=32\n", __FUNCTION__)); + pkt_len += 32; + } +#endif /* CONFIG_MMC_MSM7X00A */ + + if ((write) && (!fifo)) + err_ret = sdio_memcpy_toio( + gInstance->func[func], + addr, buf, pkt_len); + else if (write) + err_ret = sdio_memcpy_toio( + gInstance->func[func], + addr, buf, pkt_len); + else if (fifo) + err_ret = sdio_readsb( + gInstance->func[func], + buf, addr, pkt_len); + else + err_ret = sdio_memcpy_fromio( + gInstance->func[func], + buf, addr, pkt_len); + + if (err_ret) + sd_err(("%s: %s FAILED %p[%d], addr=0x%05x, pkt_len=%d, ERR=%d\n", + __FUNCTION__, + (write) ? "TX" : "RX", + pnext, SGCount, addr, pkt_len, err_ret)); + else + sd_trace(("%s: %s xfr'd %p[%d], addr=0x%05x, len=%d\n", + __FUNCTION__, + (write) ? "TX" : "RX", + pnext, SGCount, addr, pkt_len)); + + if (!fifo) + addr += pkt_len; + SGCount ++; + } + sdio_release_host(gInstance->func[func]); + } sd_trace(("%s: Exit\n", __FUNCTION__)); return ((err_ret == 0) ? SDIOH_API_RC_SUCCESS : SDIOH_API_RC_FAIL); @@ -1243,8 +1331,10 @@ sdioh_start(sdioh_info_t *si, int stage) 2.6.27. The implementation prior to that is buggy, and needs broadcom's patch for it */ - if ((ret = sdio_reset_comm(gInstance->func[0]->card))) + if ((ret = sdio_reset_comm(gInstance->func[0]->card))) { sd_err(("%s Failed, error = %d\n", __FUNCTION__, ret)); + return ret; + } else { sd->num_funcs = 2; sd->sd_blockmode = TRUE; diff --git a/drivers/net/wireless/bcmdhd/bcmsdh_sdmmc_linux.c b/drivers/net/wireless/bcmdhd/bcmsdh_sdmmc_linux.c index 22343784cb57..66e4d7797446 100644 --- a/drivers/net/wireless/bcmdhd/bcmsdh_sdmmc_linux.c +++ b/drivers/net/wireless/bcmdhd/bcmsdh_sdmmc_linux.c @@ -21,7 +21,7 @@ * software in any way with any other Broadcom software provided under a license * other than the GPL, without Broadcom's express prior written consent. * - * $Id: bcmsdh_sdmmc_linux.c 308645 2012-01-17 02:33:26Z $ + * $Id: bcmsdh_sdmmc_linux.c 312783 2012-02-03 22:53:56Z $ */ #include @@ -210,8 +210,9 @@ out: static int bcmsdh_sdmmc_resume(struct device *pdev) { +#if defined(OOB_INTR_ONLY) struct sdio_func *func = dev_to_sdio_func(pdev); - +#endif sd_trace(("%s Enter\n", __FUNCTION__)); dhd_mmc_suspend = FALSE; #if defined(OOB_INTR_ONLY) diff --git a/drivers/net/wireless/bcmdhd/dhd_cfg80211.c b/drivers/net/wireless/bcmdhd/dhd_cfg80211.c index 800590cca653..917b09b35a35 100644 --- a/drivers/net/wireless/bcmdhd/dhd_cfg80211.c +++ b/drivers/net/wireless/bcmdhd/dhd_cfg80211.c @@ -467,7 +467,6 @@ void wl_cfg80211_btcoex_deinit(struct wl_priv *wl) kfree(wl->btcoex_info); wl->btcoex_info = NULL; } -#endif int wl_cfg80211_set_btcoex_dhcp(struct net_device *dev, char *command) { @@ -591,3 +590,4 @@ int wl_cfg80211_set_btcoex_dhcp(struct net_device *dev, char *command) return (strlen("OK")); } +#endif diff --git a/drivers/net/wireless/bcmdhd/dhd_linux.c b/drivers/net/wireless/bcmdhd/dhd_linux.c index bd479acfc382..823c21a4753c 100644 --- a/drivers/net/wireless/bcmdhd/dhd_linux.c +++ b/drivers/net/wireless/bcmdhd/dhd_linux.c @@ -22,7 +22,7 @@ * software in any way with any other Broadcom software provided under a license * other than the GPL, without Broadcom's express prior written consent. * - * $Id: dhd_linux.c 308879 2012-01-17 22:03:47Z $ + * $Id: dhd_linux.c 314746 2012-02-14 03:45:02Z $ */ #include @@ -360,12 +360,6 @@ uint dhd_radio_up = 1; char iface_name[IFNAMSIZ] = {'\0'}; module_param_string(iface_name, iface_name, IFNAMSIZ, 0); -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0)) -#define BLOCKABLE() (!in_atomic()) -#else -#define BLOCKABLE() (!in_interrupt()) -#endif - /* The following are specific to the SDIO dongle */ /* IOCTL response timeout */ @@ -2339,7 +2333,6 @@ dhd_open(struct net_device *net) } dhd->pub.hang_was_sent = 0; - #if !defined(WL_CFG80211) /* * Force start if ifconfig_up gets called before START command @@ -2936,6 +2929,9 @@ dhd_preinit_ioctls(dhd_pub_t *dhd) #if defined(ARP_OFFLOAD_SUPPORT) int arpoe = 1; #endif +#if defined(KEEP_ALIVE) + int res; +#endif /* defined(KEEP_ALIVE) */ int scan_assoc_time = DHD_SCAN_ACTIVE_TIME; int scan_unassoc_time = 40; int scan_passive_time = DHD_SCAN_PASSIVE_TIME; @@ -2948,14 +2944,12 @@ dhd_preinit_ioctls(dhd_pub_t *dhd) #if (defined(AP) && !defined(WLP2P)) || (!defined(AP) && defined(WL_CFG80211)) uint32 mpc = 0; /* Turn MPC off for AP/APSTA mode */ #endif - #if defined(AP) || defined(WLP2P) uint32 apsta = 1; /* Enable APSTA mode */ #endif /* defined(AP) || defined(WLP2P) */ #ifdef GET_CUSTOM_MAC_ENABLE struct ether_addr ea_addr; #endif /* GET_CUSTOM_MAC_ENABLE */ - DHD_TRACE(("Enter %s\n", __FUNCTION__)); dhd->op_mode = 0; #ifdef GET_CUSTOM_MAC_ENABLE @@ -3086,6 +3080,7 @@ dhd_preinit_ioctls(dhd_pub_t *dhd) /* Setup assoc_retry_max count to reconnect target AP in dongle */ bcm_mkiovar("assoc_retry_max", (char *)&retry_max, 4, iovbuf, sizeof(iovbuf)); dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, sizeof(iovbuf), TRUE, 0); + #if defined(AP) && !defined(WLP2P) /* Turn off MPC in AP mode */ bcm_mkiovar("mpc", (char *)&mpc, 4, iovbuf, sizeof(iovbuf)); @@ -3101,17 +3096,13 @@ dhd_preinit_ioctls(dhd_pub_t *dhd) #endif #if defined(KEEP_ALIVE) - { /* Set Keep Alive : be sure to use FW with -keepalive */ - int res; - #if defined(SOFTAP) if (ap_fw_loaded == FALSE) #endif if ((res = dhd_keep_alive_onoff(dhd)) < 0) DHD_ERROR(("%s set keeplive failed %d\n", __FUNCTION__, res)); - } #endif /* defined(KEEP_ALIVE) */ /* Read event_msgs mask */ @@ -3750,20 +3741,20 @@ dhd_module_init(void) } #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) - /* - * Wait till MMC sdio_register_driver callback called and made driver attach. - * It's needed to make sync up exit from dhd insmod and - * Kernel MMC sdio device callback registration - */ + /* + * Wait till MMC sdio_register_driver callback called and made driver attach. + * It's needed to make sync up exit from dhd insmod and + * Kernel MMC sdio device callback registration + */ if (down_timeout(&dhd_registration_sem, msecs_to_jiffies(DHD_REGISTRATION_TIMEOUT)) != 0) { - error = -EINVAL; + error = -ENODEV; DHD_ERROR(("%s: sdio_register_driver timeout\n", __FUNCTION__)); goto fail_2; } #endif #if defined(WL_CFG80211) wl_android_post_init(); -#endif +#endif /* defined(WL_CFG80211) */ return error; #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) && 1 @@ -4388,6 +4379,8 @@ dhd_dev_get_pno_status(struct net_device *dev) #endif /* PNO_SUPPORT */ +struct work_struct work; + int net_os_send_hang_message(struct net_device *dev) { dhd_info_t *dhd = *(dhd_info_t **)netdev_priv(dev); @@ -4423,7 +4416,6 @@ void dhd_bus_country_set(struct net_device *dev, wl_country_t *cspec) memcpy(&dhd->pub.dhd_cspec, cspec, sizeof(wl_country_t)); } - void dhd_net_if_lock(struct net_device *dev) { dhd_info_t *dhd = *(dhd_info_t **)netdev_priv(dev); diff --git a/drivers/net/wireless/bcmdhd/dhd_sdio.c b/drivers/net/wireless/bcmdhd/dhd_sdio.c index 05316635144a..c206ab05fdbd 100644 --- a/drivers/net/wireless/bcmdhd/dhd_sdio.c +++ b/drivers/net/wireless/bcmdhd/dhd_sdio.c @@ -21,7 +21,7 @@ * software in any way with any other Broadcom software provided under a license * other than the GPL, without Broadcom's express prior written consent. * - * $Id: dhd_sdio.c 309234 2012-01-19 01:44:16Z $ + * $Id: dhd_sdio.c 314732 2012-02-14 03:22:42Z $ */ #include diff --git a/drivers/net/wireless/bcmdhd/include/bcmsdh_sdmmc.h b/drivers/net/wireless/bcmdhd/include/bcmsdh_sdmmc.h index bea97b610a8e..db8ea596304c 100644 --- a/drivers/net/wireless/bcmdhd/include/bcmsdh_sdmmc.h +++ b/drivers/net/wireless/bcmdhd/include/bcmsdh_sdmmc.h @@ -21,7 +21,7 @@ * software in any way with any other Broadcom software provided under a license * other than the GPL, without Broadcom's express prior written consent. * - * $Id: bcmsdh_sdmmc.h 277737 2011-08-16 17:54:59Z $ + * $Id: bcmsdh_sdmmc.h 314048 2012-02-09 20:31:56Z $ */ #ifndef __BCMSDH_SDMMC_H__ @@ -82,9 +82,10 @@ struct sdioh_info { uint8 num_funcs; /* Supported funcs on client */ uint32 com_cis_ptr; uint32 func_cis_ptr[SDIOD_MAX_IOFUNCS]; - uint max_dma_len; - uint max_dma_descriptors; /* DMA Descriptors supported by this controller. */ -// SDDMA_DESCRIPTOR SGList[32]; /* Scatter/Gather DMA List */ + +#define SDIOH_SDMMC_MAX_SG_ENTRIES 32 + struct scatterlist sg_list[SDIOH_SDMMC_MAX_SG_ENTRIES]; + bool use_rxchain; }; /************************************************************ diff --git a/drivers/net/wireless/bcmdhd/include/epivers.h b/drivers/net/wireless/bcmdhd/include/epivers.h index 53dd2f736734..0e720456f582 100644 --- a/drivers/net/wireless/bcmdhd/include/epivers.h +++ b/drivers/net/wireless/bcmdhd/include/epivers.h @@ -33,17 +33,17 @@ #define EPI_RC_NUMBER 195 -#define EPI_INCREMENTAL_NUMBER 23 +#define EPI_INCREMENTAL_NUMBER 28 #define EPI_BUILD_NUMBER 0 -#define EPI_VERSION 5, 90, 195, 23 +#define EPI_VERSION 5, 90, 195, 28 -#define EPI_VERSION_NUM 0x055ac317 +#define EPI_VERSION_NUM 0x055ac31c #define EPI_VERSION_DEV 5.90.195 -#define EPI_VERSION_STR "5.90.195.23" +#define EPI_VERSION_STR "5.90.195.28" #endif diff --git a/drivers/net/wireless/bcmdhd/include/linuxver.h b/drivers/net/wireless/bcmdhd/include/linuxver.h index d269e66f7fb8..54d88ee923b2 100644 --- a/drivers/net/wireless/bcmdhd/include/linuxver.h +++ b/drivers/net/wireless/bcmdhd/include/linuxver.h @@ -22,7 +22,7 @@ * software in any way with any other Broadcom software provided under a license * other than the GPL, without Broadcom's express prior written consent. * - * $Id: linuxver.h 280266 2011-08-28 04:18:20Z $ + * $Id: linuxver.h 312264 2012-02-02 00:49:43Z $ */ @@ -524,6 +524,11 @@ typedef struct { } while (0); #endif /* LINUX_VERSION_CODE */ +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0)) +#define BLOCKABLE() (!in_atomic()) +#else +#define BLOCKABLE() (!in_interrupt()) +#endif #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 31)) #define KILL_PROC(nr, sig) \ diff --git a/drivers/net/wireless/bcmdhd/include/sbchipc.h b/drivers/net/wireless/bcmdhd/include/sbchipc.h index 3fe2a5a49d30..8f757509b95d 100644 --- a/drivers/net/wireless/bcmdhd/include/sbchipc.h +++ b/drivers/net/wireless/bcmdhd/include/sbchipc.h @@ -5,7 +5,7 @@ * JTAG, 0/1/2 UARTs, clock frequency control, a watchdog interrupt timer, * GPIO interface, extbus, and support for serial and parallel flashes. * - * $Id: sbchipc.h 277737 2011-08-16 17:54:59Z $ + * $Id: sbchipc.h 311371 2012-01-28 05:47:25Z $ * * Copyright (C) 1999-2011, Broadcom Corporation * @@ -1659,6 +1659,9 @@ typedef volatile struct { #define CCTRL_4330_JTAG_DISABLE 0x00000008 +#define CCTRL_43239_GPIO_SEL 0x00000002 +#define CCTRL_43239_SDIO_HOST_WAKE 0x00000004 + #define RES4313_BB_PU_RSRC 0 #define RES4313_ILP_REQ_RSRC 1 #define RES4313_XTAL_PU_RSRC 2 diff --git a/drivers/net/wireless/bcmdhd/include/wlioctl.h b/drivers/net/wireless/bcmdhd/include/wlioctl.h index e31bfa94c006..91274a0c680b 100644 --- a/drivers/net/wireless/bcmdhd/include/wlioctl.h +++ b/drivers/net/wireless/bcmdhd/include/wlioctl.h @@ -24,7 +24,7 @@ * software in any way with any other Broadcom software provided under a license * other than the GPL, without Broadcom's express prior written consent. * - * $Id: wlioctl.h 307468 2012-01-11 18:29:27Z $ + * $Id: wlioctl.h 312596 2012-02-03 02:53:30Z $ */ @@ -1213,7 +1213,7 @@ typedef struct { #define WL_AUTH_OPEN_SYSTEM 0 #define WL_AUTH_SHARED_KEY 1 -#define WL_AUTH_OPEN_SHARED 3 +#define WL_AUTH_OPEN_SHARED 2 #define WL_RADIO_SW_DISABLE (1<<0) diff --git a/drivers/net/wireless/bcmdhd/wl_android.c b/drivers/net/wireless/bcmdhd/wl_android.c index 2cbe333b0dd6..8f6b1988180e 100644 --- a/drivers/net/wireless/bcmdhd/wl_android.c +++ b/drivers/net/wireless/bcmdhd/wl_android.c @@ -223,7 +223,7 @@ static int wl_android_get_band(struct net_device *dev, char *command, int total_ return bytes_written; } -#ifdef PNO_SUPPORT +#if defined(PNO_SUPPORT) && !defined(WL_SCHED_SCAN) static int wl_android_set_pno_setup(struct net_device *dev, char *command, int total_len) { wlc_ssid_t ssids_local[MAX_PFN_LIST_COUNT]; @@ -329,7 +329,7 @@ static int wl_android_set_pno_setup(struct net_device *dev, char *command, int t exit_proc: return res; } -#endif /* PNO_SUPPORT */ +#endif /* PNO_SUPPORT && !WL_SCHED_SCAN */ static int wl_android_get_p2p_dev_addr(struct net_device *ndev, char *command, int total_len) { @@ -516,7 +516,7 @@ int wl_android_priv_cmd(struct net_device *net, struct ifreq *ifr, int cmd) char *country_code = command + strlen(CMD_COUNTRY) + 1; bytes_written = wldev_set_country(net, country_code); } -#ifdef PNO_SUPPORT +#if defined(PNO_SUPPORT) && !defined(WL_SCHED_SCAN) else if (strnicmp(command, CMD_PNOSSIDCLR_SET, strlen(CMD_PNOSSIDCLR_SET)) == 0) { bytes_written = dhd_dev_pno_reset(net); } diff --git a/drivers/net/wireless/bcmdhd/wl_cfg80211.c b/drivers/net/wireless/bcmdhd/wl_cfg80211.c index fea69cf4244c..4373c852fa02 100644 --- a/drivers/net/wireless/bcmdhd/wl_cfg80211.c +++ b/drivers/net/wireless/bcmdhd/wl_cfg80211.c @@ -202,7 +202,8 @@ static s32 wl_cfg80211_del_pmksa(struct wiphy *wiphy, struct net_device *dev, struct cfg80211_pmksa *pmksa); static s32 wl_cfg80211_flush_pmksa(struct wiphy *wiphy, struct net_device *dev); -static void wl_notify_escan_complete(struct wl_priv *wl, struct net_device *ndev, bool aborted); +static s32 wl_notify_escan_complete(struct wl_priv *wl, + struct net_device *ndev, bool aborted, bool fw_abort); /* * event & event Q handlers for cfg80211 interfaces */ @@ -236,8 +237,15 @@ static s32 wl_bss_roaming_done(struct wl_priv *wl, struct net_device *ndev, const wl_event_msg_t *e, void *data); static s32 wl_notify_mic_status(struct wl_priv *wl, struct net_device *ndev, const wl_event_msg_t *e, void *data); +#ifdef WL_SCHED_SCAN +static s32 +wl_notify_sched_scan_results(struct wl_priv *wl, struct net_device *ndev, + const wl_event_msg_t *e, void *data); +#endif /* WL_SCHED_SCAN */ +#ifdef PNO_SUPPORT static s32 wl_notify_pfn_status(struct wl_priv *wl, struct net_device *ndev, const wl_event_msg_t *e, void *data); +#endif /* PNO_SUPPORT */ /* * register/deregister parent device */ @@ -516,11 +524,11 @@ static struct ieee80211_supported_band __wl_band_2ghz = { * doesn't match with the IE present in the 3/4 EAPOL msg. */ .ht_cap = { - IEEE80211_HT_CAP_SGI_20 | - IEEE80211_HT_CAP_DSSSCCK40 | IEEE80211_HT_CAP_MAX_AMSDU, - .ht_supported = TRUE, - .ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K, - .ampdu_density = IEEE80211_HT_MPDU_DENSITY_16 + IEEE80211_HT_CAP_SGI_20 | + IEEE80211_HT_CAP_DSSSCCK40 | IEEE80211_HT_CAP_MAX_AMSDU, + .ht_supported = TRUE, + .ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K, + .ampdu_density = IEEE80211_HT_MPDU_DENSITY_16 } #endif }; @@ -530,7 +538,22 @@ static struct ieee80211_supported_band __wl_band_5ghz_a = { .channels = __wl_5ghz_a_channels, .n_channels = ARRAY_SIZE(__wl_5ghz_a_channels), .bitrates = wl_a_rates, - .n_bitrates = wl_a_rates_size + .n_bitrates = wl_a_rates_size, +#if ENABLE_P2P_INTERFACE + /* wpa_supplicant sets wmm_enabled based on whether ht_cap + * is present or not. The wmm_enabled is inturn used to + * set the replay counters in the RSN IE. Without this + * the 4way handshake will fail complaining that IE in beacon + * doesn't match with the IE present in the 3/4 EAPOL msg. + */ + .ht_cap = { + IEEE80211_HT_CAP_SGI_20 | + IEEE80211_HT_CAP_DSSSCCK40 | IEEE80211_HT_CAP_MAX_AMSDU, + .ht_supported = TRUE, + .ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K, + .ampdu_density = IEEE80211_HT_MPDU_DENSITY_16 + } +#endif }; static const u32 __wl_cipher_suites[] = { @@ -918,8 +941,8 @@ wl_cfg80211_del_virtual_iface(struct wiphy *wiphy, struct net_device *dev) if (wl->p2p_supported) { memcpy(p2p_mac.octet, wl->p2p->int_addr.octet, ETHER_ADDR_LEN); if (wl->p2p->vif_created) { - if (wl_get_drv_status(wl, SCANNING, dev)) { - wl_cfg80211_scan_abort(wl, dev); + if (wl->scan_request) { + wl_notify_escan_complete(wl, dev, true, true); } wldev_iovar_setint(dev, "mpc", 1); wl_set_p2p_status(wl, IF_DELETING); @@ -1088,7 +1111,7 @@ wl_cfg80211_notify_ifdel(struct net_device *ndev) rollback_lock = true; } WL_DBG(("ESCAN COMPLETED\n")); - wl_notify_escan_complete(wl, ndev, true); + wl_notify_escan_complete(wl, ndev, true, false); if (rollback_lock) rtnl_unlock(); } @@ -1508,7 +1531,7 @@ __wl_cfg80211_scan(struct wiphy *wiphy, struct net_device *ndev, wpa_ie_fixed_t *wps_ie; s32 passive_scan; bool iscan_req; - bool escan_req; + bool escan_req = false; bool p2p_ssid; s32 err = 0; s32 i; @@ -1907,21 +1930,21 @@ wl_set_auth_type(struct net_device *dev, struct cfg80211_connect_params *sme) s32 bssidx = wl_cfgp2p_find_idx(wl, dev); switch (sme->auth_type) { case NL80211_AUTHTYPE_OPEN_SYSTEM: - val = 0; + val = WL_AUTH_OPEN_SYSTEM; WL_DBG(("open system\n")); break; case NL80211_AUTHTYPE_SHARED_KEY: - val = 1; + val = WL_AUTH_SHARED_KEY; WL_DBG(("shared key\n")); break; case NL80211_AUTHTYPE_AUTOMATIC: - val = 2; + val = WL_AUTH_OPEN_SHARED; WL_DBG(("automatic\n")); break; case NL80211_AUTHTYPE_NETWORK_EAP: WL_DBG(("network eap\n")); default: - val = 2; + val = WL_AUTH_OPEN_SHARED; WL_ERR(("invalid auth type (%d)\n", sme->auth_type)); break; } @@ -2119,9 +2142,9 @@ wl_set_set_sharedkey(struct net_device *dev, WL_ERR(("WLC_SET_KEY error (%d)\n", err)); return err; } - if (sec->auth_type == NL80211_AUTHTYPE_OPEN_SYSTEM) { + if (sec->auth_type == NL80211_AUTHTYPE_SHARED_KEY) { WL_DBG(("set auth_type to shared key\n")); - val = 1; /* shared key */ + val = WL_AUTH_SHARED_KEY; /* shared key */ err = wldev_iovar_setint_bsscfg(dev, "auth", val, bssidx); if (unlikely(err)) { WL_ERR(("set auth failed (%d)\n", err)); @@ -2160,7 +2183,7 @@ wl_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev, * Cancel ongoing scan to sync up with sme state machine of cfg80211. */ if (wl->scan_request) { - wl_cfg80211_scan_abort(wl, dev); + wl_notify_escan_complete(wl, dev, true, true); } /* Clean BSSID */ bzero(&bssid, sizeof(bssid)); @@ -2382,7 +2405,7 @@ wl_cfg80211_disconnect(struct wiphy *wiphy, struct net_device *dev, * Cancel ongoing scan to sync up with sme state machine of cfg80211. */ if (wl->scan_request) { - wl_cfg80211_scan_abort(wl, dev); + wl_notify_escan_complete(wl, dev, true, true); } wl_set_drv_status(wl, DISCONNECTING, dev); scbval.val = reason_code; @@ -2581,9 +2604,6 @@ wl_add_keyext(struct wiphy *wiphy, struct net_device *dev, return -EINVAL; } swap_key_from_BE(&key); -#if defined(CONFIG_WIRELESS_EXT) - dhd_wait_pend8021x(dev); -#endif wldev_iovar_setbuf_bsscfg(dev, "wsec_key", &key, sizeof(key), wl->ioctl_buf, WLC_IOCTL_MAXLEN, bssidx, &wl->ioctl_buf_sync); if (unlikely(err)) { @@ -2831,42 +2851,42 @@ wl_cfg80211_get_station(struct wiphy *wiphy, struct net_device *dev, sta->idle * 1000)); #endif } else if (wl_get_mode_by_netdev(wl, dev) == WL_MODE_BSS) { - u8 *curmacp = wl_read_prof(wl, dev, WL_PROF_BSSID); - if (!wl_get_drv_status(wl, CONNECTED, dev) || - (dhd_is_associated(dhd, NULL) == FALSE)) { - WL_ERR(("NOT assoc\n")); - err = -ENODEV; - goto get_station_err; - } - if (memcmp(mac, curmacp, ETHER_ADDR_LEN)) { - WL_ERR(("Wrong Mac address: "MACSTR" != "MACSTR"\n", - MAC2STR(mac), MAC2STR(curmacp))); - } + u8 *curmacp = wl_read_prof(wl, dev, WL_PROF_BSSID); + if (!wl_get_drv_status(wl, CONNECTED, dev) || + (dhd_is_associated(dhd, NULL) == FALSE)) { - /* Report the current tx rate */ - err = wldev_ioctl(dev, WLC_GET_RATE, &rate, sizeof(rate), false); - if (err) { - WL_ERR(("Could not get rate (%d)\n", err)); - } else { - rate = dtoh32(rate); - sinfo->filled |= STATION_INFO_TX_BITRATE; - sinfo->txrate.legacy = rate * 5; - WL_DBG(("Rate %d Mbps\n", (rate / 2))); - } + WL_ERR(("NOT assoc\n")); + err = -ENODEV; + goto get_station_err; + } + if (memcmp(mac, curmacp, ETHER_ADDR_LEN)) { + WL_ERR(("Wrong Mac address: "MACSTR" != "MACSTR"\n", + MAC2STR(mac), MAC2STR(curmacp))); + } - memset(&scb_val, 0, sizeof(scb_val)); - scb_val.val = 0; - err = wldev_ioctl(dev, WLC_GET_RSSI, &scb_val, - sizeof(scb_val_t), false); - if (err) { - WL_ERR(("Could not get rssi (%d)\n", err)); - goto get_station_err; - } + /* Report the current tx rate */ + err = wldev_ioctl(dev, WLC_GET_RATE, &rate, sizeof(rate), false); + if (err) { + WL_ERR(("Could not get rate (%d)\n", err)); + } else { + rate = dtoh32(rate); + sinfo->filled |= STATION_INFO_TX_BITRATE; + sinfo->txrate.legacy = rate * 5; + WL_DBG(("Rate %d Mbps\n", (rate / 2))); + } - rssi = dtoh32(scb_val.val); - sinfo->filled |= STATION_INFO_SIGNAL; - sinfo->signal = rssi; - WL_DBG(("RSSI %d dBm\n", rssi)); + memset(&scb_val, 0, sizeof(scb_val)); + scb_val.val = 0; + err = wldev_ioctl(dev, WLC_GET_RSSI, &scb_val, + sizeof(scb_val_t), false); + if (err) { + WL_ERR(("Could not get rssi (%d)\n", err)); + goto get_station_err; + } + rssi = dtoh32(scb_val.val); + sinfo->filled |= STATION_INFO_SIGNAL; + sinfo->signal = rssi; + WL_DBG(("RSSI %d dBm\n", rssi)); get_station_err: if (err) { @@ -3009,8 +3029,8 @@ wl_update_pmklist(struct net_device *dev, struct wl_pmk_list *pmk_list, return -EINVAL; } /* pmk list is supported only for STA interface i.e. primary interface - * Refer code wlc_bsscfg.c->wlc_bsscfg_sta_init - */ + * Refer code wlc_bsscfg.c->wlc_bsscfg_sta_init + */ if (primary_dev != dev) { WL_INFO(("Not supporting Flushing pmklist on virtual" " interfaces than primary interface\n")); @@ -3173,8 +3193,21 @@ wl_cfg80211_scan_abort(struct wl_priv *wl, struct net_device *ndev) s32 params_size = 0; s32 err = BCME_OK; unsigned long flags; + struct net_device *dev; WL_DBG(("Enter\n")); + if (wl->scan_request) { + if (wl->scan_request->dev == wl->p2p_net) + dev = wl_to_prmry_ndev(wl); + else + dev = wl->scan_request->dev; + } + else { + WL_ERR(("wl->scan_request is NULL did we already do scan_abort?" + "Now scan_abort for ndev %p primary %p p2p_net %p", + ndev, wl_to_prmry_ndev(wl), wl->p2p_net)); + dev = ndev; + } /* Our scan params only need space for 1 channel and 0 ssids */ params = wl_cfg80211_scan_alloc_params(-1, 0, ¶ms_size); @@ -3183,18 +3216,26 @@ wl_cfg80211_scan_abort(struct wl_priv *wl, struct net_device *ndev) err = -ENOMEM; } else { /* Do a scan abort to stop the driver's scan engine */ - err = wldev_ioctl(ndev, WLC_SCAN, params, params_size, true); + err = wldev_ioctl(dev, WLC_SCAN, params, params_size, true); if (err < 0) { WL_ERR(("scan abort failed \n")); } } del_timer_sync(&wl->scan_timeout); spin_lock_irqsave(&wl->cfgdrv_lock, flags); + +#ifdef WL_SCHED_SCAN + if (wl->sched_scan_req && !wl->scan_request) { + cfg80211_sched_scan_stopped(wl_to_wiphy(wl)); + wl->sched_scan_req = NULL; + } +#endif /* WL_SCHED_SCAN */ + if (wl->scan_request) { cfg80211_scan_done(wl->scan_request, true); wl->scan_request = NULL; } - wl_clr_drv_status(wl, SCANNING, ndev); + wl_clr_drv_status(wl, SCANNING, dev); spin_unlock_irqrestore(&wl->cfgdrv_lock, flags); if (params) kfree(params); @@ -3222,10 +3263,9 @@ wl_cfg80211_remain_on_channel(struct wiphy *wiphy, struct net_device *dev, ndev = dev; } - if (wl_get_drv_status(wl, SCANNING, ndev)) { - wl_cfg80211_scan_abort(wl, ndev); + if (wl->scan_request) { + wl_notify_escan_complete(wl, ndev, true, true); } - target_channel = ieee80211_frequency_to_channel(channel->center_freq); memcpy(&wl->remain_on_chan, channel, sizeof(struct ieee80211_channel)); wl->remain_on_chan_type = channel_type; @@ -3288,7 +3328,7 @@ wl_cfg80211_send_pending_tx_act_frm(struct wl_priv *wl) */ wl_clr_drv_status(wl, SENDING_ACT_FRM, wl->afx_hdl->dev); wl_clr_drv_status(wl, SCANNING, wl->afx_hdl->dev); - wl_cfg80211_scan_abort(wl, dev); + wl_notify_escan_complete(wl, dev, true, true); wl_cfgp2p_discover_enable_search(wl, false); tx_act_frm->channel = wl->afx_hdl->peer_chan; wl->afx_hdl->ack_recv = (wl_cfgp2p_tx_action_frame(wl, dev, @@ -3442,8 +3482,8 @@ wl_cfg80211_mgmt_tx(struct wiphy *wiphy, struct net_device *ndev, scb_val.val = mgmt->u.disassoc.reason_code; wldev_ioctl(dev, WLC_SCB_DEAUTHENTICATE_FOR_REASON, &scb_val, sizeof(scb_val_t), true); - WL_DBG(("Disconnect STA : %s\n", - bcm_ether_ntoa((const struct ether_addr *)mgmt->da, eabuf))); + WL_DBG(("Disconnect STA : %s scb_val.val %d\n", + bcm_ether_ntoa((const struct ether_addr *)mgmt->da, eabuf), scb_val.val)); cfg80211_mgmt_tx_status(ndev, *cookie, buf, len, true, GFP_KERNEL); goto exit; @@ -3455,7 +3495,7 @@ wl_cfg80211_mgmt_tx(struct wiphy *wiphy, struct net_device *ndev, * tx is still in progress (including the dwell time), * then this new action frame will not be sent out. */ - wl_cfg80211_scan_abort(wl, dev); + wl_notify_escan_complete(wl, dev, true, true); } @@ -3490,6 +3530,7 @@ wl_cfg80211_mgmt_tx(struct wiphy *wiphy, struct net_device *ndev, ieee80211_frequency_to_channel(channel->center_freq); if (channel->band == IEEE80211_BAND_5GHZ) { + WL_DBG(("5GHz channel %d", af_params->channel)); err = wldev_ioctl(dev, WLC_SET_CHANNEL, &af_params->channel, sizeof(af_params->channel), true); if (err < 0) { @@ -3653,7 +3694,7 @@ wl_validate_wpa2ie(struct net_device *dev, bcm_tlv_t *wpa2ie, s32 bssidx) { s32 len = 0; s32 err = BCME_OK; - u16 auth = 0; /* d11 open authentication */ + u16 auth = WL_AUTH_OPEN_SYSTEM; /* d11 open authentication */ u32 wsec; u32 pval = 0; u32 gval = 0; @@ -3757,7 +3798,7 @@ wl_validate_wpaie(struct net_device *dev, wpa_ie_fixed_t *wpaie, s32 bssidx) wpa_suite_mcast_t *mcast; wpa_suite_ucast_t *ucast; wpa_suite_auth_key_mgmt_t *mgmt; - u16 auth = 0; /* d11 open authentication */ + u16 auth = WL_AUTH_OPEN_SYSTEM; /* d11 open authentication */ u16 count; s32 err = BCME_OK; s32 len = 0; @@ -4080,7 +4121,7 @@ wl_cfg80211_add_set_beacon(struct wiphy *wiphy, struct net_device *dev, memcpy(beacon_ie, wps_ie, wpsie_len); wl_cfgp2p_set_management_ie(wl, dev, bssidx, VNDR_IE_BEACON_FLAG, beacon_ie, wpsie_len); - wl->ap_info->wps_ie = kmemdup(wps_ie, wpsie_len, GFP_KERNEL); + wl->ap_info->wps_ie = kmemdup(wps_ie, wpsie_len, GFP_KERNEL); /* add WLC_E_PROBREQ_MSG event to respose probe_request from STA */ wl_add_remove_eventmsg(dev, WLC_E_PROBREQ_MSG, pbc); } else { @@ -4133,12 +4174,12 @@ wl_cfg80211_add_set_beacon(struct wiphy *wiphy, struct net_device *dev, memcmp(wl->ap_info->wps_ie, wps_ie, wpsie_len)) { WL_DBG((" WPS IE is changed\n")); kfree(wl->ap_info->wps_ie); - wl->ap_info->wps_ie = kmemdup(wps_ie, wpsie_len, GFP_KERNEL); + wl->ap_info->wps_ie = kmemdup(wps_ie, wpsie_len, GFP_KERNEL); /* add WLC_E_PROBREQ_MSG event to respose probe_request from STA */ wl_add_remove_eventmsg(dev, WLC_E_PROBREQ_MSG, pbc); } else if (wl->ap_info->wps_ie == NULL) { WL_DBG((" WPS IE is added\n")); - wl->ap_info->wps_ie = kmemdup(wps_ie, wpsie_len, GFP_KERNEL); + wl->ap_info->wps_ie = kmemdup(wps_ie, wpsie_len, GFP_KERNEL); /* add WLC_E_PROBREQ_MSG event to respose probe_request from STA */ wl_add_remove_eventmsg(dev, WLC_E_PROBREQ_MSG, pbc); } @@ -4224,6 +4265,105 @@ exit: return err; } +#ifdef WL_SCHED_SCAN +#define PNO_TIME 30 +#define PNO_REPEAT 4 +#define PNO_FREQ_EXPO_MAX 3 +int wl_cfg80211_sched_scan_start(struct wiphy *wiphy, + struct net_device *dev, + struct cfg80211_sched_scan_request *request) +{ + ushort pno_time = PNO_TIME; + int pno_repeat = PNO_REPEAT; + int pno_freq_expo_max = PNO_FREQ_EXPO_MAX; + wlc_ssid_t ssids_local[MAX_PFN_LIST_COUNT]; + struct wl_priv *wl = wiphy_priv(wiphy); + struct cfg80211_ssid *ssid = NULL; + int ssid_count = 0; + int i; + int ret = 0; + + WL_DBG(("Enter n_match_sets:%d n_ssids:%d \n", + request->n_match_sets, request->n_ssids)); + WL_DBG(("ssids:%d pno_time:%d pno_repeat:%d pno_freq:%d \n", + request->n_ssids, pno_time, pno_repeat, pno_freq_expo_max)); + + if (wl_get_drv_status_all(wl, SCANNING)) { + WL_ERR(("Scanning already\n")); + return -EAGAIN; + } + + if (!request || !request->n_ssids || !request->n_match_sets) { + WL_ERR(("Invalid sched scan req!! n_ssids:%d \n", request->n_ssids)); + return -EINVAL; + } + + memset(&ssids_local, 0, sizeof(ssids_local)); + + if (request->n_match_sets > 0) { + for (i = 0; i < request->n_match_sets; i++) { + ssid = &request->match_sets[i].ssid; + memcpy(ssids_local[i].SSID, ssid->ssid, ssid->ssid_len); + ssids_local[i].SSID_len = ssid->ssid_len; + WL_DBG((">>> PNO filter set for ssid (%s) \n", ssid->ssid)); + ssid_count++; + } + } + + if (request->n_ssids > 0) { + for (i = 0; i < request->n_ssids; i++) { + /* Active scan req for ssids */ + WL_DBG((">>> Active scan req for ssid (%s) \n", request->ssids[i].ssid)); + + /* match_set ssids is a supert set of n_ssid list, so we need + * not add these set seperately + */ + } + } + + if (ssid_count) { + if ((ret = dhd_dev_pno_set(dev, ssids_local, request->n_match_sets, + pno_time, pno_repeat, pno_freq_expo_max)) < 0) { + WL_ERR(("PNO setup failed!! ret=%d \n", ret)); + return -EINVAL; + } + + /* Enable the PNO */ + if (dhd_dev_pno_enable(dev, 1) < 0) { + WL_ERR(("PNO enable failed!! ret=%d \n", ret)); + return -EINVAL; + } + wl->sched_scan_req = request; + } else { + return -EINVAL; + } + + return 0; +} + +int wl_cfg80211_sched_scan_stop(struct wiphy *wiphy, struct net_device *dev) +{ + struct wl_priv *wl = wiphy_priv(wiphy); + + WL_DBG(("Enter \n")); + + if (dhd_dev_pno_enable(dev, 0) < 0) + WL_ERR(("PNO disable failed")); + + if (dhd_dev_pno_reset(dev) < 0) + WL_ERR(("PNO reset failed")); + + if (wl->scan_request && wl->sched_scan_running) { + wl_cfg80211_scan_abort(wl, dev); + } + + wl->sched_scan_req = NULL; + wl->sched_scan_running = FALSE; + + return 0; +} +#endif /* WL_SCHED_SCAN */ + static struct cfg80211_ops wl_cfg80211_ops = { .add_virtual_intf = wl_cfg80211_add_virtual_iface, .del_virtual_intf = wl_cfg80211_del_virtual_iface, @@ -4256,6 +4396,10 @@ static struct cfg80211_ops wl_cfg80211_ops = { .set_channel = wl_cfg80211_set_channel, .set_beacon = wl_cfg80211_add_set_beacon, .add_beacon = wl_cfg80211_add_set_beacon, +#ifdef WL_SCHED_SCAN + .sched_scan_start = wl_cfg80211_sched_scan_start, + .sched_scan_stop = wl_cfg80211_sched_scan_stop, +#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(3, 2, 0) */ }; s32 wl_mode_to_nl80211_iftype(s32 mode) @@ -4291,12 +4435,18 @@ static s32 wl_setup_wiphy(struct wireless_dev *wdev, struct device *sdiofunc_dev /* Report how many SSIDs Driver can support per Scan request */ wdev->wiphy->max_scan_ssids = WL_SCAN_PARAMS_SSID_MAX; wdev->wiphy->max_num_pmkids = WL_NUM_PMKIDS_MAX; +#ifdef WL_SCHED_SCAN + wdev->wiphy->max_sched_scan_ssids = MAX_PFN_LIST_COUNT; + wdev->wiphy->max_match_sets = MAX_PFN_LIST_COUNT; + wdev->wiphy->max_sched_scan_ie_len = WL_SCAN_IE_LEN_MAX; + wdev->wiphy->flags |= WIPHY_FLAG_SUPPORTS_SCHED_SCAN; +#endif /* WL_SCHED_SCAN */ wdev->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) | BIT(NL80211_IFTYPE_AP) | BIT(NL80211_IFTYPE_MONITOR); wdev->wiphy->bands[IEEE80211_BAND_2GHZ] = &__wl_band_2ghz; - wdev->wiphy->bands[IEEE80211_BAND_5GHZ] = &__wl_band_5ghz_a; + /* wdev->wiphy->bands[IEEE80211_BAND_5GHZ] = &__wl_band_5ghz_a; - set in runtime */ wdev->wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM; wdev->wiphy->cipher_suites = __wl_cipher_suites; wdev->wiphy->n_cipher_suites = ARRAY_SIZE(__wl_cipher_suites); @@ -4472,7 +4622,7 @@ static bool wl_is_linkup(struct wl_priv *wl, const wl_event_msg_t *e, struct net u32 status = ntoh32(e->status); u16 flags = ntoh16(e->flags); - WL_DBG(("event %d, status %d\n", event, status)); + WL_DBG(("event %d, status %d flags %x\n", event, status, flags)); if (event == WLC_E_SET_SSID) { if (status == WLC_E_STATUS_SUCCESS) { if (!wl_is_ibssmode(wl, ndev)) @@ -4555,7 +4705,7 @@ wl_notify_connect_status_ap(struct wl_priv *wl, struct net_device *ndev, #if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 2, 0)) && !CFG80211_STA_EVENT_AVAILABLE memset(body, 0, sizeof(body)); memset(&bssid, 0, ETHER_ADDR_LEN); - WL_DBG(("Enter \n")); + WL_DBG(("Enter event %d ndev %p\n", event, ndev)); if (wl_get_mode_by_netdev(wl, ndev) == WL_INVALID) return WL_INVALID; @@ -4649,8 +4799,8 @@ wl_notify_connect_status(struct wl_priv *wl, struct net_device *ndev, if (wl_get_mode_by_netdev(wl, ndev) == WL_MODE_AP) { wl_notify_connect_status_ap(wl, ndev, e, data); } else { - WL_DBG(("wl_notify_connect_status : event %d status : %d \n", - ntoh32(e->event_type), ntoh32(e->status))); + WL_DBG(("wl_notify_connect_status : event %d status : %d ndev %p\n", + ntoh32(e->event_type), ntoh32(e->status), ndev)); if (wl_is_linkup(wl, e, ndev)) { wl_link_up(wl); act = true; @@ -4673,30 +4823,34 @@ wl_notify_connect_status(struct wl_priv *wl, struct net_device *ndev, } else if (wl_is_linkdown(wl, e)) { if (wl->scan_request) { - del_timer_sync(&wl->scan_timeout); if (wl->escan_on) { - wl_notify_escan_complete(wl, ndev, true); - } else + wl_notify_escan_complete(wl, ndev, true, true); + } else { + del_timer_sync(&wl->scan_timeout); wl_iscan_aborted(wl); + } } if (wl_get_drv_status(wl, CONNECTED, ndev)) { scb_val_t scbval; u8 *curbssid = wl_read_prof(wl, ndev, WL_PROF_BSSID); printk("link down, call cfg80211_disconnected\n"); wl_clr_drv_status(wl, CONNECTED, ndev); - /* To make sure disconnect, explictly send dissassoc - * for BSSID 00:00:00:00:00:00 issue - */ - scbval.val = WLAN_REASON_DEAUTH_LEAVING; - - memcpy(&scbval.ea, curbssid, ETHER_ADDR_LEN); - scbval.val = htod32(scbval.val); - wldev_ioctl(ndev, WLC_DISASSOC, &scbval, - sizeof(scb_val_t), true); - cfg80211_disconnected(ndev, 0, NULL, 0, GFP_KERNEL); - wl_link_down(wl); - wl_init_prof(wl, ndev); - } else if (wl_get_drv_status(wl, CONNECTING, ndev)) { + if (! wl_get_drv_status(wl, DISCONNECTING, ndev)) { + /* To make sure disconnect, explictly send dissassoc + * for BSSID 00:00:00:00:00:00 issue + */ + scbval.val = WLAN_REASON_DEAUTH_LEAVING; + + memcpy(&scbval.ea, curbssid, ETHER_ADDR_LEN); + scbval.val = htod32(scbval.val); + wldev_ioctl(ndev, WLC_DISASSOC, &scbval, + sizeof(scb_val_t), true); + cfg80211_disconnected(ndev, 0, NULL, 0, GFP_KERNEL); + wl_link_down(wl); + wl_init_prof(wl, ndev); + } + } + else if (wl_get_drv_status(wl, CONNECTING, ndev)) { printk("link down, during connecting\n"); wl_bss_connect_done(wl, ndev, e, data, false); } @@ -4707,11 +4861,12 @@ wl_notify_connect_status(struct wl_priv *wl, struct net_device *ndev, event, (int)ntoh32(e->status)); /* Clean up any pending scan request */ if (wl->scan_request) { - del_timer_sync(&wl->scan_timeout); if (wl->escan_on) { - wl_notify_escan_complete(wl, ndev, true); - } else + wl_notify_escan_complete(wl, ndev, true, true); + } else { + del_timer_sync(&wl->scan_timeout); wl_iscan_aborted(wl); + } } if (wl_get_drv_status(wl, CONNECTING, ndev)) wl_bss_connect_done(wl, ndev, e, data, false); @@ -4860,6 +5015,7 @@ static s32 wl_update_bss_info(struct wl_priv *wl, struct net_device *ndev) u8 *curbssid; s32 err = 0; struct wiphy *wiphy; + wiphy = wl_to_wiphy(wl); if (wl_is_ibssmode(wl, ndev)) @@ -4963,7 +5119,7 @@ wl_bss_connect_done(struct wl_priv *wl, struct net_device *ndev, WL_DBG((" enter\n")); if (wl->scan_request) { - wl_cfg80211_scan_abort(wl, ndev); + wl_notify_escan_complete(wl, ndev, true, true); } if (wl_get_drv_status(wl, CONNECTING, ndev)) { wl_clr_drv_status(wl, CONNECTING, ndev); @@ -5011,6 +5167,7 @@ wl_notify_mic_status(struct wl_priv *wl, struct net_device *ndev, return 0; } +#ifdef PNO_SUPPORT static s32 wl_notify_pfn_status(struct wl_priv *wl, struct net_device *ndev, const wl_event_msg_t *e, void *data) @@ -5018,11 +5175,19 @@ wl_notify_pfn_status(struct wl_priv *wl, struct net_device *ndev, WL_ERR((" PNO Event\n")); mutex_lock(&wl->usr_sync); +#ifndef WL_SCHED_SCAN /* TODO: Use cfg80211_sched_scan_results(wiphy); */ cfg80211_disconnected(ndev, 0, NULL, 0, GFP_KERNEL); +#else + /* If cfg80211 scheduled scan is supported, report the pno results via sched + * scan results + */ + wl_notify_sched_scan_results(wl, ndev, e, data); +#endif /* WL_SCHED_SCAN */ mutex_unlock(&wl->usr_sync); return 0; } +#endif /* PNO_SUPPORT */ static s32 wl_notify_scan_status(struct wl_priv *wl, struct net_device *ndev, @@ -5202,7 +5367,7 @@ wl_notify_rx_mgmt_frame(struct wl_priv *wl, struct net_device *ndev, * After complete GO Negotiation, roll back to mpc mode */ if (act_frm && ((act_frm->subtype == P2P_PAF_GON_CONF) || - (act_frm->subtype == P2P_PAF_PROVDIS_RSP))) { + (act_frm->subtype == P2P_PAF_PROVDIS_RSP))) { wldev_iovar_setint(dev, "mpc", 1); } } else { @@ -5220,6 +5385,127 @@ exit: return 0; } +#ifdef WL_SCHED_SCAN +/* If target scan is not reliable, set the below define to "0" to do a + * full escan + */ +#define FULL_ESCAN_ON_PFN_NET_FOUND 1 +static s32 +wl_notify_sched_scan_results(struct wl_priv *wl, struct net_device *ndev, + const wl_event_msg_t *e, void *data) +{ + wl_pfn_net_info_t *netinfo, *pnetinfo; + struct cfg80211_scan_request request; + struct wiphy *wiphy = wl_to_wiphy(wl); + int err = 0; + struct cfg80211_ssid ssid[MAX_PFN_LIST_COUNT]; + struct ieee80211_channel *channel = NULL; + int channel_req = 0; + int band = 0; + struct wl_pfn_scanresults *pfn_result = (struct wl_pfn_scanresults *)data; + + WL_DBG(("Enter\n")); + + if (e->event_type == WLC_E_PFN_NET_LOST) { + WL_DBG(("PFN NET LOST event. Do Nothing \n")); + return 0; + } else { + WL_DBG(("PFN NET FOUND event. count:%d \n", pfn_result->count)); + + + if (pfn_result->count > 0) { + int i; + + memset(&request, 0x00, sizeof(struct cfg80211_scan_request)); + memset(&ssid, 0x00, sizeof(ssid)); + request.wiphy = wiphy; + + pnetinfo = (wl_pfn_net_info_t *)(data + sizeof(wl_pfn_scanresults_t) + - sizeof(wl_pfn_net_info_t)); + + channel = (struct ieee80211_channel *)kzalloc( + (sizeof(struct ieee80211_channel) * MAX_PFN_LIST_COUNT), + GFP_KERNEL); + if (!channel) { + WL_ERR(("No memory")); + err = -ENOMEM; + goto out_err; + } + + for (i = 0; i < pfn_result->count; i++) { + netinfo = &pnetinfo[i]; + if (!netinfo) { + WL_ERR(("Invalid netinfo ptr. index:%d", i)); + err = -EINVAL; + goto out_err; + } + + WL_DBG(("SSID:%s Channel:%d \n", + netinfo->pfnsubnet.SSID, netinfo->pfnsubnet.channel)); + /* PFN result doesn't have all the info which are required by the supplicant + * (For e.g IEs) Do a target Escan so that sched scan results are reported + * via wl_inform_single_bss in the required format. Escan does require the + * scan request in the form of cfg80211_scan_request. For timebeing, create + * cfg80211_scan_request one out of the received PNO event. + */ + memcpy(ssid[i].ssid, netinfo->pfnsubnet.SSID, + netinfo->pfnsubnet.SSID_len); + ssid[i].ssid_len = netinfo->pfnsubnet.SSID_len; + request.n_ssids++; + + channel_req = netinfo->pfnsubnet.channel; + band = (channel_req <= CH_MAX_2G_CHANNEL) ? NL80211_BAND_2GHZ + : NL80211_BAND_2GHZ; + channel[i].center_freq = ieee80211_channel_to_frequency(channel_req, band); + channel[i].band = band; + channel[i].flags |= IEEE80211_CHAN_NO_HT40; + request.channels[i] = &channel[i]; + request.n_channels++; + } + + /* assign parsed ssid array */ + if (request.n_ssids) + request.ssids = &ssid[0]; + + if (wl_get_drv_status_all(wl, SCANNING)) { + /* Abort any on-going scan */ + wl_cfg80211_scan_abort(wl, ndev); + } + + if (wl_get_p2p_status(wl, DISCOVERY_ON)) { + err = wl_cfgp2p_discover_enable_search(wl, false); + if (unlikely(err)) { + wl_clr_drv_status(wl, SCANNING, ndev); + goto out_err; + } + } + + wl_set_drv_status(wl, SCANNING, ndev); +#if FULL_ESCAN_ON_PFN_NET_FOUND + err = wl_do_escan(wl, wiphy, ndev, &request); +#else + err = wl_do_escan(wl, wiphy, ndev, NULL); +#endif + if (err) { + wl_clr_drv_status(wl, SCANNING, ndev); + goto out_err; + } + } else { + WL_ERR(("FALSE PNO Event. (pfn_count == 0) \n")); + } + wl->sched_scan_running = TRUE; + } + + kfree(channel); + return 0; + +out_err: + if (channel) + kfree(channel); + return err; +} +#endif /* WL_SCHED_SCAN */ + static void wl_init_conf(struct wl_conf *conf) { WL_DBG(("Enter \n")); @@ -5260,7 +5546,9 @@ static void wl_init_event_handler(struct wl_priv *wl) wl->evt_handler[WLC_E_P2P_DISC_LISTEN_COMPLETE] = wl_cfgp2p_listen_complete; wl->evt_handler[WLC_E_ACTION_FRAME_COMPLETE] = wl_cfgp2p_action_tx_complete; wl->evt_handler[WLC_E_ACTION_FRAME_OFF_CHAN_COMPLETE] = wl_cfgp2p_action_tx_complete; +#ifdef PNO_SUPPORT wl->evt_handler[WLC_E_PFN_NET_FOUND] = wl_notify_pfn_status; +#endif /* PNO_SUPPORT */ } static s32 wl_init_priv_mem(struct wl_priv *wl) @@ -5562,7 +5850,7 @@ static void wl_scan_timeout(unsigned long data) if (wl->scan_request) { WL_ERR(("timer expired\n")); if (wl->escan_on) - wl_notify_escan_complete(wl, wl->escan_info.ndev, true); + wl_notify_escan_complete(wl, wl->escan_info.ndev, true, true); else wl_notify_iscan_complete(wl_to_iscan(wl), true); } @@ -5632,23 +5920,70 @@ static struct notifier_block wl_cfg80211_netdev_notifier = { .notifier_call = wl_cfg80211_netdev_notifier_call, }; -static void wl_notify_escan_complete(struct wl_priv *wl, +static s32 wl_notify_escan_complete(struct wl_priv *wl, struct net_device *ndev, - bool aborted) + bool aborted, bool fw_abort) { + wl_scan_params_t *params = NULL; + s32 params_size = 0; + s32 err = BCME_OK; unsigned long flags; + struct net_device *dev; WL_DBG(("Enter \n")); - wl_clr_drv_status(wl, SCANNING, ndev); - if (p2p_is_on(wl)) - wl_clr_p2p_status(wl, SCANNING); + + if (wl->scan_request) { + if (wl->scan_request->dev == wl->p2p_net) + dev = wl_to_prmry_ndev(wl); + else + dev = wl->scan_request->dev; + } + else { + WL_ERR(("wl->scan_request is NULL may be internal scan." + "doing scan_abort for ndev %p primary %p p2p_net %p", + ndev, wl_to_prmry_ndev(wl), wl->p2p_net)); + dev = ndev; + } + if (fw_abort) { + /* Our scan params only need space for 1 channel and 0 ssids */ + params = wl_cfg80211_scan_alloc_params(-1, 0, ¶ms_size); + if (params == NULL) { + WL_ERR(("scan params allocation failed \n")); + err = -ENOMEM; + } else { + /* Do a scan abort to stop the driver's scan engine */ + err = wldev_ioctl(dev, WLC_SCAN, params, params_size, true); + if (err < 0) { + WL_ERR(("scan abort failed \n")); + } + } + } + del_timer_sync(&wl->scan_timeout); spin_lock_irqsave(&wl->cfgdrv_lock, flags); + +#ifdef WL_SCHED_SCAN + if (wl->sched_scan_req && wl->sched_scan_running && !wl->scan_request) { + WL_DBG((" REPORTING SCHED SCAN RESULTS \n")); + cfg80211_sched_scan_results(wl->sched_scan_req->wiphy); + wl->sched_scan_running = FALSE; + wl->sched_scan_req = NULL; + wl->scan_request = NULL; + } +#endif /* WL_SCHED_SCAN */ + if (likely(wl->scan_request)) { cfg80211_scan_done(wl->scan_request, aborted); wl->scan_request = NULL; } + if (p2p_is_on(wl)) + wl_clr_p2p_status(wl, SCANNING); + wl_clr_drv_status(wl, SCANNING, dev); spin_unlock_irqrestore(&wl->cfgdrv_lock, flags); + if (params) + kfree(params); + + return err; } static s32 wl_escan_handler(struct wl_priv *wl, @@ -5772,13 +6107,12 @@ static s32 wl_escan_handler(struct wl_priv *wl, wl_clr_drv_status(wl, SCANNING, wl->afx_hdl->dev); if (wl->afx_hdl->peer_chan == WL_INVALID) complete(&wl->act_frm_scan); - } else if (likely(wl->scan_request)) { + } else if ((likely(wl->scan_request)) || (wl->sched_scan_running)) { mutex_lock(&wl->usr_sync); - del_timer_sync(&wl->scan_timeout); WL_INFO(("ESCAN COMPLETED\n")); wl->bss_list = (wl_scan_results_t *)wl->escan_info.escan_buf; wl_inform_bss(wl); - wl_notify_escan_complete(wl, ndev, false); + wl_notify_escan_complete(wl, ndev, false, false); mutex_unlock(&wl->usr_sync); } } @@ -5790,13 +6124,12 @@ static s32 wl_escan_handler(struct wl_priv *wl, wl_clr_p2p_status(wl, SCANNING); if (wl->afx_hdl->peer_chan == WL_INVALID) complete(&wl->act_frm_scan); - } else if (likely(wl->scan_request)) { + } else if ((likely(wl->scan_request)) || (wl->sched_scan_running)) { mutex_lock(&wl->usr_sync); - del_timer_sync(&wl->scan_timeout); WL_INFO(("ESCAN ABORTED\n")); wl->bss_list = (wl_scan_results_t *)wl->escan_info.escan_buf; wl_inform_bss(wl); - wl_notify_escan_complete(wl, ndev, true); + wl_notify_escan_complete(wl, ndev, true, false); mutex_unlock(&wl->usr_sync); } } @@ -5809,12 +6142,11 @@ static s32 wl_escan_handler(struct wl_priv *wl, wl_clr_drv_status(wl, SCANNING, wl->afx_hdl->dev); if (wl->afx_hdl->peer_chan == WL_INVALID) complete(&wl->act_frm_scan); - } else if (likely(wl->scan_request)) { + } else if ((likely(wl->scan_request)) || (wl->sched_scan_running)) { mutex_lock(&wl->usr_sync); - del_timer_sync(&wl->scan_timeout); wl->bss_list = (wl_scan_results_t *)wl->escan_info.escan_buf; wl_inform_bss(wl); - wl_notify_escan_complete(wl, ndev, true); + wl_notify_escan_complete(wl, ndev, true, false); mutex_unlock(&wl->usr_sync); } } @@ -6138,9 +6470,7 @@ static s32 wl_event_handler(void *data) tsk_ctl_t *tsk = (tsk_ctl_t *)data; wl = (struct wl_priv *)tsk->parent; - - DAEMONIZE("wl_event_handler"); - + DAEMONIZE("dhd_cfg80211_event"); complete(&tsk->completed); while (down_interruptible (&tsk->sema) == 0) { @@ -6169,7 +6499,7 @@ static s32 wl_event_handler(void *data) } DHD_OS_WAKE_UNLOCK(wl->pub); } - WL_DBG(("%s was terminated\n", __func__)); + WL_ERR(("%s was terminated\n", __func__)); complete_and_exit(&tsk->completed, 0); return 0; } @@ -6349,24 +6679,31 @@ eventmsg_out: s32 wl_update_wiphybands(struct wl_priv *wl) { struct wiphy *wiphy; - s8 phylist_buf[128]; - s8 *phy; + u32 bandlist[3]; + u32 nband = 0; + u32 i = 0; s32 err = 0; - - err = wldev_ioctl(wl_to_prmry_ndev(wl), WLC_GET_PHYLIST, phylist_buf, - sizeof(phylist_buf), false); + WL_DBG(("Entry")); + memset(bandlist, 0, sizeof(bandlist)); + err = wldev_ioctl(wl_to_prmry_ndev(wl), WLC_GET_BANDLIST, bandlist, + sizeof(bandlist), false); if (unlikely(err)) { WL_ERR(("error (%d)\n", err)); return err; } - phy = phylist_buf; - for (; *phy; phy++) { - if (*phy == 'a' || *phy == 'n') { - wiphy = wl_to_wiphy(wl); + wiphy = wl_to_wiphy(wl); + nband = bandlist[0]; + wiphy->bands[IEEE80211_BAND_5GHZ] = NULL; + wiphy->bands[IEEE80211_BAND_2GHZ] = NULL; + for (i = 1; i <= nband && i < sizeof(bandlist); i++) { + if (bandlist[i] == WLC_BAND_5G) wiphy->bands[IEEE80211_BAND_5GHZ] = &__wl_band_5ghz_a; - } + else if (bandlist[i] == WLC_BAND_2G) + wiphy->bands[IEEE80211_BAND_2GHZ] = + &__wl_band_2ghz; } + wiphy_apply_custom_regulatory(wiphy, &brcm_regdom); return err; } @@ -6376,7 +6713,7 @@ static s32 __wl_cfg80211_up(struct wl_priv *wl) struct net_device *ndev = wl_to_prmry_ndev(wl); struct wireless_dev *wdev = ndev->ieee80211_ptr; - WL_TRACE(("In\n")); + WL_DBG(("In\n")); err = dhd_config_dongle(wl, false); if (unlikely(err)) @@ -6404,7 +6741,7 @@ static s32 __wl_cfg80211_down(struct wl_priv *wl) struct net_info *iter, *next; struct net_device *ndev = wl_to_prmry_ndev(wl); - WL_TRACE(("In\n")); + WL_DBG(("In\n")); /* Check if cfg80211 interface is already down */ if (!wl_get_drv_status(wl, READY, ndev)) return err; /* it is even not ready */ @@ -6446,7 +6783,7 @@ s32 wl_cfg80211_up(void *para) struct wl_priv *wl; s32 err = 0; - WL_TRACE(("In\n")); + WL_DBG(("In\n")); wl = wlcfg_drv_priv; mutex_lock(&wl->usr_sync); wl_cfg80211_attach_post(wl_to_prmry_ndev(wl)); @@ -6476,7 +6813,7 @@ s32 wl_cfg80211_down(void *para) struct wl_priv *wl; s32 err = 0; - WL_TRACE(("In\n")); + WL_DBG(("In\n")); wl = wlcfg_drv_priv; mutex_lock(&wl->usr_sync); err = __wl_cfg80211_down(wl); diff --git a/drivers/net/wireless/bcmdhd/wl_cfg80211.h b/drivers/net/wireless/bcmdhd/wl_cfg80211.h index 2b8e66413f23..435d61833f1a 100644 --- a/drivers/net/wireless/bcmdhd/wl_cfg80211.h +++ b/drivers/net/wireless/bcmdhd/wl_cfg80211.h @@ -442,6 +442,10 @@ struct wl_priv { bool p2p_supported; struct btcoex_info *btcoex_info; struct timer_list scan_timeout; /* Timer for catch scan event timeout */ +#ifdef WL_SCHED_SCAN + struct cfg80211_sched_scan_request *sched_scan_req; /* scheduled scan req */ +#endif /* WL_SCHED_SCAN */ + bool sched_scan_running; /* scheduled scan req status */ }; static inline struct wl_bss_info *next_bss(struct wl_scan_results *list, struct wl_bss_info *bss) diff --git a/drivers/net/wireless/bcmdhd/wl_iw.c b/drivers/net/wireless/bcmdhd/wl_iw.c index 2537c2b6ba65..4d813bab5846 100644 --- a/drivers/net/wireless/bcmdhd/wl_iw.c +++ b/drivers/net/wireless/bcmdhd/wl_iw.c @@ -162,11 +162,8 @@ uint wl_msg_level = WL_ERROR_VAL; #define htodchanspec(i) i #define dtohchanspec(i) i -#ifdef CONFIG_WIRELESS_EXT - extern struct iw_statistics *dhd_get_wireless_stats(struct net_device *dev); extern int dhd_wait_pend8021x(struct net_device *dev); -#endif #if WIRELESS_EXT < 19 #define IW_IOCTL_IDX(cmd) ((cmd) - SIOCIWFIRST) -- cgit v1.2.3 From 55e9aee2025bf4416f79ec17f1cea15112e28b5d Mon Sep 17 00:00:00 2001 From: Dmitry Shmidt Date: Mon, 27 Feb 2012 14:02:51 -0800 Subject: net: wireless: bcmdhd: Update to Version 5.90.195.30 - Fix STA features if P2P FW is in use - Move ENABLE_P2P_INTERFACE to Makefile - Minor fixes in PNO scan Signed-off-by: Dmitry Shmidt --- drivers/net/wireless/bcmdhd/Makefile | 1 + drivers/net/wireless/bcmdhd/dhd.h | 15 ++- drivers/net/wireless/bcmdhd/dhd_cfg80211.c | 23 +++++ drivers/net/wireless/bcmdhd/dhd_cfg80211.h | 2 + drivers/net/wireless/bcmdhd/dhd_common.c | 16 +++- drivers/net/wireless/bcmdhd/dhd_linux.c | 4 +- drivers/net/wireless/bcmdhd/dhd_sdio.c | 5 +- drivers/net/wireless/bcmdhd/include/epivers.h | 8 +- drivers/net/wireless/bcmdhd/wl_cfg80211.c | 131 +++++++------------------- drivers/net/wireless/bcmdhd/wl_cfg80211.h | 4 - 10 files changed, 96 insertions(+), 113 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/bcmdhd/Makefile b/drivers/net/wireless/bcmdhd/Makefile index ef5e3d5e5f72..d86748a18a1e 100644 --- a/drivers/net/wireless/bcmdhd/Makefile +++ b/drivers/net/wireless/bcmdhd/Makefile @@ -8,6 +8,7 @@ DHDCFLAGS = -Wall -Wstrict-prototypes -Dlinux -DBCMDRIVER \ -DNEW_COMPAT_WIRELESS -DWIFI_ACT_FRAME -DARP_OFFLOAD_SUPPORT \ -DKEEP_ALIVE -DPKT_FILTER_SUPPORT \ -DEMBEDDED_PLATFORM \ + -DENABLE_P2P_INTERFACE \ -Idrivers/net/wireless/bcmdhd -Idrivers/net/wireless/bcmdhd/include ifeq ($(CONFIG_BCMDHD_WIFI_CONTROL_FUNC),y) diff --git a/drivers/net/wireless/bcmdhd/dhd.h b/drivers/net/wireless/bcmdhd/dhd.h index cb27e291c0d7..f72de6fb5084 100644 --- a/drivers/net/wireless/bcmdhd/dhd.h +++ b/drivers/net/wireless/bcmdhd/dhd.h @@ -24,7 +24,7 @@ * software in any way with any other Broadcom software provided under a license * other than the GPL, without Broadcom's express prior written consent. * - * $Id: dhd.h 306879 2012-01-09 21:33:03Z $ + * $Id: dhd.h 316856 2012-02-23 21:44:34Z $ */ /**************** @@ -76,9 +76,12 @@ enum dhd_bus_state { /* Firmware requested operation mode */ #define STA_MASK 0x0001 -#define HOSTAPD_MASK 0x0002 +#define HOSTAPD_MASK 0x0002 #define WFD_MASK 0x0004 -#define SOFTAP_FW_MASK 0x0008 +#define SOFTAP_FW_MASK 0x0008 +#define P2P_GO_ENABLED 0x0010 +#define P2P_GC_ENABLED 0x0020 +#define CONCURENT_MASK 0x00F0 /* max sequential rxcntl timeouts to set HANG event */ #define MAX_CNTL_TIMEOUT 2 @@ -205,6 +208,12 @@ typedef struct dhd_pub { char eventmask[WL_EVENTING_MASK_LEN]; int op_mode; /* STA, HostAPD, WFD, SoftAP */ +/* Set this to 1 to use a seperate interface (p2p0) for p2p operations. + * For ICS MR1 releases it should be disable to be compatable with ICS MR1 Framework + * see target dhd-cdc-sdmmc-panda-cfg80211-icsmr1-gpl-debug in Makefile + */ +/* #define ENABLE_P2P_INTERFACE 1 */ + #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) && defined(CONFIG_HAS_WAKELOCK) struct wake_lock wakelock[WAKE_LOCK_MAX]; #endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) && defined (CONFIG_HAS_WAKELOCK) */ diff --git a/drivers/net/wireless/bcmdhd/dhd_cfg80211.c b/drivers/net/wireless/bcmdhd/dhd_cfg80211.c index 917b09b35a35..172f25fc578a 100644 --- a/drivers/net/wireless/bcmdhd/dhd_cfg80211.c +++ b/drivers/net/wireless/bcmdhd/dhd_cfg80211.c @@ -33,6 +33,12 @@ extern struct wl_priv *wlcfg_drv_priv; static int dhd_dongle_up = FALSE; +#include +#include +#include +#include +#include + static s32 wl_dongle_up(struct net_device *ndev, u32 up); /** @@ -57,6 +63,22 @@ s32 dhd_cfg80211_down(struct wl_priv *wl) return 0; } +s32 dhd_cfg80211_set_p2p_info(struct wl_priv *wl, int val) +{ + dhd_pub_t *dhd = (dhd_pub_t *)(wl->pub); + dhd->op_mode |= val; + WL_ERR(("Set : op_mode=%d\n", dhd->op_mode)); + return 0; +} + +s32 dhd_cfg80211_clean_p2p_info(struct wl_priv *wl) +{ + dhd_pub_t *dhd = (dhd_pub_t *)(wl->pub); + dhd->op_mode &= ~CONCURENT_MASK; + WL_ERR(("Clean : op_mode=%d\n", dhd->op_mode)); + return 0; +} + static s32 wl_dongle_up(struct net_device *ndev, u32 up) { s32 err = 0; @@ -67,6 +89,7 @@ static s32 wl_dongle_up(struct net_device *ndev, u32 up) } return err; } + s32 dhd_config_dongle(struct wl_priv *wl, bool need_lock) { #ifndef DHD_SDALIGN diff --git a/drivers/net/wireless/bcmdhd/dhd_cfg80211.h b/drivers/net/wireless/bcmdhd/dhd_cfg80211.h index 8dab652c1a2c..6c033259a8d9 100644 --- a/drivers/net/wireless/bcmdhd/dhd_cfg80211.h +++ b/drivers/net/wireless/bcmdhd/dhd_cfg80211.h @@ -34,6 +34,8 @@ s32 dhd_cfg80211_init(struct wl_priv *wl); s32 dhd_cfg80211_deinit(struct wl_priv *wl); s32 dhd_cfg80211_down(struct wl_priv *wl); +s32 dhd_cfg80211_set_p2p_info(struct wl_priv *wl, int val); +s32 dhd_cfg80211_clean_p2p_info(struct wl_priv *wl); s32 dhd_config_dongle(struct wl_priv *wl, bool need_lock); int wl_cfg80211_btcoex_init(struct wl_priv *wl); diff --git a/drivers/net/wireless/bcmdhd/dhd_common.c b/drivers/net/wireless/bcmdhd/dhd_common.c index 1a8d3e08cf5e..73eeb4bdf3ff 100644 --- a/drivers/net/wireless/bcmdhd/dhd_common.c +++ b/drivers/net/wireless/bcmdhd/dhd_common.c @@ -21,7 +21,7 @@ * software in any way with any other Broadcom software provided under a license * other than the GPL, without Broadcom's express prior written consent. * - * $Id: dhd_common.c 307573 2012-01-12 00:04:39Z $ + * $Id: dhd_common.c 316272 2012-02-21 22:35:51Z $ */ #include #include @@ -134,7 +134,7 @@ enum { }; const bcm_iovar_t dhd_iovars[] = { - {"version", IOV_VERSION, 0, IOVT_BUFFER, sizeof(dhd_version) }, + {"version", IOV_VERSION, 0, IOVT_BUFFER, sizeof(dhd_version) }, #ifdef DHD_DEBUG {"msglevel", IOV_MSGLEVEL, 0, IOVT_UINT32, 0 }, #endif /* DHD_DEBUG */ @@ -1819,10 +1819,21 @@ exit: bool dhd_check_ap_wfd_mode_set(dhd_pub_t *dhd) { #ifdef WL_CFG80211 +#ifndef ENABLE_P2P_INTERFACE + /* To be back compatble with ICS MR1 release where p2p interface disable but wlan0 used for p2p */ if (((dhd->op_mode & HOSTAPD_MASK) == HOSTAPD_MASK) || ((dhd->op_mode & WFD_MASK) == WFD_MASK)) return TRUE; else +#else + /* concurent mode with p2p interface for wfd and wlan0 for sta */ + if (((dhd->op_mode & P2P_GO_ENABLED) == P2P_GO_ENABLED) || + ((dhd->op_mode & P2P_GC_ENABLED) == P2P_GC_ENABLED)) { + DHD_ERROR(("%s P2P enabled for mode=%d\n", __FUNCTION__, dhd->op_mode)); + return TRUE; + } + else +#endif #endif /* WL_CFG80211 */ return FALSE; } @@ -2064,6 +2075,7 @@ int dhd_keep_alive_onoff(dhd_pub_t *dhd) return res; } #endif /* defined(KEEP_ALIVE) */ + /* Android ComboSCAN support */ /* diff --git a/drivers/net/wireless/bcmdhd/dhd_linux.c b/drivers/net/wireless/bcmdhd/dhd_linux.c index 823c21a4753c..6c65e0163632 100644 --- a/drivers/net/wireless/bcmdhd/dhd_linux.c +++ b/drivers/net/wireless/bcmdhd/dhd_linux.c @@ -22,7 +22,7 @@ * software in any way with any other Broadcom software provided under a license * other than the GPL, without Broadcom's express prior written consent. * - * $Id: dhd_linux.c 314746 2012-02-14 03:45:02Z $ + * $Id: dhd_linux.c 316856 2012-02-23 21:44:34Z $ */ #include @@ -2924,7 +2924,7 @@ dhd_preinit_ioctls(dhd_pub_t *dhd) uint power_mode = PM_FAST; uint32 dongle_align = DHD_SDALIGN; uint32 glom = 0; - uint bcn_timeout = 4; + uint bcn_timeout = 10; uint retry_max = 3; #if defined(ARP_OFFLOAD_SUPPORT) int arpoe = 1; diff --git a/drivers/net/wireless/bcmdhd/dhd_sdio.c b/drivers/net/wireless/bcmdhd/dhd_sdio.c index c206ab05fdbd..3bef13ea1088 100644 --- a/drivers/net/wireless/bcmdhd/dhd_sdio.c +++ b/drivers/net/wireless/bcmdhd/dhd_sdio.c @@ -21,7 +21,7 @@ * software in any way with any other Broadcom software provided under a license * other than the GPL, without Broadcom's express prior written consent. * - * $Id: dhd_sdio.c 314732 2012-02-14 03:22:42Z $ + * $Id: dhd_sdio.c 315747 2012-02-18 00:16:06Z $ */ #include @@ -801,7 +801,8 @@ dhdsdio_clkctl(dhd_bus_t *bus, uint target, bool pendok) #ifdef DHD_DEBUG if (dhd_console_ms == 0) #endif /* DHD_DEBUG */ - dhd_os_wd_timer(bus->dhd, 0); + if (bus->poll == 0) + dhd_os_wd_timer(bus->dhd, 0); break; } #ifdef DHD_DEBUG diff --git a/drivers/net/wireless/bcmdhd/include/epivers.h b/drivers/net/wireless/bcmdhd/include/epivers.h index 0e720456f582..ff386de6737b 100644 --- a/drivers/net/wireless/bcmdhd/include/epivers.h +++ b/drivers/net/wireless/bcmdhd/include/epivers.h @@ -33,17 +33,17 @@ #define EPI_RC_NUMBER 195 -#define EPI_INCREMENTAL_NUMBER 28 +#define EPI_INCREMENTAL_NUMBER 30 #define EPI_BUILD_NUMBER 0 -#define EPI_VERSION 5, 90, 195, 28 +#define EPI_VERSION 5, 90, 195, 30 -#define EPI_VERSION_NUM 0x055ac31c +#define EPI_VERSION_NUM 0x055ac31e #define EPI_VERSION_DEV 5.90.195 -#define EPI_VERSION_STR "5.90.195.28" +#define EPI_VERSION_STR "5.90.195.30" #endif diff --git a/drivers/net/wireless/bcmdhd/wl_cfg80211.c b/drivers/net/wireless/bcmdhd/wl_cfg80211.c index 4373c852fa02..0b0baf001c92 100644 --- a/drivers/net/wireless/bcmdhd/wl_cfg80211.c +++ b/drivers/net/wireless/bcmdhd/wl_cfg80211.c @@ -76,11 +76,6 @@ u32 wl_dbg_level = WL_DBG_ERR; #define COEX_DHCP -/* Set this to 1 to use a seperate interface (p2p0) - * for p2p operations. - */ -#define ENABLE_P2P_INTERFACE 1 - /* This is to override regulatory domains defined in cfg80211 module (reg.c) * By default world regulatory domain defined in reg.c puts the flags NL80211_RRF_PASSIVE_SCAN * and NL80211_RRF_NO_IBSS for 5GHz channels (for 36..48 and 149..165). @@ -516,7 +511,7 @@ static struct ieee80211_supported_band __wl_band_2ghz = { .n_channels = ARRAY_SIZE(__wl_2ghz_channels), .bitrates = wl_g_rates, .n_bitrates = wl_g_rates_size, -#if ENABLE_P2P_INTERFACE +#if defined(ENABLE_P2P_INTERFACE) /* wpa_supplicant sets wmm_enabled based on whether ht_cap * is present or not. The wmm_enabled is inturn used to * set the replay counters in the RSN IE. Without this @@ -539,7 +534,7 @@ static struct ieee80211_supported_band __wl_band_5ghz_a = { .n_channels = ARRAY_SIZE(__wl_5ghz_a_channels), .bitrates = wl_a_rates, .n_bitrates = wl_a_rates_size, -#if ENABLE_P2P_INTERFACE +#if defined(ENABLE_P2P_INTERFACE) /* wpa_supplicant sets wmm_enabled based on whether ht_cap * is present or not. The wmm_enabled is inturn used to * set the replay counters in the RSN IE. Without this @@ -768,6 +763,7 @@ wl_cfg80211_add_virtual_iface(struct wiphy *wiphy, char *name, s32 timeout = -1; s32 wlif_type = -1; s32 mode = 0; + s32 dhd_mode = 0; chanspec_t chspec; struct wl_priv *wl = wiphy_priv(wiphy); struct net_device *_ndev; @@ -898,8 +894,13 @@ wl_cfg80211_add_virtual_iface(struct wiphy *wiphy, char *name, } if (net_attach && !net_attach(wl->pub, _ndev->ifindex)) { wl_alloc_netinfo(wl, _ndev, vwdev, mode); - WL_DBG((" virtual interface(%s) is " + WL_ERR((" virtual interface(%s) is " "created net attach done\n", wl->p2p->vir_ifname)); + if (type == NL80211_IFTYPE_P2P_CLIENT) + dhd_mode = P2P_GC_ENABLED; + else if (type == NL80211_IFTYPE_P2P_GO) + dhd_mode = P2P_GO_ENABLED; + DNGL_FUNC(dhd_cfg80211_set_p2p_info, (wl, dhd_mode)); } else { /* put back the rtnl_lock again */ if (rollback_lock) @@ -967,6 +968,7 @@ wl_cfg80211_del_virtual_iface(struct wiphy *wiphy, struct net_device *dev) msecs_to_jiffies(MAX_WAIT_TIME)); if (timeout > 0 && !wl_get_p2p_status(wl, IF_DELETING)) { WL_DBG(("IFDEL operation done\n")); + DNGL_FUNC(dhd_cfg80211_clean_p2p_info, (wl)); } else { WL_ERR(("IFDEL didn't complete properly\n")); } @@ -3186,62 +3188,6 @@ wl_cfg80211_scan_alloc_params(int channel, int nprobes, int *out_params_size) return params; } -s32 -wl_cfg80211_scan_abort(struct wl_priv *wl, struct net_device *ndev) -{ - wl_scan_params_t *params = NULL; - s32 params_size = 0; - s32 err = BCME_OK; - unsigned long flags; - struct net_device *dev; - - WL_DBG(("Enter\n")); - if (wl->scan_request) { - if (wl->scan_request->dev == wl->p2p_net) - dev = wl_to_prmry_ndev(wl); - else - dev = wl->scan_request->dev; - } - else { - WL_ERR(("wl->scan_request is NULL did we already do scan_abort?" - "Now scan_abort for ndev %p primary %p p2p_net %p", - ndev, wl_to_prmry_ndev(wl), wl->p2p_net)); - dev = ndev; - } - - /* Our scan params only need space for 1 channel and 0 ssids */ - params = wl_cfg80211_scan_alloc_params(-1, 0, ¶ms_size); - if (params == NULL) { - WL_ERR(("scan params allocation failed \n")); - err = -ENOMEM; - } else { - /* Do a scan abort to stop the driver's scan engine */ - err = wldev_ioctl(dev, WLC_SCAN, params, params_size, true); - if (err < 0) { - WL_ERR(("scan abort failed \n")); - } - } - del_timer_sync(&wl->scan_timeout); - spin_lock_irqsave(&wl->cfgdrv_lock, flags); - -#ifdef WL_SCHED_SCAN - if (wl->sched_scan_req && !wl->scan_request) { - cfg80211_sched_scan_stopped(wl_to_wiphy(wl)); - wl->sched_scan_req = NULL; - } -#endif /* WL_SCHED_SCAN */ - - if (wl->scan_request) { - cfg80211_scan_done(wl->scan_request, true); - wl->scan_request = NULL; - } - wl_clr_drv_status(wl, SCANNING, dev); - spin_unlock_irqrestore(&wl->cfgdrv_lock, flags); - if (params) - kfree(params); - return err; -} - static s32 wl_cfg80211_remain_on_channel(struct wiphy *wiphy, struct net_device *dev, struct ieee80211_channel * channel, @@ -4354,7 +4300,7 @@ int wl_cfg80211_sched_scan_stop(struct wiphy *wiphy, struct net_device *dev) WL_ERR(("PNO reset failed")); if (wl->scan_request && wl->sched_scan_running) { - wl_cfg80211_scan_abort(wl, dev); + wl_notify_escan_complete(wl, dev, true, true); } wl->sched_scan_req = NULL; @@ -4586,7 +4532,7 @@ static s32 wl_inform_single_bss(struct wl_priv *wl, struct wl_bss_info *bi) signal = notif_bss_info->rssi * 100; -#if defined(WLP2P) && ENABLE_P2P_INTERFACE +#if defined(WLP2P) && defined(ENABLE_P2P_INTERFACE) if (wl->p2p_net && wl->scan_request && wl->scan_request->dev == wl->p2p_net) { #else @@ -5409,10 +5355,8 @@ wl_notify_sched_scan_results(struct wl_priv *wl, struct net_device *ndev, if (e->event_type == WLC_E_PFN_NET_LOST) { WL_DBG(("PFN NET LOST event. Do Nothing \n")); return 0; - } else { - WL_DBG(("PFN NET FOUND event. count:%d \n", pfn_result->count)); - - + } + WL_DBG(("PFN NET FOUND event. count:%d \n", pfn_result->count)); if (pfn_result->count > 0) { int i; @@ -5422,15 +5366,14 @@ wl_notify_sched_scan_results(struct wl_priv *wl, struct net_device *ndev, pnetinfo = (wl_pfn_net_info_t *)(data + sizeof(wl_pfn_scanresults_t) - sizeof(wl_pfn_net_info_t)); - - channel = (struct ieee80211_channel *)kzalloc( + channel = (struct ieee80211_channel *)kzalloc( (sizeof(struct ieee80211_channel) * MAX_PFN_LIST_COUNT), GFP_KERNEL); - if (!channel) { - WL_ERR(("No memory")); - err = -ENOMEM; - goto out_err; - } + if (!channel) { + WL_ERR(("No memory")); + err = -ENOMEM; + goto out_err; + } for (i = 0; i < pfn_result->count; i++) { netinfo = &pnetinfo[i]; @@ -5439,9 +5382,8 @@ wl_notify_sched_scan_results(struct wl_priv *wl, struct net_device *ndev, err = -EINVAL; goto out_err; } - WL_DBG(("SSID:%s Channel:%d \n", - netinfo->pfnsubnet.SSID, netinfo->pfnsubnet.channel)); + netinfo->pfnsubnet.SSID, netinfo->pfnsubnet.channel)); /* PFN result doesn't have all the info which are required by the supplicant * (For e.g IEs) Do a target Escan so that sched scan results are reported * via wl_inform_single_bss in the required format. Escan does require the @@ -5455,7 +5397,7 @@ wl_notify_sched_scan_results(struct wl_priv *wl, struct net_device *ndev, channel_req = netinfo->pfnsubnet.channel; band = (channel_req <= CH_MAX_2G_CHANNEL) ? NL80211_BAND_2GHZ - : NL80211_BAND_2GHZ; + : NL80211_BAND_5GHZ; channel[i].center_freq = ieee80211_channel_to_frequency(channel_req, band); channel[i].band = band; channel[i].flags |= IEEE80211_CHAN_NO_HT40; @@ -5469,7 +5411,7 @@ wl_notify_sched_scan_results(struct wl_priv *wl, struct net_device *ndev, if (wl_get_drv_status_all(wl, SCANNING)) { /* Abort any on-going scan */ - wl_cfg80211_scan_abort(wl, ndev); + wl_notify_escan_complete(wl, ndev, true, true); } if (wl_get_p2p_status(wl, DISCOVERY_ON)) { @@ -5490,15 +5432,11 @@ wl_notify_sched_scan_results(struct wl_priv *wl, struct net_device *ndev, wl_clr_drv_status(wl, SCANNING, ndev); goto out_err; } - } else { - WL_ERR(("FALSE PNO Event. (pfn_count == 0) \n")); - } wl->sched_scan_running = TRUE; } - - kfree(channel); - return 0; - + else { + WL_ERR(("FALSE PNO Event. (pfn_count == 0) \n")); + } out_err: if (channel) kfree(channel); @@ -5932,7 +5870,6 @@ static s32 wl_notify_escan_complete(struct wl_priv *wl, WL_DBG(("Enter \n")); - if (wl->scan_request) { if (wl->scan_request->dev == wl->p2p_net) dev = wl_to_prmry_ndev(wl); @@ -5965,10 +5902,12 @@ static s32 wl_notify_escan_complete(struct wl_priv *wl, #ifdef WL_SCHED_SCAN if (wl->sched_scan_req && wl->sched_scan_running && !wl->scan_request) { WL_DBG((" REPORTING SCHED SCAN RESULTS \n")); - cfg80211_sched_scan_results(wl->sched_scan_req->wiphy); + if (aborted) + cfg80211_sched_scan_stopped(wl->sched_scan_req->wiphy); + else + cfg80211_sched_scan_results(wl->sched_scan_req->wiphy); wl->sched_scan_running = FALSE; wl->sched_scan_req = NULL; - wl->scan_request = NULL; } #endif /* WL_SCHED_SCAN */ @@ -6235,7 +6174,7 @@ static void wl_deinit_priv(struct wl_priv *wl) unregister_netdevice_notifier(&wl_cfg80211_netdev_notifier); } -#if defined(WLP2P) && ENABLE_P2P_INTERFACE +#if defined(WLP2P) && defined(ENABLE_P2P_INTERFACE) static s32 wl_cfg80211_attach_p2p(void) { struct wl_priv *wl = wlcfg_drv_priv; @@ -6285,7 +6224,7 @@ s32 wl_cfg80211_attach_post(struct net_device *ndev) if (wl && !wl_get_drv_status(wl, READY, ndev)) { if (wl->wdev && wl_cfgp2p_supported(wl, ndev)) { -#if !ENABLE_P2P_INTERFACE +#if !defined(ENABLE_P2P_INTERFACE) wl->wdev->wiphy->interface_modes |= (BIT(NL80211_IFTYPE_P2P_CLIENT)| BIT(NL80211_IFTYPE_P2P_GO)); @@ -6293,7 +6232,7 @@ s32 wl_cfg80211_attach_post(struct net_device *ndev) if ((err = wl_cfgp2p_init_priv(wl)) != 0) goto fail; -#if defined(WLP2P) && ENABLE_P2P_INTERFACE +#if defined(WLP2P) && defined(ENABLE_P2P_INTERFACE) if (wl->p2p_net) { /* Update MAC addr for p2p0 interface here. */ memcpy(wl->p2p_net->dev_addr, ndev->dev_addr, ETH_ALEN); @@ -6377,7 +6316,7 @@ s32 wl_cfg80211_attach(struct net_device *ndev, void *data) wlcfg_drv_priv = wl; -#if defined(WLP2P) && ENABLE_P2P_INTERFACE +#if defined(WLP2P) && defined(ENABLE_P2P_INTERFACE) err = wl_cfg80211_attach_p2p(); if (err) goto cfg80211_attach_out; @@ -6403,7 +6342,7 @@ void wl_cfg80211_detach(void *para) wl_cfg80211_btcoex_deinit(wl); #endif -#if defined(WLP2P) && ENABLE_P2P_INTERFACE +#if defined(WLP2P) && defined(ENABLE_P2P_INTERFACE) wl_cfg80211_detach_p2p(); #endif wl_setup_rfkill(wl, FALSE); diff --git a/drivers/net/wireless/bcmdhd/wl_cfg80211.h b/drivers/net/wireless/bcmdhd/wl_cfg80211.h index 435d61833f1a..41e7c678e41b 100644 --- a/drivers/net/wireless/bcmdhd/wl_cfg80211.h +++ b/drivers/net/wireless/bcmdhd/wl_cfg80211.h @@ -658,9 +658,5 @@ extern int wl_cfg80211_hang(struct net_device *dev, u16 reason); extern s32 wl_mode_to_nl80211_iftype(s32 mode); int wl_cfg80211_do_driver_init(struct net_device *net); void wl_cfg80211_enable_trace(int level); - -/* do scan abort */ -extern s32 wl_cfg80211_scan_abort(struct wl_priv *wl, struct net_device *ndev); - extern s32 wl_cfg80211_if_is_group_owner(void); #endif /* _wl_cfg80211_h_ */ -- cgit v1.2.3 From 5de603d349f675c08831610dd95b25b1ee0e4988 Mon Sep 17 00:00:00 2001 From: Dmitry Shmidt Date: Mon, 27 Feb 2012 15:51:56 -0800 Subject: net: wireless: bcmdhd: Add SET_RANDOM_MAC_SOFTAP option Signed-off-by: Dmitry Shmidt --- drivers/net/wireless/bcmdhd/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/bcmdhd/Makefile b/drivers/net/wireless/bcmdhd/Makefile index d86748a18a1e..fc94634f6e6f 100644 --- a/drivers/net/wireless/bcmdhd/Makefile +++ b/drivers/net/wireless/bcmdhd/Makefile @@ -8,7 +8,7 @@ DHDCFLAGS = -Wall -Wstrict-prototypes -Dlinux -DBCMDRIVER \ -DNEW_COMPAT_WIRELESS -DWIFI_ACT_FRAME -DARP_OFFLOAD_SUPPORT \ -DKEEP_ALIVE -DPKT_FILTER_SUPPORT \ -DEMBEDDED_PLATFORM \ - -DENABLE_P2P_INTERFACE \ + -DSET_RANDOM_MAC_SOFTAP -DENABLE_P2P_INTERFACE \ -Idrivers/net/wireless/bcmdhd -Idrivers/net/wireless/bcmdhd/include ifeq ($(CONFIG_BCMDHD_WIFI_CONTROL_FUNC),y) -- cgit v1.2.3 From 32478ad9d4c1a2e13065d74341097daec1076e7d Mon Sep 17 00:00:00 2001 From: Dmitry Shmidt Date: Tue, 28 Feb 2012 10:30:59 -0800 Subject: net: wireless: bcmdhd: Minor cleaning Signed-off-by: Dmitry Shmidt --- drivers/net/wireless/bcmdhd/dhd_linux.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/bcmdhd/dhd_linux.c b/drivers/net/wireless/bcmdhd/dhd_linux.c index 6c65e0163632..5be539d10bb0 100644 --- a/drivers/net/wireless/bcmdhd/dhd_linux.c +++ b/drivers/net/wireless/bcmdhd/dhd_linux.c @@ -3750,7 +3750,7 @@ dhd_module_init(void) error = -ENODEV; DHD_ERROR(("%s: sdio_register_driver timeout\n", __FUNCTION__)); goto fail_2; - } + } #endif #if defined(WL_CFG80211) wl_android_post_init(); @@ -4379,8 +4379,6 @@ dhd_dev_get_pno_status(struct net_device *dev) #endif /* PNO_SUPPORT */ -struct work_struct work; - int net_os_send_hang_message(struct net_device *dev) { dhd_info_t *dhd = *(dhd_info_t **)netdev_priv(dev); @@ -4413,7 +4411,7 @@ void dhd_bus_country_set(struct net_device *dev, wl_country_t *cspec) dhd_info_t *dhd = *(dhd_info_t **)netdev_priv(dev); if (dhd && dhd->pub.up) - memcpy(&dhd->pub.dhd_cspec, cspec, sizeof(wl_country_t)); + memcpy(&dhd->pub.dhd_cspec, cspec, sizeof(wl_country_t)); } void dhd_net_if_lock(struct net_device *dev) -- cgit v1.2.3 From a5e2789013e0767bc219d547a168b56b5e10ada3 Mon Sep 17 00:00:00 2001 From: Dmitry Shmidt Date: Tue, 28 Feb 2012 11:03:37 -0800 Subject: net: wireless: bcmdhd: Add SETSUSPENDMODE command Signed-off-by: Dmitry Shmidt --- drivers/net/wireless/bcmdhd/Makefile | 2 +- drivers/net/wireless/bcmdhd/dhd_linux.c | 131 +++++++++++++++++------------ drivers/net/wireless/bcmdhd/wl_android.c | 26 +++++- drivers/net/wireless/bcmdhd/wl_iw.c | 39 +++++++-- drivers/net/wireless/bcmdhd/wl_iw.h | 5 +- drivers/net/wireless/bcmdhd/wldev_common.h | 2 +- 6 files changed, 142 insertions(+), 63 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/bcmdhd/Makefile b/drivers/net/wireless/bcmdhd/Makefile index fc94634f6e6f..35f9c609c9e9 100644 --- a/drivers/net/wireless/bcmdhd/Makefile +++ b/drivers/net/wireless/bcmdhd/Makefile @@ -8,7 +8,7 @@ DHDCFLAGS = -Wall -Wstrict-prototypes -Dlinux -DBCMDRIVER \ -DNEW_COMPAT_WIRELESS -DWIFI_ACT_FRAME -DARP_OFFLOAD_SUPPORT \ -DKEEP_ALIVE -DPKT_FILTER_SUPPORT \ -DEMBEDDED_PLATFORM \ - -DSET_RANDOM_MAC_SOFTAP -DENABLE_P2P_INTERFACE \ + -DSET_RANDOM_MAC_SOFTAP -DENABLE_P2P_INTERFACE -DDHD_USE_EARLYSUSPEND \ -Idrivers/net/wireless/bcmdhd -Idrivers/net/wireless/bcmdhd/include ifeq ($(CONFIG_BCMDHD_WIFI_CONTROL_FUNC),y) diff --git a/drivers/net/wireless/bcmdhd/dhd_linux.c b/drivers/net/wireless/bcmdhd/dhd_linux.c index 5be539d10bb0..54e72797175a 100644 --- a/drivers/net/wireless/bcmdhd/dhd_linux.c +++ b/drivers/net/wireless/bcmdhd/dhd_linux.c @@ -155,11 +155,10 @@ print_tainted() extern wl_iw_extra_params_t g_wl_iw_params; #endif /* defined(CONFIG_BCMDHD_WEXT) */ -#if defined(CONFIG_HAS_EARLYSUSPEND) +#if defined(CONFIG_HAS_EARLYSUSPEND) && defined(DHD_USE_EARLYSUSPEND) #include -extern int dhdcdc_set_ioctl(dhd_pub_t *dhd, int ifidx, uint cmd, void *buf, uint len); -extern int dhd_get_dtim_skip(dhd_pub_t *dhd); #endif /* defined(CONFIG_HAS_EARLYSUSPEND) */ +extern int dhd_get_dtim_skip(dhd_pub_t *dhd); #ifdef PKT_FILTER_SUPPORT extern void dhd_pktfilter_offload_set(dhd_pub_t * dhd, char *arg); @@ -260,6 +259,7 @@ typedef struct dhd_info { * calls and wifi_on or wifi_off */ struct mutex dhd_net_if_mutex; + struct mutex dhd_suspend_mutex; #endif spinlock_t wakelock_spinlock; int wakelock_counter; @@ -272,7 +272,7 @@ typedef struct dhd_info { atomic_t pend_8021x_cnt; dhd_attach_states_t dhd_state; -#ifdef CONFIG_HAS_EARLYSUSPEND +#if defined(CONFIG_HAS_EARLYSUSPEND) && defined(DHD_USE_EARLYSUSPEND) struct early_suspend early_suspend; #endif /* CONFIG_HAS_EARLYSUSPEND */ @@ -425,6 +425,8 @@ static char dhd_version[] = "Dongle Host Driver, version " EPI_VERSION_STR ; static void dhd_net_if_lock_local(dhd_info_t *dhd); static void dhd_net_if_unlock_local(dhd_info_t *dhd); +static void dhd_suspend_lock(dhd_pub_t *dhdp); +static void dhd_suspend_unlock(dhd_pub_t *dhdp); #if !defined(AP) && defined(WLP2P) static u32 dhd_concurrent_fw(dhd_pub_t *dhd); #endif @@ -514,7 +516,6 @@ static void dhd_set_packet_filter(int value, dhd_pub_t *dhd) #endif } -#if defined(CONFIG_HAS_EARLYSUSPEND) static int dhd_set_suspend(int value, dhd_pub_t *dhd) { int power_mode = PM_MAX; @@ -526,70 +527,75 @@ static int dhd_set_suspend(int value, dhd_pub_t *dhd) DHD_TRACE(("%s: enter, value = %d in_suspend=%d\n", __FUNCTION__, value, dhd->in_suspend)); + dhd_suspend_lock(dhd); if (dhd && dhd->up) { if (value && dhd->in_suspend) { - /* Kernel suspended */ - DHD_ERROR(("%s: force extra Suspend setting \n", __FUNCTION__)); + /* Kernel suspended */ + DHD_ERROR(("%s: force extra Suspend setting \n", __FUNCTION__)); - dhd_wl_ioctl_cmd(dhd, WLC_SET_PM, (char *)&power_mode, - sizeof(power_mode), TRUE, 0); + dhd_wl_ioctl_cmd(dhd, WLC_SET_PM, (char *)&power_mode, + sizeof(power_mode), TRUE, 0); - /* Enable packet filter, only allow unicast packet to send up */ - dhd_set_packet_filter(1, dhd); + /* Enable packet filter, only allow unicast packet to send up */ + dhd_set_packet_filter(1, dhd); - /* If DTIM skip is set up as default, force it to wake - * each third DTIM for better power savings. Note that - * one side effect is a chance to miss BC/MC packet. - */ - bcn_li_dtim = dhd_get_dtim_skip(dhd); - bcm_mkiovar("bcn_li_dtim", (char *)&bcn_li_dtim, - 4, iovbuf, sizeof(iovbuf)); - dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, sizeof(iovbuf), TRUE, 0); - - /* Disable firmware roaming during suspend */ - bcm_mkiovar("roam_off", (char *)&roamvar, 4, - iovbuf, sizeof(iovbuf)); - dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, sizeof(iovbuf), TRUE, 0); - } else { + /* If DTIM skip is set up as default, force it to wake + * each third DTIM for better power savings. Note that + * one side effect is a chance to miss BC/MC packet. + */ + bcn_li_dtim = dhd_get_dtim_skip(dhd); + bcm_mkiovar("bcn_li_dtim", (char *)&bcn_li_dtim, + 4, iovbuf, sizeof(iovbuf)); + dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, sizeof(iovbuf), TRUE, 0); + + /* Disable firmware roaming during suspend */ + bcm_mkiovar("roam_off", (char *)&roamvar, 4, + iovbuf, sizeof(iovbuf)); + dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, sizeof(iovbuf), TRUE, 0); + } else { - /* Kernel resumed */ - DHD_TRACE(("%s: Remove extra suspend setting \n", __FUNCTION__)); + /* Kernel resumed */ + DHD_TRACE(("%s: Remove extra suspend setting \n", __FUNCTION__)); - power_mode = PM_FAST; - dhd_wl_ioctl_cmd(dhd, WLC_SET_PM, (char *)&power_mode, - sizeof(power_mode), TRUE, 0); + power_mode = PM_FAST; + dhd_wl_ioctl_cmd(dhd, WLC_SET_PM, (char *)&power_mode, + sizeof(power_mode), TRUE, 0); - /* disable pkt filter */ - dhd_set_packet_filter(0, dhd); + /* disable pkt filter */ + dhd_set_packet_filter(0, dhd); - /* restore pre-suspend setting for dtim_skip */ - bcm_mkiovar("bcn_li_dtim", (char *)&dhd->dtim_skip, - 4, iovbuf, sizeof(iovbuf)); + /* restore pre-suspend setting for dtim_skip */ + bcm_mkiovar("bcn_li_dtim", (char *)&dhd->dtim_skip, + 4, iovbuf, sizeof(iovbuf)); - dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, sizeof(iovbuf), TRUE, 0); - roamvar = dhd_roam_disable; - bcm_mkiovar("roam_off", (char *)&roamvar, 4, iovbuf, - sizeof(iovbuf)); - dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, sizeof(iovbuf), TRUE, 0); - } + dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, sizeof(iovbuf), TRUE, 0); + roamvar = dhd_roam_disable; + bcm_mkiovar("roam_off", (char *)&roamvar, 4, iovbuf, + sizeof(iovbuf)); + dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, sizeof(iovbuf), TRUE, 0); + } } - + dhd_suspend_unlock(dhd); return 0; } -static void dhd_suspend_resume_helper(struct dhd_info *dhd, int val) +static int dhd_suspend_resume_helper(struct dhd_info *dhd, int val, int force) { dhd_pub_t *dhdp = &dhd->pub; + int ret = 0; DHD_OS_WAKE_LOCK(dhdp); /* Set flag when early suspend was called */ dhdp->in_suspend = val; - if ((!dhdp->suspend_disable_flag) && (dhd_check_ap_wfd_mode_set(dhdp) == FALSE)) - dhd_set_suspend(val, dhdp); + if ((force || !dhdp->suspend_disable_flag) && + (dhd_check_ap_wfd_mode_set(dhdp) == FALSE)) + ret = dhd_set_suspend(val, dhdp); DHD_OS_WAKE_UNLOCK(dhdp); + return ret; } +#if defined(CONFIG_HAS_EARLYSUSPEND) && defined(DHD_USE_EARLYSUSPEND) static void dhd_early_suspend(struct early_suspend *h) { struct dhd_info *dhd = container_of(h, struct dhd_info, early_suspend); @@ -597,7 +603,7 @@ static void dhd_early_suspend(struct early_suspend *h) DHD_TRACE(("%s: enter\n", __FUNCTION__)); if (dhd) - dhd_suspend_resume_helper(dhd, 1); + dhd_suspend_resume_helper(dhd, 1, 0); } static void dhd_late_resume(struct early_suspend *h) @@ -607,7 +613,7 @@ static void dhd_late_resume(struct early_suspend *h) DHD_TRACE(("%s: enter\n", __FUNCTION__)); if (dhd) - dhd_suspend_resume_helper(dhd, 0); + dhd_suspend_resume_helper(dhd, 0, 0); } #endif /* defined(CONFIG_HAS_EARLYSUSPEND) */ @@ -2647,6 +2653,7 @@ dhd_attach(osl_t *osh, struct dhd_bus *bus, uint bus_hdrlen, void *dev) #endif #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25)) mutex_init(&dhd->dhd_net_if_mutex); + mutex_init(&dhd->dhd_suspend_mutex); #endif dhd_state |= DHD_ATTACH_STATE_WAKELOCKS_INIT; @@ -2732,7 +2739,7 @@ dhd_attach(osl_t *osh, struct dhd_bus *bus, uint bus_hdrlen, void *dev) register_pm_notifier(&dhd_sleep_pm_notifier); #endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) && defined(CONFIG_PM_SLEEP) */ -#ifdef CONFIG_HAS_EARLYSUSPEND +#if defined(CONFIG_HAS_EARLYSUSPEND) && defined(DHD_USE_EARLYSUSPEND) dhd->early_suspend.level = EARLY_SUSPEND_LEVEL_BLANK_SCREEN + 20; dhd->early_suspend.suspend = dhd_early_suspend; dhd->early_suspend.resume = dhd_late_resume; @@ -3565,7 +3572,7 @@ void dhd_detach(dhd_pub_t *dhdp) unregister_inetaddr_notifier(&dhd_notifier); #endif /* ARP_OFFLOAD_SUPPORT */ -#if defined(CONFIG_HAS_EARLYSUSPEND) +#if defined(CONFIG_HAS_EARLYSUSPEND) && defined(DHD_USE_EARLYSUSPEND) if (dhd->dhd_state & DHD_ATTACH_STATE_EARLYSUSPEND_DONE) { if (dhd->early_suspend.suspend) unregister_early_suspend(&dhd->early_suspend); @@ -4257,16 +4264,18 @@ int net_os_set_suspend_disable(struct net_device *dev, int val) return ret; } -int net_os_set_suspend(struct net_device *dev, int val) +int net_os_set_suspend(struct net_device *dev, int val, int force) { int ret = 0; -#if defined(CONFIG_HAS_EARLYSUSPEND) dhd_info_t *dhd = *(dhd_info_t **)netdev_priv(dev); if (dhd) { +#if defined(CONFIG_HAS_EARLYSUSPEND) && defined(DHD_USE_EARLYSUSPEND) ret = dhd_set_suspend(val, &dhd->pub); +#else + ret = dhd_suspend_resume_helper(dhd, val, force); +#endif } -#endif /* defined(CONFIG_HAS_EARLYSUSPEND) */ return ret; } @@ -4442,6 +4451,24 @@ static void dhd_net_if_unlock_local(dhd_info_t *dhd) #endif } +static void dhd_suspend_lock(dhd_pub_t *pub) +{ +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25)) + dhd_info_t *dhd = (dhd_info_t *)(pub->info); + if (dhd) + mutex_lock(&dhd->dhd_suspend_mutex); +#endif +} + +static void dhd_suspend_unlock(dhd_pub_t *pub) +{ +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25)) + dhd_info_t *dhd = (dhd_info_t *)(pub->info); + if (dhd) + mutex_unlock(&dhd->dhd_suspend_mutex); +#endif +} + unsigned long dhd_os_spin_lock(dhd_pub_t *pub) { dhd_info_t *dhd = (dhd_info_t *)(pub->info); diff --git a/drivers/net/wireless/bcmdhd/wl_android.c b/drivers/net/wireless/bcmdhd/wl_android.c index 8f6b1988180e..3b7544816aca 100644 --- a/drivers/net/wireless/bcmdhd/wl_android.c +++ b/drivers/net/wireless/bcmdhd/wl_android.c @@ -67,6 +67,7 @@ #define CMD_BTCOEXSCAN_STOP "BTCOEXSCAN-STOP" #define CMD_BTCOEXMODE "BTCOEXMODE" #define CMD_SETSUSPENDOPT "SETSUSPENDOPT" +#define CMD_SETSUSPENDMODE "SETSUSPENDMODE" #define CMD_P2P_DEV_ADDR "P2P_DEV_ADDR" #define CMD_SETFWPATH "SETFWPATH" #define CMD_SETBAND "SETBAND" @@ -201,7 +202,7 @@ static int wl_android_set_suspendopt(struct net_device *dev, char *command, int ret_now = net_os_set_suspend_disable(dev, suspend_flag); if (ret_now != suspend_flag) { - if (!(ret = net_os_set_suspend(dev, ret_now))) + if (!(ret = net_os_set_suspend(dev, ret_now, 1))) DHD_INFO(("%s: Suspend Flag %d -> %d\n", __FUNCTION__, ret_now, suspend_flag)); else @@ -210,6 +211,26 @@ static int wl_android_set_suspendopt(struct net_device *dev, char *command, int return ret; } +static int wl_android_set_suspendmode(struct net_device *dev, char *command, int total_len) +{ + int ret = 0; + +#if !defined(CONFIG_HAS_EARLYSUSPEND) || !defined(DHD_USE_EARLYSUSPEND) + int suspend_flag; + + suspend_flag = *(command + strlen(CMD_SETSUSPENDMODE) + 1) - '0'; + + if (suspend_flag != 0) + suspend_flag = 1; + + if (!(ret = net_os_set_suspend(dev, suspend_flag, 0))) + DHD_INFO(("%s: Suspend Mode %d\n",__FUNCTION__,suspend_flag)); + else + DHD_ERROR(("%s: failed %d\n",__FUNCTION__,ret)); +#endif + return ret; +} + static int wl_android_get_band(struct net_device *dev, char *command, int total_len) { uint band; @@ -505,6 +526,9 @@ int wl_android_priv_cmd(struct net_device *net, struct ifreq *ifr, int cmd) else if (strnicmp(command, CMD_SETSUSPENDOPT, strlen(CMD_SETSUSPENDOPT)) == 0) { bytes_written = wl_android_set_suspendopt(net, command, priv_cmd.total_len); } + else if (strnicmp(command, CMD_SETSUSPENDMODE, strlen(CMD_SETSUSPENDMODE)) == 0) { + bytes_written = wl_android_set_suspendmode(net, command, priv_cmd.total_len); + } else if (strnicmp(command, CMD_SETBAND, strlen(CMD_SETBAND)) == 0) { uint band = *(command + strlen(CMD_SETBAND) + 1) - '0'; bytes_written = wldev_set_band(net, band); diff --git a/drivers/net/wireless/bcmdhd/wl_iw.c b/drivers/net/wireless/bcmdhd/wl_iw.c index 4d813bab5846..25db3cada652 100644 --- a/drivers/net/wireless/bcmdhd/wl_iw.c +++ b/drivers/net/wireless/bcmdhd/wl_iw.c @@ -1119,7 +1119,7 @@ wl_iw_set_btcoex_dhcp( } static int -wl_iw_set_suspend( +wl_iw_set_suspend_opt( struct net_device *dev, struct iw_request_info *info, union iwreq_data *wrqu, @@ -1130,16 +1130,15 @@ char *extra int ret_now; int ret = 0; - suspend_flag = *(extra + strlen(SETSUSPEND_CMD) + 1) - '0'; + suspend_flag = *(extra + strlen(SETSUSPENDOPT_CMD) + 1) - '0'; if (suspend_flag != 0) suspend_flag = 1; ret_now = net_os_set_suspend_disable(dev, suspend_flag); - if (ret_now != suspend_flag) { - if (!(ret = net_os_set_suspend(dev, ret_now))) + if (!(ret = net_os_set_suspend(dev, ret_now, 1))) WL_ERROR(("%s: Suspend Flag %d -> %d\n", __FUNCTION__, ret_now, suspend_flag)); else @@ -1149,6 +1148,32 @@ char *extra return ret; } +static int +wl_iw_set_suspend_mode( +struct net_device *dev, +struct iw_request_info *info, +union iwreq_data *wrqu, +char *extra +) +{ + int ret = 0; + +#if !defined(CONFIG_HAS_EARLYSUSPEND) || !defined(DHD_USE_EARLYSUSPEND) + int suspend_flag; + + suspend_flag = *(extra + strlen(SETSUSPENDMODE_CMD) + 1) - '0'; + + if (suspend_flag != 0) + suspend_flag = 1; + + if (!(ret = net_os_set_suspend(dev, suspend_flag, 0))) + WL_ERROR(("%s: Suspend Mode %d\n",__FUNCTION__,suspend_flag)); + else + WL_ERROR(("%s: failed %d\n", __FUNCTION__, ret)); +#endif + return ret; +} + static int wl_format_ssid(char* ssid_buf, uint8* ssid, int ssid_len) { @@ -7601,8 +7626,10 @@ wl_iw_set_priv( ret = wl_iw_get_dtim_skip(dev, info, (union iwreq_data *)dwrq, extra); else if (strnicmp(extra, DTIM_SKIP_SET_CMD, strlen(DTIM_SKIP_SET_CMD)) == 0) ret = wl_iw_set_dtim_skip(dev, info, (union iwreq_data *)dwrq, extra); - else if (strnicmp(extra, SETSUSPEND_CMD, strlen(SETSUSPEND_CMD)) == 0) - ret = wl_iw_set_suspend(dev, info, (union iwreq_data *)dwrq, extra); + else if (strnicmp(extra, SETSUSPENDOPT_CMD, strlen(SETSUSPENDOPT_CMD)) == 0) + ret = wl_iw_set_suspend_opt(dev, info, (union iwreq_data *)dwrq, extra); + else if (strnicmp(extra, SETSUSPENDMODE_CMD, strlen(SETSUSPENDMODE_CMD)) == 0) + ret = wl_iw_set_suspend_mode(dev, info, (union iwreq_data *)dwrq, extra); else if (strnicmp(extra, TXPOWER_SET_CMD, strlen(TXPOWER_SET_CMD)) == 0) ret = wl_iw_set_txpower(dev, info, (union iwreq_data *)dwrq, extra); #if defined(PNO_SUPPORT) diff --git a/drivers/net/wireless/bcmdhd/wl_iw.h b/drivers/net/wireless/bcmdhd/wl_iw.h index faca5f72e223..273dcf12b89a 100644 --- a/drivers/net/wireless/bcmdhd/wl_iw.h +++ b/drivers/net/wireless/bcmdhd/wl_iw.h @@ -47,7 +47,8 @@ #define BAND_SET_CMD "SETBAND" #define DTIM_SKIP_GET_CMD "DTIMSKIPGET" #define DTIM_SKIP_SET_CMD "DTIMSKIPSET" -#define SETSUSPEND_CMD "SETSUSPENDOPT" +#define SETSUSPENDOPT_CMD "SETSUSPENDOPT" +#define SETSUSPENDMODE_CMD "SETSUSPENDMODE" #define PNOSSIDCLR_SET_CMD "PNOSSIDCLR" #define PNOSETUP_SET_CMD "PNOSETUP " @@ -206,7 +207,7 @@ extern int net_os_wake_unlock(struct net_device *dev); extern int net_os_wake_lock_timeout(struct net_device *dev); extern int net_os_wake_lock_timeout_enable(struct net_device *dev, int val); extern int net_os_set_suspend_disable(struct net_device *dev, int val); -extern int net_os_set_suspend(struct net_device *dev, int val); +extern int net_os_set_suspend(struct net_device *dev, int val, int force); extern int net_os_set_dtim_skip(struct net_device *dev, int val); extern int net_os_send_hang_message(struct net_device *dev); extern void get_customized_country_code(char *country_iso_code, wl_country_t *cspec); diff --git a/drivers/net/wireless/bcmdhd/wldev_common.h b/drivers/net/wireless/bcmdhd/wldev_common.h index 6a1ba1533600..773235e4597e 100644 --- a/drivers/net/wireless/bcmdhd/wldev_common.h +++ b/drivers/net/wireless/bcmdhd/wldev_common.h @@ -92,7 +92,7 @@ extern int net_os_wake_lock_timeout(struct net_device *dev); extern int net_os_wake_lock_timeout_enable(struct net_device *dev, int val); extern int net_os_set_dtim_skip(struct net_device *dev, int val); extern int net_os_set_suspend_disable(struct net_device *dev, int val); -extern int net_os_set_suspend(struct net_device *dev, int val); +extern int net_os_set_suspend(struct net_device *dev, int val, int force); extern int wl_iw_parse_ssid_list_tlv(char** list_str, wlc_ssid_t* ssid, int max, int *bytes_left); -- cgit v1.2.3 From ff3e4bf8efb05e445ea76378c31a8e2bd7454220 Mon Sep 17 00:00:00 2001 From: Dmitry Shmidt Date: Mon, 5 Mar 2012 10:17:06 -0800 Subject: net: wireless: bcmdhd: Always turn Off wlan power on interface down Signed-off-by: Dmitry Shmidt --- drivers/net/wireless/bcmdhd/dhd_linux.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/bcmdhd/dhd_linux.c b/drivers/net/wireless/bcmdhd/dhd_linux.c index 54e72797175a..bbba4d4fcaf1 100644 --- a/drivers/net/wireless/bcmdhd/dhd_linux.c +++ b/drivers/net/wireless/bcmdhd/dhd_linux.c @@ -2272,7 +2272,7 @@ dhd_cleanup_virt_ifaces(dhd_info_t *dhd) static int dhd_stop(struct net_device *net) { - int ifidx; + int ifidx = 0; dhd_info_t *dhd = *(dhd_info_t **)netdev_priv(net); DHD_OS_WAKE_LOCK(&dhd->pub); DHD_TRACE(("%s: Enter %p\n", __FUNCTION__, net)); @@ -2306,14 +2306,15 @@ dhd_stop(struct net_device *net) /* Stop the protocol module */ dhd_prot_stop(&dhd->pub); + OLD_MOD_DEC_USE_COUNT; +exit: #if defined(WL_CFG80211) if (ifidx == 0 && !dhd_download_fw_on_driverload) wl_android_wifi_off(net); #endif dhd->pub.rxcnt_timeout = 0; dhd->pub.txcnt_timeout = 0; - OLD_MOD_DEC_USE_COUNT; -exit: + DHD_OS_WAKE_UNLOCK(&dhd->pub); return 0; } -- cgit v1.2.3 From d25b99292335e7f4601002921f8b4a8a9c887593 Mon Sep 17 00:00:00 2001 From: Dmitry Shmidt Date: Mon, 5 Mar 2012 13:25:48 -0800 Subject: net: wireless: bcmdhd: Allow Improved suspend/resume processing on 2.6.39 Signed-off-by: Dmitry Shmidt --- drivers/net/wireless/bcmdhd/bcmsdh_sdmmc_linux.c | 8 ++++---- drivers/net/wireless/bcmdhd/dhd_linux.c | 2 +- drivers/net/wireless/bcmdhd/wl_android.c | 4 ++-- 3 files changed, 7 insertions(+), 7 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/bcmdhd/bcmsdh_sdmmc_linux.c b/drivers/net/wireless/bcmdhd/bcmsdh_sdmmc_linux.c index 66e4d7797446..5e28615fc5f5 100644 --- a/drivers/net/wireless/bcmdhd/bcmsdh_sdmmc_linux.c +++ b/drivers/net/wireless/bcmdhd/bcmsdh_sdmmc_linux.c @@ -167,7 +167,7 @@ static const struct sdio_device_id bcmsdh_sdmmc_ids[] = { MODULE_DEVICE_TABLE(sdio, bcmsdh_sdmmc_ids); -#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 39)) && defined(CONFIG_PM) +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 39)) && defined(CONFIG_PM) static int bcmsdh_sdmmc_suspend(struct device *pdev) { struct sdio_func *func = dev_to_sdio_func(pdev); @@ -228,18 +228,18 @@ static const struct dev_pm_ops bcmsdh_sdmmc_pm_ops = { .suspend = bcmsdh_sdmmc_suspend, .resume = bcmsdh_sdmmc_resume, }; -#endif /* (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 39)) && defined(CONFIG_PM) */ +#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 39)) && defined(CONFIG_PM) */ static struct sdio_driver bcmsdh_sdmmc_driver = { .probe = bcmsdh_sdmmc_probe, .remove = bcmsdh_sdmmc_remove, .name = "bcmsdh_sdmmc", .id_table = bcmsdh_sdmmc_ids, -#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 39)) && defined(CONFIG_PM) +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 39)) && defined(CONFIG_PM) .drv = { .pm = &bcmsdh_sdmmc_pm_ops, }, -#endif /* (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 39)) && defined(CONFIG_PM) */ +#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 39)) && defined(CONFIG_PM) */ }; struct sdos_info { diff --git a/drivers/net/wireless/bcmdhd/dhd_linux.c b/drivers/net/wireless/bcmdhd/dhd_linux.c index bbba4d4fcaf1..fd4719eae71d 100644 --- a/drivers/net/wireless/bcmdhd/dhd_linux.c +++ b/drivers/net/wireless/bcmdhd/dhd_linux.c @@ -472,7 +472,7 @@ static int dhd_sleep_pm_callback(struct notifier_block *nfb, unsigned long actio { int ret = NOTIFY_DONE; -#if (LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 39)) +#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 39)) switch (action) { case PM_HIBERNATION_PREPARE: case PM_SUSPEND_PREPARE: diff --git a/drivers/net/wireless/bcmdhd/wl_android.c b/drivers/net/wireless/bcmdhd/wl_android.c index 3b7544816aca..7b5dd8a0b87c 100644 --- a/drivers/net/wireless/bcmdhd/wl_android.c +++ b/drivers/net/wireless/bcmdhd/wl_android.c @@ -795,7 +795,7 @@ static int wifi_remove(struct platform_device *pdev) static int wifi_suspend(struct platform_device *pdev, pm_message_t state) { DHD_TRACE(("##> %s\n", __FUNCTION__)); -#if (LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 39)) && defined(OOB_INTR_ONLY) +#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 39)) && defined(OOB_INTR_ONLY) bcmsdh_oob_intr_set(0); #endif return 0; @@ -804,7 +804,7 @@ static int wifi_suspend(struct platform_device *pdev, pm_message_t state) static int wifi_resume(struct platform_device *pdev) { DHD_TRACE(("##> %s\n", __FUNCTION__)); -#if (LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 39)) && defined(OOB_INTR_ONLY) +#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 39)) && defined(OOB_INTR_ONLY) if (dhd_os_check_if_up(bcmsdh_get_drvdata())) bcmsdh_oob_intr_set(1); #endif -- cgit v1.2.3 From c4418cfa10725ad06682154da6d33ae73555966f Mon Sep 17 00:00:00 2001 From: Dmitry Shmidt Date: Mon, 12 Mar 2012 15:45:04 -0700 Subject: net: wireless: bcmdhd: Add sched-scan config option Signed-off-by: Dmitry Shmidt --- drivers/net/wireless/bcmdhd/Kconfig | 7 +++++++ drivers/net/wireless/bcmdhd/Makefile | 5 ++++- 2 files changed, 11 insertions(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/bcmdhd/Kconfig b/drivers/net/wireless/bcmdhd/Kconfig index d66bc996dfdc..dc490c3ecf8c 100644 --- a/drivers/net/wireless/bcmdhd/Kconfig +++ b/drivers/net/wireless/bcmdhd/Kconfig @@ -43,6 +43,13 @@ config DHD_USE_STATIC_BUF ---help--- Use memory preallocated in platform +config DHD_USE_SCHED_SCAN + bool "Use CFG80211 sched scan" + depends on BCMDHD && CFG80211 + default n + ---help--- + Use CFG80211 sched scan + config BCMDHD_CFG80211 bool "Enable CFG80211 support" depends on CFG80211 diff --git a/drivers/net/wireless/bcmdhd/Makefile b/drivers/net/wireless/bcmdhd/Makefile index 35f9c609c9e9..13b62ccfd4be 100644 --- a/drivers/net/wireless/bcmdhd/Makefile +++ b/drivers/net/wireless/bcmdhd/Makefile @@ -52,7 +52,10 @@ ifeq ($(CONFIG_BCMDHD_CFG80211),y) bcmdhd-objs += wl_cfg80211.o wl_cfgp2p.o wl_linux_mon.o DHDCFLAGS += -DWL_CFG80211 endif - +ifneq ($(CONFIG_DHD_USE_SCHED_SCAN),) +DHDCFLAGS += -DWL_SCHED_SCAN +else +endif EXTRA_CFLAGS = $(DHDCFLAGS) ifeq ($(CONFIG_BCMDHD),m) EXTRA_LDFLAGS += --strip-debug -- cgit v1.2.3 From 010e6c8fce2d4b36ef69a22530b336c536c791ff Mon Sep 17 00:00:00 2001 From: Dmitry Shmidt Date: Mon, 12 Mar 2012 17:33:52 -0700 Subject: net: wireless: bcmdhd: Fix crash on timeout in wl_notify_escan_complete Signed-off-by: Dmitry Shmidt --- drivers/net/wireless/bcmdhd/wl_cfg80211.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/bcmdhd/wl_cfg80211.c b/drivers/net/wireless/bcmdhd/wl_cfg80211.c index 0b0baf001c92..02257097f970 100644 --- a/drivers/net/wireless/bcmdhd/wl_cfg80211.c +++ b/drivers/net/wireless/bcmdhd/wl_cfg80211.c @@ -5882,7 +5882,7 @@ static s32 wl_notify_escan_complete(struct wl_priv *wl, ndev, wl_to_prmry_ndev(wl), wl->p2p_net)); dev = ndev; } - if (fw_abort) { + if (fw_abort && !in_atomic()) { /* Our scan params only need space for 1 channel and 0 ssids */ params = wl_cfg80211_scan_alloc_params(-1, 0, ¶ms_size); if (params == NULL) { @@ -5896,7 +5896,8 @@ static s32 wl_notify_escan_complete(struct wl_priv *wl, } } } - del_timer_sync(&wl->scan_timeout); + if (!in_atomic()) + del_timer_sync(&wl->scan_timeout); spin_lock_irqsave(&wl->cfgdrv_lock, flags); #ifdef WL_SCHED_SCAN -- cgit v1.2.3 From 688638f8a75603d8572dad1fd8d501043c5bcd58 Mon Sep 17 00:00:00 2001 From: Dmitry Shmidt Date: Tue, 13 Mar 2012 15:25:46 -0700 Subject: net: wireless: bcmdhd: Fix mac setting from platform hook Signed-off-by: Dmitry Shmidt --- drivers/net/wireless/bcmdhd/dhd_linux.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/net') diff --git a/drivers/net/wireless/bcmdhd/dhd_linux.c b/drivers/net/wireless/bcmdhd/dhd_linux.c index fd4719eae71d..b58a97921e18 100644 --- a/drivers/net/wireless/bcmdhd/dhd_linux.c +++ b/drivers/net/wireless/bcmdhd/dhd_linux.c @@ -2970,6 +2970,7 @@ dhd_preinit_ioctls(dhd_pub_t *dhd) DHD_ERROR(("%s: can't set MAC address , error=%d\n", __FUNCTION__, ret)); return BCME_NOTUP; } + memcpy(dhd->mac.octet, ea_addr.octet, ETHER_ADDR_LEN); } else { #endif /* GET_CUSTOM_MAC_ENABLE */ /* Get the default device MAC address directly from firmware */ -- cgit v1.2.3 From fd3142313b8f9770249ab63ea7c43e92c87210b4 Mon Sep 17 00:00:00 2001 From: Dmitry Shmidt Date: Thu, 15 Mar 2012 12:47:26 -0700 Subject: net: wireless: bcmdhd: Update to Version 5.90.195.35 - Add SoftAP auto-channel support - P2P fixes Signed-off-by: Dmitry Shmidt --- drivers/net/wireless/bcmdhd/Makefile | 2 +- drivers/net/wireless/bcmdhd/dhd.h | 1 - drivers/net/wireless/bcmdhd/dhd_common.c | 15 +- drivers/net/wireless/bcmdhd/dhd_linux.c | 43 ++++-- drivers/net/wireless/bcmdhd/include/epivers.h | 8 +- drivers/net/wireless/bcmdhd/wl_cfg80211.c | 196 ++++++++++++++++---------- drivers/net/wireless/bcmdhd/wl_cfg80211.h | 1 + drivers/net/wireless/bcmdhd/wldev_common.c | 50 +++++++ drivers/net/wireless/bcmdhd/wldev_common.h | 2 + 9 files changed, 226 insertions(+), 92 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/bcmdhd/Makefile b/drivers/net/wireless/bcmdhd/Makefile index 13b62ccfd4be..2fe7fa3d59fa 100644 --- a/drivers/net/wireless/bcmdhd/Makefile +++ b/drivers/net/wireless/bcmdhd/Makefile @@ -8,7 +8,7 @@ DHDCFLAGS = -Wall -Wstrict-prototypes -Dlinux -DBCMDRIVER \ -DNEW_COMPAT_WIRELESS -DWIFI_ACT_FRAME -DARP_OFFLOAD_SUPPORT \ -DKEEP_ALIVE -DPKT_FILTER_SUPPORT \ -DEMBEDDED_PLATFORM \ - -DSET_RANDOM_MAC_SOFTAP -DENABLE_P2P_INTERFACE -DDHD_USE_EARLYSUSPEND \ + -DSET_RANDOM_MAC_SOFTAP -DWL_ENABLE_P2P_IF -DDHD_USE_EARLYSUSPEND \ -Idrivers/net/wireless/bcmdhd -Idrivers/net/wireless/bcmdhd/include ifeq ($(CONFIG_BCMDHD_WIFI_CONTROL_FUNC),y) diff --git a/drivers/net/wireless/bcmdhd/dhd.h b/drivers/net/wireless/bcmdhd/dhd.h index f72de6fb5084..f73956afba4d 100644 --- a/drivers/net/wireless/bcmdhd/dhd.h +++ b/drivers/net/wireless/bcmdhd/dhd.h @@ -212,7 +212,6 @@ typedef struct dhd_pub { * For ICS MR1 releases it should be disable to be compatable with ICS MR1 Framework * see target dhd-cdc-sdmmc-panda-cfg80211-icsmr1-gpl-debug in Makefile */ -/* #define ENABLE_P2P_INTERFACE 1 */ #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) && defined(CONFIG_HAS_WAKELOCK) struct wake_lock wakelock[WAKE_LOCK_MAX]; diff --git a/drivers/net/wireless/bcmdhd/dhd_common.c b/drivers/net/wireless/bcmdhd/dhd_common.c index 73eeb4bdf3ff..e9511285163a 100644 --- a/drivers/net/wireless/bcmdhd/dhd_common.c +++ b/drivers/net/wireless/bcmdhd/dhd_common.c @@ -21,7 +21,7 @@ * software in any way with any other Broadcom software provided under a license * other than the GPL, without Broadcom's express prior written consent. * - * $Id: dhd_common.c 316272 2012-02-21 22:35:51Z $ + * $Id: dhd_common.c 319098 2012-03-07 01:05:20Z $ */ #include #include @@ -1819,11 +1819,14 @@ exit: bool dhd_check_ap_wfd_mode_set(dhd_pub_t *dhd) { #ifdef WL_CFG80211 -#ifndef ENABLE_P2P_INTERFACE - /* To be back compatble with ICS MR1 release where p2p interface disable but wlan0 used for p2p */ +#ifndef WL_ENABLE_P2P_IF + /* To be back compatble with ICS MR1 release where p2p interface + * disable but wlan0 used for p2p + */ if (((dhd->op_mode & HOSTAPD_MASK) == HOSTAPD_MASK) || - ((dhd->op_mode & WFD_MASK) == WFD_MASK)) + ((dhd->op_mode & WFD_MASK) == WFD_MASK)) { return TRUE; + } else #else /* concurent mode with p2p interface for wfd and wlan0 for sta */ @@ -1833,7 +1836,7 @@ bool dhd_check_ap_wfd_mode_set(dhd_pub_t *dhd) return TRUE; } else -#endif +#endif /* WL_ENABLE_P2P_IF */ #endif /* WL_CFG80211 */ return FALSE; } @@ -1885,10 +1888,12 @@ dhd_pno_enable(dhd_pub_t *dhd, int pfn_enabled) memset(iovbuf, 0, sizeof(iovbuf)); +#ifndef WL_SCHED_SCAN if ((pfn_enabled) && (dhd_is_associated(dhd, NULL) == TRUE)) { DHD_ERROR(("%s pno is NOT enable : called in assoc mode , ignore\n", __FUNCTION__)); return ret; } +#endif /* Enable/disable PNO */ if ((ret = bcm_mkiovar("pfn", (char *)&pfn_enabled, 4, iovbuf, sizeof(iovbuf))) > 0) { diff --git a/drivers/net/wireless/bcmdhd/dhd_linux.c b/drivers/net/wireless/bcmdhd/dhd_linux.c index b58a97921e18..e79a6c7e314b 100644 --- a/drivers/net/wireless/bcmdhd/dhd_linux.c +++ b/drivers/net/wireless/bcmdhd/dhd_linux.c @@ -22,7 +22,7 @@ * software in any way with any other Broadcom software provided under a license * other than the GPL, without Broadcom's express prior written consent. * - * $Id: dhd_linux.c 316856 2012-02-23 21:44:34Z $ + * $Id: dhd_linux.c 319136 2012-03-07 03:10:36Z $ */ #include @@ -427,7 +427,7 @@ static void dhd_net_if_lock_local(dhd_info_t *dhd); static void dhd_net_if_unlock_local(dhd_info_t *dhd); static void dhd_suspend_lock(dhd_pub_t *dhdp); static void dhd_suspend_unlock(dhd_pub_t *dhdp); -#if !defined(AP) && defined(WLP2P) +#if !defined(AP) && defined(WLP2P) && defined(WL_ENABLE_P2P_IF) static u32 dhd_concurrent_fw(dhd_pub_t *dhd); #endif @@ -589,8 +589,9 @@ static int dhd_suspend_resume_helper(struct dhd_info *dhd, int val, int force) /* Set flag when early suspend was called */ dhdp->in_suspend = val; if ((force || !dhdp->suspend_disable_flag) && - (dhd_check_ap_wfd_mode_set(dhdp) == FALSE)) + (dhd_check_ap_wfd_mode_set(dhdp) == FALSE)) { ret = dhd_set_suspend(val, dhdp); + } DHD_OS_WAKE_UNLOCK(dhdp); return ret; } @@ -1285,11 +1286,13 @@ dhd_start_xmit(struct sk_buff *skb, struct net_device *net) DHD_ERROR(("%s: xmit rejected pub.up=%d busstate=%d \n", __FUNCTION__, dhd->pub.up, dhd->pub.busstate)); netif_stop_queue(net); +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) /* Send Event when bus down detected during data session */ if (dhd->pub.busstate == DHD_BUS_DOWN) { DHD_ERROR(("%s: Event HANG sent up\n", __FUNCTION__)); net_os_send_hang_message(net); } +#endif DHD_OS_WAKE_UNLOCK(&dhd->pub); return -ENODEV; } @@ -2011,6 +2014,7 @@ dhd_ethtool(dhd_info_t *dhd, void *uaddr) static bool dhd_check_hang(struct net_device *net, dhd_pub_t *dhdp, int error) { +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) if (!dhdp) return FALSE; if ((error == -ETIMEDOUT) || ((dhdp->busstate == DHD_BUS_DOWN) && @@ -2020,6 +2024,7 @@ static bool dhd_check_hang(struct net_device *net, dhd_pub_t *dhdp, int error) net_os_send_hang_message(net); return TRUE; } +#endif return FALSE; } @@ -2890,7 +2895,7 @@ dhd_bus_start(dhd_pub_t *dhdp) return 0; } -#if !defined(AP) && defined(WLP2P) +#if !defined(AP) && defined(WLP2P) && defined(WL_ENABLE_P2P_IF) /* For Android ICS MR2 release, the concurrent mode is enabled by default and the firmware * name would be fw_bcmdhd.bin. So we need to determine whether P2P is enabled in the STA * firmware and accordingly enable concurrent mode (Apply P2P settings). SoftAP firmware @@ -2952,7 +2957,7 @@ dhd_preinit_ioctls(dhd_pub_t *dhd) #if (defined(AP) && !defined(WLP2P)) || (!defined(AP) && defined(WL_CFG80211)) uint32 mpc = 0; /* Turn MPC off for AP/APSTA mode */ #endif -#if defined(AP) || defined(WLP2P) +#if defined(AP) || (defined(WLP2P) && defined(WL_ENABLE_P2P_IF)) uint32 apsta = 1; /* Enable APSTA mode */ #endif /* defined(AP) || defined(WLP2P) */ #ifdef GET_CUSTOM_MAC_ENABLE @@ -3010,7 +3015,7 @@ dhd_preinit_ioctls(dhd_pub_t *dhd) #endif /* SET_RANDOM_MAC_SOFTAP */ DHD_TRACE(("Firmware = %s\n", fw_path)); -#if !defined(AP) && defined(WLP2P) +#if !defined(AP) && defined(WLP2P) && defined(WL_ENABLE_P2P_IF) /* Check if firmware with WFD support used */ if ((!op_mode && strstr(fw_path, "_p2p") != NULL) || (op_mode == 0x04) || (dhd_concurrent_fw(dhd))) { @@ -3031,6 +3036,26 @@ dhd_preinit_ioctls(dhd_pub_t *dhd) #if !defined(AP) && defined(WL_CFG80211) /* Check if firmware with HostAPD support used */ if ((!op_mode && strstr(fw_path, "_apsta") != NULL) || (op_mode == 0x02)) { + /* Turn off wme if we are having only g ONLY firmware */ + bcm_mkiovar("nmode", 0, 0, buf, sizeof(buf)); + if ((ret = dhd_wl_ioctl_cmd(dhd, WLC_GET_VAR, buf, sizeof(buf), + FALSE, 0)) < 0) { + DHD_ERROR(("%s:get nmode failed error (%d)\n", __FUNCTION__, ret)); + } + else { + DHD_TRACE(("%s:get nmode returned %d\n", __FUNCTION__,buf[0])); + } + if (buf[0] == 0) { + int wme = 0; + bcm_mkiovar("wme", (char *)&wme, 4, iovbuf, sizeof(iovbuf)); + if ((ret = dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, + sizeof(iovbuf), TRUE, 0)) < 0) { + DHD_ERROR(("%s set wme for HostAPD failed %d\n", __FUNCTION__, ret)); + } + else { + DHD_TRACE(("%s set wme succeeded for g ONLY firmware\n", __FUNCTION__)); + } + } /* Turn off MPC in AP mode */ bcm_mkiovar("mpc", (char *)&mpc, 4, iovbuf, sizeof(iovbuf)); if ((ret = dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, @@ -3766,10 +3791,10 @@ dhd_module_init(void) #endif /* defined(WL_CFG80211) */ return error; -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) && 1 +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) fail_2: dhd_bus_unregister(); -#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) */ +#endif fail_1: #if defined(CONFIG_WIFI_CONTROL_FUNC) wl_android_wifictrl_func_del(); @@ -4390,6 +4415,7 @@ dhd_dev_get_pno_status(struct net_device *dev) #endif /* PNO_SUPPORT */ +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) int net_os_send_hang_message(struct net_device *dev) { dhd_info_t *dhd = *(dhd_info_t **)netdev_priv(dev); @@ -4416,6 +4442,7 @@ int net_os_send_hang_message(struct net_device *dev) } return ret; } +#endif void dhd_bus_country_set(struct net_device *dev, wl_country_t *cspec) { diff --git a/drivers/net/wireless/bcmdhd/include/epivers.h b/drivers/net/wireless/bcmdhd/include/epivers.h index ff386de6737b..ddb28aed0baf 100644 --- a/drivers/net/wireless/bcmdhd/include/epivers.h +++ b/drivers/net/wireless/bcmdhd/include/epivers.h @@ -33,17 +33,17 @@ #define EPI_RC_NUMBER 195 -#define EPI_INCREMENTAL_NUMBER 30 +#define EPI_INCREMENTAL_NUMBER 35 #define EPI_BUILD_NUMBER 0 -#define EPI_VERSION 5, 90, 195, 30 +#define EPI_VERSION 5, 90, 195, 35 -#define EPI_VERSION_NUM 0x055ac31e +#define EPI_VERSION_NUM 0x055ac323 #define EPI_VERSION_DEV 5.90.195 -#define EPI_VERSION_STR "5.90.195.30" +#define EPI_VERSION_STR "5.90.195.35" #endif diff --git a/drivers/net/wireless/bcmdhd/wl_cfg80211.c b/drivers/net/wireless/bcmdhd/wl_cfg80211.c index 02257097f970..53bf68c0f447 100644 --- a/drivers/net/wireless/bcmdhd/wl_cfg80211.c +++ b/drivers/net/wireless/bcmdhd/wl_cfg80211.c @@ -71,6 +71,7 @@ u32 wl_dbg_level = WL_DBG_ERR; #define MAX_WAIT_TIME 1500 #define WL_SCAN_ACTIVE_TIME 40 #define WL_SCAN_PASSIVE_TIME 130 +#define WL_FRAME_LEN 300 #define DNGL_FUNC(func, parameters) func parameters; #define COEX_DHCP @@ -94,13 +95,12 @@ static const struct ieee80211_regdomain brcm_regdom = { REG_RULE(2467-10, 2472+10, 20, 6, 20, NL80211_RRF_PASSIVE_SCAN | NL80211_RRF_NO_IBSS), - /* IEEE 802.11 channel 14 - Only JP enables - * this and for 802.11b only + /* + * IEEE 802.11 channel 14 - is for JP only, + * we need cfg80211 to allow it (reg_flags = 0); so that + * hostapd could request auto channel by sending down ch 14 */ - REG_RULE(2484-10, 2484+10, 20, 6, 20, - NL80211_RRF_PASSIVE_SCAN | - NL80211_RRF_NO_IBSS | - NL80211_RRF_NO_OFDM), + REG_RULE(2484-10, 2484+10, 20, 6, 20, 0), /* IEEE 802.11a, channel 36..64 */ REG_RULE(5150-10, 5350+10, 40, 6, 20, 0), /* IEEE 802.11a, channel 100..165 */ @@ -510,22 +510,7 @@ static struct ieee80211_supported_band __wl_band_2ghz = { .channels = __wl_2ghz_channels, .n_channels = ARRAY_SIZE(__wl_2ghz_channels), .bitrates = wl_g_rates, - .n_bitrates = wl_g_rates_size, -#if defined(ENABLE_P2P_INTERFACE) - /* wpa_supplicant sets wmm_enabled based on whether ht_cap - * is present or not. The wmm_enabled is inturn used to - * set the replay counters in the RSN IE. Without this - * the 4way handshake will fail complaining that IE in beacon - * doesn't match with the IE present in the 3/4 EAPOL msg. - */ - .ht_cap = { - IEEE80211_HT_CAP_SGI_20 | - IEEE80211_HT_CAP_DSSSCCK40 | IEEE80211_HT_CAP_MAX_AMSDU, - .ht_supported = TRUE, - .ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K, - .ampdu_density = IEEE80211_HT_MPDU_DENSITY_16 - } -#endif + .n_bitrates = wl_g_rates_size }; static struct ieee80211_supported_band __wl_band_5ghz_a = { @@ -533,22 +518,7 @@ static struct ieee80211_supported_band __wl_band_5ghz_a = { .channels = __wl_5ghz_a_channels, .n_channels = ARRAY_SIZE(__wl_5ghz_a_channels), .bitrates = wl_a_rates, - .n_bitrates = wl_a_rates_size, -#if defined(ENABLE_P2P_INTERFACE) - /* wpa_supplicant sets wmm_enabled based on whether ht_cap - * is present or not. The wmm_enabled is inturn used to - * set the replay counters in the RSN IE. Without this - * the 4way handshake will fail complaining that IE in beacon - * doesn't match with the IE present in the 3/4 EAPOL msg. - */ - .ht_cap = { - IEEE80211_HT_CAP_SGI_20 | - IEEE80211_HT_CAP_DSSSCCK40 | IEEE80211_HT_CAP_MAX_AMSDU, - .ht_supported = TRUE, - .ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K, - .ampdu_density = IEEE80211_HT_MPDU_DENSITY_16 - } -#endif + .n_bitrates = wl_a_rates_size }; static const u32 __wl_cipher_suites[] = { @@ -901,6 +871,12 @@ wl_cfg80211_add_virtual_iface(struct wiphy *wiphy, char *name, else if (type == NL80211_IFTYPE_P2P_GO) dhd_mode = P2P_GO_ENABLED; DNGL_FUNC(dhd_cfg80211_set_p2p_info, (wl, dhd_mode)); + /* Start the P2P I/F with PM disabled. Enable PM from + * the framework + */ + if ((type == NL80211_IFTYPE_P2P_CLIENT) || ( + type == NL80211_IFTYPE_P2P_GO)) + vwdev->ps = NL80211_PS_DISABLED; } else { /* put back the rtnl_lock again */ if (rollback_lock) @@ -1234,7 +1210,7 @@ static void wl_scan_prep(struct wl_scan_params *params, struct cfg80211_scan_req params->channel_list[i] &= WL_CHANSPEC_CHAN_MASK; params->channel_list[i] |= chanspec; WL_SCAN(("Chan : %d, Channel spec: %x \n", - channel, params->channel_list[i])); + channel, params->channel_list[i])); params->channel_list[i] = htod16(params->channel_list[i]); } } else { @@ -2913,18 +2889,13 @@ wl_cfg80211_set_power_mgmt(struct wiphy *wiphy, struct net_device *dev, CHECK_SYS_UP(wl); + WL_DBG(("Enter : power save %s\n", (enabled ? "enable" : "disable"))); if (wl->p2p_net == dev) { return err; } pm = enabled ? PM_FAST : PM_OFF; - /* Do not enable the power save after assoc if it is p2p interface */ - if (wl->p2p && wl->p2p->vif_created) { - WL_DBG(("Do not enable the power save for p2p interfaces even after assoc\n")); - pm = PM_OFF; - } pm = htod32(pm); - WL_DBG(("power save %s\n", (pm ? "enabled" : "disabled"))); err = wldev_ioctl(dev, WLC_SET_PM, &pm, sizeof(pm), true); if (unlikely(err)) { if (err == -ENODEV) @@ -2933,6 +2904,7 @@ wl_cfg80211_set_power_mgmt(struct wiphy *wiphy, struct net_device *dev, WL_ERR(("error (%d)\n", err)); return err; } + WL_DBG(("power save %s\n", (pm ? "enabled" : "disabled"))); return err; } @@ -3429,7 +3401,8 @@ wl_cfg80211_mgmt_tx(struct wiphy *wiphy, struct net_device *ndev, wldev_ioctl(dev, WLC_SCB_DEAUTHENTICATE_FOR_REASON, &scb_val, sizeof(scb_val_t), true); WL_DBG(("Disconnect STA : %s scb_val.val %d\n", - bcm_ether_ntoa((const struct ether_addr *)mgmt->da, eabuf), scb_val.val)); + bcm_ether_ntoa((const struct ether_addr *)mgmt->da, eabuf), + scb_val.val)); cfg80211_mgmt_tx_status(ndev, *cookie, buf, len, true, GFP_KERNEL); goto exit; @@ -3626,6 +3599,14 @@ wl_cfg80211_set_channel(struct wiphy *wiphy, struct net_device *dev, dev = wl_to_prmry_ndev(wl); } channel = ieee80211_frequency_to_channel(chan->center_freq); + + if (wl_get_drv_status(wl, AP_CREATING, dev) && channel == 14) { + WL_TRACE(("<0> %s: as!!! in AP creating mode, save chan num:%d\n", + __FUNCTION__, channel)); + wl->hostapd_chan = channel; + return err; + } + WL_DBG(("netdev_ifidx(%d), chan_type(%d) target channel(%d) \n", dev->ifindex, channel_type, channel)); err = wldev_ioctl(dev, WLC_SET_CHANNEL, &channel, sizeof(channel), true); @@ -4012,6 +3993,26 @@ wl_cfg80211_add_set_beacon(struct wiphy *wiphy, struct net_device *dev, WL_ERR(("setting AP mode failed %d \n", err)); return err; } + + /* if requested, do softap ch autoselect */ + if (wl->hostapd_chan == 14) { + int auto_chan; + if ((err = wldev_get_auto_channel(dev, &auto_chan)) != 0) { + WL_ERR(("softap: auto chan select failed," + " will use ch 6\n")); + auto_chan = 6; + } else { + printf("<0>softap: got auto ch:%d\n", auto_chan); + } + err = wldev_ioctl(dev, WLC_SET_CHANNEL, + &auto_chan, sizeof(auto_chan), true); + if (err < 0) { + WL_ERR(("softap: WLC_SET_CHANNEL error %d chip" + " may not be supporting this channel\n", err)); + return err; + } + } + /* find the RSN_IE */ if ((wpa2_ie = bcm_parse_tlvs((u8 *)info->tail, info->tail_len, DOT11_MNG_RSN_ID)) != NULL) { @@ -4532,7 +4533,7 @@ static s32 wl_inform_single_bss(struct wl_priv *wl, struct wl_bss_info *bi) signal = notif_bss_info->rssi * 100; -#if defined(WLP2P) && defined(ENABLE_P2P_INTERFACE) +#if defined(WLP2P) && defined(WL_ENABLE_P2P_IF) if (wl->p2p_net && wl->scan_request && wl->scan_request->dev == wl->p2p_net) { #else @@ -4616,11 +4617,9 @@ static bool wl_is_nonetwork(struct wl_priv *wl, const wl_event_msg_t *e) /* The mainline kernel >= 3.2.0 has support for indicating new/del station * to AP/P2P GO via events. If this change is backported to kernel for which - * this driver is being built, set CFG80211_STA_EVENT_AVAILABLE to 1. You - * should use this new/del sta event mechanism for BRCM supplicant from BRANCH - * HOSTAP_BRANCH_0_15 (ver >= 15_1). + * this driver is being built, then define WL_CFG80211_STA_EVENT. You + * should use this new/del sta event mechanism for BRCM supplicant >= 22. */ -#define CFG80211_STA_EVENT_AVAILABLE 0 static s32 wl_notify_connect_status_ap(struct wl_priv *wl, struct net_device *ndev, const wl_event_msg_t *e, void *data) @@ -4630,13 +4629,13 @@ wl_notify_connect_status_ap(struct wl_priv *wl, struct net_device *ndev, u32 reason = ntoh32(e->reason); u32 len = ntoh32(e->datalen); -#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 2, 0)) && !CFG80211_STA_EVENT_AVAILABLE +#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 2, 0)) && !defined(WL_CFG80211_STA_EVENT) bool isfree = false; u8 *mgmt_frame; u8 bsscfgidx = e->bsscfgidx; s32 freq; s32 channel; - u8 body[200]; + u8 body[WL_FRAME_LEN]; u16 fc = 0; struct ieee80211_supported_band *band; struct ether_addr da; @@ -4645,16 +4644,21 @@ wl_notify_connect_status_ap(struct wl_priv *wl, struct net_device *ndev, channel_info_t ci; #else struct station_info sinfo; -#endif /* (LINUX_VERSION_CODE < KERNEL_VERSION(3, 2, 0)) && !CFG80211_STA_EVENT_AVAILABLE */ +#endif /* (LINUX_VERSION_CODE < KERNEL_VERSION(3, 2, 0)) && !WL_CFG80211_STA_EVENT */ -#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 2, 0)) && !CFG80211_STA_EVENT_AVAILABLE +#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 2, 0)) && !defined(WL_CFG80211_STA_EVENT) memset(body, 0, sizeof(body)); memset(&bssid, 0, ETHER_ADDR_LEN); WL_DBG(("Enter event %d ndev %p\n", event, ndev)); if (wl_get_mode_by_netdev(wl, ndev) == WL_INVALID) return WL_INVALID; + if (len > WL_FRAME_LEN) { + WL_ERR(("Received frame length %d from dongle is greater than" + " allocated body buffer len %d", len, WL_FRAME_LEN)); + goto exit; + } memcpy(body, data, len); wldev_iovar_getbuf_bsscfg(ndev, "cur_etheraddr", NULL, 0, wl->ioctl_buf, WLC_IOCTL_MAXLEN, bsscfgidx, &wl->ioctl_buf_sync); @@ -4713,7 +4717,7 @@ exit: if (isfree) kfree(mgmt_frame); return err; -#else /* LINUX_VERSION_CODE < KERNEL_VERSION(3, 2, 0) && !CFG80211_STA_EVENT_AVAILABLE */ +#else /* LINUX_VERSION_CODE < KERNEL_VERSION(3, 2, 0) && !WL_CFG80211_STA_EVENT */ sinfo.filled = 0; if (((event == WLC_E_ASSOC_IND) || (event == WLC_E_REASSOC_IND)) && reason == DOT11_SC_SUCCESS) { @@ -4730,7 +4734,7 @@ exit: } else if ((event == WLC_E_DEAUTH_IND) || (event == WLC_E_DEAUTH)) { cfg80211_del_sta(ndev, e->addr.octet, GFP_ATOMIC); } -#endif /* LINUX_VERSION_CODE < KERNEL_VERSION(3, 2, 0) && !CFG80211_STA_EVENT_AVAILABLE */ +#endif /* LINUX_VERSION_CODE < KERNEL_VERSION(3, 2, 0) && !WL_CFG80211_STA_EVENT */ return err; } @@ -5332,10 +5336,10 @@ exit: } #ifdef WL_SCHED_SCAN -/* If target scan is not reliable, set the below define to "0" to do a +/* If target scan is not reliable, set the below define to "1" to do a * full escan */ -#define FULL_ESCAN_ON_PFN_NET_FOUND 1 +#define FULL_ESCAN_ON_PFN_NET_FOUND 0 static s32 wl_notify_sched_scan_results(struct wl_priv *wl, struct net_device *ndev, const wl_event_msg_t *e, void *data) @@ -5424,9 +5428,9 @@ wl_notify_sched_scan_results(struct wl_priv *wl, struct net_device *ndev, wl_set_drv_status(wl, SCANNING, ndev); #if FULL_ESCAN_ON_PFN_NET_FOUND - err = wl_do_escan(wl, wiphy, ndev, &request); -#else err = wl_do_escan(wl, wiphy, ndev, NULL); +#else + err = wl_do_escan(wl, wiphy, ndev, &request); #endif if (err) { wl_clr_drv_status(wl, SCANNING, ndev); @@ -5848,9 +5852,22 @@ wl_cfg80211_netdev_notifier_call(struct notifier_block * nb, return NOTIFY_DONE; switch (state) { case NETDEV_UNREGISTER: - /* after calling list_del_rcu(&wdev->list) */ - wl_dealloc_netinfo(wl, ndev); - break; + /* after calling list_del_rcu(&wdev->list) */ + wl_dealloc_netinfo(wl, ndev); + break; + case NETDEV_GOING_DOWN: + /* At NETDEV_DOWN state, wdev_cleanup_work work will be called. + * In front of door, the function checks + * whether current scan is working or not. + * If the scanning is still working, wdev_cleanup_work call WARN_ON and + * make the scan done forcibly. + */ + if (wl_get_drv_status(wl, SCANNING, dev)) { + if (wl->escan_on) { + wl_notify_escan_complete(wl, dev, true, true); + } + } + break; } return NOTIFY_DONE; } @@ -6175,7 +6192,7 @@ static void wl_deinit_priv(struct wl_priv *wl) unregister_netdevice_notifier(&wl_cfg80211_netdev_notifier); } -#if defined(WLP2P) && defined(ENABLE_P2P_INTERFACE) +#if defined(WLP2P) && defined(WL_ENABLE_P2P_IF) static s32 wl_cfg80211_attach_p2p(void) { struct wl_priv *wl = wlcfg_drv_priv; @@ -6210,7 +6227,7 @@ static s32 wl_cfg80211_detach_p2p(void) return 0; } -#endif /* defined(WLP2P) && (ENABLE_P2P_INTERFACE) */ +#endif /* defined(WLP2P) && defined(WL_ENABLE_P2P_IF) */ s32 wl_cfg80211_attach_post(struct net_device *ndev) { @@ -6225,7 +6242,7 @@ s32 wl_cfg80211_attach_post(struct net_device *ndev) if (wl && !wl_get_drv_status(wl, READY, ndev)) { if (wl->wdev && wl_cfgp2p_supported(wl, ndev)) { -#if !defined(ENABLE_P2P_INTERFACE) +#if !defined(WL_ENABLE_P2P_IF) wl->wdev->wiphy->interface_modes |= (BIT(NL80211_IFTYPE_P2P_CLIENT)| BIT(NL80211_IFTYPE_P2P_GO)); @@ -6233,7 +6250,7 @@ s32 wl_cfg80211_attach_post(struct net_device *ndev) if ((err = wl_cfgp2p_init_priv(wl)) != 0) goto fail; -#if defined(WLP2P) && defined(ENABLE_P2P_INTERFACE) +#if defined(WLP2P) && defined(WL_ENABLE_P2P_IF) if (wl->p2p_net) { /* Update MAC addr for p2p0 interface here. */ memcpy(wl->p2p_net->dev_addr, ndev->dev_addr, ETH_ALEN); @@ -6245,7 +6262,7 @@ s32 wl_cfg80211_attach_post(struct net_device *ndev) " Couldn't update the MAC Address for p2p0 \n")); return -ENODEV; } -#endif /* defined(WLP2P) && (ENABLE_P2P_INTERFACE) */ +#endif /* defined(WLP2P) && (WL_ENABLE_P2P_IF) */ wl->p2p_supported = true; } @@ -6317,7 +6334,7 @@ s32 wl_cfg80211_attach(struct net_device *ndev, void *data) wlcfg_drv_priv = wl; -#if defined(WLP2P) && defined(ENABLE_P2P_INTERFACE) +#if defined(WLP2P) && defined(WL_ENABLE_P2P_IF) err = wl_cfg80211_attach_p2p(); if (err) goto cfg80211_attach_out; @@ -6343,7 +6360,7 @@ void wl_cfg80211_detach(void *para) wl_cfg80211_btcoex_deinit(wl); #endif -#if defined(WLP2P) && defined(ENABLE_P2P_INTERFACE) +#if defined(WLP2P) && defined(WL_ENABLE_P2P_IF) wl_cfg80211_detach_p2p(); #endif wl_setup_rfkill(wl, FALSE); @@ -6623,6 +6640,10 @@ s32 wl_update_wiphybands(struct wl_priv *wl) u32 nband = 0; u32 i = 0; s32 err = 0; + int nmode = 0; + int bw_40 = 0; + int index = 0; + WL_DBG(("Entry")); memset(bandlist, 0, sizeof(bandlist)); err = wldev_ioctl(wl_to_prmry_ndev(wl), WLC_GET_BANDLIST, bandlist, @@ -6635,14 +6656,43 @@ s32 wl_update_wiphybands(struct wl_priv *wl) nband = bandlist[0]; wiphy->bands[IEEE80211_BAND_5GHZ] = NULL; wiphy->bands[IEEE80211_BAND_2GHZ] = NULL; + + err = wldev_iovar_getint(wl_to_prmry_ndev(wl), "nmode", &nmode); + if (unlikely(err)) { + WL_ERR(("error (%d)\n", err)); + } + + err = wldev_iovar_getint(wl_to_prmry_ndev(wl), "mimo_bw_cap", &bw_40); + if (unlikely(err)) { + WL_ERR(("error (%d)\n", err)); + } + for (i = 1; i <= nband && i < sizeof(bandlist); i++) { - if (bandlist[i] == WLC_BAND_5G) + index = -1; + if (bandlist[i] == WLC_BAND_5G) { wiphy->bands[IEEE80211_BAND_5GHZ] = &__wl_band_5ghz_a; - else if (bandlist[i] == WLC_BAND_2G) + index = IEEE80211_BAND_5GHZ; + } else if (bandlist[i] == WLC_BAND_2G) { wiphy->bands[IEEE80211_BAND_2GHZ] = &__wl_band_2ghz; + index = IEEE80211_BAND_2GHZ; + } + + if ((index >= 0) && nmode) { + wiphy->bands[index]->ht_cap.cap = + IEEE80211_HT_CAP_SGI_20 | IEEE80211_HT_CAP_DSSSCCK40 + | IEEE80211_HT_CAP_MAX_AMSDU; + wiphy->bands[index]->ht_cap.ht_supported = TRUE; + wiphy->bands[index]->ht_cap.ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K; + wiphy->bands[index]->ht_cap.ampdu_density = IEEE80211_HT_MPDU_DENSITY_16; + } + + if ((index >= 0) && bw_40) { + wiphy->bands[index]->ht_cap.cap |= IEEE80211_HT_CAP_SGI_40; + } } + wiphy_apply_custom_regulatory(wiphy, &brcm_regdom); return err; } diff --git a/drivers/net/wireless/bcmdhd/wl_cfg80211.h b/drivers/net/wireless/bcmdhd/wl_cfg80211.h index 41e7c678e41b..515443bc3ec2 100644 --- a/drivers/net/wireless/bcmdhd/wl_cfg80211.h +++ b/drivers/net/wireless/bcmdhd/wl_cfg80211.h @@ -446,6 +446,7 @@ struct wl_priv { struct cfg80211_sched_scan_request *sched_scan_req; /* scheduled scan req */ #endif /* WL_SCHED_SCAN */ bool sched_scan_running; /* scheduled scan req status */ + u16 hostapd_chan; /* remember chan requested by framework for hostapd */ }; static inline struct wl_bss_info *next_bss(struct wl_scan_results *list, struct wl_bss_info *bss) diff --git a/drivers/net/wireless/bcmdhd/wldev_common.c b/drivers/net/wireless/bcmdhd/wldev_common.c index d9a0b93d689f..827033185035 100644 --- a/drivers/net/wireless/bcmdhd/wldev_common.c +++ b/drivers/net/wireless/bcmdhd/wldev_common.c @@ -366,3 +366,53 @@ int wldev_set_country( __FUNCTION__, country_code, cspec.ccode, cspec.rev)); return 0; } + +/* + * softap channel autoselect + */ +int wldev_get_auto_channel(struct net_device *dev, int *chan) +{ + int chosen = 0; + wl_uint32_list_t request; + int retry = 0; + int updown = 0; + int ret = 0; + wlc_ssid_t null_ssid; + + memset(&null_ssid, 0, sizeof(wlc_ssid_t)); + ret |= wldev_ioctl(dev, WLC_UP, &updown, sizeof(updown), true); + + ret |= wldev_ioctl(dev, WLC_SET_SSID, &null_ssid, sizeof(null_ssid), true); + + request.count = htod32(0); + ret = wldev_ioctl(dev, WLC_START_CHANNEL_SEL, &request, sizeof(request), true); + if (ret < 0) { + WLDEV_ERROR(("can't start auto channel scan:%d\n", ret)); + goto fail; + } + + while (retry++ < 15) { + + bcm_mdelay(350); + + ret = wldev_ioctl(dev, WLC_GET_CHANNEL_SEL, &chosen, sizeof(chosen), false); + + if ((ret == 0) && (dtoh32(chosen) != 0)) { + *chan = (uint16)chosen & 0x00FF; /* covert chanspec --> chan number */ + printf("%s: Got channel = %d, attempt:%d\n", + __FUNCTION__, *chan, retry); + break; + } + } + + if ((ret = wldev_ioctl(dev, WLC_DOWN, &updown, sizeof(updown), true)) < 0) { + WLDEV_ERROR(("%s fail to WLC_DOWN ioctl err =%d\n", __FUNCTION__, ret)); + goto fail; + } + +fail : + if (ret < 0) { + WLDEV_ERROR(("%s: return value %d\n", __FUNCTION__, ret)); + } + return ret; +} diff --git a/drivers/net/wireless/bcmdhd/wldev_common.h b/drivers/net/wireless/bcmdhd/wldev_common.h index 773235e4597e..f58660944420 100644 --- a/drivers/net/wireless/bcmdhd/wldev_common.h +++ b/drivers/net/wireless/bcmdhd/wldev_common.h @@ -107,4 +107,6 @@ int wldev_get_band(struct net_device *dev, uint *pband); int wldev_set_band(struct net_device *dev, uint band); +int wldev_get_auto_channel(struct net_device *dev, int *chan); + #endif /* __WLDEV_COMMON_H__ */ -- cgit v1.2.3 From edce35e13010434c6e8ed631594f28cc3fff4337 Mon Sep 17 00:00:00 2001 From: Dmitry Shmidt Date: Tue, 20 Mar 2012 13:08:13 -0700 Subject: net: wireless: bcmdhd: Add WL_CFG80211_STA_EVENT config option Signed-off-by: Dmitry Shmidt --- drivers/net/wireless/bcmdhd/Makefile | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/net') diff --git a/drivers/net/wireless/bcmdhd/Makefile b/drivers/net/wireless/bcmdhd/Makefile index 2fe7fa3d59fa..1f4426f64b2a 100644 --- a/drivers/net/wireless/bcmdhd/Makefile +++ b/drivers/net/wireless/bcmdhd/Makefile @@ -9,6 +9,7 @@ DHDCFLAGS = -Wall -Wstrict-prototypes -Dlinux -DBCMDRIVER \ -DKEEP_ALIVE -DPKT_FILTER_SUPPORT \ -DEMBEDDED_PLATFORM \ -DSET_RANDOM_MAC_SOFTAP -DWL_ENABLE_P2P_IF -DDHD_USE_EARLYSUSPEND \ + -DWL_CFG80211_STA_EVENT \ -Idrivers/net/wireless/bcmdhd -Idrivers/net/wireless/bcmdhd/include ifeq ($(CONFIG_BCMDHD_WIFI_CONTROL_FUNC),y) -- cgit v1.2.3 From b571ba77168b10748541d53e52bdd4593f408eb3 Mon Sep 17 00:00:00 2001 From: Dmitry Shmidt Date: Tue, 20 Mar 2012 13:38:06 -0700 Subject: net: wireless: bcmdhd: Add constant mDNS filter Signed-off-by: Dmitry Shmidt --- drivers/net/wireless/bcmdhd/dhd.h | 1 + drivers/net/wireless/bcmdhd/dhd_linux.c | 6 ++++-- 2 files changed, 5 insertions(+), 2 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/bcmdhd/dhd.h b/drivers/net/wireless/bcmdhd/dhd.h index f73956afba4d..68991851b32f 100644 --- a/drivers/net/wireless/bcmdhd/dhd.h +++ b/drivers/net/wireless/bcmdhd/dhd.h @@ -447,6 +447,7 @@ extern int dhd_dev_get_pno_status(struct net_device *dev); #define DHD_BROADCAST_FILTER_NUM 1 #define DHD_MULTICAST4_FILTER_NUM 2 #define DHD_MULTICAST6_FILTER_NUM 3 +#define DHD_MDNS_FILTER_NUM 4 extern int net_os_set_packet_filter(struct net_device *dev, int val); extern int net_os_rxfilter_add_remove(struct net_device *dev, int val, int num); diff --git a/drivers/net/wireless/bcmdhd/dhd_linux.c b/drivers/net/wireless/bcmdhd/dhd_linux.c index e79a6c7e314b..4196e9d3eebf 100644 --- a/drivers/net/wireless/bcmdhd/dhd_linux.c +++ b/drivers/net/wireless/bcmdhd/dhd_linux.c @@ -3218,12 +3218,13 @@ dhd_preinit_ioctls(dhd_pub_t *dhd) #ifdef PKT_FILTER_SUPPORT /* Setup defintions for pktfilter , enable in suspend */ - dhd->pktfilter_count = 4; + dhd->pktfilter_count = 5; /* Setup filter to allow only unicast */ dhd->pktfilter[0] = "100 0 0 0 0x01 0x00"; dhd->pktfilter[1] = NULL; dhd->pktfilter[2] = NULL; dhd->pktfilter[3] = NULL; + dhd->pktfilter[4] = "104 0 0 0 0xFFFFFFFFFFFF 0x01005E0000FB"; #if defined(SOFTAP) if (ap_fw_loaded) { int i; @@ -4322,7 +4323,8 @@ int net_os_rxfilter_add_remove(struct net_device *dev, int add_remove, int num) char *filterp = NULL; int ret = 0; - if (!dhd || (num == DHD_UNICAST_FILTER_NUM)) + if (!dhd || (num == DHD_UNICAST_FILTER_NUM) || + (num == DHD_MDNS_FILTER_NUM)) return ret; if (num >= dhd->pub.pktfilter_count) return -EINVAL; -- cgit v1.2.3 From a45c64bf1880ccea3668be496ffe58796bf61672 Mon Sep 17 00:00:00 2001 From: Dmitry Shmidt Date: Tue, 20 Mar 2012 17:04:02 -0700 Subject: net: wireless: bcmdhd: Set probe_resp.timestamp value to scan results Signed-off-by: Dmitry Shmidt --- drivers/net/wireless/bcmdhd/wl_cfg80211.c | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'drivers/net') diff --git a/drivers/net/wireless/bcmdhd/wl_cfg80211.c b/drivers/net/wireless/bcmdhd/wl_cfg80211.c index 53bf68c0f447..de5fd674692e 100644 --- a/drivers/net/wireless/bcmdhd/wl_cfg80211.c +++ b/drivers/net/wireless/bcmdhd/wl_cfg80211.c @@ -4549,6 +4549,14 @@ static s32 wl_inform_single_bss(struct wl_priv *wl, struct wl_bss_info *bi) } } + if (!mgmt->u.probe_resp.timestamp) { + struct timeval tv; + + do_gettimeofday(&tv); + mgmt->u.probe_resp.timestamp = ((u64)tv.tv_sec * 1000000) + + tv.tv_usec; + } + cbss = cfg80211_inform_bss_frame(wiphy, channel, mgmt, le16_to_cpu(notif_bss_info->frame_len), signal, GFP_KERNEL); if (unlikely(!cbss)) { -- cgit v1.2.3 From 572d59e21a1da53e370af3547acdf09fb0ee3b11 Mon Sep 17 00:00:00 2001 From: Dmitry Shmidt Date: Wed, 21 Mar 2012 12:35:56 -0700 Subject: net: wireless: bcmdhd: Add 'wlan_ctrl_wake' wakelock Signed-off-by: Dmitry Shmidt --- drivers/net/wireless/bcmdhd/dhd.h | 9 ++--- drivers/net/wireless/bcmdhd/dhd_linux.c | 71 +++++++++++++++++++++++++-------- 2 files changed, 59 insertions(+), 21 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/bcmdhd/dhd.h b/drivers/net/wireless/bcmdhd/dhd.h index 68991851b32f..9f378c6cb1d0 100644 --- a/drivers/net/wireless/bcmdhd/dhd.h +++ b/drivers/net/wireless/bcmdhd/dhd.h @@ -213,9 +213,6 @@ typedef struct dhd_pub { * see target dhd-cdc-sdmmc-panda-cfg80211-icsmr1-gpl-debug in Makefile */ -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) && defined(CONFIG_HAS_WAKELOCK) - struct wake_lock wakelock[WAKE_LOCK_MAX]; -#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) && defined (CONFIG_HAS_WAKELOCK) */ #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25)) && 1 struct mutex wl_start_stop_lock; /* lock/unlock for Android start/stop */ struct mutex wl_softap_lock; /* lock/unlock for any SoftAP/STA settings */ @@ -297,7 +294,8 @@ void dhd_os_spin_unlock(dhd_pub_t *pub, unsigned long flags); extern int dhd_os_wake_lock(dhd_pub_t *pub); extern int dhd_os_wake_unlock(dhd_pub_t *pub); extern int dhd_os_wake_lock_timeout(dhd_pub_t *pub); -extern int dhd_os_wake_lock_timeout_enable(dhd_pub_t *pub, int val); +extern int dhd_os_wake_lock_rx_timeout_enable(dhd_pub_t *pub, int val); +extern int dhd_os_wake_lock_ctrl_timeout_enable(dhd_pub_t *pub, int val); inline static void MUTEX_LOCK_SOFTAP_SET_INIT(dhd_pub_t * dhdp) { @@ -323,7 +321,8 @@ inline static void MUTEX_UNLOCK_SOFTAP_SET(dhd_pub_t * dhdp) #define DHD_OS_WAKE_LOCK(pub) dhd_os_wake_lock(pub) #define DHD_OS_WAKE_UNLOCK(pub) dhd_os_wake_unlock(pub) #define DHD_OS_WAKE_LOCK_TIMEOUT(pub) dhd_os_wake_lock_timeout(pub) -#define DHD_OS_WAKE_LOCK_TIMEOUT_ENABLE(pub, val) dhd_os_wake_lock_timeout_enable(pub, val) +#define DHD_OS_WAKE_LOCK_RX_TIMEOUT_ENABLE(pub, val) dhd_os_wake_lock_rx_timeout_enable(pub, val) +#define DHD_OS_WAKE_LOCK_CTRL_TIMEOUT_ENABLE(pub, val) dhd_os_wake_lock_ctrl_timeout_enable(pub, val) #define DHD_PACKET_TIMEOUT_MS 1000 #define DHD_EVENT_TIMEOUT_MS 1500 diff --git a/drivers/net/wireless/bcmdhd/dhd_linux.c b/drivers/net/wireless/bcmdhd/dhd_linux.c index 4196e9d3eebf..508f0a6e4483 100644 --- a/drivers/net/wireless/bcmdhd/dhd_linux.c +++ b/drivers/net/wireless/bcmdhd/dhd_linux.c @@ -252,6 +252,7 @@ typedef struct dhd_info { #if defined(CONFIG_HAS_WAKELOCK) && (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) struct wake_lock wl_wifi; /* Wifi wakelock */ struct wake_lock wl_rxwake; /* Wifi rx wakelock */ + struct wake_lock wl_ctrlwake; /* Wifi ctrl wakelock */ #endif #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25)) @@ -263,7 +264,8 @@ typedef struct dhd_info { #endif spinlock_t wakelock_spinlock; int wakelock_counter; - int wakelock_timeout_enable; + int wakelock_rx_timeout_enable; + int wakelock_ctrl_timeout_enable; /* Thread to issue ioctl for multicast */ bool set_macaddress; @@ -1406,7 +1408,8 @@ dhd_rx_frame(dhd_pub_t *dhdp, int ifidx, void *pktbuf, int numpkt, uint8 chan) int i; dhd_if_t *ifp; wl_event_msg_t event; - int tout = DHD_PACKET_TIMEOUT_MS; + int tout_rx = 0; + int tout_ctrl = 0; DHD_TRACE(("%s: Enter\n", __FUNCTION__)); @@ -1508,12 +1511,15 @@ dhd_rx_frame(dhd_pub_t *dhdp, int ifidx, void *pktbuf, int numpkt, uint8 chan) &data); wl_event_to_host_order(&event); - tout = DHD_EVENT_TIMEOUT_MS; + if (!tout_ctrl) + tout_ctrl = DHD_PACKET_TIMEOUT_MS; if (event.event_type == WLC_E_BTA_HCI_EVENT) { dhd_bta_doevt(dhdp, data, event.datalen); } else if (event.event_type == WLC_E_PFN_NET_FOUND) { - tout *= 2; + tout_ctrl *= 2; } + } else { + tout_rx = DHD_PACKET_TIMEOUT_MS; } ASSERT(ifidx < DHD_MAX_IFS && dhd->iflist[ifidx]); @@ -1546,7 +1552,8 @@ dhd_rx_frame(dhd_pub_t *dhdp, int ifidx, void *pktbuf, int numpkt, uint8 chan) #endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0) */ } } - DHD_OS_WAKE_LOCK_TIMEOUT_ENABLE(dhdp, tout); + DHD_OS_WAKE_LOCK_RX_TIMEOUT_ENABLE(dhdp, tout_rx); + DHD_OS_WAKE_LOCK_CTRL_TIMEOUT_ENABLE(dhdp, tout_ctrl); } void @@ -2045,7 +2052,7 @@ dhd_ioctl_entry(struct net_device *net, struct ifreq *ifr, int cmd) /* send to dongle only if we are not waiting for reload already */ if (dhd->pub.hang_was_sent) { DHD_ERROR(("%s: HANG was sent up earlier\n", __FUNCTION__)); - DHD_OS_WAKE_LOCK_TIMEOUT_ENABLE(&dhd->pub, DHD_EVENT_TIMEOUT_MS); + DHD_OS_WAKE_LOCK_CTRL_TIMEOUT_ENABLE(&dhd->pub, DHD_EVENT_TIMEOUT_MS); DHD_OS_WAKE_UNLOCK(&dhd->pub); return OSL_ERROR(BCME_DONGLE_DOWN); } @@ -2652,10 +2659,12 @@ dhd_attach(osl_t *osh, struct dhd_bus *bus, uint bus_hdrlen, void *dev) /* Initialize Wakelock stuff */ spin_lock_init(&dhd->wakelock_spinlock); dhd->wakelock_counter = 0; - dhd->wakelock_timeout_enable = 0; + dhd->wakelock_rx_timeout_enable = 0; + dhd->wakelock_ctrl_timeout_enable = 0; #ifdef CONFIG_HAS_WAKELOCK wake_lock_init(&dhd->wl_wifi, WAKE_LOCK_SUSPEND, "wlan_wake"); wake_lock_init(&dhd->wl_rxwake, WAKE_LOCK_SUSPEND, "wlan_rx_wake"); + wake_lock_init(&dhd->wl_ctrlwake, WAKE_LOCK_SUSPEND, "wlan_ctrl_wake"); #endif #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25)) mutex_init(&dhd->dhd_net_if_mutex); @@ -3696,6 +3705,7 @@ void dhd_detach(dhd_pub_t *dhdp) #ifdef CONFIG_HAS_WAKELOCK wake_lock_destroy(&dhd->wl_wifi); wake_lock_destroy(&dhd->wl_rxwake); + wake_lock_destroy(&dhd->wl_ctrlwake); #endif } } @@ -4592,13 +4602,18 @@ int dhd_os_wake_lock_timeout(dhd_pub_t *pub) if (dhd) { spin_lock_irqsave(&dhd->wakelock_spinlock, flags); - ret = dhd->wakelock_timeout_enable; + ret = dhd->wakelock_rx_timeout_enable > dhd->wakelock_ctrl_timeout_enable ? + dhd->wakelock_rx_timeout_enable : dhd->wakelock_ctrl_timeout_enable; #ifdef CONFIG_HAS_WAKELOCK - if (dhd->wakelock_timeout_enable) + if (dhd->wakelock_rx_timeout_enable) wake_lock_timeout(&dhd->wl_rxwake, - msecs_to_jiffies(dhd->wakelock_timeout_enable)); + msecs_to_jiffies(dhd->wakelock_rx_timeout_enable)); + if (dhd->wakelock_ctrl_timeout_enable) + wake_lock_timeout(&dhd->wl_ctrlwake, + msecs_to_jiffies(dhd->wakelock_ctrl_timeout_enable)); #endif - dhd->wakelock_timeout_enable = 0; + dhd->wakelock_rx_timeout_enable = 0; + dhd->wakelock_ctrl_timeout_enable = 0; spin_unlock_irqrestore(&dhd->wakelock_spinlock, flags); } return ret; @@ -4614,27 +4629,51 @@ int net_os_wake_lock_timeout(struct net_device *dev) return ret; } -int dhd_os_wake_lock_timeout_enable(dhd_pub_t *pub, int val) +int dhd_os_wake_lock_rx_timeout_enable(dhd_pub_t *pub, int val) +{ + dhd_info_t *dhd = (dhd_info_t *)(pub->info); + unsigned long flags; + + if (dhd) { + spin_lock_irqsave(&dhd->wakelock_spinlock, flags); + if (val > dhd->wakelock_rx_timeout_enable) + dhd->wakelock_rx_timeout_enable = val; + spin_unlock_irqrestore(&dhd->wakelock_spinlock, flags); + } + return 0; +} + +int dhd_os_wake_lock_ctrl_timeout_enable(dhd_pub_t *pub, int val) { dhd_info_t *dhd = (dhd_info_t *)(pub->info); unsigned long flags; if (dhd) { spin_lock_irqsave(&dhd->wakelock_spinlock, flags); - if (val > dhd->wakelock_timeout_enable) - dhd->wakelock_timeout_enable = val; + if (val > dhd->wakelock_ctrl_timeout_enable) + dhd->wakelock_ctrl_timeout_enable = val; spin_unlock_irqrestore(&dhd->wakelock_spinlock, flags); } return 0; } -int net_os_wake_lock_timeout_enable(struct net_device *dev, int val) +int net_os_wake_lock_rx_timeout_enable(struct net_device *dev, int val) +{ + dhd_info_t *dhd = *(dhd_info_t **)netdev_priv(dev); + int ret = 0; + + if (dhd) + ret = dhd_os_wake_lock_rx_timeout_enable(&dhd->pub, val); + return ret; +} + +int net_os_wake_lock_ctrl_timeout_enable(struct net_device *dev, int val) { dhd_info_t *dhd = *(dhd_info_t **)netdev_priv(dev); int ret = 0; if (dhd) - ret = dhd_os_wake_lock_timeout_enable(&dhd->pub, val); + ret = dhd_os_wake_lock_ctrl_timeout_enable(&dhd->pub, val); return ret; } -- cgit v1.2.3 From f90696b185c2ecebe82c9a1a981aae9e466348c8 Mon Sep 17 00:00:00 2001 From: Dmitry Shmidt Date: Mon, 26 Mar 2012 13:30:33 -0700 Subject: net: wireless: bcmdhd: Update to Version 5.90.195.46 - Fix WEXT compilation - Start SoftAP in G-band only - Fix IF_DEL timeout due to wrong status check - Fix P2P to pass certification - Enable arpoe in concurrent mode by default - Fail to start sched scan in P2P GO Signed-off-by: Dmitry Shmidt --- drivers/net/wireless/bcmdhd/bcmsdh_sdmmc.c | 9 +--- drivers/net/wireless/bcmdhd/dhd.h | 8 ++-- drivers/net/wireless/bcmdhd/dhd_cfg80211.c | 22 +++++++-- drivers/net/wireless/bcmdhd/dhd_cfg80211.h | 1 + drivers/net/wireless/bcmdhd/dhd_linux.c | 50 ++++++++++++------- drivers/net/wireless/bcmdhd/dhd_sdio.c | 7 +++ drivers/net/wireless/bcmdhd/include/epivers.h | 9 ++-- drivers/net/wireless/bcmdhd/wl_android.c | 8 ++++ drivers/net/wireless/bcmdhd/wl_cfg80211.c | 69 ++++++++++++++++++--------- drivers/net/wireless/bcmdhd/wl_cfg80211.h | 2 +- drivers/net/wireless/bcmdhd/wl_iw.c | 2 +- drivers/net/wireless/bcmdhd/wl_iw.h | 2 +- 12 files changed, 128 insertions(+), 61 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/bcmdhd/bcmsdh_sdmmc.c b/drivers/net/wireless/bcmdhd/bcmsdh_sdmmc.c index b47c9423b635..e67eeca1f99c 100644 --- a/drivers/net/wireless/bcmdhd/bcmsdh_sdmmc.c +++ b/drivers/net/wireless/bcmdhd/bcmsdh_sdmmc.c @@ -692,14 +692,9 @@ sdioh_enable_hw_oob_intr(sdioh_info_t *sd, bool enable) uint8 data; if (enable) - data = SDIO_SEPINT_MASK | SDIO_SEPINT_OE; /* enable hw oob interrupt */ + data = SDIO_SEPINT_MASK | SDIO_SEPINT_OE | SDIO_SEPINT_ACT_HI; else - data = SDIO_SEPINT_ACT_HI; /* disable hw oob interrupt */ - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 35) - /* Needed for Android Linux Kernel 2.6.35 */ - data |= SDIO_SEPINT_ACT_HI; /* Active HIGH */ -#endif + data = SDIO_SEPINT_ACT_HI; status = sdioh_request_byte(sd, SDIOH_WRITE, 0, SDIOD_CCCR_BRCM_SEPINT, &data); return status; diff --git a/drivers/net/wireless/bcmdhd/dhd.h b/drivers/net/wireless/bcmdhd/dhd.h index 9f378c6cb1d0..ab3f574c2c80 100644 --- a/drivers/net/wireless/bcmdhd/dhd.h +++ b/drivers/net/wireless/bcmdhd/dhd.h @@ -24,12 +24,11 @@ * software in any way with any other Broadcom software provided under a license * other than the GPL, without Broadcom's express prior written consent. * - * $Id: dhd.h 316856 2012-02-23 21:44:34Z $ + * $Id: dhd.h 323282 2012-03-23 19:41:57Z $ */ -/**************** - * Common types * - */ + + #ifndef _dhd_h_ #define _dhd_h_ @@ -511,6 +510,7 @@ extern int dhd_bus_start(dhd_pub_t *dhdp); extern int dhd_bus_membytes(dhd_pub_t *dhdp, bool set, uint32 address, uint8 *data, uint size); extern void dhd_print_buf(void *pbuf, int len, int bytes_per_line); extern bool dhd_is_associated(dhd_pub_t *dhd, void *bss_buf); +extern uint dhd_bus_chip_id(dhd_pub_t *dhdp); #if defined(KEEP_ALIVE) extern int dhd_keep_alive_onoff(dhd_pub_t *dhd); diff --git a/drivers/net/wireless/bcmdhd/dhd_cfg80211.c b/drivers/net/wireless/bcmdhd/dhd_cfg80211.c index 172f25fc578a..2503f51ec574 100644 --- a/drivers/net/wireless/bcmdhd/dhd_cfg80211.c +++ b/drivers/net/wireless/bcmdhd/dhd_cfg80211.c @@ -41,9 +41,7 @@ static int dhd_dongle_up = FALSE; static s32 wl_dongle_up(struct net_device *ndev, u32 up); -/** - * Function implementations - */ + s32 dhd_cfg80211_init(struct wl_priv *wl) { @@ -57,6 +55,12 @@ s32 dhd_cfg80211_deinit(struct wl_priv *wl) return 0; } +s32 dhd_cfg80211_get_opmode(struct wl_priv *wl) +{ + dhd_pub_t *dhd = (dhd_pub_t *)(wl->pub); + return dhd->op_mode; +} + s32 dhd_cfg80211_down(struct wl_priv *wl) { dhd_dongle_up = FALSE; @@ -68,6 +72,12 @@ s32 dhd_cfg80211_set_p2p_info(struct wl_priv *wl, int val) dhd_pub_t *dhd = (dhd_pub_t *)(wl->pub); dhd->op_mode |= val; WL_ERR(("Set : op_mode=%d\n", dhd->op_mode)); + +#ifdef ARP_OFFLOAD_SUPPORT + dhd_arp_offload_set(dhd, 0); + dhd_arp_offload_enable(dhd, false); +#endif + return 0; } @@ -76,6 +86,12 @@ s32 dhd_cfg80211_clean_p2p_info(struct wl_priv *wl) dhd_pub_t *dhd = (dhd_pub_t *)(wl->pub); dhd->op_mode &= ~CONCURENT_MASK; WL_ERR(("Clean : op_mode=%d\n", dhd->op_mode)); + +#ifdef ARP_OFFLOAD_SUPPORT + dhd_arp_offload_set(dhd, dhd_arp_mode); + dhd_arp_offload_enable(dhd, true); +#endif + return 0; } diff --git a/drivers/net/wireless/bcmdhd/dhd_cfg80211.h b/drivers/net/wireless/bcmdhd/dhd_cfg80211.h index 6c033259a8d9..ced46dbdb96c 100644 --- a/drivers/net/wireless/bcmdhd/dhd_cfg80211.h +++ b/drivers/net/wireless/bcmdhd/dhd_cfg80211.h @@ -33,6 +33,7 @@ s32 dhd_cfg80211_init(struct wl_priv *wl); s32 dhd_cfg80211_deinit(struct wl_priv *wl); +s32 dhd_cfg80211_get_opmode(struct wl_priv *wl); s32 dhd_cfg80211_down(struct wl_priv *wl); s32 dhd_cfg80211_set_p2p_info(struct wl_priv *wl, int val); s32 dhd_cfg80211_clean_p2p_info(struct wl_priv *wl); diff --git a/drivers/net/wireless/bcmdhd/dhd_linux.c b/drivers/net/wireless/bcmdhd/dhd_linux.c index 508f0a6e4483..8226ef203ff0 100644 --- a/drivers/net/wireless/bcmdhd/dhd_linux.c +++ b/drivers/net/wireless/bcmdhd/dhd_linux.c @@ -50,6 +50,7 @@ #include #include #include +#include #include #include @@ -1017,12 +1018,18 @@ dhd_op_if(dhd_if_t *ifp) DHD_TRACE(("\n%s: got 'DHD_IF_DEL' state\n", __FUNCTION__)); #ifdef WL_CFG80211 if (dhd->dhd_state & DHD_ATTACH_STATE_CFG80211) { - wl_cfg80211_notify_ifdel(ifp->net); + wl_cfg80211_ifdel_ops(ifp->net); } #endif netif_stop_queue(ifp->net); unregister_netdev(ifp->net); - ret = DHD_DEL_IF; /* Make sure the free_netdev() is called */ + ret = DHD_DEL_IF; + +#ifdef WL_CFG80211 + if (dhd->dhd_state & DHD_ATTACH_STATE_CFG80211) { + wl_cfg80211_notify_ifdel(); + } +#endif } break; case DHD_IF_DELETING: @@ -2960,13 +2967,14 @@ dhd_preinit_ioctls(dhd_pub_t *dhd) char buf[WLC_IOCTL_SMLEN]; char *ptr; uint32 listen_interval = LISTEN_INTERVAL; /* Default Listen Interval in Beacons */ + uint16 chipID; #if defined(SOFTAP) uint dtim = 1; #endif #if (defined(AP) && !defined(WLP2P)) || (!defined(AP) && defined(WL_CFG80211)) uint32 mpc = 0; /* Turn MPC off for AP/APSTA mode */ #endif -#if defined(AP) || (defined(WLP2P) && defined(WL_ENABLE_P2P_IF)) +#if defined(AP) || defined(WLP2P) uint32 apsta = 1; /* Enable APSTA mode */ #endif /* defined(AP) || defined(WLP2P) */ #ifdef GET_CUSTOM_MAC_ENABLE @@ -2981,7 +2989,7 @@ dhd_preinit_ioctls(dhd_pub_t *dhd) bcm_mkiovar("cur_etheraddr", (void *)&ea_addr, ETHER_ADDR_LEN, buf, sizeof(buf)); ret = dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, buf, sizeof(buf), TRUE, 0); if (ret < 0) { - DHD_ERROR(("%s: can't set MAC address , error=%d\n", __FUNCTION__, ret)); + DHD_ERROR(("%s: can't set custom MAC address , error=%d\n", __FUNCTION__, ret)); return BCME_NOTUP; } memcpy(dhd->mac.octet, ea_addr.octet, ETHER_ADDR_LEN); @@ -3002,7 +3010,7 @@ dhd_preinit_ioctls(dhd_pub_t *dhd) #endif /* GET_CUSTOM_MAC_ENABLE */ #ifdef SET_RANDOM_MAC_SOFTAP - if ((!op_mode && strstr(fw_path, "_apsta") != NULL) || (op_mode == 0x02)) { + if ((!op_mode && strstr(fw_path, "_apsta") != NULL) || (op_mode == HOSTAPD_MASK)) { uint rand_mac; srandom32((uint)jiffies); @@ -3023,20 +3031,20 @@ dhd_preinit_ioctls(dhd_pub_t *dhd) } #endif /* SET_RANDOM_MAC_SOFTAP */ - DHD_TRACE(("Firmware = %s\n", fw_path)); -#if !defined(AP) && defined(WLP2P) && defined(WL_ENABLE_P2P_IF) + DHD_ERROR(("Firmware = %s\n", fw_path)); +#if !defined(AP) && defined(WLP2P) /* Check if firmware with WFD support used */ - if ((!op_mode && strstr(fw_path, "_p2p") != NULL) || (op_mode == 0x04) || - (dhd_concurrent_fw(dhd))) { + if ((!op_mode && strstr(fw_path, "_p2p") != NULL) +#if defined(WL_ENABLE_P2P_IF) + || (op_mode == 0x04) ||(dhd_concurrent_fw(dhd)) +#endif + ) { bcm_mkiovar("apsta", (char *)&apsta, 4, iovbuf, sizeof(iovbuf)); if ((ret = dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, sizeof(iovbuf), TRUE, 0)) < 0) { DHD_ERROR(("%s APSTA for WFD failed ret= %d\n", __FUNCTION__, ret)); } else { dhd->op_mode |= WFD_MASK; -#if defined(ARP_OFFLOAD_SUPPORT) - arpoe = 0; -#endif /* (ARP_OFFLOAD_SUPPORT) */ dhd_pkt_filter_enable = FALSE; } } @@ -3044,8 +3052,14 @@ dhd_preinit_ioctls(dhd_pub_t *dhd) #if !defined(AP) && defined(WL_CFG80211) /* Check if firmware with HostAPD support used */ - if ((!op_mode && strstr(fw_path, "_apsta") != NULL) || (op_mode == 0x02)) { - /* Turn off wme if we are having only g ONLY firmware */ + if ((!op_mode && strstr(fw_path, "_apsta") != NULL) || (op_mode == HOSTAPD_MASK)) { + uint band = WLC_BAND_2G; + + if ((ret = dhd_wl_ioctl_cmd(dhd, WLC_SET_BAND, (char *)band, sizeof(band), + TRUE, 0)) < 0) { + DHD_ERROR(("%s:set band failed error (%d)\n", __FUNCTION__, ret)); + } + bcm_mkiovar("nmode", 0, 0, buf, sizeof(buf)); if ((ret = dhd_wl_ioctl_cmd(dhd, WLC_GET_VAR, buf, sizeof(buf), FALSE, 0)) < 0) { @@ -3114,8 +3128,12 @@ dhd_preinit_ioctls(dhd_pub_t *dhd) dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, sizeof(iovbuf), TRUE, 0); /* disable glom option per default */ - bcm_mkiovar("bus:txglom", (char *)&glom, 4, iovbuf, sizeof(iovbuf)); - dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, sizeof(iovbuf), TRUE, 0); + chipID = (uint16)dhd_bus_chip_id(dhd); + if ((chipID == BCM4330_CHIP_ID) || (chipID == BCM4329_CHIP_ID)) { + DHD_INFO(("%s disable glom for chipID=0x%X\n", __FUNCTION__, chipID)); + bcm_mkiovar("bus:txglom", (char *)&glom, 4, iovbuf, sizeof(iovbuf)); + dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, sizeof(iovbuf), TRUE, 0); + } /* Setup timeout if Beacons are lost and roam is off to report link down */ bcm_mkiovar("bcn_timeout", (char *)&bcn_timeout, 4, iovbuf, sizeof(iovbuf)); diff --git a/drivers/net/wireless/bcmdhd/dhd_sdio.c b/drivers/net/wireless/bcmdhd/dhd_sdio.c index 3bef13ea1088..a5f30518c5b2 100644 --- a/drivers/net/wireless/bcmdhd/dhd_sdio.c +++ b/drivers/net/wireless/bcmdhd/dhd_sdio.c @@ -6303,6 +6303,13 @@ dhd_bus_devreset(dhd_pub_t *dhdp, uint8 flag) return bcmerror; } +uint dhd_bus_chip_id(dhd_pub_t *dhdp) +{ + dhd_bus_t *bus = dhdp->bus; + + return bus->sih->chip; +} + int dhd_bus_membytes(dhd_pub_t *dhdp, bool set, uint32 address, uint8 *data, uint size) { diff --git a/drivers/net/wireless/bcmdhd/include/epivers.h b/drivers/net/wireless/bcmdhd/include/epivers.h index ddb28aed0baf..9fd097ec8b98 100644 --- a/drivers/net/wireless/bcmdhd/include/epivers.h +++ b/drivers/net/wireless/bcmdhd/include/epivers.h @@ -23,7 +23,6 @@ * */ - #ifndef _epivers_h_ #define _epivers_h_ @@ -33,17 +32,17 @@ #define EPI_RC_NUMBER 195 -#define EPI_INCREMENTAL_NUMBER 35 +#define EPI_INCREMENTAL_NUMBER 46 #define EPI_BUILD_NUMBER 0 -#define EPI_VERSION 5, 90, 195, 35 +#define EPI_VERSION 5, 90, 195, 46 -#define EPI_VERSION_NUM 0x055ac323 +#define EPI_VERSION_NUM 0x055ac32e #define EPI_VERSION_DEV 5.90.195 -#define EPI_VERSION_STR "5.90.195.35" +#define EPI_VERSION_STR "5.90.195.46" #endif diff --git a/drivers/net/wireless/bcmdhd/wl_android.c b/drivers/net/wireless/bcmdhd/wl_android.c index 7b5dd8a0b87c..b98fe1d8f784 100644 --- a/drivers/net/wireless/bcmdhd/wl_android.c +++ b/drivers/net/wireless/bcmdhd/wl_android.c @@ -74,6 +74,9 @@ #define CMD_GETBAND "GETBAND" #define CMD_COUNTRY "COUNTRY" #define CMD_P2P_SET_NOA "P2P_SET_NOA" +#if !defined WL_ENABLE_P2P_IF +#define CMD_P2P_GET_NOA "P2P_GET_NOA" +#endif #define CMD_P2P_SET_PS "P2P_SET_PS" #define CMD_SET_AP_WPS_P2P_IE "SET_AP_WPS_P2P_IE" @@ -560,6 +563,11 @@ int wl_android_priv_cmd(struct net_device *net, struct ifreq *ifr, int cmd) bytes_written = wl_cfg80211_set_p2p_noa(net, command + skip, priv_cmd.total_len - skip); } +#if !defined WL_ENABLE_P2P_IF + else if (strnicmp(command, CMD_P2P_GET_NOA, strlen(CMD_P2P_GET_NOA)) == 0) { + bytes_written = wl_cfg80211_get_p2p_noa(net, command, priv_cmd.total_len); + } +#endif else if (strnicmp(command, CMD_P2P_SET_PS, strlen(CMD_P2P_SET_PS)) == 0) { int skip = strlen(CMD_P2P_SET_PS) + 1; bytes_written = wl_cfg80211_set_p2p_ps(net, command + skip, diff --git a/drivers/net/wireless/bcmdhd/wl_cfg80211.c b/drivers/net/wireless/bcmdhd/wl_cfg80211.c index de5fd674692e..ca4d243e9e31 100644 --- a/drivers/net/wireless/bcmdhd/wl_cfg80211.c +++ b/drivers/net/wireless/bcmdhd/wl_cfg80211.c @@ -733,7 +733,9 @@ wl_cfg80211_add_virtual_iface(struct wiphy *wiphy, char *name, s32 timeout = -1; s32 wlif_type = -1; s32 mode = 0; +#if defined(WL_ENABLE_P2P_IF) s32 dhd_mode = 0; +#endif chanspec_t chspec; struct wl_priv *wl = wiphy_priv(wiphy); struct net_device *_ndev; @@ -866,14 +868,14 @@ wl_cfg80211_add_virtual_iface(struct wiphy *wiphy, char *name, wl_alloc_netinfo(wl, _ndev, vwdev, mode); WL_ERR((" virtual interface(%s) is " "created net attach done\n", wl->p2p->vir_ifname)); +#if defined(WL_ENABLE_P2P_IF) if (type == NL80211_IFTYPE_P2P_CLIENT) dhd_mode = P2P_GC_ENABLED; else if (type == NL80211_IFTYPE_P2P_GO) dhd_mode = P2P_GO_ENABLED; DNGL_FUNC(dhd_cfg80211_set_p2p_info, (wl, dhd_mode)); - /* Start the P2P I/F with PM disabled. Enable PM from - * the framework - */ +#endif + if ((type == NL80211_IFTYPE_P2P_CLIENT) || ( type == NL80211_IFTYPE_P2P_GO)) vwdev->ps = NL80211_PS_DISABLED; @@ -940,11 +942,13 @@ wl_cfg80211_del_virtual_iface(struct wiphy *wiphy, struct net_device *dev) /* Wait for any pending scan req to get aborted from the sysioc context */ timeout = wait_event_interruptible_timeout(wl->netif_change_event, - (wl_get_p2p_status(wl, IF_DELETING) == false), + (wl->p2p->vif_created == false), msecs_to_jiffies(MAX_WAIT_TIME)); - if (timeout > 0 && !wl_get_p2p_status(wl, IF_DELETING)) { + if (timeout > 0 && (wl->p2p->vif_created == false)) { WL_DBG(("IFDEL operation done\n")); +#if defined(WL_ENABLE_P2P_IF) DNGL_FUNC(dhd_cfg80211_clean_p2p_info, (wl)); +#endif } else { WL_ERR(("IFDEL didn't complete properly\n")); } @@ -1067,7 +1071,18 @@ wl_cfg80211_notify_ifadd(struct net_device *ndev, s32 idx, s32 bssidx, } s32 -wl_cfg80211_notify_ifdel(struct net_device *ndev) +wl_cfg80211_notify_ifdel(void) +{ + struct wl_priv *wl = wlcfg_drv_priv; + + WL_DBG(("Enter \n")); + wl_clr_p2p_status(wl, IF_DELETING); + + return 0; +} + +s32 +wl_cfg80211_ifdel_ops(struct net_device *ndev) { struct wl_priv *wl = wlcfg_drv_priv; bool rollback_lock = false; @@ -1103,7 +1118,6 @@ wl_cfg80211_notify_ifdel(struct net_device *ndev) wl->p2p->vif_created = false; wl_cfgp2p_clear_management_ie(wl, index); - wl_clr_p2p_status(wl, IF_DELETING); WL_DBG(("index : %d\n", index)); } @@ -3600,11 +3614,12 @@ wl_cfg80211_set_channel(struct wiphy *wiphy, struct net_device *dev, } channel = ieee80211_frequency_to_channel(chan->center_freq); - if (wl_get_drv_status(wl, AP_CREATING, dev) && channel == 14) { + if (wl_get_drv_status(wl, AP_CREATING, dev)) { WL_TRACE(("<0> %s: as!!! in AP creating mode, save chan num:%d\n", __FUNCTION__, channel)); wl->hostapd_chan = channel; - return err; + if (channel == 14) + return err; } WL_DBG(("netdev_ifidx(%d), chan_type(%d) target channel(%d) \n", @@ -4235,10 +4250,12 @@ int wl_cfg80211_sched_scan_start(struct wiphy *wiphy, WL_DBG(("ssids:%d pno_time:%d pno_repeat:%d pno_freq:%d \n", request->n_ssids, pno_time, pno_repeat, pno_freq_expo_max)); - if (wl_get_drv_status_all(wl, SCANNING)) { - WL_ERR(("Scanning already\n")); - return -EAGAIN; +#if defined(WL_ENABLE_P2P_IF) + if (dhd_cfg80211_get_opmode(wl) & P2P_GO_ENABLED) { + WL_DBG(("PNO not enabled! op_mode: P2P GO")); + return -1; } +#endif if (!request || !request->n_ssids || !request->n_match_sets) { WL_ERR(("Invalid sched scan req!! n_ssids:%d \n", request->n_ssids)); @@ -4535,9 +4552,11 @@ static s32 wl_inform_single_bss(struct wl_priv *wl, struct wl_bss_info *bi) #if defined(WLP2P) && defined(WL_ENABLE_P2P_IF) if (wl->p2p_net && wl->scan_request && - wl->scan_request->dev == wl->p2p_net) { + ((wl->scan_request->dev == wl->p2p_net) || + (wl->scan_request->dev == wl_to_p2p_bss_ndev(wl, P2PAPI_BSSCFG_CONNECTION)))){ #else - if (p2p_is_on(wl) && p2p_scan(wl)) { + if (p2p_is_on(wl) && ( p2p_scan(wl) || + (wl->scan_request->dev == wl_to_p2p_bss_ndev(wl, P2PAPI_BSSCFG_CONNECTION)))) { #endif /* find the P2PIE, if we do not find it, we will discard this frame */ wifi_p2p_ie_t * p2p_ie; @@ -5800,7 +5819,7 @@ static void wl_scan_timeout(unsigned long data) if (wl->scan_request) { WL_ERR(("timer expired\n")); if (wl->escan_on) - wl_notify_escan_complete(wl, wl->escan_info.ndev, true, true); + wl_notify_escan_complete(wl, wl->escan_info.ndev, false, true); else wl_notify_iscan_complete(wl_to_iscan(wl), true); } @@ -5926,7 +5945,7 @@ static s32 wl_notify_escan_complete(struct wl_priv *wl, spin_lock_irqsave(&wl->cfgdrv_lock, flags); #ifdef WL_SCHED_SCAN - if (wl->sched_scan_req && wl->sched_scan_running && !wl->scan_request) { + if (wl->sched_scan_req && !wl->scan_request) { WL_DBG((" REPORTING SCHED SCAN RESULTS \n")); if (aborted) cfg80211_sched_scan_stopped(wl->sched_scan_req->wiphy); @@ -6689,16 +6708,12 @@ s32 wl_update_wiphybands(struct wl_priv *wl) if ((index >= 0) && nmode) { wiphy->bands[index]->ht_cap.cap = - IEEE80211_HT_CAP_SGI_20 | IEEE80211_HT_CAP_DSSSCCK40 - | IEEE80211_HT_CAP_MAX_AMSDU; + IEEE80211_HT_CAP_DSSSCCK40 + | IEEE80211_HT_CAP_MAX_AMSDU | IEEE80211_HT_CAP_RX_STBC; wiphy->bands[index]->ht_cap.ht_supported = TRUE; - wiphy->bands[index]->ht_cap.ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K; + wiphy->bands[index]->ht_cap.ampdu_factor = IEEE80211_HT_MAX_AMPDU_16K; wiphy->bands[index]->ht_cap.ampdu_density = IEEE80211_HT_MPDU_DENSITY_16; } - - if ((index >= 0) && bw_40) { - wiphy->bands[index]->ht_cap.cap |= IEEE80211_HT_CAP_SGI_40; - } } wiphy_apply_custom_regulatory(wiphy, &brcm_regdom); @@ -6738,6 +6753,9 @@ static s32 __wl_cfg80211_down(struct wl_priv *wl) unsigned long flags; struct net_info *iter, *next; struct net_device *ndev = wl_to_prmry_ndev(wl); +#ifdef WL_ENABLE_P2P_IF + struct wiphy *wiphy = wl_to_prmry_ndev(wl)->ieee80211_ptr->wiphy; +#endif WL_DBG(("In\n")); /* Check if cfg80211 interface is already down */ @@ -6764,6 +6782,11 @@ static s32 __wl_cfg80211_down(struct wl_priv *wl) } wl_to_prmry_ndev(wl)->ieee80211_ptr->iftype = NL80211_IFTYPE_STATION; +#ifdef WL_ENABLE_P2P_IF + wiphy->interface_modes = (wiphy->interface_modes) + & (~(BIT(NL80211_IFTYPE_P2P_CLIENT)| + BIT(NL80211_IFTYPE_P2P_GO))); +#endif spin_unlock_irqrestore(&wl->cfgdrv_lock, flags); DNGL_FUNC(dhd_cfg80211_down, (wl)); diff --git a/drivers/net/wireless/bcmdhd/wl_cfg80211.h b/drivers/net/wireless/bcmdhd/wl_cfg80211.h index 515443bc3ec2..4cea796fa51f 100644 --- a/drivers/net/wireless/bcmdhd/wl_cfg80211.h +++ b/drivers/net/wireless/bcmdhd/wl_cfg80211.h @@ -643,7 +643,7 @@ extern s32 wl_cfg80211_down(void *para); extern s32 wl_cfg80211_notify_ifadd(struct net_device *ndev, s32 idx, s32 bssidx, void* _net_attach); extern s32 wl_cfg80211_ifdel_ops(struct net_device *net); -extern s32 wl_cfg80211_notify_ifdel(struct net_device *ndev); +extern s32 wl_cfg80211_notify_ifdel(void); extern s32 wl_cfg80211_is_progress_ifadd(void); extern s32 wl_cfg80211_is_progress_ifchange(void); extern s32 wl_cfg80211_is_progress_ifadd(void); diff --git a/drivers/net/wireless/bcmdhd/wl_iw.c b/drivers/net/wireless/bcmdhd/wl_iw.c index 25db3cada652..1b304bd6d1d8 100644 --- a/drivers/net/wireless/bcmdhd/wl_iw.c +++ b/drivers/net/wireless/bcmdhd/wl_iw.c @@ -1705,7 +1705,7 @@ wl_iw_send_priv_event( strcpy(extra, flag); wrqu.data.length = strlen(extra); wireless_send_event(dev, cmd, &wrqu, extra); - net_os_wake_lock_timeout_enable(dev, DHD_EVENT_TIMEOUT_MS); + net_os_wake_lock_ctrl_timeout_enable(dev, DHD_EVENT_TIMEOUT_MS); WL_TRACE(("Send IWEVCUSTOM Event as %s\n", extra)); return 0; diff --git a/drivers/net/wireless/bcmdhd/wl_iw.h b/drivers/net/wireless/bcmdhd/wl_iw.h index 273dcf12b89a..20fa24909f87 100644 --- a/drivers/net/wireless/bcmdhd/wl_iw.h +++ b/drivers/net/wireless/bcmdhd/wl_iw.h @@ -205,7 +205,7 @@ void wl_iw_detach(void); extern int net_os_wake_lock(struct net_device *dev); extern int net_os_wake_unlock(struct net_device *dev); extern int net_os_wake_lock_timeout(struct net_device *dev); -extern int net_os_wake_lock_timeout_enable(struct net_device *dev, int val); +extern int net_os_wake_lock_ctrl_timeout_enable(struct net_device *dev, int val); extern int net_os_set_suspend_disable(struct net_device *dev, int val); extern int net_os_set_suspend(struct net_device *dev, int val, int force); extern int net_os_set_dtim_skip(struct net_device *dev, int val); -- cgit v1.2.3 From c4c9118587a13faafb21fa3447c72be073a39acf Mon Sep 17 00:00:00 2001 From: Dmitry Shmidt Date: Tue, 27 Mar 2012 13:45:55 -0700 Subject: net: wireless: bcmdhd: Turn off DHD_USE_EARLYSUSPEND option Signed-off-by: Dmitry Shmidt --- drivers/net/wireless/bcmdhd/Makefile | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/bcmdhd/Makefile b/drivers/net/wireless/bcmdhd/Makefile index 1f4426f64b2a..64a87e1491ad 100644 --- a/drivers/net/wireless/bcmdhd/Makefile +++ b/drivers/net/wireless/bcmdhd/Makefile @@ -8,8 +8,7 @@ DHDCFLAGS = -Wall -Wstrict-prototypes -Dlinux -DBCMDRIVER \ -DNEW_COMPAT_WIRELESS -DWIFI_ACT_FRAME -DARP_OFFLOAD_SUPPORT \ -DKEEP_ALIVE -DPKT_FILTER_SUPPORT \ -DEMBEDDED_PLATFORM \ - -DSET_RANDOM_MAC_SOFTAP -DWL_ENABLE_P2P_IF -DDHD_USE_EARLYSUSPEND \ - -DWL_CFG80211_STA_EVENT \ + -DSET_RANDOM_MAC_SOFTAP -DWL_ENABLE_P2P_IF -DWL_CFG80211_STA_EVENT \ -Idrivers/net/wireless/bcmdhd -Idrivers/net/wireless/bcmdhd/include ifeq ($(CONFIG_BCMDHD_WIFI_CONTROL_FUNC),y) -- cgit v1.2.3 From 491e392c4ed0a56e005282ae2bdee5aa4c126bd9 Mon Sep 17 00:00:00 2001 From: Dmitry Shmidt Date: Thu, 29 Mar 2012 12:09:23 -0700 Subject: net: wireless: bcmdhd: Add CONFIG_DHD_ENABLE_P2P Kconfig option Signed-off-by: Dmitry Shmidt --- drivers/net/wireless/bcmdhd/Kconfig | 7 +++++++ drivers/net/wireless/bcmdhd/Makefile | 6 ++++-- 2 files changed, 11 insertions(+), 2 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/bcmdhd/Kconfig b/drivers/net/wireless/bcmdhd/Kconfig index dc490c3ecf8c..7afecb04ade9 100644 --- a/drivers/net/wireless/bcmdhd/Kconfig +++ b/drivers/net/wireless/bcmdhd/Kconfig @@ -50,6 +50,13 @@ config DHD_USE_SCHED_SCAN ---help--- Use CFG80211 sched scan +config DHD_ENABLE_P2P + bool "Enable Wifi Direct" + depends on BCMDHD && CFG80211 + default n + ---help--- + Use Enable Wifi Direct + config BCMDHD_CFG80211 bool "Enable CFG80211 support" depends on CFG80211 diff --git a/drivers/net/wireless/bcmdhd/Makefile b/drivers/net/wireless/bcmdhd/Makefile index 64a87e1491ad..fa7dc6dce6b8 100644 --- a/drivers/net/wireless/bcmdhd/Makefile +++ b/drivers/net/wireless/bcmdhd/Makefile @@ -8,7 +8,7 @@ DHDCFLAGS = -Wall -Wstrict-prototypes -Dlinux -DBCMDRIVER \ -DNEW_COMPAT_WIRELESS -DWIFI_ACT_FRAME -DARP_OFFLOAD_SUPPORT \ -DKEEP_ALIVE -DPKT_FILTER_SUPPORT \ -DEMBEDDED_PLATFORM \ - -DSET_RANDOM_MAC_SOFTAP -DWL_ENABLE_P2P_IF -DWL_CFG80211_STA_EVENT \ + -DSET_RANDOM_MAC_SOFTAP -DWL_CFG80211_STA_EVENT \ -Idrivers/net/wireless/bcmdhd -Idrivers/net/wireless/bcmdhd/include ifeq ($(CONFIG_BCMDHD_WIFI_CONTROL_FUNC),y) @@ -54,7 +54,9 @@ DHDCFLAGS += -DWL_CFG80211 endif ifneq ($(CONFIG_DHD_USE_SCHED_SCAN),) DHDCFLAGS += -DWL_SCHED_SCAN -else +endif +ifneq ($(CONFIG_DHD_ENABLE_P2P),) +DHDCFLAGS += -DWL_ENABLE_P2P_IF endif EXTRA_CFLAGS = $(DHDCFLAGS) ifeq ($(CONFIG_BCMDHD),m) -- cgit v1.2.3 From a9c881fe07e44f5bd7aaec9b8ef56b39739b6b04 Mon Sep 17 00:00:00 2001 From: Dmitry Shmidt Date: Thu, 29 Mar 2012 12:10:36 -0700 Subject: net: wireless: bcmdhd: Fix crash in dhd_preinit_ioctls() band set Signed-off-by: Dmitry Shmidt --- drivers/net/wireless/bcmdhd/dhd_linux.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/bcmdhd/dhd_linux.c b/drivers/net/wireless/bcmdhd/dhd_linux.c index 8226ef203ff0..80f53b346ced 100644 --- a/drivers/net/wireless/bcmdhd/dhd_linux.c +++ b/drivers/net/wireless/bcmdhd/dhd_linux.c @@ -3055,7 +3055,7 @@ dhd_preinit_ioctls(dhd_pub_t *dhd) if ((!op_mode && strstr(fw_path, "_apsta") != NULL) || (op_mode == HOSTAPD_MASK)) { uint band = WLC_BAND_2G; - if ((ret = dhd_wl_ioctl_cmd(dhd, WLC_SET_BAND, (char *)band, sizeof(band), + if ((ret = dhd_wl_ioctl_cmd(dhd, WLC_SET_BAND, (char *)&band, sizeof(band), TRUE, 0)) < 0) { DHD_ERROR(("%s:set band failed error (%d)\n", __FUNCTION__, ret)); } -- cgit v1.2.3 From fd034e3fa30b0dbe6b4904097d10627a8b7c7f91 Mon Sep 17 00:00:00 2001 From: Andrey Smolnikov Date: Mon, 2 Apr 2012 10:19:30 -0700 Subject: net: wireless: bcmdhd: Fix frame sequence lag issue Signed-off-by: Dmitry Shmidt --- drivers/net/wireless/bcmdhd/dhd_sdio.c | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/bcmdhd/dhd_sdio.c b/drivers/net/wireless/bcmdhd/dhd_sdio.c index a5f30518c5b2..49deee10fe11 100644 --- a/drivers/net/wireless/bcmdhd/dhd_sdio.c +++ b/drivers/net/wireless/bcmdhd/dhd_sdio.c @@ -21,7 +21,7 @@ * software in any way with any other Broadcom software provided under a license * other than the GPL, without Broadcom's express prior written consent. * - * $Id: dhd_sdio.c 315747 2012-02-18 00:16:06Z $ + * $Id: dhd_sdio.c 324417 2012-03-29 03:15:15Z $ */ #include @@ -754,7 +754,8 @@ dhdsdio_clkctl(dhd_bus_t *bus, uint target, bool pendok) uint oldstate = bus->clkstate; #endif /* DHD_DEBUG */ - DHD_TRACE(("%s: Enter\n", __FUNCTION__)); + DHD_TRACE(("%s: Enter bus->clkstate %u target %u\n", __FUNCTION__, + bus->clkstate, target)); /* Early exit if we're already there */ if (bus->clkstate == target) { @@ -4597,6 +4598,15 @@ clkwait: if (TXCTLOK(bus) && bus->ctrl_frame_stat && (bus->clkstate == CLK_AVAIL)) { int ret, i; + uint8* frame_seq = bus->ctrl_frame_buf + SDPCM_FRAMETAG_LEN; + + if (((bus->sih->chip == BCM4329_CHIP_ID) || /* limit to 4329 & 4330 for now */ + (bus->sih->chip == BCM4330_CHIP_ID)) && (*frame_seq != bus->tx_seq)) { + DHD_ERROR(("%s IOCTL frame seq lag detected!" + " frm_seq:%d != bus->tx_seq:%d, corrected\n", + __FUNCTION__, *frame_seq, bus->tx_seq)); + *frame_seq = bus->tx_seq; + } ret = dhd_bcmsdh_send_buf(bus, bcmsdh_cur_sbwad(sdh), SDIO_FUNC_2, F2SYNC, (uint8 *)bus->ctrl_frame_buf, (uint32)bus->ctrl_frame_len, @@ -6303,11 +6313,12 @@ dhd_bus_devreset(dhd_pub_t *dhdp, uint8 flag) return bcmerror; } +/* Get Chip ID version */ uint dhd_bus_chip_id(dhd_pub_t *dhdp) { dhd_bus_t *bus = dhdp->bus; - return bus->sih->chip; + return bus->sih->chip; } int -- cgit v1.2.3 From 76cc5ed02844a7ba70190e0d257ed6bb5637e1fc Mon Sep 17 00:00:00 2001 From: Dmitry Shmidt Date: Mon, 2 Apr 2012 10:23:59 -0700 Subject: net: wireless: bcmdhd: Fix FW hang recovery - Reduce IOCTL responce timeout to 2 sec (from 20) - Fix pending status in case of timeout - Pass error code from dhd_is_associated() call - Call cfg80211_disconnected() if no timeout detected Signed-off-by: Dmitry Shmidt --- drivers/net/wireless/bcmdhd/dhd.h | 2 +- drivers/net/wireless/bcmdhd/dhd_common.c | 13 ++++++++----- drivers/net/wireless/bcmdhd/dhd_dbg.h | 4 ++-- drivers/net/wireless/bcmdhd/dhd_proto.h | 2 +- drivers/net/wireless/bcmdhd/dhd_sdio.c | 2 +- drivers/net/wireless/bcmdhd/wl_cfg80211.c | 10 +++++----- 6 files changed, 18 insertions(+), 15 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/bcmdhd/dhd.h b/drivers/net/wireless/bcmdhd/dhd.h index ab3f574c2c80..db5822bbb6bf 100644 --- a/drivers/net/wireless/bcmdhd/dhd.h +++ b/drivers/net/wireless/bcmdhd/dhd.h @@ -509,7 +509,7 @@ extern uint dhd_bus_status(dhd_pub_t *dhdp); extern int dhd_bus_start(dhd_pub_t *dhdp); extern int dhd_bus_membytes(dhd_pub_t *dhdp, bool set, uint32 address, uint8 *data, uint size); extern void dhd_print_buf(void *pbuf, int len, int bytes_per_line); -extern bool dhd_is_associated(dhd_pub_t *dhd, void *bss_buf); +extern bool dhd_is_associated(dhd_pub_t *dhd, void *bss_buf, int *retval); extern uint dhd_bus_chip_id(dhd_pub_t *dhdp); #if defined(KEEP_ALIVE) diff --git a/drivers/net/wireless/bcmdhd/dhd_common.c b/drivers/net/wireless/bcmdhd/dhd_common.c index e9511285163a..1e7a0679121d 100644 --- a/drivers/net/wireless/bcmdhd/dhd_common.c +++ b/drivers/net/wireless/bcmdhd/dhd_common.c @@ -305,7 +305,7 @@ dhd_wl_ioctl(dhd_pub_t *dhd_pub, int ifindex, wl_ioctl_t *ioc, void *buf, int le dhd_os_proto_block(dhd_pub); ret = dhd_prot_ioctl(dhd_pub, ifindex, ioc, buf, len); - if (!ret) + if (ret) dhd_os_check_hang(dhd_pub, ifindex, ret); dhd_os_proto_unblock(dhd_pub); @@ -1729,10 +1729,10 @@ fail: /* * returns = TRUE if associated, FALSE if not associated */ -bool dhd_is_associated(dhd_pub_t *dhd, void *bss_buf) +bool dhd_is_associated(dhd_pub_t *dhd, void *bss_buf, int *retval) { char bssid[6], zbuf[6]; - int ret = -1; + int ret; bzero(bssid, 6); bzero(zbuf, 6); @@ -1740,6 +1740,9 @@ bool dhd_is_associated(dhd_pub_t *dhd, void *bss_buf) ret = dhd_wl_ioctl_cmd(dhd, WLC_GET_BSSID, (char *)&bssid, ETHER_ADDR_LEN, FALSE, 0); DHD_TRACE((" %s WLC_GET_BSSID ioctl res = %d\n", __FUNCTION__, ret)); + if (retval) + *retval = ret; + if (ret == BCME_NOTASSOCIATED) { DHD_TRACE(("%s: not associated! res:%d\n", __FUNCTION__, ret)); } @@ -1776,7 +1779,7 @@ dhd_get_dtim_skip(dhd_pub_t *dhd) bcn_li_dtim = dhd->dtim_skip; /* Check if associated */ - if (dhd_is_associated(dhd, NULL) == FALSE) { + if (dhd_is_associated(dhd, NULL, NULL) == FALSE) { DHD_TRACE(("%s NOT assoc ret %d\n", __FUNCTION__, ret)); goto exit; } @@ -1889,7 +1892,7 @@ dhd_pno_enable(dhd_pub_t *dhd, int pfn_enabled) memset(iovbuf, 0, sizeof(iovbuf)); #ifndef WL_SCHED_SCAN - if ((pfn_enabled) && (dhd_is_associated(dhd, NULL) == TRUE)) { + if ((pfn_enabled) && (dhd_is_associated(dhd, NULL, NULL) == TRUE)) { DHD_ERROR(("%s pno is NOT enable : called in assoc mode , ignore\n", __FUNCTION__)); return ret; } diff --git a/drivers/net/wireless/bcmdhd/dhd_dbg.h b/drivers/net/wireless/bcmdhd/dhd_dbg.h index a195cbe88e5b..01be6a1f056f 100644 --- a/drivers/net/wireless/bcmdhd/dhd_dbg.h +++ b/drivers/net/wireless/bcmdhd/dhd_dbg.h @@ -29,8 +29,8 @@ #if defined(DHD_DEBUG) -#define DHD_ERROR(args) do {if ((dhd_msg_level & DHD_ERROR_VAL) && (net_ratelimit())) \ - printf args;} while (0) +#define DHD_ERROR(args) do {if ((dhd_msg_level & DHD_ERROR_VAL) && (net_ratelimit())) \ + printf args;} while (0) #define DHD_TRACE(args) do {if (dhd_msg_level & DHD_TRACE_VAL) printf args;} while (0) #define DHD_INFO(args) do {if (dhd_msg_level & DHD_INFO_VAL) printf args;} while (0) #define DHD_DATA(args) do {if (dhd_msg_level & DHD_DATA_VAL) printf args;} while (0) diff --git a/drivers/net/wireless/bcmdhd/dhd_proto.h b/drivers/net/wireless/bcmdhd/dhd_proto.h index e0a54ad02692..bb1d7365ea94 100644 --- a/drivers/net/wireless/bcmdhd/dhd_proto.h +++ b/drivers/net/wireless/bcmdhd/dhd_proto.h @@ -34,7 +34,7 @@ #include #ifndef IOCTL_RESP_TIMEOUT -#define IOCTL_RESP_TIMEOUT 20000 /* In milli second */ +#define IOCTL_RESP_TIMEOUT 2000 /* In milli second */ #endif /* diff --git a/drivers/net/wireless/bcmdhd/dhd_sdio.c b/drivers/net/wireless/bcmdhd/dhd_sdio.c index 49deee10fe11..e4fd2edef8fa 100644 --- a/drivers/net/wireless/bcmdhd/dhd_sdio.c +++ b/drivers/net/wireless/bcmdhd/dhd_sdio.c @@ -1455,7 +1455,7 @@ dhd_bus_rxctl(struct dhd_bus *bus, uchar *msg, uint msglen) { int timeleft; uint rxlen = 0; - bool pending; + bool pending = FALSE; DHD_TRACE(("%s: Enter\n", __FUNCTION__)); diff --git a/drivers/net/wireless/bcmdhd/wl_cfg80211.c b/drivers/net/wireless/bcmdhd/wl_cfg80211.c index ca4d243e9e31..178a23103e63 100644 --- a/drivers/net/wireless/bcmdhd/wl_cfg80211.c +++ b/drivers/net/wireless/bcmdhd/wl_cfg80211.c @@ -2844,11 +2844,11 @@ wl_cfg80211_get_station(struct wiphy *wiphy, struct net_device *dev, #endif } else if (wl_get_mode_by_netdev(wl, dev) == WL_MODE_BSS) { u8 *curmacp = wl_read_prof(wl, dev, WL_PROF_BSSID); + err = -ENODEV; if (!wl_get_drv_status(wl, CONNECTED, dev) || - (dhd_is_associated(dhd, NULL) == FALSE)) { + (dhd_is_associated(dhd, NULL, &err) == FALSE)) { - WL_ERR(("NOT assoc\n")); - err = -ENODEV; + WL_ERR(("NOT assoc: %d\n", err)); goto get_station_err; } if (memcmp(mac, curmacp, ETHER_ADDR_LEN)) { @@ -2881,9 +2881,9 @@ wl_cfg80211_get_station(struct wiphy *wiphy, struct net_device *dev, WL_DBG(("RSSI %d dBm\n", rssi)); get_station_err: - if (err) { + if (err && (err != -ETIMEDOUT) && (err != -EIO)) { /* Disconnect due to zero BSSID or error to get RSSI */ - WL_ERR(("force cfg80211_disconnected\n")); + WL_ERR(("force cfg80211_disconnected: %d\n", err)); wl_clr_drv_status(wl, CONNECTED, dev); cfg80211_disconnected(dev, 0, NULL, 0, GFP_KERNEL); wl_link_down(wl); -- cgit v1.2.3 From 0b11bef2e7e660cc56d644f55b26843c66a9904b Mon Sep 17 00:00:00 2001 From: Dmitry Shmidt Date: Mon, 2 Apr 2012 10:27:13 -0700 Subject: net: wireless: bcmdhd: Move FW hang processign to work queue Signed-off-by: Dmitry Shmidt --- drivers/net/wireless/bcmdhd/dhd_linux.c | 44 ++++++++++++++++++++++----------- 1 file changed, 30 insertions(+), 14 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/bcmdhd/dhd_linux.c b/drivers/net/wireless/bcmdhd/dhd_linux.c index 80f53b346ced..6cd0d7002c19 100644 --- a/drivers/net/wireless/bcmdhd/dhd_linux.c +++ b/drivers/net/wireless/bcmdhd/dhd_linux.c @@ -130,6 +130,9 @@ DECLARE_WAIT_QUEUE_HEAD(dhd_dpc_wait); #if defined(OOB_INTR_ONLY) extern void dhd_enable_oob_intr(struct dhd_bus *bus, bool enable); #endif /* defined(OOB_INTR_ONLY) */ + +static void dhd_hang_process(struct work_struct *work); + #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0)) MODULE_LICENSE("GPL v2"); #endif /* LinuxVer */ @@ -248,6 +251,7 @@ typedef struct dhd_info { bool dhd_tasklet_create; #endif /* DHDTHREAD */ tsk_ctl_t thr_sysioc_ctl; + struct work_struct work_hang; /* Wakelocks */ #if defined(CONFIG_HAS_WAKELOCK) && (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) @@ -2752,6 +2756,8 @@ dhd_attach(osl_t *osh, struct dhd_bus *bus, uint bus_hdrlen, void *dev) } dhd_state |= DHD_ATTACH_STATE_THREADS_CREATED; + INIT_WORK(&dhd->work_hang, dhd_hang_process); + /* * Save the dhd_info into the priv */ @@ -3634,6 +3640,8 @@ void dhd_detach(dhd_pub_t *dhdp) } #endif /* defined(CONFIG_HAS_EARLYSUSPEND) */ + cancel_work_sync(&dhd->work_hang); + #if defined(CONFIG_BCMDHD_WEXT) if (dhd->dhd_state & DHD_ATTACH_STATE_WL_ATTACH) { /* Detatch and unlink in the iw */ @@ -4445,29 +4453,37 @@ dhd_dev_get_pno_status(struct net_device *dev) #endif /* PNO_SUPPORT */ +static void dhd_hang_process(struct work_struct *work) +{ + dhd_info_t *dhd; + struct net_device *dev; + + dhd = (dhd_info_t *)container_of(work, dhd_info_t, work_hang); + dev = dhd->iflist[0]->net; + + if (dev) { + rtnl_lock(); + dev_close(dev); + rtnl_unlock(); +#if defined(WL_WIRELESS_EXT) + wl_iw_send_priv_event(dev, "HANG"); +#endif +#if defined(WL_CFG80211) + wl_cfg80211_hang(dev, WLAN_REASON_UNSPECIFIED); +#endif + } +} + #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) int net_os_send_hang_message(struct net_device *dev) { dhd_info_t *dhd = *(dhd_info_t **)netdev_priv(dev); int ret = 0; - int need_unlock = 0; if (dhd) { if (!dhd->pub.hang_was_sent) { dhd->pub.hang_was_sent = 1; - if (!rtnl_is_locked()) { - need_unlock = 1; - rtnl_lock(); - } - dev_close(dev); - if (need_unlock) - rtnl_unlock(); -#if defined(CONFIG_BCMDHD_WEXT) - ret = wl_iw_send_priv_event(dev, "HANG"); -#endif -#if defined(WL_CFG80211) - ret = wl_cfg80211_hang(dev, WLAN_REASON_UNSPECIFIED); -#endif + schedule_work(&dhd->work_hang); } } return ret; -- cgit v1.2.3 From f7136c9955912b104e1d2d11cc2b1ace7de7df91 Mon Sep 17 00:00:00 2001 From: Dmitry Shmidt Date: Thu, 5 Apr 2012 14:49:13 -0700 Subject: net: wireless: bcmdhd: Update to version 5.90.195.53 - Add retry to wl_cfg80211_mgmt_tx() for P2P - Change singal pending return value from -512 to -110 - Minor cleaning Signed-off-by: Dmitry Shmidt --- drivers/net/wireless/bcmdhd/bcmsdh_sdmmc_linux.c | 4 ++ drivers/net/wireless/bcmdhd/dhd.h | 6 +-- drivers/net/wireless/bcmdhd/dhd_cdc.c | 2 +- drivers/net/wireless/bcmdhd/dhd_linux.c | 30 ++++++++++---- drivers/net/wireless/bcmdhd/dhd_sdio.c | 31 ++++++++++---- drivers/net/wireless/bcmdhd/include/bcmdevs.h | 1 + drivers/net/wireless/bcmdhd/include/bcmsdstd.h | 7 +++- drivers/net/wireless/bcmdhd/include/dhdioctl.h | 5 ++- drivers/net/wireless/bcmdhd/include/epivers.h | 8 ++-- drivers/net/wireless/bcmdhd/wl_android.c | 4 +- drivers/net/wireless/bcmdhd/wl_cfg80211.c | 53 ++++++++++++------------ drivers/net/wireless/bcmdhd/wl_cfg80211.h | 4 +- drivers/net/wireless/bcmdhd/wl_iw.h | 1 - 13 files changed, 99 insertions(+), 57 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/bcmdhd/bcmsdh_sdmmc_linux.c b/drivers/net/wireless/bcmdhd/bcmsdh_sdmmc_linux.c index 5e28615fc5f5..1fdb7c90c84e 100644 --- a/drivers/net/wireless/bcmdhd/bcmsdh_sdmmc_linux.c +++ b/drivers/net/wireless/bcmdhd/bcmsdh_sdmmc_linux.c @@ -58,6 +58,9 @@ #if !defined(SDIO_DEVICE_ID_BROADCOM_4334) #define SDIO_DEVICE_ID_BROADCOM_4334 0x4334 #endif /* !defined(SDIO_DEVICE_ID_BROADCOM_4334) */ +#if !defined(SDIO_DEVICE_ID_BROADCOM_4324) +#define SDIO_DEVICE_ID_BROADCOM_4324 0x4324 +#endif /* !defined(SDIO_DEVICE_ID_BROADCOM_4324) */ #if !defined(SDIO_DEVICE_ID_BROADCOM_43239) #define SDIO_DEVICE_ID_BROADCOM_43239 43239 #endif /* !defined(SDIO_DEVICE_ID_BROADCOM_43239) */ @@ -160,6 +163,7 @@ static const struct sdio_device_id bcmsdh_sdmmc_ids[] = { { SDIO_DEVICE(SDIO_VENDOR_ID_BROADCOM, SDIO_DEVICE_ID_BROADCOM_4319) }, { SDIO_DEVICE(SDIO_VENDOR_ID_BROADCOM, SDIO_DEVICE_ID_BROADCOM_4330) }, { SDIO_DEVICE(SDIO_VENDOR_ID_BROADCOM, SDIO_DEVICE_ID_BROADCOM_4334) }, + { SDIO_DEVICE(SDIO_VENDOR_ID_BROADCOM, SDIO_DEVICE_ID_BROADCOM_4324) }, { SDIO_DEVICE(SDIO_VENDOR_ID_BROADCOM, SDIO_DEVICE_ID_BROADCOM_43239) }, { SDIO_DEVICE_CLASS(SDIO_CLASS_NONE) }, { /* end: all zeroes */ }, diff --git a/drivers/net/wireless/bcmdhd/dhd.h b/drivers/net/wireless/bcmdhd/dhd.h index db5822bbb6bf..d1648b7d99cd 100644 --- a/drivers/net/wireless/bcmdhd/dhd.h +++ b/drivers/net/wireless/bcmdhd/dhd.h @@ -24,7 +24,7 @@ * software in any way with any other Broadcom software provided under a license * other than the GPL, without Broadcom's express prior written consent. * - * $Id: dhd.h 323282 2012-03-23 19:41:57Z $ + * $Id: dhd.h 325862 2012-04-04 22:59:48Z $ */ @@ -82,6 +82,8 @@ enum dhd_bus_state { #define P2P_GC_ENABLED 0x0020 #define CONCURENT_MASK 0x00F0 +#define MANUFACTRING_FW "WLTEST" + /* max sequential rxcntl timeouts to set HANG event */ #define MAX_CNTL_TIMEOUT 2 @@ -120,7 +122,6 @@ typedef enum { DHD_IF_DELETING } dhd_if_state_t; - #if defined(CONFIG_DHD_USE_STATIC_BUF) uint8* dhd_os_prealloc(void *osh, int section, uint size); @@ -322,7 +323,6 @@ inline static void MUTEX_UNLOCK_SOFTAP_SET(dhd_pub_t * dhdp) #define DHD_OS_WAKE_LOCK_TIMEOUT(pub) dhd_os_wake_lock_timeout(pub) #define DHD_OS_WAKE_LOCK_RX_TIMEOUT_ENABLE(pub, val) dhd_os_wake_lock_rx_timeout_enable(pub, val) #define DHD_OS_WAKE_LOCK_CTRL_TIMEOUT_ENABLE(pub, val) dhd_os_wake_lock_ctrl_timeout_enable(pub, val) - #define DHD_PACKET_TIMEOUT_MS 1000 #define DHD_EVENT_TIMEOUT_MS 1500 diff --git a/drivers/net/wireless/bcmdhd/dhd_cdc.c b/drivers/net/wireless/bcmdhd/dhd_cdc.c index d01853c71a2e..f16d81c9e198 100644 --- a/drivers/net/wireless/bcmdhd/dhd_cdc.c +++ b/drivers/net/wireless/bcmdhd/dhd_cdc.c @@ -21,7 +21,7 @@ * software in any way with any other Broadcom software provided under a license * other than the GPL, without Broadcom's express prior written consent. * - * $Id: dhd_cdc.c 303389 2011-12-16 09:30:48Z $ + * $Id: dhd_cdc.c 324280 2012-03-28 19:01:17Z $ * * BDC is like CDC, except it includes a header for data packets to convey * packet priority over the bus, and flags (e.g. to indicate checksum status diff --git a/drivers/net/wireless/bcmdhd/dhd_linux.c b/drivers/net/wireless/bcmdhd/dhd_linux.c index 6cd0d7002c19..387d43dd858d 100644 --- a/drivers/net/wireless/bcmdhd/dhd_linux.c +++ b/drivers/net/wireless/bcmdhd/dhd_linux.c @@ -22,7 +22,7 @@ * software in any way with any other Broadcom software provided under a license * other than the GPL, without Broadcom's express prior written consent. * - * $Id: dhd_linux.c 319136 2012-03-07 03:10:36Z $ + * $Id: dhd_linux.c 325862 2012-04-04 22:59:48Z $ */ #include @@ -130,9 +130,9 @@ DECLARE_WAIT_QUEUE_HEAD(dhd_dpc_wait); #if defined(OOB_INTR_ONLY) extern void dhd_enable_oob_intr(struct dhd_bus *bus, bool enable); #endif /* defined(OOB_INTR_ONLY) */ - +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) static void dhd_hang_process(struct work_struct *work); - +#endif #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0)) MODULE_LICENSE("GPL v2"); #endif /* LinuxVer */ @@ -251,7 +251,9 @@ typedef struct dhd_info { bool dhd_tasklet_create; #endif /* DHDTHREAD */ tsk_ctl_t thr_sysioc_ctl; +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) struct work_struct work_hang; +#endif /* Wakelocks */ #if defined(CONFIG_HAS_WAKELOCK) && (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) @@ -2755,9 +2757,9 @@ dhd_attach(osl_t *osh, struct dhd_bus *bus, uint bus_hdrlen, void *dev) dhd->thr_sysioc_ctl.thr_pid = -1; } dhd_state |= DHD_ATTACH_STATE_THREADS_CREATED; - +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) INIT_WORK(&dhd->work_hang, dhd_hang_process); - +#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) */ /* * Save the dhd_info into the priv */ @@ -3037,7 +3039,7 @@ dhd_preinit_ioctls(dhd_pub_t *dhd) } #endif /* SET_RANDOM_MAC_SOFTAP */ - DHD_ERROR(("Firmware = %s\n", fw_path)); + DHD_TRACE(("Firmware = %s\n", fw_path)); #if !defined(AP) && defined(WLP2P) /* Check if firmware with WFD support used */ if ((!op_mode && strstr(fw_path, "_p2p") != NULL) @@ -3059,13 +3061,14 @@ dhd_preinit_ioctls(dhd_pub_t *dhd) #if !defined(AP) && defined(WL_CFG80211) /* Check if firmware with HostAPD support used */ if ((!op_mode && strstr(fw_path, "_apsta") != NULL) || (op_mode == HOSTAPD_MASK)) { + /* Disable A-band for HostAPD */ uint band = WLC_BAND_2G; - if ((ret = dhd_wl_ioctl_cmd(dhd, WLC_SET_BAND, (char *)&band, sizeof(band), TRUE, 0)) < 0) { DHD_ERROR(("%s:set band failed error (%d)\n", __FUNCTION__, ret)); } + /* Turn off wme if we are having only g ONLY firmware */ bcm_mkiovar("nmode", 0, 0, buf, sizeof(buf)); if ((ret = dhd_wl_ioctl_cmd(dhd, WLC_GET_VAR, buf, sizeof(buf), FALSE, 0)) < 0) { @@ -3133,7 +3136,7 @@ dhd_preinit_ioctls(dhd_pub_t *dhd) bcm_mkiovar("bus:txglomalign", (char *)&dongle_align, 4, iovbuf, sizeof(iovbuf)); dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, sizeof(iovbuf), TRUE, 0); - /* disable glom option per default */ + /* disable glom option for some chips */ chipID = (uint16)dhd_bus_chip_id(dhd); if ((chipID == BCM4330_CHIP_ID) || (chipID == BCM4329_CHIP_ID)) { DHD_INFO(("%s disable glom for chipID=0x%X\n", __FUNCTION__, chipID)); @@ -3285,8 +3288,15 @@ dhd_preinit_ioctls(dhd_pub_t *dhd) bcmstrtok(&ptr, "\n", 0); /* Print fw version info */ DHD_ERROR(("Firmware version = %s\n", buf)); + DHD_BLOG(buf, strlen(buf) + 1); DHD_BLOG(dhd_version, strlen(dhd_version) + 1); + + /* Check and adjust IOCTL response timeout for Manufactring firmware */ + if (strstr(buf, MANUFACTRING_FW) != NULL) { + dhd_os_set_ioctl_resp_timeout(IOCTL_RESP_TIMEOUT * 10); + DHD_ERROR(("%s : adjust IOCTL response time for Manufactring Firmware\n", __FUNCTION__)); + } } done: @@ -3640,7 +3650,9 @@ void dhd_detach(dhd_pub_t *dhdp) } #endif /* defined(CONFIG_HAS_EARLYSUSPEND) */ +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) cancel_work_sync(&dhd->work_hang); +#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) */ #if defined(CONFIG_BCMDHD_WEXT) if (dhd->dhd_state & DHD_ATTACH_STATE_WL_ATTACH) { @@ -4453,6 +4465,7 @@ dhd_dev_get_pno_status(struct net_device *dev) #endif /* PNO_SUPPORT */ +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) static void dhd_hang_process(struct work_struct *work) { dhd_info_t *dhd; @@ -4474,7 +4487,6 @@ static void dhd_hang_process(struct work_struct *work) } } -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) int net_os_send_hang_message(struct net_device *dev) { dhd_info_t *dhd = *(dhd_info_t **)netdev_priv(dev); diff --git a/drivers/net/wireless/bcmdhd/dhd_sdio.c b/drivers/net/wireless/bcmdhd/dhd_sdio.c index e4fd2edef8fa..3086bb3cb68c 100644 --- a/drivers/net/wireless/bcmdhd/dhd_sdio.c +++ b/drivers/net/wireless/bcmdhd/dhd_sdio.c @@ -21,7 +21,7 @@ * software in any way with any other Broadcom software provided under a license * other than the GPL, without Broadcom's express prior written consent. * - * $Id: dhd_sdio.c 324417 2012-03-29 03:15:15Z $ + * $Id: dhd_sdio.c 325395 2012-04-03 03:57:43Z $ */ #include @@ -754,8 +754,7 @@ dhdsdio_clkctl(dhd_bus_t *bus, uint target, bool pendok) uint oldstate = bus->clkstate; #endif /* DHD_DEBUG */ - DHD_TRACE(("%s: Enter bus->clkstate %u target %u\n", __FUNCTION__, - bus->clkstate, target)); + DHD_TRACE(("%s: Enter\n", __FUNCTION__)); /* Early exit if we're already there */ if (bus->clkstate == target) { @@ -1482,8 +1481,9 @@ dhd_bus_rxctl(struct dhd_bus *bus, uchar *msg, uint msglen) dhd_os_sdunlock(bus->dhd); #endif /* DHD_DEBUG */ } else if (pending == TRUE) { - DHD_CTL(("%s: canceled\n", __FUNCTION__)); - return -ERESTARTSYS; + /* possibly fw hangs so never responsed back */ + DHD_ERROR(("%s: pending or timeout \n", __FUNCTION__)); + return -ETIMEDOUT; } else { DHD_CTL(("%s: resumed for unknown reason?\n", __FUNCTION__)); #ifdef DHD_DEBUG @@ -4596,13 +4596,29 @@ clkwait: bcmsdh_intr_enable(sdh); } +#if defined(OOB_INTR_ONLY) && !defined(HW_OOB) + /* In case of SW-OOB(using edge trigger), + * Check interrupt status in the dongle again after enable irq on the host. + * and rechedule dpc if interrupt is pended in the dongle. + * There is a chance to miss OOB interrupt while irq is disabled on the host. + * No need to do this with HW-OOB(level trigger) + */ + R_SDREG(newstatus, ®s->intstatus, retries); + if (bcmsdh_regfail(bus->sdh)) + newstatus = 0; + if (newstatus & bus->hostintmask) { + bus->ipend = TRUE; + resched = TRUE; + } +#endif /* defined(OOB_INTR_ONLY) && !defined(HW_OOB) */ + if (TXCTLOK(bus) && bus->ctrl_frame_stat && (bus->clkstate == CLK_AVAIL)) { int ret, i; uint8* frame_seq = bus->ctrl_frame_buf + SDPCM_FRAMETAG_LEN; if (((bus->sih->chip == BCM4329_CHIP_ID) || /* limit to 4329 & 4330 for now */ (bus->sih->chip == BCM4330_CHIP_ID)) && (*frame_seq != bus->tx_seq)) { - DHD_ERROR(("%s IOCTL frame seq lag detected!" + DHD_INFO(("%s IOCTL frame seq lag detected!" " frm_seq:%d != bus->tx_seq:%d, corrected\n", __FUNCTION__, *frame_seq, bus->tx_seq)); *frame_seq = bus->tx_seq; @@ -6189,6 +6205,7 @@ dhd_bcmsdh_send_buf(dhd_bus_t *bus, uint32 addr, uint fn, uint flags, uint8 *buf uint dhd_bus_chip(struct dhd_bus *bus) { + ASSERT(bus); ASSERT(bus->sih != NULL); return bus->sih->chip; } @@ -6196,6 +6213,7 @@ dhd_bus_chip(struct dhd_bus *bus) void * dhd_bus_pub(struct dhd_bus *bus) { + ASSERT(bus); return bus->dhd; } @@ -6242,7 +6260,6 @@ dhd_bus_devreset(dhd_pub_t *dhdp, uint8 flag) bus->dhd->dongle_reset = TRUE; bus->dhd->up = FALSE; dhd_os_sdunlock(dhdp); - DHD_TRACE(("%s: WLAN OFF DONE\n", __FUNCTION__)); /* App can now remove power from device */ } else diff --git a/drivers/net/wireless/bcmdhd/include/bcmdevs.h b/drivers/net/wireless/bcmdhd/include/bcmdevs.h index ee01d8b45675..287f1c65fc9a 100644 --- a/drivers/net/wireless/bcmdhd/include/bcmdevs.h +++ b/drivers/net/wireless/bcmdhd/include/bcmdevs.h @@ -63,6 +63,7 @@ #define BCM_DNGL_BL_PID_43239 0xbd1b #define BCM_DNGL_BDC_PID 0x0bdc #define BCM_DNGL_JTAG_PID 0x4a44 +#define BCM_DNGL_BL_PID_4324 0xbd1c #define BCM_HWUSB_PID_43239 43239 diff --git a/drivers/net/wireless/bcmdhd/include/bcmsdstd.h b/drivers/net/wireless/bcmdhd/include/bcmsdstd.h index c14444c57d36..c7382540b84f 100644 --- a/drivers/net/wireless/bcmdhd/include/bcmsdstd.h +++ b/drivers/net/wireless/bcmdhd/include/bcmsdstd.h @@ -21,7 +21,7 @@ * software in any way with any other Broadcom software provided under a license * other than the GPL, without Broadcom's express prior written consent. * - * $Id: bcmsdstd.h 281604 2011-09-02 18:58:49Z $ + * $Id: bcmsdstd.h 324819 2012-03-30 12:15:19Z $ */ #ifndef _BCM_SD_STD_H #define _BCM_SD_STD_H @@ -180,6 +180,9 @@ struct sdioh_info { #define DATA_TRANSFER_IDLE 0 #define DATA_TRANSFER_ONGOING 1 +#define CHECK_TUNING_PRE_DATA 1 +#define CHECK_TUNING_POST_DATA 2 + /************************************************************ * Internal interfaces: per-port references into bcmsdstd.c @@ -227,10 +230,12 @@ extern int sdstd_waitbits(sdioh_info_t *sd, uint16 norm, uint16 err, bool yield, extern void sdstd_3_enable_retuning_int(sdioh_info_t *sd); extern void sdstd_3_disable_retuning_int(sdioh_info_t *sd); extern bool sdstd_3_is_retuning_int_set(sdioh_info_t *sd); +extern void sdstd_3_check_and_do_tuning(sdioh_info_t *sd, int tuning_param); extern bool sdstd_3_check_and_set_retuning(sdioh_info_t *sd); extern int sdstd_3_get_tune_state(sdioh_info_t *sd); extern int sdstd_3_get_data_state(sdioh_info_t *sd); extern void sdstd_3_set_tune_state(sdioh_info_t *sd, int state); +extern void sdstd_3_set_data_state(sdioh_info_t *sd, int state); extern uint8 sdstd_3_get_tuning_exp(sdioh_info_t *sd); extern uint32 sdstd_3_get_uhsi_clkmode(sdioh_info_t *sd); extern int sdstd_3_clk_tuning(sdioh_info_t *sd, uint32 sd3ClkMode); diff --git a/drivers/net/wireless/bcmdhd/include/dhdioctl.h b/drivers/net/wireless/bcmdhd/include/dhdioctl.h index 0312d2206013..175ff8545a0c 100644 --- a/drivers/net/wireless/bcmdhd/include/dhdioctl.h +++ b/drivers/net/wireless/bcmdhd/include/dhdioctl.h @@ -25,7 +25,7 @@ * software in any way with any other Broadcom software provided under a license * other than the GPL, without Broadcom's express prior written consent. * - * $Id: dhdioctl.h 307573 2012-01-12 00:04:39Z $ + * $Id: dhdioctl.h 323572 2012-03-26 06:28:14Z $ */ #ifndef _dhdioctl_h_ @@ -87,7 +87,8 @@ enum { #define DHD_BTA_VAL 0x1000 #define DHD_ISCAN_VAL 0x2000 #define DHD_ARPOE_VAL 0x4000 -#define DHD_WL_VAL 0x8000 +#define DHD_REORDER_VAL 0x8000 +#define DHD_WL_VAL 0x10000 #ifdef SDTEST /* For pktgen iovar */ diff --git a/drivers/net/wireless/bcmdhd/include/epivers.h b/drivers/net/wireless/bcmdhd/include/epivers.h index 9fd097ec8b98..b3560bd9203f 100644 --- a/drivers/net/wireless/bcmdhd/include/epivers.h +++ b/drivers/net/wireless/bcmdhd/include/epivers.h @@ -32,17 +32,17 @@ #define EPI_RC_NUMBER 195 -#define EPI_INCREMENTAL_NUMBER 46 +#define EPI_INCREMENTAL_NUMBER 53 #define EPI_BUILD_NUMBER 0 -#define EPI_VERSION 5, 90, 195, 46 +#define EPI_VERSION 5, 90, 195, 53 -#define EPI_VERSION_NUM 0x055ac32e +#define EPI_VERSION_NUM 0x055ac335 #define EPI_VERSION_DEV 5.90.195 -#define EPI_VERSION_STR "5.90.195.46" +#define EPI_VERSION_STR "5.90.195.53" #endif diff --git a/drivers/net/wireless/bcmdhd/wl_android.c b/drivers/net/wireless/bcmdhd/wl_android.c index b98fe1d8f784..631c12bda8b6 100644 --- a/drivers/net/wireless/bcmdhd/wl_android.c +++ b/drivers/net/wireless/bcmdhd/wl_android.c @@ -619,7 +619,7 @@ int wl_android_init(void) { int ret = 0; - dhd_msg_level = DHD_ERROR_VAL; + dhd_msg_level |= DHD_ERROR_VAL; #ifdef ENABLE_INSMOD_NO_FW_LOAD dhd_download_fw_on_driverload = FALSE; #endif /* ENABLE_INSMOD_NO_FW_LOAD */ @@ -690,7 +690,7 @@ void wl_android_wifictrl_func_del(void) } } -void *wl_android_prealloc(int section, unsigned long size) +void* wl_android_prealloc(int section, unsigned long size) { void *alloc_ptr = NULL; if (wifi_control_data && wifi_control_data->mem_prealloc) { diff --git a/drivers/net/wireless/bcmdhd/wl_cfg80211.c b/drivers/net/wireless/bcmdhd/wl_cfg80211.c index 178a23103e63..8009e03fdcf3 100644 --- a/drivers/net/wireless/bcmdhd/wl_cfg80211.c +++ b/drivers/net/wireless/bcmdhd/wl_cfg80211.c @@ -3352,6 +3352,7 @@ wl_cfg80211_mgmt_tx(struct wiphy *wiphy, struct net_device *ndev, wifi_p2p_action_frame_t *p2p_act_frm = NULL; wifi_p2psd_gas_pub_act_frame_t *sd_act_frm = NULL; s8 eabuf[ETHER_ADDR_STR_LEN]; + int retry_cnt = 0; WL_DBG(("Enter \n")); @@ -3496,9 +3497,9 @@ wl_cfg80211_mgmt_tx(struct wiphy *wiphy, struct net_device *ndev, } wl_cfgp2p_print_actframe(true, action_frame->data, action_frame->len); - /* - * To make sure to send successfully action frame, we have to turn off mpc - */ + /* + * To make sure to send successfully action frame, we have to turn off mpc + */ if (act_frm && ((act_frm->subtype == P2P_PAF_GON_REQ) || (act_frm->subtype == P2P_PAF_GON_RSP) || @@ -3506,6 +3507,9 @@ wl_cfg80211_mgmt_tx(struct wiphy *wiphy, struct net_device *ndev, (act_frm->subtype == P2P_PAF_PROVDIS_REQ))) { wldev_iovar_setint(dev, "mpc", 0); } + if (act_frm->subtype == P2P_PAF_GON_RSP) + retry_cnt = 1; + else retry_cnt = WL_ACT_FRAME_RETRY; if (act_frm && act_frm->subtype == P2P_PAF_DEVDIS_REQ) { af_params->dwell_time = WL_LONG_DWELL_TIME; @@ -3530,23 +3534,12 @@ wl_cfg80211_mgmt_tx(struct wiphy *wiphy, struct net_device *ndev, } else { ack = (wl_cfgp2p_tx_action_frame(wl, dev, af_params, bssidx)) ? false : true; if (!ack) { - if (wl_to_p2p_bss_saved_ie(wl, P2PAPI_BSSCFG_DEVICE).p2p_probe_req_ie_len) { - /* if the NO ACK occurs, the peer device will be on - * listen channel of the peer - * So, we have to find the peer and send action frame on - * that channel. - */ - ack = wl_cfg80211_send_at_common_channel(wl, dev, af_params); - } else { - for (retry = 0; retry < WL_CHANNEL_SYNC_RETRY; retry++) { + for (retry = 1; retry < WL_CHANNEL_SYNC_RETRY; retry++) { ack = (wl_cfgp2p_tx_action_frame(wl, dev, af_params, bssidx)) ? false : true; if (ack) break; } - - } - } } @@ -3619,7 +3612,7 @@ wl_cfg80211_set_channel(struct wiphy *wiphy, struct net_device *dev, __FUNCTION__, channel)); wl->hostapd_chan = channel; if (channel == 14) - return err; + return err; /* hostapd requested ch auto-select, will be done later */ } WL_DBG(("netdev_ifidx(%d), chan_type(%d) target channel(%d) \n", @@ -4251,6 +4244,7 @@ int wl_cfg80211_sched_scan_start(struct wiphy *wiphy, request->n_ssids, pno_time, pno_repeat, pno_freq_expo_max)); #if defined(WL_ENABLE_P2P_IF) + /* While GO is operational, PNO is not supported */ if (dhd_cfg80211_get_opmode(wl) & P2P_GO_ENABLED) { WL_DBG(("PNO not enabled! op_mode: P2P GO")); return -1; @@ -6676,7 +6670,7 @@ s32 wl_update_wiphybands(struct wl_priv *wl) err = wldev_ioctl(wl_to_prmry_ndev(wl), WLC_GET_BANDLIST, bandlist, sizeof(bandlist), false); if (unlikely(err)) { - WL_ERR(("error (%d)\n", err)); + WL_ERR(("error read bandlist (%d)\n", err)); return err; } wiphy = wl_to_wiphy(wl); @@ -6686,12 +6680,14 @@ s32 wl_update_wiphybands(struct wl_priv *wl) err = wldev_iovar_getint(wl_to_prmry_ndev(wl), "nmode", &nmode); if (unlikely(err)) { - WL_ERR(("error (%d)\n", err)); + WL_ERR(("error reading nmode (%d)\n", err)); } - - err = wldev_iovar_getint(wl_to_prmry_ndev(wl), "mimo_bw_cap", &bw_40); - if (unlikely(err)) { - WL_ERR(("error (%d)\n", err)); + else { + /* For nmodeonly check bw cap */ + err = wldev_iovar_getint(wl_to_prmry_ndev(wl), "mimo_bw_cap", &bw_40); + if (unlikely(err)) { + WL_ERR(("error get mimo_bw_cap (%d)\n", err)); + } } for (i = 1; i <= nband && i < sizeof(bandlist); i++) { @@ -6705,7 +6701,7 @@ s32 wl_update_wiphybands(struct wl_priv *wl) &__wl_band_2ghz; index = IEEE80211_BAND_2GHZ; } - +#if defined WL_ENABLE_P2P_IF if ((index >= 0) && nmode) { wiphy->bands[index]->ht_cap.cap = IEEE80211_HT_CAP_DSSSCCK40 @@ -6714,6 +6710,7 @@ s32 wl_update_wiphybands(struct wl_priv *wl) wiphy->bands[index]->ht_cap.ampdu_factor = IEEE80211_HT_MAX_AMPDU_16K; wiphy->bands[index]->ht_cap.ampdu_density = IEEE80211_HT_MPDU_DENSITY_16; } +#endif } wiphy_apply_custom_regulatory(wiphy, &brcm_regdom); @@ -6755,6 +6752,7 @@ static s32 __wl_cfg80211_down(struct wl_priv *wl) struct net_device *ndev = wl_to_prmry_ndev(wl); #ifdef WL_ENABLE_P2P_IF struct wiphy *wiphy = wl_to_prmry_ndev(wl)->ieee80211_ptr->wiphy; + struct net_device *p2p_net = wl->p2p_net; #endif WL_DBG(("In\n")); @@ -6786,7 +6784,11 @@ static s32 __wl_cfg80211_down(struct wl_priv *wl) wiphy->interface_modes = (wiphy->interface_modes) & (~(BIT(NL80211_IFTYPE_P2P_CLIENT)| BIT(NL80211_IFTYPE_P2P_GO))); -#endif + if ((p2p_net) && (p2p_net->flags & IFF_UP)) { + /* p2p0 interface is still UP. Bring it down */ + p2p_net->flags &= ~IFF_UP; + } +#endif /* WL_ENABLE_P2P_IF */ spin_unlock_irqrestore(&wl->cfgdrv_lock, flags); DNGL_FUNC(dhd_cfg80211_down, (wl)); @@ -7035,8 +7037,7 @@ static void wl_init_eq_lock(struct wl_priv *wl) static void wl_delay(u32 ms) { - if (ms < 1000 / HZ) { - cond_resched(); + if (in_atomic() || ms < 1000 / HZ) { mdelay(ms); } else { msleep(ms); diff --git a/drivers/net/wireless/bcmdhd/wl_cfg80211.h b/drivers/net/wireless/bcmdhd/wl_cfg80211.h index 4cea796fa51f..818eff594115 100644 --- a/drivers/net/wireless/bcmdhd/wl_cfg80211.h +++ b/drivers/net/wireless/bcmdhd/wl_cfg80211.h @@ -131,7 +131,9 @@ do { \ #define IFACE_MAX_CNT 2 #define WL_SCAN_TIMER_INTERVAL_MS 8000 /* Scan timeout */ -#define WL_CHANNEL_SYNC_RETRY 5 +#define WL_CHANNEL_SYNC_RETRY 1 +#define WL_ACT_FRAME_RETRY 5 + #define WL_INVALID -1 /* driver status */ diff --git a/drivers/net/wireless/bcmdhd/wl_iw.h b/drivers/net/wireless/bcmdhd/wl_iw.h index 20fa24909f87..9cdb53dfef8c 100644 --- a/drivers/net/wireless/bcmdhd/wl_iw.h +++ b/drivers/net/wireless/bcmdhd/wl_iw.h @@ -209,7 +209,6 @@ extern int net_os_wake_lock_ctrl_timeout_enable(struct net_device *dev, int val extern int net_os_set_suspend_disable(struct net_device *dev, int val); extern int net_os_set_suspend(struct net_device *dev, int val, int force); extern int net_os_set_dtim_skip(struct net_device *dev, int val); -extern int net_os_send_hang_message(struct net_device *dev); extern void get_customized_country_code(char *country_iso_code, wl_country_t *cspec); #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27) -- cgit v1.2.3 From 8e520c423374a7d2fe383019e69d59a99c9f47ed Mon Sep 17 00:00:00 2001 From: Dmitry Shmidt Date: Tue, 10 Apr 2012 15:44:41 -0700 Subject: net: wireless: bcmdhd: Fix improper band handling Signed-off-by: Dmitry Shmidt --- drivers/net/wireless/bcmdhd/wl_cfg80211.c | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/bcmdhd/wl_cfg80211.c b/drivers/net/wireless/bcmdhd/wl_cfg80211.c index 8009e03fdcf3..19d675a2b8db 100644 --- a/drivers/net/wireless/bcmdhd/wl_cfg80211.c +++ b/drivers/net/wireless/bcmdhd/wl_cfg80211.c @@ -4509,6 +4509,11 @@ static s32 wl_inform_single_bss(struct wl_priv *wl, struct wl_bss_info *bi) band = wiphy->bands[IEEE80211_BAND_2GHZ]; else band = wiphy->bands[IEEE80211_BAND_5GHZ]; + if (!band) { + WL_ERR(("No valid band")); + kfree(notif_bss_info); + return -EINVAL; + } notif_bss_info->rssi = dtoh16(bi->RSSI); memcpy(mgmt->bssid, &bi->BSSID, ETHER_ADDR_LEN); mgmt_type = wl->active_scan ? @@ -4713,7 +4718,10 @@ wl_notify_connect_status_ap(struct wl_priv *wl, struct net_device *ndev, band = wiphy->bands[IEEE80211_BAND_2GHZ]; else band = wiphy->bands[IEEE80211_BAND_5GHZ]; - + if (!band) { + WL_ERR(("No valid band")); + return -EINVAL; + } #if LINUX_VERSION_CODE == KERNEL_VERSION(2, 6, 38) && !defined(WL_COMPAT_WIRELESS) freq = ieee80211_channel_to_frequency(channel); #else @@ -5296,7 +5304,10 @@ wl_notify_rx_mgmt_frame(struct wl_priv *wl, struct net_device *ndev, band = wiphy->bands[IEEE80211_BAND_2GHZ]; else band = wiphy->bands[IEEE80211_BAND_5GHZ]; - + if (!band) { + WL_ERR(("No valid band")); + return -EINVAL; + } #if LINUX_VERSION_CODE == KERNEL_VERSION(2, 6, 38) && !defined(WL_COMPAT_WIRELESS) freq = ieee80211_channel_to_frequency(channel); #else @@ -6675,8 +6686,8 @@ s32 wl_update_wiphybands(struct wl_priv *wl) } wiphy = wl_to_wiphy(wl); nband = bandlist[0]; + wiphy->bands[IEEE80211_BAND_2GHZ] = &__wl_band_2ghz; wiphy->bands[IEEE80211_BAND_5GHZ] = NULL; - wiphy->bands[IEEE80211_BAND_2GHZ] = NULL; err = wldev_iovar_getint(wl_to_prmry_ndev(wl), "nmode", &nmode); if (unlikely(err)) { @@ -6690,7 +6701,7 @@ s32 wl_update_wiphybands(struct wl_priv *wl) } } - for (i = 1; i <= nband && i < sizeof(bandlist); i++) { + for (i = 1; i <= nband && i < sizeof(bandlist)/sizeof(u32); i++) { index = -1; if (bandlist[i] == WLC_BAND_5G) { wiphy->bands[IEEE80211_BAND_5GHZ] = -- cgit v1.2.3 From 0e3baaafacb4c80df9ec4ba6278ad2ba4b6cf45d Mon Sep 17 00:00:00 2001 From: Dmitry Shmidt Date: Thu, 12 Apr 2012 13:48:46 -0700 Subject: net: wireless: bcmdhd: Allow 80211_HT capability Signed-off-by: Dmitry Shmidt --- drivers/net/wireless/bcmdhd/wl_cfg80211.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/bcmdhd/wl_cfg80211.c b/drivers/net/wireless/bcmdhd/wl_cfg80211.c index 19d675a2b8db..f717f8f1a07a 100644 --- a/drivers/net/wireless/bcmdhd/wl_cfg80211.c +++ b/drivers/net/wireless/bcmdhd/wl_cfg80211.c @@ -6712,7 +6712,6 @@ s32 wl_update_wiphybands(struct wl_priv *wl) &__wl_band_2ghz; index = IEEE80211_BAND_2GHZ; } -#if defined WL_ENABLE_P2P_IF if ((index >= 0) && nmode) { wiphy->bands[index]->ht_cap.cap = IEEE80211_HT_CAP_DSSSCCK40 @@ -6721,7 +6720,6 @@ s32 wl_update_wiphybands(struct wl_priv *wl) wiphy->bands[index]->ht_cap.ampdu_factor = IEEE80211_HT_MAX_AMPDU_16K; wiphy->bands[index]->ht_cap.ampdu_density = IEEE80211_HT_MPDU_DENSITY_16; } -#endif } wiphy_apply_custom_regulatory(wiphy, &brcm_regdom); -- cgit v1.2.3 From 9b5e33e67e8dd7cd664003c5a6bd805104ed82b7 Mon Sep 17 00:00:00 2001 From: Dmitry Shmidt Date: Mon, 30 Apr 2012 16:34:01 -0700 Subject: net: wireless: bcmdhd: Turn OFF wlan power if interface UP fails Signed-off-by: Dmitry Shmidt --- drivers/net/wireless/bcmdhd/dhd_linux.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers/net') diff --git a/drivers/net/wireless/bcmdhd/dhd_linux.c b/drivers/net/wireless/bcmdhd/dhd_linux.c index 387d43dd858d..98738970afad 100644 --- a/drivers/net/wireless/bcmdhd/dhd_linux.c +++ b/drivers/net/wireless/bcmdhd/dhd_linux.c @@ -2449,6 +2449,9 @@ dhd_open(struct net_device *net) OLD_MOD_INC_USE_COUNT; exit: + if (ret) + dhd_stop(net); + DHD_OS_WAKE_UNLOCK(&dhd->pub); return ret; } -- cgit v1.2.3 From 020878af9bb7aa0a7e71b41c4aed4b184e26bd29 Mon Sep 17 00:00:00 2001 From: Dmitry Shmidt Date: Tue, 1 May 2012 11:00:21 -0700 Subject: net: wireless: bcmdhd: Update to Version 5.90.195.61 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Deauth frame from p2p GO to client doesn't go from firmware if we do del_virtual_iface immediately. Putting a delay after sending deauth frame to allowed FW to send out deauth frame. - IF_DEL operation was timing out due to wrong status check. Fixed it and added few debug prints. - Sending Provision Discovery directly to GO instead of doing an internal scan. Also put the internal scan count to 3 to have better timings for GO-NEG. - Increase beacon timeout only for concurrent mode. For STA only operation, use the default beacon timeout value (4). - If scan abort is due to timeout, aborting the scan in FW is not required. Moreover, as this scan_timeout call is coming in timer interrupt context, all blocking calls such as fw scan abort will result in kernel panic : don’t call abort in Firmware. - Add p2p_cancel_listen routine. Fix p2p_listen_complete related kernel crash seen while turning off WiFi. Signed-off-by: Dmitry Shmidt --- drivers/net/wireless/bcmdhd/dhd.h | 10 ++- drivers/net/wireless/bcmdhd/dhd_cfg80211.c | 25 +++++++- drivers/net/wireless/bcmdhd/dhd_common.c | 8 ++- drivers/net/wireless/bcmdhd/dhd_linux.c | 6 +- drivers/net/wireless/bcmdhd/dhd_sdio.c | 5 +- drivers/net/wireless/bcmdhd/include/epivers.h | 8 +-- drivers/net/wireless/bcmdhd/wl_cfg80211.c | 91 ++++++++++++++++++--------- drivers/net/wireless/bcmdhd/wl_cfg80211.h | 5 +- drivers/net/wireless/bcmdhd/wl_cfgp2p.c | 49 ++++++++++++--- drivers/net/wireless/bcmdhd/wl_cfgp2p.h | 7 ++- 10 files changed, 154 insertions(+), 60 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/bcmdhd/dhd.h b/drivers/net/wireless/bcmdhd/dhd.h index d1648b7d99cd..3911f336b16f 100644 --- a/drivers/net/wireless/bcmdhd/dhd.h +++ b/drivers/net/wireless/bcmdhd/dhd.h @@ -24,11 +24,12 @@ * software in any way with any other Broadcom software provided under a license * other than the GPL, without Broadcom's express prior written consent. * - * $Id: dhd.h 325862 2012-04-04 22:59:48Z $ + * $Id: dhd.h 328934 2012-04-23 05:15:42Z $ */ - - +/**************** + * Common types * + */ #ifndef _dhd_h_ #define _dhd_h_ @@ -90,6 +91,9 @@ enum dhd_bus_state { #define DHD_SCAN_ACTIVE_TIME 40 /* ms : Embedded default Active setting from DHD Driver */ #define DHD_SCAN_PASSIVE_TIME 130 /* ms: Embedded default Passive setting from DHD Driver */ +#define DHD_BEACON_TIMEOUT_NORMAL 4 +#define DHD_BEACON_TIMEOUT_HIGH 10 + enum dhd_bus_wake_state { WAKE_LOCK_OFF, WAKE_LOCK_PRIV, diff --git a/drivers/net/wireless/bcmdhd/dhd_cfg80211.c b/drivers/net/wireless/bcmdhd/dhd_cfg80211.c index 2503f51ec574..183891df160a 100644 --- a/drivers/net/wireless/bcmdhd/dhd_cfg80211.c +++ b/drivers/net/wireless/bcmdhd/dhd_cfg80211.c @@ -41,7 +41,9 @@ static int dhd_dongle_up = FALSE; static s32 wl_dongle_up(struct net_device *ndev, u32 up); - +/** + * Function implementations + */ s32 dhd_cfg80211_init(struct wl_priv *wl) { @@ -70,13 +72,22 @@ s32 dhd_cfg80211_down(struct wl_priv *wl) s32 dhd_cfg80211_set_p2p_info(struct wl_priv *wl, int val) { dhd_pub_t *dhd = (dhd_pub_t *)(wl->pub); + int bcn_timeout = DHD_BEACON_TIMEOUT_HIGH; + char iovbuf[30]; + dhd->op_mode |= val; WL_ERR(("Set : op_mode=%d\n", dhd->op_mode)); #ifdef ARP_OFFLOAD_SUPPORT + /* IF P2P is enabled, disable arpoe */ dhd_arp_offload_set(dhd, 0); dhd_arp_offload_enable(dhd, false); -#endif +#endif /* ARP_OFFLOAD_SUPPORT */ + + /* Setup timeout if Beacons are lost and roam is off to report link down */ + bcm_mkiovar("bcn_timeout", (char *)&bcn_timeout, 4, iovbuf, sizeof(iovbuf)); + dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, sizeof(iovbuf), TRUE, 0); + return 0; } @@ -84,13 +95,21 @@ s32 dhd_cfg80211_set_p2p_info(struct wl_priv *wl, int val) s32 dhd_cfg80211_clean_p2p_info(struct wl_priv *wl) { dhd_pub_t *dhd = (dhd_pub_t *)(wl->pub); + int bcn_timeout = DHD_BEACON_TIMEOUT_NORMAL; + char iovbuf[30]; + dhd->op_mode &= ~CONCURENT_MASK; WL_ERR(("Clean : op_mode=%d\n", dhd->op_mode)); #ifdef ARP_OFFLOAD_SUPPORT + /* IF P2P is disabled, enable arpoe back for STA mode. */ dhd_arp_offload_set(dhd, dhd_arp_mode); dhd_arp_offload_enable(dhd, true); -#endif +#endif /* ARP_OFFLOAD_SUPPORT */ + + /* Setup timeout if Beacons are lost and roam is off to report link down */ + bcm_mkiovar("bcn_timeout", (char *)&bcn_timeout, 4, iovbuf, sizeof(iovbuf)); + dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, sizeof(iovbuf), TRUE, 0); return 0; } diff --git a/drivers/net/wireless/bcmdhd/dhd_common.c b/drivers/net/wireless/bcmdhd/dhd_common.c index 1e7a0679121d..d9810ace1cb4 100644 --- a/drivers/net/wireless/bcmdhd/dhd_common.c +++ b/drivers/net/wireless/bcmdhd/dhd_common.c @@ -21,7 +21,7 @@ * software in any way with any other Broadcom software provided under a license * other than the GPL, without Broadcom's express prior written consent. * - * $Id: dhd_common.c 319098 2012-03-07 01:05:20Z $ + * $Id: dhd_common.c 329682 2012-04-26 09:20:38Z $ */ #include #include @@ -1001,6 +1001,9 @@ wl_host_event(dhd_pub_t *dhd_pub, int *ifidx, void *pktdata, datalen = ntoh32_ua((void *)&event->datalen); evlen = datalen + sizeof(bcm_event_t); + DHD_TRACE(("RX: event_type:%d flags:%d status:%d reason:%d \n", + type, flags, status, reason)); + switch (type) { #ifdef PROP_TXSTATUS case WLC_E_FIFO_CREDIT_MAP: @@ -1728,6 +1731,7 @@ fail: /* * returns = TRUE if associated, FALSE if not associated + * third paramter retval can return error from error */ bool dhd_is_associated(dhd_pub_t *dhd, void *bss_buf, int *retval) { @@ -1896,7 +1900,7 @@ dhd_pno_enable(dhd_pub_t *dhd, int pfn_enabled) DHD_ERROR(("%s pno is NOT enable : called in assoc mode , ignore\n", __FUNCTION__)); return ret; } -#endif +#endif /* !WL_SCHED_SCAN */ /* Enable/disable PNO */ if ((ret = bcm_mkiovar("pfn", (char *)&pfn_enabled, 4, iovbuf, sizeof(iovbuf))) > 0) { diff --git a/drivers/net/wireless/bcmdhd/dhd_linux.c b/drivers/net/wireless/bcmdhd/dhd_linux.c index 98738970afad..320ce5975bf0 100644 --- a/drivers/net/wireless/bcmdhd/dhd_linux.c +++ b/drivers/net/wireless/bcmdhd/dhd_linux.c @@ -22,7 +22,7 @@ * software in any way with any other Broadcom software provided under a license * other than the GPL, without Broadcom's express prior written consent. * - * $Id: dhd_linux.c 325862 2012-04-04 22:59:48Z $ + * $Id: dhd_linux.c 329682 2012-04-26 09:20:38Z $ */ #include @@ -1473,6 +1473,7 @@ dhd_rx_frame(dhd_pub_t *dhdp, int ifidx, void *pktbuf, int numpkt, uint8 chan) */ ((athost_wl_status_info_t*)dhdp->wlfc_state)->stats.wlfc_header_only_pkt++; PKTFREE(dhdp->osh, pktbuf, TRUE); + DHD_TRACE(("RX: wlfc header \n")); continue; } #endif @@ -2964,7 +2965,8 @@ dhd_preinit_ioctls(dhd_pub_t *dhd) uint power_mode = PM_FAST; uint32 dongle_align = DHD_SDALIGN; uint32 glom = 0; - uint bcn_timeout = 10; + uint bcn_timeout = DHD_BEACON_TIMEOUT_NORMAL; + uint retry_max = 3; #if defined(ARP_OFFLOAD_SUPPORT) int arpoe = 1; diff --git a/drivers/net/wireless/bcmdhd/dhd_sdio.c b/drivers/net/wireless/bcmdhd/dhd_sdio.c index 3086bb3cb68c..954d8296fd6a 100644 --- a/drivers/net/wireless/bcmdhd/dhd_sdio.c +++ b/drivers/net/wireless/bcmdhd/dhd_sdio.c @@ -21,7 +21,7 @@ * software in any way with any other Broadcom software provided under a license * other than the GPL, without Broadcom's express prior written consent. * - * $Id: dhd_sdio.c 325395 2012-04-03 03:57:43Z $ + * $Id: dhd_sdio.c 326662 2012-04-10 06:38:08Z $ */ #include @@ -4616,8 +4616,7 @@ clkwait: int ret, i; uint8* frame_seq = bus->ctrl_frame_buf + SDPCM_FRAMETAG_LEN; - if (((bus->sih->chip == BCM4329_CHIP_ID) || /* limit to 4329 & 4330 for now */ - (bus->sih->chip == BCM4330_CHIP_ID)) && (*frame_seq != bus->tx_seq)) { + if (*frame_seq != bus->tx_seq) { DHD_INFO(("%s IOCTL frame seq lag detected!" " frm_seq:%d != bus->tx_seq:%d, corrected\n", __FUNCTION__, *frame_seq, bus->tx_seq)); diff --git a/drivers/net/wireless/bcmdhd/include/epivers.h b/drivers/net/wireless/bcmdhd/include/epivers.h index b3560bd9203f..3bff73e2a6bc 100644 --- a/drivers/net/wireless/bcmdhd/include/epivers.h +++ b/drivers/net/wireless/bcmdhd/include/epivers.h @@ -32,17 +32,17 @@ #define EPI_RC_NUMBER 195 -#define EPI_INCREMENTAL_NUMBER 53 +#define EPI_INCREMENTAL_NUMBER 61 #define EPI_BUILD_NUMBER 0 -#define EPI_VERSION 5, 90, 195, 53 +#define EPI_VERSION 5, 90, 195, 61 -#define EPI_VERSION_NUM 0x055ac335 +#define EPI_VERSION_NUM 0x055ac33d #define EPI_VERSION_DEV 5.90.195 -#define EPI_VERSION_STR "5.90.195.53" +#define EPI_VERSION_STR "5.90.195.61" #endif diff --git a/drivers/net/wireless/bcmdhd/wl_cfg80211.c b/drivers/net/wireless/bcmdhd/wl_cfg80211.c index f717f8f1a07a..98e498d785cd 100644 --- a/drivers/net/wireless/bcmdhd/wl_cfg80211.c +++ b/drivers/net/wireless/bcmdhd/wl_cfg80211.c @@ -100,7 +100,10 @@ static const struct ieee80211_regdomain brcm_regdom = { * we need cfg80211 to allow it (reg_flags = 0); so that * hostapd could request auto channel by sending down ch 14 */ - REG_RULE(2484-10, 2484+10, 20, 6, 20, 0), + REG_RULE(2484-10, 2484+10, 20, 6, 20, + NL80211_RRF_PASSIVE_SCAN | + NL80211_RRF_NO_IBSS | + NL80211_RRF_NO_OFDM), /* IEEE 802.11a, channel 36..64 */ REG_RULE(5150-10, 5350+10, 40, 6, 20, 0), /* IEEE 802.11a, channel 100..165 */ @@ -735,7 +738,7 @@ wl_cfg80211_add_virtual_iface(struct wiphy *wiphy, char *name, s32 mode = 0; #if defined(WL_ENABLE_P2P_IF) s32 dhd_mode = 0; -#endif +#endif /* (WL_ENABLE_P2P_IF) */ chanspec_t chspec; struct wl_priv *wl = wiphy_priv(wiphy); struct net_device *_ndev; @@ -807,7 +810,7 @@ wl_cfg80211_add_virtual_iface(struct wiphy *wiphy, char *name, return ERR_PTR(-EAGAIN); } } - if (!p2p_is_on(wl) && strstr(name, WL_P2P_INTERFACE_PREFIX)) { + if (wl->p2p && !wl->p2p->on && strstr(name, WL_P2P_INTERFACE_PREFIX)) { p2p_on(wl) = true; wl_cfgp2p_set_firm_p2p(wl); wl_cfgp2p_init_discovery(wl); @@ -819,7 +822,8 @@ wl_cfg80211_add_virtual_iface(struct wiphy *wiphy, char *name, memset(wl->p2p->vir_ifname, 0, IFNAMSIZ); strncpy(wl->p2p->vir_ifname, name, IFNAMSIZ - 1); - + wldev_iovar_setint(_ndev, "mpc", 0); + wl_notify_escan_complete(wl, _ndev, true, true); /* In concurrency case, STA may be already associated in a particular channel. * so retrieve the current channel of primary interface and then start the virtual * interface on that. @@ -874,8 +878,10 @@ wl_cfg80211_add_virtual_iface(struct wiphy *wiphy, char *name, else if (type == NL80211_IFTYPE_P2P_GO) dhd_mode = P2P_GO_ENABLED; DNGL_FUNC(dhd_cfg80211_set_p2p_info, (wl, dhd_mode)); -#endif - +#endif /* (WL_ENABLE_P2P_IF) */ + /* Start the P2P I/F with PM disabled. Enable PM from + * the framework + */ if ((type == NL80211_IFTYPE_P2P_CLIENT) || ( type == NL80211_IFTYPE_P2P_GO)) vwdev->ps = NL80211_PS_DISABLED; @@ -920,7 +926,7 @@ wl_cfg80211_del_virtual_iface(struct wiphy *wiphy, struct net_device *dev) if (wl->p2p_supported) { memcpy(p2p_mac.octet, wl->p2p->int_addr.octet, ETHER_ADDR_LEN); if (wl->p2p->vif_created) { - if (wl->scan_request) { + if (wl_get_drv_status(wl, SCANNING, dev)) { wl_notify_escan_complete(wl, dev, true, true); } wldev_iovar_setint(dev, "mpc", 1); @@ -948,7 +954,7 @@ wl_cfg80211_del_virtual_iface(struct wiphy *wiphy, struct net_device *dev) WL_DBG(("IFDEL operation done\n")); #if defined(WL_ENABLE_P2P_IF) DNGL_FUNC(dhd_cfg80211_clean_p2p_info, (wl)); -#endif +#endif /* (WL_ENABLE_P2P_IF)) */ } else { WL_ERR(("IFDEL didn't complete properly\n")); } @@ -972,7 +978,7 @@ wl_cfg80211_change_virtual_iface(struct wiphy *wiphy, struct net_device *ndev, chanspec_t chspec; struct wl_priv *wl = wiphy_priv(wiphy); - WL_DBG(("Enter \n")); + WL_DBG(("Enter type %d\n", type)); switch (type) { case NL80211_IFTYPE_MONITOR: case NL80211_IFTYPE_WDS: @@ -1003,8 +1009,10 @@ wl_cfg80211_change_virtual_iface(struct wiphy *wiphy, struct net_device *ndev, wl_set_mode_by_netdev(wl, ndev, mode); if (wl->p2p_supported && wl->p2p->vif_created) { WL_DBG(("p2p_vif_created (%d) p2p_on (%d)\n", wl->p2p->vif_created, - p2p_on(wl))); + p2p_on(wl))); wldev_iovar_setint(ndev, "mpc", 0); + wl_notify_escan_complete(wl, ndev, true, true); + /* In concurrency case, STA may be already associated in a particular * channel. so retrieve the current channel of primary interface and * then start the virtual interface on that. @@ -1121,6 +1129,7 @@ wl_cfg80211_ifdel_ops(struct net_device *ndev) WL_DBG(("index : %d\n", index)); } + /* Wake up any waiting thread */ wake_up_interruptible(&wl->netif_change_event); @@ -2007,7 +2016,11 @@ wl_set_set_cipher(struct net_device *dev, struct cfg80211_connect_params *sme) WL_DBG(("pval (%d) gval (%d)\n", pval, gval)); if (is_wps_conn(sme)) { - err = wldev_iovar_setint_bsscfg(dev, "wsec", 4, bssidx); + if (sme->privacy) + err = wldev_iovar_setint_bsscfg(dev, "wsec", 4, bssidx); + else + /* WPS-2.0 allowes no security */ + err = wldev_iovar_setint_bsscfg(dev, "wsec", 0, bssidx); } else { WL_DBG((" NO, is_wps_conn, Set pval | gval to WSEC")); err = wldev_iovar_setint_bsscfg(dev, "wsec", @@ -2847,7 +2860,6 @@ wl_cfg80211_get_station(struct wiphy *wiphy, struct net_device *dev, err = -ENODEV; if (!wl_get_drv_status(wl, CONNECTED, dev) || (dhd_is_associated(dhd, NULL, &err) == FALSE)) { - WL_ERR(("NOT assoc: %d\n", err)); goto get_station_err; } @@ -3168,7 +3180,7 @@ wl_cfg80211_scan_alloc_params(int channel, int nprobes, int *out_params_size) /* Our scan params have 1 channel and 0 ssids */ params->channel_num = htod32((0 << WL_SCAN_PARAMS_NSSID_SHIFT) | - (num_chans & WL_SCAN_PARAMS_COUNT_MASK)); + (num_chans & WL_SCAN_PARAMS_COUNT_MASK)); *out_params_size = params_size; /* rtn size to the caller */ return params; @@ -3195,7 +3207,7 @@ wl_cfg80211_remain_on_channel(struct wiphy *wiphy, struct net_device *dev, ndev = dev; } - if (wl->scan_request) { + if (wl_get_drv_status(wl, SCANNING, ndev)) { wl_notify_escan_complete(wl, ndev, true, true); } target_channel = ieee80211_frequency_to_channel(channel->center_freq); @@ -3207,7 +3219,7 @@ wl_cfg80211_remain_on_channel(struct wiphy *wiphy, struct net_device *dev, *cookie = id; cfg80211_ready_on_channel(dev, *cookie, channel, channel_type, duration, GFP_KERNEL); - if (!p2p_is_on(wl)) { + if (wl->p2p && !wl->p2p->on) { get_primary_mac(wl, &primary_mac); wl_cfgp2p_generate_bss_mac(&primary_mac, &wl->p2p->dev_addr, &wl->p2p->int_addr); @@ -3331,7 +3343,11 @@ wl_cfg80211_mgmt_tx(struct wiphy *wiphy, struct net_device *ndev, struct ieee80211_channel *channel, bool offchan, enum nl80211_channel_type channel_type, bool channel_type_valid, unsigned int wait, - const u8* buf, size_t len, u64 *cookie) + const u8* buf, size_t len, +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 2, 0) + bool no_cck, +#endif + u64 *cookie) { wl_action_frame_t *action_frame; wl_af_params_t *af_params; @@ -3418,6 +3434,10 @@ wl_cfg80211_mgmt_tx(struct wiphy *wiphy, struct net_device *ndev, WL_DBG(("Disconnect STA : %s scb_val.val %d\n", bcm_ether_ntoa((const struct ether_addr *)mgmt->da, eabuf), scb_val.val)); + /* Wait for the deauth event to come, supplicant will do the delete iface immediately + * and we will have problem in sending deauth frame if we delete the bss in firmware + */ + wl_delay(400); cfg80211_mgmt_tx_status(ndev, *cookie, buf, len, true, GFP_KERNEL); goto exit; @@ -3521,7 +3541,7 @@ wl_cfg80211_mgmt_tx(struct wiphy *wiphy, struct net_device *ndev, } if (IS_P2P_SOCIAL(af_params->channel) && - (IS_P2P_PUB_ACT_REQ(act_frm, action_frame->len) || + (IS_P2P_PUB_ACT_REQ(act_frm, &act_frm->elts[0], action_frame->len) || IS_GAS_REQ(sd_act_frm, action_frame->len)) && wl_to_p2p_bss_saved_ie(wl, P2PAPI_BSSCFG_DEVICE).p2p_probe_req_ie_len) { /* channel offload require P2P IE for Probe request @@ -3534,7 +3554,7 @@ wl_cfg80211_mgmt_tx(struct wiphy *wiphy, struct net_device *ndev, } else { ack = (wl_cfgp2p_tx_action_frame(wl, dev, af_params, bssidx)) ? false : true; if (!ack) { - for (retry = 1; retry < WL_CHANNEL_SYNC_RETRY; retry++) { + for (retry = 1; retry < retry_cnt; retry++) { ack = (wl_cfgp2p_tx_action_frame(wl, dev, af_params, bssidx)) ? false : true; if (ack) @@ -4774,17 +4794,24 @@ wl_notify_connect_status(struct wl_priv *wl, struct net_device *ndev, bool act; s32 err = 0; u32 event = ntoh32(e->event_type); + u32 reason; if (wl_get_mode_by_netdev(wl, ndev) == WL_MODE_AP) { wl_notify_connect_status_ap(wl, ndev, e, data); } else { WL_DBG(("wl_notify_connect_status : event %d status : %d ndev %p\n", ntoh32(e->event_type), ntoh32(e->status), ndev)); + if((event == WLC_E_DEAUTH_IND) || (event == WLC_E_DISASSOC_IND)) { + reason = ntoh32(e->reason); + wl->deauth_reason = reason; + WL_ERR(("Received %s event with reason code: %d\n", (event == WLC_E_DEAUTH_IND)? "WLC_E_DEAUTH_IND":"WLC_E_DISASSOC_IND", reason)); + } if (wl_is_linkup(wl, e, ndev)) { wl_link_up(wl); act = true; wl_update_prof(wl, ndev, e, &act, WL_PROF_ACT); wl_update_prof(wl, ndev, NULL, (void *)&e->addr, WL_PROF_BSSID); + wl->deauth_reason = 0; if (wl_is_ibssmode(wl, ndev)) { printk("cfg80211_ibss_joined\n"); cfg80211_ibss_joined(ndev, (s8 *)&e->addr, @@ -4812,7 +4839,6 @@ wl_notify_connect_status(struct wl_priv *wl, struct net_device *ndev, if (wl_get_drv_status(wl, CONNECTED, ndev)) { scb_val_t scbval; u8 *curbssid = wl_read_prof(wl, ndev, WL_PROF_BSSID); - printk("link down, call cfg80211_disconnected\n"); wl_clr_drv_status(wl, CONNECTED, ndev); if (! wl_get_drv_status(wl, DISCONNECTING, ndev)) { /* To make sure disconnect, explictly send dissassoc @@ -4824,7 +4850,8 @@ wl_notify_connect_status(struct wl_priv *wl, struct net_device *ndev, scbval.val = htod32(scbval.val); wldev_ioctl(ndev, WLC_DISASSOC, &scbval, sizeof(scb_val_t), true); - cfg80211_disconnected(ndev, 0, NULL, 0, GFP_KERNEL); + WL_ERR(("link down, calling cfg80211_disconnected with deauth_reason:%d\n", wl->deauth_reason)); + cfg80211_disconnected(ndev, wl->deauth_reason , NULL, 0, GFP_KERNEL); wl_link_down(wl); wl_init_prof(wl, ndev); } @@ -5824,7 +5851,7 @@ static void wl_scan_timeout(unsigned long data) if (wl->scan_request) { WL_ERR(("timer expired\n")); if (wl->escan_on) - wl_notify_escan_complete(wl, wl->escan_info.ndev, false, true); + wl_notify_escan_complete(wl, wl->escan_info.ndev, true, false); else wl_notify_iscan_complete(wl_to_iscan(wl), true); } @@ -5880,7 +5907,7 @@ wl_cfg80211_netdev_notifier_call(struct notifier_block * nb, struct wl_priv *wl = wlcfg_drv_priv; WL_DBG(("Enter \n")); - if (!wdev || dev == wl_to_prmry_ndev(wl)) + if (!wdev || !wl || dev == wl_to_prmry_ndev(wl)) return NOTIFY_DONE; switch (state) { case NETDEV_UNREGISTER: @@ -5945,7 +5972,7 @@ static s32 wl_notify_escan_complete(struct wl_priv *wl, } } } - if (!in_atomic()) + if (timer_pending(&wl->scan_timeout)) del_timer_sync(&wl->scan_timeout); spin_lock_irqsave(&wl->cfgdrv_lock, flags); @@ -5987,7 +6014,6 @@ static s32 wl_escan_handler(struct wl_priv *wl, wl_scan_results_t *list; u32 bi_length; u32 i; - u8 *p2p_dev_addr = NULL; WL_DBG((" enter event type : %d, status : %d \n", ntoh32(e->event_type), ntoh32(e->status))); @@ -6036,8 +6062,7 @@ static s32 wl_escan_handler(struct wl_priv *wl, } if (wl_get_drv_status_all(wl, SENDING_ACT_FRM)) { - p2p_dev_addr = wl_cfgp2p_retreive_p2p_dev_addr(bi, bi_length); - if (p2p_dev_addr && !memcmp(p2p_dev_addr, + if (!memcmp(bi->BSSID.octet, wl->afx_hdl->pending_tx_dst_addr.octet, ETHER_ADDR_LEN)) { s32 channel = CHSPEC_CHANNEL(dtohchanspec(bi->chanspec)); WL_DBG(("ACTION FRAME SCAN : Peer found, channel : %d\n", channel)); @@ -6190,6 +6215,7 @@ static s32 wl_init_priv(struct wl_priv *wl) wl->iscan_kickstart = false; wl->active_scan = true; wl->rf_blocked = false; + wl->deauth_reason = 0; spin_lock_init(&wl->cfgdrv_lock); mutex_init(&wl->ioctl_buf_sync); init_waitqueue_head(&wl->netif_change_event); @@ -6714,12 +6740,16 @@ s32 wl_update_wiphybands(struct wl_priv *wl) } if ((index >= 0) && nmode) { wiphy->bands[index]->ht_cap.cap = - IEEE80211_HT_CAP_DSSSCCK40 - | IEEE80211_HT_CAP_MAX_AMSDU | IEEE80211_HT_CAP_RX_STBC; + IEEE80211_HT_CAP_SGI_20 | IEEE80211_HT_CAP_DSSSCCK40 | + IEEE80211_HT_CAP_MAX_AMSDU; wiphy->bands[index]->ht_cap.ht_supported = TRUE; - wiphy->bands[index]->ht_cap.ampdu_factor = IEEE80211_HT_MAX_AMPDU_16K; + wiphy->bands[index]->ht_cap.ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K; wiphy->bands[index]->ht_cap.ampdu_density = IEEE80211_HT_MPDU_DENSITY_16; } + + if ((index >= 0) && bw_40) { + wiphy->bands[index]->ht_cap.cap |= IEEE80211_HT_CAP_SGI_40; + } } wiphy_apply_custom_regulatory(wiphy, &brcm_regdom); @@ -7046,7 +7076,8 @@ static void wl_init_eq_lock(struct wl_priv *wl) static void wl_delay(u32 ms) { - if (in_atomic() || ms < 1000 / HZ) { + if (ms < 1000 / HZ) { + cond_resched(); mdelay(ms); } else { msleep(ms); diff --git a/drivers/net/wireless/bcmdhd/wl_cfg80211.h b/drivers/net/wireless/bcmdhd/wl_cfg80211.h index 818eff594115..fba853149c35 100644 --- a/drivers/net/wireless/bcmdhd/wl_cfg80211.h +++ b/drivers/net/wireless/bcmdhd/wl_cfg80211.h @@ -131,8 +131,8 @@ do { \ #define IFACE_MAX_CNT 2 #define WL_SCAN_TIMER_INTERVAL_MS 8000 /* Scan timeout */ -#define WL_CHANNEL_SYNC_RETRY 1 -#define WL_ACT_FRAME_RETRY 5 +#define WL_CHANNEL_SYNC_RETRY 3 +#define WL_ACT_FRAME_RETRY 4 #define WL_INVALID -1 @@ -449,6 +449,7 @@ struct wl_priv { #endif /* WL_SCHED_SCAN */ bool sched_scan_running; /* scheduled scan req status */ u16 hostapd_chan; /* remember chan requested by framework for hostapd */ + u16 deauth_reason; /* Place holder to save deauth/disassoc reasons */ }; static inline struct wl_bss_info *next_bss(struct wl_scan_results *list, struct wl_bss_info *bss) diff --git a/drivers/net/wireless/bcmdhd/wl_cfgp2p.c b/drivers/net/wireless/bcmdhd/wl_cfgp2p.c index 880123e067dc..cfa5ac3f5ec6 100644 --- a/drivers/net/wireless/bcmdhd/wl_cfgp2p.c +++ b/drivers/net/wireless/bcmdhd/wl_cfgp2p.c @@ -105,6 +105,7 @@ bool wl_cfgp2p_is_p2p_action(void *frame, u32 frame_len) return false; } + bool wl_cfgp2p_is_gas_action(void *frame, u32 frame_len) { @@ -128,6 +129,7 @@ bool wl_cfgp2p_is_gas_action(void *frame, u32 frame_len) return false; } + void wl_cfgp2p_print_actframe(bool tx, void *frame, u32 frame_len) { wifi_p2p_pub_act_frame_t *pact_frm; @@ -271,7 +273,6 @@ wl_cfgp2p_init_priv(struct wl_priv *wl) wl_to_p2p_bss_bssidx(wl, P2PAPI_BSSCFG_DEVICE) = 0; wl_to_p2p_bss_ndev(wl, P2PAPI_BSSCFG_CONNECTION) = NULL; wl_to_p2p_bss_bssidx(wl, P2PAPI_BSSCFG_CONNECTION) = 0; - spin_lock_init(&wl->p2p->timer_lock); return BCME_OK; } @@ -318,7 +319,7 @@ wl_cfgp2p_set_firm_p2p(struct wl_priv *wl) ret = wldev_iovar_setbuf_bsscfg(ndev, "p2p_da_override", &null_eth_addr, sizeof(null_eth_addr), wl->ioctl_buf, WLC_IOCTL_MAXLEN, 0, &wl->ioctl_buf_sync); if (ret && ret != BCME_UNSUPPORTED) { - CFGP2P_ERR(("failed to update device address\n")); + CFGP2P_ERR(("failed to update device address ret %d\n", ret)); } return ret; } @@ -539,7 +540,7 @@ wl_cfgp2p_init_discovery(struct wl_priv *wl) /* Set the initial discovery state to SCAN */ ret = wl_cfgp2p_set_p2p_mode(wl, WL_P2P_DISC_ST_SCAN, 0, 0, - wl_to_p2p_bss_bssidx(wl, P2PAPI_BSSCFG_DEVICE)); + wl_to_p2p_bss_bssidx(wl, P2PAPI_BSSCFG_DEVICE)); if (unlikely(ret != 0)) { CFGP2P_ERR(("unable to set WL_P2P_DISC_ST_SCAN\n")); @@ -690,7 +691,7 @@ wl_cfgp2p_escan(struct wl_priv *wl, struct net_device *dev, u16 active, #define P2PAPI_SCAN_NPROBES 1 #define P2PAPI_SCAN_DWELL_TIME_MS 50 #define P2PAPI_SCAN_SOCIAL_DWELL_TIME_MS 40 -#define P2PAPI_SCAN_HOME_TIME_MS 10 +#define P2PAPI_SCAN_HOME_TIME_MS 60 struct net_device *pri_dev = wl_to_p2p_bss_ndev(wl, P2PAPI_BSSCFG_PRIMARY); wl_set_p2p_status(wl, SCANNING); /* Allocate scan params which need space for 3 channels and 0 ssids */ @@ -1180,12 +1181,15 @@ wl_cfgp2p_listen_complete(struct wl_priv *wl, struct net_device *ndev, s32 ret = BCME_OK; CFGP2P_DBG((" Enter\n")); + + /* If p2p_info is de-initialized, do nothing */ + if (!wl->p2p) + return ret; + if (wl_get_p2p_status(wl, LISTEN_EXPIRED) == 0) { wl_set_p2p_status(wl, LISTEN_EXPIRED); if (timer_pending(&wl->p2p->listen_timer)) { - spin_lock_bh(&wl->p2p->timer_lock); del_timer_sync(&wl->p2p->listen_timer); - spin_unlock_bh(&wl->p2p->timer_lock); } cfg80211_remain_on_channel_expired(ndev, wl->last_roc_id, &wl->remain_on_chan, wl->remain_on_chan_type, GFP_KERNEL); @@ -1212,6 +1216,33 @@ wl_cfgp2p_listen_expired(unsigned long data) wl_cfg80211_event(wl_to_p2p_bss_ndev(wl, P2PAPI_BSSCFG_DEVICE), &msg, NULL); } +/* + * Routine for cancelling the P2P LISTEN + */ +s32 +wl_cfgp2p_cancel_listen(struct wl_priv *wl, struct net_device *ndev, + bool notify) +{ + WL_DBG(("Enter \n")); + + /* Irrespective of whether timer is running or not, reset + * the LISTEN state. + */ + wl_cfgp2p_set_p2p_mode(wl, WL_P2P_DISC_ST_SCAN, 0, 0, + wl_to_p2p_bss_bssidx(wl, P2PAPI_BSSCFG_DEVICE)); + + if (timer_pending(&wl->p2p->listen_timer)) { + del_timer_sync(&wl->p2p->listen_timer); + + if (notify) + cfg80211_remain_on_channel_expired(ndev, wl->last_roc_id, + &wl->remain_on_chan, wl->remain_on_chan_type, GFP_KERNEL); + } + + + return 0; +} + /* * Do a P2P Listen on the given channel for the given duration. * A listen consists of sitting idle and responding to P2P probe requests @@ -1531,8 +1562,10 @@ wl_cfgp2p_supported(struct wl_priv *wl, struct net_device *ndev) s32 wl_cfgp2p_down(struct wl_priv *wl) { - if (timer_pending(&wl->p2p->listen_timer)) - del_timer_sync(&wl->p2p->listen_timer); + + wl_cfgp2p_cancel_listen(wl, + wl->p2p_net ? wl->p2p_net : wl_to_prmry_ndev(wl), TRUE); + wl_cfgp2p_deinit_priv(wl); return 0; } diff --git a/drivers/net/wireless/bcmdhd/wl_cfgp2p.h b/drivers/net/wireless/bcmdhd/wl_cfgp2p.h index 1e5b1197e92d..be497c3e2426 100644 --- a/drivers/net/wireless/bcmdhd/wl_cfgp2p.h +++ b/drivers/net/wireless/bcmdhd/wl_cfgp2p.h @@ -77,7 +77,6 @@ struct p2p_info { wl_p2p_sched_t noa; wl_p2p_ops_t ops; wlc_ssid_t ssid; - spinlock_t timer_lock; }; /* dongle status */ @@ -268,14 +267,16 @@ wl_cfgp2p_unregister_ndev(struct wl_priv *wl); #define WL_P2P_INTERFACE_PREFIX "p2p" #define WL_P2P_TEMP_CHAN "11" +/* If the provision discovery is for JOIN operations, then we need not do an internal scan to find GO */ +#define IS_PROV_DISC_WITHOUT_GROUP_ID(p2p_ie, len) (wl_cfgp2p_retreive_p2pattrib(p2p_ie, P2P_SEID_GROUP_ID) == NULL ) #define IS_GAS_REQ(frame, len) (wl_cfgp2p_is_gas_action(frame, len) && \ ((frame->action == P2PSD_ACTION_ID_GAS_IREQ) || \ (frame->action == P2PSD_ACTION_ID_GAS_CREQ))) -#define IS_P2P_PUB_ACT_REQ(frame, len) (wl_cfgp2p_is_pub_action(frame, len) && \ +#define IS_P2P_PUB_ACT_REQ(frame, p2p_ie, len) (wl_cfgp2p_is_pub_action(frame, len) && \ ((frame->subtype == P2P_PAF_GON_REQ) || \ (frame->subtype == P2P_PAF_INVITE_REQ) || \ - (frame->subtype == P2P_PAF_PROVDIS_REQ))) + ((frame->subtype == P2P_PAF_PROVDIS_REQ) && IS_PROV_DISC_WITHOUT_GROUP_ID(p2p_ie, len)))) #define IS_P2P_SOCIAL(ch) ((ch == SOCIAL_CHAN_1) || (ch == SOCIAL_CHAN_2) || (ch == SOCIAL_CHAN_3)) #define IS_P2P_SSID(ssid) (memcmp(ssid, WL_P2P_WILDCARD_SSID, WL_P2P_WILDCARD_SSID_LEN) == 0) #endif /* _wl_cfgp2p_h_ */ -- cgit v1.2.3 From d9bbd4c550a4da42469134de2037fc01c143a0f0 Mon Sep 17 00:00:00 2001 From: Dmitry Shmidt Date: Wed, 2 May 2012 14:25:59 -0700 Subject: net: wireless: bcmdhd: Set MMC_PM_KEEP_POWER flag on suspend Signed-off-by: Dmitry Shmidt --- drivers/net/wireless/bcmdhd/bcmsdh_sdmmc_linux.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) (limited to 'drivers/net') diff --git a/drivers/net/wireless/bcmdhd/bcmsdh_sdmmc_linux.c b/drivers/net/wireless/bcmdhd/bcmsdh_sdmmc_linux.c index 1fdb7c90c84e..a9b6629f386b 100644 --- a/drivers/net/wireless/bcmdhd/bcmsdh_sdmmc_linux.c +++ b/drivers/net/wireless/bcmdhd/bcmsdh_sdmmc_linux.c @@ -185,6 +185,22 @@ static int bcmsdh_sdmmc_suspend(struct device *pdev) if (dhd_os_check_wakelock(bcmsdh_get_drvdata())) return -EBUSY; + + + sdio_flags = sdio_get_host_pm_caps(func); + + if (!(sdio_flags & MMC_PM_KEEP_POWER)) { + sd_err(("%s: can't keep power while host is suspended\n", __FUNCTION__)); + return -EINVAL; + } + + /* keep power while host suspended */ + ret = sdio_set_host_pm_flags(func, MMC_PM_KEEP_POWER); + if (ret) { + sd_err(("%s: error while trying to keep power\n", __FUNCTION__)); + return ret; + } + #if defined(OOB_INTR_ONLY) bcmsdh_oob_intr_set(0); #endif /* defined(OOB_INTR_ONLY) */ -- cgit v1.2.3 From f4ec0b33cb6e2c6268c830f5b2fc7361ea1be8ca Mon Sep 17 00:00:00 2001 From: Dmitry Shmidt Date: Thu, 3 May 2012 10:34:15 -0700 Subject: net: wireless: bcmdhd: Avoid turning radio UP twice on start Signed-off-by: Dmitry Shmidt --- drivers/net/wireless/bcmdhd/dhd_linux.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/bcmdhd/dhd_linux.c b/drivers/net/wireless/bcmdhd/dhd_linux.c index 320ce5975bf0..3792e2cd35b9 100644 --- a/drivers/net/wireless/bcmdhd/dhd_linux.c +++ b/drivers/net/wireless/bcmdhd/dhd_linux.c @@ -2960,8 +2960,9 @@ dhd_preinit_ioctls(dhd_pub_t *dhd) int ret = 0; char eventmask[WL_EVENTING_MASK_LEN]; char iovbuf[WL_EVENTING_MASK_LEN + 12]; /* Room for "event_msgs" + '\0' + bitvec */ - +#if !defined(WL_CFG80211) uint up = 0; +#endif uint power_mode = PM_FAST; uint32 dongle_align = DHD_SDALIGN; uint32 glom = 0; @@ -3277,12 +3278,13 @@ dhd_preinit_ioctls(dhd_pub_t *dhd) #endif /* defined(SOFTAP) */ #endif /* PKT_FILTER_SUPPORT */ +#if !defined(WL_CFG80211) /* Force STA UP */ if ((ret = dhd_wl_ioctl_cmd(dhd, WLC_UP, (char *)&up, sizeof(up), TRUE, 0)) < 0) { DHD_ERROR(("%s Setting WL UP failed %d\n", __FUNCTION__, ret)); goto done; } - +#endif /* query for 'ver' to get version info from firmware */ memset(buf, 0, sizeof(buf)); ptr = buf; -- cgit v1.2.3 From a2fab23e5357a19fec8f01f57f09f07733b58169 Mon Sep 17 00:00:00 2001 From: Dmitry Shmidt Date: Thu, 10 May 2012 13:20:40 -0700 Subject: net: wireless: bcmdhd: Fix filtering setting in case of P2P Signed-off-by: Dmitry Shmidt --- drivers/net/wireless/bcmdhd/dhd.h | 1 + drivers/net/wireless/bcmdhd/dhd_cfg80211.c | 4 ++++ drivers/net/wireless/bcmdhd/dhd_linux.c | 22 ++++++++++++++-------- 3 files changed, 19 insertions(+), 8 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/bcmdhd/dhd.h b/drivers/net/wireless/bcmdhd/dhd.h index 3911f336b16f..5ff5c218ddcf 100644 --- a/drivers/net/wireless/bcmdhd/dhd.h +++ b/drivers/net/wireless/bcmdhd/dhd.h @@ -450,6 +450,7 @@ extern int dhd_dev_get_pno_status(struct net_device *dev); #define DHD_MULTICAST4_FILTER_NUM 2 #define DHD_MULTICAST6_FILTER_NUM 3 #define DHD_MDNS_FILTER_NUM 4 +extern int dhd_os_set_packet_filter(dhd_pub_t *dhdp, int val); extern int net_os_set_packet_filter(struct net_device *dev, int val); extern int net_os_rxfilter_add_remove(struct net_device *dev, int val, int num); diff --git a/drivers/net/wireless/bcmdhd/dhd_cfg80211.c b/drivers/net/wireless/bcmdhd/dhd_cfg80211.c index 183891df160a..bc1be94802b4 100644 --- a/drivers/net/wireless/bcmdhd/dhd_cfg80211.c +++ b/drivers/net/wireless/bcmdhd/dhd_cfg80211.c @@ -84,6 +84,8 @@ s32 dhd_cfg80211_set_p2p_info(struct wl_priv *wl, int val) dhd_arp_offload_enable(dhd, false); #endif /* ARP_OFFLOAD_SUPPORT */ + dhd_os_set_packet_filter(dhd, 0); + /* Setup timeout if Beacons are lost and roam is off to report link down */ bcm_mkiovar("bcn_timeout", (char *)&bcn_timeout, 4, iovbuf, sizeof(iovbuf)); dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, sizeof(iovbuf), TRUE, 0); @@ -107,6 +109,8 @@ s32 dhd_cfg80211_clean_p2p_info(struct wl_priv *wl) dhd_arp_offload_enable(dhd, true); #endif /* ARP_OFFLOAD_SUPPORT */ + dhd_os_set_packet_filter(dhd, 1); + /* Setup timeout if Beacons are lost and roam is off to report link down */ bcm_mkiovar("bcn_timeout", (char *)&bcn_timeout, 4, iovbuf, sizeof(iovbuf)); dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, sizeof(iovbuf), TRUE, 0); diff --git a/drivers/net/wireless/bcmdhd/dhd_linux.c b/drivers/net/wireless/bcmdhd/dhd_linux.c index 3792e2cd35b9..a042955fd884 100644 --- a/drivers/net/wireless/bcmdhd/dhd_linux.c +++ b/drivers/net/wireless/bcmdhd/dhd_linux.c @@ -513,7 +513,8 @@ static void dhd_set_packet_filter(int value, dhd_pub_t *dhd) DHD_TRACE(("%s: %d\n", __FUNCTION__, value)); /* 1 - Enable packet filter, only allow unicast packet to send up */ /* 0 - Disable packet filter */ - if (dhd_pkt_filter_enable) { + if (dhd_pkt_filter_enable && (!value || + (dhd_check_ap_wfd_mode_set(dhd) == FALSE))) { int i; for (i = 0; i < dhd->pktfilter_count; i++) { @@ -3059,7 +3060,6 @@ dhd_preinit_ioctls(dhd_pub_t *dhd) DHD_ERROR(("%s APSTA for WFD failed ret= %d\n", __FUNCTION__, ret)); } else { dhd->op_mode |= WFD_MASK; - dhd_pkt_filter_enable = FALSE; } } #endif @@ -4402,9 +4402,8 @@ int net_os_rxfilter_add_remove(struct net_device *dev, int add_remove, int num) return ret; } -int net_os_set_packet_filter(struct net_device *dev, int val) +int dhd_os_set_packet_filter(dhd_pub_t *dhdp, int val) { - dhd_info_t *dhd = *(dhd_info_t **)netdev_priv(dev); int ret = 0; /* Packet filtering is set only if we still in early-suspend and @@ -4412,15 +4411,22 @@ int net_os_set_packet_filter(struct net_device *dev, int val) * We can always turn it OFF in case of early-suspend, but we turn it * back ON only if suspend_disable_flag was not set */ - if (dhd && dhd->pub.up) { - if (dhd->pub.in_suspend) { - if (!val || (val && !dhd->pub.suspend_disable_flag)) - dhd_set_packet_filter(val, &dhd->pub); + if (dhdp && dhdp->up) { + if (dhdp->in_suspend) { + if (!val || (val && !dhdp->suspend_disable_flag)) + dhd_set_packet_filter(val, dhdp); } } return ret; + } +int net_os_set_packet_filter(struct net_device *dev, int val) +{ + dhd_info_t *dhd = *(dhd_info_t **)netdev_priv(dev); + + return dhd_os_set_packet_filter(&dhd->pub, val); +} void dhd_dev_init_ioctl(struct net_device *dev) -- cgit v1.2.3 From 99d59b5c10362bc439a2ec5dbee14961c248c18b Mon Sep 17 00:00:00 2001 From: Dmitry Shmidt Date: Tue, 15 May 2012 12:22:48 -0700 Subject: net: wireless: bcmdhd: Change singal pending return value from -110 to -4 - ETIMEDOUT is interpreted as FW is not responding, so return EINTR instead Signed-off-by: Dmitry Shmidt --- drivers/net/wireless/bcmdhd/dhd_sdio.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/bcmdhd/dhd_sdio.c b/drivers/net/wireless/bcmdhd/dhd_sdio.c index 954d8296fd6a..4e6f9c89754a 100644 --- a/drivers/net/wireless/bcmdhd/dhd_sdio.c +++ b/drivers/net/wireless/bcmdhd/dhd_sdio.c @@ -1481,9 +1481,9 @@ dhd_bus_rxctl(struct dhd_bus *bus, uchar *msg, uint msglen) dhd_os_sdunlock(bus->dhd); #endif /* DHD_DEBUG */ } else if (pending == TRUE) { - /* possibly fw hangs so never responsed back */ - DHD_ERROR(("%s: pending or timeout \n", __FUNCTION__)); - return -ETIMEDOUT; + /* signal pending */ + DHD_ERROR(("%s: signal pending\n", __FUNCTION__)); + return -EINTR; } else { DHD_CTL(("%s: resumed for unknown reason?\n", __FUNCTION__)); #ifdef DHD_DEBUG -- cgit v1.2.3 From 80cea895e912ac4b41b509137a00f3bae69a3f8c Mon Sep 17 00:00:00 2001 From: Dmitry Shmidt Date: Tue, 15 May 2012 13:20:25 -0700 Subject: net: wireless: bcmdhd: Fix WARN_ON(!res->pub.channel) Signed-off-by: Dmitry Shmidt --- drivers/net/wireless/bcmdhd/wl_cfg80211.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'drivers/net') diff --git a/drivers/net/wireless/bcmdhd/wl_cfg80211.c b/drivers/net/wireless/bcmdhd/wl_cfg80211.c index 98e498d785cd..2aea33634947 100644 --- a/drivers/net/wireless/bcmdhd/wl_cfg80211.c +++ b/drivers/net/wireless/bcmdhd/wl_cfg80211.c @@ -4560,6 +4560,11 @@ static s32 wl_inform_single_bss(struct wl_priv *wl, struct wl_bss_info *bi) freq = ieee80211_channel_to_frequency(notif_bss_info->channel, band->band); #endif channel = ieee80211_get_channel(wiphy, freq); + if (!channel) { + WL_ERR(("No valid channel")); + kfree(notif_bss_info); + return -EINVAL; + } WL_DBG(("SSID : \"%s\", rssi %d, channel %d, capability : 0x04%x, bssid %pM" "mgmt_type %d frame_len %d\n", bi->SSID, -- cgit v1.2.3 From ec02c20b7c417687c344457897abf41aac5ee087 Mon Sep 17 00:00:00 2001 From: Dmitry Shmidt Date: Wed, 16 May 2012 11:26:24 -0700 Subject: net: wireless: bcmdhd: Check return value from dhd_dev_init_ioctl() Signed-off-by: Dmitry Shmidt --- drivers/net/wireless/bcmdhd/dhd_linux.c | 4 ++-- drivers/net/wireless/bcmdhd/wl_android.c | 8 +++++--- drivers/net/wireless/bcmdhd/wl_iw.c | 2 +- 3 files changed, 8 insertions(+), 6 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/bcmdhd/dhd_linux.c b/drivers/net/wireless/bcmdhd/dhd_linux.c index a042955fd884..95753e2f08d3 100644 --- a/drivers/net/wireless/bcmdhd/dhd_linux.c +++ b/drivers/net/wireless/bcmdhd/dhd_linux.c @@ -4428,12 +4428,12 @@ int net_os_set_packet_filter(struct net_device *dev, int val) return dhd_os_set_packet_filter(&dhd->pub, val); } -void +int dhd_dev_init_ioctl(struct net_device *dev) { dhd_info_t *dhd = *(dhd_info_t **)netdev_priv(dev); - dhd_preinit_ioctls(&dhd->pub); + return dhd_preinit_ioctls(&dhd->pub); } #ifdef PNO_SUPPORT diff --git a/drivers/net/wireless/bcmdhd/wl_android.c b/drivers/net/wireless/bcmdhd/wl_android.c index 631c12bda8b6..4fcdcd32a3ff 100644 --- a/drivers/net/wireless/bcmdhd/wl_android.c +++ b/drivers/net/wireless/bcmdhd/wl_android.c @@ -115,7 +115,7 @@ typedef struct android_wifi_priv_cmd { */ void dhd_customer_gpio_wlan_ctrl(int onoff); uint dhd_dev_reset(struct net_device *dev, uint8 flag); -void dhd_dev_init_ioctl(struct net_device *dev); +int dhd_dev_init_ioctl(struct net_device *dev); #ifdef WL_CFG80211 int wl_cfg80211_get_p2p_dev_addr(struct net_device *net, struct ether_addr *p2pdev_addr); int wl_cfg80211_set_btcoex_dhcp(struct net_device *dev, char *command); @@ -387,8 +387,10 @@ int wl_android_wifi_on(struct net_device *dev) sdioh_start(NULL, 0); ret = dhd_dev_reset(dev, FALSE); sdioh_start(NULL, 1); - if (!ret) - dhd_dev_init_ioctl(dev); + if (!ret) { + if (dhd_dev_init_ioctl(dev) < 0) + ret = -EFAULT; + } g_wifi_on = 1; } dhd_net_if_unlock(dev); diff --git a/drivers/net/wireless/bcmdhd/wl_iw.c b/drivers/net/wireless/bcmdhd/wl_iw.c index 1b304bd6d1d8..059929340354 100644 --- a/drivers/net/wireless/bcmdhd/wl_iw.c +++ b/drivers/net/wireless/bcmdhd/wl_iw.c @@ -148,7 +148,7 @@ static struct mutex wl_softap_lock; #include extern void dhd_customer_gpio_wlan_ctrl(int onoff); extern uint dhd_dev_reset(struct net_device *dev, uint8 flag); -extern void dhd_dev_init_ioctl(struct net_device *dev); +extern int dhd_dev_init_ioctl(struct net_device *dev); uint wl_msg_level = WL_ERROR_VAL; -- cgit v1.2.3 From 8e845f2e9a64546124381d8052c1867bbe9db785 Mon Sep 17 00:00:00 2001 From: Dmitry Shmidt Date: Wed, 16 May 2012 16:50:06 -0700 Subject: net: wireless: bcmdhd: Ignore signal_pending() while waiting in IOCTL Signed-off-by: Dmitry Shmidt --- drivers/net/wireless/bcmdhd/dhd_linux.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/bcmdhd/dhd_linux.c b/drivers/net/wireless/bcmdhd/dhd_linux.c index 95753e2f08d3..93050b882d12 100644 --- a/drivers/net/wireless/bcmdhd/dhd_linux.c +++ b/drivers/net/wireless/bcmdhd/dhd_linux.c @@ -3933,14 +3933,11 @@ dhd_os_ioctl_resp_wait(dhd_pub_t *pub, uint *condition, bool *pending) * Can be changed by another processor. */ smp_mb(); - while (!(*condition) && (!signal_pending(current) && timeout)) { + while (!(*condition) && timeout) { timeout = schedule_timeout(timeout); smp_mb(); } - if (signal_pending(current)) - *pending = TRUE; - set_current_state(TASK_RUNNING); remove_wait_queue(&dhd->ioctl_resp_wait, &wait); -- cgit v1.2.3 From 463b5db64f9c60886c65f9ea8a4683194c891270 Mon Sep 17 00:00:00 2001 From: Neeraj Kumar Garg Date: Thu, 24 May 2012 12:19:18 -0700 Subject: net: wireless: bcmdhd: Fix WPS PBC overlap failure Signed-off-by: Dmitry Shmidt --- drivers/net/wireless/bcmdhd/wl_cfg80211.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers/net') diff --git a/drivers/net/wireless/bcmdhd/wl_cfg80211.c b/drivers/net/wireless/bcmdhd/wl_cfg80211.c index 2aea33634947..272c0322c5ec 100644 --- a/drivers/net/wireless/bcmdhd/wl_cfg80211.c +++ b/drivers/net/wireless/bcmdhd/wl_cfg80211.c @@ -2216,6 +2216,8 @@ wl_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev, */ WL_DBG(("ASSOC2 p2p index : %d sme->ie_len %d\n", wl_cfgp2p_find_idx(wl, dev), sme->ie_len)); + wl_cfgp2p_set_management_ie(wl, dev, wl_cfgp2p_find_idx(wl, dev), + VNDR_IE_PRBREQ_FLAG, sme->ie, sme->ie_len); wl_cfgp2p_set_management_ie(wl, dev, wl_cfgp2p_find_idx(wl, dev), VNDR_IE_ASSOCREQ_FLAG, sme->ie, sme->ie_len); } -- cgit v1.2.3 From dd9038724e7b36d9fb38905e279c1370e2e45fec Mon Sep 17 00:00:00 2001 From: Dmitry Shmidt Date: Tue, 29 May 2012 15:05:33 -0700 Subject: net: wireless: bcmdhd: Make responce waiting uninterruptible Signed-off-by: Dmitry Shmidt --- drivers/net/wireless/bcmdhd/dhd_linux.c | 34 +++++++++------------------------ drivers/net/wireless/bcmdhd/dhd_sdio.c | 6 +++--- 2 files changed, 12 insertions(+), 28 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/bcmdhd/dhd_linux.c b/drivers/net/wireless/bcmdhd/dhd_linux.c index 93050b882d12..6ba7df1cac32 100644 --- a/drivers/net/wireless/bcmdhd/dhd_linux.c +++ b/drivers/net/wireless/bcmdhd/dhd_linux.c @@ -672,16 +672,12 @@ dhd_timeout_expired(dhd_timeout_t *tmo) } else { wait_queue_head_t delay_wait; DECLARE_WAITQUEUE(wait, current); - int pending; init_waitqueue_head(&delay_wait); add_wait_queue(&delay_wait, &wait); set_current_state(TASK_INTERRUPTIBLE); schedule_timeout(1); - pending = signal_pending(current); remove_wait_queue(&delay_wait, &wait); set_current_state(TASK_RUNNING); - if (pending) - return 1; /* Interrupted */ } return 0; @@ -3914,7 +3910,6 @@ int dhd_os_ioctl_resp_wait(dhd_pub_t *pub, uint *condition, bool *pending) { dhd_info_t * dhd = (dhd_info_t *)(pub->info); - DECLARE_WAITQUEUE(wait, current); int timeout = dhd_ioctl_timeout_msec; /* Convert timeout in millsecond to jiffies */ @@ -3924,23 +3919,7 @@ dhd_os_ioctl_resp_wait(dhd_pub_t *pub, uint *condition, bool *pending) timeout = timeout * HZ / 1000; #endif - /* Wait until control frame is available */ - add_wait_queue(&dhd->ioctl_resp_wait, &wait); - set_current_state(TASK_INTERRUPTIBLE); - - /* Memory barrier to support multi-processing - * As the variable "condition", which points to dhd->rxlen (dhd_bus_rxctl[dhd_sdio.c]) - * Can be changed by another processor. - */ - smp_mb(); - while (!(*condition) && timeout) { - timeout = schedule_timeout(timeout); - smp_mb(); - } - - set_current_state(TASK_RUNNING); - remove_wait_queue(&dhd->ioctl_resp_wait, &wait); - + timeout = wait_event_timeout(dhd->ioctl_resp_wait, (*condition), timeout); return timeout; } @@ -3950,7 +3929,7 @@ dhd_os_ioctl_resp_wake(dhd_pub_t *pub) dhd_info_t *dhd = (dhd_info_t *)(pub->info); if (waitqueue_active(&dhd->ioctl_resp_wait)) { - wake_up_interruptible(&dhd->ioctl_resp_wait); + wake_up(&dhd->ioctl_resp_wait); } return 0; @@ -4299,8 +4278,13 @@ void dhd_wait_for_event(dhd_pub_t *dhd, bool *lockvar) { #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0)) struct dhd_info *dhdinfo = dhd->info; +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) + int timeout = msecs_to_jiffies(2000); +#else + int timeout = 2 * HZ; +#endif dhd_os_sdunlock(dhd); - wait_event_interruptible_timeout(dhdinfo->ctrl_wait, (*lockvar == FALSE), HZ * 2); + wait_event_timeout(dhdinfo->ctrl_wait, (*lockvar == FALSE), timeout); dhd_os_sdlock(dhd); #endif return; @@ -4311,7 +4295,7 @@ void dhd_wait_event_wakeup(dhd_pub_t *dhd) #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0)) struct dhd_info *dhdinfo = dhd->info; if (waitqueue_active(&dhdinfo->ctrl_wait)) - wake_up_interruptible(&dhdinfo->ctrl_wait); + wake_up(&dhdinfo->ctrl_wait); #endif return; } diff --git a/drivers/net/wireless/bcmdhd/dhd_sdio.c b/drivers/net/wireless/bcmdhd/dhd_sdio.c index 4e6f9c89754a..2cac95f2def4 100644 --- a/drivers/net/wireless/bcmdhd/dhd_sdio.c +++ b/drivers/net/wireless/bcmdhd/dhd_sdio.c @@ -3124,9 +3124,9 @@ dhd_bus_init(dhd_pub_t *dhdp, bool enforce_mutex) dhd_timeout_start(&tmo, DHD_WAIT_F2RDY * 1000); ready = 0; - while (ready != enable && !dhd_timeout_expired(&tmo)) - ready = bcmsdh_cfg_read(bus->sdh, SDIO_FUNC_0, SDIOD_CCCR_IORDY, NULL); - + do { + ready = bcmsdh_cfg_read(bus->sdh, SDIO_FUNC_0, SDIOD_CCCR_IORDY, NULL); + } while (ready != enable && !dhd_timeout_expired(&tmo)); DHD_INFO(("%s: enable 0x%02x, ready 0x%02x (waited %uus)\n", __FUNCTION__, enable, ready, tmo.elapsed)); -- cgit v1.2.3 From a5369a7586398d5071d4313e3bc068d8a0fd51cf Mon Sep 17 00:00:00 2001 From: Leslie Yu Date: Tue, 29 May 2012 15:18:17 -0700 Subject: net: wireless: bcmdhd: Fix P2P driver crash for MFG firmware Signed-off-by: Dmitry Shmidt --- drivers/net/wireless/bcmdhd/wl_cfg80211.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/bcmdhd/wl_cfg80211.c b/drivers/net/wireless/bcmdhd/wl_cfg80211.c index 272c0322c5ec..fa3766699a86 100644 --- a/drivers/net/wireless/bcmdhd/wl_cfg80211.c +++ b/drivers/net/wireless/bcmdhd/wl_cfg80211.c @@ -4568,7 +4568,7 @@ static s32 wl_inform_single_bss(struct wl_priv *wl, struct wl_bss_info *bi) return -EINVAL; } - WL_DBG(("SSID : \"%s\", rssi %d, channel %d, capability : 0x04%x, bssid %pM" + WL_DBG(("SSID : \"%s\", rssi %d, channel %d, capability : 0x04%x, bssid %pM " "mgmt_type %d frame_len %d\n", bi->SSID, notif_bss_info->rssi, notif_bss_info->channel, mgmt->u.beacon.capab_info, &bi->BSSID, mgmt_type, @@ -4577,7 +4577,7 @@ static s32 wl_inform_single_bss(struct wl_priv *wl, struct wl_bss_info *bi) signal = notif_bss_info->rssi * 100; #if defined(WLP2P) && defined(WL_ENABLE_P2P_IF) - if (wl->p2p_net && wl->scan_request && + if (wl->p2p && wl->p2p_net && wl->scan_request && ((wl->scan_request->dev == wl->p2p_net) || (wl->scan_request->dev == wl_to_p2p_bss_ndev(wl, P2PAPI_BSSCFG_CONNECTION)))){ #else -- cgit v1.2.3 From b195925f8b7380ae3d22565bb9b36b925f3f2a6b Mon Sep 17 00:00:00 2001 From: Om Prakash Singh Date: Thu, 14 Jun 2012 15:21:19 +0530 Subject: net: wireless: bcmdhd: fix Makefile and Kconfig Bug 999876 Change-Id: I83a139e6c0dd42cf095fa2ac1376732075a15434 --- drivers/net/wireless/bcmdhd/Kconfig | 7 ------- drivers/net/wireless/bcmdhd/Makefile | 2 +- 2 files changed, 1 insertion(+), 8 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/bcmdhd/Kconfig b/drivers/net/wireless/bcmdhd/Kconfig index 7afecb04ade9..ef9ce5a00538 100644 --- a/drivers/net/wireless/bcmdhd/Kconfig +++ b/drivers/net/wireless/bcmdhd/Kconfig @@ -24,11 +24,6 @@ config BCMDHD_NVRAM_DIR ---help--- Path to the calibration file. -choice - prompt "Select API" - depends on BCMDHD - default BCMDHD_NOAPI - config BCMDHD_WEXT bool "Enable WEXT support" select WIRELESS_EXT @@ -68,8 +63,6 @@ config BCMDHD_NOAPI help No wireless API is needed -endchoice - config BCMDHD_WIFI_CONTROL_FUNC bool "Use bcmdhd_wlan device" depends on BCMDHD diff --git a/drivers/net/wireless/bcmdhd/Makefile b/drivers/net/wireless/bcmdhd/Makefile index fa7dc6dce6b8..2851388cf194 100644 --- a/drivers/net/wireless/bcmdhd/Makefile +++ b/drivers/net/wireless/bcmdhd/Makefile @@ -48,7 +48,7 @@ bcmdhd-objs += wl_iw.o DHDCFLAGS += -DSOFTAP -DWL_WIRELESS_EXT endif -ifeq ($(CONFIG_BCMDHD_CFG80211),y) +ifneq ($(CONFIG_CFG80211),) bcmdhd-objs += wl_cfg80211.o wl_cfgp2p.o wl_linux_mon.o DHDCFLAGS += -DWL_CFG80211 endif -- cgit v1.2.3 From 9071241fd16598ba165db5759047e807f75c922c Mon Sep 17 00:00:00 2001 From: Nitin Bindal Date: Mon, 18 Jun 2012 18:51:30 +0530 Subject: net: wireless: bcmdhd: Enable 5 GHz support Update wiphy (wireless hardware description) to support 5 GHz scan. Bug 1000888 Change-Id: I1a7a99f97f69dd8f1790f81ee0fb21e209e8d10e Signed-off-by: Nitin Bindal Reviewed-on: http://git-master/r/109556 Reviewed-by: Automatic_Commit_Validation_User Reviewed-by: Rakesh Kumar Reviewed-by: Bharat Nihalani --- drivers/net/wireless/bcmdhd/wl_cfg80211.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/bcmdhd/wl_cfg80211.c b/drivers/net/wireless/bcmdhd/wl_cfg80211.c index fa3766699a86..2dc329b5a626 100644 --- a/drivers/net/wireless/bcmdhd/wl_cfg80211.c +++ b/drivers/net/wireless/bcmdhd/wl_cfg80211.c @@ -4426,7 +4426,7 @@ static s32 wl_setup_wiphy(struct wireless_dev *wdev, struct device *sdiofunc_dev | BIT(NL80211_IFTYPE_AP) | BIT(NL80211_IFTYPE_MONITOR); wdev->wiphy->bands[IEEE80211_BAND_2GHZ] = &__wl_band_2ghz; - /* wdev->wiphy->bands[IEEE80211_BAND_5GHZ] = &__wl_band_5ghz_a; - set in runtime */ + wdev->wiphy->bands[IEEE80211_BAND_5GHZ] = &__wl_band_5ghz_a; wdev->wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM; wdev->wiphy->cipher_suites = __wl_cipher_suites; wdev->wiphy->n_cipher_suites = ARRAY_SIZE(__wl_cipher_suites); -- cgit v1.2.3 From 77afc78b6234c4839659164ebacc88e749171d69 Mon Sep 17 00:00:00 2001 From: Mohan T Date: Mon, 25 Jun 2012 11:06:17 +0530 Subject: usb: cdc_ether: Add rmnet device info to PH450 and Tango Modified device info element for PH450 and Tango to sync with framework. Change-Id: I325571358f8c1875484254a9f497c606adb03180 Signed-off-by: Mohan T Reviewed-on: http://git-master/r/110765 Reviewed-by: Automatic_Commit_Validation_User GVS: Gerrit_Virtual_Submit Reviewed-by: Matthieu Vincenot Reviewed-by: Steve Lin --- drivers/net/usb/cdc_ether.c | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/usb/cdc_ether.c b/drivers/net/usb/cdc_ether.c index aa826d90f00d..c31b1185f492 100644 --- a/drivers/net/usb/cdc_ether.c +++ b/drivers/net/usb/cdc_ether.c @@ -469,6 +469,15 @@ static const struct driver_info wwan_info = { .manage_power = cdc_manage_power, }; +static const struct driver_info rmnet_info = { + .description = "Mobile Broadband Network Device", + .flags = FLAG_RMNET, + .bind = usbnet_cdc_bind, + .unbind = usbnet_cdc_unbind, + .status = usbnet_cdc_status, + .manage_power = cdc_manage_power, +}; + /*-------------------------------------------------------------------------*/ #define HUAWEI_VENDOR_ID 0x12D1 @@ -575,17 +584,17 @@ static const struct usb_device_id products [] = { .match_flags = USB_DEVICE_ID_MATCH_INT_INFO | USB_DEVICE_ID_MATCH_DEVICE, USB_DEVICE(0x1983, 0x0310), - .driver_info = (unsigned long)&wwan_info, + .driver_info = (unsigned long)&rmnet_info, }, { .match_flags = USB_DEVICE_ID_MATCH_INT_INFO | USB_DEVICE_ID_MATCH_DEVICE, USB_DEVICE(0x1983, 0x0321), - .driver_info = (unsigned long)&wwan_info, + .driver_info = (unsigned long)&rmnet_info, }, { .match_flags = USB_DEVICE_ID_MATCH_INT_INFO | USB_DEVICE_ID_MATCH_DEVICE, USB_DEVICE(0x1983, 0x0327), /* 5AE */ - .driver_info = (unsigned long)&wwan_info, + .driver_info = (unsigned long)&rmnet_info, }, /* Tango module */ @@ -593,7 +602,7 @@ static const struct usb_device_id products [] = { .match_flags = USB_DEVICE_ID_MATCH_INT_INFO | USB_DEVICE_ID_MATCH_DEVICE, USB_DEVICE(0x0489,0xE03A), - .driver_info = (unsigned long)&wwan_info, + .driver_info = (unsigned long)&rmnet_info, }, /* * WHITELIST!!! -- cgit v1.2.3 From eae1303e1c61ecb5ae1da10a4e4b59a551db0123 Mon Sep 17 00:00:00 2001 From: Sang-Hun Lee Date: Fri, 15 Jun 2012 17:15:46 -0700 Subject: net: wireless: bcmdhd: move barrier to after setting the suspended flag. Reviewed-on: http://mcrd1-5.corpnet.asus/code-review/master/47846 Tested-by: Kirt Hsieh Reviewed-by: Kirt Hsieh Reviewed-by: Vincent Yue Bug 984811 Signed-off-by: Roger Hsieh Change-Id: I708dadddf3f3eac9f8bacc72e3aef94247a87e70 Reviewed-on: http://git-master/r/106352 Reviewed-by: Automatic_Commit_Validation_User Reviewed-by: Sang-Hun Lee Tested-by: Sang-Hun Lee Reviewed-by: Bitan Biswas --- drivers/net/wireless/bcmdhd/bcmsdh_sdmmc_linux.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/bcmdhd/bcmsdh_sdmmc_linux.c b/drivers/net/wireless/bcmdhd/bcmsdh_sdmmc_linux.c index a9b6629f386b..7d74d3137d52 100644 --- a/drivers/net/wireless/bcmdhd/bcmsdh_sdmmc_linux.c +++ b/drivers/net/wireless/bcmdhd/bcmsdh_sdmmc_linux.c @@ -204,7 +204,6 @@ static int bcmsdh_sdmmc_suspend(struct device *pdev) #if defined(OOB_INTR_ONLY) bcmsdh_oob_intr_set(0); #endif /* defined(OOB_INTR_ONLY) */ - smp_mb(); sdio_flags = sdio_get_host_pm_caps(func); @@ -223,6 +222,7 @@ static int bcmsdh_sdmmc_suspend(struct device *pdev) } dhd_mmc_suspend = TRUE; + smp_mb(); out: return ret; -- cgit v1.2.3 From 82bb8a79e318e1b8330a9c70fe160f9bf2dedeb7 Mon Sep 17 00:00:00 2001 From: Mursalin Akon Date: Mon, 2 Jul 2012 14:03:54 -0700 Subject: net: wireless: bcmdhd: do not register for all Do not register bcmdhd driver for all sdio devices. Bug 1006828 Change-Id: I49e2d2bc7fbda4414392d8a28a0feefb1c8031ec Signed-off-by: Mursalin Akon Reviewed-on: http://git-master/r/113045 Reviewed-by: Simone Willett Tested-by: Simone Willett --- drivers/net/wireless/bcmdhd/bcmsdh_sdmmc_linux.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/bcmdhd/bcmsdh_sdmmc_linux.c b/drivers/net/wireless/bcmdhd/bcmsdh_sdmmc_linux.c index 7d74d3137d52..656953939b71 100644 --- a/drivers/net/wireless/bcmdhd/bcmsdh_sdmmc_linux.c +++ b/drivers/net/wireless/bcmdhd/bcmsdh_sdmmc_linux.c @@ -165,7 +165,6 @@ static const struct sdio_device_id bcmsdh_sdmmc_ids[] = { { SDIO_DEVICE(SDIO_VENDOR_ID_BROADCOM, SDIO_DEVICE_ID_BROADCOM_4334) }, { SDIO_DEVICE(SDIO_VENDOR_ID_BROADCOM, SDIO_DEVICE_ID_BROADCOM_4324) }, { SDIO_DEVICE(SDIO_VENDOR_ID_BROADCOM, SDIO_DEVICE_ID_BROADCOM_43239) }, - { SDIO_DEVICE_CLASS(SDIO_CLASS_NONE) }, { /* end: all zeroes */ }, }; -- cgit v1.2.3 From 09a2687ade101219c68c8069f54861eef1dec711 Mon Sep 17 00:00:00 2001 From: "Jun (Gab-Joo) Lim" Date: Tue, 26 Jun 2012 08:59:57 +0530 Subject: net: wireless: WFD specific changes WFD specific changes integrated from broadcom patch Bug 1001418 Bug 997838 Change-Id: I0632307bf5fb959def4ee12687430a14ab9e068e Signed-off-by: Narayan Reddy Reviewed-on: http://git-master/r/111032 Reviewed-by: Automatic_Commit_Validation_User Tested-by: Rakesh Goyal Reviewed-by: Rakesh Kumar GVS: Gerrit_Virtual_Submit Reviewed-by: Bharat Nihalani --- drivers/net/wireless/bcmdhd/wl_cfg80211.c | 27 +++++++++++++++++++++++++-- drivers/net/wireless/bcmdhd/wl_cfgp2p.c | 22 ++++++++++++++++++++-- drivers/net/wireless/bcmdhd/wl_cfgp2p.h | 5 ++++- 3 files changed, 49 insertions(+), 5 deletions(-) (limited to 'drivers/net') diff --git a/drivers/net/wireless/bcmdhd/wl_cfg80211.c b/drivers/net/wireless/bcmdhd/wl_cfg80211.c index 2dc329b5a626..f728c14622a1 100644 --- a/drivers/net/wireless/bcmdhd/wl_cfg80211.c +++ b/drivers/net/wireless/bcmdhd/wl_cfg80211.c @@ -3355,6 +3355,7 @@ wl_cfg80211_mgmt_tx(struct wiphy *wiphy, struct net_device *ndev, wl_af_params_t *af_params; wifi_p2p_ie_t *p2p_ie; wpa_ie_fixed_t *wps_ie; + wifi_wfd_ie_t *wfd_ie; scb_val_t scb_val; const struct ieee80211_mgmt *mgmt; struct wl_priv *wl = wiphy_priv(wiphy); @@ -3363,6 +3364,7 @@ wl_cfg80211_mgmt_tx(struct wiphy *wiphy, struct net_device *ndev, s32 bssidx = 0; u32 p2pie_len = 0; u32 wpsie_len = 0; + u32 wfdie_len = 0; u32 id; u32 retry = 0; bool ack = false; @@ -3412,6 +3414,11 @@ wl_cfg80211_mgmt_tx(struct wiphy *wiphy, struct net_device *ndev, /* Total length of P2P Information Element */ p2pie_len = p2p_ie->len + sizeof(p2p_ie->len) + sizeof(p2p_ie->id); } + if ((wfd_ie = wl_cfgp2p_find_wfdie((u8 *)(buf + ie_offset), ie_len)) + != NULL) { + /* Total length of WFD Information Element */ + wfdie_len = wfd_ie->len + sizeof(wfd_ie->len) + sizeof(wfd_ie->id); + } if ((wps_ie = wl_cfgp2p_find_wpsie((u8 *)(buf + ie_offset), ie_len)) != NULL) { /* Order of Vendor IE is 1) WPS IE + @@ -3423,7 +3430,7 @@ wl_cfg80211_mgmt_tx(struct wiphy *wiphy, struct net_device *ndev, sizeof(wps_ie->tag); wl_cfgp2p_set_management_ie(wl, dev, bssidx, VNDR_IE_PRBRSP_FLAG, - (u8 *)wps_ie, wpsie_len + p2pie_len); + (u8 *)wps_ie, wpsie_len + p2pie_len + wfdie_len); } cfg80211_mgmt_tx_status(ndev, *cookie, buf, len, true, GFP_KERNEL); goto exit; @@ -3908,11 +3915,13 @@ wl_cfg80211_add_set_beacon(struct wiphy *wiphy, struct net_device *dev, wpa_ie_fixed_t *wpa_ie; bcm_tlv_t *wpa2_ie; wifi_p2p_ie_t *p2p_ie; + wifi_wfd_ie_t *wfd_ie; bool is_bssup = false; bool update_bss = false; bool pbc = false; u16 wpsie_len = 0; u16 p2pie_len = 0; + u32 wfdie_len = 0; u8 beacon_ie[IE_MAX_LEN]; s32 ie_offset = 0; s32 bssidx = 0; @@ -3970,10 +3979,24 @@ wl_cfg80211_add_set_beacon(struct wiphy *wiphy, struct net_device *dev, } else { WL_ERR(("No P2PIE in beacon \n")); } + /* find the WFD IEs */ + if ((wfd_ie = wl_cfgp2p_find_wfdie((u8 *)info->tail, info->tail_len)) != NULL) { + /* Total length of P2P Information Element */ + wfdie_len = wfd_ie->len + sizeof(wfd_ie->len) + sizeof(wfd_ie->id); + if ((wpsie_len + p2pie_len + wfdie_len) < IE_MAX_LEN) { + memcpy(&beacon_ie[wpsie_len + p2pie_len], wfd_ie, wfdie_len); + } else { + WL_ERR(("Found WFD IE but there is no space, (%d)(%d)(%d)\n", + wpsie_len, p2pie_len, wfdie_len)); + wfdie_len = 0; + } + } else { + WL_ERR(("No WFDIE in beacon \n")); + } /* add WLC_E_PROBREQ_MSG event to respose probe_request from STA */ wl_add_remove_eventmsg(dev, WLC_E_PROBREQ_MSG, pbc); wl_cfgp2p_set_management_ie(wl, dev, bssidx, VNDR_IE_BEACON_FLAG, - beacon_ie, wpsie_len + p2pie_len); + beacon_ie, wpsie_len + p2pie_len + wfdie_len); /* find the RSN_IE */ if ((wpa2_ie = bcm_parse_tlvs((u8 *)info->tail, info->tail_len, diff --git a/drivers/net/wireless/bcmdhd/wl_cfgp2p.c b/drivers/net/wireless/bcmdhd/wl_cfgp2p.c index cfa5ac3f5ec6..a34c4ad17c25 100644 --- a/drivers/net/wireless/bcmdhd/wl_cfgp2p.c +++ b/drivers/net/wireless/bcmdhd/wl_cfgp2p.c @@ -829,6 +829,10 @@ exit: /* Check whether the given IE looks like WFA P2P IE. */ #define wl_cfgp2p_is_p2p_ie(ie, tlvs, len) wl_cfgp2p_has_ie(ie, tlvs, len, \ (const uint8 *)WFA_OUI, WFA_OUI_LEN, WFA_OUI_TYPE_P2P) +/* Check whether the given IE looks like WFA WFDisplay IE. */ +#define WFA_OUI_TYPE_WFD 0x0a /* WiFi Display OUI TYPE */ +#define wl_cfgp2p_is_wfd_ie(ie, tlvs, len) wl_cfgp2p_has_ie(ie, tlvs, len, \ + (const uint8 *)WFA_OUI, WFA_OUI_LEN, WFA_OUI_TYPE_WFD) /* Delete and Set a management vndr ie to firmware * Parameters: * @wl : wl_private data @@ -953,7 +957,8 @@ wl_cfgp2p_set_management_ie(struct wl_priv *wl, struct net_device *ndev, s32 bss ie_len = ie_buf[pos++]; if ((ie_id == DOT11_MNG_VS_ID) && (wl_cfgp2p_is_wps_ie(&ie_buf[pos-2], NULL, 0) || - wl_cfgp2p_is_p2p_ie(&ie_buf[pos-2], NULL, 0))) { + wl_cfgp2p_is_p2p_ie(&ie_buf[pos-2], NULL, 0) || + wl_cfgp2p_is_wfd_ie(&ie_buf[pos-2], NULL, 0))) { CFGP2P_INFO(("DELELED ID : %d, Len : %d , OUI :" "%02x:%02x:%02x\n", ie_id, ie_len, ie_buf[pos], ie_buf[pos+1], ie_buf[pos+2])); @@ -979,7 +984,8 @@ wl_cfgp2p_set_management_ie(struct wl_priv *wl, struct net_device *ndev, s32 bss ie_len = ie_buf[pos++]; if ((ie_id == DOT11_MNG_VS_ID) && (wl_cfgp2p_is_wps_ie(&ie_buf[pos-2], NULL, 0) || - wl_cfgp2p_is_p2p_ie(&ie_buf[pos-2], NULL, 0))) { + wl_cfgp2p_is_p2p_ie(&ie_buf[pos-2], NULL, 0) || + wl_cfgp2p_is_wfd_ie(&ie_buf[pos-2], NULL, 0))) { CFGP2P_INFO(("ADDED ID : %d, Len : %d , OUI :" "%02x:%02x:%02x\n", ie_id, ie_len, ie_buf[pos], ie_buf[pos+1], ie_buf[pos+2])); @@ -1089,6 +1095,18 @@ wl_cfgp2p_find_p2pie(u8 *parse, u32 len) } return NULL; } +wifi_wfd_ie_t * +wl_cfgp2p_find_wfdie(u8 *parse, u32 len) +{ + bcm_tlv_t *ie; + + while ((ie = bcm_parse_tlvs(parse, (int)len, DOT11_MNG_VS_ID))) { + if (wl_cfgp2p_is_wfd_ie((uint8*)ie, &parse, &len)) { + return (wifi_wfd_ie_t *)ie; + } + } + return NULL; +} static s32 wl_cfgp2p_vndr_ie(struct wl_priv *wl, struct net_device *ndev, s32 bssidx, s32 pktflag, diff --git a/drivers/net/wireless/bcmdhd/wl_cfgp2p.h b/drivers/net/wireless/bcmdhd/wl_cfgp2p.h index be497c3e2426..668198d31a2e 100644 --- a/drivers/net/wireless/bcmdhd/wl_cfgp2p.h +++ b/drivers/net/wireless/bcmdhd/wl_cfgp2p.h @@ -30,7 +30,7 @@ struct wl_priv; extern u32 wl_dbg_level; - +typedef struct wifi_p2p_ie wifi_wfd_ie_t; /* Enumeration of the usages of the BSSCFGs used by the P2P Library. Do not * confuse this with a bsscfg index. This value is an index into the * saved_ie[] array of structures which in turn contains a bsscfg index field. @@ -191,6 +191,9 @@ wl_cfgp2p_find_wpsie(u8 *parse, u32 len); extern wifi_p2p_ie_t * wl_cfgp2p_find_p2pie(u8 *parse, u32 len); +extern wifi_wfd_ie_t * +wl_cfgp2p_find_wfdie(u8 *parse, u32 len); + extern s32 wl_cfgp2p_set_management_ie(struct wl_priv *wl, struct net_device *ndev, s32 bssidx, s32 pktflag, const u8 *vndr_ie, u32 vndr_ie_len); -- cgit v1.2.3