net: wireless: bcmdhd: Update to Version 5.90.125.87

- Improve discovery of FW hanging
- Add WFD noa and power-safe related functions

Signed-off-by: Dmitry Shmidt <dimitrysh@google.com>
This commit is contained in:
Dmitry Shmidt 2011-09-21 13:09:58 -07:00
parent 7007813a12
commit 0eb5aac3aa
11 changed files with 391 additions and 110 deletions

View File

@ -24,7 +24,7 @@
* software in any way with any other Broadcom software provided under a license
* other than the GPL, without Broadcom's express prior written consent.
*
* $Id: dhd.h,v 1.60.4.17 2011-01-09 08:11:56 Exp $
* $Id: dhd.h 285209 2011-09-21 01:21:24Z $
*/
/****************
@ -80,6 +80,9 @@ enum dhd_bus_state {
#define WFD_MASK 0x0004
#define SOFTAP_FW_MASK 0x0008
/* max sequential rxcntl timeouts to set HANG event */
#define MAX_CNTL_TIMEOUT 2
enum dhd_bus_wake_state {
WAKE_LOCK_OFF,
WAKE_LOCK_PRIV,
@ -96,6 +99,7 @@ enum dhd_bus_wake_state {
WAKE_LOCK_SOFTAP_THREAD,
WAKE_LOCK_MAX
};
enum dhd_prealloc_index {
DHD_PREALLOC_PROT = 0,
DHD_PREALLOC_RXBUF,
@ -121,6 +125,7 @@ void dhd_os_prefree(void *osh, void *addr, uint size);
#ifndef DHD_SDALIGN
#define DHD_SDALIGN 32
#endif
/* Common structure for module and instance linkage */
typedef struct dhd_pub {
/* Linkage ponters */
@ -203,6 +208,8 @@ typedef struct dhd_pub {
#endif
bool dongle_isolation;
int hang_was_sent;
int rxcnt_timeout; /* counter rxcnt timeout to send HANG */
int txcnt_timeout; /* counter txcnt timeout to send HANG */
#ifdef WLMEDIA_HTSF
uint8 htsfdlystat_sz; /* Size of delay stats, max 255B */
#endif
@ -296,6 +303,7 @@ inline static void MUTEX_UNLOCK_SOFTAP_SET(dhd_pub_t * dhdp)
#define DHD_OS_WAKE_UNLOCK(pub) dhd_os_wake_unlock(pub)
#define DHD_OS_WAKE_LOCK_TIMEOUT(pub) dhd_os_wake_lock_timeout(pub)
#define DHD_OS_WAKE_LOCK_TIMEOUT_ENABLE(pub, val) dhd_os_wake_lock_timeout_enable(pub, val)
#define DHD_PACKET_TIMEOUT 1
#define DHD_EVENT_TIMEOUT 2
@ -468,6 +476,7 @@ extern uint dhd_bus_status(dhd_pub_t *dhdp);
extern int dhd_bus_start(dhd_pub_t *dhdp);
extern int dhd_bus_membytes(dhd_pub_t *dhdp, bool set, uint32 address, uint8 *data, uint size);
extern void dhd_print_buf(void *pbuf, int len, int bytes_per_line);
#if defined(KEEP_ALIVE)
extern int dhd_keep_alive_onoff(dhd_pub_t *dhd);
#endif /* KEEP_ALIVE */
@ -707,4 +716,5 @@ void dhd_aoe_arp_clr(dhd_pub_t *dhd);
int dhd_arp_get_arp_hostip_table(dhd_pub_t *dhd, void *buf, int buflen);
void dhd_arp_offload_add_ip(dhd_pub_t *dhd, uint32 ipaddr);
#endif /* ARP_OFFLOAD_SUPPORT */
#endif /* _dhd_h_ */

View File

@ -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: dhd_common.c,v 1.57.2.22 2011-02-01 18:38:37 Exp $
* $Id: dhd_common.c 284903 2011-09-20 02:36:51Z $
*/
#include <typedefs.h>
#include <osl.h>
@ -484,7 +484,7 @@ dhd_doiovar(dhd_pub_t *dhd_pub, const bcm_iovar_t *vi, uint32 actionid, const ch
#endif /* PROP_TXSTATUS */
case IOV_GVAL(IOV_BUS_TYPE):
/* The dhd application query the driver to check if its usb or sdio. */
/* The dhd application queries the driver to check if its usb or sdio. */
#ifdef BCMDHDUSB
int_val = BUS_TYPE_USB;
#endif
@ -1004,27 +1004,27 @@ wl_host_event(dhd_pub_t *dhd_pub, int *ifidx, void *pktdata,
case WLC_E_IF:
{
dhd_if_event_t *ifevent = (dhd_if_event_t *)event_data;
dhd_if_event_t *ifevent = (dhd_if_event_t *)event_data;
#ifdef PROP_TXSTATUS
{
uint8* ea = pvt_data->eth.ether_dhost;
WLFC_DBGMESG(("WLC_E_IF: idx:%d, action:%s, iftype:%s, "
"[%02x:%02x:%02x:%02x:%02x:%02x]\n",
ifevent->ifidx,
((ifevent->action == WLC_E_IF_ADD) ? "ADD":"DEL"),
((ifevent->is_AP == 0) ? "STA":"AP "),
ea[0], ea[1], ea[2], ea[3], ea[4], ea[5]));
(void)ea;
{
uint8* ea = pvt_data->eth.ether_dhost;
WLFC_DBGMESG(("WLC_E_IF: idx:%d, action:%s, iftype:%s, "
"[%02x:%02x:%02x:%02x:%02x:%02x]\n",
ifevent->ifidx,
((ifevent->action == WLC_E_IF_ADD) ? "ADD":"DEL"),
((ifevent->is_AP == 0) ? "STA":"AP "),
ea[0], ea[1], ea[2], ea[3], ea[4], ea[5]));
(void)ea;
dhd_wlfc_interface_event(dhd_pub->info,
((ifevent->action == WLC_E_IF_ADD) ?
eWLFC_MAC_ENTRY_ACTION_ADD : eWLFC_MAC_ENTRY_ACTION_DEL),
ifevent->ifidx, ifevent->is_AP, ea);
dhd_wlfc_interface_event(dhd_pub->info,
((ifevent->action == WLC_E_IF_ADD) ?
eWLFC_MAC_ENTRY_ACTION_ADD : eWLFC_MAC_ENTRY_ACTION_DEL),
ifevent->ifidx, ifevent->is_AP, ea);
/* dhd already has created an interface by default, for 0 */
if (ifevent->ifidx == 0)
break;
}
/* dhd already has created an interface by default, for 0 */
if (ifevent->ifidx == 0)
break;
}
#endif /* PROP_TXSTATUS */
#ifdef WL_CFG80211
@ -1032,7 +1032,7 @@ wl_host_event(dhd_pub_t *dhd_pub, int *ifidx, void *pktdata,
DHD_ERROR(("%s: ifidx %d for %s action %d\n",
__FUNCTION__, ifevent->ifidx,
event->ifname, ifevent->action));
if (ifevent->action == WLC_E_IF_ADD)
if (ifevent->action == WLC_E_IF_ADD)
wl_cfg80211_notify_ifchange();
return (BCME_OK);
}
@ -1868,7 +1868,7 @@ dhd_pno_enable(dhd_pub_t *dhd, int pfn_enabled)
if ((pfn_enabled) && (is_associated(dhd, NULL) == TRUE)) {
DHD_ERROR(("%s pno is NOT enable : called in assoc mode , ignore\n", __FUNCTION__));
return ret;
}
}
/* Enable/disable PNO */
if ((ret = bcm_mkiovar("pfn", (char *)&pfn_enabled, 4, iovbuf, sizeof(iovbuf))) > 0) {
@ -1906,6 +1906,7 @@ 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);
@ -2016,13 +2017,13 @@ dhd_pno_get_status(dhd_pub_t *dhd)
#if defined(KEEP_ALIVE)
int dhd_keep_alive_onoff(dhd_pub_t *dhd)
{
char buf[256];
const char *str;
char buf[256];
const char *str;
wl_mkeep_alive_pkt_t mkeep_alive_pkt;
wl_mkeep_alive_pkt_t *mkeep_alive_pktp;
int buf_len;
int str_len;
int res = -1;
int buf_len;
int str_len;
int res = -1;
if (dhd_check_ap_wfd_mode_set(dhd) == TRUE)
return (res);

View File

@ -22,7 +22,7 @@
* software in any way with any other Broadcom software provided under a license
* other than the GPL, without Broadcom's express prior written consent.
*
* $Id: dhd_linux.c,v 1.131.2.55 2011-02-09 05:31:56 Exp $
* $Id: dhd_linux.c 285209 2011-09-21 01:21:24Z $
*/
#include <typedefs.h>
@ -1986,6 +1986,20 @@ dhd_ethtool(dhd_info_t *dhd, void *uaddr)
}
#endif /* LINUX_VERSION_CODE > KERNEL_VERSION(2, 4, 2) */
static bool dhd_check_hang(struct net_device *net, dhd_pub_t *dhdp, int error)
{
dhd_info_t *dhd = (dhd_info_t*)dhdp->info;
if ((error == -ETIMEDOUT) || ((dhd->pub.busstate == DHD_BUS_DOWN) &&
(!dhd->pub.dongle_reset))) {
DHD_ERROR(("%s: Event HANG send up due to re=%d te=%d e=%d s=%d\n", __FUNCTION__,
dhd->pub.rxcnt_timeout, dhd->pub.txcnt_timeout, error, dhd->pub.busstate));
net_os_send_hang_message(net);
return TRUE;
}
return FALSE;
}
static int
dhd_ioctl_entry(struct net_device *net, struct ifreq *ifr, int cmd)
{
@ -2036,6 +2050,7 @@ dhd_ioctl_entry(struct net_device *net, struct ifreq *ifr, int cmd)
if (cmd == SIOCDEVPRIVATE+1) {
ret = wl_android_priv_cmd(net, ifr, cmd);
dhd_check_hang(net, &dhd->pub, ret);
DHD_OS_WAKE_UNLOCK(&dhd->pub);
return ret;
}
@ -2173,11 +2188,7 @@ dhd_ioctl_entry(struct net_device *net, struct ifreq *ifr, int cmd)
bcmerror = dhd_wl_ioctl(&dhd->pub, ifidx, (wl_ioctl_t *)&ioc, buf, buflen);
done:
if ((bcmerror == -ETIMEDOUT) || ((dhd->pub.busstate == DHD_BUS_DOWN) &&
(!dhd->pub.dongle_reset))) {
DHD_ERROR(("%s: Event HANG send up\n", __FUNCTION__));
net_os_send_hang_message(net);
}
dhd_check_hang(net, &dhd->pub, bcmerror);
if (!bcmerror && buf && ioc.buf) {
if (copy_to_user(ioc.buf, buf, buflen))
@ -2270,6 +2281,8 @@ dhd_stop(struct net_device *net)
wl_android_wifi_off(net);
#endif
dhd->pub.hang_was_sent = 0;
dhd->pub.rxcnt_timeout = 0;
dhd->pub.txcnt_timeout = 0;
OLD_MOD_DEC_USE_COUNT;
return 0;
}
@ -4504,6 +4517,7 @@ int dhd_ioctl_entry_local(struct net_device *net, wl_ioctl_t *ioc, int cmd)
DHD_OS_WAKE_LOCK(&dhd->pub);
ret = dhd_wl_ioctl(&dhd->pub, ifidx, ioc, ioc->buf, ioc->len);
dhd_check_hang(net, &dhd->pub, ret);
DHD_OS_WAKE_UNLOCK(&dhd->pub);
return ret;

View File

@ -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: dhd_sdio.c,v 1.274.2.40 2011-02-09 22:42:44 Exp $
* $Id: dhd_sdio.c 285209 2011-09-21 01:21:24Z $
*/
#include <typedefs.h>
@ -422,6 +422,11 @@ do { \
} \
} while (0)
#define BUS_WAKE(bus) \
do { \
if ((bus)->sleeping) \
dhdsdio_bussleep((bus), FALSE); \
} while (0);
/*
* pktavail interrupts from dongle to host can be managed in 3 different ways
@ -920,13 +925,6 @@ dhd_enable_oob_intr(struct dhd_bus *bus, bool enable)
}
#endif /* defined(OOB_INTR_ONLY) */
#define BUS_WAKE(bus) \
do { \
if ((bus)->sleeping) \
dhdsdio_bussleep((bus), FALSE); \
} while (0);
/* Writes a HW/SW header into the packet and sends it. */
/* Assumes: (a) header space already there, (b) caller holds lock */
static int
@ -1375,14 +1373,18 @@ dhd_bus_txctl(struct dhd_bus *bus, uchar *msg, uint msglen)
DHD_INFO(("%s: ctrl_frame_stat == FALSE\n", __FUNCTION__));
ret = 0;
} else {
bus->dhd->txcnt_timeout++;
if (!bus->dhd->hang_was_sent)
DHD_ERROR(("%s: ctrl_frame_stat == TRUE\n", __FUNCTION__));
DHD_ERROR(("%s: ctrl_frame_stat == TRUE txcnt_timeout=%d\n",
__FUNCTION__, bus->dhd->txcnt_timeout));
ret = -1;
bus->ctrl_frame_stat = FALSE;
goto done;
}
}
bus->dhd->txcnt_timeout = 0;
if (ret == -1) {
#ifdef DHD_DEBUG
if (DHD_BYTES_ON() && DHD_CTL_ON()) {
@ -1440,6 +1442,9 @@ dhd_bus_txctl(struct dhd_bus *bus, uchar *msg, uint msglen)
else
bus->dhd->tx_ctlpkts++;
if (bus->dhd->txcnt_timeout >= MAX_CNTL_TIMEOUT)
return -ETIMEDOUT;
return ret ? -EIO : 0;
}
@ -1485,13 +1490,22 @@ dhd_bus_rxctl(struct dhd_bus *bus, uchar *msg, uint msglen)
dhd_os_sdunlock(bus->dhd);
#endif /* DHD_DEBUG */
}
if (timeleft == 0) {
bus->dhd->rxcnt_timeout++;
DHD_ERROR(("%s: rxcnt_timeout=%d\n", __FUNCTION__, bus->dhd->rxcnt_timeout));
}
else
bus->dhd->rxcnt_timeout = 0;
if (rxlen)
bus->dhd->rx_ctlpkts++;
else
bus->dhd->rx_ctlerrs++;
return rxlen ? (int)rxlen : -ETIMEDOUT;
if (bus->dhd->rxcnt_timeout >= MAX_CNTL_TIMEOUT)
return -ETIMEDOUT;
return rxlen ? (int)rxlen : -EIO;
}
/* IOVar table */

View File

@ -19,7 +19,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: epivers.h.in,v 13.32.4.1 2010-09-17 00:39:18 Exp $
* $Id: epivers.h.in,v 13.32.4.1 2010-09-17 00:39:18 $
*
*/
@ -33,17 +33,17 @@
#define EPI_RC_NUMBER 125
#define EPI_INCREMENTAL_NUMBER 84
#define EPI_INCREMENTAL_NUMBER 87
#define EPI_BUILD_NUMBER 0
#define EPI_VERSION 5, 90, 125, 84
#define EPI_VERSION 5, 90, 125, 87
#define EPI_VERSION_NUM 0x055a7d54
#define EPI_VERSION_NUM 0x055a7d57
#define EPI_VERSION_DEV 5.90.125
#define EPI_VERSION_STR "5.90.125.84"
#define EPI_VERSION_STR "5.90.125.87"
#endif

View File

@ -36,7 +36,9 @@
#include <dngl_stats.h>
#include <dhd.h>
#include <bcmsdbus.h>
#ifdef WL_CFG80211
#include <wl_cfg80211.h>
#endif
#if defined(CONFIG_WIFI_CONTROL_FUNC)
#include <linux/platform_device.h>
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 35))
@ -51,25 +53,31 @@
* so they can be updated easily in the future (if needed)
*/
#define CMD_START "START"
#define CMD_STOP "STOP"
#define CMD_SCAN_ACTIVE "SCAN-ACTIVE"
#define CMD_SCAN_PASSIVE "SCAN-PASSIVE"
#define CMD_RSSI "RSSI"
#define CMD_LINKSPEED "LINKSPEED"
#define CMD_RXFILTER_START "RXFILTER-START"
#define CMD_RXFILTER_STOP "RXFILTER-STOP"
#define CMD_RXFILTER_ADD "RXFILTER-ADD"
#define CMD_RXFILTER_REMOVE "RXFILTER-REMOVE"
#define CMD_START "START"
#define CMD_STOP "STOP"
#define CMD_SCAN_ACTIVE "SCAN-ACTIVE"
#define CMD_SCAN_PASSIVE "SCAN-PASSIVE"
#define CMD_RSSI "RSSI"
#define CMD_LINKSPEED "LINKSPEED"
#define CMD_RXFILTER_START "RXFILTER-START"
#define CMD_RXFILTER_STOP "RXFILTER-STOP"
#define CMD_RXFILTER_ADD "RXFILTER-ADD"
#define CMD_RXFILTER_REMOVE "RXFILTER-REMOVE"
#define CMD_BTCOEXSCAN_START "BTCOEXSCAN-START"
#define CMD_BTCOEXSCAN_STOP "BTCOEXSCAN-STOP"
#define CMD_BTCOEXMODE "BTCOEXMODE"
#define CMD_SETSUSPENDOPT "SETSUSPENDOPT"
#define CMD_P2P_DEV_ADDR "P2P_DEV_ADDR"
#define CMD_SETFWPATH "SETFWPATH"
#define CMD_SETBAND "SETBAND"
#define CMD_GETBAND "GETBAND"
#define CMD_COUNTRY "COUNTRY"
#define CMD_BTCOEXSCAN_STOP "BTCOEXSCAN-STOP"
#define CMD_BTCOEXMODE "BTCOEXMODE"
#define CMD_SETSUSPENDOPT "SETSUSPENDOPT"
#define CMD_P2P_DEV_ADDR "P2P_DEV_ADDR"
#define CMD_SETFWPATH "SETFWPATH"
#define CMD_SETBAND "SETBAND"
#define CMD_GETBAND "GETBAND"
#define CMD_COUNTRY "COUNTRY"
#define CMD_P2P_SET_NOA "P2P_SET_NOA"
#define CMD_P2P_GET_NOA "P2P_GET_NOA"
#define CMD_P2P_SET_PS "P2P_SET_PS"
#define CMD_SET_ASSOC_RESP_IE "SET_ASSOC_RESP_IE"
#define CMD_SET_PROBE_RESP_IE "SET_PROBE_RESP_IE"
#define CMD_SET_BEACON_IE "SET_BEACON_IE"
#ifdef PNO_SUPPORT
#define CMD_PNOSSIDCLR_SET "PNOSSIDCLR"
@ -112,6 +120,12 @@ int wl_cfg80211_set_btcoex_dhcp(struct net_device *dev, char *command);
#else
int wl_cfg80211_get_p2p_dev_addr(struct net_device *net, struct ether_addr *p2pdev_addr)
{ return 0; }
int wl_cfg80211_set_p2p_noa(struct net_device *net, char* buf, int len)
{ return 0; }
int wl_cfg80211_get_p2p_noa(struct net_device *net, char* buf, int len)
{ return 0; }
int wl_cfg80211_set_p2p_ps(struct net_device *net, char* buf, int len)
{ return 0; }
#endif
extern bool ap_fw_loaded;
@ -517,7 +531,38 @@ int wl_android_priv_cmd(struct net_device *net, struct ifreq *ifr, int cmd)
#endif
else if (strnicmp(command, CMD_P2P_DEV_ADDR, strlen(CMD_P2P_DEV_ADDR)) == 0) {
bytes_written = wl_android_get_p2p_dev_addr(net, command, priv_cmd.total_len);
} else {
}
else if (strnicmp(command, CMD_P2P_SET_NOA, strlen(CMD_P2P_SET_NOA)) == 0) {
int skip = strlen(CMD_P2P_SET_NOA) + 1;
bytes_written = wl_cfg80211_set_p2p_noa(net, command + skip,
priv_cmd.total_len - skip);
}
else if (strnicmp(command, CMD_P2P_GET_NOA, strlen(CMD_P2P_GET_NOA)) == 0) {
bytes_written = wl_cfg80211_get_p2p_noa(net, command, priv_cmd.total_len);
}
else if (strnicmp(command, CMD_P2P_SET_PS, strlen(CMD_P2P_SET_PS)) == 0) {
int skip = strlen(CMD_P2P_SET_PS) + 1;
bytes_written = wl_cfg80211_set_p2p_ps(net, command + skip,
priv_cmd.total_len - skip);
}
#ifdef WL_CFG80211
else if (strnicmp(command, CMD_SET_ASSOC_RESP_IE, strlen(CMD_SET_ASSOC_RESP_IE)) == 0) {
int skip = strlen(CMD_SET_ASSOC_RESP_IE) + 1;
bytes_written = wl_cfg80211_set_wps_p2p_ie(net, command + skip,
priv_cmd.total_len - skip, WL_ASSOC_RESP);
}
else if (strnicmp(command, CMD_SET_PROBE_RESP_IE, strlen(CMD_SET_PROBE_RESP_IE)) == 0) {
int skip = strlen(CMD_SET_PROBE_RESP_IE) + 1;
bytes_written = wl_cfg80211_set_wps_p2p_ie(net, command + skip,
priv_cmd.total_len - skip, WL_PROBE_RESP);
}
else if (strnicmp(command, CMD_SET_BEACON_IE, strlen(CMD_SET_BEACON_IE)) == 0) {
int skip = strlen(CMD_SET_BEACON_IE) + 1;
bytes_written = wl_cfg80211_set_wps_p2p_ie(net, command + skip,
priv_cmd.total_len - skip, WL_BEACON);
}
#endif /* WL_CFG80211 */
else {
DHD_ERROR(("Unknown PRIVATE command %s - ignored\n", command));
snprintf(command, 3, "OK");
bytes_written = strlen("OK");

View File

@ -1402,8 +1402,10 @@ wl_run_escan(struct wl_priv *wl, struct net_device *ndev,
err = -ENOMEM;
goto exit;
}
wldev_iovar_setbuf(ndev, "escan", params, params_size,
err = wldev_iovar_setbuf(ndev, "escan", params, params_size,
wl->escan_ioctl_buf, WLC_IOCTL_MEDLEN);
if (unlikely(err))
WL_ERR((" Escan set error (%d)\n", err));
kfree(params);
}
else if (p2p_on(wl) && p2p_scan(wl)) {
@ -2171,7 +2173,8 @@ wl_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev,
if (IS_P2P_SSID(sme->ssid) && (dev != wl_to_prmry_ndev(wl))) {
/* we only allow to connect using virtual interface in case of P2P */
if (p2p_on(wl) && is_wps_conn(sme)) {
WL_DBG(("p2p index : %d\n", wl_cfgp2p_find_idx(wl, dev)));
WL_DBG(("ASSOC1 p2p index : %d sme->ie_len %d\n",
wl_cfgp2p_find_idx(wl, dev), sme->ie_len));
/* Have to apply WPS IE + P2P IE in assoc req frame */
wl_cfgp2p_set_management_ie(wl, dev,
wl_cfgp2p_find_idx(wl, dev), VNDR_IE_PRBREQ_FLAG,
@ -2187,6 +2190,8 @@ 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_DBG(("ASSOC2 p2p index : %d sme->ie_len %d\n",
wl_cfgp2p_find_idx(wl, dev), sme->ie_len));
wl_cfgp2p_set_management_ie(wl, dev, wl_cfgp2p_find_idx(wl, dev),
VNDR_IE_ASSOCREQ_FLAG, sme->ie, sme->ie_len);
}
@ -2902,11 +2907,8 @@ static s32 wl_cfg80211_suspend(struct wiphy *wiphy)
wl_clr_drv_status(wl, SCANNING);
wl_clr_drv_status(wl, SCAN_ABORTING);
dhd_os_spin_unlock((dhd_pub_t *)(wl->pub), flags);
if (wl_get_drv_status(wl, CONNECTING)) {
wl_bss_connect_done(wl, ndev, NULL, NULL, false);
wl_delay(500);
return -EAGAIN;
}
#endif
return 0;
@ -3286,6 +3288,9 @@ wl_cfg80211_mgmt_tx(struct wiphy *wiphy, struct net_device *dev,
if (wl->p2p->vif_created) {
wifi_p2p_pub_act_frame_t *act_frm =
(wifi_p2p_pub_act_frame_t *) (action_frame->data);
WL_DBG(("action_frame->len: %d chan %d category %d subtype %d\n",
action_frame->len, af_params->channel,
act_frm->category, act_frm->subtype));
/*
* To make sure to send successfully action frame, we have to turn off mpc
*/
@ -3687,6 +3692,8 @@ wl_cfg80211_add_set_beacon(struct wiphy *wiphy, struct net_device *dev,
} else {
WL_ERR(("No P2PIE in beacon \n"));
}
/* add WLC_E_PROBREQ_MSG event to respose probe_request from STA */
wl_dongle_add_remove_eventmsg(dev, WLC_E_PROBREQ_MSG, pbc);
wl_cfgp2p_set_management_ie(wl, dev, bssidx, VNDR_IE_BEACON_FLAG,
beacon_ie, wpsie_len + p2pie_len);
@ -4129,15 +4136,7 @@ static s32 wl_inform_single_bss(struct wl_priv *wl, struct wl_bss_info *bi)
beacon_proberesp->beacon_int = cpu_to_le16(bi->beacon_period);
beacon_proberesp->capab_info = cpu_to_le16(bi->capability);
wl_rst_ie(wl);
/*
* wl_add_ie is not necessary because it can only add duplicated
* SSID, rate information to frame_buf
*/
/*
* wl_add_ie(wl, WLAN_EID_SSID, bi->SSID_len, bi->SSID);
* wl_add_ie(wl, WLAN_EID_SUPP_RATES, bi->rateset.count,
* bi->rateset.rates);
*/
wl_mrg_ie(wl, ((u8 *) bi) + bi->ie_offset, bi->ie_length);
wl_cp_ie(wl, beacon_proberesp->variable, WL_BSS_INFO_MAX -
offsetof(struct wl_cfg80211_bss_info, frame_buf));
@ -4150,10 +4149,11 @@ static s32 wl_inform_single_bss(struct wl_priv *wl, struct wl_bss_info *bi)
#endif
channel = ieee80211_get_channel(wiphy, freq);
WL_DBG(("SSID : \"%s\", rssi %d, channel %d, capability : 0x04%x, bssid %pM\n",
bi->SSID,
notif_bss_info->rssi, notif_bss_info->channel,
mgmt->u.beacon.capab_info, &bi->BSSID));
WL_DBG(("SSID : \"%s\", rssi %d, channel %d, capability : 0x04%x, bssid %pM"
"mgmt_type %d frame_len %d\n", bi->SSID,
notif_bss_info->rssi, notif_bss_info->channel,
mgmt->u.beacon.capab_info, &bi->BSSID, mgmt_type,
notif_bss_info->frame_len));
signal = notif_bss_info->rssi * 100;
@ -5832,7 +5832,7 @@ static s32 wl_dongle_add_remove_eventmsg(struct net_device *ndev, u16 event, boo
s32 err = 0;
/* Setup event_msgs */
bcm_mkiovar("event_msgs", eventmask, WL_EVENTING_MASK_LEN, iovbuf,
bcm_mkiovar("event_msgs", NULL, 0, iovbuf,
sizeof(iovbuf));
err = wldev_ioctl(ndev, WLC_GET_VAR, iovbuf, sizeof(iovbuf), false);
if (unlikely(err)) {
@ -6619,7 +6619,64 @@ s32 wl_cfg80211_get_p2p_dev_addr(struct net_device *net, struct ether_addr *p2pd
return 0;
}
s32 wl_cfg80211_set_p2p_noa(struct net_device *net, char* buf, int len)
{
struct wl_priv *wl;
wl = wlcfg_drv_priv;
return wl_cfgp2p_set_p2p_noa(wl, net, buf, len);
}
s32 wl_cfg80211_get_p2p_noa(struct net_device *net, char* buf, int len)
{
struct wl_priv *wl;
wl = wlcfg_drv_priv;
return wl_cfgp2p_get_p2p_noa(wl, net, buf, len);
}
s32 wl_cfg80211_set_p2p_ps(struct net_device *net, char* buf, int len)
{
struct wl_priv *wl;
wl = wlcfg_drv_priv;
return wl_cfgp2p_set_p2p_ps(wl, net, buf, len);
}
s32 wl_cfg80211_set_wps_p2p_ie(struct net_device *net, char *buf, int len,
enum wl_management_type type)
{
struct wl_priv *wl;
struct net_device *ndev = NULL;
s32 ret = 0;
s32 bssidx = 0;
s32 pktflag = 0;
wl = wlcfg_drv_priv;
if (wl->p2p && wl->p2p->vif_created) {
ndev = wl_to_p2p_bss_ndev(wl, P2PAPI_BSSCFG_CONNECTION);
bssidx = wl_to_p2p_bss_bssidx(wl, P2PAPI_BSSCFG_CONNECTION);
} else if (wl_get_drv_status(wl, AP_CREATING) ||
wl_get_drv_status(wl, AP_CREATED)) {
ndev = net;
bssidx = 0;
}
if (ndev != NULL) {
switch (type) {
case WL_BEACON:
pktflag = VNDR_IE_BEACON_FLAG;
break;
case WL_PROBE_RESP:
pktflag = VNDR_IE_PRBRSP_FLAG;
break;
case WL_ASSOC_RESP:
pktflag = VNDR_IE_ASSOCRSP_FLAG;
break;
}
ret = wl_cfgp2p_set_management_ie(wl, ndev, bssidx, pktflag, buf, len);
}
return ret;
}
static __used void wl_dongle_poweron(struct wl_priv *wl)
{

View File

@ -182,6 +182,11 @@ enum wl_fw_status {
WL_NVRAM_LOADING_DONE
};
enum wl_management_type {
WL_BEACON = 0x1,
WL_PROBE_RESP = 0x2,
WL_ASSOC_RESP = 0x4
};
/* beacon / probe_response */
struct beacon_proberesp {
__le64 timestamp;
@ -538,6 +543,11 @@ extern void wl_cfg80211_release_fw(void);
extern s8 *wl_cfg80211_get_fwname(void);
extern s8 *wl_cfg80211_get_nvramname(void);
extern s32 wl_cfg80211_get_p2p_dev_addr(struct net_device *net, struct ether_addr *p2pdev_addr);
extern s32 wl_cfg80211_set_p2p_noa(struct net_device *net, char* buf, int len);
extern s32 wl_cfg80211_get_p2p_noa(struct net_device *net, char* buf, int len);
extern s32 wl_cfg80211_set_wps_p2p_ie(struct net_device *net, char *buf, int len,
enum wl_management_type type);
extern s32 wl_cfg80211_set_p2p_ps(struct net_device *net, char* buf, int len);
extern int wl_cfg80211_hang(struct net_device *dev, u16 reason);
#ifdef CONFIG_SYSCTL
extern s32 wl_cfg80211_sysctl_export_devaddr(void *data);

View File

@ -1305,6 +1305,7 @@ wl_cfgp2p_supported(struct wl_priv *wl, struct net_device *ndev)
}
return p2p_supported;
}
/* Cleanup P2P resources */
s32
wl_cfgp2p_down(struct wl_priv *wl)
@ -1313,3 +1314,139 @@ wl_cfgp2p_down(struct wl_priv *wl)
del_timer_sync(&wl->p2p->listen_timer);
return 0;
}
s32 wl_cfgp2p_set_p2p_noa(struct wl_priv *wl, struct net_device *ndev, char* buf, int len)
{
s32 ret = -1;
int count, start, duration;
wl_p2p_sched_t dongle_noa;
CFGP2P_DBG((" Enter\n"));
memset(&dongle_noa, 0, sizeof(dongle_noa));
if (wl->p2p && wl->p2p->vif_created) {
wl->p2p->noa.desc[0].start = 0;
sscanf(buf, "%d %d %d", &count, &start, &duration);
CFGP2P_DBG(("set_p2p_noa count %d start %d duration %d\n",
count, start, duration));
if (count != -1)
wl->p2p->noa.desc[0].count = count;
/* supplicant gives interval as start */
if (start != -1)
wl->p2p->noa.desc[0].interval = start * 1000;
if (duration != -1)
wl->p2p->noa.desc[0].duration = duration * 1000;
if (wl->p2p->noa.desc[0].count != 255) {
wl->p2p->noa.desc[0].start = 200 * 1000;
dongle_noa.type = WL_P2P_SCHED_TYPE_REQ_ABS;
dongle_noa.action = WL_P2P_SCHED_ACTION_GOOFF;
dongle_noa.option = WL_P2P_SCHED_OPTION_TSFOFS;
}
else {
/* Continuous NoA interval. */
dongle_noa.action = WL_P2P_SCHED_ACTION_NONE;
dongle_noa.type = WL_P2P_SCHED_TYPE_ABS;
if ((wl->p2p->noa.desc[0].interval == 102000) ||
(wl->p2p->noa.desc[0].interval == 100000)) {
wl->p2p->noa.desc[0].start = 100 -
(wl->p2p->noa.desc[0].duration / 1000);
wl->p2p->noa.desc[0].duration /= 1000;
dongle_noa.option = WL_P2P_SCHED_OPTION_BCNPCT;
}
else {
dongle_noa.option = WL_P2P_SCHED_OPTION_NORMAL;
}
}
/* Put the noa descriptor in dongle format for dongle */
dongle_noa.desc[0].count = htod32(wl->p2p->noa.desc[0].count);
dongle_noa.desc[0].start = htod32(wl->p2p->noa.desc[0].start);
dongle_noa.desc[0].interval = htod32(wl->p2p->noa.desc[0].interval);
dongle_noa.desc[0].duration = htod32(wl->p2p->noa.desc[0].duration);
ret = wldev_iovar_setbuf(wl_to_p2p_bss_ndev(wl, P2PAPI_BSSCFG_CONNECTION),
"p2p_noa", &dongle_noa, sizeof(dongle_noa), ioctlbuf, sizeof(ioctlbuf));
if (ret < 0) {
CFGP2P_ERR(("fw set p2p_noa failed %d\n", ret));
}
}
else {
CFGP2P_ERR(("ERROR: set_noa in non-p2p mode\n"));
}
return ret;
}
s32 wl_cfgp2p_get_p2p_noa(struct wl_priv *wl, struct net_device *ndev, char* buf, int len)
{
wifi_p2p_noa_desc_t* noa_desc;
CFGP2P_DBG((" Enter\n"));
if (wl->p2p && wl->p2p->vif_created) {
if (wl->p2p->noa.desc[0].count) {
#define P2P_ATTR_NOTICE_OF_ABSENCE_LEN 2
buf[0] = 0; /* noa index */
buf[1] = (wl->p2p->ops.ops ? 0x80: 0) |
(wl->p2p->ops.ctw & 0x7f); /* ops + ctw */
noa_desc = (wifi_p2p_noa_desc_t*)&buf[P2P_ATTR_NOTICE_OF_ABSENCE_LEN];
noa_desc->cnt_type = wl->p2p->noa.desc[0].count;
noa_desc->duration = wl->p2p->noa.desc[0].duration;
noa_desc->interval = wl->p2p->noa.desc[0].interval;
noa_desc->start = wl->p2p->noa.desc[0].start;
/* wl_android.c is adding 1 to ret value for all returned bufs */
return sizeof(wifi_p2p_noa_desc_t) +
P2P_ATTR_NOTICE_OF_ABSENCE_LEN - 1;
}
else {
/* NOA parameters are not set */
return 0;
}
}
else {
CFGP2P_ERR(("ERROR: set_noa in non-p2p mode\n"));
return -1;
}
}
s32 wl_cfgp2p_set_p2p_ps(struct wl_priv *wl, struct net_device *ndev, char* buf, int len)
{
int ps, ctw, legacy_ps;
int ret = -1;
CFGP2P_DBG((" Enter\n"));
if (wl->p2p && wl->p2p->vif_created) {
sscanf(buf, "%d %d %d", &legacy_ps, &ps, &ctw);
CFGP2P_DBG((" Enter ps %d ctw %d\n", ps, ctw));
if (ctw != -1) {
wl->p2p->ops.ctw = ctw;
ret = 0;
}
if (ps != -1) {
wl->p2p->ops.ops = ps;
ret = wldev_iovar_setbuf(wl_to_p2p_bss_ndev(wl, P2PAPI_BSSCFG_CONNECTION),
"p2p_ops", &wl->p2p->ops, sizeof(wl->p2p->ops),
ioctlbuf, sizeof(ioctlbuf));
if (ret < 0) {
CFGP2P_ERR(("fw set p2p_ops failed %d\n", ret));
}
}
if (legacy_ps != -1) {
s32 pm = legacy_ps ? PM_FAST : PM_OFF;
ret = wldev_ioctl(wl_to_p2p_bss_ndev(wl, P2PAPI_BSSCFG_CONNECTION),
WLC_SET_PM, &pm, sizeof(pm), true);
if (unlikely(ret)) {
CFGP2P_ERR(("error (%d)\n", ret));
}
}
}
else {
CFGP2P_ERR(("ERROR: set_noa in non-p2p mode\n"));
ret = -1;
}
return ret;
}

View File

@ -74,6 +74,8 @@ struct p2p_info {
struct ether_addr int_addr;
struct p2p_bss bss_idx[P2PAPI_BSSCFG_MAX];
struct timer_list listen_timer;
wl_p2p_sched_t noa;
wl_p2p_ops_t ops;
wlc_ssid_t ssid;
spinlock_t timer_lock;
};
@ -224,6 +226,15 @@ wl_cfgp2p_supported(struct wl_priv *wl, struct net_device *ndev);
extern s32
wl_cfgp2p_down(struct wl_priv *wl);
extern s32
wl_cfgp2p_set_p2p_noa(struct wl_priv *wl, struct net_device *ndev, char* buf, int len);
extern s32
wl_cfgp2p_get_p2p_noa(struct wl_priv *wl, struct net_device *ndev, char* buf, int len);
extern s32
wl_cfgp2p_set_p2p_ps(struct wl_priv *wl, struct net_device *ndev, char* buf, int len);
/* WiFi Direct */
#define SOCIAL_CHAN_1 1
#define SOCIAL_CHAN_2 6

View File

@ -8077,8 +8077,6 @@ wl_iw_event(struct net_device *dev, wl_event_msg_t *e, void* data)
uint32 datalen = ntoh32(e->datalen);
uint32 status = ntoh32(e->status);
uint32 toto;
static uint32 roam_no_success = 0;
static bool roam_no_success_send = FALSE;
memset(&wrqu, 0, sizeof(wrqu));
memset(extra, 0, sizeof(extra));
@ -8146,26 +8144,12 @@ wl_iw_event(struct net_device *dev, wl_event_msg_t *e, void* data)
cmd = IWEVREGISTERED;
break;
case WLC_E_ROAM:
if (status != WLC_E_STATUS_SUCCESS) {
roam_no_success++;
if ((roam_no_success == 3) && (roam_no_success_send == FALSE)) {
roam_no_success_send = TRUE;
bzero(wrqu.addr.sa_data, ETHER_ADDR_LEN);
bzero(&extra, ETHER_ADDR_LEN);
cmd = SIOCGIWAP;
WL_ERROR(("%s ROAMING did not succeeded , send Link Down\n",
__FUNCTION__));
} else {
WL_TRACE(("##### ROAMING did not succeeded %d\n", roam_no_success));
goto wl_iw_event_end;
}
} else {
memcpy(wrqu.addr.sa_data, &e->addr.octet, ETHER_ADDR_LEN);
wrqu.addr.sa_family = ARPHRD_ETHER;
cmd = SIOCGIWAP;
if (status == WLC_E_STATUS_SUCCESS) {
WL_ASSOC((" WLC_E_ROAM : success \n"));
return;
}
break;
case WLC_E_DEAUTH_IND:
case WLC_E_DISASSOC_IND:
#if defined(SOFTAP)
@ -8225,8 +8209,6 @@ wl_iw_event(struct net_device *dev, wl_event_msg_t *e, void* data)
wl_iw_send_priv_event(priv_dev, "AP_UP");
} else {
WL_TRACE(("STA_LINK_UP\n"));
roam_no_success_send = FALSE;
roam_no_success = 0;
}
#else
#endif