/** * @brief Exit deep sleep with timeout * * @param priv A pointer to wlan_private structure * @return WLAN_STATUS_SUCCESS or WLAN_STATUS_FAILURE */ int wlan_exit_deep_sleep_timeout(wlan_private * priv) { wlan_adapter *Adapter = priv->adapter; int ret = WLAN_STATUS_SUCCESS; ENTER(); Adapter->IsAutoDeepSleepEnabled = FALSE; if (Adapter->IsDeepSleep == TRUE) { PRINTM(CMND, "Exit deep sleep... @ %lu\n", os_time_get()); sbi_exit_deep_sleep(priv); if (Adapter->IsDeepSleep == TRUE) { if (os_wait_interruptible_timeout(Adapter->ds_awake_q, !Adapter->IsDeepSleep, MRVDRV_DEEP_SLEEP_EXIT_TIMEOUT) == 0) { PRINTM(MSG, "ds_awake_q: timer expired\n"); ret = WLAN_STATUS_FAILURE; } } } LEAVE(); return ret; }
/** * @brief This function handles the major job in WLAN driver. * it handles the event generated by firmware, rx data received * from firmware and tx data sent from kernel. * * @param data A pointer to wlan_thread structure * @return WLAN_STATUS_SUCCESS */ static int wlan_service_main_thread(void *data) { wlan_thread *thread = data; wlan_private *priv = thread->priv; wlan_adapter *Adapter = priv->adapter; wait_queue_t wait; u8 ireg = 0; unsigned long driver_flags; OS_INTERRUPT_SAVE_AREA; ENTER(); wlan_activate_thread(thread); init_waitqueue_entry(&wait, current); #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) current->flags |= PF_NOFREEZE; #endif wlan_meas_init(priv); PRINTM(INFO, "11H: init 11H\n"); wlan_11h_init(priv); wmm_init(priv); for (;;) { #define MAX_MAIN_THREAD_LOOPS (10000) if (++Adapter->main_thread_loops > MAX_MAIN_THREAD_LOOPS) { panic("main-thread dead loop detected: %u\n" "IntCnt=%d\n" "Adapter->HisRegCpy=%#x\n" "CurCmd=%p CmdPending=%s\n" "Connect=%s\n" "cmd_sent=%s\n" "data_sent=%s\n" "IsDeepSleep=%d\n" "PSMode=%d PSState=%d\n" "WakeupDevReq=%d\n" "HS_Activated=%d\n" "WakeupTries=%d\n", Adapter->main_thread_loops, Adapter->IntCounter, Adapter->HisRegCpy, Adapter->CurCmd, list_empty(&Adapter->CmdPendingQ) ? "N" : "Y", (Adapter->MediaConnectStatus == WlanMediaStateConnected) ? "Y" : "N", (priv->wlan_dev.cmd_sent) ? "TRUE" : "FALSE", (priv->wlan_dev.data_sent) ? "TRUE" : "FALSE", Adapter->IsDeepSleep, Adapter->PSMode, Adapter->PSState, Adapter->bWakeupDevRequired, Adapter->HS_Activated, Adapter->WakeupTries); } add_wait_queue(&thread->waitQ, &wait); OS_SET_THREAD_STATE(TASK_INTERRUPTIBLE); TX_DISABLE; if ((Adapter->WakeupTries) || (Adapter->PSState == PS_STATE_SLEEP && !Adapter->bWakeupDevRequired) || (!Adapter->IntCounter && Adapter->PSState == PS_STATE_PRE_SLEEP) || (!Adapter->IntCounter && (priv->wlan_dev.data_sent || Adapter->TxLockFlag || wmm_lists_empty(priv) || wmm_is_queue_stopped(priv)) && (priv->wlan_dev.cmd_sent || Adapter->CurCmd || list_empty(&Adapter->CmdPendingQ)) ) ) { PRINTM(INFO, "main-thread sleeping... " "HS_Act=%s WakeupReq=%s Conn=%s PS_Mode=%d PS_State=%d\n", (Adapter->HS_Activated) ? "Y" : "N", (Adapter->bWakeupDevRequired) ? "Y" : "N", (Adapter->MediaConnectStatus) ? "Y" : "N", Adapter->PSMode, Adapter->PSState); TX_RESTORE; Adapter->main_thread_loops = 0; schedule(); PRINTM(INFO, "main-thread waking up: IntCnt=%d " "CurCmd=%s CmdPending=%s\n" " Connect=%s " "cmd_sent=%s data_sent=%s\n", Adapter->IntCounter, (Adapter->CurCmd) ? "Y" : "N", list_empty(&Adapter->CmdPendingQ) ? "N" : "Y", (Adapter->MediaConnectStatus) ? "Y" : "N", (priv->wlan_dev.cmd_sent) ? "TRUE" : "FALSE", (priv->wlan_dev.data_sent) ? "TRUE" : "FALSE"); } else { TX_RESTORE; } OS_SET_THREAD_STATE(TASK_RUNNING); remove_wait_queue(&thread->waitQ, &wait); #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) if ((thread->state == WLAN_THREAD_STOPPED) || Adapter->SurpriseRemoved) #else if (kthread_should_stop() || Adapter->SurpriseRemoved) #endif { PRINTM(INFO, "main-thread: break from main thread: " "SurpriseRemoved=0x%x\n", Adapter->SurpriseRemoved); break; } if (Adapter->IntCounter) { OS_INT_DISABLE(priv, driver_flags); Adapter->IntCounter = 0; OS_INT_RESTORE(priv, driver_flags); if (sbi_get_int_status(priv, &ireg)) { PRINTM(ERROR, "main-thread: reading HOST_INT_STATUS_REG failed\n"); continue; } /* If we have a valid interrupt then we have something to do, so we are not running in a dead loop */ if (ireg) Adapter->main_thread_loops = 0; OS_INT_DISABLE(priv, driver_flags); Adapter->HisRegCpy |= ireg; OS_INT_RESTORE(priv, driver_flags); PRINTM(INTR, "INT: status = 0x%x\n", Adapter->HisRegCpy); } else if (Adapter->bWakeupDevRequired) { Adapter->WakeupTries++; PRINTM(CMND, "Wakeup device... WakeupReq=%s Conn=%s PS_Mode=%d PS_State=%d @ %lu\n", (Adapter->bWakeupDevRequired) ? "Y" : "N", (priv->adapter->MediaConnectStatus) ? "Y" : "N", priv->adapter->PSMode, priv->adapter->PSState, os_time_get()); /* Wake up device */ if (sbi_exit_deep_sleep(priv)) PRINTM(MSG, "main-thread: wakeup device failed\n"); continue; } /* Command response? */ if (Adapter->HisRegCpy & HIS_CmdUpLdRdy) { OS_INT_DISABLE(priv, driver_flags); Adapter->HisRegCpy &= ~HIS_CmdUpLdRdy; OS_INT_RESTORE(priv, driver_flags); wlan_process_cmdresp(priv); } /* Any Card Event */ if (Adapter->HisRegCpy & HIS_CardEvent) { OS_INT_DISABLE(priv, driver_flags); Adapter->HisRegCpy &= ~HIS_CardEvent; OS_INT_RESTORE(priv, driver_flags); wlan_process_event(priv); } /* Check if we need to confirm Sleep Request received previously */ if (Adapter->PSState == PS_STATE_PRE_SLEEP) { if (!priv->wlan_dev.cmd_sent && !Adapter->CurCmd) { ASSERT(Adapter->MediaConnectStatus == WlanMediaStateConnected); wlan_ps_cond_check(priv, (u16) Adapter->PSMode); } } /* The PS state is changed during processing of Sleep Request event above */ if ((Adapter->PSState == PS_STATE_SLEEP) || (Adapter->PSState == PS_STATE_PRE_SLEEP)) continue; if (Adapter->IsDeepSleep) continue; /* The HS_Activated flag is changed during processing of HS_Activate command resp */ /* We cannot send command or data if HS_Activated and WakeupDevRequired are TRUE */ if (Adapter->HS_Activated && Adapter->bWakeupDevRequired) { PRINTM(INFO, "main-thread: cannot send command or data, " "HS_Activated=%d\n", Adapter->HS_Activated); continue; } /* Execute the next command */ if (!priv->wlan_dev.cmd_sent && !Adapter->CurCmd) wlan_exec_next_cmd(priv); if (!priv->wlan_dev.data_sent && !wmm_lists_empty(priv) && !wmm_is_queue_stopped(priv)) { if ((Adapter->PSState == PS_STATE_FULL_POWER) || (Adapter->sleep_period.period == 0) || (Adapter->TxLockFlag == FALSE)) wmm_process_tx(priv); } } wlan_deactivate_thread(thread); LEAVE(); return WLAN_STATUS_SUCCESS; }
/** * @brief This function hanldes the major job in WLAN driver. * it handles the event generated by firmware, rx data received * from firmware and tx data sent from kernel. * * @param data A pointer to wlan_thread structure * @return WLAN_STATUS_SUCCESS */ static void wlan_service_main_thread(cyg_addrword_t data) { struct eth_drv_sc *sc = (struct eth_drv_sc *)data; wlan_private *priv = (wlan_private *)sc->driver_private; w99702_priv_t * priv702 = priv->priv; wlan_thread *thread = &priv->MainThread; wlan_adapter *Adapter = priv->adapter; //wait_queue_t wait; cyg_uint8 ireg = 0; int volatile save_irq; int x; int ret; //OS_INTERRUPT_SAVE_AREA; ENTER(); wlan_activate_thread(thread); thread_stop_ptr[0] = NULL; //init_waitqueue_entry(&wait, current); for (;;) { #if 0 diag_printf("main-thread 111: IntCounter=%d " "CurCmd=%p CmdPending=%s Connect=%d " "dnld_sent=%d\n", Adapter->IntCounter, Adapter->CurCmd, list_empty(&Adapter->CmdPendingQ) ? "N" : "Y", Adapter->MediaConnectStatus, /*Adapter->CurrentTxSkb,*/ priv->wlan_dev.dnld_sent); #endif //add_wait_queue(&thread->waitQ, &wait); //OS_SET_THREAD_STATE(TASK_INTERRUPTIBLE); TX_DISABLE; if ((Adapter->WakeupTries) || (Adapter->PSState == PS_STATE_SLEEP && !Adapter->bWakeupDevRequired) || (!Adapter->IntCounter && (priv->wlan_dev.dnld_sent || !Adapter->wmm.enabled || Adapter->TxLockFlag /*|| !os_queue_is_active(priv)*/ || wmm_lists_empty(priv)) && (priv->wlan_dev.dnld_sent || Adapter->TxLockFlag || !Adapter->TxSkbNum) && (priv->wlan_dev.dnld_sent || Adapter->CurCmd || list_empty(&Adapter->CmdPendingQ)) ) ) { #if 0 diag_printf( "main-thread sleeping... Conn=%d IntC=%d PS_Mode=%d PS_State=%d\n", Adapter->MediaConnectStatus, Adapter->IntCounter, Adapter->PSMode, Adapter->PSState); #endif #ifdef _MAINSTONE MST_LEDDAT1 = get_utimeofday(); #endif TX_RESTORE; //schedule(); /* Lock control thread to avoid re-entry when waiting event. ??? */ //cyg_mutex_lock(&thread->waitQ_mutex); //diag_printf("main_thread wait\n"); /* Waitint until any event input */ x = cyg_flag_wait( &thread->waitQ_flag_q, -1, CYG_FLAG_WAITMODE_OR | CYG_FLAG_WAITMODE_CLR ); //diag_printf("main_thread wakeup %d\n", Adapter->IntCounter); /* ----------if keypad pressed then print message----------------- */ //if ( 2 & x ) } else { TX_RESTORE; } #if 0 diag_printf( "main-thread 222 (waking up): IntCounter=%d " "dnld_sent=%d\n", Adapter->IntCounter, /*Adapter->CurrentTxSkb,*/ priv->wlan_dev.dnld_sent); //OS_SET_THREAD_STATE(TASK_RUNNING); //remove_wait_queue(&thread->waitQ, &wait); diag_printf("main-thread 333: IntCounter=%d "//CurrentTxSkb=%p "dnld_sent=%d g_NeedWakeupMainThread = %d\n", Adapter->IntCounter, /*Adapter->CurrentTxSkb,*/ priv->wlan_dev.dnld_sent, g_WakeupMainThreadStatus); #endif if (thread_should_stop() || Adapter->SurpriseRemoved) { diag_printf( "main-thread: break from main thread: SurpriseRemoved=0x%x\n", Adapter->SurpriseRemoved); break; } //OS_INT_DISABLE(save_irq); if(Adapter->IntCounter) { Adapter->IntCounter = 0; if ((ret = sbi_get_int_status(sc, &ireg)) < 0) { diag_printf("main-thread: reading HOST_INT_STATUS_REG failed\n"); //OS_INT_RESTORE(save_irq); continue; } OS_INT_DISABLE(save_irq); Adapter->HisRegCpy |= ireg; OS_INT_RESTORE(save_irq); } //else if (Adapter->bWakeupDevRequired && ((Adapter->PSState == PS_STATE_SLEEP))) else if (Adapter->bWakeupDevRequired && Adapter->HS_Activated) //JONO { //OS_INT_RESTORE(save_irq); Adapter->WakeupTries++; /* we borrow deep_sleep wakeup code for time being */ if (sbi_exit_deep_sleep(priv)) diag_printf("main-thread: wakeup dev failed\n"); continue; } //else OS_INT_RESTORE(save_irq); #if 0 diag_printf("main-thread 444: IntCounter=%d "// CurrentTxSkb=%p "dnld_sent=%d TxSkbNum=%d\n", Adapter->IntCounter, /*Adapter->CurrentTxSkb,*/ priv->wlan_dev.dnld_sent, Adapter->TxSkbNum); diag_printf("Adapter->HisRegCpy = %x, %d, %d, %d\n", Adapter->HisRegCpy, priv->wlan_dev.dnld_sent, Adapter->TxLockFlag, priv->open); #endif /* Command response? */ if (Adapter->HisRegCpy & HIS_CmdUpLdRdy) { //diag_printf("main-thread: Cmd response ready.\n"); OS_INT_DISABLE(save_irq); Adapter->HisRegCpy &= ~HIS_CmdUpLdRdy; OS_INT_RESTORE(save_irq); wlan_process_rx_command(priv); } /* Any received data? */ #if 1 if (Adapter->HisRegCpy & HIS_RxUpLdRdy) { //diag_printf("main-thread: Rx Packet ready.\n"); OS_INT_DISABLE(save_irq); Adapter->HisRegCpy &= ~HIS_RxUpLdRdy; OS_INT_RESTORE(save_irq); //wlan_send_rxskbQ(priv); if((priv702->rx_head != priv702->rx_tail) || !priv702->rx_head->mode) eth_drv_dsr(0, 0, (cyg_addrword_t)sc); } else OS_INT_RESTORE(save_irq); #endif /* Any Card Event */ if (Adapter->HisRegCpy & HIS_CardEvent) { //diag_printf("main-thread: Card Event Activity.\n"); OS_INT_DISABLE(save_irq); Adapter->HisRegCpy &= ~HIS_CardEvent; OS_INT_RESTORE(save_irq); if (sbi_read_event_cause(priv)) { diag_printf("main-thread: sbi_read_event_cause failed.\n"); continue; } wlan_process_event(priv); } /* Check if we need to confirm Sleep Request received previously */ if (Adapter->PSState == PS_STATE_PRE_SLEEP) { if (!priv->wlan_dev.dnld_sent && !Adapter->CurCmd) { if (Adapter->MediaConnectStatus == WlanMediaStateConnected) { diag_printf( "main_thread: PRE_SLEEP--IntCounter=%d "// CurrentTxSkb=%p "dnld_sent=%d CurCmd=%p, confirm now\n", Adapter->IntCounter, /*Adapter->CurrentTxSkb,*/ priv->wlan_dev.dnld_sent, Adapter->CurCmd); PSConfirmSleep(priv, (cyg_uint16) Adapter->PSMode); } else { /* workaround for firmware sending deauth/linkloss event immediately after sleep request, remove this after firmware fixes it */ Adapter->PSState = PS_STATE_AWAKE; diag_printf( "main-thread: ignore PS_SleepConfirm in non-connected state\n"); } } } /* The PS state is changed during processing of Sleep Request event above */ if ((priv->adapter->PSState == PS_STATE_SLEEP) || (priv->adapter->PSState == PS_STATE_PRE_SLEEP) ) { diag_printf("999 The PS state is changed during processing ... %d\n", priv->adapter->PSState); continue; //JONO } if (Adapter->HS_Activated && Adapter->bWakeupDevRequired) { //JONO diag_printf( "main-thread: cannot send command or date, HS_Activated=%d\n", Adapter->HS_Activated); //JONO continue; } /* Execute the next command */ if (!priv->wlan_dev.dnld_sent && !Adapter->CurCmd) { ExecuteNextCommand(priv); } if (Adapter->wmm.enabled) { if (!wmm_lists_empty(priv) && (priv->open == TRUE)/* && os_queue_is_active(priv)*/) { if ((Adapter->PSState == PS_STATE_FULL_POWER) || (Adapter->sleep_period.period == 0) || (Adapter->TxLockFlag == FALSE)) //wmm_process_tx(priv); handle_send(sc); } } else { if (!priv->wlan_dev.dnld_sent && (Adapter->TxLockFlag == false) &&(priv->open == TRUE) /*&& !list_empty((struct list_head *) &priv->adapter->TxSkbQ)*/) { //wlan_process_txqueue(priv); //diag_printf("send01\n"); handle_send(sc); //diag_printf("send02\n"); } } } wlan_deactivate_thread(thread); LEAVE(); return ;//WLAN_STATUS_SUCCESS; }
/** * @brief This function removes the card. * * @param priv A pointer to card * @return WLAN_STATUS_SUCCESS */ static int wlan_remove_card(void *card) { wlan_private *priv = &w99702_priv_data0; wlan_adapter *Adapter; //struct net_device *dev; struct cyg_netdevtab_entry *dev; struct eth_drv_sc *sc; union iwreq_data wrqu; ENTER(); if (!priv) { LEAVE(); return WLAN_STATUS_SUCCESS; } Adapter = priv->adapter; if (!Adapter) { LEAVE(); return WLAN_STATUS_SUCCESS; } dev = priv->wlan_dev.netdev; sc = (struct eth_drv_sc *)dev->device_instance; // wake_up_interruptible(&Adapter->ds_awake_q); cyg_cond_broadcast(&Adapter->ds_cond_q); if (Adapter->CurCmd) { diag_printf("Wake up current cmdwait_q\n"); // wake_up_interruptible(&Adapter->CurCmd->cmdwait_q); cyg_flag_setbits( &Adapter->CurCmd->cmdwait_flag_q, 3 ); } Adapter->CurCmd = NULL; if (Adapter->PSMode == Wlan802_11PowerModeMAX_PSP) { Adapter->PSMode = Wlan802_11PowerModeCAM; PSWakeup(priv, HostCmd_OPTION_WAITFORRSP); } if (Adapter->IsDeepSleep == TRUE) { Adapter->IsDeepSleep = FALSE; sbi_exit_deep_sleep(priv); } memset(wrqu.ap_addr.sa_data, 0xaa, ETH_ALEN); wrqu.ap_addr.sa_family = ARPHRD_ETHER; wireless_send_event(priv->wlan_dev.netdev, SIOCGIWAP, &wrqu, NULL); /* Disable interrupts on the card as we cannot handle them after RESET */ sbi_disable_host_int(priv); PrepareAndSendCommand(priv, HostCmd_CMD_802_11_RESET, 0, 0, 0, NULL); cyg_thread_delay(20); //udelay(200*1000); #ifdef ENABLE_PM pm_unregister(wlan_pm_dev); #endif /* Flush all the packets upto the OS before stopping */ // wlan_send_rxskbQ(priv); eth_drv_dsr(0, 0, (cyg_addrword_t)sc); cleanup_txqueues(priv); // os_stop_queue(priv); // os_carrier_off(priv); Adapter->SurpriseRemoved = TRUE; /* Stop the thread servicing the interrupts */ //wake_up_interruptible(&priv->MainThread.waitQ); cyg_flag_setbits( &priv->MainThread.waitQ_flag_q, 1 ); #ifdef REASSOCIATION //wake_up_interruptible(&priv->ReassocThread.waitQ); cyg_flag_setbits( &priv->ReassocThread.waitQ_flag_q, 1 ); #endif /* REASSOCIATION */ #ifdef PROC_DEBUG wlan_debug_remove(priv); #endif // wlan_proc_remove(priv); diag_printf("unregester dev\n"); sbi_unregister_dev(priv); diag_printf("Free Adapter\n"); wlan_free_adapter(priv); /* Last reference is our one */ // diag_printf("refcnt = %d\n", atomic_read(&dev->refcnt)); // diag_printf("netdev_finish_unregister: %s%s.\n", dev->name, // (dev->features & NETIF_F_DYNALLOC) ? "" : ", old style"); // unregister_netdev(dev); diag_printf("Unregister finish\n"); priv->wlan_dev.netdev = NULL; //free_netdev(dev); //wlanpriv = NULL; LEAVE(); return WLAN_STATUS_SUCCESS; }