linux/drivers/net/wireless/wl12xx/event.c
<<
>>
Prefs
   1/*
   2 * This file is part of wl1271
   3 *
   4 * Copyright (C) 2008-2009 Nokia Corporation
   5 *
   6 * Contact: Luciano Coelho <luciano.coelho@nokia.com>
   7 *
   8 * This program is free software; you can redistribute it and/or
   9 * modify it under the terms of the GNU General Public License
  10 * version 2 as published by the Free Software Foundation.
  11 *
  12 * This program is distributed in the hope that it will be useful, but
  13 * WITHOUT ANY WARRANTY; without even the implied warranty of
  14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  15 * General Public License for more details.
  16 *
  17 * You should have received a copy of the GNU General Public License
  18 * along with this program; if not, write to the Free Software
  19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
  20 * 02110-1301 USA
  21 *
  22 */
  23
  24#include "wl12xx.h"
  25#include "reg.h"
  26#include "io.h"
  27#include "event.h"
  28#include "ps.h"
  29#include "scan.h"
  30#include "wl12xx_80211.h"
  31
  32void wl1271_pspoll_work(struct work_struct *work)
  33{
  34        struct delayed_work *dwork;
  35        struct wl1271 *wl;
  36        int ret;
  37
  38        dwork = container_of(work, struct delayed_work, work);
  39        wl = container_of(dwork, struct wl1271, pspoll_work);
  40
  41        wl1271_debug(DEBUG_EVENT, "pspoll work");
  42
  43        mutex_lock(&wl->mutex);
  44
  45        if (unlikely(wl->state == WL1271_STATE_OFF))
  46                goto out;
  47
  48        if (!test_and_clear_bit(WL1271_FLAG_PSPOLL_FAILURE, &wl->flags))
  49                goto out;
  50
  51        if (!test_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags))
  52                goto out;
  53
  54        /*
  55         * if we end up here, then we were in powersave when the pspoll
  56         * delivery failure occurred, and no-one changed state since, so
  57         * we should go back to powersave.
  58         */
  59        ret = wl1271_ps_elp_wakeup(wl);
  60        if (ret < 0)
  61                goto out;
  62
  63        wl1271_ps_set_mode(wl, STATION_POWER_SAVE_MODE, wl->basic_rate, true);
  64
  65        wl1271_ps_elp_sleep(wl);
  66out:
  67        mutex_unlock(&wl->mutex);
  68};
  69
  70static void wl1271_event_pspoll_delivery_fail(struct wl1271 *wl)
  71{
  72        int delay = wl->conf.conn.ps_poll_recovery_period;
  73        int ret;
  74
  75        wl->ps_poll_failures++;
  76        if (wl->ps_poll_failures == 1)
  77                wl1271_info("AP with dysfunctional ps-poll, "
  78                            "trying to work around it.");
  79
  80        /* force active mode receive data from the AP */
  81        if (test_bit(WL1271_FLAG_PSM, &wl->flags)) {
  82                ret = wl1271_ps_set_mode(wl, STATION_ACTIVE_MODE,
  83                                         wl->basic_rate, true);
  84                if (ret < 0)
  85                        return;
  86                set_bit(WL1271_FLAG_PSPOLL_FAILURE, &wl->flags);
  87                ieee80211_queue_delayed_work(wl->hw, &wl->pspoll_work,
  88                                             msecs_to_jiffies(delay));
  89        }
  90
  91        /*
  92         * If already in active mode, lets we should be getting data from
  93         * the AP right away. If we enter PSM too fast after this, and data
  94         * remains on the AP, we will get another event like this, and we'll
  95         * go into active once more.
  96         */
  97}
  98
  99static int wl1271_event_ps_report(struct wl1271 *wl,
 100                                  struct event_mailbox *mbox,
 101                                  bool *beacon_loss)
 102{
 103        int ret = 0;
 104        u32 total_retries = wl->conf.conn.psm_entry_retries;
 105
 106        wl1271_debug(DEBUG_EVENT, "ps_status: 0x%x", mbox->ps_status);
 107
 108        switch (mbox->ps_status) {
 109        case EVENT_ENTER_POWER_SAVE_FAIL:
 110                wl1271_debug(DEBUG_PSM, "PSM entry failed");
 111
 112                if (!test_bit(WL1271_FLAG_PSM, &wl->flags)) {
 113                        /* remain in active mode */
 114                        wl->psm_entry_retry = 0;
 115                        break;
 116                }
 117
 118                if (wl->psm_entry_retry < total_retries) {
 119                        wl->psm_entry_retry++;
 120                        ret = wl1271_ps_set_mode(wl, STATION_POWER_SAVE_MODE,
 121                                                 wl->basic_rate, true);
 122                } else {
 123                        wl1271_info("No ack to nullfunc from AP.");
 124                        wl->psm_entry_retry = 0;
 125                        *beacon_loss = true;
 126                }
 127                break;
 128        case EVENT_ENTER_POWER_SAVE_SUCCESS:
 129                wl->psm_entry_retry = 0;
 130
 131                /* enable beacon filtering */
 132                ret = wl1271_acx_beacon_filter_opt(wl, true);
 133                if (ret < 0)
 134                        break;
 135
 136                /*
 137                 * BET has only a minor effect in 5GHz and masks
 138                 * channel switch IEs, so we only enable BET on 2.4GHz
 139                */
 140                if (wl->band == IEEE80211_BAND_2GHZ)
 141                        /* enable beacon early termination */
 142                        ret = wl1271_acx_bet_enable(wl, true);
 143
 144                if (wl->ps_compl) {
 145                        complete(wl->ps_compl);
 146                        wl->ps_compl = NULL;
 147                }
 148                break;
 149        default:
 150                break;
 151        }
 152
 153        return ret;
 154}
 155
 156static void wl1271_event_rssi_trigger(struct wl1271 *wl,
 157                                      struct event_mailbox *mbox)
 158{
 159        enum nl80211_cqm_rssi_threshold_event event;
 160        s8 metric = mbox->rssi_snr_trigger_metric[0];
 161
 162        wl1271_debug(DEBUG_EVENT, "RSSI trigger metric: %d", metric);
 163
 164        if (metric <= wl->rssi_thold)
 165                event = NL80211_CQM_RSSI_THRESHOLD_EVENT_LOW;
 166        else
 167                event = NL80211_CQM_RSSI_THRESHOLD_EVENT_HIGH;
 168
 169        if (event != wl->last_rssi_event)
 170                ieee80211_cqm_rssi_notify(wl->vif, event, GFP_KERNEL);
 171        wl->last_rssi_event = event;
 172}
 173
 174static void wl1271_stop_ba_event(struct wl1271 *wl)
 175{
 176        if (wl->bss_type != BSS_TYPE_AP_BSS) {
 177                if (!wl->ba_rx_bitmap)
 178                        return;
 179                ieee80211_stop_rx_ba_session(wl->vif, wl->ba_rx_bitmap,
 180                                             wl->bssid);
 181        } else {
 182                int i;
 183                struct wl1271_link *lnk;
 184                for (i = WL1271_AP_STA_HLID_START; i < AP_MAX_LINKS; i++) {
 185                        lnk = &wl->links[i];
 186                        if (!wl1271_is_active_sta(wl, i) || !lnk->ba_bitmap)
 187                                continue;
 188
 189                        ieee80211_stop_rx_ba_session(wl->vif,
 190                                                     lnk->ba_bitmap,
 191                                                     lnk->addr);
 192                }
 193        }
 194}
 195
 196static void wl12xx_event_soft_gemini_sense(struct wl1271 *wl,
 197                                               u8 enable)
 198{
 199        if (enable) {
 200                /* disable dynamic PS when requested by the firmware */
 201                ieee80211_disable_dyn_ps(wl->vif);
 202                set_bit(WL1271_FLAG_SOFT_GEMINI, &wl->flags);
 203        } else {
 204                ieee80211_enable_dyn_ps(wl->vif);
 205                clear_bit(WL1271_FLAG_SOFT_GEMINI, &wl->flags);
 206                wl1271_recalc_rx_streaming(wl);
 207        }
 208
 209}
 210
 211static void wl1271_event_mbox_dump(struct event_mailbox *mbox)
 212{
 213        wl1271_debug(DEBUG_EVENT, "MBOX DUMP:");
 214        wl1271_debug(DEBUG_EVENT, "\tvector: 0x%x", mbox->events_vector);
 215        wl1271_debug(DEBUG_EVENT, "\tmask: 0x%x", mbox->events_mask);
 216}
 217
 218static int wl1271_event_process(struct wl1271 *wl, struct event_mailbox *mbox)
 219{
 220        int ret;
 221        u32 vector;
 222        bool beacon_loss = false;
 223        bool is_ap = (wl->bss_type == BSS_TYPE_AP_BSS);
 224        bool disconnect_sta = false;
 225        unsigned long sta_bitmap = 0;
 226
 227        wl1271_event_mbox_dump(mbox);
 228
 229        vector = le32_to_cpu(mbox->events_vector);
 230        vector &= ~(le32_to_cpu(mbox->events_mask));
 231        wl1271_debug(DEBUG_EVENT, "vector: 0x%x", vector);
 232
 233        if (vector & SCAN_COMPLETE_EVENT_ID) {
 234                wl1271_debug(DEBUG_EVENT, "status: 0x%x",
 235                             mbox->scheduled_scan_status);
 236
 237                wl1271_scan_stm(wl);
 238        }
 239
 240        if (vector & PERIODIC_SCAN_REPORT_EVENT_ID) {
 241                wl1271_debug(DEBUG_EVENT, "PERIODIC_SCAN_REPORT_EVENT "
 242                             "(status 0x%0x)", mbox->scheduled_scan_status);
 243
 244                wl1271_scan_sched_scan_results(wl);
 245        }
 246
 247        if (vector & PERIODIC_SCAN_COMPLETE_EVENT_ID) {
 248                wl1271_debug(DEBUG_EVENT, "PERIODIC_SCAN_COMPLETE_EVENT "
 249                             "(status 0x%0x)", mbox->scheduled_scan_status);
 250                if (wl->sched_scanning) {
 251                        wl1271_scan_sched_scan_stop(wl);
 252                        ieee80211_sched_scan_stopped(wl->hw);
 253                }
 254        }
 255
 256        if (vector & SOFT_GEMINI_SENSE_EVENT_ID &&
 257            wl->bss_type == BSS_TYPE_STA_BSS)
 258                wl12xx_event_soft_gemini_sense(wl,
 259                                               mbox->soft_gemini_sense_info);
 260
 261        /*
 262         * The BSS_LOSE_EVENT_ID is only needed while psm (and hence beacon
 263         * filtering) is enabled. Without PSM, the stack will receive all
 264         * beacons and can detect beacon loss by itself.
 265         *
 266         * As there's possibility that the driver disables PSM before receiving
 267         * BSS_LOSE_EVENT, beacon loss has to be reported to the stack.
 268         *
 269         */
 270        if ((vector & BSS_LOSE_EVENT_ID) && !is_ap) {
 271                wl1271_info("Beacon loss detected.");
 272
 273                /* indicate to the stack, that beacons have been lost */
 274                beacon_loss = true;
 275        }
 276
 277        if ((vector & PS_REPORT_EVENT_ID) && !is_ap) {
 278                wl1271_debug(DEBUG_EVENT, "PS_REPORT_EVENT");
 279                ret = wl1271_event_ps_report(wl, mbox, &beacon_loss);
 280                if (ret < 0)
 281                        return ret;
 282        }
 283
 284        if ((vector & PSPOLL_DELIVERY_FAILURE_EVENT_ID) && !is_ap)
 285                wl1271_event_pspoll_delivery_fail(wl);
 286
 287        if (vector & RSSI_SNR_TRIGGER_0_EVENT_ID) {
 288                wl1271_debug(DEBUG_EVENT, "RSSI_SNR_TRIGGER_0_EVENT");
 289                if (wl->vif)
 290                        wl1271_event_rssi_trigger(wl, mbox);
 291        }
 292
 293        if ((vector & BA_SESSION_RX_CONSTRAINT_EVENT_ID)) {
 294                wl1271_debug(DEBUG_EVENT, "BA_SESSION_RX_CONSTRAINT_EVENT_ID. "
 295                             "ba_allowed = 0x%x", mbox->rx_ba_allowed);
 296
 297                wl->ba_allowed = !!mbox->rx_ba_allowed;
 298
 299                if (wl->vif && !wl->ba_allowed)
 300                        wl1271_stop_ba_event(wl);
 301        }
 302
 303        if ((vector & CHANNEL_SWITCH_COMPLETE_EVENT_ID) && !is_ap) {
 304                wl1271_debug(DEBUG_EVENT, "CHANNEL_SWITCH_COMPLETE_EVENT_ID. "
 305                                          "status = 0x%x",
 306                                          mbox->channel_switch_status);
 307                /*
 308                 * That event uses for two cases:
 309                 * 1) channel switch complete with status=0
 310                 * 2) channel switch failed status=1
 311                 */
 312                if (test_and_clear_bit(WL1271_FLAG_CS_PROGRESS, &wl->flags) &&
 313                    (wl->vif))
 314                        ieee80211_chswitch_done(wl->vif,
 315                                mbox->channel_switch_status ? false : true);
 316        }
 317
 318        if ((vector & DUMMY_PACKET_EVENT_ID)) {
 319                wl1271_debug(DEBUG_EVENT, "DUMMY_PACKET_ID_EVENT_ID");
 320                if (wl->vif)
 321                        wl1271_tx_dummy_packet(wl);
 322        }
 323
 324        /*
 325         * "TX retries exceeded" has a different meaning according to mode.
 326         * In AP mode the offending station is disconnected.
 327         */
 328        if ((vector & MAX_TX_RETRY_EVENT_ID) && is_ap) {
 329                wl1271_debug(DEBUG_EVENT, "MAX_TX_RETRY_EVENT_ID");
 330                sta_bitmap |= le16_to_cpu(mbox->sta_tx_retry_exceeded);
 331                disconnect_sta = true;
 332        }
 333
 334        if ((vector & INACTIVE_STA_EVENT_ID) && is_ap) {
 335                wl1271_debug(DEBUG_EVENT, "INACTIVE_STA_EVENT_ID");
 336                sta_bitmap |= le16_to_cpu(mbox->sta_aging_status);
 337                disconnect_sta = true;
 338        }
 339
 340        if (is_ap && disconnect_sta) {
 341                u32 num_packets = wl->conf.tx.max_tx_retries;
 342                struct ieee80211_sta *sta;
 343                const u8 *addr;
 344                int h;
 345
 346                for (h = find_first_bit(&sta_bitmap, AP_MAX_LINKS);
 347                     h < AP_MAX_LINKS;
 348                     h = find_next_bit(&sta_bitmap, AP_MAX_LINKS, h+1)) {
 349                        if (!wl1271_is_active_sta(wl, h))
 350                                continue;
 351
 352                        addr = wl->links[h].addr;
 353
 354                        rcu_read_lock();
 355                        sta = ieee80211_find_sta(wl->vif, addr);
 356                        if (sta) {
 357                                wl1271_debug(DEBUG_EVENT, "remove sta %d", h);
 358                                ieee80211_report_low_ack(sta, num_packets);
 359                        }
 360                        rcu_read_unlock();
 361                }
 362        }
 363
 364        if (wl->vif && beacon_loss)
 365                ieee80211_connection_loss(wl->vif);
 366
 367        return 0;
 368}
 369
 370int wl1271_event_unmask(struct wl1271 *wl)
 371{
 372        int ret;
 373
 374        ret = wl1271_acx_event_mbox_mask(wl, ~(wl->event_mask));
 375        if (ret < 0)
 376                return ret;
 377
 378        return 0;
 379}
 380
 381void wl1271_event_mbox_config(struct wl1271 *wl)
 382{
 383        wl->mbox_ptr[0] = wl1271_read32(wl, REG_EVENT_MAILBOX_PTR);
 384        wl->mbox_ptr[1] = wl->mbox_ptr[0] + sizeof(struct event_mailbox);
 385
 386        wl1271_debug(DEBUG_EVENT, "MBOX ptrs: 0x%x 0x%x",
 387                     wl->mbox_ptr[0], wl->mbox_ptr[1]);
 388}
 389
 390int wl1271_event_handle(struct wl1271 *wl, u8 mbox_num)
 391{
 392        struct event_mailbox mbox;
 393        int ret;
 394
 395        wl1271_debug(DEBUG_EVENT, "EVENT on mbox %d", mbox_num);
 396
 397        if (mbox_num > 1)
 398                return -EINVAL;
 399
 400        /* first we read the mbox descriptor */
 401        wl1271_read(wl, wl->mbox_ptr[mbox_num], &mbox,
 402                    sizeof(struct event_mailbox), false);
 403
 404        /* process the descriptor */
 405        ret = wl1271_event_process(wl, &mbox);
 406        if (ret < 0)
 407                return ret;
 408
 409        /* then we let the firmware know it can go on...*/
 410        wl1271_write32(wl, ACX_REG_INTERRUPT_TRIG, INTR_TRIG_EVENT_ACK);
 411
 412        return 0;
 413}
 414