root/drivers/net/wireless/ti/wl1251/event.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. wl1251_event_scan_complete
  2. wl1251_event_ps_report
  3. wl1251_event_mbox_dump
  4. wl1251_event_process
  5. wl1251_event_wait
  6. wl1251_event_unmask
  7. wl1251_event_mbox_config
  8. wl1251_event_handle

   1 // SPDX-License-Identifier: GPL-2.0-only
   2 /*
   3  * This file is part of wl1251
   4  *
   5  * Copyright (c) 1998-2007 Texas Instruments Incorporated
   6  * Copyright (C) 2008 Nokia Corporation
   7  */
   8 
   9 #include "wl1251.h"
  10 #include "reg.h"
  11 #include "io.h"
  12 #include "event.h"
  13 #include "ps.h"
  14 
  15 static int wl1251_event_scan_complete(struct wl1251 *wl,
  16                                       struct event_mailbox *mbox)
  17 {
  18         int ret = 0;
  19 
  20         wl1251_debug(DEBUG_EVENT, "status: 0x%x, channels: %d",
  21                      mbox->scheduled_scan_status,
  22                      mbox->scheduled_scan_channels);
  23 
  24         if (wl->scanning) {
  25                 struct cfg80211_scan_info info = {
  26                         .aborted = false,
  27                 };
  28 
  29                 ieee80211_scan_completed(wl->hw, &info);
  30                 wl1251_debug(DEBUG_MAC80211, "mac80211 hw scan completed");
  31                 wl->scanning = false;
  32                 if (wl->hw->conf.flags & IEEE80211_CONF_IDLE)
  33                         ret = wl1251_ps_set_mode(wl, STATION_IDLE);
  34         }
  35 
  36         return ret;
  37 }
  38 
  39 #define WL1251_PSM_ENTRY_RETRIES  3
  40 static int wl1251_event_ps_report(struct wl1251 *wl,
  41                                   struct event_mailbox *mbox)
  42 {
  43         int ret = 0;
  44 
  45         wl1251_debug(DEBUG_EVENT, "ps status: %x", mbox->ps_status);
  46 
  47         switch (mbox->ps_status) {
  48         case EVENT_ENTER_POWER_SAVE_FAIL:
  49                 wl1251_debug(DEBUG_PSM, "PSM entry failed");
  50 
  51                 if (wl->station_mode != STATION_POWER_SAVE_MODE) {
  52                         /* remain in active mode */
  53                         wl->psm_entry_retry = 0;
  54                         break;
  55                 }
  56 
  57                 if (wl->psm_entry_retry < WL1251_PSM_ENTRY_RETRIES) {
  58                         wl->psm_entry_retry++;
  59                         ret = wl1251_ps_set_mode(wl, STATION_POWER_SAVE_MODE);
  60                 } else {
  61                         wl1251_error("Power save entry failed, giving up");
  62                         wl->psm_entry_retry = 0;
  63                 }
  64                 break;
  65         case EVENT_ENTER_POWER_SAVE_SUCCESS:
  66         case EVENT_EXIT_POWER_SAVE_FAIL:
  67         case EVENT_EXIT_POWER_SAVE_SUCCESS:
  68         default:
  69                 wl->psm_entry_retry = 0;
  70                 break;
  71         }
  72 
  73         return 0;
  74 }
  75 
  76 static void wl1251_event_mbox_dump(struct event_mailbox *mbox)
  77 {
  78         wl1251_debug(DEBUG_EVENT, "MBOX DUMP:");
  79         wl1251_debug(DEBUG_EVENT, "\tvector: 0x%x", mbox->events_vector);
  80         wl1251_debug(DEBUG_EVENT, "\tmask: 0x%x", mbox->events_mask);
  81 }
  82 
  83 static int wl1251_event_process(struct wl1251 *wl, struct event_mailbox *mbox)
  84 {
  85         int ret;
  86         u32 vector;
  87 
  88         wl1251_event_mbox_dump(mbox);
  89 
  90         vector = mbox->events_vector & ~(mbox->events_mask);
  91         wl1251_debug(DEBUG_EVENT, "vector: 0x%x", vector);
  92 
  93         if (vector & SCAN_COMPLETE_EVENT_ID) {
  94                 ret = wl1251_event_scan_complete(wl, mbox);
  95                 if (ret < 0)
  96                         return ret;
  97         }
  98 
  99         if (vector & BSS_LOSE_EVENT_ID) {
 100                 wl1251_debug(DEBUG_EVENT, "BSS_LOSE_EVENT");
 101 
 102                 if (wl->psm_requested &&
 103                     wl->station_mode != STATION_ACTIVE_MODE) {
 104                         ret = wl1251_ps_set_mode(wl, STATION_ACTIVE_MODE);
 105                         if (ret < 0)
 106                                 return ret;
 107                 }
 108         }
 109 
 110         if (vector & PS_REPORT_EVENT_ID) {
 111                 wl1251_debug(DEBUG_EVENT, "PS_REPORT_EVENT");
 112                 ret = wl1251_event_ps_report(wl, mbox);
 113                 if (ret < 0)
 114                         return ret;
 115         }
 116 
 117         if (vector & SYNCHRONIZATION_TIMEOUT_EVENT_ID) {
 118                 wl1251_debug(DEBUG_EVENT, "SYNCHRONIZATION_TIMEOUT_EVENT");
 119 
 120                 /* indicate to the stack, that beacons have been lost */
 121                 if (wl->vif && wl->vif->type == NL80211_IFTYPE_STATION)
 122                         ieee80211_beacon_loss(wl->vif);
 123         }
 124 
 125         if (vector & REGAINED_BSS_EVENT_ID) {
 126                 if (wl->psm_requested) {
 127                         ret = wl1251_ps_set_mode(wl, STATION_POWER_SAVE_MODE);
 128                         if (ret < 0)
 129                                 return ret;
 130                 }
 131         }
 132 
 133         if (wl->vif && wl->rssi_thold) {
 134                 if (vector & ROAMING_TRIGGER_LOW_RSSI_EVENT_ID) {
 135                         wl1251_debug(DEBUG_EVENT,
 136                                      "ROAMING_TRIGGER_LOW_RSSI_EVENT");
 137                         ieee80211_cqm_rssi_notify(wl->vif,
 138                                 NL80211_CQM_RSSI_THRESHOLD_EVENT_LOW,
 139                                 0, GFP_KERNEL);
 140                 }
 141 
 142                 if (vector & ROAMING_TRIGGER_REGAINED_RSSI_EVENT_ID) {
 143                         wl1251_debug(DEBUG_EVENT,
 144                                      "ROAMING_TRIGGER_REGAINED_RSSI_EVENT");
 145                         ieee80211_cqm_rssi_notify(wl->vif,
 146                                 NL80211_CQM_RSSI_THRESHOLD_EVENT_HIGH,
 147                                 0, GFP_KERNEL);
 148                 }
 149         }
 150 
 151         return 0;
 152 }
 153 
 154 /*
 155  * Poll the mailbox event field until any of the bits in the mask is set or a
 156  * timeout occurs (WL1251_EVENT_TIMEOUT in msecs)
 157  */
 158 int wl1251_event_wait(struct wl1251 *wl, u32 mask, int timeout_ms)
 159 {
 160         u32 events_vector, event;
 161         unsigned long timeout;
 162 
 163         timeout = jiffies + msecs_to_jiffies(timeout_ms);
 164 
 165         do {
 166                 if (time_after(jiffies, timeout))
 167                         return -ETIMEDOUT;
 168 
 169                 msleep(1);
 170 
 171                 /* read from both event fields */
 172                 wl1251_mem_read(wl, wl->mbox_ptr[0], &events_vector,
 173                                 sizeof(events_vector));
 174                 event = events_vector & mask;
 175                 wl1251_mem_read(wl, wl->mbox_ptr[1], &events_vector,
 176                                 sizeof(events_vector));
 177                 event |= events_vector & mask;
 178         } while (!event);
 179 
 180         return 0;
 181 }
 182 
 183 int wl1251_event_unmask(struct wl1251 *wl)
 184 {
 185         int ret;
 186 
 187         ret = wl1251_acx_event_mbox_mask(wl, ~(wl->event_mask));
 188         if (ret < 0)
 189                 return ret;
 190 
 191         return 0;
 192 }
 193 
 194 void wl1251_event_mbox_config(struct wl1251 *wl)
 195 {
 196         wl->mbox_ptr[0] = wl1251_reg_read32(wl, REG_EVENT_MAILBOX_PTR);
 197         wl->mbox_ptr[1] = wl->mbox_ptr[0] + sizeof(struct event_mailbox);
 198 
 199         wl1251_debug(DEBUG_EVENT, "MBOX ptrs: 0x%x 0x%x",
 200                      wl->mbox_ptr[0], wl->mbox_ptr[1]);
 201 }
 202 
 203 int wl1251_event_handle(struct wl1251 *wl, u8 mbox_num)
 204 {
 205         struct event_mailbox mbox;
 206         int ret;
 207 
 208         wl1251_debug(DEBUG_EVENT, "EVENT on mbox %d", mbox_num);
 209 
 210         if (mbox_num > 1)
 211                 return -EINVAL;
 212 
 213         /* first we read the mbox descriptor */
 214         wl1251_mem_read(wl, wl->mbox_ptr[mbox_num], &mbox,
 215                             sizeof(struct event_mailbox));
 216 
 217         /* process the descriptor */
 218         ret = wl1251_event_process(wl, &mbox);
 219         if (ret < 0)
 220                 return ret;
 221 
 222         /* then we let the firmware know it can go on...*/
 223         wl1251_reg_write32(wl, ACX_REG_INTERRUPT_TRIG, INTR_TRIG_EVENT_ACK);
 224 
 225         return 0;
 226 }

/* [<][>][^][v][top][bottom][index][help] */