Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
unifi_sme.c
Go to the documentation of this file.
1 /*
2  * ***************************************************************************
3  * FILE: unifi_sme.c
4  *
5  * PURPOSE: SME related functions.
6  *
7  * Copyright (C) 2007-2009 by Cambridge Silicon Radio Ltd.
8  *
9  * Refer to LICENSE.txt included with this source code for details on
10  * the license terms.
11  *
12  * ***************************************************************************
13  */
14 
15 #include "unifi_priv.h"
16 #include "csr_wifi_hip_unifi.h"
18 
19 
20 
21 
22  int
24 {
25  switch (error) {
26  case CSR_RESULT_SUCCESS:
27  return 0;
28  case CSR_RESULT_FAILURE:
33  return -EIO;
35  return -EBUSY;
37  return -EINVAL;
39  return -EOPNOTSUPP;
40  default:
41  return -EIO;
42  }
43 }
44 
45 
46 /*
47  * ---------------------------------------------------------------------------
48  * sme_log_event
49  *
50  * Callback function to be registered as the SME event callback.
51  * Copies the signal content into a new udi_log_t struct and adds
52  * it to the read queue for the SME client.
53  *
54  * Arguments:
55  * arg This is the value given to unifi_add_udi_hook, in
56  * this case a pointer to the client instance.
57  * signal Pointer to the received signal.
58  * signal_len Size of the signal structure in bytes.
59  * bulkdata Pointers to any associated bulk data.
60  * dir Direction of the signal. Zero means from host,
61  * non-zero means to host.
62  *
63  * Returns:
64  * None.
65  * ---------------------------------------------------------------------------
66  */
67  void
69  const u8 *signal, int signal_len,
70  const bulk_data_param_t *bulkdata,
71  int dir)
72 {
74  CSR_SIGNAL unpacked_signal;
75  CsrWifiSmeDataBlock mlmeCommand;
76  CsrWifiSmeDataBlock dataref1;
77  CsrWifiSmeDataBlock dataref2;
79  int r;
80 
81  func_enter();
82  /* Just a sanity check */
83  if ((signal == NULL) || (signal_len <= 0)) {
84  func_exit();
85  return;
86  }
87 
88  priv = uf_find_instance(pcli->instance);
89  if (!priv) {
90  unifi_error(priv, "sme_log_event: invalid priv\n");
91  func_exit();
92  return;
93  }
94 
95  if (priv->smepriv == NULL) {
96  unifi_error(priv, "sme_log_event: invalid smepriv\n");
97  func_exit();
98  return;
99  }
100 
101  unifi_trace(priv, UDBG3,
102  "sme_log_event: Process signal 0x%.4X\n",
104 
105 
106  /* If the signal is known, then do any filtering required, otherwise it pass it to the SME. */
107  r = read_unpack_signal(signal, &unpacked_signal);
108  if (r == CSR_RESULT_SUCCESS) {
111  {
112  func_exit();
113  return;
114  }
116  {
117  u16 frmCtrl;
118  u8 unicastPdu = TRUE;
119  u8 *macHdrLocation;
120  u8 *raddr = NULL, *taddr = NULL;
121  CsrWifiMacAddress peerMacAddress;
122  /* Check if we need to send CsrWifiRouterCtrlMicFailureInd*/
123  CSR_MA_PACKET_INDICATION *ind = &unpacked_signal.u.MaPacketIndication;
124 
125  macHdrLocation = (u8 *) bulkdata->d[0].os_data_ptr;
126  /* Fetch the frame control value from mac header */
127  frmCtrl = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(macHdrLocation);
128 
129  /* Point to the addresses */
130  raddr = macHdrLocation + MAC_HEADER_ADDR1_OFFSET;
131  taddr = macHdrLocation + MAC_HEADER_ADDR2_OFFSET;
132 
133  memcpy(peerMacAddress.a, taddr, ETH_ALEN);
134 
136  {
137  if (*raddr & 0x1)
138  unicastPdu = FALSE;
139 
140  CsrWifiRouterCtrlMicFailureIndSend (priv->CSR_WIFI_SME_IFACEQUEUE, 0,
141  (ind->VirtualInterfaceIdentifier & 0xff),peerMacAddress,
142  unicastPdu);
143  return;
144  }
145  else
146  {
147  if(ind->ReceptionStatus == CSR_RX_SUCCESS)
148  {
149  u8 pmBit = (frmCtrl & 0x1000)?0x01:0x00;
150  u16 interfaceTag = (ind->VirtualInterfaceIdentifier & 0xff);
151  CsrWifiRouterCtrlStaInfo_t *srcStaInfo = CsrWifiRouterCtrlGetStationRecordFromPeerMacAddress(priv,taddr,interfaceTag);
152  if((srcStaInfo != NULL) && (uf_check_broadcast_bssid(priv, bulkdata)== FALSE))
153  {
154  uf_process_pm_bit_for_peer(priv,srcStaInfo,pmBit,interfaceTag);
155 
156  /* Update station last activity flag */
157  srcStaInfo->activity_flag = TRUE;
158  }
159  }
160  }
161  }
162 
164  {
165  CSR_MA_PACKET_CONFIRM *cfm = &unpacked_signal.u.MaPacketConfirm;
166  u16 interfaceTag = (cfm->VirtualInterfaceIdentifier & 0xff);
167  netInterface_priv_t *interfacePriv;
169  CsrWifiMacAddress peerMacAddress;
170 
171  if (interfaceTag >= CSR_WIFI_NUM_INTERFACES)
172  {
173  unifi_error(priv, "Bad MA_PACKET_CONFIRM interfaceTag %d\n", interfaceTag);
174  func_exit();
175  return;
176  }
177 
178  unifi_trace(priv,UDBG1,"MA-PACKET Confirm (%x, %x)\n", cfm->HostTag, cfm->TransmissionStatus);
179 
180  interfacePriv = priv->interfacePriv[interfaceTag];
181 #ifdef CSR_SUPPORT_SME
182  if(interfacePriv->interfaceMode == CSR_WIFI_ROUTER_CTRL_MODE_AP ||
184 
185  if(cfm->HostTag == interfacePriv->multicastPduHostTag){
186  uf_process_ma_pkt_cfm_for_ap(priv ,interfaceTag, cfm);
187  }
188  }
189 #endif
190 
191  req = &interfacePriv->m4_signal.u.MaPacketRequest;
192 
193  if(cfm->HostTag & 0x80000000)
194  {
196  {
197  result = CSR_RESULT_FAILURE;
198  }
199 #ifdef CSR_SUPPORT_SME
200  memcpy(peerMacAddress.a, req->Ra.x, ETH_ALEN);
201  /* Check if this is a confirm for EAPOL M4 frame and we need to send transmistted ind*/
202  if (interfacePriv->m4_sent && (cfm->HostTag == interfacePriv->m4_hostTag))
203  {
204  unifi_trace(priv, UDBG1, "%s: Sending M4 Transmit CFM\n", __FUNCTION__);
205  CsrWifiRouterCtrlM4TransmittedIndSend(priv->CSR_WIFI_SME_IFACEQUEUE, 0,
206  interfaceTag,
207  peerMacAddress,
208  result);
209  interfacePriv->m4_sent = FALSE;
210  interfacePriv->m4_hostTag = 0xffffffff;
211  }
212 #endif
213  /* If EAPOL was requested via router APIs then send cfm else ignore*/
214  if((cfm->HostTag & 0x80000000) != CSR_WIFI_EAPOL_M4_HOST_TAG) {
217  result,
218  (cfm->HostTag & 0x3fffffff), cfm->Rate);
219  } else {
220  unifi_trace(priv, UDBG1, "%s: M4 received from netdevice\n", __FUNCTION__);
221  }
222  func_exit();
223  return;
224  }
225  }
226  }
227 
228  mlmeCommand.length = signal_len;
229  mlmeCommand.data = (u8*)signal;
230 
231  dataref1.length = bulkdata->d[0].data_length;
232  if (dataref1.length > 0) {
233  dataref1.data = (u8 *) bulkdata->d[0].os_data_ptr;
234  } else
235  {
236  dataref1.data = NULL;
237  }
238 
239  dataref2.length = bulkdata->d[1].data_length;
240  if (dataref2.length > 0) {
241  dataref2.data = (u8 *) bulkdata->d[1].os_data_ptr;
242  } else
243  {
244  dataref2.data = NULL;
245  }
246 
247  CsrWifiRouterCtrlHipIndSend(priv->CSR_WIFI_SME_IFACEQUEUE, mlmeCommand.length, mlmeCommand.data,
248  dataref1.length, dataref1.data,
249  dataref2.length, dataref2.data);
250 
251  func_exit();
252 } /* sme_log_event() */
253 
254 
255 /*
256  * ---------------------------------------------------------------------------
257  * uf_sme_port_state
258  *
259  * Return the state of the controlled port.
260  *
261  * Arguments:
262  * priv Pointer to device private context struct
263  * address Pointer to the destination for tx or sender for rx address
264  * queue Controlled or uncontrolled queue
265  *
266  * Returns:
267  * An unifi_ControlledPortAction value.
268  * ---------------------------------------------------------------------------
269  */
271 uf_sme_port_state(unifi_priv_t *priv, unsigned char *address, int queue, u16 interfaceTag)
272 {
273  int i;
275  netInterface_priv_t *interfacePriv;
276 
277  if (interfaceTag >= CSR_WIFI_NUM_INTERFACES) {
278  unifi_error(priv, "uf_sme_port_state: bad interfaceTag\n");
280  }
281 
282  interfacePriv = priv->interfacePriv[interfaceTag];
283 
284  if (queue == UF_CONTROLLED_PORT_Q) {
285  port = &interfacePriv->controlled_data_port;
286  } else {
287  port = &interfacePriv->uncontrolled_data_port;
288  }
289 
290  if (!port->entries_in_use) {
291  unifi_trace(priv, UDBG5, "No port configurations, return Discard.\n");
293  }
294 
295  /* If the port configuration is common for all destinations, return it. */
296  if (port->overide_action == UF_DATA_PORT_OVERIDE) {
297  unifi_trace(priv, UDBG5, "Single port configuration (%d).\n",
298  port->port_cfg[0].port_action);
299  return port->port_cfg[0].port_action;
300  }
301 
302  unifi_trace(priv, UDBG5, "Multiple (%d) port configurations.\n", port->entries_in_use);
303 
304  /* If multiple configurations exist.. */
305  for (i = 0; i < UNIFI_MAX_CONNECTIONS; i++) {
306  /* .. go through the list and match the destination address. */
307  if (port->port_cfg[i].in_use &&
308  memcmp(address, port->port_cfg[i].mac_address.a, ETH_ALEN) == 0) {
309  /* Return the desired action. */
310  return port->port_cfg[i].port_action;
311  }
312  }
313 
314  /* Could not find any information, return Open. */
315  unifi_trace(priv, UDBG5, "port configuration not found, return Open.\n");
317 } /* uf_sme_port_state() */
318 
319 /*
320  * ---------------------------------------------------------------------------
321  * uf_sme_port_config_handle
322  *
323  * Return the port config handle of the controlled/uncontrolled port.
324  *
325  * Arguments:
326  * priv Pointer to device private context struct
327  * address Pointer to the destination for tx or sender for rx address
328  * queue Controlled or uncontrolled queue
329  *
330  * Returns:
331  * An unifi_port_cfg_t* .
332  * ---------------------------------------------------------------------------
333  */
335 uf_sme_port_config_handle(unifi_priv_t *priv, unsigned char *address, int queue, u16 interfaceTag)
336 {
337  int i;
339  netInterface_priv_t *interfacePriv = priv->interfacePriv[interfaceTag];
340 
341  if (interfaceTag >= CSR_WIFI_NUM_INTERFACES) {
342  unifi_error(priv, "uf_sme_port_config_handle: bad interfaceTag\n");
343  return NULL;
344  }
345 
346  if (queue == UF_CONTROLLED_PORT_Q) {
347  port = &interfacePriv->controlled_data_port;
348  } else {
349  port = &interfacePriv->uncontrolled_data_port;
350  }
351 
352  if (!port->entries_in_use) {
353  unifi_trace(priv, UDBG5, "No port configurations, return Discard.\n");
354  return NULL;
355  }
356 
357  /* If the port configuration is common for all destinations, return it. */
358  if (port->overide_action == UF_DATA_PORT_OVERIDE) {
359  unifi_trace(priv, UDBG5, "Single port configuration (%d).\n",
360  port->port_cfg[0].port_action);
361  if (address) {
362  unifi_trace(priv, UDBG5, "addr[0] = %x, addr[1] = %x, addr[2] = %x, addr[3] = %x\n", address[0], address[1], address[2], address[3]);
363  }
364  return &port->port_cfg[0];
365  }
366 
367  unifi_trace(priv, UDBG5, "Multiple port configurations.\n");
368 
369  /* If multiple configurations exist.. */
370  for (i = 0; i < UNIFI_MAX_CONNECTIONS; i++) {
371  /* .. go through the list and match the destination address. */
372  if (port->port_cfg[i].in_use &&
373  memcmp(address, port->port_cfg[i].mac_address.a, ETH_ALEN) == 0) {
374  /* Return the desired action. */
375  return &port->port_cfg[i];
376  }
377  }
378 
379  /* Could not find any information, return Open. */
380  unifi_trace(priv, UDBG5, "port configuration not found, returning NULL (debug).\n");
381  return NULL;
382 } /* uf_sme_port_config_handle */
383 
384 void
386 {
388  multicast_list_task);
389  int i;
390  u16 interfaceTag = 0;
391  CsrWifiMacAddress* multicast_address_list = NULL;
392  int mc_count;
393  u8 *mc_list;
394  netInterface_priv_t *interfacePriv = priv->interfacePriv[interfaceTag];
395 
396  if (interfaceTag >= CSR_WIFI_NUM_INTERFACES) {
397  unifi_error(priv, "uf_multicast_list_wq: bad interfaceTag\n");
398  return;
399  }
400 
401  unifi_trace(priv, UDBG5,
402  "uf_multicast_list_wq: list count = %d\n",
403  interfacePriv->mc_list_count);
404 
405  /* Flush the current list */
406  CsrWifiRouterCtrlMulticastAddressIndSend(priv->CSR_WIFI_SME_IFACEQUEUE,0, interfaceTag, CSR_WIFI_SME_LIST_ACTION_FLUSH, 0, NULL);
407 
408  mc_count = interfacePriv->mc_list_count;
409  mc_list = interfacePriv->mc_list;
410  /*
411  * Allocate a new list, need to free it later
412  * in unifi_mgt_multicast_address_cfm().
413  */
414  multicast_address_list = kmalloc(mc_count * sizeof(CsrWifiMacAddress), GFP_KERNEL);
415 
416  if (multicast_address_list == NULL) {
417  return;
418  }
419 
420  for (i = 0; i < mc_count; i++) {
421  memcpy(multicast_address_list[i].a, mc_list, ETH_ALEN);
422  mc_list += ETH_ALEN;
423  }
424 
425  if (priv->smepriv == NULL) {
426  kfree(multicast_address_list);
427  return;
428  }
429 
430  CsrWifiRouterCtrlMulticastAddressIndSend(priv->CSR_WIFI_SME_IFACEQUEUE,0,
431  interfaceTag,
433  mc_count, multicast_address_list);
434 
435  /* The SME will take a copy of the addreses*/
436  kfree(multicast_address_list);
437 }
438 
439 
440 int unifi_cfg_power(unifi_priv_t *priv, unsigned char *arg)
441 {
442  unifi_cfg_power_t cfg_power;
443  int rc;
444  int wol;
445 
446  if (get_user(cfg_power, (unifi_cfg_power_t*)(((unifi_cfg_command_t*)arg) + 1))) {
447  unifi_error(priv, "UNIFI_CFG: Failed to get the argument\n");
448  return -EFAULT;
449  }
450 
451  switch (cfg_power) {
452  case UNIFI_CFG_POWER_OFF:
453  priv->wol_suspend = (enable_wol == UNIFI_WOL_OFF) ? FALSE : TRUE;
454  rc = sme_sys_suspend(priv);
455  if (rc) {
456  return rc;
457  }
458  break;
459  case UNIFI_CFG_POWER_ON:
460  wol = priv->wol_suspend;
461  rc = sme_sys_resume(priv);
462  if (rc) {
463  return rc;
464  }
465  if (wol) {
466  /* Kick the BH to ensure pending transfers are handled when
467  * a suspend happened with card powered.
468  */
469  unifi_send_signal(priv->card, NULL, 0, NULL);
470  }
471  break;
472  default:
473  unifi_error(priv, "WIFI POWER: Unknown value.\n");
474  return -EINVAL;
475  }
476 
477  return 0;
478 }
479 
480 
482 {
483  unifi_cfg_powersave_t cfg_power_save;
484  CsrWifiSmePowerConfig powerConfig;
485  int rc;
486 
487  if (get_user(cfg_power_save, (unifi_cfg_powersave_t*)(((unifi_cfg_command_t*)arg) + 1))) {
488  unifi_error(priv, "UNIFI_CFG: Failed to get the argument\n");
489  return -EFAULT;
490  }
491 
492  /* Get the coex info from the SME */
493  rc = sme_mgt_power_config_get(priv, &powerConfig);
494  if (rc) {
495  unifi_error(priv, "UNIFI_CFG: Get unifi_PowerConfigValue failed.\n");
496  return rc;
497  }
498 
499  switch (cfg_power_save) {
502  break;
505  break;
508  break;
511  break;
512  default:
513  unifi_error(priv, "POWERSAVE: Unknown value.\n");
514  return -EINVAL;
515  }
516 
517  rc = sme_mgt_power_config_set(priv, &powerConfig);
518 
519  if (rc) {
520  unifi_error(priv, "UNIFI_CFG: Set unifi_PowerConfigValue failed.\n");
521  }
522 
523  return rc;
524 }
525 
526 
528 {
529  unifi_cfg_powersupply_t cfg_power_supply;
530  CsrWifiSmeHostConfig hostConfig;
531  int rc;
532 
533  if (get_user(cfg_power_supply, (unifi_cfg_powersupply_t*)(((unifi_cfg_command_t*)arg) + 1))) {
534  unifi_error(priv, "UNIFI_CFG: Failed to get the argument\n");
535  return -EFAULT;
536  }
537 
538  /* Get the coex info from the SME */
539  rc = sme_mgt_host_config_get(priv, &hostConfig);
540  if (rc) {
541  unifi_error(priv, "UNIFI_CFG: Get unifi_HostConfigValue failed.\n");
542  return rc;
543  }
544 
545  switch (cfg_power_supply) {
548  break;
551  break;
552  default:
553  unifi_error(priv, "POWERSUPPLY: Unknown value.\n");
554  return -EINVAL;
555  }
556 
557  rc = sme_mgt_host_config_set(priv, &hostConfig);
558  if (rc) {
559  unifi_error(priv, "UNIFI_CFG: Set unifi_HostConfigValue failed.\n");
560  }
561 
562  return rc;
563 }
564 
565 
567 {
568  unsigned char *tclas_buffer;
569  unsigned int tclas_buffer_length;
570  tclas_t *dhcp_tclas;
571  int rc;
572 
573  /* Free any TCLASs previously allocated */
574  if (priv->packet_filters.tclas_ies_length) {
575  kfree(priv->filter_tclas_ies);
576  priv->filter_tclas_ies = NULL;
577  }
578 
579  tclas_buffer = ((unsigned char*)arg) + sizeof(unifi_cfg_command_t) + sizeof(unsigned int);
580  if (copy_from_user(&priv->packet_filters, (void*)tclas_buffer,
581  sizeof(uf_cfg_bcast_packet_filter_t))) {
582  unifi_error(priv, "UNIFI_CFG: Failed to get the filter struct\n");
583  return -EFAULT;
584  }
585 
586  tclas_buffer_length = priv->packet_filters.tclas_ies_length;
587 
588  /* Allocate TCLASs if necessary */
589  if (priv->packet_filters.dhcp_filter) {
590  priv->packet_filters.tclas_ies_length += sizeof(tclas_t);
591  }
592  if (priv->packet_filters.tclas_ies_length > 0) {
593  priv->filter_tclas_ies = kmalloc(priv->packet_filters.tclas_ies_length, GFP_KERNEL);
594  if (priv->filter_tclas_ies == NULL) {
595  return -ENOMEM;
596  }
597  if (tclas_buffer_length) {
598  tclas_buffer += sizeof(uf_cfg_bcast_packet_filter_t) - sizeof(unsigned char*);
599  if (copy_from_user(priv->filter_tclas_ies,
600  tclas_buffer,
601  tclas_buffer_length)) {
602  unifi_error(priv, "UNIFI_CFG: Failed to get the TCLAS buffer\n");
603  return -EFAULT;
604  }
605  }
606  }
607 
608  if(priv->packet_filters.dhcp_filter)
609  {
610  /* Append the DHCP tclas IE */
611  dhcp_tclas = (tclas_t*)(priv->filter_tclas_ies + tclas_buffer_length);
612  memset(dhcp_tclas, 0, sizeof(tclas_t));
613  dhcp_tclas->element_id = 14;
614  dhcp_tclas->length = sizeof(tcpip_clsfr_t) + 1;
615  dhcp_tclas->user_priority = 0;
616  dhcp_tclas->tcp_ip_cls_fr.cls_fr_type = 1;
617  dhcp_tclas->tcp_ip_cls_fr.version = 4;
618  ((u8*)(&dhcp_tclas->tcp_ip_cls_fr.source_port))[0] = 0x00;
619  ((u8*)(&dhcp_tclas->tcp_ip_cls_fr.source_port))[1] = 0x44;
620  ((u8*)(&dhcp_tclas->tcp_ip_cls_fr.dest_port))[0] = 0x00;
621  ((u8*)(&dhcp_tclas->tcp_ip_cls_fr.dest_port))[1] = 0x43;
622  dhcp_tclas->tcp_ip_cls_fr.protocol = 0x11;
623  dhcp_tclas->tcp_ip_cls_fr.cls_fr_mask = 0x58; //bits: 3,4,6
624  }
625 
626  rc = sme_mgt_packet_filter_set(priv);
627 
628  return rc;
629 }
630 
631 
633 {
634  u8 wmm_qos_info;
635  int rc = 0;
636 
637  if (get_user(wmm_qos_info, (u8*)(((unifi_cfg_command_t*)arg) + 1))) {
638  unifi_error(priv, "UNIFI_CFG: Failed to get the argument\n");
639  return -EFAULT;
640  }
641 
642  /* Store the value in the connection info */
643  priv->connection_config.wmmQosInfo = wmm_qos_info;
644 
645  return rc;
646 }
647 
648 
650 {
651  u32 addts_tid;
652  u8 addts_ie_length;
653  u8 *addts_ie;
654  u8 *addts_params;
655  CsrWifiSmeDataBlock tspec;
657  int rc;
658 
659  addts_params = (u8*)(((unifi_cfg_command_t*)arg) + 1);
660  if (get_user(addts_tid, (u32*)addts_params)) {
661  unifi_error(priv, "unifi_cfg_wmm_addts: Failed to get the argument\n");
662  return -EFAULT;
663  }
664 
665  addts_params += sizeof(u32);
666  if (get_user(addts_ie_length, (u8*)addts_params)) {
667  unifi_error(priv, "unifi_cfg_wmm_addts: Failed to get the argument\n");
668  return -EFAULT;
669  }
670 
671  unifi_trace(priv, UDBG4, "addts: tid = 0x%x ie_length = %d\n",
672  addts_tid, addts_ie_length);
673 
674  addts_ie = kmalloc(addts_ie_length, GFP_KERNEL);
675  if (addts_ie == NULL) {
676  unifi_error(priv,
677  "unifi_cfg_wmm_addts: Failed to malloc %d bytes for addts_ie buffer\n",
678  addts_ie_length);
679  return -ENOMEM;
680  }
681 
682  addts_params += sizeof(u8);
683  rc = copy_from_user(addts_ie, addts_params, addts_ie_length);
684  if (rc) {
685  unifi_error(priv, "unifi_cfg_wmm_addts: Failed to get the addts buffer\n");
686  kfree(addts_ie);
687  return -EFAULT;
688  }
689 
690  tspec.data = addts_ie;
691  tspec.length = addts_ie_length;
692  tclas.data = NULL;
693  tclas.length = 0;
694 
695  rc = sme_mgt_tspec(priv, CSR_WIFI_SME_LIST_ACTION_ADD, addts_tid,
696  &tspec, &tclas);
697 
698  kfree(addts_ie);
699  return rc;
700 }
701 
702 
704 {
705  u32 delts_tid;
706  u8 *delts_params;
707  CsrWifiSmeDataBlock tspec;
709  int rc;
710 
711  delts_params = (u8*)(((unifi_cfg_command_t*)arg) + 1);
712  if (get_user(delts_tid, (u32*)delts_params)) {
713  unifi_error(priv, "unifi_cfg_wmm_delts: Failed to get the argument\n");
714  return -EFAULT;
715  }
716 
717  unifi_trace(priv, UDBG4, "delts: tid = 0x%x\n", delts_tid);
718 
719  tspec.data = tclas.data = NULL;
720  tspec.length = tclas.length = 0;
721 
722  rc = sme_mgt_tspec(priv, CSR_WIFI_SME_LIST_ACTION_REMOVE, delts_tid,
723  &tspec, &tclas);
724 
725  return rc;
726 }
727 
729 {
730  u8 strict_draft_n;
731  u8 *strict_draft_n_params;
732  int rc;
733 
734  CsrWifiSmeStaConfig staConfig;
735  CsrWifiSmeDeviceConfig deviceConfig;
736 
737  strict_draft_n_params = (u8*)(((unifi_cfg_command_t*)arg) + 1);
738  if (get_user(strict_draft_n, (u8*)strict_draft_n_params)) {
739  unifi_error(priv, "unifi_cfg_strict_draft_n: Failed to get the argument\n");
740  return -EFAULT;
741  }
742 
743  unifi_trace(priv, UDBG4, "strict_draft_n: = %s\n", ((strict_draft_n) ? "yes":"no"));
744 
745  rc = sme_mgt_sme_config_get(priv, &staConfig, &deviceConfig);
746 
747  if (rc) {
748  unifi_warning(priv, "unifi_cfg_strict_draft_n: Get unifi_SMEConfigValue failed.\n");
749  return -EFAULT;
750  }
751 
752  deviceConfig.enableStrictDraftN = strict_draft_n;
753 
754  rc = sme_mgt_sme_config_set(priv, &staConfig, &deviceConfig);
755  if (rc) {
756  unifi_warning(priv, "unifi_cfg_strict_draft_n: Set unifi_SMEConfigValue failed.\n");
757  rc = -EFAULT;
758  }
759 
760  return rc;
761 }
762 
763 
765 {
766  u8 enable_okc;
767  u8 *enable_okc_params;
768  int rc;
769 
770  CsrWifiSmeStaConfig staConfig;
771  CsrWifiSmeDeviceConfig deviceConfig;
772 
773  enable_okc_params = (u8*)(((unifi_cfg_command_t*)arg) + 1);
774  if (get_user(enable_okc, (u8*)enable_okc_params)) {
775  unifi_error(priv, "unifi_cfg_enable_okc: Failed to get the argument\n");
776  return -EFAULT;
777  }
778 
779  unifi_trace(priv, UDBG4, "enable_okc: = %s\n", ((enable_okc) ? "yes":"no"));
780 
781  rc = sme_mgt_sme_config_get(priv, &staConfig, &deviceConfig);
782  if (rc) {
783  unifi_warning(priv, "unifi_cfg_enable_okc: Get unifi_SMEConfigValue failed.\n");
784  return -EFAULT;
785  }
786 
787  staConfig.enableOpportunisticKeyCaching = enable_okc;
788 
789  rc = sme_mgt_sme_config_set(priv, &staConfig, &deviceConfig);
790  if (rc) {
791  unifi_warning(priv, "unifi_cfg_enable_okc: Set unifi_SMEConfigValue failed.\n");
792  rc = -EFAULT;
793  }
794 
795  return rc;
796 }
797 
798 
800 {
801  unifi_cfg_get_t get_cmd;
802  char inst_name[IFNAMSIZ];
803  int rc;
804 
805  if (get_user(get_cmd, (unifi_cfg_get_t*)(((unifi_cfg_command_t*)arg) + 1))) {
806  unifi_error(priv, "UNIFI_CFG: Failed to get the argument\n");
807  return -EFAULT;
808  }
809 
810  switch (get_cmd) {
811  case UNIFI_CFG_GET_COEX:
812  {
813  CsrWifiSmeCoexInfo coexInfo;
814  /* Get the coex info from the SME */
815  rc = sme_mgt_coex_info_get(priv, &coexInfo);
816  if (rc) {
817  unifi_error(priv, "UNIFI_CFG: Get unifi_CoexInfoValue failed.\n");
818  return rc;
819  }
820 
821  /* Copy the info to the out buffer */
822  if (copy_to_user((void*)arg,
823  &coexInfo,
824  sizeof(CsrWifiSmeCoexInfo))) {
825  unifi_error(priv, "UNIFI_CFG: Failed to copy the coex info\n");
826  return -EFAULT;
827  }
828  break;
829  }
831  {
832  CsrWifiSmePowerConfig powerConfig;
833  rc = sme_mgt_power_config_get(priv, &powerConfig);
834  if (rc) {
835  unifi_error(priv, "UNIFI_CFG: Get unifi_PowerConfigValue failed.\n");
836  return rc;
837  }
838 
839  /* Copy the info to the out buffer */
840  if (copy_to_user((void*)arg,
841  &powerConfig.powerSaveLevel,
842  sizeof(CsrWifiSmePowerSaveLevel))) {
843  unifi_error(priv, "UNIFI_CFG: Failed to copy the power save info\n");
844  return -EFAULT;
845  }
846  break;
847  }
849  {
850  CsrWifiSmeHostConfig hostConfig;
851  rc = sme_mgt_host_config_get(priv, &hostConfig);
852  if (rc) {
853  unifi_error(priv, "UNIFI_CFG: Get unifi_HostConfigValue failed.\n");
854  return rc;
855  }
856 
857  /* Copy the info to the out buffer */
858  if (copy_to_user((void*)arg,
859  &hostConfig.powerMode,
860  sizeof(CsrWifiSmeHostPowerMode))) {
861  unifi_error(priv, "UNIFI_CFG: Failed to copy the host power mode\n");
862  return -EFAULT;
863  }
864  break;
865  }
867  break;
869  {
870  u16 InterfaceId=0;
871  uf_net_get_name(priv->netdev[InterfaceId], &inst_name[0], sizeof(inst_name));
872 
873  /* Copy the info to the out buffer */
874  if (copy_to_user((void*)arg,
875  &inst_name[0],
876  sizeof(inst_name))) {
877  unifi_error(priv, "UNIFI_CFG: Failed to copy the instance name\n");
878  return -EFAULT;
879  }
880  }
881  break;
882 
884  {
885 #ifdef CSR_SUPPORT_WEXT_AP
886  uf_cfg_ap_config_t cfg_ap_config;
887  cfg_ap_config.channel = priv->ap_config.channel;
888  cfg_ap_config.beaconInterval = priv->ap_mac_config.beaconInterval;
889  cfg_ap_config.wmmEnabled = priv->ap_mac_config.wmmEnabled;
890  cfg_ap_config.dtimPeriod = priv->ap_mac_config.dtimPeriod;
891  cfg_ap_config.phySupportedBitmap = priv->ap_mac_config.phySupportedBitmap;
892  if (copy_to_user((void*)arg,
893  &cfg_ap_config,
894  sizeof(uf_cfg_ap_config_t))) {
895  unifi_error(priv, "UNIFI_CFG: Failed to copy the AP configuration\n");
896  return -EFAULT;
897  }
898 #else
899  return -EPERM;
900 #endif
901  }
902  break;
903 
904 
905  default:
906  unifi_error(priv, "unifi_cfg_get_info: Unknown value.\n");
907  return -EINVAL;
908  }
909 
910  return 0;
911 }
912 #ifdef CSR_SUPPORT_WEXT_AP
913 int
914  uf_configure_supported_rates(u8 * supportedRates, u8 phySupportedBitmap)
915 {
916  int i=0;
917  u8 b=FALSE, g = FALSE, n = FALSE;
918  b = phySupportedBitmap & CSR_WIFI_SME_AP_PHY_SUPPORT_B;
919  n = phySupportedBitmap & CSR_WIFI_SME_AP_PHY_SUPPORT_N;
920  g = phySupportedBitmap & CSR_WIFI_SME_AP_PHY_SUPPORT_G;
921  if(b || g) {
922  supportedRates[i++]=0x82;
923  supportedRates[i++]=0x84;
924  supportedRates[i++]=0x8b;
925  supportedRates[i++]=0x96;
926  } else if(n) {
927  /* For some strange reasons WiFi stack needs both b and g rates*/
928  supportedRates[i++]=0x02;
929  supportedRates[i++]=0x04;
930  supportedRates[i++]=0x0b;
931  supportedRates[i++]=0x16;
932  supportedRates[i++]=0x0c;
933  supportedRates[i++]=0x12;
934  supportedRates[i++]=0x18;
935  supportedRates[i++]=0x24;
936  supportedRates[i++]=0x30;
937  supportedRates[i++]=0x48;
938  supportedRates[i++]=0x60;
939  supportedRates[i++]=0x6c;
940  }
941  if(g) {
942  if(!b) {
943  supportedRates[i++]=0x8c;
944  supportedRates[i++]=0x98;
945  supportedRates[i++]=0xb0;
946  } else {
947  supportedRates[i++]=0x0c;
948  supportedRates[i++]=0x18;
949  supportedRates[i++]=0x30;
950  }
951  supportedRates[i++]=0x48;
952  supportedRates[i++]=0x12;
953  supportedRates[i++]=0x24;
954  supportedRates[i++]=0x60;
955  supportedRates[i++]=0x6c;
956  }
957  return i;
958 }
959 int unifi_cfg_set_ap_config(unifi_priv_t * priv,unsigned char* arg)
960 {
961  uf_cfg_ap_config_t cfg_ap_config;
962  char *buffer;
963 
964  buffer = ((unsigned char*)arg) + sizeof(unifi_cfg_command_t) + sizeof(unsigned int);
965  if (copy_from_user(&cfg_ap_config, (void*)buffer,
966  sizeof(uf_cfg_ap_config_t))) {
967  unifi_error(priv, "UNIFI_CFG: Failed to get the ap config struct\n");
968  return -EFAULT;
969  }
970  priv->ap_config.channel = cfg_ap_config.channel;
971  priv->ap_mac_config.dtimPeriod = cfg_ap_config.dtimPeriod;
972  priv->ap_mac_config.beaconInterval = cfg_ap_config.beaconInterval;
973  priv->group_sec_config.apGroupkeyTimeout = cfg_ap_config.groupkeyTimeout;
974  priv->group_sec_config.apStrictGtkRekey = cfg_ap_config.strictGtkRekeyEnabled;
975  priv->group_sec_config.apGmkTimeout = cfg_ap_config.gmkTimeout;
976  priv->group_sec_config.apResponseTimeout = cfg_ap_config.responseTimeout;
977  priv->group_sec_config.apRetransLimit = cfg_ap_config.retransLimit;
978 
979  priv->ap_mac_config.shortSlotTimeEnabled = cfg_ap_config.shortSlotTimeEnabled;
980  priv->ap_mac_config.ctsProtectionType=cfg_ap_config.ctsProtectionType;
981 
982  priv->ap_mac_config.wmmEnabled = cfg_ap_config.wmmEnabled;
983 
984  priv->ap_mac_config.apHtParams.rxStbc=cfg_ap_config.rxStbc;
985  priv->ap_mac_config.apHtParams.rifsModeAllowed=cfg_ap_config.rifsModeAllowed;
986 
987  priv->ap_mac_config.phySupportedBitmap = cfg_ap_config.phySupportedBitmap;
988  priv->ap_mac_config.maxListenInterval=cfg_ap_config.maxListenInterval;
989 
990  priv->ap_mac_config.supportedRatesCount= uf_configure_supported_rates(priv->ap_mac_config.supportedRates,priv->ap_mac_config.phySupportedBitmap);
991 
992  return 0;
993 }
994 
995 #endif
996 #ifdef CSR_SUPPORT_WEXT
997 
998  void
1000 {
1001  CsrWifiSmeStaConfig staConfig;
1002  CsrWifiSmeDeviceConfig deviceConfig;
1003  unifi_priv_t *priv = container_of(work, unifi_priv_t, sme_config_task);
1004 
1005  /* Register to receive indications from the SME */
1009 
1010  if (sme_mgt_sme_config_get(priv, &staConfig, &deviceConfig)) {
1011  unifi_warning(priv, "uf_sme_config_wq: Get unifi_SMEConfigValue failed.\n");
1012  return;
1013  }
1014 
1015  if (priv->if_index == CSR_INDEX_5G) {
1017  } else {
1019  }
1020 
1021  deviceConfig.trustLevel = (CsrWifiSme80211dTrustLevel)tl_80211d;
1022  if (sme_mgt_sme_config_set(priv, &staConfig, &deviceConfig)) {
1023  unifi_warning(priv,
1024  "SME config for 802.11d Trust Level and Radio Band failed.\n");
1025  return;
1026  }
1027 
1028 } /* uf_sme_config_wq() */
1029 
1030 #endif /* CSR_SUPPORT_WEXT */
1031 
1032 
1033 /*
1034  * ---------------------------------------------------------------------------
1035  * uf_ta_ind_wq
1036  *
1037  * Deferred work queue function to send Traffic Analysis protocols
1038  * indications to the SME.
1039  * These are done in a deferred work queue for two reasons:
1040  * - the CsrWifiRouterCtrl...Send() functions are not safe for atomic context
1041  * - we want to load the main driver data path as lightly as possible
1042  *
1043  * The TA classifications already come from a workqueue.
1044  *
1045  * Arguments:
1046  * work Pointer to work queue item.
1047  *
1048  * Returns:
1049  * None.
1050  * ---------------------------------------------------------------------------
1051  */
1052  void
1054 {
1055  struct ta_ind *ind = container_of(work, struct ta_ind, task);
1056  unifi_priv_t *priv = container_of(ind, unifi_priv_t, ta_ind_work);
1057  u16 interfaceTag = 0;
1058 
1059 
1060  CsrWifiRouterCtrlTrafficProtocolIndSend(priv->CSR_WIFI_SME_IFACEQUEUE,0,
1061  interfaceTag,
1062  ind->packet_type,
1063  ind->direction,
1064  ind->src_addr);
1065  ind->in_use = 0;
1066 
1067 } /* uf_ta_ind_wq() */
1068 
1069 
1070 /*
1071  * ---------------------------------------------------------------------------
1072  * uf_ta_sample_ind_wq
1073  *
1074  * Deferred work queue function to send Traffic Analysis sample
1075  * indications to the SME.
1076  * These are done in a deferred work queue for two reasons:
1077  * - the CsrWifiRouterCtrl...Send() functions are not safe for atomic context
1078  * - we want to load the main driver data path as lightly as possible
1079  *
1080  * The TA classifications already come from a workqueue.
1081  *
1082  * Arguments:
1083  * work Pointer to work queue item.
1084  *
1085  * Returns:
1086  * None.
1087  * ---------------------------------------------------------------------------
1088  */
1089  void
1091 {
1092  struct ta_sample_ind *ind = container_of(work, struct ta_sample_ind, task);
1093  unifi_priv_t *priv = container_of(ind, unifi_priv_t, ta_sample_ind_work);
1094  u16 interfaceTag = 0;
1095 
1096  unifi_trace(priv, UDBG5, "rxtcp %d txtcp %d rxudp %d txudp %d prio %d\n",
1097  priv->rxTcpThroughput,
1098  priv->txTcpThroughput,
1099  priv->rxUdpThroughput,
1100  priv->txUdpThroughput,
1101  priv->bh_thread.prio);
1102 
1103  if(priv->rxTcpThroughput > 1000)
1104  {
1105  if (bh_priority == -1 && priv->bh_thread.prio != 1)
1106  {
1107  struct sched_param param;
1108  priv->bh_thread.prio = 1;
1109  unifi_trace(priv, UDBG1, "%s new thread (RT) priority = %d\n",
1110  priv->bh_thread.name, priv->bh_thread.prio);
1111  param.sched_priority = priv->bh_thread.prio;
1112  sched_setscheduler(priv->bh_thread.thread_task, SCHED_FIFO, &param);
1113  }
1114  } else
1115  {
1116  if (bh_priority == -1 && priv->bh_thread.prio != DEFAULT_PRIO)
1117  {
1118  struct sched_param param;
1119  param.sched_priority = 0;
1120  sched_setscheduler(priv->bh_thread.thread_task, SCHED_NORMAL, &param);
1121  priv->bh_thread.prio = DEFAULT_PRIO;
1122  unifi_trace(priv, UDBG1, "%s new thread priority = %d\n",
1123  priv->bh_thread.name, priv->bh_thread.prio);
1124  set_user_nice(priv->bh_thread.thread_task, PRIO_TO_NICE(priv->bh_thread.prio));
1125  }
1126  }
1127 
1128  CsrWifiRouterCtrlTrafficSampleIndSend(priv->CSR_WIFI_SME_IFACEQUEUE,0, interfaceTag, ind->stats);
1129 
1130  ind->in_use = 0;
1131 
1132 } /* uf_ta_sample_ind_wq() */
1133 
1134 
1135 /*
1136  * ---------------------------------------------------------------------------
1137  * uf_send_m4_ready_wq
1138  *
1139  * Deferred work queue function to send M4 ReadyToSend inds to the SME.
1140  * These are done in a deferred work queue for two reasons:
1141  * - the CsrWifiRouterCtrl...Send() functions are not safe for atomic context
1142  * - we want to load the main driver data path as lightly as possible
1143  *
1144  * Arguments:
1145  * work Pointer to work queue item.
1146  *
1147  * Returns:
1148  * None.
1149  * ---------------------------------------------------------------------------
1150  */
1151 void
1153 {
1154  netInterface_priv_t *InterfacePriv = container_of(work, netInterface_priv_t, send_m4_ready_task);
1155  u16 iface = InterfacePriv->InterfaceTag;
1156  unifi_priv_t *priv = InterfacePriv->privPtr;
1158  CsrWifiMacAddress peer;
1159  unsigned long flags;
1160 
1161  func_enter();
1162 
1163  /* The peer address was stored in the signal */
1164  spin_lock_irqsave(&priv->m4_lock, flags);
1165  memcpy(peer.a, req->Ra.x, sizeof(peer.a));
1166  spin_unlock_irqrestore(&priv->m4_lock, flags);
1167 
1168  /* Send a signal to SME */
1169  CsrWifiRouterCtrlM4ReadyToSendIndSend(priv->CSR_WIFI_SME_IFACEQUEUE, 0, iface, peer);
1170 
1171  unifi_trace(priv, UDBG1, "M4ReadyToSendInd sent for peer %pMF\n",
1172  peer.a);
1173 
1174  func_exit();
1175 
1176 } /* uf_send_m4_ready_wq() */
1177 
1178 #if (defined(CSR_WIFI_SECURITY_WAPI_ENABLE) && defined(CSR_WIFI_SECURITY_WAPI_SW_ENCRYPTION))
1179 /*
1180  * ---------------------------------------------------------------------------
1181  * uf_send_pkt_to_encrypt
1182  *
1183  * Deferred work queue function to send the WAPI data pkts to SME when unicast KeyId = 1
1184  * These are done in a deferred work queue for two reasons:
1185  * - the CsrWifiRouterCtrl...Send() functions are not safe for atomic context
1186  * - we want to load the main driver data path as lightly as possible
1187  *
1188  * Arguments:
1189  * work Pointer to work queue item.
1190  *
1191  * Returns:
1192  * None.
1193  * ---------------------------------------------------------------------------
1194  */
1195 void uf_send_pkt_to_encrypt(struct work_struct *work)
1196 {
1197  netInterface_priv_t *interfacePriv = container_of(work, netInterface_priv_t, send_pkt_to_encrypt);
1198  u16 interfaceTag = interfacePriv->InterfaceTag;
1199  unifi_priv_t *priv = interfacePriv->privPtr;
1200 
1201  u32 pktBulkDataLength;
1202  u8 *pktBulkData;
1203  unsigned long flags;
1204 
1205  if (interfacePriv->interfaceMode == CSR_WIFI_ROUTER_CTRL_MODE_STA) {
1206 
1207  func_enter();
1208 
1209  pktBulkDataLength = interfacePriv->wapi_unicast_bulk_data.data_length;
1210 
1211  if (pktBulkDataLength > 0) {
1212  pktBulkData = kmalloc(pktBulkDataLength, GFP_KERNEL);
1213  memset(pktBulkData, 0, pktBulkDataLength);
1214  } else {
1215  unifi_error(priv, "uf_send_pkt_to_encrypt() : invalid buffer\n");
1216  return;
1217  }
1218 
1219  spin_lock_irqsave(&priv->wapi_lock, flags);
1220  /* Copy over the MA PKT REQ bulk data */
1221  memcpy(pktBulkData, (u8*)interfacePriv->wapi_unicast_bulk_data.os_data_ptr, pktBulkDataLength);
1222  /* Free any bulk data buffers allocated for the WAPI Data pkt */
1223  unifi_net_data_free(priv, &interfacePriv->wapi_unicast_bulk_data);
1224  interfacePriv->wapi_unicast_bulk_data.net_buf_length = 0;
1225  interfacePriv->wapi_unicast_bulk_data.data_length = 0;
1226  interfacePriv->wapi_unicast_bulk_data.os_data_ptr = interfacePriv->wapi_unicast_bulk_data.os_net_buf_ptr = NULL;
1227  spin_unlock_irqrestore(&priv->wapi_lock, flags);
1228 
1229  CsrWifiRouterCtrlWapiUnicastTxEncryptIndSend(priv->CSR_WIFI_SME_IFACEQUEUE, 0, interfaceTag, pktBulkDataLength, pktBulkData);
1230  unifi_trace(priv, UDBG1, "WapiUnicastTxEncryptInd sent to SME\n");
1231 
1232  kfree(pktBulkData); /* Would have been copied over by the SME Handler */
1233 
1234  func_exit();
1235  } else {
1236  unifi_warning(priv, "uf_send_pkt_to_encrypt() is NOT applicable for interface mode - %d\n",interfacePriv->interfaceMode);
1237  }
1238 }/* uf_send_pkt_to_encrypt() */
1239 #endif