Commit 5c895691 authored by Christian Lamparter's avatar Christian Lamparter Committed by John W. Linville

carl9170: support firmware-based rx filter

The hardware rx-filter was essentially disabled, because
of a serve, yet unidentifiable problem with iwlagn.
Due to these circumstances the driver and mac80211 were
left with the job of filtering.

This is very unfortunate and has proven to be expensive
in terms of latency, memory and load.

Therefore the new 1.8.8.3 firmware introduces a flexible
filtering infrastructure which allows the driver to
offload some of the checks (FCS & PLCP crc check,
RA match, control frame filter, etc...) whenever possible.

Note:
This patch also includes all changes to the
shared headers files since the inclusion.
Signed-off-by: default avatarChristian Lamparter <chunkeey@googlemail.com>
Signed-off-by: default avatarJohn W. Linville <linville@tuxdriver.com>
parent 85416a4f
...@@ -279,6 +279,7 @@ struct ar9170 { ...@@ -279,6 +279,7 @@ struct ar9170 {
unsigned int beacon_max_len; unsigned int beacon_max_len;
bool rx_stream; bool rx_stream;
bool tx_stream; bool tx_stream;
bool rx_filter;
unsigned int mem_blocks; unsigned int mem_blocks;
unsigned int mem_block_size; unsigned int mem_block_size;
unsigned int rx_size; unsigned int rx_size;
...@@ -314,6 +315,7 @@ struct ar9170 { ...@@ -314,6 +315,7 @@ struct ar9170 {
u64 cur_mc_hash; u64 cur_mc_hash;
u32 cur_filter; u32 cur_filter;
unsigned int filter_state; unsigned int filter_state;
unsigned int rx_filter_caps;
bool sniffer_enabled; bool sniffer_enabled;
/* MAC */ /* MAC */
......
...@@ -59,6 +59,16 @@ static inline int carl9170_flush_cab(struct ar9170 *ar, ...@@ -59,6 +59,16 @@ static inline int carl9170_flush_cab(struct ar9170 *ar,
return carl9170_bcn_ctrl(ar, vif_id, CARL9170_BCN_CTRL_DRAIN, 0, 0); return carl9170_bcn_ctrl(ar, vif_id, CARL9170_BCN_CTRL_DRAIN, 0, 0);
} }
static inline int carl9170_rx_filter(struct ar9170 *ar,
const unsigned int _rx_filter)
{
__le32 rx_filter = cpu_to_le32(_rx_filter);
return carl9170_exec_cmd(ar, CARL9170_CMD_RX_FILTER,
sizeof(rx_filter), (u8 *)&rx_filter,
0, NULL);
}
struct carl9170_cmd *carl9170_cmd_buf(struct ar9170 *ar, struct carl9170_cmd *carl9170_cmd_buf(struct ar9170 *ar,
const enum carl9170_cmd_oids cmd, const unsigned int len); const enum carl9170_cmd_oids cmd, const unsigned int len);
......
...@@ -257,6 +257,13 @@ static int carl9170_fw(struct ar9170 *ar, const __u8 *data, size_t len) ...@@ -257,6 +257,13 @@ static int carl9170_fw(struct ar9170 *ar, const __u8 *data, size_t len)
if (SUPP(CARL9170FW_USB_UP_STREAM)) if (SUPP(CARL9170FW_USB_UP_STREAM))
ar->fw.rx_stream = true; ar->fw.rx_stream = true;
if (SUPP(CARL9170FW_RX_FILTER)) {
ar->fw.rx_filter = true;
ar->rx_filter_caps = FIF_FCSFAIL | FIF_PLCPFAIL |
FIF_CONTROL | FIF_PSPOLL | FIF_OTHER_BSS |
FIF_PROMISC_IN_BSS;
}
ar->fw.vif_num = otus_desc->vif_num; ar->fw.vif_num = otus_desc->vif_num;
ar->fw.cmd_bufs = otus_desc->cmd_bufs; ar->fw.cmd_bufs = otus_desc->cmd_bufs;
ar->fw.address = le32_to_cpu(otus_desc->fw_address); ar->fw.address = le32_to_cpu(otus_desc->fw_address);
......
...@@ -53,6 +53,7 @@ enum carl9170_cmd_oids { ...@@ -53,6 +53,7 @@ enum carl9170_cmd_oids {
CARL9170_CMD_REBOOT = 0x04, CARL9170_CMD_REBOOT = 0x04,
CARL9170_CMD_BCN_CTRL = 0x05, CARL9170_CMD_BCN_CTRL = 0x05,
CARL9170_CMD_READ_TSF = 0x06, CARL9170_CMD_READ_TSF = 0x06,
CARL9170_CMD_RX_FILTER = 0x07,
/* CAM */ /* CAM */
CARL9170_CMD_EKEY = 0x10, CARL9170_CMD_EKEY = 0x10,
...@@ -153,6 +154,20 @@ struct carl9170_psm { ...@@ -153,6 +154,20 @@ struct carl9170_psm {
} __packed; } __packed;
#define CARL9170_PSM_SIZE 4 #define CARL9170_PSM_SIZE 4
struct carl9170_rx_filter_cmd {
__le32 rx_filter;
} __packed;
#define CARL9170_RX_FILTER_CMD_SIZE 4
#define CARL9170_RX_FILTER_BAD 0x01
#define CARL9170_RX_FILTER_OTHER_RA 0x02
#define CARL9170_RX_FILTER_DECRY_FAIL 0x04
#define CARL9170_RX_FILTER_CTL_OTHER 0x08
#define CARL9170_RX_FILTER_CTL_PSPOLL 0x10
#define CARL9170_RX_FILTER_CTL_BACKR 0x20
#define CARL9170_RX_FILTER_MGMT 0x40
#define CARL9170_RX_FILTER_DATA 0x80
struct carl9170_bcn_ctrl_cmd { struct carl9170_bcn_ctrl_cmd {
__le32 vif_id; __le32 vif_id;
__le32 mode; __le32 mode;
...@@ -188,6 +203,7 @@ struct carl9170_cmd { ...@@ -188,6 +203,7 @@ struct carl9170_cmd {
struct carl9170_rf_init rf_init; struct carl9170_rf_init rf_init;
struct carl9170_psm psm; struct carl9170_psm psm;
struct carl9170_bcn_ctrl_cmd bcn_ctrl; struct carl9170_bcn_ctrl_cmd bcn_ctrl;
struct carl9170_rx_filter_cmd rx_filter;
u8 data[CARL9170_MAX_CMD_PAYLOAD_LEN]; u8 data[CARL9170_MAX_CMD_PAYLOAD_LEN];
} __packed; } __packed;
} __packed; } __packed;
......
...@@ -66,6 +66,9 @@ enum carl9170fw_feature_list { ...@@ -66,6 +66,9 @@ enum carl9170fw_feature_list {
/* Firmware PSM support | CARL9170_CMD_PSM */ /* Firmware PSM support | CARL9170_CMD_PSM */
CARL9170FW_PSM, CARL9170FW_PSM,
/* Firmware RX filter | CARL9170_CMD_RX_FILTER */
CARL9170FW_RX_FILTER,
/* KEEP LAST */ /* KEEP LAST */
__CARL9170FW_FEATURE_NUM __CARL9170FW_FEATURE_NUM
}; };
...@@ -142,7 +145,7 @@ struct carl9170fw_fix_desc { ...@@ -142,7 +145,7 @@ struct carl9170fw_fix_desc {
(sizeof(struct carl9170fw_fix_desc)) (sizeof(struct carl9170fw_fix_desc))
#define CARL9170FW_DBG_DESC_MIN_VER 1 #define CARL9170FW_DBG_DESC_MIN_VER 1
#define CARL9170FW_DBG_DESC_CUR_VER 2 #define CARL9170FW_DBG_DESC_CUR_VER 3
struct carl9170fw_dbg_desc { struct carl9170fw_dbg_desc {
struct carl9170fw_desc_head head; struct carl9170fw_desc_head head;
...@@ -150,6 +153,7 @@ struct carl9170fw_dbg_desc { ...@@ -150,6 +153,7 @@ struct carl9170fw_dbg_desc {
__le32 counter_addr; __le32 counter_addr;
__le32 rx_total_addr; __le32 rx_total_addr;
__le32 rx_overrun_addr; __le32 rx_overrun_addr;
__le32 rx_filter;
/* Put your debugging definitions here */ /* Put your debugging definitions here */
} __packed; } __packed;
......
...@@ -731,6 +731,9 @@ struct ar9170_stream { ...@@ -731,6 +731,9 @@ struct ar9170_stream {
#define SET_VAL(reg, value, newvalue) \ #define SET_VAL(reg, value, newvalue) \
(value = ((value) & ~reg) | (((newvalue) << reg##_S) & reg)) (value = ((value) & ~reg) | (((newvalue) << reg##_S) & reg))
#define SET_CONSTVAL(reg, newvalue) \
(((newvalue) << reg##_S) & reg)
#define MOD_VAL(reg, value, newvalue) \ #define MOD_VAL(reg, value, newvalue) \
(((value) & ~reg) | (((newvalue) << reg##_S) & reg)) (((value) & ~reg) | (((newvalue) << reg##_S) & reg))
#endif /* __CARL9170_SHARED_HW_H */ #endif /* __CARL9170_SHARED_HW_H */
...@@ -380,6 +380,13 @@ static int carl9170_op_start(struct ieee80211_hw *hw) ...@@ -380,6 +380,13 @@ static int carl9170_op_start(struct ieee80211_hw *hw)
if (err) if (err)
goto out; goto out;
if (ar->fw.rx_filter) {
err = carl9170_rx_filter(ar, CARL9170_RX_FILTER_OTHER_RA |
CARL9170_RX_FILTER_CTL_OTHER | CARL9170_RX_FILTER_BAD);
if (err)
goto out;
}
err = carl9170_write_reg(ar, AR9170_MAC_REG_DMA_TRIGGER, err = carl9170_write_reg(ar, AR9170_MAC_REG_DMA_TRIGGER,
AR9170_DMA_TRIGGER_RXQ); AR9170_DMA_TRIGGER_RXQ);
if (err) if (err)
...@@ -840,8 +847,7 @@ static void carl9170_op_configure_filter(struct ieee80211_hw *hw, ...@@ -840,8 +847,7 @@ static void carl9170_op_configure_filter(struct ieee80211_hw *hw,
struct ar9170 *ar = hw->priv; struct ar9170 *ar = hw->priv;
/* mask supported flags */ /* mask supported flags */
*new_flags &= FIF_ALLMULTI | FIF_FCSFAIL | FIF_PLCPFAIL | *new_flags &= FIF_ALLMULTI | ar->rx_filter_caps;
FIF_OTHER_BSS | FIF_PROMISC_IN_BSS;
if (!IS_ACCEPTING_CMD(ar)) if (!IS_ACCEPTING_CMD(ar))
return; return;
...@@ -867,6 +873,26 @@ static void carl9170_op_configure_filter(struct ieee80211_hw *hw, ...@@ -867,6 +873,26 @@ static void carl9170_op_configure_filter(struct ieee80211_hw *hw,
WARN_ON(carl9170_set_operating_mode(ar)); WARN_ON(carl9170_set_operating_mode(ar));
} }
if (ar->fw.rx_filter && changed_flags & ar->rx_filter_caps) {
u32 rx_filter = 0;
if (!(*new_flags & (FIF_FCSFAIL | FIF_PLCPFAIL)))
rx_filter |= CARL9170_RX_FILTER_BAD;
if (!(*new_flags & FIF_CONTROL))
rx_filter |= CARL9170_RX_FILTER_CTL_OTHER;
if (!(*new_flags & FIF_PSPOLL))
rx_filter |= CARL9170_RX_FILTER_CTL_PSPOLL;
if (!(*new_flags & (FIF_OTHER_BSS | FIF_PROMISC_IN_BSS))) {
rx_filter |= CARL9170_RX_FILTER_OTHER_RA;
rx_filter |= CARL9170_RX_FILTER_DECRY_FAIL;
}
WARN_ON(carl9170_rx_filter(ar, rx_filter));
}
mutex_unlock(&ar->mutex); mutex_unlock(&ar->mutex);
} }
......
...@@ -423,8 +423,8 @@ ...@@ -423,8 +423,8 @@
#define AR9170_PHY_CCK_DETECT_BB_ENABLE_ANT_FAST_DIV 0x2000 #define AR9170_PHY_CCK_DETECT_BB_ENABLE_ANT_FAST_DIV 0x2000
#define AR9170_PHY_CCK_DETECT_BB_ENABLE_ANT_FAST_DIV_S 13 #define AR9170_PHY_CCK_DETECT_BB_ENABLE_ANT_FAST_DIV_S 13
#define AR9170_PHY_REG_GAIN_2GHZ_CHAIN_2 (AR9170_PHY_REG_BASE + 0x2a0c)
#define AR9170_PHY_REG_GAIN_2GHZ (AR9170_PHY_REG_BASE + 0x0a0c) #define AR9170_PHY_REG_GAIN_2GHZ (AR9170_PHY_REG_BASE + 0x0a0c)
#define AR9170_PHY_REG_GAIN_2GHZ_CHAIN_2 (AR9170_PHY_REG_BASE + 0x2a0c)
#define AR9170_PHY_GAIN_2GHZ_RXTX_MARGIN 0x00fc0000 #define AR9170_PHY_GAIN_2GHZ_RXTX_MARGIN 0x00fc0000
#define AR9170_PHY_GAIN_2GHZ_RXTX_MARGIN_S 18 #define AR9170_PHY_GAIN_2GHZ_RXTX_MARGIN_S 18
#define AR9170_PHY_GAIN_2GHZ_BSW_MARGIN 0x00003c00 #define AR9170_PHY_GAIN_2GHZ_BSW_MARGIN 0x00003c00
...@@ -561,7 +561,4 @@ ...@@ -561,7 +561,4 @@
#define AR9170_PHY_CH2_EXT_MINCCA_PWR 0xff800000 #define AR9170_PHY_CH2_EXT_MINCCA_PWR 0xff800000
#define AR9170_PHY_CH2_EXT_MINCCA_PWR_S 23 #define AR9170_PHY_CH2_EXT_MINCCA_PWR_S 23
#define REDUCE_CHAIN_0 0x00000050
#define REDUCE_CHAIN_1 0x00000051
#endif /* __CARL9170_SHARED_PHY_H */ #endif /* __CARL9170_SHARED_PHY_H */
#ifndef __CARL9170_SHARED_VERSION_H #ifndef __CARL9170_SHARED_VERSION_H
#define __CARL9170_SHARED_VERSION_H #define __CARL9170_SHARED_VERSION_H
#define CARL9170FW_VERSION_YEAR 10 #define CARL9170FW_VERSION_YEAR 10
#define CARL9170FW_VERSION_MONTH 8 #define CARL9170FW_VERSION_MONTH 9
#define CARL9170FW_VERSION_DAY 30 #define CARL9170FW_VERSION_DAY 28
#define CARL9170FW_VERSION_GIT "1.8.8.1" #define CARL9170FW_VERSION_GIT "1.8.8.3"
#endif /* __CARL9170_SHARED_VERSION_H */ #endif /* __CARL9170_SHARED_VERSION_H */
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