aboutsummaryrefslogtreecommitdiff
path: root/drivers/net/wireless/ath/carl9170
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/wireless/ath/carl9170')
-rw-r--r--drivers/net/wireless/ath/carl9170/carl9170.h3
-rw-r--r--drivers/net/wireless/ath/carl9170/debug.c1
-rw-r--r--drivers/net/wireless/ath/carl9170/main.c23
-rw-r--r--drivers/net/wireless/ath/carl9170/rx.c16
-rw-r--r--drivers/net/wireless/ath/carl9170/tx.c183
-rw-r--r--drivers/net/wireless/ath/carl9170/usb.c10
6 files changed, 129 insertions, 107 deletions
diff --git a/drivers/net/wireless/ath/carl9170/carl9170.h b/drivers/net/wireless/ath/carl9170/carl9170.h
index 9dce106cd6d..8596aba34f9 100644
--- a/drivers/net/wireless/ath/carl9170/carl9170.h
+++ b/drivers/net/wireless/ath/carl9170/carl9170.h
@@ -133,6 +133,9 @@ struct carl9170_sta_tid {
/* Preaggregation reorder queue */
struct sk_buff_head queue;
+
+ struct ieee80211_sta *sta;
+ struct ieee80211_vif *vif;
};
#define CARL9170_QUEUE_TIMEOUT 256
diff --git a/drivers/net/wireless/ath/carl9170/debug.c b/drivers/net/wireless/ath/carl9170/debug.c
index 3d70cd277fd..1c0af9cd9a8 100644
--- a/drivers/net/wireless/ath/carl9170/debug.c
+++ b/drivers/net/wireless/ath/carl9170/debug.c
@@ -37,7 +37,6 @@
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
-#include <linux/init.h>
#include <linux/slab.h>
#include <linux/module.h>
#include <linux/seq_file.h>
diff --git a/drivers/net/wireless/ath/carl9170/main.c b/drivers/net/wireless/ath/carl9170/main.c
index e9010a481df..f8ded84b7be 100644
--- a/drivers/net/wireless/ath/carl9170/main.c
+++ b/drivers/net/wireless/ath/carl9170/main.c
@@ -37,7 +37,6 @@
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
-#include <linux/init.h>
#include <linux/slab.h>
#include <linux/module.h>
#include <linux/etherdevice.h>
@@ -1448,6 +1447,8 @@ static int carl9170_op_ampdu_action(struct ieee80211_hw *hw,
tid_info->state = CARL9170_TID_STATE_PROGRESS;
tid_info->tid = tid;
tid_info->max = sta_info->ampdu_max_len;
+ tid_info->sta = sta;
+ tid_info->vif = vif;
INIT_LIST_HEAD(&tid_info->list);
INIT_LIST_HEAD(&tid_info->tmp_list);
@@ -1706,7 +1707,9 @@ found:
return 0;
}
-static void carl9170_op_flush(struct ieee80211_hw *hw, u32 queues, bool drop)
+static void carl9170_op_flush(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif,
+ u32 queues, bool drop)
{
struct ar9170 *ar = hw->priv;
unsigned int vid;
@@ -1857,7 +1860,9 @@ void *carl9170_alloc(size_t priv_size)
IEEE80211_HW_SUPPORTS_PS |
IEEE80211_HW_PS_NULLFUNC_STACK |
IEEE80211_HW_NEED_DTIM_BEFORE_ASSOC |
- IEEE80211_HW_SIGNAL_DBM;
+ IEEE80211_HW_SUPPORTS_RC_TABLE |
+ IEEE80211_HW_SIGNAL_DBM |
+ IEEE80211_HW_SUPPORTS_HT_CCK_RATES;
if (!modparam_noht) {
/*
@@ -1964,18 +1969,6 @@ static int carl9170_parse_eeprom(struct ar9170 *ar)
return -ENOMEM;
ar->num_channels = chans;
- /*
- * I measured this, a bandswitch takes roughly
- * 135 ms and a frequency switch about 80.
- *
- * FIXME: measure these values again once EEPROM settings
- * are used, that will influence them!
- */
- if (bands == 2)
- ar->hw->channel_change_time = 135 * 1000;
- else
- ar->hw->channel_change_time = 80 * 1000;
-
regulatory->current_rd = le16_to_cpu(ar->eeprom.reg_domain[0]);
/* second part of wiphy init */
diff --git a/drivers/net/wireless/ath/carl9170/rx.c b/drivers/net/wireless/ath/carl9170/rx.c
index 4684dd98949..924135b8e57 100644
--- a/drivers/net/wireless/ath/carl9170/rx.c
+++ b/drivers/net/wireless/ath/carl9170/rx.c
@@ -37,7 +37,6 @@
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
-#include <linux/init.h>
#include <linux/slab.h>
#include <linux/module.h>
#include <linux/etherdevice.h>
@@ -520,6 +519,7 @@ static void carl9170_ps_beacon(struct ar9170 *ar, void *data, unsigned int len)
{
struct ieee80211_hdr *hdr = data;
struct ieee80211_tim_ie *tim_ie;
+ struct ath_common *common = &ar->common;
u8 *tim;
u8 tim_len;
bool cam;
@@ -527,17 +527,13 @@ static void carl9170_ps_beacon(struct ar9170 *ar, void *data, unsigned int len)
if (likely(!(ar->hw->conf.flags & IEEE80211_CONF_PS)))
return;
- /* check if this really is a beacon */
- if (!ieee80211_is_beacon(hdr->frame_control))
- return;
-
/* min. beacon length + FCS_LEN */
if (len <= 40 + FCS_LEN)
return;
+ /* check if this really is a beacon */
/* and only beacons from the associated BSSID, please */
- if (!ether_addr_equal(hdr->addr3, ar->common.curbssid) ||
- !ar->common.curaid)
+ if (!ath_is_mybeacon(common, hdr) || !common->curaid)
return;
ar->ps.last_beacon = jiffies;
@@ -576,7 +572,7 @@ static void carl9170_ps_beacon(struct ar9170 *ar, void *data, unsigned int len)
static void carl9170_ba_check(struct ar9170 *ar, void *data, unsigned int len)
{
- struct ieee80211_bar *bar = (void *) data;
+ struct ieee80211_bar *bar = data;
struct carl9170_bar_list_entry *entry;
unsigned int queue;
@@ -602,8 +598,8 @@ static void carl9170_ba_check(struct ar9170 *ar, void *data, unsigned int len)
if (bar->start_seq_num == entry_bar->start_seq_num &&
TID_CHECK(bar->control, entry_bar->control) &&
- compare_ether_addr(bar->ra, entry_bar->ta) == 0 &&
- compare_ether_addr(bar->ta, entry_bar->ra) == 0) {
+ ether_addr_equal_64bits(bar->ra, entry_bar->ta) &&
+ ether_addr_equal_64bits(bar->ta, entry_bar->ra)) {
struct ieee80211_tx_info *tx_info;
tx_info = IEEE80211_SKB_CB(entry_skb);
diff --git a/drivers/net/wireless/ath/carl9170/tx.c b/drivers/net/wireless/ath/carl9170/tx.c
index c61cafa2665..4cadfd48ffd 100644
--- a/drivers/net/wireless/ath/carl9170/tx.c
+++ b/drivers/net/wireless/ath/carl9170/tx.c
@@ -37,7 +37,6 @@
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
-#include <linux/init.h>
#include <linux/slab.h>
#include <linux/module.h>
#include <linux/etherdevice.h>
@@ -625,7 +624,7 @@ static void carl9170_tx_ampdu_timeout(struct ar9170 *ar)
msecs_to_jiffies(CARL9170_QUEUE_TIMEOUT)))
goto unlock;
- sta = __carl9170_get_tx_sta(ar, skb);
+ sta = iter->sta;
if (WARN_ON(!sta))
goto unlock;
@@ -866,6 +865,93 @@ static bool carl9170_tx_cts_check(struct ar9170 *ar,
return false;
}
+static void carl9170_tx_get_rates(struct ar9170 *ar,
+ struct ieee80211_vif *vif,
+ struct ieee80211_sta *sta,
+ struct sk_buff *skb)
+{
+ struct ieee80211_tx_info *info;
+
+ BUILD_BUG_ON(IEEE80211_TX_MAX_RATES < CARL9170_TX_MAX_RATES);
+ BUILD_BUG_ON(IEEE80211_TX_MAX_RATES > IEEE80211_TX_RATE_TABLE_SIZE);
+
+ info = IEEE80211_SKB_CB(skb);
+
+ ieee80211_get_tx_rates(vif, sta, skb,
+ info->control.rates,
+ IEEE80211_TX_MAX_RATES);
+}
+
+static void carl9170_tx_apply_rateset(struct ar9170 *ar,
+ struct ieee80211_tx_info *sinfo,
+ struct sk_buff *skb)
+{
+ struct ieee80211_tx_rate *txrate;
+ struct ieee80211_tx_info *info;
+ struct _carl9170_tx_superframe *txc = (void *) skb->data;
+ int i;
+ bool ampdu;
+ bool no_ack;
+
+ info = IEEE80211_SKB_CB(skb);
+ ampdu = !!(info->flags & IEEE80211_TX_CTL_AMPDU);
+ no_ack = !!(info->flags & IEEE80211_TX_CTL_NO_ACK);
+
+ /* Set the rate control probe flag for all (sub-) frames.
+ * This is because the TX_STATS_AMPDU flag is only set on
+ * the last frame, so it has to be inherited.
+ */
+ info->flags |= (sinfo->flags & IEEE80211_TX_CTL_RATE_CTRL_PROBE);
+
+ /* NOTE: For the first rate, the ERP & AMPDU flags are directly
+ * taken from mac_control. For all fallback rate, the firmware
+ * updates the mac_control flags from the rate info field.
+ */
+ for (i = 0; i < CARL9170_TX_MAX_RATES; i++) {
+ __le32 phy_set;
+
+ txrate = &sinfo->control.rates[i];
+ if (txrate->idx < 0)
+ break;
+
+ phy_set = carl9170_tx_physet(ar, info, txrate);
+ if (i == 0) {
+ __le16 mac_tmp = cpu_to_le16(0);
+
+ /* first rate - part of the hw's frame header */
+ txc->f.phy_control = phy_set;
+
+ if (ampdu && txrate->flags & IEEE80211_TX_RC_MCS)
+ mac_tmp |= cpu_to_le16(AR9170_TX_MAC_AGGR);
+
+ if (carl9170_tx_rts_check(ar, txrate, ampdu, no_ack))
+ mac_tmp |= cpu_to_le16(AR9170_TX_MAC_PROT_RTS);
+ else if (carl9170_tx_cts_check(ar, txrate))
+ mac_tmp |= cpu_to_le16(AR9170_TX_MAC_PROT_CTS);
+
+ txc->f.mac_control |= mac_tmp;
+ } else {
+ /* fallback rates are stored in the firmware's
+ * retry rate set array.
+ */
+ txc->s.rr[i - 1] = phy_set;
+ }
+
+ SET_VAL(CARL9170_TX_SUPER_RI_TRIES, txc->s.ri[i],
+ txrate->count);
+
+ if (carl9170_tx_rts_check(ar, txrate, ampdu, no_ack))
+ txc->s.ri[i] |= (AR9170_TX_MAC_PROT_RTS <<
+ CARL9170_TX_SUPER_RI_ERP_PROT_S);
+ else if (carl9170_tx_cts_check(ar, txrate))
+ txc->s.ri[i] |= (AR9170_TX_MAC_PROT_CTS <<
+ CARL9170_TX_SUPER_RI_ERP_PROT_S);
+
+ if (ampdu && (txrate->flags & IEEE80211_TX_RC_MCS))
+ txc->s.ri[i] |= CARL9170_TX_SUPER_RI_AMPDU;
+ }
+}
+
static int carl9170_tx_prepare(struct ar9170 *ar,
struct ieee80211_sta *sta,
struct sk_buff *skb)
@@ -874,13 +960,10 @@ static int carl9170_tx_prepare(struct ar9170 *ar,
struct _carl9170_tx_superframe *txc;
struct carl9170_vif_info *cvif;
struct ieee80211_tx_info *info;
- struct ieee80211_tx_rate *txrate;
struct carl9170_tx_info *arinfo;
unsigned int hw_queue;
- int i;
__le16 mac_tmp;
u16 len;
- bool ampdu, no_ack;
BUILD_BUG_ON(sizeof(*arinfo) > sizeof(info->rate_driver_data));
BUILD_BUG_ON(sizeof(struct _carl9170_tx_superdesc) !=
@@ -889,8 +972,6 @@ static int carl9170_tx_prepare(struct ar9170 *ar,
BUILD_BUG_ON(sizeof(struct _ar9170_tx_hwdesc) !=
AR9170_TX_HWDESC_LEN);
- BUILD_BUG_ON(IEEE80211_TX_MAX_RATES < CARL9170_TX_MAX_RATES);
-
BUILD_BUG_ON(AR9170_MAX_VIRTUAL_MAC >
((CARL9170_TX_SUPER_MISC_VIF_ID >>
CARL9170_TX_SUPER_MISC_VIF_ID_S) + 1));
@@ -932,8 +1013,7 @@ static int carl9170_tx_prepare(struct ar9170 *ar,
mac_tmp |= cpu_to_le16((hw_queue << AR9170_TX_MAC_QOS_S) &
AR9170_TX_MAC_QOS);
- no_ack = !!(info->flags & IEEE80211_TX_CTL_NO_ACK);
- if (unlikely(no_ack))
+ if (unlikely(info->flags & IEEE80211_TX_CTL_NO_ACK))
mac_tmp |= cpu_to_le16(AR9170_TX_MAC_NO_ACK);
if (info->control.hw_key) {
@@ -954,8 +1034,7 @@ static int carl9170_tx_prepare(struct ar9170 *ar,
}
}
- ampdu = !!(info->flags & IEEE80211_TX_CTL_AMPDU);
- if (ampdu) {
+ if (info->flags & IEEE80211_TX_CTL_AMPDU) {
unsigned int density, factor;
if (unlikely(!sta || !cvif))
@@ -982,50 +1061,6 @@ static int carl9170_tx_prepare(struct ar9170 *ar,
txc->s.ampdu_settings, factor);
}
- /*
- * NOTE: For the first rate, the ERP & AMPDU flags are directly
- * taken from mac_control. For all fallback rate, the firmware
- * updates the mac_control flags from the rate info field.
- */
- for (i = 0; i < CARL9170_TX_MAX_RATES; i++) {
- __le32 phy_set;
- txrate = &info->control.rates[i];
- if (txrate->idx < 0)
- break;
-
- phy_set = carl9170_tx_physet(ar, info, txrate);
- if (i == 0) {
- /* first rate - part of the hw's frame header */
- txc->f.phy_control = phy_set;
-
- if (ampdu && txrate->flags & IEEE80211_TX_RC_MCS)
- mac_tmp |= cpu_to_le16(AR9170_TX_MAC_AGGR);
- if (carl9170_tx_rts_check(ar, txrate, ampdu, no_ack))
- mac_tmp |= cpu_to_le16(AR9170_TX_MAC_PROT_RTS);
- else if (carl9170_tx_cts_check(ar, txrate))
- mac_tmp |= cpu_to_le16(AR9170_TX_MAC_PROT_CTS);
-
- } else {
- /* fallback rates are stored in the firmware's
- * retry rate set array.
- */
- txc->s.rr[i - 1] = phy_set;
- }
-
- SET_VAL(CARL9170_TX_SUPER_RI_TRIES, txc->s.ri[i],
- txrate->count);
-
- if (carl9170_tx_rts_check(ar, txrate, ampdu, no_ack))
- txc->s.ri[i] |= (AR9170_TX_MAC_PROT_RTS <<
- CARL9170_TX_SUPER_RI_ERP_PROT_S);
- else if (carl9170_tx_cts_check(ar, txrate))
- txc->s.ri[i] |= (AR9170_TX_MAC_PROT_CTS <<
- CARL9170_TX_SUPER_RI_ERP_PROT_S);
-
- if (ampdu && (txrate->flags & IEEE80211_TX_RC_MCS))
- txc->s.ri[i] |= CARL9170_TX_SUPER_RI_AMPDU;
- }
-
txc->s.len = cpu_to_le16(skb->len);
txc->f.length = cpu_to_le16(len + FCS_LEN);
txc->f.mac_control = mac_tmp;
@@ -1086,31 +1121,12 @@ static void carl9170_set_ampdu_params(struct ar9170 *ar, struct sk_buff *skb)
}
}
-static bool carl9170_tx_rate_check(struct ar9170 *ar, struct sk_buff *_dest,
- struct sk_buff *_src)
-{
- struct _carl9170_tx_superframe *dest, *src;
-
- dest = (void *) _dest->data;
- src = (void *) _src->data;
-
- /*
- * The mac80211 rate control algorithm expects that all MPDUs in
- * an AMPDU share the same tx vectors.
- * This is not really obvious right now, because the hardware
- * does the AMPDU setup according to its own rulebook.
- * Our nicely assembled, strictly monotonic increasing mpdu
- * chains will be broken up, mashed back together...
- */
-
- return (dest->f.phy_control == src->f.phy_control);
-}
-
static void carl9170_tx_ampdu(struct ar9170 *ar)
{
struct sk_buff_head agg;
struct carl9170_sta_tid *tid_info;
struct sk_buff *skb, *first;
+ struct ieee80211_tx_info *tx_info_first;
unsigned int i = 0, done_ampdus = 0;
u16 seq, queue, tmpssn;
@@ -1156,6 +1172,7 @@ retry:
goto processed;
}
+ tx_info_first = NULL;
while ((skb = skb_peek(&tid_info->queue))) {
/* strict 0, 1, ..., n - 1, n frame sequence order */
if (unlikely(carl9170_get_seq(skb) != seq))
@@ -1166,8 +1183,13 @@ retry:
(tid_info->max - 1)))
break;
- if (!carl9170_tx_rate_check(ar, skb, first))
- break;
+ if (!tx_info_first) {
+ carl9170_tx_get_rates(ar, tid_info->vif,
+ tid_info->sta, first);
+ tx_info_first = IEEE80211_SKB_CB(first);
+ }
+
+ carl9170_tx_apply_rateset(ar, tx_info_first, skb);
atomic_inc(&ar->tx_ampdu_upload);
tid_info->snx = seq = SEQ_NEXT(seq);
@@ -1182,8 +1204,7 @@ retry:
if (skb_queue_empty(&tid_info->queue) ||
carl9170_get_seq(skb_peek(&tid_info->queue)) !=
tid_info->snx) {
- /*
- * stop TID, if A-MPDU frames are still missing,
+ /* stop TID, if A-MPDU frames are still missing,
* or whenever the queue is empty.
*/
@@ -1450,12 +1471,14 @@ void carl9170_op_tx(struct ieee80211_hw *hw,
struct ar9170 *ar = hw->priv;
struct ieee80211_tx_info *info;
struct ieee80211_sta *sta = control->sta;
+ struct ieee80211_vif *vif;
bool run;
if (unlikely(!IS_STARTED(ar)))
goto err_free;
info = IEEE80211_SKB_CB(skb);
+ vif = info->control.vif;
if (unlikely(carl9170_tx_prepare(ar, sta, skb)))
goto err_free;
@@ -1486,6 +1509,8 @@ void carl9170_op_tx(struct ieee80211_hw *hw,
} else {
unsigned int queue = skb_get_queue_mapping(skb);
+ carl9170_tx_get_rates(ar, vif, sta, skb);
+ carl9170_tx_apply_rateset(ar, info, skb);
skb_queue_tail(&ar->tx_pending[queue], skb);
}
diff --git a/drivers/net/wireless/ath/carl9170/usb.c b/drivers/net/wireless/ath/carl9170/usb.c
index 307bc0ddff9..f35c7f30f9a 100644
--- a/drivers/net/wireless/ath/carl9170/usb.c
+++ b/drivers/net/wireless/ath/carl9170/usb.c
@@ -773,7 +773,7 @@ void carl9170_usb_stop(struct ar9170 *ar)
complete_all(&ar->cmd_wait);
/* This is required to prevent an early completion on _start */
- INIT_COMPLETION(ar->cmd_wait);
+ reinit_completion(&ar->cmd_wait);
/*
* Note:
@@ -1076,8 +1076,14 @@ static int carl9170_usb_probe(struct usb_interface *intf,
carl9170_set_state(ar, CARL9170_STOPPED);
- return request_firmware_nowait(THIS_MODULE, 1, CARL9170FW_NAME,
+ err = request_firmware_nowait(THIS_MODULE, 1, CARL9170FW_NAME,
&ar->udev->dev, GFP_KERNEL, ar, carl9170_usb_firmware_step2);
+ if (err) {
+ usb_put_dev(udev);
+ usb_put_dev(udev);
+ carl9170_free(ar);
+ }
+ return err;
}
static void carl9170_usb_disconnect(struct usb_interface *intf)