diff options
-rw-r--r-- | drivers/net/wireless/p54/p54common.c | 73 | ||||
-rw-r--r-- | drivers/net/wireless/p54/p54common.h | 2 |
2 files changed, 49 insertions, 26 deletions
diff --git a/drivers/net/wireless/p54/p54common.c b/drivers/net/wireless/p54/p54common.c index 602392628e4e..de92b58d4508 100644 --- a/drivers/net/wireless/p54/p54common.c +++ b/drivers/net/wireless/p54/p54common.c | |||
@@ -652,6 +652,10 @@ static void p54_rx_frame_sent(struct ieee80211_hw *dev, struct sk_buff *skb) | |||
652 | __skb_unlink(entry, &priv->tx_queue); | 652 | __skb_unlink(entry, &priv->tx_queue); |
653 | spin_unlock_irqrestore(&priv->tx_queue.lock, flags); | 653 | spin_unlock_irqrestore(&priv->tx_queue.lock, flags); |
654 | 654 | ||
655 | entry_hdr = (struct p54_hdr *) entry->data; | ||
656 | entry_data = (struct p54_tx_data *) entry_hdr->data; | ||
657 | priv->tx_stats[entry_data->hw_queue].len--; | ||
658 | |||
655 | if (unlikely(entry == priv->cached_beacon)) { | 659 | if (unlikely(entry == priv->cached_beacon)) { |
656 | kfree_skb(entry); | 660 | kfree_skb(entry); |
657 | priv->cached_beacon = NULL; | 661 | priv->cached_beacon = NULL; |
@@ -668,8 +672,6 @@ static void p54_rx_frame_sent(struct ieee80211_hw *dev, struct sk_buff *skb) | |||
668 | BUILD_BUG_ON(offsetof(struct ieee80211_tx_info, | 672 | BUILD_BUG_ON(offsetof(struct ieee80211_tx_info, |
669 | status.ampdu_ack_len) != 23); | 673 | status.ampdu_ack_len) != 23); |
670 | 674 | ||
671 | entry_hdr = (struct p54_hdr *) entry->data; | ||
672 | entry_data = (struct p54_tx_data *) entry_hdr->data; | ||
673 | if (entry_hdr->flags & cpu_to_le16(P54_HDR_FLAG_DATA_ALIGN)) | 675 | if (entry_hdr->flags & cpu_to_le16(P54_HDR_FLAG_DATA_ALIGN)) |
674 | pad = entry_data->align[0]; | 676 | pad = entry_data->align[0]; |
675 | 677 | ||
@@ -687,7 +689,6 @@ static void p54_rx_frame_sent(struct ieee80211_hw *dev, struct sk_buff *skb) | |||
687 | } | 689 | } |
688 | } | 690 | } |
689 | 691 | ||
690 | priv->tx_stats[entry_data->hw_queue].len--; | ||
691 | if (!(info->flags & IEEE80211_TX_CTL_NO_ACK) && | 692 | if (!(info->flags & IEEE80211_TX_CTL_NO_ACK) && |
692 | (!payload->status)) | 693 | (!payload->status)) |
693 | info->flags |= IEEE80211_TX_STAT_ACK; | 694 | info->flags |= IEEE80211_TX_STAT_ACK; |
@@ -1004,6 +1005,38 @@ static int p54_sta_unlock(struct ieee80211_hw *dev, u8 *addr) | |||
1004 | return 0; | 1005 | return 0; |
1005 | } | 1006 | } |
1006 | 1007 | ||
1008 | static void p54_sta_notify_ps(struct ieee80211_hw *dev, | ||
1009 | enum sta_notify_ps_cmd notify_cmd, | ||
1010 | struct ieee80211_sta *sta) | ||
1011 | { | ||
1012 | switch (notify_cmd) { | ||
1013 | case STA_NOTIFY_AWAKE: | ||
1014 | p54_sta_unlock(dev, sta->addr); | ||
1015 | break; | ||
1016 | default: | ||
1017 | break; | ||
1018 | } | ||
1019 | } | ||
1020 | |||
1021 | static void p54_sta_notify(struct ieee80211_hw *dev, struct ieee80211_vif *vif, | ||
1022 | enum sta_notify_cmd notify_cmd, | ||
1023 | struct ieee80211_sta *sta) | ||
1024 | { | ||
1025 | switch (notify_cmd) { | ||
1026 | case STA_NOTIFY_ADD: | ||
1027 | case STA_NOTIFY_REMOVE: | ||
1028 | /* | ||
1029 | * Notify the firmware that we don't want or we don't | ||
1030 | * need to buffer frames for this station anymore. | ||
1031 | */ | ||
1032 | |||
1033 | p54_sta_unlock(dev, sta->addr); | ||
1034 | break; | ||
1035 | default: | ||
1036 | break; | ||
1037 | } | ||
1038 | } | ||
1039 | |||
1007 | static int p54_tx_cancel(struct ieee80211_hw *dev, struct sk_buff *entry) | 1040 | static int p54_tx_cancel(struct ieee80211_hw *dev, struct sk_buff *entry) |
1008 | { | 1041 | { |
1009 | struct p54_common *priv = dev->priv; | 1042 | struct p54_common *priv = dev->priv; |
@@ -1069,7 +1102,7 @@ static int p54_tx_fill(struct ieee80211_hw *dev, struct sk_buff *skb, | |||
1069 | if (info->control.sta) | 1102 | if (info->control.sta) |
1070 | *aid = info->control.sta->aid; | 1103 | *aid = info->control.sta->aid; |
1071 | else | 1104 | else |
1072 | *flags = P54_HDR_FLAG_DATA_OUT_NOCANCEL; | 1105 | *flags |= P54_HDR_FLAG_DATA_OUT_NOCANCEL; |
1073 | } | 1106 | } |
1074 | return ret; | 1107 | return ret; |
1075 | } | 1108 | } |
@@ -1082,7 +1115,7 @@ static int p54_tx(struct ieee80211_hw *dev, struct sk_buff *skb) | |||
1082 | struct p54_hdr *hdr; | 1115 | struct p54_hdr *hdr; |
1083 | struct p54_tx_data *txhdr; | 1116 | struct p54_tx_data *txhdr; |
1084 | size_t padding, len, tim_len = 0; | 1117 | size_t padding, len, tim_len = 0; |
1085 | int i, j, ridx; | 1118 | int i, j, ridx, ret; |
1086 | u16 hdr_flags = 0, aid = 0; | 1119 | u16 hdr_flags = 0, aid = 0; |
1087 | u8 rate, queue; | 1120 | u8 rate, queue; |
1088 | u8 cts_rate = 0x20; | 1121 | u8 cts_rate = 0x20; |
@@ -1092,30 +1125,18 @@ static int p54_tx(struct ieee80211_hw *dev, struct sk_buff *skb) | |||
1092 | 1125 | ||
1093 | queue = skb_get_queue_mapping(skb); | 1126 | queue = skb_get_queue_mapping(skb); |
1094 | 1127 | ||
1095 | if (p54_tx_fill(dev, skb, info, &queue, &tim_len, &hdr_flags, &aid)) { | 1128 | ret = p54_tx_fill(dev, skb, info, &queue, &tim_len, &hdr_flags, &aid); |
1096 | current_queue = &priv->tx_stats[queue]; | 1129 | current_queue = &priv->tx_stats[queue]; |
1097 | if (unlikely(current_queue->len > current_queue->limit)) | 1130 | if (unlikely((current_queue->len > current_queue->limit) && ret)) |
1098 | return NETDEV_TX_BUSY; | 1131 | return NETDEV_TX_BUSY; |
1099 | current_queue->len++; | 1132 | current_queue->len++; |
1100 | current_queue->count++; | 1133 | current_queue->count++; |
1101 | if (current_queue->len == current_queue->limit) | 1134 | if ((current_queue->len == current_queue->limit) && ret) |
1102 | ieee80211_stop_queue(dev, skb_get_queue_mapping(skb)); | 1135 | ieee80211_stop_queue(dev, skb_get_queue_mapping(skb)); |
1103 | } | ||
1104 | 1136 | ||
1105 | padding = (unsigned long)(skb->data - (sizeof(*hdr) + sizeof(*txhdr))) & 3; | 1137 | padding = (unsigned long)(skb->data - (sizeof(*hdr) + sizeof(*txhdr))) & 3; |
1106 | len = skb->len; | 1138 | len = skb->len; |
1107 | 1139 | ||
1108 | if (info->flags & IEEE80211_TX_CTL_CLEAR_PS_FILT) { | ||
1109 | if (info->control.sta) | ||
1110 | if (p54_sta_unlock(dev, info->control.sta->addr)) { | ||
1111 | if (current_queue) { | ||
1112 | current_queue->len--; | ||
1113 | current_queue->count--; | ||
1114 | } | ||
1115 | return NETDEV_TX_BUSY; | ||
1116 | } | ||
1117 | } | ||
1118 | |||
1119 | txhdr = (struct p54_tx_data *) skb_push(skb, sizeof(*txhdr) + padding); | 1140 | txhdr = (struct p54_tx_data *) skb_push(skb, sizeof(*txhdr) + padding); |
1120 | hdr = (struct p54_hdr *) skb_push(skb, sizeof(*hdr)); | 1141 | hdr = (struct p54_hdr *) skb_push(skb, sizeof(*hdr)); |
1121 | 1142 | ||
@@ -1834,6 +1855,8 @@ static const struct ieee80211_ops p54_ops = { | |||
1834 | .add_interface = p54_add_interface, | 1855 | .add_interface = p54_add_interface, |
1835 | .remove_interface = p54_remove_interface, | 1856 | .remove_interface = p54_remove_interface, |
1836 | .set_tim = p54_set_tim, | 1857 | .set_tim = p54_set_tim, |
1858 | .sta_notify_ps = p54_sta_notify_ps, | ||
1859 | .sta_notify = p54_sta_notify, | ||
1837 | .config = p54_config, | 1860 | .config = p54_config, |
1838 | .config_interface = p54_config_interface, | 1861 | .config_interface = p54_config_interface, |
1839 | .bss_info_changed = p54_bss_info_changed, | 1862 | .bss_info_changed = p54_bss_info_changed, |
diff --git a/drivers/net/wireless/p54/p54common.h b/drivers/net/wireless/p54/p54common.h index 3419f16be938..d292ffbec08c 100644 --- a/drivers/net/wireless/p54/p54common.h +++ b/drivers/net/wireless/p54/p54common.h | |||
@@ -302,7 +302,7 @@ enum p54_frame_sent_status { | |||
302 | P54_TX_OK = 0, | 302 | P54_TX_OK = 0, |
303 | P54_TX_FAILED, | 303 | P54_TX_FAILED, |
304 | P54_TX_PSM, | 304 | P54_TX_PSM, |
305 | P54_TX_PSM_CANCELLED | 305 | P54_TX_PSM_CANCELLED = 4 |
306 | }; | 306 | }; |
307 | 307 | ||
308 | struct p54_frame_sent { | 308 | struct p54_frame_sent { |