Skip to content

Commit

Permalink
mac80211: revamp beacon configuration
Browse files Browse the repository at this point in the history
This patch changes mac80211's beacon configuration handling
to never pass skbs to the driver directly but rather always
require the driver to use ieee80211_beacon_get(). Additionally,
it introduces "change flags" on the config_interface() call
to enable drivers to figure out what is changing. Finally, it
removes the beacon_update() driver callback in favour of
having IBSS beacon delivered by ieee80211_beacon_get() as well.

Signed-off-by: Johannes Berg <johannes@sipsolutions.net>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
  • Loading branch information
Johannes Berg authored and John W. Linville committed Jul 14, 2008
1 parent f3947e2 commit 9d139c8
Show file tree
Hide file tree
Showing 21 changed files with 226 additions and 248 deletions.
13 changes: 12 additions & 1 deletion drivers/net/wireless/ath5k/base.c
Original file line number Diff line number Diff line change
Expand Up @@ -207,7 +207,6 @@ static struct ieee80211_ops ath5k_hw_ops = {
.get_tx_stats = ath5k_get_tx_stats,
.get_tsf = ath5k_get_tsf,
.reset_tsf = ath5k_reset_tsf,
.beacon_update = ath5k_beacon_update,
};

/*
Expand Down Expand Up @@ -2785,6 +2784,18 @@ ath5k_config_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
* a clean way of letting us retrieve this yet. */
ath5k_hw_set_associd(ah, ah->ah_bssid, 0);
}

if (conf->changed & IEEE80211_IFCC_BEACON &&
vif->type == IEEE80211_IF_TYPE_IBSS) {
struct sk_buff *beacon = ieee80211_beacon_get(hw, vif);
if (!beacon) {
ret = -ENOMEM;
goto unlock;
}
/* call old handler for now */
ath5k_beacon_update(hw, beacon);
}

mutex_unlock(&sc->lock);

return ath5k_reset(hw);
Expand Down
48 changes: 20 additions & 28 deletions drivers/net/wireless/b43/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -1675,14 +1675,24 @@ static void b43_beacon_update_trigger_work(struct work_struct *work)

