]> bbs.cooldavid.org Git - net-next-2.6.git/commitdiff
carl9170: support firmware-based rx filter
authorChristian Lamparter <chunkeey@googlemail.com>
Tue, 28 Sep 2010 21:00:59 +0000 (23:00 +0200)
committerJohn W. Linville <linville@tuxdriver.com>
Tue, 5 Oct 2010 17:35:21 +0000 (13:35 -0400)
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: Christian Lamparter <chunkeey@googlemail.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
drivers/net/wireless/ath/carl9170/carl9170.h
drivers/net/wireless/ath/carl9170/cmd.h
drivers/net/wireless/ath/carl9170/fw.c
drivers/net/wireless/ath/carl9170/fwcmd.h
drivers/net/wireless/ath/carl9170/fwdesc.h
drivers/net/wireless/ath/carl9170/hw.h
drivers/net/wireless/ath/carl9170/main.c
drivers/net/wireless/ath/carl9170/phy.h
drivers/net/wireless/ath/carl9170/version.h

index 20f2a77e54d261419bcfb1bfe6ff43fde2bd4c37..6cf0c9ef47aa4e7ae005abc034edca2fb40d30e6 100644 (file)
@@ -279,6 +279,7 @@ struct ar9170 {
                unsigned int beacon_max_len;
                bool rx_stream;
                bool tx_stream;
+               bool rx_filter;
                unsigned int mem_blocks;
                unsigned int mem_block_size;
                unsigned int rx_size;
@@ -314,6 +315,7 @@ struct ar9170 {
        u64 cur_mc_hash;
        u32 cur_filter;
        unsigned int filter_state;
+       unsigned int rx_filter_caps;
        bool sniffer_enabled;
 
        /* MAC */
index 0fc83d2336fdcc602e546b6839391a6b4bbe7a2a..f78728c38294e07c6098853e8fb902f3c24d9bb7 100644 (file)
@@ -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);
 }
 
+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,
        const enum carl9170_cmd_oids cmd, const unsigned int len);
 
index 36615462b87a0c5cfc772ca1c82f85ff17e3b95e..ae6c006bbc56c03bd76f0e1cc56c46a927db1db9 100644 (file)
@@ -257,6 +257,13 @@ static int carl9170_fw(struct ar9170 *ar, const __u8 *data, size_t len)
        if (SUPP(CARL9170FW_USB_UP_STREAM))
                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.cmd_bufs = otus_desc->cmd_bufs;
        ar->fw.address = le32_to_cpu(otus_desc->fw_address);
index d4a4e1dbef0695d1d9c3acd72a9df29485d42f1b..d552166db5059149cd8e653fb2e1154dfba85173 100644 (file)
@@ -53,6 +53,7 @@ enum carl9170_cmd_oids {
        CARL9170_CMD_REBOOT             = 0x04,
        CARL9170_CMD_BCN_CTRL           = 0x05,
        CARL9170_CMD_READ_TSF           = 0x06,
+       CARL9170_CMD_RX_FILTER          = 0x07,
 
        /* CAM */
        CARL9170_CMD_EKEY               = 0x10,
@@ -153,6 +154,20 @@ struct carl9170_psm {
 } __packed;
 #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 {
        __le32          vif_id;
        __le32          mode;
@@ -188,6 +203,7 @@ struct carl9170_cmd {
                struct carl9170_rf_init         rf_init;
                struct carl9170_psm             psm;
                struct carl9170_bcn_ctrl_cmd    bcn_ctrl;
+               struct carl9170_rx_filter_cmd   rx_filter;
                u8 data[CARL9170_MAX_CMD_PAYLOAD_LEN];
        } __packed;
 } __packed;
index 7cd811708fe5b18d9911aa35d126f787edd52a37..71f3821f60581d721bd203cea46ed31245e26679 100644 (file)
@@ -66,6 +66,9 @@ enum carl9170fw_feature_list {
        /* Firmware PSM support | CARL9170_CMD_PSM */
        CARL9170FW_PSM,
 
+       /* Firmware RX filter | CARL9170_CMD_RX_FILTER */
+       CARL9170FW_RX_FILTER,
+
        /* KEEP LAST */
        __CARL9170FW_FEATURE_NUM
 };
