aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/libertas/cmd.c
diff options
context:
space:
mode:
authorHolger Schurig <h.schurig@mn-solutions.de>2007-12-05 11:58:11 -0500
committerDavid S. Miller <davem@davemloft.net>2008-01-28 18:06:04 -0500
commit675787e29fd97d08bf7e6253c89ab6de23bf7089 (patch)
tree81a51dd6696e5ba67a87e6b4bf2ee368854f23b7 /drivers/net/wireless/libertas/cmd.c
parent0d61d04210b617963c202a3c4dcbcd26a024d5d3 (diff)
libertas: handy function to call firmware commands
Using an arbitrary firmware command was actually very painful. One had to change big switch() statements in cmd.c, cmdresp.c, add structs to the big union in "struct cmd_ds_command" and add the define for the CMD_802_11_xxx to the proper place. With this function, this is now much easier. For now, it implements a blocking (a.k.a. CMD_OPTION_WAITFORRSP) way where one deals directly with command requests and response buffers. You can do everything in one place: Signed-off-by: Holger Schurig <hs4233@mail.mn-solutions.de> Signed-off-by: David Woodhouse <dwmw2@infradead.org> Signed-off-by: John W. Linville <linville@tuxdriver.com>
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