aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDaniel Drake <dsd@gentoo.org>2007-07-27 09:43:24 -0400
committerDavid S. Miller <davem@sunset.davemloft.net>2007-10-10 19:47:38 -0400
commit7e9ed18874f0df84b6651f0636e1cfdac43bc610 (patch)
tree7bac6083031a48e488c0de5bf71e7f9398e0e011
parentd5d08def9216c445339c5a24a2cdc9cc2c8c13f7 (diff)
[MAC80211]: improved short preamble handling
Similarly to CTS protection, whether short preambles are used for 802.11b transmissions should be a per-subif setting, not device global. For STAs, this patch makes short preamble handling automatic based on the ERP IE. For APs, hostapd still uses the prism ioctls, but the write ioctl has been restricted to AP-only subifs. ieee80211_txrx_data.short_preamble (an unused field) was removed. Unfortunately, some API changes were required for the following functions: - ieee80211_generic_frame_duration - ieee80211_rts_duration - ieee80211_ctstoself_duration - ieee80211_rts_get - ieee80211_ctstoself_get Affected drivers were updated accordingly. Signed-off-by: Daniel Drake <dsd@gentoo.org> Signed-off-by: Jiri Benc <jbenc@suse.cz> Signed-off-by: John W. Linville <linville@tuxdriver.com>
-rw-r--r--drivers/net/wireless/rtl8187.h1
-rw-r--r--drivers/net/wireless/rtl8187_dev.c4
-rw-r--r--include/net/mac80211.h15
-rw-r--r--net/mac80211/ieee80211_i.h7
-rw-r--r--net/mac80211/ieee80211_ioctl.c7
-rw-r--r--net/mac80211/ieee80211_sta.c16
-rw-r--r--net/mac80211/tx.c31
-rw-r--r--net/mac80211/util.c37
8 files changed, 88 insertions, 30 deletions
diff --git a/drivers/net/wireless/rtl8187.h b/drivers/net/wireless/rtl8187.h
index 6124e467b156..7993b3d87203 100644
--- a/drivers/net/wireless/rtl8187.h
+++ b/drivers/net/wireless/rtl8187.h
@@ -67,6 +67,7 @@ struct rtl8187_priv {
67 struct rtl818x_csr *map; 67 struct rtl818x_csr *map;
68 void (*rf_init)(struct ieee80211_hw *); 68 void (*rf_init)(struct ieee80211_hw *);
69 int mode; 69 int mode;
70 int if_id;
70 71
71 /* rtl8187 specific */ 72 /* rtl8187 specific */
72 struct ieee80211_channel channels[14]; 73 struct ieee80211_channel channels[14];
diff --git a/drivers/net/wireless/rtl8187_dev.c b/drivers/net/wireless/rtl8187_dev.c
index e61c6d5ba1a9..73f1ebc7eec7 100644
--- a/drivers/net/wireless/rtl8187_dev.c
+++ b/drivers/net/wireless/rtl8187_dev.c
@@ -96,7 +96,7 @@ static int rtl8187_tx(struct ieee80211_hw *dev, struct sk_buff *skb,
96 if (control->flags & IEEE80211_TXCTL_USE_RTS_CTS) { 96 if (control->flags & IEEE80211_TXCTL_USE_RTS_CTS) {
97 tmp |= RTL8187_TX_FLAG_RTS; 97 tmp |= RTL8187_TX_FLAG_RTS;
98 hdr->rts_duration = 98 hdr->rts_duration =
99 ieee80211_rts_duration(dev, skb->len, control); 99 ieee80211_rts_duration(dev, priv->if_id, skb->len, control);
100 } 100 }
101 if (control->flags & IEEE80211_TXCTL_USE_CTS_PROTECT) 101 if (control->flags & IEEE80211_TXCTL_USE_CTS_PROTECT)
102 tmp |= RTL8187_TX_FLAG_CTS; 102 tmp |= RTL8187_TX_FLAG_CTS;
@@ -510,6 +510,8 @@ static int rtl8187_config_interface(struct ieee80211_hw *dev, int if_id,
510 struct rtl8187_priv *priv = dev->priv; 510 struct rtl8187_priv *priv = dev->priv;
511 int i; 511 int i;
512 512
513 priv->if_id = if_id;
514
513 for (i = 0; i < ETH_ALEN; i++) 515 for (i = 0; i < ETH_ALEN; i++)
514 rtl818x_iowrite8(priv, &priv->map->BSSID[i], conf->bssid[i]); 516 rtl818x_iowrite8(priv, &priv->map->BSSID[i], conf->bssid[i]);
515 517
diff --git a/include/net/mac80211.h b/include/net/mac80211.h
index 91cee0f0aa71..3282038a1510 100644
--- a/include/net/mac80211.h
+++ b/include/net/mac80211.h
@@ -835,6 +835,7 @@ struct sk_buff *ieee80211_beacon_get(struct ieee80211_hw *hw,
835/** 835/**
836 * ieee80211_rts_get - RTS frame generation function 836 * ieee80211_rts_get - RTS frame generation function
837 * @hw: pointer obtained from ieee80211_alloc_hw(). 837 * @hw: pointer obtained from ieee80211_alloc_hw().
838 * @if_id: interface ID from &struct ieee80211_if_init_conf.
838 * @frame: pointer to the frame that is going to be protected by the RTS. 839 * @frame: pointer to the frame that is going to be protected by the RTS.
839 * @frame_len: the frame length (in octets). 840 * @frame_len: the frame length (in octets).
840 * @frame_txctl: &struct ieee80211_tx_control of the frame. 841 * @frame_txctl: &struct ieee80211_tx_control of the frame.
@@ -845,7 +846,7 @@ struct sk_buff *ieee80211_beacon_get(struct ieee80211_hw *hw,
845 * the next RTS frame from the 802.11 code. The low-level is responsible 846 * the next RTS frame from the 802.11 code. The low-level is responsible
846 * for calling this function before and RTS frame is needed. 847 * for calling this function before and RTS frame is needed.
847 */ 848 */
848void ieee80211_rts_get(struct ieee80211_hw *hw, 849void ieee80211_rts_get(struct ieee80211_hw *hw, int if_id,
849 const void *frame, size_t frame_len, 850 const void *frame, size_t frame_len,
850 const struct ieee80211_tx_control *frame_txctl, 851 const struct ieee80211_tx_control *frame_txctl,
851 struct ieee80211_rts *rts); 852 struct ieee80211_rts *rts);
@@ -853,6 +854,7 @@ void ieee80211_rts_get(struct ieee80211_hw *hw,
853/** 854/**
854 * ieee80211_rts_duration - Get the duration field for an RTS frame 855 * ieee80211_rts_duration - Get the duration field for an RTS frame
855 * @hw: pointer obtained from ieee80211_alloc_hw(). 856 * @hw: pointer obtained from ieee80211_alloc_hw().
857 * @if_id: interface ID from &struct ieee80211_if_init_conf.
856 * @frame_len: the length of the frame that is going to be protected by the RTS. 858 * @frame_len: the length of the frame that is going to be protected by the RTS.
857 * @frame_txctl: &struct ieee80211_tx_control of the frame. 859 * @frame_txctl: &struct ieee80211_tx_control of the frame.
858 * 860 *
@@ -860,13 +862,14 @@ void ieee80211_rts_get(struct ieee80211_hw *hw,
860 * the duration field, the low-level driver uses this function to receive 862 * the duration field, the low-level driver uses this function to receive
861 * the duration field value in little-endian byteorder. 863 * the duration field value in little-endian byteorder.
862 */ 864 */
863__le16 ieee80211_rts_duration(struct ieee80211_hw *hw, 865__le16 ieee80211_rts_duration(struct ieee80211_hw *hw, int if_id,
864 size_t frame_len, 866 size_t frame_len,
865 const struct ieee80211_tx_control *frame_txctl); 867 const struct ieee80211_tx_control *frame_txctl);
866 868
867/** 869/**
868 * ieee80211_ctstoself_get - CTS-to-self frame generation function 870 * ieee80211_ctstoself_get - CTS-to-self frame generation function
869 * @hw: pointer obtained from ieee80211_alloc_hw(). 871 * @hw: pointer obtained from ieee80211_alloc_hw().
872 * @if_id: interface ID from &struct ieee80211_if_init_conf.
870 * @frame: pointer to the frame that is going to be protected by the CTS-to-self. 873 * @frame: pointer to the frame that is going to be protected by the CTS-to-self.
871 * @frame_len: the frame length (in octets). 874 * @frame_len: the frame length (in octets).
872 * @frame_txctl: &struct ieee80211_tx_control of the frame. 875 * @frame_txctl: &struct ieee80211_tx_control of the frame.
@@ -877,7 +880,7 @@ __le16 ieee80211_rts_duration(struct ieee80211_hw *hw,
877 * the next CTS-to-self frame from the 802.11 code. The low-level is responsible 880 * the next CTS-to-self frame from the 802.11 code. The low-level is responsible
878 * for calling this function before and CTS-to-self frame is needed. 881 * for calling this function before and CTS-to-self frame is needed.
879 */ 882 */
880void ieee80211_ctstoself_get(struct ieee80211_hw *hw, 883void ieee80211_ctstoself_get(struct ieee80211_hw *hw, int if_id,
881 const void *frame, size_t frame_len, 884 const void *frame, size_t frame_len,
882 const struct ieee80211_tx_control *frame_txctl, 885 const struct ieee80211_tx_control *frame_txctl,
883 struct ieee80211_cts *cts); 886 struct ieee80211_cts *cts);
@@ -885,6 +888,7 @@ void ieee80211_ctstoself_get(struct ieee80211_hw *hw,
885/** 888/**
886 * ieee80211_ctstoself_duration - Get the duration field for a CTS-to-self frame 889 * ieee80211_ctstoself_duration - Get the duration field for a CTS-to-self frame
887 * @hw: pointer obtained from ieee80211_alloc_hw(). 890 * @hw: pointer obtained from ieee80211_alloc_hw().
891 * @if_id: interface ID from &struct ieee80211_if_init_conf.
888 * @frame_len: the length of the frame that is going to be protected by the CTS-to-self. 892 * @frame_len: the length of the frame that is going to be protected by the CTS-to-self.
889 * @frame_txctl: &struct ieee80211_tx_control of the frame. 893 * @frame_txctl: &struct ieee80211_tx_control of the frame.
890 * 894 *
@@ -892,20 +896,21 @@ void ieee80211_ctstoself_get(struct ieee80211_hw *hw,
892 * the duration field, the low-level driver uses this function to receive 896 * the duration field, the low-level driver uses this function to receive
893 * the duration field value in little-endian byteorder. 897 * the duration field value in little-endian byteorder.
894 */ 898 */
895__le16 ieee80211_ctstoself_duration(struct ieee80211_hw *hw, 899__le16 ieee80211_ctstoself_duration(struct ieee80211_hw *hw, int if_id,
896 size_t frame_len, 900 size_t frame_len,
897 const struct ieee80211_tx_control *frame_txctl); 901 const struct ieee80211_tx_control *frame_txctl);
898 902
899/** 903/**
900 * ieee80211_generic_frame_duration - Calculate the duration field for a frame 904 * ieee80211_generic_frame_duration - Calculate the duration field for a frame
901 * @hw: pointer obtained from ieee80211_alloc_hw(). 905 * @hw: pointer obtained from ieee80211_alloc_hw().
906 * @if_id: interface ID from &struct ieee80211_if_init_conf.
902 * @frame_len: the length of the frame. 907 * @frame_len: the length of the frame.
903 * @rate: the rate (in 100kbps) at which the frame is going to be transmitted. 908 * @rate: the rate (in 100kbps) at which the frame is going to be transmitted.
904 * 909 *
905 * Calculate the duration field of some generic frame, given its 910 * Calculate the duration field of some generic frame, given its
906 * length and transmission rate (in 100kbps). 911 * length and transmission rate (in 100kbps).
907 */ 912 */
908__le16 ieee80211_generic_frame_duration(struct ieee80211_hw *hw, 913__le16 ieee80211_generic_frame_duration(struct ieee80211_hw *hw, int if_id,
909 size_t frame_len, 914 size_t frame_len,
910 int rate); 915 int rate);
911 916
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index e76a58678959..b0af6e9f5319 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -127,7 +127,6 @@ struct ieee80211_txrx_data {
127 struct ieee80211_tx_control *control; 127 struct ieee80211_tx_control *control;
128 unsigned int unicast:1; 128 unsigned int unicast:1;
129 unsigned int ps_buffered:1; 129 unsigned int ps_buffered:1;
130 unsigned int short_preamble:1;
131 unsigned int probe_last_frag:1; 130 unsigned int probe_last_frag:1;
132 struct ieee80211_hw_mode *mode; 131 struct ieee80211_hw_mode *mode;
133 struct ieee80211_rate *rate; 132 struct ieee80211_rate *rate;
@@ -286,6 +285,11 @@ struct ieee80211_sub_if_data {
286 unsigned int promisc:1; 285 unsigned int promisc:1;
287 unsigned int use_protection:1; /* CTS protect ERP frames */ 286 unsigned int use_protection:1; /* CTS protect ERP frames */
288 287
288 /* use short preamble with IEEE 802.11b: this flag is set when the AP
289 * or beacon generator reports that there are no present stations that
290 * cannot support short preambles */
291 unsigned int short_preamble:1;
292
289 struct net_device_stats stats; 293 struct net_device_stats stats;
290 int drop_unencrypted; 294 int drop_unencrypted;
291 int eapol; /* 0 = process EAPOL frames as normal data frames, 295 int eapol; /* 0 = process EAPOL frames as normal data frames,
@@ -447,7 +451,6 @@ struct ieee80211_local {
447 int fragmentation_threshold; 451 int fragmentation_threshold;
448 int short_retry_limit; /* dot11ShortRetryLimit */ 452 int short_retry_limit; /* dot11ShortRetryLimit */
449 int long_retry_limit; /* dot11LongRetryLimit */ 453 int long_retry_limit; /* dot11LongRetryLimit */
450 int short_preamble; /* use short preamble with IEEE 802.11b */
451 454
452 struct crypto_blkcipher *wep_tx_tfm; 455 struct crypto_blkcipher *wep_tx_tfm;
453 struct crypto_blkcipher *wep_rx_tfm; 456 struct crypto_blkcipher *wep_rx_tfm;
diff --git a/net/mac80211/ieee80211_ioctl.c b/net/mac80211/ieee80211_ioctl.c
index e7904db55325..8292431ac48f 100644
--- a/net/mac80211/ieee80211_ioctl.c
+++ b/net/mac80211/ieee80211_ioctl.c
@@ -1061,7 +1061,10 @@ static int ieee80211_ioctl_prism2_param(struct net_device *dev,
1061 break; 1061 break;
1062 1062
1063 case PRISM2_PARAM_PREAMBLE: 1063 case PRISM2_PARAM_PREAMBLE:
1064 local->short_preamble = value; 1064 if (sdata->type != IEEE80211_IF_TYPE_AP)
1065 ret = -ENOENT;
1066 else
1067 sdata->short_preamble = value;
1065 break; 1068 break;
1066 1069
1067 case PRISM2_PARAM_STAT_TIME: 1070 case PRISM2_PARAM_STAT_TIME:
@@ -1184,7 +1187,7 @@ static int ieee80211_ioctl_get_prism2_param(struct net_device *dev,
1184 break; 1187 break;
1185 1188
1186 case PRISM2_PARAM_PREAMBLE: 1189 case PRISM2_PARAM_PREAMBLE:
1187 *param = local->short_preamble; 1190 *param = sdata->short_preamble;
1188 break; 1191 break;
1189 1192
1190 case PRISM2_PARAM_STAT_TIME: 1193 case PRISM2_PARAM_STAT_TIME:
diff --git a/net/mac80211/ieee80211_sta.c b/net/mac80211/ieee80211_sta.c
index 8e6548974a9f..0f5f8131bd71 100644
--- a/net/mac80211/ieee80211_sta.c
+++ b/net/mac80211/ieee80211_sta.c
@@ -318,6 +318,7 @@ static void ieee80211_handle_erp_ie(struct net_device *dev, u8 erp_value)
318 struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); 318 struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
319 struct ieee80211_if_sta *ifsta = &sdata->u.sta; 319 struct ieee80211_if_sta *ifsta = &sdata->u.sta;
320 int use_protection = (erp_value & WLAN_ERP_USE_PROTECTION) != 0; 320 int use_protection = (erp_value & WLAN_ERP_USE_PROTECTION) != 0;
321 int preamble_mode = (erp_value & WLAN_ERP_BARKER_PREAMBLE) != 0;
321 322
322 if (use_protection != sdata->use_protection) { 323 if (use_protection != sdata->use_protection) {
323 if (net_ratelimit()) { 324 if (net_ratelimit()) {
@@ -329,6 +330,18 @@ static void ieee80211_handle_erp_ie(struct net_device *dev, u8 erp_value)
329 } 330 }
330 sdata->use_protection = use_protection; 331 sdata->use_protection = use_protection;
331 } 332 }
333
334 if (!preamble_mode != sdata->short_preamble) {
335 if (net_ratelimit()) {
336 printk(KERN_DEBUG "%s: switched to %s barker preamble"
337 " (BSSID=" MAC_FMT ")\n",
338 dev->name,
339 (preamble_mode == WLAN_ERP_PREAMBLE_SHORT) ?
340 "short" : "long",
341 MAC_ARG(ifsta->bssid));
342 }
343 sdata->short_preamble = !preamble_mode;
344 }
332} 345}
333 346
334 347
@@ -415,6 +428,7 @@ static void ieee80211_set_associated(struct net_device *dev,
415 ieee80211_sta_send_associnfo(dev, ifsta); 428 ieee80211_sta_send_associnfo(dev, ifsta);
416 } else { 429 } else {
417 netif_carrier_off(dev); 430 netif_carrier_off(dev);
431 sdata->short_preamble = 0;
418 sdata->use_protection = 0; 432 sdata->use_protection = 0;
419 memset(wrqu.ap_addr.sa_data, 0, ETH_ALEN); 433 memset(wrqu.ap_addr.sa_data, 0, ETH_ALEN);
420 } 434 }
@@ -2281,7 +2295,7 @@ static int ieee80211_sta_join_ibss(struct net_device *dev,
2281 "for IBSS beacon\n", dev->name); 2295 "for IBSS beacon\n", dev->name);
2282 break; 2296 break;
2283 } 2297 }
2284 control.tx_rate = (local->short_preamble && 2298 control.tx_rate = (sdata->short_preamble &&
2285 (rate->flags & IEEE80211_RATE_PREAMBLE2)) ? 2299 (rate->flags & IEEE80211_RATE_PREAMBLE2)) ?
2286 rate->val2 : rate->val; 2300 rate->val2 : rate->val;
2287 control.antenna_sel_tx = local->hw.conf.antenna_sel_tx; 2301 control.antenna_sel_tx = local->hw.conf.antenna_sel_tx;
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c
index 532cf5127b70..36761c7139bc 100644
--- a/net/mac80211/tx.c
+++ b/net/mac80211/tx.c
@@ -173,7 +173,7 @@ static u16 ieee80211_duration(struct ieee80211_txrx_data *tx, int group_addr,
173 * to closest integer */ 173 * to closest integer */
174 174
175 dur = ieee80211_frame_duration(local, 10, rate, erp, 175 dur = ieee80211_frame_duration(local, 10, rate, erp,
176 local->short_preamble); 176 tx->sdata->short_preamble);
177 177
178 if (next_frag_len) { 178 if (next_frag_len) {
179 /* Frame is fragmented: duration increases with time needed to 179 /* Frame is fragmented: duration increases with time needed to
@@ -182,7 +182,7 @@ static u16 ieee80211_duration(struct ieee80211_txrx_data *tx, int group_addr,
182 /* next fragment */ 182 /* next fragment */
183 dur += ieee80211_frame_duration(local, next_frag_len, 183 dur += ieee80211_frame_duration(local, next_frag_len,
184 txrate->rate, erp, 184 txrate->rate, erp,
185 local->short_preamble); 185 tx->sdata->short_preamble);
186 } 186 }
187 187
188 return dur; 188 return dur;
@@ -627,12 +627,6 @@ ieee80211_tx_h_rate_ctrl(struct ieee80211_txrx_data *tx)
627 tx->u.tx.control->rate = tx->u.tx.rate; 627 tx->u.tx.control->rate = tx->u.tx.rate;
628 } 628 }
629 tx->u.tx.control->tx_rate = tx->u.tx.rate->val; 629 tx->u.tx.control->tx_rate = tx->u.tx.rate->val;
630 if ((tx->u.tx.rate->flags & IEEE80211_RATE_PREAMBLE2) &&
631 tx->local->short_preamble &&
632 (!tx->sta || (tx->sta->flags & WLAN_STA_SHORT_PREAMBLE))) {
633 tx->u.tx.short_preamble = 1;
634 tx->u.tx.control->tx_rate = tx->u.tx.rate->val2;
635 }
636 630
637 return TXRX_CONTINUE; 631 return TXRX_CONTINUE;
638} 632}
@@ -641,6 +635,7 @@ static ieee80211_txrx_result
641ieee80211_tx_h_misc(struct ieee80211_txrx_data *tx) 635ieee80211_tx_h_misc(struct ieee80211_txrx_data *tx)
642{ 636{
643 struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) tx->skb->data; 637 struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) tx->skb->data;
638 u16 fc = le16_to_cpu(hdr->frame_control);
644 u16 dur; 639 u16 dur;
645 struct ieee80211_tx_control *control = tx->u.tx.control; 640 struct ieee80211_tx_control *control = tx->u.tx.control;
646 struct ieee80211_hw_mode *mode = tx->u.tx.mode; 641 struct ieee80211_hw_mode *mode = tx->u.tx.mode;
@@ -677,6 +672,16 @@ ieee80211_tx_h_misc(struct ieee80211_txrx_data *tx)
677 !(control->flags & IEEE80211_TXCTL_USE_RTS_CTS)) 672 !(control->flags & IEEE80211_TXCTL_USE_RTS_CTS))
678 control->flags |= IEEE80211_TXCTL_USE_CTS_PROTECT; 673 control->flags |= IEEE80211_TXCTL_USE_CTS_PROTECT;
679 674
675 /* Transmit data frames using short preambles if the driver supports
676 * short preambles at the selected rate and short preambles are
677 * available on the network at the current point in time. */
678 if (((fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_DATA) &&
679 (tx->u.tx.rate->flags & IEEE80211_RATE_PREAMBLE2) &&
680 tx->sdata->short_preamble &&
681 (!tx->sta || (tx->sta->flags & WLAN_STA_SHORT_PREAMBLE))) {
682 tx->u.tx.control->tx_rate = tx->u.tx.rate->val2;
683 }
684
680 /* Setup duration field for the first fragment of the frame. Duration 685 /* Setup duration field for the first fragment of the frame. Duration
681 * for remaining fragments will be updated when they are being sent 686 * for remaining fragments will be updated when they are being sent
682 * to low-level driver in ieee80211_tx(). */ 687 * to low-level driver in ieee80211_tx(). */
@@ -1750,7 +1755,7 @@ struct sk_buff *ieee80211_beacon_get(struct ieee80211_hw *hw, int if_id,
1750 return NULL; 1755 return NULL;
1751 } 1756 }
1752 1757
1753 control->tx_rate = (local->short_preamble && 1758 control->tx_rate = (sdata->short_preamble &&
1754 (rate->flags & IEEE80211_RATE_PREAMBLE2)) ? 1759 (rate->flags & IEEE80211_RATE_PREAMBLE2)) ?
1755 rate->val2 : rate->val; 1760 rate->val2 : rate->val;
1756 control->antenna_sel_tx = local->hw.conf.antenna_sel_tx; 1761 control->antenna_sel_tx = local->hw.conf.antenna_sel_tx;
@@ -1765,7 +1770,7 @@ struct sk_buff *ieee80211_beacon_get(struct ieee80211_hw *hw, int if_id,
1765} 1770}
1766EXPORT_SYMBOL(ieee80211_beacon_get); 1771EXPORT_SYMBOL(ieee80211_beacon_get);
1767 1772
1768void ieee80211_rts_get(struct ieee80211_hw *hw, 1773void ieee80211_rts_get(struct ieee80211_hw *hw, int if_id,
1769 const void *frame, size_t frame_len, 1774 const void *frame, size_t frame_len,
1770 const struct ieee80211_tx_control *frame_txctl, 1775 const struct ieee80211_tx_control *frame_txctl,
1771 struct ieee80211_rts *rts) 1776 struct ieee80211_rts *rts)
@@ -1775,13 +1780,13 @@ void ieee80211_rts_get(struct ieee80211_hw *hw,
1775 1780
1776 fctl = IEEE80211_FTYPE_CTL | IEEE80211_STYPE_RTS; 1781 fctl = IEEE80211_FTYPE_CTL | IEEE80211_STYPE_RTS;
1777 rts->frame_control = cpu_to_le16(fctl); 1782 rts->frame_control = cpu_to_le16(fctl);
1778 rts->duration = ieee80211_rts_duration(hw, frame_len, frame_txctl); 1783 rts->duration = ieee80211_rts_duration(hw, if_id, frame_len, frame_txctl);
1779 memcpy(rts->ra, hdr->addr1, sizeof(rts->ra)); 1784 memcpy(rts->ra, hdr->addr1, sizeof(rts->ra));
1780 memcpy(rts->ta, hdr->addr2, sizeof(rts->ta)); 1785 memcpy(rts->ta, hdr->addr2, sizeof(rts->ta));
1781} 1786}
1782EXPORT_SYMBOL(ieee80211_rts_get); 1787EXPORT_SYMBOL(ieee80211_rts_get);
1783 1788
1784void ieee80211_ctstoself_get(struct ieee80211_hw *hw, 1789void ieee80211_ctstoself_get(struct ieee80211_hw *hw, int if_id,
1785 const void *frame, size_t frame_len, 1790 const void *frame, size_t frame_len,
1786 const struct ieee80211_tx_control *frame_txctl, 1791 const struct ieee80211_tx_control *frame_txctl,
1787 struct ieee80211_cts *cts) 1792 struct ieee80211_cts *cts)
@@ -1791,7 +1796,7 @@ void ieee80211_ctstoself_get(struct ieee80211_hw *hw,
1791 1796
1792 fctl = IEEE80211_FTYPE_CTL | IEEE80211_STYPE_CTS; 1797 fctl = IEEE80211_FTYPE_CTL | IEEE80211_STYPE_CTS;
1793 cts->frame_control = cpu_to_le16(fctl); 1798 cts->frame_control = cpu_to_le16(fctl);
1794 cts->duration = ieee80211_ctstoself_duration(hw, frame_len, frame_txctl); 1799 cts->duration = ieee80211_ctstoself_duration(hw, if_id, frame_len, frame_txctl);
1795 memcpy(cts->ra, hdr->addr1, sizeof(cts->ra)); 1800 memcpy(cts->ra, hdr->addr1, sizeof(cts->ra));
1796} 1801}
1797EXPORT_SYMBOL(ieee80211_ctstoself_get); 1802EXPORT_SYMBOL(ieee80211_ctstoself_get);
diff --git a/net/mac80211/util.c b/net/mac80211/util.c
index c45658309472..091ac0d634a5 100644
--- a/net/mac80211/util.c
+++ b/net/mac80211/util.c
@@ -314,31 +314,46 @@ int ieee80211_frame_duration(struct ieee80211_local *local, size_t len,
314} 314}
315 315
316/* Exported duration function for driver use */ 316/* Exported duration function for driver use */
317__le16 ieee80211_generic_frame_duration(struct ieee80211_hw *hw, 317__le16 ieee80211_generic_frame_duration(struct ieee80211_hw *hw, int if_id,
318 size_t frame_len, int rate) 318 size_t frame_len, int rate)
319{ 319{
320 struct ieee80211_local *local = hw_to_local(hw); 320 struct ieee80211_local *local = hw_to_local(hw);
321 struct net_device *bdev = dev_get_by_index(if_id);
322 struct ieee80211_sub_if_data *sdata;
321 u16 dur; 323 u16 dur;
322 int erp; 324 int erp;
323 325
326 if (unlikely(!bdev))
327 return 0;
328
329 sdata = IEEE80211_DEV_TO_SUB_IF(bdev);
324 erp = ieee80211_is_erp_rate(hw->conf.phymode, rate); 330 erp = ieee80211_is_erp_rate(hw->conf.phymode, rate);
325 dur = ieee80211_frame_duration(local, frame_len, rate, 331 dur = ieee80211_frame_duration(local, frame_len, rate,
326 erp, local->short_preamble); 332 erp, sdata->short_preamble);
327 333
334 dev_put(bdev);
328 return cpu_to_le16(dur); 335 return cpu_to_le16(dur);
329} 336}
330EXPORT_SYMBOL(ieee80211_generic_frame_duration); 337EXPORT_SYMBOL(ieee80211_generic_frame_duration);
331 338
332__le16 ieee80211_rts_duration(struct ieee80211_hw *hw, 339__le16 ieee80211_rts_duration(struct ieee80211_hw *hw, int if_id,
333 size_t frame_len, 340 size_t frame_len,
334 const struct ieee80211_tx_control *frame_txctl) 341 const struct ieee80211_tx_control *frame_txctl)
335{ 342{
336 struct ieee80211_local *local = hw_to_local(hw); 343 struct ieee80211_local *local = hw_to_local(hw);
337 struct ieee80211_rate *rate; 344 struct ieee80211_rate *rate;
338 int short_preamble = local->short_preamble; 345 struct net_device *bdev = dev_get_by_index(if_id);
346 struct ieee80211_sub_if_data *sdata;
347 int short_preamble;
339 int erp; 348 int erp;
340 u16 dur; 349 u16 dur;
341 350
351 if (unlikely(!bdev))
352 return 0;
353
354 sdata = IEEE80211_DEV_TO_SUB_IF(bdev);
355 short_preamble = sdata->short_preamble;
356
342 rate = frame_txctl->rts_rate; 357 rate = frame_txctl->rts_rate;
343 erp = !!(rate->flags & IEEE80211_RATE_ERP); 358 erp = !!(rate->flags & IEEE80211_RATE_ERP);
344 359
@@ -352,20 +367,29 @@ __le16 ieee80211_rts_duration(struct ieee80211_hw *hw,
352 dur += ieee80211_frame_duration(local, 10, rate->rate, 367 dur += ieee80211_frame_duration(local, 10, rate->rate,
353 erp, short_preamble); 368 erp, short_preamble);
354 369
370 dev_put(bdev);
355 return cpu_to_le16(dur); 371 return cpu_to_le16(dur);
356} 372}
357EXPORT_SYMBOL(ieee80211_rts_duration); 373EXPORT_SYMBOL(ieee80211_rts_duration);
358 374
359__le16 ieee80211_ctstoself_duration(struct ieee80211_hw *hw, 375__le16 ieee80211_ctstoself_duration(struct ieee80211_hw *hw, int if_id,
360 size_t frame_len, 376 size_t frame_len,
361 const struct ieee80211_tx_control *frame_txctl) 377 const struct ieee80211_tx_control *frame_txctl)
362{ 378{
363 struct ieee80211_local *local = hw_to_local(hw); 379 struct ieee80211_local *local = hw_to_local(hw);
364 struct ieee80211_rate *rate; 380 struct ieee80211_rate *rate;
365 int short_preamble = local->short_preamble; 381 struct net_device *bdev = dev_get_by_index(if_id);
382 struct ieee80211_sub_if_data *sdata;
383 int short_preamble;
366 int erp; 384 int erp;
367 u16 dur; 385 u16 dur;
368 386
387 if (unlikely(!bdev))
388 return 0;
389
390 sdata = IEEE80211_DEV_TO_SUB_IF(bdev);
391 short_preamble = sdata->short_preamble;
392
369 rate = frame_txctl->rts_rate; 393 rate = frame_txctl->rts_rate;
370 erp = !!(rate->flags & IEEE80211_RATE_ERP); 394 erp = !!(rate->flags & IEEE80211_RATE_ERP);
371 395
@@ -378,6 +402,7 @@ __le16 ieee80211_ctstoself_duration(struct ieee80211_hw *hw,
378 erp, short_preamble); 402 erp, short_preamble);
379 } 403 }
380 404
405 dev_put(bdev);
381 return cpu_to_le16(dur); 406 return cpu_to_le16(dur);
382} 407}
383EXPORT_SYMBOL(ieee80211_ctstoself_duration); 408EXPORT_SYMBOL(ieee80211_ctstoself_duration);