/* * --------------------------------------------------------------------------- * uf_send_pkt_to_encrypt * * Deferred work queue function to send the WAPI data pkts to SME when unicast KeyId = 1 * 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 * * Arguments: * work Pointer to work queue item. * * Returns: * None. * --------------------------------------------------------------------------- */ void uf_send_pkt_to_encrypt(struct work_struct *work) { netInterface_priv_t *interfacePriv = container_of(work, netInterface_priv_t, send_pkt_to_encrypt); u16 interfaceTag = interfacePriv->InterfaceTag; unifi_priv_t *priv = interfacePriv->privPtr; u32 pktBulkDataLength; u8 *pktBulkData; unsigned long flags; if (interfacePriv->interfaceMode == CSR_WIFI_ROUTER_CTRL_MODE_STA) { pktBulkDataLength = interfacePriv->wapi_unicast_bulk_data.data_length; if (pktBulkDataLength > 0) { pktBulkData = kmalloc(pktBulkDataLength, GFP_KERNEL); } else { unifi_error(priv, "uf_send_pkt_to_encrypt() : invalid buffer\n"); return; } spin_lock_irqsave(&priv->wapi_lock, flags); /* Copy over the MA PKT REQ bulk data */ memcpy(pktBulkData, (u8*)interfacePriv->wapi_unicast_bulk_data.os_data_ptr, pktBulkDataLength); /* Free any bulk data buffers allocated for the WAPI Data pkt */ unifi_net_data_free(priv, &interfacePriv->wapi_unicast_bulk_data); interfacePriv->wapi_unicast_bulk_data.net_buf_length = 0; interfacePriv->wapi_unicast_bulk_data.data_length = 0; interfacePriv->wapi_unicast_bulk_data.os_data_ptr = interfacePriv->wapi_unicast_bulk_data.os_net_buf_ptr = NULL; spin_unlock_irqrestore(&priv->wapi_lock, flags); CsrWifiRouterCtrlWapiUnicastTxEncryptIndSend(priv->CSR_WIFI_SME_IFACEQUEUE, 0, interfaceTag, pktBulkDataLength, pktBulkData); unifi_trace(priv, UDBG1, "WapiUnicastTxEncryptInd sent to SME\n"); kfree(pktBulkData); /* Would have been copied over by the SME Handler */ } else { unifi_warning(priv, "uf_send_pkt_to_encrypt() is NOT applicable for interface mode - %d\n", interfacePriv->interfaceMode); } }/* uf_send_pkt_to_encrypt() */
/* * --------------------------------------------------------------------------- * unifi_receive_event * * Dispatcher for received signals. * * This function receives the 'to host' signals and forwards * them to the unifi linux clients. * * Arguments: * ospriv Pointer to driver's private data. * sigdata Pointer to the packed signal buffer. * siglen Length of the packed signal. * bulkdata Pointer to the signal's bulk data. * * Returns: * None. * * Notes: * The signals are received in the format described in the host interface * specification, i.e wire formatted. Certain clients use the same format * to interpret them and other clients use the host formatted structures. * Each client has to call read_unpack_signal() to transform the wire * formatted signal into the host formatted signal, if necessary. * The code is in the core, since the signals are defined therefore * binded to the host interface specification. * --------------------------------------------------------------------------- */ void unifi_receive_event(void *ospriv, CsrUint8 *sigdata, CsrUint32 siglen, const bulk_data_param_t *bulkdata) { unifi_priv_t *priv = (unifi_priv_t*)ospriv; int i, receiver_id; int client_id; CsrInt16 signal_id; func_enter(); unifi_trace(priv, UDBG5, "unifi_receive_event: " "%04x %04x %04x %04x %04x %04x %04x %04x (%d)\n", COAL_GET_UINT16_FROM_LITTLE_ENDIAN((sigdata) + sizeof(CsrInt16)*0) & 0xFFFF, COAL_GET_UINT16_FROM_LITTLE_ENDIAN((sigdata) + sizeof(CsrInt16)*1) & 0xFFFF, COAL_GET_UINT16_FROM_LITTLE_ENDIAN((sigdata) + sizeof(CsrInt16)*2) & 0xFFFF, COAL_GET_UINT16_FROM_LITTLE_ENDIAN((sigdata) + sizeof(CsrInt16)*3) & 0xFFFF, COAL_GET_UINT16_FROM_LITTLE_ENDIAN((sigdata) + sizeof(CsrInt16)*4) & 0xFFFF, COAL_GET_UINT16_FROM_LITTLE_ENDIAN((sigdata) + sizeof(CsrInt16)*5) & 0xFFFF, COAL_GET_UINT16_FROM_LITTLE_ENDIAN((sigdata) + sizeof(CsrInt16)*6) & 0xFFFF, COAL_GET_UINT16_FROM_LITTLE_ENDIAN((sigdata) + sizeof(CsrInt16)*7) & 0xFFFF, siglen); receiver_id = COAL_GET_UINT16_FROM_LITTLE_ENDIAN((sigdata) + sizeof(CsrInt16)) & 0xFFF0; client_id = (receiver_id & 0x0F00) >> UDI_SENDER_ID_SHIFT; signal_id = COAL_GET_UINT16_FROM_LITTLE_ENDIAN(sigdata); /* Signals with ReceiverId==0 are also reported to SME / WEXT */ if (receiver_id == 0) { /* * We must not pass MA-UNITDATA.INDICATIONs to the SME because * we can not filter them in the handler. The reason is that we * need to pass some AMP related data, but the filtering needs * be done in the 802.11->802.3 translation to avoid extra process * in the data path. * Also, we filter out the MA-UNITDATA.CONFIRMs which are not * directed to the SME. */ if ((signal_id != CSR_MA_UNITDATA_INDICATION_ID) && (signal_id != CSR_MA_UNITDATA_CONFIRM_ID)) { send_to_client(priv, priv->sme_cli, receiver_id, sigdata, siglen, bulkdata); } #ifdef CSR_NATIVE_LINUX send_to_client(priv, priv->wext_client, receiver_id, sigdata, siglen, bulkdata); #endif } #ifdef CSR_SUPPORT_SME if (signal_id == CSR_MLME_EAPOL_CONFIRM_ID) { if (priv->m4_monitor_state == m4_wait_eapol_confirm) { unifi_trace(priv, UDBG1, "unifi_receive_event: Sending M4 Transmitted IND\n"); unifi_sys_m4_transmitted_ind(priv->smepriv); priv->m4_monitor_state = m4_idle; } } #endif if ((client_id < MAX_UDI_CLIENTS) && (&priv->ul_clients[client_id] != priv->logging_client)) { send_to_client(priv, &priv->ul_clients[client_id], receiver_id, sigdata, siglen, bulkdata); } /* * Free bulk data buffers here unless it is a CSR_MA_UNITDATA_INDICATION */ switch (signal_id) { case CSR_MA_UNITDATA_INDICATION_ID: #ifdef UNIFI_SNIFF_ARPHRD case CSR_MA_SNIFFDATA_INDICATION_ID: #endif break; default: for (i = 0; i < UNIFI_MAX_DATA_REFERENCES; i++) { if (bulkdata->d[i].data_length != 0) { unifi_net_data_free(priv, (void *)&bulkdata->d[i]); } } } func_exit(); } /* unifi_receive_event() */