Commit f2f6ecab authored by Michal Kazior's avatar Michal Kazior Committed by Kalle Valo

ath10k: refactor tx code

This prepares the code for future reuse with
ieee80211_txq and wake_tx_queue() in mind.
Signed-off-by: default avatarMichal Kazior <michal.kazior@tieto.com>
Signed-off-by: default avatarKalle Valo <kvalo@qca.qualcomm.com>
parent 89ef41bf
...@@ -3271,6 +3271,26 @@ static void ath10k_tx_h_add_p2p_noa_ie(struct ath10k *ar, ...@@ -3271,6 +3271,26 @@ static void ath10k_tx_h_add_p2p_noa_ie(struct ath10k *ar,
} }
} }
static void ath10k_mac_tx_h_fill_cb(struct ath10k *ar,
struct ieee80211_vif *vif,
struct sk_buff *skb)
{
struct ieee80211_hdr *hdr = (void *)skb->data;
struct ath10k_skb_cb *cb = ATH10K_SKB_CB(skb);
cb->flags = 0;
if (!ath10k_tx_h_use_hwcrypto(vif, skb))
cb->flags |= ATH10K_SKB_F_NO_HWCRYPT;
if (ieee80211_is_mgmt(hdr->frame_control))
cb->flags |= ATH10K_SKB_F_MGMT;
if (ieee80211_is_data_qos(hdr->frame_control))
cb->flags |= ATH10K_SKB_F_QOS;
cb->vif = vif;
}
bool ath10k_mac_tx_frm_has_freq(struct ath10k *ar) bool ath10k_mac_tx_frm_has_freq(struct ath10k *ar)
{ {
/* FIXME: Not really sure since when the behaviour changed. At some /* FIXME: Not really sure since when the behaviour changed. At some
...@@ -3306,8 +3326,9 @@ static int ath10k_mac_tx_wmi_mgmt(struct ath10k *ar, struct sk_buff *skb) ...@@ -3306,8 +3326,9 @@ static int ath10k_mac_tx_wmi_mgmt(struct ath10k *ar, struct sk_buff *skb)
return ret; return ret;
} }
static void ath10k_mac_tx(struct ath10k *ar, enum ath10k_hw_txrx_mode txmode, static int ath10k_mac_tx_submit(struct ath10k *ar,
struct sk_buff *skb) enum ath10k_hw_txrx_mode txmode,
struct sk_buff *skb)
{ {
struct ath10k_htt *htt = &ar->htt; struct ath10k_htt *htt = &ar->htt;
int ret = 0; int ret = 0;
...@@ -3334,6 +3355,63 @@ static void ath10k_mac_tx(struct ath10k *ar, enum ath10k_hw_txrx_mode txmode, ...@@ -3334,6 +3355,63 @@ static void ath10k_mac_tx(struct ath10k *ar, enum ath10k_hw_txrx_mode txmode,
ret); ret);
ieee80211_free_txskb(ar->hw, skb); ieee80211_free_txskb(ar->hw, skb);
} }
return ret;
}
/* This function consumes the sk_buff regardless of return value as far as
* caller is concerned so no freeing is necessary afterwards.
*/
static int ath10k_mac_tx(struct ath10k *ar,
struct ieee80211_vif *vif,
struct ieee80211_sta *sta,
enum ath10k_hw_txrx_mode txmode,
struct sk_buff *skb)
{
struct ieee80211_hw *hw = ar->hw;
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
int ret;
/* We should disable CCK RATE due to P2P */
if (info->flags & IEEE80211_TX_CTL_NO_CCK_RATE)
ath10k_dbg(ar, ATH10K_DBG_MAC, "IEEE80211_TX_CTL_NO_CCK_RATE\n");
switch (txmode) {
case ATH10K_HW_TXRX_MGMT:
case ATH10K_HW_TXRX_NATIVE_WIFI:
ath10k_tx_h_nwifi(hw, skb);
ath10k_tx_h_add_p2p_noa_ie(ar, vif, skb);
ath10k_tx_h_seq_no(vif, skb);
break;
case ATH10K_HW_TXRX_ETHERNET:
ath10k_tx_h_8023(skb);
break;
case ATH10K_HW_TXRX_RAW:
if (!test_bit(ATH10K_FLAG_RAW_MODE, &ar->dev_flags)) {
WARN_ON_ONCE(1);
ieee80211_free_txskb(hw, skb);
return -ENOTSUPP;
}
}
if (info->flags & IEEE80211_TX_CTL_TX_OFFCHAN) {
if (!ath10k_mac_tx_frm_has_freq(ar)) {
ath10k_dbg(ar, ATH10K_DBG_MAC, "queued offchannel skb %p\n",
skb);
skb_queue_tail(&ar->offchan_tx_queue, skb);
ieee80211_queue_work(hw, &ar->offchan_tx_work);
return 0;
}
}
ret = ath10k_mac_tx_submit(ar, txmode, skb);
if (ret) {
ath10k_warn(ar, "failed to submit frame: %d\n", ret);
return ret;
}
return 0;
} }
void ath10k_offchan_tx_purge(struct ath10k *ar) void ath10k_offchan_tx_purge(struct ath10k *ar)
...@@ -3354,12 +3432,12 @@ void ath10k_offchan_tx_work(struct work_struct *work) ...@@ -3354,12 +3432,12 @@ void ath10k_offchan_tx_work(struct work_struct *work)
struct ath10k *ar = container_of(work, struct ath10k, offchan_tx_work); struct ath10k *ar = container_of(work, struct ath10k, offchan_tx_work);
struct ath10k_peer *peer; struct ath10k_peer *peer;
struct ath10k_vif *arvif; struct ath10k_vif *arvif;
enum ath10k_hw_txrx_mode txmode;
struct ieee80211_hdr *hdr; struct ieee80211_hdr *hdr;
struct ieee80211_vif *vif; struct ieee80211_vif *vif;
struct ieee80211_sta *sta; struct ieee80211_sta *sta;
struct sk_buff *skb; struct sk_buff *skb;
const u8 *peer_addr; const u8 *peer_addr;
enum ath10k_hw_txrx_mode txmode;
int vdev_id; int vdev_id;
int ret; int ret;
unsigned long time_left; unsigned long time_left;
...@@ -3424,7 +3502,12 @@ void ath10k_offchan_tx_work(struct work_struct *work) ...@@ -3424,7 +3502,12 @@ void ath10k_offchan_tx_work(struct work_struct *work)
txmode = ath10k_mac_tx_h_get_txmode(ar, vif, sta, skb); txmode = ath10k_mac_tx_h_get_txmode(ar, vif, sta, skb);
ath10k_mac_tx(ar, txmode, skb); ret = ath10k_mac_tx(ar, vif, sta, txmode, skb);
if (ret) {
ath10k_warn(ar, "failed to transmit offchannel frame: %d\n",
ret);
/* not serious */
}
time_left = time_left =
wait_for_completion_timeout(&ar->offchan_tx_completed, 3 * HZ); wait_for_completion_timeout(&ar->offchan_tx_completed, 3 * HZ);
...@@ -3638,66 +3721,24 @@ static int ath10k_start_scan(struct ath10k *ar, ...@@ -3638,66 +3721,24 @@ static int ath10k_start_scan(struct ath10k *ar,
/* mac80211 callbacks */ /* mac80211 callbacks */
/**********************/ /**********************/
static void ath10k_tx(struct ieee80211_hw *hw, static void ath10k_mac_op_tx(struct ieee80211_hw *hw,
struct ieee80211_tx_control *control, struct ieee80211_tx_control *control,
struct sk_buff *skb) struct sk_buff *skb)
{ {
struct ath10k *ar = hw->priv; struct ath10k *ar = hw->priv;
struct ath10k_skb_cb *skb_cb = ATH10K_SKB_CB(skb);
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
struct ieee80211_vif *vif = info->control.vif; struct ieee80211_vif *vif = info->control.vif;
struct ieee80211_sta *sta = control->sta; struct ieee80211_sta *sta = control->sta;
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
enum ath10k_hw_txrx_mode txmode; enum ath10k_hw_txrx_mode txmode;
int ret;
/* We should disable CCK RATE due to P2P */ ath10k_mac_tx_h_fill_cb(ar, vif, skb);
if (info->flags & IEEE80211_TX_CTL_NO_CCK_RATE)
ath10k_dbg(ar, ATH10K_DBG_MAC, "IEEE80211_TX_CTL_NO_CCK_RATE\n");
txmode = ath10k_mac_tx_h_get_txmode(ar, vif, sta, skb); txmode = ath10k_mac_tx_h_get_txmode(ar, vif, sta, skb);
skb_cb->flags = 0; ret = ath10k_mac_tx(ar, vif, sta, txmode, skb);
if (!ath10k_tx_h_use_hwcrypto(vif, skb)) if (ret)
skb_cb->flags |= ATH10K_SKB_F_NO_HWCRYPT; ath10k_warn(ar, "failed to transmit frame: %d\n", ret);
if (ieee80211_is_mgmt(hdr->frame_control))
skb_cb->flags |= ATH10K_SKB_F_MGMT;
if (ieee80211_is_data_qos(hdr->frame_control))
skb_cb->flags |= ATH10K_SKB_F_QOS;
skb_cb->vif = vif;
switch (txmode) {
case ATH10K_HW_TXRX_MGMT:
case ATH10K_HW_TXRX_NATIVE_WIFI:
ath10k_tx_h_nwifi(hw, skb);
ath10k_tx_h_add_p2p_noa_ie(ar, vif, skb);
ath10k_tx_h_seq_no(vif, skb);
break;
case ATH10K_HW_TXRX_ETHERNET:
ath10k_tx_h_8023(skb);
break;
case ATH10K_HW_TXRX_RAW:
if (!test_bit(ATH10K_FLAG_RAW_MODE, &ar->dev_flags)) {
WARN_ON_ONCE(1);
ieee80211_free_txskb(hw, skb);
return;
}
}
if (info->flags & IEEE80211_TX_CTL_TX_OFFCHAN) {
if (!ath10k_mac_tx_frm_has_freq(ar)) {
ath10k_dbg(ar, ATH10K_DBG_MAC, "queued offchannel skb %p\n",
skb);
skb_queue_tail(&ar->offchan_tx_queue, skb);
ieee80211_queue_work(hw, &ar->offchan_tx_work);
return;
}
}
ath10k_mac_tx(ar, txmode, skb);
} }
/* Must not be called with conf_mutex held as workers can use that also. */ /* Must not be called with conf_mutex held as workers can use that also. */
...@@ -6807,7 +6848,7 @@ ath10k_mac_op_switch_vif_chanctx(struct ieee80211_hw *hw, ...@@ -6807,7 +6848,7 @@ ath10k_mac_op_switch_vif_chanctx(struct ieee80211_hw *hw,
} }
static const struct ieee80211_ops ath10k_ops = { static const struct ieee80211_ops ath10k_ops = {
.tx = ath10k_tx, .tx = ath10k_mac_op_tx,
.start = ath10k_start, .start = ath10k_start,
.stop = ath10k_stop, .stop = ath10k_stop,
.config = ath10k_config, .config = ath10k_config,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment