Commit cbbba30f authored by Kalle Valo's avatar Kalle Valo

Merge tag 'iwlwifi-for-kalle-2016-05-04' of...

Merge tag 'iwlwifi-for-kalle-2016-05-04' of https://git.kernel.org/pub/scm/linux/kernel/git/iwlwifi/iwlwifi-fixes

* fix P2P rates (and possibly other issues)
parents e2841ea9 5c08b0f5
...@@ -105,6 +105,7 @@ void iwl_mvm_set_tx_cmd(struct iwl_mvm *mvm, struct sk_buff *skb, ...@@ -105,6 +105,7 @@ void iwl_mvm_set_tx_cmd(struct iwl_mvm *mvm, struct sk_buff *skb,
struct iwl_tx_cmd *tx_cmd, struct iwl_tx_cmd *tx_cmd,
struct ieee80211_tx_info *info, u8 sta_id) struct ieee80211_tx_info *info, u8 sta_id)
{ {
struct ieee80211_tx_info *skb_info = IEEE80211_SKB_CB(skb);
struct ieee80211_hdr *hdr = (void *)skb->data; struct ieee80211_hdr *hdr = (void *)skb->data;
__le16 fc = hdr->frame_control; __le16 fc = hdr->frame_control;
u32 tx_flags = le32_to_cpu(tx_cmd->tx_flags); u32 tx_flags = le32_to_cpu(tx_cmd->tx_flags);
...@@ -185,7 +186,7 @@ void iwl_mvm_set_tx_cmd(struct iwl_mvm *mvm, struct sk_buff *skb, ...@@ -185,7 +186,7 @@ void iwl_mvm_set_tx_cmd(struct iwl_mvm *mvm, struct sk_buff *skb,
tx_cmd->tx_flags = cpu_to_le32(tx_flags); tx_cmd->tx_flags = cpu_to_le32(tx_flags);
/* Total # bytes to be transmitted */ /* Total # bytes to be transmitted */
tx_cmd->len = cpu_to_le16((u16)skb->len + tx_cmd->len = cpu_to_le16((u16)skb->len +
(uintptr_t)info->driver_data[0]); (uintptr_t)skb_info->driver_data[0]);
tx_cmd->next_frame_len = 0; tx_cmd->next_frame_len = 0;
tx_cmd->life_time = cpu_to_le32(TX_CMD_LIFE_TIME_INFINITE); tx_cmd->life_time = cpu_to_le32(TX_CMD_LIFE_TIME_INFINITE);
tx_cmd->sta_id = sta_id; tx_cmd->sta_id = sta_id;
...@@ -327,10 +328,11 @@ static void iwl_mvm_set_tx_cmd_crypto(struct iwl_mvm *mvm, ...@@ -327,10 +328,11 @@ static void iwl_mvm_set_tx_cmd_crypto(struct iwl_mvm *mvm,
*/ */
static struct iwl_device_cmd * static struct iwl_device_cmd *
iwl_mvm_set_tx_params(struct iwl_mvm *mvm, struct sk_buff *skb, iwl_mvm_set_tx_params(struct iwl_mvm *mvm, struct sk_buff *skb,
int hdrlen, struct ieee80211_sta *sta, u8 sta_id) struct ieee80211_tx_info *info, int hdrlen,
struct ieee80211_sta *sta, u8 sta_id)
{ {
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); struct ieee80211_tx_info *skb_info = IEEE80211_SKB_CB(skb);
struct iwl_device_cmd *dev_cmd; struct iwl_device_cmd *dev_cmd;
struct iwl_tx_cmd *tx_cmd; struct iwl_tx_cmd *tx_cmd;
...@@ -350,10 +352,10 @@ iwl_mvm_set_tx_params(struct iwl_mvm *mvm, struct sk_buff *skb, ...@@ -350,10 +352,10 @@ iwl_mvm_set_tx_params(struct iwl_mvm *mvm, struct sk_buff *skb,
iwl_mvm_set_tx_cmd_rate(mvm, tx_cmd, info, sta, hdr->frame_control); iwl_mvm_set_tx_cmd_rate(mvm, tx_cmd, info, sta, hdr->frame_control);
memset(&info->status, 0, sizeof(info->status)); memset(&skb_info->status, 0, sizeof(skb_info->status));
memset(info->driver_data, 0, sizeof(info->driver_data)); memset(skb_info->driver_data, 0, sizeof(skb_info->driver_data));
info->driver_data[1] = dev_cmd; skb_info->driver_data[1] = dev_cmd;
return dev_cmd; return dev_cmd;
} }
...@@ -361,22 +363,25 @@ iwl_mvm_set_tx_params(struct iwl_mvm *mvm, struct sk_buff *skb, ...@@ -361,22 +363,25 @@ iwl_mvm_set_tx_params(struct iwl_mvm *mvm, struct sk_buff *skb,
int iwl_mvm_tx_skb_non_sta(struct iwl_mvm *mvm, struct sk_buff *skb) int iwl_mvm_tx_skb_non_sta(struct iwl_mvm *mvm, struct sk_buff *skb)
{ {
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); struct ieee80211_tx_info *skb_info = IEEE80211_SKB_CB(skb);
struct ieee80211_tx_info info;
struct iwl_device_cmd *dev_cmd; struct iwl_device_cmd *dev_cmd;
struct iwl_tx_cmd *tx_cmd; struct iwl_tx_cmd *tx_cmd;
u8 sta_id; u8 sta_id;
int hdrlen = ieee80211_hdrlen(hdr->frame_control); int hdrlen = ieee80211_hdrlen(hdr->frame_control);
if (WARN_ON_ONCE(info->flags & IEEE80211_TX_CTL_AMPDU)) memcpy(&info, skb->cb, sizeof(info));
if (WARN_ON_ONCE(info.flags & IEEE80211_TX_CTL_AMPDU))
return -1; return -1;
if (WARN_ON_ONCE(info->flags & IEEE80211_TX_CTL_SEND_AFTER_DTIM && if (WARN_ON_ONCE(info.flags & IEEE80211_TX_CTL_SEND_AFTER_DTIM &&
(!info->control.vif || (!info.control.vif ||
info->hw_queue != info->control.vif->cab_queue))) info.hw_queue != info.control.vif->cab_queue)))
return -1; return -1;
/* This holds the amsdu headers length */ /* This holds the amsdu headers length */
info->driver_data[0] = (void *)(uintptr_t)0; skb_info->driver_data[0] = (void *)(uintptr_t)0;
/* /*
* IWL_MVM_OFFCHANNEL_QUEUE is used for ROC packets that can be used * IWL_MVM_OFFCHANNEL_QUEUE is used for ROC packets that can be used
...@@ -385,7 +390,7 @@ int iwl_mvm_tx_skb_non_sta(struct iwl_mvm *mvm, struct sk_buff *skb) ...@@ -385,7 +390,7 @@ int iwl_mvm_tx_skb_non_sta(struct iwl_mvm *mvm, struct sk_buff *skb)
* and hence needs to be sent on the aux queue * and hence needs to be sent on the aux queue
*/ */
if (IEEE80211_SKB_CB(skb)->hw_queue == IWL_MVM_OFFCHANNEL_QUEUE && if (IEEE80211_SKB_CB(skb)->hw_queue == IWL_MVM_OFFCHANNEL_QUEUE &&
info->control.vif->type == NL80211_IFTYPE_STATION) info.control.vif->type == NL80211_IFTYPE_STATION)
IEEE80211_SKB_CB(skb)->hw_queue = mvm->aux_queue; IEEE80211_SKB_CB(skb)->hw_queue = mvm->aux_queue;
/* /*
...@@ -398,14 +403,14 @@ int iwl_mvm_tx_skb_non_sta(struct iwl_mvm *mvm, struct sk_buff *skb) ...@@ -398,14 +403,14 @@ int iwl_mvm_tx_skb_non_sta(struct iwl_mvm *mvm, struct sk_buff *skb)
* AUX station. * AUX station.
*/ */
sta_id = mvm->aux_sta.sta_id; sta_id = mvm->aux_sta.sta_id;
if (info->control.vif) { if (info.control.vif) {
struct iwl_mvm_vif *mvmvif = struct iwl_mvm_vif *mvmvif =
iwl_mvm_vif_from_mac80211(info->control.vif); iwl_mvm_vif_from_mac80211(info.control.vif);
if (info->control.vif->type == NL80211_IFTYPE_P2P_DEVICE || if (info.control.vif->type == NL80211_IFTYPE_P2P_DEVICE ||
info->control.vif->type == NL80211_IFTYPE_AP) info.control.vif->type == NL80211_IFTYPE_AP)
sta_id = mvmvif->bcast_sta.sta_id; sta_id = mvmvif->bcast_sta.sta_id;
else if (info->control.vif->type == NL80211_IFTYPE_STATION && else if (info.control.vif->type == NL80211_IFTYPE_STATION &&
is_multicast_ether_addr(hdr->addr1)) { is_multicast_ether_addr(hdr->addr1)) {
u8 ap_sta_id = ACCESS_ONCE(mvmvif->ap_sta_id); u8 ap_sta_id = ACCESS_ONCE(mvmvif->ap_sta_id);
...@@ -414,19 +419,18 @@ int iwl_mvm_tx_skb_non_sta(struct iwl_mvm *mvm, struct sk_buff *skb) ...@@ -414,19 +419,18 @@ int iwl_mvm_tx_skb_non_sta(struct iwl_mvm *mvm, struct sk_buff *skb)
} }
} }
IWL_DEBUG_TX(mvm, "station Id %d, queue=%d\n", sta_id, info->hw_queue); IWL_DEBUG_TX(mvm, "station Id %d, queue=%d\n", sta_id, info.hw_queue);
dev_cmd = iwl_mvm_set_tx_params(mvm, skb, hdrlen, NULL, sta_id); dev_cmd = iwl_mvm_set_tx_params(mvm, skb, &info, hdrlen, NULL, sta_id);
if (!dev_cmd) if (!dev_cmd)
return -1; return -1;
/* From now on, we cannot access info->control */
tx_cmd = (struct iwl_tx_cmd *)dev_cmd->payload; tx_cmd = (struct iwl_tx_cmd *)dev_cmd->payload;
/* Copy MAC header from skb into command buffer */ /* Copy MAC header from skb into command buffer */
memcpy(tx_cmd->hdr, hdr, hdrlen); memcpy(tx_cmd->hdr, hdr, hdrlen);
if (iwl_trans_tx(mvm->trans, skb, dev_cmd, info->hw_queue)) { if (iwl_trans_tx(mvm->trans, skb, dev_cmd, info.hw_queue)) {
iwl_trans_free_tx_cmd(mvm->trans, dev_cmd); iwl_trans_free_tx_cmd(mvm->trans, dev_cmd);
return -1; return -1;
} }
...@@ -445,11 +449,11 @@ int iwl_mvm_tx_skb_non_sta(struct iwl_mvm *mvm, struct sk_buff *skb) ...@@ -445,11 +449,11 @@ int iwl_mvm_tx_skb_non_sta(struct iwl_mvm *mvm, struct sk_buff *skb)
#ifdef CONFIG_INET #ifdef CONFIG_INET
static int iwl_mvm_tx_tso(struct iwl_mvm *mvm, struct sk_buff *skb, static int iwl_mvm_tx_tso(struct iwl_mvm *mvm, struct sk_buff *skb,
struct ieee80211_tx_info *info,
struct ieee80211_sta *sta, struct ieee80211_sta *sta,
struct sk_buff_head *mpdus_skb) struct sk_buff_head *mpdus_skb)
{ {
struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta); struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta);
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
struct ieee80211_hdr *hdr = (void *)skb->data; struct ieee80211_hdr *hdr = (void *)skb->data;
unsigned int mss = skb_shinfo(skb)->gso_size; unsigned int mss = skb_shinfo(skb)->gso_size;
struct sk_buff *tmp, *next; struct sk_buff *tmp, *next;
...@@ -544,6 +548,8 @@ static int iwl_mvm_tx_tso(struct iwl_mvm *mvm, struct sk_buff *skb, ...@@ -544,6 +548,8 @@ static int iwl_mvm_tx_tso(struct iwl_mvm *mvm, struct sk_buff *skb,
/* This skb fits in one single A-MSDU */ /* This skb fits in one single A-MSDU */
if (num_subframes * mss >= tcp_payload_len) { if (num_subframes * mss >= tcp_payload_len) {
struct ieee80211_tx_info *skb_info = IEEE80211_SKB_CB(skb);
/* /*
* Compute the length of all the data added for the A-MSDU. * Compute the length of all the data added for the A-MSDU.
* This will be used to compute the length to write in the TX * This will be used to compute the length to write in the TX
...@@ -552,11 +558,10 @@ static int iwl_mvm_tx_tso(struct iwl_mvm *mvm, struct sk_buff *skb, ...@@ -552,11 +558,10 @@ static int iwl_mvm_tx_tso(struct iwl_mvm *mvm, struct sk_buff *skb,
* already had one set of SNAP / IP / TCP headers. * already had one set of SNAP / IP / TCP headers.
*/ */
num_subframes = DIV_ROUND_UP(tcp_payload_len, mss); num_subframes = DIV_ROUND_UP(tcp_payload_len, mss);
info = IEEE80211_SKB_CB(skb);
amsdu_add = num_subframes * sizeof(struct ethhdr) + amsdu_add = num_subframes * sizeof(struct ethhdr) +
(num_subframes - 1) * (snap_ip_tcp + pad); (num_subframes - 1) * (snap_ip_tcp + pad);
/* This holds the amsdu headers length */ /* This holds the amsdu headers length */
info->driver_data[0] = (void *)(uintptr_t)amsdu_add; skb_info->driver_data[0] = (void *)(uintptr_t)amsdu_add;
__skb_queue_tail(mpdus_skb, skb); __skb_queue_tail(mpdus_skb, skb);
return 0; return 0;
...@@ -596,11 +601,14 @@ static int iwl_mvm_tx_tso(struct iwl_mvm *mvm, struct sk_buff *skb, ...@@ -596,11 +601,14 @@ static int iwl_mvm_tx_tso(struct iwl_mvm *mvm, struct sk_buff *skb,
ip_hdr(tmp)->id = htons(ip_base_id + i * num_subframes); ip_hdr(tmp)->id = htons(ip_base_id + i * num_subframes);
if (tcp_payload_len > mss) { if (tcp_payload_len > mss) {
struct ieee80211_tx_info *skb_info =
IEEE80211_SKB_CB(tmp);
num_subframes = DIV_ROUND_UP(tcp_payload_len, mss); num_subframes = DIV_ROUND_UP(tcp_payload_len, mss);
info = IEEE80211_SKB_CB(tmp);
amsdu_add = num_subframes * sizeof(struct ethhdr) + amsdu_add = num_subframes * sizeof(struct ethhdr) +
(num_subframes - 1) * (snap_ip_tcp + pad); (num_subframes - 1) * (snap_ip_tcp + pad);
info->driver_data[0] = (void *)(uintptr_t)amsdu_add; skb_info->driver_data[0] =
(void *)(uintptr_t)amsdu_add;
skb_shinfo(tmp)->gso_size = mss; skb_shinfo(tmp)->gso_size = mss;
} else { } else {
qc = ieee80211_get_qos_ctl((void *)tmp->data); qc = ieee80211_get_qos_ctl((void *)tmp->data);
...@@ -622,6 +630,7 @@ static int iwl_mvm_tx_tso(struct iwl_mvm *mvm, struct sk_buff *skb, ...@@ -622,6 +630,7 @@ static int iwl_mvm_tx_tso(struct iwl_mvm *mvm, struct sk_buff *skb,
} }
#else /* CONFIG_INET */ #else /* CONFIG_INET */
static int iwl_mvm_tx_tso(struct iwl_mvm *mvm, struct sk_buff *skb, static int iwl_mvm_tx_tso(struct iwl_mvm *mvm, struct sk_buff *skb,
struct ieee80211_tx_info *info,
struct ieee80211_sta *sta, struct ieee80211_sta *sta,
struct sk_buff_head *mpdus_skb) struct sk_buff_head *mpdus_skb)
{ {
...@@ -636,10 +645,10 @@ static int iwl_mvm_tx_tso(struct iwl_mvm *mvm, struct sk_buff *skb, ...@@ -636,10 +645,10 @@ static int iwl_mvm_tx_tso(struct iwl_mvm *mvm, struct sk_buff *skb,
* Sets the fields in the Tx cmd that are crypto related * Sets the fields in the Tx cmd that are crypto related
*/ */
static int iwl_mvm_tx_mpdu(struct iwl_mvm *mvm, struct sk_buff *skb, static int iwl_mvm_tx_mpdu(struct iwl_mvm *mvm, struct sk_buff *skb,
struct ieee80211_tx_info *info,
struct ieee80211_sta *sta) struct ieee80211_sta *sta)
{ {
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
struct iwl_mvm_sta *mvmsta; struct iwl_mvm_sta *mvmsta;
struct iwl_device_cmd *dev_cmd; struct iwl_device_cmd *dev_cmd;
struct iwl_tx_cmd *tx_cmd; struct iwl_tx_cmd *tx_cmd;
...@@ -660,7 +669,8 @@ static int iwl_mvm_tx_mpdu(struct iwl_mvm *mvm, struct sk_buff *skb, ...@@ -660,7 +669,8 @@ static int iwl_mvm_tx_mpdu(struct iwl_mvm *mvm, struct sk_buff *skb,
if (WARN_ON_ONCE(mvmsta->sta_id == IWL_MVM_STATION_COUNT)) if (WARN_ON_ONCE(mvmsta->sta_id == IWL_MVM_STATION_COUNT))
return -1; return -1;
dev_cmd = iwl_mvm_set_tx_params(mvm, skb, hdrlen, sta, mvmsta->sta_id); dev_cmd = iwl_mvm_set_tx_params(mvm, skb, info, hdrlen,
sta, mvmsta->sta_id);
if (!dev_cmd) if (!dev_cmd)
goto drop; goto drop;
...@@ -736,7 +746,8 @@ int iwl_mvm_tx_skb(struct iwl_mvm *mvm, struct sk_buff *skb, ...@@ -736,7 +746,8 @@ int iwl_mvm_tx_skb(struct iwl_mvm *mvm, struct sk_buff *skb,
struct ieee80211_sta *sta) struct ieee80211_sta *sta)
{ {
struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta); struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta);
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); struct ieee80211_tx_info *skb_info = IEEE80211_SKB_CB(skb);
struct ieee80211_tx_info info;
struct sk_buff_head mpdus_skbs; struct sk_buff_head mpdus_skbs;
unsigned int payload_len; unsigned int payload_len;
int ret; int ret;
...@@ -747,21 +758,23 @@ int iwl_mvm_tx_skb(struct iwl_mvm *mvm, struct sk_buff *skb, ...@@ -747,21 +758,23 @@ int iwl_mvm_tx_skb(struct iwl_mvm *mvm, struct sk_buff *skb,
if (WARN_ON_ONCE(mvmsta->sta_id == IWL_MVM_STATION_COUNT)) if (WARN_ON_ONCE(mvmsta->sta_id == IWL_MVM_STATION_COUNT))
return -1; return -1;
memcpy(&info, skb->cb, sizeof(info));
/* This holds the amsdu headers length */ /* This holds the amsdu headers length */
info->driver_data[0] = (void *)(uintptr_t)0; skb_info->driver_data[0] = (void *)(uintptr_t)0;
if (!skb_is_gso(skb)) if (!skb_is_gso(skb))
return iwl_mvm_tx_mpdu(mvm, skb, sta); return iwl_mvm_tx_mpdu(mvm, skb, &info, sta);
payload_len = skb_tail_pointer(skb) - skb_transport_header(skb) - payload_len = skb_tail_pointer(skb) - skb_transport_header(skb) -
tcp_hdrlen(skb) + skb->data_len; tcp_hdrlen(skb) + skb->data_len;
if (payload_len <= skb_shinfo(skb)->gso_size) if (payload_len <= skb_shinfo(skb)->gso_size)
return iwl_mvm_tx_mpdu(mvm, skb, sta); return iwl_mvm_tx_mpdu(mvm, skb, &info, sta);
__skb_queue_head_init(&mpdus_skbs); __skb_queue_head_init(&mpdus_skbs);
ret = iwl_mvm_tx_tso(mvm, skb, sta, &mpdus_skbs); ret = iwl_mvm_tx_tso(mvm, skb, &info, sta, &mpdus_skbs);
if (ret) if (ret)
return ret; return ret;
...@@ -771,7 +784,7 @@ int iwl_mvm_tx_skb(struct iwl_mvm *mvm, struct sk_buff *skb, ...@@ -771,7 +784,7 @@ int iwl_mvm_tx_skb(struct iwl_mvm *mvm, struct sk_buff *skb,
while (!skb_queue_empty(&mpdus_skbs)) { while (!skb_queue_empty(&mpdus_skbs)) {
skb = __skb_dequeue(&mpdus_skbs); skb = __skb_dequeue(&mpdus_skbs);
ret = iwl_mvm_tx_mpdu(mvm, skb, sta); ret = iwl_mvm_tx_mpdu(mvm, skb, &info, sta);
if (ret) { if (ret) {
__skb_queue_purge(&mpdus_skbs); __skb_queue_purge(&mpdus_skbs);
return ret; return ret;
......
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