@@ -1099,170 +1099,13 @@ void brcmf_set_mpc(struct brcmf_if *ifp, int mpc)
10991099 }
11001100}
11011101
1102- static void brcmf_scan_params_v2_to_v1 (struct brcmf_scan_params_v2_le * params_v2_le ,
1103- struct brcmf_scan_params_le * params_le )
1104- {
1105- size_t params_size ;
1106- u32 ch ;
1107- int n_channels , n_ssids ;
1108-
1109- memcpy (& params_le -> ssid_le , & params_v2_le -> ssid_le ,
1110- sizeof (params_le -> ssid_le ));
1111- memcpy (& params_le -> bssid , & params_v2_le -> bssid ,
1112- sizeof (params_le -> bssid ));
1113-
1114- params_le -> bss_type = params_v2_le -> bss_type ;
1115- params_le -> scan_type = le32_to_cpu (params_v2_le -> scan_type );
1116- params_le -> nprobes = params_v2_le -> nprobes ;
1117- params_le -> active_time = params_v2_le -> active_time ;
1118- params_le -> passive_time = params_v2_le -> passive_time ;
1119- params_le -> home_time = params_v2_le -> home_time ;
1120- params_le -> channel_num = params_v2_le -> channel_num ;
1121-
1122- ch = le32_to_cpu (params_v2_le -> channel_num );
1123- n_channels = ch & BRCMF_SCAN_PARAMS_COUNT_MASK ;
1124- n_ssids = ch >> BRCMF_SCAN_PARAMS_NSSID_SHIFT ;
1125-
1126- params_size = sizeof (u16 ) * n_channels ;
1127- if (n_ssids > 0 ) {
1128- params_size = roundup (params_size , sizeof (u32 ));
1129- params_size += sizeof (struct brcmf_ssid_le ) * n_ssids ;
1130- }
1131-
1132- memcpy (& params_le -> channel_list [0 ],
1133- & params_v2_le -> channel_list [0 ], params_size );
1134- }
1135-
1136- static u32 brcmf_nl80211_scan_flags_to_scan_flags (u32 nl80211_flags )
1137- {
1138- u32 scan_flags = 0 ;
1139- if (nl80211_flags & NL80211_SCAN_FLAG_LOW_SPAN ) {
1140- scan_flags |= BRCMF_SCANFLAGS_LOW_SPAN ;
1141- brcmf_dbg (SCAN , "requested low span scan\n" );
1142- }
1143- if (nl80211_flags & NL80211_SCAN_FLAG_HIGH_ACCURACY ) {
1144- scan_flags |= BRCMF_SCANFLAGS_HIGH_ACCURACY ;
1145- brcmf_dbg (SCAN , "requested high accuracy scan\n" );
1146- }
1147- if (nl80211_flags & NL80211_SCAN_FLAG_LOW_POWER ) {
1148- scan_flags |= BRCMF_SCANFLAGS_LOW_POWER ;
1149- brcmf_dbg (SCAN , "requested low power scan\n" );
1150- }
1151- if (nl80211_flags & NL80211_SCAN_FLAG_LOW_PRIORITY ) {
1152- scan_flags |= BRCMF_SCANFLAGS_LOW_PRIO ;
1153- brcmf_dbg (SCAN , "requested low priority scan\n" );
1154- }
1155- return scan_flags ;
1156- }
1157-
1158- static void brcmf_escan_prep (struct brcmf_cfg80211_info * cfg ,
1159- struct brcmf_if * ifp ,
1160- struct brcmf_scan_params_v2_le * params_le ,
1161- struct cfg80211_scan_request * request )
1162- {
1163- u32 n_ssids ;
1164- u32 n_channels ;
1165- s32 i ;
1166- s32 offset ;
1167- u16 chanspec ;
1168- char * ptr ;
1169- int length ;
1170- struct brcmf_ssid_le ssid_le ;
1171- u32 scan_type = BRCMF_SCANTYPE_ACTIVE ;
1172-
1173- eth_broadcast_addr (params_le -> bssid );
1174-
1175- length = BRCMF_SCAN_PARAMS_V2_FIXED_SIZE ;
1176-
1177- if (brcmf_feat_is_enabled (ifp , BRCMF_FEAT_SCAN_V3 ))
1178- params_le -> version = cpu_to_le16 (BRCMF_SCAN_PARAMS_VERSION_V3 );
1179- else
1180- params_le -> version = cpu_to_le16 (BRCMF_SCAN_PARAMS_VERSION_V2 );
1181-
1182- params_le -> bss_type = DOT11_BSSTYPE_ANY ;
1183- params_le -> ssid_type = 0 ;
1184- params_le -> channel_num = 0 ;
1185- params_le -> nprobes = cpu_to_le32 (-1 );
1186- params_le -> active_time = cpu_to_le32 (-1 );
1187- params_le -> passive_time = cpu_to_le32 (-1 );
1188- params_le -> home_time = cpu_to_le32 (-1 );
1189- memset (& params_le -> ssid_le , 0 , sizeof (params_le -> ssid_le ));
1190-
1191- /* Scan abort */
1192- if (!request ) {
1193- length += sizeof (u16 );
1194- params_le -> channel_num = cpu_to_le32 (1 );
1195- params_le -> channel_list [0 ] = cpu_to_le16 (-1 );
1196- params_le -> length = cpu_to_le16 (length );
1197- return ;
1198- }
1199-
1200- n_ssids = request -> n_ssids ;
1201- n_channels = request -> n_channels ;
1202-
1203- /* Copy channel array if applicable */
1204- brcmf_dbg (SCAN , "### List of channelspecs to scan ### %d\n" ,
1205- n_channels );
1206- if (n_channels > 0 ) {
1207- length += roundup (sizeof (u16 ) * n_channels , sizeof (u32 ));
1208- for (i = 0 ; i < n_channels ; i ++ ) {
1209- chanspec = channel_to_chanspec (& cfg -> d11inf ,
1210- request -> channels [i ]);
1211- brcmf_dbg (SCAN , "Chan : %d, Channel spec: %x\n" ,
1212- request -> channels [i ]-> hw_value , chanspec );
1213- params_le -> channel_list [i ] = cpu_to_le16 (chanspec );
1214- }
1215- } else {
1216- brcmf_dbg (SCAN , "Scanning all channels\n" );
1217- }
1218-
1219- /* Copy ssid array if applicable */
1220- brcmf_dbg (SCAN , "### List of SSIDs to scan ### %d\n" , n_ssids );
1221- if (n_ssids > 0 ) {
1222- offset = offsetof(struct brcmf_scan_params_v2_le , channel_list ) +
1223- n_channels * sizeof (u16 );
1224- offset = roundup (offset , sizeof (u32 ));
1225- length += sizeof (ssid_le ) * n_ssids ,
1226- ptr = (char * )params_le + offset ;
1227- for (i = 0 ; i < n_ssids ; i ++ ) {
1228- memset (& ssid_le , 0 , sizeof (ssid_le ));
1229- ssid_le .SSID_len =
1230- cpu_to_le32 (request -> ssids [i ].ssid_len );
1231- memcpy (ssid_le .SSID , request -> ssids [i ].ssid ,
1232- request -> ssids [i ].ssid_len );
1233- if (!ssid_le .SSID_len )
1234- brcmf_dbg (SCAN , "%d: Broadcast scan\n" , i );
1235- else
1236- brcmf_dbg (SCAN , "%d: scan for %.32s size=%d\n" ,
1237- i , ssid_le .SSID , ssid_le .SSID_len );
1238- memcpy (ptr , & ssid_le , sizeof (ssid_le ));
1239- ptr += sizeof (ssid_le );
1240- }
1241- } else {
1242- brcmf_dbg (SCAN , "Performing passive scan\n" );
1243- scan_type = BRCMF_SCANTYPE_PASSIVE ;
1244- }
1245- scan_type |= brcmf_nl80211_scan_flags_to_scan_flags (request -> flags );
1246- params_le -> scan_type = cpu_to_le32 (scan_type );
1247- params_le -> length = cpu_to_le16 (length );
12481102
1249- /* Include RNR results if requested */
1250- if (request -> flags & NL80211_SCAN_FLAG_COLOCATED_6GHZ ) {
1251- params_le -> ssid_type |= BRCMF_SCANSSID_INC_RNR ;
1252- }
1253-
1254- /* Adding mask to channel numbers */
1255- params_le -> channel_num =
1256- cpu_to_le32 ((n_ssids << BRCMF_SCAN_PARAMS_NSSID_SHIFT ) |
1257- (n_channels & BRCMF_SCAN_PARAMS_COUNT_MASK ));
1258- }
12591103
12601104s32 brcmf_notify_escan_complete (struct brcmf_cfg80211_info * cfg ,
12611105 struct brcmf_if * ifp , bool aborted ,
12621106 bool fw_abort )
12631107{
12641108 struct brcmf_pub * drvr = cfg -> pub ;
1265- struct brcmf_scan_params_v2_le params_v2_le ;
12661109 struct cfg80211_scan_request * scan_request ;
12671110 u64 reqid ;
12681111 u32 bucket ;
@@ -1278,25 +1121,16 @@ s32 brcmf_notify_escan_complete(struct brcmf_cfg80211_info *cfg,
12781121 timer_delete_sync (& cfg -> escan_timeout );
12791122
12801123 if (fw_abort ) {
1124+ u32 len ;
1125+ void * data = drvr -> scan_param_handler .get_prepped_struct (cfg , & len , NULL );
1126+ if (!data ){
1127+ bphy_err (drvr , "Scan abort failed to prepare abort struct\n" );
1128+ return 0 ;
1129+ }
12811130 /* Do a scan abort to stop the driver's scan engine */
12821131 brcmf_dbg (SCAN , "ABORT scan in firmware\n" );
1283-
1284- brcmf_escan_prep (cfg , ifp , & params_v2_le , NULL );
1285-
1286- /* E-Scan (or anyother type) can be aborted by SCAN */
1287- if (brcmf_feat_is_enabled (ifp , BRCMF_FEAT_SCAN_V2 )) {
1288- err = brcmf_fil_cmd_data_set (ifp , BRCMF_C_SCAN ,
1289- & params_v2_le ,
1290- sizeof (params_v2_le ));
1291- } else {
1292- struct brcmf_scan_params_le params_le ;
1293-
1294- brcmf_scan_params_v2_to_v1 (& params_v2_le , & params_le );
1295- err = brcmf_fil_cmd_data_set (ifp , BRCMF_C_SCAN ,
1296- & params_le ,
1297- sizeof (params_le ));
1298- }
1299-
1132+ err = brcmf_fil_cmd_data_set (ifp , BRCMF_C_SCAN , data , len );
1133+ kfree (data );
13001134 if (err )
13011135 bphy_err (drvr , "Scan abort failed\n" );
13021136 }
@@ -1520,49 +1354,39 @@ brcmf_run_escan(struct brcmf_cfg80211_info *cfg, struct brcmf_if *ifp,
15201354 struct cfg80211_scan_request * request )
15211355{
15221356 struct brcmf_pub * drvr = cfg -> pub ;
1523- s32 params_size = BRCMF_SCAN_PARAMS_V2_FIXED_SIZE +
1524- offsetof(struct brcmf_escan_params_le , params_v2_le );
1357+ u32 struct_size = 0 ;
1358+ void * prepped_params = NULL ;
1359+ u32 params_size = 0 ;
15251360 struct brcmf_escan_params_le * params ;
15261361 s32 err = 0 ;
15271362
15281363 brcmf_dbg (SCAN , "E-SCAN START\n" );
15291364
1530- if (request != NULL ) {
1531- /* Allocate space for populating ssids in struct */
1532- params_size += sizeof (u32 ) * ((request -> n_channels + 1 ) / 2 );
1533-
1534- /* Allocate space for populating ssids in struct */
1535- params_size += sizeof (struct brcmf_ssid_le ) * request -> n_ssids ;
1365+ prepped_params = drvr -> scan_param_handler .get_prepped_struct (cfg , & struct_size , request );
1366+ if (!prepped_params ) {
1367+ err = - EINVAL ;
1368+ goto exit ;
1369+ }
1370+ params_size = struct_size +
1371+ offsetof(struct brcmf_escan_params_le , params_v4_le );
1372+ if (!params_size ) {
1373+ err = - EINVAL ;
1374+ goto exit ;
15361375 }
15371376
15381377 params = kzalloc (params_size , GFP_KERNEL );
15391378 if (!params ) {
15401379 err = - ENOMEM ;
15411380 goto exit ;
15421381 }
1543- BUG_ON (params_size + sizeof ("escan" ) >= BRCMF_DCMD_MEDLEN );
1544- brcmf_escan_prep (cfg , ifp , & params -> params_v2_le , request );
1545-
1546- if (brcmf_feat_is_enabled (ifp , BRCMF_FEAT_SCAN_V3 )) {
1547- params -> version = cpu_to_le32 (BRCMF_ESCAN_REQ_VERSION_V3 );
1548- } else if (brcmf_feat_is_enabled (ifp , BRCMF_FEAT_SCAN_V2 )) {
1549- params -> version = cpu_to_le32 (BRCMF_ESCAN_REQ_VERSION_V2 );
1550- } else {
1551- struct brcmf_escan_params_le * params_v1 ;
1552-
1553- params_size -= BRCMF_SCAN_PARAMS_V2_FIXED_SIZE ;
1554- params_size += BRCMF_SCAN_PARAMS_FIXED_SIZE ;
1555- params_v1 = kzalloc (params_size , GFP_KERNEL );
1556- if (!params_v1 ) {
1557- err = - ENOMEM ;
1558- goto exit_params ;
1559- }
1560- params_v1 -> version = cpu_to_le32 (BRCMF_ESCAN_REQ_VERSION );
1561- brcmf_scan_params_v2_to_v1 (& params -> params_v2_le , & params_v1 -> params_le );
1562- kfree (params );
1563- params = params_v1 ;
1564- }
1382+ /* Copy into the largest part */
1383+ unsafe_memcpy (
1384+ & params -> params_v4_le , prepped_params , struct_size ,
1385+ /* A composite flex-array that is at least as large as the memcpy due to the allocation above */ );
15651386
1387+ /* We can now free the original prepped parameters */
1388+ kfree (prepped_params );
1389+ params -> version = cpu_to_le32 (drvr -> scan_param_handler .version );
15661390 params -> action = cpu_to_le16 (WL_ESCAN_ACTION_START );
15671391 params -> sync_id = cpu_to_le16 (0x1234 );
15681392
@@ -1574,7 +1398,6 @@ brcmf_run_escan(struct brcmf_cfg80211_info *cfg, struct brcmf_if *ifp,
15741398 bphy_err (drvr , "error (%d)\n" , err );
15751399 }
15761400
1577- exit_params :
15781401 kfree (params );
15791402exit :
15801403 return err ;
0 commit comments