.. | .. |
---|
221 | 221 | if (unlikely(wmi->stopped)) |
---|
222 | 222 | goto free_skb; |
---|
223 | 223 | |
---|
| 224 | + /* Validate the obtained SKB. */ |
---|
| 225 | + if (unlikely(skb->len < sizeof(struct wmi_cmd_hdr))) |
---|
| 226 | + goto free_skb; |
---|
| 227 | + |
---|
224 | 228 | hdr = (struct wmi_cmd_hdr *) skb->data; |
---|
225 | 229 | cmd_id = be16_to_cpu(hdr->command_id); |
---|
226 | 230 | |
---|
.. | .. |
---|
238 | 242 | spin_unlock_irqrestore(&wmi->wmi_lock, flags); |
---|
239 | 243 | goto free_skb; |
---|
240 | 244 | } |
---|
241 | | - spin_unlock_irqrestore(&wmi->wmi_lock, flags); |
---|
242 | 245 | |
---|
243 | 246 | /* WMI command response */ |
---|
244 | 247 | ath9k_wmi_rsp_callback(wmi, skb); |
---|
| 248 | + spin_unlock_irqrestore(&wmi->wmi_lock, flags); |
---|
245 | 249 | |
---|
246 | 250 | free_skb: |
---|
247 | 251 | kfree_skb(skb); |
---|
.. | .. |
---|
279 | 283 | |
---|
280 | 284 | static int ath9k_wmi_cmd_issue(struct wmi *wmi, |
---|
281 | 285 | struct sk_buff *skb, |
---|
282 | | - enum wmi_cmd_id cmd, u16 len) |
---|
| 286 | + enum wmi_cmd_id cmd, u16 len, |
---|
| 287 | + u8 *rsp_buf, u32 rsp_len) |
---|
283 | 288 | { |
---|
284 | 289 | struct wmi_cmd_hdr *hdr; |
---|
285 | 290 | unsigned long flags; |
---|
.. | .. |
---|
289 | 294 | hdr->seq_no = cpu_to_be16(++wmi->tx_seq_id); |
---|
290 | 295 | |
---|
291 | 296 | spin_lock_irqsave(&wmi->wmi_lock, flags); |
---|
| 297 | + |
---|
| 298 | + /* record the rsp buffer and length */ |
---|
| 299 | + wmi->cmd_rsp_buf = rsp_buf; |
---|
| 300 | + wmi->cmd_rsp_len = rsp_len; |
---|
| 301 | + |
---|
292 | 302 | wmi->last_seq_id = wmi->tx_seq_id; |
---|
293 | 303 | spin_unlock_irqrestore(&wmi->wmi_lock, flags); |
---|
294 | 304 | |
---|
.. | .. |
---|
304 | 314 | struct ath_common *common = ath9k_hw_common(ah); |
---|
305 | 315 | u16 headroom = sizeof(struct htc_frame_hdr) + |
---|
306 | 316 | sizeof(struct wmi_cmd_hdr); |
---|
| 317 | + unsigned long time_left, flags; |
---|
307 | 318 | struct sk_buff *skb; |
---|
308 | | - unsigned long time_left; |
---|
309 | 319 | int ret = 0; |
---|
310 | 320 | |
---|
311 | 321 | if (ah->ah_flags & AH_UNPLUGGED) |
---|
.. | .. |
---|
329 | 339 | goto out; |
---|
330 | 340 | } |
---|
331 | 341 | |
---|
332 | | - /* record the rsp buffer and length */ |
---|
333 | | - wmi->cmd_rsp_buf = rsp_buf; |
---|
334 | | - wmi->cmd_rsp_len = rsp_len; |
---|
335 | | - |
---|
336 | | - ret = ath9k_wmi_cmd_issue(wmi, skb, cmd_id, cmd_len); |
---|
| 342 | + ret = ath9k_wmi_cmd_issue(wmi, skb, cmd_id, cmd_len, rsp_buf, rsp_len); |
---|
337 | 343 | if (ret) |
---|
338 | 344 | goto out; |
---|
339 | 345 | |
---|
.. | .. |
---|
341 | 347 | if (!time_left) { |
---|
342 | 348 | ath_dbg(common, WMI, "Timeout waiting for WMI command: %s\n", |
---|
343 | 349 | wmi_cmd_to_name(cmd_id)); |
---|
| 350 | + spin_lock_irqsave(&wmi->wmi_lock, flags); |
---|
| 351 | + wmi->last_seq_id = 0; |
---|
| 352 | + spin_unlock_irqrestore(&wmi->wmi_lock, flags); |
---|
344 | 353 | mutex_unlock(&wmi->op_mutex); |
---|
345 | 354 | return -ETIMEDOUT; |
---|
346 | 355 | } |
---|