bcm4329: Sync with kernel SHA1: e3e6e272c600d7fa3d8722351129b04b0697e608
Change-Id: I1bef51c1ccfafd7822267523833e710ca17e022d
Signed-off-by: Dmitry Shmidt <dimitrysh@google.com>
diff --git a/bcm4329/src/dhd/sys/dhd_linux.c b/bcm4329/src/dhd/sys/dhd_linux.c
index ef529e7..ec211ac 100644
--- a/bcm4329/src/dhd/sys/dhd_linux.c
+++ b/bcm4329/src/dhd/sys/dhd_linux.c
@@ -22,7 +22,7 @@
* software in any way with any other Broadcom software provided under a license
* other than the GPL, without Broadcom's express prior written consent.
*
- * $Id: dhd_linux.c,v 1.65.4.9.2.12.2.60 2010/02/23 00:18:36 Exp $
+ * $Id: dhd_linux.c,v 1.65.4.9.2.12.2.60.4.4 2010/03/25 05:07:49 Exp $
*/
#ifdef CONFIG_WIFI_CONTROL_FUNC
@@ -812,8 +812,30 @@
dhd_os_wake_lock(&dhd->pub);
for (i = 0; i < DHD_MAX_IFS; i++) {
if (dhd->iflist[i]) {
+#ifdef SOFTAP
+ bool in_ap = (ap_net_dev != NULL);
+#endif /* SOFTAP */
+
if (dhd->iflist[i]->state)
dhd_op_if(dhd->iflist[i]);
+
+#ifdef SOFTAP
+ if (dhd->iflist[i] == NULL) {
+ DHD_TRACE(("%s: interface %d just been removed!\n\n", __FUNCTION__, i));
+ continue;
+ }
+
+ if (in_ap && dhd->set_macaddress) {
+ DHD_TRACE(("attempt to set MAC for %s in AP Mode blocked.\n", dhd->iflist[i]->net->name));
+ dhd->set_multicast = FALSE;
+ continue;
+ } else if (in_ap && dhd->set_multicast) {
+ DHD_TRACE(("attempt to set MULTICAST list for %s in AP Mode blocked.\n", dhd->iflist[i]->net->name));
+ dhd->set_macaddress = FALSE;
+ continue;
+ }
+#endif /* SOFTAP */
+
if (dhd->set_multicast) {
dhd->set_multicast = FALSE;
_dhd_set_multicast_list(dhd, i);
@@ -916,7 +938,8 @@
/* Reject if down */
if (!dhd->pub.up || (dhd->pub.busstate == DHD_BUS_DOWN)) {
- DHD_ERROR(("%s: xmit rejected due to dhd bus down status \n", __FUNCTION__));
+ DHD_ERROR(("%s: xmit rejected pub.up=%d busstate=%d\n",
+ __FUNCTION__, dhd->pub.up, dhd->pub.busstate));
netif_stop_queue(net);
return -ENODEV;
}
diff --git a/bcm4329/src/include/epivers.h b/bcm4329/src/include/epivers.h
index 8137f60..4957e1a 100644
--- a/bcm4329/src/include/epivers.h
+++ b/bcm4329/src/include/epivers.h
@@ -33,16 +33,16 @@
#define EPI_RC_NUMBER 204
-#define EPI_INCREMENTAL_NUMBER 1
+#define EPI_INCREMENTAL_NUMBER 3
#define EPI_BUILD_NUMBER 0
-#define EPI_VERSION 4, 218, 204, 1
+#define EPI_VERSION 4, 218, 204, 3
-#define EPI_VERSION_NUM 0x04dacc01
+#define EPI_VERSION_NUM 0x04dacc03
-#define EPI_VERSION_STR "4.218.204.1"
-#define EPI_ROUTER_VERSION_STR "4.219.204.1"
+#define EPI_VERSION_STR "4.218.204.3"
+#define EPI_ROUTER_VERSION_STR "4.219.204.3"
#endif
diff --git a/bcm4329/src/wl/sys/wl_iw.c b/bcm4329/src/wl/sys/wl_iw.c
index e324dd3..f44fba9 100644
--- a/bcm4329/src/wl/sys/wl_iw.c
+++ b/bcm4329/src/wl/sys/wl_iw.c
@@ -21,7 +21,7 @@
* software in any way with any other Broadcom software provided under a license
* other than the GPL, without Broadcom's express prior written consent.
*
- * $Id: wl_iw.c,v 1.51.4.9.2.6.4.84.2.3 2010/03/16 22:09:45 Exp $
+ * $Id: wl_iw.c,v 1.51.4.9.2.6.4.84.2.10 2010/03/25 07:22:21 Exp $
*/
@@ -77,6 +77,7 @@
static int g_onoff = G_WLAN_SET_ON;
static struct mutex wl_start_lock;
+static struct mutex wl_cache_lock;
extern bool wl_iw_conn_status_str(uint32 event_type, uint32 status,
uint32 reason, char* stringBuf, uint buflen);
@@ -1875,7 +1876,6 @@
if (!extra)
return -EINVAL;
-
list = kmalloc(buflen, GFP_KERNEL);
if (!list)
return -ENOMEM;
@@ -1929,7 +1929,6 @@
dwrq->flags = 1;
}
-
return 0;
}
@@ -2004,7 +2003,6 @@
dwrq->flags = 1;
}
-
return 0;
}
@@ -2101,7 +2099,7 @@
wl_scan_results_t *results;
uint32 status;
-
+ mutex_lock(&wl_cache_lock);
if (iscan->list_cur) {
buf = iscan->list_cur;
iscan->list_cur = buf->next;
@@ -2111,6 +2109,7 @@
if (!buf) {
WL_ERROR(("%s can't alloc iscan_buf_t : going to abort currect iscan\n", \
__FUNCTION__));
+ mutex_unlock(&wl_cache_lock);
return WL_SCAN_RESULTS_NO_MEM;
}
buf->next = NULL;
@@ -2147,6 +2146,7 @@
WL_TRACE(("results->buflen = %d\n", results->buflen));
status = dtoh32(list_buf->status);
+ mutex_unlock(&wl_cache_lock);
return status;
}
@@ -2312,6 +2312,7 @@
WL_TRACE(("%s called\n", __FUNCTION__));
+ mutex_lock(&wl_cache_lock);
spec_scan_head = &g_ss_cache_ctrl.m_cache_head;
node = *spec_scan_head;
@@ -2322,6 +2323,7 @@
kfree(cur);
}
*spec_scan_head = NULL;
+ mutex_unlock(&wl_cache_lock);
}
@@ -2367,6 +2369,7 @@
wl_iw_ss_cache_t *node, *prev, *cur;
wl_iw_ss_cache_t **spec_scan_head;
+ mutex_lock(&wl_cache_lock);
spec_scan_head = &g_ss_cache_ctrl.m_cache_head;
node = *spec_scan_head;
prev = node;
@@ -2393,7 +2396,7 @@
prev = node;
node = node->next;
}
-
+ mutex_unlock(&wl_cache_lock);
}
@@ -2406,13 +2409,13 @@
wl_bss_info_t *bi = NULL;
int i;
- spec_scan_head = &g_ss_cache_ctrl.m_cache_head;
-
if (!ss_list->count) {
return 0;
}
-
+ mutex_lock(&wl_cache_lock);
+ spec_scan_head = &g_ss_cache_ctrl.m_cache_head;
+
for (i = 0; i < ss_list->count; i++) {
node = *spec_scan_head;
@@ -2437,6 +2440,7 @@
}
leaf = kmalloc(WLC_IW_SS_CACHE_MAXLEN, GFP_KERNEL);
if (!leaf) {
+ mutex_unlock(&wl_cache_lock);
return -ENOMEM;
}
@@ -2459,8 +2463,8 @@
prev->next = leaf;
}
}
+ mutex_unlock(&wl_cache_lock);
return 0;
-
}
@@ -2471,6 +2475,7 @@
wl_iw_ss_cache_t *node;
wl_scan_results_t *list_merge;
+ mutex_lock(&wl_cache_lock);
node = g_ss_cache_ctrl.m_cache_head;
for (;node;) {
list_merge = (wl_scan_results_t *)node;
@@ -2485,6 +2490,7 @@
}
node = node->next;
}
+ mutex_unlock(&wl_cache_lock);
return 0;
}
@@ -2496,6 +2502,7 @@
wl_iw_ss_cache_t *node, *prev;
wl_iw_ss_cache_t **spec_scan_head;
+ mutex_lock(&wl_cache_lock);
spec_scan_head = &g_ss_cache_ctrl.m_cache_head;
node = *spec_scan_head;
prev = node;
@@ -2518,8 +2525,8 @@
}
memset(addr, 0, ETHER_ADDR_LEN);
+ mutex_unlock(&wl_cache_lock);
return 0;
-
}
@@ -2915,7 +2922,6 @@
iscan_buf_t * p_buf;
uint32 counter = 0;
#endif
-
WL_TRACE(("%s: buflen_from_user %d: \n", dev->name, buflen_from_user));
if (!extra) {
@@ -2988,6 +2994,7 @@
kfree(list);
}
+ mutex_lock(&wl_cache_lock);
#if defined(WL_IW_USE_ISCAN)
if (g_scan_specified_ssid)
WL_TRACE(("%s: Specified scan APs from scan=%d\n", __FUNCTION__, list->count));
@@ -3007,11 +3014,11 @@
list_merge = (wl_scan_results_t *) g_scan;
len_ret = (__u16) wl_iw_get_scan_prep(list_merge, info, extra, buflen_from_user);
#endif
+ mutex_unlock(&wl_cache_lock);
if (g_ss_cache_ctrl.m_link_down) {
-
wl_iw_delete_bss_from_ss_cache(g_ss_cache_ctrl.m_active_bssid);
}
-
+
wl_iw_merge_scan_cache(info, extra+len_ret, buflen_from_user-len_ret, &merged_len);
len_ret += merged_len;
wl_iw_run_ss_cache_timer(0);
@@ -3078,8 +3085,6 @@
return wl_iw_get_scan(dev, info, dwrq, extra);
}
-
-
if (g_ss_cache_ctrl.m_timer_expired) {
wl_iw_free_ss_cache();
g_ss_cache_ctrl.m_timer_expired ^= 1;
@@ -3089,12 +3094,11 @@
}
else {
if (g_ss_cache_ctrl.m_link_down) {
-
wl_iw_delete_bss_from_ss_cache(g_ss_cache_ctrl.m_active_bssid);
}
if (g_ss_cache_ctrl.m_prev_scan_mode || g_ss_cache_ctrl.m_cons_br_scan_cnt > 4) {
g_ss_cache_ctrl.m_cons_br_scan_cnt = 0;
-
+
wl_iw_reset_ss_cache();
}
g_ss_cache_ctrl.m_prev_scan_mode = g_scan_specified_ssid;
@@ -3198,7 +3202,6 @@
dwrq->length = event - extra;
dwrq->flags = 0;
-
wl_iw_merge_scan_cache(info, event, buflen_from_user - dwrq->length, &merged_len);
dwrq->length += merged_len;
wl_iw_run_ss_cache_timer(0);
@@ -3208,7 +3211,6 @@
WL_TRACE(("%s return to WE %d bytes APs=%d\n", __FUNCTION__, dwrq->length, counter));
-
if (!dwrq->length)
return -EAGAIN;
@@ -4728,11 +4730,24 @@
ASSERT(iolen);
res |= dev_wlc_ioctl(dev, WLC_SET_VAR, buf, iolen);
+ if (res != 0) {
+ WL_ERROR(("ERROR:%d in:%s, Security & BSS reconfiguration is skipped\n",
+ res, __FUNCTION__));
+ return res;
+ }
+
if (!ap_cfg_running) {
kernel_thread(thr_wait_for_2nd_eth_dev, 0, 0);
} else {
- WL_TRACE(("%s: Configure security & restart AP bss \n", __FUNCTION__));
- res |= wl_iw_set_ap_security(dev, &my_ap);
+ if (ap_net_dev == NULL) {
+ WL_ERROR(("%s: ERROR: ap_net_dev is NULL !!!\n",__FUNCTION__));
+ return -1;
+ }
+
+ /* if the AP interface wl0.1 already exists we call security & bss UP in here */
+ WL_ERROR(("%s: %s Configure security & restart AP bss\n", __FUNCTION__, ap_net_dev->name));
+
+ res |= wl_iw_set_ap_security(ap_net_dev, &my_ap);
res |= dev_iw_write_cfg1_bss_var(dev, 1);
}
return res;
@@ -4964,21 +4979,70 @@
}
+static int wl_iw_softap_deassoc_stations(struct net_device *dev)
+{
+ int i;
+ int res = 0;
+ char mac_buf[128] = {0};
+ struct maclist *assoc_maclist = (struct maclist *)mac_buf;
+
+ memset(assoc_maclist, 0, sizeof(mac_buf));
+ assoc_maclist->count = 8;
+
+ res = dev_wlc_ioctl(dev, WLC_GET_ASSOCLIST, assoc_maclist, 128);
+ if (res != 0) {
+ WL_SOFTAP((" Error:%d in :%s, Couldn't get ASSOC List\n", res, __FUNCTION__));
+ return res;
+ }
+
+ if (assoc_maclist->count) {
+ for (i = 0; i < assoc_maclist->count; i++) {
+ scb_val_t scbval;
+
+ scbval.val = htod32(1);
+ bcopy(&assoc_maclist->ea[i], &scbval.ea, ETHER_ADDR_LEN);
+
+ WL_SOFTAP(("deauth STA:%d \n", i));
+ res |= dev_wlc_ioctl(dev, WLC_SCB_DEAUTHENTICATE_FOR_REASON,
+ &scbval, sizeof(scb_val_t));
+ }
+ } else {
+ WL_SOFTAP((" STA ASSOC list is empty\n"));
+ }
+
+ if (res != 0)
+ WL_SOFTAP((" Error:%d in :%s\n", res, __FUNCTION__));
+ return res;
+}
+
+
static int iwpriv_softap_stop(struct net_device *dev,
struct iw_request_info *info,
union iwreq_data *wrqu,
char *ext)
{
- int res;
+ int res = 0;
+ char buf[128];
- WL_SOFTAP((" iw_handler SOFTAP_STP \n"));
+ WL_SOFTAP(("got iwpriv AP_BSS_STOP\n"));
- ap_mode = 0;
- ap_cfg_running = FALSE;
+ if ((!dev) && (!ap_net_dev)) {
+ WL_ERROR(("%s: dev is null\n", __FUNCTION__));
+ return res;
+ }
- res = dev_iw_write_cfg1_bss_var(dev, 2);
+ /* Make sure that interface is UP */
+ strcpy(buf, "cur_etheraddr");
+ dev_wlc_ioctl(dev, WLC_GET_VAR, buf, sizeof(buf));
+
+ res = wl_iw_softap_deassoc_stations(ap_net_dev);
+
+ bcm_mdelay(200);
+ res |= dev_iw_write_cfg1_bss_var(dev, 2);
wrqu->data.length = 0;
+ ap_mode = 0;
+ ap_cfg_running = FALSE;
return res;
}
@@ -6114,13 +6178,11 @@
#endif
if (set == TRUE) {
-
- dev_wlc_bufvar_set(dev, "btc_flags", \
+ dev_wlc_bufvar_set(dev, "btc_flags",
(char *)&buf_flag7_dhcp_on[0], sizeof(buf_flag7_dhcp_on));
}
else {
-
- dev_wlc_bufvar_set(dev, "btc_flags", \
+ dev_wlc_bufvar_set(dev, "btc_flags",
(char *)&buf_flag7_default[0], sizeof(buf_flag7_default));
}
@@ -6135,7 +6197,7 @@
bt_info_t *bt_local = (bt_info_t *)data;
bt_local->timer_on = 0;
WL_TRACE(("%s\n", __FUNCTION__));
-
+
up(&bt_local->bt_sem);
}
@@ -6155,13 +6217,12 @@
switch (g_bt->bt_state) {
case BT_DHCP_START:
-
g_bt->bt_state = BT_DHCP_OPPORTUNITY_WINDOW;
mod_timer(&g_bt->timer, jiffies + BT_DHCP_OPPORTUNITY_WINDOW_TIEM*HZ/1000);
g_bt->timer_on = 1;
break;
+
case BT_DHCP_OPPORTUNITY_WINDOW:
-
WL_TRACE(("%s waiting for %d msec expired, force bt flag\n", \
__FUNCTION__, BT_DHCP_OPPORTUNITY_WINDOW_TIEM));
if (g_bt->dev) wl_iw_bt_flag_set(g_bt->dev, TRUE);
@@ -6169,8 +6230,8 @@
mod_timer(&g_bt->timer, jiffies + BT_DHCP_FLAG_FORCE_TIME*HZ/1000);
g_bt->timer_on = 1;
break;
+
case BT_DHCP_FLAG_FORCE_TIMEOUT:
-
WL_TRACE(("%s waiting for %d msec expired remove bt flag\n", \
__FUNCTION__, BT_DHCP_FLAG_FORCE_TIME));
@@ -6178,6 +6239,7 @@
g_bt->bt_state = BT_DHCP_IDLE;
g_bt->timer_on = 0;
break;
+
default:
WL_ERROR(("%s error g_status=%d !!!\n", __FUNCTION__, \
g_bt->bt_state));
@@ -6252,7 +6314,12 @@
wl_iw_t *iw;
#if defined(WL_IW_USE_ISCAN)
iscan_info_t *iscan = NULL;
+#endif
+ mutex_init(&wl_cache_lock);
+ mutex_init(&wl_start_lock);
+
+#if defined(WL_IW_USE_ISCAN)
if (!dev)
return 0;
@@ -6268,7 +6335,6 @@
g_first_broadcast_scan = BROADCAST_SCAN_FIRST_IDLE;
g_iscan->scan_flag = 0;
-
iscan->timer_ms = 3000;
init_timer(&iscan->timer);
iscan->timer.data = (ulong)iscan;
@@ -6279,14 +6345,12 @@
iscan->sysioc_pid = kernel_thread(_iscan_sysioc_thread, iscan, 0);
if (iscan->sysioc_pid < 0)
return -ENOMEM;
-#endif
- mutex_init(&wl_start_lock);
+#endif
iw = *(wl_iw_t **)netdev_priv(dev);
iw->pub = (dhd_pub_t *)dhdp;
g_scan = NULL;
-
g_scan = (void *)kmalloc(G_SCAN_RESULTS, GFP_KERNEL);
if (!g_scan)
return -ENOMEM;
@@ -6295,7 +6359,7 @@
g_scan_specified_ssid = 0;
wl_iw_init_ss_cache_ctrl();
-
+
wl_iw_bt_init(dev);
#ifdef SOFTAP
@@ -6317,7 +6381,7 @@
KILL_PROC(iscan->sysioc_pid, SIGTERM);
wait_for_completion(&iscan->sysioc_exited);
}
-
+ mutex_lock(&wl_cache_lock);
while (iscan->list_hdr) {
buf = iscan->list_hdr->next;
kfree(iscan->list_hdr);
@@ -6325,6 +6389,7 @@
}
kfree(iscan);
g_iscan = NULL;
+ mutex_unlock(&wl_cache_lock);
#endif
if (g_scan)
@@ -6333,7 +6398,6 @@
g_scan = NULL;
wl_iw_release_ss_cache_ctrl();
wl_iw_bt_release();
-
#ifdef SOFTAP
if (ap_mode) {
WL_TRACE(("\n%s AP is going down\n", __FUNCTION__));