static ssize_t ath6kl_bmisstime_write(struct file *file,
				      const char __user *user_buf,
				      size_t count, loff_t *ppos)
{
	struct ath6kl *ar = file->private_data;
	struct ath6kl_vif *vif;
	u16 bmiss_time;
	char buf[32];
	ssize_t len;

	vif = ath6kl_vif_first(ar);
	if (!vif)
		return -EIO;

	len = min(count, sizeof(buf) - 1);
	if (copy_from_user(buf, user_buf, len))
		return -EFAULT;

	buf[len] = '\0';
	if (kstrtou16(buf, 0, &bmiss_time))
		return -EINVAL;

	vif->bmiss_time_t = bmiss_time;

	/* Enable error report event for bmiss */
	ath6kl_wmi_set_err_report_bitmask(ar->wmi, vif->fw_vif_idx,
					  ATH6KL_ERR_REPORT_BMISS_MASK);

	ath6kl_wmi_bmisstime_cmd(ar->wmi, vif->fw_vif_idx,
				 vif->bmiss_time_t, 0);
	return count;
}
static bool ath6kl_parse_data_pkt_for_wake_lock(struct ath6kl *ar,
						struct sk_buff *skb)
{
	struct net_device *ndev;
	struct ath6kl_vif *vif;
	struct ethhdr *hdr;
	bool need_wake = false;
	u16 dst_port;

	vif = ath6kl_vif_first(ar);
	if (!vif)
		return need_wake;

	if (skb->len < sizeof(struct ethhdr))
		return need_wake;

	hdr = (struct ethhdr *) skb->data;

	if (!is_multicast_ether_addr(hdr->h_dest)) {
		switch (ntohs(hdr->h_proto)) {
		case 0x0800: /* IP */
			need_wake = ath6kl_parse_ip_pkt_for_wake_lock(skb);
			break;
		case 0x888e: /* EAPOL */
		case 0x88c7: /* RSN_PREAUTH */
		case 0x88b4: /* WAPI */
			need_wake = true;
			break;
		default:
			break;
		}
	} else if (!is_broadcast_ether_addr(hdr->h_dest)) {
		if (skb->len >= 14 + 20) { /* mDNS packets */
			u8 *dst_ipaddr = (u8 *)(skb->data + 14 + 20 - 4);
			ndev = vif->ndev;
			if (((dst_ipaddr[3] & 0xf8) == 0xf8) &&
				(vif->nw_type == AP_NETWORK ||
				(ndev->flags & IFF_ALLMULTI ||
				ndev->flags & IFF_MULTICAST)))
					need_wake = true;
		}
	} else if (vif->nw_type == AP_NETWORK) {
		switch (ntohs(hdr->h_proto)) {
		case 0x0800: /* IP */
			if (skb->len >= 14 + 20 + 2) {
				dst_port = *(u16 *)(skb->data + 14 + 20);
				/* dhcp req */
				need_wake = (ntohs(dst_port) == 0x43);
			}
			break;
		case 0x0806:
			need_wake = true;
		default:
			break;
		}
	}

