Ejemplo n.º 1
0
void ath6kl_cfg80211_scan_complete_event(struct ath6kl *ar, int status)
{
	int i;

	ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "%s: status %d\n", __func__, status);

	if (!ar->scan_req)
		return;

	if ((status == -ECANCELED) || (status == -EBUSY)) {
		cfg80211_scan_done(ar->scan_req, true);
		goto out;
	}

	cfg80211_scan_done(ar->scan_req, false);

	if (ar->scan_req->n_ssids && ar->scan_req->ssids[0].ssid_len) {
		for (i = 0; i < ar->scan_req->n_ssids; i++) {
			ath6kl_wmi_probedssid_cmd(ar->wmi, i + 1,
						  DISABLE_SSID_FLAG,
						  0, NULL);
		}
	}

out:
	ar->scan_req = NULL;
}
Ejemplo n.º 2
0
void orinoco_scan_done(struct orinoco_private *priv, bool abort)
{
	if (priv->scan_request) {
		cfg80211_scan_done(priv->scan_request, abort);
		priv->scan_request = NULL;
	}
}
Ejemplo n.º 3
0
/**
 *  lbs_eth_stop - close the ethX interface
 *
 *  @dev:	A pointer to &net_device structure
 *  returns:	0
 */
static int lbs_eth_stop(struct net_device *dev)
{
	struct lbs_private *priv = dev->ml_priv;

	lbs_deb_enter(LBS_DEB_NET);

	if (priv->connect_status == LBS_CONNECTED)
		lbs_disconnect(priv, WLAN_REASON_DEAUTH_LEAVING);

	spin_lock_irq(&priv->driver_lock);
	netif_stop_queue(dev);
	spin_unlock_irq(&priv->driver_lock);

	lbs_update_mcast(priv);
	cancel_delayed_work_sync(&priv->scan_work);
	if (priv->scan_req) {
		cfg80211_scan_done(priv->scan_req, false);
		priv->scan_req = NULL;
	}

	netif_carrier_off(priv->dev);

	if (!lbs_iface_active(priv))
		lbs_stop_iface(priv);

	lbs_deb_leave(LBS_DEB_NET);
	return 0;
}
Ejemplo n.º 4
0
Archivo: p2p.c Proyecto: AK101111/linux
void wil_p2p_search_expired(struct work_struct *work)
{
	struct wil_p2p_info *p2p = container_of(work,
			struct wil_p2p_info, discovery_expired_work);
	struct wil6210_priv *wil = container_of(p2p,
			struct wil6210_priv, p2p);
	u8 started;

	wil_dbg_misc(wil, "%s()\n", __func__);

	mutex_lock(&wil->mutex);
	started = wil_p2p_stop_discovery(wil);
	mutex_unlock(&wil->mutex);

	if (started) {
		struct cfg80211_scan_info info = {
			.aborted = false,
		};

		mutex_lock(&wil->p2p_wdev_mutex);
		cfg80211_scan_done(wil->scan_request, &info);
		wil->scan_request = NULL;
		wil->radio_wdev = wil->wdev;
		mutex_unlock(&wil->p2p_wdev_mutex);
	}
}
Ejemplo n.º 5
0
VOID
kalP2PIndicateScanDone (
    IN P_GLUE_INFO_T prGlueInfo,
    IN BOOLEAN fgIsAbort
    )
{
    P_GL_P2P_INFO_T prGlueP2pInfo = (P_GL_P2P_INFO_T)NULL;

    do {
        if (prGlueInfo == NULL) {

            ASSERT(FALSE);
            break;
        }

        prGlueP2pInfo = prGlueInfo->prP2PInfo;

        if (prGlueP2pInfo == NULL) {
            ASSERT(FALSE);
            break;
        }


        if (prGlueP2pInfo->prScanRequest) {
            cfg80211_scan_done(prGlueP2pInfo->prScanRequest,
                        fgIsAbort);

            prGlueP2pInfo->prScanRequest = NULL;
        }

    } while (FALSE);


} /* kalP2PIndicateScanDone */
Ejemplo n.º 6
0
static int r92su_stop(struct net_device *ndev)
{
	struct r92su *r92su = ndev->ml_priv;
	struct cfg80211_bss *tmp_bss;
	struct llist_node *node;
	int err = -EINVAL, i;

	mutex_lock(&r92su->lock);

	if (r92su_is_connected(r92su)) {
		err = __r92su_disconnect(r92su);
		WARN_ONCE(err, "disconnect failed");
	}

	r92su_set_power(r92su, false);

	if (r92su_is_initializing(r92su)) {
		err = r92su_hw_mac_deinit(r92su);
		WARN_ONCE(err, "failed to deinitilize MAC");
	}

	if (r92su_is_initializing(r92su))
		r92su_set_state(r92su, R92SU_STOP);

	if (r92su->scan_request)
		cfg80211_scan_done(r92su->scan_request, true);

	tmp_bss = r92su->want_connect_bss;
	r92su->want_connect_bss = NULL;
	r92su_bss_free(r92su, tmp_bss);

	r92su->scan_request = NULL;

	for (i = 0; i < MAX_STA; i++)
		r92su_sta_del(r92su, i);

	mutex_unlock(&r92su->lock);

	cancel_delayed_work_sync(&r92su->survey_done_work);
	cancel_delayed_work_sync(&r92su->service_work);
	cancel_work_sync(&r92su->add_bss_work);
	cancel_work_sync(&r92su->connect_bss_work);
	cancel_work_sync(&r92su->disconnect_work);

	node = llist_del_all(&r92su->add_bss_list);
	while (node) {
		struct r92su_add_bss *bss_priv =
			llist_entry(node, struct r92su_add_bss, head);
		node = ACCESS_ONCE(node->next);
		kfree(bss_priv);
	}

	/* wait for keys and stas to be freed */
	synchronize_rcu();
	rcu_barrier();

	return err;
}
Ejemplo n.º 7
0
void ath6kl_cfg80211_disconnect_event(struct ath6kl *ar, u8 reason,
				      u8 *bssid, u8 assoc_resp_len,
				      u8 *assoc_info, u16 proto_reason)
{
	if (ar->scan_req) {
		cfg80211_scan_done(ar->scan_req, true);
		ar->scan_req = NULL;
	}

	if (ar->nw_type & ADHOC_NETWORK) {
		if (ar->wdev->iftype != NL80211_IFTYPE_ADHOC) {
			ath6kl_dbg(ATH6KL_DBG_WLAN_CFG,
				   "%s: ath6k not in ibss mode\n", __func__);
			return;
		}
		memset(bssid, 0, ETH_ALEN);
		cfg80211_ibss_joined(ar->net_dev, bssid, GFP_KERNEL);
		return;
	}

	if (ar->nw_type & INFRA_NETWORK) {
		if (ar->wdev->iftype != NL80211_IFTYPE_STATION &&
		    ar->wdev->iftype != NL80211_IFTYPE_P2P_CLIENT) {
			ath6kl_dbg(ATH6KL_DBG_WLAN_CFG,
				   "%s: ath6k not in station mode\n", __func__);
			return;
		}
	}

	/*
	 * Send a disconnect command to target when a disconnect event is
	 * received with reason code other than 3 (DISCONNECT_CMD - disconnect
	 * request from host) to make the firmware stop trying to connect even
	 * after giving disconnect event. There will be one more disconnect
	 * event for this disconnect command with reason code DISCONNECT_CMD
	 * which will be notified to cfg80211.
	 */

	if (reason != DISCONNECT_CMD) {
		ath6kl_wmi_disconnect_cmd(ar->wmi);
		return;
	}

	clear_bit(CONNECT_PEND, &ar->flag);

	if (ar->sme_state == SME_CONNECTING) {
		cfg80211_connect_result(ar->net_dev,
				bssid, NULL, 0,
				NULL, 0,
				WLAN_STATUS_UNSPECIFIED_FAILURE,
				GFP_KERNEL);
	} else if (ar->sme_state == SME_CONNECTED) {
		cfg80211_disconnected(ar->net_dev, reason,
				NULL, 0, GFP_KERNEL);
	}

	ar->sme_state = SME_DISCONNECTED;
}
static int
woal_uap_cfg80211_scan(struct wiphy *wiphy, struct net_device *dev,
                       struct cfg80211_scan_request *request)
{
    ENTER();

