From 0c68ae2605dbcf67414d8d1f19af93be44b355fb Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Mon, 27 Oct 2008 15:56:10 -0700 Subject: mac80211: convert to %pM away from print_mac Also remove a few stray DECLARE_MAC_BUF that were no longer used at all. Signed-off-by: Johannes Berg Signed-off-by: David S. Miller --- net/mac80211/tx.c | 24 ++++++++++-------------- 1 file changed, 10 insertions(+), 14 deletions(-) (limited to 'net/mac80211/tx.c') diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c index 1460537faf3..9191b510bff 100644 --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c @@ -201,10 +201,9 @@ ieee80211_tx_h_check_assoc(struct ieee80211_tx_data *tx) tx->sdata->vif.type != NL80211_IFTYPE_ADHOC && ieee80211_is_data(hdr->frame_control))) { #ifdef CONFIG_MAC80211_VERBOSE_DEBUG - DECLARE_MAC_BUF(mac); printk(KERN_DEBUG "%s: dropped data frame to not " - "associated station %s\n", - tx->dev->name, print_mac(mac, hdr->addr1)); + "associated station %pM\n", + tx->dev->name, hdr->addr1); #endif /* CONFIG_MAC80211_VERBOSE_DEBUG */ I802_DEBUG_INC(tx->local->tx_handlers_drop_not_assoc); return TX_DROP; @@ -331,7 +330,6 @@ ieee80211_tx_h_unicast_ps_buf(struct ieee80211_tx_data *tx) struct ieee80211_tx_info *info = IEEE80211_SKB_CB(tx->skb); struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)tx->skb->data; u32 staflags; - DECLARE_MAC_BUF(mac); if (unlikely(!sta || ieee80211_is_probe_resp(hdr->frame_control))) return TX_CONTINUE; @@ -341,9 +339,9 @@ ieee80211_tx_h_unicast_ps_buf(struct ieee80211_tx_data *tx) if (unlikely((staflags & WLAN_STA_PS) && !(staflags & WLAN_STA_PSPOLL))) { #ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG - printk(KERN_DEBUG "STA %s aid %d: PS buffer (entries " + printk(KERN_DEBUG "STA %pM aid %d: PS buffer (entries " "before %d)\n", - print_mac(mac, sta->sta.addr), sta->sta.aid, + sta->sta.addr, sta->sta.aid, skb_queue_len(&sta->ps_tx_buf)); #endif /* CONFIG_MAC80211_VERBOSE_PS_DEBUG */ if (tx->local->total_ps_buffered >= TOTAL_MAX_TX_BUFFER) @@ -352,9 +350,9 @@ ieee80211_tx_h_unicast_ps_buf(struct ieee80211_tx_data *tx) struct sk_buff *old = skb_dequeue(&sta->ps_tx_buf); #ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG if (net_ratelimit()) { - printk(KERN_DEBUG "%s: STA %s TX " + printk(KERN_DEBUG "%s: STA %pM TX " "buffer full - dropping oldest frame\n", - tx->dev->name, print_mac(mac, sta->sta.addr)); + tx->dev->name, sta->sta.addr); } #endif dev_kfree_skb(old); @@ -371,9 +369,9 @@ ieee80211_tx_h_unicast_ps_buf(struct ieee80211_tx_data *tx) } #ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG else if (unlikely(test_sta_flags(sta, WLAN_STA_PS))) { - printk(KERN_DEBUG "%s: STA %s in PS mode, but pspoll " + printk(KERN_DEBUG "%s: STA %pM in PS mode, but pspoll " "set -> send frame\n", tx->dev->name, - print_mac(mac, sta->sta.addr)); + sta->sta.addr); } #endif /* CONFIG_MAC80211_VERBOSE_PS_DEBUG */ clear_sta_flags(sta, WLAN_STA_PSPOLL); @@ -1593,12 +1591,10 @@ int ieee80211_subif_start_xmit(struct sk_buff *skb, compare_ether_addr(dev->dev_addr, skb->data + ETH_ALEN) == 0))) { #ifdef CONFIG_MAC80211_VERBOSE_DEBUG - DECLARE_MAC_BUF(mac); - if (net_ratelimit()) - printk(KERN_DEBUG "%s: dropped frame to %s" + printk(KERN_DEBUG "%s: dropped frame to %pM" " (unauthorized port)\n", dev->name, - print_mac(mac, hdr.addr1)); + hdr.addr1); #endif I802_DEBUG_INC(local->tx_handlers_drop_unauth_port); -- cgit v1.2.3-70-g09d2 From 0f4ac38b5999c3d51adad52d61c56c1b99c247ec Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Thu, 9 Oct 2008 12:18:04 +0200 Subject: mac80211: kill hw.conf.antenna_sel_{rx,tx} Never actually used. Signed-off-by: Johannes Berg Signed-off-by: John W. Linville --- drivers/net/wireless/b43/main.c | 25 +++---------------------- drivers/net/wireless/b43legacy/main.c | 18 ++---------------- drivers/net/wireless/p54/p54common.c | 3 +-- drivers/net/wireless/rt2x00/rt2x00config.c | 20 ++++---------------- drivers/net/wireless/rt2x00/rt2x00dev.c | 6 ++---- include/net/mac80211.h | 7 +------ net/mac80211/debugfs.c | 8 -------- net/mac80211/ieee80211_i.h | 2 -- net/mac80211/tx.c | 1 - 9 files changed, 13 insertions(+), 77 deletions(-) (limited to 'net/mac80211/tx.c') diff --git a/drivers/net/wireless/b43/main.c b/drivers/net/wireless/b43/main.c index 6e773018cba..6b85428b0e1 100644 --- a/drivers/net/wireless/b43/main.c +++ b/drivers/net/wireless/b43/main.c @@ -1339,25 +1339,6 @@ u8 b43_ieee80211_antenna_sanitize(struct b43_wldev *dev, return antenna_nr; } -static int b43_antenna_from_ieee80211(struct b43_wldev *dev, u8 antenna) -{ - antenna = b43_ieee80211_antenna_sanitize(dev, antenna); - switch (antenna) { - case 0: /* default/diversity */ - return B43_ANTENNA_DEFAULT; - case 1: /* Antenna 0 */ - return B43_ANTENNA0; - case 2: /* Antenna 1 */ - return B43_ANTENNA1; - case 3: /* Antenna 2 */ - return B43_ANTENNA2; - case 4: /* Antenna 3 */ - return B43_ANTENNA3; - default: - return B43_ANTENNA_DEFAULT; - } -} - /* Convert a b43 antenna number value to the PHY TX control value. */ static u16 b43_antenna_to_phyctl(int antenna) { @@ -1399,7 +1380,7 @@ static void b43_write_beacon_template(struct b43_wldev *dev, len, ram_offset, shm_size_offset, rate); /* Write the PHY TX control parameters. */ - antenna = b43_antenna_from_ieee80211(dev, info->antenna_sel_tx); + antenna = B43_ANTENNA_DEFAULT; antenna = b43_antenna_to_phyctl(antenna); ctl = b43_shm_read16(dev, B43_SHM_SHARED, B43_SHM_SH_BEACPHYCTL); /* We can't send beacons with short preamble. Would get PHY errors. */ @@ -3399,9 +3380,9 @@ static int b43_op_config(struct ieee80211_hw *hw, struct ieee80211_conf *conf) } /* Antennas for RX and management frame TX. */ - antenna = b43_antenna_from_ieee80211(dev, conf->antenna_sel_tx); + antenna = B43_ANTENNA_DEFAULT; b43_mgmtframe_txantenna(dev, antenna); - antenna = b43_antenna_from_ieee80211(dev, conf->antenna_sel_rx); + antenna = B43_ANTENNA_DEFAULT; if (phy->ops->set_rx_antenna) phy->ops->set_rx_antenna(dev, antenna); diff --git a/drivers/net/wireless/b43legacy/main.c b/drivers/net/wireless/b43legacy/main.c index c66d57560e7..867f01ce45c 100644 --- a/drivers/net/wireless/b43legacy/main.c +++ b/drivers/net/wireless/b43legacy/main.c @@ -2556,20 +2556,6 @@ init_failure: return err; } -static int b43legacy_antenna_from_ieee80211(u8 antenna) -{ - switch (antenna) { - case 0: /* default/diversity */ - return B43legacy_ANTENNA_DEFAULT; - case 1: /* Antenna 0 */ - return B43legacy_ANTENNA0; - case 2: /* Antenna 1 */ - return B43legacy_ANTENNA1; - default: - return B43legacy_ANTENNA_DEFAULT; - } -} - static int b43legacy_op_dev_config(struct ieee80211_hw *hw, struct ieee80211_conf *conf) { @@ -2583,8 +2569,8 @@ static int b43legacy_op_dev_config(struct ieee80211_hw *hw, int err = 0; u32 savedirqs; - antenna_tx = b43legacy_antenna_from_ieee80211(conf->antenna_sel_tx); - antenna_rx = b43legacy_antenna_from_ieee80211(conf->antenna_sel_rx); + antenna_tx = B43legacy_ANTENNA_DEFAULT; + antenna_rx = B43legacy_ANTENNA_DEFAULT; mutex_lock(&wl->mutex); dev = wl->current_dev; diff --git a/drivers/net/wireless/p54/p54common.c b/drivers/net/wireless/p54/p54common.c index b1dc10ccd32..b3e75eb4d5b 100644 --- a/drivers/net/wireless/p54/p54common.c +++ b/drivers/net/wireless/p54/p54common.c @@ -1198,8 +1198,7 @@ static int p54_config(struct ieee80211_hw *dev, struct ieee80211_conf *conf) struct p54_common *priv = dev->priv; mutex_lock(&priv->conf_mutex); - priv->rx_antenna = (conf->antenna_sel_rx == 0) ? - 2 : conf->antenna_sel_tx - 1; + priv->rx_antenna = 2; /* automatic */ priv->output_power = conf->power_level << 2; ret = p54_set_freq(dev, cpu_to_le16(conf->channel->center_freq)); p54_set_vdcf(dev); diff --git a/drivers/net/wireless/rt2x00/rt2x00config.c b/drivers/net/wireless/rt2x00/rt2x00config.c index 4d5e87b015a..7910147157b 100644 --- a/drivers/net/wireless/rt2x00/rt2x00config.c +++ b/drivers/net/wireless/rt2x00/rt2x00config.c @@ -199,23 +199,15 @@ void rt2x00lib_config(struct rt2x00_dev *rt2x00dev, * to work with untill the link tuner decides that an antenna * switch should be performed. */ - if (!conf->antenna_sel_rx && - default_ant->rx != ANTENNA_SW_DIVERSITY && + if (default_ant->rx != ANTENNA_SW_DIVERSITY && default_ant->rx != active_ant->rx) flags |= CONFIG_UPDATE_ANTENNA; - else if (conf->antenna_sel_rx && - conf->antenna_sel_rx != active_ant->rx) - flags |= CONFIG_UPDATE_ANTENNA; else if (active_ant->rx == ANTENNA_SW_DIVERSITY) flags |= CONFIG_UPDATE_ANTENNA; - if (!conf->antenna_sel_tx && - default_ant->tx != ANTENNA_SW_DIVERSITY && + if (default_ant->tx != ANTENNA_SW_DIVERSITY && default_ant->tx != active_ant->tx) flags |= CONFIG_UPDATE_ANTENNA; - else if (conf->antenna_sel_tx && - conf->antenna_sel_tx != active_ant->tx) - flags |= CONFIG_UPDATE_ANTENNA; else if (active_ant->tx == ANTENNA_SW_DIVERSITY) flags |= CONFIG_UPDATE_ANTENNA; @@ -252,18 +244,14 @@ config: } if (flags & CONFIG_UPDATE_ANTENNA) { - if (conf->antenna_sel_rx) - libconf.ant.rx = conf->antenna_sel_rx; - else if (default_ant->rx != ANTENNA_SW_DIVERSITY) + if (default_ant->rx != ANTENNA_SW_DIVERSITY) libconf.ant.rx = default_ant->rx; else if (active_ant->rx == ANTENNA_SW_DIVERSITY) libconf.ant.rx = ANTENNA_B; else libconf.ant.rx = active_ant->rx; - if (conf->antenna_sel_tx) - libconf.ant.tx = conf->antenna_sel_tx; - else if (default_ant->tx != ANTENNA_SW_DIVERSITY) + if (default_ant->tx != ANTENNA_SW_DIVERSITY) libconf.ant.tx = default_ant->tx; else if (active_ant->tx == ANTENNA_SW_DIVERSITY) libconf.ant.tx = ANTENNA_B; diff --git a/drivers/net/wireless/rt2x00/rt2x00dev.c b/drivers/net/wireless/rt2x00/rt2x00dev.c index 86840e3585e..9e0472bd1ed 100644 --- a/drivers/net/wireless/rt2x00/rt2x00dev.c +++ b/drivers/net/wireless/rt2x00/rt2x00dev.c @@ -249,11 +249,9 @@ static void rt2x00lib_evaluate_antenna(struct rt2x00_dev *rt2x00dev) rt2x00dev->link.ant.flags &= ~ANTENNA_RX_DIVERSITY; rt2x00dev->link.ant.flags &= ~ANTENNA_TX_DIVERSITY; - if (rt2x00dev->hw->conf.antenna_sel_rx == 0 && - rt2x00dev->default_ant.rx == ANTENNA_SW_DIVERSITY) + if (rt2x00dev->default_ant.rx == ANTENNA_SW_DIVERSITY) rt2x00dev->link.ant.flags |= ANTENNA_RX_DIVERSITY; - if (rt2x00dev->hw->conf.antenna_sel_tx == 0 && - rt2x00dev->default_ant.tx == ANTENNA_SW_DIVERSITY) + if (rt2x00dev->default_ant.tx == ANTENNA_SW_DIVERSITY) rt2x00dev->link.ant.flags |= ANTENNA_TX_DIVERSITY; if (!(rt2x00dev->link.ant.flags & ANTENNA_RX_DIVERSITY) && diff --git a/include/net/mac80211.h b/include/net/mac80211.h index 2870f3973f1..5f28b7f8988 100644 --- a/include/net/mac80211.h +++ b/include/net/mac80211.h @@ -324,7 +324,7 @@ struct ieee80211_tx_altrate { * @flags: transmit info flags, defined above * @band: TBD * @tx_rate_idx: TBD - * @antenna_sel_tx: TBD + * @antenna_sel_tx: antenna to use, 0 for automatic diversity * @control: union for control data * @status: union for status data * @driver_data: array of driver_data pointers @@ -474,9 +474,6 @@ static inline int __deprecated __IEEE80211_CONF_SHORT_SLOT_TIME(void) * @listen_interval: listen interval in units of beacon interval * @flags: configuration flags defined above * @power_level: requested transmit power (in dBm) - * @antenna_sel_tx: transmit antenna selection, 0: default/diversity, - * 1/2: antenna 0/1 - * @antenna_sel_rx: receive antenna selection, like @antenna_sel_tx * @ht_cap: describes current self configuration of 802.11n HT capabilities * @ht_bss_conf: describes current BSS configuration of 802.11n HT parameters * @channel: the channel to tune to @@ -488,8 +485,6 @@ struct ieee80211_conf { u16 listen_interval; u32 flags; int power_level; - u8 antenna_sel_tx; - u8 antenna_sel_rx; struct ieee80211_channel *channel; diff --git a/net/mac80211/debugfs.c b/net/mac80211/debugfs.c index 24ce5446331..767dbca50ad 100644 --- a/net/mac80211/debugfs.c +++ b/net/mac80211/debugfs.c @@ -47,10 +47,6 @@ static const struct file_operations name## _ops = { \ DEBUGFS_READONLY_FILE(frequency, 20, "%d", local->hw.conf.channel->center_freq); -DEBUGFS_READONLY_FILE(antenna_sel_tx, 20, "%d", - local->hw.conf.antenna_sel_tx); -DEBUGFS_READONLY_FILE(antenna_sel_rx, 20, "%d", - local->hw.conf.antenna_sel_rx); DEBUGFS_READONLY_FILE(rts_threshold, 20, "%d", local->rts_threshold); DEBUGFS_READONLY_FILE(fragmentation_threshold, 20, "%d", @@ -202,8 +198,6 @@ void debugfs_hw_add(struct ieee80211_local *local) local->debugfs.keys = debugfs_create_dir("keys", phyd); DEBUGFS_ADD(frequency); - DEBUGFS_ADD(antenna_sel_tx); - DEBUGFS_ADD(antenna_sel_rx); DEBUGFS_ADD(rts_threshold); DEBUGFS_ADD(fragmentation_threshold); DEBUGFS_ADD(short_retry_limit); @@ -258,8 +252,6 @@ void debugfs_hw_add(struct ieee80211_local *local) void debugfs_hw_del(struct ieee80211_local *local) { DEBUGFS_DEL(frequency); - DEBUGFS_DEL(antenna_sel_tx); - DEBUGFS_DEL(antenna_sel_rx); DEBUGFS_DEL(rts_threshold); DEBUGFS_DEL(fragmentation_threshold); DEBUGFS_DEL(short_retry_limit); diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index ae4ca3e8b44..88015838a63 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h @@ -727,8 +727,6 @@ struct ieee80211_local { struct dentry *rcdir; struct dentry *rcname; struct dentry *frequency; - struct dentry *antenna_sel_tx; - struct dentry *antenna_sel_rx; struct dentry *rts_threshold; struct dentry *fragmentation_threshold; struct dentry *short_retry_limit; diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c index 9191b510bff..22494bcf488 100644 --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c @@ -1971,7 +1971,6 @@ struct sk_buff *ieee80211_beacon_get(struct ieee80211_hw *hw, sband->bitrates[rsel.rate_idx].flags & IEEE80211_RATE_SHORT_PREAMBLE) info->flags |= IEEE80211_TX_CTL_SHORT_PREAMBLE; - info->antenna_sel_tx = local->hw.conf.antenna_sel_tx; info->control.retry_limit = 1; out: -- cgit v1.2.3-70-g09d2 From 94778280fabdb6bc76db5509bd95859f1141385b Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Fri, 10 Oct 2008 13:21:59 +0200 Subject: mac80211: provide sequence numbers I've come to think that not providing sequence numbers for the normal STA mode case was a mistake, at least two drivers now had to implement code they wouldn't otherwise need, and I believe at76_usb and adm8211 might be broken. This patch makes mac80211 assign a sequence number to all those frames that need one except beacons. That means that if a driver only implements modes that do not do beaconing it need not worry about the sequence number. Signed-off-by: Johannes Berg Signed-off-by: John W. Linville --- drivers/net/wireless/p54/p54.h | 1 - drivers/net/wireless/p54/p54common.c | 18 +++++------------- drivers/net/wireless/rtl8187.h | 1 - drivers/net/wireless/rtl8187_dev.c | 18 ++++-------------- net/mac80211/ieee80211_i.h | 2 ++ net/mac80211/tx.c | 10 ++++++++++ 6 files changed, 21 insertions(+), 29 deletions(-) (limited to 'net/mac80211/tx.c') diff --git a/drivers/net/wireless/p54/p54.h b/drivers/net/wireless/p54/p54.h index 8da4d302059..1da96fe5024 100644 --- a/drivers/net/wireless/p54/p54.h +++ b/drivers/net/wireless/p54/p54.h @@ -67,7 +67,6 @@ struct p54_common { int (*open)(struct ieee80211_hw *dev); void (*stop)(struct ieee80211_hw *dev); int mode; - u16 seqno; u16 rx_mtu; u8 headroom; u8 tailroom; diff --git a/drivers/net/wireless/p54/p54common.c b/drivers/net/wireless/p54/p54common.c index f8cdd88e010..7c37d3fc1e2 100644 --- a/drivers/net/wireless/p54/p54common.c +++ b/drivers/net/wireless/p54/p54common.c @@ -856,19 +856,6 @@ static int p54_tx(struct ieee80211_hw *dev, struct sk_buff *skb) if (padding) txhdr->align[0] = padding; - /* FIXME: The sequence that follows is needed for this driver to - * work with mac80211 since "mac80211: fix TX sequence numbers". - * As with the temporary code in rt2x00, changes will be needed - * to get proper sequence numbers on beacons. In addition, this - * patch places the sequence number in the hardware state, which - * limits us to a single virtual state. - */ - if (info->flags & IEEE80211_TX_CTL_ASSIGN_SEQ) { - if (info->flags & IEEE80211_TX_CTL_FIRST_FRAGMENT) - priv->seqno += 0x10; - ieee80211hdr->seq_ctrl &= cpu_to_le16(IEEE80211_SCTL_FRAG); - ieee80211hdr->seq_ctrl |= cpu_to_le16(priv->seqno); - } /* modifies skb->cb and with it info, so must be last! */ p54_assign_address(dev, skb, hdr, skb->len); @@ -1392,6 +1379,11 @@ struct ieee80211_hw *p54_init_common(size_t priv_data_len) IEEE80211_HW_SIGNAL_DBM | IEEE80211_HW_NOISE_DBM; + /* + * XXX: when this driver gets support for any mode that + * requires beacons (AP, MESH, IBSS) then it must + * implement IEEE80211_TX_CTL_ASSIGN_SEQ. + */ dev->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION); dev->channel_change_time = 1000; /* TODO: find actual value */ diff --git a/drivers/net/wireless/rtl8187.h b/drivers/net/wireless/rtl8187.h index e82bb4d289e..33725d0978b 100644 --- a/drivers/net/wireless/rtl8187.h +++ b/drivers/net/wireless/rtl8187.h @@ -100,7 +100,6 @@ struct rtl8187_priv { struct usb_device *udev; u32 rx_conf; u16 txpwr_base; - u16 seqno; u8 asic_rev; u8 is_rtl8187b; enum { diff --git a/drivers/net/wireless/rtl8187_dev.c b/drivers/net/wireless/rtl8187_dev.c index 2c69ab37c65..16f2fe2d849 100644 --- a/drivers/net/wireless/rtl8187_dev.c +++ b/drivers/net/wireless/rtl8187_dev.c @@ -241,20 +241,6 @@ static int rtl8187_tx(struct ieee80211_hw *dev, struct sk_buff *skb) ep = epmap[skb_get_queue_mapping(skb)]; } - /* FIXME: The sequence that follows is needed for this driver to - * work with mac80211 since "mac80211: fix TX sequence numbers". - * As with the temporary code in rt2x00, changes will be needed - * to get proper sequence numbers on beacons. In addition, this - * patch places the sequence number in the hardware state, which - * limits us to a single virtual state. - */ - if (info->flags & IEEE80211_TX_CTL_ASSIGN_SEQ) { - if (info->flags & IEEE80211_TX_CTL_FIRST_FRAGMENT) - priv->seqno += 0x10; - ieee80211hdr->seq_ctrl &= cpu_to_le16(IEEE80211_SCTL_FRAG); - ieee80211hdr->seq_ctrl |= cpu_to_le16(priv->seqno); - } - info->driver_data[0] = dev; info->driver_data[1] = urb; @@ -1187,6 +1173,10 @@ static int __devinit rtl8187_probe(struct usb_interface *intf, dev->max_signal = 65; } + /* + * XXX: Once this driver supports anything that requires + * beacons it must implement IEEE80211_TX_CTL_ASSIGN_SEQ. + */ dev->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION); if ((id->driver_info == DEVICE_RTL8187) && priv->is_rtl8187b) diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index 1deb787ff8d..819844726dd 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h @@ -438,6 +438,8 @@ struct ieee80211_sub_if_data { struct ieee80211_key *keys[NUM_DEFAULT_KEYS]; struct ieee80211_key *default_key; + u16 sequence_number; + /* BSS configuration for this interface. */ struct ieee80211_bss_conf bss_conf; diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c index 22494bcf488..8bcabefa86e 100644 --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c @@ -600,8 +600,18 @@ ieee80211_tx_h_sequence(struct ieee80211_tx_data *tx) if (ieee80211_hdrlen(hdr->frame_control) < 24) return TX_CONTINUE; + /* + * Anything but QoS data that has a sequence number field + * (is long enough) gets a sequence number from the global + * counter. + */ if (!ieee80211_is_data_qos(hdr->frame_control)) { + /* driver should assign sequence number */ info->flags |= IEEE80211_TX_CTL_ASSIGN_SEQ; + /* for pure STA mode without beacons, we can do it */ + hdr->seq_ctrl = cpu_to_le16(tx->sdata->sequence_number); + tx->sdata->sequence_number += 0x10; + tx->sdata->sequence_number &= IEEE80211_SCTL_SEQ; return TX_CONTINUE; } -- cgit v1.2.3-70-g09d2 From 9124b07740c51cbc6e358dd0c4abc6ee8ded084d Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Tue, 14 Oct 2008 19:17:54 +0200 Subject: mac80211: make retry limits part of hw config Instead of having a separate callback, use the HW config callback with a new flag to change retry limits. Signed-off-by: Johannes Berg Signed-off-by: John W. Linville --- drivers/net/wireless/ath9k/main.c | 1 - drivers/net/wireless/b43/main.c | 60 +++++++++++++-------------------- drivers/net/wireless/b43legacy/main.c | 59 ++++++++++++-------------------- drivers/net/wireless/rt2x00/rt2400pci.c | 2 +- drivers/net/wireless/rt2x00/rt2500pci.c | 2 +- drivers/net/wireless/rt2x00/rt2x00.h | 3 ++ drivers/net/wireless/rt2x00/rt2x00mac.c | 9 +++++ drivers/net/wireless/rt2x00/rt61pci.c | 2 +- drivers/net/wireless/rt2x00/rt73usb.c | 2 +- include/net/mac80211.h | 14 +++++--- net/mac80211/debugfs.c | 4 +-- net/mac80211/ieee80211_i.h | 2 -- net/mac80211/main.c | 4 +-- net/mac80211/tx.c | 4 +-- net/mac80211/wext.c | 28 +++++++-------- 15 files changed, 89 insertions(+), 107 deletions(-) (limited to 'net/mac80211/tx.c') diff --git a/drivers/net/wireless/ath9k/main.c b/drivers/net/wireless/ath9k/main.c index f49910799ed..41cd114c438 100644 --- a/drivers/net/wireless/ath9k/main.c +++ b/drivers/net/wireless/ath9k/main.c @@ -1659,7 +1659,6 @@ static struct ieee80211_ops ath9k_ops = { .get_tkip_seq = NULL, .set_rts_threshold = NULL, .set_frag_threshold = NULL, - .set_retry_limit = NULL, .get_tsf = ath9k_get_tsf, .reset_tsf = ath9k_reset_tsf, .tx_last_beacon = NULL, diff --git a/drivers/net/wireless/b43/main.c b/drivers/net/wireless/b43/main.c index 2e81af1022e..9aeeb6553a9 100644 --- a/drivers/net/wireless/b43/main.c +++ b/drivers/net/wireless/b43/main.c @@ -3320,6 +3320,22 @@ init_failure: return err; } +/* Write the short and long frame retry limit values. */ +static void b43_set_retry_limits(struct b43_wldev *dev, + unsigned int short_retry, + unsigned int long_retry) +{ + /* The retry limit is a 4-bit counter. Enforce this to avoid overflowing + * the chip-internal counter. */ + short_retry = min(short_retry, (unsigned int)0xF); + long_retry = min(long_retry, (unsigned int)0xF); + + b43_shm_write16(dev, B43_SHM_SCRATCH, B43_SHM_SC_SRLIMIT, + short_retry); + b43_shm_write16(dev, B43_SHM_SCRATCH, B43_SHM_SC_LRLIMIT, + long_retry); +} + static int b43_op_config(struct ieee80211_hw *hw, u32 changed) { struct b43_wl *wl = hw_to_b43_wl(hw); @@ -3340,6 +3356,13 @@ static int b43_op_config(struct ieee80211_hw *hw, u32 changed) dev = wl->current_dev; phy = &dev->phy; + if (changed & IEEE80211_CONF_CHANGE_RETRY_LIMITS) + b43_set_retry_limits(dev, conf->short_frame_max_tx_count, + conf->long_frame_max_tx_count); + changed &= ~IEEE80211_CONF_CHANGE_RETRY_LIMITS; + if (!changed) + goto out_unlock_mutex; + /* Disable IRQs while reconfiguring the device. * This makes it possible to drop the spinlock throughout * the reconfiguration process. */ @@ -3859,22 +3882,6 @@ static void b43_imcfglo_timeouts_workaround(struct b43_wldev *dev) #endif /* CONFIG_SSB_DRIVER_PCICORE */ } -/* Write the short and long frame retry limit values. */ -static void b43_set_retry_limits(struct b43_wldev *dev, - unsigned int short_retry, - unsigned int long_retry) -{ - /* The retry limit is a 4-bit counter. Enforce this to avoid overflowing - * the chip-internal counter. */ - short_retry = min(short_retry, (unsigned int)0xF); - long_retry = min(long_retry, (unsigned int)0xF); - - b43_shm_write16(dev, B43_SHM_SCRATCH, B43_SHM_SC_SRLIMIT, - short_retry); - b43_shm_write16(dev, B43_SHM_SCRATCH, B43_SHM_SC_LRLIMIT, - long_retry); -} - static void b43_set_synth_pu_delay(struct b43_wldev *dev, bool idle) { u16 pu_delay; @@ -4195,26 +4202,6 @@ static void b43_op_stop(struct ieee80211_hw *hw) cancel_work_sync(&(wl->txpower_adjust_work)); } -static int b43_op_set_retry_limit(struct ieee80211_hw *hw, - u32 short_retry_limit, u32 long_retry_limit) -{ - struct b43_wl *wl = hw_to_b43_wl(hw); - struct b43_wldev *dev; - int err = 0; - - mutex_lock(&wl->mutex); - dev = wl->current_dev; - if (unlikely(!dev || (b43_status(dev) < B43_STAT_INITIALIZED))) { - err = -ENODEV; - goto out_unlock; - } - b43_set_retry_limits(dev, short_retry_limit, long_retry_limit); -out_unlock: - mutex_unlock(&wl->mutex); - - return err; -} - static int b43_op_beacon_set_tim(struct ieee80211_hw *hw, struct ieee80211_sta *sta, bool set) { @@ -4251,7 +4238,6 @@ static const struct ieee80211_ops b43_hw_ops = { .get_tx_stats = b43_op_get_tx_stats, .start = b43_op_start, .stop = b43_op_stop, - .set_retry_limit = b43_op_set_retry_limit, .set_tim = b43_op_beacon_set_tim, .sta_notify = b43_op_sta_notify, }; diff --git a/drivers/net/wireless/b43legacy/main.c b/drivers/net/wireless/b43legacy/main.c index 793cc396562..78e46365f69 100644 --- a/drivers/net/wireless/b43legacy/main.c +++ b/drivers/net/wireless/b43legacy/main.c @@ -2556,6 +2556,20 @@ init_failure: return err; } +/* Write the short and long frame retry limit values. */ +static void b43legacy_set_retry_limits(struct b43legacy_wldev *dev, + unsigned int short_retry, + unsigned int long_retry) +{ + /* The retry limit is a 4-bit counter. Enforce this to avoid overflowing + * the chip-internal counter. */ + short_retry = min(short_retry, (unsigned int)0xF); + long_retry = min(long_retry, (unsigned int)0xF); + + b43legacy_shm_write16(dev, B43legacy_SHM_WIRELESS, 0x0006, short_retry); + b43legacy_shm_write16(dev, B43legacy_SHM_WIRELESS, 0x0007, long_retry); +} + static int b43legacy_op_dev_config(struct ieee80211_hw *hw, u32 changed) { @@ -2577,6 +2591,14 @@ static int b43legacy_op_dev_config(struct ieee80211_hw *hw, dev = wl->current_dev; phy = &dev->phy; + if (changed & IEEE80211_CONF_CHANGE_RETRY_LIMITS) + b43legacy_set_retry_limits(dev, + conf->short_frame_max_tx_count, + conf->long_frame_max_tx_count); + changed &= ~IEEE80211_CONF_CHANGE_RETRY_LIMITS; + if (!changed) + goto out_unlock_mutex; + /* Switch the PHY mode (if necessary). */ switch (conf->channel->band) { case IEEE80211_BAND_2GHZ: @@ -2989,20 +3011,6 @@ static void b43legacy_imcfglo_timeouts_workaround(struct b43legacy_wldev *dev) #endif /* CONFIG_SSB_DRIVER_PCICORE */ } -/* Write the short and long frame retry limit values. */ -static void b43legacy_set_retry_limits(struct b43legacy_wldev *dev, - unsigned int short_retry, - unsigned int long_retry) -{ - /* The retry limit is a 4-bit counter. Enforce this to avoid overflowing - * the chip-internal counter. */ - short_retry = min(short_retry, (unsigned int)0xF); - long_retry = min(long_retry, (unsigned int)0xF); - - b43legacy_shm_write16(dev, B43legacy_SHM_WIRELESS, 0x0006, short_retry); - b43legacy_shm_write16(dev, B43legacy_SHM_WIRELESS, 0x0007, long_retry); -} - static void b43legacy_set_synth_pu_delay(struct b43legacy_wldev *dev, bool idle) { u16 pu_delay = 1050; @@ -3367,28 +3375,6 @@ static void b43legacy_op_stop(struct ieee80211_hw *hw) mutex_unlock(&wl->mutex); } -static int b43legacy_op_set_retry_limit(struct ieee80211_hw *hw, - u32 short_retry_limit, - u32 long_retry_limit) -{ - struct b43legacy_wl *wl = hw_to_b43legacy_wl(hw); - struct b43legacy_wldev *dev; - int err = 0; - - mutex_lock(&wl->mutex); - dev = wl->current_dev; - if (unlikely(!dev || - (b43legacy_status(dev) < B43legacy_STAT_INITIALIZED))) { - err = -ENODEV; - goto out_unlock; - } - b43legacy_set_retry_limits(dev, short_retry_limit, long_retry_limit); -out_unlock: - mutex_unlock(&wl->mutex); - - return err; -} - static int b43legacy_op_beacon_set_tim(struct ieee80211_hw *hw, struct ieee80211_sta *sta, bool set) { @@ -3414,7 +3400,6 @@ static const struct ieee80211_ops b43legacy_hw_ops = { .get_tx_stats = b43legacy_op_get_tx_stats, .start = b43legacy_op_start, .stop = b43legacy_op_stop, - .set_retry_limit = b43legacy_op_set_retry_limit, .set_tim = b43legacy_op_beacon_set_tim, }; diff --git a/drivers/net/wireless/rt2x00/rt2400pci.c b/drivers/net/wireless/rt2x00/rt2400pci.c index 96eaf5f4dc6..1adca7a1b9d 100644 --- a/drivers/net/wireless/rt2x00/rt2400pci.c +++ b/drivers/net/wireless/rt2x00/rt2400pci.c @@ -1574,7 +1574,6 @@ static const struct ieee80211_ops rt2400pci_mac80211_ops = { .config_interface = rt2x00mac_config_interface, .configure_filter = rt2x00mac_configure_filter, .get_stats = rt2x00mac_get_stats, - .set_retry_limit = rt2400pci_set_retry_limit, .bss_info_changed = rt2x00mac_bss_info_changed, .conf_tx = rt2400pci_conf_tx, .get_tx_stats = rt2x00mac_get_tx_stats, @@ -1603,6 +1602,7 @@ static const struct rt2x00lib_ops rt2400pci_rt2x00_ops = { .config_intf = rt2400pci_config_intf, .config_erp = rt2400pci_config_erp, .config = rt2400pci_config, + .set_retry_limit = rt2400pci_set_retry_limit, }; static const struct data_queue_desc rt2400pci_queue_rx = { diff --git a/drivers/net/wireless/rt2x00/rt2500pci.c b/drivers/net/wireless/rt2x00/rt2500pci.c index 8b772ab613e..85b0387f46e 100644 --- a/drivers/net/wireless/rt2x00/rt2500pci.c +++ b/drivers/net/wireless/rt2x00/rt2500pci.c @@ -1874,7 +1874,6 @@ static const struct ieee80211_ops rt2500pci_mac80211_ops = { .config_interface = rt2x00mac_config_interface, .configure_filter = rt2x00mac_configure_filter, .get_stats = rt2x00mac_get_stats, - .set_retry_limit = rt2500pci_set_retry_limit, .bss_info_changed = rt2x00mac_bss_info_changed, .conf_tx = rt2x00mac_conf_tx, .get_tx_stats = rt2x00mac_get_tx_stats, @@ -1903,6 +1902,7 @@ static const struct rt2x00lib_ops rt2500pci_rt2x00_ops = { .config_intf = rt2500pci_config_intf, .config_erp = rt2500pci_config_erp, .config = rt2500pci_config, + .set_retry_limit = rt2500pci_set_retry_limit, }; static const struct data_queue_desc rt2500pci_queue_rx = { diff --git a/drivers/net/wireless/rt2x00/rt2x00.h b/drivers/net/wireless/rt2x00/rt2x00.h index 8ec8f7e9ec6..0887e895d5c 100644 --- a/drivers/net/wireless/rt2x00/rt2x00.h +++ b/drivers/net/wireless/rt2x00/rt2x00.h @@ -599,6 +599,9 @@ struct rt2x00lib_ops { #define CONFIG_UPDATE_SLOT_TIME ( 1 << 5 ) #define CONFIG_UPDATE_BEACON_INT ( 1 << 6 ) #define CONFIG_UPDATE_ALL 0xffff + + int (*set_retry_limit) (struct ieee80211_hw *hw, + u32 short_limit, u32 long_limit); }; /* diff --git a/drivers/net/wireless/rt2x00/rt2x00mac.c b/drivers/net/wireless/rt2x00/rt2x00mac.c index da7b49a364f..931183369f0 100644 --- a/drivers/net/wireless/rt2x00/rt2x00mac.c +++ b/drivers/net/wireless/rt2x00/rt2x00mac.c @@ -349,6 +349,15 @@ int rt2x00mac_config(struct ieee80211_hw *hw, u32 changed) if (!test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags)) return 0; + if (changed & IEEE80211_CONF_CHANGE_RETRY_LIMITS) { + rt2x00dev->ops->lib->set_retry_limit(hw, + conf->short_frame_max_tx_count, + conf->long_frame_max_tx_count); + } + changed &= ~IEEE80211_CONF_CHANGE_RETRY_LIMITS; + if (!changed) + return 0; + /* * Only change device state when the radio is enabled. It does not * matter what parameters we have configured when the radio is disabled diff --git a/drivers/net/wireless/rt2x00/rt61pci.c b/drivers/net/wireless/rt2x00/rt61pci.c index 45f69f83552..08eb896ae36 100644 --- a/drivers/net/wireless/rt2x00/rt61pci.c +++ b/drivers/net/wireless/rt2x00/rt61pci.c @@ -2724,7 +2724,6 @@ static const struct ieee80211_ops rt61pci_mac80211_ops = { .configure_filter = rt2x00mac_configure_filter, .set_key = rt2x00mac_set_key, .get_stats = rt2x00mac_get_stats, - .set_retry_limit = rt61pci_set_retry_limit, .bss_info_changed = rt2x00mac_bss_info_changed, .conf_tx = rt61pci_conf_tx, .get_tx_stats = rt2x00mac_get_tx_stats, @@ -2757,6 +2756,7 @@ static const struct rt2x00lib_ops rt61pci_rt2x00_ops = { .config_intf = rt61pci_config_intf, .config_erp = rt61pci_config_erp, .config = rt61pci_config, + .set_retry_limit = rt61pci_set_retry_limit, }; static const struct data_queue_desc rt61pci_queue_rx = { diff --git a/drivers/net/wireless/rt2x00/rt73usb.c b/drivers/net/wireless/rt2x00/rt73usb.c index 336fecb04c4..7f89782a34e 100644 --- a/drivers/net/wireless/rt2x00/rt73usb.c +++ b/drivers/net/wireless/rt2x00/rt73usb.c @@ -2315,7 +2315,6 @@ static const struct ieee80211_ops rt73usb_mac80211_ops = { .configure_filter = rt2x00mac_configure_filter, .set_key = rt2x00mac_set_key, .get_stats = rt2x00mac_get_stats, - .set_retry_limit = rt73usb_set_retry_limit, .bss_info_changed = rt2x00mac_bss_info_changed, .conf_tx = rt73usb_conf_tx, .get_tx_stats = rt2x00mac_get_tx_stats, @@ -2347,6 +2346,7 @@ static const struct rt2x00lib_ops rt73usb_rt2x00_ops = { .config_intf = rt73usb_config_intf, .config_erp = rt73usb_config_erp, .config = rt73usb_config, + .set_retry_limit = rt73usb_set_retry_limit, }; static const struct data_queue_desc rt73usb_queue_rx = { diff --git a/include/net/mac80211.h b/include/net/mac80211.h index 34e8569b59b..fd52300b96d 100644 --- a/include/net/mac80211.h +++ b/include/net/mac80211.h @@ -473,6 +473,7 @@ static inline int __deprecated __IEEE80211_CONF_SHORT_SLOT_TIME(void) * @IEEE80211_CONF_CHANGE_PS: the PS flag changed * @IEEE80211_CONF_CHANGE_POWER: the TX power changed * @IEEE80211_CONF_CHANGE_CHANNEL: the channel changed + * @IEEE80211_CONF_CHANGE_RETRY_LIMITS: retry limits changed */ enum ieee80211_conf_changed { IEEE80211_CONF_CHANGE_RADIO_ENABLED = BIT(0), @@ -482,6 +483,7 @@ enum ieee80211_conf_changed { IEEE80211_CONF_CHANGE_PS = BIT(4), IEEE80211_CONF_CHANGE_POWER = BIT(5), IEEE80211_CONF_CHANGE_CHANNEL = BIT(6), + IEEE80211_CONF_CHANGE_RETRY_LIMITS = BIT(7), }; /** @@ -497,6 +499,12 @@ enum ieee80211_conf_changed { * @ht_cap: describes current self configuration of 802.11n HT capabilities * @ht_bss_conf: describes current BSS configuration of 802.11n HT parameters * @channel: the channel to tune to + * @long_frame_max_tx_count: Maximum number of transmissions for a "long" frame + * (a frame not RTS protected), called "dot11LongRetryLimit" in 802.11, + * but actually means the number of transmissions not the number of retries + * @short_frame_max_tx_count: Maximum number of transmissions for a "short" + * frame, called "dot11ShortRetryLimit" in 802.11, but actually means the + * number of transmissions not the number of retries */ struct ieee80211_conf { int beacon_int; @@ -506,6 +514,8 @@ struct ieee80211_conf { u16 listen_interval; bool radio_enabled; + u8 long_frame_max_tx_count, short_frame_max_tx_count; + struct ieee80211_channel *channel; struct ieee80211_sta_ht_cap ht_cap; @@ -1190,8 +1200,6 @@ enum ieee80211_ampdu_mlme_action { * the device does fragmentation by itself; if this method is assigned then * the stack will not do fragmentation. * - * @set_retry_limit: Configuration of retry limits (if device needs it) - * * @sta_notify: Notifies low level driver about addition or removal * of assocaited station or AP. * @@ -1261,8 +1269,6 @@ struct ieee80211_ops { u32 *iv32, u16 *iv16); int (*set_rts_threshold)(struct ieee80211_hw *hw, u32 value); int (*set_frag_threshold)(struct ieee80211_hw *hw, u32 value); - int (*set_retry_limit)(struct ieee80211_hw *hw, - u32 short_retry, u32 long_retr); void (*sta_notify)(struct ieee80211_hw *hw, struct ieee80211_vif *vif, enum sta_notify_cmd, struct ieee80211_sta *sta); int (*conf_tx)(struct ieee80211_hw *hw, u16 queue, diff --git a/net/mac80211/debugfs.c b/net/mac80211/debugfs.c index 767dbca50ad..2697a2fe608 100644 --- a/net/mac80211/debugfs.c +++ b/net/mac80211/debugfs.c @@ -52,9 +52,9 @@ DEBUGFS_READONLY_FILE(rts_threshold, 20, "%d", DEBUGFS_READONLY_FILE(fragmentation_threshold, 20, "%d", local->fragmentation_threshold); DEBUGFS_READONLY_FILE(short_retry_limit, 20, "%d", - local->short_retry_limit); + local->hw.conf.short_frame_max_tx_count); DEBUGFS_READONLY_FILE(long_retry_limit, 20, "%d", - local->long_retry_limit); + local->hw.conf.long_frame_max_tx_count); DEBUGFS_READONLY_FILE(total_ps_buffered, 20, "%d", local->total_ps_buffered); DEBUGFS_READONLY_FILE(wep_iv, 20, "%#06x", diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index 819844726dd..f1ef522bfe0 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h @@ -635,8 +635,6 @@ struct ieee80211_local { int rts_threshold; int fragmentation_threshold; - int short_retry_limit; /* dot11ShortRetryLimit */ - int long_retry_limit; /* dot11LongRetryLimit */ struct crypto_blkcipher *wep_tx_tfm; struct crypto_blkcipher *wep_rx_tfm; diff --git a/net/mac80211/main.c b/net/mac80211/main.c index c936017f6d4..59be9e78269 100644 --- a/net/mac80211/main.c +++ b/net/mac80211/main.c @@ -673,8 +673,8 @@ struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len, local->rts_threshold = IEEE80211_MAX_RTS_THRESHOLD; local->fragmentation_threshold = IEEE80211_MAX_FRAG_THRESHOLD; - local->short_retry_limit = 7; - local->long_retry_limit = 4; + local->hw.conf.long_frame_max_tx_count = 4; + local->hw.conf.short_frame_max_tx_count = 7; local->hw.conf.radio_enabled = true; INIT_LIST_HEAD(&local->interfaces); diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c index 8bcabefa86e..dd440a07634 100644 --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c @@ -505,10 +505,10 @@ ieee80211_tx_h_misc(struct ieee80211_tx_data *tx) info->flags |= IEEE80211_TX_CTL_LONG_RETRY_LIMIT; info->control.retry_limit = - tx->local->long_retry_limit; + tx->local->hw.conf.long_frame_max_tx_count - 1; } else { info->control.retry_limit = - tx->local->short_retry_limit; + tx->local->hw.conf.short_frame_max_tx_count - 1; } } else { info->control.retry_limit = 1; diff --git a/net/mac80211/wext.c b/net/mac80211/wext.c index 94c4b35eeb1..f7e442f80a1 100644 --- a/net/mac80211/wext.c +++ b/net/mac80211/wext.c @@ -802,21 +802,16 @@ static int ieee80211_ioctl_siwretry(struct net_device *dev, (retry->flags & IW_RETRY_TYPE) != IW_RETRY_LIMIT) return -EINVAL; - if (retry->flags & IW_RETRY_MAX) - local->long_retry_limit = retry->value; - else if (retry->flags & IW_RETRY_MIN) - local->short_retry_limit = retry->value; - else { - local->long_retry_limit = retry->value; - local->short_retry_limit = retry->value; + if (retry->flags & IW_RETRY_MAX) { + local->hw.conf.long_frame_max_tx_count = retry->value; + } else if (retry->flags & IW_RETRY_MIN) { + local->hw.conf.short_frame_max_tx_count = retry->value; + } else { + local->hw.conf.long_frame_max_tx_count = retry->value; + local->hw.conf.short_frame_max_tx_count = retry->value; } - if (local->ops->set_retry_limit) { - return local->ops->set_retry_limit( - local_to_hw(local), - local->short_retry_limit, - local->long_retry_limit); - } + ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_RETRY_LIMITS); return 0; } @@ -833,14 +828,15 @@ static int ieee80211_ioctl_giwretry(struct net_device *dev, /* first return min value, iwconfig will ask max value * later if needed */ retry->flags |= IW_RETRY_LIMIT; - retry->value = local->short_retry_limit; - if (local->long_retry_limit != local->short_retry_limit) + retry->value = local->hw.conf.short_frame_max_tx_count; + if (local->hw.conf.long_frame_max_tx_count != + local->hw.conf.short_frame_max_tx_count) retry->flags |= IW_RETRY_MIN; return 0; } if (retry->flags & IW_RETRY_MAX) { retry->flags = IW_RETRY_LIMIT | IW_RETRY_MAX; - retry->value = local->long_retry_limit; + retry->value = local->hw.conf.long_frame_max_tx_count; } return 0; -- cgit v1.2.3-70-g09d2 From bda3933a8aceedd03e0dd410844bd310033ca756 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Sat, 11 Oct 2008 01:51:51 +0200 Subject: mac80211: move bss_conf into vif Move bss_conf into the vif struct so that drivers can access it during ->tx without having to store it in the private data or similar. No driver updates because this is only for when they want to start using it. Signed-off-by: Johannes Berg Signed-off-by: John W. Linville --- include/net/mac80211.h | 3 +++ net/mac80211/cfg.c | 6 +++--- net/mac80211/debugfs_netdev.c | 2 +- net/mac80211/ieee80211_i.h | 3 --- net/mac80211/iface.c | 2 +- net/mac80211/main.c | 8 ++++---- net/mac80211/mlme.c | 30 +++++++++++++++--------------- net/mac80211/tx.c | 16 ++++++++-------- net/mac80211/util.c | 6 +++--- 9 files changed, 38 insertions(+), 38 deletions(-) (limited to 'net/mac80211/tx.c') diff --git a/include/net/mac80211.h b/include/net/mac80211.h index fd52300b96d..94ff3eface4 100644 --- a/include/net/mac80211.h +++ b/include/net/mac80211.h @@ -529,11 +529,14 @@ struct ieee80211_conf { * use during the life of a virtual interface. * * @type: type of this virtual interface + * @bss_conf: BSS configuration for this interface, either our own + * or the BSS we're associated to * @drv_priv: data area for driver use, will always be aligned to * sizeof(void *). */ struct ieee80211_vif { enum nl80211_iftype type; + struct ieee80211_bss_conf bss_conf; /* must be last */ u8 drv_priv[0] __attribute__((__aligned__(sizeof(void *)))); }; diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index 8ea30902d5d..28382b5c7c2 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c @@ -964,16 +964,16 @@ static int ieee80211_change_bss(struct wiphy *wiphy, return -EINVAL; if (params->use_cts_prot >= 0) { - sdata->bss_conf.use_cts_prot = params->use_cts_prot; + sdata->vif.bss_conf.use_cts_prot = params->use_cts_prot; changed |= BSS_CHANGED_ERP_CTS_PROT; } if (params->use_short_preamble >= 0) { - sdata->bss_conf.use_short_preamble = + sdata->vif.bss_conf.use_short_preamble = params->use_short_preamble; changed |= BSS_CHANGED_ERP_PREAMBLE; } if (params->use_short_slot_time >= 0) { - sdata->bss_conf.use_short_slot = + sdata->vif.bss_conf.use_short_slot = params->use_short_slot_time; changed |= BSS_CHANGED_ERP_SLOT; } diff --git a/net/mac80211/debugfs_netdev.c b/net/mac80211/debugfs_netdev.c index 56f3f29385c..c5421930172 100644 --- a/net/mac80211/debugfs_netdev.c +++ b/net/mac80211/debugfs_netdev.c @@ -119,7 +119,7 @@ static ssize_t ieee80211_if_fmt_flags( sdata->u.sta.flags & IEEE80211_STA_AUTHENTICATED ? "AUTH\n" : "", sdata->u.sta.flags & IEEE80211_STA_ASSOCIATED ? "ASSOC\n" : "", sdata->u.sta.flags & IEEE80211_STA_PROBEREQ_POLL ? "PROBEREQ POLL\n" : "", - sdata->bss_conf.use_cts_prot ? "CTS prot\n" : ""); + sdata->vif.bss_conf.use_cts_prot ? "CTS prot\n" : ""); } __IEEE80211_IF_FILE(flags); diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index f1ef522bfe0..859b5b001f2 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h @@ -440,9 +440,6 @@ struct ieee80211_sub_if_data { u16 sequence_number; - /* BSS configuration for this interface. */ - struct ieee80211_bss_conf bss_conf; - /* * AP this belongs to: self in AP mode and * corresponding AP in VLAN mode, NULL for diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c index df28c5f7c9c..cde145221b6 100644 --- a/net/mac80211/iface.c +++ b/net/mac80211/iface.c @@ -695,7 +695,7 @@ int ieee80211_if_change_type(struct ieee80211_sub_if_data *sdata, ieee80211_setup_sdata(sdata, type); /* reset some values that shouldn't be kept across type changes */ - sdata->bss_conf.basic_rates = + sdata->vif.bss_conf.basic_rates = ieee80211_mandatory_rates(sdata->local, sdata->local->hw.conf.channel->band); sdata->drop_unencrypted = 0; diff --git a/net/mac80211/main.c b/net/mac80211/main.c index 59be9e78269..ab8a860444a 100644 --- a/net/mac80211/main.c +++ b/net/mac80211/main.c @@ -249,15 +249,15 @@ void ieee80211_bss_info_change_notify(struct ieee80211_sub_if_data *sdata, if (local->ops->bss_info_changed) local->ops->bss_info_changed(local_to_hw(local), &sdata->vif, - &sdata->bss_conf, + &sdata->vif.bss_conf, changed); } u32 ieee80211_reset_erp_info(struct ieee80211_sub_if_data *sdata) { - sdata->bss_conf.use_cts_prot = false; - sdata->bss_conf.use_short_preamble = false; - sdata->bss_conf.use_short_slot = false; + sdata->vif.bss_conf.use_cts_prot = false; + sdata->vif.bss_conf.use_short_preamble = false; + sdata->vif.bss_conf.use_short_slot = false; return BSS_CHANGED_ERP_CTS_PROT | BSS_CHANGED_ERP_PREAMBLE | BSS_CHANGED_ERP_SLOT; diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index 196dd39f628..9c5f5c37a49 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c @@ -572,7 +572,7 @@ static void ieee80211_sta_wmm_params(struct ieee80211_local *local, static u32 ieee80211_handle_bss_capability(struct ieee80211_sub_if_data *sdata, u16 capab, bool erp_valid, u8 erp) { - struct ieee80211_bss_conf *bss_conf = &sdata->bss_conf; + struct ieee80211_bss_conf *bss_conf = &sdata->vif.bss_conf; #ifdef CONFIG_MAC80211_VERBOSE_DEBUG struct ieee80211_if_sta *ifsta = &sdata->u.sta; #endif @@ -718,9 +718,9 @@ static void ieee80211_set_associated(struct ieee80211_sub_if_data *sdata, ifsta->ssid, ifsta->ssid_len); if (bss) { /* set timing information */ - sdata->bss_conf.beacon_int = bss->beacon_int; - sdata->bss_conf.timestamp = bss->timestamp; - sdata->bss_conf.dtim_period = bss->dtim_period; + sdata->vif.bss_conf.beacon_int = bss->beacon_int; + sdata->vif.bss_conf.timestamp = bss->timestamp; + sdata->vif.bss_conf.dtim_period = bss->dtim_period; changed |= ieee80211_handle_bss_capability(sdata, bss->capability, bss->has_erp_value, bss->erp_value); @@ -730,9 +730,9 @@ static void ieee80211_set_associated(struct ieee80211_sub_if_data *sdata, if (conf->flags & IEEE80211_CONF_SUPPORT_HT_MODE) { changed |= BSS_CHANGED_HT; - sdata->bss_conf.assoc_ht = 1; - sdata->bss_conf.ht_cap = &conf->ht_cap; - sdata->bss_conf.ht_bss_conf = &conf->ht_bss_conf; + sdata->vif.bss_conf.assoc_ht = 1; + sdata->vif.bss_conf.ht_cap = &conf->ht_cap; + sdata->vif.bss_conf.ht_bss_conf = &conf->ht_bss_conf; } ifsta->flags |= IEEE80211_STA_PREV_BSSID_SET; @@ -742,7 +742,7 @@ static void ieee80211_set_associated(struct ieee80211_sub_if_data *sdata, ifsta->last_probe = jiffies; ieee80211_led_assoc(local, 1); - sdata->bss_conf.assoc = 1; + sdata->vif.bss_conf.assoc = 1; /* * For now just always ask the driver to update the basic rateset * when we have associated, we aren't checking whether it actually @@ -847,15 +847,15 @@ static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata, ifsta->flags &= ~IEEE80211_STA_ASSOCIATED; changed |= ieee80211_reset_erp_info(sdata); - if (sdata->bss_conf.assoc_ht) + if (sdata->vif.bss_conf.assoc_ht) changed |= BSS_CHANGED_HT; - sdata->bss_conf.assoc_ht = 0; - sdata->bss_conf.ht_cap = NULL; - sdata->bss_conf.ht_bss_conf = NULL; + sdata->vif.bss_conf.assoc_ht = 0; + sdata->vif.bss_conf.ht_cap = NULL; + sdata->vif.bss_conf.ht_bss_conf = NULL; ieee80211_led_assoc(local, 0); - sdata->bss_conf.assoc = 0; + sdata->vif.bss_conf.assoc = 0; ieee80211_sta_send_apinfo(sdata, ifsta); @@ -1182,7 +1182,7 @@ static void ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata, u64 rates, basic_rates; u16 capab_info, status_code, aid; struct ieee802_11_elems elems; - struct ieee80211_bss_conf *bss_conf = &sdata->bss_conf; + struct ieee80211_bss_conf *bss_conf = &sdata->vif.bss_conf; u8 *pos; int i, j; bool have_higher_than_11mbit = false; @@ -1324,7 +1324,7 @@ static void ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata, } sta->sta.supp_rates[local->hw.conf.channel->band] = rates; - sdata->bss_conf.basic_rates = basic_rates; + sdata->vif.bss_conf.basic_rates = basic_rates; /* cf. IEEE 802.11 9.2.12 */ if (local->hw.conf.channel->band == IEEE80211_BAND_2GHZ && diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c index dd440a07634..6f3e4be9763 100644 --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c @@ -116,7 +116,7 @@ static __le16 ieee80211_duration(struct ieee80211_tx_data *tx, int group_addr, if (r->bitrate > txrate->bitrate) break; - if (tx->sdata->bss_conf.basic_rates & BIT(i)) + if (tx->sdata->vif.bss_conf.basic_rates & BIT(i)) rate = r->bitrate; switch (sband->band) { @@ -150,7 +150,7 @@ static __le16 ieee80211_duration(struct ieee80211_tx_data *tx, int group_addr, * to closest integer */ dur = ieee80211_frame_duration(local, 10, rate, erp, - tx->sdata->bss_conf.use_short_preamble); + tx->sdata->vif.bss_conf.use_short_preamble); if (next_frag_len) { /* Frame is fragmented: duration increases with time needed to @@ -159,7 +159,7 @@ static __le16 ieee80211_duration(struct ieee80211_tx_data *tx, int group_addr, /* next fragment */ dur += ieee80211_frame_duration(local, next_frag_len, txrate->bitrate, erp, - tx->sdata->bss_conf.use_short_preamble); + tx->sdata->vif.bss_conf.use_short_preamble); } return cpu_to_le16(dur); @@ -463,7 +463,7 @@ ieee80211_tx_h_rate_ctrl(struct ieee80211_tx_data *tx) } else info->control.retries[0].rate_idx = -1; - if (tx->sdata->bss_conf.use_cts_prot && + if (tx->sdata->vif.bss_conf.use_cts_prot && (tx->flags & IEEE80211_TX_FRAGMENTED) && (rsel.nonerp_idx >= 0)) { tx->last_frag_rate_idx = tx->rate_idx; if (rsel.probe_idx >= 0) @@ -529,7 +529,7 @@ ieee80211_tx_h_misc(struct ieee80211_tx_data *tx) if ((tx->sdata->flags & IEEE80211_SDATA_OPERATING_GMODE) && (sband->bitrates[tx->rate_idx].flags & IEEE80211_RATE_ERP_G) && (tx->flags & IEEE80211_TX_UNICAST) && - tx->sdata->bss_conf.use_cts_prot && + tx->sdata->vif.bss_conf.use_cts_prot && !(info->flags & IEEE80211_TX_CTL_USE_RTS_CTS)) info->flags |= IEEE80211_TX_CTL_USE_CTS_PROTECT; @@ -538,7 +538,7 @@ ieee80211_tx_h_misc(struct ieee80211_tx_data *tx) * available on the network at the current point in time. */ if (ieee80211_is_data(hdr->frame_control) && (sband->bitrates[tx->rate_idx].flags & IEEE80211_RATE_SHORT_PREAMBLE) && - tx->sdata->bss_conf.use_short_preamble && + tx->sdata->vif.bss_conf.use_short_preamble && (!tx->sta || test_sta_flags(tx->sta, WLAN_STA_SHORT_PREAMBLE))) { info->flags |= IEEE80211_TX_CTL_SHORT_PREAMBLE; } @@ -558,7 +558,7 @@ ieee80211_tx_h_misc(struct ieee80211_tx_data *tx) for (idx = 0; idx < sband->n_bitrates; idx++) { if (sband->bitrates[idx].bitrate > rate->bitrate) continue; - if (tx->sdata->bss_conf.basic_rates & BIT(idx) && + if (tx->sdata->vif.bss_conf.basic_rates & BIT(idx) && (baserate < 0 || (sband->bitrates[baserate].bitrate < sband->bitrates[idx].bitrate))) @@ -1977,7 +1977,7 @@ struct sk_buff *ieee80211_beacon_get(struct ieee80211_hw *hw, info->flags |= IEEE80211_TX_CTL_NO_ACK; info->flags |= IEEE80211_TX_CTL_CLEAR_PS_FILT; info->flags |= IEEE80211_TX_CTL_ASSIGN_SEQ; - if (sdata->bss_conf.use_short_preamble && + if (sdata->vif.bss_conf.use_short_preamble && sband->bitrates[rsel.rate_idx].flags & IEEE80211_RATE_SHORT_PREAMBLE) info->flags |= IEEE80211_TX_CTL_SHORT_PREAMBLE; diff --git a/net/mac80211/util.c b/net/mac80211/util.c index 3288c3de67c..ec8b6335f0c 100644 --- a/net/mac80211/util.c +++ b/net/mac80211/util.c @@ -239,7 +239,7 @@ __le16 ieee80211_generic_frame_duration(struct ieee80211_hw *hw, erp = 0; if (vif) { sdata = vif_to_sdata(vif); - short_preamble = sdata->bss_conf.use_short_preamble; + short_preamble = sdata->vif.bss_conf.use_short_preamble; if (sdata->flags & IEEE80211_SDATA_OPERATING_GMODE) erp = rate->flags & IEEE80211_RATE_ERP_G; } @@ -272,7 +272,7 @@ __le16 ieee80211_rts_duration(struct ieee80211_hw *hw, erp = 0; if (vif) { sdata = vif_to_sdata(vif); - short_preamble = sdata->bss_conf.use_short_preamble; + short_preamble = sdata->vif.bss_conf.use_short_preamble; if (sdata->flags & IEEE80211_SDATA_OPERATING_GMODE) erp = rate->flags & IEEE80211_RATE_ERP_G; } @@ -312,7 +312,7 @@ __le16 ieee80211_ctstoself_duration(struct ieee80211_hw *hw, erp = 0; if (vif) { sdata = vif_to_sdata(vif); - short_preamble = sdata->bss_conf.use_short_preamble; + short_preamble = sdata->vif.bss_conf.use_short_preamble; if (sdata->flags & IEEE80211_SDATA_OPERATING_GMODE) erp = rate->flags & IEEE80211_RATE_ERP_G; } -- cgit v1.2.3-70-g09d2 From e6a9854b05c1a6af1308fe2b8c68f35abf28a3ee Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Tue, 21 Oct 2008 12:40:02 +0200 Subject: mac80211/drivers: rewrite the rate control API So after the previous changes we were still unhappy with how convoluted the API is and decided to make things simpler for everybody. This completely changes the rate control API, now taking into account 802.11n with MCS rates and more control, most drivers don't support that though. Signed-off-by: Felix Fietkau Signed-off-by: Johannes Berg Signed-off-by: John W. Linville --- drivers/net/wireless/adm8211.c | 21 +- drivers/net/wireless/ath5k/base.c | 34 ++- drivers/net/wireless/ath9k/main.c | 18 +- drivers/net/wireless/ath9k/rc.c | 40 +-- drivers/net/wireless/ath9k/xmit.c | 28 ++- drivers/net/wireless/b43/dma.c | 4 +- drivers/net/wireless/b43/main.c | 2 +- drivers/net/wireless/b43/pio.c | 3 +- drivers/net/wireless/b43/xmit.c | 60 ++++- drivers/net/wireless/b43/xmit.h | 5 +- drivers/net/wireless/b43legacy/dma.c | 46 ++-- drivers/net/wireless/b43legacy/main.c | 2 +- drivers/net/wireless/b43legacy/pio.c | 31 ++- drivers/net/wireless/b43legacy/xmit.c | 26 +- drivers/net/wireless/b43legacy/xmit.h | 2 +- drivers/net/wireless/iwlwifi/iwl-3945-rs.c | 57 ++--- drivers/net/wireless/iwlwifi/iwl-3945.c | 65 ++++- drivers/net/wireless/iwlwifi/iwl-3945.h | 2 + drivers/net/wireless/iwlwifi/iwl-4965.c | 8 +- drivers/net/wireless/iwlwifi/iwl-5000.c | 8 +- drivers/net/wireless/iwlwifi/iwl-agn-rs.c | 37 ++- drivers/net/wireless/iwlwifi/iwl-core.c | 19 +- drivers/net/wireless/iwlwifi/iwl3945-base.c | 5 +- drivers/net/wireless/libertas_tf/main.c | 4 +- drivers/net/wireless/mac80211_hwsim.c | 12 +- drivers/net/wireless/p54/p54common.c | 26 +- drivers/net/wireless/rt2x00/rt2x00dev.c | 14 +- drivers/net/wireless/rt2x00/rt2x00mac.c | 14 +- drivers/net/wireless/rt2x00/rt2x00queue.c | 22 +- drivers/net/wireless/rt2x00/rt2x00queue.h | 9 +- drivers/net/wireless/rtl8180_dev.c | 28 +-- drivers/net/wireless/rtl8187_dev.c | 18 +- drivers/net/wireless/zd1211rw/zd_mac.c | 32 +-- drivers/net/wireless/zd1211rw/zd_usb.c | 2 +- include/net/mac80211.h | 254 +++++++++++-------- net/mac80211/ieee80211_i.h | 8 - net/mac80211/main.c | 54 +++- net/mac80211/mesh_hwmp.c | 6 +- net/mac80211/rate.c | 52 ++-- net/mac80211/rate.h | 5 +- net/mac80211/rc80211_minstrel.c | 72 +++--- net/mac80211/rc80211_pid.h | 1 + net/mac80211/rc80211_pid_algo.c | 27 +- net/mac80211/rc80211_pid_debugfs.c | 5 +- net/mac80211/sta_info.h | 4 +- net/mac80211/tx.c | 378 +++++++++++++--------------- net/mac80211/wext.c | 4 +- 47 files changed, 889 insertions(+), 685 deletions(-) (limited to 'net/mac80211/tx.c') diff --git a/drivers/net/wireless/adm8211.c b/drivers/net/wireless/adm8211.c index 9a1e0c514c0..b96ebfe4ef3 100644 --- a/drivers/net/wireless/adm8211.c +++ b/drivers/net/wireless/adm8211.c @@ -341,15 +341,14 @@ static void adm8211_interrupt_tci(struct ieee80211_hw *dev) pci_unmap_single(priv->pdev, info->mapping, info->skb->len, PCI_DMA_TODEVICE); - memset(&txi->status, 0, sizeof(txi->status)); + ieee80211_tx_info_clear_status(txi); + skb_pull(skb, sizeof(struct adm8211_tx_hdr)); memcpy(skb_push(skb, info->hdrlen), skb->cb, info->hdrlen); - if (!(txi->flags & IEEE80211_TX_CTL_NO_ACK)) { - if (status & TDES0_STATUS_ES) - txi->status.excessive_retries = 1; - else - txi->flags |= IEEE80211_TX_STAT_ACK; - } + if (!(txi->flags & IEEE80211_TX_CTL_NO_ACK) && + !(status & TDES0_STATUS_ES)) + txi->flags |= IEEE80211_TX_STAT_ACK; + ieee80211_tx_status_irqsafe(dev, skb); info->skb = NULL; @@ -1691,8 +1690,10 @@ static int adm8211_tx(struct ieee80211_hw *dev, struct sk_buff *skb) struct ieee80211_hdr *hdr; struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); struct ieee80211_rate *txrate = ieee80211_get_tx_rate(dev, info); + u8 rc_flags; - short_preamble = !!(txrate->flags & IEEE80211_TX_CTL_SHORT_PREAMBLE); + rc_flags = info->control.rates[0].flags; + short_preamble = !!(rc_flags & IEEE80211_TX_RC_USE_SHORT_PREAMBLE); plcp_signal = txrate->bitrate; hdr = (struct ieee80211_hdr *)skb->data; @@ -1724,10 +1725,10 @@ static int adm8211_tx(struct ieee80211_hw *dev, struct sk_buff *skb) if (short_preamble) txhdr->header_control |= cpu_to_le16(ADM8211_TXHDRCTL_SHORT_PREAMBLE); - if (info->flags & IEEE80211_TX_CTL_USE_RTS_CTS) + if (rc_flags & IEEE80211_TX_RC_USE_RTS_CTS) txhdr->header_control |= cpu_to_le16(ADM8211_TXHDRCTL_ENABLE_RTS); - txhdr->retry_limit = info->control.retry_limit; + txhdr->retry_limit = info->control.rates[0].count; adm8211_tx_raw(dev, skb, plcp_signal, hdrlen); diff --git a/drivers/net/wireless/ath5k/base.c b/drivers/net/wireless/ath5k/base.c index 44401f6f578..3773d983ea6 100644 --- a/drivers/net/wireless/ath5k/base.c +++ b/drivers/net/wireless/ath5k/base.c @@ -541,8 +541,8 @@ ath5k_pci_probe(struct pci_dev *pdev, /* set up multi-rate retry capabilities */ if (sc->ah->ah_version == AR5K_AR5212) { - hw->max_altrates = 3; - hw->max_altrate_tries = 11; + hw->max_rates = 4; + hw->max_rate_tries = 11; } /* Finish private driver data initialization */ @@ -1181,7 +1181,7 @@ ath5k_txbuf_setup(struct ath5k_softc *sc, struct ath5k_buf *bf) ieee80211_get_hdrlen_from_skb(skb), AR5K_PKT_TYPE_NORMAL, (sc->power_level * 2), ieee80211_get_tx_rate(sc->hw, info)->hw_value, - info->control.retry_limit, keyidx, 0, flags, 0, 0); + info->control.rates[0].count, keyidx, 0, flags, 0, 0); if (ret) goto err_unmap; @@ -1193,7 +1193,7 @@ ath5k_txbuf_setup(struct ath5k_softc *sc, struct ath5k_buf *bf) break; mrr_rate[i] = rate->hw_value; - mrr_tries[i] = info->control.retries[i].limit; + mrr_tries[i] = info->control.rates[i + 1].count; } ah->ah_setup_mrr_tx_desc(ah, ds, @@ -1849,30 +1849,26 @@ ath5k_tx_processq(struct ath5k_softc *sc, struct ath5k_txq *txq) pci_unmap_single(sc->pdev, bf->skbaddr, skb->len, PCI_DMA_TODEVICE); - memset(&info->status, 0, sizeof(info->status)); - info->tx_rate_idx = ath5k_hw_to_driver_rix(sc, - ts.ts_rate[ts.ts_final_idx]); - info->status.retry_count = ts.ts_longretry; - + ieee80211_tx_info_clear_status(info); for (i = 0; i < 4; i++) { - struct ieee80211_tx_altrate *r = - &info->status.retries[i]; + struct ieee80211_tx_rate *r = + &info->status.rates[i]; if (ts.ts_rate[i]) { - r->rate_idx = ath5k_hw_to_driver_rix(sc, ts.ts_rate[i]); - r->limit = ts.ts_retry[i]; + r->idx = ath5k_hw_to_driver_rix(sc, ts.ts_rate[i]); + r->count = ts.ts_retry[i]; } else { - r->rate_idx = -1; - r->limit = 0; + r->idx = -1; + r->count = 0; } } - info->status.excessive_retries = 0; + /* count the successful attempt as well */ + info->status.rates[ts.ts_final_idx].count++; + if (unlikely(ts.ts_status)) { sc->ll_stats.dot11ACKFailureCount++; - if (ts.ts_status & AR5K_TXERR_XRETRY) - info->status.excessive_retries = 1; - else if (ts.ts_status & AR5K_TXERR_FILT) + if (ts.ts_status & AR5K_TXERR_FILT) info->flags |= IEEE80211_TX_STAT_TX_FILTERED; } else { info->flags |= IEEE80211_TX_STAT_ACK; diff --git a/drivers/net/wireless/ath9k/main.c b/drivers/net/wireless/ath9k/main.c index 32acaf7ff62..a7656a3ea1b 100644 --- a/drivers/net/wireless/ath9k/main.c +++ b/drivers/net/wireless/ath9k/main.c @@ -457,12 +457,13 @@ void ath_tx_complete(struct ath_softc *sc, struct sk_buff *skb, DPRINTF(sc, ATH_DBG_XMIT, "%s: TX complete: skb: %p\n", __func__, skb); + ieee80211_tx_info_clear_status(tx_info); if (tx_info->flags & IEEE80211_TX_CTL_NO_ACK || tx_info->flags & IEEE80211_TX_STAT_TX_FILTERED) { - /* free driver's private data area of tx_info */ - if (tx_info->driver_data[0] != NULL) - kfree(tx_info->driver_data[0]); - tx_info->driver_data[0] = NULL; + /* free driver's private data area of tx_info, XXX: HACK! */ + if (tx_info->control.vif != NULL) + kfree(tx_info->control.vif); + tx_info->control.vif = NULL; } if (tx_status->flags & ATH_TX_BAR) { @@ -470,17 +471,12 @@ void ath_tx_complete(struct ath_softc *sc, struct sk_buff *skb, tx_status->flags &= ~ATH_TX_BAR; } - if (tx_status->flags & (ATH_TX_ERROR | ATH_TX_XRETRY)) { - if (!(tx_info->flags & IEEE80211_TX_CTL_NO_ACK)) { - /* Frame was not ACKed, but an ACK was expected */ - tx_info->status.excessive_retries = 1; - } - } else { + if (!(tx_status->flags & (ATH_TX_ERROR | ATH_TX_XRETRY))) { /* Frame was ACKed */ tx_info->flags |= IEEE80211_TX_STAT_ACK; } - tx_info->status.retry_count = tx_status->retries; + tx_info->status.rates[0].count = tx_status->retries + 1; ieee80211_tx_status(hw, skb); if (an) diff --git a/drivers/net/wireless/ath9k/rc.c b/drivers/net/wireless/ath9k/rc.c index 9b252603096..6afafeddeda 100644 --- a/drivers/net/wireless/ath9k/rc.c +++ b/drivers/net/wireless/ath9k/rc.c @@ -1864,24 +1864,21 @@ static void ath_tx_status(void *priv, struct ieee80211_supported_band *sband, hdr = (struct ieee80211_hdr *)skb->data; fc = hdr->frame_control; - tx_info_priv = (struct ath_tx_info_priv *)tx_info->driver_data[0]; + /* XXX: UGLY HACK!! */ + tx_info_priv = (struct ath_tx_info_priv *)tx_info->control.vif; spin_lock_bh(&sc->node_lock); an = ath_node_find(sc, hdr->addr1); spin_unlock_bh(&sc->node_lock); - if (!an || !priv_sta || !ieee80211_is_data(fc)) { - if (tx_info->driver_data[0] != NULL) { - kfree(tx_info->driver_data[0]); - tx_info->driver_data[0] = NULL; - } + if (tx_info_priv == NULL) return; - } - if (tx_info->driver_data[0] != NULL) { + + if (an && priv_sta && ieee80211_is_data(fc)) ath_rate_tx_complete(sc, an, priv_sta, tx_info_priv); - kfree(tx_info->driver_data[0]); - tx_info->driver_data[0] = NULL; - } + + kfree(tx_info_priv); + tx_info->control.vif = NULL; } static void ath_tx_aggr_resp(struct ath_softc *sc, @@ -1927,10 +1924,11 @@ static void ath_tx_aggr_resp(struct ath_softc *sc, } } -static void ath_get_rate(void *priv, struct ieee80211_supported_band *sband, - struct ieee80211_sta *sta, void *priv_sta, - struct sk_buff *skb, struct rate_selection *sel) +static void ath_get_rate(void *priv, struct ieee80211_sta *sta, void *priv_sta, + struct ieee80211_tx_rate_control *txrc) { + struct ieee80211_supported_band *sband = txrc->sband; + struct sk_buff *skb = txrc->skb; struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; struct ath_softc *sc = priv; struct ieee80211_hw *hw = sc->hw; @@ -1945,17 +1943,17 @@ static void ath_get_rate(void *priv, struct ieee80211_supported_band *sband, DPRINTF(sc, ATH_DBG_RATE, "%s\n", __func__); - /* allocate driver private area of tx_info */ - tx_info->driver_data[0] = kzalloc(sizeof(*tx_info_priv), GFP_ATOMIC); - ASSERT(tx_info->driver_data[0] != NULL); - tx_info_priv = (struct ath_tx_info_priv *)tx_info->driver_data[0]; + /* allocate driver private area of tx_info, XXX: UGLY HACK! */ + tx_info->control.vif = kzalloc(sizeof(*tx_info_priv), GFP_ATOMIC); + tx_info_priv = (struct ath_tx_info_priv *)tx_info->control.vif; + ASSERT(tx_info_priv != NULL); lowest_idx = rate_lowest_index(sband, sta); tx_info_priv->min_rate = (sband->bitrates[lowest_idx].bitrate * 2) / 10; /* lowest rate for management and multicast/broadcast frames */ if (!ieee80211_is_data(fc) || is_multicast_ether_addr(hdr->addr1) || !sta) { - sel->rate_idx = lowest_idx; + tx_info->control.rates[0].idx = lowest_idx; return; } @@ -1966,8 +1964,10 @@ static void ath_get_rate(void *priv, struct ieee80211_supported_band *sband, tx_info_priv->rcs, &is_probe, false); +#if 0 if (is_probe) sel->probe_idx = ath_rc_priv->tx_ratectrl.probe_rate; +#endif /* Ratecontrol sometimes returns invalid rate index */ if (tx_info_priv->rcs[0].rix != 0xff) @@ -1975,7 +1975,7 @@ static void ath_get_rate(void *priv, struct ieee80211_supported_band *sband, else tx_info_priv->rcs[0].rix = ath_rc_priv->prev_data_rix; - sel->rate_idx = tx_info_priv->rcs[0].rix; + tx_info->control.rates[0].idx = tx_info_priv->rcs[0].rix; /* Check if aggregation has to be enabled for this tid */ diff --git a/drivers/net/wireless/ath9k/xmit.c b/drivers/net/wireless/ath9k/xmit.c index ba818cc2fb5..9fa395418a6 100644 --- a/drivers/net/wireless/ath9k/xmit.c +++ b/drivers/net/wireless/ath9k/xmit.c @@ -168,7 +168,9 @@ static void fill_min_rates(struct sk_buff *skb, struct ath_tx_control *txctl) hdr = (struct ieee80211_hdr *)skb->data; fc = hdr->frame_control; - tx_info_priv = (struct ath_tx_info_priv *)tx_info->driver_data[0]; + + /* XXX: HACK! */ + tx_info_priv = (struct ath_tx_info_priv *)tx_info->control.vif; if (ieee80211_is_mgmt(fc) || ieee80211_is_ctl(fc)) { txctl->use_minrate = 1; @@ -288,13 +290,16 @@ static int ath_tx_prepare(struct ath_softc *sc, if (tx_info->flags & IEEE80211_TX_CTL_NO_ACK) txctl->flags |= ATH9K_TXDESC_NOACK; - if (tx_info->flags & IEEE80211_TX_CTL_USE_RTS_CTS) + + if (tx_info->control.rates[0].flags & IEEE80211_TX_RC_USE_RTS_CTS) txctl->flags |= ATH9K_TXDESC_RTSENA; /* * Setup for rate calculations. */ - tx_info_priv = (struct ath_tx_info_priv *)tx_info->driver_data[0]; + + /* XXX: HACK! */ + tx_info_priv = (struct ath_tx_info_priv *)tx_info->control.vif; rcs = tx_info_priv->rcs; if (ieee80211_is_data(fc) && !txctl->use_minrate) { @@ -855,7 +860,9 @@ static int ath_tx_send_normal(struct ath_softc *sc, skb = (struct sk_buff *)bf->bf_mpdu; tx_info = IEEE80211_SKB_CB(skb); - tx_info_priv = (struct ath_tx_info_priv *)tx_info->driver_data[0]; + + /* XXX: HACK! */ + tx_info_priv = (struct ath_tx_info_priv *)tx_info->control.vif; memcpy(bf->bf_rcs, tx_info_priv->rcs, 4 * sizeof(tx_info_priv->rcs[0])); /* update starting sequence number for subsequent ADDBA request */ @@ -1249,8 +1256,9 @@ static int ath_tx_processq(struct ath_softc *sc, struct ath_txq *txq) } skb = bf->bf_mpdu; tx_info = IEEE80211_SKB_CB(skb); - tx_info_priv = (struct ath_tx_info_priv *) - tx_info->driver_data[0]; + + /* XXX: HACK! */ + tx_info_priv = (struct ath_tx_info_priv *) tx_info->control.vif; if (ds->ds_txstat.ts_status & ATH9K_TXERR_FILT) tx_info->flags |= IEEE80211_TX_STAT_TX_FILTERED; if ((ds->ds_txstat.ts_status & ATH9K_TXERR_FILT) == 0 && @@ -1431,7 +1439,8 @@ static int ath_tx_send_ampdu(struct ath_softc *sc, skb = (struct sk_buff *)bf->bf_mpdu; tx_info = IEEE80211_SKB_CB(skb); - tx_info_priv = (struct ath_tx_info_priv *)tx_info->driver_data[0]; + /* XXX: HACK! */ + tx_info_priv = (struct ath_tx_info_priv *)tx_info->control.vif; memcpy(bf->bf_rcs, tx_info_priv->rcs, 4 * sizeof(tx_info_priv->rcs[0])); /* Add sub-frame to BAW */ @@ -1466,7 +1475,7 @@ static u32 ath_lookup_rate(struct ath_softc *sc, skb = (struct sk_buff *)bf->bf_mpdu; tx_info = IEEE80211_SKB_CB(skb); tx_info_priv = (struct ath_tx_info_priv *) - tx_info->driver_data[0]; + tx_info->control.vif; /* XXX: HACK! */ memcpy(bf->bf_rcs, tx_info_priv->rcs, 4 * sizeof(tx_info_priv->rcs[0])); @@ -1927,7 +1936,8 @@ static int ath_tx_start_dma(struct ath_softc *sc, bf->bf_flags = txctl->flags; bf->bf_keytype = txctl->keytype; - tx_info_priv = (struct ath_tx_info_priv *)tx_info->driver_data[0]; + /* XXX: HACK! */ + tx_info_priv = (struct ath_tx_info_priv *)tx_info->control.vif; rcs = tx_info_priv->rcs; bf->bf_rcs[0] = rcs[0]; bf->bf_rcs[1] = rcs[1]; diff --git a/drivers/net/wireless/b43/dma.c b/drivers/net/wireless/b43/dma.c index 098f886976f..6d65a02b705 100644 --- a/drivers/net/wireless/b43/dma.c +++ b/drivers/net/wireless/b43/dma.c @@ -1387,13 +1387,11 @@ void b43_dma_handle_txstatus(struct b43_wldev *dev, info = IEEE80211_SKB_CB(meta->skb); - memset(&info->status, 0, sizeof(info->status)); - /* * Call back to inform the ieee80211 subsystem about * the status of the transmission. */ - frame_succeed = b43_fill_txstatus_report(info, status); + frame_succeed = b43_fill_txstatus_report(dev, info, status); #ifdef CONFIG_B43_DEBUG if (frame_succeed) ring->nr_succeed_tx_packets++; diff --git a/drivers/net/wireless/b43/main.c b/drivers/net/wireless/b43/main.c index 9aeeb6553a9..2a599fb772d 100644 --- a/drivers/net/wireless/b43/main.c +++ b/drivers/net/wireless/b43/main.c @@ -4555,7 +4555,7 @@ static int b43_wireless_init(struct ssb_device *dev) BIT(NL80211_IFTYPE_ADHOC); hw->queues = b43_modparam_qos ? 4 : 1; - hw->max_altrates = 1; + hw->max_rates = 2; SET_IEEE80211_DEV(hw, dev->dev); if (is_valid_ether_addr(sprom->et1mac)) SET_IEEE80211_PERM_ADDR(hw, sprom->et1mac); diff --git a/drivers/net/wireless/b43/pio.c b/drivers/net/wireless/b43/pio.c index 40159126759..1036bef8c4c 100644 --- a/drivers/net/wireless/b43/pio.c +++ b/drivers/net/wireless/b43/pio.c @@ -587,9 +587,8 @@ void b43_pio_handle_txstatus(struct b43_wldev *dev, spin_lock(&q->lock); /* IRQs are already disabled. */ info = IEEE80211_SKB_CB(pack->skb); - memset(&info->status, 0, sizeof(info->status)); - b43_fill_txstatus_report(info, status); + b43_fill_txstatus_report(dev, info, status); total_len = pack->skb->len + b43_txhdr_size(dev); total_len = roundup(total_len, 4); diff --git a/drivers/net/wireless/b43/xmit.c b/drivers/net/wireless/b43/xmit.c index 2fabcf8f047..adba89b816d 100644 --- a/drivers/net/wireless/b43/xmit.c +++ b/drivers/net/wireless/b43/xmit.c @@ -185,7 +185,7 @@ int b43_generate_txhdr(struct b43_wldev *dev, u8 *_txhdr, const unsigned char *fragment_data, unsigned int fragment_len, - const struct ieee80211_tx_info *info, + struct ieee80211_tx_info *info, u16 cookie) { struct b43_txhdr *txhdr = (struct b43_txhdr *)_txhdr; @@ -202,6 +202,7 @@ int b43_generate_txhdr(struct b43_wldev *dev, u16 phy_ctl = 0; u8 extra_ft = 0; struct ieee80211_rate *txrate; + struct ieee80211_tx_rate *rates; memset(txhdr, 0, sizeof(*txhdr)); @@ -291,7 +292,7 @@ int b43_generate_txhdr(struct b43_wldev *dev, phy_ctl |= B43_TXH_PHY_ENC_OFDM; else phy_ctl |= B43_TXH_PHY_ENC_CCK; - if (info->flags & IEEE80211_TX_CTL_SHORT_PREAMBLE) + if (info->control.rates[0].flags & IEEE80211_TX_RC_USE_SHORT_PREAMBLE) phy_ctl |= B43_TXH_PHY_SHORTPRMBL; switch (b43_ieee80211_antenna_sanitize(dev, info->antenna_sel_tx)) { @@ -314,6 +315,7 @@ int b43_generate_txhdr(struct b43_wldev *dev, B43_WARN_ON(1); } + rates = info->control.rates; /* MAC control */ if (!(info->flags & IEEE80211_TX_CTL_NO_ACK)) mac_ctl |= B43_TXH_MAC_ACK; @@ -324,12 +326,22 @@ int b43_generate_txhdr(struct b43_wldev *dev, mac_ctl |= B43_TXH_MAC_STMSDU; if (phy->type == B43_PHYTYPE_A) mac_ctl |= B43_TXH_MAC_5GHZ; - if (info->flags & IEEE80211_TX_CTL_LONG_RETRY_LIMIT) + + /* Overwrite rates[0].count to make the retry calculation + * in the tx status easier. need the actual retry limit to + * detect whether the fallback rate was used. + */ + if ((rates[0].flags & IEEE80211_TX_RC_USE_RTS_CTS) || + (rates[0].count <= dev->wl->hw->conf.long_frame_max_tx_count)) { + rates[0].count = dev->wl->hw->conf.long_frame_max_tx_count; mac_ctl |= B43_TXH_MAC_LONGFRAME; + } else { + rates[0].count = dev->wl->hw->conf.short_frame_max_tx_count; + } /* Generate the RTS or CTS-to-self frame */ - if ((info->flags & IEEE80211_TX_CTL_USE_RTS_CTS) || - (info->flags & IEEE80211_TX_CTL_USE_CTS_PROTECT)) { + if ((rates[0].flags & IEEE80211_TX_RC_USE_RTS_CTS) || + (rates[0].flags & IEEE80211_TX_RC_USE_CTS_PROTECT)) { unsigned int len; struct ieee80211_hdr *hdr; int rts_rate, rts_rate_fb; @@ -344,7 +356,7 @@ int b43_generate_txhdr(struct b43_wldev *dev, rts_rate_fb = b43_calc_fallback_rate(rts_rate); rts_rate_fb_ofdm = b43_is_ofdm_rate(rts_rate_fb); - if (info->flags & IEEE80211_TX_CTL_USE_CTS_PROTECT) { + if (rates[0].flags & IEEE80211_TX_RC_USE_CTS_PROTECT) { struct ieee80211_cts *cts; if (b43_is_old_txhdr_format(dev)) { @@ -687,10 +699,18 @@ void b43_handle_txstatus(struct b43_wldev *dev, /* Fill out the mac80211 TXstatus report based on the b43-specific * txstatus report data. This returns a boolean whether the frame was * successfully transmitted. */ -bool b43_fill_txstatus_report(struct ieee80211_tx_info *report, +bool b43_fill_txstatus_report(struct b43_wldev *dev, + struct ieee80211_tx_info *report, const struct b43_txstatus *status) { bool frame_success = 1; + int retry_limit; + + /* preserve the confiured retry limit before clearing the status + * The xmit function has overwritten the rc's value with the actual + * retry limit done by the hardware */ + retry_limit = report->status.rates[0].count; + ieee80211_tx_info_clear_status(report); if (status->acked) { /* The frame was ACKed. */ @@ -700,14 +720,32 @@ bool b43_fill_txstatus_report(struct ieee80211_tx_info *report, if (!(report->flags & IEEE80211_TX_CTL_NO_ACK)) { /* ...but we expected an ACK. */ frame_success = 0; - report->status.excessive_retries = 1; } } if (status->frame_count == 0) { /* The frame was not transmitted at all. */ - report->status.retry_count = 0; - } else - report->status.retry_count = status->frame_count - 1; + report->status.rates[0].count = 0; + } else if (status->rts_count > dev->wl->hw->conf.short_frame_max_tx_count) { + /* + * If the short retries (RTS, not data frame) have exceeded + * the limit, the hw will not have tried the selected rate, + * but will have used the fallback rate instead. + * Don't let the rate control count attempts for the selected + * rate in this case, otherwise the statistics will be off. + */ + report->status.rates[0].count = 0; + report->status.rates[1].count = status->frame_count; + } else { + if (status->frame_count > retry_limit) { + report->status.rates[0].count = retry_limit; + report->status.rates[1].count = status->frame_count - + retry_limit; + + } else { + report->status.rates[0].count = status->frame_count; + report->status.rates[1].idx = -1; + } + } return frame_success; } diff --git a/drivers/net/wireless/b43/xmit.h b/drivers/net/wireless/b43/xmit.h index 0215faf4754..4fb2a190f7a 100644 --- a/drivers/net/wireless/b43/xmit.h +++ b/drivers/net/wireless/b43/xmit.h @@ -178,7 +178,7 @@ int b43_generate_txhdr(struct b43_wldev *dev, u8 * txhdr, const unsigned char *fragment_data, unsigned int fragment_len, - const struct ieee80211_tx_info *txctl, u16 cookie); + struct ieee80211_tx_info *txctl, u16 cookie); /* Transmit Status */ struct b43_txstatus { @@ -294,7 +294,8 @@ void b43_rx(struct b43_wldev *dev, struct sk_buff *skb, const void *_rxhdr); void b43_handle_txstatus(struct b43_wldev *dev, const struct b43_txstatus *status); -bool b43_fill_txstatus_report(struct ieee80211_tx_info *report, +bool b43_fill_txstatus_report(struct b43_wldev *dev, + struct ieee80211_tx_info *report, const struct b43_txstatus *status); void b43_tx_suspend(struct b43_wldev *dev); diff --git a/drivers/net/wireless/b43legacy/dma.c b/drivers/net/wireless/b43legacy/dma.c index fb6819e40f3..308c2647f00 100644 --- a/drivers/net/wireless/b43legacy/dma.c +++ b/drivers/net/wireless/b43legacy/dma.c @@ -1411,6 +1411,7 @@ void b43legacy_dma_handle_txstatus(struct b43legacy_wldev *dev, struct b43legacy_dmaring *ring; struct b43legacy_dmadesc_generic *desc; struct b43legacy_dmadesc_meta *meta; + int retry_limit; int slot; ring = parse_cookie(dev, status->cookie, &slot); @@ -1437,25 +1438,42 @@ void b43legacy_dma_handle_txstatus(struct b43legacy_wldev *dev, struct ieee80211_tx_info *info; BUG_ON(!meta->skb); info = IEEE80211_SKB_CB(meta->skb); - /* Call back to inform the ieee80211 subsystem about the - * status of the transmission. - * Some fields of txstat are already filled in dma_tx(). - */ - memset(&info->status, 0, sizeof(info->status)); + /* preserve the confiured retry limit before clearing the status + * The xmit function has overwritten the rc's value with the actual + * retry limit done by the hardware */ + retry_limit = info->status.rates[0].count; + ieee80211_tx_info_clear_status(info); - if (status->acked) { + if (status->acked) info->flags |= IEEE80211_TX_STAT_ACK; + + if (status->rts_count > dev->wl->hw->conf.short_frame_max_tx_count) { + /* + * If the short retries (RTS, not data frame) have exceeded + * the limit, the hw will not have tried the selected rate, + * but will have used the fallback rate instead. + * Don't let the rate control count attempts for the selected + * rate in this case, otherwise the statistics will be off. + */ + info->status.rates[0].count = 0; + info->status.rates[1].count = status->frame_count; } else { - if (!(info->flags & IEEE80211_TX_CTL_NO_ACK)) - info->status.excessive_retries = 1; + if (status->frame_count > retry_limit) { + info->status.rates[0].count = retry_limit; + info->status.rates[1].count = status->frame_count - + retry_limit; + + } else { + info->status.rates[0].count = status->frame_count; + info->status.rates[1].idx = -1; + } } - if (status->frame_count == 0) { - /* The frame was not transmitted at all. */ - info->status.retry_count = 0; - } else - info->status.retry_count = status->frame_count - - 1; + + /* Call back to inform the ieee80211 subsystem about the + * status of the transmission. + * Some fields of txstat are already filled in dma_tx(). + */ ieee80211_tx_status_irqsafe(dev->wl->hw, meta->skb); /* skb is freed by ieee80211_tx_status_irqsafe() */ meta->skb = NULL; diff --git a/drivers/net/wireless/b43legacy/main.c b/drivers/net/wireless/b43legacy/main.c index 78e46365f69..9edbdf9cb50 100644 --- a/drivers/net/wireless/b43legacy/main.c +++ b/drivers/net/wireless/b43legacy/main.c @@ -3682,7 +3682,7 @@ static int b43legacy_wireless_init(struct ssb_device *dev) BIT(NL80211_IFTYPE_WDS) | BIT(NL80211_IFTYPE_ADHOC); hw->queues = 1; /* FIXME: hardware has more queues */ - hw->max_altrates = 1; + hw->max_rates = 2; SET_IEEE80211_DEV(hw, dev->dev); if (is_valid_ether_addr(sprom->et1mac)) SET_IEEE80211_PERM_ADDR(hw, sprom->et1mac); diff --git a/drivers/net/wireless/b43legacy/pio.c b/drivers/net/wireless/b43legacy/pio.c index a86c7647fa2..746d5361bba 100644 --- a/drivers/net/wireless/b43legacy/pio.c +++ b/drivers/net/wireless/b43legacy/pio.c @@ -491,6 +491,7 @@ void b43legacy_pio_handle_txstatus(struct b43legacy_wldev *dev, struct b43legacy_pioqueue *queue; struct b43legacy_pio_txpacket *packet; struct ieee80211_tx_info *info; + int retry_limit; queue = parse_cookie(dev, status->cookie, &packet); B43legacy_WARN_ON(!queue); @@ -503,11 +504,37 @@ void b43legacy_pio_handle_txstatus(struct b43legacy_wldev *dev, sizeof(struct b43legacy_txhdr_fw3)); info = IEEE80211_SKB_CB(packet->skb); - memset(&info->status, 0, sizeof(info->status)); + + /* preserve the confiured retry limit before clearing the status + * The xmit function has overwritten the rc's value with the actual + * retry limit done by the hardware */ + retry_limit = info->status.rates[0].count; + ieee80211_tx_info_clear_status(info); if (status->acked) info->flags |= IEEE80211_TX_STAT_ACK; - info->status.retry_count = status->frame_count - 1; + + if (status->rts_count > dev->wl->hw->conf.short_frame_max_tx_count) { + /* + * If the short retries (RTS, not data frame) have exceeded + * the limit, the hw will not have tried the selected rate, + * but will have used the fallback rate instead. + * Don't let the rate control count attempts for the selected + * rate in this case, otherwise the statistics will be off. + */ + info->status.rates[0].count = 0; + info->status.rates[1].count = status->frame_count; + } else { + if (status->frame_count > retry_limit) { + info->status.rates[0].count = retry_limit; + info->status.rates[1].count = status->frame_count - + retry_limit; + + } else { + info->status.rates[0].count = status->frame_count; + info->status.rates[1].idx = -1; + } + } ieee80211_tx_status_irqsafe(dev->wl->hw, packet->skb); packet->skb = NULL; diff --git a/drivers/net/wireless/b43legacy/xmit.c b/drivers/net/wireless/b43legacy/xmit.c index 65e83378160..12fca99f757 100644 --- a/drivers/net/wireless/b43legacy/xmit.c +++ b/drivers/net/wireless/b43legacy/xmit.c @@ -188,7 +188,7 @@ static int generate_txhdr_fw3(struct b43legacy_wldev *dev, struct b43legacy_txhdr_fw3 *txhdr, const unsigned char *fragment_data, unsigned int fragment_len, - const struct ieee80211_tx_info *info, + struct ieee80211_tx_info *info, u16 cookie) { const struct ieee80211_hdr *wlhdr; @@ -201,6 +201,7 @@ static int generate_txhdr_fw3(struct b43legacy_wldev *dev, u32 mac_ctl = 0; u16 phy_ctl = 0; struct ieee80211_rate *tx_rate; + struct ieee80211_tx_rate *rates; wlhdr = (const struct ieee80211_hdr *)fragment_data; @@ -274,7 +275,7 @@ static int generate_txhdr_fw3(struct b43legacy_wldev *dev, /* PHY TX Control word */ if (rate_ofdm) phy_ctl |= B43legacy_TX4_PHY_OFDM; - if (dev->short_preamble) + if (info->control.rates[0].flags & IEEE80211_TX_RC_USE_SHORT_PREAMBLE) phy_ctl |= B43legacy_TX4_PHY_SHORTPRMBL; switch (info->antenna_sel_tx) { case 0: @@ -291,6 +292,7 @@ static int generate_txhdr_fw3(struct b43legacy_wldev *dev, } /* MAC control */ + rates = info->control.rates; if (!(info->flags & IEEE80211_TX_CTL_NO_ACK)) mac_ctl |= B43legacy_TX4_MAC_ACK; if (info->flags & IEEE80211_TX_CTL_ASSIGN_SEQ) @@ -299,12 +301,22 @@ static int generate_txhdr_fw3(struct b43legacy_wldev *dev, mac_ctl |= B43legacy_TX4_MAC_STMSDU; if (rate_fb_ofdm) mac_ctl |= B43legacy_TX4_MAC_FALLBACKOFDM; - if (info->flags & IEEE80211_TX_CTL_LONG_RETRY_LIMIT) + + /* Overwrite rates[0].count to make the retry calculation + * in the tx status easier. need the actual retry limit to + * detect whether the fallback rate was used. + */ + if ((rates[0].flags & IEEE80211_TX_RC_USE_RTS_CTS) || + (rates[0].count <= dev->wl->hw->conf.long_frame_max_tx_count)) { + rates[0].count = dev->wl->hw->conf.long_frame_max_tx_count; mac_ctl |= B43legacy_TX4_MAC_LONGFRAME; + } else { + rates[0].count = dev->wl->hw->conf.short_frame_max_tx_count; + } /* Generate the RTS or CTS-to-self frame */ - if ((info->flags & IEEE80211_TX_CTL_USE_RTS_CTS) || - (info->flags & IEEE80211_TX_CTL_USE_CTS_PROTECT)) { + if ((rates[0].flags & IEEE80211_TX_RC_USE_RTS_CTS) || + (rates[0].flags & IEEE80211_TX_RC_USE_CTS_PROTECT)) { unsigned int len; struct ieee80211_hdr *hdr; int rts_rate; @@ -319,7 +331,7 @@ static int generate_txhdr_fw3(struct b43legacy_wldev *dev, if (rts_rate_fb_ofdm) mac_ctl |= B43legacy_TX4_MAC_CTSFALLBACKOFDM; - if (info->flags & IEEE80211_TX_CTL_USE_CTS_PROTECT) { + if (rates[0].flags & IEEE80211_TX_RC_USE_CTS_PROTECT) { ieee80211_ctstoself_get(dev->wl->hw, info->control.vif, fragment_data, @@ -362,7 +374,7 @@ int b43legacy_generate_txhdr(struct b43legacy_wldev *dev, u8 *txhdr, const unsigned char *fragment_data, unsigned int fragment_len, - const struct ieee80211_tx_info *info, + struct ieee80211_tx_info *info, u16 cookie) { return generate_txhdr_fw3(dev, (struct b43legacy_txhdr_fw3 *)txhdr, diff --git a/drivers/net/wireless/b43legacy/xmit.h b/drivers/net/wireless/b43legacy/xmit.h index e56777e0fea..62e09d02788 100644 --- a/drivers/net/wireless/b43legacy/xmit.h +++ b/drivers/net/wireless/b43legacy/xmit.h @@ -80,7 +80,7 @@ int b43legacy_generate_txhdr(struct b43legacy_wldev *dev, u8 *txhdr, const unsigned char *fragment_data, unsigned int fragment_len, - const struct ieee80211_tx_info *info, + struct ieee80211_tx_info *info, u16 cookie); diff --git a/drivers/net/wireless/iwlwifi/iwl-3945-rs.c b/drivers/net/wireless/iwlwifi/iwl-3945-rs.c index c25daec4f93..f440ed0fe54 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945-rs.c +++ b/drivers/net/wireless/iwlwifi/iwl-3945-rs.c @@ -422,34 +422,6 @@ static void rs_free_sta(void *priv, struct ieee80211_sta *sta, } -/* - * get ieee prev rate from rate scale table. - * for A and B mode we need to overright prev - * value - */ -static int rs_adjust_next_rate(struct iwl3945_priv *priv, int rate) -{ - int next_rate = iwl3945_get_prev_ieee_rate(rate); - - switch (priv->band) { - case IEEE80211_BAND_5GHZ: - if (rate == IWL_RATE_12M_INDEX) - next_rate = IWL_RATE_9M_INDEX; - else if (rate == IWL_RATE_6M_INDEX) - next_rate = IWL_RATE_6M_INDEX; - break; -/* XXX cannot be invoked in current mac80211 so not a regression - case MODE_IEEE80211B: - if (rate == IWL_RATE_11M_INDEX_TABLE) - next_rate = IWL_RATE_5M_INDEX_TABLE; - break; - */ - default: - break; - } - - return next_rate; -} /** * rs_tx_status - Update rate control values based on Tx results * @@ -460,17 +432,21 @@ static void rs_tx_status(void *priv_rate, struct ieee80211_supported_band *sband struct ieee80211_sta *sta, void *priv_sta, struct sk_buff *skb) { - u8 retries, current_count; + u8 retries = 0, current_count; int scale_rate_index, first_index, last_index; unsigned long flags; struct iwl3945_priv *priv = (struct iwl3945_priv *)priv_rate; struct iwl3945_rs_sta *rs_sta = priv_sta; struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); + int i; IWL_DEBUG_RATE("enter\n"); - retries = info->status.retry_count; - first_index = sband->bitrates[info->tx_rate_idx].hw_value; + for (i = 0; i < IEEE80211_TX_MAX_RATES; i++) + retries += info->status.rates[i].count; + retries--; + + first_index = sband->bitrates[info->status.rates[0].idx].hw_value; if ((first_index < 0) || (first_index >= IWL_RATE_COUNT)) { IWL_DEBUG_RATE("leave: Rate out of bounds: %d\n", first_index); return; @@ -502,7 +478,7 @@ static void rs_tx_status(void *priv_rate, struct ieee80211_supported_band *sband last_index = scale_rate_index; } else { current_count = priv->retry_rate; - last_index = rs_adjust_next_rate(priv, + last_index = iwl3945_rs_next_rate(priv, scale_rate_index); } @@ -518,7 +494,7 @@ static void rs_tx_status(void *priv_rate, struct ieee80211_supported_band *sband if (retries) scale_rate_index = - rs_adjust_next_rate(priv, scale_rate_index); + iwl3945_rs_next_rate(priv, scale_rate_index); } @@ -630,10 +606,11 @@ static u16 iwl3945_get_adjacent_rate(struct iwl3945_rs_sta *rs_sta, * rate table and must reference the driver allocated rate table * */ -static void rs_get_rate(void *priv_r, struct ieee80211_supported_band *sband, - struct ieee80211_sta *sta, void *priv_sta, - struct sk_buff *skb, struct rate_selection *sel) +static void rs_get_rate(void *priv_r, struct ieee80211_sta *sta, + void *priv_sta, struct ieee80211_tx_rate_control *txrc) { + struct ieee80211_supported_band *sband = txrc->sband; + struct sk_buff *skb = txrc->skb; u8 low = IWL_RATE_INVALID; u8 high = IWL_RATE_INVALID; u16 high_low; @@ -649,6 +626,7 @@ static void rs_get_rate(void *priv_r, struct ieee80211_supported_band *sband, struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; u16 fc, rate_mask; struct iwl3945_priv *priv = (struct iwl3945_priv *)priv_r; + struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); IWL_DEBUG_RATE("enter\n"); @@ -659,7 +637,7 @@ static void rs_get_rate(void *priv_r, struct ieee80211_supported_band *sband, is_multicast_ether_addr(hdr->addr1) || !sta || !priv_sta) { IWL_DEBUG_RATE("leave: No STA priv data to update!\n"); - sel->rate_idx = rate_lowest_index(sband, sta); + info->control.rates[0].idx = rate_lowest_index(sband, sta); return; } @@ -792,9 +770,10 @@ static void rs_get_rate(void *priv_r, struct ieee80211_supported_band *sband, rs_sta->last_txrate_idx = index; if (sband->band == IEEE80211_BAND_5GHZ) - sel->rate_idx = rs_sta->last_txrate_idx - IWL_FIRST_OFDM_RATE; + info->control.rates[0].idx = rs_sta->last_txrate_idx - + IWL_FIRST_OFDM_RATE; else - sel->rate_idx = rs_sta->last_txrate_idx; + info->control.rates[0].idx = rs_sta->last_txrate_idx; IWL_DEBUG_RATE("leave: %d\n", index); } diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.c b/drivers/net/wireless/iwlwifi/iwl-3945.c index 8a00245be51..7afafb62970 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945.c +++ b/drivers/net/wireless/iwlwifi/iwl-3945.c @@ -261,6 +261,35 @@ static inline const char *iwl3945_get_tx_fail_reason(u32 status) } #endif +/* + * get ieee prev rate from rate scale table. + * for A and B mode we need to overright prev + * value + */ +int iwl3945_rs_next_rate(struct iwl3945_priv *priv, int rate) +{ + int next_rate = iwl3945_get_prev_ieee_rate(rate); + + switch (priv->band) { + case IEEE80211_BAND_5GHZ: + if (rate == IWL_RATE_12M_INDEX) + next_rate = IWL_RATE_9M_INDEX; + else if (rate == IWL_RATE_6M_INDEX) + next_rate = IWL_RATE_6M_INDEX; + break; +/* XXX cannot be invoked in current mac80211 so not a regression + case MODE_IEEE80211B: + if (rate == IWL_RATE_11M_INDEX_TABLE) + next_rate = IWL_RATE_5M_INDEX_TABLE; + break; + */ + default: + break; + } + + return next_rate; +} + /** * iwl3945_tx_queue_reclaim - Reclaim Tx queue entries already Tx'd @@ -308,6 +337,7 @@ static void iwl3945_rx_reply_tx(struct iwl3945_priv *priv, struct iwl3945_tx_resp *tx_resp = (void *)&pkt->u.raw[0]; u32 status = le32_to_cpu(tx_resp->status); int rate_idx; + int fail, i; if ((index >= txq->q.n_bd) || (iwl3945_x2_queue_used(&txq->q, index) == 0)) { IWL_ERROR("Read index for DMA queue txq_id (%d) index %d " @@ -318,9 +348,36 @@ static void iwl3945_rx_reply_tx(struct iwl3945_priv *priv, } info = IEEE80211_SKB_CB(txq->txb[txq->q.read_ptr].skb[0]); - memset(&info->status, 0, sizeof(info->status)); + ieee80211_tx_info_clear_status(info); + + /* Fill the MRR chain with some info about on-chip retransmissions */ + rate_idx = iwl3945_hwrate_to_plcp_idx(tx_resp->rate); + if (info->band == IEEE80211_BAND_5GHZ) + rate_idx -= IWL_FIRST_OFDM_RATE; + + fail = tx_resp->failure_frame; + for (i = 0; i < IEEE80211_TX_MAX_RATES; i++) { + int next = iwl3945_rs_next_rate(priv, rate_idx); + + info->status.rates[i].idx = rate_idx; + + /* + * Put remaining into the last count as best approximation + * of saying exactly what the hardware would have done... + */ + if ((rate_idx == next) || (i == IEEE80211_TX_MAX_RATES - 1)) { + info->status.rates[i].count = fail; + break; + } + + info->status.rates[i].count = priv->retry_rate; + fail -= priv->retry_rate; + rate_idx = next; + if (fail <= 0) + break; + } + info->status.rates[i].count++; /* add final attempt */ - info->status.retry_count = tx_resp->failure_frame; /* tx_status->rts_retry_count = tx_resp->failure_rts; */ info->flags |= ((status & TX_STATUS_MSK) == TX_STATUS_SUCCESS) ? IEEE80211_TX_STAT_ACK : 0; @@ -329,10 +386,6 @@ static void iwl3945_rx_reply_tx(struct iwl3945_priv *priv, txq_id, iwl3945_get_tx_fail_reason(status), status, tx_resp->rate, tx_resp->failure_frame); - rate_idx = iwl3945_hwrate_to_plcp_idx(tx_resp->rate); - if (info->band == IEEE80211_BAND_5GHZ) - rate_idx -= IWL_FIRST_OFDM_RATE; - info->tx_rate_idx = rate_idx; IWL_DEBUG_TX_REPLY("Tx queue reclaim %d\n", index); iwl3945_tx_queue_reclaim(priv, txq_id, index); diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.h b/drivers/net/wireless/iwlwifi/iwl-3945.h index bdd32475b99..592c5958723 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945.h +++ b/drivers/net/wireless/iwlwifi/iwl-3945.h @@ -954,6 +954,8 @@ static inline int is_channel_ibss(const struct iwl3945_channel_info *ch) extern const struct iwl3945_channel_info *iwl3945_get_channel_info( const struct iwl3945_priv *priv, enum ieee80211_band band, u16 channel); +extern int iwl3945_rs_next_rate(struct iwl3945_priv *priv, int rate); + /* Requires full declaration of iwl3945_priv before including */ #include "iwl-3945-io.h" diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.c b/drivers/net/wireless/iwlwifi/iwl-4965.c index 9838de5f436..222c2baa95c 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965.c +++ b/drivers/net/wireless/iwlwifi/iwl-4965.c @@ -619,10 +619,10 @@ static void iwl4965_gain_computation(struct iwl_priv *priv, static void iwl4965_rts_tx_cmd_flag(struct ieee80211_tx_info *info, __le32 *tx_flags) { - if (info->flags & IEEE80211_TX_CTL_USE_RTS_CTS) { + if (info->control.rates[0].flags & IEEE80211_TX_RC_USE_RTS_CTS) { *tx_flags |= TX_CMD_FLG_RTS_MSK; *tx_flags &= ~TX_CMD_FLG_CTS_MSK; - } else if (info->flags & IEEE80211_TX_CTL_USE_CTS_PROTECT) { + } else if (info->control.rates[0].flags & IEEE80211_TX_RC_USE_CTS_PROTECT) { *tx_flags &= ~TX_CMD_FLG_RTS_MSK; *tx_flags |= TX_CMD_FLG_CTS_MSK; } @@ -2070,7 +2070,7 @@ static int iwl4965_tx_status_reply_tx(struct iwl_priv *priv, agg->frame_count, agg->start_idx, idx); info = IEEE80211_SKB_CB(priv->txq[txq_id].txb[idx].skb[0]); - info->status.retry_count = tx_resp->failure_frame; + info->status.rates[0].count = tx_resp->failure_frame + 1; info->flags &= ~IEEE80211_TX_CTL_AMPDU; info->flags |= iwl_is_tx_success(status)? IEEE80211_TX_STAT_ACK : 0; @@ -2227,7 +2227,7 @@ static void iwl4965_rx_reply_tx(struct iwl_priv *priv, iwl_txq_check_empty(priv, sta_id, tid, txq_id); } } else { - info->status.retry_count = tx_resp->failure_frame; + info->status.rates[0].count = tx_resp->failure_frame + 1; info->flags |= iwl_is_tx_success(status) ? IEEE80211_TX_STAT_ACK : 0; iwl_hwrate_to_tx_control(priv, diff --git a/drivers/net/wireless/iwlwifi/iwl-5000.c b/drivers/net/wireless/iwlwifi/iwl-5000.c index 56a3f0c84a1..d5282fa6508 100644 --- a/drivers/net/wireless/iwlwifi/iwl-5000.c +++ b/drivers/net/wireless/iwlwifi/iwl-5000.c @@ -390,8 +390,8 @@ static void iwl5000_chain_noise_reset(struct iwl_priv *priv) static void iwl5000_rts_tx_cmd_flag(struct ieee80211_tx_info *info, __le32 *tx_flags) { - if ((info->flags & IEEE80211_TX_CTL_USE_RTS_CTS) || - (info->flags & IEEE80211_TX_CTL_USE_CTS_PROTECT)) + if ((info->control.rates[0].flags & IEEE80211_TX_RC_USE_RTS_CTS) || + (info->control.rates[0].flags & IEEE80211_TX_RC_USE_CTS_PROTECT)) *tx_flags |= TX_CMD_FLG_RTS_CTS_MSK; else *tx_flags &= ~TX_CMD_FLG_RTS_CTS_MSK; @@ -1154,7 +1154,7 @@ static int iwl5000_tx_status_reply_tx(struct iwl_priv *priv, agg->frame_count, agg->start_idx, idx); info = IEEE80211_SKB_CB(priv->txq[txq_id].txb[idx].skb[0]); - info->status.retry_count = tx_resp->failure_frame; + info->status.rates[0].count = tx_resp->failure_frame + 1; info->flags &= ~IEEE80211_TX_CTL_AMPDU; info->flags |= iwl_is_tx_success(status)? IEEE80211_TX_STAT_ACK : 0; @@ -1307,7 +1307,7 @@ static void iwl5000_rx_reply_tx(struct iwl_priv *priv, iwl_txq_check_empty(priv, sta_id, tid, txq_id); } } else { - info->status.retry_count = tx_resp->failure_frame; + info->status.rates[0].count = tx_resp->failure_frame + 1; info->flags = iwl_is_tx_success(status) ? IEEE80211_TX_STAT_ACK : 0; iwl_hwrate_to_tx_control(priv, diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c index e10e0ca09ce..f685e5d6c28 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c @@ -798,7 +798,7 @@ static void rs_tx_status(void *priv_r, struct ieee80211_supported_band *sband, !(info->flags & IEEE80211_TX_STAT_AMPDU)) return; - retries = info->status.retry_count; + retries = info->status.rates[0].count - 1; if (retries > 15) retries = 15; @@ -830,20 +830,15 @@ static void rs_tx_status(void *priv_r, struct ieee80211_supported_band *sband, if (priv->band == IEEE80211_BAND_5GHZ) rs_index -= IWL_FIRST_OFDM_RATE; - if ((info->tx_rate_idx < 0) || - (tbl_type.is_SGI ^ - !!(info->flags & IEEE80211_TX_CTL_SHORT_GI)) || - (tbl_type.is_fat ^ - !!(info->flags & IEEE80211_TX_CTL_40_MHZ_WIDTH)) || - (tbl_type.is_dup ^ - !!(info->flags & IEEE80211_TX_CTL_DUP_DATA)) || - (tbl_type.ant_type ^ info->antenna_sel_tx) || - (!!(tx_rate & RATE_MCS_HT_MSK) ^ - !!(info->flags & IEEE80211_TX_CTL_OFDM_HT)) || - (!!(tx_rate & RATE_MCS_GF_MSK) ^ - !!(info->flags & IEEE80211_TX_CTL_GREEN_FIELD)) || + if ((info->status.rates[0].idx < 0) || + (tbl_type.is_SGI != !!(info->status.rates[0].flags & IEEE80211_TX_RC_SHORT_GI)) || + (tbl_type.is_fat != !!(info->status.rates[0].flags & IEEE80211_TX_RC_40_MHZ_WIDTH)) || + (tbl_type.is_dup != !!(info->status.rates[0].flags & IEEE80211_TX_RC_DUP_DATA)) || + (tbl_type.ant_type != info->antenna_sel_tx) || + (!!(tx_rate & RATE_MCS_HT_MSK) != !!(info->status.rates[0].flags & IEEE80211_TX_RC_MCS)) || + (!!(tx_rate & RATE_MCS_GF_MSK) != !!(info->status.rates[0].flags & IEEE80211_TX_RC_GREEN_FIELD)) || (hw->wiphy->bands[priv->band]->bitrates[rs_index].bitrate != - hw->wiphy->bands[info->band]->bitrates[info->tx_rate_idx].bitrate)) { + hw->wiphy->bands[info->band]->bitrates[info->status.rates[0].idx].bitrate)) { IWL_DEBUG_RATE("initial rate does not match 0x%x\n", tx_rate); goto out; } @@ -2098,15 +2093,17 @@ static void rs_initialize_lq(struct iwl_priv *priv, return; } -static void rs_get_rate(void *priv_r, struct ieee80211_supported_band *sband, - struct ieee80211_sta *sta, void *priv_sta, - struct sk_buff *skb, struct rate_selection *sel) +static void rs_get_rate(void *priv_r, struct ieee80211_sta *sta, void *priv_sta, + struct ieee80211_tx_rate_control *txrc) { int i; + struct sk_buff *skb = txrc->skb; + struct ieee80211_supported_band *sband = txrc->sband; struct iwl_priv *priv = (struct iwl_priv *)priv_r; struct ieee80211_conf *conf = &priv->hw->conf; struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; + struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); __le16 fc; struct iwl_lq_sta *lq_sta; @@ -2117,7 +2114,7 @@ static void rs_get_rate(void *priv_r, struct ieee80211_supported_band *sband, fc = hdr->frame_control; if (!ieee80211_is_data(fc) || is_multicast_ether_addr(hdr->addr1) || !sta || !priv_sta) { - sel->rate_idx = rate_lowest_index(sband, sta); + info->control.rates[0].idx = rate_lowest_index(sband, sta); return; } @@ -2143,13 +2140,13 @@ static void rs_get_rate(void *priv_r, struct ieee80211_supported_band *sband, } if ((i < 0) || (i > IWL_RATE_COUNT)) { - sel->rate_idx = rate_lowest_index(sband, sta); + info->control.rates[0].idx = rate_lowest_index(sband, sta); return; } if (sband->band == IEEE80211_BAND_5GHZ) i -= IWL_FIRST_OFDM_RATE; - sel->rate_idx = i; + info->control.rates[0].idx = i; } static void *rs_alloc_sta(void *priv_rate, struct ieee80211_sta *sta, diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c index 10f5a0a233f..2c4162e4814 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.c +++ b/drivers/net/wireless/iwlwifi/iwl-core.c @@ -88,26 +88,27 @@ EXPORT_SYMBOL(iwl_rates); * translate ucode response to mac80211 tx status control values */ void iwl_hwrate_to_tx_control(struct iwl_priv *priv, u32 rate_n_flags, - struct ieee80211_tx_info *control) + struct ieee80211_tx_info *info) { int rate_index; + struct ieee80211_tx_rate *r = &info->control.rates[0]; - control->antenna_sel_tx = + info->antenna_sel_tx = ((rate_n_flags & RATE_MCS_ANT_ABC_MSK) >> RATE_MCS_ANT_POS); if (rate_n_flags & RATE_MCS_HT_MSK) - control->flags |= IEEE80211_TX_CTL_OFDM_HT; + r->flags |= IEEE80211_TX_RC_MCS; if (rate_n_flags & RATE_MCS_GF_MSK) - control->flags |= IEEE80211_TX_CTL_GREEN_FIELD; + r->flags |= IEEE80211_TX_RC_GREEN_FIELD; if (rate_n_flags & RATE_MCS_FAT_MSK) - control->flags |= IEEE80211_TX_CTL_40_MHZ_WIDTH; + r->flags |= IEEE80211_TX_RC_40_MHZ_WIDTH; if (rate_n_flags & RATE_MCS_DUP_MSK) - control->flags |= IEEE80211_TX_CTL_DUP_DATA; + r->flags |= IEEE80211_TX_RC_DUP_DATA; if (rate_n_flags & RATE_MCS_SGI_MSK) - control->flags |= IEEE80211_TX_CTL_SHORT_GI; + r->flags |= IEEE80211_TX_RC_SHORT_GI; rate_index = iwl_hwrate_to_plcp_idx(rate_n_flags); - if (control->band == IEEE80211_BAND_5GHZ) + if (info->band == IEEE80211_BAND_5GHZ) rate_index -= IWL_FIRST_OFDM_RATE; - control->tx_rate_idx = rate_index; + r->idx = rate_index; } EXPORT_SYMBOL(iwl_hwrate_to_tx_control); diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c index b1464c71ea0..2cd33b4e9e1 100644 --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c @@ -2395,6 +2395,7 @@ static void iwl3945_build_tx_cmd_basic(struct iwl3945_priv *priv, { __le16 fc = hdr->frame_control; __le32 tx_flags = cmd->cmd.tx.tx_flags; + u8 rc_flags = info->control.rates[0].flags; cmd->cmd.tx.stop_time.life_time = TX_CMD_LIFE_TIME_INFINITE; if (!(info->flags & IEEE80211_TX_CTL_NO_ACK)) { @@ -2421,10 +2422,10 @@ static void iwl3945_build_tx_cmd_basic(struct iwl3945_priv *priv, tx_flags |= TX_CMD_FLG_SEQ_CTL_MSK; } - if (info->flags & IEEE80211_TX_CTL_USE_RTS_CTS) { + if (rc_flags & IEEE80211_TX_RC_USE_RTS_CTS) { tx_flags |= TX_CMD_FLG_RTS_MSK; tx_flags &= ~TX_CMD_FLG_CTS_MSK; - } else if (info->flags & IEEE80211_TX_CTL_USE_CTS_PROTECT) { + } else if (rc_flags & IEEE80211_TX_RC_USE_CTS_PROTECT) { tx_flags &= ~TX_CMD_FLG_RTS_MSK; tx_flags |= TX_CMD_FLG_CTS_MSK; } diff --git a/drivers/net/wireless/libertas_tf/main.c b/drivers/net/wireless/libertas_tf/main.c index 241ddcfa352..d1fc305de5f 100644 --- a/drivers/net/wireless/libertas_tf/main.c +++ b/drivers/net/wireless/libertas_tf/main.c @@ -592,14 +592,14 @@ EXPORT_SYMBOL_GPL(lbtf_remove_card); void lbtf_send_tx_feedback(struct lbtf_private *priv, u8 retrycnt, u8 fail) { struct ieee80211_tx_info *info = IEEE80211_SKB_CB(priv->tx_skb); - memset(&info->status, 0, sizeof(info->status)); + + ieee80211_tx_info_clear_status(info); /* * Commented out, otherwise we never go beyond 1Mbit/s using mac80211 * default pid rc algorithm. * * info->status.retry_count = MRVL_DEFAULT_RETRIES - retrycnt; */ - info->status.excessive_retries = fail ? 1 : 0; if (!(info->flags & IEEE80211_TX_CTL_NO_ACK) && !fail) info->flags |= IEEE80211_TX_STAT_ACK; skb_pull(priv->tx_skb, sizeof(struct txpd)); diff --git a/drivers/net/wireless/mac80211_hwsim.c b/drivers/net/wireless/mac80211_hwsim.c index e2aeef8de70..c5765232528 100644 --- a/drivers/net/wireless/mac80211_hwsim.c +++ b/drivers/net/wireless/mac80211_hwsim.c @@ -209,7 +209,7 @@ static bool mac80211_hwsim_tx_frame(struct ieee80211_hw *hw, /* TODO: set mactime */ rx_status.freq = data->channel->center_freq; rx_status.band = data->channel->band; - rx_status.rate_idx = info->tx_rate_idx; + rx_status.rate_idx = info->control.rates[0].idx; /* TODO: simulate signal strength (and optional packet drop) */ /* Copy skb to all enabled radios that are on the current frequency */ @@ -269,13 +269,9 @@ static int mac80211_hwsim_tx(struct ieee80211_hw *hw, struct sk_buff *skb) if (txi->control.sta) hwsim_check_sta_magic(txi->control.sta); - memset(&txi->status, 0, sizeof(txi->status)); - if (!(txi->flags & IEEE80211_TX_CTL_NO_ACK)) { - if (ack) - txi->flags |= IEEE80211_TX_STAT_ACK; - else - txi->status.excessive_retries = 1; - } + ieee80211_tx_info_clear_status(txi); + if (!(txi->flags & IEEE80211_TX_CTL_NO_ACK) && ack) + txi->flags |= IEEE80211_TX_STAT_ACK; ieee80211_tx_status_irqsafe(hw, skb); return NETDEV_TX_OK; } diff --git a/drivers/net/wireless/p54/p54common.c b/drivers/net/wireless/p54/p54common.c index 81a9756254f..65be5eca234 100644 --- a/drivers/net/wireless/p54/p54common.c +++ b/drivers/net/wireless/p54/p54common.c @@ -548,7 +548,7 @@ static void p54_rx_frame_sent(struct ieee80211_hw *dev, struct sk_buff *skb) spin_lock_irqsave(&priv->tx_queue.lock, flags); while (entry != (struct sk_buff *)&priv->tx_queue) { struct ieee80211_tx_info *info = IEEE80211_SKB_CB(entry); - range = (void *)info->driver_data; + range = (void *)info->rate_driver_data; if (range->start_addr == addr) { struct p54_control_hdr *entry_hdr; struct p54_tx_control_allocdata *entry_data; @@ -559,7 +559,7 @@ static void p54_rx_frame_sent(struct ieee80211_hw *dev, struct sk_buff *skb) struct memrecord *mr; ni = IEEE80211_SKB_CB(entry->next); - mr = (struct memrecord *)ni->driver_data; + mr = (struct memrecord *)ni->rate_driver_data; freed = mr->start_addr - last_addr; } else freed = priv->rx_end - last_addr; @@ -568,7 +568,7 @@ static void p54_rx_frame_sent(struct ieee80211_hw *dev, struct sk_buff *skb) __skb_unlink(entry, &priv->tx_queue); spin_unlock_irqrestore(&priv->tx_queue.lock, flags); - memset(&info->status, 0, sizeof(info->status)); + ieee80211_tx_info_clear_status(info); entry_hdr = (struct p54_control_hdr *) entry->data; entry_data = (struct p54_tx_control_allocdata *) entry_hdr->data; if ((entry_hdr->magic1 & cpu_to_le16(0x4000)) != 0) @@ -578,10 +578,8 @@ static void p54_rx_frame_sent(struct ieee80211_hw *dev, struct sk_buff *skb) if (!(info->flags & IEEE80211_TX_CTL_NO_ACK)) { if (!(payload->status & 0x01)) info->flags |= IEEE80211_TX_STAT_ACK; - else - info->status.excessive_retries = 1; } - info->status.retry_count = payload->retries - 1; + info->status.rates[0].count = payload->retries; info->status.ack_signal = p54_rssi_to_dbm(dev, le16_to_cpu(payload->ack_rssi)); skb_pull(entry, sizeof(*hdr) + pad + sizeof(*entry_data)); @@ -699,7 +697,7 @@ static void p54_assign_address(struct ieee80211_hw *dev, struct sk_buff *skb, while (left--) { u32 hole_size; struct ieee80211_tx_info *info = IEEE80211_SKB_CB(entry); - struct memrecord *range = (void *)info->driver_data; + struct memrecord *range = (void *)info->rate_driver_data; hole_size = range->start_addr - last_addr; if (!target_skb && hole_size >= len) { target_skb = entry->prev; @@ -715,7 +713,7 @@ static void p54_assign_address(struct ieee80211_hw *dev, struct sk_buff *skb, largest_hole = max(largest_hole, priv->rx_end - last_addr - len); if (!skb_queue_empty(&priv->tx_queue)) { struct ieee80211_tx_info *info = IEEE80211_SKB_CB(target_skb); - struct memrecord *range = (void *)info->driver_data; + struct memrecord *range = (void *)info->rate_driver_data; target_addr = range->end_addr; } } else @@ -723,7 +721,7 @@ static void p54_assign_address(struct ieee80211_hw *dev, struct sk_buff *skb, if (skb) { struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); - struct memrecord *range = (void *)info->driver_data; + struct memrecord *range = (void *)info->rate_driver_data; range->start_addr = target_addr; range->end_addr = target_addr + len; __skb_queue_after(&priv->tx_queue, target_skb, skb); @@ -806,6 +804,7 @@ static int p54_tx(struct ieee80211_hw *dev, struct sk_buff *skb) size_t padding, len; u8 rate; u8 cts_rate = 0x20; + u8 rc_flags; current_queue = &priv->tx_stats[skb_get_queue_mapping(skb) + 4]; if (unlikely(current_queue->len > current_queue->limit)) @@ -828,18 +827,19 @@ static int p54_tx(struct ieee80211_hw *dev, struct sk_buff *skb) hdr->magic1 = cpu_to_le16(0x0010); hdr->len = cpu_to_le16(len); hdr->type = (info->flags & IEEE80211_TX_CTL_NO_ACK) ? 0 : cpu_to_le16(1); - hdr->retry1 = hdr->retry2 = info->control.retry_limit; + hdr->retry1 = hdr->retry2 = info->control.rates[0].count; /* TODO: add support for alternate retry TX rates */ rate = ieee80211_get_tx_rate(dev, info)->hw_value; - if (info->flags & IEEE80211_TX_CTL_SHORT_PREAMBLE) { + rc_flags = info->control.rates[0].flags; + if (rc_flags & IEEE80211_TX_RC_USE_SHORT_PREAMBLE) { rate |= 0x10; cts_rate |= 0x10; } - if (info->flags & IEEE80211_TX_CTL_USE_RTS_CTS) { + if (rc_flags & IEEE80211_TX_RC_USE_RTS_CTS) { rate |= 0x40; cts_rate |= ieee80211_get_rts_cts_rate(dev, info)->hw_value; - } else if (info->flags & IEEE80211_TX_CTL_USE_CTS_PROTECT) { + } else if (rc_flags & IEEE80211_TX_RC_USE_CTS_PROTECT) { rate |= 0x20; cts_rate |= ieee80211_get_rts_cts_rate(dev, info)->hw_value; } diff --git a/drivers/net/wireless/rt2x00/rt2x00dev.c b/drivers/net/wireless/rt2x00/rt2x00dev.c index 697806cf94e..e1feab8b6b0 100644 --- a/drivers/net/wireless/rt2x00/rt2x00dev.c +++ b/drivers/net/wireless/rt2x00/rt2x00dev.c @@ -498,7 +498,9 @@ void rt2x00lib_txdone(struct queue_entry *entry, { struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev; struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(entry->skb); + struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb); enum data_queue_qid qid = skb_get_queue_mapping(entry->skb); + u8 rate_idx, rate_flags; /* * Unmap the skb. @@ -528,14 +530,18 @@ void rt2x00lib_txdone(struct queue_entry *entry, rt2x00dev->link.qual.tx_failed += test_bit(TXDONE_FAILURE, &txdesc->flags); + rate_idx = skbdesc->tx_rate_idx; + rate_flags = skbdesc->tx_rate_flags; + /* * Initialize TX status */ memset(&tx_info->status, 0, sizeof(tx_info->status)); tx_info->status.ack_signal = 0; - tx_info->status.excessive_retries = - test_bit(TXDONE_EXCESSIVE_RETRY, &txdesc->flags); - tx_info->status.retry_count = txdesc->retry; + tx_info->status.rates[0].idx = rate_idx; + tx_info->status.rates[0].flags = rate_flags; + tx_info->status.rates[0].count = txdesc->retry + 1; + tx_info->status.rates[1].idx = -1; /* terminate */ if (!(tx_info->flags & IEEE80211_TX_CTL_NO_ACK)) { if (test_bit(TXDONE_SUCCESS, &txdesc->flags)) @@ -544,7 +550,7 @@ void rt2x00lib_txdone(struct queue_entry *entry, rt2x00dev->low_level_stats.dot11ACKFailureCount++; } - if (tx_info->flags & IEEE80211_TX_CTL_USE_RTS_CTS) { + if (rate_flags & IEEE80211_TX_RC_USE_RTS_CTS) { if (test_bit(TXDONE_SUCCESS, &txdesc->flags)) rt2x00dev->low_level_stats.dot11RTSSuccessCount++; else if (test_bit(TXDONE_FAILURE, &txdesc->flags)) diff --git a/drivers/net/wireless/rt2x00/rt2x00mac.c b/drivers/net/wireless/rt2x00/rt2x00mac.c index 931183369f0..b32d59eafaa 100644 --- a/drivers/net/wireless/rt2x00/rt2x00mac.c +++ b/drivers/net/wireless/rt2x00/rt2x00mac.c @@ -39,7 +39,7 @@ static int rt2x00mac_tx_rts_cts(struct rt2x00_dev *rt2x00dev, unsigned int data_length; int retval = 0; - if (tx_info->flags & IEEE80211_TX_CTL_USE_CTS_PROTECT) + if (tx_info->control.rates[0].flags & IEEE80211_TX_RC_USE_CTS_PROTECT) data_length = sizeof(struct ieee80211_cts); else data_length = sizeof(struct ieee80211_rts); @@ -64,11 +64,11 @@ static int rt2x00mac_tx_rts_cts(struct rt2x00_dev *rt2x00dev, */ memcpy(skb->cb, frag_skb->cb, sizeof(skb->cb)); rts_info = IEEE80211_SKB_CB(skb); - rts_info->flags &= ~IEEE80211_TX_CTL_USE_RTS_CTS; - rts_info->flags &= ~IEEE80211_TX_CTL_USE_CTS_PROTECT; + rts_info->control.rates[0].flags &= ~IEEE80211_TX_RC_USE_RTS_CTS; + rts_info->control.rates[0].flags &= ~IEEE80211_TX_RC_USE_CTS_PROTECT; rts_info->flags &= ~IEEE80211_TX_CTL_REQ_TX_STATUS; - if (tx_info->flags & IEEE80211_TX_CTL_USE_CTS_PROTECT) + if (tx_info->control.rates[0].flags & IEEE80211_TX_RC_USE_CTS_PROTECT) rts_info->flags |= IEEE80211_TX_CTL_NO_ACK; else rts_info->flags &= ~IEEE80211_TX_CTL_NO_ACK; @@ -84,7 +84,7 @@ static int rt2x00mac_tx_rts_cts(struct rt2x00_dev *rt2x00dev, data_length += rt2x00crypto_tx_overhead(tx_info); #endif /* CONFIG_RT2X00_LIB_CRYPTO */ - if (tx_info->flags & IEEE80211_TX_CTL_USE_CTS_PROTECT) + if (tx_info->control.rates[0].flags & IEEE80211_TX_RC_USE_CTS_PROTECT) ieee80211_ctstoself_get(rt2x00dev->hw, tx_info->control.vif, frag_skb->data, data_length, tx_info, (struct ieee80211_cts *)(skb->data)); @@ -146,8 +146,8 @@ int rt2x00mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb) * inside the hardware. */ frame_control = le16_to_cpu(ieee80211hdr->frame_control); - if ((tx_info->flags & (IEEE80211_TX_CTL_USE_RTS_CTS | - IEEE80211_TX_CTL_USE_CTS_PROTECT)) && + if ((tx_info->control.rates[0].flags & (IEEE80211_TX_RC_USE_RTS_CTS | + IEEE80211_TX_RC_USE_CTS_PROTECT)) && !rt2x00dev->ops->hw->set_rts_threshold) { if (rt2x00queue_available(queue) <= 1) goto exit_fail; diff --git a/drivers/net/wireless/rt2x00/rt2x00queue.c b/drivers/net/wireless/rt2x00/rt2x00queue.c index 451d410ecda..070786ebd07 100644 --- a/drivers/net/wireless/rt2x00/rt2x00queue.c +++ b/drivers/net/wireless/rt2x00/rt2x00queue.c @@ -230,8 +230,15 @@ static void rt2x00queue_create_tx_descriptor(struct queue_entry *entry, /* * Determine retry information. */ - txdesc->retry_limit = tx_info->control.retry_limit; - if (tx_info->flags & IEEE80211_TX_CTL_LONG_RETRY_LIMIT) + txdesc->retry_limit = tx_info->control.rates[0].count - 1; + /* + * XXX: If at this point we knew whether the HW is going to use + * the RETRY_MODE bit or the retry_limit (currently all + * use the RETRY_MODE bit) we could do something like b43 + * does, set the RETRY_MODE bit when the RC algorithm is + * requesting more than the long retry limit. + */ + if (tx_info->control.rates[0].flags & IEEE80211_TX_RC_USE_RTS_CTS) __set_bit(ENTRY_TXD_RETRY_MODE, &txdesc->flags); /* @@ -371,10 +378,12 @@ static void rt2x00queue_write_tx_descriptor(struct queue_entry *entry, int rt2x00queue_write_tx_frame(struct data_queue *queue, struct sk_buff *skb) { + struct ieee80211_tx_info *tx_info; struct queue_entry *entry = rt2x00queue_get_entry(queue, Q_INDEX); struct txentry_desc txdesc; struct skb_frame_desc *skbdesc; unsigned int iv_len = 0; + u8 rate_idx, rate_flags; if (unlikely(rt2x00queue_full(queue))) return -EINVAL; @@ -399,13 +408,18 @@ int rt2x00queue_write_tx_frame(struct data_queue *queue, struct sk_buff *skb) iv_len = IEEE80211_SKB_CB(skb)->control.hw_key->iv_len; /* - * All information is retreived from the skb->cb array, + * All information is retrieved from the skb->cb array, * now we should claim ownership of the driver part of that - * array. + * array, preserving the bitrate index and flags. */ + tx_info = IEEE80211_SKB_CB(skb); + rate_idx = tx_info->control.rates[0].idx; + rate_flags = tx_info->control.rates[0].flags; skbdesc = get_skb_frame_desc(entry->skb); memset(skbdesc, 0, sizeof(*skbdesc)); skbdesc->entry = entry; + skbdesc->tx_rate_idx = rate_idx; + skbdesc->tx_rate_flags = rate_flags; /* * When hardware encryption is supported, and this frame diff --git a/drivers/net/wireless/rt2x00/rt2x00queue.h b/drivers/net/wireless/rt2x00/rt2x00queue.h index 9dbf04f0f04..4d3c7246f9a 100644 --- a/drivers/net/wireless/rt2x00/rt2x00queue.h +++ b/drivers/net/wireless/rt2x00/rt2x00queue.h @@ -104,6 +104,8 @@ enum skb_frame_desc_flags { * * @flags: Frame flags, see &enum skb_frame_desc_flags. * @desc_len: Length of the frame descriptor. + * @tx_rate_idx: the index of the TX rate, used for TX status reporting + * @tx_rate_flags: the TX rate flags, used for TX status reporting * @desc: Pointer to descriptor part of the frame. * Note that this pointer could point to something outside * of the scope of the skb->data pointer. @@ -113,9 +115,12 @@ enum skb_frame_desc_flags { * @entry: The entry to which this sk buffer belongs. */ struct skb_frame_desc { - unsigned int flags; + u8 flags; + + u8 desc_len; + u8 tx_rate_idx; + u8 tx_rate_flags; - unsigned int desc_len; void *desc; __le32 iv; diff --git a/drivers/net/wireless/rtl8180_dev.c b/drivers/net/wireless/rtl8180_dev.c index e8d22393797..6c226c024dd 100644 --- a/drivers/net/wireless/rtl8180_dev.c +++ b/drivers/net/wireless/rtl8180_dev.c @@ -182,15 +182,13 @@ static void rtl8180_handle_tx(struct ieee80211_hw *dev, unsigned int prio) skb->len, PCI_DMA_TODEVICE); info = IEEE80211_SKB_CB(skb); - memset(&info->status, 0, sizeof(info->status)); + ieee80211_tx_info_clear_status(info); - if (!(info->flags & IEEE80211_TX_CTL_NO_ACK)) { - if (flags & RTL818X_TX_DESC_FLAG_TX_OK) - info->flags |= IEEE80211_TX_STAT_ACK; - else - info->status.excessive_retries = 1; - } - info->status.retry_count = flags & 0xFF; + if (!(info->flags & IEEE80211_TX_CTL_NO_ACK) && + (flags & RTL818X_TX_DESC_FLAG_TX_OK)) + info->flags |= IEEE80211_TX_STAT_ACK; + + info->status.rates[0].count = (flags & 0xFF) + 1; ieee80211_tx_status_irqsafe(dev, skb); if (ring->entries - skb_queue_len(&ring->queue) == 2) @@ -243,6 +241,7 @@ static int rtl8180_tx(struct ieee80211_hw *dev, struct sk_buff *skb) unsigned int idx, prio; dma_addr_t mapping; u32 tx_flags; + u8 rc_flags; u16 plcp_len = 0; __le16 rts_duration = 0; @@ -261,15 +260,16 @@ static int rtl8180_tx(struct ieee80211_hw *dev, struct sk_buff *skb) tx_flags |= RTL818X_TX_DESC_FLAG_DMA | RTL818X_TX_DESC_FLAG_NO_ENC; - if (info->flags & IEEE80211_TX_CTL_USE_RTS_CTS) { + rc_flags = info->control.rates[0].flags; + if (rc_flags & IEEE80211_TX_RC_USE_RTS_CTS) { tx_flags |= RTL818X_TX_DESC_FLAG_RTS; tx_flags |= ieee80211_get_rts_cts_rate(dev, info)->hw_value << 19; - } else if (info->flags & IEEE80211_TX_CTL_USE_CTS_PROTECT) { + } else if (rc_flags & IEEE80211_TX_RC_USE_CTS_PROTECT) { tx_flags |= RTL818X_TX_DESC_FLAG_CTS; tx_flags |= ieee80211_get_rts_cts_rate(dev, info)->hw_value << 19; } - if (info->flags & IEEE80211_TX_CTL_USE_RTS_CTS) + if (rc_flags & IEEE80211_TX_RC_USE_RTS_CTS) rts_duration = ieee80211_rts_duration(dev, priv->vif, skb->len, info); @@ -292,9 +292,9 @@ static int rtl8180_tx(struct ieee80211_hw *dev, struct sk_buff *skb) entry->plcp_len = cpu_to_le16(plcp_len); entry->tx_buf = cpu_to_le32(mapping); entry->frame_len = cpu_to_le32(skb->len); - entry->flags2 = info->control.retries[0].rate_idx >= 0 ? + entry->flags2 = info->control.rates[1].idx >= 0 ? ieee80211_get_alt_retry_rate(dev, info, 0)->bitrate << 4 : 0; - entry->retry_limit = info->control.retry_limit; + entry->retry_limit = info->control.rates[0].count; entry->flags = cpu_to_le32(tx_flags); __skb_queue_tail(&ring->queue, skb); if (ring->entries - skb_queue_len(&ring->queue) < 2) @@ -855,7 +855,7 @@ static int __devinit rtl8180_probe(struct pci_dev *pdev, priv = dev->priv; priv->pdev = pdev; - dev->max_altrates = 1; + dev->max_rates = 2; SET_IEEE80211_DEV(dev, &pdev->dev); pci_set_drvdata(pdev, dev); diff --git a/drivers/net/wireless/rtl8187_dev.c b/drivers/net/wireless/rtl8187_dev.c index cd839bcb6d7..6260ed8ce12 100644 --- a/drivers/net/wireless/rtl8187_dev.c +++ b/drivers/net/wireless/rtl8187_dev.c @@ -160,13 +160,13 @@ static void rtl8187_tx_cb(struct urb *urb) { struct sk_buff *skb = (struct sk_buff *)urb->context; struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); - struct ieee80211_hw *hw = info->driver_data[0]; + struct ieee80211_hw *hw = info->rate_driver_data[0]; struct rtl8187_priv *priv = hw->priv; - usb_free_urb(info->driver_data[1]); + usb_free_urb(info->rate_driver_data[1]); skb_pull(skb, priv->is_rtl8187b ? sizeof(struct rtl8187b_tx_hdr) : sizeof(struct rtl8187_tx_hdr)); - memset(&info->status, 0, sizeof(info->status)); + ieee80211_tx_info_clear_status(info); info->flags |= IEEE80211_TX_STAT_ACK; ieee80211_tx_status_irqsafe(hw, skb); } @@ -194,12 +194,12 @@ static int rtl8187_tx(struct ieee80211_hw *dev, struct sk_buff *skb) flags |= ieee80211_get_tx_rate(dev, info)->hw_value << 24; if (ieee80211_has_morefrags(((struct ieee80211_hdr *)skb->data)->frame_control)) flags |= RTL818X_TX_DESC_FLAG_MOREFRAG; - if (info->flags & IEEE80211_TX_CTL_USE_RTS_CTS) { + if (info->control.rates[0].flags & IEEE80211_TX_RC_USE_RTS_CTS) { flags |= RTL818X_TX_DESC_FLAG_RTS; flags |= ieee80211_get_rts_cts_rate(dev, info)->hw_value << 19; rts_dur = ieee80211_rts_duration(dev, priv->vif, skb->len, info); - } else if (info->flags & IEEE80211_TX_CTL_USE_CTS_PROTECT) { + } else if (info->control.rates[0].flags & IEEE80211_TX_RC_USE_CTS_PROTECT) { flags |= RTL818X_TX_DESC_FLAG_CTS; flags |= ieee80211_get_rts_cts_rate(dev, info)->hw_value << 19; } @@ -210,7 +210,7 @@ static int rtl8187_tx(struct ieee80211_hw *dev, struct sk_buff *skb) hdr->flags = cpu_to_le32(flags); hdr->len = 0; hdr->rts_duration = rts_dur; - hdr->retry = cpu_to_le32(info->control.retry_limit << 8); + hdr->retry = cpu_to_le32((info->control.rates[0].count - 1) << 8); buf = hdr; ep = 2; @@ -228,7 +228,7 @@ static int rtl8187_tx(struct ieee80211_hw *dev, struct sk_buff *skb) memset(hdr, 0, sizeof(*hdr)); hdr->flags = cpu_to_le32(flags); hdr->rts_duration = rts_dur; - hdr->retry = cpu_to_le32(info->control.retry_limit << 8); + hdr->retry = cpu_to_le32((info->control.rates[0].count - 1) << 8); hdr->tx_duration = ieee80211_generic_frame_duration(dev, priv->vif, skb->len, txrate); @@ -240,8 +240,8 @@ static int rtl8187_tx(struct ieee80211_hw *dev, struct sk_buff *skb) ep = epmap[skb_get_queue_mapping(skb)]; } - info->driver_data[0] = dev; - info->driver_data[1] = urb; + info->rate_driver_data[0] = dev; + info->rate_driver_data[1] = urb; usb_fill_bulk_urb(urb, priv->udev, usb_sndbulkpipe(priv->udev, ep), buf, skb->len, rtl8187_tx_cb, skb); diff --git a/drivers/net/wireless/zd1211rw/zd_mac.c b/drivers/net/wireless/zd1211rw/zd_mac.c index 6c3e21887fc..2f0802b29c4 100644 --- a/drivers/net/wireless/zd1211rw/zd_mac.c +++ b/drivers/net/wireless/zd1211rw/zd_mac.c @@ -296,15 +296,14 @@ static void zd_op_stop(struct ieee80211_hw *hw) * If no status information has been requested, the skb is freed. */ static void tx_status(struct ieee80211_hw *hw, struct sk_buff *skb, - u32 flags, int ackssi, bool success) + int ackssi, bool success) { struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); - memset(&info->status, 0, sizeof(info->status)); + ieee80211_tx_info_clear_status(info); - if (!success) - info->status.excessive_retries = 1; - info->flags |= flags; + if (success) + info->flags |= IEEE80211_TX_STAT_ACK; info->status.ack_signal = ackssi; ieee80211_tx_status_irqsafe(hw, skb); } @@ -326,7 +325,7 @@ void zd_mac_tx_failed(struct ieee80211_hw *hw) if (skb == NULL) return; - tx_status(hw, skb, 0, 0, 0); + tx_status(hw, skb, 0, 0); } /** @@ -342,12 +341,12 @@ void zd_mac_tx_failed(struct ieee80211_hw *hw) void zd_mac_tx_to_dev(struct sk_buff *skb, int error) { struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); - struct ieee80211_hw *hw = info->driver_data[0]; + struct ieee80211_hw *hw = info->rate_driver_data[0]; skb_pull(skb, sizeof(struct zd_ctrlset)); if (unlikely(error || (info->flags & IEEE80211_TX_CTL_NO_ACK))) { - tx_status(hw, skb, 0, 0, !error); + tx_status(hw, skb, 0, !error); } else { struct sk_buff_head *q = &zd_hw_mac(hw)->ack_wait_queue; @@ -406,7 +405,8 @@ static int zd_calc_tx_length_us(u8 *service, u8 zd_rate, u16 tx_length) } static void cs_set_control(struct zd_mac *mac, struct zd_ctrlset *cs, - struct ieee80211_hdr *header, u32 flags) + struct ieee80211_hdr *header, + struct ieee80211_tx_info *info) { /* * CONTROL TODO: @@ -417,7 +417,7 @@ static void cs_set_control(struct zd_mac *mac, struct zd_ctrlset *cs, cs->control = 0; /* First fragment */ - if (flags & IEEE80211_TX_CTL_FIRST_FRAGMENT) + if (info->flags & IEEE80211_TX_CTL_FIRST_FRAGMENT) cs->control |= ZD_CS_NEED_RANDOM_BACKOFF; /* Multicast */ @@ -428,10 +428,10 @@ static void cs_set_control(struct zd_mac *mac, struct zd_ctrlset *cs, if (ieee80211_is_pspoll(header->frame_control)) cs->control |= ZD_CS_PS_POLL_FRAME; - if (flags & IEEE80211_TX_CTL_USE_RTS_CTS) + if (info->control.rates[0].flags & IEEE80211_TX_RC_USE_RTS_CTS) cs->control |= ZD_CS_RTS; - if (flags & IEEE80211_TX_CTL_USE_CTS_PROTECT) + if (info->control.rates[0].flags & IEEE80211_TX_RC_USE_CTS_PROTECT) cs->control |= ZD_CS_SELF_CTS; /* FIXME: Management frame? */ @@ -517,12 +517,12 @@ static int fill_ctrlset(struct zd_mac *mac, txrate = ieee80211_get_tx_rate(mac->hw, info); cs->modulation = txrate->hw_value; - if (info->flags & IEEE80211_TX_CTL_SHORT_PREAMBLE) + if (info->control.rates[0].flags & IEEE80211_TX_RC_USE_SHORT_PREAMBLE) cs->modulation = txrate->hw_value_short; cs->tx_length = cpu_to_le16(frag_len); - cs_set_control(mac, cs, hdr, info->flags); + cs_set_control(mac, cs, hdr, info); packet_length = frag_len + sizeof(struct zd_ctrlset) + 10; ZD_ASSERT(packet_length <= 0xffff); @@ -577,7 +577,7 @@ static int zd_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb) if (r) return r; - info->driver_data[0] = hw; + info->rate_driver_data[0] = hw; r = zd_usb_tx(&mac->chip.usb, skb); if (r) @@ -618,7 +618,7 @@ static int filter_ack(struct ieee80211_hw *hw, struct ieee80211_hdr *rx_hdr, if (likely(!compare_ether_addr(tx_hdr->addr2, rx_hdr->addr1))) { __skb_unlink(skb, q); - tx_status(hw, skb, IEEE80211_TX_STAT_ACK, stats->signal, 1); + tx_status(hw, skb, stats->signal, 1); goto out; } } diff --git a/drivers/net/wireless/zd1211rw/zd_usb.c b/drivers/net/wireless/zd1211rw/zd_usb.c index a60ae86bd5c..d7a2f52e40c 100644 --- a/drivers/net/wireless/zd1211rw/zd_usb.c +++ b/drivers/net/wireless/zd1211rw/zd_usb.c @@ -907,7 +907,7 @@ free_urb: * it might be freed by zd_mac_tx_to_dev or mac80211) */ info = IEEE80211_SKB_CB(skb); - usb = &zd_hw_mac(info->driver_data[0])->chip.usb; + usb = &zd_hw_mac(info->rate_driver_data[0])->chip.usb; zd_mac_tx_to_dev(skb, urb->status); free_tx_urb(usb, urb); tx_dec_submitted_urbs(usb); diff --git a/include/net/mac80211.h b/include/net/mac80211.h index 9801afb6254..3741c0a7978 100644 --- a/include/net/mac80211.h +++ b/include/net/mac80211.h @@ -214,29 +214,24 @@ struct ieee80211_bss_conf { * These flags are used with the @flags member of &ieee80211_tx_info. * * @IEEE80211_TX_CTL_REQ_TX_STATUS: request TX status callback for this frame. - * @IEEE80211_TX_CTL_USE_RTS_CTS: use RTS-CTS before sending frame - * @IEEE80211_TX_CTL_USE_CTS_PROTECT: use CTS protection for the frame (e.g., - * for combined 802.11g / 802.11b networks) + * @IEEE80211_TX_CTL_ASSIGN_SEQ: The driver has to assign a sequence + * number to this frame, taking care of not overwriting the fragment + * number and increasing the sequence number only when the + * IEEE80211_TX_CTL_FIRST_FRAGMENT flag is set. mac80211 will properly + * assign sequence numbers to QoS-data frames but cannot do so correctly + * for non-QoS-data and management frames because beacons need them from + * that counter as well and mac80211 cannot guarantee proper sequencing. + * If this flag is set, the driver should instruct the hardware to + * assign a sequence number to the frame or assign one itself. Cf. IEEE + * 802.11-2007 7.1.3.4.1 paragraph 3. This flag will always be set for + * beacons and always be clear for frames without a sequence number field. * @IEEE80211_TX_CTL_NO_ACK: tell the low level not to wait for an ack - * @IEEE80211_TX_CTL_RATE_CTRL_PROBE: TBD * @IEEE80211_TX_CTL_CLEAR_PS_FILT: clear powersave filter for destination * station - * @IEEE80211_TX_CTL_REQUEUE: TBD * @IEEE80211_TX_CTL_FIRST_FRAGMENT: this is a first fragment of the frame - * @IEEE80211_TX_CTL_SHORT_PREAMBLE: TBD - * @IEEE80211_TX_CTL_LONG_RETRY_LIMIT: this frame should be send using the - * through set_retry_limit configured long retry value * @IEEE80211_TX_CTL_SEND_AFTER_DTIM: send this frame after DTIM beacon * @IEEE80211_TX_CTL_AMPDU: this frame should be sent as part of an A-MPDU - * @IEEE80211_TX_CTL_OFDM_HT: this frame can be sent in HT OFDM rates. number - * of streams when this flag is on can be extracted from antenna_sel_tx, - * so if 1 antenna is marked use SISO, 2 antennas marked use MIMO, n - * antennas marked use MIMO_n. - * @IEEE80211_TX_CTL_GREEN_FIELD: use green field protection for this frame - * @IEEE80211_TX_CTL_40_MHZ_WIDTH: send this frame using 40 Mhz channel width - * @IEEE80211_TX_CTL_DUP_DATA: duplicate data frame on both 20 Mhz channels - * @IEEE80211_TX_CTL_SHORT_GI: send this frame using short guard interval - * @IEEE80211_TX_CTL_INJECTED: TBD + * @IEEE80211_TX_CTL_INJECTED: Frame was injected, internal to mac80211. * @IEEE80211_TX_STAT_TX_FILTERED: The frame was not transmitted * because the destination STA was in powersave mode. * @IEEE80211_TX_STAT_ACK: Frame was acknowledged @@ -244,62 +239,70 @@ struct ieee80211_bss_conf { * is for the whole aggregation. * @IEEE80211_TX_STAT_AMPDU_NO_BACK: no block ack was returned, * so consider using block ack request (BAR). - * @IEEE80211_TX_CTL_ASSIGN_SEQ: The driver has to assign a sequence - * number to this frame, taking care of not overwriting the fragment - * number and increasing the sequence number only when the - * IEEE80211_TX_CTL_FIRST_FRAGMENT flags is set. mac80211 will properly - * assign sequence numbers to QoS-data frames but cannot do so correctly - * for non-QoS-data and management frames because beacons need them from - * that counter as well and mac80211 cannot guarantee proper sequencing. - * If this flag is set, the driver should instruct the hardware to - * assign a sequence number to the frame or assign one itself. Cf. IEEE - * 802.11-2007 7.1.3.4.1 paragraph 3. This flag will always be set for - * beacons always be clear for frames without a sequence number field. + * @IEEE80211_TX_CTL_RATE_CTRL_PROBE: internal to mac80211, can be + * set by rate control algorithms to indicate probe rate, will + * be cleared for fragmented frames (except on the last fragment) + * @IEEE80211_TX_CTL_REQUEUE: REMOVE THIS */ enum mac80211_tx_control_flags { IEEE80211_TX_CTL_REQ_TX_STATUS = BIT(0), - IEEE80211_TX_CTL_USE_RTS_CTS = BIT(2), - IEEE80211_TX_CTL_USE_CTS_PROTECT = BIT(3), - IEEE80211_TX_CTL_NO_ACK = BIT(4), - IEEE80211_TX_CTL_RATE_CTRL_PROBE = BIT(5), - IEEE80211_TX_CTL_CLEAR_PS_FILT = BIT(6), - IEEE80211_TX_CTL_REQUEUE = BIT(7), - IEEE80211_TX_CTL_FIRST_FRAGMENT = BIT(8), - IEEE80211_TX_CTL_SHORT_PREAMBLE = BIT(9), - IEEE80211_TX_CTL_LONG_RETRY_LIMIT = BIT(10), - IEEE80211_TX_CTL_SEND_AFTER_DTIM = BIT(12), - IEEE80211_TX_CTL_AMPDU = BIT(13), - IEEE80211_TX_CTL_OFDM_HT = BIT(14), - IEEE80211_TX_CTL_GREEN_FIELD = BIT(15), - IEEE80211_TX_CTL_40_MHZ_WIDTH = BIT(16), - IEEE80211_TX_CTL_DUP_DATA = BIT(17), - IEEE80211_TX_CTL_SHORT_GI = BIT(18), - IEEE80211_TX_CTL_INJECTED = BIT(19), - IEEE80211_TX_STAT_TX_FILTERED = BIT(20), - IEEE80211_TX_STAT_ACK = BIT(21), - IEEE80211_TX_STAT_AMPDU = BIT(22), - IEEE80211_TX_STAT_AMPDU_NO_BACK = BIT(23), - IEEE80211_TX_CTL_ASSIGN_SEQ = BIT(24), + IEEE80211_TX_CTL_ASSIGN_SEQ = BIT(1), + IEEE80211_TX_CTL_NO_ACK = BIT(2), + IEEE80211_TX_CTL_CLEAR_PS_FILT = BIT(3), + IEEE80211_TX_CTL_FIRST_FRAGMENT = BIT(4), + IEEE80211_TX_CTL_SEND_AFTER_DTIM = BIT(5), + IEEE80211_TX_CTL_AMPDU = BIT(6), + IEEE80211_TX_CTL_INJECTED = BIT(7), + IEEE80211_TX_STAT_TX_FILTERED = BIT(8), + IEEE80211_TX_STAT_ACK = BIT(9), + IEEE80211_TX_STAT_AMPDU = BIT(10), + IEEE80211_TX_STAT_AMPDU_NO_BACK = BIT(11), + IEEE80211_TX_CTL_RATE_CTRL_PROBE = BIT(12), + + /* XXX: remove this */ + IEEE80211_TX_CTL_REQUEUE = BIT(13), }; +enum mac80211_rate_control_flags { + IEEE80211_TX_RC_USE_RTS_CTS = BIT(0), + IEEE80211_TX_RC_USE_CTS_PROTECT = BIT(1), + IEEE80211_TX_RC_USE_SHORT_PREAMBLE = BIT(2), + + /* rate index is an MCS rate number instead of an index */ + IEEE80211_TX_RC_MCS = BIT(3), + IEEE80211_TX_RC_GREEN_FIELD = BIT(4), + IEEE80211_TX_RC_40_MHZ_WIDTH = BIT(5), + IEEE80211_TX_RC_DUP_DATA = BIT(6), + IEEE80211_TX_RC_SHORT_GI = BIT(7), +}; + + +/* there are 40 bytes if you don't need the rateset to be kept */ +#define IEEE80211_TX_INFO_DRIVER_DATA_SIZE 40 -#define IEEE80211_TX_INFO_DRIVER_DATA_SIZE \ - (sizeof(((struct sk_buff *)0)->cb) - 8) -#define IEEE80211_TX_INFO_DRIVER_DATA_PTRS \ - (IEEE80211_TX_INFO_DRIVER_DATA_SIZE / sizeof(void *)) +/* if you do need the rateset, then you have less space */ +#define IEEE80211_TX_INFO_RATE_DRIVER_DATA_SIZE 24 -/* maximum number of alternate rate retry stages */ -#define IEEE80211_TX_MAX_ALTRATE 3 +/* maximum number of rate stages */ +#define IEEE80211_TX_MAX_RATES 5 /** - * struct ieee80211_tx_altrate - alternate rate selection/status + * struct ieee80211_tx_rate - rate selection/status * - * @rate_idx: rate index to attempt to send with + * @idx: rate index to attempt to send with + * @flags: rate control flags (&enum mac80211_rate_control_flags) * @limit: number of retries before fallback + * + * A value of -1 for @idx indicates an invalid rate and, if used + * in an array of retry rates, that no more rates should be tried. + * + * When used for transmit status reporting, the driver should + * always report the rate along with the flags it used. */ -struct ieee80211_tx_altrate { - s8 rate_idx; - u8 limit; +struct ieee80211_tx_rate { + s8 idx; + u8 count; + u8 flags; }; /** @@ -314,15 +317,12 @@ struct ieee80211_tx_altrate { * it may be NULL. * * @flags: transmit info flags, defined above - * @band: TBD - * @tx_rate_idx: TBD + * @band: the band to transmit on (use for checking for races) * @antenna_sel_tx: antenna to use, 0 for automatic diversity * @control: union for control data * @status: union for status data * @driver_data: array of driver_data pointers * @retry_count: number of retries - * @excessive_retries: set to 1 if the frame was retried many times - * but not acknowledged * @ampdu_ack_len: number of aggregated frames. * relevant only if IEEE80211_TX_STATUS_AMPDU was set. * @ampdu_ack_map: block ack bit map for the aggregation. @@ -333,31 +333,43 @@ struct ieee80211_tx_info { /* common information */ u32 flags; u8 band; - s8 tx_rate_idx; + u8 antenna_sel_tx; - /* 1 byte hole */ + /* 2 byte hole */ union { struct { + union { + /* rate control */ + struct { + struct ieee80211_tx_rate rates[ + IEEE80211_TX_MAX_RATES]; + s8 rts_cts_rate_idx; + }; + /* only needed before rate control */ + unsigned long jiffies; + }; /* NB: vif can be NULL for injected frames */ struct ieee80211_vif *vif; struct ieee80211_key_conf *hw_key; struct ieee80211_sta *sta; - unsigned long jiffies; - s8 rts_cts_rate_idx; - u8 retry_limit; - struct ieee80211_tx_altrate retries[IEEE80211_TX_MAX_ALTRATE]; } control; struct { + struct ieee80211_tx_rate rates[IEEE80211_TX_MAX_RATES]; + u8 ampdu_ack_len; u64 ampdu_ack_map; int ack_signal; - struct ieee80211_tx_altrate retries[IEEE80211_TX_MAX_ALTRATE + 1]; - u8 retry_count; - bool excessive_retries; - u8 ampdu_ack_len; + /* 8 bytes free */ } status; - void *driver_data[IEEE80211_TX_INFO_DRIVER_DATA_PTRS]; + struct { + struct ieee80211_tx_rate driver_rates[ + IEEE80211_TX_MAX_RATES]; + void *rate_driver_data[ + IEEE80211_TX_INFO_RATE_DRIVER_DATA_SIZE / sizeof(void *)]; + }; + void *driver_data[ + IEEE80211_TX_INFO_DRIVER_DATA_SIZE / sizeof(void *)]; }; }; @@ -366,6 +378,41 @@ static inline struct ieee80211_tx_info *IEEE80211_SKB_CB(struct sk_buff *skb) return (struct ieee80211_tx_info *)skb->cb; } +/** + * ieee80211_tx_info_clear_status - clear TX status + * + * @info: The &struct ieee80211_tx_info to be cleared. + * + * When the driver passes an skb back to mac80211, it must report + * a number of things in TX status. This function clears everything + * in the TX status but the rate control information (it does clear + * the count since you need to fill that in anyway). + * + * NOTE: You can only use this function if you do NOT use + * info->driver_data! Use info->rate_driver_data + * instead if you need only the less space that allows. + */ +static inline void +ieee80211_tx_info_clear_status(struct ieee80211_tx_info *info) +{ + int i; + + BUILD_BUG_ON(offsetof(struct ieee80211_tx_info, status.rates) != + offsetof(struct ieee80211_tx_info, control.rates)); + BUILD_BUG_ON(offsetof(struct ieee80211_tx_info, status.rates) != + offsetof(struct ieee80211_tx_info, driver_rates)); + BUILD_BUG_ON(offsetof(struct ieee80211_tx_info, status.rates) != 8); + /* clear the rate counts */ + for (i = 0; i < IEEE80211_TX_MAX_RATES; i++) + info->status.rates[i].count = 0; + + BUILD_BUG_ON( + offsetof(struct ieee80211_tx_info, status.ampdu_ack_len) != 23); + memset(&info->status.ampdu_ack_len, 0, + sizeof(struct ieee80211_tx_info) - + offsetof(struct ieee80211_tx_info, status.ampdu_ack_len)); +} + /** * enum mac80211_rx_flags - receive flags @@ -869,8 +916,8 @@ enum ieee80211_hw_flags { * @sta_data_size: size (in bytes) of the drv_priv data area * within &struct ieee80211_sta. * - * @max_altrates: maximum number of alternate rate retry stages - * @max_altrate_tries: maximum number of tries for each stage + * @max_rates: maximum number of alternate rate retry stages + * @max_rate_tries: maximum number of tries for each stage */ struct ieee80211_hw { struct ieee80211_conf conf; @@ -887,8 +934,8 @@ struct ieee80211_hw { u16 ampdu_queues; u16 max_listen_interval; s8 max_signal; - u8 max_altrates; - u8 max_altrate_tries; + u8 max_rates; + u8 max_rate_tries; }; /** @@ -927,9 +974,9 @@ static inline struct ieee80211_rate * ieee80211_get_tx_rate(const struct ieee80211_hw *hw, const struct ieee80211_tx_info *c) { - if (WARN_ON(c->tx_rate_idx < 0)) + if (WARN_ON(c->control.rates[0].idx < 0)) return NULL; - return &hw->wiphy->bands[c->band]->bitrates[c->tx_rate_idx]; + return &hw->wiphy->bands[c->band]->bitrates[c->control.rates[0].idx]; } static inline struct ieee80211_rate * @@ -945,9 +992,9 @@ static inline struct ieee80211_rate * ieee80211_get_alt_retry_rate(const struct ieee80211_hw *hw, const struct ieee80211_tx_info *c, int idx) { - if (c->control.retries[idx].rate_idx < 0) + if (c->control.rates[idx + 1].idx < 0) return NULL; - return &hw->wiphy->bands[c->band]->bitrates[c->control.retries[idx].rate_idx]; + return &hw->wiphy->bands[c->band]->bitrates[c->control.rates[idx + 1].idx]; } /** @@ -1840,17 +1887,30 @@ struct ieee80211_sta *ieee80211_find_sta(struct ieee80211_hw *hw, /* Rate control API */ + /** - * struct rate_selection - rate information for/from rate control algorithms - * - * @rate_idx: selected transmission rate index - * @nonerp_idx: Non-ERP rate to use instead if ERP cannot be used - * @probe_idx: rate for probing (or -1) - * @max_rate_idx: maximum rate index that can be used, this is - * input to the algorithm and will be enforced - */ -struct rate_selection { - s8 rate_idx, nonerp_idx, probe_idx, max_rate_idx; + * struct ieee80211_tx_rate_control - rate control information for/from RC algo + * + * @hw: The hardware the algorithm is invoked for. + * @sband: The band this frame is being transmitted on. + * @bss_conf: the current BSS configuration + * @reported_rate: The rate control algorithm can fill this in to indicate + * which rate should be reported to userspace as the current rate and + * used for rate calculations in the mesh network. + * @rts: whether RTS will be used for this frame because it is longer than the + * RTS threshold + * @short_preamble: whether mac80211 will request short-preamble transmission + * if the selected rate supports it + * @max_rate_idx: user-requested maximum rate (not MCS for now) + */ +struct ieee80211_tx_rate_control { + struct ieee80211_hw *hw; + struct ieee80211_supported_band *sband; + struct ieee80211_bss_conf *bss_conf; + struct sk_buff *skb; + struct ieee80211_tx_rate reported_rate; + bool rts, short_preamble; + u8 max_rate_idx; }; struct rate_control_ops { @@ -1869,10 +1929,8 @@ struct rate_control_ops { void (*tx_status)(void *priv, struct ieee80211_supported_band *sband, struct ieee80211_sta *sta, void *priv_sta, struct sk_buff *skb); - void (*get_rate)(void *priv, struct ieee80211_supported_band *sband, - struct ieee80211_sta *sta, void *priv_sta, - struct sk_buff *skb, - struct rate_selection *sel); + void (*get_rate)(void *priv, struct ieee80211_sta *sta, void *priv_sta, + struct ieee80211_tx_rate_control *txrc); void (*add_sta_debugfs)(void *priv, void *priv_sta, struct dentry *dir); diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index 6f8756d26a9..fe4efdd4253 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h @@ -142,7 +142,6 @@ typedef unsigned __bitwise__ ieee80211_tx_result; #define IEEE80211_TX_FRAGMENTED BIT(0) #define IEEE80211_TX_UNICAST BIT(1) #define IEEE80211_TX_PS_BUFFERED BIT(2) -#define IEEE80211_TX_PROBE_LAST_FRAG BIT(3) struct ieee80211_tx_data { struct sk_buff *skb; @@ -153,11 +152,6 @@ struct ieee80211_tx_data { struct ieee80211_key *key; struct ieee80211_channel *channel; - s8 rate_idx; - /* use this rate (if set) for last fragment; rate can - * be set to lower rate for the first fragments, e.g., - * when using CTS protection with IEEE 802.11g. */ - s8 last_frag_rate_idx; /* Extra fragments (in addition to the first fragment * in skb) */ @@ -203,9 +197,7 @@ struct ieee80211_rx_data { struct ieee80211_tx_stored_packet { struct sk_buff *skb; struct sk_buff **extra_frag; - s8 last_frag_rate_idx; int num_extra_frag; - bool last_frag_rate_ctrl_probe; }; struct beacon_data { diff --git a/net/mac80211/main.c b/net/mac80211/main.c index ffff54944f9..88c1975a97a 100644 --- a/net/mac80211/main.c +++ b/net/mac80211/main.c @@ -41,6 +41,8 @@ */ struct ieee80211_tx_status_rtap_hdr { struct ieee80211_radiotap_header hdr; + u8 rate; + u8 padding_for_rate; __le16 tx_flags; u8 data_retries; } __attribute__ ((packed)); @@ -465,13 +467,28 @@ void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb) struct ieee80211_sub_if_data *sdata; struct net_device *prev_dev = NULL; struct sta_info *sta; + int retry_count = -1, i; + + for (i = 0; i < IEEE80211_TX_MAX_RATES; i++) { + /* the HW cannot have attempted that rate */ + if (i >= hw->max_rates) { + info->status.rates[i].idx = -1; + info->status.rates[i].count = 0; + } + + retry_count += info->status.rates[i].count; + } + if (retry_count < 0) + retry_count = 0; rcu_read_lock(); + sband = local->hw.wiphy->bands[info->band]; + sta = sta_info_get(local, hdr->addr1); if (sta) { - if (info->status.excessive_retries && + if (!(info->flags & IEEE80211_TX_STAT_ACK) && test_sta_flags(sta, WLAN_STA_PS)) { /* * The STA is in power save mode, so assume @@ -502,12 +519,11 @@ void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb) rcu_read_unlock(); return; } else { - if (info->status.excessive_retries) + if (!(info->flags & IEEE80211_TX_STAT_ACK)) sta->tx_retry_failed++; - sta->tx_retry_count += info->status.retry_count; + sta->tx_retry_count += retry_count; } - sband = local->hw.wiphy->bands[info->band]; rate_control_tx_status(local, sband, sta, skb); } @@ -528,9 +544,9 @@ void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb) local->dot11TransmittedFrameCount++; if (is_multicast_ether_addr(hdr->addr1)) local->dot11MulticastTransmittedFrameCount++; - if (info->status.retry_count > 0) + if (retry_count > 0) local->dot11RetryCount++; - if (info->status.retry_count > 1) + if (retry_count > 1) local->dot11MultipleRetryCount++; } @@ -574,19 +590,30 @@ void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb) rthdr->hdr.it_len = cpu_to_le16(sizeof(*rthdr)); rthdr->hdr.it_present = cpu_to_le32((1 << IEEE80211_RADIOTAP_TX_FLAGS) | - (1 << IEEE80211_RADIOTAP_DATA_RETRIES)); + (1 << IEEE80211_RADIOTAP_DATA_RETRIES) | + (1 << IEEE80211_RADIOTAP_RATE)); if (!(info->flags & IEEE80211_TX_STAT_ACK) && !is_multicast_ether_addr(hdr->addr1)) rthdr->tx_flags |= cpu_to_le16(IEEE80211_RADIOTAP_F_TX_FAIL); - if ((info->flags & IEEE80211_TX_CTL_USE_RTS_CTS) && - (info->flags & IEEE80211_TX_CTL_USE_CTS_PROTECT)) + /* + * XXX: Once radiotap gets the bitmap reset thing the vendor + * extensions proposal contains, we can actually report + * the whole set of tries we did. + */ + if ((info->status.rates[0].flags & IEEE80211_TX_RC_USE_RTS_CTS) || + (info->status.rates[0].flags & IEEE80211_TX_RC_USE_CTS_PROTECT)) rthdr->tx_flags |= cpu_to_le16(IEEE80211_RADIOTAP_F_TX_CTS); - else if (info->flags & IEEE80211_TX_CTL_USE_RTS_CTS) + else if (info->status.rates[0].flags & IEEE80211_TX_RC_USE_RTS_CTS) rthdr->tx_flags |= cpu_to_le16(IEEE80211_RADIOTAP_F_TX_RTS); + if (info->status.rates[0].idx >= 0 && + !(info->status.rates[0].flags & IEEE80211_TX_RC_MCS)) + rthdr->rate = sband->bitrates[ + info->status.rates[0].idx].bitrate / 5; - rthdr->data_retries = info->status.retry_count; + /* for now report the total retry_count */ + rthdr->data_retries = retry_count; /* XXX: is this sufficient for BPF? */ skb_set_mac_header(skb, 0); @@ -671,8 +698,9 @@ struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len, BUG_ON(!ops->configure_filter); local->ops = ops; - local->hw.queues = 1; /* default */ - + /* set up some defaults */ + local->hw.queues = 1; + local->hw.max_rates = 1; local->rts_threshold = IEEE80211_MAX_RTS_THRESHOLD; local->fragmentation_threshold = IEEE80211_MAX_FRAG_THRESHOLD; local->hw.conf.long_frame_max_tx_count = 4; diff --git a/net/mac80211/mesh_hwmp.c b/net/mac80211/mesh_hwmp.c index 501c7831adb..e8d573d592e 100644 --- a/net/mac80211/mesh_hwmp.c +++ b/net/mac80211/mesh_hwmp.c @@ -218,12 +218,16 @@ static u32 airtime_link_metric_get(struct ieee80211_local *local, if (sta->fail_avg >= 100) return MAX_METRIC; + + if (sta->last_tx_rate.flags & IEEE80211_TX_RC_MCS) + return MAX_METRIC; + err = (sta->fail_avg << ARITH_SHIFT) / 100; /* bitrate is in units of 100 Kbps, while we need rate in units of * 1Mbps. This will be corrected on tx_time computation. */ - rate = sband->bitrates[sta->last_txrate_idx].bitrate; + rate = sband->bitrates[sta->last_tx_rate.idx].bitrate; tx_time = (device_constant + 10 * test_frame_len / rate); estimated_retx = ((1 << (2 * ARITH_SHIFT)) / (s_unit - err)); result = (tx_time * estimated_retx) >> (2 * ARITH_SHIFT) ; diff --git a/net/mac80211/rate.c b/net/mac80211/rate.c index 5d786720d93..3fa7ab28506 100644 --- a/net/mac80211/rate.c +++ b/net/mac80211/rate.c @@ -199,48 +199,44 @@ static void rate_control_release(struct kref *kref) } void rate_control_get_rate(struct ieee80211_sub_if_data *sdata, - struct ieee80211_supported_band *sband, - struct sta_info *sta, struct sk_buff *skb, - struct rate_selection *sel) + struct sta_info *sta, + struct ieee80211_tx_rate_control *txrc) { struct rate_control_ref *ref = sdata->local->rate_ctrl; void *priv_sta = NULL; struct ieee80211_sta *ista = NULL; + struct ieee80211_tx_info *info = IEEE80211_SKB_CB(txrc->skb); int i; - sel->rate_idx = -1; - sel->nonerp_idx = -1; - sel->probe_idx = -1; - sel->max_rate_idx = sdata->max_ratectrl_rateidx; - if (sta) { ista = &sta->sta; priv_sta = sta->rate_ctrl_priv; } + for (i = 0; i < IEEE80211_TX_MAX_RATES; i++) { + info->control.rates[i].idx = -1; + info->control.rates[i].flags = 0; + info->control.rates[i].count = 1; + } + if (sta && sdata->force_unicast_rateidx > -1) - sel->rate_idx = sdata->force_unicast_rateidx; + info->control.rates[0].idx = sdata->force_unicast_rateidx; else - ref->ops->get_rate(ref->priv, sband, ista, priv_sta, skb, sel); - - if (sdata->max_ratectrl_rateidx > -1 && - sel->rate_idx > sdata->max_ratectrl_rateidx) - sel->rate_idx = sdata->max_ratectrl_rateidx; - - BUG_ON(sel->rate_idx < 0); - - /* Select a non-ERP backup rate. */ - if (sel->nonerp_idx < 0) { - for (i = 0; i < sband->n_bitrates; i++) { - struct ieee80211_rate *rate = &sband->bitrates[i]; - if (sband->bitrates[sel->rate_idx].bitrate < rate->bitrate) - break; - - if (rate_supported(ista, sband->band, i) && - !(rate->flags & IEEE80211_RATE_ERP_G)) - sel->nonerp_idx = i; - } + ref->ops->get_rate(ref->priv, ista, priv_sta, txrc); + + /* + * try to enforce the maximum rate the user wanted + */ + if (sdata->max_ratectrl_rateidx > -1) + for (i = 0; i < IEEE80211_TX_MAX_RATES; i++) { + if (info->control.rates[i].flags & IEEE80211_TX_RC_MCS) + continue; + info->control.rates[i].idx = + min_t(s8, info->control.rates[i].idx, + sdata->max_ratectrl_rateidx); } + + BUG_ON(info->control.rates[0].idx < 0); } struct rate_control_ref *rate_control_get(struct rate_control_ref *ref) diff --git a/net/mac80211/rate.h b/net/mac80211/rate.h index d0092f847f8..7c25edf9ac5 100644 --- a/net/mac80211/rate.h +++ b/net/mac80211/rate.h @@ -31,9 +31,8 @@ struct rate_control_ref { struct rate_control_ref *rate_control_alloc(const char *name, struct ieee80211_local *local); void rate_control_get_rate(struct ieee80211_sub_if_data *sdata, - struct ieee80211_supported_band *sband, - struct sta_info *sta, struct sk_buff *skb, - struct rate_selection *sel); + struct sta_info *sta, + struct ieee80211_tx_rate_control *txrc); struct rate_control_ref *rate_control_get(struct rate_control_ref *ref); void rate_control_put(struct rate_control_ref *ref); diff --git a/net/mac80211/rc80211_minstrel.c b/net/mac80211/rc80211_minstrel.c index f6d69dab07a..759ddd8bf0f 100644 --- a/net/mac80211/rc80211_minstrel.c +++ b/net/mac80211/rc80211_minstrel.c @@ -169,30 +169,20 @@ minstrel_tx_status(void *priv, struct ieee80211_supported_band *sband, { struct minstrel_sta_info *mi = priv_sta; struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); - struct ieee80211_tx_altrate *ar = info->status.retries; - struct minstrel_priv *mp = priv; - int i, ndx, tries; - int success = 0; + struct ieee80211_tx_rate *ar = info->status.rates; + int i, ndx; + int success; - if (!info->status.excessive_retries) - success = 1; + success = !!(info->flags & IEEE80211_TX_STAT_ACK); - if (!mp->has_mrr || (ar[0].rate_idx < 0)) { - ndx = rix_to_ndx(mi, info->tx_rate_idx); - tries = info->status.retry_count + 1; - mi->r[ndx].success += success; - mi->r[ndx].attempts += tries; - return; - } - - for (i = 0; i < 4; i++) { - if (ar[i].rate_idx < 0) + for (i = 0; i < IEEE80211_TX_MAX_RATES; i++) { + if (ar[i].idx < 0) break; - ndx = rix_to_ndx(mi, ar[i].rate_idx); - mi->r[ndx].attempts += ar[i].limit + 1; + ndx = rix_to_ndx(mi, ar[i].idx); + mi->r[ndx].attempts += ar[i].count; - if ((i != 3) && (ar[i + 1].rate_idx < 0)) + if ((i != IEEE80211_TX_MAX_RATES - 1) && (ar[i + 1].idx < 0)) mi->r[ndx].success += success; } @@ -210,9 +200,9 @@ minstrel_get_retry_count(struct minstrel_rate *mr, { unsigned int retry = mr->adjusted_retry_count; - if (info->flags & IEEE80211_TX_CTL_USE_RTS_CTS) + if (info->control.rates[0].flags & IEEE80211_TX_RC_USE_RTS_CTS) retry = max(2U, min(mr->retry_count_rtscts, retry)); - else if (info->flags & IEEE80211_TX_CTL_USE_CTS_PROTECT) + else if (info->control.rates[0].flags & IEEE80211_TX_RC_USE_CTS_PROTECT) retry = max(2U, min(mr->retry_count_cts, retry)); return retry; } @@ -234,14 +224,15 @@ minstrel_get_next_sample(struct minstrel_sta_info *mi) } void -minstrel_get_rate(void *priv, struct ieee80211_supported_band *sband, - struct ieee80211_sta *sta, void *priv_sta, - struct sk_buff *skb, struct rate_selection *sel) +minstrel_get_rate(void *priv, struct ieee80211_sta *sta, + void *priv_sta, struct ieee80211_tx_rate_control *txrc) { + struct sk_buff *skb = txrc->skb; + struct ieee80211_supported_band *sband = txrc->sband; struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); struct minstrel_sta_info *mi = priv_sta; struct minstrel_priv *mp = priv; - struct ieee80211_tx_altrate *ar = info->control.retries; + struct ieee80211_tx_rate *ar = info->control.rates; unsigned int ndx, sample_ndx = 0; bool mrr; bool sample_slower = false; @@ -251,16 +242,12 @@ minstrel_get_rate(void *priv, struct ieee80211_supported_band *sband, int sample_rate; if (!sta || !mi || use_low_rate(skb)) { - sel->rate_idx = rate_lowest_index(sband, sta); + ar[0].idx = rate_lowest_index(sband, sta); + ar[0].count = mp->max_retry; return; } - mrr = mp->has_mrr; - - /* mac80211 does not allow mrr for RTS/CTS */ - if ((info->flags & IEEE80211_TX_CTL_USE_RTS_CTS) || - (info->flags & IEEE80211_TX_CTL_USE_CTS_PROTECT)) - mrr = false; + mrr = mp->has_mrr && !txrc->rts && !txrc->bss_conf->use_cts_prot; if (time_after(jiffies, mi->stats_update + (mp->update_interval * HZ) / 1000)) @@ -315,13 +302,12 @@ minstrel_get_rate(void *priv, struct ieee80211_supported_band *sband, mi->sample_deferred++; } } - sel->rate_idx = mi->r[ndx].rix; - info->control.retry_limit = minstrel_get_retry_count(&mi->r[ndx], info); + ar[0].idx = mi->r[ndx].rix; + ar[0].count = minstrel_get_retry_count(&mi->r[ndx], info); if (!mrr) { - ar[0].rate_idx = mi->lowest_rix; - ar[0].limit = mp->max_retry; - ar[1].rate_idx = -1; + ar[1].idx = mi->lowest_rix; + ar[1].count = mp->max_retry; return; } @@ -336,9 +322,9 @@ minstrel_get_rate(void *priv, struct ieee80211_supported_band *sband, } mrr_ndx[1] = mi->max_prob_rate; mrr_ndx[2] = 0; - for (i = 0; i < 3; i++) { - ar[i].rate_idx = mi->r[mrr_ndx[i]].rix; - ar[i].limit = mi->r[mrr_ndx[i]].adjusted_retry_count; + for (i = 1; i < 4; i++) { + ar[i].idx = mi->r[mrr_ndx[i - 1]].rix; + ar[i].count = mi->r[mrr_ndx[i - 1]].adjusted_retry_count; } } @@ -532,13 +518,13 @@ minstrel_alloc(struct ieee80211_hw *hw, struct dentry *debugfsdir) /* maximum time that the hw is allowed to stay in one MRR segment */ mp->segment_size = 6000; - if (hw->max_altrate_tries > 0) - mp->max_retry = hw->max_altrate_tries; + if (hw->max_rate_tries > 0) + mp->max_retry = hw->max_rate_tries; else /* safe default, does not necessarily have to match hw properties */ mp->max_retry = 7; - if (hw->max_altrates >= 3) + if (hw->max_rates >= 4) mp->has_mrr = true; mp->hw = hw; diff --git a/net/mac80211/rc80211_pid.h b/net/mac80211/rc80211_pid.h index ce099ea1d5d..1a873f00691 100644 --- a/net/mac80211/rc80211_pid.h +++ b/net/mac80211/rc80211_pid.h @@ -61,6 +61,7 @@ enum rc_pid_event_type { union rc_pid_event_data { /* RC_PID_EVENT_TX_STATUS */ struct { + u32 flags; struct ieee80211_tx_info tx_status; }; /* RC_PID_EVENT_TYPE_RATE_CHANGE */ diff --git a/net/mac80211/rc80211_pid_algo.c b/net/mac80211/rc80211_pid_algo.c index 86eb374e3b8..92caecfcee7 100644 --- a/net/mac80211/rc80211_pid_algo.c +++ b/net/mac80211/rc80211_pid_algo.c @@ -241,7 +241,7 @@ static void rate_control_pid_tx_status(void *priv, struct ieee80211_supported_ba /* Ignore all frames that were sent with a different rate than the rate * we currently advise mac80211 to use. */ - if (info->tx_rate_idx != spinfo->txrate_idx) + if (info->status.rates[0].idx != spinfo->txrate_idx) return; spinfo->tx_num_xmit++; @@ -253,10 +253,10 @@ static void rate_control_pid_tx_status(void *priv, struct ieee80211_supported_ba /* We count frames that totally failed to be transmitted as two bad * frames, those that made it out but had some retries as one good and * one bad frame. */ - if (info->status.excessive_retries) { + if (!(info->flags & IEEE80211_TX_STAT_ACK)) { spinfo->tx_num_failed += 2; spinfo->tx_num_xmit++; - } else if (info->status.retry_count) { + } else if (info->status.rates[0].count) { spinfo->tx_num_failed++; spinfo->tx_num_xmit++; } @@ -270,23 +270,32 @@ static void rate_control_pid_tx_status(void *priv, struct ieee80211_supported_ba } static void -rate_control_pid_get_rate(void *priv, struct ieee80211_supported_band *sband, - struct ieee80211_sta *sta, void *priv_sta, - struct sk_buff *skb, - struct rate_selection *sel) +rate_control_pid_get_rate(void *priv, struct ieee80211_sta *sta, + void *priv_sta, + struct ieee80211_tx_rate_control *txrc) { + struct sk_buff *skb = txrc->skb; + struct ieee80211_supported_band *sband = txrc->sband; struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; + struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); struct rc_pid_sta_info *spinfo = priv_sta; int rateidx; u16 fc; + if (txrc->rts) + info->control.rates[0].count = + txrc->hw->conf.long_frame_max_tx_count; + else + info->control.rates[0].count = + txrc->hw->conf.short_frame_max_tx_count; + /* Send management frames and broadcast/multicast data using lowest * rate. */ fc = le16_to_cpu(hdr->frame_control); if (!sta || !spinfo || (fc & IEEE80211_FCTL_FTYPE) != IEEE80211_FTYPE_DATA || is_multicast_ether_addr(hdr->addr1)) { - sel->rate_idx = rate_lowest_index(sband, sta); + info->control.rates[0].idx = rate_lowest_index(sband, sta); return; } @@ -295,7 +304,7 @@ rate_control_pid_get_rate(void *priv, struct ieee80211_supported_band *sband, if (rateidx >= sband->n_bitrates) rateidx = sband->n_bitrates - 1; - sel->rate_idx = rateidx; + info->control.rates[0].idx = rateidx; #ifdef CONFIG_MAC80211_DEBUGFS rate_control_pid_event_tx_rate(&spinfo->events, diff --git a/net/mac80211/rc80211_pid_debugfs.c b/net/mac80211/rc80211_pid_debugfs.c index 8121d3bc683..a08a9b53034 100644 --- a/net/mac80211/rc80211_pid_debugfs.c +++ b/net/mac80211/rc80211_pid_debugfs.c @@ -43,6 +43,7 @@ void rate_control_pid_event_tx_status(struct rc_pid_event_buffer *buf, { union rc_pid_event_data evd; + evd.flags = stat->flags; memcpy(&evd.tx_status, stat, sizeof(struct ieee80211_tx_info)); rate_control_pid_event(buf, RC_PID_EVENT_TYPE_TX_STATUS, &evd); } @@ -167,8 +168,8 @@ static ssize_t rate_control_pid_events_read(struct file *file, char __user *buf, switch (ev->type) { case RC_PID_EVENT_TYPE_TX_STATUS: p += snprintf(pb + p, length - p, "tx_status %u %u", - ev->data.tx_status.status.excessive_retries, - ev->data.tx_status.status.retry_count); + !(ev->data.flags & IEEE80211_TX_STAT_ACK), + ev->data.tx_status.status.rates[0].idx); break; case RC_PID_EVENT_TYPE_RATE_CHANGE: p += snprintf(pb + p, length - p, "rate_change %d %d", diff --git a/net/mac80211/sta_info.h b/net/mac80211/sta_info.h index 168a39a298b..4ac372aa75c 100644 --- a/net/mac80211/sta_info.h +++ b/net/mac80211/sta_info.h @@ -196,7 +196,7 @@ struct sta_ampdu_mlme { * @tx_packets: number of RX/TX MSDUs * @tx_bytes: TBD * @tx_fragments: number of transmitted MPDUs - * @last_txrate_idx: Index of the last used transmit rate + * @last_txrate: description of the last used transmit rate * @tid_seq: TBD * @ampdu_mlme: TBD * @timer_to_tid: identity mapping to ID timers @@ -267,7 +267,7 @@ struct sta_info { unsigned long tx_packets; unsigned long tx_bytes; unsigned long tx_fragments; - unsigned int last_txrate_idx; + struct ieee80211_tx_rate last_tx_rate; u16 tid_seq[IEEE80211_QOS_CTL_TID_MASK + 1]; /* diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c index 6f3e4be9763..21951bac1ef 100644 --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c @@ -46,13 +46,20 @@ static __le16 ieee80211_duration(struct ieee80211_tx_data *tx, int group_addr, struct ieee80211_local *local = tx->local; struct ieee80211_supported_band *sband; struct ieee80211_hdr *hdr; + struct ieee80211_tx_info *info = IEEE80211_SKB_CB(tx->skb); + + /* assume HW handles this */ + if (info->control.rates[0].flags & IEEE80211_TX_RC_MCS) + return 0; + + /* uh huh? */ + if (WARN_ON_ONCE(info->control.rates[0].idx < 0)) + return 0; sband = local->hw.wiphy->bands[tx->channel->band]; - txrate = &sband->bitrates[tx->rate_idx]; + txrate = &sband->bitrates[info->control.rates[0].idx]; - erp = 0; - if (tx->sdata->flags & IEEE80211_SDATA_OPERATING_GMODE) - erp = txrate->flags & IEEE80211_RATE_ERP_G; + erp = txrate->flags & IEEE80211_RATE_ERP_G; /* * data and mgmt (except PS Poll): @@ -437,140 +444,154 @@ ieee80211_tx_h_select_key(struct ieee80211_tx_data *tx) static ieee80211_tx_result debug_noinline ieee80211_tx_h_rate_ctrl(struct ieee80211_tx_data *tx) { - struct rate_selection rsel; - struct ieee80211_supported_band *sband; struct ieee80211_tx_info *info = IEEE80211_SKB_CB(tx->skb); + struct ieee80211_hdr *hdr = (void *)tx->skb->data; + struct ieee80211_supported_band *sband; + struct ieee80211_rate *rate; + int i, len; + bool inval = false, rts = false, short_preamble = false; + struct ieee80211_tx_rate_control txrc; - sband = tx->local->hw.wiphy->bands[tx->channel->band]; + memset(&txrc, 0, sizeof(txrc)); - if (likely(tx->rate_idx < 0)) { - rate_control_get_rate(tx->sdata, sband, tx->sta, - tx->skb, &rsel); - if (tx->sta) - tx->sta->last_txrate_idx = rsel.rate_idx; - tx->rate_idx = rsel.rate_idx; - if (unlikely(rsel.probe_idx >= 0)) { - info->flags |= IEEE80211_TX_CTL_RATE_CTRL_PROBE; - tx->flags |= IEEE80211_TX_PROBE_LAST_FRAG; - info->control.retries[0].rate_idx = tx->rate_idx; - info->control.retries[0].limit = tx->local->hw.max_altrate_tries; - tx->rate_idx = rsel.probe_idx; - } else if (info->control.retries[0].limit == 0) - info->control.retries[0].rate_idx = -1; - - if (unlikely(tx->rate_idx < 0)) - return TX_DROP; - } else - info->control.retries[0].rate_idx = -1; + sband = tx->local->hw.wiphy->bands[tx->channel->band]; - if (tx->sdata->vif.bss_conf.use_cts_prot && - (tx->flags & IEEE80211_TX_FRAGMENTED) && (rsel.nonerp_idx >= 0)) { - tx->last_frag_rate_idx = tx->rate_idx; - if (rsel.probe_idx >= 0) - tx->flags &= ~IEEE80211_TX_PROBE_LAST_FRAG; - else - tx->flags |= IEEE80211_TX_PROBE_LAST_FRAG; - tx->rate_idx = rsel.nonerp_idx; - info->tx_rate_idx = rsel.nonerp_idx; - info->flags &= ~IEEE80211_TX_CTL_RATE_CTRL_PROBE; - } else { - tx->last_frag_rate_idx = tx->rate_idx; - info->tx_rate_idx = tx->rate_idx; + len = min_t(int, tx->skb->len + FCS_LEN, + tx->local->fragmentation_threshold); + + /* set up the tx rate control struct we give the RC algo */ + txrc.hw = local_to_hw(tx->local); + txrc.sband = sband; + txrc.bss_conf = &tx->sdata->vif.bss_conf; + txrc.skb = tx->skb; + txrc.reported_rate.idx = -1; + txrc.max_rate_idx = tx->sdata->max_ratectrl_rateidx; + + /* set up RTS protection if desired */ + if (tx->local->rts_threshold < IEEE80211_MAX_RTS_THRESHOLD && + len > tx->local->rts_threshold) { + txrc.rts = rts = true; } - info->tx_rate_idx = tx->rate_idx; - return TX_CONTINUE; -} + /* + * Use short preamble if the BSS can handle it, but not for + * management frames unless we know the receiver can handle + * that -- the management frame might be to a station that + * just wants a probe response. + */ + if (tx->sdata->vif.bss_conf.use_short_preamble && + (ieee80211_is_data(hdr->frame_control) || + (tx->sta && test_sta_flags(tx->sta, WLAN_STA_SHORT_PREAMBLE)))) + txrc.short_preamble = short_preamble = true; -static ieee80211_tx_result debug_noinline -ieee80211_tx_h_misc(struct ieee80211_tx_data *tx) -{ - struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)tx->skb->data; - struct ieee80211_tx_info *info = IEEE80211_SKB_CB(tx->skb); - struct ieee80211_supported_band *sband; - sband = tx->local->hw.wiphy->bands[tx->channel->band]; + rate_control_get_rate(tx->sdata, tx->sta, &txrc); + + if (unlikely(info->control.rates[0].idx < 0)) + return TX_DROP; + + if (txrc.reported_rate.idx < 0) + txrc.reported_rate = info->control.rates[0]; if (tx->sta) - info->control.sta = &tx->sta->sta; + tx->sta->last_tx_rate = txrc.reported_rate; - if (!info->control.retry_limit) { - if (!is_multicast_ether_addr(hdr->addr1)) { - int len = min_t(int, tx->skb->len + FCS_LEN, - tx->local->fragmentation_threshold); - if (len > tx->local->rts_threshold - && tx->local->rts_threshold < - IEEE80211_MAX_RTS_THRESHOLD) { - info->flags |= IEEE80211_TX_CTL_USE_RTS_CTS; - info->flags |= - IEEE80211_TX_CTL_LONG_RETRY_LIMIT; - info->control.retry_limit = - tx->local->hw.conf.long_frame_max_tx_count - 1; - } else { - info->control.retry_limit = - tx->local->hw.conf.short_frame_max_tx_count - 1; - } - } else { - info->control.retry_limit = 1; - } - } + if (unlikely(!info->control.rates[0].count)) + info->control.rates[0].count = 1; - if (tx->flags & IEEE80211_TX_FRAGMENTED) { - /* Do not use multiple retry rates when sending fragmented - * frames. - * TODO: The last fragment could still use multiple retry - * rates. */ - info->control.retries[0].rate_idx = -1; + if (is_multicast_ether_addr(hdr->addr1)) { + /* + * XXX: verify the rate is in the basic rateset + */ + return TX_CONTINUE; } - /* Use CTS protection for unicast frames sent using extended rates if - * there are associated non-ERP stations and RTS/CTS is not configured - * for the frame. */ - if ((tx->sdata->flags & IEEE80211_SDATA_OPERATING_GMODE) && - (sband->bitrates[tx->rate_idx].flags & IEEE80211_RATE_ERP_G) && - (tx->flags & IEEE80211_TX_UNICAST) && - tx->sdata->vif.bss_conf.use_cts_prot && - !(info->flags & IEEE80211_TX_CTL_USE_RTS_CTS)) - info->flags |= IEEE80211_TX_CTL_USE_CTS_PROTECT; - - /* Transmit data frames using short preambles if the driver supports - * short preambles at the selected rate and short preambles are - * available on the network at the current point in time. */ - if (ieee80211_is_data(hdr->frame_control) && - (sband->bitrates[tx->rate_idx].flags & IEEE80211_RATE_SHORT_PREAMBLE) && - tx->sdata->vif.bss_conf.use_short_preamble && - (!tx->sta || test_sta_flags(tx->sta, WLAN_STA_SHORT_PREAMBLE))) { - info->flags |= IEEE80211_TX_CTL_SHORT_PREAMBLE; + /* + * set up the RTS/CTS rate as the fastest basic rate + * that is not faster than the data rate + * + * XXX: Should this check all retry rates? + */ + if (!(info->control.rates[0].flags & IEEE80211_TX_RC_MCS)) { + s8 baserate = 0; + + rate = &sband->bitrates[info->control.rates[0].idx]; + + for (i = 0; i < sband->n_bitrates; i++) { + /* must be a basic rate */ + if (!(tx->sdata->vif.bss_conf.basic_rates & BIT(i))) + continue; + /* must not be faster than the data rate */ + if (sband->bitrates[i].bitrate > rate->bitrate) + continue; + /* maximum */ + if (sband->bitrates[baserate].bitrate < + sband->bitrates[i].bitrate) + baserate = i; + } + + info->control.rts_cts_rate_idx = baserate; } - if ((info->flags & IEEE80211_TX_CTL_USE_RTS_CTS) || - (info->flags & IEEE80211_TX_CTL_USE_CTS_PROTECT)) { - struct ieee80211_rate *rate; - s8 baserate = -1; - int idx; + for (i = 0; i < IEEE80211_TX_MAX_RATES; i++) { + /* + * make sure there's no valid rate following + * an invalid one, just in case drivers don't + * take the API seriously to stop at -1. + */ + if (inval) { + info->control.rates[i].idx = -1; + continue; + } + if (info->control.rates[i].idx < 0) { + inval = true; + continue; + } - /* Do not use multiple retry rates when using RTS/CTS */ - info->control.retries[0].rate_idx = -1; + /* + * For now assume MCS is already set up correctly, this + * needs to be fixed. + */ + if (info->control.rates[i].flags & IEEE80211_TX_RC_MCS) { + WARN_ON(info->control.rates[i].idx > 76); + continue; + } - /* Use min(data rate, max base rate) as CTS/RTS rate */ - rate = &sband->bitrates[tx->rate_idx]; + /* set up RTS protection if desired */ + if (rts) + info->control.rates[i].flags |= + IEEE80211_TX_RC_USE_RTS_CTS; - for (idx = 0; idx < sband->n_bitrates; idx++) { - if (sband->bitrates[idx].bitrate > rate->bitrate) - continue; - if (tx->sdata->vif.bss_conf.basic_rates & BIT(idx) && - (baserate < 0 || - (sband->bitrates[baserate].bitrate - < sband->bitrates[idx].bitrate))) - baserate = idx; + /* RC is busted */ + if (WARN_ON(info->control.rates[i].idx >= + sband->n_bitrates)) { + info->control.rates[i].idx = -1; + continue; } - if (baserate >= 0) - info->control.rts_cts_rate_idx = baserate; - else - info->control.rts_cts_rate_idx = 0; + rate = &sband->bitrates[info->control.rates[i].idx]; + + /* set up short preamble */ + if (short_preamble && + rate->flags & IEEE80211_RATE_SHORT_PREAMBLE) + info->control.rates[i].flags |= + IEEE80211_TX_RC_USE_SHORT_PREAMBLE; + + /* set up G protection */ + if (!rts && tx->sdata->vif.bss_conf.use_cts_prot && + rate->flags & IEEE80211_RATE_ERP_G) + info->control.rates[i].flags |= + IEEE80211_TX_RC_USE_CTS_PROTECT; } + return TX_CONTINUE; +} + +static ieee80211_tx_result debug_noinline +ieee80211_tx_h_misc(struct ieee80211_tx_data *tx) +{ + struct ieee80211_tx_info *info = IEEE80211_SKB_CB(tx->skb); + if (tx->sta) info->control.sta = &tx->sta->sta; @@ -678,6 +699,7 @@ ieee80211_tx_h_fragment(struct ieee80211_tx_data *tx) left = payload_len - per_fragm; for (i = 0; i < num_fragm - 1; i++) { struct ieee80211_hdr *fhdr; + struct ieee80211_tx_info *info; size_t copylen; if (left <= 0) @@ -692,20 +714,45 @@ ieee80211_tx_h_fragment(struct ieee80211_tx_data *tx) IEEE80211_ENCRYPT_TAILROOM); if (!frag) goto fail; + /* Make sure that all fragments use the same priority so * that they end up using the same TX queue */ frag->priority = first->priority; + skb_reserve(frag, tx->local->tx_headroom + IEEE80211_ENCRYPT_HEADROOM); + + /* copy TX information */ + info = IEEE80211_SKB_CB(frag); + memcpy(info, first->cb, sizeof(frag->cb)); + + /* copy/fill in 802.11 header */ fhdr = (struct ieee80211_hdr *) skb_put(frag, hdrlen); memcpy(fhdr, first->data, hdrlen); - if (i == num_fragm - 2) - fhdr->frame_control &= cpu_to_le16(~IEEE80211_FCTL_MOREFRAGS); fhdr->seq_ctrl = cpu_to_le16(seq | ((i + 1) & IEEE80211_SCTL_FRAG)); + + if (i == num_fragm - 2) { + /* clear MOREFRAGS bit for the last fragment */ + fhdr->frame_control &= cpu_to_le16(~IEEE80211_FCTL_MOREFRAGS); + } else { + /* + * No multi-rate retries for fragmented frames, that + * would completely throw off the NAV at other STAs. + */ + info->control.rates[1].idx = -1; + info->control.rates[2].idx = -1; + info->control.rates[3].idx = -1; + info->control.rates[4].idx = -1; + BUILD_BUG_ON(IEEE80211_TX_MAX_RATES != 5); + info->flags &= ~IEEE80211_TX_CTL_RATE_CTRL_PROBE; + } + + /* copy data */ copylen = left > per_fragm ? per_fragm : left; memcpy(skb_put(frag, copylen), pos, copylen); - memcpy(frag->cb, first->cb, sizeof(frag->cb)); + skb_copy_queue_mapping(frag, first); + frag->do_not_encrypt = first->do_not_encrypt; pos += copylen; @@ -765,12 +812,10 @@ ieee80211_tx_h_calculate_duration(struct ieee80211_tx_data *tx) tx->extra_frag[0]->len); for (i = 0; i < tx->num_extra_frag; i++) { - if (i + 1 < tx->num_extra_frag) { + if (i + 1 < tx->num_extra_frag) next_len = tx->extra_frag[i + 1]->len; - } else { + else next_len = 0; - tx->rate_idx = tx->last_frag_rate_idx; - } hdr = (struct ieee80211_hdr *)tx->extra_frag[i]->data; hdr->duration_id = ieee80211_duration(tx, 0, next_len); @@ -823,7 +868,6 @@ __ieee80211_parse_tx_radiotap(struct ieee80211_tx_data *tx, (struct ieee80211_radiotap_header *) skb->data; struct ieee80211_supported_band *sband; int ret = ieee80211_radiotap_iterator_init(&iterator, rthdr, skb->len); - struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); sband = tx->local->hw.wiphy->bands[tx->channel->band]; @@ -837,8 +881,6 @@ __ieee80211_parse_tx_radiotap(struct ieee80211_tx_data *tx, */ while (!ret) { - int i, target_rate; - ret = ieee80211_radiotap_iterator_next(&iterator); if (ret) @@ -852,38 +894,6 @@ __ieee80211_parse_tx_radiotap(struct ieee80211_tx_data *tx, * get_unaligned((type *)iterator.this_arg) to dereference * iterator.this_arg for type "type" safely on all arches. */ - case IEEE80211_RADIOTAP_RATE: - /* - * radiotap rate u8 is in 500kbps units eg, 0x02=1Mbps - * ieee80211 rate int is in 100kbps units eg, 0x0a=1Mbps - */ - target_rate = (*iterator.this_arg) * 5; - for (i = 0; i < sband->n_bitrates; i++) { - struct ieee80211_rate *r; - - r = &sband->bitrates[i]; - - if (r->bitrate == target_rate) { - tx->rate_idx = i; - break; - } - } - break; - - case IEEE80211_RADIOTAP_ANTENNA: - /* - * radiotap uses 0 for 1st ant, mac80211 is 1 for - * 1st ant - */ - info->antenna_sel_tx = (*iterator.this_arg) + 1; - break; - -#if 0 - case IEEE80211_RADIOTAP_DBM_TX_POWER: - control->power_level = *iterator.this_arg; - break; -#endif - case IEEE80211_RADIOTAP_FLAGS: if (*iterator.this_arg & IEEE80211_RADIOTAP_F_FCS) { /* @@ -949,8 +959,6 @@ __ieee80211_tx_prepare(struct ieee80211_tx_data *tx, tx->local = local; tx->sdata = IEEE80211_DEV_TO_SUB_IF(dev); tx->channel = local->hw.conf.channel; - tx->rate_idx = -1; - tx->last_frag_rate_idx = -1; /* * Set this flag (used below to indicate "automatic fragmentation"), * it will be cleared/left by radiotap as desired. @@ -1051,23 +1059,11 @@ static int __ieee80211_tx(struct ieee80211_local *local, struct sk_buff *skb, if (!tx->extra_frag[i]) continue; info = IEEE80211_SKB_CB(tx->extra_frag[i]); - info->flags &= ~(IEEE80211_TX_CTL_USE_RTS_CTS | - IEEE80211_TX_CTL_USE_CTS_PROTECT | - IEEE80211_TX_CTL_CLEAR_PS_FILT | + info->flags &= ~(IEEE80211_TX_CTL_CLEAR_PS_FILT | IEEE80211_TX_CTL_FIRST_FRAGMENT); if (netif_subqueue_stopped(local->mdev, tx->extra_frag[i])) return IEEE80211_TX_FRAG_AGAIN; - if (i == tx->num_extra_frag) { - info->tx_rate_idx = tx->last_frag_rate_idx; - - if (tx->flags & IEEE80211_TX_PROBE_LAST_FRAG) - info->flags |= - IEEE80211_TX_CTL_RATE_CTRL_PROBE; - else - info->flags &= - ~IEEE80211_TX_CTL_RATE_CTRL_PROBE; - } ret = local->ops->tx(local_to_hw(local), tx->extra_frag[i]); @@ -1204,9 +1200,6 @@ retry: store->skb = skb; store->extra_frag = tx.extra_frag; store->num_extra_frag = tx.num_extra_frag; - store->last_frag_rate_idx = tx.last_frag_rate_idx; - store->last_frag_rate_ctrl_probe = - !!(tx.flags & IEEE80211_TX_PROBE_LAST_FRAG); } out: rcu_read_unlock(); @@ -1763,10 +1756,7 @@ void ieee80211_tx_pending(unsigned long data) store = &local->pending_packet[i]; tx.extra_frag = store->extra_frag; tx.num_extra_frag = store->num_extra_frag; - tx.last_frag_rate_idx = store->last_frag_rate_idx; tx.flags = 0; - if (store->last_frag_rate_ctrl_probe) - tx.flags |= IEEE80211_TX_PROBE_LAST_FRAG; ret = __ieee80211_tx(local, store->skb, &tx); if (ret) { if (ret == IEEE80211_TX_FRAG_AGAIN) @@ -1854,7 +1844,6 @@ struct sk_buff *ieee80211_beacon_get(struct ieee80211_hw *hw, struct ieee80211_sub_if_data *sdata = NULL; struct ieee80211_if_ap *ap = NULL; struct ieee80211_if_sta *ifsta = NULL; - struct rate_selection rsel; struct beacon_data *beacon; struct ieee80211_supported_band *sband; enum ieee80211_band band = local->hw.conf.channel->band; @@ -1958,32 +1947,23 @@ struct sk_buff *ieee80211_beacon_get(struct ieee80211_hw *hw, skb->do_not_encrypt = 1; info->band = band; - rate_control_get_rate(sdata, sband, NULL, skb, &rsel); - - if (unlikely(rsel.rate_idx < 0)) { - if (net_ratelimit()) { - printk(KERN_DEBUG "%s: ieee80211_beacon_get: " - "no rate found\n", - wiphy_name(local->hw.wiphy)); - } - dev_kfree_skb_any(skb); - skb = NULL; - goto out; - } + /* + * XXX: For now, always use the lowest rate + */ + info->control.rates[0].idx = 0; + info->control.rates[0].count = 1; + info->control.rates[1].idx = -1; + info->control.rates[2].idx = -1; + info->control.rates[3].idx = -1; + info->control.rates[4].idx = -1; + BUILD_BUG_ON(IEEE80211_TX_MAX_RATES != 5); info->control.vif = vif; - info->tx_rate_idx = rsel.rate_idx; info->flags |= IEEE80211_TX_CTL_NO_ACK; info->flags |= IEEE80211_TX_CTL_CLEAR_PS_FILT; info->flags |= IEEE80211_TX_CTL_ASSIGN_SEQ; - if (sdata->vif.bss_conf.use_short_preamble && - sband->bitrates[rsel.rate_idx].flags & IEEE80211_RATE_SHORT_PREAMBLE) - info->flags |= IEEE80211_TX_CTL_SHORT_PREAMBLE; - - info->control.retry_limit = 1; - -out: + out: rcu_read_unlock(); return skb; } diff --git a/net/mac80211/wext.c b/net/mac80211/wext.c index f7e442f80a1..31d2e74a1bc 100644 --- a/net/mac80211/wext.c +++ b/net/mac80211/wext.c @@ -636,8 +636,8 @@ static int ieee80211_ioctl_giwrate(struct net_device *dev, sta = sta_info_get(local, sdata->u.sta.bssid); - if (sta && sta->last_txrate_idx < sband->n_bitrates) - rate->value = sband->bitrates[sta->last_txrate_idx].bitrate; + if (sta && !(sta->last_tx_rate.flags & IEEE80211_TX_RC_MCS)) + rate->value = sband->bitrates[sta->last_tx_rate.idx].bitrate; else rate->value = 0; -- cgit v1.2.3-70-g09d2 From 075cbc9eb15da8f4cba7c7eaadedd8b030d3a87a Mon Sep 17 00:00:00 2001 From: Sujith Date: Thu, 23 Oct 2008 12:14:02 +0530 Subject: mac80211: Change WARN_ON to WARN_ON_ONCE A warning would be printed for every packet that is transmitted if the rate control information isn't setup. Change this to WARN_ON_ONCE. Signed-off-by: Sujith Acked-by: Johannes Berg Signed-off-by: John W. Linville --- net/mac80211/tx.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'net/mac80211/tx.c') diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c index 21951bac1ef..541e3e64493 100644 --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c @@ -563,8 +563,8 @@ ieee80211_tx_h_rate_ctrl(struct ieee80211_tx_data *tx) IEEE80211_TX_RC_USE_RTS_CTS; /* RC is busted */ - if (WARN_ON(info->control.rates[i].idx >= - sband->n_bitrates)) { + if (WARN_ON_ONCE(info->control.rates[i].idx >= + sband->n_bitrates)) { info->control.rates[i].idx = -1; continue; } -- cgit v1.2.3-70-g09d2 From 8b30b1fe368ab03049435884c11c5c50e4c4ef0b Mon Sep 17 00:00:00 2001 From: Sujith Date: Fri, 24 Oct 2008 09:55:27 +0530 Subject: mac80211: Re-enable aggregation Wireless HW without any dedicated queues for aggregation do not need the ampdu_queues mechanism present right now in mac80211. Since mac80211 is still incomplete wrt TX MQ changes, do not allow aggregation sessions for drivers that set ampdu_queues. This is only an interim hack until Intel fixes the requeue issue. Signed-off-by: Sujith Signed-off-by: Luis Rodriguez Signed-off-by: John W. Linville --- drivers/net/wireless/ath9k/main.c | 6 ++-- drivers/net/wireless/iwlwifi/iwl-core.c | 3 +- include/linux/skbuff.h | 4 +++ include/net/mac80211.h | 8 ++--- net/core/skbuff.c | 1 + net/mac80211/ht.c | 60 +++++++++++++++++++-------------- net/mac80211/main.c | 7 ++-- net/mac80211/rx.c | 7 ++-- net/mac80211/tx.c | 19 ++++++++--- net/mac80211/wme.c | 24 ++++++------- 10 files changed, 76 insertions(+), 63 deletions(-) (limited to 'net/mac80211/tx.c') diff --git a/drivers/net/wireless/ath9k/main.c b/drivers/net/wireless/ath9k/main.c index 795fed5cadf..f6dc4c82604 100644 --- a/drivers/net/wireless/ath9k/main.c +++ b/drivers/net/wireless/ath9k/main.c @@ -953,10 +953,7 @@ static int ath_attach(u16 devid, &sc->sbands[IEEE80211_BAND_5GHZ]; } - /* FIXME: Have to figure out proper hw init values later */ - hw->queues = 4; - hw->ampdu_queues = 1; /* Register rate control */ hw->rate_control_algorithm = "ath9k_rate_control"; @@ -1745,7 +1742,8 @@ static int ath_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) hw->flags = IEEE80211_HW_RX_INCLUDES_FCS | IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING | IEEE80211_HW_SIGNAL_DBM | - IEEE80211_HW_NOISE_DBM; + IEEE80211_HW_NOISE_DBM | + IEEE80211_HW_AMPDU_AGGREGATION; hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_AP) | diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c index 20c7ff38291..ba05f5ddc6d 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.c +++ b/drivers/net/wireless/iwlwifi/iwl-core.c @@ -871,7 +871,8 @@ int iwl_setup_mac(struct iwl_priv *priv) /* Tell mac80211 our characteristics */ hw->flags = IEEE80211_HW_SIGNAL_DBM | - IEEE80211_HW_NOISE_DBM; + IEEE80211_HW_NOISE_DBM | + IEEE80211_HW_AMPDU_AGGREGATION; hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_AP) | BIT(NL80211_IFTYPE_STATION) | diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h index 487e34507b4..a01b6f84e3b 100644 --- a/include/linux/skbuff.h +++ b/include/linux/skbuff.h @@ -250,6 +250,9 @@ typedef unsigned char *sk_buff_data_t; * @tc_verd: traffic control verdict * @ndisc_nodetype: router type (from link layer) * @do_not_encrypt: set to prevent encryption of this frame + * @requeue: set to indicate that the wireless core should attempt + * a software retry on this frame if we failed to + * receive an ACK for it * @dma_cookie: a cookie to one of several possible DMA operations * done by skb DMA functions * @secmark: security marking @@ -326,6 +329,7 @@ struct sk_buff { #endif #if defined(CONFIG_MAC80211) || defined(CONFIG_MAC80211_MODULE) __u8 do_not_encrypt:1; + __u8 requeue:1; #endif /* 0/13/14 bit hole */ diff --git a/include/net/mac80211.h b/include/net/mac80211.h index 16c895969e6..bba96a20388 100644 --- a/include/net/mac80211.h +++ b/include/net/mac80211.h @@ -242,7 +242,6 @@ struct ieee80211_bss_conf { * @IEEE80211_TX_CTL_RATE_CTRL_PROBE: internal to mac80211, can be * set by rate control algorithms to indicate probe rate, will * be cleared for fragmented frames (except on the last fragment) - * @IEEE80211_TX_CTL_REQUEUE: REMOVE THIS */ enum mac80211_tx_control_flags { IEEE80211_TX_CTL_REQ_TX_STATUS = BIT(0), @@ -258,9 +257,6 @@ enum mac80211_tx_control_flags { IEEE80211_TX_STAT_AMPDU = BIT(10), IEEE80211_TX_STAT_AMPDU_NO_BACK = BIT(11), IEEE80211_TX_CTL_RATE_CTRL_PROBE = BIT(12), - - /* XXX: remove this */ - IEEE80211_TX_CTL_REQUEUE = BIT(13), }; enum mac80211_rate_control_flags { @@ -847,6 +843,9 @@ enum ieee80211_tkip_key_type { * @IEEE80211_HW_SPECTRUM_MGMT: * Hardware supports spectrum management defined in 802.11h * Measurement, Channel Switch, Quieting, TPC + * + * @IEEE80211_HW_AMPDU_AGGREGATION: + * Hardware supports 11n A-MPDU aggregation. */ enum ieee80211_hw_flags { IEEE80211_HW_RX_INCLUDES_FCS = 1<<1, @@ -858,6 +857,7 @@ enum ieee80211_hw_flags { IEEE80211_HW_SIGNAL_DBM = 1<<7, IEEE80211_HW_NOISE_DBM = 1<<8, IEEE80211_HW_SPECTRUM_MGMT = 1<<9, + IEEE80211_HW_AMPDU_AGGREGATION = 1<<10, }; /** diff --git a/net/core/skbuff.c b/net/core/skbuff.c index cdfe473181a..c4c8a33f341 100644 --- a/net/core/skbuff.c +++ b/net/core/skbuff.c @@ -544,6 +544,7 @@ static struct sk_buff *__skb_clone(struct sk_buff *n, struct sk_buff *skb) C(truesize); #if defined(CONFIG_MAC80211) || defined(CONFIG_MAC80211_MODULE) C(do_not_encrypt); + C(requeue); #endif atomic_set(&n->users, 1); diff --git a/net/mac80211/ht.c b/net/mac80211/ht.c index 42c3e590df9..08009d4b7d6 100644 --- a/net/mac80211/ht.c +++ b/net/mac80211/ht.c @@ -458,7 +458,7 @@ int ieee80211_start_tx_ba_session(struct ieee80211_hw *hw, u8 *ra, u16 tid) u8 *state; int ret; - if (tid >= STA_TID_NUM) + if ((tid >= STA_TID_NUM) || !(hw->flags & IEEE80211_HW_AMPDU_AGGREGATION)) return -EINVAL; #ifdef CONFIG_MAC80211_HT_DEBUG @@ -515,17 +515,19 @@ int ieee80211_start_tx_ba_session(struct ieee80211_hw *hw, u8 *ra, u16 tid) (unsigned long)&sta->timer_to_tid[tid]; init_timer(&sta->ampdu_mlme.tid_tx[tid]->addba_resp_timer); - /* create a new queue for this aggregation */ - ret = ieee80211_ht_agg_queue_add(local, sta, tid); + if (hw->ampdu_queues) { + /* create a new queue for this aggregation */ + ret = ieee80211_ht_agg_queue_add(local, sta, tid); - /* case no queue is available to aggregation - * don't switch to aggregation */ - if (ret) { + /* case no queue is available to aggregation + * don't switch to aggregation */ + if (ret) { #ifdef CONFIG_MAC80211_HT_DEBUG - printk(KERN_DEBUG "BA request denied - queue unavailable for" - " tid %d\n", tid); + printk(KERN_DEBUG "BA request denied - " + "queue unavailable for tid %d\n", tid); #endif /* CONFIG_MAC80211_HT_DEBUG */ - goto err_unlock_queue; + goto err_unlock_queue; + } } sdata = sta->sdata; @@ -544,7 +546,8 @@ int ieee80211_start_tx_ba_session(struct ieee80211_hw *hw, u8 *ra, u16 tid) /* No need to requeue the packets in the agg queue, since we * held the tx lock: no packet could be enqueued to the newly * allocated queue */ - ieee80211_ht_agg_queue_remove(local, sta, tid, 0); + if (hw->ampdu_queues) + ieee80211_ht_agg_queue_remove(local, sta, tid, 0); #ifdef CONFIG_MAC80211_HT_DEBUG printk(KERN_DEBUG "BA request denied - HW unavailable for" " tid %d\n", tid); @@ -554,7 +557,8 @@ int ieee80211_start_tx_ba_session(struct ieee80211_hw *hw, u8 *ra, u16 tid) } /* Will put all the packets in the new SW queue */ - ieee80211_requeue(local, ieee802_1d_to_ac[tid]); + if (hw->ampdu_queues) + ieee80211_requeue(local, ieee802_1d_to_ac[tid]); spin_unlock_bh(&sta->lock); /* send an addBA request */ @@ -622,7 +626,8 @@ int ieee80211_stop_tx_ba_session(struct ieee80211_hw *hw, ra, tid); #endif /* CONFIG_MAC80211_HT_DEBUG */ - ieee80211_stop_queue(hw, sta->tid_to_tx_q[tid]); + if (hw->ampdu_queues) + ieee80211_stop_queue(hw, sta->tid_to_tx_q[tid]); *state = HT_AGG_STATE_REQ_STOP_BA_MSK | (initiator << HT_AGG_STATE_INITIATOR_SHIFT); @@ -635,7 +640,8 @@ int ieee80211_stop_tx_ba_session(struct ieee80211_hw *hw, if (ret) { WARN_ON(ret != -EBUSY); *state = HT_AGG_STATE_OPERATIONAL; - ieee80211_wake_queue(hw, sta->tid_to_tx_q[tid]); + if (hw->ampdu_queues) + ieee80211_wake_queue(hw, sta->tid_to_tx_q[tid]); goto stop_BA_exit; } @@ -691,7 +697,8 @@ void ieee80211_start_tx_ba_cb(struct ieee80211_hw *hw, u8 *ra, u16 tid) #ifdef CONFIG_MAC80211_HT_DEBUG printk(KERN_DEBUG "Aggregation is on for tid %d \n", tid); #endif - ieee80211_wake_queue(hw, sta->tid_to_tx_q[tid]); + if (hw->ampdu_queues) + ieee80211_wake_queue(hw, sta->tid_to_tx_q[tid]); } spin_unlock_bh(&sta->lock); rcu_read_unlock(); @@ -745,16 +752,18 @@ void ieee80211_stop_tx_ba_cb(struct ieee80211_hw *hw, u8 *ra, u8 tid) ieee80211_send_delba(sta->sdata, ra, tid, WLAN_BACK_INITIATOR, WLAN_REASON_QSTA_NOT_USE); - agg_queue = sta->tid_to_tx_q[tid]; - - ieee80211_ht_agg_queue_remove(local, sta, tid, 1); - - /* We just requeued the all the frames that were in the - * removed queue, and since we might miss a softirq we do - * netif_schedule_queue. ieee80211_wake_queue is not used - * here as this queue is not necessarily stopped - */ - netif_schedule_queue(netdev_get_tx_queue(local->mdev, agg_queue)); + if (hw->ampdu_queues) { + agg_queue = sta->tid_to_tx_q[tid]; + ieee80211_ht_agg_queue_remove(local, sta, tid, 1); + + /* We just requeued the all the frames that were in the + * removed queue, and since we might miss a softirq we do + * netif_schedule_queue. ieee80211_wake_queue is not used + * here as this queue is not necessarily stopped + */ + netif_schedule_queue(netdev_get_tx_queue(local->mdev, + agg_queue)); + } spin_lock_bh(&sta->lock); *state = HT_AGG_STATE_IDLE; sta->ampdu_mlme.addba_req_num[tid] = 0; @@ -1011,7 +1020,8 @@ void ieee80211_process_addba_resp(struct ieee80211_local *local, *state |= HT_ADDBA_RECEIVED_MSK; sta->ampdu_mlme.addba_req_num[tid] = 0; - if (*state == HT_AGG_STATE_OPERATIONAL) + if (*state == HT_AGG_STATE_OPERATIONAL && + local->hw.ampdu_queues) ieee80211_wake_queue(hw, sta->tid_to_tx_q[tid]); spin_unlock_bh(&sta->lock); diff --git a/net/mac80211/main.c b/net/mac80211/main.c index 88c1975a97a..fa0cc7a1e6b 100644 --- a/net/mac80211/main.c +++ b/net/mac80211/main.c @@ -386,8 +386,6 @@ static void ieee80211_handle_filtered_frame(struct ieee80211_local *local, struct sta_info *sta, struct sk_buff *skb) { - struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); - sta->tx_filtered_count++; /* @@ -434,10 +432,9 @@ static void ieee80211_handle_filtered_frame(struct ieee80211_local *local, return; } - if (!test_sta_flags(sta, WLAN_STA_PS) && - !(info->flags & IEEE80211_TX_CTL_REQUEUE)) { + if (!test_sta_flags(sta, WLAN_STA_PS) && !skb->requeue) { /* Software retry the packet once */ - info->flags |= IEEE80211_TX_CTL_REQUEUE; + skb->requeue = 1; ieee80211_remove_tx_extra(local, sta->key, skb); dev_queue_xmit(skb); return; diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index c4c95f1db60..648a1d0e6c8 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c @@ -669,7 +669,6 @@ static int ap_sta_ps_end(struct sta_info *sta) struct ieee80211_local *local = sdata->local; struct sk_buff *skb; int sent = 0; - struct ieee80211_tx_info *info; atomic_dec(&sdata->bss->num_sta_ps); @@ -685,13 +684,11 @@ static int ap_sta_ps_end(struct sta_info *sta) /* Send all buffered frames to the station */ while ((skb = skb_dequeue(&sta->tx_filtered)) != NULL) { - info = IEEE80211_SKB_CB(skb); sent++; - info->flags |= IEEE80211_TX_CTL_REQUEUE; + skb->requeue = 1; dev_queue_xmit(skb); } while ((skb = skb_dequeue(&sta->ps_tx_buf)) != NULL) { - info = IEEE80211_SKB_CB(skb); local->total_ps_buffered--; sent++; #ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG @@ -699,7 +696,7 @@ static int ap_sta_ps_end(struct sta_info *sta) "since STA not sleeping anymore\n", sdata->dev->name, sta->sta.addr, sta->sta.aid); #endif /* CONFIG_MAC80211_VERBOSE_PS_DEBUG */ - info->flags |= IEEE80211_TX_CTL_REQUEUE; + skb->requeue = 1; dev_queue_xmit(skb); } diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c index 541e3e64493..d6392af9cd2 100644 --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c @@ -661,6 +661,7 @@ ieee80211_tx_h_sequence(struct ieee80211_tx_data *tx) static ieee80211_tx_result debug_noinline ieee80211_tx_h_fragment(struct ieee80211_tx_data *tx) { + struct ieee80211_tx_info *info = IEEE80211_SKB_CB(tx->skb); struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)tx->skb->data; size_t hdrlen, per_fragm, num_fragm, payload_len, left; struct sk_buff **frags, *first, *frag; @@ -677,9 +678,7 @@ ieee80211_tx_h_fragment(struct ieee80211_tx_data *tx) * This scenario is handled in __ieee80211_tx_prepare but extra * caution taken here as fragmented ampdu may cause Tx stop. */ - if (WARN_ON(tx->flags & IEEE80211_TX_CTL_AMPDU || - skb_get_queue_mapping(tx->skb) >= - ieee80211_num_regular_queues(&tx->local->hw))) + if (WARN_ON(info->flags & IEEE80211_TX_CTL_AMPDU)) return TX_DROP; first = tx->skb; @@ -951,7 +950,8 @@ __ieee80211_tx_prepare(struct ieee80211_tx_data *tx, struct ieee80211_sub_if_data *sdata; struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); - int hdrlen; + int hdrlen, tid; + u8 *qc, *state; memset(tx, 0, sizeof(*tx)); tx->skb = skb; @@ -982,6 +982,15 @@ __ieee80211_tx_prepare(struct ieee80211_tx_data *tx, tx->sta = sta_info_get(local, hdr->addr1); + if (tx->sta && ieee80211_is_data_qos(hdr->frame_control)) { + qc = ieee80211_get_qos_ctl(hdr); + tid = *qc & IEEE80211_QOS_CTL_TID_MASK; + + state = &tx->sta->ampdu_mlme.tid_state_tx[tid]; + if (*state == HT_AGG_STATE_OPERATIONAL) + info->flags |= IEEE80211_TX_CTL_AMPDU; + } + if (is_multicast_ether_addr(hdr->addr1)) { tx->flags &= ~IEEE80211_TX_UNICAST; info->flags |= IEEE80211_TX_CTL_NO_ACK; @@ -1172,7 +1181,7 @@ retry: * queues, there's no reason for a driver to reject * a frame there, warn and drop it. */ - if (WARN_ON(queue >= ieee80211_num_regular_queues(&local->hw))) + if (WARN_ON(info->flags & IEEE80211_TX_CTL_AMPDU)) goto drop; store = &local->pending_packet[queue]; diff --git a/net/mac80211/wme.c b/net/mac80211/wme.c index d27ef7f2d4a..ac71b38f7cb 100644 --- a/net/mac80211/wme.c +++ b/net/mac80211/wme.c @@ -114,8 +114,8 @@ u16 ieee80211_select_queue(struct net_device *dev, struct sk_buff *skb) { struct ieee80211_master_priv *mpriv = netdev_priv(dev); struct ieee80211_local *local = mpriv->local; + struct ieee80211_hw *hw = &local->hw; struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; - struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); struct sta_info *sta; u16 queue; u8 tid; @@ -124,21 +124,19 @@ u16 ieee80211_select_queue(struct net_device *dev, struct sk_buff *skb) if (unlikely(queue >= local->hw.queues)) queue = local->hw.queues - 1; - if (info->flags & IEEE80211_TX_CTL_REQUEUE) { + if (skb->requeue) { + if (!hw->ampdu_queues) + return queue; + rcu_read_lock(); sta = sta_info_get(local, hdr->addr1); tid = skb->priority & IEEE80211_QOS_CTL_TAG1D_MASK; if (sta) { - struct ieee80211_hw *hw = &local->hw; int ampdu_queue = sta->tid_to_tx_q[tid]; if ((ampdu_queue < ieee80211_num_queues(hw)) && - test_bit(ampdu_queue, local->queue_pool)) { + test_bit(ampdu_queue, local->queue_pool)) queue = ampdu_queue; - info->flags |= IEEE80211_TX_CTL_AMPDU; - } else { - info->flags &= ~IEEE80211_TX_CTL_AMPDU; - } } rcu_read_unlock(); @@ -159,20 +157,18 @@ u16 ieee80211_select_queue(struct net_device *dev, struct sk_buff *skb) *p++ = ack_policy | tid; *p = 0; + if (!hw->ampdu_queues) + return queue; + rcu_read_lock(); sta = sta_info_get(local, hdr->addr1); if (sta) { int ampdu_queue = sta->tid_to_tx_q[tid]; - struct ieee80211_hw *hw = &local->hw; if ((ampdu_queue < ieee80211_num_queues(hw)) && - test_bit(ampdu_queue, local->queue_pool)) { + test_bit(ampdu_queue, local->queue_pool)) queue = ampdu_queue; - info->flags |= IEEE80211_TX_CTL_AMPDU; - } else { - info->flags &= ~IEEE80211_TX_CTL_AMPDU; - } } rcu_read_unlock(); -- cgit v1.2.3-70-g09d2 From 2df78167ade3d0542f0f95be7cc58861343cce3a Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Tue, 28 Oct 2008 16:49:41 +0100 Subject: wireless: fix a few sparse warnings Signed-off-by: Johannes Berg Signed-off-by: John W. Linville --- net/mac80211/rc80211_minstrel.c | 2 +- net/mac80211/tx.c | 1 - net/wireless/reg.c | 2 +- 3 files changed, 2 insertions(+), 3 deletions(-) (limited to 'net/mac80211/tx.c') diff --git a/net/mac80211/rc80211_minstrel.c b/net/mac80211/rc80211_minstrel.c index c643e373fc5..2b3b490a607 100644 --- a/net/mac80211/rc80211_minstrel.c +++ b/net/mac80211/rc80211_minstrel.c @@ -225,7 +225,7 @@ minstrel_get_next_sample(struct minstrel_sta_info *mi) return sample_ndx; } -void +static void minstrel_get_rate(void *priv, struct ieee80211_sta *sta, void *priv_sta, struct ieee80211_tx_rate_control *txrc) { diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c index d6392af9cd2..0d81b2cfd1a 100644 --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c @@ -698,7 +698,6 @@ ieee80211_tx_h_fragment(struct ieee80211_tx_data *tx) left = payload_len - per_fragm; for (i = 0; i < num_fragm - 1; i++) { struct ieee80211_hdr *fhdr; - struct ieee80211_tx_info *info; size_t copylen; if (left <= 0) diff --git a/net/wireless/reg.c b/net/wireless/reg.c index 9dff716d1b0..8e5d23975a0 100644 --- a/net/wireless/reg.c +++ b/net/wireless/reg.c @@ -638,7 +638,7 @@ static void print_regdomain(const struct ieee80211_regdomain *rd) print_rd_rules(rd); } -void print_regdomain_info(const struct ieee80211_regdomain *rd) +static void print_regdomain_info(const struct ieee80211_regdomain *rd) { printk(KERN_INFO "cfg80211: Regulatory domain: %c%c\n", rd->alpha2[0], rd->alpha2[1]); -- cgit v1.2.3-70-g09d2 From 8e7be8da8ec7cc2828f4434d8d3c2ab4d1d4e7a4 Mon Sep 17 00:00:00 2001 From: Rami Rosen Date: Mon, 1 Dec 2008 13:56:55 +0200 Subject: mac80211: tx module cleanup. This patch removes unnecessary parameter in ieee80211_beacon_add_tim() and removes unneeded definition and assignment for bdev (instance of net_device) in ieee80211_beacon_get() and in ieee80211_get_buffered_bc() (all in tx.c). Signed-off-by: Rami Rosen Acked-by: Johannes Berg Signed-off-by: John W. Linville --- net/mac80211/tx.c | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) (limited to 'net/mac80211/tx.c') diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c index 0d81b2cfd1a..d7761e95e4c 100644 --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c @@ -1779,8 +1779,7 @@ void ieee80211_tx_pending(unsigned long data) /* functions for drivers to get certain frames */ -static void ieee80211_beacon_add_tim(struct ieee80211_local *local, - struct ieee80211_if_ap *bss, +static void ieee80211_beacon_add_tim(struct ieee80211_if_ap *bss, struct sk_buff *skb, struct beacon_data *beacon) { @@ -1848,7 +1847,6 @@ struct sk_buff *ieee80211_beacon_get(struct ieee80211_hw *hw, struct ieee80211_local *local = hw_to_local(hw); struct sk_buff *skb = NULL; struct ieee80211_tx_info *info; - struct net_device *bdev; struct ieee80211_sub_if_data *sdata = NULL; struct ieee80211_if_ap *ap = NULL; struct ieee80211_if_sta *ifsta = NULL; @@ -1861,7 +1859,6 @@ struct sk_buff *ieee80211_beacon_get(struct ieee80211_hw *hw, rcu_read_lock(); sdata = vif_to_sdata(vif); - bdev = sdata->dev; if (sdata->vif.type == NL80211_IFTYPE_AP) { ap = &sdata->u.ap; @@ -1889,12 +1886,12 @@ struct sk_buff *ieee80211_beacon_get(struct ieee80211_hw *hw, * of the tim bitmap in mac80211 and the driver. */ if (local->tim_in_locked_section) { - ieee80211_beacon_add_tim(local, ap, skb, beacon); + ieee80211_beacon_add_tim(ap, skb, beacon); } else { unsigned long flags; spin_lock_irqsave(&local->sta_lock, flags); - ieee80211_beacon_add_tim(local, ap, skb, beacon); + ieee80211_beacon_add_tim(ap, skb, beacon); spin_unlock_irqrestore(&local->sta_lock, flags); } @@ -2016,14 +2013,12 @@ ieee80211_get_buffered_bc(struct ieee80211_hw *hw, struct sk_buff *skb = NULL; struct sta_info *sta; struct ieee80211_tx_data tx; - struct net_device *bdev; struct ieee80211_sub_if_data *sdata; struct ieee80211_if_ap *bss = NULL; struct beacon_data *beacon; struct ieee80211_tx_info *info; sdata = vif_to_sdata(vif); - bdev = sdata->dev; bss = &sdata->u.ap; if (!bss) -- cgit v1.2.3-70-g09d2 From f546638c3f809fdacddc03fe765669c3042e0d9d Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Tue, 9 Dec 2008 12:30:03 +0100 Subject: mac80211: remove fragmentation offload functionality There's no driver that actually does fragmentation on the device, and the callback is buggy (when it returns an error, mac80211's fragmentation status is changed so reading the frag threshold from userspace reads the new value despite the error). Let's just remove it, if we really find some hardware supporting it we can add it back later. Signed-off-by: Johannes Berg Signed-off-by: John W. Linville --- include/net/mac80211.h | 5 ----- net/mac80211/tx.c | 1 - net/mac80211/wext.c | 8 -------- 3 files changed, 14 deletions(-) (limited to 'net/mac80211/tx.c') diff --git a/include/net/mac80211.h b/include/net/mac80211.h index 346f373fb67..5ecc686c1f1 100644 --- a/include/net/mac80211.h +++ b/include/net/mac80211.h @@ -1258,10 +1258,6 @@ enum ieee80211_ampdu_mlme_action { * * @set_rts_threshold: Configuration of RTS threshold (if device needs it) * - * @set_frag_threshold: Configuration of fragmentation threshold. Assign this if - * the device does fragmentation by itself; if this method is assigned then - * the stack will not do fragmentation. - * * @sta_notify: Notifies low level driver about addition or removal of an * associated station, AP, IBSS/WDS/mesh peer etc. Must be atomic. * @@ -1331,7 +1327,6 @@ struct ieee80211_ops { void (*get_tkip_seq)(struct ieee80211_hw *hw, u8 hw_key_idx, u32 *iv32, u16 *iv16); int (*set_rts_threshold)(struct ieee80211_hw *hw, u32 value); - int (*set_frag_threshold)(struct ieee80211_hw *hw, u32 value); void (*sta_notify)(struct ieee80211_hw *hw, struct ieee80211_vif *vif, enum sta_notify_cmd, struct ieee80211_sta *sta); void (*sta_notify_ps)(struct ieee80211_hw *hw, diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c index d7761e95e4c..b098c58d216 100644 --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c @@ -1001,7 +1001,6 @@ __ieee80211_tx_prepare(struct ieee80211_tx_data *tx, if (tx->flags & IEEE80211_TX_FRAGMENTED) { if ((tx->flags & IEEE80211_TX_UNICAST) && skb->len + FCS_LEN > local->fragmentation_threshold && - !local->ops->set_frag_threshold && !(info->flags & IEEE80211_TX_CTL_AMPDU)) tx->flags |= IEEE80211_TX_FRAGMENTED; else diff --git a/net/mac80211/wext.c b/net/mac80211/wext.c index 4e1fdcfacb0..fbeb927c116 100644 --- a/net/mac80211/wext.c +++ b/net/mac80211/wext.c @@ -639,14 +639,6 @@ static int ieee80211_ioctl_siwfrag(struct net_device *dev, local->fragmentation_threshold = frag->value & ~0x1; } - /* If the wlan card performs fragmentation in hardware/firmware, - * configure it here */ - - if (local->ops->set_frag_threshold) - return local->ops->set_frag_threshold( - local_to_hw(local), - local->fragmentation_threshold); - return 0; } -- cgit v1.2.3-70-g09d2 From 520eb82076993b7f55ef9b80771d264272e5127b Mon Sep 17 00:00:00 2001 From: Kalle Valo Date: Thu, 18 Dec 2008 23:35:27 +0200 Subject: mac80211: implement dynamic power save This patch implements dynamic power save for mac80211. Basically it means enabling power save mode after an idle period. Implementing it dynamically gives a good compromise of low power consumption and low latency. Some hardware have support for this in firmware, but some require the host to do it. The dynamic power save is implemented by adding an timeout to ieee80211_subif_start_xmit(). The timeout can be enabled from userspace with Wireless Extensions. For example, the command below enables the dynamic power save and sets the time timeout to 500 ms: iwconfig wlan0 power timeout 500m Power save now only works with devices which handle power save in firmware. It's also disabled by default and the heuristics when and how to enable is considered as a policy decision and will be left for the userspace to handle. In case the firmware has support for this, drivers can disable this feature with IEEE80211_HW_NO_STACK_DYNAMIC_PS. Big thanks to Johannes Berg for the help with the design and code. Signed-off-by: Kalle Valo Acked-by: Johannes Berg Signed-off-by: John W. Linville --- include/net/mac80211.h | 6 ++++++ net/mac80211/ieee80211_i.h | 10 ++++++++++ net/mac80211/main.c | 7 +++++++ net/mac80211/mlme.c | 49 ++++++++++++++++++++++++++++++++++++++++++++-- net/mac80211/tx.c | 13 ++++++++++++ net/mac80211/wext.c | 30 ++++++++++++++++++---------- 6 files changed, 103 insertions(+), 12 deletions(-) (limited to 'net/mac80211/tx.c') diff --git a/include/net/mac80211.h b/include/net/mac80211.h index 9428d3e2f11..b3bd00a9d99 100644 --- a/include/net/mac80211.h +++ b/include/net/mac80211.h @@ -854,6 +854,11 @@ enum ieee80211_tkip_key_type { * * @IEEE80211_HW_AMPDU_AGGREGATION: * Hardware supports 11n A-MPDU aggregation. + * + * @IEEE80211_HW_NO_STACK_DYNAMIC_PS: + * Hardware which has dynamic power save support, meaning + * that power save is enabled in idle periods, and don't need support + * from stack. */ enum ieee80211_hw_flags { IEEE80211_HW_RX_INCLUDES_FCS = 1<<1, @@ -866,6 +871,7 @@ enum ieee80211_hw_flags { IEEE80211_HW_NOISE_DBM = 1<<8, IEEE80211_HW_SPECTRUM_MGMT = 1<<9, IEEE80211_HW_AMPDU_AGGREGATION = 1<<10, + IEEE80211_HW_NO_STACK_DYNAMIC_PS = 1<<11, }; /** diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index a74d6738b30..f3eec989662 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h @@ -540,6 +540,7 @@ enum { enum queue_stop_reason { IEEE80211_QUEUE_STOP_REASON_DRIVER, + IEEE80211_QUEUE_STOP_REASON_PS, }; /* maximum number of hardware queues we support. */ @@ -693,7 +694,12 @@ struct ieee80211_local { */ int wifi_wme_noack_test; unsigned int wmm_acm; /* bit field of ACM bits (BIT(802.1D tag)) */ + bool powersave; + int dynamic_ps_timeout; + struct work_struct dynamic_ps_enable_work; + struct work_struct dynamic_ps_disable_work; + struct timer_list dynamic_ps_timer; #ifdef CONFIG_MAC80211_DEBUGFS struct local_debugfsdentries { @@ -977,6 +983,10 @@ int ieee80211_set_freq(struct ieee80211_sub_if_data *sdata, int freq); u64 ieee80211_mandatory_rates(struct ieee80211_local *local, enum ieee80211_band band); +void ieee80211_dynamic_ps_enable_work(struct work_struct *work); +void ieee80211_dynamic_ps_disable_work(struct work_struct *work); +void ieee80211_dynamic_ps_timer(unsigned long data); + void ieee80211_wake_queues_by_reason(struct ieee80211_hw *hw, enum queue_stop_reason reason); void ieee80211_stop_queues_by_reason(struct ieee80211_hw *hw, diff --git a/net/mac80211/main.c b/net/mac80211/main.c index 21335382f53..24b14363d6e 100644 --- a/net/mac80211/main.c +++ b/net/mac80211/main.c @@ -729,6 +729,13 @@ struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len, INIT_DELAYED_WORK(&local->scan_work, ieee80211_scan_work); + INIT_WORK(&local->dynamic_ps_enable_work, + ieee80211_dynamic_ps_enable_work); + INIT_WORK(&local->dynamic_ps_disable_work, + ieee80211_dynamic_ps_disable_work); + setup_timer(&local->dynamic_ps_timer, + ieee80211_dynamic_ps_timer, (unsigned long) local); + sta_info_init(local); tasklet_init(&local->tx_pending_tasklet, ieee80211_tx_pending, diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index dac8bd37dcf..5ba721b6a39 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c @@ -745,8 +745,14 @@ static void ieee80211_set_associated(struct ieee80211_sub_if_data *sdata, ieee80211_bss_info_change_notify(sdata, bss_info_changed); if (local->powersave) { - local->hw.conf.flags |= IEEE80211_CONF_PS; - ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_PS); + if (local->dynamic_ps_timeout > 0) + mod_timer(&local->dynamic_ps_timer, jiffies + + msecs_to_jiffies(local->dynamic_ps_timeout)); + else { + conf->flags |= IEEE80211_CONF_PS; + ieee80211_hw_config(local, + IEEE80211_CONF_CHANGE_PS); + } } netif_tx_start_all_queues(sdata->dev); @@ -866,6 +872,9 @@ static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata, local->oper_channel_type = NL80211_CHAN_NO_HT; config_changed |= IEEE80211_CONF_CHANGE_HT; + del_timer_sync(&local->dynamic_ps_timer); + cancel_work_sync(&local->dynamic_ps_enable_work); + if (local->hw.conf.flags & IEEE80211_CONF_PS) { local->hw.conf.flags &= ~IEEE80211_CONF_PS; config_changed |= IEEE80211_CONF_CHANGE_PS; @@ -2593,3 +2602,39 @@ void ieee80211_mlme_notify_scan_completed(struct ieee80211_local *local) ieee80211_restart_sta_timer(sdata); rcu_read_unlock(); } + +void ieee80211_dynamic_ps_disable_work(struct work_struct *work) +{ + struct ieee80211_local *local = + container_of(work, struct ieee80211_local, + dynamic_ps_disable_work); + + if (local->hw.conf.flags & IEEE80211_CONF_PS) { + local->hw.conf.flags &= ~IEEE80211_CONF_PS; + ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_PS); + } + + ieee80211_wake_queues_by_reason(&local->hw, + IEEE80211_QUEUE_STOP_REASON_PS); +} + +void ieee80211_dynamic_ps_enable_work(struct work_struct *work) +{ + struct ieee80211_local *local = + container_of(work, struct ieee80211_local, + dynamic_ps_enable_work); + + if (local->hw.conf.flags & IEEE80211_CONF_PS) + return; + + local->hw.conf.flags |= IEEE80211_CONF_PS; + + ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_PS); +} + +void ieee80211_dynamic_ps_timer(unsigned long data) +{ + struct ieee80211_local *local = (void *) data; + + queue_work(local->hw.workqueue, &local->dynamic_ps_enable_work); +} diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c index b098c58d216..a4af3a124cc 100644 --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c @@ -1473,6 +1473,19 @@ int ieee80211_subif_start_xmit(struct sk_buff *skb, goto fail; } + if (!(local->hw.flags & IEEE80211_HW_NO_STACK_DYNAMIC_PS) && + local->dynamic_ps_timeout > 0) { + if (local->hw.conf.flags & IEEE80211_CONF_PS) { + ieee80211_stop_queues_by_reason(&local->hw, + IEEE80211_QUEUE_STOP_REASON_PS); + queue_work(local->hw.workqueue, + &local->dynamic_ps_disable_work); + } + + mod_timer(&local->dynamic_ps_timer, jiffies + + msecs_to_jiffies(local->dynamic_ps_timeout)); + } + nh_pos = skb_network_header(skb) - skb->data; h_pos = skb_transport_header(skb) - skb->data; diff --git a/net/mac80211/wext.c b/net/mac80211/wext.c index f6640d04715..7162d5816f3 100644 --- a/net/mac80211/wext.c +++ b/net/mac80211/wext.c @@ -833,7 +833,7 @@ static int ieee80211_ioctl_siwpower(struct net_device *dev, struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); struct ieee80211_conf *conf = &local->hw.conf; - int ret = 0; + int ret = 0, timeout = 0; bool ps; if (sdata->vif.type != NL80211_IFTYPE_STATION) @@ -841,6 +841,7 @@ static int ieee80211_ioctl_siwpower(struct net_device *dev, if (wrq->disabled) { ps = false; + timeout = 0; goto set; } @@ -850,22 +851,31 @@ static int ieee80211_ioctl_siwpower(struct net_device *dev, case IW_POWER_ALL_R: /* If explicitely state all */ ps = true; break; - default: /* Otherwise we don't support it */ - return -EINVAL; + default: /* Otherwise we ignore */ + break; } - if (ps == local->powersave) - return ret; + if (wrq->flags & IW_POWER_TIMEOUT) + timeout = wrq->value / 1000; set: + if (ps == local->powersave && timeout == local->dynamic_ps_timeout) + return ret; + local->powersave = ps; + local->dynamic_ps_timeout = timeout; if (sdata->u.sta.flags & IEEE80211_STA_ASSOCIATED) { - if (local->powersave) - conf->flags |= IEEE80211_CONF_PS; - else - conf->flags &= ~IEEE80211_CONF_PS; - + if (!(local->hw.flags & IEEE80211_HW_NO_STACK_DYNAMIC_PS) && + local->dynamic_ps_timeout > 0) + mod_timer(&local->dynamic_ps_timer, jiffies + + msecs_to_jiffies(local->dynamic_ps_timeout)); + else { + if (local->powersave) + conf->flags |= IEEE80211_CONF_PS; + else + conf->flags &= ~IEEE80211_CONF_PS; + } ret = ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_PS); } -- cgit v1.2.3-70-g09d2