aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/libertas/cmd.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/wireless/libertas/cmd.c')
-rw-r--r--drivers/net/wireless/libertas/cmd.c96
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 */
2028int 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
2099done:
2100 lbs_deb_leave_args(LBS_DEB_HOST, "ret %d", ret);
2101 return ret;
2102}
2103EXPORT_SYMBOL_GPL(lbs_cmd);
2104
2105