    cfg80211_scan_done(request, MTRUE);

    LEAVE();
    return 0;
}
Ejemplo n.º 9
0
static int __wil_down(struct wil6210_priv *wil)
{
	if (wil->scan_request) {
		cfg80211_scan_done(wil->scan_request, true);
		wil->scan_request = NULL;
	}

	wil6210_disconnect(wil, NULL);
	wil_rx_fini(wil);

	return 0;
}
Ejemplo n.º 10
0
/*
 * CFG802.11 network device handler for close.
 */
static int
mwifiex_close(struct net_device *dev)
{
	struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev);

	if (priv->scan_request) {
		dev_dbg(priv->adapter->dev, "aborting scan on ndo_stop\n");
		cfg80211_scan_done(priv->scan_request, 1);
		priv->scan_request = NULL;
	}

	return 0;
}
Ejemplo n.º 11
0
VOID
kalP2PIndicateScanDone (
    IN P_GLUE_INFO_T prGlueInfo,
    IN BOOLEAN fgIsAbort
    )
{
    P_GL_P2P_INFO_T prGlueP2pInfo = (P_GL_P2P_INFO_T)NULL;
    struct cfg80211_scan_request *prScanRequest = NULL;
	GLUE_SPIN_LOCK_DECLARATION();

    do {
        if (prGlueInfo == NULL) {

            ASSERT(FALSE);
            break;
        }

        prGlueP2pInfo = prGlueInfo->prP2PInfo;

        if (prGlueP2pInfo == NULL) {
            ASSERT(FALSE);
            break;
        }

		DBGLOG(INIT, TRACE, ("[p2p] scan complete %p\n", prGlueP2pInfo->prScanRequest));		

		GLUE_ACQUIRE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_NET_DEV);
		if(prGlueP2pInfo->prScanRequest != NULL) {
			prScanRequest = prGlueP2pInfo->prScanRequest;
            prGlueP2pInfo->prScanRequest = NULL;
        }
		GLUE_RELEASE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_NET_DEV);

        /* 2. then CFG80211 Indication */

        if(prScanRequest != NULL) {

			/* report all queued beacon/probe response frames  to upper layer */
			scanReportBss2Cfg80211(prGlueInfo->prAdapter,BSS_TYPE_P2P_DEVICE,NULL); 

			DBGLOG(INIT, TRACE, ("DBG:p2p_cfg_scan_done\n"));
            cfg80211_scan_done(prScanRequest, fgIsAbort);
        }

    } while (FALSE);


} /* kalP2PIndicateScanDone */
Ejemplo n.º 12
0
void ath6kl_cfg80211_deinit(struct ath6kl *ar)
{
	struct wireless_dev *wdev = ar->wdev;

	if (ar->scan_req) {
		cfg80211_scan_done(ar->scan_req, true);
		ar->scan_req = NULL;
	}

	if (!wdev)
		return;

	wiphy_unregister(wdev->wiphy);
	wiphy_free(wdev->wiphy);
	kfree(wdev);
}
Ejemplo n.º 13
0
/*
 * We reset all the structures, and we reset the UMAC.
 * After calling this routine, you're expected to reload
 * the firmware.
 */
