aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/mwl8k.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/wireless/mwl8k.c')
-rw-r--r--drivers/net/wireless/mwl8k.c77
1 files changed, 61 insertions, 16 deletions
diff --git a/drivers/net/wireless/mwl8k.c b/drivers/net/wireless/mwl8k.c
index 8913180a7bd..28ebaec80be 100644
--- a/drivers/net/wireless/mwl8k.c
+++ b/drivers/net/wireless/mwl8k.c
@@ -289,10 +289,17 @@ struct mwl8k_vif {
289#define MWL8K_VIF(_vif) ((struct mwl8k_vif *)&((_vif)->drv_priv)) 289#define MWL8K_VIF(_vif) ((struct mwl8k_vif *)&((_vif)->drv_priv))
290#define IEEE80211_KEY_CONF(_u8) ((struct ieee80211_key_conf *)(_u8)) 290#define IEEE80211_KEY_CONF(_u8) ((struct ieee80211_key_conf *)(_u8))
291 291
292struct tx_traffic_info {
293 u32 start_time;
294 u32 pkts;
295};
296
297#define MWL8K_MAX_TID 8
292struct mwl8k_sta { 298struct mwl8k_sta {
293 /* Index into station database. Returned by UPDATE_STADB. */ 299 /* Index into station database. Returned by UPDATE_STADB. */
294 u8 peer_id; 300 u8 peer_id;
295 u8 is_ampdu_allowed; 301 u8 is_ampdu_allowed;
302 struct tx_traffic_info tx_stats[MWL8K_MAX_TID];
296}; 303};
297#define MWL8K_STA(_sta) ((struct mwl8k_sta *)&((_sta)->drv_priv)) 304#define MWL8K_STA(_sta) ((struct mwl8k_sta *)&((_sta)->drv_priv))
298 305
@@ -701,7 +708,7 @@ static int mwl8k_load_firmware(struct ieee80211_hw *hw)
701 "helper image\n", pci_name(priv->pdev)); 708 "helper image\n", pci_name(priv->pdev));
702 return rc; 709 return rc;
703 } 710 }
704 msleep(5); 711 msleep(20);
705 712
706 rc = mwl8k_feed_fw_image(priv, fw->data, fw->size); 713 rc = mwl8k_feed_fw_image(priv, fw->data, fw->size);
707 } else { 714 } else {
@@ -823,8 +830,8 @@ static void mwl8k_encapsulate_tx_frame(struct sk_buff *skb)
823 /* 830 /*
824 * Make sure the packet header is in the DMA header format (4-address 831 * Make sure the packet header is in the DMA header format (4-address
825 * without QoS), the necessary crypto padding between the header and the 832 * without QoS), the necessary crypto padding between the header and the
826 * payload has already been provided by mac80211, but it doesn't add tail 833 * payload has already been provided by mac80211, but it doesn't add
827 * padding when HW crypto is enabled. 834 * tail padding when HW crypto is enabled.
828 * 835 *
829 * We have the following trailer padding requirements: 836 * We have the following trailer padding requirements:
830 * - WEP: 4 trailer bytes (ICV) 837 * - WEP: 4 trailer bytes (ICV)
@@ -1487,9 +1494,8 @@ static int mwl8k_tx_wait_empty(struct ieee80211_hw *hw)
1487 1494
1488 if (timeout) { 1495 if (timeout) {
1489 WARN_ON(priv->pending_tx_pkts); 1496 WARN_ON(priv->pending_tx_pkts);
1490 if (retry) { 1497 if (retry)
1491 wiphy_notice(hw->wiphy, "tx rings drained\n"); 1498 wiphy_notice(hw->wiphy, "tx rings drained\n");
1492 }
1493 break; 1499 break;
1494 } 1500 }
1495 1501
@@ -1649,8 +1655,8 @@ mwl8k_txq_reclaim(struct ieee80211_hw *hw, int index, int limit, int force)
1649 /* Rate control is happening in the firmware. 1655 /* Rate control is happening in the firmware.
1650 * Ensure no tx rate is being reported. 1656 * Ensure no tx rate is being reported.
1651 */ 1657 */
1652 info->status.rates[0].idx = -1; 1658 info->status.rates[0].idx = -1;
1653 info->status.rates[0].count = 1; 1659 info->status.rates[0].count = 1;
1654 1660
1655 if (MWL8K_TXD_SUCCESS(status)) 1661 if (MWL8K_TXD_SUCCESS(status))
1656 info->flags |= IEEE80211_TX_STAT_ACK; 1662 info->flags |= IEEE80211_TX_STAT_ACK;
@@ -1688,7 +1694,7 @@ static void mwl8k_txq_deinit(struct ieee80211_hw *hw, int index)
1688} 1694}
1689 1695
1690/* caller must hold priv->stream_lock when calling the stream functions */ 1696/* caller must hold priv->stream_lock when calling the stream functions */
1691struct mwl8k_ampdu_stream * 1697static struct mwl8k_ampdu_stream *
1692mwl8k_add_stream(struct ieee80211_hw *hw, struct ieee80211_sta *sta, u8 tid) 1698mwl8k_add_stream(struct ieee80211_hw *hw, struct ieee80211_sta *sta, u8 tid)
1693{ 1699{
1694 struct mwl8k_ampdu_stream *stream; 1700 struct mwl8k_ampdu_stream *stream;
@@ -1755,6 +1761,41 @@ mwl8k_lookup_stream(struct ieee80211_hw *hw, u8 *addr, u8 tid)
1755 return NULL; 1761 return NULL;
1756} 1762}
1757 1763
1764#define MWL8K_AMPDU_PACKET_THRESHOLD 64
1765static inline bool mwl8k_ampdu_allowed(struct ieee80211_sta *sta, u8 tid)
1766{
1767 struct mwl8k_sta *sta_info = MWL8K_STA(sta);
1768 struct tx_traffic_info *tx_stats;
1769
1770 BUG_ON(tid >= MWL8K_MAX_TID);
1771 tx_stats = &sta_info->tx_stats[tid];
1772
1773 return sta_info->is_ampdu_allowed &&
1774 tx_stats->pkts > MWL8K_AMPDU_PACKET_THRESHOLD;
1775}
1776
1777static inline void mwl8k_tx_count_packet(struct ieee80211_sta *sta, u8 tid)
1778{
1779 struct mwl8k_sta *sta_info = MWL8K_STA(sta);
1780 struct tx_traffic_info *tx_stats;
1781
1782 BUG_ON(tid >= MWL8K_MAX_TID);
1783 tx_stats = &sta_info->tx_stats[tid];
1784
1785 if (tx_stats->start_time == 0)
1786 tx_stats->start_time = jiffies;
1787
1788 /* reset the packet count after each second elapses. If the number of
1789 * packets ever exceeds the ampdu_min_traffic threshold, we will allow
1790 * an ampdu stream to be started.
1791 */
1792 if (jiffies - tx_stats->start_time > HZ) {
1793 tx_stats->pkts = 0;
1794 tx_stats->start_time = 0;
1795 } else
1796 tx_stats->pkts++;
1797}
1798
1758static void 1799static void
1759mwl8k_txq_xmit(struct ieee80211_hw *hw, int index, struct sk_buff *skb) 1800mwl8k_txq_xmit(struct ieee80211_hw *hw, int index, struct sk_buff *skb)
1760{ 1801{
@@ -1841,6 +1882,7 @@ mwl8k_txq_xmit(struct ieee80211_hw *hw, int index, struct sk_buff *skb)
1841 skb->protocol != cpu_to_be16(ETH_P_PAE) && 1882 skb->protocol != cpu_to_be16(ETH_P_PAE) &&
1842 sta->ht_cap.ht_supported && priv->ap_fw) { 1883 sta->ht_cap.ht_supported && priv->ap_fw) {
1843 tid = qos & 0xf; 1884 tid = qos & 0xf;
1885 mwl8k_tx_count_packet(sta, tid);
1844 spin_lock(&priv->stream_lock); 1886 spin_lock(&priv->stream_lock);
1845 stream = mwl8k_lookup_stream(hw, sta->addr, tid); 1887 stream = mwl8k_lookup_stream(hw, sta->addr, tid);
1846 if (stream != NULL) { 1888 if (stream != NULL) {
@@ -1881,7 +1923,7 @@ mwl8k_txq_xmit(struct ieee80211_hw *hw, int index, struct sk_buff *skb)
1881 * prevents sequence number mismatch at the recepient 1923 * prevents sequence number mismatch at the recepient
1882 * as described above. 1924 * as described above.
1883 */ 1925 */
1884 if (MWL8K_STA(sta)->is_ampdu_allowed) { 1926 if (mwl8k_ampdu_allowed(sta, tid)) {
1885 stream = mwl8k_add_stream(hw, sta, tid); 1927 stream = mwl8k_add_stream(hw, sta, tid);
1886 if (stream != NULL) 1928 if (stream != NULL)
1887 start_ba_session = true; 1929 start_ba_session = true;
@@ -2657,7 +2699,7 @@ struct mwl8k_cmd_tx_power {
2657 __le16 bw; 2699 __le16 bw;
2658 __le16 sub_ch; 2700 __le16 sub_ch;
2659 __le16 power_level_list[MWL8K_TX_POWER_LEVEL_TOTAL]; 2701 __le16 power_level_list[MWL8K_TX_POWER_LEVEL_TOTAL];
2660} __attribute__((packed)); 2702} __packed;
2661 2703
2662static int mwl8k_cmd_tx_power(struct ieee80211_hw *hw, 2704static int mwl8k_cmd_tx_power(struct ieee80211_hw *hw,
2663 struct ieee80211_conf *conf, 2705 struct ieee80211_conf *conf,
@@ -3520,13 +3562,13 @@ static int mwl8k_cmd_bss_start(struct ieee80211_hw *hw,
3520#define BASTREAM_FLAG_DIRECTION_UPSTREAM 0x00 3562#define BASTREAM_FLAG_DIRECTION_UPSTREAM 0x00
3521#define BASTREAM_FLAG_IMMEDIATE_TYPE 0x01 3563#define BASTREAM_FLAG_IMMEDIATE_TYPE 0x01
3522 3564
3523enum { 3565enum ba_stream_action_type {
3524 MWL8K_BA_CREATE, 3566 MWL8K_BA_CREATE,
3525 MWL8K_BA_UPDATE, 3567 MWL8K_BA_UPDATE,
3526 MWL8K_BA_DESTROY, 3568 MWL8K_BA_DESTROY,
3527 MWL8K_BA_FLUSH, 3569 MWL8K_BA_FLUSH,
3528 MWL8K_BA_CHECK, 3570 MWL8K_BA_CHECK,
3529} ba_stream_action_type; 3571};
3530 3572
3531 3573
3532struct mwl8k_create_ba_stream { 3574struct mwl8k_create_ba_stream {
@@ -3780,7 +3822,7 @@ struct mwl8k_cmd_update_encryption {
3780 __u8 mac_addr[6]; 3822 __u8 mac_addr[6];
3781 __u8 encr_type; 3823 __u8 encr_type;
3782 3824
3783} __attribute__((packed)); 3825} __packed;
3784 3826
3785struct mwl8k_cmd_set_key { 3827struct mwl8k_cmd_set_key {
3786 struct mwl8k_cmd_pkt header; 3828 struct mwl8k_cmd_pkt header;
@@ -3800,7 +3842,7 @@ struct mwl8k_cmd_set_key {
3800 __le16 tkip_tsc_low; 3842 __le16 tkip_tsc_low;
3801 __le32 tkip_tsc_high; 3843 __le32 tkip_tsc_high;
3802 __u8 mac_addr[6]; 3844 __u8 mac_addr[6];
3803} __attribute__((packed)); 3845} __packed;
3804 3846
3805enum { 3847enum {
3806 MWL8K_ENCR_ENABLE, 3848 MWL8K_ENCR_ENABLE,
@@ -4285,6 +4327,8 @@ static int mwl8k_start(struct ieee80211_hw *hw)
4285 4327
4286 /* Enable interrupts */ 4328 /* Enable interrupts */
4287 iowrite32(MWL8K_A2H_EVENTS, priv->regs + MWL8K_HIU_A2H_INTERRUPT_MASK); 4329 iowrite32(MWL8K_A2H_EVENTS, priv->regs + MWL8K_HIU_A2H_INTERRUPT_MASK);
4330 iowrite32(MWL8K_A2H_EVENTS,
4331 priv->regs + MWL8K_HIU_A2H_INTERRUPT_STATUS_MASK);
4288 4332
4289 rc = mwl8k_fw_lock(hw); 4333 rc = mwl8k_fw_lock(hw);
4290 if (!rc) { 4334 if (!rc) {
@@ -4502,7 +4546,7 @@ mwl8k_bss_info_changed_sta(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
4502 struct ieee80211_bss_conf *info, u32 changed) 4546 struct ieee80211_bss_conf *info, u32 changed)
4503{ 4547{
4504 struct mwl8k_priv *priv = hw->priv; 4548 struct mwl8k_priv *priv = hw->priv;
4505 u32 ap_legacy_rates; 4549 u32 ap_legacy_rates = 0;
4506 u8 ap_mcs_rates[16]; 4550 u8 ap_mcs_rates[16];
4507 int rc; 4551 int rc;
4508 4552
@@ -5283,7 +5327,8 @@ static int mwl8k_probe_hw(struct ieee80211_hw *hw)
5283 iowrite32(MWL8K_A2H_INT_TX_DONE|MWL8K_A2H_INT_RX_READY| 5327 iowrite32(MWL8K_A2H_INT_TX_DONE|MWL8K_A2H_INT_RX_READY|
5284 MWL8K_A2H_INT_BA_WATCHDOG, 5328 MWL8K_A2H_INT_BA_WATCHDOG,
5285 priv->regs + MWL8K_HIU_A2H_INTERRUPT_CLEAR_SEL); 5329 priv->regs + MWL8K_HIU_A2H_INTERRUPT_CLEAR_SEL);
5286 iowrite32(0xffffffff, priv->regs + MWL8K_HIU_A2H_INTERRUPT_STATUS_MASK); 5330 iowrite32(MWL8K_A2H_INT_OPC_DONE,
5331 priv->regs + MWL8K_HIU_A2H_INTERRUPT_STATUS_MASK);
5287 5332
5288 rc = request_irq(priv->pdev->irq, mwl8k_interrupt, 5333 rc = request_irq(priv->pdev->irq, mwl8k_interrupt,
5289 IRQF_SHARED, MWL8K_NAME, hw); 5334 IRQF_SHARED, MWL8K_NAME, hw);