OLD | NEW |
(Empty) | |
| 1 /* |
| 2 * |
| 3 * Copyright (c) 2004-2010 Atheros Communications Inc. |
| 4 * All rights reserved. |
| 5 * |
| 6 * |
| 7 // This program is free software; you can redistribute it and/or modify |
| 8 // it under the terms of the GNU General Public License version 2 as |
| 9 // published by the Free Software Foundation; |
| 10 // |
| 11 // Software distributed under the License is distributed on an "AS |
| 12 // IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or |
| 13 // implied. See the License for the specific language governing |
| 14 // rights and limitations under the License. |
| 15 // |
| 16 // |
| 17 * |
| 18 */ |
| 19 |
| 20 /* |
| 21 * This driver is a pseudo ethernet driver to access the Atheros AR6000 |
| 22 * WLAN Device |
| 23 */ |
| 24 #ifdef ANDROID_ENV |
| 25 /* ATHENV */ |
| 26 #include <linux/fs.h> |
| 27 /* ATHENV */ |
| 28 #endif |
| 29 |
| 30 #include "ar6000_drv.h" |
| 31 #ifdef CONFIG_CFG80211 |
| 32 #include "cfg80211.h" |
| 33 #endif /* CONFIG_CFG80211 */ |
| 34 #include "htc.h" |
| 35 #include "wmi_filter_linux.h" |
| 36 #include "epping_test.h" |
| 37 #include "wlan_config.h" |
| 38 #include "ar3kconfig.h" |
| 39 |
| 40 /* LINUX_HACK_FUDGE_FACTOR -- this is used to provide a workaround for linux beh
avior. When |
| 41 * the meta data was added to the header it was found that linux did not correc
tly provide |
| 42 * enough headroom. However when more headroom was requested beyond what was t
ruly needed |
| 43 * Linux gave the requested headroom. Therefore to get the necessary headroom f
rom Linux |
| 44 * the driver requests more than is needed by the amount = LINUX_HACK_FUDGE_FAC
TOR */ |
| 45 #define LINUX_HACK_FUDGE_FACTOR 16 |
| 46 |
| 47 A_UINT8 bcast_mac[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; |
| 48 A_UINT8 null_mac[] = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0}; |
| 49 |
| 50 #ifdef DEBUG |
| 51 |
| 52 #define ATH_DEBUG_DBG_LOG ATH_DEBUG_MAKE_MODULE_MASK(0) |
| 53 #define ATH_DEBUG_WLAN_CONNECT ATH_DEBUG_MAKE_MODULE_MASK(1) |
| 54 #define ATH_DEBUG_WLAN_SCAN ATH_DEBUG_MAKE_MODULE_MASK(2) |
| 55 #define ATH_DEBUG_WLAN_TX ATH_DEBUG_MAKE_MODULE_MASK(3) |
| 56 #define ATH_DEBUG_WLAN_RX ATH_DEBUG_MAKE_MODULE_MASK(4) |
| 57 #define ATH_DEBUG_HTC_RAW ATH_DEBUG_MAKE_MODULE_MASK(5) |
| 58 #define ATH_DEBUG_HCI_BRIDGE ATH_DEBUG_MAKE_MODULE_MASK(6) |
| 59 |
| 60 static ATH_DEBUG_MASK_DESCRIPTION driver_debug_desc[] = { |
| 61 { ATH_DEBUG_DBG_LOG , "Target Debug Logs"}, |
| 62 { ATH_DEBUG_WLAN_CONNECT , "WLAN connect"}, |
| 63 { ATH_DEBUG_WLAN_SCAN , "WLAN scan"}, |
| 64 { ATH_DEBUG_WLAN_TX , "WLAN Tx"}, |
| 65 { ATH_DEBUG_WLAN_RX , "WLAN Rx"}, |
| 66 { ATH_DEBUG_HTC_RAW , "HTC Raw IF tracing"}, |
| 67 { ATH_DEBUG_HCI_BRIDGE , "HCI Bridge Setup"}, |
| 68 { ATH_DEBUG_HCI_RECV , "HCI Recv tracing"}, |
| 69 { ATH_DEBUG_HCI_SEND , "HCI Send tracing"}, |
| 70 { ATH_DEBUG_HCI_DUMP , "HCI Packet dumps"}, |
| 71 }; |
| 72 |
| 73 ATH_DEBUG_INSTANTIATE_MODULE_VAR(driver, |
| 74 "driver", |
| 75 "Linux Driver Interface", |
| 76 ATH_DEBUG_MASK_DEFAULTS | ATH_DEBUG_WLAN_SCAN | |
| 77 ATH_DEBUG_HCI_BRIDGE, |
| 78 ATH_DEBUG_DESCRIPTION_COUNT(driver_debug_desc), |
| 79 driver_debug_desc); |
| 80 |
| 81 #endif |
| 82 |
| 83 |
| 84 #define IS_MAC_NULL(mac) (mac[0]==0 && mac[1]==0 && mac[2]==0 && mac[3]==0 && ma
c[4]==0 && mac[5]==0) |
| 85 #define IS_MAC_BCAST(mac) (*mac==0xff) |
| 86 |
| 87 MODULE_LICENSE("GPL and additional rights"); |
| 88 |
| 89 #ifndef REORG_APTC_HEURISTICS |
| 90 #undef ADAPTIVE_POWER_THROUGHPUT_CONTROL |
| 91 #endif /* REORG_APTC_HEURISTICS */ |
| 92 |
| 93 #ifdef ADAPTIVE_POWER_THROUGHPUT_CONTROL |
| 94 #define APTC_TRAFFIC_SAMPLING_INTERVAL 100 /* msec */ |
| 95 #define APTC_UPPER_THROUGHPUT_THRESHOLD 3000 /* Kbps */ |
| 96 #define APTC_LOWER_THROUGHPUT_THRESHOLD 2000 /* Kbps */ |
| 97 |
| 98 typedef struct aptc_traffic_record { |
| 99 A_BOOL timerScheduled; |
| 100 struct timeval samplingTS; |
| 101 unsigned long bytesReceived; |
| 102 unsigned long bytesTransmitted; |
| 103 } APTC_TRAFFIC_RECORD; |
| 104 |
| 105 A_TIMER aptcTimer; |
| 106 APTC_TRAFFIC_RECORD aptcTR; |
| 107 #endif /* ADAPTIVE_POWER_THROUGHPUT_CONTROL */ |
| 108 |
| 109 #ifdef EXPORT_HCI_BRIDGE_INTERFACE |
| 110 // callbacks registered by HCI transport driver |
| 111 HCI_TRANSPORT_CALLBACKS ar6kHciTransCallbacks = { NULL }; |
| 112 #endif |
| 113 |
| 114 unsigned int processDot11Hdr = 0; |
| 115 int bmienable = 1; |
| 116 |
| 117 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) |
| 118 char ifname[IFNAMSIZ] = {0,}; |
| 119 #endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) */ |
| 120 |
| 121 int wlaninitmode = WLAN_INIT_MODE_DRV; |
| 122 unsigned int bypasswmi = 0; |
| 123 unsigned int debuglevel = 0; |
| 124 int tspecCompliance = ATHEROS_COMPLIANCE; |
| 125 unsigned int busspeedlow = 0; |
| 126 unsigned int onebitmode = 0; |
| 127 unsigned int skipflash = 0; |
| 128 unsigned int wmitimeout = 2; |
| 129 unsigned int wlanNodeCaching = 1; |
| 130 unsigned int enableuartprint = 1; |
| 131 unsigned int logWmiRawMsgs = 0; |
| 132 unsigned int enabletimerwar = 0; |
| 133 unsigned int fwmode = 1; |
| 134 unsigned int mbox_yield_limit = 99; |
| 135 unsigned int enablerssicompensation = 0; |
| 136 int reduce_credit_dribble = 1 + HTC_CONNECT_FLAGS_THRESHOLD_LEVEL_ONE_HALF; |
| 137 int allow_trace_signal = 0; |
| 138 #ifdef CONFIG_HOST_TCMD_SUPPORT |
| 139 unsigned int testmode =0; |
| 140 #endif |
| 141 |
| 142 unsigned int irqprocmode = HIF_DEVICE_IRQ_ASYNC_SYNC; |
| 143 unsigned int nohifscattersupport = 0; |
| 144 unsigned int panic_on_assert = 1; |
| 145 |
| 146 unsigned int setuphci = 0; |
| 147 unsigned int loghci = 0; |
| 148 unsigned int setupbtdev = 0; |
| 149 #ifndef EXPORT_HCI_BRIDGE_INTERFACE |
| 150 unsigned int ar3khcibaud = 0; |
| 151 unsigned int hciuartscale = 0; |
| 152 unsigned int hciuartstep = 0; |
| 153 #endif |
| 154 #ifdef CONFIG_CHECKSUM_OFFLOAD |
| 155 unsigned int csumOffload=0; |
| 156 unsigned int csumOffloadTest=0; |
| 157 #endif |
| 158 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) |
| 159 module_param_string(ifname, ifname, sizeof(ifname), 0644); |
| 160 module_param(wlaninitmode, int, 0644); |
| 161 module_param(bmienable, int, 0644); |
| 162 module_param(bypasswmi, int, 0644); |
| 163 module_param(debuglevel, int, 0644); |
| 164 module_param(tspecCompliance, int, 0644); |
| 165 module_param(onebitmode, int, 0644); |
| 166 module_param(busspeedlow, int, 0644); |
| 167 module_param(skipflash, int, 0644); |
| 168 module_param(wmitimeout, int, 0644); |
| 169 module_param(wlanNodeCaching, int, 0644); |
| 170 module_param(logWmiRawMsgs, int, 0644); |
| 171 module_param(enableuartprint, int, 0644); |
| 172 module_param(enabletimerwar, int, 0644); |
| 173 module_param(fwmode, int, 0644); |
| 174 module_param(mbox_yield_limit, int, 0644); |
| 175 module_param(reduce_credit_dribble, int, 0644); |
| 176 module_param(allow_trace_signal, int, 0644); |
| 177 module_param(enablerssicompensation, int, 0644); |
| 178 module_param(processDot11Hdr, int, 0644); |
| 179 #ifdef CONFIG_CHECKSUM_OFFLOAD |
| 180 module_param(csumOffload, int, 0644); |
| 181 #endif |
| 182 #ifdef CONFIG_HOST_TCMD_SUPPORT |
| 183 module_param(testmode, int, 0644); |
| 184 #endif |
| 185 module_param(irqprocmode, int, 0644); |
| 186 module_param(nohifscattersupport, int, 0644); |
| 187 module_param(panic_on_assert, int, 0644); |
| 188 module_param(setuphci, int, 0644); |
| 189 module_param(loghci, int, 0644); |
| 190 module_param(setupbtdev, int, 0644); |
| 191 #ifndef EXPORT_HCI_BRIDGE_INTERFACE |
| 192 module_param(ar3khcibaud, int, 0644); |
| 193 module_param(hciuartscale, int, 0644); |
| 194 module_param(hciuartstep, int, 0644); |
| 195 #endif |
| 196 #else |
| 197 |
| 198 #define __user |
| 199 /* for linux 2.4 and lower */ |
| 200 MODULE_PARM(bmienable,"i"); |
| 201 MODULE_PARM(wlaninitmode,"i"); |
| 202 MODULE_PARM(bypasswmi,"i"); |
| 203 MODULE_PARM(debuglevel, "i"); |
| 204 MODULE_PARM(onebitmode,"i"); |
| 205 MODULE_PARM(busspeedlow, "i"); |
| 206 MODULE_PARM(skipflash, "i"); |
| 207 MODULE_PARM(wmitimeout, "i"); |
| 208 MODULE_PARM(wlanNodeCaching, "i"); |
| 209 MODULE_PARM(enableuartprint,"i"); |
| 210 MODULE_PARM(logWmiRawMsgs, "i"); |
| 211 MODULE_PARM(enabletimerwar,"i"); |
| 212 MODULE_PARM(fwmode,"i"); |
| 213 MODULE_PARM(mbox_yield_limit,"i"); |
| 214 MODULE_PARM(reduce_credit_dribble,"i"); |
| 215 MODULE_PARM(allow_trace_signal,"i"); |
| 216 MODULE_PARM(enablerssicompensation,"i"); |
| 217 MODULE_PARM(processDot11Hdr,"i"); |
| 218 #ifdef CONFIG_CHECKSUM_OFFLOAD |
| 219 MODULE_PARM(csumOffload,"i"); |
| 220 #endif |
| 221 #ifdef CONFIG_HOST_TCMD_SUPPORT |
| 222 MODULE_PARM(testmode, "i"); |
| 223 #endif |
| 224 MODULE_PARM(irqprocmode, "i"); |
| 225 MODULE_PARM(nohifscattersupport, "i"); |
| 226 MODULE_PARM(panic_on_assert, "i"); |
| 227 MODULE_PARM(setuphci, "i"); |
| 228 MODULE_PARM(loghci, "i"); |
| 229 #endif |
| 230 |
| 231 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,10) |
| 232 /* in 2.6.10 and later this is now a pointer to a uint */ |
| 233 unsigned int _mboxnum = HTC_MAILBOX_NUM_MAX; |
| 234 #define mboxnum &_mboxnum |
| 235 #else |
| 236 unsigned int mboxnum = HTC_MAILBOX_NUM_MAX; |
| 237 #endif |
| 238 |
| 239 #ifdef DEBUG |
| 240 A_UINT32 g_dbg_flags = DBG_DEFAULTS; |
| 241 unsigned int debugflags = 0; |
| 242 int debugdriver = 0; |
| 243 unsigned int debughtc = 0; |
| 244 unsigned int debugbmi = 0; |
| 245 unsigned int debughif = 0; |
| 246 unsigned int txcreditsavailable[HTC_MAILBOX_NUM_MAX] = {0}; |
| 247 unsigned int txcreditsconsumed[HTC_MAILBOX_NUM_MAX] = {0}; |
| 248 unsigned int txcreditintrenable[HTC_MAILBOX_NUM_MAX] = {0}; |
| 249 unsigned int txcreditintrenableaggregate[HTC_MAILBOX_NUM_MAX] = {0}; |
| 250 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) |
| 251 module_param(debugflags, int, 0644); |
| 252 module_param(debugdriver, int, 0644); |
| 253 module_param(debughtc, int, 0644); |
| 254 module_param(debugbmi, int, 0644); |
| 255 module_param(debughif, int, 0644); |
| 256 module_param_array(txcreditsavailable, int, mboxnum, 0644); |
| 257 module_param_array(txcreditsconsumed, int, mboxnum, 0644); |
| 258 module_param_array(txcreditintrenable, int, mboxnum, 0644); |
| 259 module_param_array(txcreditintrenableaggregate, int, mboxnum, 0644); |
| 260 #else |
| 261 /* linux 2.4 and lower */ |
| 262 MODULE_PARM(debugflags,"i"); |
| 263 MODULE_PARM(debugdriver, "i"); |
| 264 MODULE_PARM(debughtc, "i"); |
| 265 MODULE_PARM(debugbmi, "i"); |
| 266 MODULE_PARM(debughif, "i"); |
| 267 MODULE_PARM(txcreditsavailable, "0-3i"); |
| 268 MODULE_PARM(txcreditsconsumed, "0-3i"); |
| 269 MODULE_PARM(txcreditintrenable, "0-3i"); |
| 270 MODULE_PARM(txcreditintrenableaggregate, "0-3i"); |
| 271 #endif |
| 272 |
| 273 #endif /* DEBUG */ |
| 274 |
| 275 unsigned int resetok = 1; |
| 276 unsigned int tx_attempt[HTC_MAILBOX_NUM_MAX] = {0}; |
| 277 unsigned int tx_post[HTC_MAILBOX_NUM_MAX] = {0}; |
| 278 unsigned int tx_complete[HTC_MAILBOX_NUM_MAX] = {0}; |
| 279 unsigned int hifBusRequestNumMax = 40; |
| 280 unsigned int war23838_disabled = 0; |
| 281 #ifdef ADAPTIVE_POWER_THROUGHPUT_CONTROL |
| 282 unsigned int enableAPTCHeuristics = 1; |
| 283 #endif /* ADAPTIVE_POWER_THROUGHPUT_CONTROL */ |
| 284 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) |
| 285 module_param_array(tx_attempt, int, mboxnum, 0644); |
| 286 module_param_array(tx_post, int, mboxnum, 0644); |
| 287 module_param_array(tx_complete, int, mboxnum, 0644); |
| 288 module_param(hifBusRequestNumMax, int, 0644); |
| 289 module_param(war23838_disabled, int, 0644); |
| 290 module_param(resetok, int, 0644); |
| 291 #ifdef ADAPTIVE_POWER_THROUGHPUT_CONTROL |
| 292 module_param(enableAPTCHeuristics, int, 0644); |
| 293 #endif /* ADAPTIVE_POWER_THROUGHPUT_CONTROL */ |
| 294 #else |
| 295 MODULE_PARM(tx_attempt, "0-3i"); |
| 296 MODULE_PARM(tx_post, "0-3i"); |
| 297 MODULE_PARM(tx_complete, "0-3i"); |
| 298 MODULE_PARM(hifBusRequestNumMax, "i"); |
| 299 MODULE_PARM(war23838_disabled, "i"); |
| 300 MODULE_PARM(resetok, "i"); |
| 301 #ifdef ADAPTIVE_POWER_THROUGHPUT_CONTROL |
| 302 MODULE_PARM(enableAPTCHeuristics, "i"); |
| 303 #endif /* ADAPTIVE_POWER_THROUGHPUT_CONTROL */ |
| 304 #endif |
| 305 |
| 306 #ifdef BLOCK_TX_PATH_FLAG |
| 307 int blocktx = 0; |
| 308 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) |
| 309 module_param(blocktx, int, 0644); |
| 310 #else |
| 311 MODULE_PARM(blocktx, "i"); |
| 312 #endif |
| 313 #endif /* BLOCK_TX_PATH_FLAG */ |
| 314 |
| 315 typedef struct user_rssi_compensation_t { |
| 316 A_UINT16 a_enable; |
| 317 A_INT16 a_param_a; |
| 318 A_INT16 a_param_b; |
| 319 A_UINT16 bg_enable; |
| 320 A_INT16 bg_param_a; |
| 321 A_INT16 bg_param_b; |
| 322 } USER_RSSI_CPENSATION; |
| 323 |
| 324 static USER_RSSI_CPENSATION rssi_compensation_param; |
| 325 |
| 326 static A_INT16 rssi_compensation_table[96]; |
| 327 |
| 328 int reconnect_flag = 0; |
| 329 |
| 330 /* Function declarations */ |
| 331 static int ar6000_init_module(void); |
| 332 static void ar6000_cleanup_module(void); |
| 333 |
| 334 int ar6000_init(struct net_device *dev); |
| 335 static int ar6000_open(struct net_device *dev); |
| 336 static int ar6000_close(struct net_device *dev); |
| 337 static void ar6000_init_control_info(AR_SOFTC_T *ar); |
| 338 static int ar6000_data_tx(struct sk_buff *skb, struct net_device *dev); |
| 339 |
| 340 static void ar6000_destroy(struct net_device *dev, unsigned int unregister); |
| 341 static void ar6000_detect_error(unsigned long ptr); |
| 342 static struct net_device_stats *ar6000_get_stats(struct net_device *dev); |
| 343 static struct iw_statistics *ar6000_get_iwstats(struct net_device * dev); |
| 344 |
| 345 static void disconnect_timer_handler(unsigned long ptr); |
| 346 |
| 347 void read_rssi_compensation_param(AR_SOFTC_T *ar); |
| 348 |
| 349 /* |
| 350 * HTC service connection handlers |
| 351 */ |
| 352 static A_STATUS ar6000_avail_ev(void *context, void *hif_handle); |
| 353 |
| 354 static A_STATUS ar6000_unavail_ev(void *context, void *hif_handle); |
| 355 |
| 356 static void ar6000_target_failure(void *Instance, A_STATUS Status); |
| 357 |
| 358 static void ar6000_rx(void *Context, HTC_PACKET *pPacket); |
| 359 |
| 360 static void ar6000_rx_refill(void *Context,HTC_ENDPOINT_ID Endpoint); |
| 361 |
| 362 static void ar6000_tx_complete(void *Context, HTC_PACKET_QUEUE *pPackets); |
| 363 |
| 364 static HTC_SEND_FULL_ACTION ar6000_tx_queue_full(void *Context, HTC_PACKET *pPac
ket); |
| 365 |
| 366 #ifdef ATH_AR6K_11N_SUPPORT |
| 367 static void ar6000_alloc_netbufs(A_NETBUF_QUEUE_T *q, A_UINT16 num); |
| 368 #endif |
| 369 static void ar6000_deliver_frames_to_nw_stack(void * dev, void *osbuf); |
| 370 //static void ar6000_deliver_frames_to_bt_stack(void * dev, void *osbuf); |
| 371 |
| 372 static HTC_PACKET *ar6000_alloc_amsdu_rxbuf(void *Context, HTC_ENDPOINT_ID Endpo
int, int Length); |
| 373 |
| 374 static void ar6000_refill_amsdu_rxbufs(AR_SOFTC_T *ar, int Count); |
| 375 |
| 376 static void ar6000_cleanup_amsdu_rxbufs(AR_SOFTC_T *ar); |
| 377 |
| 378 static ssize_t |
| 379 ar6000_sysfs_bmi_read(struct kobject *kobj, struct bin_attribute *bin_attr, |
| 380 char *buf, loff_t pos, size_t count); |
| 381 |
| 382 static ssize_t |
| 383 ar6000_sysfs_bmi_write(struct kobject *kobj, struct bin_attribute *bin_attr, |
| 384 char *buf, loff_t pos, size_t count); |
| 385 |
| 386 static A_STATUS |
| 387 ar6000_sysfs_bmi_init(AR_SOFTC_T *ar); |
| 388 |
| 389 static void |
| 390 ar6000_sysfs_bmi_deinit(AR_SOFTC_T *ar); |
| 391 |
| 392 static A_STATUS |
| 393 ar6000_sysfs_bmi_get_config(AR_SOFTC_T *ar, A_UINT32 mode); |
| 394 |
| 395 /* |
| 396 * Static variables |
| 397 */ |
| 398 |
| 399 static struct net_device *ar6000_devices[MAX_AR6000]; |
| 400 extern struct iw_handler_def ath_iw_handler_def; |
| 401 DECLARE_WAIT_QUEUE_HEAD(arEvent); |
| 402 static void ar6000_cookie_init(AR_SOFTC_T *ar); |
| 403 static void ar6000_cookie_cleanup(AR_SOFTC_T *ar); |
| 404 static void ar6000_free_cookie(AR_SOFTC_T *ar, struct ar_cookie * cookie); |
| 405 static struct ar_cookie *ar6000_alloc_cookie(AR_SOFTC_T *ar); |
| 406 |
| 407 #ifdef USER_KEYS |
| 408 static A_STATUS ar6000_reinstall_keys(AR_SOFTC_T *ar,A_UINT8 key_op_ctrl); |
| 409 #endif |
| 410 |
| 411 |
| 412 static struct ar_cookie s_ar_cookie_mem[MAX_COOKIE_NUM]; |
| 413 |
| 414 #define HOST_INTEREST_ITEM_ADDRESS(ar, item) \ |
| 415 (((ar)->arTargetType == TARGET_TYPE_AR6001) ? AR6001_HOST_INTEREST_ITEM_
ADDRESS(item) : \ |
| 416 (((ar)->arTargetType == TARGET_TYPE_AR6002) ? AR6002_HOST_INTEREST_ITEM_
ADDRESS(item) : \ |
| 417 (((ar)->arTargetType == TARGET_TYPE_AR6003) ? AR6003_HOST_INTEREST_ITEM_
ADDRESS(item) : 0))) |
| 418 |
| 419 |
| 420 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,29) |
| 421 static struct net_device_ops ar6000_netdev_ops = { |
| 422 .ndo_init = NULL, |
| 423 .ndo_open = ar6000_open, |
| 424 .ndo_stop = ar6000_close, |
| 425 .ndo_get_stats = ar6000_get_stats, |
| 426 .ndo_do_ioctl = ar6000_ioctl, |
| 427 .ndo_start_xmit = ar6000_data_tx, |
| 428 }; |
| 429 #endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,29) */ |
| 430 |
| 431 /* Debug log support */ |
| 432 |
| 433 /* |
| 434 * Flag to govern whether the debug logs should be parsed in the kernel |
| 435 * or reported to the application. |
| 436 */ |
| 437 #define REPORT_DEBUG_LOGS_TO_APP |
| 438 |
| 439 A_STATUS |
| 440 ar6000_set_host_app_area(AR_SOFTC_T *ar) |
| 441 { |
| 442 A_UINT32 address, data; |
| 443 struct host_app_area_s host_app_area; |
| 444 |
| 445 /* Fetch the address of the host_app_area_s instance in the host interest ar
ea */ |
| 446 address = TARG_VTOP(ar->arTargetType, HOST_INTEREST_ITEM_ADDRESS(ar, hi_app_
host_interest)); |
| 447 if (ar6000_ReadRegDiag(ar->arHifDevice, &address, &data) != A_OK) { |
| 448 return A_ERROR; |
| 449 } |
| 450 address = TARG_VTOP(ar->arTargetType, data); |
| 451 host_app_area.wmi_protocol_ver = WMI_PROTOCOL_VERSION; |
| 452 if (ar6000_WriteDataDiag(ar->arHifDevice, address, |
| 453 (A_UCHAR *)&host_app_area, |
| 454 sizeof(struct host_app_area_s)) != A_OK) |
| 455 { |
| 456 return A_ERROR; |
| 457 } |
| 458 |
| 459 return A_OK; |
| 460 } |
| 461 |
| 462 A_UINT32 |
| 463 dbglog_get_debug_hdr_ptr(AR_SOFTC_T *ar) |
| 464 { |
| 465 A_UINT32 param; |
| 466 A_UINT32 address; |
| 467 A_STATUS status; |
| 468 |
| 469 address = TARG_VTOP(ar->arTargetType, HOST_INTEREST_ITEM_ADDRESS(ar, hi_dbgl
og_hdr)); |
| 470 if ((status = ar6000_ReadDataDiag(ar->arHifDevice, address, |
| 471 (A_UCHAR *)¶m, 4)) != A_OK) |
| 472 { |
| 473 param = 0; |
| 474 } |
| 475 |
| 476 return param; |
| 477 } |
| 478 |
| 479 /* |
| 480 * The dbglog module has been initialized. Its ok to access the relevant |
| 481 * data stuctures over the diagnostic window. |
| 482 */ |
| 483 void |
| 484 ar6000_dbglog_init_done(AR_SOFTC_T *ar) |
| 485 { |
| 486 ar->dbglog_init_done = TRUE; |
| 487 } |
| 488 |
| 489 A_UINT32 |
| 490 dbglog_get_debug_fragment(A_INT8 *datap, A_UINT32 len, A_UINT32 limit) |
| 491 { |
| 492 A_INT32 *buffer; |
| 493 A_UINT32 count; |
| 494 A_UINT32 numargs; |
| 495 A_UINT32 length; |
| 496 A_UINT32 fraglen; |
| 497 |
| 498 count = fraglen = 0; |
| 499 buffer = (A_INT32 *)datap; |
| 500 length = (limit >> 2); |
| 501 |
| 502 if (len <= limit) { |
| 503 fraglen = len; |
| 504 } else { |
| 505 while (count < length) { |
| 506 numargs = DBGLOG_GET_NUMARGS(buffer[count]); |
| 507 fraglen = (count << 2); |
| 508 count += numargs + 1; |
| 509 } |
| 510 } |
| 511 |
| 512 return fraglen; |
| 513 } |
| 514 |
| 515 void |
| 516 dbglog_parse_debug_logs(A_INT8 *datap, A_UINT32 len) |
| 517 { |
| 518 A_INT32 *buffer; |
| 519 A_UINT32 count; |
| 520 A_UINT32 timestamp; |
| 521 A_UINT32 debugid; |
| 522 A_UINT32 moduleid; |
| 523 A_UINT32 numargs; |
| 524 A_UINT32 length; |
| 525 |
| 526 count = 0; |
| 527 buffer = (A_INT32 *)datap; |
| 528 length = (len >> 2); |
| 529 while (count < length) { |
| 530 debugid = DBGLOG_GET_DBGID(buffer[count]); |
| 531 moduleid = DBGLOG_GET_MODULEID(buffer[count]); |
| 532 numargs = DBGLOG_GET_NUMARGS(buffer[count]); |
| 533 timestamp = DBGLOG_GET_TIMESTAMP(buffer[count]); |
| 534 switch (numargs) { |
| 535 case 0: |
| 536 AR_DEBUG_PRINTF(ATH_DEBUG_DBG_LOG,("%d %d (%d)\n", moduleid, debugid
, timestamp)); |
| 537 break; |
| 538 |
| 539 case 1: |
| 540 AR_DEBUG_PRINTF(ATH_DEBUG_DBG_LOG,("%d %d (%d): 0x%x\n", moduleid, d
ebugid, |
| 541 timestamp, buffer[count+1])); |
| 542 break; |
| 543 |
| 544 case 2: |
| 545 AR_DEBUG_PRINTF(ATH_DEBUG_DBG_LOG,("%d %d (%d): 0x%x, 0x%x\n", modul
eid, debugid, |
| 546 timestamp, buffer[count+1], buffer[count+2])); |
| 547 break; |
| 548 |
| 549 default: |
| 550 AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Invalid args: %d\n", numargs)); |
| 551 } |
| 552 count += numargs + 1; |
| 553 } |
| 554 } |
| 555 |
| 556 int |
| 557 ar6000_dbglog_get_debug_logs(AR_SOFTC_T *ar) |
| 558 { |
| 559 struct dbglog_hdr_s debug_hdr; |
| 560 struct dbglog_buf_s debug_buf; |
| 561 A_UINT32 address; |
| 562 A_UINT32 length; |
| 563 A_UINT32 dropped; |
| 564 A_UINT32 firstbuf; |
| 565 A_UINT32 debug_hdr_ptr; |
| 566 |
| 567 if (!ar->dbglog_init_done) return A_ERROR; |
| 568 |
| 569 |
| 570 AR6000_SPIN_LOCK(&ar->arLock, 0); |
| 571 |
| 572 if (ar->dbgLogFetchInProgress) { |
| 573 AR6000_SPIN_UNLOCK(&ar->arLock, 0); |
| 574 return A_EBUSY; |
| 575 } |
| 576 |
| 577 /* block out others */ |
| 578 ar->dbgLogFetchInProgress = TRUE; |
| 579 |
| 580 AR6000_SPIN_UNLOCK(&ar->arLock, 0); |
| 581 |
| 582 debug_hdr_ptr = dbglog_get_debug_hdr_ptr(ar); |
| 583 printk("debug_hdr_ptr: 0x%x\n", debug_hdr_ptr); |
| 584 |
| 585 /* Get the contents of the ring buffer */ |
| 586 if (debug_hdr_ptr) { |
| 587 address = TARG_VTOP(ar->arTargetType, debug_hdr_ptr); |
| 588 length = sizeof(struct dbglog_hdr_s); |
| 589 ar6000_ReadDataDiag(ar->arHifDevice, address, |
| 590 (A_UCHAR *)&debug_hdr, length); |
| 591 address = TARG_VTOP(ar->arTargetType, (A_UINT32)debug_hdr.dbuf); |
| 592 firstbuf = address; |
| 593 dropped = debug_hdr.dropped; |
| 594 length = sizeof(struct dbglog_buf_s); |
| 595 ar6000_ReadDataDiag(ar->arHifDevice, address, |
| 596 (A_UCHAR *)&debug_buf, length); |
| 597 |
| 598 do { |
| 599 address = TARG_VTOP(ar->arTargetType, (A_UINT32)debug_buf.buffer); |
| 600 length = debug_buf.length; |
| 601 if ((length) && (debug_buf.length <= debug_buf.bufsize)) { |
| 602 /* Rewind the index if it is about to overrun the buffer */ |
| 603 if (ar->log_cnt > (DBGLOG_HOST_LOG_BUFFER_SIZE - length)) { |
| 604 ar->log_cnt = 0; |
| 605 } |
| 606 if(A_OK != ar6000_ReadDataDiag(ar->arHifDevice, address, |
| 607 (A_UCHAR *)&ar->log_buffer[ar->log_cnt], len
gth)) |
| 608 { |
| 609 break; |
| 610 } |
| 611 ar6000_dbglog_event(ar, dropped, &ar->log_buffer[ar->log_cnt], l
ength); |
| 612 ar->log_cnt += length; |
| 613 } else { |
| 614 AR_DEBUG_PRINTF(ATH_DEBUG_DBG_LOG,("Length: %d (Total size: %d)\
n", |
| 615 debug_buf.length, debug_buf.bufsize)); |
| 616 } |
| 617 |
| 618 address = TARG_VTOP(ar->arTargetType, (A_UINT32)debug_buf.next); |
| 619 length = sizeof(struct dbglog_buf_s); |
| 620 if(A_OK != ar6000_ReadDataDiag(ar->arHifDevice, address, |
| 621 (A_UCHAR *)&debug_buf, length)) |
| 622 { |
| 623 break; |
| 624 } |
| 625 |
| 626 } while (address != firstbuf); |
| 627 } |
| 628 |
| 629 ar->dbgLogFetchInProgress = FALSE; |
| 630 |
| 631 return A_OK; |
| 632 } |
| 633 |
| 634 void |
| 635 ar6000_dbglog_event(AR_SOFTC_T *ar, A_UINT32 dropped, |
| 636 A_INT8 *buffer, A_UINT32 length) |
| 637 { |
| 638 #ifdef REPORT_DEBUG_LOGS_TO_APP |
| 639 #define MAX_WIRELESS_EVENT_SIZE 252 |
| 640 /* |
| 641 * Break it up into chunks of MAX_WIRELESS_EVENT_SIZE bytes of messages. |
| 642 * There seems to be a limitation on the length of message that could be |
| 643 * transmitted to the user app via this mechanism. |
| 644 */ |
| 645 A_UINT32 send, sent; |
| 646 |
| 647 sent = 0; |
| 648 send = dbglog_get_debug_fragment(&buffer[sent], length - sent, |
| 649 MAX_WIRELESS_EVENT_SIZE); |
| 650 while (send) { |
| 651 ar6000_send_event_to_app(ar, WMIX_DBGLOG_EVENTID, &buffer[sent], send); |
| 652 sent += send; |
| 653 send = dbglog_get_debug_fragment(&buffer[sent], length - sent, |
| 654 MAX_WIRELESS_EVENT_SIZE); |
| 655 } |
| 656 #else |
| 657 AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Dropped logs: 0x%x\nDebug info length: %d\n"
, |
| 658 dropped, length)); |
| 659 |
| 660 /* Interpret the debug logs */ |
| 661 dbglog_parse_debug_logs(buffer, length); |
| 662 #endif /* REPORT_DEBUG_LOGS_TO_APP */ |
| 663 } |
| 664 |
| 665 |
| 666 static int __init |
| 667 ar6000_init_module(void) |
| 668 { |
| 669 static int probed = 0; |
| 670 A_STATUS status; |
| 671 OSDRV_CALLBACKS osdrvCallbacks; |
| 672 |
| 673 a_module_debug_support_init(); |
| 674 |
| 675 #ifdef DEBUG |
| 676 /* check for debug mask overrides */ |
| 677 if (debughtc != 0) { |
| 678 ATH_DEBUG_SET_DEBUG_MASK(htc,debughtc); |
| 679 } |
| 680 if (debugbmi != 0) { |
| 681 ATH_DEBUG_SET_DEBUG_MASK(bmi,debugbmi); |
| 682 } |
| 683 if (debughif != 0) { |
| 684 ATH_DEBUG_SET_DEBUG_MASK(hif,debughif); |
| 685 } |
| 686 if (debugdriver != 0) { |
| 687 ATH_DEBUG_SET_DEBUG_MASK(driver,debugdriver); |
| 688 } |
| 689 |
| 690 #endif |
| 691 |
| 692 A_REGISTER_MODULE_DEBUG_INFO(driver); |
| 693 |
| 694 A_MEMZERO(&osdrvCallbacks,sizeof(osdrvCallbacks)); |
| 695 osdrvCallbacks.deviceInsertedHandler = ar6000_avail_ev; |
| 696 osdrvCallbacks.deviceRemovedHandler = ar6000_unavail_ev; |
| 697 |
| 698 #ifdef DEBUG |
| 699 /* Set the debug flags if specified at load time */ |
| 700 if(debugflags != 0) |
| 701 { |
| 702 g_dbg_flags = debugflags; |
| 703 } |
| 704 #endif |
| 705 |
| 706 if (probed) { |
| 707 return -ENODEV; |
| 708 } |
| 709 probed++; |
| 710 |
| 711 #ifdef ADAPTIVE_POWER_THROUGHPUT_CONTROL |
| 712 memset(&aptcTR, 0, sizeof(APTC_TRAFFIC_RECORD)); |
| 713 #endif /* ADAPTIVE_POWER_THROUGHPUT_CONTROL */ |
| 714 |
| 715 #ifdef CONFIG_HOST_GPIO_SUPPORT |
| 716 ar6000_gpio_init(); |
| 717 #endif /* CONFIG_HOST_GPIO_SUPPORT */ |
| 718 |
| 719 status = HIFInit(&osdrvCallbacks); |
| 720 if(status != A_OK) |
| 721 return -ENODEV; |
| 722 |
| 723 return 0; |
| 724 } |
| 725 |
| 726 static void __exit |
| 727 ar6000_cleanup_module(void) |
| 728 { |
| 729 int i = 0; |
| 730 struct net_device *ar6000_netdev; |
| 731 |
| 732 #ifdef ADAPTIVE_POWER_THROUGHPUT_CONTROL |
| 733 /* Delete the Adaptive Power Control timer */ |
| 734 if (timer_pending(&aptcTimer)) { |
| 735 del_timer_sync(&aptcTimer); |
| 736 } |
| 737 #endif /* ADAPTIVE_POWER_THROUGHPUT_CONTROL */ |
| 738 |
| 739 for (i=0; i < MAX_AR6000; i++) { |
| 740 if (ar6000_devices[i] != NULL) { |
| 741 ar6000_netdev = ar6000_devices[i]; |
| 742 ar6000_devices[i] = NULL; |
| 743 ar6000_destroy(ar6000_netdev, 1); |
| 744 } |
| 745 } |
| 746 |
| 747 HIFShutDownDevice(NULL); |
| 748 |
| 749 a_module_debug_support_cleanup(); |
| 750 |
| 751 AR_DEBUG_PRINTF(ATH_DEBUG_INFO,("ar6000_cleanup: success\n")); |
| 752 } |
| 753 |
| 754 #ifdef ADAPTIVE_POWER_THROUGHPUT_CONTROL |
| 755 void |
| 756 aptcTimerHandler(unsigned long arg) |
| 757 { |
| 758 A_UINT32 numbytes; |
| 759 A_UINT32 throughput; |
| 760 AR_SOFTC_T *ar; |
| 761 A_STATUS status; |
| 762 |
| 763 ar = (AR_SOFTC_T *)arg; |
| 764 A_ASSERT(ar != NULL); |
| 765 A_ASSERT(!timer_pending(&aptcTimer)); |
| 766 |
| 767 AR6000_SPIN_LOCK(&ar->arLock, 0); |
| 768 |
| 769 /* Get the number of bytes transferred */ |
| 770 numbytes = aptcTR.bytesTransmitted + aptcTR.bytesReceived; |
| 771 aptcTR.bytesTransmitted = aptcTR.bytesReceived = 0; |
| 772 |
| 773 /* Calculate and decide based on throughput thresholds */ |
| 774 throughput = ((numbytes * 8)/APTC_TRAFFIC_SAMPLING_INTERVAL); /* Kbps */ |
| 775 if (throughput < APTC_LOWER_THROUGHPUT_THRESHOLD) { |
| 776 /* Enable Sleep and delete the timer */ |
| 777 A_ASSERT(ar->arWmiReady == TRUE); |
| 778 AR6000_SPIN_UNLOCK(&ar->arLock, 0); |
| 779 status = wmi_powermode_cmd(ar->arWmi, REC_POWER); |
| 780 AR6000_SPIN_LOCK(&ar->arLock, 0); |
| 781 A_ASSERT(status == A_OK); |
| 782 aptcTR.timerScheduled = FALSE; |
| 783 } else { |
| 784 A_TIMEOUT_MS(&aptcTimer, APTC_TRAFFIC_SAMPLING_INTERVAL, 0); |
| 785 } |
| 786 |
| 787 AR6000_SPIN_UNLOCK(&ar->arLock, 0); |
| 788 } |
| 789 #endif /* ADAPTIVE_POWER_THROUGHPUT_CONTROL */ |
| 790 |
| 791 /* ATHENV */ |
| 792 #ifdef ANDROID_ENV |
| 793 extern void eeprom_ar6000_transfer(HIF_DEVICE *device, char *fake_file); |
| 794 #endif |
| 795 /* ATHENV */ |
| 796 |
| 797 /* ATHENV */ |
| 798 #ifdef ANDROID_ENV |
| 799 |
| 800 #define MAX_BUF (8*1024) |
| 801 #define A_ROUND_UP(x, y) ((((x)+((y)-1))/(y))*(y)) |
| 802 |
| 803 char * fw_buf; |
| 804 static void firmware_transfer(HIF_DEVICE *device, char* filename, A_UINT32 addre
ss, A_BOOL isCompressed) |
| 805 { |
| 806 struct file *filp; |
| 807 struct inode *inode = NULL; |
| 808 int length, remaining; |
| 809 int length1; |
| 810 A_STATUS ret; |
| 811 mm_segment_t oldfs; |
| 812 |
| 813 |
| 814 printk("%s: Enter, filename=%s\n", __FUNCTION__, filename); |
| 815 |
| 816 // Open file |
| 817 oldfs = get_fs(); |
| 818 set_fs(KERNEL_DS); |
| 819 |
| 820 filp = filp_open(filename, O_RDONLY, S_IRUSR); |
| 821 if ( IS_ERR(filp) ) { |
| 822 printk("%s: file %s filp_open error\n", __FUNCTION__, filename); |
| 823 return; |
| 824 } |
| 825 if (!filp->f_op) { |
| 826 printk("%s: File Operation Method Error\n", __FUNCTION__); |
| 827 return; |
| 828 } |
| 829 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20) |
| 830 inode = filp->f_path.dentry->d_inode; |
| 831 #else |
| 832 inode = filp->f_dentry->d_inode; |
| 833 #endif |
| 834 |
| 835 if (!inode) { |
| 836 printk("%s: Get inode from filp failed\n", __FUNCTION__); |
| 837 filp_close(filp, NULL); |
| 838 return; |
| 839 } |
| 840 |
| 841 printk("%s file offset opsition: %xh\n", __FUNCTION__, (unsigned)filp->f_pos
); |
| 842 |
| 843 fw_buf = (char*)kmalloc((MAX_BUF+12), GFP_KERNEL); |
| 844 if (fw_buf==NULL) { |
| 845 printk("%s: kernel memory alloc error\n", __FUNCTION__); |
| 846 filp_close(filp, NULL); |
| 847 return; |
| 848 } |
| 849 |
| 850 length = i_size_read(inode->i_mapping->host); |
| 851 if (length==0 ) { |
| 852 printk("%s: Try to get file size error\n", __FUNCTION__); |
| 853 goto Transfer_DONE; |
| 854 } |
| 855 printk("%s: length=%d, address=0x%x\n", __FUNCTION__, length, address); |
| 856 |
| 857 if ( isCompressed) { |
| 858 ret = BMILZStreamStart(device, address); |
| 859 if (ret != A_OK) { |
| 860 printk("%s: BMILZStreamStart failed, ret=%d\n", __FUNCTION__, ret); |
| 861 goto Transfer_DONE; |
| 862 } |
| 863 } |
| 864 |
| 865 remaining = length; |
| 866 |
| 867 while (remaining>0) { |
| 868 length = (remaining > MAX_BUF)? MAX_BUF : remaining; |
| 869 |
| 870 if ( isCompressed ) { |
| 871 ((A_UINT32 *)fw_buf)[((length-1)/4)] = 0; |
| 872 } |
| 873 |
| 874 if (filp->f_op->read(filp, fw_buf, length, &filp->f_pos) != length) { |
| 875 printk("%s: file read error, remaining=%d\n", __FUNCTION__, remaining); |
| 876 goto Transfer_DONE; |
| 877 } |
| 878 |
| 879 length1 = A_ROUND_UP(length, 4); |
| 880 |
| 881 if ( isCompressed ) { |
| 882 printk("%s: BMILZData: len=%d, org_len=%d\n", __FUNCTION__, length1,
length); |
| 883 ret = BMILZData(device, fw_buf, length1); |
| 884 if (ret != A_OK) { |
| 885 printk("%s: BMILZData failed, ret=%d\n", __FUNCTION__, ret); |
| 886 goto Transfer_DONE; |
| 887 } |
| 888 } else { |
| 889 ret = BMIWriteMemory(device, address, fw_buf, length1); |
| 890 if (ret != A_OK) { |
| 891 printk("%s: BMIWriteMemory failed, ret=%d\n", __FUNCTION__, ret); |
| 892 goto Transfer_DONE; |
| 893 } |
| 894 } |
| 895 |
| 896 remaining -= length; |
| 897 address += length; |
| 898 } |
| 899 |
| 900 Transfer_DONE: |
| 901 kfree(fw_buf); |
| 902 filp_close(filp, NULL); |
| 903 set_fs(oldfs); |
| 904 } |
| 905 |
| 906 #endif |
| 907 /* ATHENV */ |
| 908 |
| 909 #ifdef ATH_AR6K_11N_SUPPORT |
| 910 static void |
| 911 ar6000_alloc_netbufs(A_NETBUF_QUEUE_T *q, A_UINT16 num) |
| 912 { |
| 913 void * osbuf; |
| 914 |
| 915 while(num) { |
| 916 if((osbuf = A_NETBUF_ALLOC(AR6000_BUFFER_SIZE))) { |
| 917 A_NETBUF_ENQUEUE(q, osbuf); |
| 918 } else { |
| 919 break; |
| 920 } |
| 921 num--; |
| 922 } |
| 923 |
| 924 if(num) { |
| 925 A_PRINTF("%s(), allocation of netbuf failed", __func__); |
| 926 } |
| 927 } |
| 928 #endif |
| 929 |
| 930 static struct bin_attribute bmi_attr = { |
| 931 .attr = {.name = "bmi", .mode = 0600}, |
| 932 .read = ar6000_sysfs_bmi_read, |
| 933 .write = ar6000_sysfs_bmi_write, |
| 934 }; |
| 935 |
| 936 static ssize_t |
| 937 ar6000_sysfs_bmi_read(struct kobject *kobj, struct bin_attribute *bin_attr, |
| 938 char *buf, loff_t pos, size_t count) |
| 939 { |
| 940 int index; |
| 941 AR_SOFTC_T *ar; |
| 942 HIF_DEVICE_OS_DEVICE_INFO *osDevInfo; |
| 943 |
| 944 AR_DEBUG_PRINTF(ATH_DEBUG_INFO,("BMI: Read %d bytes\n", count)); |
| 945 for (index=0; index < MAX_AR6000; index++) { |
| 946 ar = (AR_SOFTC_T *)ar6k_priv(ar6000_devices[index]); |
| 947 osDevInfo = &ar->osDevInfo; |
| 948 if (kobj == (&(((struct device *)osDevInfo->pOSDevice)->kobj))) { |
| 949 break; |
| 950 } |
| 951 } |
| 952 |
| 953 if (index == MAX_AR6000) return 0; |
| 954 |
| 955 if ((BMIRawRead(ar->arHifDevice, buf, count, TRUE)) != A_OK) { |
| 956 return 0; |
| 957 } |
| 958 |
| 959 return count; |
| 960 } |
| 961 |
| 962 static ssize_t |
| 963 ar6000_sysfs_bmi_write(struct kobject *kobj, struct bin_attribute *bin_attr, |
| 964 char *buf, loff_t pos, size_t count) |
| 965 { |
| 966 int index; |
| 967 AR_SOFTC_T *ar; |
| 968 HIF_DEVICE_OS_DEVICE_INFO *osDevInfo; |
| 969 |
| 970 AR_DEBUG_PRINTF(ATH_DEBUG_INFO,("BMI: Write %d bytes\n", count)); |
| 971 for (index=0; index < MAX_AR6000; index++) { |
| 972 ar = (AR_SOFTC_T *)ar6k_priv(ar6000_devices[index]); |
| 973 osDevInfo = &ar->osDevInfo; |
| 974 if (kobj == (&(((struct device *)osDevInfo->pOSDevice)->kobj))) { |
| 975 break; |
| 976 } |
| 977 } |
| 978 |
| 979 if (index == MAX_AR6000) return 0; |
| 980 |
| 981 if ((BMIRawWrite(ar->arHifDevice, buf, count)) != A_OK) { |
| 982 return 0; |
| 983 } |
| 984 |
| 985 return count; |
| 986 } |
| 987 |
| 988 static A_STATUS |
| 989 ar6000_sysfs_bmi_init(AR_SOFTC_T *ar) |
| 990 { |
| 991 A_STATUS status; |
| 992 |
| 993 AR_DEBUG_PRINTF(ATH_DEBUG_INFO,("BMI: Creating sysfs entry\n")); |
| 994 A_MEMZERO(&ar->osDevInfo, sizeof(HIF_DEVICE_OS_DEVICE_INFO)); |
| 995 |
| 996 /* Get the underlying OS device */ |
| 997 status = HIFConfigureDevice(ar->arHifDevice, |
| 998 HIF_DEVICE_GET_OS_DEVICE, |
| 999 &ar->osDevInfo, |
| 1000 sizeof(HIF_DEVICE_OS_DEVICE_INFO)); |
| 1001 |
| 1002 if (A_FAILED(status)) { |
| 1003 AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("BMI: Failed to get OS device info from
HIF\n")); |
| 1004 return A_ERROR; |
| 1005 } |
| 1006 |
| 1007 /* Create a bmi entry in the sysfs filesystem */ |
| 1008 if ((sysfs_create_bin_file(&(((struct device *)ar->osDevInfo.pOSDevice)->kob
j), &bmi_attr)) < 0) |
| 1009 { |
| 1010 AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("BMI: Failed to create entry for bmi in s
ysfs filesystem\n")); |
| 1011 return A_ERROR; |
| 1012 } |
| 1013 |
| 1014 return A_OK; |
| 1015 } |
| 1016 |
| 1017 static void |
| 1018 ar6000_sysfs_bmi_deinit(AR_SOFTC_T *ar) |
| 1019 { |
| 1020 AR_DEBUG_PRINTF(ATH_DEBUG_INFO,("BMI: Deleting sysfs entry\n")); |
| 1021 |
| 1022 sysfs_remove_bin_file(&(((struct device *)ar->osDevInfo.pOSDevice)->kobj), &
bmi_attr); |
| 1023 } |
| 1024 |
| 1025 #define bmifn(fn) do { \ |
| 1026 if ((fn) < A_OK) { \ |
| 1027 AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("BMI operation failed: %d\n", __LINE__))
; \ |
| 1028 return A_ERROR; \ |
| 1029 } \ |
| 1030 } while(0) |
| 1031 |
| 1032 static A_STATUS |
| 1033 ar6000_sysfs_bmi_get_config(AR_SOFTC_T *ar, A_UINT32 mode) |
| 1034 { |
| 1035 const struct firmware *fw_entry; |
| 1036 |
| 1037 AR_DEBUG_PRINTF(ATH_DEBUG_INFO,("BMI: Requesting User Space Config\n")); |
| 1038 |
| 1039 if (mode == WLAN_INIT_MODE_UDEV) { |
| 1040 /* Get config using udev through a script in user space */ |
| 1041 if ((request_firmware(&fw_entry, AR6003_HW10_CONFIG, ((struct device *)a
r->osDevInfo.pOSDevice))) != 0) |
| 1042 { |
| 1043 AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("BMI: Failure to get %s\n", AR6003_H
W10_CONFIG)); |
| 1044 return A_ERROR; |
| 1045 } |
| 1046 |
| 1047 release_firmware(fw_entry); |
| 1048 #ifdef INIT_MODE_DRV_ENABLED |
| 1049 } else { |
| 1050 /* The config is compiled into the driver itself */ |
| 1051 A_UINT32 param, options, sleep, address; |
| 1052 |
| 1053 /* Temporarily disable system sleep */ |
| 1054 address = MBOX_BASE_ADDRESS + LOCAL_SCRATCH_ADDRESS; |
| 1055 bmifn(BMIReadSOCRegister(ar->arHifDevice, address, ¶m)); |
| 1056 options = param; |
| 1057 param |= AR6K_OPTION_SLEEP_DISABLE; |
| 1058 bmifn(BMIWriteSOCRegister(ar->arHifDevice, address, param)); |
| 1059 |
| 1060 address = RTC_BASE_ADDRESS + SYSTEM_SLEEP_ADDRESS; |
| 1061 bmifn(BMIReadSOCRegister(ar->arHifDevice, address, ¶m)); |
| 1062 sleep = param; |
| 1063 param |= WLAN_SYSTEM_SLEEP_DISABLE_SET(1); |
| 1064 bmifn(BMIWriteSOCRegister(ar->arHifDevice, address, param)); |
| 1065 AR_DEBUG_PRINTF(ATH_DEBUG_INFO, ("old options: %d, old sleep: %d\n", opt
ions, sleep)); |
| 1066 |
| 1067 /* Run at 80/88MHz by default */ |
| 1068 address = RTC_BASE_ADDRESS + CPU_CLOCK_ADDRESS; |
| 1069 param = CPU_CLOCK_STANDARD_SET(1); |
| 1070 bmifn(BMIWriteSOCRegister(ar->arHifDevice, address, param)); |
| 1071 |
| 1072 /* LPO_CAL.ENABLE = 1 */ |
| 1073 address = RTC_BASE_ADDRESS + LPO_CAL_ADDRESS; |
| 1074 param = LPO_CAL_ENABLE_SET(1); |
| 1075 bmifn(BMIWriteSOCRegister(ar->arHifDevice, address, param)); |
| 1076 |
| 1077 /* Transfer Board Data from Target EEPROM to Target RAM */ |
| 1078 /* Determine where in Target RAM to write Board Data */ |
| 1079 bmifn(BMIReadMemory(ar->arHifDevice, HOST_INTEREST_ITEM_ADDRESS(ar, hi_b
oard_data), (A_UCHAR *)¶m, 4)); |
| 1080 AR_DEBUG_PRINTF(ATH_DEBUG_INFO, ("Board Data download address: 0x%x\n",
param)); |
| 1081 |
| 1082 /* Write EEPROM data to Target RAM */ |
| 1083 if ((request_firmware(&fw_entry, AR6K_BOARD_DATA_FILE, ((struct device *
)ar->osDevInfo.pOSDevice))) != 0) |
| 1084 { |
| 1085 AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("BMI: Failure to get %s\n", AR6K_BOA
RD_DATA_FILE)); |
| 1086 return A_ERROR; |
| 1087 } |
| 1088 |
| 1089 if ((BMIWriteMemory(ar->arHifDevice, param, (A_UCHAR *)fw_entry->data, f
w_entry->size)) < A_OK) |
| 1090 { |
| 1091 AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("BMI operation failed: %d\n", __LINE
__)); \ |
| 1092 release_firmware(fw_entry); |
| 1093 return A_ERROR; |
| 1094 } |
| 1095 release_firmware(fw_entry); |
| 1096 |
| 1097 /* Record the fact that Board Data IS initialized */ |
| 1098 param = 1; |
| 1099 bmifn(BMIWriteMemory(ar->arHifDevice, HOST_INTEREST_ITEM_ADDRESS(ar, hi_
board_data_initialized), (A_UCHAR *)¶m, 4)); |
| 1100 |
| 1101 /* Transfer One time Programmable data */ |
| 1102 /* Data segment */ |
| 1103 if ((request_firmware(&fw_entry, AR6K_OTP_DATA_FILE, ((struct device *)a
r->osDevInfo.pOSDevice))) != 0) |
| 1104 { |
| 1105 AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("BMI: Failure to get %s\n", AR6K_OTP
_DATA_FILE)); |
| 1106 return A_ERROR; |
| 1107 } |
| 1108 param = DATA_DOWNLOAD_ADDRESS; |
| 1109 if ((BMIWriteMemory(ar->arHifDevice, param, (A_UCHAR *)fw_entry->data, f
w_entry->size)) < A_OK) |
| 1110 { |
| 1111 AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("BMI operation failed: %d\n", __LINE
__)); \ |
| 1112 release_firmware(fw_entry); |
| 1113 return A_ERROR; |
| 1114 } |
| 1115 release_firmware(fw_entry); |
| 1116 |
| 1117 /* Code segment */ |
| 1118 if ((request_firmware(&fw_entry, AR6K_OTP_BIN_FILE, ((struct device *)ar
->osDevInfo.pOSDevice))) != 0) |
| 1119 { |
| 1120 AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("BMI: Failure to get %s\n", AR6K_OTP
_BIN_FILE)); |
| 1121 return A_ERROR; |
| 1122 } |
| 1123 param = ((AR6003_REV1_APP_START_OVERRIDE & 0x7FFFFF) | 0x400000); |
| 1124 if ((BMIWriteMemory(ar->arHifDevice, param, (A_UCHAR *)fw_entry->data, f
w_entry->size)) < A_OK) |
| 1125 { |
| 1126 AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("BMI operation failed: %d\n", __LINE
__)); \ |
| 1127 release_firmware(fw_entry); |
| 1128 return A_ERROR; |
| 1129 } |
| 1130 release_firmware(fw_entry); |
| 1131 |
| 1132 /* Execute the OTP code */ |
| 1133 param = 0; |
| 1134 bmifn(BMIExecute(ar->arHifDevice, AR6003_REV1_APP_START_OVERRIDE, ¶m
)); |
| 1135 |
| 1136 /* Download Target firmware */ |
| 1137 if ((request_firmware(&fw_entry, AR6K_FIRMWARE_FILE, ((struct device *)a
r->osDevInfo.pOSDevice))) != 0) |
| 1138 { |
| 1139 AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("BMI: Failure to get %s\n", AR6K_FIR
MWARE_FILE)); |
| 1140 return A_ERROR; |
| 1141 } |
| 1142 param = DATA_DOWNLOAD_ADDRESS; |
| 1143 if ((BMIFastDownload(ar->arHifDevice, param, (A_UCHAR *)fw_entry->data,
fw_entry->size)) < A_OK) |
| 1144 { |
| 1145 AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("BMI operation failed: %d\n", __LINE
__)); \ |
| 1146 release_firmware(fw_entry); |
| 1147 return A_ERROR; |
| 1148 } |
| 1149 release_firmware(fw_entry); |
| 1150 |
| 1151 /* Set starting address for firmware */ |
| 1152 bmifn(BMISetAppStart(ar->arHifDevice, AR6003_REV1_APP_START_OVERRIDE)); |
| 1153 |
| 1154 /* Reserve 5.5K of RAM */ |
| 1155 param = 5632; |
| 1156 bmifn(BMIWriteMemory(ar->arHifDevice, HOST_INTEREST_ITEM_ADDRESS(ar, hi_
end_RAM_reserve_sz), (A_UCHAR *)¶m, 4)); |
| 1157 |
| 1158 /* Apply the patches */ |
| 1159 if ((request_firmware(&fw_entry, AR6K_PATCH_FILE, ((struct device *)ar->
osDevInfo.pOSDevice))) != 0) |
| 1160 { |
| 1161 AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("BMI: Failure to get %s\n", AR6K_PAT
CH_FILE)); |
| 1162 return A_ERROR; |
| 1163 } |
| 1164 param = PATCH_DOWNLOAD_ADDRESS; |
| 1165 if ((BMIWriteMemory(ar->arHifDevice, param, (A_UCHAR *)fw_entry->data, f
w_entry->size)) < A_OK) |
| 1166 { |
| 1167 AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("BMI operation failed: %d\n", __LINE
__)); \ |
| 1168 release_firmware(fw_entry); |
| 1169 return A_ERROR; |
| 1170 } |
| 1171 release_firmware(fw_entry); |
| 1172 bmifn(BMIWriteMemory(ar->arHifDevice, HOST_INTEREST_ITEM_ADDRESS(ar, hi_
dset_list_head), (A_UCHAR *)¶m, 4)); |
| 1173 |
| 1174 /* Restore system sleep */ |
| 1175 address = RTC_BASE_ADDRESS + SYSTEM_SLEEP_ADDRESS; |
| 1176 bmifn(BMIWriteSOCRegister(ar->arHifDevice, address, sleep)); |
| 1177 |
| 1178 address = MBOX_BASE_ADDRESS + LOCAL_SCRATCH_ADDRESS; |
| 1179 bmifn(BMIWriteSOCRegister(ar->arHifDevice, address, options)); |
| 1180 |
| 1181 /* Configure GPIO AR6003 UART */ |
| 1182 param = 8; |
| 1183 bmifn(BMIWriteMemory(ar->arHifDevice, HOST_INTEREST_ITEM_ADDRESS(ar, hi_
dbg_uart_txpin), (A_UCHAR *)¶m, 4)); |
| 1184 |
| 1185 /* Tell Target to execute loaded firmware */ |
| 1186 bmifn(BMIDone(ar->arHifDevice)); |
| 1187 #endif /* INIT_MODE_DRV_ENABLED */ |
| 1188 } |
| 1189 |
| 1190 return A_OK; |
| 1191 } |
| 1192 |
| 1193 /* |
| 1194 * HTC Event handlers |
| 1195 */ |
| 1196 static A_STATUS |
| 1197 ar6000_avail_ev(void *context, void *hif_handle) |
| 1198 { |
| 1199 int i; |
| 1200 struct net_device *dev; |
| 1201 void *ar_netif; |
| 1202 AR_SOFTC_T *ar; |
| 1203 int device_index = 0; |
| 1204 A_UINT32 param; |
| 1205 HTC_INIT_INFO htcInfo; |
| 1206 #ifdef CONFIG_CFG80211 |
| 1207 struct wireless_dev *wdev; |
| 1208 #endif /* CONFIG_CFG80211 */ |
| 1209 |
| 1210 AR_DEBUG_PRINTF(ATH_DEBUG_INFO,("ar6000_available\n")); |
| 1211 |
| 1212 for (i=0; i < MAX_AR6000; i++) { |
| 1213 if (ar6000_devices[i] == NULL) { |
| 1214 break; |
| 1215 } |
| 1216 } |
| 1217 |
| 1218 if (i == MAX_AR6000) { |
| 1219 AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("ar6000_available: max devices reached\n"
)); |
| 1220 return A_ERROR; |
| 1221 } |
| 1222 |
| 1223 /* Save this. It gives a bit better readability especially since */ |
| 1224 /* we use another local "i" variable below. */ |
| 1225 device_index = i; |
| 1226 |
| 1227 #ifdef CONFIG_CFG80211 |
| 1228 wdev = ar6k_cfg80211_init(NULL); |
| 1229 if (IS_ERR(wdev)) { |
| 1230 AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("%s: ar6k_cfg80211_init failed\n", __fun
c__)); |
| 1231 return A_ERROR; |
| 1232 } |
| 1233 ar_netif = wdev_priv(wdev); |
| 1234 #else |
| 1235 dev = alloc_etherdev(sizeof(AR_SOFTC_T)); |
| 1236 if (dev == NULL) { |
| 1237 AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("ar6000_available: can't alloc etherdev\n
")); |
| 1238 return A_ERROR; |
| 1239 } |
| 1240 ether_setup(dev); |
| 1241 ar_netif = ar6k_priv(dev); |
| 1242 #endif /* CONFIG_CFG80211 */ |
| 1243 |
| 1244 if (ar_netif == NULL) { |
| 1245 AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("%s: Can't allocate ar6k priv memory\n",
__func__)); |
| 1246 return A_ERROR; |
| 1247 } |
| 1248 |
| 1249 A_MEMZERO(ar_netif, sizeof(AR_SOFTC_T)); |
| 1250 ar = (AR_SOFTC_T *)ar_netif; |
| 1251 |
| 1252 #ifdef CONFIG_CFG80211 |
| 1253 ar->wdev = wdev; |
| 1254 wdev->iftype = NL80211_IFTYPE_STATION; |
| 1255 |
| 1256 dev = alloc_netdev_mq(0, "wlan%d", ether_setup, 5);//IWM_TX_QUEUES); |
| 1257 if (!dev) { |
| 1258 printk(KERN_CRIT "AR6K: no memory for network device instance\n"); |
| 1259 ar6k_cfg80211_deinit(ar); |
| 1260 return A_ERROR; |
| 1261 } |
| 1262 |
| 1263 dev->ieee80211_ptr = wdev; |
| 1264 SET_NETDEV_DEV(dev, wiphy_dev(wdev->wiphy)); |
| 1265 wdev->netdev = dev; |
| 1266 ar->arNetworkType = INFRA_NETWORK; |
| 1267 #endif /* CONFIG_CFG80211 */ |
| 1268 |
| 1269 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) |
| 1270 if (ifname[0]) |
| 1271 { |
| 1272 strcpy(dev->name, ifname); |
| 1273 } |
| 1274 #endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) */ |
| 1275 |
| 1276 #ifdef SET_MODULE_OWNER |
| 1277 SET_MODULE_OWNER(dev); |
| 1278 #endif |
| 1279 |
| 1280 ar->arNetDev = dev; |
| 1281 ar->arHifDevice = hif_handle; |
| 1282 ar->arWlanState = WLAN_ENABLED; |
| 1283 ar->arDeviceIndex = device_index; |
| 1284 |
| 1285 A_INIT_TIMER(&ar->arHBChallengeResp.timer, ar6000_detect_error, dev); |
| 1286 ar->arHBChallengeResp.seqNum = 0; |
| 1287 ar->arHBChallengeResp.outstanding = FALSE; |
| 1288 ar->arHBChallengeResp.missCnt = 0; |
| 1289 ar->arHBChallengeResp.frequency = AR6000_HB_CHALLENGE_RESP_FREQ_DEFAULT; |
| 1290 ar->arHBChallengeResp.missThres = AR6000_HB_CHALLENGE_RESP_MISS_THRES_DEFAUL
T; |
| 1291 |
| 1292 ar6000_init_control_info(ar); |
| 1293 init_waitqueue_head(&arEvent); |
| 1294 sema_init(&ar->arSem, 1); |
| 1295 ar->bIsDestroyProgress = FALSE; |
| 1296 |
| 1297 INIT_HTC_PACKET_QUEUE(&ar->amsdu_rx_buffer_queue); |
| 1298 |
| 1299 #ifdef ADAPTIVE_POWER_THROUGHPUT_CONTROL |
| 1300 A_INIT_TIMER(&aptcTimer, aptcTimerHandler, ar); |
| 1301 #endif /* ADAPTIVE_POWER_THROUGHPUT_CONTROL */ |
| 1302 |
| 1303 A_INIT_TIMER(&ar->disconnect_timer, disconnect_timer_handler, dev); |
| 1304 |
| 1305 /* |
| 1306 * If requested, perform some magic which requires no cooperation from |
| 1307 * the Target. It causes the Target to ignore flash and execute to the |
| 1308 * OS from ROM. |
| 1309 * |
| 1310 * This is intended to support recovery from a corrupted flash on Targets |
| 1311 * that support flash. |
| 1312 */ |
| 1313 if (skipflash) |
| 1314 { |
| 1315 //ar6000_reset_device_skipflash(ar->arHifDevice); |
| 1316 } |
| 1317 |
| 1318 BMIInit(); |
| 1319 |
| 1320 if (bmienable) { |
| 1321 ar6000_sysfs_bmi_init(ar); |
| 1322 } |
| 1323 |
| 1324 { |
| 1325 struct bmi_target_info targ_info; |
| 1326 |
| 1327 if (BMIGetTargetInfo(ar->arHifDevice, &targ_info) != A_OK) { |
| 1328 return A_ERROR; |
| 1329 } |
| 1330 |
| 1331 ar->arVersion.target_ver = targ_info.target_ver; |
| 1332 ar->arTargetType = targ_info.target_type; |
| 1333 |
| 1334 /* do any target-specific preparation that can be done through BMI *
/ |
| 1335 if (ar6000_prepare_target(ar->arHifDevice, |
| 1336 targ_info.target_type, |
| 1337 targ_info.target_ver) != A_OK) { |
| 1338 return A_ERROR; |
| 1339 } |
| 1340 |
| 1341 } |
| 1342 |
| 1343 if (enableuartprint) { |
| 1344 param = 1; |
| 1345 if (BMIWriteMemory(ar->arHifDevice, |
| 1346 HOST_INTEREST_ITEM_ADDRESS(ar, hi_serial_enable), |
| 1347 (A_UCHAR *)¶m, |
| 1348 4)!= A_OK) |
| 1349 { |
| 1350 AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("BMIWriteMemory for enableuartprint
failed \n")); |
| 1351 return A_ERROR; |
| 1352 } |
| 1353 AR_DEBUG_PRINTF(ATH_DEBUG_INFO,("Serial console prints enabled\n")); |
| 1354 } |
| 1355 |
| 1356 /* Tell target which HTC version it is used*/ |
| 1357 param = HTC_PROTOCOL_VERSION; |
| 1358 if (BMIWriteMemory(ar->arHifDevice, |
| 1359 HOST_INTEREST_ITEM_ADDRESS(ar, hi_app_host_interest), |
| 1360 (A_UCHAR *)¶m, |
| 1361 4)!= A_OK) |
| 1362 { |
| 1363 AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("BMIWriteMemory for htc version failed \
n")); |
| 1364 return A_ERROR; |
| 1365 } |
| 1366 |
| 1367 #ifdef CONFIG_HOST_TCMD_SUPPORT |
| 1368 if(testmode) { |
| 1369 ar->arTargetMode = AR6000_TCMD_MODE; |
| 1370 }else { |
| 1371 ar->arTargetMode = AR6000_WLAN_MODE; |
| 1372 } |
| 1373 #endif |
| 1374 if (enabletimerwar) { |
| 1375 A_UINT32 param; |
| 1376 |
| 1377 if (BMIReadMemory(ar->arHifDevice, |
| 1378 HOST_INTEREST_ITEM_ADDRESS(ar, hi_option_flag), |
| 1379 (A_UCHAR *)¶m, |
| 1380 4)!= A_OK) |
| 1381 { |
| 1382 AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("BMIReadMemory for enabletimerwar fai
led \n")); |
| 1383 return A_ERROR; |
| 1384 } |
| 1385 |
| 1386 param |= HI_OPTION_TIMER_WAR; |
| 1387 |
| 1388 if (BMIWriteMemory(ar->arHifDevice, |
| 1389 HOST_INTEREST_ITEM_ADDRESS(ar, hi_option_flag), |
| 1390 (A_UCHAR *)¶m, |
| 1391 4) != A_OK) |
| 1392 { |
| 1393 AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("BMIWriteMemory for enabletimerwar fa
iled \n")); |
| 1394 return A_ERROR; |
| 1395 } |
| 1396 AR_DEBUG_PRINTF(ATH_DEBUG_INFO,("Timer WAR enabled\n")); |
| 1397 } |
| 1398 |
| 1399 /* set the firmware mode to STA/IBSS/AP */ |
| 1400 { |
| 1401 A_UINT32 param; |
| 1402 |
| 1403 if (BMIReadMemory(ar->arHifDevice, |
| 1404 HOST_INTEREST_ITEM_ADDRESS(ar, hi_option_flag), |
| 1405 (A_UCHAR *)¶m, |
| 1406 4)!= A_OK) |
| 1407 { |
| 1408 AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("BMIReadMemory for setting fwmode fai
led \n")); |
| 1409 return A_ERROR; |
| 1410 } |
| 1411 |
| 1412 param |= (fwmode << HI_OPTION_FW_MODE_SHIFT); |
| 1413 |
| 1414 if (BMIWriteMemory(ar->arHifDevice, |
| 1415 HOST_INTEREST_ITEM_ADDRESS(ar, hi_option_flag), |
| 1416 (A_UCHAR *)¶m, |
| 1417 4) != A_OK) |
| 1418 { |
| 1419 AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("BMIWriteMemory for setting fwmode fa
iled \n")); |
| 1420 return A_ERROR; |
| 1421 } |
| 1422 AR_DEBUG_PRINTF(ATH_DEBUG_INFO,("Firmware mode set\n")); |
| 1423 } |
| 1424 #if 0 /* HOST_INTEREST is no longer used to configure dot11 processing rule */ |
| 1425 if (processDot11Hdr) { |
| 1426 A_UINT32 param; |
| 1427 |
| 1428 if (BMIReadMemory(ar->arHifDevice, |
| 1429 HOST_INTEREST_ITEM_ADDRESS(ar, hi_option_flag), |
| 1430 (A_UCHAR *)¶m, |
| 1431 4)!= A_OK) |
| 1432 { |
| 1433 AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("BMIReadMemory for processDot11Hdr fa
iled \n")); |
| 1434 return A_ERROR; |
| 1435 } |
| 1436 |
| 1437 param |= HI_OPTION_RELAY_DOT11_HDR; |
| 1438 |
| 1439 if (BMIWriteMemory(ar->arHifDevice, |
| 1440 HOST_INTEREST_ITEM_ADDRESS(ar, hi_option_flag), |
| 1441 (A_UCHAR *)¶m, |
| 1442 4) != A_OK) |
| 1443 { |
| 1444 AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("BMIWriteMemory for processDot11Hdr f
ailed \n")); |
| 1445 return A_ERROR; |
| 1446 } |
| 1447 AR_DEBUG_PRINTF(ATH_DEBUG_INFO,("processDot11Hdr enabled\n")); |
| 1448 } |
| 1449 #endif |
| 1450 |
| 1451 // No need to reserve RAM space for patch as AR6001 is flash based |
| 1452 if (ar->arTargetType == TARGET_TYPE_AR6001) { |
| 1453 param = 0; |
| 1454 if (BMIWriteMemory(ar->arHifDevice, |
| 1455 HOST_INTEREST_ITEM_ADDRESS(ar, hi_end_RAM_reserve_sz), |
| 1456 (A_UCHAR *)¶m, |
| 1457 4) != A_OK) |
| 1458 { |
| 1459 AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("BMIWriteMemory for hi_end_RAM_reserv
e_sz failed \n")); |
| 1460 return A_ERROR; |
| 1461 } |
| 1462 } |
| 1463 |
| 1464 |
| 1465 /* since BMIInit is called in the driver layer, we have to set the block |
| 1466 * size here for the target */ |
| 1467 |
| 1468 if (A_FAILED(ar6000_set_htc_params(ar->arHifDevice, |
| 1469 ar->arTargetType, |
| 1470 mbox_yield_limit, |
| 1471 0 /* use default number of control buffer
s */ |
| 1472 ))) { |
| 1473 return A_ERROR; |
| 1474 } |
| 1475 |
| 1476 if (setupbtdev != 0) { |
| 1477 if (A_FAILED(ar6000_set_hci_bridge_flags(ar->arHifDevice, |
| 1478 ar->arTargetType, |
| 1479 setupbtdev))) { |
| 1480 return A_ERROR; |
| 1481 } |
| 1482 } |
| 1483 |
| 1484 A_MEMZERO(&htcInfo,sizeof(htcInfo)); |
| 1485 htcInfo.pContext = ar; |
| 1486 htcInfo.TargetFailure = ar6000_target_failure; |
| 1487 |
| 1488 ar->arHtcTarget = HTCCreate(ar->arHifDevice,&htcInfo); |
| 1489 |
| 1490 if (ar->arHtcTarget == NULL) { |
| 1491 return A_ERROR; |
| 1492 } |
| 1493 |
| 1494 spin_lock_init(&ar->arLock); |
| 1495 |
| 1496 #ifdef WAPI_ENABLE |
| 1497 ar->arWapiEnable = 0; |
| 1498 #endif |
| 1499 |
| 1500 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,29) |
| 1501 dev->open = &ar6000_open; |
| 1502 dev->stop = &ar6000_close; |
| 1503 dev->hard_start_xmit = &ar6000_data_tx; |
| 1504 dev->get_stats = &ar6000_get_stats; |
| 1505 |
| 1506 /* dev->tx_timeout = ar6000_tx_timeout; */ |
| 1507 dev->do_ioctl = &ar6000_ioctl; |
| 1508 #else |
| 1509 dev->netdev_ops = &ar6000_netdev_ops; |
| 1510 #endif /* LINUX_VERSION_CODE < KERNEL_VERSION(2,6,29) */ |
| 1511 dev->watchdog_timeo = AR6000_TX_TIMEOUT; |
| 1512 dev->wireless_handlers = &ath_iw_handler_def; |
| 1513 |
| 1514 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19) |
| 1515 dev->get_wireless_stats = ar6000_get_iwstats; /*Displayed via proc fs */ |
| 1516 #else |
| 1517 ath_iw_handler_def.get_wireless_stats = ar6000_get_iwstats; /*Displayed via
proc fs */ |
| 1518 #endif |
| 1519 #ifdef CONFIG_CHECKSUM_OFFLOAD |
| 1520 if(csumOffload){ |
| 1521 |
| 1522 dev->features |= NETIF_F_IP_CSUM;/*advertise kernel capability |
| 1523 to do TCP/UDP CSUM offload for IPV4
*/ |
| 1524 ar->rxMetaVersion=WMI_META_VERSION_2;/*if external frame work is also ne
eded, change and use an extended rxMetaVerion*/ |
| 1525 } |
| 1526 #endif |
| 1527 if (processDot11Hdr) { |
| 1528 dev->hard_header_len = sizeof(struct ieee80211_qosframe) + sizeof(ATH_LL
C_SNAP_HDR) + sizeof(WMI_DATA_HDR) + HTC_HEADER_LEN + WMI_MAX_TX_META_SZ + LINUX
_HACK_FUDGE_FACTOR; |
| 1529 } else { |
| 1530 /* |
| 1531 * We need the OS to provide us with more headroom in order to |
| 1532 * perform dix to 802.3, WMI header encap, and the HTC header |
| 1533 */ |
| 1534 dev->hard_header_len = ETH_HLEN + sizeof(ATH_LLC_SNAP_HDR) + |
| 1535 sizeof(WMI_DATA_HDR) + HTC_HEADER_LEN + WMI_MAX_TX_META_SZ + LINUX_H
ACK_FUDGE_FACTOR; |
| 1536 } |
| 1537 |
| 1538 #ifdef ATH_AR6K_11N_SUPPORT |
| 1539 if((ar->aggr_cntxt = aggr_init(ar6000_alloc_netbufs)) == NULL) { |
| 1540 AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("%s() Failed to initialize aggr.\n",
__func__)); |
| 1541 return A_ERROR; |
| 1542 } |
| 1543 |
| 1544 aggr_register_rx_dispatcher(ar->aggr_cntxt, (void *)dev, ar6000_deliver_fram
es_to_nw_stack); |
| 1545 #endif |
| 1546 |
| 1547 HIFClaimDevice(ar->arHifDevice, ar); |
| 1548 |
| 1549 /* We only register the device in the global list if we succeed. */ |
| 1550 /* If the device is in the global list, it will be destroyed */ |
| 1551 /* when the module is unloaded. */ |
| 1552 ar6000_devices[device_index] = dev; |
| 1553 |
| 1554 /* Don't install the init function if BMI is requested */ |
| 1555 if (!bmienable) { |
| 1556 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,29) |
| 1557 dev->init = ar6000_init; |
| 1558 #else |
| 1559 ar6000_netdev_ops.ndo_init = ar6000_init; |
| 1560 #endif /* LINUX_VERSION_CODE < KERNEL_VERSION(2,6,29) */ |
| 1561 } else { |
| 1562 AR_DEBUG_PRINTF(ATH_DEBUG_INFO, ("BMI enabled: %d\n", wlaninitmode)); |
| 1563 if ((wlaninitmode == WLAN_INIT_MODE_UDEV) || |
| 1564 (wlaninitmode == WLAN_INIT_MODE_DRV)) |
| 1565 { |
| 1566 A_STATUS status = A_OK; |
| 1567 do { |
| 1568 if ((status = ar6000_sysfs_bmi_get_config(ar, wlaninitmode)) !=
A_OK) |
| 1569 { |
| 1570 AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("ar6000_avail: ar6000_sysfs_b
mi_get_config failed\n")); |
| 1571 break; |
| 1572 } |
| 1573 |
| 1574 if ((ar6000_init(dev)) < A_OK) { |
| 1575 AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("ar6000_avail: ar6000_init\n"
)); |
| 1576 status = A_ERROR; |
| 1577 } |
| 1578 } while (FALSE); |
| 1579 |
| 1580 if (status != A_OK) { |
| 1581 /* Clean up TODO */ |
| 1582 return status; |
| 1583 } |
| 1584 } |
| 1585 } |
| 1586 |
| 1587 /* This runs the init function if registered */ |
| 1588 if (register_netdev(dev)) { |
| 1589 AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("ar6000_avail: register_netdev failed\n")
); |
| 1590 ar6000_destroy(dev, 0); |
| 1591 return A_ERROR; |
| 1592 } |
| 1593 |
| 1594 AR_DEBUG_PRINTF(ATH_DEBUG_INFO,("ar6000_avail: name=%s hifdevice=0x%x, dev=0
x%x (%d), ar=0x%x\n", |
| 1595 dev->name, (A_UINT32)ar->arHifDevice, (A_UINT32)dev, device_
index, |
| 1596 (A_UINT32)ar)); |
| 1597 |
| 1598 return A_OK; |
| 1599 } |
| 1600 |
| 1601 static void ar6000_target_failure(void *Instance, A_STATUS Status) |
| 1602 { |
| 1603 AR_SOFTC_T *ar = (AR_SOFTC_T *)Instance; |
| 1604 WMI_TARGET_ERROR_REPORT_EVENT errEvent; |
| 1605 static A_BOOL sip = FALSE; |
| 1606 |
| 1607 if (Status != A_OK) { |
| 1608 |
| 1609 printk(KERN_ERR "ar6000_target_failure: target asserted \n"); |
| 1610 |
| 1611 if (timer_pending(&ar->arHBChallengeResp.timer)) { |
| 1612 A_UNTIMEOUT(&ar->arHBChallengeResp.timer); |
| 1613 } |
| 1614 |
| 1615 /* try dumping target assertion information (if any) */ |
| 1616 ar6000_dump_target_assert_info(ar->arHifDevice,ar->arTargetType); |
| 1617 |
| 1618 /* |
| 1619 * Fetch the logs from the target via the diagnostic |
| 1620 * window. |
| 1621 */ |
| 1622 ar6000_dbglog_get_debug_logs(ar); |
| 1623 |
| 1624 /* Report the error only once */ |
| 1625 if (!sip) { |
| 1626 sip = TRUE; |
| 1627 errEvent.errorVal = WMI_TARGET_COM_ERR | |
| 1628 WMI_TARGET_FATAL_ERR; |
| 1629 ar6000_send_event_to_app(ar, WMI_ERROR_REPORT_EVENTID, |
| 1630 (A_UINT8 *)&errEvent, |
| 1631 sizeof(WMI_TARGET_ERROR_REPORT_EVENT)); |
| 1632 } |
| 1633 } |
| 1634 } |
| 1635 |
| 1636 static A_STATUS |
| 1637 ar6000_unavail_ev(void *context, void *hif_handle) |
| 1638 { |
| 1639 AR_SOFTC_T *ar = (AR_SOFTC_T *)context; |
| 1640 /* NULL out it's entry in the global list */ |
| 1641 ar6000_devices[ar->arDeviceIndex] = NULL; |
| 1642 ar6000_destroy(ar->arNetDev, 1); |
| 1643 |
| 1644 return A_OK; |
| 1645 } |
| 1646 |
| 1647 /* |
| 1648 * We need to differentiate between the surprise and planned removal of the |
| 1649 * device because of the following consideration: |
| 1650 * - In case of surprise removal, the hcd already frees up the pending |
| 1651 * for the device and hence there is no need to unregister the function |
| 1652 * driver inorder to get these requests. For planned removal, the function |
| 1653 * driver has to explictly unregister itself to have the hcd return all the |
| 1654 * pending requests before the data structures for the devices are freed up. |
| 1655 * Note that as per the current implementation, the function driver will |
| 1656 * end up releasing all the devices since there is no API to selectively |
| 1657 * release a particular device. |
| 1658 * - Certain commands issued to the target can be skipped for surprise |
| 1659 * removal since they will anyway not go through. |
| 1660 */ |
| 1661 static void |
| 1662 ar6000_destroy(struct net_device *dev, unsigned int unregister) |
| 1663 { |
| 1664 AR_SOFTC_T *ar; |
| 1665 |
| 1666 AR_DEBUG_PRINTF(ATH_DEBUG_INFO,("+ar6000_destroy \n")); |
| 1667 |
| 1668 if((dev == NULL) || ((ar = ar6k_priv(dev)) == NULL)) |
| 1669 { |
| 1670 AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("%s(): Failed to get device structure.\n"
, __func__)); |
| 1671 return; |
| 1672 } |
| 1673 |
| 1674 ar->bIsDestroyProgress = TRUE; |
| 1675 |
| 1676 if (down_interruptible(&ar->arSem)) { |
| 1677 AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("%s(): down_interruptible failed \n", __f
unc__)); |
| 1678 return; |
| 1679 } |
| 1680 |
| 1681 /* Stop the transmit queues */ |
| 1682 netif_stop_queue(dev); |
| 1683 |
| 1684 /* Disable the target and the interrupts associated with it */ |
| 1685 if (ar->arWmiReady == TRUE) |
| 1686 { |
| 1687 if (!bypasswmi) |
| 1688 { |
| 1689 if (ar->arConnected == TRUE || ar->arConnectPending == TRUE) |
| 1690 { |
| 1691 AR_DEBUG_PRINTF(ATH_DEBUG_INFO,("%s(): Disconnect\n", __func__))
; |
| 1692 AR6000_SPIN_LOCK(&ar->arLock, 0); |
| 1693 ar6000_init_profile_info(ar); |
| 1694 AR6000_SPIN_UNLOCK(&ar->arLock, 0); |
| 1695 wmi_disconnect_cmd(ar->arWmi); |
| 1696 } |
| 1697 |
| 1698 ar6000_dbglog_get_debug_logs(ar); |
| 1699 ar->arWmiReady = FALSE; |
| 1700 ar->arConnected = FALSE; |
| 1701 ar->arConnectPending = FALSE; |
| 1702 wmi_shutdown(ar->arWmi); |
| 1703 ar->arWmiEnabled = FALSE; |
| 1704 ar->arWmi = NULL; |
| 1705 ar->arWlanState = WLAN_ENABLED; |
| 1706 #ifdef USER_KEYS |
| 1707 ar->user_savedkeys_stat = USER_SAVEDKEYS_STAT_INIT; |
| 1708 ar->user_key_ctrl = 0; |
| 1709 #endif |
| 1710 } |
| 1711 |
| 1712 AR_DEBUG_PRINTF(ATH_DEBUG_INFO,("%s(): WMI stopped\n", __func__)); |
| 1713 } |
| 1714 else |
| 1715 { |
| 1716 AR_DEBUG_PRINTF(ATH_DEBUG_INFO,("%s(): WMI not ready 0x%08x 0x%08x\n", |
| 1717 __func__, (unsigned int) ar, (unsigned int) ar->arWmi)); |
| 1718 |
| 1719 /* Shut down WMI if we have started it */ |
| 1720 if(ar->arWmiEnabled == TRUE) |
| 1721 { |
| 1722 AR_DEBUG_PRINTF(ATH_DEBUG_INFO,("%s(): Shut down WMI\n", __func__)); |
| 1723 wmi_shutdown(ar->arWmi); |
| 1724 ar->arWmiEnabled = FALSE; |
| 1725 ar->arWmi = NULL; |
| 1726 } |
| 1727 } |
| 1728 |
| 1729 if (ar->arHtcTarget != NULL) { |
| 1730 #ifdef EXPORT_HCI_BRIDGE_INTERFACE |
| 1731 if (NULL != ar6kHciTransCallbacks.cleanupTransport) { |
| 1732 ar6kHciTransCallbacks.cleanupTransport(NULL); |
| 1733 } |
| 1734 #else |
| 1735 // FIXME: workaround to reset BT's UART baud rate to default |
| 1736 if (NULL != ar->exitCallback) { |
| 1737 AR3K_CONFIG_INFO ar3kconfig; |
| 1738 A_STATUS status; |
| 1739 |
| 1740 A_MEMZERO(&ar3kconfig,sizeof(ar3kconfig)); |
| 1741 ar6000_set_default_ar3kconfig(ar, (void *)&ar3kconfig); |
| 1742 status = ar->exitCallback(&ar3kconfig); |
| 1743 if (A_OK != status) { |
| 1744 AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Failed to reset AR3K baud rate!
\n")); |
| 1745 } |
| 1746 } |
| 1747 // END workaround |
| 1748 ar6000_cleanup_hci(ar); |
| 1749 #endif |
| 1750 AR_DEBUG_PRINTF(ATH_DEBUG_INFO,(" Shutting down HTC .... \n")); |
| 1751 /* stop HTC */ |
| 1752 HTCStop(ar->arHtcTarget); |
| 1753 /* destroy HTC */ |
| 1754 HTCDestroy(ar->arHtcTarget); |
| 1755 } |
| 1756 |
| 1757 if (resetok) { |
| 1758 /* try to reset the device if we can |
| 1759 * The driver may have been configure NOT to reset the target during |
| 1760 * a debug session */ |
| 1761 AR_DEBUG_PRINTF(ATH_DEBUG_INFO,(" Attempting to reset target on instance
destroy.... \n")); |
| 1762 if (ar->arHifDevice != NULL) { |
| 1763 ar6000_reset_device(ar->arHifDevice, ar->arTargetType, TRUE, FALSE); |
| 1764 } |
| 1765 } else { |
| 1766 AR_DEBUG_PRINTF(ATH_DEBUG_INFO,(" Host does not want target reset. \n"))
; |
| 1767 } |
| 1768 |
| 1769 if (ar->arHifDevice != NULL) { |
| 1770 /*release the device so we do not get called back on remove incase we |
| 1771 * we're explicity destroyed by module unload */ |
| 1772 HIFReleaseDevice(ar->arHifDevice); |
| 1773 HIFShutDownDevice(ar->arHifDevice); |
| 1774 } |
| 1775 #ifdef ATH_AR6K_11N_SUPPORT |
| 1776 aggr_module_destroy(ar->aggr_cntxt); |
| 1777 #endif |
| 1778 |
| 1779 /* Done with cookies */ |
| 1780 ar6000_cookie_cleanup(ar); |
| 1781 |
| 1782 /* cleanup any allocated AMSDU buffers */ |
| 1783 ar6000_cleanup_amsdu_rxbufs(ar); |
| 1784 |
| 1785 if (bmienable) { |
| 1786 ar6000_sysfs_bmi_deinit(ar); |
| 1787 } |
| 1788 |
| 1789 /* Cleanup BMI */ |
| 1790 BMIInit(); |
| 1791 |
| 1792 /* Clear the tx counters */ |
| 1793 memset(tx_attempt, 0, sizeof(tx_attempt)); |
| 1794 memset(tx_post, 0, sizeof(tx_post)); |
| 1795 memset(tx_complete, 0, sizeof(tx_complete)); |
| 1796 |
| 1797 |
| 1798 /* Free up the device data structure */ |
| 1799 if( unregister ) |
| 1800 unregister_netdev(dev); |
| 1801 #ifndef free_netdev |
| 1802 kfree(dev); |
| 1803 #else |
| 1804 free_netdev(dev); |
| 1805 #endif |
| 1806 |
| 1807 #ifdef CONFIG_CFG80211 |
| 1808 ar6k_cfg80211_deinit(ar); |
| 1809 #endif /* CONFIG_CFG80211 */ |
| 1810 |
| 1811 AR_DEBUG_PRINTF(ATH_DEBUG_INFO,("-ar6000_destroy \n")); |
| 1812 } |
| 1813 |
| 1814 static void disconnect_timer_handler(unsigned long ptr) |
| 1815 { |
| 1816 struct net_device *dev = (struct net_device *)ptr; |
| 1817 AR_SOFTC_T *ar = (AR_SOFTC_T *)ar6k_priv(dev); |
| 1818 |
| 1819 A_UNTIMEOUT(&ar->disconnect_timer); |
| 1820 |
| 1821 ar6000_init_profile_info(ar); |
| 1822 wmi_disconnect_cmd(ar->arWmi); |
| 1823 } |
| 1824 |
| 1825 static void ar6000_detect_error(unsigned long ptr) |
| 1826 { |
| 1827 struct net_device *dev = (struct net_device *)ptr; |
| 1828 AR_SOFTC_T *ar = (AR_SOFTC_T *)ar6k_priv(dev); |
| 1829 WMI_TARGET_ERROR_REPORT_EVENT errEvent; |
| 1830 |
| 1831 AR6000_SPIN_LOCK(&ar->arLock, 0); |
| 1832 |
| 1833 if (ar->arHBChallengeResp.outstanding) { |
| 1834 ar->arHBChallengeResp.missCnt++; |
| 1835 } else { |
| 1836 ar->arHBChallengeResp.missCnt = 0; |
| 1837 } |
| 1838 |
| 1839 if (ar->arHBChallengeResp.missCnt > ar->arHBChallengeResp.missThres) { |
| 1840 /* Send Error Detect event to the application layer and do not reschedul
e the error detection module timer */ |
| 1841 ar->arHBChallengeResp.missCnt = 0; |
| 1842 ar->arHBChallengeResp.seqNum = 0; |
| 1843 errEvent.errorVal = WMI_TARGET_COM_ERR | WMI_TARGET_FATAL_ERR; |
| 1844 AR6000_SPIN_UNLOCK(&ar->arLock, 0); |
| 1845 ar6000_send_event_to_app(ar, WMI_ERROR_REPORT_EVENTID, |
| 1846 (A_UINT8 *)&errEvent, |
| 1847 sizeof(WMI_TARGET_ERROR_REPORT_EVENT)); |
| 1848 return; |
| 1849 } |
| 1850 |
| 1851 /* Generate the sequence number for the next challenge */ |
| 1852 ar->arHBChallengeResp.seqNum++; |
| 1853 ar->arHBChallengeResp.outstanding = TRUE; |
| 1854 |
| 1855 AR6000_SPIN_UNLOCK(&ar->arLock, 0); |
| 1856 |
| 1857 /* Send the challenge on the control channel */ |
| 1858 if (wmi_get_challenge_resp_cmd(ar->arWmi, ar->arHBChallengeResp.seqNum, DRV_
HB_CHALLENGE) != A_OK) { |
| 1859 AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Unable to send heart beat challenge\n"))
; |
| 1860 } |
| 1861 |
| 1862 |
| 1863 /* Reschedule the timer for the next challenge */ |
| 1864 A_TIMEOUT_MS(&ar->arHBChallengeResp.timer, ar->arHBChallengeResp.frequency *
1000, 0); |
| 1865 } |
| 1866 |
| 1867 void ar6000_init_profile_info(AR_SOFTC_T *ar) |
| 1868 { |
| 1869 ar->arSsidLen = 0; |
| 1870 A_MEMZERO(ar->arSsid, sizeof(ar->arSsid)); |
| 1871 |
| 1872 switch(fwmode) { |
| 1873 case HI_OPTION_FW_MODE_IBSS: |
| 1874 ar->arNetworkType = ar->arNextMode = ADHOC_NETWORK; |
| 1875 break; |
| 1876 case HI_OPTION_FW_MODE_BSS_STA: |
| 1877 ar->arNetworkType = ar->arNextMode = INFRA_NETWORK; |
| 1878 break; |
| 1879 case HI_OPTION_FW_MODE_AP: |
| 1880 ar->arNetworkType = ar->arNextMode = AP_NETWORK; |
| 1881 break; |
| 1882 } |
| 1883 |
| 1884 ar->arDot11AuthMode = OPEN_AUTH; |
| 1885 ar->arAuthMode = NONE_AUTH; |
| 1886 ar->arPairwiseCrypto = NONE_CRYPT; |
| 1887 ar->arPairwiseCryptoLen = 0; |
| 1888 ar->arGroupCrypto = NONE_CRYPT; |
| 1889 ar->arGroupCryptoLen = 0; |
| 1890 A_MEMZERO(ar->arWepKeyList, sizeof(ar->arWepKeyList)); |
| 1891 A_MEMZERO(ar->arReqBssid, sizeof(ar->arReqBssid)); |
| 1892 A_MEMZERO(ar->arBssid, sizeof(ar->arBssid)); |
| 1893 ar->arBssChannel = 0; |
| 1894 ar->arConnected = FALSE; |
| 1895 } |
| 1896 |
| 1897 static void |
| 1898 ar6000_init_control_info(AR_SOFTC_T *ar) |
| 1899 { |
| 1900 ar->arWmiEnabled = FALSE; |
| 1901 ar6000_init_profile_info(ar); |
| 1902 ar->arDefTxKeyIndex = 0; |
| 1903 A_MEMZERO(ar->arWepKeyList, sizeof(ar->arWepKeyList)); |
| 1904 ar->arChannelHint = 0; |
| 1905 ar->arListenInterval = MAX_LISTEN_INTERVAL; |
| 1906 ar->arVersion.host_ver = AR6K_SW_VERSION; |
| 1907 ar->arRssi = 0; |
| 1908 ar->arTxPwr = 0; |
| 1909 ar->arTxPwrSet = FALSE; |
| 1910 ar->arSkipScan = 0; |
| 1911 ar->arBeaconInterval = 0; |
| 1912 ar->arBitRate = 0; |
| 1913 ar->arMaxRetries = 0; |
| 1914 ar->arWmmEnabled = TRUE; |
| 1915 ar->intra_bss = 1; |
| 1916 |
| 1917 /* Initialize the AP mode state info */ |
| 1918 { |
| 1919 A_UINT8 ctr; |
| 1920 A_MEMZERO((A_UINT8 *)ar->sta_list, AP_MAX_NUM_STA * sizeof(sta_t)); |
| 1921 |
| 1922 /* init the Mutexes */ |
| 1923 A_MUTEX_INIT(&ar->mcastpsqLock); |
| 1924 |
| 1925 /* Init the PS queues */ |
| 1926 for (ctr=0; ctr < AP_MAX_NUM_STA ; ctr++) { |
| 1927 A_MUTEX_INIT(&ar->sta_list[ctr].psqLock); |
| 1928 A_NETBUF_QUEUE_INIT(&ar->sta_list[ctr].psq); |
| 1929 } |
| 1930 |
| 1931 ar->ap_profile_flag = 0; |
| 1932 A_NETBUF_QUEUE_INIT(&ar->mcastpsq); |
| 1933 |
| 1934 A_MEMCPY(ar->ap_country_code, DEF_AP_COUNTRY_CODE, 3); |
| 1935 ar->ap_wmode = DEF_AP_WMODE_G; |
| 1936 ar->ap_dtim_period = DEF_AP_DTIM; |
| 1937 ar->ap_beacon_interval = DEF_BEACON_INTERVAL; |
| 1938 } |
| 1939 } |
| 1940 |
| 1941 static int |
| 1942 ar6000_open(struct net_device *dev) |
| 1943 { |
| 1944 unsigned long flags; |
| 1945 AR_SOFTC_T *ar = (AR_SOFTC_T *)ar6k_priv(dev); |
| 1946 |
| 1947 spin_lock_irqsave(&ar->arLock, flags); |
| 1948 |
| 1949 if(ar->arWlanState == WLAN_DISABLED) { |
| 1950 ar->arWlanState = WLAN_ENABLED; |
| 1951 } |
| 1952 |
| 1953 if( ar->arConnected || bypasswmi) { |
| 1954 netif_carrier_on(dev); |
| 1955 /* Wake up the queues */ |
| 1956 netif_wake_queue(dev); |
| 1957 } |
| 1958 else |
| 1959 netif_carrier_off(dev); |
| 1960 |
| 1961 spin_unlock_irqrestore(&ar->arLock, flags); |
| 1962 return 0; |
| 1963 } |
| 1964 |
| 1965 static int |
| 1966 ar6000_close(struct net_device *dev) |
| 1967 { |
| 1968 AR_SOFTC_T *ar = (AR_SOFTC_T *)ar6k_priv(dev); |
| 1969 netif_stop_queue(dev); |
| 1970 |
| 1971 AR6000_SPIN_LOCK(&ar->arLock, 0); |
| 1972 if (ar->arConnected == TRUE || ar->arConnectPending == TRUE) { |
| 1973 AR6000_SPIN_UNLOCK(&ar->arLock, 0); |
| 1974 wmi_disconnect_cmd(ar->arWmi); |
| 1975 A_MEMZERO(ar->arSsid, sizeof(ar->arSsid)); |
| 1976 ar->arSsidLen = 0; |
| 1977 } else { |
| 1978 AR6000_SPIN_UNLOCK(&ar->arLock, 0); |
| 1979 } |
| 1980 |
| 1981 if(ar->arWmiReady == TRUE) { |
| 1982 if (wmi_scanparams_cmd(ar->arWmi, 0xFFFF, 0, |
| 1983 0, 0, 0, 0, 0, 0xFF, 0, 0) != A_OK) { |
| 1984 return -EIO; |
| 1985 } |
| 1986 ar->arWlanState = WLAN_DISABLED; |
| 1987 } |
| 1988 |
| 1989 return 0; |
| 1990 } |
| 1991 |
| 1992 /* connect to a service */ |
| 1993 static A_STATUS ar6000_connectservice(AR_SOFTC_T *ar, |
| 1994 HTC_SERVICE_CONNECT_REQ *pConnect, |
| 1995 char *pDesc) |
| 1996 { |
| 1997 A_STATUS status; |
| 1998 HTC_SERVICE_CONNECT_RESP response; |
| 1999 |
| 2000 do { |
| 2001 |
| 2002 A_MEMZERO(&response,sizeof(response)); |
| 2003 |
| 2004 status = HTCConnectService(ar->arHtcTarget, |
| 2005 pConnect, |
| 2006 &response); |
| 2007 |
| 2008 if (A_FAILED(status)) { |
| 2009 AR_DEBUG_PRINTF(ATH_DEBUG_ERR,(" Failed to connect to %s service sta
tus:%d \n", |
| 2010 pDesc, status)); |
| 2011 break; |
| 2012 } |
| 2013 switch (pConnect->ServiceID) { |
| 2014 case WMI_CONTROL_SVC : |
| 2015 if (ar->arWmiEnabled) { |
| 2016 /* set control endpoint for WMI use */ |
| 2017 wmi_set_control_ep(ar->arWmi, response.Endpoint); |
| 2018 } |
| 2019 /* save EP for fast lookup */ |
| 2020 ar->arControlEp = response.Endpoint; |
| 2021 break; |
| 2022 case WMI_DATA_BE_SVC : |
| 2023 arSetAc2EndpointIDMap(ar, WMM_AC_BE, response.Endpoint); |
| 2024 break; |
| 2025 case WMI_DATA_BK_SVC : |
| 2026 arSetAc2EndpointIDMap(ar, WMM_AC_BK, response.Endpoint); |
| 2027 break; |
| 2028 case WMI_DATA_VI_SVC : |
| 2029 arSetAc2EndpointIDMap(ar, WMM_AC_VI, response.Endpoint); |
| 2030 break; |
| 2031 case WMI_DATA_VO_SVC : |
| 2032 arSetAc2EndpointIDMap(ar, WMM_AC_VO, response.Endpoint); |
| 2033 break; |
| 2034 default: |
| 2035 AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("ServiceID not mapped %d\n", pCon
nect->ServiceID)); |
| 2036 status = A_EINVAL; |
| 2037 break; |
| 2038 } |
| 2039 |
| 2040 } while (FALSE); |
| 2041 |
| 2042 return status; |
| 2043 } |
| 2044 |
| 2045 void ar6000_TxDataCleanup(AR_SOFTC_T *ar) |
| 2046 { |
| 2047 /* flush all the data (non-control) streams |
| 2048 * we only flush packets that are tagged as data, we leave any control p
ackets that |
| 2049 * were in the TX queues alone */ |
| 2050 HTCFlushEndpoint(ar->arHtcTarget, |
| 2051 arAc2EndpointID(ar, WMM_AC_BE), |
| 2052 AR6K_DATA_PKT_TAG); |
| 2053 HTCFlushEndpoint(ar->arHtcTarget, |
| 2054 arAc2EndpointID(ar, WMM_AC_BK), |
| 2055 AR6K_DATA_PKT_TAG); |
| 2056 HTCFlushEndpoint(ar->arHtcTarget, |
| 2057 arAc2EndpointID(ar, WMM_AC_VI), |
| 2058 AR6K_DATA_PKT_TAG); |
| 2059 HTCFlushEndpoint(ar->arHtcTarget, |
| 2060 arAc2EndpointID(ar, WMM_AC_VO), |
| 2061 AR6K_DATA_PKT_TAG); |
| 2062 } |
| 2063 |
| 2064 HTC_ENDPOINT_ID |
| 2065 ar6000_ac2_endpoint_id ( void * devt, A_UINT8 ac) |
| 2066 { |
| 2067 AR_SOFTC_T *ar = (AR_SOFTC_T *) devt; |
| 2068 return(arAc2EndpointID(ar, ac)); |
| 2069 } |
| 2070 |
| 2071 A_UINT8 |
| 2072 ar6000_endpoint_id2_ac(void * devt, HTC_ENDPOINT_ID ep ) |
| 2073 { |
| 2074 AR_SOFTC_T *ar = (AR_SOFTC_T *) devt; |
| 2075 return(arEndpoint2Ac(ar, ep )); |
| 2076 } |
| 2077 |
| 2078 /* This function does one time initialization for the lifetime of the device */ |
| 2079 int ar6000_init(struct net_device *dev) |
| 2080 { |
| 2081 AR_SOFTC_T *ar; |
| 2082 A_STATUS status; |
| 2083 A_INT32 timeleft; |
| 2084 A_INT16 i; |
| 2085 |
| 2086 if((ar = ar6k_priv(dev)) == NULL) |
| 2087 { |
| 2088 return(-EIO); |
| 2089 } |
| 2090 |
| 2091 if (enablerssicompensation) { |
| 2092 read_rssi_compensation_param(ar); |
| 2093 for (i=-95; i<=0; i++) { |
| 2094 rssi_compensation_table[0-i] = rssi_compensation_calc(ar,i); |
| 2095 } |
| 2096 } |
| 2097 |
| 2098 if (!bypasswmi) |
| 2099 { |
| 2100 #if 0 /* TBDXXX */ |
| 2101 if (ar->arVersion.host_ver != ar->arVersion.target_ver) { |
| 2102 A_PRINTF("WARNING: Host version 0x%x does not match Target " |
| 2103 " version 0x%x!\n", |
| 2104 ar->arVersion.host_ver, ar->arVersion.target_ver); |
| 2105 } |
| 2106 #endif |
| 2107 |
| 2108 /* Indicate that WMI is enabled (although not ready yet) */ |
| 2109 ar->arWmiEnabled = TRUE; |
| 2110 if ((ar->arWmi = wmi_init((void *) ar)) == NULL) |
| 2111 { |
| 2112 AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("%s() Failed to initialize WMI.\n", _
_func__)); |
| 2113 return(-EIO); |
| 2114 } |
| 2115 |
| 2116 AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("%s() Got WMI @ 0x%08x.\n", __func__, |
| 2117 (unsigned int) ar->arWmi)); |
| 2118 } |
| 2119 |
| 2120 do { |
| 2121 HTC_SERVICE_CONNECT_REQ connect; |
| 2122 |
| 2123 /* the reason we have to wait for the target here is that the driver
layer |
| 2124 * has to init BMI in order to set the host block size, |
| 2125 */ |
| 2126 dev_hold(dev); |
| 2127 rtnl_unlock(); |
| 2128 status = HTCWaitTarget(ar->arHtcTarget); |
| 2129 rtnl_lock(); |
| 2130 dev_put(dev); |
| 2131 |
| 2132 if (A_FAILED(status)) { |
| 2133 break; |
| 2134 } |
| 2135 |
| 2136 A_MEMZERO(&connect,sizeof(connect)); |
| 2137 /* meta data is unused for now */ |
| 2138 connect.pMetaData = NULL; |
| 2139 connect.MetaDataLength = 0; |
| 2140 /* these fields are the same for all service endpoints */ |
| 2141 connect.EpCallbacks.pContext = ar; |
| 2142 connect.EpCallbacks.EpTxCompleteMultiple = ar6000_tx_complete; |
| 2143 connect.EpCallbacks.EpRecv = ar6000_rx; |
| 2144 connect.EpCallbacks.EpRecvRefill = ar6000_rx_refill; |
| 2145 connect.EpCallbacks.EpSendFull = ar6000_tx_queue_full; |
| 2146 /* set the max queue depth so that our ar6000_tx_queue_full handler
gets called. |
| 2147 * Linux has the peculiarity of not providing flow control between t
he |
| 2148 * NIC and the network stack. There is no API to indicate that a TX
packet |
| 2149 * was sent which could provide some back pressure to the network st
ack. |
| 2150 * Under linux you would have to wait till the network stack consume
d all sk_buffs |
| 2151 * before any back-flow kicked in. Which isn't very friendly. |
| 2152 * So we have to manage this ourselves */ |
| 2153 connect.MaxSendQueueDepth = MAX_DEFAULT_SEND_QUEUE_DEPTH; |
| 2154 connect.EpCallbacks.RecvRefillWaterMark = AR6000_MAX_RX_BUFFERS / 4; /*
set to 25 % */ |
| 2155 if (0 == connect.EpCallbacks.RecvRefillWaterMark) { |
| 2156 connect.EpCallbacks.RecvRefillWaterMark++; |
| 2157 } |
| 2158 /* connect to control service */ |
| 2159 connect.ServiceID = WMI_CONTROL_SVC; |
| 2160 status = ar6000_connectservice(ar, |
| 2161 &connect, |
| 2162 "WMI CONTROL"); |
| 2163 if (A_FAILED(status)) { |
| 2164 break; |
| 2165 } |
| 2166 |
| 2167 connect.LocalConnectionFlags |= HTC_LOCAL_CONN_FLAGS_ENABLE_SEND_BUNDLE_
PADDING; |
| 2168 /* limit the HTC message size on the send path, although we can rece
ive A-MSDU frames of |
| 2169 * 4K, we will only send ethernet-sized (802.3) frames on the send p
ath. */ |
| 2170 connect.MaxSendMsgSize = WMI_MAX_TX_DATA_FRAME_LENGTH; |
| 2171 |
| 2172 /* to reduce the amount of committed memory for larger A_MSDU frames
, use the recv-alloc threshold |
| 2173 * mechanism for larger packets */ |
| 2174 connect.EpCallbacks.RecvAllocThreshold = AR6000_BUFFER_SIZE; |
| 2175 connect.EpCallbacks.EpRecvAllocThresh = ar6000_alloc_amsdu_rxbuf; |
| 2176 |
| 2177 /* for the remaining data services set the connection flag to reduce
dribbling, |
| 2178 * if configured to do so */ |
| 2179 if (reduce_credit_dribble) { |
| 2180 connect.ConnectionFlags |= HTC_CONNECT_FLAGS_REDUCE_CREDIT_DRIBBLE; |
| 2181 /* the credit dribble trigger threshold is (reduce_credit_dribble -
1) for a value |
| 2182 * of 0-3 */ |
| 2183 connect.ConnectionFlags &= ~HTC_CONNECT_FLAGS_THRESHOLD_LEVEL_MASK; |
| 2184 connect.ConnectionFlags |= |
| 2185 ((A_UINT16)reduce_credit_dribble - 1) & HTC_CONNECT_FLAG
S_THRESHOLD_LEVEL_MASK; |
| 2186 } |
| 2187 /* connect to best-effort service */ |
| 2188 connect.ServiceID = WMI_DATA_BE_SVC; |
| 2189 |
| 2190 status = ar6000_connectservice(ar, |
| 2191 &connect, |
| 2192 "WMI DATA BE"); |
| 2193 if (A_FAILED(status)) { |
| 2194 break; |
| 2195 } |
| 2196 |
| 2197 /* connect to back-ground |
| 2198 * map this to WMI LOW_PRI */ |
| 2199 connect.ServiceID = WMI_DATA_BK_SVC; |
| 2200 status = ar6000_connectservice(ar, |
| 2201 &connect, |
| 2202 "WMI DATA BK"); |
| 2203 if (A_FAILED(status)) { |
| 2204 break; |
| 2205 } |
| 2206 |
| 2207 /* connect to Video service, map this to |
| 2208 * to HI PRI */ |
| 2209 connect.ServiceID = WMI_DATA_VI_SVC; |
| 2210 status = ar6000_connectservice(ar, |
| 2211 &connect, |
| 2212 "WMI DATA VI"); |
| 2213 if (A_FAILED(status)) { |
| 2214 break; |
| 2215 } |
| 2216 |
| 2217 /* connect to VO service, this is currently not |
| 2218 * mapped to a WMI priority stream due to historical reasons. |
| 2219 * WMI originally defined 3 priorities over 3 mailboxes |
| 2220 * We can change this when WMI is reworked so that priorities are no
t |
| 2221 * dependent on mailboxes */ |
| 2222 connect.ServiceID = WMI_DATA_VO_SVC; |
| 2223 status = ar6000_connectservice(ar, |
| 2224 &connect, |
| 2225 "WMI DATA VO"); |
| 2226 if (A_FAILED(status)) { |
| 2227 break; |
| 2228 } |
| 2229 |
| 2230 A_ASSERT(arAc2EndpointID(ar,WMM_AC_BE) != 0); |
| 2231 A_ASSERT(arAc2EndpointID(ar,WMM_AC_BK) != 0); |
| 2232 A_ASSERT(arAc2EndpointID(ar,WMM_AC_VI) != 0); |
| 2233 A_ASSERT(arAc2EndpointID(ar,WMM_AC_VO) != 0); |
| 2234 |
| 2235 /* setup access class priority mappings */ |
| 2236 ar->arAcStreamPriMap[WMM_AC_BK] = 0; /* lowest */ |
| 2237 ar->arAcStreamPriMap[WMM_AC_BE] = 1; /* */ |
| 2238 ar->arAcStreamPriMap[WMM_AC_VI] = 2; /* */ |
| 2239 ar->arAcStreamPriMap[WMM_AC_VO] = 3; /* highest */ |
| 2240 |
| 2241 #ifdef EXPORT_HCI_BRIDGE_INTERFACE |
| 2242 if (setuphci && (NULL != ar6kHciTransCallbacks.setupTransport)) { |
| 2243 HCI_TRANSPORT_MISC_HANDLES hciHandles; |
| 2244 |
| 2245 hciHandles.netDevice = ar->arNetDev; |
| 2246 hciHandles.hifDevice = ar->arHifDevice; |
| 2247 hciHandles.htcHandle = ar->arHtcTarget; |
| 2248 status = (A_STATUS)(ar6kHciTransCallbacks.setupTransport(&hciHandles
)); |
| 2249 #else |
| 2250 if (setuphci) { |
| 2251 /* setup HCI */ |
| 2252 status = ar6000_setup_hci(ar); |
| 2253 #endif |
| 2254 } |
| 2255 |
| 2256 } while (FALSE); |
| 2257 |
| 2258 if (A_FAILED(status)) { |
| 2259 return (-EIO); |
| 2260 } |
| 2261 |
| 2262 /* |
| 2263 * give our connected endpoints some buffers |
| 2264 */ |
| 2265 |
| 2266 ar6000_rx_refill(ar, ar->arControlEp); |
| 2267 ar6000_rx_refill(ar, arAc2EndpointID(ar,WMM_AC_BE)); |
| 2268 |
| 2269 /* |
| 2270 * We will post the receive buffers only for SPE or endpoint ping testing so
we are |
| 2271 * making it conditional on the 'bypasswmi' flag. |
| 2272 */ |
| 2273 if (bypasswmi) { |
| 2274 ar6000_rx_refill(ar,arAc2EndpointID(ar,WMM_AC_BK)); |
| 2275 ar6000_rx_refill(ar,arAc2EndpointID(ar,WMM_AC_VI)); |
| 2276 ar6000_rx_refill(ar,arAc2EndpointID(ar,WMM_AC_VO)); |
| 2277 } |
| 2278 |
| 2279 /* allocate some buffers that handle larger AMSDU frames */ |
| 2280 ar6000_refill_amsdu_rxbufs(ar,AR6000_MAX_AMSDU_RX_BUFFERS); |
| 2281 |
| 2282 /* setup credit distribution */ |
| 2283 ar6000_setup_credit_dist(ar->arHtcTarget, &ar->arCreditStateInfo); |
| 2284 |
| 2285 /* Since cookies are used for HTC transports, they should be */ |
| 2286 /* initialized prior to enabling HTC. */ |
| 2287 ar6000_cookie_init(ar); |
| 2288 |
| 2289 /* start HTC */ |
| 2290 status = HTCStart(ar->arHtcTarget); |
| 2291 |
| 2292 if (status != A_OK) { |
| 2293 if (ar->arWmiEnabled == TRUE) { |
| 2294 wmi_shutdown(ar->arWmi); |
| 2295 ar->arWmiEnabled = FALSE; |
| 2296 ar->arWmi = NULL; |
| 2297 } |
| 2298 ar6000_cookie_cleanup(ar); |
| 2299 return -EIO; |
| 2300 } |
| 2301 |
| 2302 if (!bypasswmi) { |
| 2303 /* Wait for Wmi event to be ready */ |
| 2304 dev_hold(dev); |
| 2305 rtnl_unlock(); |
| 2306 timeleft = wait_event_interruptible_timeout(arEvent, |
| 2307 (ar->arWmiReady == TRUE), wmitimeout * HZ); |
| 2308 rtnl_lock(); |
| 2309 dev_put(dev); |
| 2310 |
| 2311 if(!timeleft || signal_pending(current)) |
| 2312 { |
| 2313 AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("WMI is not ready or wait was interru
pted\n")); |
| 2314 return -EIO; |
| 2315 } |
| 2316 |
| 2317 AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("%s() WMI is ready\n", __func__)); |
| 2318 |
| 2319 /* Communicate the wmi protocol verision to the target */ |
| 2320 if ((ar6000_set_host_app_area(ar)) != A_OK) { |
| 2321 AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Unable to set the host app area\n"))
; |
| 2322 } |
| 2323 |
| 2324 /* configure the device for rx dot11 header rules 0,0 are the default va
lues |
| 2325 * therefore this command can be skipped if the inputs are 0,FALSE,FALSE
.Required |
| 2326 if checksum offload is needed. Set RxMetaVersion to 2*/ |
| 2327 if ((wmi_set_rx_frame_format_cmd(ar->arWmi,ar->rxMetaVersion, processDot
11Hdr, processDot11Hdr)) != A_OK) { |
| 2328 AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Unable to set the rx frame format.\n
")); |
| 2329 } |
| 2330 } |
| 2331 |
| 2332 ar->arNumDataEndPts = 1; |
| 2333 |
| 2334 if (bypasswmi) { |
| 2335 /* for tests like endpoint ping, the MAC address needs to be non-zer
o otherwise |
| 2336 * the data path through a raw socket is disabled */ |
| 2337 dev->dev_addr[0] = 0x00; |
| 2338 dev->dev_addr[1] = 0x01; |
| 2339 dev->dev_addr[2] = 0x02; |
| 2340 dev->dev_addr[3] = 0xAA; |
| 2341 dev->dev_addr[4] = 0xBB; |
| 2342 dev->dev_addr[5] = 0xCC; |
| 2343 } |
| 2344 |
| 2345 return(0); |
| 2346 } |
| 2347 |
| 2348 |
| 2349 void |
| 2350 ar6000_bitrate_rx(void *devt, A_INT32 rateKbps) |
| 2351 { |
| 2352 AR_SOFTC_T *ar = (AR_SOFTC_T *)devt; |
| 2353 |
| 2354 ar->arBitRate = rateKbps; |
| 2355 wake_up(&arEvent); |
| 2356 } |
| 2357 |
| 2358 void |
| 2359 ar6000_ratemask_rx(void *devt, A_UINT32 ratemask) |
| 2360 { |
| 2361 AR_SOFTC_T *ar = (AR_SOFTC_T *)devt; |
| 2362 |
| 2363 ar->arRateMask = ratemask; |
| 2364 wake_up(&arEvent); |
| 2365 } |
| 2366 |
| 2367 void |
| 2368 ar6000_txPwr_rx(void *devt, A_UINT8 txPwr) |
| 2369 { |
| 2370 AR_SOFTC_T *ar = (AR_SOFTC_T *)devt; |
| 2371 |
| 2372 ar->arTxPwr = txPwr; |
| 2373 wake_up(&arEvent); |
| 2374 } |
| 2375 |
| 2376 |
| 2377 void |
| 2378 ar6000_channelList_rx(void *devt, A_INT8 numChan, A_UINT16 *chanList) |
| 2379 { |
| 2380 AR_SOFTC_T *ar = (AR_SOFTC_T *)devt; |
| 2381 |
| 2382 A_MEMCPY(ar->arChannelList, chanList, numChan * sizeof (A_UINT16)); |
| 2383 ar->arNumChannels = numChan; |
| 2384 |
| 2385 wake_up(&arEvent); |
| 2386 } |
| 2387 |
| 2388 A_UINT8 |
| 2389 ar6000_ibss_map_epid(struct sk_buff *skb, struct net_device *dev, A_UINT32 * map
No) |
| 2390 { |
| 2391 AR_SOFTC_T *ar = (AR_SOFTC_T *)ar6k_priv(dev); |
| 2392 A_UINT8 *datap; |
| 2393 ATH_MAC_HDR *macHdr; |
| 2394 A_UINT32 i, eptMap; |
| 2395 |
| 2396 (*mapNo) = 0; |
| 2397 datap = A_NETBUF_DATA(skb); |
| 2398 macHdr = (ATH_MAC_HDR *)(datap + sizeof(WMI_DATA_HDR)); |
| 2399 if (IEEE80211_IS_MULTICAST(macHdr->dstMac)) { |
| 2400 return ENDPOINT_2; |
| 2401 } |
| 2402 |
| 2403 eptMap = -1; |
| 2404 for (i = 0; i < ar->arNodeNum; i ++) { |
| 2405 if (IEEE80211_ADDR_EQ(macHdr->dstMac, ar->arNodeMap[i].macAddress)) { |
| 2406 (*mapNo) = i + 1; |
| 2407 ar->arNodeMap[i].txPending ++; |
| 2408 return ar->arNodeMap[i].epId; |
| 2409 } |
| 2410 |
| 2411 if ((eptMap == -1) && !ar->arNodeMap[i].txPending) { |
| 2412 eptMap = i; |
| 2413 } |
| 2414 } |
| 2415 |
| 2416 if (eptMap == -1) { |
| 2417 eptMap = ar->arNodeNum; |
| 2418 ar->arNodeNum ++; |
| 2419 A_ASSERT(ar->arNodeNum <= MAX_NODE_NUM); |
| 2420 } |
| 2421 |
| 2422 A_MEMCPY(ar->arNodeMap[eptMap].macAddress, macHdr->dstMac, IEEE80211_ADDR_LE
N); |
| 2423 |
| 2424 for (i = ENDPOINT_2; i <= ENDPOINT_5; i ++) { |
| 2425 if (!ar->arTxPending[i]) { |
| 2426 ar->arNodeMap[eptMap].epId = i; |
| 2427 break; |
| 2428 } |
| 2429 // No free endpoint is available, start redistribution on the inuse endp
oints. |
| 2430 if (i == ENDPOINT_5) { |
| 2431 ar->arNodeMap[eptMap].epId = ar->arNexEpId; |
| 2432 ar->arNexEpId ++; |
| 2433 if (ar->arNexEpId > ENDPOINT_5) { |
| 2434 ar->arNexEpId = ENDPOINT_2; |
| 2435 } |
| 2436 } |
| 2437 } |
| 2438 |
| 2439 (*mapNo) = eptMap + 1; |
| 2440 ar->arNodeMap[eptMap].txPending ++; |
| 2441 |
| 2442 return ar->arNodeMap[eptMap].epId; |
| 2443 } |
| 2444 |
| 2445 #ifdef DEBUG |
| 2446 static void ar6000_dump_skb(struct sk_buff *skb) |
| 2447 { |
| 2448 u_char *ch; |
| 2449 for (ch = A_NETBUF_DATA(skb); |
| 2450 (A_UINT32)ch < ((A_UINT32)A_NETBUF_DATA(skb) + |
| 2451 A_NETBUF_LEN(skb)); ch++) |
| 2452 { |
| 2453 AR_DEBUG_PRINTF(ATH_DEBUG_WARN,("%2.2x ", *ch)); |
| 2454 } |
| 2455 AR_DEBUG_PRINTF(ATH_DEBUG_WARN,("\n")); |
| 2456 } |
| 2457 #endif |
| 2458 |
| 2459 #ifdef HTC_TEST_SEND_PKTS |
| 2460 static void DoHTCSendPktsTest(AR_SOFTC_T *ar, int MapNo, HTC_ENDPOINT_ID eid, st
ruct sk_buff *skb); |
| 2461 #endif |
| 2462 |
| 2463 static int |
| 2464 ar6000_data_tx(struct sk_buff *skb, struct net_device *dev) |
| 2465 { |
| 2466 #define AC_NOT_MAPPED 99 |
| 2467 AR_SOFTC_T *ar = (AR_SOFTC_T *)ar6k_priv(dev); |
| 2468 A_UINT8 ac = AC_NOT_MAPPED; |
| 2469 HTC_ENDPOINT_ID eid = ENDPOINT_UNUSED; |
| 2470 A_UINT32 mapNo = 0; |
| 2471 int len; |
| 2472 struct ar_cookie *cookie; |
| 2473 A_BOOL checkAdHocPsMapping = FALSE,bMoreData = FALSE; |
| 2474 HTC_TX_TAG htc_tag = AR6K_DATA_PKT_TAG; |
| 2475 A_UINT8 dot11Hdr = processDot11Hdr; |
| 2476 #if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,13) |
| 2477 skb->list = NULL; |
| 2478 #endif |
| 2479 |
| 2480 AR_DEBUG_PRINTF(ATH_DEBUG_WLAN_TX,("ar6000_data_tx start - skb=0x%x, data=0x
%x, len=0x%x\n", |
| 2481 (A_UINT32)skb, (A_UINT32)A_NETBUF_DATA(skb), |
| 2482 A_NETBUF_LEN(skb))); |
| 2483 |
| 2484 /* If target is not associated */ |
| 2485 if( (!ar->arConnected && !bypasswmi) |
| 2486 #ifdef CONFIG_HOST_TCMD_SUPPORT |
| 2487 /* TCMD doesnt support any data, free the buf and return */ |
| 2488 || (ar->arTargetMode == AR6000_TCMD_MODE) |
| 2489 #endif |
| 2490 ) { |
| 2491 A_NETBUF_FREE(skb); |
| 2492 return 0; |
| 2493 } |
| 2494 |
| 2495 do { |
| 2496 |
| 2497 if (ar->arWmiReady == FALSE && bypasswmi == 0) { |
| 2498 break; |
| 2499 } |
| 2500 |
| 2501 #ifdef BLOCK_TX_PATH_FLAG |
| 2502 if (blocktx) { |
| 2503 break; |
| 2504 } |
| 2505 #endif /* BLOCK_TX_PATH_FLAG */ |
| 2506 |
| 2507 /* AP mode Power save processing */ |
| 2508 /* If the dst STA is in sleep state, queue the pkt in its PS queue */ |
| 2509 |
| 2510 if (ar->arNetworkType == AP_NETWORK) { |
| 2511 ATH_MAC_HDR *datap = (ATH_MAC_HDR *)A_NETBUF_DATA(skb); |
| 2512 sta_t *conn = NULL; |
| 2513 |
| 2514 /* If the dstMac is a Multicast address & atleast one of the |
| 2515 * associated STA is in PS mode, then queue the pkt to the |
| 2516 * mcastq |
| 2517 */ |
| 2518 if (IEEE80211_IS_MULTICAST(datap->dstMac)) { |
| 2519 A_UINT8 ctr=0; |
| 2520 A_BOOL qMcast=FALSE; |
| 2521 |
| 2522 |
| 2523 for (ctr=0; ctr<AP_MAX_NUM_STA; ctr++) { |
| 2524 if (STA_IS_PWR_SLEEP((&ar->sta_list[ctr]))) { |
| 2525 qMcast = TRUE; |
| 2526 } |
| 2527 } |
| 2528 if(qMcast) { |
| 2529 |
| 2530 /* If this transmit is not because of a Dtim Expiry q it */ |
| 2531 if (ar->DTIMExpired == FALSE) { |
| 2532 A_BOOL isMcastqEmpty = FALSE; |
| 2533 |
| 2534 A_MUTEX_LOCK(&ar->mcastpsqLock); |
| 2535 isMcastqEmpty = A_NETBUF_QUEUE_EMPTY(&ar->mcastpsq); |
| 2536 A_NETBUF_ENQUEUE(&ar->mcastpsq, skb); |
| 2537 A_MUTEX_UNLOCK(&ar->mcastpsqLock); |
| 2538 |
| 2539 /* If this is the first Mcast pkt getting queued |
| 2540 * indicate to the target to set the BitmapControl LSB |
| 2541 * of the TIM IE. |
| 2542 */ |
| 2543 if (isMcastqEmpty) { |
| 2544 wmi_set_pvb_cmd(ar->arWmi, MCAST_AID, 1); |
| 2545 } |
| 2546 return 0; |
| 2547 } else { |
| 2548 /* This transmit is because of Dtim expiry. Determine if |
| 2549 * MoreData bit has to be set. |
| 2550 */ |
| 2551 A_MUTEX_LOCK(&ar->mcastpsqLock); |
| 2552 if(!A_NETBUF_QUEUE_EMPTY(&ar->mcastpsq)) { |
| 2553 bMoreData = TRUE; |
| 2554 } |
| 2555 A_MUTEX_UNLOCK(&ar->mcastpsqLock); |
| 2556 } |
| 2557 } |
| 2558 } else { |
| 2559 conn = ieee80211_find_conn(ar, datap->dstMac); |
| 2560 if (conn) { |
| 2561 if (STA_IS_PWR_SLEEP(conn)) { |
| 2562 /* If this transmit is not because of a PsPoll q it*/ |
| 2563 if (!STA_IS_PS_POLLED(conn)) { |
| 2564 A_BOOL isPsqEmpty = FALSE; |
| 2565 /* Queue the frames if the STA is sleeping */ |
| 2566 A_MUTEX_LOCK(&conn->psqLock); |
| 2567 isPsqEmpty = A_NETBUF_QUEUE_EMPTY(&conn->psq); |
| 2568 A_NETBUF_ENQUEUE(&conn->psq, skb); |
| 2569 A_MUTEX_UNLOCK(&conn->psqLock); |
| 2570 |
| 2571 /* If this is the first pkt getting queued |
| 2572 * for this STA, update the PVB for this STA |
| 2573 */ |
| 2574 if (isPsqEmpty) { |
| 2575 wmi_set_pvb_cmd(ar->arWmi, conn->aid, 1); |
| 2576 } |
| 2577 |
| 2578 return 0; |
| 2579 } else { |
| 2580 /* This tx is because of a PsPoll. Determine if |
| 2581 * MoreData bit has to be set |
| 2582 */ |
| 2583 A_MUTEX_LOCK(&conn->psqLock); |
| 2584 if (!A_NETBUF_QUEUE_EMPTY(&conn->psq)) { |
| 2585 bMoreData = TRUE; |
| 2586 } |
| 2587 A_MUTEX_UNLOCK(&conn->psqLock); |
| 2588 } |
| 2589 } |
| 2590 } else { |
| 2591 |
| 2592 /* non existent STA. drop the frame */ |
| 2593 A_NETBUF_FREE(skb); |
| 2594 return 0; |
| 2595 } |
| 2596 } |
| 2597 } |
| 2598 |
| 2599 if (ar->arWmiEnabled) { |
| 2600 #ifdef CONFIG_CHECKSUM_OFFLOAD |
| 2601 A_UINT8 csumStart=0; |
| 2602 A_UINT8 csumDest=0; |
| 2603 A_UINT8 csum=skb->ip_summed; |
| 2604 if(csumOffload && (csum==CHECKSUM_PARTIAL)){ |
| 2605 csumStart=skb->csum_start-(skb->network_header-skb->head)+si
zeof(ATH_LLC_SNAP_HDR); |
| 2606 csumDest=skb->csum_offset+csumStart; |
| 2607 } |
| 2608 #endif |
| 2609 if (A_NETBUF_HEADROOM(skb) < dev->hard_header_len - LINUX_HACK_FUDGE
_FACTOR) { |
| 2610 struct sk_buff *newbuf; |
| 2611 |
| 2612 /* |
| 2613 * We really should have gotten enough headroom but sometimes |
| 2614 * we still get packets with not enough headroom. Copy the pack
et. |
| 2615 */ |
| 2616 len = A_NETBUF_LEN(skb); |
| 2617 newbuf = A_NETBUF_ALLOC(len); |
| 2618 if (newbuf == NULL) { |
| 2619 break; |
| 2620 } |
| 2621 A_NETBUF_PUT(newbuf, len); |
| 2622 A_MEMCPY(A_NETBUF_DATA(newbuf), A_NETBUF_DATA(skb), len); |
| 2623 A_NETBUF_FREE(skb); |
| 2624 skb = newbuf; |
| 2625 /* fall through and assemble header */ |
| 2626 } |
| 2627 |
| 2628 if (dot11Hdr) { |
| 2629 if (wmi_dot11_hdr_add(ar->arWmi,skb,ar->arNetworkType) != A_OK)
{ |
| 2630 AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("ar6000_data_tx-wmi_dot11_hdr
_add failed\n")); |
| 2631 break; |
| 2632 } |
| 2633 } else { |
| 2634 if (wmi_dix_2_dot3(ar->arWmi, skb) != A_OK) { |
| 2635 AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("ar6000_data_tx - wmi_dix_2_d
ot3 failed\n")); |
| 2636 break; |
| 2637 } |
| 2638 } |
| 2639 #ifdef CONFIG_CHECKSUM_OFFLOAD |
| 2640 if(csumOffload && (csum ==CHECKSUM_PARTIAL)){ |
| 2641 WMI_TX_META_V2 metaV2; |
| 2642 metaV2.csumStart =csumStart; |
| 2643 metaV2.csumDest = csumDest; |
| 2644 metaV2.csumFlags = 0x1;/*instruct target to calculate checksum*/ |
| 2645 if (wmi_data_hdr_add(ar->arWmi, skb, DATA_MSGTYPE, bMoreData, do
t11Hdr, |
| 2646 WMI_META_VERSION_2,&metaV2) != A_OK) { |
| 2647 AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("ar6000_data_tx - wmi_data_hd
r_add failed\n")); |
| 2648 break; |
| 2649 } |
| 2650 |
| 2651 } |
| 2652 else |
| 2653 #endif |
| 2654 { |
| 2655 if (wmi_data_hdr_add(ar->arWmi, skb, DATA_MSGTYPE, bMoreData, do
t11Hdr,0,NULL) != A_OK) { |
| 2656 AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("ar6000_data_tx - wmi_data_hd
r_add failed\n")); |
| 2657 break; |
| 2658 } |
| 2659 } |
| 2660 |
| 2661 |
| 2662 if ((ar->arNetworkType == ADHOC_NETWORK) && |
| 2663 ar->arIbssPsEnable && ar->arConnected) { |
| 2664 /* flag to check adhoc mapping once we take the lock below:
*/ |
| 2665 checkAdHocPsMapping = TRUE; |
| 2666 |
| 2667 } else { |
| 2668 /* get the stream mapping */ |
| 2669 ac = wmi_implicit_create_pstream(ar->arWmi, skb, 0, ar->arWmmE
nabled); |
| 2670 } |
| 2671 |
| 2672 } else { |
| 2673 EPPING_HEADER *eppingHdr; |
| 2674 |
| 2675 eppingHdr = A_NETBUF_DATA(skb); |
| 2676 |
| 2677 if (IS_EPPING_PACKET(eppingHdr)) { |
| 2678 /* the stream ID is mapped to an access class */ |
| 2679 ac = eppingHdr->StreamNo_h; |
| 2680 /* some EPPING packets cannot be dropped no matter what acce
ss class it was |
| 2681 * sent on. We can change the packet tag to guarantee it wi
ll not get dropped */ |
| 2682 if (IS_EPING_PACKET_NO_DROP(eppingHdr)) { |
| 2683 htc_tag = AR6K_CONTROL_PKT_TAG; |
| 2684 } |
| 2685 |
| 2686 if (ac == HCI_TRANSPORT_STREAM_NUM) { |
| 2687 /* pass this to HCI */ |
| 2688 #ifndef EXPORT_HCI_BRIDGE_INTERFACE |
| 2689 if (A_SUCCESS(hci_test_send(ar,skb))) { |
| 2690 return 0; |
| 2691 } |
| 2692 #endif |
| 2693 /* set AC to discard this skb */ |
| 2694 ac = AC_NOT_MAPPED; |
| 2695 } |
| 2696 |
| 2697 } else { |
| 2698 /* not a ping packet, drop it */ |
| 2699 ac = AC_NOT_MAPPED; |
| 2700 } |
| 2701 } |
| 2702 |
| 2703 } while (FALSE); |
| 2704 |
| 2705 /* did we succeed ? */ |
| 2706 if ((ac == AC_NOT_MAPPED) && !checkAdHocPsMapping) { |
| 2707 /* cleanup and exit */ |
| 2708 A_NETBUF_FREE(skb); |
| 2709 AR6000_STAT_INC(ar, tx_dropped); |
| 2710 AR6000_STAT_INC(ar, tx_aborted_errors); |
| 2711 return 0; |
| 2712 } |
| 2713 |
| 2714 cookie = NULL; |
| 2715 |
| 2716 /* take the lock to protect driver data */ |
| 2717 AR6000_SPIN_LOCK(&ar->arLock, 0); |
| 2718 |
| 2719 do { |
| 2720 |
| 2721 if (checkAdHocPsMapping) { |
| 2722 eid = ar6000_ibss_map_epid(skb, dev, &mapNo); |
| 2723 }else { |
| 2724 eid = arAc2EndpointID (ar, ac); |
| 2725 } |
| 2726 /* validate that the endpoint is connected */ |
| 2727 if (eid == 0 || eid == ENDPOINT_UNUSED ) { |
| 2728 AR_DEBUG_PRINTF(ATH_DEBUG_ERR,(" eid %d is NOT mapped!\n", eid)); |
| 2729 break; |
| 2730 } |
| 2731 /* allocate resource for this packet */ |
| 2732 cookie = ar6000_alloc_cookie(ar); |
| 2733 |
| 2734 if (cookie != NULL) { |
| 2735 /* update counts while the lock is held */ |
| 2736 ar->arTxPending[eid]++; |
| 2737 ar->arTotalTxDataPending++; |
| 2738 } |
| 2739 |
| 2740 } while (FALSE); |
| 2741 |
| 2742 AR6000_SPIN_UNLOCK(&ar->arLock, 0); |
| 2743 |
| 2744 if (cookie != NULL) { |
| 2745 cookie->arc_bp[0] = (A_UINT32)skb; |
| 2746 cookie->arc_bp[1] = mapNo; |
| 2747 SET_HTC_PACKET_INFO_TX(&cookie->HtcPkt, |
| 2748 cookie, |
| 2749 A_NETBUF_DATA(skb), |
| 2750 A_NETBUF_LEN(skb), |
| 2751 eid, |
| 2752 htc_tag); |
| 2753 |
| 2754 #ifdef DEBUG |
| 2755 if (debugdriver >= 3) { |
| 2756 ar6000_dump_skb(skb); |
| 2757 } |
| 2758 #endif |
| 2759 #ifdef HTC_TEST_SEND_PKTS |
| 2760 DoHTCSendPktsTest(ar,mapNo,eid,skb); |
| 2761 #endif |
| 2762 /* HTC interface is asynchronous, if this fails, cleanup will happen
in |
| 2763 * the ar6000_tx_complete callback */ |
| 2764 HTCSendPkt(ar->arHtcTarget, &cookie->HtcPkt); |
| 2765 } else { |
| 2766 /* no packet to send, cleanup */ |
| 2767 A_NETBUF_FREE(skb); |
| 2768 AR6000_STAT_INC(ar, tx_dropped); |
| 2769 AR6000_STAT_INC(ar, tx_aborted_errors); |
| 2770 } |
| 2771 |
| 2772 return 0; |
| 2773 } |
| 2774 |
| 2775 int |
| 2776 ar6000_acl_data_tx(struct sk_buff *skb, struct net_device *dev) |
| 2777 { |
| 2778 AR_SOFTC_T *ar = (AR_SOFTC_T *)ar6k_priv(dev); |
| 2779 struct ar_cookie *cookie; |
| 2780 HTC_ENDPOINT_ID eid = ENDPOINT_UNUSED; |
| 2781 |
| 2782 cookie = NULL; |
| 2783 AR6000_SPIN_LOCK(&ar->arLock, 0); |
| 2784 |
| 2785 /* For now we send ACL on BE endpoint: We can also have a dedicated EP *
/ |
| 2786 eid = arAc2EndpointID (ar, 0); |
| 2787 /* allocate resource for this packet */ |
| 2788 cookie = ar6000_alloc_cookie(ar); |
| 2789 |
| 2790 if (cookie != NULL) { |
| 2791 /* update counts while the lock is held */ |
| 2792 ar->arTxPending[eid]++; |
| 2793 ar->arTotalTxDataPending++; |
| 2794 } |
| 2795 |
| 2796 |
| 2797 AR6000_SPIN_UNLOCK(&ar->arLock, 0); |
| 2798 |
| 2799 if (cookie != NULL) { |
| 2800 cookie->arc_bp[0] = (A_UINT32)skb; |
| 2801 cookie->arc_bp[1] = 0; |
| 2802 SET_HTC_PACKET_INFO_TX(&cookie->HtcPkt, |
| 2803 cookie, |
| 2804 A_NETBUF_DATA(skb), |
| 2805 A_NETBUF_LEN(skb), |
| 2806 eid, |
| 2807 AR6K_DATA_PKT_TAG); |
| 2808 |
| 2809 /* HTC interface is asynchronous, if this fails, cleanup will happen
in |
| 2810 * the ar6000_tx_complete callback */ |
| 2811 HTCSendPkt(ar->arHtcTarget, &cookie->HtcPkt); |
| 2812 } else { |
| 2813 /* no packet to send, cleanup */ |
| 2814 A_NETBUF_FREE(skb); |
| 2815 AR6000_STAT_INC(ar, tx_dropped); |
| 2816 AR6000_STAT_INC(ar, tx_aborted_errors); |
| 2817 } |
| 2818 return 0; |
| 2819 } |
| 2820 |
| 2821 |
| 2822 #ifdef ADAPTIVE_POWER_THROUGHPUT_CONTROL |
| 2823 static void |
| 2824 tvsub(register struct timeval *out, register struct timeval *in) |
| 2825 { |
| 2826 if((out->tv_usec -= in->tv_usec) < 0) { |
| 2827 out->tv_sec--; |
| 2828 out->tv_usec += 1000000; |
| 2829 } |
| 2830 out->tv_sec -= in->tv_sec; |
| 2831 } |
| 2832 |
| 2833 void |
| 2834 applyAPTCHeuristics(AR_SOFTC_T *ar) |
| 2835 { |
| 2836 A_UINT32 duration; |
| 2837 A_UINT32 numbytes; |
| 2838 A_UINT32 throughput; |
| 2839 struct timeval ts; |
| 2840 A_STATUS status; |
| 2841 |
| 2842 AR6000_SPIN_LOCK(&ar->arLock, 0); |
| 2843 |
| 2844 if ((enableAPTCHeuristics) && (!aptcTR.timerScheduled)) { |
| 2845 do_gettimeofday(&ts); |
| 2846 tvsub(&ts, &aptcTR.samplingTS); |
| 2847 duration = ts.tv_sec * 1000 + ts.tv_usec / 1000; /* ms */ |
| 2848 numbytes = aptcTR.bytesTransmitted + aptcTR.bytesReceived; |
| 2849 |
| 2850 if (duration > APTC_TRAFFIC_SAMPLING_INTERVAL) { |
| 2851 /* Initialize the time stamp and byte count */ |
| 2852 aptcTR.bytesTransmitted = aptcTR.bytesReceived = 0; |
| 2853 do_gettimeofday(&aptcTR.samplingTS); |
| 2854 |
| 2855 /* Calculate and decide based on throughput thresholds */ |
| 2856 throughput = ((numbytes * 8) / duration); |
| 2857 if (throughput > APTC_UPPER_THROUGHPUT_THRESHOLD) { |
| 2858 /* Disable Sleep and schedule a timer */ |
| 2859 A_ASSERT(ar->arWmiReady == TRUE); |
| 2860 AR6000_SPIN_UNLOCK(&ar->arLock, 0); |
| 2861 status = wmi_powermode_cmd(ar->arWmi, MAX_PERF_POWER); |
| 2862 AR6000_SPIN_LOCK(&ar->arLock, 0); |
| 2863 A_TIMEOUT_MS(&aptcTimer, APTC_TRAFFIC_SAMPLING_INTERVAL, 0); |
| 2864 aptcTR.timerScheduled = TRUE; |
| 2865 } |
| 2866 } |
| 2867 } |
| 2868 |
| 2869 AR6000_SPIN_UNLOCK(&ar->arLock, 0); |
| 2870 } |
| 2871 #endif /* ADAPTIVE_POWER_THROUGHPUT_CONTROL */ |
| 2872 |
| 2873 static HTC_SEND_FULL_ACTION ar6000_tx_queue_full(void *Context, HTC_PACKET *pPac
ket) |
| 2874 { |
| 2875 AR_SOFTC_T *ar = (AR_SOFTC_T *)Context; |
| 2876 HTC_SEND_FULL_ACTION action = HTC_SEND_FULL_KEEP; |
| 2877 A_BOOL stopNet = FALSE; |
| 2878 HTC_ENDPOINT_ID Endpoint = HTC_GET_ENDPOINT_FROM_PKT(pPacket); |
| 2879 |
| 2880 do { |
| 2881 |
| 2882 if (bypasswmi) { |
| 2883 int accessClass; |
| 2884 |
| 2885 if (HTC_GET_TAG_FROM_PKT(pPacket) == AR6K_CONTROL_PKT_TAG) { |
| 2886 /* don't drop special control packets */ |
| 2887 break; |
| 2888 } |
| 2889 |
| 2890 accessClass = arEndpoint2Ac(ar,Endpoint); |
| 2891 /* for endpoint ping testing drop Best Effort and Background */ |
| 2892 if ((accessClass == WMM_AC_BE) || (accessClass == WMM_AC_BK)) { |
| 2893 action = HTC_SEND_FULL_DROP; |
| 2894 stopNet = FALSE; |
| 2895 } else { |
| 2896 /* keep but stop the netqueues */ |
| 2897 stopNet = TRUE; |
| 2898 } |
| 2899 break; |
| 2900 } |
| 2901 |
| 2902 if (Endpoint == ar->arControlEp) { |
| 2903 /* under normal WMI if this is getting full, then something is r
unning rampant |
| 2904 * the host should not be exhausting the WMI queue with too many
commands |
| 2905 * the only exception to this is during testing using endpointpi
ng */ |
| 2906 AR6000_SPIN_LOCK(&ar->arLock, 0); |
| 2907 /* set flag to handle subsequent messages */ |
| 2908 ar->arWMIControlEpFull = TRUE; |
| 2909 AR6000_SPIN_UNLOCK(&ar->arLock, 0); |
| 2910 AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("WMI Control Endpoint is FULL!!! \n")
); |
| 2911 /* no need to stop the network */ |
| 2912 stopNet = FALSE; |
| 2913 break; |
| 2914 } |
| 2915 |
| 2916 /* if we get here, we are dealing with data endpoints getting full */ |
| 2917 |
| 2918 if (HTC_GET_TAG_FROM_PKT(pPacket) == AR6K_CONTROL_PKT_TAG) { |
| 2919 /* don't drop control packets issued on ANY data endpoint */ |
| 2920 break; |
| 2921 } |
| 2922 |
| 2923 if (ar->arNetworkType == ADHOC_NETWORK) { |
| 2924 /* in adhoc mode, we cannot differentiate traffic priorities so ther
e is no need to |
| 2925 * continue, however we should stop the network */ |
| 2926 stopNet = TRUE; |
| 2927 break; |
| 2928 } |
| 2929 /* the last MAX_HI_COOKIE_NUM "batch" of cookies are reserved for the hi
ghest |
| 2930 * active stream */ |
| 2931 if (ar->arAcStreamPriMap[arEndpoint2Ac(ar,Endpoint)] < ar->arHiAcStreamA
ctivePri && |
| 2932 ar->arCookieCount <= MAX_HI_COOKIE_NUM) { |
| 2933 /* this stream's priority is less than the highest active priori
ty, we |
| 2934 * give preference to the highest priority stream by directing |
| 2935 * HTC to drop the packet that overflowed */ |
| 2936 action = HTC_SEND_FULL_DROP; |
| 2937 /* since we are dropping packets, no need to stop the network */ |
| 2938 stopNet = FALSE; |
| 2939 break; |
| 2940 } |
| 2941 |
| 2942 } while (FALSE); |
| 2943 |
| 2944 if (stopNet) { |
| 2945 AR6000_SPIN_LOCK(&ar->arLock, 0); |
| 2946 ar->arNetQueueStopped = TRUE; |
| 2947 AR6000_SPIN_UNLOCK(&ar->arLock, 0); |
| 2948 /* one of the data endpoints queues is getting full..need to stop networ
k stack |
| 2949 * the queue will resume in ar6000_tx_complete() */ |
| 2950 netif_stop_queue(ar->arNetDev); |
| 2951 } |
| 2952 |
| 2953 return action; |
| 2954 } |
| 2955 |
| 2956 |
| 2957 static void |
| 2958 ar6000_tx_complete(void *Context, HTC_PACKET_QUEUE *pPacketQueue) |
| 2959 { |
| 2960 AR_SOFTC_T *ar = (AR_SOFTC_T *)Context; |
| 2961 A_UINT32 mapNo = 0; |
| 2962 A_STATUS status; |
| 2963 struct ar_cookie * ar_cookie; |
| 2964 HTC_ENDPOINT_ID eid; |
| 2965 A_BOOL wakeEvent = FALSE; |
| 2966 struct sk_buff_head skb_queue; |
| 2967 HTC_PACKET *pPacket; |
| 2968 struct sk_buff *pktSkb; |
| 2969 A_BOOL flushing = FALSE; |
| 2970 |
| 2971 skb_queue_head_init(&skb_queue); |
| 2972 |
| 2973 /* lock the driver as we update internal state */ |
| 2974 AR6000_SPIN_LOCK(&ar->arLock, 0); |
| 2975 |
| 2976 /* reap completed packets */ |
| 2977 while (!HTC_QUEUE_EMPTY(pPacketQueue)) { |
| 2978 |
| 2979 pPacket = HTC_PACKET_DEQUEUE(pPacketQueue); |
| 2980 |
| 2981 ar_cookie = (struct ar_cookie *)pPacket->pPktContext; |
| 2982 A_ASSERT(ar_cookie); |
| 2983 |
| 2984 status = pPacket->Status; |
| 2985 pktSkb = (struct sk_buff *)ar_cookie->arc_bp[0]; |
| 2986 eid = pPacket->Endpoint; |
| 2987 mapNo = ar_cookie->arc_bp[1]; |
| 2988 |
| 2989 A_ASSERT(pktSkb); |
| 2990 A_ASSERT(pPacket->pBuffer == A_NETBUF_DATA(pktSkb)); |
| 2991 |
| 2992 /* add this to the list, use faster non-lock API */ |
| 2993 __skb_queue_tail(&skb_queue,pktSkb); |
| 2994 |
| 2995 if (A_SUCCESS(status)) { |
| 2996 A_ASSERT(pPacket->ActualLength == A_NETBUF_LEN(pktSkb)); |
| 2997 } |
| 2998 |
| 2999 AR_DEBUG_PRINTF(ATH_DEBUG_WLAN_TX,("ar6000_tx_complete skb=0x%x data=0x%
x len=0x%x eid=%d ", |
| 3000 (A_UINT32)pktSkb, (A_UINT32)pPacket->pBuffer, |
| 3001 pPacket->ActualLength, |
| 3002 eid)); |
| 3003 |
| 3004 ar->arTxPending[eid]--; |
| 3005 |
| 3006 if ((eid != ar->arControlEp) || bypasswmi) { |
| 3007 ar->arTotalTxDataPending--; |
| 3008 } |
| 3009 |
| 3010 if (eid == ar->arControlEp) |
| 3011 { |
| 3012 if (ar->arWMIControlEpFull) { |
| 3013 /* since this packet completed, the WMI EP is no longer full
*/ |
| 3014 ar->arWMIControlEpFull = FALSE; |
| 3015 } |
| 3016 |
| 3017 if (ar->arTxPending[eid] == 0) { |
| 3018 wakeEvent = TRUE; |
| 3019 } |
| 3020 } |
| 3021 |
| 3022 if (A_FAILED(status)) { |
| 3023 if (status == A_ECANCELED) { |
| 3024 /* a packet was flushed */ |
| 3025 flushing = TRUE; |
| 3026 } |
| 3027 AR6000_STAT_INC(ar, tx_errors); |
| 3028 if (status != A_NO_RESOURCE) { |
| 3029 AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("%s() -TX ERROR, status: 0x%x\n",
__func__, |
| 3030 status)); |
| 3031 } |
| 3032 } else { |
| 3033 AR_DEBUG_PRINTF(ATH_DEBUG_WLAN_TX,("OK\n")); |
| 3034 flushing = FALSE; |
| 3035 AR6000_STAT_INC(ar, tx_packets); |
| 3036 ar->arNetStats.tx_bytes += A_NETBUF_LEN(pktSkb); |
| 3037 #ifdef ADAPTIVE_POWER_THROUGHPUT_CONTROL |
| 3038 aptcTR.bytesTransmitted += a_netbuf_to_len(pktSkb); |
| 3039 applyAPTCHeuristics(ar); |
| 3040 #endif /* ADAPTIVE_POWER_THROUGHPUT_CONTROL */ |
| 3041 } |
| 3042 |
| 3043 // TODO this needs to be looked at |
| 3044 if ((ar->arNetworkType == ADHOC_NETWORK) && ar->arIbssPsEnable |
| 3045 && (eid != ar->arControlEp) && mapNo) |
| 3046 { |
| 3047 mapNo --; |
| 3048 ar->arNodeMap[mapNo].txPending --; |
| 3049 |
| 3050 if (!ar->arNodeMap[mapNo].txPending && (mapNo == (ar->arNodeNum - 1)
)) { |
| 3051 A_UINT32 i; |
| 3052 for (i = ar->arNodeNum; i > 0; i --) { |
| 3053 if (!ar->arNodeMap[i - 1].txPending) { |
| 3054 A_MEMZERO(&ar->arNodeMap[i - 1], sizeof(struct ar_node_m
apping)); |
| 3055 ar->arNodeNum --; |
| 3056 } else { |
| 3057 break; |
| 3058 } |
| 3059 } |
| 3060 } |
| 3061 } |
| 3062 |
| 3063 ar6000_free_cookie(ar, ar_cookie); |
| 3064 |
| 3065 if (ar->arNetQueueStopped) { |
| 3066 ar->arNetQueueStopped = FALSE; |
| 3067 } |
| 3068 } |
| 3069 |
| 3070 AR6000_SPIN_UNLOCK(&ar->arLock, 0); |
| 3071 |
| 3072 /* lock is released, we can freely call other kernel APIs */ |
| 3073 |
| 3074 /* free all skbs in our local list */ |
| 3075 while (!skb_queue_empty(&skb_queue)) { |
| 3076 /* use non-lock version */ |
| 3077 pktSkb = __skb_dequeue(&skb_queue); |
| 3078 A_NETBUF_FREE(pktSkb); |
| 3079 } |
| 3080 |
| 3081 if ((ar->arConnected == TRUE) || (bypasswmi)) { |
| 3082 if (!flushing) { |
| 3083 /* don't wake the queue if we are flushing, other wise it will j
ust |
| 3084 * keep queueing packets, which will keep failing */ |
| 3085 netif_wake_queue(ar->arNetDev); |
| 3086 } |
| 3087 } |
| 3088 |
| 3089 if (wakeEvent) { |
| 3090 wake_up(&arEvent); |
| 3091 } |
| 3092 |
| 3093 } |
| 3094 |
| 3095 sta_t * |
| 3096 ieee80211_find_conn(AR_SOFTC_T *ar, A_UINT8 *node_addr) |
| 3097 { |
| 3098 sta_t *conn = NULL; |
| 3099 A_UINT8 i, max_conn; |
| 3100 |
| 3101 switch(ar->arNetworkType) { |
| 3102 case AP_NETWORK: |
| 3103 max_conn = AP_MAX_NUM_STA; |
| 3104 break; |
| 3105 default: |
| 3106 max_conn=0; |
| 3107 break; |
| 3108 } |
| 3109 |
| 3110 for (i = 0; i < max_conn; i++) { |
| 3111 if (IEEE80211_ADDR_EQ(node_addr, ar->sta_list[i].mac)) { |
| 3112 conn = &ar->sta_list[i]; |
| 3113 break; |
| 3114 } |
| 3115 } |
| 3116 |
| 3117 return conn; |
| 3118 } |
| 3119 |
| 3120 sta_t *ieee80211_find_conn_for_aid(AR_SOFTC_T *ar, A_UINT8 aid) |
| 3121 { |
| 3122 sta_t *conn = NULL; |
| 3123 A_UINT8 ctr; |
| 3124 |
| 3125 for (ctr = 0; ctr < AP_MAX_NUM_STA; ctr++) { |
| 3126 if (ar->sta_list[ctr].aid == aid) { |
| 3127 conn = &ar->sta_list[ctr]; |
| 3128 break; |
| 3129 } |
| 3130 } |
| 3131 return conn; |
| 3132 } |
| 3133 |
| 3134 /* |
| 3135 * Receive event handler. This is called by HTC when a packet is received |
| 3136 */ |
| 3137 int pktcount; |
| 3138 static void |
| 3139 ar6000_rx(void *Context, HTC_PACKET *pPacket) |
| 3140 { |
| 3141 AR_SOFTC_T *ar = (AR_SOFTC_T *)Context; |
| 3142 struct sk_buff *skb = (struct sk_buff *)pPacket->pPktContext; |
| 3143 int minHdrLen; |
| 3144 A_UINT8 containsDot11Hdr = 0; |
| 3145 A_STATUS status = pPacket->Status; |
| 3146 HTC_ENDPOINT_ID ept = pPacket->Endpoint; |
| 3147 |
| 3148 A_ASSERT((status != A_OK) || |
| 3149 (pPacket->pBuffer == (A_NETBUF_DATA(skb) + HTC_HEADER_LEN))); |
| 3150 |
| 3151 AR_DEBUG_PRINTF(ATH_DEBUG_WLAN_RX,("ar6000_rx ar=0x%x eid=%d, skb=0x%x, data
=0x%x, len=0x%x status:%d", |
| 3152 (A_UINT32)ar, ept, (A_UINT32)skb, (A_UINT32)pPacket->pBuffer
, |
| 3153 pPacket->ActualLength, status)); |
| 3154 if (status != A_OK) { |
| 3155 if (status != A_ECANCELED) { |
| 3156 AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("RX ERR (%d) \n",status)); |
| 3157 } |
| 3158 } |
| 3159 |
| 3160 /* take lock to protect buffer counts |
| 3161 * and adaptive power throughput state */ |
| 3162 AR6000_SPIN_LOCK(&ar->arLock, 0); |
| 3163 |
| 3164 if (A_SUCCESS(status)) { |
| 3165 AR6000_STAT_INC(ar, rx_packets); |
| 3166 ar->arNetStats.rx_bytes += pPacket->ActualLength; |
| 3167 #ifdef ADAPTIVE_POWER_THROUGHPUT_CONTROL |
| 3168 aptcTR.bytesReceived += a_netbuf_to_len(skb); |
| 3169 applyAPTCHeuristics(ar); |
| 3170 #endif /* ADAPTIVE_POWER_THROUGHPUT_CONTROL */ |
| 3171 |
| 3172 A_NETBUF_PUT(skb, pPacket->ActualLength + HTC_HEADER_LEN); |
| 3173 A_NETBUF_PULL(skb, HTC_HEADER_LEN); |
| 3174 |
| 3175 #ifdef DEBUG |
| 3176 if (debugdriver >= 2) { |
| 3177 ar6000_dump_skb(skb); |
| 3178 } |
| 3179 #endif /* DEBUG */ |
| 3180 } |
| 3181 |
| 3182 AR6000_SPIN_UNLOCK(&ar->arLock, 0); |
| 3183 |
| 3184 skb->dev = ar->arNetDev; |
| 3185 if (status != A_OK) { |
| 3186 AR6000_STAT_INC(ar, rx_errors); |
| 3187 A_NETBUF_FREE(skb); |
| 3188 } else if (ar->arWmiEnabled == TRUE) { |
| 3189 if (ept == ar->arControlEp) { |
| 3190 /* |
| 3191 * this is a wmi control msg |
| 3192 */ |
| 3193 wmi_control_rx(ar->arWmi, skb); |
| 3194 } else { |
| 3195 WMI_DATA_HDR *dhdr = (WMI_DATA_HDR *)A_NETBUF_DATA(skb); |
| 3196 A_UINT8 is_amsdu, tid, is_acl_data_frame; |
| 3197 is_acl_data_frame = WMI_DATA_HDR_GET_DATA_TYPE(dhdr) == WMI_DATA
_HDR_DATA_TYPE_ACL; |
| 3198 |
| 3199 /* |
| 3200 * this is a wmi data packet |
| 3201 */ |
| 3202 // NWF |
| 3203 |
| 3204 if (processDot11Hdr) { |
| 3205 minHdrLen = sizeof(WMI_DATA_HDR) + sizeof(struct ieee80211_f
rame) + sizeof(ATH_LLC_SNAP_HDR); |
| 3206 } else { |
| 3207 minHdrLen = sizeof (WMI_DATA_HDR) + sizeof(ATH_MAC_HDR) + |
| 3208 sizeof(ATH_LLC_SNAP_HDR); |
| 3209 } |
| 3210 |
| 3211 /* In the case of AP mode we may receive NULL data frames |
| 3212 * that do not have LLC hdr. They are 16 bytes in size. |
| 3213 * Allow these frames in the AP mode. |
| 3214 * ACL data frames don't follow ethernet frame bounds for |
| 3215 * min length |
| 3216 */ |
| 3217 if (ar->arNetworkType != AP_NETWORK && !is_acl_data_frame && |
| 3218 ((pPacket->ActualLength < minHdrLen) || |
| 3219 (pPacket->ActualLength > AR6000_MAX_RX_MESSAGE_SIZE))) |
| 3220 { |
| 3221 /* |
| 3222 * packet is too short or too long |
| 3223 */ |
| 3224 AR_DEBUG_PRINTF(ATH_DEBUG_INFO,("TOO SHORT or TOO LONG\n")); |
| 3225 AR6000_STAT_INC(ar, rx_errors); |
| 3226 AR6000_STAT_INC(ar, rx_length_errors); |
| 3227 A_NETBUF_FREE(skb); |
| 3228 } else { |
| 3229 A_UINT16 seq_no; |
| 3230 A_UINT8 meta_type; |
| 3231 |
| 3232 #if 0 |
| 3233 /* Access RSSI values here */ |
| 3234 AR_DEBUG_PRINTF(ATH_DEBUG_INFO,("RSSI %d\n", |
| 3235 ((WMI_DATA_HDR *) A_NETBUF_DATA(skb))->rssi)); |
| 3236 #endif |
| 3237 /* Get the Power save state of the STA */ |
| 3238 if (ar->arNetworkType == AP_NETWORK) { |
| 3239 sta_t *conn = NULL; |
| 3240 A_UINT8 psState=0,prevPsState; |
| 3241 ATH_MAC_HDR *datap=NULL; |
| 3242 A_UINT16 offset; |
| 3243 |
| 3244 meta_type = WMI_DATA_HDR_GET_META(dhdr); |
| 3245 |
| 3246 psState = (((WMI_DATA_HDR *)A_NETBUF_DATA(skb))->info |
| 3247 >> WMI_DATA_HDR_PS_SHIFT) & WMI_DATA_HDR_PS
_MASK; |
| 3248 |
| 3249 offset = sizeof(WMI_DATA_HDR); |
| 3250 |
| 3251 switch (meta_type) { |
| 3252 case 0: |
| 3253 break; |
| 3254 case WMI_META_VERSION_1: |
| 3255 offset += sizeof(WMI_RX_META_V1); |
| 3256 break; |
| 3257 #ifdef CONFIG_CHECKSUM_OFFLOAD |
| 3258 case WMI_META_VERSION_2: |
| 3259 offset += sizeof(WMI_RX_META_V2); |
| 3260 break; |
| 3261 #endif |
| 3262 default: |
| 3263 break; |
| 3264 } |
| 3265 |
| 3266 datap = (ATH_MAC_HDR *)(A_NETBUF_DATA(skb)+offset); |
| 3267 conn = ieee80211_find_conn(ar, datap->srcMac); |
| 3268 |
| 3269 if (conn) { |
| 3270 /* if there is a change in PS state of the STA, |
| 3271 * take appropriate steps. |
| 3272 * 1. If Sleep-->Awake, flush the psq for the STA |
| 3273 * Clear the PVB for the STA. |
| 3274 * 2. If Awake-->Sleep, Starting queueing frames |
| 3275 * the STA. |
| 3276 */ |
| 3277 prevPsState = STA_IS_PWR_SLEEP(conn); |
| 3278 if (psState) { |
| 3279 STA_SET_PWR_SLEEP(conn); |
| 3280 } else { |
| 3281 STA_CLR_PWR_SLEEP(conn); |
| 3282 } |
| 3283 |
| 3284 if (prevPsState ^ STA_IS_PWR_SLEEP(conn)) { |
| 3285 |
| 3286 if (!STA_IS_PWR_SLEEP(conn)) { |
| 3287 |
| 3288 A_MUTEX_LOCK(&conn->psqLock); |
| 3289 while (!A_NETBUF_QUEUE_EMPTY(&conn->psq)) { |
| 3290 struct sk_buff *skb=NULL; |
| 3291 |
| 3292 skb = A_NETBUF_DEQUEUE(&conn->psq); |
| 3293 A_MUTEX_UNLOCK(&conn->psqLock); |
| 3294 ar6000_data_tx(skb,ar->arNetDev); |
| 3295 A_MUTEX_LOCK(&conn->psqLock); |
| 3296 } |
| 3297 A_MUTEX_UNLOCK(&conn->psqLock); |
| 3298 /* Clear the PVB for this STA */ |
| 3299 wmi_set_pvb_cmd(ar->arWmi, conn->aid, 0); |
| 3300 } |
| 3301 } |
| 3302 } else { |
| 3303 /* This frame is from a STA that is not associated*/ |
| 3304 A_ASSERT(FALSE); |
| 3305 } |
| 3306 |
| 3307 /* Drop NULL data frames here */ |
| 3308 if((pPacket->ActualLength < minHdrLen) || |
| 3309 (pPacket->ActualLength > AR6000_MAX_RX_MESSAGE_S
IZE)) { |
| 3310 A_NETBUF_FREE(skb); |
| 3311 goto rx_done; |
| 3312 } |
| 3313 } |
| 3314 |
| 3315 is_amsdu = WMI_DATA_HDR_IS_AMSDU(dhdr); |
| 3316 tid = WMI_DATA_HDR_GET_UP(dhdr); |
| 3317 seq_no = WMI_DATA_HDR_GET_SEQNO(dhdr); |
| 3318 meta_type = WMI_DATA_HDR_GET_META(dhdr); |
| 3319 containsDot11Hdr = WMI_DATA_HDR_GET_DOT11(dhdr); |
| 3320 |
| 3321 wmi_data_hdr_remove(ar->arWmi, skb); |
| 3322 |
| 3323 switch (meta_type) { |
| 3324 case WMI_META_VERSION_1: |
| 3325 { |
| 3326 WMI_RX_META_V1 *pMeta = (WMI_RX_META_V1 *)A_NETB
UF_DATA(skb); |
| 3327 A_PRINTF("META %d %d %d %d %x\n", pMeta->status,
pMeta->rix, pMeta->rssi, pMeta->channel, pMeta->flags); |
| 3328 A_NETBUF_PULL((void*)skb, sizeof(WMI_RX_META_V1)
); |
| 3329 break; |
| 3330 } |
| 3331 #ifdef CONFIG_CHECKSUM_OFFLOAD |
| 3332 case WMI_META_VERSION_2: |
| 3333 { |
| 3334 WMI_RX_META_V2 *pMeta = (WMI_RX_META_V2 *)A_NETB
UF_DATA(skb); |
| 3335 if(pMeta->csumFlags & 0x1){ |
| 3336 skb->ip_summed=CHECKSUM_COMP
LETE; |
| 3337 skb->csum=(pMeta->csum); |
| 3338 } |
| 3339 A_NETBUF_PULL((void*)skb, sizeof(WMI_RX_META_V2)
); |
| 3340 break; |
| 3341 } |
| 3342 #endif |
| 3343 default: |
| 3344 break; |
| 3345 } |
| 3346 /* NWF: print the 802.11 hdr bytes */ |
| 3347 if(containsDot11Hdr) { |
| 3348 wmi_dot11_hdr_remove(ar->arWmi,skb); |
| 3349 } else if(!is_amsdu && !is_acl_data_frame) { |
| 3350 wmi_dot3_2_dix(skb); |
| 3351 } |
| 3352 |
| 3353 if (is_acl_data_frame) { |
| 3354 A_NETBUF_PUSH(skb, sizeof(int)); |
| 3355 *((short *)A_NETBUF_DATA(skb)) = WMI_ACL_DATA_EVENTID; |
| 3356 } |
| 3357 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0) |
| 3358 /* |
| 3359 * extra push and memcpy, for eth_type_trans() of 2.4 kernel |
| 3360 * will pull out hard_header_len bytes of the skb. |
| 3361 */ |
| 3362 A_NETBUF_PUSH(skb, sizeof(WMI_DATA_HDR) + sizeof(ATH_LLC_SNA
P_HDR) + HTC_HEADER_LEN); |
| 3363 A_MEMCPY(A_NETBUF_DATA(skb), A_NETBUF_DATA(skb) + sizeof(WMI
_DATA_HDR) + |
| 3364 sizeof(ATH_LLC_SNAP_HDR) + HTC_HEADER_LEN, sizeof(A
TH_MAC_HDR)); |
| 3365 #endif |
| 3366 if ((ar->arNetDev->flags & IFF_UP) == IFF_UP) { |
| 3367 if (ar->arNetworkType == AP_NETWORK) { |
| 3368 struct sk_buff *skb1 = NULL; |
| 3369 ATH_MAC_HDR *datap; |
| 3370 |
| 3371 datap = (ATH_MAC_HDR *)A_NETBUF_DATA(skb); |
| 3372 if (IEEE80211_IS_MULTICAST(datap->dstMac)) { |
| 3373 /* Bcast/Mcast frames should be sent to the OS |
| 3374 * stack as well as on the air. |
| 3375 */ |
| 3376 skb1 = skb_copy(skb,GFP_ATOMIC); |
| 3377 } else { |
| 3378 /* Search for a connected STA with dstMac as |
| 3379 * the Mac address. If found send the frame to |
| 3380 * it on the air else send the frame up the |
| 3381 * stack |
| 3382 */ |
| 3383 sta_t *conn = NULL; |
| 3384 conn = ieee80211_find_conn(ar, datap->dstMac); |
| 3385 |
| 3386 if (conn && ar->intra_bss) { |
| 3387 skb1 = skb; |
| 3388 skb = NULL; |
| 3389 } else if(conn && !ar->intra_bss) { |
| 3390 A_NETBUF_FREE(skb); |
| 3391 skb = NULL; |
| 3392 } |
| 3393 } |
| 3394 if (skb1) { |
| 3395 ar6000_data_tx(skb1, ar->arNetDev); |
| 3396 } |
| 3397 } |
| 3398 } |
| 3399 #ifdef ATH_AR6K_11N_SUPPORT |
| 3400 aggr_process_recv_frm(ar->aggr_cntxt, tid, seq_no, is_amsdu,
(void **)&skb); |
| 3401 #endif |
| 3402 ar6000_deliver_frames_to_nw_stack((void *) ar->arNetDev, (vo
id *)skb); |
| 3403 } |
| 3404 } |
| 3405 } else { |
| 3406 ar6000_deliver_frames_to_nw_stack((void *)ar->arNetDev, (void *)skb); |
| 3407 } |
| 3408 |
| 3409 rx_done: |
| 3410 |
| 3411 return; |
| 3412 } |
| 3413 |
| 3414 static void |
| 3415 ar6000_deliver_frames_to_nw_stack(void *dev, void *osbuf) |
| 3416 { |
| 3417 struct sk_buff *skb = (struct sk_buff *)osbuf; |
| 3418 |
| 3419 if(skb) { |
| 3420 skb->dev = dev; |
| 3421 if ((skb->dev->flags & IFF_UP) == IFF_UP) { |
| 3422 skb->protocol = eth_type_trans(skb, skb->dev); |
| 3423 netif_rx(skb); |
| 3424 } else { |
| 3425 A_NETBUF_FREE(skb); |
| 3426 } |
| 3427 } |
| 3428 } |
| 3429 |
| 3430 #if 0 |
| 3431 static void |
| 3432 ar6000_deliver_frames_to_bt_stack(void *dev, void *osbuf) |
| 3433 { |
| 3434 struct sk_buff *skb = (struct sk_buff *)osbuf; |
| 3435 |
| 3436 if(skb) { |
| 3437 skb->dev = dev; |
| 3438 if ((skb->dev->flags & IFF_UP) == IFF_UP) { |
| 3439 skb->protocol = htons(ETH_P_CONTROL); |
| 3440 netif_rx(skb); |
| 3441 } else { |
| 3442 A_NETBUF_FREE(skb); |
| 3443 } |
| 3444 } |
| 3445 } |
| 3446 #endif |
| 3447 |
| 3448 static void |
| 3449 ar6000_rx_refill(void *Context, HTC_ENDPOINT_ID Endpoint) |
| 3450 { |
| 3451 AR_SOFTC_T *ar = (AR_SOFTC_T *)Context; |
| 3452 void *osBuf; |
| 3453 int RxBuffers; |
| 3454 int buffersToRefill; |
| 3455 HTC_PACKET *pPacket; |
| 3456 HTC_PACKET_QUEUE queue; |
| 3457 |
| 3458 buffersToRefill = (int)AR6000_MAX_RX_BUFFERS - |
| 3459 HTCGetNumRecvBuffers(ar->arHtcTarget, Endpoi
nt); |
| 3460 |
| 3461 if (buffersToRefill <= 0) { |
| 3462 /* fast return, nothing to fill */ |
| 3463 return; |
| 3464 } |
| 3465 |
| 3466 INIT_HTC_PACKET_QUEUE(&queue); |
| 3467 |
| 3468 AR_DEBUG_PRINTF(ATH_DEBUG_WLAN_RX,("ar6000_rx_refill: providing htc with %d
buffers at eid=%d\n", |
| 3469 buffersToRefill, Endpoint)); |
| 3470 |
| 3471 for (RxBuffers = 0; RxBuffers < buffersToRefill; RxBuffers++) { |
| 3472 osBuf = A_NETBUF_ALLOC(AR6000_BUFFER_SIZE); |
| 3473 if (NULL == osBuf) { |
| 3474 break; |
| 3475 } |
| 3476 /* the HTC packet wrapper is at the head of the reserved area |
| 3477 * in the skb */ |
| 3478 pPacket = (HTC_PACKET *)(A_NETBUF_HEAD(osBuf)); |
| 3479 /* set re-fill info */ |
| 3480 SET_HTC_PACKET_INFO_RX_REFILL(pPacket,osBuf,A_NETBUF_DATA(osBuf),AR6000_
BUFFER_SIZE,Endpoint); |
| 3481 /* add to queue */ |
| 3482 HTC_PACKET_ENQUEUE(&queue,pPacket); |
| 3483 } |
| 3484 |
| 3485 if (!HTC_QUEUE_EMPTY(&queue)) { |
| 3486 /* add packets */ |
| 3487 HTCAddReceivePktMultiple(ar->arHtcTarget, &queue); |
| 3488 } |
| 3489 |
| 3490 } |
| 3491 |
| 3492 /* clean up our amsdu buffer list */ |
| 3493 static void ar6000_cleanup_amsdu_rxbufs(AR_SOFTC_T *ar) |
| 3494 { |
| 3495 HTC_PACKET *pPacket; |
| 3496 void *osBuf; |
| 3497 |
| 3498 /* empty AMSDU buffer queue and free OS bufs */ |
| 3499 while (TRUE) { |
| 3500 |
| 3501 AR6000_SPIN_LOCK(&ar->arLock, 0); |
| 3502 pPacket = HTC_PACKET_DEQUEUE(&ar->amsdu_rx_buffer_queue); |
| 3503 AR6000_SPIN_UNLOCK(&ar->arLock, 0); |
| 3504 |
| 3505 if (NULL == pPacket) { |
| 3506 break; |
| 3507 } |
| 3508 |
| 3509 osBuf = pPacket->pPktContext; |
| 3510 if (NULL == osBuf) { |
| 3511 A_ASSERT(FALSE); |
| 3512 break; |
| 3513 } |
| 3514 |
| 3515 A_NETBUF_FREE(osBuf); |
| 3516 } |
| 3517 |
| 3518 } |
| 3519 |
| 3520 |
| 3521 /* refill the amsdu buffer list */ |
| 3522 static void ar6000_refill_amsdu_rxbufs(AR_SOFTC_T *ar, int Count) |
| 3523 { |
| 3524 HTC_PACKET *pPacket; |
| 3525 void *osBuf; |
| 3526 |
| 3527 while (Count > 0) { |
| 3528 osBuf = A_NETBUF_ALLOC(AR6000_AMSDU_BUFFER_SIZE); |
| 3529 if (NULL == osBuf) { |
| 3530 break; |
| 3531 } |
| 3532 /* the HTC packet wrapper is at the head of the reserved area |
| 3533 * in the skb */ |
| 3534 pPacket = (HTC_PACKET *)(A_NETBUF_HEAD(osBuf)); |
| 3535 /* set re-fill info */ |
| 3536 SET_HTC_PACKET_INFO_RX_REFILL(pPacket,osBuf,A_NETBUF_DATA(osBuf),AR6000_
AMSDU_BUFFER_SIZE,0); |
| 3537 |
| 3538 AR6000_SPIN_LOCK(&ar->arLock, 0); |
| 3539 /* put it in the list */ |
| 3540 HTC_PACKET_ENQUEUE(&ar->amsdu_rx_buffer_queue,pPacket); |
| 3541 AR6000_SPIN_UNLOCK(&ar->arLock, 0); |
| 3542 Count--; |
| 3543 } |
| 3544 |
| 3545 } |
| 3546 |
| 3547 /* callback to allocate a large receive buffer for a pending packet. This f
unction is called when |
| 3548 * an HTC packet arrives whose length exceeds a threshold value |
| 3549 * |
| 3550 * We use a pre-allocated list of buffers of maximum AMSDU size (4K). Under
linux it is more optimal to |
| 3551 * keep the allocation size the same to optimize cached-slab allocations. |
| 3552 * |
| 3553 * */ |
| 3554 static HTC_PACKET *ar6000_alloc_amsdu_rxbuf(void *Context, HTC_ENDPOINT_ID Endpo
int, int Length) |
| 3555 { |
| 3556 HTC_PACKET *pPacket = NULL; |
| 3557 AR_SOFTC_T *ar = (AR_SOFTC_T *)Context; |
| 3558 int refillCount = 0; |
| 3559 |
| 3560 AR_DEBUG_PRINTF(ATH_DEBUG_WLAN_RX,("ar6000_alloc_amsdu_rxbuf: eid=%d, Length
:%d\n",Endpoint,Length)); |
| 3561 |
| 3562 do { |
| 3563 |
| 3564 if (Length <= AR6000_BUFFER_SIZE) { |
| 3565 /* shouldn't be getting called on normal sized packets */ |
| 3566 A_ASSERT(FALSE); |
| 3567 break; |
| 3568 } |
| 3569 |
| 3570 if (Length > AR6000_AMSDU_BUFFER_SIZE) { |
| 3571 A_ASSERT(FALSE); |
| 3572 break; |
| 3573 } |
| 3574 |
| 3575 AR6000_SPIN_LOCK(&ar->arLock, 0); |
| 3576 /* allocate a packet from the list */ |
| 3577 pPacket = HTC_PACKET_DEQUEUE(&ar->amsdu_rx_buffer_queue); |
| 3578 /* see if we need to refill again */ |
| 3579 refillCount = AR6000_MAX_AMSDU_RX_BUFFERS - HTC_PACKET_QUEUE_DEPTH(&ar->
amsdu_rx_buffer_queue); |
| 3580 AR6000_SPIN_UNLOCK(&ar->arLock, 0); |
| 3581 |
| 3582 if (NULL == pPacket) { |
| 3583 break; |
| 3584 } |
| 3585 /* set actual endpoint ID */ |
| 3586 pPacket->Endpoint = Endpoint; |
| 3587 |
| 3588 } while (FALSE); |
| 3589 |
| 3590 if (refillCount >= AR6000_AMSDU_REFILL_THRESHOLD) { |
| 3591 ar6000_refill_amsdu_rxbufs(ar,refillCount); |
| 3592 } |
| 3593 |
| 3594 return pPacket; |
| 3595 } |
| 3596 |
| 3597 |
| 3598 static struct net_device_stats * |
| 3599 ar6000_get_stats(struct net_device *dev) |
| 3600 { |
| 3601 AR_SOFTC_T *ar = (AR_SOFTC_T *)ar6k_priv(dev); |
| 3602 return &ar->arNetStats; |
| 3603 } |
| 3604 |
| 3605 static struct iw_statistics * |
| 3606 ar6000_get_iwstats(struct net_device * dev) |
| 3607 { |
| 3608 AR_SOFTC_T *ar = (AR_SOFTC_T *)ar6k_priv(dev); |
| 3609 TARGET_STATS *pStats = &ar->arTargetStats; |
| 3610 struct iw_statistics * pIwStats = &ar->arIwStats; |
| 3611 |
| 3612 if (ar->bIsDestroyProgress || ar->arWmiReady == FALSE) |
| 3613 { |
| 3614 pIwStats->status = 0; |
| 3615 pIwStats->qual.qual = 0; |
| 3616 pIwStats->qual.level =0; |
| 3617 pIwStats->qual.noise = 0; |
| 3618 pIwStats->discard.code =0; |
| 3619 pIwStats->discard.retries=0; |
| 3620 pIwStats->miss.beacon =0; |
| 3621 return pIwStats; |
| 3622 } |
| 3623 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) |
| 3624 /* |
| 3625 * The in_atomic function is used to determine if the scheduling is |
| 3626 * allowed in the current context or not. This was introduced in 2.6 |
| 3627 * From what I have read on the differences between 2.4 and 2.6, the |
| 3628 * 2.4 kernel did not support preemption and so this check might not |
| 3629 * be required for 2.4 kernels. |
| 3630 */ |
| 3631 if (in_atomic()) |
| 3632 { |
| 3633 wmi_get_stats_cmd(ar->arWmi); |
| 3634 |
| 3635 pIwStats->status = 1 ; |
| 3636 pIwStats->qual.qual = pStats->cs_aveBeacon_rssi - 161; |
| 3637 pIwStats->qual.level =pStats->cs_aveBeacon_rssi; /* noise is -95 dBm */ |
| 3638 pIwStats->qual.noise = pStats->noise_floor_calibation; |
| 3639 pIwStats->discard.code = pStats->rx_decrypt_err; |
| 3640 pIwStats->discard.retries = pStats->tx_retry_cnt; |
| 3641 pIwStats->miss.beacon = pStats->cs_bmiss_cnt; |
| 3642 return pIwStats; |
| 3643 } |
| 3644 #endif /* LINUX_VERSION_CODE */ |
| 3645 |
| 3646 if (down_interruptible(&ar->arSem)) { |
| 3647 pIwStats->status = 0; |
| 3648 return pIwStats; |
| 3649 } |
| 3650 |
| 3651 if (ar->bIsDestroyProgress) { |
| 3652 up(&ar->arSem); |
| 3653 pIwStats->status = 0; |
| 3654 return pIwStats; |
| 3655 } |
| 3656 |
| 3657 ar->statsUpdatePending = TRUE; |
| 3658 |
| 3659 if(wmi_get_stats_cmd(ar->arWmi) != A_OK) { |
| 3660 up(&ar->arSem); |
| 3661 pIwStats->status = 0; |
| 3662 return pIwStats; |
| 3663 } |
| 3664 |
| 3665 dev_hold(dev); |
| 3666 rtnl_unlock(); |
| 3667 wait_event_interruptible_timeout(arEvent, ar->statsUpdatePending == FALSE, w
mitimeout * HZ); |
| 3668 rtnl_lock(); |
| 3669 dev_put(dev); |
| 3670 |
| 3671 if (signal_pending(current)) { |
| 3672 AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("ar6000 : WMI get stats timeout \n")); |
| 3673 up(&ar->arSem); |
| 3674 pIwStats->status = 0; |
| 3675 return pIwStats; |
| 3676 } |
| 3677 pIwStats->status = 1 ; |
| 3678 pIwStats->qual.qual = pStats->cs_aveBeacon_rssi - 161; |
| 3679 pIwStats->qual.level =pStats->cs_aveBeacon_rssi; /* noise is -95 dBm */ |
| 3680 pIwStats->qual.noise = pStats->noise_floor_calibation; |
| 3681 pIwStats->discard.code = pStats->rx_decrypt_err; |
| 3682 pIwStats->discard.retries = pStats->tx_retry_cnt; |
| 3683 pIwStats->miss.beacon = pStats->cs_bmiss_cnt; |
| 3684 up(&ar->arSem); |
| 3685 return pIwStats; |
| 3686 } |
| 3687 |
| 3688 void |
| 3689 ar6000_ready_event(void *devt, A_UINT8 *datap, A_UINT8 phyCap, A_UINT32 vers) |
| 3690 { |
| 3691 AR_SOFTC_T *ar = (AR_SOFTC_T *)devt; |
| 3692 struct net_device *dev = ar->arNetDev; |
| 3693 |
| 3694 ar->arWmiReady = TRUE; |
| 3695 wake_up(&arEvent); |
| 3696 A_MEMCPY(dev->dev_addr, datap, AR6000_ETH_ADDR_LEN); |
| 3697 AR_DEBUG_PRINTF(ATH_DEBUG_INFO,("mac address = %2.2x:%2.2x:%2.2x:%2.2x:%2.2x
:%2.2x\n", |
| 3698 dev->dev_addr[0], dev->dev_addr[1], |
| 3699 dev->dev_addr[2], dev->dev_addr[3], |
| 3700 dev->dev_addr[4], dev->dev_addr[5])); |
| 3701 |
| 3702 ar->arPhyCapability = phyCap; |
| 3703 ar->arVersion.wlan_ver = vers; |
| 3704 |
| 3705 #if WLAN_CONFIG_IGNORE_POWER_SAVE_FAIL_EVENT_DURING_SCAN |
| 3706 wmi_pmparams_cmd(ar->arWmi, 0, 1, 0, 0, 1, IGNORE_POWER_SAVE_FAIL_EVENT_DURI
NG_SCAN); |
| 3707 #endif |
| 3708 #if WLAN_CONFIG_DONOT_IGNORE_BARKER_IN_ERP |
| 3709 wmi_set_lpreamble_cmd(ar->arWmi, 0, WMI_DONOT_IGNORE_BARKER_IN_ERP); |
| 3710 #endif |
| 3711 } |
| 3712 |
| 3713 A_UINT8 |
| 3714 add_new_sta(AR_SOFTC_T *ar, A_UINT8 *mac, A_UINT16 aid, A_UINT8 *wpaie, |
| 3715 A_UINT8 ielen, A_UINT8 keymgmt, A_UINT8 ucipher, A_UINT8 auth) |
| 3716 { |
| 3717 A_INT8 free_slot=-1, i; |
| 3718 |
| 3719 for(i=0; i < AP_MAX_NUM_STA; i++) { |
| 3720 if(A_MEMCMP(ar->sta_list[i].mac, mac, ATH_MAC_LEN)==0) { |
| 3721 /* it is already available */ |
| 3722 return 0; |
| 3723 } |
| 3724 |
| 3725 if(!((1 << i) & ar->sta_list_index)) { |
| 3726 free_slot = i; |
| 3727 break; |
| 3728 } |
| 3729 } |
| 3730 |
| 3731 if(free_slot >= 0) { |
| 3732 A_MEMCPY(ar->sta_list[free_slot].mac, mac, ATH_MAC_LEN); |
| 3733 A_MEMCPY(ar->sta_list[free_slot].wpa_ie, wpaie, ielen); |
| 3734 ar->sta_list[free_slot].aid = aid; |
| 3735 ar->sta_list[free_slot].keymgmt = keymgmt; |
| 3736 ar->sta_list[free_slot].ucipher = ucipher; |
| 3737 ar->sta_list[free_slot].auth = auth; |
| 3738 ar->sta_list_index = ar->sta_list_index | (1 << free_slot); |
| 3739 ar->arAPStats.sta[aid-1].aid = aid; |
| 3740 return 1; |
| 3741 } |
| 3742 return 0; /* not added */ |
| 3743 } |
| 3744 |
| 3745 void |
| 3746 ar6000_connect_event(AR_SOFTC_T *ar, A_UINT16 channel, A_UINT8 *bssid, |
| 3747 A_UINT16 listenInterval, A_UINT16 beaconInterval, |
| 3748 NETWORK_TYPE networkType, A_UINT8 beaconIeLen, |
| 3749 A_UINT8 assocReqLen, A_UINT8 assocRespLen, |
| 3750 A_UINT8 *assocInfo) |
| 3751 { |
| 3752 union iwreq_data wrqu; |
| 3753 int i, beacon_ie_pos, assoc_resp_ie_pos, assoc_req_ie_pos; |
| 3754 static const char *tag1 = "ASSOCINFO(ReqIEs="; |
| 3755 static const char *tag2 = "ASSOCRESPIE="; |
| 3756 static const char *beaconIetag = "BEACONIE="; |
| 3757 char buf[WMI_CONTROL_MSG_MAX_LEN * 2 + strlen(tag1) + 1]; |
| 3758 char *pos; |
| 3759 A_UINT8 key_op_ctrl; |
| 3760 unsigned long flags; |
| 3761 struct ieee80211req_key *ik; |
| 3762 CRYPTO_TYPE keyType = NONE_CRYPT; |
| 3763 |
| 3764 if(ar->arNetworkType & AP_NETWORK) { |
| 3765 struct net_device *dev = ar->arNetDev; |
| 3766 if(A_MEMCMP(dev->dev_addr, bssid, ATH_MAC_LEN)==0) { |
| 3767 ar->arACS = channel; |
| 3768 ik = &ar->ap_mode_bkey; |
| 3769 |
| 3770 switch(ar->arAuthMode) { |
| 3771 case NONE_AUTH: |
| 3772 if(ar->arPairwiseCrypto == WEP_CRYPT) { |
| 3773 ar6000_install_static_wep_keys(ar); |
| 3774 } |
| 3775 #ifdef WAPI_ENABLE |
| 3776 else if(ar->arPairwiseCrypto == WAPI_CRYPT) { |
| 3777 ap_set_wapi_key(ar, ik); |
| 3778 } |
| 3779 #endif |
| 3780 break; |
| 3781 case WPA_PSK_AUTH: |
| 3782 case WPA2_PSK_AUTH: |
| 3783 case (WPA_PSK_AUTH|WPA2_PSK_AUTH): |
| 3784 switch (ik->ik_type) { |
| 3785 case IEEE80211_CIPHER_TKIP: |
| 3786 keyType = TKIP_CRYPT; |
| 3787 break; |
| 3788 case IEEE80211_CIPHER_AES_CCM: |
| 3789 keyType = AES_CRYPT; |
| 3790 break; |
| 3791 default: |
| 3792 goto skip_key; |
| 3793 } |
| 3794 wmi_addKey_cmd(ar->arWmi, ik->ik_keyix, keyType, GROUP_USAGE, |
| 3795 ik->ik_keylen, (A_UINT8 *)&ik->ik_keyrsc, |
| 3796 ik->ik_keydata, KEY_OP_INIT_VAL, ik->ik_macaddr, |
| 3797 SYNC_BOTH_WMIFLAG); |
| 3798 |
| 3799 break; |
| 3800 } |
| 3801 skip_key: |
| 3802 ar->arConnected = TRUE; |
| 3803 return; |
| 3804 } |
| 3805 |
| 3806 A_PRINTF("NEW STA %2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x \n " |
| 3807 " AID=%d \n", bssid[0], bssid[1], bssid[2], |
| 3808 bssid[3], bssid[4], bssid[5], channel); |
| 3809 switch ((listenInterval>>8)&0xFF) { |
| 3810 case OPEN_AUTH: |
| 3811 A_PRINTF("AUTH: OPEN\n"); |
| 3812 break; |
| 3813 case SHARED_AUTH: |
| 3814 A_PRINTF("AUTH: SHARED\n"); |
| 3815 break; |
| 3816 default: |
| 3817 A_PRINTF("AUTH: Unknown\n"); |
| 3818 break; |
| 3819 }; |
| 3820 switch (listenInterval&0xFF) { |
| 3821 case WPA_PSK_AUTH: |
| 3822 A_PRINTF("KeyMgmt: WPA-PSK\n"); |
| 3823 break; |
| 3824 case WPA2_PSK_AUTH: |
| 3825 A_PRINTF("KeyMgmt: WPA2-PSK\n"); |
| 3826 break; |
| 3827 default: |
| 3828 A_PRINTF("KeyMgmt: NONE\n"); |
| 3829 break; |
| 3830 }; |
| 3831 switch (beaconInterval) { |
| 3832 case AES_CRYPT: |
| 3833 A_PRINTF("Cipher: AES\n"); |
| 3834 break; |
| 3835 case TKIP_CRYPT: |
| 3836 A_PRINTF("Cipher: TKIP\n"); |
| 3837 break; |
| 3838 case WEP_CRYPT: |
| 3839 A_PRINTF("Cipher: WEP\n"); |
| 3840 break; |
| 3841 #ifdef WAPI_ENABLE |
| 3842 case WAPI_CRYPT: |
| 3843 A_PRINTF("Cipher: WAPI\n"); |
| 3844 break; |
| 3845 #endif |
| 3846 default: |
| 3847 A_PRINTF("Cipher: NONE\n"); |
| 3848 break; |
| 3849 }; |
| 3850 |
| 3851 add_new_sta(ar, bssid, channel /*aid*/, |
| 3852 assocInfo /* WPA IE */, assocRespLen /* IE len */, |
| 3853 listenInterval&0xFF /* Keymgmt */, beaconInterval /* cipher */, |
| 3854 (listenInterval>>8)&0xFF /* auth alg */); |
| 3855 |
| 3856 /* Send event to application */ |
| 3857 A_MEMZERO(&wrqu, sizeof(wrqu)); |
| 3858 A_MEMCPY(wrqu.addr.sa_data, bssid, ATH_MAC_LEN); |
| 3859 wireless_send_event(ar->arNetDev, IWEVREGISTERED, &wrqu, NULL); |
| 3860 /* In case the queue is stopped when we switch modes, this will |
| 3861 * wake it up |
| 3862 */ |
| 3863 netif_wake_queue(ar->arNetDev); |
| 3864 return; |
| 3865 } |
| 3866 |
| 3867 #ifdef CONFIG_CFG80211 |
| 3868 ar6k_cfg80211_connect_event(ar, channel, bssid, |
| 3869 listenInterval, beaconInterval, |
| 3870 networkType, beaconIeLen, |
| 3871 assocReqLen, assocRespLen, |
| 3872 assocInfo); |
| 3873 #endif /* CONFIG_CFG80211 */ |
| 3874 |
| 3875 A_MEMCPY(ar->arBssid, bssid, sizeof(ar->arBssid)); |
| 3876 ar->arBssChannel = channel; |
| 3877 |
| 3878 A_PRINTF("AR6000 connected event on freq %d ", channel); |
| 3879 A_PRINTF("with bssid %2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x " |
| 3880 " listenInterval=%d, beaconInterval = %d, beaconIeLen = %d assocReqL
en=%d" |
| 3881 " assocRespLen =%d\n", |
| 3882 bssid[0], bssid[1], bssid[2], |
| 3883 bssid[3], bssid[4], bssid[5], |
| 3884 listenInterval, beaconInterval, |
| 3885 beaconIeLen, assocReqLen, assocRespLen); |
| 3886 if (networkType & ADHOC_NETWORK) { |
| 3887 if (networkType & ADHOC_CREATOR) { |
| 3888 A_PRINTF("Network: Adhoc (Creator)\n"); |
| 3889 } else { |
| 3890 A_PRINTF("Network: Adhoc (Joiner)\n"); |
| 3891 } |
| 3892 } else { |
| 3893 A_PRINTF("Network: Infrastructure\n"); |
| 3894 } |
| 3895 |
| 3896 if (beaconIeLen && (sizeof(buf) > (9 + beaconIeLen * 2))) { |
| 3897 AR_DEBUG_PRINTF(ATH_DEBUG_WLAN_CONNECT,("\nBeaconIEs= ")); |
| 3898 |
| 3899 beacon_ie_pos = 0; |
| 3900 A_MEMZERO(buf, sizeof(buf)); |
| 3901 sprintf(buf, "%s", beaconIetag); |
| 3902 pos = buf + 9; |
| 3903 for (i = beacon_ie_pos; i < beacon_ie_pos + beaconIeLen; i++) { |
| 3904 AR_DEBUG_PRINTF(ATH_DEBUG_WLAN_CONNECT,("%2.2x ", assocInfo[i])); |
| 3905 sprintf(pos, "%2.2x", assocInfo[i]); |
| 3906 pos += 2; |
| 3907 } |
| 3908 AR_DEBUG_PRINTF(ATH_DEBUG_WLAN_CONNECT,("\n")); |
| 3909 |
| 3910 A_MEMZERO(&wrqu, sizeof(wrqu)); |
| 3911 wrqu.data.length = strlen(buf); |
| 3912 wireless_send_event(ar->arNetDev, IWEVCUSTOM, &wrqu, buf); |
| 3913 } |
| 3914 |
| 3915 if (assocRespLen && (sizeof(buf) > (12 + (assocRespLen * 2)))) |
| 3916 { |
| 3917 assoc_resp_ie_pos = beaconIeLen + assocReqLen + |
| 3918 sizeof(A_UINT16) + /* capinfo*/ |
| 3919 sizeof(A_UINT16) + /* status Code */ |
| 3920 sizeof(A_UINT16) ; /* associd */ |
| 3921 A_MEMZERO(buf, sizeof(buf)); |
| 3922 sprintf(buf, "%s", tag2); |
| 3923 pos = buf + 12; |
| 3924 AR_DEBUG_PRINTF(ATH_DEBUG_WLAN_CONNECT,("\nAssocRespIEs= ")); |
| 3925 /* |
| 3926 * The Association Response Frame w.o. the WLAN header is delivered to |
| 3927 * the host, so skip over to the IEs |
| 3928 */ |
| 3929 for (i = assoc_resp_ie_pos; i < assoc_resp_ie_pos + assocRespLen - 6; i+
+) |
| 3930 { |
| 3931 AR_DEBUG_PRINTF(ATH_DEBUG_WLAN_CONNECT,("%2.2x ", assocInfo[i])); |
| 3932 sprintf(pos, "%2.2x", assocInfo[i]); |
| 3933 pos += 2; |
| 3934 } |
| 3935 AR_DEBUG_PRINTF(ATH_DEBUG_WLAN_CONNECT,("\n")); |
| 3936 |
| 3937 A_MEMZERO(&wrqu, sizeof(wrqu)); |
| 3938 wrqu.data.length = strlen(buf); |
| 3939 wireless_send_event(ar->arNetDev, IWEVCUSTOM, &wrqu, buf); |
| 3940 } |
| 3941 |
| 3942 if (assocReqLen && (sizeof(buf) > (17 + (assocReqLen * 2)))) { |
| 3943 /* |
| 3944 * assoc Request includes capability and listen interval. Skip these. |
| 3945 */ |
| 3946 assoc_req_ie_pos = beaconIeLen + |
| 3947 sizeof(A_UINT16) + /* capinfo*/ |
| 3948 sizeof(A_UINT16); /* listen interval */ |
| 3949 |
| 3950 A_MEMZERO(buf, sizeof(buf)); |
| 3951 sprintf(buf, "%s", tag1); |
| 3952 pos = buf + 17; |
| 3953 AR_DEBUG_PRINTF(ATH_DEBUG_WLAN_CONNECT,("AssocReqIEs= ")); |
| 3954 for (i = assoc_req_ie_pos; i < assoc_req_ie_pos + assocReqLen - 4; i++)
{ |
| 3955 AR_DEBUG_PRINTF(ATH_DEBUG_WLAN_CONNECT,("%2.2x ", assocInfo[i])); |
| 3956 sprintf(pos, "%2.2x", assocInfo[i]); |
| 3957 pos += 2;; |
| 3958 } |
| 3959 AR_DEBUG_PRINTF(ATH_DEBUG_WLAN_CONNECT,("\n")); |
| 3960 |
| 3961 A_MEMZERO(&wrqu, sizeof(wrqu)); |
| 3962 wrqu.data.length = strlen(buf); |
| 3963 wireless_send_event(ar->arNetDev, IWEVCUSTOM, &wrqu, buf); |
| 3964 } |
| 3965 |
| 3966 #ifdef USER_KEYS |
| 3967 if (ar->user_savedkeys_stat == USER_SAVEDKEYS_STAT_RUN && |
| 3968 ar->user_saved_keys.keyOk == TRUE) |
| 3969 { |
| 3970 key_op_ctrl = KEY_OP_VALID_MASK & ~KEY_OP_INIT_TSC; |
| 3971 |
| 3972 if (ar->user_key_ctrl & AR6000_USER_SETKEYS_RSC_UNCHANGED) { |
| 3973 key_op_ctrl &= ~KEY_OP_INIT_RSC; |
| 3974 } else { |
| 3975 key_op_ctrl |= KEY_OP_INIT_RSC; |
| 3976 } |
| 3977 ar6000_reinstall_keys(ar, key_op_ctrl); |
| 3978 } |
| 3979 #endif /* USER_KEYS */ |
| 3980 |
| 3981 netif_wake_queue(ar->arNetDev); |
| 3982 |
| 3983 if ((networkType & ADHOC_NETWORK) && |
| 3984 (OPEN_AUTH == ar->arDot11AuthMode) && |
| 3985 (NONE_AUTH == ar->arAuthMode) && |
| 3986 (WEP_CRYPT == ar->arPairwiseCrypto)) |
| 3987 { |
| 3988 if (!ar->arConnected) { |
| 3989 wmi_addKey_cmd(ar->arWmi, |
| 3990 ar->arDefTxKeyIndex, |
| 3991 WEP_CRYPT, |
| 3992 GROUP_USAGE | TX_USAGE, |
| 3993 ar->arWepKeyList[ar->arDefTxKeyIndex].arKeyLen, |
| 3994 NULL, |
| 3995 ar->arWepKeyList[ar->arDefTxKeyIndex].arKey, KEY_OP_I
NIT_VAL, NULL, |
| 3996 NO_SYNC_WMIFLAG); |
| 3997 } |
| 3998 } |
| 3999 |
| 4000 /* Update connect & link status atomically */ |
| 4001 spin_lock_irqsave(&ar->arLock, flags); |
| 4002 ar->arConnected = TRUE; |
| 4003 ar->arConnectPending = FALSE; |
| 4004 netif_carrier_on(ar->arNetDev); |
| 4005 spin_unlock_irqrestore(&ar->arLock, flags); |
| 4006 /* reset the rx aggr state */ |
| 4007 aggr_reset_state(ar->aggr_cntxt); |
| 4008 reconnect_flag = 0; |
| 4009 |
| 4010 A_MEMZERO(&wrqu, sizeof(wrqu)); |
| 4011 A_MEMCPY(wrqu.addr.sa_data, bssid, IEEE80211_ADDR_LEN); |
| 4012 wrqu.addr.sa_family = ARPHRD_ETHER; |
| 4013 wireless_send_event(ar->arNetDev, SIOCGIWAP, &wrqu, NULL); |
| 4014 if ((ar->arNetworkType == ADHOC_NETWORK) && ar->arIbssPsEnable) { |
| 4015 A_MEMZERO(ar->arNodeMap, sizeof(ar->arNodeMap)); |
| 4016 ar->arNodeNum = 0; |
| 4017 ar->arNexEpId = ENDPOINT_2; |
| 4018 } |
| 4019 if (!ar->arUserBssFilter) { |
| 4020 wmi_bssfilter_cmd(ar->arWmi, NONE_BSS_FILTER, 0); |
| 4021 } |
| 4022 |
| 4023 } |
| 4024 |
| 4025 void ar6000_set_numdataendpts(AR_SOFTC_T *ar, A_UINT32 num) |
| 4026 { |
| 4027 A_ASSERT(num <= (HTC_MAILBOX_NUM_MAX - 1)); |
| 4028 ar->arNumDataEndPts = num; |
| 4029 } |
| 4030 |
| 4031 void |
| 4032 sta_cleanup(AR_SOFTC_T *ar, A_UINT8 i) |
| 4033 { |
| 4034 struct sk_buff *skb; |
| 4035 |
| 4036 /* empty the queued pkts in the PS queue if any */ |
| 4037 A_MUTEX_LOCK(&ar->sta_list[i].psqLock); |
| 4038 while (!A_NETBUF_QUEUE_EMPTY(&ar->sta_list[i].psq)) { |
| 4039 skb = A_NETBUF_DEQUEUE(&ar->sta_list[i].psq); |
| 4040 A_NETBUF_FREE(skb); |
| 4041 } |
| 4042 A_MUTEX_UNLOCK(&ar->sta_list[i].psqLock); |
| 4043 |
| 4044 /* Zero out the state fields */ |
| 4045 A_MEMZERO(&ar->arAPStats.sta[ar->sta_list[i].aid-1], sizeof(WMI_PER_STA_STAT
)); |
| 4046 A_MEMZERO(&ar->sta_list[i].mac, ATH_MAC_LEN); |
| 4047 A_MEMZERO(&ar->sta_list[i].wpa_ie, IEEE80211_MAX_IE); |
| 4048 ar->sta_list[i].aid = 0; |
| 4049 ar->sta_list[i].flags = 0; |
| 4050 |
| 4051 ar->sta_list_index = ar->sta_list_index & ~(1 << i); |
| 4052 |
| 4053 } |
| 4054 |
| 4055 A_UINT8 |
| 4056 remove_sta(AR_SOFTC_T *ar, A_UINT8 *mac, A_UINT16 reason) |
| 4057 { |
| 4058 A_UINT8 i, removed=0; |
| 4059 |
| 4060 if(IS_MAC_NULL(mac)) { |
| 4061 return removed; |
| 4062 } |
| 4063 |
| 4064 if(IS_MAC_BCAST(mac)) { |
| 4065 A_PRINTF("DEL ALL STA\n"); |
| 4066 for(i=0; i < AP_MAX_NUM_STA; i++) { |
| 4067 if(!IS_MAC_NULL(ar->sta_list[i].mac)) { |
| 4068 sta_cleanup(ar, i); |
| 4069 removed = 1; |
| 4070 } |
| 4071 } |
| 4072 } else { |
| 4073 for(i=0; i < AP_MAX_NUM_STA; i++) { |
| 4074 if(A_MEMCMP(ar->sta_list[i].mac, mac, ATH_MAC_LEN)==0) { |
| 4075 A_PRINTF("DEL STA %2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x " |
| 4076 " aid=%d REASON=%d\n", mac[0], mac[1], mac[2], |
| 4077 mac[3], mac[4], mac[5], ar->sta_list[i].aid, reason); |
| 4078 |
| 4079 sta_cleanup(ar, i); |
| 4080 removed = 1; |
| 4081 break; |
| 4082 } |
| 4083 } |
| 4084 } |
| 4085 return removed; |
| 4086 } |
| 4087 |
| 4088 void |
| 4089 ar6000_disconnect_event(AR_SOFTC_T *ar, A_UINT8 reason, A_UINT8 *bssid, |
| 4090 A_UINT8 assocRespLen, A_UINT8 *assocInfo, A_UINT16 proto
colReasonStatus) |
| 4091 { |
| 4092 A_UINT8 i; |
| 4093 unsigned long flags; |
| 4094 |
| 4095 if(ar->arNetworkType & AP_NETWORK) { |
| 4096 union iwreq_data wrqu; |
| 4097 struct sk_buff *skb; |
| 4098 |
| 4099 if(!remove_sta(ar, bssid, protocolReasonStatus)) { |
| 4100 return; |
| 4101 } |
| 4102 |
| 4103 /* If there are no more associated STAs, empty the mcast PS q */ |
| 4104 if (ar->sta_list_index == 0) { |
| 4105 A_MUTEX_LOCK(&ar->mcastpsqLock); |
| 4106 while (!A_NETBUF_QUEUE_EMPTY(&ar->mcastpsq)) { |
| 4107 skb = A_NETBUF_DEQUEUE(&ar->mcastpsq); |
| 4108 A_NETBUF_FREE(skb); |
| 4109 } |
| 4110 A_MUTEX_UNLOCK(&ar->mcastpsqLock); |
| 4111 |
| 4112 /* Clear the LSB of the BitMapCtl field of the TIM IE */ |
| 4113 wmi_set_pvb_cmd(ar->arWmi, MCAST_AID, 0); |
| 4114 } |
| 4115 |
| 4116 if(!IS_MAC_BCAST(bssid)) { |
| 4117 /* Send event to application */ |
| 4118 A_MEMZERO(&wrqu, sizeof(wrqu)); |
| 4119 A_MEMCPY(wrqu.addr.sa_data, bssid, ATH_MAC_LEN); |
| 4120 wireless_send_event(ar->arNetDev, IWEVEXPIRED, &wrqu, NULL); |
| 4121 } |
| 4122 return; |
| 4123 } |
| 4124 |
| 4125 #ifdef CONFIG_CFG80211 |
| 4126 ar6k_cfg80211_disconnect_event(ar, reason, bssid, |
| 4127 assocRespLen, assocInfo, |
| 4128 protocolReasonStatus); |
| 4129 #endif /* CONFIG_CFG80211 */ |
| 4130 |
| 4131 if (NO_NETWORK_AVAIL != reason) |
| 4132 { |
| 4133 union iwreq_data wrqu; |
| 4134 A_MEMZERO(&wrqu, sizeof(wrqu)); |
| 4135 wrqu.addr.sa_family = ARPHRD_ETHER; |
| 4136 |
| 4137 /* Send disconnect event to supplicant */ |
| 4138 wireless_send_event(ar->arNetDev, SIOCGIWAP, &wrqu, NULL); |
| 4139 } |
| 4140 /* it is necessary to clear the host-side rx aggregation state */ |
| 4141 |
| 4142 aggr_reset_state(ar->aggr_cntxt); |
| 4143 |
| 4144 A_UNTIMEOUT(&ar->disconnect_timer); |
| 4145 |
| 4146 A_PRINTF("AR6000 disconnected"); |
| 4147 if (bssid[0] || bssid[1] || bssid[2] || bssid[3] || bssid[4] || bssid[5]) { |
| 4148 A_PRINTF(" from %2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x ", |
| 4149 bssid[0], bssid[1], bssid[2], bssid[3], bssid[4], bssid[5]); |
| 4150 } |
| 4151 |
| 4152 AR_DEBUG_PRINTF(ATH_DEBUG_WLAN_CONNECT,("\nDisconnect Reason is %d", reason)
); |
| 4153 AR_DEBUG_PRINTF(ATH_DEBUG_WLAN_CONNECT,("\nProtocol Reason/Status Code is %d
", protocolReasonStatus)); |
| 4154 AR_DEBUG_PRINTF(ATH_DEBUG_WLAN_CONNECT,("\nAssocResp Frame = %s", |
| 4155 assocRespLen ? " " : "NULL")); |
| 4156 for (i = 0; i < assocRespLen; i++) { |
| 4157 if (!(i % 0x10)) { |
| 4158 AR_DEBUG_PRINTF(ATH_DEBUG_WLAN_CONNECT,("\n")); |
| 4159 } |
| 4160 AR_DEBUG_PRINTF(ATH_DEBUG_WLAN_CONNECT,("%2.2x ", assocInfo[i])); |
| 4161 } |
| 4162 AR_DEBUG_PRINTF(ATH_DEBUG_WLAN_CONNECT,("\n")); |
| 4163 /* |
| 4164 * If the event is due to disconnect cmd from the host, only they the target |
| 4165 * would stop trying to connect. Under any other condition, target would |
| 4166 * keep trying to connect. |
| 4167 * |
| 4168 */ |
| 4169 if( reason == DISCONNECT_CMD) |
| 4170 { |
| 4171 ar->arConnectPending = FALSE; |
| 4172 if (!ar->arUserBssFilter) { |
| 4173 wmi_bssfilter_cmd(ar->arWmi, NONE_BSS_FILTER, 0); |
| 4174 } |
| 4175 } else { |
| 4176 ar->arConnectPending = TRUE; |
| 4177 if (((reason == ASSOC_FAILED) && (protocolReasonStatus == 0x11)) || |
| 4178 ((reason == ASSOC_FAILED) && (protocolReasonStatus == 0x0) && (recon
nect_flag == 1))) { |
| 4179 ar->arConnected = TRUE; |
| 4180 return; |
| 4181 } |
| 4182 } |
| 4183 |
| 4184 if (reason == NO_NETWORK_AVAIL) |
| 4185 { |
| 4186 bss_t *pWmiSsidnode = NULL; |
| 4187 |
| 4188 /* remove the current associated bssid node */ |
| 4189 wmi_free_node (ar->arWmi, bssid); |
| 4190 |
| 4191 /* |
| 4192 * In case any other same SSID nodes are present |
| 4193 * remove it, since those nodes also not available now |
| 4194 */ |
| 4195 do |
| 4196 { |
| 4197 /* |
| 4198 * Find the nodes based on SSID and remove it |
| 4199 * NOTE :: This case will not work out for Hidden-SSID |
| 4200 */ |
| 4201 pWmiSsidnode = wmi_find_Ssidnode (ar->arWmi, ar->arSsid, ar->arSsidL
en, FALSE, TRUE); |
| 4202 |
| 4203 if (pWmiSsidnode) |
| 4204 { |
| 4205 wmi_free_node (ar->arWmi, pWmiSsidnode->ni_macaddr); |
| 4206 } |
| 4207 |
| 4208 }while (pWmiSsidnode); |
| 4209 |
| 4210 #if 0 |
| 4211 /* |
| 4212 * Issuing a disconnect cmd prevent the firmware from |
| 4213 * continuing the scan and connect to the AP, if the AP |
| 4214 * cannot be found in 10 seconds. The user has to issue |
| 4215 * the iwconfig command again to connect to the AP. |
| 4216 * This change came in CL#575412 (EV# 59469) has to |
| 4217 * be fixed in a different way |
| 4218 */ |
| 4219 ar6000_init_profile_info(ar); |
| 4220 wmi_disconnect_cmd(ar->arWmi); |
| 4221 #endif |
| 4222 } |
| 4223 |
| 4224 /* Update connect & link status atomically */ |
| 4225 spin_lock_irqsave(&ar->arLock, flags); |
| 4226 ar->arConnected = FALSE; |
| 4227 netif_carrier_off(ar->arNetDev); |
| 4228 spin_unlock_irqrestore(&ar->arLock, flags); |
| 4229 |
| 4230 if( (reason != CSERV_DISCONNECT) || (reconnect_flag != 1) ) { |
| 4231 reconnect_flag = 0; |
| 4232 } |
| 4233 |
| 4234 #ifdef USER_KEYS |
| 4235 if (reason != CSERV_DISCONNECT) |
| 4236 { |
| 4237 ar->user_savedkeys_stat = USER_SAVEDKEYS_STAT_INIT; |
| 4238 ar->user_key_ctrl = 0; |
| 4239 } |
| 4240 #endif /* USER_KEYS */ |
| 4241 |
| 4242 netif_stop_queue(ar->arNetDev); |
| 4243 A_MEMZERO(ar->arBssid, sizeof(ar->arBssid)); |
| 4244 ar->arBssChannel = 0; |
| 4245 ar->arBeaconInterval = 0; |
| 4246 |
| 4247 ar6000_TxDataCleanup(ar); |
| 4248 } |
| 4249 |
| 4250 void |
| 4251 ar6000_regDomain_event(AR_SOFTC_T *ar, A_UINT32 regCode) |
| 4252 { |
| 4253 A_PRINTF("AR6000 Reg Code = 0x%x\n", regCode); |
| 4254 ar->arRegCode = regCode; |
| 4255 } |
| 4256 |
| 4257 #ifdef ATH_AR6K_11N_SUPPORT |
| 4258 void |
| 4259 ar6000_aggr_rcv_addba_req_evt(AR_SOFTC_T *ar, WMI_ADDBA_REQ_EVENT *evt) |
| 4260 { |
| 4261 if(evt->status == 0) { |
| 4262 aggr_recv_addba_req_evt(ar->aggr_cntxt, evt->tid, evt->st_seq_no, evt->w
in_sz); |
| 4263 } |
| 4264 } |
| 4265 |
| 4266 void |
| 4267 ar6000_aggr_rcv_addba_resp_evt(AR_SOFTC_T *ar, WMI_ADDBA_RESP_EVENT *evt) |
| 4268 { |
| 4269 A_PRINTF("ADDBA RESP. tid %d status %d, sz %d\n", evt->tid, evt->status, evt
->amsdu_sz); |
| 4270 if(evt->status == 0) { |
| 4271 } |
| 4272 } |
| 4273 |
| 4274 void |
| 4275 ar6000_aggr_rcv_delba_req_evt(AR_SOFTC_T *ar, WMI_DELBA_EVENT *evt) |
| 4276 { |
| 4277 aggr_recv_delba_req_evt(ar->aggr_cntxt, evt->tid); |
| 4278 } |
| 4279 #endif |
| 4280 |
| 4281 void |
| 4282 ar6000_hci_event_rcv_evt(struct ar6_softc *ar, WMI_HCI_EVENT *cmd) |
| 4283 { |
| 4284 void *osbuf = NULL; |
| 4285 A_INT8 i; |
| 4286 A_UINT8 size, *buf; |
| 4287 A_STATUS ret = A_OK; |
| 4288 |
| 4289 size = cmd->evt_buf_sz + 4; |
| 4290 osbuf = A_NETBUF_ALLOC(size); |
| 4291 if (osbuf == NULL) { |
| 4292 ret = A_NO_MEMORY; |
| 4293 A_PRINTF("Error in allocating netbuf \n"); |
| 4294 return; |
| 4295 } |
| 4296 |
| 4297 A_NETBUF_PUT(osbuf, size); |
| 4298 buf = (A_UINT8 *)A_NETBUF_DATA(osbuf); |
| 4299 /* First 2-bytes carry HCI event/ACL data type |
| 4300 * the next 2 are free |
| 4301 */ |
| 4302 *((short *)buf) = WMI_HCI_EVENT_EVENTID; |
| 4303 buf += sizeof(int); |
| 4304 A_MEMCPY(buf, cmd->buf, cmd->evt_buf_sz); |
| 4305 |
| 4306 ar6000_deliver_frames_to_nw_stack(ar->arNetDev, osbuf); |
| 4307 if(loghci) { |
| 4308 A_PRINTF_LOG("HCI Event From PAL <-- \n"); |
| 4309 for(i = 0; i < cmd->evt_buf_sz; i++) { |
| 4310 A_PRINTF_LOG("0x%02x ", cmd->buf[i]); |
| 4311 if((i % 10) == 0) { |
| 4312 A_PRINTF_LOG("\n"); |
| 4313 } |
| 4314 } |
| 4315 A_PRINTF_LOG("\n"); |
| 4316 A_PRINTF_LOG("==================================\n"); |
| 4317 } |
| 4318 } |
| 4319 |
| 4320 void |
| 4321 ar6000_neighborReport_event(AR_SOFTC_T *ar, int numAps, WMI_NEIGHBOR_INFO *info) |
| 4322 { |
| 4323 #if WIRELESS_EXT >= 18 |
| 4324 struct iw_pmkid_cand *pmkcand; |
| 4325 #else /* WIRELESS_EXT >= 18 */ |
| 4326 static const char *tag = "PRE-AUTH"; |
| 4327 char buf[128]; |
| 4328 #endif /* WIRELESS_EXT >= 18 */ |
| 4329 |
| 4330 union iwreq_data wrqu; |
| 4331 int i; |
| 4332 |
| 4333 AR_DEBUG_PRINTF(ATH_DEBUG_WLAN_SCAN,("AR6000 Neighbor Report Event\n")); |
| 4334 for (i=0; i < numAps; info++, i++) { |
| 4335 AR_DEBUG_PRINTF(ATH_DEBUG_WLAN_SCAN,("bssid %2.2x:%2.2x:%2.2x:%2.2x:%2.2
x:%2.2x ", |
| 4336 info->bssid[0], info->bssid[1], info->bssid[2], |
| 4337 info->bssid[3], info->bssid[4], info->bssid[5])); |
| 4338 if (info->bssFlags & WMI_PREAUTH_CAPABLE_BSS) { |
| 4339 AR_DEBUG_PRINTF(ATH_DEBUG_WLAN_SCAN,("preauth-cap")); |
| 4340 } |
| 4341 if (info->bssFlags & WMI_PMKID_VALID_BSS) { |
| 4342 AR_DEBUG_PRINTF(ATH_DEBUG_WLAN_SCAN,(" pmkid-valid\n")); |
| 4343 continue; /* we skip bss if the pmkid is already valid */ |
| 4344 } |
| 4345 AR_DEBUG_PRINTF(ATH_DEBUG_WLAN_SCAN,("\n")); |
| 4346 A_MEMZERO(&wrqu, sizeof(wrqu)); |
| 4347 #if WIRELESS_EXT >= 18 |
| 4348 pmkcand = A_MALLOC_NOWAIT(sizeof(struct iw_pmkid_cand)); |
| 4349 A_MEMZERO(pmkcand, sizeof(struct iw_pmkid_cand)); |
| 4350 pmkcand->index = i; |
| 4351 pmkcand->flags = info->bssFlags; |
| 4352 A_MEMCPY(pmkcand->bssid.sa_data, info->bssid, ATH_MAC_LEN); |
| 4353 wrqu.data.length = sizeof(struct iw_pmkid_cand); |
| 4354 wireless_send_event(ar->arNetDev, IWEVPMKIDCAND, &wrqu, (char *)pmkcand)
; |
| 4355 A_FREE(pmkcand); |
| 4356 #else /* WIRELESS_EXT >= 18 */ |
| 4357 snprintf(buf, sizeof(buf), "%s%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x", |
| 4358 tag, |
| 4359 info->bssid[0], info->bssid[1], info->bssid[2], |
| 4360 info->bssid[3], info->bssid[4], info->bssid[5], |
| 4361 i, info->bssFlags); |
| 4362 wrqu.data.length = strlen(buf); |
| 4363 wireless_send_event(ar->arNetDev, IWEVCUSTOM, &wrqu, buf); |
| 4364 #endif /* WIRELESS_EXT >= 18 */ |
| 4365 } |
| 4366 } |
| 4367 |
| 4368 void |
| 4369 ar6000_tkip_micerr_event(AR_SOFTC_T *ar, A_UINT8 keyid, A_BOOL ismcast) |
| 4370 { |
| 4371 static const char *tag = "MLME-MICHAELMICFAILURE.indication"; |
| 4372 char buf[128]; |
| 4373 union iwreq_data wrqu; |
| 4374 |
| 4375 /* |
| 4376 * For AP case, keyid will have aid of STA which sent pkt with |
| 4377 * MIC error. Use this aid to get MAC & send it to hostapd. |
| 4378 */ |
| 4379 if (ar->arNetworkType == AP_NETWORK) { |
| 4380 sta_t *s = ieee80211_find_conn_for_aid(ar, keyid); |
| 4381 if(!s){ |
| 4382 /* ?? Don't know why it happens - need to debug this scenario in FW
*/ |
| 4383 A_PRINTF("AP TKIP MIC error received from Invalid aid / STA not foun
d =%d\n", keyid); |
| 4384 return; |
| 4385 } |
| 4386 A_PRINTF("AP TKIP MIC error received from aid=%d\n", keyid); |
| 4387 snprintf(buf,sizeof(buf), "%s addr=%2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x", |
| 4388 tag, s->mac[0],s->mac[1],s->mac[2],s->mac[3],s->mac[4],s->mac[5]); |
| 4389 } else { |
| 4390 |
| 4391 #ifdef CONFIG_CFG80211 |
| 4392 ar6k_cfg80211_tkip_micerr_event(ar, keyid, ismcast); |
| 4393 #endif /* CONFIG_CFG80211 */ |
| 4394 |
| 4395 A_PRINTF("AR6000 TKIP MIC error received for keyid %d %scast\n", |
| 4396 keyid, ismcast ? "multi": "uni"); |
| 4397 snprintf(buf, sizeof(buf), "%s(keyid=%d %sicast)", tag, keyid, |
| 4398 ismcast ? "mult" : "un"); |
| 4399 } |
| 4400 |
| 4401 memset(&wrqu, 0, sizeof(wrqu)); |
| 4402 wrqu.data.length = strlen(buf); |
| 4403 wireless_send_event(ar->arNetDev, IWEVCUSTOM, &wrqu, buf); |
| 4404 } |
| 4405 |
| 4406 void |
| 4407 ar6000_scanComplete_event(AR_SOFTC_T *ar, A_STATUS status) |
| 4408 { |
| 4409 |
| 4410 #ifdef CONFIG_CFG80211 |
| 4411 ar6k_cfg80211_scanComplete_event(ar, status); |
| 4412 #endif /* CONFIG_CFG80211 */ |
| 4413 |
| 4414 if (!ar->arUserBssFilter) { |
| 4415 wmi_bssfilter_cmd(ar->arWmi, NONE_BSS_FILTER, 0); |
| 4416 } |
| 4417 AR_DEBUG_PRINTF(ATH_DEBUG_WLAN_SCAN,( "AR6000 scan complete: %d\n", status))
; |
| 4418 } |
| 4419 |
| 4420 void |
| 4421 ar6000_targetStats_event(AR_SOFTC_T *ar, A_UINT8 *ptr, A_UINT32 len) |
| 4422 { |
| 4423 A_UINT8 ac; |
| 4424 |
| 4425 if(ar->arNetworkType == AP_NETWORK) { |
| 4426 WMI_AP_MODE_STAT *p = (WMI_AP_MODE_STAT *)ptr; |
| 4427 WMI_AP_MODE_STAT *ap = &ar->arAPStats; |
| 4428 |
| 4429 if (len < sizeof(*p)) { |
| 4430 return; |
| 4431 } |
| 4432 |
| 4433 for(ac=0;ac<AP_MAX_NUM_STA;ac++) { |
| 4434 ap->sta[ac].tx_bytes += p->sta[ac].tx_bytes; |
| 4435 ap->sta[ac].tx_pkts += p->sta[ac].tx_pkts; |
| 4436 ap->sta[ac].tx_error += p->sta[ac].tx_error; |
| 4437 ap->sta[ac].tx_discard += p->sta[ac].tx_discard; |
| 4438 ap->sta[ac].rx_bytes += p->sta[ac].rx_bytes; |
| 4439 ap->sta[ac].rx_pkts += p->sta[ac].rx_pkts; |
| 4440 ap->sta[ac].rx_error += p->sta[ac].rx_error; |
| 4441 ap->sta[ac].rx_discard += p->sta[ac].rx_discard; |
| 4442 } |
| 4443 |
| 4444 } else { |
| 4445 WMI_TARGET_STATS *pTarget = (WMI_TARGET_STATS *)ptr; |
| 4446 TARGET_STATS *pStats = &ar->arTargetStats; |
| 4447 |
| 4448 if (len < sizeof(*pTarget)) { |
| 4449 return; |
| 4450 } |
| 4451 |
| 4452 // Update the RSSI of the connected bss. |
| 4453 if (ar->arConnected) { |
| 4454 bss_t *pConnBss = NULL; |
| 4455 |
| 4456 pConnBss = wmi_find_node(ar->arWmi,ar->arBssid); |
| 4457 if (pConnBss) |
| 4458 { |
| 4459 pConnBss->ni_rssi = pTarget->cservStats.cs_aveBeacon_rssi; |
| 4460 pConnBss->ni_snr = pTarget->cservStats.cs_aveBeacon_snr; |
| 4461 wmi_node_return(ar->arWmi, pConnBss); |
| 4462 } |
| 4463 } |
| 4464 |
| 4465 AR_DEBUG_PRINTF(ATH_DEBUG_INFO,("AR6000 updating target stats\n")); |
| 4466 pStats->tx_packets += pTarget->txrxStats.tx_stats.tx_packets; |
| 4467 pStats->tx_bytes += pTarget->txrxStats.tx_stats.tx_bytes; |
| 4468 pStats->tx_unicast_pkts += pTarget->txrxStats.tx_stats.tx_unicast_pk
ts; |
| 4469 pStats->tx_unicast_bytes += pTarget->txrxStats.tx_stats.tx_unicast_by
tes; |
| 4470 pStats->tx_multicast_pkts += pTarget->txrxStats.tx_stats.tx_multicast_
pkts; |
| 4471 pStats->tx_multicast_bytes += pTarget->txrxStats.tx_stats.tx_multicast_
bytes; |
| 4472 pStats->tx_broadcast_pkts += pTarget->txrxStats.tx_stats.tx_broadcast_
pkts; |
| 4473 pStats->tx_broadcast_bytes += pTarget->txrxStats.tx_stats.tx_broadcast_
bytes; |
| 4474 pStats->tx_rts_success_cnt += pTarget->txrxStats.tx_stats.tx_rts_succes
s_cnt; |
| 4475 for(ac = 0; ac < WMM_NUM_AC; ac++) |
| 4476 pStats->tx_packet_per_ac[ac] += pTarget->txrxStats.tx_stats.tx_packe
t_per_ac[ac]; |
| 4477 pStats->tx_errors += pTarget->txrxStats.tx_stats.tx_errors; |
| 4478 pStats->tx_failed_cnt += pTarget->txrxStats.tx_stats.tx_failed_cnt
; |
| 4479 pStats->tx_retry_cnt += pTarget->txrxStats.tx_stats.tx_retry_cnt; |
| 4480 pStats->tx_mult_retry_cnt += pTarget->txrxStats.tx_stats.tx_mult_retry
_cnt; |
| 4481 pStats->tx_rts_fail_cnt += pTarget->txrxStats.tx_stats.tx_rts_fail_c
nt; |
| 4482 pStats->tx_unicast_rate = wmi_get_rate(pTarget->txrxStats.tx_stats.
tx_unicast_rate); |
| 4483 |
| 4484 pStats->rx_packets += pTarget->txrxStats.rx_stats.rx_packets; |
| 4485 pStats->rx_bytes += pTarget->txrxStats.rx_stats.rx_bytes; |
| 4486 pStats->rx_unicast_pkts += pTarget->txrxStats.rx_stats.rx_unicast_pk
ts; |
| 4487 pStats->rx_unicast_bytes += pTarget->txrxStats.rx_stats.rx_unicast_by
tes; |
| 4488 pStats->rx_multicast_pkts += pTarget->txrxStats.rx_stats.rx_multicast_
pkts; |
| 4489 pStats->rx_multicast_bytes += pTarget->txrxStats.rx_stats.rx_multicast_
bytes; |
| 4490 pStats->rx_broadcast_pkts += pTarget->txrxStats.rx_stats.rx_broadcast_
pkts; |
| 4491 pStats->rx_broadcast_bytes += pTarget->txrxStats.rx_stats.rx_broadcast_
bytes; |
| 4492 pStats->rx_fragment_pkt += pTarget->txrxStats.rx_stats.rx_fragment_p
kt; |
| 4493 pStats->rx_errors += pTarget->txrxStats.rx_stats.rx_errors; |
| 4494 pStats->rx_crcerr += pTarget->txrxStats.rx_stats.rx_crcerr; |
| 4495 pStats->rx_key_cache_miss += pTarget->txrxStats.rx_stats.rx_key_cache_
miss; |
| 4496 pStats->rx_decrypt_err += pTarget->txrxStats.rx_stats.rx_decrypt_er
r; |
| 4497 pStats->rx_duplicate_frames += pTarget->txrxStats.rx_stats.rx_duplicate_
frames; |
| 4498 pStats->rx_unicast_rate = wmi_get_rate(pTarget->txrxStats.rx_stats.
rx_unicast_rate); |
| 4499 |
| 4500 |
| 4501 pStats->tkip_local_mic_failure |
| 4502 += pTarget->txrxStats.tkipCcmpStats.tkip_local_m
ic_failure; |
| 4503 pStats->tkip_counter_measures_invoked |
| 4504 += pTarget->txrxStats.tkipCcmpStats.tkip_counter
_measures_invoked; |
| 4505 pStats->tkip_replays += pTarget->txrxStats.tkipCcmpStats.tkip_rep
lays; |
| 4506 pStats->tkip_format_errors += pTarget->txrxStats.tkipCcmpStats.tkip_for
mat_errors; |
| 4507 pStats->ccmp_format_errors += pTarget->txrxStats.tkipCcmpStats.ccmp_for
mat_errors; |
| 4508 pStats->ccmp_replays += pTarget->txrxStats.tkipCcmpStats.ccmp_rep
lays; |
| 4509 |
| 4510 pStats->power_save_failure_cnt += pTarget->pmStats.power_save_failure_cn
t; |
| 4511 pStats->noise_floor_calibation = pTarget->noise_floor_calibation; |
| 4512 |
| 4513 pStats->cs_bmiss_cnt += pTarget->cservStats.cs_bmiss_cnt; |
| 4514 pStats->cs_lowRssi_cnt += pTarget->cservStats.cs_lowRssi_cnt; |
| 4515 pStats->cs_connect_cnt += pTarget->cservStats.cs_connect_cnt; |
| 4516 pStats->cs_disconnect_cnt += pTarget->cservStats.cs_disconnect_cnt; |
| 4517 pStats->cs_aveBeacon_snr = pTarget->cservStats.cs_aveBeacon_snr; |
| 4518 pStats->cs_aveBeacon_rssi = pTarget->cservStats.cs_aveBeacon_rssi; |
| 4519 |
| 4520 if (enablerssicompensation) { |
| 4521 pStats->cs_aveBeacon_rssi = |
| 4522 rssi_compensation_calc(ar, pStats->cs_aveBeacon_rssi); |
| 4523 } |
| 4524 pStats->cs_lastRoam_msec = pTarget->cservStats.cs_lastRoam_msec; |
| 4525 pStats->cs_snr = pTarget->cservStats.cs_snr; |
| 4526 pStats->cs_rssi = pTarget->cservStats.cs_rssi; |
| 4527 |
| 4528 pStats->lq_val = pTarget->lqVal; |
| 4529 |
| 4530 pStats->wow_num_pkts_dropped += pTarget->wowStats.wow_num_pkts_dropped; |
| 4531 pStats->wow_num_host_pkt_wakeups += pTarget->wowStats.wow_num_host_pkt_w
akeups; |
| 4532 pStats->wow_num_host_event_wakeups += pTarget->wowStats.wow_num_host_eve
nt_wakeups; |
| 4533 pStats->wow_num_events_discarded += pTarget->wowStats.wow_num_events_dis
carded; |
| 4534 pStats->arp_received += pTarget->arpStats.arp_received; |
| 4535 pStats->arp_matched += pTarget->arpStats.arp_matched; |
| 4536 pStats->arp_replied += pTarget->arpStats.arp_replied; |
| 4537 |
| 4538 if (ar->statsUpdatePending) { |
| 4539 ar->statsUpdatePending = FALSE; |
| 4540 wake_up(&arEvent); |
| 4541 } |
| 4542 } |
| 4543 } |
| 4544 |
| 4545 void |
| 4546 ar6000_rssiThreshold_event(AR_SOFTC_T *ar, WMI_RSSI_THRESHOLD_VAL newThreshold,
A_INT16 rssi) |
| 4547 { |
| 4548 USER_RSSI_THOLD userRssiThold; |
| 4549 |
| 4550 rssi = rssi + SIGNAL_QUALITY_NOISE_FLOOR; |
| 4551 |
| 4552 if (enablerssicompensation) { |
| 4553 rssi = rssi_compensation_calc(ar, rssi); |
| 4554 } |
| 4555 |
| 4556 /* Send an event to the app */ |
| 4557 userRssiThold.tag = ar->rssi_map[newThreshold].tag; |
| 4558 userRssiThold.rssi = rssi; |
| 4559 A_PRINTF("rssi Threshold range = %d tag = %d rssi = %d\n", newThreshold, |
| 4560 userRssiThold.tag, userRssiThold.rssi); |
| 4561 |
| 4562 ar6000_send_event_to_app(ar, WMI_RSSI_THRESHOLD_EVENTID,(A_UINT8 *)&userRssi
Thold, sizeof(USER_RSSI_THOLD)); |
| 4563 } |
| 4564 |
| 4565 |
| 4566 void |
| 4567 ar6000_hbChallengeResp_event(AR_SOFTC_T *ar, A_UINT32 cookie, A_UINT32 source) |
| 4568 { |
| 4569 if (source == APP_HB_CHALLENGE) { |
| 4570 /* Report it to the app in case it wants a positive acknowledgement */ |
| 4571 ar6000_send_event_to_app(ar, WMIX_HB_CHALLENGE_RESP_EVENTID, |
| 4572 (A_UINT8 *)&cookie, sizeof(cookie)); |
| 4573 } else { |
| 4574 /* This would ignore the replys that come in after their due time */ |
| 4575 if (cookie == ar->arHBChallengeResp.seqNum) { |
| 4576 ar->arHBChallengeResp.outstanding = FALSE; |
| 4577 } |
| 4578 } |
| 4579 } |
| 4580 |
| 4581 |
| 4582 void |
| 4583 ar6000_reportError_event(AR_SOFTC_T *ar, WMI_TARGET_ERROR_VAL errorVal) |
| 4584 { |
| 4585 char *errString[] = { |
| 4586 [WMI_TARGET_PM_ERR_FAIL] "WMI_TARGET_PM_ERR_FAIL", |
| 4587 [WMI_TARGET_KEY_NOT_FOUND] "WMI_TARGET_KEY_NOT_FOUND", |
| 4588 [WMI_TARGET_DECRYPTION_ERR] "WMI_TARGET_DECRYPTION_ERR", |
| 4589 [WMI_TARGET_BMISS] "WMI_TARGET_BMISS", |
| 4590 [WMI_PSDISABLE_NODE_JOIN] "WMI_PSDISABLE_NODE_JOIN" |
| 4591 }; |
| 4592 |
| 4593 A_PRINTF("AR6000 Error on Target. Error = 0x%x\n", errorVal); |
| 4594 |
| 4595 /* One error is reported at a time, and errorval is a bitmask */ |
| 4596 if(errorVal & (errorVal - 1)) |
| 4597 return; |
| 4598 |
| 4599 A_PRINTF("AR6000 Error type = "); |
| 4600 switch(errorVal) |
| 4601 { |
| 4602 case WMI_TARGET_PM_ERR_FAIL: |
| 4603 case WMI_TARGET_KEY_NOT_FOUND: |
| 4604 case WMI_TARGET_DECRYPTION_ERR: |
| 4605 case WMI_TARGET_BMISS: |
| 4606 case WMI_PSDISABLE_NODE_JOIN: |
| 4607 A_PRINTF("%s\n", errString[errorVal]); |
| 4608 break; |
| 4609 default: |
| 4610 A_PRINTF("INVALID\n"); |
| 4611 break; |
| 4612 } |
| 4613 |
| 4614 } |
| 4615 |
| 4616 |
| 4617 void |
| 4618 ar6000_cac_event(AR_SOFTC_T *ar, A_UINT8 ac, A_UINT8 cacIndication, |
| 4619 A_UINT8 statusCode, A_UINT8 *tspecSuggestion) |
| 4620 { |
| 4621 WMM_TSPEC_IE *tspecIe; |
| 4622 |
| 4623 /* |
| 4624 * This is the TSPEC IE suggestion from AP. |
| 4625 * Suggestion provided by AP under some error |
| 4626 * cases, could be helpful for the host app. |
| 4627 * Check documentation. |
| 4628 */ |
| 4629 tspecIe = (WMM_TSPEC_IE *)tspecSuggestion; |
| 4630 |
| 4631 /* |
| 4632 * What do we do, if we get TSPEC rejection? One thought |
| 4633 * that comes to mind is implictly delete the pstream... |
| 4634 */ |
| 4635 A_PRINTF("AR6000 CAC notification. " |
| 4636 "AC = %d, cacIndication = 0x%x, statusCode = 0x%x\n", |
| 4637 ac, cacIndication, statusCode); |
| 4638 } |
| 4639 |
| 4640 void |
| 4641 ar6000_channel_change_event(AR_SOFTC_T *ar, A_UINT16 oldChannel, |
| 4642 A_UINT16 newChannel) |
| 4643 { |
| 4644 A_PRINTF("Channel Change notification\nOld Channel: %d, New Channel: %d\n", |
| 4645 oldChannel, newChannel); |
| 4646 } |
| 4647 |
| 4648 #define AR6000_PRINT_BSSID(_pBss) do { \ |
| 4649 A_PRINTF("%2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x ",\ |
| 4650 (_pBss)[0],(_pBss)[1],(_pBss)[2],(_pBss)[3],\ |
| 4651 (_pBss)[4],(_pBss)[5]); \ |
| 4652 } while(0) |
| 4653 |
| 4654 void |
| 4655 ar6000_roam_tbl_event(AR_SOFTC_T *ar, WMI_TARGET_ROAM_TBL *pTbl) |
| 4656 { |
| 4657 A_UINT8 i; |
| 4658 |
| 4659 A_PRINTF("ROAM TABLE NO OF ENTRIES is %d ROAM MODE is %d\n", |
| 4660 pTbl->numEntries, pTbl->roamMode); |
| 4661 for (i= 0; i < pTbl->numEntries; i++) { |
| 4662 A_PRINTF("[%d]bssid %2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x ", i, |
| 4663 pTbl->bssRoamInfo[i].bssid[0], pTbl->bssRoamInfo[i].bssid[1], |
| 4664 pTbl->bssRoamInfo[i].bssid[2], |
| 4665 pTbl->bssRoamInfo[i].bssid[3], |
| 4666 pTbl->bssRoamInfo[i].bssid[4], |
| 4667 pTbl->bssRoamInfo[i].bssid[5]); |
| 4668 A_PRINTF("RSSI %d RSSIDT %d LAST RSSI %d UTIL %d ROAM_UTIL %d" |
| 4669 " BIAS %d\n", |
| 4670 pTbl->bssRoamInfo[i].rssi, |
| 4671 pTbl->bssRoamInfo[i].rssidt, |
| 4672 pTbl->bssRoamInfo[i].last_rssi, |
| 4673 pTbl->bssRoamInfo[i].util, |
| 4674 pTbl->bssRoamInfo[i].roam_util, |
| 4675 pTbl->bssRoamInfo[i].bias); |
| 4676 } |
| 4677 } |
| 4678 |
| 4679 void |
| 4680 ar6000_wow_list_event(struct ar6_softc *ar, A_UINT8 num_filters, WMI_GET_WOW_LIS
T_REPLY *wow_reply) |
| 4681 { |
| 4682 A_UINT8 i,j; |
| 4683 |
| 4684 /*Each event now contains exactly one filter, see bug 26613*/ |
| 4685 A_PRINTF("WOW pattern %d of %d patterns\n", wow_reply->this_filter_num,
wow_reply->num_filters); |
| 4686 A_PRINTF("wow mode = %s host mode = %s\n", |
| 4687 (wow_reply->wow_mode == 0? "disabled":"enabled"), |
| 4688 (wow_reply->host_mode == 1 ? "awake":"asleep")); |
| 4689 |
| 4690 |
| 4691 /*If there are no patterns, the reply will only contain generic |
| 4692 WoW information. Pattern information will exist only if there are |
| 4693 patterns present. Bug 26716*/ |
| 4694 |
| 4695 /* If this event contains pattern information, display it*/ |
| 4696 if (wow_reply->this_filter_num) { |
| 4697 i=0; |
| 4698 A_PRINTF("id=%d size=%d offset=%d\n", |
| 4699 wow_reply->wow_filters[i].wow_filter_id, |
| 4700 wow_reply->wow_filters[i].wow_filter_size, |
| 4701 wow_reply->wow_filters[i].wow_filter_offset); |
| 4702 A_PRINTF("wow pattern = "); |
| 4703 for (j=0; j< wow_reply->wow_filters[i].wow_filter_size; j++) { |
| 4704 A_PRINTF("%2.2x",wow_reply->wow_filters[i].wow_filter_pattern[j]); |
| 4705 } |
| 4706 |
| 4707 A_PRINTF("\nwow mask = "); |
| 4708 for (j=0; j< wow_reply->wow_filters[i].wow_filter_size; j++) { |
| 4709 A_PRINTF("%2.2x",wow_reply->wow_filters[i].wow_filter_mask[j]); |
| 4710 } |
| 4711 A_PRINTF("\n"); |
| 4712 } |
| 4713 } |
| 4714 |
| 4715 /* |
| 4716 * Report the Roaming related data collected on the target |
| 4717 */ |
| 4718 void |
| 4719 ar6000_display_roam_time(WMI_TARGET_ROAM_TIME *p) |
| 4720 { |
| 4721 A_PRINTF("Disconnect Data : BSSID: "); |
| 4722 AR6000_PRINT_BSSID(p->disassoc_bssid); |
| 4723 A_PRINTF(" RSSI %d DISASSOC Time %d NO_TXRX_TIME %d\n", |
| 4724 p->disassoc_bss_rssi,p->disassoc_time, |
| 4725 p->no_txrx_time); |
| 4726 A_PRINTF("Connect Data: BSSID: "); |
| 4727 AR6000_PRINT_BSSID(p->assoc_bssid); |
| 4728 A_PRINTF(" RSSI %d ASSOC Time %d TXRX_TIME %d\n", |
| 4729 p->assoc_bss_rssi,p->assoc_time, |
| 4730 p->allow_txrx_time); |
| 4731 } |
| 4732 |
| 4733 void |
| 4734 ar6000_roam_data_event(AR_SOFTC_T *ar, WMI_TARGET_ROAM_DATA *p) |
| 4735 { |
| 4736 switch (p->roamDataType) { |
| 4737 case ROAM_DATA_TIME: |
| 4738 ar6000_display_roam_time(&p->u.roamTime); |
| 4739 break; |
| 4740 default: |
| 4741 break; |
| 4742 } |
| 4743 } |
| 4744 |
| 4745 void |
| 4746 ar6000_bssInfo_event_rx(AR_SOFTC_T *ar, A_UINT8 *datap, int len) |
| 4747 { |
| 4748 struct sk_buff *skb; |
| 4749 WMI_BSS_INFO_HDR *bih = (WMI_BSS_INFO_HDR *)datap; |
| 4750 |
| 4751 |
| 4752 if (!ar->arMgmtFilter) { |
| 4753 return; |
| 4754 } |
| 4755 if (((ar->arMgmtFilter & IEEE80211_FILTER_TYPE_BEACON) && |
| 4756 (bih->frameType != BEACON_FTYPE)) || |
| 4757 ((ar->arMgmtFilter & IEEE80211_FILTER_TYPE_PROBE_RESP) && |
| 4758 (bih->frameType != PROBERESP_FTYPE))) |
| 4759 { |
| 4760 return; |
| 4761 } |
| 4762 |
| 4763 if ((skb = A_NETBUF_ALLOC_RAW(len)) != NULL) { |
| 4764 |
| 4765 A_NETBUF_PUT(skb, len); |
| 4766 A_MEMCPY(A_NETBUF_DATA(skb), datap, len); |
| 4767 skb->dev = ar->arNetDev; |
| 4768 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22) |
| 4769 A_MEMCPY(skb_mac_header(skb), A_NETBUF_DATA(skb), 6); |
| 4770 #else |
| 4771 skb->mac.raw = A_NETBUF_DATA(skb); |
| 4772 #endif |
| 4773 skb->ip_summed = CHECKSUM_NONE; |
| 4774 skb->pkt_type = PACKET_OTHERHOST; |
| 4775 skb->protocol = __constant_htons(0x0019); |
| 4776 netif_rx(skb); |
| 4777 } |
| 4778 } |
| 4779 |
| 4780 A_UINT32 wmiSendCmdNum; |
| 4781 |
| 4782 A_STATUS |
| 4783 ar6000_control_tx(void *devt, void *osbuf, HTC_ENDPOINT_ID eid) |
| 4784 { |
| 4785 AR_SOFTC_T *ar = (AR_SOFTC_T *)devt; |
| 4786 A_STATUS status = A_OK; |
| 4787 struct ar_cookie *cookie = NULL; |
| 4788 int i; |
| 4789 |
| 4790 /* take lock to protect ar6000_alloc_cookie() */ |
| 4791 AR6000_SPIN_LOCK(&ar->arLock, 0); |
| 4792 |
| 4793 do { |
| 4794 |
| 4795 AR_DEBUG_PRINTF(ATH_DEBUG_WLAN_TX,("ar_contrstatus = ol_tx: skb=0x%x, le
n=0x%x eid =%d\n", |
| 4796 (A_UINT32)osbuf, A_NETBUF_LEN(osbuf), eid)); |
| 4797 |
| 4798 if (ar->arWMIControlEpFull && (eid == ar->arControlEp)) { |
| 4799 /* control endpoint is full, don't allocate resources, we |
| 4800 * are just going to drop this packet */ |
| 4801 cookie = NULL; |
| 4802 AR_DEBUG_PRINTF(ATH_DEBUG_ERR,(" WMI Control EP full, dropping packe
t : 0x%X, len:%d \n", |
| 4803 (A_UINT32)osbuf, A_NETBUF_LEN(osbuf))); |
| 4804 } else { |
| 4805 cookie = ar6000_alloc_cookie(ar); |
| 4806 } |
| 4807 |
| 4808 if (cookie == NULL) { |
| 4809 status = A_NO_MEMORY; |
| 4810 break; |
| 4811 } |
| 4812 |
| 4813 if(logWmiRawMsgs) { |
| 4814 A_PRINTF("WMI cmd send, msgNo %d :", wmiSendCmdNum); |
| 4815 for(i = 0; i < a_netbuf_to_len(osbuf); i++) |
| 4816 A_PRINTF("%x ", ((A_UINT8 *)a_netbuf_to_data(osbuf))[i]); |
| 4817 A_PRINTF("\n"); |
| 4818 } |
| 4819 |
| 4820 wmiSendCmdNum++; |
| 4821 |
| 4822 } while (FALSE); |
| 4823 |
| 4824 if (cookie != NULL) { |
| 4825 /* got a structure to send it out on */ |
| 4826 ar->arTxPending[eid]++; |
| 4827 |
| 4828 if (eid != ar->arControlEp) { |
| 4829 ar->arTotalTxDataPending++; |
| 4830 } |
| 4831 } |
| 4832 |
| 4833 AR6000_SPIN_UNLOCK(&ar->arLock, 0); |
| 4834 |
| 4835 if (cookie != NULL) { |
| 4836 cookie->arc_bp[0] = (A_UINT32)osbuf; |
| 4837 cookie->arc_bp[1] = 0; |
| 4838 SET_HTC_PACKET_INFO_TX(&cookie->HtcPkt, |
| 4839 cookie, |
| 4840 A_NETBUF_DATA(osbuf), |
| 4841 A_NETBUF_LEN(osbuf), |
| 4842 eid, |
| 4843 AR6K_CONTROL_PKT_TAG); |
| 4844 /* this interface is asynchronous, if there is an error, cleanup wil
l happen in the |
| 4845 * TX completion callback */ |
| 4846 HTCSendPkt(ar->arHtcTarget, &cookie->HtcPkt); |
| 4847 status = A_OK; |
| 4848 } |
| 4849 |
| 4850 return status; |
| 4851 } |
| 4852 |
| 4853 /* indicate tx activity or inactivity on a WMI stream */ |
| 4854 void ar6000_indicate_tx_activity(void *devt, A_UINT8 TrafficClass, A_BOOL Active
) |
| 4855 { |
| 4856 AR_SOFTC_T *ar = (AR_SOFTC_T *)devt; |
| 4857 HTC_ENDPOINT_ID eid ; |
| 4858 int i; |
| 4859 |
| 4860 if (ar->arWmiEnabled) { |
| 4861 eid = arAc2EndpointID(ar, TrafficClass); |
| 4862 |
| 4863 AR6000_SPIN_LOCK(&ar->arLock, 0); |
| 4864 |
| 4865 ar->arAcStreamActive[TrafficClass] = Active; |
| 4866 |
| 4867 if (Active) { |
| 4868 /* when a stream goes active, keep track of the active stream with t
he highest priority */ |
| 4869 |
| 4870 if (ar->arAcStreamPriMap[TrafficClass] > ar->arHiAcStreamActivePri)
{ |
| 4871 /* set the new highest active priority */ |
| 4872 ar->arHiAcStreamActivePri = ar->arAcStreamPriMap[TrafficClass]; |
| 4873 } |
| 4874 |
| 4875 } else { |
| 4876 /* when a stream goes inactive, we may have to search for the next a
ctive stream |
| 4877 * that is the highest priority */ |
| 4878 |
| 4879 if (ar->arHiAcStreamActivePri == ar->arAcStreamPriMap[TrafficClass])
{ |
| 4880 |
| 4881 /* the highest priority stream just went inactive */ |
| 4882 |
| 4883 /* reset and search for the "next" highest "active" priority
stream */ |
| 4884 ar->arHiAcStreamActivePri = 0; |
| 4885 for (i = 0; i < WMM_NUM_AC; i++) { |
| 4886 if (ar->arAcStreamActive[i]) { |
| 4887 if (ar->arAcStreamPriMap[i] > ar->arHiAcStreamActivePri)
{ |
| 4888 /* set the new highest active priority */ |
| 4889 ar->arHiAcStreamActivePri = ar->arAcStreamPriMap[i]; |
| 4890 } |
| 4891 } |
| 4892 } |
| 4893 } |
| 4894 } |
| 4895 |
| 4896 AR6000_SPIN_UNLOCK(&ar->arLock, 0); |
| 4897 |
| 4898 } else { |
| 4899 /* for mbox ping testing, the traffic class is mapped directly as a
stream ID, |
| 4900 * see handling of AR6000_XIOCTL_TRAFFIC_ACTIVITY_CHANGE in ioctl.c
*/ |
| 4901 eid = (HTC_ENDPOINT_ID)TrafficClass; |
| 4902 } |
| 4903 |
| 4904 /* notify HTC, this may cause credit distribution changes */ |
| 4905 |
| 4906 HTCIndicateActivityChange(ar->arHtcTarget, |
| 4907 eid, |
| 4908 Active); |
| 4909 |
| 4910 } |
| 4911 |
| 4912 void |
| 4913 ar6000_btcoex_config_event(struct ar6_softc *ar, A_UINT8 *ptr, A_UINT32 len) |
| 4914 { |
| 4915 |
| 4916 WMI_BTCOEX_CONFIG_EVENT *pBtcoexConfig = (WMI_BTCOEX_CONFIG_EVENT *)ptr; |
| 4917 WMI_BTCOEX_CONFIG_EVENT *pArbtcoexConfig =&ar->arBtcoexConfig; |
| 4918 |
| 4919 AR_DEBUG_PRINTF(ATH_DEBUG_INFO,("AR6000 BTCOEX CONFIG EVENT \n")); |
| 4920 |
| 4921 A_PRINTF("received config event\n"); |
| 4922 pArbtcoexConfig->btProfileType = pBtcoexConfig->btProfileType; |
| 4923 pArbtcoexConfig->linkId = pBtcoexConfig->linkId; |
| 4924 |
| 4925 switch (pBtcoexConfig->btProfileType) { |
| 4926 case WMI_BTCOEX_BT_PROFILE_SCO: |
| 4927 A_MEMCPY(&pArbtcoexConfig->info.scoConfigCmd, &pBtcoexCo
nfig->info.scoConfigCmd, |
| 4928
sizeof(WMI_SET_BTCOEX_SCO_CONFIG_CMD)); |
| 4929 break; |
| 4930 case WMI_BTCOEX_BT_PROFILE_A2DP: |
| 4931 A_MEMCPY(&pArbtcoexConfig->info.a2dpConfigCmd, &pBtcoexC
onfig->info.a2dpConfigCmd, |
| 4932
sizeof(WMI_SET_BTCOEX_A2DP_CONFIG_CMD)); |
| 4933 break; |
| 4934 case WMI_BTCOEX_BT_PROFILE_ACLCOEX: |
| 4935 A_MEMCPY(&pArbtcoexConfig->info.aclcoexConfig, &pBtcoexConfi
g->info.aclcoexConfig, |
| 4936 sizeof(W
MI_SET_BTCOEX_ACLCOEX_CONFIG_CMD)); |
| 4937 break; |
| 4938 case WMI_BTCOEX_BT_PROFILE_INQUIRY_PAGE: |
| 4939 A_MEMCPY(&pArbtcoexConfig->info.btinquiryPageConfigCmd, &pBtc
oexConfig->info.btinquiryPageConfigCmd, |
| 4940
sizeof(WMI_SET_BTCOEX_ACLCOEX_CONFIG_CMD)); |
| 4941 break; |
| 4942 } |
| 4943 if (ar->statsUpdatePending) { |
| 4944 ar->statsUpdatePending = FALSE; |
| 4945 wake_up(&arEvent); |
| 4946 } |
| 4947 } |
| 4948 |
| 4949 void |
| 4950 ar6000_btcoex_stats_event(struct ar6_softc *ar, A_UINT8 *ptr, A_UINT32 len) |
| 4951 { |
| 4952 WMI_BTCOEX_STATS_EVENT *pBtcoexStats = (WMI_BTCOEX_STATS_EVENT *)ptr; |
| 4953 |
| 4954 AR_DEBUG_PRINTF(ATH_DEBUG_INFO,("AR6000 BTCOEX CONFIG EVENT \n")); |
| 4955 |
| 4956 A_MEMCPY(&ar->arBtcoexStats, pBtcoexStats, sizeof(WMI_BTCOEX_STATS_EVENT
)); |
| 4957 |
| 4958 if (ar->statsUpdatePending) { |
| 4959 ar->statsUpdatePending = FALSE; |
| 4960 wake_up(&arEvent); |
| 4961 } |
| 4962 |
| 4963 } |
| 4964 module_init(ar6000_init_module); |
| 4965 module_exit(ar6000_cleanup_module); |
| 4966 |
| 4967 /* Init cookie queue */ |
| 4968 static void |
| 4969 ar6000_cookie_init(AR_SOFTC_T *ar) |
| 4970 { |
| 4971 A_UINT32 i; |
| 4972 |
| 4973 ar->arCookieList = NULL; |
| 4974 ar->arCookieCount = 0; |
| 4975 |
| 4976 A_MEMZERO(s_ar_cookie_mem, sizeof(s_ar_cookie_mem)); |
| 4977 |
| 4978 for (i = 0; i < MAX_COOKIE_NUM; i++) { |
| 4979 ar6000_free_cookie(ar, &s_ar_cookie_mem[i]); |
| 4980 } |
| 4981 } |
| 4982 |
| 4983 /* cleanup cookie queue */ |
| 4984 static void |
| 4985 ar6000_cookie_cleanup(AR_SOFTC_T *ar) |
| 4986 { |
| 4987 /* It is gone .... */ |
| 4988 ar->arCookieList = NULL; |
| 4989 ar->arCookieCount = 0; |
| 4990 } |
| 4991 |
| 4992 /* Init cookie queue */ |
| 4993 static void |
| 4994 ar6000_free_cookie(AR_SOFTC_T *ar, struct ar_cookie * cookie) |
| 4995 { |
| 4996 /* Insert first */ |
| 4997 A_ASSERT(ar != NULL); |
| 4998 A_ASSERT(cookie != NULL); |
| 4999 |
| 5000 cookie->arc_list_next = ar->arCookieList; |
| 5001 ar->arCookieList = cookie; |
| 5002 ar->arCookieCount++; |
| 5003 } |
| 5004 |
| 5005 /* cleanup cookie queue */ |
| 5006 static struct ar_cookie * |
| 5007 ar6000_alloc_cookie(AR_SOFTC_T *ar) |
| 5008 { |
| 5009 struct ar_cookie *cookie; |
| 5010 |
| 5011 cookie = ar->arCookieList; |
| 5012 if(cookie != NULL) |
| 5013 { |
| 5014 ar->arCookieList = cookie->arc_list_next; |
| 5015 ar->arCookieCount--; |
| 5016 } |
| 5017 |
| 5018 return cookie; |
| 5019 } |
| 5020 |
| 5021 #ifdef SEND_EVENT_TO_APP |
| 5022 /* |
| 5023 * This function is used to send event which come from taget to |
| 5024 * the application. The buf which send to application is include |
| 5025 * the event ID and event content. |
| 5026 */ |
| 5027 #define EVENT_ID_LEN 2 |
| 5028 void ar6000_send_event_to_app(AR_SOFTC_T *ar, A_UINT16 eventId, |
| 5029 A_UINT8 *datap, int len) |
| 5030 { |
| 5031 |
| 5032 #if (WIRELESS_EXT >= 15) |
| 5033 |
| 5034 /* note: IWEVCUSTOM only exists in wireless extensions after version 15 */ |
| 5035 |
| 5036 char *buf; |
| 5037 A_UINT16 size; |
| 5038 union iwreq_data wrqu; |
| 5039 |
| 5040 size = len + EVENT_ID_LEN; |
| 5041 |
| 5042 if (size > IW_CUSTOM_MAX) { |
| 5043 AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("WMI event ID : 0x%4.4X, len = %d too big
for IWEVCUSTOM (max=%d) \n", |
| 5044 eventId, size, IW_CUSTOM_MAX)); |
| 5045 return; |
| 5046 } |
| 5047 |
| 5048 buf = A_MALLOC_NOWAIT(size); |
| 5049 if (NULL == buf){ |
| 5050 AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("%s: failed to allocate %d bytes\n", __fu
nc__, size)); |
| 5051 return; |
| 5052 } |
| 5053 |
| 5054 A_MEMZERO(buf, size); |
| 5055 A_MEMCPY(buf, &eventId, EVENT_ID_LEN); |
| 5056 A_MEMCPY(buf+EVENT_ID_LEN, datap, len); |
| 5057 |
| 5058 //AR_DEBUG_PRINTF(ATH_DEBUG_INFO,("event ID = %d,len = %d\n",*(A_UINT16*)buf
, size)); |
| 5059 A_MEMZERO(&wrqu, sizeof(wrqu)); |
| 5060 wrqu.data.length = size; |
| 5061 wireless_send_event(ar->arNetDev, IWEVCUSTOM, &wrqu, buf); |
| 5062 |
| 5063 A_FREE(buf); |
| 5064 #endif |
| 5065 |
| 5066 |
| 5067 } |
| 5068 |
| 5069 /* |
| 5070 * This function is used to send events larger than 256 bytes |
| 5071 * to the application. The buf which is sent to application |
| 5072 * includes the event ID and event content. |
| 5073 */ |
| 5074 void ar6000_send_generic_event_to_app(AR_SOFTC_T *ar, A_UINT16 eventId, |
| 5075 A_UINT8 *datap, int len) |
| 5076 { |
| 5077 |
| 5078 #if (WIRELESS_EXT >= 18) |
| 5079 |
| 5080 /* IWEVGENIE exists in wireless extensions version 18 onwards */ |
| 5081 |
| 5082 char *buf; |
| 5083 A_UINT16 size; |
| 5084 union iwreq_data wrqu; |
| 5085 |
| 5086 size = len + EVENT_ID_LEN; |
| 5087 |
| 5088 if (size > IW_GENERIC_IE_MAX) { |
| 5089 AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("WMI event ID : 0x%4.4X, len = %d too big
for IWEVGENIE (max=%d) \n", |
| 5090 eventId, size, IW_GENERIC_IE_MAX)); |
| 5091 return; |
| 5092 } |
| 5093 |
| 5094 buf = A_MALLOC_NOWAIT(size); |
| 5095 if (NULL == buf){ |
| 5096 AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("%s: failed to allocate %d bytes\n", __fu
nc__, size)); |
| 5097 return; |
| 5098 } |
| 5099 |
| 5100 A_MEMZERO(buf, size); |
| 5101 A_MEMCPY(buf, &eventId, EVENT_ID_LEN); |
| 5102 A_MEMCPY(buf+EVENT_ID_LEN, datap, len); |
| 5103 |
| 5104 A_MEMZERO(&wrqu, sizeof(wrqu)); |
| 5105 wrqu.data.length = size; |
| 5106 wireless_send_event(ar->arNetDev, IWEVGENIE, &wrqu, buf); |
| 5107 |
| 5108 A_FREE(buf); |
| 5109 |
| 5110 #endif /* (WIRELESS_EXT >= 18) */ |
| 5111 |
| 5112 } |
| 5113 #endif /* SEND_EVENT_TO_APP */ |
| 5114 |
| 5115 |
| 5116 void |
| 5117 ar6000_tx_retry_err_event(void *devt) |
| 5118 { |
| 5119 AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Tx retries reach maximum!\n")); |
| 5120 } |
| 5121 |
| 5122 void |
| 5123 ar6000_snrThresholdEvent_rx(void *devt, WMI_SNR_THRESHOLD_VAL newThreshold, A_UI
NT8 snr) |
| 5124 { |
| 5125 WMI_SNR_THRESHOLD_EVENT event; |
| 5126 AR_SOFTC_T *ar = (AR_SOFTC_T *)devt; |
| 5127 |
| 5128 event.range = newThreshold; |
| 5129 event.snr = snr; |
| 5130 |
| 5131 ar6000_send_event_to_app(ar, WMI_SNR_THRESHOLD_EVENTID, (A_UINT8 *)&event, |
| 5132 sizeof(WMI_SNR_THRESHOLD_EVENT)); |
| 5133 } |
| 5134 |
| 5135 void |
| 5136 ar6000_lqThresholdEvent_rx(void *devt, WMI_LQ_THRESHOLD_VAL newThreshold, A_UINT
8 lq) |
| 5137 { |
| 5138 AR_DEBUG_PRINTF(ATH_DEBUG_INFO,("lq threshold range %d, lq %d\n", newThresho
ld, lq)); |
| 5139 } |
| 5140 |
| 5141 |
| 5142 |
| 5143 A_UINT32 |
| 5144 a_copy_to_user(void *to, const void *from, A_UINT32 n) |
| 5145 { |
| 5146 return(copy_to_user(to, from, n)); |
| 5147 } |
| 5148 |
| 5149 A_UINT32 |
| 5150 a_copy_from_user(void *to, const void *from, A_UINT32 n) |
| 5151 { |
| 5152 return(copy_from_user(to, from, n)); |
| 5153 } |
| 5154 |
| 5155 |
| 5156 A_STATUS |
| 5157 ar6000_get_driver_cfg(struct net_device *dev, |
| 5158 A_UINT16 cfgParam, |
| 5159 void *result) |
| 5160 { |
| 5161 |
| 5162 A_STATUS ret = 0; |
| 5163 |
| 5164 switch(cfgParam) |
| 5165 { |
| 5166 case AR6000_DRIVER_CFG_GET_WLANNODECACHING: |
| 5167 *((A_UINT32 *)result) = wlanNodeCaching; |
| 5168 break; |
| 5169 case AR6000_DRIVER_CFG_LOG_RAW_WMI_MSGS: |
| 5170 *((A_UINT32 *)result) = logWmiRawMsgs; |
| 5171 break; |
| 5172 default: |
| 5173 ret = EINVAL; |
| 5174 break; |
| 5175 } |
| 5176 |
| 5177 return ret; |
| 5178 } |
| 5179 |
| 5180 void |
| 5181 ar6000_keepalive_rx(void *devt, A_UINT8 configured) |
| 5182 { |
| 5183 AR_SOFTC_T *ar = (AR_SOFTC_T *)devt; |
| 5184 |
| 5185 ar->arKeepaliveConfigured = configured; |
| 5186 wake_up(&arEvent); |
| 5187 } |
| 5188 |
| 5189 void |
| 5190 ar6000_pmkid_list_event(void *devt, A_UINT8 numPMKID, WMI_PMKID *pmkidList, |
| 5191 A_UINT8 *bssidList) |
| 5192 { |
| 5193 A_UINT8 i, j; |
| 5194 |
| 5195 A_PRINTF("Number of Cached PMKIDs is %d\n", numPMKID); |
| 5196 |
| 5197 for (i = 0; i < numPMKID; i++) { |
| 5198 A_PRINTF("\nBSSID %d ", i); |
| 5199 for (j = 0; j < ATH_MAC_LEN; j++) { |
| 5200 A_PRINTF("%2.2x", bssidList[j]); |
| 5201 } |
| 5202 bssidList += (ATH_MAC_LEN + WMI_PMKID_LEN); |
| 5203 A_PRINTF("\nPMKID %d ", i); |
| 5204 for (j = 0; j < WMI_PMKID_LEN; j++) { |
| 5205 A_PRINTF("%2.2x", pmkidList->pmkid[j]); |
| 5206 } |
| 5207 pmkidList = (WMI_PMKID *)((A_UINT8 *)pmkidList + ATH_MAC_LEN + |
| 5208 WMI_PMKID_LEN); |
| 5209 } |
| 5210 } |
| 5211 |
| 5212 void ar6000_pspoll_event(AR_SOFTC_T *ar,A_UINT8 aid) |
| 5213 { |
| 5214 sta_t *conn=NULL; |
| 5215 A_BOOL isPsqEmpty = FALSE; |
| 5216 |
| 5217 conn = ieee80211_find_conn_for_aid(ar, aid); |
| 5218 |
| 5219 /* If the PS q for this STA is not empty, dequeue and send a pkt from |
| 5220 * the head of the q. Also update the More data bit in the WMI_DATA_HDR |
| 5221 * if there are more pkts for this STA in the PS q. If there are no more |
| 5222 * pkts for this STA, update the PVB for this STA. |
| 5223 */ |
| 5224 A_MUTEX_LOCK(&conn->psqLock); |
| 5225 isPsqEmpty = A_NETBUF_QUEUE_EMPTY(&conn->psq); |
| 5226 A_MUTEX_UNLOCK(&conn->psqLock); |
| 5227 |
| 5228 if (isPsqEmpty) { |
| 5229 /* TODO:No buffered pkts for this STA. Send out a NULL data frame */ |
| 5230 } else { |
| 5231 struct sk_buff *skb = NULL; |
| 5232 |
| 5233 A_MUTEX_LOCK(&conn->psqLock); |
| 5234 skb = A_NETBUF_DEQUEUE(&conn->psq); |
| 5235 A_MUTEX_UNLOCK(&conn->psqLock); |
| 5236 /* Set the STA flag to PSPolled, so that the frame will go out */ |
| 5237 STA_SET_PS_POLLED(conn); |
| 5238 ar6000_data_tx(skb, ar->arNetDev); |
| 5239 STA_CLR_PS_POLLED(conn); |
| 5240 |
| 5241 /* Clear the PVB for this STA if the queue has become empty */ |
| 5242 A_MUTEX_LOCK(&conn->psqLock); |
| 5243 isPsqEmpty = A_NETBUF_QUEUE_EMPTY(&conn->psq); |
| 5244 A_MUTEX_UNLOCK(&conn->psqLock); |
| 5245 |
| 5246 if (isPsqEmpty) { |
| 5247 wmi_set_pvb_cmd(ar->arWmi, conn->aid, 0); |
| 5248 } |
| 5249 } |
| 5250 } |
| 5251 |
| 5252 void ar6000_dtimexpiry_event(AR_SOFTC_T *ar) |
| 5253 { |
| 5254 A_BOOL isMcastQueued = FALSE; |
| 5255 struct sk_buff *skb = NULL; |
| 5256 |
| 5257 /* If there are no associated STAs, ignore the DTIM expiry event. |
| 5258 * There can be potential race conditions where the last associated |
| 5259 * STA may disconnect & before the host could clear the 'Indicate DTIM' |
| 5260 * request to the firmware, the firmware would have just indicated a DTIM |
| 5261 * expiry event. The race is between 'clear DTIM expiry cmd' going |
| 5262 * from the host to the firmware & the DTIM expiry event happening from |
| 5263 * the firmware to the host. |
| 5264 */ |
| 5265 if (ar->sta_list_index == 0) { |
| 5266 return; |
| 5267 } |
| 5268 |
| 5269 A_MUTEX_LOCK(&ar->mcastpsqLock); |
| 5270 isMcastQueued = A_NETBUF_QUEUE_EMPTY(&ar->mcastpsq); |
| 5271 A_MUTEX_UNLOCK(&ar->mcastpsqLock); |
| 5272 |
| 5273 A_ASSERT(isMcastQueued == FALSE); |
| 5274 |
| 5275 /* Flush the mcast psq to the target */ |
| 5276 /* Set the STA flag to DTIMExpired, so that the frame will go out */ |
| 5277 ar->DTIMExpired = TRUE; |
| 5278 |
| 5279 A_MUTEX_LOCK(&ar->mcastpsqLock); |
| 5280 while (!A_NETBUF_QUEUE_EMPTY(&ar->mcastpsq)) { |
| 5281 skb = A_NETBUF_DEQUEUE(&ar->mcastpsq); |
| 5282 A_MUTEX_UNLOCK(&ar->mcastpsqLock); |
| 5283 |
| 5284 ar6000_data_tx(skb, ar->arNetDev); |
| 5285 |
| 5286 A_MUTEX_LOCK(&ar->mcastpsqLock); |
| 5287 } |
| 5288 A_MUTEX_UNLOCK(&ar->mcastpsqLock); |
| 5289 |
| 5290 /* Reset the DTIMExpired flag back to 0 */ |
| 5291 ar->DTIMExpired = FALSE; |
| 5292 |
| 5293 /* Clear the LSB of the BitMapCtl field of the TIM IE */ |
| 5294 wmi_set_pvb_cmd(ar->arWmi, MCAST_AID, 0); |
| 5295 } |
| 5296 |
| 5297 void |
| 5298 read_rssi_compensation_param(AR_SOFTC_T *ar) |
| 5299 { |
| 5300 HIF_DEVICE *device= ar->arHifDevice; |
| 5301 A_UINT32 rssicomp; |
| 5302 A_UINT32 param; |
| 5303 |
| 5304 if (BMIReadMemory(device, |
| 5305 HOST_INTEREST_ITEM_ADDRESS(ar, hi_board_data), |
| 5306 (A_UCHAR *)&rssicomp, |
| 5307 4)!= A_OK) |
| 5308 { |
| 5309 AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("BMIReadMemory for reading board data ad
dress failed \n")); |
| 5310 return; |
| 5311 } |
| 5312 |
| 5313 rssicomp += 0x40; |
| 5314 if (BMIReadSOCRegister(device, rssicomp, ¶m)!= A_OK) { |
| 5315 AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("BMIReadSOCRegister () failed \n")); |
| 5316 return ; |
| 5317 } |
| 5318 rssi_compensation_param.a_enable = (A_INT16) (param & 0xffff); |
| 5319 rssi_compensation_param.a_param_a = (A_INT16) (param >> 16); |
| 5320 |
| 5321 rssicomp += 4; |
| 5322 if (BMIReadSOCRegister(device, rssicomp, ¶m)!= A_OK) { |
| 5323 AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("BMIReadSOCRegister () failed \n")); |
| 5324 return ; |
| 5325 } |
| 5326 rssi_compensation_param.a_param_b = (A_INT16) (param & 0xffff); |
| 5327 rssi_compensation_param.bg_enable = (A_INT16) (param >> 16); |
| 5328 |
| 5329 rssicomp += 4; |
| 5330 if (BMIReadSOCRegister(device, rssicomp, ¶m)!= A_OK) { |
| 5331 AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("BMIReadSOCRegister () failed \n")); |
| 5332 return ; |
| 5333 } |
| 5334 rssi_compensation_param.bg_param_a = (A_INT16) (param & 0xffff); |
| 5335 rssi_compensation_param.bg_param_b = (A_INT16) (param >> 16); |
| 5336 |
| 5337 if (rssi_compensation_param.bg_enable != 0x1) |
| 5338 rssi_compensation_param.bg_enable = 0; |
| 5339 |
| 5340 if (rssi_compensation_param.a_enable != 0x1) |
| 5341 rssi_compensation_param.a_enable = 0; |
| 5342 |
| 5343 AR_DEBUG_PRINTF(ATH_DEBUG_INFO, ("compensation flag = %d a = %d b = %d\n",\ |
| 5344 rssi_compensation_param.bg_enable, |
| 5345 rssi_compensation_param.bg_param_a, |
| 5346 rssi_compensation_param.bg_param_b)); |
| 5347 |
| 5348 AR_DEBUG_PRINTF(ATH_DEBUG_INFO, ("compensation flag = %d a = %d b = %d\n",\ |
| 5349 rssi_compensation_param.a_enable, |
| 5350 rssi_compensation_param.a_param_a, |
| 5351 rssi_compensation_param.a_param_b)); |
| 5352 |
| 5353 return ; |
| 5354 } |
| 5355 |
| 5356 A_INT32 |
| 5357 rssi_compensation_calc_tcmd(A_UINT32 freq, A_INT32 rssi, A_UINT32 totalPkt) |
| 5358 { |
| 5359 |
| 5360 if (freq > 5000) |
| 5361 { |
| 5362 if (rssi_compensation_param.a_enable) |
| 5363 { |
| 5364 AR_DEBUG_PRINTF(ATH_DEBUG_INFO, (">>> 11a\n")); |
| 5365 AR_DEBUG_PRINTF(ATH_DEBUG_INFO, ("rssi before compensation = %d, to
talPkt = %d\n", rssi,totalPkt)); |
| 5366 rssi = rssi * rssi_compensation_param.a_param_a + totalPkt * rssi_co
mpensation_param.a_param_b; |
| 5367 rssi = (rssi-50) /100; |
| 5368 AR_DEBUG_PRINTF(ATH_DEBUG_INFO, ("rssi after compensation = %d\n", r
ssi)); |
| 5369 } |
| 5370 } |
| 5371 else |
| 5372 { |
| 5373 if (rssi_compensation_param.bg_enable) |
| 5374 { |
| 5375 AR_DEBUG_PRINTF(ATH_DEBUG_INFO, (">>> 11bg\n")); |
| 5376 AR_DEBUG_PRINTF(ATH_DEBUG_INFO, ("rssi before compensation = %d, to
talPkt = %d\n", rssi,totalPkt)); |
| 5377 rssi = rssi * rssi_compensation_param.bg_param_a + totalPkt * rssi_c
ompensation_param.bg_param_b; |
| 5378 rssi = (rssi-50) /100; |
| 5379 AR_DEBUG_PRINTF(ATH_DEBUG_INFO, ("rssi after compensation = %d\n", r
ssi)); |
| 5380 } |
| 5381 } |
| 5382 |
| 5383 return rssi; |
| 5384 } |
| 5385 |
| 5386 A_INT16 |
| 5387 rssi_compensation_calc(AR_SOFTC_T *ar, A_INT16 rssi) |
| 5388 { |
| 5389 if (ar->arBssChannel > 5000) |
| 5390 { |
| 5391 if (rssi_compensation_param.a_enable) |
| 5392 { |
| 5393 AR_DEBUG_PRINTF(ATH_DEBUG_INFO, (">>> 11a\n")); |
| 5394 AR_DEBUG_PRINTF(ATH_DEBUG_INFO, ("rssi before compensation = %d\n",
rssi)); |
| 5395 rssi = rssi * rssi_compensation_param.a_param_a + rssi_compensation_
param.a_param_b; |
| 5396 rssi = (rssi-50) /100; |
| 5397 AR_DEBUG_PRINTF(ATH_DEBUG_INFO, ("rssi after compensation = %d\n", r
ssi)); |
| 5398 } |
| 5399 } |
| 5400 else |
| 5401 { |
| 5402 if (rssi_compensation_param.bg_enable) |
| 5403 { |
| 5404 AR_DEBUG_PRINTF(ATH_DEBUG_INFO, (">>> 11bg\n")); |
| 5405 AR_DEBUG_PRINTF(ATH_DEBUG_INFO, ("rssi before compensation = %d\n",
rssi)); |
| 5406 rssi = rssi * rssi_compensation_param.bg_param_a + rssi_compensation
_param.bg_param_b; |
| 5407 rssi = (rssi-50) /100; |
| 5408 AR_DEBUG_PRINTF(ATH_DEBUG_INFO, ("rssi after compensation = %d\n", r
ssi)); |
| 5409 } |
| 5410 } |
| 5411 |
| 5412 return rssi; |
| 5413 } |
| 5414 |
| 5415 A_INT16 |
| 5416 rssi_compensation_reverse_calc(AR_SOFTC_T *ar, A_INT16 rssi, A_BOOL Above) |
| 5417 { |
| 5418 A_INT16 i; |
| 5419 |
| 5420 if (ar->arBssChannel > 5000) |
| 5421 { |
| 5422 if (rssi_compensation_param.a_enable) |
| 5423 { |
| 5424 AR_DEBUG_PRINTF(ATH_DEBUG_INFO, (">>> 11a\n")); |
| 5425 AR_DEBUG_PRINTF(ATH_DEBUG_INFO, ("rssi before rev compensation = %d
\n", rssi)); |
| 5426 rssi = rssi * 100; |
| 5427 rssi = (rssi - rssi_compensation_param.a_param_b) / rssi_compensatio
n_param.a_param_a; |
| 5428 AR_DEBUG_PRINTF(ATH_DEBUG_INFO, ("rssi after rev compensation = %d\n
", rssi)); |
| 5429 } |
| 5430 } |
| 5431 else |
| 5432 { |
| 5433 if (rssi_compensation_param.bg_enable) |
| 5434 { |
| 5435 AR_DEBUG_PRINTF(ATH_DEBUG_INFO, (">>> 11bg\n")); |
| 5436 AR_DEBUG_PRINTF(ATH_DEBUG_INFO, ("rssi before rev compensation = %d
\n", rssi)); |
| 5437 |
| 5438 if (Above) { |
| 5439 for (i=95; i>=0; i--) { |
| 5440 if (rssi <= rssi_compensation_table[i]) { |
| 5441 rssi = 0 - i; |
| 5442 break; |
| 5443 } |
| 5444 } |
| 5445 } else { |
| 5446 for (i=0; i<=95; i++) { |
| 5447 if (rssi >= rssi_compensation_table[i]) { |
| 5448 rssi = 0 - i; |
| 5449 break; |
| 5450 } |
| 5451 } |
| 5452 } |
| 5453 AR_DEBUG_PRINTF(ATH_DEBUG_INFO, ("rssi after rev compensation = %d\n
", rssi)); |
| 5454 } |
| 5455 } |
| 5456 |
| 5457 return rssi; |
| 5458 } |
| 5459 |
| 5460 #ifdef WAPI_ENABLE |
| 5461 void ap_wapi_rekey_event(AR_SOFTC_T *ar, A_UINT8 type, A_UINT8 *mac) |
| 5462 { |
| 5463 union iwreq_data wrqu; |
| 5464 A_UINT8 buf[20]; |
| 5465 |
| 5466 A_MEMZERO(buf, sizeof(buf)); |
| 5467 |
| 5468 strcpy(buf, "WAPI_REKEY"); |
| 5469 buf[10] = type; |
| 5470 A_MEMCPY(&buf[11], mac, ATH_MAC_LEN); |
| 5471 |
| 5472 A_MEMZERO(&wrqu, sizeof(wrqu)); |
| 5473 wrqu.data.length = 10+1+ATH_MAC_LEN; |
| 5474 wireless_send_event(ar->arNetDev, IWEVCUSTOM, &wrqu, buf); |
| 5475 |
| 5476 A_PRINTF("WAPI REKEY - %d - %02x:%02x\n", type, mac[4], mac[5]); |
| 5477 } |
| 5478 #endif |
| 5479 |
| 5480 #ifdef USER_KEYS |
| 5481 static A_STATUS |
| 5482 |
| 5483 ar6000_reinstall_keys(AR_SOFTC_T *ar, A_UINT8 key_op_ctrl) |
| 5484 { |
| 5485 A_STATUS status = A_OK; |
| 5486 struct ieee80211req_key *uik = &ar->user_saved_keys.ucast_ik; |
| 5487 struct ieee80211req_key *bik = &ar->user_saved_keys.bcast_ik; |
| 5488 CRYPTO_TYPE keyType = ar->user_saved_keys.keyType; |
| 5489 |
| 5490 if (IEEE80211_CIPHER_CCKM_KRK != uik->ik_type) { |
| 5491 if (NONE_CRYPT == keyType) { |
| 5492 goto _reinstall_keys_out; |
| 5493 } |
| 5494 |
| 5495 if (uik->ik_keylen) { |
| 5496 status = wmi_addKey_cmd(ar->arWmi, uik->ik_keyix, |
| 5497 ar->user_saved_keys.keyType, PAIRWISE_USAGE, |
| 5498 uik->ik_keylen, (A_UINT8 *)&uik->ik_keyrsc, |
| 5499 uik->ik_keydata, key_op_ctrl, uik->ik_macaddr, SYNC_BEFORE_W
MIFLAG); |
| 5500 } |
| 5501 |
| 5502 } else { |
| 5503 status = wmi_add_krk_cmd(ar->arWmi, uik->ik_keydata); |
| 5504 } |
| 5505 |
| 5506 if (IEEE80211_CIPHER_CCKM_KRK != bik->ik_type) { |
| 5507 if (NONE_CRYPT == keyType) { |
| 5508 goto _reinstall_keys_out; |
| 5509 } |
| 5510 |
| 5511 if (bik->ik_keylen) { |
| 5512 status = wmi_addKey_cmd(ar->arWmi, bik->ik_keyix, |
| 5513 ar->user_saved_keys.keyType, GROUP_USAGE, |
| 5514 bik->ik_keylen, (A_UINT8 *)&bik->ik_keyrsc, |
| 5515 bik->ik_keydata, key_op_ctrl, bik->ik_macaddr, NO_SYNC_WMIFL
AG); |
| 5516 } |
| 5517 } else { |
| 5518 status = wmi_add_krk_cmd(ar->arWmi, bik->ik_keydata); |
| 5519 } |
| 5520 |
| 5521 _reinstall_keys_out: |
| 5522 ar->user_savedkeys_stat = USER_SAVEDKEYS_STAT_INIT; |
| 5523 ar->user_key_ctrl = 0; |
| 5524 |
| 5525 return status; |
| 5526 } |
| 5527 #endif /* USER_KEYS */ |
| 5528 |
| 5529 |
| 5530 void |
| 5531 ar6000_dset_open_req( |
| 5532 void *context, |
| 5533 A_UINT32 id, |
| 5534 A_UINT32 targHandle, |
| 5535 A_UINT32 targReplyFn, |
| 5536 A_UINT32 targReplyArg) |
| 5537 { |
| 5538 } |
| 5539 |
| 5540 void |
| 5541 ar6000_dset_close( |
| 5542 void *context, |
| 5543 A_UINT32 access_cookie) |
| 5544 { |
| 5545 return; |
| 5546 } |
| 5547 |
| 5548 void |
| 5549 ar6000_dset_data_req( |
| 5550 void *context, |
| 5551 A_UINT32 accessCookie, |
| 5552 A_UINT32 offset, |
| 5553 A_UINT32 length, |
| 5554 A_UINT32 targBuf, |
| 5555 A_UINT32 targReplyFn, |
| 5556 A_UINT32 targReplyArg) |
| 5557 { |
| 5558 } |
| 5559 |
| 5560 int |
| 5561 ar6000_ap_mode_profile_commit(struct ar6_softc *ar) |
| 5562 { |
| 5563 WMI_CONNECT_CMD p; |
| 5564 unsigned long flags; |
| 5565 |
| 5566 /* No change in AP's profile configuration */ |
| 5567 if(ar->ap_profile_flag==0) { |
| 5568 A_PRINTF("COMMIT: No change in profile!!!\n"); |
| 5569 return -ENODATA; |
| 5570 } |
| 5571 |
| 5572 if(!ar->arSsidLen) { |
| 5573 A_PRINTF("SSID not set!!!\n"); |
| 5574 return -ECHRNG; |
| 5575 } |
| 5576 |
| 5577 switch(ar->arAuthMode) { |
| 5578 case NONE_AUTH: |
| 5579 if((ar->arPairwiseCrypto != NONE_CRYPT) && |
| 5580 #ifdef WAPI_ENABLE |
| 5581 (ar->arPairwiseCrypto != WAPI_CRYPT) && |
| 5582 #endif |
| 5583 (ar->arPairwiseCrypto != WEP_CRYPT)) { |
| 5584 A_PRINTF("Cipher not supported in AP mode Open auth\n"); |
| 5585 return -EOPNOTSUPP; |
| 5586 } |
| 5587 break; |
| 5588 case WPA_PSK_AUTH: |
| 5589 case WPA2_PSK_AUTH: |
| 5590 case (WPA_PSK_AUTH|WPA2_PSK_AUTH): |
| 5591 break; |
| 5592 default: |
| 5593 A_PRINTF("This key mgmt type not supported in AP mode\n"); |
| 5594 return -EOPNOTSUPP; |
| 5595 } |
| 5596 |
| 5597 /* Update the arNetworkType */ |
| 5598 ar->arNetworkType = ar->arNextMode; |
| 5599 |
| 5600 A_MEMZERO(&p,sizeof(p)); |
| 5601 p.ssidLength = ar->arSsidLen; |
| 5602 A_MEMCPY(p.ssid,ar->arSsid,p.ssidLength); |
| 5603 p.channel = ar->arChannelHint; |
| 5604 p.networkType = ar->arNetworkType; |
| 5605 |
| 5606 p.dot11AuthMode = ar->arDot11AuthMode; |
| 5607 p.authMode = ar->arAuthMode; |
| 5608 p.pairwiseCryptoType = ar->arPairwiseCrypto; |
| 5609 p.pairwiseCryptoLen = ar->arPairwiseCryptoLen; |
| 5610 p.groupCryptoType = ar->arGroupCrypto; |
| 5611 p.groupCryptoLen = ar->arGroupCryptoLen; |
| 5612 p.ctrl_flags = ar->arConnectCtrlFlags; |
| 5613 |
| 5614 ar->arConnected = FALSE; |
| 5615 |
| 5616 wmi_ap_profile_commit(ar->arWmi, &p); |
| 5617 spin_lock_irqsave(&ar->arLock, flags); |
| 5618 ar->arConnected = TRUE; |
| 5619 netif_carrier_on(ar->arNetDev); |
| 5620 spin_unlock_irqrestore(&ar->arLock, flags); |
| 5621 ar->ap_profile_flag = 0; |
| 5622 return 0; |
| 5623 } |
| 5624 |
| 5625 A_STATUS |
| 5626 ar6000_ap_mode_get_wpa_ie(struct ar6_softc *ar, struct ieee80211req_wpaie *wpaie
) |
| 5627 { |
| 5628 sta_t *conn = NULL; |
| 5629 conn = ieee80211_find_conn(ar, wpaie->wpa_macaddr); |
| 5630 |
| 5631 A_MEMZERO(wpaie->wpa_ie, IEEE80211_MAX_IE); |
| 5632 A_MEMZERO(wpaie->rsn_ie, IEEE80211_MAX_IE); |
| 5633 |
| 5634 if(conn) { |
| 5635 A_MEMCPY(wpaie->wpa_ie, conn->wpa_ie, IEEE80211_MAX_IE); |
| 5636 } |
| 5637 |
| 5638 return 0; |
| 5639 } |
| 5640 |
| 5641 A_STATUS |
| 5642 is_iwioctl_allowed(A_UINT8 mode, A_UINT16 cmd) |
| 5643 { |
| 5644 if(cmd >= SIOCSIWCOMMIT && cmd <= SIOCGIWPOWER) { |
| 5645 cmd -= SIOCSIWCOMMIT; |
| 5646 if(sioctl_filter[cmd] == 0xFF) return A_OK; |
| 5647 if(sioctl_filter[cmd] & mode) return A_OK; |
| 5648 } else if(cmd >= SIOCIWFIRSTPRIV && cmd <= (SIOCIWFIRSTPRIV+30)) { |
| 5649 cmd -= SIOCIWFIRSTPRIV; |
| 5650 if(pioctl_filter[cmd] == 0xFF) return A_OK; |
| 5651 if(pioctl_filter[cmd] & mode) return A_OK; |
| 5652 } else { |
| 5653 return A_ERROR; |
| 5654 } |
| 5655 return A_ENOTSUP; |
| 5656 } |
| 5657 |
| 5658 A_STATUS |
| 5659 is_xioctl_allowed(A_UINT8 mode, int cmd) |
| 5660 { |
| 5661 if(sizeof(xioctl_filter)-1 < cmd) { |
| 5662 A_PRINTF("Filter for this cmd=%d not defined\n",cmd); |
| 5663 return 0; |
| 5664 } |
| 5665 if(xioctl_filter[cmd] == 0xFF) return A_OK; |
| 5666 if(xioctl_filter[cmd] & mode) return A_OK; |
| 5667 return A_ERROR; |
| 5668 } |
| 5669 |
| 5670 #ifdef WAPI_ENABLE |
| 5671 int |
| 5672 ap_set_wapi_key(struct ar6_softc *ar, void *ikey) |
| 5673 { |
| 5674 struct ieee80211req_key *ik = (struct ieee80211req_key *)ikey; |
| 5675 KEY_USAGE keyUsage = 0; |
| 5676 A_STATUS status; |
| 5677 |
| 5678 if (A_MEMCMP(ik->ik_macaddr, bcast_mac, IEEE80211_ADDR_LEN) == 0) { |
| 5679 keyUsage = GROUP_USAGE; |
| 5680 } else { |
| 5681 keyUsage = PAIRWISE_USAGE; |
| 5682 } |
| 5683 A_PRINTF("WAPI_KEY: Type:%d ix:%d mac:%02x:%02x len:%d\n", |
| 5684 keyUsage, ik->ik_keyix, ik->ik_macaddr[4], ik->ik_macaddr[5], |
| 5685 ik->ik_keylen); |
| 5686 |
| 5687 status = wmi_addKey_cmd(ar->arWmi, ik->ik_keyix, WAPI_CRYPT, keyUsage, |
| 5688 ik->ik_keylen, (A_UINT8 *)&ik->ik_keyrsc, |
| 5689 ik->ik_keydata, KEY_OP_INIT_VAL, ik->ik_macaddr, |
| 5690 SYNC_BOTH_WMIFLAG); |
| 5691 |
| 5692 if (A_OK != status) { |
| 5693 return -EIO; |
| 5694 } |
| 5695 return 0; |
| 5696 } |
| 5697 #endif |
| 5698 |
| 5699 void ar6000_peer_event( |
| 5700 void *context, |
| 5701 A_UINT8 eventCode, |
| 5702 A_UINT8 *macAddr) |
| 5703 { |
| 5704 A_UINT8 pos; |
| 5705 |
| 5706 for (pos=0;pos<6;pos++) |
| 5707 printk("%02x: ",*(macAddr+pos)); |
| 5708 printk("\n"); |
| 5709 } |
| 5710 |
| 5711 #ifdef HTC_TEST_SEND_PKTS |
| 5712 #define HTC_TEST_DUPLICATE 8 |
| 5713 static void DoHTCSendPktsTest(AR_SOFTC_T *ar, int MapNo, HTC_ENDPOINT_ID eid, st
ruct sk_buff *dupskb) |
| 5714 { |
| 5715 struct ar_cookie *cookie; |
| 5716 struct ar_cookie *cookieArray[HTC_TEST_DUPLICATE]; |
| 5717 struct sk_buff *new_skb; |
| 5718 int i; |
| 5719 int pkts = 0; |
| 5720 HTC_PACKET_QUEUE pktQueue; |
| 5721 EPPING_HEADER *eppingHdr; |
| 5722 |
| 5723 eppingHdr = A_NETBUF_DATA(dupskb); |
| 5724 |
| 5725 if (eppingHdr->Cmd_h == EPPING_CMD_NO_ECHO) { |
| 5726 /* skip test if this is already a tx perf test */ |
| 5727 return; |
| 5728 } |
| 5729 |
| 5730 for (i = 0; i < HTC_TEST_DUPLICATE; i++,pkts++) { |
| 5731 AR6000_SPIN_LOCK(&ar->arLock, 0); |
| 5732 cookie = ar6000_alloc_cookie(ar); |
| 5733 if (cookie != NULL) { |
| 5734 ar->arTxPending[eid]++; |
| 5735 ar->arTotalTxDataPending++; |
| 5736 } |
| 5737 |
| 5738 AR6000_SPIN_UNLOCK(&ar->arLock, 0); |
| 5739 |
| 5740 if (NULL == cookie) { |
| 5741 break; |
| 5742 } |
| 5743 |
| 5744 new_skb = A_NETBUF_ALLOC(A_NETBUF_LEN(dupskb)); |
| 5745 |
| 5746 if (new_skb == NULL) { |
| 5747 AR6000_SPIN_LOCK(&ar->arLock, 0); |
| 5748 ar6000_free_cookie(ar,cookie); |
| 5749 AR6000_SPIN_UNLOCK(&ar->arLock, 0); |
| 5750 break; |
| 5751 } |
| 5752 |
| 5753 A_NETBUF_PUT_DATA(new_skb, A_NETBUF_DATA(dupskb), A_NETBUF_LEN(dupskb)); |
| 5754 cookie->arc_bp[0] = (A_UINT32)new_skb; |
| 5755 cookie->arc_bp[1] = MapNo; |
| 5756 SET_HTC_PACKET_INFO_TX(&cookie->HtcPkt, |
| 5757 cookie, |
| 5758 A_NETBUF_DATA(new_skb), |
| 5759 A_NETBUF_LEN(new_skb), |
| 5760 eid, |
| 5761 AR6K_DATA_PKT_TAG); |
| 5762 |
| 5763 cookieArray[i] = cookie; |
| 5764 |
| 5765 { |
| 5766 EPPING_HEADER *pHdr = (EPPING_HEADER *)A_NETBUF_DATA(new_skb); |
| 5767 pHdr->Cmd_h = EPPING_CMD_NO_ECHO; /* do not echo the packet */ |
| 5768 } |
| 5769 } |
| 5770 |
| 5771 if (pkts == 0) { |
| 5772 return; |
| 5773 } |
| 5774 |
| 5775 INIT_HTC_PACKET_QUEUE(&pktQueue); |
| 5776 |
| 5777 for (i = 0; i < pkts; i++) { |
| 5778 HTC_PACKET_ENQUEUE(&pktQueue,&cookieArray[i]->HtcPkt); |
| 5779 } |
| 5780 |
| 5781 HTCSendPktsMultiple(ar->arHtcTarget, &pktQueue); |
| 5782 |
| 5783 } |
| 5784 |
| 5785 #endif |
| 5786 |
| 5787 #ifdef EXPORT_HCI_BRIDGE_INTERFACE |
| 5788 EXPORT_SYMBOL(setupbtdev); |
| 5789 #endif |
OLD | NEW |