forked from Minki/linux
wireless-drivers-next patches for 4.8
Major changes: wl18xx * add initial mesh support bcma * serial flash support on non-MIPS SoCs ath10k * enable support for QCA9888 * disable wake_tx_queue() mac80211 op for older devices to workaround throughput regression ath9k * implement temperature compensation support for AR9003+ -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.11 (GNU/Linux) iQEcBAABAgAGBQJXkilmAAoJEG4XJFUm622bWa0H/140nogmko+U1QXTSzVcNeJM dNPwYvkrDu5PPjWL0PekUXT8WVPk6P/SD7Sa93822BQFyR1i5QEWnXX7NMMw8WwW f7uhCdACHoVwIktVj+CTWmat9viknyed2/B9Qbi07tfuhDMKdfi76wHf4frPW5yP wygslKYgyV2Af/18puEcfLeBHDYI61AA1NEO69uPIx5WdT/71YrlwssnH8/xtSlV YElYyApxv7GUVx6Irj6d/YyilvElDbzQlZSLW5zfO2664LW63MGpCY5cnP7K5Nfo pGNVj1f3FpYK8ZncHAlNUH8bJj9snNn7RFYSo//6QAoWv7t4M2T7AbdYhNHK/ko= =a9OQ -----END PGP SIGNATURE----- Merge tag 'wireless-drivers-next-for-davem-2016-07-22' of git://git.kernel.org/pub/scm/linux/kernel/git/kvalo/wireless-drivers-next Kalle Valo says: ==================== pull-request: wireless-drivers-next 2016-07-22 I'm sick so I have to keep this short, but here's the last pull request to net-next. This time there's a trivial conflict with mtd tree: http://lkml.kernel.org/g/20160720123133.44dab209@canb.auug.org.au We concluded with Brian (CCed) that it's best that we ask Linus to fix this. The patches have been in linux-next for a couple of days. This time I haven't done any merge tests so I don't know if there are any other conflicts etc. Please let me know if there are any problems. wireless-drivers-next patches for 4.8 Major changes: wl18xx * add initial mesh support bcma * serial flash support on non-MIPS SoCs ath10k * enable support for QCA9888 * disable wake_tx_queue() mac80211 op for older devices to workaround throughput regression ath9k * implement temperature compensation support for AR9003+ ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
commit
d5b160d342
@ -1,19 +1,30 @@
|
||||
* Texas Instruments wl1271 wireless lan controller
|
||||
* Texas Instruments wl12xx/wl18xx wireless lan controller
|
||||
|
||||
The wl1271 chip can be connected via SPI or via SDIO. This
|
||||
The wl12xx/wl18xx chips can be connected via SPI or via SDIO. This
|
||||
document describes the binding for the SPI connected chip.
|
||||
|
||||
Required properties:
|
||||
- compatible : Should be "ti,wl1271"
|
||||
- compatible : Should be one of the following:
|
||||
* "ti,wl1271"
|
||||
* "ti,wl1273"
|
||||
* "ti,wl1281"
|
||||
* "ti,wl1283"
|
||||
* "ti,wl1801"
|
||||
* "ti,wl1805"
|
||||
* "ti,wl1807"
|
||||
* "ti,wl1831"
|
||||
* "ti,wl1835"
|
||||
* "ti,wl1837"
|
||||
- reg : Chip select address of device
|
||||
- spi-max-frequency : Maximum SPI clocking speed of device in Hz
|
||||
- ref-clock-frequency : Reference clock frequency
|
||||
- interrupt-parent, interrupts :
|
||||
Should contain parameters for 1 interrupt line.
|
||||
Interrupt parameters: parent, line number, type.
|
||||
- vwlan-supply : Point the node of the regulator that powers/enable the wl1271 chip
|
||||
- vwlan-supply : Point the node of the regulator that powers/enable the
|
||||
wl12xx/wl18xx chip
|
||||
|
||||
Optional properties:
|
||||
- ref-clock-frequency : Reference clock frequency (should be set for wl12xx)
|
||||
- clock-xtal : boolean, clock is generated from XTAL
|
||||
|
||||
- Please consult Documentation/devicetree/bindings/spi/spi-bus.txt
|
||||
@ -21,16 +32,28 @@ Optional properties:
|
||||
|
||||
Examples:
|
||||
|
||||
For wl12xx family:
|
||||
&spi1 {
|
||||
wl1271@1 {
|
||||
wlcore: wlcore@1 {
|
||||
compatible = "ti,wl1271";
|
||||
|
||||
reg = <1>;
|
||||
spi-max-frequency = <48000000>;
|
||||
clock-xtal;
|
||||
ref-clock-frequency = <38400000>;
|
||||
interrupt-parent = <&gpio3>;
|
||||
interrupts = <8 IRQ_TYPE_LEVEL_HIGH>;
|
||||
vwlan-supply = <&vwlan_fixed>;
|
||||
clock-xtal;
|
||||
ref-clock-frequency = <38400000>;
|
||||
};
|
||||
};
|
||||
|
||||
For wl18xx family:
|
||||
&spi0 {
|
||||
wlcore: wlcore@0 {
|
||||
compatible = "ti,wl1835";
|
||||
reg = <0>;
|
||||
spi-max-frequency = <48000000>;
|
||||
interrupt-parent = <&gpio0>;
|
||||
interrupts = <27 IRQ_TYPE_EDGE_RISING>;
|
||||
vwlan-supply = <&vwlan_fixed>;
|
||||
};
|
||||
};
|
||||
|
@ -76,9 +76,16 @@ config BCMA_PFLASH
|
||||
default y
|
||||
|
||||
config BCMA_SFLASH
|
||||
bool
|
||||
depends on BCMA_DRIVER_MIPS
|
||||
bool "ChipCommon-attached serial flash support"
|
||||
depends on BCMA_HOST_SOC
|
||||
default y
|
||||
help
|
||||
Some cheap devices have serial flash connected to the ChipCommon
|
||||
instead of independent SPI controller. It requires using a separated
|
||||
driver that implements ChipCommon specific interface communication.
|
||||
|
||||
Enabling this symbol will let bcma recognize serial flash and register
|
||||
it as platform device.
|
||||
|
||||
config BCMA_NFLASH
|
||||
bool
|
||||
|
@ -33,11 +33,12 @@ static bool bcma_wait_reg(struct bcma_bus *bus, void __iomem *addr, u32 mask,
|
||||
void bcma_chipco_b_mii_write(struct bcma_drv_cc_b *ccb, u32 offset, u32 value)
|
||||
{
|
||||
struct bcma_bus *bus = ccb->core->bus;
|
||||
void __iomem *mii = ccb->mii;
|
||||
|
||||
writel(offset, ccb->mii + 0x00);
|
||||
bcma_wait_reg(bus, ccb->mii + 0x00, 0x0100, 0x0000, 100);
|
||||
writel(value, ccb->mii + 0x04);
|
||||
bcma_wait_reg(bus, ccb->mii + 0x00, 0x0100, 0x0000, 100);
|
||||
writel(offset, mii + BCMA_CCB_MII_MNG_CTL);
|
||||
bcma_wait_reg(bus, mii + BCMA_CCB_MII_MNG_CTL, 0x0100, 0x0000, 100);
|
||||
writel(value, mii + BCMA_CCB_MII_MNG_CMD_DATA);
|
||||
bcma_wait_reg(bus, mii + BCMA_CCB_MII_MNG_CTL, 0x0100, 0x0000, 100);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(bcma_chipco_b_mii_write);
|
||||
|
||||
|
@ -295,6 +295,7 @@ static const struct pci_device_id bcma_pci_bridge_tbl[] = {
|
||||
{ PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4359) },
|
||||
{ PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4360) },
|
||||
{ PCI_DEVICE_SUB(PCI_VENDOR_ID_BROADCOM, 0x4365, PCI_VENDOR_ID_DELL, 0x0016) },
|
||||
{ PCI_DEVICE_SUB(PCI_VENDOR_ID_BROADCOM, 0x4365, PCI_VENDOR_ID_FOXCONN, 0xe092) },
|
||||
{ PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x43a0) },
|
||||
{ PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x43a9) },
|
||||
{ PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x43aa) },
|
||||
|
@ -114,7 +114,7 @@ config MTD_SST25L
|
||||
|
||||
config MTD_BCM47XXSFLASH
|
||||
tristate "R/O support for serial flash on BCMA bus"
|
||||
depends on BCMA_SFLASH
|
||||
depends on BCMA_SFLASH && (MIPS || ARM)
|
||||
help
|
||||
BCMA bus can have various flash memories attached, they are
|
||||
registered by bcma as platform devices. This enables driver for
|
||||
|
@ -206,6 +206,28 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
|
||||
.board_ext_size = QCA99X0_BOARD_EXT_DATA_SZ,
|
||||
},
|
||||
},
|
||||
{
|
||||
.id = QCA9888_HW_2_0_DEV_VERSION,
|
||||
.dev_id = QCA9888_2_0_DEVICE_ID,
|
||||
.name = "qca9888 hw2.0",
|
||||
.patch_load_addr = QCA9888_HW_2_0_PATCH_LOAD_ADDR,
|
||||
.uart_pin = 7,
|
||||
.otp_exe_param = 0x00000700,
|
||||
.continuous_frag_desc = true,
|
||||
.channel_counters_freq_hz = 150000,
|
||||
.max_probe_resp_desc_thres = 24,
|
||||
.hw_4addr_pad = ATH10K_HW_4ADDR_PAD_BEFORE,
|
||||
.tx_chain_mask = 3,
|
||||
.rx_chain_mask = 3,
|
||||
.max_spatial_stream = 2,
|
||||
.cal_data_len = 12064,
|
||||
.fw = {
|
||||
.dir = QCA9888_HW_2_0_FW_DIR,
|
||||
.board = QCA9888_HW_2_0_BOARD_DATA_FILE,
|
||||
.board_size = QCA99X0_BOARD_DATA_SZ,
|
||||
.board_ext_size = QCA99X0_BOARD_EXT_DATA_SZ,
|
||||
},
|
||||
},
|
||||
{
|
||||
.id = QCA9377_HW_1_0_DEV_VERSION,
|
||||
.dev_id = QCA9377_1_0_DEVICE_ID,
|
||||
@ -1675,7 +1697,7 @@ static int ath10k_core_init_firmware_features(struct ath10k *ar)
|
||||
case ATH10K_FW_WMI_OP_VERSION_10_4:
|
||||
case ATH10K_FW_WMI_OP_VERSION_UNSET:
|
||||
case ATH10K_FW_WMI_OP_VERSION_MAX:
|
||||
WARN_ON(1);
|
||||
ath10k_err(ar, "htt op version not found from fw meta data");
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
@ -2171,6 +2193,10 @@ struct ath10k *ath10k_core_create(size_t priv_size, struct device *dev,
|
||||
ar->regs = &qca99x0_regs;
|
||||
ar->hw_values = &qca99x0_values;
|
||||
break;
|
||||
case ATH10K_HW_QCA9888:
|
||||
ar->regs = &qca99x0_regs;
|
||||
ar->hw_values = &qca9888_values;
|
||||
break;
|
||||
case ATH10K_HW_QCA4019:
|
||||
ar->regs = &qca4019_regs;
|
||||
ar->hw_values = &qca4019_values;
|
||||
|
@ -165,6 +165,13 @@ struct ath10k_fw_stats_peer {
|
||||
u32 rx_duration;
|
||||
};
|
||||
|
||||
struct ath10k_fw_extd_stats_peer {
|
||||
struct list_head list;
|
||||
|
||||
u8 peer_macaddr[ETH_ALEN];
|
||||
u32 rx_duration;
|
||||
};
|
||||
|
||||
struct ath10k_fw_stats_vdev {
|
||||
struct list_head list;
|
||||
|
||||
@ -256,9 +263,11 @@ struct ath10k_fw_stats_pdev {
|
||||
};
|
||||
|
||||
struct ath10k_fw_stats {
|
||||
bool extended;
|
||||
struct list_head pdevs;
|
||||
struct list_head vdevs;
|
||||
struct list_head peers;
|
||||
struct list_head peers_extd;
|
||||
};
|
||||
|
||||
#define ATH10K_TPC_TABLE_TYPE_FLAG 1
|
||||
@ -667,6 +676,7 @@ struct ath10k_fw_components {
|
||||
struct ath10k {
|
||||
struct ath_common ath_common;
|
||||
struct ieee80211_hw *hw;
|
||||
struct ieee80211_ops *ops;
|
||||
struct device *dev;
|
||||
u8 mac_addr[ETH_ALEN];
|
||||
|
||||
|
@ -313,13 +313,25 @@ static void ath10k_fw_stats_peers_free(struct list_head *head)
|
||||
}
|
||||
}
|
||||
|
||||
static void ath10k_fw_extd_stats_peers_free(struct list_head *head)
|
||||
{
|
||||
struct ath10k_fw_extd_stats_peer *i, *tmp;
|
||||
|
||||
list_for_each_entry_safe(i, tmp, head, list) {
|
||||
list_del(&i->list);
|
||||
kfree(i);
|
||||
}
|
||||
}
|
||||
|
||||
static void ath10k_debug_fw_stats_reset(struct ath10k *ar)
|
||||
{
|
||||
spin_lock_bh(&ar->data_lock);
|
||||
ar->debug.fw_stats_done = false;
|
||||
ar->debug.fw_stats.extended = false;
|
||||
ath10k_fw_stats_pdevs_free(&ar->debug.fw_stats.pdevs);
|
||||
ath10k_fw_stats_vdevs_free(&ar->debug.fw_stats.vdevs);
|
||||
ath10k_fw_stats_peers_free(&ar->debug.fw_stats.peers);
|
||||
ath10k_fw_extd_stats_peers_free(&ar->debug.fw_stats.peers_extd);
|
||||
spin_unlock_bh(&ar->data_lock);
|
||||
}
|
||||
|
||||
@ -334,6 +346,7 @@ void ath10k_debug_fw_stats_process(struct ath10k *ar, struct sk_buff *skb)
|
||||
INIT_LIST_HEAD(&stats.pdevs);
|
||||
INIT_LIST_HEAD(&stats.vdevs);
|
||||
INIT_LIST_HEAD(&stats.peers);
|
||||
INIT_LIST_HEAD(&stats.peers_extd);
|
||||
|
||||
spin_lock_bh(&ar->data_lock);
|
||||
ret = ath10k_wmi_pull_fw_stats(ar, skb, &stats);
|
||||
@ -354,7 +367,7 @@ void ath10k_debug_fw_stats_process(struct ath10k *ar, struct sk_buff *skb)
|
||||
* delivered which is treated as end-of-data and is itself discarded
|
||||
*/
|
||||
if (ath10k_peer_stats_enabled(ar))
|
||||
ath10k_sta_update_rx_duration(ar, &stats.peers);
|
||||
ath10k_sta_update_rx_duration(ar, &stats);
|
||||
|
||||
if (ar->debug.fw_stats_done) {
|
||||
if (!ath10k_peer_stats_enabled(ar))
|
||||
@ -396,6 +409,8 @@ void ath10k_debug_fw_stats_process(struct ath10k *ar, struct sk_buff *skb)
|
||||
|
||||
list_splice_tail_init(&stats.peers, &ar->debug.fw_stats.peers);
|
||||
list_splice_tail_init(&stats.vdevs, &ar->debug.fw_stats.vdevs);
|
||||
list_splice_tail_init(&stats.peers_extd,
|
||||
&ar->debug.fw_stats.peers_extd);
|
||||
}
|
||||
|
||||
complete(&ar->debug.fw_stats_complete);
|
||||
@ -407,6 +422,7 @@ free:
|
||||
ath10k_fw_stats_pdevs_free(&stats.pdevs);
|
||||
ath10k_fw_stats_vdevs_free(&stats.vdevs);
|
||||
ath10k_fw_stats_peers_free(&stats.peers);
|
||||
ath10k_fw_extd_stats_peers_free(&stats.peers_extd);
|
||||
|
||||
spin_unlock_bh(&ar->data_lock);
|
||||
}
|
||||
@ -2330,6 +2346,7 @@ int ath10k_debug_create(struct ath10k *ar)
|
||||
INIT_LIST_HEAD(&ar->debug.fw_stats.pdevs);
|
||||
INIT_LIST_HEAD(&ar->debug.fw_stats.vdevs);
|
||||
INIT_LIST_HEAD(&ar->debug.fw_stats.peers);
|
||||
INIT_LIST_HEAD(&ar->debug.fw_stats.peers_extd);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -154,10 +154,15 @@ ath10k_debug_get_new_fw_crash_data(struct ath10k *ar)
|
||||
#ifdef CONFIG_MAC80211_DEBUGFS
|
||||
void ath10k_sta_add_debugfs(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
|
||||
struct ieee80211_sta *sta, struct dentry *dir);
|
||||
void ath10k_sta_update_rx_duration(struct ath10k *ar, struct list_head *peer);
|
||||
void ath10k_sta_update_rx_duration(struct ath10k *ar,
|
||||
struct ath10k_fw_stats *stats);
|
||||
void ath10k_sta_statistics(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
|
||||
struct ieee80211_sta *sta,
|
||||
struct station_info *sinfo);
|
||||
#else
|
||||
static inline void ath10k_sta_update_rx_duration(struct ath10k *ar,
|
||||
struct list_head *peer)
|
||||
static inline
|
||||
void ath10k_sta_update_rx_duration(struct ath10k *ar,
|
||||
struct ath10k_fw_stats *stats)
|
||||
{
|
||||
}
|
||||
#endif /* CONFIG_MAC80211_DEBUGFS */
|
||||
|
@ -18,13 +18,15 @@
|
||||
#include "wmi-ops.h"
|
||||
#include "debug.h"
|
||||
|
||||
void ath10k_sta_update_rx_duration(struct ath10k *ar, struct list_head *head)
|
||||
{ struct ieee80211_sta *sta;
|
||||
struct ath10k_fw_stats_peer *peer;
|
||||
static void ath10k_sta_update_extd_stats_rx_duration(struct ath10k *ar,
|
||||
struct ath10k_fw_stats *stats)
|
||||
{
|
||||
struct ath10k_fw_extd_stats_peer *peer;
|
||||
struct ieee80211_sta *sta;
|
||||
struct ath10k_sta *arsta;
|
||||
|
||||
rcu_read_lock();
|
||||
list_for_each_entry(peer, head, list) {
|
||||
list_for_each_entry(peer, &stats->peers_extd, list) {
|
||||
sta = ieee80211_find_sta_by_ifaddr(ar->hw, peer->peer_macaddr,
|
||||
NULL);
|
||||
if (!sta)
|
||||
@ -35,6 +37,48 @@ void ath10k_sta_update_rx_duration(struct ath10k *ar, struct list_head *head)
|
||||
rcu_read_unlock();
|
||||
}
|
||||
|
||||
static void ath10k_sta_update_stats_rx_duration(struct ath10k *ar,
|
||||
struct ath10k_fw_stats *stats)
|
||||
{
|
||||
struct ath10k_fw_stats_peer *peer;
|
||||
struct ieee80211_sta *sta;
|
||||
struct ath10k_sta *arsta;
|
||||
|
||||
rcu_read_lock();
|
||||
list_for_each_entry(peer, &stats->peers, list) {
|
||||
sta = ieee80211_find_sta_by_ifaddr(ar->hw, peer->peer_macaddr,
|
||||
NULL);
|
||||
if (!sta)
|
||||
continue;
|
||||
arsta = (struct ath10k_sta *)sta->drv_priv;
|
||||
arsta->rx_duration += (u64)peer->rx_duration;
|
||||
}
|
||||
rcu_read_unlock();
|
||||
}
|
||||
|
||||
void ath10k_sta_update_rx_duration(struct ath10k *ar,
|
||||
struct ath10k_fw_stats *stats)
|
||||
{
|
||||
if (stats->extended)
|
||||
ath10k_sta_update_extd_stats_rx_duration(ar, stats);
|
||||
else
|
||||
ath10k_sta_update_stats_rx_duration(ar, stats);
|
||||
}
|
||||
|
||||
void ath10k_sta_statistics(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
|
||||
struct ieee80211_sta *sta,
|
||||
struct station_info *sinfo)
|
||||
{
|
||||
struct ath10k_sta *arsta = (struct ath10k_sta *)sta->drv_priv;
|
||||
struct ath10k *ar = arsta->arvif->ar;
|
||||
|
||||
if (!ath10k_peer_stats_enabled(ar))
|
||||
return;
|
||||
|
||||
sinfo->rx_duration = arsta->rx_duration;
|
||||
sinfo->filled |= 1ULL << NL80211_STA_INFO_RX_DURATION;
|
||||
}
|
||||
|
||||
static ssize_t ath10k_dbg_sta_read_aggr_mode(struct file *file,
|
||||
char __user *user_buf,
|
||||
size_t count, loff_t *ppos)
|
||||
@ -249,28 +293,6 @@ static const struct file_operations fops_delba = {
|
||||
.llseek = default_llseek,
|
||||
};
|
||||
|
||||
static ssize_t ath10k_dbg_sta_read_rx_duration(struct file *file,
|
||||
char __user *user_buf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
struct ieee80211_sta *sta = file->private_data;
|
||||
struct ath10k_sta *arsta = (struct ath10k_sta *)sta->drv_priv;
|
||||
char buf[100];
|
||||
int len = 0;
|
||||
|
||||
len = scnprintf(buf, sizeof(buf),
|
||||
"%llu usecs\n", arsta->rx_duration);
|
||||
|
||||
return simple_read_from_buffer(user_buf, count, ppos, buf, len);
|
||||
}
|
||||
|
||||
static const struct file_operations fops_rx_duration = {
|
||||
.read = ath10k_dbg_sta_read_rx_duration,
|
||||
.open = simple_open,
|
||||
.owner = THIS_MODULE,
|
||||
.llseek = default_llseek,
|
||||
};
|
||||
|
||||
void ath10k_sta_add_debugfs(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
|
||||
struct ieee80211_sta *sta, struct dentry *dir)
|
||||
{
|
||||
@ -279,6 +301,4 @@ void ath10k_sta_add_debugfs(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
|
||||
debugfs_create_file("addba", S_IWUSR, dir, sta, &fops_addba);
|
||||
debugfs_create_file("addba_resp", S_IWUSR, dir, sta, &fops_addba_resp);
|
||||
debugfs_create_file("delba", S_IWUSR, dir, sta, &fops_delba);
|
||||
debugfs_create_file("rx_duration", S_IRUGO, dir, sta,
|
||||
&fops_rx_duration);
|
||||
}
|
||||
|
@ -22,7 +22,6 @@
|
||||
#include <linux/list.h>
|
||||
#include <linux/bug.h>
|
||||
#include <linux/skbuff.h>
|
||||
#include <linux/semaphore.h>
|
||||
#include <linux/timer.h>
|
||||
|
||||
struct ath10k;
|
||||
|
@ -748,7 +748,7 @@ ath10k_htt_rx_h_peer_channel(struct ath10k *ar, struct htt_rx_desc *rxd)
|
||||
if (WARN_ON_ONCE(!arvif))
|
||||
return NULL;
|
||||
|
||||
if (WARN_ON_ONCE(ath10k_mac_vif_chan(arvif->vif, &def)))
|
||||
if (ath10k_mac_vif_chan(arvif->vif, &def))
|
||||
return NULL;
|
||||
|
||||
return def.chan;
|
||||
@ -2307,12 +2307,10 @@ bool ath10k_htt_t2h_msg_handler(struct ath10k *ar, struct sk_buff *skb)
|
||||
ath10k_htt_rx_delba(ar, resp);
|
||||
break;
|
||||
case HTT_T2H_MSG_TYPE_PKTLOG: {
|
||||
struct ath10k_pktlog_hdr *hdr =
|
||||
(struct ath10k_pktlog_hdr *)resp->pktlog_msg.payload;
|
||||
|
||||
trace_ath10k_htt_pktlog(ar, resp->pktlog_msg.payload,
|
||||
sizeof(*hdr) +
|
||||
__le16_to_cpu(hdr->size));
|
||||
skb->len -
|
||||
offsetof(struct htt_resp,
|
||||
pktlog_msg.payload));
|
||||
break;
|
||||
}
|
||||
case HTT_T2H_MSG_TYPE_RX_FLUSH: {
|
||||
|
@ -49,7 +49,7 @@ static void __ath10k_htt_tx_txq_recalc(struct ieee80211_hw *hw,
|
||||
struct ieee80211_txq *txq)
|
||||
{
|
||||
struct ath10k *ar = hw->priv;
|
||||
struct ath10k_sta *arsta = (void *)txq->sta->drv_priv;
|
||||
struct ath10k_sta *arsta;
|
||||
struct ath10k_vif *arvif = (void *)txq->vif->drv_priv;
|
||||
unsigned long frame_cnt;
|
||||
unsigned long byte_cnt;
|
||||
@ -67,10 +67,12 @@ static void __ath10k_htt_tx_txq_recalc(struct ieee80211_hw *hw,
|
||||
if (ar->htt.tx_q_state.mode != HTT_TX_MODE_SWITCH_PUSH_PULL)
|
||||
return;
|
||||
|
||||
if (txq->sta)
|
||||
if (txq->sta) {
|
||||
arsta = (void *)txq->sta->drv_priv;
|
||||
peer_id = arsta->peer_id;
|
||||
else
|
||||
} else {
|
||||
peer_id = arvif->peer_id;
|
||||
}
|
||||
|
||||
tid = txq->tid;
|
||||
bit = BIT(peer_id % 32);
|
||||
@ -388,6 +390,8 @@ void ath10k_htt_tx_free(struct ath10k_htt *htt)
|
||||
{
|
||||
int size;
|
||||
|
||||
tasklet_kill(&htt->txrx_compl_task);
|
||||
|
||||
idr_for_each(&htt->pending_tx, ath10k_htt_tx_clean_up_pending, htt->ar);
|
||||
idr_destroy(&htt->pending_tx);
|
||||
|
||||
@ -733,16 +737,18 @@ static u8 ath10k_htt_tx_get_vdev_id(struct ath10k *ar, struct sk_buff *skb)
|
||||
{
|
||||
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
|
||||
struct ath10k_skb_cb *cb = ATH10K_SKB_CB(skb);
|
||||
struct ath10k_vif *arvif = (void *)cb->vif->drv_priv;
|
||||
struct ath10k_vif *arvif;
|
||||
|
||||
if (info->flags & IEEE80211_TX_CTL_TX_OFFCHAN)
|
||||
if (info->flags & IEEE80211_TX_CTL_TX_OFFCHAN) {
|
||||
return ar->scan.vdev_id;
|
||||
else if (cb->vif)
|
||||
} else if (cb->vif) {
|
||||
arvif = (void *)cb->vif->drv_priv;
|
||||
return arvif->vdev_id;
|
||||
else if (ar->monitor_started)
|
||||
} else if (ar->monitor_started) {
|
||||
return ar->monitor_vdev_id;
|
||||
else
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
static u8 ath10k_htt_tx_get_tid(struct sk_buff *skb, bool is_eth)
|
||||
|
@ -19,7 +19,6 @@
|
||||
#include "hw.h"
|
||||
|
||||
const struct ath10k_hw_regs qca988x_regs = {
|
||||
.rtc_state_cold_reset_mask = 0x00000400,
|
||||
.rtc_soc_base_address = 0x00004000,
|
||||
.rtc_wmac_base_address = 0x00005000,
|
||||
.soc_core_base_address = 0x00009000,
|
||||
@ -46,7 +45,6 @@ const struct ath10k_hw_regs qca988x_regs = {
|
||||
};
|
||||
|
||||
const struct ath10k_hw_regs qca6174_regs = {
|
||||
.rtc_state_cold_reset_mask = 0x00002000,
|
||||
.rtc_soc_base_address = 0x00000800,
|
||||
.rtc_wmac_base_address = 0x00001000,
|
||||
.soc_core_base_address = 0x0003a000,
|
||||
@ -73,7 +71,6 @@ const struct ath10k_hw_regs qca6174_regs = {
|
||||
};
|
||||
|
||||
const struct ath10k_hw_regs qca99x0_regs = {
|
||||
.rtc_state_cold_reset_mask = 0x00000400,
|
||||
.rtc_soc_base_address = 0x00080000,
|
||||
.rtc_wmac_base_address = 0x00000000,
|
||||
.soc_core_base_address = 0x00082000,
|
||||
@ -168,6 +165,15 @@ const struct ath10k_hw_values qca99x0_values = {
|
||||
.ce_desc_meta_data_lsb = 4,
|
||||
};
|
||||
|
||||
const struct ath10k_hw_values qca9888_values = {
|
||||
.rtc_state_val_on = 3,
|
||||
.ce_count = 12,
|
||||
.msi_assign_ce_max = 12,
|
||||
.num_target_ce_config_wlan = 10,
|
||||
.ce_desc_meta_data_mask = 0xFFF0,
|
||||
.ce_desc_meta_data_lsb = 4,
|
||||
};
|
||||
|
||||
const struct ath10k_hw_values qca4019_values = {
|
||||
.ce_count = 12,
|
||||
.num_target_ce_config_wlan = 10,
|
||||
@ -198,7 +204,8 @@ void ath10k_hw_fill_survey_time(struct ath10k *ar, struct survey_info *survey,
|
||||
case ATH10K_HW_CC_WRAP_SHIFTED_EACH:
|
||||
if (cc < cc_prev)
|
||||
cc_fix = 0x7fffffff;
|
||||
else
|
||||
|
||||
if (rcc < rcc_prev)
|
||||
rcc_fix = 0x7fffffff;
|
||||
break;
|
||||
case ATH10K_HW_CC_WRAP_DISABLED:
|
||||
|
@ -26,6 +26,7 @@
|
||||
#define QCA6164_2_1_DEVICE_ID (0x0041)
|
||||
#define QCA6174_2_1_DEVICE_ID (0x003e)
|
||||
#define QCA99X0_2_0_DEVICE_ID (0x0040)
|
||||
#define QCA9888_2_0_DEVICE_ID (0x0056)
|
||||
#define QCA9984_1_0_DEVICE_ID (0x0046)
|
||||
#define QCA9377_1_0_DEVICE_ID (0x0042)
|
||||
#define QCA9887_1_0_DEVICE_ID (0x0050)
|
||||
@ -108,6 +109,14 @@ enum qca9377_chip_id_rev {
|
||||
#define QCA9984_HW_1_0_BOARD_DATA_FILE "board.bin"
|
||||
#define QCA9984_HW_1_0_PATCH_LOAD_ADDR 0x1234
|
||||
|
||||
/* QCA9888 2.0 defines */
|
||||
#define QCA9888_HW_2_0_DEV_VERSION 0x1000000
|
||||
#define QCA9888_HW_DEV_TYPE 0xc
|
||||
#define QCA9888_HW_2_0_CHIP_ID_REV 0x0
|
||||
#define QCA9888_HW_2_0_FW_DIR ATH10K_FW_DIR "/QCA9888/hw2.0"
|
||||
#define QCA9888_HW_2_0_BOARD_DATA_FILE "board.bin"
|
||||
#define QCA9888_HW_2_0_PATCH_LOAD_ADDR 0x1234
|
||||
|
||||
/* QCA9377 1.0 definitions */
|
||||
#define QCA9377_HW_1_0_FW_DIR ATH10K_FW_DIR "/QCA9377/hw1.0"
|
||||
#define QCA9377_HW_1_0_BOARD_DATA_FILE "board.bin"
|
||||
@ -210,6 +219,7 @@ enum ath10k_hw_rev {
|
||||
ATH10K_HW_QCA988X,
|
||||
ATH10K_HW_QCA6174,
|
||||
ATH10K_HW_QCA99X0,
|
||||
ATH10K_HW_QCA9888,
|
||||
ATH10K_HW_QCA9984,
|
||||
ATH10K_HW_QCA9377,
|
||||
ATH10K_HW_QCA4019,
|
||||
@ -217,7 +227,6 @@ enum ath10k_hw_rev {
|
||||
};
|
||||
|
||||
struct ath10k_hw_regs {
|
||||
u32 rtc_state_cold_reset_mask;
|
||||
u32 rtc_soc_base_address;
|
||||
u32 rtc_wmac_base_address;
|
||||
u32 soc_core_base_address;
|
||||
@ -260,6 +269,7 @@ struct ath10k_hw_values {
|
||||
extern const struct ath10k_hw_values qca988x_values;
|
||||
extern const struct ath10k_hw_values qca6174_values;
|
||||
extern const struct ath10k_hw_values qca99x0_values;
|
||||
extern const struct ath10k_hw_values qca9888_values;
|
||||
extern const struct ath10k_hw_values qca4019_values;
|
||||
|
||||
void ath10k_hw_fill_survey_time(struct ath10k *ar, struct survey_info *survey,
|
||||
@ -269,6 +279,7 @@ void ath10k_hw_fill_survey_time(struct ath10k *ar, struct survey_info *survey,
|
||||
#define QCA_REV_9887(ar) ((ar)->hw_rev == ATH10K_HW_QCA9887)
|
||||
#define QCA_REV_6174(ar) ((ar)->hw_rev == ATH10K_HW_QCA6174)
|
||||
#define QCA_REV_99X0(ar) ((ar)->hw_rev == ATH10K_HW_QCA99X0)
|
||||
#define QCA_REV_9888(ar) ((ar)->hw_rev == ATH10K_HW_QCA9888)
|
||||
#define QCA_REV_9984(ar) ((ar)->hw_rev == ATH10K_HW_QCA9984)
|
||||
#define QCA_REV_9377(ar) ((ar)->hw_rev == ATH10K_HW_QCA9377)
|
||||
#define QCA_REV_40XX(ar) ((ar)->hw_rev == ATH10K_HW_QCA4019)
|
||||
@ -296,25 +307,6 @@ enum ath10k_mcast2ucast_mode {
|
||||
ATH10K_MCAST2UCAST_ENABLED = 1,
|
||||
};
|
||||
|
||||
struct ath10k_pktlog_hdr {
|
||||
__le16 flags;
|
||||
__le16 missed_cnt;
|
||||
__le16 log_type;
|
||||
__le16 size;
|
||||
__le32 timestamp;
|
||||
u8 payload[0];
|
||||
} __packed;
|
||||
|
||||
struct ath10k_pktlog_10_4_hdr {
|
||||
__le16 flags;
|
||||
__le16 missed_cnt;
|
||||
__le16 log_type;
|
||||
__le16 size;
|
||||
__le32 timestamp;
|
||||
__le32 type_specific_data;
|
||||
u8 payload[0];
|
||||
} __packed;
|
||||
|
||||
enum ath10k_hw_rate_ofdm {
|
||||
ATH10K_HW_RATE_OFDM_48M = 0,
|
||||
ATH10K_HW_RATE_OFDM_24M,
|
||||
@ -535,7 +527,6 @@ enum ath10k_hw_cc_wraparound_type {
|
||||
/* as of IP3.7.1 */
|
||||
#define RTC_STATE_V_ON ar->hw_values->rtc_state_val_on
|
||||
|
||||
#define RTC_STATE_COLD_RESET_MASK ar->regs->rtc_state_cold_reset_mask
|
||||
#define RTC_STATE_V_LSB 0
|
||||
#define RTC_STATE_V_MASK 0x00000007
|
||||
#define RTC_STATE_ADDRESS 0x0000
|
||||
|
@ -802,6 +802,7 @@ static void ath10k_peer_cleanup(struct ath10k *ar, u32 vdev_id)
|
||||
{
|
||||
struct ath10k_peer *peer, *tmp;
|
||||
int peer_id;
|
||||
int i;
|
||||
|
||||
lockdep_assert_held(&ar->conf_mutex);
|
||||
|
||||
@ -818,6 +819,17 @@ static void ath10k_peer_cleanup(struct ath10k *ar, u32 vdev_id)
|
||||
ar->peer_map[peer_id] = NULL;
|
||||
}
|
||||
|
||||
/* Double check that peer is properly un-referenced from
|
||||
* the peer_map
|
||||
*/
|
||||
for (i = 0; i < ARRAY_SIZE(ar->peer_map); i++) {
|
||||
if (ar->peer_map[i] == peer) {
|
||||
ath10k_warn(ar, "removing stale peer_map entry for %pM (ptr %p idx %d)\n",
|
||||
peer->addr, peer, i);
|
||||
ar->peer_map[i] = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
list_del(&peer->list);
|
||||
kfree(peer);
|
||||
ar->num_peers--;
|
||||
@ -828,6 +840,7 @@ static void ath10k_peer_cleanup(struct ath10k *ar, u32 vdev_id)
|
||||
static void ath10k_peer_cleanup_all(struct ath10k *ar)
|
||||
{
|
||||
struct ath10k_peer *peer, *tmp;
|
||||
int i;
|
||||
|
||||
lockdep_assert_held(&ar->conf_mutex);
|
||||
|
||||
@ -836,6 +849,10 @@ static void ath10k_peer_cleanup_all(struct ath10k *ar)
|
||||
list_del(&peer->list);
|
||||
kfree(peer);
|
||||
}
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(ar->peer_map); i++)
|
||||
ar->peer_map[i] = NULL;
|
||||
|
||||
spin_unlock_bh(&ar->data_lock);
|
||||
|
||||
ar->num_peers = 0;
|
||||
@ -2939,7 +2956,7 @@ static int ath10k_update_channel_list(struct ath10k *ar)
|
||||
if (channel->flags & IEEE80211_CHAN_DISABLED)
|
||||
continue;
|
||||
|
||||
ch->allow_ht = true;
|
||||
ch->allow_ht = true;
|
||||
|
||||
/* FIXME: when should we really allow VHT? */
|
||||
ch->allow_vht = true;
|
||||
@ -3675,17 +3692,18 @@ void ath10k_mgmt_over_wmi_tx_work(struct work_struct *work)
|
||||
|
||||
static void ath10k_mac_txq_init(struct ieee80211_txq *txq)
|
||||
{
|
||||
struct ath10k_txq *artxq = (void *)txq->drv_priv;
|
||||
struct ath10k_txq *artxq;
|
||||
|
||||
if (!txq)
|
||||
return;
|
||||
|
||||
artxq = (void *)txq->drv_priv;
|
||||
INIT_LIST_HEAD(&artxq->list);
|
||||
}
|
||||
|
||||
static void ath10k_mac_txq_unref(struct ath10k *ar, struct ieee80211_txq *txq)
|
||||
{
|
||||
struct ath10k_txq *artxq = (void *)txq->drv_priv;
|
||||
struct ath10k_txq *artxq;
|
||||
struct ath10k_skb_cb *cb;
|
||||
struct sk_buff *msdu;
|
||||
int msdu_id;
|
||||
@ -3693,6 +3711,7 @@ static void ath10k_mac_txq_unref(struct ath10k *ar, struct ieee80211_txq *txq)
|
||||
if (!txq)
|
||||
return;
|
||||
|
||||
artxq = (void *)txq->drv_priv;
|
||||
spin_lock_bh(&ar->txqs_lock);
|
||||
if (!list_empty(&artxq->list))
|
||||
list_del_init(&artxq->list);
|
||||
@ -4228,6 +4247,9 @@ static struct ieee80211_sta_vht_cap ath10k_create_vht_cap(struct ath10k *ar)
|
||||
mcs_map |= IEEE80211_VHT_MCS_NOT_SUPPORTED << (i * 2);
|
||||
}
|
||||
|
||||
if (ar->cfg_tx_chainmask <= 1)
|
||||
vht_cap.cap &= ~IEEE80211_VHT_CAP_TXSTBC;
|
||||
|
||||
vht_cap.vht_mcs.rx_mcs_map = cpu_to_le16(mcs_map);
|
||||
vht_cap.vht_mcs.tx_mcs_map = cpu_to_le16(mcs_map);
|
||||
|
||||
@ -4265,7 +4287,7 @@ static struct ieee80211_sta_ht_cap ath10k_get_ht_cap(struct ath10k *ar)
|
||||
ht_cap.cap |= smps;
|
||||
}
|
||||
|
||||
if (ar->ht_cap_info & WMI_HT_CAP_TX_STBC)
|
||||
if (ar->ht_cap_info & WMI_HT_CAP_TX_STBC && (ar->cfg_tx_chainmask > 1))
|
||||
ht_cap.cap |= IEEE80211_HT_CAP_TX_STBC;
|
||||
|
||||
if (ar->ht_cap_info & WMI_HT_CAP_RX_STBC) {
|
||||
@ -5979,9 +6001,17 @@ static int ath10k_sta_state(struct ieee80211_hw *hw,
|
||||
continue;
|
||||
|
||||
if (peer->sta == sta) {
|
||||
ath10k_warn(ar, "found sta peer %pM entry on vdev %i after it was supposedly removed\n",
|
||||
sta->addr, arvif->vdev_id);
|
||||
ath10k_warn(ar, "found sta peer %pM (ptr %p id %d) entry on vdev %i after it was supposedly removed\n",
|
||||
sta->addr, peer, i, arvif->vdev_id);
|
||||
peer->sta = NULL;
|
||||
|
||||
/* Clean up the peer object as well since we
|
||||
* must have failed to do this above.
|
||||
*/
|
||||
list_del(&peer->list);
|
||||
ar->peer_map[i] = NULL;
|
||||
kfree(peer);
|
||||
ar->num_peers--;
|
||||
}
|
||||
}
|
||||
spin_unlock_bh(&ar->data_lock);
|
||||
@ -7406,6 +7436,7 @@ static const struct ieee80211_ops ath10k_ops = {
|
||||
#endif
|
||||
#ifdef CONFIG_MAC80211_DEBUGFS
|
||||
.sta_add_debugfs = ath10k_sta_add_debugfs,
|
||||
.sta_statistics = ath10k_sta_statistics,
|
||||
#endif
|
||||
};
|
||||
|
||||
@ -7475,21 +7506,32 @@ static const struct ieee80211_channel ath10k_5ghz_channels[] = {
|
||||
struct ath10k *ath10k_mac_create(size_t priv_size)
|
||||
{
|
||||
struct ieee80211_hw *hw;
|
||||
struct ieee80211_ops *ops;
|
||||
struct ath10k *ar;
|
||||
|
||||
hw = ieee80211_alloc_hw(sizeof(struct ath10k) + priv_size, &ath10k_ops);
|
||||
if (!hw)
|
||||
ops = kmemdup(&ath10k_ops, sizeof(ath10k_ops), GFP_KERNEL);
|
||||
if (!ops)
|
||||
return NULL;
|
||||
|
||||
hw = ieee80211_alloc_hw(sizeof(struct ath10k) + priv_size, ops);
|
||||
if (!hw) {
|
||||
kfree(ops);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ar = hw->priv;
|
||||
ar->hw = hw;
|
||||
ar->ops = ops;
|
||||
|
||||
return ar;
|
||||
}
|
||||
|
||||
void ath10k_mac_destroy(struct ath10k *ar)
|
||||
{
|
||||
struct ieee80211_ops *ops = ar->ops;
|
||||
|
||||
ieee80211_free_hw(ar->hw);
|
||||
kfree(ops);
|
||||
}
|
||||
|
||||
static const struct ieee80211_iface_limit ath10k_if_limits[] = {
|
||||
@ -7923,6 +7965,15 @@ int ath10k_mac_register(struct ath10k *ar)
|
||||
ath10k_warn(ar, "failed to initialise DFS pattern detector\n");
|
||||
}
|
||||
|
||||
/* Current wake_tx_queue implementation imposes a significant
|
||||
* performance penalty in some setups. The tx scheduling code needs
|
||||
* more work anyway so disable the wake_tx_queue unless firmware
|
||||
* supports the pull-push mechanism.
|
||||
*/
|
||||
if (!test_bit(ATH10K_FW_FEATURE_PEER_FLOW_CONTROL,
|
||||
ar->running_fw->fw_file.fw_features))
|
||||
ar->ops->wake_tx_queue = NULL;
|
||||
|
||||
ret = ath_regd_init(&ar->ath_common.regulatory, ar->hw->wiphy,
|
||||
ath10k_reg_notifier);
|
||||
if (ret) {
|
||||
|
@ -56,6 +56,7 @@ static const struct pci_device_id ath10k_pci_id_table[] = {
|
||||
{ PCI_VDEVICE(ATHEROS, QCA6164_2_1_DEVICE_ID) }, /* PCI-E QCA6164 V2.1 */
|
||||
{ PCI_VDEVICE(ATHEROS, QCA6174_2_1_DEVICE_ID) }, /* PCI-E QCA6174 V2.1 */
|
||||
{ PCI_VDEVICE(ATHEROS, QCA99X0_2_0_DEVICE_ID) }, /* PCI-E QCA99X0 V2 */
|
||||
{ PCI_VDEVICE(ATHEROS, QCA9888_2_0_DEVICE_ID) }, /* PCI-E QCA9888 V2 */
|
||||
{ PCI_VDEVICE(ATHEROS, QCA9984_1_0_DEVICE_ID) }, /* PCI-E QCA9984 V1 */
|
||||
{ PCI_VDEVICE(ATHEROS, QCA9377_1_0_DEVICE_ID) }, /* PCI-E QCA9377 V1 */
|
||||
{ PCI_VDEVICE(ATHEROS, QCA9887_1_0_DEVICE_ID) }, /* PCI-E QCA9887 */
|
||||
@ -85,6 +86,8 @@ static const struct ath10k_pci_supp_chip ath10k_pci_supp_chips[] = {
|
||||
|
||||
{ QCA9984_1_0_DEVICE_ID, QCA9984_HW_1_0_CHIP_ID_REV },
|
||||
|
||||
{ QCA9888_2_0_DEVICE_ID, QCA9888_HW_2_0_CHIP_ID_REV },
|
||||
|
||||
{ QCA9377_1_0_DEVICE_ID, QCA9377_HW_1_0_CHIP_ID_REV },
|
||||
{ QCA9377_1_0_DEVICE_ID, QCA9377_HW_1_1_CHIP_ID_REV },
|
||||
|
||||
@ -850,6 +853,7 @@ static u32 ath10k_pci_targ_cpu_to_ce_addr(struct ath10k *ar, u32 addr)
|
||||
CORE_CTRL_ADDRESS) &
|
||||
0x7ff) << 21;
|
||||
break;
|
||||
case ATH10K_HW_QCA9888:
|
||||
case ATH10K_HW_QCA99X0:
|
||||
case ATH10K_HW_QCA9984:
|
||||
case ATH10K_HW_QCA4019:
|
||||
@ -1583,6 +1587,7 @@ static void ath10k_pci_irq_msi_fw_mask(struct ath10k *ar)
|
||||
break;
|
||||
case ATH10K_HW_QCA99X0:
|
||||
case ATH10K_HW_QCA9984:
|
||||
case ATH10K_HW_QCA9888:
|
||||
case ATH10K_HW_QCA4019:
|
||||
/* TODO: Find appropriate register configuration for QCA99X0
|
||||
* to mask irq/MSI.
|
||||
@ -1608,6 +1613,7 @@ static void ath10k_pci_irq_msi_fw_unmask(struct ath10k *ar)
|
||||
break;
|
||||
case ATH10K_HW_QCA99X0:
|
||||
case ATH10K_HW_QCA9984:
|
||||
case ATH10K_HW_QCA9888:
|
||||
case ATH10K_HW_QCA4019:
|
||||
/* TODO: Find appropriate register configuration for QCA99X0
|
||||
* to unmask irq/MSI.
|
||||
@ -1948,6 +1954,7 @@ static int ath10k_pci_get_num_banks(struct ath10k *ar)
|
||||
switch (ar_pci->pdev->device) {
|
||||
case QCA988X_2_0_DEVICE_ID:
|
||||
case QCA99X0_2_0_DEVICE_ID:
|
||||
case QCA9888_2_0_DEVICE_ID:
|
||||
case QCA9984_1_0_DEVICE_ID:
|
||||
case QCA9887_1_0_DEVICE_ID:
|
||||
return 1;
|
||||
@ -2216,6 +2223,14 @@ static void ath10k_pci_fw_crashed_clear(struct ath10k *ar)
|
||||
ath10k_pci_write32(ar, FW_INDICATOR_ADDRESS, val);
|
||||
}
|
||||
|
||||
static bool ath10k_pci_has_device_gone(struct ath10k *ar)
|
||||
{
|
||||
u32 val;
|
||||
|
||||
val = ath10k_pci_read32(ar, FW_INDICATOR_ADDRESS);
|
||||
return (val == 0xffffffff);
|
||||
}
|
||||
|
||||
/* this function effectively clears target memory controller assert line */
|
||||
static void ath10k_pci_warm_reset_si0(struct ath10k *ar)
|
||||
{
|
||||
@ -2748,6 +2763,9 @@ static irqreturn_t ath10k_pci_interrupt_handler(int irq, void *arg)
|
||||
struct ath10k_pci *ar_pci = ath10k_pci_priv(ar);
|
||||
int ret;
|
||||
|
||||
if (ath10k_pci_has_device_gone(ar))
|
||||
return IRQ_NONE;
|
||||
|
||||
ret = ath10k_pci_force_wake(ar);
|
||||
if (ret) {
|
||||
ath10k_warn(ar, "failed to wake device up on irq: %d\n", ret);
|
||||
@ -3169,6 +3187,12 @@ static int ath10k_pci_probe(struct pci_dev *pdev,
|
||||
pci_soft_reset = ath10k_pci_qca99x0_soft_chip_reset;
|
||||
pci_hard_reset = ath10k_pci_qca99x0_chip_reset;
|
||||
break;
|
||||
case QCA9888_2_0_DEVICE_ID:
|
||||
hw_rev = ATH10K_HW_QCA9888;
|
||||
pci_ps = false;
|
||||
pci_soft_reset = ath10k_pci_qca99x0_soft_chip_reset;
|
||||
pci_hard_reset = ath10k_pci_qca99x0_chip_reset;
|
||||
break;
|
||||
case QCA9377_1_0_DEVICE_ID:
|
||||
hw_rev = ATH10K_HW_QCA9377;
|
||||
pci_ps = true;
|
||||
|
@ -101,9 +101,9 @@ int ath10k_spectral_process_fft(struct ath10k *ar,
|
||||
break;
|
||||
case 80:
|
||||
/* TODO: As experiments with an analogue sender and various
|
||||
* configuaritions (fft-sizes of 64/128/256 and 20/40/80 Mhz)
|
||||
* configurations (fft-sizes of 64/128/256 and 20/40/80 Mhz)
|
||||
* show, the particular configuration of 80 MHz/64 bins does
|
||||
* not match with the other smaples at all. Until the reason
|
||||
* not match with the other samples at all. Until the reason
|
||||
* for that is found, don't report these samples.
|
||||
*/
|
||||
if (bin_len == 64)
|
||||
|
@ -81,10 +81,11 @@ int ath10k_txrx_tx_unref(struct ath10k_htt *htt,
|
||||
|
||||
skb_cb = ATH10K_SKB_CB(msdu);
|
||||
txq = skb_cb->txq;
|
||||
artxq = (void *)txq->drv_priv;
|
||||
|
||||
if (txq)
|
||||
if (txq) {
|
||||
artxq = (void *)txq->drv_priv;
|
||||
artxq->num_fw_queued--;
|
||||
}
|
||||
|
||||
ath10k_htt_tx_free_msdu_id(htt, tx_done->msdu_id);
|
||||
ath10k_htt_tx_dec_pending(htt);
|
||||
@ -216,6 +217,7 @@ void ath10k_peer_map_event(struct ath10k_htt *htt,
|
||||
ath10k_dbg(ar, ATH10K_DBG_HTT, "htt peer map vdev %d peer %pM id %d\n",
|
||||
ev->vdev_id, ev->addr, ev->peer_id);
|
||||
|
||||
WARN_ON(ar->peer_map[ev->peer_id] && (ar->peer_map[ev->peer_id] != peer));
|
||||
ar->peer_map[ev->peer_id] = peer;
|
||||
set_bit(ev->peer_id, peer->peer_ids);
|
||||
exit:
|
||||
|
@ -1826,7 +1826,7 @@ static struct sk_buff *
|
||||
ath10k_wmi_op_gen_mgmt_tx(struct ath10k *ar, struct sk_buff *msdu)
|
||||
{
|
||||
struct ath10k_skb_cb *cb = ATH10K_SKB_CB(msdu);
|
||||
struct ath10k_vif *arvif = (void *)cb->vif->drv_priv;
|
||||
struct ath10k_vif *arvif;
|
||||
struct wmi_mgmt_tx_cmd *cmd;
|
||||
struct ieee80211_hdr *hdr;
|
||||
struct sk_buff *skb;
|
||||
@ -1838,10 +1838,12 @@ ath10k_wmi_op_gen_mgmt_tx(struct ath10k *ar, struct sk_buff *msdu)
|
||||
hdr = (struct ieee80211_hdr *)msdu->data;
|
||||
fc = le16_to_cpu(hdr->frame_control);
|
||||
|
||||
if (cb->vif)
|
||||
if (cb->vif) {
|
||||
arvif = (void *)cb->vif->drv_priv;
|
||||
vdev_id = arvif->vdev_id;
|
||||
else
|
||||
} else {
|
||||
vdev_id = 0;
|
||||
}
|
||||
|
||||
if (WARN_ON_ONCE(!ieee80211_is_mgmt(hdr->frame_control)))
|
||||
return ERR_PTR(-EINVAL);
|
||||
@ -2924,6 +2926,7 @@ static int ath10k_wmi_10_4_op_pull_fw_stats(struct ath10k *ar,
|
||||
u32 num_pdev_ext_stats;
|
||||
u32 num_vdev_stats;
|
||||
u32 num_peer_stats;
|
||||
u32 num_bcnflt_stats;
|
||||
u32 stats_id;
|
||||
int i;
|
||||
|
||||
@ -2934,6 +2937,7 @@ static int ath10k_wmi_10_4_op_pull_fw_stats(struct ath10k *ar,
|
||||
num_pdev_ext_stats = __le32_to_cpu(ev->num_pdev_ext_stats);
|
||||
num_vdev_stats = __le32_to_cpu(ev->num_vdev_stats);
|
||||
num_peer_stats = __le32_to_cpu(ev->num_peer_stats);
|
||||
num_bcnflt_stats = __le32_to_cpu(ev->num_bcnflt_stats);
|
||||
stats_id = __le32_to_cpu(ev->stats_id);
|
||||
|
||||
for (i = 0; i < num_pdev_stats; i++) {
|
||||
@ -2974,32 +2978,57 @@ static int ath10k_wmi_10_4_op_pull_fw_stats(struct ath10k *ar,
|
||||
/* fw doesn't implement vdev stats */
|
||||
|
||||
for (i = 0; i < num_peer_stats; i++) {
|
||||
const struct wmi_10_4_peer_extd_stats *src;
|
||||
const struct wmi_10_4_peer_stats *src;
|
||||
struct ath10k_fw_stats_peer *dst;
|
||||
int stats_len;
|
||||
bool extd_peer_stats = !!(stats_id & WMI_10_4_STAT_PEER_EXTD);
|
||||
|
||||
if (extd_peer_stats)
|
||||
stats_len = sizeof(struct wmi_10_4_peer_extd_stats);
|
||||
else
|
||||
stats_len = sizeof(struct wmi_10_4_peer_stats);
|
||||
|
||||
src = (void *)skb->data;
|
||||
if (!skb_pull(skb, stats_len))
|
||||
if (!skb_pull(skb, sizeof(*src)))
|
||||
return -EPROTO;
|
||||
|
||||
dst = kzalloc(sizeof(*dst), GFP_ATOMIC);
|
||||
if (!dst)
|
||||
continue;
|
||||
|
||||
ath10k_wmi_10_4_pull_peer_stats(&src->common, dst);
|
||||
/* FIXME: expose 10.4 specific values */
|
||||
if (extd_peer_stats)
|
||||
dst->rx_duration = __le32_to_cpu(src->rx_duration);
|
||||
|
||||
ath10k_wmi_10_4_pull_peer_stats(src, dst);
|
||||
list_add_tail(&dst->list, &stats->peers);
|
||||
}
|
||||
|
||||
for (i = 0; i < num_bcnflt_stats; i++) {
|
||||
const struct wmi_10_4_bss_bcn_filter_stats *src;
|
||||
|
||||
src = (void *)skb->data;
|
||||
if (!skb_pull(skb, sizeof(*src)))
|
||||
return -EPROTO;
|
||||
|
||||
/* FIXME: expose values to userspace
|
||||
*
|
||||
* Note: Even though this loop seems to do nothing it is
|
||||
* required to parse following sub-structures properly.
|
||||
*/
|
||||
}
|
||||
|
||||
if ((stats_id & WMI_10_4_STAT_PEER_EXTD) == 0)
|
||||
return 0;
|
||||
|
||||
stats->extended = true;
|
||||
|
||||
for (i = 0; i < num_peer_stats; i++) {
|
||||
const struct wmi_10_4_peer_extd_stats *src;
|
||||
struct ath10k_fw_extd_stats_peer *dst;
|
||||
|
||||
src = (void *)skb->data;
|
||||
if (!skb_pull(skb, sizeof(*src)))
|
||||
return -EPROTO;
|
||||
|
||||
dst = kzalloc(sizeof(*dst), GFP_ATOMIC);
|
||||
if (!dst)
|
||||
continue;
|
||||
|
||||
ether_addr_copy(dst->peer_macaddr, src->peer_macaddr.addr);
|
||||
dst->rx_duration = __le32_to_cpu(src->rx_duration);
|
||||
list_add_tail(&dst->list, &stats->peers_extd);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -5257,6 +5286,9 @@ static void ath10k_wmi_10_4_op_rx(struct ath10k *ar, struct sk_buff *skb)
|
||||
case WMI_10_4_PEER_STA_KICKOUT_EVENTID:
|
||||
ath10k_wmi_event_peer_sta_kickout(ar, skb);
|
||||
break;
|
||||
case WMI_10_4_ROAM_EVENTID:
|
||||
ath10k_wmi_event_roam(ar, skb);
|
||||
break;
|
||||
case WMI_10_4_HOST_SWBA_EVENTID:
|
||||
ath10k_wmi_event_host_swba(ar, skb);
|
||||
break;
|
||||
@ -7903,6 +7935,7 @@ static const struct wmi_ops wmi_10_4_ops = {
|
||||
.pull_phyerr = ath10k_wmi_10_4_op_pull_phyerr_ev,
|
||||
.pull_svc_rdy = ath10k_wmi_main_op_pull_svc_rdy_ev,
|
||||
.pull_rdy = ath10k_wmi_op_pull_rdy_ev,
|
||||
.pull_roam_ev = ath10k_wmi_op_pull_roam_ev,
|
||||
.get_txbf_conf_scheme = ath10k_wmi_10_4_txbf_conf_scheme,
|
||||
|
||||
.gen_pdev_suspend = ath10k_wmi_op_gen_pdev_suspend,
|
||||
|
@ -4340,7 +4340,6 @@ struct wmi_10_4_peer_stats {
|
||||
} __packed;
|
||||
|
||||
struct wmi_10_4_peer_extd_stats {
|
||||
struct wmi_10_4_peer_stats common;
|
||||
struct wmi_mac_addr peer_macaddr;
|
||||
__le32 inactive_time;
|
||||
__le32 peer_chain_rssi;
|
||||
@ -4348,6 +4347,19 @@ struct wmi_10_4_peer_extd_stats {
|
||||
__le32 reserved[10];
|
||||
} __packed;
|
||||
|
||||
struct wmi_10_4_bss_bcn_stats {
|
||||
__le32 vdev_id;
|
||||
__le32 bss_bcns_dropped;
|
||||
__le32 bss_bcn_delivered;
|
||||
} __packed;
|
||||
|
||||
struct wmi_10_4_bss_bcn_filter_stats {
|
||||
__le32 bcns_dropped;
|
||||
__le32 bcns_delivered;
|
||||
__le32 active_filters;
|
||||
struct wmi_10_4_bss_bcn_stats bss_stats;
|
||||
} __packed;
|
||||
|
||||
struct wmi_10_2_pdev_ext_stats {
|
||||
__le32 rx_rssi_comb;
|
||||
__le32 rx_rssi[4];
|
||||
|
@ -847,8 +847,6 @@ static int ath6kl_cfg80211_disconnect(struct wiphy *wiphy,
|
||||
|
||||
up(&ar->sem);
|
||||
|
||||
vif->sme_state = SME_DISCONNECTED;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -1111,7 +1109,8 @@ void ath6kl_cfg80211_ch_switch_notify(struct ath6kl_vif *vif, int freq,
|
||||
|
||||
cfg80211_chandef_create(&chandef,
|
||||
ieee80211_get_channel(vif->ar->wiphy, freq),
|
||||
(mode == WMI_11G_HT20) ?
|
||||
(mode == WMI_11G_HT20 &&
|
||||
ath6kl_band_2ghz.ht_cap.ht_supported) ?
|
||||
NL80211_CHAN_HT20 : NL80211_CHAN_NO_HT);
|
||||
|
||||
mutex_lock(&vif->wdev.mtx);
|
||||
@ -2978,6 +2977,7 @@ static int ath6kl_stop_ap(struct wiphy *wiphy, struct net_device *dev)
|
||||
|
||||
ath6kl_wmi_disconnect_cmd(ar->wmi, vif->fw_vif_idx);
|
||||
clear_bit(CONNECTED, &vif->flags);
|
||||
netif_carrier_off(vif->ndev);
|
||||
|
||||
/* Restore ht setting in firmware */
|
||||
return ath6kl_restore_htcap(vif);
|
||||
|
@ -1401,6 +1401,10 @@ void ath6kl_rx(struct htc_target *target, struct htc_packet *packet)
|
||||
return;
|
||||
}
|
||||
|
||||
pad_before_data_start =
|
||||
(le16_to_cpu(dhdr->info3) >> WMI_DATA_HDR_PAD_BEFORE_DATA_SHIFT)
|
||||
& WMI_DATA_HDR_PAD_BEFORE_DATA_MASK;
|
||||
|
||||
/* Get the Power save state of the STA */
|
||||
if (vif->nw_type == AP_NETWORK) {
|
||||
meta_type = wmi_data_hdr_get_meta(dhdr);
|
||||
@ -1408,7 +1412,7 @@ void ath6kl_rx(struct htc_target *target, struct htc_packet *packet)
|
||||
ps_state = !!((dhdr->info >> WMI_DATA_HDR_PS_SHIFT) &
|
||||
WMI_DATA_HDR_PS_MASK);
|
||||
|
||||
offset = sizeof(struct wmi_data_hdr);
|
||||
offset = sizeof(struct wmi_data_hdr) + pad_before_data_start;
|
||||
trig_state = !!(le16_to_cpu(dhdr->info3) & WMI_DATA_HDR_TRIG);
|
||||
|
||||
switch (meta_type) {
|
||||
@ -1523,9 +1527,6 @@ void ath6kl_rx(struct htc_target *target, struct htc_packet *packet)
|
||||
seq_no = wmi_data_hdr_get_seqno(dhdr);
|
||||
meta_type = wmi_data_hdr_get_meta(dhdr);
|
||||
dot11_hdr = wmi_data_hdr_get_dot11(dhdr);
|
||||
pad_before_data_start =
|
||||
(le16_to_cpu(dhdr->info3) >> WMI_DATA_HDR_PAD_BEFORE_DATA_SHIFT)
|
||||
& WMI_DATA_HDR_PAD_BEFORE_DATA_MASK;
|
||||
|
||||
skb_pull(skb, sizeof(struct wmi_data_hdr));
|
||||
|
||||
|
@ -18,7 +18,6 @@
|
||||
|
||||
#include <linux/nl80211.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/ath9k_platform.h>
|
||||
#include <linux/module.h>
|
||||
#include "ath9k.h"
|
||||
|
||||
@ -58,20 +57,9 @@ static void ath_ahb_read_cachesize(struct ath_common *common, int *csz)
|
||||
|
||||
static bool ath_ahb_eeprom_read(struct ath_common *common, u32 off, u16 *data)
|
||||
{
|
||||
struct ath_softc *sc = (struct ath_softc *)common->priv;
|
||||
struct platform_device *pdev = to_platform_device(sc->dev);
|
||||
struct ath9k_platform_data *pdata;
|
||||
|
||||
pdata = dev_get_platdata(&pdev->dev);
|
||||
if (off >= (ARRAY_SIZE(pdata->eeprom_data))) {
|
||||
ath_err(common,
|
||||
"%s: flash read failed, offset %08x is out of range\n",
|
||||
__func__, off);
|
||||
return false;
|
||||
}
|
||||
|
||||
*data = pdata->eeprom_data[off];
|
||||
return true;
|
||||
ath_err(common, "%s: eeprom data has to be provided externally\n",
|
||||
__func__);
|
||||
return false;
|
||||
}
|
||||
|
||||
static struct ath_bus_ops ath_ahb_bus_ops = {
|
||||
|
@ -476,6 +476,7 @@ static void ar9002_hw_set_bt_ant_diversity(struct ath_hw *ah, bool enable)
|
||||
static void ar9002_hw_spectral_scan_config(struct ath_hw *ah,
|
||||
struct ath_spec_scan *param)
|
||||
{
|
||||
u32 repeat_bit;
|
||||
u8 count;
|
||||
|
||||
if (!param->enabled) {
|
||||
@ -486,12 +487,15 @@ static void ar9002_hw_spectral_scan_config(struct ath_hw *ah,
|
||||
REG_SET_BIT(ah, AR_PHY_RADAR_0, AR_PHY_RADAR_0_FFT_ENA);
|
||||
REG_SET_BIT(ah, AR_PHY_SPECTRAL_SCAN, AR_PHY_SPECTRAL_SCAN_ENABLE);
|
||||
|
||||
if (param->short_repeat)
|
||||
REG_SET_BIT(ah, AR_PHY_SPECTRAL_SCAN,
|
||||
AR_PHY_SPECTRAL_SCAN_SHORT_REPEAT);
|
||||
if (AR_SREV_9280(ah))
|
||||
repeat_bit = AR_PHY_SPECTRAL_SCAN_SHORT_REPEAT;
|
||||
else
|
||||
REG_CLR_BIT(ah, AR_PHY_SPECTRAL_SCAN,
|
||||
AR_PHY_SPECTRAL_SCAN_SHORT_REPEAT);
|
||||
repeat_bit = AR_PHY_SPECTRAL_SCAN_SHORT_REPEAT_KIWI;
|
||||
|
||||
if (param->short_repeat)
|
||||
REG_SET_BIT(ah, AR_PHY_SPECTRAL_SCAN, repeat_bit);
|
||||
else
|
||||
REG_CLR_BIT(ah, AR_PHY_SPECTRAL_SCAN, repeat_bit);
|
||||
|
||||
/* on AR92xx, the highest bit of count will make the the chip send
|
||||
* spectral samples endlessly. Check if this really was intended,
|
||||
@ -499,15 +503,25 @@ static void ar9002_hw_spectral_scan_config(struct ath_hw *ah,
|
||||
*/
|
||||
count = param->count;
|
||||
if (param->endless) {
|
||||
if (AR_SREV_9271(ah))
|
||||
count = 0;
|
||||
else
|
||||
if (AR_SREV_9280(ah))
|
||||
count = 0x80;
|
||||
else
|
||||
count = 0;
|
||||
} else if (count & 0x80)
|
||||
count = 0x7f;
|
||||
else if (!count)
|
||||
count = 1;
|
||||
|
||||
if (AR_SREV_9280(ah)) {
|
||||
REG_RMW_FIELD(ah, AR_PHY_SPECTRAL_SCAN,
|
||||
AR_PHY_SPECTRAL_SCAN_COUNT, count);
|
||||
} else {
|
||||
REG_RMW_FIELD(ah, AR_PHY_SPECTRAL_SCAN,
|
||||
AR_PHY_SPECTRAL_SCAN_COUNT_KIWI, count);
|
||||
REG_SET_BIT(ah, AR_PHY_SPECTRAL_SCAN,
|
||||
AR_PHY_SPECTRAL_SCAN_PHYERR_MASK_SELECT);
|
||||
}
|
||||
|
||||
REG_RMW_FIELD(ah, AR_PHY_SPECTRAL_SCAN,
|
||||
AR_PHY_SPECTRAL_SCAN_COUNT, count);
|
||||
REG_RMW_FIELD(ah, AR_PHY_SPECTRAL_SCAN,
|
||||
AR_PHY_SPECTRAL_SCAN_PERIOD, param->period);
|
||||
REG_RMW_FIELD(ah, AR_PHY_SPECTRAL_SCAN,
|
||||
|
@ -177,8 +177,11 @@
|
||||
#define AR_PHY_SPECTRAL_SCAN_PERIOD_S 8
|
||||
#define AR_PHY_SPECTRAL_SCAN_COUNT 0x00FF0000 /* Number of reports, reg 68, bits 16-23*/
|
||||
#define AR_PHY_SPECTRAL_SCAN_COUNT_S 16
|
||||
#define AR_PHY_SPECTRAL_SCAN_COUNT_KIWI 0x0FFF0000 /* Number of reports, reg 68, bits 16-27*/
|
||||
#define AR_PHY_SPECTRAL_SCAN_COUNT_KIWI_S 16
|
||||
#define AR_PHY_SPECTRAL_SCAN_SHORT_REPEAT 0x01000000 /* Short repeat, reg 68, bit 24*/
|
||||
#define AR_PHY_SPECTRAL_SCAN_SHORT_REPEAT_S 24 /* Short repeat, reg 68, bit 24*/
|
||||
#define AR_PHY_SPECTRAL_SCAN_SHORT_REPEAT_KIWI 0x10000000 /* Short repeat, reg 68, bit 28*/
|
||||
#define AR_PHY_SPECTRAL_SCAN_PHYERR_MASK_SELECT 0x40000000
|
||||
|
||||
#define AR_PHY_RX_DELAY 0x9914
|
||||
#define AR_PHY_SEARCH_START_DELAY 0x9918
|
||||
|
@ -33,6 +33,7 @@ struct coeff {
|
||||
|
||||
enum ar9003_cal_types {
|
||||
IQ_MISMATCH_CAL = BIT(0),
|
||||
TEMP_COMP_CAL = BIT(1),
|
||||
};
|
||||
|
||||
static void ar9003_hw_setup_calibration(struct ath_hw *ah,
|
||||
@ -58,6 +59,12 @@ static void ar9003_hw_setup_calibration(struct ath_hw *ah,
|
||||
/* Kick-off cal */
|
||||
REG_SET_BIT(ah, AR_PHY_TIMING4, AR_PHY_TIMING4_DO_CAL);
|
||||
break;
|
||||
case TEMP_COMP_CAL:
|
||||
ath_dbg(common, CALIBRATE,
|
||||
"starting Temperature Compensation Calibration\n");
|
||||
REG_SET_BIT(ah, AR_CH0_THERM, AR_CH0_THERM_LOCAL);
|
||||
REG_SET_BIT(ah, AR_CH0_THERM, AR_CH0_THERM_START);
|
||||
break;
|
||||
default:
|
||||
ath_err(common, "Invalid calibration type\n");
|
||||
break;
|
||||
@ -75,50 +82,51 @@ static bool ar9003_hw_per_calibration(struct ath_hw *ah,
|
||||
struct ath9k_cal_list *currCal)
|
||||
{
|
||||
struct ath9k_hw_cal_data *caldata = ah->caldata;
|
||||
/* Cal is assumed not done until explicitly set below */
|
||||
bool iscaldone = false;
|
||||
const struct ath9k_percal_data *cur_caldata = currCal->calData;
|
||||
|
||||
/* Calibration in progress. */
|
||||
if (currCal->calState == CAL_RUNNING) {
|
||||
/* Check to see if it has finished. */
|
||||
if (!(REG_READ(ah, AR_PHY_TIMING4) & AR_PHY_TIMING4_DO_CAL)) {
|
||||
if (REG_READ(ah, AR_PHY_TIMING4) & AR_PHY_TIMING4_DO_CAL)
|
||||
return false;
|
||||
|
||||
/*
|
||||
* Accumulate cal measures for active chains
|
||||
*/
|
||||
if (cur_caldata->calCollect)
|
||||
cur_caldata->calCollect(ah);
|
||||
ah->cal_samples++;
|
||||
|
||||
if (ah->cal_samples >= cur_caldata->calNumSamples) {
|
||||
unsigned int i, numChains = 0;
|
||||
for (i = 0; i < AR9300_MAX_CHAINS; i++) {
|
||||
if (rxchainmask & (1 << i))
|
||||
numChains++;
|
||||
}
|
||||
|
||||
/*
|
||||
* Accumulate cal measures for active chains
|
||||
* Process accumulated data
|
||||
*/
|
||||
currCal->calData->calCollect(ah);
|
||||
ah->cal_samples++;
|
||||
if (cur_caldata->calPostProc)
|
||||
cur_caldata->calPostProc(ah, numChains);
|
||||
|
||||
if (ah->cal_samples >=
|
||||
currCal->calData->calNumSamples) {
|
||||
unsigned int i, numChains = 0;
|
||||
for (i = 0; i < AR9300_MAX_CHAINS; i++) {
|
||||
if (rxchainmask & (1 << i))
|
||||
numChains++;
|
||||
}
|
||||
|
||||
/*
|
||||
* Process accumulated data
|
||||
*/
|
||||
currCal->calData->calPostProc(ah, numChains);
|
||||
|
||||
/* Calibration has finished. */
|
||||
caldata->CalValid |= currCal->calData->calType;
|
||||
currCal->calState = CAL_DONE;
|
||||
iscaldone = true;
|
||||
} else {
|
||||
/* Calibration has finished. */
|
||||
caldata->CalValid |= cur_caldata->calType;
|
||||
currCal->calState = CAL_DONE;
|
||||
return true;
|
||||
} else {
|
||||
/*
|
||||
* Set-up collection of another sub-sample until we
|
||||
* get desired number
|
||||
*/
|
||||
ar9003_hw_setup_calibration(ah, currCal);
|
||||
}
|
||||
}
|
||||
} else if (!(caldata->CalValid & currCal->calData->calType)) {
|
||||
} else if (!(caldata->CalValid & cur_caldata->calType)) {
|
||||
/* If current cal is marked invalid in channel, kick it off */
|
||||
ath9k_hw_reset_calibration(ah, currCal);
|
||||
}
|
||||
|
||||
return iscaldone;
|
||||
return false;
|
||||
}
|
||||
|
||||
static int ar9003_hw_calibrate(struct ath_hw *ah, struct ath9k_channel *chan,
|
||||
@ -315,9 +323,16 @@ static const struct ath9k_percal_data iq_cal_single_sample = {
|
||||
ar9003_hw_iqcalibrate
|
||||
};
|
||||
|
||||
static const struct ath9k_percal_data temp_cal_single_sample = {
|
||||
TEMP_COMP_CAL,
|
||||
MIN_CAL_SAMPLES,
|
||||
PER_MAX_LOG_COUNT,
|
||||
};
|
||||
|
||||
static void ar9003_hw_init_cal_settings(struct ath_hw *ah)
|
||||
{
|
||||
ah->iq_caldata.calData = &iq_cal_single_sample;
|
||||
ah->temp_caldata.calData = &temp_cal_single_sample;
|
||||
|
||||
if (AR_SREV_9300_20_OR_LATER(ah)) {
|
||||
ah->enabled_cals |= TX_IQ_CAL;
|
||||
@ -325,7 +340,7 @@ static void ar9003_hw_init_cal_settings(struct ath_hw *ah)
|
||||
ah->enabled_cals |= TX_IQ_ON_AGC_CAL;
|
||||
}
|
||||
|
||||
ah->supp_cals = IQ_MISMATCH_CAL;
|
||||
ah->supp_cals = IQ_MISMATCH_CAL | TEMP_COMP_CAL;
|
||||
}
|
||||
|
||||
#define OFF_UPPER_LT 24
|
||||
@ -1374,6 +1389,29 @@ static void ar9003_hw_cl_cal_post_proc(struct ath_hw *ah, bool is_reusable)
|
||||
}
|
||||
}
|
||||
|
||||
static void ar9003_hw_init_cal_common(struct ath_hw *ah)
|
||||
{
|
||||
struct ath9k_hw_cal_data *caldata = ah->caldata;
|
||||
|
||||
/* Initialize list pointers */
|
||||
ah->cal_list = ah->cal_list_last = ah->cal_list_curr = NULL;
|
||||
|
||||
INIT_CAL(&ah->iq_caldata);
|
||||
INSERT_CAL(ah, &ah->iq_caldata);
|
||||
|
||||
INIT_CAL(&ah->temp_caldata);
|
||||
INSERT_CAL(ah, &ah->temp_caldata);
|
||||
|
||||
/* Initialize current pointer to first element in list */
|
||||
ah->cal_list_curr = ah->cal_list;
|
||||
|
||||
if (ah->cal_list_curr)
|
||||
ath9k_hw_reset_calibration(ah, ah->cal_list_curr);
|
||||
|
||||
if (caldata)
|
||||
caldata->CalValid = 0;
|
||||
}
|
||||
|
||||
static bool ar9003_hw_init_cal_pcoem(struct ath_hw *ah,
|
||||
struct ath9k_channel *chan)
|
||||
{
|
||||
@ -1533,21 +1571,7 @@ skip_tx_iqcal:
|
||||
/* Revert chainmask to runtime parameters */
|
||||
ar9003_hw_set_chain_masks(ah, ah->rxchainmask, ah->txchainmask);
|
||||
|
||||
/* Initialize list pointers */
|
||||
ah->cal_list = ah->cal_list_last = ah->cal_list_curr = NULL;
|
||||
|
||||
INIT_CAL(&ah->iq_caldata);
|
||||
INSERT_CAL(ah, &ah->iq_caldata);
|
||||
ath_dbg(common, CALIBRATE, "enabling IQ Calibration\n");
|
||||
|
||||
/* Initialize current pointer to first element in list */
|
||||
ah->cal_list_curr = ah->cal_list;
|
||||
|
||||
if (ah->cal_list_curr)
|
||||
ath9k_hw_reset_calibration(ah, ah->cal_list_curr);
|
||||
|
||||
if (caldata)
|
||||
caldata->CalValid = 0;
|
||||
ar9003_hw_init_cal_common(ah);
|
||||
|
||||
return true;
|
||||
}
|
||||
@ -1578,8 +1602,6 @@ static bool do_ar9003_agc_cal(struct ath_hw *ah)
|
||||
static bool ar9003_hw_init_cal_soc(struct ath_hw *ah,
|
||||
struct ath9k_channel *chan)
|
||||
{
|
||||
struct ath_common *common = ath9k_hw_common(ah);
|
||||
struct ath9k_hw_cal_data *caldata = ah->caldata;
|
||||
bool txiqcal_done = false;
|
||||
bool status = true;
|
||||
bool run_agc_cal = false, sep_iq_cal = false;
|
||||
@ -1677,21 +1699,7 @@ skip_tx_iqcal:
|
||||
/* Revert chainmask to runtime parameters */
|
||||
ar9003_hw_set_chain_masks(ah, ah->rxchainmask, ah->txchainmask);
|
||||
|
||||
/* Initialize list pointers */
|
||||
ah->cal_list = ah->cal_list_last = ah->cal_list_curr = NULL;
|
||||
|
||||
INIT_CAL(&ah->iq_caldata);
|
||||
INSERT_CAL(ah, &ah->iq_caldata);
|
||||
ath_dbg(common, CALIBRATE, "enabling IQ Calibration\n");
|
||||
|
||||
/* Initialize current pointer to first element in list */
|
||||
ah->cal_list_curr = ah->cal_list;
|
||||
|
||||
if (ah->cal_list_curr)
|
||||
ath9k_hw_reset_calibration(ah, ah->cal_list_curr);
|
||||
|
||||
if (caldata)
|
||||
caldata->CalValid = 0;
|
||||
ar9003_hw_init_cal_common(ah);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -4175,7 +4175,7 @@ static void ath9k_hw_ar9300_set_board_values(struct ath_hw *ah,
|
||||
if (!AR_SREV_9330(ah) && !AR_SREV_9340(ah) && !AR_SREV_9531(ah))
|
||||
ar9003_hw_internal_regulator_apply(ah);
|
||||
ar9003_hw_apply_tuning_caps(ah);
|
||||
ar9003_hw_apply_minccapwr_thresh(ah, chan);
|
||||
ar9003_hw_apply_minccapwr_thresh(ah, is2ghz);
|
||||
ar9003_hw_txend_to_xpa_off_apply(ah, is2ghz);
|
||||
ar9003_hw_thermometer_apply(ah);
|
||||
ar9003_hw_thermo_cal_apply(ah);
|
||||
|
@ -689,13 +689,6 @@
|
||||
#define AR_CH0_TOP_XPABIASLVL (AR_SREV_9550(ah) ? 0x3c0 : 0x300)
|
||||
#define AR_CH0_TOP_XPABIASLVL_S (AR_SREV_9550(ah) ? 6 : 8)
|
||||
|
||||
#define AR_CH0_THERM (AR_SREV_9300(ah) ? 0x16290 : \
|
||||
((AR_SREV_9485(ah) ? 0x1628c : 0x16294)))
|
||||
#define AR_CH0_THERM_XPABIASLVL_MSB 0x3
|
||||
#define AR_CH0_THERM_XPABIASLVL_MSB_S 0
|
||||
#define AR_CH0_THERM_XPASHORT2GND 0x4
|
||||
#define AR_CH0_THERM_XPASHORT2GND_S 2
|
||||
|
||||
#define AR_SWITCH_TABLE_COM_ALL (0xffff)
|
||||
#define AR_SWITCH_TABLE_COM_ALL_S (0)
|
||||
#define AR_SWITCH_TABLE_COM_AR9462_ALL (0xffffff)
|
||||
@ -712,15 +705,17 @@
|
||||
#define AR_SWITCH_TABLE_ALL (0xfff)
|
||||
#define AR_SWITCH_TABLE_ALL_S (0)
|
||||
|
||||
#define AR_PHY_65NM_CH0_THERM (AR_SREV_9300(ah) ? 0x16290 :\
|
||||
((AR_SREV_9462(ah) || AR_SREV_9565(ah)) ? 0x16294 : 0x1628c))
|
||||
#define AR_CH0_THERM (AR_SREV_9300(ah) ? 0x16290 :\
|
||||
((AR_SREV_9462(ah) || AR_SREV_9565(ah)) ? 0x16294 : 0x1628c))
|
||||
#define AR_CH0_THERM_XPABIASLVL_MSB 0x3
|
||||
#define AR_CH0_THERM_XPABIASLVL_MSB_S 0
|
||||
#define AR_CH0_THERM_XPASHORT2GND 0x4
|
||||
#define AR_CH0_THERM_XPASHORT2GND_S 2
|
||||
|
||||
#define AR_PHY_65NM_CH0_THERM_LOCAL 0x80000000
|
||||
#define AR_PHY_65NM_CH0_THERM_LOCAL_S 31
|
||||
#define AR_PHY_65NM_CH0_THERM_START 0x20000000
|
||||
#define AR_PHY_65NM_CH0_THERM_START_S 29
|
||||
#define AR_PHY_65NM_CH0_THERM_SAR_ADC_OUT 0x0000ff00
|
||||
#define AR_PHY_65NM_CH0_THERM_SAR_ADC_OUT_S 8
|
||||
#define AR_CH0_THERM_LOCAL 0x80000000
|
||||
#define AR_CH0_THERM_START 0x20000000
|
||||
#define AR_CH0_THERM_SAR_ADC_OUT 0x0000ff00
|
||||
#define AR_CH0_THERM_SAR_ADC_OUT_S 8
|
||||
|
||||
#define AR_CH0_TOP2 (AR_SREV_9300(ah) ? 0x1628c : \
|
||||
(AR_SREV_9462(ah) ? 0x16290 : 0x16284))
|
||||
|
@ -637,6 +637,8 @@ struct ath9k_vif_iter_data {
|
||||
int nwds; /* number of WDS vifs */
|
||||
int nadhocs; /* number of adhoc vifs */
|
||||
int nocbs; /* number of OCB vifs */
|
||||
int nbcnvifs; /* number of beaconing vifs */
|
||||
struct ieee80211_vif *primary_beacon_vif;
|
||||
struct ieee80211_vif *primary_sta;
|
||||
};
|
||||
|
||||
@ -685,10 +687,11 @@ struct ath_beacon {
|
||||
};
|
||||
|
||||
void ath9k_beacon_tasklet(unsigned long data);
|
||||
void ath9k_beacon_config(struct ath_softc *sc, struct ieee80211_vif *vif,
|
||||
u32 changed);
|
||||
void ath9k_beacon_config(struct ath_softc *sc, struct ieee80211_vif *main_vif,
|
||||
bool beacons);
|
||||
void ath9k_beacon_assign_slot(struct ath_softc *sc, struct ieee80211_vif *vif);
|
||||
void ath9k_beacon_remove_slot(struct ath_softc *sc, struct ieee80211_vif *vif);
|
||||
void ath9k_beacon_ensure_primary_slot(struct ath_softc *sc);
|
||||
void ath9k_set_beacon(struct ath_softc *sc);
|
||||
bool ath9k_csa_is_finished(struct ath_softc *sc, struct ieee80211_vif *vif);
|
||||
void ath9k_csa_update(struct ath_softc *sc);
|
||||
|
@ -50,7 +50,7 @@ static void ath9k_beaconq_config(struct ath_softc *sc)
|
||||
txq = sc->tx.txq_map[IEEE80211_AC_BE];
|
||||
ath9k_hw_get_txq_props(ah, txq->axq_qnum, &qi_be);
|
||||
qi.tqi_aifs = qi_be.tqi_aifs;
|
||||
if (ah->slottime == ATH9K_SLOT_TIME_20)
|
||||
if (ah->slottime == 20)
|
||||
qi.tqi_cwmin = 2*qi_be.tqi_cwmin;
|
||||
else
|
||||
qi.tqi_cwmin = 4*qi_be.tqi_cwmin;
|
||||
@ -209,7 +209,6 @@ void ath9k_beacon_assign_slot(struct ath_softc *sc, struct ieee80211_vif *vif)
|
||||
}
|
||||
|
||||
sc->beacon.bslot[avp->av_bslot] = vif;
|
||||
sc->nbcnvifs++;
|
||||
|
||||
ath_dbg(common, CONFIG, "Added interface at beacon slot: %d\n",
|
||||
avp->av_bslot);
|
||||
@ -220,15 +219,12 @@ void ath9k_beacon_remove_slot(struct ath_softc *sc, struct ieee80211_vif *vif)
|
||||
struct ath_common *common = ath9k_hw_common(sc->sc_ah);
|
||||
struct ath_vif *avp = (void *)vif->drv_priv;
|
||||
struct ath_buf *bf = avp->av_bcbuf;
|
||||
struct ath_beacon_config *cur_conf = &sc->cur_chan->beacon;
|
||||
|
||||
ath_dbg(common, CONFIG, "Removing interface at beacon slot: %d\n",
|
||||
avp->av_bslot);
|
||||
|
||||
tasklet_disable(&sc->bcon_tasklet);
|
||||
|
||||
cur_conf->enable_beacon &= ~BIT(avp->av_bslot);
|
||||
|
||||
if (bf && bf->bf_mpdu) {
|
||||
struct sk_buff *skb = bf->bf_mpdu;
|
||||
dma_unmap_single(sc->dev, bf->bf_buf_addr,
|
||||
@ -240,12 +236,73 @@ void ath9k_beacon_remove_slot(struct ath_softc *sc, struct ieee80211_vif *vif)
|
||||
|
||||
avp->av_bcbuf = NULL;
|
||||
sc->beacon.bslot[avp->av_bslot] = NULL;
|
||||
sc->nbcnvifs--;
|
||||
list_add_tail(&bf->list, &sc->beacon.bbuf);
|
||||
|
||||
tasklet_enable(&sc->bcon_tasklet);
|
||||
}
|
||||
|
||||
void ath9k_beacon_ensure_primary_slot(struct ath_softc *sc)
|
||||
{
|
||||
struct ath_common *common = ath9k_hw_common(sc->sc_ah);
|
||||
struct ieee80211_vif *vif;
|
||||
struct ath_vif *avp;
|
||||
s64 tsfadjust;
|
||||
u32 offset;
|
||||
int first_slot = ATH_BCBUF;
|
||||
int slot;
|
||||
|
||||
tasklet_disable(&sc->bcon_tasklet);
|
||||
|
||||
/* Find first taken slot. */
|
||||
for (slot = 0; slot < ATH_BCBUF; slot++) {
|
||||
if (sc->beacon.bslot[slot]) {
|
||||
first_slot = slot;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (first_slot == 0)
|
||||
goto out;
|
||||
|
||||
/* Re-enumarate all slots, moving them forward. */
|
||||
for (slot = 0; slot < ATH_BCBUF; slot++) {
|
||||
if (slot + first_slot < ATH_BCBUF) {
|
||||
vif = sc->beacon.bslot[slot + first_slot];
|
||||
sc->beacon.bslot[slot] = vif;
|
||||
|
||||
if (vif) {
|
||||
avp = (void *)vif->drv_priv;
|
||||
avp->av_bslot = slot;
|
||||
}
|
||||
} else {
|
||||
sc->beacon.bslot[slot] = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
vif = sc->beacon.bslot[0];
|
||||
if (WARN_ON(!vif))
|
||||
goto out;
|
||||
|
||||
/* Get the tsf_adjust value for the new first slot. */
|
||||
avp = (void *)vif->drv_priv;
|
||||
tsfadjust = le64_to_cpu(avp->tsf_adjust);
|
||||
|
||||
ath_dbg(common, CONFIG,
|
||||
"Adjusting global TSF after beacon slot reassignment: %lld\n",
|
||||
(signed long long)tsfadjust);
|
||||
|
||||
/* Modify TSF as required and update the HW. */
|
||||
avp->chanctx->tsf_val += tsfadjust;
|
||||
if (sc->cur_chan == avp->chanctx) {
|
||||
offset = ath9k_hw_get_tsf_offset(&avp->chanctx->tsf_ts, NULL);
|
||||
ath9k_hw_settsf64(sc->sc_ah, avp->chanctx->tsf_val + offset);
|
||||
}
|
||||
|
||||
/* The slots tsf_adjust will be updated by ath9k_beacon_config later. */
|
||||
|
||||
out:
|
||||
tasklet_enable(&sc->bcon_tasklet);
|
||||
}
|
||||
|
||||
static int ath9k_beacon_choose_slot(struct ath_softc *sc)
|
||||
{
|
||||
struct ath_common *common = ath9k_hw_common(sc->sc_ah);
|
||||
@ -274,22 +331,33 @@ static int ath9k_beacon_choose_slot(struct ath_softc *sc)
|
||||
return slot;
|
||||
}
|
||||
|
||||
static void ath9k_set_tsfadjust(struct ath_softc *sc, struct ieee80211_vif *vif)
|
||||
static void ath9k_set_tsfadjust(struct ath_softc *sc,
|
||||
struct ath_beacon_config *cur_conf)
|
||||
{
|
||||
struct ath_common *common = ath9k_hw_common(sc->sc_ah);
|
||||
struct ath_vif *avp = (void *)vif->drv_priv;
|
||||
struct ath_beacon_config *cur_conf = &avp->chanctx->beacon;
|
||||
u32 tsfadjust;
|
||||
s64 tsfadjust;
|
||||
int slot;
|
||||
|
||||
if (avp->av_bslot == 0)
|
||||
return;
|
||||
for (slot = 0; slot < ATH_BCBUF; slot++) {
|
||||
struct ath_vif *avp;
|
||||
|
||||
tsfadjust = cur_conf->beacon_interval * avp->av_bslot;
|
||||
tsfadjust = TU_TO_USEC(tsfadjust) / ATH_BCBUF;
|
||||
avp->tsf_adjust = cpu_to_le64(tsfadjust);
|
||||
if (!sc->beacon.bslot[slot])
|
||||
continue;
|
||||
|
||||
ath_dbg(common, CONFIG, "tsfadjust is: %llu for bslot: %d\n",
|
||||
(unsigned long long)tsfadjust, avp->av_bslot);
|
||||
avp = (void *)sc->beacon.bslot[slot]->drv_priv;
|
||||
|
||||
/* tsf_adjust is added to the TSF value. We send out the
|
||||
* beacon late, so need to adjust the TSF starting point to be
|
||||
* later in time (i.e. the theoretical first beacon has a TSF
|
||||
* of 0 after correction).
|
||||
*/
|
||||
tsfadjust = cur_conf->beacon_interval * avp->av_bslot;
|
||||
tsfadjust = -TU_TO_USEC(tsfadjust) / ATH_BCBUF;
|
||||
avp->tsf_adjust = cpu_to_le64(tsfadjust);
|
||||
|
||||
ath_dbg(common, CONFIG, "tsfadjust is: %lld for bslot: %d\n",
|
||||
(signed long long)tsfadjust, avp->av_bslot);
|
||||
}
|
||||
}
|
||||
|
||||
bool ath9k_csa_is_finished(struct ath_softc *sc, struct ieee80211_vif *vif)
|
||||
@ -443,20 +511,28 @@ void ath9k_beacon_tasklet(unsigned long data)
|
||||
* Both nexttbtt and intval have to be in usecs.
|
||||
*/
|
||||
static void ath9k_beacon_init(struct ath_softc *sc, u32 nexttbtt,
|
||||
u32 intval, bool reset_tsf)
|
||||
u32 intval)
|
||||
{
|
||||
struct ath_hw *ah = sc->sc_ah;
|
||||
|
||||
ath9k_hw_disable_interrupts(ah);
|
||||
if (reset_tsf)
|
||||
ath9k_hw_reset_tsf(ah);
|
||||
ath9k_beaconq_config(sc);
|
||||
ath9k_hw_beaconinit(ah, nexttbtt, intval);
|
||||
ah->imask |= ATH9K_INT_SWBA;
|
||||
sc->beacon.bmisscnt = 0;
|
||||
ath9k_hw_set_interrupts(ah);
|
||||
ath9k_hw_enable_interrupts(ah);
|
||||
}
|
||||
|
||||
static void ath9k_beacon_stop(struct ath_softc *sc)
|
||||
{
|
||||
ath9k_hw_disable_interrupts(sc->sc_ah);
|
||||
sc->sc_ah->imask &= ~(ATH9K_INT_SWBA | ATH9K_INT_BMISS);
|
||||
sc->beacon.bmisscnt = 0;
|
||||
ath9k_hw_set_interrupts(sc->sc_ah);
|
||||
ath9k_hw_enable_interrupts(sc->sc_ah);
|
||||
}
|
||||
|
||||
/*
|
||||
* For multi-bss ap support beacons are either staggered evenly over N slots or
|
||||
* burst together. For the former arrange for the SWBA to be delivered for each
|
||||
@ -468,7 +544,7 @@ static void ath9k_beacon_config_ap(struct ath_softc *sc,
|
||||
struct ath_hw *ah = sc->sc_ah;
|
||||
|
||||
ath9k_cmn_beacon_config_ap(ah, conf, ATH_BCBUF);
|
||||
ath9k_beacon_init(sc, conf->nexttbtt, conf->intval, false);
|
||||
ath9k_beacon_init(sc, conf->nexttbtt, conf->intval);
|
||||
}
|
||||
|
||||
static void ath9k_beacon_config_sta(struct ath_hw *ah,
|
||||
@ -497,7 +573,7 @@ static void ath9k_beacon_config_adhoc(struct ath_softc *sc,
|
||||
|
||||
ath9k_cmn_beacon_config_adhoc(ah, conf);
|
||||
|
||||
ath9k_beacon_init(sc, conf->nexttbtt, conf->intval, conf->ibss_creator);
|
||||
ath9k_beacon_init(sc, conf->nexttbtt, conf->intval);
|
||||
|
||||
/*
|
||||
* Set the global 'beacon has been configured' flag for the
|
||||
@ -507,44 +583,6 @@ static void ath9k_beacon_config_adhoc(struct ath_softc *sc,
|
||||
set_bit(ATH_OP_BEACONS, &common->op_flags);
|
||||
}
|
||||
|
||||
static bool ath9k_allow_beacon_config(struct ath_softc *sc,
|
||||
struct ieee80211_vif *vif)
|
||||
{
|
||||
struct ath_common *common = ath9k_hw_common(sc->sc_ah);
|
||||
struct ath_vif *avp = (void *)vif->drv_priv;
|
||||
|
||||
if (ath9k_is_chanctx_enabled()) {
|
||||
/*
|
||||
* If the VIF is not present in the current channel context,
|
||||
* then we can't do the usual opmode checks. Allow the
|
||||
* beacon config for the VIF to be updated in this case and
|
||||
* return immediately.
|
||||
*/
|
||||
if (sc->cur_chan != avp->chanctx)
|
||||
return true;
|
||||
}
|
||||
|
||||
if (sc->sc_ah->opmode == NL80211_IFTYPE_AP) {
|
||||
if (vif->type != NL80211_IFTYPE_AP) {
|
||||
ath_dbg(common, CONFIG,
|
||||
"An AP interface is already present !\n");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (sc->sc_ah->opmode == NL80211_IFTYPE_STATION) {
|
||||
if ((vif->type == NL80211_IFTYPE_STATION) &&
|
||||
test_bit(ATH_OP_BEACONS, &common->op_flags) &&
|
||||
vif != sc->cur_chan->primary_sta) {
|
||||
ath_dbg(common, CONFIG,
|
||||
"Beacon already configured for a station interface\n");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static void ath9k_cache_beacon_config(struct ath_softc *sc,
|
||||
struct ath_chanctx *ctx,
|
||||
struct ieee80211_bss_conf *bss_conf)
|
||||
@ -580,87 +618,79 @@ static void ath9k_cache_beacon_config(struct ath_softc *sc,
|
||||
if (cur_conf->dtim_period == 0)
|
||||
cur_conf->dtim_period = 1;
|
||||
|
||||
ath9k_set_tsfadjust(sc, cur_conf);
|
||||
}
|
||||
|
||||
void ath9k_beacon_config(struct ath_softc *sc, struct ieee80211_vif *vif,
|
||||
u32 changed)
|
||||
void ath9k_beacon_config(struct ath_softc *sc, struct ieee80211_vif *main_vif,
|
||||
bool beacons)
|
||||
{
|
||||
struct ieee80211_bss_conf *bss_conf = &vif->bss_conf;
|
||||
struct ath_hw *ah = sc->sc_ah;
|
||||
struct ath_common *common = ath9k_hw_common(ah);
|
||||
struct ath_vif *avp = (void *)vif->drv_priv;
|
||||
struct ath_chanctx *ctx = avp->chanctx;
|
||||
struct ath_hw *ah = sc->sc_ah;
|
||||
struct ath_common *common = ath9k_hw_common(ah);
|
||||
struct ath_vif *avp;
|
||||
struct ath_chanctx *ctx;
|
||||
struct ath_beacon_config *cur_conf;
|
||||
unsigned long flags;
|
||||
bool enabled;
|
||||
bool skip_beacon = false;
|
||||
|
||||
if (!ctx)
|
||||
if (!beacons) {
|
||||
clear_bit(ATH_OP_BEACONS, &common->op_flags);
|
||||
ath9k_beacon_stop(sc);
|
||||
return;
|
||||
}
|
||||
|
||||
if (WARN_ON(!main_vif))
|
||||
return;
|
||||
|
||||
cur_conf = &avp->chanctx->beacon;
|
||||
if (vif->type == NL80211_IFTYPE_AP)
|
||||
ath9k_set_tsfadjust(sc, vif);
|
||||
avp = (void *)main_vif->drv_priv;
|
||||
ctx = avp->chanctx;
|
||||
cur_conf = &ctx->beacon;
|
||||
enabled = cur_conf->enable_beacon;
|
||||
cur_conf->enable_beacon = beacons;
|
||||
|
||||
if (!ath9k_allow_beacon_config(sc, vif))
|
||||
return;
|
||||
|
||||
if (vif->type == NL80211_IFTYPE_STATION) {
|
||||
ath9k_cache_beacon_config(sc, ctx, bss_conf);
|
||||
if (ctx != sc->cur_chan)
|
||||
return;
|
||||
if (sc->sc_ah->opmode == NL80211_IFTYPE_STATION) {
|
||||
ath9k_cache_beacon_config(sc, ctx, &main_vif->bss_conf);
|
||||
|
||||
ath9k_set_beacon(sc);
|
||||
set_bit(ATH_OP_BEACONS, &common->op_flags);
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Take care of multiple interfaces when
|
||||
* enabling/disabling SWBA.
|
||||
*/
|
||||
if (changed & BSS_CHANGED_BEACON_ENABLED) {
|
||||
bool enabled = cur_conf->enable_beacon;
|
||||
|
||||
if (!bss_conf->enable_beacon) {
|
||||
cur_conf->enable_beacon &= ~BIT(avp->av_bslot);
|
||||
} else {
|
||||
cur_conf->enable_beacon |= BIT(avp->av_bslot);
|
||||
if (!enabled)
|
||||
ath9k_cache_beacon_config(sc, ctx, bss_conf);
|
||||
}
|
||||
}
|
||||
|
||||
if (ctx != sc->cur_chan)
|
||||
return;
|
||||
/* Update the beacon configuration. */
|
||||
ath9k_cache_beacon_config(sc, ctx, &main_vif->bss_conf);
|
||||
|
||||
/*
|
||||
* Configure the HW beacon registers only when we have a valid
|
||||
* beacon interval.
|
||||
*/
|
||||
if (cur_conf->beacon_interval) {
|
||||
/*
|
||||
* If we are joining an existing IBSS network, start beaconing
|
||||
* only after a TSF-sync has taken place. Ensure that this
|
||||
* happens by setting the appropriate flags.
|
||||
/* Special case to sync the TSF when joining an existing IBSS.
|
||||
* This is only done if no AP interface is active.
|
||||
* Note that mac80211 always resets the TSF when creating a new
|
||||
* IBSS interface.
|
||||
*/
|
||||
if ((changed & BSS_CHANGED_IBSS) && !bss_conf->ibss_creator &&
|
||||
bss_conf->enable_beacon) {
|
||||
if (sc->sc_ah->opmode == NL80211_IFTYPE_ADHOC &&
|
||||
!enabled && beacons && !main_vif->bss_conf.ibss_creator) {
|
||||
spin_lock_irqsave(&sc->sc_pm_lock, flags);
|
||||
sc->ps_flags |= PS_BEACON_SYNC | PS_WAIT_FOR_BEACON;
|
||||
spin_unlock_irqrestore(&sc->sc_pm_lock, flags);
|
||||
skip_beacon = true;
|
||||
} else {
|
||||
ath9k_set_beacon(sc);
|
||||
}
|
||||
|
||||
/*
|
||||
* Do not set the ATH_OP_BEACONS flag for IBSS joiner mode
|
||||
* here, it is done in ath9k_beacon_config_adhoc().
|
||||
*/
|
||||
if (cur_conf->enable_beacon && !skip_beacon)
|
||||
if (beacons && !skip_beacon) {
|
||||
set_bit(ATH_OP_BEACONS, &common->op_flags);
|
||||
else
|
||||
ath9k_set_beacon(sc);
|
||||
} else {
|
||||
clear_bit(ATH_OP_BEACONS, &common->op_flags);
|
||||
ath9k_beacon_stop(sc);
|
||||
}
|
||||
} else {
|
||||
clear_bit(ATH_OP_BEACONS, &common->op_flags);
|
||||
ath9k_beacon_stop(sc);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -50,6 +50,7 @@
|
||||
#define IEEE80211_MS_TO_TU(x) (((x) * 1000) / 1024)
|
||||
|
||||
struct ath_beacon_config {
|
||||
struct ieee80211_vif *main_vif;
|
||||
int beacon_interval;
|
||||
u16 dtim_period;
|
||||
u16 bmiss_timeout;
|
||||
|
@ -280,7 +280,7 @@ EXPORT_SYMBOL(ath_dynack_sample_ack_ts);
|
||||
void ath_dynack_node_init(struct ath_hw *ah, struct ath_node *an)
|
||||
{
|
||||
/* ackto = slottime + sifs + air delay */
|
||||
u32 ackto = ATH9K_SLOT_TIME_9 + 16 + 64;
|
||||
u32 ackto = 9 + 16 + 64;
|
||||
struct ath_dynack *da = &ah->dynack;
|
||||
|
||||
an->ackto = ackto;
|
||||
@ -315,7 +315,7 @@ EXPORT_SYMBOL(ath_dynack_node_deinit);
|
||||
void ath_dynack_reset(struct ath_hw *ah)
|
||||
{
|
||||
/* ackto = slottime + sifs + air delay */
|
||||
u32 ackto = ATH9K_SLOT_TIME_9 + 16 + 64;
|
||||
u32 ackto = 9 + 16 + 64;
|
||||
struct ath_dynack *da = &ah->dynack;
|
||||
|
||||
da->lto = jiffies;
|
||||
|
@ -15,6 +15,7 @@
|
||||
*/
|
||||
|
||||
#include "hw.h"
|
||||
#include <linux/ath9k_platform.h>
|
||||
|
||||
void ath9k_hw_analog_shift_regwrite(struct ath_hw *ah, u32 reg, u32 val)
|
||||
{
|
||||
@ -108,26 +109,42 @@ void ath9k_hw_usb_gen_fill_eeprom(struct ath_hw *ah, u16 *eep_data,
|
||||
}
|
||||
}
|
||||
|
||||
static bool ath9k_hw_nvram_read_blob(struct ath_hw *ah, u32 off,
|
||||
u16 *data)
|
||||
static bool ath9k_hw_nvram_read_array(u16 *blob, size_t blob_size,
|
||||
off_t offset, u16 *data)
|
||||
{
|
||||
u16 *blob_data;
|
||||
|
||||
if (off * sizeof(u16) > ah->eeprom_blob->size)
|
||||
if (offset > blob_size)
|
||||
return false;
|
||||
|
||||
blob_data = (u16 *)ah->eeprom_blob->data;
|
||||
*data = blob_data[off];
|
||||
*data = blob[offset];
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool ath9k_hw_nvram_read_pdata(struct ath9k_platform_data *pdata,
|
||||
off_t offset, u16 *data)
|
||||
{
|
||||
return ath9k_hw_nvram_read_array(pdata->eeprom_data,
|
||||
ARRAY_SIZE(pdata->eeprom_data),
|
||||
offset, data);
|
||||
}
|
||||
|
||||
static bool ath9k_hw_nvram_read_firmware(const struct firmware *eeprom_blob,
|
||||
off_t offset, u16 *data)
|
||||
{
|
||||
return ath9k_hw_nvram_read_array((u16 *) eeprom_blob->data,
|
||||
eeprom_blob->size / sizeof(u16),
|
||||
offset, data);
|
||||
}
|
||||
|
||||
bool ath9k_hw_nvram_read(struct ath_hw *ah, u32 off, u16 *data)
|
||||
{
|
||||
struct ath_common *common = ath9k_hw_common(ah);
|
||||
struct ath9k_platform_data *pdata = ah->dev->platform_data;
|
||||
bool ret;
|
||||
|
||||
if (ah->eeprom_blob)
|
||||
ret = ath9k_hw_nvram_read_blob(ah, off, data);
|
||||
ret = ath9k_hw_nvram_read_firmware(ah->eeprom_blob, off, data);
|
||||
else if (pdata && !pdata->use_eeprom && pdata->eeprom_data)
|
||||
ret = ath9k_hw_nvram_read_pdata(pdata, off, data);
|
||||
else
|
||||
ret = common->bus_ops->eeprom_read(common, off, data);
|
||||
|
||||
|
@ -45,7 +45,7 @@ void ath9k_htc_beaconq_config(struct ath9k_htc_priv *priv)
|
||||
* Long slot time : 2x cwmin
|
||||
* Short slot time : 4x cwmin
|
||||
*/
|
||||
if (ah->slottime == ATH9K_SLOT_TIME_20)
|
||||
if (ah->slottime == 20)
|
||||
qi.tqi_cwmin = 2*qi_be.tqi_cwmin;
|
||||
else
|
||||
qi.tqi_cwmin = 4*qi_be.tqi_cwmin;
|
||||
|
@ -678,7 +678,7 @@ static int ath9k_init_priv(struct ath9k_htc_priv *priv,
|
||||
|
||||
for (i = 0; i < ATH9K_HTC_MAX_BCN_VIF; i++)
|
||||
priv->beacon.bslot[i] = NULL;
|
||||
priv->beacon.slottime = ATH9K_SLOT_TIME_9;
|
||||
priv->beacon.slottime = 9;
|
||||
|
||||
ath9k_cmn_init_channels_rates(common);
|
||||
ath9k_cmn_init_crypto(ah);
|
||||
|
@ -454,7 +454,7 @@ static void ath9k_hw_init_defaults(struct ath_hw *ah)
|
||||
if (AR_SREV_9100(ah))
|
||||
ah->sta_id1_defaults |= AR_STA_ID1_AR9100_BA_FIX;
|
||||
|
||||
ah->slottime = ATH9K_SLOT_TIME_9;
|
||||
ah->slottime = 9;
|
||||
ah->globaltxtimeout = (u32) -1;
|
||||
ah->power_mode = ATH9K_PM_UNDEFINED;
|
||||
ah->htc_reset_init = true;
|
||||
@ -471,33 +471,34 @@ static void ath9k_hw_init_defaults(struct ath_hw *ah)
|
||||
ah->tx_trig_level = (AR_FTRIG_512B >> AR_FTRIG_S);
|
||||
}
|
||||
|
||||
static int ath9k_hw_init_macaddr(struct ath_hw *ah)
|
||||
static void ath9k_hw_init_macaddr(struct ath_hw *ah)
|
||||
{
|
||||
struct ath_common *common = ath9k_hw_common(ah);
|
||||
u32 sum;
|
||||
int i;
|
||||
u16 eeval;
|
||||
static const u32 EEP_MAC[] = { EEP_MAC_LSW, EEP_MAC_MID, EEP_MAC_MSW };
|
||||
|
||||
sum = 0;
|
||||
/* MAC address may already be loaded via ath9k_platform_data */
|
||||
if (is_valid_ether_addr(common->macaddr))
|
||||
return;
|
||||
|
||||
for (i = 0; i < 3; i++) {
|
||||
eeval = ah->eep_ops->get_eeprom(ah, EEP_MAC[i]);
|
||||
sum += eeval;
|
||||
common->macaddr[2 * i] = eeval >> 8;
|
||||
common->macaddr[2 * i + 1] = eeval & 0xff;
|
||||
}
|
||||
if (!is_valid_ether_addr(common->macaddr)) {
|
||||
ath_err(common,
|
||||
"eeprom contains invalid mac address: %pM\n",
|
||||
common->macaddr);
|
||||
|
||||
random_ether_addr(common->macaddr);
|
||||
ath_err(common,
|
||||
"random mac address will be used: %pM\n",
|
||||
common->macaddr);
|
||||
}
|
||||
if (is_valid_ether_addr(common->macaddr))
|
||||
return;
|
||||
|
||||
return 0;
|
||||
ath_err(common, "eeprom contains invalid mac address: %pM\n",
|
||||
common->macaddr);
|
||||
|
||||
random_ether_addr(common->macaddr);
|
||||
ath_err(common, "random mac address will be used: %pM\n",
|
||||
common->macaddr);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
static int ath9k_hw_post_init(struct ath_hw *ah)
|
||||
@ -636,12 +637,7 @@ static int __ath9k_hw_init(struct ath_hw *ah)
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
r = ath9k_hw_init_macaddr(ah);
|
||||
if (r) {
|
||||
ath_err(common, "Failed to initialize MAC address\n");
|
||||
return r;
|
||||
}
|
||||
|
||||
ath9k_hw_init_macaddr(ah);
|
||||
ath9k_hw_init_hang_checks(ah);
|
||||
|
||||
common->state = ATH_HW_INITIALIZED;
|
||||
@ -1832,8 +1828,9 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan,
|
||||
u32 saveLedState;
|
||||
u32 saveDefAntenna;
|
||||
u32 macStaId1;
|
||||
struct timespec tsf_ts;
|
||||
u32 tsf_offset;
|
||||
u64 tsf = 0;
|
||||
s64 usec = 0;
|
||||
int r;
|
||||
bool start_mci_reset = false;
|
||||
bool save_fullsleep = ah->chip_fullsleep;
|
||||
@ -1877,8 +1874,8 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan,
|
||||
macStaId1 = REG_READ(ah, AR_STA_ID1) & AR_STA_ID1_BASE_RATE_11B;
|
||||
|
||||
/* Save TSF before chip reset, a cold reset clears it */
|
||||
getrawmonotonic(&tsf_ts);
|
||||
tsf = ath9k_hw_gettsf64(ah);
|
||||
usec = ktime_to_us(ktime_get_raw());
|
||||
|
||||
saveLedState = REG_READ(ah, AR_CFG_LED) &
|
||||
(AR_CFG_LED_ASSOC_CTL | AR_CFG_LED_MODE_SEL |
|
||||
@ -1911,8 +1908,8 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan,
|
||||
}
|
||||
|
||||
/* Restore TSF */
|
||||
usec = ktime_to_us(ktime_get_raw()) - usec;
|
||||
ath9k_hw_settsf64(ah, tsf + usec);
|
||||
tsf_offset = ath9k_hw_get_tsf_offset(&tsf_ts, NULL);
|
||||
ath9k_hw_settsf64(ah, tsf + tsf_offset);
|
||||
|
||||
if (AR_SREV_9280_20_OR_LATER(ah))
|
||||
REG_SET_BIT(ah, AR_GPIO_INPUT_EN_VAL, AR_GPIO_JTAG_DISABLE);
|
||||
@ -1932,12 +1929,11 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan,
|
||||
/*
|
||||
* Some AR91xx SoC devices frequently fail to accept TSF writes
|
||||
* right after the chip reset. When that happens, write a new
|
||||
* value after the initvals have been applied, with an offset
|
||||
* based on measured time difference
|
||||
* value after the initvals have been applied.
|
||||
*/
|
||||
if (AR_SREV_9100(ah) && (ath9k_hw_gettsf64(ah) < tsf)) {
|
||||
tsf += 1500;
|
||||
ath9k_hw_settsf64(ah, tsf);
|
||||
tsf_offset = ath9k_hw_get_tsf_offset(&tsf_ts, NULL);
|
||||
ath9k_hw_settsf64(ah, tsf + tsf_offset);
|
||||
}
|
||||
|
||||
ath9k_hw_init_mfp(ah);
|
||||
|
@ -830,6 +830,7 @@ struct ath_hw {
|
||||
/* Calibration */
|
||||
u32 supp_cals;
|
||||
struct ath9k_cal_list iq_caldata;
|
||||
struct ath9k_cal_list temp_caldata;
|
||||
struct ath9k_cal_list adcgain_caldata;
|
||||
struct ath9k_cal_list adcdc_caldata;
|
||||
struct ath9k_cal_list *cal_list;
|
||||
|
@ -372,7 +372,7 @@ static void ath9k_init_misc(struct ath_softc *sc)
|
||||
|
||||
common->last_rssi = ATH_RSSI_DUMMY_MARKER;
|
||||
memcpy(common->bssidmask, ath_bcast_mac, ETH_ALEN);
|
||||
sc->beacon.slottime = ATH9K_SLOT_TIME_9;
|
||||
sc->beacon.slottime = 9;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(sc->beacon.bslot); i++)
|
||||
sc->beacon.bslot[i] = NULL;
|
||||
@ -512,31 +512,52 @@ static void ath9k_eeprom_release(struct ath_softc *sc)
|
||||
release_firmware(sc->sc_ah->eeprom_blob);
|
||||
}
|
||||
|
||||
static int ath9k_init_soc_platform(struct ath_softc *sc)
|
||||
static int ath9k_init_platform(struct ath_softc *sc)
|
||||
{
|
||||
struct ath9k_platform_data *pdata = sc->dev->platform_data;
|
||||
struct ath_hw *ah = sc->sc_ah;
|
||||
int ret = 0;
|
||||
struct ath_common *common = ath9k_hw_common(ah);
|
||||
int ret;
|
||||
|
||||
if (!pdata)
|
||||
return 0;
|
||||
|
||||
if (!pdata->use_eeprom) {
|
||||
ah->ah_flags &= ~AH_USE_EEPROM;
|
||||
ah->gpio_mask = pdata->gpio_mask;
|
||||
ah->gpio_val = pdata->gpio_val;
|
||||
ah->led_pin = pdata->led_pin;
|
||||
ah->is_clk_25mhz = pdata->is_clk_25mhz;
|
||||
ah->get_mac_revision = pdata->get_mac_revision;
|
||||
ah->external_reset = pdata->external_reset;
|
||||
ah->disable_2ghz = pdata->disable_2ghz;
|
||||
ah->disable_5ghz = pdata->disable_5ghz;
|
||||
|
||||
if (!pdata->endian_check)
|
||||
ah->ah_flags |= AH_NO_EEP_SWAP;
|
||||
}
|
||||
|
||||
if (pdata->eeprom_name) {
|
||||
ret = ath9k_eeprom_request(sc, pdata->eeprom_name);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (pdata->led_active_high)
|
||||
ah->config.led_active_high = true;
|
||||
|
||||
if (pdata->tx_gain_buffalo)
|
||||
ah->config.tx_gain_buffalo = true;
|
||||
|
||||
return ret;
|
||||
if (pdata->macaddr)
|
||||
ether_addr_copy(common->macaddr, pdata->macaddr);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ath9k_init_softc(u16 devid, struct ath_softc *sc,
|
||||
const struct ath_bus_ops *bus_ops)
|
||||
{
|
||||
struct ath9k_platform_data *pdata = sc->dev->platform_data;
|
||||
struct ath_hw *ah = NULL;
|
||||
struct ath9k_hw_capabilities *pCap;
|
||||
struct ath_common *common;
|
||||
@ -550,6 +571,8 @@ static int ath9k_init_softc(u16 devid, struct ath_softc *sc,
|
||||
ah->dev = sc->dev;
|
||||
ah->hw = sc->hw;
|
||||
ah->hw_version.devid = devid;
|
||||
ah->ah_flags |= AH_USE_EEPROM;
|
||||
ah->led_pin = -1;
|
||||
ah->reg_ops.read = ath9k_ioread32;
|
||||
ah->reg_ops.multi_read = ath9k_multi_ioread32;
|
||||
ah->reg_ops.write = ath9k_iowrite32;
|
||||
@ -569,22 +592,6 @@ static int ath9k_init_softc(u16 devid, struct ath_softc *sc,
|
||||
if (!ath9k_is_chanctx_enabled())
|
||||
sc->cur_chan->hw_queue_base = 0;
|
||||
|
||||
if (!pdata || pdata->use_eeprom) {
|
||||
ah->ah_flags |= AH_USE_EEPROM;
|
||||
sc->sc_ah->led_pin = -1;
|
||||
} else {
|
||||
sc->sc_ah->gpio_mask = pdata->gpio_mask;
|
||||
sc->sc_ah->gpio_val = pdata->gpio_val;
|
||||
sc->sc_ah->led_pin = pdata->led_pin;
|
||||
ah->is_clk_25mhz = pdata->is_clk_25mhz;
|
||||
ah->get_mac_revision = pdata->get_mac_revision;
|
||||
ah->external_reset = pdata->external_reset;
|
||||
ah->disable_2ghz = pdata->disable_2ghz;
|
||||
ah->disable_5ghz = pdata->disable_5ghz;
|
||||
if (!pdata->endian_check)
|
||||
ah->ah_flags |= AH_NO_EEP_SWAP;
|
||||
}
|
||||
|
||||
common->ops = &ah->reg_ops;
|
||||
common->bus_ops = bus_ops;
|
||||
common->ps_ops = &ath9k_ps_ops;
|
||||
@ -600,7 +607,7 @@ static int ath9k_init_softc(u16 devid, struct ath_softc *sc,
|
||||
*/
|
||||
ath9k_init_pcoem_platform(sc);
|
||||
|
||||
ret = ath9k_init_soc_platform(sc);
|
||||
ret = ath9k_init_platform(sc);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
@ -646,9 +653,6 @@ static int ath9k_init_softc(u16 devid, struct ath_softc *sc,
|
||||
if (ret)
|
||||
goto err_hw;
|
||||
|
||||
if (pdata && pdata->macaddr)
|
||||
memcpy(common->macaddr, pdata->macaddr, ETH_ALEN);
|
||||
|
||||
ret = ath9k_init_queues(sc);
|
||||
if (ret)
|
||||
goto err_queues;
|
||||
|
@ -65,10 +65,6 @@
|
||||
#define INIT_SSH_RETRY 32
|
||||
#define INIT_SLG_RETRY 32
|
||||
|
||||
#define ATH9K_SLOT_TIME_6 6
|
||||
#define ATH9K_SLOT_TIME_9 9
|
||||
#define ATH9K_SLOT_TIME_20 20
|
||||
|
||||
#define ATH9K_TXERR_XRETRY 0x01
|
||||
#define ATH9K_TXERR_FILT 0x02
|
||||
#define ATH9K_TXERR_FIFO 0x04
|
||||
|
@ -910,6 +910,22 @@ static bool ath9k_uses_beacons(int type)
|
||||
}
|
||||
}
|
||||
|
||||
static void ath9k_vif_iter_set_beacon(struct ath9k_vif_iter_data *iter_data,
|
||||
struct ieee80211_vif *vif)
|
||||
{
|
||||
/* Use the first (configured) interface, but prefering AP interfaces. */
|
||||
if (!iter_data->primary_beacon_vif) {
|
||||
iter_data->primary_beacon_vif = vif;
|
||||
} else {
|
||||
if (iter_data->primary_beacon_vif->type != NL80211_IFTYPE_AP &&
|
||||
vif->type == NL80211_IFTYPE_AP)
|
||||
iter_data->primary_beacon_vif = vif;
|
||||
}
|
||||
|
||||
iter_data->beacons = true;
|
||||
iter_data->nbcnvifs += 1;
|
||||
}
|
||||
|
||||
static void ath9k_vif_iter(struct ath9k_vif_iter_data *iter_data,
|
||||
u8 *mac, struct ieee80211_vif *vif)
|
||||
{
|
||||
@ -926,11 +942,13 @@ static void ath9k_vif_iter(struct ath9k_vif_iter_data *iter_data,
|
||||
}
|
||||
|
||||
if (!vif->bss_conf.use_short_slot)
|
||||
iter_data->slottime = ATH9K_SLOT_TIME_20;
|
||||
iter_data->slottime = 20;
|
||||
|
||||
switch (vif->type) {
|
||||
case NL80211_IFTYPE_AP:
|
||||
iter_data->naps++;
|
||||
if (vif->bss_conf.enable_beacon)
|
||||
ath9k_vif_iter_set_beacon(iter_data, vif);
|
||||
break;
|
||||
case NL80211_IFTYPE_STATION:
|
||||
iter_data->nstations++;
|
||||
@ -943,12 +961,12 @@ static void ath9k_vif_iter(struct ath9k_vif_iter_data *iter_data,
|
||||
case NL80211_IFTYPE_ADHOC:
|
||||
iter_data->nadhocs++;
|
||||
if (vif->bss_conf.enable_beacon)
|
||||
iter_data->beacons = true;
|
||||
ath9k_vif_iter_set_beacon(iter_data, vif);
|
||||
break;
|
||||
case NL80211_IFTYPE_MESH_POINT:
|
||||
iter_data->nmeshes++;
|
||||
if (vif->bss_conf.enable_beacon)
|
||||
iter_data->beacons = true;
|
||||
ath9k_vif_iter_set_beacon(iter_data, vif);
|
||||
break;
|
||||
case NL80211_IFTYPE_WDS:
|
||||
iter_data->nwds++;
|
||||
@ -999,7 +1017,7 @@ void ath9k_calculate_iter_data(struct ath_softc *sc,
|
||||
*/
|
||||
memset(iter_data, 0, sizeof(*iter_data));
|
||||
eth_broadcast_addr(iter_data->mask);
|
||||
iter_data->slottime = ATH9K_SLOT_TIME_9;
|
||||
iter_data->slottime = 9;
|
||||
|
||||
list_for_each_entry(avp, &ctx->vifs, list)
|
||||
ath9k_vif_iter(iter_data, avp->vif->addr, avp->vif);
|
||||
@ -1061,7 +1079,7 @@ static void ath9k_set_offchannel_state(struct ath_softc *sc)
|
||||
ah->opmode = vif->type;
|
||||
ah->imask &= ~ATH9K_INT_SWBA;
|
||||
ah->imask &= ~ATH9K_INT_TSFOOR;
|
||||
ah->slottime = ATH9K_SLOT_TIME_9;
|
||||
ah->slottime = 9;
|
||||
|
||||
ath_hw_setbssidmask(common);
|
||||
ath9k_hw_setopmode(ah);
|
||||
@ -1081,7 +1099,6 @@ void ath9k_calculate_summary_state(struct ath_softc *sc,
|
||||
struct ath_hw *ah = sc->sc_ah;
|
||||
struct ath_common *common = ath9k_hw_common(ah);
|
||||
struct ath9k_vif_iter_data iter_data;
|
||||
struct ath_beacon_config *cur_conf;
|
||||
|
||||
ath_chanctx_check_active(sc, ctx);
|
||||
|
||||
@ -1103,13 +1120,12 @@ void ath9k_calculate_summary_state(struct ath_softc *sc,
|
||||
ath_hw_setbssidmask(common);
|
||||
|
||||
if (iter_data.naps > 0) {
|
||||
cur_conf = &ctx->beacon;
|
||||
ath9k_hw_set_tsfadjust(ah, true);
|
||||
ah->opmode = NL80211_IFTYPE_AP;
|
||||
if (cur_conf->enable_beacon)
|
||||
iter_data.beacons = true;
|
||||
} else {
|
||||
ath9k_hw_set_tsfadjust(ah, false);
|
||||
if (iter_data.beacons)
|
||||
ath9k_beacon_ensure_primary_slot(sc);
|
||||
|
||||
if (iter_data.nmeshes)
|
||||
ah->opmode = NL80211_IFTYPE_MESH_POINT;
|
||||
@ -1134,7 +1150,6 @@ void ath9k_calculate_summary_state(struct ath_softc *sc,
|
||||
ctx->switch_after_beacon = true;
|
||||
}
|
||||
|
||||
ah->imask &= ~ATH9K_INT_SWBA;
|
||||
if (ah->opmode == NL80211_IFTYPE_STATION) {
|
||||
bool changed = (iter_data.primary_sta != ctx->primary_sta);
|
||||
|
||||
@ -1151,16 +1166,12 @@ void ath9k_calculate_summary_state(struct ath_softc *sc,
|
||||
if (ath9k_hw_mci_is_enabled(sc->sc_ah))
|
||||
ath9k_mci_update_wlan_channels(sc, true);
|
||||
}
|
||||
} else if (iter_data.beacons) {
|
||||
ah->imask |= ATH9K_INT_SWBA;
|
||||
}
|
||||
sc->nbcnvifs = iter_data.nbcnvifs;
|
||||
ath9k_beacon_config(sc, iter_data.primary_beacon_vif,
|
||||
iter_data.beacons);
|
||||
ath9k_hw_set_interrupts(ah);
|
||||
|
||||
if (iter_data.beacons)
|
||||
set_bit(ATH_OP_BEACONS, &common->op_flags);
|
||||
else
|
||||
clear_bit(ATH_OP_BEACONS, &common->op_flags);
|
||||
|
||||
if (ah->slottime != iter_data.slottime) {
|
||||
ah->slottime = iter_data.slottime;
|
||||
ath9k_hw_init_global_settings(ah);
|
||||
@ -1777,9 +1788,7 @@ static void ath9k_bss_info_changed(struct ieee80211_hw *hw,
|
||||
if ((changed & BSS_CHANGED_BEACON_ENABLED) ||
|
||||
(changed & BSS_CHANGED_BEACON_INT) ||
|
||||
(changed & BSS_CHANGED_BEACON_INFO)) {
|
||||
ath9k_beacon_config(sc, vif, changed);
|
||||
if (changed & BSS_CHANGED_BEACON_ENABLED)
|
||||
ath9k_calculate_summary_state(sc, avp->chanctx);
|
||||
ath9k_calculate_summary_state(sc, avp->chanctx);
|
||||
}
|
||||
|
||||
if ((avp->chanctx == sc->cur_chan) &&
|
||||
@ -1788,6 +1797,7 @@ static void ath9k_bss_info_changed(struct ieee80211_hw *hw,
|
||||
slottime = 9;
|
||||
else
|
||||
slottime = 20;
|
||||
|
||||
if (vif->type == NL80211_IFTYPE_AP) {
|
||||
/*
|
||||
* Defer update, so that connected stations can adjust
|
||||
@ -1823,11 +1833,19 @@ static void ath9k_bss_info_changed(struct ieee80211_hw *hw,
|
||||
static u64 ath9k_get_tsf(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
|
||||
{
|
||||
struct ath_softc *sc = hw->priv;
|
||||
struct ath_vif *avp = (void *)vif->drv_priv;
|
||||
u64 tsf;
|
||||
|
||||
mutex_lock(&sc->mutex);
|
||||
ath9k_ps_wakeup(sc);
|
||||
tsf = ath9k_hw_gettsf64(sc->sc_ah);
|
||||
/* Get current TSF either from HW or kernel time. */
|
||||
if (sc->cur_chan == avp->chanctx) {
|
||||
tsf = ath9k_hw_gettsf64(sc->sc_ah);
|
||||
} else {
|
||||
tsf = sc->cur_chan->tsf_val +
|
||||
ath9k_hw_get_tsf_offset(&sc->cur_chan->tsf_ts, NULL);
|
||||
}
|
||||
tsf += le64_to_cpu(avp->tsf_adjust);
|
||||
ath9k_ps_restore(sc);
|
||||
mutex_unlock(&sc->mutex);
|
||||
|
||||
@ -1839,10 +1857,15 @@ static void ath9k_set_tsf(struct ieee80211_hw *hw,
|
||||
u64 tsf)
|
||||
{
|
||||
struct ath_softc *sc = hw->priv;
|
||||
struct ath_vif *avp = (void *)vif->drv_priv;
|
||||
|
||||
mutex_lock(&sc->mutex);
|
||||
ath9k_ps_wakeup(sc);
|
||||
ath9k_hw_settsf64(sc->sc_ah, tsf);
|
||||
tsf -= le64_to_cpu(avp->tsf_adjust);
|
||||
getrawmonotonic(&avp->chanctx->tsf_ts);
|
||||
if (sc->cur_chan == avp->chanctx)
|
||||
ath9k_hw_settsf64(sc->sc_ah, tsf);
|
||||
avp->chanctx->tsf_val = tsf;
|
||||
ath9k_ps_restore(sc);
|
||||
mutex_unlock(&sc->mutex);
|
||||
}
|
||||
@ -1850,11 +1873,15 @@ static void ath9k_set_tsf(struct ieee80211_hw *hw,
|
||||
static void ath9k_reset_tsf(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
|
||||
{
|
||||
struct ath_softc *sc = hw->priv;
|
||||
struct ath_vif *avp = (void *)vif->drv_priv;
|
||||
|
||||
mutex_lock(&sc->mutex);
|
||||
|
||||
ath9k_ps_wakeup(sc);
|
||||
ath9k_hw_reset_tsf(sc->sc_ah);
|
||||
getrawmonotonic(&avp->chanctx->tsf_ts);
|
||||
if (sc->cur_chan == avp->chanctx)
|
||||
ath9k_hw_reset_tsf(sc->sc_ah);
|
||||
avp->chanctx->tsf_val = 0;
|
||||
ath9k_ps_restore(sc);
|
||||
|
||||
mutex_unlock(&sc->mutex);
|
||||
|
@ -19,7 +19,6 @@
|
||||
#include <linux/nl80211.h>
|
||||
#include <linux/pci.h>
|
||||
#include <linux/pci-aspm.h>
|
||||
#include <linux/ath9k_platform.h>
|
||||
#include <linux/module.h>
|
||||
#include "ath9k.h"
|
||||
|
||||
@ -786,35 +785,21 @@ static void ath_pci_read_cachesize(struct ath_common *common, int *csz)
|
||||
|
||||
static bool ath_pci_eeprom_read(struct ath_common *common, u32 off, u16 *data)
|
||||
{
|
||||
struct ath_softc *sc = (struct ath_softc *) common->priv;
|
||||
struct ath9k_platform_data *pdata = sc->dev->platform_data;
|
||||
struct ath_hw *ah = (struct ath_hw *) common->ah;
|
||||
|
||||
if (pdata && !pdata->use_eeprom) {
|
||||
if (off >= (ARRAY_SIZE(pdata->eeprom_data))) {
|
||||
ath_err(common,
|
||||
"%s: eeprom read failed, offset %08x is out of range\n",
|
||||
__func__, off);
|
||||
}
|
||||
common->ops->read(ah, AR5416_EEPROM_OFFSET + (off << AR5416_EEPROM_S));
|
||||
|
||||
*data = pdata->eeprom_data[off];
|
||||
} else {
|
||||
struct ath_hw *ah = (struct ath_hw *) common->ah;
|
||||
|
||||
common->ops->read(ah, AR5416_EEPROM_OFFSET +
|
||||
(off << AR5416_EEPROM_S));
|
||||
|
||||
if (!ath9k_hw_wait(ah,
|
||||
AR_EEPROM_STATUS_DATA,
|
||||
AR_EEPROM_STATUS_DATA_BUSY |
|
||||
AR_EEPROM_STATUS_DATA_PROT_ACCESS, 0,
|
||||
AH_WAIT_TIMEOUT)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
*data = MS(common->ops->read(ah, AR_EEPROM_STATUS_DATA),
|
||||
AR_EEPROM_STATUS_DATA_VAL);
|
||||
if (!ath9k_hw_wait(ah,
|
||||
AR_EEPROM_STATUS_DATA,
|
||||
AR_EEPROM_STATUS_DATA_BUSY |
|
||||
AR_EEPROM_STATUS_DATA_PROT_ACCESS, 0,
|
||||
AH_WAIT_TIMEOUT)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
*data = MS(common->ops->read(ah, AR_EEPROM_STATUS_DATA),
|
||||
AR_EEPROM_STATUS_DATA_VAL);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -35,26 +35,27 @@ void *wcn36xx_dxe_get_next_bd(struct wcn36xx *wcn, bool is_low)
|
||||
return ch->head_blk_ctl->bd_cpu_addr;
|
||||
}
|
||||
|
||||
static void wcn36xx_ccu_write_register(struct wcn36xx *wcn, int addr, int data)
|
||||
{
|
||||
wcn36xx_dbg(WCN36XX_DBG_DXE,
|
||||
"wcn36xx_ccu_write_register: addr=%x, data=%x\n",
|
||||
addr, data);
|
||||
|
||||
writel(data, wcn->ccu_base + addr);
|
||||
}
|
||||
|
||||
static void wcn36xx_dxe_write_register(struct wcn36xx *wcn, int addr, int data)
|
||||
{
|
||||
wcn36xx_dbg(WCN36XX_DBG_DXE,
|
||||
"wcn36xx_dxe_write_register: addr=%x, data=%x\n",
|
||||
addr, data);
|
||||
|
||||
writel(data, wcn->mmio + addr);
|
||||
writel(data, wcn->dxe_base + addr);
|
||||
}
|
||||
|
||||
#define wcn36xx_dxe_write_register_x(wcn, reg, reg_data) \
|
||||
do { \
|
||||
if (wcn->chip_version == WCN36XX_CHIP_3680) \
|
||||
wcn36xx_dxe_write_register(wcn, reg ## _3680, reg_data); \
|
||||
else \
|
||||
wcn36xx_dxe_write_register(wcn, reg ## _3660, reg_data); \
|
||||
} while (0) \
|
||||
|
||||
static void wcn36xx_dxe_read_register(struct wcn36xx *wcn, int addr, int *data)
|
||||
{
|
||||
*data = readl(wcn->mmio + addr);
|
||||
*data = readl(wcn->dxe_base + addr);
|
||||
|
||||
wcn36xx_dbg(WCN36XX_DBG_DXE,
|
||||
"wcn36xx_dxe_read_register: addr=%x, data=%x\n",
|
||||
@ -701,9 +702,13 @@ int wcn36xx_dxe_init(struct wcn36xx *wcn)
|
||||
reg_data = WCN36XX_DXE_REG_RESET;
|
||||
wcn36xx_dxe_write_register(wcn, WCN36XX_DXE_REG_CSR_RESET, reg_data);
|
||||
|
||||
/* Setting interrupt path */
|
||||
reg_data = WCN36XX_DXE_CCU_INT;
|
||||
wcn36xx_dxe_write_register_x(wcn, WCN36XX_DXE_REG_CCU_INT, reg_data);
|
||||
/* Select channels for rx avail and xfer done interrupts... */
|
||||
reg_data = (WCN36XX_DXE_INT_CH3_MASK | WCN36XX_DXE_INT_CH1_MASK) << 16 |
|
||||
WCN36XX_DXE_INT_CH0_MASK | WCN36XX_DXE_INT_CH4_MASK;
|
||||
if (wcn->is_pronto)
|
||||
wcn36xx_ccu_write_register(wcn, WCN36XX_CCU_DXE_INT_SELECT_PRONTO, reg_data);
|
||||
else
|
||||
wcn36xx_ccu_write_register(wcn, WCN36XX_CCU_DXE_INT_SELECT_RIVA, reg_data);
|
||||
|
||||
/***************************************/
|
||||
/* Init descriptors for TX LOW channel */
|
||||
|
@ -28,11 +28,10 @@ H2H_TEST_RX_TX = DMA2
|
||||
*/
|
||||
|
||||
/* DXE registers */
|
||||
#define WCN36XX_DXE_MEM_REG 0x202000
|
||||
#define WCN36XX_DXE_MEM_REG 0
|
||||
|
||||
#define WCN36XX_DXE_CCU_INT 0xA0011
|
||||
#define WCN36XX_DXE_REG_CCU_INT_3660 0x200b10
|
||||
#define WCN36XX_DXE_REG_CCU_INT_3680 0x2050dc
|
||||
#define WCN36XX_CCU_DXE_INT_SELECT_RIVA 0x310
|
||||
#define WCN36XX_CCU_DXE_INT_SELECT_PRONTO 0x10dc
|
||||
|
||||
/* TODO This must calculated properly but not hardcoded */
|
||||
#define WCN36XX_DXE_CTRL_TX_L 0x328a44
|
||||
|
@ -4123,7 +4123,7 @@ struct wcn36xx_hal_update_scan_params_req {
|
||||
|
||||
/* Update scan params - sent from host to PNO to be used during PNO
|
||||
* scanningx */
|
||||
struct update_scan_params_req_ex {
|
||||
struct wcn36xx_hal_update_scan_params_req_ex {
|
||||
|
||||
struct wcn36xx_hal_msg_header header;
|
||||
|
||||
@ -4151,7 +4151,7 @@ struct update_scan_params_req_ex {
|
||||
|
||||
/* Cb State */
|
||||
enum phy_chan_bond_state state;
|
||||
};
|
||||
} __packed;
|
||||
|
||||
/* Update scan params - sent from host to PNO to be used during PNO
|
||||
* scanningx */
|
||||
|
@ -19,6 +19,8 @@
|
||||
#include <linux/module.h>
|
||||
#include <linux/firmware.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/of_address.h>
|
||||
#include <linux/of_device.h>
|
||||
#include "wcn36xx.h"
|
||||
|
||||
unsigned int wcn36xx_dbg_mask;
|
||||
@ -259,17 +261,6 @@ static void wcn36xx_feat_caps_info(struct wcn36xx *wcn)
|
||||
}
|
||||
}
|
||||
|
||||
static void wcn36xx_detect_chip_version(struct wcn36xx *wcn)
|
||||
{
|
||||
if (get_feat_caps(wcn->fw_feat_caps, DOT11AC)) {
|
||||
wcn36xx_info("Chip is 3680\n");
|
||||
wcn->chip_version = WCN36XX_CHIP_3680;
|
||||
} else {
|
||||
wcn36xx_info("Chip is 3660\n");
|
||||
wcn->chip_version = WCN36XX_CHIP_3660;
|
||||
}
|
||||
}
|
||||
|
||||
static int wcn36xx_start(struct ieee80211_hw *hw)
|
||||
{
|
||||
struct wcn36xx *wcn = hw->priv;
|
||||
@ -324,9 +315,6 @@ static int wcn36xx_start(struct ieee80211_hw *hw)
|
||||
wcn36xx_feat_caps_info(wcn);
|
||||
}
|
||||
|
||||
wcn36xx_detect_chip_version(wcn);
|
||||
wcn36xx_smd_update_cfg(wcn, WCN36XX_HAL_CFG_ENABLE_MC_ADDR_LIST, 1);
|
||||
|
||||
/* DMA channel initialization */
|
||||
ret = wcn36xx_dxe_init(wcn);
|
||||
if (ret) {
|
||||
@ -1064,7 +1052,11 @@ static int wcn36xx_init_ieee80211(struct wcn36xx *wcn)
|
||||
static int wcn36xx_platform_get_resources(struct wcn36xx *wcn,
|
||||
struct platform_device *pdev)
|
||||
{
|
||||
struct device_node *mmio_node;
|
||||
struct resource *res;
|
||||
int index;
|
||||
int ret;
|
||||
|
||||
/* Set TX IRQ */
|
||||
res = platform_get_resource_byname(pdev, IORESOURCE_IRQ,
|
||||
"wcnss_wlantx_irq");
|
||||
@ -1083,19 +1075,40 @@ static int wcn36xx_platform_get_resources(struct wcn36xx *wcn,
|
||||
}
|
||||
wcn->rx_irq = res->start;
|
||||
|
||||
/* Map the memory */
|
||||
res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
|
||||
"wcnss_mmio");
|
||||
if (!res) {
|
||||
wcn36xx_err("failed to get mmio\n");
|
||||
return -ENOENT;
|
||||
mmio_node = of_parse_phandle(pdev->dev.parent->of_node, "qcom,mmio", 0);
|
||||
if (!mmio_node) {
|
||||
wcn36xx_err("failed to acquire qcom,mmio reference\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
wcn->mmio = ioremap(res->start, resource_size(res));
|
||||
if (!wcn->mmio) {
|
||||
wcn36xx_err("failed to map io memory\n");
|
||||
return -ENOMEM;
|
||||
|
||||
wcn->is_pronto = !!of_device_is_compatible(mmio_node, "qcom,pronto");
|
||||
|
||||
/* Map the CCU memory */
|
||||
index = of_property_match_string(mmio_node, "reg-names", "ccu");
|
||||
wcn->ccu_base = of_iomap(mmio_node, index);
|
||||
if (!wcn->ccu_base) {
|
||||
wcn36xx_err("failed to map ccu memory\n");
|
||||
ret = -ENOMEM;
|
||||
goto put_mmio_node;
|
||||
}
|
||||
|
||||
/* Map the DXE memory */
|
||||
index = of_property_match_string(mmio_node, "reg-names", "dxe");
|
||||
wcn->dxe_base = of_iomap(mmio_node, index);
|
||||
if (!wcn->dxe_base) {
|
||||
wcn36xx_err("failed to map dxe memory\n");
|
||||
ret = -ENOMEM;
|
||||
goto unmap_ccu;
|
||||
}
|
||||
|
||||
of_node_put(mmio_node);
|
||||
return 0;
|
||||
|
||||
unmap_ccu:
|
||||
iounmap(wcn->ccu_base);
|
||||
put_mmio_node:
|
||||
of_node_put(mmio_node);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int wcn36xx_probe(struct platform_device *pdev)
|
||||
@ -1138,7 +1151,8 @@ static int wcn36xx_probe(struct platform_device *pdev)
|
||||
return 0;
|
||||
|
||||
out_unmap:
|
||||
iounmap(wcn->mmio);
|
||||
iounmap(wcn->ccu_base);
|
||||
iounmap(wcn->dxe_base);
|
||||
out_wq:
|
||||
ieee80211_free_hw(hw);
|
||||
out_err:
|
||||
@ -1154,7 +1168,8 @@ static int wcn36xx_remove(struct platform_device *pdev)
|
||||
mutex_destroy(&wcn->hal_mutex);
|
||||
|
||||
ieee80211_unregister_hw(hw);
|
||||
iounmap(wcn->mmio);
|
||||
iounmap(wcn->dxe_base);
|
||||
iounmap(wcn->ccu_base);
|
||||
ieee80211_free_hw(hw);
|
||||
|
||||
return 0;
|
||||
|
@ -674,22 +674,25 @@ static int wcn36xx_smd_update_scan_params_rsp(void *buf, size_t len)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int wcn36xx_smd_update_scan_params(struct wcn36xx *wcn)
|
||||
int wcn36xx_smd_update_scan_params(struct wcn36xx *wcn,
|
||||
u8 *channels, size_t channel_count)
|
||||
{
|
||||
struct wcn36xx_hal_update_scan_params_req msg_body;
|
||||
struct wcn36xx_hal_update_scan_params_req_ex msg_body;
|
||||
int ret = 0;
|
||||
|
||||
mutex_lock(&wcn->hal_mutex);
|
||||
INIT_HAL_MSG(msg_body, WCN36XX_HAL_UPDATE_SCAN_PARAM_REQ);
|
||||
|
||||
msg_body.dot11d_enabled = 0;
|
||||
msg_body.dot11d_resolved = 0;
|
||||
msg_body.channel_count = 26;
|
||||
msg_body.dot11d_enabled = false;
|
||||
msg_body.dot11d_resolved = true;
|
||||
|
||||
msg_body.channel_count = channel_count;
|
||||
memcpy(msg_body.channels, channels, channel_count);
|
||||
msg_body.active_min_ch_time = 60;
|
||||
msg_body.active_max_ch_time = 120;
|
||||
msg_body.passive_min_ch_time = 60;
|
||||
msg_body.passive_max_ch_time = 110;
|
||||
msg_body.state = 0;
|
||||
msg_body.state = PHY_SINGLE_CHANNEL_CENTERED;
|
||||
|
||||
PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
|
||||
|
||||
@ -2226,17 +2229,12 @@ static void wcn36xx_smd_rsp_process(struct wcn36xx *wcn, void *buf, size_t len)
|
||||
|
||||
case WCN36XX_HAL_COEX_IND:
|
||||
case WCN36XX_HAL_AVOID_FREQ_RANGE_IND:
|
||||
case WCN36XX_HAL_DEL_BA_IND:
|
||||
case WCN36XX_HAL_OTA_TX_COMPL_IND:
|
||||
case WCN36XX_HAL_MISSED_BEACON_IND:
|
||||
case WCN36XX_HAL_DELETE_STA_CONTEXT_IND:
|
||||
msg_ind = kmalloc(sizeof(*msg_ind), GFP_KERNEL);
|
||||
if (!msg_ind)
|
||||
goto nomem;
|
||||
msg_ind->msg_len = len;
|
||||
msg_ind->msg = kmemdup(buf, len, GFP_KERNEL);
|
||||
if (!msg_ind->msg) {
|
||||
kfree(msg_ind);
|
||||
nomem:
|
||||
msg_ind = kmalloc(sizeof(*msg_ind) + len, GFP_KERNEL);
|
||||
if (!msg_ind) {
|
||||
/*
|
||||
* FIXME: Do something smarter then just
|
||||
* printing an error.
|
||||
@ -2245,10 +2243,14 @@ nomem:
|
||||
msg_header->msg_type);
|
||||
break;
|
||||
}
|
||||
mutex_lock(&wcn->hal_ind_mutex);
|
||||
|
||||
msg_ind->msg_len = len;
|
||||
memcpy(msg_ind->msg, buf, len);
|
||||
|
||||
spin_lock(&wcn->hal_ind_lock);
|
||||
list_add_tail(&msg_ind->list, &wcn->hal_ind_queue);
|
||||
queue_work(wcn->hal_ind_wq, &wcn->hal_ind_work);
|
||||
mutex_unlock(&wcn->hal_ind_mutex);
|
||||
spin_unlock(&wcn->hal_ind_lock);
|
||||
wcn36xx_dbg(WCN36XX_DBG_HAL, "indication arrived\n");
|
||||
break;
|
||||
default:
|
||||
@ -2262,8 +2264,9 @@ static void wcn36xx_ind_smd_work(struct work_struct *work)
|
||||
container_of(work, struct wcn36xx, hal_ind_work);
|
||||
struct wcn36xx_hal_msg_header *msg_header;
|
||||
struct wcn36xx_hal_ind_msg *hal_ind_msg;
|
||||
unsigned long flags;
|
||||
|
||||
mutex_lock(&wcn->hal_ind_mutex);
|
||||
spin_lock_irqsave(&wcn->hal_ind_lock, flags);
|
||||
|
||||
hal_ind_msg = list_first_entry(&wcn->hal_ind_queue,
|
||||
struct wcn36xx_hal_ind_msg,
|
||||
@ -2273,6 +2276,7 @@ static void wcn36xx_ind_smd_work(struct work_struct *work)
|
||||
|
||||
switch (msg_header->msg_type) {
|
||||
case WCN36XX_HAL_COEX_IND:
|
||||
case WCN36XX_HAL_DEL_BA_IND:
|
||||
case WCN36XX_HAL_AVOID_FREQ_RANGE_IND:
|
||||
break;
|
||||
case WCN36XX_HAL_OTA_TX_COMPL_IND:
|
||||
@ -2295,9 +2299,8 @@ static void wcn36xx_ind_smd_work(struct work_struct *work)
|
||||
msg_header->msg_type);
|
||||
}
|
||||
list_del(wcn->hal_ind_queue.next);
|
||||
kfree(hal_ind_msg->msg);
|
||||
spin_unlock_irqrestore(&wcn->hal_ind_lock, flags);
|
||||
kfree(hal_ind_msg);
|
||||
mutex_unlock(&wcn->hal_ind_mutex);
|
||||
}
|
||||
int wcn36xx_smd_open(struct wcn36xx *wcn)
|
||||
{
|
||||
@ -2310,7 +2313,7 @@ int wcn36xx_smd_open(struct wcn36xx *wcn)
|
||||
}
|
||||
INIT_WORK(&wcn->hal_ind_work, wcn36xx_ind_smd_work);
|
||||
INIT_LIST_HEAD(&wcn->hal_ind_queue);
|
||||
mutex_init(&wcn->hal_ind_mutex);
|
||||
spin_lock_init(&wcn->hal_ind_lock);
|
||||
|
||||
ret = wcn->ctrl_ops->open(wcn, wcn36xx_smd_rsp_process);
|
||||
if (ret) {
|
||||
@ -2330,5 +2333,4 @@ void wcn36xx_smd_close(struct wcn36xx *wcn)
|
||||
{
|
||||
wcn->ctrl_ops->close();
|
||||
destroy_workqueue(wcn->hal_ind_wq);
|
||||
mutex_destroy(&wcn->hal_ind_mutex);
|
||||
}
|
||||
|
@ -46,8 +46,8 @@ struct wcn36xx_fw_msg_status_rsp {
|
||||
|
||||
struct wcn36xx_hal_ind_msg {
|
||||
struct list_head list;
|
||||
u8 *msg;
|
||||
size_t msg_len;
|
||||
u8 msg[];
|
||||
};
|
||||
|
||||
struct wcn36xx;
|
||||
@ -63,7 +63,7 @@ int wcn36xx_smd_start_scan(struct wcn36xx *wcn);
|
||||
int wcn36xx_smd_end_scan(struct wcn36xx *wcn);
|
||||
int wcn36xx_smd_finish_scan(struct wcn36xx *wcn,
|
||||
enum wcn36xx_hal_sys_mode mode);
|
||||
int wcn36xx_smd_update_scan_params(struct wcn36xx *wcn);
|
||||
int wcn36xx_smd_update_scan_params(struct wcn36xx *wcn, u8 *channels, size_t channel_count);
|
||||
int wcn36xx_smd_add_sta_self(struct wcn36xx *wcn, struct ieee80211_vif *vif);
|
||||
int wcn36xx_smd_delete_sta_self(struct wcn36xx *wcn, u8 *addr);
|
||||
int wcn36xx_smd_delete_sta(struct wcn36xx *wcn, u8 sta_index);
|
||||
|
@ -193,7 +193,7 @@ struct wcn36xx {
|
||||
u8 fw_minor;
|
||||
u8 fw_major;
|
||||
u32 fw_feat_caps[WCN36XX_HAL_CAPS_SIZE];
|
||||
u32 chip_version;
|
||||
bool is_pronto;
|
||||
|
||||
/* extra byte for the NULL termination */
|
||||
u8 crm_version[WCN36XX_HAL_VERSION_LENGTH + 1];
|
||||
@ -202,7 +202,8 @@ struct wcn36xx {
|
||||
/* IRQs */
|
||||
int tx_irq;
|
||||
int rx_irq;
|
||||
void __iomem *mmio;
|
||||
void __iomem *ccu_base;
|
||||
void __iomem *dxe_base;
|
||||
|
||||
struct wcn36xx_platform_ctrl_ops *ctrl_ops;
|
||||
/*
|
||||
@ -215,7 +216,7 @@ struct wcn36xx {
|
||||
struct completion hal_rsp_compl;
|
||||
struct workqueue_struct *hal_ind_wq;
|
||||
struct work_struct hal_ind_work;
|
||||
struct mutex hal_ind_mutex;
|
||||
spinlock_t hal_ind_lock;
|
||||
struct list_head hal_ind_queue;
|
||||
|
||||
/* DXE channels */
|
||||
@ -241,9 +242,6 @@ struct wcn36xx {
|
||||
|
||||
};
|
||||
|
||||
#define WCN36XX_CHIP_3660 0
|
||||
#define WCN36XX_CHIP_3680 1
|
||||
|
||||
static inline bool wcn36xx_is_fw_version(struct wcn36xx *wcn,
|
||||
u8 major,
|
||||
u8 minor,
|
||||
|
@ -726,8 +726,10 @@ int brcmf_sdiod_recv_chain(struct brcmf_sdio_dev *sdiodev,
|
||||
return -ENOMEM;
|
||||
err = brcmf_sdiod_buffrw(sdiodev, SDIO_FUNC_2, false, addr,
|
||||
glom_skb);
|
||||
if (err)
|
||||
if (err) {
|
||||
brcmu_pkt_buf_free_skb(glom_skb);
|
||||
goto done;
|
||||
}
|
||||
|
||||
skb_queue_walk(pktq, skb) {
|
||||
memcpy(skb->data, glom_skb->data, skb->len);
|
||||
|
@ -4666,6 +4666,15 @@ brcmf_cfg80211_start_ap(struct wiphy *wiphy, struct net_device *ndev,
|
||||
brcmf_err("SET SSID error (%d)\n", err);
|
||||
goto exit;
|
||||
}
|
||||
|
||||
if (settings->hidden_ssid) {
|
||||
err = brcmf_fil_iovar_int_set(ifp, "closednet", 1);
|
||||
if (err) {
|
||||
brcmf_err("closednet error (%d)\n", err);
|
||||
goto exit;
|
||||
}
|
||||
}
|
||||
|
||||
brcmf_dbg(TRACE, "AP mode configuration complete\n");
|
||||
} else if (dev_role == NL80211_IFTYPE_P2P_GO) {
|
||||
err = brcmf_fil_iovar_int_set(ifp, "chanspec", chanspec);
|
||||
@ -4724,6 +4733,10 @@ static int brcmf_cfg80211_stop_ap(struct wiphy *wiphy, struct net_device *ndev)
|
||||
return err;
|
||||
}
|
||||
|
||||
/* First BSS doesn't get a full reset */
|
||||
if (ifp->bsscfgidx == 0)
|
||||
brcmf_fil_iovar_int_set(ifp, "closednet", 0);
|
||||
|
||||
memset(&join_params, 0, sizeof(join_params));
|
||||
err = brcmf_fil_cmd_data_set(ifp, BRCMF_C_SET_SSID,
|
||||
&join_params, sizeof(join_params));
|
||||
|
@ -2469,10 +2469,22 @@ void brcmf_fws_bustxfail(struct brcmf_fws_info *fws, struct sk_buff *skb)
|
||||
void brcmf_fws_bus_blocked(struct brcmf_pub *drvr, bool flow_blocked)
|
||||
{
|
||||
struct brcmf_fws_info *fws = drvr->fws;
|
||||
struct brcmf_if *ifp;
|
||||
int i;
|
||||
|
||||
fws->bus_flow_blocked = flow_blocked;
|
||||
if (!flow_blocked)
|
||||
brcmf_fws_schedule_deq(fws);
|
||||
else
|
||||
fws->stats.bus_flow_block++;
|
||||
if (fws->avoid_queueing) {
|
||||
for (i = 0; i < BRCMF_MAX_IFS; i++) {
|
||||
ifp = drvr->iflist[i];
|
||||
if (!ifp || !ifp->ndev)
|
||||
continue;
|
||||
brcmf_txflowblock_if(ifp, BRCMF_NETIF_STOP_REASON_FLOW,
|
||||
flow_blocked);
|
||||
}
|
||||
} else {
|
||||
fws->bus_flow_blocked = flow_blocked;
|
||||
if (!flow_blocked)
|
||||
brcmf_fws_schedule_deq(fws);
|
||||
else
|
||||
fws->stats.bus_flow_block++;
|
||||
}
|
||||
}
|
||||
|
@ -3305,10 +3305,6 @@ static int brcmf_sdio_download_firmware(struct brcmf_sdio *bus,
|
||||
goto err;
|
||||
}
|
||||
|
||||
/* Allow full data communication using DPC from now on. */
|
||||
brcmf_sdiod_change_state(bus->sdiodev, BRCMF_SDIOD_DATA);
|
||||
bcmerror = 0;
|
||||
|
||||
err:
|
||||
brcmf_sdio_clkctl(bus, CLK_SDONLY, false);
|
||||
sdio_release_host(bus->sdiodev->func[1]);
|
||||
@ -4046,6 +4042,9 @@ static void brcmf_sdio_firmware_callback(struct device *dev,
|
||||
}
|
||||
|
||||
if (err == 0) {
|
||||
/* Allow full data communication using DPC from now on. */
|
||||
brcmf_sdiod_change_state(bus->sdiodev, BRCMF_SDIOD_DATA);
|
||||
|
||||
err = brcmf_sdiod_intr_register(sdiodev);
|
||||
if (err != 0)
|
||||
brcmf_err("intr register failed:%d\n", err);
|
||||
|
@ -1079,8 +1079,10 @@ bool dma_rxfill(struct dma_pub *pub)
|
||||
|
||||
pa = dma_map_single(di->dmadev, p->data, di->rxbufsize,
|
||||
DMA_FROM_DEVICE);
|
||||
if (dma_mapping_error(di->dmadev, pa))
|
||||
if (dma_mapping_error(di->dmadev, pa)) {
|
||||
brcmu_pkt_buf_free_skb(p);
|
||||
return false;
|
||||
}
|
||||
|
||||
/* save the free packet pointer */
|
||||
di->rxp[rxout] = p;
|
||||
|
@ -87,7 +87,7 @@ void
|
||||
brcms_c_stf_ss_algo_channel_get(struct brcms_c_info *wlc, u16 *ss_algo_channel,
|
||||
u16 chanspec)
|
||||
{
|
||||
struct tx_power power;
|
||||
struct tx_power power = { };
|
||||
u8 siso_mcs_id, cdd_mcs_id, stbc_mcs_id;
|
||||
|
||||
/* Clear previous settings */
|
||||
|
@ -73,8 +73,8 @@
|
||||
/* Highest firmware API version supported */
|
||||
#define IWL7260_UCODE_API_MAX 17
|
||||
#define IWL7265_UCODE_API_MAX 17
|
||||
#define IWL7265D_UCODE_API_MAX 21
|
||||
#define IWL3168_UCODE_API_MAX 21
|
||||
#define IWL7265D_UCODE_API_MAX 24
|
||||
#define IWL3168_UCODE_API_MAX 24
|
||||
|
||||
/* Lowest firmware API version supported */
|
||||
#define IWL7260_UCODE_API_MIN 16
|
||||
|
@ -70,8 +70,8 @@
|
||||
#include "iwl-agn-hw.h"
|
||||
|
||||
/* Highest firmware API version supported */
|
||||
#define IWL8000_UCODE_API_MAX 21
|
||||
#define IWL8265_UCODE_API_MAX 21
|
||||
#define IWL8000_UCODE_API_MAX 24
|
||||
#define IWL8265_UCODE_API_MAX 24
|
||||
|
||||
/* Lowest firmware API version supported */
|
||||
#define IWL8000_UCODE_API_MIN 16
|
||||
|
@ -55,7 +55,7 @@
|
||||
#include "iwl-agn-hw.h"
|
||||
|
||||
/* Highest firmware API version supported */
|
||||
#define IWL9000_UCODE_API_MAX 21
|
||||
#define IWL9000_UCODE_API_MAX 24
|
||||
|
||||
/* Lowest firmware API version supported */
|
||||
#define IWL9000_UCODE_API_MIN 16
|
||||
|
@ -2044,8 +2044,8 @@ static int lbs_leave_ibss(struct wiphy *wiphy, struct net_device *dev)
|
||||
|
||||
|
||||
|
||||
int lbs_set_power_mgmt(struct wiphy *wiphy, struct net_device *dev,
|
||||
bool enabled, int timeout)
|
||||
static int lbs_set_power_mgmt(struct wiphy *wiphy, struct net_device *dev,
|
||||
bool enabled, int timeout)
|
||||
{
|
||||
struct lbs_private *priv = wiphy_priv(wiphy);
|
||||
|
||||
|
@ -1936,10 +1936,9 @@ static int mwifiex_cfg80211_start_ap(struct wiphy *wiphy,
|
||||
mwifiex_set_uap_rates(bss_cfg, params);
|
||||
|
||||
if (mwifiex_set_secure_params(priv, bss_cfg, params)) {
|
||||
kfree(bss_cfg);
|
||||
mwifiex_dbg(priv->adapter, ERROR,
|
||||
"Failed to parse secuirty parameters!\n");
|
||||
return -1;
|
||||
goto out;
|
||||
}
|
||||
|
||||
mwifiex_set_ht_params(priv, bss_cfg, params);
|
||||
@ -1968,7 +1967,7 @@ static int mwifiex_cfg80211_start_ap(struct wiphy *wiphy,
|
||||
if (mwifiex_11h_activate(priv, false)) {
|
||||
mwifiex_dbg(priv->adapter, ERROR,
|
||||
"Failed to disable 11h extensions!!");
|
||||
return -1;
|
||||
goto out;
|
||||
}
|
||||
priv->state_11h.is_11h_active = false;
|
||||
}
|
||||
@ -1976,12 +1975,11 @@ static int mwifiex_cfg80211_start_ap(struct wiphy *wiphy,
|
||||
if (mwifiex_config_start_uap(priv, bss_cfg)) {
|
||||
mwifiex_dbg(priv->adapter, ERROR,
|
||||
"Failed to start AP\n");
|
||||
kfree(bss_cfg);
|
||||
return -1;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (mwifiex_set_mgmt_ies(priv, ¶ms->beacon))
|
||||
return -1;
|
||||
goto out;
|
||||
|
||||
if (!netif_carrier_ok(priv->netdev))
|
||||
netif_carrier_on(priv->netdev);
|
||||
@ -1990,6 +1988,10 @@ static int mwifiex_cfg80211_start_ap(struct wiphy *wiphy,
|
||||
memcpy(&priv->bss_cfg, bss_cfg, sizeof(priv->bss_cfg));
|
||||
kfree(bss_cfg);
|
||||
return 0;
|
||||
|
||||
out:
|
||||
kfree(bss_cfg);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -343,16 +343,16 @@ enum {
|
||||
};
|
||||
|
||||
struct mwifiex_ds_reg_rw {
|
||||
__le32 type;
|
||||
__le32 offset;
|
||||
__le32 value;
|
||||
u32 type;
|
||||
u32 offset;
|
||||
u32 value;
|
||||
};
|
||||
|
||||
#define MAX_EEPROM_DATA 256
|
||||
|
||||
struct mwifiex_ds_read_eeprom {
|
||||
__le16 offset;
|
||||
__le16 byte_count;
|
||||
u16 offset;
|
||||
u16 byte_count;
|
||||
u8 value[MAX_EEPROM_DATA];
|
||||
};
|
||||
|
||||
|
@ -202,7 +202,6 @@ static int mwifiex_pcie_probe(struct pci_dev *pdev,
|
||||
if (mwifiex_add_card(card, &add_remove_card_sem, &pcie_ops,
|
||||
MWIFIEX_PCIE)) {
|
||||
pr_err("%s failed\n", __func__);
|
||||
kfree(card);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@ -1617,6 +1616,7 @@ static int mwifiex_pcie_process_cmd_complete(struct mwifiex_adapter *adapter)
|
||||
|
||||
pkt_len = *((__le16 *)skb->data);
|
||||
rx_len = le16_to_cpu(pkt_len);
|
||||
skb_put(skb, MWIFIEX_UPLD_SIZE - skb->len);
|
||||
skb_trim(skb, rx_len);
|
||||
skb_pull(skb, INTF_HEADER_LEN);
|
||||
|
||||
@ -2301,6 +2301,12 @@ static int mwifiex_process_pcie_int(struct mwifiex_adapter *adapter)
|
||||
}
|
||||
|
||||
}
|
||||
if (!card->msi_enable) {
|
||||
spin_lock_irqsave(&adapter->int_lock, flags);
|
||||
pcie_ireg |= adapter->int_status;
|
||||
adapter->int_status = 0;
|
||||
spin_unlock_irqrestore(&adapter->int_lock, flags);
|
||||
}
|
||||
}
|
||||
mwifiex_dbg(adapter, INTR,
|
||||
"info: cmd_sent=%d data_sent=%d\n",
|
||||
@ -2843,7 +2849,6 @@ static int mwifiex_pcie_request_irq(struct mwifiex_adapter *adapter)
|
||||
"MRVL_PCIE", &card->share_irq_ctx);
|
||||
if (ret) {
|
||||
pr_err("request_irq failed: ret=%d\n", ret);
|
||||
adapter->card = NULL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
@ -1148,9 +1148,8 @@ static int mwifiex_cmd_reg_access(struct host_cmd_ds_command *cmd,
|
||||
cmd->size = cpu_to_le16(sizeof(*mac_reg) + S_DS_GEN);
|
||||
mac_reg = &cmd->params.mac_reg;
|
||||
mac_reg->action = cpu_to_le16(cmd_action);
|
||||
mac_reg->offset =
|
||||
cpu_to_le16((u16) le32_to_cpu(reg_rw->offset));
|
||||
mac_reg->value = reg_rw->value;
|
||||
mac_reg->offset = cpu_to_le16((u16) reg_rw->offset);
|
||||
mac_reg->value = cpu_to_le32(reg_rw->value);
|
||||
break;
|
||||
}
|
||||
case HostCmd_CMD_BBP_REG_ACCESS:
|
||||
@ -1160,9 +1159,8 @@ static int mwifiex_cmd_reg_access(struct host_cmd_ds_command *cmd,
|
||||
cmd->size = cpu_to_le16(sizeof(*bbp_reg) + S_DS_GEN);
|
||||
bbp_reg = &cmd->params.bbp_reg;
|
||||
bbp_reg->action = cpu_to_le16(cmd_action);
|
||||
bbp_reg->offset =
|
||||
cpu_to_le16((u16) le32_to_cpu(reg_rw->offset));
|
||||
bbp_reg->value = (u8) le32_to_cpu(reg_rw->value);
|
||||
bbp_reg->offset = cpu_to_le16((u16) reg_rw->offset);
|
||||
bbp_reg->value = (u8) reg_rw->value;
|
||||
break;
|
||||
}
|
||||
case HostCmd_CMD_RF_REG_ACCESS:
|
||||
@ -1172,8 +1170,8 @@ static int mwifiex_cmd_reg_access(struct host_cmd_ds_command *cmd,
|
||||
cmd->size = cpu_to_le16(sizeof(*rf_reg) + S_DS_GEN);
|
||||
rf_reg = &cmd->params.rf_reg;
|
||||
rf_reg->action = cpu_to_le16(cmd_action);
|
||||
rf_reg->offset = cpu_to_le16((u16) le32_to_cpu(reg_rw->offset));
|
||||
rf_reg->value = (u8) le32_to_cpu(reg_rw->value);
|
||||
rf_reg->offset = cpu_to_le16((u16) reg_rw->offset);
|
||||
rf_reg->value = (u8) reg_rw->value;
|
||||
break;
|
||||
}
|
||||
case HostCmd_CMD_PMIC_REG_ACCESS:
|
||||
@ -1183,9 +1181,8 @@ static int mwifiex_cmd_reg_access(struct host_cmd_ds_command *cmd,
|
||||
cmd->size = cpu_to_le16(sizeof(*pmic_reg) + S_DS_GEN);
|
||||
pmic_reg = &cmd->params.pmic_reg;
|
||||
pmic_reg->action = cpu_to_le16(cmd_action);
|
||||
pmic_reg->offset =
|
||||
cpu_to_le16((u16) le32_to_cpu(reg_rw->offset));
|
||||
pmic_reg->value = (u8) le32_to_cpu(reg_rw->value);
|
||||
pmic_reg->offset = cpu_to_le16((u16) reg_rw->offset);
|
||||
pmic_reg->value = (u8) reg_rw->value;
|
||||
break;
|
||||
}
|
||||
case HostCmd_CMD_CAU_REG_ACCESS:
|
||||
@ -1195,9 +1192,8 @@ static int mwifiex_cmd_reg_access(struct host_cmd_ds_command *cmd,
|
||||
cmd->size = cpu_to_le16(sizeof(*cau_reg) + S_DS_GEN);
|
||||
cau_reg = &cmd->params.rf_reg;
|
||||
cau_reg->action = cpu_to_le16(cmd_action);
|
||||
cau_reg->offset =
|
||||
cpu_to_le16((u16) le32_to_cpu(reg_rw->offset));
|
||||
cau_reg->value = (u8) le32_to_cpu(reg_rw->value);
|
||||
cau_reg->offset = cpu_to_le16((u16) reg_rw->offset);
|
||||
cau_reg->value = (u8) reg_rw->value;
|
||||
break;
|
||||
}
|
||||
case HostCmd_CMD_802_11_EEPROM_ACCESS:
|
||||
@ -1208,8 +1204,8 @@ static int mwifiex_cmd_reg_access(struct host_cmd_ds_command *cmd,
|
||||
|
||||
cmd->size = cpu_to_le16(sizeof(*cmd_eeprom) + S_DS_GEN);
|
||||
cmd_eeprom->action = cpu_to_le16(cmd_action);
|
||||
cmd_eeprom->offset = rd_eeprom->offset;
|
||||
cmd_eeprom->byte_count = rd_eeprom->byte_count;
|
||||
cmd_eeprom->offset = cpu_to_le16(rd_eeprom->offset);
|
||||
cmd_eeprom->byte_count = cpu_to_le16(rd_eeprom->byte_count);
|
||||
cmd_eeprom->value = 0;
|
||||
break;
|
||||
}
|
||||
|
@ -786,45 +786,44 @@ static int mwifiex_ret_reg_access(u16 type, struct host_cmd_ds_command *resp,
|
||||
switch (type) {
|
||||
case HostCmd_CMD_MAC_REG_ACCESS:
|
||||
r.mac = &resp->params.mac_reg;
|
||||
reg_rw->offset = cpu_to_le32((u32) le16_to_cpu(r.mac->offset));
|
||||
reg_rw->value = r.mac->value;
|
||||
reg_rw->offset = (u32) le16_to_cpu(r.mac->offset);
|
||||
reg_rw->value = le32_to_cpu(r.mac->value);
|
||||
break;
|
||||
case HostCmd_CMD_BBP_REG_ACCESS:
|
||||
r.bbp = &resp->params.bbp_reg;
|
||||
reg_rw->offset = cpu_to_le32((u32) le16_to_cpu(r.bbp->offset));
|
||||
reg_rw->value = cpu_to_le32((u32) r.bbp->value);
|
||||
reg_rw->offset = (u32) le16_to_cpu(r.bbp->offset);
|
||||
reg_rw->value = (u32) r.bbp->value;
|
||||
break;
|
||||
|
||||
case HostCmd_CMD_RF_REG_ACCESS:
|
||||
r.rf = &resp->params.rf_reg;
|
||||
reg_rw->offset = cpu_to_le32((u32) le16_to_cpu(r.rf->offset));
|
||||
reg_rw->value = cpu_to_le32((u32) r.bbp->value);
|
||||
reg_rw->offset = (u32) le16_to_cpu(r.rf->offset);
|
||||
reg_rw->value = (u32) r.bbp->value;
|
||||
break;
|
||||
case HostCmd_CMD_PMIC_REG_ACCESS:
|
||||
r.pmic = &resp->params.pmic_reg;
|
||||
reg_rw->offset = cpu_to_le32((u32) le16_to_cpu(r.pmic->offset));
|
||||
reg_rw->value = cpu_to_le32((u32) r.pmic->value);
|
||||
reg_rw->offset = (u32) le16_to_cpu(r.pmic->offset);
|
||||
reg_rw->value = (u32) r.pmic->value;
|
||||
break;
|
||||
case HostCmd_CMD_CAU_REG_ACCESS:
|
||||
r.rf = &resp->params.rf_reg;
|
||||
reg_rw->offset = cpu_to_le32((u32) le16_to_cpu(r.rf->offset));
|
||||
reg_rw->value = cpu_to_le32((u32) r.rf->value);
|
||||
reg_rw->offset = (u32) le16_to_cpu(r.rf->offset);
|
||||
reg_rw->value = (u32) r.rf->value;
|
||||
break;
|
||||
case HostCmd_CMD_802_11_EEPROM_ACCESS:
|
||||
r.eeprom = &resp->params.eeprom;
|
||||
pr_debug("info: EEPROM read len=%x\n", r.eeprom->byte_count);
|
||||
if (le16_to_cpu(eeprom->byte_count) <
|
||||
le16_to_cpu(r.eeprom->byte_count)) {
|
||||
eeprom->byte_count = cpu_to_le16(0);
|
||||
pr_debug("info: EEPROM read len=%x\n",
|
||||
le16_to_cpu(r.eeprom->byte_count));
|
||||
if (eeprom->byte_count < le16_to_cpu(r.eeprom->byte_count)) {
|
||||
eeprom->byte_count = 0;
|
||||
pr_debug("info: EEPROM read length is too big\n");
|
||||
return -1;
|
||||
}
|
||||
eeprom->offset = r.eeprom->offset;
|
||||
eeprom->byte_count = r.eeprom->byte_count;
|
||||
if (le16_to_cpu(eeprom->byte_count) > 0)
|
||||
eeprom->offset = le16_to_cpu(r.eeprom->offset);
|
||||
eeprom->byte_count = le16_to_cpu(r.eeprom->byte_count);
|
||||
if (eeprom->byte_count > 0)
|
||||
memcpy(&eeprom->value, &r.eeprom->value,
|
||||
le16_to_cpu(r.eeprom->byte_count));
|
||||
|
||||
min((u16)MAX_EEPROM_DATA, eeprom->byte_count));
|
||||
break;
|
||||
default:
|
||||
return -1;
|
||||
|
@ -1251,7 +1251,7 @@ static int mwifiex_reg_mem_ioctl_reg_rw(struct mwifiex_private *priv,
|
||||
{
|
||||
u16 cmd_no;
|
||||
|
||||
switch (le32_to_cpu(reg_rw->type)) {
|
||||
switch (reg_rw->type) {
|
||||
case MWIFIEX_REG_MAC:
|
||||
cmd_no = HostCmd_CMD_MAC_REG_ACCESS;
|
||||
break;
|
||||
@ -1286,9 +1286,9 @@ mwifiex_reg_write(struct mwifiex_private *priv, u32 reg_type,
|
||||
{
|
||||
struct mwifiex_ds_reg_rw reg_rw;
|
||||
|
||||
reg_rw.type = cpu_to_le32(reg_type);
|
||||
reg_rw.offset = cpu_to_le32(reg_offset);
|
||||
reg_rw.value = cpu_to_le32(reg_value);
|
||||
reg_rw.type = reg_type;
|
||||
reg_rw.offset = reg_offset;
|
||||
reg_rw.value = reg_value;
|
||||
|
||||
return mwifiex_reg_mem_ioctl_reg_rw(priv, ®_rw, HostCmd_ACT_GEN_SET);
|
||||
}
|
||||
@ -1306,14 +1306,14 @@ mwifiex_reg_read(struct mwifiex_private *priv, u32 reg_type,
|
||||
int ret;
|
||||
struct mwifiex_ds_reg_rw reg_rw;
|
||||
|
||||
reg_rw.type = cpu_to_le32(reg_type);
|
||||
reg_rw.offset = cpu_to_le32(reg_offset);
|
||||
reg_rw.type = reg_type;
|
||||
reg_rw.offset = reg_offset;
|
||||
ret = mwifiex_reg_mem_ioctl_reg_rw(priv, ®_rw, HostCmd_ACT_GEN_GET);
|
||||
|
||||
if (ret)
|
||||
goto done;
|
||||
|
||||
*value = le32_to_cpu(reg_rw.value);
|
||||
*value = reg_rw.value;
|
||||
|
||||
done:
|
||||
return ret;
|
||||
@ -1332,15 +1332,16 @@ mwifiex_eeprom_read(struct mwifiex_private *priv, u16 offset, u16 bytes,
|
||||
int ret;
|
||||
struct mwifiex_ds_read_eeprom rd_eeprom;
|
||||
|
||||
rd_eeprom.offset = cpu_to_le16((u16) offset);
|
||||
rd_eeprom.byte_count = cpu_to_le16((u16) bytes);
|
||||
rd_eeprom.offset = offset;
|
||||
rd_eeprom.byte_count = bytes;
|
||||
|
||||
/* Send request to firmware */
|
||||
ret = mwifiex_send_cmd(priv, HostCmd_CMD_802_11_EEPROM_ACCESS,
|
||||
HostCmd_ACT_GEN_GET, 0, &rd_eeprom, true);
|
||||
|
||||
if (!ret)
|
||||
memcpy(value, rd_eeprom.value, MAX_EEPROM_DATA);
|
||||
memcpy(value, rd_eeprom.value, min((u16)MAX_EEPROM_DATA,
|
||||
rd_eeprom.byte_count));
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -12,4 +12,4 @@ rtl8188ee-objs := \
|
||||
|
||||
obj-$(CONFIG_RTL8188EE) += rtl8188ee.o
|
||||
|
||||
ccflags-y += -Idrivers/net/wireless/rtlwifi -D__CHECK_ENDIAN__
|
||||
ccflags-y += -D__CHECK_ENDIAN__
|
||||
|
@ -1214,6 +1214,10 @@ static void wl18xx_convert_fw_status(struct wl1271 *wl, void *raw_fw_status,
|
||||
int_fw_status->counters.tx_voice_released_blks;
|
||||
fw_status->counters.tx_last_rate =
|
||||
int_fw_status->counters.tx_last_rate;
|
||||
fw_status->counters.tx_last_rate_mbps =
|
||||
int_fw_status->counters.tx_last_rate_mbps;
|
||||
fw_status->counters.hlid =
|
||||
int_fw_status->counters.hlid;
|
||||
|
||||
fw_status->log_start_addr = le32_to_cpu(int_fw_status->log_start_addr);
|
||||
|
||||
@ -1821,9 +1825,12 @@ static const struct ieee80211_iface_limit wl18xx_iface_limits[] = {
|
||||
},
|
||||
{
|
||||
.max = 1,
|
||||
.types = BIT(NL80211_IFTYPE_AP) |
|
||||
BIT(NL80211_IFTYPE_P2P_GO) |
|
||||
BIT(NL80211_IFTYPE_P2P_CLIENT),
|
||||
.types = BIT(NL80211_IFTYPE_AP)
|
||||
| BIT(NL80211_IFTYPE_P2P_GO)
|
||||
| BIT(NL80211_IFTYPE_P2P_CLIENT)
|
||||
#ifdef CONFIG_MAC80211_MESH
|
||||
| BIT(NL80211_IFTYPE_MESH_POINT)
|
||||
#endif
|
||||
},
|
||||
{
|
||||
.max = 1,
|
||||
@ -1836,6 +1843,12 @@ static const struct ieee80211_iface_limit wl18xx_iface_ap_limits[] = {
|
||||
.max = 2,
|
||||
.types = BIT(NL80211_IFTYPE_AP),
|
||||
},
|
||||
#ifdef CONFIG_MAC80211_MESH
|
||||
{
|
||||
.max = 1,
|
||||
.types = BIT(NL80211_IFTYPE_MESH_POINT),
|
||||
},
|
||||
#endif
|
||||
{
|
||||
.max = 1,
|
||||
.types = BIT(NL80211_IFTYPE_P2P_DEVICE),
|
||||
|
@ -30,9 +30,9 @@
|
||||
|
||||
static
|
||||
void wl18xx_get_last_tx_rate(struct wl1271 *wl, struct ieee80211_vif *vif,
|
||||
u8 band, struct ieee80211_tx_rate *rate)
|
||||
u8 band, struct ieee80211_tx_rate *rate, u8 hlid)
|
||||
{
|
||||
u8 fw_rate = wl->fw_status->counters.tx_last_rate;
|
||||
u8 fw_rate = wl->links[hlid].fw_rate_idx;
|
||||
|
||||
if (fw_rate > CONF_HW_RATE_INDEX_MAX) {
|
||||
wl1271_error("last Tx rate invalid: %d", fw_rate);
|
||||
@ -79,6 +79,7 @@ static void wl18xx_tx_complete_packet(struct wl1271 *wl, u8 tx_stat_byte)
|
||||
struct sk_buff *skb;
|
||||
int id = tx_stat_byte & WL18XX_TX_STATUS_DESC_ID_MASK;
|
||||
bool tx_success;
|
||||
struct wl1271_tx_hw_descr *tx_desc;
|
||||
|
||||
/* check for id legality */
|
||||
if (unlikely(id >= wl->num_tx_desc || wl->tx_frames[id] == NULL)) {
|
||||
@ -91,6 +92,7 @@ static void wl18xx_tx_complete_packet(struct wl1271 *wl, u8 tx_stat_byte)
|
||||
|
||||
skb = wl->tx_frames[id];
|
||||
info = IEEE80211_SKB_CB(skb);
|
||||
tx_desc = (struct wl1271_tx_hw_descr *)skb->data;
|
||||
|
||||
if (wl12xx_is_dummy_packet(wl, skb)) {
|
||||
wl1271_free_tx_id(wl, id);
|
||||
@ -105,7 +107,9 @@ static void wl18xx_tx_complete_packet(struct wl1271 *wl, u8 tx_stat_byte)
|
||||
* the info->status structures
|
||||
*/
|
||||
wl18xx_get_last_tx_rate(wl, info->control.vif,
|
||||
info->band, &info->status.rates[0]);
|
||||
info->band,
|
||||
&info->status.rates[0],
|
||||
tx_desc->hlid);
|
||||
|
||||
info->status.rates[0].count = 1; /* no data about retries */
|
||||
info->status.ack_signal = -1;
|
||||
@ -144,12 +148,22 @@ void wl18xx_tx_immediate_complete(struct wl1271 *wl)
|
||||
struct wl18xx_fw_status_priv *status_priv =
|
||||
(struct wl18xx_fw_status_priv *)wl->fw_status->priv;
|
||||
struct wl18xx_priv *priv = wl->priv;
|
||||
u8 i;
|
||||
u8 i, hlid;
|
||||
|
||||
/* nothing to do here */
|
||||
if (priv->last_fw_rls_idx == status_priv->fw_release_idx)
|
||||
return;
|
||||
|
||||
/* update rates per link */
|
||||
hlid = wl->fw_status->counters.hlid;
|
||||
|
||||
if (hlid < WLCORE_MAX_LINKS) {
|
||||
wl->links[hlid].fw_rate_idx =
|
||||
wl->fw_status->counters.tx_last_rate;
|
||||
wl->links[hlid].fw_rate_mbps =
|
||||
wl->fw_status->counters.tx_last_rate_mbps;
|
||||
}
|
||||
|
||||
/* freed Tx descriptors */
|
||||
wl1271_debug(DEBUG_TX, "last released desc = %d, current idx = %d",
|
||||
priv->last_fw_rls_idx, status_priv->fw_release_idx);
|
||||
|
@ -29,7 +29,7 @@
|
||||
#define WL18XX_IFTYPE_VER 9
|
||||
#define WL18XX_MAJOR_VER WLCORE_FW_VER_IGNORE
|
||||
#define WL18XX_SUBTYPE_VER WLCORE_FW_VER_IGNORE
|
||||
#define WL18XX_MINOR_VER 11
|
||||
#define WL18XX_MINOR_VER 58
|
||||
|
||||
#define WL18XX_CMD_MAX_SIZE 740
|
||||
|
||||
@ -125,7 +125,11 @@ struct wl18xx_fw_packet_counters {
|
||||
/* Tx rate of the last transmitted packet */
|
||||
u8 tx_last_rate;
|
||||
|
||||
u8 padding[2];
|
||||
/* Tx rate or Tx rate estimate pre-calculated by fw in mbps units */
|
||||
u8 tx_last_rate_mbps;
|
||||
|
||||
/* hlid for which the rates were reported */
|
||||
u8 hlid;
|
||||
} __packed;
|
||||
|
||||
/* FW status registers */
|
||||
|
@ -105,6 +105,7 @@ enum wl12xx_role {
|
||||
WL1271_ROLE_DEVICE,
|
||||
WL1271_ROLE_P2P_CL,
|
||||
WL1271_ROLE_P2P_GO,
|
||||
WL1271_ROLE_MESH_POINT,
|
||||
|
||||
WL12XX_INVALID_ROLE_TYPE = 0xff
|
||||
};
|
||||
|
@ -130,7 +130,7 @@ fail:
|
||||
wl1271_error("Your WiFi FW version (%u.%u.%u.%u.%u) is invalid.\n"
|
||||
"Please use at least FW %s\n"
|
||||
"You can get the latest firmwares at:\n"
|
||||
"git://github.com/TI-OpenLink/firmwares.git",
|
||||
"git://git.ti.com/wilink8-wlan/wl18xx_fw.git",
|
||||
fw_ver[FW_VER_CHIP], fw_ver[FW_VER_IF_TYPE],
|
||||
fw_ver[FW_VER_MAJOR], fw_ver[FW_VER_SUBTYPE],
|
||||
fw_ver[FW_VER_MINOR], min_fw_str);
|
||||
|
@ -629,11 +629,14 @@ int wl12xx_cmd_role_start_ap(struct wl1271 *wl, struct wl12xx_vif *wlvif)
|
||||
|
||||
wl1271_debug(DEBUG_CMD, "cmd role start ap %d", wlvif->role_id);
|
||||
|
||||
/* trying to use hidden SSID with an old hostapd version */
|
||||
if (wlvif->ssid_len == 0 && !bss_conf->hidden_ssid) {
|
||||
wl1271_error("got a null SSID from beacon/bss");
|
||||
ret = -EINVAL;
|
||||
goto out;
|
||||
/* If MESH --> ssid_len is always 0 */
|
||||
if (!ieee80211_vif_is_mesh(vif)) {
|
||||
/* trying to use hidden SSID with an old hostapd version */
|
||||
if (wlvif->ssid_len == 0 && !bss_conf->hidden_ssid) {
|
||||
wl1271_error("got a null SSID from beacon/bss");
|
||||
ret = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
|
||||
|
@ -221,6 +221,7 @@ static void wlcore_rc_update_work(struct work_struct *work)
|
||||
struct wl12xx_vif *wlvif = container_of(work, struct wl12xx_vif,
|
||||
rc_update_work);
|
||||
struct wl1271 *wl = wlvif->wl;
|
||||
struct ieee80211_vif *vif = wl12xx_wlvif_to_vif(wlvif);
|
||||
|
||||
mutex_lock(&wl->mutex);
|
||||
|
||||
@ -231,8 +232,16 @@ static void wlcore_rc_update_work(struct work_struct *work)
|
||||
if (ret < 0)
|
||||
goto out;
|
||||
|
||||
wlcore_hw_sta_rc_update(wl, wlvif);
|
||||
if (ieee80211_vif_is_mesh(vif)) {
|
||||
ret = wl1271_acx_set_ht_capabilities(wl, &wlvif->rc_ht_cap,
|
||||
true, wlvif->sta.hlid);
|
||||
if (ret < 0)
|
||||
goto out_sleep;
|
||||
} else {
|
||||
wlcore_hw_sta_rc_update(wl, wlvif);
|
||||
}
|
||||
|
||||
out_sleep:
|
||||
wl1271_ps_elp_sleep(wl);
|
||||
out:
|
||||
mutex_unlock(&wl->mutex);
|
||||
@ -2153,10 +2162,14 @@ static void wlcore_free_klv_template(struct wl1271 *wl, u8 *idx)
|
||||
|
||||
static u8 wl12xx_get_role_type(struct wl1271 *wl, struct wl12xx_vif *wlvif)
|
||||
{
|
||||
struct ieee80211_vif *vif = wl12xx_wlvif_to_vif(wlvif);
|
||||
|
||||
switch (wlvif->bss_type) {
|
||||
case BSS_TYPE_AP_BSS:
|
||||
if (wlvif->p2p)
|
||||
return WL1271_ROLE_P2P_GO;
|
||||
else if (ieee80211_vif_is_mesh(vif))
|
||||
return WL1271_ROLE_MESH_POINT;
|
||||
else
|
||||
return WL1271_ROLE_AP;
|
||||
|
||||
@ -2198,6 +2211,7 @@ static int wl12xx_init_vif_data(struct wl1271 *wl, struct ieee80211_vif *vif)
|
||||
wlvif->p2p = 1;
|
||||
/* fall-through */
|
||||
case NL80211_IFTYPE_AP:
|
||||
case NL80211_IFTYPE_MESH_POINT:
|
||||
wlvif->bss_type = BSS_TYPE_AP_BSS;
|
||||
break;
|
||||
default:
|
||||
@ -4131,9 +4145,14 @@ static void wl1271_bss_info_changed_ap(struct wl1271 *wl,
|
||||
if (ret < 0)
|
||||
goto out;
|
||||
|
||||
ret = wl1271_ap_set_probe_resp_tmpl(wl, wlvif->basic_rate, vif);
|
||||
if (ret < 0)
|
||||
goto out;
|
||||
/* No need to set probe resp template for mesh */
|
||||
if (!ieee80211_vif_is_mesh(vif)) {
|
||||
ret = wl1271_ap_set_probe_resp_tmpl(wl,
|
||||
wlvif->basic_rate,
|
||||
vif);
|
||||
if (ret < 0)
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = wlcore_set_beacon_template(wl, vif, true);
|
||||
if (ret < 0)
|
||||
@ -4967,6 +4986,7 @@ static int wl12xx_sta_add(struct wl1271 *wl,
|
||||
return ret;
|
||||
|
||||
wl_sta = (struct wl1271_station *)sta->drv_priv;
|
||||
wl_sta->wl = wl;
|
||||
hlid = wl_sta->hlid;
|
||||
|
||||
ret = wl12xx_cmd_add_peer(wl, wlvif, sta, hlid);
|
||||
@ -5641,6 +5661,7 @@ static void wlcore_op_sta_rc_update(struct ieee80211_hw *hw,
|
||||
|
||||
/* this callback is atomic, so schedule a new work */
|
||||
wlvif->rc_update_bw = sta->bandwidth;
|
||||
memcpy(&wlvif->rc_ht_cap, &sta->ht_cap, sizeof(sta->ht_cap));
|
||||
ieee80211_queue_work(hw, &wlvif->rc_update_work);
|
||||
}
|
||||
|
||||
@ -5679,6 +5700,16 @@ out:
|
||||
mutex_unlock(&wl->mutex);
|
||||
}
|
||||
|
||||
static u32 wlcore_op_get_expected_throughput(struct ieee80211_sta *sta)
|
||||
{
|
||||
struct wl1271_station *wl_sta = (struct wl1271_station *)sta->drv_priv;
|
||||
struct wl1271 *wl = wl_sta->wl;
|
||||
u8 hlid = wl_sta->hlid;
|
||||
|
||||
/* return in units of Kbps */
|
||||
return (wl->links[hlid].fw_rate_mbps * 1000);
|
||||
}
|
||||
|
||||
static bool wl1271_tx_frames_pending(struct ieee80211_hw *hw)
|
||||
{
|
||||
struct wl1271 *wl = hw->priv;
|
||||
@ -5879,6 +5910,7 @@ static const struct ieee80211_ops wl1271_ops = {
|
||||
.switch_vif_chanctx = wlcore_op_switch_vif_chanctx,
|
||||
.sta_rc_update = wlcore_op_sta_rc_update,
|
||||
.sta_statistics = wlcore_op_sta_statistics,
|
||||
.get_expected_throughput = wlcore_op_get_expected_throughput,
|
||||
CFG80211_TESTMODE_CMD(wl1271_tm_cmd)
|
||||
};
|
||||
|
||||
@ -6062,7 +6094,11 @@ static int wl1271_init_ieee80211(struct wl1271 *wl)
|
||||
BIT(NL80211_IFTYPE_AP) |
|
||||
BIT(NL80211_IFTYPE_P2P_DEVICE) |
|
||||
BIT(NL80211_IFTYPE_P2P_CLIENT) |
|
||||
#ifdef CONFIG_MAC80211_MESH
|
||||
BIT(NL80211_IFTYPE_MESH_POINT) |
|
||||
#endif
|
||||
BIT(NL80211_IFTYPE_P2P_GO);
|
||||
|
||||
wl->hw->wiphy->max_scan_ssids = 1;
|
||||
wl->hw->wiphy->max_sched_scan_ssids = 16;
|
||||
wl->hw->wiphy->max_match_sets = 16;
|
||||
|
@ -222,6 +222,13 @@ int wlcore_rx(struct wl1271 *wl, struct wl_fw_status *status)
|
||||
enum wl_rx_buf_align rx_align;
|
||||
int ret = 0;
|
||||
|
||||
/* update rates per link */
|
||||
hlid = status->counters.hlid;
|
||||
|
||||
if (hlid < WLCORE_MAX_LINKS)
|
||||
wl->links[hlid].fw_rate_mbps =
|
||||
status->counters.tx_last_rate_mbps;
|
||||
|
||||
while (drv_rx_counter != fw_rx_counter) {
|
||||
buf_size = 0;
|
||||
rx_counter = drv_rx_counter;
|
||||
|
@ -70,16 +70,30 @@
|
||||
#define WSPI_MAX_CHUNK_SIZE 4092
|
||||
|
||||
/*
|
||||
* only support SPI for 12xx - this code should be reworked when 18xx
|
||||
* support is introduced
|
||||
* wl18xx driver aggregation buffer size is (13 * PAGE_SIZE) compared to
|
||||
* (4 * PAGE_SIZE) for wl12xx, so use the larger buffer needed for wl18xx
|
||||
*/
|
||||
#define SPI_AGGR_BUFFER_SIZE (4 * PAGE_SIZE)
|
||||
#define SPI_AGGR_BUFFER_SIZE (13 * PAGE_SIZE)
|
||||
|
||||
/* Maximum number of SPI write chunks */
|
||||
#define WSPI_MAX_NUM_OF_CHUNKS \
|
||||
((SPI_AGGR_BUFFER_SIZE / WSPI_MAX_CHUNK_SIZE) + 1)
|
||||
|
||||
|
||||
struct wilink_familiy_data {
|
||||
char name[8];
|
||||
};
|
||||
|
||||
const struct wilink_familiy_data *wilink_data;
|
||||
|
||||
static const struct wilink_familiy_data wl18xx_data = {
|
||||
.name = "wl18xx",
|
||||
};
|
||||
|
||||
static const struct wilink_familiy_data wl12xx_data = {
|
||||
.name = "wl12xx",
|
||||
};
|
||||
|
||||
struct wl12xx_spi_glue {
|
||||
struct device *dev;
|
||||
struct platform_device *core;
|
||||
@ -119,6 +133,7 @@ static void wl12xx_spi_init(struct device *child)
|
||||
struct wl12xx_spi_glue *glue = dev_get_drvdata(child->parent);
|
||||
struct spi_transfer t;
|
||||
struct spi_message m;
|
||||
struct spi_device *spi = to_spi_device(glue->dev);
|
||||
u8 *cmd = kzalloc(WSPI_INIT_CMD_LEN, GFP_KERNEL);
|
||||
|
||||
if (!cmd) {
|
||||
@ -151,6 +166,7 @@ static void wl12xx_spi_init(struct device *child)
|
||||
cmd[6] |= WSPI_INIT_CMD_EN_FIXEDBUSY;
|
||||
|
||||
cmd[7] = crc7_be(0, cmd+2, WSPI_INIT_CMD_CRC_LEN) | WSPI_INIT_CMD_END;
|
||||
|
||||
/*
|
||||
* The above is the logical order; it must actually be stored
|
||||
* in the buffer byte-swapped.
|
||||
@ -163,6 +179,28 @@ static void wl12xx_spi_init(struct device *child)
|
||||
spi_message_add_tail(&t, &m);
|
||||
|
||||
spi_sync(to_spi_device(glue->dev), &m);
|
||||
|
||||
/* Send extra clocks with inverted CS (high). this is required
|
||||
* by the wilink family in order to successfully enter WSPI mode.
|
||||
*/
|
||||
spi->mode ^= SPI_CS_HIGH;
|
||||
memset(&m, 0, sizeof(m));
|
||||
spi_message_init(&m);
|
||||
|
||||
cmd[0] = 0xff;
|
||||
cmd[1] = 0xff;
|
||||
cmd[2] = 0xff;
|
||||
cmd[3] = 0xff;
|
||||
__swab32s((u32 *)cmd);
|
||||
|
||||
t.tx_buf = cmd;
|
||||
t.len = 4;
|
||||
spi_message_add_tail(&t, &m);
|
||||
|
||||
spi_sync(to_spi_device(glue->dev), &m);
|
||||
|
||||
/* Restore chip select configration to normal */
|
||||
spi->mode ^= SPI_CS_HIGH;
|
||||
kfree(cmd);
|
||||
}
|
||||
|
||||
@ -270,22 +308,25 @@ static int __must_check wl12xx_spi_raw_read(struct device *child, int addr,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __must_check wl12xx_spi_raw_write(struct device *child, int addr,
|
||||
void *buf, size_t len, bool fixed)
|
||||
static int __wl12xx_spi_raw_write(struct device *child, int addr,
|
||||
void *buf, size_t len, bool fixed)
|
||||
{
|
||||
struct wl12xx_spi_glue *glue = dev_get_drvdata(child->parent);
|
||||
/* SPI write buffers - 2 for each chunk */
|
||||
struct spi_transfer t[2 * WSPI_MAX_NUM_OF_CHUNKS];
|
||||
struct spi_transfer *t;
|
||||
struct spi_message m;
|
||||
u32 commands[WSPI_MAX_NUM_OF_CHUNKS]; /* 1 command per chunk */
|
||||
u32 *cmd;
|
||||
u32 chunk_len;
|
||||
int i;
|
||||
|
||||
/* SPI write buffers - 2 for each chunk */
|
||||
t = kzalloc(sizeof(*t) * 2 * WSPI_MAX_NUM_OF_CHUNKS, GFP_KERNEL);
|
||||
if (!t)
|
||||
return -ENOMEM;
|
||||
|
||||
WARN_ON(len > SPI_AGGR_BUFFER_SIZE);
|
||||
|
||||
spi_message_init(&m);
|
||||
memset(t, 0, sizeof(t));
|
||||
|
||||
cmd = &commands[0];
|
||||
i = 0;
|
||||
@ -318,9 +359,26 @@ static int __must_check wl12xx_spi_raw_write(struct device *child, int addr,
|
||||
|
||||
spi_sync(to_spi_device(glue->dev), &m);
|
||||
|
||||
kfree(t);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __must_check wl12xx_spi_raw_write(struct device *child, int addr,
|
||||
void *buf, size_t len, bool fixed)
|
||||
{
|
||||
int ret;
|
||||
|
||||
/* The ELP wakeup write may fail the first time due to internal
|
||||
* hardware latency. It is safer to send the wakeup command twice to
|
||||
* avoid unexpected failures.
|
||||
*/
|
||||
if (addr == HW_ACCESS_ELP_CTRL_REG)
|
||||
ret = __wl12xx_spi_raw_write(child, addr, buf, len, fixed);
|
||||
ret = __wl12xx_spi_raw_write(child, addr, buf, len, fixed);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* wl12xx_spi_set_power - power on/off the wl12xx unit
|
||||
* @child: wl12xx device handle.
|
||||
@ -349,17 +407,38 @@ static int wl12xx_spi_set_power(struct device *child, bool enable)
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* wl12xx_spi_set_block_size
|
||||
*
|
||||
* This function is not needed for spi mode, but need to be present.
|
||||
* Without it defined the wlcore fallback to use the wrong packet
|
||||
* allignment on tx.
|
||||
*/
|
||||
static void wl12xx_spi_set_block_size(struct device *child,
|
||||
unsigned int blksz)
|
||||
{
|
||||
}
|
||||
|
||||
static struct wl1271_if_operations spi_ops = {
|
||||
.read = wl12xx_spi_raw_read,
|
||||
.write = wl12xx_spi_raw_write,
|
||||
.reset = wl12xx_spi_reset,
|
||||
.init = wl12xx_spi_init,
|
||||
.power = wl12xx_spi_set_power,
|
||||
.set_block_size = NULL,
|
||||
.set_block_size = wl12xx_spi_set_block_size,
|
||||
};
|
||||
|
||||
static const struct of_device_id wlcore_spi_of_match_table[] = {
|
||||
{ .compatible = "ti,wl1271" },
|
||||
{ .compatible = "ti,wl1271", .data = &wl12xx_data},
|
||||
{ .compatible = "ti,wl1273", .data = &wl12xx_data},
|
||||
{ .compatible = "ti,wl1281", .data = &wl12xx_data},
|
||||
{ .compatible = "ti,wl1283", .data = &wl12xx_data},
|
||||
{ .compatible = "ti,wl1801", .data = &wl18xx_data},
|
||||
{ .compatible = "ti,wl1805", .data = &wl18xx_data},
|
||||
{ .compatible = "ti,wl1807", .data = &wl18xx_data},
|
||||
{ .compatible = "ti,wl1831", .data = &wl18xx_data},
|
||||
{ .compatible = "ti,wl1835", .data = &wl18xx_data},
|
||||
{ .compatible = "ti,wl1837", .data = &wl18xx_data},
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, wlcore_spi_of_match_table);
|
||||
@ -375,18 +454,24 @@ static int wlcore_probe_of(struct spi_device *spi, struct wl12xx_spi_glue *glue,
|
||||
struct wlcore_platdev_data *pdev_data)
|
||||
{
|
||||
struct device_node *dt_node = spi->dev.of_node;
|
||||
int ret;
|
||||
const struct of_device_id *of_id;
|
||||
|
||||
of_id = of_match_node(wlcore_spi_of_match_table, dt_node);
|
||||
if (!of_id)
|
||||
return -ENODEV;
|
||||
|
||||
wilink_data = of_id->data;
|
||||
dev_info(&spi->dev, "selected chip familiy is %s\n",
|
||||
wilink_data->name);
|
||||
|
||||
if (of_find_property(dt_node, "clock-xtal", NULL))
|
||||
pdev_data->ref_clock_xtal = true;
|
||||
|
||||
ret = of_property_read_u32(dt_node, "ref-clock-frequency",
|
||||
&pdev_data->ref_clock_freq);
|
||||
if (ret) {
|
||||
dev_err(glue->dev,
|
||||
"can't get reference clock frequency (%d)\n", ret);
|
||||
return ret;
|
||||
}
|
||||
/* optional clock frequency params */
|
||||
of_property_read_u32(dt_node, "ref-clock-frequency",
|
||||
&pdev_data->ref_clock_freq);
|
||||
of_property_read_u32(dt_node, "tcxo-clock-frequency",
|
||||
&pdev_data->tcxo_clock_freq);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -437,7 +522,8 @@ static int wl1271_probe(struct spi_device *spi)
|
||||
return ret;
|
||||
}
|
||||
|
||||
glue->core = platform_device_alloc("wl12xx", PLATFORM_DEVID_AUTO);
|
||||
glue->core = platform_device_alloc(wilink_data->name,
|
||||
PLATFORM_DEVID_AUTO);
|
||||
if (!glue->core) {
|
||||
dev_err(glue->dev, "can't allocate platform_device\n");
|
||||
return -ENOMEM;
|
||||
|
@ -171,6 +171,12 @@ struct wl_fw_status {
|
||||
|
||||
/* Tx rate of the last transmitted packet */
|
||||
u8 tx_last_rate;
|
||||
|
||||
/* Tx rate or Tx rate estimate pre calculated by fw in mbps */
|
||||
u8 tx_last_rate_mbps;
|
||||
|
||||
/* hlid for which the rates were reported */
|
||||
u8 hlid;
|
||||
} counters;
|
||||
|
||||
u32 log_start_addr;
|
||||
@ -273,6 +279,12 @@ struct wl1271_link {
|
||||
/* bitmap of TIDs where RX BA sessions are active for this link */
|
||||
u8 ba_bitmap;
|
||||
|
||||
/* the last fw rate index we used for this link */
|
||||
u8 fw_rate_idx;
|
||||
|
||||
/* the last fw rate [Mbps] we used for this link */
|
||||
u8 fw_rate_mbps;
|
||||
|
||||
/* The wlvif this link belongs to. Might be null for global links */
|
||||
struct wl12xx_vif *wlvif;
|
||||
|
||||
@ -335,6 +347,7 @@ struct wl1271_station {
|
||||
* Used in both AP and STA mode.
|
||||
*/
|
||||
u64 total_freed_pkts;
|
||||
struct wl1271 *wl;
|
||||
};
|
||||
|
||||
struct wl12xx_vif {
|
||||
@ -472,6 +485,7 @@ struct wl12xx_vif {
|
||||
|
||||
/* update rate conrol */
|
||||
enum ieee80211_sta_rx_bandwidth rc_update_bw;
|
||||
struct ieee80211_sta_ht_cap rc_ht_cap;
|
||||
struct work_struct rc_update_work;
|
||||
|
||||
/*
|
||||
|
@ -40,6 +40,7 @@ struct ath9k_platform_data {
|
||||
bool tx_gain_buffalo;
|
||||
bool disable_2ghz;
|
||||
bool disable_5ghz;
|
||||
bool led_active_high;
|
||||
|
||||
int (*get_mac_revision)(void);
|
||||
int (*external_reset)(void);
|
||||
|
@ -504,6 +504,9 @@
|
||||
#define BCMA_CC_PMU1_PLL0_PC2_NDIV_INT_MASK 0x1ff00000
|
||||
#define BCMA_CC_PMU1_PLL0_PC2_NDIV_INT_SHIFT 20
|
||||
|
||||
#define BCMA_CCB_MII_MNG_CTL 0x0000
|
||||
#define BCMA_CCB_MII_MNG_CMD_DATA 0x0004
|
||||
|
||||
/* BCM4331 ChipControl numbers. */
|
||||
#define BCMA_CHIPCTL_4331_BT_COEXIST BIT(0) /* 0 disable */
|
||||
#define BCMA_CHIPCTL_4331_SECI BIT(1) /* 0 SECI is disabled (JATG functional) */
|
||||
|
Loading…
Reference in New Issue
Block a user