aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJohn Stultz <john.stultz@linaro.org>2011-09-14 12:03:58 -0700
committerJohn Stultz <john.stultz@linaro.org>2011-09-14 12:03:58 -0700
commit3f1fc539a29e09d940df1418b36d23621f85d545 (patch)
tree2693bc745b788a753adaebfbb98635436adf55bb
parent3b728cae2f6a04b80c0df33a874b141d14a3d965 (diff)
parent5cb5fb6fef3fd81b55ddc48010e1b520e8473553 (diff)
downloadsnowball-3f1fc539a29e09d940df1418b36d23621f85d545.tar.gz
Merge branch 'upstream/android-3.0' into linaro-android-3.0
-rw-r--r--arch/arm/Kconfig9
-rw-r--r--arch/arm/kernel/process.c30
-rw-r--r--drivers/net/wireless/bcmdhd/Makefile2
-rw-r--r--drivers/net/wireless/bcmdhd/bcmsdh_linux.c9
-rw-r--r--drivers/net/wireless/bcmdhd/dhd.h1
-rw-r--r--drivers/net/wireless/bcmdhd/dhd_bus.h5
-rw-r--r--drivers/net/wireless/bcmdhd/dhd_cdc.c50
-rw-r--r--drivers/net/wireless/bcmdhd/dhd_common.c38
-rw-r--r--drivers/net/wireless/bcmdhd/dhd_linux.c7
-rw-r--r--drivers/net/wireless/bcmdhd/dhd_linux_mon.c4
-rw-r--r--drivers/net/wireless/bcmdhd/dhd_sdio.c6
-rw-r--r--drivers/net/wireless/bcmdhd/include/epivers.h8
-rw-r--r--drivers/net/wireless/bcmdhd/include/sdio.h5
-rw-r--r--drivers/net/wireless/bcmdhd/include/wlioctl.h5
-rw-r--r--drivers/net/wireless/bcmdhd/wl_cfg80211.c83
-rw-r--r--drivers/net/wireless/bcmdhd/wl_cfg80211.h1
-rw-r--r--drivers/net/wireless/bcmdhd/wl_cfgp2p.c14
-rw-r--r--drivers/net/wireless/bcmdhd/wl_cfgp2p.h1
-rw-r--r--drivers/net/wireless/bcmdhd/wl_iw.c100
-rw-r--r--fs/ext4/inode.c7
-rw-r--r--net/netfilter/xt_qtaguid.c88
21 files changed, 327 insertions, 146 deletions
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index 3a232545197..cd0c9523496 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -1710,6 +1710,15 @@ config DEPRECATED_PARAM_STRUCT
This was deprecated in 2001 and announced to live on for 5 years.
Some old boot loaders still use this way.
+config ARM_FLUSH_CONSOLE_ON_RESTART
+ bool "Force flush the console on restart"
+ help
+ If the console is locked while the system is rebooted, the messages
+ in the temporary logbuffer would not have propogated to all the
+ console drivers. This option forces the console lock to be
+ released if it failed to be acquired, which will cause all the
+ pending messages to be flushed.
+
endmenu
menu "Boot options"
diff --git a/arch/arm/kernel/process.c b/arch/arm/kernel/process.c
index 919de7c84f7..34fca2e272c 100644
--- a/arch/arm/kernel/process.c
+++ b/arch/arm/kernel/process.c
@@ -30,6 +30,7 @@
#include <linux/uaccess.h>
#include <linux/random.h>
#include <linux/hw_breakpoint.h>
+#include <linux/console.h>
#include <asm/cacheflush.h>
#include <asm/processor.h>
@@ -90,8 +91,37 @@ static int __init hlt_setup(char *__unused)
__setup("nohlt", nohlt_setup);
__setup("hlt", hlt_setup);
+#ifdef CONFIG_ARM_FLUSH_CONSOLE_ON_RESTART
+void arm_machine_flush_console(void)
+{
+ printk("\n");
+ pr_emerg("Restarting %s\n", linux_banner);
+ if (console_trylock()) {
+ console_unlock();
+ return;
+ }
+
+ mdelay(50);
+
+ local_irq_disable();
+ if (!console_trylock())
+ pr_emerg("arm_restart: Console was locked! Busting\n");
+ else
+ pr_emerg("arm_restart: Console was locked!\n");
+ console_unlock();
+}
+#else
+void arm_machine_flush_console(void)
+{
+}
+#endif
+
void arm_machine_restart(char mode, const char *cmd)
{
+ /* Flush the console to make sure all the relevant messages make it
+ * out to the console drivers */
+ arm_machine_flush_console();
+
/* Disable interrupts first */
local_irq_disable();
local_fiq_disable();
diff --git a/drivers/net/wireless/bcmdhd/Makefile b/drivers/net/wireless/bcmdhd/Makefile
index 56500b7220c..e82c9856f00 100644
--- a/drivers/net/wireless/bcmdhd/Makefile
+++ b/drivers/net/wireless/bcmdhd/Makefile
@@ -1,5 +1,5 @@
# bcmdhd
-DHDCFLAGS = -Wall -Wstrict-prototypes -Werror -Dlinux -DBCMDRIVER \
+DHDCFLAGS = -Wall -Wstrict-prototypes -Dlinux -DBCMDRIVER \
-DBCMDONGLEHOST -DUNRELEASEDCHIP -DBCMDMA32 -DWLBTAMP -DBCMFILEIMAGE \
-DDHDTHREAD -DDHD_GPL -DDHD_SCHED -DDHD_DEBUG -DSDTEST -DBDC -DTOE \
-DDHD_BCMEVENTS -DSHOW_EVENTS -DDONGLEOVERLAYS -DBCMDBG \
diff --git a/drivers/net/wireless/bcmdhd/bcmsdh_linux.c b/drivers/net/wireless/bcmdhd/bcmsdh_linux.c
index 6fa47378cfe..a4dc6ff4042 100644
--- a/drivers/net/wireless/bcmdhd/bcmsdh_linux.c
+++ b/drivers/net/wireless/bcmdhd/bcmsdh_linux.c
@@ -48,15 +48,6 @@ extern void dhdsdio_isr(void * args);
#include <dngl_stats.h>
#include <dhd.h>
#endif /* defined(OOB_INTR_ONLY) */
-#if defined(CONFIG_MACH_SANDGATE2G) || defined(CONFIG_MACH_LOGICPD_PXA270)
-#if !defined(BCMPLATFORM_BUS)
-#define BCMPLATFORM_BUS
-#endif /* !defined(BCMPLATFORM_BUS) */
-
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 19))
-#include <linux/platform_device.h>
-#endif /* KERNEL_VERSION(2, 6, 19) */
-#endif /* CONFIG_MACH_SANDGATE2G || CONFIG_MACH_LOGICPD_PXA270 */
/**
* SDIO Host Controller info
diff --git a/drivers/net/wireless/bcmdhd/dhd.h b/drivers/net/wireless/bcmdhd/dhd.h
index b0df6c77200..281e047af85 100644
--- a/drivers/net/wireless/bcmdhd/dhd.h
+++ b/drivers/net/wireless/bcmdhd/dhd.h
@@ -430,6 +430,7 @@ extern void dhd_timeout_start(dhd_timeout_t *tmo, uint usec);
extern int dhd_timeout_expired(dhd_timeout_t *tmo);
extern int dhd_ifname2idx(struct dhd_info *dhd, char *name);
+extern int dhd_net2idx(struct dhd_info *dhd, struct net_device *net);
extern struct net_device * dhd_idx2net(struct dhd_pub *dhd_pub, int ifidx);
extern int wl_host_event(dhd_pub_t *dhd_pub, int *idx, void *pktdata,
wl_event_msg_t *, void **data_ptr);
diff --git a/drivers/net/wireless/bcmdhd/dhd_bus.h b/drivers/net/wireless/bcmdhd/dhd_bus.h
index 294322026e9..bccb8b6603f 100644
--- a/drivers/net/wireless/bcmdhd/dhd_bus.h
+++ b/drivers/net/wireless/bcmdhd/dhd_bus.h
@@ -48,6 +48,11 @@ extern void dhd_bus_stop(struct dhd_bus *bus, bool enforce_mutex);
/* Initialize bus module: prepare for communication w/dongle */
extern int dhd_bus_init(dhd_pub_t *dhdp, bool enforce_mutex);
+/* Get the Bus Idle Time */
+extern void dhd_bus_getidletime(dhd_pub_t *dhdp, int *idletime);
+
+/* Set the Bus Idle Time*/
+extern void dhd_bus_setidletime(dhd_pub_t *dhdp, int idle_time);
/* Send a data frame to the dongle. Callee disposes of txp. */
extern int dhd_bus_txdata(struct dhd_bus *bus, void *txp);
diff --git a/drivers/net/wireless/bcmdhd/dhd_cdc.c b/drivers/net/wireless/bcmdhd/dhd_cdc.c
index fde8a35f289..0f9893a1537 100644
--- a/drivers/net/wireless/bcmdhd/dhd_cdc.c
+++ b/drivers/net/wireless/bcmdhd/dhd_cdc.c
@@ -916,7 +916,10 @@ _dhd_wlfc_send_signalonly_packet(athost_wl_status_info_t* ctx, wlfc_mac_descript
#ifdef PROP_TXSTATUS_DEBUG
ctx->stats.signal_only_pkts_sent++;
#endif
- dhd_bus_txdata(((dhd_pub_t *)ctx->dhdp)->bus, p);
+ rc = dhd_bus_txdata(((dhd_pub_t *)ctx->dhdp)->bus, p);
+ if (rc != BCME_OK) {
+ PKTFREE(ctx->osh, p, TRUE);
+ }
}
else {
DHD_ERROR(("%s: couldn't allocate new %d-byte packet\n",
@@ -2236,49 +2239,6 @@ dhd_prot_dstats(dhd_pub_t *dhd)
return;
}
-int dhd_set_suspend(int value, dhd_pub_t *dhd)
-{
- int power_mode = PM_MAX;
- wl_pkt_filter_enable_t enable_parm;
- char iovbuf[32];
- int bcn_li_dtim = 3;
-
-#define htod32(i) i
-
- if (dhd && dhd->up) {
- if (value) {
- dhd_wl_ioctl_cmd(dhd, WLC_SET_PM,
- (char *)&power_mode, sizeof(power_mode), TRUE, 0);
- /* Enable packet filter, only allow unicast packet to send up */
- enable_parm.id = htod32(100);
- enable_parm.enable = htod32(1);
- bcm_mkiovar("pkt_filter_enable", (char *)&enable_parm,
- sizeof(wl_pkt_filter_enable_t), iovbuf, sizeof(iovbuf));
- dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, sizeof(iovbuf), TRUE, 0);
- /* set bcn_li_dtim */
- bcm_mkiovar("bcn_li_dtim", (char *)&bcn_li_dtim,
- 4, iovbuf, sizeof(iovbuf));
- dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, sizeof(iovbuf), TRUE, 0);
- } else {
- power_mode = PM_FAST;
- dhd_wl_ioctl_cmd(dhd, WLC_SET_PM, (char *)&power_mode,
- sizeof(power_mode), TRUE, 0);
- /* disable pkt filter */
- enable_parm.id = htod32(100);
- enable_parm.enable = htod32(0);
- bcm_mkiovar("pkt_filter_enable", (char *)&enable_parm,
- sizeof(wl_pkt_filter_enable_t), iovbuf, sizeof(iovbuf));
- dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, sizeof(iovbuf), TRUE, 0);
- /* set bcn_li_dtim */
- bcn_li_dtim = 0;
- bcm_mkiovar("bcn_li_dtim", (char *)&bcn_li_dtim,
- 4, iovbuf, sizeof(iovbuf));
- dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, sizeof(iovbuf), TRUE, 0);
- }
- }
-
- return 0;
-}
int
dhd_prot_init(dhd_pub_t *dhd)
@@ -2300,7 +2260,9 @@ dhd_prot_init(dhd_pub_t *dhd)
ret = dhd_wlfc_init(dhd);
#endif
+#ifndef WL_CFG80211
ret = dhd_preinit_ioctls(dhd);
+#endif /* WL_CFG80211 */
/* Always assumes wl for now */
dhd->iswl = TRUE;
diff --git a/drivers/net/wireless/bcmdhd/dhd_common.c b/drivers/net/wireless/bcmdhd/dhd_common.c
index 66d60420069..f6bb8e5bb56 100644
--- a/drivers/net/wireless/bcmdhd/dhd_common.c
+++ b/drivers/net/wireless/bcmdhd/dhd_common.c
@@ -70,6 +70,7 @@ char nv_path[MOD_PARAM_PATHLEN];
#ifdef SOFTAP
char fw_path2[MOD_PARAM_PATHLEN];
+extern bool softap_enabled;
#endif
/* Last connection success/failure status */
@@ -1534,7 +1535,9 @@ dhd_preinit_ioctls(dhd_pub_t *dhd)
uint32 glom = 0;
uint bcn_timeout = 4;
uint retry_max = 3;
+#if defined(ARP_OFFLOAD_SUPPORT)
int arpoe = 1;
+#endif
int scan_assoc_time = 40;
int scan_unassoc_time = 40;
const char *str;
@@ -1589,7 +1592,7 @@ dhd_preinit_ioctls(dhd_pub_t *dhd)
#endif /* GET_CUSTOM_MAC_ENABLE */
#ifdef SET_RANDOM_MAC_SOFTAP
- if (strstr(fw_path, "apsta") != NULL) {
+ if (strstr(fw_path, "_apsta") != NULL) {
uint rand_mac;
srandom32((uint)jiffies);
@@ -1610,6 +1613,7 @@ dhd_preinit_ioctls(dhd_pub_t *dhd)
}
#endif /* SET_RANDOM_MAC_SOFTAP */
+ DHD_TRACE(("Firmware = %s\n", fw_path));
#if !defined(AP) && defined(WLP2P)
/* Check if firmware with WFD support used */
if (strstr(fw_path, "_p2p") != NULL) {
@@ -1619,7 +1623,10 @@ dhd_preinit_ioctls(dhd_pub_t *dhd)
DHD_ERROR(("%s APSTA for WFD failed ret= %d\n", __FUNCTION__, ret));
} else {
dhd->op_mode |= WFD_MASK;
+#if defined(ARP_OFFLOAD_SUPPORT)
arpoe = 0;
+#endif /* (ARP_OFFLOAD_SUPPORT) */
+ dhd_pkt_filter_enable = FALSE;
}
}
#endif /* !defined(AP) && defined(WLP2P) */
@@ -1634,10 +1641,19 @@ dhd_preinit_ioctls(dhd_pub_t *dhd)
DHD_ERROR(("%s mpc for HostAPD failed %d\n", __FUNCTION__, ret));
} else {
dhd->op_mode |= HOSTAPD_MASK;
+#if defined(ARP_OFFLOAD_SUPPORT)
arpoe = 0;
+#endif /* (ARP_OFFLOAD_SUPPORT) */
+ dhd_pkt_filter_enable = FALSE;
}
}
#endif /* !defined(AP) && defined(WL_CFG80211) */
+
+ if ((dhd->op_mode != WFD_MASK) && (dhd->op_mode != HOSTAPD_MASK)) {
+ /* STA only operation mode */
+ dhd->op_mode |= STA_MASK;
+ dhd_pkt_filter_enable = TRUE;
+ }
DHD_ERROR(("Firmware up: op_mode=%d, "
"Broadcom Dongle Host Driver mac=%.2x:%.2x:%.2x:%.2x:%.2x:%.2x\n",
dhd->op_mode,
@@ -2089,6 +2105,17 @@ exit:
return bcn_li_dtim;
}
+/* Check if HostAPD or WFD mode setup */
+bool dhd_check_ap_wfd_mode_set(dhd_pub_t *dhd)
+{
+#ifdef WL_CFG80211
+ if (((dhd->op_mode & HOSTAPD_MASK) == HOSTAPD_MASK) ||
+ ((dhd->op_mode & WFD_MASK) == WFD_MASK))
+ return TRUE;
+ else
+#endif /* WL_CFG80211 */
+ return FALSE;
+}
#ifdef PNO_SUPPORT
int
@@ -2133,6 +2160,8 @@ dhd_pno_enable(dhd_pub_t *dhd, int pfn_enabled)
return ret;
}
+ if (dhd_check_ap_wfd_mode_set(dhd) == TRUE)
+ return (ret);
memset(iovbuf, 0, sizeof(iovbuf));
/* Check if disassoc to enable pno */
if ((pfn_enabled) &&
@@ -2180,6 +2209,8 @@ dhd_pno_set(dhd_pub_t *dhd, wlc_ssid_t* ssids_local, int nssid, ushort scan_fr,
DHD_ERROR(("%s error exit\n", __FUNCTION__));
err = -1;
}
+ if (dhd_check_ap_wfd_mode_set(dhd) == TRUE)
+ return (err);
/* Check for broadcast ssid */
for (k = 0; k < nssid; k++) {
@@ -2296,7 +2327,10 @@ int dhd_keep_alive_onoff(dhd_pub_t *dhd)
int str_len;
int res = -1;
- DHD_ERROR(("%s Enter\n", __FUNCTION__));
+ if (dhd_check_ap_wfd_mode_set(dhd) == TRUE)
+ return (res);
+
+ DHD_TRACE(("%s execution\n", __FUNCTION__));
str = "mkeep_alive";
str_len = strlen(str);
diff --git a/drivers/net/wireless/bcmdhd/dhd_linux.c b/drivers/net/wireless/bcmdhd/dhd_linux.c
index d07b3ca9e33..03ba34a2c82 100644
--- a/drivers/net/wireless/bcmdhd/dhd_linux.c
+++ b/drivers/net/wireless/bcmdhd/dhd_linux.c
@@ -671,7 +671,7 @@ dhd_timeout_expired(dhd_timeout_t *tmo)
return 0;
}
-static int
+int
dhd_net2idx(dhd_info_t *dhd, struct net_device *net)
{
int i = 0;
@@ -1022,10 +1022,10 @@ dhd_op_if(dhd_if_t *ifp)
free_netdev(ifp->net);
}
dhd->iflist[ifp->idx] = NULL;
- MFREE(dhd->pub.osh, ifp, sizeof(*ifp));
#ifdef WL_CFG80211
- if (dhd->dhd_state & DHD_ATTACH_STATE_CFG80211)
+ if (dhd->dhd_state & DHD_ATTACH_STATE_CFG80211) {
wl_cfg80211_notify_ifdel(ifp->net);
+ }
#endif
#ifdef SOFTAP
flags = dhd_os_spin_lock(&dhd->pub);
@@ -1033,6 +1033,7 @@ dhd_op_if(dhd_if_t *ifp)
ap_net_dev = NULL; /* NULL SOFTAP global wl0.1 as well */
dhd_os_spin_unlock(&dhd->pub, flags);
#endif /* SOFTAP */
+ MFREE(dhd->pub.osh, ifp, sizeof(*ifp));
}
}
diff --git a/drivers/net/wireless/bcmdhd/dhd_linux_mon.c b/drivers/net/wireless/bcmdhd/dhd_linux_mon.c
index 6c1ff4d8ad4..dd9c71f75be 100644
--- a/drivers/net/wireless/bcmdhd/dhd_linux_mon.c
+++ b/drivers/net/wireless/bcmdhd/dhd_linux_mon.c
@@ -106,8 +106,10 @@ static struct net_device* lookup_real_netdev(char *name)
for (i = 0; i < DHD_MAX_IFS; i++) {
ndev = dhd_idx2net(g_monitor.dhd_pub, i);
if (ndev && strstr(name, ndev->name)) {
- if (strlen(ndev->name) > last_name_len)
+ if (strlen(ndev->name) > last_name_len) {
ndev_found = ndev;
+ last_name_len = strlen(ndev->name);
+ }
}
}
diff --git a/drivers/net/wireless/bcmdhd/dhd_sdio.c b/drivers/net/wireless/bcmdhd/dhd_sdio.c
index 50bc7e4190d..6d89f6b984a 100644
--- a/drivers/net/wireless/bcmdhd/dhd_sdio.c
+++ b/drivers/net/wireless/bcmdhd/dhd_sdio.c
@@ -77,11 +77,7 @@
#define TXRETRIES 2 /* # of retries for tx frames */
-#if defined(CONFIG_MACH_SANDGATE2G)
-#define DHD_RXBOUND 250 /* Default for max rx frames in one scheduling */
-#else
#define DHD_RXBOUND 50 /* Default for max rx frames in one scheduling */
-#endif /* defined(CONFIG_MACH_SANDGATE2G) */
#define DHD_TXBOUND 20 /* Default for max tx frames in one scheduling */
@@ -1846,6 +1842,8 @@ dhdsdio_readshared(dhd_bus_t *bus, sdpcm_shared_t *sh)
sh->console_addr = ltoh32(sh->console_addr);
sh->msgtrace_addr = ltoh32(sh->msgtrace_addr);
+ if ((sh->flags & SDPCM_SHARED_VERSION_MASK) == 3 && SDPCM_SHARED_VERSION == 1)
+ return BCME_OK;
if ((sh->flags & SDPCM_SHARED_VERSION_MASK) != SDPCM_SHARED_VERSION) {
DHD_ERROR(("%s: sdpcm_shared version %d in dhd "
"is different than sdpcm_shared version %d in dongle\n",
diff --git a/drivers/net/wireless/bcmdhd/include/epivers.h b/drivers/net/wireless/bcmdhd/include/epivers.h
index 30ef842fcbe..f474dfa482a 100644
--- a/drivers/net/wireless/bcmdhd/include/epivers.h
+++ b/drivers/net/wireless/bcmdhd/include/epivers.h
@@ -33,17 +33,17 @@
#define EPI_RC_NUMBER 125
-#define EPI_INCREMENTAL_NUMBER 65
+#define EPI_INCREMENTAL_NUMBER 69
#define EPI_BUILD_NUMBER 0
-#define EPI_VERSION 5, 90, 125, 65
+#define EPI_VERSION 5, 90, 125, 69
-#define EPI_VERSION_NUM 0x055a7d41
+#define EPI_VERSION_NUM 0x055a7d45
#define EPI_VERSION_DEV 5.90.125
-#define EPI_VERSION_STR "5.90.125.65"
+#define EPI_VERSION_STR "5.90.125.69"
#endif
diff --git a/drivers/net/wireless/bcmdhd/include/sdio.h b/drivers/net/wireless/bcmdhd/include/sdio.h
index 7e94e7df13c..ca932266a1b 100644
--- a/drivers/net/wireless/bcmdhd/include/sdio.h
+++ b/drivers/net/wireless/bcmdhd/include/sdio.h
@@ -376,6 +376,7 @@ typedef volatile struct {
#define SDIOH_CMD_5 5
#define SDIOH_CMD_7 7
#define SDIOH_CMD_11 11
+#define SDIOH_CMD_14 14
#define SDIOH_CMD_15 15
#define SDIOH_CMD_19 19
#define SDIOH_CMD_52 52
@@ -411,6 +412,10 @@ typedef volatile struct {
#define CMD7_RCA_M BITFIELD_MASK(16)
#define CMD7_RCA_S 16
+#define CMD14_RCA_M BITFIELD_MASK(16)
+#define CMD14_RCA_S 16
+#define CMD14_SLEEP_M BITFIELD_MASK(1)
+#define CMD14_SLEEP_S 15
#define CMD_15_RCA_M BITFIELD_MASK(16)
#define CMD_15_RCA_S 16
diff --git a/drivers/net/wireless/bcmdhd/include/wlioctl.h b/drivers/net/wireless/bcmdhd/include/wlioctl.h
index a09dd269264..1059de147ef 100644
--- a/drivers/net/wireless/bcmdhd/include/wlioctl.h
+++ b/drivers/net/wireless/bcmdhd/include/wlioctl.h
@@ -555,6 +555,7 @@ typedef enum sup_auth_status {
#define CRYPTO_ALGO_AES_OCB_MSDU 5
#define CRYPTO_ALGO_AES_OCB_MPDU 6
#define CRYPTO_ALGO_NALG 7
+#define CRYPTO_ALGO_PMK 12
#define WSEC_GEN_MIC_ERROR 0x0001
#define WSEC_GEN_REPLAY 0x0002
@@ -616,6 +617,9 @@ typedef struct {
#define WPA2_AUTH_PSK 0x0080
#define BRCM_AUTH_PSK 0x0100
#define BRCM_AUTH_DPT 0x0200
+#define WPA2_AUTH_MFP 0x1000
+#define WPA2_AUTH_TPK 0x2000
+#define WPA2_AUTH_FT 0x4000
#define MAXPMKID 16
@@ -1499,6 +1503,7 @@ typedef struct wl_sampledata {
#define WL_JOIN_PREF_WPA 2
#define WL_JOIN_PREF_BAND 3
#define WL_JOIN_PREF_RSSI_DELTA 4
+#define WL_JOIN_PREF_TRANS_PREF 5
#define WLJP_BAND_ASSOC_PREF 255
diff --git a/drivers/net/wireless/bcmdhd/wl_cfg80211.c b/drivers/net/wireless/bcmdhd/wl_cfg80211.c
index b2861f49221..09529136787 100644
--- a/drivers/net/wireless/bcmdhd/wl_cfg80211.c
+++ b/drivers/net/wireless/bcmdhd/wl_cfg80211.c
@@ -874,7 +874,8 @@ wl_cfg80211_add_virtual_iface(struct wiphy *wiphy, char *name,
return ERR_PTR(-ENOMEM);
}
vwdev->wiphy = wl->wdev->wiphy;
- WL_INFO((" virtual interface(%s) is created \n", wl->p2p->vir_ifname));
+ WL_INFO((" virtual interface(%s) is created memalloc done \n",
+ wl->p2p->vir_ifname));
index = alloc_idx_vwdev(wl);
wl->vwdev[index] = vwdev;
vwdev->iftype =
@@ -891,7 +892,7 @@ wl_cfg80211_add_virtual_iface(struct wiphy *wiphy, char *name,
rtnl_unlock();
if (net_attach && !net_attach(dhd, _ndev->ifindex))
WL_DBG((" virtual interface(%s) is "
- "created\n", wl->p2p->vir_ifname));
+ "created net attach done\n", wl->p2p->vir_ifname));
else {
rtnl_lock();
goto fail;
@@ -918,6 +919,7 @@ wl_cfg80211_del_virtual_iface(struct wiphy *wiphy, struct net_device *dev)
struct wl_priv *wl = wiphy_priv(wiphy);
s32 timeout = -1;
s32 ret = 0;
+ WL_DBG(("Enter\n"));
if (wl->p2p_supported) {
memcpy(p2p_mac.octet, wl->p2p->int_addr.octet, ETHER_ADDR_LEN);
if (wl->p2p->vif_created) {
@@ -925,8 +927,17 @@ wl_cfg80211_del_virtual_iface(struct wiphy *wiphy, struct net_device *dev)
wl_cfg80211_scan_abort(wl, dev);
}
- wl_cfgp2p_ifdel(wl, &p2p_mac);
+ ret = wl_cfgp2p_ifdel(wl, &p2p_mac);
wl_set_p2p_status(wl, IF_DELETING);
+ if (ret) {
+ /* Firmware could not delete the interface so we will not get WLC_E_IF event for cleaning the dhd virtual nw interace
+ * So lets do it here. Failures from fw will ensure the application to do ifconfig <inter> down and up sequnce, which will reload the fw
+ * however we should cleanup the linux network virtual interfaces
+ */
+ dhd_pub_t *dhd = (dhd_pub_t *)(wl->pub);
+ WL_ERR(("Firmware returned an error from p2p_ifdel, try to remove linux virtual network interface dev->name %s\n", dev->name));
+ dhd_del_if(dhd->info, dhd_net2idx(dhd->info, dev));
+ }
/* Wait for any pending scan req to get aborted from the sysioc context */
timeout = wait_event_interruptible_timeout(wl->dongle_event_wait,
@@ -1082,8 +1093,8 @@ wl_cfg80211_notify_ifdel(struct net_device *net)
if (wl->p2p->vif_created) {
s32 index = 0;
- WL_DBG(("IF_DEL event called from dongle, _net name: %s, vif name: %s\n",
- net->name, wl->p2p->vir_ifname));
+ WL_DBG(("IF_DEL event called from dongle, net %x, vif name: %s\n",
+ (unsigned int)net, wl->p2p->vir_ifname));
memset(wl->p2p->vir_ifname, '\0', IFNAMSIZ);
index = wl_cfgp2p_find_idx(wl, net);
@@ -2220,12 +2231,20 @@ wl_cfg80211_disconnect(struct wiphy *wiphy, struct net_device *dev,
CHECK_SYS_UP(wl);
act = *(bool *) wl_read_prof(wl, WL_PROF_ACT);
if (likely(act)) {
+ /*
+ * Cancel ongoing scan to sync up with sme state machine of cfg80211.
+ */
+ if (wl->scan_request) {
+ wl_cfg80211_scan_abort(wl, dev);
+ }
+ wl_set_drv_status(wl, DISCONNECTING);
scbval.val = reason_code;
memcpy(&scbval.ea, &wl->bssid, ETHER_ADDR_LEN);
scbval.val = htod32(scbval.val);
err = wldev_ioctl(dev, WLC_DISASSOC, &scbval,
sizeof(scb_val_t), false);
if (unlikely(err)) {
+ wl_clr_drv_status(wl, DISCONNECTING);
WL_ERR(("error (%d)\n", err));
return err;
}
@@ -2710,6 +2729,11 @@ wl_cfg80211_set_power_mgmt(struct wiphy *wiphy, struct net_device *dev,
CHECK_SYS_UP(wl);
pm = enabled ? PM_FAST : PM_OFF;
+ /* Do not enable the power save after assoc if it is p2p interface */
+ if (wl->p2p && wl->p2p->vif_created) {
+ WL_DBG(("Do not enable the power save for p2p interfaces even after assoc\n"));
+ pm = PM_OFF;
+ }
pm = htod32(pm);
WL_DBG(("power save %s\n", (pm ? "enabled" : "disabled")));
err = wldev_ioctl(dev, WLC_SET_PM, &pm, sizeof(pm), false);
@@ -3616,7 +3640,10 @@ wl_cfg80211_set_beacon(struct wiphy *wiphy, struct net_device *dev,
wldev_iovar_setint(dev, "mpc", 0);
wldev_ioctl(dev, WLC_DOWN, &ap, sizeof(s32), false);
wldev_ioctl(dev, WLC_SET_INFRA, &infra, sizeof(s32), false);
- wldev_ioctl(dev, WLC_SET_AP, &ap, sizeof(s32), false);
+ if ((err = wldev_ioctl(dev, WLC_SET_AP, &ap, sizeof(s32), false)) < 0) {
+ WL_ERR(("setting AP mode failed %d \n", err));
+ return err;
+ }
/* find the RSN_IE */
if ((wpa2_ie = bcm_parse_tlvs((u8 *)info->tail, info->tail_len,
DOT11_MNG_RSN_ID)) != NULL) {
@@ -4188,21 +4215,30 @@ wl_notify_connect_status(struct wl_priv *wl, struct net_device *ndev,
ntoh32(e->event_type), ntoh32(e->status)));
if (wl_is_linkup(wl, e, ndev)) {
wl_link_up(wl);
+ act = true;
+ wl_update_prof(wl, e, &act, WL_PROF_ACT);
if (wl_is_ibssmode(wl, ndev)) {
printk("cfg80211_ibss_joined");
cfg80211_ibss_joined(ndev, (s8 *)&e->addr,
GFP_KERNEL);
WL_DBG(("joined in IBSS network\n"));
} else {
- printk("wl_bss_connect_done succeeded");
- wl_bss_connect_done(wl, ndev, e, data, true);
- WL_DBG(("joined in BSS network \"%s\"\n",
+ if (!wl_get_drv_status(wl, DISCONNECTING)) {
+ printk("wl_bss_connect_done succeeded");
+ wl_bss_connect_done(wl, ndev, e, data, true);
+ WL_DBG(("joined in BSS network \"%s\"\n",
((struct wlc_ssid *)
wl_read_prof(wl, WL_PROF_SSID))->SSID));
+ }
}
- act = true;
- wl_update_prof(wl, e, &act, WL_PROF_ACT);
+
} else if (wl_is_linkdown(wl, e)) {
+ if (wl->scan_request) {
+ if (wl->escan_on) {
+ wl_notify_escan_complete(wl, true);
+ } else
+ wl_iscan_aborted(wl);
+ }
if (wl_get_drv_status(wl, CONNECTED)) {
printk("link down, call cfg80211_disconnected ");
wl_clr_drv_status(wl, CONNECTED);
@@ -4213,9 +4249,8 @@ wl_notify_connect_status(struct wl_priv *wl, struct net_device *ndev,
printk("link down, during connecting");
wl_bss_connect_done(wl, ndev, e, data, false);
}
- if (wl->scan_request) {
- wl_cfg80211_scan_abort(wl, ndev);
- }
+ wl_clr_drv_status(wl, DISCONNECTING);
+
} else if (wl_is_nonetwork(wl, e)) {
printk("connect failed e->status 0x%x", (int)ntoh32(e->status));
if (wl_get_drv_status(wl, CONNECTING))
@@ -4498,7 +4533,9 @@ wl_bss_connect_done(struct wl_priv *wl, struct net_device *ndev,
s32 err = 0;
WL_DBG((" enter\n"));
-
+ if (wl->scan_request) {
+ wl_cfg80211_scan_abort(wl, ndev);
+ }
if (wl_get_drv_status(wl, CONNECTING)) {
wl_clr_drv_status(wl, CONNECTING);
if (completed) {
@@ -4506,6 +4543,7 @@ wl_bss_connect_done(struct wl_priv *wl, struct net_device *ndev,
memcpy(&wl->bssid, &e->addr, ETHER_ADDR_LEN);
wl_update_bss_info(wl, ndev);
wl_update_pmklist(ndev, wl->pmk_list, err);
+ wl_set_drv_status(wl, CONNECTED);
}
cfg80211_connect_result(ndev,
(u8 *)&wl->bssid,
@@ -4518,14 +4556,6 @@ wl_bss_connect_done(struct wl_priv *wl, struct net_device *ndev,
WL_DBG(("Report connect result - connection %s\n",
completed ? "succeeded" : "failed"));
}
- if (completed)
- wl_set_drv_status(wl, CONNECTED);
- else {
- if (wl->scan_request) {
- wl_cfg80211_scan_abort(wl, ndev);
- }
- }
-
return err;
}
@@ -5085,6 +5115,7 @@ static void wl_notify_escan_complete(struct wl_priv *wl, bool aborted)
if (unlikely(!wl_get_drv_status(wl, SCANNING))) {
wl_clr_drv_status(wl, SCANNING);
WL_ERR(("Scan complete while device not scanning\n"));
+ wl->scan_request = NULL;
return;
}
wl_clr_drv_status(wl, SCANNING);
@@ -5191,7 +5222,9 @@ static s32 wl_escan_handler(struct wl_priv *wl,
wl->escan_info.escan_state = WL_ESCAN_STATE_IDLE;
if (likely(wl->scan_request)) {
rtnl_lock();
- WL_INFO(("ESCAN COMPLETED\n"));
+ WL_INFO(("ESCAN ABORTED\n"));
+ wl->bss_list = (wl_scan_results_t *)wl->escan_info.escan_buf;
+ wl_inform_bss(wl);
wl_notify_escan_complete(wl, true);
rtnl_unlock();
}
@@ -6040,7 +6073,6 @@ static s32 wl_update_wiphybands(struct wl_priv *wl)
}
phy = phylist_buf;
for (; *phy; phy++) {
- WL_ERR(("%c phy\n", *phy));
if (*phy == 'a' || *phy == 'n') {
wiphy = wl_to_wiphy(wl);
wiphy->bands[IEEE80211_BAND_5GHZ] =
@@ -6087,6 +6119,7 @@ static s32 __wl_cfg80211_down(struct wl_priv *wl)
wl_clr_drv_status(wl, SCAN_ABORTING);
wl_clr_drv_status(wl, CONNECTING);
wl_clr_drv_status(wl, CONNECTED);
+ wl_clr_drv_status(wl, DISCONNECTING);
if (wl_get_drv_status(wl, AP_CREATED)) {
wl_clr_drv_status(wl, AP_CREATED);
wl_clr_drv_status(wl, AP_CREATING);
diff --git a/drivers/net/wireless/bcmdhd/wl_cfg80211.h b/drivers/net/wireless/bcmdhd/wl_cfg80211.h
index 8116d63d56e..a5637240c17 100644
--- a/drivers/net/wireless/bcmdhd/wl_cfg80211.h
+++ b/drivers/net/wireless/bcmdhd/wl_cfg80211.h
@@ -129,6 +129,7 @@ enum wl_status {
WL_STATUS_SCAN_ABORTING,
WL_STATUS_CONNECTING,
WL_STATUS_CONNECTED,
+ WL_STATUS_DISCONNECTING,
WL_STATUS_AP_CREATING,
WL_STATUS_AP_CREATED
};
diff --git a/drivers/net/wireless/bcmdhd/wl_cfgp2p.c b/drivers/net/wireless/bcmdhd/wl_cfgp2p.c
index 3d7b5484152..98271c28658 100644
--- a/drivers/net/wireless/bcmdhd/wl_cfgp2p.c
+++ b/drivers/net/wireless/bcmdhd/wl_cfgp2p.c
@@ -176,8 +176,8 @@ wl_cfgp2p_ifdel(struct wl_priv *wl, struct ether_addr *mac)
s32 ret;
struct net_device *netdev = wl_to_prmry_ndev(wl);
- CFGP2P_INFO(("---wl p2p_ifdel %02x:%02x:%02x:%02x:%02x:%02x\n",
- mac->octet[0], mac->octet[1], mac->octet[2],
+ CFGP2P_INFO(("------primary idx %d : wl p2p_ifdel %02x:%02x:%02x:%02x:%02x:%02x\n",
+ netdev->ifindex, mac->octet[0], mac->octet[1], mac->octet[2],
mac->octet[3], mac->octet[4], mac->octet[5]));
ret = wldev_iovar_setbuf(netdev, "p2p_ifdel", mac, sizeof(*mac),
@@ -1047,10 +1047,13 @@ wl_cfgp2p_action_tx_complete(struct wl_priv *wl, struct net_device *ndev,
if (event_type == WLC_E_ACTION_FRAME_COMPLETE) {
CFGP2P_INFO((" WLC_E_ACTION_FRAME_COMPLETE is received : %d\n", status));
- if (status == WLC_E_STATUS_SUCCESS)
+ if (status == WLC_E_STATUS_SUCCESS) {
wl_set_p2p_status(wl, ACTION_TX_COMPLETED);
- else
+ }
+ else {
+ wl_set_p2p_status(wl, ACTION_TX_NOACK);
CFGP2P_ERR(("WLC_E_ACTION_FRAME_COMPLETE : NO ACK\n"));
+ }
wake_up_interruptible(&wl->dongle_event_wait);
} else {
CFGP2P_INFO((" WLC_E_ACTION_FRAME_OFFCHAN_COMPLETE is received,"
@@ -1081,6 +1084,7 @@ wl_cfgp2p_tx_action_frame(struct wl_priv *wl, struct net_device *dev,
af_params->channel, af_params->dwell_time));
wl_clr_p2p_status(wl, ACTION_TX_COMPLETED);
+ wl_clr_p2p_status(wl, ACTION_TX_NOACK);
#define MAX_WAIT_TIME 2000
if (bssidx == P2PAPI_BSSCFG_PRIMARY)
bssidx = wl_to_p2p_bss_bssidx(wl, P2PAPI_BSSCFG_DEVICE);
@@ -1094,7 +1098,7 @@ wl_cfgp2p_tx_action_frame(struct wl_priv *wl, struct net_device *dev,
goto exit;
}
timeout = wait_event_interruptible_timeout(wl->dongle_event_wait,
- (wl_get_p2p_status(wl, ACTION_TX_COMPLETED) == TRUE),
+ (wl_get_p2p_status(wl, ACTION_TX_COMPLETED) ||wl_get_p2p_status(wl, ACTION_TX_NOACK)),
msecs_to_jiffies(MAX_WAIT_TIME));
if (timeout > 0 && wl_get_p2p_status(wl, ACTION_TX_COMPLETED)) {
diff --git a/drivers/net/wireless/bcmdhd/wl_cfgp2p.h b/drivers/net/wireless/bcmdhd/wl_cfgp2p.h
index d62f5422708..b08504d8f95 100644
--- a/drivers/net/wireless/bcmdhd/wl_cfgp2p.h
+++ b/drivers/net/wireless/bcmdhd/wl_cfgp2p.h
@@ -88,6 +88,7 @@ enum wl_cfgp2p_status {
WLP2P_STATUS_IF_CHANGED,
WLP2P_STATUS_LISTEN_EXPIRED,
WLP2P_STATUS_ACTION_TX_COMPLETED,
+ WLP2P_STATUS_ACTION_TX_NOACK,
WLP2P_STATUS_SCANNING
};
diff --git a/drivers/net/wireless/bcmdhd/wl_iw.c b/drivers/net/wireless/bcmdhd/wl_iw.c
index ae28c6d0215..6d546fcd396 100644
--- a/drivers/net/wireless/bcmdhd/wl_iw.c
+++ b/drivers/net/wireless/bcmdhd/wl_iw.c
@@ -792,7 +792,7 @@ wl_iw_set_power_mode(
#ifdef COEX_DHCP
g_bt->ts_dhcp_start = JF2MS;
- g_bt->dhcp_done = false;
+ g_bt->dhcp_done = FALSE;
WL_TRACE_COEX(("%s: DHCP start, pm:%d changed to pm:%d\n",
__FUNCTION__, pm, pm_local));
@@ -806,7 +806,7 @@ wl_iw_set_power_mode(
net_os_set_packet_filter(dev, 1);
#ifdef COEX_DHCP
- g_bt->dhcp_done = true;
+ g_bt->dhcp_done = TRUE;
g_bt->ts_dhcp_ok = JF2MS;
WL_TRACE_COEX(("%s: DHCP done for:%d ms, restored pm:%d\n",
__FUNCTION__, (g_bt->ts_dhcp_ok - g_bt->ts_dhcp_start), pm));
@@ -828,7 +828,7 @@ wl_iw_set_power_mode(
bool btcoex_is_sco_active(struct net_device *dev)
{
int ioc_res = 0;
- bool res = false;
+ bool res = FALSE;
int sco_id_cnt = 0;
int param27;
int i;
@@ -852,7 +852,7 @@ bool btcoex_is_sco_active(struct net_device *dev)
if (sco_id_cnt > 2) {
WL_TRACE_COEX(("%s, sco/esco detected, pkt id_cnt:%d samples:%d\n",
__FUNCTION__, sco_id_cnt, i));
- res = true;
+ res = TRUE;
break;
}
@@ -866,7 +866,7 @@ bool btcoex_is_sco_active(struct net_device *dev)
static int set_btc_esco_params(struct net_device *dev, bool trump_sco)
{
- static bool saved_status = false;
+ static bool saved_status = FALSE;
char buf_reg50va_dhcp_on[8] = { 50, 00, 00, 00, 0x22, 0x80, 0x00, 0x00 };
char buf_reg51va_dhcp_on[8] = { 51, 00, 00, 00, 0x00, 0x00, 0x00, 0x00 };
@@ -902,7 +902,7 @@ static int set_btc_esco_params(struct net_device *dev, bool trump_sco)
} else {
WL_ERROR((":%s: save btc_params failed\n",
__FUNCTION__));
- saved_status = false;
+ saved_status = FALSE;
return -1;
}
@@ -920,7 +920,7 @@ static int set_btc_esco_params(struct net_device *dev, bool trump_sco)
dev_wlc_bufvar_set(dev, "btc_params", (char *)&buf_reg65va_dhcp_on[0], 8);
dev_wlc_bufvar_set(dev, "btc_params", (char *)&buf_reg71va_dhcp_on[0], 8);
- saved_status = true;
+ saved_status = TRUE;
} else if (saved_status) {
@@ -946,7 +946,7 @@ static int set_btc_esco_params(struct net_device *dev, bool trump_sco)
saved_reg50, saved_reg51, saved_reg64,
saved_reg65, saved_reg71));
- saved_status = false;
+ saved_status = FALSE;
} else {
WL_ERROR((":%s att to restore not saved BTCOEX params\n",
__FUNCTION__));
@@ -6320,12 +6320,12 @@ fail:
#ifndef AP_ONLY
static int last_auto_channel = 6;
#endif
+
static int
get_softap_auto_channel(struct net_device *dev, struct ap_profile *ap)
{
int chosen = 0;
wl_uint32_list_t request;
- int rescan = 0;
int retry = 0;
int updown = 0;
int ret = 0;
@@ -6354,42 +6354,57 @@ get_softap_auto_channel(struct net_device *dev, struct ap_profile *ap)
null_ssid.SSID_len+4, buf, sizeof(buf), &mkvar_err);
ASSERT(iolen);
res |= dev_wlc_ioctl(dev, WLC_SET_VAR, buf, iolen);
+
#endif
- auto_channel_retry:
- request.count = htod32(0);
- ret = dev_wlc_ioctl(dev, WLC_START_CHANNEL_SEL, &request, sizeof(request));
- if (ret < 0) {
- WL_ERROR(("can't start auto channel scan\n"));
- goto fail;
- }
+
+ request.count = htod32(0);
+ ret = dev_wlc_ioctl(dev, WLC_START_CHANNEL_SEL, &request, sizeof(request));
+ if (ret < 0) {
+ WL_ERROR(("can't start auto channel scan\n"));
+ goto fail;
+ }
get_channel_retry:
- bcm_mdelay(500);
+ bcm_mdelay(350);
- ret = dev_wlc_ioctl(dev, WLC_GET_CHANNEL_SEL, &chosen, sizeof(chosen));
- if (ret < 0 || dtoh32(chosen) == 0) {
- if (retry++ < 3)
- goto get_channel_retry;
- else {
+ ret = dev_wlc_ioctl(dev, WLC_GET_CHANNEL_SEL, &chosen, sizeof(chosen));
+ if (ret < 0 || dtoh32(chosen) == 0) {
+ if (retry++ < 15) {
+ goto get_channel_retry;
+ } else {
+ if (ret < 0) {
WL_ERROR(("can't get auto channel sel, err = %d, "
- "chosen = %d\n", ret, chosen));
+ "chosen = 0x%04X\n", ret, (uint16)chosen));
goto fail;
+ } else {
+ ap->channel = (uint16)last_auto_channel;
+ WL_ERROR(("auto channel sel timed out. we get channel %d\n",
+ ap->channel));
}
}
- if ((chosen == 1) && (!rescan++))
- goto auto_channel_retry;
- WL_SOFTAP(("Set auto channel = %d\n", chosen));
- ap->channel = chosen;
- if ((res = dev_wlc_ioctl(dev, WLC_DOWN, &updown, sizeof(updown))) < 0) {
- WL_ERROR(("%s fail to set up err =%d\n", __FUNCTION__, res));
- goto fail;
- }
+ }
+
+ if (chosen) {
+ ap->channel = (uint16)chosen & 0x00FF;
+ WL_SOFTAP(("%s: Got auto channel = %d, attempt:%d\n",
+ __FUNCTION__, ap->channel, retry));
+ }
+
+ if ((res = dev_wlc_ioctl(dev, WLC_DOWN, &updown, sizeof(updown))) < 0) {
+ WL_ERROR(("%s fail to set up err =%d\n", __FUNCTION__, res));
+ goto fail;
+ }
+
#ifndef AP_ONLY
- if (!res)
+ if (!res || !ret)
last_auto_channel = ap->channel;
#endif
fail :
+ if (ret < 0) {
+ WL_TRACE(("%s: return value %d\n", __FUNCTION__, ret));
+ return ret;
+ }
return res;
}
@@ -6482,6 +6497,15 @@ set_ap_cfg(struct net_device *dev, struct ap_profile *ap)
goto fail;
}
WL_TRACE(("\n>in %s: apsta set result: %d \n", __FUNCTION__, res));
+
+
+ mpc = 0;
+ if ((res = dev_wlc_intvar_set(dev, "mpc", mpc))) {
+ WL_ERROR(("%s fail to set mpc\n", __FUNCTION__));
+ goto fail;
+ }
+
+
#endif
updown = 1;
@@ -6528,16 +6552,16 @@ set_ap_cfg(struct net_device *dev, struct ap_profile *ap)
if ((ap->channel == 0) && (get_softap_auto_channel(dev, ap) < 0)) {
ap->channel = 1;
- WL_ERROR(("%s auto channel failed, pick up channel=%d\n",
+ WL_ERROR(("%s auto channel failed, use channel=%d\n",
__FUNCTION__, ap->channel));
}
channel = ap->channel;
if ((res = dev_wlc_ioctl(dev, WLC_SET_CHANNEL, &channel, sizeof(channel)))) {
WL_ERROR(("%s fail to set channel\n", __FUNCTION__));
- goto fail;
}
+
if (ap_cfg_running == FALSE) {
updown = 0;
if ((res = dev_wlc_ioctl(dev, WLC_UP, &updown, sizeof(updown)))) {
@@ -6877,11 +6901,11 @@ static int wl_iw_softap_deassoc_stations(struct net_device *dev, u8 *mac)
char z_mac[6] = {0, 0, 0, 0, 0, 0};
char *sta_mac;
struct maclist *assoc_maclist = (struct maclist *) mac_buf;
- bool deauth_all = false;
+ bool deauth_all = FALSE;
if (mac == NULL) {
- deauth_all = true;
+ deauth_all = TRUE;
sta_mac = z_mac;
} else {
sta_mac = mac;
@@ -7179,7 +7203,7 @@ set_ap_mac_list(struct net_device *dev, void *buf)
if (assoc_maclist->count)
for (i = 0; i < assoc_maclist->count; i++) {
int j;
- bool assoc_mac_matched = false;
+ bool assoc_mac_matched = FALSE;
WL_SOFTAP(("\n Cheking assoc STA: "));
dhd_print_buf(&assoc_maclist->ea[i], 6, 7);
@@ -7189,7 +7213,7 @@ set_ap_mac_list(struct net_device *dev, void *buf)
if (!bcmp(&assoc_maclist->ea[i], &maclist->ea[j],
ETHER_ADDR_LEN)) {
- assoc_mac_matched = true;
+ assoc_mac_matched = TRUE;
break;
}
diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
index e3126c05100..159300429d7 100644
--- a/fs/ext4/inode.c
+++ b/fs/ext4/inode.c
@@ -2148,7 +2148,12 @@ static int mpage_da_submit_io(struct mpage_da_data *mpd,
else if (test_opt(inode->i_sb, MBLK_IO_SUBMIT))
err = ext4_bio_write_page(&io_submit, page,
len, mpd->wbc);
- else
+ else if (buffer_uninit(page_bufs)) {
+ ext4_set_bh_endio(page_bufs, inode);
+ err = block_write_full_page_endio(page,
+ noalloc_get_block_write,
+ mpd->wbc, ext4_end_io_buffer_write);
+ } else
err = block_write_full_page(page,
noalloc_get_block_write, mpd->wbc);
diff --git a/net/netfilter/xt_qtaguid.c b/net/netfilter/xt_qtaguid.c
index b9dcfde9976..5afd4192f35 100644
--- a/net/netfilter/xt_qtaguid.c
+++ b/net/netfilter/xt_qtaguid.c
@@ -222,6 +222,28 @@ struct sock_tag {
tag_t tag;
};
+struct qtaguid_event_counts {
+ /* Various successful events */
+ atomic64_t sockets_tagged;
+ atomic64_t sockets_untagged;
+ atomic64_t counter_set_changes;
+ atomic64_t delete_cmds;
+ atomic64_t iface_events; /* Number of NETDEV_* events handled */
+ /*
+ * match_found_sk_*: numbers related to the netfilter matching
+ * function finding a sock for the sk_buff.
+ */
+ atomic64_t match_found_sk; /* An sk was already in the sk_buff. */
+ /* The connection tracker had the sk. */
+ atomic64_t match_found_sk_in_ct;
+ /*
+ * No sk could be found. No apparent owner. Could happen with
+ * unsolicited traffic.
+ */
+ atomic64_t match_found_sk_none;
+};
+static struct qtaguid_event_counts qtu_events;
+
static struct rb_root sock_tag_tree = RB_ROOT;
static DEFINE_SPINLOCK(sock_tag_list_lock);
@@ -954,6 +976,7 @@ static int iface_inet6addr_event_handler(struct notifier_block *nb,
BUG_ON(!ifa || !ifa->idev);
dev = (struct net_device *)ifa->idev->dev;
iface_stat_create_ipv6(dev, ifa);
+ atomic64_inc(&qtu_events.iface_events);
break;
}
return NOTIFY_DONE;
@@ -977,6 +1000,7 @@ static int iface_inetaddr_event_handler(struct notifier_block *nb,
BUG_ON(!ifa || !ifa->ifa_dev);
dev = ifa->ifa_dev->dev;
iface_stat_create(dev, ifa);
+ atomic64_inc(&qtu_events.iface_events);
break;
}
return NOTIFY_DONE;
@@ -1149,6 +1173,10 @@ static bool qtaguid_mt(const struct sk_buff *skb, struct xt_action_param *par)
* it back, as nf_tproxy_get_sock_v4() got it.
*/
got_sock = sk;
+ if (sk)
+ atomic64_inc(&qtu_events.match_found_sk_in_ct);
+ } else {
+ atomic64_inc(&qtu_events.match_found_sk);
}
MT_DEBUG("qtaguid[%d]: sk=%p got_sock=%d proto=%d\n",
par->hooknum, sk, got_sock, ip_hdr(skb)->protocol);
@@ -1178,6 +1206,7 @@ static bool qtaguid_mt(const struct sk_buff *skb, struct xt_action_param *par)
par->hooknum,
sk ? sk->sk_socket : NULL);
res = (info->match ^ info->invert) == 0;
+ atomic64_inc(&qtu_events.match_found_sk_none);
goto put_sock_ret_res;
} else if (info->match & info->invert & XT_QTAGUID_SOCKET) {
res = false;
@@ -1254,6 +1283,7 @@ static int qtaguid_ctrl_proc_read(char *page, char **num_items_returned,
return 0;
}
+ /* TODO: support skipping num_items_returned on entry. */
CT_DEBUG("qtaguid: proc ctrl page=%p off=%ld char_count=%d *eof=%d\n",
page, items_to_skip, char_count, *eof);
@@ -1286,6 +1316,34 @@ static int qtaguid_ctrl_proc_read(char *page, char **num_items_returned,
(*num_items_returned)++;
}
spin_unlock_bh(&sock_tag_list_lock);
+
+ if (item_index++ >= items_to_skip) {
+ len = snprintf(outp, char_count,
+ "events: sockets_tagged=%llu "
+ "sockets_untagged=%llu "
+ "counter_set_changes=%llu "
+ "delete_cmds=%llu "
+ "iface_events=%llu "
+ "match_found_sk=%llu "
+ "match_found_sk_in_ct=%llu "
+ "match_found_sk_none=%llu\n",
+ atomic64_read(&qtu_events.sockets_tagged),
+ atomic64_read(&qtu_events.sockets_untagged),
+ atomic64_read(&qtu_events.counter_set_changes),
+ atomic64_read(&qtu_events.delete_cmds),
+ atomic64_read(&qtu_events.iface_events),
+ atomic64_read(&qtu_events.match_found_sk),
+ atomic64_read(&qtu_events.match_found_sk_in_ct),
+ atomic64_read(&qtu_events.match_found_sk_none));
+ if (len >= char_count) {
+ *outp = '\0';
+ return outp - page;
+ }
+ outp += len;
+ char_count -= len;
+ (*num_items_returned)++;
+ }
+
*eof = 1;
return outp - page;
}
@@ -1325,6 +1383,7 @@ static int ctrl_cmd_delete(const char *input)
struct iface_stat *iface_entry;
struct rb_node *node;
struct sock_tag *st_entry;
+ struct rb_root st_to_free_tree = RB_ROOT;
struct tag_stat *ts_entry;
struct tag_counter_set *tcs_entry;
@@ -1362,18 +1421,27 @@ static int ctrl_cmd_delete(const char *input)
continue;
if (!acct_tag || st_entry->tag == tag) {
- CT_DEBUG("qtaguid: ctrl_delete(): "
- "erase st: sk=%p tag=0x%llx (uid=%u)\n",
- st_entry->sk,
- st_entry->tag,
- entry_uid);
rb_erase(&st_entry->sock_node, &sock_tag_tree);
- sockfd_put(st_entry->socket);
- kfree(st_entry);
+ /* Can't sockfd_put() within spinlock, do it later. */
+ sock_tag_tree_insert(st_entry, &st_to_free_tree);
}
}
spin_unlock_bh(&sock_tag_list_lock);
+ node = rb_first(&st_to_free_tree);
+ while (node) {
+ st_entry = rb_entry(node, struct sock_tag, sock_node);
+ node = rb_next(node);
+ CT_DEBUG("qtaguid: ctrl_delete(): "
+ "erase st: sk=%p tag=0x%llx (uid=%u)\n",
+ st_entry->sk,
+ st_entry->tag,
+ entry_uid);
+ rb_erase(&st_entry->sock_node, &st_to_free_tree);
+ sockfd_put(st_entry->socket);
+ kfree(st_entry);
+ }
+
tag = combine_atag_with_uid(acct_tag, uid);
/* Delete tag counter-sets */
@@ -1418,7 +1486,7 @@ static int ctrl_cmd_delete(const char *input)
spin_unlock_bh(&iface_entry->tag_stat_list_lock);
}
spin_unlock_bh(&iface_stat_list_lock);
-
+ atomic64_inc(&qtu_events.delete_cmds);
res = 0;
err:
@@ -1477,7 +1545,7 @@ static int ctrl_cmd_counter_set(const char *input)
}
tcs->active_set = counter_set;
spin_unlock_bh(&tag_counter_set_list_lock);
-
+ atomic64_inc(&qtu_events.counter_set_changes);
res = 0;
err:
@@ -1563,6 +1631,7 @@ static int ctrl_cmd_tag(const char *input)
sock_tag_entry->tag = combine_atag_with_uid(acct_tag,
uid);
sock_tag_tree_insert(sock_tag_entry, &sock_tag_tree);
+ atomic64_inc(&qtu_events.sockets_tagged);
}
spin_unlock_bh(&sock_tag_list_lock);
/* We keep the ref to the socket (file) until it is untagged */
@@ -1628,6 +1697,7 @@ static int ctrl_cmd_untag(const char *input)
sockfd_put(el_socket);
refcnt -= 2;
kfree(sock_tag_entry);
+ atomic64_inc(&qtu_events.sockets_untagged);
CT_DEBUG("qtaguid: ctrl_untag(%s): done. socket->...->f_count=%d\n",
input, refcnt);