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

Commit 4a6967b8 authored by Johannes Berg's avatar Johannes Berg Committed by John W. Linville
Browse files

mwl8k: convert to new station add/remove callbacks



This converts mwl8k to use the new station
add/remove callbacks instead of using the
old sta_notify callback.

The new callbacks can sleep, so a lot of
code can be removed now.

Signed-off-by: default avatarJohannes Berg <johannes@sipsolutions.net>
Acked-by: default avatarLennert Buytenhek <buytenh@wantstofly.org>
Signed-off-by: default avatarJohn W. Linville <linville@tuxdriver.com>
parent 4ca77860
Loading
Loading
Loading
Loading
+22 −84
Original line number Diff line number Diff line
@@ -188,10 +188,6 @@ struct mwl8k_priv {
	bool sniffer_enabled;
	bool wmm_enabled;

	struct work_struct sta_notify_worker;
	spinlock_t sta_notify_list_lock;
	struct list_head sta_notify_list;

	/* XXX need to convert this to handle multiple interfaces */
	bool capture_beacon;
	u8 capture_bssid[ETH_ALEN];
@@ -3706,90 +3702,36 @@ static int mwl8k_set_rts_threshold(struct ieee80211_hw *hw, u32 value)
	return mwl8k_cmd_set_rts_threshold(hw, value);
}

struct mwl8k_sta_notify_item
{
	struct list_head list;
	struct ieee80211_vif *vif;
	enum sta_notify_cmd cmd;
	struct ieee80211_sta sta;
};

static void
mwl8k_do_sta_notify(struct ieee80211_hw *hw, struct mwl8k_sta_notify_item *s)
static int mwl8k_sta_remove(struct ieee80211_hw *hw,
			    struct ieee80211_vif *vif,
			    struct ieee80211_sta *sta)
{
	struct mwl8k_priv *priv = hw->priv;

	/*
	 * STA firmware uses UPDATE_STADB, AP firmware uses SET_NEW_STN.
	 */
	if (!priv->ap_fw && s->cmd == STA_NOTIFY_ADD) {
		int rc;

		rc = mwl8k_cmd_update_stadb_add(hw, s->vif, &s->sta);
		if (rc >= 0) {
			struct ieee80211_sta *sta;

			rcu_read_lock();
			sta = ieee80211_find_sta(s->vif, s->sta.addr);
			if (sta != NULL)
				MWL8K_STA(sta)->peer_id = rc;
			rcu_read_unlock();
		}
	} else if (!priv->ap_fw && s->cmd == STA_NOTIFY_REMOVE) {
		mwl8k_cmd_update_stadb_del(hw, s->vif, s->sta.addr);
	} else if (priv->ap_fw && s->cmd == STA_NOTIFY_ADD) {
		mwl8k_cmd_set_new_stn_add(hw, s->vif, &s->sta);
	} else if (priv->ap_fw && s->cmd == STA_NOTIFY_REMOVE) {
		mwl8k_cmd_set_new_stn_del(hw, s->vif, s->sta.addr);
	}
}

static void mwl8k_sta_notify_worker(struct work_struct *work)
{
	struct mwl8k_priv *priv =
		container_of(work, struct mwl8k_priv, sta_notify_worker);
	struct ieee80211_hw *hw = priv->hw;

	spin_lock_bh(&priv->sta_notify_list_lock);
	while (!list_empty(&priv->sta_notify_list)) {
		struct mwl8k_sta_notify_item *s;

		s = list_entry(priv->sta_notify_list.next,
			       struct mwl8k_sta_notify_item, list);
		list_del(&s->list);

		spin_unlock_bh(&priv->sta_notify_list_lock);

		mwl8k_do_sta_notify(hw, s);
		kfree(s);

		spin_lock_bh(&priv->sta_notify_list_lock);
	}
	spin_unlock_bh(&priv->sta_notify_list_lock);
	if (priv->ap_fw)
		return mwl8k_cmd_set_new_stn_del(hw, vif, sta->addr);
	else
		return mwl8k_cmd_update_stadb_del(hw, vif, sta->addr);
}

static void
mwl8k_sta_notify(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
		 enum sta_notify_cmd cmd, struct ieee80211_sta *sta)
static int mwl8k_sta_add(struct ieee80211_hw *hw,
			 struct ieee80211_vif *vif,
			 struct ieee80211_sta *sta)
{
	struct mwl8k_priv *priv = hw->priv;
	struct mwl8k_sta_notify_item *s;

	if (cmd != STA_NOTIFY_ADD && cmd != STA_NOTIFY_REMOVE)
		return;

	s = kmalloc(sizeof(*s), GFP_ATOMIC);
	if (s != NULL) {
		s->vif = vif;
		s->cmd = cmd;
		s->sta = *sta;
	int ret;

		spin_lock_bh(&priv->sta_notify_list_lock);
		list_add_tail(&s->list, &priv->sta_notify_list);
		spin_unlock_bh(&priv->sta_notify_list_lock);
	if (!priv->ap_fw) {
		ret = mwl8k_cmd_update_stadb_add(hw, vif, sta);
		if (ret >= 0) {
			MWL8K_STA(sta)->peer_id = ret;
			return 0;
		}

		ieee80211_queue_work(hw, &priv->sta_notify_worker);
		return ret;
	}

	return mwl8k_cmd_set_new_stn_add(hw, vif, sta);
}

static int mwl8k_conf_tx(struct ieee80211_hw *hw, u16 queue,
@@ -3849,7 +3791,8 @@ static const struct ieee80211_ops mwl8k_ops = {
	.prepare_multicast	= mwl8k_prepare_multicast,
	.configure_filter	= mwl8k_configure_filter,
	.set_rts_threshold	= mwl8k_set_rts_threshold,
	.sta_notify		= mwl8k_sta_notify,
	.sta_add		= mwl8k_sta_add,
	.sta_remove		= mwl8k_sta_remove,
	.conf_tx		= mwl8k_conf_tx,
	.get_stats		= mwl8k_get_stats,
	.ampdu_action		= mwl8k_ampdu_action,
@@ -4051,11 +3994,6 @@ static int __devinit mwl8k_probe(struct pci_dev *pdev,
	priv->radio_on = 0;
	priv->radio_short_preamble = 0;

	/* Station database handling */
	INIT_WORK(&priv->sta_notify_worker, mwl8k_sta_notify_worker);
	spin_lock_init(&priv->sta_notify_list_lock);
	INIT_LIST_HEAD(&priv->sta_notify_list);

	/* Finalize join worker */
	INIT_WORK(&priv->finalize_join_worker, mwl8k_finalize_join_worker);