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,9 +14,15 @@ #include "hif.h" unsigned int ath11k_debug_mask; +unsigned int rawmode; +unsigned int cryptmode; EXPORT_SYMBOL(ath11k_debug_mask); 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[] = { { @@ -580,6 +586,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 @@ -55,6 +55,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 @@ -2136,8 +2136,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) { @@ -2152,6 +2150,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 | @@ -2353,6 +2355,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 @@ -13,6 +13,10 @@ static enum hal_tcl_encap_type ath11k_dp_tx_get_encap_type(struct ath11k_vif *arvif, struct sk_buff *skb) { struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); + struct ath11k_base *ab = arvif->ar->ab; + + if (test_bit(ATH11K_FLAG_RAW_MODE, &ab->dev_flags)) + return HAL_TCL_ENCAP_TYPE_RAW; if (tx_info->control.flags & IEEE80211_TX_CTRL_HW_80211_ENCAP) return HAL_TCL_ENCAP_TYPE_ETHERNET; @@ -142,11 +146,17 @@ tcl_ring_sel: 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; @@ -156,7 +166,8 @@ tcl_ring_sel: 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) | @@ -176,10 +187,11 @@ tcl_ring_sel: 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: /* no need to encap */ break; @@ -235,6 +247,9 @@ tcl_ring_sel: 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); @@ -352,7 +367,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 @@ -2380,6 +2380,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; */ @@ -2411,8 +2414,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; @@ -2484,6 +2491,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; @@ -4442,6 +4452,9 @@ static int ath11k_mac_op_add_interface(s else 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) { @@ -6179,8 +6192,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 @@ -864,6 +864,8 @@ int ath11k_wmi_vdev_start(struct ath11k } cmd->flags |= WMI_VDEV_START_LDPC_RX_ENABLED; + if (test_bit(ATH11K_FLAG_HW_CRYPTO_DISABLED, &ar->ab->dev_flags)) + cmd->flags |= WMI_VDEV_START_HW_ENCRYPTION_DISABLED; ptr = skb->data + sizeof(*cmd); chan = ptr; @@ -1684,7 +1686,8 @@ int ath11k_wmi_vdev_install_key(struct a static inline void ath11k_wmi_copy_peer_flags(struct wmi_peer_assoc_complete_cmd *cmd, - struct peer_assoc_params *param) + struct peer_assoc_params *param, + bool hw_crypto_disabled) { cmd->peer_flags = 0; @@ -1738,7 +1741,8 @@ ath11k_wmi_copy_peer_flags(struct wmi_pe cmd->peer_flags |= WMI_PEER_AUTH; if (param->need_ptk_4_way) { cmd->peer_flags |= WMI_PEER_NEED_PTK_4_WAY; - cmd->peer_flags &= ~WMI_PEER_AUTH; + if (!hw_crypto_disabled) + cmd->peer_flags &= ~WMI_PEER_AUTH; } if (param->need_gtk_2_way) cmd->peer_flags |= WMI_PEER_NEED_GTK_2_WAY; @@ -1805,7 +1809,8 @@ int ath11k_wmi_send_peer_assoc_cmd(struc cmd->peer_new_assoc = param->peer_new_assoc; cmd->peer_associd = param->peer_associd; - ath11k_wmi_copy_peer_flags(cmd, param); + ath11k_wmi_copy_peer_flags(cmd, param, + test_bit(ATH11K_FLAG_HW_CRYPTO_DISABLED, &ar->ab->dev_flags)); ether_addr_copy(cmd->peer_macaddr.addr, param->peer_mac); @@ -3368,6 +3373,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 @@ -26,6 +26,8 @@ enum ath11k_debug_mask { ATH11K_DBG_TESTMODE = 0x00000400, ATH11k_DBG_HAL = 0x00000800, ATH11K_DBG_PCI = 0x00001000, + ATH11K_DBG_DP_TX = 0x00002000, + ATH11K_DBG_DP_RX = 0x00004000, ATH11K_DBG_ANY = 0xffffffff, }; --- a/drivers/net/wireless/ath/ath11k/wmi.h +++ b/drivers/net/wireless/ath/ath11k/wmi.h @@ -2502,6 +2502,7 @@ struct wmi_vdev_down_cmd { #define WMI_VDEV_START_HIDDEN_SSID BIT(0) #define WMI_VDEV_START_PMF_ENABLED BIT(1) #define WMI_VDEV_START_LDPC_RX_ENABLED BIT(3) +#define WMI_VDEV_START_HW_ENCRYPTION_DISABLED BIT(4) struct wmi_ssid { u32 ssid_len;