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