int wil_reset(struct wil6210_priv *wil)
{
	int rc;

	WARN_ON(!mutex_is_locked(&wil->mutex));

	cancel_work_sync(&wil->disconnect_worker);
	wil6210_disconnect(wil, NULL);

	wil->status = 0; /* prevent NAPI from being scheduled */
	if (test_bit(wil_status_napi_en, &wil->status)) {
		napi_synchronize(&wil->napi_rx);
	}

	if (wil->scan_request) {
		wil_dbg_misc(wil, "Abort scan_request 0x%p\n",
			     wil->scan_request);
		del_timer_sync(&wil->scan_timer);
		cfg80211_scan_done(wil->scan_request, true);
		wil->scan_request = NULL;
	}

	wil6210_disable_irq(wil);

	wmi_event_flush(wil);

	flush_workqueue(wil->wmi_wq_conn);
	flush_workqueue(wil->wmi_wq);

	/* TODO: put MAC in reset */
	wil_target_reset(wil);

	wil_rx_fini(wil);

	/* init after reset */
	wil->pending_connect_cid = -1;
	reinit_completion(&wil->wmi_ready);

	/* TODO: release MAC reset */
	wil6210_enable_irq(wil);

	/* we just started MAC, wait for FW ready */
	rc = wil_wait_for_fw_ready(wil);

	return rc;
}
Ejemplo n.º 14
0
/*Close interface*/
static int sprdwl_close(struct net_device *dev)
{
	unsigned long flags;
	struct sprdwl_priv *priv = netdev_priv(dev);

	dev_info(&dev->dev, "%s\n", __func__);
	napi_disable(&priv->napi);

	if (timer_pending(&priv->scan_timeout))
		del_timer_sync(&priv->scan_timeout);
	spin_lock_irqsave(&priv->scan_lock, flags);
	if (priv->scan_request) {
		/*If there's a pending scan request,abort it */
		cfg80211_scan_done(priv->scan_request, true);
		priv->scan_request = NULL;
	}
	spin_unlock_irqrestore(&priv->scan_lock, flags);

	return 0;
}
Ejemplo n.º 15
0
static void r92su_survey_done_work(struct work_struct *work)
{
	struct cfg80211_scan_request *req;
	struct r92su *r92su = container_of(work, struct r92su,
					   survey_done_work.work);

	mutex_lock(&r92su->lock);
	if (!r92su_is_open(r92su))
		goto out;

	req = r92su->scan_request;
	r92su->scan_request = NULL;

	if (req)
		cfg80211_scan_done(req, req->aborted);

	r92su->scanned = true;
	complete(&r92su->scan_done);
out:
	mutex_unlock(&r92su->lock);
}
Ejemplo n.º 16
0
static int __wil_down(struct wil6210_priv *wil)
{
	WARN_ON(!mutex_is_locked(&wil->mutex));

	clear_bit(wil_status_napi_en, &wil->status);
	napi_disable(&wil->napi_rx);
	napi_disable(&wil->napi_tx);

	if (wil->scan_request) {
		wil_dbg_misc(wil, "Abort scan_request 0x%p\n",
			     wil->scan_request);
		del_timer_sync(&wil->scan_timer);
		cfg80211_scan_done(wil->scan_request, true);
		wil->scan_request = NULL;
	}

	wil6210_disconnect(wil, NULL);
	wil_rx_fini(wil);

	return 0;
}
Ejemplo n.º 17
0
/*
 * CFG802.11 network device handler for close.
 */
