Update to 5.90.125.40

Add monitor interface support and fix cfg80211 management frame isses
Add support for hostapd
Use private command to get p2p device address

Change-Id: Ie490e38f1af9f259ff4a96b2f7d367119c65c377
Signed-off-by: Howard M. Harte <hharte@broadcom.com>
Signed-off-by: Dmitry Shmidt <dimitrysh@google.com>
This commit is contained in:
Lin Ma 2011-07-18 11:42:36 -07:00 committed by Dmitry Shmidt
parent b06f3b5edb
commit 2f66cb426e
9 changed files with 1488 additions and 472 deletions

View File

@ -91,6 +91,7 @@ static histo_t vi_d1, vi_d2, vi_d3, vi_d4;
#if defined(SOFTAP)
extern bool ap_cfg_running;
extern bool ap_fw_loaded;
#endif
/* enable HOSTIP cache update from the host side when an eth0:N is up */
@ -442,6 +443,12 @@ static void dhd_htsf_addrxts(dhd_pub_t *dhdp, void *pktbuf);
static void dhd_dump_htsfhisto(histo_t *his, char *s);
#endif /* WLMEDIA_HTSF */
extern s32 wl_cfg80211_ifdel_ops(struct net_device *net);
/* Monitor interface */
extern int dhd_monitor_init(void *dhd_pub);
extern int dhd_monitor_uninit(void);
#if defined(CONFIG_WIRELESS_EXT)
struct iw_statistics *dhd_get_wireless_stats(struct net_device *dev);
@ -491,6 +498,7 @@ extern int register_pm_notifier(struct notifier_block *nb);
extern int unregister_pm_notifier(struct notifier_block *nb);
#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) && defined(CONFIG_PM_SLEEP) */
/* && defined(DHD_GPL) */
static void dhd_set_packet_filter(int value, dhd_pub_t *dhd)
{
#ifdef PKT_FILTER_SUPPORT
@ -972,7 +980,7 @@ dhd_op_if(dhd_if_t *ifp)
ret = -EOPNOTSUPP;
} else {
#if defined(SOFTAP)
if (ap_cfg_running && !(dhd->dhd_state & DHD_ATTACH_STATE_CFG80211)) {
if (ap_fw_loaded && !(dhd->dhd_state & DHD_ATTACH_STATE_CFG80211)) {
/* semaphore that the soft AP CODE waits on */
flags = dhd_os_spin_lock(&dhd->pub);
@ -992,6 +1000,9 @@ dhd_op_if(dhd_if_t *ifp)
case WLC_E_IF_DEL:
if (ifp->net != NULL) {
DHD_TRACE(("\n%s: got 'WLC_E_IF_DEL' state\n", __FUNCTION__));
#ifdef WL_CFG80211
wl_cfg80211_ifdel_ops(ifp->net);
#endif
netif_stop_queue(ifp->net);
unregister_netdev(ifp->net);
ret = DHD_DEL_IF; /* Make sure the free_netdev() is called */
@ -1234,7 +1245,7 @@ dhd_sendpkt(dhd_pub_t *dhdp, int ifidx, void *pktbuf)
return ret;
}
static int
int
dhd_start_xmit(struct sk_buff *skb, struct net_device *net)
{
int ret;
@ -1462,7 +1473,6 @@ dhd_rx_frame(dhd_pub_t *dhdp, int ifidx, void *pktbuf, int numpkt, uint8 chan)
}
}
ASSERT(ifidx < DHD_MAX_IFS && dhd->iflist[ifidx]);
if (dhd->iflist[ifidx] && !dhd->iflist[ifidx]->state)
ifp = dhd->iflist[ifidx];
@ -1473,6 +1483,14 @@ dhd_rx_frame(dhd_pub_t *dhdp, int ifidx, void *pktbuf, int numpkt, uint8 chan)
dhdp->dstats.rx_bytes += skb->len;
dhdp->rx_packets++; /* Local count */
/* Dropping packets before registering net device to avoid kernel panic */
if (!ifp->net || ifp->net->reg_state != NETREG_REGISTERED) {
DHD_ERROR(("%s: net device is NOT registered yet. drop [%s] packet\n",
__FUNCTION__, (ntoh16(skb->protocol) == ETHER_TYPE_BRCM) ? "event" : "data"));
PKTFREE(dhdp->osh, pktbuf, TRUE);
continue;
}
if (in_interrupt()) {
netif_rx(skb);
} else {
@ -2363,7 +2381,6 @@ dhd_attach(osl_t *osh, struct dhd_bus *bus, uint bus_hdrlen)
dhd_attach_states_t dhd_state = DHD_ATTACH_STATE_INIT;
DHD_TRACE(("%s: Enter\n", __FUNCTION__));
/* updates firmware nvram path if it was provided as module parameters */
if ((firmware_path != NULL) && (firmware_path[0] != '\0'))
strcpy(fw_path, firmware_path);
@ -2469,6 +2486,8 @@ dhd_attach(osl_t *osh, struct dhd_bus *bus, uint bus_hdrlen)
DHD_ERROR(("wl_cfg80211_attach failed\n"));
goto fail;
}
dhd_monitor_init(&dhd->pub);
dhd_state |= DHD_ATTACH_STATE_CFG80211;
#endif
#if defined(CONFIG_WIRELESS_EXT)
@ -2563,7 +2582,6 @@ dhd_attach(osl_t *osh, struct dhd_bus *bus, uint bus_hdrlen)
dhd_free(&dhd->pub);
}
return NULL;
}
@ -2665,7 +2683,11 @@ dhd_bus_start(dhd_pub_t *dhdp)
setbit(dhdp->eventmask, WLC_E_TXFAIL);
setbit(dhdp->eventmask, WLC_E_JOIN_START);
setbit(dhdp->eventmask, WLC_E_SCAN_COMPLETE);
setbit(dhdp->eventmask, WLC_E_ACTION_FRAME_RX);
setbit(dhdp->eventmask, WLC_E_ACTION_FRAME_COMPLETE);
#if defined(WLP2P)
setbit(dhdp->eventmask, WLC_E_P2P_PROBREQ_MSG);
#endif /* WLP2P */
#ifdef PNO_SUPPORT
setbit(dhdp->eventmask, WLC_E_PFN_NET_FOUND);
#endif /* PNO_SUPPORT */
@ -2694,10 +2716,6 @@ dhd_bus_start(dhd_pub_t *dhdp)
dhd_write_macaddr(dhd->pub.mac.octet);
#endif
#if defined(CONFIG_SYSCTL) && defined(WL_CFG80211)
wl_cfg80211_sysctl_export_devaddr(&dhd->pub);
#endif
return 0;
}
@ -2724,6 +2742,7 @@ dhd_iovar(dhd_pub_t *pub, int ifidx, char *name, char *cmd_buf, uint cmd_len, in
return ret;
}
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 31))
static struct net_device_ops dhd_ops_pri = {
.ndo_open = dhd_open,
@ -2848,6 +2867,8 @@ static int dhd_device_event(struct notifier_block *this,
__FUNCTION__));
aoe_update_host_ipv4_table(dhd_pub, ifa->ifa_address, TRUE);
}
else
aoe_update_host_ipv4_table(dhd_pub, ifa->ifa_address, TRUE);
#endif
break;
@ -2923,12 +2944,18 @@ dhd_net_attach(dhd_pub_t *dhdp, int ifidx)
* We have to use the primary MAC for virtual interfaces
*/
memcpy(temp_addr, dhd->iflist[ifidx]->mac_addr, ETHER_ADDR_LEN);
if (ifidx == 1) {
DHD_TRACE(("%s ACCESS POINT MAC: \n", __FUNCTION__));
/* ACCESSPOINT INTERFACE CASE */
temp_addr[0] |= 0x02; /* set bit 2 , - Locally Administered address */
/*
* Android sets the locally administered bit to indicate that this is a
* portable hotspot. This will not work in simultaneous AP/STA mode,
* nor with P2P. Need to set the Donlge's MAC address, and then use that.
*/
if (ifidx > 0) {
DHD_ERROR(("%s interface [%s]: set locally administered bit in MAC\n",
__func__, net->name));
temp_addr[0] |= 0x02;
}
}
net->hard_header_len = ETH_HLEN + dhd->pub.hdrlen;
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 24)
net->ethtool_ops = &dhd_ethtool_ops;
@ -2951,11 +2978,11 @@ dhd_net_attach(dhd_pub_t *dhdp, int ifidx)
DHD_ERROR(("couldn't register the net device, err %d\n", err));
goto fail;
}
printf("%s: Driver up: Broadcom Dongle Host Driver mac=%.2x:%.2x:%.2x:%.2x:%.2x:%.2x\n",
printf("Broadcom Dongle Host Driver: register interface [%s]"
" MAC: %.2x:%.2x:%.2x:%.2x:%.2x:%.2x\n",
net->name,
dhd->pub.mac.octet[0], dhd->pub.mac.octet[1], dhd->pub.mac.octet[2],
dhd->pub.mac.octet[3], dhd->pub.mac.octet[4], dhd->pub.mac.octet[5]);
net->dev_addr[0], net->dev_addr[1], net->dev_addr[2],
net->dev_addr[3], net->dev_addr[4], net->dev_addr[5]);
#if defined(SOFTAP) && defined(CONFIG_WIRELESS_EXT) && !defined(WL_CFG80211)
wl_iw_iscan_set_scan_broadcast_prep(net, 1);
@ -3106,8 +3133,10 @@ void dhd_detach(dhd_pub_t *dhdp)
}
#ifdef WL_CFG80211
if (dhd->dhd_state & DHD_ATTACH_STATE_CFG80211)
if (dhd->dhd_state & DHD_ATTACH_STATE_CFG80211) {
wl_cfg80211_detach();
dhd_monitor_uninit();
}
#endif
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) && defined(CONFIG_PM_SLEEP)
@ -3120,6 +3149,7 @@ void dhd_detach(dhd_pub_t *dhdp)
wake_lock_destroy(&dhd->wl_rxwake);
#endif
}
}

