diff options
author | David S. Miller <davem@davemloft.net> | 2015-04-01 14:27:28 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2015-04-01 14:27:28 -0400 |
commit | 45eb5168873c93b4f1c3c3867fea65aad4c6abd6 (patch) | |
tree | 4949e1083f214ce51565d41614df912cba017219 /drivers/net/wireless/mwifiex | |
parent | b9600d2d0901cd0f91cb372e72bd53d22f49638d (diff) | |
parent | 9374e7d2fdcad3c36dafc8d3effd554bc702c4b6 (diff) |
Merge tag 'wireless-drivers-next-for-davem-2015-04-01' of git://git.kernel.org/pub/scm/linux/kernel/git/kvalo/wireless-drivers-next
Kalle Valo says:
====================
Major changes:
ath9k:
* add Active Interference Cancellation, a method implemented in the HW
to counter WLAN RX > sensitivity degradation when BT is transmitting
at the same time. This feature is supported by cards like WB222
based on AR9462.
iwlwifi:
* Location Aware Regulatory was added by Arik
* 8000 device family work
* update to the BT Coex firmware API
brmcfmac:
* add new BCM43455 and BCM43457 SDIO device support
* add new BCM43430 SDIO device support
wil6210:
* take care of AP bridging
* fix NAPI behavior
* found approach to achieve 4*n+2 alignment of Rx frames
rt2x00:
* add new rt2800usb device DWA 130
rtlwifi:
* add USB ID for D-Link DWA-131
* add USB ID ASUS N10 WiFi dongle
mwifiex:
* throughput enhancements
====================
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/wireless/mwifiex')
21 files changed, 714 insertions, 224 deletions
diff --git a/drivers/net/wireless/mwifiex/11n.c b/drivers/net/wireless/mwifiex/11n.c index 543148d27b01..433bd6837c79 100644 --- a/drivers/net/wireless/mwifiex/11n.c +++ b/drivers/net/wireless/mwifiex/11n.c | |||
@@ -159,6 +159,7 @@ int mwifiex_ret_11n_addba_req(struct mwifiex_private *priv, | |||
159 | int tid; | 159 | int tid; |
160 | struct host_cmd_ds_11n_addba_rsp *add_ba_rsp = &resp->params.add_ba_rsp; | 160 | struct host_cmd_ds_11n_addba_rsp *add_ba_rsp = &resp->params.add_ba_rsp; |
161 | struct mwifiex_tx_ba_stream_tbl *tx_ba_tbl; | 161 | struct mwifiex_tx_ba_stream_tbl *tx_ba_tbl; |
162 | struct mwifiex_ra_list_tbl *ra_list; | ||
162 | u16 block_ack_param_set = le16_to_cpu(add_ba_rsp->block_ack_param_set); | 163 | u16 block_ack_param_set = le16_to_cpu(add_ba_rsp->block_ack_param_set); |
163 | 164 | ||
164 | add_ba_rsp->ssn = cpu_to_le16((le16_to_cpu(add_ba_rsp->ssn)) | 165 | add_ba_rsp->ssn = cpu_to_le16((le16_to_cpu(add_ba_rsp->ssn)) |
@@ -166,7 +167,13 @@ int mwifiex_ret_11n_addba_req(struct mwifiex_private *priv, | |||
166 | 167 | ||
167 | tid = (block_ack_param_set & IEEE80211_ADDBA_PARAM_TID_MASK) | 168 | tid = (block_ack_param_set & IEEE80211_ADDBA_PARAM_TID_MASK) |
168 | >> BLOCKACKPARAM_TID_POS; | 169 | >> BLOCKACKPARAM_TID_POS; |
170 | ra_list = mwifiex_wmm_get_ralist_node(priv, tid, add_ba_rsp-> | ||
171 | peer_mac_addr); | ||
169 | if (le16_to_cpu(add_ba_rsp->status_code) != BA_RESULT_SUCCESS) { | 172 | if (le16_to_cpu(add_ba_rsp->status_code) != BA_RESULT_SUCCESS) { |
173 | if (ra_list) { | ||
174 | ra_list->ba_status = BA_SETUP_NONE; | ||
175 | ra_list->amsdu_in_ampdu = false; | ||
176 | } | ||
170 | mwifiex_del_ba_tbl(priv, tid, add_ba_rsp->peer_mac_addr, | 177 | mwifiex_del_ba_tbl(priv, tid, add_ba_rsp->peer_mac_addr, |
171 | TYPE_DELBA_SENT, true); | 178 | TYPE_DELBA_SENT, true); |
172 | if (add_ba_rsp->add_rsp_result != BA_RESULT_TIMEOUT) | 179 | if (add_ba_rsp->add_rsp_result != BA_RESULT_TIMEOUT) |
@@ -185,6 +192,10 @@ int mwifiex_ret_11n_addba_req(struct mwifiex_private *priv, | |||
185 | tx_ba_tbl->amsdu = true; | 192 | tx_ba_tbl->amsdu = true; |
186 | else | 193 | else |
187 | tx_ba_tbl->amsdu = false; | 194 | tx_ba_tbl->amsdu = false; |
195 | if (ra_list) { | ||
196 | ra_list->amsdu_in_ampdu = tx_ba_tbl->amsdu; | ||
197 | ra_list->ba_status = BA_SETUP_COMPLETE; | ||
198 | } | ||
188 | } else { | 199 | } else { |
189 | dev_err(priv->adapter->dev, "BA stream not created\n"); | 200 | dev_err(priv->adapter->dev, "BA stream not created\n"); |
190 | } | 201 | } |
@@ -515,6 +526,7 @@ void mwifiex_create_ba_tbl(struct mwifiex_private *priv, u8 *ra, int tid, | |||
515 | enum mwifiex_ba_status ba_status) | 526 | enum mwifiex_ba_status ba_status) |
516 | { | 527 | { |
517 | struct mwifiex_tx_ba_stream_tbl *new_node; | 528 | struct mwifiex_tx_ba_stream_tbl *new_node; |
529 | struct mwifiex_ra_list_tbl *ra_list; | ||
518 | unsigned long flags; | 530 | unsigned long flags; |
519 | 531 | ||
520 | if (!mwifiex_get_ba_tbl(priv, tid, ra)) { | 532 | if (!mwifiex_get_ba_tbl(priv, tid, ra)) { |
@@ -522,7 +534,11 @@ void mwifiex_create_ba_tbl(struct mwifiex_private *priv, u8 *ra, int tid, | |||
522 | GFP_ATOMIC); | 534 | GFP_ATOMIC); |
523 | if (!new_node) | 535 | if (!new_node) |
524 | return; | 536 | return; |
525 | 537 | ra_list = mwifiex_wmm_get_ralist_node(priv, tid, ra); | |
538 | if (ra_list) { | ||
539 | ra_list->ba_status = ba_status; | ||
540 | ra_list->amsdu_in_ampdu = false; | ||
541 | } | ||
526 | INIT_LIST_HEAD(&new_node->list); | 542 | INIT_LIST_HEAD(&new_node->list); |
527 | 543 | ||
528 | new_node->tid = tid; | 544 | new_node->tid = tid; |
diff --git a/drivers/net/wireless/mwifiex/11n.h b/drivers/net/wireless/mwifiex/11n.h index 8e2e39422ad8..afdd58aa90de 100644 --- a/drivers/net/wireless/mwifiex/11n.h +++ b/drivers/net/wireless/mwifiex/11n.h | |||
@@ -77,22 +77,6 @@ mwifiex_is_station_ampdu_allowed(struct mwifiex_private *priv, | |||
77 | return (node->ampdu_sta[tid] != BA_STREAM_NOT_ALLOWED) ? true : false; | 77 | return (node->ampdu_sta[tid] != BA_STREAM_NOT_ALLOWED) ? true : false; |
78 | } | 78 | } |
79 | 79 | ||
80 | /* This function checks whether AMSDU is allowed for BA stream. */ | ||
81 | static inline u8 | ||
82 | mwifiex_is_amsdu_in_ampdu_allowed(struct mwifiex_private *priv, | ||
83 | struct mwifiex_ra_list_tbl *ptr, int tid) | ||
84 | { | ||
85 | struct mwifiex_tx_ba_stream_tbl *tx_tbl; | ||
86 | |||
87 | if (is_broadcast_ether_addr(ptr->ra)) | ||
88 | return false; | ||
89 | tx_tbl = mwifiex_get_ba_tbl(priv, tid, ptr->ra); | ||
90 | if (tx_tbl) | ||
91 | return tx_tbl->amsdu; | ||
92 | |||
93 | return false; | ||
94 | } | ||
95 | |||
96 | /* This function checks whether AMPDU is allowed or not for a particular TID. */ | 80 | /* This function checks whether AMPDU is allowed or not for a particular TID. */ |
97 | static inline u8 | 81 | static inline u8 |
98 | mwifiex_is_ampdu_allowed(struct mwifiex_private *priv, | 82 | mwifiex_is_ampdu_allowed(struct mwifiex_private *priv, |
@@ -182,22 +166,6 @@ mwifiex_find_stream_to_delete(struct mwifiex_private *priv, int ptr_tid, | |||
182 | } | 166 | } |
183 | 167 | ||
184 | /* | 168 | /* |
185 | * This function checks whether BA stream is set up or not. | ||
186 | */ | ||
187 | static inline int | ||
188 | mwifiex_is_ba_stream_setup(struct mwifiex_private *priv, | ||
189 | struct mwifiex_ra_list_tbl *ptr, int tid) | ||
190 | { | ||
191 | struct mwifiex_tx_ba_stream_tbl *tx_tbl; | ||
192 | |||
193 | tx_tbl = mwifiex_get_ba_tbl(priv, tid, ptr->ra); | ||
194 | if (tx_tbl && IS_BASTREAM_SETUP(tx_tbl)) | ||
195 | return true; | ||
196 | |||
197 | return false; | ||
198 | } | ||
199 | |||
200 | /* | ||
201 | * This function checks whether associated station is 11n enabled | 169 | * This function checks whether associated station is 11n enabled |
202 | */ | 170 | */ |
203 | static inline int mwifiex_is_sta_11n_enabled(struct mwifiex_private *priv, | 171 | static inline int mwifiex_is_sta_11n_enabled(struct mwifiex_private *priv, |
diff --git a/drivers/net/wireless/mwifiex/11n_aggr.c b/drivers/net/wireless/mwifiex/11n_aggr.c index 9b983b5cebbd..6183e255e62a 100644 --- a/drivers/net/wireless/mwifiex/11n_aggr.c +++ b/drivers/net/wireless/mwifiex/11n_aggr.c | |||
@@ -170,7 +170,7 @@ mwifiex_11n_aggregate_pkt(struct mwifiex_private *priv, | |||
170 | struct mwifiex_adapter *adapter = priv->adapter; | 170 | struct mwifiex_adapter *adapter = priv->adapter; |
171 | struct sk_buff *skb_aggr, *skb_src; | 171 | struct sk_buff *skb_aggr, *skb_src; |
172 | struct mwifiex_txinfo *tx_info_aggr, *tx_info_src; | 172 | struct mwifiex_txinfo *tx_info_aggr, *tx_info_src; |
173 | int pad = 0, ret; | 173 | int pad = 0, aggr_num = 0, ret; |
174 | struct mwifiex_tx_param tx_param; | 174 | struct mwifiex_tx_param tx_param; |
175 | struct txpd *ptx_pd = NULL; | 175 | struct txpd *ptx_pd = NULL; |
176 | struct timeval tv; | 176 | struct timeval tv; |
@@ -184,7 +184,8 @@ mwifiex_11n_aggregate_pkt(struct mwifiex_private *priv, | |||
184 | } | 184 | } |
185 | 185 | ||
186 | tx_info_src = MWIFIEX_SKB_TXCB(skb_src); | 186 | tx_info_src = MWIFIEX_SKB_TXCB(skb_src); |
187 | skb_aggr = dev_alloc_skb(adapter->tx_buf_size); | 187 | skb_aggr = mwifiex_alloc_dma_align_buf(adapter->tx_buf_size, |
188 | GFP_ATOMIC | GFP_DMA); | ||
188 | if (!skb_aggr) { | 189 | if (!skb_aggr) { |
189 | dev_err(adapter->dev, "%s: alloc skb_aggr\n", __func__); | 190 | dev_err(adapter->dev, "%s: alloc skb_aggr\n", __func__); |
190 | spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock, | 191 | spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock, |
@@ -200,6 +201,7 @@ mwifiex_11n_aggregate_pkt(struct mwifiex_private *priv, | |||
200 | 201 | ||
201 | if (tx_info_src->flags & MWIFIEX_BUF_FLAG_TDLS_PKT) | 202 | if (tx_info_src->flags & MWIFIEX_BUF_FLAG_TDLS_PKT) |
202 | tx_info_aggr->flags |= MWIFIEX_BUF_FLAG_TDLS_PKT; | 203 | tx_info_aggr->flags |= MWIFIEX_BUF_FLAG_TDLS_PKT; |
204 | tx_info_aggr->flags |= MWIFIEX_BUF_FLAG_AGGR_PKT; | ||
203 | skb_aggr->priority = skb_src->priority; | 205 | skb_aggr->priority = skb_src->priority; |
204 | 206 | ||
205 | do_gettimeofday(&tv); | 207 | do_gettimeofday(&tv); |
@@ -211,11 +213,9 @@ mwifiex_11n_aggregate_pkt(struct mwifiex_private *priv, | |||
211 | break; | 213 | break; |
212 | 214 | ||
213 | skb_src = skb_dequeue(&pra_list->skb_head); | 215 | skb_src = skb_dequeue(&pra_list->skb_head); |
214 | |||
215 | pra_list->total_pkt_count--; | 216 | pra_list->total_pkt_count--; |
216 | |||
217 | atomic_dec(&priv->wmm.tx_pkts_queued); | 217 | atomic_dec(&priv->wmm.tx_pkts_queued); |
218 | 218 | aggr_num++; | |
219 | spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock, | 219 | spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock, |
220 | ra_list_flags); | 220 | ra_list_flags); |
221 | mwifiex_11n_form_amsdu_pkt(skb_aggr, skb_src, &pad); | 221 | mwifiex_11n_form_amsdu_pkt(skb_aggr, skb_src, &pad); |
@@ -251,6 +251,12 @@ mwifiex_11n_aggregate_pkt(struct mwifiex_private *priv, | |||
251 | ptx_pd = (struct txpd *)skb_aggr->data; | 251 | ptx_pd = (struct txpd *)skb_aggr->data; |
252 | 252 | ||
253 | skb_push(skb_aggr, headroom); | 253 | skb_push(skb_aggr, headroom); |
254 | tx_info_aggr->aggr_num = aggr_num * 2; | ||
255 | if (adapter->data_sent || adapter->tx_lock_flag) { | ||
256 | atomic_add(aggr_num * 2, &adapter->tx_queued); | ||
257 | skb_queue_tail(&adapter->tx_data_q, skb_aggr); | ||
258 | return 0; | ||
259 | } | ||
254 | 260 | ||
255 | if (adapter->iface_type == MWIFIEX_USB) { | 261 | if (adapter->iface_type == MWIFIEX_USB) { |
256 | adapter->data_sent = true; | 262 | adapter->data_sent = true; |
diff --git a/drivers/net/wireless/mwifiex/11n_rxreorder.c b/drivers/net/wireless/mwifiex/11n_rxreorder.c index a2e8817b56d8..f75f8acfaca0 100644 --- a/drivers/net/wireless/mwifiex/11n_rxreorder.c +++ b/drivers/net/wireless/mwifiex/11n_rxreorder.c | |||
@@ -659,6 +659,7 @@ mwifiex_del_ba_tbl(struct mwifiex_private *priv, int tid, u8 *peer_mac, | |||
659 | { | 659 | { |
660 | struct mwifiex_rx_reorder_tbl *tbl; | 660 | struct mwifiex_rx_reorder_tbl *tbl; |
661 | struct mwifiex_tx_ba_stream_tbl *ptx_tbl; | 661 | struct mwifiex_tx_ba_stream_tbl *ptx_tbl; |
662 | struct mwifiex_ra_list_tbl *ra_list; | ||
662 | u8 cleanup_rx_reorder_tbl; | 663 | u8 cleanup_rx_reorder_tbl; |
663 | unsigned long flags; | 664 | unsigned long flags; |
664 | 665 | ||
@@ -686,7 +687,11 @@ mwifiex_del_ba_tbl(struct mwifiex_private *priv, int tid, u8 *peer_mac, | |||
686 | "event: TID, RA not found in table\n"); | 687 | "event: TID, RA not found in table\n"); |
687 | return; | 688 | return; |
688 | } | 689 | } |
689 | 690 | ra_list = mwifiex_wmm_get_ralist_node(priv, tid, peer_mac); | |
691 | if (ra_list) { | ||
692 | ra_list->amsdu_in_ampdu = false; | ||
693 | ra_list->ba_status = BA_SETUP_NONE; | ||
694 | } | ||
690 | spin_lock_irqsave(&priv->tx_ba_stream_tbl_lock, flags); | 695 | spin_lock_irqsave(&priv->tx_ba_stream_tbl_lock, flags); |
691 | mwifiex_11n_delete_tx_ba_stream_tbl_entry(priv, ptx_tbl); | 696 | mwifiex_11n_delete_tx_ba_stream_tbl_entry(priv, ptx_tbl); |
692 | spin_unlock_irqrestore(&priv->tx_ba_stream_tbl_lock, flags); | 697 | spin_unlock_irqrestore(&priv->tx_ba_stream_tbl_lock, flags); |
diff --git a/drivers/net/wireless/mwifiex/cfg80211.c b/drivers/net/wireless/mwifiex/cfg80211.c index 6f8993c12373..bf9020ff2d33 100644 --- a/drivers/net/wireless/mwifiex/cfg80211.c +++ b/drivers/net/wireless/mwifiex/cfg80211.c | |||
@@ -717,6 +717,9 @@ mwifiex_cfg80211_init_p2p_go(struct mwifiex_private *priv) | |||
717 | 717 | ||
718 | static int mwifiex_deinit_priv_params(struct mwifiex_private *priv) | 718 | static int mwifiex_deinit_priv_params(struct mwifiex_private *priv) |
719 | { | 719 | { |
720 | struct mwifiex_adapter *adapter = priv->adapter; | ||
721 | unsigned long flags; | ||
722 | |||
720 | priv->mgmt_frame_mask = 0; | 723 | priv->mgmt_frame_mask = 0; |
721 | if (mwifiex_send_cmd(priv, HostCmd_CMD_MGMT_FRAME_REG, | 724 | if (mwifiex_send_cmd(priv, HostCmd_CMD_MGMT_FRAME_REG, |
722 | HostCmd_ACT_GEN_SET, 0, | 725 | HostCmd_ACT_GEN_SET, 0, |
@@ -727,6 +730,25 @@ static int mwifiex_deinit_priv_params(struct mwifiex_private *priv) | |||
727 | } | 730 | } |
728 | 731 | ||
729 | mwifiex_deauthenticate(priv, NULL); | 732 | mwifiex_deauthenticate(priv, NULL); |
733 | |||
734 | spin_lock_irqsave(&adapter->main_proc_lock, flags); | ||
735 | adapter->main_locked = true; | ||
736 | if (adapter->mwifiex_processing) { | ||
737 | spin_unlock_irqrestore(&adapter->main_proc_lock, flags); | ||
738 | flush_workqueue(adapter->workqueue); | ||
739 | } else { | ||
740 | spin_unlock_irqrestore(&adapter->main_proc_lock, flags); | ||
741 | } | ||
742 | |||
743 | spin_lock_irqsave(&adapter->rx_proc_lock, flags); | ||
744 | adapter->rx_locked = true; | ||
745 | if (adapter->rx_processing) { | ||
746 | spin_unlock_irqrestore(&adapter->rx_proc_lock, flags); | ||
747 | flush_workqueue(adapter->rx_workqueue); | ||
748 | } else { | ||
749 | spin_unlock_irqrestore(&adapter->rx_proc_lock, flags); | ||
750 | } | ||
751 | |||
730 | mwifiex_free_priv(priv); | 752 | mwifiex_free_priv(priv); |
731 | priv->wdev.iftype = NL80211_IFTYPE_UNSPECIFIED; | 753 | priv->wdev.iftype = NL80211_IFTYPE_UNSPECIFIED; |
732 | priv->bss_mode = NL80211_IFTYPE_UNSPECIFIED; | 754 | priv->bss_mode = NL80211_IFTYPE_UNSPECIFIED; |
@@ -740,6 +762,9 @@ mwifiex_init_new_priv_params(struct mwifiex_private *priv, | |||
740 | struct net_device *dev, | 762 | struct net_device *dev, |
741 | enum nl80211_iftype type) | 763 | enum nl80211_iftype type) |
742 | { | 764 | { |
765 | struct mwifiex_adapter *adapter = priv->adapter; | ||
766 | unsigned long flags; | ||
767 | |||
743 | mwifiex_init_priv(priv); | 768 | mwifiex_init_priv(priv); |
744 | 769 | ||
745 | priv->bss_mode = type; | 770 | priv->bss_mode = type; |
@@ -770,6 +795,14 @@ mwifiex_init_new_priv_params(struct mwifiex_private *priv, | |||
770 | return -EOPNOTSUPP; | 795 | return -EOPNOTSUPP; |
771 | } | 796 | } |
772 | 797 | ||
798 | spin_lock_irqsave(&adapter->main_proc_lock, flags); | ||
799 | adapter->main_locked = false; | ||
800 | spin_unlock_irqrestore(&adapter->main_proc_lock, flags); | ||
801 | |||
802 | spin_lock_irqsave(&adapter->rx_proc_lock, flags); | ||
803 | adapter->rx_locked = false; | ||
804 | spin_unlock_irqrestore(&adapter->rx_proc_lock, flags); | ||
805 | |||
773 | return 0; | 806 | return 0; |
774 | } | 807 | } |
775 | 808 | ||
@@ -2733,24 +2766,71 @@ mwifiex_is_pattern_supported(struct cfg80211_pkt_pattern *pat, s8 *byte_seq, | |||
2733 | } | 2766 | } |
2734 | 2767 | ||
2735 | #ifdef CONFIG_PM | 2768 | #ifdef CONFIG_PM |
2736 | static int mwifiex_set_mef_filter(struct mwifiex_private *priv, | 2769 | static void mwifiex_set_auto_arp_mef_entry(struct mwifiex_private *priv, |
2737 | struct cfg80211_wowlan *wowlan) | 2770 | struct mwifiex_mef_entry *mef_entry) |
2771 | { | ||
2772 | int i, filt_num = 0, num_ipv4 = 0; | ||
2773 | struct in_device *in_dev; | ||
2774 | struct in_ifaddr *ifa; | ||
2775 | __be32 ips[MWIFIEX_MAX_SUPPORTED_IPADDR]; | ||
2776 | struct mwifiex_adapter *adapter = priv->adapter; | ||
2777 | |||
2778 | mef_entry->mode = MEF_MODE_HOST_SLEEP; | ||
2779 | mef_entry->action = MEF_ACTION_AUTO_ARP; | ||
2780 | |||
2781 | /* Enable ARP offload feature */ | ||
2782 | memset(ips, 0, sizeof(ips)); | ||
2783 | for (i = 0; i < MWIFIEX_MAX_BSS_NUM; i++) { | ||
2784 | if (adapter->priv[i]->netdev) { | ||
2785 | in_dev = __in_dev_get_rtnl(adapter->priv[i]->netdev); | ||
2786 | if (!in_dev) | ||
2787 | continue; | ||
2788 | ifa = in_dev->ifa_list; | ||
2789 | if (!ifa || !ifa->ifa_local) | ||
2790 | continue; | ||
2791 | ips[i] = ifa->ifa_local; | ||
2792 | num_ipv4++; | ||
2793 | } | ||
2794 | } | ||
2795 | |||
2796 | for (i = 0; i < num_ipv4; i++) { | ||
2797 | if (!ips[i]) | ||
2798 | continue; | ||
2799 | mef_entry->filter[filt_num].repeat = 1; | ||
2800 | memcpy(mef_entry->filter[filt_num].byte_seq, | ||
2801 | (u8 *)&ips[i], sizeof(ips[i])); | ||
2802 | mef_entry->filter[filt_num]. | ||
2803 | byte_seq[MWIFIEX_MEF_MAX_BYTESEQ] = | ||
2804 | sizeof(ips[i]); | ||
2805 | mef_entry->filter[filt_num].offset = 46; | ||
2806 | mef_entry->filter[filt_num].filt_type = TYPE_EQ; | ||
2807 | if (filt_num) { | ||
2808 | mef_entry->filter[filt_num].filt_action = | ||
2809 | TYPE_OR; | ||
2810 | } | ||
2811 | filt_num++; | ||
2812 | } | ||
2813 | |||
2814 | mef_entry->filter[filt_num].repeat = 1; | ||
2815 | mef_entry->filter[filt_num].byte_seq[0] = 0x08; | ||
2816 | mef_entry->filter[filt_num].byte_seq[1] = 0x06; | ||
2817 | mef_entry->filter[filt_num].byte_seq[MWIFIEX_MEF_MAX_BYTESEQ] = 2; | ||
2818 | mef_entry->filter[filt_num].offset = 20; | ||
2819 | mef_entry->filter[filt_num].filt_type = TYPE_EQ; | ||
2820 | mef_entry->filter[filt_num].filt_action = TYPE_AND; | ||
2821 | } | ||
2822 | |||
2823 | static int mwifiex_set_wowlan_mef_entry(struct mwifiex_private *priv, | ||
2824 | struct mwifiex_ds_mef_cfg *mef_cfg, | ||
2825 | struct mwifiex_mef_entry *mef_entry, | ||
2826 | struct cfg80211_wowlan *wowlan) | ||
2738 | { | 2827 | { |
2739 | int i, filt_num = 0, ret = 0; | 2828 | int i, filt_num = 0, ret = 0; |
2740 | bool first_pat = true; | 2829 | bool first_pat = true; |
2741 | u8 byte_seq[MWIFIEX_MEF_MAX_BYTESEQ + 1]; | 2830 | u8 byte_seq[MWIFIEX_MEF_MAX_BYTESEQ + 1]; |
2742 | const u8 ipv4_mc_mac[] = {0x33, 0x33}; | 2831 | const u8 ipv4_mc_mac[] = {0x33, 0x33}; |
2743 | const u8 ipv6_mc_mac[] = {0x01, 0x00, 0x5e}; | 2832 | const u8 ipv6_mc_mac[] = {0x01, 0x00, 0x5e}; |
2744 | struct mwifiex_ds_mef_cfg mef_cfg; | ||
2745 | struct mwifiex_mef_entry *mef_entry; | ||
2746 | 2833 | ||
2747 | mef_entry = kzalloc(sizeof(*mef_entry), GFP_KERNEL); | ||
2748 | if (!mef_entry) | ||
2749 | return -ENOMEM; | ||
2750 | |||
2751 | memset(&mef_cfg, 0, sizeof(mef_cfg)); | ||
2752 | mef_cfg.num_entries = 1; | ||
2753 | mef_cfg.mef_entry = mef_entry; | ||
2754 | mef_entry->mode = MEF_MODE_HOST_SLEEP; | 2834 | mef_entry->mode = MEF_MODE_HOST_SLEEP; |
2755 | mef_entry->action = MEF_ACTION_ALLOW_AND_WAKEUP_HOST; | 2835 | mef_entry->action = MEF_ACTION_ALLOW_AND_WAKEUP_HOST; |
2756 | 2836 | ||
@@ -2767,20 +2847,19 @@ static int mwifiex_set_mef_filter(struct mwifiex_private *priv, | |||
2767 | if (!wowlan->patterns[i].pkt_offset) { | 2847 | if (!wowlan->patterns[i].pkt_offset) { |
2768 | if (!(byte_seq[0] & 0x01) && | 2848 | if (!(byte_seq[0] & 0x01) && |
2769 | (byte_seq[MWIFIEX_MEF_MAX_BYTESEQ] == 1)) { | 2849 | (byte_seq[MWIFIEX_MEF_MAX_BYTESEQ] == 1)) { |
2770 | mef_cfg.criteria |= MWIFIEX_CRITERIA_UNICAST; | 2850 | mef_cfg->criteria |= MWIFIEX_CRITERIA_UNICAST; |
2771 | continue; | 2851 | continue; |
2772 | } else if (is_broadcast_ether_addr(byte_seq)) { | 2852 | } else if (is_broadcast_ether_addr(byte_seq)) { |
2773 | mef_cfg.criteria |= MWIFIEX_CRITERIA_BROADCAST; | 2853 | mef_cfg->criteria |= MWIFIEX_CRITERIA_BROADCAST; |
2774 | continue; | 2854 | continue; |
2775 | } else if ((!memcmp(byte_seq, ipv4_mc_mac, 2) && | 2855 | } else if ((!memcmp(byte_seq, ipv4_mc_mac, 2) && |
2776 | (byte_seq[MWIFIEX_MEF_MAX_BYTESEQ] == 2)) || | 2856 | (byte_seq[MWIFIEX_MEF_MAX_BYTESEQ] == 2)) || |
2777 | (!memcmp(byte_seq, ipv6_mc_mac, 3) && | 2857 | (!memcmp(byte_seq, ipv6_mc_mac, 3) && |
2778 | (byte_seq[MWIFIEX_MEF_MAX_BYTESEQ] == 3))) { | 2858 | (byte_seq[MWIFIEX_MEF_MAX_BYTESEQ] == 3))) { |
2779 | mef_cfg.criteria |= MWIFIEX_CRITERIA_MULTICAST; | 2859 | mef_cfg->criteria |= MWIFIEX_CRITERIA_MULTICAST; |
2780 | continue; | 2860 | continue; |
2781 | } | 2861 | } |
2782 | } | 2862 | } |
2783 | |||
2784 | mef_entry->filter[filt_num].repeat = 1; | 2863 | mef_entry->filter[filt_num].repeat = 1; |
2785 | mef_entry->filter[filt_num].offset = | 2864 | mef_entry->filter[filt_num].offset = |
2786 | wowlan->patterns[i].pkt_offset; | 2865 | wowlan->patterns[i].pkt_offset; |
@@ -2797,7 +2876,7 @@ static int mwifiex_set_mef_filter(struct mwifiex_private *priv, | |||
2797 | } | 2876 | } |
2798 | 2877 | ||
2799 | if (wowlan->magic_pkt) { | 2878 | if (wowlan->magic_pkt) { |
2800 | mef_cfg.criteria |= MWIFIEX_CRITERIA_UNICAST; | 2879 | mef_cfg->criteria |= MWIFIEX_CRITERIA_UNICAST; |
2801 | mef_entry->filter[filt_num].repeat = 16; | 2880 | mef_entry->filter[filt_num].repeat = 16; |
2802 | memcpy(mef_entry->filter[filt_num].byte_seq, priv->curr_addr, | 2881 | memcpy(mef_entry->filter[filt_num].byte_seq, priv->curr_addr, |
2803 | ETH_ALEN); | 2882 | ETH_ALEN); |
@@ -2818,6 +2897,34 @@ static int mwifiex_set_mef_filter(struct mwifiex_private *priv, | |||
2818 | mef_entry->filter[filt_num].filt_type = TYPE_EQ; | 2897 | mef_entry->filter[filt_num].filt_type = TYPE_EQ; |
2819 | mef_entry->filter[filt_num].filt_action = TYPE_OR; | 2898 | mef_entry->filter[filt_num].filt_action = TYPE_OR; |
2820 | } | 2899 | } |
2900 | return ret; | ||
2901 | } | ||
2902 | |||
2903 | static int mwifiex_set_mef_filter(struct mwifiex_private *priv, | ||
2904 | struct cfg80211_wowlan *wowlan) | ||
2905 | { | ||
2906 | int ret = 0, num_entries = 1; | ||
2907 | struct mwifiex_ds_mef_cfg mef_cfg; | ||
2908 | struct mwifiex_mef_entry *mef_entry; | ||
2909 | |||
2910 | if (wowlan->n_patterns || wowlan->magic_pkt) | ||
2911 | num_entries++; | ||
2912 | |||
2913 | mef_entry = kcalloc(num_entries, sizeof(*mef_entry), GFP_KERNEL); | ||
2914 | if (!mef_entry) | ||
2915 | return -ENOMEM; | ||
2916 | |||
2917 | memset(&mef_cfg, 0, sizeof(mef_cfg)); | ||
2918 | mef_cfg.criteria |= MWIFIEX_CRITERIA_BROADCAST | | ||
2919 | MWIFIEX_CRITERIA_UNICAST; | ||
2920 | mef_cfg.num_entries = num_entries; | ||
2921 | mef_cfg.mef_entry = mef_entry; | ||
2922 | |||
2923 | mwifiex_set_auto_arp_mef_entry(priv, &mef_entry[0]); | ||
2924 | |||
2925 | if (wowlan->n_patterns || wowlan->magic_pkt) | ||
2926 | ret = mwifiex_set_wowlan_mef_entry(priv, &mef_cfg, | ||
2927 | &mef_entry[1], wowlan); | ||
2821 | 2928 | ||
2822 | if (!mef_cfg.criteria) | 2929 | if (!mef_cfg.criteria) |
2823 | mef_cfg.criteria = MWIFIEX_CRITERIA_BROADCAST | | 2930 | mef_cfg.criteria = MWIFIEX_CRITERIA_BROADCAST | |
@@ -2825,8 +2932,8 @@ static int mwifiex_set_mef_filter(struct mwifiex_private *priv, | |||
2825 | MWIFIEX_CRITERIA_MULTICAST; | 2932 | MWIFIEX_CRITERIA_MULTICAST; |
2826 | 2933 | ||
2827 | ret = mwifiex_send_cmd(priv, HostCmd_CMD_MEF_CFG, | 2934 | ret = mwifiex_send_cmd(priv, HostCmd_CMD_MEF_CFG, |
2828 | HostCmd_ACT_GEN_SET, 0, &mef_cfg, true); | 2935 | HostCmd_ACT_GEN_SET, 0, |
2829 | 2936 | &mef_cfg, true); | |
2830 | kfree(mef_entry); | 2937 | kfree(mef_entry); |
2831 | return ret; | 2938 | return ret; |
2832 | } | 2939 | } |
@@ -2836,27 +2943,33 @@ static int mwifiex_cfg80211_suspend(struct wiphy *wiphy, | |||
2836 | { | 2943 | { |
2837 | struct mwifiex_adapter *adapter = mwifiex_cfg80211_get_adapter(wiphy); | 2944 | struct mwifiex_adapter *adapter = mwifiex_cfg80211_get_adapter(wiphy); |
2838 | struct mwifiex_ds_hs_cfg hs_cfg; | 2945 | struct mwifiex_ds_hs_cfg hs_cfg; |
2839 | int ret = 0; | 2946 | int i, ret = 0; |
2840 | struct mwifiex_private *priv = | 2947 | struct mwifiex_private *priv; |
2841 | mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_STA); | 2948 | |
2949 | for (i = 0; i < adapter->priv_num; i++) { | ||
2950 | priv = adapter->priv[i]; | ||
2951 | mwifiex_abort_cac(priv); | ||
2952 | } | ||
2953 | |||
2954 | mwifiex_cancel_all_pending_cmd(adapter); | ||
2842 | 2955 | ||
2843 | if (!wowlan) { | 2956 | if (!wowlan) { |
2844 | dev_warn(adapter->dev, "None of the WOWLAN triggers enabled\n"); | 2957 | dev_warn(adapter->dev, "None of the WOWLAN triggers enabled\n"); |
2845 | return 0; | 2958 | return 0; |
2846 | } | 2959 | } |
2847 | 2960 | ||
2961 | priv = mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_STA); | ||
2962 | |||
2848 | if (!priv->media_connected) { | 2963 | if (!priv->media_connected) { |
2849 | dev_warn(adapter->dev, | 2964 | dev_warn(adapter->dev, |
2850 | "Can not configure WOWLAN in disconnected state\n"); | 2965 | "Can not configure WOWLAN in disconnected state\n"); |
2851 | return 0; | 2966 | return 0; |
2852 | } | 2967 | } |
2853 | 2968 | ||
2854 | if (wowlan->n_patterns || wowlan->magic_pkt) { | 2969 | ret = mwifiex_set_mef_filter(priv, wowlan); |
2855 | ret = mwifiex_set_mef_filter(priv, wowlan); | 2970 | if (ret) { |
2856 | if (ret) { | 2971 | dev_err(adapter->dev, "Failed to set MEF filter\n"); |
2857 | dev_err(adapter->dev, "Failed to set MEF filter\n"); | 2972 | return ret; |
2858 | return ret; | ||
2859 | } | ||
2860 | } | 2973 | } |
2861 | 2974 | ||
2862 | if (wowlan->disconnect) { | 2975 | if (wowlan->disconnect) { |
diff --git a/drivers/net/wireless/mwifiex/decl.h b/drivers/net/wireless/mwifiex/decl.h index cf2fa110e251..38f24e0427d2 100644 --- a/drivers/net/wireless/mwifiex/decl.h +++ b/drivers/net/wireless/mwifiex/decl.h | |||
@@ -83,6 +83,7 @@ | |||
83 | #define MWIFIEX_BUF_FLAG_TDLS_PKT BIT(2) | 83 | #define MWIFIEX_BUF_FLAG_TDLS_PKT BIT(2) |
84 | #define MWIFIEX_BUF_FLAG_EAPOL_TX_STATUS BIT(3) | 84 | #define MWIFIEX_BUF_FLAG_EAPOL_TX_STATUS BIT(3) |
85 | #define MWIFIEX_BUF_FLAG_ACTION_TX_STATUS BIT(4) | 85 | #define MWIFIEX_BUF_FLAG_ACTION_TX_STATUS BIT(4) |
86 | #define MWIFIEX_BUF_FLAG_AGGR_PKT BIT(5) | ||
86 | 87 | ||
87 | #define MWIFIEX_BRIDGED_PKTS_THR_HIGH 1024 | 88 | #define MWIFIEX_BRIDGED_PKTS_THR_HIGH 1024 |
88 | #define MWIFIEX_BRIDGED_PKTS_THR_LOW 128 | 89 | #define MWIFIEX_BRIDGED_PKTS_THR_LOW 128 |
@@ -111,6 +112,11 @@ | |||
111 | 112 | ||
112 | #define MWIFIEX_A_BAND_START_FREQ 5000 | 113 | #define MWIFIEX_A_BAND_START_FREQ 5000 |
113 | 114 | ||
115 | /* SDIO Aggr data packet special info */ | ||
116 | #define SDIO_MAX_AGGR_BUF_SIZE (256 * 255) | ||
117 | #define BLOCK_NUMBER_OFFSET 15 | ||
118 | #define SDIO_HEADER_OFFSET 28 | ||
119 | |||
114 | enum mwifiex_bss_type { | 120 | enum mwifiex_bss_type { |
115 | MWIFIEX_BSS_TYPE_STA = 0, | 121 | MWIFIEX_BSS_TYPE_STA = 0, |
116 | MWIFIEX_BSS_TYPE_UAP = 1, | 122 | MWIFIEX_BSS_TYPE_UAP = 1, |
@@ -168,10 +174,11 @@ struct mwifiex_wait_queue { | |||
168 | }; | 174 | }; |
169 | 175 | ||
170 | struct mwifiex_rxinfo { | 176 | struct mwifiex_rxinfo { |
177 | struct sk_buff *parent; | ||
171 | u8 bss_num; | 178 | u8 bss_num; |
172 | u8 bss_type; | 179 | u8 bss_type; |
173 | struct sk_buff *parent; | ||
174 | u8 use_count; | 180 | u8 use_count; |
181 | u8 buf_type; | ||
175 | }; | 182 | }; |
176 | 183 | ||
177 | struct mwifiex_txinfo { | 184 | struct mwifiex_txinfo { |
@@ -179,6 +186,7 @@ struct mwifiex_txinfo { | |||
179 | u8 flags; | 186 | u8 flags; |
180 | u8 bss_num; | 187 | u8 bss_num; |
181 | u8 bss_type; | 188 | u8 bss_type; |
189 | u8 aggr_num; | ||
182 | u32 pkt_len; | 190 | u32 pkt_len; |
183 | u8 ack_frame_id; | 191 | u8 ack_frame_id; |
184 | u64 cookie; | 192 | u64 cookie; |
diff --git a/drivers/net/wireless/mwifiex/fw.h b/drivers/net/wireless/mwifiex/fw.h index df553e86a0ad..59d8964dd0dc 100644 --- a/drivers/net/wireless/mwifiex/fw.h +++ b/drivers/net/wireless/mwifiex/fw.h | |||
@@ -197,6 +197,7 @@ enum MWIFIEX_802_11_PRIVACY_FILTER { | |||
197 | 197 | ||
198 | #define ISSUPP_11NENABLED(FwCapInfo) (FwCapInfo & BIT(11)) | 198 | #define ISSUPP_11NENABLED(FwCapInfo) (FwCapInfo & BIT(11)) |
199 | #define ISSUPP_TDLS_ENABLED(FwCapInfo) (FwCapInfo & BIT(14)) | 199 | #define ISSUPP_TDLS_ENABLED(FwCapInfo) (FwCapInfo & BIT(14)) |
200 | #define ISSUPP_SDIO_SPA_ENABLED(FwCapInfo) (FwCapInfo & BIT(16)) | ||
200 | 201 | ||
201 | #define MWIFIEX_DEF_HT_CAP (IEEE80211_HT_CAP_DSSSCCK40 | \ | 202 | #define MWIFIEX_DEF_HT_CAP (IEEE80211_HT_CAP_DSSSCCK40 | \ |
202 | (1 << IEEE80211_HT_CAP_RX_STBC_SHIFT) | \ | 203 | (1 << IEEE80211_HT_CAP_RX_STBC_SHIFT) | \ |
@@ -353,6 +354,7 @@ enum MWIFIEX_802_11_PRIVACY_FILTER { | |||
353 | #define HostCmd_CMD_REMAIN_ON_CHAN 0x010d | 354 | #define HostCmd_CMD_REMAIN_ON_CHAN 0x010d |
354 | #define HostCmd_CMD_11AC_CFG 0x0112 | 355 | #define HostCmd_CMD_11AC_CFG 0x0112 |
355 | #define HostCmd_CMD_TDLS_OPER 0x0122 | 356 | #define HostCmd_CMD_TDLS_OPER 0x0122 |
357 | #define HostCmd_CMD_SDIO_SP_RX_AGGR_CFG 0x0223 | ||
356 | 358 | ||
357 | #define PROTOCOL_NO_SECURITY 0x01 | 359 | #define PROTOCOL_NO_SECURITY 0x01 |
358 | #define PROTOCOL_STATIC_WEP 0x02 | 360 | #define PROTOCOL_STATIC_WEP 0x02 |
@@ -523,9 +525,11 @@ enum P2P_MODES { | |||
523 | #define TYPE_OR (MAX_OPERAND+5) | 525 | #define TYPE_OR (MAX_OPERAND+5) |
524 | #define MEF_MODE_HOST_SLEEP 1 | 526 | #define MEF_MODE_HOST_SLEEP 1 |
525 | #define MEF_ACTION_ALLOW_AND_WAKEUP_HOST 3 | 527 | #define MEF_ACTION_ALLOW_AND_WAKEUP_HOST 3 |
528 | #define MEF_ACTION_AUTO_ARP 0x10 | ||
526 | #define MWIFIEX_CRITERIA_BROADCAST BIT(0) | 529 | #define MWIFIEX_CRITERIA_BROADCAST BIT(0) |
527 | #define MWIFIEX_CRITERIA_UNICAST BIT(1) | 530 | #define MWIFIEX_CRITERIA_UNICAST BIT(1) |
528 | #define MWIFIEX_CRITERIA_MULTICAST BIT(3) | 531 | #define MWIFIEX_CRITERIA_MULTICAST BIT(3) |
532 | #define MWIFIEX_MAX_SUPPORTED_IPADDR 4 | ||
529 | 533 | ||
530 | #define ACT_TDLS_DELETE 0x00 | 534 | #define ACT_TDLS_DELETE 0x00 |
531 | #define ACT_TDLS_CREATE 0x01 | 535 | #define ACT_TDLS_CREATE 0x01 |
@@ -1240,6 +1244,12 @@ struct host_cmd_ds_chan_rpt_event { | |||
1240 | u8 tlvbuf[0]; | 1244 | u8 tlvbuf[0]; |
1241 | } __packed; | 1245 | } __packed; |
1242 | 1246 | ||
1247 | struct host_cmd_sdio_sp_rx_aggr_cfg { | ||
1248 | u8 action; | ||
1249 | u8 enable; | ||
1250 | __le16 block_size; | ||
1251 | } __packed; | ||
1252 | |||
1243 | struct mwifiex_fixed_bcn_param { | 1253 | struct mwifiex_fixed_bcn_param { |
1244 | __le64 timestamp; | 1254 | __le64 timestamp; |
1245 | __le16 beacon_period; | 1255 | __le16 beacon_period; |
@@ -1962,6 +1972,7 @@ struct host_cmd_ds_command { | |||
1962 | struct host_cmd_ds_coalesce_cfg coalesce_cfg; | 1972 | struct host_cmd_ds_coalesce_cfg coalesce_cfg; |
1963 | struct host_cmd_ds_tdls_oper tdls_oper; | 1973 | struct host_cmd_ds_tdls_oper tdls_oper; |
1964 | struct host_cmd_ds_chan_rpt_req chan_rpt_req; | 1974 | struct host_cmd_ds_chan_rpt_req chan_rpt_req; |
1975 | struct host_cmd_sdio_sp_rx_aggr_cfg sdio_rx_aggr_cfg; | ||
1965 | } params; | 1976 | } params; |
1966 | } __packed; | 1977 | } __packed; |
1967 | 1978 | ||
diff --git a/drivers/net/wireless/mwifiex/init.c b/drivers/net/wireless/mwifiex/init.c index 0153ce6d5879..e12192f5cfad 100644 --- a/drivers/net/wireless/mwifiex/init.c +++ b/drivers/net/wireless/mwifiex/init.c | |||
@@ -266,18 +266,15 @@ static void mwifiex_init_adapter(struct mwifiex_adapter *adapter) | |||
266 | 266 | ||
267 | mwifiex_wmm_init(adapter); | 267 | mwifiex_wmm_init(adapter); |
268 | 268 | ||
269 | if (adapter->sleep_cfm) { | 269 | sleep_cfm_buf = (struct mwifiex_opt_sleep_confirm *) |
270 | sleep_cfm_buf = (struct mwifiex_opt_sleep_confirm *) | 270 | adapter->sleep_cfm->data; |
271 | adapter->sleep_cfm->data; | 271 | memset(sleep_cfm_buf, 0, adapter->sleep_cfm->len); |
272 | memset(sleep_cfm_buf, 0, adapter->sleep_cfm->len); | 272 | sleep_cfm_buf->command = cpu_to_le16(HostCmd_CMD_802_11_PS_MODE_ENH); |
273 | sleep_cfm_buf->command = | 273 | sleep_cfm_buf->size = cpu_to_le16(adapter->sleep_cfm->len); |
274 | cpu_to_le16(HostCmd_CMD_802_11_PS_MODE_ENH); | 274 | sleep_cfm_buf->result = 0; |
275 | sleep_cfm_buf->size = | 275 | sleep_cfm_buf->action = cpu_to_le16(SLEEP_CONFIRM); |
276 | cpu_to_le16(adapter->sleep_cfm->len); | 276 | sleep_cfm_buf->resp_ctrl = cpu_to_le16(RESP_NEEDED); |
277 | sleep_cfm_buf->result = 0; | 277 | |
278 | sleep_cfm_buf->action = cpu_to_le16(SLEEP_CONFIRM); | ||
279 | sleep_cfm_buf->resp_ctrl = cpu_to_le16(RESP_NEEDED); | ||
280 | } | ||
281 | memset(&adapter->sleep_params, 0, sizeof(adapter->sleep_params)); | 278 | memset(&adapter->sleep_params, 0, sizeof(adapter->sleep_params)); |
282 | memset(&adapter->sleep_period, 0, sizeof(adapter->sleep_period)); | 279 | memset(&adapter->sleep_period, 0, sizeof(adapter->sleep_period)); |
283 | adapter->tx_lock_flag = false; | 280 | adapter->tx_lock_flag = false; |
@@ -481,6 +478,7 @@ int mwifiex_init_lock_list(struct mwifiex_adapter *adapter) | |||
481 | spin_lock_init(&adapter->rx_proc_lock); | 478 | spin_lock_init(&adapter->rx_proc_lock); |
482 | 479 | ||
483 | skb_queue_head_init(&adapter->rx_data_q); | 480 | skb_queue_head_init(&adapter->rx_data_q); |
481 | skb_queue_head_init(&adapter->tx_data_q); | ||
484 | 482 | ||
485 | for (i = 0; i < adapter->priv_num; ++i) { | 483 | for (i = 0; i < adapter->priv_num; ++i) { |
486 | INIT_LIST_HEAD(&adapter->bss_prio_tbl[i].bss_prio_head); | 484 | INIT_LIST_HEAD(&adapter->bss_prio_tbl[i].bss_prio_head); |
@@ -688,6 +686,10 @@ mwifiex_shutdown_drv(struct mwifiex_adapter *adapter) | |||
688 | } | 686 | } |
689 | } | 687 | } |
690 | 688 | ||
689 | atomic_set(&adapter->tx_queued, 0); | ||
690 | while ((skb = skb_dequeue(&adapter->tx_data_q))) | ||
691 | mwifiex_write_data_complete(adapter, skb, 0, 0); | ||
692 | |||
691 | spin_lock_irqsave(&adapter->rx_proc_lock, flags); | 693 | spin_lock_irqsave(&adapter->rx_proc_lock, flags); |
692 | 694 | ||
693 | while ((skb = skb_dequeue(&adapter->rx_data_q))) { | 695 | while ((skb = skb_dequeue(&adapter->rx_data_q))) { |
diff --git a/drivers/net/wireless/mwifiex/main.c b/drivers/net/wireless/mwifiex/main.c index d73a9217b9da..03a95c7d34bf 100644 --- a/drivers/net/wireless/mwifiex/main.c +++ b/drivers/net/wireless/mwifiex/main.c | |||
@@ -131,10 +131,39 @@ static int mwifiex_unregister(struct mwifiex_adapter *adapter) | |||
131 | return 0; | 131 | return 0; |
132 | } | 132 | } |
133 | 133 | ||
134 | void mwifiex_queue_main_work(struct mwifiex_adapter *adapter) | ||
135 | { | ||
136 | unsigned long flags; | ||
137 | |||
138 | spin_lock_irqsave(&adapter->main_proc_lock, flags); | ||
139 | if (adapter->mwifiex_processing) { | ||
140 | adapter->more_task_flag = true; | ||
141 | spin_unlock_irqrestore(&adapter->main_proc_lock, flags); | ||
142 | } else { | ||
143 | spin_unlock_irqrestore(&adapter->main_proc_lock, flags); | ||
144 | queue_work(adapter->workqueue, &adapter->main_work); | ||
145 | } | ||
146 | } | ||
147 | EXPORT_SYMBOL_GPL(mwifiex_queue_main_work); | ||
148 | |||
149 | static void mwifiex_queue_rx_work(struct mwifiex_adapter *adapter) | ||
150 | { | ||
151 | unsigned long flags; | ||
152 | |||
153 | spin_lock_irqsave(&adapter->rx_proc_lock, flags); | ||
154 | if (adapter->rx_processing) { | ||
155 | spin_unlock_irqrestore(&adapter->rx_proc_lock, flags); | ||
156 | } else { | ||
157 | spin_unlock_irqrestore(&adapter->rx_proc_lock, flags); | ||
158 | queue_work(adapter->rx_workqueue, &adapter->rx_work); | ||
159 | } | ||
160 | } | ||
161 | |||
134 | static int mwifiex_process_rx(struct mwifiex_adapter *adapter) | 162 | static int mwifiex_process_rx(struct mwifiex_adapter *adapter) |
135 | { | 163 | { |
136 | unsigned long flags; | 164 | unsigned long flags; |
137 | struct sk_buff *skb; | 165 | struct sk_buff *skb; |
166 | struct mwifiex_rxinfo *rx_info; | ||
138 | 167 | ||
139 | spin_lock_irqsave(&adapter->rx_proc_lock, flags); | 168 | spin_lock_irqsave(&adapter->rx_proc_lock, flags); |
140 | if (adapter->rx_processing || adapter->rx_locked) { | 169 | if (adapter->rx_processing || adapter->rx_locked) { |
@@ -154,9 +183,16 @@ static int mwifiex_process_rx(struct mwifiex_adapter *adapter) | |||
154 | if (adapter->if_ops.submit_rem_rx_urbs) | 183 | if (adapter->if_ops.submit_rem_rx_urbs) |
155 | adapter->if_ops.submit_rem_rx_urbs(adapter); | 184 | adapter->if_ops.submit_rem_rx_urbs(adapter); |
156 | adapter->delay_main_work = false; | 185 | adapter->delay_main_work = false; |
157 | queue_work(adapter->workqueue, &adapter->main_work); | 186 | mwifiex_queue_main_work(adapter); |
187 | } | ||
188 | rx_info = MWIFIEX_SKB_RXCB(skb); | ||
189 | if (rx_info->buf_type == MWIFIEX_TYPE_AGGR_DATA) { | ||
190 | if (adapter->if_ops.deaggr_pkt) | ||
191 | adapter->if_ops.deaggr_pkt(adapter, skb); | ||
192 | dev_kfree_skb_any(skb); | ||
193 | } else { | ||
194 | mwifiex_handle_rx_packet(adapter, skb); | ||
158 | } | 195 | } |
159 | mwifiex_handle_rx_packet(adapter, skb); | ||
160 | } | 196 | } |
161 | spin_lock_irqsave(&adapter->rx_proc_lock, flags); | 197 | spin_lock_irqsave(&adapter->rx_proc_lock, flags); |
162 | adapter->rx_processing = false; | 198 | adapter->rx_processing = false; |
@@ -189,7 +225,7 @@ int mwifiex_main_process(struct mwifiex_adapter *adapter) | |||
189 | spin_lock_irqsave(&adapter->main_proc_lock, flags); | 225 | spin_lock_irqsave(&adapter->main_proc_lock, flags); |
190 | 226 | ||
191 | /* Check if already processing */ | 227 | /* Check if already processing */ |
192 | if (adapter->mwifiex_processing) { | 228 | if (adapter->mwifiex_processing || adapter->main_locked) { |
193 | adapter->more_task_flag = true; | 229 | adapter->more_task_flag = true; |
194 | spin_unlock_irqrestore(&adapter->main_proc_lock, flags); | 230 | spin_unlock_irqrestore(&adapter->main_proc_lock, flags); |
195 | goto exit_main_proc; | 231 | goto exit_main_proc; |
@@ -214,9 +250,7 @@ process_start: | |||
214 | if (atomic_read(&adapter->rx_pending) >= HIGH_RX_PENDING && | 250 | if (atomic_read(&adapter->rx_pending) >= HIGH_RX_PENDING && |
215 | adapter->iface_type != MWIFIEX_USB) { | 251 | adapter->iface_type != MWIFIEX_USB) { |
216 | adapter->delay_main_work = true; | 252 | adapter->delay_main_work = true; |
217 | if (!adapter->rx_processing) | 253 | mwifiex_queue_rx_work(adapter); |
218 | queue_work(adapter->rx_workqueue, | ||
219 | &adapter->rx_work); | ||
220 | break; | 254 | break; |
221 | } | 255 | } |
222 | 256 | ||
@@ -229,13 +263,14 @@ process_start: | |||
229 | } | 263 | } |
230 | 264 | ||
231 | if (adapter->rx_work_enabled && adapter->data_received) | 265 | if (adapter->rx_work_enabled && adapter->data_received) |
232 | queue_work(adapter->rx_workqueue, &adapter->rx_work); | 266 | mwifiex_queue_rx_work(adapter); |
233 | 267 | ||
234 | /* Need to wake up the card ? */ | 268 | /* Need to wake up the card ? */ |
235 | if ((adapter->ps_state == PS_STATE_SLEEP) && | 269 | if ((adapter->ps_state == PS_STATE_SLEEP) && |
236 | (adapter->pm_wakeup_card_req && | 270 | (adapter->pm_wakeup_card_req && |
237 | !adapter->pm_wakeup_fw_try) && | 271 | !adapter->pm_wakeup_fw_try) && |
238 | (is_command_pending(adapter) || | 272 | (is_command_pending(adapter) || |
273 | !skb_queue_empty(&adapter->tx_data_q) || | ||
239 | !mwifiex_wmm_lists_empty(adapter))) { | 274 | !mwifiex_wmm_lists_empty(adapter))) { |
240 | adapter->pm_wakeup_fw_try = true; | 275 | adapter->pm_wakeup_fw_try = true; |
241 | mod_timer(&adapter->wakeup_timer, jiffies + (HZ*3)); | 276 | mod_timer(&adapter->wakeup_timer, jiffies + (HZ*3)); |
@@ -247,7 +282,7 @@ process_start: | |||
247 | if (IS_CARD_RX_RCVD(adapter)) { | 282 | if (IS_CARD_RX_RCVD(adapter)) { |
248 | adapter->data_received = false; | 283 | adapter->data_received = false; |
249 | adapter->pm_wakeup_fw_try = false; | 284 | adapter->pm_wakeup_fw_try = false; |
250 | del_timer_sync(&adapter->wakeup_timer); | 285 | del_timer(&adapter->wakeup_timer); |
251 | if (adapter->ps_state == PS_STATE_SLEEP) | 286 | if (adapter->ps_state == PS_STATE_SLEEP) |
252 | adapter->ps_state = PS_STATE_AWAKE; | 287 | adapter->ps_state = PS_STATE_AWAKE; |
253 | } else { | 288 | } else { |
@@ -260,7 +295,8 @@ process_start: | |||
260 | 295 | ||
261 | if ((!adapter->scan_chan_gap_enabled && | 296 | if ((!adapter->scan_chan_gap_enabled && |
262 | adapter->scan_processing) || adapter->data_sent || | 297 | adapter->scan_processing) || adapter->data_sent || |
263 | mwifiex_wmm_lists_empty(adapter)) { | 298 | (mwifiex_wmm_lists_empty(adapter) && |
299 | skb_queue_empty(&adapter->tx_data_q))) { | ||
264 | if (adapter->cmd_sent || adapter->curr_cmd || | 300 | if (adapter->cmd_sent || adapter->curr_cmd || |
265 | (!is_command_pending(adapter))) | 301 | (!is_command_pending(adapter))) |
266 | break; | 302 | break; |
@@ -312,6 +348,20 @@ process_start: | |||
312 | 348 | ||
313 | if ((adapter->scan_chan_gap_enabled || | 349 | if ((adapter->scan_chan_gap_enabled || |
314 | !adapter->scan_processing) && | 350 | !adapter->scan_processing) && |
351 | !adapter->data_sent && | ||
352 | !skb_queue_empty(&adapter->tx_data_q)) { | ||
353 | mwifiex_process_tx_queue(adapter); | ||
354 | if (adapter->hs_activated) { | ||
355 | adapter->is_hs_configured = false; | ||
356 | mwifiex_hs_activated_event | ||
357 | (mwifiex_get_priv | ||
358 | (adapter, MWIFIEX_BSS_ROLE_ANY), | ||
359 | false); | ||
360 | } | ||
361 | } | ||
362 | |||
363 | if ((adapter->scan_chan_gap_enabled || | ||
364 | !adapter->scan_processing) && | ||
315 | !adapter->data_sent && !mwifiex_wmm_lists_empty(adapter)) { | 365 | !adapter->data_sent && !mwifiex_wmm_lists_empty(adapter)) { |
316 | mwifiex_wmm_process_tx(adapter); | 366 | mwifiex_wmm_process_tx(adapter); |
317 | if (adapter->hs_activated) { | 367 | if (adapter->hs_activated) { |
@@ -325,7 +375,8 @@ process_start: | |||
325 | 375 | ||
326 | if (adapter->delay_null_pkt && !adapter->cmd_sent && | 376 | if (adapter->delay_null_pkt && !adapter->cmd_sent && |
327 | !adapter->curr_cmd && !is_command_pending(adapter) && | 377 | !adapter->curr_cmd && !is_command_pending(adapter) && |
328 | mwifiex_wmm_lists_empty(adapter)) { | 378 | (mwifiex_wmm_lists_empty(adapter) && |
379 | skb_queue_empty(&adapter->tx_data_q))) { | ||
329 | if (!mwifiex_send_null_packet | 380 | if (!mwifiex_send_null_packet |
330 | (mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_STA), | 381 | (mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_STA), |
331 | MWIFIEX_TxPD_POWER_MGMT_NULL_PACKET | | 382 | MWIFIEX_TxPD_POWER_MGMT_NULL_PACKET | |
@@ -606,7 +657,7 @@ int mwifiex_queue_tx_pkt(struct mwifiex_private *priv, struct sk_buff *skb) | |||
606 | atomic_inc(&priv->adapter->tx_pending); | 657 | atomic_inc(&priv->adapter->tx_pending); |
607 | mwifiex_wmm_add_buf_txqueue(priv, skb); | 658 | mwifiex_wmm_add_buf_txqueue(priv, skb); |
608 | 659 | ||
609 | queue_work(priv->adapter->workqueue, &priv->adapter->main_work); | 660 | mwifiex_queue_main_work(priv->adapter); |
610 | 661 | ||
611 | return 0; | 662 | return 0; |
612 | } | 663 | } |
@@ -1098,9 +1149,6 @@ mwifiex_add_card(void *card, struct semaphore *sem, | |||
1098 | INIT_WORK(&adapter->rx_work, mwifiex_rx_work_queue); | 1149 | INIT_WORK(&adapter->rx_work, mwifiex_rx_work_queue); |
1099 | } | 1150 | } |
1100 | 1151 | ||
1101 | if (adapter->if_ops.iface_work) | ||
1102 | INIT_WORK(&adapter->iface_work, adapter->if_ops.iface_work); | ||
1103 | |||
1104 | /* Register the device. Fill up the private data structure with relevant | 1152 | /* Register the device. Fill up the private data structure with relevant |
1105 | information from the card. */ | 1153 | information from the card. */ |
1106 | if (adapter->if_ops.register_dev(adapter)) { | 1154 | if (adapter->if_ops.register_dev(adapter)) { |
diff --git a/drivers/net/wireless/mwifiex/main.h b/drivers/net/wireless/mwifiex/main.h index ad8db61aeeef..fe1256044a6c 100644 --- a/drivers/net/wireless/mwifiex/main.h +++ b/drivers/net/wireless/mwifiex/main.h | |||
@@ -35,6 +35,7 @@ | |||
35 | #include <linux/ctype.h> | 35 | #include <linux/ctype.h> |
36 | #include <linux/of.h> | 36 | #include <linux/of.h> |
37 | #include <linux/idr.h> | 37 | #include <linux/idr.h> |
38 | #include <linux/inetdevice.h> | ||
38 | 39 | ||
39 | #include "decl.h" | 40 | #include "decl.h" |
40 | #include "ioctl.h" | 41 | #include "ioctl.h" |
@@ -58,6 +59,8 @@ enum { | |||
58 | 59 | ||
59 | #define MWIFIEX_MAX_AP 64 | 60 | #define MWIFIEX_MAX_AP 64 |
60 | 61 | ||
62 | #define MWIFIEX_MAX_PKTS_TXQ 16 | ||
63 | |||
61 | #define MWIFIEX_DEFAULT_WATCHDOG_TIMEOUT (5 * HZ) | 64 | #define MWIFIEX_DEFAULT_WATCHDOG_TIMEOUT (5 * HZ) |
62 | 65 | ||
63 | #define MWIFIEX_TIMER_10S 10000 | 66 | #define MWIFIEX_TIMER_10S 10000 |
@@ -118,6 +121,7 @@ enum { | |||
118 | 121 | ||
119 | #define MWIFIEX_TYPE_CMD 1 | 122 | #define MWIFIEX_TYPE_CMD 1 |
120 | #define MWIFIEX_TYPE_DATA 0 | 123 | #define MWIFIEX_TYPE_DATA 0 |
124 | #define MWIFIEX_TYPE_AGGR_DATA 10 | ||
121 | #define MWIFIEX_TYPE_EVENT 3 | 125 | #define MWIFIEX_TYPE_EVENT 3 |
122 | 126 | ||
123 | #define MAX_BITMAP_RATES_SIZE 18 | 127 | #define MAX_BITMAP_RATES_SIZE 18 |
@@ -210,6 +214,12 @@ struct mwifiex_tx_aggr { | |||
210 | u8 amsdu; | 214 | u8 amsdu; |
211 | }; | 215 | }; |
212 | 216 | ||
217 | enum mwifiex_ba_status { | ||
218 | BA_SETUP_NONE = 0, | ||
219 | BA_SETUP_INPROGRESS, | ||
220 | BA_SETUP_COMPLETE | ||
221 | }; | ||
222 | |||
213 | struct mwifiex_ra_list_tbl { | 223 | struct mwifiex_ra_list_tbl { |
214 | struct list_head list; | 224 | struct list_head list; |
215 | struct sk_buff_head skb_head; | 225 | struct sk_buff_head skb_head; |
@@ -218,6 +228,8 @@ struct mwifiex_ra_list_tbl { | |||
218 | u16 max_amsdu; | 228 | u16 max_amsdu; |
219 | u16 ba_pkt_count; | 229 | u16 ba_pkt_count; |
220 | u8 ba_packet_thr; | 230 | u8 ba_packet_thr; |
231 | enum mwifiex_ba_status ba_status; | ||
232 | u8 amsdu_in_ampdu; | ||
221 | u16 total_pkt_count; | 233 | u16 total_pkt_count; |
222 | bool tdls_link; | 234 | bool tdls_link; |
223 | }; | 235 | }; |
@@ -601,11 +613,6 @@ struct mwifiex_private { | |||
601 | struct mwifiex_11h_intf_state state_11h; | 613 | struct mwifiex_11h_intf_state state_11h; |
602 | }; | 614 | }; |
603 | 615 | ||
604 | enum mwifiex_ba_status { | ||
605 | BA_SETUP_NONE = 0, | ||
606 | BA_SETUP_INPROGRESS, | ||
607 | BA_SETUP_COMPLETE | ||
608 | }; | ||
609 | 616 | ||
610 | struct mwifiex_tx_ba_stream_tbl { | 617 | struct mwifiex_tx_ba_stream_tbl { |
611 | struct list_head list; | 618 | struct list_head list; |
@@ -738,6 +745,7 @@ struct mwifiex_if_ops { | |||
738 | int (*clean_pcie_ring) (struct mwifiex_adapter *adapter); | 745 | int (*clean_pcie_ring) (struct mwifiex_adapter *adapter); |
739 | void (*iface_work)(struct work_struct *work); | 746 | void (*iface_work)(struct work_struct *work); |
740 | void (*submit_rem_rx_urbs)(struct mwifiex_adapter *adapter); | 747 | void (*submit_rem_rx_urbs)(struct mwifiex_adapter *adapter); |
748 | void (*deaggr_pkt)(struct mwifiex_adapter *, struct sk_buff *); | ||
741 | }; | 749 | }; |
742 | 750 | ||
743 | struct mwifiex_adapter { | 751 | struct mwifiex_adapter { |
@@ -771,6 +779,7 @@ struct mwifiex_adapter { | |||
771 | bool rx_processing; | 779 | bool rx_processing; |
772 | bool delay_main_work; | 780 | bool delay_main_work; |
773 | bool rx_locked; | 781 | bool rx_locked; |
782 | bool main_locked; | ||
774 | struct mwifiex_bss_prio_tbl bss_prio_tbl[MWIFIEX_MAX_BSS_NUM]; | 783 | struct mwifiex_bss_prio_tbl bss_prio_tbl[MWIFIEX_MAX_BSS_NUM]; |
775 | /* spin lock for init/shutdown */ | 784 | /* spin lock for init/shutdown */ |
776 | spinlock_t mwifiex_lock; | 785 | spinlock_t mwifiex_lock; |
@@ -780,6 +789,8 @@ struct mwifiex_adapter { | |||
780 | u8 more_task_flag; | 789 | u8 more_task_flag; |
781 | u16 tx_buf_size; | 790 | u16 tx_buf_size; |
782 | u16 curr_tx_buf_size; | 791 | u16 curr_tx_buf_size; |
792 | bool sdio_rx_aggr_enable; | ||
793 | u16 sdio_rx_block_size; | ||
783 | u32 ioport; | 794 | u32 ioport; |
784 | enum MWIFIEX_HARDWARE_STATUS hw_status; | 795 | enum MWIFIEX_HARDWARE_STATUS hw_status; |
785 | u16 number_of_antenna; | 796 | u16 number_of_antenna; |
@@ -814,6 +825,8 @@ struct mwifiex_adapter { | |||
814 | spinlock_t scan_pending_q_lock; | 825 | spinlock_t scan_pending_q_lock; |
815 | /* spin lock for RX processing routine */ | 826 | /* spin lock for RX processing routine */ |
816 | spinlock_t rx_proc_lock; | 827 | spinlock_t rx_proc_lock; |
828 | struct sk_buff_head tx_data_q; | ||
829 | atomic_t tx_queued; | ||
817 | u32 scan_processing; | 830 | u32 scan_processing; |
818 | u16 region_code; | 831 | u16 region_code; |
819 | struct mwifiex_802_11d_domain_reg domain_reg; | 832 | struct mwifiex_802_11d_domain_reg domain_reg; |
@@ -885,8 +898,6 @@ struct mwifiex_adapter { | |||
885 | bool ext_scan; | 898 | bool ext_scan; |
886 | u8 fw_api_ver; | 899 | u8 fw_api_ver; |
887 | u8 key_api_major_ver, key_api_minor_ver; | 900 | u8 key_api_major_ver, key_api_minor_ver; |
888 | struct work_struct iface_work; | ||
889 | unsigned long iface_work_flags; | ||
890 | struct memory_type_mapping *mem_type_mapping_tbl; | 901 | struct memory_type_mapping *mem_type_mapping_tbl; |
891 | u8 num_mem_types; | 902 | u8 num_mem_types; |
892 | u8 curr_mem_idx; | 903 | u8 curr_mem_idx; |
@@ -900,6 +911,8 @@ struct mwifiex_adapter { | |||
900 | bool auto_tdls; | 911 | bool auto_tdls; |
901 | }; | 912 | }; |
902 | 913 | ||
914 | void mwifiex_process_tx_queue(struct mwifiex_adapter *adapter); | ||
915 | |||
903 | int mwifiex_init_lock_list(struct mwifiex_adapter *adapter); | 916 | int mwifiex_init_lock_list(struct mwifiex_adapter *adapter); |
904 | 917 | ||
905 | void mwifiex_set_trans_start(struct net_device *dev); | 918 | void mwifiex_set_trans_start(struct net_device *dev); |
@@ -1422,7 +1435,8 @@ u8 mwifiex_adjust_data_rate(struct mwifiex_private *priv, | |||
1422 | u8 rx_rate, u8 ht_info); | 1435 | u8 rx_rate, u8 ht_info); |
1423 | 1436 | ||
1424 | void mwifiex_dump_drv_info(struct mwifiex_adapter *adapter); | 1437 | void mwifiex_dump_drv_info(struct mwifiex_adapter *adapter); |
1425 | void *mwifiex_alloc_rx_buf(int rx_len, gfp_t flags); | 1438 | void *mwifiex_alloc_dma_align_buf(int rx_len, gfp_t flags); |
1439 | void mwifiex_queue_main_work(struct mwifiex_adapter *adapter); | ||
1426 | 1440 | ||
1427 | #ifdef CONFIG_DEBUG_FS | 1441 | #ifdef CONFIG_DEBUG_FS |
1428 | void mwifiex_debugfs_init(void); | 1442 | void mwifiex_debugfs_init(void); |
diff --git a/drivers/net/wireless/mwifiex/pcie.c b/drivers/net/wireless/mwifiex/pcie.c index 4b463c3b9906..bcc7751d883c 100644 --- a/drivers/net/wireless/mwifiex/pcie.c +++ b/drivers/net/wireless/mwifiex/pcie.c | |||
@@ -234,8 +234,6 @@ static void mwifiex_pcie_remove(struct pci_dev *pdev) | |||
234 | if (!adapter || !adapter->priv_num) | 234 | if (!adapter || !adapter->priv_num) |
235 | return; | 235 | return; |
236 | 236 | ||
237 | cancel_work_sync(&adapter->iface_work); | ||
238 | |||
239 | if (user_rmmod) { | 237 | if (user_rmmod) { |
240 | #ifdef CONFIG_PM_SLEEP | 238 | #ifdef CONFIG_PM_SLEEP |
241 | if (adapter->is_suspended) | 239 | if (adapter->is_suspended) |
@@ -498,8 +496,8 @@ static int mwifiex_init_rxq_ring(struct mwifiex_adapter *adapter) | |||
498 | 496 | ||
499 | for (i = 0; i < MWIFIEX_MAX_TXRX_BD; i++) { | 497 | for (i = 0; i < MWIFIEX_MAX_TXRX_BD; i++) { |
500 | /* Allocate skb here so that firmware can DMA data from it */ | 498 | /* Allocate skb here so that firmware can DMA data from it */ |
501 | skb = mwifiex_alloc_rx_buf(MWIFIEX_RX_DATA_BUF_SIZE, | 499 | skb = mwifiex_alloc_dma_align_buf(MWIFIEX_RX_DATA_BUF_SIZE, |
502 | GFP_KERNEL | GFP_DMA); | 500 | GFP_KERNEL | GFP_DMA); |
503 | if (!skb) { | 501 | if (!skb) { |
504 | dev_err(adapter->dev, | 502 | dev_err(adapter->dev, |
505 | "Unable to allocate skb for RX ring.\n"); | 503 | "Unable to allocate skb for RX ring.\n"); |
@@ -1298,8 +1296,8 @@ static int mwifiex_pcie_process_recv_data(struct mwifiex_adapter *adapter) | |||
1298 | } | 1296 | } |
1299 | } | 1297 | } |
1300 | 1298 | ||
1301 | skb_tmp = mwifiex_alloc_rx_buf(MWIFIEX_RX_DATA_BUF_SIZE, | 1299 | skb_tmp = mwifiex_alloc_dma_align_buf(MWIFIEX_RX_DATA_BUF_SIZE, |
1302 | GFP_KERNEL | GFP_DMA); | 1300 | GFP_KERNEL | GFP_DMA); |
1303 | if (!skb_tmp) { | 1301 | if (!skb_tmp) { |
1304 | dev_err(adapter->dev, | 1302 | dev_err(adapter->dev, |
1305 | "Unable to allocate skb.\n"); | 1303 | "Unable to allocate skb.\n"); |
@@ -2101,7 +2099,7 @@ static irqreturn_t mwifiex_pcie_interrupt(int irq, void *context) | |||
2101 | goto exit; | 2099 | goto exit; |
2102 | 2100 | ||
2103 | mwifiex_interrupt_status(adapter); | 2101 | mwifiex_interrupt_status(adapter); |
2104 | queue_work(adapter->workqueue, &adapter->main_work); | 2102 | mwifiex_queue_main_work(adapter); |
2105 | 2103 | ||
2106 | exit: | 2104 | exit: |
2107 | return IRQ_HANDLED; | 2105 | return IRQ_HANDLED; |
@@ -2373,25 +2371,26 @@ done: | |||
2373 | adapter->curr_mem_idx = 0; | 2371 | adapter->curr_mem_idx = 0; |
2374 | } | 2372 | } |
2375 | 2373 | ||
2374 | static unsigned long iface_work_flags; | ||
2375 | static struct mwifiex_adapter *save_adapter; | ||
2376 | static void mwifiex_pcie_work(struct work_struct *work) | 2376 | static void mwifiex_pcie_work(struct work_struct *work) |
2377 | { | 2377 | { |
2378 | struct mwifiex_adapter *adapter = | ||
2379 | container_of(work, struct mwifiex_adapter, iface_work); | ||
2380 | |||
2381 | if (test_and_clear_bit(MWIFIEX_IFACE_WORK_FW_DUMP, | 2378 | if (test_and_clear_bit(MWIFIEX_IFACE_WORK_FW_DUMP, |
2382 | &adapter->iface_work_flags)) | 2379 | &iface_work_flags)) |
2383 | mwifiex_pcie_fw_dump_work(adapter); | 2380 | mwifiex_pcie_fw_dump_work(save_adapter); |
2384 | } | 2381 | } |
2385 | 2382 | ||
2383 | static DECLARE_WORK(pcie_work, mwifiex_pcie_work); | ||
2386 | /* This function dumps FW information */ | 2384 | /* This function dumps FW information */ |
2387 | static void mwifiex_pcie_fw_dump(struct mwifiex_adapter *adapter) | 2385 | static void mwifiex_pcie_fw_dump(struct mwifiex_adapter *adapter) |
2388 | { | 2386 | { |
2389 | if (test_bit(MWIFIEX_IFACE_WORK_FW_DUMP, &adapter->iface_work_flags)) | 2387 | save_adapter = adapter; |
2388 | if (test_bit(MWIFIEX_IFACE_WORK_FW_DUMP, &iface_work_flags)) | ||
2390 | return; | 2389 | return; |
2391 | 2390 | ||
2392 | set_bit(MWIFIEX_IFACE_WORK_FW_DUMP, &adapter->iface_work_flags); | 2391 | set_bit(MWIFIEX_IFACE_WORK_FW_DUMP, &iface_work_flags); |
2393 | 2392 | ||
2394 | schedule_work(&adapter->iface_work); | 2393 | schedule_work(&pcie_work); |
2395 | } | 2394 | } |
2396 | 2395 | ||
2397 | /* | 2396 | /* |
@@ -2619,7 +2618,6 @@ static struct mwifiex_if_ops pcie_ops = { | |||
2619 | .init_fw_port = mwifiex_pcie_init_fw_port, | 2618 | .init_fw_port = mwifiex_pcie_init_fw_port, |
2620 | .clean_pcie_ring = mwifiex_clean_pcie_ring_buf, | 2619 | .clean_pcie_ring = mwifiex_clean_pcie_ring_buf, |
2621 | .fw_dump = mwifiex_pcie_fw_dump, | 2620 | .fw_dump = mwifiex_pcie_fw_dump, |
2622 | .iface_work = mwifiex_pcie_work, | ||
2623 | }; | 2621 | }; |
2624 | 2622 | ||
2625 | /* | 2623 | /* |
@@ -2665,6 +2663,7 @@ static void mwifiex_pcie_cleanup_module(void) | |||
2665 | /* Set the flag as user is removing this module. */ | 2663 | /* Set the flag as user is removing this module. */ |
2666 | user_rmmod = 1; | 2664 | user_rmmod = 1; |
2667 | 2665 | ||
2666 | cancel_work_sync(&pcie_work); | ||
2668 | pci_unregister_driver(&mwifiex_pcie); | 2667 | pci_unregister_driver(&mwifiex_pcie); |
2669 | } | 2668 | } |
2670 | 2669 | ||
diff --git a/drivers/net/wireless/mwifiex/sdio.c b/drivers/net/wireless/mwifiex/sdio.c index 57d85ab442bf..d10320f89bc1 100644 --- a/drivers/net/wireless/mwifiex/sdio.c +++ b/drivers/net/wireless/mwifiex/sdio.c | |||
@@ -47,6 +47,7 @@ | |||
47 | static u8 user_rmmod; | 47 | static u8 user_rmmod; |
48 | 48 | ||
49 | static struct mwifiex_if_ops sdio_ops; | 49 | static struct mwifiex_if_ops sdio_ops; |
50 | static unsigned long iface_work_flags; | ||
50 | 51 | ||
51 | static struct semaphore add_remove_card_sem; | 52 | static struct semaphore add_remove_card_sem; |
52 | 53 | ||
@@ -200,8 +201,6 @@ mwifiex_sdio_remove(struct sdio_func *func) | |||
200 | if (!adapter || !adapter->priv_num) | 201 | if (!adapter || !adapter->priv_num) |
201 | return; | 202 | return; |
202 | 203 | ||
203 | cancel_work_sync(&adapter->iface_work); | ||
204 | |||
205 | if (user_rmmod) { | 204 | if (user_rmmod) { |
206 | if (adapter->is_suspended) | 205 | if (adapter->is_suspended) |
207 | mwifiex_sdio_resume(adapter->dev); | 206 | mwifiex_sdio_resume(adapter->dev); |
@@ -1043,6 +1042,59 @@ static int mwifiex_check_fw_status(struct mwifiex_adapter *adapter, | |||
1043 | } | 1042 | } |
1044 | 1043 | ||
1045 | /* | 1044 | /* |
1045 | * This function decode sdio aggreation pkt. | ||
1046 | * | ||
1047 | * Based on the the data block size and pkt_len, | ||
1048 | * skb data will be decoded to few packets. | ||
1049 | */ | ||
1050 | static void mwifiex_deaggr_sdio_pkt(struct mwifiex_adapter *adapter, | ||
1051 | struct sk_buff *skb) | ||
1052 | { | ||
1053 | u32 total_pkt_len, pkt_len; | ||
1054 | struct sk_buff *skb_deaggr; | ||
1055 | u32 pkt_type; | ||
1056 | u16 blk_size; | ||
1057 | u8 blk_num; | ||
1058 | u8 *data; | ||
1059 | |||
1060 | data = skb->data; | ||
1061 | total_pkt_len = skb->len; | ||
1062 | |||
1063 | while (total_pkt_len >= (SDIO_HEADER_OFFSET + INTF_HEADER_LEN)) { | ||
1064 | if (total_pkt_len < adapter->sdio_rx_block_size) | ||
1065 | break; | ||
1066 | blk_num = *(data + BLOCK_NUMBER_OFFSET); | ||
1067 | blk_size = adapter->sdio_rx_block_size * blk_num; | ||
1068 | if (blk_size > total_pkt_len) { | ||
1069 | dev_err(adapter->dev, "%s: error in pkt,\t" | ||
1070 | "blk_num=%d, blk_size=%d, total_pkt_len=%d\n", | ||
1071 | __func__, blk_num, blk_size, total_pkt_len); | ||
1072 | break; | ||
1073 | } | ||
1074 | pkt_len = le16_to_cpu(*(__le16 *)(data + SDIO_HEADER_OFFSET)); | ||
1075 | pkt_type = le16_to_cpu(*(__le16 *)(data + SDIO_HEADER_OFFSET + | ||
1076 | 2)); | ||
1077 | if ((pkt_len + SDIO_HEADER_OFFSET) > blk_size) { | ||
1078 | dev_err(adapter->dev, "%s: error in pkt,\t" | ||
1079 | "pkt_len=%d, blk_size=%d\n", | ||
1080 | __func__, pkt_len, blk_size); | ||
1081 | break; | ||
1082 | } | ||
1083 | skb_deaggr = mwifiex_alloc_dma_align_buf(pkt_len, | ||
1084 | GFP_KERNEL | GFP_DMA); | ||
1085 | if (!skb_deaggr) | ||
1086 | break; | ||
1087 | skb_put(skb_deaggr, pkt_len); | ||
1088 | memcpy(skb_deaggr->data, data + SDIO_HEADER_OFFSET, pkt_len); | ||
1089 | skb_pull(skb_deaggr, INTF_HEADER_LEN); | ||
1090 | |||
1091 | mwifiex_handle_rx_packet(adapter, skb_deaggr); | ||
1092 | data += blk_size; | ||
1093 | total_pkt_len -= blk_size; | ||
1094 | } | ||
1095 | } | ||
1096 | |||
1097 | /* | ||
1046 | * This function decodes a received packet. | 1098 | * This function decodes a received packet. |
1047 | * | 1099 | * |
1048 | * Based on the type, the packet is treated as either a data, or | 1100 | * Based on the type, the packet is treated as either a data, or |
@@ -1055,11 +1107,28 @@ static int mwifiex_decode_rx_packet(struct mwifiex_adapter *adapter, | |||
1055 | u8 *cmd_buf; | 1107 | u8 *cmd_buf; |
1056 | __le16 *curr_ptr = (__le16 *)skb->data; | 1108 | __le16 *curr_ptr = (__le16 *)skb->data; |
1057 | u16 pkt_len = le16_to_cpu(*curr_ptr); | 1109 | u16 pkt_len = le16_to_cpu(*curr_ptr); |
1110 | struct mwifiex_rxinfo *rx_info; | ||
1058 | 1111 | ||
1059 | skb_trim(skb, pkt_len); | 1112 | if (upld_typ != MWIFIEX_TYPE_AGGR_DATA) { |
1060 | skb_pull(skb, INTF_HEADER_LEN); | 1113 | skb_trim(skb, pkt_len); |
1114 | skb_pull(skb, INTF_HEADER_LEN); | ||
1115 | } | ||
1061 | 1116 | ||
1062 | switch (upld_typ) { | 1117 | switch (upld_typ) { |
1118 | case MWIFIEX_TYPE_AGGR_DATA: | ||
1119 | dev_dbg(adapter->dev, "info: --- Rx: Aggr Data packet ---\n"); | ||
1120 | rx_info = MWIFIEX_SKB_RXCB(skb); | ||
1121 | rx_info->buf_type = MWIFIEX_TYPE_AGGR_DATA; | ||
1122 | if (adapter->rx_work_enabled) { | ||
1123 | skb_queue_tail(&adapter->rx_data_q, skb); | ||
1124 | atomic_inc(&adapter->rx_pending); | ||
1125 | adapter->data_received = true; | ||
1126 | } else { | ||
1127 | mwifiex_deaggr_sdio_pkt(adapter, skb); | ||
1128 | dev_kfree_skb_any(skb); | ||
1129 | } | ||
1130 | break; | ||
1131 | |||
1063 | case MWIFIEX_TYPE_DATA: | 1132 | case MWIFIEX_TYPE_DATA: |
1064 | dev_dbg(adapter->dev, "info: --- Rx: Data packet ---\n"); | 1133 | dev_dbg(adapter->dev, "info: --- Rx: Data packet ---\n"); |
1065 | if (adapter->rx_work_enabled) { | 1134 | if (adapter->rx_work_enabled) { |
@@ -1127,17 +1196,17 @@ static int mwifiex_decode_rx_packet(struct mwifiex_adapter *adapter, | |||
1127 | * provided there is space left, processed and finally uploaded. | 1196 | * provided there is space left, processed and finally uploaded. |
1128 | */ | 1197 | */ |
1129 | static int mwifiex_sdio_card_to_host_mp_aggr(struct mwifiex_adapter *adapter, | 1198 | static int mwifiex_sdio_card_to_host_mp_aggr(struct mwifiex_adapter *adapter, |
1130 | struct sk_buff *skb, u8 port) | 1199 | u16 rx_len, u8 port) |
1131 | { | 1200 | { |
1132 | struct sdio_mmc_card *card = adapter->card; | 1201 | struct sdio_mmc_card *card = adapter->card; |
1133 | s32 f_do_rx_aggr = 0; | 1202 | s32 f_do_rx_aggr = 0; |
1134 | s32 f_do_rx_cur = 0; | 1203 | s32 f_do_rx_cur = 0; |
1135 | s32 f_aggr_cur = 0; | 1204 | s32 f_aggr_cur = 0; |
1205 | s32 f_post_aggr_cur = 0; | ||
1136 | struct sk_buff *skb_deaggr; | 1206 | struct sk_buff *skb_deaggr; |
1137 | u32 pind; | 1207 | struct sk_buff *skb = NULL; |
1138 | u32 pkt_len, pkt_type, mport; | 1208 | u32 pkt_len, pkt_type, mport, pind; |
1139 | u8 *curr_ptr; | 1209 | u8 *curr_ptr; |
1140 | u32 rx_len = skb->len; | ||
1141 | 1210 | ||
1142 | if ((card->has_control_mask) && (port == CTRL_PORT)) { | 1211 | if ((card->has_control_mask) && (port == CTRL_PORT)) { |
1143 | /* Read the command Resp without aggr */ | 1212 | /* Read the command Resp without aggr */ |
@@ -1164,12 +1233,12 @@ static int mwifiex_sdio_card_to_host_mp_aggr(struct mwifiex_adapter *adapter, | |||
1164 | dev_dbg(adapter->dev, "info: %s: not last packet\n", __func__); | 1233 | dev_dbg(adapter->dev, "info: %s: not last packet\n", __func__); |
1165 | 1234 | ||
1166 | if (MP_RX_AGGR_IN_PROGRESS(card)) { | 1235 | if (MP_RX_AGGR_IN_PROGRESS(card)) { |
1167 | if (MP_RX_AGGR_BUF_HAS_ROOM(card, skb->len)) { | 1236 | if (MP_RX_AGGR_BUF_HAS_ROOM(card, rx_len)) { |
1168 | f_aggr_cur = 1; | 1237 | f_aggr_cur = 1; |
1169 | } else { | 1238 | } else { |
1170 | /* No room in Aggr buf, do rx aggr now */ | 1239 | /* No room in Aggr buf, do rx aggr now */ |
1171 | f_do_rx_aggr = 1; | 1240 | f_do_rx_aggr = 1; |
1172 | f_do_rx_cur = 1; | 1241 | f_post_aggr_cur = 1; |
1173 | } | 1242 | } |
1174 | } else { | 1243 | } else { |
1175 | /* Rx aggr not in progress */ | 1244 | /* Rx aggr not in progress */ |
@@ -1182,7 +1251,7 @@ static int mwifiex_sdio_card_to_host_mp_aggr(struct mwifiex_adapter *adapter, | |||
1182 | 1251 | ||
1183 | if (MP_RX_AGGR_IN_PROGRESS(card)) { | 1252 | if (MP_RX_AGGR_IN_PROGRESS(card)) { |
1184 | f_do_rx_aggr = 1; | 1253 | f_do_rx_aggr = 1; |
1185 | if (MP_RX_AGGR_BUF_HAS_ROOM(card, skb->len)) | 1254 | if (MP_RX_AGGR_BUF_HAS_ROOM(card, rx_len)) |
1186 | f_aggr_cur = 1; | 1255 | f_aggr_cur = 1; |
1187 | else | 1256 | else |
1188 | /* No room in Aggr buf, do rx aggr now */ | 1257 | /* No room in Aggr buf, do rx aggr now */ |
@@ -1195,7 +1264,7 @@ static int mwifiex_sdio_card_to_host_mp_aggr(struct mwifiex_adapter *adapter, | |||
1195 | if (f_aggr_cur) { | 1264 | if (f_aggr_cur) { |
1196 | dev_dbg(adapter->dev, "info: current packet aggregation\n"); | 1265 | dev_dbg(adapter->dev, "info: current packet aggregation\n"); |
1197 | /* Curr pkt can be aggregated */ | 1266 | /* Curr pkt can be aggregated */ |
1198 | mp_rx_aggr_setup(card, skb, port); | 1267 | mp_rx_aggr_setup(card, rx_len, port); |
1199 | 1268 | ||
1200 | if (MP_RX_AGGR_PKT_LIMIT_REACHED(card) || | 1269 | if (MP_RX_AGGR_PKT_LIMIT_REACHED(card) || |
1201 | mp_rx_aggr_port_limit_reached(card)) { | 1270 | mp_rx_aggr_port_limit_reached(card)) { |
@@ -1238,16 +1307,29 @@ static int mwifiex_sdio_card_to_host_mp_aggr(struct mwifiex_adapter *adapter, | |||
1238 | curr_ptr = card->mpa_rx.buf; | 1307 | curr_ptr = card->mpa_rx.buf; |
1239 | 1308 | ||
1240 | for (pind = 0; pind < card->mpa_rx.pkt_cnt; pind++) { | 1309 | for (pind = 0; pind < card->mpa_rx.pkt_cnt; pind++) { |
1310 | u32 *len_arr = card->mpa_rx.len_arr; | ||
1241 | 1311 | ||
1242 | /* get curr PKT len & type */ | 1312 | /* get curr PKT len & type */ |
1243 | pkt_len = le16_to_cpu(*(__le16 *) &curr_ptr[0]); | 1313 | pkt_len = le16_to_cpu(*(__le16 *) &curr_ptr[0]); |
1244 | pkt_type = le16_to_cpu(*(__le16 *) &curr_ptr[2]); | 1314 | pkt_type = le16_to_cpu(*(__le16 *) &curr_ptr[2]); |
1245 | 1315 | ||
1246 | /* copy pkt to deaggr buf */ | 1316 | /* copy pkt to deaggr buf */ |
1247 | skb_deaggr = card->mpa_rx.skb_arr[pind]; | 1317 | skb_deaggr = mwifiex_alloc_dma_align_buf(len_arr[pind], |
1318 | GFP_KERNEL | | ||
1319 | GFP_DMA); | ||
1320 | if (!skb_deaggr) { | ||
1321 | dev_err(adapter->dev, "skb allocation failure drop pkt len=%d type=%d\n", | ||
1322 | pkt_len, pkt_type); | ||
1323 | curr_ptr += len_arr[pind]; | ||
1324 | continue; | ||
1325 | } | ||
1248 | 1326 | ||
1249 | if ((pkt_type == MWIFIEX_TYPE_DATA) && (pkt_len <= | 1327 | skb_put(skb_deaggr, len_arr[pind]); |
1250 | card->mpa_rx.len_arr[pind])) { | 1328 | |
1329 | if ((pkt_type == MWIFIEX_TYPE_DATA || | ||
1330 | (pkt_type == MWIFIEX_TYPE_AGGR_DATA && | ||
1331 | adapter->sdio_rx_aggr_enable)) && | ||
1332 | (pkt_len <= len_arr[pind])) { | ||
1251 | 1333 | ||
1252 | memcpy(skb_deaggr->data, curr_ptr, pkt_len); | 1334 | memcpy(skb_deaggr->data, curr_ptr, pkt_len); |
1253 | 1335 | ||
@@ -1257,13 +1339,15 @@ static int mwifiex_sdio_card_to_host_mp_aggr(struct mwifiex_adapter *adapter, | |||
1257 | mwifiex_decode_rx_packet(adapter, skb_deaggr, | 1339 | mwifiex_decode_rx_packet(adapter, skb_deaggr, |
1258 | pkt_type); | 1340 | pkt_type); |
1259 | } else { | 1341 | } else { |
1260 | dev_err(adapter->dev, "wrong aggr pkt:" | 1342 | dev_err(adapter->dev, " drop wrong aggr pkt:\t" |
1261 | " type=%d len=%d max_len=%d\n", | 1343 | "sdio_single_port_rx_aggr=%d\t" |
1344 | "type=%d len=%d max_len=%d\n", | ||
1345 | adapter->sdio_rx_aggr_enable, | ||
1262 | pkt_type, pkt_len, | 1346 | pkt_type, pkt_len, |
1263 | card->mpa_rx.len_arr[pind]); | 1347 | len_arr[pind]); |
1264 | dev_kfree_skb_any(skb_deaggr); | 1348 | dev_kfree_skb_any(skb_deaggr); |
1265 | } | 1349 | } |
1266 | curr_ptr += card->mpa_rx.len_arr[pind]; | 1350 | curr_ptr += len_arr[pind]; |
1267 | } | 1351 | } |
1268 | MP_RX_AGGR_BUF_RESET(card); | 1352 | MP_RX_AGGR_BUF_RESET(card); |
1269 | } | 1353 | } |
@@ -1273,28 +1357,46 @@ rx_curr_single: | |||
1273 | dev_dbg(adapter->dev, "info: RX: port: %d, rx_len: %d\n", | 1357 | dev_dbg(adapter->dev, "info: RX: port: %d, rx_len: %d\n", |
1274 | port, rx_len); | 1358 | port, rx_len); |
1275 | 1359 | ||
1360 | skb = mwifiex_alloc_dma_align_buf(rx_len, GFP_KERNEL | GFP_DMA); | ||
1361 | if (!skb) { | ||
1362 | dev_err(adapter->dev, "single skb allocated fail,\t" | ||
1363 | "drop pkt port=%d len=%d\n", port, rx_len); | ||
1364 | if (mwifiex_sdio_card_to_host(adapter, &pkt_type, | ||
1365 | card->mpa_rx.buf, rx_len, | ||
1366 | adapter->ioport + port)) | ||
1367 | goto error; | ||
1368 | return 0; | ||
1369 | } | ||
1370 | |||
1371 | skb_put(skb, rx_len); | ||
1372 | |||
1276 | if (mwifiex_sdio_card_to_host(adapter, &pkt_type, | 1373 | if (mwifiex_sdio_card_to_host(adapter, &pkt_type, |
1277 | skb->data, skb->len, | 1374 | skb->data, skb->len, |
1278 | adapter->ioport + port)) | 1375 | adapter->ioport + port)) |
1279 | goto error; | 1376 | goto error; |
1377 | if (!adapter->sdio_rx_aggr_enable && | ||
1378 | pkt_type == MWIFIEX_TYPE_AGGR_DATA) { | ||
1379 | dev_err(adapter->dev, "drop wrong pkt type %d\t" | ||
1380 | "current SDIO RX Aggr not enabled\n", | ||
1381 | pkt_type); | ||
1382 | dev_kfree_skb_any(skb); | ||
1383 | return 0; | ||
1384 | } | ||
1280 | 1385 | ||
1281 | mwifiex_decode_rx_packet(adapter, skb, pkt_type); | 1386 | mwifiex_decode_rx_packet(adapter, skb, pkt_type); |
1282 | } | 1387 | } |
1388 | if (f_post_aggr_cur) { | ||
1389 | dev_dbg(adapter->dev, "info: current packet aggregation\n"); | ||
1390 | /* Curr pkt can be aggregated */ | ||
1391 | mp_rx_aggr_setup(card, rx_len, port); | ||
1392 | } | ||
1283 | 1393 | ||
1284 | return 0; | 1394 | return 0; |
1285 | |||
1286 | error: | 1395 | error: |
1287 | if (MP_RX_AGGR_IN_PROGRESS(card)) { | 1396 | if (MP_RX_AGGR_IN_PROGRESS(card)) |
1288 | /* Multiport-aggregation transfer failed - cleanup */ | ||
1289 | for (pind = 0; pind < card->mpa_rx.pkt_cnt; pind++) { | ||
1290 | /* copy pkt to deaggr buf */ | ||
1291 | skb_deaggr = card->mpa_rx.skb_arr[pind]; | ||
1292 | dev_kfree_skb_any(skb_deaggr); | ||
1293 | } | ||
1294 | MP_RX_AGGR_BUF_RESET(card); | 1397 | MP_RX_AGGR_BUF_RESET(card); |
1295 | } | ||
1296 | 1398 | ||
1297 | if (f_do_rx_cur) | 1399 | if (f_do_rx_cur && skb) |
1298 | /* Single transfer pending. Free curr buff also */ | 1400 | /* Single transfer pending. Free curr buff also */ |
1299 | dev_kfree_skb_any(skb); | 1401 | dev_kfree_skb_any(skb); |
1300 | 1402 | ||
@@ -1356,8 +1458,9 @@ static int mwifiex_process_int_status(struct mwifiex_adapter *adapter) | |||
1356 | MWIFIEX_RX_DATA_BUF_SIZE) | 1458 | MWIFIEX_RX_DATA_BUF_SIZE) |
1357 | return -1; | 1459 | return -1; |
1358 | rx_len = (u16) (rx_blocks * MWIFIEX_SDIO_BLOCK_SIZE); | 1460 | rx_len = (u16) (rx_blocks * MWIFIEX_SDIO_BLOCK_SIZE); |
1461 | dev_dbg(adapter->dev, "info: rx_len = %d\n", rx_len); | ||
1359 | 1462 | ||
1360 | skb = mwifiex_alloc_rx_buf(rx_len, GFP_KERNEL | GFP_DMA); | 1463 | skb = mwifiex_alloc_dma_align_buf(rx_len, GFP_KERNEL | GFP_DMA); |
1361 | if (!skb) | 1464 | if (!skb) |
1362 | return -1; | 1465 | return -1; |
1363 | 1466 | ||
@@ -1447,28 +1550,16 @@ static int mwifiex_process_int_status(struct mwifiex_adapter *adapter) | |||
1447 | 1) / MWIFIEX_SDIO_BLOCK_SIZE; | 1550 | 1) / MWIFIEX_SDIO_BLOCK_SIZE; |
1448 | if (rx_len <= INTF_HEADER_LEN || | 1551 | if (rx_len <= INTF_HEADER_LEN || |
1449 | (rx_blocks * MWIFIEX_SDIO_BLOCK_SIZE) > | 1552 | (rx_blocks * MWIFIEX_SDIO_BLOCK_SIZE) > |
1450 | MWIFIEX_RX_DATA_BUF_SIZE) { | 1553 | card->mpa_rx.buf_size) { |
1451 | dev_err(adapter->dev, "invalid rx_len=%d\n", | 1554 | dev_err(adapter->dev, "invalid rx_len=%d\n", |
1452 | rx_len); | 1555 | rx_len); |
1453 | return -1; | 1556 | return -1; |
1454 | } | 1557 | } |
1455 | rx_len = (u16) (rx_blocks * MWIFIEX_SDIO_BLOCK_SIZE); | ||
1456 | |||
1457 | skb = mwifiex_alloc_rx_buf(rx_len, | ||
1458 | GFP_KERNEL | GFP_DMA); | ||
1459 | |||
1460 | if (!skb) { | ||
1461 | dev_err(adapter->dev, "%s: failed to alloc skb", | ||
1462 | __func__); | ||
1463 | return -1; | ||
1464 | } | ||
1465 | 1558 | ||
1466 | skb_put(skb, rx_len); | 1559 | rx_len = (u16) (rx_blocks * MWIFIEX_SDIO_BLOCK_SIZE); |
1467 | 1560 | dev_dbg(adapter->dev, "info: rx_len = %d\n", rx_len); | |
1468 | dev_dbg(adapter->dev, "info: rx_len = %d skb->len = %d\n", | ||
1469 | rx_len, skb->len); | ||
1470 | 1561 | ||
1471 | if (mwifiex_sdio_card_to_host_mp_aggr(adapter, skb, | 1562 | if (mwifiex_sdio_card_to_host_mp_aggr(adapter, rx_len, |
1472 | port)) { | 1563 | port)) { |
1473 | dev_err(adapter->dev, "card_to_host_mpa failed:" | 1564 | dev_err(adapter->dev, "card_to_host_mpa failed:" |
1474 | " int status=%#x\n", sdio_ireg); | 1565 | " int status=%#x\n", sdio_ireg); |
@@ -1736,6 +1827,7 @@ static int mwifiex_alloc_sdio_mpa_buffers(struct mwifiex_adapter *adapter, | |||
1736 | u32 mpa_tx_buf_size, u32 mpa_rx_buf_size) | 1827 | u32 mpa_tx_buf_size, u32 mpa_rx_buf_size) |
1737 | { | 1828 | { |
1738 | struct sdio_mmc_card *card = adapter->card; | 1829 | struct sdio_mmc_card *card = adapter->card; |
1830 | u32 rx_buf_size; | ||
1739 | int ret = 0; | 1831 | int ret = 0; |
1740 | 1832 | ||
1741 | card->mpa_tx.buf = kzalloc(mpa_tx_buf_size, GFP_KERNEL); | 1833 | card->mpa_tx.buf = kzalloc(mpa_tx_buf_size, GFP_KERNEL); |
@@ -1746,13 +1838,15 @@ static int mwifiex_alloc_sdio_mpa_buffers(struct mwifiex_adapter *adapter, | |||
1746 | 1838 | ||
1747 | card->mpa_tx.buf_size = mpa_tx_buf_size; | 1839 | card->mpa_tx.buf_size = mpa_tx_buf_size; |
1748 | 1840 | ||
1749 | card->mpa_rx.buf = kzalloc(mpa_rx_buf_size, GFP_KERNEL); | 1841 | rx_buf_size = max_t(u32, mpa_rx_buf_size, |
1842 | (u32)SDIO_MAX_AGGR_BUF_SIZE); | ||
1843 | card->mpa_rx.buf = kzalloc(rx_buf_size, GFP_KERNEL); | ||
1750 | if (!card->mpa_rx.buf) { | 1844 | if (!card->mpa_rx.buf) { |
1751 | ret = -1; | 1845 | ret = -1; |
1752 | goto error; | 1846 | goto error; |
1753 | } | 1847 | } |
1754 | 1848 | ||
1755 | card->mpa_rx.buf_size = mpa_rx_buf_size; | 1849 | card->mpa_rx.buf_size = rx_buf_size; |
1756 | 1850 | ||
1757 | error: | 1851 | error: |
1758 | if (ret) { | 1852 | if (ret) { |
@@ -1951,6 +2045,7 @@ mwifiex_update_mp_end_port(struct mwifiex_adapter *adapter, u16 port) | |||
1951 | port, card->mp_data_port_mask); | 2045 | port, card->mp_data_port_mask); |
1952 | } | 2046 | } |
1953 | 2047 | ||
2048 | static struct mwifiex_adapter *save_adapter; | ||
1954 | static void mwifiex_sdio_card_reset_work(struct mwifiex_adapter *adapter) | 2049 | static void mwifiex_sdio_card_reset_work(struct mwifiex_adapter *adapter) |
1955 | { | 2050 | { |
1956 | struct sdio_mmc_card *card = adapter->card; | 2051 | struct sdio_mmc_card *card = adapter->card; |
@@ -2019,10 +2114,8 @@ rdwr_status mwifiex_sdio_rdwr_firmware(struct mwifiex_adapter *adapter, | |||
2019 | } | 2114 | } |
2020 | 2115 | ||
2021 | /* This function dump firmware memory to file */ | 2116 | /* This function dump firmware memory to file */ |
2022 | static void mwifiex_sdio_fw_dump_work(struct work_struct *work) | 2117 | static void mwifiex_sdio_fw_dump_work(struct mwifiex_adapter *adapter) |
2023 | { | 2118 | { |
2024 | struct mwifiex_adapter *adapter = | ||
2025 | container_of(work, struct mwifiex_adapter, iface_work); | ||
2026 | struct sdio_mmc_card *card = adapter->card; | 2119 | struct sdio_mmc_card *card = adapter->card; |
2027 | int ret = 0; | 2120 | int ret = 0; |
2028 | unsigned int reg, reg_start, reg_end; | 2121 | unsigned int reg, reg_start, reg_end; |
@@ -2144,36 +2237,36 @@ done: | |||
2144 | 2237 | ||
2145 | static void mwifiex_sdio_work(struct work_struct *work) | 2238 | static void mwifiex_sdio_work(struct work_struct *work) |
2146 | { | 2239 | { |
2147 | struct mwifiex_adapter *adapter = | ||
2148 | container_of(work, struct mwifiex_adapter, iface_work); | ||
2149 | |||
2150 | if (test_and_clear_bit(MWIFIEX_IFACE_WORK_CARD_RESET, | ||
2151 | &adapter->iface_work_flags)) | ||
2152 | mwifiex_sdio_card_reset_work(adapter); | ||
2153 | if (test_and_clear_bit(MWIFIEX_IFACE_WORK_FW_DUMP, | 2240 | if (test_and_clear_bit(MWIFIEX_IFACE_WORK_FW_DUMP, |
2154 | &adapter->iface_work_flags)) | 2241 | &iface_work_flags)) |
2155 | mwifiex_sdio_fw_dump_work(work); | 2242 | mwifiex_sdio_fw_dump_work(save_adapter); |
2243 | if (test_and_clear_bit(MWIFIEX_IFACE_WORK_CARD_RESET, | ||
2244 | &iface_work_flags)) | ||
2245 | mwifiex_sdio_card_reset_work(save_adapter); | ||
2156 | } | 2246 | } |
2157 | 2247 | ||
2248 | static DECLARE_WORK(sdio_work, mwifiex_sdio_work); | ||
2158 | /* This function resets the card */ | 2249 | /* This function resets the card */ |
2159 | static void mwifiex_sdio_card_reset(struct mwifiex_adapter *adapter) | 2250 | static void mwifiex_sdio_card_reset(struct mwifiex_adapter *adapter) |
2160 | { | 2251 | { |
2161 | if (test_bit(MWIFIEX_IFACE_WORK_CARD_RESET, &adapter->iface_work_flags)) | 2252 | save_adapter = adapter; |
2253 | if (test_bit(MWIFIEX_IFACE_WORK_CARD_RESET, &iface_work_flags)) | ||
2162 | return; | 2254 | return; |
2163 | 2255 | ||
2164 | set_bit(MWIFIEX_IFACE_WORK_CARD_RESET, &adapter->iface_work_flags); | 2256 | set_bit(MWIFIEX_IFACE_WORK_CARD_RESET, &iface_work_flags); |
2165 | 2257 | ||
2166 | schedule_work(&adapter->iface_work); | 2258 | schedule_work(&sdio_work); |
2167 | } | 2259 | } |
2168 | 2260 | ||
2169 | /* This function dumps FW information */ | 2261 | /* This function dumps FW information */ |
2170 | static void mwifiex_sdio_fw_dump(struct mwifiex_adapter *adapter) | 2262 | static void mwifiex_sdio_fw_dump(struct mwifiex_adapter *adapter) |
2171 | { | 2263 | { |
2172 | if (test_bit(MWIFIEX_IFACE_WORK_FW_DUMP, &adapter->iface_work_flags)) | 2264 | save_adapter = adapter; |
2265 | if (test_bit(MWIFIEX_IFACE_WORK_FW_DUMP, &iface_work_flags)) | ||
2173 | return; | 2266 | return; |
2174 | 2267 | ||
2175 | set_bit(MWIFIEX_IFACE_WORK_FW_DUMP, &adapter->iface_work_flags); | 2268 | set_bit(MWIFIEX_IFACE_WORK_FW_DUMP, &iface_work_flags); |
2176 | schedule_work(&adapter->iface_work); | 2269 | schedule_work(&sdio_work); |
2177 | } | 2270 | } |
2178 | 2271 | ||
2179 | /* Function to dump SDIO function registers and SDIO scratch registers in case | 2272 | /* Function to dump SDIO function registers and SDIO scratch registers in case |
@@ -2289,9 +2382,9 @@ static struct mwifiex_if_ops sdio_ops = { | |||
2289 | .cmdrsp_complete = mwifiex_sdio_cmdrsp_complete, | 2382 | .cmdrsp_complete = mwifiex_sdio_cmdrsp_complete, |
2290 | .event_complete = mwifiex_sdio_event_complete, | 2383 | .event_complete = mwifiex_sdio_event_complete, |
2291 | .card_reset = mwifiex_sdio_card_reset, | 2384 | .card_reset = mwifiex_sdio_card_reset, |
2292 | .iface_work = mwifiex_sdio_work, | ||
2293 | .fw_dump = mwifiex_sdio_fw_dump, | 2385 | .fw_dump = mwifiex_sdio_fw_dump, |
2294 | .reg_dump = mwifiex_sdio_reg_dump, | 2386 | .reg_dump = mwifiex_sdio_reg_dump, |
2387 | .deaggr_pkt = mwifiex_deaggr_sdio_pkt, | ||
2295 | }; | 2388 | }; |
2296 | 2389 | ||
2297 | /* | 2390 | /* |
@@ -2328,6 +2421,7 @@ mwifiex_sdio_cleanup_module(void) | |||
2328 | 2421 | ||
2329 | /* Set the flag as user is removing this module. */ | 2422 | /* Set the flag as user is removing this module. */ |
2330 | user_rmmod = 1; | 2423 | user_rmmod = 1; |
2424 | cancel_work_sync(&sdio_work); | ||
2331 | 2425 | ||
2332 | sdio_unregister_driver(&mwifiex_sdio); | 2426 | sdio_unregister_driver(&mwifiex_sdio); |
2333 | } | 2427 | } |
diff --git a/drivers/net/wireless/mwifiex/sdio.h b/drivers/net/wireless/mwifiex/sdio.h index c636944c77bc..6f645cf47369 100644 --- a/drivers/net/wireless/mwifiex/sdio.h +++ b/drivers/net/wireless/mwifiex/sdio.h | |||
@@ -67,6 +67,8 @@ | |||
67 | 67 | ||
68 | #define MWIFIEX_MP_AGGR_BUF_SIZE_16K (16384) | 68 | #define MWIFIEX_MP_AGGR_BUF_SIZE_16K (16384) |
69 | #define MWIFIEX_MP_AGGR_BUF_SIZE_32K (32768) | 69 | #define MWIFIEX_MP_AGGR_BUF_SIZE_32K (32768) |
70 | /* we leave one block of 256 bytes for DMA alignment*/ | ||
71 | #define MWIFIEX_MP_AGGR_BUF_SIZE_MAX (65280) | ||
70 | 72 | ||
71 | /* Misc. Config Register : Auto Re-enable interrupts */ | 73 | /* Misc. Config Register : Auto Re-enable interrupts */ |
72 | #define AUTO_RE_ENABLE_INT BIT(4) | 74 | #define AUTO_RE_ENABLE_INT BIT(4) |
@@ -458,8 +460,8 @@ static const struct mwifiex_sdio_device mwifiex_sdio_sd8897 = { | |||
458 | .max_ports = 32, | 460 | .max_ports = 32, |
459 | .mp_agg_pkt_limit = 16, | 461 | .mp_agg_pkt_limit = 16, |
460 | .tx_buf_size = MWIFIEX_TX_DATA_BUF_SIZE_4K, | 462 | .tx_buf_size = MWIFIEX_TX_DATA_BUF_SIZE_4K, |
461 | .mp_tx_agg_buf_size = MWIFIEX_MP_AGGR_BUF_SIZE_32K, | 463 | .mp_tx_agg_buf_size = MWIFIEX_MP_AGGR_BUF_SIZE_MAX, |
462 | .mp_rx_agg_buf_size = MWIFIEX_MP_AGGR_BUF_SIZE_32K, | 464 | .mp_rx_agg_buf_size = MWIFIEX_MP_AGGR_BUF_SIZE_MAX, |
463 | .supports_sdio_new_mode = true, | 465 | .supports_sdio_new_mode = true, |
464 | .has_control_mask = false, | 466 | .has_control_mask = false, |
465 | .can_dump_fw = true, | 467 | .can_dump_fw = true, |
@@ -571,9 +573,9 @@ mp_tx_aggr_port_limit_reached(struct sdio_mmc_card *card) | |||
571 | 573 | ||
572 | /* Prepare to copy current packet from card to SDIO Rx aggregation buffer */ | 574 | /* Prepare to copy current packet from card to SDIO Rx aggregation buffer */ |
573 | static inline void mp_rx_aggr_setup(struct sdio_mmc_card *card, | 575 | static inline void mp_rx_aggr_setup(struct sdio_mmc_card *card, |
574 | struct sk_buff *skb, u8 port) | 576 | u16 rx_len, u8 port) |
575 | { | 577 | { |
576 | card->mpa_rx.buf_len += skb->len; | 578 | card->mpa_rx.buf_len += rx_len; |
577 | 579 | ||
578 | if (!card->mpa_rx.pkt_cnt) | 580 | if (!card->mpa_rx.pkt_cnt) |
579 | card->mpa_rx.start_port = port; | 581 | card->mpa_rx.start_port = port; |
@@ -586,8 +588,8 @@ static inline void mp_rx_aggr_setup(struct sdio_mmc_card *card, | |||
586 | else | 588 | else |
587 | card->mpa_rx.ports |= 1 << (card->mpa_rx.pkt_cnt + 1); | 589 | card->mpa_rx.ports |= 1 << (card->mpa_rx.pkt_cnt + 1); |
588 | } | 590 | } |
589 | card->mpa_rx.skb_arr[card->mpa_rx.pkt_cnt] = skb; | 591 | card->mpa_rx.skb_arr[card->mpa_rx.pkt_cnt] = NULL; |
590 | card->mpa_rx.len_arr[card->mpa_rx.pkt_cnt] = skb->len; | 592 | card->mpa_rx.len_arr[card->mpa_rx.pkt_cnt] = rx_len; |
591 | card->mpa_rx.pkt_cnt++; | 593 | card->mpa_rx.pkt_cnt++; |
592 | } | 594 | } |
593 | #endif /* _MWIFIEX_SDIO_H */ | 595 | #endif /* _MWIFIEX_SDIO_H */ |
diff --git a/drivers/net/wireless/mwifiex/sta_cmd.c b/drivers/net/wireless/mwifiex/sta_cmd.c index f7d204ffd6e9..49422f2a5380 100644 --- a/drivers/net/wireless/mwifiex/sta_cmd.c +++ b/drivers/net/wireless/mwifiex/sta_cmd.c | |||
@@ -1370,22 +1370,29 @@ mwifiex_cmd_mef_cfg(struct mwifiex_private *priv, | |||
1370 | struct mwifiex_ds_mef_cfg *mef) | 1370 | struct mwifiex_ds_mef_cfg *mef) |
1371 | { | 1371 | { |
1372 | struct host_cmd_ds_mef_cfg *mef_cfg = &cmd->params.mef_cfg; | 1372 | struct host_cmd_ds_mef_cfg *mef_cfg = &cmd->params.mef_cfg; |
1373 | struct mwifiex_fw_mef_entry *mef_entry = NULL; | ||
1373 | u8 *pos = (u8 *)mef_cfg; | 1374 | u8 *pos = (u8 *)mef_cfg; |
1375 | u16 i; | ||
1374 | 1376 | ||
1375 | cmd->command = cpu_to_le16(HostCmd_CMD_MEF_CFG); | 1377 | cmd->command = cpu_to_le16(HostCmd_CMD_MEF_CFG); |
1376 | 1378 | ||
1377 | mef_cfg->criteria = cpu_to_le32(mef->criteria); | 1379 | mef_cfg->criteria = cpu_to_le32(mef->criteria); |
1378 | mef_cfg->num_entries = cpu_to_le16(mef->num_entries); | 1380 | mef_cfg->num_entries = cpu_to_le16(mef->num_entries); |
1379 | pos += sizeof(*mef_cfg); | 1381 | pos += sizeof(*mef_cfg); |
1380 | mef_cfg->mef_entry->mode = mef->mef_entry->mode; | ||
1381 | mef_cfg->mef_entry->action = mef->mef_entry->action; | ||
1382 | pos += sizeof(*(mef_cfg->mef_entry)); | ||
1383 | 1382 | ||
1384 | if (mwifiex_cmd_append_rpn_expression(priv, mef->mef_entry, &pos)) | 1383 | for (i = 0; i < mef->num_entries; i++) { |
1385 | return -1; | 1384 | mef_entry = (struct mwifiex_fw_mef_entry *)pos; |
1385 | mef_entry->mode = mef->mef_entry[i].mode; | ||
1386 | mef_entry->action = mef->mef_entry[i].action; | ||
1387 | pos += sizeof(*mef_cfg->mef_entry); | ||
1388 | |||
1389 | if (mwifiex_cmd_append_rpn_expression(priv, | ||
1390 | &mef->mef_entry[i], &pos)) | ||
1391 | return -1; | ||
1386 | 1392 | ||
1387 | mef_cfg->mef_entry->exprsize = | 1393 | mef_entry->exprsize = |
1388 | cpu_to_le16(pos - mef_cfg->mef_entry->expr); | 1394 | cpu_to_le16(pos - mef_entry->expr); |
1395 | } | ||
1389 | cmd->size = cpu_to_le16((u16) (pos - (u8 *)mef_cfg) + S_DS_GEN); | 1396 | cmd->size = cpu_to_le16((u16) (pos - (u8 *)mef_cfg) + S_DS_GEN); |
1390 | 1397 | ||
1391 | return 0; | 1398 | return 0; |
@@ -1664,6 +1671,25 @@ mwifiex_cmd_tdls_oper(struct mwifiex_private *priv, | |||
1664 | 1671 | ||
1665 | return 0; | 1672 | return 0; |
1666 | } | 1673 | } |
1674 | |||
1675 | /* This function prepares command of sdio rx aggr info. */ | ||
1676 | static int mwifiex_cmd_sdio_rx_aggr_cfg(struct host_cmd_ds_command *cmd, | ||
1677 | u16 cmd_action, void *data_buf) | ||
1678 | { | ||
1679 | struct host_cmd_sdio_sp_rx_aggr_cfg *cfg = | ||
1680 | &cmd->params.sdio_rx_aggr_cfg; | ||
1681 | |||
1682 | cmd->command = cpu_to_le16(HostCmd_CMD_SDIO_SP_RX_AGGR_CFG); | ||
1683 | cmd->size = | ||
1684 | cpu_to_le16(sizeof(struct host_cmd_sdio_sp_rx_aggr_cfg) + | ||
1685 | S_DS_GEN); | ||
1686 | cfg->action = cmd_action; | ||
1687 | if (cmd_action == HostCmd_ACT_GEN_SET) | ||
1688 | cfg->enable = *(u8 *)data_buf; | ||
1689 | |||
1690 | return 0; | ||
1691 | } | ||
1692 | |||
1667 | /* | 1693 | /* |
1668 | * This function prepares the commands before sending them to the firmware. | 1694 | * This function prepares the commands before sending them to the firmware. |
1669 | * | 1695 | * |
@@ -1901,6 +1927,10 @@ int mwifiex_sta_prepare_cmd(struct mwifiex_private *priv, uint16_t cmd_no, | |||
1901 | ret = mwifiex_cmd_issue_chan_report_request(priv, cmd_ptr, | 1927 | ret = mwifiex_cmd_issue_chan_report_request(priv, cmd_ptr, |
1902 | data_buf); | 1928 | data_buf); |
1903 | break; | 1929 | break; |
1930 | case HostCmd_CMD_SDIO_SP_RX_AGGR_CFG: | ||
1931 | ret = mwifiex_cmd_sdio_rx_aggr_cfg(cmd_ptr, cmd_action, | ||
1932 | data_buf); | ||
1933 | break; | ||
1904 | default: | 1934 | default: |
1905 | dev_err(priv->adapter->dev, | 1935 | dev_err(priv->adapter->dev, |
1906 | "PREP_CMD: unknown cmd- %#x\n", cmd_no); | 1936 | "PREP_CMD: unknown cmd- %#x\n", cmd_no); |
@@ -1940,6 +1970,7 @@ int mwifiex_sta_init_cmd(struct mwifiex_private *priv, u8 first_sta, bool init) | |||
1940 | struct mwifiex_ds_auto_ds auto_ds; | 1970 | struct mwifiex_ds_auto_ds auto_ds; |
1941 | enum state_11d_t state_11d; | 1971 | enum state_11d_t state_11d; |
1942 | struct mwifiex_ds_11n_tx_cfg tx_cfg; | 1972 | struct mwifiex_ds_11n_tx_cfg tx_cfg; |
1973 | u8 sdio_sp_rx_aggr_enable; | ||
1943 | 1974 | ||
1944 | if (first_sta) { | 1975 | if (first_sta) { |
1945 | if (priv->adapter->iface_type == MWIFIEX_PCIE) { | 1976 | if (priv->adapter->iface_type == MWIFIEX_PCIE) { |
@@ -1983,6 +2014,22 @@ int mwifiex_sta_init_cmd(struct mwifiex_private *priv, u8 first_sta, bool init) | |||
1983 | if (ret) | 2014 | if (ret) |
1984 | return -1; | 2015 | return -1; |
1985 | 2016 | ||
2017 | /** Set SDIO Single Port RX Aggr Info */ | ||
2018 | if (priv->adapter->iface_type == MWIFIEX_SDIO && | ||
2019 | ISSUPP_SDIO_SPA_ENABLED(priv->adapter->fw_cap_info)) { | ||
2020 | sdio_sp_rx_aggr_enable = true; | ||
2021 | ret = mwifiex_send_cmd(priv, | ||
2022 | HostCmd_CMD_SDIO_SP_RX_AGGR_CFG, | ||
2023 | HostCmd_ACT_GEN_SET, 0, | ||
2024 | &sdio_sp_rx_aggr_enable, | ||
2025 | true); | ||
2026 | if (ret) { | ||
2027 | dev_err(priv->adapter->dev, | ||
2028 | "error while enabling SP aggregation..disable it"); | ||
2029 | adapter->sdio_rx_aggr_enable = false; | ||
2030 | } | ||
2031 | } | ||
2032 | |||
1986 | /* Reconfigure tx buf size */ | 2033 | /* Reconfigure tx buf size */ |
1987 | ret = mwifiex_send_cmd(priv, HostCmd_CMD_RECONFIGURE_TX_BUFF, | 2034 | ret = mwifiex_send_cmd(priv, HostCmd_CMD_RECONFIGURE_TX_BUFF, |
1988 | HostCmd_ACT_GEN_SET, 0, | 2035 | HostCmd_ACT_GEN_SET, 0, |
diff --git a/drivers/net/wireless/mwifiex/sta_cmdresp.c b/drivers/net/wireless/mwifiex/sta_cmdresp.c index 5f8da5924666..88dc6b672ef4 100644 --- a/drivers/net/wireless/mwifiex/sta_cmdresp.c +++ b/drivers/net/wireless/mwifiex/sta_cmdresp.c | |||
@@ -90,6 +90,10 @@ mwifiex_process_cmdresp_error(struct mwifiex_private *priv, | |||
90 | case HostCmd_CMD_MAC_CONTROL: | 90 | case HostCmd_CMD_MAC_CONTROL: |
91 | break; | 91 | break; |
92 | 92 | ||
93 | case HostCmd_CMD_SDIO_SP_RX_AGGR_CFG: | ||
94 | dev_err(priv->adapter->dev, "SDIO RX single-port aggregation Not support\n"); | ||
95 | break; | ||
96 | |||
93 | default: | 97 | default: |
94 | break; | 98 | break; |
95 | } | 99 | } |
@@ -943,6 +947,20 @@ static int mwifiex_ret_cfg_data(struct mwifiex_private *priv, | |||
943 | return 0; | 947 | return 0; |
944 | } | 948 | } |
945 | 949 | ||
950 | /** This Function handles the command response of sdio rx aggr */ | ||
951 | static int mwifiex_ret_sdio_rx_aggr_cfg(struct mwifiex_private *priv, | ||
952 | struct host_cmd_ds_command *resp) | ||
953 | { | ||
954 | struct mwifiex_adapter *adapter = priv->adapter; | ||
955 | struct host_cmd_sdio_sp_rx_aggr_cfg *cfg = | ||
956 | &resp->params.sdio_rx_aggr_cfg; | ||
957 | |||
958 | adapter->sdio_rx_aggr_enable = cfg->enable; | ||
959 | adapter->sdio_rx_block_size = le16_to_cpu(cfg->block_size); | ||
960 | |||
961 | return 0; | ||
962 | } | ||
963 | |||
946 | /* | 964 | /* |
947 | * This function handles the command responses. | 965 | * This function handles the command responses. |
948 | * | 966 | * |
@@ -1124,6 +1142,9 @@ int mwifiex_process_sta_cmdresp(struct mwifiex_private *priv, u16 cmdresp_no, | |||
1124 | break; | 1142 | break; |
1125 | case HostCmd_CMD_CHAN_REPORT_REQUEST: | 1143 | case HostCmd_CMD_CHAN_REPORT_REQUEST: |
1126 | break; | 1144 | break; |
1145 | case HostCmd_CMD_SDIO_SP_RX_AGGR_CFG: | ||
1146 | ret = mwifiex_ret_sdio_rx_aggr_cfg(priv, resp); | ||
1147 | break; | ||
1127 | default: | 1148 | default: |
1128 | dev_err(adapter->dev, "CMD_RESP: unknown cmd response %#x\n", | 1149 | dev_err(adapter->dev, "CMD_RESP: unknown cmd response %#x\n", |
1129 | resp->command); | 1150 | resp->command); |
diff --git a/drivers/net/wireless/mwifiex/sta_event.c b/drivers/net/wireless/mwifiex/sta_event.c index 64c4223a1e1e..0dc7a1d3993d 100644 --- a/drivers/net/wireless/mwifiex/sta_event.c +++ b/drivers/net/wireless/mwifiex/sta_event.c | |||
@@ -312,7 +312,7 @@ int mwifiex_process_sta_event(struct mwifiex_private *priv) | |||
312 | adapter->ps_state = PS_STATE_AWAKE; | 312 | adapter->ps_state = PS_STATE_AWAKE; |
313 | adapter->pm_wakeup_card_req = false; | 313 | adapter->pm_wakeup_card_req = false; |
314 | adapter->pm_wakeup_fw_try = false; | 314 | adapter->pm_wakeup_fw_try = false; |
315 | del_timer_sync(&adapter->wakeup_timer); | 315 | del_timer(&adapter->wakeup_timer); |
316 | break; | 316 | break; |
317 | } | 317 | } |
318 | if (!mwifiex_send_null_packet | 318 | if (!mwifiex_send_null_packet |
@@ -327,7 +327,7 @@ int mwifiex_process_sta_event(struct mwifiex_private *priv) | |||
327 | adapter->ps_state = PS_STATE_AWAKE; | 327 | adapter->ps_state = PS_STATE_AWAKE; |
328 | adapter->pm_wakeup_card_req = false; | 328 | adapter->pm_wakeup_card_req = false; |
329 | adapter->pm_wakeup_fw_try = false; | 329 | adapter->pm_wakeup_fw_try = false; |
330 | del_timer_sync(&adapter->wakeup_timer); | 330 | del_timer(&adapter->wakeup_timer); |
331 | 331 | ||
332 | break; | 332 | break; |
333 | 333 | ||
diff --git a/drivers/net/wireless/mwifiex/txrx.c b/drivers/net/wireless/mwifiex/txrx.c index ea4549f0e0b9..a245f444aeec 100644 --- a/drivers/net/wireless/mwifiex/txrx.c +++ b/drivers/net/wireless/mwifiex/txrx.c | |||
@@ -92,6 +92,12 @@ int mwifiex_process_tx(struct mwifiex_private *priv, struct sk_buff *skb, | |||
92 | else | 92 | else |
93 | head_ptr = mwifiex_process_sta_txpd(priv, skb); | 93 | head_ptr = mwifiex_process_sta_txpd(priv, skb); |
94 | 94 | ||
95 | if ((adapter->data_sent || adapter->tx_lock_flag) && head_ptr) { | ||
96 | skb_queue_tail(&adapter->tx_data_q, skb); | ||
97 | atomic_inc(&adapter->tx_queued); | ||
98 | return 0; | ||
99 | } | ||
100 | |||
95 | if (head_ptr) { | 101 | if (head_ptr) { |
96 | if (GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_STA) | 102 | if (GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_STA) |
97 | local_tx_pd = (struct txpd *)(head_ptr + hroom); | 103 | local_tx_pd = (struct txpd *)(head_ptr + hroom); |
@@ -142,6 +148,123 @@ int mwifiex_process_tx(struct mwifiex_private *priv, struct sk_buff *skb, | |||
142 | return ret; | 148 | return ret; |
143 | } | 149 | } |
144 | 150 | ||
151 | static int mwifiex_host_to_card(struct mwifiex_adapter *adapter, | ||
152 | struct sk_buff *skb, | ||
153 | struct mwifiex_tx_param *tx_param) | ||
154 | { | ||
155 | struct txpd *local_tx_pd = NULL; | ||
156 | u8 *head_ptr = skb->data; | ||
157 | int ret = 0; | ||
158 | struct mwifiex_private *priv; | ||
159 | struct mwifiex_txinfo *tx_info; | ||
160 | |||
161 | tx_info = MWIFIEX_SKB_TXCB(skb); | ||
162 | priv = mwifiex_get_priv_by_id(adapter, tx_info->bss_num, | ||
163 | tx_info->bss_type); | ||
164 | if (!priv) { | ||
165 | dev_err(adapter->dev, "data: priv not found. Drop TX packet\n"); | ||
166 | adapter->dbg.num_tx_host_to_card_failure++; | ||
167 | mwifiex_write_data_complete(adapter, skb, 0, 0); | ||
168 | return ret; | ||
169 | } | ||
170 | if (GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_STA) { | ||
171 | if (adapter->iface_type == MWIFIEX_USB) | ||
172 | local_tx_pd = (struct txpd *)head_ptr; | ||
173 | else | ||
174 | local_tx_pd = (struct txpd *) (head_ptr + | ||
175 | INTF_HEADER_LEN); | ||
176 | } | ||
177 | |||
178 | if (adapter->iface_type == MWIFIEX_USB) { | ||
179 | adapter->data_sent = true; | ||
180 | ret = adapter->if_ops.host_to_card(adapter, | ||
181 | MWIFIEX_USB_EP_DATA, | ||
182 | skb, NULL); | ||
183 | } else { | ||
184 | ret = adapter->if_ops.host_to_card(adapter, | ||
185 | MWIFIEX_TYPE_DATA, | ||
186 | skb, tx_param); | ||
187 | } | ||
188 | switch (ret) { | ||
189 | case -ENOSR: | ||
190 | dev_err(adapter->dev, "data: -ENOSR is returned\n"); | ||
191 | break; | ||
192 | case -EBUSY: | ||
193 | if ((GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_STA) && | ||
194 | (adapter->pps_uapsd_mode) && | ||
195 | (adapter->tx_lock_flag)) { | ||
196 | priv->adapter->tx_lock_flag = false; | ||
197 | if (local_tx_pd) | ||
198 | local_tx_pd->flags = 0; | ||
199 | } | ||
200 | skb_queue_head(&adapter->tx_data_q, skb); | ||
201 | if (tx_info->flags & MWIFIEX_BUF_FLAG_AGGR_PKT) | ||
202 | atomic_add(tx_info->aggr_num, &adapter->tx_queued); | ||
203 | else | ||
204 | atomic_inc(&adapter->tx_queued); | ||
205 | dev_dbg(adapter->dev, "data: -EBUSY is returned\n"); | ||
206 | break; | ||
207 | case -1: | ||
208 | if (adapter->iface_type != MWIFIEX_PCIE) | ||
209 | adapter->data_sent = false; | ||
210 | dev_err(adapter->dev, "mwifiex_write_data_async failed: 0x%X\n", | ||
211 | ret); | ||
212 | adapter->dbg.num_tx_host_to_card_failure++; | ||
213 | mwifiex_write_data_complete(adapter, skb, 0, ret); | ||
214 | break; | ||
215 | case -EINPROGRESS: | ||
216 | if (adapter->iface_type != MWIFIEX_PCIE) | ||
217 | adapter->data_sent = false; | ||
218 | break; | ||
219 | case 0: | ||
220 | mwifiex_write_data_complete(adapter, skb, 0, ret); | ||
221 | break; | ||
222 | default: | ||
223 | break; | ||
224 | } | ||
225 | return ret; | ||
226 | } | ||
227 | |||
228 | static int | ||
229 | mwifiex_dequeue_tx_queue(struct mwifiex_adapter *adapter) | ||
230 | { | ||
231 | struct sk_buff *skb, *skb_next; | ||
232 | struct mwifiex_txinfo *tx_info; | ||
233 | struct mwifiex_tx_param tx_param; | ||
234 | |||
235 | skb = skb_dequeue(&adapter->tx_data_q); | ||
236 | if (!skb) | ||
237 | return -1; | ||
238 | |||
239 | tx_info = MWIFIEX_SKB_TXCB(skb); | ||
240 | if (tx_info->flags & MWIFIEX_BUF_FLAG_AGGR_PKT) | ||
241 | atomic_sub(tx_info->aggr_num, &adapter->tx_queued); | ||
242 | else | ||
243 | atomic_dec(&adapter->tx_queued); | ||
244 | |||
245 | if (!skb_queue_empty(&adapter->tx_data_q)) | ||
246 | skb_next = skb_peek(&adapter->tx_data_q); | ||
247 | else | ||
248 | skb_next = NULL; | ||
249 | tx_param.next_pkt_len = ((skb_next) ? skb_next->len : 0); | ||
250 | if (!tx_param.next_pkt_len) { | ||
251 | if (!mwifiex_wmm_lists_empty(adapter)) | ||
252 | tx_param.next_pkt_len = 1; | ||
253 | } | ||
254 | return mwifiex_host_to_card(adapter, skb, &tx_param); | ||
255 | } | ||
256 | |||
257 | void | ||
258 | mwifiex_process_tx_queue(struct mwifiex_adapter *adapter) | ||
259 | { | ||
260 | do { | ||
261 | if (adapter->data_sent || adapter->tx_lock_flag) | ||
262 | break; | ||
263 | if (mwifiex_dequeue_tx_queue(adapter)) | ||
264 | break; | ||
265 | } while (!skb_queue_empty(&adapter->tx_data_q)); | ||
266 | } | ||
267 | |||
145 | /* | 268 | /* |
146 | * Packet send completion callback handler. | 269 | * Packet send completion callback handler. |
147 | * | 270 | * |
@@ -179,8 +302,11 @@ int mwifiex_write_data_complete(struct mwifiex_adapter *adapter, | |||
179 | priv->stats.tx_errors++; | 302 | priv->stats.tx_errors++; |
180 | } | 303 | } |
181 | 304 | ||
182 | if (tx_info->flags & MWIFIEX_BUF_FLAG_BRIDGED_PKT) | 305 | if (tx_info->flags & MWIFIEX_BUF_FLAG_BRIDGED_PKT) { |
183 | atomic_dec_return(&adapter->pending_bridged_pkts); | 306 | atomic_dec_return(&adapter->pending_bridged_pkts); |
307 | if (tx_info->flags & MWIFIEX_BUF_FLAG_AGGR_PKT) | ||
308 | goto done; | ||
309 | } | ||
184 | 310 | ||
185 | if (aggr) | 311 | if (aggr) |
186 | /* For skb_aggr, do not wake up tx queue */ | 312 | /* For skb_aggr, do not wake up tx queue */ |
diff --git a/drivers/net/wireless/mwifiex/usb.c b/drivers/net/wireless/mwifiex/usb.c index 223873022ffe..fd8027f200a0 100644 --- a/drivers/net/wireless/mwifiex/usb.c +++ b/drivers/net/wireless/mwifiex/usb.c | |||
@@ -193,7 +193,7 @@ static void mwifiex_usb_rx_complete(struct urb *urb) | |||
193 | dev_dbg(adapter->dev, "info: recv_length=%d, status=%d\n", | 193 | dev_dbg(adapter->dev, "info: recv_length=%d, status=%d\n", |
194 | recv_length, status); | 194 | recv_length, status); |
195 | if (status == -EINPROGRESS) { | 195 | if (status == -EINPROGRESS) { |
196 | queue_work(adapter->workqueue, &adapter->main_work); | 196 | mwifiex_queue_main_work(adapter); |
197 | 197 | ||
198 | /* urb for data_ep is re-submitted now; | 198 | /* urb for data_ep is re-submitted now; |
199 | * urb for cmd_ep will be re-submitted in callback | 199 | * urb for cmd_ep will be re-submitted in callback |
@@ -262,7 +262,7 @@ static void mwifiex_usb_tx_complete(struct urb *urb) | |||
262 | urb->status ? -1 : 0); | 262 | urb->status ? -1 : 0); |
263 | } | 263 | } |
264 | 264 | ||
265 | queue_work(adapter->workqueue, &adapter->main_work); | 265 | mwifiex_queue_main_work(adapter); |
266 | 266 | ||
267 | return; | 267 | return; |
268 | } | 268 | } |
@@ -1006,7 +1006,7 @@ static int mwifiex_pm_wakeup_card(struct mwifiex_adapter *adapter) | |||
1006 | { | 1006 | { |
1007 | /* Simulation of HS_AWAKE event */ | 1007 | /* Simulation of HS_AWAKE event */ |
1008 | adapter->pm_wakeup_fw_try = false; | 1008 | adapter->pm_wakeup_fw_try = false; |
1009 | del_timer_sync(&adapter->wakeup_timer); | 1009 | del_timer(&adapter->wakeup_timer); |
1010 | adapter->pm_wakeup_card_req = false; | 1010 | adapter->pm_wakeup_card_req = false; |
1011 | adapter->ps_state = PS_STATE_AWAKE; | 1011 | adapter->ps_state = PS_STATE_AWAKE; |
1012 | 1012 | ||
diff --git a/drivers/net/wireless/mwifiex/util.c b/drivers/net/wireless/mwifiex/util.c index 2148a573396b..b8a45872354d 100644 --- a/drivers/net/wireless/mwifiex/util.c +++ b/drivers/net/wireless/mwifiex/util.c | |||
@@ -632,7 +632,7 @@ void mwifiex_hist_data_reset(struct mwifiex_private *priv) | |||
632 | atomic_set(&phist_data->sig_str[ix], 0); | 632 | atomic_set(&phist_data->sig_str[ix], 0); |
633 | } | 633 | } |
634 | 634 | ||
635 | void *mwifiex_alloc_rx_buf(int rx_len, gfp_t flags) | 635 | void *mwifiex_alloc_dma_align_buf(int rx_len, gfp_t flags) |
636 | { | 636 | { |
637 | struct sk_buff *skb; | 637 | struct sk_buff *skb; |
638 | int buf_len, pad; | 638 | int buf_len, pad; |
@@ -653,4 +653,4 @@ void *mwifiex_alloc_rx_buf(int rx_len, gfp_t flags) | |||
653 | 653 | ||
654 | return skb; | 654 | return skb; |
655 | } | 655 | } |
656 | EXPORT_SYMBOL_GPL(mwifiex_alloc_rx_buf); | 656 | EXPORT_SYMBOL_GPL(mwifiex_alloc_dma_align_buf); |
diff --git a/drivers/net/wireless/mwifiex/wmm.c b/drivers/net/wireless/mwifiex/wmm.c index 0cd4f6bed9fc..b2e99569a0f8 100644 --- a/drivers/net/wireless/mwifiex/wmm.c +++ b/drivers/net/wireless/mwifiex/wmm.c | |||
@@ -157,6 +157,8 @@ void mwifiex_ralist_add(struct mwifiex_private *priv, const u8 *ra) | |||
157 | 157 | ||
158 | ra_list->is_11n_enabled = 0; | 158 | ra_list->is_11n_enabled = 0; |
159 | ra_list->tdls_link = false; | 159 | ra_list->tdls_link = false; |
160 | ra_list->ba_status = BA_SETUP_NONE; | ||
161 | ra_list->amsdu_in_ampdu = false; | ||
160 | if (!mwifiex_queuing_ra_based(priv)) { | 162 | if (!mwifiex_queuing_ra_based(priv)) { |
161 | if (mwifiex_get_tdls_link_status(priv, ra) == | 163 | if (mwifiex_get_tdls_link_status(priv, ra) == |
162 | TDLS_SETUP_COMPLETE) { | 164 | TDLS_SETUP_COMPLETE) { |
@@ -574,7 +576,7 @@ mwifiex_clean_txrx(struct mwifiex_private *priv) | |||
574 | * This function retrieves a particular RA list node, matching with the | 576 | * This function retrieves a particular RA list node, matching with the |
575 | * given TID and RA address. | 577 | * given TID and RA address. |
576 | */ | 578 | */ |
577 | static struct mwifiex_ra_list_tbl * | 579 | struct mwifiex_ra_list_tbl * |
578 | mwifiex_wmm_get_ralist_node(struct mwifiex_private *priv, u8 tid, | 580 | mwifiex_wmm_get_ralist_node(struct mwifiex_private *priv, u8 tid, |
579 | const u8 *ra_addr) | 581 | const u8 *ra_addr) |
580 | { | 582 | { |
@@ -942,14 +944,11 @@ mwifiex_wmm_get_highest_priolist_ptr(struct mwifiex_adapter *adapter, | |||
942 | struct mwifiex_ra_list_tbl *ptr; | 944 | struct mwifiex_ra_list_tbl *ptr; |
943 | struct mwifiex_tid_tbl *tid_ptr; | 945 | struct mwifiex_tid_tbl *tid_ptr; |
944 | atomic_t *hqp; | 946 | atomic_t *hqp; |
945 | unsigned long flags_bss, flags_ra; | 947 | unsigned long flags_ra; |
946 | int i, j; | 948 | int i, j; |
947 | 949 | ||
948 | /* check the BSS with highest priority first */ | 950 | /* check the BSS with highest priority first */ |
949 | for (j = adapter->priv_num - 1; j >= 0; --j) { | 951 | for (j = adapter->priv_num - 1; j >= 0; --j) { |
950 | spin_lock_irqsave(&adapter->bss_prio_tbl[j].bss_prio_lock, | ||
951 | flags_bss); | ||
952 | |||
953 | /* iterate over BSS with the equal priority */ | 952 | /* iterate over BSS with the equal priority */ |
954 | list_for_each_entry(adapter->bss_prio_tbl[j].bss_prio_cur, | 953 | list_for_each_entry(adapter->bss_prio_tbl[j].bss_prio_cur, |
955 | &adapter->bss_prio_tbl[j].bss_prio_head, | 954 | &adapter->bss_prio_tbl[j].bss_prio_head, |
@@ -985,19 +984,15 @@ mwifiex_wmm_get_highest_priolist_ptr(struct mwifiex_adapter *adapter, | |||
985 | } | 984 | } |
986 | } | 985 | } |
987 | 986 | ||
988 | spin_unlock_irqrestore(&adapter->bss_prio_tbl[j].bss_prio_lock, | ||
989 | flags_bss); | ||
990 | } | 987 | } |
991 | 988 | ||
992 | return NULL; | 989 | return NULL; |
993 | 990 | ||
994 | found: | 991 | found: |
995 | /* holds bss_prio_lock / ra_list_spinlock */ | 992 | /* holds ra_list_spinlock */ |
996 | if (atomic_read(hqp) > i) | 993 | if (atomic_read(hqp) > i) |
997 | atomic_set(hqp, i); | 994 | atomic_set(hqp, i); |
998 | spin_unlock_irqrestore(&priv_tmp->wmm.ra_list_spinlock, flags_ra); | 995 | spin_unlock_irqrestore(&priv_tmp->wmm.ra_list_spinlock, flags_ra); |
999 | spin_unlock_irqrestore(&adapter->bss_prio_tbl[j].bss_prio_lock, | ||
1000 | flags_bss); | ||
1001 | 996 | ||
1002 | *priv = priv_tmp; | 997 | *priv = priv_tmp; |
1003 | *tid = tos_to_tid[i]; | 998 | *tid = tos_to_tid[i]; |
@@ -1179,6 +1174,14 @@ mwifiex_send_processed_packet(struct mwifiex_private *priv, | |||
1179 | 1174 | ||
1180 | skb = skb_dequeue(&ptr->skb_head); | 1175 | skb = skb_dequeue(&ptr->skb_head); |
1181 | 1176 | ||
1177 | if (adapter->data_sent || adapter->tx_lock_flag) { | ||
1178 | spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock, | ||
1179 | ra_list_flags); | ||
1180 | skb_queue_tail(&adapter->tx_data_q, skb); | ||
1181 | atomic_inc(&adapter->tx_queued); | ||
1182 | return; | ||
1183 | } | ||
1184 | |||
1182 | if (!skb_queue_empty(&ptr->skb_head)) | 1185 | if (!skb_queue_empty(&ptr->skb_head)) |
1183 | skb_next = skb_peek(&ptr->skb_head); | 1186 | skb_next = skb_peek(&ptr->skb_head); |
1184 | else | 1187 | else |
@@ -1276,13 +1279,13 @@ mwifiex_dequeue_tx_packet(struct mwifiex_adapter *adapter) | |||
1276 | } | 1279 | } |
1277 | 1280 | ||
1278 | if (!ptr->is_11n_enabled || | 1281 | if (!ptr->is_11n_enabled || |
1279 | mwifiex_is_ba_stream_setup(priv, ptr, tid) || | 1282 | ptr->ba_status || |
1280 | priv->wps.session_enable) { | 1283 | priv->wps.session_enable) { |
1281 | if (ptr->is_11n_enabled && | 1284 | if (ptr->is_11n_enabled && |
1282 | mwifiex_is_ba_stream_setup(priv, ptr, tid) && | 1285 | ptr->ba_status && |
1283 | mwifiex_is_amsdu_in_ampdu_allowed(priv, ptr, tid) && | 1286 | ptr->amsdu_in_ampdu && |
1284 | mwifiex_is_amsdu_allowed(priv, tid) && | 1287 | mwifiex_is_amsdu_allowed(priv, tid) && |
1285 | mwifiex_is_11n_aggragation_possible(priv, ptr, | 1288 | mwifiex_is_11n_aggragation_possible(priv, ptr, |
1286 | adapter->tx_buf_size)) | 1289 | adapter->tx_buf_size)) |
1287 | mwifiex_11n_aggregate_pkt(priv, ptr, ptr_index, flags); | 1290 | mwifiex_11n_aggregate_pkt(priv, ptr, ptr_index, flags); |
1288 | /* ra_list_spinlock has been freed in | 1291 | /* ra_list_spinlock has been freed in |
@@ -1329,11 +1332,16 @@ void | |||
1329 | mwifiex_wmm_process_tx(struct mwifiex_adapter *adapter) | 1332 | mwifiex_wmm_process_tx(struct mwifiex_adapter *adapter) |
1330 | { | 1333 | { |
1331 | do { | 1334 | do { |
1332 | /* Check if busy */ | ||
1333 | if (adapter->data_sent || adapter->tx_lock_flag) | ||
1334 | break; | ||
1335 | |||
1336 | if (mwifiex_dequeue_tx_packet(adapter)) | 1335 | if (mwifiex_dequeue_tx_packet(adapter)) |
1337 | break; | 1336 | break; |
1337 | if (adapter->iface_type != MWIFIEX_SDIO) { | ||
1338 | if (adapter->data_sent || | ||
1339 | adapter->tx_lock_flag) | ||
1340 | break; | ||
1341 | } else { | ||
1342 | if (atomic_read(&adapter->tx_queued) >= | ||
1343 | MWIFIEX_MAX_PKTS_TXQ) | ||
1344 | break; | ||
1345 | } | ||
1338 | } while (!mwifiex_wmm_lists_empty(adapter)); | 1346 | } while (!mwifiex_wmm_lists_empty(adapter)); |
1339 | } | 1347 | } |
diff --git a/drivers/net/wireless/mwifiex/wmm.h b/drivers/net/wireless/mwifiex/wmm.h index 569bd73f33c5..48ece0b35591 100644 --- a/drivers/net/wireless/mwifiex/wmm.h +++ b/drivers/net/wireless/mwifiex/wmm.h | |||
@@ -127,4 +127,6 @@ mwifiex_wmm_get_queue_raptr(struct mwifiex_private *priv, u8 tid, | |||
127 | const u8 *ra_addr); | 127 | const u8 *ra_addr); |
128 | u8 mwifiex_wmm_downgrade_tid(struct mwifiex_private *priv, u32 tid); | 128 | u8 mwifiex_wmm_downgrade_tid(struct mwifiex_private *priv, u32 tid); |
129 | 129 | ||
130 | struct mwifiex_ra_list_tbl *mwifiex_wmm_get_ralist_node(struct mwifiex_private | ||
131 | *priv, u8 tid, const u8 *ra_addr); | ||
130 | #endif /* !_MWIFIEX_WMM_H_ */ | 132 | #endif /* !_MWIFIEX_WMM_H_ */ |