aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/iwlwifi/iwl-hcmd.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/wireless/iwlwifi/iwl-hcmd.c')
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-hcmd.c63
1 files changed, 29 insertions, 34 deletions
diff --git a/drivers/net/wireless/iwlwifi/iwl-hcmd.c b/drivers/net/wireless/iwlwifi/iwl-hcmd.c
index 17d61ac8ed61..b82ad15d5189 100644
--- a/drivers/net/wireless/iwlwifi/iwl-hcmd.c
+++ b/drivers/net/wireless/iwlwifi/iwl-hcmd.c
@@ -103,22 +103,23 @@ EXPORT_SYMBOL(get_cmd_string);
103 103
104#define HOST_COMPLETE_TIMEOUT (HZ / 2) 104#define HOST_COMPLETE_TIMEOUT (HZ / 2)
105 105
106static int iwl_generic_cmd_callback(struct iwl_priv *priv, 106static void iwl_generic_cmd_callback(struct iwl_priv *priv,
107 struct iwl_cmd *cmd, struct sk_buff *skb) 107 struct iwl_device_cmd *cmd,
108 struct sk_buff *skb)
108{ 109{
109 struct iwl_rx_packet *pkt = NULL; 110 struct iwl_rx_packet *pkt = NULL;
110 111
111 if (!skb) { 112 if (!skb) {
112 IWL_ERR(priv, "Error: Response NULL in %s.\n", 113 IWL_ERR(priv, "Error: Response NULL in %s.\n",
113 get_cmd_string(cmd->hdr.cmd)); 114 get_cmd_string(cmd->hdr.cmd));
114 return 1; 115 return;
115 } 116 }
116 117
117 pkt = (struct iwl_rx_packet *)skb->data; 118 pkt = (struct iwl_rx_packet *)skb->data;
118 if (pkt->hdr.flags & IWL_CMD_FAILED_MSK) { 119 if (pkt->hdr.flags & IWL_CMD_FAILED_MSK) {
119 IWL_ERR(priv, "Bad return from %s (0x%08X)\n", 120 IWL_ERR(priv, "Bad return from %s (0x%08X)\n",
120 get_cmd_string(cmd->hdr.cmd), pkt->hdr.flags); 121 get_cmd_string(cmd->hdr.cmd), pkt->hdr.flags);
121 return 1; 122 return;
122 } 123 }
123 124
124#ifdef CONFIG_IWLWIFI_DEBUG 125#ifdef CONFIG_IWLWIFI_DEBUG
@@ -127,29 +128,26 @@ static int iwl_generic_cmd_callback(struct iwl_priv *priv,
127 case SENSITIVITY_CMD: 128 case SENSITIVITY_CMD:
128 IWL_DEBUG_HC_DUMP(priv, "back from %s (0x%08X)\n", 129 IWL_DEBUG_HC_DUMP(priv, "back from %s (0x%08X)\n",
129 get_cmd_string(cmd->hdr.cmd), pkt->hdr.flags); 130 get_cmd_string(cmd->hdr.cmd), pkt->hdr.flags);
130 break; 131 break;
131 default: 132 default:
132 IWL_DEBUG_HC(priv, "back from %s (0x%08X)\n", 133 IWL_DEBUG_HC(priv, "back from %s (0x%08X)\n",
133 get_cmd_string(cmd->hdr.cmd), pkt->hdr.flags); 134 get_cmd_string(cmd->hdr.cmd), pkt->hdr.flags);
134 } 135 }
135#endif 136#endif
136
137 /* Let iwl_tx_complete free the response skb */
138 return 1;
139} 137}
140 138
141static int iwl_send_cmd_async(struct iwl_priv *priv, struct iwl_host_cmd *cmd) 139static int iwl_send_cmd_async(struct iwl_priv *priv, struct iwl_host_cmd *cmd)
142{ 140{
143 int ret; 141 int ret;
144 142
145 BUG_ON(!(cmd->meta.flags & CMD_ASYNC)); 143 BUG_ON(!(cmd->flags & CMD_ASYNC));
146 144
147 /* An asynchronous command can not expect an SKB to be set. */ 145 /* An asynchronous command can not expect an SKB to be set. */
148 BUG_ON(cmd->meta.flags & CMD_WANT_SKB); 146 BUG_ON(cmd->flags & CMD_WANT_SKB);
149 147
150 /* Assign a generic callback if one is not provided */ 148 /* Assign a generic callback if one is not provided */
151 if (!cmd->meta.u.callback) 149 if (!cmd->callback)
152 cmd->meta.u.callback = iwl_generic_cmd_callback; 150 cmd->callback = iwl_generic_cmd_callback;
153 151
154 if (test_bit(STATUS_EXIT_PENDING, &priv->status)) 152 if (test_bit(STATUS_EXIT_PENDING, &priv->status))
155 return -EBUSY; 153 return -EBUSY;
@@ -168,10 +166,10 @@ int iwl_send_cmd_sync(struct iwl_priv *priv, struct iwl_host_cmd *cmd)
168 int cmd_idx; 166 int cmd_idx;
169 int ret; 167 int ret;
170 168
171 BUG_ON(cmd->meta.flags & CMD_ASYNC); 169 BUG_ON(cmd->flags & CMD_ASYNC);
172 170
173 /* A synchronous command can not have a callback set. */ 171 /* A synchronous command can not have a callback set. */
174 BUG_ON(cmd->meta.u.callback != NULL); 172 BUG_ON(cmd->callback);
175 173
176 if (test_and_set_bit(STATUS_HCMD_SYNC_ACTIVE, &priv->status)) { 174 if (test_and_set_bit(STATUS_HCMD_SYNC_ACTIVE, &priv->status)) {
177 IWL_ERR(priv, 175 IWL_ERR(priv,
@@ -183,9 +181,6 @@ int iwl_send_cmd_sync(struct iwl_priv *priv, struct iwl_host_cmd *cmd)
183 181
184 set_bit(STATUS_HCMD_ACTIVE, &priv->status); 182 set_bit(STATUS_HCMD_ACTIVE, &priv->status);
185 183
186 if (cmd->meta.flags & CMD_WANT_SKB)
187 cmd->meta.source = &cmd->meta;
188
189 cmd_idx = iwl_enqueue_hcmd(priv, cmd); 184 cmd_idx = iwl_enqueue_hcmd(priv, cmd);
190 if (cmd_idx < 0) { 185 if (cmd_idx < 0) {
191 ret = cmd_idx; 186 ret = cmd_idx;
@@ -222,7 +217,7 @@ int iwl_send_cmd_sync(struct iwl_priv *priv, struct iwl_host_cmd *cmd)
222 ret = -EIO; 217 ret = -EIO;
223 goto fail; 218 goto fail;
224 } 219 }
225 if ((cmd->meta.flags & CMD_WANT_SKB) && !cmd->meta.u.skb) { 220 if ((cmd->flags & CMD_WANT_SKB) && !cmd->reply_skb) {
226 IWL_ERR(priv, "Error: Response NULL in '%s'\n", 221 IWL_ERR(priv, "Error: Response NULL in '%s'\n",
227 get_cmd_string(cmd->id)); 222 get_cmd_string(cmd->id));
228 ret = -EIO; 223 ret = -EIO;
@@ -233,20 +228,20 @@ int iwl_send_cmd_sync(struct iwl_priv *priv, struct iwl_host_cmd *cmd)
233 goto out; 228 goto out;
234 229
235cancel: 230cancel:
236 if (cmd->meta.flags & CMD_WANT_SKB) { 231 if (cmd->flags & CMD_WANT_SKB) {
237 struct iwl_cmd *qcmd; 232 /*
238 233 * Cancel the CMD_WANT_SKB flag for the cmd in the
239 /* Cancel the CMD_WANT_SKB flag for the cmd in the
240 * TX cmd queue. Otherwise in case the cmd comes 234 * TX cmd queue. Otherwise in case the cmd comes
241 * in later, it will possibly set an invalid 235 * in later, it will possibly set an invalid
242 * address (cmd->meta.source). */ 236 * address (cmd->meta.source).
243 qcmd = priv->txq[IWL_CMD_QUEUE_NUM].cmd[cmd_idx]; 237 */
244 qcmd->meta.flags &= ~CMD_WANT_SKB; 238 priv->txq[IWL_CMD_QUEUE_NUM].meta[cmd_idx].flags &=
239 ~CMD_WANT_SKB;
245 } 240 }
246fail: 241fail:
247 if (cmd->meta.u.skb) { 242 if (cmd->reply_skb) {
248 dev_kfree_skb_any(cmd->meta.u.skb); 243 dev_kfree_skb_any(cmd->reply_skb);
249 cmd->meta.u.skb = NULL; 244 cmd->reply_skb = NULL;
250 } 245 }
251out: 246out:
252 clear_bit(STATUS_HCMD_SYNC_ACTIVE, &priv->status); 247 clear_bit(STATUS_HCMD_SYNC_ACTIVE, &priv->status);
@@ -256,7 +251,7 @@ EXPORT_SYMBOL(iwl_send_cmd_sync);
256 251
257int iwl_send_cmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd) 252int iwl_send_cmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd)
258{ 253{
259 if (cmd->meta.flags & CMD_ASYNC) 254 if (cmd->flags & CMD_ASYNC)
260 return iwl_send_cmd_async(priv, cmd); 255 return iwl_send_cmd_async(priv, cmd);
261 256
262 return iwl_send_cmd_sync(priv, cmd); 257 return iwl_send_cmd_sync(priv, cmd);
@@ -277,9 +272,9 @@ EXPORT_SYMBOL(iwl_send_cmd_pdu);
277 272
278int iwl_send_cmd_pdu_async(struct iwl_priv *priv, 273int iwl_send_cmd_pdu_async(struct iwl_priv *priv,
279 u8 id, u16 len, const void *data, 274 u8 id, u16 len, const void *data,
280 int (*callback)(struct iwl_priv *priv, 275 void (*callback)(struct iwl_priv *priv,
281 struct iwl_cmd *cmd, 276 struct iwl_device_cmd *cmd,
282 struct sk_buff *skb)) 277 struct sk_buff *skb))
283{ 278{
284 struct iwl_host_cmd cmd = { 279 struct iwl_host_cmd cmd = {
285 .id = id, 280 .id = id,
@@ -287,8 +282,8 @@ int iwl_send_cmd_pdu_async(struct iwl_priv *priv,
287 .data = data, 282 .data = data,
288 }; 283 };
289 284
290 cmd.meta.flags |= CMD_ASYNC; 285 cmd.flags |= CMD_ASYNC;
291 cmd.meta.u.callback = callback; 286 cmd.callback = callback;
292 287
293 return iwl_send_cmd_async(priv, &cmd); 288 return iwl_send_cmd_async(priv, &cmd);
294} 289}