X-Git-Url: https://git.openpandora.org/cgi-bin/gitweb.cgi?p=pandora-kernel.git;a=blobdiff_plain;f=drivers%2Fnet%2Fwireless%2Fwl1251%2Fmain.c;h=b012867ad6c55b8151a753cdb5c47c1a9b467aba;hp=24e7aac4669ec0d3ddf926cb4904cac903e5aef3;hb=e466b34681a0a07960cbf43791da3b8e042a05e0;hpb=c432db279f4f03bf6a315bc2138ac3a15717e6bb diff --git a/drivers/net/wireless/wl1251/main.c b/drivers/net/wireless/wl1251/main.c index 24e7aac4669e..b012867ad6c5 100644 --- a/drivers/net/wireless/wl1251/main.c +++ b/drivers/net/wireless/wl1251/main.c @@ -43,6 +43,13 @@ #include "debugfs.h" #include "boot.h" +static bool use_fw_ps = true; +module_param(use_fw_ps, bool, 0644); +MODULE_PARM_DESC(use_fw_ps, "Enable powersave once and leave it for chip's " + "firmware to manage. When disabled, mac80211 " + "will toggle powersave on tx activity instead. " + "Default: y/Y/1"); + void wl1251_enable_interrupts(struct wl1251 *wl) { wl->if_ops->enable_irq(wl); @@ -279,9 +286,18 @@ irqreturn_t wl1251_irq(int irq, void *cookie) goto out_sleep; } + if (intr & WL1251_ACX_INTR_TX_RESULT) { + wl1251_debug(DEBUG_IRQ, "WL1251_ACX_INTR_TX_RESULT"); + wl1251_tx_complete(wl); + } + if (intr & WL1251_ACX_INTR_RX0_DATA) { wl1251_debug(DEBUG_IRQ, "WL1251_ACX_INTR_RX0_DATA"); wl1251_rx(wl); + + if ((intr & WL1251_ACX_INTR_RX1_DATA) + && skb_queue_len(&wl->tx_queue) > 0) + wl1251_tx_work_unlocked(wl, false); } if (intr & WL1251_ACX_INTR_RX1_DATA) { @@ -289,11 +305,6 @@ irqreturn_t wl1251_irq(int irq, void *cookie) wl1251_rx(wl); } - if (intr & WL1251_ACX_INTR_TX_RESULT) { - wl1251_debug(DEBUG_IRQ, "WL1251_ACX_INTR_TX_RESULT"); - wl1251_tx_complete(wl); - } - if (intr & WL1251_ACX_INTR_EVENT_A) { wl1251_debug(DEBUG_IRQ, "WL1251_ACX_INTR_EVENT_A"); wl1251_event_handle(wl, 0); @@ -308,21 +319,8 @@ irqreturn_t wl1251_irq(int irq, void *cookie) wl1251_debug(DEBUG_IRQ, "WL1251_ACX_INTR_INIT_COMPLETE"); - while (skb_queue_len(&wl->tx_queue) > 0 - && wl1251_tx_path_status(wl) == 0) { - - struct sk_buff *skb = skb_dequeue(&wl->tx_queue); - if (skb == NULL) - goto out_sleep; - - ret = wl1251_tx_frame(wl, skb); - if (ret == -EBUSY) { - skb_queue_head(&wl->tx_queue, skb); - break; - } else if (ret < 0) { - dev_kfree_skb(skb); - } - } + if (skb_queue_len(&wl->tx_queue) > 0) + wl1251_tx_work_unlocked(wl, false); if (--ctr == 0) break; @@ -376,6 +374,9 @@ static int wl1251_join(struct wl1251 *wl, u8 bss_type, u8 channel, if (ret < 0) wl1251_warning("join timeout"); + wl1251_no_ps_event(wl); + wl->bss_lost = 0; + out: return ret; } @@ -510,6 +511,7 @@ static void wl1251_op_stop(struct ieee80211_hw *hw) wl->channel = WL1251_DEFAULT_CHANNEL; wl->monitor_present = false; wl->joined = false; + wl->long_doze_mode_set = false; wl1251_debugfs_reset(wl); @@ -651,8 +653,9 @@ static void wl1251_ps_work(struct work_struct *work) } } - need_ps = wl->psm_requested && !wl->bss_lost; have_ps = wl->station_mode == STATION_POWER_SAVE_MODE; + need_ps = wl->psm_requested && !wl->bss_lost + && wl->rate < wl->ps_rate_threshold; if (need_ps == have_ps) { //wl1251_info("ps: already in mode %d", have_ps); @@ -663,11 +666,13 @@ static void wl1251_ps_work(struct work_struct *work) if (need_ps) { wait = 0; - diff = jiffies - wl->last_io_jiffies; - if (diff < msecs_to_jiffies(150)) { - //wl1251_info("ps: postponed psm, j %ld", diff); - wait = msecs_to_jiffies(150) - diff + 1; - } + diff = jiffies - wl->last_no_ps_jiffies[1]; + if (diff < msecs_to_jiffies(1000)) + wait = msecs_to_jiffies(1000) - diff + 1; + + diff = jiffies - wl->last_no_ps_jiffies[0]; + if (diff < msecs_to_jiffies(3000)) + wait += msecs_to_jiffies(1000); for (i = 0; i < ARRAY_SIZE(wl->tx_frames); i++) { if (wl->tx_frames[i] != NULL) { @@ -697,8 +702,7 @@ static void wl1251_ps_work(struct work_struct *work) if (ret < 0) goto out_sleep; - //wl1251_info("psm %d, j %ld, d %ld", need_ps, - // jiffies - wl->last_io_jiffies); + // wl1251_info("psm %d, r %u", need_ps, wl->rate); out_sleep: wl1251_ps_elp_sleep(wl); @@ -1604,6 +1608,9 @@ int wl1251_init_ieee80211(struct wl1251 *wl) IEEE80211_HW_SUPPORTS_UAPSD | IEEE80211_HW_SUPPORTS_CQM_RSSI; + if (use_fw_ps) + wl->hw->flags |= IEEE80211_HW_SUPPORTS_DYNAMIC_PS; + wl->hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) | BIT(NL80211_IFTYPE_ADHOC); wl->hw->wiphy->max_scan_ssids = 1; @@ -1676,6 +1683,7 @@ struct ieee80211_hw *wl1251_alloc_hw(void) wl->beacon_int = WL1251_DEFAULT_BEACON_INT; wl->dtim_period = WL1251_DEFAULT_DTIM_PERIOD; wl->vif = NULL; + wl->ps_rate_threshold = 100000; for (i = 0; i < FW_TX_CMPLT_BLOCK_SIZE; i++) wl->tx_frames[i] = NULL;