Skip to content

Commit

Permalink
ath10k: enable raw encap mode and software crypto engine
Browse files Browse the repository at this point in the history
This patch enables raw Rx/Tx encap mode to support software based
crypto engine. This patch introduces a new module param 'cryptmode'.

 cryptmode:

   0: Use hardware crypto engine globally with native Wi-Fi mode TX/RX
      encapsulation to the firmware. This is the default mode.
   1: Use sofware crypto engine globally with raw mode TX/RX
      encapsulation to the firmware.

Known limitation:
   A-MSDU must be disabled for RAW Tx encap mode to perform well when
   heavy traffic is applied.

Testing: (by Michal Kazior <michal.kazior@tieto.com>)

     a) Performance Testing

      cryptmode=1
       ap=qca988x sta=killer1525
        killer1525  ->  qca988x     194.496 mbps [tcp1 ip4]
        killer1525  ->  qca988x     238.309 mbps [tcp5 ip4]
        killer1525  ->  qca988x     266.958 mbps [udp1 ip4]
        killer1525  ->  qca988x     477.468 mbps [udp5 ip4]
        qca988x     ->  killer1525  301.378 mbps [tcp1 ip4]
        qca988x     ->  killer1525  297.949 mbps [tcp5 ip4]
        qca988x     ->  killer1525  331.351 mbps [udp1 ip4]
        qca988x     ->  killer1525  371.528 mbps [udp5 ip4]
       ap=killer1525 sta=qca988x
        qca988x     ->  killer1525  331.447 mbps [tcp1 ip4]
        qca988x     ->  killer1525  328.783 mbps [tcp5 ip4]
        qca988x     ->  killer1525  375.309 mbps [udp1 ip4]
        qca988x     ->  killer1525  403.379 mbps [udp5 ip4]
        killer1525  ->  qca988x     203.689 mbps [tcp1 ip4]
        killer1525  ->  qca988x     222.339 mbps [tcp5 ip4]
        killer1525  ->  qca988x     264.199 mbps [udp1 ip4]
        killer1525  ->  qca988x     479.371 mbps [udp5 ip4]

      Note:
       - only open network tested for RAW vs nwifi performance comparison
       - killer1525 (qca6174 hw2.2) is 2x2 device (hence max 866mbps)
       - used iperf
       - OTA, devices a few cm apart from each other, no shielding
       - tcpX/udpX, X - means number of threads used

      Overview:
       - relative Tx performance drop is seen but is within reasonable and
         expected threshold (A-MSDU must be disabled with RAW Tx)

     b) Connectivity Testing

      cryptmode=1
       ap=iwl6205 sta1=qca988x crypto=open     topology-1ap1sta          OK
       ap=iwl6205 sta1=qca988x crypto=wep1     topology-1ap1sta          OK
       ap=iwl6205 sta1=qca988x crypto=wpa      topology-1ap1sta          OK
       ap=iwl6205 sta1=qca988x crypto=wpa-ccmp topology-1ap1sta          OK
       ap=qca988x sta1=iwl6205 crypto=open     topology-1ap1sta          OK
       ap=qca988x sta1=iwl6205 crypto=wep1     topology-1ap1sta          OK
       ap=qca988x sta1=iwl6205 crypto=wpa      topology-1ap1sta          OK
       ap=qca988x sta1=iwl6205 crypto=wpa-ccmp topology-1ap1sta          OK
       ap=iwl6205 sta1=qca988x crypto=open     topology-1ap1sta2br       OK
       ap=iwl6205 sta1=qca988x crypto=wep1     topology-1ap1sta2br       OK
       ap=iwl6205 sta1=qca988x crypto=wpa      topology-1ap1sta2br       OK
       ap=iwl6205 sta1=qca988x crypto=wpa-ccmp topology-1ap1sta2br       OK
       ap=qca988x sta1=iwl6205 crypto=open     topology-1ap1sta2br       OK
       ap=qca988x sta1=iwl6205 crypto=wep1     topology-1ap1sta2br       OK
       ap=qca988x sta1=iwl6205 crypto=wpa      topology-1ap1sta2br       OK
       ap=qca988x sta1=iwl6205 crypto=wpa-ccmp topology-1ap1sta2br       OK
       ap=iwl6205 sta1=qca988x crypto=open     topology-1ap1sta2br1vlan  OK
       ap=iwl6205 sta1=qca988x crypto=wep1     topology-1ap1sta2br1vlan  OK
       ap=iwl6205 sta1=qca988x crypto=wpa      topology-1ap1sta2br1vlan  OK
       ap=iwl6205 sta1=qca988x crypto=wpa-ccmp topology-1ap1sta2br1vlan  OK
       ap=qca988x sta1=iwl6205 crypto=open     topology-1ap1sta2br1vlan  OK
       ap=qca988x sta1=iwl6205 crypto=wep1     topology-1ap1sta2br1vlan  OK
       ap=qca988x sta1=iwl6205 crypto=wpa      topology-1ap1sta2br1vlan  OK
       ap=qca988x sta1=iwl6205 crypto=wpa-ccmp topology-1ap1sta2br1vlan  OK

      Note:
       - each test takes all possible endpoint pairs and pings
       - each pair-ping flushes arp table
       - ip6 is used

     c) Testbed Topology:

      1ap1sta:
        [ap] ---- [sta]

        endpoints: ap, sta

      1ap1sta2br:
        [veth0] [ap] ---- [sta] [veth2]
           |     |          |     |
        [veth1]  |          \   [veth3]
            \   /            \  /
            [br0]            [br1]

        endpoints: veth0, veth2, br0, br1
        note: STA works in 4addr mode, AP has wds_sta=1

      1ap1sta2br1vlan:
        [veth0] [ap] ---- [sta] [veth2]
           |     |          |     |
        [veth1]  |          \   [veth3]
            \   /            \  /
          [br0]              [br1]
            |                  |
          [vlan0_id2]        [vlan1_id2]

        endpoints: vlan0_id2, vlan1_id2
        note: STA works in 4addr mode, AP has wds_sta=1

