X-Git-Url: https://git.openpandora.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=drivers%2Fnet%2Fwireless%2Fwl12xx%2Fwl1251_main.c;h=8b3e78e74694970f847fd2beecebc423b22b1296;hb=4213d143b82b07dfc5cd9a05c2693f15c087e5d4;hp=5e091611f69f8a8e599fc8fca137c43eb04389e5;hpb=fd04b4023b06eb70ab0db22e1c46924300c8320f;p=pandora-wifi.git diff --git a/drivers/net/wireless/wl12xx/wl1251_main.c b/drivers/net/wireless/wl12xx/wl1251_main.c index 5e09161..8b3e78e 100644 --- a/drivers/net/wireless/wl12xx/wl1251_main.c +++ b/drivers/net/wireless/wl12xx/wl1251_main.c @@ -323,6 +323,46 @@ out: mutex_unlock(&wl->mutex); } +static void wl1251_convert_filters(struct wl1251 *wl, + unsigned int mac80211_filters) +{ + wl->rx_config = WL1251_DEFAULT_RX_CONFIG; + wl->rx_filter = WL1251_DEFAULT_RX_FILTER; + + if (mac80211_filters & FIF_PROMISC_IN_BSS) { + wl->rx_config |= CFG_BSSID_FILTER_EN; + wl->rx_config &= ~CFG_UNI_FILTER_EN; + } + if (mac80211_filters & FIF_ALLMULTI) + /* + * CFG_MC_FILTER_EN in rx_config needs to be 0 to receive + * all multicast frames + */ + wl->rx_config &= ~CFG_MC_FILTER_EN; + if (mac80211_filters & FIF_FCSFAIL) + wl->rx_filter |= CFG_RX_FCS_ERROR; + if (mac80211_filters & FIF_BCN_PRBRESP_PROMISC) { + wl->rx_config &= ~CFG_BSSID_FILTER_EN; + wl->rx_config &= ~CFG_SSID_FILTER_EN; + } + if (mac80211_filters & FIF_CONTROL) + wl->rx_filter |= CFG_RX_CTL_EN; + if (mac80211_filters & FIF_OTHER_BSS) + wl->rx_config &= ~CFG_BSSID_FILTER_EN; + if (mac80211_filters & FIF_PROBE_REQ) + wl->rx_filter |= CFG_RX_PREQ_EN; + + /* + * If we have no associated BSSID, the filter must be disabled + * or else association will break + */ + if (is_zero_ether_addr(wl->bssid)) + wl->rx_config &= ~CFG_BSSID_FILTER_EN; + + wl1251_debug(DEBUG_FILTERS, "rx_config %04x, rx_filter %04x", + wl->rx_config, wl->rx_filter); +} + static int wl1251_join(struct wl1251 *wl, u8 bss_type, u8 channel, u16 beacon_interval, u8 dtim_period) { @@ -335,6 +375,8 @@ static int wl1251_join(struct wl1251 *wl, u8 bss_type, u8 channel, if (ret < 0) goto out; + /* Join uses filters, update them */ + wl1251_convert_filters(wl, wl->mac80211_filters); ret = wl1251_cmd_join(wl, bss_type, channel, beacon_interval, dtim_period); @@ -349,33 +391,6 @@ out: return ret; } -static void wl1251_filter_work(struct work_struct *work) -{ - struct wl1251 *wl = - container_of(work, struct wl1251, filter_work); - int ret; - - mutex_lock(&wl->mutex); - - if (wl->state == WL1251_STATE_OFF) - goto out; - - ret = wl1251_ps_elp_wakeup(wl); - if (ret < 0) - goto out; - - ret = wl1251_join(wl, wl->bss_type, wl->channel, wl->beacon_int, - wl->dtim_period); - if (ret < 0) - goto out_sleep; - -out_sleep: - wl1251_ps_elp_sleep(wl); - -out: - mutex_unlock(&wl->mutex); -} - static int wl1251_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb) { struct wl1251 *wl = hw->priv; @@ -483,7 +498,6 @@ static void wl1251_op_stop(struct ieee80211_hw *hw) cancel_work_sync(&wl->irq_work); cancel_work_sync(&wl->tx_work); - cancel_work_sync(&wl->filter_work); mutex_lock(&wl->mutex); @@ -676,15 +690,18 @@ out: FIF_FCSFAIL | \ FIF_BCN_PRBRESP_PROMISC | \ FIF_CONTROL | \ - FIF_OTHER_BSS) + FIF_OTHER_BSS | \ + FIF_PROBE_REQ) static void wl1251_op_configure_filter(struct ieee80211_hw *hw, unsigned int changed, unsigned int *total,u64 multicast) { struct wl1251 *wl = hw->priv; + int ret; wl1251_debug(DEBUG_MAC80211, "mac80211 configure filter"); + wl1251_debug(DEBUG_FILTERS, "configure filter %x %x", *total, changed); *total &= WL1251_SUPPORTED_FILTERS; changed &= WL1251_SUPPORTED_FILTERS; @@ -693,38 +710,25 @@ static void wl1251_op_configure_filter(struct ieee80211_hw *hw, /* no filters which we support changed */ return; - /* FIXME: wl->rx_config and wl->rx_filter are not protected */ + mutex_lock(&wl->mutex); - wl->rx_config = WL1251_DEFAULT_RX_CONFIG; - wl->rx_filter = WL1251_DEFAULT_RX_FILTER; + wl->mac80211_filters = *total; + wl1251_convert_filters(wl, *total); - if (*total & FIF_PROMISC_IN_BSS) { - wl->rx_config |= CFG_BSSID_FILTER_EN; - wl->rx_config |= CFG_RX_ALL_GOOD; - } - if (*total & FIF_ALLMULTI) - /* - * CFG_MC_FILTER_EN in rx_config needs to be 0 to receive - * all multicast frames - */ - wl->rx_config &= ~CFG_MC_FILTER_EN; - if (*total & FIF_FCSFAIL) - wl->rx_filter |= CFG_RX_FCS_ERROR; - if (*total & FIF_BCN_PRBRESP_PROMISC) { - wl->rx_config &= ~CFG_BSSID_FILTER_EN; - wl->rx_config &= ~CFG_SSID_FILTER_EN; - } - if (*total & FIF_CONTROL) - wl->rx_filter |= CFG_RX_CTL_EN; - if (*total & FIF_OTHER_BSS) - wl->rx_filter &= ~CFG_BSSID_FILTER_EN; + if (wl->state == WL1251_STATE_OFF) + goto out; - /* - * FIXME: workqueues need to be properly cancelled on stop(), for - * now let's just disable changing the filter settings. They will - * be updated any on config(). - */ - /* schedule_work(&wl->filter_work); */ + ret = wl1251_ps_elp_wakeup(wl); + if (ret < 0) + goto out; + + /* apply configured filters */ + wl1251_acx_rx_config(wl, wl->rx_config, wl->rx_filter); + + wl1251_ps_elp_sleep(wl); + +out: + mutex_unlock(&wl->mutex); } /* HW encryption */ @@ -1358,7 +1362,6 @@ struct ieee80211_hw *wl1251_alloc_hw(void) skb_queue_head_init(&wl->tx_queue); - INIT_WORK(&wl->filter_work, wl1251_filter_work); INIT_DELAYED_WORK(&wl->elp_work, wl1251_elp_work); wl->channel = WL1251_DEFAULT_CHANNEL; wl->scanning = false;