diff options
author | codeworkx <codeworkx@cyanogenmod.com> | 2012-09-22 09:48:20 +0200 |
---|---|---|
committer | codeworkx <codeworkx@cyanogenmod.com> | 2012-09-22 14:02:16 +0200 |
commit | 2489007e7d740ccbc3e0a202914e243ad5178787 (patch) | |
tree | b8e6380ea7b1da63474ad68a5dba997e01146043 /drivers/net/wireless/ath | |
parent | 5f67568eb31e3a813c7c52461dcf66ade15fc2e7 (diff) | |
download | kernel_samsung_smdk4412-2489007e7d740ccbc3e0a202914e243ad5178787.zip kernel_samsung_smdk4412-2489007e7d740ccbc3e0a202914e243ad5178787.tar.gz kernel_samsung_smdk4412-2489007e7d740ccbc3e0a202914e243ad5178787.tar.bz2 |
merge opensource jb u5
Change-Id: I1aaec157aa196f3448eff8636134fce89a814cf2
Diffstat (limited to 'drivers/net/wireless/ath')
26 files changed, 652 insertions, 85 deletions
diff --git a/drivers/net/wireless/ath/Kconfig b/drivers/net/wireless/ath/Kconfig index 3945707..3945707 100644..100755 --- a/drivers/net/wireless/ath/Kconfig +++ b/drivers/net/wireless/ath/Kconfig diff --git a/drivers/net/wireless/ath/Makefile b/drivers/net/wireless/ath/Makefile index 214def7..214def7 100644..100755 --- a/drivers/net/wireless/ath/Makefile +++ b/drivers/net/wireless/ath/Makefile diff --git a/drivers/net/wireless/ath/ath.h b/drivers/net/wireless/ath/ath.h index 4596c33..4596c33 100644..100755 --- a/drivers/net/wireless/ath/ath.h +++ b/drivers/net/wireless/ath/ath.h diff --git a/drivers/net/wireless/ath/ath6kl/Kconfig b/drivers/net/wireless/ath/ath6kl/Kconfig index d755a5e..f8965d0 100755 --- a/drivers/net/wireless/ath/ath6kl/Kconfig +++ b/drivers/net/wireless/ath/ath6kl/Kconfig @@ -30,3 +30,12 @@ config ATH6KL_DEBUG depends on ATH6KL ---help--- Enables debug support + +config ATH6KL_LOCALE_USA + bool "Atheros regulatory domain as USA" + depends on ATH6KL + +config 5GH_WLAN_COUNTRY_CODE + bool "Atheros WiFi Driver for 5GH channel setting" + default y + diff --git a/drivers/net/wireless/ath/ath6kl/Makefile b/drivers/net/wireless/ath/ath6kl/Makefile index dcf2db9..b8b22e5 100755 --- a/drivers/net/wireless/ath/ath6kl/Makefile +++ b/drivers/net/wireless/ath/ath6kl/Makefile @@ -64,3 +64,7 @@ ath6kl_usb-y += wmiconfig.o ath6kl_usb-$(CONFIG_NL80211_TESTMODE) += testmode.o ccflags-y += -D__CHECK_ENDIAN__ +# 5GHz channels setting +ifeq ($(CONFIG_5GH_WLAN_COUNTRY_CODE),y) +ccflags-y += -DGLOBALCONFIG_WLAN_COUNTRY_CODE +endif diff --git a/drivers/net/wireless/ath/ath6kl/c210.c b/drivers/net/wireless/ath/ath6kl/c210.c index 4ae23ac..bb5f189 100644 --- a/drivers/net/wireless/ath/ath6kl/c210.c +++ b/drivers/net/wireless/ath/ath6kl/c210.c @@ -68,7 +68,7 @@ int android_readwrite_file(const A_CHAR *filename, A_CHAR *rbuf, const A_CHAR *w inode = GET_INODE_FROM_FILEP(filp); if (!inode) { - printk(KERN_ERR "android_readwrite_file: Error 2\n"); + printk(KERN_INFO "android_readwrite_file: Error 2\n"); ret = -ENOENT; break; } @@ -78,12 +78,12 @@ int android_readwrite_file(const A_CHAR *filename, A_CHAR *rbuf, const A_CHAR *w if (wbuf) { if ((ret=filp->f_op->write(filp, wbuf, length, &filp->f_pos)) < 0) { - printk(KERN_ERR "android_readwrite_file: Error 3\n"); + printk(KERN_INFO "android_readwrite_file: Error 3\n"); break; } } else { if ((ret=filp->f_op->read(filp, rbuf, length, &filp->f_pos)) < 0) { - printk(KERN_ERR "android_readwrite_file: Error 4\n"); + printk(KERN_INFO "android_readwrite_file: Error 4\n"); break; } } @@ -94,7 +94,7 @@ int android_readwrite_file(const A_CHAR *filename, A_CHAR *rbuf, const A_CHAR *w } set_fs(oldfs); - printk(KERN_ERR "android_readwrite_file: ret=%d\n", ret); + printk(KERN_INFO "android_readwrite_file: ret=%d\n", ret); return ret; } diff --git a/drivers/net/wireless/ath/ath6kl/cfg80211.c b/drivers/net/wireless/ath/ath6kl/cfg80211.c index d4b000c..cceb9fd 100755 --- a/drivers/net/wireless/ath/ath6kl/cfg80211.c +++ b/drivers/net/wireless/ath/ath6kl/cfg80211.c @@ -872,6 +872,33 @@ void ath6kl_cfg80211_disconnect_event(struct ath6kl_vif *vif, u8 reason, vif->sme_state = SME_DISCONNECTED; } +static int ath6kl_set_probed_ssids(struct ath6kl *ar, + struct ath6kl_vif *vif, + struct cfg80211_ssid *ssids, int n_ssids) +{ + u8 i; + + if (n_ssids > MAX_PROBED_SSIDS) + return -EINVAL; + + for (i = 0; i < n_ssids; i++) { + ath6kl_wmi_probedssid_cmd(ar->wmi, vif->fw_vif_idx, i, + ssids[i].ssid_len ? + SPECIFIC_SSID_FLAG : ANY_SSID_FLAG, + ssids[i].ssid_len, + ssids[i].ssid); + } + + /* Make sure no old entries are left behind */ + for (i = n_ssids; i < MAX_PROBED_SSIDS; i++) { + ath6kl_wmi_probedssid_cmd(ar->wmi, vif->fw_vif_idx, i, + DISABLE_SSID_FLAG, 0, NULL); + } + + return 0; +} + + static int ath6kl_cfg80211_scan(struct wiphy *wiphy, struct net_device *ndev, struct cfg80211_scan_request *request) { @@ -899,18 +926,10 @@ static int ath6kl_cfg80211_scan(struct wiphy *wiphy, struct net_device *ndev, } } - if (request->n_ssids && request->ssids[0].ssid_len) { - u8 i; - - if (request->n_ssids > (MAX_PROBED_SSID_INDEX - 1)) - request->n_ssids = MAX_PROBED_SSID_INDEX - 1; - - for (i = 0; i < request->n_ssids; i++) - ath6kl_wmi_probedssid_cmd(ar->wmi, vif->fw_vif_idx, - i + 1, SPECIFIC_SSID_FLAG, - request->ssids[i].ssid_len, - request->ssids[i].ssid); - } + ret = ath6kl_set_probed_ssids(ar, vif, request->ssids, + request->n_ssids); + if (ret < 0) + return ret; /* this also clears IE in fw if it's not set */ ret = ath6kl_wmi_set_appie_cmd(ar->wmi, vif->fw_vif_idx, @@ -946,6 +965,9 @@ static int ath6kl_cfg80211_scan(struct wiphy *wiphy, struct net_device *ndev, } for (i = 0; i < n_channels; i++) { +#if 0 + ath6kl_err("scanning channel %d\n",request->channels[i]->center_freq); +#endif if (ath6kl_first_2g_only && request->channels[i]->center_freq > 5000) { ath6kl_err("skip 5ghz channel %d %d\n", @@ -2115,7 +2137,10 @@ skip_arp: if (ret) return ret; - return 0; + + ret = ath6kl_hif_wait_for_pending_recv(ar); + + return ret; } static int ath6kl_wow_resume(struct ath6kl *ar) @@ -2203,7 +2228,10 @@ static int ath6kl_cfg80211_deepsleep_suspend(struct ath6kl *ar) if (ret) return ret; - return 0; + + ret = ath6kl_hif_wait_for_pending_recv(ar); + + return ret; } static int ath6kl_cfg80211_deepsleep_resume(struct ath6kl *ar) @@ -3128,7 +3156,6 @@ static int ath6kl_cfg80211_sscan_start(struct wiphy *wiphy, struct ath6kl_vif *vif = netdev_priv(dev); u16 interval; int ret; - u8 i; if (ar->state != ATH6KL_STATE_ON) return -EIO; @@ -3138,11 +3165,11 @@ static int ath6kl_cfg80211_sscan_start(struct wiphy *wiphy, ath6kl_cfg80211_scan_complete_event(vif, true); - for (i = 0; i < ar->wiphy->max_sched_scan_ssids; i++) { - ath6kl_wmi_probedssid_cmd(ar->wmi, vif->fw_vif_idx, - i, DISABLE_SSID_FLAG, - 0, NULL); - } + ret = ath6kl_set_probed_ssids(ar, vif, request->ssids, + request->n_ssids); + if (ret < 0) + return ret; + /* fw uses seconds, also make sure that it's >0 */ interval = max_t(u16, 1, request->interval / 1000); @@ -3151,15 +3178,6 @@ static int ath6kl_cfg80211_sscan_start(struct wiphy *wiphy, interval, interval, 10, 0, 0, 0, 3, 0, 0, 0); - if (request->n_ssids && request->ssids[0].ssid_len) { - for (i = 0; i < request->n_ssids; i++) { - ath6kl_wmi_probedssid_cmd(ar->wmi, vif->fw_vif_idx, - i, SPECIFIC_SSID_FLAG, - request->ssids[i].ssid_len, - request->ssids[i].ssid); - } - } - ret = ath6kl_wmi_set_wow_mode_cmd(ar->wmi, vif->fw_vif_idx, ATH6KL_WOW_MODE_ENABLE, WOW_FILTER_SSID, @@ -3441,7 +3459,7 @@ int ath6kl_register_ieee80211_hw(struct ath6kl *ar) } /* max num of ssids that can be probed during scanning */ - wiphy->max_scan_ssids = MAX_PROBED_SSID_INDEX; + wiphy->max_scan_ssids = MAX_PROBED_SSIDS; wiphy->max_scan_ie_len = 1000; /* FIX: what is correct limit? */ wiphy->bands[IEEE80211_BAND_2GHZ] = &ath6kl_band_2ghz; wiphy->bands[IEEE80211_BAND_5GHZ] = &ath6kl_band_5ghz; @@ -3460,7 +3478,7 @@ int ath6kl_register_ieee80211_hw(struct ath6kl *ar) wiphy->wowlan.pattern_min_len = 1; wiphy->wowlan.pattern_max_len = WOW_PATTERN_SIZE; - wiphy->max_sched_scan_ssids = 10; + wiphy->max_sched_scan_ssids = MAX_PROBED_SSIDS; ath6kl_setup_android_resource(ar); @@ -3551,6 +3569,8 @@ struct net_device *ath6kl_interface_add(struct ath6kl *ar, char *name, vif->pspoll_num = WLAN_CONFIG_PSPOLL_NUM; vif->mcastrate = WLAN_CONFIG_MCAST_RATE; + vif->force_reload = false; + vif->sdio_remove = false; memcpy(ndev->dev_addr, ar->mac_addr, ETH_ALEN); if (fw_vif_idx != 0) diff --git a/drivers/net/wireless/ath/ath6kl/core.h b/drivers/net/wireless/ath/ath6kl/core.h index 8ee906d..97c1ae5 100755 --- a/drivers/net/wireless/ath/ath6kl/core.h +++ b/drivers/net/wireless/ath/ath6kl/core.h @@ -609,6 +609,8 @@ struct ath6kl_vif { struct wmi_scan_params_cmd scparams; unsigned int pspoll_num; u16 mcastrate; + bool force_reload; + bool sdio_remove; }; #define WOW_LIST_ID 0 diff --git a/drivers/net/wireless/ath/ath6kl/debug.c b/drivers/net/wireless/ath/ath6kl/debug.c index 8fd6d1f..28b3e77 100755 --- a/drivers/net/wireless/ath/ath6kl/debug.c +++ b/drivers/net/wireless/ath/ath6kl/debug.c @@ -400,8 +400,10 @@ static ssize_t ath6kl_fwlog_block_read(struct file *file, ret = wait_for_completion_interruptible( &ar->debug.fwlog_completion); - if (ret == -ERESTARTSYS) + if (ret == -ERESTARTSYS) { + vfree(buf); return ret; + } spin_lock(&ar->debug.fwlog_queue.lock); } @@ -1787,6 +1789,139 @@ static const struct file_operations fops_power_params = { .llseek = default_llseek, }; +static ssize_t ath6kl_lrssi_roam_config_write(struct file *file, + const char __user *user_buf, + size_t count, loff_t *ppos) +{ + struct ath6kl *ar = file->private_data; + struct low_rssi_scan_params lrssi_params; + char buf[32]; + ssize_t len; + char *sptr, *token; + u16 val16; + + len = min(count, sizeof(buf) - 1); + if (copy_from_user(buf, user_buf, len)) + return -EFAULT; + + buf[len] = '\0'; + sptr = buf; + + token = strsep(&sptr, " "); + if (!token) + return -EINVAL; + if (kstrtou16(token, 0, &val16)) + return -EINVAL; + lrssi_params.lrssi_scan_period = cpu_to_le16(val16); + + token = strsep(&sptr, " "); + if (!token) + return -EINVAL; + if (kstrtou16(token, 0, &val16)) + return -EINVAL; + lrssi_params.lrssi_scan_threshold = cpu_to_le16(val16); + + token = strsep(&sptr, " "); + if (!token) + return -EINVAL; + if (kstrtou16(token, 0, &val16)) + return -EINVAL; + lrssi_params.lrssi_roam_threshold = cpu_to_le16(val16); + + token = strsep(&sptr, " "); + if (!token) + return -EINVAL; + if (kstrtou8(token, 0, &lrssi_params.roam_rssi_floor)) + return -EINVAL; + + ath6kl_wmi_set_roam_lrssi_config_cmd(ar->wmi, &lrssi_params); + + return count; +} + +static const struct file_operations fops_lrssi_roam_config = { + .write = ath6kl_lrssi_roam_config_write, + .open = ath6kl_debugfs_open, + .owner = THIS_MODULE, + .llseek = default_llseek, +}; + +static ssize_t ath6kl_ht_cap_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; + struct wmi_set_ht_cap_cmd ht_cap; + char buf[32]; + ssize_t len; + char *sptr, *token; + + 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'; + sptr = buf; + + token = strsep(&sptr, " "); + if (!token) + return -EINVAL; + if (kstrtou8(token, 0, &ht_cap.band)) + return -EINVAL; + + token = strsep(&sptr, " "); + if (!token) + return -EINVAL; + if (kstrtou8(token, 0, &ht_cap.enable)) + return -EINVAL; + + token = strsep(&sptr, " "); + if (!token) + return -EINVAL; + if (kstrtou8(token, 0, &ht_cap.chan_width_40m_supported)) + return -EINVAL; + + token = strsep(&sptr, " "); + if (!token) + return -EINVAL; + if (kstrtou8(token, 0, &ht_cap.short_gi_20mhz)) + return -EINVAL; + + token = strsep(&sptr, " "); + if (!token) + return -EINVAL; + if (kstrtou8(token, 0, &ht_cap.short_gi_40mhz)) + return -EINVAL; + + token = strsep(&sptr, " "); + if (!token) + return -EINVAL; + if (kstrtou8(token, 0, &ht_cap.intolerance_40mhz)) + return -EINVAL; + + token = strsep(&sptr, " "); + if (!token) + return -EINVAL; + if (kstrtou8(token, 0, &ht_cap.max_ampdu_len_exp)) + return -EINVAL; + + ath6kl_wmi_set_ht_cap_cmd(ar->wmi, vif->fw_vif_idx, &ht_cap); + + return count; +} + +static const struct file_operations fops_ht_cap = { + .write = ath6kl_ht_cap_write, + .open = ath6kl_debugfs_open, + .owner = THIS_MODULE, + .llseek = default_llseek, +}; + int ath6kl_debug_init(struct ath6kl *ar) { skb_queue_head_init(&ar->debug.fwlog_queue); @@ -1869,6 +2004,12 @@ int ath6kl_debug_init(struct ath6kl *ar) debugfs_create_file("power_params", S_IWUSR, ar->debugfs_phy, ar, &fops_power_params); + debugfs_create_file("lrssi_roam_config", S_IRUSR, ar->debugfs_phy, ar, + &fops_lrssi_roam_config); + + debugfs_create_file("ht_cap", S_IRUSR, ar->debugfs_phy, ar, + &fops_ht_cap); + return ath6kl_init_debugfs_pri(ar); } diff --git a/drivers/net/wireless/ath/ath6kl/debug.h b/drivers/net/wireless/ath/ath6kl/debug.h index 83a7322..aaecb5d 100755 --- a/drivers/net/wireless/ath/ath6kl/debug.h +++ b/drivers/net/wireless/ath/ath6kl/debug.h @@ -54,9 +54,9 @@ char *sec_conv_mac(const u8 *mac); #define ath6kl_info(fmt, ...) \ ath6kl_printk(KERN_INFO, fmt, ##__VA_ARGS__) #define ath6kl_err(fmt, ...) \ - ath6kl_printk(KERN_ERR, fmt, ##__VA_ARGS__) + ath6kl_printk(KERN_INFO, fmt, ##__VA_ARGS__) #define ath6kl_warn(fmt, ...) \ - ath6kl_printk(KERN_WARNING, fmt, ##__VA_ARGS__) + ath6kl_printk(KERN_INFO, fmt, ##__VA_ARGS__) #define AR_DBG_LVL_CHECK(mask) (debug_mask & mask) diff --git a/drivers/net/wireless/ath/ath6kl/hif.c b/drivers/net/wireless/ath/ath6kl/hif.c index ca910a1..2793ab6 100755 --- a/drivers/net/wireless/ath/ath6kl/hif.c +++ b/drivers/net/wireless/ath/ath6kl/hif.c @@ -118,6 +118,9 @@ static int ath6kl_hif_proc_dbg_intr(struct ath6kl_device *dev) { u32 dummy; int ret; + struct ath6kl_vif *vif; + + vif = ath6kl_vif_first(dev->ar); ath6kl_warn("firmware crashed\n"); @@ -133,6 +136,8 @@ static int ath6kl_hif_proc_dbg_intr(struct ath6kl_device *dev) ath6kl_hif_dump_fw_crash(dev->ar); ath6kl_read_fwlogs(dev->ar); + cfg80211_priv_event(vif->ndev, "HANG", GFP_ATOMIC); + return ret; } @@ -393,7 +398,8 @@ static int proc_pending_irqs(struct ath6kl_device *dev, bool *done) u8 host_int_status = 0; u32 lk_ahd = 0; u8 htc_mbox = 1 << HTC_MAILBOX; - + struct ath6kl_vif *vif; + vif = ath6kl_vif_first(dev->ar); ath6kl_dbg(ATH6KL_DBG_IRQ, "proc_pending_irqs: (dev: 0x%p)\n", dev); /* @@ -402,7 +408,12 @@ static int proc_pending_irqs(struct ath6kl_device *dev, bool *done) * sleep or call any API that can block or switch thread/task * contexts. This is a fully schedulable context. */ - +#ifdef CONFIG_MACH_PX + if (vif->sdio_remove == true) { + *done = true; + goto out; + } +#endif /* * Process pending intr only when int_status_en is clear, it may * result in unnecessary bus transaction otherwise. Target may be @@ -450,8 +461,19 @@ static int proc_pending_irqs(struct ath6kl_device *dev, bool *done) htc_mbox) { rg = &dev->irq_proc_reg; lk_ahd = le32_to_cpu(rg->rx_lkahd[HTC_MAILBOX]); - if (!lk_ahd) - ath6kl_err("lookAhead is zero!\n"); + + if (vif->force_reload == true) { + lk_ahd = 0; + } + if (!lk_ahd) { + ath6kl_err("lookAhead is zero! force_reload = %d\n", vif->force_reload); +#ifdef CONFIG_MACH_PX + cfg80211_priv_event(vif->ndev, "HANG", GFP_ATOMIC); + ath6kl_hif_rx_control(dev, false); + ssleep(3); + status = -ENOMEM; +#endif + } } } } @@ -476,9 +498,17 @@ static int proc_pending_irqs(struct ath6kl_device *dev, bool *done) */ status = ath6kl_htc_rxmsg_pending_handler(dev->htc_cnxt, lk_ahd, &fetched); +#ifdef CONFIG_MACH_PX + if (status && status != -ECANCELED) { + cfg80211_priv_event(vif->ndev, "HANG", GFP_ATOMIC); + ath6kl_hif_rx_control(dev, false); + ssleep(3); + goto out; + } +#else if (status) goto out; - +#endif if (!fetched) /* * HTC could not pull any messages out due to lack @@ -539,10 +569,22 @@ out: /* interrupt handler, kicks off all interrupt processing */ int ath6kl_hif_intr_bh_handler(struct ath6kl *ar) { +#ifdef CONFIG_MACH_PX + struct ath6kl_device *dev; + unsigned long timeout; + int status = 0; + bool done = false; + + if ((ar != NULL) && (ar->htc_target != NULL) && (ar->htc_target->dev != NULL)) + dev = ar->htc_target->dev; + else + return status; +#else struct ath6kl_device *dev = ar->htc_target->dev; unsigned long timeout; int status = 0; bool done = false; +#endif /* * Reset counter used to flag a re-scan of IRQ status registers on @@ -555,7 +597,12 @@ int ath6kl_hif_intr_bh_handler(struct ath6kl *ar) * re-read. */ timeout = jiffies + msecs_to_jiffies(ATH6KL_HIF_COMMUNICATION_TIMEOUT); - while (time_before(jiffies, timeout) && !done) { +#ifdef CONFIG_MACH_PX + while (time_before(jiffies, timeout) && !done && (dev != NULL)) +#else + while (time_before(jiffies, timeout) && !done) +#endif + { status = proc_pending_irqs(dev, &done); if (status) break; diff --git a/drivers/net/wireless/ath/ath6kl/htc.c b/drivers/net/wireless/ath/ath6kl/htc.c index 402e1c5..16729fb 100755 --- a/drivers/net/wireless/ath/ath6kl/htc.c +++ b/drivers/net/wireless/ath/ath6kl/htc.c @@ -1451,6 +1451,8 @@ static int ath6kl_htc_rx_alloc(struct htc_target *target, struct htc_packet *packet, *tmp_pkt; struct htc_frame_hdr *htc_hdr; int i, n_msg; + struct ath6kl_vif *vif; + vif = ath6kl_vif_first(target->dev->ar); spin_lock_bh(&target->rx_lock); @@ -2128,6 +2130,8 @@ int ath6kl_htc_rxmsg_pending_handler(struct htc_target *target, int num_look_ahead = 1; enum htc_endpoint_id id; int n_fetched = 0; + struct ath6kl_vif *vif; + vif = ath6kl_vif_first(target->dev->ar); INIT_LIST_HEAD(&comp_pktq); *num_pkts = 0; diff --git a/drivers/net/wireless/ath/ath6kl/init.c b/drivers/net/wireless/ath/ath6kl/init.c index 76a1d64..ba587f9 100755 --- a/drivers/net/wireless/ath/ath6kl/init.c +++ b/drivers/net/wireless/ath/ath6kl/init.c @@ -46,7 +46,13 @@ static unsigned int ar6k_clock = 26000000; #else static unsigned int ar6k_clock = 19200000; #endif + +#ifdef CONFIG_ATH6KL_LOCALE_USA +static unsigned short reg_domain = 0x8348; +#else static unsigned short reg_domain = 0xffff; +#endif + static unsigned short lrssi = 10; static unsigned short en_ani = 1; @@ -481,7 +487,7 @@ static int ath6kl_target_config_wlan_params(struct ath6kl *ar, int idx) { int status = 0; int ret; -#if CONFIG_MACH_PX +#ifdef CONFIG_MACH_PX struct ath6kl_vif *vif = ath6kl_get_vif_by_index(ar, idx); #endif /* @@ -496,7 +502,7 @@ static int ath6kl_target_config_wlan_params(struct ath6kl *ar, int idx) } -#if CONFIG_MACH_PX +#ifdef CONFIG_MACH_PX if (ar->conf_flags & ATH6KL_CONF_IGNORE_PS_FAIL_EVT_IN_SCAN) { if ((ath6kl_wmi_pmparams_cmd(ar->wmi, idx, 0, vif->pspoll_num, 0, 0, 1, @@ -1528,6 +1534,157 @@ static int ath6kl_upload_testscript(struct ath6kl *ar) return 0; } +#ifdef GLOBALCONFIG_WLAN_COUNTRY_CODE +#define COUNTRY_MAX 76 +struct channels { + char country[30]; + char ccode[6]; + unsigned short reg_dmn_code; +} +pArray[COUNTRY_MAX] = { + {"Afghanistan", "AF 0", 0x406a}, + {"Albania", "AL 0", 0x8008}, + {"Algeria", "DZ 0", 0x800c}, + {"Angola", "AD 0", 0x406a}, + {"Austria", "AT 0", 0x8028}, + {"Australia", "AU 0", 0x8024}, + {"Bangladesh", "BD 0", 0x8032}, + {"Belgium", "BE 0", 0x8038}, + {"Bosnia", "BA 0", 0x8046}, + {"Bulgaria", "BG 0", 0x8064}, + {"Croatia", "HR 0", 0x80bf}, + {"Greece", "GR 0", 0x812c}, + {"Czech Republic", "CZ 0", 0x80cb}, + {"Egypt", "EG 0", 0x8332}, + {"Nordic", "FI 0", 0x80f6}, + {"Finland", "FI 0", 0x80f6}, + {"France", "FR 0", 0x80FA}, + {"Gabon", "GA 0", 0x406a}, + {"Germany", "DE 0", 0x8114}, + {"Ghana", "GH 0", 0x406a}, + {"Greece", "GR 0", 0x812c}, + {"Hungary", "HU 0", 0x815c}, + {"Iceland", "IS 0", 0x8160}, + {"India", "IN 0", 0x8164}, + {"Indonesia", "ID 0", 0x8168}, + {"Iraq", "IQ 0", 0x406a}, + {"IE", "IE 0", 0x8174}, + {"Ireland", "IE 0", 0x8174}, + {"Israel", "IL 0", 0x8178}, + {"Italy", "IT 0", 0x817c}, + {"Jamaica", "JM 0", 0x8184}, + {"Jordan", "JO 0", 0x8190}, + {"Central Asia", "KZ 0", 0x818e}, + {"Kazakhstan", "KZ 0", 0x818e}, + {"Kenya", "KE 0", 0x8198}, + {"BALTIC", "LV 0", 0x81ac}, + {"Libya", "LY 0", 0x406a}, + {"Lithuania", "LT 0", 0x81b8}, + {"Luxemburg", "LU 0", 0x81ba}, + {"Macedonia", "MK 0", 0x8327}, + {"Malaysia", "MY 0", 0x81ca}, + {"Mongolia", "MN 0", 0x406a}, + {"Montenegro", "ME 0", 0x837b}, + {"Morocco", "MA 0", 0x81f8}, + {"Nepal", "NP 0", 0x820c}, + {"Netherlands", "NL 0", 0x8210}, + {"The Netherlands", "NL 0", 0x8210}, + {"New Zealand", "NZ 0", 0x822a}, + {"Nigeria", "NG 0", 0x406a}, + {"Norway", "NO 0", 0x8242}, + {"Pakistan", "PK 0", 0x824a}, + {"Philippines", "PH 0", 0x8260}, + {"Poland", "PL 0", 0x8268}, + {"Portugal", "PT 0", 0x826c}, + {"Romania", "RO 0", 0x8282}, + {"Russia", "RU 0", 0x8283}, + {"KSA", "SA 0", 0x82aa}, + {"Senegal", "SN 0", 0x406a}, + {"Serbia", "RS 0", 0x8114}, + {"Singapore", "SG 0", 0x82be}, + {"Slovakia", "SK 0", 0x82bf}, + {"Slovenia", "SI 0", 0x82c1}, + {"South Africa", "ZA 0", 0x82c6}, + {"Spain", "ES 0", 0x82D4}, + {"Sri Lanka", "LK 0", 0x8090}, + {"Sweden", "SE 0", 0x82f0}, + {"Switzerland", "CH 0", 0x82f4}, + {"Thailand", "TH 0", 0x82fc}, + {"Tunisia", "TN 0", 0x8314}, + {"Turkey", "TR 0", 0x8318}, + {"Ukraine", "UA 0", 0x8324}, + {"UK", "GB 0", 0x833A}, + {"UK &IRE", "GB 0", 0x833A}, + {"United Kingdom", "GB 0", 0x833A}, + {"Uzbekistan", "UZ 0", 0x835c}, + {"Vietnam", "VN 0", 0x82c0} +}; + +static unsigned short ath6kl_get_reg_dmn_code(u8 *ccode) +{ + int i = 0; + + for (i = 0; i < COUNTRY_MAX; i++) { + if (strncmp(ccode, pArray[i].ccode, 2) == 0) { + ath6kl_dbg(ATH6KL_DBG_BOOT, "%s: %s %s 0x%x", + __func__, pArray[i].country, pArray[i].ccode, + pArray[i].reg_dmn_code); + return pArray[i].reg_dmn_code; + } + } + + ath6kl_err("%s() Failed to find reg_domain code for %s\n", + __func__, ccode); + + return 0xffff; +} + +static void ath6kl_update_ccodeinfo(struct ath6kl *ar) +{ + char ccode_filename[32]; + + do { + int ret = 0; + size_t length; + u8 *pdata = NULL; + + snprintf(ccode_filename, sizeof(ccode_filename), + "/data/.ccode.info"); + + ret = android_readwrite_file(ccode_filename, NULL, NULL, 0); + + if (ret < 0) + break; + else + length = ret; + + pdata = vmalloc(length + 1); + + if (!pdata) { + ath6kl_dbg(ATH6KL_DBG_BOOT, + "%s: Cannot allocate buffer for ccode_info (%d)\n", + __func__, length); + break; + } + + if (android_readwrite_file(ccode_filename, + (char *)pdata, NULL, length) != length) { + ath6kl_dbg(ATH6KL_DBG_BOOT, + "%s: file read error, length %d\n", + __func__, length); + vfree(pdata); + break; + } + pdata[length] = '\0'; + + if (reg_domain == 0xffff) + reg_domain = ath6kl_get_reg_dmn_code(pdata); + + + vfree(pdata); + } while (0); +} +#endif static void ath6kl_update_psminfo(struct ath6kl *ar) { @@ -1859,6 +2016,9 @@ int ath6kl_init_hw_start(struct ath6kl *ar) } ar->state = ATH6KL_STATE_ON; +#ifdef CONFIG_MACH_PX + wake_up(&ar->event_wq); +#endif return 0; @@ -1941,6 +2101,9 @@ int ath6kl_core_init(struct ath6kl *ar) ath6kl_mangle_mac_address(ar); ath6kl_update_psminfo(ar); +#ifdef GLOBALCONFIG_WLAN_COUNTRY_CODE + ath6kl_update_ccodeinfo(ar); +#endif /* FIXME: we should free all firmwares in the error cases below */ diff --git a/drivers/net/wireless/ath/ath6kl/main.c b/drivers/net/wireless/ath/ath6kl/main.c index 2b1a37b..9c674e6 100755 --- a/drivers/net/wireless/ath/ath6kl/main.c +++ b/drivers/net/wireless/ath/ath6kl/main.c @@ -343,6 +343,7 @@ out: #ifdef CONFIG_MACH_PX void ath6kl_print_ar6k_registers(struct ath6kl *ar) { +#if 0 u32 reg_addr; u32 epc_addr1, epc_addr2, epc_addr3, epc_addr4; u32 epc1, epc2, epc3, epc4; @@ -417,7 +418,7 @@ void ath6kl_print_ar6k_registers(struct ath6kl *ar) else ath6kl_dbg(ATH6KL_DBG_TRC, "ath6kl:reg_dump system sleep: %x\n", ssleep); - +#endif } #endif @@ -1267,20 +1268,26 @@ static void ath6kl_set_multicast_list(struct net_device *ndev) goto out; } - memcpy(mc_filter->hw_addr, ha->addr, - ATH6KL_MCAST_FILTER_MAC_ADDR_SIZE); - /* Set the multicast filter */ - ath6kl_dbg(ATH6KL_DBG_TRC, - "Adding %s to multicast filter list\n", - sec_conv_mac(mc_filter->hw_addr)); - ret = ath6kl_wmi_add_del_mcast_filter_cmd(vif->ar->wmi, - vif->fw_vif_idx, mc_filter->hw_addr, - true); - if (ret) { - ath6kl_warn("Failed to add multicast filter :%s\n", - sec_conv_mac(mc_filter->hw_addr)); + if (memcmp(ha->addr, "\x33\x33\x00\x00\x00\x01", ETH_ALEN) == 0) { + ath6kl_warn("Skipped : %s\n", sec_conv_mac(ha->addr)); kfree(mc_filter); - goto out; + continue; + } else { + memcpy(mc_filter->hw_addr, ha->addr, + ATH6KL_MCAST_FILTER_MAC_ADDR_SIZE); + /* Set the multicast filter */ + ath6kl_dbg(ATH6KL_DBG_TRC, + "Adding %s to multicast filter list\n", + sec_conv_mac(mc_filter->hw_addr)); + ret = ath6kl_wmi_add_del_mcast_filter_cmd(vif->ar->wmi, + vif->fw_vif_idx, mc_filter->hw_addr, + true); + if (ret) { + ath6kl_warn("Failed to add multicast filter :%s\n", + sec_conv_mac(mc_filter->hw_addr)); + kfree(mc_filter); + goto out; + } } list_add_tail(&mc_filter->list, &mc_filter_new); diff --git a/drivers/net/wireless/ath/ath6kl/sdio.c b/drivers/net/wireless/ath/ath6kl/sdio.c index 52f56ab..d4ea7ad 100755 --- a/drivers/net/wireless/ath/ath6kl/sdio.c +++ b/drivers/net/wireless/ath/ath6kl/sdio.c @@ -926,7 +926,9 @@ cut_pwr: static int ath6kl_sdio_resume(struct ath6kl *ar) { +#if !defined(CONFIG_MACH_P8LTE) ath6kl_sdio_setup_irq_mode(ar); +#endif switch (ar->state) { case ATH6KL_STATE_OFF: @@ -1288,7 +1290,7 @@ static int ath6kl_sdio_pm_suspend(struct device *device) struct sdio_func *func; struct ath6kl_sdio *ar_sdio; int ret; - ath6kl_dbg(ATH6KL_DBG_SUSPEND, "sdio pm resume\n"); + ath6kl_dbg(ATH6KL_DBG_SUSPEND, "sdio pm suspend\n"); func = dev_to_sdio_func(device); ar_sdio = sdio_get_drvdata(func); @@ -1433,12 +1435,24 @@ err_hif: static void ath6kl_sdio_remove(struct sdio_func *func) { struct ath6kl_sdio *ar_sdio; + struct ath6kl_vif *vif; + long timeleft; ath6kl_dbg(ATH6KL_DBG_BOOT, "sdio removed func %d vendor 0x%x device 0x%x\n", func->num, func->vendor, func->device); ar_sdio = sdio_get_drvdata(func); +#ifdef CONFIG_MACH_PX + vif = ath6kl_vif_first(ar_sdio->ar); + /* Wait for Wmi event to be ready */ + timeleft = wait_event_interruptible_timeout(ar_sdio->ar->event_wq, + ar_sdio->ar->state == ATH6KL_STATE_ON, + WMI_TIMEOUT); + + ath6kl_hif_rx_control(ar_sdio->ar->htc_target->dev, false); + vif->sdio_remove = true; +#endif ath6kl_stop_txrx(ar_sdio->ar); cancel_work_sync(&ar_sdio->wr_async_work); diff --git a/drivers/net/wireless/ath/ath6kl/softmac.c b/drivers/net/wireless/ath/ath6kl/softmac.c index d26e9e8..3725871 100644 --- a/drivers/net/wireless/ath/ath6kl/softmac.c +++ b/drivers/net/wireless/ath/ath6kl/softmac.c @@ -78,13 +78,15 @@ static int ath6kl_fetch_nvmac_info(struct ath6kl *ar) char *softmac_old_filename = "/data/.mac.info"; do { + /* isnvmac_imei = android_readwrite_file(nvfilepath_imei, NULL, NULL, 0); isnvmac_wifi = android_readwrite_file(nvfilepath_wifi, - NULL, NULL, 0); + NULL, NULL, 0); */ ismac_file = android_readwrite_file(softmac_filename, NULL, NULL, 0); + /* if (isnvmac_imei >= 16 && isnvmac_wifi >= 16) { strcpy(nvfilepath, nvfilepath_wifi); isnvmac_file = isnvmac_wifi; @@ -94,10 +96,11 @@ static int ath6kl_fetch_nvmac_info(struct ath6kl *ar) } else if (isnvmac_imei >= 16) { strcpy(nvfilepath, nvfilepath_imei); isnvmac_file = isnvmac_imei; - } + } */ /* copy .nvmac.info file to .mac.info wifi driver will use .mac.info finally */ + /* if (isnvmac_file >= 16) { ret = android_readwrite_file(nvfilepath, (char *)softmac_temp, NULL, isnvmac_file); @@ -111,9 +114,10 @@ static int ath6kl_fetch_nvmac_info(struct ath6kl *ar) __func__, ret); ret = android_readwrite_file(softmac_old_filename, NULL, (char *)softmac_temp, ret); - } + } */ - if (isnvmac_file < 16 && ismac_file < 16) { + //if (isnvmac_file < 16 && ismac_file < 16) { + if (ismac_file < 16) { snprintf(softmac_temp, sizeof(softmac_temp), "00:12:34:%02x:%02x:%02x", random32() & 0xff, diff --git a/drivers/net/wireless/ath/ath6kl/txrx.c b/drivers/net/wireless/ath/ath6kl/txrx.c index ff32b70..b8924dd 100755..100644 --- a/drivers/net/wireless/ath/ath6kl/txrx.c +++ b/drivers/net/wireless/ath/ath6kl/txrx.c @@ -286,6 +286,8 @@ int ath6kl_control_tx(void *devt, struct sk_buff *skb, struct ath6kl *ar = devt; int status = 0; struct ath6kl_cookie *cookie = NULL; + struct ath6kl_vif *vif; + vif = ath6kl_vif_first(ar); if (WARN_ON_ONCE(ar->state == ATH6KL_STATE_WOW)) goto fail_ctrl_tx; @@ -308,7 +310,8 @@ int ath6kl_control_tx(void *devt, struct sk_buff *skb, ath6kl_err("wmi ctrl ep full, dropping pkt : 0x%p, len:%d\n", skb, skb->len); #ifdef CONFIG_MACH_PX - ath6kl_print_ar6k_registers(ar); + if (vif->nw_type == INFRA_NETWORK) + vif->force_reload = true; #endif } else cookie = ath6kl_alloc_cookie(ar); @@ -362,8 +365,8 @@ int ath6kl_data_tx(struct sk_buff *skb, struct net_device *dev) u32 flags = 0; ath6kl_dbg(ATH6KL_DBG_WLAN_TX, - "%s: skb=0x%p, data=0x%p, len=0x%x\n", __func__, - skb, skb->data, skb->len); + "%s: skb=0x%p, data=0x%p, len=0x%x, actual_len=0x%x\n", __func__, + skb, skb->data, skb->len, skb->tail - skb->data); /* If target is not associated */ if (!test_bit(CONNECTED, &vif->flags)) { @@ -394,7 +397,8 @@ int ath6kl_data_tx(struct sk_buff *skb, struct net_device *dev) csum_dest = skb->csum_offset + csum_start; } - if (skb_headroom(skb) < dev->needed_headroom) { + if (skb_headroom(skb) < dev->needed_headroom) + { struct sk_buff *tmp_skb = skb; skb = skb_realloc_headroom(skb, dev->needed_headroom); @@ -476,13 +480,8 @@ int ath6kl_data_tx(struct sk_buff *skb, struct net_device *dev) spin_unlock_bh(&ar->lock); -#ifdef CONFIG_MACH_PX - if (false && !IS_ALIGNED((unsigned long) skb->data - HTC_HDR_LENGTH, 4) && - skb_cloned(skb)) { -#else if (!IS_ALIGNED((unsigned long) skb->data - HTC_HDR_LENGTH, 4) && skb_cloned(skb)) { -#endif /* * We will touch (move the buffer data to align it. Since the * skb buffer is cloned and not only the header is changed, we @@ -506,7 +505,6 @@ int ath6kl_data_tx(struct sk_buff *skb, struct net_device *dev) ath6kl_dbg_dump(ATH6KL_DBG_RAW_BYTES, __func__, "tx ", skb->data, skb->len); - /* * HTC interface is asynchronous, if this fails, cleanup will * happen in the ath6kl_tx_complete callback. @@ -836,6 +834,10 @@ static void ath6kl_deliver_frames_to_nw_stack(struct net_device *dev, skb->protocol = eth_type_trans(skb, skb->dev); +#ifdef CONFIG_MACH_PX + skb->len = skb->tail - skb->data; +#endif + netif_rx_ni(skb); } @@ -1344,8 +1346,8 @@ void ath6kl_rx(struct htc_target *target, struct htc_packet *packet) spin_unlock_bh(&vif->if_lock); - ath6kl_dbg_dump(ATH6KL_DBG_RAW_BYTES, __func__, "rx ", - skb->data, skb->len); + //ath6kl_dbg_dump(ATH6KL_DBG_RAW_BYTES, __func__, "rx ", + // skb->data, skb->len); skb->dev = vif->ndev; diff --git a/drivers/net/wireless/ath/ath6kl/wmi.c b/drivers/net/wireless/ath/ath6kl/wmi.c index 6fbf4a9..f7afb1d 100755 --- a/drivers/net/wireless/ath/ath6kl/wmi.c +++ b/drivers/net/wireless/ath/ath6kl/wmi.c @@ -291,6 +291,13 @@ int ath6kl_wmi_implicit_create_pstream(struct wmi *wmi, u8 if_idx, layer2_priority); } else usr_pri = layer2_priority & 0x7; + + /* + * Queue the EAPOL frames in the same WMM_AC_VO queue + * as that of management frames. + */ + if (skb->protocol == cpu_to_be16(ETH_P_PAE)) + usr_pri = WMI_VOICE_USER_PRIORITY; } /* @@ -526,6 +533,8 @@ static int ath6kl_wmi_tx_status_event_rx(struct wmi *wmi, u8 *datap, int len, id = le32_to_cpu(ev->id); ath6kl_dbg(ATH6KL_DBG_WMI, "tx_status: id=%x ack_status=%u\n", id, ev->ack_status); + + mutex_lock(&wmi->lock_mgmt); if (wmi->last_mgmt_tx_frame) { cfg80211_mgmt_tx_status(vif->ndev, id, wmi->last_mgmt_tx_frame, @@ -535,6 +544,7 @@ static int ath6kl_wmi_tx_status_event_rx(struct wmi *wmi, u8 *datap, int len, wmi->last_mgmt_tx_frame = NULL; wmi->last_mgmt_tx_frame_len = 0; } + mutex_unlock(&wmi->lock_mgmt); return 0; } @@ -712,13 +722,57 @@ int ath6kl_wmi_set_roam_lrssi_cmd(struct wmi *wmi, u8 lrssi) cmd = (struct roam_ctrl_cmd *) skb->data; +#ifdef CONFIG_MACH_PX + if (wmi->parent_dev->psminfo == 0) + cmd->info.params.lrssi_scan_period = 0xFFFF; + else + cmd->info.params.lrssi_scan_period = cpu_to_le16(DEF_LRSSI_SCAN_PERIOD); +#else cmd->info.params.lrssi_scan_period = cpu_to_le16(DEF_LRSSI_SCAN_PERIOD); +#endif + cmd->info.params.lrssi_scan_threshold = a_cpu_to_sle16(lrssi + DEF_SCAN_FOR_ROAM_INTVL); cmd->info.params.lrssi_roam_threshold = a_cpu_to_sle16(lrssi); cmd->info.params.roam_rssi_floor = DEF_LRSSI_ROAM_FLOOR; cmd->roam_ctrl = WMI_SET_LRSSI_SCAN_PARAMS; + ath6kl_dbg(ATH6KL_DBG_WMI, "lrssi_scan_period %d, lrssi_scan_threshold = %d, " + "lrssi_roam_threshold = %d, roam_rssi_floor = %d\n", + cmd->info.params.lrssi_scan_period, cmd->info.params.lrssi_scan_threshold, + cmd->info.params.lrssi_roam_threshold, cmd->info.params.roam_rssi_floor); + + ath6kl_wmi_cmd_send(wmi, 0, skb, WMI_SET_ROAM_CTRL_CMDID, + NO_SYNC_WMIFLAG); + + return 0; +} + +int ath6kl_wmi_set_roam_lrssi_config_cmd(struct wmi *wmi, + struct low_rssi_scan_params *params) +{ + struct sk_buff *skb; + struct roam_ctrl_cmd *cmd; + + skb = ath6kl_wmi_get_new_buf(sizeof(*cmd)); + if (!skb) + return -ENOMEM; + + cmd = (struct roam_ctrl_cmd *) skb->data; + ath6kl_dbg(ATH6KL_DBG_WMI, "lrssi_scan_period %d, lrssi_scan_threshold = %d, " + "lrssi_roam_threshold = %d, roam_rssi_floor = %d\n", + params->lrssi_scan_period, params->lrssi_scan_threshold, + params->lrssi_roam_threshold, params->roam_rssi_floor); + + if (params->lrssi_scan_period == 0) + cmd->info.params.lrssi_scan_period = 0xFFFF; + else + cmd->info.params.lrssi_scan_period = params->lrssi_scan_period; + cmd->info.params.lrssi_scan_threshold = params->lrssi_scan_threshold; + cmd->info.params.lrssi_roam_threshold = params->lrssi_roam_threshold; + cmd->info.params.roam_rssi_floor = params->roam_rssi_floor; + cmd->roam_ctrl = WMI_SET_LRSSI_SCAN_PARAMS; + ath6kl_wmi_cmd_send(wmi, 0, skb, WMI_SET_ROAM_CTRL_CMDID, NO_SYNC_WMIFLAG); @@ -1823,7 +1877,11 @@ int ath6kl_wmi_beginscan_cmd(struct wmi *wmi, u8 if_idx, { struct sk_buff *skb; struct wmi_begin_scan_cmd *sc; +#ifdef CONFIG_MACH_PX + unsigned int size; +#else s8 size; +#endif int i, band, ret; struct ath6kl *ar = wmi->parent_dev; int num_rates; @@ -1989,7 +2047,7 @@ int ath6kl_wmi_probedssid_cmd(struct wmi *wmi, u8 if_idx, u8 index, u8 flag, struct wmi_probed_ssid_cmd *cmd; int ret; - if (index > MAX_PROBED_SSID_INDEX) + if (index > MAX_PROBED_SSIDS) return -EINVAL; if (ssid_len > sizeof(cmd->ssid)) @@ -2047,7 +2105,7 @@ int ath6kl_wmi_mcastrate_cmd(struct wmi *wmi, u8 if_idx, struct wmi_set_mcastrate_cmd *cmd; int ret; - printk(KERN_ERR "\tmcastrate = %d\n", bitrate); + printk(KERN_INFO "\tmcastrate = %d\n", bitrate); skb = ath6kl_wmi_get_new_buf(sizeof(*cmd)); if (!skb) @@ -2988,6 +3046,61 @@ int ath6kl_wmi_add_del_mcast_filter_cmd(struct wmi *wmi, u8 if_idx, return ret; } +int ath6kl_wmi_set_ht_cap_cmd(struct wmi *wmi, u8 if_idx, + struct wmi_set_ht_cap_cmd *params) +{ + struct sk_buff *skb; + struct wmi_set_ht_cap_cmd *cmd; + struct ath6kl *ar = wmi->parent_dev; + struct ieee80211_supported_band *sband; + int ret; + + skb = ath6kl_wmi_get_new_buf(sizeof(*cmd)); + if (!skb) + return -ENOMEM; + + cmd = (struct wmi_set_ht_cap_cmd *) skb->data; + ath6kl_dbg(ATH6KL_DBG_WMI, "bands %d, ht_supported = %d, " + "chan_width_40m_supported %d, short_gi_20mhz = %d, " + "short_gi_40mhz = %d, intolerance_40mhz = %d\n", + params->band, params->enable, + params->chan_width_40m_supported, params->short_gi_20mhz, + params->short_gi_40mhz, params->intolerance_40mhz); + memcpy(cmd, params, sizeof(*cmd)); + + sband = ar->wiphy->bands[params->band]; + sband->ht_cap.ht_supported = params->enable; + if (params->chan_width_40m_supported) + sband->ht_cap.cap |= IEEE80211_HT_CAP_SUP_WIDTH_20_40; + else + sband->ht_cap.cap &= ~IEEE80211_HT_CAP_SUP_WIDTH_20_40; + + if (params->short_gi_20mhz) + sband->ht_cap.cap |= IEEE80211_HT_CAP_SGI_20; + else + sband->ht_cap.cap &= ~IEEE80211_HT_CAP_SGI_20; + + if (params->short_gi_40mhz) + sband->ht_cap.cap |= IEEE80211_HT_CAP_SGI_40; + else + sband->ht_cap.cap &= ~IEEE80211_HT_CAP_SGI_40; + + if (params->intolerance_40mhz) + sband->ht_cap.cap |= IEEE80211_HT_CAP_40MHZ_INTOLERANT; + else + sband->ht_cap.cap &= ~IEEE80211_HT_CAP_40MHZ_INTOLERANT; + + if (params->max_ampdu_len_exp) + sband->ht_cap.cap |= IEEE80211_HT_CAP_MAX_AMSDU; + else + sband->ht_cap.cap &= ~IEEE80211_HT_CAP_MAX_AMSDU; + + ret = ath6kl_wmi_cmd_send(wmi, if_idx, skb, WMI_SET_HT_CAP_CMDID, + NO_SYNC_WMIFLAG); + return ret; +} + + s32 ath6kl_wmi_get_rate(s8 rate_index) { u32 sgi; @@ -3311,6 +3424,7 @@ static int ath6kl_wmi_send_action_cmd(struct wmi *wmi, u8 if_idx, u32 id, struct sk_buff *skb; struct wmi_send_action_cmd *p; u8 *buf; + int ret; if (wait) return -EINVAL; /* Offload for wait not supported */ @@ -3325,7 +3439,10 @@ static int ath6kl_wmi_send_action_cmd(struct wmi *wmi, u8 if_idx, u32 id, return -ENOMEM; } - kfree(wmi->last_mgmt_tx_frame); + mutex_lock(&wmi->lock_mgmt); + if (wmi->last_mgmt_tx_frame) + kfree(wmi->last_mgmt_tx_frame); + memcpy(buf, data, data_len); wmi->last_mgmt_tx_frame = buf; wmi->last_mgmt_tx_frame_len = data_len; @@ -3338,8 +3455,10 @@ static int ath6kl_wmi_send_action_cmd(struct wmi *wmi, u8 if_idx, u32 id, p->wait = cpu_to_le32(wait); p->len = cpu_to_le16(data_len); memcpy(p->data, data, data_len); - return ath6kl_wmi_cmd_send(wmi, if_idx, skb, WMI_SEND_ACTION_CMDID, + ret = ath6kl_wmi_cmd_send(wmi, if_idx, skb, WMI_SEND_ACTION_CMDID, NO_SYNC_WMIFLAG); + mutex_unlock(&wmi->lock_mgmt); + return ret; } static int __ath6kl_wmi_send_mgmt_cmd(struct wmi *wmi, u8 if_idx, u32 id, @@ -3349,6 +3468,7 @@ static int __ath6kl_wmi_send_mgmt_cmd(struct wmi *wmi, u8 if_idx, u32 id, struct sk_buff *skb; struct wmi_send_mgmt_cmd *p; u8 *buf; + int ret; if (wait) return -EINVAL; /* Offload for wait not supported */ @@ -3363,7 +3483,10 @@ static int __ath6kl_wmi_send_mgmt_cmd(struct wmi *wmi, u8 if_idx, u32 id, return -ENOMEM; } - kfree(wmi->last_mgmt_tx_frame); + mutex_lock(&wmi->lock_mgmt); + if (wmi->last_mgmt_tx_frame) + kfree(wmi->last_mgmt_tx_frame); + memcpy(buf, data, data_len); wmi->last_mgmt_tx_frame = buf; wmi->last_mgmt_tx_frame_len = data_len; @@ -3377,8 +3500,11 @@ static int __ath6kl_wmi_send_mgmt_cmd(struct wmi *wmi, u8 if_idx, u32 id, p->no_cck = cpu_to_le32(no_cck); p->len = cpu_to_le16(data_len); memcpy(p->data, data, data_len); - return ath6kl_wmi_cmd_send(wmi, if_idx, skb, WMI_SEND_MGMT_CMDID, + ret = ath6kl_wmi_cmd_send(wmi, if_idx, skb, WMI_SEND_MGMT_CMDID, NO_SYNC_WMIFLAG); + mutex_unlock(&wmi->lock_mgmt); + + return ret; } int ath6kl_wmi_send_mgmt_cmd(struct wmi *wmi, u8 if_idx, u32 id, u32 freq, @@ -3800,6 +3926,7 @@ void *ath6kl_wmi_init(struct ath6kl *dev) return NULL; spin_lock_init(&wmi->lock); + mutex_init(&wmi->lock_mgmt); wmi->parent_dev = dev; diff --git a/drivers/net/wireless/ath/ath6kl/wmi.h b/drivers/net/wireless/ath/ath6kl/wmi.h index a9458e2..1e6c48d 100755 --- a/drivers/net/wireless/ath/ath6kl/wmi.h +++ b/drivers/net/wireless/ath/ath6kl/wmi.h @@ -106,12 +106,15 @@ struct wmi_data_sync_bufs { #define WMM_AC_VI 2 /* video */ #define WMM_AC_VO 3 /* voice */ +#define WMI_VOICE_USER_PRIORITY 0x7 + struct wmi { u16 stream_exist_for_ac[WMM_NUM_AC]; u8 fat_pipe_exist; struct ath6kl *parent_dev; u8 pwr_mode; spinlock_t lock; + struct mutex lock_mgmt; enum htc_endpoint_id ep_id; struct sq_threshold_params sq_threshld[SIGNAL_QUALITY_METRICS_NUM_MAX]; @@ -972,7 +975,7 @@ struct wmi_bss_filter_cmd { } __packed; /* WMI_SET_PROBED_SSID_CMDID */ -#define MAX_PROBED_SSID_INDEX 9 +#define MAX_PROBED_SSIDS 16 enum wmi_ssid_flag { /* disables entry */ @@ -986,7 +989,7 @@ enum wmi_ssid_flag { }; struct wmi_probed_ssid_cmd { - /* 0 to MAX_PROBED_SSID_INDEX */ + /* 0 to MAX_PROBED_SSIDS - 1 */ u8 entry_index; /* see, enum wmi_ssid_flg */ @@ -1487,7 +1490,11 @@ enum wmi_bi_ftype { PROBEREQ_FTYPE, }; +#ifdef CONFIG_MACH_PX +#define DEF_LRSSI_SCAN_PERIOD ( 5 * 1000 ) +#else #define DEF_LRSSI_SCAN_PERIOD 5 +#endif #define DEF_LRSSI_ROAM_THRESHOLD 20 #define DEF_LRSSI_ROAM_FLOOR 60 #ifdef CONFIG_MACH_PX @@ -2308,6 +2315,17 @@ struct wmi_p2p_probe_response_cmd { u8 data[0]; } __packed; +struct wmi_set_ht_cap_cmd { + u8 band; + u8 enable; + u8 chan_width_40m_supported; + u8 short_gi_20mhz; + u8 short_gi_40mhz; + u8 intolerance_40mhz; + u8 max_ampdu_len_exp; +} __packed; + + /* Extended WMI (WMIX) * * Extended WMIX commands are encapsulated in a WMI message with @@ -2507,11 +2525,16 @@ int ath6kl_wmi_add_wow_pattern_cmd(struct wmi *wmi, u8 if_idx, int ath6kl_wmi_del_wow_pattern_cmd(struct wmi *wmi, u8 if_idx, u16 list_id, u16 filter_id); int ath6kl_wmi_set_roam_lrssi_cmd(struct wmi *wmi, u8 lrssi); +int ath6kl_wmi_set_roam_lrssi_config_cmd(struct wmi *wmi, + struct low_rssi_scan_params *params); int ath6kl_wmi_force_roam_cmd(struct wmi *wmi, const u8 *bssid); int ath6kl_wmi_set_roam_mode_cmd(struct wmi *wmi, enum wmi_roam_mode mode); int ath6kl_wmi_mcast_filter_cmd(struct wmi *wmi, u8 if_idx, bool mc_all_on); int ath6kl_wmi_add_del_mcast_filter_cmd(struct wmi *wmi, u8 if_idx, u8 *filter, bool add_filter); +int ath6kl_wmi_set_ht_cap_cmd(struct wmi *wmi, u8 if_idx, + struct wmi_set_ht_cap_cmd *params); + /* AP mode uAPSD */ int ath6kl_wmi_ap_set_apsd(struct wmi *wmi, u8 if_idx, u8 enable); diff --git a/drivers/net/wireless/ath/debug.c b/drivers/net/wireless/ath/debug.c index 508eccf..508eccf 100644..100755 --- a/drivers/net/wireless/ath/debug.c +++ b/drivers/net/wireless/ath/debug.c diff --git a/drivers/net/wireless/ath/hw.c b/drivers/net/wireless/ath/hw.c index 19befb3..19befb3 100644..100755 --- a/drivers/net/wireless/ath/hw.c +++ b/drivers/net/wireless/ath/hw.c diff --git a/drivers/net/wireless/ath/key.c b/drivers/net/wireless/ath/key.c index 4cf7c5e..4cf7c5e 100644..100755 --- a/drivers/net/wireless/ath/key.c +++ b/drivers/net/wireless/ath/key.c diff --git a/drivers/net/wireless/ath/main.c b/drivers/net/wireless/ath/main.c index 947ef45..947ef45 100644..100755 --- a/drivers/net/wireless/ath/main.c +++ b/drivers/net/wireless/ath/main.c diff --git a/drivers/net/wireless/ath/regd.c b/drivers/net/wireless/ath/regd.c index 65ecb5b..65ecb5b 100644..100755 --- a/drivers/net/wireless/ath/regd.c +++ b/drivers/net/wireless/ath/regd.c diff --git a/drivers/net/wireless/ath/regd.h b/drivers/net/wireless/ath/regd.h index 03a8268..03a8268 100644..100755 --- a/drivers/net/wireless/ath/regd.h +++ b/drivers/net/wireless/ath/regd.h diff --git a/drivers/net/wireless/ath/regd_common.h b/drivers/net/wireless/ath/regd_common.h index bdd2b4d..bdd2b4d 100644..100755 --- a/drivers/net/wireless/ath/regd_common.h +++ b/drivers/net/wireless/ath/regd_common.h |