static int
mwifiex_close(struct net_device *dev)
{
	struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev);

	if (priv->scan_request) {
		mwifiex_dbg(priv->adapter, INFO,
			    "aborting scan on ndo_stop\n");
		cfg80211_scan_done(priv->scan_request, 1);
		priv->scan_request = NULL;
		priv->scan_aborting = true;
	}

	if (priv->sched_scanning) {
		mwifiex_dbg(priv->adapter, INFO,
			    "aborting bgscan on ndo_stop\n");
		mwifiex_stop_bg_scan(priv);
		cfg80211_sched_scan_stopped(priv->wdev.wiphy);
	}

	return 0;
}
Ejemplo n.º 18
0
/*
 * This function handles the result of different pending network operations.
 *
 * The following operations are handled and CFG802.11 subsystem is
 * notified accordingly -
 *      - Scan request completion
 *      - Association request completion
 *      - IBSS join request completion
 *      - Disconnect request completion
 */
void
mwifiex_cfg80211_results(struct work_struct *work)
{
	struct mwifiex_private *priv =
		container_of(work, struct mwifiex_private, cfg_workqueue);
	struct mwifiex_user_scan_cfg *scan_req;
	int ret = 0, i;
	struct ieee80211_channel *chan;

	if (priv->scan_request) {
		scan_req = kzalloc(sizeof(struct mwifiex_user_scan_cfg),
				   GFP_KERNEL);
		if (!scan_req) {
			dev_err(priv->adapter->dev, "failed to alloc "
						    "scan_req\n");
			return;
		}
		for (i = 0; i < priv->scan_request->n_ssids; i++) {
			memcpy(scan_req->ssid_list[i].ssid,
					priv->scan_request->ssids[i].ssid,
					priv->scan_request->ssids[i].ssid_len);
			scan_req->ssid_list[i].max_len =
					priv->scan_request->ssids[i].ssid_len;
		}
		for (i = 0; i < priv->scan_request->n_channels; i++) {
			chan = priv->scan_request->channels[i];
			scan_req->chan_list[i].chan_number = chan->hw_value;
			scan_req->chan_list[i].radio_type = chan->band;
			if (chan->flags & IEEE80211_CHAN_DISABLED)
				scan_req->chan_list[i].scan_type =
					MWIFIEX_SCAN_TYPE_PASSIVE;
			else
				scan_req->chan_list[i].scan_type =
					MWIFIEX_SCAN_TYPE_ACTIVE;
			scan_req->chan_list[i].scan_time = 0;
		}
		if (mwifiex_set_user_scan_ioctl(priv, scan_req)) {
			ret = -EFAULT;
			goto done;
		}
		if (mwifiex_inform_bss_from_scan_result(priv, NULL))
			ret = -EFAULT;
done:
		priv->scan_result_status = ret;
		dev_dbg(priv->adapter->dev, "info: %s: sending scan results\n",
							__func__);
		cfg80211_scan_done(priv->scan_request,
				(priv->scan_result_status < 0));
		priv->scan_request = NULL;
		kfree(scan_req);
	}

	if (priv->assoc_request == 1) {
		if (!priv->assoc_result) {
			cfg80211_connect_result(priv->netdev, priv->cfg_bssid,
						NULL, 0, NULL, 0,
						WLAN_STATUS_SUCCESS,
						GFP_KERNEL);
			dev_dbg(priv->adapter->dev,
				"info: associated to bssid %pM successfully\n",
			       priv->cfg_bssid);
		} else {
			dev_dbg(priv->adapter->dev,
				"info: association to bssid %pM failed\n",
			       priv->cfg_bssid);
			memset(priv->cfg_bssid, 0, ETH_ALEN);
		}
		priv->assoc_request = 0;
		priv->assoc_result = 0;
	}

	if (priv->ibss_join_request == 1) {
		if (!priv->ibss_join_result) {
			cfg80211_ibss_joined(priv->netdev, priv->cfg_bssid,
					     GFP_KERNEL);
			dev_dbg(priv->adapter->dev,
				"info: joined/created adhoc network with bssid"
					" %pM successfully\n", priv->cfg_bssid);
		} else {
			dev_dbg(priv->adapter->dev,
				"info: failed creating/joining adhoc network\n");
		}
		priv->ibss_join_request = 0;
		priv->ibss_join_result = 0;
	}

	if (priv->disconnect) {
		memset(priv->cfg_bssid, 0, ETH_ALEN);
		priv->disconnect = 0;
	}
}
Ejemplo n.º 19
0
int prism2_scan(struct wiphy *wiphy, struct net_device *dev,
		struct cfg80211_scan_request *request)
{
	struct prism2_wiphy_private *priv = wiphy_priv(wiphy);
	wlandevice_t *wlandev = dev->ml_priv;
	struct p80211msg_dot11req_scan msg1;
	struct p80211msg_dot11req_scan_results msg2;
	int result;
	int err = 0;
	int numbss = 0;
	int i = 0;
	u8 ie_buf[46];
	int ie_len;

