From patchwork Wed May 6 01:06:46 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Liu CF/TW X-Patchwork-Id: 6345141 Return-Path: X-Original-To: patchwork-ath10k@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork1.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.136]) by patchwork1.web.kernel.org (Postfix) with ESMTP id 0CAE89F1C2 for ; Wed, 6 May 2015 01:08:01 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 552C420220 for ; Wed, 6 May 2015 01:07:59 +0000 (UTC) Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.9]) (using TLSv1.2 with cipher DHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 8B43D2017D for ; Wed, 6 May 2015 01:07:57 +0000 (UTC) Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.80.1 #2 (Red Hat Linux)) id 1YpnoW-0003TI-IM; Wed, 06 May 2015 01:07:52 +0000 Received: from mail-ig0-x235.google.com ([2607:f8b0:4001:c05::235]) by bombadil.infradead.org with esmtps (Exim 4.80.1 #2 (Red Hat Linux)) id 1YpnoS-0003KL-8y for ath10k@lists.infradead.org; Wed, 06 May 2015 01:07:50 +0000 Received: by igblo3 with SMTP id lo3so116779524igb.1 for ; Tue, 05 May 2015 18:07:26 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=mime-version:from:date:message-id:subject:to:cc:content-type; bh=XQ6S3f8he3jJwbUcI8wClb7U0LU34ciaE6+1MxO1QxM=; b=0MiQHy09UICV6UongiBUfmcZB7+PUGf9dK/6PsfP62wJUS6IwxtLOUfsDsuI1YhsGv 3qDAQeAM4gMjYoqSBQuCti5c5g4GlSFsPoktWHOof/R10yTodIDj2r9nkORCa3kBkfSn tcEZBmuahBJQVc8q5qyIvhJG30c6P73ujH8WhxL6EM1cnbL5iTkSIWBdl/HJRVZ5Uwi9 gOMPkpdDz9xcIDlNpJ8OSYD2T9j+uy/ERpXwn2kf/XjbKkFB9irj4UkmLZGfMjsFixdL IHHi1W/yWFQ4QeNdufrTodFp4PgSs7EwhXKm3cA7xO0/EUPM6/iGccGaLtI5adhbZOP7 1ciA== X-Received: by 10.43.65.19 with SMTP id xk19mr222426icb.20.1430874446421; Tue, 05 May 2015 18:07:26 -0700 (PDT) MIME-Version: 1.0 Received: by 10.36.216.4 with HTTP; Tue, 5 May 2015 18:06:46 -0700 (PDT) From: "Liu CF/TW" Date: Tue, 5 May 2015 18:06:46 -0700 Message-ID: Subject: [PATCH] ath10k/mac80211: add rawtxrx, nohwcrypt module param for raw tx injection, sw crypto support. To: kvalo@qca.qualcomm.com, "ath10k@lists.infradead.org" X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20150505_180748_513323_8ADF674B X-CRM114-Status: GOOD ( 22.51 ) X-Spam-Score: -0.8 (/) Cc: linux-wireless@vger.kernel.org X-BeenThere: ath10k@lists.infradead.org X-Mailman-Version: 2.1.18-1 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "ath10k" Errors-To: ath10k-bounces+patchwork-ath10k=patchwork.kernel.org@lists.infradead.org X-Spam-Status: No, score=-4.1 required=5.0 tests=BAYES_00, DKIM_ADSP_CUSTOM_MED, DKIM_SIGNED, FREEMAIL_FROM, RCVD_IN_DNSWL_MED, T_DKIM_INVALID, T_RP_MATCHES_RCVD, UNPARSEABLE_RELAY autolearn=unavailable version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP - ath10k: add rawtxrx param for 10.2+ firmware to support sw, hw crypto engine and raw Tx injection. - mac80211: Add IEEE80211_KEY_FLAG_RESERVE_TAILROOM support for TKIP and CCMP required by ath10k and add per BSS(vif) based sw_crypto control. This change enables the raw Tx/Rx feature in ath10k 10.2+ firmware with a module parameter 'rawtxrx'. With rawtxrx=1, the ath10k hardware crypto engine could be optionally skipped to support use cases such as enabling mac80211 sw crypto engine, user level crypto engine, raw Tx frame injection. ath10k hw supports hw encryption in both native wifi and raw encap mode. SW may choose to skip hw crypto engine on per Tx frame or per STA descriptor basis. This change implements per BSS based sw_crypto control policy by adding the NL80211_ATTR_SW_CRYPTO attribute to nl80211. This change also implements the classic 'nohwcrypt' module param in ath9k/5k to globally disable the hardware engine. When sw crypto or raw tx injection is used, 'rawtxrx=1' module param is required. - ath10k_core module parameters: rawtxrx: When set to 1, hw uses raw Tx encap (per frame), and raw Rx decap (global, pdev setting) on datapath. nohwcrypt: When set to 1, disables HW crypto engine globally. - mac80211 change: Support IEEE80211_KEY_FLAG_RESERVE_TAILROOM. Required for sw crypto to work for ath10k. Introduce NL80211_ATTR_SW_CRYPTO attribute as a per BSS parameter to selectively choose sw or hw crypto engine when BSS is created. Testing: used QCA988x hw 2.0 with 10.2 firmware. ath10k ath10k nl80211 rawtxrx nohwcrypt SW_CRYPTO param param attribute Testing Status ------- --------- --------- --------------------------------- 0 0 - HW CCMP/TKIP tested ok. 0 1 - Not supported by ath10k hw. 1 0 - HW CCMP/TKIP tested ok. 1 0 0 BSS 1 tested HW CCMP/TKIP ok. 1 0 1 BSS 2 can bypass HW engine. - mac80211 SW crypto tested ok. - raw Tx frame injection tested ok. 1 1 - HW crypto globally disabled. - mac80211 SW crypto tested ok. - raw Tx frame injection tested ok. Signed-off-by: David Liu --- drivers/net/wireless/ath/ath10k/core.c | 12 +++++++ drivers/net/wireless/ath/ath10k/core.h | 5 +++ drivers/net/wireless/ath/ath10k/htt_rx.c | 3 +- drivers/net/wireless/ath/ath10k/htt_tx.c | 3 ++ drivers/net/wireless/ath/ath10k/hw.h | 2 +- drivers/net/wireless/ath/ath10k/mac.c | 56 +++++++++++++++++++++++++++++--- drivers/net/wireless/ath/ath10k/wmi.c | 6 ++-- include/net/cfg80211.h | 4 +++ include/net/mac80211.h | 3 ++ include/uapi/linux/nl80211.h | 5 +++ net/mac80211/cfg.c | 7 ++++ net/mac80211/wpa.c | 24 +++++++++++--- net/wireless/nl80211.c | 5 +++ net/wireless/trace.h | 7 ++-- 14 files changed, 125 insertions(+), 17 deletions(-) diff --git a/drivers/net/wireless/ath/ath10k/core.c b/drivers/net/wireless/ath/ath10k/core.c index bcccae1..d31597d 100644 --- a/drivers/net/wireless/ath/ath10k/core.c +++ b/drivers/net/wireless/ath/ath10k/core.c @@ -31,16 +31,22 @@ #include "wmi-ops.h" unsigned int ath10k_debug_mask; +bool ath10k_modparam_nohwcrypt; +bool ath10k_modparam_rawtxrx; static bool uart_print; static bool skip_otp; module_param_named(debug_mask, ath10k_debug_mask, uint, 0644); +module_param_named(nohwcrypt, ath10k_modparam_nohwcrypt, bool, 0644); +module_param_named(rawtxrx, ath10k_modparam_rawtxrx, bool, 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(nohwcrypt, "Disable hw crypto globally"); +MODULE_PARM_DESC(rxwtxrx, "Use raw encap/decap mode"); static const struct ath10k_hw_params ath10k_hw_params_list[] = { { @@ -990,6 +996,12 @@ static int ath10k_core_init_firmware_features(struct ath10k *ar) return -EINVAL; } + if ((ath10k_modparam_rawtxrx || ath10k_modparam_nohwcrypt) && + !test_bit(ATH10K_FW_FEATURE_WMI_10_2, ar->fw_features)) { + ath10k_err(ar, "rawtxrx mode supported only in 10.2+ firmware"); + return -EINVAL; + } + /* Backwards compatibility for firmwares without * ATH10K_FW_IE_WMI_OP_VERSION. */ diff --git a/drivers/net/wireless/ath/ath10k/core.h b/drivers/net/wireless/ath/ath10k/core.h index 827b3d7..1e7a5ca 100644 --- a/drivers/net/wireless/ath/ath10k/core.h +++ b/drivers/net/wireless/ath/ath10k/core.h @@ -66,6 +66,9 @@ struct ath10k; +extern bool ath10k_modparam_nohwcrypt; +extern bool ath10k_modparam_rawtxrx; + enum ath10k_bus { ATH10K_BUS_PCI, }; @@ -91,6 +94,7 @@ struct ath10k_skb_cb { u8 tid; u16 freq; bool is_offchan; + bool nohwcrypt; struct ath10k_htt_txbuf *txbuf; u32 txbuf_paddr; } __packed htt; @@ -349,6 +353,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; diff --git a/drivers/net/wireless/ath/ath10k/htt_rx.c b/drivers/net/wireless/ath/ath10k/htt_rx.c index b26e32f..29ec1ec 100644 --- a/drivers/net/wireless/ath/ath10k/htt_rx.c +++ b/drivers/net/wireless/ath/ath10k/htt_rx.c @@ -1012,8 +1012,7 @@ static void ath10k_htt_rx_h_undecap_raw(struct ath10k *ar, /* 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). + * also make sense 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. diff --git a/drivers/net/wireless/ath/ath10k/htt_tx.c b/drivers/net/wireless/ath/ath10k/htt_tx.c index a60ef7d..18446d9 100644 --- a/drivers/net/wireless/ath/ath10k/htt_tx.c +++ b/drivers/net/wireless/ath/ath10k/htt_tx.c @@ -508,6 +508,9 @@ 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; diff --git a/drivers/net/wireless/ath/ath10k/hw.h b/drivers/net/wireless/ath/ath10k/hw.h index 89e09cb..3d3bb9e 100644 --- a/drivers/net/wireless/ath/ath10k/hw.h +++ b/drivers/net/wireless/ath/ath10k/hw.h @@ -293,7 +293,7 @@ enum ath10k_hw_rate_cck { #define TARGET_10X_RX_SKIP_DEFRAG_TIMEOUT_DUP_DETECTION_CHECK 1 #define TARGET_10X_VOW_CONFIG 0 #define TARGET_10X_NUM_MSDU_DESC (1024 + 400) -#define TARGET_10X_MAX_FRAG_ENTRIES 0 +#define TARGET_10X_MAX_FRAG_ENTRIES 10 /* 10.2 parameters */ #define TARGET_10_2_DMA_BURST_SIZE 1 diff --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c index 425dbe2..8f34e79 100644 --- a/drivers/net/wireless/ath/ath10k/mac.c +++ b/drivers/net/wireless/ath/ath10k/mac.c @@ -172,6 +172,7 @@ static int ath10k_send_key(struct ath10k_vif *arvif, .key_flags = flags, .macaddr = macaddr, }; + int ret; lockdep_assert_held(&arvif->ar->conf_mutex); @@ -184,6 +185,9 @@ static int ath10k_send_key(struct ath10k_vif *arvif, arg.key_cipher = WMI_CIPHER_TKIP; arg.key_txmic_len = 8; arg.key_rxmic_len = 8; + if (ath10k_modparam_rawtxrx) + key->flags |= IEEE80211_KEY_FLAG_GENERATE_MMIC; + break; case WLAN_CIPHER_SUITE_WEP40: case WLAN_CIPHER_SUITE_WEP104: @@ -197,12 +201,24 @@ static int ath10k_send_key(struct ath10k_vif *arvif, return -EOPNOTSUPP; } + if (ath10k_modparam_rawtxrx) { + key->flags |= IEEE80211_KEY_FLAG_GENERATE_IV; + key->flags |= IEEE80211_KEY_FLAG_RESERVE_TAILROOM; + } + + if (arvif->nohwcrypt) + cmd = DISABLE_KEY; + if (cmd == DISABLE_KEY) { arg.key_cipher = WMI_CIPHER_NONE; arg.key_data = NULL; } - return ath10k_wmi_vdev_install_key(arvif->ar, &arg); + ret = ath10k_wmi_vdev_install_key(arvif->ar, &arg); + + if (arvif->nohwcrypt && !ret) + return -EOPNOTSUPP; + return ret; } static int ath10k_install_key(struct ath10k_vif *arvif, @@ -3192,9 +3208,24 @@ ath10k_tx_h_get_txmode(struct ath10k *ar, struct ieee80211_vif *vif, if (ieee80211_is_data_present(fc) && sta && sta->tdls) return ATH10K_HW_TXRX_ETHERNET; + if (ath10k_modparam_rawtxrx) + return ATH10K_HW_TXRX_RAW; + return ATH10K_HW_TXRX_NATIVE_WIFI; } +static bool ath10k_tx_h_use_hwcrypto(struct ieee80211_vif *vif, + struct sk_buff *skb) { + struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); + const u32 mask = IEEE80211_TX_INTFL_DONT_ENCRYPT | + IEEE80211_TX_CTL_INJECTED; + if ((info->flags & mask) == mask) + return false; + if (vif) + return !ath10k_vif_to_arvif(vif)->nohwcrypt; + return true; +} + /* HTT Tx uses Native Wifi tx mode which expects 802.11 frames without QoS * Control in the header. */ @@ -3640,6 +3671,7 @@ static void ath10k_tx(struct ieee80211_hw *hw, ATH10K_SKB_CB(skb)->htt.is_offchan = false; ATH10K_SKB_CB(skb)->htt.freq = 0; ATH10K_SKB_CB(skb)->htt.tid = ath10k_tx_h_get_tid(hdr); + ATH10K_SKB_CB(skb)->htt.nohwcrypt = !ath10k_tx_h_use_hwcrypto(vif, skb); ATH10K_SKB_CB(skb)->vdev_id = ath10k_tx_h_get_vdev_id(ar, vif); ATH10K_SKB_CB(skb)->txmode = ath10k_tx_h_get_txmode(ar, vif, sta, skb); ATH10K_SKB_CB(skb)->is_protected = ieee80211_has_protected(fc); @@ -3655,9 +3687,8 @@ static void ath10k_tx(struct ieee80211_hw *hw, ath10k_tx_h_8023(skb); break; case ATH10K_HW_TXRX_RAW: - /* FIXME: Packet injection isn't implemented. It should be - * doable with firmware 10.2 on qca988x. - */ + if (ath10k_modparam_rawtxrx) + break; WARN_ON_ONCE(1); ieee80211_free_txskb(hw, skb); return; @@ -4154,6 +4185,7 @@ static int ath10k_add_interface(struct ieee80211_hw *hw, int bit; int i; u32 vdev_param; + u32 param_value; vif->driver_flags |= IEEE80211_VIF_SUPPORTS_UAPSD; @@ -4257,6 +4289,14 @@ static int ath10k_add_interface(struct ieee80211_hw *hw, } } + if (ath10k_modparam_nohwcrypt || vif->sw_crypto) + arvif->nohwcrypt = true; + + if (arvif->nohwcrypt && !ath10k_modparam_rawtxrx) { + ath10k_warn(ar, "rawtxrx module param needed for sw crypto\n"); + goto err; + } + ath10k_dbg(ar, ATH10K_DBG_MAC, "mac vdev create %d (add interface) type %d subtype %d bcnmode %s\n", arvif->vdev_id, arvif->vdev_type, arvif->vdev_subtype, arvif->beacon_buf ? "single-buf" : "per-skb"); @@ -4285,8 +4325,14 @@ static int ath10k_add_interface(struct ieee80211_hw *hw, arvif->def_wep_key_idx = -1; vdev_param = ar->wmi.vdev_param->tx_encap_type; + if (ath10k_modparam_rawtxrx) + param_value = ATH10K_HW_TXRX_RAW; + else + param_value = ATH10K_HW_TXRX_NATIVE_WIFI; + ret = ath10k_wmi_vdev_set_param(ar, arvif->vdev_id, vdev_param, - ATH10K_HW_TXRX_NATIVE_WIFI); + param_value); + /* 10.X firmware does not support this VDEV parameter. Do not warn */ if (ret && ret != -EOPNOTSUPP) { ath10k_warn(ar, "failed to set vdev %i TX encapsulation: %d\n", diff --git a/drivers/net/wireless/ath/ath10k/wmi.c b/drivers/net/wireless/ath/ath10k/wmi.c index ebaa096..d7e557b 100644 --- a/drivers/net/wireless/ath/ath10k/wmi.c +++ b/drivers/net/wireless/ath/ath10k/wmi.c @@ -507,7 +507,7 @@ static struct wmi_vdev_param_map wmi_10x_vdev_param_map = { .txbf = WMI_VDEV_PARAM_UNSUPPORTED, .packet_powersave = WMI_VDEV_PARAM_UNSUPPORTED, .drop_unencry = WMI_VDEV_PARAM_UNSUPPORTED, - .tx_encap_type = WMI_VDEV_PARAM_UNSUPPORTED, + .tx_encap_type = WMI_10X_VDEV_PARAM_TX_ENCAP_TYPE, .ap_detect_out_of_sync_sleeping_sta_time_secs = WMI_10X_VDEV_PARAM_AP_DETECT_OUT_OF_SYNC_SLEEPING_STA_TIME_SECS, }; @@ -3891,7 +3891,9 @@ static struct sk_buff *ath10k_wmi_10_2_op_gen_init(struct ath10k *ar) config.rx_timeout_pri_vi = __cpu_to_le32(TARGET_10X_RX_TIMEOUT_LO_PRI); config.rx_timeout_pri_be = __cpu_to_le32(TARGET_10X_RX_TIMEOUT_LO_PRI); config.rx_timeout_pri_bk = __cpu_to_le32(TARGET_10X_RX_TIMEOUT_HI_PRI); - config.rx_decap_mode = __cpu_to_le32(TARGET_10X_RX_DECAP_MODE); + config.rx_decap_mode = __cpu_to_le32(ATH10K_HW_TXRX_NATIVE_WIFI); + if (ath10k_modparam_rawtxrx) + config.rx_decap_mode = __cpu_to_le32(ATH10K_HW_TXRX_RAW); config.scan_max_pending_reqs = __cpu_to_le32(TARGET_10X_SCAN_MAX_PENDING_REQS); diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h index f8d6813..b41c71c 100644 --- a/include/net/cfg80211.h +++ b/include/net/cfg80211.h @@ -711,6 +711,7 @@ struct cfg80211_acl_data { * @p2p_opp_ps: P2P opportunistic PS * @acl: ACL configuration used by the drivers which has support for * MAC address based access control + * @sw_crypto: use software crypto engine.* */ struct cfg80211_ap_settings { struct cfg80211_chan_def chandef; @@ -729,6 +730,7 @@ struct cfg80211_ap_settings { u8 p2p_ctwindow; bool p2p_opp_ps; const struct cfg80211_acl_data *acl; + int sw_crypto; }; /** @@ -1210,6 +1212,7 @@ struct mpath_info { * @ap_isolate: do not forward packets between connected stations * @ht_opmode: HT Operation mode * (u16 = opmode, -1 = do not change) + * @sw_crypto: Use software crypto instead of hardware. * @p2p_ctwindow: P2P CT Window (-1 = no change) * @p2p_opp_ps: P2P opportunistic PS (-1 = no change) */ @@ -1221,6 +1224,7 @@ struct bss_parameters { u8 basic_rates_len; int ap_isolate; int ht_opmode; + int sw_crypto; s8 p2p_ctwindow, p2p_opp_ps; }; diff --git a/include/net/mac80211.h b/include/net/mac80211.h index 3314298..5f45d02 100644 --- a/include/net/mac80211.h +++ b/include/net/mac80211.h @@ -1344,6 +1344,8 @@ enum ieee80211_vif_flags { * @csa_active: marks whether a channel switch is going on. Internally it is * write-protected by sdata_lock and local->mtx so holding either is fine * for read access. + * @sw_crypto: indicates frames on the BSS should be encrypted by software + * and bypass hardware crypto engine. * @driver_flags: flags/capabilities the driver has for this interface, * these need to be set (or cleared) when the interface is added * or, if supported by the driver, the interface type is changed @@ -1368,6 +1370,7 @@ struct ieee80211_vif { u8 addr[ETH_ALEN]; bool p2p; bool csa_active; + bool sw_crypto; u8 cab_queue; u8 hw_queue[IEEE80211_NUM_ACS]; diff --git a/include/uapi/linux/nl80211.h b/include/uapi/linux/nl80211.h index 241220c..cdfa8a8 100644 --- a/include/uapi/linux/nl80211.h +++ b/include/uapi/linux/nl80211.h @@ -1761,6 +1761,9 @@ enum nl80211_commands { * @NL80211_ATTR_REG_INDOOR: flag attribute, if set indicates that the device * is operating in an indoor environment. * + * @NL80211_ATTR_SW_CRYPTO: use software crypto instead of hardware crypto for + * the BSS. + * * @NUM_NL80211_ATTR: total number of nl80211_attrs available * @NL80211_ATTR_MAX: highest attribute number currently defined * @__NL80211_ATTR_AFTER_LAST: internal use @@ -2130,6 +2133,8 @@ enum nl80211_attrs { NL80211_ATTR_REG_INDOOR, + NL80211_ATTR_SW_CRYPTO, + /* add attributes here, update the policy in nl80211.c */ __NL80211_ATTR_AFTER_LAST, diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index 72a0178..a50c9226 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c @@ -1889,6 +1889,13 @@ static int ieee80211_change_bss(struct wiphy *wiphy, sdata->flags &= ~IEEE80211_SDATA_DONT_BRIDGE_PACKETS; } + if (params->sw_crypto >= 0) { + if (params->sw_crypto) + sdata->vif.sw_crypto = true; + else + sdata->vif.sw_crypto = false; + } + if (params->ht_opmode >= 0) { sdata->vif.bss_conf.ht_operation_mode = (u16) params->ht_opmode; diff --git a/net/mac80211/wpa.c b/net/mac80211/wpa.c index 9d63d93..b56f31a 100644 --- a/net/mac80211/wpa.c +++ b/net/mac80211/wpa.c @@ -192,7 +192,9 @@ static int tkip_encrypt_skb(struct ieee80211_tx_data *tx, struct sk_buff *skb) if (info->control.hw_key && !(info->control.hw_key->flags & IEEE80211_KEY_FLAG_GENERATE_IV) && - !(info->control.hw_key->flags & IEEE80211_KEY_FLAG_PUT_IV_SPACE)) { + !(info->control.hw_key->flags & IEEE80211_KEY_FLAG_PUT_IV_SPACE) && + !(info->control.hw_key->flags & + IEEE80211_KEY_FLAG_RESERVE_TAILROOM)) { /* hwaccel - with no need for software-generated IV */ return 0; } @@ -200,7 +202,8 @@ static int tkip_encrypt_skb(struct ieee80211_tx_data *tx, struct sk_buff *skb) hdrlen = ieee80211_hdrlen(hdr->frame_control); len = skb->len - hdrlen; - if (info->control.hw_key) + if (info->control.hw_key && !(info->control.hw_key->flags & + IEEE80211_KEY_FLAG_RESERVE_TAILROOM)) tail = 0; else tail = IEEE80211_TKIP_ICV_LEN; @@ -227,8 +230,12 @@ static int tkip_encrypt_skb(struct ieee80211_tx_data *tx, struct sk_buff *skb) spin_unlock(&key->u.tkip.txlock); /* hwaccel - with software IV */ - if (info->control.hw_key) + if (info->control.hw_key) { + if (info->control.hw_key->flags & + IEEE80211_KEY_FLAG_RESERVE_TAILROOM) + skb_put(skb, tail); return 0; + } /* Add room for ICV */ skb_put(skb, IEEE80211_TKIP_ICV_LEN); @@ -411,6 +418,8 @@ static int ccmp_encrypt_skb(struct ieee80211_tx_data *tx, struct sk_buff *skb, if (info->control.hw_key && !(info->control.hw_key->flags & IEEE80211_KEY_FLAG_GENERATE_IV) && !(info->control.hw_key->flags & IEEE80211_KEY_FLAG_PUT_IV_SPACE) && + !(info->control.hw_key->flags & + IEEE80211_KEY_FLAG_RESERVE_TAILROOM) && !((info->control.hw_key->flags & IEEE80211_KEY_FLAG_GENERATE_IV_MGMT) && ieee80211_is_mgmt(hdr->frame_control))) { @@ -424,7 +433,8 @@ static int ccmp_encrypt_skb(struct ieee80211_tx_data *tx, struct sk_buff *skb, hdrlen = ieee80211_hdrlen(hdr->frame_control); len = skb->len - hdrlen; - if (info->control.hw_key) + if (info->control.hw_key && !(info->control.hw_key->flags & + IEEE80211_KEY_FLAG_RESERVE_TAILROOM)) tail = 0; else tail = mic_len; @@ -456,8 +466,12 @@ static int ccmp_encrypt_skb(struct ieee80211_tx_data *tx, struct sk_buff *skb, ccmp_pn2hdr(pos, pn, key->conf.keyidx); /* hwaccel - with software CCMP header */ - if (info->control.hw_key) + if (info->control.hw_key) { + if (info->control.hw_key->flags & + IEEE80211_KEY_FLAG_RESERVE_TAILROOM) + skb_put(skb, tail); return 0; + } pos += IEEE80211_CCMP_HDR_LEN; ccmp_special_blocks(skb, pn, b_0, aad); diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index 8a33bba..c2dea0e 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c @@ -4851,6 +4851,7 @@ static int nl80211_set_bss(struct sk_buff *skb, struct genl_info *info) params.use_short_preamble = -1; params.use_short_slot_time = -1; params.ap_isolate = -1; + params.sw_crypto = -1; params.ht_opmode = -1; params.p2p_ctwindow = -1; params.p2p_opp_ps = -1; @@ -4901,6 +4902,10 @@ static int nl80211_set_bss(struct sk_buff *skb, struct genl_info *info) !(rdev->wiphy.features & NL80211_FEATURE_P2P_GO_OPPPS)) return -EINVAL; } + if (info->attrs[NL80211_ATTR_SW_CRYPTO]) { + params.sw_crypto = + !!nla_get_u8(info->attrs[NL80211_ATTR_SW_CRYPTO]); + } if (!rdev->ops->change_bss) return -EOPNOTSUPP; diff --git a/net/wireless/trace.h b/net/wireless/trace.h index af3617c..c411a20 100644 --- a/net/wireless/trace.h +++ b/net/wireless/trace.h @@ -986,6 +986,7 @@ TRACE_EVENT(rdev_change_bss, __field(int, use_short_preamble) __field(int, use_short_slot_time) __field(int, ap_isolate) + __field(int, sw_crypto) __field(int, ht_opmode) ), TP_fast_assign( @@ -995,14 +996,16 @@ TRACE_EVENT(rdev_change_bss, __entry->use_short_preamble = params->use_short_preamble; __entry->use_short_slot_time = params->use_short_slot_time; __entry->ap_isolate = params->ap_isolate; + __entry->sw_crypto = params->sw_crypto; __entry->ht_opmode = params->ht_opmode; ), TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", use cts prot: %d, " "use short preamble: %d, use short slot time: %d, " - "ap isolate: %d, ht opmode: %d", + "ap isolate: %d, sw_crypto: %d, ht opmode: %d", WIPHY_PR_ARG, NETDEV_PR_ARG, __entry->use_cts_prot, __entry->use_short_preamble, __entry->use_short_slot_time, - __entry->ap_isolate, __entry->ht_opmode) + __entry->ap_isolate, __entry->sw_crypto, + __entry->ht_opmode) ); TRACE_EVENT(rdev_set_txq_params,