diff options
Diffstat (limited to 'drivers/net/wireless/libertas/cmd.c')
-rw-r--r-- | drivers/net/wireless/libertas/cmd.c | 96 |
1 files changed, 96 insertions, 0 deletions
diff --git a/drivers/net/wireless/libertas/cmd.c b/drivers/net/wireless/libertas/cmd.c index 54ef990a46cc..9064513aea0d 100644 --- a/drivers/net/wireless/libertas/cmd.c +++ b/drivers/net/wireless/libertas/cmd.c | |||
@@ -2007,3 +2007,99 @@ void lbs_ps_confirm_sleep(struct lbs_private *priv, u16 psmode) | |||
2007 | 2007 | ||
2008 | lbs_deb_leave(LBS_DEB_HOST); | 2008 | lbs_deb_leave(LBS_DEB_HOST); |
2009 | } | 2009 | } |
2010 | |||
2011 | |||
2012 | /** | ||
2013 | * @brief Simple way to call firmware functions | ||
2014 | * | ||
2015 | * @param priv A pointer to struct lbs_private structure | ||
2016 | * @param psmode one of the many CMD_802_11_xxxx | ||
2017 | * @param cmd pointer to the parameters structure for above command | ||
2018 | * (this should not include the command, size, sequence | ||
2019 | * and result fields from struct cmd_ds_gen) | ||
2020 | * @param cmd_size size structure pointed to by cmd | ||
2021 | * @param rsp pointer to an area where the result should be placed | ||
2022 | * @param rsp_size pointer to the size of the rsp area. If the firmware | ||
2023 | * returns fewer bytes, then this *rsp_size will be | ||
2024 | * changed to the actual size. | ||
2025 | * @return -1 in case of a higher level error, otherwise | ||
2026 | * the result code from the firmware | ||
2027 | */ | ||
2028 | int lbs_cmd(struct lbs_private *priv, | ||
2029 | u16 command, | ||
2030 | void *cmd, int cmd_size, | ||
2031 | void *rsp, int *rsp_size) | ||
2032 | { | ||
2033 | struct lbs_adapter *adapter = priv->adapter; | ||
2034 | struct cmd_ctrl_node *cmdnode; | ||
2035 | struct cmd_ds_gen *cmdptr; | ||
2036 | unsigned long flags; | ||
2037 | int ret = 0; | ||
2038 | |||
2039 | lbs_deb_enter(LBS_DEB_HOST); | ||
2040 | lbs_deb_host("rsp at %p, rsp_size at %p\n", rsp, rsp_size); | ||
2041 | |||
2042 | if (!adapter || !rsp_size) { | ||
2043 | lbs_deb_host("PREP_CMD: adapter is NULL\n"); | ||
2044 | ret = -1; | ||
2045 | goto done; | ||
2046 | } | ||
2047 | |||
2048 | if (adapter->surpriseremoved) { | ||
2049 | lbs_deb_host("PREP_CMD: card removed\n"); | ||
2050 | ret = -1; | ||
2051 | goto done; | ||
2052 | } | ||
2053 | |||
2054 | cmdnode = lbs_get_cmd_ctrl_node(priv); | ||
2055 | |||
2056 | if (cmdnode == NULL) { | ||
2057 | lbs_deb_host("PREP_CMD: cmdnode is NULL\n"); | ||
2058 | |||
2059 | /* Wake up main thread to execute next command */ | ||
2060 | wake_up_interruptible(&priv->waitq); | ||
2061 | ret = -1; | ||
2062 | goto done; | ||
2063 | } | ||
2064 | |||
2065 | cmdptr = (struct cmd_ds_gen *)cmdnode->bufvirtualaddr; | ||
2066 | cmdnode->wait_option = CMD_OPTION_WAITFORRSP; | ||
2067 | cmdnode->pdata_buf = rsp; | ||
2068 | cmdnode->pdata_size = rsp_size; | ||
2069 | |||
2070 | /* Set sequence number, clean result, move to buffer */ | ||
2071 | adapter->seqnum++; | ||
2072 | cmdptr->command = cpu_to_le16(command); | ||
2073 | cmdptr->size = cmd_size + S_DS_GEN; | ||
2074 | cmdptr->seqnum = cpu_to_le16(adapter->seqnum); | ||
2075 | cmdptr->result = 0; | ||
2076 | memcpy(cmdptr->cmdresp, cmd, cmd_size); | ||
2077 | |||
2078 | lbs_deb_host("PREP_CMD: command 0x%04x\n", command); | ||
2079 | |||
2080 | /* here was the big old switch() statement, which is now obsolete, | ||
2081 | * because the caller of lbs_cmd() sets up all of *cmd for us. */ | ||
2082 | |||
2083 | cmdnode->cmdwaitqwoken = 0; | ||
2084 | lbs_queue_cmd(adapter, cmdnode, 1); | ||
2085 | wake_up_interruptible(&priv->waitq); | ||
2086 | |||
2087 | might_sleep(); | ||
2088 | wait_event_interruptible(cmdnode->cmdwait_q, cmdnode->cmdwaitqwoken); | ||
2089 | |||
2090 | spin_lock_irqsave(&adapter->driver_lock, flags); | ||
2091 | if (adapter->cur_cmd_retcode) { | ||
2092 | lbs_deb_host("PREP_CMD: command failed with return code %d\n", | ||
2093 | adapter->cur_cmd_retcode); | ||
2094 | adapter->cur_cmd_retcode = 0; | ||
2095 | ret = -1; | ||
2096 | } | ||
2097 | spin_unlock_irqrestore(&adapter->driver_lock, flags); | ||
2098 | |||
2099 | done: | ||
2100 | lbs_deb_leave_args(LBS_DEB_HOST, "ret %d", ret); | ||
2101 | return ret; | ||
2102 | } | ||
2103 | EXPORT_SYMBOL_GPL(lbs_cmd); | ||
2104 | |||
2105 | |||