|
@@ -86,6 +86,7 @@ MODULE_PARM_DESC(ap_mode_default,
|
|
|
|
|
|
#define MWL8K_RX_QUEUES 1
|
|
|
#define MWL8K_TX_QUEUES 4
|
|
|
+#define MWL8K_MAX_AMPDU_QUEUES 8
|
|
|
|
|
|
struct rxd_ops {
|
|
|
int rxd_size;
|
|
@@ -159,6 +160,9 @@ struct mwl8k_priv {
|
|
|
u32 ap_macids_supported;
|
|
|
u32 sta_macids_supported;
|
|
|
|
|
|
+ /* Ampdu stream information */
|
|
|
+ u8 num_ampdu_queues;
|
|
|
+
|
|
|
/* firmware access */
|
|
|
struct mutex fw_mutex;
|
|
|
struct task_struct *fw_mutex_owner;
|
|
@@ -190,8 +194,8 @@ struct mwl8k_priv {
|
|
|
int pending_tx_pkts;
|
|
|
|
|
|
struct mwl8k_rx_queue rxq[MWL8K_RX_QUEUES];
|
|
|
- struct mwl8k_tx_queue txq[MWL8K_TX_QUEUES];
|
|
|
- u32 txq_offset[MWL8K_TX_QUEUES];
|
|
|
+ struct mwl8k_tx_queue txq[MWL8K_TX_QUEUES + MWL8K_MAX_AMPDU_QUEUES];
|
|
|
+ u32 txq_offset[MWL8K_TX_QUEUES + MWL8K_MAX_AMPDU_QUEUES];
|
|
|
|
|
|
bool radio_on;
|
|
|
bool radio_short_preamble;
|
|
@@ -1322,7 +1326,7 @@ struct mwl8k_tx_desc {
|
|
|
__le16 pkt_len;
|
|
|
__u8 dest_MAC_addr[ETH_ALEN];
|
|
|
__le32 next_txd_phys_addr;
|
|
|
- __le32 reserved;
|
|
|
+ __le32 timestamp;
|
|
|
__le16 rate_info;
|
|
|
__u8 peer_id;
|
|
|
__u8 tx_frag_cnt;
|
|
@@ -2023,13 +2027,16 @@ struct mwl8k_cmd_get_hw_spec_ap {
|
|
|
__le32 wcbbase2;
|
|
|
__le32 wcbbase3;
|
|
|
__le32 fw_api_version;
|
|
|
+ __le32 caps;
|
|
|
+ __le32 num_of_ampdu_queues;
|
|
|
+ __le32 wcbbase_ampdu[MWL8K_MAX_AMPDU_QUEUES];
|
|
|
} __packed;
|
|
|
|
|
|
static int mwl8k_cmd_get_hw_spec_ap(struct ieee80211_hw *hw)
|
|
|
{
|
|
|
struct mwl8k_priv *priv = hw->priv;
|
|
|
struct mwl8k_cmd_get_hw_spec_ap *cmd;
|
|
|
- int rc;
|
|
|
+ int rc, i;
|
|
|
u32 api_version;
|
|
|
|
|
|
cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
|
|
@@ -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->fw_rev = le32_to_cpu(cmd->fw_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->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;
|
|
|
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)
|
|
|
priv->txq_offset[1] = le32_to_cpu(cmd->wcbbase1) & 0xffff;
|
|
|
priv->txq_offset[2] = le32_to_cpu(cmd->wcbbase2) & 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:
|
|
@@ -2103,6 +2121,14 @@ struct mwl8k_cmd_set_hw_spec {
|
|
|
__le32 total_rxd;
|
|
|
} __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_HOSTFORM_PROBERESP 0x00000020
|
|
|
#define MWL8K_SET_HW_SPEC_FLAG_HOSTFORM_BEACON 0x00000010
|
|
@@ -4434,7 +4460,7 @@ enum {
|
|
|
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_8366_AP_FW(api)
|
|
|
|
|
@@ -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
|
|
|
* case we must initialize the tx queues after.
|
|
|
*/
|
|
|
+ priv->num_ampdu_queues = 0;
|
|
|
if (!priv->ap_fw) {
|
|
|
rc = mwl8k_init_txqs(hw);
|
|
|
if (rc)
|