3232#include "vendor.h"
3333#include "bus.h"
3434#include "common.h"
35+ #include "feature.h"
3536
3637#define BRCMF_SCAN_IE_LEN_MAX 2048
3738
@@ -365,6 +366,22 @@ static u8 nl80211_band_to_fwil(enum nl80211_band band)
365366 return 0 ;
366367}
367368
369+ static enum nl80211_band fwil_band_to_nl80211 (u8 band )
370+ {
371+ switch (band ) {
372+ case WLC_BAND_2G :
373+ return NL80211_BAND_2GHZ ;
374+ case WLC_BAND_5G :
375+ return NL80211_BAND_5GHZ ;
376+ case WLC_BAND_6G :
377+ return NL80211_BAND_6GHZ ;
378+ default :
379+ WARN_ON (1 );
380+ break ;
381+ }
382+ return 0 ;
383+ }
384+
368385static u16 chandef_to_chanspec (struct brcmu_d11inf * d11inf ,
369386 struct cfg80211_chan_def * ch )
370387{
@@ -3427,6 +3444,7 @@ static s32 brcmf_inform_single_bss(struct brcmf_cfg80211_info *cfg,
34273444 struct cfg80211_bss * bss ;
34283445 enum nl80211_band band ;
34293446 struct brcmu_chan ch ;
3447+ u16 chanspec ;
34303448 u16 channel ;
34313449 u32 freq ;
34323450 u16 notify_capability ;
@@ -3440,16 +3458,17 @@ static s32 brcmf_inform_single_bss(struct brcmf_cfg80211_info *cfg,
34403458 return - EINVAL ;
34413459 }
34423460
3461+ chanspec = le16_to_cpu (bi -> chanspec );
34433462 if (!bi -> ctl_ch ) {
3444- ch .chspec = le16_to_cpu ( bi -> chanspec ) ;
3463+ ch .chspec = chanspec ;
34453464 cfg -> d11inf .decchspec (& ch );
34463465 bi -> ctl_ch = ch .control_ch_num ;
34473466 }
34483467 channel = bi -> ctl_ch ;
34493468
3450- if (CHSPEC_IS6G (bi -> chanspec ))
3469+ if (CHSPEC_IS6G (chanspec ))
34513470 band = NL80211_BAND_6GHZ ;
3452- else if (CHSPEC_IS5G (bi -> chanspec ))
3471+ else if (CHSPEC_IS5G (chanspec ))
34533472 band = NL80211_BAND_5GHZ ;
34543473 else
34553474 band = NL80211_BAND_2GHZ ;
@@ -3943,6 +3962,34 @@ brcmf_get_netinfo_array(struct brcmf_pno_scanresults_le *pfn_v1)
39433962 pfn_v2 = (struct brcmf_pno_scanresults_v2_le * )pfn_v1 ;
39443963 netinfo = (struct brcmf_pno_net_info_le * )(pfn_v2 + 1 );
39453964 break ;
3965+ case cpu_to_le32 (3 ):
3966+ brcmf_err (
3967+ "This should use the brcmf_get_netinfo_v3_array function to retrieve the array\n" );
3968+ break ;
3969+ }
3970+
3971+ return netinfo ;
3972+ }
3973+
3974+ static struct brcmf_pno_net_info_v3_le *
3975+ brcmf_get_netinfo_v3_array (struct brcmf_pno_scanresults_le * pfn_v1 )
3976+ {
3977+ struct brcmf_pno_scanresults_v2_le * pfn_v2 ;
3978+ struct brcmf_pno_net_info_v3_le * netinfo ;
3979+
3980+ switch (pfn_v1 -> version ) {
3981+ default :
3982+ WARN_ON (1 );
3983+ fallthrough ;
3984+ case cpu_to_le32 (1 ):
3985+ case cpu_to_le32 (2 ):
3986+ brcmf_err (
3987+ "This should use the brcmf_get_netinfo_array function to retrieve the array\n" );
3988+ break ;
3989+ case cpu_to_le32 (3 ):
3990+ pfn_v2 = (struct brcmf_pno_scanresults_v2_le * )pfn_v1 ;
3991+ netinfo = (struct brcmf_pno_net_info_v3_le * )(pfn_v2 + 1 );
3992+ break ;
39463993 }
39473994
39483995 return netinfo ;
@@ -3954,13 +4001,12 @@ brcmf_get_netinfo_array(struct brcmf_pno_scanresults_le *pfn_v1)
39544001 * scan request in the form of cfg80211_scan_request. For timebeing, create
39554002 * cfg80211_scan_request one out of the received PNO event.
39564003 */
3957- static s32
3958- brcmf_notify_sched_scan_results ( struct brcmf_if * ifp ,
3959- const struct brcmf_event_msg * e , void * data )
4004+ static s32 brcmf_notify_sched_scan_results ( struct brcmf_if * ifp ,
4005+ const struct brcmf_event_msg * e ,
4006+ void * data )
39604007{
39614008 struct brcmf_pub * drvr = ifp -> drvr ;
39624009 struct brcmf_cfg80211_info * cfg = drvr -> config ;
3963- struct brcmf_pno_net_info_le * netinfo , * netinfo_start ;
39644010 struct cfg80211_scan_request * request = NULL ;
39654011 struct wiphy * wiphy = cfg_to_wiphy (cfg );
39664012 int i , err = 0 ;
@@ -3969,10 +4015,19 @@ brcmf_notify_sched_scan_results(struct brcmf_if *ifp,
39694015 u32 result_count ;
39704016 u32 status ;
39714017 u32 datalen ;
4018+ u32 min_data_len ;
39724019
39734020 brcmf_dbg (SCAN , "Enter\n" );
39744021
3975- if (e -> datalen < (sizeof (* pfn_result ) + sizeof (* netinfo ))) {
4022+ if (brcmf_feat_is_enabled (ifp , BRCMF_FEAT_PFN_V3 )) {
4023+ min_data_len = sizeof (* pfn_result ) +
4024+ sizeof (struct brcmf_pno_net_info_v3_le );
4025+ } else {
4026+ min_data_len = sizeof (* pfn_result ) +
4027+ sizeof (struct brcmf_pno_net_info_le );
4028+ }
4029+
4030+ if (e -> datalen < min_data_len ) {
39764031 brcmf_dbg (SCAN , "Event data to small. Ignore\n" );
39774032 return 0 ;
39784033 }
@@ -3995,38 +4050,78 @@ brcmf_notify_sched_scan_results(struct brcmf_if *ifp,
39954050 bphy_err (drvr , "FALSE PNO Event. (pfn_count == 0)\n" );
39964051 goto out_err ;
39974052 }
4053+ if (brcmf_feat_is_enabled (ifp , BRCMF_FEAT_PFN_V3 )) {
4054+ struct brcmf_pno_net_info_v3_le * netinfo_v3 , * netinfo_v3_start ;
4055+ netinfo_v3_start = brcmf_get_netinfo_v3_array (pfn_result );
39984056
3999- netinfo_start = brcmf_get_netinfo_array ( pfn_result );
4000- datalen = e -> datalen - ((void * )netinfo_start - (void * )pfn_result );
4001- if (datalen < result_count * sizeof (* netinfo )) {
4002- bphy_err (drvr , "insufficient event data\n" );
4003- goto out_err ;
4004- }
4057+ datalen = e -> datalen -
4058+ ((void * )netinfo_v3_start - (void * )pfn_result );
4059+ if (datalen < result_count * sizeof (* netinfo_v3 )) {
4060+ bphy_err (drvr , "insufficient event data\n" );
4061+ goto out_err ;
4062+ }
40054063
4006- request = brcmf_alloc_internal_escan_request ( wiphy ,
4007- result_count );
4008- if (!request ) {
4009- err = - ENOMEM ;
4010- goto out_err ;
4011- }
4064+ request =
4065+ brcmf_alloc_internal_escan_request ( wiphy , result_count );
4066+ if (!request ) {
4067+ err = - ENOMEM ;
4068+ goto out_err ;
4069+ }
40124070
4013- bucket_map = 0 ;
4014- for (i = 0 ; i < result_count ; i ++ ) {
4015- netinfo = & netinfo_start [i ];
4071+ bucket_map = 0 ;
4072+ for (i = 0 ; i < result_count ; i ++ ) {
4073+ netinfo_v3 = & netinfo_v3_start [i ];
4074+
4075+ if (netinfo_v3 -> SSID_len > IEEE80211_MAX_SSID_LEN )
4076+ netinfo_v3 -> SSID_len = IEEE80211_MAX_SSID_LEN ;
4077+ brcmf_dbg (SCAN , "SSID:%.32s Channel:%d Band:%d\n" ,
4078+ netinfo_v3 -> SSID ,
4079+ CHSPEC_CHANNEL (netinfo_v3 -> chanspec ),
4080+ CHSPEC_BAND (netinfo_v3 -> chanspec ));
4081+ bucket_map |= brcmf_pno_get_bucket_map_v3 (cfg -> pno ,
4082+ netinfo_v3 );
4083+ err = brcmf_internal_escan_add_info (
4084+ request , netinfo_v3 -> SSID , netinfo_v3 -> SSID_len ,
4085+ CHSPEC_CHANNEL (netinfo_v3 -> chanspec ));
4086+ if (err )
4087+ goto out_err ;
4088+ }
4089+ } else {
4090+ struct brcmf_pno_net_info_le * netinfo , * netinfo_start ;
40164091
4017- if (netinfo -> SSID_len > IEEE80211_MAX_SSID_LEN )
4018- netinfo -> SSID_len = IEEE80211_MAX_SSID_LEN ;
4019- brcmf_dbg (SCAN , "SSID:%.32s Channel:%d\n" ,
4020- netinfo -> SSID , netinfo -> channel );
4021- bucket_map |= brcmf_pno_get_bucket_map (cfg -> pno , netinfo );
4022- err = brcmf_internal_escan_add_info (request ,
4023- netinfo -> SSID ,
4024- netinfo -> SSID_len ,
4025- netinfo -> channel );
4026- if (err )
4092+ netinfo_start = brcmf_get_netinfo_array (pfn_result );
4093+ datalen = e -> datalen -
4094+ ((void * )netinfo_start - (void * )pfn_result );
4095+ if (datalen < result_count * sizeof (* netinfo )) {
4096+ bphy_err (drvr , "insufficient event data\n" );
40274097 goto out_err ;
4028- }
4098+ }
40294099
4100+ request =
4101+ brcmf_alloc_internal_escan_request (wiphy , result_count );
4102+ if (!request ) {
4103+ err = - ENOMEM ;
4104+ goto out_err ;
4105+ }
4106+
4107+ bucket_map = 0 ;
4108+ for (i = 0 ; i < result_count ; i ++ ) {
4109+ netinfo = & netinfo_start [i ];
4110+
4111+ if (netinfo -> SSID_len > IEEE80211_MAX_SSID_LEN )
4112+ netinfo -> SSID_len = IEEE80211_MAX_SSID_LEN ;
4113+ brcmf_dbg (SCAN , "SSID:%.32s Channel:%d\n" ,
4114+ netinfo -> SSID , netinfo -> channel );
4115+ bucket_map |=
4116+ brcmf_pno_get_bucket_map (cfg -> pno , netinfo );
4117+ err = brcmf_internal_escan_add_info (request ,
4118+ netinfo -> SSID ,
4119+ netinfo -> SSID_len ,
4120+ netinfo -> channel );
4121+ if (err )
4122+ goto out_err ;
4123+ }
4124+ }
40304125 if (!bucket_map )
40314126 goto free_req ;
40324127
@@ -4129,18 +4224,25 @@ static s32 brcmf_config_wowl_pattern(struct brcmf_if *ifp, u8 cmd[4],
41294224 return ret ;
41304225}
41314226
4132- static s32
4133- brcmf_wowl_nd_results (struct brcmf_if * ifp , const struct brcmf_event_msg * e ,
4134- void * data )
4227+ static s32 brcmf_wowl_nd_results (struct brcmf_if * ifp ,
4228+ const struct brcmf_event_msg * e , void * data )
41354229{
41364230 struct brcmf_pub * drvr = ifp -> drvr ;
41374231 struct brcmf_cfg80211_info * cfg = drvr -> config ;
41384232 struct brcmf_pno_scanresults_le * pfn_result ;
4139- struct brcmf_pno_net_info_le * netinfo ;
4233+ u32 min_data_len ;
41404234
41414235 brcmf_dbg (SCAN , "Enter\n" );
41424236
4143- if (e -> datalen < (sizeof (* pfn_result ) + sizeof (* netinfo ))) {
4237+ if (brcmf_feat_is_enabled (ifp , BRCMF_FEAT_PFN_V3 )) {
4238+ min_data_len = sizeof (* pfn_result ) +
4239+ sizeof (struct brcmf_pno_net_info_v3_le );
4240+ } else {
4241+ min_data_len = sizeof (* pfn_result ) +
4242+ sizeof (struct brcmf_pno_net_info_le );
4243+ }
4244+
4245+ if (e -> datalen < min_data_len ) {
41444246 brcmf_dbg (SCAN , "Event data to small. Ignore\n" );
41454247 return 0 ;
41464248 }
@@ -4158,20 +4260,38 @@ brcmf_wowl_nd_results(struct brcmf_if *ifp, const struct brcmf_event_msg *e,
41584260 return - EINVAL ;
41594261 }
41604262
4161- netinfo = brcmf_get_netinfo_array (pfn_result );
4162- if (netinfo -> SSID_len > IEEE80211_MAX_SSID_LEN )
4163- netinfo -> SSID_len = IEEE80211_MAX_SSID_LEN ;
4164- memcpy (cfg -> wowl .nd -> ssid .ssid , netinfo -> SSID , netinfo -> SSID_len );
4165- cfg -> wowl .nd -> ssid .ssid_len = netinfo -> SSID_len ;
4166- cfg -> wowl .nd -> n_channels = 1 ;
4167- /* TODO - need to store band so we can handle 6G */
4168- cfg -> wowl .nd -> channels [0 ] =
4169- ieee80211_channel_to_frequency (netinfo -> channel ,
4263+ if (brcmf_feat_is_enabled (ifp , BRCMF_FEAT_PFN_V3 )) {
4264+ struct brcmf_pno_net_info_v3_le * netinfo_v3 ;
4265+ netinfo_v3 = brcmf_get_netinfo_v3_array (pfn_result );
4266+
4267+ if (netinfo_v3 -> SSID_len > IEEE80211_MAX_SSID_LEN )
4268+ netinfo_v3 -> SSID_len = IEEE80211_MAX_SSID_LEN ;
4269+ memcpy (cfg -> wowl .nd -> ssid .ssid , netinfo_v3 -> SSID ,
4270+ netinfo_v3 -> SSID_len );
4271+ cfg -> wowl .nd -> ssid .ssid_len = netinfo_v3 -> SSID_len ;
4272+ cfg -> wowl .nd -> n_channels = 1 ;
4273+ /* TODO - need to store band so we can handle 6G */
4274+ cfg -> wowl .nd -> channels [0 ] = ieee80211_channel_to_frequency (
4275+ CHSPEC_CHANNEL (netinfo_v3 -> chanspec ),
4276+ fwil_band_to_nl80211 (netinfo_v3 -> chanspec ));
4277+ } else {
4278+ struct brcmf_pno_net_info_le * netinfo ;
4279+ netinfo = brcmf_get_netinfo_array (pfn_result );
4280+ if (netinfo -> SSID_len > IEEE80211_MAX_SSID_LEN )
4281+ netinfo -> SSID_len = IEEE80211_MAX_SSID_LEN ;
4282+ memcpy (cfg -> wowl .nd -> ssid .ssid , netinfo -> SSID ,
4283+ netinfo -> SSID_len );
4284+ cfg -> wowl .nd -> ssid .ssid_len = netinfo -> SSID_len ;
4285+ cfg -> wowl .nd -> n_channels = 1 ;
4286+ /* TODO - need to store band so we can handle 6G */
4287+ cfg -> wowl .nd -> channels [0 ] = ieee80211_channel_to_frequency (
4288+ netinfo -> channel ,
41704289 netinfo -> channel <= CH_MAX_2G_CHANNEL ?
4171- NL80211_BAND_2GHZ : NL80211_BAND_5GHZ );
4290+ NL80211_BAND_2GHZ :
4291+ NL80211_BAND_5GHZ );
4292+ }
41724293 cfg -> wowl .nd_info -> n_matches = 1 ;
41734294 cfg -> wowl .nd_info -> matches [0 ] = cfg -> wowl .nd ;
4174-
41754295 /* Inform (the resume task) that the net detect information was recvd */
41764296 cfg -> wowl .nd_data_completed = true;
41774297 wake_up (& cfg -> wowl .nd_data_wait );
0 commit comments