aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/rt2x00/rt2x00dev.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/wireless/rt2x00/rt2x00dev.c')
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00dev.c96
1 files changed, 83 insertions, 13 deletions
diff --git a/drivers/net/wireless/rt2x00/rt2x00dev.c b/drivers/net/wireless/rt2x00/rt2x00dev.c
index 12ee7bdedd02..f59b9f7226a8 100644
--- a/drivers/net/wireless/rt2x00/rt2x00dev.c
+++ b/drivers/net/wireless/rt2x00/rt2x00dev.c
@@ -70,6 +70,11 @@ int rt2x00lib_enable_radio(struct rt2x00_dev *rt2x00dev)
70 rt2x00lib_toggle_rx(rt2x00dev, STATE_RADIO_RX_ON); 70 rt2x00lib_toggle_rx(rt2x00dev, STATE_RADIO_RX_ON);
71 71
72 /* 72 /*
73 * Start watchdog monitoring.
74 */
75 rt2x00link_start_watchdog(rt2x00dev);
76
77 /*
73 * Start the TX queues. 78 * Start the TX queues.
74 */ 79 */
75 ieee80211_wake_queues(rt2x00dev->hw); 80 ieee80211_wake_queues(rt2x00dev->hw);
@@ -89,6 +94,11 @@ void rt2x00lib_disable_radio(struct rt2x00_dev *rt2x00dev)
89 rt2x00queue_stop_queues(rt2x00dev); 94 rt2x00queue_stop_queues(rt2x00dev);
90 95
91 /* 96 /*
97 * Stop watchdog monitoring.
98 */
99 rt2x00link_stop_watchdog(rt2x00dev);
100
101 /*
92 * Disable RX. 102 * Disable RX.
93 */ 103 */
94 rt2x00lib_toggle_rx(rt2x00dev, STATE_RADIO_RX_OFF); 104 rt2x00lib_toggle_rx(rt2x00dev, STATE_RADIO_RX_OFF);
@@ -168,10 +178,32 @@ static void rt2x00lib_intf_scheduled(struct work_struct *work)
168/* 178/*
169 * Interrupt context handlers. 179 * Interrupt context handlers.
170 */ 180 */
171static void rt2x00lib_beacondone_iter(void *data, u8 *mac, 181static void rt2x00lib_bc_buffer_iter(void *data, u8 *mac,
172 struct ieee80211_vif *vif) 182 struct ieee80211_vif *vif)
173{ 183{
174 struct rt2x00_intf *intf = vif_to_intf(vif); 184 struct rt2x00_dev *rt2x00dev = data;
185 struct sk_buff *skb;
186
187 /*
188 * Only AP mode interfaces do broad- and multicast buffering
189 */
190 if (vif->type != NL80211_IFTYPE_AP)
191 return;
192
193 /*
194 * Send out buffered broad- and multicast frames
195 */
196 skb = ieee80211_get_buffered_bc(rt2x00dev->hw, vif);
197 while (skb) {
198 rt2x00mac_tx(rt2x00dev->hw, skb);
199 skb = ieee80211_get_buffered_bc(rt2x00dev->hw, vif);
200 }
201}
202
203static void rt2x00lib_beaconupdate_iter(void *data, u8 *mac,
204 struct ieee80211_vif *vif)
205{
206 struct rt2x00_dev *rt2x00dev = data;
175 207
176 if (vif->type != NL80211_IFTYPE_AP && 208 if (vif->type != NL80211_IFTYPE_AP &&
177 vif->type != NL80211_IFTYPE_ADHOC && 209 vif->type != NL80211_IFTYPE_ADHOC &&
@@ -179,9 +211,7 @@ static void rt2x00lib_beacondone_iter(void *data, u8 *mac,
179 vif->type != NL80211_IFTYPE_WDS) 211 vif->type != NL80211_IFTYPE_WDS)
180 return; 212 return;
181 213
182 spin_lock(&intf->lock); 214 rt2x00queue_update_beacon(rt2x00dev, vif, true);
183 intf->delayed_flags |= DELAYED_UPDATE_BEACON;
184 spin_unlock(&intf->lock);
185} 215}
186 216
187void rt2x00lib_beacondone(struct rt2x00_dev *rt2x00dev) 217void rt2x00lib_beacondone(struct rt2x00_dev *rt2x00dev)
@@ -189,14 +219,37 @@ void rt2x00lib_beacondone(struct rt2x00_dev *rt2x00dev)
189 if (!test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags)) 219 if (!test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags))
190 return; 220 return;
191 221
192 ieee80211_iterate_active_interfaces_atomic(rt2x00dev->hw, 222 /* send buffered bc/mc frames out for every bssid */
193 rt2x00lib_beacondone_iter, 223 ieee80211_iterate_active_interfaces(rt2x00dev->hw,
194 rt2x00dev); 224 rt2x00lib_bc_buffer_iter,
225 rt2x00dev);
226 /*
227 * Devices with pre tbtt interrupt don't need to update the beacon
228 * here as they will fetch the next beacon directly prior to
229 * transmission.
230 */
231 if (test_bit(DRIVER_SUPPORT_PRE_TBTT_INTERRUPT, &rt2x00dev->flags))
232 return;
195 233
196 ieee80211_queue_work(rt2x00dev->hw, &rt2x00dev->intf_work); 234 /* fetch next beacon */
235 ieee80211_iterate_active_interfaces(rt2x00dev->hw,
236 rt2x00lib_beaconupdate_iter,
237 rt2x00dev);
197} 238}
198EXPORT_SYMBOL_GPL(rt2x00lib_beacondone); 239EXPORT_SYMBOL_GPL(rt2x00lib_beacondone);
199 240
241void rt2x00lib_pretbtt(struct rt2x00_dev *rt2x00dev)
242{
243 if (!test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags))
244 return;
245
246 /* fetch next beacon */
247 ieee80211_iterate_active_interfaces(rt2x00dev->hw,
248 rt2x00lib_beaconupdate_iter,
249 rt2x00dev);
250}
251EXPORT_SYMBOL_GPL(rt2x00lib_pretbtt);
252
200void rt2x00lib_txdone(struct queue_entry *entry, 253void rt2x00lib_txdone(struct queue_entry *entry,
201 struct txdone_entry_desc *txdesc) 254 struct txdone_entry_desc *txdesc)
202{ 255{
@@ -330,9 +383,17 @@ void rt2x00lib_txdone(struct queue_entry *entry,
330 * send the status report back. 383 * send the status report back.
331 */ 384 */
332 if (!(skbdesc_flags & SKBDESC_NOT_MAC80211)) 385 if (!(skbdesc_flags & SKBDESC_NOT_MAC80211))
333 ieee80211_tx_status_irqsafe(rt2x00dev->hw, entry->skb); 386 /*
387 * Only PCI and SOC devices process the tx status in process
388 * context. Hence use ieee80211_tx_status for PCI and SOC
389 * devices and stick to ieee80211_tx_status_irqsafe for USB.
390 */
391 if (rt2x00_is_usb(rt2x00dev))
392 ieee80211_tx_status_irqsafe(rt2x00dev->hw, entry->skb);
393 else
394 ieee80211_tx_status(rt2x00dev->hw, entry->skb);
334 else 395 else
335 dev_kfree_skb_irq(entry->skb); 396 dev_kfree_skb_any(entry->skb);
336 397
337 /* 398 /*
338 * Make this entry available for reuse. 399 * Make this entry available for reuse.
@@ -479,7 +540,16 @@ void rt2x00lib_rxdone(struct rt2x00_dev *rt2x00dev,
479 */ 540 */
480 rt2x00debug_dump_frame(rt2x00dev, DUMP_FRAME_RXDONE, entry->skb); 541 rt2x00debug_dump_frame(rt2x00dev, DUMP_FRAME_RXDONE, entry->skb);
481 memcpy(IEEE80211_SKB_RXCB(entry->skb), rx_status, sizeof(*rx_status)); 542 memcpy(IEEE80211_SKB_RXCB(entry->skb), rx_status, sizeof(*rx_status));
482 ieee80211_rx_irqsafe(rt2x00dev->hw, entry->skb); 543
544 /*
545 * Currently only PCI and SOC devices handle rx interrupts in process
546 * context. Hence, use ieee80211_rx_irqsafe for USB and ieee80211_rx_ni
547 * for PCI and SOC devices.
548 */
549 if (rt2x00_is_usb(rt2x00dev))
550 ieee80211_rx_irqsafe(rt2x00dev->hw, entry->skb);
551 else
552 ieee80211_rx_ni(rt2x00dev->hw, entry->skb);
483 553
484 /* 554 /*
485 * Replace the skb with the freshly allocated one. 555 * Replace the skb with the freshly allocated one.