From ac4ddc177cf0cfbb52678c7b5959a4985074e289 Mon Sep 17 00:00:00 2001 From: Manikanta Pubbisetty Date: Wed, 29 May 2019 21:09:28 +0530 Subject: [PATCH] ath11k: add raw mode support Adding raw mode tx/rx support; also, adding support for software crypto which depends on raw mode. To enable raw mode tx/rx: insmod ath11k.ko rawmode=1 To enable software crypto: insmod ath11k.ko cryptmode=1 Signed-off-by: Manikanta Pubbisetty --- drivers/net/wireless/ath/ath11k/core.c | 23 ++++++++++++++++++++++ drivers/net/wireless/ath/ath11k/core.h | 7 +++++++ drivers/net/wireless/ath/ath11k/dp_rx.c | 9 +++++---- drivers/net/wireless/ath/ath11k/dp_tx.c | 34 +++++++++++++++++++++------------ drivers/net/wireless/ath/ath11k/mac.c | 20 +++++++++++++++++-- drivers/net/wireless/ath/ath11k/wmi.c | 4 ++++ 6 files changed, 79 insertions(+), 18 deletions(-) --- a/drivers/net/wireless/ath/ath11k/core.c +++ b/drivers/net/wireless/ath/ath11k/core.c @@ -14,8 +14,14 @@ #include "debug.h" unsigned int ath11k_debug_mask; +unsigned int rawmode; +unsigned int cryptmode; module_param_named(debug_mask, ath11k_debug_mask, uint, 0644); +module_param_named(rawmode, rawmode, uint, 0644); +module_param_named(cryptmode, cryptmode, uint, 0644); MODULE_PARM_DESC(debug_mask, "Debugging mask"); +MODULE_PARM_DESC(cryptmode, "crypto mode: 0-hardware, 1-software"); +MODULE_PARM_DESC(rawmode, "RAW mode TX: 0-disable, 1-enable"); static const struct ath11k_hw_params ath11k_hw_params = { .name = "ipq8074", @@ -547,6 +553,23 @@ int ath11k_core_qmi_firmware_ready(struc return ret; } + switch (cryptmode) { + case ATH11K_CRYPT_MODE_SW: + set_bit(ATH11K_FLAG_HW_CRYPTO_DISABLED, &ab->dev_flags); + set_bit(ATH11K_FLAG_RAW_MODE, &ab->dev_flags); + break; + case ATH11K_CRYPT_MODE_HW: + clear_bit(ATH11K_FLAG_HW_CRYPTO_DISABLED, &ab->dev_flags); + clear_bit(ATH11K_FLAG_RAW_MODE, &ab->dev_flags); + break; + default: + ath11k_info(ab, "invalid cryptmode: %d\n", cryptmode); + return -EINVAL; + } + + if (rawmode) + set_bit(ATH11K_FLAG_RAW_MODE, &ab->dev_flags); + mutex_lock(&ab->core_lock); ret = ath11k_core_start(ab, ATH11K_FIRMWARE_MODE_NORMAL); if (ret) { --- a/drivers/net/wireless/ath/ath11k/core.h +++ b/drivers/net/wireless/ath/ath11k/core.h @@ -53,6 +53,13 @@ enum wme_ac { #define ATH11K_VHT_MCS_MAX 9 #define ATH11K_HE_MCS_MAX 11 +enum ath11k_crypt_mode { + /* Only use hardware crypto engine */ + ATH11K_CRYPT_MODE_HW, + /* Only use software crypto */ + ATH11K_CRYPT_MODE_SW, +}; + static inline enum wme_ac ath11k_tid_to_ac(u32 tid) { return (((tid == 0) || (tid == 3)) ? WME_AC_BE : --- a/drivers/net/wireless/ath/ath11k/dp_rx.c +++ b/drivers/net/wireless/ath/ath11k/dp_rx.c @@ -2040,8 +2040,6 @@ static void ath11k_dp_rx_h_mpdu(struct a mcast = is_multicast_ether_addr(hdr->addr1); fill_crypto_hdr = mcast; - is_decrypted = ath11k_dp_rx_h_attn_is_decrypted(rx_desc); - spin_lock_bh(&ar->ab->base_lock); peer = ath11k_peer_find_by_addr(ar->ab, hdr->addr2); if (peer) { @@ -2056,6 +2054,10 @@ static void ath11k_dp_rx_h_mpdu(struct a err_bitmap = ath11k_dp_rx_h_attn_mpdu_err(rx_desc); + enctype = ath11k_dp_rx_h_mpdu_start_enctype(rx_desc); + if (enctype != HAL_ENCRYPT_TYPE_OPEN && !err_bitmap) + is_decrypted = ath11k_dp_rx_h_attn_is_decrypted(rx_desc); + /* Clear per-MPDU flags while leaving per-PPDU flags intact */ rx_status->flag &= ~(RX_FLAG_FAILED_FCS_CRC | RX_FLAG_MMIC_ERROR | @@ -2253,6 +2255,8 @@ static void ath11k_dp_rx_deliver_msdu(st !!(status->flag & RX_FLAG_MMIC_ERROR), !!(status->flag & RX_FLAG_AMSDU_MORE)); + ath11k_dbg_dump(ar->ab, ATH11K_DBG_DP_RX, NULL, "dp rx msdu: ", + msdu->data, msdu->len); /* TODO: trace rx packet */ ieee80211_rx_napi(ar->hw, NULL, msdu, napi); --- a/drivers/net/wireless/ath/ath11k/dp_tx.c +++ b/drivers/net/wireless/ath/ath11k/dp_tx.c @@ -16,7 +16,11 @@ ath11k_txq_tcl_ring_map[ATH11K_HW_MAX_QU static enum hal_tcl_encap_type ath11k_dp_tx_get_encap_type(struct ath11k_vif *arvif, struct sk_buff *skb) { - /* TODO: Determine encap type based on vif_type and configuration */ + struct ath11k_base *ab = arvif->ar->ab; + + if (test_bit(ATH11K_FLAG_RAW_MODE, &ab->dev_flags)) + return HAL_TCL_ENCAP_TYPE_RAW; + return HAL_TCL_ENCAP_TYPE_NATIVE_WIFI; } @@ -110,11 +114,17 @@ int ath11k_dp_tx(struct ath11k *ar, stru ti.encap_type = ath11k_dp_tx_get_encap_type(arvif, skb); ti.meta_data_flags = arvif->tcl_metadata; - if (info->control.hw_key) - ti.encrypt_type = - ath11k_dp_tx_get_encrypt_type(info->control.hw_key->cipher); - else - ti.encrypt_type = HAL_ENCRYPT_TYPE_OPEN; + if (ti.encap_type == HAL_TCL_ENCAP_TYPE_RAW) { + if (info->control.hw_key) { + ti.encrypt_type = + ath11k_dp_tx_get_encrypt_type(info->control.hw_key->cipher); + + if (ieee80211_has_protected(hdr->frame_control)) + skb_put(skb, IEEE80211_CCMP_MIC_LEN); + } else { + ti.encrypt_type = HAL_ENCRYPT_TYPE_OPEN; + } + } ti.addr_search_flags = arvif->hal_addr_search_flags; ti.search_type = arvif->search_type; @@ -124,7 +134,8 @@ int ath11k_dp_tx(struct ath11k *ar, stru ti.bss_ast_hash = arvif->ast_hash; ti.dscp_tid_tbl_idx = 0; - if (skb->ip_summed == CHECKSUM_PARTIAL) { + if (skb->ip_summed == CHECKSUM_PARTIAL && + ti.encap_type != HAL_TCL_ENCAP_TYPE_RAW) { ti.flags0 |= FIELD_PREP(HAL_TCL_DATA_CMD_INFO1_IP4_CKSUM_EN, 1) | FIELD_PREP(HAL_TCL_DATA_CMD_INFO1_UDP4_CKSUM_EN, 1) | FIELD_PREP(HAL_TCL_DATA_CMD_INFO1_UDP6_CKSUM_EN, 1) | @@ -144,10 +155,11 @@ int ath11k_dp_tx(struct ath11k *ar, stru ath11k_dp_tx_encap_nwifi(skb); break; case HAL_TCL_ENCAP_TYPE_RAW: - /* TODO: for CHECKSUM_PARTIAL case in raw mode, HW checksum offload - * is not applicable, hence manual checksum calculation using - * skb_checksum_help() is needed - */ + if (!test_bit(ATH11K_FLAG_RAW_MODE, &ab->dev_flags)) { + ret = -EINVAL; + goto fail_remove_idr; + } + break; case HAL_TCL_ENCAP_TYPE_ETHERNET: case HAL_TCL_ENCAP_TYPE_802_3: /* TODO: Take care of other encap modes as well */ @@ -186,6 +198,9 @@ int ath11k_dp_tx(struct ath11k *ar, stru goto fail_unmap_dma; } + ath11k_dbg_dump(ab, ATH11K_DBG_DP_TX, NULL, "dp tx msdu: ", + skb->data, skb->len); + ath11k_hal_tx_cmd_desc_setup(ab, hal_tcl_desc + sizeof(struct hal_tlv_hdr), &ti); @@ -300,7 +315,6 @@ ath11k_dp_tx_process_htt_tx_complete(str wbm_status = FIELD_GET(HTT_TX_WBM_COMP_INFO0_STATUS, status_desc->info0); - switch (wbm_status) { case HAL_WBM_REL_HTT_TX_COMP_STATUS_OK: case HAL_WBM_REL_HTT_TX_COMP_STATUS_DROP: --- a/drivers/net/wireless/ath/ath11k/mac.c +++ b/drivers/net/wireless/ath/ath11k/mac.c @@ -2258,6 +2258,9 @@ static int ath11k_install_key(struct ath reinit_completion(&ar->install_key_done); + if (test_bit(ATH11K_FLAG_HW_CRYPTO_DISABLED, &ar->ab->dev_flags)) + return 0; + if (cmd == DISABLE_KEY) { /* TODO: Check if FW expects value other than NONE for del */ /* arg.key_cipher = WMI_CIPHER_NONE; */ @@ -2289,8 +2292,12 @@ static int ath11k_install_key(struct ath return -EOPNOTSUPP; } + if (test_bit(ATH11K_FLAG_RAW_MODE, &ar->ab->dev_flags)) + key->flags |= IEEE80211_KEY_FLAG_GENERATE_IV; + install: ret = ath11k_wmi_vdev_install_key(arvif->ar, &arg); + if (ret) return ret; @@ -2362,6 +2369,9 @@ static int ath11k_mac_op_set_key(struct key->cipher == WLAN_CIPHER_SUITE_BIP_CMAC_256) return 1; + if (test_bit(ATH11K_FLAG_HW_CRYPTO_DISABLED, &ar->ab->dev_flags)) + return 1; + if (key->keyidx > WMI_MAX_KEY_INDEX) return -ENOSPC; @@ -4220,6 +4230,10 @@ static int ath11k_mac_op_add_interface(s param_id = WMI_VDEV_PARAM_TX_ENCAP_TYPE; param_value = ATH11K_HW_TXRX_NATIVE_WIFI; + + if (test_bit(ATH11K_FLAG_RAW_MODE, &ab->dev_flags)) + param_value = ATH11K_HW_TXRX_RAW; + ret = ath11k_wmi_vdev_set_param_cmd(ar, arvif->vdev_id, param_id, param_value); if (ret) { @@ -5855,8 +5869,10 @@ static int __ath11k_mac_register(struct ath11k_reg_init(ar); - /* advertise HW checksum offload capabilities */ - ar->hw->netdev_features = NETIF_F_HW_CSUM; + if (!test_bit(ATH11K_FLAG_RAW_MODE, &ab->dev_flags)) { + ar->hw->netdev_features = NETIF_F_HW_CSUM; + ieee80211_hw_set(ar->hw, SW_CRYPTO_CONTROL); + } ret = ieee80211_register_hw(ar->hw); if (ret) { --- a/drivers/net/wireless/ath/ath11k/wmi.c +++ b/drivers/net/wireless/ath/ath11k/wmi.c @@ -3229,6 +3229,10 @@ int ath11k_wmi_cmd_init(struct ath11k_ba config.rx_timeout_pri[2] = TARGET_RX_TIMEOUT_LO_PRI; config.rx_timeout_pri[3] = TARGET_RX_TIMEOUT_HI_PRI; config.rx_decap_mode = TARGET_DECAP_MODE_NATIVE_WIFI; + + if (test_bit(ATH11K_FLAG_RAW_MODE, &ab->dev_flags)) + config.rx_decap_mode = TARGET_DECAP_MODE_RAW; + config.scan_max_pending_req = TARGET_SCAN_MAX_PENDING_REQS; config.bmiss_offload_max_vdev = TARGET_BMISS_OFFLOAD_MAX_VDEV; config.roam_offload_max_vdev = TARGET_ROAM_OFFLOAD_MAX_VDEV; --- a/drivers/net/wireless/ath/ath11k/debug.h +++ b/drivers/net/wireless/ath/ath11k/debug.h @@ -25,6 +25,8 @@ enum ath11k_debug_mask { ATH11K_DBG_REG = 0x00000200, ATH11K_DBG_TESTMODE = 0x00000400, ATH11k_DBG_HAL = 0x00000800, + ATH11K_DBG_DP_TX = 0x00001000, + ATH11K_DBG_DP_RX = 0x00002000, ATH11K_DBG_ANY = 0xffffffff, };