net: wireless: bcmdhd: Update to Version 5.90.195.23

- WFD fixes

Signed-off-by: Dmitry Shmidt <dimitrysh@google.com>
This commit is contained in:
Dmitry Shmidt 2012-01-24 13:59:40 -08:00
parent 96034c2006
commit ff93146589
8 changed files with 367 additions and 358 deletions

View File

@ -34,13 +34,6 @@ extern struct wl_priv *wlcfg_drv_priv;
static int dhd_dongle_up = FALSE;
static s32 wl_dongle_up(struct net_device *ndev, u32 up);
static s32 wl_dongle_power(struct net_device *ndev, u32 power_mode);
static s32 wl_dongle_glom(struct net_device *ndev, u32 glom, u32 dongle_align);
static s32 wl_dongle_roam(struct net_device *ndev, u32 roamvar, u32 bcn_timeout);
static s32 wl_dongle_scantime(struct net_device *ndev, s32 scan_assoc_time, s32 scan_unassoc_time);
static s32 wl_dongle_offload(struct net_device *ndev, s32 arpoe, s32 arp_ol);
static s32 wl_pattern_atoh(s8 *src, s8 *dst);
static s32 wl_dongle_filter(struct net_device *ndev, u32 filter_mode);
/**
* Function implementations
@ -74,250 +67,6 @@ static s32 wl_dongle_up(struct net_device *ndev, u32 up)
}
return err;
}
static s32 wl_dongle_power(struct net_device *ndev, u32 power_mode)
{
s32 err = 0;
WL_TRACE(("In\n"));
err = wldev_ioctl(ndev, WLC_SET_PM, &power_mode, sizeof(power_mode), true);
if (unlikely(err)) {
WL_ERR(("WLC_SET_PM error (%d)\n", err));
}
return err;
}
static s32
wl_dongle_glom(struct net_device *ndev, u32 glom, u32 dongle_align)
{
s8 iovbuf[WL_EVENTING_MASK_LEN + 12];
s32 err = 0;
/* Match Host and Dongle rx alignment */
bcm_mkiovar("bus:txglomalign", (char *)&dongle_align, 4, iovbuf,
sizeof(iovbuf));
err = wldev_ioctl(ndev, WLC_SET_VAR, iovbuf, sizeof(iovbuf), true);
if (unlikely(err)) {
WL_ERR(("txglomalign error (%d)\n", err));
goto dongle_glom_out;
}
/* disable glom option per default */
bcm_mkiovar("bus:txglom", (char *)&glom, 4, iovbuf, sizeof(iovbuf));
err = wldev_ioctl(ndev, WLC_SET_VAR, iovbuf, sizeof(iovbuf), true);
if (unlikely(err)) {
WL_ERR(("txglom error (%d)\n", err));
goto dongle_glom_out;
}
dongle_glom_out:
return err;
}
static s32
wl_dongle_roam(struct net_device *ndev, u32 roamvar, u32 bcn_timeout)
{
s8 iovbuf[WL_EVENTING_MASK_LEN + 12];
s32 err = 0;
/* Setup timeout if Beacons are lost and roam is off to report link down */
if (roamvar) {
bcm_mkiovar("bcn_timeout", (char *)&bcn_timeout, 4, iovbuf,
sizeof(iovbuf));
err = wldev_ioctl(ndev, WLC_SET_VAR, iovbuf, sizeof(iovbuf), true);
if (unlikely(err)) {
WL_ERR(("bcn_timeout error (%d)\n", err));
goto dongle_rom_out;
}
}
/* Enable/Disable built-in roaming to allow supplicant to take care of roaming */
bcm_mkiovar("roam_off", (char *)&roamvar, 4, iovbuf, sizeof(iovbuf));
err = wldev_ioctl(ndev, WLC_SET_VAR, iovbuf, sizeof(iovbuf), true);
if (unlikely(err)) {
WL_ERR(("roam_off error (%d)\n", err));
goto dongle_rom_out;
}
dongle_rom_out:
return err;
}
static s32
wl_dongle_scantime(struct net_device *ndev, s32 scan_assoc_time,
s32 scan_unassoc_time)
{
s32 err = 0;
err = wldev_ioctl(ndev, WLC_SET_SCAN_CHANNEL_TIME, &scan_assoc_time,
sizeof(scan_assoc_time), true);
if (err) {
if (err == -EOPNOTSUPP) {
WL_INFO(("Scan assoc time is not supported\n"));
} else {
WL_ERR(("Scan assoc time error (%d)\n", err));
}
goto dongle_scantime_out;
}
err = wldev_ioctl(ndev, WLC_SET_SCAN_UNASSOC_TIME, &scan_unassoc_time,
sizeof(scan_unassoc_time), true);
if (err) {
if (err == -EOPNOTSUPP) {
WL_INFO(("Scan unassoc time is not supported\n"));
} else {
WL_ERR(("Scan unassoc time error (%d)\n", err));
}
goto dongle_scantime_out;
}
dongle_scantime_out:
return err;
}
static s32
wl_dongle_offload(struct net_device *ndev, s32 arpoe, s32 arp_ol)
{
/* Room for "event_msgs" + '\0' + bitvec */
s8 iovbuf[WL_EVENTING_MASK_LEN + 12];
s32 err = 0;
/* Set ARP offload */
bcm_mkiovar("arpoe", (char *)&arpoe, 4, iovbuf, sizeof(iovbuf));
err = wldev_ioctl(ndev, WLC_SET_VAR, iovbuf, sizeof(iovbuf), true);
if (err) {
if (err == -EOPNOTSUPP)
WL_INFO(("arpoe is not supported\n"));
else
WL_ERR(("arpoe error (%d)\n", err));
goto dongle_offload_out;
}
bcm_mkiovar("arp_ol", (char *)&arp_ol, 4, iovbuf, sizeof(iovbuf));
err = wldev_ioctl(ndev, WLC_SET_VAR, iovbuf, sizeof(iovbuf), true);
if (err) {
if (err == -EOPNOTSUPP)
WL_INFO(("arp_ol is not supported\n"));
else
WL_ERR(("arp_ol error (%d)\n", err));
goto dongle_offload_out;
}
dongle_offload_out:
return err;
}
static s32 wl_pattern_atoh(s8 *src, s8 *dst)
{
int i;
if (strncmp(src, "0x", 2) != 0 && strncmp(src, "0X", 2) != 0) {
WL_ERR(("Mask invalid format. Needs to start with 0x\n"));
return -1;
}
src = src + 2; /* Skip past 0x */
if (strlen(src) % 2 != 0) {
WL_ERR(("Mask invalid format. Needs to be of even length\n"));
return -1;
}
for (i = 0; *src != '\0'; i++) {
char num[3];
strncpy(num, src, 2);
num[2] = '\0';
dst[i] = (u8) simple_strtoul(num, NULL, 16);
src += 2;
}
return i;
}
static s32 wl_dongle_filter(struct net_device *ndev, u32 filter_mode)
{
/* Room for "event_msgs" + '\0' + bitvec */
s8 iovbuf[WL_EVENTING_MASK_LEN + 12];
const s8 *str;
struct wl_pkt_filter pkt_filter;
struct wl_pkt_filter *pkt_filterp;
s32 buf_len;
s32 str_len;
u32 mask_size;
u32 pattern_size;
s8 buf[256];
s32 err = 0;
/* add a default packet filter pattern */
str = "pkt_filter_add";
str_len = strlen(str);
strncpy(buf, str, str_len);
buf[str_len] = '\0';
buf_len = str_len + 1;
pkt_filterp = (struct wl_pkt_filter *)(buf + str_len + 1);
/* Parse packet filter id. */
pkt_filter.id = htod32(100);
/* Parse filter polarity. */
pkt_filter.negate_match = htod32(0);
/* Parse filter type. */
pkt_filter.type = htod32(0);
/* Parse pattern filter offset. */
pkt_filter.u.pattern.offset = htod32(0);
/* Parse pattern filter mask. */
mask_size = htod32(wl_pattern_atoh("0xff",
(char *)pkt_filterp->u.pattern.
mask_and_pattern));
/* Parse pattern filter pattern. */
pattern_size = htod32(wl_pattern_atoh("0x00",
(char *)&pkt_filterp->u.pattern.mask_and_pattern[mask_size]));
if (mask_size != pattern_size) {
WL_ERR(("Mask and pattern not the same size\n"));
err = -EINVAL;
goto dongle_filter_out;
}
pkt_filter.u.pattern.size_bytes = mask_size;
buf_len += WL_PKT_FILTER_FIXED_LEN;
buf_len += (WL_PKT_FILTER_PATTERN_FIXED_LEN + 2 * mask_size);
/* Keep-alive attributes are set in local
* variable (keep_alive_pkt), and
* then memcpy'ed into buffer (keep_alive_pktp) since there is no
* guarantee that the buffer is properly aligned.
*/
memcpy((char *)pkt_filterp, &pkt_filter,
WL_PKT_FILTER_FIXED_LEN + WL_PKT_FILTER_PATTERN_FIXED_LEN);
err = wldev_ioctl(ndev, WLC_SET_VAR, buf, buf_len, true);
if (err) {
if (err == -EOPNOTSUPP) {
WL_INFO(("filter not supported\n"));
} else {
WL_ERR(("filter (%d)\n", err));
}
goto dongle_filter_out;
}
/* set mode to allow pattern */
bcm_mkiovar("pkt_filter_mode", (char *)&filter_mode, 4, iovbuf,
sizeof(iovbuf));
err = wldev_ioctl(ndev, WLC_SET_VAR, iovbuf, sizeof(iovbuf), true);
if (err) {
if (err == -EOPNOTSUPP) {
WL_INFO(("filter_mode not supported\n"));
} else {
WL_ERR(("filter_mode (%d)\n", err));
}
goto dongle_filter_out;
}
dongle_filter_out:
return err;
}
s32 dhd_config_dongle(struct wl_priv *wl, bool need_lock)
{
#ifndef DHD_SDALIGN
@ -342,24 +91,6 @@ s32 dhd_config_dongle(struct wl_priv *wl, bool need_lock)
WL_ERR(("wl_dongle_up failed\n"));
goto default_conf_out;
}
err = wl_dongle_power(ndev, PM_FAST);
if (unlikely(err)) {
WL_ERR(("wl_dongle_power failed\n"));
goto default_conf_out;
}
err = wl_dongle_glom(ndev, 0, DHD_SDALIGN);
if (unlikely(err)) {
WL_ERR(("wl_dongle_glom failed\n"));
goto default_conf_out;
}
err = wl_dongle_roam(ndev, (wl->roam_on ? 0 : 1), 3);
if (unlikely(err)) {
WL_ERR(("wl_dongle_roam failed\n"));
goto default_conf_out;
}
wl_dongle_scantime(ndev, 40, 80);
wl_dongle_offload(ndev, 1, 0xf);
wl_dongle_filter(ndev, 1);
dhd_dongle_up = true;
default_conf_out:

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 307603 2012-01-12 01:32:01Z $
* $Id: dhd_linux.c 308879 2012-01-17 22:03:47Z $
*/
#include <typedefs.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_sdio.c 308574 2012-01-16 22:56:40Z $
* $Id: dhd_sdio.c 309234 2012-01-19 01:44:16Z $
*/
#include <typedefs.h>
@ -5195,6 +5195,12 @@ dhdsdio_chipmatch(uint16 chipid)
return TRUE;
if (chipid == BCM43239_CHIP_ID)
return TRUE;
if (chipid == BCM4336_CHIP_ID)
return TRUE;
if (chipid == BCM43237_CHIP_ID)
return TRUE;
if (chipid == BCM43362_CHIP_ID)
return TRUE;
return FALSE;
}

