From 34c09b89cb76c09f4796c18f4be6ee27d783bb06 Mon Sep 17 00:00:00 2001 From: "Howard M. Harte" Date: Sun, 9 Oct 2011 02:31:21 +0100 Subject: net: wireless: bcmdhd: add support for mkeepalive. Fix p2p group add issue. Change-Id: Ieb8fba54e04912b4002837243c00ba90fd150e5d Signed-off-by: Howard M. Harte Signed-off-by: Dmitry Shmidt --- drivers/net/wireless/bcmdhd/dhd_common.c | 64 +++++++++------------ drivers/net/wireless/bcmdhd/dhd_linux.c | 10 +++- drivers/net/wireless/bcmdhd/include/wlioctl.h | 13 ++++- drivers/net/wireless/bcmdhd/wl_cfg80211.c | 80 ++++++--------------------- drivers/net/wireless/bcmdhd/wl_cfg80211.h | 3 +- drivers/net/wireless/bcmdhd/wl_cfgp2p.h | 2 + 6 files changed, 67 insertions(+), 105 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/bcmdhd/dhd_common.c b/drivers/net/wireless/bcmdhd/dhd_common.c index 2e6a53ed9ca..2a68965bb91 100644 --- a/drivers/net/wireless/bcmdhd/dhd_common.c +++ b/drivers/net/wireless/bcmdhd/dhd_common.c @@ -92,7 +92,7 @@ bool ap_cfg_running = FALSE; bool ap_fw_loaded = FALSE; #if defined(KEEP_ALIVE) -int dhd_keep_alive_onoff(dhd_pub_t *dhd, int ka_on); +int dhd_keep_alive_onoff(dhd_pub_t *dhd); #endif /* KEEP_ALIVE */ /* Packet alignment for most efficient SDIO (can change based on platform) */ @@ -1674,7 +1674,7 @@ dhd_preinit_ioctls(dhd_pub_t *dhd) #if defined(SOFTAP) if (ap_fw_loaded == FALSE) #endif - if ((res = dhd_keep_alive_onoff(dhd, 1)) < 0) + if ((res = dhd_keep_alive_onoff(dhd)) < 0) DHD_ERROR(("%s set keeplive failed %d\n", __FUNCTION__, res)); } @@ -2260,49 +2260,39 @@ dhd_pno_get_status(dhd_pub_t *dhd) #endif /* PNO_SUPPORT */ #if defined(KEEP_ALIVE) -int dhd_keep_alive_onoff(dhd_pub_t *dhd, int ka_on) +int dhd_keep_alive_onoff(dhd_pub_t *dhd) { - char buf[256]; - char *buf_ptr = buf; - wl_keep_alive_pkt_t keep_alive_pkt; - char * str; - int str_len, buf_len; - int res = -1; - int keep_alive_period = KEEP_ALIVE_PERIOD; /* in ms */ + 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; - DHD_TRACE(("%s: param=%d\n", __FUNCTION__, ka_on)); + DHD_ERROR(("%s Enter\n", __FUNCTION__)); - if (ka_on) { /* on suspend */ - keep_alive_pkt.period_msec = keep_alive_period; - - } else { - /* on resume, turn off keep_alive packets */ - keep_alive_pkt.period_msec = 0; - } - - /* IOC var name */ - str = "keep_alive"; + str = "mkeep_alive"; str_len = strlen(str); strncpy(buf, str, str_len); - buf[str_len] = '\0'; + buf[ str_len ] = '\0'; + mkeep_alive_pktp = (wl_mkeep_alive_pkt_t *) (buf + str_len + 1); + mkeep_alive_pkt.period_msec = KEEP_ALIVE_PERIOD; buf_len = str_len + 1; + mkeep_alive_pkt.version = htod16(WL_MKEEP_ALIVE_VERSION); + mkeep_alive_pkt.length = htod16(WL_MKEEP_ALIVE_FIXED_LEN); + /* Setup keep alive zero for null packet generation */ + mkeep_alive_pkt.keep_alive_id = 0; + mkeep_alive_pkt.len_bytes = 0; + buf_len += WL_MKEEP_ALIVE_FIXED_LEN; + /* Keep-alive attributes are set in local variable (mkeep_alive_pkt), and + * then memcpy'ed into buffer (mkeep_alive_pktp) since there is no + * guarantee that the buffer is properly aligned. + */ + memcpy((char *)mkeep_alive_pktp, &mkeep_alive_pkt, WL_MKEEP_ALIVE_FIXED_LEN); - /* set ptr to IOCTL payload after the var name */ - buf_ptr += buf_len; /* include term Z */ - - /* copy Keep-alive attributes from local var keep_alive_pkt */ - str = NULL_PKT_STR; - keep_alive_pkt.len_bytes = strlen(str); - - memcpy(buf_ptr, &keep_alive_pkt, WL_KEEP_ALIVE_FIXED_LEN); - buf_ptr += WL_KEEP_ALIVE_FIXED_LEN; - - /* copy packet data */ - memcpy(buf_ptr, str, keep_alive_pkt.len_bytes); - buf_len += (WL_KEEP_ALIVE_FIXED_LEN + keep_alive_pkt.len_bytes); -/* res = dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, buf, buf_len, TRUE, 0); -*/ + return res; } #endif /* defined(KEEP_ALIVE) */ diff --git a/drivers/net/wireless/bcmdhd/dhd_linux.c b/drivers/net/wireless/bcmdhd/dhd_linux.c index 690384a2495..ba1f6a21dea 100644 --- a/drivers/net/wireless/bcmdhd/dhd_linux.c +++ b/drivers/net/wireless/bcmdhd/dhd_linux.c @@ -967,13 +967,17 @@ dhd_op_if(dhd_if_t *ifp) } if (ret == 0) { strncpy(ifp->net->name, ifp->name, IFNAMSIZ); + ifp->net->name[IFNAMSIZ - 1] = '\0'; + memcpy(netdev_priv(ifp->net), &dhd, sizeof(dhd)); #ifdef WL_CFG80211 if (dhd->dhd_state & DHD_ATTACH_STATE_CFG80211) - wl_cfg80211_notify_ifadd(ifp->net); + if (!wl_cfg80211_notify_ifadd(ifp->net, ifp->idx, dhd_net_attach)) { + ifp->state = 0; + return; + } + #endif - ifp->net->name[IFNAMSIZ - 1] = '\0'; - memcpy(netdev_priv(ifp->net), &dhd, sizeof(dhd)); if ((err = dhd_net_attach(&dhd->pub, ifp->idx)) != 0) { DHD_ERROR(("%s: dhd_net_attach failed, err %d\n", __FUNCTION__, err)); diff --git a/drivers/net/wireless/bcmdhd/include/wlioctl.h b/drivers/net/wireless/bcmdhd/include/wlioctl.h index f1af5b1841b..a441eabc076 100644 --- a/drivers/net/wireless/bcmdhd/include/wlioctl.h +++ b/drivers/net/wireless/bcmdhd/include/wlioctl.h @@ -1747,7 +1747,18 @@ struct wl_msglevel2 { uint32 high; }; - +typedef struct wl_mkeep_alive_pkt { + uint16 version; + uint16 length; + uint32 period_msec; + uint16 len_bytes; + uint8 keep_alive_id; + uint8 data[1]; +} wl_mkeep_alive_pkt_t; + +#define WL_MKEEP_ALIVE_VERSION 1 +#define WL_MKEEP_ALIVE_FIXED_LEN OFFSETOF(wl_mkeep_alive_pkt_t, data) +#define WL_MKEEP_ALIVE_PRECISION 500 #define WLC_ROAM_TRIGGER_DEFAULT 0 #define WLC_ROAM_TRIGGER_BANDWIDTH 1 diff --git a/drivers/net/wireless/bcmdhd/wl_cfg80211.c b/drivers/net/wireless/bcmdhd/wl_cfg80211.c index cc5d86e8e7b..366ce2224ab 100644 --- a/drivers/net/wireless/bcmdhd/wl_cfg80211.c +++ b/drivers/net/wireless/bcmdhd/wl_cfg80211.c @@ -213,10 +213,6 @@ static s32 wl_cfg80211_get_station(struct wiphy *wiphy, static s32 wl_cfg80211_set_power_mgmt(struct wiphy *wiphy, struct net_device *dev, bool enabled, s32 timeout); -static s32 wl_cfg80211_set_bitrate_mask(struct wiphy *wiphy, - struct net_device *dev, - const u8 *addr, - const struct cfg80211_bitrate_mask *mask); static int wl_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev, struct cfg80211_connect_params *sme); static s32 wl_cfg80211_disconnect(struct wiphy *wiphy, struct net_device *dev, @@ -883,6 +879,7 @@ wl_cfg80211_add_virtual_iface(struct wiphy *wiphy, char *name, struct wl_priv *wl = WL_PRIV_GET(); struct net_device *_ndev; dhd_pub_t *dhd = (dhd_pub_t *)(wl->pub); + int (*net_attach)(dhd_pub_t *dhdp, int ifidx); WL_DBG(("if name: %s, type: %d\n", name, type)); switch (type) { @@ -985,6 +982,16 @@ wl_cfg80211_add_virtual_iface(struct wiphy *wiphy, char *name, wl->p2p->vif_created = true; set_mode_by_netdev(wl, _ndev, mode); wl = wdev_to_wl(vwdev); + net_attach = wl_to_p2p_bss_private(wl, P2PAPI_BSSCFG_CONNECTION); + rtnl_unlock(); + if (net_attach && !net_attach(dhd, _ndev->ifindex)) + WL_DBG((" virtual interface(%s) is " + "created\n", wl->p2p->vir_ifname)); + else { + rtnl_lock(); + goto fail; + } + rtnl_lock(); return _ndev; } else { @@ -994,6 +1001,7 @@ wl_cfg80211_add_virtual_iface(struct wiphy *wiphy, char *name, wl->p2p->vif_created = false; } } +fail: return ERR_PTR(-ENODEV); } @@ -1110,11 +1118,12 @@ wl_cfg80211_change_virtual_iface(struct wiphy *wiphy, struct net_device *ndev, } s32 -wl_cfg80211_notify_ifadd(struct net_device *net) +wl_cfg80211_notify_ifadd(struct net_device *net, s32 idx, +int (*_net_attach)(dhd_pub_t *dhdp, int ifidx)) { struct wl_priv *wl = WL_PRIV_GET(); s32 ret = BCME_OK; - if (!net || !net->name) { + if (!net) { WL_ERR(("net is NULL\n")); return 0; } @@ -1126,7 +1135,9 @@ wl_cfg80211_notify_ifadd(struct net_device *net) wl_to_p2p_bss_ndev(wl, P2PAPI_BSSCFG_CONNECTION) = net; wl_to_p2p_bss_bssidx(wl, P2PAPI_BSSCFG_CONNECTION) = P2PAPI_BSSCFG_CONNECTION; + wl_to_p2p_bss_private(wl, P2PAPI_BSSCFG_CONNECTION) = _net_attach; wl_clr_p2p_status(wl, IF_ADD); + net->ifindex = idx; wake_up_interruptible(&wl->dongle_event_wait); } return ret; @@ -2704,62 +2715,6 @@ static __used u32 wl_find_msb(u16 bit16) return ret; } -static s32 -wl_cfg80211_set_bitrate_mask(struct wiphy *wiphy, struct net_device *dev, - const u8 *addr, - const struct cfg80211_bitrate_mask *mask) -{ - struct wl_rateset rateset; - s32 rate; - s32 val; - s32 err_bg; - s32 err_a; - u32 legacy; - s32 err = 0; - - CHECK_SYS_UP(); - /* addr param is always NULL. ignore it */ - /* Get current rateset */ - err = wldev_ioctl(dev, WLC_GET_CURR_RATESET, &rateset, - sizeof(rateset), false); - if (unlikely(err)) { - WL_ERR(("could not get current rateset (%d)\n", err)); - return err; - } - - rateset.count = dtoh32(rateset.count); - - legacy = wl_find_msb(mask->control[IEEE80211_BAND_2GHZ].legacy); - if (!legacy) - legacy = wl_find_msb(mask->control[IEEE80211_BAND_5GHZ].legacy); - - val = wl_g_rates[legacy - 1].bitrate * 100000; - - if (val < rateset.count) { - /* Select rate by rateset index */ - rate = rateset.rates[val] & 0x7f; - } else { - /* Specified rate in bps */ - rate = val / 500000; - } - - WL_DBG(("rate %d mbps\n", (rate / 2))); - - /* - * - * Set rate override, - * Since the is a/b/g-blind, both a/bg_rate are enforced. - */ - err_bg = wl_dev_intvar_set(dev, "bg_rate", rate); - err_a = wl_dev_intvar_set(dev, "a_rate", rate); - if (unlikely(err_bg && err_a)) { - WL_ERR(("could not set fixed rate (%d) (%d)\n", err_bg, err_a)); - return err_bg | err_a; - } - - return err; -} - static s32 wl_cfg80211_resume(struct wiphy *wiphy) { struct wl_priv *wl = WL_PRIV_GET(); @@ -3837,7 +3792,6 @@ static struct cfg80211_ops wl_cfg80211_ops = { .set_default_key = wl_cfg80211_config_default_key, .set_default_mgmt_key = wl_cfg80211_config_default_mgmt_key, .set_power_mgmt = wl_cfg80211_set_power_mgmt, - .set_bitrate_mask = wl_cfg80211_set_bitrate_mask, .connect = wl_cfg80211_connect, .disconnect = wl_cfg80211_disconnect, .suspend = wl_cfg80211_suspend, diff --git a/drivers/net/wireless/bcmdhd/wl_cfg80211.h b/drivers/net/wireless/bcmdhd/wl_cfg80211.h index f9de60f0ca3..4dea1327cb9 100644 --- a/drivers/net/wireless/bcmdhd/wl_cfg80211.h +++ b/drivers/net/wireless/bcmdhd/wl_cfg80211.h @@ -499,7 +499,8 @@ extern void wl_cfg80211_set_sdio_func(void *func); /* set sdio function info */ extern struct sdio_func *wl_cfg80211_get_sdio_func(void); /* set sdio function info */ 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_notify_ifadd(struct net_device *net, s32 idx, +int (*_net_attach)(dhd_pub_t *dhdp, int ifidx)); 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); diff --git a/drivers/net/wireless/bcmdhd/wl_cfgp2p.h b/drivers/net/wireless/bcmdhd/wl_cfgp2p.h index 971633ae214..d62f5422708 100644 --- a/drivers/net/wireless/bcmdhd/wl_cfgp2p.h +++ b/drivers/net/wireless/bcmdhd/wl_cfgp2p.h @@ -61,6 +61,7 @@ struct p2p_bss { u32 bssidx; struct net_device *dev; struct p2p_saved_ie saved_ie; + void *private_data; }; struct p2p_info { @@ -94,6 +95,7 @@ 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_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, \ &(wl)->p2p->status)) -- cgit v1.2.3