OSDN Git Service

net: wireless: bcmdhd: Combined P2P fixes
authorDmitry Shmidt <dimitrysh@google.com>
Wed, 13 Jun 2012 18:22:56 +0000 (11:22 -0700)
committerDmitry Shmidt <dimitrysh@google.com>
Wed, 13 Jun 2012 18:29:39 +0000 (11:29 -0700)
- Fix p2p scan
- Fix p2p processing for channels 12 and 13
- Fix service discovery

Signed-off-by: Dmitry Shmidt <dimitrysh@google.com>
drivers/net/wireless/bcmdhd/wl_cfg80211.c
drivers/net/wireless/bcmdhd/wl_cfgp2p.c

index bee7d55..cccc4d1 100644 (file)
@@ -84,17 +84,15 @@ u32 wl_dbg_level = WL_DBG_ERR;
  * All the chnages in world regulatory domain are to be done here.
  */
 static const struct ieee80211_regdomain brcm_regdom = {
-       .n_reg_rules = 5,
+       .n_reg_rules = 4,
        .alpha2 =  "99",
        .reg_rules = {
                /* IEEE 802.11b/g, channels 1..11 */
-               REG_RULE(2412-10, 2462+10, 40, 6, 20, 0),
+               REG_RULE(2412-10, 2472+10, 40, 6, 20, 0),
                /* IEEE 802.11b/g, channels 12..13. No HT40
                 * channel fits here.
                 */
-               REG_RULE(2467-10, 2472+10, 20, 6, 20,
-               NL80211_RRF_PASSIVE_SCAN |
-               NL80211_RRF_NO_IBSS),
+               /* If any */
                /*
                 * IEEE 802.11 channel 14 - is for JP only,
                 * we need cfg80211 to allow it (reg_flags = 0); so that
@@ -2343,8 +2341,9 @@ wl_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev,
                         */
                        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_PRBREQ_FLAG, sme->ie, sme->ie_len);
+                       wl_cfgp2p_set_management_ie(wl, dev,
+                               wl_cfgp2p_find_idx(wl, dev), VNDR_IE_PRBREQ_FLAG,
+                               sme->ie, 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);
                }
@@ -3455,8 +3454,8 @@ wl_cfg80211_send_at_common_channel(struct wl_priv *wl,
        if (wl->afx_hdl->peer_chan != WL_INVALID)
                wl_cfg80211_send_pending_tx_act_frm(wl);
        else {
-               WL_ERR(("Couldn't find the peer after %d retries\n",
-                       wl->afx_hdl->retry));
+               WL_ERR(("Couldn't find the peer " MACSTR " after %d retries\n",
+                       MAC2STR(wl->afx_hdl->pending_tx_dst_addr.octet), wl->afx_hdl->retry));
        }
        wl->afx_hdl->dev = NULL;
        wl->afx_hdl->bssidx = WL_INVALID;
@@ -3674,7 +3673,8 @@ wl_cfg80211_mgmt_tx(struct wiphy *wiphy, struct net_device *ndev,
                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));
-
+               af_params->dwell_time = WL_MED_DWELL_TIME;
+               retry_cnt = WL_ACT_FRAME_RETRY;
        }
        wl_cfgp2p_print_actframe(true, action_frame->data, action_frame->len);
        /*
@@ -3691,6 +3691,18 @@ wl_cfg80211_mgmt_tx(struct wiphy *wiphy, struct net_device *ndev,
 
                /* channel offload for action request frame */
                ack = wl_cfg80211_send_at_common_channel(wl, dev, af_params);
