static int r8192_wx_set_scan(struct net_device *dev, struct iw_request_info *a, union iwreq_data *wrqu, char *b) { struct r8192_priv *priv = rtllib_priv(dev); struct rtllib_device *ieee = priv->rtllib; enum rt_rf_power_state rtState; int ret; if (!(ieee->softmac_features & IEEE_SOFTMAC_SCAN)) { if ((ieee->state >= RTLLIB_ASSOCIATING) && (ieee->state <= RTLLIB_ASSOCIATING_AUTHENTICATED)) return 0; if ((priv->rtllib->state == RTLLIB_LINKED) && (priv->rtllib->CntAfterLink < 2)) return 0; } if (priv->bHwRadioOff == true) { printk(KERN_INFO "================>%s(): hwradio off\n", __func__); return 0; } rtState = priv->rtllib->eRFPowerState; if (!priv->up) return -ENETDOWN; if (priv->rtllib->LinkDetectInfo.bBusyTraffic == true) return -EAGAIN; if (wrqu->data.flags & IW_SCAN_THIS_ESSID) { struct iw_scan_req *req = (struct iw_scan_req *)b; if (req->essid_len) { ieee->current_network.ssid_len = req->essid_len; memcpy(ieee->current_network.ssid, req->essid, req->essid_len); } } down(&priv->wx_sem); priv->rtllib->FirstIe_InScan = true; if (priv->rtllib->state != RTLLIB_LINKED) { if (priv->rtllib->PowerSaveControl.bInactivePs) { if (rtState == eRfOff) { if (priv->rtllib->RfOffReason > RF_CHANGE_BY_IPS) { RT_TRACE(COMP_ERR, "%s(): RF is " "OFF.\n", __func__); up(&priv->wx_sem); return -1; } else { RT_TRACE(COMP_PS, "=========>%s(): " "IPSLeave\n", __func__); down(&priv->rtllib->ips_sem); IPSLeave(dev); up(&priv->rtllib->ips_sem); } } } rtllib_stop_scan(priv->rtllib); if (priv->rtllib->LedControlHandler) priv->rtllib->LedControlHandler(dev, LED_CTL_SITE_SURVEY); if (priv->rtllib->eRFPowerState != eRfOff) { priv->rtllib->actscanning = true; if (ieee->ScanOperationBackupHandler) ieee->ScanOperationBackupHandler(ieee->dev, SCAN_OPT_BACKUP); rtllib_start_scan_syncro(priv->rtllib, 0); if (ieee->ScanOperationBackupHandler) ieee->ScanOperationBackupHandler(ieee->dev, SCAN_OPT_RESTORE); } ret = 0; } else { priv->rtllib->actscanning = true; ret = rtllib_wx_set_scan(priv->rtllib, a, wrqu, b); } up(&priv->wx_sem); return ret; }
void rtllib_wx_sync_scan_wq(void *data) { struct rtllib_device *ieee = container_of_work_rsl(data, struct rtllib_device, wx_sync_scan_wq); short chan; enum ht_extchnl_offset chan_offset = 0; enum ht_channel_width bandwidth = 0; int b40M = 0; if (!(ieee->softmac_features & IEEE_SOFTMAC_SCAN)) { rtllib_start_scan_syncro(ieee, 0); goto out; } chan = ieee->current_network.channel; if (ieee->LeisurePSLeave) ieee->LeisurePSLeave(ieee->dev); /* notify AP to be in PS mode */ rtllib_sta_ps_send_null_frame(ieee, 1); rtllib_sta_ps_send_null_frame(ieee, 1); rtllib_stop_all_queues(ieee); if (ieee->data_hard_stop) ieee->data_hard_stop(ieee->dev); rtllib_stop_send_beacons(ieee); ieee->state = RTLLIB_LINKED_SCANNING; ieee->link_change(ieee->dev); /* wait for ps packet to be kicked out successfully */ msleep(50); if (ieee->ScanOperationBackupHandler) ieee->ScanOperationBackupHandler(ieee->dev, SCAN_OPT_BACKUP); if (ieee->pHTInfo->bCurrentHTSupport && ieee->pHTInfo->bEnableHT && ieee->pHTInfo->bCurBW40MHz) { b40M = 1; chan_offset = ieee->pHTInfo->CurSTAExtChnlOffset; bandwidth = (enum ht_channel_width)ieee->pHTInfo->bCurBW40MHz; RT_TRACE(COMP_DBG, "Scan in 40M, force to 20M first:%d, %d\n", chan_offset, bandwidth); ieee->SetBWModeHandler(ieee->dev, HT_CHANNEL_WIDTH_20, HT_EXTCHNL_OFFSET_NO_EXT); } rtllib_start_scan_syncro(ieee, 0); if (b40M) { RT_TRACE(COMP_DBG, "Scan in 20M, back to 40M\n"); if (chan_offset == HT_EXTCHNL_OFFSET_UPPER) ieee->set_chan(ieee->dev, chan + 2); else if (chan_offset == HT_EXTCHNL_OFFSET_LOWER) ieee->set_chan(ieee->dev, chan - 2); else ieee->set_chan(ieee->dev, chan); ieee->SetBWModeHandler(ieee->dev, bandwidth, chan_offset); } else { ieee->set_chan(ieee->dev, chan); } if (ieee->ScanOperationBackupHandler) ieee->ScanOperationBackupHandler(ieee->dev, SCAN_OPT_RESTORE); ieee->state = RTLLIB_LINKED; ieee->link_change(ieee->dev); /* Notify AP that I wake up again */ rtllib_sta_ps_send_null_frame(ieee, 0); if (ieee->LinkDetectInfo.NumRecvBcnInPeriod == 0 || ieee->LinkDetectInfo.NumRecvDataInPeriod == 0) { ieee->LinkDetectInfo.NumRecvBcnInPeriod = 1; ieee->LinkDetectInfo.NumRecvDataInPeriod = 1; } if (ieee->data_hard_resume) ieee->data_hard_resume(ieee->dev); if (ieee->iw_mode == IW_MODE_ADHOC || ieee->iw_mode == IW_MODE_MASTER) rtllib_start_send_beacons(ieee); rtllib_wake_all_queues(ieee); out: mutex_unlock(&ieee->wx_mutex); }