View File

@ -0,0 +1,331 @@
/*
* Broadcom Dongle Host Driver (DHD), Linux monitor network interface
*
* Copyright (C) 1999-2011, Broadcom Corporation
*
* Unless you and Broadcom execute a separate written software license
* agreement governing use of this software, this software is licensed to you
* under the terms of the GNU General Public License version 2 (the "GPL"),
* available at http://www.broadcom.com/licenses/GPLv2.php, with the
* following added to such license:
*
* As a special exception, the copyright holders of this software give you
* permission to link this software with independent modules, and to copy and
* distribute the resulting executable under terms of your choice, provided that
* you also meet, for each linked independent module, the terms and conditions of
* the license of that module. An independent module is a module which is not
* derived from this software. The special exception does not apply to any
* modifications of the software.
*
* Notwithstanding the above, under no circumstances may you combine this
* 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_mon.c,v 1.131.2.55 2011-02-09 05:31:56 Exp $
*/
#include <linux/string.h>
#include <linux/module.h>
#include <linux/netdevice.h>
#include <linux/etherdevice.h>
#include <linux/if_arp.h>
#include <linux/ieee80211.h>
#include <net/ieee80211_radiotap.h>
#include <wlioctl.h>
#include <bcmutils.h>
#include <linux_osl.h>
#include <dhd_dbg.h>
#include <dngl_stats.h>
#include <dhd.h>
/*
* Some external functions, TODO: move them to dhd_linux.h
*/
int dhd_start_xmit(struct sk_buff *skb, struct net_device *net);
/**
* Local declarations and defintions (not exposed)
*/
#define MON_PRINT(format, ...) printk("DHD-MON: %s " format, __func__, ##__VA_ARGS__)
#define MON_TRACE MON_PRINT
typedef struct monitor_interface {
int radiotap_enabled;
struct net_device* real_ndev; /* The real interface that the monitor is on */
struct net_device* mon_ndev;
} monitor_interface;
typedef struct dhd_linux_monitor {
void *dhd_pub;
monitor_interface mon_if[DHD_MAX_IFS];
int count; /* Number of total monitor interface */
struct mutex lock; /* lock to protect count and mon_if */
} dhd_linux_monitor_t;
static dhd_linux_monitor_t g_monitor;
static struct net_device* lookup_real_netdev(char *name);
static monitor_interface* ndev_to_monif(struct net_device *ndev);
static int dhd_mon_if_open(struct net_device *ndev);
static int dhd_mon_if_stop(struct net_device *ndev);
static int dhd_mon_if_subif_start_xmit(struct sk_buff *skb, struct net_device *ndev);
static void dhd_mon_if_set_multicast_list(struct net_device *ndev);
static int dhd_mon_if_change_mac(struct net_device *ndev, void *addr);
static const struct net_device_ops dhd_mon_if_ops = {
.ndo_open = dhd_mon_if_open,
.ndo_stop = dhd_mon_if_stop,
.ndo_start_xmit = dhd_mon_if_subif_start_xmit,
.ndo_set_multicast_list = dhd_mon_if_set_multicast_list,
.ndo_set_mac_address = dhd_mon_if_change_mac,
};
/**
* Local static function defintions
*/
/* Look up dhd's net device table to find a match (e.g. interface "eth0" is a match for "mon.eth0"
* "p2p-eth0-0" is a match for "mon.p2p-eth0-0")
*/
static struct net_device* lookup_real_netdev(char *name)
{
int i;
int last_name_len = 0;
struct net_device *ndev;
struct net_device *ndev_found = NULL;
/* We want to find interface "p2p-eth0-0" for monitor interface "mon.p2p-eth0-0", so
* we skip "eth0" even if "mon.p2p-eth0-0" contains "eth0"
*/
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)
ndev_found = ndev;
}
}
return ndev_found;
}
static monitor_interface* ndev_to_monif(struct net_device *ndev)
{
int i;
for (i = 0; i < DHD_MAX_IFS; i++) {
if (g_monitor.mon_if[i].mon_ndev == ndev)
return &g_monitor.mon_if[i];
}
return NULL;
}
static int dhd_mon_if_open(struct net_device *ndev)
{
int ret = 0;
MON_PRINT("enter\n");
return ret;
}
static int dhd_mon_if_stop(struct net_device *ndev)
{
int ret = 0;
MON_PRINT("enter\n");
return ret;
}
static int dhd_mon_if_subif_start_xmit(struct sk_buff *skb, struct net_device *ndev)
{
int ret = 0;
int rtap_len;
int qos_len = 0;
int dot11_hdr_len = 24;
int snap_len = 6;
unsigned char *pdata;
unsigned char src_mac_addr[6];
unsigned char dst_mac_addr[6];
struct ieee80211_hdr *dot11_hdr;
struct ieee80211_radiotap_header *rtap_hdr;
monitor_interface* mon_if;
MON_PRINT("enter\n");
mon_if = ndev_to_monif(ndev);
if (mon_if == NULL || mon_if->real_ndev == NULL) {
MON_PRINT(" cannot find matched net dev, skip the packet\n");
goto fail;
}
if (unlikely(skb->len < sizeof(struct ieee80211_radiotap_header)))
goto fail;
rtap_hdr = (struct ieee80211_radiotap_header *)skb->data;
if (unlikely(rtap_hdr->it_version))
goto fail;
rtap_len = ieee80211_get_radiotap_len(skb->data);
if (unlikely(skb->len < rtap_len))
goto fail;
MON_PRINT("radiotap len (should be 14): %d\n", rtap_len);
/* Skip the ratio tap header */
skb_pull(skb, rtap_len);
dot11_hdr = (struct ieee80211_hdr *)skb->data;
/* 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;
fail:
dev_kfree_skb(skb);
return 0;
}
static void dhd_mon_if_set_multicast_list(struct net_device *ndev)
{
monitor_interface* mon_if;
mon_if = ndev_to_monif(ndev);
if (mon_if == NULL || mon_if->real_ndev == NULL) {
MON_PRINT(" cannot find matched net dev, skip the packet\n");
}
MON_PRINT("enter, if name: %s, matched if name %s\n", ndev->name, mon_if->real_ndev->name);
}
static int dhd_mon_if_change_mac(struct net_device *ndev, void *addr)
{
int ret = 0;
monitor_interface* mon_if;
mon_if = ndev_to_monif(ndev);
if (mon_if == NULL || mon_if->real_ndev == NULL) {
MON_PRINT(" cannot find matched net dev, skip the packet\n");
}
MON_PRINT("enter, if name: %s, matched if name %s\n", ndev->name, mon_if->real_ndev->name);
return ret;
}
/**
* Global function definitions (declared in dhd_linux_mon.h)
*/
int dhd_add_monitor(char *name, struct net_device **new_ndev)
{
int idx;
int ret = 0;
struct net_device* ndev = NULL;
dhd_linux_monitor_t **dhd_mon;
mutex_lock(&g_monitor.lock);
MON_TRACE("enter, if name: %s\n", name);
if (!name || !new_ndev) {
MON_PRINT("invalid parameters\n");
ret = -EINVAL;
goto out;
}
if (g_monitor.count >= DHD_MAX_IFS) {
MON_PRINT("exceeds maximum interfaces\n");
ret = -EFAULT;
goto out;
}
ndev = alloc_etherdev(sizeof(dhd_linux_monitor_t*));
if (!ndev) {
MON_PRINT("failed to allocate memory\n");
ret = -ENOMEM;
goto out;
}
ndev->type = ARPHRD_IEEE80211_RADIOTAP;
strncpy(ndev->name, name, IFNAMSIZ);
ndev->name[IFNAMSIZ - 1] = 0;
ndev->netdev_ops = &dhd_mon_if_ops;
ret = register_netdevice(ndev);
if (ret) {
MON_PRINT(" register_netdevice failed (%d)\n", ret);
goto out;
}
*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;
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);
out:
if (ret && ndev)
free_netdev(ndev);
mutex_unlock(&g_monitor.lock);
return ret;
}
int dhd_monitor_init(void *dhd_pub)
{
g_monitor.dhd_pub = dhd_pub;
mutex_init(&g_monitor.lock);
return 0;
}
int dhd_monitor_uninit(void)
{
int i;
struct net_device *ndev;
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--;
}
}
mutex_unlock(&g_monitor.lock);
return 0;
}