@@ -142,7 +145,7 @@ struct carl9170fw_fix_desc {
        (sizeof(struct carl9170fw_fix_desc))
 
 #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_desc_head head;
 
@@ -150,6 +153,7 @@ struct carl9170fw_dbg_desc {
        __le32 counter_addr;
        __le32 rx_total_addr;
        __le32 rx_overrun_addr;
+       __le32 rx_filter;
 
        /* Put your debugging definitions here */
 } __packed;
index b1292ac5b7033f4704d96bc691226ce4ebfe4efb..2f471b3f05afdec737ab6e1d293ac40bb7c0db5c 100644 (file)
@@ -731,6 +731,9 @@ struct ar9170_stream {
 #define SET_VAL(reg, value, newvalue)                                  \
        (value = ((value) & ~reg) | (((newvalue) << reg##_S) & reg))
 
+#define SET_CONSTVAL(reg, newvalue)                                    \
+       (((newvalue) << reg##_S) & reg)
+
 #define MOD_VAL(reg, value, newvalue)                                  \
        (((value) & ~reg) | (((newvalue) << reg##_S) & reg))
 #endif /* __CARL9170_SHARED_HW_H */
index 84bd38e9961cb62d84a7d25f314c5b72713186eb..3cc99f3f7ab5728af8eeb40c759f954a319671b7 100644 (file)
@@ -380,6 +380,13 @@ static int carl9170_op_start(struct ieee80211_hw *hw)
        if (err)
                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,
                                 AR9170_DMA_TRIGGER_RXQ);
        if (err)
@@ -840,8 +847,7 @@ static void carl9170_op_configure_filter(struct ieee80211_hw *hw,
        struct ar9170 *ar = hw->priv;
 
        /* mask supported flags */
-       *new_flags &= FIF_ALLMULTI | FIF_FCSFAIL | FIF_PLCPFAIL |
-                     FIF_OTHER_BSS | FIF_PROMISC_IN_BSS;
+       *new_flags &= FIF_ALLMULTI | ar->rx_filter_caps;
 
        if (!IS_ACCEPTING_CMD(ar))
                return;
@@ -867,6 +873,26 @@ static void carl9170_op_configure_filter(struct ieee80211_hw *hw,
                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);
 }
 
index 53c18d34ffccb6ba1e4aab146feecea372e9f97e..02c34eb4ebdec5fe64eb0730e24e89393c8f800f 100644 (file)
 #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_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_CHAIN_2        (AR9170_PHY_REG_BASE + 0x2a0c)
 #define                AR9170_PHY_GAIN_2GHZ_RXTX_MARGIN        0x00fc0000
 #define                AR9170_PHY_GAIN_2GHZ_RXTX_MARGIN_S      18
 #define                AR9170_PHY_GAIN_2GHZ_BSW_MARGIN         0x00003c00
 #define                AR9170_PHY_CH2_EXT_MINCCA_PWR           0xff800000
 #define                AR9170_PHY_CH2_EXT_MINCCA_PWR_S         23
 
-#define        REDUCE_CHAIN_0 0x00000050
-#define        REDUCE_CHAIN_1 0x00000051
-
 #endif /* __CARL9170_SHARED_PHY_H */
index 0e917f80eab4656951eb325239e6290f711c60bc..ff53f078a0b5eaff1080bd7e27840940ae1cc0d1 100644 (file)
@@ -1,7 +1,7 @@
 #ifndef __CARL9170_SHARED_VERSION_H
 #define __CARL9170_SHARED_VERSION_H
 #define CARL9170FW_VERSION_YEAR 10
-#define CARL9170FW_VERSION_MONTH 8
-#define CARL9170FW_VERSION_DAY 30
-#define CARL9170FW_VERSION_GIT "1.8.8.1"
+#define CARL9170FW_VERSION_MONTH 9
+#define CARL9170FW_VERSION_DAY 28
+#define CARL9170FW_VERSION_GIT "1.8.8.3"
 #endif /* __CARL9170_SHARED_VERSION_H */