	if (!request)
		return -EINVAL;

	if (priv->scan_request && priv->scan_request != request)
		return -EBUSY;

	if (wlandev->macmode == WLAN_MACMODE_ESS_AP) {
		printk(KERN_ERR "Can't scan in AP mode\n");
		return -EOPNOTSUPP;
	}

	priv->scan_request = request;

	memset(&msg1, 0x00, sizeof(struct p80211msg_dot11req_scan));
	msg1.msgcode = DIDmsg_dot11req_scan;
	msg1.bsstype.data = P80211ENUM_bsstype_any;

	memset(&(msg1.bssid.data), 0xFF, sizeof(p80211item_pstr6_t));
	msg1.bssid.data.len = 6;

	if (request->n_ssids > 0) {
		msg1.scantype.data = P80211ENUM_scantype_active;
		msg1.ssid.data.len = request->ssids->ssid_len;
		memcpy(msg1.ssid.data.data, request->ssids->ssid, request->ssids->ssid_len);
	} else {
		msg1.scantype.data = 0;
	}
	msg1.probedelay.data = 0;

	for (i = 0;
		(i < request->n_channels) && i < ARRAY_SIZE(prism2_channels);
		i++)
		msg1.channellist.data.data[i] =
			ieee80211_frequency_to_channel(request->channels[i]->center_freq);
	msg1.channellist.data.len = request->n_channels;

	msg1.maxchanneltime.data = 250;
	msg1.minchanneltime.data = 200;

	result = p80211req_dorequest(wlandev, (u8 *) &msg1);
	if (result) {
		err = prism2_result2err(msg1.resultcode.data);
		goto exit;
	}
	/* Now retrieve scan results */
	numbss = msg1.numbss.data;

	for (i = 0; i < numbss; i++) {
		memset(&msg2, 0, sizeof(msg2));
		msg2.msgcode = DIDmsg_dot11req_scan_results;
		msg2.bssindex.data = i;

		result = p80211req_dorequest(wlandev, (u8 *) &msg2);
		if ((result != 0) ||
		    (msg2.resultcode.data != P80211ENUM_resultcode_success)) {
			break;
		}

		ie_buf[0] = WLAN_EID_SSID;
		ie_buf[1] = msg2.ssid.data.len;
		ie_len = ie_buf[1] + 2;
		memcpy(&ie_buf[2], &(msg2.ssid.data.data), msg2.ssid.data.len);
		cfg80211_inform_bss(wiphy,
			ieee80211_get_channel(wiphy, ieee80211_dsss_chan_to_freq(msg2.dschannel.data)),
			(const u8 *) &(msg2.bssid.data.data),
			msg2.timestamp.data, msg2.capinfo.data,
			msg2.beaconperiod.data,
			ie_buf,
			ie_len,
			(msg2.signal.data - 65536) * 100, /* Conversion to signed type */
			GFP_KERNEL
		);
	}

