Commit 8a7a578c authored by Brian Cavagnolo's avatar Brian Cavagnolo Committed by John W. Linville

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: default avatarBrian Cavagnolo <brian@cozybit.com>
Signed-off-by: default avatarJohn W. Linville <linville@tuxdriver.com>
parent 73b46320
...@@ -86,6 +86,7 @@ MODULE_PARM_DESC(ap_mode_default, ...@@ -86,6 +86,7 @@ MODULE_PARM_DESC(ap_mode_default,
#define MWL8K_RX_QUEUES 1 #define MWL8K_RX_QUEUES 1
#define MWL8K_TX_QUEUES 4 #define MWL8K_TX_QUEUES 4
#define MWL8K_MAX_AMPDU_QUEUES 8
struct rxd_ops { struct rxd_ops {
int rxd_size; int rxd_size;
...@@ -159,6 +160,9 @@ struct mwl8k_priv { ...@@ -159,6 +160,9 @@ struct mwl8k_priv {
u32 ap_macids_supported; u32 ap_macids_supported;
u32 sta_macids_supported; u32 sta_macids_supported;
/* Ampdu stream information */
u8 num_ampdu_queues;
/* firmware access */ /* firmware access */
struct mutex fw_mutex; struct mutex fw_mutex;
struct task_struct *fw_mutex_owner; struct task_struct *fw_mutex_owner;
...@@ -190,8 +194,8 @@ struct mwl8k_priv { ...@@ -190,8 +194,8 @@ struct mwl8k_priv {
int pending_tx_pkts; int pending_tx_pkts;
struct mwl8k_rx_queue rxq[MWL8K_RX_QUEUES]; struct mwl8k_rx_queue rxq[MWL8K_RX_QUEUES];
struct mwl8k_tx_queue txq[MWL8K_TX_QUEUES]; struct mwl8k_tx_queue txq[MWL8K_TX_QUEUES + MWL8K_MAX_AMPDU_QUEUES];
u32 txq_offset[MWL8K_TX_QUEUES]; u32 txq_offset[MWL8K_TX_QUEUES + MWL8K_MAX_AMPDU_QUEUES];
bool radio_on; bool radio_on;
bool radio_short_preamble; bool radio_short_preamble;
...@@ -1322,7 +1326,7 @@ struct mwl8k_tx_desc { ...@@ -1322,7 +1326,7 @@ struct mwl8k_tx_desc {
__le16 pkt_len; __le16 pkt_len;
__u8 dest_MAC_addr[ETH_ALEN]; __u8 dest_MAC_addr[ETH_ALEN];
__le32 next_txd_phys_addr; __le32 next_txd_phys_addr;
__le32 reserved; __le32 timestamp;
__le16 rate_info; __le16 rate_info;
__u8 peer_id; __u8 peer_id;
__u8 tx_frag_cnt; __u8 tx_frag_cnt;
...@@ -2023,13 +2027,16 @@ struct mwl8k_cmd_get_hw_spec_ap { ...@@ -2023,13 +2027,16 @@ struct mwl8k_cmd_get_hw_spec_ap {
__le32 wcbbase2; __le32 wcbbase2;
__le32 wcbbase3; __le32 wcbbase3;
__le32 fw_api_version; __le32 fw_api_version;
__le32 caps;
__le32 num_of_ampdu_queues;
__le32 wcbbase_ampdu[MWL8K_MAX_AMPDU_QUEUES];
} __packed; } __packed;
static int mwl8k_cmd_get_hw_spec_ap(struct ieee80211_hw *hw) static int mwl8k_cmd_get_hw_spec_ap(struct ieee80211_hw *hw)
{ {
struct mwl8k_priv *priv = hw->priv; struct mwl8k_priv *priv = hw->priv;
struct mwl8k_cmd_get_hw_spec_ap *cmd; struct mwl8k_cmd_get_hw_spec_ap *cmd;
int rc; int rc, i;
u32 api_version; u32 api_version;
cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
...@@ -2061,10 +2068,17 @@ static int mwl8k_cmd_get_hw_spec_ap(struct ieee80211_hw *hw) ...@@ -2061,10 +2068,17 @@ static int mwl8k_cmd_get_hw_spec_ap(struct ieee80211_hw *hw)
priv->num_mcaddrs = le16_to_cpu(cmd->num_mcaddrs); priv->num_mcaddrs = le16_to_cpu(cmd->num_mcaddrs);
priv->fw_rev = le32_to_cpu(cmd->fw_rev); priv->fw_rev = le32_to_cpu(cmd->fw_rev);
priv->hw_rev = cmd->hw_rev; priv->hw_rev = cmd->hw_rev;
mwl8k_setup_2ghz_band(hw); mwl8k_set_caps(hw, le32_to_cpu(cmd->caps));
priv->ap_macids_supported = 0x000000ff; priv->ap_macids_supported = 0x000000ff;
priv->sta_macids_supported = 0x00000000; priv->sta_macids_supported = 0x00000000;
priv->num_ampdu_queues = le32_to_cpu(cmd->num_of_ampdu_queues);
if (priv->num_ampdu_queues > MWL8K_MAX_AMPDU_QUEUES) {
wiphy_warn(hw->wiphy, "fw reported %d ampdu queues"
" but we only support %d.\n",
priv->num_ampdu_queues,
MWL8K_MAX_AMPDU_QUEUES);
priv->num_ampdu_queues = MWL8K_MAX_AMPDU_QUEUES;
}
off = le32_to_cpu(cmd->rxwrptr) & 0xffff; off = le32_to_cpu(cmd->rxwrptr) & 0xffff;
iowrite32(priv->rxq[0].rxd_dma, priv->sram + off); iowrite32(priv->rxq[0].rxd_dma, priv->sram + off);
...@@ -2075,6 +2089,10 @@ static int mwl8k_cmd_get_hw_spec_ap(struct ieee80211_hw *hw) ...@@ -2075,6 +2089,10 @@ static int mwl8k_cmd_get_hw_spec_ap(struct ieee80211_hw *hw)
priv->txq_offset[1] = le32_to_cpu(cmd->wcbbase1) & 0xffff; priv->txq_offset[1] = le32_to_cpu(cmd->wcbbase1) & 0xffff;
priv->txq_offset[2] = le32_to_cpu(cmd->wcbbase2) & 0xffff; priv->txq_offset[2] = le32_to_cpu(cmd->wcbbase2) & 0xffff;
priv->txq_offset[3] = le32_to_cpu(cmd->wcbbase3) & 0xffff; priv->txq_offset[3] = le32_to_cpu(cmd->wcbbase3) & 0xffff;
for (i = 0; i < priv->num_ampdu_queues; i++)
priv->txq_offset[i + MWL8K_TX_QUEUES] =
le32_to_cpu(cmd->wcbbase_ampdu[i]) & 0xffff;
} }
done: done:
...@@ -2103,6 +2121,14 @@ struct mwl8k_cmd_set_hw_spec { ...@@ -2103,6 +2121,14 @@ struct mwl8k_cmd_set_hw_spec {
__le32 total_rxd; __le32 total_rxd;
} __packed; } __packed;
/* If enabled, MWL8K_SET_HW_SPEC_FLAG_ENABLE_LIFE_TIME_EXPIRY will cause
* packets to expire 500 ms after the timestamp in the tx descriptor. That is,
* the packets that are queued for more than 500ms, will be dropped in the
* hardware. This helps minimizing the issues caused due to head-of-line
* blocking where a slow client can hog the bandwidth and affect traffic to a
* faster client.
*/
#define MWL8K_SET_HW_SPEC_FLAG_ENABLE_LIFE_TIME_EXPIRY 0x00000400
#define MWL8K_SET_HW_SPEC_FLAG_HOST_DECR_MGMT 0x00000080 #define MWL8K_SET_HW_SPEC_FLAG_HOST_DECR_MGMT 0x00000080
#define MWL8K_SET_HW_SPEC_FLAG_HOSTFORM_PROBERESP 0x00000020 #define MWL8K_SET_HW_SPEC_FLAG_HOSTFORM_PROBERESP 0x00000020
#define MWL8K_SET_HW_SPEC_FLAG_HOSTFORM_BEACON 0x00000010 #define MWL8K_SET_HW_SPEC_FLAG_HOSTFORM_BEACON 0x00000010
...@@ -4434,7 +4460,7 @@ enum { ...@@ -4434,7 +4460,7 @@ enum {
MWL8366, MWL8366,
}; };
#define MWL8K_8366_AP_FW_API 1 #define MWL8K_8366_AP_FW_API 2
#define _MWL8K_8366_AP_FW(api) "mwl8k/fmimage_8366_ap-" #api ".fw" #define _MWL8K_8366_AP_FW(api) "mwl8k/fmimage_8366_ap-" #api ".fw"
#define MWL8K_8366_AP_FW(api) _MWL8K_8366_AP_FW(api) #define MWL8K_8366_AP_FW(api) _MWL8K_8366_AP_FW(api)
...@@ -4650,6 +4676,7 @@ static int mwl8k_probe_hw(struct ieee80211_hw *hw) ...@@ -4650,6 +4676,7 @@ static int mwl8k_probe_hw(struct ieee80211_hw *hw)
* total number of queues from the result CMD_GET_HW_SPEC, so for this * total number of queues from the result CMD_GET_HW_SPEC, so for this
* case we must initialize the tx queues after. * case we must initialize the tx queues after.
*/ */
priv->num_ampdu_queues = 0;
if (!priv->ap_fw) { if (!priv->ap_fw) {
rc = mwl8k_init_txqs(hw); rc = mwl8k_init_txqs(hw);
if (rc) if (rc)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment