aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/ath/ath10k/wmi.c
diff options
context:
space:
mode:
authorBartosz Markowski <bartosz.markowski@tieto.com>2013-09-26 11:47:12 -0400
committerKalle Valo <kvalo@qca.qualcomm.com>2013-09-27 07:58:14 -0400
commit5e00d31a0fb74c36f3b174ff0d4914cf09016e6f (patch)
tree9557fe332e411ef341be3fb11951bb5a7c9a8baa /drivers/net/wireless/ath/ath10k/wmi.c
parentb3effe61a1a3b8f20fa4b4d30c4390a6b81a6fc2 (diff)
ath10k: bring back the WMI path for mgmt frames
This is still the only way to submit mgmt frames in case of 10.X firmware. This patch introduces wmi_mgmt_tx queue, because of the fact WMI command can block. This is a problem for ath10k_tx_htt(), since it's called from atomic context. The skb queue and worker are introduced to move the mgmt frame handling out of .tx callback context and not block. Signed-off-by: Bartosz Markowski <bartosz.markowski@tieto.com> Signed-off-by: Kalle Valo <kvalo@qca.qualcomm.com>
Diffstat (limited to 'drivers/net/wireless/ath/ath10k/wmi.c')
-rw-r--r--drivers/net/wireless/ath/ath10k/wmi.c51
1 files changed, 51 insertions, 0 deletions
diff --git a/drivers/net/wireless/ath/ath10k/wmi.c b/drivers/net/wireless/ath/ath10k/wmi.c
index 97ba23e78abf..8c223671ecc4 100644
--- a/drivers/net/wireless/ath/ath10k/wmi.c
+++ b/drivers/net/wireless/ath/ath10k/wmi.c
@@ -410,6 +410,57 @@ static int ath10k_wmi_cmd_send(struct ath10k *ar, struct sk_buff *skb,
410 return ret; 410 return ret;
411} 411}
412 412
413int ath10k_wmi_mgmt_tx(struct ath10k *ar, struct sk_buff *skb)
414{
415 int ret = 0;
416 struct wmi_mgmt_tx_cmd *cmd;
417 struct ieee80211_hdr *hdr;
418 struct sk_buff *wmi_skb;
419 struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
420 int len;
421 u16 fc;
422
423 hdr = (struct ieee80211_hdr *)skb->data;
424 fc = le16_to_cpu(hdr->frame_control);
425
426 if (WARN_ON_ONCE(!ieee80211_is_mgmt(hdr->frame_control)))
427 return -EINVAL;
428
429 len = sizeof(cmd->hdr) + skb->len;
430 len = round_up(len, 4);
431
432 wmi_skb = ath10k_wmi_alloc_skb(len);
433 if (!wmi_skb)
434 return -ENOMEM;
435
436 cmd = (struct wmi_mgmt_tx_cmd *)wmi_skb->data;
437
438 cmd->hdr.vdev_id = __cpu_to_le32(ATH10K_SKB_CB(skb)->vdev_id);
439 cmd->hdr.tx_rate = 0;
440 cmd->hdr.tx_power = 0;
441 cmd->hdr.buf_len = __cpu_to_le32((u32)(skb->len));
442
443 memcpy(cmd->hdr.peer_macaddr.addr, ieee80211_get_DA(hdr), ETH_ALEN);
444 memcpy(cmd->buf, skb->data, skb->len);
445
446 ath10k_dbg(ATH10K_DBG_WMI, "wmi mgmt tx skb %p len %d ftype %02x stype %02x\n",
447 wmi_skb, wmi_skb->len, fc & IEEE80211_FCTL_FTYPE,
448 fc & IEEE80211_FCTL_STYPE);
449
450 /* Send the management frame buffer to the target */
451 ret = ath10k_wmi_cmd_send(ar, wmi_skb, ar->wmi.cmd->mgmt_tx_cmdid);
452 if (ret) {
453 dev_kfree_skb_any(skb);
454 return ret;
455 }
456
457 /* TODO: report tx status to mac80211 - temporary just ACK */
458 info->flags |= IEEE80211_TX_STAT_ACK;
459 ieee80211_tx_status_irqsafe(ar->hw, skb);
460
461 return ret;
462}
463
413static int ath10k_wmi_event_scan(struct ath10k *ar, struct sk_buff *skb) 464static int ath10k_wmi_event_scan(struct ath10k *ar, struct sk_buff *skb)
414{ 465{
415 struct wmi_scan_event *event = (struct wmi_scan_event *)skb->data; 466 struct wmi_scan_event *event = (struct wmi_scan_event *)skb->data;