From 98ee7783062335984f5979cea6a08e79982a4061 Mon Sep 17 00:00:00 2001 From: Arik Nemtsov Date: Wed, 2 Oct 2013 16:58:09 +0300 Subject: iwlwifi: add very first D0i3 support When the bus is in D0i3, we can't send regular commands to the firmware. This means that we need to add a state to remember what is our d0i3 state and make sure that only d0i3 exit commands can be sent. Add flags to CMD_ flags and transport status for this purpose. Commands with CMD_HIGH_PRIO set are queued at the head of the command queue, behind other high priority commands. Commands with CMD_SEND_IN_IDLE set can be sent while the transport is idle (without taking rpm reference). Commands with CMD_MAKE_TRANS_IDLE set indicate that command completion should mark the transport as idle (and release the bus). Commands with CMD_WAKE_UP_TRANS set instruct the transport to exit from idle when this command is completed. The transport is marked as idle (STATUS_TRANS_IDLE) when the FW enters D0i3 state. This bit is cleared when it enters D0 state again. Process only commands with CMD_SEND_IN_IDLE flag while the transport is idle. Other enqueued commands will be processed only later, right after exiting D0i3. Signed-off-by: Arik Nemtsov Signed-off-by: Eliad Peller Reviewed-by: Johannes Berg Signed-off-by: Emmanuel Grumbach --- drivers/net/wireless/iwlwifi/mvm/ops.c | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) (limited to 'drivers/net/wireless/iwlwifi/mvm/ops.c') diff --git a/drivers/net/wireless/iwlwifi/mvm/ops.c b/drivers/net/wireless/iwlwifi/mvm/ops.c index 0f87bc3..6e46b7c 100644 --- a/drivers/net/wireless/iwlwifi/mvm/ops.c +++ b/drivers/net/wireless/iwlwifi/mvm/ops.c @@ -291,6 +291,7 @@ static const char *iwl_mvm_cmd_strings[REPLY_MAX] = { CMD(REDUCE_TX_POWER_CMD), CMD(TX_ANT_CONFIGURATION_CMD), CMD(D3_CONFIG_CMD), + CMD(D0I3_END_CMD), CMD(PROT_OFFLOAD_CONFIG_CMD), CMD(OFFLOADS_QUERY_CMD), CMD(REMOTE_WAKE_CONFIG_CMD), @@ -815,17 +816,27 @@ static void iwl_mvm_cmd_queue_full(struct iwl_op_mode *op_mode) static int iwl_mvm_enter_d0i3(struct iwl_op_mode *op_mode) { struct iwl_mvm *mvm = IWL_OP_MODE_GET_MVM(op_mode); + u32 flags = CMD_ASYNC | CMD_HIGH_PRIO | CMD_SEND_IN_IDLE; + struct iwl_d3_manager_config d3_cfg_cmd = { + .min_sleep_time = cpu_to_le32(1000), + }; IWL_DEBUG_RPM(mvm, "MVM entering D0i3\n"); - return 0; + + return iwl_mvm_send_cmd_pdu(mvm, D3_CONFIG_CMD, + flags | CMD_MAKE_TRANS_IDLE, + sizeof(d3_cfg_cmd), &d3_cfg_cmd); } static int iwl_mvm_exit_d0i3(struct iwl_op_mode *op_mode) { struct iwl_mvm *mvm = IWL_OP_MODE_GET_MVM(op_mode); + u32 flags = CMD_ASYNC | CMD_HIGH_PRIO | CMD_SEND_IN_IDLE | + CMD_WAKE_UP_TRANS; IWL_DEBUG_RPM(mvm, "MVM exiting D0i3\n"); - return 0; + + return iwl_mvm_send_cmd_pdu(mvm, D0I3_END_CMD, flags, 0, NULL); } static const struct iwl_op_mode_ops iwl_mvm_ops = { -- cgit v1.1