mac80211 QoS-related enhancements
Subsystems (4)
Johannes Berg
maintainercover mac80211 QoS-related enhancements
Note: This patch series requires a number of other patches, notably Ivo's rt2x00 update and Ivo's mac80211 patch
"mac80211: Replace ieee80211_tx_control->key_idx with ieee80211_key_conf"
Any testing of this series is welcome, even just the first patch by itself (especially with drivers other than b43), it doesn't make sense to test with patch 2 and not 3 though, so if you're going to test one by one treat 2/3 as a set.
This series of patches reworks mac80211 step-by-step to use more generic code instead of having implementations of everything built-in.
The first patch (mac80211: use rate index in TX control) is just preparation (but I'm not entirely sure about the iwlwifi changes, haven't tested them yet.)
The second patch I want input from netdev from, what do people think about using the GSO code that way? It does seem like a bit of an abuse to fill the skb->next pointer from within ->hard_start_xmit() but it works and allows me to get rid of all the weird retry logic in mac80211 (patch three). Finally, the fourth patch converts mac80211 and drivers to be multiqueue aware.
There are still a number of things missing in this series:
* we need to rework the classification function to be a real classifier that we install on our wme qdisc
* we should allow tuning the medium access parameters via the wme qdisc
johannes
PATCH 1/4 mac80211: use rate index in TX control
This patch modifies struct ieee80211_tx_control to give band info and the rate index (instead of rate pointers) to drivers. This mostly serves to reduce the TX control structure size to make it fit into skb->cb so that the fragmentation code can put it there and we can think about passing it to drivers that way in the future.
--- drivers/net/wireless/adm8211.c | 6 - drivers/net/wireless/at76_usb.c | 2 drivers/net/wireless/ath5k/base.c | 8 +- drivers/net/wireless/b43/main.c | 2 drivers/net/wireless/b43/xmit.c | 13 ++- drivers/net/wireless/b43legacy/xmit.c | 9 +- drivers/net/wireless/iwlwifi/iwl-3945-rs.c | 6 - drivers/net/wireless/iwlwifi/iwl-3945.c | 7 + drivers/net/wireless/iwlwifi/iwl-4965-rs.c | 12 +-- drivers/net/wireless/iwlwifi/iwl-4965.c | 13 +-- drivers/net/wireless/iwlwifi/iwl3945-base.c | 4 - drivers/net/wireless/iwlwifi/iwl4965-base.c | 4 - drivers/net/wireless/p54/p54common.c | 2 drivers/net/wireless/rt2x00/rt2x00dev.c | 6 - drivers/net/wireless/rtl8180_dev.c | 19 ++--- drivers/net/wireless/rtl8187_dev.c | 10 -- drivers/net/wireless/zd1211rw/zd_mac.c | 7 + include/net/mac80211.h | 51 ++++++++++--- net/mac80211/ieee80211_i.h | 8 +- net/mac80211/mlme.c | 6 - net/mac80211/rate.c | 12 ++- net/mac80211/rate.h | 25 ++---- net/mac80211/rc80211_pid_algo.c | 6 - net/mac80211/tx.c | 104 +++++++++++++++------------- net/mac80211/util.c | 10 ++ 25 files changed, 200 insertions(+), 152 deletions(-)
include/net/mac80211.h +39 -12
@@ -266,27 +266,26 @@ enum mac80211_tx_control_flags {* ieee80211_ops->remove_interface() callback funtion. * The hw_key pointer is valid until it has been removed with the * ieee80211_ops->set_key() callback function. -* The tx_rate and alt_retry_rate pointers are valid until the phy is -* deregistered. */ struct ieee80211_tx_control { -struct ieee80211_vif *vif; -struct ieee80211_rate *tx_rate; +u32 flags;/* tx control flags defined above */ + +s8 tx_rate_idx,/* Transmit rate (indexes registered rates) */ + rts_cts_rate_idx,/* Transmit rate for RTS/CTS frame */ + alt_retry_rate_idx;/* retry rate for the last retries */ -/* Transmit rate for RTS/CTS frame */ -struct ieee80211_rate *rts_cts_rate; +s8 retry_limit;/* 1 = only first attempt, 2 = one retry, .. +* This could be used when set_retry_limit +* is not implemented by the driver */ -/* retry rate for the last retries */ -struct ieee80211_rate *alt_retry_rate; +struct ieee80211_vif *vif;/* Key used for hardware encryption * NULL if IEEE80211_TXCTL_DO_NOT_ENCRYPT is set */ struct ieee80211_key_conf *hw_key; -u32 flags;/* tx control flags defined above */ -u8 retry_limit;/* 1 = only first attempt, 2 = one retry, .. -* This could be used when set_retry_limit -* is not implemented by the driver */ +enum ieee80211_band band; +u8 antenna_sel_tx;/* 0 = default/diversity, otherwise bit * position represents antenna number used */ u8 icv_len;/* length of the ICV/MIC field in octets */
@@ -298,6 +297,7 @@ struct ieee80211_tx_control { }; +/** * enum mac80211_rx_flags - receive flags *
@@ -799,6 +799,33 @@ static inline void SET_IEEE80211_PERM_ADmemcpy (hw->wiphy->perm_addr, addr,ETH_ALEN ); } +static inline struct ieee80211_rate * +ieee80211_get_tx_rate (const struct ieee80211_hw *hw, +const struct ieee80211_tx_control *c) +{ +if (WARN_ON (c->tx_rate_idx <0 )) +return NULL ; +return &hw->wiphy->bands[c->band]->bitrates[c->tx_rate_idx]; +} + +static inline struct ieee80211_rate * +ieee80211_get_rts_cts_rate (const struct ieee80211_hw *hw, +const struct ieee80211_tx_control *c) +{ +if (c->rts_cts_rate_idx <0 ) +return NULL ; +return &hw->wiphy->bands[c->band]->bitrates[c->rts_cts_rate_idx]; +} + +static inline struct ieee80211_rate * +ieee80211_get_alt_retry_rate (const struct ieee80211_hw *hw, +const struct ieee80211_tx_control *c) +{ +if (c->alt_retry_rate_idx <0 ) +return NULL ; +return &hw->wiphy->bands[c->band]->bitrates[c->alt_retry_rate_idx]; +} +/** * DOC: Hardware crypto acceleration *
net/mac80211/rate.h +9 -16
@@ -19,14 +19,15 @@#include "ieee80211_i.h" #include "sta_info.h" -/* TODO: kdoc */ +/** +* struct rate_selection - rate selection for rate control algos +* @rate: selected transmission rate index +* @nonerp: Non-ERP rate to use instead if ERP cannot be used +* @probe: rate for probing (or -1) +* +*/ struct rate_selection { -/* Selected transmission rate */ -struct ieee80211_rate *rate; -/* Non-ERP rate to use if mac80211 decides it cannot use an ERP rate */ -struct ieee80211_rate *nonerp; -/* probe with this rate, or NULL for no probing */ -struct ieee80211_rate *probe; +s8 rate_idx, nonerp_idx, probe_idx; };struct rate_control_ops {
@@ -138,7 +139,7 @@ static inline int rate_supported(structreturn (sta ==NULL || sta->supp_rates[band] &BIT (index)); } -static inline int +static inline s8 rate_lowest_index (struct ieee80211_local *local,struct ieee80211_supported_band *sband,struct sta_info *sta)
@@ -155,14 +156,6 @@ rate_lowest_index(struct ieee80211_localreturn 0 ; } -static inline struct ieee80211_rate * -rate_lowest (struct ieee80211_local *local, -struct ieee80211_supported_band *sband, -struct sta_info *sta) -{ -return &sband->bitrates[rate_lowest_index (local, sband, sta)]; -} -/* functions for rate control related to a device */ int ieee80211_init_rate_ctrl_alg(struct ieee80211_local *local,
net/mac80211/mlme.c +3 -3
@@ -2371,15 +2371,15 @@ static int ieee80211_sta_join_ibss(strucmemset (&control,0 ,sizeof (control));rate_control_get_rate (dev, sband, skb, &ratesel); -if (!ratesel.rate) { +if (ratesel.rate_idx <0 ) {printk (KERN_DEBUG "%s: Failed to determine TX rate " "for IBSS beacon\n" , dev->name);break ; } control.vif = &sdata->vif; - control.tx_rate = ratesel.rate; + control.tx_rate_idx = ratesel.rate_idx;if (sdata->bss_conf.use_short_preamble && - ratesel.rate->flags &IEEE80211_RATE_SHORT_PREAMBLE ) + sband->bitrates[ratesel.rate_idx].flags &IEEE80211_RATE_SHORT_PREAMBLE ) control.flags |=IEEE80211_TXCTL_SHORT_PREAMBLE ; control.antenna_sel_tx = local->hw.conf.antenna_sel_tx; control.flags |=IEEE80211_TXCTL_NO_ACK ;
net/mac80211/rate.c +8 -4
@@ -176,20 +176,24 @@ void rate_control_get_rate(struct net_dercu_read_lock (); sta =sta_info_get (local, hdr->addr1); -memset (sel,0 ,sizeof (struct rate_selection )); + sel->rate_idx =-1 ; + sel->nonerp_idx =-1 ; + sel->probe_idx =-1 ; ref->ops->get_rate (ref->priv, dev, sband, skb, sel); +BUG_ON (sel->rate_idx <0 ); +/* Select a non-ERP backup rate. */ -if (!sel->nonerp) { +if (sel->nonerp_idx <0 ) {for (i =0 ; i < sband->n_bitrates; i++) {struct ieee80211_rate *rate = &sband->bitrates[i]; -if (sel->rate->bitrate < rate->bitrate) +if (sband->bitrates[sel->rate_idx].bitrate < rate->bitrate)break ;if (rate_supported (sta, sband->band, i) && !(rate->flags &IEEE80211_RATE_ERP_G )) - sel->nonerp = rate; + sel->nonerp_idx = i; } }
net/mac80211/ieee80211_i.h +4 -4
@@ -159,11 +159,11 @@ struct ieee80211_tx_data {struct ieee80211_tx_control *control;struct ieee80211_channel *channel; -struct ieee80211_rate *rate; +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. */ -struct ieee80211_rate *last_frag_rate; +s8 last_frag_rate_idx;/* Extra fragments (in addition to the first fragment * in skb) */
@@ -225,9 +225,9 @@ struct ieee80211_tx_stored_packet {struct ieee80211_tx_control control;struct sk_buff *skb;struct sk_buff **extra_frag; -struct ieee80211_rate *last_frag_rate; +s8 last_frag_rate_idx;int num_extra_frag; -unsigned int last_frag_rate_ctrl_probe; +bool last_frag_rate_ctrl_probe; };struct beacon_data {
net/mac80211/rc80211_pid_algo.c +3 -3
@@ -266,7 +266,7 @@ static void rate_control_pid_tx_status(v/* Ignore all frames that were sent with a different rate than the rate * we currently advise mac80211 to use. */ -if (status->control.tx_rate != &sband->bitrates[sta->txrate_idx]) +if (status->control.tx_rate_idx != sta->txrate_idx) goto unlock; spinfo = sta->rate_ctrl_priv;
@@ -330,7 +330,7 @@ static void rate_control_pid_get_rate(vo fc =le16_to_cpu (hdr->frame_control);if ((fc &IEEE80211_FCTL_FTYPE ) !=IEEE80211_FTYPE_DATA ||is_multicast_ether_addr (hdr->addr1) || !sta) { - sel->rate =rate_lowest (local, sband, sta); + sel->rate_idx =rate_lowest_index (local, sband, sta);rcu_read_unlock ();return ; }
@@ -349,7 +349,7 @@ static void rate_control_pid_get_rate(vorcu_read_unlock (); - sel->rate = &sband->bitrates[rateidx]; + sel->rate_idx = rateidx;#ifdef CONFIG_MAC80211_DEBUGFS rate_control_pid_event_tx_rate(
net/mac80211/tx.c +58 -46
262 lines not on this page · raw message
net/mac80211/util.c +8 -2
@@ -266,10 +266,13 @@ __le16 ieee80211_rts_duration(struct ieebool short_preamble;int erp;u16 dur; +struct ieee80211_supported_band *sband; + + sband = local->hw.wiphy->bands[local->hw.conf.channel->band]; short_preamble = sdata->bss_conf.use_short_preamble; - rate = frame_txctl->rts_cts_rate; + rate = &sband->bitrates[frame_txctl->rts_cts_rate_idx]; erp =0 ;if (sdata->flags &IEEE80211_SDATA_OPERATING_GMODE )
@@ -300,10 +303,13 @@ __le16 ieee80211_ctstoself_duration(strubool short_preamble;int erp;u16 dur; +struct ieee80211_supported_band *sband; + + sband = local->hw.wiphy->bands[local->hw.conf.channel->band]; short_preamble = sdata->bss_conf.use_short_preamble; - rate = frame_txctl->rts_cts_rate; + rate = &sband->bitrates[frame_txctl->rts_cts_rate_idx]; erp =0 ;if (sdata->flags &IEEE80211_SDATA_OPERATING_GMODE ) erp = rate->flags &IEEE80211_RATE_ERP_G ;
drivers/net/wireless/adm8211.c +3 -3
@@ -1693,10 +1693,10 @@ static int adm8211_tx(struct ieee80211_hsize_t payload_len, hdrlen;int plcp, dur, len, plcp_signal, short_preamble;struct ieee80211_hdr *hdr; +struct ieee80211_rate *txrate =ieee80211_get_tx_rate (dev, control); - short_preamble = !!(control->tx_rate->flags & -IEEE80211_TXCTL_SHORT_PREAMBLE ); - plcp_signal = control->tx_rate->bitrate; + short_preamble = !!(txrate->flags &IEEE80211_TXCTL_SHORT_PREAMBLE ); + plcp_signal = txrate->bitrate; hdr = (struct ieee80211_hdr *)skb->data; fc =le16_to_cpu (hdr->frame_control) & ~IEEE80211_FCTL_PROTECTED ;
drivers/net/wireless/at76_usb.c +1 -1
@@ -1753,7 +1753,7 @@ static int at76_mac80211_tx(struct ieee8memset (tx_buffer,0 ,sizeof (*tx_buffer)); tx_buffer->padding = padding; tx_buffer->wlength =cpu_to_le16 (skb->len); - tx_buffer->tx_rate = control->tx_rate->hw_value; + tx_buffer->tx_rate =ieee80211_get_tx_rate (hw, control)->hw_value;memset (tx_buffer->reserved,0 ,sizeof (tx_buffer->reserved));memcpy (tx_buffer->packet, skb->data, skb->len);
drivers/net/wireless/ath5k/base.c +5 -3
@@ -1329,7 +1329,8 @@ ath5k_txbuf_setup(struct ath5k_softc *sc ret = ah->ah_setup_tx_desc (ah, ds, pktlen,ieee80211_get_hdrlen_from_skb (skb),AR5K_PKT_TYPE_NORMAL , - (sc->power_level *2 ), ctl->tx_rate->hw_value, + (sc->power_level *2 ), +ieee80211_get_tx_rate (sc->hw, ctl)->hw_value, ctl->retry_limit, keyidx,0 , flags,0 ,0 );if (ret) goto err_unmap;
@@ -2061,7 +2062,8 @@ ath5k_beacon_setup(struct ath5k_softc *s ret = ah->ah_setup_tx_desc (ah, ds, skb->len,ieee80211_get_hdrlen_from_skb (skb),AR5K_PKT_TYPE_BEACON , (sc->power_level *2 ), - ctl->tx_rate->hw_value,1 ,AR5K_TXKEYIX_INVALID , +ieee80211_get_tx_rate (sc->hw, ctl)->hw_value, +1 ,AR5K_TXKEYIX_INVALID , antenna, flags,0 ,0 );if (ret) goto err_unmap;
@@ -2669,7 +2671,7 @@ ath5k_tx(struct ieee80211_hw *hw, structmemmove (skb->data, skb->data+pad, hdrlen); } - sc->led_txrate = ctl->tx_rate->hw_value; + sc->led_txrate =ieee80211_get_tx_rate (hw, ctl)->hw_value;spin_lock_irqsave (&sc->txbuflock, flags);if (list_empty (&sc->txbuf)) {
drivers/net/wireless/b43/main.c +1 -1
@@ -1365,7 +1365,7 @@ static void b43_write_beacon_template(st bcn = (const struct ieee80211_mgmt *)(dev->wl->current_beacon->data); len =min ((size_t ) dev->wl->current_beacon->len,0x200 -sizeof (struct b43_plcp_hdr6 )); - rate = dev->wl->beacon_txctl.tx_rate->hw_value; + rate =ieee80211_get_tx_rate (dev->wl->hw, &dev->wl->beacon_txctl)->hw_value;b43_write_template_common (dev, (const u8 *)bcn, len, ram_offset, shm_size_offset, rate);
drivers/net/wireless/b43/xmit.c +8 -5
@@ -201,13 +201,14 @@ int b43_generate_txhdr(struct b43_wldevu32 mac_ctl =0 ;u16 phy_ctl =0 ;u8 extra_ft =0 ; +struct ieee80211_rate *txrate;memset (txhdr,0 ,sizeof (*txhdr)); -WARN_ON (!txctl->tx_rate); - rate = txctl->tx_rate ? txctl->tx_rate->hw_value :B43_CCK_RATE_1MB ; + txrate =ieee80211_get_tx_rate (dev->wl->hw, txctl); + rate = txrate ? txrate->hw_value :B43_CCK_RATE_1MB ; rate_ofdm =b43_is_ofdm_rate (rate); - fbrate = txctl->alt_retry_rate ? : txctl->tx_rate; + fbrate =ieee80211_get_alt_retry_rate (dev->wl->hw, txctl) ? : txrate; rate_fb = fbrate->hw_value; rate_fb_ofdm =b43_is_ofdm_rate (rate_fb);
@@ -336,9 +337,11 @@ int b43_generate_txhdr(struct b43_wldevint rts_rate, rts_rate_fb;int rts_rate_ofdm, rts_rate_fb_ofdm;struct b43_plcp_hdr6 *plcp; +struct ieee80211_rate *rts_cts_rate; -WARN_ON (!txctl->rts_cts_rate); - rts_rate = txctl->rts_cts_rate ? txctl->rts_cts_rate->hw_value :B43_CCK_RATE_1MB ; + rts_cts_rate =ieee80211_get_rts_cts_rate (dev->wl->hw, txctl); + + rts_rate = rts_cts_rate ? rts_cts_rate->hw_value :B43_CCK_RATE_1MB ; rts_rate_ofdm =b43_is_ofdm_rate (rts_rate); rts_rate_fb =b43_calc_fallback_rate (rts_rate); rts_rate_fb_ofdm =b43_is_ofdm_rate (rts_rate_fb);
drivers/net/wireless/b43legacy/xmit.c +6 -3
@@ -201,15 +201,18 @@ static int generate_txhdr_fw3(struct b43unsigned int plcp_fragment_len;u32 mac_ctl =0 ;u16 phy_ctl =0 ; +struct ieee80211_rate *tx_rate; wlhdr = (const struct ieee80211_hdr *)fragment_data; fctl =le16_to_cpu (wlhdr->frame_control);memset (txhdr,0 ,sizeof (*txhdr)); - rate = txctl->tx_rate->hw_value; + tx_rate =ieee80211_get_tx_rate (dev->wl->hw, txctl); + + rate = tx_rate->hw_value; rate_ofdm =b43legacy_is_ofdm_rate (rate); - rate_fb = txctl->alt_retry_rate ? : txctl->tx_rate; + rate_fb =ieee80211_get_alt_retry_rate (dev->wl->hw, txctl) ? : tx_rate; rate_fb_ofdm =b43legacy_is_ofdm_rate (rate_fb->hw_value); txhdr->mac_frame_ctl = wlhdr->frame_control;
@@ -312,7 +315,7 @@ static int generate_txhdr_fw3(struct b43int rts_rate_ofdm;int rts_rate_fb_ofdm; - rts_rate = txctl->rts_cts_rate->hw_value; + rts_rate =ieee80211_get_rts_cts_rate (dev->wl->hw, txctl)->hw_value; rts_rate_ofdm =b43legacy_is_ofdm_rate (rts_rate); rts_rate_fb =b43legacy_calc_fallback_rate (rts_rate); rts_rate_fb_ofdm =b43legacy_is_ofdm_rate (rts_rate_fb);
drivers/net/wireless/iwlwifi/iwl-3945-rs.c +3 -3
@@ -465,7 +465,7 @@ static void rs_tx_status(void *priv_rate retries = tx_resp->retry_count; - first_index = tx_resp->control.tx_rate->hw_value; + first_index = sband->bitrates[tx_resp->control.tx_rate_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 ;
@@ -670,7 +670,7 @@ static void rs_get_rate(void *priv_rate, is_multicast_ether_addr(hdr->addr1) || !sta || !sta->rate_ctrl_priv) {IWL_DEBUG_RATE ("leave: No STA priv data to update!\n" ); - sel->rate =rate_lowest (local, sband, sta); + sel->rate_idx =rate_lowest_index (local, sband, sta);rcu_read_unlock ();return ; }
@@ -814,7 +814,7 @@ static void rs_get_rate(void *priv_rate,IWL_DEBUG_RATE ("leave: %d\n" , index); - sel->rate = &sband->bitrates[sta->txrate_idx]; + sel->rate_idx = sta->txrate_idx; }static struct rate_control_ops rs_ops = {
drivers/net/wireless/iwlwifi/iwl-3945.c +5 -2
@@ -331,7 +331,9 @@ static void iwl3945_rx_reply_tx(struct i tx_resp->rate, tx_resp->failure_frame); rate_idx =iwl3945_hwrate_to_plcp_idx (tx_resp->rate); - tx_status->control.tx_rate = &priv->ieee_rates[rate_idx]; +if (tx_status->control.band ==IEEE80211_BAND_5GHZ ) + rate_idx -=IWL_FIRST_OFDM_RATE ; + tx_status->control.tx_rate_idx = rate_idx;IWL_DEBUG_TX_REPLY ("Tx queue reclaim %d\n" , index);iwl3945_tx_queue_reclaim (priv, txq_id, index);
@@ -966,7 +968,8 @@ void iwl3945_hw_build_tx_cmd_rate(struct struct ieee80211_hdr *hdr, int sta_id, int tx_id) { unsigned long flags; -u16 rate_index =min (ctrl->tx_rate->hw_value &0xffff ,IWL_RATE_COUNT -1 ); +u16 hw_value =ieee80211_get_tx_rate (priv->hw, ctrl)->hw_value; +u16 rate_index =min (hw_value &0xffff ,IWL_RATE_COUNT -1 );u16 rate_mask;int rate;u8 rts_retry_limit;
drivers/net/wireless/iwlwifi/iwl-4965-rs.c +7 -5
@@ -851,7 +851,7 @@ static void rs_tx_status(void *priv_rateif (priv->band ==IEEE80211_BAND_5GHZ ) rs_index -=IWL_FIRST_OFDM_RATE ; - if ((tx_resp->control.tx_rate == NULL) || + if ((tx_resp->control.tx_rate_idx < 0) || (tbl_type.is_SGI ^ !!(tx_resp->control.flags & IEEE80211_TXCTL_SHORT_GI)) || (tbl_type.is_fat ^
@@ -865,7 +865,7 @@ static void rs_tx_status(void *priv_rate (!!(tx_mcs.rate_n_flags & RATE_MCS_GF_MSK) ^ !!(tx_resp->control.flags & IEEE80211_TXCTL_GREEN_FIELD)) || (hw->wiphy->bands[priv->band]->bitrates[rs_index].bitrate != - tx_resp->control.tx_rate->bitrate)) { + hw->wiphy->bands[tx_resp->control.band]->bitrates[tx_resp->control.tx_rate_idx].bitrate)) {IWL_DEBUG_RATE ("initial rate does not match 0x%x\n" , tx_mcs.rate_n_flags); goto out;
@@ -2181,7 +2181,7 @@ static void rs_get_rate(void *priv_rate, fc =le16_to_cpu (hdr->frame_control);if (!ieee80211_is_data (fc) ||is_multicast_ether_addr (hdr->addr1) || !sta || !sta->rate_ctrl_priv) { - sel->rate =rate_lowest (local, sband, sta); + sel->rate_idx =rate_lowest_index (local, sband, sta); goto out; }
@@ -2211,11 +2211,13 @@ static void rs_get_rate(void *priv_rate, done:if ((i <0 ) || (i >IWL_RATE_COUNT )) { - sel->rate =rate_lowest (local, sband, sta); + sel->rate_idx =rate_lowest_index (local, sband, sta); goto out; } - sel->rate = &priv->ieee_rates[i]; +if (sband->band ==IEEE80211_BAND_5GHZ ) + i -=IWL_FIRST_OFDM_RATE ; + sel->rate_idx = i; out:rcu_read_unlock (); }
drivers/net/wireless/iwlwifi/iwl-4965.c +5 -8
@@ -421,14 +421,10 @@ void iwl4965_hwrate_to_tx_control(struct control->flags |=IEEE80211_TXCTL_DUP_DATA ;if (rate_n_flags &RATE_MCS_SGI_MSK ) control->flags |=IEEE80211_TXCTL_SHORT_GI ; -/* since iwl4965_hwrate_to_plcp_idx is band indifferent, we always use -* IEEE80211_BAND_2GHZ band as it contains all the rates */ rate_index =iwl4965_hwrate_to_plcp_idx (rate_n_flags); -if (rate_index ==-1 ) - control->tx_rate =NULL ; -else - control->tx_rate = - &priv->bands[IEEE80211_BAND_2GHZ ].bitrates[rate_index]; +if (control->band ==IEEE80211_BAND_5GHZ ) + rate_index -=IWL_FIRST_OFDM_RATE ; + control->tx_rate_idx = rate_index; }/*
@@ -2980,7 +2976,8 @@ void iwl4965_hw_build_tx_cmd_rate(structu16 fc =le16_to_cpu (hdr->frame_control);u8 rate_plcp;u16 rate_flags =0 ; -int rate_idx =min (ctrl->tx_rate->hw_value &0xffff ,IWL_RATE_COUNT -1 ); +u16 hw_value =ieee80211_get_tx_rate (priv->hw, ctrl)->hw_value; +int rate_idx =min (hw_value &0xffff ,IWL_RATE_COUNT -1 ); rate_plcp = iwl4965_rates[rate_idx].plcp;
drivers/net/wireless/iwlwifi/iwl3945-base.c +2 -2
@@ -2589,7 +2589,7 @@ static int iwl3945_tx_skb(struct iwl3945 goto drop_unlock; } -if ((ctl->tx_rate->hw_value &0xFF ) ==IWL_INVALID_RATE ) { +if ((ieee80211_get_tx_rate (priv->hw, ctl)->hw_value &0xFF ) ==IWL_INVALID_RATE ) {IWL_ERROR ("ERROR: No TX rate available.\n" ); goto drop_unlock; }
@@ -6700,7 +6700,7 @@ static int iwl3945_mac_tx(struct ieee802 }IWL_DEBUG_TX ("dev->xmit(%d bytes) at rate 0x%02x\n" , skb->len, - ctl->tx_rate->bitrate); +ieee80211_get_tx_rate (hw, ctl)->bitrate);if (iwl3945_tx_skb (priv, skb, ctl))dev_kfree_skb_any (skb);
drivers/net/wireless/iwlwifi/iwl4965-base.c +2 -2
@@ -2154,7 +2154,7 @@ static int iwl4965_tx_skb(struct iwl_pri goto drop_unlock; } -if ((ctl->tx_rate->hw_value &0xFF ) ==IWL_INVALID_RATE ) { +if ((ieee80211_get_tx_rate (priv->hw, ctl)->hw_value &0xFF ) ==IWL_INVALID_RATE ) {IWL_ERROR ("ERROR: No TX rate available.\n" ); goto drop_unlock; }
@@ -6243,7 +6243,7 @@ static int iwl4965_mac_tx(struct ieee802 }IWL_DEBUG_TX ("dev->xmit(%d bytes) at rate 0x%02x\n" , skb->len, - ctl->tx_rate->bitrate); +ieee80211_get_tx_rate (hw, ctl)->bitrate);if (iwl4965_tx_skb (priv, skb, ctl))dev_kfree_skb_any (skb);
drivers/net/wireless/p54/p54common.c +1 -1
@@ -595,7 +595,7 @@ static int p54_tx(struct ieee80211_hw *d txhdr->padding2 =0 ;/* TODO: add support for alternate retry TX rates */ - rate = control->tx_rate->hw_value; + rate =ieee80211_get_tx_rate (dev, control)->hw_value;if (control->flags &IEEE80211_TXCTL_SHORT_PREAMBLE ) rate |=0x10 ;if (control->flags &IEEE80211_TXCTL_USE_RTS_CTS )
drivers/net/wireless/rt2x00/rt2x00dev.c +3 -3
@@ -648,7 +648,7 @@ void rt2x00lib_write_tx_desc(struct rt2x frame_control =le16_to_cpu (hdr->frame_control); seq_ctrl =le16_to_cpu (hdr->seq_ctrl); - tx_rate = control->tx_rate->hw_value; + tx_rate =ieee80211_get_tx_rate (rt2x00dev->hw, control)->hw_value;/* * Check whether this frame is to be acked
@@ -666,8 +666,8 @@ void rt2x00lib_write_tx_desc(struct rt2x__set_bit (ENTRY_TXD_ACK , &txdesc.flags); }else __clear_bit (ENTRY_TXD_ACK , &txdesc.flags); -if (control->rts_cts_rate) - tx_rate = control->rts_cts_rate->hw_value; +if (control->rts_cts_rate_idx >=0 ) + tx_rate =ieee80211_get_rts_cts_rate (rt2x00dev->hw, control)->hw_value; } rate =rt2x00_get_rate (tx_rate);
drivers/net/wireless/rtl8180_dev.c +8 -11
@@ -257,24 +257,21 @@ static int rtl8180_tx(struct ieee80211_h mapping =pci_map_single (priv->pdev, skb->data, skb->len,PCI_DMA_TODEVICE ); -BUG_ON (!control->tx_rate); - tx_flags =RTL8180_TX_DESC_FLAG_OWN |RTL8180_TX_DESC_FLAG_FS |RTL8180_TX_DESC_FLAG_LS | - (control->tx_rate->hw_value <<24 ) | skb->len; + (ieee80211_get_tx_rate (dev, control)->hw_value <<24 ) | + skb->len;if (priv->r8185) tx_flags |=RTL8180_TX_DESC_FLAG_DMA |RTL8180_TX_DESC_FLAG_NO_ENC ;if (control->flags &IEEE80211_TXCTL_USE_RTS_CTS ) { -BUG_ON (!control->rts_cts_rate); tx_flags |=RTL8180_TX_DESC_FLAG_RTS ; - tx_flags |= control->rts_cts_rate->hw_value <<19 ; + tx_flags |=ieee80211_get_rts_cts_rate (dev, control)->hw_value <<19 ; }else if (control->flags &IEEE80211_TXCTL_USE_CTS_PROTECT ) { -BUG_ON (!control->rts_cts_rate); tx_flags |=RTL8180_TX_DESC_FLAG_CTS ; - tx_flags |= control->rts_cts_rate->hw_value <<19 ; + tx_flags |=ieee80211_get_rts_cts_rate (dev, control)->hw_value <<19 ; } *((struct ieee80211_tx_control **) skb->cb) =
@@ -288,9 +285,9 @@ static int rtl8180_tx(struct ieee80211_hunsigned int remainder; plcp_len =DIV_ROUND_UP (16 * (skb->len +4 ), - (control->tx_rate->bitrate *2 ) /10 ); + (ieee80211_get_tx_rate (dev, control)->bitrate *2 ) /10 ); remainder = (16 * (skb->len +4 )) % - ((control->tx_rate->bitrate *2 ) /10 ); + ((ieee80211_get_tx_rate (dev, control)->bitrate *2 ) /10 );if (remainder >0 && remainder <=6 ) plcp_len |=1 <<15 ; }
@@ -303,8 +300,8 @@ static int rtl8180_tx(struct ieee80211_h 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 = control->alt_retry_rate !=NULL ? - control->alt_retry_rate->bitrate <<4 :0 ; + entry->flags2 = control->alt_retry_rate_idx >=0 ? +ieee80211_get_alt_retry_rate (dev, control)->bitrate <<4 :0 ; entry->retry_limit = control->retry_limit; entry->flags =cpu_to_le32 (tx_flags);__skb_queue_tail (&ring->queue, skb);
drivers/net/wireless/rtl8187_dev.c +3 -7
@@ -179,21 +179,17 @@ static int rtl8187_tx(struct ieee80211_h flags = skb->len; flags |=RTL8187_TX_FLAG_NO_ENCRYPT ; -BUG_ON (!control->tx_rate); - - flags |= control->tx_rate->hw_value <<24 ; + flags |=ieee80211_get_tx_rate (dev, control)->hw_value <<24 ;if (ieee80211_get_morefrag ((struct ieee80211_hdr *)skb->data)) flags |=RTL8187_TX_FLAG_MORE_FRAG ;if (control->flags &IEEE80211_TXCTL_USE_RTS_CTS ) { -BUG_ON (!control->rts_cts_rate); flags |=RTL8187_TX_FLAG_RTS ; - flags |= control->rts_cts_rate->hw_value <<19 ; + flags |=ieee80211_get_rts_cts_rate (dev, control)->hw_value <<19 ; rts_dur =ieee80211_rts_duration (dev, priv->vif, skb->len, control); }else if (control->flags &IEEE80211_TXCTL_USE_CTS_PROTECT ) { -BUG_ON (!control->rts_cts_rate); flags |=RTL8187_TX_FLAG_CTS ; - flags |= control->rts_cts_rate->hw_value <<19 ; + flags |=ieee80211_get_rts_cts_rate (dev, control)->hw_value <<19 ; } hdr = (struct rtl8187_tx_hdr *)skb_push (skb,sizeof (*hdr));
drivers/net/wireless/zd1211rw/zd_mac.c +5 -2
@@ -523,14 +523,17 @@ static int fill_ctrlset(struct zd_mac *mstruct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;unsigned int frag_len = skb->len +FCS_LEN ;unsigned int packet_length; +struct ieee80211_rate *txrate;struct zd_ctrlset *cs = (struct zd_ctrlset *)skb_push (skb,sizeof (struct zd_ctrlset ));ZD_ASSERT (frag_len <=0xffff ); - cs->modulation = control->tx_rate->hw_value; + txrate =ieee80211_get_tx_rate (mac->hw, control); + + cs->modulation = txrate->hw_value;if (control->flags &IEEE80211_TXCTL_SHORT_PREAMBLE ) - cs->modulation = control->tx_rate->hw_value_short; + cs->modulation = txrate->hw_value_short; cs->tx_length =cpu_to_le16 (frag_len);
Signature · 4 lines
-- To unsubscribe from this list: send the line "unsubscribe linux-wireless" in the body of a message to [email protected] More majordomo info at http://vger.kernel.org/majordomo-info.html
PATCH 4/4 mac80211: use multi-queue master netdevice
In reply to Johannes BergThis patch updates mac80211 and drivers to be multi-queue aware and use that instead of the internal queue mapping.
---
This is just ground-work. We'll be able to play with Qos much more now.
drivers/net/wireless/ath5k/base.c | 2 - drivers/net/wireless/b43/dma.c | 7 ++- drivers/net/wireless/b43/pio.c | 8 ++-- drivers/net/wireless/b43legacy/dma.c | 2 - drivers/net/wireless/iwlwifi/iwl3945-base.c | 4 +- drivers/net/wireless/iwlwifi/iwl4965-base.c | 4 +- drivers/net/wireless/p54/p54common.c | 10 ++--- drivers/net/wireless/rt2x00/rt2x00mac.c | 12 +++--- drivers/net/wireless/rt2x00/rt2x00pci.c | 2 - drivers/net/wireless/rt2x00/rt2x00queue.h | 13 ------ drivers/net/wireless/rtl8180_dev.c | 4 +- include/net/mac80211.h | 12 ++++-- net/mac80211/Kconfig | 14 ++++++- net/mac80211/Makefile | 2 - net/mac80211/ieee80211_i.h | 7 --- net/mac80211/main.c | 21 ++++++---- net/mac80211/tx.c | 9 ---- net/mac80211/util.c | 54 +++++++++++++++++++--------- net/mac80211/wme.c | 13 ++---- net/mac80211/wme.h | 2 - 20 files changed, 109 insertions(+), 93 deletions(-)
drivers/net/wireless/ath5k/base.c +1 -1
@@ -2677,7 +2677,7 @@ ath5k_tx(struct ieee80211_hw *hw, structif (list_empty (&sc->txbuf)) {ATH5K_ERR (sc,"no further txbuf available, dropping packet\n" );spin_unlock_irqrestore (&sc->txbuflock, flags); -ieee80211_stop_queue (hw, ctl->queue); +ieee80211_stop_queue (hw,skb_get_queue_mapping (skb));return -1 ; } bf = list_first_entry(&sc->txbuf, struct ath5k_buf, list);
drivers/net/wireless/iwlwifi/iwl3945-base.c +2 -2
@@ -2562,7 +2562,7 @@ static int iwl3945_tx_skb(struct iwl3945struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;struct iwl3945_tfd_frame *tfd;u32 *control_flags; -int txq_id = ctl->queue; +int txq_id =skb_get_queue_mapping (skb);struct iwl3945_tx_queue *txq =NULL ;struct iwl3945_queue *q =NULL ;dma_addr_t phys_addr;
@@ -2776,7 +2776,7 @@ static int iwl3945_tx_skb(struct iwl3945spin_unlock_irqrestore (&priv->lock, flags); } -ieee80211_stop_queue (priv->hw, ctl->queue); +ieee80211_stop_queue (priv->hw,skb_get_queue_mapping (skb)); }return 0 ;
drivers/net/wireless/iwlwifi/iwl4965-base.c +2 -2
@@ -2126,7 +2126,7 @@ static int iwl4965_tx_skb(struct iwl_pristruct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;struct iwl4965_tfd_frame *tfd;u32 *control_flags; -int txq_id = ctl->queue; +int txq_id =skb_get_queue_mapping (skb);struct iwl4965_tx_queue *txq =NULL ;struct iwl4965_queue *q =NULL ;dma_addr_t phys_addr;
@@ -2350,7 +2350,7 @@ static int iwl4965_tx_skb(struct iwl_prispin_unlock_irqrestore (&priv->lock, flags); } -ieee80211_stop_queue (priv->hw, ctl->queue); +ieee80211_stop_queue (priv->hw,skb_get_queue_mapping (skb)); }return 0 ;
drivers/net/wireless/p54/p54common.c +5 -5
@@ -417,7 +417,7 @@ static void p54_rx_frame_sent(struct ieememcpy (&status.control, range->control,sizeof (status.control));kfree (range->control); - priv->tx_stats[status.control.queue].len--; + priv->tx_stats[skb_get_queue_mapping (skb)].len--; 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 )
@@ -562,13 +562,13 @@ static int p54_tx(struct ieee80211_hw *dsize_t padding, len;u8 rate; - current_queue = &priv->tx_stats[control->queue]; + current_queue = &priv->tx_stats[skb_get_queue_mapping (skb)];if (unlikely (current_queue->len > current_queue->limit))return NETDEV_TX_BUSY ; current_queue->len++; current_queue->count++;if (current_queue->len == current_queue->limit) -ieee80211_stop_queue (dev, control->queue); +ieee80211_stop_queue (dev,skb_get_queue_mapping (skb)); padding = (unsigned long )(skb->data - (sizeof (*hdr) +sizeof (*txhdr))) &3 ; len = skb->len;
@@ -605,7 +605,7 @@ static int p54_tx(struct ieee80211_hw *dmemset (txhdr->rateset, rate,8 ); txhdr->wep_key_present =0 ; txhdr->wep_key_len =0 ; - txhdr->frame_type =cpu_to_le32 (control->queue +4 ); + txhdr->frame_type =cpu_to_le32 (skb_get_queue_mapping (skb) +4 ); txhdr->magic4 =0 ; txhdr->antenna = (control->antenna_sel_tx ==0 ) ?2 : control->antenna_sel_tx -1 ;
@@ -944,7 +944,7 @@ static int p54_conf_tx(struct ieee80211_ vdcf = (struct p54_tx_control_vdcf *)(((struct p54_control_hdr *) ((void *)priv->cached_vdcf + priv->tx_hdr_len))->data); -if ((params) && !((queue <0 ) || (queue >4 ))) { +if (params && queue < dev->queues) {P54_SET_QUEUE (vdcf->queue[queue], params->aifs, params->cw_min, params->cw_max, params->txop); }else
drivers/net/wireless/rtl8180_dev.c +2 -2
@@ -251,7 +251,7 @@ static int rtl8180_tx(struct ieee80211_hu16 plcp_len =0 ;__le16 rts_duration =0 ; - prio = control->queue; + prio =skb_get_queue_mapping (skb); ring = &priv->tx_ring[prio]; mapping = pci_map_single(priv->pdev, skb->data,
@@ -306,7 +306,7 @@ static int rtl8180_tx(struct ieee80211_h entry->flags =cpu_to_le32 (tx_flags);__skb_queue_tail (&ring->queue, skb);if (ring->entries -skb_queue_len (&ring->queue) <2 ) -ieee80211_stop_queue (dev, control->queue); +ieee80211_stop_queue (dev,skb_get_queue_mapping (skb));spin_unlock_irqrestore (&priv->lock, flags);rtl818x_iowrite8 (priv, &priv->map->TX_DMA_POLLING, (1 << (prio +4 )));
include/net/mac80211.h +9 -3
@@ -282,9 +282,6 @@ struct ieee80211_tx_control {* This could be used when set_retry_limit * is not implemented by the driver */ -u16 queue;/* hardware queue to use for this frame; -* 0 = highest, hw->queues-1 = lowest */ -struct ieee80211_vif *vif;/* Key used for hardware encryption
@@ -1575,6 +1572,15 @@ void ieee80211_wake_queue(struct ieee802void ieee80211_stop_queue (struct ieee80211_hw *hw,int queue);/** +* ieee80211_start_queue - start specific queue +* @hw: pointer as obtained from ieee80211_alloc_hw(). +* @queue: queue number (counted from zero). +* +* Drivers should use this function instead of netif_start_queue. +*/ +void ieee80211_start_queue (struct ieee80211_hw *hw,int queue); + +/** * ieee80211_start_queues - start all queues * @hw: pointer to as obtained from ieee80211_alloc_hw(). *
net/mac80211/Kconfig +13 -1
@@ -7,11 +7,23 @@ config MAC80211 select CRC32 select WIRELESS_EXT select CFG80211 - select NET_SCH_FIFO ---help--- This option enables the hardware independent IEEE 802.11 networking stack. +config MAC80211_QOS + def_bool y + depends on MAC80211 + depends on NET_SCHED + depends on NETDEVICES_MULTIQUEUE + +comment "QoS/HT support disabled" + depends on !MAC80211_QOS +comment "QoS/HT support needs CONFIG_NET_SCHED" + depends on MAC80211 && !NET_SCHED +comment "QoS/HT support needs CONFIG_NETDEVICES_MULTIQUEUE" + depends on MAC80211 && !NETDEVICES_MULTIQUEUE + menu "Rate control algorithm selection" depends on MAC80211 != n
net/mac80211/Makefile +1 -1
@@ -29,7 +29,7 @@ mac80211-y := \ event.o mac80211-$(CONFIG_MAC80211_LEDS) += led.o -mac80211-$(CONFIG_NET_SCHED) += wme.o +mac80211-$(CONFIG_MAC80211_QOS) += wme.o mac80211-$(CONFIG_MAC80211_DEBUGFS) += \ debugfs.o \ debugfs_sta.o \
net/mac80211/ieee80211_i.h +0 -7
@@ -213,7 +213,6 @@ struct ieee80211_rx_data {struct ieee80211_tx_packet_data {u32 flags;int ifindex; -u16 queue;unsigned long jiffies; };
@@ -605,8 +604,6 @@ struct ieee80211_local {struct sta_info *sta_hash[STA_HASH_SIZE ];struct timer_list sta_cleanup; -unsigned long state[IEEE80211_MAX_AMPDU_QUEUES +IEEE80211_MAX_AMPDU_QUEUES ]; -/* number of interfaces with corresponding IFF_ flags */ atomic_t iff_allmultis, iff_promiscs;
@@ -836,10 +833,6 @@ static inline struct ieee80211_hw *localreturn &local->hw; } -enum ieee80211_link_state_t { -IEEE80211_LINK_STATE_XOFF =0 , -}; -struct sta_attribute {struct attribute attr;ssize_t (*show)(const struct sta_info *,char *buf);
net/mac80211/main.c +13 -8
@@ -1313,7 +1313,6 @@ static void ieee80211_remove_tx_extra(st pkt_data->flags |=IEEE80211_TXPD_REQUEUE ;if (control->flags &IEEE80211_TXCTL_EAPOL_FRAME ) pkt_data->flags |=IEEE80211_TXPD_EAPOL_FRAME ; - pkt_data->queue = control->queue; hdrlen =ieee80211_get_hdrlen_from_skb (skb);
@@ -1713,9 +1712,20 @@ int ieee80211_register_hw(struct ieee802if (result <0 )return result; +#ifdef CONFIG_MAC80211_QOS +if (hw->queues >IEEE80211_MAX_QUEUES ) + hw->queues =IEEE80211_MAX_QUEUES ; +if (hw->ampdu_queues >IEEE80211_MAX_AMPDU_QUEUES ) + hw->ampdu_queues =IEEE80211_MAX_AMPDU_QUEUES ; +#else + hw->queues =1 ; + hw->ampdu_queues =0 ; +#endif +/* for now, mdev needs sub_if_data :/ */ - mdev =alloc_netdev (sizeof (struct ieee80211_sub_if_data ), -"wmaster%d" , ether_setup); + mdev =alloc_netdev_mq (sizeof (struct ieee80211_sub_if_data ), +"wmaster%d" , ether_setup, + hw->queues + hw->ampdu_queues);if (!mdev) goto fail_mdev_alloc;
@@ -1807,11 +1817,6 @@ int ieee80211_register_hw(struct ieee802 goto fail_wep; } -if (hw->queues >IEEE80211_MAX_QUEUES ) - hw->queues =IEEE80211_MAX_QUEUES ; -if (hw->ampdu_queues >IEEE80211_MAX_AMPDU_QUEUES ) - hw->ampdu_queues =IEEE80211_MAX_AMPDU_QUEUES ; -ieee80211_install_qdisc (local->mdev);/* add one default STA interface */
net/mac80211/tx.c +1 -8
@@ -210,12 +210,6 @@ static u16 ieee80211_duration(struct ieereturn dur; } -static inline int __ieee80211_queue_stopped (const struct ieee80211_local *local, -int queue) -{ -return test_bit (IEEE80211_LINK_STATE_XOFF , &local->state[queue]); -} -static int inline is_ieee80211_device (struct net_device *dev,struct net_device *master) {
@@ -1066,7 +1060,7 @@ static int ___ieee80211_tx(struct ieee80print_control (control, skb);if (unlikely (netif_queue_stopped (local->mdev) || -__ieee80211_queue_stopped (local, control->queue))) +netif_subqueue_stopped (local->mdev, skb)))return NETDEV_TX_BUSY ; ieee80211_dump_frame(wiphy_name(local->hw.wiphy),
@@ -1354,7 +1348,6 @@ int ieee80211_master_start_xmit(struct s control.flags |=IEEE80211_TXCTL_EAPOL_FRAME ;if (pkt_data->flags &IEEE80211_TXPD_AMPDU ) control.flags |=IEEE80211_TXCTL_AMPDU ; - control.queue = pkt_data->queue;memset (skb->cb,0 ,sizeof (skb->cb)); ret =ieee80211_tx (odev, skb, &control);
net/mac80211/util.c +38 -16
95 lines not on this page · raw message
net/mac80211/wme.c +4 -9
@@ -160,7 +160,7 @@ static int wme_qdiscop_enqueue(struct sku8 tid;if (pkt_data->flags &IEEE80211_TXPD_REQUEUE ) { - queue = pkt_data->queue; + queue =skb_get_queue_mapping (skb);rcu_read_lock (); sta =sta_info_get (local, hdr->addr1); tid = skb->priority &QOS_CONTROL_TAG1D_MASK ;
@@ -221,7 +221,7 @@ static int wme_qdiscop_enqueue(struct sk err =NET_XMIT_DROP ; }else { tid = skb->priority &QOS_CONTROL_TAG1D_MASK ; - pkt_data->queue = (unsigned int ) queue; +skb_set_queue_mapping (skb, queue); qdisc = q->queues[queue]; err = qdisc->enqueue (skb, qdisc);if (err ==NET_XMIT_SUCCESS ) {
@@ -239,13 +239,10 @@ static int wme_qdiscop_enqueue(struct skstatic int wme_qdiscop_requeue (struct sk_buff *skb,struct Qdisc * qd) {struct ieee80211_sched_data *q =qdisc_priv (qd); -struct ieee80211_tx_packet_data *pkt_data = - (struct ieee80211_tx_packet_data *) skb->cb;struct Qdisc *qdisc;int err; -/* We recorded which queue to use earlier. */ - qdisc = q->queues[pkt_data->queue]; + qdisc = q->queues[skb_get_queue_mapping (skb)];if ((err = qdisc->ops->requeue (skb, qdisc)) ==0 ) { qd->q.qlen++;
@@ -269,9 +266,7 @@ static struct sk_buff *wme_qdiscop_deque/* check all the h/w queues in numeric/priority order */ for (queue =0 ; queue <QD_NUM (hw); queue++) {/* see if there is room in this hardware queue */ -if ((test_bit (IEEE80211_LINK_STATE_XOFF , - &local->state[queue])) || - (!test_bit (queue, q->qdisc_pool))) +if (__netif_subqueue_stopped (local->mdev, queue))continue ;/* there is space - try and get a frame */
net/mac80211/wme.h +1 -1
@@ -31,7 +31,7 @@ static inline int WLAN_FC_IS_QOS_DATA(u1return (fc &0x8C ) ==0x88 ; } -#ifdef CONFIG_NET_SCHED +#ifdef CONFIG_MAC80211_QOS void ieee80211_install_qdisc (struct net_device *dev);int ieee80211_qdisc_installed (struct net_device *dev); int ieee80211_ht_agg_queue_add(struct ieee80211_local *local,
drivers/net/wireless/b43/dma.c +4 -3
@@ -1298,7 +1298,8 @@ int b43_dma_tx(struct b43_wldev *dev, hdr->frame_control |=cpu_to_le16 (IEEE80211_FCTL_MOREDATA ); }else {/* Decide by priority where to put this frame. */ - ring =select_ring_by_priority (dev, ctl->queue); + ring =select_ring_by_priority ( + dev,skb_get_queue_mapping (skb)); }spin_lock_irqsave (&ring->lock, flags);
@@ -1316,7 +1317,7 @@ int b43_dma_tx(struct b43_wldev *dev,/* Assign the queue number to the ring (if not already done before) * so TX status handling can use it. The queue to ring mapping is * static, so we don't need to store it per frame. */ - ring->queue_prio = ctl->queue; + ring->queue_prio =skb_get_queue_mapping (skb); err =dma_tx_fragment (ring, skb, ctl);if (unlikely (err == -ENOKEY )) {
@@ -1334,7 +1335,7 @@ int b43_dma_tx(struct b43_wldev *dev,if ((free_slots (ring) <SLOTS_PER_PACKET ) ||should_inject_overflow (ring)) {/* This TX ring is full. */ -ieee80211_stop_queue (dev->wl->hw, ctl->queue); +ieee80211_stop_queue (dev->wl->hw,skb_get_queue_mapping (skb)); ring->stopped =1 ;if (b43_debug (dev,B43_DBG_DMAVERBOSE )) {b43dbg (dev->wl,"Stopped TX ring %d\n" , ring->index);
drivers/net/wireless/b43/pio.c +4 -4
@@ -510,7 +510,7 @@ int b43_pio_tx(struct b43_wldev *dev, hdr->frame_control |=cpu_to_le16 (IEEE80211_FCTL_MOREDATA ); }else {/* Decide by priority where to put this frame. */ - q =select_queue_by_priority (dev, ctl->queue); + q =select_queue_by_priority (dev,skb_get_queue_mapping (skb)); }spin_lock_irqsave (&q->lock, flags);
@@ -533,7 +533,7 @@ int b43_pio_tx(struct b43_wldev *dev,if (total_len > (q->buffer_size - q->buffer_used)) {/* Not enough memory on the queue. */ err = -EBUSY ; -ieee80211_stop_queue (dev->wl->hw, ctl->queue); +ieee80211_stop_queue (dev->wl->hw,skb_get_queue_mapping (skb)); q->stopped =1 ; goto out_unlock; }
@@ -541,7 +541,7 @@ int b43_pio_tx(struct b43_wldev *dev,/* Assign the queue number to the ring (if not already done before) * so TX status handling can use it. The mac80211-queue to b43-queue * mapping is static, so we don't need to store it per frame. */ - q->queue_prio = ctl->queue; + q->queue_prio =skb_get_queue_mapping (skb); err =pio_tx_frame (q, skb, ctl);if (unlikely (err == -ENOKEY )) {
@@ -561,7 +561,7 @@ int b43_pio_tx(struct b43_wldev *dev,if (((q->buffer_size - q->buffer_used) <roundup (2 +2 +6 ,4 )) || (q->free_packet_slots ==0 )) {/* The queue is full. */ -ieee80211_stop_queue (dev->wl->hw, ctl->queue); +ieee80211_stop_queue (dev->wl->hw,skb_get_queue_mapping (skb)); q->stopped =1 ; }
drivers/net/wireless/b43legacy/dma.c +1 -1
@@ -1330,7 +1330,7 @@ int b43legacy_dma_tx(struct b43legacy_wlint err =0 ;unsigned long flags; - ring =priority_to_txring (dev, ctl->queue); + ring =priority_to_txring (dev,skb_get_queue_mapping (skb));spin_lock_irqsave (&ring->lock, flags);B43legacy_WARN_ON (!ring->tx);if (unlikely (free_slots (ring) <SLOTS_PER_PACKET )) {
drivers/net/wireless/rt2x00/rt2x00mac.c +7 -5
@@ -81,7 +81,7 @@ int rt2x00mac_tx(struct ieee80211_hw *hw {struct rt2x00_dev *rt2x00dev = hw->priv;struct ieee80211_hdr *ieee80211hdr = (struct ieee80211_hdr *)skb->data; -enum data_queue_qid qid =mac80211_queue_to_qid (control->queue); +enum data_queue_qid qid =skb_get_queue_mapping (skb);struct data_queue *queue;struct skb_frame_desc *skbdesc;u16 frame_control;
@@ -129,12 +129,14 @@ int rt2x00mac_tx(struct ieee80211_hw *hw IEEE80211_TXCTL_USE_CTS_PROTECT)) && !rt2x00dev->ops->hw->set_rts_threshold) {if (rt2x00queue_available (queue) <=1 ) { -ieee80211_stop_queue (rt2x00dev->hw, control->queue); +ieee80211_stop_queue ( + rt2x00dev->hw,skb_get_queue_mapping (skb));return NETDEV_TX_BUSY ; }if (rt2x00mac_tx_rts_cts (rt2x00dev, queue, skb, control)) { -ieee80211_stop_queue (rt2x00dev->hw, control->queue); +ieee80211_stop_queue ( + rt2x00dev->hw,skb_get_queue_mapping (skb));return NETDEV_TX_BUSY ; } }
@@ -146,12 +148,12 @@ int rt2x00mac_tx(struct ieee80211_hw *hwmemset (skbdesc,0 ,sizeof (*skbdesc));if (rt2x00dev->ops->lib->write_tx_data (rt2x00dev, queue, skb, control)) { -ieee80211_stop_queue (rt2x00dev->hw, control->queue); +ieee80211_stop_queue (rt2x00dev->hw,skb_get_queue_mapping (skb));return NETDEV_TX_BUSY ; }if (rt2x00queue_full (queue)) -ieee80211_stop_queue (rt2x00dev->hw, control->queue); +ieee80211_stop_queue (rt2x00dev->hw,skb_get_queue_mapping (skb));if (rt2x00dev->ops->lib->kick_tx_queue) rt2x00dev->ops->lib->kick_tx_queue (rt2x00dev, qid);
drivers/net/wireless/rt2x00/rt2x00pci.c +1 -1
@@ -178,7 +178,7 @@ void rt2x00pci_txdone(struct rt2x00_dev* is reenabled when the txdone handler has finished. */ if (!rt2x00queue_full (entry->queue)) -ieee80211_wake_queue (rt2x00dev->hw, priv_tx->control.queue); +ieee80211_wake_queue (rt2x00dev->hw, entry->queue->qid); }EXPORT_SYMBOL_GPL (rt2x00pci_txdone);
drivers/net/wireless/rt2x00/rt2x00queue.h +0 -11
@@ -80,19 +80,6 @@ enum data_queue_qid { };/** -* mac80211_queue_to_qid - Convert mac80211 queue to rt2x00 qid -* @queue: mac80211 queue. -*/ -static inline enum data_queue_qid mac80211_queue_to_qid (unsigned int queue) -{ -/* Regular TX queues are mapped directly */ -if (queue <4 ) -return queue; -WARN_ON (1 ); -return QID_OTHER ; -}
A message that is not in the archive (sent off-list or not yet received): [email protected]
Re: [RFC/RFT 4/4] mac80211: use multi-queue master netdevice
Hi,
Overall the rt2x00 changes are good, but I have a few suggestions :)
Quoted 12 lines
drivers/net/wireless/rt2x00/rt2x00mac.c +1
-1@@ -81,7 +81,7 @@ int rt2x00mac_tx(struct ieee80211_hw *hw {struct rt2x00_dev *rt2x00dev = hw->priv;struct ieee80211_hdr *ieee80211hdr = (struct ieee80211_hdr *)skb->data; -enum data_queue_qid qid =mac80211_queue_to_qid (control->queue); +enum data_queue_qid qid =skb_get_queue_mapping (skb);struct data_queue *queue;struct skb_frame_desc *skbdesc;u16 frame_control;
drivers/net/wireless/rt2x00/rt2x00mac.c int rt2x00mac_tx(struct ieee80211_hw *hw · line 133
Quoted 6 lines
drivers/net/wireless/rt2x00/rt2x00mac.c +2
-1@@ -129,12 +129,14 @@ int rt2x00mac_tx(struct ieee80211_hw *hw IEEE80211_TXCTL_USE_CTS_PROTECT)) && !rt2x00dev->ops->hw->set_rts_threshold) {if (rt2x00queue_available (queue) <=1 ) { -ieee80211_stop_queue (rt2x00dev->hw, control->queue); +ieee80211_stop_queue ( + rt2x00dev->hw,skb_get_queue_mapping (skb));
ieee80211_stop_queue(rt2x00dev->hw, qid);
The result of skb_get_queue_mapping(skb) was already stored in the 'qid' variable at the start of the function. And since this is a 1-1 mapping from skb queue to rt2x00 queue, it is safe to use 'qid' directly in all instances.
drivers/net/wireless/rt2x00/rt2x00mac.c int rt2x00mac_tx(struct ieee80211_hw *hw · line 139
Quoted 7 lines
drivers/net/wireless/rt2x00/rt2x00mac.c +2
-1return NETDEV_TX_BUSY ; }if (rt2x00mac_tx_rts_cts (rt2x00dev, queue, skb, control)) { -ieee80211_stop_queue (rt2x00dev->hw, control->queue); +ieee80211_stop_queue ( + rt2x00dev->hw,skb_get_queue_mapping (skb));
ieee80211_stop_queue(rt2x00dev->hw, qid);
drivers/net/wireless/rt2x00/rt2x00mac.c int rt2x00mac_tx(struct ieee80211_hw *hw · line 151
Quoted 9 lines
drivers/net/wireless/rt2x00/rt2x00mac.c +1
-1return NETDEV_TX_BUSY ; } }@@ -146,12 +148,12 @@ int rt2x00mac_tx(struct ieee80211_hw *hwmemset (skbdesc,0 ,sizeof (*skbdesc));if (rt2x00dev->ops->lib->write_tx_data (rt2x00dev, queue, skb, control)) { -ieee80211_stop_queue (rt2x00dev->hw, control->queue); +ieee80211_stop_queue (rt2x00dev->hw,skb_get_queue_mapping (skb));
ieee80211_stop_queue(rt2x00dev->hw, qid);
drivers/net/wireless/rt2x00/rt2x00mac.c int rt2x00mac_tx(struct ieee80211_hw *hw · line 156
Quoted 6 lines
drivers/net/wireless/rt2x00/rt2x00mac.c +1
-1return NETDEV_TX_BUSY ; }if (rt2x00queue_full (queue)) -ieee80211_stop_queue (rt2x00dev->hw, control->queue); +ieee80211_stop_queue (rt2x00dev->hw,skb_get_queue_mapping (skb));
ieee80211_stop_queue(rt2x00dev->hw, qid);
drivers/net/wireless/rt2x00/rt2x00mac.c int rt2x00mac_tx(struct ieee80211_hw *hw · line 159
Quoted 2 lines
drivers/net/wireless/rt2x00/rt2x00mac.c +0
-0if (rt2x00dev->ops->lib->kick_tx_queue) rt2x00dev->ops->lib->kick_tx_queue (rt2x00dev, qid);
Thanks,
Ivo
A message that is not in the archive (sent off-list or not yet received): 200804301637.35170.IvDoorn-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org
Re: [RFC/RFT 4/4] mac80211: use multi-queue master netdevice
Hi Ivo,
Quoted 8 lines
Overall the rt2x00 changes are good, but I have a few suggestions :)
Quoted 5 lines
drivers/net/wireless/rt2x00/rt2x00mac.c +1
-1struct rt2x00_dev *rt2x00dev = hw->priv;struct ieee80211_hdr *ieee80211hdr = (struct ieee80211_hdr *)skb->data; -enum data_queue_qid qid =mac80211_queue_to_qid (control->queue); +enum data_queue_qid qid =skb_get_queue_mapping (skb);struct data_queue *queue;
Quoted 9 lines
drivers/net/wireless/rt2x00/rt2x00mac.c int rt2x00mac_tx(struct ieee80211_hw *hw · line 133
Quoted 4 lines
drivers/net/wireless/rt2x00/rt2x00mac.c +2
-1if (rt2x00queue_available (queue) <=1 ) { -ieee80211_stop_queue (rt2x00dev->hw, control->queue); +ieee80211_stop_queue ( + rt2x00dev->hw,skb_get_queue_mapping (skb));
ieee80211_stop_queue(rt2x00dev->hw, qid);
The result ofskb_get_queue_mapping(skb)was already stored in the 'qid' variable at the start of the function. And since this is a 1-1 mapping from skb queue to rt2x00 queue, it is safe to use 'qid' directly in all instances.
Heh, good point, changed that. Will probably generate the same code since get_queue_mapping is a static inline, but hey, much nicer to read that way :)
johannes
A message that is not in the archive (sent off-list or not yet received): 1209566743.18659.30.camel-YfaajirXv214zXjbi5bjpg@public.gmane.org
Re: [RFC/RFT 4/4] mac80211: use multi-queue master netdevice
Turns out there was something missing (last hunk of this updated version) from the rt2x00 part of the patch that I accidentally didn't quilt edit, here's an updated version if anybody wants to test on rt2x00 hw.
johannes
Subject: mac80211: use multi-queue master netdevice
This patch updates mac80211 and drivers to be multi-queue aware and use that instead of the internal queue mapping.
---
This is just ground-work. We'll be able to play with Qos much more now.
drivers/net/wireless/ath5k/base.c | 2 - drivers/net/wireless/b43/dma.c | 7 ++- drivers/net/wireless/b43/pio.c | 8 ++-- drivers/net/wireless/b43legacy/dma.c | 2 - drivers/net/wireless/iwlwifi/iwl3945-base.c | 4 +- drivers/net/wireless/iwlwifi/iwl4965-base.c | 4 +- drivers/net/wireless/p54/p54common.c | 10 ++--- drivers/net/wireless/rt2x00/rt2x00mac.c | 10 ++--- drivers/net/wireless/rt2x00/rt2x00pci.c | 2 - drivers/net/wireless/rt2x00/rt2x00queue.h | 13 ------ drivers/net/wireless/rt2x00/rt2x00usb.c | 2 - drivers/net/wireless/rtl8180_dev.c | 4 +- include/net/mac80211.h | 12 ++++-- net/mac80211/Kconfig | 14 ++++++- net/mac80211/Makefile | 2 - net/mac80211/ieee80211_i.h | 7 --- net/mac80211/main.c | 21 ++++++---- net/mac80211/tx.c | 9 ---- net/mac80211/util.c | 54 +++++++++++++++++++--------- net/mac80211/wme.c | 13 ++---- net/mac80211/wme.h | 2 - 21 files changed, 108 insertions(+), 94 deletions(-)
drivers/net/wireless/ath5k/base.c +1 -1
@@ -2677,7 +2677,7 @@ ath5k_tx(struct ieee80211_hw *hw, structif (list_empty (&sc->txbuf)) {ATH5K_ERR (sc,"no further txbuf available, dropping packet\n" );spin_unlock_irqrestore (&sc->txbuflock, flags); -ieee80211_stop_queue (hw, ctl->queue); +ieee80211_stop_queue (hw,skb_get_queue_mapping (skb));return -1 ; } bf = list_first_entry(&sc->txbuf, struct ath5k_buf, list);
drivers/net/wireless/iwlwifi/iwl3945-base.c +2 -2
@@ -2562,7 +2562,7 @@ static int iwl3945_tx_skb(struct iwl3945struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;struct iwl3945_tfd_frame *tfd;u32 *control_flags; -int txq_id = ctl->queue; +int txq_id =skb_get_queue_mapping (skb);struct iwl3945_tx_queue *txq =NULL ;struct iwl3945_queue *q =NULL ;dma_addr_t phys_addr;
@@ -2776,7 +2776,7 @@ static int iwl3945_tx_skb(struct iwl3945spin_unlock_irqrestore (&priv->lock, flags); } -ieee80211_stop_queue (priv->hw, ctl->queue); +ieee80211_stop_queue (priv->hw,skb_get_queue_mapping (skb)); }return 0 ;
drivers/net/wireless/iwlwifi/iwl4965-base.c +2 -2
@@ -2126,7 +2126,7 @@ static int iwl4965_tx_skb(struct iwl_pristruct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;struct iwl4965_tfd_frame *tfd;u32 *control_flags; -int txq_id = ctl->queue; +int txq_id =skb_get_queue_mapping (skb);struct iwl4965_tx_queue *txq =NULL ;struct iwl4965_queue *q =NULL ;dma_addr_t phys_addr;
@@ -2350,7 +2350,7 @@ static int iwl4965_tx_skb(struct iwl_prispin_unlock_irqrestore (&priv->lock, flags); } -ieee80211_stop_queue (priv->hw, ctl->queue); +ieee80211_stop_queue (priv->hw,skb_get_queue_mapping (skb)); }return 0 ;
drivers/net/wireless/p54/p54common.c +5 -5
@@ -417,7 +417,7 @@ static void p54_rx_frame_sent(struct ieememcpy (&status.control, range->control,sizeof (status.control));kfree (range->control); - priv->tx_stats[status.control.queue].len--; + priv->tx_stats[skb_get_queue_mapping (skb)].len--; 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 )
@@ -562,13 +562,13 @@ static int p54_tx(struct ieee80211_hw *dsize_t padding, len;u8 rate; - current_queue = &priv->tx_stats[control->queue]; + current_queue = &priv->tx_stats[skb_get_queue_mapping (skb)];if (unlikely (current_queue->len > current_queue->limit))return NETDEV_TX_BUSY ; current_queue->len++; current_queue->count++;if (current_queue->len == current_queue->limit) -ieee80211_stop_queue (dev, control->queue); +ieee80211_stop_queue (dev,skb_get_queue_mapping (skb)); padding = (unsigned long )(skb->data - (sizeof (*hdr) +sizeof (*txhdr))) &3 ; len = skb->len;
@@ -605,7 +605,7 @@ static int p54_tx(struct ieee80211_hw *dmemset (txhdr->rateset, rate,8 ); txhdr->wep_key_present =0 ; txhdr->wep_key_len =0 ; - txhdr->frame_type =cpu_to_le32 (control->queue +4 ); + txhdr->frame_type =cpu_to_le32 (skb_get_queue_mapping (skb) +4 ); txhdr->magic4 =0 ; txhdr->antenna = (control->antenna_sel_tx ==0 ) ?2 : control->antenna_sel_tx -1 ;
@@ -944,7 +944,7 @@ static int p54_conf_tx(struct ieee80211_ vdcf = (struct p54_tx_control_vdcf *)(((struct p54_control_hdr *) ((void *)priv->cached_vdcf + priv->tx_hdr_len))->data); -if ((params) && !((queue <0 ) || (queue >4 ))) { +if (params && queue < dev->queues) {P54_SET_QUEUE (vdcf->queue[queue], params->aifs, params->cw_min, params->cw_max, params->txop); }else
drivers/net/wireless/rtl8180_dev.c +2 -2
@@ -251,7 +251,7 @@ static int rtl8180_tx(struct ieee80211_hu16 plcp_len =0 ;__le16 rts_duration =0 ; - prio = control->queue; + prio =skb_get_queue_mapping (skb); ring = &priv->tx_ring[prio]; mapping = pci_map_single(priv->pdev, skb->data,
@@ -306,7 +306,7 @@ static int rtl8180_tx(struct ieee80211_h entry->flags =cpu_to_le32 (tx_flags);__skb_queue_tail (&ring->queue, skb);if (ring->entries -skb_queue_len (&ring->queue) <2 ) -ieee80211_stop_queue (dev, control->queue); +ieee80211_stop_queue (dev,skb_get_queue_mapping (skb));spin_unlock_irqrestore (&priv->lock, flags);rtl818x_iowrite8 (priv, &priv->map->TX_DMA_POLLING, (1 << (prio +4 )));
include/net/mac80211.h +9 -3
@@ -282,9 +282,6 @@ struct ieee80211_tx_control {* This could be used when set_retry_limit * is not implemented by the driver */ -u16 queue;/* hardware queue to use for this frame; -* 0 = highest, hw->queues-1 = lowest */ -struct ieee80211_vif *vif;/* Key used for hardware encryption
@@ -1575,6 +1572,15 @@ void ieee80211_wake_queue(struct ieee802void ieee80211_stop_queue (struct ieee80211_hw *hw,int queue);/** +* ieee80211_start_queue - start specific queue +* @hw: pointer as obtained from ieee80211_alloc_hw(). +* @queue: queue number (counted from zero). +* +* Drivers should use this function instead of netif_start_queue. +*/ +void ieee80211_start_queue (struct ieee80211_hw *hw,int queue); + +/** * ieee80211_start_queues - start all queues * @hw: pointer to as obtained from ieee80211_alloc_hw(). *
net/mac80211/Kconfig +13 -1
@@ -7,11 +7,23 @@ config MAC80211 select CRC32 select WIRELESS_EXT select CFG80211 - select NET_SCH_FIFO ---help--- This option enables the hardware independent IEEE 802.11 networking stack. +config MAC80211_QOS + def_bool y + depends on MAC80211 + depends on NET_SCHED + depends on NETDEVICES_MULTIQUEUE + +comment "QoS/HT support disabled" + depends on !MAC80211_QOS +comment "QoS/HT support needs CONFIG_NET_SCHED" + depends on MAC80211 && !NET_SCHED +comment "QoS/HT support needs CONFIG_NETDEVICES_MULTIQUEUE" + depends on MAC80211 && !NETDEVICES_MULTIQUEUE + menu "Rate control algorithm selection" depends on MAC80211 != n
net/mac80211/Makefile +1 -1
@@ -29,7 +29,7 @@ mac80211-y := \ event.o mac80211-$(CONFIG_MAC80211_LEDS) += led.o -mac80211-$(CONFIG_NET_SCHED) += wme.o +mac80211-$(CONFIG_MAC80211_QOS) += wme.o mac80211-$(CONFIG_MAC80211_DEBUGFS) += \ debugfs.o \ debugfs_sta.o \
net/mac80211/ieee80211_i.h +0 -7
@@ -213,7 +213,6 @@ struct ieee80211_rx_data {struct ieee80211_tx_packet_data {u32 flags;int ifindex; -u16 queue;unsigned long jiffies; };
@@ -605,8 +604,6 @@ struct ieee80211_local {struct sta_info *sta_hash[STA_HASH_SIZE ];struct timer_list sta_cleanup; -unsigned long state[IEEE80211_MAX_AMPDU_QUEUES +IEEE80211_MAX_AMPDU_QUEUES ]; -/* number of interfaces with corresponding IFF_ flags */ atomic_t iff_allmultis, iff_promiscs;
@@ -836,10 +833,6 @@ static inline struct ieee80211_hw *localreturn &local->hw; } -enum ieee80211_link_state_t { -IEEE80211_LINK_STATE_XOFF =0 , -}; -struct sta_attribute {struct attribute attr;ssize_t (*show)(const struct sta_info *,char *buf);
net/mac80211/main.c +13 -8
@@ -1313,7 +1313,6 @@ static void ieee80211_remove_tx_extra(st pkt_data->flags |=IEEE80211_TXPD_REQUEUE ;if (control->flags &IEEE80211_TXCTL_EAPOL_FRAME ) pkt_data->flags |=IEEE80211_TXPD_EAPOL_FRAME ; - pkt_data->queue = control->queue; hdrlen =ieee80211_get_hdrlen_from_skb (skb);
@@ -1713,9 +1712,20 @@ int ieee80211_register_hw(struct ieee802if (result <0 )return result; +#ifdef CONFIG_MAC80211_QOS +if (hw->queues >IEEE80211_MAX_QUEUES ) + hw->queues =IEEE80211_MAX_QUEUES ; +if (hw->ampdu_queues >IEEE80211_MAX_AMPDU_QUEUES ) + hw->ampdu_queues =IEEE80211_MAX_AMPDU_QUEUES ; +#else + hw->queues =1 ; + hw->ampdu_queues =0 ; +#endif +/* for now, mdev needs sub_if_data :/ */ - mdev =alloc_netdev (sizeof (struct ieee80211_sub_if_data ), -"wmaster%d" , ether_setup); + mdev =alloc_netdev_mq (sizeof (struct ieee80211_sub_if_data ), +"wmaster%d" , ether_setup, + hw->queues + hw->ampdu_queues);if (!mdev) goto fail_mdev_alloc;
@@ -1807,11 +1817,6 @@ int ieee80211_register_hw(struct ieee802 goto fail_wep; } -if (hw->queues >IEEE80211_MAX_QUEUES ) - hw->queues =IEEE80211_MAX_QUEUES ; -if (hw->ampdu_queues >IEEE80211_MAX_AMPDU_QUEUES ) - hw->ampdu_queues =IEEE80211_MAX_AMPDU_QUEUES ; -ieee80211_install_qdisc (local->mdev);/* add one default STA interface */
net/mac80211/tx.c +1 -8
@@ -210,12 +210,6 @@ static u16 ieee80211_duration(struct ieereturn dur; } -static inline int __ieee80211_queue_stopped (const struct ieee80211_local *local, -int queue) -{ -return test_bit (IEEE80211_LINK_STATE_XOFF , &local->state[queue]); -} -static int inline is_ieee80211_device (struct net_device *dev,struct net_device *master) {
@@ -1066,7 +1060,7 @@ static int ___ieee80211_tx(struct ieee80print_control (control, skb);if (unlikely (netif_queue_stopped (local->mdev) || -__ieee80211_queue_stopped (local, control->queue))) +netif_subqueue_stopped (local->mdev, skb)))return NETDEV_TX_BUSY ; ieee80211_dump_frame(wiphy_name(local->hw.wiphy),
@@ -1354,7 +1348,6 @@ int ieee80211_master_start_xmit(struct s control.flags |=IEEE80211_TXCTL_EAPOL_FRAME ;if (pkt_data->flags &IEEE80211_TXPD_AMPDU ) control.flags |=IEEE80211_TXCTL_AMPDU ; - control.queue = pkt_data->queue;memset (skb->cb,0 ,sizeof (skb->cb)); ret =ieee80211_tx (odev, skb, &control);
net/mac80211/util.c +38 -16
95 lines not on this page · raw message
net/mac80211/wme.c +4 -9
@@ -160,7 +160,7 @@ static int wme_qdiscop_enqueue(struct sku8 tid;if (pkt_data->flags &IEEE80211_TXPD_REQUEUE ) { - queue = pkt_data->queue; + queue =skb_get_queue_mapping (skb);rcu_read_lock (); sta =sta_info_get (local, hdr->addr1); tid = skb->priority &QOS_CONTROL_TAG1D_MASK ;
@@ -221,7 +221,7 @@ static int wme_qdiscop_enqueue(struct sk err =NET_XMIT_DROP ; }else { tid = skb->priority &QOS_CONTROL_TAG1D_MASK ; - pkt_data->queue = (unsigned int ) queue; +skb_set_queue_mapping (skb, queue); qdisc = q->queues[queue]; err = qdisc->enqueue (skb, qdisc);if (err ==NET_XMIT_SUCCESS ) {
@@ -239,13 +239,10 @@ static int wme_qdiscop_enqueue(struct skstatic int wme_qdiscop_requeue (struct sk_buff *skb,struct Qdisc * qd) {struct ieee80211_sched_data *q =qdisc_priv (qd); -struct ieee80211_tx_packet_data *pkt_data = - (struct ieee80211_tx_packet_data *) skb->cb;struct Qdisc *qdisc;int err; -/* We recorded which queue to use earlier. */ - qdisc = q->queues[pkt_data->queue]; + qdisc = q->queues[skb_get_queue_mapping (skb)];if ((err = qdisc->ops->requeue (skb, qdisc)) ==0 ) { qd->q.qlen++;
@@ -269,9 +266,7 @@ static struct sk_buff *wme_qdiscop_deque/* check all the h/w queues in numeric/priority order */ for (queue =0 ; queue <QD_NUM (hw); queue++) {/* see if there is room in this hardware queue */ -if ((test_bit (IEEE80211_LINK_STATE_XOFF , - &local->state[queue])) || - (!test_bit (queue, q->qdisc_pool))) +if (__netif_subqueue_stopped (local->mdev, queue))continue ;/* there is space - try and get a frame */
net/mac80211/wme.h +1 -1
@@ -31,7 +31,7 @@ static inline int WLAN_FC_IS_QOS_DATA(u1return (fc &0x8C ) ==0x88 ; } -#ifdef CONFIG_NET_SCHED +#ifdef CONFIG_MAC80211_QOS void ieee80211_install_qdisc (struct net_device *dev);int ieee80211_qdisc_installed (struct net_device *dev); int ieee80211_ht_agg_queue_add(struct ieee80211_local *local,
drivers/net/wireless/b43/dma.c +4 -3
@@ -1298,7 +1298,8 @@ int b43_dma_tx(struct b43_wldev *dev, hdr->frame_control |=cpu_to_le16 (IEEE80211_FCTL_MOREDATA ); }else {/* Decide by priority where to put this frame. */ - ring =select_ring_by_priority (dev, ctl->queue); + ring =select_ring_by_priority ( + dev,skb_get_queue_mapping (skb)); }spin_lock_irqsave (&ring->lock, flags);
@@ -1316,7 +1317,7 @@ int b43_dma_tx(struct b43_wldev *dev,/* Assign the queue number to the ring (if not already done before) * so TX status handling can use it. The queue to ring mapping is * static, so we don't need to store it per frame. */ - ring->queue_prio = ctl->queue; + ring->queue_prio =skb_get_queue_mapping (skb); err =dma_tx_fragment (ring, skb, ctl);if (unlikely (err == -ENOKEY )) {
@@ -1334,7 +1335,7 @@ int b43_dma_tx(struct b43_wldev *dev,if ((free_slots (ring) <SLOTS_PER_PACKET ) ||should_inject_overflow (ring)) {/* This TX ring is full. */ -ieee80211_stop_queue (dev->wl->hw, ctl->queue); +ieee80211_stop_queue (dev->wl->hw,skb_get_queue_mapping (skb)); ring->stopped =1 ;if (b43_debug (dev,B43_DBG_DMAVERBOSE )) {b43dbg (dev->wl,"Stopped TX ring %d\n" , ring->index);
drivers/net/wireless/b43/pio.c +4 -4
@@ -510,7 +510,7 @@ int b43_pio_tx(struct b43_wldev *dev, hdr->frame_control |=cpu_to_le16 (IEEE80211_FCTL_MOREDATA ); }else {/* Decide by priority where to put this frame. */ - q =select_queue_by_priority (dev, ctl->queue); + q =select_queue_by_priority (dev,skb_get_queue_mapping (skb)); }spin_lock_irqsave (&q->lock, flags);
@@ -533,7 +533,7 @@ int b43_pio_tx(struct b43_wldev *dev,if (total_len > (q->buffer_size - q->buffer_used)) {/* Not enough memory on the queue. */ err = -EBUSY ; -ieee80211_stop_queue (dev->wl->hw, ctl->queue); +ieee80211_stop_queue (dev->wl->hw,skb_get_queue_mapping (skb)); q->stopped =1 ; goto out_unlock; }
@@ -541,7 +541,7 @@ int b43_pio_tx(struct b43_wldev *dev,/* Assign the queue number to the ring (if not already done before) * so TX status handling can use it. The mac80211-queue to b43-queue * mapping is static, so we don't need to store it per frame. */ - q->queue_prio = ctl->queue; + q->queue_prio =skb_get_queue_mapping (skb); err =pio_tx_frame (q, skb, ctl);if (unlikely (err == -ENOKEY )) {
@@ -561,7 +561,7 @@ int b43_pio_tx(struct b43_wldev *dev,if (((q->buffer_size - q->buffer_used) <roundup (2 +2 +6 ,4 )) || (q->free_packet_slots ==0 )) {/* The queue is full. */ -ieee80211_stop_queue (dev->wl->hw, ctl->queue); +ieee80211_stop_queue (dev->wl->hw,skb_get_queue_mapping (skb)); q->stopped =1 ; }
drivers/net/wireless/b43legacy/dma.c +1 -1
@@ -1330,7 +1330,7 @@ int b43legacy_dma_tx(struct b43legacy_wlint err =0 ;unsigned long flags; - ring =priority_to_txring (dev, ctl->queue); + ring =priority_to_txring (dev,skb_get_queue_mapping (skb));spin_lock_irqsave (&ring->lock, flags);B43legacy_WARN_ON (!ring->tx);if (unlikely (free_slots (ring) <SLOTS_PER_PACKET )) {
drivers/net/wireless/rt2x00/rt2x00mac.c +5 -5
@@ -81,7 +81,7 @@ int rt2x00mac_tx(struct ieee80211_hw *hw {struct rt2x00_dev *rt2x00dev = hw->priv;struct ieee80211_hdr *ieee80211hdr = (struct ieee80211_hdr *)skb->data; -enum data_queue_qid qid =mac80211_queue_to_qid (control->queue); +enum data_queue_qid qid =skb_get_queue_mapping (skb);struct data_queue *queue;struct skb_frame_desc *skbdesc;u16 frame_control;
@@ -129,12 +129,12 @@ int rt2x00mac_tx(struct ieee80211_hw *hw IEEE80211_TXCTL_USE_CTS_PROTECT)) && !rt2x00dev->ops->hw->set_rts_threshold) {if (rt2x00queue_available (queue) <=1 ) { -ieee80211_stop_queue (rt2x00dev->hw, control->queue); +ieee80211_stop_queue (rt2x00dev->hw, qid);return NETDEV_TX_BUSY ; }if (rt2x00mac_tx_rts_cts (rt2x00dev, queue, skb, control)) { -ieee80211_stop_queue (rt2x00dev->hw, control->queue); +ieee80211_stop_queue (rt2x00dev->hw, qid);return NETDEV_TX_BUSY ; } }
@@ -146,12 +146,12 @@ int rt2x00mac_tx(struct ieee80211_hw *hwmemset (skbdesc,0 ,sizeof (*skbdesc));if (rt2x00dev->ops->lib->write_tx_data (rt2x00dev, queue, skb, control)) { -ieee80211_stop_queue (rt2x00dev->hw, control->queue); +ieee80211_stop_queue (rt2x00dev->hw, qid);return NETDEV_TX_BUSY ; }if (rt2x00queue_full (queue)) -ieee80211_stop_queue (rt2x00dev->hw, control->queue); +ieee80211_stop_queue (rt2x00dev->hw, qid);if (rt2x00dev->ops->lib->kick_tx_queue) rt2x00dev->ops->lib->kick_tx_queue (rt2x00dev, qid);
drivers/net/wireless/rt2x00/rt2x00pci.c +1 -1
@@ -178,7 +178,7 @@ void rt2x00pci_txdone(struct rt2x00_dev* is reenabled when the txdone handler has finished. */ if (!rt2x00queue_full (entry->queue)) -ieee80211_wake_queue (rt2x00dev->hw, priv_tx->control.queue); +ieee80211_wake_queue (rt2x00dev->hw, entry->queue->qid); }EXPORT_SYMBOL_GPL (rt2x00pci_txdone);
drivers/net/wireless/rt2x00/rt2x00queue.h +0 -11
@@ -80,19 +80,6 @@ enum data_queue_qid { };/** -* mac80211_queue_to_qid - Convert mac80211 queue to rt2x00 qid -* @queue: mac80211 queue. -*/ -static inline enum data_queue_qid mac80211_queue_to_qid (unsigned int queue) -{ -/* Regular TX queues are mapped directly */ -if (queue <4 ) -return queue; -WARN_ON (1 ); -return QID_OTHER ; -}
A message that is not in the archive (sent off-list or not yet received): 1209567609.18659.33.camel-YfaajirXv214zXjbi5bjpg@public.gmane.org
Re: [RFC/RFT 4/4] mac80211: use multi-queue master netdevice
Hi,
Don't want to spoil the fun, but the following part doesn't compile when CONFIG_MAC80211_QOS is not set.
In the following occurences struct ieee80211_local *local needs to be defined.
net/mac80211/util.c void ieee80211_stop_queue(struct ieee802 · line 371
Quoted 13 lines
void
ieee80211_start_queues(struct ieee80211_hw *hw){net/mac80211/util.c +4
-5-struct ieee80211_local *local =hw_to_local (hw); +#ifdef CONFIG_MAC80211_QOS int i; -for (i =0 ; i < local->hw.queues; i++) -clear_bit (IEEE80211_LINK_STATE_XOFF , &local->state[i]); -if (!ieee80211_qdisc_installed (local->mdev)) -netif_start_queue (local->mdev); +for (i =0 ; i < hw->queues; i++) +ieee80211_start_queue (hw, i); +#else
struct ieee80211_local *local = hw_to_local(hw);
net/mac80211/util.c void ieee80211_stop_queue(struct ieee802 · line 384
Quoted 13 lines
net/mac80211/util.c +4
-0+netif_start_queue (local->mdev); +#endif }EXPORT_SYMBOL (ieee80211_start_queues);void ieee80211_stop_queues (struct ieee80211_hw *hw) { +#ifdef CONFIG_MAC80211_QOS int i;for (i =0 ; i < hw->queues; i++)ieee80211_stop_queue (hw, i); +#else
struct ieee80211_local *local = hw_to_local(hw);
net/mac80211/util.c void ieee80211_stop_queue(struct ieee802 · line 397
Quoted 13 lines
net/mac80211/util.c +4
-0+netif_stop_queue (local->mdev); +#endif }EXPORT_SYMBOL (ieee80211_stop_queues);void ieee80211_wake_queues (struct ieee80211_hw *hw) { +#ifdef CONFIG_MAC80211_QOS int i;for (i =0 ; i < hw->queues; i++)ieee80211_wake_queue (hw, i); +#else
struct ieee80211_local *local = hw_to_local(hw);
net/mac80211/util.c void ieee80211_stop_queue(struct ieee802 · line 401
Quoted 4 lines
net/mac80211/util.c +2
-0+netif_wake_queue (local->mdev); +#endif }EXPORT_SYMBOL (ieee80211_wake_queues);
Ivo
Johannes Berg
maintainerRe: [RFC/RFT 4/4] mac80211: use multi-queue master netdevice
Quoted 4 lines · Ivo van Doorn
Hi,
Don't want to spoil the fun, but the following part doesn't compile when
CONFIG_MAC80211_QOSis not set.
Oh! I hadn't tried that yet, thanks. I had tried not configuring it and tested the Kconfig for it, but evidently not compiling.
johannes
Re: [RFC/RFT 4/4] mac80211: use multi-queue master netdevice
In reply to a message not in the archiveQuoted 4 lines · Johannes Berg
Turns out there was something missing (last hunk of this updated version) from the rt2x00 part of the patch that I accidentally didn't quilt edit, here's an updated version if anybody wants to test on rt2x00 hw.
I've tested the following patch series:
mac80211: clean up get_tx_stats callback
mac80211: remove queue info from ieee80211_tx_status
mac80211: QoS related cleanups
mac80211: use rate index in TX control
GSO: generalize for mac80211
mac80211: use GSO for fragmentation
mac80211: use multi-queue master netdevice
My rt61 card (4 TX queues) seems to work correctly, it uses queue 3 as default queue, and a few packets seem to go over queue 1.
Ivo
Quoted 646 lines
johannes
Subject: mac80211: use multi-queue master netdevice
This patch updates mac80211 and drivers to be multi-queue aware and use that instead of the internal queue mapping.
Signed-off-by Johannes Berg <[email protected]>---
This is just ground-work. We'll be able to play with Qos much more now.drivers/net/wireless/ath5k/base.c | 2 - drivers/net/wireless/b43/dma.c | 7 ++- drivers/net/wireless/b43/pio.c | 8 ++-- drivers/net/wireless/b43legacy/dma.c | 2 - drivers/net/wireless/iwlwifi/iwl3945-base.c | 4 +- drivers/net/wireless/iwlwifi/iwl4965-base.c | 4 +- drivers/net/wireless/p54/p54common.c | 10 ++--- drivers/net/wireless/rt2x00/rt2x00mac.c | 10 ++--- drivers/net/wireless/rt2x00/rt2x00pci.c | 2 - drivers/net/wireless/rt2x00/rt2x00queue.h | 13 ------ drivers/net/wireless/rt2x00/rt2x00usb.c | 2 - drivers/net/wireless/rtl8180_dev.c | 4 +- include/net/mac80211.h | 12 ++++-- net/mac80211/Kconfig | 14 ++++++- net/mac80211/Makefile | 2 - net/mac80211/ieee80211_i.h | 7 --- net/mac80211/main.c | 21 ++++++---- net/mac80211/tx.c | 9 ---- net/mac80211/util.c | 54 +++++++++++++++++++--------- net/mac80211/wme.c | 13 ++---- net/mac80211/wme.h | 2 - 21 files changed, 108 insertions(+), 94 deletions(-)drivers/net/wireless/ath5k/base.c +1
-1@@ -2677,7 +2677,7 @@ ath5k_tx(struct ieee80211_hw *hw, structif (list_empty (&sc->txbuf)) {ATH5K_ERR (sc,"no further txbuf available, dropping packet\n" );spin_unlock_irqrestore (&sc->txbuflock, flags); -ieee80211_stop_queue (hw, ctl->queue); +ieee80211_stop_queue (hw,skb_get_queue_mapping (skb));return -1 ; } bf = list_first_entry(&sc->txbuf, struct ath5k_buf, list);drivers/net/wireless/iwlwifi/iwl3945-base.c +2
-2@@ -2562,7 +2562,7 @@ static int iwl3945_tx_skb(struct iwl3945struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;struct iwl3945_tfd_frame *tfd;u32 *control_flags; -int txq_id = ctl->queue; +int txq_id =skb_get_queue_mapping (skb);struct iwl3945_tx_queue *txq =NULL ;struct iwl3945_queue *q =NULL ;dma_addr_t phys_addr;@@ -2776,7 +2776,7 @@ static int iwl3945_tx_skb(struct iwl3945spin_unlock_irqrestore (&priv->lock, flags); } -ieee80211_stop_queue (priv->hw, ctl->queue); +ieee80211_stop_queue (priv->hw,skb_get_queue_mapping (skb)); }return 0 ;drivers/net/wireless/iwlwifi/iwl4965-base.c +2
-2@@ -2126,7 +2126,7 @@ static int iwl4965_tx_skb(struct iwl_pristruct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;struct iwl4965_tfd_frame *tfd;u32 *control_flags; -int txq_id = ctl->queue; +int txq_id =skb_get_queue_mapping (skb);struct iwl4965_tx_queue *txq =NULL ;struct iwl4965_queue *q =NULL ;dma_addr_t phys_addr;@@ -2350,7 +2350,7 @@ static int iwl4965_tx_skb(struct iwl_prispin_unlock_irqrestore (&priv->lock, flags); } -ieee80211_stop_queue (priv->hw, ctl->queue); +ieee80211_stop_queue (priv->hw,skb_get_queue_mapping (skb)); }return 0 ;drivers/net/wireless/p54/p54common.c +5
-5@@ -417,7 +417,7 @@ static void p54_rx_frame_sent(struct ieememcpy (&status.control, range->control,sizeof (status.control));kfree (range->control); - priv->tx_stats[status.control.queue].len--; + priv->tx_stats[skb_get_queue_mapping (skb)].len--; 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 )@@ -562,13 +562,13 @@ static int p54_tx(struct ieee80211_hw *dsize_t padding, len;u8 rate; - current_queue = &priv->tx_stats[control->queue]; + current_queue = &priv->tx_stats[skb_get_queue_mapping (skb)];if (unlikely (current_queue->len > current_queue->limit))return NETDEV_TX_BUSY ; current_queue->len++; current_queue->count++;if (current_queue->len == current_queue->limit) -ieee80211_stop_queue (dev, control->queue); +ieee80211_stop_queue (dev,skb_get_queue_mapping (skb)); padding = (unsigned long )(skb->data - (sizeof (*hdr) +sizeof (*txhdr))) &3 ; len = skb->len;@@ -605,7 +605,7 @@ static int p54_tx(struct ieee80211_hw *dmemset (txhdr->rateset, rate,8 ); txhdr->wep_key_present =0 ; txhdr->wep_key_len =0 ; - txhdr->frame_type =cpu_to_le32 (control->queue +4 ); + txhdr->frame_type =cpu_to_le32 (skb_get_queue_mapping (skb) +4 ); txhdr->magic4 =0 ; txhdr->antenna = (control->antenna_sel_tx ==0 ) ?2 : control->antenna_sel_tx -1 ;@@ -944,7 +944,7 @@ static int p54_conf_tx(struct ieee80211_ vdcf = (struct p54_tx_control_vdcf *)(((struct p54_control_hdr *) ((void *)priv->cached_vdcf + priv->tx_hdr_len))->data); -if ((params) && !((queue <0 ) || (queue >4 ))) { +if (params && queue < dev->queues) {P54_SET_QUEUE (vdcf->queue[queue], params->aifs, params->cw_min, params->cw_max, params->txop); }else drivers/net/wireless/rtl8180_dev.c +2
-2@@ -251,7 +251,7 @@ static int rtl8180_tx(struct ieee80211_hu16 plcp_len =0 ;__le16 rts_duration =0 ; - prio = control->queue; + prio =skb_get_queue_mapping (skb); ring = &priv->tx_ring[prio]; mapping = pci_map_single(priv->pdev, skb->data,@@ -306,7 +306,7 @@ static int rtl8180_tx(struct ieee80211_h entry->flags =cpu_to_le32 (tx_flags);__skb_queue_tail (&ring->queue, skb);if (ring->entries -skb_queue_len (&ring->queue) <2 ) -ieee80211_stop_queue (dev, control->queue); +ieee80211_stop_queue (dev,skb_get_queue_mapping (skb));spin_unlock_irqrestore (&priv->lock, flags);rtl818x_iowrite8 (priv, &priv->map->TX_DMA_POLLING, (1 << (prio +4 )));include/net/mac80211.h +9
-3@@ -282,9 +282,6 @@ struct ieee80211_tx_control {* This could be used when set_retry_limit * is not implemented by the driver */ -u16 queue;/* hardware queue to use for this frame; -* 0 = highest, hw->queues-1 = lowest */ -struct ieee80211_vif *vif;/* Key used for hardware encryption @@ -1575,6 +1572,15 @@ void ieee80211_wake_queue(struct ieee802void ieee80211_stop_queue (struct ieee80211_hw *hw,int queue);/** +* ieee80211_start_queue - start specific queue +* @hw: pointer as obtained from ieee80211_alloc_hw(). +* @queue: queue number (counted from zero). +* +* Drivers should use this function instead of netif_start_queue. +*/ +void ieee80211_start_queue (struct ieee80211_hw *hw,int queue); + +/** * ieee80211_start_queues - start all queues * @hw: pointer to as obtained from ieee80211_alloc_hw(). * net/mac80211/Kconfig +13
-1@@ -7,11 +7,23 @@ config MAC80211 select CRC32 select WIRELESS_EXT select CFG80211 - select NET_SCH_FIFO ---help--- This option enables the hardware independent IEEE 802.11 networking stack. +config MAC80211_QOS + def_bool y + depends on MAC80211 + depends on NET_SCHED + depends on NETDEVICES_MULTIQUEUE + +comment "QoS/HT support disabled" + depends on !MAC80211_QOS +comment "QoS/HT support needs CONFIG_NET_SCHED" + depends on MAC80211 && !NET_SCHED +comment "QoS/HT support needs CONFIG_NETDEVICES_MULTIQUEUE" + depends on MAC80211 && !NETDEVICES_MULTIQUEUE + menu "Rate control algorithm selection" depends on MAC80211 != nnet/mac80211/Makefile +1
-1@@ -29,7 +29,7 @@ mac80211-y := \ event.o mac80211-$(CONFIG_MAC80211_LEDS) += led.o -mac80211-$(CONFIG_NET_SCHED) += wme.o +mac80211-$(CONFIG_MAC80211_QOS) += wme.o mac80211-$(CONFIG_MAC80211_DEBUGFS) += \ debugfs.o \ debugfs_sta.o \net/mac80211/ieee80211_i.h +0
-7@@ -213,7 +213,6 @@ struct ieee80211_rx_data {struct ieee80211_tx_packet_data {u32 flags;int ifindex; -u16 queue;unsigned long jiffies; };@@ -605,8 +604,6 @@ struct ieee80211_local {struct sta_info *sta_hash[STA_HASH_SIZE ];struct timer_list sta_cleanup; -unsigned long state[IEEE80211_MAX_AMPDU_QUEUES +IEEE80211_MAX_AMPDU_QUEUES ]; -/* number of interfaces with corresponding IFF_ flags */ atomic_t iff_allmultis, iff_promiscs;@@ -836,10 +833,6 @@ static inline struct ieee80211_hw *localreturn &local->hw; } -enum ieee80211_link_state_t { -IEEE80211_LINK_STATE_XOFF =0 , -}; -struct sta_attribute {struct attribute attr;ssize_t (*show)(const struct sta_info *,char *buf);net/mac80211/main.c +13
-8@@ -1313,7 +1313,6 @@ static void ieee80211_remove_tx_extra(st pkt_data->flags |=IEEE80211_TXPD_REQUEUE ;if (control->flags &IEEE80211_TXCTL_EAPOL_FRAME ) pkt_data->flags |=IEEE80211_TXPD_EAPOL_FRAME ; - pkt_data->queue = control->queue; hdrlen =ieee80211_get_hdrlen_from_skb (skb);@@ -1713,9 +1712,20 @@ int ieee80211_register_hw(struct ieee802if (result <0 )return result; +#ifdef CONFIG_MAC80211_QOS +if (hw->queues >IEEE80211_MAX_QUEUES ) + hw->queues =IEEE80211_MAX_QUEUES ; +if (hw->ampdu_queues >IEEE80211_MAX_AMPDU_QUEUES ) + hw->ampdu_queues =IEEE80211_MAX_AMPDU_QUEUES ; +#else + hw->queues =1 ; + hw->ampdu_queues =0 ; +#endif +/* for now, mdev needs sub_if_data :/ */ - mdev =alloc_netdev (sizeof (struct ieee80211_sub_if_data ), -"wmaster%d" , ether_setup); + mdev =alloc_netdev_mq (sizeof (struct ieee80211_sub_if_data ), +"wmaster%d" , ether_setup, + hw->queues + hw->ampdu_queues);if (!mdev) goto fail_mdev_alloc;@@ -1807,11 +1817,6 @@ int ieee80211_register_hw(struct ieee802 goto fail_wep; } -if (hw->queues >IEEE80211_MAX_QUEUES ) - hw->queues =IEEE80211_MAX_QUEUES ; -if (hw->ampdu_queues >IEEE80211_MAX_AMPDU_QUEUES ) - hw->ampdu_queues =IEEE80211_MAX_AMPDU_QUEUES ; -ieee80211_install_qdisc (local->mdev);/* add one default STA interface */ net/mac80211/tx.c +1
-8@@ -210,12 +210,6 @@ static u16 ieee80211_duration(struct ieereturn dur; } -static inline int __ieee80211_queue_stopped (const struct ieee80211_local *local, -int queue) -{ -return test_bit (IEEE80211_LINK_STATE_XOFF , &local->state[queue]); -} -static int inline is_ieee80211_device (struct net_device *dev,struct net_device *master) {@@ -1066,7 +1060,7 @@ static int ___ieee80211_tx(struct ieee80print_control (control, skb);if (unlikely (netif_queue_stopped (local->mdev) || -__ieee80211_queue_stopped (local, control->queue))) +netif_subqueue_stopped (local->mdev, skb)))return NETDEV_TX_BUSY ; ieee80211_dump_frame(wiphy_name(local->hw.wiphy),@@ -1354,7 +1348,6 @@ int ieee80211_master_start_xmit(struct s control.flags |=IEEE80211_TXCTL_EAPOL_FRAME ;if (pkt_data->flags &IEEE80211_TXPD_AMPDU ) control.flags |=IEEE80211_TXCTL_AMPDU ; - control.queue = pkt_data->queue;memset (skb->cb,0 ,sizeof (skb->cb)); ret =ieee80211_tx (odev, skb, &control);net/mac80211/util.c +38
-16@@ -323,18 +323,28 @@ __le16 ieee80211_ctstoself_duration(stru }EXPORT_SYMBOL (ieee80211_ctstoself_duration); +void ieee80211_start_queue (struct ieee80211_hw *hw,int queue) +{ +struct ieee80211_local *local =hw_to_local (hw); +#ifdef CONFIG_MAC80211_QOS +netif_start_subqueue (local->mdev, queue); +#else +WARN_ON (queue !=0 ); +netif_start_queue (local->mdev); +#endif +} +EXPORT_SYMBOL (ieee80211_start_queue); +void ieee80211_wake_queue (struct ieee80211_hw *hw,int queue) {struct ieee80211_local *local =hw_to_local (hw); -if (test_and_clear_bit (IEEE80211_LINK_STATE_XOFF , - &local->state[queue])) { -if (!ieee80211_qdisc_installed (local->mdev)) { -if (queue ==0 ) -netif_wake_queue (local->mdev); - }else -__netif_schedule (local->mdev); - } +#ifdef CONFIG_MAC80211_QOS +netif_wake_subqueue (local->mdev, queue); +#else +WARN_ON (queue !=0 ); +netif_wake_queue (local->mdev); +#endif }EXPORT_SYMBOL (ieee80211_wake_queue);@@ -342,39 +352,51 @@ void ieee80211_stop_queue(struct ieee802 {struct ieee80211_local *local =hw_to_local (hw); -if (!ieee80211_qdisc_installed (local->mdev) && queue ==0 ) -netif_stop_queue (local->mdev); -set_bit (IEEE80211_LINK_STATE_XOFF , &local->state[queue]); +#ifdef CONFIG_MAC80211_QOS +netif_stop_subqueue (local->mdev, queue); +#else +WARN_ON (queue !=0 ); +netif_stop_queue (local->mdev); +#endif }EXPORT_SYMBOL (ieee80211_stop_queue);void ieee80211_start_queues (struct ieee80211_hw *hw) { -struct ieee80211_local *local =hw_to_local (hw); +#ifdef CONFIG_MAC80211_QOS int i; -for (i =0 ; i < local->hw.queues; i++) -clear_bit (IEEE80211_LINK_STATE_XOFF , &local->state[i]); -if (!ieee80211_qdisc_installed (local->mdev)) -netif_start_queue (local->mdev); +for (i =0 ; i < hw->queues; i++) +ieee80211_start_queue (hw, i); +#else +netif_start_queue (local->mdev); +#endif }EXPORT_SYMBOL (ieee80211_start_queues);void ieee80211_stop_queues (struct ieee80211_hw *hw) { +#ifdef CONFIG_MAC80211_QOS int i;for (i =0 ; i < hw->queues; i++)ieee80211_stop_queue (hw, i); +#else +netif_stop_queue (local->mdev); +#endif }EXPORT_SYMBOL (ieee80211_stop_queues);void ieee80211_wake_queues (struct ieee80211_hw *hw) { +#ifdef CONFIG_MAC80211_QOS int i;for (i =0 ; i < hw->queues; i++)ieee80211_wake_queue (hw, i); +#else +netif_wake_queue (local->mdev); +#endif }EXPORT_SYMBOL (ieee80211_wake_queues);net/mac80211/wme.c +4
-9@@ -160,7 +160,7 @@ static int wme_qdiscop_enqueue(struct sku8 tid;if (pkt_data->flags &IEEE80211_TXPD_REQUEUE ) { - queue = pkt_data->queue; + queue =skb_get_queue_mapping (skb);rcu_read_lock (); sta =sta_info_get (local, hdr->addr1); tid = skb->priority &QOS_CONTROL_TAG1D_MASK ;@@ -221,7 +221,7 @@ static int wme_qdiscop_enqueue(struct sk err =NET_XMIT_DROP ; }else { tid = skb->priority &QOS_CONTROL_TAG1D_MASK ; - pkt_data->queue = (unsigned int ) queue; +skb_set_queue_mapping (skb, queue); qdisc = q->queues[queue]; err = qdisc->enqueue (skb, qdisc);if (err ==NET_XMIT_SUCCESS ) {@@ -239,13 +239,10 @@ static int wme_qdiscop_enqueue(struct skstatic int wme_qdiscop_requeue (struct sk_buff *skb,struct Qdisc * qd) {struct ieee80211_sched_data *q =qdisc_priv (qd); -struct ieee80211_tx_packet_data *pkt_data = - (struct ieee80211_tx_packet_data *) skb->cb;struct Qdisc *qdisc;int err; -/* We recorded which queue to use earlier. */ - qdisc = q->queues[pkt_data->queue]; + qdisc = q->queues[skb_get_queue_mapping (skb)];if ((err = qdisc->ops->requeue (skb, qdisc)) ==0 ) { qd->q.qlen++;@@ -269,9 +266,7 @@ static struct sk_buff *wme_qdiscop_deque/* check all the h/w queues in numeric/priority order */ for (queue =0 ; queue <QD_NUM (hw); queue++) {/* see if there is room in this hardware queue */ -if ((test_bit (IEEE80211_LINK_STATE_XOFF , - &local->state[queue])) || - (!test_bit (queue, q->qdisc_pool))) +if (__netif_subqueue_stopped (local->mdev, queue))continue ;/* there is space - try and get a frame */ net/mac80211/wme.h +1
-1@@ -31,7 +31,7 @@ static inline int WLAN_FC_IS_QOS_DATA(u1return (fc &0x8C ) ==0x88 ; } -#ifdef CONFIG_NET_SCHED +#ifdef CONFIG_MAC80211_QOS void ieee80211_install_qdisc (struct net_device *dev);int ieee80211_qdisc_installed (struct net_device *dev); int ieee80211_ht_agg_queue_add(struct ieee80211_local *local,drivers/net/wireless/b43/dma.c +4
-3@@ -1298,7 +1298,8 @@ int b43_dma_tx(struct b43_wldev *dev, hdr->frame_control |=cpu_to_le16 (IEEE80211_FCTL_MOREDATA ); }else {/* Decide by priority where to put this frame. */ - ring =select_ring_by_priority (dev, ctl->queue); + ring =select_ring_by_priority ( + dev,skb_get_queue_mapping (skb)); }spin_lock_irqsave (&ring->lock, flags);@@ -1316,7 +1317,7 @@ int b43_dma_tx(struct b43_wldev *dev,/* Assign the queue number to the ring (if not already done before) * so TX status handling can use it. The queue to ring mapping is * static, so we don't need to store it per frame. */ - ring->queue_prio = ctl->queue; + ring->queue_prio =skb_get_queue_mapping (skb); err =dma_tx_fragment (ring, skb, ctl);if (unlikely (err == -ENOKEY )) {@@ -1334,7 +1335,7 @@ int b43_dma_tx(struct b43_wldev *dev,if ((free_slots (ring) <SLOTS_PER_PACKET ) ||should_inject_overflow (ring)) {/* This TX ring is full. */ -ieee80211_stop_queue (dev->wl->hw, ctl->queue); +ieee80211_stop_queue (dev->wl->hw,skb_get_queue_mapping (skb)); ring->stopped =1 ;if (b43_debug (dev,B43_DBG_DMAVERBOSE )) {b43dbg (dev->wl,"Stopped TX ring %d\n" , ring->index);drivers/net/wireless/b43/pio.c +4
-4@@ -510,7 +510,7 @@ int b43_pio_tx(struct b43_wldev *dev, hdr->frame_control |=cpu_to_le16 (IEEE80211_FCTL_MOREDATA ); }else {/* Decide by priority where to put this frame. */ - q =select_queue_by_priority (dev, ctl->queue); + q =select_queue_by_priority (dev,skb_get_queue_mapping (skb)); }spin_lock_irqsave (&q->lock, flags);@@ -533,7 +533,7 @@ int b43_pio_tx(struct b43_wldev *dev,if (total_len > (q->buffer_size - q->buffer_used)) {/* Not enough memory on the queue. */ err = -EBUSY ; -ieee80211_stop_queue (dev->wl->hw, ctl->queue); +ieee80211_stop_queue (dev->wl->hw,skb_get_queue_mapping (skb)); q->stopped =1 ; goto out_unlock; }@@ -541,7 +541,7 @@ int b43_pio_tx(struct b43_wldev *dev,/* Assign the queue number to the ring (if not already done before) * so TX status handling can use it. The mac80211-queue to b43-queue * mapping is static, so we don't need to store it per frame. */ - q->queue_prio = ctl->queue; + q->queue_prio =skb_get_queue_mapping (skb); err =pio_tx_frame (q, skb, ctl);if (unlikely (err == -ENOKEY )) {@@ -561,7 +561,7 @@ int b43_pio_tx(struct b43_wldev *dev,if (((q->buffer_size - q->buffer_used) <roundup (2 +2 +6 ,4 )) || (q->free_packet_slots ==0 )) {/* The queue is full. */ -ieee80211_stop_queue (dev->wl->hw, ctl->queue); +ieee80211_stop_queue (dev->wl->hw,skb_get_queue_mapping (skb)); q->stopped =1 ; }drivers/net/wireless/b43legacy/dma.c +1
-1@@ -1330,7 +1330,7 @@ int b43legacy_dma_tx(struct b43legacy_wlint err =0 ;unsigned long flags; - ring =priority_to_txring (dev, ctl->queue); + ring =priority_to_txring (dev,skb_get_queue_mapping (skb));spin_lock_irqsave (&ring->lock, flags);B43legacy_WARN_ON (!ring->tx);if (unlikely (free_slots (ring) <SLOTS_PER_PACKET )) {drivers/net/wireless/rt2x00/rt2x00mac.c +5
-5@@ -81,7 +81,7 @@ int rt2x00mac_tx(struct ieee80211_hw *hw {struct rt2x00_dev *rt2x00dev = hw->priv;struct ieee80211_hdr *ieee80211hdr = (struct ieee80211_hdr *)skb->data; -enum data_queue_qid qid =mac80211_queue_to_qid (control->queue); +enum data_queue_qid qid =skb_get_queue_mapping (skb);struct data_queue *queue;struct skb_frame_desc *skbdesc;u16 frame_control;@@ -129,12 +129,12 @@ int rt2x00mac_tx(struct ieee80211_hw *hw IEEE80211_TXCTL_USE_CTS_PROTECT)) && !rt2x00dev->ops->hw->set_rts_threshold) {if (rt2x00queue_available (queue) <=1 ) { -ieee80211_stop_queue (rt2x00dev->hw, control->queue); +ieee80211_stop_queue (rt2x00dev->hw, qid);return NETDEV_TX_BUSY ; }if (rt2x00mac_tx_rts_cts (rt2x00dev, queue, skb, control)) { -ieee80211_stop_queue (rt2x00dev->hw, control->queue); +ieee80211_stop_queue (rt2x00dev->hw, qid);return NETDEV_TX_BUSY ; } }@@ -146,12 +146,12 @@ int rt2x00mac_tx(struct ieee80211_hw *hwmemset (skbdesc,0 ,sizeof (*skbdesc));if (rt2x00dev->ops->lib->write_tx_data (rt2x00dev, queue, skb, control)) { -ieee80211_stop_queue (rt2x00dev->hw, control->queue); +ieee80211_stop_queue (rt2x00dev->hw, qid);return NETDEV_TX_BUSY ; }if (rt2x00queue_full (queue)) -ieee80211_stop_queue (rt2x00dev->hw, control->queue); +ieee80211_stop_queue (rt2x00dev->hw, qid);if (rt2x00dev->ops->lib->kick_tx_queue) rt2x00dev->ops->lib->kick_tx_queue (rt2x00dev, qid);drivers/net/wireless/rt2x00/rt2x00pci.c +1
-1@@ -178,7 +178,7 @@ void rt2x00pci_txdone(struct rt2x00_dev* is reenabled when the txdone handler has finished. */ if (!rt2x00queue_full (entry->queue)) -ieee80211_wake_queue (rt2x00dev->hw, priv_tx->control.queue); +ieee80211_wake_queue (rt2x00dev->hw, entry->queue->qid); }EXPORT_SYMBOL_GPL (rt2x00pci_txdone);drivers/net/wireless/rt2x00/rt2x00queue.h +0
-13@@ -80,19 +80,6 @@ enum data_queue_qid { };/** -* mac80211_queue_to_qid - Convert mac80211 queue to rt2x00 qid -* @queue: mac80211 queue. -*/ -static inline enum data_queue_qid mac80211_queue_to_qid (unsigned int queue) -{ -/* Regular TX queues are mapped directly */ -if (queue <4 ) -return queue; -WARN_ON (1 ); -return QID_OTHER ; -} - -/** * enum skb_frame_desc_flags: Flags for &struct skb_frame_desc * * @FRAME_DESC_DRIVER_GENERATED: Frame was generated inside driver drivers/net/wireless/rt2x00/rt2x00usb.c +1
-1@@ -166,7 +166,7 @@ static void rt2x00usb_interrupt_txdone(s* is reenabled when the txdone handler has finished. */ if (!rt2x00queue_full (entry->queue)) -ieee80211_wake_queue (rt2x00dev->hw, priv_tx->control.queue); +ieee80211_wake_queue (rt2x00dev->hw, entry->queue->qid); } int rt2x00usb_write_tx_data(struct rt2x00_dev *rt2x00dev,
A message that is not in the archive (sent off-list or not yet received): 200805011021.04435.IvDoorn-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org
Re: [RFC/RFT 4/4] mac80211: use multi-queue master netdevice
Quoted 11 lines
I've tested the following patch series:
mac80211: clean up
get_tx_statscallback
mac80211: remove queue info fromieee80211_tx_status
mac80211: QoS related cleanups
mac80211: use rate index in TX control
GSO: generalize for mac80211
mac80211: use GSO for fragmentation
mac80211: use multi-queue master netdevice
Quoted 3 lines
My rt61 card (4 TX queues) seems to work correctly, it uses queue 3 as default queue, and a few packets seem to go over queue 1.
Nice, thanks for testing!
johannes
RE: [RFC/RFT 4/4] mac80211: use multi-queue master netdevice
In reply to a message not in the archiveQuoted 10 lines
---
everything.orig/net/mac80211/util.c2008-04-30
14:02:31.000000000 +0200
+++everything/net/mac80211/util.c2008-04-30
14:20:06.000000000 +0200net/mac80211/util.c +2
-0@@ -323,18 +323,28 @@ __le16 ieee80211_ctstoself_duration(stru }EXPORT_SYMBOL (ieee80211_ctstoself_duration); +void ieee80211_start_queue (struct ieee80211_hw *hw,int queue) +{
net/mac80211/util.c __le16 ieee80211_ctstoself_duration(stru · line 337
Quoted 10 lines
net/mac80211/util.c +10
-0+struct ieee80211_local *local =hw_to_local (hw); +#ifdef CONFIG_MAC80211_QOS +netif_start_subqueue (local->mdev, queue); +#else +WARN_ON (queue !=0 ); +netif_start_queue (local->mdev); +#endif +} +EXPORT_SYMBOL (ieee80211_start_queue); +
I would suggest that you enable the netdev feature flag for NETIF_F_MULTI_QUEUE on devices when you create them. That way you can have things like ieee80211_start_queue() key on that instead of a compile-time option, in case wireless devices come along that won't support multiple queues, if that's possible. So something like this:
+void ieee80211_start_queue(struct ieee80211_hw *hw, int queue) +{
+ struct ieee80211_local *local = hw_to_local(hw);
+ if (netif_is_multiqueue(local->mdev) {
+ netif_start_subqueue(local->mdev, queue);
+ } else {
+ WARN_ON(queue != 0);
+ netif_start_queue(local->mdev);
+ }
+}
+EXPORT_SYMBOL(ieee80211_start_queue);
+
If you think this is a decent idea, I'd suggest that any function that has a compile-time check for multiqueue being changed to use the runtime check. Then in your device setup, where you call netdev_alloc_mq(), there you set the flag NETIF_F_MULTI_QUEUE based on the device features.
Other than that, this patch looks great. Exciting to see this starting to take flight.
Cheers,
-PJ Waskiewicz
A message that is not in the archive (sent off-list or not yet received): D5C1322C3E673F459512FB59E0DDC32904FE144F-O6kdQIuPh0Q64kNsxIetb7fspsVTdybXVpNB7YpNyf8@public.gmane.org
RE: [RFC/RFT 4/4] mac80211: use multi-queue master netdevice
Quoted 11 lines
Quoted 11 lines
net/mac80211/util.c +10
-0+void ieee80211_start_queue (struct ieee80211_hw *hw,int queue) +{ +struct ieee80211_local *local =hw_to_local (hw); +#ifdef CONFIG_MAC80211_QOS +netif_start_subqueue (local->mdev, queue); +#else +WARN_ON (queue !=0 ); +netif_start_queue (local->mdev); +#endif +}
Quoted 8 lines
net/mac80211/util.c __le16 ieee80211_ctstoself_duration(stru · line 337
Quoted 2 lines
net/mac80211/util.c +2
-0+EXPORT_SYMBOL (ieee80211_start_queue); +I would suggest that you enable the netdev feature flag for
NETIF_F_MULTI_QUEUEon devices when you create them. That way you can have things likeieee80211_start_queue()key on that instead of a compile-time option, in case wireless devices come along that won't support multiple queues, if that's possible.
Ah. I thought that then I'd just create a device with alloc_mq with a single queue.
Quoted 4 lines
If you think this is a decent idea, I'd suggest that any function that has a compile-time check for multiqueue being changed to use the runtime check. Then in your device setup, where you call
netdev_alloc_mq(), there you set the flagNETIF_F_MULTI_QUEUEbased on the device features.
Hah, indeed, I don't currently set it at all. Yes, I guess I should do it that way.
Quoted 2 lines
Other than that, this patch looks great. Exciting to see this starting to take flight.
:)
johannes
Johannes Berg
maintainerPATCH 2/4 GSO: generalize for mac80211
In reply to Johannes BergThis patch adds a new function dev_skb_segment() that generalises the existing dev_gso_segment() by allowing to give a segmentation function. mac80211 will use that function using the segmentation function skb_segment().
This patch also changes dev_gso_skb_destructor() to be safe when the skb no longer has any segments, this will happen when mac80211 has internally passed off all the fragments to the driver instead of asking dev_hard_start_xmit() to do it (which protects against this by resetting the destructor if it has sent all fragments.)
--- include/linux/netdevice.h | 1 + net/core/dev.c | 38 ++++++++++++++++++++++++++++++-------- 2 files changed, 31 insertions(+), 8 deletions(-)
net/core/dev.c +30 -8
@@ -1491,13 +1491,13 @@ static void dev_gso_skb_destructor(struc {struct dev_gso_cb *cb; -do { +while (skb->next) {struct sk_buff *nskb = skb->next; skb->next = nskb->next; nskb->next =NULL ;kfree_skb (nskb); - }while (skb->next); + } cb =DEV_GSO_CB (skb);if (cb->destructor)
@@ -1505,22 +1505,31 @@ static void dev_gso_skb_destructor(struc }/** -* dev_gso_segment - Perform emulated hardware segmentation on skb. +* dev_skb_segment - Perform segmentation on skb. * @skb: buffer to segment +* @segmfn: function that does the actual segmentation * -* This function segments the given skb and stores the list of segments -* in skb->next. +* This function segments the given skb and stores the list +* of segments in skb->next. The segmentation function is +* used to do the actual segmentation, it must return the +* list of segments as chained via the returned skb's @next +* pointer. The segmentation function is given the skb to +* segment and the features of the device the skb is going +* to. The segmentation function needs to return an ERR_PTR +* or a valid sk_buff pointer (or NULL for no segments.) +* +* Note that segmentation needs the skbs @cb data. */ -static int dev_gso_segment (struct sk_buff *skb) +int dev_skb_segment (struct sk_buff *skb,struct sk_buff *(segmfn )(struct sk_buff *skb,int feat)) {struct net_device *dev = skb->dev;struct sk_buff *segs;int features = dev->features & ~(illegal_highdma (dev, skb) ?NETIF_F_SG :0 ); - segs =skb_gso_segment (skb, features); + segs =segmfn (skb, features); -/* Verifying header integrity only. */ +/* Verifying header integrity only/no segments required. */ if (!segs)return 0 ;
@@ -1533,6 +1542,19 @@ static int dev_gso_segment(struct sk_bufreturn 0 ; } +EXPORT_SYMBOL_GPL (dev_skb_segment); + +/** +* dev_gso_segment - Perform emulated hardware segmentation on skb. +* @skb: buffer to segment +* +* This function segments the given skb and stores the list of segments +* in skb->next. +*/ +static int dev_gso_segment (struct sk_buff *skb) +{ +return dev_skb_segment (skb, skb_gso_segment); +}int dev_hard_start_xmit (struct sk_buff *skb,struct net_device *dev) {
include/linux/netdevice.h +1 -0
@@ -1454,6 +1454,7 @@ extern int weight_p;extern int netdev_set_master (struct net_device *dev,struct net_device *master);extern int skb_checksum_help (struct sk_buff *skb);extern struct sk_buff *skb_gso_segment (struct sk_buff *skb,int features); +extern int dev_skb_segment (struct sk_buff *skb,struct sk_buff *(segmfn )(struct sk_buff *skb,int feat));#ifdef CONFIG_BUG extern void netdev_rx_csum_fault (struct net_device *dev);#else
A message that is not in the archive (sent off-list or not yet received): [email protected]
Re: [RFC/RFT 2/4] GSO: generalize for mac80211
Quoted 11 lines · Johannes Berg
plain text document attachment (037-generalize-gso-functions.patch) This patch adds a new function
dev_skb_segment()that generalises the existingdev_gso_segment()by allowing to give a segmentation function. mac80211 will use that function using the segmentation functionskb_segment().This patch also changes
dev_gso_skb_destructor()to be safe when the skb no longer has any segments, this will happen when mac80211 has internally passed off all the fragments to the driver instead of askingdev_hard_start_xmit()to do it (which protects against this by resetting the destructor if it has sent all fragments.)
Any comments on this? I'd like to include this (well, more importantly the mac80211 patch that needs it) for testing for 2.6.27, should I send it via John or directly to you, Dave?
Also, I'm not sure, should I allow for a segmentation function at all? I'm only going to use the generic skb_segment and the code there only uses skb_gso_segment.
johannes
Johannes Berg
maintainerPATCH 3/4 mac80211: use GSO for fragmentation
In reply to Johannes BergThis patch makes mac80211 use the GSO infrastructure for segmentation, but not really all of it because we do not register a protocol handler (nor can do that easily since a lot of functions need to be done before segmentation and another bunch afterwards, and we need to keep rcu- protected structures for both.)
Hence, the way it works is that if a packet is to be fragmented then we call dev_skb_segment() on it and get a fragment list in skb->next. We then go to pass this fragment list to the driver one by one but if at any point the driver is unable to handle more data on its queues we reject the skb (with the remaining fragments) which will cause it to be stored into dev->gso_skb and handed to us (once the queue is woken again) fragment by fragment which we detect and hand on to the driver.
This has the benefit of removing a lot of code that is rarely used (since fragmentation in IEEE 802.11 isn't all that common any more) and is rather complex.
---
Herbert, would you mind taking a look at ieee80211_tx_h_fragment and __ieee80211_tx?
The diffstat is negative despite adding lots of comments :)
include/net/mac80211.h | 11 net/mac80211/ieee80211_i.h | 19 - net/mac80211/main.c | 33 +- net/mac80211/mlme.c | 1 net/mac80211/tx.c | 589 +++++++++++++++++++++------------------------ net/mac80211/util.c | 30 -- net/mac80211/wep.c | 28 +- net/mac80211/wme.c | 9 net/mac80211/wpa.c | 46 ++- 9 files changed, 370 insertions(+), 396 deletions(-)
net/mac80211/ieee80211_i.h +4 -15
@@ -147,7 +147,6 @@ typedef unsigned __bitwise__ ieee80211_t#define IEEE80211_TX_UNICAST BIT(1)#define IEEE80211_TX_PS_BUFFERED BIT(2)#define IEEE80211_TX_PROBE_LAST_FRAG BIT(3) -#define IEEE80211_TX_INJECTED BIT(4)struct ieee80211_tx_data {struct sk_buff *skb;
@@ -165,11 +164,6 @@ struct ieee80211_tx_data {* when using CTS protection with IEEE 802.11g. */ s8 last_frag_rate_idx; -/* Extra fragments (in addition to the first fragment -* in skb) */ -struct sk_buff **extra_frag; -int num_extra_frag; -u16 fc, ethertype;unsigned int flags; };
@@ -213,20 +207,20 @@ struct ieee80211_rx_data {#define IEEE80211_TXPD_REQUEUE BIT(2)#define IEEE80211_TXPD_EAPOL_FRAME BIT(3)#define IEEE80211_TXPD_AMPDU BIT(4) +/* ALWAYS(!) set the _PRESENT bit */ +#define IEEE80211_TXPD_PRESENT BIT(19)/* Stored in sk_buff->cb */ struct ieee80211_tx_packet_data { +u32 flags;int ifindex; +u16 queue;unsigned long jiffies; -unsigned int flags; -u8 queue; };struct ieee80211_tx_stored_packet {struct ieee80211_tx_control control;struct sk_buff *skb; -struct sk_buff **extra_frag;s8 last_frag_rate_idx; -int num_extra_frag;bool last_frag_rate_ctrl_probe; };
@@ -612,8 +606,6 @@ struct ieee80211_local {struct timer_list sta_cleanup;unsigned long state[IEEE80211_MAX_AMPDU_QUEUES +IEEE80211_MAX_AMPDU_QUEUES ]; -struct ieee80211_tx_stored_packet pending_packet[IEEE80211_MAX_AMPDU_QUEUES +IEEE80211_MAX_AMPDU_QUEUES ]; -struct tasklet_struct tx_pending_tasklet;/* number of interfaces with corresponding IFF_ flags */ atomic_t iff_allmultis, iff_promiscs;
@@ -846,7 +838,6 @@ static inline struct ieee80211_hw *localenum ieee80211_link_state_t {IEEE80211_LINK_STATE_XOFF =0 , -IEEE80211_LINK_STATE_PENDING , };struct sta_attribute {
@@ -968,8 +959,6 @@ void ieee80211_if_free(struct net_devicevoid ieee80211_if_sdata_init (struct ieee80211_sub_if_data *sdata);/* tx handling */ -void ieee80211_clear_tx_pending (struct ieee80211_local *local); -void ieee80211_tx_pending (unsigned long data);int ieee80211_master_start_xmit (struct sk_buff *skb,struct net_device *dev);int ieee80211_monitor_start_xmit (struct sk_buff *skb,struct net_device *dev);int ieee80211_subif_start_xmit (struct sk_buff *skb,struct net_device *dev);
net/mac80211/tx.c +281 -308
757 lines not on this page · raw message
net/mac80211/wep.c +17 -11
@@ -349,23 +349,29 @@ static int wep_encrypt_skb(struct ieee80ieee80211_tx_result ieee80211_crypto_wep_encrypt (struct ieee80211_tx_data *tx) { +struct sk_buff *skb; + tx->control->iv_len =WEP_IV_LEN ; tx->control->icv_len =WEP_ICV_LEN ;ieee80211_tx_set_protected (tx); -if (wep_encrypt_skb (tx, tx->skb) <0 ) { -I802_DEBUG_INC (tx->local->tx_handlers_drop_wep); -return TX_DROP ; +/* not fragmented */ +if (!tx->skb->next) { +if (wep_encrypt_skb (tx, tx->skb) <0 ) { +I802_DEBUG_INC (tx->local->tx_handlers_drop_wep); +return TX_DROP ; + } +return TX_CONTINUE ; } -if (tx->extra_frag) { -int i; -for (i =0 ; i < tx->num_extra_frag; i++) { -if (wep_encrypt_skb (tx, tx->extra_frag[i]) <0 ) { -I802_DEBUG_INC (tx->local-> - tx_handlers_drop_wep); -return TX_DROP ; - } +/* fragmented, encrypt fragments */ + + skb = tx->skb; +/* tx->skb is the non-fragmented one */ +while ((skb = skb->next)) { +if (wep_encrypt_skb (tx, skb) <0 ) { +I802_DEBUG_INC (tx->local->tx_handlers_drop_wep); +return TX_DROP ; } }
net/mac80211/wpa.c +28 -18
60 lines not on this page · raw message
net/mac80211/util.c +11 -19
@@ -167,17 +167,13 @@ int ieee80211_get_mesh_hdrlen(struct ieevoid ieee80211_tx_set_protected (struct ieee80211_tx_data *tx) { -struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) tx->skb->data; +struct sk_buff *skb = tx->skb; +struct ieee80211_hdr *hdr; - hdr->frame_control |=cpu_to_le16 (IEEE80211_FCTL_PROTECTED ); -if (tx->extra_frag) { -struct ieee80211_hdr *fhdr; -int i; -for (i =0 ; i < tx->num_extra_frag; i++) { - fhdr = (struct ieee80211_hdr *) - tx->extra_frag[i]->data; - fhdr->frame_control |=cpu_to_le16 (IEEE80211_FCTL_PROTECTED ); - } +while (skb) { + hdr = (struct ieee80211_hdr *) skb->data; + hdr->frame_control |=cpu_to_le16 (IEEE80211_FCTL_PROTECTED ); + skb = skb->next; } }
@@ -333,15 +329,11 @@ void ieee80211_wake_queue(struct ieee802if (test_and_clear_bit (IEEE80211_LINK_STATE_XOFF , &local->state[queue])) { -if (test_bit (IEEE80211_LINK_STATE_PENDING , - &local->state[queue])) -tasklet_schedule (&local->tx_pending_tasklet); -else -if (!ieee80211_qdisc_installed (local->mdev)) { -if (queue ==0 ) -netif_wake_queue (local->mdev); - }else -__netif_schedule (local->mdev); +if (!ieee80211_qdisc_installed (local->mdev)) { +if (queue ==0 ) +netif_wake_queue (local->mdev); + }else +__netif_schedule (local->mdev); } }EXPORT_SYMBOL (ieee80211_wake_queue);
net/mac80211/wme.c +2 -7
@@ -236,9 +236,6 @@ static int wme_qdiscop_enqueue(struct sk } -/* TODO: clean up the cases where master_hard_start_xmit -* returns non 0 - it shouldn't ever do that. Once done we -* can remove this function */ static int wme_qdiscop_requeue (struct sk_buff *skb,struct Qdisc * qd) {struct ieee80211_sched_data *q =qdisc_priv (qd);
@@ -247,7 +244,7 @@ static int wme_qdiscop_requeue(struct skstruct Qdisc *qdisc;int err; -/* we recorded which queue to use earlier! */ +/* We recorded which queue to use earlier. */ qdisc = q->queues[pkt_data->queue];if ((err = qdisc->ops->requeue (skb, qdisc)) ==0 ) {
@@ -274,9 +271,7 @@ static struct sk_buff *wme_qdiscop_deque/* see if there is room in this hardware queue */ if ((test_bit (IEEE80211_LINK_STATE_XOFF , &local->state[queue])) || - (test_bit (IEEE80211_LINK_STATE_PENDING , - &local->state[queue])) || - (!test_bit (queue, q->qdisc_pool))) + (!test_bit (queue, q->qdisc_pool)))continue ;/* there is space - try and get a frame */
net/mac80211/main.c +18 -15
@@ -408,7 +408,6 @@ static int ieee80211_open(struct net_devWARN_ON (res);if (res) goto err_del_interface; -tasklet_enable (&local->tx_pending_tasklet);tasklet_enable (&local->tasklet); }
@@ -602,7 +601,6 @@ static int ieee80211_stop(struct net_devieee80211_led_radio (local,0 ); -tasklet_disable (&local->tx_pending_tasklet);tasklet_disable (&local->tasklet); }
@@ -1204,8 +1202,16 @@ void ieee80211_tx_status_irqsafe(structstruct ieee80211_tx_status *saved;int tmp; +if (WARN_ON (!skb)) +return ; + +if (WARN_ON (!status)) { +dev_kfree_skb (skb); +return ; + } + skb->dev = local->mdev; - saved =kmalloc (sizeof (struct ieee80211_tx_status ),GFP_ATOMIC ); + saved =kmemdup (status,sizeof (struct ieee80211_tx_status ),GFP_ATOMIC );if (unlikely (!saved)) {if (net_ratelimit ()) printk(KERN_WARNING "%s: Not enough memory, "
@@ -1216,7 +1222,6 @@ void ieee80211_tx_status_irqsafe(structdev_kfree_skb_any (skb);return ; } -memcpy (saved, status,sizeof (struct ieee80211_tx_status ));/* copy pointer to saved status into skb->cb for use by tasklet */ memcpy (skb->cb, &saved,sizeof (saved));
@@ -1299,7 +1304,7 @@ static void ieee80211_remove_tx_extra(st pkt_data = (struct ieee80211_tx_packet_data *)skb->cb; pkt_data->ifindex =vif_to_sdata (control->vif)->dev->ifindex; - pkt_data->flags =0 ; + pkt_data->flags =IEEE80211_TXPD_PRESENT ;if (control->flags &IEEE80211_TXCTL_REQ_TX_STATUS ) pkt_data->flags |=IEEE80211_TXPD_REQ_TX_STATUS ;if (control->flags &IEEE80211_TXCTL_DO_NOT_ENCRYPT )
@@ -1435,10 +1440,10 @@ void ieee80211_tx_status(struct ieee8021struct ieee80211_sub_if_data *sdata;struct net_device *prev_dev =NULL ; -if (!status) { -printk (KERN_ERR -"%s: ieee80211_tx_status called with NULL status\n" , -wiphy_name (local->hw.wiphy)); +if (WARN_ON (!skb)) +return ; + +if (WARN_ON (!status)) {dev_kfree_skb (skb);return ; }
@@ -1665,10 +1670,6 @@ struct ieee80211_hw *ieee80211_alloc_hw(sta_info_init (local); -tasklet_init (&local->tx_pending_tasklet, ieee80211_tx_pending, - (unsigned long )local); -tasklet_disable (&local->tx_pending_tasklet); -tasklet_init (&local->tasklet, ieee80211_tasklet_handler, (unsigned long ) local);
@@ -1852,7 +1853,6 @@ void ieee80211_unregister_hw(struct ieeestruct ieee80211_local *local =hw_to_local (hw);struct ieee80211_sub_if_data *sdata, *tmp; -tasklet_kill (&local->tx_pending_tasklet);tasklet_kill (&local->tasklet);rtnl_lock ();
@@ -1886,7 +1886,6 @@ void ieee80211_unregister_hw(struct ieeertnl_unlock ();ieee80211_rx_bss_list_deinit (local->mdev); -ieee80211_clear_tx_pending (local);sta_info_stop (local);rate_control_deinitialize (local);debugfs_hw_del (local);
@@ -1921,6 +1920,10 @@ static int __init ieee80211_init(void)int ret;BUILD_BUG_ON (sizeof (struct ieee80211_tx_packet_data ) >sizeof (skb->cb)); +BUILD_BUG_ON (sizeof (struct ieee80211_tx_control ) >sizeof (skb->cb)); +BUILD_BUG_ON (offsetof(struct ieee80211_tx_control , flags) !=0 ); +BUILD_BUG_ON (offsetof(struct ieee80211_tx_packet_data , flags) !=0 ); +BUILD_BUG_ON (IEEE80211_TXPD_PRESENT !=IEEE80211_TXCTL_TXPD_PRESENT ); ret =rc80211_pid_init ();if (ret)
include/net/mac80211.h +8 -3
@@ -3,7 +3,7 @@* * Copyright 2002-2005, Devicescape Software, Inc. * Copyright 2006-2007 Jiri Benc <[email protected]> -* Copyright 2007 Johannes Berg <[email protected]> +* Copyright 2007-2008 Johannes Berg <[email protected]> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as
@@ -233,6 +233,8 @@ struct ieee80211_bss_conf {* @IEEE80211_TXCTL_40_MHZ_WIDTH: send this frame using 40 Mhz channel width * @IEEE80211_TXCTL_DUP_DATA: duplicate data frame on both 20 Mhz channels * @IEEE80211_TXCTL_SHORT_GI: send this frame using short guard interval +* @IEEE80211_TXCTL_TXPD_PRESENT: Reserved, must never be set. +* @IEEE80211_TXCTL_INJECTED: Frame was injected (NOT for driver use!) */ enum mac80211_tx_control_flags {IEEE80211_TXCTL_REQ_TX_STATUS = (1 <<0 ),
@@ -254,6 +256,8 @@ enum mac80211_tx_control_flags {IEEE80211_TXCTL_40_MHZ_WIDTH = (1 <<16 ),IEEE80211_TXCTL_DUP_DATA = (1 <<17 ),IEEE80211_TXCTL_SHORT_GI = (1 <<18 ), +IEEE80211_TXCTL_TXPD_PRESENT = (1 <<19 ), + IEEE80211_TXCTL_INJECTED = (1<<20), };/* Transmit control fields. This data structure is passed to low-level driver
@@ -278,6 +282,9 @@ struct ieee80211_tx_control {* This could be used when set_retry_limit * is not implemented by the driver */ +u16 queue;/* hardware queue to use for this frame; +* 0 = highest, hw->queues-1 = lowest */ +struct ieee80211_vif *vif;/* Key used for hardware encryption
@@ -290,8 +297,6 @@ struct ieee80211_tx_control {* position represents antenna number used */ u8 icv_len;/* length of the ICV/MIC field in octets */ u8 iv_len;/* length of the IV field in octets */ -u16 queue;/* hardware queue to use for this frame; -* 0 = highest, hw->queues-1 = lowest */ u16 aid;/* Station AID */ int type;/* internal */ };
net/mac80211/mlme.c +1 -0
@@ -587,6 +587,7 @@ void ieee80211_sta_tx(struct net_device pkt_data = (struct ieee80211_tx_packet_data *) skb->cb;memset (pkt_data,0 ,sizeof (struct ieee80211_tx_packet_data )); pkt_data->ifindex = sdata->dev->ifindex; + pkt_data->flags =IEEE80211_TXPD_PRESENT ;if (!encrypt) pkt_data->flags |=IEEE80211_TXPD_DO_NOT_ENCRYPT ;
Re: [RFC/RFT 3/4] mac80211: use GSO for fragmentation
Quoted 5 lines · Johannes Berg
This patch makes mac80211 use the GSO infrastructure for segmentation, but not really all of it because we do not register a protocol handler (nor can do that easily since a lot of functions need to be done before segmentation and another bunch afterwards, and we need to keep rcu- protected structures for both.)
Your idea of using skb_segment to remove duplicate code is great.
However, using skb->gso_skb for the push-back doesn't work. For example, what is going to happen when I enable software GSO on a wireless device and then send a real GSO packet to it where each GSO fragment also required wireless fragmentation?
I suggest that you just use skb_segment for the actual fragmentation but keep the original infrastructure for handling the fragments.
Cheers,
Signature · 4 lines
Visit Openswan at http://www.openswan.org/
Email: Herbert Xu ~{PmV>HI~} <[email protected]>
Home Page: http://gondor.apana.org.au/~herbert/
PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txtJohannes Berg
maintainerRe: [RFC/RFT 3/4] mac80211: use GSO for fragmentation
Quoted 7 lines · Herbert Xu
Quoted 5 lines · Johannes Berg
This patch makes mac80211 use the GSO infrastructure for segmentation, but not really all of it because we do not register a protocol handler (nor can do that easily since a lot of functions need to be done before segmentation and another bunch afterwards, and we need to keep rcu- protected structures for both.)
Quoted 6 lines
Your idea of using
skb_segmentto remove duplicate code is great.However, using
skb->gso_skbfor the push-back doesn't work. For example, what is going to happen when I enable software GSO on a wireless device and then send a real GSO packet to it where each GSO fragment also required wireless fragmentation?
Good point. Somehow I thought this couldn't happen but of course it can since we don't do hw GSO.
Quoted 2 lines
I suggest that you just use
skb_segmentfor the actual fragmentation but keep the original infrastructure for handling the fragments.
But I want to get rid of that much more than I want to get rid of the fragmentation code :/ Also, if I need to keep that code, I will absolutely not use skb_segment either as it's more efficient to just trim the existing skb to make the first segment out of it (like the code does now) rather than reallocate that too.
However, I'm sure it's buggy under certain circumstances we never understood (as indicated by a WARN_ON triggering that shouldn't and lots of reports about that) and I don't like the extra tasklet. I guess I could remove it and copy the existing code into the wireless qdisc, but that would be weird.
But you're right, it doesn't work this way. I'll have to think of something. Maybe I can rip out all the retry logic and just store an skb myself (like dev->gso_skb) and return NETDEV_TX_BUSY when I used that one and the queue got full because of it. That'll requeue a lot when non-gso skbs are coming in, but mind you this is not a common case, most of the time fragmentation will not be enabled and even when it is device queues should be long enough.
johannes
Re: [RFC/RFT 3/4] mac80211: use GSO for fragmentation
Quoted 8 lines · Johannes Berg
But you're right, it doesn't work this way. I'll have to think of something. Maybe I can rip out all the retry logic and just store an skb myself (like
dev->gso_skb) and returnNETDEV_TX_BUSYwhen I used that one and the queue got full because of it. That'll requeue a lot when non-gso skbs are coming in, but mind you this is not a common case, most of the time fragmentation will not be enabled and even when it is device queues should be long enough.
Yes keeping your own gso_skb sounds like a good solution.
Cheers,
Signature · 4 lines
Visit Openswan at http://www.openswan.org/
Email: Herbert Xu ~{PmV>HI~} <[email protected]>
Home Page: http://gondor.apana.org.au/~herbert/
PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txtA message that is not in the archive (sent off-list or not yet received): 20080507090040.GA25186-lOAM2aK0SrRLBo1qDEOMRrpzq4S04n8Q@public.gmane.org
PATCH 1/1 mac80211: rewrite fragmentation code
This patch rewrites mac80211's fragmentation handling to
(a) use skb_segment
(b) get rid of the tasklet etc. and just push responsibility to the qdisc/core code
This can result in excessive requeues when the device only accepts a fragment at a time or so then we'll always ask the generic code to try again but then won't accept the skb. However, devices that only accept a single skb at a time won't get good performance anyhow so it doesn't matter.
---
John, this has no more dependencies on other patches except ones I submitted earlier, please merge unless somebody objects.
include/net/mac80211.h | 10 net/mac80211/ieee80211_i.h | 32 -- net/mac80211/main.c | 46 ++- net/mac80211/tx.c | 629 ++++++++++++++++++++++----------------------- net/mac80211/util.c | 30 -- net/mac80211/wep.c | 26 - net/mac80211/wme.c | 9 net/mac80211/wpa.c | 44 +-- 8 files changed, 395 insertions(+), 431 deletions(-)
net/mac80211/ieee80211_i.h +9 -23
@@ -147,7 +147,6 @@ typedef unsigned __bitwise__ ieee80211_t#define IEEE80211_TX_UNICAST BIT(1)#define IEEE80211_TX_PS_BUFFERED BIT(2)#define IEEE80211_TX_PROBE_LAST_FRAG BIT(3) -#define IEEE80211_TX_INJECTED BIT(4)struct ieee80211_tx_data {struct sk_buff *skb;
@@ -165,11 +164,6 @@ struct ieee80211_tx_data {* when using CTS protection with IEEE 802.11g. */ s8 last_frag_rate_idx; -/* Extra fragments (in addition to the first fragment -* in skb) */ -struct sk_buff **extra_frag; -int num_extra_frag; -u16 fc, ethertype;unsigned int flags; };
@@ -215,19 +209,10 @@ struct ieee80211_rx_data {#define IEEE80211_TXPD_AMPDU BIT(4)/* Stored in sk_buff->cb */ struct ieee80211_tx_packet_data { +u32 flags;int ifindex; +u16 queue;unsigned long jiffies; -unsigned int flags; -u8 queue; -}; - -struct ieee80211_tx_stored_packet { -struct ieee80211_tx_control control; -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 {
@@ -612,8 +597,7 @@ struct ieee80211_local {struct timer_list sta_cleanup;unsigned long state[IEEE80211_MAX_QUEUES +IEEE80211_MAX_AMPDU_QUEUES ]; -struct ieee80211_tx_stored_packet pending_packet[IEEE80211_MAX_QUEUES +IEEE80211_MAX_AMPDU_QUEUES ]; -struct tasklet_struct tx_pending_tasklet; +struct sk_buff *pending_packet[IEEE80211_MAX_QUEUES ];/* number of interfaces with corresponding IFF_ flags */ atomic_t iff_allmultis, iff_promiscs;
@@ -846,7 +830,6 @@ static inline struct ieee80211_hw *localenum ieee80211_link_state_t {IEEE80211_LINK_STATE_XOFF =0 , -IEEE80211_LINK_STATE_PENDING , };struct sta_attribute {
@@ -866,7 +849,6 @@ static inline int ieee80211_bssid_match(int ieee80211_hw_config (struct ieee80211_local *local);int ieee80211_if_config (struct net_device *dev);int ieee80211_if_config_beacon (struct net_device *dev); -void ieee80211_tx_set_protected (struct ieee80211_tx_data *tx);void ieee80211_if_setup (struct net_device *dev); u32 ieee80211_handle_ht(struct ieee80211_local *local, int enable_ht, struct ieee80211_ht_info *req_ht_cap,
@@ -967,8 +949,6 @@ void ieee80211_if_free(struct net_devicevoid ieee80211_if_sdata_init (struct ieee80211_sub_if_data *sdata);/* tx handling */ -void ieee80211_clear_tx_pending (struct ieee80211_local *local); -void ieee80211_tx_pending (unsigned long data);int ieee80211_master_start_xmit (struct sk_buff *skb,struct net_device *dev);int ieee80211_monitor_start_xmit (struct sk_buff *skb,struct net_device *dev);int ieee80211_subif_start_xmit (struct sk_buff *skb,struct net_device *dev);
@@ -984,4 +964,10 @@ int ieee80211_frame_duration(struct ieeevoid mac80211_ev_michael_mic_failure (struct net_device *dev,int keyidx,struct ieee80211_hdr *hdr); +static inline void ieee80211_skb_set_protected (struct sk_buff *skb) +{ +struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; + hdr->frame_control |=cpu_to_le16 (IEEE80211_FCTL_PROTECTED ); +} +#endif /* IEEE80211_I_H */
net/mac80211/tx.c +309 -320
801 lines not on this page · raw message
net/mac80211/wep.c +12 -14
@@ -333,6 +333,8 @@ ieee80211_crypto_wep_decrypt(struct ieeestatic int wep_encrypt_skb (struct ieee80211_tx_data *tx,struct sk_buff *skb) { +ieee80211_skb_set_protected (skb); +if (!(tx->key->flags &KEY_FLAG_UPLOADED_TO_HARDWARE )) {if (ieee80211_wep_encrypt (tx->local, skb, tx->key))return -1 ;
@@ -349,25 +351,21 @@ static int wep_encrypt_skb(struct ieee80ieee80211_tx_result ieee80211_crypto_wep_encrypt (struct ieee80211_tx_data *tx) { +struct sk_buff *skb = tx->skb; + tx->control->iv_len =WEP_IV_LEN ; tx->control->icv_len =WEP_ICV_LEN ; -ieee80211_tx_set_protected (tx); -if (wep_encrypt_skb (tx, tx->skb) <0 ) { +/* skip original if fragmented */ +if (skb->next) + skb = skb->next; + +do { +if (wep_encrypt_skb (tx, tx->skb) ==0 ) +continue ;I802_DEBUG_INC (tx->local->tx_handlers_drop_wep);return TX_DROP ; - } - -if (tx->extra_frag) { -int i; -for (i =0 ; i < tx->num_extra_frag; i++) { -if (wep_encrypt_skb (tx, tx->extra_frag[i]) <0 ) { -I802_DEBUG_INC (tx->local-> - tx_handlers_drop_wep); -return TX_DROP ; - } - } - } + }while ((skb = skb->next));return TX_CONTINUE ; }
net/mac80211/wpa.c +20 -24
80 lines not on this page · raw message
net/mac80211/util.c +5 -25
@@ -165,22 +165,6 @@ int ieee80211_get_mesh_hdrlen(struct iee } } -void ieee80211_tx_set_protected (struct ieee80211_tx_data *tx) -{ -struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) tx->skb->data; - - hdr->frame_control |=cpu_to_le16 (IEEE80211_FCTL_PROTECTED ); -if (tx->extra_frag) { -struct ieee80211_hdr *fhdr; -int i; -for (i =0 ; i < tx->num_extra_frag; i++) { - fhdr = (struct ieee80211_hdr *) - tx->extra_frag[i]->data; - fhdr->frame_control |=cpu_to_le16 (IEEE80211_FCTL_PROTECTED ); - } - } -} -int ieee80211_frame_duration (struct ieee80211_local *local,size_t len,int rate,int erp,int short_preamble) {
@@ -333,15 +317,11 @@ void ieee80211_wake_queue(struct ieee802if (test_and_clear_bit (IEEE80211_LINK_STATE_XOFF , &local->state[queue])) { -if (test_bit (IEEE80211_LINK_STATE_PENDING , - &local->state[queue])) -tasklet_schedule (&local->tx_pending_tasklet); -else -if (!ieee80211_qdisc_installed (local->mdev)) { -if (queue ==0 ) -netif_wake_queue (local->mdev); - }else -__netif_schedule (local->mdev); +if (!ieee80211_qdisc_installed (local->mdev)) { +if (queue ==0 ) +netif_wake_queue (local->mdev); + }else +__netif_schedule (local->mdev); } }EXPORT_SYMBOL (ieee80211_wake_queue);
net/mac80211/wme.c +2 -7
@@ -235,9 +235,6 @@ static int wme_qdiscop_enqueue(struct sk } -/* TODO: clean up the cases where master_hard_start_xmit -* returns non 0 - it shouldn't ever do that. Once done we -* can remove this function */ static int wme_qdiscop_requeue (struct sk_buff *skb,struct Qdisc * qd) {struct ieee80211_sched_data *q =qdisc_priv (qd);
@@ -246,7 +243,7 @@ static int wme_qdiscop_requeue(struct skstruct Qdisc *qdisc;int err; -/* we recorded which queue to use earlier! */ +/* We recorded which queue to use earlier. */ qdisc = q->queues[pkt_data->queue];if ((err = qdisc->ops->requeue (skb, qdisc)) ==0 ) {
@@ -273,9 +270,7 @@ static struct sk_buff *wme_qdiscop_deque/* see if there is room in this hardware queue */ if ((test_bit (IEEE80211_LINK_STATE_XOFF , &local->state[queue])) || - (test_bit (IEEE80211_LINK_STATE_PENDING , - &local->state[queue])) || - (!test_bit (queue, q->qdisc_pool))) + (!test_bit (queue, q->qdisc_pool)))continue ;/* there is space - try and get a frame */
net/mac80211/main.c +32 -14
108 lines not on this page · raw message
include/net/mac80211.h +6 -4
@@ -3,7 +3,7 @@* * Copyright 2002-2005, Devicescape Software, Inc. * Copyright 2006-2007 Jiri Benc <[email protected]> -* Copyright 2007 Johannes Berg <[email protected]> +* Copyright 2007-2008 Johannes Berg <[email protected]> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as
@@ -233,6 +233,7 @@ struct ieee80211_bss_conf {* @IEEE80211_TXCTL_40_MHZ_WIDTH: send this frame using 40 Mhz channel width * @IEEE80211_TXCTL_DUP_DATA: duplicate data frame on both 20 Mhz channels * @IEEE80211_TXCTL_SHORT_GI: send this frame using short guard interval +* @IEEE80211_TXCTL_INJECTED: Frame was injected (NOT for driver use!) */ enum mac80211_tx_control_flags {IEEE80211_TXCTL_REQ_TX_STATUS = (1 <<0 ),
@@ -254,6 +255,7 @@ enum mac80211_tx_control_flags {IEEE80211_TXCTL_40_MHZ_WIDTH = (1 <<16 ),IEEE80211_TXCTL_DUP_DATA = (1 <<17 ),IEEE80211_TXCTL_SHORT_GI = (1 <<18 ), + IEEE80211_TXCTL_INJECTED = (1<<19), };/* Transmit control fields. This data structure is passed to low-level driver
@@ -278,6 +280,9 @@ struct ieee80211_tx_control {* This could be used when set_retry_limit * is not implemented by the driver */ +u16 queue;/* hardware queue to use for this frame; +* 0 = highest, hw->queues-1 = lowest */ +struct ieee80211_vif *vif;/* Key used for hardware encryption
@@ -290,10 +295,7 @@ struct ieee80211_tx_control {* position represents antenna number used */ u8 icv_len;/* length of the ICV/MIC field in octets */ u8 iv_len;/* length of the IV field in octets */ -u16 queue;/* hardware queue to use for this frame; -* 0 = highest, hw->queues-1 = lowest */ u16 aid;/* Station AID */ -int type;/* internal */ };
--
To unsubscribe from this list: send the line "unsubscribe linux-wireless" in the body of a message to [email protected] More majordomo info at http://vger.kernel.org/majordomo-info.html
A message that is not in the archive (sent off-list or not yet received): [email protected]
Re: [PATCH] mac80211: rewrite fragmentation code
net/mac80211/tx.c static int ieee80211_tx_prepare(struct i · line 1081
Quoted 4 lines · Johannes Berg
net/mac80211/tx.c +3
-0+if (unlikely (netif_queue_stopped (local->mdev) || +__ieee80211_queue_stopped (local, control->queue))) +return NETDEV_TX_BUSY ;
Returning busy should be avoided because not everything expects it. For example, this can cause tcpdump to see the same packet twice.
Besides, I'm not sure if this will even work if you're fiddling with skb->next. Perhaps you can stash it in a pointer local to your device.
Cheers,
Signature · 8 lines
Visit Openswan at http://www.openswan.org/
Email: Herbert Xu ~{PmV>HI~} <[email protected]>
Home Page: http://gondor.apana.org.au/~herbert/
PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt
--
To unsubscribe from this list: send the line "unsubscribe linux-wireless" in
the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.htmlJohannes Berg
maintainerRe: [PATCH] mac80211: rewrite fragmentation code
Quoted 7 lines · Herbert Xu
net/mac80211/tx.c static int ieee80211_tx_prepare(struct i · line 1081
Quoted 4 lines · Johannes Berg
net/mac80211/tx.c +3
-0+if (unlikely (netif_queue_stopped (local->mdev) || +__ieee80211_queue_stopped (local, control->queue))) +return NETDEV_TX_BUSY ;Returning busy should be avoided because not everything expects it.
Hmm. Why does busy exist then? Historical accident? I really really don't want to keep all that logic that does "if device enables queue then first check if maybe we have pending packets and try to send them and then go back to the regular queues and see if ..."
Quoted 3 lines
Besides, I'm not sure if this will even work if you're fiddling with
skb->next. Perhaps you can stash it in a pointer local to your device.
You're looking at an internal helper function that is never called with skb->next assigned; if it returns BUSY for a fragmented skb then later in __ieee80211_tx() I will store the fragmented frame away and return OK.
But if I really need to avoid returning busy I need to hook into all the queue management stuff which I'd like to avoid.
johannes
A message that is not in the archive (sent off-list or not yet received): [email protected]
Re: [PATCH] mac80211: rewrite fragmentation code
Quoted 2 lines · Johannes Berg
Hmm. Why does busy exist then? Historical accident? I really really
Yes it's historical baggage. These days the biggest users would be LLTX drivers which should all be converted to non-LLTX and drivers that don't keep track of queue status properly.
Cheers,
Signature · 8 lines
Visit Openswan at http://www.openswan.org/
Email: Herbert Xu ~{PmV>HI~} <[email protected]>
Home Page: http://gondor.apana.org.au/~herbert/
PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt
--
To unsubscribe from this list: send the line "unsubscribe linux-wireless" in
the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.htmlA message that is not in the archive (sent off-list or not yet received): 20080507130548.GA26977-lOAM2aK0SrRLBo1qDEOMRrpzq4S04n8Q@public.gmane.org
Re: [PATCH] mac80211: rewrite fragmentation code
Quoted 7 lines · On Wednesday 07 May 2008 15:05:48 Herbert Xu wrote:
Quoted 2 lines · Johannes Berg
Hmm. Why does busy exist then? Historical accident? I really really
Yes it's historical baggage. These days the biggest users would be LLTX drivers which should all be converted to non-LLTX and drivers that don't keep track of queue status properly.
So there's no way to actually fail in a TX handler? Drivers are doomed to drop the packet, if they cannot handle it due to ring overflow?
Signature · 5 lines
Greetings Michael. -- To unsubscribe from this list: send the line "unsubscribe linux-wireless" in the body of a message to [email protected] More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH] mac80211: rewrite fragmentation code
Quoted 4 lines · Michael Buesch
So there's no way to actually fail in a TX handler? Drivers are doomed to drop the packet, if they cannot handle it due to ring overflow?
You're supposed to stop the queue before the ring overflows.
Cheers,
Signature · 4 lines
Visit Openswan at http://www.openswan.org/
Email: Herbert Xu ~{PmV>HI~} <[email protected]>
Home Page: http://gondor.apana.org.au/~herbert/
PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txtA message that is not in the archive (sent off-list or not yet received): 20080508032208.GA401-lOAM2aK0SrRLBo1qDEOMRrpzq4S04n8Q@public.gmane.org
Re: [PATCH] mac80211: rewrite fragmentation code
From: Herbert Xu <[email protected]>
Date: Thu, 8 May 2008 11:22:08 +0800
Quoted 7 lines · Michael Buesch
Quoted 4 lines
So there's no way to actually fail in a TX handler? Drivers are doomed to drop the packet, if they cannot handle it due to ring overflow?
You're supposed to stop the queue before the ring overflows.
Right, and this is why drivers choose a TX wakeup threshold such that they can accept an arbitrarily sized TSO frame.
For example, from drivers/net/tg3.c's ->hard_start_xmit():
if (unlikely(tg3_tx_avail(tp) <= (MAX_SKB_FRAGS + 1))) {
netif_stop_queue(dev);
if (tg3_tx_avail(tp) > TG3_TX_WAKEUP_THRESH(tp))
netif_wake_queue(tp->dev);
}The driver is responsible for stopping the queue _before_ it enters a state where there is not enough space in the queue to accept a packet.
This is why most drivers make the following kind of BUG check at the start of their ->hard_start_xmit()
if (unlikely(tg3_tx_avail(tp) <= (skb_shinfo(skb)->nr_frags + 1))) {
if (!netif_queue_stopped(dev)) {
netif_stop_queue(dev);
/* This is a hard error, log it. */
printk(KERN_ERR PFX "%s: BUG! Tx Ring full when "
"queue awake!\n", dev->name);
}
return NETDEV_TX_BUSY;
}--
To unsubscribe from this list: send the line "unsubscribe linux-wireless" in the body of a message to [email protected] More majordomo info at http://vger.kernel.org/majordomo-info.html
A message that is not in the archive (sent off-list or not yet received): 20080507.202606.242037993.davem-fT/PcQaiUtIeIZ0/[email protected]
Re: [PATCH] mac80211: rewrite fragmentation code
Quoted 13 lines · David Miller
Quoted 1 line
You're supposed to stop the queue before the ring overflows.
Right, and this is why drivers choose a TX wakeup threshold such that they can accept an arbitrarily sized TSO frame.
For example, from drivers/net/tg3.c's ->hard_start_xmit():
if (unlikely(tg3_tx_avail(tp) <= (MAX_SKB_FRAGS + 1))) { netif_stop_queue(dev); if (tg3_tx_avail(tp) > TG3_TX_WAKEUP_THRESH(tp)) netif_wake_queue(tp->dev); }
Quoted 3 lines
The driver is responsible for stopping the queue _before_ it enters a state where there is not enough space in the queue to accept a packet.
Yes yes yes I know :) It's just quite awkward to handle when your hard_start_xmit() actually increases the number of packets, you don't really know how deep the queue is etc. I'll add an assertion like that to mac80211 for the non-fragmented case and clean up the fragmented case to retry by itself without upper layer involvement after the tx->cb patch.
johannes
Re: [PATCH] mac80211: rewrite fragmentation code
In reply to a message not in the archiveQuoted 4 lines · On Thursday 08 May 2008 13:26:06 David Miller wrote:
From: Herbert Xu <[email protected]>
Date: Thu, 8 May 2008 11:22:08 +0800Quoted 1 line · Michael Buesch
Quoted 8 lines
Quoted 5 lines
Quoted 3 lines
So there's no way to actually fail in a TX handler? Drivers are doomed to drop the packet, if they cannot handle it due to ring overflow?
You're supposed to stop the queue before the ring overflows.
Right, and this is why drivers choose a TX wakeup threshold such that they can accept an arbitrarily sized TSO frame.
Dave, please allow me to ask a heretical question. Returning TX_BUSY has some appeal for virtio_net: is it fundamentally a flawed idea, or simply a matter of coding?
Currently we have no virtio interface to ask how many descriptors are left; it's not clear that it's a fair question to ask, since for Xen it's depends on the actual buffers we're trying to put in the descirptors.
Thanks,
Rusty.
--
To unsubscribe from this list: send the line "unsubscribe linux-wireless" in the body of a message to [email protected] More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH] mac80211: rewrite fragmentation code
Quoted 4 lines · Rusty Russell
Dave, please allow me to ask a heretical question. Returning
TX_BUSYhas some appeal forvirtio_net: is it fundamentally a flawed idea, or simply a matter of coding?
I don't think returning TX_BUSY is fundamentally flawed (unlike LLTX which is). However, until somebody (i.e., you :) writes the code to handle it properly, i.e., not making the requeued packet go through AF_PCAKET twice, it's something that shouldn't be encouraged.
Cheers,
Signature · 4 lines
Visit Openswan at http://www.openswan.org/
Email: Herbert Xu ~{PmV>HI~} <[email protected]>
Home Page: http://gondor.apana.org.au/~herbert/
PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txtDavid Miller
maintainerRe: [PATCH] mac80211: rewrite fragmentation code
In reply to Rusty RussellFrom: Rusty Russell <[email protected]>
Date: Fri, 16 May 2008 12:01:48 +1000
Quoted 3 lines
Dave, please allow me to ask a heretical question. Returning
TX_BUSYhas some appeal forvirtio_net: is it fundamentally a flawed idea, or simply a matter of coding?
Allowing TX_BUSY adds a special case to the caller which we'd like to remove at some point.
Quoted 3 lines
Currently we have no virtio interface to ask how many descriptors are left; it's not clear that it's a fair question to ask, since for Xen it's depends on the actual buffers we're trying to put in the descirptors.
Two things:
1) You can always make sure that you have enough space for a TSO frame, with arbitrary page boundaries and thus buffer chopping.
It can even be estimated, and if violated by some corner case you can punt and drop.
2) You can queue inside of the driver one packet when you hit the limits unexpectedly, netif_stop_queue(), and return success. Spit this packet out right before waking the queue again.
Really, there are no hard reasons to ever return TX_BUSY, it's always a bug.
In fact, I want to move things more and more towards the driver queueing TX packets internally instead of the networking mid-layer.
That will ahve benefits for things like TX multiqueue, we won't need any locking at all, nor have any knowledge about multiple queues at all, if the driver takes care of providing the buffer between what the kernel gives it and what the device can handle at the moment.
A message that is not in the archive (sent off-list or not yet received): 20080515.215823.28841530.davem-fT/PcQaiUtIeIZ0/[email protected]
Re: [PATCH] mac80211: rewrite fragmentation code
Quoted 14 lines · On Friday 16 May 2008 14:58:23 David Miller wrote:
From: Rusty Russell <rusty-8n+1lVoiYb80n/[email protected]>
Date: Fri, 16 May 2008 12:01:48 +1000Quoted 3 lines
Dave, please allow me to ask a heretical question. Returning
TX_BUSYhas some appeal forvirtio_net: is it fundamentally a flawed idea, or simply a matter of coding?Allowing
TX_BUSYadds a special case to the caller which we'd like to remove at some point.Quoted 3 lines
Currently we have no virtio interface to ask how many descriptors are left; it's not clear that it's a fair question to ask, since for Xen it's depends on the actual buffers we're trying to put in the descirptors.
Quoted 8 lines
Two things:
1) You can always make sure that you have enough space for a TSO frame, with arbitrary page boundaries and thus buffer chopping.
It can even be estimated, and if violated by some corner case you can punt and drop.
Yes, this is what we'd have to do. Wasting room in the ring feels wrong though.
Quoted 4 lines
2) You can queue inside of the driver one packet when you hit the limits unexpectedly,
netif_stop_queue(), and return success. Spit this packet out right before waking the queue again.
I put a patch in to do exactly that at Herbert's prompting, for 2.6.26, but it's buggy in (at least) two ways. I have a fix for this, which adds a new tasklet to xmit the packet. There's still some subtle race, however, since I'm still seeing a stuck packet. I'll have to revert to TX_BUSY for 2.6.26 if I can't find it (unlikely).
And I haven't measured what it does to performance (should be OK, but still).
Quoted 2 lines
Really, there are no hard reasons to ever return
TX_BUSY, it's always a bug.
But it's *simple*, and seems like a common thing to want. Why not change everything to use TX_BUSY and rip out the guestimate/buffering hacks?
Quoted 8 lines
In fact, I want to move things more and more towards the driver queueing TX packets internally instead of the networking mid-layer.
That will ahve benefits for things like TX multiqueue, we won't need any locking at all, nor have any knowledge about multiple queues at all, if the driver takes care of providing the buffer between what the kernel gives it and what the device can handle at the moment.
That would be great: then I could shove the packet back on the queue myself and not have to ask you about it. It's adding a *second* queue inside the driver which feels terribly ugly...
Cheers,
Rusty.
--
To unsubscribe from this list: send the line "unsubscribe linux-wireless" in the body of a message to [email protected] More majordomo info at http://vger.kernel.org/majordomo-info.html
A message that is not in the archive (sent off-list or not yet received): 200805162032.48469.rusty-8n+1lVoiYb80n/[email protected]
Re: [PATCH] mac80211: rewrite fragmentation code
Quoted 6 lines
I put a patch in to do exactly that at Herbert's prompting, for 2.6.26, but it's buggy in (at least) two ways. I have a fix for this, which adds a new tasklet to xmit the packet. There's still some subtle race, however, since I'm still seeing a stuck packet. I'll have to revert to
TX_BUSYfor 2.6.26 if I can't find it (unlikely).
Incidentally, mac80211 has a tasklet for this as well, and I'm pretty sure it's also buggy in the corner cases (rather than inefficient or something)
johannes
Re: [PATCH] mac80211: rewrite fragmentation code
In reply to Rusty RussellQuoted 3 lines · Rusty Russell
But it's *simple*, and seems like a common thing to want. Why not change everything to use
TX_BUSYand rip out the guestimate/buffering hacks?
I think this sounds quite reasonable.
Cheers,
Signature · 4 lines
Visit Openswan at http://www.openswan.org/
Email: Herbert Xu ~{PmV>HI~} <[email protected]>
Home Page: http://gondor.apana.org.au/~herbert/
PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txtDavid Miller
maintainerRe: [PATCH] mac80211: rewrite fragmentation code
In reply to Rusty RussellFrom: Rusty Russell <[email protected]>
Date: Fri, 16 May 2008 20:32:48 +1000
Quoted 10 lines · On Friday 16 May 2008 14:58:23 David Miller wrote:
Quoted 8 lines
In fact, I want to move things more and more towards the driver queueing TX packets internally instead of the networking mid-layer.
That will ahve benefits for things like TX multiqueue, we won't need any locking at all, nor have any knowledge about multiple queues at all, if the driver takes care of providing the buffer between what the kernel gives it and what the device can handle at the moment.
Quoted 3 lines
That would be great: then I could shove the packet back on the queue myself and not have to ask you about it. It's adding a *second* queue inside the driver which feels terribly ugly...
My description describes how I want the mid-layer queue to disappear entirely. Queueing would be done by the driver only.
Only the driver knows all of these details about how much space there is, what packet chopping has to take place and what effects that has on queue space, multiqueue configurations, how one wants to hash to multiple queues, how to lock this stuff the most efficiently.
The kernel should just get out of the way and let the driver take care of everything.
Sure, we can have some standard helpers to deal with the most common cases. But anything non-trivial right now is painful because the mid-layer model tries to be too helpful when it should just get out of the way.
A message that is not in the archive (sent off-list or not yet received): 20080516.124039.253626477.davem-fT/PcQaiUtIeIZ0/[email protected]
Re: [PATCH] mac80211: rewrite fragmentation code
Quoted 2 lines · On Saturday 17 May 2008 05:40:39 David Miller wrote:
My description describes how I want the mid-layer queue to disappear entirely. Queueing would be done by the driver only.
Ok, the more I ponder this, the more I like it. It has a very nice side benefit for virtio_net: we can xmit a whole bunch of packets before notifying the host. Real NICs might gain similarly.
The bit I can't see is what to do about qdisc if the driver manages its own queue(s). Leave the qdisc as currently in place and have the driver call dev_dequeue_skb() (or some wrapper) directly? Modulo locking issues, that should be a fairly simple change.
Thanks,
Rusty.
--
To unsubscribe from this list: send the line "unsubscribe linux-wireless" in the body of a message to [email protected] More majordomo info at http://vger.kernel.org/majordomo-info.html
David Miller
maintainerRe: [PATCH] mac80211: rewrite fragmentation code
From: Rusty Russell <[email protected]>
Date: Mon, 19 May 2008 13:08:13 +1000
Quoted 4 lines
The bit I can't see is what to do about qdisc if the driver manages its own queue(s). Leave the qdisc as currently in place and have the driver call
dev_dequeue_skb()(or some wrapper) directly? Modulo locking issues, that should be a fairly simple change.
I'd like to approach a state where the device is just a black hole that the qdisc injects packets into. At least theoretically, that's what the network is once the packet leaves the device anyways. Nobody really notices as long as flows don't get reordered.
I realize it isn't feasible to retain many of the qualities that some qdiscs want (rates, qfull handling, etc.), so we'll have to provide some handling for that, ideally in some cheap slowpath test.
But for things like tx queue backlog overflow the behavior would be essentially the same. The only change is that the txqueuelen parameter is handled inside of the driver (again, perhaps via helpers).
Our TX path is way too complicated and, frankly, restrictive.
This is why we don't have real parallel TX multiqueue support as a simple patch to some drivers. We have fundamental restrictions that keep that from happening.
Re: [PATCH] mac80211: rewrite fragmentation code
In reply to Herbert XuQuoted 7 lines · On Thursday 08 May 2008 05:22:08 Herbert Xu wrote:
Quoted 4 lines · Michael Buesch
So there's no way to actually fail in a TX handler? Drivers are doomed to drop the packet, if they cannot handle it due to ring overflow?
You're supposed to stop the queue before the ring overflows.
Ok, what about DMA error. kmalloc error or something else? ring overflow was a bad example, of course.
Signature · 1 line
Greetings Michael.
A message that is not in the archive (sent off-list or not yet received): [email protected]
Re: [PATCH] mac80211: rewrite fragmentation code
Quoted 3 lines · Michael Buesch
Ok, what about DMA error. kmalloc error or something else? ring overflow was a bad example, of course.
If your NIC gets DMA errors all the time then I suggest you invest in some new hardware. Ditto if you fail to kmalloc all the time.
If they're rare as they should be then dropping the packet is perfectly reasonable.
Cheers,
Signature · 8 lines
Visit Openswan at http://www.openswan.org/
Email: Herbert Xu ~{PmV>HI~} <[email protected]>
Home Page: http://gondor.apana.org.au/~herbert/
PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt
--
To unsubscribe from this list: send the line "unsubscribe linux-wireless" in
the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.htmlRe: [PATCH] mac80211: rewrite fragmentation code
Quoted 11 lines · On Thursday 08 May 2008 15:08:46 Herbert Xu wrote:
Quoted 3 lines · Michael Buesch
Ok, what about DMA error. kmalloc error or something else? ring overflow was a bad example, of course.
If your NIC gets DMA errors all the time then I suggest you invest in some new hardware. Ditto if you fail to kmalloc all the time.
If they're rare as they should be then dropping the packet is perfectly reasonable.
Ok, why is nobody actually answering my _question_? :)
So I'll try to answer it by myself: the hard_start_xmit callback is actually supposed to return "void", but it returns "int" just for historical reasons. So there is no way to fail in a TX handler. If a failure happens, the driver must free and drop the skb. How likely errors are is a completely different story. One could argue that errors are unlikely for any part of the kernel, except for very sone special cases.
So does that also apply to the wireless stack? Should we change drivers to always return 0. later we can change the function prototype to return void.
Signature · 1 line
Greetings Michael.
Re: [PATCH] mac80211: rewrite fragmentation code
Quoted 2 lines · On Thursday 08 May 2008 15:13:56 Michael Buesch wrote:
that errors are unlikely for any part of the kernel, except for very sone special cases.
"..., except for some very special cases."
Signature · 1 line
Greetings Michael.
A message that is not in the archive (sent off-list or not yet received): [email protected]
Re: [PATCH] mac80211: rewrite fragmentation code
Quoted 5 lines · Michael Buesch
Ok, why is nobody actually answering my _question_? :) So I'll try to answer it by myself: the
hard_start_xmitcallback is actually supposed to return "void", but it returns "int" just for historical reasons. So there is no way to fail in a TX handler.
Pretty much. When lockless drivers were the vogue the return value was useful but as we've since found better ways to scale NICs in an SMP environment (first the tg3 model, and then multi- queue TX) that don't have the problems associated with requeueing the packet, any non-zero return value should only be used by existing code.
Cheers,
Signature · 8 lines
Visit Openswan at http://www.openswan.org/
Email: Herbert Xu ~{PmV>HI~} <[email protected]>
Home Page: http://gondor.apana.org.au/~herbert/
PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt
--
To unsubscribe from this list: send the line "unsubscribe linux-wireless" in
the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.htmlRe: [PATCH] mac80211: rewrite fragmentation code
In reply to a message not in the archiveQuoted 7 lines · Herbert Xu
Quoted 2 lines · Johannes Berg
Hmm. Why does busy exist then? Historical accident? I really really
Yes it's historical baggage. These days the biggest users would be LLTX drivers which should all be converted to non-LLTX and drivers that don't keep track of queue status properly.
Hmmm mmmm. I'll clean it up later, it gets easier with my patch that puts the control info into skb->cb so I'll do that later in a separate patch. The way I see it, this is actually *correct* from a "what hits the air" point of view and the current code is crappy.
johannes
Johannes Berg
maintainerQuoted 5 lines
Any testing of this series is welcome, even just the first patch by itself (especially with drivers other than b43), it doesn't make sense to test with patch 2 and not 3 though, so if you're going to test one by one treat 2/3 as a set.
I have, of course, tested this series with b43 (and founds dozens of bugs...) Michael, thanks for your dma overflow injection feature :)
One thing that turned up was that if I enable dma overflow with this patchset then b43 hardware spews lots of PHY TX errors. I have verified that the ieee80211_tx_control info is correct, and the frame data is also fine, so I'm not sure what's up there. Could that be unrelated to this patch? I haven't tested dma overflow injection w/o this series yet.
johannes
Quoted 8 lines · On Wednesday 30 April 2008 15:07:29 Johannes Berg wrote:
Quoted 5 lines
Any testing of this series is welcome, even just the first patch by itself (especially with drivers other than b43), it doesn't make sense to test with patch 2 and not 3 though, so if you're going to test one by one treat 2/3 as a set.
I have, of course, tested this series with b43 (and founds dozens of bugs...) Michael, thanks for your dma overflow injection feature :)
:)
Quoted 5 lines
One thing that turned up was that if I enable dma overflow with this patchset then b43 hardware spews lots of PHY TX errors. I have verified that the
ieee80211_tx_controlinfo is correct, and the frame data is also fine, so I'm not sure what's up there. Could that be unrelated to this patch? I haven't tested dma overflow injection w/o this series yet.
Hm, not sure. It could be a b43 bug, of course. But last time I tested the overflow injection, it worked fine. And that's not too long ago. Probably 3 or 4 weeks. Of course, we should test this again with the QOS patch applied and removed now. If that patch does actually trigger it, then we probably still need to search for a b43 bug.
Is the QOS callback (forgot its name) called when we have an overflow?
Signature · 1 line
Greetings Michael.