Skip to content

Commit

Permalink
Merge tag 'wireless-drivers-next-for-davem-2016-12-01' of git://git.k…
Browse files Browse the repository at this point in the history
…ernel.org/pub/scm/linux/kernel/git/kvalo/wireless-drivers-next

Kalle Valo says:

====================
wireless-drivers-next patches for 4.10

Major changes:

rsi

* filter rx frames
* configure tx power
* make it possible to select antenna
* support 802.11d

brcmfmac

* cleanup of scheduled scan code
* support for bcm43341 chipset with different chip id
* support rev6 of PCIe device interface

ath10k

* add spectral scan support for QCA6174 and QCA9377 families
* show used tx bitrate with 10.4 firmware

wil6210

* add power save mode support
* add abort scan functionality
* add support settings retry limit for short frames

bcma

* add Dell Inspiron 3148
====================

Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
David S. Miller committed Dec 2, 2016
2 parents 4f4f907 + d5fb3a1 commit ab17cb1
Show file tree
Hide file tree
Showing 65 changed files with 2,560 additions and 788 deletions.
1 change: 1 addition & 0 deletions drivers/bcma/host_pci.c
Original file line number Diff line number Diff line change
Expand Up @@ -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_DELL, 0x0018) },
{ 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) },
Expand Down
8 changes: 5 additions & 3 deletions drivers/net/wireless/ath/ath10k/core.c
Original file line number Diff line number Diff line change
Expand Up @@ -326,6 +326,7 @@ static const char *const ath10k_core_fw_feature_str[] = {
[ATH10K_FW_FEATURE_PEER_FLOW_CONTROL] = "peer-flow-ctrl",
[ATH10K_FW_FEATURE_BTCOEX_PARAM] = "btcoex-param",
[ATH10K_FW_FEATURE_SKIP_NULL_FUNC_WAR] = "skip-null-func-war",
[ATH10K_FW_FEATURE_ALLOWS_MESH_BCAST] = "allows-mesh-bcast",
};

