aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/mwl8k.c
diff options
context:
space:
mode:
authorBrian Cavagnolo <brian@cozybit.com>2011-03-17 14:58:42 -0400
committerJohn W. Linville <linville@tuxdriver.com>2011-03-30 14:15:13 -0400
commit8a7a578c2e3ac463a17fe30b11ada0509658a952 (patch)
tree119aaafe120f9ee4d97538d923126910b94c66d9 /drivers/net/wireless/mwl8k.c
parent73b46320209e9fe0d65aba1b8c21489278047574 (diff)
mwl8k: update to ap firmware API version 2
Firmware APIv2 adds the following enhancements: -- capabilities are reported by the firmware -- API supports up to 8 dedicated AMPDU streams -- optional packet timestamping and expiration can be enabled. Specifically, packets that are queued in firmware for longer than 500ms will be dropped if this option is used. Based on work by "Nishant Sarmukadam" <nishants@marvell.com> Signed-off-by: Brian Cavagnolo <brian@cozybit.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net/wireless/mwl8k.c')
-rw-r--r--drivers/net/wireless/mwl8k.c41
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
90struct rxd_ops { 91struct 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
2028static int mwl8k_cmd_get_hw_spec_ap(struct ieee80211_hw *hw) 2035static 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
2080done: 2098done:
@@ -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)