net: wireless: rockchip_wlan: update bcmdhd driver to 1.363.59.144.10 (r)

1. Fix disconnect issue during system suspend
2. Add more module support
3. fix read country code from config
4. modify config.txt reading behavior

Change-Id: Ib6392523752d9af60329df0dd810ceb8b76467ff
Signed-off-by: Xu Xuehui <xxh@rock-chips.com>
This commit is contained in:
Xu Xuehui 2017-08-14 10:55:24 +08:00 committed by Huang, Tao
parent fcb60baab3
commit 98b4237c7d
23 changed files with 1949 additions and 1180 deletions

View File

@ -2309,7 +2309,7 @@ bcm_bprintf(struct bcmstrbuf *b, const char *fmt, ...)
r = vsnprintf(b->buf, b->size, fmt, ap);
if (bcm_bprintf_bypass == TRUE) {
printf(b->buf);
printf("%s", b->buf);
goto exit;
}
@ -2469,6 +2469,7 @@ process_nvram_vars(char *varbuf, unsigned int len)
int column;
unsigned int buf_len, n;
unsigned int pad = 0;
char nv_ver[128];
dp = varbuf;
@ -2477,13 +2478,13 @@ process_nvram_vars(char *varbuf, unsigned int len)
// terence 20130914: print out NVRAM version
if (varbuf[0] == '#') {
printf("NVRAM version: ");
for (n=1; n<len; n++) {
memset(nv_ver, 0x00, sizeof(nv_ver));
for (n=1; n<len && n<(sizeof(nv_ver)-1); n++) {
if (varbuf[n] == '\n')
break;
printk("%c", varbuf[n]);
nv_ver[n-1] = varbuf[n];
}
printk("\n");
printk("NVRAM version: %s\n", nv_ver);
}
for (n = 0; n < len; n++) {

View File

@ -128,7 +128,9 @@ enum dhd_bus_state {
/* Download Types */
typedef enum download_type {
FW,
NVRAM
NVRAM,
CLM_BLOB,
CLMINFO
} download_type_t;
@ -177,12 +179,20 @@ enum dhd_op_flags {
#define POWERUP_WAIT_MS 2000 /* ms: time out in waiting wifi to come up */
#endif
#define MAX_NVRAMBUF_SIZE (16 * 1024) /* max nvram buf size */
#define MAX_CLMINFO_BUF_SIZE (4 * 1024) /* max clminfo buf size */
#define MAX_CLM_BUF_SIZE (48 * 1024) /* max clm blob size */
#ifdef DHD_DEBUG
#define DHD_JOIN_MAX_TIME_DEFAULT 10000 /* ms: Max time out for joining AP */
#define DHD_SCAN_DEF_TIMEOUT 10000 /* ms: Max time out for scan in progress */
#endif
#ifndef CONFIG_BCMDHD_CLM_PATH
#define CONFIG_BCMDHD_CLM_PATH "/system/etc/wifi/bcmdhd_clm.blob"
#endif /* CONFIG_BCMDHD_CLM_PATH */
#define WL_CCODE_NULL_COUNTRY "#n"
#define FW_VER_STR_LEN 128
#define CLM_VER_STR_LEN 128
enum dhd_bus_wake_state {
WAKE_LOCK_OFF,
@ -629,6 +639,7 @@ typedef struct dhd_pub {
struct dhd_log_dump_buf dld_buf;
unsigned int dld_enable;
#endif /* DHD_LOG_DUMP */
char *clm_path; /* module_param: path to clm vars file */
char *conf_path; /* module_param: path to config vars file */
struct dhd_conf *conf; /* Bus module handle */
} dhd_pub_t;
@ -965,6 +976,7 @@ extern int dhd_wakeup_ioctl_event(dhd_pub_t *pub, dhd_ioctl_recieved_status_t re
extern int dhd_os_get_image_block(char * buf, int len, void * image);
extern int dhd_os_get_image_size(void * image);
extern void * dhd_os_open_image(char * filename);
extern void dhd_os_close_image(void * image);
extern void dhd_os_wd_timer(void *bus, uint wdtick);
@ -1392,7 +1404,8 @@ int dhd_ndo_remove_ip(dhd_pub_t *dhd, int idx);
/* ioctl processing for nl80211 */
int dhd_ioctl_process(dhd_pub_t *pub, int ifidx, struct dhd_ioctl *ioc, void *data_buf);
void dhd_bus_update_fw_nv_path(struct dhd_bus *bus, char *pfw_path, char *pnv_path, char *pconf_path);
void dhd_bus_update_fw_nv_path(struct dhd_bus *bus, char *pfw_path, char *pnv_path,
char *pclm_path, char *pconf_path);
void dhd_set_bus_state(void *bus, uint32 state);
/* Remove proper pkts(either one no-frag pkt or whole fragmented pkts) */
@ -1525,6 +1538,9 @@ int dhd_get_download_buffer(dhd_pub_t *dhd, char *file_path, download_type_t com
void dhd_free_download_buffer(dhd_pub_t *dhd, void *buffer, int length);
int dhd_download_clm_blob(dhd_pub_t *dhd, unsigned char *image, uint32 len);
int dhd_apply_default_clm(dhd_pub_t *dhd, char *clm_path);
#define dhd_is_device_removed(x) FALSE
#define dhd_os_ind_firmware_stall(x)

View File

@ -43,7 +43,7 @@ extern void dhd_bus_unregister(void);
/* Download firmware image and nvram image */
extern int dhd_bus_download_firmware(struct dhd_bus *bus, osl_t *osh,
char *fw_path, char *nv_path, char *conf_path);
char *fw_path, char *nv_path, char *clm_path, char *conf_path);
/* Stop bus module: clear pending frames, disable data flow */
extern void dhd_bus_stop(struct dhd_bus *bus, bool enforce_mutex);

View File

@ -130,6 +130,8 @@ extern int dhd_get_concurrent_capabilites(dhd_pub_t *dhd);
extern int dhd_socram_dump(struct dhd_bus *bus);
#define MAX_CHUNK_LEN 1408 /* 8 * 8 * 22 */
bool ap_cfg_running = FALSE;
bool ap_fw_loaded = FALSE;
@ -141,12 +143,15 @@ bool ap_fw_loaded = FALSE;
#define DHD_COMPILED "\nCompiled in " SRCBASE
#endif /* DHD_DEBUG */
#define CHIPID_MISMATCH 8
#if defined(DHD_DEBUG)
const char dhd_version[] = "Dongle Host Driver, version " EPI_VERSION_STR;
#else
const char dhd_version[] = "\nDongle Host Driver, version " EPI_VERSION_STR "\nCompiled from ";
#endif
char fw_version[FW_VER_STR_LEN] = "\0";
char clm_version[CLM_VER_STR_LEN] = "\0";
void dhd_set_timer(void *bus, uint wdtick);
@ -3493,6 +3498,12 @@ int dhd_get_download_buffer(dhd_pub_t *dhd, char *file_path, download_type_t com
len = dhd->cached_nvram_length;
buf = dhd->cached_nvram;
}
}
else if (component == CLM_BLOB) {
if (dhd->cached_clm_length) {
len = dhd->cached_clm_length;
buf = dhd->cached_clm;
}
} else {
return ret;
}
@ -3542,6 +3553,12 @@ int dhd_get_download_buffer(dhd_pub_t *dhd, char *file_path, download_type_t com
dhd->cached_nvram_length = len;
}
}
else if (component == CLM_BLOB) {
if (!dhd->cached_clm_length) {
dhd->cached_clm = buf;
dhd->cached_clm_length = len;
}
}
#endif
err:
@ -3551,6 +3568,187 @@ int dhd_get_download_buffer(dhd_pub_t *dhd, char *file_path, download_type_t com
return ret;
}
int
dhd_download_2_dongle(dhd_pub_t *dhd, char *iovar, uint16 flag, uint16 dload_type,
unsigned char *dload_buf, int len)
{
struct wl_dload_data *dload_ptr = (struct wl_dload_data *)dload_buf;
int err = 0;
int dload_data_offset;
static char iovar_buf[WLC_IOCTL_MEDLEN];
int iovar_len;
memset(iovar_buf, 0, sizeof(iovar_buf));
dload_data_offset = OFFSETOF(wl_dload_data_t, data);
dload_ptr->flag = (DLOAD_HANDLER_VER << DLOAD_FLAG_VER_SHIFT) | flag;
dload_ptr->dload_type = dload_type;
dload_ptr->len = htod32(len - dload_data_offset);
dload_ptr->crc = 0;
len = len + 8 - (len%8);
iovar_len = bcm_mkiovar(iovar, dload_buf,
(uint)len, iovar_buf, sizeof(iovar_buf));
if (iovar_len == 0) {
DHD_ERROR(("%s: insufficient buffer space passed to bcm_mkiovar for '%s' \n",
__FUNCTION__, iovar));
return BCME_BUFTOOSHORT;
}
err = dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovar_buf,
iovar_len, IOV_SET, 0);
return err;
}
int
dhd_download_clm_blob(dhd_pub_t *dhd, unsigned char *image, uint32 len)
{
int chunk_len;
int size2alloc;
unsigned char *new_buf;
int err = 0, data_offset;
uint16 dl_flag = DL_BEGIN;
data_offset = OFFSETOF(wl_dload_data_t, data);
size2alloc = data_offset + MAX_CHUNK_LEN;
if ((new_buf = (unsigned char *)MALLOCZ(dhd->osh, size2alloc)) != NULL) {
do {
chunk_len = dhd_os_get_image_block((char *)(new_buf + data_offset),
MAX_CHUNK_LEN, image);
if (chunk_len < 0) {
DHD_ERROR(("%s: dhd_os_get_image_block failed (%d)\n",
__FUNCTION__, chunk_len));
err = BCME_ERROR;
goto exit;
}
if (len - chunk_len == 0)
dl_flag |= DL_END;
err = dhd_download_2_dongle(dhd, "clmload", dl_flag, DL_TYPE_CLM,
new_buf, data_offset + chunk_len);
dl_flag &= ~DL_BEGIN;
len = len - chunk_len;
} while ((len > 0) && (err == 0));
} else {
err = BCME_NOMEM;
}
exit:
if (new_buf) {
MFREE(dhd->osh, new_buf, size2alloc);
}
return err;
}
int
dhd_apply_default_clm(dhd_pub_t *dhd, char *clm_path)
{
char *clm_blob_path;
int len;
unsigned char *imgbuf = NULL;
int err = BCME_OK;
char iovbuf[WLC_IOCTL_SMLEN];
wl_country_t *cspec;
if (clm_path[0] != '\0') {
if (strlen(clm_path) > MOD_PARAM_PATHLEN) {
DHD_ERROR(("clm path exceeds max len\n"));
return BCME_ERROR;
}
clm_blob_path = clm_path;
DHD_TRACE(("clm path from module param:%s\n", clm_path));
} else {
clm_blob_path = CONFIG_BCMDHD_CLM_PATH;
}
/* If CLM blob file is found on the filesystem, download the file.
* After CLM file download or If the blob file is not present,
* validate the country code before proceeding with the initialization.
* If country code is not valid, fail the initialization.
*/
imgbuf = dhd_os_open_image((char *)clm_blob_path);
if (imgbuf == NULL) {
printf("%s: Ignore clm file %s\n", __FUNCTION__, clm_path);
goto exit;
}
len = dhd_os_get_image_size(imgbuf);
if ((len > 0) && (len < MAX_CLM_BUF_SIZE) && imgbuf) {
bcm_mkiovar("country", NULL, 0, iovbuf, sizeof(iovbuf));
err = dhd_wl_ioctl_cmd(dhd, WLC_GET_VAR, iovbuf, sizeof(iovbuf), FALSE, 0);
if (err) {
DHD_ERROR(("%s: country code get failed\n", __FUNCTION__));
goto exit;
}
cspec = (wl_country_t *)iovbuf;
if ((strncmp(cspec->ccode, WL_CCODE_NULL_COUNTRY, WLC_CNTRY_BUF_SZ)) != 0) {
DHD_ERROR(("%s: CLM already exist in F/W, "
"new CLM data will be added to the end of existing CLM data!\n",
__FUNCTION__));
}
/* Found blob file. Download the file */
DHD_ERROR(("clm file download from %s \n", clm_blob_path));
err = dhd_download_clm_blob(dhd, imgbuf, len);
if (err) {
DHD_ERROR(("%s: CLM download failed err=%d\n", __FUNCTION__, err));
/* Retrieve clmload_status and print */
bcm_mkiovar("clmload_status", NULL, 0, iovbuf, sizeof(iovbuf));
err = dhd_wl_ioctl_cmd(dhd, WLC_GET_VAR, iovbuf, sizeof(iovbuf), FALSE, 0);
if (err) {
DHD_ERROR(("%s: clmload_status get failed err=%d \n",
__FUNCTION__, err));
} else {
DHD_ERROR(("%s: clmload_status: %d \n",
__FUNCTION__, *((int *)iovbuf)));
if (*((int *)iovbuf) == CHIPID_MISMATCH) {
DHD_ERROR(("Chip ID mismatch error \n"));
}
}
err = BCME_ERROR;
goto exit;
} else {
DHD_INFO(("%s: CLM download succeeded \n", __FUNCTION__));
}
} else {
DHD_INFO(("Skipping the clm download. len:%d memblk:%p \n", len, imgbuf));
#ifdef DHD_USE_CLMINFO_PARSER
err = BCME_ERROR;
goto exit;
#endif /* DHD_USE_CLMINFO_PARSER */
}
/* Verify country code */
bcm_mkiovar("country", NULL, 0, iovbuf, sizeof(iovbuf));
err = dhd_wl_ioctl_cmd(dhd, WLC_GET_VAR, iovbuf, sizeof(iovbuf), FALSE, 0);
if (err) {
DHD_ERROR(("%s: country code get failed\n", __FUNCTION__));
goto exit;
}
cspec = (wl_country_t *)iovbuf;
if ((strncmp(cspec->ccode, WL_CCODE_NULL_COUNTRY, WLC_CNTRY_BUF_SZ)) == 0) {
/* Country code not initialized or CLM download not proper */
DHD_ERROR(("country code not initialized\n"));
err = BCME_ERROR;
}
exit:
if (imgbuf) {
dhd_os_close_image(imgbuf);
}
return err;
}
void dhd_free_download_buffer(dhd_pub_t *dhd, void *buffer, int length)
{
#ifdef CACHE_FW_IMAGES

File diff suppressed because it is too large Load Diff

View File

@ -23,6 +23,7 @@ extern uint dhd_slpauto;
#define BCM43430A0_CHIP_REV 0
#define BCM43430A1_CHIP_REV 1
#define BCM43430A2_CHIP_REV 2
#define BCM43012B0_CHIP_REV 1
#define BCM4330B2_CHIP_REV 4
#define BCM4334B1_CHIP_REV 3
#define BCM43341B0_CHIP_REV 2
@ -30,11 +31,13 @@ extern uint dhd_slpauto;
#define BCM4335A0_CHIP_REV 2
#define BCM4339A0_CHIP_REV 1
#define BCM43455C0_CHIP_REV 6
#define BCM43455C5_CHIP_REV 9
#define BCM4354A1_CHIP_REV 1
#define BCM4359B1_CHIP_REV 5
#define BCM4359C0_CHIP_REV 9
#endif
#define BCM4356A2_CHIP_REV 2
#define BCM4358A3_CHIP_REV 3
/* mac range */
typedef struct wl_mac_range {
@ -132,7 +135,8 @@ typedef struct dhd_conf {
int fullroamperiod; /* Full Roaming period */
uint keep_alive_period; /* The perioid in ms to send keep alive packet */
int force_wme_ac;
wme_param_t wme; /* WME parameters */
wme_param_t wme_sta; /* WME parameters */
wme_param_t wme_ap; /* WME parameters */
int stbc; /* STBC for Tx/Rx */
int phy_oclscdenable; /* phy_oclscdenable */
#ifdef PKT_FILTER_SUPPORT
@ -181,6 +185,7 @@ typedef struct dhd_conf {
int ampdu_ba_wsize;
int ampdu_hostreorder;
int dpc_cpucore;
int rxf_cpucore;
int frameburst;
bool deepsleep;
int pm;
@ -194,14 +199,26 @@ typedef struct dhd_conf {
int vhtmode;
int num_different_channels;
int xmit_in_suspend;
#ifdef IDHCPC
int ap_in_suspend;
#ifdef SUSPEND_EVENT
bool suspend_eventmask_enable;
char suspend_eventmask[WL_EVENTING_MASK_LEN];
char resume_eventmask[WL_EVENTING_MASK_LEN];
#endif
#ifdef IDHCP
int dhcpc_enable;
int dhcpd_enable;
struct ipv4_addr dhcpd_ip_addr;
struct ipv4_addr dhcpd_ip_mask;
struct ipv4_addr dhcpd_ip_start;
struct ipv4_addr dhcpd_ip_end;
#endif
#ifdef IAPSTA_PREINIT
char iapsta_init[50];
char iapsta_config[300];
char iapsta_enable[50];
#endif
int autocountry;
int tsq;
} dhd_conf_t;
@ -215,13 +232,15 @@ void dhd_conf_set_hw_oob_intr(bcmsdh_info_t *sdh, uint chip);
void dhd_conf_set_txglom_params(dhd_pub_t *dhd, bool enable);
#endif
void dhd_conf_set_fw_name_by_chip(dhd_pub_t *dhd, char *fw_path, char *nv_path);
void dhd_conf_set_clm_name_by_chip(dhd_pub_t *dhd, char *clm_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);
void dhd_conf_set_path(dhd_pub_t *dhd, char *dst_name, char *dst_path, char *src_path);
#ifdef CONFIG_PATH_AUTO_SELECT
void dhd_conf_set_conf_name_by_chip(dhd_pub_t *dhd, char *conf_path);
#endif
int dhd_conf_set_intiovar(dhd_pub_t *dhd, uint cmd, char *name, int val, int def, bool down);
int dhd_conf_get_iovar(dhd_pub_t *dhd, int cmd, char *name, char *buf, int len, int ifidx);
int dhd_conf_set_bufiovar(dhd_pub_t *dhd, uint cmd, char *name, char *buf, int len, bool down);
uint dhd_conf_get_band(dhd_pub_t *dhd);
int dhd_conf_set_country(dhd_pub_t *dhd);
int dhd_conf_get_country(dhd_pub_t *dhd, wl_country_t *cspec);
@ -230,8 +249,7 @@ int dhd_conf_fix_country(dhd_pub_t *dhd);
bool dhd_conf_match_channel(dhd_pub_t *dhd, uint32 channel);
int dhd_conf_set_roam(dhd_pub_t *dhd);
void dhd_conf_set_bw_cap(dhd_pub_t *dhd);
void dhd_conf_get_wme(dhd_pub_t *dhd, edcf_acparam_t *acp);
void dhd_conf_set_wme(dhd_pub_t *dhd);
void dhd_conf_set_wme(dhd_pub_t *dhd, int mode);
void dhd_conf_add_pkt_filter(dhd_pub_t *dhd);
bool dhd_conf_del_pkt_filter(dhd_pub_t *dhd, uint32 id);
void dhd_conf_discard_pkt_filter(dhd_pub_t *dhd);
@ -243,6 +261,8 @@ int dhd_conf_get_pm(dhd_pub_t *dhd);
#ifdef PROP_TXSTATUS
int dhd_conf_get_disable_proptx(dhd_pub_t *dhd);
#endif
int dhd_conf_get_ap_mode_in_suspend(dhd_pub_t *dhd);
int dhd_conf_set_ap_in_suspend(dhd_pub_t *dhd, int suspend);
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

@ -145,6 +145,22 @@ static int dhd_wlan_get_mac_addr(unsigned char *buf)
bcopy((char *)&ea_example, buf, sizeof(struct ether_addr));
}
#endif /* EXAMPLE_GET_MAC */
#ifdef EXAMPLE_GET_MAC_VER2
/* EXAMPLE code */
{
char mac[6] = {0x00,0x11,0x22,0x33,0x44,0xFF};
char macpad[56]= {
0x00,0xaa,0x9c,0x84,0xc7,0xbc,0x9b,0xf6,
0x02,0x33,0xa9,0x4d,0x5c,0xb4,0x0a,0x5d,
0xa8,0xef,0xb0,0xcf,0x8e,0xbf,0x24,0x8a,
0x87,0x0f,0x6f,0x0d,0xeb,0x83,0x6a,0x70,
0x4a,0xeb,0xf6,0xe6,0x3c,0xe7,0x5f,0xfc,
0x0e,0xa7,0xb3,0x0f,0x00,0xe4,0x4a,0xaf,
0x87,0x08,0x16,0x6d,0x3a,0xe3,0xc7,0x80};
bcopy(mac, buf, sizeof(mac));
bcopy(macpad, buf+6, sizeof(macpad));
}
#endif /* EXAMPLE_GET_MAC_VER2 */
err = rockchip_wifi_mac_addr(buf);
return err;

View File

@ -474,6 +474,7 @@ typedef struct dhd_info {
void *adapter; /* adapter information, interrupt, fw path etc. */
char fw_path[PATH_MAX]; /* path to firmware image */
char nv_path[PATH_MAX]; /* path to nvram vars file */
char clm_path[PATH_MAX]; /* path to clm vars file */
char conf_path[PATH_MAX]; /* path to config vars file */
/* serialize dhd iovars */
@ -702,6 +703,7 @@ uint dhd_driver_init_done = FALSE;
*/
char firmware_path[MOD_PARAM_PATHLEN];
char nvram_path[MOD_PARAM_PATHLEN];
char clm_path[MOD_PARAM_PATHLEN];
char config_path[MOD_PARAM_PATHLEN];
/* backup buffer for firmware and nvram path */
@ -769,6 +771,7 @@ module_param(disable_proptx, int, 0644);
/* load firmware and/or nvram values from the filesystem */
module_param_string(firmware_path, firmware_path, MOD_PARAM_PATHLEN, 0660);
module_param_string(nvram_path, nvram_path, MOD_PARAM_PATHLEN, 0660);
module_param_string(clm_path, clm_path, MOD_PARAM_PATHLEN, 0660);
module_param_string(config_path, config_path, MOD_PARAM_PATHLEN, 0);
/* Watchdog interval */
@ -1355,6 +1358,7 @@ module_param(allow_delay_fwdl, int, 0);
extern char dhd_version[];
extern char fw_version[];
extern char clm_version[];
int dhd_net_bus_devreset(struct net_device *dev, uint8 flag);
static void dhd_net_if_lock_local(dhd_info_t *dhd);
@ -2713,7 +2717,9 @@ static int dhd_set_suspend(int value, dhd_pub_t *dhd)
}
#endif /* DYNAMIC_SWOOB_DURATION */
#endif /* DHD_USE_EARLYSUSPEND */
dhd_conf_set_ap_in_suspend(dhd, value);
} else {
dhd_conf_set_ap_in_suspend(dhd, value);
#ifdef PKT_FILTER_SUPPORT
dhd->early_suspended = 0;
#endif
@ -2823,7 +2829,7 @@ 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_support_sta_mode(dhdp))
(dhd_support_sta_mode(dhdp) || dhd_conf_get_ap_mode_in_suspend(dhdp)))
{
ret = dhd_set_suspend(val, dhdp);
}
@ -4942,17 +4948,17 @@ dhd_dpc_thread(void *data)
#ifdef CUSTOM_DPC_CPUCORE
set_cpus_allowed_ptr(current, cpumask_of(CUSTOM_DPC_CPUCORE));
#else
if (dhd->pub.conf->dpc_cpucore >= 0) {
printf("%s: set dpc_cpucore %d from config.txt\n", __FUNCTION__, dhd->pub.conf->dpc_cpucore);
set_cpus_allowed_ptr(current, cpumask_of(dhd->pub.conf->dpc_cpucore));
}
#endif
#ifdef CUSTOM_SET_CPUCORE
dhd->pub.current_dpc = current;
#endif /* CUSTOM_SET_CPUCORE */
/* Run until signal received */
while (1) {
if (dhd->pub.conf->dpc_cpucore >= 0) {
printf("%s: set dpc_cpucore %d\n", __FUNCTION__, dhd->pub.conf->dpc_cpucore);
set_cpus_allowed_ptr(current, cpumask_of(dhd->pub.conf->dpc_cpucore));
dhd->pub.conf->dpc_cpucore = -1;
}
if (!binary_sema_down(tsk)) {
#ifdef ENABLE_ADAPTIVE_SCHED
dhd_sched_policy(dhd_dpc_prio);
@ -5020,6 +5026,11 @@ dhd_rxf_thread(void *data)
DAEMONIZE("dhd_rxf");
/* DHD_OS_WAKE_LOCK is called in dhd_sched_dpc[dhd_linux.c] down below */
#ifdef CUSTOM_RXF_CPUCORE
/* change rxf thread to other cpu core */
set_cpus_allowed_ptr(current, cpumask_of(CUSTOM_RXF_CPUCORE));
#endif
/* signal: thread has started */
complete(&tsk->completed);
#ifdef CUSTOM_SET_CPUCORE
@ -5027,6 +5038,11 @@ dhd_rxf_thread(void *data)
#endif /* CUSTOM_SET_CPUCORE */
/* Run until signal received */
while (1) {
if (dhd->pub.conf->rxf_cpucore >= 0) {
printf("%s: set rxf_cpucore %d\n", __FUNCTION__, dhd->pub.conf->rxf_cpucore);
set_cpus_allowed_ptr(current, cpumask_of(dhd->pub.conf->rxf_cpucore));
dhd->pub.conf->rxf_cpucore = -1;
}
if (down_interruptible(&tsk->sema) == 0) {
void *skb;
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 0)
@ -6161,6 +6177,12 @@ dhd_open(struct net_device *net)
#endif /* BCM_FD_AGGR */
int ifidx;
int32 ret = 0;
#if defined(OOB_INTR_ONLY)
uint32 bus_type = -1;
uint32 bus_num = -1;
uint32 slot_num = -1;
wifi_adapter_info_t *adapter = NULL;
#endif
if (!dhd_download_fw_on_driverload && !dhd_driver_init_done) {
DHD_ERROR(("%s: WLAN driver is not initialized\n", __FUNCTION__));
@ -6258,6 +6280,16 @@ dhd_open(struct net_device *net)
dhd_fix_cpu_freq(dhd);
}
#endif /* FIX_CPU_MIN_CLOCK */
#if defined(OOB_INTR_ONLY)
if (dhd->pub.conf->dpc_cpucore >= 0) {
dhd_bus_get_ids(dhd->pub.bus, &bus_type, &bus_num, &slot_num);
adapter = dhd_wifi_platform_get_adapter(bus_type, bus_num, slot_num);
if (adapter) {
printf("%s: set irq affinity hit %d\n", __FUNCTION__, dhd->pub.conf->dpc_cpucore);
irq_set_affinity_hint(adapter->irq_num, cpumask_of(dhd->pub.conf->dpc_cpucore));
}
}
#endif
if (dhd->pub.busstate != DHD_BUS_DATA) {
@ -7160,9 +7192,6 @@ dhd_attach(osl_t *osh, struct dhd_bus *bus, uint bus_hdrlen)
* solution
*/
dhd_update_fw_nv_path(dhd);
#ifndef BUILD_IN_KERNEL
dhd_conf_read_config(&dhd->pub, dhd->conf_path);
#endif
/* Set network interface name if it was provided as module parameter */
if (iface_name[0]) {
@ -7284,7 +7313,7 @@ dhd_attach(osl_t *osh, struct dhd_bus *bus, uint bus_hdrlen)
}
#ifdef WL_ESCAN
wl_escan_attach(net, (void *)&dhd->pub);
#endif
#endif /* WL_ESCAN */
#endif /* defined(WL_WIRELESS_EXT) */
#ifdef SHOW_LOGTRACE
@ -7522,9 +7551,11 @@ bool dhd_update_fw_nv_path(dhd_info_t *dhdinfo)
{
int fw_len;
int nv_len;
int clm_len;
int conf_len;
const char *fw = NULL;
const char *nv = NULL;
const char *clm = NULL;
const char *conf = NULL;
char firmware[100] = {0};
char nvram[100] = {0};
@ -7566,6 +7597,10 @@ bool dhd_update_fw_nv_path(dhd_info_t *dhdinfo)
if (adapter && adapter->nv_path && adapter->nv_path[0] != '\0')
nv = adapter->nv_path;
}
if (dhdinfo->clm_path[0] == '\0') {
if (adapter && adapter->clm_path && adapter->clm_path[0] != '\0')
clm = adapter->clm_path;
}
if (dhdinfo->conf_path[0] == '\0') {
if (adapter && adapter->conf_path && adapter->conf_path[0] != '\0')
conf = adapter->conf_path;
@ -7579,6 +7614,8 @@ bool dhd_update_fw_nv_path(dhd_info_t *dhdinfo)
fw = firmware_path;
if (nvram_path[0] != '\0')
nv = nvram_path;
if (clm_path[0] != '\0')
clm = clm_path;
if (config_path[0] != '\0')
conf = config_path;
@ -7602,6 +7639,16 @@ bool dhd_update_fw_nv_path(dhd_info_t *dhdinfo)
if (dhdinfo->nv_path[nv_len-1] == '\n')
dhdinfo->nv_path[nv_len-1] = '\0';
}
if (clm && clm[0] != '\0') {
clm_len = strlen(clm);
if (clm_len >= sizeof(dhdinfo->clm_path)) {
DHD_ERROR(("clm path len exceeds max len of dhdinfo->clm_path\n"));
return FALSE;
}
strncpy(dhdinfo->clm_path, clm, sizeof(dhdinfo->clm_path));
if (dhdinfo->clm_path[clm_len-1] == '\n')
dhdinfo->clm_path[clm_len-1] = '\0';
}
if (conf && conf[0] != '\0') {
conf_len = strlen(conf);
if (conf_len >= sizeof(dhdinfo->conf_path)) {
@ -7618,6 +7665,7 @@ bool dhd_update_fw_nv_path(dhd_info_t *dhdinfo)
if (dhd_download_fw_on_driverload) {
firmware_path[0] = '\0';
nvram_path[0] = '\0';
clm_path[0] = '\0';
config_path[0] = '\0';
}
#endif
@ -7632,12 +7680,6 @@ bool dhd_update_fw_nv_path(dhd_info_t *dhdinfo)
DHD_ERROR(("nvram path not found\n"));
return FALSE;
}
if (dhdinfo->conf_path[0] == '\0') {
dhd_conf_set_conf_path_by_nv_path(&dhdinfo->pub, dhdinfo->conf_path, dhdinfo->nv_path);
}
#ifdef CONFIG_PATH_AUTO_SELECT
dhd_conf_set_conf_name_by_chip(&dhdinfo->pub, dhdinfo->conf_path);
#endif
#endif /* BCMEMBEDIMAGE */
return TRUE;
@ -7673,6 +7715,8 @@ bool dhd_validate_chipid(dhd_pub_t *dhdp)
config_chipid = BCM43342_CHIP_ID;
#elif defined(BCM43455_CHIP)
config_chipid = BCM4345_CHIP_ID;
#elif defined(BCM43012_CHIP_)
config_chipid = BCM43012_CHIP_ID;
#else
DHD_ERROR(("%s: Unknown chip id, if you use new chipset,"
" please add CONFIG_BCMXXXX into the Kernel and"
@ -7713,7 +7757,7 @@ dhd_bus_start(dhd_pub_t *dhdp)
DHD_INFO(("%s download fw %s, nv %s, conf %s\n",
__FUNCTION__, dhd->fw_path, dhd->nv_path, dhd->conf_path));
ret = dhd_bus_download_firmware(dhd->pub.bus, dhd->pub.osh,
dhd->fw_path, dhd->nv_path, dhd->conf_path);
dhd->fw_path, dhd->nv_path, dhd->clm_path, dhd->conf_path);
if (ret < 0) {
DHD_ERROR(("%s: failed to download firmware %s\n",
__FUNCTION__, dhd->fw_path));
@ -8241,6 +8285,7 @@ dhd_preinit_ioctls(dhd_pub_t *dhd)
#endif /* (defined(AP) || defined(WLP2P)) && !defined(SOFTAP_AND_GC) */
#ifdef GET_CUSTOM_MAC_ENABLE
struct ether_addr ea_addr;
char hw_ether[62];
#endif /* GET_CUSTOM_MAC_ENABLE */
#ifdef DISABLE_11N
@ -8311,15 +8356,33 @@ dhd_preinit_ioctls(dhd_pub_t *dhd)
DHD_INFO(("%s : Set IOCTL response time.\n", __FUNCTION__));
}
#ifdef GET_CUSTOM_MAC_ENABLE
ret = wifi_platform_get_mac_addr(dhd->info->adapter, ea_addr.octet);
ret = wifi_platform_get_mac_addr(dhd->info->adapter, hw_ether);
if (!ret) {
memset(buf, 0, sizeof(buf));
bcopy(hw_ether, ea_addr.octet, sizeof(struct ether_addr));
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 MAC="MACDBG", error=%d\n",
__FUNCTION__, MAC2STRDBG(ea_addr.octet), ret));
memset(buf, 0, sizeof(buf));
bcm_mkiovar("hw_ether", hw_ether, sizeof(hw_ether), buf, sizeof(buf));
ret = dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, buf, sizeof(buf), TRUE, 0);
if (ret) {
int i;
DHD_ERROR(("%s: can't set MAC address MAC="MACDBG", error=%d\n",
__FUNCTION__, MAC2STRDBG(hw_ether), ret));
for (i=0; i<sizeof(hw_ether)-ETHER_ADDR_LEN; i++) {
printf("0x%02x,", hw_ether[i+ETHER_ADDR_LEN]);
if ((i+1)%8 == 0)
printf("\n");
}
ret = BCME_NOTUP;
goto done;
}
}
} else {
DHD_ERROR(("%s: can't get custom MAC address, ret=%d\n", __FUNCTION__, ret));
ret = BCME_NOTUP;
goto done;
}
#endif /* GET_CUSTOM_MAC_ENABLE */
/* Get the default device MAC address directly from firmware */
@ -8334,6 +8397,11 @@ dhd_preinit_ioctls(dhd_pub_t *dhd)
/* Update public MAC address after reading from Firmware */
memcpy(dhd->mac.octet, buf, ETHER_ADDR_LEN);
if ((ret = dhd_apply_default_clm(dhd, dhd->clm_path)) < 0) {
DHD_ERROR(("%s: CLM set failed. Abort initialization.\n", __FUNCTION__));
goto done;
}
/* get a capabilities from firmware */
{
uint32 cap_buf_size = sizeof(dhd->fw_capabilities);
@ -8479,8 +8547,10 @@ dhd_preinit_ioctls(dhd_pub_t *dhd)
(void)concurrent_mode;
#endif
}
#ifdef BCMSDIO
if (dhd->conf->sd_f2_blocksize)
dhdsdio_func_blocksize(dhd, 2, dhd->conf->sd_f2_blocksize);
#endif
#ifdef RSDB_MODE_FROM_FILE
(void)dhd_rsdb_mode_from_file(dhd);
@ -8529,6 +8599,7 @@ dhd_preinit_ioctls(dhd_pub_t *dhd)
dhd_conf_set_country(dhd);
dhd_conf_fix_country(dhd);
}
dhd_conf_set_intiovar(dhd, WLC_SET_VAR, "autocountry", dhd->conf->autocountry, 0, FALSE);
dhd_conf_get_country(dhd, &dhd->dhd_cspec);
@ -8643,7 +8714,7 @@ dhd_preinit_ioctls(dhd_pub_t *dhd)
dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, sizeof(iovbuf), TRUE, 0);
#endif /* defined(AP) && !defined(WLP2P) */
/* 0:HT20 in ALL, 1:HT40 in ALL, 2: HT20 in 2G HT40 in 5G */
dhd_conf_set_intiovar(dhd, WLC_SET_VAR, "mimo_bw_cap", dhd->conf->mimo_bw_cap, 1, TRUE);
dhd_conf_set_intiovar(dhd, WLC_SET_VAR, "mimo_bw_cap", dhd->conf->mimo_bw_cap, 0, TRUE);
dhd_conf_set_intiovar(dhd, WLC_SET_VAR, "force_wme_ac", dhd->conf->force_wme_ac, 1, FALSE);
dhd_conf_set_intiovar(dhd, WLC_SET_VAR, "stbc_tx", dhd->conf->stbc, 0, FALSE);
dhd_conf_set_intiovar(dhd, WLC_SET_VAR, "stbc_rx", dhd->conf->stbc, 0, FALSE);
@ -8652,8 +8723,15 @@ dhd_preinit_ioctls(dhd_pub_t *dhd)
dhd_conf_set_intiovar(dhd, WLC_SET_SPECT_MANAGMENT, "WLC_SET_SPECT_MANAGMENT", dhd->conf->spect, 0, FALSE);
dhd_conf_set_intiovar(dhd, WLC_SET_VAR, "rsdb_mode", dhd->conf->rsdb_mode, -1, TRUE);
dhd_conf_set_intiovar(dhd, WLC_SET_VAR, "vhtmode", dhd->conf->vhtmode, 0, TRUE);
#ifdef IDHCPC
#ifdef IDHCP
dhd_conf_set_intiovar(dhd, WLC_SET_VAR, "dhcpc_enable", dhd->conf->dhcpc_enable, 0, FALSE);
if(dhd->conf->dhcpd_enable >= 0){
dhd_conf_set_bufiovar(dhd, WLC_SET_VAR, "dhcpd_ip_addr", (char *)&dhd->conf->dhcpd_ip_addr, sizeof(dhd->conf->dhcpd_ip_addr), FALSE);
dhd_conf_set_bufiovar(dhd, WLC_SET_VAR, "dhcpd_ip_mask", (char *)&dhd->conf->dhcpd_ip_mask, sizeof(dhd->conf->dhcpd_ip_mask), FALSE);
dhd_conf_set_bufiovar(dhd, WLC_SET_VAR, "dhcpd_ip_start", (char *)&dhd->conf->dhcpd_ip_start, sizeof(dhd->conf->dhcpd_ip_start), FALSE);
dhd_conf_set_bufiovar(dhd, WLC_SET_VAR, "dhcpd_ip_end", (char *)&dhd->conf->dhcpd_ip_end, sizeof(dhd->conf->dhcpd_ip_end), FALSE);
dhd_conf_set_intiovar(dhd, WLC_SET_VAR, "dhcpd_enable", dhd->conf->dhcpd_enable, 0, FALSE);
}
#endif
dhd_conf_set_bw_cap(dhd);
@ -8859,7 +8937,7 @@ dhd_preinit_ioctls(dhd_pub_t *dhd)
#endif /* WLTDLS */
#ifdef WL_ESCAN
setbit(eventmask, WLC_E_ESCAN_RESULT);
#endif
#endif /* WL_ESCAN */
#ifdef WL_CFG80211
setbit(eventmask, WLC_E_ESCAN_RESULT);
setbit(eventmask, WLC_E_AP_STARTED);
@ -8892,6 +8970,9 @@ dhd_preinit_ioctls(dhd_pub_t *dhd)
dhd_update_flow_prio_map(dhd, DHD_FLOW_PRIO_LLR_MAP);
#endif /* defined(PCIE_FULL_DONGLE) && defined(DHD_LOSSLESS_ROAMING) */
#ifdef SUSPEND_EVENT
bcopy(eventmask, dhd->conf->resume_eventmask, WL_EVENTING_MASK_LEN);
#endif
/* Write updated Event mask */
bcm_mkiovar("event_msgs", eventmask, WL_EVENTING_MASK_LEN, iovbuf, sizeof(iovbuf));
if ((ret = dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, sizeof(iovbuf), TRUE, 0)) < 0) {
@ -9034,6 +9115,28 @@ dhd_preinit_ioctls(dhd_pub_t *dhd)
sec_save_wlinfo(buf, EPI_VERSION_STR, dhd->info->nv_path);
#endif /* WRITE_WLANINFO */
}
/* query for 'clmver' to get clm version info from firmware */
memset(buf, 0, sizeof(buf));
bcm_mkiovar("clmver", (char *)&buf, 4, buf, sizeof(buf));
if ((ret = dhd_wl_ioctl_cmd(dhd, WLC_GET_VAR, buf, sizeof(buf), FALSE, 0)) < 0)
DHD_ERROR(("%s failed %d\n", __FUNCTION__, ret));
else {
char *clmver_temp_buf = NULL;
if ((clmver_temp_buf = bcmstrstr(buf, "Data:")) == NULL) {
DHD_ERROR(("Couldn't find \"Data:\"\n"));
} else {
ptr = (clmver_temp_buf + strlen("Data:"));
if ((clmver_temp_buf = bcmstrtok(&ptr, "\n", 0)) == NULL) {
DHD_ERROR(("Couldn't find New line character\n"));
} else {
memset(clm_version, 0, CLM_VER_STR_LEN);
strncpy(clm_version, clmver_temp_buf,
MIN(strlen(clmver_temp_buf), CLM_VER_STR_LEN - 1));
DHD_ERROR((" clm = %s\n", clm_version));
}
}
}
#if defined(BCMSDIO)
dhd_txglom_enable(dhd, dhd->conf->bus_rxglom);
@ -9098,8 +9201,11 @@ dhd_preinit_ioctls(dhd_pub_t *dhd)
#endif /* DISABLE_11N */
if (wlfc_enable)
if (wlfc_enable) {
dhd_wlfc_init(dhd);
/* terence 20161229: enable ampdu_hostreorder if tlv enabled */
dhd_conf_set_intiovar(dhd, WLC_SET_VAR, "ampdu_hostreorder", 1, 0, TRUE);
}
#ifndef DISABLE_11N
else if (hostreorder)
dhd_wlfc_hostreorder_init(dhd);
@ -9107,6 +9213,7 @@ dhd_preinit_ioctls(dhd_pub_t *dhd)
#else
/* terence 20161229: disable ampdu_hostreorder if PROP_TXSTATUS not defined */
printf("%s: not define PROP_TXSTATUS\n", __FUNCTION__);
dhd_conf_set_intiovar(dhd, WLC_SET_VAR, "ampdu_hostreorder", 0, 0, TRUE);
#endif /* PROP_TXSTATUS */
dhd_conf_set_intiovar(dhd, WLC_SET_VAR, "ampdu_hostreorder", dhd->conf->ampdu_hostreorder, 0, TRUE);
#endif /* BCMSDIO || BCMBUS */
@ -9750,7 +9857,7 @@ void dhd_detach(dhd_pub_t *dhdp)
}
#ifdef WL_ESCAN
wl_escan_detach();
#endif
#endif /* WL_ESCAN */
#endif /* defined(WL_WIRELESS_EXT) */
/* delete all interfaces, start with virtual */
@ -10043,7 +10150,7 @@ dhd_module_init(void)
int err;
int retry = 0;
printf("%s: in\n", __FUNCTION__);
printf("%s: in %s\n", __FUNCTION__, dhd_version);
dhd_buzzz_attach();
@ -10481,6 +10588,20 @@ dhd_os_get_image_block(char *buf, int len, void *image)
return rdlen;
}
int
dhd_os_get_image_size(void *image)
{
struct file *fp = (struct file *)image;
int size;
if (!image) {
return 0;
}
size = i_size_read(file_inode(fp));
return size;
}
void
dhd_os_close_image(void *image)
{
@ -10806,7 +10927,7 @@ dhd_net_bus_devreset(struct net_device *dev, uint8 flag)
dhd_update_fw_nv_path(dhd);
/* update firmware and nvram path to sdio bus */
dhd_bus_update_fw_nv_path(dhd->pub.bus,
dhd->fw_path, dhd->nv_path, dhd->conf_path);
dhd->fw_path, dhd->nv_path, dhd->clm_path, dhd->conf_path);
}
#endif /* BCMSDIO */