View File

@ -392,6 +392,11 @@ static bool dhd_readahead;
/* To check if there's window offered */
#define DATAOK(bus) \
(((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*/
#define TXCTLOK(bus) \
(((uint8)(bus->tx_max - bus->tx_seq) != 0) && \
(((uint8)(bus->tx_max - bus->tx_seq) & 0x80) == 0))
@ -1364,7 +1369,7 @@ dhd_bus_txctl(struct dhd_bus *bus, uchar *msg, uint msglen)
htol32_ua_store(swheader, frame + SDPCM_FRAMETAG_LEN);
htol32_ua_store(0, frame + SDPCM_FRAMETAG_LEN + sizeof(swheader));
if (!DATAOK(bus)) {
if (!TXCTLOK(bus)) {
DHD_INFO(("%s: No bus credit bus->tx_max %d, bus->tx_seq %d\n",
__FUNCTION__, bus->tx_max, bus->tx_seq));
bus->ctrl_frame_stat = TRUE;
@ -2602,46 +2607,44 @@ dhdsdio_doiovar(dhd_bus_t *bus, const bcm_iovar_t *vi, uint32 actionid, const ch
break;
#ifdef SOFTAP
case IOV_GVAL(IOV_FWPATH):
{
uint32 fw_path_len;
fw_path_len = strlen(bus->fw_path);
DHD_INFO(("[softap] get fwpath, l=%d\n", len));
if ( fw_path_len > len-1 ) {
bcmerror = BCME_BUFTOOSHORT;
break;
}
if ( fw_path_len )
bcopy(bus->fw_path, arg, fw_path_len);
((uchar*)arg)[fw_path_len] = 0;
}
break;
case IOV_SVAL(IOV_FWPATH):
{
DHD_INFO(("[softap] set fwpath, idx=%d\n", int_val));
switch(int_val) {
case 1:
bus->fw_path = fw_path; /* ordinary one */
break;
case 2:
bus->fw_path = fw_path2;
break;
default:
bcmerror = BCME_BADARG;
return bcmerror;
}
DHD_INFO(("[softap] new fw path: %s\n", (bus->fw_path[0]?bus->fw_path:"NULL")));
}
break;
#endif
case IOV_GVAL(IOV_FWPATH):
{
uint32 fw_path_len;
fw_path_len = strlen(bus->fw_path);
DHD_INFO(("[softap] get fwpath, l=%d\n", len));
if (fw_path_len > len-1) {
bcmerror = BCME_BUFTOOSHORT;
break;
}
if (fw_path_len) {
bcopy(bus->fw_path, arg, fw_path_len);
((uchar*)arg)[fw_path_len] = 0;
}
break;
}
case IOV_SVAL(IOV_FWPATH):
DHD_INFO(("[softap] set fwpath, idx=%d\n", int_val));
switch (int_val) {
case 1:
bus->fw_path = fw_path; /* ordinary one */
break;
case 2:
bus->fw_path = fw_path2;
break;
default:
bcmerror = BCME_BADARG;
break;
}
DHD_INFO(("[softap] new fw path: %s\n", (bus->fw_path[0] ? bus->fw_path : "NULL")));
break;
#endif /* SOFTAP */
case IOV_GVAL(IOV_DEVRESET):
DHD_TRACE(("%s: Called get IOV_DEVRESET\n", __FUNCTION__));
@ -4386,6 +4389,12 @@ dhdsdio_dpc(dhd_bus_t *bus)
DHD_TRACE(("%s: Enter\n", __FUNCTION__));
if (bus->dhd->busstate == DHD_BUS_DOWN) {
DHD_ERROR(("%s: Bus down, ret\n", __FUNCTION__));
bus->intstatus = 0;
return 0;
}
/* Start with leftover status bits */
intstatus = bus->intstatus;
@ -4544,7 +4553,7 @@ dhdsdio_dpc(dhd_bus_t *bus)
bcmsdh_intr_enable(sdh);
}
if (DATAOK(bus) && bus->ctrl_frame_stat && (bus->clkstate == CLK_AVAIL)) {
if (TXCTLOK(bus) && bus->ctrl_frame_stat && (bus->clkstate == CLK_AVAIL)) {
int ret, i;
ret = dhd_bcmsdh_send_buf(bus, bcmsdh_cur_sbwad(sdh), SDIO_FUNC_2, F2SYNC,
@ -4589,6 +4598,9 @@ dhdsdio_dpc(dhd_bus_t *bus)
framecnt = dhdsdio_sendfromq(bus, framecnt);
txlimit -= framecnt;
}
/* Resched the DPC if ctrl cmd is pending on bus credit*/
if (bus->ctrl_frame_stat)
resched = TRUE;
/* Resched if events or tx frames are pending, else await next interrupt */
/* On failed register access, all bets are off: no resched or interrupts */
@ -5176,7 +5188,7 @@ dhdsdio_probe(uint16 venid, uint16 devid, uint16 bus_no, uint16 slot,
sd1idle = TRUE;
dhd_readahead = TRUE;
retrydata = FALSE;
dhd_doflow = TRUE;
dhd_doflow = FALSE;
dhd_dongle_memsize = 0;
dhd_txminmax = DHD_TXMINMAX;
@ -5291,15 +5303,20 @@ dhdsdio_probe(uint16 venid, uint16 devid, uint16 bus_no, uint16 slot,
goto fail;
}
/* Register interrupt callback, but mask it (not operational yet). */
DHD_INTR(("%s: disable SDIO interrupts (not interested yet)\n", __FUNCTION__));
bcmsdh_intr_disable(sdh);
if ((ret = bcmsdh_intr_reg(sdh, dhdsdio_isr, bus)) != 0) {
DHD_ERROR(("%s: FAILED: bcmsdh_intr_reg returned %d\n",
__FUNCTION__, ret));
goto fail;
if (bus->intr) {
/* Register interrupt callback, but mask it (not operational yet). */
DHD_INTR(("%s: disable SDIO interrupts (not interested yet)\n", __FUNCTION__));
bcmsdh_intr_disable(sdh);
if ((ret = bcmsdh_intr_reg(sdh, dhdsdio_isr, bus)) != 0) {
DHD_ERROR(("%s: FAILED: bcmsdh_intr_reg returned %d\n",
__FUNCTION__, ret));
goto fail;
}
DHD_INTR(("%s: registered SDIO interrupt function ok\n", __FUNCTION__));
} else {
DHD_INFO(("%s: SDIO interrupt function is NOT registered due to polling mode\n",
__FUNCTION__));
}
DHD_INTR(("%s: registered SDIO interrupt function ok\n", __FUNCTION__));
DHD_INFO(("%s: completed!!\n", __FUNCTION__));

View File

@ -65,6 +65,7 @@
#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"
@ -105,6 +106,7 @@ typedef struct android_wifi_priv_cmd {
void dhd_customer_gpio_wlan_ctrl(int onoff);
uint dhd_dev_reset(struct net_device *dev, uint8 flag);
void dhd_dev_init_ioctl(struct net_device *dev);
int wl_cfg80211_get_p2p_dev_addr(struct net_device *net, struct ether_addr *p2pdev_addr);
extern bool ap_fw_loaded;
#ifdef CUSTOMER_HW2
@ -276,6 +278,18 @@ static int wl_android_set_pno_setup(struct net_device *dev, char *command, int t
}
#endif
static int wl_android_get_p2p_dev_addr(struct net_device *ndev, char *command, int total_len)
{
int ret;
int bytes_written = 0;
ret = wl_cfg80211_get_p2p_dev_addr(ndev, (struct ether_addr*)command);
if (ret)
return 0;
bytes_written = sizeof(struct ether_addr);
return bytes_written;
}
/**
* Global function definitions (declared in wl_android.h)
*/
@ -439,8 +453,8 @@ int wl_android_priv_cmd(struct net_device *net, struct ifreq *ifr, int cmd)
else if (strnicmp(command, CMD_COUNTRY, strlen(CMD_COUNTRY)) == 0) {
char *country_code = command + strlen(CMD_COUNTRY) + 1;
bytes_written = wldev_set_country(net, country_code);
#ifdef PNO_SUPPORT
}
#ifdef PNO_SUPPORT
else if (strnicmp(command, CMD_PNOSSIDCLR_SET, strlen(CMD_PNOSSIDCLR_SET)) == 0) {
bytes_written = dhd_dev_pno_reset(net);
}
@ -450,7 +464,10 @@ int wl_android_priv_cmd(struct net_device *net, struct ifreq *ifr, int cmd)
else if (strnicmp(command, CMD_PNOENABLE_SET, strlen(CMD_PNOENABLE_SET)) == 0) {
uint pfn_enabled = *(command + strlen(CMD_PNOENABLE_SET) + 1) - '0';
bytes_written = dhd_dev_pno_enable(net, pfn_enabled);
}
#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 {
DHD_ERROR(("Unknown PRIVATE command %s - ignored\n", command));
snprintf(command, 3, "OK");

File diff suppressed because it is too large Load Diff

View File

@ -114,12 +114,6 @@ do { \
*/
#define WL_FILE_NAME_MAX 256
#define WL_DWELL_TIME 200
/* WiFi Direct */
#define WL_P2P_WILDCARD_SSID "DIRECT-"
#define WL_P2P_WILDCARD_SSID_LEN 7
#define WL_P2P_INTERFACE_PREFIX "p2p"
#define WL_P2P_TEMP_CHAN "11"
#define VWDEV_CNT 3
/* dongle status */
enum wl_status {
@ -127,7 +121,9 @@ enum wl_status {
WL_STATUS_SCANNING,
WL_STATUS_SCAN_ABORTING,
WL_STATUS_CONNECTING,
WL_STATUS_CONNECTED
WL_STATUS_CONNECTED,
WL_STATUS_AP_CREATING,
WL_STATUS_AP_CREATED
};
/* wi-fi mode */
@ -315,6 +311,17 @@ struct escan_info {
struct wiphy *wiphy;
};
struct ap_info {
/* Structure to hold WPS, WPA IEs for a AP */
u8 probe_res_ie[IE_MAX_LEN];
u8 beacon_ie[IE_MAX_LEN];
u32 probe_res_ie_len;
u32 beacon_ie_len;
u8 *wpa_ie;
u8 *rsn_ie;
u8 *wps_ie;
bool security_mode;
};
/* dongle private data of cfg80211 interface */
struct wl_priv {
struct wireless_dev *wdev; /* representing wl cfg80211 device */
@ -373,12 +380,13 @@ struct wl_priv {
struct dentry *debugfsdir;
struct rfkill *rfkill;
bool rf_blocked;
struct ieee80211_channel remain_on_chan;
enum nl80211_channel_type remain_on_chan_type;
u64 cache_cookie;
wait_queue_head_t dongle_event_wait;
struct p2p_info p2p;
struct ap_info *ap_info;
struct p2p_info *p2p;
bool p2p_supported;
s8 last_eventmask[WL_EVENTING_MASK_LEN];
u8 ci[0] __attribute__ ((__aligned__(NETDEV_ALIGN)));
};
@ -398,6 +406,10 @@ struct wl_priv {
#define wl_to_iscan(w) (w->iscan)
#define wl_to_conn(w) (&w->conn_info)
#define wiphy_from_scan(w) (w->escan_info.wiphy)
#define wl_get_drv_status(wl, stat) (test_bit(WL_STATUS_ ## stat, &(wl)->status))
#define wl_set_drv_status(wl, stat) (set_bit(WL_STATUS_ ## stat, &(wl)->status))
#define wl_clr_drv_status(wl, stat) (clear_bit(WL_STATUS_ ## stat, &(wl)->status))
#define wl_chg_drv_status(wl, stat) (change_bit(WL_STATUS_ ## stat, &(wl)->status))
static inline struct wl_bss_info *next_bss(struct wl_scan_results *list, struct wl_bss_info *bss)
{
@ -488,6 +500,7 @@ extern struct sdio_func *wl_cfg80211_get_sdio_func(void); /* set sdio function i
extern s32 wl_cfg80211_up(void); /* dongle up */
extern s32 wl_cfg80211_down(void); /* dongle down */
extern s32 wl_cfg80211_notify_ifadd(struct net_device *net);
extern s32 wl_cfg80211_ifdel_ops(struct net_device *net);
extern s32 wl_cfg80211_notify_ifdel(struct net_device *net);
extern s32 wl_cfg80211_is_progress_ifadd(void);
extern s32 wl_cfg80211_is_progress_ifchange(void);
@ -499,6 +512,7 @@ extern s32 wl_cfg80211_read_fw(s8 *buf, u32 size);
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);
#ifdef CONFIG_SYSCTL
extern s32 wl_cfg80211_sysctl_export_devaddr(void *data);
#endif

View File

@ -65,14 +65,13 @@ wl_cfgp2p_vndr_ie(struct net_device *ndev, s32 bssidx, s32 pktflag,
* Initialize variables related to P2P
*
*/
void
s32
wl_cfgp2p_init_priv(struct wl_priv *wl)
{
wl->p2p.on = 0;
wl->p2p.scan = 0; /* by default , legacy scan */
wl->p2p.status = 0;
wl->p2p.listen_timer = NULL;
if (!(wl->p2p = kzalloc(sizeof(struct p2p_info), GFP_KERNEL))) {
CFGP2P_ERR(("struct p2p_info allocation failed\n"));
return -ENOMEM;
}
#define INIT_IE(IE_TYPE, BSS_TYPE) \
do { \
memset(wl_to_p2p_bss_saved_ie(wl, BSS_TYPE).p2p_ ## IE_TYPE ## _ie, 0, \
@ -103,17 +102,38 @@ wl_cfgp2p_init_priv(struct wl_priv *wl)
wl_to_p2p_bss_ndev(wl, P2PAPI_BSSCFG_CONNECTION) = NULL;
wl_to_p2p_bss_bssidx(wl, P2PAPI_BSSCFG_CONNECTION) = 0;
}
return BCME_OK;
}
/*
* Deinitialize variables related to P2P
*
*/
void
wl_cfgp2p_deinit_priv(struct wl_priv *wl)
{
if (wl->p2p) {
kfree(wl->p2p);
}
wl->p2p_supported = 0;
}
/*
* Set P2P functions into firmware
*/
s32
wl_cfgp2p_set_firm_p2p(struct wl_priv *wl)
{
struct net_device *ndev = wl_to_prmry_ndev(wl);
s32 ret = BCME_OK;
/* TODO : Do we have to check whether APSTA is enabled or not ? */
s32 val = 0;
/* Do we have to check whether APSTA is enabled or not ? */
wldev_iovar_getint(ndev, "apsta", &val);
if (val == 0) {
val = 1;
wldev_ioctl(ndev, WLC_DOWN, &val, sizeof(s32), false);
wldev_iovar_setint(ndev, "apsta", val);
wldev_ioctl(ndev, WLC_UP, &val, sizeof(s32), false);
}
return ret;
}
@ -130,7 +150,7 @@ wl_cfgp2p_ifadd(struct wl_priv *wl, struct ether_addr *mac, u8 if_type,
{
wl_p2p_if_t ifreq;
s32 err;
struct net_device *netdev = wl_to_prmry_ndev(wl);
struct net_device *ndev = wl_to_prmry_ndev(wl);
ifreq.type = if_type;
ifreq.chspec = chspec;
@ -142,7 +162,7 @@ wl_cfgp2p_ifadd(struct wl_priv *wl, struct ether_addr *mac, u8 if_type,
(if_type == WL_P2P_IF_GO) ? "go" : "client",
(chspec & WL_CHANSPEC_CHAN_MASK) >> WL_CHANSPEC_CHAN_SHIFT));
err = wldev_iovar_setbuf(netdev, "p2p_ifadd", &ifreq, sizeof(ifreq),
err = wldev_iovar_setbuf(ndev, "p2p_ifadd", &ifreq, sizeof(ifreq),
ioctlbuf, sizeof(ioctlbuf));
return err;
}
@ -571,21 +591,21 @@ wl_cfgp2p_escan(struct wl_priv *wl, struct net_device *dev, u16 active,
/* Check whether the given IE looks like WFA P2P IE. */
#define wl_cfgp2p_is_p2p_ie(ie, tlvs, len) wl_cfgp2p_has_ie(ie, tlvs, len, \
(const uint8 *)WFA_OUI, WFA_OUI_LEN, WFA_OUI_TYPE_P2P)
/* Delete and Set a management ie to firmware
/* Delete and Set a management vndr ie to firmware
* Parameters:
* @wl : wl_private data
* @ndev : net device for bssidx
* @bssidx : bssidx for BSS
* @pktflag : packet flag for IE (VNDR_IE_PRBREQ_FLAG,VNDR_IE_PRBRSP_FLAG, VNDR_IE_ASSOCRSP_FLAG,
* VNDR_IE_ASSOCREQ_FLAG)
* @ie : probe request ie (WPS IE + P2P IE)
* @ie_len : probe request ie length
* @ie : VNDR IE (such as P2P IE , WPS IE)
* @ie_len : VNDR IE Length
* Returns 0 if success.
*/
s32
wl_cfgp2p_set_managment_ie(struct wl_priv *wl, struct net_device *ndev, s32 bssidx,
s32 pktflag, const u8 *p2p_ie, u32 p2p_ie_len)
s32 pktflag, const u8 *vndr_ie, u32 vndr_ie_len)
{
/* Vendor-specific Information Element ID */
#define VNDR_SPEC_ELEMENT_ID 0xdd
@ -601,50 +621,70 @@ wl_cfgp2p_set_managment_ie(struct wl_priv *wl, struct net_device *ndev, s32 bssi
#define IE_TYPE_LEN(type, bsstype) (wl_to_p2p_bss_saved_ie(wl, bsstype).p2p_ ## type ## _ie_len)
if (bssidx == -1)
return BCME_BADARG;
if (bssidx == P2PAPI_BSSCFG_PRIMARY)
bssidx = wl_to_p2p_bss_bssidx(wl, P2PAPI_BSSCFG_DEVICE);
switch (pktflag) {
case VNDR_IE_PRBREQ_FLAG :
mgmt_ie_buf = IE_TYPE(probe_req, bssidx);
mgmt_ie_len = &IE_TYPE_LEN(probe_req, bssidx);
mgmt_ie_buf_len = sizeof(IE_TYPE(probe_req, bssidx));
break;
case VNDR_IE_PRBRSP_FLAG :
mgmt_ie_buf = IE_TYPE(probe_res, bssidx);
mgmt_ie_len = &IE_TYPE_LEN(probe_res, bssidx);
mgmt_ie_buf_len = sizeof(IE_TYPE(probe_res, bssidx));
break;
case VNDR_IE_ASSOCREQ_FLAG :
mgmt_ie_buf = IE_TYPE(assoc_req, bssidx);
mgmt_ie_len = &IE_TYPE_LEN(assoc_req, bssidx);
mgmt_ie_buf_len = sizeof(IE_TYPE(assoc_req, bssidx));
break;
case VNDR_IE_ASSOCRSP_FLAG :
mgmt_ie_buf = IE_TYPE(assoc_res, bssidx);
mgmt_ie_len = &IE_TYPE_LEN(assoc_res, bssidx);
mgmt_ie_buf_len = sizeof(IE_TYPE(assoc_res, bssidx));
break;
case VNDR_IE_BEACON_FLAG :
mgmt_ie_buf = IE_TYPE(beacon, bssidx);
mgmt_ie_len = &IE_TYPE_LEN(beacon, bssidx);
mgmt_ie_buf_len = sizeof(IE_TYPE(beacon, bssidx));
break;
default:
mgmt_ie_buf = NULL;
mgmt_ie_len = NULL;
CFGP2P_ERR(("not suitable type\n"));
return -1;
if (wl->p2p_supported && p2p_on(wl)) {
if (bssidx == P2PAPI_BSSCFG_PRIMARY)
bssidx = wl_to_p2p_bss_bssidx(wl, P2PAPI_BSSCFG_DEVICE);
switch (pktflag) {
case VNDR_IE_PRBREQ_FLAG :
mgmt_ie_buf = IE_TYPE(probe_req, bssidx);
mgmt_ie_len = &IE_TYPE_LEN(probe_req, bssidx);
mgmt_ie_buf_len = sizeof(IE_TYPE(probe_req, bssidx));
break;
case VNDR_IE_PRBRSP_FLAG :
mgmt_ie_buf = IE_TYPE(probe_res, bssidx);
mgmt_ie_len = &IE_TYPE_LEN(probe_res, bssidx);
mgmt_ie_buf_len = sizeof(IE_TYPE(probe_res, bssidx));
break;
case VNDR_IE_ASSOCREQ_FLAG :
mgmt_ie_buf = IE_TYPE(assoc_req, bssidx);
mgmt_ie_len = &IE_TYPE_LEN(assoc_req, bssidx);
mgmt_ie_buf_len = sizeof(IE_TYPE(assoc_req, bssidx));
break;
case VNDR_IE_ASSOCRSP_FLAG :
mgmt_ie_buf = IE_TYPE(assoc_res, bssidx);
mgmt_ie_len = &IE_TYPE_LEN(assoc_res, bssidx);
mgmt_ie_buf_len = sizeof(IE_TYPE(assoc_res, bssidx));
break;
case VNDR_IE_BEACON_FLAG :
mgmt_ie_buf = IE_TYPE(beacon, bssidx);
mgmt_ie_len = &IE_TYPE_LEN(beacon, bssidx);
mgmt_ie_buf_len = sizeof(IE_TYPE(beacon, bssidx));
break;
default:
mgmt_ie_buf = NULL;
mgmt_ie_len = NULL;
CFGP2P_ERR(("not suitable type\n"));
return -1;
}
} else {
switch (pktflag) {
case VNDR_IE_PRBRSP_FLAG :
mgmt_ie_buf = wl->ap_info->probe_res_ie;
mgmt_ie_len = &wl->ap_info->probe_res_ie_len;
mgmt_ie_buf_len = sizeof(wl->ap_info->probe_res_ie);
break;
case VNDR_IE_BEACON_FLAG :
mgmt_ie_buf = wl->ap_info->beacon_ie;
mgmt_ie_len = &wl->ap_info->beacon_ie_len;
mgmt_ie_buf_len = sizeof(wl->ap_info->beacon_ie);
break;
default:
mgmt_ie_buf = NULL;
mgmt_ie_len = NULL;
CFGP2P_ERR(("not suitable type\n"));
return -1;
}
}
/* Add if there is any extra IE */
if (p2p_ie && p2p_ie_len) {
CFGP2P_INFO(("Request has extra IE"));
if (p2p_ie_len > mgmt_ie_buf_len) {
if (vndr_ie && vndr_ie_len) {
CFGP2P_ERR(("Request has extra IE"));
if (vndr_ie_len > mgmt_ie_buf_len) {
CFGP2P_ERR(("extra IE size too big\n"));
ret = -ENOMEM;
} else {
if (mgmt_ie_buf != NULL) {
if ((p2p_ie_len == *mgmt_ie_len) &&
(memcmp(mgmt_ie_buf, p2p_ie, p2p_ie_len) == 0)) {
if ((vndr_ie_len == *mgmt_ie_len) &&
(memcmp(mgmt_ie_buf, vndr_ie, vndr_ie_len) == 0)) {
CFGP2P_INFO(("Previous mgmt IE is equals to current IE"));
goto exit;
}
@ -666,12 +706,12 @@ wl_cfgp2p_set_managment_ie(struct wl_priv *wl, struct net_device *ndev, s32 bssi
}
/* save the current IE in wl struct */
memcpy(mgmt_ie_buf, p2p_ie, p2p_ie_len);
*mgmt_ie_len = p2p_ie_len;
memcpy(mgmt_ie_buf, vndr_ie, vndr_ie_len);
*mgmt_ie_len = vndr_ie_len;
pos = 0;
ie_buf = (u8 *) p2p_ie;
ie_buf = (u8 *) vndr_ie;
delete = 0;
while (pos < p2p_ie_len) {
while (pos < vndr_ie_len) {
ie_id = ie_buf[pos++];
ie_len = ie_buf[pos++];
if ((ie_id == DOT11_MNG_VS_ID) &&
@ -719,8 +759,6 @@ wl_cfgp2p_clear_management_ie(struct wl_priv *wl, s32 bssidx)
INIT_IE(assoc_req, bssidx);
INIT_IE(assoc_res, bssidx);
INIT_IE(beacon, bssidx);
return BCME_OK;
}
@ -749,6 +787,7 @@ wl_cfgp2p_has_ie(u8 *ie, u8 **tlvs, u32 *tlvs_len, const u8 *oui, u32 oui_len, u
return FALSE;
}
wpa_ie_fixed_t *
wl_cfgp2p_find_wpaie(u8 *parse, u32 len)
{
@ -855,12 +894,17 @@ wl_cfgp2p_find_idx(struct wl_priv *wl, struct net_device *ndev)
CFGP2P_ERR((" ndev is NULL\n"));
goto exit;
}
if (!wl->p2p_supported) {
return P2PAPI_BSSCFG_PRIMARY;
}
for (i = 0; i < P2PAPI_BSSCFG_MAX; i++) {
if (ndev == wl_to_p2p_bss_ndev(wl, i)) {
index = wl_to_p2p_bss_bssidx(wl, i);
break;
}
}
if (index == -1)
return P2PAPI_BSSCFG_PRIMARY;
exit:
return index;
}
@ -874,12 +918,11 @@ wl_cfgp2p_listen_complete(struct wl_priv *wl, struct net_device *ndev,
s32 ret = BCME_OK;
CFGP2P_DBG((" Enter\n"));
/* TODO : have to acquire bottom half lock ? */
if (wl_get_p2p_status(wl, LISTEN_EXPIRED) == 0) {
wl_set_p2p_status(wl, LISTEN_EXPIRED);
if (wl->p2p.listen_timer)
del_timer_sync(wl->p2p.listen_timer);
if (wl->p2p->listen_timer)
del_timer_sync(wl->p2p->listen_timer);
cfg80211_remain_on_channel_expired(ndev, wl->cache_cookie, &wl->remain_on_chan,
wl->remain_on_chan_type, GFP_KERNEL);
@ -944,12 +987,12 @@ wl_cfgp2p_discover_listen(struct wl_priv *wl, s32 channel, u32 duration_ms)
wl_cfgp2p_set_p2p_mode(wl, WL_P2P_DISC_ST_LISTEN, channel, (u16) duration_ms,
wl_to_p2p_bss_bssidx(wl, P2PAPI_BSSCFG_DEVICE));
if (wl->p2p.listen_timer)
del_timer_sync(wl->p2p.listen_timer);
if (wl->p2p->listen_timer)
del_timer_sync(wl->p2p->listen_timer);
wl->p2p.listen_timer = kmalloc(sizeof(struct timer_list), GFP_KERNEL);
wl->p2p->listen_timer = kmalloc(sizeof(struct timer_list), GFP_KERNEL);
if (wl->p2p.listen_timer == NULL) {
if (wl->p2p->listen_timer == NULL) {
CFGP2P_ERR(("listen_timer allocation failed\n"));
return -ENOMEM;
}
@ -957,7 +1000,7 @@ wl_cfgp2p_discover_listen(struct wl_priv *wl, s32 channel, u32 duration_ms)
/* We will wait to receive WLC_E_P2P_DISC_LISTEN_COMPLETE from dongle ,
* otherwise we will wait up to duration_ms + 10ms
*/
INIT_TIMER(wl->p2p.listen_timer, wl_cfgp2p_listen_expired, duration_ms, 20);
INIT_TIMER(wl->p2p->listen_timer, wl_cfgp2p_listen_expired, duration_ms, 20);
#undef INIT_TIMER
exit:
@ -986,7 +1029,7 @@ wl_cfgp2p_discover_enable_search(struct wl_priv *wl, u8 enable)
*/
if (!enable) {
wl_clr_p2p_status(wl, SCANNING);
(void) wl_cfgp2p_set_p2p_mode(wl, WL_P2P_DISC_ST_SCAN, 0, 0,
ret = wl_cfgp2p_set_p2p_mode(wl, WL_P2P_DISC_ST_SCAN, 0, 0,
wl_to_p2p_bss_bssidx(wl, P2PAPI_BSSCFG_DEVICE));
}
@ -1214,16 +1257,19 @@ wl_cfgp2p_supported(struct wl_priv *wl, struct net_device *ndev)
CFGP2P_ERR(("wl p2p error %d\n", ret));
return 0;
}
if (p2p_supported)
if (p2p_supported == 1) {
CFGP2P_INFO(("p2p is supported\n"));
} else {
CFGP2P_INFO(("p2p is unsupported\n"));
p2p_supported = 0;
}
return p2p_supported;
}
/* Cleanup P2P resources */
s32
wl_cfgp2p_down(struct wl_priv *wl)
{
if (wl->p2p.listen_timer)
del_timer_sync(wl->p2p.listen_timer);
if (wl->p2p->listen_timer)
del_timer_sync(wl->p2p->listen_timer);
return 0;
}

View File

@ -91,16 +91,20 @@ enum wl_cfgp2p_status {
};
#define wl_to_p2p_bss_ndev(w, type) ((wl)->p2p.bss_idx[type].dev)
#define wl_to_p2p_bss_bssidx(w, type) ((wl)->p2p.bss_idx[type].bssidx)
#define wl_to_p2p_bss_saved_ie(w, type) ((wl)->p2p.bss_idx[type].saved_ie)
#define wl_to_p2p_bss(wl, type) ((wl)->p2p.bss_idx[type])
#define wl_get_p2p_status(wl, stat) (test_bit(WLP2P_STATUS_ ## stat, &(wl)->p2p.status))
#define wl_set_p2p_status(wl, stat) (set_bit(WLP2P_STATUS_ ## stat, &(wl)->p2p.status))
#define wl_clr_p2p_status(wl, stat) (clear_bit(WLP2P_STATUS_ ## stat, &(wl)->p2p.status))
#define wl_chg_p2p_status(wl, stat) (change_bit(WLP2P_STATUS_ ## stat, &(wl)->p2p.status))
#define p2p_on(wl) ((wl)->p2p.on)
#define p2p_scan(wl) ((wl)->p2p.scan)
#define wl_to_p2p_bss_ndev(w, type) ((wl)->p2p->bss_idx[type].dev)
#define wl_to_p2p_bss_bssidx(w, type) ((wl)->p2p->bss_idx[type].bssidx)
#define wl_to_p2p_bss_saved_ie(w, type) ((wl)->p2p->bss_idx[type].saved_ie)
#define wl_to_p2p_bss(wl, type) ((wl)->p2p->bss_idx[type])
#define wl_get_p2p_status(wl, stat) ((!(wl)->p2p_supported) ? 0 : test_bit(WLP2P_STATUS_ ## stat, \
&(wl)->p2p->status))
#define wl_set_p2p_status(wl, stat) ((!(wl)->p2p_supported) ? : set_bit(WLP2P_STATUS_ ## stat, \
&(wl)->p2p->status))
#define wl_clr_p2p_status(wl, stat) ((!(wl)->p2p_supported) ? : clear_bit(WLP2P_STATUS_ ## stat, \
&(wl)->p2p->status))
#define wl_chg_p2p_status(wl, stat) ((!(wl)->p2p_supported) ? : change_bit(WLP2P_STATUS_ ## stat, \
&(wl)->p2p->status))
#define p2p_on(wl) ((wl)->p2p->on)
#define p2p_scan(wl) ((wl)->p2p->scan)
/* dword align allocation */
@ -131,8 +135,10 @@ enum wl_cfgp2p_status {
} while (0)
extern void
extern s32
wl_cfgp2p_init_priv(struct wl_priv *wl);
extern void
wl_cfgp2p_deinit_priv(struct wl_priv *wl);
extern s32
wl_cfgp2p_set_firm_p2p(struct wl_priv *wl);
extern s32
@ -171,7 +177,7 @@ 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,
s32 pktflag, const u8 *p2p_ie, u32 p2p_ie_len);
s32 pktflag, const u8 *vndr_ie, u32 vndr_ie_len);
extern s32
wl_cfgp2p_clear_management_ie(struct wl_priv *wl, s32 bssidx);
@ -220,5 +226,7 @@ wl_cfgp2p_down(struct wl_priv *wl);
#define SOCIAL_CHAN_3 11
#define WL_P2P_WILDCARD_SSID "DIRECT-"
#define WL_P2P_WILDCARD_SSID_LEN 7
#define WL_P2P_INTERFACE_PREFIX "p2p"
#define WL_P2P_TEMP_CHAN "11"
#define IS_P2P_SSID(ssid) (memcmp(ssid, WL_P2P_WILDCARD_SSID, WL_P2P_WILDCARD_SSID_LEN) == 0)
#endif /* _wl_cfgp2p_h_ */

View File

@ -1889,6 +1889,12 @@ iwpriv_set_ap_config(struct net_device *dev,
info->cmd, info->flags,
wrqu->data.pointer, wrqu->data.length));
if (!ap_fw_loaded) {
WL_ERROR(("Can't execute %s(), SOFTAP fw is not Loaded\n",
__FUNCTION__));
return -1;
}
if (wrqu->data.length != 0) {
char *str_ptr;
@ -1955,13 +1961,14 @@ static int iwpriv_get_assoc_list(struct net_device *dev,
iw = *(wl_iw_t **)netdev_priv(dev);
MUTEX_LOCK_SOFTAP_SET(iw->pub);
DHD_OS_WAKE_LOCK(iw->pub);
net_os_wake_lock(dev);
DHD_OS_MUTEX_LOCK(&wl_softap_lock);
WL_TRACE(("\n %s: IWPRIV IOCTL: cmd:%hx, flags:%hx, extra:%p, iwp.len:%d,"
"iwp.len:%p, iwp.flags:%x \n", __FUNCTION__, info->cmd, info->flags,
extra, p_iwrq->data.length, p_iwrq->data.pointer, p_iwrq->data.flags));
memset(sta_maclist, 0, sizeof(mac_buf));
sta_maclist->count = 8;
@ -2028,8 +2035,9 @@ static int iwpriv_get_assoc_list(struct net_device *dev,
}
func_exit:
DHD_OS_WAKE_UNLOCK(iw->pub);
MUTEX_UNLOCK_SOFTAP_SET(iw->pub);
DHD_OS_MUTEX_UNLOCK(&wl_softap_lock);
net_os_wake_unlock(dev);
WL_SOFTAP(("%s: Exited\n", __FUNCTION__));
return ret;
@ -4320,6 +4328,10 @@ wl_iw_iscan_get_scan(
WL_TRACE(("%s return to WE %d bytes APs=%d\n", __FUNCTION__, dwrq->length, counter));
if (!dwrq->length)
return -EAGAIN;
return 0;
}
#endif
@ -6266,7 +6278,7 @@ thr_wait_for_2nd_eth_dev(void *data)
}
DHD_OS_WAKE_LOCK(iw->pub);
complete(&tsk_ctl->completed);
if (down_timeout(&tsk_ctl->sema, msecs_to_jiffies(5000)) != 0) {
if (down_timeout(&tsk_ctl->sema, msecs_to_jiffies(1000)) != 0) {
#else
if (down_interruptible(&tsk_ctl->sema) != 0) {
#endif
@ -6289,7 +6301,7 @@ thr_wait_for_2nd_eth_dev(void *data)
goto fail;
}
WL_TRACE(("\n>%s: Thread:'softap ethdev IF:%s is detected !!!'\n\n",
WL_SOFTAP(("\n>%s: Thread:'softap ethdev IF:%s is detected!'\n\n",
__FUNCTION__, ap_net_dev->name));
ap_cfg_running = TRUE;
@ -6304,7 +6316,7 @@ thr_wait_for_2nd_eth_dev(void *data)
DHD_OS_WAKE_UNLOCK(iw->pub);
WL_TRACE(("\n>%s, thread completed\n", __FUNCTION__));
WL_SOFTAP(("\n>%s, thread completed\n", __FUNCTION__));
complete_and_exit(&tsk_ctl->completed, 0);
return ret;