wl->sta_rate_set = 0;
        wl->flags = 0;
        wl->vif = NULL;
+       wl->filters = 0;
 
        for (i = 0; i < NUM_TX_QUEUES; i++)
                wl->tx_blocks_freed[i] = 0;
        mutex_unlock(&wl->mutex);
 }
 
+static void wl1271_configure_filters(struct wl1271 *wl, unsigned int filters)
+{
+       wl->rx_config = WL1271_DEFAULT_RX_CONFIG;
+       wl->rx_filter = WL1271_DEFAULT_RX_FILTER;
+
+       /* combine requested filters with current filter config */
+       filters = wl->filters | filters;
+
+       wl1271_debug(DEBUG_FILTERS, "RX filters set: ");
+
+       if (filters & FIF_PROMISC_IN_BSS) {
+               wl1271_debug(DEBUG_FILTERS, " - FIF_PROMISC_IN_BSS");
+               wl->rx_config &= ~CFG_UNI_FILTER_EN;
+               wl->rx_config |= CFG_BSSID_FILTER_EN;
+       }
+       if (filters & FIF_BCN_PRBRESP_PROMISC) {
+               wl1271_debug(DEBUG_FILTERS, " - FIF_BCN_PRBRESP_PROMISC");
+               wl->rx_config &= ~CFG_BSSID_FILTER_EN;
+               wl->rx_config &= ~CFG_SSID_FILTER_EN;
+       }
+       if (filters & FIF_OTHER_BSS) {
+               wl1271_debug(DEBUG_FILTERS, " - FIF_OTHER_BSS");
+               wl->rx_config &= ~CFG_BSSID_FILTER_EN;
+       }
+       if (filters & FIF_CONTROL) {
+               wl1271_debug(DEBUG_FILTERS, " - FIF_CONTROL");
+               wl->rx_filter |= CFG_RX_CTL_EN;
+       }
+       if (filters & FIF_FCSFAIL) {
+               wl1271_debug(DEBUG_FILTERS, " - FIF_FCSFAIL");
+               wl->rx_filter |= CFG_RX_FCS_ERROR;
+       }
+}
+
 static int wl1271_join_channel(struct wl1271 *wl, int channel)
 {
        int ret = 0;
        static const u8 dummy_bssid[ETH_ALEN] = { 0x0b, 0xad, 0xde,
                                                  0xad, 0xbe, 0xef };
 
-       /* disable mac filter, so we hear everything */
-       wl->rx_config &= ~CFG_BSSID_FILTER_EN;
-
        wl->channel = channel;
        memcpy(wl->bssid, dummy_bssid, ETH_ALEN);
 
+       /* pass through frames from all BSS */
+       wl1271_configure_filters(wl, FIF_OTHER_BSS);
+
        /* the dummy join is performed always with STATION BSS type to allow
           also ad-hoc mode to listen to the surroundings without sending any
           beacons yet. */
        clear_bit(WL1271_FLAG_JOINED, &wl->flags);
        wl->channel = 0;
        memset(wl->bssid, 0, ETH_ALEN);
-       wl->rx_config = WL1271_DEFAULT_RX_CONFIG;
+
+       /* stop filterting packets based on bssid */
+       wl1271_configure_filters(wl, FIF_OTHER_BSS);
 
 out:
        return ret;
        if (ret < 0)
                goto out_sleep;
 
-       kfree(fp);
-
-       /* FIXME: We still need to set our filters properly */
-
        /* determine, whether supported filter values have changed */
        if (changed == 0)
                goto out_sleep;
 
+       /* configure filters */
+       wl->filters = *total;
+       wl1271_configure_filters(wl, 0);
+
        /* apply configured filters */
        ret = wl1271_acx_rx_config(wl, wl->rx_config, wl->rx_filter);
        if (ret < 0)
 
 out:
        mutex_unlock(&wl->mutex);
+       kfree(fp);
 }
 
 static int wl1271_op_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
             * and enable the BSSID filter
             */
            memcmp(wl->bssid, bss_conf->bssid, ETH_ALEN)) {
-                       wl->rx_config |= CFG_BSSID_FILTER_EN;
                        memcpy(wl->bssid, bss_conf->bssid, ETH_ALEN);
                        ret = wl1271_cmd_build_null_data(wl);
                        if (ret < 0) {
                                goto out_sleep;
                        }
 
+                       /* filter out all packets not from this BSSID */
+                       wl1271_configure_filters(wl, 0);
+
                        /* Need to update the BSSID (for filtering etc) */
                        do_join = true;
        }