	if (result)
		err = prism2_result2err(msg2.resultcode.data);

exit:
	cfg80211_scan_done(request, err ? 1 : 0);
	priv->scan_request = NULL;
	return err;
}
Ejemplo n.º 20
0
void orinoco_add_hostscan_results(struct orinoco_private *priv,
				  unsigned char *buf,
				  size_t len)
{
	int offset;		/* In the scan data */
	size_t atom_len;
	bool abort = false;

	switch (priv->firmware_type) {
	case FIRMWARE_TYPE_AGERE:
		atom_len = sizeof(struct agere_scan_apinfo);
		offset = 0;
		break;

	case FIRMWARE_TYPE_SYMBOL:
		/* Lack of documentation necessitates this hack.
		 * Different firmwares have 68 or 76 byte long atoms.
		 * We try modulo first.  If the length divides by both,
		 * we check what would be the channel in the second
		 * frame for a 68-byte atom.  76-byte atoms have 0 there.
		 * Valid channel cannot be 0.  */
		if (len % 76)
			atom_len = 68;
		else if (len % 68)
			atom_len = 76;
		else if (len >= 1292 && buf[68] == 0)
			atom_len = 76;
		else
			atom_len = 68;
		offset = 0;
		break;

	case FIRMWARE_TYPE_INTERSIL:
		offset = 4;
		if (priv->has_hostscan) {
			atom_len = le16_to_cpup((__le16 *)buf);
			/* Sanity check for atom_len */
			if (atom_len < sizeof(struct prism2_scan_apinfo)) {
				printk(KERN_ERR "%s: Invalid atom_len in scan "
				       "data: %zu\n", priv->ndev->name,
				       atom_len);
				abort = true;
				goto scan_abort;
			}
		} else
			atom_len = offsetof(struct prism2_scan_apinfo, atim);
		break;

	default:
		abort = true;
		goto scan_abort;
	}

	/* Check that we got an whole number of atoms */
	if ((len - offset) % atom_len) {
		printk(KERN_ERR "%s: Unexpected scan data length %zu, "
		       "atom_len %zu, offset %d\n", priv->ndev->name, len,
		       atom_len, offset);
		abort = true;
		goto scan_abort;
	}

	/* Process the entries one by one */
	for (; offset + atom_len <= len; offset += atom_len) {
		union hermes_scan_info *atom;

		atom = (union hermes_scan_info *) (buf + offset);

		orinoco_add_hostscan_result(priv, atom);
	}

 scan_abort:
	if (priv->scan_request) {
		cfg80211_scan_done(priv->scan_request, abort);
		priv->scan_request = NULL;
	}
}
Ejemplo n.º 21
0
static int prism2_scan(struct wiphy *wiphy,
		       struct cfg80211_scan_request *request)
{
	struct net_device *dev;
	struct prism2_wiphy_private *priv = wiphy_priv(wiphy);
	struct wlandevice *wlandev;
	struct p80211msg_dot11req_scan msg1;
	struct p80211msg_dot11req_scan_results msg2;
	struct cfg80211_bss *bss;
	struct cfg80211_scan_info info = {};

	int result;
	int err = 0;
	int numbss = 0;
	int i = 0;
	u8 ie_buf[46];
	int ie_len;

	if (!request)
		return -EINVAL;

	dev = request->wdev->netdev;
	wlandev = dev->ml_priv;

	if (priv->scan_request && priv->scan_request != request)
		return -EBUSY;

	if (wlandev->macmode == WLAN_MACMODE_ESS_AP) {
		netdev_err(dev, "Can't scan in AP mode\n");
		return -EOPNOTSUPP;
	}

	priv->scan_request = request;

	memset(&msg1, 0x00, sizeof(msg1));
	msg1.msgcode = DIDMSG_DOT11REQ_SCAN;
	msg1.bsstype.data = P80211ENUM_bsstype_any;

	memset(&msg1.bssid.data.data, 0xFF, sizeof(msg1.bssid.data.data));
	msg1.bssid.data.len = 6;

	if (request->n_ssids > 0) {
		msg1.scantype.data = P80211ENUM_scantype_active;
		msg1.ssid.data.len = request->ssids->ssid_len;
		memcpy(msg1.ssid.data.data,
		       request->ssids->ssid, request->ssids->ssid_len);
	} else {
		msg1.scantype.data = 0;
	}
	msg1.probedelay.data = 0;

	for (i = 0;
		(i < request->n_channels) && i < ARRAY_SIZE(prism2_channels);
		i++)
		msg1.channellist.data.data[i] =
			ieee80211_frequency_to_channel(
				request->channels[i]->center_freq);
	msg1.channellist.data.len = request->n_channels;

	msg1.maxchanneltime.data = 250;
	msg1.minchanneltime.data = 200;

	result = p80211req_dorequest(wlandev, (u8 *)&msg1);
	if (result) {
		err = prism2_result2err(msg1.resultcode.data);
		goto exit;
	}
	/* Now retrieve scan results */
	numbss = msg1.numbss.data;

	for (i = 0; i < numbss; i++) {
		int freq;

		memset(&msg2, 0, sizeof(msg2));
		msg2.msgcode = DIDMSG_DOT11REQ_SCAN_RESULTS;
		msg2.bssindex.data = i;

		result = p80211req_dorequest(wlandev, (u8 *)&msg2);
		if ((result != 0) ||
		    (msg2.resultcode.data != P80211ENUM_resultcode_success)) {
			break;
		}

		ie_buf[0] = WLAN_EID_SSID;
		ie_buf[1] = msg2.ssid.data.len;
		ie_len = ie_buf[1] + 2;
		memcpy(&ie_buf[2], &msg2.ssid.data.data, msg2.ssid.data.len);
		freq = ieee80211_channel_to_frequency(msg2.dschannel.data,
						      NL80211_BAND_2GHZ);
		bss = cfg80211_inform_bss(wiphy,
			ieee80211_get_channel(wiphy, freq),
			CFG80211_BSS_FTYPE_UNKNOWN,
			(const u8 *)&msg2.bssid.data.data,
			msg2.timestamp.data, msg2.capinfo.data,
			msg2.beaconperiod.data,
			ie_buf,
			ie_len,
			(msg2.signal.data - 65536) * 100, /* Conversion to signed type */
			GFP_KERNEL
		);

		if (!bss) {
			err = -ENOMEM;
			goto exit;
		}

		cfg80211_put_bss(wiphy, bss);
	}

