@@ -1103,170 +1103,13 @@ void brcmf_set_mpc(struct brcmf_if *ifp, int mpc)
11031103 }
11041104}
11051105
1106- static void brcmf_scan_params_v2_to_v1 (struct brcmf_scan_params_v2_le * params_v2_le ,
1107- struct brcmf_scan_params_le * params_le )
1108- {
1109- size_t params_size ;
1110- u32 ch ;
1111- int n_channels , n_ssids ;
1112-
1113- memcpy (& params_le -> ssid_le , & params_v2_le -> ssid_le ,
1114- sizeof (params_le -> ssid_le ));
1115- memcpy (& params_le -> bssid , & params_v2_le -> bssid ,
1116- sizeof (params_le -> bssid ));
1117-
1118- params_le -> bss_type = params_v2_le -> bss_type ;
1119- params_le -> scan_type = le32_to_cpu (params_v2_le -> scan_type );
1120- params_le -> nprobes = params_v2_le -> nprobes ;
1121- params_le -> active_time = params_v2_le -> active_time ;
1122- params_le -> passive_time = params_v2_le -> passive_time ;
1123- params_le -> home_time = params_v2_le -> home_time ;
1124- params_le -> channel_num = params_v2_le -> channel_num ;
1125-
1126- ch = le32_to_cpu (params_v2_le -> channel_num );
1127- n_channels = ch & BRCMF_SCAN_PARAMS_COUNT_MASK ;
1128- n_ssids = ch >> BRCMF_SCAN_PARAMS_NSSID_SHIFT ;
1129-
1130- params_size = sizeof (u16 ) * n_channels ;
1131- if (n_ssids > 0 ) {
1132- params_size = roundup (params_size , sizeof (u32 ));
1133- params_size += sizeof (struct brcmf_ssid_le ) * n_ssids ;
1134- }
1135-
1136- memcpy (& params_le -> channel_list [0 ],
1137- & params_v2_le -> channel_list [0 ], params_size );
1138- }
1139-
1140- static u32 brcmf_nl80211_scan_flags_to_scan_flags (u32 nl80211_flags )
1141- {
1142- u32 scan_flags = 0 ;
1143- if (nl80211_flags & NL80211_SCAN_FLAG_LOW_SPAN ) {
1144- scan_flags |= BRCMF_SCANFLAGS_LOW_SPAN ;
1145- brcmf_dbg (SCAN , "requested low span scan\n" );
1146- }
1147- if (nl80211_flags & NL80211_SCAN_FLAG_HIGH_ACCURACY ) {
1148- scan_flags |= BRCMF_SCANFLAGS_HIGH_ACCURACY ;
1149- brcmf_dbg (SCAN , "requested high accuracy scan\n" );
1150- }
1151- if (nl80211_flags & NL80211_SCAN_FLAG_LOW_POWER ) {
1152- scan_flags |= BRCMF_SCANFLAGS_LOW_POWER ;
1153- brcmf_dbg (SCAN , "requested low power scan\n" );
1154- }
1155- if (nl80211_flags & NL80211_SCAN_FLAG_LOW_PRIORITY ) {
1156- scan_flags |= BRCMF_SCANFLAGS_LOW_PRIO ;
1157- brcmf_dbg (SCAN , "requested low priority scan\n" );
1158- }
1159- return scan_flags ;
1160- }
1161-
1162- static void brcmf_escan_prep (struct brcmf_cfg80211_info * cfg ,
1163- struct brcmf_if * ifp ,
1164- struct brcmf_scan_params_v2_le * params_le ,
1165- struct cfg80211_scan_request * request )
1166- {
1167- u32 n_ssids ;
1168- u32 n_channels ;
1169- s32 i ;
1170- s32 offset ;
1171- u16 chanspec ;
1172- char * ptr ;
1173- int length ;
1174- struct brcmf_ssid_le ssid_le ;
1175- u32 scan_type = BRCMF_SCANTYPE_ACTIVE ;
1176-
1177- eth_broadcast_addr (params_le -> bssid );
1178-
1179- length = BRCMF_SCAN_PARAMS_V2_FIXED_SIZE ;
1180-
1181- if (brcmf_feat_is_enabled (ifp , BRCMF_FEAT_SCAN_V3 ))
1182- params_le -> version = cpu_to_le16 (BRCMF_SCAN_PARAMS_VERSION_V3 );
1183- else
1184- params_le -> version = cpu_to_le16 (BRCMF_SCAN_PARAMS_VERSION_V2 );
1185-
1186- params_le -> bss_type = DOT11_BSSTYPE_ANY ;
1187- params_le -> ssid_type = 0 ;
1188- params_le -> channel_num = 0 ;
1189- params_le -> nprobes = cpu_to_le32 (-1 );
1190- params_le -> active_time = cpu_to_le32 (-1 );
1191- params_le -> passive_time = cpu_to_le32 (-1 );
1192- params_le -> home_time = cpu_to_le32 (-1 );
1193- memset (& params_le -> ssid_le , 0 , sizeof (params_le -> ssid_le ));
1194-
1195- /* Scan abort */
1196- if (!request ) {
1197- length += sizeof (u16 );
1198- params_le -> channel_num = cpu_to_le32 (1 );
1199- params_le -> channel_list [0 ] = cpu_to_le16 (-1 );
1200- params_le -> length = cpu_to_le16 (length );
1201- return ;
1202- }
1203-
1204- n_ssids = request -> n_ssids ;
1205- n_channels = request -> n_channels ;
1206-
1207- /* Copy channel array if applicable */
1208- brcmf_dbg (SCAN , "### List of channelspecs to scan ### %d\n" ,
1209- n_channels );
1210- if (n_channels > 0 ) {
1211- length += roundup (sizeof (u16 ) * n_channels , sizeof (u32 ));
1212- for (i = 0 ; i < n_channels ; i ++ ) {
1213- chanspec = channel_to_chanspec (& cfg -> d11inf ,
1214- request -> channels [i ]);
1215- brcmf_dbg (SCAN , "Chan : %d, Channel spec: %x\n" ,
1216- request -> channels [i ]-> hw_value , chanspec );
1217- params_le -> channel_list [i ] = cpu_to_le16 (chanspec );
1218- }
1219- } else {
1220- brcmf_dbg (SCAN , "Scanning all channels\n" );
1221- }
1222-
1223- /* Copy ssid array if applicable */
1224- brcmf_dbg (SCAN , "### List of SSIDs to scan ### %d\n" , n_ssids );
1225- if (n_ssids > 0 ) {
1226- offset = offsetof(struct brcmf_scan_params_v2_le , channel_list ) +
1227- n_channels * sizeof (u16 );
1228- offset = roundup (offset , sizeof (u32 ));
1229- length += sizeof (ssid_le ) * n_ssids ;
1230- ptr = (char * )params_le + offset ;
1231- for (i = 0 ; i < n_ssids ; i ++ ) {
1232- memset (& ssid_le , 0 , sizeof (ssid_le ));
1233- ssid_le .SSID_len =
1234- cpu_to_le32 (request -> ssids [i ].ssid_len );
1235- memcpy (ssid_le .SSID , request -> ssids [i ].ssid ,
1236- request -> ssids [i ].ssid_len );
1237- if (!ssid_le .SSID_len )
1238- brcmf_dbg (SCAN , "%d: Broadcast scan\n" , i );
1239- else
1240- brcmf_dbg (SCAN , "%d: scan for %.32s size=%d\n" ,
1241- i , ssid_le .SSID , ssid_le .SSID_len );
1242- memcpy (ptr , & ssid_le , sizeof (ssid_le ));
1243- ptr += sizeof (ssid_le );
1244- }
1245- } else {
1246- brcmf_dbg (SCAN , "Performing passive scan\n" );
1247- scan_type = BRCMF_SCANTYPE_PASSIVE ;
1248- }
1249- scan_type |= brcmf_nl80211_scan_flags_to_scan_flags (request -> flags );
1250- params_le -> scan_type = cpu_to_le32 (scan_type );
1251- params_le -> length = cpu_to_le16 (length );
12521106
1253- /* Include RNR results if requested */
1254- if (request -> flags & NL80211_SCAN_FLAG_COLOCATED_6GHZ ) {
1255- params_le -> ssid_type |= BRCMF_SCANSSID_INC_RNR ;
1256- }
1257-
1258- /* Adding mask to channel numbers */
1259- params_le -> channel_num =
1260- cpu_to_le32 ((n_ssids << BRCMF_SCAN_PARAMS_NSSID_SHIFT ) |
1261- (n_channels & BRCMF_SCAN_PARAMS_COUNT_MASK ));
1262- }
12631107
12641108s32 brcmf_notify_escan_complete (struct brcmf_cfg80211_info * cfg ,
12651109 struct brcmf_if * ifp , bool aborted ,
12661110 bool fw_abort )
12671111{
12681112 struct brcmf_pub * drvr = cfg -> pub ;
1269- struct brcmf_scan_params_v2_le params_v2_le ;
12701113 struct cfg80211_scan_request * scan_request ;
12711114 u64 reqid ;
12721115 u32 bucket ;
@@ -1282,25 +1125,16 @@ s32 brcmf_notify_escan_complete(struct brcmf_cfg80211_info *cfg,
12821125 timer_delete_sync (& cfg -> escan_timeout );
12831126
12841127 if (fw_abort ) {
1128+ u32 len ;
1129+ void * data = drvr -> scan_param_handler .get_prepped_struct (cfg , & len , NULL );
1130+ if (!data ){
1131+ bphy_err (drvr , "Scan abort failed to prepare abort struct\n" );
1132+ return 0 ;
1133+ }
12851134 /* Do a scan abort to stop the driver's scan engine */
12861135 brcmf_dbg (SCAN , "ABORT scan in firmware\n" );
1287-
1288- brcmf_escan_prep (cfg , ifp , & params_v2_le , NULL );
1289-
1290- /* E-Scan (or anyother type) can be aborted by SCAN */
1291- if (brcmf_feat_is_enabled (ifp , BRCMF_FEAT_SCAN_V2 )) {
1292- err = brcmf_fil_cmd_data_set (ifp , BRCMF_C_SCAN ,
1293- & params_v2_le ,
1294- sizeof (params_v2_le ));
1295- } else {
1296- struct brcmf_scan_params_le params_le ;
1297-
1298- brcmf_scan_params_v2_to_v1 (& params_v2_le , & params_le );
1299- err = brcmf_fil_cmd_data_set (ifp , BRCMF_C_SCAN ,
1300- & params_le ,
1301- sizeof (params_le ));
1302- }
1303-
1136+ err = brcmf_fil_cmd_data_set (ifp , BRCMF_C_SCAN , data , len );
1137+ kfree (data );
13041138 if (err )
13051139 bphy_err (drvr , "Scan abort failed\n" );
13061140 }
@@ -1524,49 +1358,39 @@ brcmf_run_escan(struct brcmf_cfg80211_info *cfg, struct brcmf_if *ifp,
15241358 struct cfg80211_scan_request * request )
15251359{
15261360 struct brcmf_pub * drvr = cfg -> pub ;
1527- s32 params_size = BRCMF_SCAN_PARAMS_V2_FIXED_SIZE +
1528- offsetof(struct brcmf_escan_params_le , params_v2_le );
1361+ u32 struct_size = 0 ;
1362+ void * prepped_params = NULL ;
1363+ u32 params_size = 0 ;
15291364 struct brcmf_escan_params_le * params ;
15301365 s32 err = 0 ;
15311366
15321367 brcmf_dbg (SCAN , "E-SCAN START\n" );
15331368
1534- if (request != NULL ) {
1535- /* Allocate space for populating ssids in struct */
1536- params_size += sizeof (u32 ) * ((request -> n_channels + 1 ) / 2 );
1537-
1538- /* Allocate space for populating ssids in struct */
1539- params_size += sizeof (struct brcmf_ssid_le ) * request -> n_ssids ;
1369+ prepped_params = drvr -> scan_param_handler .get_prepped_struct (cfg , & struct_size , request );
1370+ if (!prepped_params ) {
1371+ err = - EINVAL ;
1372+ goto exit ;
1373+ }
1374+ params_size = struct_size +
1375+ offsetof(struct brcmf_escan_params_le , params_v4_le );
1376+ if (!params_size ) {
1377+ err = - EINVAL ;
1378+ goto exit ;
15401379 }
15411380
15421381 params = kzalloc (params_size , GFP_KERNEL );
15431382 if (!params ) {
15441383 err = - ENOMEM ;
15451384 goto exit ;
15461385 }
1547- BUG_ON (params_size + sizeof ("escan" ) >= BRCMF_DCMD_MEDLEN );
1548- brcmf_escan_prep (cfg , ifp , & params -> params_v2_le , request );
1549-
1550- if (brcmf_feat_is_enabled (ifp , BRCMF_FEAT_SCAN_V3 )) {
1551- params -> version = cpu_to_le32 (BRCMF_ESCAN_REQ_VERSION_V3 );
1552- } else if (brcmf_feat_is_enabled (ifp , BRCMF_FEAT_SCAN_V2 )) {
1553- params -> version = cpu_to_le32 (BRCMF_ESCAN_REQ_VERSION_V2 );
1554- } else {
1555- struct brcmf_escan_params_le * params_v1 ;
1556-
1557- params_size -= BRCMF_SCAN_PARAMS_V2_FIXED_SIZE ;
1558- params_size += BRCMF_SCAN_PARAMS_FIXED_SIZE ;
1559- params_v1 = kzalloc (params_size , GFP_KERNEL );
1560- if (!params_v1 ) {
1561- err = - ENOMEM ;
1562- goto exit_params ;
1563- }
1564- params_v1 -> version = cpu_to_le32 (BRCMF_ESCAN_REQ_VERSION );
1565- brcmf_scan_params_v2_to_v1 (& params -> params_v2_le , & params_v1 -> params_le );
1566- kfree (params );
1567- params = params_v1 ;
1568- }
1386+ /* Copy into the largest part */
1387+ unsafe_memcpy (
1388+ & params -> params_v4_le , prepped_params , struct_size ,
1389+ /* A composite flex-array that is at least as large as the memcpy due to the allocation above */ );
15691390
1391+ /* We can now free the original prepped parameters */
1392+ kfree (prepped_params );
1393+ params -> version = cpu_to_le32 (drvr -> scan_param_handler .version );
15701394 params -> action = cpu_to_le16 (WL_ESCAN_ACTION_START );
15711395 params -> sync_id = cpu_to_le16 (0x1234 );
15721396
@@ -1578,7 +1402,6 @@ brcmf_run_escan(struct brcmf_cfg80211_info *cfg, struct brcmf_if *ifp,
15781402 bphy_err (drvr , "error (%d)\n" , err );
15791403 }
15801404
1581- exit_params :
15821405 kfree (params );
15831406exit :
15841407 return err ;
0 commit comments