diff options
Diffstat (limited to 'drivers/net/wireless/mwl8k.c')
-rw-r--r-- | drivers/net/wireless/mwl8k.c | 41 |
1 files changed, 34 insertions, 7 deletions
diff --git a/drivers/net/wireless/mwl8k.c b/drivers/net/wireless/mwl8k.c index 8fefed2342d7..9db66d58f0ef 100644 --- a/drivers/net/wireless/mwl8k.c +++ b/drivers/net/wireless/mwl8k.c | |||
@@ -86,6 +86,7 @@ MODULE_PARM_DESC(ap_mode_default, | |||
86 | 86 | ||
87 | #define MWL8K_RX_QUEUES 1 | 87 | #define MWL8K_RX_QUEUES 1 |
88 | #define MWL8K_TX_QUEUES 4 | 88 | #define MWL8K_TX_QUEUES 4 |
89 | #define MWL8K_MAX_AMPDU_QUEUES 8 | ||
89 | 90 | ||
90 | struct rxd_ops { | 91 | struct rxd_ops { |
91 | int rxd_size; | 92 | int rxd_size; |
@@ -159,6 +160,9 @@ struct mwl8k_priv { | |||
159 | u32 ap_macids_supported; | 160 | u32 ap_macids_supported; |
160 | u32 sta_macids_supported; | 161 | u32 sta_macids_supported; |
161 | 162 | ||
163 | /* Ampdu stream information */ | ||
164 | u8 num_ampdu_queues; | ||
165 | |||
162 | /* firmware access */ | 166 | /* firmware access */ |
163 | struct mutex fw_mutex; | 167 | struct mutex fw_mutex; |
164 | struct task_struct *fw_mutex_owner; | 168 | struct task_struct *fw_mutex_owner; |
@@ -190,8 +194,8 @@ struct mwl8k_priv { | |||
190 | int pending_tx_pkts; | 194 | int pending_tx_pkts; |
191 | 195 | ||
192 | struct mwl8k_rx_queue rxq[MWL8K_RX_QUEUES]; | 196 | struct mwl8k_rx_queue rxq[MWL8K_RX_QUEUES]; |
193 | struct mwl8k_tx_queue txq[MWL8K_TX_QUEUES]; | 197 | struct mwl8k_tx_queue txq[MWL8K_TX_QUEUES + MWL8K_MAX_AMPDU_QUEUES]; |
194 | u32 txq_offset[MWL8K_TX_QUEUES]; | 198 | u32 txq_offset[MWL8K_TX_QUEUES + MWL8K_MAX_AMPDU_QUEUES]; |
195 | 199 | ||
196 | bool radio_on; | 200 | bool radio_on; |
197 | bool radio_short_preamble; | 201 | bool radio_short_preamble; |
@@ -1322,7 +1326,7 @@ struct mwl8k_tx_desc { | |||
1322 | __le16 pkt_len; | 1326 | __le16 pkt_len; |
1323 | __u8 dest_MAC_addr[ETH_ALEN]; | 1327 | __u8 dest_MAC_addr[ETH_ALEN]; |
1324 | __le32 next_txd_phys_addr; | 1328 | __le32 next_txd_phys_addr; |
1325 | __le32 reserved; | 1329 | __le32 timestamp; |
1326 | __le16 rate_info; | 1330 | __le16 rate_info; |
1327 | __u8 peer_id; | 1331 | __u8 peer_id; |
1328 | __u8 tx_frag_cnt; | 1332 | __u8 tx_frag_cnt; |
@@ -2023,13 +2027,16 @@ struct mwl8k_cmd_get_hw_spec_ap { | |||
2023 | __le32 wcbbase2; | 2027 | __le32 wcbbase2; |
2024 | __le32 wcbbase3; | 2028 | __le32 wcbbase3; |
2025 | __le32 fw_api_version; | 2029 | __le32 fw_api_version; |
2030 | __le32 caps; | ||
2031 | __le32 num_of_ampdu_queues; | ||
2032 | __le32 wcbbase_ampdu[MWL8K_MAX_AMPDU_QUEUES]; | ||
2026 | } __packed; | 2033 | } __packed; |
2027 | 2034 | ||
2028 | static int mwl8k_cmd_get_hw_spec_ap(struct ieee80211_hw *hw) | 2035 | static int mwl8k_cmd_get_hw_spec_ap(struct ieee80211_hw *hw) |
2029 | { | 2036 | { |
2030 | struct mwl8k_priv *priv = hw->priv; | 2037 | struct mwl8k_priv *priv = hw->priv; |
2031 | struct mwl8k_cmd_get_hw_spec_ap *cmd; | 2038 | struct mwl8k_cmd_get_hw_spec_ap *cmd; |
2032 | int rc; | 2039 | int rc, i; |
2033 | u32 api_version; | 2040 | u32 api_version; |
2034 | 2041 | ||
2035 | cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); | 2042 | cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); |
@@ -2061,10 +2068,17 @@ static int mwl8k_cmd_get_hw_spec_ap(struct ieee80211_hw *hw) | |||
2061 | priv->num_mcaddrs = le16_to_cpu(cmd->num_mcaddrs); | 2068 | priv->num_mcaddrs = le16_to_cpu(cmd->num_mcaddrs); |
2062 | priv->fw_rev = le32_to_cpu(cmd->fw_rev); | 2069 | priv->fw_rev = le32_to_cpu(cmd->fw_rev); |
2063 | priv->hw_rev = cmd->hw_rev; | 2070 | priv->hw_rev = cmd->hw_rev; |
2064 | mwl8k_setup_2ghz_band(hw); | 2071 | mwl8k_set_caps(hw, le32_to_cpu(cmd->caps)); |
2065 | priv->ap_macids_supported = 0x000000ff; | 2072 | priv->ap_macids_supported = 0x000000ff; |
2066 | priv->sta_macids_supported = 0x00000000; | 2073 | priv->sta_macids_supported = 0x00000000; |
2067 | 2074 | priv->num_ampdu_queues = le32_to_cpu(cmd->num_of_ampdu_queues); | |
2075 | if (priv->num_ampdu_queues > MWL8K_MAX_AMPDU_QUEUES) { | ||
2076 | wiphy_warn(hw->wiphy, "fw reported %d ampdu queues" | ||
2077 | " but we only support %d.\n", | ||
2078 | priv->num_ampdu_queues, | ||
2079 | MWL8K_MAX_AMPDU_QUEUES); | ||
2080 | priv->num_ampdu_queues = MWL8K_MAX_AMPDU_QUEUES; | ||
2081 | } | ||
2068 | off = le32_to_cpu(cmd->rxwrptr) & 0xffff; | 2082 | off = le32_to_cpu(cmd->rxwrptr) & 0xffff; |
2069 | iowrite32(priv->rxq[0].rxd_dma, priv->sram + off); | 2083 | iowrite32(priv->rxq[0].rxd_dma, priv->sram + off); |
2070 | 2084 | ||
@@ -2075,6 +2089,10 @@ static int mwl8k_cmd_get_hw_spec_ap(struct ieee80211_hw *hw) | |||
2075 | priv->txq_offset[1] = le32_to_cpu(cmd->wcbbase1) & 0xffff; | 2089 | priv->txq_offset[1] = le32_to_cpu(cmd->wcbbase1) & 0xffff; |
2076 | priv->txq_offset[2] = le32_to_cpu(cmd->wcbbase2) & 0xffff; | 2090 | priv->txq_offset[2] = le32_to_cpu(cmd->wcbbase2) & 0xffff; |
2077 | priv->txq_offset[3] = le32_to_cpu(cmd->wcbbase3) & 0xffff; | 2091 | priv->txq_offset[3] = le32_to_cpu(cmd->wcbbase3) & 0xffff; |
2092 | |||
2093 | for (i = 0; i < priv->num_ampdu_queues; i++) | ||
2094 | priv->txq_offset[i + MWL8K_TX_QUEUES] = | ||
2095 | le32_to_cpu(cmd->wcbbase_ampdu[i]) & 0xffff; | ||
2078 | } | 2096 | } |
2079 | 2097 | ||
2080 | done: | 2098 | done: |
@@ -2103,6 +2121,14 @@ struct mwl8k_cmd_set_hw_spec { | |||
2103 | __le32 total_rxd; | 2121 | __le32 total_rxd; |
2104 | } __packed; | 2122 | } __packed; |
2105 | 2123 | ||
2124 | /* If enabled, MWL8K_SET_HW_SPEC_FLAG_ENABLE_LIFE_TIME_EXPIRY will cause | ||
2125 | * packets to expire 500 ms after the timestamp in the tx descriptor. That is, | ||
2126 | * the packets that are queued for more than 500ms, will be dropped in the | ||
2127 | * hardware. This helps minimizing the issues caused due to head-of-line | ||
2128 | * blocking where a slow client can hog the bandwidth and affect traffic to a | ||
2129 | * faster client. | ||
2130 | */ | ||
2131 | #define MWL8K_SET_HW_SPEC_FLAG_ENABLE_LIFE_TIME_EXPIRY 0x00000400 | ||
2106 | #define MWL8K_SET_HW_SPEC_FLAG_HOST_DECR_MGMT 0x00000080 | 2132 | #define MWL8K_SET_HW_SPEC_FLAG_HOST_DECR_MGMT 0x00000080 |
2107 | #define MWL8K_SET_HW_SPEC_FLAG_HOSTFORM_PROBERESP 0x00000020 | 2133 | #define MWL8K_SET_HW_SPEC_FLAG_HOSTFORM_PROBERESP 0x00000020 |
2108 | #define MWL8K_SET_HW_SPEC_FLAG_HOSTFORM_BEACON 0x00000010 | 2134 | #define MWL8K_SET_HW_SPEC_FLAG_HOSTFORM_BEACON 0x00000010 |
@@ -4434,7 +4460,7 @@ enum { | |||
4434 | MWL8366, | 4460 | MWL8366, |
4435 | }; | 4461 | }; |
4436 | 4462 | ||
4437 | #define MWL8K_8366_AP_FW_API 1 | 4463 | #define MWL8K_8366_AP_FW_API 2 |
4438 | #define _MWL8K_8366_AP_FW(api) "mwl8k/fmimage_8366_ap-" #api ".fw" | 4464 | #define _MWL8K_8366_AP_FW(api) "mwl8k/fmimage_8366_ap-" #api ".fw" |
4439 | #define MWL8K_8366_AP_FW(api) _MWL8K_8366_AP_FW(api) | 4465 | #define MWL8K_8366_AP_FW(api) _MWL8K_8366_AP_FW(api) |
4440 | 4466 | ||
@@ -4650,6 +4676,7 @@ static int mwl8k_probe_hw(struct ieee80211_hw *hw) | |||
4650 | * total number of queues from the result CMD_GET_HW_SPEC, so for this | 4676 | * total number of queues from the result CMD_GET_HW_SPEC, so for this |
4651 | * case we must initialize the tx queues after. | 4677 | * case we must initialize the tx queues after. |
4652 | */ | 4678 | */ |
4679 | priv->num_ampdu_queues = 0; | ||
4653 | if (!priv->ap_fw) { | 4680 | if (!priv->ap_fw) { |
4654 | rc = mwl8k_init_txqs(hw); | 4681 | rc = mwl8k_init_txqs(hw); |
4655 | if (rc) | 4682 | if (rc) |