Credits:

    Thanks to Michal Kazior <michal.kazior@tieto.com> who helped find the
    amsdu issue, contributed a workaround (already squashed into this
    patch), and contributed the throughput and connectivity tests results.

Signed-off-by: David Liu <cfliu.tw@gmail.com>
Signed-off-by: Michal Kazior <michal.kazior@tieto.com>
Tested-by: Michal Kazior <michal.kazior@tieto.com>
Signed-off-by: Kalle Valo <kvalo@qca.qualcomm.com>
  • Loading branch information
cfliu authored and kvalo committed Jul 29, 2015
1 parent 005fb16 commit ccec903
Show file tree
Hide file tree
Showing 11 changed files with 183 additions and 51 deletions.
43 changes: 43 additions & 0 deletions drivers/net/wireless/ath/ath10k/core.c
Original file line number Diff line number Diff line change
Expand Up @@ -31,16 +31,19 @@
#include "wmi-ops.h"

unsigned int ath10k_debug_mask;
static unsigned int ath10k_cryptmode_param;
static bool uart_print;
static bool skip_otp;

module_param_named(debug_mask, ath10k_debug_mask, uint, 0644);
module_param_named(cryptmode, ath10k_cryptmode_param, uint, 0644);
module_param(uart_print, bool, 0644);
module_param(skip_otp, bool, 0644);

MODULE_PARM_DESC(debug_mask, "Debugging mask");
MODULE_PARM_DESC(uart_print, "Uart target debugging");
MODULE_PARM_DESC(skip_otp, "Skip otp failure for calibration in testmode");
MODULE_PARM_DESC(cryptmode, "Crypto mode: 0-hardware, 1-software");