	if (result)
		err = prism2_result2err(msg2.resultcode.data);

exit:
	info.aborted = !!(err);
	cfg80211_scan_done(request, &info);
	priv->scan_request = NULL;
	return err;
}
Ejemplo n.º 22
0
static void r92su_survey_done_work(struct work_struct *work)
{
	struct cfg80211_scan_request *req;
	struct r92su *r92su = container_of(work, struct r92su,
					   survey_done_work.work);

	mutex_lock(&r92su->lock);
	if (!r92su_is_open(r92su))
		goto out;

	req = r92su->scan_request;
	r92su->scan_request = NULL;

	if (req) {
		struct cfg80211_scan_info info = {
			.aborted = false,
		};
		cfg80211_scan_done(req, &info);
	}

	r92su->scanned = true;
	complete(&r92su->scan_done);
out:
	mutex_unlock(&r92su->lock);
}

static int r92su_stop(struct net_device *ndev)
{
	struct r92su *r92su = ndev->ml_priv;
	struct cfg80211_bss *tmp_bss;
	struct llist_node *node;
	int err = -EINVAL, i;

	mutex_lock(&r92su->lock);

	if (r92su_is_connected(r92su)) {
		err = __r92su_disconnect(r92su);
		WARN_ONCE(err, "disconnect failed");
	}

	r92su_set_power(r92su, false);

	if (r92su_is_initializing(r92su)) {
		err = r92su_hw_mac_deinit(r92su);
		WARN_ONCE(err, "failed to deinitilize MAC");
	}

	if (r92su_is_initializing(r92su))
		r92su_set_state(r92su, R92SU_STOP);

	if (r92su->scan_request) {
		struct cfg80211_scan_info info = {
			.aborted = true,
		};
		cfg80211_scan_done(r92su->scan_request, &info);
	}

	tmp_bss = r92su->want_connect_bss;
	r92su->want_connect_bss = NULL;
	r92su_bss_free(r92su, tmp_bss);

	r92su->scan_request = NULL;

	for (i = 0; i < MAX_STA; i++)
		r92su_sta_del(r92su, i);

	mutex_unlock(&r92su->lock);

	cancel_delayed_work_sync(&r92su->survey_done_work);
	cancel_delayed_work_sync(&r92su->service_work);
	cancel_work_sync(&r92su->add_bss_work);
	cancel_work_sync(&r92su->connect_bss_work);
	cancel_work_sync(&r92su->disconnect_work);

	node = llist_del_all(&r92su->add_bss_list);
	while (node) {
		struct r92su_add_bss *bss_priv =
			llist_entry(node, struct r92su_add_bss, head);
		node = ACCESS_ONCE(node->next);
		kfree(bss_priv);
	}

	/* wait for keys and stas to be freed */
	synchronize_rcu();
	rcu_barrier();

	return err;
}

static netdev_tx_t r92su_start_xmit(struct sk_buff *skb,
				    struct net_device *ndev)
{
	struct r92su *r92su = ndev->ml_priv;

	switch (r92su->wdev.iftype) {
	case NL80211_IFTYPE_STATION:
	case NL80211_IFTYPE_ADHOC:
		if (skb->len >= ETH_ALEN + ETH_ALEN + 2)
			r92su_tx(r92su, skb, false);
		break;

	case NL80211_IFTYPE_MONITOR:
		r92su_tx_monitor(r92su, skb);
		break;

	default:
		dev_kfree_skb_any(skb);
		break;
	}
	return NETDEV_TX_OK;
}

static const struct net_device_ops r92su_netdevice_ops = {
	.ndo_open = r92su_open,
	.ndo_stop = r92su_stop,
	.ndo_start_xmit = r92su_start_xmit,
	.ndo_set_mac_address = eth_mac_addr,
	.ndo_set_rx_mode = r92su_set_rx_mode,
	.ndo_change_mtu = eth_change_mtu,
	.ndo_validate_addr = eth_validate_addr,
};

static void *devm_dup(struct device *dev, void *src, size_t len)
{
	void *tmp;

	tmp = devm_kzalloc(dev, len, GFP_KERNEL);
	if (tmp)
		memcpy(tmp, src, len);
	return tmp;
}

