@@ -1115,6 +1115,18 @@ static int iwl_get_channels_for_scan(struct iwl_priv *priv,
11151115return added ;
11161116}
11171117
1118+ static int iwl_fill_offch_tx (struct iwl_priv * priv , void * data , size_t maxlen )
1119+ {
1120+ struct sk_buff * skb = priv -> _agn .offchan_tx_skb ;
1121+
1122+ if (skb -> len < maxlen )
1123+ maxlen = skb -> len ;
1124+
1125+ memcpy (data , skb -> data , maxlen );
1126+
1127+ return maxlen ;
1128+ }
1129+
11181130int iwlagn_request_scan (struct iwl_priv * priv , struct ieee80211_vif * vif )
11191131{
11201132struct iwl_host_cmd cmd = {
@@ -1157,17 +1169,25 @@ int iwlagn_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif)
11571169scan -> quiet_plcp_th = IWL_PLCP_QUIET_THRESH ;
11581170scan -> quiet_time = IWL_ACTIVE_QUIET_TIME ;
11591171
1160- if (iwl_is_any_associated (priv )) {
1172+ if (priv -> scan_type != IWL_SCAN_OFFCH_TX &&
1173+ iwl_is_any_associated (priv )) {
11611174u16 interval = 0 ;
11621175u32 extra ;
11631176u32 suspend_time = 100 ;
11641177u32 scan_suspend_time = 100 ;
11651178
11661179IWL_DEBUG_INFO (priv , "Scanning while associated...\n" );
1167- if (priv -> is_internal_short_scan )
1180+ switch (priv -> scan_type ) {
1181+ case IWL_SCAN_OFFCH_TX :
1182+ WARN_ON (1 );
1183+ break ;
1184+ case IWL_SCAN_RADIO_RESET :
11681185interval = 0 ;
1169- else
1186+ break ;
1187+ case IWL_SCAN_NORMAL :
11701188interval = vif -> bss_conf .beacon_int ;
1189+ break ;
1190+ }
11711191
11721192scan -> suspend_time = 0 ;
11731193scan -> max_out_time = cpu_to_le32 (200 * 1024 );
@@ -1180,29 +1200,41 @@ int iwlagn_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif)
11801200scan -> suspend_time = cpu_to_le32 (scan_suspend_time );
11811201IWL_DEBUG_SCAN (priv , "suspend_time 0x%X beacon interval %d\n" ,
11821202 scan_suspend_time , interval );
1203+ } else if (priv -> scan_type == IWL_SCAN_OFFCH_TX ) {
1204+ scan -> suspend_time = 0 ;
1205+ scan -> max_out_time =
1206+ cpu_to_le32 (1024 * priv -> _agn .offchan_tx_timeout );
11831207}
11841208
1185- if (priv -> is_internal_short_scan ) {
1209+ switch (priv -> scan_type ) {
1210+ case IWL_SCAN_RADIO_RESET :
11861211IWL_DEBUG_SCAN (priv , "Start internal passive scan.\n" );
1187- } else if (priv -> scan_request -> n_ssids ) {
1188- int i , p = 0 ;
1189- IWL_DEBUG_SCAN (priv , "Kicking off active scan\n" );
1190- for (i = 0 ; i < priv -> scan_request -> n_ssids ; i ++ ) {
1191- /* always does wildcard anyway */
1192- if (!priv -> scan_request -> ssids [i ].ssid_len )
1193- continue ;
1194- scan -> direct_scan [p ].id = WLAN_EID_SSID ;
1195- scan -> direct_scan [p ].len =
1196- priv -> scan_request -> ssids [i ].ssid_len ;
1197- memcpy (scan -> direct_scan [p ].ssid ,
1198- priv -> scan_request -> ssids [i ].ssid ,
1199- priv -> scan_request -> ssids [i ].ssid_len );
1200- n_probes ++ ;
1201- p ++ ;
1202- }
1203- is_active = true;
1204- } else
1205- IWL_DEBUG_SCAN (priv , "Start passive scan.\n" );
1212+ break ;
1213+ case IWL_SCAN_NORMAL :
1214+ if (priv -> scan_request -> n_ssids ) {
1215+ int i , p = 0 ;
1216+ IWL_DEBUG_SCAN (priv , "Kicking off active scan\n" );
1217+ for (i = 0 ; i < priv -> scan_request -> n_ssids ; i ++ ) {
1218+ /* always does wildcard anyway */
1219+ if (!priv -> scan_request -> ssids [i ].ssid_len )
1220+ continue ;
1221+ scan -> direct_scan [p ].id = WLAN_EID_SSID ;
1222+ scan -> direct_scan [p ].len =
1223+ priv -> scan_request -> ssids [i ].ssid_len ;
1224+ memcpy (scan -> direct_scan [p ].ssid ,
1225+ priv -> scan_request -> ssids [i ].ssid ,
1226+ priv -> scan_request -> ssids [i ].ssid_len );
1227+ n_probes ++ ;
1228+ p ++ ;
1229+ }
1230+ is_active = true;
1231+ } else
1232+ IWL_DEBUG_SCAN (priv , "Start passive scan.\n" );
1233+ break ;
1234+ case IWL_SCAN_OFFCH_TX :
1235+ IWL_DEBUG_SCAN (priv , "Start offchannel TX scan.\n" );
1236+ break ;
1237+ }
12061238
12071239scan -> tx_cmd .tx_flags = TX_CMD_FLG_SEQ_CTL_MSK ;
12081240scan -> tx_cmd .sta_id = ctx -> bcast_sta_id ;
@@ -1300,38 +1332,77 @@ int iwlagn_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif)
13001332rx_chain |= rx_ant << RXON_RX_CHAIN_FORCE_SEL_POS ;
13011333rx_chain |= 0x1 << RXON_RX_CHAIN_DRIVER_FORCE_POS ;
13021334scan -> rx_chain = cpu_to_le16 (rx_chain );
1303- if (!priv -> is_internal_short_scan ) {
1335+ switch (priv -> scan_type ) {
1336+ case IWL_SCAN_NORMAL :
13041337cmd_len = iwl_fill_probe_req (priv ,
13051338(struct ieee80211_mgmt * )scan -> data ,
13061339vif -> addr ,
13071340priv -> scan_request -> ie ,
13081341priv -> scan_request -> ie_len ,
13091342IWL_MAX_SCAN_SIZE - sizeof (* scan ));
1310- } else {
1343+ break ;
1344+ case IWL_SCAN_RADIO_RESET :
13111345/* use bcast addr, will not be transmitted but must be valid */
13121346cmd_len = iwl_fill_probe_req (priv ,
13131347(struct ieee80211_mgmt * )scan -> data ,
13141348iwl_bcast_addr , NULL , 0 ,
13151349IWL_MAX_SCAN_SIZE - sizeof (* scan ));
1316-
1350+ break ;
1351+ case IWL_SCAN_OFFCH_TX :
1352+ cmd_len = iwl_fill_offch_tx (priv , scan -> data ,
1353+ IWL_MAX_SCAN_SIZE
1354+ - sizeof (* scan )
1355+ - sizeof (struct iwl_scan_channel ));
1356+ scan -> scan_flags |= IWL_SCAN_FLAGS_ACTION_FRAME_TX ;
1357+ break ;
1358+ default :
1359+ BUG ();
13171360}
13181361scan -> tx_cmd .len = cpu_to_le16 (cmd_len );
13191362
13201363scan -> filter_flags |= (RXON_FILTER_ACCEPT_GRP_MSK |
13211364 RXON_FILTER_BCON_AWARE_MSK );
13221365
1323- if (priv -> is_internal_short_scan ) {
1366+ switch (priv -> scan_type ) {
1367+ case IWL_SCAN_RADIO_RESET :
13241368scan -> channel_count =
13251369iwl_get_single_channel_for_scan (priv , vif , band ,
1326- (void * )& scan -> data [le16_to_cpu (
1327- scan -> tx_cmd . len )]) ;
1328- } else {
1370+ (void * )& scan -> data [cmd_len ]);
1371+ break ;
1372+ case IWL_SCAN_NORMAL :
13291373scan -> channel_count =
13301374iwl_get_channels_for_scan (priv , vif , band ,
13311375is_active , n_probes ,
1332- (void * )& scan -> data [le16_to_cpu (
1333- scan -> tx_cmd .len )]);
1376+ (void * )& scan -> data [cmd_len ]);
1377+ break ;
1378+ case IWL_SCAN_OFFCH_TX : {
1379+ struct iwl_scan_channel * scan_ch ;
1380+
1381+ scan -> channel_count = 1 ;
1382+
1383+ scan_ch = (void * )& scan -> data [cmd_len ];
1384+ scan_ch -> type = SCAN_CHANNEL_TYPE_ACTIVE ;
1385+ scan_ch -> channel =
1386+ cpu_to_le16 (priv -> _agn .offchan_tx_chan -> hw_value );
1387+ scan_ch -> active_dwell =
1388+ cpu_to_le16 (priv -> _agn .offchan_tx_timeout );
1389+ scan_ch -> passive_dwell = 0 ;
1390+
1391+ /* Set txpower levels to defaults */
1392+ scan_ch -> dsp_atten = 110 ;
1393+
1394+ /* NOTE: if we were doing 6Mb OFDM for scans we'd use
1395+ * power level:
1396+ * scan_ch->tx_gain = ((1 << 5) | (2 << 3)) | 3;
1397+ */
1398+ if (priv -> _agn .offchan_tx_chan -> band == IEEE80211_BAND_5GHZ )
1399+ scan_ch -> tx_gain = ((1 << 5 ) | (3 << 3 )) | 3 ;
1400+ else
1401+ scan_ch -> tx_gain = ((1 << 5 ) | (5 << 3 ));
1402+ }
1403+ break ;
13341404}
1405+
13351406if (scan -> channel_count == 0 ) {
13361407IWL_DEBUG_SCAN (priv , "channel count %d\n" , scan -> channel_count );
13371408return - EIO ;
0 commit comments