Received: by 2002:a89:48b:0:b0:1f5:f2ab:c469 with SMTP id a11csp1043873lqd; Thu, 25 Apr 2024 04:40:10 -0700 (PDT) X-Forwarded-Encrypted: i=3; AJvYcCVYF8X5XfXrKzeBYdtd49r1p02klcl3wd7q+cIj7ZHIALQvgPWPBFx/YnyH3BxBOBcx5dWUAhNcDyEWkCldY6sNRHdcHLMB8dWIi/adNA== X-Google-Smtp-Source: AGHT+IHcSFiWsZ4JfrDZllimG7Gqkc19aujPErFBUIez1fvzk1xoNPmCJrnGZFjBKX7bgzok1z27 X-Received: by 2002:a17:902:da87:b0:1e4:362b:17d5 with SMTP id j7-20020a170902da8700b001e4362b17d5mr6856399plx.4.1714045210543; Thu, 25 Apr 2024 04:40:10 -0700 (PDT) ARC-Seal: i=2; a=rsa-sha256; t=1714045210; cv=pass; d=google.com; s=arc-20160816; b=BLMZTYlNRrUQkLHITi/aRXV1FGFxJ7Ft3+GkbeoMb8JBv6mIBjGguItYLQ2hD8tAbI P4qggwV84tEZtx0IgPBoV83F2w5hTYqFPSmQ595v9T3a+ljSLn5afdPW6YhNDIerO9bY qtbXSXsQ1eS2JgB/I+mlWasrEdmNXb14BJf8IZ8SdReKbvpI0CnChjo/yS7vCot3hQ/G 0bEUSz9tyJCfUrhCoXhY4cn5p1HyWBPlFWboLfx+ha89/7X53Zx6fqzOCDLevx+b8NkA l7aC7FJwufQXUO93rwbRtxmaaDJO9lMrMBNCY8VAulyMqWlGO1atl37Hv90OAuvOUutu DkPQ== ARC-Message-Signature: i=2; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=content-transfer-encoding:mime-version:list-unsubscribe :list-subscribe:list-id:precedence:references:in-reply-to:message-id :date:subject:cc:to:from; bh=OKTw11OAnEkdkM158uoPeeleHlx2wuPnF6OdsQYyrw0=; fh=Q+3JKoLZIMN+muDUq31kjnNN0UgJXr8C3Bak/Yf/zn8=; b=SZTDvozMOpJ14/nrY7NpV0FEEt/PNjC8XBucaPSKJ0H6FVTWOya6jn7D8gYCaAzf0M NZWZEbCmIqL88R0G9HnCREFl5nL4cJaIJGk+zxSlZJRKxIDE/pOlsqMU2izaItulqXaE osI/cLScHiGCamR1Tis7bPfmwpIAqSMVru20rzLZbTZFeClxaBN42zxubke2OvErJk63 /kN6mq5O9ZQwLy1XGnqT4n4DdBVg/rKJgUTQQsUU5BsNMvrevnUrCTU41f+Vk4coIFyR kNxPelVlfXR38JvkBOvWL8PW0xUNR5wKB9OI/Z0sRm1h13LTFA8S6UNi9Yh8Noy8aIS3 RD0w==; dara=google.com ARC-Authentication-Results: i=2; mx.google.com; arc=pass (i=1 spf=pass spfdomain=realtek.com); spf=pass (google.com: domain of linux-wireless+bounces-6845-linux.lists.archive=gmail.com@vger.kernel.org designates 2604:1380:40f1:3f00::1 as permitted sender) smtp.mailfrom="linux-wireless+bounces-6845-linux.lists.archive=gmail.com@vger.kernel.org" Return-Path: Received: from sy.mirrors.kernel.org (sy.mirrors.kernel.org. [2604:1380:40f1:3f00::1]) by mx.google.com with ESMTPS id h8-20020a170902f54800b001e445481862si13468842plf.78.2024.04.25.04.40.10 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 25 Apr 2024 04:40:10 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-wireless+bounces-6845-linux.lists.archive=gmail.com@vger.kernel.org designates 2604:1380:40f1:3f00::1 as permitted sender) client-ip=2604:1380:40f1:3f00::1; Authentication-Results: mx.google.com; arc=pass (i=1 spf=pass spfdomain=realtek.com); spf=pass (google.com: domain of linux-wireless+bounces-6845-linux.lists.archive=gmail.com@vger.kernel.org designates 2604:1380:40f1:3f00::1 as permitted sender) smtp.mailfrom="linux-wireless+bounces-6845-linux.lists.archive=gmail.com@vger.kernel.org" Received: from smtp.subspace.kernel.org (wormhole.subspace.kernel.org [52.25.139.140]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by sy.mirrors.kernel.org (Postfix) with ESMTPS id 906B5B2433C for ; Thu, 25 Apr 2024 11:29:51 +0000 (UTC) Received: from localhost.localdomain (localhost.localdomain [127.0.0.1]) by smtp.subspace.kernel.org (Postfix) with ESMTP id F318783CCD; Thu, 25 Apr 2024 11:29:39 +0000 (UTC) X-Original-To: linux-wireless@vger.kernel.org Received: from rtits2.realtek.com.tw (rtits2.realtek.com [211.75.126.72]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 2CD0612A177 for ; Thu, 25 Apr 2024 11:29:37 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=211.75.126.72 ARC-Seal:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1714044579; cv=none; b=Gfw529JhY4DLsy0UtuCE43f8ah0QAAJXWWlsiBbg6+L5ghRClpw/1cLux/XUsDPoN7WW8d+hTjULuOBrjWefSN2g8Vl6mEvP+oNmv01P3UPYnEl/KJy8s22CSXt6bapyB/oqk5WgkIvv/DXRw+QgrPbkoEuubIeMJb/uaFl9IPU= ARC-Message-Signature:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1714044579; c=relaxed/simple; bh=Y12EvOeEJLOlFzrIANMotfbZ4QSqef+wz2fX7hCMjqg=; h=From:To:CC:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=rlhA0Rbdv3asDRj528JFQBBCXYTU5h5wz3iLVZ1r95bjxXAciUHQh13wxgESTok6I1lCYlTbUulJHAFXKGw45kAqHalJ53jEuLHOUoQoaCEZybMNuKvK/CtyKAPmMErZQoVKZ1R7KAhRcmKv8Asom10hxFqT6daGiH2rGodxV9c= ARC-Authentication-Results:i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=realtek.com; spf=pass smtp.mailfrom=realtek.com; arc=none smtp.client-ip=211.75.126.72 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=realtek.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=realtek.com X-SpamFilter-By: ArmorX SpamTrap 5.78 with qID 43PBTaqbE3482377, This message is accepted by code: ctloc85258 Received: from mail.realtek.com (rtexh36505.realtek.com.tw[172.21.6.25]) by rtits2.realtek.com.tw (8.15.2/2.95/5.92) with ESMTPS id 43PBTaqbE3482377 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK) for ; Thu, 25 Apr 2024 19:29:36 +0800 Received: from RTEXMBS04.realtek.com.tw (172.21.6.97) by RTEXH36505.realtek.com.tw (172.21.6.25) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.1.2507.35; Thu, 25 Apr 2024 19:29:36 +0800 Received: from [127.0.1.1] (172.16.16.129) by RTEXMBS04.realtek.com.tw (172.21.6.97) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.1.2507.35; Thu, 25 Apr 2024 19:29:35 +0800 From: Ping-Ke Shih To: CC: , Subject: [PATCH 12/12] wifi: rtw89: wow: add ARP offload feature Date: Thu, 25 Apr 2024 19:28:16 +0800 Message-ID: <20240425112816.26431-13-pkshih@realtek.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20240425112816.26431-1-pkshih@realtek.com> References: <20240425112816.26431-1-pkshih@realtek.com> Precedence: bulk X-Mailing-List: linux-wireless@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: 8bit Content-Type: text/plain X-ClientProxiedBy: RTEXMBS02.realtek.com.tw (172.21.6.95) To RTEXMBS04.realtek.com.tw (172.21.6.97) X-KSE-ServerInfo: RTEXH36505.realtek.com.tw, 9 X-KSE-AntiSpam-Interceptor-Info: fallback X-KSE-Antivirus-Interceptor-Info: fallback X-KSE-AntiSpam-Interceptor-Info: fallback From: Chin-Yen Lee Add H2C command and offload template packet to allow firmware send ARP response in WoWLAN mode. Then, firmware in WoWLAN mode can interactive with peer that issue ARP request to query MAC address. Signed-off-by: Chin-Yen Lee Signed-off-by: Ping-Ke Shih --- drivers/net/wireless/realtek/rtw89/core.h | 1 + drivers/net/wireless/realtek/rtw89/fw.c | 108 ++++++++++++++++++ drivers/net/wireless/realtek/rtw89/fw.h | 14 +++ drivers/net/wireless/realtek/rtw89/mac80211.c | 3 + drivers/net/wireless/realtek/rtw89/wow.c | 8 ++ 5 files changed, 134 insertions(+) diff --git a/drivers/net/wireless/realtek/rtw89/core.h b/drivers/net/wireless/realtek/rtw89/core.h index 1aa25a3f3659..e03645bb27b7 100644 --- a/drivers/net/wireless/realtek/rtw89/core.h +++ b/drivers/net/wireless/realtek/rtw89/core.h @@ -3341,6 +3341,7 @@ struct rtw89_vif { u8 port; u8 mac_addr[ETH_ALEN]; u8 bssid[ETH_ALEN]; + __be32 ip_addr; u8 phy_idx; u8 mac_idx; u8 net_type; diff --git a/drivers/net/wireless/realtek/rtw89/fw.c b/drivers/net/wireless/realtek/rtw89/fw.c index 444badc3eede..044a5b90c7f4 100644 --- a/drivers/net/wireless/realtek/rtw89/fw.c +++ b/drivers/net/wireless/realtek/rtw89/fw.c @@ -2,6 +2,7 @@ /* Copyright(c) 2019-2020 Realtek Corporation */ +#include #include "cam.h" #include "chan.h" #include "coex.h" @@ -26,6 +27,17 @@ struct rtw89_sa_query { u8 action; } __packed __aligned(2); +struct rtw89_arp_rsp { + struct ieee80211_hdr_3addr addr; + u8 llc_hdr[sizeof(rfc1042_header)]; + __be16 llc_type; + struct arphdr arp_hdr; + u8 sender_hw[ETH_ALEN]; + __be32 sender_ip; + u8 target_hw[ETH_ALEN]; + __be32 target_ip; +} __packed __aligned(2); + static const u8 mss_signature[] = {0x4D, 0x53, 0x53, 0x4B, 0x50, 0x4F, 0x4F, 0x4C}; union rtw89_fw_element_arg { @@ -2223,6 +2235,48 @@ static struct sk_buff *rtw89_sa_query_get(struct rtw89_dev *rtwdev, return skb; } +static struct sk_buff *rtw89_arp_response_get(struct rtw89_dev *rtwdev, + struct rtw89_vif *rtwvif) +{ + struct rtw89_wow_param *rtw_wow = &rtwdev->wow; + struct rtw89_arp_rsp *arp_skb; + struct arphdr *arp_hdr; + struct sk_buff *skb; + __le16 fc; + + skb = dev_alloc_skb(sizeof(struct rtw89_arp_rsp)); + if (!skb) + return NULL; + + arp_skb = skb_put_zero(skb, sizeof(*arp_skb)); + + if (rtw_wow->ptk_alg) + fc = cpu_to_le16(IEEE80211_FTYPE_DATA | IEEE80211_FCTL_TODS | + IEEE80211_FCTL_PROTECTED); + else + fc = cpu_to_le16(IEEE80211_FTYPE_DATA | IEEE80211_FCTL_TODS); + + arp_skb->addr.frame_control = fc; + ether_addr_copy(arp_skb->addr.addr1, rtwvif->bssid); + ether_addr_copy(arp_skb->addr.addr2, rtwvif->mac_addr); + ether_addr_copy(arp_skb->addr.addr3, rtwvif->bssid); + + memcpy(arp_skb->llc_hdr, rfc1042_header, sizeof(rfc1042_header)); + arp_skb->llc_type = htons(ETH_P_ARP); + + arp_hdr = &arp_skb->arp_hdr; + arp_hdr->ar_hrd = htons(ARPHRD_ETHER); + arp_hdr->ar_pro = htons(ETH_P_IP); + arp_hdr->ar_hln = ETH_ALEN; + arp_hdr->ar_pln = 4; + arp_hdr->ar_op = htons(ARPOP_REPLY); + + ether_addr_copy(arp_skb->sender_hw, rtwvif->mac_addr); + arp_skb->sender_ip = rtwvif->ip_addr; + + return skb; +} + static int rtw89_fw_h2c_add_general_pkt(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif, enum rtw89_fw_pkt_ofld_type type, @@ -2256,6 +2310,9 @@ static int rtw89_fw_h2c_add_general_pkt(struct rtw89_dev *rtwdev, case RTW89_PKT_OFLD_TYPE_SA_QUERY: skb = rtw89_sa_query_get(rtwdev, rtwvif); break; + case RTW89_PKT_OFLD_TYPE_ARP_RSP: + skb = rtw89_arp_response_get(rtwdev, rtwvif); + break; default: goto err; } @@ -6390,6 +6447,57 @@ int rtw89_fw_h2c_keep_alive(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif, return ret; } +int rtw89_fw_h2c_arp_offload(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif, + bool enable) +{ + struct rtw89_h2c_arp_offload *h2c; + u32 len = sizeof(*h2c); + struct sk_buff *skb; + u8 pkt_id = 0; + int ret; + + if (enable) { + ret = rtw89_fw_h2c_add_general_pkt(rtwdev, rtwvif, + RTW89_PKT_OFLD_TYPE_ARP_RSP, + &pkt_id); + if (ret) + return ret; + } + + skb = rtw89_fw_h2c_alloc_skb_with_hdr(rtwdev, len); + if (!skb) { + rtw89_err(rtwdev, "failed to alloc skb for arp offload\n"); + return -ENOMEM; + } + + skb_put(skb, len); + h2c = (struct rtw89_h2c_arp_offload *)skb->data; + + h2c->w0 = le32_encode_bits(enable, RTW89_H2C_ARP_OFFLOAD_W0_ENABLE) | + le32_encode_bits(0, RTW89_H2C_ARP_OFFLOAD_W0_ACTION) | + le32_encode_bits(rtwvif->mac_id, RTW89_H2C_ARP_OFFLOAD_W0_MACID) | + le32_encode_bits(pkt_id, RTW89_H2C_ARP_OFFLOAD_W0_PKT_ID); + + rtw89_h2c_pkt_set_hdr(rtwdev, skb, FWCMD_TYPE_H2C, + H2C_CAT_MAC, + H2C_CL_MAC_WOW, + H2C_FUNC_ARP_OFLD, 0, 1, + len); + + ret = rtw89_h2c_tx(rtwdev, skb, false); + if (ret) { + rtw89_err(rtwdev, "failed to send h2c\n"); + goto fail; + } + + return 0; + +fail: + dev_kfree_skb_any(skb); + + return ret; +} + #define H2C_DISCONNECT_DETECT_LEN 8 int rtw89_fw_h2c_disconnect_detect(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif, bool enable) diff --git a/drivers/net/wireless/realtek/rtw89/fw.h b/drivers/net/wireless/realtek/rtw89/fw.h index 5e51267558ad..4151c9d566bd 100644 --- a/drivers/net/wireless/realtek/rtw89/fw.h +++ b/drivers/net/wireless/realtek/rtw89/fw.h @@ -2025,6 +2025,17 @@ struct rtw89_h2c_wow_gtk_ofld { #define RTW89_H2C_WOW_GTK_OFLD_W1_PMF_BIP_SEC_ALGO GENMASK(9, 8) #define RTW89_H2C_WOW_GTK_OFLD_W1_ALGO_AKM_SUIT GENMASK(17, 10) +struct rtw89_h2c_arp_offload { + __le32 w0; + __le32 w1; +} __packed; + +#define RTW89_H2C_ARP_OFFLOAD_W0_ENABLE BIT(0) +#define RTW89_H2C_ARP_OFFLOAD_W0_ACTION BIT(1) +#define RTW89_H2C_ARP_OFFLOAD_W0_MACID GENMASK(23, 16) +#define RTW89_H2C_ARP_OFFLOAD_W0_PKT_ID GENMASK(31, 24) +#define RTW89_H2C_ARP_OFFLOAD_W1_CONTENT GENMASK(31, 0) + enum rtw89_btc_btf_h2c_class { BTFC_SET = 0x10, BTFC_GET = 0x11, @@ -3919,6 +3930,7 @@ enum rtw89_wow_h2c_func { H2C_FUNC_DISCONNECT_DETECT = 0x1, H2C_FUNC_WOW_GLOBAL = 0x2, H2C_FUNC_GTK_OFLD = 0x3, + H2C_FUNC_ARP_OFLD = 0x4, H2C_FUNC_WAKEUP_CTRL = 0x8, H2C_FUNC_WOW_CAM_UPD = 0xC, H2C_FUNC_AOAC_REPORT_REQ = 0xD, @@ -4436,6 +4448,8 @@ int rtw89_fw_h2c_wow_wakeup_ctrl(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif, bool enable); int rtw89_fw_h2c_keep_alive(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif, bool enable); +int rtw89_fw_h2c_arp_offload(struct rtw89_dev *rtwdev, + struct rtw89_vif *rtwvif, bool enable); int rtw89_fw_h2c_disconnect_detect(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif, bool enable); int rtw89_fw_h2c_wow_global(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif, diff --git a/drivers/net/wireless/realtek/rtw89/mac80211.c b/drivers/net/wireless/realtek/rtw89/mac80211.c index 2fd23f79544d..ca4938eed23c 100644 --- a/drivers/net/wireless/realtek/rtw89/mac80211.c +++ b/drivers/net/wireless/realtek/rtw89/mac80211.c @@ -473,6 +473,9 @@ static void rtw89_ops_bss_info_changed(struct ieee80211_hw *hw, if (changed & BSS_CHANGED_PS) rtw89_recalc_lps(rtwdev); + if (changed & BSS_CHANGED_ARP_FILTER) + rtwvif->ip_addr = vif->cfg.arp_addr_list[0]; + mutex_unlock(&rtwdev->mutex); } diff --git a/drivers/net/wireless/realtek/rtw89/wow.c b/drivers/net/wireless/realtek/rtw89/wow.c index 434b29ae8ae9..fa61484c3839 100644 --- a/drivers/net/wireless/realtek/rtw89/wow.c +++ b/drivers/net/wireless/realtek/rtw89/wow.c @@ -1320,6 +1320,10 @@ static int rtw89_wow_fw_start(struct rtw89_dev *rtwdev) goto out; } + ret = rtw89_fw_h2c_arp_offload(rtwdev, rtwvif, true); + if (ret) + rtw89_warn(rtwdev, "wow: failed to enable arp offload\n"); + ret = rtw89_wow_cfg_wake(rtwdev, true); if (ret) { rtw89_err(rtwdev, "wow: failed to config wake\n"); @@ -1362,6 +1366,10 @@ static int rtw89_wow_fw_stop(struct rtw89_dev *rtwdev) goto out; } + ret = rtw89_fw_h2c_arp_offload(rtwdev, rtwvif, false); + if (ret) + rtw89_warn(rtwdev, "wow: failed to disable arp offload\n"); + rtw89_wow_key_clear(rtwdev); rtw89_fw_release_general_pkt_list(rtwdev, true); -- 2.25.1