View File

@ -59,6 +59,7 @@ typedef struct wifi_adapter_info {
uint intr_flags;
const char *fw_path;
const char *nv_path;
const char *clm_path;
const char *conf_path;
void *wifi_plat_data; /* wifi ctrl func, for backward compatibility */
uint bus_type;

View File

@ -1183,12 +1183,14 @@ dhdpcie_mem_check(struct dhd_bus *bus)
/* Download firmware image and nvram image */
int
dhd_bus_download_firmware(struct dhd_bus *bus, osl_t *osh,
char *pfw_path, char *pnv_path, char *pconf_path)
char *pfw_path, char *pnv_path,
char *pclm_path, char *pconf_path)
{
int ret;
bus->fw_path = pfw_path;
bus->nv_path = pnv_path;
bus->dhd->clm_path = pclm_path;
bus->dhd->conf_path = pconf_path;
DHD_ERROR(("%s: firmware path=%s, nvram path=%s\n",
@ -1201,6 +1203,36 @@ dhd_bus_download_firmware(struct dhd_bus *bus, osl_t *osh,
return ret;
}
void
dhd_set_path_params(struct dhd_bus *bus)
{
/* External conf takes precedence if specified */
dhd_conf_preinit(bus->dhd);
if (bus->dhd->clm_path[0] == '\0') {
dhd_conf_set_path(bus->dhd, "clm.blob", bus->dhd->clm_path, bus->fw_path);
}
dhd_conf_set_clm_name_by_chip(bus->dhd, bus->dhd->clm_path);
if (bus->dhd->conf_path[0] == '\0') {
dhd_conf_set_path(bus->dhd, "config.txt", bus->dhd->conf_path, bus->nv_path);
}
#ifdef CONFIG_PATH_AUTO_SELECT
dhd_conf_set_conf_name_by_chip(bus->dhd, bus->dhd->conf_path);
#endif
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_clm_name_by_chip(bus->dhd, bus->dhd->clm_path);
printf("Final fw_path=%s\n", bus->fw_path);
printf("Final nv_path=%s\n", bus->nv_path);
printf("Final clm_path=%s\n", bus->dhd->clm_path);
printf("Final conf_path=%s\n", bus->dhd->conf_path);
}
static int
dhdpcie_download_firmware(struct dhd_bus *bus, osl_t *osh)
{
@ -1241,15 +1273,7 @@ dhdpcie_download_firmware(struct dhd_bus *bus, osl_t *osh)
DHD_OS_WAKE_LOCK(bus->dhd);
/* External conf takes precedence if specified */
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, bus->nv_path);
dhd_conf_set_nv_name_by_chip(bus->dhd, bus->nv_path);
printf("Final fw_path=%s\n", bus->fw_path);
printf("Final nv_path=%s\n", bus->nv_path);
printf("Final conf_path=%s\n", bus->dhd->conf_path);
dhd_set_path_params(bus);
ret = _dhdpcie_download_firmware(bus);

View File

@ -774,13 +774,17 @@ dhdsdio_sr_cap(dhd_bus_t *bus)
(bus->sih->chip == BCM4354_CHIP_ID) ||
(bus->sih->chip == BCM4356_CHIP_ID) ||
(bus->sih->chip == BCM4358_CHIP_ID) ||
(bus->sih->chip == BCM43569_CHIP_ID) ||
(bus->sih->chip == BCM4371_CHIP_ID) ||
(BCM4349_CHIP(bus->sih->chip)) ||
(bus->sih->chip == BCM4350_CHIP_ID)) {
(bus->sih->chip == BCM4350_CHIP_ID) ||
(bus->sih->chip == BCM43012_CHIP_ID)) {
core_capext = TRUE;
} else {
core_capext = bcmsdh_reg_read(bus->sdh, CORE_CAPEXT_ADDR, 4);
core_capext = (core_capext & CORE_CAPEXT_SR_SUPPORTED_MASK);
core_capext = bcmsdh_reg_read(bus->sdh,
si_get_pmu_reg_addr(bus->sih, OFFSETOF(chipcregs_t, core_cap_ext)),
4);
core_capext = (core_capext & CORE_CAPEXT_SR_SUPPORTED_MASK);
}
if (!(core_capext))
return FALSE;
@ -796,6 +800,7 @@ dhdsdio_sr_cap(dhd_bus_t *bus)
(bus->sih->chip == BCM4354_CHIP_ID) ||
(bus->sih->chip == BCM4356_CHIP_ID) ||
(bus->sih->chip == BCM4358_CHIP_ID) ||
(bus->sih->chip == BCM43569_CHIP_ID) ||
(bus->sih->chip == BCM4371_CHIP_ID) ||
(bus->sih->chip == BCM4350_CHIP_ID)) {
uint32 enabval = 0;
@ -810,6 +815,7 @@ dhdsdio_sr_cap(dhd_bus_t *bus)
(bus->sih->chip == BCM4354_CHIP_ID) ||
(bus->sih->chip == BCM4356_CHIP_ID) ||
(bus->sih->chip == BCM4358_CHIP_ID) ||
(bus->sih->chip == BCM43569_CHIP_ID) ||
(bus->sih->chip == BCM4371_CHIP_ID))
enabval &= CC_CHIPCTRL3_SR_ENG_ENABLE;
@ -817,7 +823,8 @@ dhdsdio_sr_cap(dhd_bus_t *bus)
cap = TRUE;
} else {
data = bcmsdh_reg_read(bus->sdh,
SI_ENUM_BASE + OFFSETOF(chipcregs_t, retention_ctl), 4);
si_get_pmu_reg_addr(bus->sih, OFFSETOF(chipcregs_t, retention_ctl)),
4);
if ((data & (RCTL_MACPHY_DISABLE_MASK | RCTL_LOGIC_DISABLE_MASK)) == 0)
cap = TRUE;
}
@ -847,11 +854,19 @@ dhdsdio_sr_init(dhd_bus_t *bus)
if ((bus->sih->chip == BCM4334_CHIP_ID) && (bus->sih->chiprev == 2))
dhdsdio_srwar_init(bus);
val = bcmsdh_cfg_read(bus->sdh, SDIO_FUNC_1, SBSDIO_FUNC1_WAKEUPCTRL, NULL);
val |= 1 << SBSDIO_FUNC1_WCTRL_HTWAIT_SHIFT;
bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_1, SBSDIO_FUNC1_WAKEUPCTRL,
1 << SBSDIO_FUNC1_WCTRL_HTWAIT_SHIFT, &err);
val = bcmsdh_cfg_read(bus->sdh, SDIO_FUNC_1, SBSDIO_FUNC1_WAKEUPCTRL, NULL);
if (bus->sih->chip == BCM43012_CHIP_ID) {
val = bcmsdh_cfg_read(bus->sdh, SDIO_FUNC_1, SBSDIO_FUNC1_WAKEUPCTRL, NULL);
val |= 1 << SBSDIO_FUNC1_WCTRL_ALPWAIT_SHIFT;
bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_1, SBSDIO_FUNC1_WAKEUPCTRL,
1 << SBSDIO_FUNC1_WCTRL_ALPWAIT_SHIFT, &err);
val = bcmsdh_cfg_read(bus->sdh, SDIO_FUNC_1, SBSDIO_FUNC1_WAKEUPCTRL, NULL);
} else {
val = bcmsdh_cfg_read(bus->sdh, SDIO_FUNC_1, SBSDIO_FUNC1_WAKEUPCTRL, NULL);
val |= 1 << SBSDIO_FUNC1_WCTRL_HTWAIT_SHIFT;
bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_1, SBSDIO_FUNC1_WAKEUPCTRL,
1 << SBSDIO_FUNC1_WCTRL_HTWAIT_SHIFT, &err);
val = bcmsdh_cfg_read(bus->sdh, SDIO_FUNC_1, SBSDIO_FUNC1_WAKEUPCTRL, NULL);
}
#ifdef USE_CMD14
/* Add CMD14 Support */
@ -861,9 +876,13 @@ dhdsdio_sr_init(dhd_bus_t *bus)
dhdsdio_devcap_set(bus, SDIOD_CCCR_BRCM_CARDCAP_CMD_NODEC);
bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_1,
SBSDIO_FUNC1_CHIPCLKCSR, SBSDIO_FORCE_HT, &err);
if (bus->sih->chip == BCM43012_CHIP_ID) {
bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_1,
SBSDIO_FUNC1_CHIPCLKCSR, SBSDIO_HT_AVAIL_REQ, &err);
} else {
bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_1,
SBSDIO_FUNC1_CHIPCLKCSR, SBSDIO_FORCE_HT, &err);
}
bus->_slpauto = dhd_slpauto ? TRUE : FALSE;
bus->_srenab = TRUE;
@ -924,6 +943,15 @@ dhdsdio_clk_kso_enab(dhd_bus_t *bus, bool on)
bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_1, SBSDIO_FUNC1_SLEEPCSR, wr_val, &err);
/* In case of 43012 chip, the chip could go down immediately after KSO bit is cleared.
* So the further reads of KSO register could fail. Thereby just bailing out immediately
* after clearing KSO bit, to avoid polling of KSO bit.
*/
if ((!on) && (bus->sih->chip == BCM43012_CHIP_ID)) {
return err;
}
if (on) {
cmp_val = SBSDIO_FUNC1_SLEEPCSR_KSO_MASK | SBSDIO_FUNC1_SLEEPCSR_DEVON_MASK;
bmask = cmp_val;
@ -5268,8 +5296,13 @@ dhd_bus_init(dhd_pub_t *dhdp, bool enforce_mutex)
/* Force clocks on backplane to be sure F2 interrupt propagates */
saveclk = bcmsdh_cfg_read(bus->sdh, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR, &err);
if (!err) {
bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR,
(saveclk | SBSDIO_FORCE_HT), &err);
if (bus->sih->chip == BCM43012_CHIP_ID) {
bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR,
(saveclk | SBSDIO_HT_AVAIL_REQ), &err);
} else {
bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR,
(saveclk | SBSDIO_FORCE_HT), &err);
}
}
if (err) {
DHD_ERROR(("%s: Failed to force clock for F2: err %d\n", __FUNCTION__, err));
@ -7140,7 +7173,7 @@ void dhdsdio_txpktstatics(void)
}
for (i=0;i<tx_statics.glom_max;i++) {
printf("%02d: %d", i+1, tx_statics.glom_cnt[i]);
if ((i+1)%8)
if ((i+1)%8)
printf(", ");
else
printf("\n");
@ -7148,7 +7181,7 @@ void dhdsdio_txpktstatics(void)
printf("\n");
for (i=0;i<tx_statics.glom_max;i++) {
printf("%02d:%3d%%", i+1, (tx_statics.glom_cnt[i]*100)/total);
if ((i+1)%8)
if ((i+1)%8)
printf(", ");
else
printf("\n");
@ -7790,12 +7823,16 @@ dhdsdio_chipmatch(uint16 chipid)
return TRUE;
if (chipid == BCM4358_CHIP_ID)
return TRUE;
if (chipid == BCM43569_CHIP_ID)
return TRUE;
if (chipid == BCM4371_CHIP_ID)
return TRUE;
if (chipid == BCM43430_CHIP_ID)
return TRUE;
if (BCM4349_CHIP(chipid))
return TRUE;
if (chipid == BCM43012_CHIP_ID)
return TRUE;
return FALSE;
}
@ -8175,6 +8212,7 @@ dhdsdio_probe_attach(struct dhd_bus *bus, osl_t *osh, void *sdh, void *regsva,
case BCM4354_CHIP_ID:
case BCM4356_CHIP_ID:
case BCM4358_CHIP_ID:
case BCM43569_CHIP_ID:
case BCM4371_CHIP_ID:
bus->dongle_ram_base = CR4_4350_RAM_BASE;
break;
@ -8389,12 +8427,14 @@ dhdsdio_probe_init(dhd_bus_t *bus, osl_t *osh, void *sdh)
int
dhd_bus_download_firmware(struct dhd_bus *bus, osl_t *osh,
char *pfw_path, char *pnv_path, char *pconf_path)
char *pfw_path, char *pnv_path,
char *pclm_path, char *pconf_path)
{
int ret;
bus->fw_path = pfw_path;
bus->nv_path = pnv_path;
bus->dhd->clm_path = pclm_path;
bus->dhd->conf_path = pconf_path;
ret = dhdsdio_download_firmware(bus, osh, bus->sdh);
@ -8404,7 +8444,39 @@ dhd_bus_download_firmware(struct dhd_bus *bus, osl_t *osh,
}
void
dhd_conf_set_bus_params(struct dhd_bus *bus)
dhd_set_path_params(struct dhd_bus *bus)
{
/* External conf takes precedence if specified */
dhd_conf_preinit(bus->dhd);
if (bus->dhd->conf_path[0] == '\0') {
dhd_conf_set_path(bus->dhd, "config.txt", bus->dhd->conf_path, bus->nv_path);
}
if (bus->dhd->clm_path[0] == '\0') {
dhd_conf_set_path(bus->dhd, "clm.blob", bus->dhd->clm_path, bus->fw_path);
}
#ifdef CONFIG_PATH_AUTO_SELECT
dhd_conf_set_conf_name_by_chip(bus->dhd, bus->dhd->conf_path);
#endif
dhd_conf_read_config(bus->dhd, bus->dhd->conf_path);
dhd_conf_set_fw_name_by_chip(bus->dhd, bus->fw_path, bus->nv_path);
dhd_conf_set_nv_name_by_chip(bus->dhd, bus->nv_path);
dhd_conf_set_clm_name_by_chip(bus->dhd, bus->dhd->clm_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);
printf("Final fw_path=%s\n", bus->fw_path);
printf("Final nv_path=%s\n", bus->nv_path);
printf("Final clm_path=%s\n", bus->dhd->clm_path);
printf("Final conf_path=%s\n", bus->dhd->conf_path);
}
void
dhd_set_bus_params(struct dhd_bus *bus)
{
if (bus->dhd->conf->dhd_poll >= 0) {
bus->poll = bus->dhd->conf->dhd_poll;
@ -8439,18 +8511,8 @@ dhdsdio_download_firmware(struct dhd_bus *bus, osl_t *osh, void *sdh)
/* Download the firmware */
dhdsdio_clkctl(bus, CLK_AVAIL, FALSE);
/* External conf takes precedence if specified */
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, bus->nv_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);
dhd_conf_set_bus_params(bus);
printf("Final fw_path=%s\n", bus->fw_path);
printf("Final nv_path=%s\n", bus->nv_path);
printf("Final conf_path=%s\n", bus->dhd->conf_path);
dhd_set_path_params(bus);
dhd_set_bus_params(bus);
ret = _dhdsdio_download_firmware(bus);
@ -9309,10 +9371,12 @@ dhd_bus_membytes(dhd_pub_t *dhdp, bool set, uint32 address, uint8 *data, uint si
void
dhd_bus_update_fw_nv_path(struct dhd_bus *bus, char *pfw_path, char *pnv_path, char *pconf_path)
dhd_bus_update_fw_nv_path(struct dhd_bus *bus, char *pfw_path, char *pnv_path,
char *pclm_path, char *pconf_path)
{
bus->fw_path = pfw_path;
bus->nv_path = pnv_path;
bus->dhd->clm_path = pclm_path;
bus->dhd->conf_path = pconf_path;
}

View File

@ -17,7 +17,9 @@ enum dhd_prealloc_index {
DHD_PREALLOC_DHD_INFO = 7,
DHD_PREALLOC_DHD_WLFC_INFO = 8,
DHD_PREALLOC_IF_FLOW_LKUP = 9,
DHD_PREALLOC_FLOWRING = 10,
DHD_PREALLOC_MEMDUMP_BUF = 10,
DHD_PREALLOC_MEMDUMP_RAM = 11,
DHD_PREALLOC_DHD_WLFC_HANGER = 12,
DHD_PREALLOC_MAX
};
@ -30,6 +32,7 @@ enum dhd_prealloc_index {
#define DHD_PREALLOC_OSL_BUF_SIZE (STATIC_BUF_MAX_NUM * STATIC_BUF_SIZE)
#define DHD_PREALLOC_WIPHY_ESCAN0_SIZE (64 * 1024)
#define DHD_PREALLOC_DHD_INFO_SIZE (24 * 1024)
#define DHD_PREALLOC_DHD_WLFC_HANGER_SIZE (64 * 1024)
#ifdef CONFIG_64BIT
#define DHD_PREALLOC_IF_FLOW_LKUP_SIZE (20 * 1024 * 2)
#else
@ -42,7 +45,7 @@ enum dhd_prealloc_index {
#define WLAN_DHD_IF_FLOW_LKUP_SIZE (64 * 1024)
#else
#define WLAN_DHD_INFO_BUF_SIZE (16 * 1024)
#define WLAN_DHD_WLFC_BUF_SIZE (16 * 1024)
#define WLAN_DHD_WLFC_BUF_SIZE (24 * 1024)
#define WLAN_DHD_IF_FLOW_LKUP_SIZE (20 * 1024)
#endif /* CONFIG_64BIT */
#define WLAN_DHD_MEMDUMP_SIZE (800 * 1024)
@ -83,6 +86,7 @@ void *wlan_static_scan_buf1 = NULL;
void *wlan_static_dhd_info_buf = NULL;
void *wlan_static_dhd_wlfc_info_buf = NULL;
void *wlan_static_if_flow_lkup = NULL;
void *wlan_static_dhd_wlfc_hanger_buf = NULL;
static struct sk_buff *wlan_static_skb[WLAN_SKB_BUF_NUM];
@ -126,7 +130,7 @@ void *dhd_wlan_mem_prealloc(int section, unsigned long size)
}
if (section == DHD_PREALLOC_DHD_WLFC_INFO) {
if (size > WLAN_DHD_WLFC_BUF_SIZE) {
pr_err("request DHD_INFO size(%lu) is bigger than static size(%d).\n",
pr_err("request DHD_WLFC_INFO size(%lu) is bigger than static size(%d).\n",
size, WLAN_DHD_WLFC_BUF_SIZE);
return NULL;
}
@ -141,6 +145,14 @@ void *dhd_wlan_mem_prealloc(int section, unsigned long size)
return wlan_static_if_flow_lkup;
}
if (section == DHD_PREALLOC_DHD_WLFC_HANGER) {
if (size > DHD_PREALLOC_DHD_WLFC_HANGER_SIZE) {
pr_err("request DHD_WLFC_HANGER size(%lu) is bigger than static size(%d).\n",
size, DHD_PREALLOC_DHD_WLFC_HANGER_SIZE);
return NULL;
}
return wlan_static_dhd_wlfc_hanger_buf;
}
if ((section < 0) || (section > DHD_PREALLOC_MAX))
pr_err("request section id(%d) is out of max index %d\n",
section, DHD_PREALLOC_MAX);
@ -230,6 +242,13 @@ static int dhd_init_wlan_mem(void)
}
printk("%s: sectoin %d, size=%d\n", __FUNCTION__, DHD_PREALLOC_DHD_WLFC_INFO, WLAN_DHD_WLFC_BUF_SIZE);
wlan_static_dhd_wlfc_hanger_buf = kmalloc(DHD_PREALLOC_DHD_WLFC_HANGER_SIZE, GFP_KERNEL);
if (!wlan_static_dhd_wlfc_hanger_buf) {
pr_err("Failed to alloc wlan_static_dhd_wlfc_hanger_buf\n");
goto err_mem_alloc;
}
printk("%s: sectoin %d, size=%d\n", __FUNCTION__, DHD_PREALLOC_DHD_WLFC_HANGER, DHD_PREALLOC_DHD_WLFC_HANGER_SIZE);
#ifdef CONFIG_BCMDHD_PCIE
wlan_static_if_flow_lkup = kmalloc(DHD_PREALLOC_IF_FLOW_LKUP_SIZE, GFP_KERNEL);
if (!wlan_static_if_flow_lkup) {
@ -259,6 +278,9 @@ static int dhd_init_wlan_mem(void)
if (wlan_static_dhd_wlfc_info_buf)
kfree(wlan_static_dhd_wlfc_info_buf);
if (wlan_static_dhd_wlfc_hanger_buf)
kfree(wlan_static_dhd_wlfc_hanger_buf);
if (wlan_static_scan_buf1)
kfree(wlan_static_scan_buf1);
@ -340,6 +362,9 @@ dhd_static_buf_exit(void)
if (wlan_static_dhd_wlfc_info_buf)
kfree(wlan_static_dhd_wlfc_info_buf);
if (wlan_static_dhd_wlfc_hanger_buf)
kfree(wlan_static_dhd_wlfc_hanger_buf);
if (wlan_static_scan_buf1)
kfree(wlan_static_scan_buf1);

View File

@ -2812,7 +2812,11 @@ static void
_dhd_wlfc_reorderinfo_indicate(uint8 *val, uint8 len, uchar *info_buf, uint *info_len)
{
if (info_len) {
if (info_buf) {
/* Check copy length to avoid buffer overrun. In case of length exceeding
* WLHOST_REORDERDATA_TOTLEN, return failure instead sending incomplete result
* of length WLHOST_REORDERDATA_TOTLEN
*/
if ((info_buf) && (len <= WLHOST_REORDERDATA_TOTLEN)) {
bcopy(val, info_buf, len);
*info_len = len;
} else {
@ -2910,6 +2914,7 @@ int dhd_wlfc_enable(dhd_pub_t *dhd)
exit:
DHD_ERROR(("%s: ret=%d\n", __FUNCTION__, rc));
dhd_os_wlfc_unblock(dhd);
return rc;
@ -3566,8 +3571,6 @@ dhd_wlfc_init(dhd_pub_t *dhd)
*/
DHD_ERROR(("dhd_wlfc_init(): successfully %s bdcv2 tlv signaling, %d\n",
dhd->wlfc_enabled?"enabled":"disabled", tlv));
/* terence 20161229: enable ampdu_hostreorder if tlv enable hostreorder */
dhd_conf_set_intiovar(dhd, WLC_SET_VAR, "ampdu_hostreorder", 1, 0, TRUE);
}
mode = 0;
@ -3762,6 +3765,8 @@ dhd_wlfc_deinit(dhd_pub_t *dhd)
dhd->proptxstatus_mode = hostreorder ?
WLFC_ONLY_AMPDU_HOSTREORDER : WLFC_FCMODE_NONE;
DHD_ERROR(("%s: wlfc_mode=0x%x, tlv=%d\n", __FUNCTION__, dhd->wlfc_mode, tlv));
dhd_os_wlfc_unblock(dhd);
if (dhd->plat_deinit)

View File

@ -46,6 +46,6 @@
#define EPI_VERSION_DEV 1.363.59
/* Driver Version String, ASCII, 32 chars max */
#define EPI_VERSION_STR "1.363.59.144.7 (r)"
#define EPI_VERSION_STR "1.363.59.144.10 (r)"
#endif /* _epivers_h_ */

View File

@ -92,8 +92,19 @@ typedef volatile struct {
uint32 pmuintmask1; /* 0x704 */
uint32 PAD[14];
uint32 pmuintstatus; /* 0x740 */
uint32 PAD[15];
uint32 pmuintctrl0; /* 0x780 */
uint32 extwakeupstatus; /* 0x744 */
uint32 watchdog_res_mask; /* 0x748 */
uint32 PAD[1]; /* 0x74C */
uint32 swscratch; /* 0x750 */
uint32 PAD[3]; /* 0x754-0x75C */
uint32 extwakemask[2]; /* 0x760-0x764 */
uint32 PAD[2]; /* 0x768-0x76C */
uint32 extwakereqmask[2]; /* 0x770-0x774 */
uint32 PAD[2]; /* 0x778-0x77C */
uint32 pmuintctrl0; /* 0x780 */
uint32 pmuintctrl1; /* 0x784 */
uint32 PAD[2];
uint32 extwakectrl[2] ; /* 0x790 */
} pmuregs_t;
typedef struct eci_prerev35 {
@ -345,7 +356,7 @@ typedef volatile struct {
uint32 res_req_timer_sel;
uint32 res_req_timer;
uint32 res_req_mask;
uint32 PAD;
uint32 core_cap_ext; /* 0x64c */
uint32 chipcontrol_addr; /* 0x650 */
uint32 chipcontrol_data; /* 0x654 */
uint32 regcontrol_addr;
@ -1069,6 +1080,9 @@ typedef volatile struct {
#define PCTL_XTALFREQ_SHIFT 2
#define PCTL_ILP_DIV_EN 0x00000002
#define PCTL_LPO_SEL 0x00000001
#define PCTL_EXT_FASTLPO_SWENAB 0x00000200
#define DEFAULT_43012_MIN_RES_MASK 0x0f8bfe77
/* Retention Control */
#define PMU_RCTL_CLK_DIV_SHIFT 0
@ -1326,6 +1340,7 @@ typedef volatile struct {
#define PST_ALPAVAIL 0x0008
#define PST_HTAVAIL 0x0004
#define PST_RESINIT 0x0003
#define PST_ILPFASTLPO 0x00010000
/* pmucapabilities */
#define PCAP_REV_MASK 0x000000ff

View File

@ -123,6 +123,8 @@ typedef volatile struct sbsocramregs {
#define SRCI_SRBSZ_MASK 0xf
#define SRCI_SRBSZ_SHIFT 0
#define SRCI_SRNB_MASK_EXT 0x100
#define SR_BSZ_BASE 14
/* Standby control register */

View File

@ -119,6 +119,8 @@ typedef const struct si_pub si_t;
#define ISSIM_ENAB(sih) FALSE
#define INVALID_ADDR (~0)
/* PMU clock/power control */
#if defined(BCMPMUCTL)
#define PMUCTL_ENAB(sih) (BCMPMUCTL)
@ -453,6 +455,7 @@ extern uint32 si_gci_preinit_upd_indirect(uint32 regidx, uint32 setval, uint32 m
extern uint8 si_enable_device_wake(si_t *sih, uint8 *wake_status, uint8 *cur_status);
extern void si_swdenable(si_t *sih, uint32 swdflag);
extern uint32 si_get_pmu_reg_addr(si_t *sih, uint32 offset);
#define CHIPCTRLREG1 0x1
#define CHIPCTRLREG2 0x2
#define CHIPCTRLREG3 0x3
@ -505,6 +508,17 @@ extern void si_d11rsdb_core_reset(si_t *sih, uint32 bits, uint32 resetbits);
OFFSETOF(pmuregs_t, member), mask, val): \
si_pmu_corereg(si, cc_idx, OFFSETOF(chipcregs_t, member), mask, val))
/* Used only for the regs present in the pmu core and not present in the old cc core */
#define PMU_REG_NEW(si, member, mask, val) \
si_corereg(si, si_findcoreidx(si, PMU_CORE_ID, 0), \
OFFSETOF(pmuregs_t, member), mask, val)
#define PMU_REG(si, member, mask, val) \
(AOB_ENAB(si) ? \
si_corereg(si, si_findcoreidx(si, PMU_CORE_ID, 0), \
OFFSETOF(pmuregs_t, member), mask, val): \
si_corereg(si, SI_CC_IDX, OFFSETOF(chipcregs_t, member), mask, val))
/* GCI Macros */
#define ALLONES_32 0xFFFFFFFF
#define GCI_CCTL_SECIRST_OFFSET 0 /**< SeciReset */

View File

@ -7998,6 +7998,15 @@ typedef enum {
} ulb_bw_type_t;
#endif /* WL11ULB */
#ifdef MFP
/* values for IOV_MFP arg */
enum {
WL_MFP_NONE = 0,
WL_MFP_CAPABLE,
WL_MFP_REQUIRED
};
#endif /* MFP */
#if defined(WLRCC)
#define MAX_ROAM_CHANNEL 20

View File

@ -246,6 +246,34 @@ si_buscore_prep(si_info_t *sii, uint bustype, uint devid, void *sdh)
return TRUE;
}
uint32
si_get_pmu_reg_addr(si_t *sih, uint32 offset)
{
si_info_t *sii = SI_INFO(sih);
uint32 pmuaddr = INVALID_ADDR;
uint origidx = 0;
SI_MSG(("%s: pmu access, offset: %x\n", __FUNCTION__, offset));
if (!(sii->pub.cccaps & CC_CAP_PMU)) {
goto done;
}
if (AOB_ENAB(&sii->pub)) {
uint pmucoreidx;
pmuregs_t *pmu;
SI_MSG(("%s: AOBENAB: %x\n", __FUNCTION__, offset));
origidx = sii->curidx;
pmucoreidx = si_findcoreidx(&sii->pub, PMU_CORE_ID, 0);
pmu = si_setcoreidx(&sii->pub, pmucoreidx);
pmuaddr = (uint32)(uintptr)((volatile uint8*)pmu + offset);
si_setcoreidx(sih, origidx);
} else
pmuaddr = SI_ENUM_BASE + offset;
done:
SI_MSG(("%s: pmuaddr: %x\n", __FUNCTION__, pmuaddr));
return pmuaddr;
}
static bool
si_buscore_setup(si_info_t *sii, chipcregs_t *cc, uint bustype, uint32 savewin,
uint *origidx, void *regs)
@ -1527,6 +1555,9 @@ si_chip_hostif(si_t *sih)
switch (CHIPID(sih->chip)) {
case BCM43012_CHIP_ID:
hosti = CHIP_HOSTIF_SDIOMODE;
break;
CASE_BCM43602_CHIP:
hosti = CHIP_HOSTIF_PCIEMODE;
break;
@ -1630,6 +1661,14 @@ si_watchdog(si_t *sih, uint ticks)
ticks = 2;
else if (ticks > maxt)
ticks = maxt;
if (CHIPID(sih->chip) == BCM43012_CHIP_ID) {
PMU_REG_NEW(sih, min_res_mask, ~0, DEFAULT_43012_MIN_RES_MASK);
PMU_REG_NEW(sih, watchdog_res_mask, ~0, DEFAULT_43012_MIN_RES_MASK);
PMU_REG_NEW(sih, pmustatus, PST_WDRESET, PST_WDRESET);
PMU_REG_NEW(sih, pmucontrol_ext, PCTL_EXT_FASTLPO_SWENAB, 0);
SPINWAIT((PMU_REG(sih, pmustatus, 0, 0) & PST_ILPFASTLPO),
PMU_MAX_TRANSITION_DLY);
}
pmu_corereg(sih, SI_CC_IDX, pmuwatchdog, ~0, ticks);
} else {
@ -2431,7 +2470,13 @@ si_socram_size(si_t *sih)
memsize += (1 << ((lss - 1) + SR_BSZ_BASE));
} else {
uint8 i;
uint nb = (coreinfo & SRCI_SRNB_MASK) >> SRCI_SRNB_SHIFT;
uint nb;
/* length of SRAM Banks increased for corerev greater than 23 */
if (corerev >= 23) {
nb = (coreinfo & (SRCI_SRNB_MASK | SRCI_SRNB_MASK_EXT)) >> SRCI_SRNB_SHIFT;
} else {
nb = (coreinfo & SRCI_SRNB_MASK) >> SRCI_SRNB_SHIFT;
}
for (i = 0; i < nb; i++)
memsize += socram_banksize(sii, regs, i, SOCRAM_MEMTYPE_RAM);
}
@ -3024,6 +3069,8 @@ si_is_sprom_available(si_t *sih)
case BCM43228_CHIP_ID:
case BCM43428_CHIP_ID:
return (sih->chipst & CST43228_OTP_PRESENT) != CST43228_OTP_PRESENT;
case BCM43012_CHIP_ID:
return FALSE;
default:
return TRUE;
}

View File

@ -89,7 +89,7 @@ int wl_android_priv_cmd(struct net_device *net, struct ifreq *ifr, int cmd);
#ifdef WL_EXT_IAPSTA
int wl_android_ext_attach_netdev(struct net_device *net, uint8 bssidx);
int wl_android_ext_dettach_netdev(void);
void wl_android_ext_iapsta_disconnect_sta(u32 channel);
void wl_android_ext_iapsta_disconnect_sta(struct net_device *dev, u32 channel);
#endif
int wl_android_ext_priv_cmd(struct net_device *net, char *command, int total_len,
int *bytes_written);
@ -97,17 +97,19 @@ int wl_android_ext_priv_cmd(struct net_device *net, char *command, int total_len
#define strnicmp(str1, str2, len) strncasecmp((str1), (str2), (len))
#endif
typedef enum ACTION {
ACTION_INIT = 1,
ACTION_DISABLE,
ACTION_ENABLE
} action_t;
typedef enum IF_STATE {
IF_STATE_INIT = 1,
IF_STATE_DISALBE,
IF_STATE_ENABLE
} if_state_t;
typedef enum APSTAMODE {
ISTAONLY_MODE = 1,
IAPONLY_MODE,
IAPSTA_MODE,
IDUALAP_MODE
IDUALAP_MODE,
IGOSTA_MODE,
IGCSTA_MODE
} apstamode_t;
typedef enum IFMODE {
@ -142,6 +144,7 @@ typedef enum ENCMODE {
/* i/f query */
typedef struct wl_if_info {
struct net_device *dev;
if_state_t ifstate;
ifmode_t ifmode;
uint bssidx;
char ifname[IFNAMSIZ+1];
@ -160,7 +163,7 @@ typedef struct wl_apsta_params {
struct wl_if_info pif; // primary device
struct wl_if_info vif; // virtual device
int ioctl_ver;
action_t action;
bool init;
apstamode_t apstamode;
} wl_apsta_params_t;

View File

@ -35,8 +35,14 @@
#define CMD_IAPSTA_CONFIG "IAPSTA_CONFIG"
#define CMD_IAPSTA_ENABLE "IAPSTA_ENABLE"
#define CMD_IAPSTA_DISABLE "IAPSTA_DISABLE"
#ifdef PROP_TXSTATUS
#ifdef PROP_TXSTATUS_VSDB
#include <dhd_wlfc.h>
extern int disable_proptx;
#endif /* PROP_TXSTATUS_VSDB */
#endif
#ifdef IDHCPC
#endif
#ifdef IDHCP
#define CMD_DHCPC_ENABLE "DHCPC_ENABLE"
#define CMD_DHCPC_DUMP "DHCPC_DUMP"
#endif
@ -690,14 +696,8 @@ wl_ext_set_amode(struct wl_if_info *cur_if, struct wl_apsta_params *apsta_params
}
wl_ext_iovar_setint(dev, "auth", auth);
if (apsta_params->apstamode == IAPONLY_MODE) // fix for 43455
wl_ext_ioctl(dev, WLC_DOWN, NULL, 0, 1);
wl_ext_iovar_setint(dev, "wpa_auth", wpa_auth);
if (apsta_params->apstamode == IAPONLY_MODE) // fix for 43455
wl_ext_ioctl(dev, WLC_UP, NULL, 0, 1);;
return 0;
}
@ -747,34 +747,9 @@ wl_ext_set_emode(struct wl_if_info *cur_if, struct wl_apsta_params *apsta_params
wl_ext_iovar_setint(dev, "wsec", wsec);
if (wsec == 1) {
/* OPEN-WEP */
/* 43438a1: wl0: Feb 23 2017 11:24:58 version 7.46.57.8 (r1174) FWID 01-62ddbfa1
* sta only wlan0 TBD
* ap only wlan0 OK
* apsta wlan0 TBD, wlan1 OK
*/
wl_ext_ioctl(dev, WLC_SET_KEY, &wsec_key, sizeof(wsec_key), 1);
} else if (emode == ENC_TKIP || emode == ENC_AES || emode == ENC_TKIPAES) {
if (dev) {
/* WPA2-PSK-AES */
/* 43438a1:
* wl0: Feb 23 2017 11:24:58 version 7.46.57.8 (r1174) FWID 01-62ddbfa1
* wl0: Nov 25 2016 15:06:56 version 7.46.57.5.apsta.r4.o12 (Station/Softap) FWID 01-64fb9fe8 es6.c5.n4.a3
* sta only: wlan0 OK
* ap only: wlan0 OK
* apsta: wlan0 OK, wlan1 NG(condigured ok, ping NG, same as dhd_helper)
*/
/* 43455c0: wl0: Feb 20 2017 15:38:37 version 7.45.69.3 (r) FWID 01-485b0401
* sta only: wlan0 OK
* ap only: wlan0 OK
* apsta: wlan0 OK, wlan1 OK
*/
/* 4359c0: wl0: Mar 6 2017 10:16:06 version 9.87.51.7 (r686312) FWID 01-4dcc75d9
* sta only: wlan0 OK
* ap only: wlan0 OK
* apsta: wlan0 OK, wlan1 OK
* dualap: wlan0 and wlan1 OK
*/
if (cur_if->ifmode == ISTA_MODE)
wl_ext_iovar_setint(dev, "sup_wpa", 1);
wl_ext_ioctl(dev, WLC_SET_WSEC_PMK, &psk, sizeof(psk), 1);
@ -786,24 +761,6 @@ wl_ext_set_emode(struct wl_if_info *cur_if, struct wl_apsta_params *apsta_params
return 0;
}
/*
terence 20170326:
dhd_priv iapsta_init mode [sta|ap|apsta|dualap] vifname [wlan1]
dhd_priv iapsta_config ifname [wlan0|wlan1] ssid [xxx] chan [x]
hidden [y|n] maxassoc [x]
amode [open|shared|wpapsk|wpa2psk|wpawpa2psk]
emode [none|wep|tkip|aes|tkipaes]
key [xxxxx]
dhd_priv iapsta_enable ifname [wlan0|wlan1]
dhd_priv iapsta_disable ifname [wlan0|wlan1]
dhd_priv iapsta_config ifname wlan0 ssid ttt_apsta chan 1 amode wpa2psk emode aes key 12345678 ifname wlan1 ssid ttt_apsta chan 149 amode wpa2psk emode aes key 12345678
For dualAP procedure:
1) you must disable both wlan0 and wlan1 first when you would like to enable
dhd_priv iapsta_disable ifname wlan0; dhd_priv iapsta_disable ifname wlan1
2) you must enable both wlan0 first and then wlan1
dhd_priv iapsta_enable ifname wlan0; dhd_priv iapsta_disable ifname wlan1
*/
static int
wl_ext_iapsta_init(struct net_device *dev, char *command, int total_len)
{
@ -814,12 +771,14 @@ wl_ext_iapsta_init(struct net_device *dev, char *command, int total_len)
struct wl_apsta_params *apsta_params = &g_apsta_params;
wl_interface_create_t iface;
struct dhd_pub *dhd;
wl_p2p_if_t ifreq;
if (apsta_params->action >= ACTION_INIT) {
if (apsta_params->init) {
ANDROID_ERROR(("%s: don't init twice\n", __FUNCTION__));
return -1;
}
dhd = dhd_get_pub(dev);
memset(apsta_params, 0, sizeof(struct wl_apsta_params));
ANDROID_TRACE(("%s: command=%s, len=%d\n", __FUNCTION__, command, total_len));
@ -839,6 +798,16 @@ wl_ext_iapsta_init(struct net_device *dev, char *command, int total_len)
apsta_params->apstamode = IAPSTA_MODE;
} else if (!strcmp(pch, "dualap")) {
apsta_params->apstamode = IDUALAP_MODE;
} else if (!strcmp(pch, "gosta")) {
if (!FW_SUPPORTED(dhd, p2p)) {
return -1;
}
apsta_params->apstamode = IGOSTA_MODE;
} else if (!strcmp(pch, "gcsta")) {
if (!FW_SUPPORTED(dhd, p2p)) {
return -1;
}
apsta_params->apstamode = IGCSTA_MODE;
} else {
ANDROID_ERROR(("%s: mode [sta|ap|apsta|dualap]\n", __FUNCTION__));
return -1;
@ -876,31 +845,33 @@ wl_ext_iapsta_init(struct net_device *dev, char *command, int total_len)
if (apsta_params->apstamode == ISTAONLY_MODE) {
apsta_params->pif.ifmode = ISTA_MODE;
apsta_params->pif.ifstate = IF_STATE_INIT;
wl_ext_ioctl(dev, WLC_DOWN, NULL, 0, 1);
wl_ext_iovar_setint(dev, "apsta", 1); // keep 1 as we set in dhd_preinit_ioctls
// don't set WLC_SET_AP to 0, some parameters will be reset, such as bcn_timeout and roam_off
wl_ext_ioctl(dev, WLC_UP, NULL, 0, 1);
} else if (apsta_params->apstamode == IAPONLY_MODE) {
apsta_params->pif.ifmode = IAP_MODE;
apsta_params->pif.ifstate = IF_STATE_INIT;
wl_ext_ioctl(dev, WLC_DOWN, NULL, 0, 1);
/* IF SoftAP is enabled, disable arpoe or wlan1 will ping fail */
wl_ext_iovar_setint(dev, "arp_ol", 0);
wl_ext_iovar_setint(dev, "arpoe", 0);
#ifdef ARP_OFFLOAD_SUPPORT
/* IF SoftAP is enabled, disable arpoe */
dhd_arp_offload_set(dhd, 0);
dhd_arp_offload_enable(dhd, FALSE);
#endif /* ARP_OFFLOAD_SUPPORT */
wl_ext_iovar_setint(dev, "mpc", 0);
wl_ext_iovar_setint(dev, "apsta", 0);
val = 1;
wl_ext_ioctl(dev, WLC_SET_AP, &val, sizeof(val), 1);
} else if (apsta_params->apstamode == IAPSTA_MODE) {
apsta_params->pif.ifmode = ISTA_MODE;
apsta_params->pif.ifstate = IF_STATE_INIT;
apsta_params->vif.ifmode = IAP_MODE;
/* IF SoftAP is enabled, disable arpoe or wlan1 will ping fail */
wl_ext_iovar_setint(dev, "arp_ol", 0);
wl_ext_iovar_setint(dev, "arpoe", 0);
apsta_params->vif.ifstate = IF_STATE_INIT;
wl_ext_iovar_setint(dev, "mpc", 0);
wl_ext_ioctl(dev, WLC_DOWN, NULL, 0, 1);
wl_ext_iovar_setint(dev, "apsta", 1);
val = 0;
wl_ext_ioctl(dev, WLC_SET_PM, &val, sizeof(val), 1);
dhd = dhd_get_pub(dev);
wl_ext_ioctl(dev, WLC_UP, NULL, 0, 1);
if (FW_SUPPORTED(dhd, rsdb)) {
bzero(&iface, sizeof(wl_interface_create_t));
iface.ver = WL_INTERFACE_CREATE_VER;
@ -911,28 +882,60 @@ wl_ext_iapsta_init(struct net_device *dev, char *command, int total_len)
wl_ext_iovar_setbuf_bsscfg(dev, "ssid", &ssid, sizeof(ssid), iovar_buf,
WLC_IOCTL_SMLEN, 1, NULL);
}
} else if (apsta_params->apstamode == IDUALAP_MODE) {
}
else if (apsta_params->apstamode == IDUALAP_MODE) {
apsta_params->pif.ifmode = IAP_MODE;
apsta_params->pif.ifstate = IF_STATE_INIT;
apsta_params->vif.ifmode = IAP_MODE;
apsta_params->vif.ifstate = IF_STATE_INIT;
wl_ext_ioctl(dev, WLC_DOWN, NULL, 0, 1);
wl_ext_iovar_setint(dev, "apsta", 0);
wl_ext_ioctl(dev, WLC_UP, NULL, 0, 1);
val = 1;
wl_ext_ioctl(dev, WLC_SET_AP, &val, sizeof(val), 1);
/* IF SoftAP is enabled, disable arpoe or wlan1 will ping fail */
wl_ext_iovar_setint(dev, "arp_ol", 0);
wl_ext_iovar_setint(dev, "arpoe", 0);
#ifdef ARP_OFFLOAD_SUPPORT
/* IF SoftAP is enabled, disable arpoe */
dhd_arp_offload_set(dhd, 0);
dhd_arp_offload_enable(dhd, FALSE);
#endif /* ARP_OFFLOAD_SUPPORT */
bzero(&iface, sizeof(wl_interface_create_t));
iface.ver = WL_INTERFACE_CREATE_VER;
iface.flags = WL_INTERFACE_CREATE_AP;
wl_ext_iovar_getbuf_bsscfg(dev, "interface_create", &iface, sizeof(iface), iovar_buf,
WLC_IOCTL_SMLEN, 1, NULL);
}
else if (apsta_params->apstamode == IGOSTA_MODE) {
apsta_params->pif.ifmode = ISTA_MODE;
apsta_params->pif.ifstate = IF_STATE_INIT;
apsta_params->vif.ifmode = IAP_MODE;
apsta_params->vif.ifstate = IF_STATE_INIT;
wl_ext_ioctl(dev, WLC_DOWN, NULL, 0, 1);
wl_ext_iovar_setint(dev, "apsta", 1);
wl_ext_ioctl(dev, WLC_UP, NULL, 0, 1);
bzero(&ifreq, sizeof(wl_p2p_if_t));
ifreq.type = htod32(WL_P2P_IF_GO);
wl_ext_iovar_setbuf(dev, "p2p_ifadd", &ifreq, sizeof(ifreq),
iovar_buf, WLC_IOCTL_SMLEN, NULL);
}
else if (apsta_params->apstamode == IGCSTA_MODE) {
apsta_params->pif.ifmode = ISTA_MODE;
apsta_params->pif.ifstate = IF_STATE_INIT;
apsta_params->vif.ifmode = ISTA_MODE;
apsta_params->vif.ifstate = IF_STATE_INIT;
wl_ext_ioctl(dev, WLC_DOWN, NULL, 0, 1);
wl_ext_iovar_setint(dev, "apsta", 1);
wl_ext_ioctl(dev, WLC_UP, NULL, 0, 1);
bzero(&ifreq, sizeof(wl_p2p_if_t));
ifreq.type = htod32(WL_P2P_IF_CLIENT);
wl_ext_iovar_setbuf(dev, "p2p_ifadd", &ifreq, sizeof(ifreq),
iovar_buf, WLC_IOCTL_SMLEN, NULL);
}
wl_ext_get_ioctl_ver(dev, &apsta_params->ioctl_ver);
printf("%s: apstamode=%d\n", __FUNCTION__, apsta_params->apstamode);
apsta_params->action = ACTION_INIT;
apsta_params->init = TRUE;
return 0;
}
@ -946,7 +949,7 @@ wl_ext_iapsta_config(struct net_device *dev, char *command, int total_len)
char ifname[IFNAMSIZ+1];
struct wl_if_info *cur_if = &apsta_params->pif;
if (apsta_params->action < ACTION_INIT) {
if (!apsta_params->init) {
ANDROID_ERROR(("%s: please init first\n", __FUNCTION__));
return -1;
}
@ -1093,15 +1096,18 @@ wl_ext_iapsta_disable(struct net_device *dev, char *command, int total_len)
s32 val;
} bss_setbuf;
struct wl_apsta_params *apsta_params = &g_apsta_params;
apstamode_t apstamode = apsta_params->apstamode;
char ifname[IFNAMSIZ+1];
struct wl_if_info *cur_if;
struct dhd_pub *dhd;
if (apsta_params->action < ACTION_INIT) {
if (!apsta_params->init) {
ANDROID_ERROR(("%s: please init first\n", __FUNCTION__));
return -1;
}
ANDROID_TRACE(("%s: command=%s, len=%d\n", __FUNCTION__, command, total_len));
dhd = dhd_get_pub(dev);
pick_tmp = command;
param = bcmstrtok(&pick_tmp, " ", 0); // skip iapsta_disable
@ -1139,11 +1145,12 @@ wl_ext_iapsta_disable(struct net_device *dev, char *command, int total_len)
wl_ext_ioctl(cur_if->dev, WLC_SCB_DEAUTHENTICATE, &scbval.ea, ETHER_ADDR_LEN, 1);
}
if (apsta_params->apstamode == IAPONLY_MODE) {
if (apstamode == IAPONLY_MODE) {
wl_ext_ioctl(dev, WLC_DOWN, NULL, 0, 1);
wl_ext_ioctl(dev, WLC_SET_SSID, &ssid, sizeof(ssid), 1); // reset ssid
wl_ext_iovar_setint(dev, "mpc", 1);
} else if (apsta_params->apstamode == IAPSTA_MODE && cur_if->ifmode == IAP_MODE) {
} else if ((apstamode==IAPSTA_MODE || apstamode==IGOSTA_MODE) &&
cur_if->ifmode == IAP_MODE) {
// vif is AP mode
bss_setbuf.tmp = 0xffffffff;
bss_setbuf.cfg = 0; // must be 0, or wlan1 can not be down
@ -1151,7 +1158,12 @@ wl_ext_iapsta_disable(struct net_device *dev, char *command, int total_len)
wl_ext_iovar_setbuf(cur_if->dev, "bss", &bss_setbuf, sizeof(bss_setbuf),
iovar_buf, WLC_IOCTL_SMLEN, NULL);
wl_ext_iovar_setint(dev, "mpc", 1);
} else if (apsta_params->apstamode == IDUALAP_MODE) {
#ifdef ARP_OFFLOAD_SUPPORT
/* IF SoftAP is disabled, enable arpoe back for STA mode. */
dhd_arp_offload_set(dhd, dhd_arp_mode);
dhd_arp_offload_enable(dhd, TRUE);
#endif /* ARP_OFFLOAD_SUPPORT */
} else if (apstamode == IDUALAP_MODE) {
bss_setbuf.tmp = 0xffffffff;
bss_setbuf.cfg = 0; // must be 0, or wlan1 can not be down
bss_setbuf.val = htod32(0);
@ -1159,8 +1171,20 @@ wl_ext_iapsta_disable(struct net_device *dev, char *command, int total_len)
iovar_buf, WLC_IOCTL_SMLEN, NULL);
}
apsta_params->action = ACTION_DISABLE;
printf("%s: apstamode=%d, ifname=%s\n", __FUNCTION__, apsta_params->apstamode, ifname);
#ifdef PROP_TXSTATUS_VSDB
#if defined(BCMSDIO)
if (cur_if==&apsta_params->vif && dhd->conf->disable_proptx!=0) {
bool enabled;
dhd_wlfc_get_enable(dhd, &enabled);
if (enabled) {
dhd_wlfc_deinit(dhd);
}
}
#endif
#endif /* PROP_TXSTATUS_VSDB */
cur_if->ifstate = IF_STATE_DISALBE;
printf("%s: apstamode=%d, ifname=%s\n", __FUNCTION__, apstamode, ifname);
return 0;
}
@ -1184,12 +1208,13 @@ wl_ext_iapsta_enable(struct net_device *dev, char *command, int total_len)
char cmd[128] = "iapsta_stop ifname ";
struct dhd_pub *dhd;
if (apsta_params->action < ACTION_INIT) {
if (!apsta_params->init) {
ANDROID_ERROR(("%s: please init first\n", __FUNCTION__));
return -1;
}
ANDROID_TRACE(("%s: command=%s, len=%d\n", __FUNCTION__, command, total_len));
dhd = dhd_get_pub(dev);
pick_tmp = command;
param = bcmstrtok(&pick_tmp, " ", 0); // skip iapsta_enable
@ -1232,13 +1257,15 @@ wl_ext_iapsta_enable(struct net_device *dev, char *command, int total_len)
ETHER_ADDR_LEN, iovar_buf, WLC_IOCTL_SMLEN, NULL);
}
if (apstamode == IAPONLY_MODE) {
// set ssid for AP
if (cur_if->ifmode == IAP_MODE) {
wl_ext_iovar_setint(dev, "mpc", 0);
wl_ext_ioctl(dev, WLC_UP, NULL, 0, 1);
} else if (apstamode == IAPSTA_MODE) {
wl_ext_iovar_setint(dev, "mpc", 0);
wl_ext_iovar_setbuf_bsscfg(dev, "ssid", &ssid, sizeof(ssid),
iovar_buf, WLC_IOCTL_SMLEN, cur_if->bssidx, NULL);
if (apstamode == IAPONLY_MODE) {
wl_ext_ioctl(dev, WLC_UP, NULL, 0, 1);
} else if (apstamode==IAPSTA_MODE || apstamode==IGOSTA_MODE) {
wl_ext_iovar_setbuf_bsscfg(cur_if->dev, "ssid", &ssid, sizeof(ssid),
iovar_buf, WLC_IOCTL_SMLEN, cur_if->bssidx, NULL);
}
}
if (cur_if->ifmode == IAP_MODE) {
@ -1248,10 +1275,10 @@ wl_ext_iapsta_enable(struct net_device *dev, char *command, int total_len)
wl_ext_set_amode(cur_if, apsta_params);
wl_ext_set_emode(cur_if, apsta_params);
if (apstamode == ISTAONLY_MODE) {
if (apstamode == ISTAONLY_MODE || apstamode == IGCSTA_MODE) {
if (!ETHER_ISBCAST(&cur_if->bssid) && !ETHER_ISNULLADDR(&cur_if->bssid)) {
printf("%s: BSSID: %pM\n", __FUNCTION__, &cur_if->bssid);
wl_ext_ioctl(dev, WLC_SET_BSSID, &cur_if->bssid, ETHER_ADDR_LEN, 1);
wl_ext_ioctl(cur_if->dev, WLC_SET_BSSID, &cur_if->bssid, ETHER_ADDR_LEN, 1);
}
val = 1;
wl_ext_ioctl(dev, WLC_SET_INFRA, &val, sizeof(val), 1);
@ -1264,16 +1291,15 @@ wl_ext_iapsta_enable(struct net_device *dev, char *command, int total_len)
wl_ext_ioctl(cur_if->dev, WLC_SET_CLOSED, &cur_if->hidden, sizeof(cur_if->hidden), 1);
}
if (apstamode == ISTAONLY_MODE) {
wl_ext_ioctl(dev, WLC_SET_SSID, &ssid, sizeof(ssid), 1);
if (apstamode == ISTAONLY_MODE || apstamode == IGCSTA_MODE) {
wl_ext_ioctl(cur_if->dev, WLC_SET_SSID, &ssid, sizeof(ssid), 1);
} else if (apstamode == IAPONLY_MODE) {
wl_ext_ioctl(dev, WLC_SET_SSID, &ssid, sizeof(ssid), 1);
wl_ext_ioctl(cur_if->dev, WLC_SET_SSID, &ssid, sizeof(ssid), 1);
wl_ext_ioctl(dev, WLC_UP, NULL, 0, 1);
} else if (apstamode == IAPSTA_MODE) {
} else if (apstamode == IAPSTA_MODE || apstamode == IGOSTA_MODE) {
if (cur_if->ifmode == ISTA_MODE) {
wl_ext_ioctl(dev, WLC_SET_SSID, &ssid, sizeof(ssid), 1);
wl_ext_ioctl(cur_if->dev, WLC_SET_SSID, &ssid, sizeof(ssid), 1);
} else {
dhd = dhd_get_pub(dev);
if (FW_SUPPORTED(dhd, rsdb)) {
wl_ext_ioctl(cur_if->dev, WLC_SET_SSID, &ssid, sizeof(ssid), 1);
} else {
@ -1282,33 +1308,57 @@ wl_ext_iapsta_enable(struct net_device *dev, char *command, int total_len)
wl_ext_iovar_setbuf(cur_if->dev, "bss", &bss_setbuf, sizeof(bss_setbuf),
iovar_buf, WLC_IOCTL_SMLEN, NULL);
}
#ifdef ARP_OFFLOAD_SUPPORT
/* IF SoftAP is enabled, disable arpoe */
dhd_arp_offload_set(dhd, 0);
dhd_arp_offload_enable(dhd, FALSE);
#endif /* ARP_OFFLOAD_SUPPORT */
}
} else if (apstamode == IDUALAP_MODE) {
}
else if (apstamode == IDUALAP_MODE) {
wl_ext_ioctl(cur_if->dev, WLC_SET_SSID, &ssid, sizeof(ssid), 1);
}
#ifdef PROP_TXSTATUS_VSDB
#if defined(BCMSDIO)
if (cur_if==&apsta_params->vif && !disable_proptx) {
bool enabled;
dhd_wlfc_get_enable(dhd, &enabled);
if (!enabled) {
dhd_wlfc_init(dhd);
wl_ext_ioctl(dev, WLC_UP, NULL, 0, 1);
}
}
#endif
#endif /* PROP_TXSTATUS_VSDB */
printf("%s: ifname=%s, SSID: %s\n", __FUNCTION__, ifname, cur_if->ssid);
apsta_params->action = ACTION_ENABLE;
cur_if->ifstate = IF_STATE_ENABLE;
exit:
return ret;
}
void
wl_android_ext_iapsta_disconnect_sta(u32 channel)
wl_android_ext_iapsta_disconnect_sta(struct net_device *dev, u32 channel)
{
struct wl_apsta_params *apsta_params = &g_apsta_params;
struct wl_if_info *cur_if = &apsta_params->vif;
scb_val_t scbval;
int ret;
channel_info_t ci;
struct dhd_pub *dhd;
if (apsta_params->apstamode==IAPSTA_MODE && apsta_params->action==ACTION_ENABLE) {
if (!(ret = wldev_ioctl(cur_if->dev, WLC_GET_CHANNEL, &ci, sizeof(channel_info_t), FALSE))) {
if (channel != ci.target_channel) {
printf("%s: deauthenticate all STA on vif\n", __FUNCTION__);
memcpy(scbval.ea.octet, &ether_bcast, ETHER_ADDR_LEN);
wl_ext_ioctl(cur_if->dev, WLC_SCB_DEAUTHENTICATE, &scbval.ea, ETHER_ADDR_LEN, 1);
if (apsta_params->apstamode==IAPSTA_MODE && cur_if->ifstate==IF_STATE_ENABLE) {
dhd = dhd_get_pub(dev);
if (!FW_SUPPORTED(dhd, vsdb)) {
if (!(ret = wldev_ioctl(cur_if->dev, WLC_GET_CHANNEL, &ci, sizeof(channel_info_t), FALSE))) {
if (channel != ci.target_channel) {
printf("%s: deauthenticate all STA on vif\n", __FUNCTION__);
memcpy(scbval.ea.octet, &ether_bcast, ETHER_ADDR_LEN);
wl_ext_ioctl(cur_if->dev, WLC_SCB_DEAUTHENTICATE, &scbval.ea, ETHER_ADDR_LEN, 1);
}
}
}
}
@ -1342,7 +1392,7 @@ int wl_android_ext_dettach_netdev(void)
}
#endif
#ifdef IDHCPC
#ifdef IDHCP
int wl_ext_ip_dump(int ip, char *buf)
{
unsigned char bytes[4];
@ -1533,7 +1583,7 @@ int wl_android_ext_priv_cmd(struct net_device *net, char *command, int total_len
*bytes_written = wl_ext_iapsta_disable(net, command, total_len);
}
#endif
#ifdef IDHCPC
#ifdef IDHCP
else if (strnicmp(command, CMD_DHCPC_ENABLE, strlen(CMD_DHCPC_ENABLE)) == 0) {
*bytes_written = wl_ext_dhcpc_enable(net, command, total_len);
}

View File

@ -616,6 +616,9 @@ static void wl_update_hidden_ap_ie(struct wl_bss_info *bi, const u8 *ie_stream,
static s32 wl_mrg_ie(struct bcm_cfg80211 *cfg, u8 *ie_stream, u16 ie_size);
static s32 wl_cp_ie(struct bcm_cfg80211 *cfg, u8 *dst, u16 dst_size);
static u32 wl_get_ielen(struct bcm_cfg80211 *cfg);
#ifdef MFP
static int wl_cfg80211_get_rsn_capa(bcm_tlv_t *wpa2ie, u8* capa);
#endif
#ifdef WL11U
bcm_tlv_t *
@ -1487,10 +1490,10 @@ wl_cfg80211_add_virtual_iface(struct wiphy *wiphy,
#ifdef WL_VIRTUAL_APSTA
bcm_struct_cfgdev *new_cfgdev;
#endif /* WL_VIRTUAL_APSTA */
dhd_pub_t *dhd;
#ifdef PROP_TXSTATUS_VSDB
#if defined(BCMSDIO)
s32 up = 1;
dhd_pub_t *dhd;
bool enabled;
#endif
#endif /* PROP_TXSTATUS_VSDB */
@ -1502,11 +1505,7 @@ wl_cfg80211_add_virtual_iface(struct wiphy *wiphy,
if (!cfg)
return ERR_PTR(-EINVAL);
#ifdef PROP_TXSTATUS_VSDB
#if defined(BCMSDIO)
dhd = (dhd_pub_t *)(cfg->pub);
#endif
#endif /* PROP_TXSTATUS_VSDB */
#if defined(SUPPORT_AP_POWERSAVE)
dhd = (dhd_pub_t *)(cfg->pub);
#endif /* SUPPORT_AP_POWERSAVE */
@ -1586,12 +1585,8 @@ wl_cfg80211_add_virtual_iface(struct wiphy *wiphy,
if (cfg->p2p_supported && (wlif_type != -1)) {
ASSERT(cfg->p2p); /* ensure expectation of p2p initialization */
#ifdef PROP_TXSTATUS_VSDB
#if defined(BCMSDIO)
if (!dhd)
return ERR_PTR(-ENODEV);
#endif
#endif /* PROP_TXSTATUS_VSDB */
if (!cfg->p2p)
return ERR_PTR(-ENODEV);
@ -1721,6 +1716,7 @@ wl_cfg80211_add_virtual_iface(struct wiphy *wiphy,
val = 1;
/* Disable firmware roaming for P2P interface */
wldev_iovar_setint(new_ndev, "roam_off", val);
wldev_iovar_setint(new_ndev, "bcn_timeout", dhd->conf->bcn_timeout);
#ifdef WL11ULB
if (cfg->p2p_wdev && is_p2p_group_iface(new_ndev->ieee80211_ptr)) {
u32 ulb_bw = wl_cfg80211_get_ulb_bw(cfg->p2p_wdev);
@ -1815,7 +1811,7 @@ wl_cfg80211_add_virtual_iface(struct wiphy *wiphy,
#if defined(BCMSDIO)
dhd_wlfc_get_enable(dhd, &enabled);
if (enabled && cfg->wlfc_on && dhd->op_mode != DHD_FLAG_HOSTAP_MODE &&
dhd->op_mode != DHD_FLAG_IBSS_MODE) {
dhd->op_mode != DHD_FLAG_IBSS_MODE && dhd->conf->disable_proptx!=0) {
dhd_wlfc_deinit(dhd);
cfg->wlfc_on = false;
}
@ -2246,7 +2242,7 @@ static s32 wl_cfg80211_handle_ifdel(struct bcm_cfg80211 *cfg, wl_if_event_info *
#if defined(BCMSDIO)
dhd_wlfc_get_enable(dhd, &enabled);
if (enabled && cfg->wlfc_on && dhd->op_mode != DHD_FLAG_HOSTAP_MODE &&
dhd->op_mode != DHD_FLAG_IBSS_MODE) {
dhd->op_mode != DHD_FLAG_IBSS_MODE && dhd->conf->disable_proptx!=0) {
dhd_wlfc_deinit(dhd);
cfg->wlfc_on = false;
}
@ -2426,7 +2422,7 @@ static void wl_scan_prep(struct wl_scan_params *params, struct cfg80211_scan_req
ptr = (char*)params + offset;
for (i = 0; i < n_ssids; i++) {
memset(&ssid, 0, sizeof(wlc_ssid_t));
ssid.SSID_len = request->ssids[i].ssid_len;
ssid.SSID_len = MIN(request->ssids[i].ssid_len, DOT11_MAX_SSID_LEN);
memcpy(ssid.SSID, request->ssids[i].ssid, ssid.SSID_len);
if (!ssid.SSID_len)
WL_SCAN(("%d: Broadcast scan\n", i));
@ -3789,7 +3785,8 @@ wl_cfg80211_join_ibss(struct wiphy *wiphy, struct net_device *dev,
WL_TRACE(("In\n"));
RETURN_EIO_IF_NOT_UP(cfg);
WL_INFORM(("JOIN BSSID:" MACDBG "\n", MAC2STRDBG(params->bssid)));
if (!params->ssid || params->ssid_len <= 0) {
if (!params->ssid || params->ssid_len <= 0 ||
params->ssid_len > DOT11_MAX_SSID_LEN) {
WL_ERR(("Invalid parameter\n"));
return -EINVAL;
}
@ -3958,6 +3955,43 @@ static s32 wl_cfg80211_leave_ibss(struct wiphy *wiphy, struct net_device *dev)
return err;
}
#ifdef MFP
static int wl_cfg80211_get_rsn_capa(bcm_tlv_t *wpa2ie, u8* capa)
{
u16 suite_count;
wpa_suite_mcast_t *mcast;
wpa_suite_ucast_t *ucast;
u16 len;
wpa_suite_auth_key_mgmt_t *mgmt;
if (!wpa2ie)
return -1;
len = wpa2ie->len;
mcast = (wpa_suite_mcast_t *)&wpa2ie->data[WPA2_VERSION_LEN];
if ((len -= WPA_SUITE_LEN) <= 0)
return BCME_BADLEN;
ucast = (wpa_suite_ucast_t *)&mcast[1];
suite_count = ltoh16_ua(&ucast->count);
if ((suite_count > NL80211_MAX_NR_CIPHER_SUITES) ||
(len -= (WPA_IE_SUITE_COUNT_LEN +
(WPA_SUITE_LEN * suite_count))) <= 0)
return BCME_BADLEN;
mgmt = (wpa_suite_auth_key_mgmt_t *)&ucast->list[suite_count];
suite_count = ltoh16_ua(&mgmt->count);
if ((suite_count > NL80211_MAX_NR_CIPHER_SUITES) ||
(len -= (WPA_IE_SUITE_COUNT_LEN +
(WPA_SUITE_LEN * suite_count))) >= RSN_CAP_LEN) {
capa[0] = *(u8 *)&mgmt->list[suite_count];
capa[1] = *((u8 *)&mgmt->list[suite_count] + 1);
} else
return BCME_BADLEN;
return 0;
}
#endif /* MFP */
static s32
wl_set_wpa_version(struct net_device *dev, struct cfg80211_connect_params *sme)
@ -4134,6 +4168,11 @@ wl_set_key_mgmt(struct net_device *dev, struct cfg80211_connect_params *sme)
s32 val = 0;
s32 err = 0;
s32 bssidx;
#ifdef MFP
s32 mfp = WL_MFP_NONE;
bcm_tlv_t *wpa2_ie;
u8 rsn_cap[2];
#endif /* MFP */
if ((bssidx = wl_get_bssidx_by_wdev(cfg, dev->ieee80211_ptr)) < 0) {
WL_ERR(("Find p2p index from wdev(%p) failed\n", dev->ieee80211_ptr));
@ -4166,6 +4205,14 @@ wl_set_key_mgmt(struct net_device *dev, struct cfg80211_connect_params *sme)
case WLAN_AKM_SUITE_8021X:
val = WPA2_AUTH_UNSPECIFIED;
break;
#ifdef MFP
case WL_AKM_SUITE_SHA256_1X:
val = WPA2_AUTH_UNSPECIFIED;
break;
case WL_AKM_SUITE_SHA256_PSK:
val = WPA2_AUTH_PSK;
break;
#endif /* MFP */
case WLAN_AKM_SUITE_PSK:
val = WPA2_AUTH_PSK;
break;
@ -4176,6 +4223,33 @@ wl_set_key_mgmt(struct net_device *dev, struct cfg80211_connect_params *sme)
}
}
#ifdef MFP
if (((wpa2_ie = bcm_parse_tlvs((u8 *)sme->ie, sme->ie_len,
DOT11_MNG_RSN_ID)) != NULL) &&
(wl_cfg80211_get_rsn_capa(wpa2_ie, rsn_cap) == 0)) {
/* Check for MFP cap in the RSN capability field */
if (rsn_cap[0] & RSN_CAP_MFPR) {
mfp = WL_MFP_REQUIRED;
} else if (rsn_cap[0] & RSN_CAP_MFPC) {
mfp = WL_MFP_CAPABLE;
}
}
err = wldev_iovar_setint(dev, "mfp", mfp);
if (unlikely(err)) {
if (!mfp && (err == BCME_UNSUPPORTED)) {
/* For non-mfp cases, if firmware doesn't support MFP
* ignore the failure and proceed ahead.
*/
WL_DBG(("fw doesn't support mfp \n"));
err = 0;
} else {
WL_ERR(("mfp set failed ret:%d \n", err));
return err;
}
} else {
WL_DBG(("mfp set to 0x%x \n", mfp));
}
#endif /* MFP */
WL_DBG(("setting wpa_auth to 0x%x\n", val));
@ -4585,7 +4659,7 @@ wl_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev,
return BCME_ERROR;
}
#ifdef WL_EXT_IAPSTA
wl_android_ext_iapsta_disconnect_sta(cfg->channel);
wl_android_ext_iapsta_disconnect_sta(dev, cfg->channel);
#endif
err = wldev_iovar_setbuf_bsscfg(dev, "join", ext_join_params, join_params_size,
cfg->ioctl_buf, WLC_IOCTL_MAXLEN, bssidx, &cfg->ioctl_buf_sync);
@ -5128,8 +5202,10 @@ wl_cfg80211_del_key(struct wiphy *wiphy, struct net_device *dev,
return BCME_ERROR;
}
#ifndef MFP
if ((key_idx >= DOT11_MAX_DEFAULT_KEYS) && (key_idx < DOT11_MAX_DEFAULT_KEYS+2))
return -EINVAL;
#endif
RETURN_EIO_IF_NOT_UP(cfg);
memset(&key, 0, sizeof(key));
@ -5226,8 +5302,12 @@ static s32
wl_cfg80211_config_default_mgmt_key(struct wiphy *wiphy,
struct net_device *dev, u8 key_idx)
{
#ifdef MFP
return 0;
#else
WL_INFORM(("Not supported\n"));
return -EOPNOTSUPP;
#endif /* MFP */
}
#if defined(RSSIAVG)
@ -6554,6 +6634,11 @@ wl_cfg80211_mgmt_tx(struct wiphy *wiphy, bcm_struct_cfgdev *cfgdev,
WL_DBG(("Enter \n"));
if (len > ACTION_FRAME_SIZE) {
WL_ERR(("bad length:%zu\n", len));
return BCME_BADLEN;
}
dev = cfgdev_to_wlc_ndev(cfgdev, cfg);
if (!dev) {
@ -6954,6 +7039,10 @@ wl_validate_wpa2ie(struct net_device *dev, bcm_tlv_t *wpa2ie, s32 bssidx)
wpa_suite_auth_key_mgmt_t *mgmt;
wpa_pmkid_list_t *pmkid;
int cnt = 0;
#ifdef MFP
int mfp = 0;
struct bcm_cfg80211 *cfg = g_bcm_cfg;
#endif /* MFP */
u16 suite_count;
u8 rsn_cap[2];
@ -7026,6 +7115,16 @@ wl_validate_wpa2ie(struct net_device *dev, bcm_tlv_t *wpa2ie, s32 bssidx)
case RSN_AKM_PSK:
wpa_auth |= WPA2_AUTH_PSK;
break;
#ifdef MFP
case RSN_AKM_MFP_PSK:
wpa_auth |= WPA2_AUTH_PSK;
wsec |= MFP_SHA256;
break;
case RSN_AKM_MFP_1X:
wpa_auth |= WPA2_AUTH_UNSPECIFIED;
wsec |= MFP_SHA256;
break;
#endif /* MFP */
default:
WL_ERR(("No Key Mgmt Info\n"));
}
@ -7041,6 +7140,15 @@ wl_validate_wpa2ie(struct net_device *dev, bcm_tlv_t *wpa2ie, s32 bssidx)
wme_bss_disable = 1;
}
#ifdef MFP
if (rsn_cap[0] & RSN_CAP_MFPR) {
WL_DBG(("MFP Required \n"));
mfp = WL_MFP_REQUIRED;
} else if (rsn_cap[0] & RSN_CAP_MFPC) {
WL_DBG(("MFP Capable \n"));
mfp = WL_MFP_CAPABLE;
}
#endif /* MFP */
/* set wme_bss_disable to sync RSN Capabilities */
err = wldev_iovar_setint_bsscfg(dev, "wme_bss_disable", wme_bss_disable, bssidx);
@ -7064,6 +7172,19 @@ wl_validate_wpa2ie(struct net_device *dev, bcm_tlv_t *wpa2ie, s32 bssidx)
/* so don't bother to send down this info to firmware */
}
#ifdef MFP
len -= WPA2_PMKID_COUNT_LEN;
if (len >= WPA_SUITE_LEN) {
err = wldev_iovar_setbuf_bsscfg(dev, "bip",
(void *)((u8 *)&mgmt->list[suite_count] + RSN_CAP_LEN + WPA2_PMKID_COUNT_LEN),
WPA_SUITE_LEN,
cfg->ioctl_buf, WLC_IOCTL_SMLEN, bssidx, &cfg->ioctl_buf_sync);
if (err < 0) {
WL_ERR(("bip set error %d\n", err));
return BCME_ERROR;
}
}
#endif
/* set auth */
err = wldev_iovar_setint_bsscfg(dev, "auth", auth, bssidx);
@ -7079,6 +7200,17 @@ wl_validate_wpa2ie(struct net_device *dev, bcm_tlv_t *wpa2ie, s32 bssidx)
return BCME_ERROR;
}
#ifdef MFP
if (mfp) {
/* This needs to go after wsec otherwise the wsec command will
* overwrite the values set by MFP
*/
if ((err = wldev_iovar_setint_bsscfg(dev, "mfp", mfp, bssidx)) < 0) {
WL_ERR(("MFP Setting failed. ret = %d \n", err));
return err;
}
}
#endif /* MFP */
/* set upper-layer auth */
err = wldev_iovar_setint_bsscfg(dev, "wpa_auth", wpa_auth, bssidx);
@ -7595,17 +7727,17 @@ static s32 wl_cfg80211_bcn_set_params(
}
if ((info->ssid) && (info->ssid_len > 0) &&
(info->ssid_len <= 32)) {
(info->ssid_len <= DOT11_MAX_SSID_LEN)) {
WL_DBG(("SSID (%s) len:%zd \n", info->ssid, info->ssid_len));
if (dev_role == NL80211_IFTYPE_AP) {
/* Store the hostapd SSID */
memset(cfg->hostapd_ssid.SSID, 0x00, 32);
memset(cfg->hostapd_ssid.SSID, 0x00, DOT11_MAX_SSID_LEN);
memcpy(cfg->hostapd_ssid.SSID, info->ssid, info->ssid_len);
cfg->hostapd_ssid.SSID_len = info->ssid_len;
} else {
/* P2P GO */
memset(cfg->p2p->ssid.SSID, 0x00, 32);
memcpy(cfg->p2p->ssid.SSID, info->ssid, info->ssid_len);
memset(cfg->p2p->ssid.SSID, 0x00, DOT11_MAX_SSID_LEN);
memcpy(cfg->p2p->ssid.SSID, info->ssid, cfg->p2p->ssid.SSID_len);
cfg->p2p->ssid.SSID_len = info->ssid_len;
}
}
@ -7789,6 +7921,7 @@ wl_cfg80211_bcn_bringup_ap(
WL_ERR(("failed to disable uapsd, error=%d\n", err));
}
#endif /* SOFTAP_UAPSD_OFF */
dhd_conf_set_wme(cfg->pub, 1);
err = wldev_ioctl(dev, WLC_UP, &ap, sizeof(s32), true);
if (unlikely(err)) {
@ -7817,9 +7950,11 @@ wl_cfg80211_bcn_bringup_ap(
memset(&join_params, 0, sizeof(join_params));
/* join parameters starts with ssid */
join_params_size = sizeof(join_params.ssid);
join_params.ssid.SSID_len = min(cfg->hostapd_ssid.SSID_len,
(uint32)DOT11_MAX_SSID_LEN);
memcpy(join_params.ssid.SSID, cfg->hostapd_ssid.SSID,
cfg->hostapd_ssid.SSID_len);
join_params.ssid.SSID_len = htod32(cfg->hostapd_ssid.SSID_len);
join_params.ssid.SSID_len);
join_params.ssid.SSID_len = htod32(join_params.ssid.SSID_len);
/* create softap */
if ((err = wldev_ioctl(dev, WLC_SET_SSID, &join_params,
@ -8698,14 +8833,16 @@ wl_cfg80211_add_set_beacon(struct wiphy *wiphy, struct net_device *dev,
DOT11_MNG_SSID_ID)) != NULL) {
if (dev_role == NL80211_IFTYPE_AP) {
/* Store the hostapd SSID */
memset(&cfg->hostapd_ssid.SSID[0], 0x00, 32);
memcpy(&cfg->hostapd_ssid.SSID[0], ssid_ie->data, ssid_ie->len);
cfg->hostapd_ssid.SSID_len = ssid_ie->len;
memset(&cfg->hostapd_ssid.SSID[0], 0x00, DOT11_MAX_SSID_LEN);
cfg->hostapd_ssid.SSID_len = MIN(ssid_ie->len, DOT11_MAX_SSID_LEN);
memcpy(&cfg->hostapd_ssid.SSID[0], ssid_ie->data,
cfg->hostapd_ssid.SSID_len);
} else {
/* P2P GO */
memset(&cfg->p2p->ssid.SSID[0], 0x00, 32);
memcpy(cfg->p2p->ssid.SSID, ssid_ie->data, ssid_ie->len);
cfg->p2p->ssid.SSID_len = ssid_ie->len;
/* P2P GO */
memset(&cfg->p2p->ssid.SSID[0], 0x00, DOT11_MAX_SSID_LEN);
cfg->p2p->ssid.SSID_len = MIN(ssid_ie->len, DOT11_MAX_SSID_LEN);
memcpy(cfg->p2p->ssid.SSID, ssid_ie->data,
cfg->p2p->ssid.SSID_len);
}
}
@ -8879,8 +9016,10 @@ wl_cfg80211_sched_scan_start(struct wiphy *wiphy,
ssid = &request->match_sets[i].ssid;
/* No need to include null ssid */
if (ssid->ssid_len) {
memcpy(ssids_local[ssid_cnt].SSID, ssid->ssid, ssid->ssid_len);
ssids_local[ssid_cnt].SSID_len = ssid->ssid_len;
ssids_local[ssid_cnt].SSID_len = min(ssid->ssid_len,
(u8)DOT11_MAX_SSID_LEN);
memcpy(ssids_local[ssid_cnt].SSID, ssid->ssid,
ssids_local[ssid_cnt].SSID_len);
if (is_ssid_in_list(ssid, hidden_ssid_list, request->n_ssids)) {
ssids_local[ssid_cnt].hidden = TRUE;
WL_PNO((">>> PNO hidden SSID (%s) \n", ssid->ssid));
@ -9291,24 +9430,17 @@ static const struct wiphy_wowlan_support brcm_wowlan_support = {
#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(3, 9, 0) */
};
#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0) */
/* terence 20161107: remove to fix:
* PC is at kfree+0x174/0x180
* LR is at nl80211_set_wowlan+0x55c/0x614 [cfg80211]
*/
#if 0
static struct cfg80211_wowlan brcm_wowlan_config = {
.disconnect = true,
.gtk_rekey_failure = true,
.eap_identity_req = true,
.four_way_handshake = true,
};
#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0) */
#endif /* CONFIG_PM */
static s32 wl_setup_wiphy(struct wireless_dev *wdev, struct device *sdiofunc_dev, dhd_pub_t *context)
{
s32 err = 0;
#ifdef CONFIG_PM
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0))
struct cfg80211_wowlan *brcm_wowlan_config = NULL;
#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0) */
#endif /* CONFIG_PM */
//#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0))
dhd_pub_t *dhd = (dhd_pub_t *)context;
BCM_REFERENCE(dhd);
@ -9445,11 +9577,20 @@ static s32 wl_setup_wiphy(struct wireless_dev *wdev, struct device *sdiofunc_dev
/* If this is not provided cfg stack will get disconnect
* during suspend.
*/
/* terence 20161107: remove to fix:
* PC is at kfree+0x174/0x180
* LR is at nl80211_set_wowlan+0x55c/0x614 [cfg80211]
*/
// wdev->wiphy->wowlan_config = &brcm_wowlan_config;
brcm_wowlan_config = kmalloc(sizeof(struct cfg80211_wowlan), GFP_KERNEL);
if (brcm_wowlan_config) {
brcm_wowlan_config->disconnect = true;
brcm_wowlan_config->gtk_rekey_failure = true;
brcm_wowlan_config->eap_identity_req = true;
brcm_wowlan_config->four_way_handshake = true;
brcm_wowlan_config->patterns = NULL;
brcm_wowlan_config->n_patterns = 0;
brcm_wowlan_config->tcp = NULL;
} else {
WL_ERR(("Can not allocate memory for brcm_wowlan_config,"
" So wiphy->wowlan_config is set to NULL\n"));
}
wdev->wiphy->wowlan_config = brcm_wowlan_config;
#else
wdev->wiphy->wowlan.flags = WIPHY_WOWLAN_ANY;
wdev->wiphy->wowlan.n_patterns = WL_WOWLAN_MAX_PATTERNS;
@ -9509,7 +9650,6 @@ static void wl_free_wdev(struct bcm_cfg80211 *cfg)
/* Reset wowlan & wowlan_config before Unregister to avoid Kernel Panic */
WL_DBG(("wl_free_wdev Clearing wowlan Config \n"));
wdev->wiphy->wowlan = NULL;
wdev->wiphy->wowlan_config = NULL;
#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0) */
#endif /* CONFIG_PM && WL_CFG80211_P2P_DEV_IF */
wiphy_unregister(wdev->wiphy);
@ -10501,7 +10641,7 @@ wl_notify_connect_status(struct bcm_cfg80211 *cfg, bcm_struct_cfgdev *cfgdev,
}
wl_update_prof(cfg, ndev, e, &act, WL_PROF_ACT);
wl_update_prof(cfg, ndev, NULL, (const void *)&e->addr, WL_PROF_BSSID);
dhd_conf_set_wme(cfg->pub);
dhd_conf_set_wme(cfg->pub, 0);
} else if (wl_is_linkdown(cfg, e)) {
#ifdef DHD_LOSSLESS_ROAMING
@ -10583,13 +10723,12 @@ wl_notify_connect_status(struct bcm_cfg80211 *cfg, bcm_struct_cfgdev *cfgdev,
if (!memcmp(ndev->name, WL_P2P_INTERFACE_PREFIX, strlen(WL_P2P_INTERFACE_PREFIX))) {
// terence 20130703: Fix for wrong group_capab (timing issue)
cfg->p2p_disconnected = 1;
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0))
if (wl_get_drv_status(cfg, DISCONNECTING, ndev)) {
CFG80211_DISCONNECTED(ndev, reason, NULL, 0,
false, GFP_KERNEL);
}
#endif
}
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0))
if (wl_get_drv_status(cfg, DISCONNECTING, ndev)) {
CFG80211_DISCONNECTED(ndev, reason, NULL, 0, false, GFP_KERNEL);
}
#endif
memcpy(&cfg->disconnected_bssid, curbssid, ETHER_ADDR_LEN);
wl_clr_drv_status(cfg, CONNECTED, ndev);
if (! wl_get_drv_status(cfg, DISCONNECTING, ndev)) {
@ -11192,7 +11331,7 @@ wl_bss_roaming_done(struct bcm_cfg80211 *cfg, struct net_device *ndev,
#endif
printf("wl_bss_roaming_done succeeded to " MACDBG "\n",
MAC2STRDBG((const u8*)(&e->addr)));
dhd_conf_set_wme(cfg->pub);
dhd_conf_set_wme(cfg->pub, 0);
cfg80211_roamed(ndev,
#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 39))
@ -11291,7 +11430,7 @@ wl_bss_connect_done(struct bcm_cfg80211 *cfg, struct net_device *ndev,
GFP_KERNEL);
if (completed) {
WL_INFORM(("Report connect result - connection succeeded\n"));
dhd_conf_set_wme(cfg->pub);
dhd_conf_set_wme(cfg->pub, 0);
} else
WL_ERR(("Report connect result - connection failed\n"));
}
@ -14411,7 +14550,7 @@ static s32 __wl_cfg80211_down(struct bcm_cfg80211 *cfg)
bool enabled = false;
dhd_wlfc_get_enable(dhd, &enabled);
if (enabled && cfg->wlfc_on && dhd->op_mode != DHD_FLAG_HOSTAP_MODE &&
dhd->op_mode != DHD_FLAG_IBSS_MODE) {
dhd->op_mode != DHD_FLAG_IBSS_MODE && dhd->conf->disable_proptx!=0) {
dhd_wlfc_deinit(dhd);
cfg->wlfc_on = false;
}
@ -14731,8 +14870,8 @@ wl_update_prof(struct bcm_cfg80211 *cfg, struct net_device *ndev,
ssid = (const wlc_ssid_t *) data;
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;
profile->ssid.SSID_len = MIN(ssid->SSID_len, DOT11_MAX_SSID_LEN);
memcpy(profile->ssid.SSID, ssid->SSID, profile->ssid.SSID_len);
break;
case WL_PROF_BSSID:
if (data)
@ -14816,6 +14955,8 @@ static void wl_update_hidden_ap_ie(struct wl_bss_info *bi, const u8 *ie_stream,
bool roam)
{
u8 *ssidie;
int32 ssid_len = MIN(bi->SSID_len, DOT11_MAX_SSID_LEN);
int32 remaining_ie_buf_len, available_buffer_len;
/* cfg80211_find_ie defined in kernel returning const u8 */
#if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == \
4 && __GNUC_MINOR__ >= 6))
@ -14827,26 +14968,41 @@ _Pragma("GCC diagnostic ignored \"-Wcast-qual\"")
4 && __GNUC_MINOR__ >= 6))
_Pragma("GCC diagnostic pop")
#endif
if (!ssidie)
/* ERROR out if
* 1. No ssid IE is FOUND or
* 2. New ssid length is > what was allocated for existing ssid (as
* we do not want to overwrite the rest of the IEs) or
* 3. If in case of erroneous buffer input where ssid length doesnt match the space
* allocated to it.
*/
if (!ssidie) {
return;
if (ssidie[1] != bi->SSID_len) {
}
available_buffer_len = ((int)(*ie_size)) - (ssidie + 2 - ie_stream);
remaining_ie_buf_len = available_buffer_len - (int)ssidie[1];
if ((ssid_len > ssidie[1]) ||
(ssidie[1] > available_buffer_len)) {
return;
}
if (ssidie[1] != ssid_len) {
if (ssidie[1]) {
WL_ERR(("%s: Wrong SSID len: %d != %d\n",
__FUNCTION__, ssidie[1], bi->SSID_len));
}
if (roam) {
WL_ERR(("Changing the SSID Info.\n"));
memmove(ssidie + bi->SSID_len + 2,
memmove(ssidie + ssid_len + 2,
(ssidie + 2) + ssidie[1],
*ie_size - (ssidie + 2 + ssidie[1] - ie_stream));
memcpy(ssidie + 2, bi->SSID, bi->SSID_len);
*ie_size = *ie_size + bi->SSID_len - ssidie[1];
ssidie[1] = bi->SSID_len;
remaining_ie_buf_len);
memcpy(ssidie + 2, bi->SSID, ssid_len);
*ie_size = *ie_size + ssid_len - ssidie[1];
ssidie[1] = ssid_len;
}
return;
}
if (*(ssidie + 2) == '\0')
memcpy(ssidie + 2, bi->SSID, bi->SSID_len);
memcpy(ssidie + 2, bi->SSID, ssid_len);
return;
}

View File

@ -753,13 +753,16 @@ wl_cfgvendor_significant_change_cfg(struct wiphy *wiphy,
gscan_swc_params_t *significant_params;
int tmp, tmp1, tmp2, type, j = 0;
const struct nlattr *outer, *inner, *iter;
uint8 flush = 0;
wl_pfn_significant_bssid_t *bssid;
significant_params = (gscan_swc_params_t *) kzalloc(len, GFP_KERNEL);
bool flush = FALSE;
wl_pfn_significant_bssid_t *pbssid;
uint16 num_bssid = 0;
uint16 max_buf_size = sizeof(gscan_swc_params_t) +
sizeof(wl_pfn_significant_bssid_t) * (PFN_SWC_MAX_NUM_APS - 1);
significant_params = kzalloc(max_buf_size, GFP_KERNEL);
if (!significant_params) {
WL_ERR(("Cannot Malloc mem to parse config commands size - %d bytes \n", len));
return -ENOMEM;
WL_ERR(("Cannot Malloc mem size:%d\n", len));
return BCME_NOMEM;
}
nla_for_each_attr(iter, data, len, tmp2) {
@ -767,7 +770,7 @@ wl_cfgvendor_significant_change_cfg(struct wiphy *wiphy,
switch (type) {
case GSCAN_ATTRIBUTE_SIGNIFICANT_CHANGE_FLUSH:
flush = nla_get_u8(iter);
flush = (bool) nla_get_u8(iter);
break;
case GSCAN_ATTRIBUTE_RSSI_SAMPLE_SIZE:
significant_params->rssi_window = nla_get_u16(iter);
@ -778,23 +781,41 @@ wl_cfgvendor_significant_change_cfg(struct wiphy *wiphy,
case GSCAN_ATTRIBUTE_MIN_BREACHING:
significant_params->swc_threshold = nla_get_u16(iter);
break;
case GSCAN_ATTRIBUTE_NUM_BSSID:
num_bssid = nla_get_u16(iter);
if (num_bssid > PFN_SWC_MAX_NUM_APS) {
WL_ERR(("ovar max SWC bssids:%d\n",
num_bssid));
err = BCME_BADARG;
goto exit;
}
break;
case GSCAN_ATTRIBUTE_SIGNIFICANT_CHANGE_BSSIDS:
bssid = significant_params->bssid_elem_list;
if (num_bssid == 0) {
WL_ERR(("num_bssid : 0\n"));
err = BCME_BADARG;
goto exit;
}
pbssid = significant_params->bssid_elem_list;
nla_for_each_nested(outer, iter, tmp) {
if (j >= num_bssid) {
j++;
break;
}
nla_for_each_nested(inner, outer, tmp1) {
switch (nla_type(inner)) {
case GSCAN_ATTRIBUTE_BSSID:
memcpy(&(bssid[j].macaddr),
nla_data(inner),
ETHER_ADDR_LEN);
memcpy(&(pbssid[j].macaddr),
nla_data(inner),
ETHER_ADDR_LEN);
break;
case GSCAN_ATTRIBUTE_RSSI_HIGH:
bssid[j].rssi_high_threshold
= (int8) nla_get_u8(inner);
pbssid[j].rssi_high_threshold =
(int8) nla_get_u8(inner);
break;
case GSCAN_ATTRIBUTE_RSSI_LOW:
bssid[j].rssi_low_threshold
= (int8) nla_get_u8(inner);
pbssid[j].rssi_low_threshold =
(int8) nla_get_u8(inner);
break;
default:
WL_ERR(("ATTR unknown %d\n",
@ -810,13 +831,19 @@ wl_cfgvendor_significant_change_cfg(struct wiphy *wiphy,
break;
}
}
if (j != num_bssid) {
WL_ERR(("swc bssids count:%d not matched to num_bssid:%d\n",
j, num_bssid));
err = BCME_BADARG;
goto exit;
}
significant_params->nbssid = j;
if (dhd_dev_pno_set_cfg_gscan(bcmcfg_to_prmry_ndev(cfg),
DHD_PNO_SIGNIFICANT_SCAN_CFG_ID,
significant_params, flush) < 0) {
WL_ERR(("Could not set GSCAN significant cfg\n"));
err = -EINVAL;
err = BCME_ERROR;
goto exit;
}
exit: