linux/drivers/staging/csr/sme_blocking.c
<<
>>
Prefs
   1/*
   2 * ---------------------------------------------------------------------------
   3 * FILE:     sme_mgt_blocking.c
   4 *
   5 * PURPOSE:
   6 *      This file contains the driver specific implementation of
   7 *      the WEXT <==> SME MGT interface for all SME builds that support WEXT.
   8 *
   9 * Copyright (C) 2009 by Cambridge Silicon Radio Ltd.
  10 *
  11 * Refer to LICENSE.txt included with this source code for details on
  12 * the license terms.
  13 *
  14 * ---------------------------------------------------------------------------
  15 */
  16
  17#include "unifi_priv.h"
  18
  19
  20/*
  21 * This file also contains the implementation of the asynchronous
  22 * requests to the SME.
  23 *
  24 * Before calling an asynchronous SME function, we call sme_init_request()
  25 * which gets hold of the SME semaphore and updates the request status.
  26 * The semaphore makes sure that there is only one pending request to
  27 * the SME at a time.
  28 *
  29 * Now we are ready to call the SME function, but only if
  30 * sme_init_request() has returned 0.
  31 *
  32 * When the SME function returns, we need to wait
  33 * for the reply. This is done in sme_wait_for_reply().
  34 * If the request times-out, the request status is set to SME_REQUEST_TIMEDOUT
  35 * and the sme_wait_for_reply() returns.
  36 *
  37 * If the SME replies in time, we call sme_complete_request().
  38 * There we change the request status to SME_REQUEST_RECEIVED. This will
  39 * wake up the process waiting on sme_wait_for_reply().
  40 * It is important that we copy the reply data in priv->sme_reply
  41 * before calling sme_complete_request().
  42 *
  43 * Handling the wext requests, we need to block
  44 * until the SME sends the response to our request.
  45 * We use the sme_init_request() and sme_wait_for_reply()
  46 * to implement this behavior in the following functions:
  47 * sme_mgt_wifi_on()
  48 * sme_mgt_wifi_off()
  49 * sme_mgt_scan_full()
  50 * sme_mgt_scan_results_get_async()
  51 * sme_mgt_connect()
  52 * unifi_mgt_media_status_ind()
  53 * sme_mgt_disconnect()
  54 * sme_mgt_pmkid()
  55 * sme_mgt_key()
  56 * sme_mgt_mib_get()
  57 * sme_mgt_mib_set()
  58 * sme_mgt_versions_get()
  59 * sme_mgt_set_value()
  60 * sme_mgt_get_value()
  61 * sme_mgt_set_value_async()
  62 * sme_mgt_get_value_async()
  63 * sme_mgt_packet_filter_set()
  64 * sme_mgt_tspec()
  65 */
  66
  67
  68/*
  69 * Handling the suspend and resume system events, we need to block
  70 * until the SME sends the response to our indication.
  71 * We use the sme_init_request() and sme_wait_for_reply()
  72 * to implement this behavior in the following functions:
  73 * sme_sys_suspend()
  74 * sme_sys_resume()
  75 */
  76
  77#define UNIFI_SME_MGT_SHORT_TIMEOUT    10000
  78#define UNIFI_SME_MGT_LONG_TIMEOUT     19000
  79#define UNIFI_SME_SYS_LONG_TIMEOUT     10000
  80
  81#ifdef UNIFI_DEBUG
  82# define sme_wait_for_reply(priv, t) _sme_wait_for_reply(priv, t, __func__)
  83#else
  84# define sme_wait_for_reply(priv, t) _sme_wait_for_reply(priv, t, NULL)
  85#endif
  86
  87static int
  88sme_init_request(unifi_priv_t *priv)
  89{
  90    if (priv == NULL) {
  91        unifi_error(priv, "sme_init_request: Invalid priv\n");
  92        return -EIO;
  93    }
  94
  95    unifi_trace(priv, UDBG5, "sme_init_request: wait sem\n");
  96
  97    /* Grab the SME semaphore until the reply comes, or timeout */
  98    if (down_interruptible(&priv->sme_sem)) {
  99        unifi_error(priv, "sme_init_request: Failed to get SME semaphore\n");
 100        return -EIO;
 101    }
 102    unifi_trace(priv, UDBG5, "sme_init_request: got sem: pending\n");
 103
 104    priv->sme_reply.request_status = SME_REQUEST_PENDING;
 105
 106    return 0;
 107
 108} /* sme_init_request() */
 109
 110
 111void
 112uf_sme_complete_request(unifi_priv_t *priv, CsrResult reply_status, const char *func)
 113{
 114    if (priv == NULL) {
 115        unifi_error(priv, "sme_complete_request: Invalid priv\n");
 116        return;
 117    }
 118
 119    if (priv->sme_reply.request_status != SME_REQUEST_PENDING) {
 120        unifi_notice(priv,
 121                    "sme_complete_request: request not pending %s (s:%d)\n",
 122                    (func ? func : ""), priv->sme_reply.request_status);
 123        return;
 124    }
 125    unifi_trace(priv, UDBG5,
 126                "sme_complete_request: completed %s (s:%d)\n",
 127                (func ? func : ""), priv->sme_reply.request_status);
 128
 129    priv->sme_reply.request_status = SME_REQUEST_RECEIVED;
 130    priv->sme_reply.reply_status = reply_status;
 131
 132    wake_up_interruptible(&priv->sme_request_wq);
 133
 134    return;
 135}
 136
 137
 138void
 139uf_sme_cancel_request(unifi_priv_t *priv, CsrResult reply_status)
 140{
 141    /* Check for a blocking SME request in progress, and cancel the wait.
 142     * This should be used when the character device is closed.
 143     */
 144
 145    if (priv == NULL) {
 146        unifi_error(priv, "sme_cancel_request: Invalid priv\n");
 147        return;
 148    }
 149
 150    /* If no request is pending, nothing to wake up */
 151    if (priv->sme_reply.request_status != SME_REQUEST_PENDING) {
 152        unifi_trace(priv, UDBG5,
 153                    "sme_cancel_request: no request was pending (s:%d)\n",
 154                    priv->sme_reply.request_status);
 155        /* Nothing to do */
 156        return;
 157    }
 158    unifi_trace(priv, UDBG5,
 159                "sme_cancel_request: request cancelled (s:%d)\n",
 160                priv->sme_reply.request_status);
 161
 162    /* Wake up the wait with an error status */
 163    priv->sme_reply.request_status = SME_REQUEST_CANCELLED;
 164    priv->sme_reply.reply_status = reply_status; /* unimportant since the CANCELLED state will fail the ioctl */
 165
 166    wake_up_interruptible(&priv->sme_request_wq);
 167
 168    return;
 169}
 170
 171
 172static int
 173_sme_wait_for_reply(unifi_priv_t *priv,
 174        unsigned long timeout, const char *func)
 175{
 176    long r;
 177
 178    unifi_trace(priv, UDBG5, "sme_wait_for_reply: %s sleep\n", func ? func : "");
 179    r = wait_event_interruptible_timeout(priv->sme_request_wq,
 180                                         (priv->sme_reply.request_status != SME_REQUEST_PENDING),
 181                                         msecs_to_jiffies(timeout));
 182    unifi_trace(priv, UDBG5, "sme_wait_for_reply: %s awake (%d)\n", func ? func : "", r);
 183
 184    if (r == -ERESTARTSYS) {
 185        /* The thread was killed */
 186        unifi_info(priv, "ERESTARTSYS in _sme_wait_for_reply\n");
 187        up(&priv->sme_sem);
 188        return r;
 189    }
 190    if (priv->sme_reply.request_status == SME_REQUEST_CANCELLED) {
 191        unifi_trace(priv, UDBG5, "Cancelled waiting for SME to reply (%s s:%d, t:%d, r:%d)\n",
 192                    (func ? func : ""), priv->sme_reply.request_status, timeout, r);
 193
 194        /* Release the SME semaphore that was downed in sme_init_request() */
 195        up(&priv->sme_sem);
 196        return -EIO; /* fail the ioctl */
 197    }
 198    if ((r == 0) && (priv->sme_reply.request_status != SME_REQUEST_RECEIVED)) {
 199        unifi_notice(priv, "Timeout waiting for SME to reply (%s s:%d, t:%d)\n",
 200                     (func ? func : ""), priv->sme_reply.request_status, timeout);
 201
 202        priv->sme_reply.request_status = SME_REQUEST_TIMEDOUT;
 203
 204        /* Release the SME semaphore that was downed in sme_init_request() */
 205        up(&priv->sme_sem);
 206
 207        return -ETIMEDOUT;
 208    }
 209
 210    unifi_trace(priv, UDBG5, "sme_wait_for_reply: %s received (%d)\n",
 211                func ? func : "", r);
 212
 213    /* Release the SME semaphore that was downed in sme_init_request() */
 214    up(&priv->sme_sem);
 215
 216    return 0;
 217} /* sme_wait_for_reply() */
 218
 219
 220
 221
 222#ifdef CSR_SUPPORT_WEXT
 223int sme_mgt_wifi_on(unifi_priv_t *priv)
 224{
 225    u16 numElements;
 226    CsrWifiSmeDataBlock* dataList;
 227#ifdef CSR_SUPPORT_WEXT_AP
 228    int r;
 229#endif
 230
 231    if (priv->smepriv == NULL) {
 232        unifi_error(priv, "sme_mgt_wifi_on: invalid smepriv\n");
 233        return -EIO;
 234    }
 235
 236    if (priv->mib_data.length) {
 237        numElements = 1;
 238        dataList = &priv->mib_data;
 239    } else {
 240        numElements = 0;
 241        dataList = NULL;
 242    }
 243    /* Start the SME */
 244#ifdef CSR_SUPPORT_WEXT_AP
 245    r = sme_init_request(priv);
 246    if (r) {
 247        return -EIO;
 248    }
 249#endif
 250    CsrWifiSmeWifiOnReqSend(0, priv->sta_mac_address, numElements, dataList);
 251#ifdef CSR_SUPPORT_WEXT_AP
 252    r = sme_wait_for_reply(priv, UNIFI_SME_MGT_LONG_TIMEOUT);
 253    unifi_trace(priv, UDBG4,
 254                "sme_mgt_wifi_on: unifi_mgt_wifi_oo_req <-- (r=%d, status=%d)\n",
 255                r, priv->sme_reply.reply_status);
 256    return convert_sme_error(priv->sme_reply.reply_status);
 257#else
 258    return 0;
 259#endif
 260} /* sme_mgt_wifi_on() */
 261
 262
 263int sme_mgt_wifi_off(unifi_priv_t *priv)
 264{
 265    int r;
 266
 267    if (priv->smepriv == NULL) {
 268        unifi_error(priv, "sme_mgt_wifi_off: invalid smepriv\n");
 269        return -EIO;
 270    }
 271
 272    r = sme_init_request(priv);
 273    if (r)
 274        return -EIO;
 275
 276    /* Stop the SME */
 277    CsrWifiSmeWifiOffReqSend(0);
 278
 279    r = sme_wait_for_reply(priv, UNIFI_SME_MGT_LONG_TIMEOUT);
 280    if (r)
 281        return r;
 282
 283    unifi_trace(priv, UDBG4,
 284                "sme_mgt_wifi_off: unifi_mgt_wifi_off_req <-- (r=%d, status=%d)\n",
 285                r, priv->sme_reply.reply_status);
 286    return convert_sme_error(priv->sme_reply.reply_status);
 287
 288} /* sme_mgt_wifi_off */
 289
 290int sme_mgt_key(unifi_priv_t *priv, CsrWifiSmeKey *sme_key,
 291        CsrWifiSmeListAction action)
 292{
 293    int r;
 294
 295    if (priv->smepriv == NULL) {
 296        unifi_error(priv, "sme_mgt_key: invalid smepriv\n");
 297        return -EIO;
 298    }
 299
 300    r = sme_init_request(priv);
 301    if (r)
 302        return -EIO;
 303
 304    CsrWifiSmeKeyReqSend(0, CSR_WIFI_INTERFACE_IN_USE, action, *sme_key);
 305
 306    r = sme_wait_for_reply(priv, UNIFI_SME_MGT_SHORT_TIMEOUT);
 307    if (r)
 308        return r;
 309
 310    return convert_sme_error(priv->sme_reply.reply_status);
 311}
 312
 313
 314int sme_mgt_scan_full(unifi_priv_t *priv,
 315        CsrWifiSsid *specific_ssid,
 316        int num_channels,
 317        unsigned char *channel_list)
 318{
 319    CsrWifiMacAddress bcastAddress = {{0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }};
 320    u8 is_active = (num_channels > 0) ? TRUE : FALSE;
 321    int r;
 322
 323    if (priv->smepriv == NULL) {
 324        unifi_error(priv, "sme_mgt_scan_full: invalid smepriv\n");
 325        return -EIO;
 326    }
 327
 328    unifi_trace(priv, UDBG4, "sme_mgt_scan_full: -->\n");
 329
 330    r = sme_init_request(priv);
 331    if (r)
 332        return -EIO;
 333
 334    /* If a channel list is provided, do an active scan */
 335    if (is_active) {
 336        unifi_trace(priv, UDBG1,
 337                    "channel list - num_channels: %d, active scan\n",
 338                    num_channels);
 339    }
 340
 341    CsrWifiSmeScanFullReqSend(0,
 342                              specific_ssid->length?1:0, /* 0 or 1 SSIDS */
 343                              specific_ssid,
 344                              bcastAddress,
 345                              is_active,
 346                              CSR_WIFI_SME_BSS_TYPE_ANY_BSS,
 347                              CSR_WIFI_SME_SCAN_TYPE_ALL,
 348                              (u16)num_channels, channel_list,
 349                              0, NULL);
 350
 351    r = sme_wait_for_reply(priv, UNIFI_SME_MGT_LONG_TIMEOUT);
 352    if (r)
 353        return r;
 354
 355    unifi_trace(priv, UDBG4, "sme_mgt_scan_full: <-- (status=%d)\n", priv->sme_reply.reply_status);
 356    if (priv->sme_reply.reply_status == CSR_WIFI_RESULT_UNAVAILABLE)
 357        return 0; /* initial scan already underway */
 358    else
 359        return convert_sme_error(priv->sme_reply.reply_status);
 360}
 361
 362
 363int sme_mgt_scan_results_get_async(unifi_priv_t *priv,
 364        struct iw_request_info *info,
 365        char *scan_results,
 366        long scan_results_len)
 367{
 368    u16 scan_result_list_count;
 369    CsrWifiSmeScanResult *scan_result_list;
 370    CsrWifiSmeScanResult *scan_result;
 371    int r;
 372    int i;
 373    char *current_ev = scan_results;
 374
 375    if (priv->smepriv == NULL) {
 376        unifi_error(priv, "sme_mgt_scan_results_get_async: invalid smepriv\n");
 377        return -EIO;
 378    }
 379
 380    r = sme_init_request(priv);
 381    if (r)
 382        return -EIO;
 383
 384    CsrWifiSmeScanResultsGetReqSend(0);
 385    r = sme_wait_for_reply(priv, UNIFI_SME_MGT_LONG_TIMEOUT);
 386    if (r)
 387        return r;
 388
 389    scan_result_list_count = priv->sme_reply.reply_scan_results_count;
 390    scan_result_list = priv->sme_reply.reply_scan_results;
 391    unifi_trace(priv, UDBG2,
 392                "scan_results: Scan returned %d, numElements=%d\n",
 393                r, scan_result_list_count);
 394
 395    /* OK, now we have the scan results */
 396    for (i = 0; i < scan_result_list_count; ++i) {
 397        scan_result = &scan_result_list[i];
 398
 399        unifi_trace(priv, UDBG2, "Scan Result: %.*s\n",
 400                    scan_result->ssid.length,
 401                    scan_result->ssid.ssid);
 402
 403        r = unifi_translate_scan(priv->netdev[0], info,
 404                                 current_ev,
 405                                 scan_results + scan_results_len,
 406                                 scan_result, i+1);
 407
 408        if (r < 0) {
 409            kfree(scan_result_list);
 410            priv->sme_reply.reply_scan_results_count = 0;
 411            priv->sme_reply.reply_scan_results = NULL;
 412            return r;
 413        }
 414
 415        current_ev += r;
 416    }
 417
 418    /*
 419     * Free the scan results allocated in unifi_mgt_scan_results_get_cfm()
 420     * and invalidate the reply_scan_results to avoid re-using
 421     * the freed pointers.
 422     */
 423    kfree(scan_result_list);
 424    priv->sme_reply.reply_scan_results_count = 0;
 425    priv->sme_reply.reply_scan_results = NULL;
 426
 427    unifi_trace(priv, UDBG2,
 428                "scan_results: Scan translated to %d bytes\n",
 429                current_ev - scan_results);
 430    return (current_ev - scan_results);
 431}
 432
 433
 434int sme_mgt_connect(unifi_priv_t *priv)
 435{
 436    int r;
 437
 438    if (priv->smepriv == NULL) {
 439        unifi_error(priv, "sme_mgt_connect: invalid smepriv\n");
 440        return -EIO;
 441    }
 442
 443    unifi_trace(priv, UDBG2, "sme_mgt_connect: %.*s\n",
 444                priv->connection_config.ssid.length,
 445                priv->connection_config.ssid.ssid);
 446
 447    r = sme_init_request(priv);
 448    if (r)
 449        return -EIO;
 450
 451    CsrWifiSmeConnectReqSend(0, CSR_WIFI_INTERFACE_IN_USE, priv->connection_config);
 452    r = sme_wait_for_reply(priv, UNIFI_SME_MGT_SHORT_TIMEOUT);
 453    if (r)
 454        return r;
 455
 456    if (priv->sme_reply.reply_status)
 457        unifi_trace(priv, UDBG1, "sme_mgt_connect: failed with SME status %d\n",
 458                    priv->sme_reply.reply_status);
 459
 460    return convert_sme_error(priv->sme_reply.reply_status);
 461}
 462
 463
 464int sme_mgt_disconnect(unifi_priv_t *priv)
 465{
 466    int r;
 467
 468    if (priv->smepriv == NULL) {
 469        unifi_error(priv, "sme_mgt_disconnect: invalid smepriv\n");
 470        return -EIO;
 471    }
 472
 473    r = sme_init_request(priv);
 474    if (r)
 475        return -EIO;
 476
 477    CsrWifiSmeDisconnectReqSend(0, CSR_WIFI_INTERFACE_IN_USE);
 478    r = sme_wait_for_reply(priv, UNIFI_SME_MGT_SHORT_TIMEOUT);
 479    if (r)
 480        return r;
 481
 482    unifi_trace(priv, UDBG4, "sme_mgt_disconnect: <-- (status=%d)\n", priv->sme_reply.reply_status);
 483    return convert_sme_error(priv->sme_reply.reply_status);
 484}
 485
 486
 487int sme_mgt_pmkid(unifi_priv_t *priv,
 488        CsrWifiSmeListAction action,
 489        CsrWifiSmePmkidList *pmkid_list)
 490{
 491    int r;
 492
 493    if (priv->smepriv == NULL) {
 494        unifi_error(priv, "sme_mgt_pmkid: invalid smepriv\n");
 495        return -EIO;
 496    }
 497
 498    r = sme_init_request(priv);
 499    if (r)
 500        return -EIO;
 501
 502    CsrWifiSmePmkidReqSend(0, CSR_WIFI_INTERFACE_IN_USE, action,
 503                        pmkid_list->pmkidsCount, pmkid_list->pmkids);
 504    r = sme_wait_for_reply(priv, UNIFI_SME_MGT_SHORT_TIMEOUT);
 505    if (r)
 506        return r;
 507
 508    unifi_trace(priv, UDBG4, "sme_mgt_pmkid: <-- (status=%d)\n", priv->sme_reply.reply_status);
 509    return convert_sme_error(priv->sme_reply.reply_status);
 510}
 511
 512
 513int sme_mgt_mib_get(unifi_priv_t *priv,
 514        unsigned char *varbind, int *length)
 515{
 516    int r;
 517
 518    if (priv->smepriv == NULL) {
 519        unifi_error(priv, "sme_mgt_mib_get: invalid smepriv\n");
 520        return -EIO;
 521    }
 522
 523    r = sme_init_request(priv);
 524    if (r)
 525        return -EIO;
 526
 527    priv->mib_cfm_buffer = varbind;
 528    priv->mib_cfm_buffer_length = MAX_VARBIND_LENGTH;
 529
 530    CsrWifiSmeMibGetReqSend(0, *length, varbind);
 531    r = sme_wait_for_reply(priv, UNIFI_SME_MGT_SHORT_TIMEOUT);
 532    if (r) {
 533        priv->mib_cfm_buffer_length = 0;
 534        priv->mib_cfm_buffer = NULL;
 535        return r;
 536    }
 537
 538    *length = priv->mib_cfm_buffer_length;
 539
 540    priv->mib_cfm_buffer_length = 0;
 541    priv->mib_cfm_buffer = NULL;
 542    unifi_trace(priv, UDBG4, "sme_mgt_mib_get: <-- (status=%d)\n", priv->sme_reply.reply_status);
 543    return convert_sme_error(priv->sme_reply.reply_status);
 544}
 545
 546int sme_mgt_mib_set(unifi_priv_t *priv,
 547        unsigned char *varbind, int length)
 548{
 549    int r;
 550
 551    if (priv->smepriv == NULL) {
 552        unifi_error(priv, "sme_mgt_mib_get: invalid smepriv\n");
 553        return -EIO;
 554    }
 555
 556    r = sme_init_request(priv);
 557    if (r)
 558        return -EIO;
 559
 560    CsrWifiSmeMibSetReqSend(0, length, varbind);
 561    r = sme_wait_for_reply(priv, UNIFI_SME_MGT_SHORT_TIMEOUT);
 562    if (r)
 563        return r;
 564
 565    unifi_trace(priv, UDBG4, "sme_mgt_mib_set: <-- (status=%d)\n", priv->sme_reply.reply_status);
 566    return convert_sme_error(priv->sme_reply.reply_status);
 567}
 568
 569#endif /* CSR_SUPPORT_WEXT */
 570
 571int sme_mgt_power_config_set(unifi_priv_t *priv, CsrWifiSmePowerConfig *powerConfig)
 572{
 573#ifdef CSR_SME_USERSPACE
 574    int r;
 575
 576    if (priv->smepriv == NULL) {
 577        unifi_error(priv, "sme_mgt_set_value_async: invalid smepriv\n");
 578        return -EIO;
 579    }
 580
 581    r = sme_init_request(priv);
 582    if (r)
 583        return -EIO;
 584
 585    CsrWifiSmePowerConfigSetReqSend(0, *powerConfig);
 586
 587    r = sme_wait_for_reply(priv, UNIFI_SME_MGT_SHORT_TIMEOUT);
 588    if (r)
 589        return r;
 590
 591    unifi_trace(priv, UDBG4,
 592                "sme_mgt_set_value_async: unifi_mgt_set_value_req <-- (r=%d status=%d)\n",
 593                r, priv->sme_reply.reply_status);
 594    return convert_sme_error(priv->sme_reply.reply_status);
 595#else
 596    CsrResult status;
 597    if (priv->smepriv == NULL) {
 598        unifi_error(priv, "sme_mgt_set_value: invalid smepriv\n");
 599        return -EIO;
 600    }
 601    CsrWifiSmeMgtClaimSyncAccess(priv->smepriv);
 602    status = CsrWifiSmeMgtPowerConfigSetReq(priv->smepriv, *powerConfig);
 603    CsrWifiSmeMgtReleaseSyncAccess(priv->smepriv);
 604    return convert_sme_error(status);
 605#endif
 606}
 607
 608int sme_mgt_sme_config_set(unifi_priv_t *priv, CsrWifiSmeStaConfig *staConfig, CsrWifiSmeDeviceConfig *deviceConfig)
 609{
 610#ifdef CSR_SME_USERSPACE
 611    int r;
 612
 613    if (priv->smepriv == NULL) {
 614        unifi_error(priv, "sme_mgt_sme_config_set: invalid smepriv\n");
 615        return -EIO;
 616    }
 617
 618    r = sme_init_request(priv);
 619    if (r)
 620        return -EIO;
 621
 622    CsrWifiSmeSmeStaConfigSetReqSend(0, CSR_WIFI_INTERFACE_IN_USE, *staConfig);
 623    r = sme_wait_for_reply(priv, UNIFI_SME_MGT_SHORT_TIMEOUT);
 624    if (r)
 625        return r;
 626
 627    unifi_trace(priv, UDBG4,
 628                "sme_mgt_sme_config_set: CsrWifiSmeSmeStaConfigSetReq <-- (r=%d status=%d)\n",
 629                r, priv->sme_reply.reply_status);
 630
 631    r = sme_init_request(priv);
 632    if (r)
 633        return -EIO;
 634
 635    CsrWifiSmeSmeCommonConfigSetReqSend(0, *deviceConfig);
 636    r = sme_wait_for_reply(priv, UNIFI_SME_MGT_SHORT_TIMEOUT);
 637    if (r)
 638        return r;
 639
 640    unifi_trace(priv, UDBG4,
 641                "sme_mgt_sme_config_set: CsrWifiSmeSmeCommonConfigSetReq <-- (r=%d status=%d)\n",
 642                r, priv->sme_reply.reply_status);
 643
 644    return convert_sme_error(priv->sme_reply.reply_status);
 645#else
 646    CsrResult status;
 647    if (priv->smepriv == NULL) {
 648        unifi_error(priv, "sme_mgt_sme_config_set: invalid smepriv\n");
 649        return -EIO;
 650    }
 651    CsrWifiSmeMgtClaimSyncAccess(priv->smepriv);
 652    status = CsrWifiSmeMgtSmeConfigSetReq(priv->smepriv, *staConfig);
 653    status = CsrWifiSmeMgtDeviceConfigSetReq(priv->smepriv, *deviceConfig);
 654    CsrWifiSmeMgtReleaseSyncAccess(priv->smepriv);
 655    return convert_sme_error(status);
 656#endif
 657}
 658
 659#ifdef CSR_SUPPORT_WEXT
 660
 661int sme_mgt_mib_config_set(unifi_priv_t *priv, CsrWifiSmeMibConfig *mibConfig)
 662{
 663#ifdef CSR_SME_USERSPACE
 664    int r;
 665
 666    if (priv->smepriv == NULL) {
 667        unifi_error(priv, "sme_mgt_mib_config_set: invalid smepriv\n");
 668        return -EIO;
 669    }
 670
 671    r = sme_init_request(priv);
 672    if (r)
 673        return -EIO;
 674
 675    CsrWifiSmeMibConfigSetReqSend(0, *mibConfig);
 676
 677    r = sme_wait_for_reply(priv, UNIFI_SME_MGT_SHORT_TIMEOUT);
 678    if (r)
 679        return r;
 680
 681    unifi_trace(priv, UDBG4,
 682                "sme_mgt_mib_config_set: unifi_mgt_set_mib_config_req <-- (r=%d status=%d)\n",
 683                r, priv->sme_reply.reply_status);
 684    return convert_sme_error(priv->sme_reply.reply_status);
 685#else
 686    CsrResult status;
 687    if (priv->smepriv == NULL) {
 688        unifi_error(priv, "sme_mgt_mib_config_set: invalid smepriv\n");
 689        return -EIO;
 690    }
 691    CsrWifiSmeMgtClaimSyncAccess(priv->smepriv);
 692    status = CsrWifiSmeMgtMibConfigSetReq(priv->smepriv, *mibConfig);
 693    CsrWifiSmeMgtReleaseSyncAccess(priv->smepriv);
 694    return convert_sme_error(status);
 695#endif
 696}
 697
 698int sme_mgt_coex_config_set(unifi_priv_t *priv, CsrWifiSmeCoexConfig *coexConfig)
 699{
 700#ifdef CSR_SME_USERSPACE
 701    int r;
 702
 703    if (priv->smepriv == NULL) {
 704        unifi_error(priv, "sme_mgt_coex_config_set: invalid smepriv\n");
 705        return -EIO;
 706    }
 707
 708    r = sme_init_request(priv);
 709    if (r)
 710        return -EIO;
 711
 712    CsrWifiSmeCoexConfigSetReqSend(0, *coexConfig);
 713
 714    r = sme_wait_for_reply(priv, UNIFI_SME_MGT_SHORT_TIMEOUT);
 715    if (r)
 716        return r;
 717
 718    unifi_trace(priv, UDBG4,
 719                "sme_mgt_coex_config_set: unifi_mgt_set_mib_config_req <-- (r=%d status=%d)\n",
 720                r, priv->sme_reply.reply_status);
 721    return convert_sme_error(priv->sme_reply.reply_status);
 722#else
 723    CsrResult status;
 724    if (priv->smepriv == NULL) {
 725        unifi_error(priv, "sme_mgt_coex_config_set: invalid smepriv\n");
 726        return -EIO;
 727    }
 728    CsrWifiSmeMgtClaimSyncAccess(priv->smepriv);
 729    status = CsrWifiSmeMgtCoexConfigSetReq(priv->smepriv, *coexConfig);
 730    CsrWifiSmeMgtReleaseSyncAccess(priv->smepriv);
 731    return convert_sme_error(status);
 732#endif
 733}
 734
 735#endif /* CSR_SUPPORT_WEXT */
 736
 737int sme_mgt_host_config_set(unifi_priv_t *priv, CsrWifiSmeHostConfig *hostConfig)
 738{
 739#ifdef CSR_SME_USERSPACE
 740    int r;
 741
 742    if (priv->smepriv == NULL) {
 743        unifi_error(priv, "sme_mgt_host_config_set: invalid smepriv\n");
 744        return -EIO;
 745    }
 746
 747    r = sme_init_request(priv);
 748    if (r)
 749        return -EIO;
 750
 751    CsrWifiSmeHostConfigSetReqSend(0, CSR_WIFI_INTERFACE_IN_USE, *hostConfig);
 752
 753    r = sme_wait_for_reply(priv, UNIFI_SME_MGT_SHORT_TIMEOUT);
 754    if (r)
 755        return r;
 756
 757    unifi_trace(priv, UDBG4,
 758                "sme_mgt_host_config_set: unifi_mgt_set_host_config_req <-- (r=%d status=%d)\n",
 759                r, priv->sme_reply.reply_status);
 760    return convert_sme_error(priv->sme_reply.reply_status);
 761#else
 762    CsrResult status;
 763    if (priv->smepriv == NULL) {
 764        unifi_error(priv, "sme_mgt_host_config_set: invalid smepriv\n");
 765        return -EIO;
 766    }
 767    CsrWifiSmeMgtClaimSyncAccess(priv->smepriv);
 768    status = CsrWifiSmeMgtHostConfigSetReq(priv->smepriv, *hostConfig);
 769    CsrWifiSmeMgtReleaseSyncAccess(priv->smepriv);
 770    return convert_sme_error(status);
 771#endif
 772}
 773
 774#ifdef CSR_SUPPORT_WEXT
 775
 776int sme_mgt_versions_get(unifi_priv_t *priv, CsrWifiSmeVersions *versions)
 777{
 778#ifdef CSR_SME_USERSPACE
 779    int r;
 780
 781    if (priv->smepriv == NULL) {
 782        unifi_error(priv, "sme_mgt_versions_get: invalid smepriv\n");
 783        return -EIO;
 784    }
 785
 786    unifi_trace(priv, UDBG4, "sme_mgt_versions_get: unifi_mgt_versions_get_req -->\n");
 787    r = sme_init_request(priv);
 788    if (r)
 789        return -EIO;
 790
 791    CsrWifiSmeVersionsGetReqSend(0);
 792
 793    r = sme_wait_for_reply(priv, UNIFI_SME_MGT_SHORT_TIMEOUT);
 794    if (r)
 795        return r;
 796
 797    /* store the reply */
 798    if (versions != NULL) {
 799        memcpy((unsigned char*)versions,
 800               (unsigned char*)&priv->sme_reply.versions,
 801               sizeof(CsrWifiSmeVersions));
 802    }
 803
 804    unifi_trace(priv, UDBG4,
 805                "sme_mgt_versions_get: unifi_mgt_versions_get_req <-- (r=%d status=%d)\n",
 806                r, priv->sme_reply.reply_status);
 807
 808    return convert_sme_error(priv->sme_reply.reply_status);
 809#else
 810    CsrResult status;
 811    CsrWifiSmeMgtClaimSyncAccess(priv->smepriv);
 812    status = CsrWifiSmeMgtVersionsGetReq(priv->smepriv, versions);
 813    CsrWifiSmeMgtReleaseSyncAccess(priv->smepriv);
 814    return convert_sme_error(status);
 815#endif
 816}
 817
 818#endif /* CSR_SUPPORT_WEXT */
 819
 820int sme_mgt_power_config_get(unifi_priv_t *priv, CsrWifiSmePowerConfig *powerConfig)
 821{
 822#ifdef CSR_SME_USERSPACE
 823    int r;
 824
 825    if (priv->smepriv == NULL) {
 826        unifi_error(priv, "sme_mgt_power_config_get: invalid smepriv\n");
 827        return -EIO;
 828    }
 829
 830    unifi_trace(priv, UDBG4, "sme_mgt_power_config_get: unifi_mgt_power_config_req -->\n");
 831    r = sme_init_request(priv);
 832    if (r)
 833        return -EIO;
 834
 835    CsrWifiSmePowerConfigGetReqSend(0);
 836
 837    r = sme_wait_for_reply(priv, UNIFI_SME_MGT_SHORT_TIMEOUT);
 838    if (r)
 839        return r;
 840
 841    /* store the reply */
 842    if (powerConfig != NULL) {
 843        memcpy((unsigned char*)powerConfig,
 844               (unsigned char*)&priv->sme_reply.powerConfig,
 845               sizeof(CsrWifiSmePowerConfig));
 846    }
 847
 848    unifi_trace(priv, UDBG4,
 849                "sme_mgt_get_versions: unifi_mgt_power_config_req <-- (r=%d status=%d)\n",
 850                r, priv->sme_reply.reply_status);
 851
 852    return convert_sme_error(priv->sme_reply.reply_status);
 853#else
 854    CsrResult status;
 855    CsrWifiSmeMgtClaimSyncAccess(priv->smepriv);
 856    status = CsrWifiSmeMgtPowerConfigGetReq(priv->smepriv, powerConfig);
 857    CsrWifiSmeMgtReleaseSyncAccess(priv->smepriv);
 858    return convert_sme_error(status);
 859#endif
 860}
 861
 862int sme_mgt_host_config_get(unifi_priv_t *priv, CsrWifiSmeHostConfig *hostConfig)
 863{
 864#ifdef CSR_SME_USERSPACE
 865    int r;
 866
 867    if (priv->smepriv == NULL) {
 868        unifi_error(priv, "sme_mgt_host_config_get: invalid smepriv\n");
 869        return -EIO;
 870    }
 871
 872    unifi_trace(priv, UDBG4, "sme_mgt_host_config_get: unifi_mgt_host_config_get_req -->\n");
 873    r = sme_init_request(priv);
 874    if (r)
 875        return -EIO;
 876
 877    CsrWifiSmeHostConfigGetReqSend(0, CSR_WIFI_INTERFACE_IN_USE);
 878
 879    r = sme_wait_for_reply(priv, UNIFI_SME_MGT_SHORT_TIMEOUT);
 880    if (r)
 881        return r;
 882
 883    /* store the reply */
 884    if (hostConfig != NULL)
 885        memcpy((unsigned char*)hostConfig,
 886               (unsigned char*)&priv->sme_reply.hostConfig,
 887               sizeof(CsrWifiSmeHostConfig));
 888
 889    unifi_trace(priv, UDBG4,
 890                "sme_mgt_host_config_get: unifi_mgt_host_config_get_req <-- (r=%d status=%d)\n",
 891                r, priv->sme_reply.reply_status);
 892
 893    return convert_sme_error(priv->sme_reply.reply_status);
 894#else
 895    CsrResult status;
 896    CsrWifiSmeMgtClaimSyncAccess(priv->smepriv);
 897    status = CsrWifiSmeMgtHostConfigGetReq(priv->smepriv, hostConfig);
 898    CsrWifiSmeMgtReleaseSyncAccess(priv->smepriv);
 899    return convert_sme_error(status);
 900#endif
 901}
 902
 903int sme_mgt_sme_config_get(unifi_priv_t *priv, CsrWifiSmeStaConfig *staConfig, CsrWifiSmeDeviceConfig *deviceConfig)
 904{
 905#ifdef CSR_SME_USERSPACE
 906    int r;
 907
 908    if (priv->smepriv == NULL) {
 909        unifi_error(priv, "sme_mgt_sme_config_get: invalid smepriv\n");
 910        return -EIO;
 911    }
 912
 913    unifi_trace(priv, UDBG4, "sme_mgt_sme_config_get: unifi_mgt_sme_config_get_req -->\n");
 914
 915    /* Common device config */
 916    r = sme_init_request(priv);
 917    if (r)
 918        return -EIO;
 919
 920    CsrWifiSmeSmeCommonConfigGetReqSend(0);
 921    r = sme_wait_for_reply(priv, UNIFI_SME_MGT_SHORT_TIMEOUT);
 922    if (r)
 923        return r;
 924
 925    /* store the reply */
 926    if (deviceConfig != NULL)
 927        memcpy((unsigned char*)deviceConfig,
 928               (unsigned char*)&priv->sme_reply.deviceConfig,
 929               sizeof(CsrWifiSmeDeviceConfig));
 930
 931    /* STA config */
 932    r = sme_init_request(priv);
 933    if (r)
 934        return -EIO;
 935
 936    CsrWifiSmeSmeStaConfigGetReqSend(0, CSR_WIFI_INTERFACE_IN_USE);
 937    r = sme_wait_for_reply(priv, UNIFI_SME_MGT_SHORT_TIMEOUT);
 938    if (r)
 939        return r;
 940
 941    /* store the reply */
 942    if (staConfig != NULL)
 943        memcpy((unsigned char*)staConfig,
 944               (unsigned char*)&priv->sme_reply.staConfig,
 945               sizeof(CsrWifiSmeStaConfig));
 946
 947    unifi_trace(priv, UDBG4,
 948                "sme_mgt_sme_config_get: unifi_mgt_sme_config_get_req <-- (r=%d status=%d)\n",
 949                r, priv->sme_reply.reply_status);
 950
 951    return convert_sme_error(priv->sme_reply.reply_status);
 952#else
 953    CsrResult status;
 954    CsrWifiSmeMgtClaimSyncAccess(priv->smepriv);
 955    status = CsrWifiSmeMgtSmeConfigGetReq(priv->smepriv, staConfig);
 956    status = CsrWifiSmeMgtDeviceConfigGetReq(priv->smepriv, deviceConfig);
 957    CsrWifiSmeMgtReleaseSyncAccess(priv->smepriv);
 958    return convert_sme_error(status);
 959#endif
 960}
 961
 962int sme_mgt_coex_info_get(unifi_priv_t *priv, CsrWifiSmeCoexInfo *coexInfo)
 963{
 964#ifdef CSR_SME_USERSPACE
 965    int r;
 966
 967    if (priv->smepriv == NULL) {
 968        unifi_error(priv, "sme_mgt_coex_info_get: invalid smepriv\n");
 969        return -EIO;
 970    }
 971
 972    unifi_trace(priv, UDBG4, "sme_mgt_coex_info_get: unifi_mgt_coex_info_get_req -->\n");
 973    r = sme_init_request(priv);
 974    if (r)
 975        return -EIO;
 976
 977    CsrWifiSmeCoexInfoGetReqSend(0);
 978
 979    r = sme_wait_for_reply(priv, UNIFI_SME_MGT_SHORT_TIMEOUT);
 980    if (r)
 981        return r;
 982
 983    /* store the reply */
 984    if (coexInfo != NULL)
 985        memcpy((unsigned char*)coexInfo,
 986               (unsigned char*)&priv->sme_reply.coexInfo,
 987               sizeof(CsrWifiSmeCoexInfo));
 988
 989    unifi_trace(priv, UDBG4,
 990                "sme_mgt_coex_info_get: unifi_mgt_coex_info_get_req <-- (r=%d status=%d)\n",
 991                r, priv->sme_reply.reply_status);
 992
 993    return convert_sme_error(priv->sme_reply.reply_status);
 994#else
 995    CsrResult status;
 996    CsrWifiSmeMgtClaimSyncAccess(priv->smepriv);
 997    status = CsrWifiSmeMgtCoexInfoGetReq(priv->smepriv, coexInfo);
 998    CsrWifiSmeMgtReleaseSyncAccess(priv->smepriv);
 999    return convert_sme_error(status);
1000#endif
1001}
1002
1003#ifdef CSR_SUPPORT_WEXT
1004
1005int sme_mgt_coex_config_get(unifi_priv_t *priv, CsrWifiSmeCoexConfig *coexConfig)
1006{
1007#ifdef CSR_SME_USERSPACE
1008    int r;
1009
1010    if (priv->smepriv == NULL) {
1011        unifi_error(priv, "sme_mgt_coex_config_get: invalid smepriv\n");
1012        return -EIO;
1013    }
1014
1015    unifi_trace(priv, UDBG4, "sme_mgt_coex_config_get: unifi_mgt_coex_config_get_req -->\n");
1016    r = sme_init_request(priv);
1017    if (r)
1018        return -EIO;
1019
1020    CsrWifiSmeCoexConfigGetReqSend(0);
1021
1022    r = sme_wait_for_reply(priv, UNIFI_SME_MGT_SHORT_TIMEOUT);
1023    if (r)
1024        return r;
1025
1026    /* store the reply */
1027    if (coexConfig != NULL)
1028        memcpy((unsigned char*)coexConfig,
1029               (unsigned char*)&priv->sme_reply.coexConfig,
1030               sizeof(CsrWifiSmeCoexConfig));
1031
1032    unifi_trace(priv, UDBG4,
1033                "sme_mgt_coex_config_get: unifi_mgt_coex_config_get_req <-- (r=%d status=%d)\n",
1034                r, priv->sme_reply.reply_status);
1035
1036    return convert_sme_error(priv->sme_reply.reply_status);
1037#else
1038    CsrResult status;
1039    CsrWifiSmeMgtClaimSyncAccess(priv->smepriv);
1040    status = CsrWifiSmeMgtCoexConfigGetReq(priv->smepriv, coexConfig);
1041    CsrWifiSmeMgtReleaseSyncAccess(priv->smepriv);
1042    return convert_sme_error(status);
1043#endif
1044}
1045
1046int sme_mgt_mib_config_get(unifi_priv_t *priv, CsrWifiSmeMibConfig *mibConfig)
1047{
1048#ifdef CSR_SME_USERSPACE
1049    int r;
1050
1051    if (priv->smepriv == NULL) {
1052        unifi_error(priv, "sme_mgt_mib_config_get: invalid smepriv\n");
1053        return -EIO;
1054    }
1055
1056    unifi_trace(priv, UDBG4, "sme_mgt_mib_config_get: unifi_mgt_mib_config_get_req -->\n");
1057    r = sme_init_request(priv);
1058    if (r)
1059        return -EIO;
1060
1061    CsrWifiSmeMibConfigGetReqSend(0);
1062
1063    r = sme_wait_for_reply(priv, UNIFI_SME_MGT_SHORT_TIMEOUT);
1064    if (r)
1065        return r;
1066
1067    /* store the reply */
1068    if (mibConfig != NULL)
1069        memcpy((unsigned char*)mibConfig,
1070               (unsigned char*)&priv->sme_reply.mibConfig,
1071               sizeof(CsrWifiSmeMibConfig));
1072
1073    unifi_trace(priv, UDBG4,
1074                "sme_mgt_mib_config_get: unifi_mgt_mib_config_get_req <-- (r=%d status=%d)\n",
1075                r, priv->sme_reply.reply_status);
1076
1077    return convert_sme_error(priv->sme_reply.reply_status);
1078#else
1079    CsrResult status;
1080    CsrWifiSmeMgtClaimSyncAccess(priv->smepriv);
1081    status = CsrWifiSmeMgtMibConfigGetReq(priv->smepriv, mibConfig);
1082    CsrWifiSmeMgtReleaseSyncAccess(priv->smepriv);
1083    return convert_sme_error(status);
1084#endif
1085}
1086
1087int sme_mgt_connection_info_get(unifi_priv_t *priv, CsrWifiSmeConnectionInfo *connectionInfo)
1088{
1089#ifdef CSR_SME_USERSPACE
1090    int r;
1091
1092    if (priv->smepriv == NULL) {
1093        unifi_error(priv, "sme_mgt_connection_info_get: invalid smepriv\n");
1094        return -EIO;
1095    }
1096
1097    unifi_trace(priv, UDBG4, "sme_mgt_connection_info_get: unifi_mgt_connection_info_get_req -->\n");
1098    r = sme_init_request(priv);
1099    if (r)
1100        return -EIO;
1101
1102    CsrWifiSmeConnectionInfoGetReqSend(0, CSR_WIFI_INTERFACE_IN_USE);
1103
1104    r = sme_wait_for_reply(priv, UNIFI_SME_MGT_SHORT_TIMEOUT);
1105    if (r)
1106        return r;
1107
1108    /* store the reply */
1109    if (connectionInfo != NULL)
1110        memcpy((unsigned char*)connectionInfo,
1111               (unsigned char*)&priv->sme_reply.connectionInfo,
1112               sizeof(CsrWifiSmeConnectionInfo));
1113
1114    unifi_trace(priv, UDBG4,
1115                "sme_mgt_connection_info_get: unifi_mgt_connection_info_get_req <-- (r=%d status=%d)\n",
1116                r, priv->sme_reply.reply_status);
1117
1118    return convert_sme_error(priv->sme_reply.reply_status);
1119#else
1120    CsrResult status;
1121    CsrWifiSmeMgtClaimSyncAccess(priv->smepriv);
1122    status = CsrWifiSmeMgtConnectionInfoGetReq(priv->smepriv, connectionInfo);
1123    CsrWifiSmeMgtReleaseSyncAccess(priv->smepriv);
1124    return convert_sme_error(status);
1125#endif
1126}
1127
1128int sme_mgt_connection_config_get(unifi_priv_t *priv, CsrWifiSmeConnectionConfig *connectionConfig)
1129{
1130#ifdef CSR_SME_USERSPACE
1131    int r;
1132
1133    if (priv->smepriv == NULL) {
1134        unifi_error(priv, "sme_mgt_connection_config_get: invalid smepriv\n");
1135        return -EIO;
1136    }
1137
1138    unifi_trace(priv, UDBG4, "sme_mgt_connection_config_get: unifi_mgt_connection_config_get_req -->\n");
1139    r = sme_init_request(priv);
1140    if (r)
1141        return -EIO;
1142
1143    CsrWifiSmeConnectionConfigGetReqSend(0, CSR_WIFI_INTERFACE_IN_USE);
1144
1145    r = sme_wait_for_reply(priv, UNIFI_SME_MGT_SHORT_TIMEOUT);
1146    if (r)
1147        return r;
1148
1149    /* store the reply */
1150    if (connectionConfig != NULL)
1151        memcpy((unsigned char*)connectionConfig,
1152               (unsigned char*)&priv->sme_reply.connectionConfig,
1153               sizeof(CsrWifiSmeConnectionConfig));
1154
1155    unifi_trace(priv, UDBG4,
1156                "sme_mgt_connection_config_get: unifi_mgt_connection_config_get_req <-- (r=%d status=%d)\n",
1157                r, priv->sme_reply.reply_status);
1158
1159    return convert_sme_error(priv->sme_reply.reply_status);
1160#else
1161    CsrResult status;
1162    CsrWifiSmeMgtClaimSyncAccess(priv->smepriv);
1163    status = CsrWifiSmeMgtConnectionConfigGetReq(priv->smepriv, connectionConfig);
1164    CsrWifiSmeMgtReleaseSyncAccess(priv->smepriv);
1165    return convert_sme_error(status);
1166#endif
1167}
1168
1169int sme_mgt_connection_stats_get(unifi_priv_t *priv, CsrWifiSmeConnectionStats *connectionStats)
1170{
1171#ifdef CSR_SME_USERSPACE
1172    int r;
1173
1174    if (priv->smepriv == NULL) {
1175        unifi_error(priv, "sme_mgt_connection_stats_get: invalid smepriv\n");
1176        return -EIO;
1177    }
1178
1179    unifi_trace(priv, UDBG4, "sme_mgt_connection_stats_get: unifi_mgt_connection_stats_get_req -->\n");
1180    r = sme_init_request(priv);
1181    if (r)
1182        return -EIO;
1183
1184    CsrWifiSmeConnectionStatsGetReqSend(0, CSR_WIFI_INTERFACE_IN_USE);
1185
1186    r = sme_wait_for_reply(priv, UNIFI_SME_MGT_SHORT_TIMEOUT);
1187    if (r)
1188        return r;
1189
1190    /* store the reply */
1191    if (connectionStats != NULL)
1192        memcpy((unsigned char*)connectionStats,
1193               (unsigned char*)&priv->sme_reply.connectionStats,
1194               sizeof(CsrWifiSmeConnectionStats));
1195
1196    unifi_trace(priv, UDBG4,
1197                "sme_mgt_connection_stats_get: unifi_mgt_connection_stats_get_req <-- (r=%d status=%d)\n",
1198                r, priv->sme_reply.reply_status);
1199
1200    return convert_sme_error(priv->sme_reply.reply_status);
1201#else
1202    CsrResult status;
1203    CsrWifiSmeMgtClaimSyncAccess(priv->smepriv);
1204    status = CsrWifiSmeMgtConnectionStatsGetReq(priv->smepriv, connectionStats);
1205    CsrWifiSmeMgtReleaseSyncAccess(priv->smepriv);
1206    return convert_sme_error(status);
1207#endif
1208}
1209
1210#endif /* CSR_SUPPORT_WEXT */
1211
1212int sme_mgt_packet_filter_set(unifi_priv_t *priv)
1213{
1214        CsrWifiIp4Address ipAddress = {{0xFF, 0xFF, 0xFF, 0xFF }};
1215        if (priv->smepriv == NULL) {
1216                unifi_error(priv, "sme_mgt_packet_filter_set: invalid smepriv\n");
1217                return -EIO;
1218        }
1219        if (priv->packet_filters.arp_filter) {
1220                ipAddress.a[0] = (priv->sta_ip_address      ) & 0xFF;
1221                ipAddress.a[1] = (priv->sta_ip_address >>  8) & 0xFF;
1222                ipAddress.a[2] = (priv->sta_ip_address >> 16) & 0xFF;
1223                ipAddress.a[3] = (priv->sta_ip_address >> 24) & 0xFF;
1224        }
1225
1226        unifi_trace(priv, UDBG5,
1227                "sme_mgt_packet_filter_set: IP address %d.%d.%d.%d\n",
1228                ipAddress.a[0], ipAddress.a[1],
1229                ipAddress.a[2], ipAddress.a[3]);
1230
1231        /* Doesn't block for a confirm */
1232        CsrWifiSmePacketFilterSetReqSend(0, CSR_WIFI_INTERFACE_IN_USE,
1233                                     priv->packet_filters.tclas_ies_length,
1234                                     priv->filter_tclas_ies,
1235                                     priv->packet_filters.filter_mode,
1236                                     ipAddress);
1237        return 0;
1238}
1239
1240int sme_mgt_tspec(unifi_priv_t *priv, CsrWifiSmeListAction action,
1241        u32 tid, CsrWifiSmeDataBlock *tspec, CsrWifiSmeDataBlock *tclas)
1242{
1243        int r;
1244
1245        if (priv->smepriv == NULL) {
1246                unifi_error(priv, "sme_mgt_tspec: invalid smepriv\n");
1247                return -EIO;
1248        }
1249
1250        r = sme_init_request(priv);
1251        if (r)
1252                return -EIO;
1253
1254        CsrWifiSmeTspecReqSend(0, CSR_WIFI_INTERFACE_IN_USE,
1255                              action, tid, TRUE, 0,
1256                              tspec->length, tspec->data,
1257                              tclas->length, tclas->data);
1258        r = sme_wait_for_reply(priv, UNIFI_SME_MGT_SHORT_TIMEOUT);
1259        if (r)
1260                return r;
1261
1262        unifi_trace(priv, UDBG4, "sme_mgt_tspec: <-- (status=%d)\n", priv->sme_reply.reply_status);
1263        return convert_sme_error(priv->sme_reply.reply_status);
1264}
1265
1266
1267
1268int sme_sys_suspend(unifi_priv_t *priv)
1269{
1270    int r;
1271    CsrResult csrResult;
1272
1273    if (priv->smepriv == NULL) {
1274        unifi_error(priv, "sme_sys_suspend: invalid smepriv\n");
1275        return -EIO;
1276    }
1277
1278    r = sme_init_request(priv);
1279    if (r)
1280        return -EIO;
1281
1282    /* Suspend the SME, which MAY cause it to power down UniFi */
1283    CsrWifiRouterCtrlSuspendIndSend(priv->CSR_WIFI_SME_IFACEQUEUE,0, 0, priv->wol_suspend);
1284    r = sme_wait_for_reply(priv, UNIFI_SME_SYS_LONG_TIMEOUT);
1285    if (r) {
1286        /* No reply - forcibly power down in case the request wasn't processed */
1287        unifi_notice(priv,
1288                     "suspend: SME did not reply %s, ",
1289                     (priv->ptest_mode | priv->wol_suspend) ? "leave powered" : "power off UniFi anyway\n");
1290
1291        /* Leave power on for production test, though */
1292        if (!priv->ptest_mode) {
1293            /* Put UniFi to deep sleep, in case we can not power it off */
1294            CsrSdioClaim(priv->sdio);
1295            unifi_trace(priv, UDBG1, "Force deep sleep");
1296            csrResult = unifi_force_low_power_mode(priv->card);
1297
1298            /* For WOL, the UniFi must stay powered */
1299            if (!priv->wol_suspend) {
1300                unifi_trace(priv, UDBG1, "Power off\n");
1301                CsrSdioPowerOff(priv->sdio);
1302            }
1303            CsrSdioRelease(priv->sdio);
1304        }
1305    }
1306
1307    if (priv->wol_suspend) {
1308        unifi_trace(priv, UDBG1, "UniFi left powered for WOL\n");
1309
1310        /* Remove the IRQ, which also disables the card SDIO interrupt.
1311         * Disabling the card SDIO interrupt enables the PIO WOL source.
1312         * Removal of the of the handler ensures that in both SDIO and PIO cases
1313         * the card interrupt only wakes the host. The card will be polled
1314         * after resume to handle any pending data.
1315         */
1316        if (csr_sdio_linux_remove_irq(priv->sdio)) {
1317            unifi_notice(priv, "WOL csr_sdio_linux_remove_irq failed\n");
1318        }
1319
1320        if (enable_wol == UNIFI_WOL_SDIO) {
1321            /* Because csr_sdio_linux_remove_irq() disabled the card SDIO interrupt,
1322             * it must be left enabled to wake-on-SDIO.
1323             */
1324            unifi_trace(priv, UDBG1, "Enable card SDIO interrupt for SDIO WOL\n");
1325
1326            CsrSdioClaim(priv->sdio);
1327            csrResult = CsrSdioInterruptEnable(priv->sdio);
1328            CsrSdioRelease(priv->sdio);
1329
1330            if (csrResult != CSR_RESULT_SUCCESS) {
1331                unifi_error(priv, "WOL CsrSdioInterruptEnable failed %d\n", csrResult);
1332            }
1333        } else {
1334            unifi_trace(priv, UDBG1, "Disabled card SDIO interrupt for PIO WOL\n");
1335        }
1336
1337        /* Prevent the BH thread from running during the suspend.
1338         * Upon resume, sme_sys_resume() will trigger a wifi-on, this will cause
1339         * the BH thread to be re-enabled and reinstall the ISR.
1340         */
1341        priv->bh_thread.block_thread = 1;
1342
1343        unifi_trace(priv, UDBG1, "unifi_suspend: suspended BH");
1344    }
1345
1346    /* Consider UniFi to be uninitialised */
1347    priv->init_progress = UNIFI_INIT_NONE;
1348
1349    unifi_trace(priv, UDBG1, "sme_sys_suspend: <-- (r=%d status=%d)\n", r, priv->sme_reply.reply_status);
1350    return convert_sme_error(priv->sme_reply.reply_status);
1351}
1352
1353
1354int sme_sys_resume(unifi_priv_t *priv)
1355{
1356    int r;
1357
1358    unifi_trace(priv, UDBG1, "sme_sys_resume %s\n", priv->wol_suspend ? "warm" : "");
1359
1360    if (priv->smepriv == NULL) {
1361        unifi_error(priv, "sme_sys_resume: invalid smepriv\n");
1362        return -EIO;
1363    }
1364
1365    r = sme_init_request(priv);
1366    if (r)
1367        return -EIO;
1368
1369    CsrWifiRouterCtrlResumeIndSend(priv->CSR_WIFI_SME_IFACEQUEUE,0, priv->wol_suspend);
1370
1371    r = sme_wait_for_reply(priv, UNIFI_SME_SYS_LONG_TIMEOUT);
1372    if (r)
1373        unifi_notice(priv,
1374                "resume: SME did not reply, return success anyway\n");
1375
1376    return 0;
1377}
1378
1379#ifdef CSR_SUPPORT_WEXT_AP
1380int sme_ap_stop(unifi_priv_t *priv,u16 interface_tag)
1381{
1382    int r;
1383
1384    if (priv->smepriv == NULL) {
1385        unifi_error(priv, "sme_ap_stop: invalid smepriv\n");
1386        return -EIO;
1387    }
1388
1389    r = sme_init_request(priv);
1390    if (r)
1391        return -EIO;
1392
1393    CsrWifiNmeApStopReqSend(0,interface_tag);
1394
1395    r = sme_wait_for_reply(priv, UNIFI_SME_MGT_SHORT_TIMEOUT);
1396    if (r)
1397        return r;
1398
1399    unifi_trace(priv, UDBG4,
1400                "sme_ap_stop <-- (r=%d status=%d)\n",
1401                r, priv->sme_reply.reply_status);
1402    return convert_sme_error(priv->sme_reply.reply_status);
1403
1404}
1405
1406int sme_ap_start(unifi_priv_t *priv,u16 interface_tag,
1407                 CsrWifiSmeApConfig_t * ap_config)
1408{
1409    int r;
1410    CsrWifiSmeApP2pGoConfig p2p_go_param;
1411    memset(&p2p_go_param,0,sizeof(CsrWifiSmeApP2pGoConfig));
1412
1413    if (priv->smepriv == NULL) {
1414        unifi_error(priv, "sme_ap_start: invalid smepriv\n");
1415        return -EIO;
1416    }
1417
1418    r = sme_init_request(priv);
1419    if (r)
1420        return -EIO;
1421
1422    CsrWifiNmeApStartReqSend(0,interface_tag,CSR_WIFI_AP_TYPE_LEGACY,FALSE,
1423                             ap_config->ssid,1,ap_config->channel,
1424                             ap_config->credentials,ap_config->max_connections,
1425                             p2p_go_param,FALSE);
1426
1427    r = sme_wait_for_reply(priv, UNIFI_SME_MGT_SHORT_TIMEOUT);
1428    if (r)
1429        return r;
1430
1431    unifi_trace(priv, UDBG4,
1432                "sme_ap_start <-- (r=%d status=%d)\n",
1433                r, priv->sme_reply.reply_status);
1434    return convert_sme_error(priv->sme_reply.reply_status);
1435}
1436
1437int sme_ap_config(unifi_priv_t *priv,
1438                  CsrWifiSmeApMacConfig *ap_mac_config,
1439                  CsrWifiNmeApConfig *group_security_config)
1440{
1441    int r;
1442    CsrWifiSmeApP2pGoConfig p2p_go_param;
1443    memset(&p2p_go_param,0,sizeof(CsrWifiSmeApP2pGoConfig));
1444
1445    if (priv->smepriv == NULL) {
1446        unifi_error(priv, "sme_ap_config: invalid smepriv\n");
1447        return -EIO;
1448    }
1449
1450    r = sme_init_request(priv);
1451    if (r)
1452        return -EIO;
1453
1454    CsrWifiNmeApConfigSetReqSend(0,*group_security_config,
1455                                 *ap_mac_config);
1456
1457    r = sme_wait_for_reply(priv, UNIFI_SME_MGT_SHORT_TIMEOUT);
1458        if (r)
1459                return r;
1460
1461    unifi_trace(priv, UDBG4,
1462                "sme_ap_config <-- (r=%d status=%d)\n",
1463                r, priv->sme_reply.reply_status);
1464    return convert_sme_error(priv->sme_reply.reply_status);
1465}
1466#endif
1467