bcmdhd wifi: update to 1.201.59.4

This commit is contained in:
hwg 2015-06-01 15:54:19 +08:00
parent 94dfc90f19
commit a9f10c0192
13 changed files with 366 additions and 199 deletions

View File

@ -67,7 +67,7 @@ DHDCFLAGS += -DCUSTOMER_HW -DDHD_OF_SUPPORT -DGET_CUSTOM_MAC_ENABLE
#DHDCFLAGS += -DBCMWAPI_WPI -DBCMWAPI_WAI
#endif
DHDCFLAGS += -DBAND_AG
#DHDCFLAGS += -DBAND_AG
ifeq ($(CONFIG_DHD_USE_STATIC_BUF),y)
# add dhd_static_buf to kernel image build
@ -83,7 +83,7 @@ ifneq ($(CONFIG_CFG80211),)
bcmdhd-objs += wl_cfg80211.o wl_cfgp2p.o wl_linux_mon.o wl_cfg_btcoex.o
bcmdhd-objs += dhd_cfg80211.o dhd_cfg_vendor.o
DHDCFLAGS += -DWL_CFG80211 -DWLP2P -DWL_CFG80211_STA_EVENT -DWL_ENABLE_P2P_IF
#DHDCFLAGS += -DWL_IFACE_COMB_NUM_CHANNELS
DHDCFLAGS += -DWL_IFACE_COMB_NUM_CHANNELS
DHDCFLAGS += -DCUSTOM_ROAM_TRIGGER_SETTING=-65
DHDCFLAGS += -DCUSTOM_ROAM_DELTA_SETTING=15
DHDCFLAGS += -DCUSTOM_KEEP_ALIVE_SETTING=28000

View File

