@@ -1117,170 +1117,11 @@ bool brcmf_is_apmode_operating(struct wiphy *wiphy)
11171117 return ret ;
11181118}
11191119
1120- static void brcmf_scan_params_v2_to_v1 (struct brcmf_scan_params_v2_le * params_v2_le ,
1121- struct brcmf_scan_params_le * params_le )
1122- {
1123- size_t params_size ;
1124- u32 ch ;
1125- int n_channels , n_ssids ;
1126-
1127- memcpy (& params_le -> ssid_le , & params_v2_le -> ssid_le ,
1128- sizeof (params_le -> ssid_le ));
1129- memcpy (& params_le -> bssid , & params_v2_le -> bssid ,
1130- sizeof (params_le -> bssid ));
1131-
1132- params_le -> bss_type = params_v2_le -> bss_type ;
1133- params_le -> scan_type = le32_to_cpu (params_v2_le -> scan_type );
1134- params_le -> nprobes = params_v2_le -> nprobes ;
1135- params_le -> active_time = params_v2_le -> active_time ;
1136- params_le -> passive_time = params_v2_le -> passive_time ;
1137- params_le -> home_time = params_v2_le -> home_time ;
1138- params_le -> channel_num = params_v2_le -> channel_num ;
1139-
1140- ch = le32_to_cpu (params_v2_le -> channel_num );
1141- n_channels = ch & BRCMF_SCAN_PARAMS_COUNT_MASK ;
1142- n_ssids = ch >> BRCMF_SCAN_PARAMS_NSSID_SHIFT ;
1143-
1144- params_size = sizeof (u16 ) * n_channels ;
1145- if (n_ssids > 0 ) {
1146- params_size = roundup (params_size , sizeof (u32 ));
1147- params_size += sizeof (struct brcmf_ssid_le ) * n_ssids ;
1148- }
1149-
1150- memcpy (& params_le -> channel_list [0 ],
1151- & params_v2_le -> channel_list [0 ], params_size );
1152- }
1153-
1154- static u32 brcmf_nl80211_scan_flags_to_scan_flags (u32 nl80211_flags )
1155- {
1156- u32 scan_flags = 0 ;
1157- if (nl80211_flags & NL80211_SCAN_FLAG_LOW_SPAN ) {
1158- scan_flags |= BRCMF_SCANFLAGS_LOW_SPAN ;
1159- brcmf_dbg (SCAN , "requested low span scan\n" );
1160- }
1161- if (nl80211_flags & NL80211_SCAN_FLAG_HIGH_ACCURACY ) {
1162- scan_flags |= BRCMF_SCANFLAGS_HIGH_ACCURACY ;
1163- brcmf_dbg (SCAN , "requested high accuracy scan\n" );
1164- }
1165- if (nl80211_flags & NL80211_SCAN_FLAG_LOW_POWER ) {
1166- scan_flags |= BRCMF_SCANFLAGS_LOW_POWER ;
1167- brcmf_dbg (SCAN , "requested low power scan\n" );
1168- }
1169- if (nl80211_flags & NL80211_SCAN_FLAG_LOW_PRIORITY ) {
1170- scan_flags |= BRCMF_SCANFLAGS_LOW_PRIO ;
1171- brcmf_dbg (SCAN , "requested low priority scan\n" );
1172- }
1173- return scan_flags ;
1174- }
1175-
1176- static void brcmf_escan_prep (struct brcmf_cfg80211_info * cfg ,
1177- struct brcmf_if * ifp ,
1178- struct brcmf_scan_params_v2_le * params_le ,
1179- struct cfg80211_scan_request * request )
1180- {
1181- u32 n_ssids ;
1182- u32 n_channels ;
1183- s32 i ;
1184- s32 offset ;
1185- u16 chanspec ;
1186- char * ptr ;
1187- int length ;
1188- struct brcmf_ssid_le ssid_le ;
1189- u32 scan_type = BRCMF_SCANTYPE_ACTIVE ;
1190-
1191- eth_broadcast_addr (params_le -> bssid );
1192-
1193- length = BRCMF_SCAN_PARAMS_V2_FIXED_SIZE ;
1194-
1195- if (brcmf_feat_is_enabled (ifp , BRCMF_FEAT_SCAN_V3 ))
1196- params_le -> version = cpu_to_le16 (BRCMF_SCAN_PARAMS_VERSION_V3 );
1197- else
1198- params_le -> version = cpu_to_le16 (BRCMF_SCAN_PARAMS_VERSION_V2 );
1199-
1200- params_le -> bss_type = DOT11_BSSTYPE_ANY ;
1201- params_le -> ssid_type = 0 ;
1202- params_le -> channel_num = 0 ;
1203- params_le -> nprobes = cpu_to_le32 (-1 );
1204- params_le -> active_time = cpu_to_le32 (-1 );
1205- params_le -> passive_time = cpu_to_le32 (-1 );
1206- params_le -> home_time = cpu_to_le32 (-1 );
1207- memset (& params_le -> ssid_le , 0 , sizeof (params_le -> ssid_le ));
1208-
1209- /* Scan abort */
1210- if (!request ) {
1211- length += sizeof (u16 );
1212- params_le -> channel_num = cpu_to_le32 (1 );
1213- params_le -> channel_list [0 ] = cpu_to_le16 (-1 );
1214- params_le -> length = cpu_to_le16 (length );
1215- return ;
1216- }
1217-
1218- n_ssids = request -> n_ssids ;
1219- n_channels = request -> n_channels ;
1220-
1221- /* Copy channel array if applicable */
1222- brcmf_dbg (SCAN , "### List of channelspecs to scan ### %d\n" ,
1223- n_channels );
1224- if (n_channels > 0 ) {
1225- length += roundup (sizeof (u16 ) * n_channels , sizeof (u32 ));
1226- for (i = 0 ; i < n_channels ; i ++ ) {
1227- chanspec = channel_to_chanspec (& cfg -> d11inf ,
1228- request -> channels [i ]);
1229- brcmf_dbg (SCAN , "Chan : %d, Channel spec: %x\n" ,
1230- request -> channels [i ]-> hw_value , chanspec );
1231- params_le -> channel_list [i ] = cpu_to_le16 (chanspec );
1232- }
1233- } else {
1234- brcmf_dbg (SCAN , "Scanning all channels\n" );
1235- }
1236-
1237- /* Copy ssid array if applicable */
1238- brcmf_dbg (SCAN , "### List of SSIDs to scan ### %d\n" , n_ssids );
1239- if (n_ssids > 0 ) {
1240- offset = offsetof(struct brcmf_scan_params_v2_le , channel_list ) +
1241- n_channels * sizeof (u16 );
1242- offset = roundup (offset , sizeof (u32 ));
1243- length += sizeof (ssid_le ) * n_ssids ;
1244- ptr = (char * )params_le + offset ;
1245- for (i = 0 ; i < n_ssids ; i ++ ) {
1246- memset (& ssid_le , 0 , sizeof (ssid_le ));
1247- ssid_le .SSID_len =
1248- cpu_to_le32 (request -> ssids [i ].ssid_len );
1249- memcpy (ssid_le .SSID , request -> ssids [i ].ssid ,
1250- request -> ssids [i ].ssid_len );
1251- if (!ssid_le .SSID_len )
1252- brcmf_dbg (SCAN , "%d: Broadcast scan\n" , i );
1253- else
1254- brcmf_dbg (SCAN , "%d: scan for %.32s size=%d\n" ,
1255- i , ssid_le .SSID , ssid_le .SSID_len );
1256- memcpy (ptr , & ssid_le , sizeof (ssid_le ));
1257- ptr += sizeof (ssid_le );
1258- }
1259- } else {
1260- brcmf_dbg (SCAN , "Performing passive scan\n" );
1261- scan_type = BRCMF_SCANTYPE_PASSIVE ;
1262- }
1263- scan_type |= brcmf_nl80211_scan_flags_to_scan_flags (request -> flags );
1264- params_le -> scan_type = cpu_to_le32 (scan_type );
1265- params_le -> length = cpu_to_le16 (length );
1266-
1267- /* Include RNR results if requested */
1268- if (request -> flags & NL80211_SCAN_FLAG_COLOCATED_6GHZ ) {
1269- params_le -> ssid_type |= BRCMF_SCANSSID_INC_RNR ;
1270- }
1271-
1272- /* Adding mask to channel numbers */
1273- params_le -> channel_num =
1274- cpu_to_le32 ((n_ssids << BRCMF_SCAN_PARAMS_NSSID_SHIFT ) |
1275- (n_channels & BRCMF_SCAN_PARAMS_COUNT_MASK ));
1276- }
1277-
12781120s32 brcmf_notify_escan_complete (struct brcmf_cfg80211_info * cfg ,
12791121 struct brcmf_if * ifp , bool aborted ,
12801122 bool fw_abort )
12811123{
12821124 struct brcmf_pub * drvr = cfg -> pub ;
1283- struct brcmf_scan_params_v2_le params_v2_le ;
12841125 struct cfg80211_scan_request * scan_request ;
12851126 u64 reqid ;
12861127 u32 bucket ;
@@ -1296,25 +1137,16 @@ s32 brcmf_notify_escan_complete(struct brcmf_cfg80211_info *cfg,
12961137 timer_delete_sync (& cfg -> escan_timeout );
12971138
12981139 if (fw_abort ) {
1140+ u32 len ;
1141+ void * data = drvr -> scan_param_handler .get_prepped_struct (cfg , & len , NULL );
1142+ if (!data ){
1143+ bphy_err (drvr , "Scan abort failed to prepare abort struct\n" );
1144+ return 0 ;
1145+ }
12991146 /* Do a scan abort to stop the driver's scan engine */
13001147 brcmf_dbg (SCAN , "ABORT scan in firmware\n" );
1301-
1302- brcmf_escan_prep (cfg , ifp , & params_v2_le , NULL );
1303-
1304- /* E-Scan (or anyother type) can be aborted by SCAN */
1305- if (brcmf_feat_is_enabled (ifp , BRCMF_FEAT_SCAN_V2 )) {
1306- err = brcmf_fil_cmd_data_set (ifp , BRCMF_C_SCAN ,
1307- & params_v2_le ,
1308- sizeof (params_v2_le ));
1309- } else {
1310- struct brcmf_scan_params_le params_le ;
1311-
1312- brcmf_scan_params_v2_to_v1 (& params_v2_le , & params_le );
1313- err = brcmf_fil_cmd_data_set (ifp , BRCMF_C_SCAN ,
1314- & params_le ,
1315- sizeof (params_le ));
1316- }
1317-
1148+ err = brcmf_fil_cmd_data_set (ifp , BRCMF_C_SCAN , data , len );
1149+ kfree (data );
13181150 if (err )
13191151 bphy_err (drvr , "Scan abort failed\n" );
13201152 }
@@ -1538,49 +1370,39 @@ brcmf_run_escan(struct brcmf_cfg80211_info *cfg, struct brcmf_if *ifp,
15381370 struct cfg80211_scan_request * request )
15391371{
15401372 struct brcmf_pub * drvr = cfg -> pub ;
1541- s32 params_size = BRCMF_SCAN_PARAMS_V2_FIXED_SIZE +
1542- offsetof(struct brcmf_escan_params_le , params_v2_le );
1373+ u32 struct_size = 0 ;
1374+ void * prepped_params = NULL ;
1375+ u32 params_size = 0 ;
15431376 struct brcmf_escan_params_le * params ;
15441377 s32 err = 0 ;
15451378
15461379 brcmf_dbg (SCAN , "E-SCAN START\n" );
15471380
1548- if (request != NULL ) {
1549- /* Allocate space for populating ssids in struct */
1550- params_size += sizeof (u32 ) * ((request -> n_channels + 1 ) / 2 );
1551-
1552- /* Allocate space for populating ssids in struct */
1553- params_size += sizeof (struct brcmf_ssid_le ) * request -> n_ssids ;
1381+ prepped_params = drvr -> scan_param_handler .get_prepped_struct (cfg , & struct_size , request );
1382+ if (!prepped_params ) {
1383+ err = - EINVAL ;
1384+ goto exit ;
1385+ }
1386+ params_size = struct_size +
1387+ offsetof(struct brcmf_escan_params_le , params_v4_le );
1388+ if (!params_size ) {
1389+ err = - EINVAL ;
1390+ goto exit ;
15541391 }
15551392
15561393 params = kzalloc (params_size , GFP_KERNEL );
15571394 if (!params ) {
15581395 err = - ENOMEM ;
15591396 goto exit ;
15601397 }
1561- BUG_ON (params_size + sizeof ("escan" ) >= BRCMF_DCMD_MEDLEN );
1562- brcmf_escan_prep (cfg , ifp , & params -> params_v2_le , request );
1563-
1564- if (brcmf_feat_is_enabled (ifp , BRCMF_FEAT_SCAN_V3 )) {
1565- params -> version = cpu_to_le32 (BRCMF_ESCAN_REQ_VERSION_V3 );
1566- } else if (brcmf_feat_is_enabled (ifp , BRCMF_FEAT_SCAN_V2 )) {
1567- params -> version = cpu_to_le32 (BRCMF_ESCAN_REQ_VERSION_V2 );
1568- } else {
1569- struct brcmf_escan_params_le * params_v1 ;
1570-
1571- params_size -= BRCMF_SCAN_PARAMS_V2_FIXED_SIZE ;
1572- params_size += BRCMF_SCAN_PARAMS_FIXED_SIZE ;
1573- params_v1 = kzalloc (params_size , GFP_KERNEL );
1574- if (!params_v1 ) {
1575- err = - ENOMEM ;
1576- goto exit_params ;
1577- }
1578- params_v1 -> version = cpu_to_le32 (BRCMF_ESCAN_REQ_VERSION );
1579- brcmf_scan_params_v2_to_v1 (& params -> params_v2_le , & params_v1 -> params_le );
1580- kfree (params );
1581- params = params_v1 ;
1582- }
1398+ /* Copy into the largest part */
1399+ unsafe_memcpy (
1400+ & params -> params_v4_le , prepped_params , struct_size ,
1401+ /* A composite flex-array that is at least as large as the memcpy due to the allocation above */ );
15831402
1403+ /* We can now free the original prepped parameters */
1404+ kfree (prepped_params );
1405+ params -> version = cpu_to_le32 (drvr -> scan_param_handler .version );
15841406 params -> action = cpu_to_le16 (WL_ESCAN_ACTION_START );
15851407 params -> sync_id = cpu_to_le16 (0x1234 );
15861408
@@ -1592,7 +1414,6 @@ brcmf_run_escan(struct brcmf_cfg80211_info *cfg, struct brcmf_if *ifp,
15921414 bphy_err (drvr , "error (%d)\n" , err );
15931415 }
15941416
1595- exit_params :
15961417 kfree (params );
15971418exit :
15981419 return err ;
0 commit comments