View File

@ -33,17 +33,17 @@
#define EPI_RC_NUMBER 195
#define EPI_INCREMENTAL_NUMBER 22
#define EPI_INCREMENTAL_NUMBER 23
#define EPI_BUILD_NUMBER 0
#define EPI_VERSION 5, 90, 195, 22
#define EPI_VERSION 5, 90, 195, 23
#define EPI_VERSION_NUM 0x055ac316
#define EPI_VERSION_NUM 0x055ac317
#define EPI_VERSION_DEV 5.90.195
#define EPI_VERSION_STR "5.90.195.22"
#define EPI_VERSION_STR "5.90.195.23"
#endif

View File

@ -1897,6 +1897,11 @@ si_is_sprom_available(si_t *sih)
return (sih->chipst & CST4315_SPROM_SEL) != 0;
case BCM4319_CHIP_ID:
return (sih->chipst & CST4319_SPROM_SEL) != 0;
case BCM4336_CHIP_ID:
case BCM43362_CHIP_ID:
return (sih->chipst & CST4336_SPROM_PRESENT) != 0;
case BCM4330_CHIP_ID:
return (sih->chipst & CST4330_SPROM_PRESENT) != 0;
case BCM4313_CHIP_ID:

View File

@ -820,12 +820,14 @@ wl_cfg80211_add_virtual_iface(struct wiphy *wiphy, char *name,
p2p_on(wl) = true;
wl_cfgp2p_set_firm_p2p(wl);
wl_cfgp2p_init_discovery(wl);
get_primary_mac(wl, &primary_mac);
wl_cfgp2p_generate_bss_mac(&primary_mac,
&wl->p2p->dev_addr, &wl->p2p->int_addr);
}
memset(wl->p2p->vir_ifname, 0, IFNAMSIZ);
strncpy(wl->p2p->vir_ifname, name, IFNAMSIZ - 1);
get_primary_mac(wl, &primary_mac);
wl_cfgp2p_generate_bss_mac(&primary_mac, &wl->p2p->dev_addr, &wl->p2p->int_addr);
/* In concurrency case, STA may be already associated in a particular channel.
* so retrieve the current channel of primary interface and then start the virtual
@ -1318,6 +1320,25 @@ static s32 wl_do_iscan(struct wl_priv *wl, struct cfg80211_scan_request *request
return err;
}
static s32
wl_get_valid_channels(struct net_device *ndev, u8 *valid_chan_list, s32 size)
{
wl_uint32_list_t *list;
s32 err = BCME_OK;
if (valid_chan_list == NULL || size <= 0)
return -ENOMEM;
memset(valid_chan_list, 0, size);
list = (wl_uint32_list_t *)(void *) valid_chan_list;
list->count = htod32(WL_NUMCHANNELS);
err = wldev_ioctl(ndev, WLC_GET_VALID_CHANNELS, valid_chan_list, size, false);
if (err != 0) {
WL_ERR(("get channels failed with %d\n", err));
}
return err;
}
static s32
wl_run_escan(struct wl_priv *wl, struct net_device *ndev,
struct cfg80211_scan_request *request, uint16 action)
@ -1326,12 +1347,16 @@ wl_run_escan(struct wl_priv *wl, struct net_device *ndev,
u32 n_channels;
u32 n_ssids;
s32 params_size = (WL_SCAN_PARAMS_FIXED_SIZE + OFFSETOF(wl_escan_params_t, params));
wl_escan_params_t *params;
wl_escan_params_t *params = NULL;
struct cfg80211_scan_request *scan_request = wl->scan_request;
u8 chan_buf[sizeof(u32)*(WL_NUMCHANNELS + 1)];
u32 num_chans = 0;
s32 channel;
s32 n_valid_chan;
s32 search_state = WL_P2P_DISC_ST_SCAN;
u32 i;
u32 i, j, n_nodfs = 0;
u16 *default_chan_list = NULL;
wl_uint32_list_t *list;
struct net_device *dev = NULL;
WL_DBG(("Enter \n"));
@ -1378,6 +1403,8 @@ wl_run_escan(struct wl_priv *wl, struct net_device *ndev,
}
else if (p2p_is_on(wl) && p2p_scan(wl)) {
/* P2P SCAN TRIGGER */
s32 _freq = 0;
n_nodfs = 0;
if (scan_request && scan_request->n_channels) {
num_chans = scan_request->n_channels;
WL_SCAN((" chann number : %d\n", num_chans));
@ -1388,11 +1415,26 @@ wl_run_escan(struct wl_priv *wl, struct net_device *ndev,
err = -ENOMEM;
goto exit;
}
for (i = 0; i < num_chans; i++)
{
default_chan_list[i] =
ieee80211_frequency_to_channel(
scan_request->channels[i]->center_freq);
if (!wl_get_valid_channels(ndev, chan_buf, sizeof(chan_buf))) {
list = (wl_uint32_list_t *) chan_buf;
n_valid_chan = dtoh32(list->count);
for (i = 0; i < num_chans; i++)
{
_freq = scan_request->channels[i]->center_freq;
channel = ieee80211_frequency_to_channel(_freq);
/* remove DFS channels */
if (channel < 52 || channel > 140) {
for (j = 0; j < n_valid_chan; j++) {
/* allows only supported channel on
* current reguatory
*/
if (channel == (dtoh32(list->element[j])))
default_chan_list[n_nodfs++] =
channel;
}
}
}
}
if (num_chans == 3 && (
(default_chan_list[0] == SOCIAL_CHAN_1) &&
@ -1406,8 +1448,11 @@ wl_run_escan(struct wl_priv *wl, struct net_device *ndev,
/* If you are already a GO, then do SEARCH only */
WL_INFO(("Already a GO. Do SEARCH Only"));
search_state = WL_P2P_DISC_ST_SEARCH;
num_chans = n_nodfs;
} else {
WL_INFO(("P2P SCAN STATE START \n"));
num_chans = n_nodfs;
}
}
@ -1459,6 +1504,7 @@ __wl_cfg80211_scan(struct wiphy *wiphy, struct net_device *ndev,
struct wl_priv *wl = wiphy_priv(wiphy);
struct cfg80211_ssid *ssids;
struct wl_scan_req *sr = wl_to_sr(wl);
struct ether_addr primary_mac;
wpa_ie_fixed_t *wps_ie;
s32 passive_scan;
bool iscan_req;
@ -1513,6 +1559,9 @@ __wl_cfg80211_scan(struct wiphy *wiphy, struct net_device *ndev,
/* p2p on at the first time */
p2p_on(wl) = true;
wl_cfgp2p_set_firm_p2p(wl);
get_primary_mac(wl, &primary_mac);
wl_cfgp2p_generate_bss_mac(&primary_mac,
&wl->p2p->dev_addr, &wl->p2p->int_addr);
}
p2p_scan(wl) = true;
}
@ -2655,9 +2704,9 @@ wl_cfg80211_del_key(struct wiphy *wiphy, struct net_device *dev,
CHECK_SYS_UP(wl);
memset(&key, 0, sizeof(key));
key.index = (u32) key_idx;
key.flags = WL_PRIMARY_KEY;
key.algo = CRYPTO_ALGO_OFF;
key.index = (u32) key_idx;
WL_DBG(("key index (%d)\n", key_idx));
/* Set the new key/index */
@ -3312,7 +3361,6 @@ wl_cfg80211_mgmt_tx(struct wiphy *wiphy, struct net_device *ndev,
bool channel_type_valid, unsigned int wait,
const u8* buf, size_t len, u64 *cookie)
{
struct ether_addr primary_mac;
wl_action_frame_t *action_frame;
wl_af_params_t *af_params;
wifi_p2p_ie_t *p2p_ie;
@ -3328,7 +3376,9 @@ wl_cfg80211_mgmt_tx(struct wiphy *wiphy, struct net_device *ndev,
u32 id;
u32 retry = 0;
bool ack = false;
wifi_p2p_pub_act_frame_t *act_frm;
wifi_p2p_pub_act_frame_t *act_frm = NULL;
wifi_p2p_action_frame_t *p2p_act_frm = NULL;
wifi_p2psd_gas_pub_act_frame_t *sd_act_frm = NULL;
s8 eabuf[ETHER_ADDR_STR_LEN];
WL_DBG(("Enter \n"));
@ -3348,8 +3398,6 @@ wl_cfg80211_mgmt_tx(struct wiphy *wiphy, struct net_device *ndev,
return -ENODEV;
}
if (p2p_is_on(wl)) {
get_primary_mac(wl, &primary_mac);
wl_cfgp2p_generate_bss_mac(&primary_mac, &wl->p2p->dev_addr, &wl->p2p->int_addr);
/* Suspend P2P discovery search-listen to prevent it from changing the
* channel.
*/
@ -3400,11 +3448,12 @@ wl_cfg80211_mgmt_tx(struct wiphy *wiphy, struct net_device *ndev,
goto exit;
} else if (ieee80211_is_action(mgmt->frame_control)) {
/* Abort the dwell time of any previous off-channel action frame that may
* be still in effect. Sending off-channel action frames relies on the
* driver's scan engine. If a previous off-channel action frame tx is
* still in progress (including the dwell time), then this new action
* frame will not be sent out.
/* Abort the dwell time of any previous off-channel
* action frame that may be still in effect. Sending
* off-channel action frames relies on the driver's
* scan engine. If a previous off-channel action frame
* tx is still in progress (including the dwell time),
* then this new action frame will not be sent out.
*/
wl_cfg80211_scan_abort(wl, dev);
@ -3455,50 +3504,80 @@ wl_cfg80211_mgmt_tx(struct wiphy *wiphy, struct net_device *ndev,
af_params->dwell_time = WL_DWELL_TIME;
memcpy(action_frame->data, &buf[DOT11_MGMT_HDR_LEN], action_frame->len);
if (wl_cfgp2p_is_pub_action(action_frame->data, action_frame->len)) {
act_frm = (wifi_p2p_pub_act_frame_t *) (action_frame->data);
WL_DBG(("P2P PUB action_frame->len: %d chan %d category %d subtype %d\n",
action_frame->len, af_params->channel,
act_frm->category, act_frm->subtype));
} else if (wl_cfgp2p_is_p2p_action(action_frame->data, action_frame->len)) {
p2p_act_frm = (wifi_p2p_action_frame_t *) (action_frame->data);
WL_DBG(("P2P action_frame->len: %d chan %d category %d subtype %d\n",
action_frame->len, af_params->channel,
p2p_act_frm->category, p2p_act_frm->subtype));
} else if (wl_cfgp2p_is_gas_action(action_frame->data, action_frame->len)) {
sd_act_frm = (wifi_p2psd_gas_pub_act_frame_t *) (action_frame->data);
WL_DBG(("Service Discovery action_frame->len: %d chan %d category %d action %d\n",
action_frame->len, af_params->channel,
sd_act_frm->category, sd_act_frm->action));
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
*/
if ((IS_PUB_ACT_FRAME(act_frm->category)) &&
((act_frm->subtype == P2P_PAF_GON_REQ) ||
}
wl_cfgp2p_print_actframe(true, action_frame->data, action_frame->len);
/*
* To make sure to send successfully action frame, we have to turn off mpc
*/
if (act_frm && ((act_frm->subtype == P2P_PAF_GON_REQ) ||
(act_frm->subtype == P2P_PAF_GON_RSP) ||
(act_frm->subtype == P2P_PAF_GON_CONF) ||
(act_frm->subtype == P2P_PAF_PROVDIS_REQ))) {
wldev_iovar_setint(dev, "mpc", 0);
}
if (IS_PUB_ACT_FRAME(act_frm->category)) {
if (act_frm->subtype == P2P_PAF_DEVDIS_REQ) {
af_params->dwell_time = WL_LONG_DWELL_TIME;
} else if ((act_frm->subtype == P2P_PAF_PROVDIS_REQ) ||
(act_frm->subtype == P2P_PAF_PROVDIS_RSP)) {
af_params->dwell_time = WL_MED_DWELL_TIME;
}
if (act_frm && act_frm->subtype == P2P_PAF_DEVDIS_REQ) {
af_params->dwell_time = WL_LONG_DWELL_TIME;
} else if (act_frm &&
(act_frm->subtype == P2P_PAF_PROVDIS_REQ ||
act_frm->subtype == P2P_PAF_PROVDIS_RSP ||
act_frm->subtype == P2P_PAF_GON_RSP)) {
af_params->dwell_time = WL_MED_DWELL_TIME;
}
if (IS_P2P_SOCIAL(af_params->channel) &&
(IS_P2P_ACT_REQ(act_frm->category, act_frm->subtype) ||
IS_GAS_REQ(act_frm->category, act_frm->action)) &&
(IS_P2P_PUB_ACT_REQ(act_frm, action_frame->len) ||
IS_GAS_REQ(sd_act_frm, action_frame->len)) &&
wl_to_p2p_bss_saved_ie(wl, P2PAPI_BSSCFG_DEVICE).p2p_probe_req_ie_len) {
/* channel offload require P2P IE for Probe request
* otherwise, we will use wl_cfgp2p_tx_action_frame directly.
* channel offload for action request frame
*/
*/
/* channel offload for action request frame */
ack = wl_cfg80211_send_at_common_channel(wl, dev, af_params);
} else {
for (retry = 0; retry < WL_CHANNEL_SYNC_RETRY; retry++) {
ack = (wl_cfgp2p_tx_action_frame(wl, dev, af_params, bssidx)) ?
false : true;
if (ack)
break;
ack = (wl_cfgp2p_tx_action_frame(wl, dev, af_params, bssidx)) ? false : true;
if (!ack) {
if (wl_to_p2p_bss_saved_ie(wl, P2PAPI_BSSCFG_DEVICE).p2p_probe_req_ie_len) {
/* if the NO ACK occurs, the peer device will be on
* listen channel of the peer
* So, we have to find the peer and send action frame on
* that channel.
*/
ack = wl_cfg80211_send_at_common_channel(wl, dev, af_params);
} else {
for (retry = 0; retry < WL_CHANNEL_SYNC_RETRY; retry++) {
ack = (wl_cfgp2p_tx_action_frame(wl, dev,
af_params, bssidx)) ? false : true;
if (ack)
break;
}
}
}
}
cfg80211_mgmt_tx_status(ndev, *cookie, buf, len, ack, GFP_KERNEL);
if (IS_PUB_ACT_FRAME(act_frm->category) &&
(act_frm->subtype == P2P_PAF_GON_CONF)) {
if (act_frm && act_frm->subtype == P2P_PAF_GON_CONF) {
wldev_iovar_setint(dev, "mpc", 1);
}
kfree(af_params);
@ -4235,7 +4314,7 @@ static s32 wl_setup_wiphy(struct wireless_dev *wdev, struct device *sdiofunc_dev
#endif
WIPHY_FLAG_4ADDR_STATION;
#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 2, 0)
wdev->wiphy->flags |= WIPHY_FLAG_SUPPORTS_FW_ROAM;
wdev->wiphy->flags |= WIPHY_FLAG_SUPPORTS_FW_ROAM;
#endif
WL_DBG(("Registering custom regulatory)\n"));
wdev->wiphy->flags |= WIPHY_FLAG_CUSTOM_REGULATORY;
@ -4355,7 +4434,8 @@ static s32 wl_inform_single_bss(struct wl_priv *wl, struct wl_bss_info *bi)
signal = notif_bss_info->rssi * 100;
#if defined(WLP2P) && ENABLE_P2P_INTERFACE
if (wl->p2p_net && wl->scan_request && wl->scan_request->dev == wl->p2p_net) {
if (wl->p2p_net && wl->scan_request &&
wl->scan_request->dev == wl->p2p_net) {
#else
if (p2p_is_on(wl) && p2p_scan(wl)) {
#endif
@ -5054,7 +5134,9 @@ wl_notify_rx_mgmt_frame(struct wl_priv *wl, struct net_device *ndev,
s32 err = 0;
s32 freq;
struct net_device *dev = NULL;
wifi_p2p_pub_act_frame_t *act_frm;
wifi_p2p_pub_act_frame_t *act_frm = NULL;
wifi_p2p_action_frame_t *p2p_act_frm = NULL;
wifi_p2psd_gas_pub_act_frame_t *sd_act_frm = NULL;
wl_event_rx_frame_data_t *rxframe =
(wl_event_rx_frame_data_t*)data;
u32 event = ntoh32(e->event_type);
@ -5096,23 +5178,30 @@ wl_notify_rx_mgmt_frame(struct wl_priv *wl, struct net_device *ndev,
goto exit;
}
isfree = true;
act_frm =
(wifi_p2p_pub_act_frame_t *) (&mgmt_frame[DOT11_MGMT_HDR_LEN]);
if (wl_cfgp2p_is_pub_action(&mgmt_frame[DOT11_MGMT_HDR_LEN],
mgmt_frame_len - DOT11_MGMT_HDR_LEN)) {
act_frm = (wifi_p2p_pub_act_frame_t *)
(&mgmt_frame[DOT11_MGMT_HDR_LEN]);
} else if (wl_cfgp2p_is_p2p_action(&mgmt_frame[DOT11_MGMT_HDR_LEN],
mgmt_frame_len - DOT11_MGMT_HDR_LEN)) {
p2p_act_frm = (wifi_p2p_action_frame_t *)
(&mgmt_frame[DOT11_MGMT_HDR_LEN]);
(void) p2p_act_frm;
} else if (wl_cfgp2p_is_gas_action(&mgmt_frame[DOT11_MGMT_HDR_LEN],
mgmt_frame_len - DOT11_MGMT_HDR_LEN)) {
sd_act_frm = (wifi_p2psd_gas_pub_act_frame_t *)
(&mgmt_frame[DOT11_MGMT_HDR_LEN]);
(void) sd_act_frm;
}
wl_cfgp2p_print_actframe(false, &mgmt_frame[DOT11_MGMT_HDR_LEN],
mgmt_frame_len - DOT11_MGMT_HDR_LEN);
/*
* After complete GO Negotiation, roll back to mpc mode
*/
if (IS_PUB_ACT_FRAME(act_frm->category) &&
((act_frm->subtype == P2P_PAF_GON_CONF)||
(act_frm->subtype == P2P_PAF_PROVDIS_RSP))) {
if (act_frm && ((act_frm->subtype == P2P_PAF_GON_CONF) ||
(act_frm->subtype == P2P_PAF_PROVDIS_RSP))) {
wldev_iovar_setint(dev, "mpc", 1);
}
if (IS_P2P_ACT_FRAME(act_frm->category) &&
(act_frm->subtype == P2P_AF_PRESENCE_REQ)) {
/* TODO Do not submit these frames to supplicant,
* we will handle it in the driver
*/
}
} else {
mgmt_frame = (u8 *)((wl_event_rx_frame_data_t *)rxframe + 1);
}
@ -6592,13 +6681,19 @@ static void wl_delay(u32 ms)
s32 wl_cfg80211_get_p2p_dev_addr(struct net_device *net, struct ether_addr *p2pdev_addr)
{
struct wl_priv *wl;
struct wl_priv *wl = wlcfg_drv_priv;
struct ether_addr p2pif_addr;
struct ether_addr primary_mac;
wl = wlcfg_drv_priv;
get_primary_mac(wl, &primary_mac);
wl_cfgp2p_generate_bss_mac(&primary_mac, p2pdev_addr, &p2pif_addr);
if (!wl->p2p)
return -1;
if (!p2p_is_on(wl)) {
get_primary_mac(wl, &primary_mac);
wl_cfgp2p_generate_bss_mac(&primary_mac, p2pdev_addr, &p2pif_addr);
} else {
memcpy(p2pdev_addr->octet,
wl->p2p->dev_addr.octet, ETHER_ADDR_LEN);
}
return 0;
}

View File

@ -67,6 +67,170 @@ static const struct net_device_ops wl_cfgp2p_if_ops = {
.ndo_start_xmit = wl_cfgp2p_start_xmit,
};
bool wl_cfgp2p_is_pub_action(void *frame, u32 frame_len)
{
wifi_p2p_pub_act_frame_t *pact_frm;
if (frame == NULL)
return false;
pact_frm = (wifi_p2p_pub_act_frame_t *)frame;
if (frame_len < sizeof(wifi_p2p_pub_act_frame_t) -1)
return false;
if (pact_frm->category == P2P_PUB_AF_CATEGORY &&
pact_frm->action == P2P_PUB_AF_ACTION &&
pact_frm->oui_type == P2P_VER &&
memcmp(pact_frm->oui, P2P_OUI, sizeof(pact_frm->oui)) == 0) {
return true;
}
return false;
}
bool wl_cfgp2p_is_p2p_action(void *frame, u32 frame_len)
{
wifi_p2p_action_frame_t *act_frm;
if (frame == NULL)
return false;
act_frm = (wifi_p2p_action_frame_t *)frame;
if (frame_len < sizeof(wifi_p2p_action_frame_t) -1)
return false;
if (act_frm->category == P2P_AF_CATEGORY &&
act_frm->type == P2P_VER &&
memcmp(act_frm->OUI, P2P_OUI, DOT11_OUI_LEN) == 0) {
return true;
}
return false;
}
bool wl_cfgp2p_is_gas_action(void *frame, u32 frame_len)
{
wifi_p2psd_gas_pub_act_frame_t *sd_act_frm;
if (frame == NULL)
return false;
sd_act_frm = (wifi_p2psd_gas_pub_act_frame_t *)frame;
if (frame_len < sizeof(wifi_p2psd_gas_pub_act_frame_t) - 1)
return false;
if (sd_act_frm->category != P2PSD_ACTION_CATEGORY)
return false;
if (sd_act_frm->action == P2PSD_ACTION_ID_GAS_IREQ ||
sd_act_frm->action == P2PSD_ACTION_ID_GAS_IRESP ||
sd_act_frm->action == P2PSD_ACTION_ID_GAS_CREQ ||
sd_act_frm->action == P2PSD_ACTION_ID_GAS_CRESP)
return true;
else
return false;
}
void wl_cfgp2p_print_actframe(bool tx, void *frame, u32 frame_len)
{
wifi_p2p_pub_act_frame_t *pact_frm;
wifi_p2p_action_frame_t *act_frm;
wifi_p2psd_gas_pub_act_frame_t *sd_act_frm;
if (!frame || frame_len <= 2)
return;
if (wl_cfgp2p_is_pub_action(frame, frame_len)) {
pact_frm = (wifi_p2p_pub_act_frame_t *)frame;
switch (pact_frm->subtype) {
case P2P_PAF_GON_REQ:
CFGP2P_DBG(("%s P2P Group Owner Negotiation Req Frame\n",
(tx)? "TX": "RX"));
break;
case P2P_PAF_GON_RSP:
CFGP2P_DBG(("%s P2P Group Owner Negotiation Rsp Frame\n",
(tx)? "TX": "RX"));
break;
case P2P_PAF_GON_CONF:
CFGP2P_DBG(("%s P2P Group Owner Negotiation Confirm Frame\n",
(tx)? "TX": "RX"));
break;
case P2P_PAF_INVITE_REQ:
CFGP2P_DBG(("%s P2P Invitation Request Frame\n",
(tx)? "TX": "RX"));
break;
case P2P_PAF_INVITE_RSP:
CFGP2P_DBG(("%s P2P Invitation Response Frame\n",
(tx)? "TX": "RX"));
break;
case P2P_PAF_DEVDIS_REQ:
CFGP2P_DBG(("%s P2P Device Discoverability Request Frame\n",
(tx)? "TX": "RX"));
break;
case P2P_PAF_DEVDIS_RSP:
CFGP2P_DBG(("%s P2P Device Discoverability Response Frame\n",
(tx)? "TX": "RX"));
break;
case P2P_PAF_PROVDIS_REQ:
CFGP2P_DBG(("%s P2P Provision Discovery Request Frame\n",
(tx)? "TX": "RX"));
break;
case P2P_PAF_PROVDIS_RSP:
CFGP2P_DBG(("%s P2P Provision Discovery Response Frame\n",
(tx)? "TX": "RX"));
break;
default:
CFGP2P_DBG(("%s Unknown P2P Public Action Frame\n",
(tx)? "TX": "RX"));
}
} else if (wl_cfgp2p_is_p2p_action(frame, frame_len)) {
act_frm = (wifi_p2p_action_frame_t *)frame;
switch (act_frm->subtype) {
case P2P_AF_NOTICE_OF_ABSENCE:
CFGP2P_DBG(("%s P2P Notice of Absence Frame\n",
(tx)? "TX": "RX"));
break;
case P2P_AF_PRESENCE_REQ:
CFGP2P_DBG(("%s P2P Presence Request Frame\n",
(tx)? "TX": "RX"));
break;
case P2P_AF_PRESENCE_RSP:
CFGP2P_DBG(("%s P2P Presence Response Frame\n",
(tx)? "TX": "RX"));
break;
case P2P_AF_GO_DISC_REQ:
CFGP2P_DBG(("%s P2P Discoverability Request Frame\n",
(tx)? "TX": "RX"));
break;
default:
CFGP2P_DBG(("%s Unknown P2P Action Frame\n",
(tx)? "TX": "RX"));
}
} else if (wl_cfgp2p_is_gas_action(frame, frame_len)) {
sd_act_frm = (wifi_p2psd_gas_pub_act_frame_t *)frame;
switch (sd_act_frm->action) {
case P2PSD_ACTION_ID_GAS_IREQ:
CFGP2P_DBG(("%s P2P GAS Initial Request\n",
(tx)? "TX" : "RX"));
break;
case P2PSD_ACTION_ID_GAS_IRESP:
CFGP2P_DBG(("%s P2P GAS Initial Response\n",
(tx)? "TX" : "RX"));
break;
case P2PSD_ACTION_ID_GAS_CREQ:
CFGP2P_DBG(("%s P2P GAS Comback Request\n",
(tx)? "TX" : "RX"));
break;
case P2PSD_ACTION_ID_GAS_CRESP:
CFGP2P_DBG(("%s P2P GAS Comback Response\n",
(tx)? "TX" : "RX"));
break;
default:
CFGP2P_DBG(("%s Unknown P2P GAS Frame\n",
(tx)? "TX" : "RX"));
}
}
}
/*
* Initialize variables related to P2P
*
@ -1373,7 +1537,8 @@ wl_cfgp2p_down(struct wl_priv *wl)
return 0;
}
s32 wl_cfgp2p_set_p2p_noa(struct wl_priv *wl, struct net_device *ndev, char* buf, int len)
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;
@ -1446,7 +1611,8 @@ s32 wl_cfgp2p_set_p2p_noa(struct wl_priv *wl, struct net_device *ndev, char* buf
return ret;
}
s32 wl_cfgp2p_get_p2p_noa(struct wl_priv *wl, struct net_device *ndev, char* buf, int buf_len)
s32
wl_cfgp2p_get_p2p_noa(struct wl_priv *wl, struct net_device *ndev, char* buf, int buf_len)
{
wifi_p2p_noa_desc_t *noa_desc;
int len = 0, i;
@ -1488,7 +1654,8 @@ s32 wl_cfgp2p_get_p2p_noa(struct wl_priv *wl, struct net_device *ndev, char* buf
return len * 2;
}
s32 wl_cfgp2p_set_p2p_ps(struct wl_priv *wl, struct net_device *ndev, char* buf, int len)
s32
wl_cfgp2p_set_p2p_ps(struct wl_priv *wl, struct net_device *ndev, char* buf, int len)
{
int ps, ctw;
int ret = -1;
@ -1552,7 +1719,7 @@ wl_cfgp2p_retreive_p2pattrib(void *buf, u8 element_id)
len -= 4; /* exclude OUI + OUI_TYPE */
while (len >= 3) {
/* attribute id */
/* attribute id */
subelt_id = *subel;
subel += 1;
len -= 1;

View File

@ -101,13 +101,13 @@ enum wl_cfgp2p_status {
#define wl_to_p2p_bss_saved_ie(w, type) ((wl)->p2p->bss_idx[type].saved_ie)
#define wl_to_p2p_bss_private(w, type) ((wl)->p2p->bss_idx[type].private_data)
#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, \
#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) ? 0 : set_bit(WLP2P_STATUS_ ## stat, \
#define wl_set_p2p_status(wl, stat) ((!(wl)->p2p_supported) ? 0:set_bit(WLP2P_STATUS_ ## stat, \
&(wl)->p2p->status))
#define wl_clr_p2p_status(wl, stat) ((!(wl)->p2p_supported) ? 0 : clear_bit(WLP2P_STATUS_ ## stat, \
#define wl_clr_p2p_status(wl, stat) ((!(wl)->p2p_supported) ? 0:clear_bit(WLP2P_STATUS_ ## stat, \
&(wl)->p2p->status))
#define wl_chg_p2p_status(wl, stat) ((!(wl)->p2p_supported) ? 0: change_bit(WLP2P_STATUS_ ## stat, \
#define wl_chg_p2p_status(wl, stat) ((!(wl)->p2p_supported) ? 0:change_bit(WLP2P_STATUS_ ## stat, \
&(wl)->p2p->status))
#define p2p_on(wl) ((wl)->p2p->on)
#define p2p_scan(wl) ((wl)->p2p->scan)
@ -140,7 +140,14 @@ enum wl_cfgp2p_status {
} \
} while (0)
extern bool
wl_cfgp2p_is_pub_action(void *frame, u32 frame_len);
extern bool
wl_cfgp2p_is_p2p_action(void *frame, u32 frame_len);
extern bool
wl_cfgp2p_is_gas_action(void *frame, u32 frame_len);
extern void
wl_cfgp2p_print_actframe(bool tx, void *frame, u32 frame_len);
extern s32
wl_cfgp2p_init_priv(struct wl_priv *wl);
extern void
@ -260,17 +267,15 @@ wl_cfgp2p_unregister_ndev(struct wl_priv *wl);
#define WL_P2P_WILDCARD_SSID_LEN 7
#define WL_P2P_INTERFACE_PREFIX "p2p"
#define WL_P2P_TEMP_CHAN "11"
#define IS_PUB_ACT_FRAME(category) ((category == P2P_PUB_AF_CATEGORY))
#define IS_P2P_ACT_FRAME(category) ((category == P2P_AF_CATEGORY))
#define IS_P2P_ACTION(categry, action) (IS_PUB_ACT_FRAME(category) && (action == P2P_PUB_AF_ACTION))
#define IS_GAS_REQ(category, action) (IS_PUB_ACT_FRAME(category) && \
((action == P2PSD_ACTION_ID_GAS_IREQ) || \
(action == P2PSD_ACTION_ID_GAS_CREQ)))
#define IS_P2P_ACT_REQ(category, subtype) (IS_PUB_ACT_FRAME(category) && \
((subtype == P2P_PAF_GON_REQ) || \
(subtype == P2P_PAF_INVITE_REQ) || \
(subtype == P2P_PAF_PROVDIS_REQ)))
#define IS_GAS_REQ(frame, len) (wl_cfgp2p_is_gas_action(frame, len) && \
((frame->action == P2PSD_ACTION_ID_GAS_IREQ) || \
(frame->action == P2PSD_ACTION_ID_GAS_CREQ)))
#define IS_P2P_PUB_ACT_REQ(frame, len) (wl_cfgp2p_is_pub_action(frame, len) && \
((frame->subtype == P2P_PAF_GON_REQ) || \
(frame->subtype == P2P_PAF_INVITE_REQ) || \
(frame->subtype == P2P_PAF_PROVDIS_REQ)))
#define IS_P2P_SOCIAL(ch) ((ch == SOCIAL_CHAN_1) || (ch == SOCIAL_CHAN_2) || (ch == SOCIAL_CHAN_3))
#define IS_P2P_SSID(ssid) (memcmp(ssid, WL_P2P_WILDCARD_SSID, WL_P2P_WILDCARD_SSID_LEN) == 0)
#endif /* _wl_cfgp2p_h_ */