Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 85a9994a authored by Luciano Coelho's avatar Luciano Coelho Committed by John W. Linville
Browse files

cfg80211/mac80211: avoid bounce back mac->cfg->mac on sched_scan_stopped



When sched_scan_stopped was called by the driver, mac80211 calls
cfg80211, which in turn was calling mac80211 back with a flag
"driver_initiated".  This flag was used so that mac80211 would do the
necessary cleanup but would not call the driver.  This was enough to
prevent the bounce back between the driver and mac80211, but not
between mac80211 and cfg80211.

To fix this, we now do the cleanup in mac80211 before calling
cfg80211.  To help with locking issues, the workqueue was moved from
cfg80211 to mac80211.

Reported-by: default avatarJohannes Berg <johannes@sipsolutions.net>
Signed-off-by: default avatarLuciano Coelho <coelho@ti.com>
Signed-off-by: default avatarJohn W. Linville <linville@tuxdriver.com>
parent a3836e02
Loading
Loading
Loading
Loading
+1 −2
Original line number Original line Diff line number Diff line
@@ -1515,8 +1515,7 @@ struct cfg80211_ops {
	int	(*sched_scan_start)(struct wiphy *wiphy,
	int	(*sched_scan_start)(struct wiphy *wiphy,
				struct net_device *dev,
				struct net_device *dev,
				struct cfg80211_sched_scan_request *request);
				struct cfg80211_sched_scan_request *request);
	int	(*sched_scan_stop)(struct wiphy *wiphy, struct net_device *dev,
	int	(*sched_scan_stop)(struct wiphy *wiphy, struct net_device *dev);
				   bool driver_initiated);
};
};


/*
/*
+2 −3
Original line number Original line Diff line number Diff line
@@ -1372,15 +1372,14 @@ ieee80211_sched_scan_start(struct wiphy *wiphy,
}
}


static int
static int
ieee80211_sched_scan_stop(struct wiphy *wiphy, struct net_device *dev,
ieee80211_sched_scan_stop(struct wiphy *wiphy, struct net_device *dev)
			  bool driver_initiated)
{
{
	struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
	struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);


	if (!sdata->local->ops->sched_scan_stop)
	if (!sdata->local->ops->sched_scan_stop)
		return -EOPNOTSUPP;
		return -EOPNOTSUPP;


	return ieee80211_request_sched_scan_stop(sdata, driver_initiated);
	return ieee80211_request_sched_scan_stop(sdata);
}
}


static int ieee80211_auth(struct wiphy *wiphy, struct net_device *dev,
static int ieee80211_auth(struct wiphy *wiphy, struct net_device *dev,
+3 −2
Original line number Original line Diff line number Diff line
@@ -849,6 +849,7 @@ struct ieee80211_local {


	bool sched_scanning;
	bool sched_scanning;
	struct ieee80211_sched_scan_ies sched_scan_ies;
	struct ieee80211_sched_scan_ies sched_scan_ies;
	struct work_struct sched_scan_stopped_work;


	unsigned long leave_oper_channel_time;
	unsigned long leave_oper_channel_time;
	enum mac80211_scan_state next_scan_state;
	enum mac80211_scan_state next_scan_state;
@@ -1160,8 +1161,8 @@ void ieee80211_rx_bss_put(struct ieee80211_local *local,
/* scheduled scan handling */
/* scheduled scan handling */
int ieee80211_request_sched_scan_start(struct ieee80211_sub_if_data *sdata,
int ieee80211_request_sched_scan_start(struct ieee80211_sub_if_data *sdata,
				       struct cfg80211_sched_scan_request *req);
				       struct cfg80211_sched_scan_request *req);
int ieee80211_request_sched_scan_stop(struct ieee80211_sub_if_data *sdata,
int ieee80211_request_sched_scan_stop(struct ieee80211_sub_if_data *sdata);
				      bool driver_initiated);
void ieee80211_sched_scan_stopped_work(struct work_struct *work);


