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>
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 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37)
28 sema_init(&priv
->mlme_blocking_mutex
, 1);
30 init_MUTEX(&priv
->mlme_blocking_mutex
);
33 #ifdef CSR_SUPPORT_WEXT
35 int r
= uf_init_wext_interface(priv
);
51 uf_sme_deinit(unifi_priv_t
*priv
)
56 /* Free memory allocated for the scan table */
57 /* unifi_clear_scan_table(priv); */
59 /* Cancel any pending workqueue tasks */
60 flush_workqueue(priv
->unifi_workqueue
);
62 #ifdef CSR_SUPPORT_WEXT
63 uf_deinit_wext_interface(priv
);
68 } /* uf_sme_deinit() */
71 int sme_mgt_wifi_on(unifi_priv_t
*priv
)
79 /* Initialize the interface mode to None */
80 for (i
=0; i
<CSR_WIFI_NUM_INTERFACES
; i
++) {
81 priv
->interfacePriv
[i
]->interfaceMode
= 0;
84 /* Set up interface mode so that get_packet_priority() can
85 * select the right QOS priority when WMM is enabled.
87 priv
->interfacePriv
[0]->interfaceMode
= CSR_WIFI_ROUTER_CTRL_MODE_STA
;
89 r
= uf_request_firmware_files(priv
, UNIFI_FW_STA
);
91 unifi_error(priv
, "sme_mgt_wifi_on: Failed to get f/w\n");
96 * The request to initialise UniFi might come while UniFi is running.
97 * We need to block all I/O activity until the reset completes, otherwise
98 * an SDIO error might occur resulting an indication to the SME which
99 * makes it think that the initialisation has failed.
101 priv
->bh_thread
.block_thread
= 1;
104 CsrSdioClaim(priv
->sdio
);
105 csrResult
= CsrSdioPowerOn(priv
->sdio
);
106 CsrSdioRelease(priv
->sdio
);
107 if(csrResult
!= CSR_RESULT_SUCCESS
&& csrResult
!= CSR_SDIO_RESULT_NOT_RESET
) {
111 if (csrResult
== CSR_RESULT_SUCCESS
) {
112 /* Initialise UniFi hardware */
113 r
= uf_init_hw(priv
);
119 /* Re-enable the I/O thread */
120 priv
->bh_thread
.block_thread
= 0;
122 /* Disable deep sleep signalling during the firmware initialisation, to
123 * prevent the wakeup mechanism raising the SDIO clock beyond INIT before
124 * the first MLME-RESET.ind. It gets re-enabled at the CONNECTED.ind,
125 * immediately after the MLME-RESET.ind
127 csrResult
= unifi_configure_low_power_mode(priv
->card
,
128 UNIFI_LOW_POWER_DISABLED
,
129 UNIFI_PERIODIC_WAKE_HOST_DISABLED
);
130 if (csrResult
!= CSR_RESULT_SUCCESS
) {
132 "sme_mgt_wifi_on: unifi_configure_low_power_mode() returned an error\n");
136 /* Start the I/O thread */
137 CsrSdioClaim(priv
->sdio
);
138 r
= uf_init_bh(priv
);
140 CsrSdioPowerOff(priv
->sdio
);
141 CsrSdioRelease(priv
->sdio
);
144 CsrSdioRelease(priv
->sdio
);
146 priv
->init_progress
= UNIFI_INIT_FW_DOWNLOADED
;
152 sme_sys_suspend(unifi_priv_t
*priv
)
154 const int interfaceNum
= 0; /* FIXME */
157 /* Abort any pending requests. */
160 /* Allow our mlme request to go through. */
161 priv
->io_aborted
= 0;
163 /* Send MLME-RESET.req to UniFi. */
164 unifi_reset_state(priv
, priv
->netdev
[interfaceNum
]->dev_addr
, 0);
166 /* Stop the network traffic */
167 netif_carrier_off(priv
->netdev
[interfaceNum
]);
169 /* Put UniFi to deep sleep */
170 CsrSdioClaim(priv
->sdio
);
171 csrResult
= unifi_force_low_power_mode(priv
->card
);
172 CsrSdioRelease(priv
->sdio
);
175 } /* sme_sys_suspend() */
179 sme_sys_resume(unifi_priv_t
*priv
)
181 #ifdef CSR_SUPPORT_WEXT
182 /* Send disconnect event so clients will re-initialise connection. */
183 memset(priv
->wext_conf
.current_ssid
, 0, UNIFI_MAX_SSID_LEN
);
184 memset((void*)priv
->wext_conf
.current_bssid
, 0, ETH_ALEN
);
185 priv
->wext_conf
.capability
= 0;
186 wext_send_disassoc_event(priv
);
189 } /* sme_sys_resume() */
193 * ---------------------------------------------------------------------------
194 * sme_native_log_event
196 * Callback function to be registered as the SME event callback.
197 * Copies the signal content into a new udi_log_t struct and adds
198 * it to the read queue for the SME client.
201 * arg This is the value given to unifi_add_udi_hook, in
202 * this case a pointer to the client instance.
203 * signal Pointer to the received signal.
204 * signal_len Size of the signal structure in bytes.
205 * bulkdata Pointers to any associated bulk data.
206 * dir Direction of the signal. Zero means from host,
207 * non-zero means to host.
211 * ---------------------------------------------------------------------------
214 sme_native_log_event(ul_client_t
*pcli
,
215 const u8
*sig_packed
, int sig_len
,
216 const bulk_data_param_t
*bulkdata
,
227 ul_client_t
*client
= pcli
;
231 if (client
== NULL
) {
232 unifi_error(NULL
, "sme_native_log_event: client has exited\n");
236 priv
= uf_find_instance(client
->instance
);
238 unifi_error(priv
, "invalid priv\n");
242 /* Just a sanity check */
243 if ((sig_packed
== NULL
) || (sig_len
<= 0)) {
247 /* Get the unpacked signal */
248 r
= read_unpack_signal(sig_packed
, &signal
);
250 signal_len
= SigGetSize(&signal
);
252 u16 receiver_id
= CSR_GET_UINT16_FROM_LITTLE_ENDIAN((sig_packed
) + sizeof(u16
)) & 0xFF00;
254 /* The control indications are 1 byte, pass them to client. */
256 unifi_trace(priv
, UDBG5
,
257 "Control indication (0x%x) for native SME.\n",
260 *(u8
*)&signal
= *sig_packed
;
261 signal_len
= sig_len
;
262 } else if (receiver_id
== 0) {
264 * Also "unknown" signals with a ReceiverId of 0 are passed to the client
265 * without unpacking. (This is a code size optimisation to allow signals
266 * that the driver not interested in to be dropped from the unpack code).
268 unifi_trace(priv
, UDBG5
,
269 "Signal 0x%.4X with ReceiverId 0 for native SME.\n",
270 CSR_GET_UINT16_FROM_LITTLE_ENDIAN(sig_packed
));
272 *(u8
*)&signal
= *sig_packed
;
273 signal_len
= sig_len
;
276 "sme_native_log_event - Received unknown signal 0x%.4X.\n",
277 CSR_GET_UINT16_FROM_LITTLE_ENDIAN(sig_packed
));
282 unifi_trace(priv
, UDBG3
, "sme_native_log_event: signal 0x%.4X for %d\n",
283 signal
.SignalPrimitiveHeader
.SignalId
,
286 total_len
= signal_len
;
287 /* Calculate the buffer we need to store signal plus bulk data */
288 for (i
= 0; i
< UNIFI_MAX_DATA_REFERENCES
; i
++) {
289 total_len
+= bulkdata
->d
[i
].data_length
;
292 /* Allocate log structure plus actual signal. */
293 logptr
= (udi_log_t
*)kmalloc(sizeof(udi_log_t
) + total_len
, GFP_KERNEL
);
295 if (logptr
== NULL
) {
297 "Failed to allocate %d bytes for a UDI log record\n",
298 sizeof(udi_log_t
) + total_len
);
302 /* Fill in udi_log struct */
303 INIT_LIST_HEAD(&logptr
->q
);
304 msgptr
= &logptr
->msg
;
305 msgptr
->length
= sizeof(udi_msg_t
) + total_len
;
306 msgptr
->timestamp
= jiffies_to_msecs(jiffies
);
307 msgptr
->direction
= dir
;
308 msgptr
->signal_length
= signal_len
;
310 /* Copy signal and bulk data to the log */
311 p
= (u8
*)(msgptr
+ 1);
312 memcpy(p
, &signal
, signal_len
);
315 /* Append any bulk data */
316 for (i
= 0; i
< UNIFI_MAX_DATA_REFERENCES
; i
++) {
317 int len
= bulkdata
->d
[i
].data_length
;
320 * Len here might not be the same as the length in the bulk data slot.
321 * The slot length will always be even, but len could be odd.
324 if (bulkdata
->d
[i
].os_data_ptr
) {
325 memcpy(p
, bulkdata
->d
[i
].os_data_ptr
, len
);
333 /* Add to tail of log queue */
334 down(&client
->udi_sem
);
335 list_add_tail(&logptr
->q
, &client
->udi_log
);
336 up(&client
->udi_sem
);
338 /* Wake any waiting user process */
339 wake_up_interruptible(&client
->udi_wq
);
343 } /* sme_native_log_event() */
347 * ---------------------------------------------------------------------------
348 * unifi_ta_indicate_protocol
350 * Report that a packet of a particular type has been seen
353 * drv_priv The device context pointer passed to ta_init.
354 * protocol The protocol type enum value.
355 * direction Whether the packet was a tx or rx.
356 * src_addr The source MAC address from the data packet.
362 * We defer the actual sending to a background workqueue,
363 * see uf_ta_ind_wq().
364 * ---------------------------------------------------------------------------
367 unifi_ta_indicate_protocol(void *ospriv
,
368 CsrWifiRouterCtrlTrafficPacketType packet_type
,
369 CsrWifiRouterCtrlProtocolDirection direction
,
370 const CsrWifiMacAddress
*src_addr
)
373 } /* unifi_ta_indicate_protocol */
376 * ---------------------------------------------------------------------------
377 * unifi_ta_indicate_sampling
379 * Send the TA sampling information to the SME.
382 * drv_priv The device context pointer passed to ta_init.
383 * stats The TA sampling data to send.
387 * ---------------------------------------------------------------------------
390 unifi_ta_indicate_sampling(void *ospriv
, CsrWifiRouterCtrlTrafficStats
*stats
)
393 } /* unifi_ta_indicate_sampling() */
397 unifi_ta_indicate_l4stats(void *ospriv
,
404 } /* unifi_ta_indicate_l4stats() */
407 * ---------------------------------------------------------------------------
408 * uf_native_process_udi_signal
410 * Process interesting signals from the UDI interface.
413 * pcli A pointer to the client instance.
414 * signal Pointer to the received signal.
415 * signal_len Size of the signal structure in bytes.
416 * bulkdata Pointers to any associated bulk data.
417 * dir Direction of the signal. Zero means from host,
418 * non-zero means to host.
423 * ---------------------------------------------------------------------------
426 uf_native_process_udi_signal(ul_client_t
*pcli
,
427 const u8
*packed_signal
, int packed_signal_len
,
428 const bulk_data_param_t
*bulkdata
, int dir
)
431 } /* uf_native_process_udi_signal() */
435 * ---------------------------------------------------------------------------
436 * sme_native_mlme_event_handler
438 * Callback function to be used as the udi_event_callback when registering
440 * This function implements a blocking request-reply interface for WEXT.
441 * To use it, a client specifies this function as the udi_event_callback
442 * to ul_register_client(). The signal dispatcher in
443 * unifi_receive_event() will call this function to deliver a signal.
446 * pcli Pointer to the client instance.
447 * signal Pointer to the received signal.
448 * signal_len Size of the signal structure in bytes.
449 * bulkdata Pointer to structure containing any associated bulk data.
450 * dir Direction of the signal. Zero means from host,
451 * non-zero means to host.
455 * ---------------------------------------------------------------------------
458 sme_native_mlme_event_handler(ul_client_t
*pcli
,
459 const u8
*sig_packed
, int sig_len
,
460 const bulk_data_param_t
*bulkdata
,
465 unifi_priv_t
*priv
= uf_find_instance(pcli
->instance
);
470 /* Just a sanity check */
471 if ((sig_packed
== NULL
) || (sig_len
<= 0)) {
475 /* Get the unpacked signal */
476 r
= read_unpack_signal(sig_packed
, &signal
);
478 signal_len
= SigGetSize(&signal
);
481 "sme_native_mlme_event_handler - Received unknown signal 0x%.4X.\n",
482 CSR_GET_UINT16_FROM_LITTLE_ENDIAN(sig_packed
));
486 id
= signal
.SignalPrimitiveHeader
.SignalId
;
487 unifi_trace(priv
, UDBG4
, "wext - Process signal 0x%.4X\n", id
);
490 * Take the appropriate action for the signal.
494 * Confirm replies from UniFi.
495 * These all have zero or one CSR_DATAREF member. (FIXME: check this is still true for softmac)
497 case CSR_MA_PACKET_CONFIRM_ID
:
498 case CSR_MLME_RESET_CONFIRM_ID
:
499 case CSR_MLME_GET_CONFIRM_ID
:
500 case CSR_MLME_SET_CONFIRM_ID
:
501 case CSR_MLME_GET_NEXT_CONFIRM_ID
:
502 case CSR_MLME_POWERMGT_CONFIRM_ID
:
503 case CSR_MLME_SCAN_CONFIRM_ID
:
504 case CSR_MLME_HL_SYNC_CONFIRM_ID
:
505 case CSR_MLME_MEASURE_CONFIRM_ID
:
506 case CSR_MLME_SETKEYS_CONFIRM_ID
:
507 case CSR_MLME_DELETEKEYS_CONFIRM_ID
:
508 case CSR_MLME_HL_SYNC_CANCEL_CONFIRM_ID
:
509 case CSR_MLME_ADD_PERIODIC_CONFIRM_ID
:
510 case CSR_MLME_DEL_PERIODIC_CONFIRM_ID
:
511 case CSR_MLME_ADD_AUTONOMOUS_SCAN_CONFIRM_ID
:
512 case CSR_MLME_DEL_AUTONOMOUS_SCAN_CONFIRM_ID
:
513 case CSR_MLME_SET_PACKET_FILTER_CONFIRM_ID
:
514 case CSR_MLME_STOP_MEASURE_CONFIRM_ID
:
515 case CSR_MLME_PAUSE_AUTONOMOUS_SCAN_CONFIRM_ID
:
516 case CSR_MLME_ADD_TRIGGERED_GET_CONFIRM_ID
:
517 case CSR_MLME_DEL_TRIGGERED_GET_CONFIRM_ID
:
518 case CSR_MLME_ADD_BLACKOUT_CONFIRM_ID
:
519 case CSR_MLME_DEL_BLACKOUT_CONFIRM_ID
:
520 case CSR_MLME_ADD_RX_TRIGGER_CONFIRM_ID
:
521 case CSR_MLME_DEL_RX_TRIGGER_CONFIRM_ID
:
522 case CSR_MLME_CONNECT_STATUS_CONFIRM_ID
:
523 case CSR_MLME_MODIFY_BSS_PARAMETER_CONFIRM_ID
:
524 case CSR_MLME_ADD_TEMPLATE_CONFIRM_ID
:
525 case CSR_MLME_CONFIG_QUEUE_CONFIRM_ID
:
526 case CSR_MLME_ADD_TSPEC_CONFIRM_ID
:
527 case CSR_MLME_DEL_TSPEC_CONFIRM_ID
:
528 case CSR_MLME_START_AGGREGATION_CONFIRM_ID
:
529 case CSR_MLME_STOP_AGGREGATION_CONFIRM_ID
:
530 case CSR_MLME_SM_START_CONFIRM_ID
:
531 case CSR_MLME_LEAVE_CONFIRM_ID
:
532 case CSR_MLME_SET_TIM_CONFIRM_ID
:
533 case CSR_MLME_GET_KEY_SEQUENCE_CONFIRM_ID
:
534 case CSR_MLME_SET_CHANNEL_CONFIRM_ID
:
535 case CSR_MLME_ADD_MULTICAST_ADDRESS_CONFIRM_ID
:
536 case CSR_DEBUG_GENERIC_CONFIRM_ID
:
537 unifi_mlme_copy_reply_and_wakeup_client(pcli
, &signal
, signal_len
, bulkdata
);
540 case CSR_MLME_CONNECTED_INDICATION_ID
:
541 /* We currently ignore the connected-ind for softmac f/w development */
542 unifi_info(priv
, "CSR_MLME_CONNECTED_INDICATION_ID ignored\n");
550 } /* sme_native_mlme_event_handler() */
555 * -------------------------------------------------------------------------
558 * Ensure that a MAC address has been set.
559 * Send the MLME-RESET signal.
560 * This must be called at least once before starting to do any
561 * network activities (e.g. scan, join etc).
564 * priv Pointer to device private context struct
565 * macaddr Pointer to chip MAC address.
566 * If this is FF:FF:FF:FF:FF:FF it will be replaced
567 * with the MAC address from the chip.
568 * set_default_mib 1 if the f/w must reset the MIB to the default values
572 * 0 on success, an error code otherwise.
573 * -------------------------------------------------------------------------
576 unifi_reset_state(unifi_priv_t
*priv
, unsigned char *macaddr
,
577 unsigned char set_default_mib
)
583 #ifdef CSR_SUPPORT_WEXT
584 /* The reset clears any 802.11 association. */
585 priv
->wext_conf
.flag_associated
= 0;
590 } /* unifi_reset_state() */