aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net')
-rw-r--r--drivers/net/wireless/libertas/cmd.c96
-rw-r--r--drivers/net/wireless/libertas/cmdresp.c23
-rw-r--r--drivers/net/wireless/libertas/decl.h6
-rw-r--r--drivers/net/wireless/libertas/hostcmd.h11
4 files changed, 126 insertions, 10 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
diff --git a/drivers/net/wireless/libertas/cmdresp.c b/drivers/net/wireless/libertas/cmdresp.c
index cbd28ee7c5b8..6a43de772aa0 100644
--- a/drivers/net/wireless/libertas/cmdresp.c
+++ b/drivers/net/wireless/libertas/cmdresp.c
@@ -799,7 +799,7 @@ int lbs_process_rx_command(struct lbs_private *priv)
799 } 799 }
800 800
801 /* Store the response code to cur_cmd_retcode. */ 801 /* Store the response code to cur_cmd_retcode. */
802 adapter->cur_cmd_retcode = result;; 802 adapter->cur_cmd_retcode = result;
803 803
804 if (respcmd == CMD_RET(CMD_802_11_PS_MODE)) { 804 if (respcmd == CMD_RET(CMD_802_11_PS_MODE)) {
805 struct cmd_ds_802_11_ps_mode *psmode = &resp->params.psmode; 805 struct cmd_ds_802_11_ps_mode *psmode = &resp->params.psmode;
@@ -880,11 +880,22 @@ int lbs_process_rx_command(struct lbs_private *priv)
880 goto done; 880 goto done;
881 } 881 }
882 882
883 spin_unlock_irqrestore(&adapter->driver_lock, flags); 883 if (adapter->cur_cmd->pdata_size) {
884 884 struct cmd_ds_gen *r = (struct cmd_ds_gen *)resp;
885 ret = handle_cmd_response(respcmd, resp, priv); 885 u16 sz = cpu_to_le16(resp->size);
886 886 if (sz > *adapter->cur_cmd->pdata_size) {
887 spin_lock_irqsave(&adapter->driver_lock, flags); 887 lbs_pr_err("response 0x%04x doesn't fit into "
888 "buffer (%d > %d)\n", respcmd,
889 sz, *adapter->cur_cmd->pdata_size);
890 sz = *adapter->cur_cmd->pdata_size;
891 }
892 memcpy(adapter->cur_cmd->pdata_buf, r->cmdresp, sz);
893 *adapter->cur_cmd->pdata_size = sz;
894 } else {
895 spin_unlock_irqrestore(&adapter->driver_lock, flags);
896 ret = handle_cmd_response(respcmd, resp, priv);
897 spin_lock_irqsave(&adapter->driver_lock, flags);
898 }
888 if (adapter->cur_cmd) { 899 if (adapter->cur_cmd) {
889 /* Clean up and Put current command back to cmdfreeq */ 900 /* Clean up and Put current command back to cmdfreeq */
890 __lbs_cleanup_and_insert_cmd(priv, adapter->cur_cmd); 901 __lbs_cleanup_and_insert_cmd(priv, adapter->cur_cmd);
diff --git a/drivers/net/wireless/libertas/decl.h b/drivers/net/wireless/libertas/decl.h
index 0856cc96f513..6f47ff089622 100644
--- a/drivers/net/wireless/libertas/decl.h
+++ b/drivers/net/wireless/libertas/decl.h
@@ -16,6 +16,7 @@ struct lbs_adapter;
16struct sk_buff; 16struct sk_buff;
17struct net_device; 17struct net_device;
18struct cmd_ctrl_node; 18struct cmd_ctrl_node;
19struct cmd_ds_command;
19 20
20int lbs_set_mac_packet_filter(struct lbs_private *priv); 21int lbs_set_mac_packet_filter(struct lbs_private *priv);
21 22
@@ -23,6 +24,11 @@ void lbs_send_tx_feedback(struct lbs_private *priv);
23 24
24int lbs_free_cmd_buffer(struct lbs_private *priv); 25int lbs_free_cmd_buffer(struct lbs_private *priv);
25 26
27int lbs_cmd(struct lbs_private *priv,
28 u16 command,
29 void *cmd, int cmd_size,
30 void *resp, int *resp_size);
31
26int lbs_prepare_and_send_command(struct lbs_private *priv, 32int lbs_prepare_and_send_command(struct lbs_private *priv,
27 u16 cmd_no, 33 u16 cmd_no,
28 u16 cmd_action, 34 u16 cmd_action,
diff --git a/drivers/net/wireless/libertas/hostcmd.h b/drivers/net/wireless/libertas/hostcmd.h
index f096d995194a..be69ae652923 100644
--- a/drivers/net/wireless/libertas/hostcmd.h
+++ b/drivers/net/wireless/libertas/hostcmd.h
@@ -66,13 +66,13 @@ struct rxpd {
66}; 66};
67 67
68struct cmd_ctrl_node { 68struct cmd_ctrl_node {
69 /* CMD link list */
70 struct list_head list; 69 struct list_head list;
71 /*CMD wait option: wait for finish or no wait */ 70 /* wait for finish or not */
72 u16 wait_option; 71 u16 wait_option;
73 /* command parameter */ 72 /* command response */
74 void *pdata_buf; 73 void *pdata_buf;
75 /*command data */ 74 int *pdata_size;
75 /* command data */
76 u8 *bufvirtualaddr; 76 u8 *bufvirtualaddr;
77 /* wait queue */ 77 /* wait queue */
78 u16 cmdwaitqwoken; 78 u16 cmdwaitqwoken;
@@ -100,9 +100,12 @@ struct cmd_ds_gen {
100 __le16 size; 100 __le16 size;
101 __le16 seqnum; 101 __le16 seqnum;
102 __le16 result; 102 __le16 result;
103 void *cmdresp[0];
103}; 104};
104 105
105#define S_DS_GEN sizeof(struct cmd_ds_gen) 106#define S_DS_GEN sizeof(struct cmd_ds_gen)
107
108
106/* 109/*
107 * Define data structure for CMD_GET_HW_SPEC 110 * Define data structure for CMD_GET_HW_SPEC
108 * This structure defines the response for the GET_HW_SPEC command 111 * This structure defines the response for the GET_HW_SPEC command