static unsigned int ath10k_core_get_fw_feature_str(char *buf,
Expand Down Expand Up @@ -1536,7 +1537,7 @@ static void ath10k_core_restart(struct work_struct *work)
switch (ar->state) {
case ATH10K_STATE_ON:
ar->state = ATH10K_STATE_RESTARTING;
ath10k_hif_stop(ar);
ath10k_halt(ar);
ath10k_scan_finish(ar);
ieee80211_restart_hw(ar->hw);
break;
Expand Down Expand Up @@ -1857,7 +1858,7 @@ int ath10k_core_start(struct ath10k *ar, enum ath10k_firmware_mode mode,
goto err_wmi_detach;
}

status = ath10k_htt_tx_alloc(&ar->htt);
status = ath10k_htt_tx_start(&ar->htt);
if (status) {
ath10k_err(ar, "failed to alloc htt tx: %d\n", status);
goto err_wmi_detach;
Expand Down Expand Up @@ -2052,7 +2053,7 @@ void ath10k_core_stop(struct ath10k *ar)
ath10k_wait_for_suspend(ar, WMI_PDEV_SUSPEND_AND_DISABLE_INTR);

ath10k_hif_stop(ar);
ath10k_htt_tx_free(&ar->htt);
ath10k_htt_tx_stop(&ar->htt);
ath10k_htt_rx_free(&ar->htt);
ath10k_wmi_detach(ar);
}
Expand Down Expand Up @@ -2385,6 +2386,7 @@ void ath10k_core_destroy(struct ath10k *ar)
destroy_workqueue(ar->workqueue_aux);

ath10k_debug_destroy(ar);
ath10k_htt_tx_destroy(&ar->htt);
ath10k_wmi_free_host_mem(ar);
ath10k_mac_destroy(ar);
}
Expand Down
24 changes: 24 additions & 0 deletions drivers/net/wireless/ath/ath10k/core.h
Original file line number Diff line number Diff line change
Expand Up @@ -337,6 +337,7 @@ struct ath10k_sta {
u32 nss;
u32 smps;
u16 peer_id;
struct rate_info txrate;

struct work_struct update_wk;

Expand Down Expand Up @@ -562,6 +563,13 @@ enum ath10k_fw_features {
*/
ATH10K_FW_FEATURE_SKIP_NULL_FUNC_WAR = 15,

/* Firmware allow other BSS mesh broadcast/multicast frames without
* creating monitor interface. Appropriate rxfilters are programmed for
* mesh vdev by firmware itself. This feature flags will be used for
* not creating monitor vdev while configuring mesh node.
*/
ATH10K_FW_FEATURE_ALLOWS_MESH_BCAST = 16,

/* keep last */
ATH10K_FW_FEATURE_COUNT,
};
Expand Down Expand Up @@ -693,6 +701,21 @@ struct ath10k_fw_components {
struct ath10k_fw_file fw_file;
};

struct ath10k_per_peer_tx_stats {
u32 succ_bytes;
u32 retry_bytes;
u32 failed_bytes;
u8 ratecode;
u8 flags;
u16 peer_id;
u16 succ_pkts;
u16 retry_pkts;
u16 failed_pkts;
u16 duration;
u32 reserved1;
u32 reserved2;
};

struct ath10k {
struct ath_common ath_common;
struct ieee80211_hw *hw;
Expand Down Expand Up @@ -906,6 +929,7 @@ struct ath10k {

struct ath10k_thermal thermal;
struct ath10k_wow wow;
struct ath10k_per_peer_tx_stats peer_tx_stats;

/* NAPI */
struct net_device napi_dev;
Expand Down
13 changes: 13 additions & 0 deletions drivers/net/wireless/ath/ath10k/debugfs_sta.c
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,19 @@ void ath10k_sta_statistics(struct ieee80211_hw *hw, struct ieee80211_vif *vif,

sinfo->rx_duration = arsta->rx_duration;
sinfo->filled |= 1ULL << NL80211_STA_INFO_RX_DURATION;

if (!arsta->txrate.legacy && !arsta->txrate.nss)
return;

if (arsta->txrate.legacy) {
sinfo->txrate.legacy = arsta->txrate.legacy;
} else {
sinfo->txrate.mcs = arsta->txrate.mcs;
sinfo->txrate.nss = arsta->txrate.nss;
sinfo->txrate.bw = arsta->txrate.bw;
}
sinfo->txrate.flags = arsta->txrate.flags;
sinfo->filled |= 1ULL << NL80211_STA_INFO_TX_BITRATE;
}

static ssize_t ath10k_dbg_sta_read_aggr_mode(struct file *file,
Expand Down
2 changes: 2 additions & 0 deletions drivers/net/wireless/ath/ath10k/htt.c
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,8 @@ static const enum htt_t2h_msg_type htt_10_4_t2h_msg_types[] = {
HTT_T2H_MSG_TYPE_STATS_NOUPLOAD,
[HTT_10_4_T2H_MSG_TYPE_TX_MODE_SWITCH_IND] =
HTT_T2H_MSG_TYPE_TX_MODE_SWITCH_IND,
[HTT_10_4_T2H_MSG_TYPE_PEER_STATS] =
HTT_T2H_MSG_TYPE_PEER_STATS,
};

int ath10k_htt_connect(struct ath10k_htt *htt)
Expand Down
31 changes: 30 additions & 1 deletion drivers/net/wireless/ath/ath10k/htt.h
Original file line number Diff line number Diff line change
Expand Up @@ -419,6 +419,7 @@ enum htt_10_4_t2h_msg_type {
HTT_10_4_T2H_MSG_TYPE_STATS_NOUPLOAD = 0x18,
/* 0x19 to 0x2f are reserved */
HTT_10_4_T2H_MSG_TYPE_TX_MODE_SWITCH_IND = 0x30,
HTT_10_4_T2H_MSG_TYPE_PEER_STATS = 0x31,
/* keep this last */
HTT_10_4_T2H_NUM_MSGS
};
Expand Down Expand Up @@ -453,6 +454,7 @@ enum htt_t2h_msg_type {
HTT_T2H_MSG_TYPE_TX_FETCH_IND,
HTT_T2H_MSG_TYPE_TX_FETCH_CONFIRM,
HTT_T2H_MSG_TYPE_TX_MODE_SWITCH_IND,
HTT_T2H_MSG_TYPE_PEER_STATS,
/* keep this last */
HTT_T2H_NUM_MSGS
};
Expand Down Expand Up @@ -1470,6 +1472,28 @@ struct htt_channel_change {
__le32 phymode;
} __packed;

struct htt_per_peer_tx_stats_ind {
__le32 succ_bytes;
__le32 retry_bytes;
__le32 failed_bytes;
u8 ratecode;
u8 flags;
__le16 peer_id;
__le16 succ_pkts;
__le16 retry_pkts;
__le16 failed_pkts;
__le16 tx_duration;
__le32 reserved1;
__le32 reserved2;
} __packed;

struct htt_peer_tx_stats {
u8 num_ppdu;
u8 ppdu_len;
u8 version;
u8 payload[0];
} __packed;

union htt_rx_pn_t {
/* WEP: 24-bit PN */
u32 pn24;
Expand Down Expand Up @@ -1521,6 +1545,7 @@ struct htt_resp {
struct htt_tx_fetch_confirm tx_fetch_confirm;
struct htt_tx_mode_switch_ind tx_mode_switch_ind;
struct htt_channel_change chan_change;
struct htt_peer_tx_stats peer_tx_stats;
};
} __packed;

Expand Down Expand Up @@ -1692,6 +1717,8 @@ struct ath10k_htt {
enum htt_tx_mode_switch_mode mode;
enum htt_q_depth_type type;
} tx_q_state;

bool tx_mem_allocated;
};

#define RX_HTT_HDR_STATUS_LEN 64
Expand Down Expand Up @@ -1754,7 +1781,9 @@ int ath10k_htt_connect(struct ath10k_htt *htt);
int ath10k_htt_init(struct ath10k *ar);
int ath10k_htt_setup(struct ath10k_htt *htt);

int ath10k_htt_tx_alloc(struct ath10k_htt *htt);
int ath10k_htt_tx_start(struct ath10k_htt *htt);
void ath10k_htt_tx_stop(struct ath10k_htt *htt);
void ath10k_htt_tx_destroy(struct ath10k_htt *htt);
void ath10k_htt_tx_free(struct ath10k_htt *htt);

int ath10k_htt_rx_alloc(struct ath10k_htt *htt);
Expand Down
125 changes: 125 additions & 0 deletions drivers/net/wireless/ath/ath10k/htt_rx.c
Original file line number Diff line number Diff line change
Expand Up @@ -2194,6 +2194,128 @@ void ath10k_htt_htc_t2h_msg_handler(struct ath10k *ar, struct sk_buff *skb)
dev_kfree_skb_any(skb);
}

static inline bool is_valid_legacy_rate(u8 rate)
{
static const u8 legacy_rates[] = {1, 2, 5, 11, 6, 9, 12,
18, 24, 36, 48, 54};
int i;

for (i = 0; i < ARRAY_SIZE(legacy_rates); i++) {
if (rate == legacy_rates[i])
return true;
}

return false;
}

static void
ath10k_update_per_peer_tx_stats(struct ath10k *ar,
struct ieee80211_sta *sta,
struct ath10k_per_peer_tx_stats *peer_stats)
{
struct ath10k_sta *arsta = (struct ath10k_sta *)sta->drv_priv;
u8 rate = 0, sgi;
struct rate_info txrate;

lockdep_assert_held(&ar->data_lock);

txrate.flags = ATH10K_HW_PREAMBLE(peer_stats->ratecode);
txrate.bw = ATH10K_HW_BW(peer_stats->flags);
txrate.nss = ATH10K_HW_NSS(peer_stats->ratecode);
txrate.mcs = ATH10K_HW_MCS_RATE(peer_stats->ratecode);
sgi = ATH10K_HW_GI(peer_stats->flags);

if (((txrate.flags == WMI_RATE_PREAMBLE_HT) ||
(txrate.flags == WMI_RATE_PREAMBLE_VHT)) && txrate.mcs > 9) {
ath10k_warn(ar, "Invalid mcs %hhd peer stats", txrate.mcs);
return;
}

if (txrate.flags == WMI_RATE_PREAMBLE_CCK ||
txrate.flags == WMI_RATE_PREAMBLE_OFDM) {
rate = ATH10K_HW_LEGACY_RATE(peer_stats->ratecode);

if (!is_valid_legacy_rate(rate)) {
ath10k_warn(ar, "Invalid legacy rate %hhd peer stats",
rate);
return;
}

/* This is hacky, FW sends CCK rate 5.5Mbps as 6 */
rate *= 10;
if (rate == 60 && txrate.flags == WMI_RATE_PREAMBLE_CCK)
rate = rate - 5;
arsta->txrate.legacy = rate * 10;
} else if (txrate.flags == WMI_RATE_PREAMBLE_HT) {
arsta->txrate.flags = RATE_INFO_FLAGS_MCS;
arsta->txrate.mcs = txrate.mcs;
} else {
arsta->txrate.flags = RATE_INFO_FLAGS_VHT_MCS;
arsta->txrate.mcs = txrate.mcs;
}

if (sgi)
arsta->txrate.flags |= RATE_INFO_FLAGS_SHORT_GI;

arsta->txrate.nss = txrate.nss;
arsta->txrate.bw = txrate.bw + RATE_INFO_BW_20;
}

static void ath10k_htt_fetch_peer_stats(struct ath10k *ar,
struct sk_buff *skb)
{
struct htt_resp *resp = (struct htt_resp *)skb->data;
struct ath10k_per_peer_tx_stats *p_tx_stats = &ar->peer_tx_stats;
struct htt_per_peer_tx_stats_ind *tx_stats;
struct ieee80211_sta *sta;
struct ath10k_peer *peer;
int peer_id, i;
u8 ppdu_len, num_ppdu;

num_ppdu = resp->peer_tx_stats.num_ppdu;
ppdu_len = resp->peer_tx_stats.ppdu_len * sizeof(__le32);

if (skb->len < sizeof(struct htt_resp_hdr) + num_ppdu * ppdu_len) {
ath10k_warn(ar, "Invalid peer stats buf length %d\n", skb->len);
return;
}

tx_stats = (struct htt_per_peer_tx_stats_ind *)
(resp->peer_tx_stats.payload);
peer_id = __le16_to_cpu(tx_stats->peer_id);

rcu_read_lock();
spin_lock_bh(&ar->data_lock);
peer = ath10k_peer_find_by_id(ar, peer_id);
if (!peer) {
ath10k_warn(ar, "Invalid peer id %d peer stats buffer\n",
peer_id);
goto out;
}

sta = peer->sta;
for (i = 0; i < num_ppdu; i++) {
tx_stats = (struct htt_per_peer_tx_stats_ind *)
(resp->peer_tx_stats.payload + i * ppdu_len);

p_tx_stats->succ_bytes = __le32_to_cpu(tx_stats->succ_bytes);
p_tx_stats->retry_bytes = __le32_to_cpu(tx_stats->retry_bytes);
p_tx_stats->failed_bytes =
__le32_to_cpu(tx_stats->failed_bytes);
p_tx_stats->ratecode = tx_stats->ratecode;
p_tx_stats->flags = tx_stats->flags;
p_tx_stats->succ_pkts = __le16_to_cpu(tx_stats->succ_pkts);
p_tx_stats->retry_pkts = __le16_to_cpu(tx_stats->retry_pkts);
p_tx_stats->failed_pkts = __le16_to_cpu(tx_stats->failed_pkts);

ath10k_update_per_peer_tx_stats(ar, sta, p_tx_stats);
}

out:
spin_unlock_bh(&ar->data_lock);
rcu_read_unlock();
}

bool ath10k_htt_t2h_msg_handler(struct ath10k *ar, struct sk_buff *skb)
{
struct ath10k_htt *htt = &ar->htt;
Expand Down Expand Up @@ -2354,6 +2476,9 @@ bool ath10k_htt_t2h_msg_handler(struct ath10k *ar, struct sk_buff *skb)
case HTT_T2H_MSG_TYPE_TX_MODE_SWITCH_IND:
ath10k_htt_rx_tx_mode_switch_ind(ar, skb);
break;
case HTT_T2H_MSG_TYPE_PEER_STATS:
ath10k_htt_fetch_peer_stats(ar, skb);
break;
case HTT_T2H_MSG_TYPE_EN_STATS:
default:
ath10k_warn(ar, "htt event (%d) not handled\n",
Expand Down
Loading

0 comments on commit ab17cb1

Please sign in to comment.