static const struct ath10k_hw_params ath10k_hw_params_list[] = {
{
Expand Down Expand Up @@ -1073,6 +1076,46 @@ static int ath10k_core_init_firmware_features(struct ath10k *ar)
return -EINVAL;
}

ar->wmi.rx_decap_mode = ATH10K_HW_TXRX_NATIVE_WIFI;
switch (ath10k_cryptmode_param) {
case ATH10K_CRYPT_MODE_HW:
clear_bit(ATH10K_FLAG_RAW_MODE, &ar->dev_flags);
clear_bit(ATH10K_FLAG_HW_CRYPTO_DISABLED, &ar->dev_flags);
break;
case ATH10K_CRYPT_MODE_SW:
if (!test_bit(ATH10K_FW_FEATURE_RAW_MODE_SUPPORT,
ar->fw_features)) {
ath10k_err(ar, "cryptmode > 0 requires raw mode support from firmware");
return -EINVAL;
}

set_bit(ATH10K_FLAG_RAW_MODE, &ar->dev_flags);
set_bit(ATH10K_FLAG_HW_CRYPTO_DISABLED, &ar->dev_flags);
break;
default:
ath10k_info(ar, "invalid cryptmode: %d\n",
ath10k_cryptmode_param);
return -EINVAL;
}

ar->htt.max_num_amsdu = ATH10K_HTT_MAX_NUM_AMSDU_DEFAULT;
ar->htt.max_num_ampdu = ATH10K_HTT_MAX_NUM_AMPDU_DEFAULT;

if (test_bit(ATH10K_FLAG_RAW_MODE, &ar->dev_flags)) {
ar->wmi.rx_decap_mode = ATH10K_HW_TXRX_RAW;

/* Workaround:
*
* Firmware A-MSDU aggregation breaks with RAW Tx encap mode
* and causes enormous performance issues (malformed frames,
* etc).
*
* Disabling A-MSDU makes RAW mode stable with heavy traffic
* albeit a bit slower compared to regular operation.
*/
ar->htt.max_num_amsdu = 1;
}

/* Backwards compatibility for firmwares without
* ATH10K_FW_IE_WMI_OP_VERSION.
*/
Expand Down
31 changes: 26 additions & 5 deletions drivers/net/wireless/ath/ath10k/core.h
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,7 @@ struct ath10k_skb_cb {
u8 tid;
u16 freq;
bool is_offchan;
bool nohwcrypt;
struct ath10k_htt_txbuf *txbuf;
u32 txbuf_paddr;
} __packed htt;
Expand Down Expand Up @@ -152,6 +153,7 @@ struct ath10k_wmi {
const struct wmi_ops *ops;

u32 num_mem_chunks;
u32 rx_decap_mode;
struct ath10k_mem_chunk mem_chunks[WMI_MAX_MEM_REQS];
};

Expand Down Expand Up @@ -341,6 +343,7 @@ struct ath10k_vif {
} u;

bool use_cts_prot;
bool nohwcrypt;
int num_legacy_stations;
int txpower;
struct wmi_wmm_params_all_arg wmm_params;
Expand Down Expand Up @@ -382,9 +385,6 @@ struct ath10k_debug {
u32 reg_addr;
u32 nf_cal_period;

u8 htt_max_amsdu;
u8 htt_max_ampdu;

struct ath10k_fw_crash_data *fw_crash_data;
};

Expand Down Expand Up @@ -453,16 +453,21 @@ enum ath10k_fw_features {
ATH10K_FW_FEATURE_WOWLAN_SUPPORT = 6,

/* Don't trust error code from otp.bin */
ATH10K_FW_FEATURE_IGNORE_OTP_RESULT,
ATH10K_FW_FEATURE_IGNORE_OTP_RESULT = 7,

/* Some firmware revisions pad 4th hw address to 4 byte boundary making
* it 8 bytes long in Native Wifi Rx decap.
*/
ATH10K_FW_FEATURE_NO_NWIFI_DECAP_4ADDR_PADDING,
ATH10K_FW_FEATURE_NO_NWIFI_DECAP_4ADDR_PADDING = 8,

/* Firmware supports bypassing PLL setting on init. */
ATH10K_FW_FEATURE_SUPPORTS_SKIP_CLOCK_INIT = 9,

/* Raw mode support. If supported, FW supports receiving and trasmitting
* frames in raw mode.
*/
ATH10K_FW_FEATURE_RAW_MODE_SUPPORT = 10,

/* keep last */
ATH10K_FW_FEATURE_COUNT,
};
Expand All @@ -476,6 +481,15 @@ enum ath10k_dev_flags {
* waiters should immediately cancel instead of waiting for a time out.
*/
ATH10K_FLAG_CRASH_FLUSH,

/* Use Raw mode instead of native WiFi Tx/Rx encap mode.
* Raw mode supports both hardware and software crypto. Native WiFi only
* supports hardware crypto.
*/
ATH10K_FLAG_RAW_MODE,

/* Disable HW crypto engine */
ATH10K_FLAG_HW_CRYPTO_DISABLED,
};

enum ath10k_cal_mode {
Expand All @@ -484,6 +498,13 @@ enum ath10k_cal_mode {
ATH10K_CAL_MODE_DT,
};

enum ath10k_crypt_mode {
/* Only use hardware crypto engine */
ATH10K_CRYPT_MODE_HW,
/* Only use software crypto engine */
ATH10K_CRYPT_MODE_SW,
};

static inline const char *ath10k_cal_mode_str(enum ath10k_cal_mode mode)
{
switch (mode) {
Expand Down
19 changes: 7 additions & 12 deletions drivers/net/wireless/ath/ath10k/debug.c
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,7 @@ void ath10k_print_driver_info(struct ath10k *ar)

ath10k_core_get_fw_features_str(ar, fw_features, sizeof(fw_features));

ath10k_info(ar, "%s (0x%08x, 0x%08x%s%s%s) fw %s api %d htt-ver %d.%d wmi-op %d htt-op %d cal %s max-sta %d features %s\n",
ath10k_info(ar, "%s (0x%08x, 0x%08x%s%s%s) fw %s api %d htt-ver %d.%d wmi-op %d htt-op %d cal %s max-sta %d raw %d hwcrypto %d features %s\n",
ar->hw_params.name,
ar->target_version,
ar->chip_id,
Expand All @@ -144,6 +144,8 @@ void ath10k_print_driver_info(struct ath10k *ar)
ar->htt.op_version,
ath10k_cal_mode_str(ar->cal_mode),
ar->max_num_stations,
test_bit(ATH10K_FLAG_RAW_MODE, &ar->dev_flags),
!test_bit(ATH10K_FLAG_HW_CRYPTO_DISABLED, &ar->dev_flags),
fw_features);
ath10k_info(ar, "debug %d debugfs %d tracing %d dfs %d testmode %d\n",
config_enabled(CONFIG_ATH10K_DEBUG),
Expand Down Expand Up @@ -1363,12 +1365,8 @@ static ssize_t ath10k_read_htt_max_amsdu_ampdu(struct file *file,

mutex_lock(&ar->conf_mutex);

if (ar->debug.htt_max_amsdu)
amsdu = ar->debug.htt_max_amsdu;

if (ar->debug.htt_max_ampdu)
ampdu = ar->debug.htt_max_ampdu;

amsdu = ar->htt.max_num_amsdu;
ampdu = ar->htt.max_num_ampdu;
mutex_unlock(&ar->conf_mutex);

len = scnprintf(buf, sizeof(buf), "%u %u\n", amsdu, ampdu);
Expand Down Expand Up @@ -1402,8 +1400,8 @@ static ssize_t ath10k_write_htt_max_amsdu_ampdu(struct file *file,
goto out;

res = count;
ar->debug.htt_max_amsdu = amsdu;
ar->debug.htt_max_ampdu = ampdu;
ar->htt.max_num_amsdu = amsdu;
ar->htt.max_num_ampdu = ampdu;

out:
mutex_unlock(&ar->conf_mutex);
Expand Down Expand Up @@ -1905,9 +1903,6 @@ void ath10k_debug_stop(struct ath10k *ar)
if (ar->debug.htt_stats_mask != 0)
cancel_delayed_work(&ar->debug.htt_stats_dwork);

ar->debug.htt_max_amsdu = 0;
ar->debug.htt_max_ampdu = 0;

ath10k_wmi_pdev_pktlog_disable(ar);
}

Expand Down
23 changes: 21 additions & 2 deletions drivers/net/wireless/ath/ath10k/htt.c
Original file line number Diff line number Diff line change
Expand Up @@ -246,12 +246,31 @@ int ath10k_htt_setup(struct ath10k_htt *htt)
}

status = ath10k_htt_verify_version(htt);
if (status)
if (status) {
ath10k_warn(ar, "failed to verify htt version: %d\n",
status);
return status;
}

status = ath10k_htt_send_frag_desc_bank_cfg(htt);
if (status)
return status;

return ath10k_htt_send_rx_ring_cfg_ll(htt);
status = ath10k_htt_send_rx_ring_cfg_ll(htt);
if (status) {
ath10k_warn(ar, "failed to setup rx ring: %d\n",
status);
return status;
}

status = ath10k_htt_h2t_aggr_cfg_msg(htt,
htt->max_num_ampdu,
htt->max_num_amsdu);
if (status) {
ath10k_warn(ar, "failed to setup amsdu/ampdu limit: %d\n",
status);
return status;
}

return 0;
}
8 changes: 8 additions & 0 deletions drivers/net/wireless/ath/ath10k/htt.h
Original file line number Diff line number Diff line change
Expand Up @@ -1396,6 +1396,8 @@ struct ath10k_htt {
u8 target_version_minor;
struct completion target_version_received;
enum ath10k_fw_htt_op_version op_version;
u8 max_num_amsdu;
u8 max_num_ampdu;

const enum htt_t2h_msg_type *t2h_msg_types;
u32 t2h_msg_types_max;
Expand Down Expand Up @@ -1558,6 +1560,12 @@ struct htt_rx_desc {
#define HTT_LOG2_MAX_CACHE_LINE_SIZE 7 /* 2^7 = 128 */
#define HTT_MAX_CACHE_LINE_SIZE_MASK ((1 << HTT_LOG2_MAX_CACHE_LINE_SIZE) - 1)

/* These values are default in most firmware revisions and apparently are a
* sweet spot performance wise.
*/
#define ATH10K_HTT_MAX_NUM_AMSDU_DEFAULT 3
#define ATH10K_HTT_MAX_NUM_AMPDU_DEFAULT 64

int ath10k_htt_connect(struct ath10k_htt *htt);
int ath10k_htt_init(struct ath10k *ar);
int ath10k_htt_setup(struct ath10k_htt *htt);
Expand Down
7 changes: 4 additions & 3 deletions drivers/net/wireless/ath/ath10k/htt_rx.c
Original file line number Diff line number Diff line change
Expand Up @@ -1017,9 +1017,8 @@ static void ath10k_htt_rx_h_undecap_raw(struct ath10k *ar,
skb_trim(msdu, msdu->len - FCS_LEN);

/* In most cases this will be true for sniffed frames. It makes sense
* to deliver them as-is without stripping the crypto param. This would
* also make sense for software based decryption (which is not
* implemented in ath10k).
* to deliver them as-is without stripping the crypto param. This is
* necessary for software based decryption.
*
* If there's no error then the frame is decrypted. At least that is
* the case for frames that come in via fragmented rx indication.
Expand Down Expand Up @@ -2066,6 +2065,8 @@ void ath10k_htt_t2h_msg_handler(struct ath10k *ar, struct sk_buff *skb)
break;
case HTT_T2H_MSG_TYPE_CHAN_CHANGE:
break;
case HTT_T2H_MSG_TYPE_AGGR_CONF:
break;
case HTT_T2H_MSG_TYPE_EN_STATS:
case HTT_T2H_MSG_TYPE_TX_FETCH_IND:
case HTT_T2H_MSG_TYPE_TX_FETCH_CONF:
Expand Down
12 changes: 10 additions & 2 deletions drivers/net/wireless/ath/ath10k/htt_tx.c
Original file line number Diff line number Diff line change
Expand Up @@ -523,8 +523,12 @@ int ath10k_htt_tx(struct ath10k_htt *htt, struct sk_buff *msdu)
if ((ieee80211_is_action(hdr->frame_control) ||
ieee80211_is_deauth(hdr->frame_control) ||
ieee80211_is_disassoc(hdr->frame_control)) &&
ieee80211_has_protected(hdr->frame_control))
ieee80211_has_protected(hdr->frame_control)) {
skb_put(msdu, IEEE80211_CCMP_MIC_LEN);
} else if (!skb_cb->htt.nohwcrypt &&
skb_cb->txmode == ATH10K_HW_TXRX_RAW) {
skb_put(msdu, IEEE80211_CCMP_MIC_LEN);
}

skb_cb->paddr = dma_map_single(dev, msdu->data, msdu->len,
DMA_TO_DEVICE);
Expand Down Expand Up @@ -595,12 +599,16 @@ int ath10k_htt_tx(struct ath10k_htt *htt, struct sk_buff *msdu)
prefetch_len);
skb_cb->htt.txbuf->htc_hdr.flags = 0;

if (skb_cb->htt.nohwcrypt)
flags0 |= HTT_DATA_TX_DESC_FLAGS0_NO_ENCRYPT;

if (!skb_cb->is_protected)
flags0 |= HTT_DATA_TX_DESC_FLAGS0_NO_ENCRYPT;

flags1 |= SM((u16)vdev_id, HTT_DATA_TX_DESC_FLAGS1_VDEV_ID);
flags1 |= SM((u16)tid, HTT_DATA_TX_DESC_FLAGS1_EXT_TID);
if (msdu->ip_summed == CHECKSUM_PARTIAL) {
if (msdu->ip_summed == CHECKSUM_PARTIAL &&
!test_bit(ATH10K_FLAG_RAW_MODE, &ar->dev_flags)) {
flags1 |= HTT_DATA_TX_DESC_FLAGS1_CKSUM_L3_OFFLOAD;
flags1 |= HTT_DATA_TX_DESC_FLAGS1_CKSUM_L4_OFFLOAD;
if (ar->hw_params.continuous_frag_desc)
Expand Down
11 changes: 4 additions & 7 deletions drivers/net/wireless/ath/ath10k/hw.h
Original file line number Diff line number Diff line change
Expand Up @@ -217,14 +217,16 @@ void ath10k_hw_fill_survey_time(struct ath10k *ar, struct survey_info *survey,
#define QCA_REV_99X0(ar) ((ar)->hw_rev == ATH10K_HW_QCA99X0)

/* Known pecularities:
* - current FW doesn't support raw rx mode (last tested v599)
* - current FW dumps upon raw tx mode (last tested v599)
* - raw appears in nwifi decap, raw and nwifi appear in ethernet decap
* - raw have FCS, nwifi doesn't
* - ethernet frames have 802.11 header decapped and parts (base hdr, cipher
* param, llc/snap) are aligned to 4byte boundaries each */
enum ath10k_hw_txrx_mode {
ATH10K_HW_TXRX_RAW = 0,

/* Native Wifi decap mode is used to align IP frames to 4-byte
* boundaries and avoid a very expensive re-alignment in mac80211.
*/
ATH10K_HW_TXRX_NATIVE_WIFI = 1,
ATH10K_HW_TXRX_ETHERNET = 2,

Expand Down Expand Up @@ -286,10 +288,6 @@ enum ath10k_hw_rate_cck {
#define TARGET_RX_TIMEOUT_LO_PRI 100
#define TARGET_RX_TIMEOUT_HI_PRI 40

/* Native Wifi decap mode is used to align IP frames to 4-byte boundaries and
* avoid a very expensive re-alignment in mac80211. */
#define TARGET_RX_DECAP_MODE ATH10K_HW_TXRX_NATIVE_WIFI

#define TARGET_SCAN_MAX_PENDING_REQS 4
#define TARGET_BMISS_OFFLOAD_MAX_VDEV 3
#define TARGET_ROAM_OFFLOAD_MAX_VDEV 3
Expand Down Expand Up @@ -324,7 +322,6 @@ enum ath10k_hw_rate_cck {
#define TARGET_10X_RX_CHAIN_MASK (BIT(0) | BIT(1) | BIT(2))
#define TARGET_10X_RX_TIMEOUT_LO_PRI 100
#define TARGET_10X_RX_TIMEOUT_HI_PRI 40
#define TARGET_10X_RX_DECAP_MODE ATH10K_HW_TXRX_NATIVE_WIFI
#define TARGET_10X_SCAN_MAX_PENDING_REQS 4
#define TARGET_10X_BMISS_OFFLOAD_MAX_VDEV 2
#define TARGET_10X_ROAM_OFFLOAD_MAX_VDEV 2
Expand Down
Loading

0 comments on commit ccec903

Please sign in to comment.