	return need_wake;
}
Beispiel #3
0
void ath6kl_config_suspend_wake_lock(struct ath6kl *ar, struct sk_buff *skb,
				     bool is_event_pkt)
{
	struct ath6kl_vif *vif;
#ifdef CONFIG_HAS_WAKELOCK
#if 1 /* 20120927 Matt */
	unsigned long wl_timeout = HZ;
#else
	unsigned long wl_timeout = 5;
#endif /* 20120927 Matt */
#endif
	bool need_wake = false;

	vif = ath6kl_vif_first(ar);
	if (!vif)
		return;

	if (
#ifdef CONFIG_HAS_EARLYSUSPEND
			ar->screen_off &&
#endif
			skb && test_bit(CONNECTED, &vif->flags)) {
		if (is_event_pkt) { /* Ctrl pkt received */
			need_wake =
#if 1	// by bbelief
				ath6kl_parse_event_pkt_for_wake_lock(skb);
#else
			ath6kl_parse_event_pkt_for_wake_lock(ar, skb);
#endif
			if (need_wake) {
#ifdef CONFIG_HAS_WAKELOCK
				wl_timeout = 3 * HZ;
#endif
			}
		} else /* Data pkt received */
			need_wake = ath6kl_parse_data_pkt_for_wake_lock(ar,
									skb);
	}

	if (need_wake) {
#ifdef CONFIG_HAS_WAKELOCK
		/*
		 * Keep the host wake up if there is any event
		 * and pkt comming in.
		 */
		wake_lock_timeout(&ar->wake_lock, wl_timeout);
#endif
	}
}
static ssize_t ath6kl_bmisstime_read(struct file *file,
				     char __user *user_buf,
				     size_t count, loff_t *ppos)
{
	struct ath6kl *ar = file->private_data;
	struct ath6kl_vif *vif;
	char buf[32];
	int len;

	vif = ath6kl_vif_first(ar);
	if (!vif)
		return -EIO;

	len = scnprintf(buf, sizeof(buf), "%u\n", vif->bmiss_time_t);

	return simple_read_from_buffer(user_buf, count, ppos, buf, len);
}
Beispiel #5
0
static bool ath6kl_parse_data_pkt_for_wake_lock(struct ath6kl *ar,
						struct sk_buff *skb)
{
	struct net_device *ndev;
	struct ath6kl_vif *vif;
	struct ethhdr *hdr;
	bool need_wake = false;
	u16 dst_port;

	vif = ath6kl_vif_first(ar);
	if (!vif)
		return need_wake;

	if (skb->len < sizeof(struct ethhdr))
		return need_wake;

	hdr = (struct ethhdr *) skb->data;

#if 0 // by bbelief
	if (test_and_clear_bit(WOW_RESUME_PRINT, &ar->flag)) {
		ath6kl_dbg(ATH6KL_DBG_SUSPEND,
			   "(wow) dest mac:%pM, src mac:%pM, type/len :%04x\n",
			   hdr->h_dest, hdr->h_source,
			   be16_to_cpu(hdr->h_proto));
	}
#endif

	if (!is_multicast_ether_addr(hdr->h_dest)) {
		switch (ntohs(hdr->h_proto)) {
		case 0x0800: /* IP */
			need_wake = ath6kl_parse_ip_pkt_for_wake_lock(skb);
			break;
		case 0x888e: /* EAPOL */
		case 0x88c7: /* RSN_PREAUTH */
		case 0x88b4: /* WAPI */
			need_wake = true;
			break;
		default:
			break;
		}
	} else if (!is_broadcast_ether_addr(hdr->h_dest)) {
		if (skb->len >= 14 + 20) { /* mDNS packets */
			u8 *dst_ipaddr = (u8 *)(skb->data + 14 + 20 - 4);
			ndev = vif->ndev;
			if (((dst_ipaddr[3] & 0xf8) == 0xf8) &&
				(vif->nw_type == AP_NETWORK ||
				(ndev->flags & IFF_ALLMULTI ||
				ndev->flags & IFF_MULTICAST)))
					need_wake = true;
		}
	} else if (vif->nw_type == AP_NETWORK) {
		switch (ntohs(hdr->h_proto)) {
		case 0x0800: /* IP */
			if (skb->len >= 14 + 20 + 2) {
				dst_port = *(u16 *)(skb->data + 14 + 20);
				/* dhcp req */
				need_wake = (ntohs(dst_port) == 0x43);
			}
			break;
		case 0x0806:
			need_wake = true;
		default:
			break;
		}
	}

