diff options
-rw-r--r-- | drivers/net/wireless/wl12xx/acx.c | 5 | ||||
-rw-r--r-- | drivers/net/wireless/wl12xx/acx.h | 3 | ||||
-rw-r--r-- | drivers/net/wireless/wl12xx/debugfs.c | 10 | ||||
-rw-r--r-- | drivers/net/wireless/wl12xx/event.c | 4 | ||||
-rw-r--r-- | drivers/net/wireless/wl12xx/main.c | 53 | ||||
-rw-r--r-- | drivers/net/wireless/wl12xx/rx.c | 35 | ||||
-rw-r--r-- | drivers/net/wireless/wl12xx/tx.c | 67 | ||||
-rw-r--r-- | drivers/net/wireless/wl12xx/tx.h | 1 | ||||
-rw-r--r-- | drivers/net/wireless/wl12xx/wl12xx.h | 12 |
9 files changed, 109 insertions, 81 deletions
diff --git a/drivers/net/wireless/wl12xx/acx.c b/drivers/net/wireless/wl12xx/acx.c index 5b70cc19e1d4..21e74ca4ddb2 100644 --- a/drivers/net/wireless/wl12xx/acx.c +++ b/drivers/net/wireless/wl12xx/acx.c | |||
@@ -1510,10 +1510,9 @@ out: | |||
1510 | return ret; | 1510 | return ret; |
1511 | } | 1511 | } |
1512 | 1512 | ||
1513 | int wl1271_acx_ps_rx_streaming(struct wl1271 *wl, bool enable) | 1513 | int wl1271_acx_ps_rx_streaming(struct wl1271 *wl, struct wl12xx_vif *wlvif, |
1514 | bool enable) | ||
1514 | { | 1515 | { |
1515 | struct ieee80211_vif *vif = wl->vif; /* TODO: get as param */ | ||
1516 | struct wl12xx_vif *wlvif = wl12xx_vif_to_data(vif); | ||
1517 | struct wl1271_acx_ps_rx_streaming *rx_streaming; | 1516 | struct wl1271_acx_ps_rx_streaming *rx_streaming; |
1518 | u32 conf_queues, enable_queues; | 1517 | u32 conf_queues, enable_queues; |
1519 | int i, ret = 0; | 1518 | int i, ret = 0; |
diff --git a/drivers/net/wireless/wl12xx/acx.h b/drivers/net/wireless/wl12xx/acx.h index 7fccfcc55ca0..c06119b053e3 100644 --- a/drivers/net/wireless/wl12xx/acx.h +++ b/drivers/net/wireless/wl12xx/acx.h | |||
@@ -1310,7 +1310,8 @@ int wl12xx_acx_set_ba_initiator_policy(struct wl1271 *wl, | |||
1310 | int wl12xx_acx_set_ba_receiver_session(struct wl1271 *wl, u8 tid_index, | 1310 | int wl12xx_acx_set_ba_receiver_session(struct wl1271 *wl, u8 tid_index, |
1311 | u16 ssn, bool enable, u8 peer_hlid); | 1311 | u16 ssn, bool enable, u8 peer_hlid); |
1312 | int wl1271_acx_tsf_info(struct wl1271 *wl, u64 *mactime); | 1312 | int wl1271_acx_tsf_info(struct wl1271 *wl, u64 *mactime); |
1313 | int wl1271_acx_ps_rx_streaming(struct wl1271 *wl, bool enable); | 1313 | int wl1271_acx_ps_rx_streaming(struct wl1271 *wl, struct wl12xx_vif *wlvif, |
1314 | bool enable); | ||
1314 | int wl1271_acx_ap_max_tx_retry(struct wl1271 *wl, struct wl12xx_vif *wlvif); | 1315 | int wl1271_acx_ap_max_tx_retry(struct wl1271 *wl, struct wl12xx_vif *wlvif); |
1315 | int wl12xx_acx_config_ps(struct wl1271 *wl, struct wl12xx_vif *wlvif); | 1316 | int wl12xx_acx_config_ps(struct wl1271 *wl, struct wl12xx_vif *wlvif); |
1316 | int wl1271_acx_set_inconnection_sta(struct wl1271 *wl, u8 *addr); | 1317 | int wl1271_acx_set_inconnection_sta(struct wl1271 *wl, u8 *addr); |
diff --git a/drivers/net/wireless/wl12xx/debugfs.c b/drivers/net/wireless/wl12xx/debugfs.c index 669b081848e8..4abff8274ac3 100644 --- a/drivers/net/wireless/wl12xx/debugfs.c +++ b/drivers/net/wireless/wl12xx/debugfs.c | |||
@@ -505,6 +505,7 @@ static ssize_t rx_streaming_interval_write(struct file *file, | |||
505 | size_t count, loff_t *ppos) | 505 | size_t count, loff_t *ppos) |
506 | { | 506 | { |
507 | struct wl1271 *wl = file->private_data; | 507 | struct wl1271 *wl = file->private_data; |
508 | struct wl12xx_vif *wlvif; | ||
508 | unsigned long value; | 509 | unsigned long value; |
509 | int ret; | 510 | int ret; |
510 | 511 | ||
@@ -528,7 +529,9 @@ static ssize_t rx_streaming_interval_write(struct file *file, | |||
528 | if (ret < 0) | 529 | if (ret < 0) |
529 | goto out; | 530 | goto out; |
530 | 531 | ||
531 | wl1271_recalc_rx_streaming(wl); | 532 | wl12xx_for_each_wlvif_sta(wl, wlvif) { |
533 | wl1271_recalc_rx_streaming(wl, wlvif); | ||
534 | } | ||
532 | 535 | ||
533 | wl1271_ps_elp_sleep(wl); | 536 | wl1271_ps_elp_sleep(wl); |
534 | out: | 537 | out: |
@@ -557,6 +560,7 @@ static ssize_t rx_streaming_always_write(struct file *file, | |||
557 | size_t count, loff_t *ppos) | 560 | size_t count, loff_t *ppos) |
558 | { | 561 | { |
559 | struct wl1271 *wl = file->private_data; | 562 | struct wl1271 *wl = file->private_data; |
563 | struct wl12xx_vif *wlvif; | ||
560 | unsigned long value; | 564 | unsigned long value; |
561 | int ret; | 565 | int ret; |
562 | 566 | ||
@@ -580,7 +584,9 @@ static ssize_t rx_streaming_always_write(struct file *file, | |||
580 | if (ret < 0) | 584 | if (ret < 0) |
581 | goto out; | 585 | goto out; |
582 | 586 | ||
583 | wl1271_recalc_rx_streaming(wl); | 587 | wl12xx_for_each_wlvif_sta(wl, wlvif) { |
588 | wl1271_recalc_rx_streaming(wl, wlvif); | ||
589 | } | ||
584 | 590 | ||
585 | wl1271_ps_elp_sleep(wl); | 591 | wl1271_ps_elp_sleep(wl); |
586 | out: | 592 | out: |
diff --git a/drivers/net/wireless/wl12xx/event.c b/drivers/net/wireless/wl12xx/event.c index dbc40bb49bcd..be9e1121c8f8 100644 --- a/drivers/net/wireless/wl12xx/event.c +++ b/drivers/net/wireless/wl12xx/event.c | |||
@@ -220,12 +220,12 @@ static void wl12xx_event_soft_gemini_sense(struct wl1271 *wl, | |||
220 | } | 220 | } |
221 | set_bit(WL1271_FLAG_SOFT_GEMINI, &wl->flags); | 221 | set_bit(WL1271_FLAG_SOFT_GEMINI, &wl->flags); |
222 | } else { | 222 | } else { |
223 | clear_bit(WL1271_FLAG_SOFT_GEMINI, &wl->flags); | ||
223 | wl12xx_for_each_wlvif_sta(wl, wlvif) { | 224 | wl12xx_for_each_wlvif_sta(wl, wlvif) { |
224 | vif = wl12xx_wlvif_to_vif(wlvif); | 225 | vif = wl12xx_wlvif_to_vif(wlvif); |
225 | ieee80211_enable_dyn_ps(vif); | 226 | ieee80211_enable_dyn_ps(vif); |
227 | wl1271_recalc_rx_streaming(wl, wlvif); | ||
226 | } | 228 | } |
227 | clear_bit(WL1271_FLAG_SOFT_GEMINI, &wl->flags); | ||
228 | wl1271_recalc_rx_streaming(wl); | ||
229 | } | 229 | } |
230 | 230 | ||
231 | } | 231 | } |
diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/main.c index 8d87df53bbec..5ce01f1379a4 100644 --- a/drivers/net/wireless/wl12xx/main.c +++ b/drivers/net/wireless/wl12xx/main.c | |||
@@ -502,12 +502,13 @@ static int wl1271_reg_notify(struct wiphy *wiphy, | |||
502 | return 0; | 502 | return 0; |
503 | } | 503 | } |
504 | 504 | ||
505 | static int wl1271_set_rx_streaming(struct wl1271 *wl, bool enable) | 505 | static int wl1271_set_rx_streaming(struct wl1271 *wl, struct wl12xx_vif *wlvif, |
506 | bool enable) | ||
506 | { | 507 | { |
507 | int ret = 0; | 508 | int ret = 0; |
508 | 509 | ||
509 | /* we should hold wl->mutex */ | 510 | /* we should hold wl->mutex */ |
510 | ret = wl1271_acx_ps_rx_streaming(wl, enable); | 511 | ret = wl1271_acx_ps_rx_streaming(wl, wlvif, enable); |
511 | if (ret < 0) | 512 | if (ret < 0) |
512 | goto out; | 513 | goto out; |
513 | 514 | ||
@@ -523,7 +524,7 @@ out: | |||
523 | * this function is being called when the rx_streaming interval | 524 | * this function is being called when the rx_streaming interval |
524 | * has beed changed or rx_streaming should be disabled | 525 | * has beed changed or rx_streaming should be disabled |
525 | */ | 526 | */ |
526 | int wl1271_recalc_rx_streaming(struct wl1271 *wl) | 527 | int wl1271_recalc_rx_streaming(struct wl1271 *wl, struct wl12xx_vif *wlvif) |
527 | { | 528 | { |
528 | int ret = 0; | 529 | int ret = 0; |
529 | int period = wl->conf.rx_streaming.interval; | 530 | int period = wl->conf.rx_streaming.interval; |
@@ -537,11 +538,11 @@ int wl1271_recalc_rx_streaming(struct wl1271 *wl) | |||
537 | test_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags) && | 538 | test_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags) && |
538 | (wl->conf.rx_streaming.always || | 539 | (wl->conf.rx_streaming.always || |
539 | test_bit(WL1271_FLAG_SOFT_GEMINI, &wl->flags))) | 540 | test_bit(WL1271_FLAG_SOFT_GEMINI, &wl->flags))) |
540 | ret = wl1271_set_rx_streaming(wl, true); | 541 | ret = wl1271_set_rx_streaming(wl, wlvif, true); |
541 | else { | 542 | else { |
542 | ret = wl1271_set_rx_streaming(wl, false); | 543 | ret = wl1271_set_rx_streaming(wl, wlvif, false); |
543 | /* don't cancel_work_sync since we might deadlock */ | 544 | /* don't cancel_work_sync since we might deadlock */ |
544 | del_timer_sync(&wl->rx_streaming_timer); | 545 | del_timer_sync(&wlvif->rx_streaming_timer); |
545 | } | 546 | } |
546 | out: | 547 | out: |
547 | return ret; | 548 | return ret; |
@@ -550,8 +551,9 @@ out: | |||
550 | static void wl1271_rx_streaming_enable_work(struct work_struct *work) | 551 | static void wl1271_rx_streaming_enable_work(struct work_struct *work) |
551 | { | 552 | { |
552 | int ret; | 553 | int ret; |
553 | struct wl1271 *wl = | 554 | struct wl12xx_vif *wlvif = container_of(work, struct wl12xx_vif, |
554 | container_of(work, struct wl1271, rx_streaming_enable_work); | 555 | rx_streaming_enable_work); |
556 | struct wl1271 *wl = wlvif->wl; | ||
555 | 557 | ||
556 | mutex_lock(&wl->mutex); | 558 | mutex_lock(&wl->mutex); |
557 | 559 | ||
@@ -568,12 +570,12 @@ static void wl1271_rx_streaming_enable_work(struct work_struct *work) | |||
568 | if (ret < 0) | 570 | if (ret < 0) |
569 | goto out; | 571 | goto out; |
570 | 572 | ||
571 | ret = wl1271_set_rx_streaming(wl, true); | 573 | ret = wl1271_set_rx_streaming(wl, wlvif, true); |
572 | if (ret < 0) | 574 | if (ret < 0) |
573 | goto out_sleep; | 575 | goto out_sleep; |
574 | 576 | ||
575 | /* stop it after some time of inactivity */ | 577 | /* stop it after some time of inactivity */ |
576 | mod_timer(&wl->rx_streaming_timer, | 578 | mod_timer(&wlvif->rx_streaming_timer, |
577 | jiffies + msecs_to_jiffies(wl->conf.rx_streaming.duration)); | 579 | jiffies + msecs_to_jiffies(wl->conf.rx_streaming.duration)); |
578 | 580 | ||
579 | out_sleep: | 581 | out_sleep: |
@@ -585,8 +587,9 @@ out: | |||
585 | static void wl1271_rx_streaming_disable_work(struct work_struct *work) | 587 | static void wl1271_rx_streaming_disable_work(struct work_struct *work) |
586 | { | 588 | { |
587 | int ret; | 589 | int ret; |
588 | struct wl1271 *wl = | 590 | struct wl12xx_vif *wlvif = container_of(work, struct wl12xx_vif, |
589 | container_of(work, struct wl1271, rx_streaming_disable_work); | 591 | rx_streaming_disable_work); |
592 | struct wl1271 *wl = wlvif->wl; | ||
590 | 593 | ||
591 | mutex_lock(&wl->mutex); | 594 | mutex_lock(&wl->mutex); |
592 | 595 | ||
@@ -597,7 +600,7 @@ static void wl1271_rx_streaming_disable_work(struct work_struct *work) | |||
597 | if (ret < 0) | 600 | if (ret < 0) |
598 | goto out; | 601 | goto out; |
599 | 602 | ||
600 | ret = wl1271_set_rx_streaming(wl, false); | 603 | ret = wl1271_set_rx_streaming(wl, wlvif, false); |
601 | if (ret) | 604 | if (ret) |
602 | goto out_sleep; | 605 | goto out_sleep; |
603 | 606 | ||
@@ -609,8 +612,9 @@ out: | |||
609 | 612 | ||
610 | static void wl1271_rx_streaming_timer(unsigned long data) | 613 | static void wl1271_rx_streaming_timer(unsigned long data) |
611 | { | 614 | { |
612 | struct wl1271 *wl = (struct wl1271 *)data; | 615 | struct wl12xx_vif *wlvif = (struct wl12xx_vif *)data; |
613 | ieee80211_queue_work(wl->hw, &wl->rx_streaming_disable_work); | 616 | struct wl1271 *wl = wlvif->wl; |
617 | ieee80211_queue_work(wl->hw, &wlvif->rx_streaming_disable_work); | ||
614 | } | 618 | } |
615 | 619 | ||
616 | static void wl1271_conf_init(struct wl1271 *wl) | 620 | static void wl1271_conf_init(struct wl1271 *wl) |
@@ -1827,9 +1831,6 @@ static void wl1271_op_stop(struct ieee80211_hw *hw) | |||
1827 | cancel_delayed_work_sync(&wl->scan_complete_work); | 1831 | cancel_delayed_work_sync(&wl->scan_complete_work); |
1828 | cancel_work_sync(&wl->netstack_work); | 1832 | cancel_work_sync(&wl->netstack_work); |
1829 | cancel_work_sync(&wl->tx_work); | 1833 | cancel_work_sync(&wl->tx_work); |
1830 | del_timer_sync(&wl->rx_streaming_timer); | ||
1831 | cancel_work_sync(&wl->rx_streaming_enable_work); | ||
1832 | cancel_work_sync(&wl->rx_streaming_disable_work); | ||
1833 | cancel_delayed_work_sync(&wl->elp_work); | 1834 | cancel_delayed_work_sync(&wl->elp_work); |
1834 | 1835 | ||
1835 | /* let's notify MAC80211 about the remaining pending TX frames */ | 1836 | /* let's notify MAC80211 about the remaining pending TX frames */ |
@@ -1960,9 +1961,16 @@ static int wl12xx_init_vif_data(struct wl1271 *wl, struct ieee80211_vif *vif) | |||
1960 | wlvif->rate_set = CONF_TX_RATE_MASK_BASIC; | 1961 | wlvif->rate_set = CONF_TX_RATE_MASK_BASIC; |
1961 | wlvif->beacon_int = WL1271_DEFAULT_BEACON_INT; | 1962 | wlvif->beacon_int = WL1271_DEFAULT_BEACON_INT; |
1962 | 1963 | ||
1964 | INIT_WORK(&wlvif->rx_streaming_enable_work, | ||
1965 | wl1271_rx_streaming_enable_work); | ||
1966 | INIT_WORK(&wlvif->rx_streaming_disable_work, | ||
1967 | wl1271_rx_streaming_disable_work); | ||
1963 | INIT_DELAYED_WORK(&wlvif->pspoll_work, wl1271_pspoll_work); | 1968 | INIT_DELAYED_WORK(&wlvif->pspoll_work, wl1271_pspoll_work); |
1964 | INIT_LIST_HEAD(&wlvif->list); | 1969 | INIT_LIST_HEAD(&wlvif->list); |
1965 | 1970 | ||
1971 | setup_timer(&wlvif->rx_streaming_timer, wl1271_rx_streaming_timer, | ||
1972 | (unsigned long) wlvif); | ||
1973 | |||
1966 | return 0; | 1974 | return 0; |
1967 | } | 1975 | } |
1968 | 1976 | ||
@@ -2203,6 +2211,9 @@ deinit: | |||
2203 | wl->sta_count--; | 2211 | wl->sta_count--; |
2204 | 2212 | ||
2205 | mutex_unlock(&wl->mutex); | 2213 | mutex_unlock(&wl->mutex); |
2214 | del_timer_sync(&wlvif->rx_streaming_timer); | ||
2215 | cancel_work_sync(&wlvif->rx_streaming_enable_work); | ||
2216 | cancel_work_sync(&wlvif->rx_streaming_disable_work); | ||
2206 | cancel_delayed_work_sync(&wlvif->pspoll_work); | 2217 | cancel_delayed_work_sync(&wlvif->pspoll_work); |
2207 | 2218 | ||
2208 | mutex_lock(&wl->mutex); | 2219 | mutex_lock(&wl->mutex); |
@@ -4903,10 +4914,6 @@ struct ieee80211_hw *wl1271_alloc_hw(void) | |||
4903 | INIT_WORK(&wl->tx_work, wl1271_tx_work); | 4914 | INIT_WORK(&wl->tx_work, wl1271_tx_work); |
4904 | INIT_WORK(&wl->recovery_work, wl1271_recovery_work); | 4915 | INIT_WORK(&wl->recovery_work, wl1271_recovery_work); |
4905 | INIT_DELAYED_WORK(&wl->scan_complete_work, wl1271_scan_complete_work); | 4916 | INIT_DELAYED_WORK(&wl->scan_complete_work, wl1271_scan_complete_work); |
4906 | INIT_WORK(&wl->rx_streaming_enable_work, | ||
4907 | wl1271_rx_streaming_enable_work); | ||
4908 | INIT_WORK(&wl->rx_streaming_disable_work, | ||
4909 | wl1271_rx_streaming_disable_work); | ||
4910 | 4917 | ||
4911 | wl->freezable_wq = create_freezable_workqueue("wl12xx_wq"); | 4918 | wl->freezable_wq = create_freezable_workqueue("wl12xx_wq"); |
4912 | if (!wl->freezable_wq) { | 4919 | if (!wl->freezable_wq) { |
@@ -4930,8 +4937,6 @@ struct ieee80211_hw *wl1271_alloc_hw(void) | |||
4930 | wl->tx_spare_blocks = TX_HW_BLOCK_SPARE_DEFAULT; | 4937 | wl->tx_spare_blocks = TX_HW_BLOCK_SPARE_DEFAULT; |
4931 | wl->system_hlid = WL12XX_SYSTEM_HLID; | 4938 | wl->system_hlid = WL12XX_SYSTEM_HLID; |
4932 | wl->active_sta_count = 0; | 4939 | wl->active_sta_count = 0; |
4933 | setup_timer(&wl->rx_streaming_timer, wl1271_rx_streaming_timer, | ||
4934 | (unsigned long) wl); | ||
4935 | wl->fwlog_size = 0; | 4940 | wl->fwlog_size = 0; |
4936 | init_waitqueue_head(&wl->fwlog_waitq); | 4941 | init_waitqueue_head(&wl->fwlog_waitq); |
4937 | 4942 | ||
diff --git a/drivers/net/wireless/wl12xx/rx.c b/drivers/net/wireless/wl12xx/rx.c index 9cfa0b25a6f8..dd2f8b714a7f 100644 --- a/drivers/net/wireless/wl12xx/rx.c +++ b/drivers/net/wireless/wl12xx/rx.c | |||
@@ -28,6 +28,7 @@ | |||
28 | #include "acx.h" | 28 | #include "acx.h" |
29 | #include "reg.h" | 29 | #include "reg.h" |
30 | #include "rx.h" | 30 | #include "rx.h" |
31 | #include "tx.h" | ||
31 | #include "io.h" | 32 | #include "io.h" |
32 | 33 | ||
33 | static u8 wl12xx_rx_get_mem_block(struct wl12xx_fw_status *status, | 34 | static u8 wl12xx_rx_get_mem_block(struct wl12xx_fw_status *status, |
@@ -96,7 +97,7 @@ static void wl1271_rx_status(struct wl1271 *wl, | |||
96 | } | 97 | } |
97 | 98 | ||
98 | static int wl1271_rx_handle_data(struct wl1271 *wl, u8 *data, u32 length, | 99 | static int wl1271_rx_handle_data(struct wl1271 *wl, u8 *data, u32 length, |
99 | bool unaligned) | 100 | bool unaligned, u8 *hlid) |
100 | { | 101 | { |
101 | struct wl1271_rx_descriptor *desc; | 102 | struct wl1271_rx_descriptor *desc; |
102 | struct sk_buff *skb; | 103 | struct sk_buff *skb; |
@@ -159,6 +160,7 @@ static int wl1271_rx_handle_data(struct wl1271 *wl, u8 *data, u32 length, | |||
159 | * payload aligned to 4 bytes. | 160 | * payload aligned to 4 bytes. |
160 | */ | 161 | */ |
161 | memcpy(buf, data + sizeof(*desc), length - sizeof(*desc)); | 162 | memcpy(buf, data + sizeof(*desc), length - sizeof(*desc)); |
163 | *hlid = desc->hlid; | ||
162 | 164 | ||
163 | hdr = (struct ieee80211_hdr *)skb->data; | 165 | hdr = (struct ieee80211_hdr *)skb->data; |
164 | if (ieee80211_is_beacon(hdr->frame_control)) | 166 | if (ieee80211_is_beacon(hdr->frame_control)) |
@@ -169,10 +171,10 @@ static int wl1271_rx_handle_data(struct wl1271 *wl, u8 *data, u32 length, | |||
169 | wl1271_rx_status(wl, desc, IEEE80211_SKB_RXCB(skb), beacon); | 171 | wl1271_rx_status(wl, desc, IEEE80211_SKB_RXCB(skb), beacon); |
170 | 172 | ||
171 | seq_num = (le16_to_cpu(hdr->seq_ctrl) & IEEE80211_SCTL_SEQ) >> 4; | 173 | seq_num = (le16_to_cpu(hdr->seq_ctrl) & IEEE80211_SCTL_SEQ) >> 4; |
172 | wl1271_debug(DEBUG_RX, "rx skb 0x%p: %d B %s seq %d", skb, | 174 | wl1271_debug(DEBUG_RX, "rx skb 0x%p: %d B %s seq %d hlid %d", skb, |
173 | skb->len - desc->pad_len, | 175 | skb->len - desc->pad_len, |
174 | beacon ? "beacon" : "", | 176 | beacon ? "beacon" : "", |
175 | seq_num); | 177 | seq_num, *hlid); |
176 | 178 | ||
177 | skb_trim(skb, skb->len - desc->pad_len); | 179 | skb_trim(skb, skb->len - desc->pad_len); |
178 | 180 | ||
@@ -185,8 +187,7 @@ static int wl1271_rx_handle_data(struct wl1271 *wl, u8 *data, u32 length, | |||
185 | void wl12xx_rx(struct wl1271 *wl, struct wl12xx_fw_status *status) | 187 | void wl12xx_rx(struct wl1271 *wl, struct wl12xx_fw_status *status) |
186 | { | 188 | { |
187 | struct wl1271_acx_mem_map *wl_mem_map = wl->target_mem_map; | 189 | struct wl1271_acx_mem_map *wl_mem_map = wl->target_mem_map; |
188 | struct ieee80211_vif *vif = wl->vif; /* TODO: get as param */ | 190 | unsigned long active_hlids[BITS_TO_LONGS(WL12XX_MAX_LINKS)] = {0}; |
189 | struct wl12xx_vif *wlvif = wl12xx_vif_to_data(vif); | ||
190 | u32 buf_size; | 191 | u32 buf_size; |
191 | u32 fw_rx_counter = status->fw_rx_counter & NUM_RX_PKT_DESC_MOD_MASK; | 192 | u32 fw_rx_counter = status->fw_rx_counter & NUM_RX_PKT_DESC_MOD_MASK; |
192 | u32 drv_rx_counter = wl->rx_counter & NUM_RX_PKT_DESC_MOD_MASK; | 193 | u32 drv_rx_counter = wl->rx_counter & NUM_RX_PKT_DESC_MOD_MASK; |
@@ -194,8 +195,7 @@ void wl12xx_rx(struct wl1271 *wl, struct wl12xx_fw_status *status) | |||
194 | u32 mem_block; | 195 | u32 mem_block; |
195 | u32 pkt_length; | 196 | u32 pkt_length; |
196 | u32 pkt_offset; | 197 | u32 pkt_offset; |
197 | bool is_ap = (wlvif->bss_type == BSS_TYPE_AP_BSS); | 198 | u8 hlid; |
198 | bool had_data = false; | ||
199 | bool unaligned = false; | 199 | bool unaligned = false; |
200 | 200 | ||
201 | while (drv_rx_counter != fw_rx_counter) { | 201 | while (drv_rx_counter != fw_rx_counter) { |
@@ -255,8 +255,11 @@ void wl12xx_rx(struct wl1271 *wl, struct wl12xx_fw_status *status) | |||
255 | */ | 255 | */ |
256 | if (wl1271_rx_handle_data(wl, | 256 | if (wl1271_rx_handle_data(wl, |
257 | wl->aggr_buf + pkt_offset, | 257 | wl->aggr_buf + pkt_offset, |
258 | pkt_length, unaligned) == 1) | 258 | pkt_length, unaligned, |
259 | had_data = true; | 259 | &hlid) == 1) { |
260 | WARN_ON(hlid >= WL12XX_MAX_LINKS); | ||
261 | __set_bit(hlid, active_hlids); | ||
262 | } | ||
260 | 263 | ||
261 | wl->rx_counter++; | 264 | wl->rx_counter++; |
262 | drv_rx_counter++; | 265 | drv_rx_counter++; |
@@ -272,17 +275,5 @@ void wl12xx_rx(struct wl1271 *wl, struct wl12xx_fw_status *status) | |||
272 | if (wl->quirks & WL12XX_QUIRK_END_OF_TRANSACTION) | 275 | if (wl->quirks & WL12XX_QUIRK_END_OF_TRANSACTION) |
273 | wl1271_write32(wl, RX_DRIVER_COUNTER_ADDRESS, wl->rx_counter); | 276 | wl1271_write32(wl, RX_DRIVER_COUNTER_ADDRESS, wl->rx_counter); |
274 | 277 | ||
275 | if (!is_ap && wl->conf.rx_streaming.interval && had_data && | 278 | wl12xx_rearm_rx_streaming(wl, active_hlids); |
276 | (wl->conf.rx_streaming.always || | ||
277 | test_bit(WL1271_FLAG_SOFT_GEMINI, &wl->flags))) { | ||
278 | u32 timeout = wl->conf.rx_streaming.duration; | ||
279 | |||
280 | /* restart rx streaming */ | ||
281 | if (!test_bit(WL1271_FLAG_RX_STREAMING_STARTED, &wl->flags)) | ||
282 | ieee80211_queue_work(wl->hw, | ||
283 | &wl->rx_streaming_enable_work); | ||
284 | |||
285 | mod_timer(&wl->rx_streaming_timer, | ||
286 | jiffies + msecs_to_jiffies(timeout)); | ||
287 | } | ||
288 | } | 279 | } |
diff --git a/drivers/net/wireless/wl12xx/tx.c b/drivers/net/wireless/wl12xx/tx.c index 8c35d37ba600..a06aa4e8df7b 100644 --- a/drivers/net/wireless/wl12xx/tx.c +++ b/drivers/net/wireless/wl12xx/tx.c | |||
@@ -643,21 +643,58 @@ static bool wl1271_tx_is_data_present(struct sk_buff *skb) | |||
643 | return ieee80211_is_data_present(hdr->frame_control); | 643 | return ieee80211_is_data_present(hdr->frame_control); |
644 | } | 644 | } |
645 | 645 | ||
646 | void wl12xx_rearm_rx_streaming(struct wl1271 *wl, unsigned long *active_hlids) | ||
647 | { | ||
648 | struct wl12xx_vif *wlvif; | ||
649 | u32 timeout; | ||
650 | u8 hlid; | ||
651 | |||
652 | if (!wl->conf.rx_streaming.interval) | ||
653 | return; | ||
654 | |||
655 | if (!wl->conf.rx_streaming.always && | ||
656 | !test_bit(WL1271_FLAG_SOFT_GEMINI, &wl->flags)) | ||
657 | return; | ||
658 | |||
659 | timeout = wl->conf.rx_streaming.duration; | ||
660 | wl12xx_for_each_wlvif_sta(wl, wlvif) { | ||
661 | bool found = false; | ||
662 | for_each_set_bit(hlid, active_hlids, WL12XX_MAX_LINKS) { | ||
663 | if (test_bit(hlid, wlvif->links_map)) { | ||
664 | found = true; | ||
665 | break; | ||
666 | } | ||
667 | } | ||
668 | |||
669 | if (!found) | ||
670 | continue; | ||
671 | |||
672 | /* enable rx streaming */ | ||
673 | if (!test_bit(WL1271_FLAG_RX_STREAMING_STARTED, &wl->flags)) | ||
674 | ieee80211_queue_work(wl->hw, | ||
675 | &wlvif->rx_streaming_enable_work); | ||
676 | |||
677 | mod_timer(&wlvif->rx_streaming_timer, | ||
678 | jiffies + msecs_to_jiffies(timeout)); | ||
679 | } | ||
680 | } | ||
681 | |||
646 | void wl1271_tx_work_locked(struct wl1271 *wl) | 682 | void wl1271_tx_work_locked(struct wl1271 *wl) |
647 | { | 683 | { |
648 | struct wl12xx_vif *wlvif; | 684 | struct wl12xx_vif *wlvif; |
649 | struct sk_buff *skb; | 685 | struct sk_buff *skb; |
686 | struct wl1271_tx_hw_descr *desc; | ||
650 | u32 buf_offset = 0; | 687 | u32 buf_offset = 0; |
651 | bool sent_packets = false; | 688 | bool sent_packets = false; |
652 | bool had_data = false; | 689 | unsigned long active_hlids[BITS_TO_LONGS(WL12XX_MAX_LINKS)] = {0}; |
653 | /* TODO: save bitmap of relevant stations */ | ||
654 | bool is_sta = false; | ||
655 | int ret; | 690 | int ret; |
656 | 691 | ||
657 | if (unlikely(wl->state == WL1271_STATE_OFF)) | 692 | if (unlikely(wl->state == WL1271_STATE_OFF)) |
658 | return; | 693 | return; |
659 | 694 | ||
660 | while ((skb = wl1271_skb_dequeue(wl))) { | 695 | while ((skb = wl1271_skb_dequeue(wl))) { |
696 | bool has_data = false; | ||
697 | |||
661 | wlvif = NULL; | 698 | wlvif = NULL; |
662 | if (!wl12xx_is_dummy_packet(wl, skb)) { | 699 | if (!wl12xx_is_dummy_packet(wl, skb)) { |
663 | struct ieee80211_tx_info *info; | 700 | struct ieee80211_tx_info *info; |
@@ -667,9 +704,7 @@ void wl1271_tx_work_locked(struct wl1271 *wl) | |||
667 | vif = info->control.vif; | 704 | vif = info->control.vif; |
668 | wlvif = wl12xx_vif_to_data(vif); | 705 | wlvif = wl12xx_vif_to_data(vif); |
669 | } | 706 | } |
670 | 707 | has_data = wlvif && wl1271_tx_is_data_present(skb); | |
671 | if (wl1271_tx_is_data_present(skb)) | ||
672 | had_data = true; | ||
673 | 708 | ||
674 | ret = wl1271_prepare_tx_frame(wl, wlvif, skb, buf_offset); | 709 | ret = wl1271_prepare_tx_frame(wl, wlvif, skb, buf_offset); |
675 | if (ret == -EAGAIN) { | 710 | if (ret == -EAGAIN) { |
@@ -698,8 +733,10 @@ void wl1271_tx_work_locked(struct wl1271 *wl) | |||
698 | } | 733 | } |
699 | buf_offset += ret; | 734 | buf_offset += ret; |
700 | wl->tx_packets_count++; | 735 | wl->tx_packets_count++; |
701 | if (wlvif && wlvif->bss_type == BSS_TYPE_STA_BSS) | 736 | if (has_data) { |
702 | is_sta = true; | 737 | desc = (struct wl1271_tx_hw_descr *) skb->data; |
738 | __set_bit(desc->hlid, active_hlids); | ||
739 | } | ||
703 | } | 740 | } |
704 | 741 | ||
705 | out_ack: | 742 | out_ack: |
@@ -719,19 +756,7 @@ out_ack: | |||
719 | 756 | ||
720 | wl1271_handle_tx_low_watermark(wl); | 757 | wl1271_handle_tx_low_watermark(wl); |
721 | } | 758 | } |
722 | if (is_sta && wl->conf.rx_streaming.interval && had_data && | 759 | wl12xx_rearm_rx_streaming(wl, active_hlids); |
723 | (wl->conf.rx_streaming.always || | ||
724 | test_bit(WL1271_FLAG_SOFT_GEMINI, &wl->flags))) { | ||
725 | u32 timeout = wl->conf.rx_streaming.duration; | ||
726 | |||
727 | /* enable rx streaming */ | ||
728 | if (!test_bit(WL1271_FLAG_RX_STREAMING_STARTED, &wl->flags)) | ||
729 | ieee80211_queue_work(wl->hw, | ||
730 | &wl->rx_streaming_enable_work); | ||
731 | |||
732 | mod_timer(&wl->rx_streaming_timer, | ||
733 | jiffies + msecs_to_jiffies(timeout)); | ||
734 | } | ||
735 | } | 760 | } |
736 | 761 | ||
737 | void wl1271_tx_work(struct work_struct *work) | 762 | void wl1271_tx_work(struct work_struct *work) |
diff --git a/drivers/net/wireless/wl12xx/tx.h b/drivers/net/wireless/wl12xx/tx.h index fe29ff524e9a..2dbb24e6d541 100644 --- a/drivers/net/wireless/wl12xx/tx.h +++ b/drivers/net/wireless/wl12xx/tx.h | |||
@@ -220,6 +220,7 @@ u8 wl12xx_tx_get_hlid(struct wl1271 *wl, struct wl12xx_vif *wlvif, | |||
220 | void wl1271_tx_reset_link_queues(struct wl1271 *wl, u8 hlid); | 220 | void wl1271_tx_reset_link_queues(struct wl1271 *wl, u8 hlid); |
221 | void wl1271_handle_tx_low_watermark(struct wl1271 *wl); | 221 | void wl1271_handle_tx_low_watermark(struct wl1271 *wl); |
222 | bool wl12xx_is_dummy_packet(struct wl1271 *wl, struct sk_buff *skb); | 222 | bool wl12xx_is_dummy_packet(struct wl1271 *wl, struct sk_buff *skb); |
223 | void wl12xx_rearm_rx_streaming(struct wl1271 *wl, unsigned long *active_hlids); | ||
223 | 224 | ||
224 | /* from main.c */ | 225 | /* from main.c */ |
225 | void wl1271_free_sta(struct wl1271 *wl, struct wl12xx_vif *wlvif, u8 hlid); | 226 | void wl1271_free_sta(struct wl1271 *wl, struct wl12xx_vif *wlvif, u8 hlid); |
diff --git a/drivers/net/wireless/wl12xx/wl12xx.h b/drivers/net/wireless/wl12xx/wl12xx.h index d58488598d11..52d1cd0ddb6f 100644 --- a/drivers/net/wireless/wl12xx/wl12xx.h +++ b/drivers/net/wireless/wl12xx/wl12xx.h | |||
@@ -480,11 +480,6 @@ struct wl1271 { | |||
480 | /* The current band */ | 480 | /* The current band */ |
481 | enum ieee80211_band band; | 481 | enum ieee80211_band band; |
482 | 482 | ||
483 | /* Rx Streaming */ | ||
484 | struct work_struct rx_streaming_enable_work; | ||
485 | struct work_struct rx_streaming_disable_work; | ||
486 | struct timer_list rx_streaming_timer; | ||
487 | |||
488 | struct completion *elp_compl; | 483 | struct completion *elp_compl; |
489 | struct delayed_work elp_work; | 484 | struct delayed_work elp_work; |
490 | 485 | ||
@@ -635,6 +630,11 @@ struct wl12xx_vif { | |||
635 | bool ba_support; | 630 | bool ba_support; |
636 | bool ba_allowed; | 631 | bool ba_allowed; |
637 | 632 | ||
633 | /* Rx Streaming */ | ||
634 | struct work_struct rx_streaming_enable_work; | ||
635 | struct work_struct rx_streaming_disable_work; | ||
636 | struct timer_list rx_streaming_timer; | ||
637 | |||
638 | /* | 638 | /* |
639 | * This struct must be last! | 639 | * This struct must be last! |
640 | * data that has to be saved acrossed reconfigs (e.g. recovery) | 640 | * data that has to be saved acrossed reconfigs (e.g. recovery) |
@@ -681,7 +681,7 @@ struct ieee80211_vif *wl12xx_wlvif_to_vif(struct wl12xx_vif *wlvif) | |||
681 | 681 | ||
682 | int wl1271_plt_start(struct wl1271 *wl); | 682 | int wl1271_plt_start(struct wl1271 *wl); |
683 | int wl1271_plt_stop(struct wl1271 *wl); | 683 | int wl1271_plt_stop(struct wl1271 *wl); |
684 | int wl1271_recalc_rx_streaming(struct wl1271 *wl); | 684 | int wl1271_recalc_rx_streaming(struct wl1271 *wl, struct wl12xx_vif *wlvif); |
685 | void wl12xx_queue_recovery_work(struct wl1271 *wl); | 685 | void wl12xx_queue_recovery_work(struct wl1271 *wl); |
686 | size_t wl12xx_copy_fwlog(struct wl1271 *wl, u8 *memblock, size_t maxlen); | 686 | size_t wl12xx_copy_fwlog(struct wl1271 *wl, u8 *memblock, size_t maxlen); |
687 | 687 | ||