diff options
Diffstat (limited to 'drivers/net/wireless/iwlwifi/mvm/time-event.c')
| -rw-r--r-- | drivers/net/wireless/iwlwifi/mvm/time-event.c | 99 | 
1 files changed, 26 insertions, 73 deletions
diff --git a/drivers/net/wireless/iwlwifi/mvm/time-event.c b/drivers/net/wireless/iwlwifi/mvm/time-event.c index 76a3c177e10..80100f6cc12 100644 --- a/drivers/net/wireless/iwlwifi/mvm/time-event.c +++ b/drivers/net/wireless/iwlwifi/mvm/time-event.c @@ -5,7 +5,7 @@   *   * GPL LICENSE SUMMARY   * - * Copyright(c) 2012 - 2013 Intel Corporation. All rights reserved. + * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.   *   * This program is free software; you can redistribute it and/or modify   * it under the terms of version 2 of the GNU General Public License as @@ -30,7 +30,7 @@   *   * BSD LICENSE   * - * Copyright(c) 2012 - 2013 Intel Corporation. All rights reserved. + * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.   * All rights reserved.   *   * Redistribution and use in source and binary forms, with or without @@ -126,6 +126,7 @@ static void iwl_mvm_roc_finished(struct iwl_mvm *mvm)  	 * in iwl_mvm_te_handle_notif).  	 */  	clear_bit(IWL_MVM_STATUS_ROC_RUNNING, &mvm->status); +	iwl_mvm_unref(mvm, IWL_MVM_REF_ROC);  	/*  	 * Of course, our status bit is just as racy as mac80211, so in @@ -176,8 +177,11 @@ static void iwl_mvm_te_handle_notif(struct iwl_mvm *mvm,  	 * P2P Device discoveribility, while there are other higher priority  	 * events in the system).  	 */ -	if (WARN_ONCE(!le32_to_cpu(notif->status), -		      "Failed to schedule time event\n")) { +	if (!le32_to_cpu(notif->status)) { +		bool start = le32_to_cpu(notif->action) & +				TE_V2_NOTIF_HOST_EVENT_START; +		IWL_WARN(mvm, "Time Event %s notification failure\n", +			 start ? "start" : "end");  		if (iwl_mvm_te_check_disconnect(mvm, te_data->vif, NULL)) {  			iwl_mvm_te_clear_data(mvm, te_data);  			return; @@ -207,6 +211,7 @@ static void iwl_mvm_te_handle_notif(struct iwl_mvm *mvm,  		if (te_data->vif->type == NL80211_IFTYPE_P2P_DEVICE) {  			set_bit(IWL_MVM_STATUS_ROC_RUNNING, &mvm->status); +			iwl_mvm_ref(mvm, IWL_MVM_REF_ROC);  			ieee80211_ready_on_channel(mvm->hw);  		}  	} else { @@ -246,12 +251,12 @@ static bool iwl_mvm_time_event_response(struct iwl_notif_wait_data *notif_wait,  		container_of(notif_wait, struct iwl_mvm, notif_wait);  	struct iwl_mvm_time_event_data *te_data = data;  	struct iwl_time_event_resp *resp; -	int resp_len = le32_to_cpu(pkt->len_n_flags) & FH_RSCSR_FRAME_SIZE_MSK; +	int resp_len = iwl_rx_packet_payload_len(pkt);  	if (WARN_ON(pkt->hdr.cmd != TIME_EVENT_CMD))  		return true; -	if (WARN_ON_ONCE(resp_len != sizeof(pkt->hdr) + sizeof(*resp))) { +	if (WARN_ON_ONCE(resp_len != sizeof(*resp))) {  		IWL_ERR(mvm, "Invalid TIME_EVENT_CMD response\n");  		return true;  	} @@ -268,67 +273,10 @@ static bool iwl_mvm_time_event_response(struct iwl_notif_wait_data *notif_wait,  	return true;  } -/* used to convert from time event API v2 to v1 */ -#define TE_V2_DEP_POLICY_MSK (TE_V2_DEP_OTHER | TE_V2_DEP_TSF |\ -			     TE_V2_EVENT_SOCIOPATHIC) -static inline u16 te_v2_get_notify(__le16 policy) -{ -	return le16_to_cpu(policy) & TE_V2_NOTIF_MSK; -} - -static inline u16 te_v2_get_dep_policy(__le16 policy) -{ -	return (le16_to_cpu(policy) & TE_V2_DEP_POLICY_MSK) >> -		TE_V2_PLACEMENT_POS; -} - -static inline u16 te_v2_get_absence(__le16 policy) -{ -	return (le16_to_cpu(policy) & TE_V2_ABSENCE) >> TE_V2_ABSENCE_POS; -} - -static void iwl_mvm_te_v2_to_v1(const struct iwl_time_event_cmd_v2 *cmd_v2, -				struct iwl_time_event_cmd_v1 *cmd_v1) -{ -	cmd_v1->id_and_color = cmd_v2->id_and_color; -	cmd_v1->action = cmd_v2->action; -	cmd_v1->id = cmd_v2->id; -	cmd_v1->apply_time = cmd_v2->apply_time; -	cmd_v1->max_delay = cmd_v2->max_delay; -	cmd_v1->depends_on = cmd_v2->depends_on; -	cmd_v1->interval = cmd_v2->interval; -	cmd_v1->duration = cmd_v2->duration; -	if (cmd_v2->repeat == TE_V2_REPEAT_ENDLESS) -		cmd_v1->repeat = cpu_to_le32(TE_V1_REPEAT_ENDLESS); -	else -		cmd_v1->repeat = cpu_to_le32(cmd_v2->repeat); -	cmd_v1->max_frags = cpu_to_le32(cmd_v2->max_frags); -	cmd_v1->interval_reciprocal = 0; /* unused */ - -	cmd_v1->dep_policy = cpu_to_le32(te_v2_get_dep_policy(cmd_v2->policy)); -	cmd_v1->is_present = cpu_to_le32(!te_v2_get_absence(cmd_v2->policy)); -	cmd_v1->notify = cpu_to_le32(te_v2_get_notify(cmd_v2->policy)); -} - -static int iwl_mvm_send_time_event_cmd(struct iwl_mvm *mvm, -				       const struct iwl_time_event_cmd_v2 *cmd) -{ -	struct iwl_time_event_cmd_v1 cmd_v1; - -	if (mvm->fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_TIME_EVENT_API_V2) -		return iwl_mvm_send_cmd_pdu(mvm, TIME_EVENT_CMD, CMD_SYNC, -					    sizeof(*cmd), cmd); - -	iwl_mvm_te_v2_to_v1(cmd, &cmd_v1); -	return iwl_mvm_send_cmd_pdu(mvm, TIME_EVENT_CMD, CMD_SYNC, -				    sizeof(cmd_v1), &cmd_v1); -} - -  static int iwl_mvm_time_event_send_add(struct iwl_mvm *mvm,  				       struct ieee80211_vif *vif,  				       struct iwl_mvm_time_event_data *te_data, -				       struct iwl_time_event_cmd_v2 *te_cmd) +				       struct iwl_time_event_cmd *te_cmd)  {  	static const u8 time_event_response[] = { TIME_EVENT_CMD };  	struct iwl_notification_wait wait_time_event; @@ -364,7 +312,8 @@ static int iwl_mvm_time_event_send_add(struct iwl_mvm *mvm,  				   ARRAY_SIZE(time_event_response),  				   iwl_mvm_time_event_response, te_data); -	ret = iwl_mvm_send_time_event_cmd(mvm, te_cmd); +	ret = iwl_mvm_send_cmd_pdu(mvm, TIME_EVENT_CMD, 0, +					    sizeof(*te_cmd), te_cmd);  	if (ret) {  		IWL_ERR(mvm, "Couldn't send TIME_EVENT_CMD: %d\n", ret);  		iwl_remove_notification(&mvm->notif_wait, &wait_time_event); @@ -387,11 +336,12 @@ static int iwl_mvm_time_event_send_add(struct iwl_mvm *mvm,  void iwl_mvm_protect_session(struct iwl_mvm *mvm,  			     struct ieee80211_vif *vif, -			     u32 duration, u32 min_duration) +			     u32 duration, u32 min_duration, +			     u32 max_delay)  {  	struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);  	struct iwl_mvm_time_event_data *te_data = &mvmvif->time_event_data; -	struct iwl_time_event_cmd_v2 time_cmd = {}; +	struct iwl_time_event_cmd time_cmd = {};  	lockdep_assert_held(&mvm->mutex); @@ -426,13 +376,14 @@ void iwl_mvm_protect_session(struct iwl_mvm *mvm,  		cpu_to_le32(iwl_read_prph(mvm->trans, DEVICE_SYSTEM_TIME_REG));  	time_cmd.max_frags = TE_V2_FRAG_NONE; -	time_cmd.max_delay = cpu_to_le32(500); +	time_cmd.max_delay = cpu_to_le32(max_delay);  	/* TODO: why do we need to interval = bi if it is not periodic? */  	time_cmd.interval = cpu_to_le32(1);  	time_cmd.duration = cpu_to_le32(duration);  	time_cmd.repeat = 1;  	time_cmd.policy = cpu_to_le16(TE_V2_NOTIF_HOST_EVENT_START | -				      TE_V2_NOTIF_HOST_EVENT_END); +				      TE_V2_NOTIF_HOST_EVENT_END | +				      T2_V2_START_IMMEDIATELY);  	iwl_mvm_time_event_send_add(mvm, vif, te_data, &time_cmd);  } @@ -446,7 +397,7 @@ void iwl_mvm_remove_time_event(struct iwl_mvm *mvm,  			       struct iwl_mvm_vif *mvmvif,  			       struct iwl_mvm_time_event_data *te_data)  { -	struct iwl_time_event_cmd_v2 time_cmd = {}; +	struct iwl_time_event_cmd time_cmd = {};  	u32 id, uid;  	int ret; @@ -483,7 +434,8 @@ void iwl_mvm_remove_time_event(struct iwl_mvm *mvm,  		cpu_to_le32(FW_CMD_ID_AND_COLOR(mvmvif->id, mvmvif->color));  	IWL_DEBUG_TE(mvm, "Removing TE 0x%x\n", le32_to_cpu(time_cmd.id)); -	ret = iwl_mvm_send_time_event_cmd(mvm, &time_cmd); +	ret = iwl_mvm_send_cmd_pdu(mvm, TIME_EVENT_CMD, 0, +				   sizeof(time_cmd), &time_cmd);  	if (WARN_ON(ret))  		return;  } @@ -503,7 +455,7 @@ int iwl_mvm_start_p2p_roc(struct iwl_mvm *mvm, struct ieee80211_vif *vif,  {  	struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);  	struct iwl_mvm_time_event_data *te_data = &mvmvif->time_event_data; -	struct iwl_time_event_cmd_v2 time_cmd = {}; +	struct iwl_time_event_cmd time_cmd = {};  	lockdep_assert_held(&mvm->mutex);  	if (te_data->running) { @@ -547,7 +499,8 @@ int iwl_mvm_start_p2p_roc(struct iwl_mvm *mvm, struct ieee80211_vif *vif,  	time_cmd.duration = cpu_to_le32(MSEC_TO_TU(duration));  	time_cmd.repeat = 1;  	time_cmd.policy = cpu_to_le16(TE_V2_NOTIF_HOST_EVENT_START | -				      TE_V2_NOTIF_HOST_EVENT_END); +				      TE_V2_NOTIF_HOST_EVENT_END | +				      T2_V2_START_IMMEDIATELY);  	return iwl_mvm_time_event_send_add(mvm, vif, te_data, &time_cmd);  }  | 
