Beispiel #1
0
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);
}
Beispiel #2
0
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() */
Beispiel #4
0
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
}
Beispiel #5
0
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);
    }
}
Beispiel #6
0
/*
 * ---------------------------------------------------------------------------
 * 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 */
Beispiel #7
0
/*
 * ---------------------------------------------------------------------------
 * 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() */
Beispiel #8
0
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);
}
Beispiel #9
0
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);
}
Beispiel #10
0
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 */
Beispiel #11
0
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;
}
Beispiel #12
0
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;
    }
}
Beispiel #13
0
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;
}
Beispiel #14
0
/*
 * ---------------------------------------------------------------------------
 *  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() */
Beispiel #15
0
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);
}
Beispiel #16
0
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;
}
Beispiel #17
0
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);
}
Beispiel #18
0
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() */
Beispiel #19
0
/*
 * ---------------------------------------------------------------------------
 *  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, &param);
        }
    } 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, &param);
            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() */
Beispiel #21
0
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
}
Beispiel #22
0
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
}
Beispiel #23
0
/*
 * ---------------------------------------------------------------------------
 *  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() */
Beispiel #24
0
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);
}
Beispiel #25
0
/*
 * ---------------------------------------------------------------------------
 *  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 */
Beispiel #26
0
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;
}
Beispiel #27
0
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;
}
Beispiel #28
0
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);
}
Beispiel #29
0
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);
}
Beispiel #30
0
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);
}