	return need_wake;
}
int ath6kl_tm_cmd(struct wiphy *wiphy, void *data, int len)
{
	struct ath6kl *ar = wiphy_priv(wiphy);
	struct nlattr *tb[ATH6KL_TM_ATTR_MAX + 1];
	int err, buf_len;
	void *buf;

	err = nla_parse(tb, ATH6KL_TM_ATTR_MAX, data, len,
			ath6kl_tm_policy);

	if (err)
		return err;

	if (!tb[ATH6KL_TM_ATTR_CMD])
		return -EINVAL;

	switch (nla_get_u32(tb[ATH6KL_TM_ATTR_CMD])) {
	case ATH6KL_TM_CMD_TCMD:
		if (!tb[ATH6KL_TM_ATTR_DATA])
			return -EINVAL;

		buf = nla_data(tb[ATH6KL_TM_ATTR_DATA]);
		buf_len = nla_len(tb[ATH6KL_TM_ATTR_DATA]);

		ath6kl_wmi_test_cmd(ar->wmi, buf, buf_len);

		return 0;

		break;
#ifdef ATH6KL_SUPPORT_WLAN_HB
	case ATH6KL_TM_CMD_WLAN_HB:
	{
		struct wlan_hb_params *hb_params;
		struct ath6kl_vif *vif;

		vif = ath6kl_vif_first(ar);

		if (!vif)
			return -EINVAL;

		if (!tb[ATH6KL_TM_ATTR_DATA]) {
			printk(KERN_ERR "%s: NO DATA\n", __func__);
			return -EINVAL;
		}

		buf = nla_data(tb[ATH6KL_TM_ATTR_DATA]);
		buf_len = nla_len(tb[ATH6KL_TM_ATTR_DATA]);

		hb_params = (struct wlan_hb_params *)buf;

		if (hb_params->cmd == NL80211_WLAN_HB_ENABLE) {
			if (hb_params->enable != 0) {

				if (ath6kl_enable_wow_hb(ar)) {
					printk(KERN_ERR
					"%s: enable hb wow fail\n",
					__func__);
					return -EINVAL;
				}

				if (hb_params->enable & WLAN_HB_TCP_ENABLE) {
					ar->wlan_hb_enable |=
						WLAN_HB_TCP_ENABLE;

					if (ath6kl_wmi_set_heart_beat_params(
						ar->wmi,
						vif->fw_vif_idx,
						WLAN_HB_TCP_ENABLE)) {
						printk(KERN_ERR
						"%s: set heart beat enable fail\n",
						__func__);
						return -EINVAL;
					}
				} else
				if (hb_params->enable & WLAN_HB_UDP_ENABLE) {
					ar->wlan_hb_enable |=
						WLAN_HB_UDP_ENABLE;
				}
			} else {
				ar->wlan_hb_enable = 0;

#ifdef CONFIG_ANDROID
				if (ath6kl_android_enable_wow_default(ar)) {
					printk(KERN_ERR
					"%s: enable android defualt wow fail\n",
					__func__);
				}
#endif

				if (ath6kl_wmi_set_heart_beat_params(ar->wmi,
					vif->fw_vif_idx, 0)) {
					printk(KERN_ERR
					"%s: set heart beat enable fail\n",
					__func__);
					return -EINVAL;
				}
			}

		} else if (hb_params->cmd == NL80211_WLAN_TCP_PARAMS) {
			if (ath6kl_wmi_heart_beat_set_tcp_params(ar->wmi,
				vif->fw_vif_idx,
				hb_params->params.tcp_params.src_port,
				hb_params->params.tcp_params.dst_port,
				hb_params->params.tcp_params.timeout)) {
				printk(KERN_ERR
				"%s: set heart beat tcp params fail\n",
				__func__);
				return -EINVAL;
			}

		} else if (hb_params->cmd == NL80211_WLAN_TCP_FILTER) {
			if (hb_params->params.tcp_filter.length
				> WMI_MAX_TCP_FILTER_SIZE) {
				printk(KERN_ERR "%s: size of tcp filter is too large: %d\n",
					__func__,
					hb_params->params.tcp_filter.length);
				return -E2BIG;
			}

			if (ath6kl_wmi_heart_beat_set_tcp_filter(ar->wmi,
				vif->fw_vif_idx,
				hb_params->params.tcp_filter.filter,
				hb_params->params.tcp_filter.length)) {
				printk(KERN_ERR
				"%s: set heart beat tcp filter fail\n",
				__func__);
				return -EINVAL;
			}
		} else if (hb_params->cmd == NL80211_WLAN_UDP_PARAMS) {
			if (ath6kl_wmi_heart_beat_set_udp_params(ar->wmi,
				vif->fw_vif_idx,
				hb_params->params.udp_params.src_port,
				hb_params->params.udp_params.dst_port,
				hb_params->params.udp_params.interval,
				hb_params->params.udp_params.timeout)) {
				printk(KERN_ERR
				"%s: set heart beat udp params fail\n",
				__func__);
				return -EINVAL;
			}
		} else if (hb_params->cmd == NL80211_WLAN_UDP_FILTER) {
			if (hb_params->params.udp_filter.length
					> WMI_MAX_UDP_FILTER_SIZE) {
				printk(KERN_ERR
				"%s: size of udp filter is too large: %d\n",
				__func__,
				hb_params->params.udp_filter.length);
				return -E2BIG;
			}

			if (ath6kl_wmi_heart_beat_set_udp_filter(ar->wmi,
					vif->fw_vif_idx,
					hb_params->params.udp_filter.filter,
					hb_params->params.udp_filter.length)) {
				printk(KERN_ERR
				"%s: set heart beat udp filter fail\n",
				__func__);
				return -EINVAL;
			}
		} else if (hb_params->cmd == NL80211_WLAN_NET_INFO) {
			if (ath6kl_wmi_heart_beat_set_network_info(ar->wmi,
				vif->fw_vif_idx,
				hb_params->params.net_info.device_ip,
				hb_params->params.net_info.server_ip,
				hb_params->params.net_info.gateway_ip,
				hb_params->params.net_info.gateway_mac)) {
				printk(KERN_ERR
				"%s: set heart beat network information fail\n",
				__func__);
				return -EINVAL;
			}
		}
	}

	return 0;
	break;
#endif
#ifdef ATH6KL_SUPPORT_WIFI_DISC
	case ATH6KL_TM_CMD_WIFI_DISC:
	{
		struct wifi_disc_params *disc_params;
		struct ath6kl_vif *vif;

		vif = ath6kl_vif_first(ar);

		if (!vif)
			return -EINVAL;

		if (!tb[ATH6KL_TM_ATTR_DATA]) {
			printk(KERN_ERR "%s: NO DATA\n", __func__);
			return -EINVAL;
		}

		buf = nla_data(tb[ATH6KL_TM_ATTR_DATA]);
		buf_len = nla_len(tb[ATH6KL_TM_ATTR_DATA]);

		disc_params = (struct wifi_disc_params *)buf;

		if (disc_params->cmd == NL80211_WIFI_DISC_IE) {
			u8 ie_hdr[6] = {0xDD, 0x00, 0x00, 0x03, 0x7f, 0x00};
			u8 *ie = NULL;
			u16 ie_length = disc_params->params.ie_params.length;

			ie = kmalloc(ie_length+6, GFP_KERNEL);
			if (ie == NULL)
				return -ENOMEM;

			memcpy(ie, ie_hdr, 6);
			ie[1] = ie_length+4;
			memcpy(ie+6,
				disc_params->params.ie_params.ie,
				ie_length);

			if (ath6kl_wmi_set_appie_cmd(ar->wmi, vif->fw_vif_idx,
				WMI_FRAME_PROBE_REQ, ie, ie_length+6)) {
				kfree(ie);
				printk(KERN_ERR
				"%s: wifi discovery set probe request ie fail\n",
				__func__);
				return -EINVAL;
			}

			if (ath6kl_wmi_set_appie_cmd(ar->wmi, vif->fw_vif_idx,
				WMI_FRAME_PROBE_RESP, ie, ie_length+6)) {
				kfree(ie);
				printk(KERN_ERR
				"%s: wifi discovery set probe response ie fail\n",
				__func__);
				return -EINVAL;
			}

			kfree(ie);
		} else if (disc_params->cmd == NL80211_WIFI_DISC_IE_FILTER) {
			if (ath6kl_wmi_disc_ie_cmd(ar->wmi, vif->fw_vif_idx,
				disc_params->params.ie_filter_params.enable,
				disc_params->params.ie_filter_params.startPos,
				disc_params->params.ie_filter_params.filter,
				disc_params->params.ie_filter_params.length)) {
				printk(KERN_ERR
				"%s: wifi discovery set ie filter fail\n",
				__func__);
				return -EINVAL;
			}
		} else if (disc_params->cmd == NL80211_WIFI_DISC_START) {
			int band, freq, numPeers, random;

			if (disc_params->params.start_params.channel <= 14)
				band = IEEE80211_BAND_2GHZ;
			else
				band = IEEE80211_BAND_5GHZ;

			freq = ieee80211_channel_to_frequency(
				disc_params->params.start_params.channel, band);
			if (!freq) {
				printk(KERN_ERR "%s: wifi discovery start channel %d error\n",
				__func__,
				disc_params->params.start_params.channel);
				return -EINVAL;
			}

			if (disc_params->params.start_params.numPeers == 0)
				numPeers = 1;
			else if (disc_params->params.start_params.numPeers > 4)
				numPeers = 4;
			else
				numPeers =
				disc_params->params.start_params.numPeers;

			random = (disc_params->params.start_params.random == 0)
				? 100 : disc_params->params.start_params.random;

			if (disc_params->params.start_params.txPower)
				ath6kl_wmi_set_tx_pwr_cmd(ar->wmi,
				vif->fw_vif_idx,
				disc_params->params.start_params.txPower);

			/* disable scanning */
			ath6kl_wmi_scanparams_cmd(ar->wmi, vif->fw_vif_idx,
						0xFFFF, 0, 0,
						0, 0, 0, 0, 0, 0, 0);

			if (ath6kl_wmi_disc_mode_cmd(ar->wmi,
				vif->fw_vif_idx, 1, freq,
				disc_params->params.start_params.dwellTime,
				disc_params->params.start_params.sleepTime,
				random, numPeers,
				disc_params->params.start_params.peerTimeout
				)) {
				printk(KERN_ERR "%s: wifi discovery start fail\n",
						__func__);
				return -EINVAL;
			}

			/* change disc state to active */
			ar->disc_active = true;
		} else if (disc_params->cmd == NL80211_WIFI_DISC_STOP) {
			/* change disc state to inactive */
			ar->disc_active = false;
			if (ath6kl_wmi_disc_mode_cmd(ar->wmi, vif->fw_vif_idx,
							0, 0, 0, 0, 0, 0, 0)) {
				printk(KERN_ERR "%s: wifi discovery stop fail\n",
						__func__);
				return -EINVAL;
			}
		}
	}

	return 0;
	break;
#endif

#ifdef ATH6KL_SUPPORT_WIFI_KTK
	case ATH6KL_TM_CMD_WIFI_KTK:
	{
		struct wifi_ktk_params *ktk_params;
		struct ath6kl_vif *vif;

		vif = ath6kl_vif_first(ar);
		if (!vif)
			return -EINVAL;

		if (!tb[ATH6KL_TM_ATTR_DATA]) {
			printk(KERN_ERR "%s: NO DATA\n", __func__);
			return -EINVAL;
		}

		buf = nla_data(tb[ATH6KL_TM_ATTR_DATA]);
		buf_len = nla_len(tb[ATH6KL_TM_ATTR_DATA]);

		ktk_params = (struct wifi_ktk_params *)buf;

		if (ktk_params->cmd == NL80211_WIFI_KTK_IE) {
			u8 ie_hdr[6] = {0xDD, 0x00, 0x00, 0x03, 0x7f, 0x00};
			u8 *ie = NULL;
			u16 ie_length = ktk_params->params.ie_params.length;

			ie = kmalloc(ie_length+6, GFP_KERNEL);
			if (ie == NULL)
				return -ENOMEM;

			memcpy(ie, ie_hdr, 6);
			ie[1] = ie_length+4;
			memcpy(ie+6, ktk_params->params.ie_params.ie,
				ie_length);

			if (ath6kl_wmi_set_appie_cmd(ar->wmi, vif->fw_vif_idx,
							WMI_FRAME_PROBE_RESP,
							ie,
							ie_length+6)) {
				kfree(ie);
				printk(KERN_ERR
					"%s: wifi ktk set probe	response ie fail\n",
					__func__);
				return -EINVAL;
			}

			if (ath6kl_wmi_set_appie_cmd(ar->wmi, vif->fw_vif_idx,
					WMI_FRAME_BEACON, ie, ie_length+6)) {
				kfree(ie);
				printk(KERN_ERR
					"%s: wifi ktk set beacon ie fail\n",
					__func__);
				return -EINVAL;
			}

			kfree(ie);
		} else if (ktk_params->cmd == NL80211_WIFI_KTK_IE_FILTER) {
			if (ath6kl_wmi_disc_ie_cmd(ar->wmi, vif->fw_vif_idx,
				ktk_params->params.ie_filter_params.enable,
				ktk_params->params.ie_filter_params.startPos,
				ktk_params->params.ie_filter_params.filter,
				ktk_params->params.ie_filter_params.length)) {
				printk(KERN_ERR
					"%s: wifi ktk set ie filter fail\n",
					__func__);
				return -EINVAL;
			}
		} else if (ktk_params->cmd == NL80211_WIFI_KTK_START) {
			ar->ktk_active = true;

			/* Clear the legacy ie pattern and filter */
			if (ath6kl_wmi_disc_ie_cmd(ar->wmi, vif->fw_vif_idx,
					0,
					0,
					NULL,
					0)) {
				printk(KERN_ERR "%s: wifi ktk clear ie filter fail\n",
					__func__);
				return -EINVAL;
			}

			memcpy(ar->ktk_passphrase,
				ktk_params->params.start_params.passphrase,
				16);

			if (ath6kl_wmi_probedssid_cmd(ar->wmi, vif->fw_vif_idx,
				1, SPECIFIC_SSID_FLAG,
				ktk_params->params.start_params.ssid_len,
				ktk_params->params.start_params.ssid)) {
				printk(KERN_ERR "%s: wifi ktk set probedssid fail\n",
					__func__);
				return -EINVAL;
			}

			if (ath6kl_wmi_ibss_pm_caps_cmd(ar->wmi,
					vif->fw_vif_idx,
					ADHOC_PS_KTK,
					5,
					10,
					10)) {
				printk(KERN_ERR "%s: wifi ktk set power save mode on fail\n",
					__func__);
				return -EINVAL;
			}
		} else if (ktk_params->cmd == NL80211_WIFI_KTK_STOP) {
			ar->ktk_active = false;

			if (ath6kl_wmi_ibss_pm_caps_cmd(ar->wmi,
					vif->fw_vif_idx,
					ADHOC_PS_DISABLE,
					0,
					0,
					0)) {
				printk(KERN_ERR "%s: wifi ktk set power save mode off fail\n",
					__func__);
				return -EINVAL;
			}
		}
	}

	return 0;
	break;
#endif
	default:
		return -EOPNOTSUPP;
	}
}
Beispiel #7
0
void ath6kl_btcoex_adjust_params(struct ath6kl *ar,
			int wmi_cmd, u8 *buf)
{
	switch (wmi_cmd) {
	case WMI_SET_BTCOEX_FE_ANT_CMDID:
	{
		struct wmi_set_btcoex_fe_antenna_cmd *cmd =
			(struct wmi_set_btcoex_fe_antenna_cmd *)buf;

		cmd->fe_antenna_type = fe_antenna_type(ar);

		/* disable green tx if it's enabled & BT is on */
		ar->green_tx_params.enable = false;
		ath6kl_wmi_set_green_tx_params(ar->wmi,
			&ar->green_tx_params);
	}
	break;
	case WMI_SET_BTCOEX_COLOCATED_BT_DEV_CMDID:
	{
		struct wmi_set_btcoex_colocated_bt_dev_cmd *cmd =
			(struct wmi_set_btcoex_colocated_bt_dev_cmd *)buf;
		/* Regardless of setting, force to use
		 * qcom-colocated BT. It's the current working mode.
		 */
		ar->btcoex_info.bt_vendor = BT_DEVICE_TYPE_QCOM;
		cmd->colocated_bt_dev = BT_DEVICE_TYPE_QCOM;
	}
	break;
	case WMI_SET_BTCOEX_A2DP_CONFIG_CMDID:
	{
		struct wmi_set_btcoex_a2dp_config_cmd *cmd =
			(struct wmi_set_btcoex_a2dp_config_cmd *)buf;
		struct btcoex_a2dp_config *a2dp_config = &cmd->a2dp_config;
		struct btcoex_pspoll_a2dp_config *pspoll_config =
							&cmd->pspoll_config;
		struct ath6kl_vif *vif;

		if (ar->btcoex_info.bt_vendor == BT_DEVICE_TYPE_QCOM) {
			a2dp_config->a2dp_flags |= cpu_to_le32(
				WMI_A2DP_CONFIG_FLAG_ALLOW_OPTIMIZATION);
		} else {
			a2dp_config->a2dp_flags |= cpu_to_le32(
				WMI_A2DP_CONFIG_FLAG_IS_A2DP_HIGH_PRI);
		}

		if (a2dp_config->a2dp_flags &
			WMI_A2DP_CONFIG_FLAG_IS_EDR_CAPABLE) {
			/* A2DP EDR config overwrites */

			if (a2dp_config->a2dp_flags &
				WMI_A2DP_CONFIG_FLAG_IS_BT_ROLE_MASTER) {

				a2dp_config->a2dp_flags |= cpu_to_le32(
					BTCOEX_A2DP_EDR_MAX_BLUETOOTH_TIME);

				/* disable stomping BT during WLAN scan
				 * or connection
				 */
				a2dp_config->a2dp_flags |= cpu_to_le32(
					WMI_A2DP_CONFIG_FLAG_DIS_SCANCONN_STOMP
					);
			} else {
				/* use BDR parameter for A2DP EDR slave case */
				a2dp_config->a2dp_flags |= cpu_to_le32(
					BTCOEX_A2DP_BDR_MAX_BLUETOOTH_TIME);
			}
			pspoll_config->a2dp_wlan_max_dur =
				BTCOEX_A2DP_WLAN_MAX_DUR;
		} else {
			/* A2DP BDR config overwrites */
			a2dp_config->a2dp_flags |= cpu_to_le32(
				BTCOEX_A2DP_BDR_MAX_BLUETOOTH_TIME);
			pspoll_config->a2dp_wlan_max_dur =
				BTCOEX_A2DP_BDR_WLAN_MAX_DUR;
		}

		/* change A2DP parameters for AP mode*/
		vif = ath6kl_vif_first(ar);
		if (!vif)
			return;

		if (vif->nw_type == AP_NETWORK) {
			if (a2dp_config->a2dp_flags &
				WMI_A2DP_CONFIG_FLAG_IS_EDR_CAPABLE) {
				pspoll_config->a2dp_wlan_max_dur =
					BTCOEX_APMODE_A2DP_WLAN_MAX_DUR;
				a2dp_config->a2dp_flags |= cpu_to_le32(
					BTCOEX_APMODE_A2DP_MAX_BLUETOOTH_TIME);
			} else {
				pspoll_config->a2dp_wlan_max_dur =
					BTCOEX_APMODE_A2DP_BDR_WLAN_MAX_DUR;
				a2dp_config->a2dp_flags |= cpu_to_le32(
				BTCOEX_APMODE_A2DP_BDR_MAX_BLUETOOTH_TIME);
			}

			if (ar->version.target_ver == AR6004_HW_1_3_VERSION) {
				pspoll_config->a2dp_min_bus_cnt = cpu_to_le32(
					BTCOEX_APMODE_A2DP_MIN_BURST_CNT);
			}
		}
	}
	break;
	case WMI_SET_BTCOEX_SCO_CONFIG_CMDID:
	{
		struct wmi_set_btcoex_sco_config_cmd *cmd =
			(struct wmi_set_btcoex_sco_config_cmd *)buf;
		struct btcoex_sco_config *sco_config = &cmd->sco_config;
		if (sco_config->sco_flags &
			WMI_SCO_CONFIG_FLAG_IS_EDR_CAPABLE) {
			/* disable stomping BT during WLAN scan/connection */
			sco_config->sco_flags |= cpu_to_le32(
				WMI_SCO_CONFIG_FLAG_DIS_SCANCONN_STOMP);
		}
	}
	break;

	}
}