Eliad Peller | c50a282 | 2012-11-22 18:06:19 +0200 | [diff] [blame] | 1 | /* |
| 2 | * This file is part of wl12xx |
| 3 | * |
| 4 | * Copyright (C) 2012 Texas Instruments. All rights reserved. |
| 5 | * |
| 6 | * This program is free software; you can redistribute it and/or |
| 7 | * modify it under the terms of the GNU General Public License |
| 8 | * version 2 as published by the Free Software Foundation. |
| 9 | * |
| 10 | * This program is distributed in the hope that it will be useful, but |
| 11 | * WITHOUT ANY WARRANTY; without even the implied warranty of |
| 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
| 13 | * General Public License for more details. |
| 14 | * |
| 15 | * You should have received a copy of the GNU General Public License |
| 16 | * along with this program; if not, write to the Free Software |
| 17 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA |
| 18 | * 02110-1301 USA |
| 19 | * |
| 20 | */ |
| 21 | |
Eliad Peller | e93e15f | 2014-07-11 03:01:33 +0300 | [diff] [blame] | 22 | #include <net/genetlink.h> |
Eliad Peller | c50a282 | 2012-11-22 18:06:19 +0200 | [diff] [blame] | 23 | #include "event.h" |
| 24 | #include "scan.h" |
| 25 | #include "../wlcore/cmd.h" |
| 26 | #include "../wlcore/debug.h" |
Eliad Peller | e93e15f | 2014-07-11 03:01:33 +0300 | [diff] [blame] | 27 | #include "../wlcore/vendor_cmd.h" |
Eliad Peller | c50a282 | 2012-11-22 18:06:19 +0200 | [diff] [blame] | 28 | |
| 29 | int wl18xx_wait_for_event(struct wl1271 *wl, enum wlcore_wait_event event, |
| 30 | bool *timeout) |
| 31 | { |
| 32 | u32 local_event; |
| 33 | |
| 34 | switch (event) { |
| 35 | case WLCORE_EVENT_PEER_REMOVE_COMPLETE: |
| 36 | local_event = PEER_REMOVE_COMPLETE_EVENT_ID; |
| 37 | break; |
| 38 | |
Victor Goldenshtein | 6b70e7e | 2012-11-25 18:26:59 +0200 | [diff] [blame] | 39 | case WLCORE_EVENT_DFS_CONFIG_COMPLETE: |
| 40 | local_event = DFS_CHANNELS_CONFIG_COMPLETE_EVENT; |
| 41 | break; |
| 42 | |
Eliad Peller | c50a282 | 2012-11-22 18:06:19 +0200 | [diff] [blame] | 43 | default: |
| 44 | /* event not implemented */ |
| 45 | return 0; |
| 46 | } |
| 47 | return wlcore_cmd_wait_for_event_or_timeout(wl, local_event, timeout); |
| 48 | } |
| 49 | |
Eliad Peller | 750e9d1 | 2014-12-29 08:24:07 +0200 | [diff] [blame] | 50 | static const char *wl18xx_radar_type_decode(u8 radar_type) |
| 51 | { |
| 52 | switch (radar_type) { |
| 53 | case RADAR_TYPE_REGULAR: |
| 54 | return "REGULAR"; |
| 55 | case RADAR_TYPE_CHIRP: |
| 56 | return "CHIRP"; |
| 57 | case RADAR_TYPE_NONE: |
| 58 | default: |
| 59 | return "N/A"; |
| 60 | } |
| 61 | } |
| 62 | |
Eliad Peller | e93e15f | 2014-07-11 03:01:33 +0300 | [diff] [blame] | 63 | static int wlcore_smart_config_sync_event(struct wl1271 *wl, u8 sync_channel, |
| 64 | u8 sync_band) |
| 65 | { |
| 66 | struct sk_buff *skb; |
Johannes Berg | 57fbcce | 2016-04-12 15:56:15 +0200 | [diff] [blame] | 67 | enum nl80211_band band; |
Eliad Peller | e93e15f | 2014-07-11 03:01:33 +0300 | [diff] [blame] | 68 | int freq; |
| 69 | |
| 70 | if (sync_band == WLCORE_BAND_5GHZ) |
Johannes Berg | 57fbcce | 2016-04-12 15:56:15 +0200 | [diff] [blame] | 71 | band = NL80211_BAND_5GHZ; |
Eliad Peller | e93e15f | 2014-07-11 03:01:33 +0300 | [diff] [blame] | 72 | else |
Johannes Berg | 57fbcce | 2016-04-12 15:56:15 +0200 | [diff] [blame] | 73 | band = NL80211_BAND_2GHZ; |
Eliad Peller | e93e15f | 2014-07-11 03:01:33 +0300 | [diff] [blame] | 74 | |
| 75 | freq = ieee80211_channel_to_frequency(sync_channel, band); |
| 76 | |
| 77 | wl1271_debug(DEBUG_EVENT, |
| 78 | "SMART_CONFIG_SYNC_EVENT_ID, freq: %d (chan: %d band %d)", |
| 79 | freq, sync_channel, sync_band); |
Ahmad Kholaif | 6c09e79 | 2015-02-26 15:26:53 +0200 | [diff] [blame] | 80 | skb = cfg80211_vendor_event_alloc(wl->hw->wiphy, NULL, 20, |
Eliad Peller | e93e15f | 2014-07-11 03:01:33 +0300 | [diff] [blame] | 81 | WLCORE_VENDOR_EVENT_SC_SYNC, |
| 82 | GFP_KERNEL); |
| 83 | |
| 84 | if (nla_put_u32(skb, WLCORE_VENDOR_ATTR_FREQ, freq)) { |
| 85 | kfree_skb(skb); |
| 86 | return -EMSGSIZE; |
| 87 | } |
| 88 | cfg80211_vendor_event(skb, GFP_KERNEL); |
| 89 | return 0; |
| 90 | } |
| 91 | |
| 92 | static int wlcore_smart_config_decode_event(struct wl1271 *wl, |
| 93 | u8 ssid_len, u8 *ssid, |
| 94 | u8 pwd_len, u8 *pwd) |
| 95 | { |
| 96 | struct sk_buff *skb; |
| 97 | |
| 98 | wl1271_debug(DEBUG_EVENT, "SMART_CONFIG_DECODE_EVENT_ID"); |
| 99 | wl1271_dump_ascii(DEBUG_EVENT, "SSID:", ssid, ssid_len); |
| 100 | |
Ahmad Kholaif | 6c09e79 | 2015-02-26 15:26:53 +0200 | [diff] [blame] | 101 | skb = cfg80211_vendor_event_alloc(wl->hw->wiphy, NULL, |
Eliad Peller | e93e15f | 2014-07-11 03:01:33 +0300 | [diff] [blame] | 102 | ssid_len + pwd_len + 20, |
| 103 | WLCORE_VENDOR_EVENT_SC_DECODE, |
| 104 | GFP_KERNEL); |
| 105 | |
| 106 | if (nla_put(skb, WLCORE_VENDOR_ATTR_SSID, ssid_len, ssid) || |
| 107 | nla_put(skb, WLCORE_VENDOR_ATTR_PSK, pwd_len, pwd)) { |
| 108 | kfree_skb(skb); |
| 109 | return -EMSGSIZE; |
| 110 | } |
| 111 | cfg80211_vendor_event(skb, GFP_KERNEL); |
| 112 | return 0; |
| 113 | } |
| 114 | |
Machani, Yaniv | 585dfe8 | 2016-06-27 16:37:14 +0300 | [diff] [blame^] | 115 | static void wlcore_event_time_sync(struct wl1271 *wl, |
| 116 | u16 tsf_high_msb, u16 tsf_high_lsb, |
| 117 | u16 tsf_low_msb, u16 tsf_low_lsb) |
Machani, Yaniv | 6d5c898 | 2015-07-30 22:38:19 +0300 | [diff] [blame] | 118 | { |
Machani, Yaniv | 585dfe8 | 2016-06-27 16:37:14 +0300 | [diff] [blame^] | 119 | u32 clock_low; |
| 120 | u32 clock_high; |
| 121 | |
| 122 | clock_high = (tsf_high_msb << 16) | tsf_high_lsb; |
| 123 | clock_low = (tsf_low_msb << 16) | tsf_low_lsb; |
| 124 | |
| 125 | wl1271_info("TIME_SYNC_EVENT_ID: clock_high %u, clock low %u", |
| 126 | clock_high, clock_low); |
Machani, Yaniv | 6d5c898 | 2015-07-30 22:38:19 +0300 | [diff] [blame] | 127 | } |
| 128 | |
Eliad Peller | c50a282 | 2012-11-22 18:06:19 +0200 | [diff] [blame] | 129 | int wl18xx_process_mailbox_events(struct wl1271 *wl) |
| 130 | { |
| 131 | struct wl18xx_event_mailbox *mbox = wl->mbox; |
| 132 | u32 vector; |
| 133 | |
| 134 | vector = le32_to_cpu(mbox->events_vector); |
| 135 | wl1271_debug(DEBUG_EVENT, "MBOX vector: 0x%x", vector); |
| 136 | |
| 137 | if (vector & SCAN_COMPLETE_EVENT_ID) { |
| 138 | wl1271_debug(DEBUG_EVENT, "scan results: %d", |
| 139 | mbox->number_of_scan_results); |
| 140 | |
| 141 | if (wl->scan_wlvif) |
| 142 | wl18xx_scan_completed(wl, wl->scan_wlvif); |
| 143 | } |
| 144 | |
Machani, Yaniv | 6d5c898 | 2015-07-30 22:38:19 +0300 | [diff] [blame] | 145 | if (vector & TIME_SYNC_EVENT_ID) |
| 146 | wlcore_event_time_sync(wl, |
Machani, Yaniv | 585dfe8 | 2016-06-27 16:37:14 +0300 | [diff] [blame^] | 147 | mbox->time_sync_tsf_high_msb, |
| 148 | mbox->time_sync_tsf_high_lsb, |
| 149 | mbox->time_sync_tsf_low_msb, |
| 150 | mbox->time_sync_tsf_low_lsb); |
Machani, Yaniv | 6d5c898 | 2015-07-30 22:38:19 +0300 | [diff] [blame] | 151 | |
Eliad Peller | 750e9d1 | 2014-12-29 08:24:07 +0200 | [diff] [blame] | 152 | if (vector & RADAR_DETECTED_EVENT_ID) { |
| 153 | wl1271_info("radar event: channel %d type %s", |
| 154 | mbox->radar_channel, |
| 155 | wl18xx_radar_type_decode(mbox->radar_type)); |
| 156 | |
Eliad Peller | 8cf77e1 | 2016-03-07 00:28:09 +0200 | [diff] [blame] | 157 | if (!wl->radar_debug_mode) |
| 158 | ieee80211_radar_detected(wl->hw); |
Eliad Peller | 750e9d1 | 2014-12-29 08:24:07 +0200 | [diff] [blame] | 159 | } |
| 160 | |
Eyal Shapira | 0b70078 | 2012-11-28 11:42:47 +0200 | [diff] [blame] | 161 | if (vector & PERIODIC_SCAN_REPORT_EVENT_ID) { |
| 162 | wl1271_debug(DEBUG_EVENT, |
| 163 | "PERIODIC_SCAN_REPORT_EVENT (results %d)", |
| 164 | mbox->number_of_sched_scan_results); |
| 165 | |
| 166 | wlcore_scan_sched_scan_results(wl); |
| 167 | } |
| 168 | |
Eliad Peller | c50a282 | 2012-11-22 18:06:19 +0200 | [diff] [blame] | 169 | if (vector & PERIODIC_SCAN_COMPLETE_EVENT_ID) |
| 170 | wlcore_event_sched_scan_completed(wl, 1); |
| 171 | |
| 172 | if (vector & RSSI_SNR_TRIGGER_0_EVENT_ID) |
| 173 | wlcore_event_rssi_trigger(wl, mbox->rssi_snr_trigger_metric); |
| 174 | |
| 175 | if (vector & BA_SESSION_RX_CONSTRAINT_EVENT_ID) |
| 176 | wlcore_event_ba_rx_constraint(wl, |
| 177 | le16_to_cpu(mbox->rx_ba_role_id_bitmap), |
| 178 | le16_to_cpu(mbox->rx_ba_allowed_bitmap)); |
| 179 | |
| 180 | if (vector & BSS_LOSS_EVENT_ID) |
| 181 | wlcore_event_beacon_loss(wl, |
| 182 | le16_to_cpu(mbox->bss_loss_bitmap)); |
| 183 | |
| 184 | if (vector & CHANNEL_SWITCH_COMPLETE_EVENT_ID) |
| 185 | wlcore_event_channel_switch(wl, |
| 186 | le16_to_cpu(mbox->channel_switch_role_id_bitmap), |
| 187 | true); |
| 188 | |
| 189 | if (vector & DUMMY_PACKET_EVENT_ID) |
| 190 | wlcore_event_dummy_packet(wl); |
| 191 | |
| 192 | /* |
| 193 | * "TX retries exceeded" has a different meaning according to mode. |
| 194 | * In AP mode the offending station is disconnected. |
| 195 | */ |
| 196 | if (vector & MAX_TX_FAILURE_EVENT_ID) |
| 197 | wlcore_event_max_tx_failure(wl, |
Machani, Yaniv | 585dfe8 | 2016-06-27 16:37:14 +0300 | [diff] [blame^] | 198 | le16_to_cpu(mbox->tx_retry_exceeded_bitmap)); |
Eliad Peller | c50a282 | 2012-11-22 18:06:19 +0200 | [diff] [blame] | 199 | |
| 200 | if (vector & INACTIVE_STA_EVENT_ID) |
| 201 | wlcore_event_inactive_sta(wl, |
Machani, Yaniv | 585dfe8 | 2016-06-27 16:37:14 +0300 | [diff] [blame^] | 202 | le16_to_cpu(mbox->inactive_sta_bitmap)); |
Eliad Peller | c50a282 | 2012-11-22 18:06:19 +0200 | [diff] [blame] | 203 | |
| 204 | if (vector & REMAIN_ON_CHANNEL_COMPLETE_EVENT_ID) |
| 205 | wlcore_event_roc_complete(wl); |
| 206 | |
Eliad Peller | e93e15f | 2014-07-11 03:01:33 +0300 | [diff] [blame] | 207 | if (vector & SMART_CONFIG_SYNC_EVENT_ID) |
| 208 | wlcore_smart_config_sync_event(wl, mbox->sc_sync_channel, |
| 209 | mbox->sc_sync_band); |
| 210 | |
| 211 | if (vector & SMART_CONFIG_DECODE_EVENT_ID) |
| 212 | wlcore_smart_config_decode_event(wl, |
| 213 | mbox->sc_ssid_len, |
| 214 | mbox->sc_ssid, |
| 215 | mbox->sc_pwd_len, |
| 216 | mbox->sc_pwd); |
Shahar Patury | 3719c17 | 2015-12-22 14:30:06 +0200 | [diff] [blame] | 217 | if (vector & FW_LOGGER_INDICATION) |
| 218 | wlcore_event_fw_logger(wl); |
Eliad Peller | e93e15f | 2014-07-11 03:01:33 +0300 | [diff] [blame] | 219 | |
Eliad Peller | c50a282 | 2012-11-22 18:06:19 +0200 | [diff] [blame] | 220 | return 0; |
| 221 | } |