int lbs_stop_iface(struct lbs_private *priv) { unsigned long flags; int ret = 0; lbs_deb_enter(LBS_DEB_MAIN); spin_lock_irqsave(&priv->driver_lock, flags); priv->iface_running = false; kfree_skb(priv->currenttxskb); priv->currenttxskb = NULL; priv->tx_pending_len = 0; spin_unlock_irqrestore(&priv->driver_lock, flags); cancel_work_sync(&priv->mcast_work); del_timer_sync(&priv->tx_lockup_timer); /* Disable command processing, and wait for all commands to complete */ lbs_deb_main("waiting for commands to complete\n"); wait_event(priv->waitq, lbs_command_queue_empty(priv)); lbs_deb_main("all commands completed\n"); if (priv->power_save) ret = priv->power_save(priv); lbs_deb_leave(LBS_DEB_MAIN); return ret; }
/** * auto_deepsleep_timer_fn - put the device back to deep sleep mode when * timer expires and no activity (command, event, data etc.) is detected. * @data: &struct lbs_private pointer * returns: N/A */ static void auto_deepsleep_timer_fn(unsigned long data) { struct lbs_private *priv = (struct lbs_private *)data; lbs_deb_enter(LBS_DEB_CMD); if (priv->is_activity_detected) { priv->is_activity_detected = 0; } else { if (priv->is_auto_deep_sleep_enabled && (!priv->wakeup_dev_required) && (priv->connect_status != LBS_CONNECTED)) { struct cmd_header cmd; lbs_deb_main("Entering auto deep sleep mode...\n"); memset(&cmd, 0, sizeof(cmd)); cmd.size = cpu_to_le16(sizeof(cmd)); lbs_cmd_async(priv, CMD_802_11_DEEP_SLEEP, &cmd, sizeof(cmd)); } } mod_timer(&priv->auto_deepsleep_timer , jiffies + (priv->auto_deep_sleep_timeout * HZ)/1000); lbs_deb_leave(LBS_DEB_CMD); }
void lbs_remove_card(struct lbs_private *priv) { struct net_device *dev = priv->dev; lbs_remove_mesh(priv); if (priv->wiphy_registered) lbs_scan_deinit(priv); lbs_wait_for_firmware_load(priv); /* worker thread destruction blocks on the in-flight command which * should have been cleared already in lbs_stop_card(). */ lbs_deb_main("destroying worker thread\n"); destroy_workqueue(priv->work_thread); lbs_deb_main("done destroying worker thread\n"); if (priv->psmode == LBS802_11POWERMODEMAX_PSP) { priv->psmode = LBS802_11POWERMODECAM; /* no need to wakeup if already woken up, * on suspend, this exit ps command is not processed * the driver hangs */ if (priv->psstate != PS_STATE_FULL_POWER) lbs_set_ps_mode(priv, PS_MODE_ACTION_EXIT_PS, true); } if (priv->is_deep_sleep) { priv->is_deep_sleep = 0; wake_up_interruptible(&priv->ds_awake_q); } priv->is_host_sleep_configured = 0; priv->is_host_sleep_activated = 0; wake_up_interruptible(&priv->host_sleep_q); /* Stop the thread servicing the interrupts */ priv->surpriseremoved = 1; kthread_stop(priv->main_thread); lbs_free_adapter(priv); lbs_cfg_free(priv); free_netdev(dev); }
void lbs_remove_card(struct lbs_private *priv) { struct net_device *dev = priv->dev; lbs_deb_enter(LBS_DEB_MAIN); lbs_remove_mesh(priv); lbs_scan_deinit(priv); /* worker thread destruction blocks on the in-flight command which * should have been cleared already in lbs_stop_card(). */ lbs_deb_main("destroying worker thread\n"); destroy_workqueue(priv->work_thread); lbs_deb_main("done destroying worker thread\n"); if (priv->psmode == LBS802_11POWERMODEMAX_PSP) { priv->psmode = LBS802_11POWERMODECAM; lbs_set_ps_mode(priv, PS_MODE_ACTION_EXIT_PS, true); } if (priv->is_deep_sleep) { priv->is_deep_sleep = 0; wake_up_interruptible(&priv->ds_awake_q); } priv->is_host_sleep_configured = 0; priv->is_host_sleep_activated = 0; wake_up_interruptible(&priv->host_sleep_q); /* Stop the thread servicing the interrupts */ priv->surpriseremoved = 1; kthread_stop(priv->main_thread); lbs_free_adapter(priv); lbs_cfg_free(priv); free_netdev(dev); lbs_deb_leave(LBS_DEB_MAIN); }