diff options
author | John Stultz <john.stultz@linaro.org> | 2011-09-14 12:03:58 -0700 |
---|---|---|
committer | John Stultz <john.stultz@linaro.org> | 2011-09-14 12:03:58 -0700 |
commit | 3f1fc539a29e09d940df1418b36d23621f85d545 (patch) | |
tree | 2693bc745b788a753adaebfbb98635436adf55bb | |
parent | 3b728cae2f6a04b80c0df33a874b141d14a3d965 (diff) | |
parent | 5cb5fb6fef3fd81b55ddc48010e1b520e8473553 (diff) | |
download | snowball-3f1fc539a29e09d940df1418b36d23621f85d545.tar.gz |
Merge branch 'upstream/android-3.0' into linaro-android-3.0
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); |