@ -121,7 +121,7 @@ enum dhd_op_flags {
#define DHD_SCAN_PASSIVE_TIME 130 /* ms: Embedded default Passive setting from DHD */
#ifndef POWERUP_MAX_RETRY
#define POWERUP_MAX_RETRY 3 /* how many times we retry to power up the chip */
#define POWERUP_MAX_RETRY 0//3 /* how many times we retry to power up the chip */
#endif
#ifndef POWERUP_WAIT_MS
#define POWERUP_WAIT_MS 2000 /* ms: time out in waiting wifi to come up */

View File

@ -2007,7 +2007,7 @@ dhd_pktfilter_offload_enable(dhd_pub_t * dhd, char *arg, int enable, int master_
rc = dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, buf, buf_len, TRUE, 0);
rc = rc >= 0 ? 0 : rc;
if (rc)
DHD_TRACE(("%s: failed to %s pktfilter %s, retcode = %d\n",
DHD_ERROR(("%s: failed to %s pktfilter %s, retcode = %d\n",
__FUNCTION__, enable?"enable":"disable", arg, rc));
else
DHD_TRACE(("%s: successfully %s pktfilter %s\n",
@ -2151,7 +2151,7 @@ dhd_pktfilter_offload_set(dhd_pub_t * dhd, char *arg)
rc = rc >= 0 ? 0 : rc;
if (rc)
DHD_TRACE(("%s: failed to add pktfilter %s, retcode = %d\n",
DHD_ERROR(("%s: failed to add pktfilter %s, retcode = %d\n",
__FUNCTION__, arg, rc));
else
DHD_TRACE(("%s: successfully added pktfilter %s\n",

View File

@ -14,25 +14,25 @@
#include <dhd_config.h>
#include <dhd_dbg.h>
/* message levels */
/* message levels */
#define CONFIG_ERROR_LEVEL 0x0001
#define CONFIG_TRACE_LEVEL 0x0002
uint config_msg_level = CONFIG_ERROR_LEVEL;
#define CONFIG_ERROR(x) \
do { \
do { \
if (config_msg_level & CONFIG_ERROR_LEVEL) { \
printk(KERN_ERR "CONFIG-ERROR) "); \
printk x; \
} \
} while (0)
printk x; \
} \
} while (0)
#define CONFIG_TRACE(x) \
do { \
do { \
if (config_msg_level & CONFIG_TRACE_LEVEL) { \
printk(KERN_ERR "CONFIG-TRACE) "); \
printk x; \
} \
printk x; \
} \
} while (0)
#define MAXSZ_BUF 1000
@ -58,6 +58,7 @@ uint config_msg_level = CONFIG_ERROR_LEVEL;
#define BCM43241B4_CHIP_REV 5
#define BCM4335A0_CHIP_REV 2
#define BCM4339A0_CHIP_REV 1
#define BCM43455C0_CHIP_REV 6
#define BCM4354A1_CHIP_REV 1
#define BCM4356A2_CHIP_REV 2
@ -124,6 +125,13 @@ const static char *bcm4339a0_ag_fw_name[] = {
"fw_bcm4339a0_ag_mfg.bin"
};
const static char *bcm43455c0_ag_fw_name[] = {
"fw_bcm43455c0_ag.bin",
"fw_bcm43455c0_ag_apsta.bin",
"fw_bcm43455c0_ag_p2p.bin",
"fw_bcm43455c0_ag_mfg.bin"
};
const static char *bcm4354a1_ag_fw_name[] = {
"fw_bcm4354a1_ag.bin",
"fw_bcm4354a1_ag_apsta.bin",
@ -149,11 +157,11 @@ const static char *bcm4356a2_pcie_ag_fw_name[] = {
};
#endif
#define htod32(i) i
#define htod16(i) i
#define dtoh32(i) i
#define dtoh16(i) i
#define htodchanspec(i) i
#define htod32(i) i
#define htod16(i) i
#define dtoh32(i) i
#define dtoh16(i) i
#define htodchanspec(i) i
#define dtohchanspec(i) i
#ifdef BCMSDIO
@ -173,6 +181,18 @@ dhd_conf_free_mac_list(wl_mac_list_ctrl_t *mac_list)
mac_list->count = 0;
}
void
dhd_conf_free_chip_nv_path_list(wl_chip_nv_path_list_ctrl_t *chip_nv_list)
{
CONFIG_TRACE(("%s called\n", __FUNCTION__));
if (chip_nv_list->m_chip_nv_path_head) {
CONFIG_TRACE(("%s Free %p\n", __FUNCTION__, chip_nv_list->m_chip_nv_path_head));
kfree(chip_nv_list->m_chip_nv_path_head);
}
chip_nv_list->count = 0;
}
#if defined(HW_OOB)
void
dhd_conf_set_hw_oob_intr(bcmsdh_info_t *sdh, uint chip)
@ -463,6 +483,10 @@ dhd_conf_set_fw_name_by_chip(dhd_pub_t *dhd, char *fw_path)
if (chiprev == BCM4335A0_CHIP_REV)
strcpy(&fw_path[i+1], bcm4339a0_ag_fw_name[fw_type]);
break;
case BCM4345_CHIP_ID:
if (chiprev == BCM43455C0_CHIP_REV)
strcpy(&fw_path[i+1], bcm43455c0_ag_fw_name[fw_type]);
break;
case BCM4339_CHIP_ID:
if (chiprev == BCM4339A0_CHIP_REV)
strcpy(&fw_path[i+1], bcm4339a0_ag_fw_name[fw_type]);
@ -485,6 +509,49 @@ dhd_conf_set_fw_name_by_chip(dhd_pub_t *dhd, char *fw_path)
printf("%s: firmware_path=%s\n", __FUNCTION__, fw_path);
}
void
dhd_conf_set_nv_name_by_chip(dhd_pub_t *dhd, char *nv_path)
{
int matched=-1;
uint chip, chiprev;
int i;
chip = dhd->conf->chip;
chiprev = dhd->conf->chiprev;
for (i=0; i<dhd->conf->nv_by_chip.count; i++) {
if (chip==dhd->conf->nv_by_chip.m_chip_nv_path_head[i].chip &&
chiprev==dhd->conf->nv_by_chip.m_chip_nv_path_head[i].chiprev) {
matched = i;
break;
}
}
if (matched < 0)
return;
if (nv_path[0] == '\0') {
#ifdef CONFIG_BCMDHD_NVRAM_PATH
bcm_strncpy_s(nv_path, MOD_PARAM_PATHLEN-1, CONFIG_BCMDHD_NVRAM_PATH, MOD_PARAM_PATHLEN-1);
if (nv_path[0] == '\0')
#endif
{
printf("nvram path is null\n");
return;
}
}
/* find out the last '/' */
i = strlen(nv_path);
while (i>0){
if (nv_path[i] == '/') break;
i--;
}
strcpy(&nv_path[i+1], dhd->conf->nv_by_chip.m_chip_nv_path_head[matched].name);
printf("%s: nvram_path=%s\n", __FUNCTION__, nv_path);
}
void
dhd_conf_set_conf_path_by_nv_path(dhd_pub_t *dhd, char *conf_path, char *nv_path)
{
@ -582,10 +649,10 @@ dhd_conf_fix_country(dhd_pub_t *dhd)
if (!(dhd && dhd->conf)) {
return bcmerror;
}
memset(valid_chan_list, 0, sizeof(valid_chan_list));
list = (wl_uint32_list_t *)(void *) valid_chan_list;
list->count = htod32(WL_NUMCHANNELS);
list = (wl_uint32_list_t *)(void *) valid_chan_list;
list->count = htod32(WL_NUMCHANNELS);
if ((bcmerror = dhd_wl_ioctl_cmd(dhd, WLC_GET_VALID_CHANNELS, valid_chan_list, sizeof(valid_chan_list), FALSE, 0)) < 0) {
CONFIG_ERROR(("%s: get channels failed with %d\n", __FUNCTION__, bcmerror));
}
@ -718,25 +785,25 @@ dhd_conf_get_wme(dhd_pub_t *dhd, edcf_acparam_t *acp)
memcpy((char*)acp, iovbuf, sizeof(edcf_acparam_t)*AC_COUNT);
acparam = &acp[AC_BK];
CONFIG_TRACE(("%s: BK: aci %d aifsn %d ecwmin %d ecwmax %d size %zu\n", __FUNCTION__,
CONFIG_TRACE(("%s: BK: aci %d aifsn %d ecwmin %d ecwmax %d size %d\n", __FUNCTION__,
acparam->ACI, acparam->ACI&EDCF_AIFSN_MASK,
acparam->ECW&EDCF_ECWMIN_MASK, (acparam->ECW&EDCF_ECWMAX_MASK)>>EDCF_ECWMAX_SHIFT,
sizeof(acp)));
(int)sizeof(acp)));
acparam = &acp[AC_BE];
CONFIG_TRACE(("%s: BE: aci %d aifsn %d ecwmin %d ecwmax %d size %zu\n", __FUNCTION__,
CONFIG_TRACE(("%s: BE: aci %d aifsn %d ecwmin %d ecwmax %d size %d\n", __FUNCTION__,
acparam->ACI, acparam->ACI&EDCF_AIFSN_MASK,
acparam->ECW&EDCF_ECWMIN_MASK, (acparam->ECW&EDCF_ECWMAX_MASK)>>EDCF_ECWMAX_SHIFT,
sizeof(acp)));
(int)sizeof(acp)));
acparam = &acp[AC_VI];
CONFIG_TRACE(("%s: VI: aci %d aifsn %d ecwmin %d ecwmax %d size %zu\n", __FUNCTION__,
CONFIG_TRACE(("%s: VI: aci %d aifsn %d ecwmin %d ecwmax %d size %d\n", __FUNCTION__,
acparam->ACI, acparam->ACI&EDCF_AIFSN_MASK,
acparam->ECW&EDCF_ECWMIN_MASK, (acparam->ECW&EDCF_ECWMAX_MASK)>>EDCF_ECWMAX_SHIFT,
sizeof(acp)));
(int)sizeof(acp)));
acparam = &acp[AC_VO];
CONFIG_TRACE(("%s: VO: aci %d aifsn %d ecwmin %d ecwmax %d size %zu\n", __FUNCTION__,
CONFIG_TRACE(("%s: VO: aci %d aifsn %d ecwmin %d ecwmax %d size %d\n", __FUNCTION__,
acparam->ACI, acparam->ACI&EDCF_AIFSN_MASK,
acparam->ECW&EDCF_ECWMIN_MASK, (acparam->ECW&EDCF_ECWMAX_MASK)>>EDCF_ECWMAX_SHIFT,
sizeof(acp)));
(int)sizeof(acp)));
return;
}
@ -769,10 +836,10 @@ dhd_conf_update_wme(dhd_pub_t *dhd, edcf_acparam_t *acparam_cur, int aci)
acp->ECW = ((ecwmax << EDCF_ECWMAX_SHIFT) & EDCF_ECWMAX_MASK) | (acp->ECW & EDCF_ECWMIN_MASK);
acp->ECW = ((acp->ECW & EDCF_ECWMAX_MASK) | (ecwmin & EDCF_ECWMIN_MASK));
CONFIG_TRACE(("%s: mod aci %d aifsn %d ecwmin %d ecwmax %d size %zu\n", __FUNCTION__,
CONFIG_TRACE(("%s: mod aci %d aifsn %d ecwmin %d ecwmax %d size %d\n", __FUNCTION__,
acp->ACI, acp->ACI&EDCF_AIFSN_MASK,
acp->ECW&EDCF_ECWMIN_MASK, (acp->ECW&EDCF_ECWMAX_MASK)>>EDCF_ECWMAX_SHIFT,
sizeof(edcf_acparam_t)));
(int)sizeof(edcf_acparam_t)));
/*
* Now use buf as an output buffer.
@ -1053,6 +1120,16 @@ dhd_conf_set_disable_proptx(dhd_pub_t *dhd)
disable_proptx = dhd->conf->disable_proptx;
}
int
dhd_conf_get_pm(void *context)
{
dhd_pub_t *dhd = context;
if (dhd && dhd->conf)
return dhd->conf->pm;
return -1;
}
unsigned int
process_config_vars(char *varbuf, unsigned int len, char *pickbuf, char *param)
{
@ -1173,8 +1250,8 @@ dhd_conf_read_log_level(dhd_pub_t *dhd, char *bufp, uint len)
dhd_console_ms = (int)simple_strtol(pick, NULL, 0);
printf("%s: dhd_console_ms = 0x%X\n", __FUNCTION__, dhd_console_ms);
}
}
}
void
dhd_conf_read_wme_ac_params(dhd_pub_t *dhd, char *bufp, uint len)
{
@ -1365,6 +1442,7 @@ dhd_conf_read_config(dhd_pub_t *dhd, char *conf_path)
bool conf_file_exists;
wl_mac_list_t *mac_list;
wl_mac_range_t *mac_range;
wl_chip_nv_path_t *chip_nv_path;
struct dhd_conf *conf = dhd->conf;
conf_file_exists = ((conf_path != NULL) && (conf_path[0] != '\0'));
@ -1399,7 +1477,7 @@ dhd_conf_read_config(dhd_pub_t *dhd, char *conf_path)
/* Process log_level */
dhd_conf_read_log_level(dhd, bufp, len);
dhd_conf_read_roam_params(dhd, bufp, len);
dhd_conf_read_wme_ac_params(dhd, bufp, len);
dhd_conf_read_wme_ac_params(dhd, bufp, len);
/* Process fw_by_mac */
memset(pick, 0, MAXSZ_BUF);
@ -1481,6 +1559,31 @@ dhd_conf_read_config(dhd_pub_t *dhd, char *conf_path)
}
}
/* Process nv_by_chip */
memset(pick, 0, MAXSZ_BUF);
len_val = process_config_vars(bufp, len, pick, "nv_by_chip=");
if (len_val) {
pick_tmp = pick;
pch = bcmstrtok(&pick_tmp, " ", 0);
conf->nv_by_chip.count = (uint32)simple_strtol(pch, NULL, 0);
if (!(chip_nv_path = kmalloc(sizeof(wl_mac_list_t)*conf->nv_by_chip.count, GFP_KERNEL))) {
conf->nv_by_chip.count = 0;
CONFIG_ERROR(("%s: kmalloc failed\n", __FUNCTION__));
}
printf("%s: nv_by_chip_count=%d\n", __FUNCTION__, conf->nv_by_chip.count);
conf->nv_by_chip.m_chip_nv_path_head = chip_nv_path;
for (i=0; i<conf->nv_by_chip.count; i++) {
pch = bcmstrtok(&pick_tmp, " ", 0);
chip_nv_path[i].chip = (uint32)simple_strtol(pch, NULL, 0);
pch = bcmstrtok(&pick_tmp, " ", 0);
chip_nv_path[i].chiprev = (uint32)simple_strtol(pch, NULL, 0);
pch = bcmstrtok(&pick_tmp, " ", 0);
strcpy(chip_nv_path[i].name, pch);
printf("%s: chip=0x%x, chiprev=%d, name=%s\n", __FUNCTION__,
chip_nv_path[i].chip, chip_nv_path[i].chiprev, chip_nv_path[i].name);
}
}
/* Process band */
memset(pick, 0, MAXSZ_BUF);
len_val = process_config_vars(bufp, len, pick, "band=");
@ -1647,7 +1750,7 @@ dhd_conf_read_config(dhd_pub_t *dhd, char *conf_path)
len_val = process_config_vars(bufp, len, pick, "bus:txglom=");
if (len_val) {
conf->bus_txglom = (int)simple_strtol(pick, NULL, 10);
printf("%s: bus:txglom = %d\n", __FUNCTION__, conf->bus_txglom);
printf("%s: bus:txglom = %d\n", __FUNCTION__, conf->bus_txglom);
}
/* Process ampdu_ba_wsize parameters */
@ -1741,7 +1844,7 @@ dhd_conf_read_config(dhd_pub_t *dhd, char *conf_path)
conf->bus_rxglom = FALSE;
else
conf->bus_rxglom = TRUE;
printf("%s: bus_rxglom = %d\n", __FUNCTION__, conf->bus_rxglom);
printf("%s: bus:rxglom = %d\n", __FUNCTION__, conf->bus_rxglom);
}
/* Process deepsleep parameters */
@ -1755,6 +1858,14 @@ dhd_conf_read_config(dhd_pub_t *dhd, char *conf_path)
printf("%s: deepsleep = %d\n", __FUNCTION__, conf->deepsleep);
}
/* Process PM parameters */
memset(pick, 0, MAXSZ_BUF);
len_val = process_config_vars(bufp, len, pick, "PM=");
if (len_val) {
conf->pm = (int)simple_strtol(pick, NULL, 10);
printf("%s: PM = %d\n", __FUNCTION__, conf->pm);
}
bcmerror = 0;
} else {
CONFIG_ERROR(("%s: error reading config file: %d\n", __FUNCTION__, len));
@ -1810,6 +1921,7 @@ dhd_conf_preinit(dhd_pub_t *dhd)
#ifdef BCMSDIO
dhd_conf_free_mac_list(&conf->fw_by_mac);
dhd_conf_free_mac_list(&conf->nv_by_mac);
dhd_conf_free_chip_nv_path_list(&conf->nv_by_chip);
#endif
conf->band = WLC_BAND_AUTO;
conf->mimo_bw_cap = -1;
@ -1844,9 +1956,9 @@ dhd_conf_preinit(dhd_pub_t *dhd)
conf->roam_delta[0] = 15;
#endif
conf->roam_delta[1] = WLC_BAND_ALL;
#ifdef FULL_ROAMING_SCAN_PERIOD_60_SEC
#ifdef FULL_ROAMING_SCAN_PERIOD_60_SEC
conf->fullroamperiod = 60;
#else /* FULL_ROAMING_SCAN_PERIOD_60_SEC */
#else /* FULL_ROAMING_SCAN_PERIOD_60_SEC */
conf->fullroamperiod = 120;
#endif /* FULL_ROAMING_SCAN_PERIOD_60_SEC */
#ifdef CUSTOM_KEEP_ALIVE_SETTING
@ -1877,17 +1989,17 @@ dhd_conf_preinit(dhd_pub_t *dhd)
conf->dpc_cpucore = 0;
conf->frameburst = -1;
conf->deepsleep = FALSE;
conf->pm = -1;
if ((conf->chip == BCM43362_CHIP_ID) || (conf->chip == BCM4330_CHIP_ID)) {
conf->disable_proptx = 1;
conf->use_rxchain = 0;
}
if (conf->chip == BCM43430_CHIP_ID) {
conf->use_rxchain = 0;
conf->bus_rxglom = FALSE;
}
}
if (conf->chip == BCM4339_CHIP_ID) {
conf->txbf = 1;
}
if (conf->chip == BCM4345_CHIP_ID) {
conf->txbf = 1;
}
if (conf->chip == BCM4354_CHIP_ID) {
conf->txbf = 1;
}
@ -1904,6 +2016,7 @@ dhd_conf_reset(dhd_pub_t *dhd)
#ifdef BCMSDIO
dhd_conf_free_mac_list(&dhd->conf->fw_by_mac);
dhd_conf_free_mac_list(&dhd->conf->nv_by_mac);
dhd_conf_free_chip_nv_path_list(&dhd->conf->nv_by_chip);
#endif
memset(dhd->conf, 0, sizeof(dhd_conf_t));
return 0;
@ -1946,6 +2059,7 @@ dhd_conf_detach(dhd_pub_t *dhd)
#ifdef BCMSDIO
dhd_conf_free_mac_list(&dhd->conf->fw_by_mac);
dhd_conf_free_mac_list(&dhd->conf->nv_by_mac);
dhd_conf_free_chip_nv_path_list(&dhd->conf->nv_by_chip);
#endif
MFREE(dhd->osh, dhd->conf, sizeof(dhd_conf_t));
}

View File

@ -35,6 +35,19 @@ typedef struct wl_mac_list_ctrl {
struct wl_mac_list *m_mac_list_head;
} wl_mac_list_ctrl_t;
/* chip_nv_path */
typedef struct wl_chip_nv_path {
uint chip;
uint chiprev;
char name[MOD_PARAM_PATHLEN]; /* path */
} wl_chip_nv_path_t;
/* chip_nv_path list head */
typedef struct wl_chip_nv_path_list_ctrl {
int count;
struct wl_chip_nv_path *m_chip_nv_path_head;
} wl_chip_nv_path_list_ctrl_t;
/* channel list */
typedef struct wl_channel_list {
/* in - # of channels, out - # of entries */
@ -74,6 +87,7 @@ typedef struct dhd_conf {
uint chiprev; /* chip revision */
wl_mac_list_ctrl_t fw_by_mac; /* Firmware auto selection by MAC */
wl_mac_list_ctrl_t nv_by_mac; /* NVRAM auto selection by MAC */
wl_chip_nv_path_list_ctrl_t nv_by_chip; /* NVRAM auto selection by chip */
uint band; /* Band, b:2.4G only, otherwise for auto */
int mimo_bw_cap; /* Bandwidth, 0:HT20ALL, 1: HT40ALL, 2:HT20IN2G_HT40PIN5G */
wl_country_t cspec; /* Country */
@ -109,6 +123,7 @@ typedef struct dhd_conf {
int dpc_cpucore;
int frameburst;
bool deepsleep;
int pm;
} dhd_conf_t;
#ifdef BCMSDIO
@ -120,6 +135,7 @@ void dhd_conf_set_hw_oob_intr(bcmsdh_info_t *sdh, uint chip);
#endif
#endif
void dhd_conf_set_fw_name_by_chip(dhd_pub_t *dhd, char *fw_path);
void dhd_conf_set_nv_name_by_chip(dhd_pub_t *dhd, char *nv_path);
void dhd_conf_set_conf_path_by_nv_path(dhd_pub_t *dhd, char *conf_path, char *nv_path);
int dhd_conf_set_band(dhd_pub_t *dhd);
uint dhd_conf_get_band(dhd_pub_t *dhd);
@ -150,6 +166,7 @@ int dhd_conf_read_config(dhd_pub_t *dhd, char *conf_path);
int dhd_conf_set_chiprev(dhd_pub_t *dhd, uint chip, uint chiprev);
uint dhd_conf_get_chip(void *context);
uint dhd_conf_get_chiprev(void *context);
int dhd_conf_get_pm(void *context);
int dhd_conf_preinit(dhd_pub_t *dhd);
int dhd_conf_reset(dhd_pub_t *dhd);
int dhd_conf_attach(dhd_pub_t *dhd);

View File

@ -1635,6 +1635,10 @@ static int dhd_set_suspend(int value, dhd_pub_t *dhd)
/* set specific cpucore */
dhd_set_cpucore(dhd, TRUE);
#endif /* CUSTOM_SET_CPUCORE */
#ifndef SUPPORT_PM2_ONLY
if (dhd->conf->pm >= 0)
power_mode = dhd->conf->pm;
#endif /* SUPPORT_PM2_ONLY */
if (dhd->up) {
if (value && dhd->in_suspend) {
#ifdef PKT_FILTER_SUPPORT
@ -2397,7 +2401,7 @@ dhd_os_wlfc_unblock(dhd_pub_t *pub)
#endif /* PROP_TXSTATUS */
#ifdef DHD_RX_DUMP
#if defined(DHD_RX_DUMP) || defined(DHD_TX_DUMP)
typedef struct {
uint16 type;
const char *str;
@ -2425,17 +2429,19 @@ static const char *_get_packet_type_str(uint16 type)
return packet_type_info[n].str;
}
#endif /* DHD_RX_DUMP */
#endif /* DHD_RX_DUMP || DHD_TX_DUMP */
#if defined(DHD_8021X_DUMP)
#if defined(DHD_TX_DUMP)
void
dhd_tx_dump(osl_t *osh, void *pkt)
{
uint8 *dump_data;
uint16 protocol;
struct ether_header *eh;
dump_data = PKTDATA(osh, pkt);
protocol = (dump_data[12] << 8) | dump_data[13];
eh = (struct ether_header *) dump_data;
protocol = ntoh16(eh->ether_type);
DHD_ERROR(("TX DUMP - %s\n", _get_packet_type_str(protocol)));
@ -2444,22 +2450,22 @@ dhd_tx_dump(osl_t *osh, void *pkt)
dump_data[14], dump_data[15], dump_data[30]));
}
#if defined(DHD_TX_DUMP) && defined(DHD_TX_FULL_DUMP)
#if defined(DHD_TX_FULL_DUMP)
{
int i;
uint datalen;
datalen = PKTLEN(osh, pkt);
for (i = 0; i < (datalen - 4); i++) {
for (i = 0; i < datalen; i++) {
DHD_ERROR(("%02X ", dump_data[i]));
if ((i & 15) == 15)
printk("\n");
}
DHD_ERROR(("\n"));
}
#endif /* DHD_TX_DUMP && DHD_TX_FULL_DUMP */
#endif /* DHD_TX_FULL_DUMP */
}
#endif /* DHD_8021X_DUMP */
#endif /* DHD_TX_DUMP */
int BCMFASTPATH
dhd_sendpkt(dhd_pub_t *dhdp, int ifidx, void *pktbuf)
@ -2523,6 +2529,9 @@ dhd_sendpkt(dhd_pub_t *dhdp, int ifidx, void *pktbuf)
return ret;
}
#endif
#if defined(DHD_TX_DUMP)
dhd_tx_dump(dhdp->osh, pktbuf);
#endif
#ifdef PROP_TXSTATUS
if (dhd_wlfc_is_supported(dhdp)) {
@ -2547,9 +2556,7 @@ dhd_sendpkt(dhd_pub_t *dhdp, int ifidx, void *pktbuf)
#ifdef WLMEDIA_HTSF
dhd_htsf_addtxts(dhdp, pktbuf);
#endif
#if defined(DHD_8021X_DUMP)
dhd_tx_dump(dhdp->osh, pktbuf);
#endif
#ifdef PROP_TXSTATUS
{
if (dhd_wlfc_commit_packets(dhdp, (f_commitpkt_t)dhd_bus_txdata,
@ -5187,7 +5194,6 @@ bool dhd_update_fw_nv_path(dhd_info_t *dhdinfo)
const char *conf = NULL;
char firmware[100] = {0};
char nvram[100] = {0};
//char config[100] = "";
wifi_adapter_info_t *adapter = dhdinfo->adapter;
@ -6321,6 +6327,8 @@ dhd_preinit_ioctls(dhd_pub_t *dhd)
dhd_conf_set_lpc(dhd);
/* Set PowerSave mode */
if (dhd->conf->pm >= 0)
power_mode = dhd->conf->pm;
dhd_wl_ioctl_cmd(dhd, WLC_SET_PM, (char *)&power_mode, sizeof(power_mode), TRUE, 0);
/* Match Host and Dongle rx alignment */
@ -10404,5 +10412,8 @@ EXPORT_SYMBOL(SDA_function4RecvDone);
void *dhd_get_pub(struct net_device *dev)
{
dhd_info_t *dhdinfo = *(dhd_info_t **)netdev_priv(dev);
return (void *)&dhdinfo->pub;
if (dhdinfo)
return (void *)&dhdinfo->pub;
else
return NULL;
}

View File

@ -508,7 +508,8 @@ dhdpcie_dongle_attach(dhd_bus_t *bus)
bus->dongle_ram_base = CR4_4360_RAM_BASE;
break;
case BCM4345_CHIP_ID:
bus->dongle_ram_base = CR4_4345_RAM_BASE;
bus->dongle_ram_base = (bus->sih->chiprev < 6) /* changed at 4345C0 */
? CR4_4345_LT_C0_RAM_BASE : CR4_4345_GE_C0_RAM_BASE;
break;
case BCM43602_CHIP_ID:
bus->dongle_ram_base = CR4_43602_RAM_BASE;

View File

@ -1563,10 +1563,6 @@ dhd_bus_txdata(struct dhd_bus *bus, void *pkt)
int ret = BCME_ERROR;
osl_t *osh;
uint datalen, prec;
#if defined(DHD_TX_DUMP)
uint8 *dump_data;
uint16 protocol;
#endif /* DHD_TX_DUMP */
DHD_TRACE(("%s: Enter\n", __FUNCTION__));
@ -1589,31 +1585,6 @@ dhd_bus_txdata(struct dhd_bus *bus, void *pkt)
BCM_REFERENCE(datalen);
#endif /* SDTEST */
#if defined(DHD_TX_DUMP)
dump_data = PKTDATA(osh, pkt);
dump_data += 4; /* skip 4 bytes header */
protocol = (dump_data[12] << 8) | dump_data[13];
if (protocol == ETHER_TYPE_802_1X) {
DHD_ERROR(("ETHER_TYPE_802_1X [TX]: ver %d, type %d, replay %d\n",
dump_data[14], dump_data[15], dump_data[30]));
}
#endif /* DHD_TX_DUMP */
#if defined(DHD_TX_DUMP) && defined(DHD_TX_FULL_DUMP)
{
int i;
DHD_ERROR(("TX DUMP\n"));
for (i = 0; i < (datalen - 4); i++) {
DHD_ERROR(("%02X ", dump_data[i]));
if ((i & 15) == 15)
printk("\n");
}
DHD_ERROR(("\n"));
}
#endif /* DHD_TX_DUMP && DHD_TX_FULL_DUMP */
prec = PRIO2PREC((PKTPRIO(pkt) & PRIOMASK));
/* Check for existing queue, current flow-control, pending event, or pending clock */
@ -7423,7 +7394,8 @@ dhdsdio_probe_attach(struct dhd_bus *bus, osl_t *osh, void *sdh, void *regsva,
bus->dongle_ram_base = CR4_4360_RAM_BASE;
break;
case BCM4345_CHIP_ID:
bus->dongle_ram_base = CR4_4345_RAM_BASE;
bus->dongle_ram_base = (bus->sih->chiprev < 6) /* from 4345C0 */
? CR4_4345_LT_C0_RAM_BASE : CR4_4345_GE_C0_RAM_BASE;
break;
case BCM4349_CHIP_GRPID:
bus->dongle_ram_base = CR4_4349_RAM_BASE;
@ -7661,6 +7633,7 @@ dhdsdio_download_firmware(struct dhd_bus *bus, osl_t *osh, void *sdh)
dhd_conf_preinit(bus->dhd);
dhd_conf_read_config(bus->dhd, bus->dhd->conf_path);
dhd_conf_set_fw_name_by_chip(bus->dhd, bus->fw_path);
dhd_conf_set_nv_name_by_chip(bus->dhd, bus->nv_path);
dhd_conf_set_fw_name_by_mac(bus->dhd, bus->sdh, bus->fw_path);
dhd_conf_set_nv_name_by_mac(bus->dhd, bus->sdh, bus->nv_path);

View File

@ -25,6 +25,6 @@
#define EPI_VERSION_DEV 1.201.59
/* Driver Version String, ASCII, 32 chars max */
#define EPI_VERSION_STR "1.201.59.3 (r506368)"
#define EPI_VERSION_STR "1.201.59.4 (r506368)"
#endif /* _epivers_h_ */

View File

@ -2824,7 +2824,8 @@ typedef volatile struct {
#define CCTRL2_4335_PMUWAKE (1 << 31)
#define PATCHTBL_SIZE (0x800)
#define CR4_4335_RAM_BASE (0x180000)
#define CR4_4345_RAM_BASE (0x1b0000)
#define CR4_4345_LT_C0_RAM_BASE (0x1b0000)
#define CR4_4345_GE_C0_RAM_BASE (0x198000)
#define CR4_4349_RAM_BASE (0x180000)
#define CR4_4350_RAM_BASE (0x180000)
#define CR4_4360_RAM_BASE (0x0)

View File

@ -2989,12 +2989,13 @@ typedef struct wl_pkt_decrypter {
* that indicates which bits within the pattern should be matched.
*/
typedef struct wl_pkt_filter_pattern {
union {
// terence 20150525: fix pkt filter error -14 in 64bit OS
// union {
uint32 offset; /* Offset within received packet to start pattern matching.
* Offset '0' is the first byte of the ethernet header.
*/
wl_pkt_decrypter_t* decrypt_ctx; /* Decrypt context */
};
// wl_pkt_decrypter_t* decrypt_ctx; /* Decrypt context */
// };
uint32 size_bytes; /* Size of the pattern. Bitmask must be the same size. */
uint8 mask_and_pattern[1]; /* Variable length mask and pattern data. mask starts
* at offset 0. Pattern immediately follows mask.

View File

@ -5302,6 +5302,7 @@ wl_cfg80211_set_power_mgmt(struct wiphy *wiphy, struct net_device *dev,
s32 err = 0;
struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
struct net_info *_net_info = wl_get_netinfo_by_netdev(cfg, dev);
dhd_pub_t *dhd = (dhd_pub_t *)(cfg->pub);
RETURN_EIO_IF_NOT_UP(cfg);
WL_DBG(("Enter\n"));
@ -5319,6 +5320,8 @@ wl_cfg80211_set_power_mgmt(struct wiphy *wiphy, struct net_device *dev,
dev->name, _net_info->pm_block));
pm = PM_OFF;
}
if (enabled && dhd_conf_get_pm(dhd) >= 0)
pm = dhd_conf_get_pm(dhd);
pm = htod32(pm);
WL_DBG(("%s:power save %s\n", dev->name, (pm ? "enabled" : "disabled")));
err = wldev_ioctl(dev, WLC_SET_PM, &pm, sizeof(pm), true);
@ -11626,6 +11629,7 @@ static s32 wl_notifier_change_state(struct bcm_cfg80211 *cfg, struct net_info *_
u32 chan = 0;
struct net_info *iter, *next;
struct net_device *primary_dev = bcmcfg_to_prmry_ndev(cfg);
dhd_pub_t *dhd = (dhd_pub_t *)(cfg->pub);
WL_DBG(("Enter state %d set %d _net_info->pm_restore %d iface %s\n",
state, set, _net_info->pm_restore, _net_info->ndev->name));
@ -11649,6 +11653,8 @@ static s32 wl_notifier_change_state(struct bcm_cfg80211 *cfg, struct net_info *_
*/
if (!_net_info->pm_block && (mode == WL_MODE_BSS)) {
_net_info->pm = PM_FAST;
if (dhd_conf_get_pm(dhd) >= 0)
_net_info->pm = dhd_conf_get_pm(dhd);
_net_info->pm_restore = true;
}
pm = PM_OFF;
@ -11668,6 +11674,8 @@ static s32 wl_notifier_change_state(struct bcm_cfg80211 *cfg, struct net_info *_
for_each_ndev(cfg, iter, next) {
if (!wl_get_drv_status(cfg, CONNECTED, iter->ndev))
continue;
if (pm != PM_OFF && dhd_conf_get_pm(dhd) >= 0)
pm = dhd_conf_get_pm(dhd);
if ((err = wldev_ioctl(iter->ndev, WLC_SET_PM, &pm,
sizeof(pm), true)) != 0) {
if (err == -ENODEV)
@ -11705,6 +11713,8 @@ static s32 wl_notifier_change_state(struct bcm_cfg80211 *cfg, struct net_info *_
for_each_ndev(cfg, iter, next) {
if (!wl_get_drv_status(cfg, CONNECTED, iter->ndev))
continue;
if (pm != PM_OFF && dhd_conf_get_pm(dhd) >= 0)
pm = dhd_conf_get_pm(dhd);
if ((err = wldev_ioctl(iter->ndev, WLC_SET_PM, &pm,
sizeof(pm), true)) != 0) {
if (err == -ENODEV)
@ -11742,6 +11752,8 @@ static s32 wl_notifier_change_state(struct bcm_cfg80211 *cfg, struct net_info *_
if (iter->pm_restore && iter->pm) {
WL_DBG(("%s:restoring power save %s\n",
iter->ndev->name, (iter->pm ? "enabled" : "disabled")));
if (iter->pm != PM_OFF && dhd_conf_get_pm(dhd) >= 0)
iter->pm = dhd_conf_get_pm(dhd);
err = wldev_ioctl(iter->ndev,
WLC_SET_PM, &iter->pm, sizeof(iter->pm), true);
if (unlikely(err)) {
@ -12118,7 +12130,7 @@ static void wl_wakeup_event(struct bcm_cfg80211 *cfg)
}
}
#if defined(P2PONEINT)
#if defined(P2PONEINT) || defined(WL_ENABLE_P2P_IF)
static int wl_is_p2p_event(struct wl_event_q *e)
{
struct bcm_cfg80211 *cfg = g_bcm_cfg;
@ -12165,7 +12177,7 @@ static int wl_is_p2p_event(struct wl_event_q *e)
return FALSE;
}
}
#endif
#endif
static s32 wl_event_handler(void *data)
{
@ -12220,7 +12232,9 @@ static s32 wl_event_handler(void *data)
#endif
}
#elif defined(WL_ENABLE_P2P_IF)
if (WL_IS_P2P_DEV_EVENT(e) && (cfg->p2p_net)) {
// terence 20150116: fix for p2p connection in kernel 3.4
// if (WL_IS_P2P_DEV_EVENT(e) && (cfg->p2p_net)) {
if ((wl_is_p2p_event(e) == TRUE) && (cfg->p2p_net)) {
cfgdev = cfg->p2p_net;
} else {
cfgdev = dhd_idx2net((struct dhd_pub *)(cfg->pub),
@ -12231,7 +12245,7 @@ static s32 wl_event_handler(void *data)
if (!cfgdev) {
#if defined(WL_CFG80211_P2P_DEV_IF)
cfgdev = bcmcfg_to_prmry_wdev(cfg);
#elif defined(WL_ENABLE_P2P_IF)
#else
cfgdev = bcmcfg_to_prmry_ndev(cfg);
#endif /* WL_CFG80211_P2P_DEV_IF */
}
@ -15302,6 +15316,7 @@ static void wl_cfg80211_work_handler(struct work_struct * work)
struct net_info *iter, *next;
s32 err = BCME_OK;
s32 pm = PM_FAST;
dhd_pub_t *dhd;
cfg = container_of(work, struct bcm_cfg80211, pm_enable_work.work);
WL_DBG(("Enter \n"));
@ -15312,6 +15327,9 @@ static void wl_cfg80211_work_handler(struct work_struct * work)
(wl_get_mode_by_netdev(cfg, iter->ndev) != WL_MODE_BSS))
continue;
if (iter->ndev) {
dhd = (dhd_pub_t *)(cfg->pub);
if (pm != PM_OFF && dhd_conf_get_pm(dhd) >= 0)
pm = dhd_conf_get_pm(dhd);
if ((err = wldev_ioctl(iter->ndev, WLC_SET_PM,
&pm, sizeof(pm), true)) != 0) {
if (err == -ENODEV)

View File

@ -22,6 +22,7 @@
typedef const struct si_pub si_t;
#include <wlioctl.h>
#include <wl_android.h>
/* message levels */
@ -599,9 +600,12 @@ wl_iw_set_freq(
chan = wf_mhz2channel(fwrq->m, sf);
}
WL_ERROR(("%s: chan=%d\n", __FUNCTION__, chan));
chan = htod32(chan);
if ((error = dev_wlc_ioctl(dev, WLC_SET_CHANNEL, &chan, sizeof(chan))))
if ((error = dev_wlc_ioctl(dev, WLC_SET_CHANNEL, &chan, sizeof(chan)))) {
WL_ERROR(("%s: WLC_DISASSOC failed (%d).\n", __FUNCTION__, error));
return error;
}
/* -EINPROGRESS: Call commit handler */
return -EINPROGRESS;
@ -993,6 +997,7 @@ wl_iw_set_wap(
if (ETHER_ISBCAST(awrq->sa_data) || ETHER_ISNULLADDR(awrq->sa_data)) {
scb_val_t scbval;
bzero(&scbval, sizeof(scb_val_t));
WL_ERROR(("%s: WLC_DISASSOC\n", __FUNCTION__));
if ((error = dev_wlc_ioctl(dev, WLC_DISASSOC, &scbval, sizeof(scb_val_t)))) {
WL_ERROR(("%s: WLC_DISASSOC failed (%d).\n", __FUNCTION__, error));
}
@ -1006,6 +1011,7 @@ wl_iw_set_wap(
WL_ERROR(("%s: WLC_REASSOC failed (%d).\n", __FUNCTION__, error));
return error;
}
WL_ERROR(("%s: join BSSID="MACSTR"\n", __FUNCTION__, MAC2STR((u8 *)awrq->sa_data)));
return 0;
}
@ -1085,6 +1091,7 @@ wl_iw_get_aplist(
wl_bss_info_t *bi = NULL;
int error, i;
uint buflen = dwrq->length;
int16 rssi;
WL_TRACE(("%s: SIOCGIWAPLIST\n", dev->name));
@ -1119,8 +1126,10 @@ wl_iw_get_aplist(
/* BSSID */
memcpy(addr[dwrq->length].sa_data, &bi->BSSID, ETHER_ADDR_LEN);
addr[dwrq->length].sa_family = ARPHRD_ETHER;
qual[dwrq->length].qual = rssi_to_qual(dtoh16(bi->RSSI));
qual[dwrq->length].level = 0x100 + dtoh16(bi->RSSI);
// terence 20150419: limit the max. rssi to -2 or the bss will be filtered out in android OS
rssi = MIN(dtoh16(bi->RSSI), RSSI_MAXVAL);
qual[dwrq->length].qual = rssi_to_qual(rssi);
qual[dwrq->length].level = 0x100 + rssi;
qual[dwrq->length].noise = 0x100 + bi->phy_noise;
/* Updated qual, level, and noise */
@ -1160,6 +1169,7 @@ wl_iw_iscan_get_aplist(
struct iw_quality qual[IW_MAX_AP];
wl_bss_info_t *bi = NULL;
int i;
int16 rssi;
WL_TRACE(("%s: SIOCGIWAPLIST\n", dev->name));
@ -1189,8 +1199,10 @@ wl_iw_iscan_get_aplist(
/* BSSID */
memcpy(addr[dwrq->length].sa_data, &bi->BSSID, ETHER_ADDR_LEN);
addr[dwrq->length].sa_family = ARPHRD_ETHER;
qual[dwrq->length].qual = rssi_to_qual(dtoh16(bi->RSSI));
qual[dwrq->length].level = 0x100 + dtoh16(bi->RSSI);
// terence 20150419: limit the max. rssi to -2 or the bss will be filtered out in android OS
rssi = MIN(dtoh16(bi->RSSI), RSSI_MAXVAL);
qual[dwrq->length].qual = rssi_to_qual(rssi);
qual[dwrq->length].level = 0x100 + rssi;
qual[dwrq->length].noise = 0x100 + bi->phy_noise;
/* Updated qual, level, and noise */
@ -1497,6 +1509,8 @@ wl_iw_get_scan(
int error, i, j;
char *event = extra, *end = extra + dwrq->length, *value;
uint buflen = dwrq->length;
int16 rssi;
int channel;
WL_TRACE(("%s: %s SIOCGIWSCAN\n", __FUNCTION__, dev->name));
@ -1531,12 +1545,11 @@ wl_iw_get_scan(
ASSERT(((uintptr)bi + dtoh32(bi->length)) <= ((uintptr)list +
buflen));
{
int channel;
// terence 20150419: limit the max. rssi to -2 or the bss will be filtered out in android OS
rssi = MIN(dtoh16(bi->RSSI), RSSI_MAXVAL);
channel = (bi->ctl_ch == 0) ? CHSPEC_CHANNEL(bi->chanspec) : bi->ctl_ch;
WL_SCAN(("%s: BSSID="MACSTR", channel=%d, RSSI=%d, merge broadcast SSID=\"%s\"\n",
__FUNCTION__, MAC2STR(bi->BSSID.octet), channel, dtoh16(bi->RSSI), bi->SSID));
}
__FUNCTION__, MAC2STR(bi->BSSID.octet), channel, rssi, bi->SSID));
/* First entry must be the BSSID */
iwe.cmd = SIOCGIWAP;
@ -1562,8 +1575,7 @@ wl_iw_get_scan(
/* Channel */
iwe.cmd = SIOCGIWFREQ;
iwe.u.freq.m = wf_channel2mhz(CHSPEC_CHANNEL(bi->chanspec),
iwe.u.freq.m = wf_channel2mhz(channel,
(CHSPEC_IS2G(bi->chanspec)) ?
WF_CHAN_FACTOR_2_4_G : WF_CHAN_FACTOR_5_G);
iwe.u.freq.e = 6;
@ -1571,8 +1583,8 @@ wl_iw_get_scan(
/* Channel quality */
iwe.cmd = IWEVQUAL;
iwe.u.qual.qual = rssi_to_qual(dtoh16(bi->RSSI));
iwe.u.qual.level = 0x100 + dtoh16(bi->RSSI);
iwe.u.qual.qual = rssi_to_qual(rssi);
iwe.u.qual.level = 0x100 + rssi;
iwe.u.qual.noise = 0x100 + bi->phy_noise;
event = IWE_STREAM_ADD_EVENT(info, event, end, &iwe, IW_EV_QUAL_LEN);
@ -1627,6 +1639,8 @@ wl_iw_iscan_get_scan(
char *event = extra, *end = extra + dwrq->length, *value;
iscan_info_t *iscan = g_iscan;
iscan_buf_t * p_buf;
int16 rssi;
int channel;
WL_TRACE(("%s: %s SIOCGIWSCAN\n", __FUNCTION__, dev->name));
@ -1639,103 +1653,105 @@ wl_iw_iscan_get_scan(
}
/* Check for scan in progress */
if (iscan->iscan_state == ISCAN_STATE_SCANING)
if (iscan->iscan_state == ISCAN_STATE_SCANING) {
WL_TRACE(("%s: SIOCGIWSCAN GET still scanning\n", dev->name));
return -EAGAIN;
}
apcnt = 0;
p_buf = iscan->list_hdr;
/* Get scan results */
while (p_buf != iscan->list_cur) {
list = &((wl_iscan_results_t*)p_buf->iscan_buf)->results;
list = &((wl_iscan_results_t*)p_buf->iscan_buf)->results;
if (list->version != WL_BSS_INFO_VERSION) {
WL_ERROR(("list->version %d != WL_BSS_INFO_VERSION\n", list->version));
}
bi = NULL;
for (ii = 0; ii < list->count && apcnt < IW_MAX_AP; apcnt++, ii++) {
bi = bi ? (wl_bss_info_t *)((uintptr)bi + dtoh32(bi->length)) : list->bss_info;
ASSERT(((uintptr)bi + dtoh32(bi->length)) <= ((uintptr)list +
WLC_IW_ISCAN_MAXLEN));
/* overflow check cover fields before wpa IEs */
if (event + ETHER_ADDR_LEN + bi->SSID_len + IW_EV_UINT_LEN + IW_EV_FREQ_LEN +
IW_EV_QUAL_LEN >= end)
return -E2BIG;
{
int channel;
channel = (bi->ctl_ch == 0) ? CHSPEC_CHANNEL(bi->chanspec) : bi->ctl_ch;
WL_SCAN(("%s: BSSID="MACSTR", channel=%d, RSSI=%d, merge broadcast SSID=\"%s\"\n",
__FUNCTION__, MAC2STR(bi->BSSID.octet), channel, dtoh16(bi->RSSI), bi->SSID));
}
/* First entry must be the BSSID */
iwe.cmd = SIOCGIWAP;
iwe.u.ap_addr.sa_family = ARPHRD_ETHER;
memcpy(iwe.u.ap_addr.sa_data, &bi->BSSID, ETHER_ADDR_LEN);
event = IWE_STREAM_ADD_EVENT(info, event, end, &iwe, IW_EV_ADDR_LEN);
/* SSID */
iwe.u.data.length = dtoh32(bi->SSID_len);
iwe.cmd = SIOCGIWESSID;
iwe.u.data.flags = 1;
event = IWE_STREAM_ADD_POINT(info, event, end, &iwe, bi->SSID);
/* Mode */
if (dtoh16(bi->capability) & (DOT11_CAP_ESS | DOT11_CAP_IBSS)) {
iwe.cmd = SIOCGIWMODE;
if (dtoh16(bi->capability) & DOT11_CAP_ESS)
iwe.u.mode = IW_MODE_INFRA;
else
iwe.u.mode = IW_MODE_ADHOC;
event = IWE_STREAM_ADD_EVENT(info, event, end, &iwe, IW_EV_UINT_LEN);
if (list->version != WL_BSS_INFO_VERSION) {
WL_ERROR(("list->version %d != WL_BSS_INFO_VERSION\n", list->version));
}
/* Channel */
iwe.cmd = SIOCGIWFREQ;
bi = NULL;
for (ii = 0; ii < list->count && apcnt < IW_MAX_AP; apcnt++, ii++) {
bi = bi ? (wl_bss_info_t *)((uintptr)bi + dtoh32(bi->length)) : list->bss_info;
ASSERT(((uintptr)bi + dtoh32(bi->length)) <= ((uintptr)list +
WLC_IW_ISCAN_MAXLEN));
iwe.u.freq.m = wf_channel2mhz(CHSPEC_CHANNEL(bi->chanspec),
(CHSPEC_IS2G(bi->chanspec)) ?
WF_CHAN_FACTOR_2_4_G : WF_CHAN_FACTOR_5_G);
iwe.u.freq.e = 6;
event = IWE_STREAM_ADD_EVENT(info, event, end, &iwe, IW_EV_FREQ_LEN);
/* Channel quality */
iwe.cmd = IWEVQUAL;
iwe.u.qual.qual = rssi_to_qual(dtoh16(bi->RSSI));
iwe.u.qual.level = 0x100 + dtoh16(bi->RSSI);
iwe.u.qual.noise = 0x100 + bi->phy_noise;
event = IWE_STREAM_ADD_EVENT(info, event, end, &iwe, IW_EV_QUAL_LEN);
/* WPA, WPA2, WPS, WAPI IEs */
wl_iw_handle_scanresults_ies(&event, end, info, bi);
/* Encryption */
iwe.cmd = SIOCGIWENCODE;
if (dtoh16(bi->capability) & DOT11_CAP_PRIVACY)
iwe.u.data.flags = IW_ENCODE_ENABLED | IW_ENCODE_NOKEY;
else
iwe.u.data.flags = IW_ENCODE_DISABLED;
iwe.u.data.length = 0;
event = IWE_STREAM_ADD_POINT(info, event, end, &iwe, (char *)event);
/* Rates */
if (bi->rateset.count <= sizeof(bi->rateset.rates)) {
if (event + IW_MAX_BITRATES*IW_EV_PARAM_LEN >= end)
/* overflow check cover fields before wpa IEs */
if (event + ETHER_ADDR_LEN + bi->SSID_len + IW_EV_UINT_LEN + IW_EV_FREQ_LEN +
IW_EV_QUAL_LEN >= end)
return -E2BIG;
value = event + IW_EV_LCP_LEN;
iwe.cmd = SIOCGIWRATE;
/* Those two flags are ignored... */
iwe.u.bitrate.fixed = iwe.u.bitrate.disabled = 0;
for (j = 0; j < bi->rateset.count && j < IW_MAX_BITRATES; j++) {
iwe.u.bitrate.value = (bi->rateset.rates[j] & 0x7f) * 500000;
value = IWE_STREAM_ADD_VALUE(info, event, value, end, &iwe,
IW_EV_PARAM_LEN);
// terence 20150419: limit the max. rssi to -2 or the bss will be filtered out in android OS
rssi = MIN(dtoh16(bi->RSSI), RSSI_MAXVAL);
channel = (bi->ctl_ch == 0) ? CHSPEC_CHANNEL(bi->chanspec) : bi->ctl_ch;
WL_SCAN(("%s: BSSID="MACSTR", channel=%d, RSSI=%d, merge broadcast SSID=\"%s\"\n",
__FUNCTION__, MAC2STR(bi->BSSID.octet), channel, rssi, bi->SSID));
/* First entry must be the BSSID */
iwe.cmd = SIOCGIWAP;
iwe.u.ap_addr.sa_family = ARPHRD_ETHER;
memcpy(iwe.u.ap_addr.sa_data, &bi->BSSID, ETHER_ADDR_LEN);
event = IWE_STREAM_ADD_EVENT(info, event, end, &iwe, IW_EV_ADDR_LEN);
/* SSID */
iwe.u.data.length = dtoh32(bi->SSID_len);
iwe.cmd = SIOCGIWESSID;
iwe.u.data.flags = 1;
event = IWE_STREAM_ADD_POINT(info, event, end, &iwe, bi->SSID);
/* Mode */
if (dtoh16(bi->capability) & (DOT11_CAP_ESS | DOT11_CAP_IBSS)) {
iwe.cmd = SIOCGIWMODE;
if (dtoh16(bi->capability) & DOT11_CAP_ESS)
iwe.u.mode = IW_MODE_INFRA;
else
iwe.u.mode = IW_MODE_ADHOC;
event = IWE_STREAM_ADD_EVENT(info, event, end, &iwe, IW_EV_UINT_LEN);
}
/* Channel */
iwe.cmd = SIOCGIWFREQ;
iwe.u.freq.m = wf_channel2mhz(channel,
(CHSPEC_IS2G(bi->chanspec)) ?
WF_CHAN_FACTOR_2_4_G : WF_CHAN_FACTOR_5_G);
iwe.u.freq.e = 6;
event = IWE_STREAM_ADD_EVENT(info, event, end, &iwe, IW_EV_FREQ_LEN);
/* Channel quality */
iwe.cmd = IWEVQUAL;
iwe.u.qual.qual = rssi_to_qual(rssi);
iwe.u.qual.level = 0x100 + rssi;
iwe.u.qual.noise = 0x100 + bi->phy_noise;
event = IWE_STREAM_ADD_EVENT(info, event, end, &iwe, IW_EV_QUAL_LEN);
/* WPA, WPA2, WPS, WAPI IEs */
wl_iw_handle_scanresults_ies(&event, end, info, bi);
/* Encryption */
iwe.cmd = SIOCGIWENCODE;
if (dtoh16(bi->capability) & DOT11_CAP_PRIVACY)
iwe.u.data.flags = IW_ENCODE_ENABLED | IW_ENCODE_NOKEY;
else
iwe.u.data.flags = IW_ENCODE_DISABLED;
iwe.u.data.length = 0;
event = IWE_STREAM_ADD_POINT(info, event, end, &iwe, (char *)event);
/* Rates */
if (bi->rateset.count <= sizeof(bi->rateset.rates)) {
if (event + IW_MAX_BITRATES*IW_EV_PARAM_LEN >= end)
return -E2BIG;
value = event + IW_EV_LCP_LEN;
iwe.cmd = SIOCGIWRATE;
/* Those two flags are ignored... */
iwe.u.bitrate.fixed = iwe.u.bitrate.disabled = 0;
for (j = 0; j < bi->rateset.count && j < IW_MAX_BITRATES; j++) {
iwe.u.bitrate.value = (bi->rateset.rates[j] & 0x7f) * 500000;
value = IWE_STREAM_ADD_VALUE(info, event, value, end, &iwe,
IW_EV_PARAM_LEN);
}
event = value;
}
event = value;
}
}
p_buf = p_buf->next;
p_buf = p_buf->next;
} /* while (p_buf) */
dwrq->length = event - extra;
@ -1771,15 +1787,21 @@ wl_iw_set_essid(
memcpy(ssid.SSID, extra, ssid.SSID_len);
ssid.SSID_len = htod32(ssid.SSID_len);
if ((error = dev_wlc_ioctl(dev, WLC_SET_SSID, &ssid, sizeof(ssid))))
if ((error = dev_wlc_ioctl(dev, WLC_SET_SSID, &ssid, sizeof(ssid)))) {
WL_ERROR(("%s: WLC_SET_SSID failed (%d).\n", __FUNCTION__, error));
return error;
}
WL_ERROR(("%s: join SSID=%s\n", __FUNCTION__, ssid.SSID));
}
/* If essid null then it is "iwconfig <interface> essid off" command */
else {
scb_val_t scbval;
bzero(&scbval, sizeof(scb_val_t));
if ((error = dev_wlc_ioctl(dev, WLC_DISASSOC, &scbval, sizeof(scb_val_t))))
WL_ERROR(("%s: WLC_DISASSOC\n", __FUNCTION__));
if ((error = dev_wlc_ioctl(dev, WLC_DISASSOC, &scbval, sizeof(scb_val_t)))) {
WL_ERROR(("%s: WLC_DISASSOC failed (%d).\n", __FUNCTION__, error));
return error;
}
}
return 0;
}
@ -3396,8 +3418,13 @@ wl_iw_event(struct net_device *dev, wl_event_msg_t *e, void* data)
cmd = SIOCGIWAP;
wrqu.data.length = strlen(extra);
if (!(flags & WLC_EVENT_MSG_LINK)) {
printk("%s: Link Down with BSSID="MACSTR"\n", __FUNCTION__,
MAC2STR((u8 *)wrqu.addr.sa_data));
bzero(wrqu.addr.sa_data, ETHER_ADDR_LEN);
bzero(&extra, ETHER_ADDR_LEN);
} else {
printk("%s: Link UP with BSSID="MACSTR"\n", __FUNCTION__,
MAC2STR((u8 *)wrqu.addr.sa_data));
}
break;
case WLC_E_ACTION_FRAME:
@ -3495,9 +3522,11 @@ wl_iw_event(struct net_device *dev, wl_event_msg_t *e, void* data)
}
if (cmd) {
if (cmd == SIOCGIWSCAN)
wireless_send_event(dev, cmd, &wrqu, NULL);
else
if (cmd == SIOCGIWSCAN) {
if ((!g_iscan) || (g_iscan->sysioc_pid < 0)) {
wireless_send_event(dev, cmd, &wrqu, NULL);
};
} else
wireless_send_event(dev, cmd, &wrqu, extra);
}
@ -3754,6 +3783,7 @@ _iscan_sysioc_thread(void *data)
uint32 status;
iscan_info_t *iscan = (iscan_info_t *)data;
printk("%s: thread Enter\n", __FUNCTION__);
DAEMONIZE("iscan_sysioc");
status = WL_SCAN_RESULTS_PARTIAL;
@ -3809,6 +3839,7 @@ _iscan_sysioc_thread(void *data)
break;
}
}
printk("%s: was terminated\n", __FUNCTION__);
complete_and_exit(&iscan->sysioc_exited, 0);
}