/* off-channel helpers */
/* off-channel helpers */
bool ieee80211_cfg_on_oper_channel(struct ieee80211_local *local);
bool ieee80211_cfg_on_oper_channel(struct ieee80211_local *local);
+3 −0
Original line number Original line Diff line number Diff line
@@ -652,6 +652,9 @@ struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len,
	setup_timer(&local->dynamic_ps_timer,
	setup_timer(&local->dynamic_ps_timer,
		    ieee80211_dynamic_ps_timer, (unsigned long) local);
		    ieee80211_dynamic_ps_timer, (unsigned long) local);


	INIT_WORK(&local->sched_scan_stopped_work,
		  ieee80211_sched_scan_stopped_work);

	sta_info_init(local);
	sta_info_init(local);


	for (i = 0; i < IEEE80211_MAX_QUEUES; i++) {
	for (i = 0; i < IEEE80211_MAX_QUEUES; i++) {
+27 −6
Original line number Original line Diff line number Diff line
@@ -902,8 +902,7 @@ int ieee80211_request_sched_scan_start(struct ieee80211_sub_if_data *sdata,
	return ret;
	return ret;
}
}


int ieee80211_request_sched_scan_stop(struct ieee80211_sub_if_data *sdata,
int ieee80211_request_sched_scan_stop(struct ieee80211_sub_if_data *sdata)
				      bool driver_initiated)
{
{
	struct ieee80211_local *local = sdata->local;
	struct ieee80211_local *local = sdata->local;
	int ret = 0, i;
	int ret = 0, i;
@@ -919,11 +918,9 @@ int ieee80211_request_sched_scan_stop(struct ieee80211_sub_if_data *sdata,
		for (i = 0; i < IEEE80211_NUM_BANDS; i++)
		for (i = 0; i < IEEE80211_NUM_BANDS; i++)
			kfree(local->sched_scan_ies.ie[i]);
			kfree(local->sched_scan_ies.ie[i]);


		if (!driver_initiated)
		drv_sched_scan_stop(local, sdata);
		drv_sched_scan_stop(local, sdata);
		local->sched_scanning = false;
		local->sched_scanning = false;
	}
	}

out:
out:
	mutex_unlock(&sdata->local->mtx);
	mutex_unlock(&sdata->local->mtx);


@@ -940,12 +937,36 @@ void ieee80211_sched_scan_results(struct ieee80211_hw *hw)
}
}
EXPORT_SYMBOL(ieee80211_sched_scan_results);
EXPORT_SYMBOL(ieee80211_sched_scan_results);


void ieee80211_sched_scan_stopped_work(struct work_struct *work)
{
	struct ieee80211_local *local =
		container_of(work, struct ieee80211_local,
			     sched_scan_stopped_work);
	int i;

	mutex_lock(&local->mtx);

	if (!local->sched_scanning) {
		mutex_unlock(&local->mtx);
		return;
	}

	for (i = 0; i < IEEE80211_NUM_BANDS; i++)
		kfree(local->sched_scan_ies.ie[i]);

	local->sched_scanning = false;

	mutex_unlock(&local->mtx);

	cfg80211_sched_scan_stopped(local->hw.wiphy);
}

void ieee80211_sched_scan_stopped(struct ieee80211_hw *hw)
void ieee80211_sched_scan_stopped(struct ieee80211_hw *hw)
{
{
	struct ieee80211_local *local = hw_to_local(hw);
	struct ieee80211_local *local = hw_to_local(hw);


	trace_api_sched_scan_stopped(local);
	trace_api_sched_scan_stopped(local);


	cfg80211_sched_scan_stopped(hw->wiphy);
	ieee80211_queue_work(&local->hw, &local->sched_scan_stopped_work);
}
}
EXPORT_SYMBOL(ieee80211_sched_scan_stopped);
EXPORT_SYMBOL(ieee80211_sched_scan_stopped);
Loading