From 635d2b00e5070378e7bf812acf47fb135c6ab928 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Tue, 19 Jun 2012 16:15:42 -0700 Subject: Staging: add CSR wifi module This consists of two modules, the driver, and a "helper" module that is just a wrapper around common kernel functions. The wrapper module will be removed soon, but for now it's needed. These files were based on the csr-linux-wifi-5.0.3-oss.tar.gz package provided by CSR and Blue Giga, and is covered under the license specified in the LICENSE.txt file (basically dual BSD and GPLv2). The files were flattened out of the deep directory mess they were originally in, and a few EXPORT_SYMBOL_GPL() were added in order for everything to link properly with the helper module setup. Cc: Mikko Virkkilä Cc: Lauri Hintsala Cc: Riku Mettälä Cc: Veli-Pekka Peltola Signed-off-by: Greg Kroah-Hartman --- drivers/staging/csr/mlme.c | 441 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 441 insertions(+) create mode 100644 drivers/staging/csr/mlme.c (limited to 'drivers/staging/csr/mlme.c') diff --git a/drivers/staging/csr/mlme.c b/drivers/staging/csr/mlme.c new file mode 100644 index 000000000000..790d5d77375f --- /dev/null +++ b/drivers/staging/csr/mlme.c @@ -0,0 +1,441 @@ +/* + * --------------------------------------------------------------------------- + * FILE: mlme.c + * + * PURPOSE: + * This file provides functions to send MLME requests to the UniFi. + * + * Copyright (C) 2007-2008 by Cambridge Silicon Radio Ltd. + * + * Refer to LICENSE.txt included with this source code for details on + * the license terms. + * + * --------------------------------------------------------------------------- + */ +#include "csr_wifi_hip_unifi.h" +#include "unifi_priv.h" + + +/* The additional time taken by the UniFi to do a scan per channel */ +#define SCAN_STARTUP_TIME 300 /* in millisecs */ + + +/* + * --------------------------------------------------------------------------- + * unifi_mlme_wait_for_reply + * + * Wait for a reply after sending a signal. + * + * Arguments: + * priv Pointer to device private context struct + * ul_client Pointer to linux client + * sig_reply_id ID of the expected reply (defined in sigs.h). + * timeout timeout in ms + * + * Returns: + * 0 on success, -ve POSIX code on error. + * + * Notes: + * This function waits for a specific (sig_reply_id) signal from UniFi. + * It also match the sequence number of the received (cfm) signal, with + * the latest sequence number of the signal (req) we have sent. + * These two number match be equal. + * Should only be used for waiting xxx.cfm signals and only after + * we have sent the matching xxx.req signal to UniFi. + * If no response is received within the expected time (timeout), we assume + * that the UniFi is busy and return an error. + * If the wait is aborted by a kernel signal arriving, we stop waiting. + * If a response from UniFi is not what we expected, we discard it and + * wait again. This could be a response from an aborted request. If we + * see several bad responses we assume we have lost synchronisation with + * UniFi. + * --------------------------------------------------------------------------- + */ +static int +unifi_mlme_wait_for_reply(unifi_priv_t *priv, ul_client_t *pcli, int sig_reply_id, int timeout) +{ + int retries = 0; + long r; + long t = timeout; + unsigned int sent_seq_no; + + /* Convert t in ms to jiffies */ + t = msecs_to_jiffies(t); + + do { + /* Wait for the confirm or timeout. */ + r = wait_event_interruptible_timeout(pcli->udi_wq, + (pcli->wake_up_wq_id) || (priv->io_aborted == 1), + t); + /* Check for general i/o error */ + if (priv->io_aborted) { + unifi_error(priv, "MLME operation aborted\n"); + return -EIO; + } + + /* + * If r=0 the request has timed-out. + * If r>0 the request has completed successfully. + * If r=-ERESTARTSYS an event (kill signal) has interrupted the wait_event. + */ + if ((r == 0) && (pcli->wake_up_wq_id == 0)) { + unifi_error(priv, "mlme_wait: timed-out waiting for 0x%.4X, after %lu msec.\n", + sig_reply_id, jiffies_to_msecs(t)); + pcli->wake_up_wq_id = 0; + return -ETIMEDOUT; + } else if (r == -ERESTARTSYS) { + unifi_error(priv, "mlme_wait: waiting for 0x%.4X was aborted.\n", sig_reply_id); + pcli->wake_up_wq_id = 0; + return -EINTR; + } else { + /* Get the sequence number of the signal that we previously set. */ + if (pcli->seq_no != 0) { + sent_seq_no = pcli->seq_no - 1; + } else { + sent_seq_no = 0x0F; + } + + unifi_trace(priv, UDBG5, "Received 0x%.4X, seq: (r:%d, s:%d)\n", + pcli->wake_up_wq_id, + pcli->wake_seq_no, sent_seq_no); + + /* The two sequence ids must match. */ + if (pcli->wake_seq_no == sent_seq_no) { + /* and the signal ids must match. */ + if (sig_reply_id == pcli->wake_up_wq_id) { + /* Found the expected signal */ + break; + } else { + /* This should never happen ... */ + unifi_error(priv, "mlme_wait: mismatching signal id (0x%.4X - exp 0x%.4X) (seq %d)\n", + pcli->wake_up_wq_id, + sig_reply_id, + pcli->wake_seq_no); + pcli->wake_up_wq_id = 0; + return -EIO; + } + } + /* Wait for the next signal. */ + pcli->wake_up_wq_id = 0; + + retries ++; + if (retries >= 3) { + unifi_error(priv, "mlme_wait: confirm wait retries exhausted (0x%.4X - exp 0x%.4X)\n", + pcli->wake_up_wq_id, + sig_reply_id); + pcli->wake_up_wq_id = 0; + return -EIO; + } + } + } while (1); + + pcli->wake_up_wq_id = 0; + + return 0; +} /* unifi_mlme_wait_for_reply() */ + + +/* + * --------------------------------------------------------------------------- + * unifi_mlme_blocking_request + * + * Send a MLME request signal to UniFi. + * + * Arguments: + * priv Pointer to device private context struct + * pcli Pointer to context of calling process + * sig Pointer to the signal to send + * data_ptrs Pointer to the bulk data of the signal + * timeout The request's timeout. + * + * Returns: + * 0 on success, 802.11 result code on error. + * --------------------------------------------------------------------------- + */ +int +unifi_mlme_blocking_request(unifi_priv_t *priv, ul_client_t *pcli, + CSR_SIGNAL *sig, bulk_data_param_t *data_ptrs, + int timeout) +{ + int r; + + func_enter(); + + if (sig->SignalPrimitiveHeader.SignalId == 0) { + unifi_error(priv, "unifi_mlme_blocking_request: Invalid Signal Id (0x%x)\n", + sig->SignalPrimitiveHeader.SignalId); + return -EINVAL; + } + + down(&priv->mlme_blocking_mutex); + + sig->SignalPrimitiveHeader.ReceiverProcessId = 0; + sig->SignalPrimitiveHeader.SenderProcessId = pcli->sender_id | pcli->seq_no; + + unifi_trace(priv, UDBG2, "Send client=%d, S:0x%04X, sig 0x%.4X\n", + pcli->client_id, + sig->SignalPrimitiveHeader.SenderProcessId, + sig->SignalPrimitiveHeader.SignalId); + /* Send the signal to UniFi */ + r = ul_send_signal_unpacked(priv, sig, data_ptrs); + if (r) { + up(&priv->mlme_blocking_mutex); + unifi_error(priv, "Error queueing MLME REQUEST signal\n"); + return r; + } + + unifi_trace(priv, UDBG5, "Send 0x%.4X, seq = %d\n", + sig->SignalPrimitiveHeader.SignalId, pcli->seq_no); + + /* + * Advance the sequence number of the last sent signal, only + * if the signal has been successfully set. + */ + pcli->seq_no++; + if (pcli->seq_no > 0x0F) { + pcli->seq_no = 0; + } + + r = unifi_mlme_wait_for_reply(priv, pcli, (sig->SignalPrimitiveHeader.SignalId + 1), timeout); + up(&priv->mlme_blocking_mutex); + + if (r) { + unifi_error(priv, "Error waiting for MLME CONFIRM signal\n"); + return r; + } + + func_exit(); + return 0; +} /* unifi_mlme_blocking_request() */ + + +/* + * --------------------------------------------------------------------------- + * unifi_mlme_copy_reply_and_wakeup_client + * + * Copy the reply signal from UniFi to the client's structure + * and wake up the waiting client. + * + * Arguments: + * None. + * + * Returns: + * None. + * --------------------------------------------------------------------------- + */ +void +unifi_mlme_copy_reply_and_wakeup_client(ul_client_t *pcli, + CSR_SIGNAL *signal, int signal_len, + const bulk_data_param_t *bulkdata) +{ + int i; + + /* Copy the signal to the reply */ + memcpy(pcli->reply_signal, signal, signal_len); + + /* Get the sequence number of the signal that woke us up. */ + pcli->wake_seq_no = pcli->reply_signal->SignalPrimitiveHeader.ReceiverProcessId & 0x0F; + + /* Append any bulk data */ + for (i = 0; i < UNIFI_MAX_DATA_REFERENCES; i++) { + if (bulkdata->d[i].data_length > 0) { + if (bulkdata->d[i].os_data_ptr) { + memcpy(pcli->reply_bulkdata[i]->ptr, bulkdata->d[i].os_data_ptr, bulkdata->d[i].data_length); + pcli->reply_bulkdata[i]->length = bulkdata->d[i].data_length; + } else { + pcli->reply_bulkdata[i]->length = 0; + } + } + } + + /* Wake the requesting MLME function. */ + pcli->wake_up_wq_id = pcli->reply_signal->SignalPrimitiveHeader.SignalId; + wake_up_interruptible(&pcli->udi_wq); + +} /* unifi_mlme_copy_reply_and_wakeup_client() */ + + +/* + * --------------------------------------------------------------------------- + * uf_abort_mlme + * + * Abort any MLME operation in progress. + * This is used in the error recovery mechanism. + * + * Arguments: + * priv Pointer to driver context. + * + * Returns: + * 0 on success. + * --------------------------------------------------------------------------- + */ +int +uf_abort_mlme(unifi_priv_t *priv) +{ + ul_client_t *ul_cli; + + /* Ensure no MLME functions are waiting on a the mlme_event semaphore. */ + priv->io_aborted = 1; + + ul_cli = priv->netdev_client; + if (ul_cli) { + wake_up_interruptible(&ul_cli->udi_wq); + } + + ul_cli = priv->wext_client; + if (ul_cli) { + wake_up_interruptible(&ul_cli->udi_wq); + } + + return 0; +} /* uf_abort_mlme() */ + + + +/* + * --------------------------------------------------------------------------- + * + * Human-readable decoding of Reason and Result codes. + * + * --------------------------------------------------------------------------- + */ + +struct mlme_code { + const char *name; + int id; +}; + +static const struct mlme_code Result_codes[] = { + { "Success", 0x0000 }, + { "Unspecified Failure", 0x0001 }, + /* (Reserved) 0x0002 - 0x0009 */ + { "Refused Capabilities Mismatch", 0x000A }, + /* (Reserved) 0x000B */ + { "Refused External Reason", 0x000C }, + /* (Reserved) 0x000D - 0x0010 */ + { "Refused AP Out Of Memory", 0x0011 }, + { "Refused Basic Rates Mismatch", 0x0012 }, + /* (Reserved) 0x0013 - 0x001F */ + { "Failure", 0x0020 }, + /* (Reserved) 0x0021 - 0x0024 */ + { "Refused Reason Unspecified", 0x0025 }, + { "Invalid Parameters", 0x0026 }, + { "Rejected With Suggested Changes", 0x0027 }, + /* (Reserved) 0x0028 - 0x002E */ + { "Rejected For Delay Period", 0x002F }, + { "Not Allowed", 0x0030 }, + { "Not Present", 0x0031 }, + { "Not QSTA", 0x0032 }, + /* (Reserved) 0x0033 - 0x7FFF */ + { "Timeout", 0x8000 }, + { "Too Many Simultaneous Requests", 0x8001 }, + { "BSS Already Started Or Joined", 0x8002 }, + { "Not Supported", 0x8003 }, + { "Transmission Failure", 0x8004 }, + { "Refused Not Authenticated", 0x8005 }, + { "Reset Required Before Start", 0x8006 }, + { "LM Info Unavailable", 0x8007 }, + { NULL, -1 } +}; + +static const struct mlme_code Reason_codes[] = { + /* (Reserved) 0x0000 */ + { "Unspecified Reason", 0x0001 }, + { "Authentication Not Valid", 0x0002 }, + { "Deauthenticated Leave BSS", 0x0003 }, + { "Disassociated Inactivity", 0x0004 }, + { "AP Overload", 0x0005 }, + { "Class2 Frame Error", 0x0006 }, + { "Class3 Frame Error", 0x0007 }, + { "Disassociated Leave BSS", 0x0008 }, + { "Association Not Authenticated", 0x0009 }, + { "Disassociated Power Capability", 0x000A }, + { "Disassociated Supported Channels", 0x000B }, + /* (Reserved) 0x000C */ + { "Invalid Information Element", 0x000D }, + { "Michael MIC Failure", 0x000E }, + { "Fourway Handshake Timeout", 0x000F }, + { "Group Key Update Timeout", 0x0010 }, + { "Handshake Element Different", 0x0011 }, + { "Invalid Group Cipher", 0x0012 }, + { "Invalid Pairwise Cipher", 0x0013 }, + { "Invalid AKMP", 0x0014 }, + { "Unsupported RSN IE Version", 0x0015 }, + { "Invalid RSN IE Capabilities", 0x0016 }, + { "Dot1X Auth Failed", 0x0017 }, + { "Cipher Rejected By Policy", 0x0018 }, + /* (Reserved) 0x0019 - 0x001F */ + { "QoS Unspecified Reason", 0x0020 }, + { "QoS Insufficient Bandwidth", 0x0021 }, + { "QoS Excessive Not Ack", 0x0022 }, + { "QoS TXOP Limit Exceeded", 0x0023 }, + { "QSTA Leaving", 0x0024 }, + { "End TS, End DLS, End BA", 0x0025 }, + { "Unknown TS, Unknown DLS, Unknown BA", 0x0026 }, + { "Timeout", 0x0027 }, + /* (Reserved) 0x0028 - 0x002C */ + { "STAKey Mismatch", 0x002D }, + { NULL, -1 } +}; + + +static const char * +lookup_something(const struct mlme_code *n, int id) +{ + for (; n->name; n++) { + if (n->id == id) { + return n->name; + } + } + + /* not found */ + return NULL; +} /* lookup_something() */ + + +const char * +lookup_result_code(int result) +{ + static char fallback[16]; + const char *str; + + str = lookup_something(Result_codes, result); + + if (str == NULL) { + snprintf(fallback, 16, "%d", result); + str = fallback; + } + + return str; +} /* lookup_result_code() */ + + +/* + * --------------------------------------------------------------------------- + * lookup_reason + * + * Return a description string for a WiFi MLME ReasonCode. + * + * Arguments: + * reason The ReasonCode to interpret. + * + * Returns: + * Pointer to description string. + * --------------------------------------------------------------------------- + */ +const char * +lookup_reason_code(int reason) +{ + static char fallback[16]; + const char *str; + + str = lookup_something(Reason_codes, reason); + + if (str == NULL) { + snprintf(fallback, 16, "%d", reason); + str = fallback; + } + + return str; +} /* lookup_reason_code() */ + -- cgit v1.2.3-55-g7522 From 69a7cd7dd54d4d7a129c209a9586f850b13721bb Mon Sep 17 00:00:00 2001 From: Marcos Paulo de Souza Date: Mon, 9 Jul 2012 23:43:13 -0300 Subject: staging: csr: Remove unused macros These macros are not used, so remove it. Signed-off-by: Marcos Paulo de Souza Signed-off-by: Greg Kroah-Hartman --- drivers/staging/csr/csr_wifi_hip_card_sdio.c | 3 --- drivers/staging/csr/drv.c | 1 - drivers/staging/csr/firmware.c | 1 - drivers/staging/csr/mlme.c | 5 ----- drivers/staging/csr/monitor.c | 2 -- drivers/staging/csr/sme_sys.c | 1 - 6 files changed, 13 deletions(-) (limited to 'drivers/staging/csr/mlme.c') diff --git a/drivers/staging/csr/csr_wifi_hip_card_sdio.c b/drivers/staging/csr/csr_wifi_hip_card_sdio.c index 91976b824a4e..5a86ff90253d 100644 --- a/drivers/staging/csr/csr_wifi_hip_card_sdio.c +++ b/drivers/staging/csr/csr_wifi_hip_card_sdio.c @@ -36,9 +36,6 @@ #define MAILBOX2_TIMEOUT 5 /* in millisecs */ #define MAILBOX2_ATTEMPTS 10 /* 50ms */ -#define MAILBOX2_RESET_ATTEMPTS 10 -#define MAILBOX2_RESET_TIMEOUT 5 /* in millisecs */ - #define RESET_SETTLE_DELAY 25 /* in millisecs */ static CsrResult card_init_slots(card_t *card); diff --git a/drivers/staging/csr/drv.c b/drivers/staging/csr/drv.c index fbe86301816c..4be6d9533cd0 100644 --- a/drivers/staging/csr/drv.c +++ b/drivers/staging/csr/drv.c @@ -63,7 +63,6 @@ int coredump_max = CSR_WIFI_HIP_NUM_COREDUMP_BUFFERS; int run_bh_once = -1; /* Set for scheduled interrupt mode, -1 = default */ int bh_priority = -1; #ifdef CSR_WIFI_HIP_DEBUG_OFFLINE -#define UNIFI_LOG_HIP_SIGNALS_FILTER_SIGNAL (1 << 0) #define UNIFI_LOG_HIP_SIGNALS_FILTER_BULKDATA (1 << 1) #define UNIFI_LOG_HIP_SIGNALS_FILTER_TIMESTAMP (1 << 2) int log_hip_signals = 0; diff --git a/drivers/staging/csr/firmware.c b/drivers/staging/csr/firmware.c index 03da0d5c247a..98e27d6f440e 100644 --- a/drivers/staging/csr/firmware.c +++ b/drivers/staging/csr/firmware.c @@ -220,7 +220,6 @@ unifi_fw_read(void *ospriv, void *arg, CsrUint32 offset, void *buf, CsrUint32 le -#define UNIFIHELPER_INIT_MODE_SMEEMB 0 #define UNIFIHELPER_INIT_MODE_SMEUSER 2 #define UNIFIHELPER_INIT_MODE_NATIVE 1 diff --git a/drivers/staging/csr/mlme.c b/drivers/staging/csr/mlme.c index 790d5d77375f..ed767eccbb32 100644 --- a/drivers/staging/csr/mlme.c +++ b/drivers/staging/csr/mlme.c @@ -15,11 +15,6 @@ #include "csr_wifi_hip_unifi.h" #include "unifi_priv.h" - -/* The additional time taken by the UniFi to do a scan per channel */ -#define SCAN_STARTUP_TIME 300 /* in millisecs */ - - /* * --------------------------------------------------------------------------- * unifi_mlme_wait_for_reply diff --git a/drivers/staging/csr/monitor.c b/drivers/staging/csr/monitor.c index 8c35b7e9fc96..628782ad641e 100644 --- a/drivers/staging/csr/monitor.c +++ b/drivers/staging/csr/monitor.c @@ -242,9 +242,7 @@ netrx_prism(unifi_priv_t *priv, unsigned char *ptr; unsigned char *base; int ind_data_len = skb_orig->len - 2 - ETH_HLEN; -#define WLANCAP_MAGIC_COOKIE_BASE 0x80211000 #define WLANCAP_MAGIC_COOKIE_V1 0x80211001 -#define WLANCAP_MAGIC_COOKIE_V2 0x80211002 struct avs_header_v1 { uint32 version; uint32 length; diff --git a/drivers/staging/csr/sme_sys.c b/drivers/staging/csr/sme_sys.c index 9c3aa7494604..5f38f9dbb986 100644 --- a/drivers/staging/csr/sme_sys.c +++ b/drivers/staging/csr/sme_sys.c @@ -1572,7 +1572,6 @@ void CsrWifiRouterMaPacketReqHandler(void* drvpriv, CsrWifiFsmEvent* msg) r = _sys_packet_req(priv, &signal, mareq->subscriptionHandle, mareq->frameLength, mareq->frame, snap_protocol); -#define MAX_RETRY 2 if (r && mareq->cfmRequested) { CsrWifiRouterMaPacketCfmSend(msg->source,interfaceTag, -- cgit v1.2.3-55-g7522