/* Asynchronously update the packet templates in template RAM.
* Locking: Requires wl->irq_lock to be locked. */
static void b43_update_templates(struct b43_wl *wl, struct sk_buff *beacon)
static void b43_update_templates(struct b43_wl *wl)
{
struct sk_buff *beacon;

/* This is the top half of the ansynchronous beacon update.
* The bottom half is the beacon IRQ.
* Beacon update must be asynchronous to avoid sending an
* invalid beacon. This can happen for example, if the firmware
* transmits a beacon while we are updating it. */

/* We could modify the existing beacon and set the aid bit in
* the TIM field, but that would probably require resizing and
* moving of data within the beacon template.
* Simply request a new beacon and let mac80211 do the hard work. */
beacon = ieee80211_beacon_get(wl->hw, wl->vif);
if (unlikely(!beacon))
return;

if (wl->current_beacon)
dev_kfree_skb_any(wl->current_beacon);
wl->current_beacon = beacon;
Expand Down Expand Up @@ -3645,10 +3655,14 @@ static int b43_op_config_interface(struct ieee80211_hw *hw,
if (b43_status(dev) >= B43_STAT_INITIALIZED) {
if (b43_is_mode(wl, IEEE80211_IF_TYPE_AP) ||
b43_is_mode(wl, IEEE80211_IF_TYPE_MESH_POINT)) {
B43_WARN_ON(conf->type != wl->if_type);
b43_set_ssid(dev, conf->ssid, conf->ssid_len);
if (conf->beacon)
b43_update_templates(wl, conf->beacon);
B43_WARN_ON(vif->type != wl->if_type);
if (conf->changed & IEEE80211_IFCC_SSID)
b43_set_ssid(dev, conf->ssid, conf->ssid_len);
if (conf->changed & IEEE80211_IFCC_BEACON)
b43_update_templates(wl);
} else if (b43_is_mode(wl, IEEE80211_IF_TYPE_IBSS)) {
if (conf->changed & IEEE80211_IFCC_BEACON)
b43_update_templates(wl);
}
b43_write_mac_bssid_templates(dev);
}
Expand Down Expand Up @@ -4334,33 +4348,12 @@ static int b43_op_set_retry_limit(struct ieee80211_hw *hw,
}

static int b43_op_beacon_set_tim(struct ieee80211_hw *hw, int aid, int set)
{
struct b43_wl *wl = hw_to_b43_wl(hw);
struct sk_buff *beacon;
unsigned long flags;

/* We could modify the existing beacon and set the aid bit in
* the TIM field, but that would probably require resizing and
* moving of data within the beacon template.
* Simply request a new beacon and let mac80211 do the hard work. */
beacon = ieee80211_beacon_get(hw, wl->vif);
if (unlikely(!beacon))
return -ENOMEM;
spin_lock_irqsave(&wl->irq_lock, flags);
b43_update_templates(wl, beacon);
spin_unlock_irqrestore(&wl->irq_lock, flags);

return 0;
}

static int b43_op_ibss_beacon_update(struct ieee80211_hw *hw,
struct sk_buff *beacon)
{
struct b43_wl *wl = hw_to_b43_wl(hw);
unsigned long flags;

spin_lock_irqsave(&wl->irq_lock, flags);
b43_update_templates(wl, beacon);
b43_update_templates(wl);
spin_unlock_irqrestore(&wl->irq_lock, flags);

return 0;
Expand Down Expand Up @@ -4391,7 +4384,6 @@ static const struct ieee80211_ops b43_hw_ops = {
.stop = b43_op_stop,
.set_retry_limit = b43_op_set_retry_limit,
.set_tim = b43_op_beacon_set_tim,
.beacon_update = b43_op_ibss_beacon_update,
.sta_notify = b43_op_sta_notify,
};

Expand Down
45 changes: 17 additions & 28 deletions drivers/net/wireless/b43legacy/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -1138,14 +1138,22 @@ static void b43legacy_write_probe_resp_template(struct b43legacy_wldev *dev,

/* Asynchronously update the packet templates in template RAM.
* Locking: Requires wl->irq_lock to be locked. */
static void b43legacy_update_templates(struct b43legacy_wl *wl,
struct sk_buff *beacon)
static void b43legacy_update_templates(struct b43legacy_wl *wl)
{
struct sk_buff *beacon;
/* This is the top half of the ansynchronous beacon update. The bottom
* half is the beacon IRQ. Beacon update must be asynchronous to avoid
* sending an invalid beacon. This can happen for example, if the
* firmware transmits a beacon while we are updating it. */

/* We could modify the existing beacon and set the aid bit in the TIM
* field, but that would probably require resizing and moving of data
* within the beacon template. Simply request a new beacon and let
* mac80211 do the hard work. */
beacon = ieee80211_beacon_get(wl->hw, wl->vif);
if (unlikely(!beacon))
return;

if (wl->current_beacon)
dev_kfree_skb_any(wl->current_beacon);
wl->current_beacon = beacon;
Expand Down Expand Up @@ -2727,10 +2735,13 @@ static int b43legacy_op_config_interface(struct ieee80211_hw *hw,
memset(wl->bssid, 0, ETH_ALEN);
if (b43legacy_status(dev) >= B43legacy_STAT_INITIALIZED) {
if (b43legacy_is_mode(wl, IEEE80211_IF_TYPE_AP)) {
B43legacy_WARN_ON(conf->type != IEEE80211_IF_TYPE_AP);
B43legacy_WARN_ON(vif->type != IEEE80211_IF_TYPE_AP);
b43legacy_set_ssid(dev, conf->ssid, conf->ssid_len);
if (conf->beacon)
b43legacy_update_templates(wl, conf->beacon);
if (conf->changed & IEEE80211_IFCC_BEACON)
b43legacy_update_templates(wl);
} else if (b43legacy_is_mode(wl, IEEE80211_IF_TYPE_IBSS)) {
if (conf->changed & IEEE80211_IFCC_BEACON)
b43legacy_update_templates(wl);
}
b43legacy_write_mac_bssid_templates(dev);
}
Expand Down Expand Up @@ -3394,33 +3405,12 @@ static int b43legacy_op_set_retry_limit(struct ieee80211_hw *hw,

static int b43legacy_op_beacon_set_tim(struct ieee80211_hw *hw,
int aid, int set)
{
struct b43legacy_wl *wl = hw_to_b43legacy_wl(hw);
struct sk_buff *beacon;
unsigned long flags;

/* We could modify the existing beacon and set the aid bit in the TIM
* field, but that would probably require resizing and moving of data
* within the beacon template. Simply request a new beacon and let
* mac80211 do the hard work. */
beacon = ieee80211_beacon_get(hw, wl->vif);
if (unlikely(!beacon))
return -ENOMEM;
spin_lock_irqsave(&wl->irq_lock, flags);
b43legacy_update_templates(wl, beacon);
spin_unlock_irqrestore(&wl->irq_lock, flags);

return 0;
}

static int b43legacy_op_ibss_beacon_update(struct ieee80211_hw *hw,
struct sk_buff *beacon)
{
struct b43legacy_wl *wl = hw_to_b43legacy_wl(hw);
unsigned long flags;

spin_lock_irqsave(&wl->irq_lock, flags);
b43legacy_update_templates(wl, beacon);
b43legacy_update_templates(wl);
spin_unlock_irqrestore(&wl->irq_lock, flags);

return 0;
Expand All @@ -3440,7 +3430,6 @@ static const struct ieee80211_ops b43legacy_hw_ops = {
.stop = b43legacy_op_stop,
.set_retry_limit = b43legacy_op_set_retry_limit,
.set_tim = b43legacy_op_beacon_set_tim,
.beacon_update = b43legacy_op_ibss_beacon_update,
};

/* Hard-reset the chip. Do not call this directly.
Expand Down
19 changes: 16 additions & 3 deletions drivers/net/wireless/iwlwifi/iwl3945-base.c
Original file line number Diff line number Diff line change
Expand Up @@ -6907,6 +6907,9 @@ static void iwl3945_config_ap(struct iwl3945_priv *priv)
* clear sta table, add BCAST sta... */
}

/* temporary */
static int iwl3945_mac_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb);

static int iwl3945_mac_config_interface(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
struct ieee80211_if_conf *conf)
Expand All @@ -6924,10 +6927,21 @@ static int iwl3945_mac_config_interface(struct ieee80211_hw *hw,
return 0;
}

/* handle this temporarily here */
if (priv->iw_mode == IEEE80211_IF_TYPE_IBSS &&
conf->changed & IEEE80211_IFCC_BEACON) {
struct sk_buff *beacon = ieee80211_beacon_get(hw, vif);
if (!beacon)
return -ENOMEM;
rc = iwl3945_mac_beacon_update(hw, beacon);
if (rc)
return rc;
}

/* XXX: this MUST use conf->mac_addr */

if ((priv->iw_mode == IEEE80211_IF_TYPE_AP) &&
(!conf->beacon || !conf->ssid_len)) {
(!conf->ssid_len)) {
IWL_DEBUG_MAC80211
("Leaving in AP mode because HostAPD is not ready.\n");
return 0;
Expand Down Expand Up @@ -6959,7 +6973,7 @@ static int iwl3945_mac_config_interface(struct ieee80211_hw *hw,
if (priv->ibss_beacon)
dev_kfree_skb(priv->ibss_beacon);

priv->ibss_beacon = conf->beacon;
priv->ibss_beacon = ieee80211_beacon_get(hw, vif);
}

if (iwl3945_is_rfkill(priv))
Expand Down Expand Up @@ -7940,7 +7954,6 @@ static struct ieee80211_ops iwl3945_hw_ops = {
.conf_tx = iwl3945_mac_conf_tx,
.get_tsf = iwl3945_mac_get_tsf,
.reset_tsf = iwl3945_mac_reset_tsf,
.beacon_update = iwl3945_mac_beacon_update,
.hw_scan = iwl3945_mac_hw_scan
};

Expand Down
18 changes: 15 additions & 3 deletions drivers/net/wireless/iwlwifi/iwl4965-base.c
Original file line number Diff line number Diff line change
Expand Up @@ -2912,6 +2912,9 @@ static void iwl4965_config_ap(struct iwl_priv *priv)
* clear sta table, add BCAST sta... */
}

/* temporary */
static int iwl4965_mac_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb);

static int iwl4965_mac_config_interface(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
struct ieee80211_if_conf *conf)
Expand All @@ -2929,8 +2932,18 @@ static int iwl4965_mac_config_interface(struct ieee80211_hw *hw,
return 0;
}

if (priv->iw_mode == IEEE80211_IF_TYPE_IBSS &&
conf->changed & IEEE80211_IFCC_BEACON) {
struct sk_buff *beacon = ieee80211_beacon_get(hw, vif);
if (!beacon)
return -ENOMEM;
rc = iwl4965_mac_beacon_update(hw, beacon);
if (rc)
return rc;
}

if ((priv->iw_mode == IEEE80211_IF_TYPE_AP) &&
(!conf->beacon || !conf->ssid_len)) {
(!conf->ssid_len)) {
IWL_DEBUG_MAC80211
("Leaving in AP mode because HostAPD is not ready.\n");
return 0;
Expand Down Expand Up @@ -2962,7 +2975,7 @@ static int iwl4965_mac_config_interface(struct ieee80211_hw *hw,
if (priv->ibss_beacon)
dev_kfree_skb(priv->ibss_beacon);

priv->ibss_beacon = conf->beacon;
priv->ibss_beacon = ieee80211_beacon_get(hw, vif);
}

if (iwl_is_rfkill(priv))
Expand Down Expand Up @@ -4090,7 +4103,6 @@ static struct ieee80211_ops iwl4965_hw_ops = {
.get_tx_stats = iwl4965_mac_get_tx_stats,
.conf_tx = iwl4965_mac_conf_tx,
.reset_tsf = iwl4965_mac_reset_tsf,
.beacon_update = iwl4965_mac_beacon_update,
.bss_info_changed = iwl4965_bss_info_changed,
.ampdu_action = iwl4965_mac_ampdu_action,
.hw_scan = iwl4965_mac_hw_scan
Expand Down
2 changes: 1 addition & 1 deletion drivers/net/wireless/rt2x00/rt2400pci.c
Original file line number Diff line number Diff line change
Expand Up @@ -1581,7 +1581,6 @@ static const struct ieee80211_ops rt2400pci_mac80211_ops = {
.conf_tx = rt2400pci_conf_tx,
.get_tx_stats = rt2x00mac_get_tx_stats,
.get_tsf = rt2400pci_get_tsf,
.beacon_update = rt2400pci_beacon_update,
.tx_last_beacon = rt2400pci_tx_last_beacon,
};

Expand All @@ -1601,6 +1600,7 @@ static const struct rt2x00lib_ops rt2400pci_rt2x00_ops = {
.write_tx_data = rt2x00pci_write_tx_data,
.kick_tx_queue = rt2400pci_kick_tx_queue,
.fill_rxdone = rt2400pci_fill_rxdone,
.beacon_update = rt2400pci_beacon_update,
.config_filter = rt2400pci_config_filter,
.config_intf = rt2400pci_config_intf,
.config_erp = rt2400pci_config_erp,
Expand Down
2 changes: 1 addition & 1 deletion drivers/net/wireless/rt2x00/rt2500pci.c
Original file line number Diff line number Diff line change
Expand Up @@ -1875,7 +1875,6 @@ static const struct ieee80211_ops rt2500pci_mac80211_ops = {
.conf_tx = rt2x00mac_conf_tx,
.get_tx_stats = rt2x00mac_get_tx_stats,
.get_tsf = rt2500pci_get_tsf,
.beacon_update = rt2500pci_beacon_update,
.tx_last_beacon = rt2500pci_tx_last_beacon,
};

Expand All @@ -1895,6 +1894,7 @@ static const struct rt2x00lib_ops rt2500pci_rt2x00_ops = {
.write_tx_data = rt2x00pci_write_tx_data,
.kick_tx_queue = rt2500pci_kick_tx_queue,
.fill_rxdone = rt2500pci_fill_rxdone,
.beacon_update = rt2500pci_beacon_update,
.config_filter = rt2500pci_config_filter,
.config_intf = rt2500pci_config_intf,
.config_erp = rt2500pci_config_erp,
Expand Down
2 changes: 1 addition & 1 deletion drivers/net/wireless/rt2x00/rt2500usb.c
Original file line number Diff line number Diff line change
Expand Up @@ -1775,7 +1775,6 @@ static const struct ieee80211_ops rt2500usb_mac80211_ops = {
.bss_info_changed = rt2x00mac_bss_info_changed,
.conf_tx = rt2x00mac_conf_tx,
.get_tx_stats = rt2x00mac_get_tx_stats,
.beacon_update = rt2500usb_beacon_update,
};

static const struct rt2x00lib_ops rt2500usb_rt2x00_ops = {
Expand All @@ -1793,6 +1792,7 @@ static const struct rt2x00lib_ops rt2500usb_rt2x00_ops = {
.get_tx_data_len = rt2500usb_get_tx_data_len,
.kick_tx_queue = rt2500usb_kick_tx_queue,
.fill_rxdone = rt2500usb_fill_rxdone,
.beacon_update = rt2500usb_beacon_update,
.config_filter = rt2500usb_config_filter,
.config_intf = rt2500usb_config_intf,
.config_erp = rt2500usb_config_erp,
Expand Down
2 changes: 2 additions & 0 deletions drivers/net/wireless/rt2x00/rt2x00.h
Original file line number Diff line number Diff line change
Expand Up @@ -534,6 +534,8 @@ struct rt2x00lib_ops {
/*
* Configuration handlers.
*/
int (*beacon_update) (struct ieee80211_hw *hw, struct sk_buff *bcn);

void (*config_filter) (struct rt2x00_dev *rt2x00dev,
const unsigned int filter_flags);
void (*config_intf) (struct rt2x00_dev *rt2x00dev,
Expand Down
10 changes: 5 additions & 5 deletions drivers/net/wireless/rt2x00/rt2x00dev.c
Original file line number Diff line number Diff line change
Expand Up @@ -409,7 +409,6 @@ static void rt2x00lib_intf_scheduled_iter(void *data, u8 *mac,
{
struct rt2x00_dev *rt2x00dev = data;
struct rt2x00_intf *intf = vif_to_intf(vif);
struct sk_buff *skb;
struct ieee80211_bss_conf conf;
int delayed_flags;

Expand All @@ -436,10 +435,11 @@ static void rt2x00lib_intf_scheduled_iter(void *data, u8 *mac,
return;

if (delayed_flags & DELAYED_UPDATE_BEACON) {
skb = ieee80211_beacon_get(rt2x00dev->hw, vif);
if (skb &&
rt2x00dev->ops->hw->beacon_update(rt2x00dev->hw, skb))
dev_kfree_skb(skb);
struct ieee80211_if_conf conf;
conf.bssid = conf.ssid = NULL;
conf.ssid_len = 0;
conf.changed = IEEE80211_IFCC_BEACON;
rt2x00dev->ops->hw->config_interface(rt2x00dev->hw, vif, &conf);
}

if (delayed_flags & DELAYED_CONFIG_ERP)
Expand Down
Loading

0 comments on commit 9d139c8

Please sign in to comment.