From da6d60c72fe2a23a0fd0fd44860c91f0ce5c3a88 Mon Sep 17 00:00:00 2001 From: "Bisht Kshitij (IFINS CSS ICW ENG SW WFSW 1)" Date: Fri, 31 Mar 2023 15:01:43 +0000 Subject: [PATCH 183/296] brcmfmac: offload: add configuration infrastructure support using mod param Provide offload infrastructure support using user driven power profile from host if offload infra is implemented in firmware to start all the offloads in a preset configuration. Below mentioned module params can be set during insmod, offload_prof - 1:LOW / 2:MID / 3:HIGH power offload_feat - list of all offloads for default (LOW power) or user configured power profile. Ex: ARP, ND, GTKOE, WOWLPF etc... User doesn't have to configure parameters of different offload but only have to provide a suitable power profile which will enable all the required offloads in their preset configurations. It can also activate or deactivate the offload according to the "suspend or resume" host power. An offload may remain activated depending on the power profile. Signed-off-by: Bisht Kshitij (IFINS CSS ICW ENG SW WFSW 1) Signed-off-by: Shelley Yang --- .../broadcom/brcm80211/brcmfmac/cfg80211.c | 40 +++++- .../broadcom/brcm80211/brcmfmac/common.c | 130 ++++++++++++++++++ .../broadcom/brcm80211/brcmfmac/common.h | 13 ++ .../broadcom/brcm80211/brcmfmac/core.c | 113 ++++++++------- .../broadcom/brcm80211/brcmfmac/feature.c | 10 ++ .../broadcom/brcm80211/brcmfmac/feature.h | 19 ++- .../broadcom/brcm80211/brcmfmac/fwil_types.h | 82 +++++++++++ 7 files changed, 356 insertions(+), 51 deletions(-) diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c index a81294208849..59d03c38afff 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c @@ -4705,6 +4705,12 @@ static s32 brcmf_cfg80211_resume(struct wiphy *wiphy) brcmf_pktfilter_enable(ifp->ndev, false); } + /* During resume, disable all offload modules which are enabled + * previously while entering suspend. + */ + if (brcmf_feat_is_enabled(ifp, BRCMF_FEAT_OFFLOADS)) + brcmf_generic_offload_enable(ifp, brcmf_offload_feat, false); + config->pm_state = BRCMF_CFG80211_PM_STATE_RESUMED; return 0; } @@ -4812,6 +4818,13 @@ static s32 brcmf_cfg80211_suspend(struct wiphy *wiphy, if (test_bit(BRCMF_SCAN_STATUS_BUSY, &cfg->scan_status)) brcmf_abort_scanning(cfg); + /* Enable offload features that were not in default (LOW) or user selected + * power profile but should be offloaded to fw in suspend as host goes to + * sleep. These will be disabled on resume. + */ + if (brcmf_feat_is_enabled(ifp, BRCMF_FEAT_OFFLOADS)) + brcmf_generic_offload_enable(ifp, brcmf_offload_feat, true); + if (!wowl || !test_bit(BRCMF_VIF_STATUS_CONNECTED, &ifp->vif->sme_state)) { brcmf_bus_wowl_config(cfg->pub->bus_if, false); @@ -4840,6 +4853,8 @@ static s32 brcmf_cfg80211_suspend(struct wiphy *wiphy, /* Prevent disassociation due to inactivity with keep-alive */ brcmf_keepalive_start(ifp, 30); } + if (brcmf_feat_is_enabled(ifp, BRCMF_FEAT_OFFLOADS)) + brcmf_generic_offload_enable(ifp, BRCMF_OL_WOWLPF, true); } exit: @@ -9690,6 +9705,7 @@ static s32 brcmf_config_dongle(struct brcmf_cfg80211_info *cfg) s32 power_mode; s32 eap_restrict; s32 err = 0; + u32 wowl_config = 0; if (cfg->dongle_up) return err; @@ -9726,7 +9742,22 @@ static s32 brcmf_config_dongle(struct brcmf_cfg80211_info *cfg) if (err) goto default_conf_out; - brcmf_configure_arp_nd_offload(ifp, true); + /* Configure user based power profile for offloads. + * Default profile is LOW_PWR. + */ + if (brcmf_feat_is_enabled(ifp, BRCMF_FEAT_OFFLOADS)) { + brcmf_generic_offload_config(ifp, brcmf_offload_feat, + brcmf_offload_prof, false); + + if (brcmf_feat_is_enabled(ifp, BRCMF_FEAT_ULP)) { + wowl_config = BRCMF_WOWL_DIS | BRCMF_WOWL_BCN; + err = brcmf_fil_iovar_int_set(ifp, "wowl", wowl_config); + if (err < 0) + brcmf_err("wowl_flags DIS,BCN not set"); + } + } else { + brcmf_configure_arp_nd_offload(ifp, true); + } err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_FAKEFRAG, 1); if (err) { @@ -9752,6 +9783,13 @@ static s32 __brcmf_cfg80211_down(struct brcmf_if *ifp) { struct brcmf_cfg80211_info *cfg = ifp->drvr->config; + /* Disable all offloads started on brcmf_config_dongle before + * link is brought down. + */ + if (brcmf_feat_is_enabled(ifp, BRCMF_FEAT_OFFLOADS)) + brcmf_generic_offload_config(ifp, brcmf_offload_feat, + brcmf_offload_prof, true); + /* * While going down, if associated with AP disassociate * from AP to save power diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c index 20b2cf21894d..b68b29d005d0 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c @@ -108,6 +108,25 @@ static int brcmf_sdio_rxf_in_kthread; module_param_named(sdio_rxf_thread, brcmf_sdio_rxf_in_kthread, int, 0400); MODULE_PARM_DESC(sdio_rxf_thread, "SDIO RX Frame in Kthread"); +unsigned int brcmf_offload_prof = BRCMF_OL_PROF_TYPE_LOW_PWR; +module_param_named(offload_prof, brcmf_offload_prof, uint, 0400); +MODULE_PARM_DESC(offload_prof, + "Offload power profile: 1:low 2:mid 3:high (default:1)"); + +unsigned int brcmf_offload_feat = BRCMF_OL_ARP | + BRCMF_OL_ND | + BRCMF_OL_BDO | + BRCMF_OL_ICMP | + BRCMF_OL_TKO | + BRCMF_OL_DLTRO | + BRCMF_OL_PNO | + BRCMF_OL_KEEPALIVE | + BRCMF_OL_GTKOE; +module_param_named(offload_feat, brcmf_offload_feat, uint, 0400); +MODULE_PARM_DESC(offload_feat, + "Offload feat bitmap: 0:arp 1:nd 2:mdns 3:icmp 4:tcp-keepalive " + "5:dhcp-renewal 6:pno 7:keepalive 8:gtk 9:wowlpf (default: 0x1FF)"); + static struct brcmfmac_platform_data *brcmfmac_pdata; struct brcmf_mp_global_t brcmf_mp_global; @@ -117,6 +136,109 @@ static struct notifier_block brcmf_reboot_notifier = { .priority = 1, }; +/* Offload features to firmware based on a user based power profile using module param + * offload_prof and offload_feat (provides flag list of all offloads). + * Default power profile : LowPwr with all offloads enabled. + */ +void brcmf_generic_offload_config(struct brcmf_if *ifp, unsigned int ol_feat, + unsigned int ol_profile, bool reset) +{ + struct brcmf_ol_cfg_v1 ol_cfg = {0}; + u32 ol_feat_skip = ~ol_feat; + int err = 0; + + ol_cfg.ver = BRCMF_OL_CFG_VER_1; + ol_cfg.len = sizeof(ol_cfg); + ol_cfg.id = BRCMF_OL_CFG_ID_PROF; + ol_cfg.offload_skip = ol_feat_skip; + ol_cfg.u.ol_profile.reset = reset; + ol_cfg.u.ol_profile.type = ol_profile; + + err = brcmf_fil_iovar_data_set(ifp, "offload_config", &ol_cfg, + sizeof(ol_cfg)); + if (err < 0) + brcmf_err("failed to %s generic offload profile:%u feat:0x%x, err = %d", + reset ? "reset" : "set", ol_profile, ol_feat, err); + else + brcmf_info("successfully %s generic offload profile:%u feat:0x%x", + reset ? "reset" : "set", ol_profile, ol_feat); +} + +/* Enable specific offloads that are not enabled in a power profile but have + * to be enabled in suspend state as host goes to sleep. + */ +void brcmf_generic_offload_enable(struct brcmf_if *ifp, unsigned int ol_feat, + bool enable) +{ + struct brcmf_ol_cfg_v1 ol_cfg = {0}; + u32 ol_feat_skip = ~ol_feat; + int err = 0; + + ol_cfg.ver = BRCMF_OL_CFG_VER_1; + ol_cfg.len = sizeof(ol_cfg); + ol_cfg.id = BRCMF_OL_CFG_ID_ACTIVATE; + ol_cfg.u.ol_activate.enable = enable; + ol_cfg.offload_skip = ol_feat_skip; + + err = brcmf_fil_iovar_data_set(ifp, "offload_config", &ol_cfg, + sizeof(ol_cfg)); + if (err < 0) + brcmf_err("failed to %s generic offload feat:0x%x, err = %d", + enable ? "enable" : "disable", ol_feat, err); + else + brcmf_info("successfully %s generic offload feat:0x%x", + enable ? "enabled" : "disabled", ol_feat); +} + +void brcmf_generic_offload_host_ipv4_update(struct brcmf_if *ifp, unsigned int ol_feat, + u32 ipaddr, bool is_add) +{ + struct brcmf_ol_cfg_v1 ol_cfg = {0}; + u32 ol_feat_skip = ~ol_feat; + int err = 0; + + ol_cfg.ver = BRCMF_OL_CFG_VER_1; + ol_cfg.len = sizeof(ol_cfg); + ol_cfg.id = BRCMF_OL_CFG_ID_INET_V4; + ol_cfg.u.ol_inet_v4.del = !is_add; + memcpy(ol_cfg.u.ol_inet_v4.host_ipv4.addr, &ipaddr, sizeof(struct ipv4_addr)); + ol_cfg.offload_skip = ol_feat_skip; + + err = brcmf_fil_iovar_data_set(ifp, "offload_config", &ol_cfg, + sizeof(ol_cfg)); + if (err < 0) + brcmf_err("failed to %s generic offload host address %pI4, err = %d", + is_add ? "add" : "del", &ipaddr, err); + else + brcmf_dbg(TRACE, "successfully %s generic offload host address %pI4", + is_add ? "added" : "deleted", &ipaddr); +} + +void brcmf_generic_offload_host_ipv6_update(struct brcmf_if *ifp, unsigned int ol_feat, + void *ptr, u8 type, bool is_add) +{ + struct brcmf_ol_cfg_v1 ol_cfg = {0}; + u32 ol_feat_skip = ~ol_feat; + int err = 0; + + ol_cfg.ver = BRCMF_OL_CFG_VER_1; + ol_cfg.len = sizeof(ol_cfg); + ol_cfg.id = BRCMF_OL_CFG_ID_INET_V6; + ol_cfg.u.ol_inet_v6.del = !is_add; + ol_cfg.u.ol_inet_v6.type = type; + memcpy(ol_cfg.u.ol_inet_v6.host_ipv6.addr, ptr, sizeof(struct ipv6_addr)); + ol_cfg.offload_skip = ol_feat_skip; + + err = brcmf_fil_iovar_data_set(ifp, "offload_config", &ol_cfg, + sizeof(ol_cfg)); + if (err < 0) + brcmf_err("failed to %s host address %pI6 err = %d", + is_add ? "add" : "del", ptr, err); + else + brcmf_dbg(TRACE, "successfully %s host address %pI6", + is_add ? "add" : "del", ptr); +} + void brcmf_c_set_joinpref_default(struct brcmf_if *ifp) { struct brcmf_pub *drvr = ifp->drvr; @@ -633,6 +755,14 @@ struct brcmf_mp_device *brcmf_get_module_param(struct device *dev, settings->pkt_prio = !!brcmf_pkt_prio_enable; settings->sdio_rxf_in_kthread_enabled = !!brcmf_sdio_rxf_in_kthread; + if (brcmf_offload_prof >= BRCMF_OL_PROF_TYPE_MAX) { + brcmf_err("Invalid Offload power profile %u, using default profile 1", + brcmf_offload_prof); + brcmf_offload_prof = BRCMF_OL_PROF_TYPE_LOW_PWR; + } + settings->offload_prof = brcmf_offload_prof; + settings->offload_feat = brcmf_offload_feat; + if (bus_type == BRCMF_BUSTYPE_SDIO) settings->bus.sdio.txglomsz = brcmf_sdiod_txglomsz; diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.h b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.h index 8a6657ab011a..5a32f64a462e 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.h +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.h @@ -44,6 +44,8 @@ extern struct brcmf_mp_global_t brcmf_mp_global; * @fw_ap_select: Allow FW to select AP. * @disable_6ghz: Disable 6GHz operation * @sdio_in_isr: Handle SDIO DPC in ISR. + * @offload_prof: Enable offloads configuration power profile (Low,Mid,High) + * @offload_feat: offloads feature flags to be enabled for selected pwr profile * @country_codes: If available, pointer to struct for translating country codes * @bus: Bus specific platform data. Only SDIO at the mmoment. * @pkt_prio: Support customer dscp to WMM up mapping. @@ -62,6 +64,8 @@ struct brcmf_mp_device { bool disable_6ghz; bool sdio_in_isr; bool sdio_rxf_in_kthread_enabled; + unsigned int offload_prof; + unsigned int offload_feat; struct brcmfmac_pd_cc *country_codes; const char *board_type; unsigned char mac[ETH_ALEN]; @@ -105,4 +109,13 @@ u8 brcmf_map_prio_to_prec(void *cfg, u8 prio); u8 brcmf_map_prio_to_aci(void *cfg, u8 prio); +void brcmf_generic_offload_config(struct brcmf_if *ifp, unsigned int ol_feat, + unsigned int ol_profile, bool reset); +void brcmf_generic_offload_enable(struct brcmf_if *ifp, unsigned int ol_feat, + bool enable); +void brcmf_generic_offload_host_ipv4_update(struct brcmf_if *ifp, unsigned int ol_feat, + u32 ipaddr, bool is_add); +void brcmf_generic_offload_host_ipv6_update(struct brcmf_if *ifp, unsigned int ol_feat, + void *ptr, u8 type, bool is_add); + #endif /* BRCMFMAC_COMMON_H */ diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c index f20c3953fd74..cc80a80c2a61 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c @@ -1314,7 +1314,7 @@ static int brcmf_inetaddr_changed(struct notifier_block *nb, struct in_ifaddr *ifa = data; struct net_device *ndev = ifa->ifa_dev->dev; struct brcmf_if *ifp; - int idx, i, ret; + int idx, i = 0, ret; u32 val; __be32 addr_table[ARPOL_MAX_ENTRIES] = {0}; @@ -1327,64 +1327,79 @@ static int brcmf_inetaddr_changed(struct notifier_block *nb, return NOTIFY_DONE; } - /* check if arp offload is supported */ - ret = brcmf_fil_iovar_int_get(ifp, "arpoe", &val); - if (ret) - return NOTIFY_OK; + if (!brcmf_feat_is_enabled(ifp, BRCMF_FEAT_OFFLOADS)) { + /* check if arp offload is supported */ + ret = brcmf_fil_iovar_int_get(ifp, "arpoe", &val); + if (ret) + return NOTIFY_OK; - /* old version only support primary index */ - ret = brcmf_fil_iovar_int_get(ifp, "arp_version", &val); - if (ret) - val = 1; - if (val == 1) - ifp = drvr->iflist[0]; + /* old version only support primary index */ + ret = brcmf_fil_iovar_int_get(ifp, "arp_version", &val); + if (ret) + val = 1; + if (val == 1) + ifp = drvr->iflist[0]; - /* retrieve the table from firmware */ - ret = brcmf_fil_iovar_data_get(ifp, "arp_hostip", addr_table, - sizeof(addr_table)); - if (ret) { - bphy_err(drvr, "fail to get arp ip table err:%d\n", ret); - return NOTIFY_OK; - } + /* retrieve the table from firmware */ + ret = brcmf_fil_iovar_data_get(ifp, "arp_hostip", addr_table, + sizeof(addr_table)); + if (ret) { + bphy_err(drvr, "fail to get arp ip table err:%d\n", ret); + return NOTIFY_OK; + } - for (i = 0; i < ARPOL_MAX_ENTRIES; i++) - if (ifa->ifa_address == addr_table[i]) - break; + for (i = 0; i < ARPOL_MAX_ENTRIES; i++) + if (ifa->ifa_address == addr_table[i]) + break; + } switch (action) { case NETDEV_UP: - if (i == ARPOL_MAX_ENTRIES) { - brcmf_dbg(TRACE, "add %pI4 to arp table\n", - &ifa->ifa_address); - /* set it directly */ - ret = brcmf_fil_iovar_data_set(ifp, "arp_hostip", - &ifa->ifa_address, sizeof(ifa->ifa_address)); - if (ret) - bphy_err(drvr, "add arp ip err %d\n", ret); + if (brcmf_feat_is_enabled(ifp, BRCMF_FEAT_OFFLOADS)) { + brcmf_generic_offload_host_ipv4_update(ifp, + BRCMF_OL_ARP | BRCMF_OL_ICMP, + ifa->ifa_address, true); + } else { + if (i == ARPOL_MAX_ENTRIES) { + brcmf_dbg(TRACE, "add %pI4 to arp table\n", + &ifa->ifa_address); + /* set it directly */ + ret = brcmf_fil_iovar_data_set(ifp, "arp_hostip", + &ifa->ifa_address, + sizeof(ifa->ifa_address)); + if (ret) + bphy_err(drvr, "add arp ip err %d\n", ret); + } } break; case NETDEV_DOWN: - if (i < ARPOL_MAX_ENTRIES) { - addr_table[i] = 0; - brcmf_dbg(TRACE, "remove %pI4 from arp table\n", - &ifa->ifa_address); - /* clear the table in firmware */ - ret = brcmf_fil_iovar_data_set(ifp, "arp_hostip_clear", - NULL, 0); - if (ret) { - bphy_err(drvr, "fail to clear arp ip table err:%d\n", - ret); - return NOTIFY_OK; - } - for (i = 0; i < ARPOL_MAX_ENTRIES; i++) { - if (addr_table[i] == 0) - continue; - ret = brcmf_fil_iovar_data_set(ifp, "arp_hostip", - &addr_table[i], - sizeof(addr_table[i])); - if (ret) - bphy_err(drvr, "add arp ip err %d\n", + if (brcmf_feat_is_enabled(ifp, BRCMF_FEAT_OFFLOADS)) { + brcmf_generic_offload_host_ipv4_update(ifp, + BRCMF_OL_ARP | BRCMF_OL_ICMP, + ifa->ifa_address, false); + } else { + if (i < ARPOL_MAX_ENTRIES) { + addr_table[i] = 0; + brcmf_dbg(TRACE, "remove %pI4 from arp table\n", + &ifa->ifa_address); + /* clear the table in firmware */ + ret = brcmf_fil_iovar_data_set(ifp, "arp_hostip_clear", + NULL, 0); + if (ret) { + bphy_err(drvr, "fail to clear arp ip table err:%d\n", ret); + return NOTIFY_OK; + } + for (i = 0; i < ARPOL_MAX_ENTRIES; i++) { + if (addr_table[i] == 0) + continue; + ret = brcmf_fil_iovar_data_set(ifp, "arp_hostip", + &addr_table[i], + sizeof(addr_table[i])); + if (ret) + bphy_err(drvr, "add arp ip err %d\n", + ret); + } } } break; diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/feature.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/feature.c index 56a66b978c58..f5e90025a892 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/feature.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/feature.c @@ -48,6 +48,8 @@ static const struct brcmf_feat_fwcap brcmf_fwcap_map[] = { { BRCMF_FEAT_FBT, "fbt " }, { BRCMF_FEAT_OKC, "okc" }, { BRCMF_FEAT_GCMP, "gcmp" }, + { BRCMF_FEAT_OFFLOADS, "offloads" }, + { BRCMF_FEAT_ULP, "ulp" }, }; #ifdef DEBUG @@ -422,3 +424,11 @@ bool brcmf_feat_is_sdio_rxf_in_kthread(struct brcmf_pub *drvr) else return false; } + +bool brcmf_feat_is_offloads_enabled(struct brcmf_if *ifp) +{ + if (ifp && ifp->drvr) + return ifp->drvr->settings->offload_prof; + + return false; +} diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/feature.h b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/feature.h index eceee1129d18..a91554883601 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/feature.h +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/feature.h @@ -34,6 +34,11 @@ * SAE_EXT: SAE be handled by userspace supplicant * GCMP: firmware has defined GCMP or not. * TWT: Firmware has the TWT Module Support. + * OFFLOADS: Firmware can do the packet processing work offloaded by + * Host Driver, i.e, it can process specifc types of RX packets like + * ARP, ND, etc and send out a suitable response packet from within + * Firmware. + * ULP: Firmware supports Ultra Low Power mode of operation. */ #define BRCMF_FEAT_LIST \ BRCMF_FEAT_DEF(MBSS) \ @@ -65,7 +70,9 @@ BRCMF_FEAT_DEF(FBT) \ BRCMF_FEAT_DEF(OKC) \ BRCMF_FEAT_DEF(GCMP) \ - BRCMF_FEAT_DEF(TWT) + BRCMF_FEAT_DEF(TWT) \ + BRCMF_FEAT_DEF(OFFLOADS) \ + BRCMF_FEAT_DEF(ULP) /* * Quirks: @@ -150,4 +157,14 @@ bool brcmf_feat_is_6ghz_enabled(struct brcmf_if *ifp); */ bool brcmf_feat_is_sdio_rxf_in_kthread(struct brcmf_pub *drvr); +/** + * brcmf_feat_is_offloads_enabled() - Find if offload_prof power profile + * is given by user + * + * @ifp: interface instance. + * + * Return: true if offloads_prof is set otherwise false. + */ +bool brcmf_feat_is_offloads_enabled(struct brcmf_if *ifp); + #endif /* _BRCMF_FEATURE_H */ diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwil_types.h b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwil_types.h index d973d053b4a7..07a93445012b 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwil_types.h +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwil_types.h @@ -145,6 +145,11 @@ #define BRCMF_WOWL_MAXPATTERNS 16 #define BRCMF_WOWL_MAXPATTERNSIZE 128 +/* IPV4 address length */ +#define BRCMF_IPV4_ADDR_LEN 4 +/* IPV6 address length */ +#define BRCMF_IPV6_ADDR_LEN 16 + enum { BRCMF_UNICAST_FILTER_NUM = 0, BRCMF_BROADCAST_FILTER_NUM, @@ -217,6 +222,43 @@ enum { #define WL_RSSI_EVENT_BRCM_VERSION 0 #define WL_RSSI_EVENT_IFX_VERSION 1 +/* Offloads profile configuration version */ +#define BRCMF_OL_CFG_VER_1 1 + +extern unsigned int brcmf_offload_prof; +extern unsigned int brcmf_offload_feat; + +/* Packet types to be offloaded to firmware for processing */ +enum brcmf_ol_feats { + BRCMF_OL_ARP = BIT(0), + BRCMF_OL_ND = BIT(1), + BRCMF_OL_BDO = BIT(2), + BRCMF_OL_ICMP = BIT(3), + BRCMF_OL_TKO = BIT(4), + BRCMF_OL_DLTRO = BIT(5), + BRCMF_OL_PNO = BIT(6), + BRCMF_OL_KEEPALIVE = BIT(7), + BRCMF_OL_GTKOE = BIT(8), + BRCMF_OL_WOWLPF = BIT(9) +}; + +enum brcmf_ol_cfg_id { + BRCMF_OL_CFG_ID_PROF = 1, /* Offload Profile Update */ + BRCMF_OL_CFG_ID_INET_V4, /* ADD/DEL IPv4 Address */ + BRCMF_OL_CFG_ID_INET_V6, /* ADD/DEL IPv6 Address */ + BRCMF_OL_CFG_ID_ACTIVATE, /* Activate/Deactivate Offload */ + /* Add new type before this line */ + BRCMF_OL_CFG_ID_MAX /* Max Offload Config ID */ +}; + +enum brcmf_ol_prof_type { + BRCMF_OL_PROF_TYPE_LOW_PWR = 1, /* Low Power Profile */ + BRCMF_OL_PROF_TYPE_MID_PWR = 2, /* Mid Power Profile */ + BRCMF_OL_PROF_TYPE_HIGH_PWR = 3, /* High Power Profile */ + /* Add new type before this line */ + BRCMF_OL_PROF_TYPE_MAX /* Max Offload Profile */ +}; + /* join preference types for join_pref iovar */ enum brcmf_join_pref_types { BRCMF_JOIN_PREF_RSSI = 1, @@ -1317,4 +1359,44 @@ struct wl_rssi_event { s8 pad[2]; }; +struct ipv4_addr { + u8 addr[BRCMF_IPV4_ADDR_LEN]; +}; + +struct ipv6_addr { + u8 addr[BRCMF_IPV6_ADDR_LEN]; +}; + +/* Offload profile configuration */ +struct brcmf_ol_cfg_v1 { + u16 ver; /* version of this structure */ + u16 len; /* length of structure in bytes */ + enum brcmf_ol_cfg_id id; /* Offload Config ID */ + + union { + struct { + enum brcmf_ol_prof_type type; /* offload profile type */ + bool reset; /* Remove profile configuration */ + u8 pad[3]; + } ol_profile; + struct { + struct ipv4_addr host_ipv4; + bool del; /* 1:del 0:add host ipv4 address */ + u8 pad[3]; + } ol_inet_v4; + struct { + struct ipv6_addr host_ipv6; + u8 type; /* 0:unicast 1:anycast */ + bool del; /* 1:del 0:add host ipv6 address */ + u8 pad[2]; + } ol_inet_v6; + struct { + bool enable; /* enable/disable offload feature */ + u8 pad[3]; + } ol_activate; + } u; + + u32 offload_skip; /* Bitmap of offload to be skipped */ +}; + #endif /* FWIL_TYPES_H_ */ -- 2.25.1