X-Git-Url: http://demsky.eecs.uci.edu/git/?a=blobdiff_plain;ds=sidebyside;f=drivers%2Fnet%2Fwireless%2Flibertas%2Fcfg.c;h=89f34ad8d34acd1f01ba34644339bdffa228fdb1;hb=731f8e1c41a4d0ffb589e2395f931f8a1aa6c6a4;hp=63009c7eb2f1a0105795bc853f244d4d8810b9c1;hpb=49fee69204035247fd2a5828863fc6f633e829f2;p=firefly-linux-kernel-4.4.55.git diff --git a/drivers/net/wireless/libertas/cfg.c b/drivers/net/wireless/libertas/cfg.c index 63009c7eb2f1..89f34ad8d34a 100644 --- a/drivers/net/wireless/libertas/cfg.c +++ b/drivers/net/wireless/libertas/cfg.c @@ -485,6 +485,7 @@ static int lbs_cfg_set_channel(struct wiphy *wiphy, static int lbs_ret_scan(struct lbs_private *priv, unsigned long dummy, struct cmd_header *resp) { + struct cfg80211_bss *bss; struct cmd_ds_802_11_scan_rsp *scanresp = (void *)resp; int bsssize; const u8 *pos; @@ -632,12 +633,14 @@ static int lbs_ret_scan(struct lbs_private *priv, unsigned long dummy, LBS_SCAN_RSSI_TO_MBM(rssi)/100); if (channel && - !(channel->flags & IEEE80211_CHAN_DISABLED)) - cfg80211_inform_bss(wiphy, channel, + !(channel->flags & IEEE80211_CHAN_DISABLED)) { + bss = cfg80211_inform_bss(wiphy, channel, bssid, le64_to_cpu(*(__le64 *)tsfdesc), capa, intvl, ie, ielen, LBS_SCAN_RSSI_TO_MBM(rssi), GFP_KERNEL); + cfg80211_put_bss(bss); + } } else lbs_deb_scan("scan response: missing BSS channel IE\n"); @@ -695,7 +698,7 @@ static void lbs_scan_worker(struct work_struct *work) tlv = scan_cmd->tlvbuffer; /* add SSID TLV */ - if (priv->scan_req->n_ssids) + if (priv->scan_req->n_ssids && priv->scan_req->ssids[0].ssid_len > 0) tlv += lbs_add_ssid_tlv(tlv, priv->scan_req->ssids[0].ssid, priv->scan_req->ssids[0].ssid_len); @@ -712,7 +715,7 @@ static void lbs_scan_worker(struct work_struct *work) if (priv->scan_channel < priv->scan_req->n_channels) { cancel_delayed_work(&priv->scan_work); - if (!priv->stopping) + if (netif_running(priv->dev)) queue_delayed_work(priv->work_thread, &priv->scan_work, msecs_to_jiffies(300)); } @@ -728,16 +731,9 @@ static void lbs_scan_worker(struct work_struct *work) le16_to_cpu(scan_cmd->hdr.size), lbs_ret_scan, 0); - if (priv->scan_channel >= priv->scan_req->n_channels) { + if (priv->scan_channel >= priv->scan_req->n_channels) /* Mark scan done */ - if (priv->internal_scan) - kfree(priv->scan_req); - else - cfg80211_scan_done(priv->scan_req, false); - - priv->scan_req = NULL; - priv->last_scan = jiffies; - } + lbs_scan_done(priv); /* Restart network */ if (carrier) @@ -775,6 +771,21 @@ static void _internal_start_scan(struct lbs_private *priv, bool internal, lbs_deb_leave(LBS_DEB_CFG80211); } +/* + * Clean up priv->scan_req. Should be used to handle the allocation details. + */ +void lbs_scan_done(struct lbs_private *priv) +{ + WARN_ON(!priv->scan_req); + + if (priv->internal_scan) + kfree(priv->scan_req); + else + cfg80211_scan_done(priv->scan_req, false); + + priv->scan_req = NULL; +} + static int lbs_cfg_scan(struct wiphy *wiphy, struct net_device *dev, struct cfg80211_scan_request *request) @@ -1302,24 +1313,26 @@ static int lbs_cfg_connect(struct wiphy *wiphy, struct net_device *dev, lbs_deb_enter(LBS_DEB_CFG80211); if (!sme->bssid) { - /* Run a scan if one isn't in-progress already and if the last - * scan was done more than 2 seconds ago. - */ - if (priv->scan_req == NULL && - time_after(jiffies, priv->last_scan + (2 * HZ))) { - struct cfg80211_scan_request *creq; + struct cfg80211_scan_request *creq; - creq = _new_connect_scan_req(wiphy, sme); - if (!creq) { - ret = -EINVAL; - goto done; - } + /* + * Scan for the requested network after waiting for existing + * scans to finish. + */ + lbs_deb_assoc("assoc: waiting for existing scans\n"); + wait_event_interruptible_timeout(priv->scan_q, + (priv->scan_req == NULL), + (15 * HZ)); - lbs_deb_assoc("assoc: scanning for compatible AP\n"); - _internal_start_scan(priv, true, creq); + creq = _new_connect_scan_req(wiphy, sme); + if (!creq) { + ret = -EINVAL; + goto done; } - /* Wait for any in-progress scan to complete */ + lbs_deb_assoc("assoc: scanning for compatible AP\n"); + _internal_start_scan(priv, true, creq); + lbs_deb_assoc("assoc: waiting for scan to complete\n"); wait_event_interruptible_timeout(priv->scan_q, (priv->scan_req == NULL), @@ -1409,31 +1422,23 @@ static int lbs_cfg_connect(struct wiphy *wiphy, struct net_device *dev, return ret; } -static int lbs_cfg_disconnect(struct wiphy *wiphy, struct net_device *dev, - u16 reason_code) +int lbs_disconnect(struct lbs_private *priv, u16 reason) { - struct lbs_private *priv = wiphy_priv(wiphy); struct cmd_ds_802_11_deauthenticate cmd; - - if (dev == priv->mesh_dev) - return -EOPNOTSUPP; - - lbs_deb_enter_args(LBS_DEB_CFG80211, "reason_code %d", reason_code); - - /* store for lbs_cfg_ret_disconnect() */ - priv->disassoc_reason = reason_code; + int ret; memset(&cmd, 0, sizeof(cmd)); cmd.hdr.size = cpu_to_le16(sizeof(cmd)); /* Mildly ugly to use a locally store my own BSSID ... */ memcpy(cmd.macaddr, &priv->assoc_bss, ETH_ALEN); - cmd.reasoncode = cpu_to_le16(reason_code); + cmd.reasoncode = cpu_to_le16(reason); - if (lbs_cmd_with_response(priv, CMD_802_11_DEAUTHENTICATE, &cmd)) - return -EFAULT; + ret = lbs_cmd_with_response(priv, CMD_802_11_DEAUTHENTICATE, &cmd); + if (ret) + return ret; cfg80211_disconnected(priv->dev, - priv->disassoc_reason, + reason, NULL, 0, GFP_KERNEL); priv->connect_status = LBS_DISCONNECTED; @@ -1441,6 +1446,21 @@ static int lbs_cfg_disconnect(struct wiphy *wiphy, struct net_device *dev, return 0; } +static int lbs_cfg_disconnect(struct wiphy *wiphy, struct net_device *dev, + u16 reason_code) +{ + struct lbs_private *priv = wiphy_priv(wiphy); + + if (dev == priv->mesh_dev) + return -EOPNOTSUPP; + + lbs_deb_enter_args(LBS_DEB_CFG80211, "reason_code %d", reason_code); + + /* store for lbs_cfg_ret_disconnect() */ + priv->disassoc_reason = reason_code; + + return lbs_disconnect(priv, reason_code); +} static int lbs_cfg_set_default_key(struct wiphy *wiphy, struct net_device *netdev, @@ -1658,28 +1678,20 @@ static int lbs_change_intf(struct wiphy *wiphy, struct net_device *dev, if (dev == priv->mesh_dev) return -EOPNOTSUPP; - lbs_deb_enter(LBS_DEB_CFG80211); - switch (type) { case NL80211_IFTYPE_MONITOR: - ret = lbs_set_monitor_mode(priv, 1); - break; case NL80211_IFTYPE_STATION: - if (priv->wdev->iftype == NL80211_IFTYPE_MONITOR) - ret = lbs_set_monitor_mode(priv, 0); - if (!ret) - ret = lbs_set_snmp_mib(priv, SNMP_MIB_OID_BSS_TYPE, 1); - break; case NL80211_IFTYPE_ADHOC: - if (priv->wdev->iftype == NL80211_IFTYPE_MONITOR) - ret = lbs_set_monitor_mode(priv, 0); - if (!ret) - ret = lbs_set_snmp_mib(priv, SNMP_MIB_OID_BSS_TYPE, 2); break; default: - ret = -ENOTSUPP; + return -EOPNOTSUPP; } + lbs_deb_enter(LBS_DEB_CFG80211); + + if (priv->iface_running) + ret = lbs_set_iface_type(priv, type); + if (!ret) priv->wdev->iftype = type; @@ -1711,6 +1723,7 @@ static void lbs_join_post(struct lbs_private *priv, 2 + 2 + /* atim */ 2 + 8]; /* extended rates */ u8 *fake = fake_ie; + struct cfg80211_bss *bss; lbs_deb_enter(LBS_DEB_CFG80211); @@ -1754,14 +1767,15 @@ static void lbs_join_post(struct lbs_private *priv, *fake++ = 0x6c; lbs_deb_hex(LBS_DEB_CFG80211, "IE", fake_ie, fake - fake_ie); - cfg80211_inform_bss(priv->wdev->wiphy, - params->channel, - bssid, - 0, - capability, - params->beacon_interval, - fake_ie, fake - fake_ie, - 0, GFP_KERNEL); + bss = cfg80211_inform_bss(priv->wdev->wiphy, + params->channel, + bssid, + 0, + capability, + params->beacon_interval, + fake_ie, fake - fake_ie, + 0, GFP_KERNEL); + cfg80211_put_bss(bss); memcpy(priv->wdev->ssid, params->ssid, params->ssid_len); priv->wdev->ssid_len = params->ssid_len;