aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/libertas/main.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/wireless/libertas/main.c')
-rw-r--r--drivers/net/wireless/libertas/main.c79
1 files changed, 55 insertions, 24 deletions
diff --git a/drivers/net/wireless/libertas/main.c b/drivers/net/wireless/libertas/main.c
index d9b8ee130c45..abfecc4814b4 100644
--- a/drivers/net/wireless/libertas/main.c
+++ b/drivers/net/wireless/libertas/main.c
@@ -625,16 +625,13 @@ static int lbs_thread(void *data)
625 return 0; 625 return 0;
626} 626}
627 627
628static int lbs_suspend_callback(struct lbs_private *priv, unsigned long dummy, 628static int lbs_ret_host_sleep_activate(struct lbs_private *priv,
629 struct cmd_header *cmd) 629 unsigned long dummy,
630 struct cmd_header *cmd)
630{ 631{
631 lbs_deb_enter(LBS_DEB_FW); 632 lbs_deb_enter(LBS_DEB_FW);
632 633 priv->is_host_sleep_activated = 1;
633 netif_device_detach(priv->dev); 634 wake_up_interruptible(&priv->host_sleep_q);
634 if (priv->mesh_dev)
635 netif_device_detach(priv->mesh_dev);
636
637 priv->fw_ready = 0;
638 lbs_deb_leave(LBS_DEB_FW); 635 lbs_deb_leave(LBS_DEB_FW);
639 return 0; 636 return 0;
640} 637}
@@ -646,39 +643,65 @@ int lbs_suspend(struct lbs_private *priv)
646 643
647 lbs_deb_enter(LBS_DEB_FW); 644 lbs_deb_enter(LBS_DEB_FW);
648 645
649 if (priv->wol_criteria == 0xffffffff) { 646 if (priv->is_deep_sleep) {
650 lbs_pr_info("Suspend attempt without configuring wake params!\n"); 647 ret = lbs_set_deep_sleep(priv, 0);
651 return -EINVAL; 648 if (ret) {
649 lbs_pr_err("deep sleep cancellation failed: %d\n", ret);
650 return ret;
651 }
652 priv->deep_sleep_required = 1;
652 } 653 }
653 654
654 memset(&cmd, 0, sizeof(cmd)); 655 memset(&cmd, 0, sizeof(cmd));
656 ret = lbs_host_sleep_cfg(priv, priv->wol_criteria,
657 (struct wol_config *)NULL);
658 if (ret) {
659 lbs_pr_info("Host sleep configuration failed: %d\n", ret);
660 return ret;
661 }
662 if (priv->psstate == PS_STATE_FULL_POWER) {
663 ret = __lbs_cmd(priv, CMD_802_11_HOST_SLEEP_ACTIVATE, &cmd,
664 sizeof(cmd), lbs_ret_host_sleep_activate, 0);
665 if (ret)
666 lbs_pr_info("HOST_SLEEP_ACTIVATE failed: %d\n", ret);
667 }
655 668
656 ret = __lbs_cmd(priv, CMD_802_11_HOST_SLEEP_ACTIVATE, &cmd, 669 if (!wait_event_interruptible_timeout(priv->host_sleep_q,
657 sizeof(cmd), lbs_suspend_callback, 0); 670 priv->is_host_sleep_activated, (10 * HZ))) {
658 if (ret) 671 lbs_pr_err("host_sleep_q: timer expired\n");
659 lbs_pr_info("HOST_SLEEP_ACTIVATE failed: %d\n", ret); 672 ret = -1;
673 }
674 netif_device_detach(priv->dev);
675 if (priv->mesh_dev)
676 netif_device_detach(priv->mesh_dev);
660 677
661 lbs_deb_leave_args(LBS_DEB_FW, "ret %d", ret); 678 lbs_deb_leave_args(LBS_DEB_FW, "ret %d", ret);
662 return ret; 679 return ret;
663} 680}
664EXPORT_SYMBOL_GPL(lbs_suspend); 681EXPORT_SYMBOL_GPL(lbs_suspend);
665 682
666void lbs_resume(struct lbs_private *priv) 683int lbs_resume(struct lbs_private *priv)
667{ 684{
668 lbs_deb_enter(LBS_DEB_FW); 685 int ret;
686 uint32_t criteria = EHS_REMOVE_WAKEUP;
669 687
670 priv->fw_ready = 1; 688 lbs_deb_enter(LBS_DEB_FW);
671 689
672 /* Firmware doesn't seem to give us RX packets any more 690 ret = lbs_host_sleep_cfg(priv, criteria, (struct wol_config *)NULL);
673 until we send it some command. Might as well update */
674 lbs_prepare_and_send_command(priv, CMD_802_11_RSSI, 0,
675 0, 0, NULL);
676 691
677 netif_device_attach(priv->dev); 692 netif_device_attach(priv->dev);
678 if (priv->mesh_dev) 693 if (priv->mesh_dev)
679 netif_device_attach(priv->mesh_dev); 694 netif_device_attach(priv->mesh_dev);
680 695
681 lbs_deb_leave(LBS_DEB_FW); 696 if (priv->deep_sleep_required) {
697 priv->deep_sleep_required = 0;
698 ret = lbs_set_deep_sleep(priv, 1);
699 if (ret)
700 lbs_pr_err("deep sleep activation failed: %d\n", ret);
701 }
702
703 lbs_deb_leave_args(LBS_DEB_FW, "ret %d", ret);
704 return ret;
682} 705}
683EXPORT_SYMBOL_GPL(lbs_resume); 706EXPORT_SYMBOL_GPL(lbs_resume);
684 707
@@ -834,10 +857,13 @@ static int lbs_init_adapter(struct lbs_private *priv)
834 priv->psstate = PS_STATE_FULL_POWER; 857 priv->psstate = PS_STATE_FULL_POWER;
835 priv->is_deep_sleep = 0; 858 priv->is_deep_sleep = 0;
836 priv->is_auto_deep_sleep_enabled = 0; 859 priv->is_auto_deep_sleep_enabled = 0;
860 priv->deep_sleep_required = 0;
837 priv->wakeup_dev_required = 0; 861 priv->wakeup_dev_required = 0;
838 init_waitqueue_head(&priv->ds_awake_q); 862 init_waitqueue_head(&priv->ds_awake_q);
839 priv->authtype_auto = 1; 863 priv->authtype_auto = 1;
840 864 priv->is_host_sleep_configured = 0;
865 priv->is_host_sleep_activated = 0;
866 init_waitqueue_head(&priv->host_sleep_q);
841 mutex_init(&priv->lock); 867 mutex_init(&priv->lock);
842 868
843 setup_timer(&priv->command_timer, lbs_cmd_timeout_handler, 869 setup_timer(&priv->command_timer, lbs_cmd_timeout_handler,
@@ -976,6 +1002,7 @@ struct lbs_private *lbs_add_card(void *card, struct device *dmdev)
976 1002
977 priv->wol_criteria = 0xffffffff; 1003 priv->wol_criteria = 0xffffffff;
978 priv->wol_gpio = 0xff; 1004 priv->wol_gpio = 0xff;
1005 priv->wol_gap = 20;
979 1006
980 goto done; 1007 goto done;
981 1008
@@ -1031,6 +1058,10 @@ void lbs_remove_card(struct lbs_private *priv)
1031 wake_up_interruptible(&priv->ds_awake_q); 1058 wake_up_interruptible(&priv->ds_awake_q);
1032 } 1059 }
1033 1060
1061 priv->is_host_sleep_configured = 0;
1062 priv->is_host_sleep_activated = 0;
1063 wake_up_interruptible(&priv->host_sleep_q);
1064
1034 /* Stop the thread servicing the interrupts */ 1065 /* Stop the thread servicing the interrupts */
1035 priv->surpriseremoved = 1; 1066 priv->surpriseremoved = 1;
1036 kthread_stop(priv->main_thread); 1067 kthread_stop(priv->main_thread);