staging: csr: remove CsrInt8 typedef
[linux-2.6-block.git] / drivers / staging / csr / sme_native.c
CommitLineData
635d2b00
GKH
1/*
2 * ***************************************************************************
3 *
4 * FILE: sme_native.c
5 *
6 * Copyright (C) 2005-2009 by Cambridge Silicon Radio Ltd.
7 *
8 * Refer to LICENSE.txt included with this source code for details on
9 * the license terms.
10 *
11 * ***************************************************************************
12 */
13
14#include <linux/netdevice.h>
15
16#include "unifi_priv.h"
17#include "csr_wifi_hip_unifi.h"
18#include "csr_wifi_hip_conversions.h"
19
20static const unsigned char wildcard_address[ETH_ALEN] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
21
22int
23uf_sme_init(unifi_priv_t *priv)
24{
25 func_enter();
26
27#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37)
28 sema_init(&priv->mlme_blocking_mutex, 1);
29#else
30 init_MUTEX(&priv->mlme_blocking_mutex);
31#endif
32
33#ifdef CSR_SUPPORT_WEXT
34 {
35 int r = uf_init_wext_interface(priv);
36 if (r != 0) {
37 func_exit();
38 return r;
39 }
40 }
41#endif
42
43
44
45 func_exit();
46 return 0;
47} /* uf_sme_init() */
48
49
50void
51uf_sme_deinit(unifi_priv_t *priv)
52{
53
54 func_enter();
55
56 /* Free memory allocated for the scan table */
57/* unifi_clear_scan_table(priv); */
58
59 /* Cancel any pending workqueue tasks */
60 flush_workqueue(priv->unifi_workqueue);
61
62#ifdef CSR_SUPPORT_WEXT
63 uf_deinit_wext_interface(priv);
64#endif
65
66
67 func_exit();
68} /* uf_sme_deinit() */
69
70
71int sme_mgt_wifi_on(unifi_priv_t *priv)
72{
73 int r,i;
74 CsrInt32 csrResult;
75
76 if (priv == NULL) {
77 return -EINVAL;
78 }
79 /* Initialize the interface mode to None */
80 for (i=0; i<CSR_WIFI_NUM_INTERFACES; i++) {
81 priv->interfacePriv[i]->interfaceMode = 0;
82 }
83
84 /* Set up interface mode so that get_packet_priority() can
85 * select the right QOS priority when WMM is enabled.
86 */
87 priv->interfacePriv[0]->interfaceMode = CSR_WIFI_ROUTER_CTRL_MODE_STA;
88
89 r = uf_request_firmware_files(priv, UNIFI_FW_STA);
90 if (r) {
91 unifi_error(priv, "sme_mgt_wifi_on: Failed to get f/w\n");
92 return r;
93 }
94
95 /*
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.
100 */
101 priv->bh_thread.block_thread = 1;
102
103 /* Power on UniFi */
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) {
108 return -EIO;
109 }
110
111 if (csrResult == CSR_RESULT_SUCCESS) {
112 /* Initialise UniFi hardware */
113 r = uf_init_hw(priv);
114 if (r) {
115 return r;
116 }
117 }
118
119 /* Re-enable the I/O thread */
120 priv->bh_thread.block_thread = 0;
121
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
126 */
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) {
131 unifi_warning(priv,
132 "sme_mgt_wifi_on: unifi_configure_low_power_mode() returned an error\n");
133 }
134
135
136 /* Start the I/O thread */
137 CsrSdioClaim(priv->sdio);
138 r = uf_init_bh(priv);
139 if (r) {
140 CsrSdioPowerOff(priv->sdio);
141 CsrSdioRelease(priv->sdio);
142 return r;
143 }
144 CsrSdioRelease(priv->sdio);
145
146 priv->init_progress = UNIFI_INIT_FW_DOWNLOADED;
147
148 return 0;
149}
150
151int
152sme_sys_suspend(unifi_priv_t *priv)
153{
154 const int interfaceNum = 0; /* FIXME */
155 CsrResult csrResult;
156
157 /* Abort any pending requests. */
158 uf_abort_mlme(priv);
159
160 /* Allow our mlme request to go through. */
161 priv->io_aborted = 0;
162
163 /* Send MLME-RESET.req to UniFi. */
164 unifi_reset_state(priv, priv->netdev[interfaceNum]->dev_addr, 0);
165
166 /* Stop the network traffic */
167 netif_carrier_off(priv->netdev[interfaceNum]);
168
169 /* Put UniFi to deep sleep */
170 CsrSdioClaim(priv->sdio);
171 csrResult = unifi_force_low_power_mode(priv->card);
172 CsrSdioRelease(priv->sdio);
173
174 return 0;
175} /* sme_sys_suspend() */
176
177
178int
179sme_sys_resume(unifi_priv_t *priv)
180{
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);
187#endif
188 return 0;
189} /* sme_sys_resume() */
190
191
192/*
193 * ---------------------------------------------------------------------------
194 * sme_native_log_event
195 *
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.
199 *
200 * Arguments:
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.
208 *
209 * Returns:
210 * None.
211 * ---------------------------------------------------------------------------
212 */
213void
214sme_native_log_event(ul_client_t *pcli,
215 const u8 *sig_packed, int sig_len,
216 const bulk_data_param_t *bulkdata,
217 int dir)
218{
219 unifi_priv_t *priv;
220 udi_log_t *logptr;
221 u8 *p;
222 int i, r;
223 int signal_len;
224 int total_len;
225 udi_msg_t *msgptr;
226 CSR_SIGNAL signal;
227 ul_client_t *client = pcli;
228
229 func_enter();
230
231 if (client == NULL) {
232 unifi_error(NULL, "sme_native_log_event: client has exited\n");
233 return;
234 }
235
236 priv = uf_find_instance(client->instance);
237 if (!priv) {
238 unifi_error(priv, "invalid priv\n");
239 return;
240 }
241
242 /* Just a sanity check */
243 if ((sig_packed == NULL) || (sig_len <= 0)) {
244 return;
245 }
246
247 /* Get the unpacked signal */
248 r = read_unpack_signal(sig_packed, &signal);
249 if (r == 0) {
250 signal_len = SigGetSize(&signal);
251 } else {
252 CsrUint16 receiver_id = CSR_GET_UINT16_FROM_LITTLE_ENDIAN((sig_packed) + sizeof(CsrUint16)) & 0xFF00;
253
254 /* The control indications are 1 byte, pass them to client. */
255 if (sig_len == 1) {
256 unifi_trace(priv, UDBG5,
257 "Control indication (0x%x) for native SME.\n",
258 *sig_packed);
259
260 *(u8*)&signal = *sig_packed;
261 signal_len = sig_len;
262 } else if (receiver_id == 0) {
263 /*
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).
267 */
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));
271
272 *(u8*)&signal = *sig_packed;
273 signal_len = sig_len;
274 } else {
275 unifi_error(priv,
276 "sme_native_log_event - Received unknown signal 0x%.4X.\n",
277 CSR_GET_UINT16_FROM_LITTLE_ENDIAN(sig_packed));
278 return;
279 }
280 }
281
282 unifi_trace(priv, UDBG3, "sme_native_log_event: signal 0x%.4X for %d\n",
283 signal.SignalPrimitiveHeader.SignalId,
284 client->client_id);
285
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;
290 }
291
292 /* Allocate log structure plus actual signal. */
293 logptr = (udi_log_t *)kmalloc(sizeof(udi_log_t) + total_len, GFP_KERNEL);
294
295 if (logptr == NULL) {
296 unifi_error(priv,
297 "Failed to allocate %d bytes for a UDI log record\n",
298 sizeof(udi_log_t) + total_len);
299 return;
300 }
301
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;
309
310 /* Copy signal and bulk data to the log */
311 p = (u8 *)(msgptr + 1);
312 memcpy(p, &signal, signal_len);
313 p += signal_len;
314
315 /* Append any bulk data */
316 for (i = 0; i < UNIFI_MAX_DATA_REFERENCES; i++) {
317 int len = bulkdata->d[i].data_length;
318
319 /*
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.
322 */
323 if (len > 0) {
324 if (bulkdata->d[i].os_data_ptr) {
325 memcpy(p, bulkdata->d[i].os_data_ptr, len);
326 } else {
327 memset(p, 0, len);
328 }
329 p += len;
330 }
331 }
332
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);
337
338 /* Wake any waiting user process */
339 wake_up_interruptible(&client->udi_wq);
340
341 func_exit();
342
343} /* sme_native_log_event() */
344
345
346/*
347 * ---------------------------------------------------------------------------
348 * unifi_ta_indicate_protocol
349 *
350 * Report that a packet of a particular type has been seen
351 *
352 * Arguments:
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.
357 *
358 * Returns:
359 * None.
360 *
361 * Notes:
362 * We defer the actual sending to a background workqueue,
363 * see uf_ta_ind_wq().
364 * ---------------------------------------------------------------------------
365 */
366void
367unifi_ta_indicate_protocol(void *ospriv,
368 CsrWifiRouterCtrlTrafficPacketType packet_type,
369 CsrWifiRouterCtrlProtocolDirection direction,
370 const CsrWifiMacAddress *src_addr)
371{
372
373} /* unifi_ta_indicate_protocol */
374
375/*
376 * ---------------------------------------------------------------------------
377 * unifi_ta_indicate_sampling
378 *
379 * Send the TA sampling information to the SME.
380 *
381 * Arguments:
382 * drv_priv The device context pointer passed to ta_init.
383 * stats The TA sampling data to send.
384 *
385 * Returns:
386 * None.
387 * ---------------------------------------------------------------------------
388 */
389void
390unifi_ta_indicate_sampling(void *ospriv, CsrWifiRouterCtrlTrafficStats *stats)
391{
392
393} /* unifi_ta_indicate_sampling() */
394
395
396void
397unifi_ta_indicate_l4stats(void *ospriv,
398 CsrUint32 rxTcpThroughput,
399 CsrUint32 txTcpThroughput,
400 CsrUint32 rxUdpThroughput,
401 CsrUint32 txUdpThroughput)
402{
403
404} /* unifi_ta_indicate_l4stats() */
405
406/*
407 * ---------------------------------------------------------------------------
408 * uf_native_process_udi_signal
409 *
410 * Process interesting signals from the UDI interface.
411 *
412 * Arguments:
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.
419 *
420 *
421 * Returns:
422 * None.
423 * ---------------------------------------------------------------------------
424 */
425void
426uf_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)
429{
430
431} /* uf_native_process_udi_signal() */
432
433
434/*
435 * ---------------------------------------------------------------------------
436 * sme_native_mlme_event_handler
437 *
438 * Callback function to be used as the udi_event_callback when registering
439 * as a client.
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.
444 *
445 * Arguments:
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.
452 *
453 * Returns:
454 * None.
455 * ---------------------------------------------------------------------------
456 */
457void
458sme_native_mlme_event_handler(ul_client_t *pcli,
459 const u8 *sig_packed, int sig_len,
460 const bulk_data_param_t *bulkdata,
461 int dir)
462{
463 CSR_SIGNAL signal;
464 int signal_len;
465 unifi_priv_t *priv = uf_find_instance(pcli->instance);
466 int id, r;
467
468 func_enter();
469
470 /* Just a sanity check */
471 if ((sig_packed == NULL) || (sig_len <= 0)) {
472 return;
473 }
474
475 /* Get the unpacked signal */
476 r = read_unpack_signal(sig_packed, &signal);
477 if (r == 0) {
478 signal_len = SigGetSize(&signal);
479 } else {
480 unifi_error(priv,
481 "sme_native_mlme_event_handler - Received unknown signal 0x%.4X.\n",
482 CSR_GET_UINT16_FROM_LITTLE_ENDIAN(sig_packed));
483 return;
484 }
485
486 id = signal.SignalPrimitiveHeader.SignalId;
487 unifi_trace(priv, UDBG4, "wext - Process signal 0x%.4X\n", id);
488
489 /*
490 * Take the appropriate action for the signal.
491 */
492 switch (id) {
493 /*
494 * Confirm replies from UniFi.
495 * These all have zero or one CSR_DATAREF member. (FIXME: check this is still true for softmac)
496 */
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);
538 break;
539
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");
543 break;
544
545 default:
546 break;
547 }
548
549 func_exit();
550} /* sme_native_mlme_event_handler() */
551
552
553
554/*
555 * -------------------------------------------------------------------------
556 * unifi_reset_state
557 *
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).
562 *
563 * Arguments:
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
569 * 0 otherwise
570 *
571 * Returns:
572 * 0 on success, an error code otherwise.
573 * -------------------------------------------------------------------------
574 */
575int
576unifi_reset_state(unifi_priv_t *priv, unsigned char *macaddr,
577 unsigned char set_default_mib)
578{
579 int r = 0;
580
581 func_enter();
582
583#ifdef CSR_SUPPORT_WEXT
584 /* The reset clears any 802.11 association. */
585 priv->wext_conf.flag_associated = 0;
586#endif
587
588 func_exit();
589 return r;
590} /* unifi_reset_state() */
591