static int r92su_init_band(struct r92su *r92su)
{
	struct ieee80211_supported_band *band;

	band = &r92su->band_2GHZ;
	band->channels = devm_dup(&r92su->wdev.wiphy->dev,
		r92su_channeltable, sizeof(r92su_channeltable));
	if (!band->channels)
		return -ENOMEM;

	band->bitrates = devm_dup(&r92su->wdev.wiphy->dev,
		r92su_ratetable, sizeof(r92su_ratetable));
	if (!band->bitrates)
		return -ENOMEM;

	band->n_channels = ARRAY_SIZE(r92su_channeltable);
	band->n_bitrates = ARRAY_SIZE(r92su_ratetable);

	memcpy(&band->ht_cap, &r92su_ht_info, sizeof(r92su_ht_info));
	band->ht_cap.ht_supported = !r92su->disable_ht;

	switch (r92su->rf_type) {
	case R92SU_1T1R:
		/* nothing needs to be done. The default ht_cap
		 * contains all the necessary bits for just 1T1R
		 * devices */
		break;

	case R92SU_1T2R:
	case R92SU_2T2R:
		band->ht_cap.mcs.rx_mask[1] = 0xff;
		band->ht_cap.mcs.rx_highest = cpu_to_le16(300);
		break;
	}

	r92su->wdev.wiphy->bands[NL80211_BAND_2GHZ] = &r92su->band_2GHZ;

	return 0;
}

static const struct ieee80211_txrx_stypes
r92su_default_mgmt_stypes[NUM_NL80211_IFTYPES] = {
	[NL80211_IFTYPE_ADHOC] = {
		.tx = 0xffff,
		.rx = 0,
	},
Ejemplo n.º 23
0
void wil_p2p_search_expired(struct work_struct *work)
{
	struct wil_p2p_info *p2p = container_of(work,
			struct wil_p2p_info, discovery_expired_work);
	struct wil6210_priv *wil = container_of(p2p,
			struct wil6210_priv, p2p);
	u8 started;

	wil_dbg_misc(wil, "p2p_search_expired\n");

	mutex_lock(&wil->mutex);
	started = wil_p2p_stop_discovery(wil);
	mutex_unlock(&wil->mutex);

	if (started) {
		struct cfg80211_scan_info info = {
			.aborted = false,
		};

		mutex_lock(&wil->p2p_wdev_mutex);
		if (wil->scan_request) {
			cfg80211_scan_done(wil->scan_request, &info);
			wil->scan_request = NULL;
			wil->radio_wdev = wil->wdev;
		}
		mutex_unlock(&wil->p2p_wdev_mutex);
	}
}

void wil_p2p_delayed_listen_work(struct work_struct *work)
{
	struct wil_p2p_info *p2p = container_of(work,
			struct wil_p2p_info, delayed_listen_work);
	struct wil6210_priv *wil = container_of(p2p,
			struct wil6210_priv, p2p);
	int rc;

	mutex_lock(&wil->mutex);

	wil_dbg_misc(wil, "Checking delayed p2p listen\n");
	if (!p2p->discovery_started || !p2p->pending_listen_wdev)
		goto out;

	mutex_lock(&wil->p2p_wdev_mutex);
	if (wil->scan_request) {
		/* another scan started, wait again... */
		mutex_unlock(&wil->p2p_wdev_mutex);
		goto out;
	}
	mutex_unlock(&wil->p2p_wdev_mutex);

	rc = wil_p2p_start_listen(wil);

	mutex_lock(&wil->p2p_wdev_mutex);
	if (rc) {
		cfg80211_remain_on_channel_expired(p2p->pending_listen_wdev,
						   p2p->cookie,
						   &p2p->listen_chan,
						   GFP_KERNEL);
		wil->radio_wdev = wil->wdev;
	} else {
		cfg80211_ready_on_channel(p2p->pending_listen_wdev, p2p->cookie,
					  &p2p->listen_chan,
					  p2p->listen_duration, GFP_KERNEL);
		wil->radio_wdev = p2p->pending_listen_wdev;
	}
	p2p->pending_listen_wdev = NULL;
	mutex_unlock(&wil->p2p_wdev_mutex);

out:
	mutex_unlock(&wil->mutex);
}

void wil_p2p_stop_radio_operations(struct wil6210_priv *wil)
{
	struct wil_p2p_info *p2p = &wil->p2p;
	struct cfg80211_scan_info info = {
		.aborted = true,
	};

	lockdep_assert_held(&wil->mutex);
	lockdep_assert_held(&wil->p2p_wdev_mutex);

	if (wil->radio_wdev != wil->p2p_wdev)
		goto out;

	if (!p2p->discovery_started) {
		/* Regular scan on the p2p device */
		if (wil->scan_request &&
		    wil->scan_request->wdev == wil->p2p_wdev)
			wil_abort_scan(wil, true);
		goto out;
	}

	/* Search or listen on p2p device */
	mutex_unlock(&wil->p2p_wdev_mutex);
	wil_p2p_stop_discovery(wil);
	mutex_lock(&wil->p2p_wdev_mutex);

	if (wil->scan_request) {
		/* search */
		cfg80211_scan_done(wil->scan_request, &info);
		wil->scan_request = NULL;
	} else {
		/* listen */
		cfg80211_remain_on_channel_expired(wil->radio_wdev,
						   p2p->cookie,
						   &p2p->listen_chan,
						   GFP_KERNEL);
	}

out:
	wil->radio_wdev = wil->wdev;
}