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/Kconfig3
-rw-r--r--drivers/net/wireless/ath/carl9170/carl9170.h49
-rw-r--r--drivers/net/wireless/ath/carl9170/cmd.c2
-rw-r--r--drivers/net/wireless/ath/carl9170/cmd.h6
-rw-r--r--drivers/net/wireless/ath/carl9170/debug.c12
-rw-r--r--drivers/net/wireless/ath/carl9170/fw.c81
-rw-r--r--drivers/net/wireless/ath/carl9170/fwcmd.h8
-rw-r--r--drivers/net/wireless/ath/carl9170/fwdesc.h3
-rw-r--r--drivers/net/wireless/ath/carl9170/hw.h2
-rw-r--r--drivers/net/wireless/ath/carl9170/mac.c69
-rw-r--r--drivers/net/wireless/ath/carl9170/main.c198
-rw-r--r--drivers/net/wireless/ath/carl9170/phy.c121
-rw-r--r--drivers/net/wireless/ath/carl9170/rx.c128
-rw-r--r--drivers/net/wireless/ath/carl9170/tx.c435
-rw-r--r--drivers/net/wireless/ath/carl9170/usb.c18
-rw-r--r--drivers/net/wireless/ath/carl9170/version.h6
16 files changed, 701 insertions, 440 deletions
diff --git a/drivers/net/wireless/ath/carl9170/Kconfig b/drivers/net/wireless/ath/carl9170/Kconfig
index 267d5dcf82d..1a796e5f69e 100644
--- a/drivers/net/wireless/ath/carl9170/Kconfig
+++ b/drivers/net/wireless/ath/carl9170/Kconfig
@@ -1,6 +1,7 @@
config CARL9170
tristate "Linux Community AR9170 802.11n USB support"
- depends on USB && MAC80211 && EXPERIMENTAL
+ depends on USB && MAC80211
+ select ATH_COMMON
select FW_LOADER
select CRC32
help
diff --git a/drivers/net/wireless/ath/carl9170/carl9170.h b/drivers/net/wireless/ath/carl9170/carl9170.h
index 6cfbb419e2f..8596aba34f9 100644
--- a/drivers/net/wireless/ath/carl9170/carl9170.h
+++ b/drivers/net/wireless/ath/carl9170/carl9170.h
@@ -70,12 +70,6 @@
static const u8 ar9170_qmap[__AR9170_NUM_TXQ] = { 3, 2, 1, 0 };
-enum carl9170_rf_init_mode {
- CARL9170_RFI_NONE,
- CARL9170_RFI_WARM,
- CARL9170_RFI_COLD,
-};
-
#define CARL9170_MAX_RX_BUFFER_SIZE 8192
enum carl9170_device_state {
@@ -85,20 +79,14 @@ enum carl9170_device_state {
CARL9170_STARTED,
};
-#define CARL9170_NUM_TID 16
#define WME_BA_BMP_SIZE 64
#define CARL9170_TX_USER_RATE_TRIES 3
-#define WME_AC_BE 2
-#define WME_AC_BK 3
-#define WME_AC_VI 1
-#define WME_AC_VO 0
-
#define TID_TO_WME_AC(_tid) \
- ((((_tid) == 0) || ((_tid) == 3)) ? WME_AC_BE : \
- (((_tid) == 1) || ((_tid) == 2)) ? WME_AC_BK : \
- (((_tid) == 4) || ((_tid) == 5)) ? WME_AC_VI : \
- WME_AC_VO)
+ ((((_tid) == 0) || ((_tid) == 3)) ? IEEE80211_AC_BE : \
+ (((_tid) == 1) || ((_tid) == 2)) ? IEEE80211_AC_BK : \
+ (((_tid) == 4) || ((_tid) == 5)) ? IEEE80211_AC_VI : \
+ IEEE80211_AC_VO)
#define SEQ_DIFF(_start, _seq) \
(((_start) - (_seq)) & 0x0fff)
@@ -145,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
@@ -289,6 +280,8 @@ struct ar9170 {
unsigned int mem_block_size;
unsigned int rx_size;
unsigned int tx_seq_table;
+ bool ba_filter;
+ bool disable_offload_fw;
} fw;
/* interface configuration combinations */
@@ -302,6 +295,7 @@ struct ar9170 {
unsigned long queue_stop_timeout[__AR9170_NUM_TXQ];
unsigned long max_queue_stop_timeout[__AR9170_NUM_TXQ];
bool needs_full_reset;
+ bool force_usb_reset;
atomic_t pending_restarts;
/* interface mode settings */
@@ -424,6 +418,11 @@ struct ar9170 {
bool rx_has_plcp;
struct sk_buff *rx_failover;
int rx_failover_missing;
+ u32 ampdu_ref;
+
+ /* FIFO for collecting outstanding BlockAckRequest */
+ struct list_head bar_list[__AR9170_NUM_TXQ];
+ spinlock_t bar_list_lock[__AR9170_NUM_TXQ];
#ifdef CONFIG_CARL9170_WPC
struct {
@@ -468,6 +467,12 @@ enum carl9170_ps_off_override_reasons {
PS_OFF_BCN = BIT(1),
};
+struct carl9170_bar_list_entry {
+ struct list_head list;
+ struct rcu_head head;
+ struct sk_buff *skb;
+};
+
struct carl9170_ba_stats {
u8 ampdu_len;
u8 ampdu_ack_len;
@@ -480,8 +485,8 @@ struct carl9170_sta_info {
bool sleeping;
atomic_t pending_frames;
unsigned int ampdu_max_len;
- struct carl9170_sta_tid __rcu *agg[CARL9170_NUM_TID];
- struct carl9170_ba_stats stats[CARL9170_NUM_TID];
+ struct carl9170_sta_tid __rcu *agg[IEEE80211_NUM_TIDS];
+ struct carl9170_ba_stats stats[IEEE80211_NUM_TIDS];
};
struct carl9170_tx_info {
@@ -559,13 +564,16 @@ int carl9170_set_hwretry_limit(struct ar9170 *ar, const u32 max_retry);
int carl9170_upload_key(struct ar9170 *ar, const u8 id, const u8 *mac,
const u8 ktype, const u8 keyidx, const u8 *keydata, const int keylen);
int carl9170_disable_key(struct ar9170 *ar, const u8 id);
+int carl9170_set_mac_tpc(struct ar9170 *ar, struct ieee80211_channel *channel);
/* RX */
void carl9170_rx(struct ar9170 *ar, void *buf, unsigned int len);
void carl9170_handle_command_response(struct ar9170 *ar, void *buf, u32 len);
/* TX */
-void carl9170_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb);
+void carl9170_op_tx(struct ieee80211_hw *hw,
+ struct ieee80211_tx_control *control,
+ struct sk_buff *skb);
void carl9170_tx_janitor(struct work_struct *work);
void carl9170_tx_process_status(struct ar9170 *ar,
const struct carl9170_rsp *cmd);
@@ -588,12 +596,11 @@ int carl9170_led_set_state(struct ar9170 *ar, const u32 led_state);
/* PHY / RF */
int carl9170_set_channel(struct ar9170 *ar, struct ieee80211_channel *channel,
- enum nl80211_channel_type bw, enum carl9170_rf_init_mode rfi);
+ enum nl80211_channel_type bw);
int carl9170_get_noisefloor(struct ar9170 *ar);
/* FW */
int carl9170_parse_firmware(struct ar9170 *ar);
-int carl9170_fw_fix_eeprom(struct ar9170 *ar);
extern struct ieee80211_rate __carl9170_ratetable[];
extern int modparam_noht;
diff --git a/drivers/net/wireless/ath/carl9170/cmd.c b/drivers/net/wireless/ath/carl9170/cmd.c
index 195dc653811..39a63874b27 100644
--- a/drivers/net/wireless/ath/carl9170/cmd.c
+++ b/drivers/net/wireless/ath/carl9170/cmd.c
@@ -138,7 +138,7 @@ int carl9170_reboot(struct ar9170 *ar)
if (!cmd)
return -ENOMEM;
- err = __carl9170_exec_cmd(ar, (struct carl9170_cmd *)cmd, true);
+ err = __carl9170_exec_cmd(ar, cmd, true);
return err;
}
diff --git a/drivers/net/wireless/ath/carl9170/cmd.h b/drivers/net/wireless/ath/carl9170/cmd.h
index 885c42778b8..65919c902f5 100644
--- a/drivers/net/wireless/ath/carl9170/cmd.h
+++ b/drivers/net/wireless/ath/carl9170/cmd.h
@@ -114,7 +114,7 @@ __regwrite_out : \
#define carl9170_regwrite_result() \
__err; \
-} while (0);
+} while (0)
#define carl9170_async_regwrite_get_buf() \
@@ -126,7 +126,7 @@ do { \
__err = -ENOMEM; \
goto __async_regwrite_out; \
} \
-} while (0);
+} while (0)
#define carl9170_async_regwrite_begin(carl) \
do { \
@@ -169,6 +169,6 @@ __async_regwrite_out: \
#define carl9170_async_regwrite_result() \
__err; \
-} while (0);
+} while (0)
#endif /* __CMD_H */
diff --git a/drivers/net/wireless/ath/carl9170/debug.c b/drivers/net/wireless/ath/carl9170/debug.c
index 3c164226687..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>
@@ -48,11 +47,6 @@
#define ADD(buf, off, max, fmt, args...) \
off += snprintf(&buf[off], max - off, fmt, ##args);
-static int carl9170_debugfs_open(struct inode *inode, struct file *file)
-{
- file->private_data = inode->i_private;
- return 0;
-}
struct carl9170_debugfs_fops {
unsigned int read_bufsize;
@@ -178,7 +172,7 @@ static const struct carl9170_debugfs_fops carl_debugfs_##name ##_ops = {\
.attr = _attr, \
.req_dev_state = _dstate, \
.fops = { \
- .open = carl9170_debugfs_open, \
+ .open = simple_open, \
.read = carl9170_debugfs_read, \
.write = carl9170_debugfs_write, \
.owner = THIS_MODULE \
@@ -659,8 +653,8 @@ static ssize_t carl9170_debugfs_bug_write(struct ar9170 *ar, const char *buf,
goto out;
case 'P':
- err = carl9170_set_channel(ar, ar->hw->conf.channel,
- ar->hw->conf.channel_type, CARL9170_RFI_COLD);
+ err = carl9170_set_channel(ar, ar->hw->conf.chandef.chan,
+ cfg80211_get_chandef_type(&ar->hw->conf.chandef));
if (err < 0)
count = err;
diff --git a/drivers/net/wireless/ath/carl9170/fw.c b/drivers/net/wireless/ath/carl9170/fw.c
index 3de61adacd3..47d5c2e910a 100644
--- a/drivers/net/wireless/ath/carl9170/fw.c
+++ b/drivers/net/wireless/ath/carl9170/fw.c
@@ -28,11 +28,6 @@
#include "fwcmd.h"
#include "version.h"
-#define MAKE_STR(symbol) #symbol
-#define TO_STR(symbol) MAKE_STR(symbol)
-#define CARL9170FW_API_VER_STR TO_STR(CARL9170FW_API_MAX_VER)
-MODULE_VERSION(CARL9170FW_API_VER_STR ":" CARL9170FW_VERSION_GIT);
-
static const u8 otus_magic[4] = { OTUS_MAGIC };
static const void *carl9170_fw_find_desc(struct ar9170 *ar, const u8 descid[4],
@@ -220,6 +215,24 @@ static int carl9170_fw_tx_sequence(struct ar9170 *ar)
return 0;
}
+static void carl9170_fw_set_if_combinations(struct ar9170 *ar,
+ u16 if_comb_types)
+{
+ if (ar->fw.vif_num < 2)
+ return;
+
+ ar->if_comb_limits[0].max = ar->fw.vif_num;
+ ar->if_comb_limits[0].types = if_comb_types;
+
+ ar->if_combs[0].num_different_channels = 1;
+ ar->if_combs[0].max_interfaces = ar->fw.vif_num;
+ ar->if_combs[0].limits = ar->if_comb_limits;
+ ar->if_combs[0].n_limits = ARRAY_SIZE(ar->if_comb_limits);
+
+ ar->hw->wiphy->iface_combinations = ar->if_combs;
+ ar->hw->wiphy->n_iface_combinations = ARRAY_SIZE(ar->if_combs);
+}
+
static int carl9170_fw(struct ar9170 *ar, const __u8 *data, size_t len)
{
const struct carl9170fw_otus_desc *otus_desc;
@@ -269,7 +282,7 @@ static int carl9170_fw(struct ar9170 *ar, const __u8 *data, size_t len)
if (!SUPP(CARL9170FW_COMMAND_CAM)) {
dev_info(&ar->udev->dev, "crypto offloading is disabled "
"by firmware.\n");
- ar->disable_offload = true;
+ ar->fw.disable_offload_fw = true;
}
if (SUPP(CARL9170FW_PSM) && SUPP(CARL9170FW_FIXED_5GHZ_PSM))
@@ -307,6 +320,9 @@ static int carl9170_fw(struct ar9170 *ar, const __u8 *data, size_t len)
if (SUPP(CARL9170FW_WOL))
device_set_wakeup_enable(&ar->udev->dev, true);
+ if (SUPP(CARL9170FW_RX_BA_FILTER))
+ ar->fw.ba_filter = true;
+
if_comb_types = BIT(NL80211_IFTYPE_STATION) |
BIT(NL80211_IFTYPE_P2P_CLIENT);
@@ -339,21 +355,23 @@ static int carl9170_fw(struct ar9170 *ar, const __u8 *data, size_t len)
if_comb_types |=
BIT(NL80211_IFTYPE_AP) |
BIT(NL80211_IFTYPE_P2P_GO);
+
+#ifdef CONFIG_MAC80211_MESH
+ if_comb_types |=
+ BIT(NL80211_IFTYPE_MESH_POINT);
+#endif /* CONFIG_MAC80211_MESH */
}
}
- ar->if_comb_limits[0].max = ar->fw.vif_num;
- ar->if_comb_limits[0].types = if_comb_types;
+ carl9170_fw_set_if_combinations(ar, if_comb_types);
- ar->if_combs[0].num_different_channels = 1;
- ar->if_combs[0].max_interfaces = ar->fw.vif_num;
- ar->if_combs[0].limits = ar->if_comb_limits;
- ar->if_combs[0].n_limits = ARRAY_SIZE(ar->if_comb_limits);
+ ar->hw->wiphy->interface_modes |= if_comb_types;
- ar->hw->wiphy->iface_combinations = ar->if_combs;
- ar->hw->wiphy->n_iface_combinations = ARRAY_SIZE(ar->if_combs);
+ ar->hw->wiphy->flags &= ~WIPHY_FLAG_PS_ON_BY_DEFAULT;
- ar->hw->wiphy->interface_modes |= if_comb_types;
+ /* As IBSS Encryption is software-based, IBSS RSN is supported. */
+ ar->hw->wiphy->flags |= WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL |
+ WIPHY_FLAG_IBSS_RSN | WIPHY_FLAG_SUPPORTS_TDLS;
#undef SUPPORTED
return carl9170_fw_tx_sequence(ar);
@@ -389,39 +407,6 @@ carl9170_find_fw_desc(struct ar9170 *ar, const __u8 *fw_data, const size_t len)
return (void *)&fw_data[scan - found];
}
-int carl9170_fw_fix_eeprom(struct ar9170 *ar)
-{
- const struct carl9170fw_fix_desc *fix_desc = NULL;
- unsigned int i, n, off;
- u32 *data = (void *)&ar->eeprom;
-
- fix_desc = carl9170_fw_find_desc(ar, FIX_MAGIC,
- sizeof(*fix_desc), CARL9170FW_FIX_DESC_CUR_VER);
-
- if (!fix_desc)
- return 0;
-
- n = (le16_to_cpu(fix_desc->head.length) - sizeof(*fix_desc)) /
- sizeof(struct carl9170fw_fix_entry);
-
- for (i = 0; i < n; i++) {
- off = le32_to_cpu(fix_desc->data[i].address) -
- AR9170_EEPROM_START;
-
- if (off >= sizeof(struct ar9170_eeprom) || (off & 3)) {
- dev_err(&ar->udev->dev, "Skip invalid entry %d\n", i);
- continue;
- }
-
- data[off / sizeof(*data)] &=
- le32_to_cpu(fix_desc->data[i].mask);
- data[off / sizeof(*data)] |=
- le32_to_cpu(fix_desc->data[i].value);
- }
-
- return 0;
-}
-
int carl9170_parse_firmware(struct ar9170 *ar)
{
const struct carl9170fw_desc_head *fw_desc = NULL;
diff --git a/drivers/net/wireless/ath/carl9170/fwcmd.h b/drivers/net/wireless/ath/carl9170/fwcmd.h
index 9443c802b25..9111d4ffc1b 100644
--- a/drivers/net/wireless/ath/carl9170/fwcmd.h
+++ b/drivers/net/wireless/ath/carl9170/fwcmd.h
@@ -156,6 +156,14 @@ struct carl9170_psm {
} __packed;
#define CARL9170_PSM_SIZE 4
+/*
+ * Note: If a bit in rx_filter is set, then it
+ * means that the particular frames which matches
+ * the condition are FILTERED/REMOVED/DISCARDED!
+ * (This is can be a bit confusing, especially
+ * because someone people think it's the exact
+ * opposite way, so watch out!)
+ */
struct carl9170_rx_filter_cmd {
__le32 rx_filter;
} __packed;
diff --git a/drivers/net/wireless/ath/carl9170/fwdesc.h b/drivers/net/wireless/ath/carl9170/fwdesc.h
index 6d9c0891ce7..66848d47c88 100644
--- a/drivers/net/wireless/ath/carl9170/fwdesc.h
+++ b/drivers/net/wireless/ath/carl9170/fwdesc.h
@@ -78,6 +78,9 @@ enum carl9170fw_feature_list {
/* HW (ANI, CCA, MIB) tally counters */
CARL9170FW_HW_COUNTERS,
+ /* Firmware will pass BA when BARs are queued */
+ CARL9170FW_RX_BA_FILTER,
+
/* KEEP LAST */
__CARL9170FW_FEATURE_NUM
};
diff --git a/drivers/net/wireless/ath/carl9170/hw.h b/drivers/net/wireless/ath/carl9170/hw.h
index fa834c1460f..0db874abde5 100644
--- a/drivers/net/wireless/ath/carl9170/hw.h
+++ b/drivers/net/wireless/ath/carl9170/hw.h
@@ -384,7 +384,7 @@
#define AR9170_MAC_REG_BCN_ADDR (AR9170_MAC_REG_BASE + 0xd84)
#define AR9170_MAC_REG_BCN_LENGTH (AR9170_MAC_REG_BASE + 0xd88)
-#define AR9170_MAC_BCN_LENGTH_MAX 256
+#define AR9170_MAC_BCN_LENGTH_MAX (512 - 32)
#define AR9170_MAC_REG_BCN_STATUS (AR9170_MAC_REG_BASE + 0xd8c)
diff --git a/drivers/net/wireless/ath/carl9170/mac.c b/drivers/net/wireless/ath/carl9170/mac.c
index dfda9197099..a2f005703c0 100644
--- a/drivers/net/wireless/ath/carl9170/mac.c
+++ b/drivers/net/wireless/ath/carl9170/mac.c
@@ -48,7 +48,7 @@ int carl9170_set_dyn_sifs_ack(struct ar9170 *ar)
if (conf_is_ht40(&ar->hw->conf))
val = 0x010a;
else {
- if (ar->hw->conf.channel->band == IEEE80211_BAND_2GHZ)
+ if (ar->hw->conf.chandef.chan->band == IEEE80211_BAND_2GHZ)
val = 0x105;
else
val = 0x104;
@@ -66,7 +66,7 @@ int carl9170_set_rts_cts_rate(struct ar9170 *ar)
rts_rate = 0x1da;
cts_rate = 0x10a;
} else {
- if (ar->hw->conf.channel->band == IEEE80211_BAND_2GHZ) {
+ if (ar->hw->conf.chandef.chan->band == IEEE80211_BAND_2GHZ) {
/* 11 mbit CCK */
rts_rate = 033;
cts_rate = 003;
@@ -93,7 +93,7 @@ int carl9170_set_slot_time(struct ar9170 *ar)
return 0;
}
- if ((ar->hw->conf.channel->band == IEEE80211_BAND_5GHZ) ||
+ if ((ar->hw->conf.chandef.chan->band == IEEE80211_BAND_5GHZ) ||
vif->bss_conf.use_short_slot)
slottime = 9;
@@ -120,7 +120,7 @@ int carl9170_set_mac_rates(struct ar9170 *ar)
basic |= (vif->bss_conf.basic_rates & 0xff0) << 4;
rcu_read_unlock();
- if (ar->hw->conf.channel->band == IEEE80211_BAND_5GHZ)
+ if (ar->hw->conf.chandef.chan->band == IEEE80211_BAND_5GHZ)
mandatory = 0xff00; /* OFDM 6/9/12/18/24/36/48/54 */
else
mandatory = 0xff0f; /* OFDM (6/9../54) + CCK (1/2/5.5/11) */
@@ -304,7 +304,8 @@ int carl9170_set_operating_mode(struct ar9170 *ar)
struct ath_common *common = &ar->common;
u8 *mac_addr, *bssid;
u32 cam_mode = AR9170_MAC_CAM_DEFAULTS;
- u32 enc_mode = AR9170_MAC_ENCRYPTION_DEFAULTS;
+ u32 enc_mode = AR9170_MAC_ENCRYPTION_DEFAULTS |
+ AR9170_MAC_ENCRYPTION_MGMT_RX_SOFTWARE;
u32 rx_ctrl = AR9170_MAC_RX_CTRL_DEAGG |
AR9170_MAC_RX_CTRL_SHORT_FILTER;
u32 sniffer = AR9170_MAC_SNIFFER_DEFAULTS;
@@ -318,10 +319,10 @@ int carl9170_set_operating_mode(struct ar9170 *ar)
bssid = common->curbssid;
switch (vif->type) {
- case NL80211_IFTYPE_MESH_POINT:
case NL80211_IFTYPE_ADHOC:
cam_mode |= AR9170_MAC_CAM_IBSS;
break;
+ case NL80211_IFTYPE_MESH_POINT:
case NL80211_IFTYPE_AP:
cam_mode |= AR9170_MAC_CAM_AP;
@@ -342,7 +343,24 @@ int carl9170_set_operating_mode(struct ar9170 *ar)
break;
}
} else {
- mac_addr = NULL;
+ /*
+ * Enable monitor mode
+ *
+ * rx_ctrl |= AR9170_MAC_RX_CTRL_ACK_IN_SNIFFER;
+ * sniffer |= AR9170_MAC_SNIFFER_ENABLE_PROMISC;
+ *
+ * When the hardware is in SNIFFER_PROMISC mode,
+ * it generates spurious ACKs for every incoming
+ * frame. This confuses every peer in the
+ * vicinity and the network throughput will suffer
+ * badly.
+ *
+ * Hence, the hardware will be put into station
+ * mode and just the rx filters are disabled.
+ */
+ cam_mode |= AR9170_MAC_CAM_STA;
+ rx_ctrl |= AR9170_MAC_RX_CTRL_PASS_TO_HOST;
+ mac_addr = common->macaddr;
bssid = NULL;
}
rcu_read_unlock();
@@ -354,8 +372,6 @@ int carl9170_set_operating_mode(struct ar9170 *ar)
enc_mode |= AR9170_MAC_ENCRYPTION_RX_SOFTWARE;
if (ar->sniffer_enabled) {
- rx_ctrl |= AR9170_MAC_RX_CTRL_ACK_IN_SNIFFER;
- sniffer |= AR9170_MAC_SNIFFER_ENABLE_PROMISC;
enc_mode |= AR9170_MAC_ENCRYPTION_RX_SOFTWARE;
}
@@ -485,3 +501,38 @@ int carl9170_disable_key(struct ar9170 *ar, const u8 id)
return carl9170_exec_cmd(ar, CARL9170_CMD_DKEY,
sizeof(key), (u8 *)&key, 0, NULL);
}
+
+int carl9170_set_mac_tpc(struct ar9170 *ar, struct ieee80211_channel *channel)
+{
+ unsigned int power, chains;
+
+ if (ar->eeprom.tx_mask != 1)
+ chains = AR9170_TX_PHY_TXCHAIN_2;
+ else
+ chains = AR9170_TX_PHY_TXCHAIN_1;
+
+ switch (channel->band) {
+ case IEEE80211_BAND_2GHZ:
+ power = ar->power_2G_ofdm[0] & 0x3f;
+ break;
+ case IEEE80211_BAND_5GHZ:
+ power = ar->power_5G_leg[0] & 0x3f;
+ break;
+ default:
+ BUG_ON(1);
+ }
+
+ power = min_t(unsigned int, power, ar->hw->conf.power_level * 2);
+
+ carl9170_regwrite_begin(ar);
+ carl9170_regwrite(AR9170_MAC_REG_ACK_TPC,
+ 0x3c1e | power << 20 | chains << 26);
+ carl9170_regwrite(AR9170_MAC_REG_RTS_CTS_TPC,
+ power << 5 | chains << 11 |
+ power << 21 | chains << 27);
+ carl9170_regwrite(AR9170_MAC_REG_CFEND_QOSNULL_TPC,
+ power << 5 | chains << 11 |
+ power << 21 | chains << 27);
+ carl9170_regwrite_finish();
+ return carl9170_regwrite_result();
+}
diff --git a/drivers/net/wireless/ath/carl9170/main.c b/drivers/net/wireless/ath/carl9170/main.c
index db774212161..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>
@@ -358,8 +357,13 @@ static int carl9170_op_start(struct ieee80211_hw *hw)
ar->ps.last_action = jiffies;
ar->ps.last_slept = jiffies;
ar->erp_mode = CARL9170_ERP_AUTO;
- ar->rx_software_decryption = false;
- ar->disable_offload = false;
+
+ /* Set "disable hw crypto offload" whenever the module parameter
+ * nohwcrypt is true or if the firmware does not support it.
+ */
+ ar->disable_offload = modparam_nohwcrypt |
+ ar->fw.disable_offload_fw;
+ ar->rx_software_decryption = ar->disable_offload;
for (i = 0; i < ar->hw->queues; i++) {
ar->queue_stop_timeout[i] = jiffies;
@@ -465,27 +469,26 @@ static void carl9170_restart_work(struct work_struct *work)
{
struct ar9170 *ar = container_of(work, struct ar9170,
restart_work);
- int err;
+ int err = -EIO;
ar->usedkeys = 0;
ar->filter_state = 0;
carl9170_cancel_worker(ar);
mutex_lock(&ar->mutex);
- err = carl9170_usb_restart(ar);
- if (net_ratelimit()) {
- if (err) {
- dev_err(&ar->udev->dev, "Failed to restart device "
- " (%d).\n", err);
- } else {
- dev_info(&ar->udev->dev, "device restarted "
- "successfully.\n");
+ if (!ar->force_usb_reset) {
+ err = carl9170_usb_restart(ar);
+ if (net_ratelimit()) {
+ if (err)
+ dev_err(&ar->udev->dev, "Failed to restart device (%d).\n", err);
+ else
+ dev_info(&ar->udev->dev, "device restarted successfully.\n");
}
}
-
carl9170_zap_queues(ar);
mutex_unlock(&ar->mutex);
- if (!err) {
+
+ if (!err && !ar->force_usb_reset) {
ar->restart_counter++;
atomic_set(&ar->pending_restarts, 0);
@@ -526,10 +529,10 @@ void carl9170_restart(struct ar9170 *ar, const enum carl9170_restart_reasons r)
if (!ar->registered)
return;
- if (IS_ACCEPTING_CMD(ar) && !ar->needs_full_reset)
- ieee80211_queue_work(ar->hw, &ar->restart_work);
- else
- carl9170_usb_reset(ar);
+ if (!IS_ACCEPTING_CMD(ar) || ar->needs_full_reset)
+ ar->force_usb_reset = true;
+
+ ieee80211_queue_work(ar->hw, &ar->restart_work);
/*
* At this point, the device instance might have vanished/disabled.
@@ -566,12 +569,28 @@ static int carl9170_init_interface(struct ar9170 *ar,
memcpy(common->macaddr, vif->addr, ETH_ALEN);
- if (modparam_nohwcrypt ||
- ((vif->type != NL80211_IFTYPE_STATION) &&
- (vif->type != NL80211_IFTYPE_AP))) {
- ar->rx_software_decryption = true;
- ar->disable_offload = true;
- }
+ /* We have to fall back to software crypto, whenever
+ * the user choose to participates in an IBSS. HW
+ * offload for IBSS RSN is not supported by this driver.
+ *
+ * NOTE: If the previous main interface has already
+ * disabled hw crypto offload, we have to keep this
+ * previous disable_offload setting as it was.
+ * Altough ideally, we should notify mac80211 and tell
+ * it to forget about any HW crypto offload for now.
+ */
+ ar->disable_offload |= ((vif->type != NL80211_IFTYPE_STATION) &&
+ (vif->type != NL80211_IFTYPE_AP));
+
+ /* While the driver supports HW offload in a single
+ * P2P client configuration, it doesn't support HW
+ * offload in the favourit, concurrent P2P GO+CLIENT
+ * configuration. Hence, HW offload will always be
+ * disabled for P2P.
+ */
+ ar->disable_offload |= vif->p2p;
+
+ ar->rx_software_decryption = ar->disable_offload;
err = carl9170_set_operating_mode(ar);
return err;
@@ -581,7 +600,7 @@ static int carl9170_op_add_interface(struct ieee80211_hw *hw,
struct ieee80211_vif *vif)
{
struct carl9170_vif_info *vif_priv = (void *) vif->drv_priv;
- struct ieee80211_vif *main_vif;
+ struct ieee80211_vif *main_vif, *old_main = NULL;
struct ar9170 *ar = hw->priv;
int vif_id = -1, err = 0;
@@ -603,6 +622,15 @@ static int carl9170_op_add_interface(struct ieee80211_hw *hw,
goto init;
}
+ /* Because the AR9170 HW's MAC doesn't provide full support for
+ * multiple, independent interfaces [of different operation modes].
+ * We have to select ONE main interface [main mode of HW], but we
+ * can have multiple slaves [AKA: entry in the ACK-table].
+ *
+ * The first (from HEAD/TOP) interface in the ar->vif_list is
+ * always the main intf. All following intfs in this list
+ * are considered to be slave intfs.
+ */
main_vif = carl9170_get_main_vif(ar);
if (main_vif) {
@@ -611,15 +639,29 @@ static int carl9170_op_add_interface(struct ieee80211_hw *hw,
if (vif->type == NL80211_IFTYPE_STATION)
break;
+ /* P2P GO [master] use-case
+ * Because the P2P GO station is selected dynamically
+ * by all participating peers of a WIFI Direct network,
+ * the driver has be able to change the main interface
+ * operating mode on the fly.
+ */
+ if (main_vif->p2p && vif->p2p &&
+ vif->type == NL80211_IFTYPE_AP) {
+ old_main = main_vif;
+ break;
+ }
+
err = -EBUSY;
rcu_read_unlock();
goto unlock;
+ case NL80211_IFTYPE_MESH_POINT:
case NL80211_IFTYPE_AP:
if ((vif->type == NL80211_IFTYPE_STATION) ||
(vif->type == NL80211_IFTYPE_WDS) ||
- (vif->type == NL80211_IFTYPE_AP))
+ (vif->type == NL80211_IFTYPE_AP) ||
+ (vif->type == NL80211_IFTYPE_MESH_POINT))
break;
err = -EBUSY;
@@ -647,14 +689,41 @@ static int carl9170_op_add_interface(struct ieee80211_hw *hw,
vif_priv->id = vif_id;
vif_priv->enable_beacon = false;
ar->vifs++;
- list_add_tail_rcu(&vif_priv->list, &ar->vif_list);
+ if (old_main) {
+ /* We end up in here, if the main interface is being replaced.
+ * Put the new main interface at the HEAD of the list and the
+ * previous inteface will automatically become second in line.
+ */
+ list_add_rcu(&vif_priv->list, &ar->vif_list);
+ } else {
+ /* Add new inteface. If the list is empty, it will become the
+ * main inteface, otherwise it will be slave.
+ */
+ list_add_tail_rcu(&vif_priv->list, &ar->vif_list);
+ }
rcu_assign_pointer(ar->vif_priv[vif_id].vif, vif);
init:
- if (carl9170_get_main_vif(ar) == vif) {
+ main_vif = carl9170_get_main_vif(ar);
+
+ if (main_vif == vif) {
rcu_assign_pointer(ar->beacon_iter, vif_priv);
rcu_read_unlock();
+ if (old_main) {
+ struct carl9170_vif_info *old_main_priv =
+ (void *) old_main->drv_priv;
+ /* downgrade old main intf to slave intf.
+ * NOTE: We are no longer under rcu_read_lock.
+ * But we are still holding ar->mutex, so the
+ * vif data [id, addr] is safe.
+ */
+ err = carl9170_mod_virtual_mac(ar, old_main_priv->id,
+ old_main->addr);
+ if (err)
+ goto unlock;
+ }
+
err = carl9170_init_interface(ar, vif);
if (err)
goto unlock;
@@ -853,17 +922,15 @@ static int carl9170_op_config(struct ieee80211_hw *hw, u32 changed)
goto out;
}
- if (changed & IEEE80211_CONF_CHANGE_POWER) {
- /* TODO */
- err = 0;
- }
-
if (changed & IEEE80211_CONF_CHANGE_SMPS) {
/* TODO */
err = 0;
}
if (changed & IEEE80211_CONF_CHANGE_CHANNEL) {
+ enum nl80211_channel_type channel_type =
+ cfg80211_get_chandef_type(&hw->conf.chandef);
+
/* adjust slot time for 5 GHz */
err = carl9170_set_slot_time(ar);
if (err)
@@ -873,8 +940,8 @@ static int carl9170_op_config(struct ieee80211_hw *hw, u32 changed)
if (err)
goto out;
- err = carl9170_set_channel(ar, hw->conf.channel,
- hw->conf.channel_type, CARL9170_RFI_NONE);
+ err = carl9170_set_channel(ar, hw->conf.chandef.chan,
+ channel_type);
if (err)
goto out;
@@ -891,6 +958,12 @@ static int carl9170_op_config(struct ieee80211_hw *hw, u32 changed)
goto out;
}
+ if (changed & IEEE80211_CONF_CHANGE_POWER) {
+ err = carl9170_set_mac_tpc(ar, ar->hw->conf.chandef.chan);
+ if (err)
+ goto out;
+ }
+
out:
mutex_unlock(&ar->mutex);
return err;
@@ -948,6 +1021,9 @@ static void carl9170_op_configure_filter(struct ieee80211_hw *hw,
if (ar->fw.rx_filter && changed_flags & ar->rx_filter_caps) {
u32 rx_filter = 0;
+ if (!ar->fw.ba_filter)
+ rx_filter |= CARL9170_RX_FILTER_CTL_OTHER;
+
if (!(*new_flags & (FIF_FCSFAIL | FIF_PLCPFAIL)))
rx_filter |= CARL9170_RX_FILTER_BAD;
@@ -1107,9 +1183,7 @@ static int carl9170_op_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
if (ar->disable_offload || !vif)
return -EOPNOTSUPP;
- /*
- * We have to fall back to software encryption, whenever
- * the user choose to participates in an IBSS or is connected
+ /* Fall back to software encryption whenever the driver is connected
* to more than one network.
*
* This is very unfortunate, because some machines cannot handle
@@ -1143,6 +1217,7 @@ static int carl9170_op_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
break;
case WLAN_CIPHER_SUITE_CCMP:
ktype = AR9170_ENC_ALG_AESCCMP;
+ key->flags |= IEEE80211_KEY_FLAG_SW_MGMT_TX;
break;
default:
return -EOPNOTSUPP;
@@ -1257,7 +1332,7 @@ static int carl9170_op_sta_add(struct ieee80211_hw *hw,
return 0;
}
- for (i = 0; i < CARL9170_NUM_TID; i++)
+ for (i = 0; i < ARRAY_SIZE(sta_info->agg); i++)
RCU_INIT_POINTER(sta_info->agg[i], NULL);
sta_info->ampdu_max_len = 1 << (3 + sta->ht_cap.ampdu_factor);
@@ -1281,7 +1356,7 @@ static int carl9170_op_sta_remove(struct ieee80211_hw *hw,
sta_info->ht_sta = false;
rcu_read_lock();
- for (i = 0; i < CARL9170_NUM_TID; i++) {
+ for (i = 0; i < ARRAY_SIZE(sta_info->agg); i++) {
struct carl9170_sta_tid *tid_info;
tid_info = rcu_dereference(sta_info->agg[i]);
@@ -1372,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);
@@ -1388,7 +1465,9 @@ static int carl9170_op_ampdu_action(struct ieee80211_hw *hw,
ieee80211_start_tx_ba_cb_irqsafe(vif, sta->addr, tid);
break;
- case IEEE80211_AMPDU_TX_STOP:
+ case IEEE80211_AMPDU_TX_STOP_CONT:
+ case IEEE80211_AMPDU_TX_STOP_FLUSH:
+ case IEEE80211_AMPDU_TX_STOP_FLUSH_CONT:
rcu_read_lock();
tid_info = rcu_dereference(sta_info->agg[tid]);
if (tid_info) {
@@ -1628,7 +1707,9 @@ found:
return 0;
}
-static void carl9170_op_flush(struct ieee80211_hw *hw, 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;
@@ -1752,6 +1833,9 @@ void *carl9170_alloc(size_t priv_size)
for (i = 0; i < ar->hw->queues; i++) {
skb_queue_head_init(&ar->tx_status[i]);
skb_queue_head_init(&ar->tx_pending[i]);
+
+ INIT_LIST_HEAD(&ar->bar_list[i]);
+ spin_lock_init(&ar->bar_list_lock[i]);
}
INIT_WORK(&ar->ps_work, carl9170_ps_work);
INIT_WORK(&ar->ping_work, carl9170_ping_work);
@@ -1771,11 +1855,14 @@ void *carl9170_alloc(size_t priv_size)
hw->wiphy->interface_modes = 0;
hw->flags |= IEEE80211_HW_RX_INCLUDES_FCS |
+ IEEE80211_HW_MFP_CAPABLE |
IEEE80211_HW_REPORTS_TX_ACK_STATUS |
IEEE80211_HW_SUPPORTS_PS |
IEEE80211_HW_PS_NULLFUNC_STACK |
- IEEE80211_HW_NEED_DTIM_PERIOD |
- IEEE80211_HW_SIGNAL_DBM;
+ IEEE80211_HW_NEED_DTIM_BEFORE_ASSOC |
+ IEEE80211_HW_SUPPORTS_RC_TABLE |
+ IEEE80211_HW_SIGNAL_DBM |
+ IEEE80211_HW_SUPPORTS_HT_CCK_RATES;
if (!modparam_noht) {
/*
@@ -1795,7 +1882,6 @@ void *carl9170_alloc(size_t priv_size)
for (i = 0; i < ARRAY_SIZE(ar->noise); i++)
ar->noise[i] = -95; /* ATH_DEFAULT_NOISE_FLOOR */
- hw->wiphy->flags &= ~WIPHY_FLAG_PS_ON_BY_DEFAULT;
return ar;
err_nomem:
@@ -1883,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 */
@@ -1903,13 +1977,13 @@ static int carl9170_parse_eeprom(struct ar9170 *ar)
return 0;
}
-static int carl9170_reg_notifier(struct wiphy *wiphy,
- struct regulatory_request *request)
+static void carl9170_reg_notifier(struct wiphy *wiphy,
+ struct regulatory_request *request)
{
struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy);
struct ar9170 *ar = hw->priv;
- return ath_reg_notifier_apply(wiphy, request, &ar->common.regulatory);
+ ath_reg_notifier_apply(wiphy, request, &ar->common.regulatory);
}
int carl9170_register(struct ar9170 *ar)
@@ -1931,10 +2005,6 @@ int carl9170_register(struct ar9170 *ar)
if (err)
return err;
- err = carl9170_fw_fix_eeprom(ar);
- if (err)
- return err;
-
err = carl9170_parse_eeprom(ar);
if (err)
return err;
diff --git a/drivers/net/wireless/ath/carl9170/phy.c b/drivers/net/wireless/ath/carl9170/phy.c
index 472efc7e340..ab4ee7d39ad 100644
--- a/drivers/net/wireless/ath/carl9170/phy.c
+++ b/drivers/net/wireless/ath/carl9170/phy.c
@@ -1331,7 +1331,7 @@ static void carl9170_calc_ctl(struct ar9170 *ar, u32 freq, enum carl9170_bw bw)
* CTL_ETSI for 2GHz and CTL_FCC for 5GHz.
*/
ctl_grp = ath_regd_get_band_ctl(&ar->common.regulatory,
- ar->hw->conf.channel->band);
+ ar->hw->conf.chandef.chan->band);
/* ctl group not found - either invalid band (NO_CTL) or ww roaming */
if (ctl_grp == NO_CTL || ctl_grp == SD_NO_CTL)
@@ -1341,7 +1341,7 @@ static void carl9170_calc_ctl(struct ar9170 *ar, u32 freq, enum carl9170_bw bw)
/* skip CTL and heavy clip for CTL_MKK and CTL_ETSI */
return;
- if (ar->hw->conf.channel->band == IEEE80211_BAND_2GHZ) {
+ if (ar->hw->conf.chandef.chan->band == IEEE80211_BAND_2GHZ) {
modes = mode_list_2ghz;
nr_modes = ARRAY_SIZE(mode_list_2ghz);
} else {
@@ -1426,15 +1426,15 @@ static void carl9170_calc_ctl(struct ar9170 *ar, u32 freq, enum carl9170_bw bw)
#undef EDGES
}
-static int carl9170_set_power_cal(struct ar9170 *ar, u32 freq,
- enum carl9170_bw bw)
+static void carl9170_set_power_cal(struct ar9170 *ar, u32 freq,
+ enum carl9170_bw bw)
{
struct ar9170_calibration_target_power_legacy *ctpl;
struct ar9170_calibration_target_power_ht *ctph;
u8 *ctpres;
int ntargets;
int idx, i, n;
- u8 ackpower, ackchains, f;
+ u8 f;
u8 pwr_freqs[AR5416_MAX_NUM_TGT_PWRS];
if (freq < 3000)
@@ -1523,32 +1523,6 @@ static int carl9170_set_power_cal(struct ar9170 *ar, u32 freq,
/* calc. conformance test limits and apply to ar->power*[] */
carl9170_calc_ctl(ar, freq, bw);
-
- /* set ACK/CTS TX power */
- carl9170_regwrite_begin(ar);
-
- if (ar->eeprom.tx_mask != 1)
- ackchains = AR9170_TX_PHY_TXCHAIN_2;
- else
- ackchains = AR9170_TX_PHY_TXCHAIN_1;
-
- if (freq < 3000)
- ackpower = ar->power_2G_ofdm[0] & 0x3f;
- else
- ackpower = ar->power_5G_leg[0] & 0x3f;
-
- carl9170_regwrite(AR9170_MAC_REG_ACK_TPC,
- 0x3c1e | ackpower << 20 | ackchains << 26);
- carl9170_regwrite(AR9170_MAC_REG_RTS_CTS_TPC,
- ackpower << 5 | ackchains << 11 |
- ackpower << 21 | ackchains << 27);
-
- carl9170_regwrite(AR9170_MAC_REG_CFEND_QOSNULL_TPC,
- ackpower << 5 | ackchains << 11 |
- ackpower << 21 | ackchains << 27);
-
- carl9170_regwrite_finish();
- return carl9170_regwrite_result();
}
int carl9170_get_noisefloor(struct ar9170 *ar)
@@ -1595,16 +1569,14 @@ static enum carl9170_bw nl80211_to_carl(enum nl80211_channel_type type)
}
int carl9170_set_channel(struct ar9170 *ar, struct ieee80211_channel *channel,
- enum nl80211_channel_type _bw,
- enum carl9170_rf_init_mode rfi)
+ enum nl80211_channel_type _bw)
{
const struct carl9170_phy_freq_params *freqpar;
struct carl9170_rf_init_result rf_res;
struct carl9170_rf_init rf;
- u32 cmd, tmp, offs = 0, new_ht = 0;
+ u32 tmp, offs = 0, new_ht = 0;
int err;
enum carl9170_bw bw;
- bool warm_reset;
struct ieee80211_channel *old_channel = NULL;
bw = nl80211_to_carl(_bw);
@@ -1618,51 +1590,27 @@ int carl9170_set_channel(struct ar9170 *ar, struct ieee80211_channel *channel,
/* may be NULL at first setup */
if (ar->channel) {
old_channel = ar->channel;
- warm_reset = (old_channel->band != channel->band) ||
- (old_channel->center_freq ==
- channel->center_freq) ||
- (ar->ht_settings != new_ht);
-
ar->channel = NULL;
- } else {
- warm_reset = true;
}
- /* HW workaround */
- if (!ar->hw->wiphy->bands[IEEE80211_BAND_5GHZ] &&
- channel->center_freq <= 2417)
- warm_reset = true;
-
- if (rfi != CARL9170_RFI_NONE || warm_reset) {
- u32 val;
-
- if (rfi == CARL9170_RFI_COLD)
- val = AR9170_PWR_RESET_BB_COLD_RESET;
- else
- val = AR9170_PWR_RESET_BB_WARM_RESET;
-
- /* warm/cold reset BB/ADDA */
- err = carl9170_write_reg(ar, AR9170_PWR_REG_RESET, val);
- if (err)
- return err;
-
- err = carl9170_write_reg(ar, AR9170_PWR_REG_RESET, 0x0);
- if (err)
- return err;
+ /* cold reset BB/ADDA */
+ err = carl9170_write_reg(ar, AR9170_PWR_REG_RESET,
+ AR9170_PWR_RESET_BB_COLD_RESET);
+ if (err)
+ return err;
- err = carl9170_init_phy(ar, channel->band);
- if (err)
- return err;
+ err = carl9170_write_reg(ar, AR9170_PWR_REG_RESET, 0x0);
+ if (err)
+ return err;
- err = carl9170_init_rf_banks_0_7(ar,
- channel->band == IEEE80211_BAND_5GHZ);
- if (err)
- return err;
+ err = carl9170_init_phy(ar, channel->band);
+ if (err)
+ return err;
- cmd = CARL9170_CMD_RF_INIT;
- } else {
- cmd = CARL9170_CMD_FREQUENCY;
- }
+ err = carl9170_init_rf_banks_0_7(ar,
+ channel->band == IEEE80211_BAND_5GHZ);
+ if (err)
+ return err;
err = carl9170_exec_cmd(ar, CARL9170_CMD_FREQ_START, 0, NULL, 0, NULL);
if (err)
@@ -1674,8 +1622,8 @@ int carl9170_set_channel(struct ar9170 *ar, struct ieee80211_channel *channel,
return err;
err = carl9170_init_rf_bank4_pwr(ar,
- channel->band == IEEE80211_BAND_5GHZ,
- channel->center_freq, bw);
+ channel->band == IEEE80211_BAND_5GHZ,
+ channel->center_freq, bw);
if (err)
return err;
@@ -1712,7 +1660,9 @@ int carl9170_set_channel(struct ar9170 *ar, struct ieee80211_channel *channel,
if (err)
return err;
- err = carl9170_set_power_cal(ar, channel->center_freq, bw);
+ carl9170_set_power_cal(ar, channel->center_freq, bw);
+
+ err = carl9170_set_mac_tpc(ar, channel);
if (err)
return err;
@@ -1727,13 +1677,8 @@ int carl9170_set_channel(struct ar9170 *ar, struct ieee80211_channel *channel,
rf.delta_slope_coeff_man = cpu_to_le32(freqpar->coeff_man);
rf.delta_slope_coeff_exp_shgi = cpu_to_le32(freqpar->coeff_exp_shgi);
rf.delta_slope_coeff_man_shgi = cpu_to_le32(freqpar->coeff_man_shgi);
-
- if (rfi != CARL9170_RFI_NONE)
- rf.finiteLoopCount = cpu_to_le32(2000);
- else
- rf.finiteLoopCount = cpu_to_le32(1000);
-
- err = carl9170_exec_cmd(ar, cmd, sizeof(rf), &rf,
+ rf.finiteLoopCount = cpu_to_le32(2000);
+ err = carl9170_exec_cmd(ar, CARL9170_CMD_RF_INIT, sizeof(rf), &rf,
sizeof(rf_res), &rf_res);
if (err)
return err;
@@ -1748,9 +1693,8 @@ int carl9170_set_channel(struct ar9170 *ar, struct ieee80211_channel *channel,
old_channel->center_freq : -1, channel->center_freq,
err);
- if ((rfi == CARL9170_RFI_COLD) || (ar->chan_fail > 3)) {
- /*
- * We have tried very hard to change to _another_
+ if (ar->chan_fail > 3) {
+ /* We have tried very hard to change to _another_
* channel and we've failed to do so!
* Chances are that the PHY/RF is no longer
* operable (due to corruptions/fatal events/bugs?)
@@ -1760,8 +1704,7 @@ int carl9170_set_channel(struct ar9170 *ar, struct ieee80211_channel *channel,
return 0;
}
- err = carl9170_set_channel(ar, channel, _bw,
- CARL9170_RFI_COLD);
+ err = carl9170_set_channel(ar, channel, _bw);
if (err)
return err;
} else {
diff --git a/drivers/net/wireless/ath/carl9170/rx.c b/drivers/net/wireless/ath/carl9170/rx.c
index dc99030ea8b..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>
@@ -161,12 +160,9 @@ static void carl9170_cmd_callback(struct ar9170 *ar, u32 len, void *buffer)
void carl9170_handle_command_response(struct ar9170 *ar, void *buf, u32 len)
{
- struct carl9170_rsp *cmd = (void *) buf;
+ struct carl9170_rsp *cmd = buf;
struct ieee80211_vif *vif;
- if (carl9170_check_sequence(ar, cmd->hdr.seq))
- return;
-
if ((cmd->hdr.cmd & CARL9170_RSP_FLAG) != CARL9170_RSP_FLAG) {
if (!(cmd->hdr.cmd & CARL9170_CMD_ASYNC_FLAG))
carl9170_cmd_callback(ar, len, buf);
@@ -206,6 +202,7 @@ void carl9170_handle_command_response(struct ar9170 *ar, void *buf, u32 len)
case NL80211_IFTYPE_AP:
case NL80211_IFTYPE_ADHOC:
+ case NL80211_IFTYPE_MESH_POINT:
carl9170_update_beacon(ar, true);
break;
@@ -520,8 +517,9 @@ static u8 *carl9170_find_ie(u8 *data, unsigned int len, u8 ie)
*/
static void carl9170_ps_beacon(struct ar9170 *ar, void *data, unsigned int len)
{
- struct ieee80211_hdr *hdr = (void *) data;
+ struct ieee80211_hdr *hdr = data;
struct ieee80211_tim_ie *tim_ie;
+ struct ath_common *common = &ar->common;
u8 *tim;
u8 tim_len;
bool cam;
@@ -529,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 (compare_ether_addr(hdr->addr3, ar->common.curbssid) ||
- !ar->common.curaid)
+ if (!ath_is_mybeacon(common, hdr) || !common->curaid)
return;
ar->ps.last_beacon = jiffies;
@@ -576,7 +570,55 @@ static void carl9170_ps_beacon(struct ar9170 *ar, void *data, unsigned int len)
}
}
-static bool carl9170_ampdu_check(struct ar9170 *ar, u8 *buf, u8 ms)
+static void carl9170_ba_check(struct ar9170 *ar, void *data, unsigned int len)
+{
+ struct ieee80211_bar *bar = data;
+ struct carl9170_bar_list_entry *entry;
+ unsigned int queue;
+
+ if (likely(!ieee80211_is_back(bar->frame_control)))
+ return;
+
+ if (len <= sizeof(*bar) + FCS_LEN)
+ return;
+
+ queue = TID_TO_WME_AC(((le16_to_cpu(bar->control) &
+ IEEE80211_BAR_CTRL_TID_INFO_MASK) >>
+ IEEE80211_BAR_CTRL_TID_INFO_SHIFT) & 7);
+
+ rcu_read_lock();
+ list_for_each_entry_rcu(entry, &ar->bar_list[queue], list) {
+ struct sk_buff *entry_skb = entry->skb;
+ struct _carl9170_tx_superframe *super = (void *)entry_skb->data;
+ struct ieee80211_bar *entry_bar = (void *)super->frame_data;
+
+#define TID_CHECK(a, b) ( \
+ ((a) & cpu_to_le16(IEEE80211_BAR_CTRL_TID_INFO_MASK)) == \
+ ((b) & cpu_to_le16(IEEE80211_BAR_CTRL_TID_INFO_MASK))) \
+
+ if (bar->start_seq_num == entry_bar->start_seq_num &&
+ TID_CHECK(bar->control, entry_bar->control) &&
+ 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);
+ tx_info->flags |= IEEE80211_TX_STAT_ACK;
+
+ spin_lock_bh(&ar->bar_list_lock[queue]);
+ list_del_rcu(&entry->list);
+ spin_unlock_bh(&ar->bar_list_lock[queue]);
+ kfree_rcu(entry, head);
+ break;
+ }
+ }
+ rcu_read_unlock();
+
+#undef TID_CHECK
+}
+
+static bool carl9170_ampdu_check(struct ar9170 *ar, u8 *buf, u8 ms,
+ struct ieee80211_rx_status *rx_status)
{
__le16 fc;
@@ -589,6 +631,9 @@ static bool carl9170_ampdu_check(struct ar9170 *ar, u8 *buf, u8 ms)
return true;
}
+ rx_status->flag |= RX_FLAG_AMPDU_DETAILS | RX_FLAG_AMPDU_LAST_KNOWN;
+ rx_status->ampdu_reference = ar->ampdu_ref;
+
/*
* "802.11n - 7.4a.3 A-MPDU contents" describes in which contexts
* certain frame types can be part of an aMPDU.
@@ -611,6 +656,35 @@ static bool carl9170_ampdu_check(struct ar9170 *ar, u8 *buf, u8 ms)
return false;
}
+static int carl9170_handle_mpdu(struct ar9170 *ar, u8 *buf, int len,
+ struct ieee80211_rx_status *status)
+{
+ struct sk_buff *skb;
+
+ /* (driver) frame trap handler
+ *
+ * Because power-saving mode handing has to be implemented by
+ * the driver/firmware. We have to check each incoming beacon
+ * from the associated AP, if there's new data for us (either
+ * broadcast/multicast or unicast) we have to react quickly.
+ *
+ * So, if you have you want to add additional frame trap
+ * handlers, this would be the perfect place!
+ */
+
+ carl9170_ps_beacon(ar, buf, len);
+
+ carl9170_ba_check(ar, buf, len);
+
+ skb = carl9170_rx_copy_data(buf, len);
+ if (!skb)
+ return -ENOMEM;
+
+ memcpy(IEEE80211_SKB_RXCB(skb), status, sizeof(*status));
+ ieee80211_rx(ar->hw, skb);
+ return 0;
+}
+
/*
* If the frame alignment is right (or the kernel has
* CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS), and there
@@ -620,14 +694,12 @@ static bool carl9170_ampdu_check(struct ar9170 *ar, u8 *buf, u8 ms)
* mode, and we need to observe the proper ordering,
* this is non-trivial.
*/
-
-static void carl9170_handle_mpdu(struct ar9170 *ar, u8 *buf, int len)
+static void carl9170_rx_untie_data(struct ar9170 *ar, u8 *buf, int len)
{
struct ar9170_rx_head *head;
struct ar9170_rx_macstatus *mac;
struct ar9170_rx_phystatus *phy = NULL;
struct ieee80211_rx_status status;
- struct sk_buff *skb;
int mpdu_len;
u8 mac_status;
@@ -637,12 +709,15 @@ static void carl9170_handle_mpdu(struct ar9170 *ar, u8 *buf, int len)
if (unlikely(len < sizeof(*mac)))
goto drop;
+ memset(&status, 0, sizeof(status));
+
mpdu_len = len - sizeof(*mac);
mac = (void *)(buf + mpdu_len);
mac_status = mac->status;
switch (mac_status & AR9170_RX_STATUS_MPDU) {
case AR9170_RX_STATUS_MPDU_FIRST:
+ ar->ampdu_ref++;
/* Aggregated MPDUs start with an PLCP header */
if (likely(mpdu_len >= sizeof(struct ar9170_rx_head))) {
head = (void *) buf;
@@ -673,12 +748,13 @@ static void carl9170_handle_mpdu(struct ar9170 *ar, u8 *buf, int len)
break;
case AR9170_RX_STATUS_MPDU_LAST:
+ status.flag |= RX_FLAG_AMPDU_IS_LAST;
+
/*
* The last frame of an A-MPDU has an extra tail
* which does contain the phy status of the whole
* aggregate.
*/
-
if (likely(mpdu_len >= sizeof(struct ar9170_rx_phystatus))) {
mpdu_len -= sizeof(struct ar9170_rx_phystatus);
phy = (void *)(buf + mpdu_len);
@@ -726,26 +802,21 @@ static void carl9170_handle_mpdu(struct ar9170 *ar, u8 *buf, int len)
if (unlikely(mpdu_len < (2 + 2 + ETH_ALEN + FCS_LEN)))
goto drop;
- memset(&status, 0, sizeof(status));
if (unlikely(carl9170_rx_mac_status(ar, head, mac, &status)))
goto drop;
- if (!carl9170_ampdu_check(ar, buf, mac_status))
+ if (!carl9170_ampdu_check(ar, buf, mac_status, &status))
goto drop;
if (phy)
carl9170_rx_phy_status(ar, phy, &status);
+ else
+ status.flag |= RX_FLAG_NO_SIGNAL_VAL;
- carl9170_ps_beacon(ar, buf, mpdu_len);
-
- skb = carl9170_rx_copy_data(buf, mpdu_len);
- if (!skb)
+ if (carl9170_handle_mpdu(ar, buf, mpdu_len, &status))
goto drop;
- memcpy(IEEE80211_SKB_RXCB(skb), &status, sizeof(status));
- ieee80211_rx(ar->hw, skb);
return;
-
drop:
ar->rx_dropped++;
}
@@ -763,6 +834,9 @@ static void carl9170_rx_untie_cmds(struct ar9170 *ar, const u8 *respbuf,
if (unlikely(i > resplen))
break;
+ if (carl9170_check_sequence(ar, cmd->hdr.seq))
+ break;
+
carl9170_handle_command_response(ar, cmd, cmd->hdr.len + 4);
}
@@ -794,7 +868,7 @@ static void __carl9170_rx(struct ar9170 *ar, u8 *buf, unsigned int len)
if (i == 12)
carl9170_rx_untie_cmds(ar, buf, len);
else
- carl9170_handle_mpdu(ar, buf, len);
+ carl9170_rx_untie_data(ar, buf, len);
}
static void carl9170_rx_stream(struct ar9170 *ar, void *buf, unsigned int len)
diff --git a/drivers/net/wireless/ath/carl9170/tx.c b/drivers/net/wireless/ath/carl9170/tx.c
index bbc813dee98..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>
@@ -277,11 +276,11 @@ static void carl9170_tx_release(struct kref *ref)
return;
BUILD_BUG_ON(
- offsetof(struct ieee80211_tx_info, status.ampdu_ack_len) != 23);
+ offsetof(struct ieee80211_tx_info, status.ack_signal) != 20);
- memset(&txinfo->status.ampdu_ack_len, 0,
+ memset(&txinfo->status.ack_signal, 0,
sizeof(struct ieee80211_tx_info) -
- offsetof(struct ieee80211_tx_info, status.ampdu_ack_len));
+ offsetof(struct ieee80211_tx_info, status.ack_signal));
if (atomic_read(&ar->tx_total_queued))
ar->tx_schedule = true;
@@ -387,8 +386,7 @@ static void carl9170_tx_status_process_ampdu(struct ar9170 *ar,
u8 tid;
if (!(txinfo->flags & IEEE80211_TX_CTL_AMPDU) ||
- txinfo->flags & IEEE80211_TX_CTL_INJECTED ||
- (!(super->f.mac_control & cpu_to_le16(AR9170_TX_MAC_AGGR))))
+ txinfo->flags & IEEE80211_TX_CTL_INJECTED)
return;
rcu_read_lock();
@@ -436,6 +434,45 @@ out_rcu:
rcu_read_unlock();
}
+static void carl9170_tx_bar_status(struct ar9170 *ar, struct sk_buff *skb,
+ struct ieee80211_tx_info *tx_info)
+{
+ struct _carl9170_tx_superframe *super = (void *) skb->data;
+ struct ieee80211_bar *bar = (void *) super->frame_data;
+
+ /*
+ * Unlike all other frames, the status report for BARs does
+ * not directly come from the hardware as it is incapable of
+ * matching a BA to a previously send BAR.
+ * Instead the RX-path will scan for incoming BAs and set the
+ * IEEE80211_TX_STAT_ACK if it sees one that was likely
+ * caused by a BAR from us.
+ */
+
+ if (unlikely(ieee80211_is_back_req(bar->frame_control)) &&
+ !(tx_info->flags & IEEE80211_TX_STAT_ACK)) {
+ struct carl9170_bar_list_entry *entry;
+ int queue = skb_get_queue_mapping(skb);
+
+ rcu_read_lock();
+ list_for_each_entry_rcu(entry, &ar->bar_list[queue], list) {
+ if (entry->skb == skb) {
+ spin_lock_bh(&ar->bar_list_lock[queue]);
+ list_del_rcu(&entry->list);
+ spin_unlock_bh(&ar->bar_list_lock[queue]);
+ kfree_rcu(entry, head);
+ goto out;
+ }
+ }
+
+ WARN(1, "bar not found in %d - ra:%pM ta:%pM c:%x ssn:%x\n",
+ queue, bar->ra, bar->ta, bar->control,
+ bar->start_seq_num);
+out:
+ rcu_read_unlock();
+ }
+}
+
void carl9170_tx_status(struct ar9170 *ar, struct sk_buff *skb,
const bool success)
{
@@ -445,6 +482,8 @@ void carl9170_tx_status(struct ar9170 *ar, struct sk_buff *skb,
txinfo = IEEE80211_SKB_CB(skb);
+ carl9170_tx_bar_status(ar, skb, txinfo);
+
if (success)
txinfo->flags |= IEEE80211_TX_STAT_ACK;
else
@@ -585,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;
@@ -719,6 +758,8 @@ static void carl9170_tx_rate_tpc_chains(struct ar9170 *ar,
else
*chains = AR9170_TX_PHY_TXCHAIN_2;
}
+
+ *tpc = min_t(unsigned int, *tpc, ar->hw->conf.power_level * 2);
}
static __le32 carl9170_tx_physet(struct ar9170 *ar,
@@ -824,20 +865,105 @@ static bool carl9170_tx_cts_check(struct ar9170 *ar,
return false;
}
-static int carl9170_tx_prepare(struct ar9170 *ar, struct sk_buff *skb)
+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)
{
struct ieee80211_hdr *hdr;
struct _carl9170_tx_superframe *txc;
struct carl9170_vif_info *cvif;
struct ieee80211_tx_info *info;
- struct ieee80211_tx_rate *txrate;
- struct ieee80211_sta *sta;
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) !=
@@ -846,8 +972,6 @@ static int carl9170_tx_prepare(struct ar9170 *ar, struct sk_buff *skb)
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));
@@ -867,8 +991,6 @@ static int carl9170_tx_prepare(struct ar9170 *ar, struct sk_buff *skb)
else
cvif = NULL;
- sta = info->control.sta;
-
txc = (void *)skb_push(skb, sizeof(*txc));
memset(txc, 0, sizeof(*txc));
@@ -891,8 +1013,7 @@ static int carl9170_tx_prepare(struct ar9170 *ar, struct sk_buff *skb)
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) {
@@ -913,8 +1034,7 @@ static int carl9170_tx_prepare(struct ar9170 *ar, struct sk_buff *skb)
}
}
- ampdu = !!(info->flags & IEEE80211_TX_CTL_AMPDU);
- if (ampdu) {
+ if (info->flags & IEEE80211_TX_CTL_AMPDU) {
unsigned int density, factor;
if (unlikely(!sta || !cvif))
@@ -939,67 +1059,11 @@ static int carl9170_tx_prepare(struct ar9170 *ar, struct sk_buff *skb)
SET_VAL(CARL9170_TX_SUPER_AMPDU_FACTOR,
txc->s.ampdu_settings, factor);
-
- for (i = 0; i < CARL9170_TX_MAX_RATES; i++) {
- txrate = &info->control.rates[i];
- if (txrate->idx >= 0) {
- txc->s.ri[i] =
- CARL9170_TX_SUPER_RI_AMPDU;
-
- if (WARN_ON(!(txrate->flags &
- IEEE80211_TX_RC_MCS))) {
- /*
- * Not sure if it's even possible
- * to aggregate non-ht rates with
- * this HW.
- */
- goto err_out;
- }
- continue;
- }
-
- txrate->idx = 0;
- txrate->count = ar->hw->max_rate_tries;
- }
-
- mac_tmp |= cpu_to_le16(AR9170_TX_MAC_AGGR);
}
- /*
- * 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 = 1; i < CARL9170_TX_MAX_RATES; i++) {
- txrate = &info->control.rates[i];
- if (txrate->idx < 0)
- break;
-
- 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);
-
- txc->s.rr[i - 1] = carl9170_tx_physet(ar, info, txrate);
- }
-
- txrate = &info->control.rates[0];
- SET_VAL(CARL9170_TX_SUPER_RI_TRIES, txc->s.ri[0], txrate->count);
-
- 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->s.len = cpu_to_le16(skb->len);
txc->f.length = cpu_to_le16(len + FCS_LEN);
txc->f.mac_control = mac_tmp;
- txc->f.phy_control = carl9170_tx_physet(ar, info, txrate);
arinfo = (void *)info->rate_driver_data;
arinfo->timeout = jiffies;
@@ -1057,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;
@@ -1127,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))
@@ -1137,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);
@@ -1153,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.
*/
@@ -1245,7 +1295,7 @@ static bool carl9170_tx_ps_drop(struct ar9170 *ar, struct sk_buff *skb)
tx_info = IEEE80211_SKB_CB(skb);
if (unlikely(sta_info->sleeping) &&
- !(tx_info->flags & (IEEE80211_TX_CTL_POLL_RESPONSE |
+ !(tx_info->flags & (IEEE80211_TX_CTL_NO_PS_BUFFER |
IEEE80211_TX_CTL_CLEAR_PS_FILT))) {
rcu_read_unlock();
@@ -1263,6 +1313,26 @@ out_rcu:
return false;
}
+static void carl9170_bar_check(struct ar9170 *ar, struct sk_buff *skb)
+{
+ struct _carl9170_tx_superframe *super = (void *) skb->data;
+ struct ieee80211_bar *bar = (void *) super->frame_data;
+
+ if (unlikely(ieee80211_is_back_req(bar->frame_control)) &&
+ skb->len >= sizeof(struct ieee80211_bar)) {
+ struct carl9170_bar_list_entry *entry;
+ unsigned int queue = skb_get_queue_mapping(skb);
+
+ entry = kmalloc(sizeof(*entry), GFP_ATOMIC);
+ if (!WARN_ON_ONCE(!entry)) {
+ entry->skb = skb;
+ spin_lock_bh(&ar->bar_list_lock[queue]);
+ list_add_tail_rcu(&entry->list, &ar->bar_list[queue]);
+ spin_unlock_bh(&ar->bar_list_lock[queue]);
+ }
+ }
+}
+
static void carl9170_tx(struct ar9170 *ar)
{
struct sk_buff *skb;
@@ -1285,6 +1355,8 @@ static void carl9170_tx(struct ar9170 *ar)
if (unlikely(carl9170_tx_ps_drop(ar, skb)))
continue;
+ carl9170_bar_check(ar, skb);
+
atomic_inc(&ar->tx_total_pending);
q = __carl9170_get_queue(ar, i);
@@ -1317,9 +1389,9 @@ static void carl9170_tx(struct ar9170 *ar)
}
static bool carl9170_tx_ampdu_queue(struct ar9170 *ar,
- struct ieee80211_sta *sta, struct sk_buff *skb)
+ struct ieee80211_sta *sta, struct sk_buff *skb,
+ struct ieee80211_tx_info *txinfo)
{
- struct _carl9170_tx_superframe *super = (void *) skb->data;
struct carl9170_sta_info *sta_info;
struct carl9170_sta_tid *agg;
struct sk_buff *iter;
@@ -1386,26 +1458,29 @@ err_unlock:
err_unlock_rcu:
rcu_read_unlock();
- super->f.mac_control &= ~cpu_to_le16(AR9170_TX_MAC_AGGR);
+ txinfo->flags &= ~IEEE80211_TX_CTL_AMPDU;
carl9170_tx_status(ar, skb, false);
ar->tx_dropped++;
return false;
}
-void carl9170_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
+void carl9170_op_tx(struct ieee80211_hw *hw,
+ struct ieee80211_tx_control *control,
+ struct sk_buff *skb)
{
struct ar9170 *ar = hw->priv;
struct ieee80211_tx_info *info;
- struct ieee80211_sta *sta;
+ 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);
- sta = info->control.sta;
+ vif = info->control.vif;
- if (unlikely(carl9170_tx_prepare(ar, skb)))
+ if (unlikely(carl9170_tx_prepare(ar, sta, skb)))
goto err_free;
carl9170_tx_accounting(ar, skb);
@@ -1420,13 +1495,22 @@ void carl9170_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
}
if (info->flags & IEEE80211_TX_CTL_AMPDU) {
- run = carl9170_tx_ampdu_queue(ar, sta, skb);
+ /* to static code analyzers and reviewers:
+ * mac80211 guarantees that a valid "sta"
+ * reference is present, if a frame is to
+ * be part of an ampdu. Hence any extra
+ * sta == NULL checks are redundant in this
+ * special case.
+ */
+ run = carl9170_tx_ampdu_queue(ar, sta, skb, info);
if (run)
carl9170_tx_ampdu(ar);
} 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);
}
@@ -1448,35 +1532,92 @@ void carl9170_tx_scheduler(struct ar9170 *ar)
carl9170_tx(ar);
}
-int carl9170_update_beacon(struct ar9170 *ar, const bool submit)
+/* caller has to take rcu_read_lock */
+static struct carl9170_vif_info *carl9170_pick_beaconing_vif(struct ar9170 *ar)
{
- struct sk_buff *skb = NULL;
struct carl9170_vif_info *cvif;
+ int i = 1;
+
+ /* The AR9170 hardware has no fancy beacon queue or some
+ * other scheduling mechanism. So, the driver has to make
+ * due by setting the two beacon timers (pretbtt and tbtt)
+ * once and then swapping the beacon address in the HW's
+ * register file each time the pretbtt fires.
+ */
+
+ cvif = rcu_dereference(ar->beacon_iter);
+ if (ar->vifs > 0 && cvif) {
+ do {
+ list_for_each_entry_continue_rcu(cvif, &ar->vif_list,
+ list) {
+ if (cvif->active && cvif->enable_beacon)
+ goto out;
+ }
+ } while (ar->beacon_enabled && i--);
+ }
+
+out:
+ rcu_assign_pointer(ar->beacon_iter, cvif);
+ return cvif;
+}
+
+static bool carl9170_tx_beacon_physet(struct ar9170 *ar, struct sk_buff *skb,
+ u32 *ht1, u32 *plcp)
+{
struct ieee80211_tx_info *txinfo;
struct ieee80211_tx_rate *rate;
- __le32 *data, *old = NULL;
- unsigned int plcp, power, chains;
- u32 word, ht1, off, addr, len;
- int i = 0, err = 0;
+ unsigned int power, chains;
+ bool ht_rate;
- rcu_read_lock();
- cvif = rcu_dereference(ar->beacon_iter);
-retry:
- if (ar->vifs == 0 || !cvif)
- goto out_unlock;
+ txinfo = IEEE80211_SKB_CB(skb);
+ rate = &txinfo->control.rates[0];
+ ht_rate = !!(txinfo->control.rates[0].flags & IEEE80211_TX_RC_MCS);
+ carl9170_tx_rate_tpc_chains(ar, txinfo, rate, plcp, &power, &chains);
+
+ *ht1 = AR9170_MAC_BCN_HT1_TX_ANT0;
+ if (chains == AR9170_TX_PHY_TXCHAIN_2)
+ *ht1 |= AR9170_MAC_BCN_HT1_TX_ANT1;
+ SET_VAL(AR9170_MAC_BCN_HT1_PWR_CTRL, *ht1, 7);
+ SET_VAL(AR9170_MAC_BCN_HT1_TPC, *ht1, power);
+ SET_VAL(AR9170_MAC_BCN_HT1_CHAIN_MASK, *ht1, chains);
+
+ if (ht_rate) {
+ *ht1 |= AR9170_MAC_BCN_HT1_HT_EN;
+ if (rate->flags & IEEE80211_TX_RC_SHORT_GI)
+ *plcp |= AR9170_MAC_BCN_HT2_SGI;
- list_for_each_entry_continue_rcu(cvif, &ar->vif_list, list) {
- if (cvif->active && cvif->enable_beacon)
- goto found;
+ if (rate->flags & IEEE80211_TX_RC_40_MHZ_WIDTH) {
+ *ht1 |= AR9170_MAC_BCN_HT1_BWC_40M_SHARED;
+ *plcp |= AR9170_MAC_BCN_HT2_BW40;
+ } else if (rate->flags & IEEE80211_TX_RC_DUP_DATA) {
+ *ht1 |= AR9170_MAC_BCN_HT1_BWC_40M_DUP;
+ *plcp |= AR9170_MAC_BCN_HT2_BW40;
+ }
+
+ SET_VAL(AR9170_MAC_BCN_HT2_LEN, *plcp, skb->len + FCS_LEN);
+ } else {
+ if (*plcp <= AR9170_TX_PHY_RATE_CCK_11M)
+ *plcp |= ((skb->len + FCS_LEN) << (3 + 16)) + 0x0400;
+ else
+ *plcp |= ((skb->len + FCS_LEN) << 16) + 0x0010;
}
- if (!ar->beacon_enabled || i++)
- goto out_unlock;
+ return ht_rate;
+}
- goto retry;
+int carl9170_update_beacon(struct ar9170 *ar, const bool submit)
+{
+ struct sk_buff *skb = NULL;
+ struct carl9170_vif_info *cvif;
+ __le32 *data, *old = NULL;
+ u32 word, ht1, plcp, off, addr, len;
+ int i = 0, err = 0;
+ bool ht_rate;
-found:
- rcu_assign_pointer(ar->beacon_iter, cvif);
+ rcu_read_lock();
+ cvif = carl9170_pick_beaconing_vif(ar);
+ if (!cvif)
+ goto out_unlock;
skb = ieee80211_beacon_get_tim(ar->hw, carl9170_get_vif(cvif),
NULL, NULL);
@@ -1486,7 +1627,6 @@ found:
goto err_free;
}
- txinfo = IEEE80211_SKB_CB(skb);
spin_lock_bh(&ar->beacon_lock);
data = (__le32 *)skb->data;
if (cvif->beacon)
@@ -1516,43 +1656,14 @@ found:
goto err_unlock;
}
- ht1 = AR9170_MAC_BCN_HT1_TX_ANT0;
- rate = &txinfo->control.rates[0];
- carl9170_tx_rate_tpc_chains(ar, txinfo, rate, &plcp, &power, &chains);
- if (!(txinfo->control.rates[0].flags & IEEE80211_TX_RC_MCS)) {
- if (plcp <= AR9170_TX_PHY_RATE_CCK_11M)
- plcp |= ((skb->len + FCS_LEN) << (3 + 16)) + 0x0400;
- else
- plcp |= ((skb->len + FCS_LEN) << 16) + 0x0010;
- } else {
- ht1 |= AR9170_MAC_BCN_HT1_HT_EN;
- if (rate->flags & IEEE80211_TX_RC_SHORT_GI)
- plcp |= AR9170_MAC_BCN_HT2_SGI;
-
- if (rate->flags & IEEE80211_TX_RC_40_MHZ_WIDTH) {
- ht1 |= AR9170_MAC_BCN_HT1_BWC_40M_SHARED;
- plcp |= AR9170_MAC_BCN_HT2_BW40;
- }
- if (rate->flags & IEEE80211_TX_RC_DUP_DATA) {
- ht1 |= AR9170_MAC_BCN_HT1_BWC_40M_DUP;
- plcp |= AR9170_MAC_BCN_HT2_BW40;
- }
-
- SET_VAL(AR9170_MAC_BCN_HT2_LEN, plcp, skb->len + FCS_LEN);
- }
-
- SET_VAL(AR9170_MAC_BCN_HT1_PWR_CTRL, ht1, 7);
- SET_VAL(AR9170_MAC_BCN_HT1_TPC, ht1, power);
- SET_VAL(AR9170_MAC_BCN_HT1_CHAIN_MASK, ht1, chains);
- if (chains == AR9170_TX_PHY_TXCHAIN_2)
- ht1 |= AR9170_MAC_BCN_HT1_TX_ANT1;
+ ht_rate = carl9170_tx_beacon_physet(ar, skb, &ht1, &plcp);
carl9170_async_regwrite_begin(ar);
carl9170_async_regwrite(AR9170_MAC_REG_BCN_HT1, ht1);
- if (!(txinfo->control.rates[0].flags & IEEE80211_TX_RC_MCS))
- carl9170_async_regwrite(AR9170_MAC_REG_BCN_PLCP, plcp);
- else
+ if (ht_rate)
carl9170_async_regwrite(AR9170_MAC_REG_BCN_HT2, plcp);
+ else
+ carl9170_async_regwrite(AR9170_MAC_REG_BCN_PLCP, plcp);
for (i = 0; i < DIV_ROUND_UP(skb->len, 4); i++) {
/*
diff --git a/drivers/net/wireless/ath/carl9170/usb.c b/drivers/net/wireless/ath/carl9170/usb.c
index 89821e4835c..f35c7f30f9a 100644
--- a/drivers/net/wireless/ath/carl9170/usb.c
+++ b/drivers/net/wireless/ath/carl9170/usb.c
@@ -295,6 +295,13 @@ static void carl9170_usb_rx_irq_complete(struct urb *urb)
goto resubmit;
}
+ /*
+ * While the carl9170 firmware does not use this EP, the
+ * firmware loader in the EEPROM unfortunately does.
+ * Therefore we need to be ready to handle out-of-band
+ * responses and traps in case the firmware crashed and
+ * the loader took over again.
+ */
carl9170_handle_command_response(ar, urb->transfer_buffer,
urb->actual_length);
@@ -766,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:
@@ -1069,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)
@@ -1159,6 +1172,7 @@ static struct usb_driver carl9170_driver = {
.resume = carl9170_usb_resume,
.reset_resume = carl9170_usb_resume,
#endif /* CONFIG_PM */
+ .disable_hub_initiated_lpm = 1,
};
module_usb_driver(carl9170_driver);
diff --git a/drivers/net/wireless/ath/carl9170/version.h b/drivers/net/wireless/ath/carl9170/version.h
index e651db85634..2282847d4bb 100644
--- a/drivers/net/wireless/ath/carl9170/version.h
+++ b/drivers/net/wireless/ath/carl9170/version.h
@@ -1,7 +1,7 @@
#ifndef __CARL9170_SHARED_VERSION_H
#define __CARL9170_SHARED_VERSION_H
-#define CARL9170FW_VERSION_YEAR 11
-#define CARL9170FW_VERSION_MONTH 8
+#define CARL9170FW_VERSION_YEAR 12
+#define CARL9170FW_VERSION_MONTH 12
#define CARL9170FW_VERSION_DAY 15
-#define CARL9170FW_VERSION_GIT "1.9.4"
+#define CARL9170FW_VERSION_GIT "1.9.7"
#endif /* __CARL9170_SHARED_VERSION_H */