int sme_mgt_connect(unifi_priv_t *priv) { int r; if (priv->smepriv == NULL) { unifi_error(priv, "sme_mgt_connect: invalid smepriv\n"); return -EIO; } unifi_trace(priv, UDBG2, "sme_mgt_connect: %.*s\n", priv->connection_config.ssid.length, priv->connection_config.ssid.ssid); r = sme_init_request(priv); if (r) { return -EIO; } CsrWifiSmeConnectReqSend(0, CSR_WIFI_INTERFACE_IN_USE, priv->connection_config); r = sme_wait_for_reply(priv, UNIFI_SME_MGT_SHORT_TIMEOUT); if (r) { return r; } if (priv->sme_reply.reply_status) { unifi_trace(priv, UDBG1, "sme_mgt_connect: failed with SME status %d\n", priv->sme_reply.reply_status); } return convert_sme_error(priv->sme_reply.reply_status); }
void uf_sme_cancel_request(unifi_priv_t *priv, CsrResult reply_status) { /* Check for a blocking SME request in progress, and cancel the wait. * This should be used when the character device is closed. */ if (priv == NULL) { unifi_error(priv, "sme_cancel_request: Invalid priv\n"); return; } /* If no request is pending, nothing to wake up */ if (priv->sme_reply.request_status != SME_REQUEST_PENDING) { unifi_trace(priv, UDBG5, "sme_cancel_request: no request was pending (s:%d)\n", priv->sme_reply.request_status); /* Nothing to do */ return; } unifi_trace(priv, UDBG5, "sme_cancel_request: request cancelled (s:%d)\n", priv->sme_reply.request_status); /* Wake up the wait with an error status */ priv->sme_reply.request_status = SME_REQUEST_CANCELLED; priv->sme_reply.reply_status = reply_status; /* unimportant since the CANCELLED state will fail the ioctl */ wake_up_interruptible(&priv->sme_request_wq); return; }
/* * --------------------------------------------------------------------------- * unifi_suspend * * Handles a suspend request from the SDIO driver. * * Arguments: * ospriv Pointer to OS driver context. * * --------------------------------------------------------------------------- */ void unifi_suspend(void *ospriv) { unifi_priv_t *priv = ospriv; int interfaceTag=0; /* For powered suspend, tell the resume's wifi_on() not to reinit UniFi */ priv->wol_suspend = (enable_wol == UNIFI_WOL_OFF) ? FALSE : TRUE; unifi_trace(priv, UDBG1, "unifi_suspend: wol_suspend %d, enable_wol %d", priv->wol_suspend, enable_wol ); /* Stop network traffic. */ /* need to stop all the netdevices*/ for( interfaceTag=0;interfaceTag<CSR_WIFI_NUM_INTERFACES;interfaceTag++) { netInterface_priv_t *interfacePriv = priv->interfacePriv[interfaceTag]; if (interfacePriv->netdev_registered == 1) { if( priv->wol_suspend ) { unifi_trace(priv, UDBG1, "unifi_suspend: Don't netif_carrier_off"); } else { unifi_trace(priv, UDBG1, "unifi_suspend: netif_carrier_off"); netif_carrier_off(priv->netdev[interfaceTag]); } UF_NETIF_TX_STOP_ALL_QUEUES(priv->netdev[interfaceTag]); } } unifi_trace(priv, UDBG1, "unifi_suspend: suspend SME"); sme_sys_suspend(priv); } /* unifi_suspend() */
int sme_mgt_sme_config_set(unifi_priv_t *priv, CsrWifiSmeStaConfig *staConfig, CsrWifiSmeDeviceConfig *deviceConfig) { #ifdef CSR_SME_USERSPACE int r; if (priv->smepriv == NULL) { unifi_error(priv, "sme_mgt_sme_config_set: invalid smepriv\n"); return -EIO; } r = sme_init_request(priv); if (r) { return -EIO; } CsrWifiSmeSmeStaConfigSetReqSend(0, CSR_WIFI_INTERFACE_IN_USE, *staConfig); r = sme_wait_for_reply(priv, UNIFI_SME_MGT_SHORT_TIMEOUT); if (r) { return r; } unifi_trace(priv, UDBG4, "sme_mgt_sme_config_set: CsrWifiSmeSmeStaConfigSetReq <-- (r=%d status=%d)\n", r, priv->sme_reply.reply_status); r = sme_init_request(priv); if (r) { return -EIO; } CsrWifiSmeSmeCommonConfigSetReqSend(0, *deviceConfig); r = sme_wait_for_reply(priv, UNIFI_SME_MGT_SHORT_TIMEOUT); if (r) { return r; } unifi_trace(priv, UDBG4, "sme_mgt_sme_config_set: CsrWifiSmeSmeCommonConfigSetReq <-- (r=%d status=%d)\n", r, priv->sme_reply.reply_status); return convert_sme_error(priv->sme_reply.reply_status); #else CsrResult status; if (priv->smepriv == NULL) { unifi_error(priv, "sme_mgt_sme_config_set: invalid smepriv\n"); return -EIO; } CsrWifiSmeMgtClaimSyncAccess(priv->smepriv); status = CsrWifiSmeMgtSmeConfigSetReq(priv->smepriv, *staConfig); status = CsrWifiSmeMgtDeviceConfigSetReq(priv->smepriv, *deviceConfig); CsrWifiSmeMgtReleaseSyncAccess(priv->smepriv); return convert_sme_error(status); #endif }
int sme_mgt_scan_full(unifi_priv_t *priv, CsrWifiSsid *specific_ssid, int num_channels, unsigned char *channel_list) { CsrWifiMacAddress bcastAddress = {{0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }}; u8 is_active = (num_channels > 0) ? TRUE : FALSE; int r; if (priv->smepriv == NULL) { unifi_error(priv, "sme_mgt_scan_full: invalid smepriv\n"); return -EIO; } unifi_trace(priv, UDBG4, "sme_mgt_scan_full: -->\n"); r = sme_init_request(priv); if (r) { return -EIO; } /* If a channel list is provided, do an active scan */ if (is_active) { unifi_trace(priv, UDBG1, "channel list - num_channels: %d, active scan\n", num_channels); } CsrWifiSmeScanFullReqSend(0, specific_ssid->length?1:0, /* 0 or 1 SSIDS */ specific_ssid, bcastAddress, is_active, CSR_WIFI_SME_BSS_TYPE_ANY_BSS, CSR_WIFI_SME_SCAN_TYPE_ALL, (u16)num_channels, channel_list, 0, NULL); r = sme_wait_for_reply(priv, UNIFI_SME_MGT_LONG_TIMEOUT); if (r) { return r; } unifi_trace(priv, UDBG4, "sme_mgt_scan_full: <-- (status=%d)\n", priv->sme_reply.reply_status); if (priv->sme_reply.reply_status == CSR_WIFI_RESULT_UNAVAILABLE) { return 0; /* initial scan already underway */ } else { return convert_sme_error(priv->sme_reply.reply_status); } }
/* * --------------------------------------------------------------------------- * uf_sme_port_config_handle * * Return the port config handle of the controlled/uncontrolled port. * * Arguments: * priv Pointer to device private context struct * address Pointer to the destination for tx or sender for rx address * queue Controlled or uncontrolled queue * * Returns: * An unifi_port_cfg_t* . * --------------------------------------------------------------------------- */ unifi_port_cfg_t* uf_sme_port_config_handle(unifi_priv_t *priv, unsigned char *address, int queue, u16 interfaceTag) { int i; unifi_port_config_t *port; netInterface_priv_t *interfacePriv = priv->interfacePriv[interfaceTag]; if (interfaceTag >= CSR_WIFI_NUM_INTERFACES) { unifi_error(priv, "uf_sme_port_config_handle: bad interfaceTag\n"); return NULL; } if (queue == UF_CONTROLLED_PORT_Q) { port = &interfacePriv->controlled_data_port; } else { port = &interfacePriv->uncontrolled_data_port; } if (!port->entries_in_use) { unifi_trace(priv, UDBG5, "No port configurations, return Discard.\n"); return NULL; } /* If the port configuration is common for all destinations, return it. */ if (port->overide_action == UF_DATA_PORT_OVERIDE) { unifi_trace(priv, UDBG5, "Single port configuration (%d).\n", port->port_cfg[0].port_action); if (address) { 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]); } return &port->port_cfg[0]; } unifi_trace(priv, UDBG5, "Multiple port configurations.\n"); /* If multiple configurations exist.. */ for (i = 0; i < UNIFI_MAX_CONNECTIONS; i++) { /* .. go through the list and match the destination address. */ if (port->port_cfg[i].in_use && memcmp(address, port->port_cfg[i].mac_address.a, ETH_ALEN) == 0) { /* Return the desired action. */ return &port->port_cfg[i]; } } /* Could not find any information, return Open. */ unifi_trace(priv, UDBG5, "port configuration not found, returning NULL (debug).\n"); return NULL; } /* uf_sme_port_config_handle */
/* * --------------------------------------------------------------------------- * uf_sme_port_state * * Return the state of the controlled port. * * Arguments: * priv Pointer to device private context struct * address Pointer to the destination for tx or sender for rx address * queue Controlled or uncontrolled queue * * Returns: * An unifi_ControlledPortAction value. * --------------------------------------------------------------------------- */ CsrWifiRouterCtrlPortAction uf_sme_port_state(unifi_priv_t *priv, unsigned char *address, int queue, u16 interfaceTag) { int i; unifi_port_config_t *port; netInterface_priv_t *interfacePriv; if (interfaceTag >= CSR_WIFI_NUM_INTERFACES) { unifi_error(priv, "uf_sme_port_state: bad interfaceTag\n"); return CSR_WIFI_ROUTER_CTRL_PORT_ACTION_8021X_PORT_CLOSED_DISCARD; } interfacePriv = priv->interfacePriv[interfaceTag]; if (queue == UF_CONTROLLED_PORT_Q) { port = &interfacePriv->controlled_data_port; } else { port = &interfacePriv->uncontrolled_data_port; } if (!port->entries_in_use) { unifi_trace(priv, UDBG5, "No port configurations, return Discard.\n"); return CSR_WIFI_ROUTER_CTRL_PORT_ACTION_8021X_PORT_CLOSED_DISCARD; } /* If the port configuration is common for all destinations, return it. */ if (port->overide_action == UF_DATA_PORT_OVERIDE) { unifi_trace(priv, UDBG5, "Single port configuration (%d).\n", port->port_cfg[0].port_action); return port->port_cfg[0].port_action; } unifi_trace(priv, UDBG5, "Multiple (%d) port configurations.\n", port->entries_in_use); /* If multiple configurations exist.. */ for (i = 0; i < UNIFI_MAX_CONNECTIONS; i++) { /* .. go through the list and match the destination address. */ if (port->port_cfg[i].in_use && memcmp(address, port->port_cfg[i].mac_address.a, ETH_ALEN) == 0) { /* Return the desired action. */ return port->port_cfg[i].port_action; } } /* Could not find any information, return Open. */ unifi_trace(priv, UDBG5, "port configuration not found, return Open.\n"); return CSR_WIFI_ROUTER_CTRL_PORT_ACTION_8021X_PORT_OPEN; } /* uf_sme_port_state() */
int sme_mgt_mib_get(unifi_priv_t *priv, unsigned char *varbind, int *length) { int r; if (priv->smepriv == NULL) { unifi_error(priv, "sme_mgt_mib_get: invalid smepriv\n"); return -EIO; } r = sme_init_request(priv); if (r) { return -EIO; } priv->mib_cfm_buffer = varbind; priv->mib_cfm_buffer_length = MAX_VARBIND_LENGTH; CsrWifiSmeMibGetReqSend(0, *length, varbind); r = sme_wait_for_reply(priv, UNIFI_SME_MGT_SHORT_TIMEOUT); if (r) { priv->mib_cfm_buffer_length = 0; priv->mib_cfm_buffer = NULL; return r; } *length = priv->mib_cfm_buffer_length; priv->mib_cfm_buffer_length = 0; priv->mib_cfm_buffer = NULL; unifi_trace(priv, UDBG4, "sme_mgt_mib_get: <-- (status=%d)\n", priv->sme_reply.reply_status); return convert_sme_error(priv->sme_reply.reply_status); }
int sme_mgt_pmkid(unifi_priv_t *priv, CsrWifiSmeListAction action, CsrWifiSmePmkidList *pmkid_list) { int r; if (priv->smepriv == NULL) { unifi_error(priv, "sme_mgt_pmkid: invalid smepriv\n"); return -EIO; } r = sme_init_request(priv); if (r) { return -EIO; } CsrWifiSmePmkidReqSend(0, CSR_WIFI_INTERFACE_IN_USE, action, pmkid_list->pmkidsCount, pmkid_list->pmkids); r = sme_wait_for_reply(priv, UNIFI_SME_MGT_SHORT_TIMEOUT); if (r) { return r; } unifi_trace(priv, UDBG4, "sme_mgt_pmkid: <-- (status=%d)\n", priv->sme_reply.reply_status); return convert_sme_error(priv->sme_reply.reply_status); }
int sme_mgt_wifi_off(unifi_priv_t *priv) { int r; if (priv->smepriv == NULL) { unifi_error(priv, "sme_mgt_wifi_off: invalid smepriv\n"); return -EIO; } r = sme_init_request(priv); if (r) { return -EIO; } /* Stop the SME */ CsrWifiSmeWifiOffReqSend(0); r = sme_wait_for_reply(priv, UNIFI_SME_MGT_LONG_TIMEOUT); if (r) { return r; } unifi_trace(priv, UDBG4, "sme_mgt_wifi_off: unifi_mgt_wifi_off_req <-- (r=%d, status=%d)\n", r, priv->sme_reply.reply_status); return convert_sme_error(priv->sme_reply.reply_status); } /* sme_mgt_wifi_off */
void uf_sme_complete_request(unifi_priv_t *priv, CsrResult reply_status, const char *func) { if (priv == NULL) { unifi_error(priv, "sme_complete_request: Invalid priv\n"); return; } if (priv->sme_reply.request_status != SME_REQUEST_PENDING) { unifi_notice(priv, "sme_complete_request: request not pending %s (s:%d)\n", (func ? func : ""), priv->sme_reply.request_status); return; } unifi_trace(priv, UDBG5, "sme_complete_request: completed %s (s:%d)\n", (func ? func : ""), priv->sme_reply.request_status); priv->sme_reply.request_status = SME_REQUEST_RECEIVED; priv->sme_reply.reply_status = reply_status; wake_up_interruptible(&priv->sme_request_wq); return; }
int uf_verify_m4(unifi_priv_t *priv, const unsigned char *packet, unsigned int length) { const unsigned char *p = packet; CsrUint16 keyinfo; if (length < (4 + 5 + 8 + 32 + 16 + 8 + 8 + 16 + 1 + 8)) { return 1; } p += 8; keyinfo = p[5] << 8 | p[6]; /* big-endian */ if ( (p[0] == 1 || p[0] == 2) /* protocol version 802.1X-2001 (WPA) or -2004 (WPA2) */ && p[1] == 3 /* EAPOL-Key */ && /* don't bother checking p[2] p[3] (hh ll, packet body length) */ (p[4] == 254 || p[4] == 2) /* descriptor type P802.1i-D3.0 (WPA) or 802.11i-2004 (WPA2) */ && ((keyinfo & 0x0007) == 1 || (keyinfo & 0x0007) == 2) /* key descriptor version */ && (keyinfo & ~0x0207U) == 0x0108 && /* key info for 4/4 or 4/2 -- ignore key desc version and sec bit (since varies in WPA 4/4) */ (p[4 + 5 + 8 + 32 + 16 + 8 + 8 + 16 + 0] == 0 && /* key data length (2 octets) 0 for 4/4 only */ p[4 + 5 + 8 + 32 + 16 + 8 + 8 + 16 + 1] == 0) ) { unifi_trace(priv, UDBG1, "uf_verify_m4: M4 detected \n"); return 0; } else { return 1; } }
int unifi_cfg_enable_okc(unifi_priv_t *priv, unsigned char *arg) { u8 enable_okc; u8 *enable_okc_params; int rc; CsrWifiSmeStaConfig staConfig; CsrWifiSmeDeviceConfig deviceConfig; enable_okc_params = (u8*)(((unifi_cfg_command_t*)arg) + 1); if (get_user(enable_okc, (u8*)enable_okc_params)) { unifi_error(priv, "unifi_cfg_enable_okc: Failed to get the argument\n"); return -EFAULT; } unifi_trace(priv, UDBG4, "enable_okc: = %s\n", ((enable_okc) ? "yes":"no")); rc = sme_mgt_sme_config_get(priv, &staConfig, &deviceConfig); if (rc) { unifi_warning(priv, "unifi_cfg_enable_okc: Get unifi_SMEConfigValue failed.\n"); return -EFAULT; } staConfig.enableOpportunisticKeyCaching = enable_okc; rc = sme_mgt_sme_config_set(priv, &staConfig, &deviceConfig); if (rc) { unifi_warning(priv, "unifi_cfg_enable_okc: Set unifi_SMEConfigValue failed.\n"); rc = -EFAULT; } return rc; }
/* * --------------------------------------------------------------------------- * uf_unregister_netdev * * Unregisters the network interface and the inet handler. * * Arguments: * priv Pointer to driver context. * * Returns: * None. * * --------------------------------------------------------------------------- */ void uf_unregister_netdev(unifi_priv_t *priv) { int i=0; #ifdef CSR_SUPPORT_SME /* Unregister the inet handler... */ uf_unregister_inet_notifier(); #endif /* CSR_SUPPORT_SME */ for (i=0; i<CSR_WIFI_NUM_INTERFACES; i++) { netInterface_priv_t *interfacePriv = priv->interfacePriv[i]; if (interfacePriv->netdev_registered) { unifi_trace(priv, UDBG5, "uf_unregister_netdev: netdev %d - 0x%p\n", i, priv->netdev[i]); /* ... and the netdev */ unregister_netdev(priv->netdev[i]); interfacePriv->netdev_registered = 0; } interfacePriv->interfaceMode = 0; /* Enable all queues by default */ interfacePriv->queueEnabled[0] = 1; interfacePriv->queueEnabled[1] = 1; interfacePriv->queueEnabled[2] = 1; interfacePriv->queueEnabled[3] = 1; } priv->totalInterfaceCount = 0; } /* uf_unregister_netdev() */
void unifi_mgt_scan_full_req(FsmContext* context, void* appHandle, CsrUint8 ssidCount, const unifi_SSID *ssid, const unifi_MACAddress *bssid, CsrBool forceScan, unifi_BSSType bssType, unifi_ScanType scanType, CsrUint16 channelListCount, const CsrUint8 *channelList, CsrUint16 probeIeLength, const CsrUint8 *probeIe) { unifi_priv_t* priv = (unifi_priv_t*)context; CsrUint8* buf; CsrUint16 buflen; unifi_trace(priv, UDBG2, "unifi_mgt_scan_full_req\n"); buflen = serialise_unifi_mgt_scan_full_req(&buf, appHandle, ssidCount, ssid, bssid, forceScan, bssType, scanType, channelListCount, channelList, probeIeLength, probeIe); /* Send message to user space */ sme_queue_message(priv, buf, buflen); }
int unifi_cfg_strict_draft_n(unifi_priv_t *priv, unsigned char *arg) { u8 strict_draft_n; u8 *strict_draft_n_params; int rc; CsrWifiSmeStaConfig staConfig; CsrWifiSmeDeviceConfig deviceConfig; strict_draft_n_params = (u8*)(((unifi_cfg_command_t*)arg) + 1); if (get_user(strict_draft_n, (u8*)strict_draft_n_params)) { unifi_error(priv, "unifi_cfg_strict_draft_n: Failed to get the argument\n"); return -EFAULT; } unifi_trace(priv, UDBG4, "strict_draft_n: = %s\n", ((strict_draft_n) ? "yes":"no")); rc = sme_mgt_sme_config_get(priv, &staConfig, &deviceConfig); if (rc) { unifi_warning(priv, "unifi_cfg_strict_draft_n: Get unifi_SMEConfigValue failed.\n"); return -EFAULT; } deviceConfig.enableStrictDraftN = strict_draft_n; rc = sme_mgt_sme_config_set(priv, &staConfig, &deviceConfig); if (rc) { unifi_warning(priv, "unifi_cfg_strict_draft_n: Set unifi_SMEConfigValue failed.\n"); rc = -EFAULT; } return rc; }
void unifi_mgt_mic_failure_ind(void *drvpriv, CsrUint16 appHandlesCount, void* *appHandles, CsrBool secondFailure, CsrUint16 count, const unifi_MACAddress* address, unifi_KeyType keyType, CsrUint16 keyId, const CsrUint16* tSC) { unifi_priv_t *priv = (unifi_priv_t*)drvpriv; CSR_MLME_MICHAELMICFAILURE_INDICATION mic_ind; if (priv == NULL) { unifi_error(NULL, "unifi_mgt_mic_failure_ind: invalid priv\n"); return; } unifi_trace(priv, UDBG1, "unifi_mgt_mic_failure_ind: count=%d, KeyType=%d, KeyId=%d\n", count, keyType, keyId); mic_ind.Count = count; memcpy(mic_ind.Address.x, address->data, 6); mic_ind.KeyType = keyType; mic_ind.KeyId = keyId; memcpy(mic_ind.Tsc, tSC, sizeof(CsrUint16) * 4); wext_send_michaelmicfailure_event(priv, &mic_ind); }
static int _sme_wait_for_reply(unifi_priv_t *priv, unsigned long timeout, const char *func) { long r; unifi_trace(priv, UDBG5, "sme_wait_for_reply: %s sleep\n", func ? func : ""); r = wait_event_interruptible_timeout(priv->sme_request_wq, (priv->sme_reply.request_status != SME_REQUEST_PENDING), msecs_to_jiffies(timeout)); unifi_trace(priv, UDBG5, "sme_wait_for_reply: %s awake (%d)\n", func ? func : "", r); if (r == -ERESTARTSYS) { /* The thread was killed */ unifi_info(priv, "ERESTARTSYS in _sme_wait_for_reply\n"); up(&priv->sme_sem); return r; } if (priv->sme_reply.request_status == SME_REQUEST_CANCELLED) { unifi_trace(priv, UDBG5, "Cancelled waiting for SME to reply (%s s:%d, t:%d, r:%d)\n", (func ? func : ""), priv->sme_reply.request_status, timeout, r); /* Release the SME semaphore that was downed in sme_init_request() */ up(&priv->sme_sem); return -EIO; /* fail the ioctl */ } if ((r == 0) && (priv->sme_reply.request_status != SME_REQUEST_RECEIVED)) { unifi_notice(priv, "Timeout waiting for SME to reply (%s s:%d, t:%d)\n", (func ? func : ""), priv->sme_reply.request_status, timeout); priv->sme_reply.request_status = SME_REQUEST_TIMEDOUT; /* Release the SME semaphore that was downed in sme_init_request() */ up(&priv->sme_sem); return -ETIMEDOUT; } unifi_trace(priv, UDBG5, "sme_wait_for_reply: %s received (%d)\n", func ? func : "", r); /* Release the SME semaphore that was downed in sme_init_request() */ up(&priv->sme_sem); return 0; } /* sme_wait_for_reply() */
/* * --------------------------------------------------------------------------- * uf_ta_sample_ind_wq * * Deferred work queue function to send Traffic Analysis sample * indications to the SME. * These are done in a deferred work queue for two reasons: * - the CsrWifiRouterCtrl...Send() functions are not safe for atomic context * - we want to load the main driver data path as lightly as possible * * The TA classifications already come from a workqueue. * * Arguments: * work Pointer to work queue item. * * Returns: * None. * --------------------------------------------------------------------------- */ void uf_ta_sample_ind_wq(struct work_struct *work) { struct ta_sample_ind *ind = container_of(work, struct ta_sample_ind, task); unifi_priv_t *priv = container_of(ind, unifi_priv_t, ta_sample_ind_work); u16 interfaceTag = 0; unifi_trace(priv, UDBG5, "rxtcp %d txtcp %d rxudp %d txudp %d prio %d\n", priv->rxTcpThroughput, priv->txTcpThroughput, priv->rxUdpThroughput, priv->txUdpThroughput, priv->bh_thread.prio); if(priv->rxTcpThroughput > 1000) { if (bh_priority == -1 && priv->bh_thread.prio != 1) { struct sched_param param; priv->bh_thread.prio = 1; unifi_trace(priv, UDBG1, "%s new thread (RT) priority = %d\n", priv->bh_thread.name, priv->bh_thread.prio); param.sched_priority = priv->bh_thread.prio; sched_setscheduler(priv->bh_thread.thread_task, SCHED_FIFO, ¶m); } } else { if (bh_priority == -1 && priv->bh_thread.prio != DEFAULT_PRIO) { struct sched_param param; param.sched_priority = 0; sched_setscheduler(priv->bh_thread.thread_task, SCHED_NORMAL, ¶m); priv->bh_thread.prio = DEFAULT_PRIO; unifi_trace(priv, UDBG1, "%s new thread priority = %d\n", priv->bh_thread.name, priv->bh_thread.prio); set_user_nice(priv->bh_thread.thread_task, PRIO_TO_NICE(priv->bh_thread.prio)); } } CsrWifiRouterCtrlTrafficSampleIndSend(priv->CSR_WIFI_SME_IFACEQUEUE, 0, interfaceTag, ind->stats); ind->in_use = 0; } /* uf_ta_sample_ind_wq() */
/* * --------------------------------------------------------------------------- * unifi_resume * * Handles a resume request from the SDIO driver. * * Arguments: * ospriv Pointer to OS driver context. * * --------------------------------------------------------------------------- */ void unifi_resume(void *ospriv) { unifi_priv_t *priv = ospriv; int interfaceTag=0; int r; int wol = priv->wol_suspend; unifi_trace(priv, UDBG1, "unifi_resume: resume SME, enable_wol=%d", enable_wol); /* The resume causes wifi-on which will re-enable the BH and reinstall the ISR */ r = sme_sys_resume(priv); if (r) { unifi_error(priv, "Failed to resume UniFi\n"); } /* Resume the network interfaces. For the cold resume case, this will * happen upon reconnection. */ if (wol) { unifi_trace(priv, UDBG1, "unifi_resume: try to enable carrier"); /* need to start all the netdevices*/ for( interfaceTag=0;interfaceTag<CSR_WIFI_NUM_INTERFACES;interfaceTag++) { netInterface_priv_t *interfacePriv = priv->interfacePriv[interfaceTag]; unifi_trace(priv, UDBG1, "unifi_resume: interfaceTag %d netdev_registered %d mode %d\n", interfaceTag, interfacePriv->netdev_registered, interfacePriv->interfaceMode); if (interfacePriv->netdev_registered == 1) { netif_carrier_on(priv->netdev[interfaceTag]); UF_NETIF_TX_START_ALL_QUEUES(priv->netdev[interfaceTag]); } } /* Kick the BH thread (with reason=host) to poll for data that may have * arrived during a powered suspend. This caters for the case where the SME * doesn't interact with the chip (e.g install autonomous scans) during resume. */ unifi_send_signal(priv->card, NULL, 0, NULL); } } /* unifi_resume() */
int sme_mgt_host_config_get(unifi_priv_t *priv, CsrWifiSmeHostConfig *hostConfig) { #ifdef CSR_SME_USERSPACE int r; if (priv->smepriv == NULL) { unifi_error(priv, "sme_mgt_host_config_get: invalid smepriv\n"); return -EIO; } unifi_trace(priv, UDBG4, "sme_mgt_host_config_get: unifi_mgt_host_config_get_req -->\n"); r = sme_init_request(priv); if (r) { return -EIO; } CsrWifiSmeHostConfigGetReqSend(0, CSR_WIFI_INTERFACE_IN_USE); r = sme_wait_for_reply(priv, UNIFI_SME_MGT_SHORT_TIMEOUT); if (r) { return r; } /* store the reply */ if (hostConfig != NULL) { memcpy((unsigned char*)hostConfig, (unsigned char*)&priv->sme_reply.hostConfig, sizeof(CsrWifiSmeHostConfig)); } unifi_trace(priv, UDBG4, "sme_mgt_host_config_get: unifi_mgt_host_config_get_req <-- (r=%d status=%d)\n", r, priv->sme_reply.reply_status); return convert_sme_error(priv->sme_reply.reply_status); #else CsrResult status; CsrWifiSmeMgtClaimSyncAccess(priv->smepriv); status = CsrWifiSmeMgtHostConfigGetReq(priv->smepriv, hostConfig); CsrWifiSmeMgtReleaseSyncAccess(priv->smepriv); return convert_sme_error(status); #endif }
int sme_mgt_versions_get(unifi_priv_t *priv, CsrWifiSmeVersions *versions) { #ifdef CSR_SME_USERSPACE int r; if (priv->smepriv == NULL) { unifi_error(priv, "sme_mgt_versions_get: invalid smepriv\n"); return -EIO; } unifi_trace(priv, UDBG4, "sme_mgt_versions_get: unifi_mgt_versions_get_req -->\n"); r = sme_init_request(priv); if (r) { return -EIO; } CsrWifiSmeVersionsGetReqSend(0); r = sme_wait_for_reply(priv, UNIFI_SME_MGT_SHORT_TIMEOUT); if (r) { return r; } /* store the reply */ if (versions != NULL) { memcpy((unsigned char*)versions, (unsigned char*)&priv->sme_reply.versions, sizeof(CsrWifiSmeVersions)); } unifi_trace(priv, UDBG4, "sme_mgt_versions_get: unifi_mgt_versions_get_req <-- (r=%d status=%d)\n", r, priv->sme_reply.reply_status); return convert_sme_error(priv->sme_reply.reply_status); #else CsrResult status; CsrWifiSmeMgtClaimSyncAccess(priv->smepriv); status = CsrWifiSmeMgtVersionsGetReq(priv->smepriv, versions); CsrWifiSmeMgtReleaseSyncAccess(priv->smepriv); return convert_sme_error(status); #endif }
/* * --------------------------------------------------------------------------- * unifi_fw_read_start * * Returns a structure to be passed in unifi_fw_read(). * This structure is an OS specific description of the f/w file. * In the linux implementation it is a buffer with the f/w and its' length. * The HIP driver calls this functions to request for the loader or * the firmware file. * The structure pointer can be freed when unifi_fw_read_stop() is called. * * Arguments: * ospriv Pointer to driver context. * is_fw Flag to indicate whether it is the f/w or the loader * info Versions information. Can be used to determine * the appropriate f/w file to load. * * Returns: * O on success, non-zero otherwise. * * --------------------------------------------------------------------------- */ void* unifi_fw_read_start(void *ospriv, CsrInt8 is_fw, const card_info_t *info) { unifi_priv_t *priv = (unifi_priv_t*)ospriv; CSR_UNUSED(info); func_enter(); #ifdef ANDROID_BUILD /* Copy content of info to the priv struct to make it available in the reguest_firmware_files() function */ priv->card_info = *info; printk("Unifi: Firmware build %d\n", (int) info->fw_build); #endif if (is_fw == UNIFI_FW_LOADER) { /* F/w may have been released after a previous successful download */ if (priv->fw_loader.dl_data == NULL) { unifi_trace(priv, UDBG2, "Attempt reload of loader f/w\n"); uf_request_firmware_files(priv, UNIFI_FW_LOADER); } /* Set up callback struct for readfunc() */ if (priv->fw_loader.dl_data != NULL) { func_exit(); return &priv->fw_loader; } } else if (is_fw == UNIFI_FW_STA) { /* F/w may have been released after a previous successful download. */ if (priv->fw_sta.dl_data == NULL) { unifi_trace(priv, UDBG2, "Attempt reload of sta f/w\n"); uf_request_firmware_files(priv, UNIFI_FW_STA); } /* Set up callback struct for readfunc() */ if (priv->fw_sta.dl_data != NULL) { func_exit(); return &priv->fw_sta; } } else { unifi_error(priv, "downloading firmware... unknown request: %d\n", is_fw); } func_exit(); return NULL; } /* unifi_fw_read_start() */
void uf_multicast_list_wq(struct work_struct *work) { unifi_priv_t *priv = container_of(work, unifi_priv_t, multicast_list_task); int i; u16 interfaceTag = 0; CsrWifiMacAddress* multicast_address_list = NULL; int mc_count; u8 *mc_list; netInterface_priv_t *interfacePriv = priv->interfacePriv[interfaceTag]; if (interfaceTag >= CSR_WIFI_NUM_INTERFACES) { unifi_error(priv, "uf_multicast_list_wq: bad interfaceTag\n"); return; } unifi_trace(priv, UDBG5, "uf_multicast_list_wq: list count = %d\n", interfacePriv->mc_list_count); /* Flush the current list */ CsrWifiRouterCtrlMulticastAddressIndSend(priv->CSR_WIFI_SME_IFACEQUEUE, 0, interfaceTag, CSR_WIFI_SME_LIST_ACTION_FLUSH, 0, NULL); mc_count = interfacePriv->mc_list_count; mc_list = interfacePriv->mc_list; /* * Allocate a new list, need to free it later * in unifi_mgt_multicast_address_cfm(). */ multicast_address_list = kmalloc(mc_count * sizeof(CsrWifiMacAddress), GFP_KERNEL); if (multicast_address_list == NULL) { return; } for (i = 0; i < mc_count; i++) { memcpy(multicast_address_list[i].a, mc_list, ETH_ALEN); mc_list += ETH_ALEN; } if (priv->smepriv == NULL) { kfree(multicast_address_list); return; } CsrWifiRouterCtrlMulticastAddressIndSend(priv->CSR_WIFI_SME_IFACEQUEUE, 0, interfaceTag, CSR_WIFI_SME_LIST_ACTION_ADD, mc_count, multicast_address_list); /* The SME will take a copy of the addreses*/ kfree(multicast_address_list); }
/* * --------------------------------------------------------------------------- * uf_register_netdev * * Registers the network interface, installes the qdisc, * and registers the inet handler. * In the porting exercise, register the driver to the network * stack if necessary. * * Arguments: * priv Pointer to driver context. * * Returns: * O on success, non-zero otherwise. * * Notes: * We will only unregister when the card is ejected, so we must * only do it once. * --------------------------------------------------------------------------- */ int uf_register_netdev(unifi_priv_t *priv, int interfaceTag) { int r; netInterface_priv_t *interfacePriv = priv->interfacePriv[interfaceTag]; if (interfaceTag >= CSR_WIFI_NUM_INTERFACES) { unifi_error(priv, "uf_register_netdev bad interfaceTag\n"); return -EINVAL; } /* * Allocates a device number and registers device with the network * stack. */ unifi_trace(priv, UDBG5, "uf_register_netdev: netdev %d - 0x%p\n", interfaceTag, priv->netdev[interfaceTag]); r = register_netdev(priv->netdev[interfaceTag]); if (r) { unifi_error(priv, "Failed to register net device\n"); return -EINVAL; } /* The device is registed */ interfacePriv->netdev_registered = 1; #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,28) #ifdef CONFIG_NET_SCHED /* * IMPORTANT: * uf_install_qdisc() holds the network device lock, we can not * install the qdisk before the network device is registered. */ r = uf_install_qdisc(priv->netdev[interfaceTag]); if (r) { unifi_error(priv, "Failed to install qdisc\n"); return r; } #endif /* CONFIG_NET_SCHED */ #endif /* LINUX_VERSION_CODE */ #ifdef CSR_SUPPORT_SME /* * Register the inet handler; it notifies us for changes in the IP address. */ uf_register_inet_notifier(); #endif /* CSR_SUPPORT_SME */ unifi_notice(priv, "unifi%d is %s\n", priv->instance, priv->netdev[interfaceTag]->name); return 0; } /* uf_register_netdev */
int unifi_cfg_wmm_addts(unifi_priv_t *priv, unsigned char *arg) { CsrUint32 addts_tid; CsrUint8 addts_ie_length; CsrUint8 *addts_ie; CsrUint8 *addts_params; unifi_DataBlock tspec; unifi_DataBlock tclas; int rc; addts_params = (CsrUint8*)(((unifi_cfg_command_t*)arg) + 1); if (get_user(addts_tid, (CsrUint32*)addts_params)) { unifi_error(priv, "unifi_cfg_wmm_addts: Failed to get the argument\n"); return -EFAULT; } addts_params += sizeof(CsrUint32); if (get_user(addts_ie_length, (CsrUint8*)addts_params)) { unifi_error(priv, "unifi_cfg_wmm_addts: Failed to get the argument\n"); return -EFAULT; } unifi_trace(priv, UDBG4, "addts: tid = 0x%x ie_length = %d\n", addts_tid, addts_ie_length); addts_ie = CsrPmalloc(addts_ie_length); if (addts_ie == NULL) { unifi_error(priv, "unifi_cfg_wmm_addts: Failed to malloc %d bytes for addts_ie buffer\n", addts_ie_length); return -ENOMEM; } addts_params += sizeof(CsrUint8); rc = copy_from_user(addts_ie, addts_params, addts_ie_length); if (rc) { unifi_error(priv, "unifi_cfg_wmm_addts: Failed to get the addts buffer\n"); CsrPfree(addts_ie); return -EFAULT; } tspec.data = addts_ie; tspec.length = addts_ie_length; tclas.data = NULL; tclas.length = 0; rc = sme_mgt_tspec(priv, unifi_ListActionAdd, addts_tid, &tspec, &tclas); CsrPfree(addts_ie); return rc; }
int unifi_cfg_wmm_addts(unifi_priv_t *priv, unsigned char *arg) { u32 addts_tid; u8 addts_ie_length; u8 *addts_ie; u8 *addts_params; CsrWifiSmeDataBlock tspec; CsrWifiSmeDataBlock tclas; int rc; addts_params = (u8*)(((unifi_cfg_command_t*)arg) + 1); if (get_user(addts_tid, (u32*)addts_params)) { unifi_error(priv, "unifi_cfg_wmm_addts: Failed to get the argument\n"); return -EFAULT; } addts_params += sizeof(u32); if (get_user(addts_ie_length, (u8*)addts_params)) { unifi_error(priv, "unifi_cfg_wmm_addts: Failed to get the argument\n"); return -EFAULT; } unifi_trace(priv, UDBG4, "addts: tid = 0x%x ie_length = %d\n", addts_tid, addts_ie_length); addts_ie = kmalloc(addts_ie_length, GFP_KERNEL); if (addts_ie == NULL) { unifi_error(priv, "unifi_cfg_wmm_addts: Failed to malloc %d bytes for addts_ie buffer\n", addts_ie_length); return -ENOMEM; } addts_params += sizeof(u8); rc = copy_from_user(addts_ie, addts_params, addts_ie_length); if (rc) { unifi_error(priv, "unifi_cfg_wmm_addts: Failed to get the addts buffer\n"); kfree(addts_ie); return -EFAULT; } tspec.data = addts_ie; tspec.length = addts_ie_length; tclas.data = NULL; tclas.length = 0; rc = sme_mgt_tspec(priv, CSR_WIFI_SME_LIST_ACTION_ADD, addts_tid, &tspec, &tclas); kfree(addts_ie); return rc; }
void unifi_mgt_get_value_req(FsmContext* context, void* appHandle, unifi_AppValueId appValueId) { unifi_priv_t* priv = (unifi_priv_t*)context; CsrUint8* buf; CsrUint16 buflen; unifi_trace(priv, UDBG2, "unifi_mgt_get_value_req(%d)\n", appValueId); buflen = serialise_unifi_mgt_get_value_req(&buf, appHandle, appValueId); /* Send message to user space */ sme_queue_message(priv, buf, buflen); }
void unifi_mgt_wifi_off_req(FsmContext* context, void* appHandle) { unifi_priv_t* priv = (unifi_priv_t*)context; CsrUint8* buf; CsrUint16 buflen; unifi_trace(priv, UDBG2, "unifi_mgt_wifi_off_req\n"); buflen = serialise_unifi_mgt_wifi_off_req(&buf, appHandle); /* Send message to user space */ sme_queue_message(priv, buf, buflen); }
void unifi_mgt_mib_set_req(FsmContext* context, void* appHandle, CsrUint16 mibAttributeLength, const CsrUint8 *mibAttribute) { unifi_priv_t* priv = (unifi_priv_t*)context; CsrUint8* buf; CsrUint16 buflen; unifi_trace(priv, UDBG2, "unifi_mgt_mib_set_req\n"); buflen = serialise_unifi_mgt_mib_set_req(&buf, appHandle, mibAttributeLength, mibAttribute); /* Send message to user space */ sme_queue_message(priv, buf, buflen); }