2 * ***************************************************************************
6 * Copyright (C) 2005-2009 by Cambridge Silicon Radio Ltd.
8 * Refer to LICENSE.txt included with this source code for details on
11 * ***************************************************************************
14 #include <linux/netdevice.h>
15 #include <linux/version.h>
16 #include "unifi_priv.h"
17 #include "csr_wifi_hip_unifi.h"
18 #include "csr_wifi_hip_conversions.h"
20 static const unsigned char wildcard_address[ETH_ALEN] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
23 uf_sme_init(unifi_priv_t *priv)
27 sema_init(&priv->mlme_blocking_mutex, 1);
29 #ifdef CSR_SUPPORT_WEXT
31 int r = uf_init_wext_interface(priv);
47 uf_sme_deinit(unifi_priv_t *priv)
52 /* Free memory allocated for the scan table */
53 /* unifi_clear_scan_table(priv); */
55 /* Cancel any pending workqueue tasks */
56 flush_workqueue(priv->unifi_workqueue);
58 #ifdef CSR_SUPPORT_WEXT
59 uf_deinit_wext_interface(priv);
64 } /* uf_sme_deinit() */
67 int sme_mgt_wifi_on(unifi_priv_t *priv)
75 /* Initialize the interface mode to None */
76 for (i=0; i<CSR_WIFI_NUM_INTERFACES; i++) {
77 priv->interfacePriv[i]->interfaceMode = 0;
80 /* Set up interface mode so that get_packet_priority() can
81 * select the right QOS priority when WMM is enabled.
83 priv->interfacePriv[0]->interfaceMode = CSR_WIFI_ROUTER_CTRL_MODE_STA;
85 r = uf_request_firmware_files(priv, UNIFI_FW_STA);
87 unifi_error(priv, "sme_mgt_wifi_on: Failed to get f/w\n");
92 * The request to initialise UniFi might come while UniFi is running.
93 * We need to block all I/O activity until the reset completes, otherwise
94 * an SDIO error might occur resulting an indication to the SME which
95 * makes it think that the initialisation has failed.
97 priv->bh_thread.block_thread = 1;
100 CsrSdioClaim(priv->sdio);
101 csrResult = CsrSdioPowerOn(priv->sdio);
102 CsrSdioRelease(priv->sdio);
103 if(csrResult != CSR_RESULT_SUCCESS && csrResult != CSR_SDIO_RESULT_NOT_RESET) {
107 if (csrResult == CSR_RESULT_SUCCESS) {
108 /* Initialise UniFi hardware */
109 r = uf_init_hw(priv);
115 /* Re-enable the I/O thread */
116 priv->bh_thread.block_thread = 0;
118 /* Disable deep sleep signalling during the firmware initialisation, to
119 * prevent the wakeup mechanism raising the SDIO clock beyond INIT before
120 * the first MLME-RESET.ind. It gets re-enabled at the CONNECTED.ind,
121 * immediately after the MLME-RESET.ind
123 csrResult = unifi_configure_low_power_mode(priv->card,
124 UNIFI_LOW_POWER_DISABLED,
125 UNIFI_PERIODIC_WAKE_HOST_DISABLED);
126 if (csrResult != CSR_RESULT_SUCCESS) {
128 "sme_mgt_wifi_on: unifi_configure_low_power_mode() returned an error\n");
132 /* Start the I/O thread */
133 CsrSdioClaim(priv->sdio);
134 r = uf_init_bh(priv);
136 CsrSdioPowerOff(priv->sdio);
137 CsrSdioRelease(priv->sdio);
140 CsrSdioRelease(priv->sdio);
142 priv->init_progress = UNIFI_INIT_FW_DOWNLOADED;
148 sme_sys_suspend(unifi_priv_t *priv)
150 const int interfaceNum = 0; /* FIXME */
153 /* Abort any pending requests. */
156 /* Allow our mlme request to go through. */
157 priv->io_aborted = 0;
159 /* Send MLME-RESET.req to UniFi. */
160 unifi_reset_state(priv, priv->netdev[interfaceNum]->dev_addr, 0);
162 /* Stop the network traffic */
163 netif_carrier_off(priv->netdev[interfaceNum]);
165 /* Put UniFi to deep sleep */
166 CsrSdioClaim(priv->sdio);
167 csrResult = unifi_force_low_power_mode(priv->card);
168 CsrSdioRelease(priv->sdio);
171 } /* sme_sys_suspend() */
175 sme_sys_resume(unifi_priv_t *priv)
177 #ifdef CSR_SUPPORT_WEXT
178 /* Send disconnect event so clients will re-initialise connection. */
179 memset(priv->wext_conf.current_ssid, 0, UNIFI_MAX_SSID_LEN);
180 memset((void*)priv->wext_conf.current_bssid, 0, ETH_ALEN);
181 priv->wext_conf.capability = 0;
182 wext_send_disassoc_event(priv);
185 } /* sme_sys_resume() */
189 * ---------------------------------------------------------------------------
190 * sme_native_log_event
192 * Callback function to be registered as the SME event callback.
193 * Copies the signal content into a new udi_log_t struct and adds
194 * it to the read queue for the SME client.
197 * arg This is the value given to unifi_add_udi_hook, in
198 * this case a pointer to the client instance.
199 * signal Pointer to the received signal.
200 * signal_len Size of the signal structure in bytes.
201 * bulkdata Pointers to any associated bulk data.
202 * dir Direction of the signal. Zero means from host,
203 * non-zero means to host.
207 * ---------------------------------------------------------------------------
210 sme_native_log_event(ul_client_t *pcli,
211 const u8 *sig_packed, int sig_len,
212 const bulk_data_param_t *bulkdata,
223 ul_client_t *client = pcli;
227 if (client == NULL) {
228 unifi_error(NULL, "sme_native_log_event: client has exited\n");
232 priv = uf_find_instance(client->instance);
234 unifi_error(priv, "invalid priv\n");
238 /* Just a sanity check */
239 if ((sig_packed == NULL) || (sig_len <= 0)) {
243 /* Get the unpacked signal */
244 r = read_unpack_signal(sig_packed, &signal);
246 signal_len = SigGetSize(&signal);
248 u16 receiver_id = CSR_GET_UINT16_FROM_LITTLE_ENDIAN((sig_packed) + sizeof(u16)) & 0xFF00;
250 /* The control indications are 1 byte, pass them to client. */
252 unifi_trace(priv, UDBG5,
253 "Control indication (0x%x) for native SME.\n",
256 *(u8*)&signal = *sig_packed;
257 signal_len = sig_len;
258 } else if (receiver_id == 0) {
260 * Also "unknown" signals with a ReceiverId of 0 are passed to the client
261 * without unpacking. (This is a code size optimisation to allow signals
262 * that the driver not interested in to be dropped from the unpack code).
264 unifi_trace(priv, UDBG5,
265 "Signal 0x%.4X with ReceiverId 0 for native SME.\n",
266 CSR_GET_UINT16_FROM_LITTLE_ENDIAN(sig_packed));
268 *(u8*)&signal = *sig_packed;
269 signal_len = sig_len;
272 "sme_native_log_event - Received unknown signal 0x%.4X.\n",
273 CSR_GET_UINT16_FROM_LITTLE_ENDIAN(sig_packed));
278 unifi_trace(priv, UDBG3, "sme_native_log_event: signal 0x%.4X for %d\n",
279 signal.SignalPrimitiveHeader.SignalId,
282 total_len = signal_len;
283 /* Calculate the buffer we need to store signal plus bulk data */
284 for (i = 0; i < UNIFI_MAX_DATA_REFERENCES; i++) {
285 total_len += bulkdata->d[i].data_length;
288 /* Allocate log structure plus actual signal. */
289 logptr = (udi_log_t *)kmalloc(sizeof(udi_log_t) + total_len, GFP_KERNEL);
291 if (logptr == NULL) {
293 "Failed to allocate %d bytes for a UDI log record\n",
294 sizeof(udi_log_t) + total_len);
298 /* Fill in udi_log struct */
299 INIT_LIST_HEAD(&logptr->q);
300 msgptr = &logptr->msg;
301 msgptr->length = sizeof(udi_msg_t) + total_len;
302 msgptr->timestamp = jiffies_to_msecs(jiffies);
303 msgptr->direction = dir;
304 msgptr->signal_length = signal_len;
306 /* Copy signal and bulk data to the log */
307 p = (u8 *)(msgptr + 1);
308 memcpy(p, &signal, signal_len);
311 /* Append any bulk data */
312 for (i = 0; i < UNIFI_MAX_DATA_REFERENCES; i++) {
313 int len = bulkdata->d[i].data_length;
316 * Len here might not be the same as the length in the bulk data slot.
317 * The slot length will always be even, but len could be odd.
320 if (bulkdata->d[i].os_data_ptr) {
321 memcpy(p, bulkdata->d[i].os_data_ptr, len);
329 /* Add to tail of log queue */
330 down(&client->udi_sem);
331 list_add_tail(&logptr->q, &client->udi_log);
332 up(&client->udi_sem);
334 /* Wake any waiting user process */
335 wake_up_interruptible(&client->udi_wq);
339 } /* sme_native_log_event() */
343 * ---------------------------------------------------------------------------
344 * unifi_ta_indicate_protocol
346 * Report that a packet of a particular type has been seen
349 * drv_priv The device context pointer passed to ta_init.
350 * protocol The protocol type enum value.
351 * direction Whether the packet was a tx or rx.
352 * src_addr The source MAC address from the data packet.
358 * We defer the actual sending to a background workqueue,
359 * see uf_ta_ind_wq().
360 * ---------------------------------------------------------------------------
363 unifi_ta_indicate_protocol(void *ospriv,
364 CsrWifiRouterCtrlTrafficPacketType packet_type,
365 CsrWifiRouterCtrlProtocolDirection direction,
366 const CsrWifiMacAddress *src_addr)
369 } /* unifi_ta_indicate_protocol */
372 * ---------------------------------------------------------------------------
373 * unifi_ta_indicate_sampling
375 * Send the TA sampling information to the SME.
378 * drv_priv The device context pointer passed to ta_init.
379 * stats The TA sampling data to send.
383 * ---------------------------------------------------------------------------
386 unifi_ta_indicate_sampling(void *ospriv, CsrWifiRouterCtrlTrafficStats *stats)
389 } /* unifi_ta_indicate_sampling() */
393 unifi_ta_indicate_l4stats(void *ospriv,
400 } /* unifi_ta_indicate_l4stats() */
403 * ---------------------------------------------------------------------------
404 * uf_native_process_udi_signal
406 * Process interesting signals from the UDI interface.
409 * pcli A pointer to the client instance.
410 * signal Pointer to the received signal.
411 * signal_len Size of the signal structure in bytes.
412 * bulkdata Pointers to any associated bulk data.
413 * dir Direction of the signal. Zero means from host,
414 * non-zero means to host.
419 * ---------------------------------------------------------------------------
422 uf_native_process_udi_signal(ul_client_t *pcli,
423 const u8 *packed_signal, int packed_signal_len,
424 const bulk_data_param_t *bulkdata, int dir)
427 } /* uf_native_process_udi_signal() */
431 * ---------------------------------------------------------------------------
432 * sme_native_mlme_event_handler
434 * Callback function to be used as the udi_event_callback when registering
436 * This function implements a blocking request-reply interface for WEXT.
437 * To use it, a client specifies this function as the udi_event_callback
438 * to ul_register_client(). The signal dispatcher in
439 * unifi_receive_event() will call this function to deliver a signal.
442 * pcli Pointer to the client instance.
443 * signal Pointer to the received signal.
444 * signal_len Size of the signal structure in bytes.
445 * bulkdata Pointer to structure containing any associated bulk data.
446 * dir Direction of the signal. Zero means from host,
447 * non-zero means to host.
451 * ---------------------------------------------------------------------------
454 sme_native_mlme_event_handler(ul_client_t *pcli,
455 const u8 *sig_packed, int sig_len,
456 const bulk_data_param_t *bulkdata,
461 unifi_priv_t *priv = uf_find_instance(pcli->instance);
466 /* Just a sanity check */
467 if ((sig_packed == NULL) || (sig_len <= 0)) {
471 /* Get the unpacked signal */
472 r = read_unpack_signal(sig_packed, &signal);
474 signal_len = SigGetSize(&signal);
477 "sme_native_mlme_event_handler - Received unknown signal 0x%.4X.\n",
478 CSR_GET_UINT16_FROM_LITTLE_ENDIAN(sig_packed));
482 id = signal.SignalPrimitiveHeader.SignalId;
483 unifi_trace(priv, UDBG4, "wext - Process signal 0x%.4X\n", id);
486 * Take the appropriate action for the signal.
490 * Confirm replies from UniFi.
491 * These all have zero or one CSR_DATAREF member. (FIXME: check this is still true for softmac)
493 case CSR_MA_PACKET_CONFIRM_ID:
494 case CSR_MLME_RESET_CONFIRM_ID:
495 case CSR_MLME_GET_CONFIRM_ID:
496 case CSR_MLME_SET_CONFIRM_ID:
497 case CSR_MLME_GET_NEXT_CONFIRM_ID:
498 case CSR_MLME_POWERMGT_CONFIRM_ID:
499 case CSR_MLME_SCAN_CONFIRM_ID:
500 case CSR_MLME_HL_SYNC_CONFIRM_ID:
501 case CSR_MLME_MEASURE_CONFIRM_ID:
502 case CSR_MLME_SETKEYS_CONFIRM_ID:
503 case CSR_MLME_DELETEKEYS_CONFIRM_ID:
504 case CSR_MLME_HL_SYNC_CANCEL_CONFIRM_ID:
505 case CSR_MLME_ADD_PERIODIC_CONFIRM_ID:
506 case CSR_MLME_DEL_PERIODIC_CONFIRM_ID:
507 case CSR_MLME_ADD_AUTONOMOUS_SCAN_CONFIRM_ID:
508 case CSR_MLME_DEL_AUTONOMOUS_SCAN_CONFIRM_ID:
509 case CSR_MLME_SET_PACKET_FILTER_CONFIRM_ID:
510 case CSR_MLME_STOP_MEASURE_CONFIRM_ID:
511 case CSR_MLME_PAUSE_AUTONOMOUS_SCAN_CONFIRM_ID:
512 case CSR_MLME_ADD_TRIGGERED_GET_CONFIRM_ID:
513 case CSR_MLME_DEL_TRIGGERED_GET_CONFIRM_ID:
514 case CSR_MLME_ADD_BLACKOUT_CONFIRM_ID:
515 case CSR_MLME_DEL_BLACKOUT_CONFIRM_ID:
516 case CSR_MLME_ADD_RX_TRIGGER_CONFIRM_ID:
517 case CSR_MLME_DEL_RX_TRIGGER_CONFIRM_ID:
518 case CSR_MLME_CONNECT_STATUS_CONFIRM_ID:
519 case CSR_MLME_MODIFY_BSS_PARAMETER_CONFIRM_ID:
520 case CSR_MLME_ADD_TEMPLATE_CONFIRM_ID:
521 case CSR_MLME_CONFIG_QUEUE_CONFIRM_ID:
522 case CSR_MLME_ADD_TSPEC_CONFIRM_ID:
523 case CSR_MLME_DEL_TSPEC_CONFIRM_ID:
524 case CSR_MLME_START_AGGREGATION_CONFIRM_ID:
525 case CSR_MLME_STOP_AGGREGATION_CONFIRM_ID:
526 case CSR_MLME_SM_START_CONFIRM_ID:
527 case CSR_MLME_LEAVE_CONFIRM_ID:
528 case CSR_MLME_SET_TIM_CONFIRM_ID:
529 case CSR_MLME_GET_KEY_SEQUENCE_CONFIRM_ID:
530 case CSR_MLME_SET_CHANNEL_CONFIRM_ID:
531 case CSR_MLME_ADD_MULTICAST_ADDRESS_CONFIRM_ID:
532 case CSR_DEBUG_GENERIC_CONFIRM_ID:
533 unifi_mlme_copy_reply_and_wakeup_client(pcli, &signal, signal_len, bulkdata);
536 case CSR_MLME_CONNECTED_INDICATION_ID:
537 /* We currently ignore the connected-ind for softmac f/w development */
538 unifi_info(priv, "CSR_MLME_CONNECTED_INDICATION_ID ignored\n");
546 } /* sme_native_mlme_event_handler() */
551 * -------------------------------------------------------------------------
554 * Ensure that a MAC address has been set.
555 * Send the MLME-RESET signal.
556 * This must be called at least once before starting to do any
557 * network activities (e.g. scan, join etc).
560 * priv Pointer to device private context struct
561 * macaddr Pointer to chip MAC address.
562 * If this is FF:FF:FF:FF:FF:FF it will be replaced
563 * with the MAC address from the chip.
564 * set_default_mib 1 if the f/w must reset the MIB to the default values
568 * 0 on success, an error code otherwise.
569 * -------------------------------------------------------------------------
572 unifi_reset_state(unifi_priv_t *priv, unsigned char *macaddr,
573 unsigned char set_default_mib)
579 #ifdef CSR_SUPPORT_WEXT
580 /* The reset clears any 802.11 association. */
581 priv->wext_conf.flag_associated = 0;
586 } /* unifi_reset_state() */