From d03d7b2227341cc38b8c662f6edb9139ea50f928 Mon Sep 17 00:00:00 2001 From: "Howard M. Harte" Date: Mon, 25 Jul 2011 19:15:11 -0700 Subject: [PATCH] Update to 5.90.125.52: Fix unremoved monitor interface problem after killing hostapd. Add WPS support for hostapd. Change-Id: I4e476fafb203592fcdf5c15a526b67d4aa78df3e Signed-off-by: Howard M. Harte Signed-off-by: Dmitry Shmidt --- drivers/net/wireless/bcmdhd/dhd_bus.h | 1 + drivers/net/wireless/bcmdhd/dhd_linux.c | 3 + drivers/net/wireless/bcmdhd/dhd_linux_mon.c | 163 ++++++++++++++------- drivers/net/wireless/bcmdhd/dhd_sdio.c | 12 +- drivers/net/wireless/bcmdhd/include/epivers.h | 8 +- drivers/net/wireless/bcmdhd/wl_android.c | 17 ++- drivers/net/wireless/bcmdhd/wl_android.h | 4 +- drivers/net/wireless/bcmdhd/wl_cfg80211.c | 203 +++++++++++++++----------- drivers/net/wireless/bcmdhd/wl_cfgp2p.c | 20 ++- drivers/net/wireless/bcmdhd/wl_cfgp2p.h | 4 +- 10 files changed, 274 insertions(+), 161 deletions(-) diff --git a/drivers/net/wireless/bcmdhd/dhd_bus.h b/drivers/net/wireless/bcmdhd/dhd_bus.h index bae0713..2943220 100644 --- a/drivers/net/wireless/bcmdhd/dhd_bus.h +++ b/drivers/net/wireless/bcmdhd/dhd_bus.h @@ -59,6 +59,7 @@ extern int dhd_bus_rxctl(struct dhd_bus *bus, uchar *msg, uint msglen); /* Watchdog timer function */ extern bool dhd_bus_watchdog(dhd_pub_t *dhd); +extern void dhd_disable_intr(dhd_pub_t *dhd); #if defined(DHD_DEBUG) /* Device console input function */ diff --git a/drivers/net/wireless/bcmdhd/dhd_linux.c b/drivers/net/wireless/bcmdhd/dhd_linux.c index e318017..690384a 100644 --- a/drivers/net/wireless/bcmdhd/dhd_linux.c +++ b/drivers/net/wireless/bcmdhd/dhd_linux.c @@ -3248,6 +3248,9 @@ dhd_module_init(void) goto fail_2; } #endif +#if defined(WL_CFG80211) + error = wl_android_post_init(); +#endif return error; #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) && 1 diff --git a/drivers/net/wireless/bcmdhd/dhd_linux_mon.c b/drivers/net/wireless/bcmdhd/dhd_linux_mon.c index a51db01..25eba63 100644 --- a/drivers/net/wireless/bcmdhd/dhd_linux_mon.c +++ b/drivers/net/wireless/bcmdhd/dhd_linux_mon.c @@ -30,6 +30,7 @@ #include #include #include +#include #include #include @@ -39,10 +40,14 @@ #include #include -/* - * Some external functions, TODO: move them to dhd_linux.h - */ -int dhd_start_xmit(struct sk_buff *skb, struct net_device *net); +typedef enum monitor_states +{ + MONITOR_STATE_DEINIT = 0x0, + MONITOR_STATE_INIT = 0x1, + MONITOR_STATE_INTERFACE_ADDED = 0x2, + MONITOR_STATE_INTERFACE_DELETED = 0x4 +} monitor_states_t; +extern int dhd_start_xmit(struct sk_buff *skb, struct net_device *net); /** * Local declarations and defintions (not exposed) @@ -58,9 +63,9 @@ typedef struct monitor_interface { typedef struct dhd_linux_monitor { void *dhd_pub; + monitor_states_t monitor_state; monitor_interface mon_if[DHD_MAX_IFS]; - int count; /* Number of total monitor interface */ - struct mutex lock; /* lock to protect count and mon_if */ + struct mutex lock; /* lock to protect mon_if */ } dhd_linux_monitor_t; static dhd_linux_monitor_t g_monitor; @@ -145,6 +150,7 @@ static int dhd_mon_if_subif_start_xmit(struct sk_buff *skb, struct net_device *n int dot11_hdr_len = 24; int snap_len = 6; unsigned char *pdata; + unsigned short frame_ctl; unsigned char src_mac_addr[6]; unsigned char dst_mac_addr[6]; struct ieee80211_hdr *dot11_hdr; @@ -176,35 +182,35 @@ static int dhd_mon_if_subif_start_xmit(struct sk_buff *skb, struct net_device *n skb_pull(skb, rtap_len); dot11_hdr = (struct ieee80211_hdr *)skb->data; - + frame_ctl = le16_to_cpu(dot11_hdr->frame_control); /* Check if the QoS bit is set */ - if (dot11_hdr->frame_control & 0x0080) - qos_len = 2; - - /* Check if this ia a Wireless Distribution System (WDS) frame - * which has 4 MAC addresses - */ - if ((dot11_hdr->frame_control & 0x0300) == 0x0300) - dot11_hdr_len += 6; - - memcpy(dst_mac_addr, dot11_hdr->addr1, sizeof(dst_mac_addr)); - memcpy(src_mac_addr, dot11_hdr->addr2, sizeof(src_mac_addr)); - - /* Skip the 802.11 header, QoS (if any) and SNAP, but leave spaces for - * for two MAC addresses - */ - skb_pull(skb, dot11_hdr_len + qos_len + snap_len - sizeof(src_mac_addr) * 2); - pdata = (unsigned char*)skb->data; - memcpy(pdata, dst_mac_addr, sizeof(dst_mac_addr)); - memcpy(pdata + sizeof(dst_mac_addr), src_mac_addr, sizeof(src_mac_addr)); - - MON_PRINT("if name: %s, matched if name %s\n", ndev->name, mon_if->real_ndev->name); - - /* Use the real net device to transmit the packet */ - ret = dhd_start_xmit(skb, mon_if->real_ndev); - - return ret; - + if ((frame_ctl & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_DATA) { + /* Check if this ia a Wireless Distribution System (WDS) frame + * which has 4 MAC addresses + */ + if (dot11_hdr->frame_control & 0x0080) + qos_len = 2; + if ((dot11_hdr->frame_control & 0x0300) == 0x0300) + dot11_hdr_len += 6; + + memcpy(dst_mac_addr, dot11_hdr->addr1, sizeof(dst_mac_addr)); + memcpy(src_mac_addr, dot11_hdr->addr2, sizeof(src_mac_addr)); + + /* Skip the 802.11 header, QoS (if any) and SNAP, but leave spaces for + * for two MAC addresses + */ + skb_pull(skb, dot11_hdr_len + qos_len + snap_len - sizeof(src_mac_addr) * 2); + pdata = (unsigned char*)skb->data; + memcpy(pdata, dst_mac_addr, sizeof(dst_mac_addr)); + memcpy(pdata + sizeof(dst_mac_addr), src_mac_addr, sizeof(src_mac_addr)); + + MON_PRINT("if name: %s, matched if name %s\n", ndev->name, mon_if->real_ndev->name); + + /* Use the real net device to transmit the packet */ + ret = dhd_start_xmit(skb, mon_if->real_ndev); + + return ret; + } fail: dev_kfree_skb(skb); return 0; @@ -242,7 +248,8 @@ static int dhd_mon_if_change_mac(struct net_device *ndev, void *addr) int dhd_add_monitor(char *name, struct net_device **new_ndev) { - int idx; + int i; + int idx = -1; int ret = 0; struct net_device* ndev = NULL; dhd_linux_monitor_t **dhd_mon; @@ -256,7 +263,15 @@ int dhd_add_monitor(char *name, struct net_device **new_ndev) goto out; } - if (g_monitor.count >= DHD_MAX_IFS) { + /* + * Find a vacancy + */ + for (i = 0; i < DHD_MAX_IFS; i++) + if (g_monitor.mon_if[i].mon_ndev == NULL) { + idx = i; + break; + } + if (idx == -1) { MON_PRINT("exceeds maximum interfaces\n"); ret = -EFAULT; goto out; @@ -281,14 +296,12 @@ int dhd_add_monitor(char *name, struct net_device **new_ndev) } *new_ndev = ndev; - idx = g_monitor.count; g_monitor.mon_if[idx].radiotap_enabled = TRUE; g_monitor.mon_if[idx].mon_ndev = ndev; g_monitor.mon_if[idx].real_ndev = lookup_real_netdev(name); - g_monitor.count++; dhd_mon = (dhd_linux_monitor_t **)netdev_priv(ndev); *dhd_mon = &g_monitor; - + g_monitor.monitor_state = MONITOR_STATE_INTERFACE_ADDED; MON_PRINT("net device returned: 0x%p\n", ndev); MON_PRINT("found a matched net device, name %s\n", g_monitor.mon_if[idx].real_ndev->name); @@ -301,10 +314,48 @@ out: } +int dhd_del_monitor(struct net_device *ndev) +{ + int i; + bool rollback_lock = false; + if (!ndev) + return -EINVAL; + mutex_lock(&g_monitor.lock); + for (i = 0; i < DHD_MAX_IFS; i++) { + if (g_monitor.mon_if[i].mon_ndev == ndev) { + g_monitor.mon_if[i].real_ndev = NULL; + g_monitor.mon_if[i].mon_ndev = NULL; + if (rtnl_is_locked()) { + rtnl_unlock(); + rollback_lock = true; + } + unregister_netdev(ndev); + free_netdev(ndev); + g_monitor.monitor_state = MONITOR_STATE_INTERFACE_DELETED; + ndev = NULL; + break; + } + } + if (rollback_lock) { + rtnl_lock(); + rollback_lock = false; + } + + if (ndev) + MON_PRINT("interface not found in monitor IF array, is this a monitor IF? 0x%p\n", + ndev); + mutex_unlock(&g_monitor.lock); + + return 0; +} + int dhd_monitor_init(void *dhd_pub) { - g_monitor.dhd_pub = dhd_pub; - mutex_init(&g_monitor.lock); + if (g_monitor.monitor_state == MONITOR_STATE_DEINIT) { + g_monitor.dhd_pub = dhd_pub; + mutex_init(&g_monitor.lock); + g_monitor.monitor_state = MONITOR_STATE_INIT; + } return 0; } @@ -312,20 +363,28 @@ int dhd_monitor_uninit(void) { int i; struct net_device *ndev; - + bool rollback_lock = false; mutex_lock(&g_monitor.lock); - - for (i = 0; i < DHD_MAX_IFS; i++) { - ndev = g_monitor.mon_if[i].mon_ndev; - if (ndev) { - unregister_netdev(ndev); - free_netdev(ndev); - g_monitor.mon_if[i].real_ndev = NULL; - g_monitor.mon_if[i].mon_ndev = NULL; - g_monitor.count--; + if (g_monitor.monitor_state != MONITOR_STATE_DEINIT) { + for (i = 0; i < DHD_MAX_IFS; i++) { + ndev = g_monitor.mon_if[i].mon_ndev; + if (ndev) { + if (rtnl_is_locked()) { + rtnl_unlock(); + rollback_lock = true; + } + unregister_netdev(ndev); + free_netdev(ndev); + g_monitor.mon_if[i].real_ndev = NULL; + g_monitor.mon_if[i].mon_ndev = NULL; + if (rollback_lock) { + rtnl_lock(); + rollback_lock = false; + } + } } + g_monitor.monitor_state = MONITOR_STATE_DEINIT; } - mutex_unlock(&g_monitor.lock); return 0; } diff --git a/drivers/net/wireless/bcmdhd/dhd_sdio.c b/drivers/net/wireless/bcmdhd/dhd_sdio.c index e57654b..db763ab 100644 --- a/drivers/net/wireless/bcmdhd/dhd_sdio.c +++ b/drivers/net/wireless/bcmdhd/dhd_sdio.c @@ -395,7 +395,7 @@ static bool dhd_readahead; (((uint8)(bus->tx_max - bus->tx_seq) > 1) && \ (((uint8)(bus->tx_max - bus->tx_seq) & 0x80) == 0)) -/* To check if there's window offered for ctrl frame*/ +/* To check if there's window offered for ctrl frame */ #define TXCTLOK(bus) \ (((uint8)(bus->tx_max - bus->tx_seq) != 0) && \ (((uint8)(bus->tx_max - bus->tx_seq) & 0x80) == 0)) @@ -4598,7 +4598,7 @@ clkwait: framecnt = dhdsdio_sendfromq(bus, framecnt); txlimit -= framecnt; } - /* Resched the DPC if ctrl cmd is pending on bus credit*/ + /* Resched the DPC if ctrl cmd is pending on bus credit */ if (bus->ctrl_frame_stat) resched = TRUE; @@ -4958,6 +4958,14 @@ dhdsdio_testrcv(dhd_bus_t *bus, void *pkt, uint seq) } #endif /* SDTEST */ +extern void +dhd_disable_intr(dhd_pub_t *dhdp) +{ + dhd_bus_t *bus; + bus = dhdp->bus; + bcmsdh_intr_disable(bus->sdh); +} + extern bool dhd_bus_watchdog(dhd_pub_t *dhdp) { diff --git a/drivers/net/wireless/bcmdhd/include/epivers.h b/drivers/net/wireless/bcmdhd/include/epivers.h index 3dfcc15..5c63a39 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 48 +#define EPI_INCREMENTAL_NUMBER 52 #define EPI_BUILD_NUMBER 0 -#define EPI_VERSION 5, 90, 125, 48 +#define EPI_VERSION 5, 90, 125, 52 -#define EPI_VERSION_NUM 0x055a7d30 +#define EPI_VERSION_NUM 0x055a7d34 #define EPI_VERSION_DEV 5.90.125 -#define EPI_VERSION_STR "5.90.125.48" +#define EPI_VERSION_STR "5.90.125.52" #endif diff --git a/drivers/net/wireless/bcmdhd/wl_android.c b/drivers/net/wireless/bcmdhd/wl_android.c index 876fc08..8314bbc 100644 --- a/drivers/net/wireless/bcmdhd/wl_android.c +++ b/drivers/net/wireless/bcmdhd/wl_android.c @@ -92,7 +92,7 @@ typedef struct cmd_tlv { char subver; char reserved; } cmd_tlv_t; -#endif +#endif /* PNO_SUPPORT */ typedef struct android_wifi_priv_cmd { char *buf; @@ -280,7 +280,7 @@ static int wl_android_set_pno_setup(struct net_device *dev, char *command, int t exit_proc: return res; } -#endif +#endif /* PNO_SUPPORT */ static int wl_android_get_p2p_dev_addr(struct net_device *ndev, char *command, int total_len) { @@ -401,7 +401,7 @@ int wl_android_priv_cmd(struct net_device *net, struct ifreq *ifr, int cmd) if (!g_wifi_on) { DHD_ERROR(("%s: Ignore private cmd \"%s\" - iface %s is down\n", - __FUNCTION__, command, ifr->ifr_name)); + __FUNCTION__, command, ifr->ifr_name)); ret = 0; goto exit; } @@ -520,6 +520,17 @@ int wl_android_exit(void) return ret; } +int wl_android_post_init(void) +{ + int ret = 0; + if (!dhd_download_fw_on_driverload) { + /* Call customer gpio to turn off power with WL_REG_ON signal */ + dhd_customer_gpio_wlan_ctrl(WLAN_RESET_OFF); + g_wifi_on = 0; + + } + return ret; +} /** * Functions for Android WiFi card detection diff --git a/drivers/net/wireless/bcmdhd/wl_android.h b/drivers/net/wireless/bcmdhd/wl_android.h index 3c75bfb..289a326 100644 --- a/drivers/net/wireless/bcmdhd/wl_android.h +++ b/drivers/net/wireless/bcmdhd/wl_android.h @@ -22,7 +22,7 @@ */ int wl_android_init(void); int wl_android_exit(void); - +int wl_android_post_init(void); int wl_android_wifi_on(struct net_device *dev); int wl_android_wifi_off(struct net_device *dev); int wl_android_priv_cmd(struct net_device *net, struct ifreq *ifr, int cmd); @@ -36,4 +36,4 @@ int wifi_get_irq_number(unsigned long *irq_flags_ptr); int wifi_set_power(int on, unsigned long msec); int wifi_get_mac_addr(unsigned char *buf); void *wifi_get_country_code(char *ccode); -#endif /* CONFIG_WIFI_CONTROL_FUNC */ \ No newline at end of file +#endif /* CONFIG_WIFI_CONTROL_FUNC */ diff --git a/drivers/net/wireless/bcmdhd/wl_cfg80211.c b/drivers/net/wireless/bcmdhd/wl_cfg80211.c index b7a8a7e..b83cb3e 100644 --- a/drivers/net/wireless/bcmdhd/wl_cfg80211.c +++ b/drivers/net/wireless/bcmdhd/wl_cfg80211.c @@ -138,28 +138,25 @@ static const struct ieee80211_regdomain brcm_regdom = { /* IEEE 802.11b/g, channels 1..11 */ REG_RULE(2412-10, 2462+10, 40, 6, 20, 0), /* IEEE 802.11b/g, channels 12..13. No HT40 - * channel fits here. */ + * channel fits here. + */ REG_RULE(2467-10, 2472+10, 20, 6, 20, - NL80211_RRF_PASSIVE_SCAN | - NL80211_RRF_NO_IBSS), + NL80211_RRF_PASSIVE_SCAN | + NL80211_RRF_NO_IBSS), /* IEEE 802.11 channel 14 - Only JP enables - * this and for 802.11b only */ + * this and for 802.11b only + */ REG_RULE(2484-10, 2484+10, 20, 6, 20, - NL80211_RRF_PASSIVE_SCAN | - NL80211_RRF_NO_IBSS | - NL80211_RRF_NO_OFDM), + NL80211_RRF_PASSIVE_SCAN | + NL80211_RRF_NO_IBSS | + NL80211_RRF_NO_OFDM), /* IEEE 802.11a, channel 36..48 */ - REG_RULE(5180-10, 5240+10, 40, 6, 20, 0 - /*NL80211_RRF_PASSIVE_SCAN | - NL80211_RRF_NO_IBSS*/), + REG_RULE(5180-10, 5240+10, 40, 6, 20, 0), /* NB: 5260 MHz - 5700 MHz requies DFS */ /* IEEE 802.11a, channel 149..165 */ - REG_RULE(5745-10, 5825+10, 40, 6, 20, 0 - /*NL80211_RRF_PASSIVE_SCAN | - NL80211_RRF_NO_IBSS*/), - } + REG_RULE(5745-10, 5825+10, 40, 6, 20, 0), } }; @@ -170,8 +167,32 @@ static const struct ieee80211_regdomain brcm_regdom = { #define WPS_ID_VERSION 0x104A #define WPS_ID_DEVICE_PWD_ID 0x1012 #define WPS_ID_REQ_DEV_TYPE 0x106A +#define WPS_ID_SELECTED_REGISTRAR_CONFIG_METHODS 0x1053 #define WPS_ID_PRIM_DEV_TYPE 0x1054 +/* Device Password ID */ +#define DEV_PW_DEFAULT 0x0000 +#define DEV_PW_USER_SPECIFIED 0x0001, +#define DEV_PW_MACHINE_SPECIFIED 0x0002 +#define DEV_PW_REKEY 0x0003 +#define DEV_PW_PUSHBUTTON 0x0004 +#define DEV_PW_REGISTRAR_SPECIFIED 0x0005 + +/* Config Methods */ +#define WPS_CONFIG_USBA 0x0001 +#define WPS_CONFIG_ETHERNET 0x0002 +#define WPS_CONFIG_LABEL 0x0004 +#define WPS_CONFIG_DISPLAY 0x0008 +#define WPS_CONFIG_EXT_NFC_TOKEN 0x0010 +#define WPS_CONFIG_INT_NFC_TOKEN 0x0020 +#define WPS_CONFIG_NFC_INTERFACE 0x0040 +#define WPS_CONFIG_PUSHBUTTON 0x0080 +#define WPS_CONFIG_KEYPAD 0x0100 +#define WPS_CONFIG_VIRT_PUSHBUTTON 0x0280 +#define WPS_CONFIG_PHY_PUSHBUTTON 0x0480 +#define WPS_CONFIG_VIRT_DISPLAY 0x2008 +#define WPS_CONFIG_PHY_DISPLAY 0x4008 + /* * cfg80211_ops api/callback list */ @@ -264,7 +285,6 @@ static s32 wl_bss_roaming_done(struct wl_priv *wl, struct net_device *ndev, const wl_event_msg_t *e, void *data); static s32 wl_notify_mic_status(struct wl_priv *wl, struct net_device *ndev, const wl_event_msg_t *e, void *data); - /* * register/deregister sdio function */ @@ -455,6 +475,9 @@ static int wl_rfkill_set(void *data, bool blocked); * Some external functions, TODO: move them to dhd_linux.h */ int dhd_add_monitor(char *name, struct net_device **new_ndev); +int dhd_del_monitor(struct net_device *ndev); +int dhd_monitor_init(void *dhd_pub); +int dhd_monitor_uninit(void); int dhd_start_xmit(struct sk_buff *skb, struct net_device *net); #define WL_PRIV_GET() \ @@ -478,9 +501,11 @@ do { \ } \ } while (0) + #define IS_WPA_AKM(akm) ((akm) == RSN_AKM_NONE || \ - (akm) == RSN_AKM_UNSPECIFIED || \ - (akm) == RSN_AKM_PSK) + (akm) == RSN_AKM_UNSPECIFIED || \ + (akm) == RSN_AKM_PSK) + extern int dhd_wait_pend8021x(struct net_device *dev); @@ -762,7 +787,7 @@ static void swap_key_to_BE(struct wl_wsec_key *key) /* For debug: Dump the contents of the encoded wps ie buffe */ static void -wl_dbg_dump_wps_ie(char *wps_ie) +wl_validate_wps_ie(char *wps_ie, bool *pbc) { #define WPS_IE_FIXED_LEN 6 u16 len = (u16) wps_ie[TLV_LEN_OFF]; @@ -808,6 +833,7 @@ wl_dbg_dump_wps_ie(char *wps_ie) valptr[0] = *subel; valptr[1] = *(subel + 1); WL_DBG((" attr WPS_ID_DEVICE_PWD_ID: %u\n", HTON16(val))); + *pbc = (HTON16(val) == DEV_PW_PUSHBUTTON) ? true : false; } else if (subelt_id == WPS_ID_PRIM_DEV_TYPE) { valptr[0] = *subel; valptr[1] = *(subel + 1); @@ -822,6 +848,11 @@ wl_dbg_dump_wps_ie(char *wps_ie) valptr[0] = *(subel + 6); valptr[1] = *(subel + 7); WL_DBG((" attr WPS_ID_REQ_DEV_TYPE: subcat=%u\n", HTON16(val))); + } else if (subelt_id == WPS_ID_SELECTED_REGISTRAR_CONFIG_METHODS) { + valptr[0] = *subel; + valptr[1] = *(subel + 1); + WL_DBG((" attr WPS_ID_SELECTED_REGISTRAR_CONFIG_METHODS" + ": cat=%u\n", HTON16(val))); } else { WL_DBG((" unknown attr 0x%x\n", subelt_id)); } @@ -836,7 +867,7 @@ static struct net_device* wl_cfg80211_add_monitor_if(char *name) struct net_device* ndev = NULL; ret = dhd_add_monitor(name, &ndev); - WL_ERR(("wl_cfg80211_add_monitor_if net device returned: 0x%p\n", ndev)); + WL_INFO(("wl_cfg80211_add_monitor_if net device returned: 0x%p\n", ndev)); return ndev; } @@ -918,48 +949,48 @@ wl_cfg80211_add_virtual_iface(struct wiphy *wiphy, char *name, strncpy(wl->p2p->vir_ifname, name, IFNAMSIZ - 1); wl_cfgp2p_generate_bss_mac(&dhd->mac, &wl->p2p->dev_addr, &wl->p2p->int_addr); - /* Temporary use channel 11, in case GO will be changed with set_channel API */ - chspec = wf_chspec_aton(WL_P2P_TEMP_CHAN); + /* Temporary use channel 11, in case GO will be changed with set_channel API */ + chspec = wf_chspec_aton(WL_P2P_TEMP_CHAN); - /* For P2P mode, use P2P-specific driver features to create the - * bss: "wl p2p_ifadd" - */ - wl_set_p2p_status(wl, IF_ADD); + /* For P2P mode, use P2P-specific driver features to create the + * bss: "wl p2p_ifadd" + */ + wl_set_p2p_status(wl, IF_ADD); err = wl_cfgp2p_ifadd(wl, &wl->p2p->int_addr, htod32(wlif_type), chspec); - if (unlikely(err)) - return ERR_PTR(-ENOMEM); + if (unlikely(err)) + return ERR_PTR(-ENOMEM); - timeout = wait_event_interruptible_timeout(wl->dongle_event_wait, + timeout = wait_event_interruptible_timeout(wl->dongle_event_wait, (wl_get_p2p_status(wl, IF_ADD) == false), - msecs_to_jiffies(MAX_WAIT_TIME)); - if (timeout > 0 && (!wl_get_p2p_status(wl, IF_ADD))) { - - struct wireless_dev *vwdev; - vwdev = kzalloc(sizeof(*vwdev), GFP_KERNEL); - if (unlikely(!vwdev)) { - WL_ERR(("Could not allocate wireless device\n")); - return ERR_PTR(-ENOMEM); - } - vwdev->wiphy = wl->wdev->wiphy; + msecs_to_jiffies(MAX_WAIT_TIME)); + if (timeout > 0 && (!wl_get_p2p_status(wl, IF_ADD))) { + + struct wireless_dev *vwdev; + vwdev = kzalloc(sizeof(*vwdev), GFP_KERNEL); + if (unlikely(!vwdev)) { + WL_ERR(("Could not allocate wireless device\n")); + return ERR_PTR(-ENOMEM); + } + vwdev->wiphy = wl->wdev->wiphy; WL_INFO((" virtual interface(%s) is created \n", wl->p2p->vir_ifname)); - index = alloc_idx_vwdev(wl); - wl->vwdev[index] = vwdev; - vwdev->iftype = - (wlif_type == WL_P2P_IF_CLIENT) ? NL80211_IFTYPE_STATION - : NL80211_IFTYPE_AP; - _ndev = wl_to_p2p_bss_ndev(wl, P2PAPI_BSSCFG_CONNECTION); - _ndev->ieee80211_ptr = vwdev; - SET_NETDEV_DEV(_ndev, wiphy_dev(vwdev->wiphy)); - vwdev->netdev = _ndev; + index = alloc_idx_vwdev(wl); + wl->vwdev[index] = vwdev; + vwdev->iftype = + (wlif_type == WL_P2P_IF_CLIENT) ? NL80211_IFTYPE_STATION + : NL80211_IFTYPE_AP; + _ndev = wl_to_p2p_bss_ndev(wl, P2PAPI_BSSCFG_CONNECTION); + _ndev->ieee80211_ptr = vwdev; + SET_NETDEV_DEV(_ndev, wiphy_dev(vwdev->wiphy)); + vwdev->netdev = _ndev; wl_set_drv_status(wl, READY); wl->p2p->vif_created = true; - set_mode_by_netdev(wl, _ndev, mode); - wl = wdev_to_wl(vwdev); - return _ndev; + set_mode_by_netdev(wl, _ndev, mode); + wl = wdev_to_wl(vwdev); + return _ndev; - } else { - wl_clr_p2p_status(wl, IF_ADD); + } else { + wl_clr_p2p_status(wl, IF_ADD); WL_ERR((" virtual interface(%s) is not created \n", wl->p2p->vir_ifname)); memset(wl->p2p->vir_ifname, '\0', IFNAMSIZ); wl->p2p->vif_created = false; @@ -975,7 +1006,11 @@ wl_cfg80211_del_virtual_iface(struct wiphy *wiphy, struct net_device *dev) struct ether_addr p2p_mac; struct wl_priv *wl = WL_PRIV_GET(); s32 timeout = -1; - + s32 ret = 0; + if (dev && dev->type == ARPHRD_IEEE80211_RADIOTAP) { + ret = dhd_del_monitor(dev); + goto exit; + } if (wl->p2p_supported) { memcpy(p2p_mac.octet, wl->p2p->int_addr.octet, ETHER_ADDR_LEN); if (wl->p2p->vif_created) { @@ -998,8 +1033,8 @@ wl_cfg80211_del_virtual_iface(struct wiphy *wiphy, struct net_device *dev) } } } - - return 0; +exit: + return ret; } static s32 @@ -1137,7 +1172,7 @@ 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", + WL_DBG(("IF_DEL event called from dongle, _net name: %s, vif name: %s\n", net->name, wl->p2p->vir_ifname)); memset(wl->p2p->vir_ifname, '\0', IFNAMSIZ); @@ -1155,10 +1190,10 @@ wl_cfg80211_notify_ifdel(struct net_device *net) } } - wl_clr_p2p_status(wl, IF_DELETING); + wl_clr_p2p_status(wl, IF_DELETING); /* Wake up any waiting thread */ - wake_up_interruptible(&wl->dongle_event_wait); + wake_up_interruptible(&wl->dongle_event_wait); return 0; } @@ -2040,12 +2075,12 @@ wl_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev, if (p2p_on(wl) && is_wps_conn(sme)) { WL_DBG(("p2p index : %d\n", wl_cfgp2p_find_idx(wl, dev))); /* Have to apply WPS IE + P2P IE in assoc req frame */ - wl_cfgp2p_set_managment_ie(wl, dev, + wl_cfgp2p_set_management_ie(wl, dev, wl_cfgp2p_find_idx(wl, dev), VNDR_IE_PRBREQ_FLAG, wl_to_p2p_bss_saved_ie(wl, P2PAPI_BSSCFG_DEVICE).p2p_probe_req_ie, wl_to_p2p_bss_saved_ie(wl, P2PAPI_BSSCFG_DEVICE).p2p_probe_req_ie_len); - wl_cfgp2p_set_managment_ie(wl, dev, wl_cfgp2p_find_idx(wl, dev), + wl_cfgp2p_set_management_ie(wl, dev, wl_cfgp2p_find_idx(wl, dev), VNDR_IE_ASSOCREQ_FLAG, sme->ie, sme->ie_len); } else if (p2p_on(wl) && (sme->crypto.wpa_versions & NL80211_WPA_VERSION_2)) { /* This is the connect req after WPS is done [credentials exchanged] @@ -2054,7 +2089,7 @@ wl_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev, * the newly received IEs from Supplicant. This will remove the WPS IE from * the Assoc Req. */ - wl_cfgp2p_set_managment_ie(wl, dev, wl_cfgp2p_find_idx(wl, dev), + wl_cfgp2p_set_management_ie(wl, dev, wl_cfgp2p_find_idx(wl, dev), VNDR_IE_ASSOCREQ_FLAG, sme->ie, sme->ie_len); } @@ -3040,9 +3075,9 @@ wl_cfg80211_mgmt_tx(struct wiphy *wiphy, struct net_device *dev, } if (wl->p2p_supported && p2p_on(wl)) { wl_cfgp2p_generate_bss_mac(&dhd->mac, &wl->p2p->dev_addr, &wl->p2p->int_addr); - /* Suspend P2P discovery search-listen to prevent it from changing the - * channel. - */ + /* Suspend P2P discovery search-listen to prevent it from changing the + * channel. + */ if ((err = wl_cfgp2p_discover_enable_search(wl, false)) < 0) { WL_ERR(("Can not disable discovery mode\n")); return -EFAULT; @@ -3076,17 +3111,15 @@ wl_cfg80211_mgmt_tx(struct wiphy *wiphy, struct net_device *dev, */ wpsie_len = wps_ie->length + sizeof(wps_ie->length) + sizeof(wps_ie->tag); - wl_cfgp2p_set_managment_ie(wl, dev, bssidx, + wl_cfgp2p_set_management_ie(wl, dev, bssidx, VNDR_IE_PRBRSP_FLAG, (u8 *)wps_ie, wpsie_len + p2pie_len); /* remove WLC_E_PROBREQ_MSG event to prevent HOSTAPD * from responding many probe request */ - wl_dongle_add_remove_eventmsg(dev, WLC_E_PROBREQ_MSG, false); } } cfg80211_mgmt_tx_status(dev, *cookie, buf, len, true, GFP_KERNEL); - goto exit; } else { /* Abort the dwell time of any previous off-channel action frame that may @@ -3484,6 +3517,7 @@ wl_cfg80211_set_beacon(struct wiphy *wiphy, struct net_device *dev, wifi_p2p_ie_t *p2p_ie; bool is_bssup = false; bool update_bss = false; + bool pbc = false; u16 wpsie_len = 0; u16 p2pie_len = 0; u8 beacon_ie[IE_MAX_LEN]; @@ -3521,8 +3555,7 @@ wl_cfg80211_set_beacon(struct wiphy *wiphy, struct net_device *dev, /* * Should be compared with saved ie before saving it */ - if (wl_dbg_level & WL_DBG_INFO) - wl_dbg_dump_wps_ie((char *) wps_ie); + wl_validate_wps_ie((char *) wps_ie, &pbc); memcpy(beacon_ie, wps_ie, wpsie_len); } else { WL_ERR(("No WPSIE in beacon \n")); @@ -3544,9 +3577,9 @@ wl_cfg80211_set_beacon(struct wiphy *wiphy, struct net_device *dev, } else { WL_ERR(("No P2PIE in beacon \n")); } - wl_cfgp2p_set_managment_ie(wl, dev, bssidx, VNDR_IE_BEACON_FLAG, + wl_cfgp2p_set_management_ie(wl, dev, bssidx, VNDR_IE_BEACON_FLAG, beacon_ie, wpsie_len + p2pie_len); - wl_cfgp2p_set_managment_ie(wl, dev, bssidx, VNDR_IE_ASSOCRSP_FLAG, + wl_cfgp2p_set_management_ie(wl, dev, bssidx, VNDR_IE_ASSOCRSP_FLAG, beacon_ie, wpsie_len + p2pie_len); /* find the RSN_IE */ @@ -3634,16 +3667,15 @@ wl_cfg80211_set_beacon(struct wiphy *wiphy, struct net_device *dev, /* * Should be compared with saved ie before saving it */ - if (wl_dbg_level & WL_DBG_INFO) - wl_dbg_dump_wps_ie((char *) wps_ie); + wl_validate_wps_ie((char *) wps_ie, &pbc); memcpy(beacon_ie, wps_ie, wpsie_len); - wl_cfgp2p_set_managment_ie(wl, dev, bssidx, VNDR_IE_BEACON_FLAG, + wl_cfgp2p_set_management_ie(wl, dev, bssidx, VNDR_IE_BEACON_FLAG, beacon_ie, wpsie_len); wl->ap_info->wps_ie = kmemdup(wps_ie, wpsie_len, GFP_KERNEL); /* add WLC_E_PROBREQ_MSG event to respose probe_request from STA */ - wl_dongle_add_remove_eventmsg(dev, WLC_E_PROBREQ_MSG, true); + wl_dongle_add_remove_eventmsg(dev, WLC_E_PROBREQ_MSG, pbc); } else { - WL_ERR(("No WPSIE in beacon \n")); + WL_DBG(("No WPSIE in beacon \n")); } wldev_ioctl(dev, WLC_UP, &ap, sizeof(s32), false); @@ -3667,10 +3699,9 @@ wl_cfg80211_set_beacon(struct wiphy *wiphy, struct net_device *dev, /* * Should be compared with saved ie before saving it */ - if (wl_dbg_level & WL_DBG_INFO) - wl_dbg_dump_wps_ie((char *) wps_ie); + wl_validate_wps_ie((char *) wps_ie, &pbc); memcpy(beacon_ie, wps_ie, wpsie_len); - wl_cfgp2p_set_managment_ie(wl, dev, bssidx, VNDR_IE_BEACON_FLAG, + wl_cfgp2p_set_management_ie(wl, dev, bssidx, VNDR_IE_BEACON_FLAG, beacon_ie, wpsie_len); if (wl->ap_info->wps_ie && memcmp(wl->ap_info->wps_ie, wps_ie, wpsie_len)) { @@ -3678,12 +3709,12 @@ wl_cfg80211_set_beacon(struct wiphy *wiphy, struct net_device *dev, kfree(wl->ap_info->wps_ie); wl->ap_info->wps_ie = kmemdup(wps_ie, wpsie_len, GFP_KERNEL); /* add WLC_E_PROBREQ_MSG event to respose probe_request from STA */ - wl_dongle_add_remove_eventmsg(dev, WLC_E_PROBREQ_MSG, true); + wl_dongle_add_remove_eventmsg(dev, WLC_E_PROBREQ_MSG, pbc); } else if (wl->ap_info->wps_ie == NULL) { WL_DBG((" WPS IE is added\n")); wl->ap_info->wps_ie = kmemdup(wps_ie, wpsie_len, GFP_KERNEL); /* add WLC_E_PROBREQ_MSG event to respose probe_request from STA */ - wl_dongle_add_remove_eventmsg(dev, WLC_E_PROBREQ_MSG, true); + wl_dongle_add_remove_eventmsg(dev, WLC_E_PROBREQ_MSG, pbc); } /* find the RSN_IE */ if ((wpa2_ie = bcm_parse_tlvs((u8 *)info->tail, info->tail_len, @@ -5050,7 +5081,7 @@ static void wl_notify_escan_complete(struct wl_priv *wl, bool aborted) } wl_clr_drv_status(wl, SCANNING); if (wl->p2p_supported && p2p_on(wl)) - wl_clr_p2p_status(wl, SCANNING); + wl_clr_p2p_status(wl, SCANNING); if (likely(wl->scan_request)) { cfg80211_scan_done(wl->scan_request, aborted); @@ -5085,7 +5116,6 @@ static s32 wl_escan_handler(struct wl_priv *wl, WL_ERR(("Invalid escan result (NULL pointer)\n")); goto exit; } - if (dtoh16(escan_result->bss_count) != 1) { WL_ERR(("Invalid bss_count %d: ignoring\n", escan_result->bss_count)); goto exit; @@ -6034,7 +6064,7 @@ static s32 __wl_cfg80211_up(struct wl_priv *wl) err = wl_config_dongle(wl, false); if (unlikely(err)) return err; - + dhd_monitor_init(wl->pub); wl_invoke_iscan(wl); wl_set_drv_status(wl, READY); return err; @@ -6071,6 +6101,7 @@ static s32 __wl_cfg80211_down(struct wl_priv *wl) wl_link_down(wl); if (wl->p2p_supported) wl_cfgp2p_down(wl); + dhd_monitor_uninit(); wl_debugfs_remove_netdev(wl); @@ -6107,7 +6138,6 @@ s32 wl_cfg80211_down(void) return err; } - static s32 wl_dongle_probecap(struct wl_priv *wl) { s32 err = 0; @@ -6420,6 +6450,7 @@ s32 wl_cfg80211_get_p2p_dev_addr(struct net_device *net, struct ether_addr *p2pd static __used void wl_dongle_poweron(struct wl_priv *wl) { + WL_DBG(("Enter \n")); dhd_customer_gpio_wlan_ctrl(WLAN_RESET_ON); @@ -6434,6 +6465,8 @@ static __used void wl_dongle_poweron(struct wl_priv *wl) static __used void wl_dongle_poweroff(struct wl_priv *wl) { + + WL_DBG(("Enter \n")); #if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 39) wl_cfg80211_suspend(wl_to_wiphy(wl), NULL); diff --git a/drivers/net/wireless/bcmdhd/wl_cfgp2p.c b/drivers/net/wireless/bcmdhd/wl_cfgp2p.c index fa88d4b..7a5619e 100644 --- a/drivers/net/wireless/bcmdhd/wl_cfgp2p.c +++ b/drivers/net/wireless/bcmdhd/wl_cfgp2p.c @@ -21,11 +21,9 @@ * 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_cfg80211.c,v 1.1.4.1.2.14 2011-02-09 01:40:07 Exp $ - * $Id$ + * $Id: wl_cfgp2p.c,v 1.1.4.1.2.14 2011-02-09 01:40:07 Exp $ + * */ - - #include #include #include @@ -436,7 +434,7 @@ wl_cfgp2p_enable_discovery(struct wl_priv *wl, struct net_device *dev, const u8 CFGP2P_ERR((" wsec error %d\n", ret)); } set_ie: - ret = wl_cfgp2p_set_managment_ie(wl, dev, + ret = wl_cfgp2p_set_management_ie(wl, dev, wl_to_p2p_bss_bssidx(wl, P2PAPI_BSSCFG_DEVICE), VNDR_IE_PRBREQ_FLAG, ie, ie_len); @@ -604,7 +602,7 @@ wl_cfgp2p_escan(struct wl_priv *wl, struct net_device *dev, u16 active, */ s32 -wl_cfgp2p_set_managment_ie(struct wl_priv *wl, struct net_device *ndev, s32 bssidx, +wl_cfgp2p_set_management_ie(struct wl_priv *wl, struct net_device *ndev, s32 bssidx, s32 pktflag, const u8 *vndr_ie, u32 vndr_ie_len) { /* Vendor-specific Information Element ID */ @@ -677,7 +675,7 @@ wl_cfgp2p_set_managment_ie(struct wl_priv *wl, struct net_device *ndev, s32 bssi } /* Add if there is any extra IE */ if (vndr_ie && vndr_ie_len) { - CFGP2P_ERR(("Request has extra IE")); + CFGP2P_INFO(("Request has extra IE")); if (vndr_ie_len > mgmt_ie_buf_len) { CFGP2P_ERR(("extra IE size too big\n")); ret = -ENOMEM; @@ -898,7 +896,7 @@ wl_cfgp2p_find_idx(struct wl_priv *wl, struct net_device *ndev) return P2PAPI_BSSCFG_PRIMARY; } for (i = 0; i < P2PAPI_BSSCFG_MAX; i++) { - if (ndev == wl_to_p2p_bss_ndev(wl, i)) { + if (ndev == wl_to_p2p_bss_ndev(wl, i)) { index = wl_to_p2p_bss_bssidx(wl, i); break; } @@ -1015,11 +1013,11 @@ wl_cfgp2p_discover_enable_search(struct wl_priv *wl, u8 enable) CFGP2P_DBG((" Enter\n")); if (!wl_get_p2p_status(wl, DISCOVERY_ON)) { - CFGP2P_ERR((" do nothing, discovery is off\n")); + CFGP2P_DBG((" do nothing, discovery is off\n")); return ret; } if (wl_get_p2p_status(wl, SEARCH_ENABLED) == enable) { - CFGP2P_ERR(("already : %d\n", enable)); + CFGP2P_DBG(("already : %d\n", enable)); return ret; } @@ -1254,7 +1252,7 @@ wl_cfgp2p_supported(struct wl_priv *wl, struct net_device *ndev) ret = wldev_iovar_getint(ndev, "p2p", &p2p_supported); if (ret < 0) { - CFGP2P_ERR(("wl p2p error %d\n", ret)); + CFGP2P_ERR(("wl p2p error %d\n", ret)); return 0; } if (p2p_supported == 1) { diff --git a/drivers/net/wireless/bcmdhd/wl_cfgp2p.h b/drivers/net/wireless/bcmdhd/wl_cfgp2p.h index 1b28fa9..971633a 100644 --- a/drivers/net/wireless/bcmdhd/wl_cfgp2p.h +++ b/drivers/net/wireless/bcmdhd/wl_cfgp2p.h @@ -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_cfg80211.h,v 1.1.4.1.2.8 2011/02/09 01:37:52 Exp $ + * $Id: wl_cfgp2p.h,v 1.1.4.1.2.8 2011/02/09 01:37:52 Exp $ */ #ifndef _wl_cfgp2p_h_ #define _wl_cfgp2p_h_ @@ -176,7 +176,7 @@ extern wifi_p2p_ie_t * wl_cfgp2p_find_p2pie(u8 *parse, u32 len); extern s32 -wl_cfgp2p_set_managment_ie(struct wl_priv *wl, struct net_device *ndev, s32 bssidx, +wl_cfgp2p_set_management_ie(struct wl_priv *wl, struct net_device *ndev, s32 bssidx, s32 pktflag, const u8 *vndr_ie, u32 vndr_ie_len); extern s32 wl_cfgp2p_clear_management_ie(struct wl_priv *wl, s32 bssidx); -- 2.7.4