diff options
Diffstat (limited to 'drivers/net')
-rw-r--r-- | drivers/net/wireless/libertas/cmd.c | 96 | ||||
-rw-r--r-- | drivers/net/wireless/libertas/cmdresp.c | 23 | ||||
-rw-r--r-- | drivers/net/wireless/libertas/decl.h | 6 | ||||
-rw-r--r-- | drivers/net/wireless/libertas/hostcmd.h | 11 |
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 | */ | ||
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 | |||
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; | |||
16 | struct sk_buff; | 16 | struct sk_buff; |
17 | struct net_device; | 17 | struct net_device; |
18 | struct cmd_ctrl_node; | 18 | struct cmd_ctrl_node; |
19 | struct cmd_ds_command; | ||
19 | 20 | ||
20 | int lbs_set_mac_packet_filter(struct lbs_private *priv); | 21 | int 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 | ||
24 | int lbs_free_cmd_buffer(struct lbs_private *priv); | 25 | int lbs_free_cmd_buffer(struct lbs_private *priv); |
25 | 26 | ||
27 | int lbs_cmd(struct lbs_private *priv, | ||
28 | u16 command, | ||
29 | void *cmd, int cmd_size, | ||
30 | void *resp, int *resp_size); | ||
31 | |||
26 | int lbs_prepare_and_send_command(struct lbs_private *priv, | 32 | int 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 | ||
68 | struct cmd_ctrl_node { | 68 | struct 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 |