+               /* We need to retry Service discovery frames as they don't get retried immediately by supplicant*/
+               if ((!ack) && (IS_GAS_REQ(sd_act_frm, action_frame->len))) {
+                       for (retry = 1; retry < retry_cnt; retry++) {
+                               WL_DBG(("Service Discovery action_frame retry %d len: %d chan %d category %d action %d\n",
+                                       retry, action_frame->len, af_params->channel,
+                                       sd_act_frm->category, sd_act_frm->action));
+                               ack = (wl_cfgp2p_tx_action_frame(wl, dev,
+                                       af_params, bssidx)) ? false : true;
+                               if (ack)
+                                       break;
+                       }
+               }
        } else {
                ack = (wl_cfgp2p_tx_action_frame(wl, dev, af_params, bssidx)) ? false : true;
                if (!ack) {
@@ -6315,7 +6327,7 @@ static s32 wl_escan_handler(struct wl_priv *wl,
        wl_scan_results_t *list;
        u32 bi_length;
        u32 i;
-
+       u8 *p2p_dev_addr = NULL;
        WL_DBG((" enter event type : %d, status : %d \n",
                ntoh32(e->event_type), ntoh32(e->status)));
        /* P2P SCAN is coming from primary interface */
@@ -6363,10 +6375,12 @@ static s32 wl_escan_handler(struct wl_priv *wl,
                }
 
                if (wl_get_drv_status_all(wl, SENDING_ACT_FRM)) {
-                       if (!memcmp(bi->BSSID.octet,
+                       p2p_dev_addr = wl_cfgp2p_retreive_p2p_dev_addr(bi, bi_length);
+                       if (p2p_dev_addr && !memcmp(p2p_dev_addr,
                                wl->afx_hdl->pending_tx_dst_addr.octet, ETHER_ADDR_LEN)) {
                                s32 channel = CHSPEC_CHANNEL(dtohchanspec(bi->chanspec));
-                               WL_DBG(("ACTION FRAME SCAN : Peer found, channel : %d\n", channel));
+                               WL_DBG(("ACTION FRAME SCAN : Peer " MACSTR " found, channel : %d\n",
+                                       MAC2STR(wl->afx_hdl->pending_tx_dst_addr.octet), channel));
                                wl_clr_p2p_status(wl, SCANNING);
                                wl->afx_hdl->peer_chan = channel;
                                complete(&wl->act_frm_scan);
@@ -7155,29 +7169,33 @@ s32 wl_update_wiphybands(struct wl_priv *wl)
                }
        }
 
+       err = wl_construct_reginfo(wl, bw_cap);
+       if (err) {
+               WL_ERR(("wl_construct_reginfo() fails err=%d\n", err));
+               return err;
+       }
        for (i = 1; i <= nband && i < sizeof(bandlist)/sizeof(u32); i++) {
                index = -1;
-               if (bandlist[i] == WLC_BAND_5G) {
+               if (bandlist[i] == WLC_BAND_5G && __wl_band_5ghz_a.n_channels > 0) {
                        wiphy->bands[IEEE80211_BAND_5GHZ] =
                                &__wl_band_5ghz_a;
-                               index = IEEE80211_BAND_5GHZ;
-               } else if (bandlist[i] == WLC_BAND_2G) {
+                       index = IEEE80211_BAND_5GHZ;
+                       if (bw_cap == WLC_N_BW_40ALL || bw_cap == WLC_N_BW_20IN2G_40IN5G)
+                               wiphy->bands[index]->ht_cap.cap |= IEEE80211_HT_CAP_SGI_40;
+               } else if (bandlist[i] == WLC_BAND_2G && __wl_band_2ghz.n_channels > 0) {
                        wiphy->bands[IEEE80211_BAND_2GHZ] =
                                &__wl_band_2ghz;
-                               index = IEEE80211_BAND_2GHZ;
+                       index = IEEE80211_BAND_2GHZ;
+                       if (bandlist[i] == WLC_BAND_2G && bw_cap == WLC_N_BW_40ALL)
+                               wiphy->bands[index]->ht_cap.cap |= IEEE80211_HT_CAP_SGI_40;
                }
                if ((index >= 0) && nmode) {
-                       wiphy->bands[index]->ht_cap.cap =
-                               IEEE80211_HT_CAP_SGI_20 | IEEE80211_HT_CAP_DSSSCCK40 |
-                               IEEE80211_HT_CAP_MAX_AMSDU;
+                       wiphy->bands[index]->ht_cap.cap |=
+                               IEEE80211_HT_CAP_SGI_20 | IEEE80211_HT_CAP_DSSSCCK40;
                        wiphy->bands[index]->ht_cap.ht_supported = TRUE;
                        wiphy->bands[index]->ht_cap.ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K;
                        wiphy->bands[index]->ht_cap.ampdu_density = IEEE80211_HT_MPDU_DENSITY_16;
                }
-
-               if ((index >= 0) && bw_cap) {
-                       wiphy->bands[index]->ht_cap.cap |= IEEE80211_HT_CAP_SGI_40;
-               }
        }
 
        wiphy_apply_custom_regulatory(wiphy, &brcm_regdom);
@@ -7559,17 +7577,44 @@ s32 wl_cfg80211_set_wps_p2p_ie(struct net_device *net, char *buf, int len,
 {
        struct wl_priv *wl;
        struct net_device *ndev = NULL;
+       struct ether_addr primary_mac;
        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, net) ||
+
+       if (wl_get_drv_status(wl, AP_CREATING, net) ||
                wl_get_drv_status(wl, AP_CREATED, net)) {
                ndev = net;
                bssidx = 0;
+       } else if (wl->p2p) {
+          if (net == wl->p2p_net) {
+                       net = wl_to_prmry_ndev(wl);
+               }
+
+               if (!wl->p2p->on) {
+                       get_primary_mac(wl, &primary_mac);
+                       wl_cfgp2p_generate_bss_mac(&primary_mac, &wl->p2p->dev_addr,
+                               &wl->p2p->int_addr);
+                       /* In case of p2p_listen command, supplicant send remain_on_channel
+                       * without turning on P2P
+                       */
+                       p2p_on(wl) = true;
+                       ret = wl_cfgp2p_enable_discovery(wl, ndev, NULL, 0);
+
+                       if (unlikely(ret)) {
+                               goto exit;
+                       }
+               }
+               if (net  != wl_to_prmry_ndev(wl)) {
+                       if (wl_get_mode_by_netdev(wl, net) == WL_MODE_AP) {
+                               ndev = wl_to_p2p_bss_ndev(wl, P2PAPI_BSSCFG_CONNECTION);
+                               bssidx = wl_to_p2p_bss_bssidx(wl, P2PAPI_BSSCFG_CONNECTION);
+                       }
+               } else {
+                               ndev = wl_to_p2p_bss_ndev(wl, P2PAPI_BSSCFG_PRIMARY);
+                               bssidx = wl_to_p2p_bss_bssidx(wl, P2PAPI_BSSCFG_DEVICE);
+               }
        }
        if (ndev != NULL) {
                switch (type) {
@@ -7586,7 +7631,7 @@ s32 wl_cfg80211_set_wps_p2p_ie(struct net_device *net, char *buf, int len,
                if (pktflag)
                        ret = wl_cfgp2p_set_management_ie(wl, ndev, bssidx, pktflag, buf, len);
        }
-
+exit:
        return ret;
 }
 
index a902666..bdcfa95 100644 (file)
@@ -1229,6 +1229,7 @@ wl_cfgp2p_listen_expired(unsigned long data)
        struct wl_priv *wl = (struct wl_priv *) data;
 
        CFGP2P_DBG((" Enter\n"));
+       memset(&msg, 0, sizeof(wl_event_msg_t));
        msg.event_type =  hton32(WLC_E_P2P_DISC_LISTEN_COMPLETE);
        wl_cfg80211_event(wl_to_p2p_bss_ndev(wl, P2PAPI_BSSCFG_DEVICE), &msg, NULL);
 }
@@ -1401,13 +1402,12 @@ wl_cfgp2p_tx_action_frame(struct wl_priv *wl, struct net_device *dev,
                wl->ioctl_buf, WLC_IOCTL_MAXLEN, bssidx, &wl->ioctl_buf_sync);
 
        if (ret < 0) {
-
                CFGP2P_ERR((" sending action frame is failed\n"));
                goto exit;
        }
        timeout = wait_event_interruptible_timeout(wl->netif_change_event,
-       (wl_get_p2p_status(wl, ACTION_TX_COMPLETED) || wl_get_p2p_status(wl, ACTION_TX_NOACK)),
-       msecs_to_jiffies(MAX_WAIT_TIME));
+               (wl_get_p2p_status(wl, ACTION_TX_COMPLETED) || wl_get_p2p_status(wl, ACTION_TX_NOACK)),
+               msecs_to_jiffies(MAX_WAIT_TIME));
 
        if (timeout > 0 && wl_get_p2p_status(wl, ACTION_TX_COMPLETED)) {
                CFGP2P_INFO(("tx action frame operation is completed\n"));