| 
									
										
										
										
											2012-11-22 18:06:18 +02:00
										 |  |  | /*
 | 
					
						
							|  |  |  |  * This file is part of wl18xx | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * Copyright (C) 2011 Texas Instruments Inc. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * This program is free software; you can redistribute it and/or | 
					
						
							|  |  |  |  * modify it under the terms of the GNU General Public License | 
					
						
							|  |  |  |  * version 2 as published by the Free Software Foundation. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * This program is distributed in the hope that it will be useful, but | 
					
						
							|  |  |  |  * WITHOUT ANY WARRANTY; without even the implied warranty of | 
					
						
							|  |  |  |  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU | 
					
						
							|  |  |  |  * General Public License for more details. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * You should have received a copy of the GNU General Public License | 
					
						
							|  |  |  |  * along with this program; if not, write to the Free Software | 
					
						
							|  |  |  |  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA | 
					
						
							|  |  |  |  * 02110-1301 USA | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include "../wlcore/cmd.h"
 | 
					
						
							|  |  |  | #include "../wlcore/debug.h"
 | 
					
						
							|  |  |  | #include "../wlcore/hw_ops.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include "cmd.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | int wl18xx_cmd_channel_switch(struct wl1271 *wl, | 
					
						
							|  |  |  | 			      struct wl12xx_vif *wlvif, | 
					
						
							|  |  |  | 			      struct ieee80211_channel_switch *ch_switch) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	struct wl18xx_cmd_channel_switch *cmd; | 
					
						
							|  |  |  | 	u32 supported_rates; | 
					
						
							|  |  |  | 	int ret; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	wl1271_debug(DEBUG_ACX, "cmd channel switch"); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); | 
					
						
							|  |  |  | 	if (!cmd) { | 
					
						
							|  |  |  | 		ret = -ENOMEM; | 
					
						
							|  |  |  | 		goto out; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	cmd->role_id = wlvif->role_id; | 
					
						
							| 
									
										
										
										
											2013-03-25 18:29:27 +01:00
										 |  |  | 	cmd->channel = ch_switch->chandef.chan->hw_value; | 
					
						
							| 
									
										
										
										
											2012-11-22 18:06:18 +02:00
										 |  |  | 	cmd->switch_time = ch_switch->count; | 
					
						
							|  |  |  | 	cmd->stop_tx = ch_switch->block_tx; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-03-25 18:29:27 +01:00
										 |  |  | 	switch (ch_switch->chandef.chan->band) { | 
					
						
							| 
									
										
										
										
											2012-11-22 18:06:18 +02:00
										 |  |  | 	case IEEE80211_BAND_2GHZ: | 
					
						
							|  |  |  | 		cmd->band = WLCORE_BAND_2_4GHZ; | 
					
						
							|  |  |  | 		break; | 
					
						
							|  |  |  | 	case IEEE80211_BAND_5GHZ: | 
					
						
							|  |  |  | 		cmd->band = WLCORE_BAND_5GHZ; | 
					
						
							|  |  |  | 		break; | 
					
						
							|  |  |  | 	default: | 
					
						
							|  |  |  | 		wl1271_error("invalid channel switch band: %d", | 
					
						
							| 
									
										
										
										
											2013-03-25 18:29:27 +01:00
										 |  |  | 			     ch_switch->chandef.chan->band); | 
					
						
							| 
									
										
										
										
											2012-11-22 18:06:18 +02:00
										 |  |  | 		ret = -EINVAL; | 
					
						
							|  |  |  | 		goto out_free; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	supported_rates = CONF_TX_ENABLED_RATES | CONF_TX_MCS_RATES | | 
					
						
							|  |  |  | 			  wlcore_hw_sta_get_ap_rate_mask(wl, wlvif); | 
					
						
							|  |  |  | 	if (wlvif->p2p) | 
					
						
							|  |  |  | 		supported_rates &= ~CONF_TX_CCK_RATES; | 
					
						
							|  |  |  | 	cmd->local_supported_rates = cpu_to_le32(supported_rates); | 
					
						
							|  |  |  | 	cmd->channel_type = wlvif->channel_type; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	ret = wl1271_cmd_send(wl, CMD_CHANNEL_SWITCH, cmd, sizeof(*cmd), 0); | 
					
						
							|  |  |  | 	if (ret < 0) { | 
					
						
							|  |  |  | 		wl1271_error("failed to send channel switch command"); | 
					
						
							|  |  |  | 		goto out_free; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | out_free: | 
					
						
							|  |  |  | 	kfree(cmd); | 
					
						
							|  |  |  | out: | 
					
						
							|  |  |  | 	return ret; | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2014-07-11 03:01:31 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | int wl18xx_cmd_smart_config_start(struct wl1271 *wl, u32 group_bitmap) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	struct wl18xx_cmd_smart_config_start *cmd; | 
					
						
							|  |  |  | 	int ret = 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	wl1271_debug(DEBUG_CMD, "cmd smart config start group_bitmap=0x%x", | 
					
						
							|  |  |  | 		     group_bitmap); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); | 
					
						
							|  |  |  | 	if (!cmd) { | 
					
						
							|  |  |  | 		ret = -ENOMEM; | 
					
						
							|  |  |  | 		goto out; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	cmd->group_id_bitmask = cpu_to_le32(group_bitmap); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	ret = wl1271_cmd_send(wl, CMD_SMART_CONFIG_START, cmd, sizeof(*cmd), 0); | 
					
						
							|  |  |  | 	if (ret < 0) { | 
					
						
							|  |  |  | 		wl1271_error("failed to send smart config start command"); | 
					
						
							|  |  |  | 		goto out_free; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | out_free: | 
					
						
							|  |  |  | 	kfree(cmd); | 
					
						
							|  |  |  | out: | 
					
						
							|  |  |  | 	return ret; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | int wl18xx_cmd_smart_config_stop(struct wl1271 *wl) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	struct wl1271_cmd_header *cmd; | 
					
						
							|  |  |  | 	int ret = 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	wl1271_debug(DEBUG_CMD, "cmd smart config stop"); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); | 
					
						
							|  |  |  | 	if (!cmd) { | 
					
						
							|  |  |  | 		ret = -ENOMEM; | 
					
						
							|  |  |  | 		goto out; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	ret = wl1271_cmd_send(wl, CMD_SMART_CONFIG_STOP, cmd, sizeof(*cmd), 0); | 
					
						
							|  |  |  | 	if (ret < 0) { | 
					
						
							|  |  |  | 		wl1271_error("failed to send smart config stop command"); | 
					
						
							|  |  |  | 		goto out_free; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | out_free: | 
					
						
							|  |  |  | 	kfree(cmd); | 
					
						
							|  |  |  | out: | 
					
						
							|  |  |  | 	return ret; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | int wl18xx_cmd_smart_config_set_group_key(struct wl1271 *wl, u16 group_id, | 
					
						
							|  |  |  | 					  u8 key_len, u8 *key) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	struct wl18xx_cmd_smart_config_set_group_key *cmd; | 
					
						
							|  |  |  | 	int ret = 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	wl1271_debug(DEBUG_CMD, "cmd smart config set group key id=0x%x", | 
					
						
							|  |  |  | 		     group_id); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (key_len != sizeof(cmd->key)) { | 
					
						
							|  |  |  | 		wl1271_error("invalid group key size: %d", key_len); | 
					
						
							|  |  |  | 		return -E2BIG; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); | 
					
						
							|  |  |  | 	if (!cmd) { | 
					
						
							|  |  |  | 		ret = -ENOMEM; | 
					
						
							|  |  |  | 		goto out; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	cmd->group_id = cpu_to_le32(group_id); | 
					
						
							|  |  |  | 	memcpy(cmd->key, key, key_len); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	ret = wl1271_cmd_send(wl, CMD_SMART_CONFIG_SET_GROUP_KEY, cmd, | 
					
						
							|  |  |  | 			      sizeof(*cmd), 0); | 
					
						
							|  |  |  | 	if (ret < 0) { | 
					
						
							|  |  |  | 		wl1271_error("failed to send smart config set group key cmd"); | 
					
						
							|  |  |  | 		goto out_free; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | out_free: | 
					
						
							|  |  |  | 	kfree(cmd); | 
					
						
							|  |  |  | out: | 
					
						
							|  |  |  | 	return ret; | 
					
						
							|  |  |  | } |