From 45c302c9b9d88f1668be095aa32b10a10cd9cc06 Mon Sep 17 00:00:00 2001 From: Ilan Peer Date: Thu, 10 May 2012 15:53:14 +0300 Subject: [PATCH] --- yaml --- r: 314209 b: refs/heads/master c: e19ebcab01cc130fa832764d453b263460ec3b91 h: refs/heads/master i: 314207: 1c570963dd9c809214ffe34e84f116cb8735bda8 v: v3 --- [refs] | 2 +- trunk/MAINTAINERS | 18 +- trunk/drivers/bcma/driver_chipcommon_pmu.c | 4 +- trunk/drivers/bcma/sprom.c | 4 +- trunk/drivers/net/wireless/ath/ath9k/Makefile | 4 +- trunk/drivers/net/wireless/ath/ath9k/ahb.c | 2 +- .../drivers/net/wireless/ath/ath9k/antenna.c | 776 --------- .../net/wireless/ath/ath9k/ar9003_calib.c | 20 +- .../net/wireless/ath/ath9k/ar9003_eeprom.c | 1 - .../net/wireless/ath/ath9k/ar9003_mci.c | 457 +++-- .../net/wireless/ath/ath9k/ar9003_mci.h | 10 +- .../net/wireless/ath/ath9k/ar9003_phy.c | 4 - .../net/wireless/ath/ath9k/ar9003_phy.h | 32 +- .../wireless/ath/ath9k/ar9462_2p0_initvals.h | 4 +- trunk/drivers/net/wireless/ath/ath9k/ath9k.h | 49 +- trunk/drivers/net/wireless/ath/ath9k/beacon.c | 23 +- trunk/drivers/net/wireless/ath/ath9k/btcoex.c | 10 +- trunk/drivers/net/wireless/ath/ath9k/btcoex.h | 4 - trunk/drivers/net/wireless/ath/ath9k/debug.c | 9 +- trunk/drivers/net/wireless/ath/ath9k/debug.h | 1 - trunk/drivers/net/wireless/ath/ath9k/gpio.c | 36 +- trunk/drivers/net/wireless/ath/ath9k/hw.c | 212 ++- trunk/drivers/net/wireless/ath/ath9k/hw.h | 10 +- trunk/drivers/net/wireless/ath/ath9k/init.c | 18 +- trunk/drivers/net/wireless/ath/ath9k/link.c | 502 ------ trunk/drivers/net/wireless/ath/ath9k/main.c | 558 ++++++- trunk/drivers/net/wireless/ath/ath9k/mci.c | 65 +- trunk/drivers/net/wireless/ath/ath9k/mci.h | 11 +- trunk/drivers/net/wireless/ath/ath9k/pci.c | 7 +- trunk/drivers/net/wireless/ath/ath9k/recv.c | 768 ++++++++- trunk/drivers/net/wireless/ath/ath9k/reg.h | 2 - trunk/drivers/net/wireless/ath/ath9k/xmit.c | 51 +- trunk/drivers/net/wireless/b43legacy/main.c | 2 +- .../net/wireless/brcm80211/brcmfmac/bcmsdh.c | 4 +- .../net/wireless/brcm80211/brcmsmac/aiutils.c | 3 +- .../net/wireless/brcm80211/brcmsmac/aiutils.h | 2 +- .../drivers/net/wireless/iwlegacy/4965-mac.c | 13 +- .../net/wireless/iwlwifi/iwl-agn-lib.c | 5 + trunk/drivers/net/wireless/iwlwifi/iwl-drv.c | 10 +- .../drivers/net/wireless/iwlwifi/iwl-eeprom.c | 18 +- .../net/wireless/iwlwifi/iwl-mac80211.c | 3 - trunk/drivers/net/wireless/libertas/cfg.c | 39 +- trunk/drivers/net/wireless/libertas/dev.h | 1 - trunk/drivers/net/wireless/libertas/mesh.c | 7 +- trunk/drivers/net/wireless/mac80211_hwsim.c | 21 - trunk/drivers/net/wireless/orinoco/cfg.c | 9 +- trunk/drivers/net/wireless/rt2x00/rt2800.h | 6 - trunk/drivers/net/wireless/rt2x00/rt2800lib.c | 22 +- trunk/drivers/net/wireless/rt2x00/rt2x00.h | 3 +- trunk/drivers/net/wireless/rt2x00/rt2x00dev.c | 2 - trunk/drivers/net/wireless/rt2x00/rt2x00mac.c | 15 +- .../drivers/net/wireless/rt2x00/rt2x00queue.c | 13 +- trunk/drivers/net/wireless/ti/Kconfig | 1 - trunk/drivers/net/wireless/ti/Makefile | 1 - trunk/drivers/net/wireless/ti/wl12xx/Makefile | 2 +- trunk/drivers/net/wireless/ti/wl12xx/acx.h | 237 --- trunk/drivers/net/wireless/ti/wl12xx/cmd.c | 8 +- .../drivers/net/wireless/ti/wl12xx/debugfs.c | 243 --- .../drivers/net/wireless/ti/wl12xx/debugfs.h | 28 - trunk/drivers/net/wireless/ti/wl12xx/main.c | 242 +-- trunk/drivers/net/wireless/ti/wl12xx/wl12xx.h | 8 - trunk/drivers/net/wireless/ti/wl18xx/Kconfig | 7 - trunk/drivers/net/wireless/ti/wl18xx/Makefile | 3 - trunk/drivers/net/wireless/ti/wl18xx/acx.c | 111 -- trunk/drivers/net/wireless/ti/wl18xx/acx.h | 291 ---- trunk/drivers/net/wireless/ti/wl18xx/conf.h | 92 -- .../drivers/net/wireless/ti/wl18xx/debugfs.c | 403 ----- .../drivers/net/wireless/ti/wl18xx/debugfs.h | 28 - trunk/drivers/net/wireless/ti/wl18xx/io.c | 60 - trunk/drivers/net/wireless/ti/wl18xx/io.h | 28 - trunk/drivers/net/wireless/ti/wl18xx/main.c | 1463 ----------------- trunk/drivers/net/wireless/ti/wl18xx/reg.h | 191 --- trunk/drivers/net/wireless/ti/wl18xx/tx.c | 127 -- trunk/drivers/net/wireless/ti/wl18xx/tx.h | 46 - trunk/drivers/net/wireless/ti/wl18xx/wl18xx.h | 88 - trunk/drivers/net/wireless/ti/wlcore/acx.c | 8 +- trunk/drivers/net/wireless/ti/wlcore/acx.h | 254 ++- trunk/drivers/net/wireless/ti/wlcore/boot.c | 57 +- trunk/drivers/net/wireless/ti/wlcore/boot.h | 1 - trunk/drivers/net/wireless/ti/wlcore/cmd.c | 62 +- trunk/drivers/net/wireless/ti/wlcore/cmd.h | 13 +- trunk/drivers/net/wireless/ti/wlcore/conf.h | 93 +- .../drivers/net/wireless/ti/wlcore/debugfs.c | 390 +++-- .../drivers/net/wireless/ti/wlcore/debugfs.h | 87 - trunk/drivers/net/wireless/ti/wlcore/event.c | 24 +- trunk/drivers/net/wireless/ti/wlcore/hw_ops.h | 78 - trunk/drivers/net/wireless/ti/wlcore/init.c | 3 - trunk/drivers/net/wireless/ti/wlcore/main.c | 504 +++--- trunk/drivers/net/wireless/ti/wlcore/ps.c | 21 +- trunk/drivers/net/wireless/ti/wlcore/rx.c | 11 +- trunk/drivers/net/wireless/ti/wlcore/rx.h | 7 +- trunk/drivers/net/wireless/ti/wlcore/scan.c | 52 +- trunk/drivers/net/wireless/ti/wlcore/scan.h | 19 +- trunk/drivers/net/wireless/ti/wlcore/sdio.c | 35 +- trunk/drivers/net/wireless/ti/wlcore/tx.c | 185 +-- trunk/drivers/net/wireless/ti/wlcore/tx.h | 49 +- .../ti/wlcore/{wlcore_i.h => wl12xx.h} | 44 +- trunk/drivers/net/wireless/ti/wlcore/wlcore.h | 70 +- trunk/drivers/nfc/pn533.c | 662 ++------ trunk/drivers/nfc/pn544_hci.c | 10 +- trunk/drivers/ssb/scan.c | 2 - trunk/include/linux/nfc.h | 12 - trunk/include/linux/nl80211.h | 2 - trunk/include/linux/ssb/ssb.h | 1 - trunk/include/net/cfg80211.h | 24 +- trunk/include/net/mac80211.h | 5 +- trunk/include/net/nfc/hci.h | 3 +- trunk/include/net/nfc/nfc.h | 14 +- trunk/include/net/nfc/shdlc.h | 3 +- trunk/net/bluetooth/af_bluetooth.c | 2 +- trunk/net/mac80211/Makefile | 1 + trunk/net/mac80211/agg-rx.c | 7 +- trunk/net/mac80211/cfg.c | 490 +++--- trunk/net/mac80211/debugfs_netdev.c | 1 - trunk/net/mac80211/ieee80211_i.h | 89 +- trunk/net/mac80211/iface.c | 24 +- trunk/net/mac80211/main.c | 10 +- trunk/net/mac80211/mlme.c | 55 +- trunk/net/mac80211/offchannel.c | 272 +-- trunk/net/mac80211/pm.c | 1 - trunk/net/mac80211/scan.c | 4 +- trunk/net/mac80211/sta_info.c | 4 +- trunk/net/mac80211/status.c | 28 +- trunk/net/mac80211/tx.c | 9 +- trunk/net/mac80211/util.c | 117 +- trunk/net/mac80211/work.c | 370 +++++ trunk/net/nfc/core.c | 119 +- trunk/net/nfc/hci/core.c | 13 +- trunk/net/nfc/hci/shdlc.c | 6 +- trunk/net/nfc/llcp/commands.c | 54 +- trunk/net/nfc/llcp/llcp.c | 421 ++--- trunk/net/nfc/llcp/llcp.h | 26 +- trunk/net/nfc/llcp/sock.c | 47 +- trunk/net/nfc/nci/core.c | 15 +- trunk/net/nfc/netlink.c | 81 +- trunk/net/nfc/nfc.h | 12 +- trunk/net/rfkill/core.c | 2 +- trunk/net/wireless/chan.c | 43 +- trunk/net/wireless/core.h | 5 +- trunk/net/wireless/ibss.c | 6 +- trunk/net/wireless/mesh.c | 26 +- trunk/net/wireless/mlme.c | 2 + trunk/net/wireless/nl80211.c | 44 +- trunk/net/wireless/util.c | 19 +- trunk/net/wireless/wext-compat.c | 10 +- trunk/net/wireless/wext-sme.c | 10 +- 146 files changed, 4056 insertions(+), 8774 deletions(-) delete mode 100644 trunk/drivers/net/wireless/ath/ath9k/antenna.c delete mode 100644 trunk/drivers/net/wireless/ath/ath9k/link.c delete mode 100644 trunk/drivers/net/wireless/ti/wl12xx/debugfs.c delete mode 100644 trunk/drivers/net/wireless/ti/wl12xx/debugfs.h delete mode 100644 trunk/drivers/net/wireless/ti/wl18xx/Kconfig delete mode 100644 trunk/drivers/net/wireless/ti/wl18xx/Makefile delete mode 100644 trunk/drivers/net/wireless/ti/wl18xx/acx.c delete mode 100644 trunk/drivers/net/wireless/ti/wl18xx/acx.h delete mode 100644 trunk/drivers/net/wireless/ti/wl18xx/conf.h delete mode 100644 trunk/drivers/net/wireless/ti/wl18xx/debugfs.c delete mode 100644 trunk/drivers/net/wireless/ti/wl18xx/debugfs.h delete mode 100644 trunk/drivers/net/wireless/ti/wl18xx/io.c delete mode 100644 trunk/drivers/net/wireless/ti/wl18xx/io.h delete mode 100644 trunk/drivers/net/wireless/ti/wl18xx/main.c delete mode 100644 trunk/drivers/net/wireless/ti/wl18xx/reg.h delete mode 100644 trunk/drivers/net/wireless/ti/wl18xx/tx.c delete mode 100644 trunk/drivers/net/wireless/ti/wl18xx/tx.h delete mode 100644 trunk/drivers/net/wireless/ti/wl18xx/wl18xx.h rename trunk/drivers/net/wireless/ti/wlcore/{wlcore_i.h => wl12xx.h} (95%) create mode 100644 trunk/net/mac80211/work.c diff --git a/[refs] b/[refs] index a453f399d84a..b72c919aae23 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: 2e48686835370dfe78697839ca293d250793809d +refs/heads/master: e19ebcab01cc130fa832764d453b263460ec3b91 diff --git a/trunk/MAINTAINERS b/trunk/MAINTAINERS index c5fd905206e7..55f0fda602ec 100644 --- a/trunk/MAINTAINERS +++ b/trunk/MAINTAINERS @@ -329,7 +329,7 @@ F: drivers/hwmon/adm1029.c ADM8211 WIRELESS DRIVER L: linux-wireless@vger.kernel.org -W: http://wireless.kernel.org/ +W: http://linuxwireless.org/ S: Orphan F: drivers/net/wireless/adm8211.* @@ -1423,7 +1423,7 @@ B43 WIRELESS DRIVER M: Stefano Brivio L: linux-wireless@vger.kernel.org L: b43-dev@lists.infradead.org -W: http://wireless.kernel.org/en/users/Drivers/b43 +W: http://linuxwireless.org/en/users/Drivers/b43 S: Maintained F: drivers/net/wireless/b43/ @@ -1432,7 +1432,7 @@ M: Larry Finger M: Stefano Brivio L: linux-wireless@vger.kernel.org L: b43-dev@lists.infradead.org -W: http://wireless.kernel.org/en/users/Drivers/b43 +W: http://linuxwireless.org/en/users/Drivers/b43 S: Maintained F: drivers/net/wireless/b43legacy/ @@ -4339,7 +4339,7 @@ F: arch/m68k/hp300/ MAC80211 M: Johannes Berg L: linux-wireless@vger.kernel.org -W: http://wireless.kernel.org/ +W: http://linuxwireless.org/ T: git git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless.git S: Maintained F: Documentation/networking/mac80211-injection.txt @@ -4350,7 +4350,7 @@ MAC80211 PID RATE CONTROL M: Stefano Brivio M: Mattias Nissler L: linux-wireless@vger.kernel.org -W: http://wireless.kernel.org/en/developers/Documentation/mac80211/RateControl/PID +W: http://linuxwireless.org/en/developers/Documentation/mac80211/RateControl/PID T: git git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless.git S: Maintained F: net/mac80211/rc80211_pid* @@ -5027,7 +5027,7 @@ F: fs/ocfs2/ ORINOCO DRIVER L: linux-wireless@vger.kernel.org -W: http://wireless.kernel.org/en/users/Drivers/orinoco +W: http://linuxwireless.org/en/users/Drivers/orinoco W: http://www.nongnu.org/orinoco/ S: Orphan F: drivers/net/wireless/orinoco/ @@ -5729,7 +5729,7 @@ F: net/rose/ RTL8180 WIRELESS DRIVER M: "John W. Linville" L: linux-wireless@vger.kernel.org -W: http://wireless.kernel.org/ +W: http://linuxwireless.org/ T: git git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-testing.git S: Maintained F: drivers/net/wireless/rtl818x/rtl8180/ @@ -5739,7 +5739,7 @@ M: Herton Ronaldo Krzesinski M: Hin-Tak Leung M: Larry Finger L: linux-wireless@vger.kernel.org -W: http://wireless.kernel.org/ +W: http://linuxwireless.org/ T: git git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-testing.git S: Maintained F: drivers/net/wireless/rtl818x/rtl8187/ @@ -5748,7 +5748,7 @@ RTL8192CE WIRELESS DRIVER M: Larry Finger M: Chaoming Li L: linux-wireless@vger.kernel.org -W: http://wireless.kernel.org/ +W: http://linuxwireless.org/ T: git git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-testing.git S: Maintained F: drivers/net/wireless/rtlwifi/ diff --git a/trunk/drivers/bcma/driver_chipcommon_pmu.c b/trunk/drivers/bcma/driver_chipcommon_pmu.c index 61ce4054b3c3..a058842f14fd 100644 --- a/trunk/drivers/bcma/driver_chipcommon_pmu.c +++ b/trunk/drivers/bcma/driver_chipcommon_pmu.c @@ -139,9 +139,7 @@ void bcma_pmu_workarounds(struct bcma_drv_cc *cc) bcma_chipco_chipctl_maskset(cc, 0, ~0, 0x7); break; case 0x4331: - case 43431: - /* Ext PA lines must be enabled for tx on BCM4331 */ - bcma_chipco_bcm4331_ext_pa_lines_ctl(cc, true); + /* BCM4331 workaround is SPROM-related, we put it in sprom.c */ break; case 43224: if (bus->chipinfo.rev == 0) { diff --git a/trunk/drivers/bcma/sprom.c b/trunk/drivers/bcma/sprom.c index f16f42d36071..c7f93359acb0 100644 --- a/trunk/drivers/bcma/sprom.c +++ b/trunk/drivers/bcma/sprom.c @@ -579,13 +579,13 @@ int bcma_sprom_get(struct bcma_bus *bus) if (!sprom) return -ENOMEM; - if (bus->chipinfo.id == 0x4331 || bus->chipinfo.id == 43431) + if (bus->chipinfo.id == 0x4331) bcma_chipco_bcm4331_ext_pa_lines_ctl(&bus->drv_cc, false); pr_debug("SPROM offset 0x%x\n", offset); bcma_sprom_read(bus, offset, sprom); - if (bus->chipinfo.id == 0x4331 || bus->chipinfo.id == 43431) + if (bus->chipinfo.id == 0x4331) bcma_chipco_bcm4331_ext_pa_lines_ctl(&bus->drv_cc, true); err = bcma_sprom_valid(sprom); diff --git a/trunk/drivers/net/wireless/ath/ath9k/Makefile b/trunk/drivers/net/wireless/ath/ath9k/Makefile index 9c41232b0cd0..3f0b84723789 100644 --- a/trunk/drivers/net/wireless/ath/ath9k/Makefile +++ b/trunk/drivers/net/wireless/ath/ath9k/Makefile @@ -3,9 +3,7 @@ ath9k-y += beacon.o \ init.o \ main.o \ recv.o \ - xmit.o \ - link.o \ - antenna.o + xmit.o ath9k-$(CONFIG_ATH9K_BTCOEX_SUPPORT) += mci.o ath9k-$(CONFIG_ATH9K_RATE_CONTROL) += rc.o diff --git a/trunk/drivers/net/wireless/ath/ath9k/ahb.c b/trunk/drivers/net/wireless/ath/ath9k/ahb.c index 4a4e8a2b9d2c..5e47ca6d16a8 100644 --- a/trunk/drivers/net/wireless/ath/ath9k/ahb.c +++ b/trunk/drivers/net/wireless/ath/ath9k/ahb.c @@ -126,7 +126,7 @@ static int ath_ahb_probe(struct platform_device *pdev) sc->irq = irq; /* Will be cleared in ath9k_start() */ - set_bit(SC_OP_INVALID, &sc->sc_flags); + sc->sc_flags |= SC_OP_INVALID; ret = request_irq(irq, ath_isr, IRQF_SHARED, "ath9k", sc); if (ret) { diff --git a/trunk/drivers/net/wireless/ath/ath9k/antenna.c b/trunk/drivers/net/wireless/ath/ath9k/antenna.c deleted file mode 100644 index bbcfeb3b2a60..000000000000 --- a/trunk/drivers/net/wireless/ath/ath9k/antenna.c +++ /dev/null @@ -1,776 +0,0 @@ -/* - * Copyright (c) 2012 Qualcomm Atheros, Inc. - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#include "ath9k.h" - -static inline bool ath_is_alt_ant_ratio_better(int alt_ratio, int maxdelta, - int mindelta, int main_rssi_avg, - int alt_rssi_avg, int pkt_count) -{ - return (((alt_ratio >= ATH_ANT_DIV_COMB_ALT_ANT_RATIO2) && - (alt_rssi_avg > main_rssi_avg + maxdelta)) || - (alt_rssi_avg > main_rssi_avg + mindelta)) && (pkt_count > 50); -} - -static inline bool ath_ant_div_comb_alt_check(u8 div_group, int alt_ratio, - int curr_main_set, int curr_alt_set, - int alt_rssi_avg, int main_rssi_avg) -{ - bool result = false; - switch (div_group) { - case 0: - if (alt_ratio > ATH_ANT_DIV_COMB_ALT_ANT_RATIO) - result = true; - break; - case 1: - case 2: - if ((((curr_main_set == ATH_ANT_DIV_COMB_LNA2) && - (curr_alt_set == ATH_ANT_DIV_COMB_LNA1) && - (alt_rssi_avg >= (main_rssi_avg - 5))) || - ((curr_main_set == ATH_ANT_DIV_COMB_LNA1) && - (curr_alt_set == ATH_ANT_DIV_COMB_LNA2) && - (alt_rssi_avg >= (main_rssi_avg - 2)))) && - (alt_rssi_avg >= 4)) - result = true; - else - result = false; - break; - } - - return result; -} - -static void ath_lnaconf_alt_good_scan(struct ath_ant_comb *antcomb, - struct ath_hw_antcomb_conf ant_conf, - int main_rssi_avg) -{ - antcomb->quick_scan_cnt = 0; - - if (ant_conf.main_lna_conf == ATH_ANT_DIV_COMB_LNA2) - antcomb->rssi_lna2 = main_rssi_avg; - else if (ant_conf.main_lna_conf == ATH_ANT_DIV_COMB_LNA1) - antcomb->rssi_lna1 = main_rssi_avg; - - switch ((ant_conf.main_lna_conf << 4) | ant_conf.alt_lna_conf) { - case 0x10: /* LNA2 A-B */ - antcomb->main_conf = ATH_ANT_DIV_COMB_LNA1_MINUS_LNA2; - antcomb->first_quick_scan_conf = - ATH_ANT_DIV_COMB_LNA1_PLUS_LNA2; - antcomb->second_quick_scan_conf = ATH_ANT_DIV_COMB_LNA1; - break; - case 0x20: /* LNA1 A-B */ - antcomb->main_conf = ATH_ANT_DIV_COMB_LNA1_MINUS_LNA2; - antcomb->first_quick_scan_conf = - ATH_ANT_DIV_COMB_LNA1_PLUS_LNA2; - antcomb->second_quick_scan_conf = ATH_ANT_DIV_COMB_LNA2; - break; - case 0x21: /* LNA1 LNA2 */ - antcomb->main_conf = ATH_ANT_DIV_COMB_LNA2; - antcomb->first_quick_scan_conf = - ATH_ANT_DIV_COMB_LNA1_MINUS_LNA2; - antcomb->second_quick_scan_conf = - ATH_ANT_DIV_COMB_LNA1_PLUS_LNA2; - break; - case 0x12: /* LNA2 LNA1 */ - antcomb->main_conf = ATH_ANT_DIV_COMB_LNA1; - antcomb->first_quick_scan_conf = - ATH_ANT_DIV_COMB_LNA1_MINUS_LNA2; - antcomb->second_quick_scan_conf = - ATH_ANT_DIV_COMB_LNA1_PLUS_LNA2; - break; - case 0x13: /* LNA2 A+B */ - antcomb->main_conf = ATH_ANT_DIV_COMB_LNA1_PLUS_LNA2; - antcomb->first_quick_scan_conf = - ATH_ANT_DIV_COMB_LNA1_MINUS_LNA2; - antcomb->second_quick_scan_conf = ATH_ANT_DIV_COMB_LNA1; - break; - case 0x23: /* LNA1 A+B */ - antcomb->main_conf = ATH_ANT_DIV_COMB_LNA1_PLUS_LNA2; - antcomb->first_quick_scan_conf = - ATH_ANT_DIV_COMB_LNA1_MINUS_LNA2; - antcomb->second_quick_scan_conf = ATH_ANT_DIV_COMB_LNA2; - break; - default: - break; - } -} - -static void ath_select_ant_div_from_quick_scan(struct ath_ant_comb *antcomb, - struct ath_hw_antcomb_conf *div_ant_conf, - int main_rssi_avg, int alt_rssi_avg, - int alt_ratio) -{ - /* alt_good */ - switch (antcomb->quick_scan_cnt) { - case 0: - /* set alt to main, and alt to first conf */ - div_ant_conf->main_lna_conf = antcomb->main_conf; - div_ant_conf->alt_lna_conf = antcomb->first_quick_scan_conf; - break; - case 1: - /* set alt to main, and alt to first conf */ - div_ant_conf->main_lna_conf = antcomb->main_conf; - div_ant_conf->alt_lna_conf = antcomb->second_quick_scan_conf; - antcomb->rssi_first = main_rssi_avg; - antcomb->rssi_second = alt_rssi_avg; - - if (antcomb->main_conf == ATH_ANT_DIV_COMB_LNA1) { - /* main is LNA1 */ - if (ath_is_alt_ant_ratio_better(alt_ratio, - ATH_ANT_DIV_COMB_LNA1_DELTA_HI, - ATH_ANT_DIV_COMB_LNA1_DELTA_LOW, - main_rssi_avg, alt_rssi_avg, - antcomb->total_pkt_count)) - antcomb->first_ratio = true; - else - antcomb->first_ratio = false; - } else if (antcomb->main_conf == ATH_ANT_DIV_COMB_LNA2) { - if (ath_is_alt_ant_ratio_better(alt_ratio, - ATH_ANT_DIV_COMB_LNA1_DELTA_MID, - ATH_ANT_DIV_COMB_LNA1_DELTA_LOW, - main_rssi_avg, alt_rssi_avg, - antcomb->total_pkt_count)) - antcomb->first_ratio = true; - else - antcomb->first_ratio = false; - } else { - if ((((alt_ratio >= ATH_ANT_DIV_COMB_ALT_ANT_RATIO2) && - (alt_rssi_avg > main_rssi_avg + - ATH_ANT_DIV_COMB_LNA1_DELTA_HI)) || - (alt_rssi_avg > main_rssi_avg)) && - (antcomb->total_pkt_count > 50)) - antcomb->first_ratio = true; - else - antcomb->first_ratio = false; - } - break; - case 2: - antcomb->alt_good = false; - antcomb->scan_not_start = false; - antcomb->scan = false; - antcomb->rssi_first = main_rssi_avg; - antcomb->rssi_third = alt_rssi_avg; - - if (antcomb->second_quick_scan_conf == ATH_ANT_DIV_COMB_LNA1) - antcomb->rssi_lna1 = alt_rssi_avg; - else if (antcomb->second_quick_scan_conf == - ATH_ANT_DIV_COMB_LNA2) - antcomb->rssi_lna2 = alt_rssi_avg; - else if (antcomb->second_quick_scan_conf == - ATH_ANT_DIV_COMB_LNA1_PLUS_LNA2) { - if (antcomb->main_conf == ATH_ANT_DIV_COMB_LNA2) - antcomb->rssi_lna2 = main_rssi_avg; - else if (antcomb->main_conf == ATH_ANT_DIV_COMB_LNA1) - antcomb->rssi_lna1 = main_rssi_avg; - } - - if (antcomb->rssi_lna2 > antcomb->rssi_lna1 + - ATH_ANT_DIV_COMB_LNA1_LNA2_SWITCH_DELTA) - div_ant_conf->main_lna_conf = ATH_ANT_DIV_COMB_LNA2; - else - div_ant_conf->main_lna_conf = ATH_ANT_DIV_COMB_LNA1; - - if (antcomb->main_conf == ATH_ANT_DIV_COMB_LNA1) { - if (ath_is_alt_ant_ratio_better(alt_ratio, - ATH_ANT_DIV_COMB_LNA1_DELTA_HI, - ATH_ANT_DIV_COMB_LNA1_DELTA_LOW, - main_rssi_avg, alt_rssi_avg, - antcomb->total_pkt_count)) - antcomb->second_ratio = true; - else - antcomb->second_ratio = false; - } else if (antcomb->main_conf == ATH_ANT_DIV_COMB_LNA2) { - if (ath_is_alt_ant_ratio_better(alt_ratio, - ATH_ANT_DIV_COMB_LNA1_DELTA_MID, - ATH_ANT_DIV_COMB_LNA1_DELTA_LOW, - main_rssi_avg, alt_rssi_avg, - antcomb->total_pkt_count)) - antcomb->second_ratio = true; - else - antcomb->second_ratio = false; - } else { - if ((((alt_ratio >= ATH_ANT_DIV_COMB_ALT_ANT_RATIO2) && - (alt_rssi_avg > main_rssi_avg + - ATH_ANT_DIV_COMB_LNA1_DELTA_HI)) || - (alt_rssi_avg > main_rssi_avg)) && - (antcomb->total_pkt_count > 50)) - antcomb->second_ratio = true; - else - antcomb->second_ratio = false; - } - - /* set alt to the conf with maximun ratio */ - if (antcomb->first_ratio && antcomb->second_ratio) { - if (antcomb->rssi_second > antcomb->rssi_third) { - /* first alt*/ - if ((antcomb->first_quick_scan_conf == - ATH_ANT_DIV_COMB_LNA1) || - (antcomb->first_quick_scan_conf == - ATH_ANT_DIV_COMB_LNA2)) - /* Set alt LNA1 or LNA2*/ - if (div_ant_conf->main_lna_conf == - ATH_ANT_DIV_COMB_LNA2) - div_ant_conf->alt_lna_conf = - ATH_ANT_DIV_COMB_LNA1; - else - div_ant_conf->alt_lna_conf = - ATH_ANT_DIV_COMB_LNA2; - else - /* Set alt to A+B or A-B */ - div_ant_conf->alt_lna_conf = - antcomb->first_quick_scan_conf; - } else if ((antcomb->second_quick_scan_conf == - ATH_ANT_DIV_COMB_LNA1) || - (antcomb->second_quick_scan_conf == - ATH_ANT_DIV_COMB_LNA2)) { - /* Set alt LNA1 or LNA2 */ - if (div_ant_conf->main_lna_conf == - ATH_ANT_DIV_COMB_LNA2) - div_ant_conf->alt_lna_conf = - ATH_ANT_DIV_COMB_LNA1; - else - div_ant_conf->alt_lna_conf = - ATH_ANT_DIV_COMB_LNA2; - } else { - /* Set alt to A+B or A-B */ - div_ant_conf->alt_lna_conf = - antcomb->second_quick_scan_conf; - } - } else if (antcomb->first_ratio) { - /* first alt */ - if ((antcomb->first_quick_scan_conf == - ATH_ANT_DIV_COMB_LNA1) || - (antcomb->first_quick_scan_conf == - ATH_ANT_DIV_COMB_LNA2)) - /* Set alt LNA1 or LNA2 */ - if (div_ant_conf->main_lna_conf == - ATH_ANT_DIV_COMB_LNA2) - div_ant_conf->alt_lna_conf = - ATH_ANT_DIV_COMB_LNA1; - else - div_ant_conf->alt_lna_conf = - ATH_ANT_DIV_COMB_LNA2; - else - /* Set alt to A+B or A-B */ - div_ant_conf->alt_lna_conf = - antcomb->first_quick_scan_conf; - } else if (antcomb->second_ratio) { - /* second alt */ - if ((antcomb->second_quick_scan_conf == - ATH_ANT_DIV_COMB_LNA1) || - (antcomb->second_quick_scan_conf == - ATH_ANT_DIV_COMB_LNA2)) - /* Set alt LNA1 or LNA2 */ - if (div_ant_conf->main_lna_conf == - ATH_ANT_DIV_COMB_LNA2) - div_ant_conf->alt_lna_conf = - ATH_ANT_DIV_COMB_LNA1; - else - div_ant_conf->alt_lna_conf = - ATH_ANT_DIV_COMB_LNA2; - else - /* Set alt to A+B or A-B */ - div_ant_conf->alt_lna_conf = - antcomb->second_quick_scan_conf; - } else { - /* main is largest */ - if ((antcomb->main_conf == ATH_ANT_DIV_COMB_LNA1) || - (antcomb->main_conf == ATH_ANT_DIV_COMB_LNA2)) - /* Set alt LNA1 or LNA2 */ - if (div_ant_conf->main_lna_conf == - ATH_ANT_DIV_COMB_LNA2) - div_ant_conf->alt_lna_conf = - ATH_ANT_DIV_COMB_LNA1; - else - div_ant_conf->alt_lna_conf = - ATH_ANT_DIV_COMB_LNA2; - else - /* Set alt to A+B or A-B */ - div_ant_conf->alt_lna_conf = antcomb->main_conf; - } - break; - default: - break; - } -} - -static void ath_ant_div_conf_fast_divbias(struct ath_hw_antcomb_conf *ant_conf, - struct ath_ant_comb *antcomb, - int alt_ratio) -{ - if (ant_conf->div_group == 0) { - /* Adjust the fast_div_bias based on main and alt lna conf */ - switch ((ant_conf->main_lna_conf << 4) | - ant_conf->alt_lna_conf) { - case 0x01: /* A-B LNA2 */ - ant_conf->fast_div_bias = 0x3b; - break; - case 0x02: /* A-B LNA1 */ - ant_conf->fast_div_bias = 0x3d; - break; - case 0x03: /* A-B A+B */ - ant_conf->fast_div_bias = 0x1; - break; - case 0x10: /* LNA2 A-B */ - ant_conf->fast_div_bias = 0x7; - break; - case 0x12: /* LNA2 LNA1 */ - ant_conf->fast_div_bias = 0x2; - break; - case 0x13: /* LNA2 A+B */ - ant_conf->fast_div_bias = 0x7; - break; - case 0x20: /* LNA1 A-B */ - ant_conf->fast_div_bias = 0x6; - break; - case 0x21: /* LNA1 LNA2 */ - ant_conf->fast_div_bias = 0x0; - break; - case 0x23: /* LNA1 A+B */ - ant_conf->fast_div_bias = 0x6; - break; - case 0x30: /* A+B A-B */ - ant_conf->fast_div_bias = 0x1; - break; - case 0x31: /* A+B LNA2 */ - ant_conf->fast_div_bias = 0x3b; - break; - case 0x32: /* A+B LNA1 */ - ant_conf->fast_div_bias = 0x3d; - break; - default: - break; - } - } else if (ant_conf->div_group == 1) { - /* Adjust the fast_div_bias based on main and alt_lna_conf */ - switch ((ant_conf->main_lna_conf << 4) | - ant_conf->alt_lna_conf) { - case 0x01: /* A-B LNA2 */ - ant_conf->fast_div_bias = 0x1; - ant_conf->main_gaintb = 0; - ant_conf->alt_gaintb = 0; - break; - case 0x02: /* A-B LNA1 */ - ant_conf->fast_div_bias = 0x1; - ant_conf->main_gaintb = 0; - ant_conf->alt_gaintb = 0; - break; - case 0x03: /* A-B A+B */ - ant_conf->fast_div_bias = 0x1; - ant_conf->main_gaintb = 0; - ant_conf->alt_gaintb = 0; - break; - case 0x10: /* LNA2 A-B */ - if (!(antcomb->scan) && - (alt_ratio > ATH_ANT_DIV_COMB_ALT_ANT_RATIO)) - ant_conf->fast_div_bias = 0x3f; - else - ant_conf->fast_div_bias = 0x1; - ant_conf->main_gaintb = 0; - ant_conf->alt_gaintb = 0; - break; - case 0x12: /* LNA2 LNA1 */ - ant_conf->fast_div_bias = 0x1; - ant_conf->main_gaintb = 0; - ant_conf->alt_gaintb = 0; - break; - case 0x13: /* LNA2 A+B */ - if (!(antcomb->scan) && - (alt_ratio > ATH_ANT_DIV_COMB_ALT_ANT_RATIO)) - ant_conf->fast_div_bias = 0x3f; - else - ant_conf->fast_div_bias = 0x1; - ant_conf->main_gaintb = 0; - ant_conf->alt_gaintb = 0; - break; - case 0x20: /* LNA1 A-B */ - if (!(antcomb->scan) && - (alt_ratio > ATH_ANT_DIV_COMB_ALT_ANT_RATIO)) - ant_conf->fast_div_bias = 0x3f; - else - ant_conf->fast_div_bias = 0x1; - ant_conf->main_gaintb = 0; - ant_conf->alt_gaintb = 0; - break; - case 0x21: /* LNA1 LNA2 */ - ant_conf->fast_div_bias = 0x1; - ant_conf->main_gaintb = 0; - ant_conf->alt_gaintb = 0; - break; - case 0x23: /* LNA1 A+B */ - if (!(antcomb->scan) && - (alt_ratio > ATH_ANT_DIV_COMB_ALT_ANT_RATIO)) - ant_conf->fast_div_bias = 0x3f; - else - ant_conf->fast_div_bias = 0x1; - ant_conf->main_gaintb = 0; - ant_conf->alt_gaintb = 0; - break; - case 0x30: /* A+B A-B */ - ant_conf->fast_div_bias = 0x1; - ant_conf->main_gaintb = 0; - ant_conf->alt_gaintb = 0; - break; - case 0x31: /* A+B LNA2 */ - ant_conf->fast_div_bias = 0x1; - ant_conf->main_gaintb = 0; - ant_conf->alt_gaintb = 0; - break; - case 0x32: /* A+B LNA1 */ - ant_conf->fast_div_bias = 0x1; - ant_conf->main_gaintb = 0; - ant_conf->alt_gaintb = 0; - break; - default: - break; - } - } else if (ant_conf->div_group == 2) { - /* Adjust the fast_div_bias based on main and alt_lna_conf */ - switch ((ant_conf->main_lna_conf << 4) | - ant_conf->alt_lna_conf) { - case 0x01: /* A-B LNA2 */ - ant_conf->fast_div_bias = 0x1; - ant_conf->main_gaintb = 0; - ant_conf->alt_gaintb = 0; - break; - case 0x02: /* A-B LNA1 */ - ant_conf->fast_div_bias = 0x1; - ant_conf->main_gaintb = 0; - ant_conf->alt_gaintb = 0; - break; - case 0x03: /* A-B A+B */ - ant_conf->fast_div_bias = 0x1; - ant_conf->main_gaintb = 0; - ant_conf->alt_gaintb = 0; - break; - case 0x10: /* LNA2 A-B */ - if (!(antcomb->scan) && - (alt_ratio > ATH_ANT_DIV_COMB_ALT_ANT_RATIO)) - ant_conf->fast_div_bias = 0x1; - else - ant_conf->fast_div_bias = 0x2; - ant_conf->main_gaintb = 0; - ant_conf->alt_gaintb = 0; - break; - case 0x12: /* LNA2 LNA1 */ - ant_conf->fast_div_bias = 0x1; - ant_conf->main_gaintb = 0; - ant_conf->alt_gaintb = 0; - break; - case 0x13: /* LNA2 A+B */ - if (!(antcomb->scan) && - (alt_ratio > ATH_ANT_DIV_COMB_ALT_ANT_RATIO)) - ant_conf->fast_div_bias = 0x1; - else - ant_conf->fast_div_bias = 0x2; - ant_conf->main_gaintb = 0; - ant_conf->alt_gaintb = 0; - break; - case 0x20: /* LNA1 A-B */ - if (!(antcomb->scan) && - (alt_ratio > ATH_ANT_DIV_COMB_ALT_ANT_RATIO)) - ant_conf->fast_div_bias = 0x1; - else - ant_conf->fast_div_bias = 0x2; - ant_conf->main_gaintb = 0; - ant_conf->alt_gaintb = 0; - break; - case 0x21: /* LNA1 LNA2 */ - ant_conf->fast_div_bias = 0x1; - ant_conf->main_gaintb = 0; - ant_conf->alt_gaintb = 0; - break; - case 0x23: /* LNA1 A+B */ - if (!(antcomb->scan) && - (alt_ratio > ATH_ANT_DIV_COMB_ALT_ANT_RATIO)) - ant_conf->fast_div_bias = 0x1; - else - ant_conf->fast_div_bias = 0x2; - ant_conf->main_gaintb = 0; - ant_conf->alt_gaintb = 0; - break; - case 0x30: /* A+B A-B */ - ant_conf->fast_div_bias = 0x1; - ant_conf->main_gaintb = 0; - ant_conf->alt_gaintb = 0; - break; - case 0x31: /* A+B LNA2 */ - ant_conf->fast_div_bias = 0x1; - ant_conf->main_gaintb = 0; - ant_conf->alt_gaintb = 0; - break; - case 0x32: /* A+B LNA1 */ - ant_conf->fast_div_bias = 0x1; - ant_conf->main_gaintb = 0; - ant_conf->alt_gaintb = 0; - break; - default: - break; - } - } -} - -void ath_ant_comb_scan(struct ath_softc *sc, struct ath_rx_status *rs) -{ - struct ath_hw_antcomb_conf div_ant_conf; - struct ath_ant_comb *antcomb = &sc->ant_comb; - int alt_ratio = 0, alt_rssi_avg = 0, main_rssi_avg = 0, curr_alt_set; - int curr_main_set; - int main_rssi = rs->rs_rssi_ctl0; - int alt_rssi = rs->rs_rssi_ctl1; - int rx_ant_conf, main_ant_conf; - bool short_scan = false; - - rx_ant_conf = (rs->rs_rssi_ctl2 >> ATH_ANT_RX_CURRENT_SHIFT) & - ATH_ANT_RX_MASK; - main_ant_conf = (rs->rs_rssi_ctl2 >> ATH_ANT_RX_MAIN_SHIFT) & - ATH_ANT_RX_MASK; - - /* Record packet only when both main_rssi and alt_rssi is positive */ - if (main_rssi > 0 && alt_rssi > 0) { - antcomb->total_pkt_count++; - antcomb->main_total_rssi += main_rssi; - antcomb->alt_total_rssi += alt_rssi; - if (main_ant_conf == rx_ant_conf) - antcomb->main_recv_cnt++; - else - antcomb->alt_recv_cnt++; - } - - /* Short scan check */ - if (antcomb->scan && antcomb->alt_good) { - if (time_after(jiffies, antcomb->scan_start_time + - msecs_to_jiffies(ATH_ANT_DIV_COMB_SHORT_SCAN_INTR))) - short_scan = true; - else - if (antcomb->total_pkt_count == - ATH_ANT_DIV_COMB_SHORT_SCAN_PKTCOUNT) { - alt_ratio = ((antcomb->alt_recv_cnt * 100) / - antcomb->total_pkt_count); - if (alt_ratio < ATH_ANT_DIV_COMB_ALT_ANT_RATIO) - short_scan = true; - } - } - - if (((antcomb->total_pkt_count < ATH_ANT_DIV_COMB_MAX_PKTCOUNT) || - rs->rs_moreaggr) && !short_scan) - return; - - if (antcomb->total_pkt_count) { - alt_ratio = ((antcomb->alt_recv_cnt * 100) / - antcomb->total_pkt_count); - main_rssi_avg = (antcomb->main_total_rssi / - antcomb->total_pkt_count); - alt_rssi_avg = (antcomb->alt_total_rssi / - antcomb->total_pkt_count); - } - - - ath9k_hw_antdiv_comb_conf_get(sc->sc_ah, &div_ant_conf); - curr_alt_set = div_ant_conf.alt_lna_conf; - curr_main_set = div_ant_conf.main_lna_conf; - - antcomb->count++; - - if (antcomb->count == ATH_ANT_DIV_COMB_MAX_COUNT) { - if (alt_ratio > ATH_ANT_DIV_COMB_ALT_ANT_RATIO) { - ath_lnaconf_alt_good_scan(antcomb, div_ant_conf, - main_rssi_avg); - antcomb->alt_good = true; - } else { - antcomb->alt_good = false; - } - - antcomb->count = 0; - antcomb->scan = true; - antcomb->scan_not_start = true; - } - - if (!antcomb->scan) { - if (ath_ant_div_comb_alt_check(div_ant_conf.div_group, - alt_ratio, curr_main_set, curr_alt_set, - alt_rssi_avg, main_rssi_avg)) { - if (curr_alt_set == ATH_ANT_DIV_COMB_LNA2) { - /* Switch main and alt LNA */ - div_ant_conf.main_lna_conf = - ATH_ANT_DIV_COMB_LNA2; - div_ant_conf.alt_lna_conf = - ATH_ANT_DIV_COMB_LNA1; - } else if (curr_alt_set == ATH_ANT_DIV_COMB_LNA1) { - div_ant_conf.main_lna_conf = - ATH_ANT_DIV_COMB_LNA1; - div_ant_conf.alt_lna_conf = - ATH_ANT_DIV_COMB_LNA2; - } - - goto div_comb_done; - } else if ((curr_alt_set != ATH_ANT_DIV_COMB_LNA1) && - (curr_alt_set != ATH_ANT_DIV_COMB_LNA2)) { - /* Set alt to another LNA */ - if (curr_main_set == ATH_ANT_DIV_COMB_LNA2) - div_ant_conf.alt_lna_conf = - ATH_ANT_DIV_COMB_LNA1; - else if (curr_main_set == ATH_ANT_DIV_COMB_LNA1) - div_ant_conf.alt_lna_conf = - ATH_ANT_DIV_COMB_LNA2; - - goto div_comb_done; - } - - if ((alt_rssi_avg < (main_rssi_avg + - div_ant_conf.lna1_lna2_delta))) - goto div_comb_done; - } - - if (!antcomb->scan_not_start) { - switch (curr_alt_set) { - case ATH_ANT_DIV_COMB_LNA2: - antcomb->rssi_lna2 = alt_rssi_avg; - antcomb->rssi_lna1 = main_rssi_avg; - antcomb->scan = true; - /* set to A+B */ - div_ant_conf.main_lna_conf = - ATH_ANT_DIV_COMB_LNA1; - div_ant_conf.alt_lna_conf = - ATH_ANT_DIV_COMB_LNA1_PLUS_LNA2; - break; - case ATH_ANT_DIV_COMB_LNA1: - antcomb->rssi_lna1 = alt_rssi_avg; - antcomb->rssi_lna2 = main_rssi_avg; - antcomb->scan = true; - /* set to A+B */ - div_ant_conf.main_lna_conf = ATH_ANT_DIV_COMB_LNA2; - div_ant_conf.alt_lna_conf = - ATH_ANT_DIV_COMB_LNA1_PLUS_LNA2; - break; - case ATH_ANT_DIV_COMB_LNA1_PLUS_LNA2: - antcomb->rssi_add = alt_rssi_avg; - antcomb->scan = true; - /* set to A-B */ - div_ant_conf.alt_lna_conf = - ATH_ANT_DIV_COMB_LNA1_MINUS_LNA2; - break; - case ATH_ANT_DIV_COMB_LNA1_MINUS_LNA2: - antcomb->rssi_sub = alt_rssi_avg; - antcomb->scan = false; - if (antcomb->rssi_lna2 > - (antcomb->rssi_lna1 + - ATH_ANT_DIV_COMB_LNA1_LNA2_SWITCH_DELTA)) { - /* use LNA2 as main LNA */ - if ((antcomb->rssi_add > antcomb->rssi_lna1) && - (antcomb->rssi_add > antcomb->rssi_sub)) { - /* set to A+B */ - div_ant_conf.main_lna_conf = - ATH_ANT_DIV_COMB_LNA2; - div_ant_conf.alt_lna_conf = - ATH_ANT_DIV_COMB_LNA1_PLUS_LNA2; - } else if (antcomb->rssi_sub > - antcomb->rssi_lna1) { - /* set to A-B */ - div_ant_conf.main_lna_conf = - ATH_ANT_DIV_COMB_LNA2; - div_ant_conf.alt_lna_conf = - ATH_ANT_DIV_COMB_LNA1_MINUS_LNA2; - } else { - /* set to LNA1 */ - div_ant_conf.main_lna_conf = - ATH_ANT_DIV_COMB_LNA2; - div_ant_conf.alt_lna_conf = - ATH_ANT_DIV_COMB_LNA1; - } - } else { - /* use LNA1 as main LNA */ - if ((antcomb->rssi_add > antcomb->rssi_lna2) && - (antcomb->rssi_add > antcomb->rssi_sub)) { - /* set to A+B */ - div_ant_conf.main_lna_conf = - ATH_ANT_DIV_COMB_LNA1; - div_ant_conf.alt_lna_conf = - ATH_ANT_DIV_COMB_LNA1_PLUS_LNA2; - } else if (antcomb->rssi_sub > - antcomb->rssi_lna1) { - /* set to A-B */ - div_ant_conf.main_lna_conf = - ATH_ANT_DIV_COMB_LNA1; - div_ant_conf.alt_lna_conf = - ATH_ANT_DIV_COMB_LNA1_MINUS_LNA2; - } else { - /* set to LNA2 */ - div_ant_conf.main_lna_conf = - ATH_ANT_DIV_COMB_LNA1; - div_ant_conf.alt_lna_conf = - ATH_ANT_DIV_COMB_LNA2; - } - } - break; - default: - break; - } - } else { - if (!antcomb->alt_good) { - antcomb->scan_not_start = false; - /* Set alt to another LNA */ - if (curr_main_set == ATH_ANT_DIV_COMB_LNA2) { - div_ant_conf.main_lna_conf = - ATH_ANT_DIV_COMB_LNA2; - div_ant_conf.alt_lna_conf = - ATH_ANT_DIV_COMB_LNA1; - } else if (curr_main_set == ATH_ANT_DIV_COMB_LNA1) { - div_ant_conf.main_lna_conf = - ATH_ANT_DIV_COMB_LNA1; - div_ant_conf.alt_lna_conf = - ATH_ANT_DIV_COMB_LNA2; - } - goto div_comb_done; - } - } - - ath_select_ant_div_from_quick_scan(antcomb, &div_ant_conf, - main_rssi_avg, alt_rssi_avg, - alt_ratio); - - antcomb->quick_scan_cnt++; - -div_comb_done: - ath_ant_div_conf_fast_divbias(&div_ant_conf, antcomb, alt_ratio); - ath9k_hw_antdiv_comb_conf_set(sc->sc_ah, &div_ant_conf); - - antcomb->scan_start_time = jiffies; - antcomb->total_pkt_count = 0; - antcomb->main_total_rssi = 0; - antcomb->alt_total_rssi = 0; - antcomb->main_recv_cnt = 0; - antcomb->alt_recv_cnt = 0; -} - -void ath_ant_comb_update(struct ath_softc *sc) -{ - struct ath_hw *ah = sc->sc_ah; - struct ath_hw_antcomb_conf div_ant_conf; - u8 lna_conf; - - ath9k_hw_antdiv_comb_conf_get(ah, &div_ant_conf); - - if (sc->ant_rx == 1) - lna_conf = ATH_ANT_DIV_COMB_LNA1; - else - lna_conf = ATH_ANT_DIV_COMB_LNA2; - - div_ant_conf.main_lna_conf = lna_conf; - div_ant_conf.alt_lna_conf = lna_conf; - - ath9k_hw_antdiv_comb_conf_set(ah, &div_ant_conf); -} diff --git a/trunk/drivers/net/wireless/ath/ath9k/ar9003_calib.c b/trunk/drivers/net/wireless/ath/ath9k/ar9003_calib.c index d7deb8c9f299..9fdd70fcaf5b 100644 --- a/trunk/drivers/net/wireless/ath/ath9k/ar9003_calib.c +++ b/trunk/drivers/net/wireless/ath/ath9k/ar9003_calib.c @@ -653,6 +653,7 @@ static void ar9003_hw_detect_outlier(int *mp_coeff, int nmeasurement, } static void ar9003_hw_tx_iqcal_load_avg_2_passes(struct ath_hw *ah, + u8 num_chains, struct coeff *coeff, bool is_reusable) { @@ -676,9 +677,7 @@ static void ar9003_hw_tx_iqcal_load_avg_2_passes(struct ath_hw *ah, } /* Load the average of 2 passes */ - for (i = 0; i < AR9300_MAX_CHAINS; i++) { - if (!(ah->txchainmask & (1 << i))) - continue; + for (i = 0; i < num_chains; i++) { nmeasurement = REG_READ_FIELD(ah, AR_PHY_TX_IQCAL_STATUS_B0, AR_PHY_CALIBRATED_GAINS_0); @@ -768,13 +767,16 @@ static void ar9003_hw_tx_iq_cal_post_proc(struct ath_hw *ah, bool is_reusable) }; struct coeff coeff; s32 iq_res[6]; + u8 num_chains = 0; int i, im, j; int nmeasurement; for (i = 0; i < AR9300_MAX_CHAINS; i++) { - if (!(ah->txchainmask & (1 << i))) - continue; + if (ah->txchainmask & (1 << i)) + num_chains++; + } + for (i = 0; i < num_chains; i++) { nmeasurement = REG_READ_FIELD(ah, AR_PHY_TX_IQCAL_STATUS_B0, AR_PHY_CALIBRATED_GAINS_0); @@ -837,7 +839,8 @@ static void ar9003_hw_tx_iq_cal_post_proc(struct ath_hw *ah, bool is_reusable) coeff.phs_coeff[i][im] -= 128; } } - ar9003_hw_tx_iqcal_load_avg_2_passes(ah, &coeff, is_reusable); + ar9003_hw_tx_iqcal_load_avg_2_passes(ah, num_chains, + &coeff, is_reusable); return; @@ -898,6 +901,7 @@ static bool ar9003_hw_init_cal(struct ath_hw *ah, bool is_reusable = true, status = true; bool run_rtt_cal = false, run_agc_cal; bool rtt = !!(ah->caps.hw_caps & ATH9K_HW_CAP_RTT); + bool mci = !!(ah->caps.hw_caps & ATH9K_HW_CAP_MCI); u32 agc_ctrl = 0, agc_supp_cals = AR_PHY_AGC_CONTROL_OFFSET_CAL | AR_PHY_AGC_CONTROL_FLTR_CAL | AR_PHY_AGC_CONTROL_PKDET_CAL; @@ -966,7 +970,7 @@ static bool ar9003_hw_init_cal(struct ath_hw *ah, } else if (caldata && !caldata->done_txiqcal_once) run_agc_cal = true; - if (ath9k_hw_mci_is_enabled(ah) && IS_CHAN_2GHZ(chan) && run_agc_cal) + if (mci && IS_CHAN_2GHZ(chan) && run_agc_cal) ar9003_mci_init_cal_req(ah, &is_reusable); if (!(IS_CHAN_HALF_RATE(chan) || IS_CHAN_QUARTER_RATE(chan))) { @@ -989,7 +993,7 @@ static bool ar9003_hw_init_cal(struct ath_hw *ah, 0, AH_WAIT_TIMEOUT); } - if (ath9k_hw_mci_is_enabled(ah) && IS_CHAN_2GHZ(chan) && run_agc_cal) + if (mci && IS_CHAN_2GHZ(chan) && run_agc_cal) ar9003_mci_init_cal_done(ah); if (rtt && !run_rtt_cal) { diff --git a/trunk/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c b/trunk/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c index 2cdf82bdb11d..f794828c08e2 100644 --- a/trunk/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c +++ b/trunk/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c @@ -3613,7 +3613,6 @@ static void ar9003_hw_ant_ctrl_apply(struct ath_hw *ah, bool is2ghz) value = ar9003_switch_com_spdt_get(ah, is2ghz); REG_RMW_FIELD(ah, AR_PHY_GLB_CONTROL, AR_SWITCH_TABLE_COM_SPDT_ALL, value); - REG_SET_BIT(ah, AR_PHY_GLB_CONTROL, AR_BTCOEX_CTRL_SPDT_ENABLE); } value = ar9003_hw_ant_ctrl_common_2_get(ah, is2ghz); diff --git a/trunk/drivers/net/wireless/ath/ath9k/ar9003_mci.c b/trunk/drivers/net/wireless/ath/ath9k/ar9003_mci.c index b1ced2a76da3..ffbb180f91e1 100644 --- a/trunk/drivers/net/wireless/ath/ath9k/ar9003_mci.c +++ b/trunk/drivers/net/wireless/ath/ath9k/ar9003_mci.c @@ -35,30 +35,31 @@ static int ar9003_mci_wait_for_interrupt(struct ath_hw *ah, u32 address, struct ath_common *common = ath9k_hw_common(ah); while (time_out) { - if (!(REG_READ(ah, address) & bit_position)) { - udelay(10); - time_out -= 10; - - if (time_out < 0) - break; - else - continue; - } - REG_WRITE(ah, address, bit_position); - - if (address != AR_MCI_INTERRUPT_RX_MSG_RAW) + if (REG_READ(ah, address) & bit_position) { + REG_WRITE(ah, address, bit_position); + + if (address == AR_MCI_INTERRUPT_RX_MSG_RAW) { + if (bit_position & + AR_MCI_INTERRUPT_RX_MSG_REQ_WAKE) + ar9003_mci_reset_req_wakeup(ah); + + if (bit_position & + (AR_MCI_INTERRUPT_RX_MSG_SYS_SLEEPING | + AR_MCI_INTERRUPT_RX_MSG_SYS_WAKING)) + REG_WRITE(ah, AR_MCI_INTERRUPT_RAW, + AR_MCI_INTERRUPT_REMOTE_SLEEP_UPDATE); + + REG_WRITE(ah, AR_MCI_INTERRUPT_RAW, + AR_MCI_INTERRUPT_RX_MSG); + } break; + } - if (bit_position & AR_MCI_INTERRUPT_RX_MSG_REQ_WAKE) - ar9003_mci_reset_req_wakeup(ah); - - if (bit_position & (AR_MCI_INTERRUPT_RX_MSG_SYS_SLEEPING | - AR_MCI_INTERRUPT_RX_MSG_SYS_WAKING)) - REG_WRITE(ah, AR_MCI_INTERRUPT_RAW, - AR_MCI_INTERRUPT_REMOTE_SLEEP_UPDATE); + udelay(10); + time_out -= 10; - REG_WRITE(ah, AR_MCI_INTERRUPT_RAW, AR_MCI_INTERRUPT_RX_MSG); - break; + if (time_out < 0) + break; } if (time_out <= 0) { @@ -126,13 +127,14 @@ static void ar9003_mci_send_coex_version_query(struct ath_hw *ah, struct ath9k_hw_mci *mci = &ah->btcoex_hw.mci; u32 payload[4] = {0, 0, 0, 0}; - if (mci->bt_version_known || - (mci->bt_state == MCI_BT_SLEEP)) - return; - - MCI_GPM_SET_TYPE_OPCODE(payload, MCI_GPM_COEX_AGENT, - MCI_GPM_COEX_VERSION_QUERY); - ar9003_mci_send_message(ah, MCI_GPM, 0, payload, 16, wait_done, true); + if (!mci->bt_version_known && + (mci->bt_state != MCI_BT_SLEEP)) { + MCI_GPM_SET_TYPE_OPCODE(payload, + MCI_GPM_COEX_AGENT, + MCI_GPM_COEX_VERSION_QUERY); + ar9003_mci_send_message(ah, MCI_GPM, 0, payload, 16, + wait_done, true); + } } static void ar9003_mci_send_coex_version_response(struct ath_hw *ah, @@ -156,14 +158,15 @@ static void ar9003_mci_send_coex_wlan_channels(struct ath_hw *ah, struct ath9k_hw_mci *mci = &ah->btcoex_hw.mci; u32 *payload = &mci->wlan_channels[0]; - if (!mci->wlan_channels_update || - (mci->bt_state == MCI_BT_SLEEP)) - return; - - MCI_GPM_SET_TYPE_OPCODE(payload, MCI_GPM_COEX_AGENT, - MCI_GPM_COEX_WLAN_CHANNELS); - ar9003_mci_send_message(ah, MCI_GPM, 0, payload, 16, wait_done, true); - MCI_GPM_SET_TYPE_OPCODE(payload, 0xff, 0xff); + if ((mci->wlan_channels_update == true) && + (mci->bt_state != MCI_BT_SLEEP)) { + MCI_GPM_SET_TYPE_OPCODE(payload, + MCI_GPM_COEX_AGENT, + MCI_GPM_COEX_WLAN_CHANNELS); + ar9003_mci_send_message(ah, MCI_GPM, 0, payload, 16, + wait_done, true); + MCI_GPM_SET_TYPE_OPCODE(payload, 0xff, 0xff); + } } static void ar9003_mci_send_coex_bt_status_query(struct ath_hw *ah, @@ -171,30 +174,29 @@ static void ar9003_mci_send_coex_bt_status_query(struct ath_hw *ah, { struct ath9k_hw_mci *mci = &ah->btcoex_hw.mci; u32 payload[4] = {0, 0, 0, 0}; - bool query_btinfo; + bool query_btinfo = !!(query_type & (MCI_GPM_COEX_QUERY_BT_ALL_INFO | + MCI_GPM_COEX_QUERY_BT_TOPOLOGY)); - if (mci->bt_state == MCI_BT_SLEEP) - return; + if (mci->bt_state != MCI_BT_SLEEP) { - query_btinfo = !!(query_type & (MCI_GPM_COEX_QUERY_BT_ALL_INFO | - MCI_GPM_COEX_QUERY_BT_TOPOLOGY)); - MCI_GPM_SET_TYPE_OPCODE(payload, MCI_GPM_COEX_AGENT, - MCI_GPM_COEX_STATUS_QUERY); + MCI_GPM_SET_TYPE_OPCODE(payload, MCI_GPM_COEX_AGENT, + MCI_GPM_COEX_STATUS_QUERY); - *(((u8 *)payload) + MCI_GPM_COEX_B_BT_BITMAP) = query_type; + *(((u8 *)payload) + MCI_GPM_COEX_B_BT_BITMAP) = query_type; + + /* + * If bt_status_query message is not sent successfully, + * then need_flush_btinfo should be set again. + */ + if (!ar9003_mci_send_message(ah, MCI_GPM, 0, payload, 16, + wait_done, true)) { + if (query_btinfo) + mci->need_flush_btinfo = true; + } - /* - * If bt_status_query message is not sent successfully, - * then need_flush_btinfo should be set again. - */ - if (!ar9003_mci_send_message(ah, MCI_GPM, 0, payload, 16, - wait_done, true)) { if (query_btinfo) - mci->need_flush_btinfo = true; + mci->query_bt = false; } - - if (query_btinfo) - mci->query_bt = false; } static void ar9003_mci_send_coex_halt_bt_gpm(struct ath_hw *ah, bool halt, @@ -239,73 +241,73 @@ static void ar9003_mci_prep_interface(struct ath_hw *ah) ar9003_mci_remote_reset(ah, true); ar9003_mci_send_req_wake(ah, true); - if (!ar9003_mci_wait_for_interrupt(ah, AR_MCI_INTERRUPT_RX_MSG_RAW, - AR_MCI_INTERRUPT_RX_MSG_SYS_WAKING, 500)) - goto clear_redunt; + if (ar9003_mci_wait_for_interrupt(ah, AR_MCI_INTERRUPT_RX_MSG_RAW, + AR_MCI_INTERRUPT_RX_MSG_SYS_WAKING, 500)) { - mci->bt_state = MCI_BT_AWAKE; + mci->bt_state = MCI_BT_AWAKE; - /* - * we don't need to send more remote_reset at this moment. - * If BT receive first remote_reset, then BT HW will - * be cleaned up and will be able to receive req_wake - * and BT HW will respond sys_waking. - * In this case, WLAN will receive BT's HW sys_waking. - * Otherwise, if BT SW missed initial remote_reset, - * that remote_reset will still clean up BT MCI RX, - * and the req_wake will wake BT up, - * and BT SW will respond this req_wake with a remote_reset and - * sys_waking. In this case, WLAN will receive BT's SW - * sys_waking. In either case, BT's RX is cleaned up. So we - * don't need to reply BT's remote_reset now, if any. - * Similarly, if in any case, WLAN can receive BT's sys_waking, - * that means WLAN's RX is also fine. - */ - ar9003_mci_send_sys_waking(ah, true); - udelay(10); + /* + * we don't need to send more remote_reset at this moment. + * If BT receive first remote_reset, then BT HW will + * be cleaned up and will be able to receive req_wake + * and BT HW will respond sys_waking. + * In this case, WLAN will receive BT's HW sys_waking. + * Otherwise, if BT SW missed initial remote_reset, + * that remote_reset will still clean up BT MCI RX, + * and the req_wake will wake BT up, + * and BT SW will respond this req_wake with a remote_reset and + * sys_waking. In this case, WLAN will receive BT's SW + * sys_waking. In either case, BT's RX is cleaned up. So we + * don't need to reply BT's remote_reset now, if any. + * Similarly, if in any case, WLAN can receive BT's sys_waking, + * that means WLAN's RX is also fine. + */ + ar9003_mci_send_sys_waking(ah, true); + udelay(10); - /* - * Set BT priority interrupt value to be 0xff to - * avoid having too many BT PRIORITY interrupts. - */ - REG_WRITE(ah, AR_MCI_BT_PRI0, 0xFFFFFFFF); - REG_WRITE(ah, AR_MCI_BT_PRI1, 0xFFFFFFFF); - REG_WRITE(ah, AR_MCI_BT_PRI2, 0xFFFFFFFF); - REG_WRITE(ah, AR_MCI_BT_PRI3, 0xFFFFFFFF); - REG_WRITE(ah, AR_MCI_BT_PRI, 0X000000FF); + /* + * Set BT priority interrupt value to be 0xff to + * avoid having too many BT PRIORITY interrupts. + */ + REG_WRITE(ah, AR_MCI_BT_PRI0, 0xFFFFFFFF); + REG_WRITE(ah, AR_MCI_BT_PRI1, 0xFFFFFFFF); + REG_WRITE(ah, AR_MCI_BT_PRI2, 0xFFFFFFFF); + REG_WRITE(ah, AR_MCI_BT_PRI3, 0xFFFFFFFF); + REG_WRITE(ah, AR_MCI_BT_PRI, 0X000000FF); - /* - * A contention reset will be received after send out - * sys_waking. Also BT priority interrupt bits will be set. - * Clear those bits before the next step. - */ + /* + * A contention reset will be received after send out + * sys_waking. Also BT priority interrupt bits will be set. + * Clear those bits before the next step. + */ - REG_WRITE(ah, AR_MCI_INTERRUPT_RX_MSG_RAW, - AR_MCI_INTERRUPT_RX_MSG_CONT_RST); - REG_WRITE(ah, AR_MCI_INTERRUPT_RAW, AR_MCI_INTERRUPT_BT_PRI); + REG_WRITE(ah, AR_MCI_INTERRUPT_RX_MSG_RAW, + AR_MCI_INTERRUPT_RX_MSG_CONT_RST); + REG_WRITE(ah, AR_MCI_INTERRUPT_RAW, + AR_MCI_INTERRUPT_BT_PRI); - if (mci->is_2g) { - ar9003_mci_send_lna_transfer(ah, true); - udelay(5); - } + if (mci->is_2g) { + ar9003_mci_send_lna_transfer(ah, true); + udelay(5); + } - if ((mci->is_2g && !mci->update_2g5g)) { - if (ar9003_mci_wait_for_interrupt(ah, - AR_MCI_INTERRUPT_RX_MSG_RAW, - AR_MCI_INTERRUPT_RX_MSG_LNA_INFO, - mci_timeout)) - ath_dbg(common, MCI, - "MCI WLAN has control over the LNA & BT obeys it\n"); - else - ath_dbg(common, MCI, - "MCI BT didn't respond to LNA_TRANS\n"); + if ((mci->is_2g && !mci->update_2g5g)) { + if (ar9003_mci_wait_for_interrupt(ah, + AR_MCI_INTERRUPT_RX_MSG_RAW, + AR_MCI_INTERRUPT_RX_MSG_LNA_INFO, + mci_timeout)) + ath_dbg(common, MCI, + "MCI WLAN has control over the LNA & BT obeys it\n"); + else + ath_dbg(common, MCI, + "MCI BT didn't respond to LNA_TRANS\n"); + } } -clear_redunt: /* Clear the extra redundant SYS_WAKING from BT */ if ((mci->bt_state == MCI_BT_AWAKE) && - (REG_READ_FIELD(ah, AR_MCI_INTERRUPT_RX_MSG_RAW, - AR_MCI_INTERRUPT_RX_MSG_SYS_WAKING)) && + (REG_READ_FIELD(ah, AR_MCI_INTERRUPT_RX_MSG_RAW, + AR_MCI_INTERRUPT_RX_MSG_SYS_WAKING)) && (REG_READ_FIELD(ah, AR_MCI_INTERRUPT_RX_MSG_RAW, AR_MCI_INTERRUPT_RX_MSG_SYS_SLEEPING) == 0)) { REG_WRITE(ah, AR_MCI_INTERRUPT_RX_MSG_RAW, @@ -328,6 +330,7 @@ void ar9003_mci_set_full_sleep(struct ath_hw *ah) } mci->ready = false; + REG_WRITE(ah, AR_RTC_KEEP_AWAKE, 0x2); } static void ar9003_mci_disable_interrupt(struct ath_hw *ah) @@ -612,9 +615,9 @@ static u32 ar9003_mci_wait_for_gpm(struct ath_hw *ah, u8 gpm_type, } break; } - } else if ((recv_type == gpm_type) && - (recv_opcode == gpm_opcode)) + } else if ((recv_type == gpm_type) && (recv_opcode == gpm_opcode)) { break; + } /* * check if it's cal_grant @@ -728,38 +731,38 @@ int ar9003_mci_end_reset(struct ath_hw *ah, struct ath9k_channel *chan, if (!IS_CHAN_2GHZ(chan) || (mci_hw->bt_state != MCI_BT_SLEEP)) goto exit; - if (!ar9003_mci_check_int(ah, AR_MCI_INTERRUPT_RX_MSG_REMOTE_RESET) && - !ar9003_mci_check_int(ah, AR_MCI_INTERRUPT_RX_MSG_REQ_WAKE)) - goto exit; + if (ar9003_mci_check_int(ah, AR_MCI_INTERRUPT_RX_MSG_REMOTE_RESET) || + ar9003_mci_check_int(ah, AR_MCI_INTERRUPT_RX_MSG_REQ_WAKE)) { - /* - * BT is sleeping. Check if BT wakes up during - * WLAN calibration. If BT wakes up during - * WLAN calibration, need to go through all - * message exchanges again and recal. - */ - REG_WRITE(ah, AR_MCI_INTERRUPT_RX_MSG_RAW, - (AR_MCI_INTERRUPT_RX_MSG_REMOTE_RESET | - AR_MCI_INTERRUPT_RX_MSG_REQ_WAKE)); + /* + * BT is sleeping. Check if BT wakes up during + * WLAN calibration. If BT wakes up during + * WLAN calibration, need to go through all + * message exchanges again and recal. + */ + REG_WRITE(ah, AR_MCI_INTERRUPT_RX_MSG_RAW, + AR_MCI_INTERRUPT_RX_MSG_REMOTE_RESET | + AR_MCI_INTERRUPT_RX_MSG_REQ_WAKE); - ar9003_mci_remote_reset(ah, true); - ar9003_mci_send_sys_waking(ah, true); - udelay(1); + ar9003_mci_remote_reset(ah, true); + ar9003_mci_send_sys_waking(ah, true); + udelay(1); - if (IS_CHAN_2GHZ(chan)) - ar9003_mci_send_lna_transfer(ah, true); + if (IS_CHAN_2GHZ(chan)) + ar9003_mci_send_lna_transfer(ah, true); - mci_hw->bt_state = MCI_BT_AWAKE; + mci_hw->bt_state = MCI_BT_AWAKE; - if (caldata) { - caldata->done_txiqcal_once = false; - caldata->done_txclcal_once = false; - caldata->rtt_done = false; - } + if (caldata) { + caldata->done_txiqcal_once = false; + caldata->done_txclcal_once = false; + caldata->rtt_done = false; + } - if (!ath9k_hw_init_cal(ah, chan)) - return -EIO; + if (!ath9k_hw_init_cal(ah, chan)) + return -EIO; + } exit: ar9003_mci_enable_interrupt(ah); return 0; @@ -795,27 +798,29 @@ static void ar9003_mci_osla_setup(struct ath_hw *ah, bool enable) struct ath9k_hw_mci *mci = &ah->btcoex_hw.mci; u32 thresh; - if (!enable) { + if (enable) { + REG_RMW_FIELD(ah, AR_MCI_SCHD_TABLE_2, + AR_MCI_SCHD_TABLE_2_HW_BASED, 1); + REG_RMW_FIELD(ah, AR_MCI_SCHD_TABLE_2, + AR_MCI_SCHD_TABLE_2_MEM_BASED, 1); + + if (!(mci->config & ATH_MCI_CONFIG_DISABLE_AGGR_THRESH)) { + thresh = MS(mci->config, ATH_MCI_CONFIG_AGGR_THRESH); + REG_RMW_FIELD(ah, AR_BTCOEX_CTRL, + AR_BTCOEX_CTRL_AGGR_THRESH, thresh); + REG_RMW_FIELD(ah, AR_BTCOEX_CTRL, + AR_BTCOEX_CTRL_TIME_TO_NEXT_BT_THRESH_EN, 1); + } else { + REG_RMW_FIELD(ah, AR_BTCOEX_CTRL, + AR_BTCOEX_CTRL_TIME_TO_NEXT_BT_THRESH_EN, 0); + } + + REG_RMW_FIELD(ah, AR_BTCOEX_CTRL, + AR_BTCOEX_CTRL_ONE_STEP_LOOK_AHEAD_EN, 1); + } else { REG_CLR_BIT(ah, AR_BTCOEX_CTRL, AR_BTCOEX_CTRL_ONE_STEP_LOOK_AHEAD_EN); - return; } - REG_RMW_FIELD(ah, AR_MCI_SCHD_TABLE_2, AR_MCI_SCHD_TABLE_2_HW_BASED, 1); - REG_RMW_FIELD(ah, AR_MCI_SCHD_TABLE_2, - AR_MCI_SCHD_TABLE_2_MEM_BASED, 1); - - if (!(mci->config & ATH_MCI_CONFIG_DISABLE_AGGR_THRESH)) { - thresh = MS(mci->config, ATH_MCI_CONFIG_AGGR_THRESH); - REG_RMW_FIELD(ah, AR_BTCOEX_CTRL, - AR_BTCOEX_CTRL_AGGR_THRESH, thresh); - REG_RMW_FIELD(ah, AR_BTCOEX_CTRL, - AR_BTCOEX_CTRL_TIME_TO_NEXT_BT_THRESH_EN, 1); - } else - REG_RMW_FIELD(ah, AR_BTCOEX_CTRL, - AR_BTCOEX_CTRL_TIME_TO_NEXT_BT_THRESH_EN, 0); - - REG_RMW_FIELD(ah, AR_BTCOEX_CTRL, - AR_BTCOEX_CTRL_ONE_STEP_LOOK_AHEAD_EN, 1); } void ar9003_mci_reset(struct ath_hw *ah, bool en_int, bool is_2g, @@ -938,27 +943,26 @@ static void ar9003_mci_send_2g5g_status(struct ath_hw *ah, bool wait_done) struct ath9k_hw_mci *mci = &ah->btcoex_hw.mci; u32 new_flags, to_set, to_clear; - if (!mci->update_2g5g || (mci->bt_state == MCI_BT_SLEEP)) - return; - - if (mci->is_2g) { - new_flags = MCI_2G_FLAGS; - to_clear = MCI_2G_FLAGS_CLEAR_MASK; - to_set = MCI_2G_FLAGS_SET_MASK; - } else { - new_flags = MCI_5G_FLAGS; - to_clear = MCI_5G_FLAGS_CLEAR_MASK; - to_set = MCI_5G_FLAGS_SET_MASK; - } + if (mci->update_2g5g && (mci->bt_state != MCI_BT_SLEEP)) { + if (mci->is_2g) { + new_flags = MCI_2G_FLAGS; + to_clear = MCI_2G_FLAGS_CLEAR_MASK; + to_set = MCI_2G_FLAGS_SET_MASK; + } else { + new_flags = MCI_5G_FLAGS; + to_clear = MCI_5G_FLAGS_CLEAR_MASK; + to_set = MCI_5G_FLAGS_SET_MASK; + } - if (to_clear) - ar9003_mci_send_coex_bt_flags(ah, wait_done, + if (to_clear) + ar9003_mci_send_coex_bt_flags(ah, wait_done, MCI_GPM_COEX_BT_FLAGS_CLEAR, to_clear); - if (to_set) - ar9003_mci_send_coex_bt_flags(ah, wait_done, + if (to_set) + ar9003_mci_send_coex_bt_flags(ah, wait_done, MCI_GPM_COEX_BT_FLAGS_SET, to_set); + } } static void ar9003_mci_queue_unsent_gpm(struct ath_hw *ah, u8 header, @@ -1014,34 +1018,34 @@ void ar9003_mci_2g5g_switch(struct ath_hw *ah, bool wait_done) { struct ath9k_hw_mci *mci = &ah->btcoex_hw.mci; - if (!mci->update_2g5g) - return; - - if (mci->is_2g) { - ar9003_mci_send_2g5g_status(ah, true); - ar9003_mci_send_lna_transfer(ah, true); - udelay(5); + if (mci->update_2g5g) { + if (mci->is_2g) { + ar9003_mci_send_2g5g_status(ah, true); + ar9003_mci_send_lna_transfer(ah, true); + udelay(5); - REG_CLR_BIT(ah, AR_MCI_TX_CTRL, - AR_MCI_TX_CTRL_DISABLE_LNA_UPDATE); - REG_CLR_BIT(ah, AR_PHY_GLB_CONTROL, - AR_BTCOEX_CTRL_BT_OWN_SPDT_CTRL); + REG_CLR_BIT(ah, AR_MCI_TX_CTRL, + AR_MCI_TX_CTRL_DISABLE_LNA_UPDATE); + REG_CLR_BIT(ah, AR_PHY_GLB_CONTROL, + AR_BTCOEX_CTRL_BT_OWN_SPDT_CTRL); - if (!(mci->config & ATH_MCI_CONFIG_DISABLE_OSLA)) - REG_SET_BIT(ah, AR_BTCOEX_CTRL, + if (!(mci->config & ATH_MCI_CONFIG_DISABLE_OSLA)) { + REG_SET_BIT(ah, AR_BTCOEX_CTRL, + AR_BTCOEX_CTRL_ONE_STEP_LOOK_AHEAD_EN); + } + } else { + ar9003_mci_send_lna_take(ah, true); + udelay(5); + + REG_SET_BIT(ah, AR_MCI_TX_CTRL, + AR_MCI_TX_CTRL_DISABLE_LNA_UPDATE); + REG_SET_BIT(ah, AR_PHY_GLB_CONTROL, + AR_BTCOEX_CTRL_BT_OWN_SPDT_CTRL); + REG_CLR_BIT(ah, AR_BTCOEX_CTRL, AR_BTCOEX_CTRL_ONE_STEP_LOOK_AHEAD_EN); - } else { - ar9003_mci_send_lna_take(ah, true); - udelay(5); - REG_SET_BIT(ah, AR_MCI_TX_CTRL, - AR_MCI_TX_CTRL_DISABLE_LNA_UPDATE); - REG_SET_BIT(ah, AR_PHY_GLB_CONTROL, - AR_BTCOEX_CTRL_BT_OWN_SPDT_CTRL); - REG_CLR_BIT(ah, AR_BTCOEX_CTRL, - AR_BTCOEX_CTRL_ONE_STEP_LOOK_AHEAD_EN); - - ar9003_mci_send_2g5g_status(ah, true); + ar9003_mci_send_2g5g_status(ah, true); + } } } @@ -1128,7 +1132,7 @@ void ar9003_mci_init_cal_req(struct ath_hw *ah, bool *is_reusable) if (ar9003_mci_wait_for_gpm(ah, MCI_GPM_BT_CAL_GRANT, 0, 50000)) { ath_dbg(common, MCI, "MCI BT_CAL_GRANT received\n"); } else { - *is_reusable = false; + is_reusable = false; ath_dbg(common, MCI, "MCI BT_CAL_GRANT not received\n"); } } @@ -1255,12 +1259,12 @@ u32 ar9003_mci_state(struct ath_hw *ah, u32 state_type, u32 *p_data) } if (p_data) *p_data = more_gpm; - } + } - if (value != MCI_GPM_INVALID) - value <<= 4; + if (value != MCI_GPM_INVALID) + value <<= 4; - break; + break; case MCI_STATE_LAST_SCHD_MSG_OFFSET: value = MS(REG_READ(ah, AR_MCI_RX_STATUS), AR_MCI_RX_LAST_SCHD_MSG_INDEX); @@ -1355,22 +1359,24 @@ u32 ar9003_mci_state(struct ath_hw *ah, u32 state_type, u32 *p_data) ar9003_mci_send_coex_bt_status_query(ah, true, query_type); break; case MCI_STATE_NEED_FLUSH_BT_INFO: - /* - * btcoex_hw.mci.unhalt_bt_gpm means whether it's - * needed to send UNHALT message. It's set whenever - * there's a request to send HALT message. - * mci_halted_bt_gpm means whether HALT message is sent - * out successfully. - * - * Checking (mci_unhalt_bt_gpm == false) instead of - * checking (ah->mci_halted_bt_gpm == false) will make - * sure currently is in UNHALT-ed mode and BT can - * respond to status query. - */ - value = (!mci->unhalt_bt_gpm && mci->need_flush_btinfo) ? 1 : 0; - if (p_data) - mci->need_flush_btinfo = (*p_data != 0) ? true : false; - break; + /* + * btcoex_hw.mci.unhalt_bt_gpm means whether it's + * needed to send UNHALT message. It's set whenever + * there's a request to send HALT message. + * mci_halted_bt_gpm means whether HALT message is sent + * out successfully. + * + * Checking (mci_unhalt_bt_gpm == false) instead of + * checking (ah->mci_halted_bt_gpm == false) will make + * sure currently is in UNHALT-ed mode and BT can + * respond to status query. + */ + value = (!mci->unhalt_bt_gpm && + mci->need_flush_btinfo) ? 1 : 0; + if (p_data) + mci->need_flush_btinfo = + (*p_data != 0) ? true : false; + break; case MCI_STATE_RECOVER_RX: ar9003_mci_prep_interface(ah); mci->query_bt = true; @@ -1381,6 +1387,9 @@ u32 ar9003_mci_state(struct ath_hw *ah, u32 state_type, u32 *p_data) case MCI_STATE_NEED_FTP_STOMP: value = !(mci->config & ATH_MCI_CONFIG_DISABLE_FTP_STOMP); break; + case MCI_STATE_NEED_TUNING: + value = !(mci->config & ATH_MCI_CONFIG_DISABLE_TUNING); + break; default: break; } @@ -1388,19 +1397,3 @@ u32 ar9003_mci_state(struct ath_hw *ah, u32 state_type, u32 *p_data) return value; } EXPORT_SYMBOL(ar9003_mci_state); - -void ar9003_mci_bt_gain_ctrl(struct ath_hw *ah) -{ - struct ath_common *common = ath9k_hw_common(ah); - struct ath9k_hw_mci *mci = &ah->btcoex_hw.mci; - - ath_dbg(common, MCI, "Give LNA and SPDT control to BT\n"); - - REG_SET_BIT(ah, AR_PHY_GLB_CONTROL, AR_BTCOEX_CTRL_BT_OWN_SPDT_CTRL); - mci->is_2g = false; - mci->update_2g5g = true; - ar9003_mci_send_2g5g_status(ah, true); - - /* Force another 2g5g update at next scanning */ - mci->update_2g5g = true; -} diff --git a/trunk/drivers/net/wireless/ath/ath9k/ar9003_mci.h b/trunk/drivers/net/wireless/ath/ath9k/ar9003_mci.h index 10282e2bcdc9..4842f6c06b8c 100644 --- a/trunk/drivers/net/wireless/ath/ath9k/ar9003_mci.h +++ b/trunk/drivers/net/wireless/ath/ath9k/ar9003_mci.h @@ -212,6 +212,7 @@ enum mci_state_type { MCI_STATE_SET_CONCUR_TX_PRI, MCI_STATE_RECOVER_RX, MCI_STATE_NEED_FTP_STOMP, + MCI_STATE_NEED_TUNING, MCI_STATE_DEBUG, MCI_STATE_MAX }; @@ -265,7 +266,6 @@ void ar9003_mci_setup(struct ath_hw *ah, u32 gpm_addr, void *gpm_buf, void ar9003_mci_cleanup(struct ath_hw *ah); void ar9003_mci_get_interrupt(struct ath_hw *ah, u32 *raw_intr, u32 *rx_msg_intr); -void ar9003_mci_bt_gain_ctrl(struct ath_hw *ah); /* * These functions are used by ath9k_hw. @@ -273,6 +273,10 @@ void ar9003_mci_bt_gain_ctrl(struct ath_hw *ah); #ifdef CONFIG_ATH9K_BTCOEX_SUPPORT +static inline bool ar9003_mci_is_ready(struct ath_hw *ah) +{ + return ah->btcoex_hw.mci.ready; +} void ar9003_mci_stop_bt(struct ath_hw *ah, bool save_fullsleep); void ar9003_mci_init_cal_req(struct ath_hw *ah, bool *is_reusable); void ar9003_mci_init_cal_done(struct ath_hw *ah); @@ -288,6 +292,10 @@ void ar9003_mci_get_isr(struct ath_hw *ah, enum ath9k_int *masked); #else +static inline bool ar9003_mci_is_ready(struct ath_hw *ah) +{ + return false; +} static inline void ar9003_mci_stop_bt(struct ath_hw *ah, bool save_fullsleep) { } diff --git a/trunk/drivers/net/wireless/ath/ath9k/ar9003_phy.c b/trunk/drivers/net/wireless/ath/ath9k/ar9003_phy.c index d6baf69cdc14..11abb972be1f 100644 --- a/trunk/drivers/net/wireless/ath/ath9k/ar9003_phy.c +++ b/trunk/drivers/net/wireless/ath/ath9k/ar9003_phy.c @@ -676,10 +676,6 @@ static int ar9003_hw_process_ini(struct ath_hw *ah, if (chan->channel == 2484) ar9003_hw_prog_ini(ah, &ah->ini_japan2484, 1); - if (AR_SREV_9462(ah)) - REG_WRITE(ah, AR_GLB_SWREG_DISCONT_MODE, - AR_GLB_SWREG_DISCONT_EN_BT_WLAN); - ah->modes_index = modesIndex; ar9003_hw_override_ini(ah); ar9003_hw_set_channel_regs(ah, chan); diff --git a/trunk/drivers/net/wireless/ath/ath9k/ar9003_phy.h b/trunk/drivers/net/wireless/ath/ath9k/ar9003_phy.h index ed662c3bae5b..7268a48a92a1 100644 --- a/trunk/drivers/net/wireless/ath/ath9k/ar9003_phy.h +++ b/trunk/drivers/net/wireless/ath/ath9k/ar9003_phy.h @@ -820,26 +820,18 @@ #define AR_PHY_CHAN_INFO_MEMORY_CAPTURE_MASK 0x0001 #define AR_PHY_RX_DELAY_DELAY 0x00003FFF #define AR_PHY_CCK_TX_CTRL_JAPAN 0x00000010 - -#define AR_PHY_SPECTRAL_SCAN_ENABLE 0x00000001 -#define AR_PHY_SPECTRAL_SCAN_ENABLE_S 0 -#define AR_PHY_SPECTRAL_SCAN_ACTIVE 0x00000002 -#define AR_PHY_SPECTRAL_SCAN_ACTIVE_S 1 -#define AR_PHY_SPECTRAL_SCAN_FFT_PERIOD 0x000000F0 -#define AR_PHY_SPECTRAL_SCAN_FFT_PERIOD_S 4 -#define AR_PHY_SPECTRAL_SCAN_PERIOD 0x0000FF00 -#define AR_PHY_SPECTRAL_SCAN_PERIOD_S 8 -#define AR_PHY_SPECTRAL_SCAN_COUNT 0x0FFF0000 -#define AR_PHY_SPECTRAL_SCAN_COUNT_S 16 -#define AR_PHY_SPECTRAL_SCAN_SHORT_REPEAT 0x10000000 -#define AR_PHY_SPECTRAL_SCAN_SHORT_REPEAT_S 28 -#define AR_PHY_SPECTRAL_SCAN_PRIORITY 0x20000000 -#define AR_PHY_SPECTRAL_SCAN_PRIORITY_S 29 -#define AR_PHY_SPECTRAL_SCAN_USE_ERR5 0x40000000 -#define AR_PHY_SPECTRAL_SCAN_USE_ERR5_S 30 -#define AR_PHY_SPECTRAL_SCAN_COMPRESSED_RPT 0x80000000 -#define AR_PHY_SPECTRAL_SCAN_COMPRESSED_RPT_S 31 - +#define AR_PHY_SPECTRAL_SCAN_ENABLE 0x00000001 +#define AR_PHY_SPECTRAL_SCAN_ENABLE_S 0 +#define AR_PHY_SPECTRAL_SCAN_ACTIVE 0x00000002 +#define AR_PHY_SPECTRAL_SCAN_ACTIVE_S 1 +#define AR_PHY_SPECTRAL_SCAN_FFT_PERIOD 0x000000F0 +#define AR_PHY_SPECTRAL_SCAN_FFT_PERIOD_S 4 +#define AR_PHY_SPECTRAL_SCAN_PERIOD 0x0000FF00 +#define AR_PHY_SPECTRAL_SCAN_PERIOD_S 8 +#define AR_PHY_SPECTRAL_SCAN_COUNT 0x00FF0000 +#define AR_PHY_SPECTRAL_SCAN_COUNT_S 16 +#define AR_PHY_SPECTRAL_SCAN_SHORT_REPEAT 0x01000000 +#define AR_PHY_SPECTRAL_SCAN_SHORT_REPEAT_S 24 #define AR_PHY_CHANNEL_STATUS_RX_CLEAR 0x00000004 #define AR_PHY_RTT_CTRL_ENA_RADIO_RETENTION 0x00000001 #define AR_PHY_RTT_CTRL_ENA_RADIO_RETENTION_S 0 diff --git a/trunk/drivers/net/wireless/ath/ath9k/ar9462_2p0_initvals.h b/trunk/drivers/net/wireless/ath/ath9k/ar9462_2p0_initvals.h index a10ece0cb6cd..1d6658e139b5 100644 --- a/trunk/drivers/net/wireless/ath/ath9k/ar9462_2p0_initvals.h +++ b/trunk/drivers/net/wireless/ath/ath9k/ar9462_2p0_initvals.h @@ -958,7 +958,7 @@ static const u32 ar9462_2p0_radio_core[][2] = { {0x0001604c, 0x2699e04f}, {0x00016050, 0x6db6db6c}, {0x00016058, 0x6c200000}, - {0x00016080, 0x000c0000}, + {0x00016080, 0x00040000}, {0x00016084, 0x9a68048c}, {0x00016088, 0x54214514}, {0x0001608c, 0x1203040b}, @@ -981,7 +981,7 @@ static const u32 ar9462_2p0_radio_core[][2] = { {0x00016144, 0x02084080}, {0x00016148, 0x000080c0}, {0x00016280, 0x050a0001}, - {0x00016284, 0x3d841418}, + {0x00016284, 0x3d841400}, {0x00016288, 0x00000000}, {0x0001628c, 0xe3000000}, {0x00016290, 0xa1005080}, diff --git a/trunk/drivers/net/wireless/ath/ath9k/ath9k.h b/trunk/drivers/net/wireless/ath/ath9k/ath9k.h index 02fc1c1e5eeb..a277cf6f339d 100644 --- a/trunk/drivers/net/wireless/ath/ath9k/ath9k.h +++ b/trunk/drivers/net/wireless/ath/ath9k/ath9k.h @@ -307,7 +307,6 @@ struct ath_rx { u8 defant; u8 rxotherant; u32 *rxlink; - u32 num_pkts; unsigned int rxfilter; spinlock_t rxbuflock; struct list_head rxbuf; @@ -326,9 +325,6 @@ int ath_rx_init(struct ath_softc *sc, int nbufs); void ath_rx_cleanup(struct ath_softc *sc); int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp); struct ath_txq *ath_txq_setup(struct ath_softc *sc, int qtype, int subtype); -void ath_txq_lock(struct ath_softc *sc, struct ath_txq *txq); -void ath_txq_unlock(struct ath_softc *sc, struct ath_txq *txq); -void ath_txq_unlock_complete(struct ath_softc *sc, struct ath_txq *txq); void ath_tx_cleanupq(struct ath_softc *sc, struct ath_txq *txq); bool ath_drain_all_txq(struct ath_softc *sc, bool retry_tx); void ath_draintxq(struct ath_softc *sc, @@ -418,9 +414,9 @@ int ath_beaconq_config(struct ath_softc *sc); void ath_set_beacon(struct ath_softc *sc); void ath9k_set_beaconing_status(struct ath_softc *sc, bool status); -/*******************/ -/* Link Monitoring */ -/*******************/ +/*******/ +/* ANI */ +/*******/ #define ATH_STA_SHORT_CALINTERVAL 1000 /* 1 second */ #define ATH_AP_SHORT_CALINTERVAL 100 /* 100 ms */ @@ -431,9 +427,7 @@ void ath9k_set_beaconing_status(struct ath_softc *sc, bool status); #define ATH_RESTART_CALINTERVAL 1200000 /* 20 minutes */ #define ATH_PAPRD_TIMEOUT 100 /* msecs */ -#define ATH_PLL_WORK_INTERVAL 100 -void ath_tx_complete_poll_work(struct work_struct *work); void ath_reset_work(struct work_struct *work); void ath_hw_check(struct work_struct *work); void ath_hw_pll_work(struct work_struct *work); @@ -442,31 +436,22 @@ void ath_start_rx_poll(struct ath_softc *sc, u8 nbeacon); void ath_paprd_calibrate(struct work_struct *work); void ath_ani_calibrate(unsigned long data); void ath_start_ani(struct ath_common *common); -int ath_update_survey_stats(struct ath_softc *sc); -void ath_update_survey_nf(struct ath_softc *sc, int channel); /**********/ /* BTCOEX */ /**********/ -enum bt_op_flags { - BT_OP_PRIORITY_DETECTED, - BT_OP_SCAN, -}; - struct ath_btcoex { bool hw_timer_enabled; spinlock_t btcoex_lock; struct timer_list period_timer; /* Timer for BT period */ u32 bt_priority_cnt; unsigned long bt_priority_time; - unsigned long op_flags; int bt_stomp_type; /* Types of BT stomping */ u32 btcoex_no_stomp; /* in usec */ u32 btcoex_period; /* in usec */ u32 btscan_no_stomp; /* in usec */ u32 duty_cycle; - u32 bt_wait_time; struct ath_gen_timer *no_stomp_timer; /* Timer for no BT stomping */ struct ath_mci_profile mci; }; @@ -528,10 +513,8 @@ static inline void ath_deinit_leds(struct ath_softc *sc) } #endif -/*******************************/ -/* Antenna diversity/combining */ -/*******************************/ +/* Antenna diversity/combining */ #define ATH_ANT_RX_CURRENT_SHIFT 4 #define ATH_ANT_RX_MAIN_SHIFT 2 #define ATH_ANT_RX_MASK 0x3 @@ -584,9 +567,6 @@ struct ath_ant_comb { unsigned long scan_start_time; }; -void ath_ant_comb_scan(struct ath_softc *sc, struct ath_rx_status *rs); -void ath_ant_comb_update(struct ath_softc *sc); - /********************/ /* Main driver core */ /********************/ @@ -604,15 +584,15 @@ void ath_ant_comb_update(struct ath_softc *sc); #define ATH_TXPOWER_MAX 100 /* .5 dBm units */ #define ATH_RATE_DUMMY_MARKER 0 -enum sc_op_flags { - SC_OP_INVALID, - SC_OP_BEACONS, - SC_OP_RXFLUSH, - SC_OP_TSF_RESET, - SC_OP_ANI_RUN, - SC_OP_PRIM_STA_VIF, - SC_OP_HW_RESET, -}; +#define SC_OP_INVALID BIT(0) +#define SC_OP_BEACONS BIT(1) +#define SC_OP_OFFCHANNEL BIT(2) +#define SC_OP_RXFLUSH BIT(3) +#define SC_OP_TSF_RESET BIT(4) +#define SC_OP_BT_PRIORITY_DETECTED BIT(5) +#define SC_OP_BT_SCAN BIT(6) +#define SC_OP_ANI_RUN BIT(7) +#define SC_OP_PRIM_STA_VIF BIT(8) /* Powersave flags */ #define PS_WAIT_FOR_BEACON BIT(0) @@ -658,9 +638,9 @@ struct ath_softc { struct completion paprd_complete; unsigned int hw_busy_count; - unsigned long sc_flags; u32 intrstatus; + u32 sc_flags; /* SC_OP_* */ u16 ps_flags; /* PS_* */ u16 curtxpow; bool ps_enabled; @@ -756,4 +736,5 @@ void ath9k_calculate_iter_data(struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct ath9k_vif_iter_data *iter_data); + #endif /* ATH9K_H */ diff --git a/trunk/drivers/net/wireless/ath/ath9k/beacon.c b/trunk/drivers/net/wireless/ath/ath9k/beacon.c index 40775da8941e..11bc55e3d697 100644 --- a/trunk/drivers/net/wireless/ath/ath9k/beacon.c +++ b/trunk/drivers/net/wireless/ath/ath9k/beacon.c @@ -48,10 +48,7 @@ int ath_beaconq_config(struct ath_softc *sc) txq = sc->tx.txq_map[WME_AC_BE]; ath9k_hw_get_txq_props(ah, txq->axq_qnum, &qi_be); qi.tqi_aifs = qi_be.tqi_aifs; - if (ah->slottime == ATH9K_SLOT_TIME_20) - qi.tqi_cwmin = 2*qi_be.tqi_cwmin; - else - qi.tqi_cwmin = 4*qi_be.tqi_cwmin; + qi.tqi_cwmin = 4*qi_be.tqi_cwmin; qi.tqi_cwmax = qi_be.tqi_cwmax; } @@ -390,7 +387,7 @@ void ath_beacon_tasklet(unsigned long data) } else if (sc->beacon.bmisscnt >= BSTUCK_THRESH) { ath_dbg(common, BSTUCK, "beacon is officially stuck\n"); sc->beacon.bmisscnt = 0; - set_bit(SC_OP_TSF_RESET, &sc->sc_flags); + sc->sc_flags |= SC_OP_TSF_RESET; ieee80211_queue_work(sc->hw, &sc->hw_reset_work); } @@ -480,16 +477,16 @@ static void ath9k_beacon_init(struct ath_softc *sc, u32 next_beacon, u32 beacon_period) { - if (test_bit(SC_OP_TSF_RESET, &sc->sc_flags)) { + if (sc->sc_flags & SC_OP_TSF_RESET) { ath9k_ps_wakeup(sc); ath9k_hw_reset_tsf(sc->sc_ah); } ath9k_hw_beaconinit(sc->sc_ah, next_beacon, beacon_period); - if (test_bit(SC_OP_TSF_RESET, &sc->sc_flags)) { + if (sc->sc_flags & SC_OP_TSF_RESET) { ath9k_ps_restore(sc); - clear_bit(SC_OP_TSF_RESET, &sc->sc_flags); + sc->sc_flags &= ~SC_OP_TSF_RESET; } } @@ -519,7 +516,7 @@ static void ath_beacon_config_ap(struct ath_softc *sc, /* Set the computed AP beacon timers */ ath9k_hw_disable_interrupts(ah); - set_bit(SC_OP_TSF_RESET, &sc->sc_flags); + sc->sc_flags |= SC_OP_TSF_RESET; ath9k_beacon_init(sc, nexttbtt, intval); sc->beacon.bmisscnt = 0; ath9k_hw_set_interrupts(ah); @@ -662,7 +659,7 @@ static void ath_beacon_config_adhoc(struct ath_softc *sc, u32 tsf, intval, nexttbtt; ath9k_reset_beacon_status(sc); - if (!test_bit(SC_OP_BEACONS, &sc->sc_flags)) + if (!(sc->sc_flags & SC_OP_BEACONS)) ath9k_hw_settsf64(ah, sc->beacon.bc_tstamp); intval = TU_TO_USEC(conf->beacon_interval); @@ -727,7 +724,7 @@ static bool ath9k_allow_beacon_config(struct ath_softc *sc, */ if ((sc->sc_ah->opmode == NL80211_IFTYPE_STATION) && (vif->type == NL80211_IFTYPE_STATION) && - test_bit(SC_OP_BEACONS, &sc->sc_flags) && + (sc->sc_flags & SC_OP_BEACONS) && !avp->primary_sta_vif) { ath_dbg(common, CONFIG, "Beacon already configured for a station interface\n"); @@ -813,7 +810,7 @@ void ath_set_beacon(struct ath_softc *sc) return; } - set_bit(SC_OP_BEACONS, &sc->sc_flags); + sc->sc_flags |= SC_OP_BEACONS; } void ath9k_set_beaconing_status(struct ath_softc *sc, bool status) @@ -821,7 +818,7 @@ void ath9k_set_beaconing_status(struct ath_softc *sc, bool status) struct ath_hw *ah = sc->sc_ah; if (!ath_has_valid_bslot(sc)) { - clear_bit(SC_OP_BEACONS, &sc->sc_flags); + sc->sc_flags &= ~SC_OP_BEACONS; return; } diff --git a/trunk/drivers/net/wireless/ath/ath9k/btcoex.c b/trunk/drivers/net/wireless/ath/ath9k/btcoex.c index acd437384fe4..1ca6da80d4ad 100644 --- a/trunk/drivers/net/wireless/ath/ath9k/btcoex.c +++ b/trunk/drivers/net/wireless/ath/ath9k/btcoex.c @@ -336,16 +336,10 @@ static void ar9003_btcoex_bt_stomp(struct ath_hw *ah, enum ath_stomp_type stomp_type) { struct ath_btcoex_hw *btcoex = &ah->btcoex_hw; - const u32 *weight = ar9003_wlan_weights[stomp_type]; + const u32 *weight = AR_SREV_9462(ah) ? ar9003_wlan_weights[stomp_type] : + ar9462_wlan_weights[stomp_type]; int i; - if (AR_SREV_9462(ah)) { - if ((stomp_type == ATH_BTCOEX_STOMP_LOW) && - btcoex->mci.stomp_ftp) - stomp_type = ATH_BTCOEX_STOMP_LOW_FTP; - weight = ar9462_wlan_weights[stomp_type]; - } - for (i = 0; i < AR9300_NUM_WLAN_WEIGHTS; i++) { btcoex->bt_weight[i] = AR9300_BT_WGHT; btcoex->wlan_weight[i] = weight[i]; diff --git a/trunk/drivers/net/wireless/ath/ath9k/btcoex.h b/trunk/drivers/net/wireless/ath/ath9k/btcoex.h index 20092f98658f..3a1e1cfabd5e 100644 --- a/trunk/drivers/net/wireless/ath/ath9k/btcoex.h +++ b/trunk/drivers/net/wireless/ath/ath9k/btcoex.h @@ -36,9 +36,6 @@ #define ATH_BT_CNT_THRESHOLD 3 #define ATH_BT_CNT_SCAN_THRESHOLD 15 -#define ATH_BTCOEX_RX_WAIT_TIME 100 -#define ATH_BTCOEX_STOMP_FTP_THRESH 5 - #define AR9300_NUM_BT_WEIGHTS 4 #define AR9300_NUM_WLAN_WEIGHTS 4 /* Defines the BT AR_BT_COEX_WGHT used */ @@ -83,7 +80,6 @@ struct ath9k_hw_mci { u8 bt_ver_major; u8 bt_ver_minor; u8 bt_state; - u8 stomp_ftp; }; struct ath_btcoex_hw { diff --git a/trunk/drivers/net/wireless/ath/ath9k/debug.c b/trunk/drivers/net/wireless/ath/ath9k/debug.c index 2831258d9507..fde700c4e490 100644 --- a/trunk/drivers/net/wireless/ath/ath9k/debug.c +++ b/trunk/drivers/net/wireless/ath/ath9k/debug.c @@ -205,10 +205,10 @@ static ssize_t write_file_disable_ani(struct file *file, common->disable_ani = !!disable_ani; if (disable_ani) { - clear_bit(SC_OP_ANI_RUN, &sc->sc_flags); + sc->sc_flags &= ~SC_OP_ANI_RUN; del_timer_sync(&common->ani.timer); } else { - set_bit(SC_OP_ANI_RUN, &sc->sc_flags); + sc->sc_flags |= SC_OP_ANI_RUN; ath_start_ani(common); } @@ -374,8 +374,6 @@ void ath_debug_stat_interrupt(struct ath_softc *sc, enum ath9k_int status) sc->debug.stats.istats.dtim++; if (status & ATH9K_INT_TSFOOR) sc->debug.stats.istats.tsfoor++; - if (status & ATH9K_INT_MCI) - sc->debug.stats.istats.mci++; } static ssize_t read_file_interrupt(struct file *file, char __user *user_buf, @@ -420,7 +418,6 @@ static ssize_t read_file_interrupt(struct file *file, char __user *user_buf, PR_IS("DTIMSYNC", dtimsync); PR_IS("DTIM", dtim); PR_IS("TSFOOR", tsfoor); - PR_IS("MCI", mci); PR_IS("TOTAL", total); len += snprintf(buf + len, mxlen - len, @@ -1321,7 +1318,7 @@ static int open_file_bb_mac_samps(struct inode *inode, struct file *file) u8 chainmask = (ah->rxchainmask << 3) | ah->rxchainmask; u8 nread; - if (test_bit(SC_OP_INVALID, &sc->sc_flags)) + if (sc->sc_flags & SC_OP_INVALID) return -EAGAIN; buf = vmalloc(size); diff --git a/trunk/drivers/net/wireless/ath/ath9k/debug.h b/trunk/drivers/net/wireless/ath/ath9k/debug.h index d0f851cea43a..c34da09d9103 100644 --- a/trunk/drivers/net/wireless/ath/ath9k/debug.h +++ b/trunk/drivers/net/wireless/ath/ath9k/debug.h @@ -86,7 +86,6 @@ struct ath_interrupt_stats { u32 dtim; u32 bb_watchdog; u32 tsfoor; - u32 mci; /* Sync-cause stats */ u32 sync_cause_all; diff --git a/trunk/drivers/net/wireless/ath/ath9k/gpio.c b/trunk/drivers/net/wireless/ath/ath9k/gpio.c index af6d27350291..281a9af0f1b6 100644 --- a/trunk/drivers/net/wireless/ath/ath9k/gpio.c +++ b/trunk/drivers/net/wireless/ath/ath9k/gpio.c @@ -132,18 +132,17 @@ static void ath_detect_bt_priority(struct ath_softc *sc) if (time_after(jiffies, btcoex->bt_priority_time + msecs_to_jiffies(ATH_BT_PRIORITY_TIME_THRESHOLD))) { - clear_bit(BT_OP_PRIORITY_DETECTED, &btcoex->op_flags); - clear_bit(BT_OP_SCAN, &btcoex->op_flags); + sc->sc_flags &= ~(SC_OP_BT_PRIORITY_DETECTED | SC_OP_BT_SCAN); /* Detect if colocated bt started scanning */ if (btcoex->bt_priority_cnt >= ATH_BT_CNT_SCAN_THRESHOLD) { ath_dbg(ath9k_hw_common(sc->sc_ah), BTCOEX, "BT scan detected\n"); - set_bit(BT_OP_PRIORITY_DETECTED, &btcoex->op_flags); - set_bit(BT_OP_SCAN, &btcoex->op_flags); + sc->sc_flags |= (SC_OP_BT_SCAN | + SC_OP_BT_PRIORITY_DETECTED); } else if (btcoex->bt_priority_cnt >= ATH_BT_CNT_THRESHOLD) { ath_dbg(ath9k_hw_common(sc->sc_ah), BTCOEX, "BT priority traffic detected\n"); - set_bit(BT_OP_PRIORITY_DETECTED, &btcoex->op_flags); + sc->sc_flags |= SC_OP_BT_PRIORITY_DETECTED; } btcoex->bt_priority_cnt = 0; @@ -191,26 +190,13 @@ static void ath_btcoex_period_timer(unsigned long data) struct ath_softc *sc = (struct ath_softc *) data; struct ath_hw *ah = sc->sc_ah; struct ath_btcoex *btcoex = &sc->btcoex; - struct ath_mci_profile *mci = &btcoex->mci; u32 timer_period; bool is_btscan; ath9k_ps_wakeup(sc); if (!(ah->caps.hw_caps & ATH9K_HW_CAP_MCI)) ath_detect_bt_priority(sc); - is_btscan = test_bit(BT_OP_SCAN, &btcoex->op_flags); - - btcoex->bt_wait_time += btcoex->btcoex_period; - if (btcoex->bt_wait_time > ATH_BTCOEX_RX_WAIT_TIME) { - if (ar9003_mci_state(ah, MCI_STATE_NEED_FTP_STOMP, NULL) && - (mci->num_pan || mci->num_other_acl)) - ah->btcoex_hw.mci.stomp_ftp = - (sc->rx.num_pkts < ATH_BTCOEX_STOMP_FTP_THRESH); - else - ah->btcoex_hw.mci.stomp_ftp = false; - btcoex->bt_wait_time = 0; - sc->rx.num_pkts = 0; - } + is_btscan = sc->sc_flags & SC_OP_BT_SCAN; spin_lock_bh(&btcoex->btcoex_lock); @@ -233,7 +219,8 @@ static void ath_btcoex_period_timer(unsigned long data) ath9k_ps_restore(sc); timer_period = btcoex->btcoex_period / 1000; - mod_timer(&btcoex->period_timer, jiffies + msecs_to_jiffies(timer_period)); + mod_timer(&btcoex->period_timer, jiffies + + msecs_to_jiffies(timer_period)); } /* @@ -246,14 +233,14 @@ static void ath_btcoex_no_stomp_timer(void *arg) struct ath_hw *ah = sc->sc_ah; struct ath_btcoex *btcoex = &sc->btcoex; struct ath_common *common = ath9k_hw_common(ah); + bool is_btscan = sc->sc_flags & SC_OP_BT_SCAN; ath_dbg(common, BTCOEX, "no stomp timer running\n"); ath9k_ps_wakeup(sc); spin_lock_bh(&btcoex->btcoex_lock); - if (btcoex->bt_stomp_type == ATH_BTCOEX_STOMP_LOW || - test_bit(BT_OP_SCAN, &btcoex->op_flags)) + if (btcoex->bt_stomp_type == ATH_BTCOEX_STOMP_LOW || is_btscan) ath9k_hw_btcoex_bt_stomp(ah, ATH_BTCOEX_STOMP_NONE); else if (btcoex->bt_stomp_type == ATH_BTCOEX_STOMP_ALL) ath9k_hw_btcoex_bt_stomp(ah, ATH_BTCOEX_STOMP_LOW); @@ -305,7 +292,7 @@ void ath9k_btcoex_timer_resume(struct ath_softc *sc) btcoex->bt_priority_cnt = 0; btcoex->bt_priority_time = jiffies; - btcoex->op_flags &= ~(BT_OP_PRIORITY_DETECTED | BT_OP_SCAN); + sc->sc_flags &= ~(SC_OP_BT_PRIORITY_DETECTED | SC_OP_BT_SCAN); mod_timer(&btcoex->period_timer, jiffies); } @@ -329,13 +316,12 @@ void ath9k_btcoex_timer_pause(struct ath_softc *sc) u16 ath9k_btcoex_aggr_limit(struct ath_softc *sc, u32 max_4ms_framelen) { - struct ath_btcoex *btcoex = &sc->btcoex; struct ath_mci_profile *mci = &sc->btcoex.mci; u16 aggr_limit = 0; if ((sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_MCI) && mci->aggr_limit) aggr_limit = (max_4ms_framelen * mci->aggr_limit) >> 4; - else if (test_bit(BT_OP_PRIORITY_DETECTED, &btcoex->op_flags)) + else if (sc->sc_flags & SC_OP_BT_PRIORITY_DETECTED) aggr_limit = min((max_4ms_framelen * 3) / 8, (u32)ATH_AMPDU_LIMIT_MAX); diff --git a/trunk/drivers/net/wireless/ath/ath9k/hw.c b/trunk/drivers/net/wireless/ath/ath9k/hw.c index 45e670087e1c..7db1890448f2 100644 --- a/trunk/drivers/net/wireless/ath/ath9k/hw.c +++ b/trunk/drivers/net/wireless/ath/ath9k/hw.c @@ -390,6 +390,14 @@ static void ath9k_hw_disablepcie(struct ath_hw *ah) REG_WRITE(ah, AR_PCIE_SERDES2, 0x00000000); } +static void ath9k_hw_aspm_init(struct ath_hw *ah) +{ + struct ath_common *common = ath9k_hw_common(ah); + + if (common->bus_ops->aspm_init) + common->bus_ops->aspm_init(common); +} + /* This should work for all families including legacy */ static bool ath9k_hw_chip_test(struct ath_hw *ah) { @@ -685,6 +693,9 @@ static int __ath9k_hw_init(struct ath_hw *ah) if (r) return r; + if (ah->is_pciexpress) + ath9k_hw_aspm_init(ah); + r = ath9k_hw_init_macaddr(ah); if (r) { ath_err(common, "Failed to initialize MAC address\n"); @@ -1432,6 +1443,9 @@ static bool ath9k_hw_set_reset_reg(struct ath_hw *ah, u32 type) break; } + if (ah->caps.hw_caps & ATH9K_HW_CAP_MCI) + REG_WRITE(ah, AR_RTC_KEEP_AWAKE, 0x2); + return ret; } @@ -1707,7 +1721,7 @@ static int ath9k_hw_do_fastcc(struct ath_hw *ah, struct ath9k_channel *chan) ath9k_hw_loadnf(ah, ah->curchan); ath9k_hw_start_nfcal(ah, true); - if (ath9k_hw_mci_is_enabled(ah)) + if ((ah->caps.hw_caps & ATH9K_HW_CAP_MCI) && ar9003_mci_is_ready(ah)) ar9003_mci_2g5g_switch(ah, true); if (AR_SREV_9271(ah)) @@ -1728,9 +1742,10 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan, u64 tsf = 0; int i, r; bool start_mci_reset = false; + bool mci = !!(ah->caps.hw_caps & ATH9K_HW_CAP_MCI); bool save_fullsleep = ah->chip_fullsleep; - if (ath9k_hw_mci_is_enabled(ah)) { + if (mci) { start_mci_reset = ar9003_mci_start_reset(ah, chan); if (start_mci_reset) return 0; @@ -1759,7 +1774,7 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan, return r; } - if (ath9k_hw_mci_is_enabled(ah)) + if (mci) ar9003_mci_stop_bt(ah, save_fullsleep); saveDefAntenna = REG_READ(ah, AR_DEF_ANTENNA); @@ -1817,7 +1832,7 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan, if (r) return r; - if (ath9k_hw_mci_is_enabled(ah)) + if (mci) ar9003_mci_reset(ah, false, IS_CHAN_2GHZ(chan), save_fullsleep); /* @@ -1936,7 +1951,7 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan, ath9k_hw_loadnf(ah, chan); ath9k_hw_start_nfcal(ah, true); - if (ath9k_hw_mci_is_enabled(ah) && ar9003_mci_end_reset(ah, chan, caldata)) + if (mci && ar9003_mci_end_reset(ah, chan, caldata)) return -EIO; ENABLE_REGWRITE_BUFFER(ah); @@ -1981,7 +1996,7 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan, if (ath9k_hw_btcoex_is_enabled(ah)) ath9k_hw_btcoex_enable(ah); - if (ath9k_hw_mci_is_enabled(ah)) + if (mci) ar9003_mci_check_bt(ah); if (AR_SREV_9300_20_OR_LATER(ah)) { @@ -2004,35 +2019,39 @@ EXPORT_SYMBOL(ath9k_hw_reset); * Notify Power Mgt is disabled in self-generated frames. * If requested, force chip to sleep. */ -static void ath9k_set_power_sleep(struct ath_hw *ah) +static void ath9k_set_power_sleep(struct ath_hw *ah, int setChip) { REG_SET_BIT(ah, AR_STA_ID1, AR_STA_ID1_PWR_SAV); + if (setChip) { + if (AR_SREV_9462(ah)) { + REG_WRITE(ah, AR_TIMER_MODE, + REG_READ(ah, AR_TIMER_MODE) & 0xFFFFFF00); + REG_WRITE(ah, AR_NDP2_TIMER_MODE, REG_READ(ah, + AR_NDP2_TIMER_MODE) & 0xFFFFFF00); + REG_WRITE(ah, AR_SLP32_INC, + REG_READ(ah, AR_SLP32_INC) & 0xFFF00000); + /* xxx Required for WLAN only case ? */ + REG_WRITE(ah, AR_MCI_INTERRUPT_RX_MSG_EN, 0); + udelay(100); + } - if (AR_SREV_9462(ah)) { - REG_CLR_BIT(ah, AR_TIMER_MODE, 0xff); - REG_CLR_BIT(ah, AR_NDP2_TIMER_MODE, 0xff); - REG_CLR_BIT(ah, AR_SLP32_INC, 0xfffff); - /* xxx Required for WLAN only case ? */ - REG_WRITE(ah, AR_MCI_INTERRUPT_RX_MSG_EN, 0); - udelay(100); - } - - /* - * Clear the RTC force wake bit to allow the - * mac to go to sleep. - */ - REG_CLR_BIT(ah, AR_RTC_FORCE_WAKE, AR_RTC_FORCE_WAKE_EN); + /* + * Clear the RTC force wake bit to allow the + * mac to go to sleep. + */ + REG_CLR_BIT(ah, AR_RTC_FORCE_WAKE, AR_RTC_FORCE_WAKE_EN); - if (ath9k_hw_mci_is_enabled(ah)) - udelay(100); + if (AR_SREV_9462(ah)) + udelay(100); - if (!AR_SREV_9100(ah) && !AR_SREV_9300_20_OR_LATER(ah)) - REG_WRITE(ah, AR_RC, AR_RC_AHB | AR_RC_HOSTIF); + if (!AR_SREV_9100(ah) && !AR_SREV_9300_20_OR_LATER(ah)) + REG_WRITE(ah, AR_RC, AR_RC_AHB | AR_RC_HOSTIF); - /* Shutdown chip. Active low */ - if (!AR_SREV_5416(ah) && !AR_SREV_9271(ah)) { - REG_CLR_BIT(ah, AR_RTC_RESET, AR_RTC_RESET_EN); - udelay(2); + /* Shutdown chip. Active low */ + if (!AR_SREV_5416(ah) && !AR_SREV_9271(ah)) { + REG_CLR_BIT(ah, AR_RTC_RESET, AR_RTC_RESET_EN); + udelay(2); + } } /* Clear Bit 14 of AR_WA after putting chip into Full Sleep mode. */ @@ -2045,38 +2064,44 @@ static void ath9k_set_power_sleep(struct ath_hw *ah) * frames. If request, set power mode of chip to * auto/normal. Duration in units of 128us (1/8 TU). */ -static void ath9k_set_power_network_sleep(struct ath_hw *ah) +static void ath9k_set_power_network_sleep(struct ath_hw *ah, int setChip) { - struct ath9k_hw_capabilities *pCap = &ah->caps; + u32 val; REG_SET_BIT(ah, AR_STA_ID1, AR_STA_ID1_PWR_SAV); + if (setChip) { + struct ath9k_hw_capabilities *pCap = &ah->caps; - if (!(pCap->hw_caps & ATH9K_HW_CAP_AUTOSLEEP)) { - /* Set WakeOnInterrupt bit; clear ForceWake bit */ - REG_WRITE(ah, AR_RTC_FORCE_WAKE, - AR_RTC_FORCE_WAKE_ON_INT); - } else { - - /* When chip goes into network sleep, it could be waken - * up by MCI_INT interrupt caused by BT's HW messages - * (LNA_xxx, CONT_xxx) which chould be in a very fast - * rate (~100us). This will cause chip to leave and - * re-enter network sleep mode frequently, which in - * consequence will have WLAN MCI HW to generate lots of - * SYS_WAKING and SYS_SLEEPING messages which will make - * BT CPU to busy to process. - */ - if (ath9k_hw_mci_is_enabled(ah)) - REG_CLR_BIT(ah, AR_MCI_INTERRUPT_RX_MSG_EN, - AR_MCI_INTERRUPT_RX_HW_MSG_MASK); - /* - * Clear the RTC force wake bit to allow the - * mac to go to sleep. - */ - REG_CLR_BIT(ah, AR_RTC_FORCE_WAKE, AR_RTC_FORCE_WAKE_EN); + if (!(pCap->hw_caps & ATH9K_HW_CAP_AUTOSLEEP)) { + /* Set WakeOnInterrupt bit; clear ForceWake bit */ + REG_WRITE(ah, AR_RTC_FORCE_WAKE, + AR_RTC_FORCE_WAKE_ON_INT); + } else { - if (ath9k_hw_mci_is_enabled(ah)) - udelay(30); + /* When chip goes into network sleep, it could be waken + * up by MCI_INT interrupt caused by BT's HW messages + * (LNA_xxx, CONT_xxx) which chould be in a very fast + * rate (~100us). This will cause chip to leave and + * re-enter network sleep mode frequently, which in + * consequence will have WLAN MCI HW to generate lots of + * SYS_WAKING and SYS_SLEEPING messages which will make + * BT CPU to busy to process. + */ + if (AR_SREV_9462(ah)) { + val = REG_READ(ah, AR_MCI_INTERRUPT_RX_MSG_EN) & + ~AR_MCI_INTERRUPT_RX_HW_MSG_MASK; + REG_WRITE(ah, AR_MCI_INTERRUPT_RX_MSG_EN, val); + } + /* + * Clear the RTC force wake bit to allow the + * mac to go to sleep. + */ + REG_CLR_BIT(ah, AR_RTC_FORCE_WAKE, + AR_RTC_FORCE_WAKE_EN); + + if (AR_SREV_9462(ah)) + udelay(30); + } } /* Clear Bit 14 of AR_WA after putting chip into Net Sleep mode. */ @@ -2084,7 +2109,7 @@ static void ath9k_set_power_network_sleep(struct ath_hw *ah) REG_WRITE(ah, AR_WA, ah->WARegVal & ~AR_WA_D3_L1_DISABLE); } -static bool ath9k_hw_set_power_awake(struct ath_hw *ah) +static bool ath9k_hw_set_power_awake(struct ath_hw *ah, int setChip) { u32 val; int i; @@ -2095,35 +2120,37 @@ static bool ath9k_hw_set_power_awake(struct ath_hw *ah) udelay(10); } - if ((REG_READ(ah, AR_RTC_STATUS) & - AR_RTC_STATUS_M) == AR_RTC_STATUS_SHUTDOWN) { - if (!ath9k_hw_set_reset_reg(ah, ATH9K_RESET_POWER_ON)) { - return false; + if (setChip) { + if ((REG_READ(ah, AR_RTC_STATUS) & + AR_RTC_STATUS_M) == AR_RTC_STATUS_SHUTDOWN) { + if (!ath9k_hw_set_reset_reg(ah, ATH9K_RESET_POWER_ON)) { + return false; + } + if (!AR_SREV_9300_20_OR_LATER(ah)) + ath9k_hw_init_pll(ah, NULL); } - if (!AR_SREV_9300_20_OR_LATER(ah)) - ath9k_hw_init_pll(ah, NULL); - } - if (AR_SREV_9100(ah)) - REG_SET_BIT(ah, AR_RTC_RESET, - AR_RTC_RESET_EN); + if (AR_SREV_9100(ah)) + REG_SET_BIT(ah, AR_RTC_RESET, + AR_RTC_RESET_EN); - REG_SET_BIT(ah, AR_RTC_FORCE_WAKE, - AR_RTC_FORCE_WAKE_EN); - udelay(50); - - for (i = POWER_UP_TIME / 50; i > 0; i--) { - val = REG_READ(ah, AR_RTC_STATUS) & AR_RTC_STATUS_M; - if (val == AR_RTC_STATUS_ON) - break; - udelay(50); REG_SET_BIT(ah, AR_RTC_FORCE_WAKE, AR_RTC_FORCE_WAKE_EN); - } - if (i == 0) { - ath_err(ath9k_hw_common(ah), - "Failed to wakeup in %uus\n", - POWER_UP_TIME / 20); - return false; + udelay(50); + + for (i = POWER_UP_TIME / 50; i > 0; i--) { + val = REG_READ(ah, AR_RTC_STATUS) & AR_RTC_STATUS_M; + if (val == AR_RTC_STATUS_ON) + break; + udelay(50); + REG_SET_BIT(ah, AR_RTC_FORCE_WAKE, + AR_RTC_FORCE_WAKE_EN); + } + if (i == 0) { + ath_err(ath9k_hw_common(ah), + "Failed to wakeup in %uus\n", + POWER_UP_TIME / 20); + return false; + } } REG_CLR_BIT(ah, AR_STA_ID1, AR_STA_ID1_PWR_SAV); @@ -2134,7 +2161,7 @@ static bool ath9k_hw_set_power_awake(struct ath_hw *ah) bool ath9k_hw_setpower(struct ath_hw *ah, enum ath9k_power_mode mode) { struct ath_common *common = ath9k_hw_common(ah); - int status = true; + int status = true, setChip = true; static const char *modes[] = { "AWAKE", "FULL-SLEEP", @@ -2150,17 +2177,25 @@ bool ath9k_hw_setpower(struct ath_hw *ah, enum ath9k_power_mode mode) switch (mode) { case ATH9K_PM_AWAKE: - status = ath9k_hw_set_power_awake(ah); + status = ath9k_hw_set_power_awake(ah, setChip); + + if (ah->caps.hw_caps & ATH9K_HW_CAP_MCI) + REG_WRITE(ah, AR_RTC_KEEP_AWAKE, 0x2); + break; case ATH9K_PM_FULL_SLEEP: - if (ath9k_hw_mci_is_enabled(ah)) + if (ah->caps.hw_caps & ATH9K_HW_CAP_MCI) ar9003_mci_set_full_sleep(ah); - ath9k_set_power_sleep(ah); + ath9k_set_power_sleep(ah, setChip); ah->chip_fullsleep = true; break; case ATH9K_PM_NETWORK_SLEEP: - ath9k_set_power_network_sleep(ah); + + if (ah->caps.hw_caps & ATH9K_HW_CAP_MCI) + REG_WRITE(ah, AR_RTC_KEEP_AWAKE, 0x2); + + ath9k_set_power_network_sleep(ah, setChip); break; default: ath_err(common, "Unknown power mode %u\n", mode); @@ -2730,9 +2765,6 @@ EXPORT_SYMBOL(ath9k_hw_setrxfilter); bool ath9k_hw_phy_disable(struct ath_hw *ah) { - if (ath9k_hw_mci_is_enabled(ah)) - ar9003_mci_bt_gain_ctrl(ah); - if (!ath9k_hw_set_reset_reg(ah, ATH9K_RESET_WARM)) return false; diff --git a/trunk/drivers/net/wireless/ath/ath9k/hw.h b/trunk/drivers/net/wireless/ath/ath9k/hw.h index 03d590924c64..b620c557c2a6 100644 --- a/trunk/drivers/net/wireless/ath/ath9k/hw.h +++ b/trunk/drivers/net/wireless/ath/ath9k/hw.h @@ -824,6 +824,7 @@ struct ath_hw { struct ar5416IniArray ini_japan2484; struct ar5416IniArray iniModes_9271_ANI_reg; struct ar5416IniArray ini_radio_post_sys2ant; + struct ar5416IniArray ini_BTCOEX_MAX_TXPWR; struct ar5416IniArray iniMac[ATH_INI_NUM_SPLIT]; struct ar5416IniArray iniBB[ATH_INI_NUM_SPLIT]; @@ -1036,11 +1037,6 @@ static inline bool ath9k_hw_btcoex_is_enabled(struct ath_hw *ah) { return ah->btcoex_hw.enabled; } -static inline bool ath9k_hw_mci_is_enabled(struct ath_hw *ah) -{ - return ah->btcoex_hw.enabled && (ah->caps.hw_caps & ATH9K_HW_CAP_MCI); - -} void ath9k_hw_btcoex_enable(struct ath_hw *ah); static inline enum ath_btcoex_scheme ath9k_hw_get_btcoex_scheme(struct ath_hw *ah) @@ -1052,10 +1048,6 @@ static inline bool ath9k_hw_btcoex_is_enabled(struct ath_hw *ah) { return false; } -static inline bool ath9k_hw_mci_is_enabled(struct ath_hw *ah) -{ - return false; -} static inline void ath9k_hw_btcoex_enable(struct ath_hw *ah) { } diff --git a/trunk/drivers/net/wireless/ath/ath9k/init.c b/trunk/drivers/net/wireless/ath/ath9k/init.c index 9dfce1a69c73..dee9e092449a 100644 --- a/trunk/drivers/net/wireless/ath/ath9k/init.c +++ b/trunk/drivers/net/wireless/ath/ath9k/init.c @@ -489,7 +489,6 @@ static void ath9k_init_misc(struct ath_softc *sc) setup_timer(&common->ani.timer, ath_ani_calibrate, (unsigned long)sc); - sc->last_rssi = ATH_RSSI_DUMMY_MARKER; sc->config.txpowlimit = ATH_TXPOWER_MAX; memcpy(common->bssidmask, ath_bcast_mac, ETH_ALEN); sc->beacon.slottime = ATH9K_SLOT_TIME_9; @@ -561,12 +560,6 @@ static int ath9k_init_softc(u16 devid, struct ath_softc *sc, tasklet_init(&sc->bcon_tasklet, ath_beacon_tasklet, (unsigned long)sc); - INIT_WORK(&sc->hw_reset_work, ath_reset_work); - INIT_WORK(&sc->hw_check_work, ath_hw_check); - INIT_WORK(&sc->paprd_work, ath_paprd_calibrate); - INIT_DELAYED_WORK(&sc->hw_pll_work, ath_hw_pll_work); - setup_timer(&sc->rx_poll_timer, ath_rx_poll, (unsigned long)sc); - /* * Cache line size is used to size and align various * structures used to communicate with the hardware. @@ -597,9 +590,6 @@ static int ath9k_init_softc(u16 devid, struct ath_softc *sc, ath9k_cmn_init_crypto(sc->sc_ah); ath9k_init_misc(sc); - if (common->bus_ops->aspm_init) - common->bus_ops->aspm_init(common); - return 0; err_btcoex: @@ -792,6 +782,11 @@ int ath9k_init_device(u16 devid, struct ath_softc *sc, ARRAY_SIZE(ath9k_tpt_blink)); #endif + INIT_WORK(&sc->hw_reset_work, ath_reset_work); + INIT_WORK(&sc->hw_check_work, ath_hw_check); + INIT_WORK(&sc->paprd_work, ath_paprd_calibrate); + INIT_DELAYED_WORK(&sc->hw_pll_work, ath_hw_pll_work); + /* Register with mac80211 */ error = ieee80211_register_hw(hw); if (error) @@ -810,6 +805,9 @@ int ath9k_init_device(u16 devid, struct ath_softc *sc, goto error_world; } + setup_timer(&sc->rx_poll_timer, ath_rx_poll, (unsigned long)sc); + sc->last_rssi = ATH_RSSI_DUMMY_MARKER; + ath_init_leds(sc); ath_start_rfkill_poll(sc); diff --git a/trunk/drivers/net/wireless/ath/ath9k/link.c b/trunk/drivers/net/wireless/ath/ath9k/link.c deleted file mode 100644 index 0cc4c70f7f0c..000000000000 --- a/trunk/drivers/net/wireless/ath/ath9k/link.c +++ /dev/null @@ -1,502 +0,0 @@ -/* - * Copyright (c) 2012 Qualcomm Atheros, Inc. - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#include "ath9k.h" - -/* - * TX polling - checks if the TX engine is stuck somewhere - * and issues a chip reset if so. - */ -void ath_tx_complete_poll_work(struct work_struct *work) -{ - struct ath_softc *sc = container_of(work, struct ath_softc, - tx_complete_work.work); - struct ath_txq *txq; - int i; - bool needreset = false; -#ifdef CONFIG_ATH9K_DEBUGFS - sc->tx_complete_poll_work_seen++; -#endif - - for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++) - if (ATH_TXQ_SETUP(sc, i)) { - txq = &sc->tx.txq[i]; - ath_txq_lock(sc, txq); - if (txq->axq_depth) { - if (txq->axq_tx_inprogress) { - needreset = true; - ath_txq_unlock(sc, txq); - break; - } else { - txq->axq_tx_inprogress = true; - } - } - ath_txq_unlock_complete(sc, txq); - } - - if (needreset) { - ath_dbg(ath9k_hw_common(sc->sc_ah), RESET, - "tx hung, resetting the chip\n"); - RESET_STAT_INC(sc, RESET_TYPE_TX_HANG); - ieee80211_queue_work(sc->hw, &sc->hw_reset_work); - return; - } - - ieee80211_queue_delayed_work(sc->hw, &sc->tx_complete_work, - msecs_to_jiffies(ATH_TX_COMPLETE_POLL_INT)); -} - -/* - * Checks if the BB/MAC is hung. - */ -void ath_hw_check(struct work_struct *work) -{ - struct ath_softc *sc = container_of(work, struct ath_softc, hw_check_work); - struct ath_common *common = ath9k_hw_common(sc->sc_ah); - unsigned long flags; - int busy; - u8 is_alive, nbeacon = 1; - - ath9k_ps_wakeup(sc); - is_alive = ath9k_hw_check_alive(sc->sc_ah); - - if (is_alive && !AR_SREV_9300(sc->sc_ah)) - goto out; - else if (!is_alive && AR_SREV_9300(sc->sc_ah)) { - ath_dbg(common, RESET, - "DCU stuck is detected. Schedule chip reset\n"); - RESET_STAT_INC(sc, RESET_TYPE_MAC_HANG); - goto sched_reset; - } - - spin_lock_irqsave(&common->cc_lock, flags); - busy = ath_update_survey_stats(sc); - spin_unlock_irqrestore(&common->cc_lock, flags); - - ath_dbg(common, RESET, "Possible baseband hang, busy=%d (try %d)\n", - busy, sc->hw_busy_count + 1); - if (busy >= 99) { - if (++sc->hw_busy_count >= 3) { - RESET_STAT_INC(sc, RESET_TYPE_BB_HANG); - goto sched_reset; - } - } else if (busy >= 0) { - sc->hw_busy_count = 0; - nbeacon = 3; - } - - ath_start_rx_poll(sc, nbeacon); - goto out; - -sched_reset: - ieee80211_queue_work(sc->hw, &sc->hw_reset_work); -out: - ath9k_ps_restore(sc); -} - -/* - * PLL-WAR for AR9485/AR9340 - */ -static bool ath_hw_pll_rx_hang_check(struct ath_softc *sc, u32 pll_sqsum) -{ - static int count; - struct ath_common *common = ath9k_hw_common(sc->sc_ah); - - if (pll_sqsum >= 0x40000) { - count++; - if (count == 3) { - ath_dbg(common, RESET, "PLL WAR, resetting the chip\n"); - RESET_STAT_INC(sc, RESET_TYPE_PLL_HANG); - ieee80211_queue_work(sc->hw, &sc->hw_reset_work); - count = 0; - return true; - } - } else { - count = 0; - } - - return false; -} - -void ath_hw_pll_work(struct work_struct *work) -{ - u32 pll_sqsum; - struct ath_softc *sc = container_of(work, struct ath_softc, - hw_pll_work.work); - - ath9k_ps_wakeup(sc); - pll_sqsum = ar9003_get_pll_sqsum_dvc(sc->sc_ah); - ath9k_ps_restore(sc); - if (ath_hw_pll_rx_hang_check(sc, pll_sqsum)) - return; - - ieee80211_queue_delayed_work(sc->hw, &sc->hw_pll_work, - msecs_to_jiffies(ATH_PLL_WORK_INTERVAL)); -} - -/* - * RX Polling - monitors baseband hangs. - */ -void ath_start_rx_poll(struct ath_softc *sc, u8 nbeacon) -{ - if (!AR_SREV_9300(sc->sc_ah)) - return; - - if (!test_bit(SC_OP_PRIM_STA_VIF, &sc->sc_flags)) - return; - - mod_timer(&sc->rx_poll_timer, jiffies + msecs_to_jiffies - (nbeacon * sc->cur_beacon_conf.beacon_interval)); -} - -void ath_rx_poll(unsigned long data) -{ - struct ath_softc *sc = (struct ath_softc *)data; - - ieee80211_queue_work(sc->hw, &sc->hw_check_work); -} - -/* - * PA Pre-distortion. - */ -static void ath_paprd_activate(struct ath_softc *sc) -{ - struct ath_hw *ah = sc->sc_ah; - struct ath9k_hw_cal_data *caldata = ah->caldata; - int chain; - - if (!caldata || !caldata->paprd_done) - return; - - ath9k_ps_wakeup(sc); - ar9003_paprd_enable(ah, false); - for (chain = 0; chain < AR9300_MAX_CHAINS; chain++) { - if (!(ah->txchainmask & BIT(chain))) - continue; - - ar9003_paprd_populate_single_table(ah, caldata, chain); - } - - ar9003_paprd_enable(ah, true); - ath9k_ps_restore(sc); -} - -static bool ath_paprd_send_frame(struct ath_softc *sc, struct sk_buff *skb, int chain) -{ - struct ieee80211_hw *hw = sc->hw; - struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); - struct ath_hw *ah = sc->sc_ah; - struct ath_common *common = ath9k_hw_common(ah); - struct ath_tx_control txctl; - int time_left; - - memset(&txctl, 0, sizeof(txctl)); - txctl.txq = sc->tx.txq_map[WME_AC_BE]; - - memset(tx_info, 0, sizeof(*tx_info)); - tx_info->band = hw->conf.channel->band; - tx_info->flags |= IEEE80211_TX_CTL_NO_ACK; - tx_info->control.rates[0].idx = 0; - tx_info->control.rates[0].count = 1; - tx_info->control.rates[0].flags = IEEE80211_TX_RC_MCS; - tx_info->control.rates[1].idx = -1; - - init_completion(&sc->paprd_complete); - txctl.paprd = BIT(chain); - - if (ath_tx_start(hw, skb, &txctl) != 0) { - ath_dbg(common, CALIBRATE, "PAPRD TX failed\n"); - dev_kfree_skb_any(skb); - return false; - } - - time_left = wait_for_completion_timeout(&sc->paprd_complete, - msecs_to_jiffies(ATH_PAPRD_TIMEOUT)); - - if (!time_left) - ath_dbg(common, CALIBRATE, - "Timeout waiting for paprd training on TX chain %d\n", - chain); - - return !!time_left; -} - -void ath_paprd_calibrate(struct work_struct *work) -{ - struct ath_softc *sc = container_of(work, struct ath_softc, paprd_work); - struct ieee80211_hw *hw = sc->hw; - struct ath_hw *ah = sc->sc_ah; - struct ieee80211_hdr *hdr; - struct sk_buff *skb = NULL; - struct ath9k_hw_cal_data *caldata = ah->caldata; - struct ath_common *common = ath9k_hw_common(ah); - int ftype; - int chain_ok = 0; - int chain; - int len = 1800; - - if (!caldata) - return; - - ath9k_ps_wakeup(sc); - - if (ar9003_paprd_init_table(ah) < 0) - goto fail_paprd; - - skb = alloc_skb(len, GFP_KERNEL); - if (!skb) - goto fail_paprd; - - skb_put(skb, len); - memset(skb->data, 0, len); - hdr = (struct ieee80211_hdr *)skb->data; - ftype = IEEE80211_FTYPE_DATA | IEEE80211_STYPE_NULLFUNC; - hdr->frame_control = cpu_to_le16(ftype); - hdr->duration_id = cpu_to_le16(10); - memcpy(hdr->addr1, hw->wiphy->perm_addr, ETH_ALEN); - memcpy(hdr->addr2, hw->wiphy->perm_addr, ETH_ALEN); - memcpy(hdr->addr3, hw->wiphy->perm_addr, ETH_ALEN); - - for (chain = 0; chain < AR9300_MAX_CHAINS; chain++) { - if (!(ah->txchainmask & BIT(chain))) - continue; - - chain_ok = 0; - - ath_dbg(common, CALIBRATE, - "Sending PAPRD frame for thermal measurement on chain %d\n", - chain); - if (!ath_paprd_send_frame(sc, skb, chain)) - goto fail_paprd; - - ar9003_paprd_setup_gain_table(ah, chain); - - ath_dbg(common, CALIBRATE, - "Sending PAPRD training frame on chain %d\n", chain); - if (!ath_paprd_send_frame(sc, skb, chain)) - goto fail_paprd; - - if (!ar9003_paprd_is_done(ah)) { - ath_dbg(common, CALIBRATE, - "PAPRD not yet done on chain %d\n", chain); - break; - } - - if (ar9003_paprd_create_curve(ah, caldata, chain)) { - ath_dbg(common, CALIBRATE, - "PAPRD create curve failed on chain %d\n", - chain); - break; - } - - chain_ok = 1; - } - kfree_skb(skb); - - if (chain_ok) { - caldata->paprd_done = true; - ath_paprd_activate(sc); - } - -fail_paprd: - ath9k_ps_restore(sc); -} - -/* - * ANI performs periodic noise floor calibration - * that is used to adjust and optimize the chip performance. This - * takes environmental changes (location, temperature) into account. - * When the task is complete, it reschedules itself depending on the - * appropriate interval that was calculated. - */ -void ath_ani_calibrate(unsigned long data) -{ - struct ath_softc *sc = (struct ath_softc *)data; - struct ath_hw *ah = sc->sc_ah; - struct ath_common *common = ath9k_hw_common(ah); - bool longcal = false; - bool shortcal = false; - bool aniflag = false; - unsigned int timestamp = jiffies_to_msecs(jiffies); - u32 cal_interval, short_cal_interval, long_cal_interval; - unsigned long flags; - - if (ah->caldata && ah->caldata->nfcal_interference) - long_cal_interval = ATH_LONG_CALINTERVAL_INT; - else - long_cal_interval = ATH_LONG_CALINTERVAL; - - short_cal_interval = (ah->opmode == NL80211_IFTYPE_AP) ? - ATH_AP_SHORT_CALINTERVAL : ATH_STA_SHORT_CALINTERVAL; - - /* Only calibrate if awake */ - if (sc->sc_ah->power_mode != ATH9K_PM_AWAKE) - goto set_timer; - - ath9k_ps_wakeup(sc); - - /* Long calibration runs independently of short calibration. */ - if ((timestamp - common->ani.longcal_timer) >= long_cal_interval) { - longcal = true; - common->ani.longcal_timer = timestamp; - } - - /* Short calibration applies only while caldone is false */ - if (!common->ani.caldone) { - if ((timestamp - common->ani.shortcal_timer) >= short_cal_interval) { - shortcal = true; - common->ani.shortcal_timer = timestamp; - common->ani.resetcal_timer = timestamp; - } - } else { - if ((timestamp - common->ani.resetcal_timer) >= - ATH_RESTART_CALINTERVAL) { - common->ani.caldone = ath9k_hw_reset_calvalid(ah); - if (common->ani.caldone) - common->ani.resetcal_timer = timestamp; - } - } - - /* Verify whether we must check ANI */ - if (sc->sc_ah->config.enable_ani - && (timestamp - common->ani.checkani_timer) >= - ah->config.ani_poll_interval) { - aniflag = true; - common->ani.checkani_timer = timestamp; - } - - /* Call ANI routine if necessary */ - if (aniflag) { - spin_lock_irqsave(&common->cc_lock, flags); - ath9k_hw_ani_monitor(ah, ah->curchan); - ath_update_survey_stats(sc); - spin_unlock_irqrestore(&common->cc_lock, flags); - } - - /* Perform calibration if necessary */ - if (longcal || shortcal) { - common->ani.caldone = - ath9k_hw_calibrate(ah, ah->curchan, - ah->rxchainmask, longcal); - } - - ath_dbg(common, ANI, - "Calibration @%lu finished: %s %s %s, caldone: %s\n", - jiffies, - longcal ? "long" : "", shortcal ? "short" : "", - aniflag ? "ani" : "", common->ani.caldone ? "true" : "false"); - - ath9k_ps_restore(sc); - -set_timer: - /* - * Set timer interval based on previous results. - * The interval must be the shortest necessary to satisfy ANI, - * short calibration and long calibration. - */ - ath9k_debug_samp_bb_mac(sc); - cal_interval = ATH_LONG_CALINTERVAL; - if (sc->sc_ah->config.enable_ani) - cal_interval = min(cal_interval, - (u32)ah->config.ani_poll_interval); - if (!common->ani.caldone) - cal_interval = min(cal_interval, (u32)short_cal_interval); - - mod_timer(&common->ani.timer, jiffies + msecs_to_jiffies(cal_interval)); - if ((sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_PAPRD) && ah->caldata) { - if (!ah->caldata->paprd_done) - ieee80211_queue_work(sc->hw, &sc->paprd_work); - else if (!ah->paprd_table_write_done) - ath_paprd_activate(sc); - } -} - -void ath_start_ani(struct ath_common *common) -{ - struct ath_hw *ah = common->ah; - unsigned long timestamp = jiffies_to_msecs(jiffies); - struct ath_softc *sc = (struct ath_softc *) common->priv; - - if (!test_bit(SC_OP_ANI_RUN, &sc->sc_flags)) - return; - - if (sc->hw->conf.flags & IEEE80211_CONF_OFFCHANNEL) - return; - - common->ani.longcal_timer = timestamp; - common->ani.shortcal_timer = timestamp; - common->ani.checkani_timer = timestamp; - - mod_timer(&common->ani.timer, - jiffies + msecs_to_jiffies((u32)ah->config.ani_poll_interval)); -} - -void ath_update_survey_nf(struct ath_softc *sc, int channel) -{ - struct ath_hw *ah = sc->sc_ah; - struct ath9k_channel *chan = &ah->channels[channel]; - struct survey_info *survey = &sc->survey[channel]; - - if (chan->noisefloor) { - survey->filled |= SURVEY_INFO_NOISE_DBM; - survey->noise = ath9k_hw_getchan_noise(ah, chan); - } -} - -/* - * Updates the survey statistics and returns the busy time since last - * update in %, if the measurement duration was long enough for the - * result to be useful, -1 otherwise. - */ -int ath_update_survey_stats(struct ath_softc *sc) -{ - struct ath_hw *ah = sc->sc_ah; - struct ath_common *common = ath9k_hw_common(ah); - int pos = ah->curchan - &ah->channels[0]; - struct survey_info *survey = &sc->survey[pos]; - struct ath_cycle_counters *cc = &common->cc_survey; - unsigned int div = common->clockrate * 1000; - int ret = 0; - - if (!ah->curchan) - return -1; - - if (ah->power_mode == ATH9K_PM_AWAKE) - ath_hw_cycle_counters_update(common); - - if (cc->cycles > 0) { - survey->filled |= SURVEY_INFO_CHANNEL_TIME | - SURVEY_INFO_CHANNEL_TIME_BUSY | - SURVEY_INFO_CHANNEL_TIME_RX | - SURVEY_INFO_CHANNEL_TIME_TX; - survey->channel_time += cc->cycles / div; - survey->channel_time_busy += cc->rx_busy / div; - survey->channel_time_rx += cc->rx_frame / div; - survey->channel_time_tx += cc->tx_frame / div; - } - - if (cc->cycles < div) - return -1; - - if (cc->cycles > 0) - ret = cc->rx_busy * 100 / cc->cycles; - - memset(cc, 0, sizeof(*cc)); - - ath_update_survey_nf(sc, pos); - - return ret; -} diff --git a/trunk/drivers/net/wireless/ath/ath9k/main.c b/trunk/drivers/net/wireless/ath/ath9k/main.c index c0f478b0a9a2..cfbcc047c61e 100644 --- a/trunk/drivers/net/wireless/ath/ath9k/main.c +++ b/trunk/drivers/net/wireless/ath/ath9k/main.c @@ -101,7 +101,6 @@ void ath9k_ps_wakeup(struct ath_softc *sc) spin_lock(&common->cc_lock); ath_hw_cycle_counters_update(common); memset(&common->cc_survey, 0, sizeof(common->cc_survey)); - memset(&common->cc_ani, 0, sizeof(common->cc_ani)); spin_unlock(&common->cc_lock); } @@ -144,6 +143,84 @@ void ath9k_ps_restore(struct ath_softc *sc) spin_unlock_irqrestore(&sc->sc_pm_lock, flags); } +void ath_start_ani(struct ath_common *common) +{ + struct ath_hw *ah = common->ah; + unsigned long timestamp = jiffies_to_msecs(jiffies); + struct ath_softc *sc = (struct ath_softc *) common->priv; + + if (!(sc->sc_flags & SC_OP_ANI_RUN)) + return; + + if (sc->sc_flags & SC_OP_OFFCHANNEL) + return; + + common->ani.longcal_timer = timestamp; + common->ani.shortcal_timer = timestamp; + common->ani.checkani_timer = timestamp; + + mod_timer(&common->ani.timer, + jiffies + + msecs_to_jiffies((u32)ah->config.ani_poll_interval)); +} + +static void ath_update_survey_nf(struct ath_softc *sc, int channel) +{ + struct ath_hw *ah = sc->sc_ah; + struct ath9k_channel *chan = &ah->channels[channel]; + struct survey_info *survey = &sc->survey[channel]; + + if (chan->noisefloor) { + survey->filled |= SURVEY_INFO_NOISE_DBM; + survey->noise = ath9k_hw_getchan_noise(ah, chan); + } +} + +/* + * Updates the survey statistics and returns the busy time since last + * update in %, if the measurement duration was long enough for the + * result to be useful, -1 otherwise. + */ +static int ath_update_survey_stats(struct ath_softc *sc) +{ + struct ath_hw *ah = sc->sc_ah; + struct ath_common *common = ath9k_hw_common(ah); + int pos = ah->curchan - &ah->channels[0]; + struct survey_info *survey = &sc->survey[pos]; + struct ath_cycle_counters *cc = &common->cc_survey; + unsigned int div = common->clockrate * 1000; + int ret = 0; + + if (!ah->curchan) + return -1; + + if (ah->power_mode == ATH9K_PM_AWAKE) + ath_hw_cycle_counters_update(common); + + if (cc->cycles > 0) { + survey->filled |= SURVEY_INFO_CHANNEL_TIME | + SURVEY_INFO_CHANNEL_TIME_BUSY | + SURVEY_INFO_CHANNEL_TIME_RX | + SURVEY_INFO_CHANNEL_TIME_TX; + survey->channel_time += cc->cycles / div; + survey->channel_time_busy += cc->rx_busy / div; + survey->channel_time_rx += cc->rx_frame / div; + survey->channel_time_tx += cc->tx_frame / div; + } + + if (cc->cycles < div) + return -1; + + if (cc->cycles > 0) + ret = cc->rx_busy * 100 / cc->cycles; + + memset(cc, 0, sizeof(*cc)); + + ath_update_survey_nf(sc, pos); + + return ret; +} + static void __ath_cancel_work(struct ath_softc *sc) { cancel_work_sync(&sc->paprd_work); @@ -158,22 +235,6 @@ static void ath_cancel_work(struct ath_softc *sc) cancel_work_sync(&sc->hw_reset_work); } -static void ath_restart_work(struct ath_softc *sc) -{ - struct ath_common *common = ath9k_hw_common(sc->sc_ah); - - ieee80211_queue_delayed_work(sc->hw, &sc->tx_complete_work, 0); - - if (AR_SREV_9485(sc->sc_ah) || AR_SREV_9340(sc->sc_ah)) - ieee80211_queue_delayed_work(sc->hw, &sc->hw_pll_work, - msecs_to_jiffies(ATH_PLL_WORK_INTERVAL)); - - ath_start_rx_poll(sc, 3); - - if (!common->disable_ani) - ath_start_ani(common); -} - static bool ath_prepare_reset(struct ath_softc *sc, bool retry_tx, bool flush) { struct ath_hw *ah = sc->sc_ah; @@ -210,7 +271,6 @@ static bool ath_complete_reset(struct ath_softc *sc, bool start) { struct ath_hw *ah = sc->sc_ah; struct ath_common *common = ath9k_hw_common(ah); - unsigned long flags; if (ath_startrecv(sc) != 0) { ath_err(common, "Unable to restart recv logic\n"); @@ -219,29 +279,35 @@ static bool ath_complete_reset(struct ath_softc *sc, bool start) ath9k_cmn_update_txpow(ah, sc->curtxpow, sc->config.txpowlimit, &sc->curtxpow); - - clear_bit(SC_OP_HW_RESET, &sc->sc_flags); ath9k_hw_set_interrupts(ah); ath9k_hw_enable_interrupts(ah); - if (!(sc->hw->conf.flags & IEEE80211_CONF_OFFCHANNEL) && start) { - if (!test_bit(SC_OP_BEACONS, &sc->sc_flags)) - goto work; - - ath_set_beacon(sc); + if (!(sc->sc_flags & (SC_OP_OFFCHANNEL)) && start) { + if (sc->sc_flags & SC_OP_BEACONS) + ath_set_beacon(sc); - if (ah->opmode == NL80211_IFTYPE_STATION && - test_bit(SC_OP_PRIM_STA_VIF, &sc->sc_flags)) { - spin_lock_irqsave(&sc->sc_pm_lock, flags); - sc->ps_flags |= PS_BEACON_SYNC | PS_WAIT_FOR_BEACON; - spin_unlock_irqrestore(&sc->sc_pm_lock, flags); - } - work: - ath_restart_work(sc); + ieee80211_queue_delayed_work(sc->hw, &sc->tx_complete_work, 0); + ieee80211_queue_delayed_work(sc->hw, &sc->hw_pll_work, HZ/2); + ath_start_rx_poll(sc, 3); + if (!common->disable_ani) + ath_start_ani(common); } - if ((ah->caps.hw_caps & ATH9K_HW_CAP_ANT_DIV_COMB) && sc->ant_rx != 3) - ath_ant_comb_update(sc); + if ((ah->caps.hw_caps & ATH9K_HW_CAP_ANT_DIV_COMB) && sc->ant_rx != 3) { + struct ath_hw_antcomb_conf div_ant_conf; + u8 lna_conf; + + ath9k_hw_antdiv_comb_conf_get(ah, &div_ant_conf); + + if (sc->ant_rx == 1) + lna_conf = ATH_ANT_DIV_COMB_LNA1; + else + lna_conf = ATH_ANT_DIV_COMB_LNA2; + div_ant_conf.main_lna_conf = lna_conf; + div_ant_conf.alt_lna_conf = lna_conf; + + ath9k_hw_antdiv_comb_conf_set(ah, &div_ant_conf); + } ieee80211_wake_queues(sc->hw); @@ -262,7 +328,7 @@ static int ath_reset_internal(struct ath_softc *sc, struct ath9k_channel *hchan, spin_lock_bh(&sc->sc_pcu_lock); - if (!(sc->hw->conf.flags & IEEE80211_CONF_OFFCHANNEL)) { + if (!(sc->sc_flags & SC_OP_OFFCHANNEL)) { fastcc = false; caldata = &sc->caldata; } @@ -305,7 +371,7 @@ static int ath_set_channel(struct ath_softc *sc, struct ieee80211_hw *hw, { int r; - if (test_bit(SC_OP_INVALID, &sc->sc_flags)) + if (sc->sc_flags & SC_OP_INVALID) return -EIO; r = ath_reset_internal(sc, hchan, false); @@ -313,6 +379,258 @@ static int ath_set_channel(struct ath_softc *sc, struct ieee80211_hw *hw, return r; } +static void ath_paprd_activate(struct ath_softc *sc) +{ + struct ath_hw *ah = sc->sc_ah; + struct ath9k_hw_cal_data *caldata = ah->caldata; + int chain; + + if (!caldata || !caldata->paprd_done) + return; + + ath9k_ps_wakeup(sc); + ar9003_paprd_enable(ah, false); + for (chain = 0; chain < AR9300_MAX_CHAINS; chain++) { + if (!(ah->txchainmask & BIT(chain))) + continue; + + ar9003_paprd_populate_single_table(ah, caldata, chain); + } + + ar9003_paprd_enable(ah, true); + ath9k_ps_restore(sc); +} + +static bool ath_paprd_send_frame(struct ath_softc *sc, struct sk_buff *skb, int chain) +{ + struct ieee80211_hw *hw = sc->hw; + struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); + struct ath_hw *ah = sc->sc_ah; + struct ath_common *common = ath9k_hw_common(ah); + struct ath_tx_control txctl; + int time_left; + + memset(&txctl, 0, sizeof(txctl)); + txctl.txq = sc->tx.txq_map[WME_AC_BE]; + + memset(tx_info, 0, sizeof(*tx_info)); + tx_info->band = hw->conf.channel->band; + tx_info->flags |= IEEE80211_TX_CTL_NO_ACK; + tx_info->control.rates[0].idx = 0; + tx_info->control.rates[0].count = 1; + tx_info->control.rates[0].flags = IEEE80211_TX_RC_MCS; + tx_info->control.rates[1].idx = -1; + + init_completion(&sc->paprd_complete); + txctl.paprd = BIT(chain); + + if (ath_tx_start(hw, skb, &txctl) != 0) { + ath_dbg(common, CALIBRATE, "PAPRD TX failed\n"); + dev_kfree_skb_any(skb); + return false; + } + + time_left = wait_for_completion_timeout(&sc->paprd_complete, + msecs_to_jiffies(ATH_PAPRD_TIMEOUT)); + + if (!time_left) + ath_dbg(common, CALIBRATE, + "Timeout waiting for paprd training on TX chain %d\n", + chain); + + return !!time_left; +} + +void ath_paprd_calibrate(struct work_struct *work) +{ + struct ath_softc *sc = container_of(work, struct ath_softc, paprd_work); + struct ieee80211_hw *hw = sc->hw; + struct ath_hw *ah = sc->sc_ah; + struct ieee80211_hdr *hdr; + struct sk_buff *skb = NULL; + struct ath9k_hw_cal_data *caldata = ah->caldata; + struct ath_common *common = ath9k_hw_common(ah); + int ftype; + int chain_ok = 0; + int chain; + int len = 1800; + + if (!caldata) + return; + + ath9k_ps_wakeup(sc); + + if (ar9003_paprd_init_table(ah) < 0) + goto fail_paprd; + + skb = alloc_skb(len, GFP_KERNEL); + if (!skb) + goto fail_paprd; + + skb_put(skb, len); + memset(skb->data, 0, len); + hdr = (struct ieee80211_hdr *)skb->data; + ftype = IEEE80211_FTYPE_DATA | IEEE80211_STYPE_NULLFUNC; + hdr->frame_control = cpu_to_le16(ftype); + hdr->duration_id = cpu_to_le16(10); + memcpy(hdr->addr1, hw->wiphy->perm_addr, ETH_ALEN); + memcpy(hdr->addr2, hw->wiphy->perm_addr, ETH_ALEN); + memcpy(hdr->addr3, hw->wiphy->perm_addr, ETH_ALEN); + + for (chain = 0; chain < AR9300_MAX_CHAINS; chain++) { + if (!(ah->txchainmask & BIT(chain))) + continue; + + chain_ok = 0; + + ath_dbg(common, CALIBRATE, + "Sending PAPRD frame for thermal measurement on chain %d\n", + chain); + if (!ath_paprd_send_frame(sc, skb, chain)) + goto fail_paprd; + + ar9003_paprd_setup_gain_table(ah, chain); + + ath_dbg(common, CALIBRATE, + "Sending PAPRD training frame on chain %d\n", chain); + if (!ath_paprd_send_frame(sc, skb, chain)) + goto fail_paprd; + + if (!ar9003_paprd_is_done(ah)) { + ath_dbg(common, CALIBRATE, + "PAPRD not yet done on chain %d\n", chain); + break; + } + + if (ar9003_paprd_create_curve(ah, caldata, chain)) { + ath_dbg(common, CALIBRATE, + "PAPRD create curve failed on chain %d\n", + chain); + break; + } + + chain_ok = 1; + } + kfree_skb(skb); + + if (chain_ok) { + caldata->paprd_done = true; + ath_paprd_activate(sc); + } + +fail_paprd: + ath9k_ps_restore(sc); +} + +/* + * This routine performs the periodic noise floor calibration function + * that is used to adjust and optimize the chip performance. This + * takes environmental changes (location, temperature) into account. + * When the task is complete, it reschedules itself depending on the + * appropriate interval that was calculated. + */ +void ath_ani_calibrate(unsigned long data) +{ + struct ath_softc *sc = (struct ath_softc *)data; + struct ath_hw *ah = sc->sc_ah; + struct ath_common *common = ath9k_hw_common(ah); + bool longcal = false; + bool shortcal = false; + bool aniflag = false; + unsigned int timestamp = jiffies_to_msecs(jiffies); + u32 cal_interval, short_cal_interval, long_cal_interval; + unsigned long flags; + + if (ah->caldata && ah->caldata->nfcal_interference) + long_cal_interval = ATH_LONG_CALINTERVAL_INT; + else + long_cal_interval = ATH_LONG_CALINTERVAL; + + short_cal_interval = (ah->opmode == NL80211_IFTYPE_AP) ? + ATH_AP_SHORT_CALINTERVAL : ATH_STA_SHORT_CALINTERVAL; + + /* Only calibrate if awake */ + if (sc->sc_ah->power_mode != ATH9K_PM_AWAKE) + goto set_timer; + + ath9k_ps_wakeup(sc); + + /* Long calibration runs independently of short calibration. */ + if ((timestamp - common->ani.longcal_timer) >= long_cal_interval) { + longcal = true; + common->ani.longcal_timer = timestamp; + } + + /* Short calibration applies only while caldone is false */ + if (!common->ani.caldone) { + if ((timestamp - common->ani.shortcal_timer) >= short_cal_interval) { + shortcal = true; + common->ani.shortcal_timer = timestamp; + common->ani.resetcal_timer = timestamp; + } + } else { + if ((timestamp - common->ani.resetcal_timer) >= + ATH_RESTART_CALINTERVAL) { + common->ani.caldone = ath9k_hw_reset_calvalid(ah); + if (common->ani.caldone) + common->ani.resetcal_timer = timestamp; + } + } + + /* Verify whether we must check ANI */ + if (sc->sc_ah->config.enable_ani + && (timestamp - common->ani.checkani_timer) >= + ah->config.ani_poll_interval) { + aniflag = true; + common->ani.checkani_timer = timestamp; + } + + /* Call ANI routine if necessary */ + if (aniflag) { + spin_lock_irqsave(&common->cc_lock, flags); + ath9k_hw_ani_monitor(ah, ah->curchan); + ath_update_survey_stats(sc); + spin_unlock_irqrestore(&common->cc_lock, flags); + } + + /* Perform calibration if necessary */ + if (longcal || shortcal) { + common->ani.caldone = + ath9k_hw_calibrate(ah, ah->curchan, + ah->rxchainmask, longcal); + } + + ath_dbg(common, ANI, + "Calibration @%lu finished: %s %s %s, caldone: %s\n", + jiffies, + longcal ? "long" : "", shortcal ? "short" : "", + aniflag ? "ani" : "", common->ani.caldone ? "true" : "false"); + + ath9k_ps_restore(sc); + +set_timer: + /* + * Set timer interval based on previous results. + * The interval must be the shortest necessary to satisfy ANI, + * short calibration and long calibration. + */ + ath9k_debug_samp_bb_mac(sc); + cal_interval = ATH_LONG_CALINTERVAL; + if (sc->sc_ah->config.enable_ani) + cal_interval = min(cal_interval, + (u32)ah->config.ani_poll_interval); + if (!common->ani.caldone) + cal_interval = min(cal_interval, (u32)short_cal_interval); + + mod_timer(&common->ani.timer, jiffies + msecs_to_jiffies(cal_interval)); + if ((sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_PAPRD) && ah->caldata) { + if (!ah->caldata->paprd_done) + ieee80211_queue_work(sc->hw, &sc->paprd_work); + else if (!ah->paprd_table_write_done) + ath_paprd_activate(sc); + } +} + static void ath_node_attach(struct ath_softc *sc, struct ieee80211_sta *sta, struct ieee80211_vif *vif) { @@ -350,12 +668,13 @@ static void ath_node_detach(struct ath_softc *sc, struct ieee80211_sta *sta) ath_tx_node_cleanup(sc, an); } + void ath9k_tasklet(unsigned long data) { struct ath_softc *sc = (struct ath_softc *)data; struct ath_hw *ah = sc->sc_ah; struct ath_common *common = ath9k_hw_common(ah); - unsigned long flags; + u32 status = sc->intrstatus; u32 rxmask; @@ -374,12 +693,10 @@ void ath9k_tasklet(unsigned long data) RESET_STAT_INC(sc, type); #endif - set_bit(SC_OP_HW_RESET, &sc->sc_flags); ieee80211_queue_work(sc->hw, &sc->hw_reset_work); goto out; } - spin_lock_irqsave(&sc->sc_pm_lock, flags); if ((status & ATH9K_INT_TSFOOR) && sc->ps_enabled) { /* * TSF sync does not look correct; remain awake to sync with @@ -388,7 +705,6 @@ void ath9k_tasklet(unsigned long data) ath_dbg(common, PS, "TSFOOR - Sync with next Beacon\n"); sc->ps_flags |= PS_WAIT_FOR_BEACON | PS_BEACON_SYNC; } - spin_unlock_irqrestore(&sc->sc_pm_lock, flags); if (ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) rxmask = (ATH9K_INT_RXHP | ATH9K_INT_RXLP | ATH9K_INT_RXEOL | @@ -450,17 +766,15 @@ irqreturn_t ath_isr(int irq, void *dev) * touch anything. Note this can happen early * on if the IRQ is shared. */ - if (test_bit(SC_OP_INVALID, &sc->sc_flags)) + if (sc->sc_flags & SC_OP_INVALID) return IRQ_NONE; + /* shared irq, not for us */ if (!ath9k_hw_intrpend(ah)) return IRQ_NONE; - if(test_bit(SC_OP_HW_RESET, &sc->sc_flags)) - return IRQ_HANDLED; - /* * Figure out the reason(s) for the interrupt. Note * that the hal returns a pseudo-ISR that may include @@ -538,10 +852,8 @@ irqreturn_t ath_isr(int irq, void *dev) /* Clear RxAbort bit so that we can * receive frames */ ath9k_setpower(sc, ATH9K_PM_AWAKE); - spin_lock(&sc->sc_pm_lock); ath9k_hw_setrxabort(sc->sc_ah, 0); sc->ps_flags |= PS_WAIT_FOR_BEACON; - spin_unlock(&sc->sc_pm_lock); } chip_reset: @@ -590,6 +902,87 @@ void ath_reset_work(struct work_struct *work) ath_reset(sc, true); } +void ath_hw_check(struct work_struct *work) +{ + struct ath_softc *sc = container_of(work, struct ath_softc, hw_check_work); + struct ath_common *common = ath9k_hw_common(sc->sc_ah); + unsigned long flags; + int busy; + u8 is_alive, nbeacon = 1; + + ath9k_ps_wakeup(sc); + is_alive = ath9k_hw_check_alive(sc->sc_ah); + + if (is_alive && !AR_SREV_9300(sc->sc_ah)) + goto out; + else if (!is_alive && AR_SREV_9300(sc->sc_ah)) { + ath_dbg(common, RESET, + "DCU stuck is detected. Schedule chip reset\n"); + RESET_STAT_INC(sc, RESET_TYPE_MAC_HANG); + goto sched_reset; + } + + spin_lock_irqsave(&common->cc_lock, flags); + busy = ath_update_survey_stats(sc); + spin_unlock_irqrestore(&common->cc_lock, flags); + + ath_dbg(common, RESET, "Possible baseband hang, busy=%d (try %d)\n", + busy, sc->hw_busy_count + 1); + if (busy >= 99) { + if (++sc->hw_busy_count >= 3) { + RESET_STAT_INC(sc, RESET_TYPE_BB_HANG); + goto sched_reset; + } + } else if (busy >= 0) { + sc->hw_busy_count = 0; + nbeacon = 3; + } + + ath_start_rx_poll(sc, nbeacon); + goto out; + +sched_reset: + ieee80211_queue_work(sc->hw, &sc->hw_reset_work); +out: + ath9k_ps_restore(sc); +} + +static void ath_hw_pll_rx_hang_check(struct ath_softc *sc, u32 pll_sqsum) +{ + static int count; + struct ath_common *common = ath9k_hw_common(sc->sc_ah); + + if (pll_sqsum >= 0x40000) { + count++; + if (count == 3) { + /* Rx is hung for more than 500ms. Reset it */ + ath_dbg(common, RESET, "Possible RX hang, resetting\n"); + RESET_STAT_INC(sc, RESET_TYPE_PLL_HANG); + ieee80211_queue_work(sc->hw, &sc->hw_reset_work); + count = 0; + } + } else + count = 0; +} + +void ath_hw_pll_work(struct work_struct *work) +{ + struct ath_softc *sc = container_of(work, struct ath_softc, + hw_pll_work.work); + u32 pll_sqsum; + + if (AR_SREV_9485(sc->sc_ah)) { + + ath9k_ps_wakeup(sc); + pll_sqsum = ar9003_get_pll_sqsum_dvc(sc->sc_ah); + ath9k_ps_restore(sc); + + ath_hw_pll_rx_hang_check(sc, pll_sqsum); + + ieee80211_queue_delayed_work(sc->hw, &sc->hw_pll_work, HZ/5); + } +} + /**********************/ /* mac80211 callbacks */ /**********************/ @@ -652,9 +1045,10 @@ static int ath9k_start(struct ieee80211_hw *hw) if (ah->caps.hw_caps & ATH9K_HW_CAP_HT) ah->imask |= ATH9K_INT_CST; - ath_mci_enable(sc); + if (ah->caps.hw_caps & ATH9K_HW_CAP_MCI) + ah->imask |= ATH9K_INT_MCI; - clear_bit(SC_OP_INVALID, &sc->sc_flags); + sc->sc_flags &= ~SC_OP_INVALID; sc->sc_ah->is_monitoring = false; if (!ath_complete_reset(sc, false)) { @@ -696,7 +1090,6 @@ static void ath9k_tx(struct ieee80211_hw *hw, struct sk_buff *skb) struct ath_common *common = ath9k_hw_common(sc->sc_ah); struct ath_tx_control txctl; struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; - unsigned long flags; if (sc->ps_enabled) { /* @@ -719,7 +1112,6 @@ static void ath9k_tx(struct ieee80211_hw *hw, struct sk_buff *skb) * completed and if needed, also for RX of buffered frames. */ ath9k_ps_wakeup(sc); - spin_lock_irqsave(&sc->sc_pm_lock, flags); if (!(sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_AUTOSLEEP)) ath9k_hw_setrxabort(sc->sc_ah, 0); if (ieee80211_is_pspoll(hdr->frame_control)) { @@ -735,7 +1127,6 @@ static void ath9k_tx(struct ieee80211_hw *hw, struct sk_buff *skb) * the ps_flags bit is cleared. We are just dropping * the ps_usecount here. */ - spin_unlock_irqrestore(&sc->sc_pm_lock, flags); ath9k_ps_restore(sc); } @@ -776,7 +1167,7 @@ static void ath9k_stop(struct ieee80211_hw *hw) ath_cancel_work(sc); del_timer_sync(&sc->rx_poll_timer); - if (test_bit(SC_OP_INVALID, &sc->sc_flags)) { + if (sc->sc_flags & SC_OP_INVALID) { ath_dbg(common, ANY, "Device not present\n"); mutex_unlock(&sc->mutex); return; @@ -833,7 +1224,7 @@ static void ath9k_stop(struct ieee80211_hw *hw) ath9k_ps_restore(sc); - set_bit(SC_OP_INVALID, &sc->sc_flags); + sc->sc_flags |= SC_OP_INVALID; sc->ps_idle = prev_idle; mutex_unlock(&sc->mutex); @@ -937,11 +1328,11 @@ static void ath9k_calculate_summary_state(struct ieee80211_hw *hw, /* Set op-mode & TSF */ if (iter_data.naps > 0) { ath9k_hw_set_tsfadjust(ah, 1); - set_bit(SC_OP_TSF_RESET, &sc->sc_flags); + sc->sc_flags |= SC_OP_TSF_RESET; ah->opmode = NL80211_IFTYPE_AP; } else { ath9k_hw_set_tsfadjust(ah, 0); - clear_bit(SC_OP_TSF_RESET, &sc->sc_flags); + sc->sc_flags &= ~SC_OP_TSF_RESET; if (iter_data.nmeshes) ah->opmode = NL80211_IFTYPE_MESH_POINT; @@ -972,12 +1363,12 @@ static void ath9k_calculate_summary_state(struct ieee80211_hw *hw, sc->sc_ah->stats.avgbrssi = ATH_RSSI_DUMMY_MARKER; if (!common->disable_ani) { - set_bit(SC_OP_ANI_RUN, &sc->sc_flags); + sc->sc_flags |= SC_OP_ANI_RUN; ath_start_ani(common); } } else { - clear_bit(SC_OP_ANI_RUN, &sc->sc_flags); + sc->sc_flags &= ~SC_OP_ANI_RUN; del_timer_sync(&common->ani.timer); } } @@ -998,6 +1389,25 @@ static void ath9k_do_vif_add_setup(struct ieee80211_hw *hw, } } +void ath_start_rx_poll(struct ath_softc *sc, u8 nbeacon) +{ + if (!AR_SREV_9300(sc->sc_ah)) + return; + + if (!(sc->sc_flags & SC_OP_PRIM_STA_VIF)) + return; + + mod_timer(&sc->rx_poll_timer, jiffies + msecs_to_jiffies + (nbeacon * sc->cur_beacon_conf.beacon_interval)); +} + +void ath_rx_poll(unsigned long data) +{ + struct ath_softc *sc = (struct ath_softc *)data; + + ieee80211_queue_work(sc->hw, &sc->hw_check_work); +} + static int ath9k_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif) { @@ -1217,6 +1627,11 @@ static int ath9k_config(struct ieee80211_hw *hw, u32 changed) if (ah->curchan) old_pos = ah->curchan - &ah->channels[0]; + if (hw->conf.flags & IEEE80211_CONF_OFFCHANNEL) + sc->sc_flags |= SC_OP_OFFCHANNEL; + else + sc->sc_flags &= ~SC_OP_OFFCHANNEL; + ath_dbg(common, CONFIG, "Set channel: %d MHz type: %d\n", curchan->center_freq, conf->channel_type); @@ -1496,16 +1911,16 @@ static void ath9k_bss_iter(void *data, u8 *mac, struct ieee80211_vif *vif) struct ath_common *common = ath9k_hw_common(sc->sc_ah); struct ieee80211_bss_conf *bss_conf = &vif->bss_conf; struct ath_vif *avp = (void *)vif->drv_priv; - unsigned long flags; + /* * Skip iteration if primary station vif's bss info * was not changed */ - if (test_bit(SC_OP_PRIM_STA_VIF, &sc->sc_flags)) + if (sc->sc_flags & SC_OP_PRIM_STA_VIF) return; if (bss_conf->assoc) { - set_bit(SC_OP_PRIM_STA_VIF, &sc->sc_flags); + sc->sc_flags |= SC_OP_PRIM_STA_VIF; avp->primary_sta_vif = true; memcpy(common->curbssid, bss_conf->bssid, ETH_ALEN); common->curaid = bss_conf->aid; @@ -1518,10 +1933,7 @@ static void ath9k_bss_iter(void *data, u8 *mac, struct ieee80211_vif *vif) * on the receipt of the first Beacon frame (i.e., * after time sync with the AP). */ - spin_lock_irqsave(&sc->sc_pm_lock, flags); sc->ps_flags |= PS_BEACON_SYNC | PS_WAIT_FOR_BEACON; - spin_unlock_irqrestore(&sc->sc_pm_lock, flags); - /* Reset rssi stats */ sc->last_rssi = ATH_RSSI_DUMMY_MARKER; sc->sc_ah->stats.avgbrssi = ATH_RSSI_DUMMY_MARKER; @@ -1529,7 +1941,7 @@ static void ath9k_bss_iter(void *data, u8 *mac, struct ieee80211_vif *vif) ath_start_rx_poll(sc, 3); if (!common->disable_ani) { - set_bit(SC_OP_ANI_RUN, &sc->sc_flags); + sc->sc_flags |= SC_OP_ANI_RUN; ath_start_ani(common); } @@ -1549,8 +1961,7 @@ static void ath9k_config_bss(struct ath_softc *sc, struct ieee80211_vif *vif) if (avp->primary_sta_vif && !bss_conf->assoc) { ath_dbg(common, CONFIG, "Bss Info DISASSOC %d, bssid %pM\n", common->curaid, common->curbssid); - clear_bit(SC_OP_PRIM_STA_VIF, &sc->sc_flags); - clear_bit(SC_OP_BEACONS, &sc->sc_flags); + sc->sc_flags &= ~(SC_OP_PRIM_STA_VIF | SC_OP_BEACONS); avp->primary_sta_vif = false; memset(common->curbssid, 0, ETH_ALEN); common->curaid = 0; @@ -1563,9 +1974,10 @@ static void ath9k_config_bss(struct ath_softc *sc, struct ieee80211_vif *vif) * None of station vifs are associated. * Clear bssid & aid */ - if (!test_bit(SC_OP_PRIM_STA_VIF, &sc->sc_flags)) { + if (!(sc->sc_flags & SC_OP_PRIM_STA_VIF)) { ath9k_hw_write_associd(sc->sc_ah); - clear_bit(SC_OP_ANI_RUN, &sc->sc_flags); + /* Stop ANI */ + sc->sc_flags &= ~SC_OP_ANI_RUN; del_timer_sync(&common->ani.timer); del_timer_sync(&sc->rx_poll_timer); memset(&sc->caldata, 0, sizeof(sc->caldata)); @@ -1603,12 +2015,12 @@ static void ath9k_bss_info_changed(struct ieee80211_hw *hw, sc->sc_ah->stats.avgbrssi = ATH_RSSI_DUMMY_MARKER; if (!common->disable_ani) { - set_bit(SC_OP_ANI_RUN, &sc->sc_flags); + sc->sc_flags |= SC_OP_ANI_RUN; ath_start_ani(common); } } else { - clear_bit(SC_OP_ANI_RUN, &sc->sc_flags); + sc->sc_flags &= ~SC_OP_ANI_RUN; del_timer_sync(&common->ani.timer); del_timer_sync(&sc->rx_poll_timer); } @@ -1620,7 +2032,7 @@ static void ath9k_bss_info_changed(struct ieee80211_hw *hw, */ if ((changed & BSS_CHANGED_BEACON_INT) && (vif->type == NL80211_IFTYPE_AP)) - set_bit(SC_OP_TSF_RESET, &sc->sc_flags); + sc->sc_flags |= SC_OP_TSF_RESET; /* Configure beaconing (AP, IBSS, MESH) */ if (ath9k_uses_beacons(vif->type) && @@ -1812,7 +2224,7 @@ static void ath9k_flush(struct ieee80211_hw *hw, bool drop) return; } - if (test_bit(SC_OP_INVALID, &sc->sc_flags)) { + if (sc->sc_flags & SC_OP_INVALID) { ath_dbg(common, ANY, "Device not present\n"); mutex_unlock(&sc->mutex); return; diff --git a/trunk/drivers/net/wireless/ath/ath9k/mci.c b/trunk/drivers/net/wireless/ath/ath9k/mci.c index 49137f477b05..29fe52d69973 100644 --- a/trunk/drivers/net/wireless/ath/ath9k/mci.c +++ b/trunk/drivers/net/wireless/ath/ath9k/mci.c @@ -116,58 +116,42 @@ static void ath_mci_update_scheme(struct ath_softc *sc) struct ath_common *common = ath9k_hw_common(sc->sc_ah); struct ath_btcoex *btcoex = &sc->btcoex; struct ath_mci_profile *mci = &btcoex->mci; - struct ath9k_hw_mci *mci_hw = &sc->sc_ah->btcoex_hw.mci; struct ath_mci_profile_info *info; u32 num_profile = NUM_PROF(mci); - if (mci_hw->config & ATH_MCI_CONFIG_DISABLE_TUNING) - goto skip_tuning; - if (num_profile == 1) { info = list_first_entry(&mci->info, struct ath_mci_profile_info, list); - if (mci->num_sco) { - if (info->T == 12) - mci->aggr_limit = 8; - else if (info->T == 6) { - mci->aggr_limit = 6; - btcoex->duty_cycle = 30; - } + if (mci->num_sco && info->T == 12) { + mci->aggr_limit = 8; ath_dbg(common, MCI, - "Single SCO, aggregation limit %d 1/4 ms\n", - mci->aggr_limit); - } else if (mci->num_pan || mci->num_other_acl) { - /* - * For single PAN/FTP profile, allocate 35% for BT - * to improve WLAN throughput. - */ - btcoex->duty_cycle = 35; - btcoex->btcoex_period = 53; + "Single SCO, aggregation limit 2 ms\n"); + } else if ((info->type == MCI_GPM_COEX_PROFILE_BNEP) && + !info->master) { + btcoex->btcoex_period = 60; ath_dbg(common, MCI, - "Single PAN/FTP bt period %d ms dutycycle %d\n", - btcoex->duty_cycle, btcoex->btcoex_period); - } else if (mci->num_hid) { + "Single slave PAN/FTP, bt period 60 ms\n"); + } else if ((info->type == MCI_GPM_COEX_PROFILE_HID) && + (info->T > 0 && info->T < 50) && + (info->A > 1 || info->W > 1)) { btcoex->duty_cycle = 30; - mci->aggr_limit = 6; + mci->aggr_limit = 8; ath_dbg(common, MCI, "Multiple attempt/timeout single HID " - "aggregation limit 1.5 ms dutycycle 30%%\n"); + "aggregation limit 2 ms dutycycle 30%%\n"); } - } else if (num_profile == 2) { - if (mci->num_hid == 2) - btcoex->duty_cycle = 30; - mci->aggr_limit = 6; + } else if ((num_profile == 2) && (mci->num_hid == 2)) { + btcoex->duty_cycle = 30; + mci->aggr_limit = 8; ath_dbg(common, MCI, - "Two BT profiles aggr limit 1.5 ms dutycycle %d%%\n", - btcoex->duty_cycle); - } else if (num_profile >= 3) { - mci->aggr_limit = 4; + "Two HIDs aggregation limit 2 ms dutycycle 30%%\n"); + } else if (num_profile > 3) { + mci->aggr_limit = 6; ath_dbg(common, MCI, - "Three or more profiles aggregation limit 1 ms\n"); + "Three or more profiles aggregation limit 1.5 ms\n"); } -skip_tuning: if (IS_CHAN_2GHZ(sc->sc_ah->curchan)) { if (IS_CHAN_HT(sc->sc_ah->curchan)) ath_mci_adjust_aggr_limit(btcoex); @@ -554,14 +538,3 @@ void ath_mci_intr(struct ath_softc *sc) mci_int &= ~(AR_MCI_INTERRUPT_RX_INVALID_HDR | AR_MCI_INTERRUPT_CONT_INFO_TIMEOUT); } - -void ath_mci_enable(struct ath_softc *sc) -{ - struct ath_common *common = ath9k_hw_common(sc->sc_ah); - - if (!common->btcoex_enabled) - return; - - if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_MCI) - sc->sc_ah->imask |= ATH9K_INT_MCI; -} diff --git a/trunk/drivers/net/wireless/ath/ath9k/mci.h b/trunk/drivers/net/wireless/ath/ath9k/mci.h index fc14eea034eb..c841444f53c2 100644 --- a/trunk/drivers/net/wireless/ath/ath9k/mci.h +++ b/trunk/drivers/net/wireless/ath/ath9k/mci.h @@ -130,13 +130,4 @@ void ath_mci_flush_profile(struct ath_mci_profile *mci); int ath_mci_setup(struct ath_softc *sc); void ath_mci_cleanup(struct ath_softc *sc); void ath_mci_intr(struct ath_softc *sc); - -#ifdef CONFIG_ATH9K_BTCOEX_SUPPORT -void ath_mci_enable(struct ath_softc *sc); -#else -static inline void ath_mci_enable(struct ath_softc *sc) -{ -} -#endif /* CONFIG_ATH9K_BTCOEX_SUPPORT */ - -#endif /* MCI_H*/ +#endif diff --git a/trunk/drivers/net/wireless/ath/ath9k/pci.c b/trunk/drivers/net/wireless/ath/ath9k/pci.c index aa0e83ac51f4..a856b51255f4 100644 --- a/trunk/drivers/net/wireless/ath/ath9k/pci.c +++ b/trunk/drivers/net/wireless/ath/ath9k/pci.c @@ -115,9 +115,6 @@ static void ath_pci_aspm_init(struct ath_common *common) int pos; u8 aspm; - if (!ah->is_pciexpress) - return; - pos = pci_pcie_cap(pdev); if (!pos) return; @@ -141,7 +138,6 @@ static void ath_pci_aspm_init(struct ath_common *common) aspm &= ~(PCIE_LINK_STATE_L0S | PCIE_LINK_STATE_L1); pci_write_config_byte(parent, pos + PCI_EXP_LNKCTL, aspm); - ath_info(common, "Disabling ASPM since BTCOEX is enabled\n"); return; } @@ -151,7 +147,6 @@ static void ath_pci_aspm_init(struct ath_common *common) ah->aspm_enabled = true; /* Initialize PCIe PM and SERDES registers. */ ath9k_hw_configpcipowersave(ah, false); - ath_info(common, "ASPM enabled: 0x%x\n", aspm); } } @@ -251,7 +246,7 @@ static int ath_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) sc->mem = mem; /* Will be cleared in ath9k_start() */ - set_bit(SC_OP_INVALID, &sc->sc_flags); + sc->sc_flags |= SC_OP_INVALID; ret = request_irq(pdev->irq, ath_isr, IRQF_SHARED, "ath9k", sc); if (ret) { diff --git a/trunk/drivers/net/wireless/ath/ath9k/recv.c b/trunk/drivers/net/wireless/ath/ath9k/recv.c index fbdcc80437fe..e1fcc68124dc 100644 --- a/trunk/drivers/net/wireless/ath/ath9k/recv.c +++ b/trunk/drivers/net/wireless/ath/ath9k/recv.c @@ -20,6 +20,43 @@ #define SKB_CB_ATHBUF(__skb) (*((struct ath_buf **)__skb->cb)) +static inline bool ath_is_alt_ant_ratio_better(int alt_ratio, int maxdelta, + int mindelta, int main_rssi_avg, + int alt_rssi_avg, int pkt_count) +{ + return (((alt_ratio >= ATH_ANT_DIV_COMB_ALT_ANT_RATIO2) && + (alt_rssi_avg > main_rssi_avg + maxdelta)) || + (alt_rssi_avg > main_rssi_avg + mindelta)) && (pkt_count > 50); +} + +static inline bool ath_ant_div_comb_alt_check(u8 div_group, int alt_ratio, + int curr_main_set, int curr_alt_set, + int alt_rssi_avg, int main_rssi_avg) +{ + bool result = false; + switch (div_group) { + case 0: + if (alt_ratio > ATH_ANT_DIV_COMB_ALT_ANT_RATIO) + result = true; + break; + case 1: + case 2: + if ((((curr_main_set == ATH_ANT_DIV_COMB_LNA2) && + (curr_alt_set == ATH_ANT_DIV_COMB_LNA1) && + (alt_rssi_avg >= (main_rssi_avg - 5))) || + ((curr_main_set == ATH_ANT_DIV_COMB_LNA1) && + (curr_alt_set == ATH_ANT_DIV_COMB_LNA2) && + (alt_rssi_avg >= (main_rssi_avg - 2)))) && + (alt_rssi_avg >= 4)) + result = true; + else + result = false; + break; + } + + return result; +} + static inline bool ath9k_check_auto_sleep(struct ath_softc *sc) { return sc->ps_enabled && @@ -266,7 +303,7 @@ static void ath_edma_start_recv(struct ath_softc *sc) ath_opmode_init(sc); - ath9k_hw_startpcureceive(sc->sc_ah, !!(sc->hw->conf.flags & IEEE80211_CONF_OFFCHANNEL)); + ath9k_hw_startpcureceive(sc->sc_ah, (sc->sc_flags & SC_OP_OFFCHANNEL)); spin_unlock_bh(&sc->rx.rxbuflock); } @@ -285,8 +322,8 @@ int ath_rx_init(struct ath_softc *sc, int nbufs) int error = 0; spin_lock_init(&sc->sc_pcu_lock); + sc->sc_flags &= ~SC_OP_RXFLUSH; spin_lock_init(&sc->rx.rxbuflock); - clear_bit(SC_OP_RXFLUSH, &sc->sc_flags); common->rx_bufsize = IEEE80211_MAX_MPDU_LEN / 2 + sc->sc_ah->caps.rx_status_len; @@ -463,7 +500,7 @@ int ath_startrecv(struct ath_softc *sc) start_recv: ath_opmode_init(sc); - ath9k_hw_startpcureceive(ah, !!(sc->hw->conf.flags & IEEE80211_CONF_OFFCHANNEL)); + ath9k_hw_startpcureceive(ah, (sc->sc_flags & SC_OP_OFFCHANNEL)); spin_unlock_bh(&sc->rx.rxbuflock); @@ -498,11 +535,11 @@ bool ath_stoprecv(struct ath_softc *sc) void ath_flushrecv(struct ath_softc *sc) { - set_bit(SC_OP_RXFLUSH, &sc->sc_flags); + sc->sc_flags |= SC_OP_RXFLUSH; if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) ath_rx_tasklet(sc, 1, true); ath_rx_tasklet(sc, 1, false); - clear_bit(SC_OP_RXFLUSH, &sc->sc_flags); + sc->sc_flags &= ~SC_OP_RXFLUSH; } static bool ath_beacon_dtim_pending_cab(struct sk_buff *skb) @@ -587,13 +624,13 @@ static void ath_rx_ps(struct ath_softc *sc, struct sk_buff *skb, bool mybeacon) /* Process Beacon and CAB receive in PS state */ if (((sc->ps_flags & PS_WAIT_FOR_BEACON) || ath9k_check_auto_sleep(sc)) - && mybeacon) { + && mybeacon) ath_rx_ps_beacon(sc, skb); - } else if ((sc->ps_flags & PS_WAIT_FOR_CAB) && - (ieee80211_is_data(hdr->frame_control) || - ieee80211_is_action(hdr->frame_control)) && - is_multicast_ether_addr(hdr->addr1) && - !ieee80211_has_moredata(hdr->frame_control)) { + else if ((sc->ps_flags & PS_WAIT_FOR_CAB) && + (ieee80211_is_data(hdr->frame_control) || + ieee80211_is_action(hdr->frame_control)) && + is_multicast_ether_addr(hdr->addr1) && + !ieee80211_has_moredata(hdr->frame_control)) { /* * No more broadcast/multicast frames to be received at this * point. @@ -1030,6 +1067,709 @@ static void ath9k_rx_skb_postprocess(struct ath_common *common, rxs->flag &= ~RX_FLAG_DECRYPTED; } +static void ath_lnaconf_alt_good_scan(struct ath_ant_comb *antcomb, + struct ath_hw_antcomb_conf ant_conf, + int main_rssi_avg) +{ + antcomb->quick_scan_cnt = 0; + + if (ant_conf.main_lna_conf == ATH_ANT_DIV_COMB_LNA2) + antcomb->rssi_lna2 = main_rssi_avg; + else if (ant_conf.main_lna_conf == ATH_ANT_DIV_COMB_LNA1) + antcomb->rssi_lna1 = main_rssi_avg; + + switch ((ant_conf.main_lna_conf << 4) | ant_conf.alt_lna_conf) { + case 0x10: /* LNA2 A-B */ + antcomb->main_conf = ATH_ANT_DIV_COMB_LNA1_MINUS_LNA2; + antcomb->first_quick_scan_conf = + ATH_ANT_DIV_COMB_LNA1_PLUS_LNA2; + antcomb->second_quick_scan_conf = ATH_ANT_DIV_COMB_LNA1; + break; + case 0x20: /* LNA1 A-B */ + antcomb->main_conf = ATH_ANT_DIV_COMB_LNA1_MINUS_LNA2; + antcomb->first_quick_scan_conf = + ATH_ANT_DIV_COMB_LNA1_PLUS_LNA2; + antcomb->second_quick_scan_conf = ATH_ANT_DIV_COMB_LNA2; + break; + case 0x21: /* LNA1 LNA2 */ + antcomb->main_conf = ATH_ANT_DIV_COMB_LNA2; + antcomb->first_quick_scan_conf = + ATH_ANT_DIV_COMB_LNA1_MINUS_LNA2; + antcomb->second_quick_scan_conf = + ATH_ANT_DIV_COMB_LNA1_PLUS_LNA2; + break; + case 0x12: /* LNA2 LNA1 */ + antcomb->main_conf = ATH_ANT_DIV_COMB_LNA1; + antcomb->first_quick_scan_conf = + ATH_ANT_DIV_COMB_LNA1_MINUS_LNA2; + antcomb->second_quick_scan_conf = + ATH_ANT_DIV_COMB_LNA1_PLUS_LNA2; + break; + case 0x13: /* LNA2 A+B */ + antcomb->main_conf = ATH_ANT_DIV_COMB_LNA1_PLUS_LNA2; + antcomb->first_quick_scan_conf = + ATH_ANT_DIV_COMB_LNA1_MINUS_LNA2; + antcomb->second_quick_scan_conf = ATH_ANT_DIV_COMB_LNA1; + break; + case 0x23: /* LNA1 A+B */ + antcomb->main_conf = ATH_ANT_DIV_COMB_LNA1_PLUS_LNA2; + antcomb->first_quick_scan_conf = + ATH_ANT_DIV_COMB_LNA1_MINUS_LNA2; + antcomb->second_quick_scan_conf = ATH_ANT_DIV_COMB_LNA2; + break; + default: + break; + } +} + +static void ath_select_ant_div_from_quick_scan(struct ath_ant_comb *antcomb, + struct ath_hw_antcomb_conf *div_ant_conf, + int main_rssi_avg, int alt_rssi_avg, + int alt_ratio) +{ + /* alt_good */ + switch (antcomb->quick_scan_cnt) { + case 0: + /* set alt to main, and alt to first conf */ + div_ant_conf->main_lna_conf = antcomb->main_conf; + div_ant_conf->alt_lna_conf = antcomb->first_quick_scan_conf; + break; + case 1: + /* set alt to main, and alt to first conf */ + div_ant_conf->main_lna_conf = antcomb->main_conf; + div_ant_conf->alt_lna_conf = antcomb->second_quick_scan_conf; + antcomb->rssi_first = main_rssi_avg; + antcomb->rssi_second = alt_rssi_avg; + + if (antcomb->main_conf == ATH_ANT_DIV_COMB_LNA1) { + /* main is LNA1 */ + if (ath_is_alt_ant_ratio_better(alt_ratio, + ATH_ANT_DIV_COMB_LNA1_DELTA_HI, + ATH_ANT_DIV_COMB_LNA1_DELTA_LOW, + main_rssi_avg, alt_rssi_avg, + antcomb->total_pkt_count)) + antcomb->first_ratio = true; + else + antcomb->first_ratio = false; + } else if (antcomb->main_conf == ATH_ANT_DIV_COMB_LNA2) { + if (ath_is_alt_ant_ratio_better(alt_ratio, + ATH_ANT_DIV_COMB_LNA1_DELTA_MID, + ATH_ANT_DIV_COMB_LNA1_DELTA_LOW, + main_rssi_avg, alt_rssi_avg, + antcomb->total_pkt_count)) + antcomb->first_ratio = true; + else + antcomb->first_ratio = false; + } else { + if ((((alt_ratio >= ATH_ANT_DIV_COMB_ALT_ANT_RATIO2) && + (alt_rssi_avg > main_rssi_avg + + ATH_ANT_DIV_COMB_LNA1_DELTA_HI)) || + (alt_rssi_avg > main_rssi_avg)) && + (antcomb->total_pkt_count > 50)) + antcomb->first_ratio = true; + else + antcomb->first_ratio = false; + } + break; + case 2: + antcomb->alt_good = false; + antcomb->scan_not_start = false; + antcomb->scan = false; + antcomb->rssi_first = main_rssi_avg; + antcomb->rssi_third = alt_rssi_avg; + + if (antcomb->second_quick_scan_conf == ATH_ANT_DIV_COMB_LNA1) + antcomb->rssi_lna1 = alt_rssi_avg; + else if (antcomb->second_quick_scan_conf == + ATH_ANT_DIV_COMB_LNA2) + antcomb->rssi_lna2 = alt_rssi_avg; + else if (antcomb->second_quick_scan_conf == + ATH_ANT_DIV_COMB_LNA1_PLUS_LNA2) { + if (antcomb->main_conf == ATH_ANT_DIV_COMB_LNA2) + antcomb->rssi_lna2 = main_rssi_avg; + else if (antcomb->main_conf == ATH_ANT_DIV_COMB_LNA1) + antcomb->rssi_lna1 = main_rssi_avg; + } + + if (antcomb->rssi_lna2 > antcomb->rssi_lna1 + + ATH_ANT_DIV_COMB_LNA1_LNA2_SWITCH_DELTA) + div_ant_conf->main_lna_conf = ATH_ANT_DIV_COMB_LNA2; + else + div_ant_conf->main_lna_conf = ATH_ANT_DIV_COMB_LNA1; + + if (antcomb->main_conf == ATH_ANT_DIV_COMB_LNA1) { + if (ath_is_alt_ant_ratio_better(alt_ratio, + ATH_ANT_DIV_COMB_LNA1_DELTA_HI, + ATH_ANT_DIV_COMB_LNA1_DELTA_LOW, + main_rssi_avg, alt_rssi_avg, + antcomb->total_pkt_count)) + antcomb->second_ratio = true; + else + antcomb->second_ratio = false; + } else if (antcomb->main_conf == ATH_ANT_DIV_COMB_LNA2) { + if (ath_is_alt_ant_ratio_better(alt_ratio, + ATH_ANT_DIV_COMB_LNA1_DELTA_MID, + ATH_ANT_DIV_COMB_LNA1_DELTA_LOW, + main_rssi_avg, alt_rssi_avg, + antcomb->total_pkt_count)) + antcomb->second_ratio = true; + else + antcomb->second_ratio = false; + } else { + if ((((alt_ratio >= ATH_ANT_DIV_COMB_ALT_ANT_RATIO2) && + (alt_rssi_avg > main_rssi_avg + + ATH_ANT_DIV_COMB_LNA1_DELTA_HI)) || + (alt_rssi_avg > main_rssi_avg)) && + (antcomb->total_pkt_count > 50)) + antcomb->second_ratio = true; + else + antcomb->second_ratio = false; + } + + /* set alt to the conf with maximun ratio */ + if (antcomb->first_ratio && antcomb->second_ratio) { + if (antcomb->rssi_second > antcomb->rssi_third) { + /* first alt*/ + if ((antcomb->first_quick_scan_conf == + ATH_ANT_DIV_COMB_LNA1) || + (antcomb->first_quick_scan_conf == + ATH_ANT_DIV_COMB_LNA2)) + /* Set alt LNA1 or LNA2*/ + if (div_ant_conf->main_lna_conf == + ATH_ANT_DIV_COMB_LNA2) + div_ant_conf->alt_lna_conf = + ATH_ANT_DIV_COMB_LNA1; + else + div_ant_conf->alt_lna_conf = + ATH_ANT_DIV_COMB_LNA2; + else + /* Set alt to A+B or A-B */ + div_ant_conf->alt_lna_conf = + antcomb->first_quick_scan_conf; + } else if ((antcomb->second_quick_scan_conf == + ATH_ANT_DIV_COMB_LNA1) || + (antcomb->second_quick_scan_conf == + ATH_ANT_DIV_COMB_LNA2)) { + /* Set alt LNA1 or LNA2 */ + if (div_ant_conf->main_lna_conf == + ATH_ANT_DIV_COMB_LNA2) + div_ant_conf->alt_lna_conf = + ATH_ANT_DIV_COMB_LNA1; + else + div_ant_conf->alt_lna_conf = + ATH_ANT_DIV_COMB_LNA2; + } else { + /* Set alt to A+B or A-B */ + div_ant_conf->alt_lna_conf = + antcomb->second_quick_scan_conf; + } + } else if (antcomb->first_ratio) { + /* first alt */ + if ((antcomb->first_quick_scan_conf == + ATH_ANT_DIV_COMB_LNA1) || + (antcomb->first_quick_scan_conf == + ATH_ANT_DIV_COMB_LNA2)) + /* Set alt LNA1 or LNA2 */ + if (div_ant_conf->main_lna_conf == + ATH_ANT_DIV_COMB_LNA2) + div_ant_conf->alt_lna_conf = + ATH_ANT_DIV_COMB_LNA1; + else + div_ant_conf->alt_lna_conf = + ATH_ANT_DIV_COMB_LNA2; + else + /* Set alt to A+B or A-B */ + div_ant_conf->alt_lna_conf = + antcomb->first_quick_scan_conf; + } else if (antcomb->second_ratio) { + /* second alt */ + if ((antcomb->second_quick_scan_conf == + ATH_ANT_DIV_COMB_LNA1) || + (antcomb->second_quick_scan_conf == + ATH_ANT_DIV_COMB_LNA2)) + /* Set alt LNA1 or LNA2 */ + if (div_ant_conf->main_lna_conf == + ATH_ANT_DIV_COMB_LNA2) + div_ant_conf->alt_lna_conf = + ATH_ANT_DIV_COMB_LNA1; + else + div_ant_conf->alt_lna_conf = + ATH_ANT_DIV_COMB_LNA2; + else + /* Set alt to A+B or A-B */ + div_ant_conf->alt_lna_conf = + antcomb->second_quick_scan_conf; + } else { + /* main is largest */ + if ((antcomb->main_conf == ATH_ANT_DIV_COMB_LNA1) || + (antcomb->main_conf == ATH_ANT_DIV_COMB_LNA2)) + /* Set alt LNA1 or LNA2 */ + if (div_ant_conf->main_lna_conf == + ATH_ANT_DIV_COMB_LNA2) + div_ant_conf->alt_lna_conf = + ATH_ANT_DIV_COMB_LNA1; + else + div_ant_conf->alt_lna_conf = + ATH_ANT_DIV_COMB_LNA2; + else + /* Set alt to A+B or A-B */ + div_ant_conf->alt_lna_conf = antcomb->main_conf; + } + break; + default: + break; + } +} + +static void ath_ant_div_conf_fast_divbias(struct ath_hw_antcomb_conf *ant_conf, + struct ath_ant_comb *antcomb, int alt_ratio) +{ + if (ant_conf->div_group == 0) { + /* Adjust the fast_div_bias based on main and alt lna conf */ + switch ((ant_conf->main_lna_conf << 4) | + ant_conf->alt_lna_conf) { + case 0x01: /* A-B LNA2 */ + ant_conf->fast_div_bias = 0x3b; + break; + case 0x02: /* A-B LNA1 */ + ant_conf->fast_div_bias = 0x3d; + break; + case 0x03: /* A-B A+B */ + ant_conf->fast_div_bias = 0x1; + break; + case 0x10: /* LNA2 A-B */ + ant_conf->fast_div_bias = 0x7; + break; + case 0x12: /* LNA2 LNA1 */ + ant_conf->fast_div_bias = 0x2; + break; + case 0x13: /* LNA2 A+B */ + ant_conf->fast_div_bias = 0x7; + break; + case 0x20: /* LNA1 A-B */ + ant_conf->fast_div_bias = 0x6; + break; + case 0x21: /* LNA1 LNA2 */ + ant_conf->fast_div_bias = 0x0; + break; + case 0x23: /* LNA1 A+B */ + ant_conf->fast_div_bias = 0x6; + break; + case 0x30: /* A+B A-B */ + ant_conf->fast_div_bias = 0x1; + break; + case 0x31: /* A+B LNA2 */ + ant_conf->fast_div_bias = 0x3b; + break; + case 0x32: /* A+B LNA1 */ + ant_conf->fast_div_bias = 0x3d; + break; + default: + break; + } + } else if (ant_conf->div_group == 1) { + /* Adjust the fast_div_bias based on main and alt_lna_conf */ + switch ((ant_conf->main_lna_conf << 4) | + ant_conf->alt_lna_conf) { + case 0x01: /* A-B LNA2 */ + ant_conf->fast_div_bias = 0x1; + ant_conf->main_gaintb = 0; + ant_conf->alt_gaintb = 0; + break; + case 0x02: /* A-B LNA1 */ + ant_conf->fast_div_bias = 0x1; + ant_conf->main_gaintb = 0; + ant_conf->alt_gaintb = 0; + break; + case 0x03: /* A-B A+B */ + ant_conf->fast_div_bias = 0x1; + ant_conf->main_gaintb = 0; + ant_conf->alt_gaintb = 0; + break; + case 0x10: /* LNA2 A-B */ + if (!(antcomb->scan) && + (alt_ratio > ATH_ANT_DIV_COMB_ALT_ANT_RATIO)) + ant_conf->fast_div_bias = 0x3f; + else + ant_conf->fast_div_bias = 0x1; + ant_conf->main_gaintb = 0; + ant_conf->alt_gaintb = 0; + break; + case 0x12: /* LNA2 LNA1 */ + ant_conf->fast_div_bias = 0x1; + ant_conf->main_gaintb = 0; + ant_conf->alt_gaintb = 0; + break; + case 0x13: /* LNA2 A+B */ + if (!(antcomb->scan) && + (alt_ratio > ATH_ANT_DIV_COMB_ALT_ANT_RATIO)) + ant_conf->fast_div_bias = 0x3f; + else + ant_conf->fast_div_bias = 0x1; + ant_conf->main_gaintb = 0; + ant_conf->alt_gaintb = 0; + break; + case 0x20: /* LNA1 A-B */ + if (!(antcomb->scan) && + (alt_ratio > ATH_ANT_DIV_COMB_ALT_ANT_RATIO)) + ant_conf->fast_div_bias = 0x3f; + else + ant_conf->fast_div_bias = 0x1; + ant_conf->main_gaintb = 0; + ant_conf->alt_gaintb = 0; + break; + case 0x21: /* LNA1 LNA2 */ + ant_conf->fast_div_bias = 0x1; + ant_conf->main_gaintb = 0; + ant_conf->alt_gaintb = 0; + break; + case 0x23: /* LNA1 A+B */ + if (!(antcomb->scan) && + (alt_ratio > ATH_ANT_DIV_COMB_ALT_ANT_RATIO)) + ant_conf->fast_div_bias = 0x3f; + else + ant_conf->fast_div_bias = 0x1; + ant_conf->main_gaintb = 0; + ant_conf->alt_gaintb = 0; + break; + case 0x30: /* A+B A-B */ + ant_conf->fast_div_bias = 0x1; + ant_conf->main_gaintb = 0; + ant_conf->alt_gaintb = 0; + break; + case 0x31: /* A+B LNA2 */ + ant_conf->fast_div_bias = 0x1; + ant_conf->main_gaintb = 0; + ant_conf->alt_gaintb = 0; + break; + case 0x32: /* A+B LNA1 */ + ant_conf->fast_div_bias = 0x1; + ant_conf->main_gaintb = 0; + ant_conf->alt_gaintb = 0; + break; + default: + break; + } + } else if (ant_conf->div_group == 2) { + /* Adjust the fast_div_bias based on main and alt_lna_conf */ + switch ((ant_conf->main_lna_conf << 4) | + ant_conf->alt_lna_conf) { + case 0x01: /* A-B LNA2 */ + ant_conf->fast_div_bias = 0x1; + ant_conf->main_gaintb = 0; + ant_conf->alt_gaintb = 0; + break; + case 0x02: /* A-B LNA1 */ + ant_conf->fast_div_bias = 0x1; + ant_conf->main_gaintb = 0; + ant_conf->alt_gaintb = 0; + break; + case 0x03: /* A-B A+B */ + ant_conf->fast_div_bias = 0x1; + ant_conf->main_gaintb = 0; + ant_conf->alt_gaintb = 0; + break; + case 0x10: /* LNA2 A-B */ + if (!(antcomb->scan) && + (alt_ratio > ATH_ANT_DIV_COMB_ALT_ANT_RATIO)) + ant_conf->fast_div_bias = 0x1; + else + ant_conf->fast_div_bias = 0x2; + ant_conf->main_gaintb = 0; + ant_conf->alt_gaintb = 0; + break; + case 0x12: /* LNA2 LNA1 */ + ant_conf->fast_div_bias = 0x1; + ant_conf->main_gaintb = 0; + ant_conf->alt_gaintb = 0; + break; + case 0x13: /* LNA2 A+B */ + if (!(antcomb->scan) && + (alt_ratio > ATH_ANT_DIV_COMB_ALT_ANT_RATIO)) + ant_conf->fast_div_bias = 0x1; + else + ant_conf->fast_div_bias = 0x2; + ant_conf->main_gaintb = 0; + ant_conf->alt_gaintb = 0; + break; + case 0x20: /* LNA1 A-B */ + if (!(antcomb->scan) && + (alt_ratio > ATH_ANT_DIV_COMB_ALT_ANT_RATIO)) + ant_conf->fast_div_bias = 0x1; + else + ant_conf->fast_div_bias = 0x2; + ant_conf->main_gaintb = 0; + ant_conf->alt_gaintb = 0; + break; + case 0x21: /* LNA1 LNA2 */ + ant_conf->fast_div_bias = 0x1; + ant_conf->main_gaintb = 0; + ant_conf->alt_gaintb = 0; + break; + case 0x23: /* LNA1 A+B */ + if (!(antcomb->scan) && + (alt_ratio > ATH_ANT_DIV_COMB_ALT_ANT_RATIO)) + ant_conf->fast_div_bias = 0x1; + else + ant_conf->fast_div_bias = 0x2; + ant_conf->main_gaintb = 0; + ant_conf->alt_gaintb = 0; + break; + case 0x30: /* A+B A-B */ + ant_conf->fast_div_bias = 0x1; + ant_conf->main_gaintb = 0; + ant_conf->alt_gaintb = 0; + break; + case 0x31: /* A+B LNA2 */ + ant_conf->fast_div_bias = 0x1; + ant_conf->main_gaintb = 0; + ant_conf->alt_gaintb = 0; + break; + case 0x32: /* A+B LNA1 */ + ant_conf->fast_div_bias = 0x1; + ant_conf->main_gaintb = 0; + ant_conf->alt_gaintb = 0; + break; + default: + break; + } + } +} + +/* Antenna diversity and combining */ +static void ath_ant_comb_scan(struct ath_softc *sc, struct ath_rx_status *rs) +{ + struct ath_hw_antcomb_conf div_ant_conf; + struct ath_ant_comb *antcomb = &sc->ant_comb; + int alt_ratio = 0, alt_rssi_avg = 0, main_rssi_avg = 0, curr_alt_set; + int curr_main_set; + int main_rssi = rs->rs_rssi_ctl0; + int alt_rssi = rs->rs_rssi_ctl1; + int rx_ant_conf, main_ant_conf; + bool short_scan = false; + + rx_ant_conf = (rs->rs_rssi_ctl2 >> ATH_ANT_RX_CURRENT_SHIFT) & + ATH_ANT_RX_MASK; + main_ant_conf = (rs->rs_rssi_ctl2 >> ATH_ANT_RX_MAIN_SHIFT) & + ATH_ANT_RX_MASK; + + /* Record packet only when both main_rssi and alt_rssi is positive */ + if (main_rssi > 0 && alt_rssi > 0) { + antcomb->total_pkt_count++; + antcomb->main_total_rssi += main_rssi; + antcomb->alt_total_rssi += alt_rssi; + if (main_ant_conf == rx_ant_conf) + antcomb->main_recv_cnt++; + else + antcomb->alt_recv_cnt++; + } + + /* Short scan check */ + if (antcomb->scan && antcomb->alt_good) { + if (time_after(jiffies, antcomb->scan_start_time + + msecs_to_jiffies(ATH_ANT_DIV_COMB_SHORT_SCAN_INTR))) + short_scan = true; + else + if (antcomb->total_pkt_count == + ATH_ANT_DIV_COMB_SHORT_SCAN_PKTCOUNT) { + alt_ratio = ((antcomb->alt_recv_cnt * 100) / + antcomb->total_pkt_count); + if (alt_ratio < ATH_ANT_DIV_COMB_ALT_ANT_RATIO) + short_scan = true; + } + } + + if (((antcomb->total_pkt_count < ATH_ANT_DIV_COMB_MAX_PKTCOUNT) || + rs->rs_moreaggr) && !short_scan) + return; + + if (antcomb->total_pkt_count) { + alt_ratio = ((antcomb->alt_recv_cnt * 100) / + antcomb->total_pkt_count); + main_rssi_avg = (antcomb->main_total_rssi / + antcomb->total_pkt_count); + alt_rssi_avg = (antcomb->alt_total_rssi / + antcomb->total_pkt_count); + } + + + ath9k_hw_antdiv_comb_conf_get(sc->sc_ah, &div_ant_conf); + curr_alt_set = div_ant_conf.alt_lna_conf; + curr_main_set = div_ant_conf.main_lna_conf; + + antcomb->count++; + + if (antcomb->count == ATH_ANT_DIV_COMB_MAX_COUNT) { + if (alt_ratio > ATH_ANT_DIV_COMB_ALT_ANT_RATIO) { + ath_lnaconf_alt_good_scan(antcomb, div_ant_conf, + main_rssi_avg); + antcomb->alt_good = true; + } else { + antcomb->alt_good = false; + } + + antcomb->count = 0; + antcomb->scan = true; + antcomb->scan_not_start = true; + } + + if (!antcomb->scan) { + if (ath_ant_div_comb_alt_check(div_ant_conf.div_group, + alt_ratio, curr_main_set, curr_alt_set, + alt_rssi_avg, main_rssi_avg)) { + if (curr_alt_set == ATH_ANT_DIV_COMB_LNA2) { + /* Switch main and alt LNA */ + div_ant_conf.main_lna_conf = + ATH_ANT_DIV_COMB_LNA2; + div_ant_conf.alt_lna_conf = + ATH_ANT_DIV_COMB_LNA1; + } else if (curr_alt_set == ATH_ANT_DIV_COMB_LNA1) { + div_ant_conf.main_lna_conf = + ATH_ANT_DIV_COMB_LNA1; + div_ant_conf.alt_lna_conf = + ATH_ANT_DIV_COMB_LNA2; + } + + goto div_comb_done; + } else if ((curr_alt_set != ATH_ANT_DIV_COMB_LNA1) && + (curr_alt_set != ATH_ANT_DIV_COMB_LNA2)) { + /* Set alt to another LNA */ + if (curr_main_set == ATH_ANT_DIV_COMB_LNA2) + div_ant_conf.alt_lna_conf = + ATH_ANT_DIV_COMB_LNA1; + else if (curr_main_set == ATH_ANT_DIV_COMB_LNA1) + div_ant_conf.alt_lna_conf = + ATH_ANT_DIV_COMB_LNA2; + + goto div_comb_done; + } + + if ((alt_rssi_avg < (main_rssi_avg + + div_ant_conf.lna1_lna2_delta))) + goto div_comb_done; + } + + if (!antcomb->scan_not_start) { + switch (curr_alt_set) { + case ATH_ANT_DIV_COMB_LNA2: + antcomb->rssi_lna2 = alt_rssi_avg; + antcomb->rssi_lna1 = main_rssi_avg; + antcomb->scan = true; + /* set to A+B */ + div_ant_conf.main_lna_conf = + ATH_ANT_DIV_COMB_LNA1; + div_ant_conf.alt_lna_conf = + ATH_ANT_DIV_COMB_LNA1_PLUS_LNA2; + break; + case ATH_ANT_DIV_COMB_LNA1: + antcomb->rssi_lna1 = alt_rssi_avg; + antcomb->rssi_lna2 = main_rssi_avg; + antcomb->scan = true; + /* set to A+B */ + div_ant_conf.main_lna_conf = ATH_ANT_DIV_COMB_LNA2; + div_ant_conf.alt_lna_conf = + ATH_ANT_DIV_COMB_LNA1_PLUS_LNA2; + break; + case ATH_ANT_DIV_COMB_LNA1_PLUS_LNA2: + antcomb->rssi_add = alt_rssi_avg; + antcomb->scan = true; + /* set to A-B */ + div_ant_conf.alt_lna_conf = + ATH_ANT_DIV_COMB_LNA1_MINUS_LNA2; + break; + case ATH_ANT_DIV_COMB_LNA1_MINUS_LNA2: + antcomb->rssi_sub = alt_rssi_avg; + antcomb->scan = false; + if (antcomb->rssi_lna2 > + (antcomb->rssi_lna1 + + ATH_ANT_DIV_COMB_LNA1_LNA2_SWITCH_DELTA)) { + /* use LNA2 as main LNA */ + if ((antcomb->rssi_add > antcomb->rssi_lna1) && + (antcomb->rssi_add > antcomb->rssi_sub)) { + /* set to A+B */ + div_ant_conf.main_lna_conf = + ATH_ANT_DIV_COMB_LNA2; + div_ant_conf.alt_lna_conf = + ATH_ANT_DIV_COMB_LNA1_PLUS_LNA2; + } else if (antcomb->rssi_sub > + antcomb->rssi_lna1) { + /* set to A-B */ + div_ant_conf.main_lna_conf = + ATH_ANT_DIV_COMB_LNA2; + div_ant_conf.alt_lna_conf = + ATH_ANT_DIV_COMB_LNA1_MINUS_LNA2; + } else { + /* set to LNA1 */ + div_ant_conf.main_lna_conf = + ATH_ANT_DIV_COMB_LNA2; + div_ant_conf.alt_lna_conf = + ATH_ANT_DIV_COMB_LNA1; + } + } else { + /* use LNA1 as main LNA */ + if ((antcomb->rssi_add > antcomb->rssi_lna2) && + (antcomb->rssi_add > antcomb->rssi_sub)) { + /* set to A+B */ + div_ant_conf.main_lna_conf = + ATH_ANT_DIV_COMB_LNA1; + div_ant_conf.alt_lna_conf = + ATH_ANT_DIV_COMB_LNA1_PLUS_LNA2; + } else if (antcomb->rssi_sub > + antcomb->rssi_lna1) { + /* set to A-B */ + div_ant_conf.main_lna_conf = + ATH_ANT_DIV_COMB_LNA1; + div_ant_conf.alt_lna_conf = + ATH_ANT_DIV_COMB_LNA1_MINUS_LNA2; + } else { + /* set to LNA2 */ + div_ant_conf.main_lna_conf = + ATH_ANT_DIV_COMB_LNA1; + div_ant_conf.alt_lna_conf = + ATH_ANT_DIV_COMB_LNA2; + } + } + break; + default: + break; + } + } else { + if (!antcomb->alt_good) { + antcomb->scan_not_start = false; + /* Set alt to another LNA */ + if (curr_main_set == ATH_ANT_DIV_COMB_LNA2) { + div_ant_conf.main_lna_conf = + ATH_ANT_DIV_COMB_LNA2; + div_ant_conf.alt_lna_conf = + ATH_ANT_DIV_COMB_LNA1; + } else if (curr_main_set == ATH_ANT_DIV_COMB_LNA1) { + div_ant_conf.main_lna_conf = + ATH_ANT_DIV_COMB_LNA1; + div_ant_conf.alt_lna_conf = + ATH_ANT_DIV_COMB_LNA2; + } + goto div_comb_done; + } + } + + ath_select_ant_div_from_quick_scan(antcomb, &div_ant_conf, + main_rssi_avg, alt_rssi_avg, + alt_ratio); + + antcomb->quick_scan_cnt++; + +div_comb_done: + ath_ant_div_conf_fast_divbias(&div_ant_conf, antcomb, alt_ratio); + ath9k_hw_antdiv_comb_conf_set(sc->sc_ah, &div_ant_conf); + + antcomb->scan_start_time = jiffies; + antcomb->total_pkt_count = 0; + antcomb->main_total_rssi = 0; + antcomb->alt_total_rssi = 0; + antcomb->main_recv_cnt = 0; + antcomb->alt_recv_cnt = 0; +} + int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp) { struct ath_buf *bf; @@ -1063,7 +1803,7 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp) do { /* If handling rx interrupt and flush is in progress => exit */ - if (test_bit(SC_OP_RXFLUSH, &sc->sc_flags) && (flush == 0)) + if ((sc->sc_flags & SC_OP_RXFLUSH) && (flush == 0)) break; memset(&rs, 0, sizeof(rs)); @@ -1101,14 +1841,13 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp) else rs.is_mybeacon = false; - sc->rx.num_pkts++; ath_debug_stat_rx(sc, &rs); /* * If we're asked to flush receive queue, directly * chain it back at the queue without processing it. */ - if (test_bit(SC_OP_RXFLUSH, &sc->sc_flags)) { + if (sc->sc_flags & SC_OP_RXFLUSH) { RX_STAT_INC(rx_drop_rxflush); goto requeue_drop_frag; } @@ -1229,6 +1968,7 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp) skb_trim(skb, skb->len - 8); spin_lock_irqsave(&sc->sc_pm_lock, flags); + if ((sc->ps_flags & (PS_WAIT_FOR_BEACON | PS_WAIT_FOR_CAB | PS_WAIT_FOR_PSPOLL_DATA)) || diff --git a/trunk/drivers/net/wireless/ath/ath9k/reg.h b/trunk/drivers/net/wireless/ath/ath9k/reg.h index 560d6effac7a..458f81b4a7cb 100644 --- a/trunk/drivers/net/wireless/ath/ath9k/reg.h +++ b/trunk/drivers/net/wireless/ath/ath9k/reg.h @@ -2211,7 +2211,5 @@ enum { #define AR_BTCOEX_CTRL3_CONT_INFO_TIMEOUT 0x00000fff #define AR_BTCOEX_CTRL3_CONT_INFO_TIMEOUT_S 0 -#define AR_GLB_SWREG_DISCONT_MODE 0x2002c -#define AR_GLB_SWREG_DISCONT_EN_BT_WLAN 0x3 #endif diff --git a/trunk/drivers/net/wireless/ath/ath9k/xmit.c b/trunk/drivers/net/wireless/ath/ath9k/xmit.c index f777ddcd1172..d59dd01d6cde 100644 --- a/trunk/drivers/net/wireless/ath/ath9k/xmit.c +++ b/trunk/drivers/net/wireless/ath/ath9k/xmit.c @@ -105,19 +105,19 @@ static int ath_max_4ms_framelen[4][32] = { /* Aggregation logic */ /*********************/ -void ath_txq_lock(struct ath_softc *sc, struct ath_txq *txq) +static void ath_txq_lock(struct ath_softc *sc, struct ath_txq *txq) __acquires(&txq->axq_lock) { spin_lock_bh(&txq->axq_lock); } -void ath_txq_unlock(struct ath_softc *sc, struct ath_txq *txq) +static void ath_txq_unlock(struct ath_softc *sc, struct ath_txq *txq) __releases(&txq->axq_lock) { spin_unlock_bh(&txq->axq_lock); } -void ath_txq_unlock_complete(struct ath_softc *sc, struct ath_txq *txq) +static void ath_txq_unlock_complete(struct ath_softc *sc, struct ath_txq *txq) __releases(&txq->axq_lock) { struct sk_buff_head q; @@ -1536,7 +1536,7 @@ bool ath_drain_all_txq(struct ath_softc *sc, bool retry_tx) int i; u32 npend = 0; - if (test_bit(SC_OP_INVALID, &sc->sc_flags)) + if (sc->sc_flags & SC_OP_INVALID) return true; ath9k_hw_abort_tx_dma(ah); @@ -1994,7 +1994,6 @@ static void ath_tx_complete(struct ath_softc *sc, struct sk_buff *skb, struct ath_common *common = ath9k_hw_common(sc->sc_ah); struct ieee80211_hdr * hdr = (struct ieee80211_hdr *)skb->data; int q, padpos, padsize; - unsigned long flags; ath_dbg(common, XMIT, "TX complete: skb: %p\n", skb); @@ -2013,7 +2012,6 @@ static void ath_tx_complete(struct ath_softc *sc, struct sk_buff *skb, skb_pull(skb, padsize); } - spin_lock_irqsave(&sc->sc_pm_lock, flags); if ((sc->ps_flags & PS_WAIT_FOR_TX_ACK) && !txq->axq_depth) { sc->ps_flags &= ~PS_WAIT_FOR_TX_ACK; ath_dbg(common, PS, @@ -2023,7 +2021,6 @@ static void ath_tx_complete(struct ath_softc *sc, struct sk_buff *skb, PS_WAIT_FOR_PSPOLL_DATA | PS_WAIT_FOR_TX_ACK)); } - spin_unlock_irqrestore(&sc->sc_pm_lock, flags); q = skb_get_queue_mapping(skb); if (txq == sc->tx.txq_map[q]) { @@ -2234,6 +2231,46 @@ static void ath_tx_processq(struct ath_softc *sc, struct ath_txq *txq) ath_txq_unlock_complete(sc, txq); } +static void ath_tx_complete_poll_work(struct work_struct *work) +{ + struct ath_softc *sc = container_of(work, struct ath_softc, + tx_complete_work.work); + struct ath_txq *txq; + int i; + bool needreset = false; +#ifdef CONFIG_ATH9K_DEBUGFS + sc->tx_complete_poll_work_seen++; +#endif + + for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++) + if (ATH_TXQ_SETUP(sc, i)) { + txq = &sc->tx.txq[i]; + ath_txq_lock(sc, txq); + if (txq->axq_depth) { + if (txq->axq_tx_inprogress) { + needreset = true; + ath_txq_unlock(sc, txq); + break; + } else { + txq->axq_tx_inprogress = true; + } + } + ath_txq_unlock_complete(sc, txq); + } + + if (needreset) { + ath_dbg(ath9k_hw_common(sc->sc_ah), RESET, + "tx hung, resetting the chip\n"); + RESET_STAT_INC(sc, RESET_TYPE_TX_HANG); + ieee80211_queue_work(sc->hw, &sc->hw_reset_work); + } + + ieee80211_queue_delayed_work(sc->hw, &sc->tx_complete_work, + msecs_to_jiffies(ATH_TX_COMPLETE_POLL_INT)); +} + + + void ath_tx_tasklet(struct ath_softc *sc) { struct ath_hw *ah = sc->sc_ah; diff --git a/trunk/drivers/net/wireless/b43legacy/main.c b/trunk/drivers/net/wireless/b43legacy/main.c index 8b06ca56125e..cd9c9bc186d9 100644 --- a/trunk/drivers/net/wireless/b43legacy/main.c +++ b/trunk/drivers/net/wireless/b43legacy/main.c @@ -1508,7 +1508,7 @@ static void b43legacy_release_firmware(struct b43legacy_wldev *dev) static void b43legacy_print_fw_helptext(struct b43legacy_wl *wl) { - b43legacyerr(wl, "You must go to http://wireless.kernel.org/en/users/" + b43legacyerr(wl, "You must go to http://linuxwireless.org/en/users/" "Drivers/b43#devicefirmware " "and download the correct firmware (version 3).\n"); } diff --git a/trunk/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c b/trunk/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c index 8e7e6928c936..e2480d196276 100644 --- a/trunk/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c +++ b/trunk/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c @@ -89,9 +89,9 @@ int brcmf_sdio_intr_register(struct brcmf_sdio_dev *sdiodev) data |= 1 << SDIO_FUNC_1 | 1 << SDIO_FUNC_2 | 1; brcmf_sdio_regwb(sdiodev, SDIO_CCCR_IENx, data, &ret); - /* redirect, configure and enable io for interrupt signal */ + /* redirect, configure ane enable io for interrupt signal */ data = SDIO_SEPINT_MASK | SDIO_SEPINT_OE; - if (sdiodev->irq_flags & IRQF_TRIGGER_HIGH) + if (sdiodev->irq_flags | IRQF_TRIGGER_HIGH) data |= SDIO_SEPINT_ACT_HI; brcmf_sdio_regwb(sdiodev, SDIO_CCCR_BRCM_SEPINT, data, &ret); diff --git a/trunk/drivers/net/wireless/brcm80211/brcmsmac/aiutils.c b/trunk/drivers/net/wireless/brcm80211/brcmsmac/aiutils.c index 3c6f9b1e8d05..6d8b7213643a 100644 --- a/trunk/drivers/net/wireless/brcm80211/brcmsmac/aiutils.c +++ b/trunk/drivers/net/wireless/brcm80211/brcmsmac/aiutils.c @@ -631,8 +631,9 @@ uint ai_cc_reg(struct si_pub *sih, uint regoff, u32 mask, u32 val) cc = sii->icbus->drv_cc.core; /* mask and set */ - if (mask || val) + if (mask || val) { bcma_maskset32(cc, regoff, ~mask, val); + } /* readback */ w = bcma_read32(cc, regoff); diff --git a/trunk/drivers/net/wireless/brcm80211/brcmsmac/aiutils.h b/trunk/drivers/net/wireless/brcm80211/brcmsmac/aiutils.h index d6fa9829af9a..d9f04a683bdb 100644 --- a/trunk/drivers/net/wireless/brcm80211/brcmsmac/aiutils.h +++ b/trunk/drivers/net/wireless/brcm80211/brcmsmac/aiutils.h @@ -193,7 +193,7 @@ extern void ai_detach(struct si_pub *sih); extern uint ai_cc_reg(struct si_pub *sih, uint regoff, u32 mask, u32 val); extern void ai_clkctl_init(struct si_pub *sih); extern u16 ai_clkctl_fast_pwrup_delay(struct si_pub *sih); -extern bool ai_clkctl_cc(struct si_pub *sih, enum bcma_clkmode mode); +extern bool ai_clkctl_cc(struct si_pub *sih, uint mode); extern bool ai_deviceremoved(struct si_pub *sih); extern void ai_pci_down(struct si_pub *sih); diff --git a/trunk/drivers/net/wireless/iwlegacy/4965-mac.c b/trunk/drivers/net/wireless/iwlegacy/4965-mac.c index d24eaf89ffb5..509301a5e7e2 100644 --- a/trunk/drivers/net/wireless/iwlegacy/4965-mac.c +++ b/trunk/drivers/net/wireless/iwlegacy/4965-mac.c @@ -5724,8 +5724,7 @@ il4965_mac_setup_register(struct il_priv *il, u32 max_probe_length) BIT(NL80211_IFTYPE_STATION) | BIT(NL80211_IFTYPE_ADHOC); hw->wiphy->flags |= - WIPHY_FLAG_CUSTOM_REGULATORY | WIPHY_FLAG_DISABLE_BEACON_HINTS | - WIPHY_FLAG_IBSS_RSN; + WIPHY_FLAG_CUSTOM_REGULATORY | WIPHY_FLAG_DISABLE_BEACON_HINTS; /* * For now, disable PS by default because it affects @@ -5874,16 +5873,6 @@ il4965_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, return -EOPNOTSUPP; } - /* - * To support IBSS RSN, don't program group keys in IBSS, the - * hardware will then not attempt to decrypt the frames. - */ - if (vif->type == NL80211_IFTYPE_ADHOC && - !(key->flags & IEEE80211_KEY_FLAG_PAIRWISE)) { - D_MAC80211("leave - ad-hoc group key\n"); - return -EOPNOTSUPP; - } - sta_id = il_sta_id_or_broadcast(il, sta); if (sta_id == IL_INVALID_STATION) return -EINVAL; diff --git a/trunk/drivers/net/wireless/iwlwifi/iwl-agn-lib.c b/trunk/drivers/net/wireless/iwlwifi/iwl-agn-lib.c index e55ec6c8a920..c31072d42791 100644 --- a/trunk/drivers/net/wireless/iwlwifi/iwl-agn-lib.c +++ b/trunk/drivers/net/wireless/iwlwifi/iwl-agn-lib.c @@ -617,6 +617,11 @@ static bool iwlagn_fill_txpower_mode(struct iwl_priv *priv, struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS]; int ave_rssi; + if (!ctx->vif || (ctx->vif->type != NL80211_IFTYPE_STATION)) { + IWL_DEBUG_INFO(priv, "BSS ctx not active or not in sta mode\n"); + return false; + } + ave_rssi = ieee80211_ave_rssi(ctx->vif); if (!ave_rssi) { /* no rssi data, no changes to reduce tx power */ diff --git a/trunk/drivers/net/wireless/iwlwifi/iwl-drv.c b/trunk/drivers/net/wireless/iwlwifi/iwl-drv.c index 49df0e9d5c5f..cdfdfaec395e 100644 --- a/trunk/drivers/net/wireless/iwlwifi/iwl-drv.c +++ b/trunk/drivers/net/wireless/iwlwifi/iwl-drv.c @@ -897,6 +897,7 @@ static void iwl_ucode_callback(const struct firmware *ucode_raw, void *context) /* We have our copies now, allow OS release its copies */ release_firmware(ucode_raw); + complete(&drv->request_firmware_complete); op = &iwlwifi_opmode_table[DVM_OP_MODE]; @@ -906,19 +907,10 @@ static void iwl_ucode_callback(const struct firmware *ucode_raw, void *context) if (op->ops) { const struct iwl_op_mode_ops *ops = op->ops; drv->op_mode = ops->start(drv->trans, drv->cfg, &drv->fw); - - if (!drv->op_mode) - goto out_unbind; } else { request_module_nowait("%s", op->name); } - /* - * Complete the firmware request last so that - * a driver unbind (stop) doesn't run while we - * are doing the start() above. - */ - complete(&drv->request_firmware_complete); return; try_again: diff --git a/trunk/drivers/net/wireless/iwlwifi/iwl-eeprom.c b/trunk/drivers/net/wireless/iwlwifi/iwl-eeprom.c index b8e2b223ac36..50c58911e718 100644 --- a/trunk/drivers/net/wireless/iwlwifi/iwl-eeprom.c +++ b/trunk/drivers/net/wireless/iwlwifi/iwl-eeprom.c @@ -568,28 +568,28 @@ static int iwl_find_otp_image(struct iwl_trans *trans, * iwl_get_max_txpower_avg - get the highest tx power from all chains. * find the highest tx power from all chains for the channel */ -static s8 iwl_get_max_txpower_avg(struct iwl_priv *priv, +static s8 iwl_get_max_txpower_avg(const struct iwl_cfg *cfg, struct iwl_eeprom_enhanced_txpwr *enhanced_txpower, int element, s8 *max_txpower_in_half_dbm) { s8 max_txpower_avg = 0; /* (dBm) */ /* Take the highest tx power from any valid chains */ - if ((priv->hw_params.valid_tx_ant & ANT_A) && + if ((cfg->valid_tx_ant & ANT_A) && (enhanced_txpower[element].chain_a_max > max_txpower_avg)) max_txpower_avg = enhanced_txpower[element].chain_a_max; - if ((priv->hw_params.valid_tx_ant & ANT_B) && + if ((cfg->valid_tx_ant & ANT_B) && (enhanced_txpower[element].chain_b_max > max_txpower_avg)) max_txpower_avg = enhanced_txpower[element].chain_b_max; - if ((priv->hw_params.valid_tx_ant & ANT_C) && + if ((cfg->valid_tx_ant & ANT_C) && (enhanced_txpower[element].chain_c_max > max_txpower_avg)) max_txpower_avg = enhanced_txpower[element].chain_c_max; - if (((priv->hw_params.valid_tx_ant == ANT_AB) | - (priv->hw_params.valid_tx_ant == ANT_BC) | - (priv->hw_params.valid_tx_ant == ANT_AC)) && + if (((cfg->valid_tx_ant == ANT_AB) | + (cfg->valid_tx_ant == ANT_BC) | + (cfg->valid_tx_ant == ANT_AC)) && (enhanced_txpower[element].mimo2_max > max_txpower_avg)) max_txpower_avg = enhanced_txpower[element].mimo2_max; - if ((priv->hw_params.valid_tx_ant == ANT_ABC) && + if ((cfg->valid_tx_ant == ANT_ABC) && (enhanced_txpower[element].mimo3_max > max_txpower_avg)) max_txpower_avg = enhanced_txpower[element].mimo3_max; @@ -691,7 +691,7 @@ static void iwl_eeprom_enhanced_txpower(struct iwl_priv *priv) ((txp->delta_20_in_40 & 0xf0) >> 4), (txp->delta_20_in_40 & 0x0f)); - max_txp_avg = iwl_get_max_txpower_avg(priv, txp_array, idx, + max_txp_avg = iwl_get_max_txpower_avg(priv->cfg, txp_array, idx, &max_txp_avg_halfdbm); /* diff --git a/trunk/drivers/net/wireless/iwlwifi/iwl-mac80211.c b/trunk/drivers/net/wireless/iwlwifi/iwl-mac80211.c index a55012609cac..ff66200b8eaa 100644 --- a/trunk/drivers/net/wireless/iwlwifi/iwl-mac80211.c +++ b/trunk/drivers/net/wireless/iwlwifi/iwl-mac80211.c @@ -199,7 +199,6 @@ int iwlagn_mac_setup_register(struct iwl_priv *priv, WIPHY_FLAG_DISABLE_BEACON_HINTS | WIPHY_FLAG_IBSS_RSN; -#ifdef CONFIG_PM_SLEEP if (priv->fw->img[IWL_UCODE_WOWLAN].sec[0].len && priv->trans->ops->wowlan_suspend && device_can_wakeup(priv->trans->dev)) { @@ -218,7 +217,6 @@ int iwlagn_mac_setup_register(struct iwl_priv *priv, hw->wiphy->wowlan.pattern_max_len = IWLAGN_WOWLAN_MAX_PATTERN_LEN; } -#endif if (iwlwifi_mod_params.power_save) hw->wiphy->flags |= WIPHY_FLAG_PS_ON_BY_DEFAULT; @@ -251,7 +249,6 @@ int iwlagn_mac_setup_register(struct iwl_priv *priv, ret = ieee80211_register_hw(priv->hw); if (ret) { IWL_ERR(priv, "Failed to register hw (error %d)\n", ret); - iwl_leds_exit(priv); return ret; } priv->mac80211_registered = 1; diff --git a/trunk/drivers/net/wireless/libertas/cfg.c b/trunk/drivers/net/wireless/libertas/cfg.c index f4a203049fb4..2fa879b015b6 100644 --- a/trunk/drivers/net/wireless/libertas/cfg.c +++ b/trunk/drivers/net/wireless/libertas/cfg.c @@ -435,40 +435,24 @@ static int lbs_add_wpa_tlv(u8 *tlv, const u8 *ie, u8 ie_len) * Set Channel */ -static int lbs_cfg_set_monitor_channel(struct wiphy *wiphy, - struct ieee80211_channel *channel, - enum nl80211_channel_type channel_type) +static int lbs_cfg_set_channel(struct wiphy *wiphy, + struct net_device *netdev, + struct ieee80211_channel *channel, + enum nl80211_channel_type channel_type) { struct lbs_private *priv = wiphy_priv(wiphy); int ret = -ENOTSUPP; - lbs_deb_enter_args(LBS_DEB_CFG80211, "freq %d, type %d", - channel->center_freq, channel_type); + lbs_deb_enter_args(LBS_DEB_CFG80211, "iface %s freq %d, type %d", + netdev_name(netdev), channel->center_freq, channel_type); if (channel_type != NL80211_CHAN_NO_HT) goto out; - ret = lbs_set_channel(priv, channel->hw_value); - - out: - lbs_deb_leave_args(LBS_DEB_CFG80211, "ret %d", ret); - return ret; -} - -static int lbs_cfg_set_mesh_channel(struct wiphy *wiphy, - struct net_device *netdev, - struct ieee80211_channel *channel) -{ - struct lbs_private *priv = wiphy_priv(wiphy); - int ret = -ENOTSUPP; - - lbs_deb_enter_args(LBS_DEB_CFG80211, "iface %s freq %d", - netdev_name(netdev), channel->center_freq); - - if (netdev != priv->mesh_dev) - goto out; - - ret = lbs_mesh_set_channel(priv, channel->hw_value); + if (netdev == priv->mesh_dev) + ret = lbs_mesh_set_channel(priv, channel->hw_value); + else + ret = lbs_set_channel(priv, channel->hw_value); out: lbs_deb_leave_args(LBS_DEB_CFG80211, "ret %d", ret); @@ -2045,8 +2029,7 @@ static int lbs_leave_ibss(struct wiphy *wiphy, struct net_device *dev) */ static struct cfg80211_ops lbs_cfg80211_ops = { - .set_monitor_channel = lbs_cfg_set_monitor_channel, - .libertas_set_mesh_channel = lbs_cfg_set_mesh_channel, + .set_channel = lbs_cfg_set_channel, .scan = lbs_cfg_scan, .connect = lbs_cfg_connect, .disconnect = lbs_cfg_disconnect, diff --git a/trunk/drivers/net/wireless/libertas/dev.h b/trunk/drivers/net/wireless/libertas/dev.h index 60996ce89f77..672005430aca 100644 --- a/trunk/drivers/net/wireless/libertas/dev.h +++ b/trunk/drivers/net/wireless/libertas/dev.h @@ -58,7 +58,6 @@ struct lbs_private { uint16_t mesh_tlv; u8 mesh_ssid[IEEE80211_MAX_SSID_LEN + 1]; u8 mesh_ssid_len; - u8 mesh_channel; #endif /* Debugfs */ diff --git a/trunk/drivers/net/wireless/libertas/mesh.c b/trunk/drivers/net/wireless/libertas/mesh.c index 97807751ebcf..e87c031b298f 100644 --- a/trunk/drivers/net/wireless/libertas/mesh.c +++ b/trunk/drivers/net/wireless/libertas/mesh.c @@ -131,13 +131,16 @@ static int lbs_mesh_config(struct lbs_private *priv, uint16_t action, int lbs_mesh_set_channel(struct lbs_private *priv, u8 channel) { - priv->mesh_channel = channel; return lbs_mesh_config(priv, CMD_ACT_MESH_CONFIG_START, channel); } static uint16_t lbs_mesh_get_channel(struct lbs_private *priv) { - return priv->mesh_channel ?: 1; + struct wireless_dev *mesh_wdev = priv->mesh_dev->ieee80211_ptr; + if (mesh_wdev->channel) + return mesh_wdev->channel->hw_value; + else + return 1; } /*************************************************************************** diff --git a/trunk/drivers/net/wireless/mac80211_hwsim.c b/trunk/drivers/net/wireless/mac80211_hwsim.c index 4c9336cee817..fb787df01666 100644 --- a/trunk/drivers/net/wireless/mac80211_hwsim.c +++ b/trunk/drivers/net/wireless/mac80211_hwsim.c @@ -1721,24 +1721,6 @@ static void hwsim_exit_netlink(void) "unregister family %i\n", ret); } -static const struct ieee80211_iface_limit hwsim_if_limits[] = { - { .max = 1, .types = BIT(NL80211_IFTYPE_ADHOC) }, - { .max = 2048, .types = BIT(NL80211_IFTYPE_STATION) | - BIT(NL80211_IFTYPE_P2P_CLIENT) | -#ifdef CONFIG_MAC80211_MESH - BIT(NL80211_IFTYPE_MESH_POINT) | -#endif - BIT(NL80211_IFTYPE_AP) | - BIT(NL80211_IFTYPE_P2P_GO) }, -}; - -static const struct ieee80211_iface_combination hwsim_if_comb = { - .limits = hwsim_if_limits, - .n_limits = ARRAY_SIZE(hwsim_if_limits), - .max_interfaces = 2048, - .num_different_channels = 1, -}; - static int __init init_mac80211_hwsim(void) { int i, err = 0; @@ -1800,9 +1782,6 @@ static int __init init_mac80211_hwsim(void) hw->wiphy->n_addresses = 2; hw->wiphy->addresses = data->addresses; - hw->wiphy->iface_combinations = &hwsim_if_comb; - hw->wiphy->n_iface_combinations = 1; - if (fake_hw_scan) { hw->wiphy->max_scan_ssids = 255; hw->wiphy->max_scan_ie_len = IEEE80211_MAX_DATA_LEN; diff --git a/trunk/drivers/net/wireless/orinoco/cfg.c b/trunk/drivers/net/wireless/orinoco/cfg.c index e15675585fb1..f7b15b8934fa 100644 --- a/trunk/drivers/net/wireless/orinoco/cfg.c +++ b/trunk/drivers/net/wireless/orinoco/cfg.c @@ -160,9 +160,10 @@ static int orinoco_scan(struct wiphy *wiphy, struct net_device *dev, return err; } -static int orinoco_set_monitor_channel(struct wiphy *wiphy, - struct ieee80211_channel *chan, - enum nl80211_channel_type channel_type) +static int orinoco_set_channel(struct wiphy *wiphy, + struct net_device *netdev, + struct ieee80211_channel *chan, + enum nl80211_channel_type channel_type) { struct orinoco_private *priv = wiphy_priv(wiphy); int err = 0; @@ -285,7 +286,7 @@ static int orinoco_set_wiphy_params(struct wiphy *wiphy, u32 changed) const struct cfg80211_ops orinoco_cfg_ops = { .change_virtual_intf = orinoco_change_vif, - .set_monitor_channel = orinoco_set_monitor_channel, + .set_channel = orinoco_set_channel, .scan = orinoco_scan, .set_wiphy_params = orinoco_set_wiphy_params, }; diff --git a/trunk/drivers/net/wireless/rt2x00/rt2800.h b/trunk/drivers/net/wireless/rt2x00/rt2800.h index 1ca88cdc6ece..6403f49da419 100644 --- a/trunk/drivers/net/wireless/rt2x00/rt2800.h +++ b/trunk/drivers/net/wireless/rt2x00/rt2800.h @@ -72,7 +72,6 @@ #define RF5370 0x5370 #define RF5372 0x5372 #define RF5390 0x5390 -#define RF5392 0x5392 /* * Chipset revisions. @@ -1946,11 +1945,6 @@ struct mac_iveiv_entry { */ #define RFCSR49_TX FIELD8(0x3f) -/* - * RFCSR 50: - */ -#define RFCSR50_TX FIELD8(0x3f) - /* * RF registers */ diff --git a/trunk/drivers/net/wireless/rt2x00/rt2800lib.c b/trunk/drivers/net/wireless/rt2x00/rt2800lib.c index 4d3747c3010b..11488e743f08 100644 --- a/trunk/drivers/net/wireless/rt2x00/rt2800lib.c +++ b/trunk/drivers/net/wireless/rt2x00/rt2800lib.c @@ -1958,22 +1958,7 @@ static void rt2800_config_channel_rf53xx(struct rt2x00_dev *rt2x00dev, rt2x00_set_field8(&rfcsr, RFCSR49_TX, info->default_power1); rt2800_rfcsr_write(rt2x00dev, 49, rfcsr); - if (rt2x00_rt(rt2x00dev, RT5392)) { - rt2800_rfcsr_read(rt2x00dev, 50, &rfcsr); - if (info->default_power1 > RT5390_POWER_BOUND) - rt2x00_set_field8(&rfcsr, RFCSR50_TX, - RT5390_POWER_BOUND); - else - rt2x00_set_field8(&rfcsr, RFCSR50_TX, - info->default_power2); - rt2800_rfcsr_write(rt2x00dev, 50, rfcsr); - } - rt2800_rfcsr_read(rt2x00dev, 1, &rfcsr); - if (rt2x00_rt(rt2x00dev, RT5392)) { - rt2x00_set_field8(&rfcsr, RFCSR1_RX1_PD, 1); - rt2x00_set_field8(&rfcsr, RFCSR1_TX1_PD, 1); - } rt2x00_set_field8(&rfcsr, RFCSR1_RF_BLOCK_EN, 1); rt2x00_set_field8(&rfcsr, RFCSR1_PLL_PD, 1); rt2x00_set_field8(&rfcsr, RFCSR1_RX0_PD, 1); @@ -2079,7 +2064,6 @@ static void rt2800_config_channel(struct rt2x00_dev *rt2x00dev, case RF5370: case RF5372: case RF5390: - case RF5392: rt2800_config_channel_rf53xx(rt2x00dev, conf, rf, info); break; default: @@ -2570,7 +2554,6 @@ void rt2800_vco_calibration(struct rt2x00_dev *rt2x00dev) case RF5370: case RF5372: case RF5390: - case RF5392: rt2800_rfcsr_read(rt2x00dev, 3, &rfcsr); rt2x00_set_field8(&rfcsr, RFCSR30_RF_CALIBRATION, 1); rt2800_rfcsr_write(rt2x00dev, 3, rfcsr); @@ -4286,7 +4269,6 @@ int rt2800_init_eeprom(struct rt2x00_dev *rt2x00dev) case RF5370: case RF5372: case RF5390: - case RF5392: break; default: ERROR(rt2x00dev, "Invalid RF chipset 0x%04x detected.\n", @@ -4601,8 +4583,7 @@ int rt2800_probe_hw_mode(struct rt2x00_dev *rt2x00dev) rt2x00_rf(rt2x00dev, RF5360) || rt2x00_rf(rt2x00dev, RF5370) || rt2x00_rf(rt2x00dev, RF5372) || - rt2x00_rf(rt2x00dev, RF5390) || - rt2x00_rf(rt2x00dev, RF5392)) { + rt2x00_rf(rt2x00dev, RF5390)) { spec->num_channels = 14; spec->channels = rf_vals_3x; } else if (rt2x00_rf(rt2x00dev, RF3052)) { @@ -4689,7 +4670,6 @@ int rt2800_probe_hw_mode(struct rt2x00_dev *rt2x00dev) case RF5370: case RF5372: case RF5390: - case RF5392: __set_bit(CAPABILITY_VCO_RECALIBRATION, &rt2x00dev->cap_flags); break; } diff --git a/trunk/drivers/net/wireless/rt2x00/rt2x00.h b/trunk/drivers/net/wireless/rt2x00/rt2x00.h index 8f754025b06e..ca36cccaba31 100644 --- a/trunk/drivers/net/wireless/rt2x00/rt2x00.h +++ b/trunk/drivers/net/wireless/rt2x00/rt2x00.h @@ -396,7 +396,8 @@ struct rt2x00_intf { * for hardware which doesn't support hardware * sequence counting. */ - atomic_t seqno; + spinlock_t seqlock; + u16 seqno; }; static inline struct rt2x00_intf* vif_to_intf(struct ieee80211_vif *vif) diff --git a/trunk/drivers/net/wireless/rt2x00/rt2x00dev.c b/trunk/drivers/net/wireless/rt2x00/rt2x00dev.c index a6b88bd4a1a5..e5404e576251 100644 --- a/trunk/drivers/net/wireless/rt2x00/rt2x00dev.c +++ b/trunk/drivers/net/wireless/rt2x00/rt2x00dev.c @@ -1161,8 +1161,6 @@ int rt2x00lib_probe_dev(struct rt2x00_dev *rt2x00dev) BIT(NL80211_IFTYPE_MESH_POINT) | BIT(NL80211_IFTYPE_WDS); - rt2x00dev->hw->wiphy->flags |= WIPHY_FLAG_IBSS_RSN; - /* * Initialize work. */ diff --git a/trunk/drivers/net/wireless/rt2x00/rt2x00mac.c b/trunk/drivers/net/wireless/rt2x00/rt2x00mac.c index 4ff26c2159bf..b49773ef72f2 100644 --- a/trunk/drivers/net/wireless/rt2x00/rt2x00mac.c +++ b/trunk/drivers/net/wireless/rt2x00/rt2x00mac.c @@ -277,6 +277,7 @@ int rt2x00mac_add_interface(struct ieee80211_hw *hw, else rt2x00dev->intf_sta_count++; + spin_lock_init(&intf->seqlock); mutex_init(&intf->beacon_skb_mutex); intf->beacon = entry; @@ -506,19 +507,9 @@ int rt2x00mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, if (!test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags)) return 0; - - if (!test_bit(CAPABILITY_HW_CRYPTO, &rt2x00dev->cap_flags)) - return -EOPNOTSUPP; - - /* - * To support IBSS RSN, don't program group keys in IBSS, the - * hardware will then not attempt to decrypt the frames. - */ - if (vif->type == NL80211_IFTYPE_ADHOC && - !(key->flags & IEEE80211_KEY_FLAG_PAIRWISE)) + else if (!test_bit(CAPABILITY_HW_CRYPTO, &rt2x00dev->cap_flags)) return -EOPNOTSUPP; - - if (key->keylen > 32) + else if (key->keylen > 32) return -ENOSPC; memset(&crypto, 0, sizeof(crypto)); diff --git a/trunk/drivers/net/wireless/rt2x00/rt2x00queue.c b/trunk/drivers/net/wireless/rt2x00/rt2x00queue.c index 2fd830103415..4c662eccf53c 100644 --- a/trunk/drivers/net/wireless/rt2x00/rt2x00queue.c +++ b/trunk/drivers/net/wireless/rt2x00/rt2x00queue.c @@ -207,7 +207,6 @@ static void rt2x00queue_create_tx_descriptor_seq(struct rt2x00_dev *rt2x00dev, struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; struct rt2x00_intf *intf = vif_to_intf(tx_info->control.vif); - u16 seqno; if (!(tx_info->flags & IEEE80211_TX_CTL_ASSIGN_SEQ)) return; @@ -239,13 +238,15 @@ static void rt2x00queue_create_tx_descriptor_seq(struct rt2x00_dev *rt2x00dev, * sequence counting per-frame, since those will override the * sequence counter given by mac80211. */ - if (test_bit(ENTRY_TXD_FIRST_FRAGMENT, &txdesc->flags)) - seqno = atomic_add_return(0x10, &intf->seqno); - else - seqno = atomic_read(&intf->seqno); + spin_lock(&intf->seqlock); + if (test_bit(ENTRY_TXD_FIRST_FRAGMENT, &txdesc->flags)) + intf->seqno += 0x10; hdr->seq_ctrl &= cpu_to_le16(IEEE80211_SCTL_FRAG); - hdr->seq_ctrl |= cpu_to_le16(seqno); + hdr->seq_ctrl |= cpu_to_le16(intf->seqno); + + spin_unlock(&intf->seqlock); + } static void rt2x00queue_create_tx_descriptor_plcp(struct rt2x00_dev *rt2x00dev, diff --git a/trunk/drivers/net/wireless/ti/Kconfig b/trunk/drivers/net/wireless/ti/Kconfig index be800119d0a3..1a72932e2213 100644 --- a/trunk/drivers/net/wireless/ti/Kconfig +++ b/trunk/drivers/net/wireless/ti/Kconfig @@ -8,7 +8,6 @@ menuconfig WL_TI if WL_TI source "drivers/net/wireless/ti/wl1251/Kconfig" source "drivers/net/wireless/ti/wl12xx/Kconfig" -source "drivers/net/wireless/ti/wl18xx/Kconfig" # keep last for automatic dependencies source "drivers/net/wireless/ti/wlcore/Kconfig" diff --git a/trunk/drivers/net/wireless/ti/Makefile b/trunk/drivers/net/wireless/ti/Makefile index 4d6823983c04..0a565622d4a4 100644 --- a/trunk/drivers/net/wireless/ti/Makefile +++ b/trunk/drivers/net/wireless/ti/Makefile @@ -2,4 +2,3 @@ obj-$(CONFIG_WLCORE) += wlcore/ obj-$(CONFIG_WL12XX) += wl12xx/ obj-$(CONFIG_WL12XX_PLATFORM_DATA) += wlcore/ obj-$(CONFIG_WL1251) += wl1251/ -obj-$(CONFIG_WL18XX) += wl18xx/ diff --git a/trunk/drivers/net/wireless/ti/wl12xx/Makefile b/trunk/drivers/net/wireless/ti/wl12xx/Makefile index da509aa7d009..87f64b14db35 100644 --- a/trunk/drivers/net/wireless/ti/wl12xx/Makefile +++ b/trunk/drivers/net/wireless/ti/wl12xx/Makefile @@ -1,3 +1,3 @@ -wl12xx-objs = main.o cmd.o acx.o debugfs.o +wl12xx-objs = main.o cmd.o acx.o obj-$(CONFIG_WL12XX) += wl12xx.o diff --git a/trunk/drivers/net/wireless/ti/wl12xx/acx.h b/trunk/drivers/net/wireless/ti/wl12xx/acx.h index 2a26868b837d..d1f5aba0afce 100644 --- a/trunk/drivers/net/wireless/ti/wl12xx/acx.h +++ b/trunk/drivers/net/wireless/ti/wl12xx/acx.h @@ -24,21 +24,6 @@ #define __WL12XX_ACX_H__ #include "../wlcore/wlcore.h" -#include "../wlcore/acx.h" - -#define WL12XX_ACX_ALL_EVENTS_VECTOR (WL1271_ACX_INTR_WATCHDOG | \ - WL1271_ACX_INTR_INIT_COMPLETE | \ - WL1271_ACX_INTR_EVENT_A | \ - WL1271_ACX_INTR_EVENT_B | \ - WL1271_ACX_INTR_CMD_COMPLETE | \ - WL1271_ACX_INTR_HW_AVAILABLE | \ - WL1271_ACX_INTR_DATA) - -#define WL12XX_INTR_MASK (WL1271_ACX_INTR_WATCHDOG | \ - WL1271_ACX_INTR_EVENT_A | \ - WL1271_ACX_INTR_EVENT_B | \ - WL1271_ACX_INTR_HW_AVAILABLE | \ - WL1271_ACX_INTR_DATA) struct wl1271_acx_host_config_bitmap { struct acx_header header; @@ -46,228 +31,6 @@ struct wl1271_acx_host_config_bitmap { __le32 host_cfg_bitmap; } __packed; -struct wl12xx_acx_tx_statistics { - __le32 internal_desc_overflow; -} __packed; - -struct wl12xx_acx_rx_statistics { - __le32 out_of_mem; - __le32 hdr_overflow; - __le32 hw_stuck; - __le32 dropped; - __le32 fcs_err; - __le32 xfr_hint_trig; - __le32 path_reset; - __le32 reset_counter; -} __packed; - -struct wl12xx_acx_dma_statistics { - __le32 rx_requested; - __le32 rx_errors; - __le32 tx_requested; - __le32 tx_errors; -} __packed; - -struct wl12xx_acx_isr_statistics { - /* host command complete */ - __le32 cmd_cmplt; - - /* fiqisr() */ - __le32 fiqs; - - /* (INT_STS_ND & INT_TRIG_RX_HEADER) */ - __le32 rx_headers; - - /* (INT_STS_ND & INT_TRIG_RX_CMPLT) */ - __le32 rx_completes; - - /* (INT_STS_ND & INT_TRIG_NO_RX_BUF) */ - __le32 rx_mem_overflow; - - /* (INT_STS_ND & INT_TRIG_S_RX_RDY) */ - __le32 rx_rdys; - - /* irqisr() */ - __le32 irqs; - - /* (INT_STS_ND & INT_TRIG_TX_PROC) */ - __le32 tx_procs; - - /* (INT_STS_ND & INT_TRIG_DECRYPT_DONE) */ - __le32 decrypt_done; - - /* (INT_STS_ND & INT_TRIG_DMA0) */ - __le32 dma0_done; - - /* (INT_STS_ND & INT_TRIG_DMA1) */ - __le32 dma1_done; - - /* (INT_STS_ND & INT_TRIG_TX_EXC_CMPLT) */ - __le32 tx_exch_complete; - - /* (INT_STS_ND & INT_TRIG_COMMAND) */ - __le32 commands; - - /* (INT_STS_ND & INT_TRIG_RX_PROC) */ - __le32 rx_procs; - - /* (INT_STS_ND & INT_TRIG_PM_802) */ - __le32 hw_pm_mode_changes; - - /* (INT_STS_ND & INT_TRIG_ACKNOWLEDGE) */ - __le32 host_acknowledges; - - /* (INT_STS_ND & INT_TRIG_PM_PCI) */ - __le32 pci_pm; - - /* (INT_STS_ND & INT_TRIG_ACM_WAKEUP) */ - __le32 wakeups; - - /* (INT_STS_ND & INT_TRIG_LOW_RSSI) */ - __le32 low_rssi; -} __packed; - -struct wl12xx_acx_wep_statistics { - /* WEP address keys configured */ - __le32 addr_key_count; - - /* default keys configured */ - __le32 default_key_count; - - __le32 reserved; - - /* number of times that WEP key not found on lookup */ - __le32 key_not_found; - - /* number of times that WEP key decryption failed */ - __le32 decrypt_fail; - - /* WEP packets decrypted */ - __le32 packets; - - /* WEP decrypt interrupts */ - __le32 interrupt; -} __packed; - -#define ACX_MISSED_BEACONS_SPREAD 10 - -struct wl12xx_acx_pwr_statistics { - /* the amount of enters into power save mode (both PD & ELP) */ - __le32 ps_enter; - - /* the amount of enters into ELP mode */ - __le32 elp_enter; - - /* the amount of missing beacon interrupts to the host */ - __le32 missing_bcns; - - /* the amount of wake on host-access times */ - __le32 wake_on_host; - - /* the amount of wake on timer-expire */ - __le32 wake_on_timer_exp; - - /* the number of packets that were transmitted with PS bit set */ - __le32 tx_with_ps; - - /* the number of packets that were transmitted with PS bit clear */ - __le32 tx_without_ps; - - /* the number of received beacons */ - __le32 rcvd_beacons; - - /* the number of entering into PowerOn (power save off) */ - __le32 power_save_off; - - /* the number of entries into power save mode */ - __le16 enable_ps; - - /* - * the number of exits from power save, not including failed PS - * transitions - */ - __le16 disable_ps; - - /* - * the number of times the TSF counter was adjusted because - * of drift - */ - __le32 fix_tsf_ps; - - /* Gives statistics about the spread continuous missed beacons. - * The 16 LSB are dedicated for the PS mode. - * The 16 MSB are dedicated for the PS mode. - * cont_miss_bcns_spread[0] - single missed beacon. - * cont_miss_bcns_spread[1] - two continuous missed beacons. - * cont_miss_bcns_spread[2] - three continuous missed beacons. - * ... - * cont_miss_bcns_spread[9] - ten and more continuous missed beacons. - */ - __le32 cont_miss_bcns_spread[ACX_MISSED_BEACONS_SPREAD]; - - /* the number of beacons in awake mode */ - __le32 rcvd_awake_beacons; -} __packed; - -struct wl12xx_acx_mic_statistics { - __le32 rx_pkts; - __le32 calc_failure; -} __packed; - -struct wl12xx_acx_aes_statistics { - __le32 encrypt_fail; - __le32 decrypt_fail; - __le32 encrypt_packets; - __le32 decrypt_packets; - __le32 encrypt_interrupt; - __le32 decrypt_interrupt; -} __packed; - -struct wl12xx_acx_event_statistics { - __le32 heart_beat; - __le32 calibration; - __le32 rx_mismatch; - __le32 rx_mem_empty; - __le32 rx_pool; - __le32 oom_late; - __le32 phy_transmit_error; - __le32 tx_stuck; -} __packed; - -struct wl12xx_acx_ps_statistics { - __le32 pspoll_timeouts; - __le32 upsd_timeouts; - __le32 upsd_max_sptime; - __le32 upsd_max_apturn; - __le32 pspoll_max_apturn; - __le32 pspoll_utilization; - __le32 upsd_utilization; -} __packed; - -struct wl12xx_acx_rxpipe_statistics { - __le32 rx_prep_beacon_drop; - __le32 descr_host_int_trig_rx_data; - __le32 beacon_buffer_thres_host_int_trig_rx_data; - __le32 missed_beacon_host_int_trig_rx_data; - __le32 tx_xfr_host_int_trig_rx_data; -} __packed; - -struct wl12xx_acx_statistics { - struct acx_header header; - - struct wl12xx_acx_tx_statistics tx; - struct wl12xx_acx_rx_statistics rx; - struct wl12xx_acx_dma_statistics dma; - struct wl12xx_acx_isr_statistics isr; - struct wl12xx_acx_wep_statistics wep; - struct wl12xx_acx_pwr_statistics pwr; - struct wl12xx_acx_aes_statistics aes; - struct wl12xx_acx_mic_statistics mic; - struct wl12xx_acx_event_statistics event; - struct wl12xx_acx_ps_statistics ps; - struct wl12xx_acx_rxpipe_statistics rxpipe; -} __packed; - int wl1271_acx_host_if_cfg_bitmap(struct wl1271 *wl, u32 host_cfg_bitmap); #endif /* __WL12XX_ACX_H__ */ diff --git a/trunk/drivers/net/wireless/ti/wl12xx/cmd.c b/trunk/drivers/net/wireless/ti/wl12xx/cmd.c index 50ba7480b790..8ffaeb5f2147 100644 --- a/trunk/drivers/net/wireless/ti/wl12xx/cmd.c +++ b/trunk/drivers/net/wireless/ti/wl12xx/cmd.c @@ -65,7 +65,6 @@ int wl1271_cmd_general_parms(struct wl1271 *wl) struct wl1271_general_parms_cmd *gen_parms; struct wl1271_ini_general_params *gp = &((struct wl1271_nvs_file *)wl->nvs)->general_params; - struct wl12xx_priv *priv = wl->priv; bool answer = false; int ret; @@ -89,7 +88,7 @@ int wl1271_cmd_general_parms(struct wl1271 *wl) answer = true; /* Override the REF CLK from the NVS with the one from platform data */ - gen_parms->general_params.ref_clock = priv->ref_clock; + gen_parms->general_params.ref_clock = wl->ref_clock; ret = wl1271_cmd_test(wl, gen_parms, sizeof(*gen_parms), answer); if (ret < 0) { @@ -119,7 +118,6 @@ int wl128x_cmd_general_parms(struct wl1271 *wl) struct wl128x_general_parms_cmd *gen_parms; struct wl128x_ini_general_params *gp = &((struct wl128x_nvs_file *)wl->nvs)->general_params; - struct wl12xx_priv *priv = wl->priv; bool answer = false; int ret; @@ -143,8 +141,8 @@ int wl128x_cmd_general_parms(struct wl1271 *wl) answer = true; /* Replace REF and TCXO CLKs with the ones from platform data */ - gen_parms->general_params.ref_clock = priv->ref_clock; - gen_parms->general_params.tcxo_ref_clock = priv->tcxo_clock; + gen_parms->general_params.ref_clock = wl->ref_clock; + gen_parms->general_params.tcxo_ref_clock = wl->tcxo_clock; ret = wl1271_cmd_test(wl, gen_parms, sizeof(*gen_parms), answer); if (ret < 0) { diff --git a/trunk/drivers/net/wireless/ti/wl12xx/debugfs.c b/trunk/drivers/net/wireless/ti/wl12xx/debugfs.c deleted file mode 100644 index 0521cbf858cf..000000000000 --- a/trunk/drivers/net/wireless/ti/wl12xx/debugfs.c +++ /dev/null @@ -1,243 +0,0 @@ -/* - * This file is part of wl12xx - * - * Copyright (C) 2009 Nokia Corporation - * Copyright (C) 2011-2012 Texas Instruments - * - * 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/debugfs.h" -#include "../wlcore/wlcore.h" - -#include "wl12xx.h" -#include "acx.h" -#include "debugfs.h" - -#define WL12XX_DEBUGFS_FWSTATS_FILE(a, b, c) \ - DEBUGFS_FWSTATS_FILE(a, b, c, wl12xx_acx_statistics) - -WL12XX_DEBUGFS_FWSTATS_FILE(tx, internal_desc_overflow, "%u"); - -WL12XX_DEBUGFS_FWSTATS_FILE(rx, out_of_mem, "%u"); -WL12XX_DEBUGFS_FWSTATS_FILE(rx, hdr_overflow, "%u"); -WL12XX_DEBUGFS_FWSTATS_FILE(rx, hw_stuck, "%u"); -WL12XX_DEBUGFS_FWSTATS_FILE(rx, dropped, "%u"); -WL12XX_DEBUGFS_FWSTATS_FILE(rx, fcs_err, "%u"); -WL12XX_DEBUGFS_FWSTATS_FILE(rx, xfr_hint_trig, "%u"); -WL12XX_DEBUGFS_FWSTATS_FILE(rx, path_reset, "%u"); -WL12XX_DEBUGFS_FWSTATS_FILE(rx, reset_counter, "%u"); - -WL12XX_DEBUGFS_FWSTATS_FILE(dma, rx_requested, "%u"); -WL12XX_DEBUGFS_FWSTATS_FILE(dma, rx_errors, "%u"); -WL12XX_DEBUGFS_FWSTATS_FILE(dma, tx_requested, "%u"); -WL12XX_DEBUGFS_FWSTATS_FILE(dma, tx_errors, "%u"); - -WL12XX_DEBUGFS_FWSTATS_FILE(isr, cmd_cmplt, "%u"); -WL12XX_DEBUGFS_FWSTATS_FILE(isr, fiqs, "%u"); -WL12XX_DEBUGFS_FWSTATS_FILE(isr, rx_headers, "%u"); -WL12XX_DEBUGFS_FWSTATS_FILE(isr, rx_mem_overflow, "%u"); -WL12XX_DEBUGFS_FWSTATS_FILE(isr, rx_rdys, "%u"); -WL12XX_DEBUGFS_FWSTATS_FILE(isr, irqs, "%u"); -WL12XX_DEBUGFS_FWSTATS_FILE(isr, tx_procs, "%u"); -WL12XX_DEBUGFS_FWSTATS_FILE(isr, decrypt_done, "%u"); -WL12XX_DEBUGFS_FWSTATS_FILE(isr, dma0_done, "%u"); -WL12XX_DEBUGFS_FWSTATS_FILE(isr, dma1_done, "%u"); -WL12XX_DEBUGFS_FWSTATS_FILE(isr, tx_exch_complete, "%u"); -WL12XX_DEBUGFS_FWSTATS_FILE(isr, commands, "%u"); -WL12XX_DEBUGFS_FWSTATS_FILE(isr, rx_procs, "%u"); -WL12XX_DEBUGFS_FWSTATS_FILE(isr, hw_pm_mode_changes, "%u"); -WL12XX_DEBUGFS_FWSTATS_FILE(isr, host_acknowledges, "%u"); -WL12XX_DEBUGFS_FWSTATS_FILE(isr, pci_pm, "%u"); -WL12XX_DEBUGFS_FWSTATS_FILE(isr, wakeups, "%u"); -WL12XX_DEBUGFS_FWSTATS_FILE(isr, low_rssi, "%u"); - -WL12XX_DEBUGFS_FWSTATS_FILE(wep, addr_key_count, "%u"); -WL12XX_DEBUGFS_FWSTATS_FILE(wep, default_key_count, "%u"); -/* skipping wep.reserved */ -WL12XX_DEBUGFS_FWSTATS_FILE(wep, key_not_found, "%u"); -WL12XX_DEBUGFS_FWSTATS_FILE(wep, decrypt_fail, "%u"); -WL12XX_DEBUGFS_FWSTATS_FILE(wep, packets, "%u"); -WL12XX_DEBUGFS_FWSTATS_FILE(wep, interrupt, "%u"); - -WL12XX_DEBUGFS_FWSTATS_FILE(pwr, ps_enter, "%u"); -WL12XX_DEBUGFS_FWSTATS_FILE(pwr, elp_enter, "%u"); -WL12XX_DEBUGFS_FWSTATS_FILE(pwr, missing_bcns, "%u"); -WL12XX_DEBUGFS_FWSTATS_FILE(pwr, wake_on_host, "%u"); -WL12XX_DEBUGFS_FWSTATS_FILE(pwr, wake_on_timer_exp, "%u"); -WL12XX_DEBUGFS_FWSTATS_FILE(pwr, tx_with_ps, "%u"); -WL12XX_DEBUGFS_FWSTATS_FILE(pwr, tx_without_ps, "%u"); -WL12XX_DEBUGFS_FWSTATS_FILE(pwr, rcvd_beacons, "%u"); -WL12XX_DEBUGFS_FWSTATS_FILE(pwr, power_save_off, "%u"); -WL12XX_DEBUGFS_FWSTATS_FILE(pwr, enable_ps, "%u"); -WL12XX_DEBUGFS_FWSTATS_FILE(pwr, disable_ps, "%u"); -WL12XX_DEBUGFS_FWSTATS_FILE(pwr, fix_tsf_ps, "%u"); -/* skipping cont_miss_bcns_spread for now */ -WL12XX_DEBUGFS_FWSTATS_FILE(pwr, rcvd_awake_beacons, "%u"); - -WL12XX_DEBUGFS_FWSTATS_FILE(mic, rx_pkts, "%u"); -WL12XX_DEBUGFS_FWSTATS_FILE(mic, calc_failure, "%u"); - -WL12XX_DEBUGFS_FWSTATS_FILE(aes, encrypt_fail, "%u"); -WL12XX_DEBUGFS_FWSTATS_FILE(aes, decrypt_fail, "%u"); -WL12XX_DEBUGFS_FWSTATS_FILE(aes, encrypt_packets, "%u"); -WL12XX_DEBUGFS_FWSTATS_FILE(aes, decrypt_packets, "%u"); -WL12XX_DEBUGFS_FWSTATS_FILE(aes, encrypt_interrupt, "%u"); -WL12XX_DEBUGFS_FWSTATS_FILE(aes, decrypt_interrupt, "%u"); - -WL12XX_DEBUGFS_FWSTATS_FILE(event, heart_beat, "%u"); -WL12XX_DEBUGFS_FWSTATS_FILE(event, calibration, "%u"); -WL12XX_DEBUGFS_FWSTATS_FILE(event, rx_mismatch, "%u"); -WL12XX_DEBUGFS_FWSTATS_FILE(event, rx_mem_empty, "%u"); -WL12XX_DEBUGFS_FWSTATS_FILE(event, rx_pool, "%u"); -WL12XX_DEBUGFS_FWSTATS_FILE(event, oom_late, "%u"); -WL12XX_DEBUGFS_FWSTATS_FILE(event, phy_transmit_error, "%u"); -WL12XX_DEBUGFS_FWSTATS_FILE(event, tx_stuck, "%u"); - -WL12XX_DEBUGFS_FWSTATS_FILE(ps, pspoll_timeouts, "%u"); -WL12XX_DEBUGFS_FWSTATS_FILE(ps, upsd_timeouts, "%u"); -WL12XX_DEBUGFS_FWSTATS_FILE(ps, upsd_max_sptime, "%u"); -WL12XX_DEBUGFS_FWSTATS_FILE(ps, upsd_max_apturn, "%u"); -WL12XX_DEBUGFS_FWSTATS_FILE(ps, pspoll_max_apturn, "%u"); -WL12XX_DEBUGFS_FWSTATS_FILE(ps, pspoll_utilization, "%u"); -WL12XX_DEBUGFS_FWSTATS_FILE(ps, upsd_utilization, "%u"); - -WL12XX_DEBUGFS_FWSTATS_FILE(rxpipe, rx_prep_beacon_drop, "%u"); -WL12XX_DEBUGFS_FWSTATS_FILE(rxpipe, descr_host_int_trig_rx_data, "%u"); -WL12XX_DEBUGFS_FWSTATS_FILE(rxpipe, beacon_buffer_thres_host_int_trig_rx_data, - "%u"); -WL12XX_DEBUGFS_FWSTATS_FILE(rxpipe, missed_beacon_host_int_trig_rx_data, "%u"); -WL12XX_DEBUGFS_FWSTATS_FILE(rxpipe, tx_xfr_host_int_trig_rx_data, "%u"); - -int wl12xx_debugfs_add_files(struct wl1271 *wl, - struct dentry *rootdir) -{ - int ret = 0; - struct dentry *entry, *stats, *moddir; - - moddir = debugfs_create_dir(KBUILD_MODNAME, rootdir); - if (!moddir || IS_ERR(moddir)) { - entry = moddir; - goto err; - } - - stats = debugfs_create_dir("fw_stats", moddir); - if (!stats || IS_ERR(stats)) { - entry = stats; - goto err; - } - - DEBUGFS_FWSTATS_ADD(tx, internal_desc_overflow); - - DEBUGFS_FWSTATS_ADD(rx, out_of_mem); - DEBUGFS_FWSTATS_ADD(rx, hdr_overflow); - DEBUGFS_FWSTATS_ADD(rx, hw_stuck); - DEBUGFS_FWSTATS_ADD(rx, dropped); - DEBUGFS_FWSTATS_ADD(rx, fcs_err); - DEBUGFS_FWSTATS_ADD(rx, xfr_hint_trig); - DEBUGFS_FWSTATS_ADD(rx, path_reset); - DEBUGFS_FWSTATS_ADD(rx, reset_counter); - - DEBUGFS_FWSTATS_ADD(dma, rx_requested); - DEBUGFS_FWSTATS_ADD(dma, rx_errors); - DEBUGFS_FWSTATS_ADD(dma, tx_requested); - DEBUGFS_FWSTATS_ADD(dma, tx_errors); - - DEBUGFS_FWSTATS_ADD(isr, cmd_cmplt); - DEBUGFS_FWSTATS_ADD(isr, fiqs); - DEBUGFS_FWSTATS_ADD(isr, rx_headers); - DEBUGFS_FWSTATS_ADD(isr, rx_mem_overflow); - DEBUGFS_FWSTATS_ADD(isr, rx_rdys); - DEBUGFS_FWSTATS_ADD(isr, irqs); - DEBUGFS_FWSTATS_ADD(isr, tx_procs); - DEBUGFS_FWSTATS_ADD(isr, decrypt_done); - DEBUGFS_FWSTATS_ADD(isr, dma0_done); - DEBUGFS_FWSTATS_ADD(isr, dma1_done); - DEBUGFS_FWSTATS_ADD(isr, tx_exch_complete); - DEBUGFS_FWSTATS_ADD(isr, commands); - DEBUGFS_FWSTATS_ADD(isr, rx_procs); - DEBUGFS_FWSTATS_ADD(isr, hw_pm_mode_changes); - DEBUGFS_FWSTATS_ADD(isr, host_acknowledges); - DEBUGFS_FWSTATS_ADD(isr, pci_pm); - DEBUGFS_FWSTATS_ADD(isr, wakeups); - DEBUGFS_FWSTATS_ADD(isr, low_rssi); - - DEBUGFS_FWSTATS_ADD(wep, addr_key_count); - DEBUGFS_FWSTATS_ADD(wep, default_key_count); - /* skipping wep.reserved */ - DEBUGFS_FWSTATS_ADD(wep, key_not_found); - DEBUGFS_FWSTATS_ADD(wep, decrypt_fail); - DEBUGFS_FWSTATS_ADD(wep, packets); - DEBUGFS_FWSTATS_ADD(wep, interrupt); - - DEBUGFS_FWSTATS_ADD(pwr, ps_enter); - DEBUGFS_FWSTATS_ADD(pwr, elp_enter); - DEBUGFS_FWSTATS_ADD(pwr, missing_bcns); - DEBUGFS_FWSTATS_ADD(pwr, wake_on_host); - DEBUGFS_FWSTATS_ADD(pwr, wake_on_timer_exp); - DEBUGFS_FWSTATS_ADD(pwr, tx_with_ps); - DEBUGFS_FWSTATS_ADD(pwr, tx_without_ps); - DEBUGFS_FWSTATS_ADD(pwr, rcvd_beacons); - DEBUGFS_FWSTATS_ADD(pwr, power_save_off); - DEBUGFS_FWSTATS_ADD(pwr, enable_ps); - DEBUGFS_FWSTATS_ADD(pwr, disable_ps); - DEBUGFS_FWSTATS_ADD(pwr, fix_tsf_ps); - /* skipping cont_miss_bcns_spread for now */ - DEBUGFS_FWSTATS_ADD(pwr, rcvd_awake_beacons); - - DEBUGFS_FWSTATS_ADD(mic, rx_pkts); - DEBUGFS_FWSTATS_ADD(mic, calc_failure); - - DEBUGFS_FWSTATS_ADD(aes, encrypt_fail); - DEBUGFS_FWSTATS_ADD(aes, decrypt_fail); - DEBUGFS_FWSTATS_ADD(aes, encrypt_packets); - DEBUGFS_FWSTATS_ADD(aes, decrypt_packets); - DEBUGFS_FWSTATS_ADD(aes, encrypt_interrupt); - DEBUGFS_FWSTATS_ADD(aes, decrypt_interrupt); - - DEBUGFS_FWSTATS_ADD(event, heart_beat); - DEBUGFS_FWSTATS_ADD(event, calibration); - DEBUGFS_FWSTATS_ADD(event, rx_mismatch); - DEBUGFS_FWSTATS_ADD(event, rx_mem_empty); - DEBUGFS_FWSTATS_ADD(event, rx_pool); - DEBUGFS_FWSTATS_ADD(event, oom_late); - DEBUGFS_FWSTATS_ADD(event, phy_transmit_error); - DEBUGFS_FWSTATS_ADD(event, tx_stuck); - - DEBUGFS_FWSTATS_ADD(ps, pspoll_timeouts); - DEBUGFS_FWSTATS_ADD(ps, upsd_timeouts); - DEBUGFS_FWSTATS_ADD(ps, upsd_max_sptime); - DEBUGFS_FWSTATS_ADD(ps, upsd_max_apturn); - DEBUGFS_FWSTATS_ADD(ps, pspoll_max_apturn); - DEBUGFS_FWSTATS_ADD(ps, pspoll_utilization); - DEBUGFS_FWSTATS_ADD(ps, upsd_utilization); - - DEBUGFS_FWSTATS_ADD(rxpipe, rx_prep_beacon_drop); - DEBUGFS_FWSTATS_ADD(rxpipe, descr_host_int_trig_rx_data); - DEBUGFS_FWSTATS_ADD(rxpipe, beacon_buffer_thres_host_int_trig_rx_data); - DEBUGFS_FWSTATS_ADD(rxpipe, missed_beacon_host_int_trig_rx_data); - DEBUGFS_FWSTATS_ADD(rxpipe, tx_xfr_host_int_trig_rx_data); - - return 0; - -err: - if (IS_ERR(entry)) - ret = PTR_ERR(entry); - else - ret = -ENOMEM; - - return ret; -} diff --git a/trunk/drivers/net/wireless/ti/wl12xx/debugfs.h b/trunk/drivers/net/wireless/ti/wl12xx/debugfs.h deleted file mode 100644 index 96898e291b78..000000000000 --- a/trunk/drivers/net/wireless/ti/wl12xx/debugfs.h +++ /dev/null @@ -1,28 +0,0 @@ -/* - * This file is part of wl12xx - * - * Copyright (C) 2012 Texas Instruments. All rights reserved. - * - * 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 - * - */ - -#ifndef __WL12XX_DEBUGFS_H__ -#define __WL12XX_DEBUGFS_H__ - -int wl12xx_debugfs_add_files(struct wl1271 *wl, - struct dentry *rootdir); - -#endif /* __WL12XX_DEBUGFS_H__ */ diff --git a/trunk/drivers/net/wireless/ti/wl12xx/main.c b/trunk/drivers/net/wireless/ti/wl12xx/main.c index 85d1600ee340..d7dd3def07b5 100644 --- a/trunk/drivers/net/wireless/ti/wl12xx/main.c +++ b/trunk/drivers/net/wireless/ti/wl12xx/main.c @@ -39,10 +39,6 @@ #include "reg.h" #include "cmd.h" #include "acx.h" -#include "debugfs.h" - -static char *fref_param; -static char *tcxo_param; static struct wlcore_conf wl12xx_conf = { .sg = { @@ -216,7 +212,7 @@ static struct wlcore_conf wl12xx_conf = { .suspend_wake_up_event = CONF_WAKE_UP_EVENT_N_DTIM, .suspend_listen_interval = 3, .bcn_filt_mode = CONF_BCN_FILT_MODE_ENABLED, - .bcn_filt_ie_count = 3, + .bcn_filt_ie_count = 2, .bcn_filt_ie = { [0] = { .ie = WLAN_EID_CHANNEL_SWITCH, @@ -226,13 +222,9 @@ static struct wlcore_conf wl12xx_conf = { .ie = WLAN_EID_HT_OPERATION, .rule = CONF_BCN_RULE_PASS_ON_CHANGE, }, - [2] = { - .ie = WLAN_EID_ERP_INFO, - .rule = CONF_BCN_RULE_PASS_ON_CHANGE, - }, }, - .synch_fail_thold = 12, - .bss_lose_timeout = 400, + .synch_fail_thold = 10, + .bss_lose_timeout = 100, .beacon_rx_timeout = 10000, .broadcast_timeout = 20000, .rx_broadcast_in_ps = 1, @@ -242,7 +234,7 @@ static struct wlcore_conf wl12xx_conf = { .psm_entry_retries = 8, .psm_exit_retries = 16, .psm_entry_nullfunc_retries = 3, - .dynamic_ps_timeout = 200, + .dynamic_ps_timeout = 40, .forced_ps = false, .keep_alive_interval = 55000, .max_listen_interval = 20, @@ -253,7 +245,7 @@ static struct wlcore_conf wl12xx_conf = { }, .pm_config = { .host_clk_settling_time = 5000, - .host_fast_wakeup_support = CONF_FAST_WAKEUP_DISABLE, + .host_fast_wakeup_support = false }, .roam_trigger = { .trigger_pacing = 1, @@ -313,8 +305,8 @@ static struct wlcore_conf wl12xx_conf = { .swallow_period = 5, .n_divider_fref_set_1 = 0xff, /* default */ .n_divider_fref_set_2 = 12, - .m_divider_fref_set_1 = 0xffff, - .m_divider_fref_set_2 = 148, /* default */ + .m_divider_fref_set_1 = 148, + .m_divider_fref_set_2 = 0xffff, /* default */ .coex_pll_stabilization_time = 0xffffffff, /* default */ .ldo_stabilization_time = 0xffff, /* default */ .fm_disturbed_band_margin = 0xff, /* default */ @@ -601,7 +593,7 @@ static void wl127x_prepare_read(struct wl1271 *wl, u32 rx_desc, u32 len) { if (wl->chip.id != CHIP_ID_1283_PG20) { struct wl1271_acx_mem_map *wl_mem_map = wl->target_mem_map; - struct wl127x_rx_mem_pool_addr rx_mem_addr; + struct wl1271_rx_mem_pool_addr rx_mem_addr; /* * Choose the block we want to read @@ -629,8 +621,10 @@ static int wl12xx_identify_chip(struct wl1271 *wl) wl1271_warning("chip id 0x%x (1271 PG10) support is obsolete", wl->chip.id); - wl->quirks |= WLCORE_QUIRK_LEGACY_NVS | - WLCORE_QUIRK_TKIP_HEADER_SPACE; + /* clear the alignment quirk, since we don't support it */ + wl->quirks &= ~WLCORE_QUIRK_TX_BLOCKSIZE_ALIGN; + + wl->quirks |= WLCORE_QUIRK_LEGACY_NVS; wl->sr_fw_name = WL127X_FW_NAME_SINGLE; wl->mr_fw_name = WL127X_FW_NAME_MULTI; memcpy(&wl->conf.mem, &wl12xx_default_priv_conf.mem_wl127x, @@ -645,8 +639,10 @@ static int wl12xx_identify_chip(struct wl1271 *wl) wl1271_debug(DEBUG_BOOT, "chip id 0x%x (1271 PG20)", wl->chip.id); - wl->quirks |= WLCORE_QUIRK_LEGACY_NVS | - WLCORE_QUIRK_TKIP_HEADER_SPACE; + /* clear the alignment quirk, since we don't support it */ + wl->quirks &= ~WLCORE_QUIRK_TX_BLOCKSIZE_ALIGN; + + wl->quirks |= WLCORE_QUIRK_LEGACY_NVS; wl->plt_fw_name = WL127X_PLT_FW_NAME; wl->sr_fw_name = WL127X_FW_NAME_SINGLE; wl->mr_fw_name = WL127X_FW_NAME_MULTI; @@ -664,11 +660,6 @@ static int wl12xx_identify_chip(struct wl1271 *wl) wl->plt_fw_name = WL128X_PLT_FW_NAME; wl->sr_fw_name = WL128X_FW_NAME_SINGLE; wl->mr_fw_name = WL128X_FW_NAME_MULTI; - - /* wl128x requires TX blocksize alignment */ - wl->quirks |= WLCORE_QUIRK_TX_BLOCKSIZE_ALIGN | - WLCORE_QUIRK_TKIP_HEADER_SPACE; - break; case CHIP_ID_1283_PG10: default: @@ -782,7 +773,6 @@ static int wl128x_configure_mcs_pll(struct wl1271 *wl, int clk) u16 spare_reg; u16 pll_config; u8 input_freq; - struct wl12xx_priv *priv = wl->priv; /* Mask bits [3:1] in the sys_clk_cfg register */ spare_reg = wl12xx_top_reg_read(wl, WL_SPARE_REG); @@ -792,8 +782,8 @@ static int wl128x_configure_mcs_pll(struct wl1271 *wl, int clk) wl12xx_top_reg_write(wl, WL_SPARE_REG, spare_reg); /* Handle special cases of the TCXO clock */ - if (priv->tcxo_clock == WL12XX_TCXOCLOCK_16_8 || - priv->tcxo_clock == WL12XX_TCXOCLOCK_33_6) + if (wl->tcxo_clock == WL12XX_TCXOCLOCK_16_8 || + wl->tcxo_clock == WL12XX_TCXOCLOCK_33_6) return wl128x_manually_configure_mcs_pll(wl); /* Set the input frequency according to the selected clock source */ @@ -818,12 +808,11 @@ static int wl128x_configure_mcs_pll(struct wl1271 *wl, int clk) */ static int wl128x_boot_clk(struct wl1271 *wl, int *selected_clock) { - struct wl12xx_priv *priv = wl->priv; u16 sys_clk_cfg; /* For XTAL-only modes, FREF will be used after switching from TCXO */ - if (priv->ref_clock == WL12XX_REFCLOCK_26_XTAL || - priv->ref_clock == WL12XX_REFCLOCK_38_XTAL) { + if (wl->ref_clock == WL12XX_REFCLOCK_26_XTAL || + wl->ref_clock == WL12XX_REFCLOCK_38_XTAL) { if (!wl128x_switch_tcxo_to_fref(wl)) return -EINVAL; goto fref_clk; @@ -837,8 +826,8 @@ static int wl128x_boot_clk(struct wl1271 *wl, int *selected_clock) goto fref_clk; /* If TCXO is either 32.736MHz or 16.368MHz, switch to FREF */ - if (priv->tcxo_clock == WL12XX_TCXOCLOCK_16_368 || - priv->tcxo_clock == WL12XX_TCXOCLOCK_32_736) { + if (wl->tcxo_clock == WL12XX_TCXOCLOCK_16_368 || + wl->tcxo_clock == WL12XX_TCXOCLOCK_32_736) { if (!wl128x_switch_tcxo_to_fref(wl)) return -EINVAL; goto fref_clk; @@ -847,14 +836,14 @@ static int wl128x_boot_clk(struct wl1271 *wl, int *selected_clock) /* TCXO clock is selected */ if (!wl128x_is_tcxo_valid(wl)) return -EINVAL; - *selected_clock = priv->tcxo_clock; + *selected_clock = wl->tcxo_clock; goto config_mcs_pll; fref_clk: /* FREF clock is selected */ if (!wl128x_is_fref_valid(wl)) return -EINVAL; - *selected_clock = priv->ref_clock; + *selected_clock = wl->ref_clock; config_mcs_pll: return wl128x_configure_mcs_pll(wl, *selected_clock); @@ -862,27 +851,25 @@ static int wl128x_boot_clk(struct wl1271 *wl, int *selected_clock) static int wl127x_boot_clk(struct wl1271 *wl) { - struct wl12xx_priv *priv = wl->priv; u32 pause; u32 clk; if (WL127X_PG_GET_MAJOR(wl->hw_pg_ver) < 3) wl->quirks |= WLCORE_QUIRK_END_OF_TRANSACTION; - if (priv->ref_clock == CONF_REF_CLK_19_2_E || - priv->ref_clock == CONF_REF_CLK_38_4_E || - priv->ref_clock == CONF_REF_CLK_38_4_M_XTAL) + if (wl->ref_clock == CONF_REF_CLK_19_2_E || + wl->ref_clock == CONF_REF_CLK_38_4_E || + wl->ref_clock == CONF_REF_CLK_38_4_M_XTAL) /* ref clk: 19.2/38.4/38.4-XTAL */ clk = 0x3; - else if (priv->ref_clock == CONF_REF_CLK_26_E || - priv->ref_clock == CONF_REF_CLK_26_M_XTAL || - priv->ref_clock == CONF_REF_CLK_52_E) + else if (wl->ref_clock == CONF_REF_CLK_26_E || + wl->ref_clock == CONF_REF_CLK_52_E) /* ref clk: 26/52 */ clk = 0x5; else return -EINVAL; - if (priv->ref_clock != CONF_REF_CLK_19_2_E) { + if (wl->ref_clock != CONF_REF_CLK_19_2_E) { u16 val; /* Set clock type (open drain) */ val = wl12xx_top_reg_read(wl, OCP_REG_CLK_TYPE); @@ -952,7 +939,6 @@ static int wl1271_boot_soft_reset(struct wl1271 *wl) static int wl12xx_pre_boot(struct wl1271 *wl) { - struct wl12xx_priv *priv = wl->priv; int ret = 0; u32 clk; int selected_clock = -1; @@ -984,7 +970,7 @@ static int wl12xx_pre_boot(struct wl1271 *wl) if (wl->chip.id == CHIP_ID_1283_PG20) clk |= ((selected_clock & 0x3) << 1) << 4; else - clk |= (priv->ref_clock << 1) << 4; + clk |= (wl->ref_clock << 1) << 4; wl1271_write32(wl, WL12XX_DRPW_SCRATCH_START, clk); @@ -1003,7 +989,7 @@ static int wl12xx_pre_boot(struct wl1271 *wl) static void wl12xx_pre_upload(struct wl1271 *wl) { - u32 tmp, polarity; + u32 tmp; /* write firmware's last address (ie. it's length) to * ACX_EEPROMLESS_IND_REG */ @@ -1023,23 +1009,23 @@ static void wl12xx_pre_upload(struct wl1271 *wl) if (wl->chip.id == CHIP_ID_1283_PG20) wl12xx_top_reg_write(wl, SDIO_IO_DS, HCI_IO_DS_6MA); +} + +static void wl12xx_enable_interrupts(struct wl1271 *wl) +{ + u32 polarity; - /* polarity must be set before the firmware is loaded */ polarity = wl12xx_top_reg_read(wl, OCP_REG_POLARITY); /* We use HIGH polarity, so unset the LOW bit */ polarity &= ~POLARITY_LOW; wl12xx_top_reg_write(wl, OCP_REG_POLARITY, polarity); -} - -static void wl12xx_enable_interrupts(struct wl1271 *wl) -{ - wlcore_write_reg(wl, REG_INTERRUPT_MASK, WL12XX_ACX_ALL_EVENTS_VECTOR); + wlcore_write_reg(wl, REG_INTERRUPT_MASK, WL1271_ACX_ALL_EVENTS_VECTOR); wlcore_enable_interrupts(wl); wlcore_write_reg(wl, REG_INTERRUPT_MASK, - WL1271_ACX_INTR_ALL & ~(WL12XX_INTR_MASK)); + WL1271_ACX_INTR_ALL & ~(WL1271_INTR_MASK)); wl1271_write32(wl, WL12XX_HI_CFG, HI_CFG_DEF_VAL); } @@ -1163,8 +1149,7 @@ static u32 wl12xx_get_rx_packet_len(struct wl1271 *wl, void *rx_data, static void wl12xx_tx_delayed_compl(struct wl1271 *wl) { - if (wl->fw_status_1->tx_results_counter == - (wl->tx_results_count & 0xff)) + if (wl->fw_status->tx_results_counter == (wl->tx_results_count & 0xff)) return; wl1271_tx_complete(wl); @@ -1303,90 +1288,10 @@ static void wl12xx_get_mac(struct wl1271 *wl) wl12xx_get_fuse_mac(wl); } -static void wl12xx_set_tx_desc_csum(struct wl1271 *wl, - struct wl1271_tx_hw_descr *desc, - struct sk_buff *skb) -{ - desc->wl12xx_reserved = 0; -} - -static int wl12xx_plt_init(struct wl1271 *wl) -{ - int ret; - - ret = wl->ops->boot(wl); - if (ret < 0) - goto out; - - ret = wl->ops->hw_init(wl); - if (ret < 0) - goto out_irq_disable; - - ret = wl1271_acx_init_mem_config(wl); - if (ret < 0) - goto out_irq_disable; - - ret = wl12xx_acx_mem_cfg(wl); - if (ret < 0) - goto out_free_memmap; - - /* Enable data path */ - ret = wl1271_cmd_data_path(wl, 1); - if (ret < 0) - goto out_free_memmap; - - /* Configure for CAM power saving (ie. always active) */ - ret = wl1271_acx_sleep_auth(wl, WL1271_PSM_CAM); - if (ret < 0) - goto out_free_memmap; - - /* configure PM */ - ret = wl1271_acx_pm_config(wl); - if (ret < 0) - goto out_free_memmap; - - goto out; - -out_free_memmap: - kfree(wl->target_mem_map); - wl->target_mem_map = NULL; - -out_irq_disable: - mutex_unlock(&wl->mutex); - /* Unlocking the mutex in the middle of handling is - inherently unsafe. In this case we deem it safe to do, - because we need to let any possibly pending IRQ out of - the system (and while we are WL1271_STATE_OFF the IRQ - work function will not do anything.) Also, any other - possible concurrent operations will fail due to the - current state, hence the wl1271 struct should be safe. */ - wlcore_disable_interrupts(wl); - mutex_lock(&wl->mutex); -out: - return ret; -} - -static int wl12xx_get_spare_blocks(struct wl1271 *wl, bool is_gem) -{ - if (is_gem) - return WL12XX_TX_HW_BLOCK_GEM_SPARE; - - return WL12XX_TX_HW_BLOCK_SPARE_DEFAULT; -} - -static int wl12xx_set_key(struct wl1271 *wl, enum set_key_cmd cmd, - struct ieee80211_vif *vif, - struct ieee80211_sta *sta, - struct ieee80211_key_conf *key_conf) -{ - return wlcore_set_key(wl, cmd, vif, sta, key_conf); -} - static struct wlcore_ops wl12xx_ops = { .identify_chip = wl12xx_identify_chip, .identify_fw = wl12xx_identify_fw, .boot = wl12xx_boot, - .plt_init = wl12xx_plt_init, .trigger_cmd = wl12xx_trigger_cmd, .ack_event = wl12xx_ack_event, .calc_tx_blocks = wl12xx_calc_tx_blocks, @@ -1401,13 +1306,6 @@ static struct wlcore_ops wl12xx_ops = { .sta_get_ap_rate_mask = wl12xx_sta_get_ap_rate_mask, .get_pg_ver = wl12xx_get_pg_ver, .get_mac = wl12xx_get_mac, - .set_tx_desc_csum = wl12xx_set_tx_desc_csum, - .set_rx_csum = NULL, - .ap_get_mimo_wide_rate_mask = NULL, - .debugfs_init = wl12xx_debugfs_add_files, - .get_spare_blocks = wl12xx_get_spare_blocks, - .set_key = wl12xx_set_key, - .pre_pkt_send = NULL, }; static struct ieee80211_sta_ht_cap wl12xx_ht_cap = { @@ -1425,7 +1323,6 @@ static struct ieee80211_sta_ht_cap wl12xx_ht_cap = { static int __devinit wl12xx_probe(struct platform_device *pdev) { - struct wl12xx_platform_data *pdata = pdev->dev.platform_data; struct wl1271 *wl; struct ieee80211_hw *hw; struct wl12xx_priv *priv; @@ -1437,65 +1334,19 @@ static int __devinit wl12xx_probe(struct platform_device *pdev) } wl = hw->priv; - priv = wl->priv; wl->ops = &wl12xx_ops; wl->ptable = wl12xx_ptable; wl->rtable = wl12xx_rtable; wl->num_tx_desc = 16; - wl->num_rx_desc = 8; + wl->normal_tx_spare = WL12XX_TX_HW_BLOCK_SPARE_DEFAULT; + wl->gem_tx_spare = WL12XX_TX_HW_BLOCK_GEM_SPARE; wl->band_rate_to_idx = wl12xx_band_rate_to_idx; wl->hw_tx_rate_tbl_size = WL12XX_CONF_HW_RXTX_RATE_MAX; wl->hw_min_ht_rate = WL12XX_CONF_HW_RXTX_RATE_MCS0; wl->fw_status_priv_len = 0; - wl->stats.fw_stats_len = sizeof(struct wl12xx_acx_statistics); - memcpy(&wl->ht_cap[IEEE80211_BAND_2GHZ], &wl12xx_ht_cap, - sizeof(wl12xx_ht_cap)); - memcpy(&wl->ht_cap[IEEE80211_BAND_5GHZ], &wl12xx_ht_cap, - sizeof(wl12xx_ht_cap)); + memcpy(&wl->ht_cap, &wl12xx_ht_cap, sizeof(wl12xx_ht_cap)); wl12xx_conf_init(wl); - if (!fref_param) { - priv->ref_clock = pdata->board_ref_clock; - } else { - if (!strcmp(fref_param, "19.2")) - priv->ref_clock = WL12XX_REFCLOCK_19; - else if (!strcmp(fref_param, "26")) - priv->ref_clock = WL12XX_REFCLOCK_26; - else if (!strcmp(fref_param, "26x")) - priv->ref_clock = WL12XX_REFCLOCK_26_XTAL; - else if (!strcmp(fref_param, "38.4")) - priv->ref_clock = WL12XX_REFCLOCK_38; - else if (!strcmp(fref_param, "38.4x")) - priv->ref_clock = WL12XX_REFCLOCK_38_XTAL; - else if (!strcmp(fref_param, "52")) - priv->ref_clock = WL12XX_REFCLOCK_52; - else - wl1271_error("Invalid fref parameter %s", fref_param); - } - - if (!tcxo_param) { - priv->tcxo_clock = pdata->board_tcxo_clock; - } else { - if (!strcmp(tcxo_param, "19.2")) - priv->tcxo_clock = WL12XX_TCXOCLOCK_19_2; - else if (!strcmp(tcxo_param, "26")) - priv->tcxo_clock = WL12XX_TCXOCLOCK_26; - else if (!strcmp(tcxo_param, "38.4")) - priv->tcxo_clock = WL12XX_TCXOCLOCK_38_4; - else if (!strcmp(tcxo_param, "52")) - priv->tcxo_clock = WL12XX_TCXOCLOCK_52; - else if (!strcmp(tcxo_param, "16.368")) - priv->tcxo_clock = WL12XX_TCXOCLOCK_16_368; - else if (!strcmp(tcxo_param, "32.736")) - priv->tcxo_clock = WL12XX_TCXOCLOCK_32_736; - else if (!strcmp(tcxo_param, "16.8")) - priv->tcxo_clock = WL12XX_TCXOCLOCK_16_8; - else if (!strcmp(tcxo_param, "33.6")) - priv->tcxo_clock = WL12XX_TCXOCLOCK_33_6; - else - wl1271_error("Invalid tcxo parameter %s", tcxo_param); - } - return wlcore_probe(wl, pdev); } @@ -1527,13 +1378,6 @@ static void __exit wl12xx_exit(void) } module_exit(wl12xx_exit); -module_param_named(fref, fref_param, charp, 0); -MODULE_PARM_DESC(fref, "FREF clock: 19.2, 26, 26x, 38.4, 38.4x, 52"); - -module_param_named(tcxo, tcxo_param, charp, 0); -MODULE_PARM_DESC(tcxo, - "TCXO clock: 19.2, 26, 38.4, 52, 16.368, 32.736, 16.8, 33.6"); - MODULE_LICENSE("GPL v2"); MODULE_AUTHOR("Luciano Coelho "); MODULE_FIRMWARE(WL127X_FW_NAME_SINGLE); diff --git a/trunk/drivers/net/wireless/ti/wl12xx/wl12xx.h b/trunk/drivers/net/wireless/ti/wl12xx/wl12xx.h index de1132410876..74cd332e23ef 100644 --- a/trunk/drivers/net/wireless/ti/wl12xx/wl12xx.h +++ b/trunk/drivers/net/wireless/ti/wl12xx/wl12xx.h @@ -24,16 +24,8 @@ #include "conf.h" -struct wl127x_rx_mem_pool_addr { - u32 addr; - u32 addr_extra; -}; - struct wl12xx_priv { struct wl12xx_priv_conf conf; - - int ref_clock; - int tcxo_clock; }; #endif /* __WL12XX_PRIV_H__ */ diff --git a/trunk/drivers/net/wireless/ti/wl18xx/Kconfig b/trunk/drivers/net/wireless/ti/wl18xx/Kconfig deleted file mode 100644 index 1cfdb2548821..000000000000 --- a/trunk/drivers/net/wireless/ti/wl18xx/Kconfig +++ /dev/null @@ -1,7 +0,0 @@ -config WL18XX - tristate "TI wl18xx support" - depends on MAC80211 - select WLCORE - ---help--- - This module adds support for wireless adapters based on TI - WiLink 8 chipsets. diff --git a/trunk/drivers/net/wireless/ti/wl18xx/Makefile b/trunk/drivers/net/wireless/ti/wl18xx/Makefile deleted file mode 100644 index 67c098734c7f..000000000000 --- a/trunk/drivers/net/wireless/ti/wl18xx/Makefile +++ /dev/null @@ -1,3 +0,0 @@ -wl18xx-objs = main.o acx.o tx.o io.o debugfs.o - -obj-$(CONFIG_WL18XX) += wl18xx.o diff --git a/trunk/drivers/net/wireless/ti/wl18xx/acx.c b/trunk/drivers/net/wireless/ti/wl18xx/acx.c deleted file mode 100644 index 72840e23bf59..000000000000 --- a/trunk/drivers/net/wireless/ti/wl18xx/acx.c +++ /dev/null @@ -1,111 +0,0 @@ -/* - * 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/acx.h" - -#include "acx.h" - -int wl18xx_acx_host_if_cfg_bitmap(struct wl1271 *wl, u32 host_cfg_bitmap, - u32 sdio_blk_size, u32 extra_mem_blks, - u32 len_field_size) -{ - struct wl18xx_acx_host_config_bitmap *bitmap_conf; - int ret; - - wl1271_debug(DEBUG_ACX, "acx cfg bitmap %d blk %d spare %d field %d", - host_cfg_bitmap, sdio_blk_size, extra_mem_blks, - len_field_size); - - bitmap_conf = kzalloc(sizeof(*bitmap_conf), GFP_KERNEL); - if (!bitmap_conf) { - ret = -ENOMEM; - goto out; - } - - bitmap_conf->host_cfg_bitmap = cpu_to_le32(host_cfg_bitmap); - bitmap_conf->host_sdio_block_size = cpu_to_le32(sdio_blk_size); - bitmap_conf->extra_mem_blocks = cpu_to_le32(extra_mem_blks); - bitmap_conf->length_field_size = cpu_to_le32(len_field_size); - - ret = wl1271_cmd_configure(wl, ACX_HOST_IF_CFG_BITMAP, - bitmap_conf, sizeof(*bitmap_conf)); - if (ret < 0) { - wl1271_warning("wl1271 bitmap config opt failed: %d", ret); - goto out; - } - -out: - kfree(bitmap_conf); - - return ret; -} - -int wl18xx_acx_set_checksum_state(struct wl1271 *wl) -{ - struct wl18xx_acx_checksum_state *acx; - int ret; - - wl1271_debug(DEBUG_ACX, "acx checksum state"); - - acx = kzalloc(sizeof(*acx), GFP_KERNEL); - if (!acx) { - ret = -ENOMEM; - goto out; - } - - acx->checksum_state = CHECKSUM_OFFLOAD_ENABLED; - - ret = wl1271_cmd_configure(wl, ACX_CHECKSUM_CONFIG, acx, sizeof(*acx)); - if (ret < 0) { - wl1271_warning("failed to set Tx checksum state: %d", ret); - goto out; - } - -out: - kfree(acx); - return ret; -} - -int wl18xx_acx_clear_statistics(struct wl1271 *wl) -{ - struct wl18xx_acx_clear_statistics *acx; - int ret = 0; - - wl1271_debug(DEBUG_ACX, "acx clear statistics"); - - acx = kzalloc(sizeof(*acx), GFP_KERNEL); - if (!acx) { - ret = -ENOMEM; - goto out; - } - - ret = wl1271_cmd_configure(wl, ACX_CLEAR_STATISTICS, acx, sizeof(*acx)); - if (ret < 0) { - wl1271_warning("failed to clear firmware statistics: %d", ret); - goto out; - } - -out: - kfree(acx); - return ret; -} diff --git a/trunk/drivers/net/wireless/ti/wl18xx/acx.h b/trunk/drivers/net/wireless/ti/wl18xx/acx.h deleted file mode 100644 index ebbaf611e97b..000000000000 --- a/trunk/drivers/net/wireless/ti/wl18xx/acx.h +++ /dev/null @@ -1,291 +0,0 @@ -/* - * This file is part of wl18xx - * - * Copyright (C) 2011 Texas Instruments. All rights reserved. - * - * 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 - * - */ - -#ifndef __WL18XX_ACX_H__ -#define __WL18XX_ACX_H__ - -#include "../wlcore/wlcore.h" -#include "../wlcore/acx.h" - -enum { - ACX_CLEAR_STATISTICS = 0x0047, -}; - -/* numbers of bits the length field takes (add 1 for the actual number) */ -#define WL18XX_HOST_IF_LEN_SIZE_FIELD 15 - -#define WL18XX_ACX_EVENTS_VECTOR_PG1 (WL1271_ACX_INTR_WATCHDOG | \ - WL1271_ACX_INTR_INIT_COMPLETE | \ - WL1271_ACX_INTR_EVENT_A | \ - WL1271_ACX_INTR_EVENT_B | \ - WL1271_ACX_INTR_CMD_COMPLETE | \ - WL1271_ACX_INTR_HW_AVAILABLE | \ - WL1271_ACX_INTR_DATA) - -#define WL18XX_ACX_EVENTS_VECTOR_PG2 (WL18XX_ACX_EVENTS_VECTOR_PG1 | \ - WL1271_ACX_SW_INTR_WATCHDOG) - -#define WL18XX_INTR_MASK_PG1 (WL1271_ACX_INTR_WATCHDOG | \ - WL1271_ACX_INTR_EVENT_A | \ - WL1271_ACX_INTR_EVENT_B | \ - WL1271_ACX_INTR_HW_AVAILABLE | \ - WL1271_ACX_INTR_DATA) - -#define WL18XX_INTR_MASK_PG2 (WL18XX_INTR_MASK_PG1 | \ - WL1271_ACX_SW_INTR_WATCHDOG) - -struct wl18xx_acx_host_config_bitmap { - struct acx_header header; - - __le32 host_cfg_bitmap; - - __le32 host_sdio_block_size; - - /* extra mem blocks per frame in TX. */ - __le32 extra_mem_blocks; - - /* - * number of bits of the length field in the first TX word - * (up to 15 - for using the entire 16 bits). - */ - __le32 length_field_size; - -} __packed; - -enum { - CHECKSUM_OFFLOAD_DISABLED = 0, - CHECKSUM_OFFLOAD_ENABLED = 1, - CHECKSUM_OFFLOAD_FAKE_RX = 2, - CHECKSUM_OFFLOAD_INVALID = 0xFF -}; - -struct wl18xx_acx_checksum_state { - struct acx_header header; - - /* enum acx_checksum_state */ - u8 checksum_state; - u8 pad[3]; -} __packed; - - -struct wl18xx_acx_error_stats { - u32 error_frame; - u32 error_null_Frame_tx_start; - u32 error_numll_frame_cts_start; - u32 error_bar_retry; - u32 error_frame_cts_nul_flid; -} __packed; - -struct wl18xx_acx_debug_stats { - u32 debug1; - u32 debug2; - u32 debug3; - u32 debug4; - u32 debug5; - u32 debug6; -} __packed; - -struct wl18xx_acx_ring_stats { - u32 prepared_descs; - u32 tx_cmplt; -} __packed; - -struct wl18xx_acx_tx_stats { - u32 tx_prepared_descs; - u32 tx_cmplt; - u32 tx_template_prepared; - u32 tx_data_prepared; - u32 tx_template_programmed; - u32 tx_data_programmed; - u32 tx_burst_programmed; - u32 tx_starts; - u32 tx_imm_resp; - u32 tx_start_templates; - u32 tx_start_int_templates; - u32 tx_start_fw_gen; - u32 tx_start_data; - u32 tx_start_null_frame; - u32 tx_exch; - u32 tx_retry_template; - u32 tx_retry_data; - u32 tx_exch_pending; - u32 tx_exch_expiry; - u32 tx_done_template; - u32 tx_done_data; - u32 tx_done_int_template; - u32 tx_frame_checksum; - u32 tx_checksum_result; - u32 frag_called; - u32 frag_mpdu_alloc_failed; - u32 frag_init_called; - u32 frag_in_process_called; - u32 frag_tkip_called; - u32 frag_key_not_found; - u32 frag_need_fragmentation; - u32 frag_bad_mblk_num; - u32 frag_failed; - u32 frag_cache_hit; - u32 frag_cache_miss; -} __packed; - -struct wl18xx_acx_rx_stats { - u32 rx_beacon_early_term; - u32 rx_out_of_mpdu_nodes; - u32 rx_hdr_overflow; - u32 rx_dropped_frame; - u32 rx_done_stage; - u32 rx_done; - u32 rx_defrag; - u32 rx_defrag_end; - u32 rx_cmplt; - u32 rx_pre_complt; - u32 rx_cmplt_task; - u32 rx_phy_hdr; - u32 rx_timeout; - u32 rx_timeout_wa; - u32 rx_wa_density_dropped_frame; - u32 rx_wa_ba_not_expected; - u32 rx_frame_checksum; - u32 rx_checksum_result; - u32 defrag_called; - u32 defrag_init_called; - u32 defrag_in_process_called; - u32 defrag_tkip_called; - u32 defrag_need_defrag; - u32 defrag_decrypt_failed; - u32 decrypt_key_not_found; - u32 defrag_need_decrypt; - u32 rx_tkip_replays; -} __packed; - -struct wl18xx_acx_isr_stats { - u32 irqs; -} __packed; - -#define PWR_STAT_MAX_CONT_MISSED_BCNS_SPREAD 10 - -struct wl18xx_acx_pwr_stats { - u32 missing_bcns_cnt; - u32 rcvd_bcns_cnt; - u32 connection_out_of_sync; - u32 cont_miss_bcns_spread[PWR_STAT_MAX_CONT_MISSED_BCNS_SPREAD]; - u32 rcvd_awake_bcns_cnt; -} __packed; - -struct wl18xx_acx_event_stats { - u32 calibration; - u32 rx_mismatch; - u32 rx_mem_empty; -} __packed; - -struct wl18xx_acx_ps_poll_stats { - u32 ps_poll_timeouts; - u32 upsd_timeouts; - u32 upsd_max_ap_turn; - u32 ps_poll_max_ap_turn; - u32 ps_poll_utilization; - u32 upsd_utilization; -} __packed; - -struct wl18xx_acx_rx_filter_stats { - u32 beacon_filter; - u32 arp_filter; - u32 mc_filter; - u32 dup_filter; - u32 data_filter; - u32 ibss_filter; - u32 protection_filter; - u32 accum_arp_pend_requests; - u32 max_arp_queue_dep; -} __packed; - -struct wl18xx_acx_rx_rate_stats { - u32 rx_frames_per_rates[50]; -} __packed; - -#define AGGR_STATS_TX_AGG 16 -#define AGGR_STATS_TX_RATE 16 -#define AGGR_STATS_RX_SIZE_LEN 16 - -struct wl18xx_acx_aggr_stats { - u32 tx_agg_vs_rate[AGGR_STATS_TX_AGG * AGGR_STATS_TX_RATE]; - u32 rx_size[AGGR_STATS_RX_SIZE_LEN]; -} __packed; - -#define PIPE_STATS_HW_FIFO 11 - -struct wl18xx_acx_pipeline_stats { - u32 hs_tx_stat_fifo_int; - u32 hs_rx_stat_fifo_int; - u32 tcp_tx_stat_fifo_int; - u32 tcp_rx_stat_fifo_int; - u32 enc_tx_stat_fifo_int; - u32 enc_rx_stat_fifo_int; - u32 rx_complete_stat_fifo_int; - u32 pre_proc_swi; - u32 post_proc_swi; - u32 sec_frag_swi; - u32 pre_to_defrag_swi; - u32 defrag_to_csum_swi; - u32 csum_to_rx_xfer_swi; - u32 dec_packet_in; - u32 dec_packet_in_fifo_full; - u32 dec_packet_out; - u32 cs_rx_packet_in; - u32 cs_rx_packet_out; - u16 pipeline_fifo_full[PIPE_STATS_HW_FIFO]; -} __packed; - -struct wl18xx_acx_mem_stats { - u32 rx_free_mem_blks; - u32 tx_free_mem_blks; - u32 fwlog_free_mem_blks; - u32 fw_gen_free_mem_blks; -} __packed; - -struct wl18xx_acx_statistics { - struct acx_header header; - - struct wl18xx_acx_error_stats error; - struct wl18xx_acx_debug_stats debug; - struct wl18xx_acx_tx_stats tx; - struct wl18xx_acx_rx_stats rx; - struct wl18xx_acx_isr_stats isr; - struct wl18xx_acx_pwr_stats pwr; - struct wl18xx_acx_ps_poll_stats ps_poll; - struct wl18xx_acx_rx_filter_stats rx_filter; - struct wl18xx_acx_rx_rate_stats rx_rate; - struct wl18xx_acx_aggr_stats aggr_size; - struct wl18xx_acx_pipeline_stats pipeline; - struct wl18xx_acx_mem_stats mem; -} __packed; - -struct wl18xx_acx_clear_statistics { - struct acx_header header; -}; - -int wl18xx_acx_host_if_cfg_bitmap(struct wl1271 *wl, u32 host_cfg_bitmap, - u32 sdio_blk_size, u32 extra_mem_blks, - u32 len_field_size); -int wl18xx_acx_set_checksum_state(struct wl1271 *wl); -int wl18xx_acx_clear_statistics(struct wl1271 *wl); - -#endif /* __WL18XX_ACX_H__ */ diff --git a/trunk/drivers/net/wireless/ti/wl18xx/conf.h b/trunk/drivers/net/wireless/ti/wl18xx/conf.h deleted file mode 100644 index fac0b7e87e75..000000000000 --- a/trunk/drivers/net/wireless/ti/wl18xx/conf.h +++ /dev/null @@ -1,92 +0,0 @@ -/* - * 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 - * - */ - -#ifndef __WL18XX_CONF_H__ -#define __WL18XX_CONF_H__ - -#define WL18XX_CONF_MAGIC 0x10e100ca -#define WL18XX_CONF_VERSION (WLCORE_CONF_VERSION | 0x0002) -#define WL18XX_CONF_MASK 0x0000ffff -#define WL18XX_CONF_SIZE (WLCORE_CONF_SIZE + \ - sizeof(struct wl18xx_priv_conf)) - -#define NUM_OF_CHANNELS_11_ABG 150 -#define NUM_OF_CHANNELS_11_P 7 -#define WL18XX_NUM_OF_SUB_BANDS 9 -#define SRF_TABLE_LEN 16 -#define PIN_MUXING_SIZE 2 - -struct wl18xx_mac_and_phy_params { - u8 phy_standalone; - u8 rdl; - u8 enable_clpc; - u8 enable_tx_low_pwr_on_siso_rdl; - u8 auto_detect; - u8 dedicated_fem; - - u8 low_band_component; - - /* Bit 0: One Hot, Bit 1: Control Enable, Bit 2: 1.8V, Bit 3: 3V */ - u8 low_band_component_type; - - u8 high_band_component; - - /* Bit 0: One Hot, Bit 1: Control Enable, Bit 2: 1.8V, Bit 3: 3V */ - u8 high_band_component_type; - u8 number_of_assembled_ant2_4; - u8 number_of_assembled_ant5; - u8 pin_muxing_platform_options[PIN_MUXING_SIZE]; - u8 external_pa_dc2dc; - u8 tcxo_ldo_voltage; - u8 xtal_itrim_val; - u8 srf_state; - u8 srf1[SRF_TABLE_LEN]; - u8 srf2[SRF_TABLE_LEN]; - u8 srf3[SRF_TABLE_LEN]; - u8 io_configuration; - u8 sdio_configuration; - u8 settings; - u8 rx_profile; - u8 per_chan_pwr_limit_arr_11abg[NUM_OF_CHANNELS_11_ABG]; - u8 pwr_limit_reference_11_abg; - u8 per_chan_pwr_limit_arr_11p[NUM_OF_CHANNELS_11_P]; - u8 pwr_limit_reference_11p; - u8 per_sub_band_tx_trace_loss[WL18XX_NUM_OF_SUB_BANDS]; - u8 per_sub_band_rx_trace_loss[WL18XX_NUM_OF_SUB_BANDS]; - u8 primary_clock_setting_time; - u8 clock_valid_on_wake_up; - u8 secondary_clock_setting_time; - u8 board_type; - /* enable point saturation */ - u8 psat; - /* low/medium/high Tx power in dBm */ - s8 low_power_val; - s8 med_power_val; - s8 high_power_val; - u8 padding[1]; -} __packed; - -struct wl18xx_priv_conf { - /* this structure is copied wholesale to FW */ - struct wl18xx_mac_and_phy_params phy; -} __packed; - -#endif /* __WL18XX_CONF_H__ */ diff --git a/trunk/drivers/net/wireless/ti/wl18xx/debugfs.c b/trunk/drivers/net/wireless/ti/wl18xx/debugfs.c deleted file mode 100644 index 3ce6f1039af3..000000000000 --- a/trunk/drivers/net/wireless/ti/wl18xx/debugfs.c +++ /dev/null @@ -1,403 +0,0 @@ -/* - * This file is part of wl18xx - * - * Copyright (C) 2009 Nokia Corporation - * Copyright (C) 2011-2012 Texas Instruments - * - * 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/debugfs.h" -#include "../wlcore/wlcore.h" - -#include "wl18xx.h" -#include "acx.h" -#include "debugfs.h" - -#define WL18XX_DEBUGFS_FWSTATS_FILE(a, b, c) \ - DEBUGFS_FWSTATS_FILE(a, b, c, wl18xx_acx_statistics) -#define WL18XX_DEBUGFS_FWSTATS_FILE_ARRAY(a, b, c) \ - DEBUGFS_FWSTATS_FILE_ARRAY(a, b, c, wl18xx_acx_statistics) - - -WL18XX_DEBUGFS_FWSTATS_FILE(debug, debug1, "%u"); -WL18XX_DEBUGFS_FWSTATS_FILE(debug, debug2, "%u"); -WL18XX_DEBUGFS_FWSTATS_FILE(debug, debug3, "%u"); -WL18XX_DEBUGFS_FWSTATS_FILE(debug, debug4, "%u"); -WL18XX_DEBUGFS_FWSTATS_FILE(debug, debug5, "%u"); -WL18XX_DEBUGFS_FWSTATS_FILE(debug, debug6, "%u"); - -WL18XX_DEBUGFS_FWSTATS_FILE(error, error_frame, "%u"); -WL18XX_DEBUGFS_FWSTATS_FILE(error, error_null_Frame_tx_start, "%u"); -WL18XX_DEBUGFS_FWSTATS_FILE(error, error_numll_frame_cts_start, "%u"); -WL18XX_DEBUGFS_FWSTATS_FILE(error, error_bar_retry, "%u"); -WL18XX_DEBUGFS_FWSTATS_FILE(error, error_frame_cts_nul_flid, "%u"); - -WL18XX_DEBUGFS_FWSTATS_FILE(tx, tx_prepared_descs, "%u"); -WL18XX_DEBUGFS_FWSTATS_FILE(tx, tx_cmplt, "%u"); -WL18XX_DEBUGFS_FWSTATS_FILE(tx, tx_template_prepared, "%u"); -WL18XX_DEBUGFS_FWSTATS_FILE(tx, tx_data_prepared, "%u"); -WL18XX_DEBUGFS_FWSTATS_FILE(tx, tx_template_programmed, "%u"); -WL18XX_DEBUGFS_FWSTATS_FILE(tx, tx_data_programmed, "%u"); -WL18XX_DEBUGFS_FWSTATS_FILE(tx, tx_burst_programmed, "%u"); -WL18XX_DEBUGFS_FWSTATS_FILE(tx, tx_starts, "%u"); -WL18XX_DEBUGFS_FWSTATS_FILE(tx, tx_imm_resp, "%u"); -WL18XX_DEBUGFS_FWSTATS_FILE(tx, tx_start_templates, "%u"); -WL18XX_DEBUGFS_FWSTATS_FILE(tx, tx_start_int_templates, "%u"); -WL18XX_DEBUGFS_FWSTATS_FILE(tx, tx_start_fw_gen, "%u"); -WL18XX_DEBUGFS_FWSTATS_FILE(tx, tx_start_data, "%u"); -WL18XX_DEBUGFS_FWSTATS_FILE(tx, tx_start_null_frame, "%u"); -WL18XX_DEBUGFS_FWSTATS_FILE(tx, tx_exch, "%u"); -WL18XX_DEBUGFS_FWSTATS_FILE(tx, tx_retry_template, "%u"); -WL18XX_DEBUGFS_FWSTATS_FILE(tx, tx_retry_data, "%u"); -WL18XX_DEBUGFS_FWSTATS_FILE(tx, tx_exch_pending, "%u"); -WL18XX_DEBUGFS_FWSTATS_FILE(tx, tx_exch_expiry, "%u"); -WL18XX_DEBUGFS_FWSTATS_FILE(tx, tx_done_template, "%u"); -WL18XX_DEBUGFS_FWSTATS_FILE(tx, tx_done_data, "%u"); -WL18XX_DEBUGFS_FWSTATS_FILE(tx, tx_done_int_template, "%u"); -WL18XX_DEBUGFS_FWSTATS_FILE(tx, tx_frame_checksum, "%u"); -WL18XX_DEBUGFS_FWSTATS_FILE(tx, tx_checksum_result, "%u"); -WL18XX_DEBUGFS_FWSTATS_FILE(tx, frag_called, "%u"); -WL18XX_DEBUGFS_FWSTATS_FILE(tx, frag_mpdu_alloc_failed, "%u"); -WL18XX_DEBUGFS_FWSTATS_FILE(tx, frag_init_called, "%u"); -WL18XX_DEBUGFS_FWSTATS_FILE(tx, frag_in_process_called, "%u"); -WL18XX_DEBUGFS_FWSTATS_FILE(tx, frag_tkip_called, "%u"); -WL18XX_DEBUGFS_FWSTATS_FILE(tx, frag_key_not_found, "%u"); -WL18XX_DEBUGFS_FWSTATS_FILE(tx, frag_need_fragmentation, "%u"); -WL18XX_DEBUGFS_FWSTATS_FILE(tx, frag_bad_mblk_num, "%u"); -WL18XX_DEBUGFS_FWSTATS_FILE(tx, frag_failed, "%u"); -WL18XX_DEBUGFS_FWSTATS_FILE(tx, frag_cache_hit, "%u"); -WL18XX_DEBUGFS_FWSTATS_FILE(tx, frag_cache_miss, "%u"); - -WL18XX_DEBUGFS_FWSTATS_FILE(rx, rx_beacon_early_term, "%u"); -WL18XX_DEBUGFS_FWSTATS_FILE(rx, rx_out_of_mpdu_nodes, "%u"); -WL18XX_DEBUGFS_FWSTATS_FILE(rx, rx_hdr_overflow, "%u"); -WL18XX_DEBUGFS_FWSTATS_FILE(rx, rx_dropped_frame, "%u"); -WL18XX_DEBUGFS_FWSTATS_FILE(rx, rx_done, "%u"); -WL18XX_DEBUGFS_FWSTATS_FILE(rx, rx_defrag, "%u"); -WL18XX_DEBUGFS_FWSTATS_FILE(rx, rx_defrag_end, "%u"); -WL18XX_DEBUGFS_FWSTATS_FILE(rx, rx_cmplt, "%u"); -WL18XX_DEBUGFS_FWSTATS_FILE(rx, rx_pre_complt, "%u"); -WL18XX_DEBUGFS_FWSTATS_FILE(rx, rx_cmplt_task, "%u"); -WL18XX_DEBUGFS_FWSTATS_FILE(rx, rx_phy_hdr, "%u"); -WL18XX_DEBUGFS_FWSTATS_FILE(rx, rx_timeout, "%u"); -WL18XX_DEBUGFS_FWSTATS_FILE(rx, rx_timeout_wa, "%u"); -WL18XX_DEBUGFS_FWSTATS_FILE(rx, rx_wa_density_dropped_frame, "%u"); -WL18XX_DEBUGFS_FWSTATS_FILE(rx, rx_wa_ba_not_expected, "%u"); -WL18XX_DEBUGFS_FWSTATS_FILE(rx, rx_frame_checksum, "%u"); -WL18XX_DEBUGFS_FWSTATS_FILE(rx, rx_checksum_result, "%u"); -WL18XX_DEBUGFS_FWSTATS_FILE(rx, defrag_called, "%u"); -WL18XX_DEBUGFS_FWSTATS_FILE(rx, defrag_init_called, "%u"); -WL18XX_DEBUGFS_FWSTATS_FILE(rx, defrag_in_process_called, "%u"); -WL18XX_DEBUGFS_FWSTATS_FILE(rx, defrag_tkip_called, "%u"); -WL18XX_DEBUGFS_FWSTATS_FILE(rx, defrag_need_defrag, "%u"); -WL18XX_DEBUGFS_FWSTATS_FILE(rx, defrag_decrypt_failed, "%u"); -WL18XX_DEBUGFS_FWSTATS_FILE(rx, decrypt_key_not_found, "%u"); -WL18XX_DEBUGFS_FWSTATS_FILE(rx, defrag_need_decrypt, "%u"); -WL18XX_DEBUGFS_FWSTATS_FILE(rx, rx_tkip_replays, "%u"); - -WL18XX_DEBUGFS_FWSTATS_FILE(isr, irqs, "%u"); - -WL18XX_DEBUGFS_FWSTATS_FILE(pwr, missing_bcns_cnt, "%u"); -WL18XX_DEBUGFS_FWSTATS_FILE(pwr, rcvd_bcns_cnt, "%u"); -WL18XX_DEBUGFS_FWSTATS_FILE(pwr, connection_out_of_sync, "%u"); -WL18XX_DEBUGFS_FWSTATS_FILE_ARRAY(pwr, cont_miss_bcns_spread, - PWR_STAT_MAX_CONT_MISSED_BCNS_SPREAD); -WL18XX_DEBUGFS_FWSTATS_FILE(pwr, rcvd_awake_bcns_cnt, "%u"); - - -WL18XX_DEBUGFS_FWSTATS_FILE(ps_poll, ps_poll_timeouts, "%u"); -WL18XX_DEBUGFS_FWSTATS_FILE(ps_poll, upsd_timeouts, "%u"); -WL18XX_DEBUGFS_FWSTATS_FILE(ps_poll, upsd_max_ap_turn, "%u"); -WL18XX_DEBUGFS_FWSTATS_FILE(ps_poll, ps_poll_max_ap_turn, "%u"); -WL18XX_DEBUGFS_FWSTATS_FILE(ps_poll, ps_poll_utilization, "%u"); -WL18XX_DEBUGFS_FWSTATS_FILE(ps_poll, upsd_utilization, "%u"); - -WL18XX_DEBUGFS_FWSTATS_FILE(rx_filter, beacon_filter, "%u"); -WL18XX_DEBUGFS_FWSTATS_FILE(rx_filter, arp_filter, "%u"); -WL18XX_DEBUGFS_FWSTATS_FILE(rx_filter, mc_filter, "%u"); -WL18XX_DEBUGFS_FWSTATS_FILE(rx_filter, dup_filter, "%u"); -WL18XX_DEBUGFS_FWSTATS_FILE(rx_filter, data_filter, "%u"); -WL18XX_DEBUGFS_FWSTATS_FILE(rx_filter, ibss_filter, "%u"); -WL18XX_DEBUGFS_FWSTATS_FILE(rx_filter, protection_filter, "%u"); -WL18XX_DEBUGFS_FWSTATS_FILE(rx_filter, accum_arp_pend_requests, "%u"); -WL18XX_DEBUGFS_FWSTATS_FILE(rx_filter, max_arp_queue_dep, "%u"); - -WL18XX_DEBUGFS_FWSTATS_FILE(rx_rate, rx_frames_per_rates, "%u"); - -WL18XX_DEBUGFS_FWSTATS_FILE_ARRAY(aggr_size, tx_agg_vs_rate, - AGGR_STATS_TX_AGG*AGGR_STATS_TX_RATE); -WL18XX_DEBUGFS_FWSTATS_FILE_ARRAY(aggr_size, rx_size, - AGGR_STATS_RX_SIZE_LEN); - -WL18XX_DEBUGFS_FWSTATS_FILE(pipeline, hs_tx_stat_fifo_int, "%u"); -WL18XX_DEBUGFS_FWSTATS_FILE(pipeline, tcp_tx_stat_fifo_int, "%u"); -WL18XX_DEBUGFS_FWSTATS_FILE(pipeline, tcp_rx_stat_fifo_int, "%u"); -WL18XX_DEBUGFS_FWSTATS_FILE(pipeline, enc_tx_stat_fifo_int, "%u"); -WL18XX_DEBUGFS_FWSTATS_FILE(pipeline, enc_rx_stat_fifo_int, "%u"); -WL18XX_DEBUGFS_FWSTATS_FILE(pipeline, rx_complete_stat_fifo_int, "%u"); -WL18XX_DEBUGFS_FWSTATS_FILE(pipeline, pre_proc_swi, "%u"); -WL18XX_DEBUGFS_FWSTATS_FILE(pipeline, post_proc_swi, "%u"); -WL18XX_DEBUGFS_FWSTATS_FILE(pipeline, sec_frag_swi, "%u"); -WL18XX_DEBUGFS_FWSTATS_FILE(pipeline, pre_to_defrag_swi, "%u"); -WL18XX_DEBUGFS_FWSTATS_FILE(pipeline, defrag_to_csum_swi, "%u"); -WL18XX_DEBUGFS_FWSTATS_FILE(pipeline, csum_to_rx_xfer_swi, "%u"); -WL18XX_DEBUGFS_FWSTATS_FILE(pipeline, dec_packet_in, "%u"); -WL18XX_DEBUGFS_FWSTATS_FILE(pipeline, dec_packet_in_fifo_full, "%u"); -WL18XX_DEBUGFS_FWSTATS_FILE(pipeline, dec_packet_out, "%u"); -WL18XX_DEBUGFS_FWSTATS_FILE(pipeline, cs_rx_packet_in, "%u"); -WL18XX_DEBUGFS_FWSTATS_FILE(pipeline, cs_rx_packet_out, "%u"); - -WL18XX_DEBUGFS_FWSTATS_FILE_ARRAY(pipeline, pipeline_fifo_full, - PIPE_STATS_HW_FIFO); - -WL18XX_DEBUGFS_FWSTATS_FILE(mem, rx_free_mem_blks, "%u"); -WL18XX_DEBUGFS_FWSTATS_FILE(mem, tx_free_mem_blks, "%u"); -WL18XX_DEBUGFS_FWSTATS_FILE(mem, fwlog_free_mem_blks, "%u"); -WL18XX_DEBUGFS_FWSTATS_FILE(mem, fw_gen_free_mem_blks, "%u"); - -static ssize_t conf_read(struct file *file, char __user *user_buf, - size_t count, loff_t *ppos) -{ - struct wl1271 *wl = file->private_data; - struct wl18xx_priv *priv = wl->priv; - struct wlcore_conf_header header; - char *buf, *pos; - size_t len; - int ret; - - len = WL18XX_CONF_SIZE; - buf = kmalloc(len, GFP_KERNEL); - if (!buf) - return -ENOMEM; - - header.magic = cpu_to_le32(WL18XX_CONF_MAGIC); - header.version = cpu_to_le32(WL18XX_CONF_VERSION); - header.checksum = 0; - - mutex_lock(&wl->mutex); - - pos = buf; - memcpy(pos, &header, sizeof(header)); - pos += sizeof(header); - memcpy(pos, &wl->conf, sizeof(wl->conf)); - pos += sizeof(wl->conf); - memcpy(pos, &priv->conf, sizeof(priv->conf)); - - mutex_unlock(&wl->mutex); - - ret = simple_read_from_buffer(user_buf, count, ppos, buf, len); - - kfree(buf); - return ret; -} - -static const struct file_operations conf_ops = { - .read = conf_read, - .open = simple_open, - .llseek = default_llseek, -}; - -static ssize_t clear_fw_stats_write(struct file *file, - const char __user *user_buf, - size_t count, loff_t *ppos) -{ - struct wl1271 *wl = file->private_data; - int ret; - - mutex_lock(&wl->mutex); - - if (wl->state == WL1271_STATE_OFF) - goto out; - - ret = wl18xx_acx_clear_statistics(wl); - if (ret < 0) { - count = ret; - goto out; - } -out: - mutex_unlock(&wl->mutex); - return count; -} - -static const struct file_operations clear_fw_stats_ops = { - .write = clear_fw_stats_write, - .open = simple_open, - .llseek = default_llseek, -}; - -int wl18xx_debugfs_add_files(struct wl1271 *wl, - struct dentry *rootdir) -{ - int ret = 0; - struct dentry *entry, *stats, *moddir; - - moddir = debugfs_create_dir(KBUILD_MODNAME, rootdir); - if (!moddir || IS_ERR(moddir)) { - entry = moddir; - goto err; - } - - stats = debugfs_create_dir("fw_stats", moddir); - if (!stats || IS_ERR(stats)) { - entry = stats; - goto err; - } - - DEBUGFS_ADD(clear_fw_stats, stats); - - DEBUGFS_FWSTATS_ADD(debug, debug1); - DEBUGFS_FWSTATS_ADD(debug, debug2); - DEBUGFS_FWSTATS_ADD(debug, debug3); - DEBUGFS_FWSTATS_ADD(debug, debug4); - DEBUGFS_FWSTATS_ADD(debug, debug5); - DEBUGFS_FWSTATS_ADD(debug, debug6); - - DEBUGFS_FWSTATS_ADD(error, error_frame); - DEBUGFS_FWSTATS_ADD(error, error_null_Frame_tx_start); - DEBUGFS_FWSTATS_ADD(error, error_numll_frame_cts_start); - DEBUGFS_FWSTATS_ADD(error, error_bar_retry); - DEBUGFS_FWSTATS_ADD(error, error_frame_cts_nul_flid); - - DEBUGFS_FWSTATS_ADD(tx, tx_prepared_descs); - DEBUGFS_FWSTATS_ADD(tx, tx_cmplt); - DEBUGFS_FWSTATS_ADD(tx, tx_template_prepared); - DEBUGFS_FWSTATS_ADD(tx, tx_data_prepared); - DEBUGFS_FWSTATS_ADD(tx, tx_template_programmed); - DEBUGFS_FWSTATS_ADD(tx, tx_data_programmed); - DEBUGFS_FWSTATS_ADD(tx, tx_burst_programmed); - DEBUGFS_FWSTATS_ADD(tx, tx_starts); - DEBUGFS_FWSTATS_ADD(tx, tx_imm_resp); - DEBUGFS_FWSTATS_ADD(tx, tx_start_templates); - DEBUGFS_FWSTATS_ADD(tx, tx_start_int_templates); - DEBUGFS_FWSTATS_ADD(tx, tx_start_fw_gen); - DEBUGFS_FWSTATS_ADD(tx, tx_start_data); - DEBUGFS_FWSTATS_ADD(tx, tx_start_null_frame); - DEBUGFS_FWSTATS_ADD(tx, tx_exch); - DEBUGFS_FWSTATS_ADD(tx, tx_retry_template); - DEBUGFS_FWSTATS_ADD(tx, tx_retry_data); - DEBUGFS_FWSTATS_ADD(tx, tx_exch_pending); - DEBUGFS_FWSTATS_ADD(tx, tx_exch_expiry); - DEBUGFS_FWSTATS_ADD(tx, tx_done_template); - DEBUGFS_FWSTATS_ADD(tx, tx_done_data); - DEBUGFS_FWSTATS_ADD(tx, tx_done_int_template); - DEBUGFS_FWSTATS_ADD(tx, tx_frame_checksum); - DEBUGFS_FWSTATS_ADD(tx, tx_checksum_result); - DEBUGFS_FWSTATS_ADD(tx, frag_called); - DEBUGFS_FWSTATS_ADD(tx, frag_mpdu_alloc_failed); - DEBUGFS_FWSTATS_ADD(tx, frag_init_called); - DEBUGFS_FWSTATS_ADD(tx, frag_in_process_called); - DEBUGFS_FWSTATS_ADD(tx, frag_tkip_called); - DEBUGFS_FWSTATS_ADD(tx, frag_key_not_found); - DEBUGFS_FWSTATS_ADD(tx, frag_need_fragmentation); - DEBUGFS_FWSTATS_ADD(tx, frag_bad_mblk_num); - DEBUGFS_FWSTATS_ADD(tx, frag_failed); - DEBUGFS_FWSTATS_ADD(tx, frag_cache_hit); - DEBUGFS_FWSTATS_ADD(tx, frag_cache_miss); - - DEBUGFS_FWSTATS_ADD(rx, rx_beacon_early_term); - DEBUGFS_FWSTATS_ADD(rx, rx_out_of_mpdu_nodes); - DEBUGFS_FWSTATS_ADD(rx, rx_hdr_overflow); - DEBUGFS_FWSTATS_ADD(rx, rx_dropped_frame); - DEBUGFS_FWSTATS_ADD(rx, rx_done); - DEBUGFS_FWSTATS_ADD(rx, rx_defrag); - DEBUGFS_FWSTATS_ADD(rx, rx_defrag_end); - DEBUGFS_FWSTATS_ADD(rx, rx_cmplt); - DEBUGFS_FWSTATS_ADD(rx, rx_pre_complt); - DEBUGFS_FWSTATS_ADD(rx, rx_cmplt_task); - DEBUGFS_FWSTATS_ADD(rx, rx_phy_hdr); - DEBUGFS_FWSTATS_ADD(rx, rx_timeout); - DEBUGFS_FWSTATS_ADD(rx, rx_timeout_wa); - DEBUGFS_FWSTATS_ADD(rx, rx_wa_density_dropped_frame); - DEBUGFS_FWSTATS_ADD(rx, rx_wa_ba_not_expected); - DEBUGFS_FWSTATS_ADD(rx, rx_frame_checksum); - DEBUGFS_FWSTATS_ADD(rx, rx_checksum_result); - DEBUGFS_FWSTATS_ADD(rx, defrag_called); - DEBUGFS_FWSTATS_ADD(rx, defrag_init_called); - DEBUGFS_FWSTATS_ADD(rx, defrag_in_process_called); - DEBUGFS_FWSTATS_ADD(rx, defrag_tkip_called); - DEBUGFS_FWSTATS_ADD(rx, defrag_need_defrag); - DEBUGFS_FWSTATS_ADD(rx, defrag_decrypt_failed); - DEBUGFS_FWSTATS_ADD(rx, decrypt_key_not_found); - DEBUGFS_FWSTATS_ADD(rx, defrag_need_decrypt); - DEBUGFS_FWSTATS_ADD(rx, rx_tkip_replays); - - DEBUGFS_FWSTATS_ADD(isr, irqs); - - DEBUGFS_FWSTATS_ADD(pwr, missing_bcns_cnt); - DEBUGFS_FWSTATS_ADD(pwr, rcvd_bcns_cnt); - DEBUGFS_FWSTATS_ADD(pwr, connection_out_of_sync); - DEBUGFS_FWSTATS_ADD(pwr, cont_miss_bcns_spread); - DEBUGFS_FWSTATS_ADD(pwr, rcvd_awake_bcns_cnt); - - DEBUGFS_FWSTATS_ADD(ps_poll, ps_poll_timeouts); - DEBUGFS_FWSTATS_ADD(ps_poll, upsd_timeouts); - DEBUGFS_FWSTATS_ADD(ps_poll, upsd_max_ap_turn); - DEBUGFS_FWSTATS_ADD(ps_poll, ps_poll_max_ap_turn); - DEBUGFS_FWSTATS_ADD(ps_poll, ps_poll_utilization); - DEBUGFS_FWSTATS_ADD(ps_poll, upsd_utilization); - - DEBUGFS_FWSTATS_ADD(rx_filter, beacon_filter); - DEBUGFS_FWSTATS_ADD(rx_filter, arp_filter); - DEBUGFS_FWSTATS_ADD(rx_filter, mc_filter); - DEBUGFS_FWSTATS_ADD(rx_filter, dup_filter); - DEBUGFS_FWSTATS_ADD(rx_filter, data_filter); - DEBUGFS_FWSTATS_ADD(rx_filter, ibss_filter); - DEBUGFS_FWSTATS_ADD(rx_filter, protection_filter); - DEBUGFS_FWSTATS_ADD(rx_filter, accum_arp_pend_requests); - DEBUGFS_FWSTATS_ADD(rx_filter, max_arp_queue_dep); - - DEBUGFS_FWSTATS_ADD(rx_rate, rx_frames_per_rates); - - DEBUGFS_FWSTATS_ADD(aggr_size, tx_agg_vs_rate); - DEBUGFS_FWSTATS_ADD(aggr_size, rx_size); - - DEBUGFS_FWSTATS_ADD(pipeline, hs_tx_stat_fifo_int); - DEBUGFS_FWSTATS_ADD(pipeline, tcp_tx_stat_fifo_int); - DEBUGFS_FWSTATS_ADD(pipeline, tcp_rx_stat_fifo_int); - DEBUGFS_FWSTATS_ADD(pipeline, enc_tx_stat_fifo_int); - DEBUGFS_FWSTATS_ADD(pipeline, enc_rx_stat_fifo_int); - DEBUGFS_FWSTATS_ADD(pipeline, rx_complete_stat_fifo_int); - DEBUGFS_FWSTATS_ADD(pipeline, pre_proc_swi); - DEBUGFS_FWSTATS_ADD(pipeline, post_proc_swi); - DEBUGFS_FWSTATS_ADD(pipeline, sec_frag_swi); - DEBUGFS_FWSTATS_ADD(pipeline, pre_to_defrag_swi); - DEBUGFS_FWSTATS_ADD(pipeline, defrag_to_csum_swi); - DEBUGFS_FWSTATS_ADD(pipeline, csum_to_rx_xfer_swi); - DEBUGFS_FWSTATS_ADD(pipeline, dec_packet_in); - DEBUGFS_FWSTATS_ADD(pipeline, dec_packet_in_fifo_full); - DEBUGFS_FWSTATS_ADD(pipeline, dec_packet_out); - DEBUGFS_FWSTATS_ADD(pipeline, cs_rx_packet_in); - DEBUGFS_FWSTATS_ADD(pipeline, cs_rx_packet_out); - DEBUGFS_FWSTATS_ADD(pipeline, pipeline_fifo_full); - - DEBUGFS_FWSTATS_ADD(mem, rx_free_mem_blks); - DEBUGFS_FWSTATS_ADD(mem, tx_free_mem_blks); - DEBUGFS_FWSTATS_ADD(mem, fwlog_free_mem_blks); - DEBUGFS_FWSTATS_ADD(mem, fw_gen_free_mem_blks); - - DEBUGFS_ADD(conf, moddir); - - return 0; - -err: - if (IS_ERR(entry)) - ret = PTR_ERR(entry); - else - ret = -ENOMEM; - - return ret; -} diff --git a/trunk/drivers/net/wireless/ti/wl18xx/debugfs.h b/trunk/drivers/net/wireless/ti/wl18xx/debugfs.h deleted file mode 100644 index ed679bebf620..000000000000 --- a/trunk/drivers/net/wireless/ti/wl18xx/debugfs.h +++ /dev/null @@ -1,28 +0,0 @@ -/* - * This file is part of wl18xx - * - * Copyright (C) 2012 Texas Instruments. All rights reserved. - * - * 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 - * - */ - -#ifndef __WL18XX_DEBUGFS_H__ -#define __WL18XX_DEBUGFS_H__ - -int wl18xx_debugfs_add_files(struct wl1271 *wl, - struct dentry *rootdir); - -#endif /* __WL18XX_DEBUGFS_H__ */ diff --git a/trunk/drivers/net/wireless/ti/wl18xx/io.c b/trunk/drivers/net/wireless/ti/wl18xx/io.c deleted file mode 100644 index 598c057e722b..000000000000 --- a/trunk/drivers/net/wireless/ti/wl18xx/io.c +++ /dev/null @@ -1,60 +0,0 @@ -/* - * This file is part of wl18xx - * - * Copyright (C) 2011 Texas Instruments - * - * 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/wlcore.h" -#include "../wlcore/io.h" - -#include "io.h" - -void wl18xx_top_reg_write(struct wl1271 *wl, int addr, u16 val) -{ - u32 tmp; - - if (WARN_ON(addr % 2)) - return; - - if ((addr % 4) == 0) { - tmp = wl1271_read32(wl, addr); - tmp = (tmp & 0xffff0000) | val; - wl1271_write32(wl, addr, tmp); - } else { - tmp = wl1271_read32(wl, addr - 2); - tmp = (tmp & 0xffff) | (val << 16); - wl1271_write32(wl, addr - 2, tmp); - } -} - -u16 wl18xx_top_reg_read(struct wl1271 *wl, int addr) -{ - u32 val; - - if (WARN_ON(addr % 2)) - return 0; - - if ((addr % 4) == 0) { - /* address is 4-bytes aligned */ - val = wl1271_read32(wl, addr); - return val & 0xffff; - } else { - val = wl1271_read32(wl, addr - 2); - return (val & 0xffff0000) >> 16; - } -} diff --git a/trunk/drivers/net/wireless/ti/wl18xx/io.h b/trunk/drivers/net/wireless/ti/wl18xx/io.h deleted file mode 100644 index be4e126ff617..000000000000 --- a/trunk/drivers/net/wireless/ti/wl18xx/io.h +++ /dev/null @@ -1,28 +0,0 @@ -/* - * This file is part of wl18xx - * - * Copyright (C) 2011 Texas Instruments - * - * 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 - * - */ - -#ifndef __WL18XX_IO_H__ -#define __WL18XX_IO_H__ - -void wl18xx_top_reg_write(struct wl1271 *wl, int addr, u16 val); -u16 wl18xx_top_reg_read(struct wl1271 *wl, int addr); - -#endif /* __WL18XX_IO_H__ */ diff --git a/trunk/drivers/net/wireless/ti/wl18xx/main.c b/trunk/drivers/net/wireless/ti/wl18xx/main.c deleted file mode 100644 index ed9c3650e08a..000000000000 --- a/trunk/drivers/net/wireless/ti/wl18xx/main.c +++ /dev/null @@ -1,1463 +0,0 @@ -/* - * This file is part of wl18xx - * - * Copyright (C) 2011 Texas Instruments - * - * 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 -#include -#include -#include - -#include "../wlcore/wlcore.h" -#include "../wlcore/debug.h" -#include "../wlcore/io.h" -#include "../wlcore/acx.h" -#include "../wlcore/tx.h" -#include "../wlcore/rx.h" -#include "../wlcore/io.h" -#include "../wlcore/boot.h" - -#include "reg.h" -#include "conf.h" -#include "acx.h" -#include "tx.h" -#include "wl18xx.h" -#include "io.h" -#include "debugfs.h" - -#define WL18XX_RX_CHECKSUM_MASK 0x40 - -static char *ht_mode_param = "wide"; -static char *board_type_param = "hdk"; -static bool checksum_param = false; -static bool enable_11a_param = true; - -/* phy paramters */ -static int dc2dc_param = -1; -static int n_antennas_2_param = -1; -static int n_antennas_5_param = -1; -static int low_band_component_param = -1; -static int low_band_component_type_param = -1; -static int high_band_component_param = -1; -static int high_band_component_type_param = -1; -static int pwr_limit_reference_11_abg_param = -1; - -static const u8 wl18xx_rate_to_idx_2ghz[] = { - /* MCS rates are used only with 11n */ - 15, /* WL18XX_CONF_HW_RXTX_RATE_MCS15 */ - 14, /* WL18XX_CONF_HW_RXTX_RATE_MCS14 */ - 13, /* WL18XX_CONF_HW_RXTX_RATE_MCS13 */ - 12, /* WL18XX_CONF_HW_RXTX_RATE_MCS12 */ - 11, /* WL18XX_CONF_HW_RXTX_RATE_MCS11 */ - 10, /* WL18XX_CONF_HW_RXTX_RATE_MCS10 */ - 9, /* WL18XX_CONF_HW_RXTX_RATE_MCS9 */ - 8, /* WL18XX_CONF_HW_RXTX_RATE_MCS8 */ - 7, /* WL18XX_CONF_HW_RXTX_RATE_MCS7 */ - 6, /* WL18XX_CONF_HW_RXTX_RATE_MCS6 */ - 5, /* WL18XX_CONF_HW_RXTX_RATE_MCS5 */ - 4, /* WL18XX_CONF_HW_RXTX_RATE_MCS4 */ - 3, /* WL18XX_CONF_HW_RXTX_RATE_MCS3 */ - 2, /* WL18XX_CONF_HW_RXTX_RATE_MCS2 */ - 1, /* WL18XX_CONF_HW_RXTX_RATE_MCS1 */ - 0, /* WL18XX_CONF_HW_RXTX_RATE_MCS0 */ - - 11, /* WL18XX_CONF_HW_RXTX_RATE_54 */ - 10, /* WL18XX_CONF_HW_RXTX_RATE_48 */ - 9, /* WL18XX_CONF_HW_RXTX_RATE_36 */ - 8, /* WL18XX_CONF_HW_RXTX_RATE_24 */ - - /* TI-specific rate */ - CONF_HW_RXTX_RATE_UNSUPPORTED, /* WL18XX_CONF_HW_RXTX_RATE_22 */ - - 7, /* WL18XX_CONF_HW_RXTX_RATE_18 */ - 6, /* WL18XX_CONF_HW_RXTX_RATE_12 */ - 3, /* WL18XX_CONF_HW_RXTX_RATE_11 */ - 5, /* WL18XX_CONF_HW_RXTX_RATE_9 */ - 4, /* WL18XX_CONF_HW_RXTX_RATE_6 */ - 2, /* WL18XX_CONF_HW_RXTX_RATE_5_5 */ - 1, /* WL18XX_CONF_HW_RXTX_RATE_2 */ - 0 /* WL18XX_CONF_HW_RXTX_RATE_1 */ -}; - -static const u8 wl18xx_rate_to_idx_5ghz[] = { - /* MCS rates are used only with 11n */ - 15, /* WL18XX_CONF_HW_RXTX_RATE_MCS15 */ - 14, /* WL18XX_CONF_HW_RXTX_RATE_MCS14 */ - 13, /* WL18XX_CONF_HW_RXTX_RATE_MCS13 */ - 12, /* WL18XX_CONF_HW_RXTX_RATE_MCS12 */ - 11, /* WL18XX_CONF_HW_RXTX_RATE_MCS11 */ - 10, /* WL18XX_CONF_HW_RXTX_RATE_MCS10 */ - 9, /* WL18XX_CONF_HW_RXTX_RATE_MCS9 */ - 8, /* WL18XX_CONF_HW_RXTX_RATE_MCS8 */ - 7, /* WL18XX_CONF_HW_RXTX_RATE_MCS7 */ - 6, /* WL18XX_CONF_HW_RXTX_RATE_MCS6 */ - 5, /* WL18XX_CONF_HW_RXTX_RATE_MCS5 */ - 4, /* WL18XX_CONF_HW_RXTX_RATE_MCS4 */ - 3, /* WL18XX_CONF_HW_RXTX_RATE_MCS3 */ - 2, /* WL18XX_CONF_HW_RXTX_RATE_MCS2 */ - 1, /* WL18XX_CONF_HW_RXTX_RATE_MCS1 */ - 0, /* WL18XX_CONF_HW_RXTX_RATE_MCS0 */ - - 7, /* WL18XX_CONF_HW_RXTX_RATE_54 */ - 6, /* WL18XX_CONF_HW_RXTX_RATE_48 */ - 5, /* WL18XX_CONF_HW_RXTX_RATE_36 */ - 4, /* WL18XX_CONF_HW_RXTX_RATE_24 */ - - /* TI-specific rate */ - CONF_HW_RXTX_RATE_UNSUPPORTED, /* WL18XX_CONF_HW_RXTX_RATE_22 */ - - 3, /* WL18XX_CONF_HW_RXTX_RATE_18 */ - 2, /* WL18XX_CONF_HW_RXTX_RATE_12 */ - CONF_HW_RXTX_RATE_UNSUPPORTED, /* WL18XX_CONF_HW_RXTX_RATE_11 */ - 1, /* WL18XX_CONF_HW_RXTX_RATE_9 */ - 0, /* WL18XX_CONF_HW_RXTX_RATE_6 */ - CONF_HW_RXTX_RATE_UNSUPPORTED, /* WL18XX_CONF_HW_RXTX_RATE_5_5 */ - CONF_HW_RXTX_RATE_UNSUPPORTED, /* WL18XX_CONF_HW_RXTX_RATE_2 */ - CONF_HW_RXTX_RATE_UNSUPPORTED, /* WL18XX_CONF_HW_RXTX_RATE_1 */ -}; - -static const u8 *wl18xx_band_rate_to_idx[] = { - [IEEE80211_BAND_2GHZ] = wl18xx_rate_to_idx_2ghz, - [IEEE80211_BAND_5GHZ] = wl18xx_rate_to_idx_5ghz -}; - -enum wl18xx_hw_rates { - WL18XX_CONF_HW_RXTX_RATE_MCS15 = 0, - WL18XX_CONF_HW_RXTX_RATE_MCS14, - WL18XX_CONF_HW_RXTX_RATE_MCS13, - WL18XX_CONF_HW_RXTX_RATE_MCS12, - WL18XX_CONF_HW_RXTX_RATE_MCS11, - WL18XX_CONF_HW_RXTX_RATE_MCS10, - WL18XX_CONF_HW_RXTX_RATE_MCS9, - WL18XX_CONF_HW_RXTX_RATE_MCS8, - WL18XX_CONF_HW_RXTX_RATE_MCS7, - WL18XX_CONF_HW_RXTX_RATE_MCS6, - WL18XX_CONF_HW_RXTX_RATE_MCS5, - WL18XX_CONF_HW_RXTX_RATE_MCS4, - WL18XX_CONF_HW_RXTX_RATE_MCS3, - WL18XX_CONF_HW_RXTX_RATE_MCS2, - WL18XX_CONF_HW_RXTX_RATE_MCS1, - WL18XX_CONF_HW_RXTX_RATE_MCS0, - WL18XX_CONF_HW_RXTX_RATE_54, - WL18XX_CONF_HW_RXTX_RATE_48, - WL18XX_CONF_HW_RXTX_RATE_36, - WL18XX_CONF_HW_RXTX_RATE_24, - WL18XX_CONF_HW_RXTX_RATE_22, - WL18XX_CONF_HW_RXTX_RATE_18, - WL18XX_CONF_HW_RXTX_RATE_12, - WL18XX_CONF_HW_RXTX_RATE_11, - WL18XX_CONF_HW_RXTX_RATE_9, - WL18XX_CONF_HW_RXTX_RATE_6, - WL18XX_CONF_HW_RXTX_RATE_5_5, - WL18XX_CONF_HW_RXTX_RATE_2, - WL18XX_CONF_HW_RXTX_RATE_1, - WL18XX_CONF_HW_RXTX_RATE_MAX, -}; - -static struct wlcore_conf wl18xx_conf = { - .sg = { - .params = { - [CONF_SG_ACL_BT_MASTER_MIN_BR] = 10, - [CONF_SG_ACL_BT_MASTER_MAX_BR] = 180, - [CONF_SG_ACL_BT_SLAVE_MIN_BR] = 10, - [CONF_SG_ACL_BT_SLAVE_MAX_BR] = 180, - [CONF_SG_ACL_BT_MASTER_MIN_EDR] = 10, - [CONF_SG_ACL_BT_MASTER_MAX_EDR] = 80, - [CONF_SG_ACL_BT_SLAVE_MIN_EDR] = 10, - [CONF_SG_ACL_BT_SLAVE_MAX_EDR] = 80, - [CONF_SG_ACL_WLAN_PS_MASTER_BR] = 8, - [CONF_SG_ACL_WLAN_PS_SLAVE_BR] = 8, - [CONF_SG_ACL_WLAN_PS_MASTER_EDR] = 20, - [CONF_SG_ACL_WLAN_PS_SLAVE_EDR] = 20, - [CONF_SG_ACL_WLAN_ACTIVE_MASTER_MIN_BR] = 20, - [CONF_SG_ACL_WLAN_ACTIVE_MASTER_MAX_BR] = 35, - [CONF_SG_ACL_WLAN_ACTIVE_SLAVE_MIN_BR] = 16, - [CONF_SG_ACL_WLAN_ACTIVE_SLAVE_MAX_BR] = 35, - [CONF_SG_ACL_WLAN_ACTIVE_MASTER_MIN_EDR] = 32, - [CONF_SG_ACL_WLAN_ACTIVE_MASTER_MAX_EDR] = 50, - [CONF_SG_ACL_WLAN_ACTIVE_SLAVE_MIN_EDR] = 28, - [CONF_SG_ACL_WLAN_ACTIVE_SLAVE_MAX_EDR] = 50, - [CONF_SG_ACL_ACTIVE_SCAN_WLAN_BR] = 10, - [CONF_SG_ACL_ACTIVE_SCAN_WLAN_EDR] = 20, - [CONF_SG_ACL_PASSIVE_SCAN_BT_BR] = 75, - [CONF_SG_ACL_PASSIVE_SCAN_WLAN_BR] = 15, - [CONF_SG_ACL_PASSIVE_SCAN_BT_EDR] = 27, - [CONF_SG_ACL_PASSIVE_SCAN_WLAN_EDR] = 17, - /* active scan params */ - [CONF_SG_AUTO_SCAN_PROBE_REQ] = 170, - [CONF_SG_ACTIVE_SCAN_DURATION_FACTOR_HV3] = 50, - [CONF_SG_ACTIVE_SCAN_DURATION_FACTOR_A2DP] = 100, - /* passive scan params */ - [CONF_SG_PASSIVE_SCAN_DURATION_FACTOR_A2DP_BR] = 800, - [CONF_SG_PASSIVE_SCAN_DURATION_FACTOR_A2DP_EDR] = 200, - [CONF_SG_PASSIVE_SCAN_DURATION_FACTOR_HV3] = 200, - /* passive scan in dual antenna params */ - [CONF_SG_CONSECUTIVE_HV3_IN_PASSIVE_SCAN] = 0, - [CONF_SG_BCN_HV3_COLLISION_THRESH_IN_PASSIVE_SCAN] = 0, - [CONF_SG_TX_RX_PROTECTION_BWIDTH_IN_PASSIVE_SCAN] = 0, - /* general params */ - [CONF_SG_STA_FORCE_PS_IN_BT_SCO] = 1, - [CONF_SG_ANTENNA_CONFIGURATION] = 0, - [CONF_SG_BEACON_MISS_PERCENT] = 60, - [CONF_SG_DHCP_TIME] = 5000, - [CONF_SG_RXT] = 1200, - [CONF_SG_TXT] = 1000, - [CONF_SG_ADAPTIVE_RXT_TXT] = 1, - [CONF_SG_GENERAL_USAGE_BIT_MAP] = 3, - [CONF_SG_HV3_MAX_SERVED] = 6, - [CONF_SG_PS_POLL_TIMEOUT] = 10, - [CONF_SG_UPSD_TIMEOUT] = 10, - [CONF_SG_CONSECUTIVE_CTS_THRESHOLD] = 2, - [CONF_SG_STA_RX_WINDOW_AFTER_DTIM] = 5, - [CONF_SG_STA_CONNECTION_PROTECTION_TIME] = 30, - /* AP params */ - [CONF_AP_BEACON_MISS_TX] = 3, - [CONF_AP_RX_WINDOW_AFTER_BEACON] = 10, - [CONF_AP_BEACON_WINDOW_INTERVAL] = 2, - [CONF_AP_CONNECTION_PROTECTION_TIME] = 0, - [CONF_AP_BT_ACL_VAL_BT_SERVE_TIME] = 25, - [CONF_AP_BT_ACL_VAL_WL_SERVE_TIME] = 25, - /* CTS Diluting params */ - [CONF_SG_CTS_DILUTED_BAD_RX_PACKETS_TH] = 0, - [CONF_SG_CTS_CHOP_IN_DUAL_ANT_SCO_MASTER] = 0, - }, - .state = CONF_SG_PROTECTIVE, - }, - .rx = { - .rx_msdu_life_time = 512000, - .packet_detection_threshold = 0, - .ps_poll_timeout = 15, - .upsd_timeout = 15, - .rts_threshold = IEEE80211_MAX_RTS_THRESHOLD, - .rx_cca_threshold = 0, - .irq_blk_threshold = 0xFFFF, - .irq_pkt_threshold = 0, - .irq_timeout = 600, - .queue_type = CONF_RX_QUEUE_TYPE_LOW_PRIORITY, - }, - .tx = { - .tx_energy_detection = 0, - .sta_rc_conf = { - .enabled_rates = 0, - .short_retry_limit = 10, - .long_retry_limit = 10, - .aflags = 0, - }, - .ac_conf_count = 4, - .ac_conf = { - [CONF_TX_AC_BE] = { - .ac = CONF_TX_AC_BE, - .cw_min = 15, - .cw_max = 63, - .aifsn = 3, - .tx_op_limit = 0, - }, - [CONF_TX_AC_BK] = { - .ac = CONF_TX_AC_BK, - .cw_min = 15, - .cw_max = 63, - .aifsn = 7, - .tx_op_limit = 0, - }, - [CONF_TX_AC_VI] = { - .ac = CONF_TX_AC_VI, - .cw_min = 15, - .cw_max = 63, - .aifsn = CONF_TX_AIFS_PIFS, - .tx_op_limit = 3008, - }, - [CONF_TX_AC_VO] = { - .ac = CONF_TX_AC_VO, - .cw_min = 15, - .cw_max = 63, - .aifsn = CONF_TX_AIFS_PIFS, - .tx_op_limit = 1504, - }, - }, - .max_tx_retries = 100, - .ap_aging_period = 300, - .tid_conf_count = 4, - .tid_conf = { - [CONF_TX_AC_BE] = { - .queue_id = CONF_TX_AC_BE, - .channel_type = CONF_CHANNEL_TYPE_EDCF, - .tsid = CONF_TX_AC_BE, - .ps_scheme = CONF_PS_SCHEME_LEGACY, - .ack_policy = CONF_ACK_POLICY_LEGACY, - .apsd_conf = {0, 0}, - }, - [CONF_TX_AC_BK] = { - .queue_id = CONF_TX_AC_BK, - .channel_type = CONF_CHANNEL_TYPE_EDCF, - .tsid = CONF_TX_AC_BK, - .ps_scheme = CONF_PS_SCHEME_LEGACY, - .ack_policy = CONF_ACK_POLICY_LEGACY, - .apsd_conf = {0, 0}, - }, - [CONF_TX_AC_VI] = { - .queue_id = CONF_TX_AC_VI, - .channel_type = CONF_CHANNEL_TYPE_EDCF, - .tsid = CONF_TX_AC_VI, - .ps_scheme = CONF_PS_SCHEME_LEGACY, - .ack_policy = CONF_ACK_POLICY_LEGACY, - .apsd_conf = {0, 0}, - }, - [CONF_TX_AC_VO] = { - .queue_id = CONF_TX_AC_VO, - .channel_type = CONF_CHANNEL_TYPE_EDCF, - .tsid = CONF_TX_AC_VO, - .ps_scheme = CONF_PS_SCHEME_LEGACY, - .ack_policy = CONF_ACK_POLICY_LEGACY, - .apsd_conf = {0, 0}, - }, - }, - .frag_threshold = IEEE80211_MAX_FRAG_THRESHOLD, - .tx_compl_timeout = 350, - .tx_compl_threshold = 10, - .basic_rate = CONF_HW_BIT_RATE_1MBPS, - .basic_rate_5 = CONF_HW_BIT_RATE_6MBPS, - .tmpl_short_retry_limit = 10, - .tmpl_long_retry_limit = 10, - .tx_watchdog_timeout = 5000, - }, - .conn = { - .wake_up_event = CONF_WAKE_UP_EVENT_DTIM, - .listen_interval = 1, - .suspend_wake_up_event = CONF_WAKE_UP_EVENT_N_DTIM, - .suspend_listen_interval = 3, - .bcn_filt_mode = CONF_BCN_FILT_MODE_ENABLED, - .bcn_filt_ie_count = 3, - .bcn_filt_ie = { - [0] = { - .ie = WLAN_EID_CHANNEL_SWITCH, - .rule = CONF_BCN_RULE_PASS_ON_APPEARANCE, - }, - [1] = { - .ie = WLAN_EID_HT_OPERATION, - .rule = CONF_BCN_RULE_PASS_ON_CHANGE, - }, - [2] = { - .ie = WLAN_EID_ERP_INFO, - .rule = CONF_BCN_RULE_PASS_ON_CHANGE, - }, - }, - .synch_fail_thold = 12, - .bss_lose_timeout = 400, - .beacon_rx_timeout = 10000, - .broadcast_timeout = 20000, - .rx_broadcast_in_ps = 1, - .ps_poll_threshold = 10, - .bet_enable = CONF_BET_MODE_ENABLE, - .bet_max_consecutive = 50, - .psm_entry_retries = 8, - .psm_exit_retries = 16, - .psm_entry_nullfunc_retries = 3, - .dynamic_ps_timeout = 200, - .forced_ps = false, - .keep_alive_interval = 55000, - .max_listen_interval = 20, - }, - .itrim = { - .enable = false, - .timeout = 50000, - }, - .pm_config = { - .host_clk_settling_time = 5000, - .host_fast_wakeup_support = CONF_FAST_WAKEUP_DISABLE, - }, - .roam_trigger = { - .trigger_pacing = 1, - .avg_weight_rssi_beacon = 20, - .avg_weight_rssi_data = 10, - .avg_weight_snr_beacon = 20, - .avg_weight_snr_data = 10, - }, - .scan = { - .min_dwell_time_active = 7500, - .max_dwell_time_active = 30000, - .min_dwell_time_passive = 100000, - .max_dwell_time_passive = 100000, - .num_probe_reqs = 2, - .split_scan_timeout = 50000, - }, - .sched_scan = { - /* - * Values are in TU/1000 but since sched scan FW command - * params are in TUs rounding up may occur. - */ - .base_dwell_time = 7500, - .max_dwell_time_delta = 22500, - /* based on 250bits per probe @1Mbps */ - .dwell_time_delta_per_probe = 2000, - /* based on 250bits per probe @6Mbps (plus a bit more) */ - .dwell_time_delta_per_probe_5 = 350, - .dwell_time_passive = 100000, - .dwell_time_dfs = 150000, - .num_probe_reqs = 2, - .rssi_threshold = -90, - .snr_threshold = 0, - }, - .ht = { - .rx_ba_win_size = 10, - .tx_ba_win_size = 64, - .inactivity_timeout = 10000, - .tx_ba_tid_bitmap = CONF_TX_BA_ENABLED_TID_BITMAP, - }, - .mem = { - .num_stations = 1, - .ssid_profiles = 1, - .rx_block_num = 40, - .tx_min_block_num = 40, - .dynamic_memory = 1, - .min_req_tx_blocks = 45, - .min_req_rx_blocks = 22, - .tx_min = 27, - }, - .fm_coex = { - .enable = true, - .swallow_period = 5, - .n_divider_fref_set_1 = 0xff, /* default */ - .n_divider_fref_set_2 = 12, - .m_divider_fref_set_1 = 0xffff, - .m_divider_fref_set_2 = 148, /* default */ - .coex_pll_stabilization_time = 0xffffffff, /* default */ - .ldo_stabilization_time = 0xffff, /* default */ - .fm_disturbed_band_margin = 0xff, /* default */ - .swallow_clk_diff = 0xff, /* default */ - }, - .rx_streaming = { - .duration = 150, - .queues = 0x1, - .interval = 20, - .always = 0, - }, - .fwlog = { - .mode = WL12XX_FWLOG_ON_DEMAND, - .mem_blocks = 2, - .severity = 0, - .timestamp = WL12XX_FWLOG_TIMESTAMP_DISABLED, - .output = WL12XX_FWLOG_OUTPUT_HOST, - .threshold = 0, - }, - .rate = { - .rate_retry_score = 32000, - .per_add = 8192, - .per_th1 = 2048, - .per_th2 = 4096, - .max_per = 8100, - .inverse_curiosity_factor = 5, - .tx_fail_low_th = 4, - .tx_fail_high_th = 10, - .per_alpha_shift = 4, - .per_add_shift = 13, - .per_beta1_shift = 10, - .per_beta2_shift = 8, - .rate_check_up = 2, - .rate_check_down = 12, - .rate_retry_policy = { - 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, - }, - }, - .hangover = { - .recover_time = 0, - .hangover_period = 20, - .dynamic_mode = 1, - .early_termination_mode = 1, - .max_period = 20, - .min_period = 1, - .increase_delta = 1, - .decrease_delta = 2, - .quiet_time = 4, - .increase_time = 1, - .window_size = 16, - }, -}; - -static struct wl18xx_priv_conf wl18xx_default_priv_conf = { - .phy = { - .phy_standalone = 0x00, - .primary_clock_setting_time = 0x05, - .clock_valid_on_wake_up = 0x00, - .secondary_clock_setting_time = 0x05, - .rdl = 0x01, - .auto_detect = 0x00, - .dedicated_fem = FEM_NONE, - .low_band_component = COMPONENT_2_WAY_SWITCH, - .low_band_component_type = 0x05, - .high_band_component = COMPONENT_2_WAY_SWITCH, - .high_band_component_type = 0x09, - .tcxo_ldo_voltage = 0x00, - .xtal_itrim_val = 0x04, - .srf_state = 0x00, - .io_configuration = 0x01, - .sdio_configuration = 0x00, - .settings = 0x00, - .enable_clpc = 0x00, - .enable_tx_low_pwr_on_siso_rdl = 0x00, - .rx_profile = 0x00, - .pwr_limit_reference_11_abg = 0xc8, - .psat = 0, - .low_power_val = 0x00, - .med_power_val = 0x0a, - .high_power_val = 0x1e, - .external_pa_dc2dc = 0, - .number_of_assembled_ant2_4 = 1, - .number_of_assembled_ant5 = 1, - }, -}; - -static const struct wlcore_partition_set wl18xx_ptable[PART_TABLE_LEN] = { - [PART_TOP_PRCM_ELP_SOC] = { - .mem = { .start = 0x00A02000, .size = 0x00010000 }, - .reg = { .start = 0x00807000, .size = 0x00005000 }, - .mem2 = { .start = 0x00800000, .size = 0x0000B000 }, - .mem3 = { .start = 0x00000000, .size = 0x00000000 }, - }, - [PART_DOWN] = { - .mem = { .start = 0x00000000, .size = 0x00014000 }, - .reg = { .start = 0x00810000, .size = 0x0000BFFF }, - .mem2 = { .start = 0x00000000, .size = 0x00000000 }, - .mem3 = { .start = 0x00000000, .size = 0x00000000 }, - }, - [PART_BOOT] = { - .mem = { .start = 0x00700000, .size = 0x0000030c }, - .reg = { .start = 0x00802000, .size = 0x00014578 }, - .mem2 = { .start = 0x00B00404, .size = 0x00001000 }, - .mem3 = { .start = 0x00C00000, .size = 0x00000400 }, - }, - [PART_WORK] = { - .mem = { .start = 0x00800000, .size = 0x000050FC }, - .reg = { .start = 0x00B00404, .size = 0x00001000 }, - .mem2 = { .start = 0x00C00000, .size = 0x00000400 }, - .mem3 = { .start = 0x00000000, .size = 0x00000000 }, - }, - [PART_PHY_INIT] = { - .mem = { .start = 0x80926000, - .size = sizeof(struct wl18xx_mac_and_phy_params) }, - .reg = { .start = 0x00000000, .size = 0x00000000 }, - .mem2 = { .start = 0x00000000, .size = 0x00000000 }, - .mem3 = { .start = 0x00000000, .size = 0x00000000 }, - }, -}; - -static const int wl18xx_rtable[REG_TABLE_LEN] = { - [REG_ECPU_CONTROL] = WL18XX_REG_ECPU_CONTROL, - [REG_INTERRUPT_NO_CLEAR] = WL18XX_REG_INTERRUPT_NO_CLEAR, - [REG_INTERRUPT_ACK] = WL18XX_REG_INTERRUPT_ACK, - [REG_COMMAND_MAILBOX_PTR] = WL18XX_REG_COMMAND_MAILBOX_PTR, - [REG_EVENT_MAILBOX_PTR] = WL18XX_REG_EVENT_MAILBOX_PTR, - [REG_INTERRUPT_TRIG] = WL18XX_REG_INTERRUPT_TRIG_H, - [REG_INTERRUPT_MASK] = WL18XX_REG_INTERRUPT_MASK, - [REG_PC_ON_RECOVERY] = WL18XX_SCR_PAD4, - [REG_CHIP_ID_B] = WL18XX_REG_CHIP_ID_B, - [REG_CMD_MBOX_ADDRESS] = WL18XX_CMD_MBOX_ADDRESS, - - /* data access memory addresses, used with partition translation */ - [REG_SLV_MEM_DATA] = WL18XX_SLV_MEM_DATA, - [REG_SLV_REG_DATA] = WL18XX_SLV_REG_DATA, - - /* raw data access memory addresses */ - [REG_RAW_FW_STATUS_ADDR] = WL18XX_FW_STATUS_ADDR, -}; - -static const struct wl18xx_clk_cfg wl18xx_clk_table[NUM_CLOCK_CONFIGS] = { - [CLOCK_CONFIG_16_2_M] = { 7, 104, 801, 4, true }, - [CLOCK_CONFIG_16_368_M] = { 9, 132, 3751, 4, true }, - [CLOCK_CONFIG_16_8_M] = { 7, 100, 0, 0, false }, - [CLOCK_CONFIG_19_2_M] = { 8, 100, 0, 0, false }, - [CLOCK_CONFIG_26_M] = { 13, 120, 0, 0, false }, - [CLOCK_CONFIG_32_736_M] = { 9, 132, 3751, 4, true }, - [CLOCK_CONFIG_33_6_M] = { 7, 100, 0, 0, false }, - [CLOCK_CONFIG_38_468_M] = { 8, 100, 0, 0, false }, - [CLOCK_CONFIG_52_M] = { 13, 120, 0, 0, false }, -}; - -/* TODO: maybe move to a new header file? */ -#define WL18XX_FW_NAME "ti-connectivity/wl18xx-fw.bin" - -static int wl18xx_identify_chip(struct wl1271 *wl) -{ - int ret = 0; - - switch (wl->chip.id) { - case CHIP_ID_185x_PG20: - wl1271_debug(DEBUG_BOOT, "chip id 0x%x (185x PG20)", - wl->chip.id); - wl->sr_fw_name = WL18XX_FW_NAME; - /* wl18xx uses the same firmware for PLT */ - wl->plt_fw_name = WL18XX_FW_NAME; - wl->quirks |= WLCORE_QUIRK_NO_ELP | - WLCORE_QUIRK_RX_BLOCKSIZE_ALIGN | - WLCORE_QUIRK_TX_PAD_LAST_FRAME; - - break; - case CHIP_ID_185x_PG10: - wl1271_debug(DEBUG_BOOT, "chip id 0x%x (185x PG10)", - wl->chip.id); - wl->sr_fw_name = WL18XX_FW_NAME; - /* wl18xx uses the same firmware for PLT */ - wl->plt_fw_name = WL18XX_FW_NAME; - wl->quirks |= WLCORE_QUIRK_NO_ELP | - WLCORE_QUIRK_FWLOG_NOT_IMPLEMENTED | - WLCORE_QUIRK_RX_BLOCKSIZE_ALIGN | - WLCORE_QUIRK_TX_BLOCKSIZE_ALIGN; - - /* PG 1.0 has some problems with MCS_13, so disable it */ - wl->ht_cap[IEEE80211_BAND_2GHZ].mcs.rx_mask[1] &= ~BIT(5); - - break; - default: - wl1271_warning("unsupported chip id: 0x%x", wl->chip.id); - ret = -ENODEV; - goto out; - } - -out: - return ret; -} - -static void wl18xx_set_clk(struct wl1271 *wl) -{ - u32 clk_freq; - - wlcore_set_partition(wl, &wl->ptable[PART_TOP_PRCM_ELP_SOC]); - - /* TODO: PG2: apparently we need to read the clk type */ - - clk_freq = wl18xx_top_reg_read(wl, PRIMARY_CLK_DETECT); - wl1271_debug(DEBUG_BOOT, "clock freq %d (%d, %d, %d, %d, %s)", clk_freq, - wl18xx_clk_table[clk_freq].n, wl18xx_clk_table[clk_freq].m, - wl18xx_clk_table[clk_freq].p, wl18xx_clk_table[clk_freq].q, - wl18xx_clk_table[clk_freq].swallow ? "swallow" : "spit"); - - wl18xx_top_reg_write(wl, PLLSH_WCS_PLL_N, wl18xx_clk_table[clk_freq].n); - wl18xx_top_reg_write(wl, PLLSH_WCS_PLL_M, wl18xx_clk_table[clk_freq].m); - - if (wl18xx_clk_table[clk_freq].swallow) { - /* first the 16 lower bits */ - wl18xx_top_reg_write(wl, PLLSH_WCS_PLL_Q_FACTOR_CFG_1, - wl18xx_clk_table[clk_freq].q & - PLLSH_WCS_PLL_Q_FACTOR_CFG_1_MASK); - /* then the 16 higher bits, masked out */ - wl18xx_top_reg_write(wl, PLLSH_WCS_PLL_Q_FACTOR_CFG_2, - (wl18xx_clk_table[clk_freq].q >> 16) & - PLLSH_WCS_PLL_Q_FACTOR_CFG_2_MASK); - - /* first the 16 lower bits */ - wl18xx_top_reg_write(wl, PLLSH_WCS_PLL_P_FACTOR_CFG_1, - wl18xx_clk_table[clk_freq].p & - PLLSH_WCS_PLL_P_FACTOR_CFG_1_MASK); - /* then the 16 higher bits, masked out */ - wl18xx_top_reg_write(wl, PLLSH_WCS_PLL_P_FACTOR_CFG_2, - (wl18xx_clk_table[clk_freq].p >> 16) & - PLLSH_WCS_PLL_P_FACTOR_CFG_2_MASK); - } else { - wl18xx_top_reg_write(wl, PLLSH_WCS_PLL_SWALLOW_EN, - PLLSH_WCS_PLL_SWALLOW_EN_VAL2); - } -} - -static void wl18xx_boot_soft_reset(struct wl1271 *wl) -{ - /* disable Rx/Tx */ - wl1271_write32(wl, WL18XX_ENABLE, 0x0); - - /* disable auto calibration on start*/ - wl1271_write32(wl, WL18XX_SPARE_A2, 0xffff); -} - -static int wl18xx_pre_boot(struct wl1271 *wl) -{ - wl18xx_set_clk(wl); - - /* Continue the ELP wake up sequence */ - wl1271_write32(wl, WL18XX_WELP_ARM_COMMAND, WELP_ARM_COMMAND_VAL); - udelay(500); - - wlcore_set_partition(wl, &wl->ptable[PART_BOOT]); - - /* Disable interrupts */ - wlcore_write_reg(wl, REG_INTERRUPT_MASK, WL1271_ACX_INTR_ALL); - - wl18xx_boot_soft_reset(wl); - - return 0; -} - -static void wl18xx_pre_upload(struct wl1271 *wl) -{ - u32 tmp; - - wlcore_set_partition(wl, &wl->ptable[PART_BOOT]); - - /* TODO: check if this is all needed */ - wl1271_write32(wl, WL18XX_EEPROMLESS_IND, WL18XX_EEPROMLESS_IND); - - tmp = wlcore_read_reg(wl, REG_CHIP_ID_B); - - wl1271_debug(DEBUG_BOOT, "chip id 0x%x", tmp); - - tmp = wl1271_read32(wl, WL18XX_SCR_PAD2); -} - -static void wl18xx_set_mac_and_phy(struct wl1271 *wl) -{ - struct wl18xx_priv *priv = wl->priv; - size_t len; - - /* the parameters struct is smaller for PG1 */ - if (wl->chip.id == CHIP_ID_185x_PG10) - len = offsetof(struct wl18xx_mac_and_phy_params, psat) + 1; - else - len = sizeof(struct wl18xx_mac_and_phy_params); - - wlcore_set_partition(wl, &wl->ptable[PART_PHY_INIT]); - wl1271_write(wl, WL18XX_PHY_INIT_MEM_ADDR, (u8 *)&priv->conf.phy, len, - false); -} - -static void wl18xx_enable_interrupts(struct wl1271 *wl) -{ - u32 event_mask, intr_mask; - - if (wl->chip.id == CHIP_ID_185x_PG10) { - event_mask = WL18XX_ACX_EVENTS_VECTOR_PG1; - intr_mask = WL18XX_INTR_MASK_PG1; - } else { - event_mask = WL18XX_ACX_EVENTS_VECTOR_PG2; - intr_mask = WL18XX_INTR_MASK_PG2; - } - - wlcore_write_reg(wl, REG_INTERRUPT_MASK, event_mask); - - wlcore_enable_interrupts(wl); - wlcore_write_reg(wl, REG_INTERRUPT_MASK, - WL1271_ACX_INTR_ALL & ~intr_mask); -} - -static int wl18xx_boot(struct wl1271 *wl) -{ - int ret; - - ret = wl18xx_pre_boot(wl); - if (ret < 0) - goto out; - - wl18xx_pre_upload(wl); - - ret = wlcore_boot_upload_firmware(wl); - if (ret < 0) - goto out; - - wl18xx_set_mac_and_phy(wl); - - ret = wlcore_boot_run_firmware(wl); - if (ret < 0) - goto out; - - wl18xx_enable_interrupts(wl); - -out: - return ret; -} - -static void wl18xx_trigger_cmd(struct wl1271 *wl, int cmd_box_addr, - void *buf, size_t len) -{ - struct wl18xx_priv *priv = wl->priv; - - memcpy(priv->cmd_buf, buf, len); - memset(priv->cmd_buf + len, 0, WL18XX_CMD_MAX_SIZE - len); - - wl1271_write(wl, cmd_box_addr, priv->cmd_buf, WL18XX_CMD_MAX_SIZE, - false); -} - -static void wl18xx_ack_event(struct wl1271 *wl) -{ - wlcore_write_reg(wl, REG_INTERRUPT_TRIG, WL18XX_INTR_TRIG_EVENT_ACK); -} - -static u32 wl18xx_calc_tx_blocks(struct wl1271 *wl, u32 len, u32 spare_blks) -{ - u32 blk_size = WL18XX_TX_HW_BLOCK_SIZE; - return (len + blk_size - 1) / blk_size + spare_blks; -} - -static void -wl18xx_set_tx_desc_blocks(struct wl1271 *wl, struct wl1271_tx_hw_descr *desc, - u32 blks, u32 spare_blks) -{ - desc->wl18xx_mem.total_mem_blocks = blks; -} - -static void -wl18xx_set_tx_desc_data_len(struct wl1271 *wl, struct wl1271_tx_hw_descr *desc, - struct sk_buff *skb) -{ - desc->length = cpu_to_le16(skb->len); - - /* if only the last frame is to be padded, we unset this bit on Tx */ - if (wl->quirks & WLCORE_QUIRK_TX_PAD_LAST_FRAME) - desc->wl18xx_mem.ctrl = WL18XX_TX_CTRL_NOT_PADDED; - else - desc->wl18xx_mem.ctrl = 0; - - wl1271_debug(DEBUG_TX, "tx_fill_hdr: hlid: %d " - "len: %d life: %d mem: %d", desc->hlid, - le16_to_cpu(desc->length), - le16_to_cpu(desc->life_time), - desc->wl18xx_mem.total_mem_blocks); -} - -static enum wl_rx_buf_align -wl18xx_get_rx_buf_align(struct wl1271 *wl, u32 rx_desc) -{ - if (rx_desc & RX_BUF_PADDED_PAYLOAD) - return WLCORE_RX_BUF_PADDED; - - return WLCORE_RX_BUF_ALIGNED; -} - -static u32 wl18xx_get_rx_packet_len(struct wl1271 *wl, void *rx_data, - u32 data_len) -{ - struct wl1271_rx_descriptor *desc = rx_data; - - /* invalid packet */ - if (data_len < sizeof(*desc)) - return 0; - - return data_len - sizeof(*desc); -} - -static void wl18xx_tx_immediate_completion(struct wl1271 *wl) -{ - wl18xx_tx_immediate_complete(wl); -} - -static int wl18xx_set_host_cfg_bitmap(struct wl1271 *wl, u32 extra_mem_blk) -{ - int ret; - u32 sdio_align_size = 0; - u32 host_cfg_bitmap = HOST_IF_CFG_RX_FIFO_ENABLE | - HOST_IF_CFG_ADD_RX_ALIGNMENT; - - /* Enable Tx SDIO padding */ - if (wl->quirks & WLCORE_QUIRK_TX_BLOCKSIZE_ALIGN) { - host_cfg_bitmap |= HOST_IF_CFG_TX_PAD_TO_SDIO_BLK; - sdio_align_size = WL12XX_BUS_BLOCK_SIZE; - } - - /* Enable Rx SDIO padding */ - if (wl->quirks & WLCORE_QUIRK_RX_BLOCKSIZE_ALIGN) { - host_cfg_bitmap |= HOST_IF_CFG_RX_PAD_TO_SDIO_BLK; - sdio_align_size = WL12XX_BUS_BLOCK_SIZE; - } - - ret = wl18xx_acx_host_if_cfg_bitmap(wl, host_cfg_bitmap, - sdio_align_size, extra_mem_blk, - WL18XX_HOST_IF_LEN_SIZE_FIELD); - if (ret < 0) - return ret; - - return 0; -} - -static int wl18xx_hw_init(struct wl1271 *wl) -{ - int ret; - struct wl18xx_priv *priv = wl->priv; - - /* (re)init private structures. Relevant on recovery as well. */ - priv->last_fw_rls_idx = 0; - priv->extra_spare_vif_count = 0; - - /* set the default amount of spare blocks in the bitmap */ - ret = wl18xx_set_host_cfg_bitmap(wl, WL18XX_TX_HW_BLOCK_SPARE); - if (ret < 0) - return ret; - - if (checksum_param) { - ret = wl18xx_acx_set_checksum_state(wl); - if (ret != 0) - return ret; - } - - return ret; -} - -static void wl18xx_set_tx_desc_csum(struct wl1271 *wl, - struct wl1271_tx_hw_descr *desc, - struct sk_buff *skb) -{ - u32 ip_hdr_offset; - struct iphdr *ip_hdr; - - if (!checksum_param) { - desc->wl18xx_checksum_data = 0; - return; - } - - if (skb->ip_summed != CHECKSUM_PARTIAL) { - desc->wl18xx_checksum_data = 0; - return; - } - - ip_hdr_offset = skb_network_header(skb) - skb_mac_header(skb); - if (WARN_ON(ip_hdr_offset >= (1<<7))) { - desc->wl18xx_checksum_data = 0; - return; - } - - desc->wl18xx_checksum_data = ip_hdr_offset << 1; - - /* FW is interested only in the LSB of the protocol TCP=0 UDP=1 */ - ip_hdr = (void *)skb_network_header(skb); - desc->wl18xx_checksum_data |= (ip_hdr->protocol & 0x01); -} - -static void wl18xx_set_rx_csum(struct wl1271 *wl, - struct wl1271_rx_descriptor *desc, - struct sk_buff *skb) -{ - if (desc->status & WL18XX_RX_CHECKSUM_MASK) - skb->ip_summed = CHECKSUM_UNNECESSARY; -} - -/* - * TODO: instead of having these two functions to get the rate mask, - * we should modify the wlvif->rate_set instead - */ -static u32 wl18xx_sta_get_ap_rate_mask(struct wl1271 *wl, - struct wl12xx_vif *wlvif) -{ - u32 hw_rate_set = wlvif->rate_set; - - if (wlvif->channel_type == NL80211_CHAN_HT40MINUS || - wlvif->channel_type == NL80211_CHAN_HT40PLUS) { - wl1271_debug(DEBUG_ACX, "using wide channel rate mask"); - hw_rate_set |= CONF_TX_RATE_USE_WIDE_CHAN; - - /* we don't support MIMO in wide-channel mode */ - hw_rate_set &= ~CONF_TX_MIMO_RATES; - } - - return hw_rate_set; -} - -static u32 wl18xx_ap_get_mimo_wide_rate_mask(struct wl1271 *wl, - struct wl12xx_vif *wlvif) -{ - if ((wlvif->channel_type == NL80211_CHAN_HT40MINUS || - wlvif->channel_type == NL80211_CHAN_HT40PLUS) && - !strcmp(ht_mode_param, "wide")) { - wl1271_debug(DEBUG_ACX, "using wide channel rate mask"); - return CONF_TX_RATE_USE_WIDE_CHAN; - } else if (!strcmp(ht_mode_param, "mimo")) { - wl1271_debug(DEBUG_ACX, "using MIMO rate mask"); - - /* - * PG 1.0 has some problems with MCS_13, so disable it - * - * TODO: instead of hacking this in here, we should - * make it more general and change a bit in the - * wlvif->rate_set instead. - */ - if (wl->chip.id == CHIP_ID_185x_PG10) - return CONF_TX_MIMO_RATES & ~CONF_HW_BIT_RATE_MCS_13; - - return CONF_TX_MIMO_RATES; - } else { - return 0; - } -} - -static s8 wl18xx_get_pg_ver(struct wl1271 *wl) -{ - u32 fuse; - - wlcore_set_partition(wl, &wl->ptable[PART_TOP_PRCM_ELP_SOC]); - - fuse = wl1271_read32(wl, WL18XX_REG_FUSE_DATA_1_3); - fuse = (fuse & WL18XX_PG_VER_MASK) >> WL18XX_PG_VER_OFFSET; - - wlcore_set_partition(wl, &wl->ptable[PART_BOOT]); - - return (s8)fuse; -} - -#define WL18XX_CONF_FILE_NAME "ti-connectivity/wl18xx-conf.bin" -static int wl18xx_conf_init(struct wl1271 *wl, struct device *dev) -{ - struct wl18xx_priv *priv = wl->priv; - struct wlcore_conf_file *conf_file; - const struct firmware *fw; - int ret; - - ret = request_firmware(&fw, WL18XX_CONF_FILE_NAME, dev); - if (ret < 0) { - wl1271_error("could not get configuration binary %s: %d", - WL18XX_CONF_FILE_NAME, ret); - goto out_fallback; - } - - if (fw->size != WL18XX_CONF_SIZE) { - wl1271_error("configuration binary file size is wrong, " - "expected %ld got %zd", - WL18XX_CONF_SIZE, fw->size); - ret = -EINVAL; - goto out; - } - - conf_file = (struct wlcore_conf_file *) fw->data; - - if (conf_file->header.magic != cpu_to_le32(WL18XX_CONF_MAGIC)) { - wl1271_error("configuration binary file magic number mismatch, " - "expected 0x%0x got 0x%0x", WL18XX_CONF_MAGIC, - conf_file->header.magic); - ret = -EINVAL; - goto out; - } - - if (conf_file->header.version != cpu_to_le32(WL18XX_CONF_VERSION)) { - wl1271_error("configuration binary file version not supported, " - "expected 0x%08x got 0x%08x", - WL18XX_CONF_VERSION, conf_file->header.version); - ret = -EINVAL; - goto out; - } - - memcpy(&wl->conf, &conf_file->core, sizeof(wl18xx_conf)); - memcpy(&priv->conf, &conf_file->priv, sizeof(priv->conf)); - - goto out; - -out_fallback: - wl1271_warning("falling back to default config"); - - /* apply driver default configuration */ - memcpy(&wl->conf, &wl18xx_conf, sizeof(wl18xx_conf)); - /* apply default private configuration */ - memcpy(&priv->conf, &wl18xx_default_priv_conf, sizeof(priv->conf)); - - /* For now we just fallback */ - return 0; - -out: - release_firmware(fw); - return ret; -} - -static int wl18xx_plt_init(struct wl1271 *wl) -{ - wl1271_write32(wl, WL18XX_SCR_PAD8, WL18XX_SCR_PAD8_PLT); - - return wl->ops->boot(wl); -} - -static void wl18xx_get_mac(struct wl1271 *wl) -{ - u32 mac1, mac2; - - wlcore_set_partition(wl, &wl->ptable[PART_TOP_PRCM_ELP_SOC]); - - mac1 = wl1271_read32(wl, WL18XX_REG_FUSE_BD_ADDR_1); - mac2 = wl1271_read32(wl, WL18XX_REG_FUSE_BD_ADDR_2); - - /* these are the two parts of the BD_ADDR */ - wl->fuse_oui_addr = ((mac2 & 0xffff) << 8) + - ((mac1 & 0xff000000) >> 24); - wl->fuse_nic_addr = (mac1 & 0xffffff); - - wlcore_set_partition(wl, &wl->ptable[PART_DOWN]); -} - -static int wl18xx_handle_static_data(struct wl1271 *wl, - struct wl1271_static_data *static_data) -{ - struct wl18xx_static_data_priv *static_data_priv = - (struct wl18xx_static_data_priv *) static_data->priv; - - wl1271_info("PHY firmware version: %s", static_data_priv->phy_version); - - return 0; -} - -static int wl18xx_get_spare_blocks(struct wl1271 *wl, bool is_gem) -{ - struct wl18xx_priv *priv = wl->priv; - - /* If we have VIFs requiring extra spare, indulge them */ - if (priv->extra_spare_vif_count) - return WL18XX_TX_HW_EXTRA_BLOCK_SPARE; - - return WL18XX_TX_HW_BLOCK_SPARE; -} - -static int wl18xx_set_key(struct wl1271 *wl, enum set_key_cmd cmd, - struct ieee80211_vif *vif, - struct ieee80211_sta *sta, - struct ieee80211_key_conf *key_conf) -{ - struct wl18xx_priv *priv = wl->priv; - bool change_spare = false; - int ret; - - /* - * when adding the first or removing the last GEM/TKIP interface, - * we have to adjust the number of spare blocks. - */ - change_spare = (key_conf->cipher == WL1271_CIPHER_SUITE_GEM || - key_conf->cipher == WLAN_CIPHER_SUITE_TKIP) && - ((priv->extra_spare_vif_count == 0 && cmd == SET_KEY) || - (priv->extra_spare_vif_count == 1 && cmd == DISABLE_KEY)); - - /* no need to change spare - just regular set_key */ - if (!change_spare) - return wlcore_set_key(wl, cmd, vif, sta, key_conf); - - /* - * stop the queues and flush to ensure the next packets are - * in sync with FW spare block accounting - */ - wlcore_stop_queues(wl, WLCORE_QUEUE_STOP_REASON_SPARE_BLK); - wl1271_tx_flush(wl); - - ret = wlcore_set_key(wl, cmd, vif, sta, key_conf); - if (ret < 0) - goto out; - - /* key is now set, change the spare blocks */ - if (cmd == SET_KEY) { - ret = wl18xx_set_host_cfg_bitmap(wl, - WL18XX_TX_HW_EXTRA_BLOCK_SPARE); - if (ret < 0) - goto out; - - priv->extra_spare_vif_count++; - } else { - ret = wl18xx_set_host_cfg_bitmap(wl, - WL18XX_TX_HW_BLOCK_SPARE); - if (ret < 0) - goto out; - - priv->extra_spare_vif_count--; - } - -out: - wlcore_wake_queues(wl, WLCORE_QUEUE_STOP_REASON_SPARE_BLK); - return ret; -} - -static u32 wl18xx_pre_pkt_send(struct wl1271 *wl, - u32 buf_offset, u32 last_len) -{ - if (wl->quirks & WLCORE_QUIRK_TX_PAD_LAST_FRAME) { - struct wl1271_tx_hw_descr *last_desc; - - /* get the last TX HW descriptor written to the aggr buf */ - last_desc = (struct wl1271_tx_hw_descr *)(wl->aggr_buf + - buf_offset - last_len); - - /* the last frame is padded up to an SDIO block */ - last_desc->wl18xx_mem.ctrl &= ~WL18XX_TX_CTRL_NOT_PADDED; - return ALIGN(buf_offset, WL12XX_BUS_BLOCK_SIZE); - } - - /* no modifications */ - return buf_offset; -} - -static struct wlcore_ops wl18xx_ops = { - .identify_chip = wl18xx_identify_chip, - .boot = wl18xx_boot, - .plt_init = wl18xx_plt_init, - .trigger_cmd = wl18xx_trigger_cmd, - .ack_event = wl18xx_ack_event, - .calc_tx_blocks = wl18xx_calc_tx_blocks, - .set_tx_desc_blocks = wl18xx_set_tx_desc_blocks, - .set_tx_desc_data_len = wl18xx_set_tx_desc_data_len, - .get_rx_buf_align = wl18xx_get_rx_buf_align, - .get_rx_packet_len = wl18xx_get_rx_packet_len, - .tx_immediate_compl = wl18xx_tx_immediate_completion, - .tx_delayed_compl = NULL, - .hw_init = wl18xx_hw_init, - .set_tx_desc_csum = wl18xx_set_tx_desc_csum, - .get_pg_ver = wl18xx_get_pg_ver, - .set_rx_csum = wl18xx_set_rx_csum, - .sta_get_ap_rate_mask = wl18xx_sta_get_ap_rate_mask, - .ap_get_mimo_wide_rate_mask = wl18xx_ap_get_mimo_wide_rate_mask, - .get_mac = wl18xx_get_mac, - .debugfs_init = wl18xx_debugfs_add_files, - .handle_static_data = wl18xx_handle_static_data, - .get_spare_blocks = wl18xx_get_spare_blocks, - .set_key = wl18xx_set_key, - .pre_pkt_send = wl18xx_pre_pkt_send, -}; - -/* HT cap appropriate for wide channels */ -static struct ieee80211_sta_ht_cap wl18xx_siso40_ht_cap = { - .cap = IEEE80211_HT_CAP_SGI_20 | IEEE80211_HT_CAP_SGI_40 | - IEEE80211_HT_CAP_SUP_WIDTH_20_40 | IEEE80211_HT_CAP_DSSSCCK40, - .ht_supported = true, - .ampdu_factor = IEEE80211_HT_MAX_AMPDU_16K, - .ampdu_density = IEEE80211_HT_MPDU_DENSITY_16, - .mcs = { - .rx_mask = { 0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0, }, - .rx_highest = cpu_to_le16(150), - .tx_params = IEEE80211_HT_MCS_TX_DEFINED, - }, -}; - -/* HT cap appropriate for SISO 20 */ -static struct ieee80211_sta_ht_cap wl18xx_siso20_ht_cap = { - .cap = IEEE80211_HT_CAP_SGI_20, - .ht_supported = true, - .ampdu_factor = IEEE80211_HT_MAX_AMPDU_16K, - .ampdu_density = IEEE80211_HT_MPDU_DENSITY_16, - .mcs = { - .rx_mask = { 0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0, }, - .rx_highest = cpu_to_le16(72), - .tx_params = IEEE80211_HT_MCS_TX_DEFINED, - }, -}; - -/* HT cap appropriate for MIMO rates in 20mhz channel */ -static struct ieee80211_sta_ht_cap wl18xx_mimo_ht_cap_2ghz = { - .cap = IEEE80211_HT_CAP_SGI_20, - .ht_supported = true, - .ampdu_factor = IEEE80211_HT_MAX_AMPDU_16K, - .ampdu_density = IEEE80211_HT_MPDU_DENSITY_16, - .mcs = { - .rx_mask = { 0xff, 0xff, 0, 0, 0, 0, 0, 0, 0, 0, }, - .rx_highest = cpu_to_le16(144), - .tx_params = IEEE80211_HT_MCS_TX_DEFINED, - }, -}; - -static struct ieee80211_sta_ht_cap wl18xx_mimo_ht_cap_5ghz = { - .cap = IEEE80211_HT_CAP_SGI_20, - .ht_supported = true, - .ampdu_factor = IEEE80211_HT_MAX_AMPDU_16K, - .ampdu_density = IEEE80211_HT_MPDU_DENSITY_16, - .mcs = { - .rx_mask = { 0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0, }, - .rx_highest = cpu_to_le16(72), - .tx_params = IEEE80211_HT_MCS_TX_DEFINED, - }, -}; - -static int __devinit wl18xx_probe(struct platform_device *pdev) -{ - struct wl1271 *wl; - struct ieee80211_hw *hw; - struct wl18xx_priv *priv; - int ret; - - hw = wlcore_alloc_hw(sizeof(*priv)); - if (IS_ERR(hw)) { - wl1271_error("can't allocate hw"); - ret = PTR_ERR(hw); - goto out; - } - - wl = hw->priv; - priv = wl->priv; - wl->ops = &wl18xx_ops; - wl->ptable = wl18xx_ptable; - wl->rtable = wl18xx_rtable; - wl->num_tx_desc = 32; - wl->num_rx_desc = 16; - wl->band_rate_to_idx = wl18xx_band_rate_to_idx; - wl->hw_tx_rate_tbl_size = WL18XX_CONF_HW_RXTX_RATE_MAX; - wl->hw_min_ht_rate = WL18XX_CONF_HW_RXTX_RATE_MCS0; - wl->fw_status_priv_len = sizeof(struct wl18xx_fw_status_priv); - wl->stats.fw_stats_len = sizeof(struct wl18xx_acx_statistics); - wl->static_data_priv_len = sizeof(struct wl18xx_static_data_priv); - - if (!strcmp(ht_mode_param, "wide")) { - memcpy(&wl->ht_cap[IEEE80211_BAND_2GHZ], - &wl18xx_siso40_ht_cap, - sizeof(wl18xx_siso40_ht_cap)); - memcpy(&wl->ht_cap[IEEE80211_BAND_5GHZ], - &wl18xx_siso40_ht_cap, - sizeof(wl18xx_siso40_ht_cap)); - } else if (!strcmp(ht_mode_param, "mimo")) { - memcpy(&wl->ht_cap[IEEE80211_BAND_2GHZ], - &wl18xx_mimo_ht_cap_2ghz, - sizeof(wl18xx_mimo_ht_cap_2ghz)); - memcpy(&wl->ht_cap[IEEE80211_BAND_5GHZ], - &wl18xx_mimo_ht_cap_5ghz, - sizeof(wl18xx_mimo_ht_cap_5ghz)); - } else if (!strcmp(ht_mode_param, "siso20")) { - memcpy(&wl->ht_cap[IEEE80211_BAND_2GHZ], - &wl18xx_siso20_ht_cap, - sizeof(wl18xx_siso20_ht_cap)); - memcpy(&wl->ht_cap[IEEE80211_BAND_5GHZ], - &wl18xx_siso20_ht_cap, - sizeof(wl18xx_siso20_ht_cap)); - } else { - wl1271_error("invalid ht_mode '%s'", ht_mode_param); - ret = -EINVAL; - goto out_free; - } - - ret = wl18xx_conf_init(wl, &pdev->dev); - if (ret < 0) - goto out_free; - - if (!strcmp(board_type_param, "fpga")) { - priv->conf.phy.board_type = BOARD_TYPE_FPGA_18XX; - } else if (!strcmp(board_type_param, "hdk")) { - priv->conf.phy.board_type = BOARD_TYPE_HDK_18XX; - /* HACK! Just for now we hardcode HDK to 0x06 */ - priv->conf.phy.low_band_component_type = 0x06; - } else if (!strcmp(board_type_param, "dvp")) { - priv->conf.phy.board_type = BOARD_TYPE_DVP_18XX; - } else if (!strcmp(board_type_param, "evb")) { - priv->conf.phy.board_type = BOARD_TYPE_EVB_18XX; - } else if (!strcmp(board_type_param, "com8")) { - priv->conf.phy.board_type = BOARD_TYPE_COM8_18XX; - /* HACK! Just for now we hardcode COM8 to 0x06 */ - priv->conf.phy.low_band_component_type = 0x06; - } else { - wl1271_error("invalid board type '%s'", board_type_param); - ret = -EINVAL; - goto out_free; - } - - /* If the module param is set, update it in conf */ - if (low_band_component_param != -1) - priv->conf.phy.low_band_component = low_band_component_param; - if (low_band_component_type_param != -1) - priv->conf.phy.low_band_component_type = - low_band_component_type_param; - if (high_band_component_param != -1) - priv->conf.phy.high_band_component = high_band_component_param; - if (high_band_component_type_param != -1) - priv->conf.phy.high_band_component_type = - high_band_component_type_param; - if (pwr_limit_reference_11_abg_param != -1) - priv->conf.phy.pwr_limit_reference_11_abg = - pwr_limit_reference_11_abg_param; - if (n_antennas_2_param != -1) - priv->conf.phy.number_of_assembled_ant2_4 = n_antennas_2_param; - if (n_antennas_5_param != -1) - priv->conf.phy.number_of_assembled_ant5 = n_antennas_5_param; - if (dc2dc_param != -1) - priv->conf.phy.external_pa_dc2dc = dc2dc_param; - - if (!checksum_param) { - wl18xx_ops.set_rx_csum = NULL; - wl18xx_ops.init_vif = NULL; - } - - wl->enable_11a = enable_11a_param; - - return wlcore_probe(wl, pdev); - -out_free: - wlcore_free_hw(wl); -out: - return ret; -} - -static const struct platform_device_id wl18xx_id_table[] __devinitconst = { - { "wl18xx", 0 }, - { } /* Terminating Entry */ -}; -MODULE_DEVICE_TABLE(platform, wl18xx_id_table); - -static struct platform_driver wl18xx_driver = { - .probe = wl18xx_probe, - .remove = __devexit_p(wlcore_remove), - .id_table = wl18xx_id_table, - .driver = { - .name = "wl18xx_driver", - .owner = THIS_MODULE, - } -}; - -static int __init wl18xx_init(void) -{ - return platform_driver_register(&wl18xx_driver); -} -module_init(wl18xx_init); - -static void __exit wl18xx_exit(void) -{ - platform_driver_unregister(&wl18xx_driver); -} -module_exit(wl18xx_exit); - -module_param_named(ht_mode, ht_mode_param, charp, S_IRUSR); -MODULE_PARM_DESC(ht_mode, "Force HT mode: wide (default), mimo or siso20"); - -module_param_named(board_type, board_type_param, charp, S_IRUSR); -MODULE_PARM_DESC(board_type, "Board type: fpga, hdk (default), evb, com8 or " - "dvp"); - -module_param_named(checksum, checksum_param, bool, S_IRUSR); -MODULE_PARM_DESC(checksum, "Enable TCP checksum: boolean (defaults to false)"); - -module_param_named(enable_11a, enable_11a_param, bool, S_IRUSR); -MODULE_PARM_DESC(enable_11a, "Enable 11a (5GHz): boolean (defaults to true)"); - -module_param_named(dc2dc, dc2dc_param, int, S_IRUSR); -MODULE_PARM_DESC(dc2dc, "External DC2DC: u8 (defaults to 0)"); - -module_param_named(n_antennas_2, n_antennas_2_param, int, S_IRUSR); -MODULE_PARM_DESC(n_antennas_2, - "Number of installed 2.4GHz antennas: 1 (default) or 2"); - -module_param_named(n_antennas_5, n_antennas_5_param, int, S_IRUSR); -MODULE_PARM_DESC(n_antennas_5, - "Number of installed 5GHz antennas: 1 (default) or 2"); - -module_param_named(low_band_component, low_band_component_param, int, - S_IRUSR); -MODULE_PARM_DESC(low_band_component, "Low band component: u8 " - "(default is 0x01)"); - -module_param_named(low_band_component_type, low_band_component_type_param, - int, S_IRUSR); -MODULE_PARM_DESC(low_band_component_type, "Low band component type: u8 " - "(default is 0x05 or 0x06 depending on the board_type)"); - -module_param_named(high_band_component, high_band_component_param, int, - S_IRUSR); -MODULE_PARM_DESC(high_band_component, "High band component: u8, " - "(default is 0x01)"); - -module_param_named(high_band_component_type, high_band_component_type_param, - int, S_IRUSR); -MODULE_PARM_DESC(high_band_component_type, "High band component type: u8 " - "(default is 0x09)"); - -module_param_named(pwr_limit_reference_11_abg, - pwr_limit_reference_11_abg_param, int, S_IRUSR); -MODULE_PARM_DESC(pwr_limit_reference_11_abg, "Power limit reference: u8 " - "(default is 0xc8)"); - -MODULE_LICENSE("GPL v2"); -MODULE_AUTHOR("Luciano Coelho "); -MODULE_FIRMWARE(WL18XX_FW_NAME); diff --git a/trunk/drivers/net/wireless/ti/wl18xx/reg.h b/trunk/drivers/net/wireless/ti/wl18xx/reg.h deleted file mode 100644 index 937b71d8783f..000000000000 --- a/trunk/drivers/net/wireless/ti/wl18xx/reg.h +++ /dev/null @@ -1,191 +0,0 @@ -/* - * This file is part of wlcore - * - * 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 - * - */ - -#ifndef __REG_H__ -#define __REG_H__ - -#define WL18XX_REGISTERS_BASE 0x00800000 -#define WL18XX_CODE_BASE 0x00000000 -#define WL18XX_DATA_BASE 0x00400000 -#define WL18XX_DOUBLE_BUFFER_BASE 0x00600000 -#define WL18XX_MCU_KEY_SEARCH_BASE 0x00700000 -#define WL18XX_PHY_BASE 0x00900000 -#define WL18XX_TOP_OCP_BASE 0x00A00000 -#define WL18XX_PACKET_RAM_BASE 0x00B00000 -#define WL18XX_HOST_BASE 0x00C00000 - -#define WL18XX_REGISTERS_DOWN_SIZE 0x0000B000 - -#define WL18XX_REG_BOOT_PART_START 0x00802000 -#define WL18XX_REG_BOOT_PART_SIZE 0x00014578 - -#define WL18XX_PHY_INIT_MEM_ADDR 0x80926000 - -#define WL18XX_SDIO_WSPI_BASE (WL18XX_REGISTERS_BASE) -#define WL18XX_REG_CONFIG_BASE (WL18XX_REGISTERS_BASE + 0x02000) -#define WL18XX_WGCM_REGS_BASE (WL18XX_REGISTERS_BASE + 0x03000) -#define WL18XX_ENC_BASE (WL18XX_REGISTERS_BASE + 0x04000) -#define WL18XX_INTERRUPT_BASE (WL18XX_REGISTERS_BASE + 0x05000) -#define WL18XX_UART_BASE (WL18XX_REGISTERS_BASE + 0x06000) -#define WL18XX_WELP_BASE (WL18XX_REGISTERS_BASE + 0x07000) -#define WL18XX_TCP_CKSM_BASE (WL18XX_REGISTERS_BASE + 0x08000) -#define WL18XX_FIFO_BASE (WL18XX_REGISTERS_BASE + 0x09000) -#define WL18XX_OCP_BRIDGE_BASE (WL18XX_REGISTERS_BASE + 0x0A000) -#define WL18XX_PMAC_RX_BASE (WL18XX_REGISTERS_BASE + 0x14800) -#define WL18XX_PMAC_ACM_BASE (WL18XX_REGISTERS_BASE + 0x14C00) -#define WL18XX_PMAC_TX_BASE (WL18XX_REGISTERS_BASE + 0x15000) -#define WL18XX_PMAC_CSR_BASE (WL18XX_REGISTERS_BASE + 0x15400) - -#define WL18XX_REG_ECPU_CONTROL (WL18XX_REGISTERS_BASE + 0x02004) -#define WL18XX_REG_INTERRUPT_NO_CLEAR (WL18XX_REGISTERS_BASE + 0x050E8) -#define WL18XX_REG_INTERRUPT_ACK (WL18XX_REGISTERS_BASE + 0x050F0) -#define WL18XX_REG_INTERRUPT_TRIG (WL18XX_REGISTERS_BASE + 0x5074) -#define WL18XX_REG_INTERRUPT_TRIG_H (WL18XX_REGISTERS_BASE + 0x5078) -#define WL18XX_REG_INTERRUPT_MASK (WL18XX_REGISTERS_BASE + 0x0050DC) - -#define WL18XX_REG_CHIP_ID_B (WL18XX_REGISTERS_BASE + 0x01542C) - -#define WL18XX_SLV_MEM_DATA (WL18XX_HOST_BASE + 0x0018) -#define WL18XX_SLV_REG_DATA (WL18XX_HOST_BASE + 0x0008) - -/* Scratch Pad registers*/ -#define WL18XX_SCR_PAD0 (WL18XX_REGISTERS_BASE + 0x0154EC) -#define WL18XX_SCR_PAD1 (WL18XX_REGISTERS_BASE + 0x0154F0) -#define WL18XX_SCR_PAD2 (WL18XX_REGISTERS_BASE + 0x0154F4) -#define WL18XX_SCR_PAD3 (WL18XX_REGISTERS_BASE + 0x0154F8) -#define WL18XX_SCR_PAD4 (WL18XX_REGISTERS_BASE + 0x0154FC) -#define WL18XX_SCR_PAD4_SET (WL18XX_REGISTERS_BASE + 0x015504) -#define WL18XX_SCR_PAD4_CLR (WL18XX_REGISTERS_BASE + 0x015500) -#define WL18XX_SCR_PAD5 (WL18XX_REGISTERS_BASE + 0x015508) -#define WL18XX_SCR_PAD5_SET (WL18XX_REGISTERS_BASE + 0x015510) -#define WL18XX_SCR_PAD5_CLR (WL18XX_REGISTERS_BASE + 0x01550C) -#define WL18XX_SCR_PAD6 (WL18XX_REGISTERS_BASE + 0x015514) -#define WL18XX_SCR_PAD7 (WL18XX_REGISTERS_BASE + 0x015518) -#define WL18XX_SCR_PAD8 (WL18XX_REGISTERS_BASE + 0x01551C) -#define WL18XX_SCR_PAD9 (WL18XX_REGISTERS_BASE + 0x015520) - -/* Spare registers*/ -#define WL18XX_SPARE_A1 (WL18XX_REGISTERS_BASE + 0x002194) -#define WL18XX_SPARE_A2 (WL18XX_REGISTERS_BASE + 0x002198) -#define WL18XX_SPARE_A3 (WL18XX_REGISTERS_BASE + 0x00219C) -#define WL18XX_SPARE_A4 (WL18XX_REGISTERS_BASE + 0x0021A0) -#define WL18XX_SPARE_A5 (WL18XX_REGISTERS_BASE + 0x0021A4) -#define WL18XX_SPARE_A6 (WL18XX_REGISTERS_BASE + 0x0021A8) -#define WL18XX_SPARE_A7 (WL18XX_REGISTERS_BASE + 0x0021AC) -#define WL18XX_SPARE_A8 (WL18XX_REGISTERS_BASE + 0x0021B0) -#define WL18XX_SPARE_B1 (WL18XX_REGISTERS_BASE + 0x015524) -#define WL18XX_SPARE_B2 (WL18XX_REGISTERS_BASE + 0x015528) -#define WL18XX_SPARE_B3 (WL18XX_REGISTERS_BASE + 0x01552C) -#define WL18XX_SPARE_B4 (WL18XX_REGISTERS_BASE + 0x015530) -#define WL18XX_SPARE_B5 (WL18XX_REGISTERS_BASE + 0x015534) -#define WL18XX_SPARE_B6 (WL18XX_REGISTERS_BASE + 0x015538) -#define WL18XX_SPARE_B7 (WL18XX_REGISTERS_BASE + 0x01553C) -#define WL18XX_SPARE_B8 (WL18XX_REGISTERS_BASE + 0x015540) - -#define WL18XX_REG_COMMAND_MAILBOX_PTR (WL18XX_SCR_PAD0) -#define WL18XX_REG_EVENT_MAILBOX_PTR (WL18XX_SCR_PAD1) -#define WL18XX_EEPROMLESS_IND (WL18XX_SCR_PAD4) - -#define WL18XX_WELP_ARM_COMMAND (WL18XX_REGISTERS_BASE + 0x7100) -#define WL18XX_ENABLE (WL18XX_REGISTERS_BASE + 0x01543C) - -/* PRCM registers */ -#define PLATFORM_DETECTION 0xA0E3E0 -#define OCS_EN 0xA02080 -#define PRIMARY_CLK_DETECT 0xA020A6 -#define PLLSH_WCS_PLL_N 0xA02362 -#define PLLSH_WCS_PLL_M 0xA02360 -#define PLLSH_WCS_PLL_Q_FACTOR_CFG_1 0xA02364 -#define PLLSH_WCS_PLL_Q_FACTOR_CFG_2 0xA02366 -#define PLLSH_WCS_PLL_P_FACTOR_CFG_1 0xA02368 -#define PLLSH_WCS_PLL_P_FACTOR_CFG_2 0xA0236A -#define PLLSH_WCS_PLL_SWALLOW_EN 0xA0236C -#define PLLSH_WL_PLL_EN 0xA02392 - -#define PLLSH_WCS_PLL_Q_FACTOR_CFG_1_MASK 0xFFFF -#define PLLSH_WCS_PLL_Q_FACTOR_CFG_2_MASK 0x007F -#define PLLSH_WCS_PLL_P_FACTOR_CFG_1_MASK 0xFFFF -#define PLLSH_WCS_PLL_P_FACTOR_CFG_2_MASK 0x000F - -#define PLLSH_WCS_PLL_SWALLOW_EN_VAL1 0x1 -#define PLLSH_WCS_PLL_SWALLOW_EN_VAL2 0x12 - -#define WL18XX_REG_FUSE_DATA_1_3 0xA0260C -#define WL18XX_PG_VER_MASK 0x70 -#define WL18XX_PG_VER_OFFSET 4 - -#define WL18XX_REG_FUSE_BD_ADDR_1 0xA02602 -#define WL18XX_REG_FUSE_BD_ADDR_2 0xA02606 - -#define WL18XX_CMD_MBOX_ADDRESS 0xB007B4 - -#define WL18XX_FW_STATUS_ADDR 0x50F8 - -#define CHIP_ID_185x_PG10 (0x06030101) -#define CHIP_ID_185x_PG20 (0x06030111) - -/* - * Host Command Interrupt. Setting this bit masks - * the interrupt that the host issues to inform - * the FW that it has sent a command - * to the Wlan hardware Command Mailbox. - */ -#define WL18XX_INTR_TRIG_CMD BIT(28) - -/* - * Host Event Acknowlegde Interrupt. The host - * sets this bit to acknowledge that it received - * the unsolicited information from the event - * mailbox. - */ -#define WL18XX_INTR_TRIG_EVENT_ACK BIT(29) - -/* - * To boot the firmware in PLT mode we need to write this value in - * SCR_PAD8 before starting. - */ -#define WL18XX_SCR_PAD8_PLT 0xBABABEBE - -enum { - COMPONENT_NO_SWITCH = 0x0, - COMPONENT_2_WAY_SWITCH = 0x1, - COMPONENT_3_WAY_SWITCH = 0x2, - COMPONENT_MATCHING = 0x3, -}; - -enum { - FEM_NONE = 0x0, - FEM_VENDOR_1 = 0x1, - FEM_VENDOR_2 = 0x2, - FEM_VENDOR_3 = 0x3, -}; - -enum { - BOARD_TYPE_EVB_18XX = 0, - BOARD_TYPE_DVP_18XX = 1, - BOARD_TYPE_HDK_18XX = 2, - BOARD_TYPE_FPGA_18XX = 3, - BOARD_TYPE_COM8_18XX = 4, - - NUM_BOARD_TYPES, -}; - -#endif /* __REG_H__ */ diff --git a/trunk/drivers/net/wireless/ti/wl18xx/tx.c b/trunk/drivers/net/wireless/ti/wl18xx/tx.c deleted file mode 100644 index 5b1fb10d9fd7..000000000000 --- a/trunk/drivers/net/wireless/ti/wl18xx/tx.c +++ /dev/null @@ -1,127 +0,0 @@ -/* - * 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/wlcore.h" -#include "../wlcore/cmd.h" -#include "../wlcore/debug.h" -#include "../wlcore/acx.h" -#include "../wlcore/tx.h" - -#include "wl18xx.h" -#include "tx.h" - -static void wl18xx_tx_complete_packet(struct wl1271 *wl, u8 tx_stat_byte) -{ - struct ieee80211_tx_info *info; - struct sk_buff *skb; - int id = tx_stat_byte & WL18XX_TX_STATUS_DESC_ID_MASK; - bool tx_success; - - /* check for id legality */ - if (unlikely(id >= wl->num_tx_desc || wl->tx_frames[id] == NULL)) { - wl1271_warning("illegal id in tx completion: %d", id); - return; - } - - /* a zero bit indicates Tx success */ - tx_success = !(tx_stat_byte & BIT(WL18XX_TX_STATUS_STAT_BIT_IDX)); - - - skb = wl->tx_frames[id]; - info = IEEE80211_SKB_CB(skb); - - if (wl12xx_is_dummy_packet(wl, skb)) { - wl1271_free_tx_id(wl, id); - return; - } - - /* update the TX status info */ - if (tx_success && !(info->flags & IEEE80211_TX_CTL_NO_ACK)) - info->flags |= IEEE80211_TX_STAT_ACK; - - /* no real data about Tx completion */ - info->status.rates[0].idx = -1; - info->status.rates[0].count = 0; - info->status.rates[0].flags = 0; - info->status.ack_signal = -1; - - if (!tx_success) - wl->stats.retry_count++; - - /* - * TODO: update sequence number for encryption? seems to be - * unsupported for now. needed for recovery with encryption. - */ - - /* remove private header from packet */ - skb_pull(skb, sizeof(struct wl1271_tx_hw_descr)); - - /* remove TKIP header space if present */ - if ((wl->quirks & WLCORE_QUIRK_TKIP_HEADER_SPACE) && - info->control.hw_key && - info->control.hw_key->cipher == WLAN_CIPHER_SUITE_TKIP) { - int hdrlen = ieee80211_get_hdrlen_from_skb(skb); - memmove(skb->data + WL1271_EXTRA_SPACE_TKIP, skb->data, hdrlen); - skb_pull(skb, WL1271_EXTRA_SPACE_TKIP); - } - - wl1271_debug(DEBUG_TX, "tx status id %u skb 0x%p success %d", - id, skb, tx_success); - - /* return the packet to the stack */ - skb_queue_tail(&wl->deferred_tx_queue, skb); - queue_work(wl->freezable_wq, &wl->netstack_work); - wl1271_free_tx_id(wl, id); -} - -void wl18xx_tx_immediate_complete(struct wl1271 *wl) -{ - struct wl18xx_fw_status_priv *status_priv = - (struct wl18xx_fw_status_priv *)wl->fw_status_2->priv; - struct wl18xx_priv *priv = wl->priv; - u8 i; - - /* nothing to do here */ - if (priv->last_fw_rls_idx == status_priv->fw_release_idx) - return; - - /* freed Tx descriptors */ - wl1271_debug(DEBUG_TX, "last released desc = %d, current idx = %d", - priv->last_fw_rls_idx, status_priv->fw_release_idx); - - if (status_priv->fw_release_idx >= WL18XX_FW_MAX_TX_STATUS_DESC) { - wl1271_error("invalid desc release index %d", - status_priv->fw_release_idx); - WARN_ON(1); - return; - } - - for (i = priv->last_fw_rls_idx; - i != status_priv->fw_release_idx; - i = (i + 1) % WL18XX_FW_MAX_TX_STATUS_DESC) { - wl18xx_tx_complete_packet(wl, - status_priv->released_tx_desc[i]); - - wl->tx_results_count++; - } - - priv->last_fw_rls_idx = status_priv->fw_release_idx; -} diff --git a/trunk/drivers/net/wireless/ti/wl18xx/tx.h b/trunk/drivers/net/wireless/ti/wl18xx/tx.h deleted file mode 100644 index ccddc548e44a..000000000000 --- a/trunk/drivers/net/wireless/ti/wl18xx/tx.h +++ /dev/null @@ -1,46 +0,0 @@ -/* - * This file is part of wl18xx - * - * Copyright (C) 2011 Texas Instruments. All rights reserved. - * - * 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 - * - */ - -#ifndef __WL18XX_TX_H__ -#define __WL18XX_TX_H__ - -#include "../wlcore/wlcore.h" - -#define WL18XX_TX_HW_BLOCK_SPARE 1 -/* for special cases - namely, TKIP and GEM */ -#define WL18XX_TX_HW_EXTRA_BLOCK_SPARE 2 -#define WL18XX_TX_HW_BLOCK_SIZE 268 - -#define WL18XX_TX_STATUS_DESC_ID_MASK 0x7F -#define WL18XX_TX_STATUS_STAT_BIT_IDX 7 - -/* Indicates this TX HW frame is not padded to SDIO block size */ -#define WL18XX_TX_CTRL_NOT_PADDED BIT(7) - -/* - * The FW uses a special bit to indicate a wide channel should be used in - * the rate policy. - */ -#define CONF_TX_RATE_USE_WIDE_CHAN BIT(31) - -void wl18xx_tx_immediate_complete(struct wl1271 *wl); - -#endif /* __WL12XX_TX_H__ */ diff --git a/trunk/drivers/net/wireless/ti/wl18xx/wl18xx.h b/trunk/drivers/net/wireless/ti/wl18xx/wl18xx.h deleted file mode 100644 index bc67a4750615..000000000000 --- a/trunk/drivers/net/wireless/ti/wl18xx/wl18xx.h +++ /dev/null @@ -1,88 +0,0 @@ -/* - * 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 - * - */ - -#ifndef __WL18XX_PRIV_H__ -#define __WL18XX_PRIV_H__ - -#include "conf.h" - -#define WL18XX_CMD_MAX_SIZE 740 - -struct wl18xx_priv { - /* buffer for sending commands to FW */ - u8 cmd_buf[WL18XX_CMD_MAX_SIZE]; - - struct wl18xx_priv_conf conf; - - /* Index of last released Tx desc in FW */ - u8 last_fw_rls_idx; - - /* number of VIFs requiring extra spare mem-blocks */ - int extra_spare_vif_count; -}; - -#define WL18XX_FW_MAX_TX_STATUS_DESC 33 - -struct wl18xx_fw_status_priv { - /* - * Index in released_tx_desc for first byte that holds - * released tx host desc - */ - u8 fw_release_idx; - - /* - * Array of host Tx descriptors, where fw_release_idx - * indicated the first released idx. - */ - u8 released_tx_desc[WL18XX_FW_MAX_TX_STATUS_DESC]; - - u8 padding[2]; -}; - -#define WL18XX_PHY_VERSION_MAX_LEN 20 - -struct wl18xx_static_data_priv { - char phy_version[WL18XX_PHY_VERSION_MAX_LEN]; -}; - -struct wl18xx_clk_cfg { - u32 n; - u32 m; - u32 p; - u32 q; - bool swallow; -}; - -enum { - CLOCK_CONFIG_16_2_M = 1, - CLOCK_CONFIG_16_368_M, - CLOCK_CONFIG_16_8_M, - CLOCK_CONFIG_19_2_M, - CLOCK_CONFIG_26_M, - CLOCK_CONFIG_32_736_M, - CLOCK_CONFIG_33_6_M, - CLOCK_CONFIG_38_468_M, - CLOCK_CONFIG_52_M, - - NUM_CLOCK_CONFIGS, -}; - -#endif /* __WL18XX_PRIV_H__ */ diff --git a/trunk/drivers/net/wireless/ti/wlcore/acx.c b/trunk/drivers/net/wireless/ti/wlcore/acx.c index b9ec42c83757..f3d6fa508269 100644 --- a/trunk/drivers/net/wireless/ti/wlcore/acx.c +++ b/trunk/drivers/net/wireless/ti/wlcore/acx.c @@ -86,7 +86,6 @@ int wl1271_acx_sleep_auth(struct wl1271 *wl, u8 sleep_auth) kfree(auth); return ret; } -EXPORT_SYMBOL_GPL(wl1271_acx_sleep_auth); int wl1271_acx_tx_power(struct wl1271 *wl, struct wl12xx_vif *wlvif, int power) @@ -709,14 +708,14 @@ int wl1271_acx_cts_protect(struct wl1271 *wl, struct wl12xx_vif *wlvif, return ret; } -int wl1271_acx_statistics(struct wl1271 *wl, void *stats) +int wl1271_acx_statistics(struct wl1271 *wl, struct acx_statistics *stats) { int ret; wl1271_debug(DEBUG_ACX, "acx statistics"); ret = wl1271_cmd_interrogate(wl, ACX_STATISTICS, stats, - wl->stats.fw_stats_len); + sizeof(*stats)); if (ret < 0) { wl1271_warning("acx statistics failed: %d", ret); return -ENOMEM; @@ -998,7 +997,6 @@ int wl12xx_acx_mem_cfg(struct wl1271 *wl) kfree(mem_conf); return ret; } -EXPORT_SYMBOL_GPL(wl12xx_acx_mem_cfg); int wl1271_acx_init_mem_config(struct wl1271 *wl) { @@ -1029,7 +1027,6 @@ int wl1271_acx_init_mem_config(struct wl1271 *wl) return 0; } -EXPORT_SYMBOL_GPL(wl1271_acx_init_mem_config); int wl1271_acx_init_rx_interrupt(struct wl1271 *wl) { @@ -1153,7 +1150,6 @@ int wl1271_acx_pm_config(struct wl1271 *wl) kfree(acx); return ret; } -EXPORT_SYMBOL_GPL(wl1271_acx_pm_config); int wl1271_acx_keep_alive_mode(struct wl1271 *wl, struct wl12xx_vif *wlvif, bool enable) diff --git a/trunk/drivers/net/wireless/ti/wlcore/acx.h b/trunk/drivers/net/wireless/ti/wlcore/acx.h index c0181258b722..e6a74869a5ff 100644 --- a/trunk/drivers/net/wireless/ti/wlcore/acx.h +++ b/trunk/drivers/net/wireless/ti/wlcore/acx.h @@ -51,18 +51,21 @@ #define WL1271_ACX_INTR_TRACE_A BIT(7) /* Trace message on MBOX #B */ #define WL1271_ACX_INTR_TRACE_B BIT(8) -/* SW FW Initiated interrupt Watchdog timer expiration */ -#define WL1271_ACX_SW_INTR_WATCHDOG BIT(9) -#define WL1271_ACX_INTR_ALL 0xFFFFFFFF - -/* all possible interrupts - only appropriate ones will be masked in */ -#define WLCORE_ALL_INTR_MASK (WL1271_ACX_INTR_WATCHDOG | \ - WL1271_ACX_INTR_EVENT_A | \ - WL1271_ACX_INTR_EVENT_B | \ - WL1271_ACX_INTR_HW_AVAILABLE | \ - WL1271_ACX_INTR_DATA | \ - WL1271_ACX_SW_INTR_WATCHDOG) +#define WL1271_ACX_INTR_ALL 0xFFFFFFFF +#define WL1271_ACX_ALL_EVENTS_VECTOR (WL1271_ACX_INTR_WATCHDOG | \ + WL1271_ACX_INTR_INIT_COMPLETE | \ + WL1271_ACX_INTR_EVENT_A | \ + WL1271_ACX_INTR_EVENT_B | \ + WL1271_ACX_INTR_CMD_COMPLETE | \ + WL1271_ACX_INTR_HW_AVAILABLE | \ + WL1271_ACX_INTR_DATA) + +#define WL1271_INTR_MASK (WL1271_ACX_INTR_WATCHDOG | \ + WL1271_ACX_INTR_EVENT_A | \ + WL1271_ACX_INTR_EVENT_B | \ + WL1271_ACX_INTR_HW_AVAILABLE | \ + WL1271_ACX_INTR_DATA) /* Target's information element */ struct acx_header { @@ -414,6 +417,228 @@ struct acx_ctsprotect { u8 padding[2]; } __packed; +struct acx_tx_statistics { + __le32 internal_desc_overflow; +} __packed; + +struct acx_rx_statistics { + __le32 out_of_mem; + __le32 hdr_overflow; + __le32 hw_stuck; + __le32 dropped; + __le32 fcs_err; + __le32 xfr_hint_trig; + __le32 path_reset; + __le32 reset_counter; +} __packed; + +struct acx_dma_statistics { + __le32 rx_requested; + __le32 rx_errors; + __le32 tx_requested; + __le32 tx_errors; +} __packed; + +struct acx_isr_statistics { + /* host command complete */ + __le32 cmd_cmplt; + + /* fiqisr() */ + __le32 fiqs; + + /* (INT_STS_ND & INT_TRIG_RX_HEADER) */ + __le32 rx_headers; + + /* (INT_STS_ND & INT_TRIG_RX_CMPLT) */ + __le32 rx_completes; + + /* (INT_STS_ND & INT_TRIG_NO_RX_BUF) */ + __le32 rx_mem_overflow; + + /* (INT_STS_ND & INT_TRIG_S_RX_RDY) */ + __le32 rx_rdys; + + /* irqisr() */ + __le32 irqs; + + /* (INT_STS_ND & INT_TRIG_TX_PROC) */ + __le32 tx_procs; + + /* (INT_STS_ND & INT_TRIG_DECRYPT_DONE) */ + __le32 decrypt_done; + + /* (INT_STS_ND & INT_TRIG_DMA0) */ + __le32 dma0_done; + + /* (INT_STS_ND & INT_TRIG_DMA1) */ + __le32 dma1_done; + + /* (INT_STS_ND & INT_TRIG_TX_EXC_CMPLT) */ + __le32 tx_exch_complete; + + /* (INT_STS_ND & INT_TRIG_COMMAND) */ + __le32 commands; + + /* (INT_STS_ND & INT_TRIG_RX_PROC) */ + __le32 rx_procs; + + /* (INT_STS_ND & INT_TRIG_PM_802) */ + __le32 hw_pm_mode_changes; + + /* (INT_STS_ND & INT_TRIG_ACKNOWLEDGE) */ + __le32 host_acknowledges; + + /* (INT_STS_ND & INT_TRIG_PM_PCI) */ + __le32 pci_pm; + + /* (INT_STS_ND & INT_TRIG_ACM_WAKEUP) */ + __le32 wakeups; + + /* (INT_STS_ND & INT_TRIG_LOW_RSSI) */ + __le32 low_rssi; +} __packed; + +struct acx_wep_statistics { + /* WEP address keys configured */ + __le32 addr_key_count; + + /* default keys configured */ + __le32 default_key_count; + + __le32 reserved; + + /* number of times that WEP key not found on lookup */ + __le32 key_not_found; + + /* number of times that WEP key decryption failed */ + __le32 decrypt_fail; + + /* WEP packets decrypted */ + __le32 packets; + + /* WEP decrypt interrupts */ + __le32 interrupt; +} __packed; + +#define ACX_MISSED_BEACONS_SPREAD 10 + +struct acx_pwr_statistics { + /* the amount of enters into power save mode (both PD & ELP) */ + __le32 ps_enter; + + /* the amount of enters into ELP mode */ + __le32 elp_enter; + + /* the amount of missing beacon interrupts to the host */ + __le32 missing_bcns; + + /* the amount of wake on host-access times */ + __le32 wake_on_host; + + /* the amount of wake on timer-expire */ + __le32 wake_on_timer_exp; + + /* the number of packets that were transmitted with PS bit set */ + __le32 tx_with_ps; + + /* the number of packets that were transmitted with PS bit clear */ + __le32 tx_without_ps; + + /* the number of received beacons */ + __le32 rcvd_beacons; + + /* the number of entering into PowerOn (power save off) */ + __le32 power_save_off; + + /* the number of entries into power save mode */ + __le16 enable_ps; + + /* + * the number of exits from power save, not including failed PS + * transitions + */ + __le16 disable_ps; + + /* + * the number of times the TSF counter was adjusted because + * of drift + */ + __le32 fix_tsf_ps; + + /* Gives statistics about the spread continuous missed beacons. + * The 16 LSB are dedicated for the PS mode. + * The 16 MSB are dedicated for the PS mode. + * cont_miss_bcns_spread[0] - single missed beacon. + * cont_miss_bcns_spread[1] - two continuous missed beacons. + * cont_miss_bcns_spread[2] - three continuous missed beacons. + * ... + * cont_miss_bcns_spread[9] - ten and more continuous missed beacons. + */ + __le32 cont_miss_bcns_spread[ACX_MISSED_BEACONS_SPREAD]; + + /* the number of beacons in awake mode */ + __le32 rcvd_awake_beacons; +} __packed; + +struct acx_mic_statistics { + __le32 rx_pkts; + __le32 calc_failure; +} __packed; + +struct acx_aes_statistics { + __le32 encrypt_fail; + __le32 decrypt_fail; + __le32 encrypt_packets; + __le32 decrypt_packets; + __le32 encrypt_interrupt; + __le32 decrypt_interrupt; +} __packed; + +struct acx_event_statistics { + __le32 heart_beat; + __le32 calibration; + __le32 rx_mismatch; + __le32 rx_mem_empty; + __le32 rx_pool; + __le32 oom_late; + __le32 phy_transmit_error; + __le32 tx_stuck; +} __packed; + +struct acx_ps_statistics { + __le32 pspoll_timeouts; + __le32 upsd_timeouts; + __le32 upsd_max_sptime; + __le32 upsd_max_apturn; + __le32 pspoll_max_apturn; + __le32 pspoll_utilization; + __le32 upsd_utilization; +} __packed; + +struct acx_rxpipe_statistics { + __le32 rx_prep_beacon_drop; + __le32 descr_host_int_trig_rx_data; + __le32 beacon_buffer_thres_host_int_trig_rx_data; + __le32 missed_beacon_host_int_trig_rx_data; + __le32 tx_xfr_host_int_trig_rx_data; +} __packed; + +struct acx_statistics { + struct acx_header header; + + struct acx_tx_statistics tx; + struct acx_rx_statistics rx; + struct acx_dma_statistics dma; + struct acx_isr_statistics isr; + struct acx_wep_statistics wep; + struct acx_pwr_statistics pwr; + struct acx_aes_statistics aes; + struct acx_mic_statistics mic; + struct acx_event_statistics event; + struct acx_ps_statistics ps; + struct acx_rxpipe_statistics rxpipe; +} __packed; + struct acx_rate_class { __le32 enabled_rates; u8 short_retry_limit; @@ -603,8 +828,6 @@ struct wl1271_acx_keep_alive_config { #define HOST_IF_CFG_RX_FIFO_ENABLE BIT(0) #define HOST_IF_CFG_TX_EXTRA_BLKS_SWAP BIT(1) #define HOST_IF_CFG_TX_PAD_TO_SDIO_BLK BIT(3) -#define HOST_IF_CFG_RX_PAD_TO_SDIO_BLK BIT(4) -#define HOST_IF_CFG_ADD_RX_ALIGNMENT BIT(6) enum { WL1271_ACX_TRIG_TYPE_LEVEL = 0, @@ -723,7 +946,7 @@ struct wl1271_acx_ht_information { u8 padding[2]; } __packed; -#define RX_BA_MAX_SESSIONS 3 +#define RX_BA_MAX_SESSIONS 2 struct wl1271_acx_ba_initiator_policy { struct acx_header header; @@ -1020,7 +1243,6 @@ enum { ACX_CONFIG_HANGOVER = 0x0042, ACX_FEATURE_CFG = 0x0043, ACX_PROTECTION_CFG = 0x0044, - ACX_CHECKSUM_CONFIG = 0x0045, }; @@ -1059,7 +1281,7 @@ int wl1271_acx_set_preamble(struct wl1271 *wl, struct wl12xx_vif *wlvif, enum acx_preamble_type preamble); int wl1271_acx_cts_protect(struct wl1271 *wl, struct wl12xx_vif *wlvif, enum acx_ctsprotect_type ctsprotect); -int wl1271_acx_statistics(struct wl1271 *wl, void *stats); +int wl1271_acx_statistics(struct wl1271 *wl, struct acx_statistics *stats); int wl1271_acx_sta_rate_policies(struct wl1271 *wl, struct wl12xx_vif *wlvif); int wl1271_acx_ap_rate_policy(struct wl1271 *wl, struct conf_tx_rate_class *c, u8 idx); diff --git a/trunk/drivers/net/wireless/ti/wlcore/boot.c b/trunk/drivers/net/wireless/ti/wlcore/boot.c index 0fda500c01c9..9b98230f84ce 100644 --- a/trunk/drivers/net/wireless/ti/wlcore/boot.c +++ b/trunk/drivers/net/wireless/ti/wlcore/boot.c @@ -45,17 +45,10 @@ static void wl1271_boot_set_ecpu_ctrl(struct wl1271 *wl, u32 flag) wlcore_write_reg(wl, REG_ECPU_CONTROL, cpu_ctrl); } -static int wlcore_boot_parse_fw_ver(struct wl1271 *wl, - struct wl1271_static_data *static_data) +static int wlcore_parse_fw_ver(struct wl1271 *wl) { int ret; - strncpy(wl->chip.fw_ver_str, static_data->fw_version, - sizeof(wl->chip.fw_ver_str)); - - /* make sure the string is NULL-terminated */ - wl->chip.fw_ver_str[sizeof(wl->chip.fw_ver_str) - 1] = '\0'; - ret = sscanf(wl->chip.fw_ver_str + 4, "%u.%u.%u.%u.%u", &wl->chip.fw_ver[0], &wl->chip.fw_ver[1], &wl->chip.fw_ver[2], &wl->chip.fw_ver[3], @@ -64,43 +57,43 @@ static int wlcore_boot_parse_fw_ver(struct wl1271 *wl, if (ret != 5) { wl1271_warning("fw version incorrect value"); memset(wl->chip.fw_ver, 0, sizeof(wl->chip.fw_ver)); - ret = -EINVAL; - goto out; + return -EINVAL; } ret = wlcore_identify_fw(wl); if (ret < 0) - goto out; -out: - return ret; + return ret; + + return 0; } -static int wlcore_boot_static_data(struct wl1271 *wl) +static int wlcore_boot_fw_version(struct wl1271 *wl) { struct wl1271_static_data *static_data; - size_t len = sizeof(*static_data) + wl->static_data_priv_len; int ret; - static_data = kmalloc(len, GFP_KERNEL); + static_data = kmalloc(sizeof(*static_data), GFP_KERNEL | GFP_DMA); if (!static_data) { - ret = -ENOMEM; - goto out; + wl1271_error("Couldn't allocate memory for static data!"); + return -ENOMEM; } - wl1271_read(wl, wl->cmd_box_addr, static_data, len, false); + wl1271_read(wl, wl->cmd_box_addr, static_data, sizeof(*static_data), + false); - ret = wlcore_boot_parse_fw_ver(wl, static_data); - if (ret < 0) - goto out_free; + strncpy(wl->chip.fw_ver_str, static_data->fw_version, + sizeof(wl->chip.fw_ver_str)); + + kfree(static_data); + + /* make sure the string is NULL-terminated */ + wl->chip.fw_ver_str[sizeof(wl->chip.fw_ver_str) - 1] = '\0'; - ret = wlcore_handle_static_data(wl, static_data); + ret = wlcore_parse_fw_ver(wl); if (ret < 0) - goto out_free; + return ret; -out_free: - kfree(static_data); -out: - return ret; + return 0; } static int wl1271_boot_upload_firmware_chunk(struct wl1271 *wl, void *buf, @@ -211,10 +204,8 @@ int wlcore_boot_upload_nvs(struct wl1271 *wl) u32 dest_addr, val; u8 *nvs_ptr, *nvs_aligned; - if (wl->nvs == NULL) { - wl1271_error("NVS file is needed during boot"); + if (wl->nvs == NULL) return -ENODEV; - } if (wl->quirks & WLCORE_QUIRK_LEGACY_NVS) { struct wl1271_nvs_file *nvs = @@ -409,9 +400,9 @@ int wlcore_boot_run_firmware(struct wl1271 *wl) wl1271_debug(DEBUG_MAILBOX, "MBOX ptrs: 0x%x 0x%x", wl->mbox_ptr[0], wl->mbox_ptr[1]); - ret = wlcore_boot_static_data(wl); + ret = wlcore_boot_fw_version(wl); if (ret < 0) { - wl1271_error("error getting static data"); + wl1271_error("couldn't boot firmware"); return ret; } diff --git a/trunk/drivers/net/wireless/ti/wlcore/boot.h b/trunk/drivers/net/wireless/ti/wlcore/boot.h index a525225f990c..094981dd2227 100644 --- a/trunk/drivers/net/wireless/ti/wlcore/boot.h +++ b/trunk/drivers/net/wireless/ti/wlcore/boot.h @@ -40,7 +40,6 @@ struct wl1271_static_data { u8 fw_version[WL1271_FW_VERSION_MAX_LEN]; u32 hw_version; u8 tx_power_table[WL1271_NO_SUBBANDS][WL1271_NO_POWER_LEVELS]; - u8 priv[0]; }; /* number of times we try to read the INIT interrupt */ diff --git a/trunk/drivers/net/wireless/ti/wlcore/cmd.c b/trunk/drivers/net/wireless/ti/wlcore/cmd.c index 885364ca4344..5b128a971449 100644 --- a/trunk/drivers/net/wireless/ti/wlcore/cmd.c +++ b/trunk/drivers/net/wireless/ti/wlcore/cmd.c @@ -36,7 +36,6 @@ #include "cmd.h" #include "event.h" #include "tx.h" -#include "hw_ops.h" #define WL1271_CMD_FAST_POLL_COUNT 50 @@ -292,23 +291,6 @@ static int wl12xx_get_new_session_id(struct wl1271 *wl, return wlvif->session_counter; } -static u8 wlcore_get_native_channel_type(u8 nl_channel_type) -{ - switch (nl_channel_type) { - case NL80211_CHAN_NO_HT: - return WLCORE_CHAN_NO_HT; - case NL80211_CHAN_HT20: - return WLCORE_CHAN_HT20; - case NL80211_CHAN_HT40MINUS: - return WLCORE_CHAN_HT40MINUS; - case NL80211_CHAN_HT40PLUS: - return WLCORE_CHAN_HT40PLUS; - default: - WARN_ON(1); - return WLCORE_CHAN_NO_HT; - } -} - static int wl12xx_cmd_role_start_dev(struct wl1271 *wl, struct wl12xx_vif *wlvif) { @@ -425,7 +407,6 @@ int wl12xx_cmd_role_start_sta(struct wl1271 *wl, struct wl12xx_vif *wlvif) memcpy(cmd->sta.ssid, wlvif->ssid, wlvif->ssid_len); memcpy(cmd->sta.bssid, vif->bss_conf.bssid, ETH_ALEN); cmd->sta.local_rates = cpu_to_le32(wlvif->rate_set); - cmd->channel_type = wlcore_get_native_channel_type(wlvif->channel_type); if (wlvif->sta.hlid == WL12XX_INVALID_LINK_ID) { ret = wl12xx_allocate_link(wl, wlvif, &wlvif->sta.hlid); @@ -501,7 +482,6 @@ int wl12xx_cmd_role_start_ap(struct wl1271 *wl, struct wl12xx_vif *wlvif) struct wl12xx_cmd_role_start *cmd; struct ieee80211_vif *vif = wl12xx_wlvif_to_vif(wlvif); struct ieee80211_bss_conf *bss_conf = &vif->bss_conf; - u32 supported_rates; int ret; wl1271_debug(DEBUG_CMD, "cmd role start ap %d", wlvif->role_id); @@ -539,7 +519,6 @@ int wl12xx_cmd_role_start_ap(struct wl1271 *wl, struct wl12xx_vif *wlvif) /* FIXME: Change when adding DFS */ cmd->ap.reset_tsf = 1; /* By default reset AP TSF */ cmd->channel = wlvif->channel; - cmd->channel_type = wlcore_get_native_channel_type(wlvif->channel_type); if (!bss_conf->hidden_ssid) { /* take the SSID from the beacon for backward compatibility */ @@ -552,13 +531,7 @@ int wl12xx_cmd_role_start_ap(struct wl1271 *wl, struct wl12xx_vif *wlvif) memcpy(cmd->ap.ssid, bss_conf->ssid, bss_conf->ssid_len); } - supported_rates = CONF_TX_AP_ENABLED_RATES | CONF_TX_MCS_RATES | - wlcore_hw_ap_get_mimo_wide_rate_mask(wl, wlvif); - - wl1271_debug(DEBUG_CMD, "cmd role start ap with supported_rates 0x%08x", - supported_rates); - - cmd->ap.local_rates = cpu_to_le32(supported_rates); + cmd->ap.local_rates = cpu_to_le32(0xffffffff); switch (wlvif->band) { case IEEE80211_BAND_2GHZ: @@ -824,7 +797,6 @@ int wl1271_cmd_data_path(struct wl1271 *wl, bool enable) kfree(cmd); return ret; } -EXPORT_SYMBOL_GPL(wl1271_cmd_data_path); int wl1271_cmd_ps_mode(struct wl1271 *wl, struct wl12xx_vif *wlvif, u8 ps_mode, u16 auto_ps_timeout) @@ -1046,7 +1018,7 @@ struct sk_buff *wl1271_cmd_build_ap_probe_req(struct wl1271 *wl, int wl1271_cmd_build_arp_rsp(struct wl1271 *wl, struct wl12xx_vif *wlvif) { - int ret, extra = 0; + int ret, extra; u16 fc; struct ieee80211_vif *vif = wl12xx_wlvif_to_vif(wlvif); struct sk_buff *skb; @@ -1085,8 +1057,7 @@ int wl1271_cmd_build_arp_rsp(struct wl1271 *wl, struct wl12xx_vif *wlvif) /* encryption space */ switch (wlvif->encryption_type) { case KEY_TKIP: - if (wl->quirks & WLCORE_QUIRK_TKIP_HEADER_SPACE) - extra = WL1271_EXTRA_SPACE_TKIP; + extra = WL1271_EXTRA_SPACE_TKIP; break; case KEY_AES: extra = WL1271_EXTRA_SPACE_AES; @@ -1375,18 +1346,13 @@ int wl12xx_cmd_add_peer(struct wl1271 *wl, struct wl12xx_vif *wlvif, for (i = 0; i < NUM_ACCESS_CATEGORIES_COPY; i++) if (sta->wme && (sta->uapsd_queues & BIT(i))) - cmd->psd_type[NUM_ACCESS_CATEGORIES_COPY-1-i] = - WL1271_PSD_UPSD_TRIGGER; + cmd->psd_type[i] = WL1271_PSD_UPSD_TRIGGER; else - cmd->psd_type[NUM_ACCESS_CATEGORIES_COPY-1-i] = - WL1271_PSD_LEGACY; - + cmd->psd_type[i] = WL1271_PSD_LEGACY; sta_rates = sta->supp_rates[wlvif->band]; if (sta->ht_cap.ht_supported) - sta_rates |= - (sta->ht_cap.mcs.rx_mask[0] << HW_HT_RATES_OFFSET) | - (sta->ht_cap.mcs.rx_mask[1] << HW_MIMO_RATES_OFFSET); + sta_rates |= sta->ht_cap.mcs.rx_mask[0] << HW_HT_RATES_OFFSET; cmd->supported_rates = cpu_to_le32(wl1271_tx_enabled_rates_get(wl, sta_rates, @@ -1607,25 +1573,19 @@ static int wl12xx_cmd_croc(struct wl1271 *wl, u8 role_id) int wl12xx_roc(struct wl1271 *wl, struct wl12xx_vif *wlvif, u8 role_id) { int ret = 0; - bool is_first_roc; if (WARN_ON(test_bit(role_id, wl->roc_map))) return 0; - is_first_roc = (find_first_bit(wl->roc_map, WL12XX_MAX_ROLES) >= - WL12XX_MAX_ROLES); - ret = wl12xx_cmd_roc(wl, wlvif, role_id); if (ret < 0) goto out; - if (is_first_roc) { - ret = wl1271_cmd_wait_for_event(wl, - REMAIN_ON_CHANNEL_COMPLETE_EVENT_ID); - if (ret < 0) { - wl1271_error("cmd roc event completion error"); - goto out; - } + ret = wl1271_cmd_wait_for_event(wl, + REMAIN_ON_CHANNEL_COMPLETE_EVENT_ID); + if (ret < 0) { + wl1271_error("cmd roc event completion error"); + goto out; } __set_bit(role_id, wl->roc_map); diff --git a/trunk/drivers/net/wireless/ti/wlcore/cmd.h b/trunk/drivers/net/wireless/ti/wlcore/cmd.h index 85171f2bf68e..a46ae07cb77e 100644 --- a/trunk/drivers/net/wireless/ti/wlcore/cmd.h +++ b/trunk/drivers/net/wireless/ti/wlcore/cmd.h @@ -192,7 +192,7 @@ enum cmd_templ { #define WL1271_COMMAND_TIMEOUT 2000 #define WL1271_CMD_TEMPL_DFLT_SIZE 252 #define WL1271_CMD_TEMPL_MAX_SIZE 512 -#define WL1271_EVENT_TIMEOUT 1000 +#define WL1271_EVENT_TIMEOUT 750 struct wl1271_cmd_header { __le16 id; @@ -266,22 +266,13 @@ enum wlcore_band { WLCORE_BAND_MAX_RADIO = 0x7F, }; -enum wlcore_channel_type { - WLCORE_CHAN_NO_HT, - WLCORE_CHAN_HT20, - WLCORE_CHAN_HT40MINUS, - WLCORE_CHAN_HT40PLUS -}; - struct wl12xx_cmd_role_start { struct wl1271_cmd_header header; u8 role_id; u8 band; u8 channel; - - /* enum wlcore_channel_type */ - u8 channel_type; + u8 padding; union { struct { diff --git a/trunk/drivers/net/wireless/ti/wlcore/conf.h b/trunk/drivers/net/wireless/ti/wlcore/conf.h index 03c635872335..fef0db4213bc 100644 --- a/trunk/drivers/net/wireless/ti/wlcore/conf.h +++ b/trunk/drivers/net/wireless/ti/wlcore/conf.h @@ -45,15 +45,7 @@ enum { CONF_HW_BIT_RATE_MCS_4 = BIT(17), CONF_HW_BIT_RATE_MCS_5 = BIT(18), CONF_HW_BIT_RATE_MCS_6 = BIT(19), - CONF_HW_BIT_RATE_MCS_7 = BIT(20), - CONF_HW_BIT_RATE_MCS_8 = BIT(21), - CONF_HW_BIT_RATE_MCS_9 = BIT(22), - CONF_HW_BIT_RATE_MCS_10 = BIT(23), - CONF_HW_BIT_RATE_MCS_11 = BIT(24), - CONF_HW_BIT_RATE_MCS_12 = BIT(25), - CONF_HW_BIT_RATE_MCS_13 = BIT(26), - CONF_HW_BIT_RATE_MCS_14 = BIT(27), - CONF_HW_BIT_RATE_MCS_15 = BIT(28), + CONF_HW_BIT_RATE_MCS_7 = BIT(20) }; enum { @@ -318,7 +310,7 @@ enum { struct conf_sg_settings { u32 params[CONF_SG_PARAMS_MAX]; u8 state; -} __packed; +}; enum conf_rx_queue_type { CONF_RX_QUEUE_TYPE_LOW_PRIORITY, /* All except the high priority */ @@ -402,7 +394,7 @@ struct conf_rx_settings { * Range: RX_QUEUE_TYPE_RX_LOW_PRIORITY, RX_QUEUE_TYPE_RX_HIGH_PRIORITY, */ u8 queue_type; -} __packed; +}; #define CONF_TX_MAX_RATE_CLASSES 10 @@ -443,12 +435,6 @@ struct conf_rx_settings { CONF_HW_BIT_RATE_MCS_5 | CONF_HW_BIT_RATE_MCS_6 | \ CONF_HW_BIT_RATE_MCS_7) -#define CONF_TX_MIMO_RATES (CONF_HW_BIT_RATE_MCS_8 | \ - CONF_HW_BIT_RATE_MCS_9 | CONF_HW_BIT_RATE_MCS_10 | \ - CONF_HW_BIT_RATE_MCS_11 | CONF_HW_BIT_RATE_MCS_12 | \ - CONF_HW_BIT_RATE_MCS_13 | CONF_HW_BIT_RATE_MCS_14 | \ - CONF_HW_BIT_RATE_MCS_15) - /* * Default rates for management traffic when operating in AP mode. This * should be configured according to the basic rate set of the AP @@ -501,7 +487,7 @@ struct conf_tx_rate_class { * the policy (0 - long preamble, 1 - short preamble. */ u8 aflags; -} __packed; +}; #define CONF_TX_MAX_AC_COUNT 4 @@ -518,7 +504,7 @@ enum conf_tx_ac { CONF_TX_AC_VI = 2, /* video */ CONF_TX_AC_VO = 3, /* voice */ CONF_TX_AC_CTS2SELF = 4, /* fictitious AC, follows AC_VO */ - CONF_TX_AC_ANY_TID = 0xff + CONF_TX_AC_ANY_TID = 0x1f }; struct conf_tx_ac_category { @@ -558,7 +544,7 @@ struct conf_tx_ac_category { * Range: u16 */ u16 tx_op_limit; -} __packed; +}; #define CONF_TX_MAX_TID_COUNT 8 @@ -592,7 +578,7 @@ struct conf_tx_tid { u8 ps_scheme; u8 ack_policy; u32 apsd_conf[2]; -} __packed; +}; struct conf_tx_settings { /* @@ -678,7 +664,7 @@ struct conf_tx_settings { /* Time in ms for Tx watchdog timer to expire */ u32 tx_watchdog_timeout; -} __packed; +}; enum { CONF_WAKE_UP_EVENT_BEACON = 0x01, /* Wake on every Beacon*/ @@ -725,7 +711,7 @@ struct conf_bcn_filt_rule { * Version for the vendor specifie IE (221) */ u8 version[CONF_BCN_IE_VER_LEN]; -} __packed; +}; #define CONF_MAX_RSSI_SNR_TRIGGERS 8 @@ -776,7 +762,7 @@ struct conf_sig_weights { * Range: u8 */ u8 snr_pkt_avg_weight; -} __packed; +}; enum conf_bcn_filt_mode { CONF_BCN_FILT_MODE_DISABLED = 0, @@ -824,7 +810,7 @@ struct conf_conn_settings { * * Range: CONF_BCN_FILT_MODE_* */ - u8 bcn_filt_mode; + enum conf_bcn_filt_mode bcn_filt_mode; /* * Configure Beacon filter pass-thru rules. @@ -951,7 +937,7 @@ struct conf_conn_settings { * Range: u16 */ u8 max_listen_interval; -} __packed; +}; enum { CONF_REF_CLK_19_2_E, @@ -979,11 +965,6 @@ struct conf_itrim_settings { /* moderation timeout in microsecs from the last TX */ u32 timeout; -} __packed; - -enum conf_fast_wakeup { - CONF_FAST_WAKEUP_ENABLE, - CONF_FAST_WAKEUP_DISABLE, }; struct conf_pm_config_settings { @@ -997,10 +978,10 @@ struct conf_pm_config_settings { /* * Host fast wakeup support * - * Range: enum conf_fast_wakeup + * Range: true, false */ - u8 host_fast_wakeup_support; -} __packed; + bool host_fast_wakeup_support; +}; struct conf_roam_trigger_settings { /* @@ -1037,7 +1018,7 @@ struct conf_roam_trigger_settings { * Range: 0 - 255 */ u8 avg_weight_snr_data; -} __packed; +}; struct conf_scan_settings { /* @@ -1083,7 +1064,7 @@ struct conf_scan_settings { * Range: u32 Microsecs */ u32 split_scan_timeout; -} __packed; +}; struct conf_sched_scan_settings { /* @@ -1121,7 +1102,7 @@ struct conf_sched_scan_settings { /* SNR threshold to be used for filtering */ s8 snr_threshold; -} __packed; +}; struct conf_ht_setting { u8 rx_ba_win_size; @@ -1130,7 +1111,7 @@ struct conf_ht_setting { /* bitmap of enabled TIDs for TX BA sessions */ u8 tx_ba_tid_bitmap; -} __packed; +}; struct conf_memory_settings { /* Number of stations supported in IBSS mode */ @@ -1170,7 +1151,7 @@ struct conf_memory_settings { * Range: 0-120 */ u8 tx_min; -} __packed; +}; struct conf_fm_coex { u8 enable; @@ -1183,7 +1164,7 @@ struct conf_fm_coex { u16 ldo_stabilization_time; u8 fm_disturbed_band_margin; u8 swallow_clk_diff; -} __packed; +}; struct conf_rx_streaming_settings { /* @@ -1212,7 +1193,7 @@ struct conf_rx_streaming_settings { * enable rx streaming also when there is no coex activity */ u8 always; -} __packed; +}; struct conf_fwlog { /* Continuous or on-demand */ @@ -1236,7 +1217,7 @@ struct conf_fwlog { /* Regulates the frequency of log messages */ u8 threshold; -} __packed; +}; #define ACX_RATE_MGMT_NUM_OF_RATES 13 struct conf_rate_policy_settings { @@ -1255,7 +1236,7 @@ struct conf_rate_policy_settings { u8 rate_check_up; u8 rate_check_down; u8 rate_retry_policy[ACX_RATE_MGMT_NUM_OF_RATES]; -} __packed; +}; struct conf_hangover_settings { u32 recover_time; @@ -1269,23 +1250,7 @@ struct conf_hangover_settings { u8 quiet_time; u8 increase_time; u8 window_size; -} __packed; - -/* - * The conf version consists of 4 bytes. The two MSB are the wlcore - * version, the two LSB are the lower driver's private conf - * version. - */ -#define WLCORE_CONF_VERSION (0x0001 << 16) -#define WLCORE_CONF_MASK 0xffff0000 -#define WLCORE_CONF_SIZE (sizeof(struct wlcore_conf_header) + \ - sizeof(struct wlcore_conf)) - -struct wlcore_conf_header { - __le32 magic; - __le32 version; - __le32 checksum; -} __packed; +}; struct wlcore_conf { struct conf_sg_settings sg; @@ -1304,12 +1269,6 @@ struct wlcore_conf { struct conf_fwlog fwlog; struct conf_rate_policy_settings rate; struct conf_hangover_settings hangover; -} __packed; - -struct wlcore_conf_file { - struct wlcore_conf_header header; - struct wlcore_conf core; - u8 priv[0]; -} __packed; +}; #endif diff --git a/trunk/drivers/net/wireless/ti/wlcore/debugfs.c b/trunk/drivers/net/wireless/ti/wlcore/debugfs.c index 689a847005c9..d5aea1ff5ad1 100644 --- a/trunk/drivers/net/wireless/ti/wlcore/debugfs.c +++ b/trunk/drivers/net/wireless/ti/wlcore/debugfs.c @@ -25,7 +25,6 @@ #include #include -#include #include "wlcore.h" #include "debug.h" @@ -33,14 +32,14 @@ #include "ps.h" #include "io.h" #include "tx.h" -#include "hw_ops.h" /* ms */ #define WL1271_DEBUGFS_STATS_LIFETIME 1000 /* debugfs macros idea from mac80211 */ -int wl1271_format_buffer(char __user *userbuf, size_t count, - loff_t *ppos, char *fmt, ...) +#define DEBUGFS_FORMAT_BUFFER_SIZE 100 +static int wl1271_format_buffer(char __user *userbuf, size_t count, + loff_t *ppos, char *fmt, ...) { va_list args; char buf[DEBUGFS_FORMAT_BUFFER_SIZE]; @@ -52,9 +51,59 @@ int wl1271_format_buffer(char __user *userbuf, size_t count, return simple_read_from_buffer(userbuf, count, ppos, buf, res); } -EXPORT_SYMBOL_GPL(wl1271_format_buffer); -void wl1271_debugfs_update_stats(struct wl1271 *wl) +#define DEBUGFS_READONLY_FILE(name, fmt, value...) \ +static ssize_t name## _read(struct file *file, char __user *userbuf, \ + size_t count, loff_t *ppos) \ +{ \ + struct wl1271 *wl = file->private_data; \ + return wl1271_format_buffer(userbuf, count, ppos, \ + fmt "\n", ##value); \ +} \ + \ +static const struct file_operations name## _ops = { \ + .read = name## _read, \ + .open = simple_open, \ + .llseek = generic_file_llseek, \ +}; + +#define DEBUGFS_ADD(name, parent) \ + entry = debugfs_create_file(#name, 0400, parent, \ + wl, &name## _ops); \ + if (!entry || IS_ERR(entry)) \ + goto err; \ + +#define DEBUGFS_ADD_PREFIX(prefix, name, parent) \ + do { \ + entry = debugfs_create_file(#name, 0400, parent, \ + wl, &prefix## _## name## _ops); \ + if (!entry || IS_ERR(entry)) \ + goto err; \ + } while (0); + +#define DEBUGFS_FWSTATS_FILE(sub, name, fmt) \ +static ssize_t sub## _ ##name## _read(struct file *file, \ + char __user *userbuf, \ + size_t count, loff_t *ppos) \ +{ \ + struct wl1271 *wl = file->private_data; \ + \ + wl1271_debugfs_update_stats(wl); \ + \ + return wl1271_format_buffer(userbuf, count, ppos, fmt "\n", \ + wl->stats.fw_stats->sub.name); \ +} \ + \ +static const struct file_operations sub## _ ##name## _ops = { \ + .read = sub## _ ##name## _read, \ + .open = simple_open, \ + .llseek = generic_file_llseek, \ +}; + +#define DEBUGFS_FWSTATS_ADD(sub, name) \ + DEBUGFS_ADD(sub## _ ##name, stats) + +static void wl1271_debugfs_update_stats(struct wl1271 *wl) { int ret; @@ -76,7 +125,97 @@ void wl1271_debugfs_update_stats(struct wl1271 *wl) out: mutex_unlock(&wl->mutex); } -EXPORT_SYMBOL_GPL(wl1271_debugfs_update_stats); + +DEBUGFS_FWSTATS_FILE(tx, internal_desc_overflow, "%u"); + +DEBUGFS_FWSTATS_FILE(rx, out_of_mem, "%u"); +DEBUGFS_FWSTATS_FILE(rx, hdr_overflow, "%u"); +DEBUGFS_FWSTATS_FILE(rx, hw_stuck, "%u"); +DEBUGFS_FWSTATS_FILE(rx, dropped, "%u"); +DEBUGFS_FWSTATS_FILE(rx, fcs_err, "%u"); +DEBUGFS_FWSTATS_FILE(rx, xfr_hint_trig, "%u"); +DEBUGFS_FWSTATS_FILE(rx, path_reset, "%u"); +DEBUGFS_FWSTATS_FILE(rx, reset_counter, "%u"); + +DEBUGFS_FWSTATS_FILE(dma, rx_requested, "%u"); +DEBUGFS_FWSTATS_FILE(dma, rx_errors, "%u"); +DEBUGFS_FWSTATS_FILE(dma, tx_requested, "%u"); +DEBUGFS_FWSTATS_FILE(dma, tx_errors, "%u"); + +DEBUGFS_FWSTATS_FILE(isr, cmd_cmplt, "%u"); +DEBUGFS_FWSTATS_FILE(isr, fiqs, "%u"); +DEBUGFS_FWSTATS_FILE(isr, rx_headers, "%u"); +DEBUGFS_FWSTATS_FILE(isr, rx_mem_overflow, "%u"); +DEBUGFS_FWSTATS_FILE(isr, rx_rdys, "%u"); +DEBUGFS_FWSTATS_FILE(isr, irqs, "%u"); +DEBUGFS_FWSTATS_FILE(isr, tx_procs, "%u"); +DEBUGFS_FWSTATS_FILE(isr, decrypt_done, "%u"); +DEBUGFS_FWSTATS_FILE(isr, dma0_done, "%u"); +DEBUGFS_FWSTATS_FILE(isr, dma1_done, "%u"); +DEBUGFS_FWSTATS_FILE(isr, tx_exch_complete, "%u"); +DEBUGFS_FWSTATS_FILE(isr, commands, "%u"); +DEBUGFS_FWSTATS_FILE(isr, rx_procs, "%u"); +DEBUGFS_FWSTATS_FILE(isr, hw_pm_mode_changes, "%u"); +DEBUGFS_FWSTATS_FILE(isr, host_acknowledges, "%u"); +DEBUGFS_FWSTATS_FILE(isr, pci_pm, "%u"); +DEBUGFS_FWSTATS_FILE(isr, wakeups, "%u"); +DEBUGFS_FWSTATS_FILE(isr, low_rssi, "%u"); + +DEBUGFS_FWSTATS_FILE(wep, addr_key_count, "%u"); +DEBUGFS_FWSTATS_FILE(wep, default_key_count, "%u"); +/* skipping wep.reserved */ +DEBUGFS_FWSTATS_FILE(wep, key_not_found, "%u"); +DEBUGFS_FWSTATS_FILE(wep, decrypt_fail, "%u"); +DEBUGFS_FWSTATS_FILE(wep, packets, "%u"); +DEBUGFS_FWSTATS_FILE(wep, interrupt, "%u"); + +DEBUGFS_FWSTATS_FILE(pwr, ps_enter, "%u"); +DEBUGFS_FWSTATS_FILE(pwr, elp_enter, "%u"); +DEBUGFS_FWSTATS_FILE(pwr, missing_bcns, "%u"); +DEBUGFS_FWSTATS_FILE(pwr, wake_on_host, "%u"); +DEBUGFS_FWSTATS_FILE(pwr, wake_on_timer_exp, "%u"); +DEBUGFS_FWSTATS_FILE(pwr, tx_with_ps, "%u"); +DEBUGFS_FWSTATS_FILE(pwr, tx_without_ps, "%u"); +DEBUGFS_FWSTATS_FILE(pwr, rcvd_beacons, "%u"); +DEBUGFS_FWSTATS_FILE(pwr, power_save_off, "%u"); +DEBUGFS_FWSTATS_FILE(pwr, enable_ps, "%u"); +DEBUGFS_FWSTATS_FILE(pwr, disable_ps, "%u"); +DEBUGFS_FWSTATS_FILE(pwr, fix_tsf_ps, "%u"); +/* skipping cont_miss_bcns_spread for now */ +DEBUGFS_FWSTATS_FILE(pwr, rcvd_awake_beacons, "%u"); + +DEBUGFS_FWSTATS_FILE(mic, rx_pkts, "%u"); +DEBUGFS_FWSTATS_FILE(mic, calc_failure, "%u"); + +DEBUGFS_FWSTATS_FILE(aes, encrypt_fail, "%u"); +DEBUGFS_FWSTATS_FILE(aes, decrypt_fail, "%u"); +DEBUGFS_FWSTATS_FILE(aes, encrypt_packets, "%u"); +DEBUGFS_FWSTATS_FILE(aes, decrypt_packets, "%u"); +DEBUGFS_FWSTATS_FILE(aes, encrypt_interrupt, "%u"); +DEBUGFS_FWSTATS_FILE(aes, decrypt_interrupt, "%u"); + +DEBUGFS_FWSTATS_FILE(event, heart_beat, "%u"); +DEBUGFS_FWSTATS_FILE(event, calibration, "%u"); +DEBUGFS_FWSTATS_FILE(event, rx_mismatch, "%u"); +DEBUGFS_FWSTATS_FILE(event, rx_mem_empty, "%u"); +DEBUGFS_FWSTATS_FILE(event, rx_pool, "%u"); +DEBUGFS_FWSTATS_FILE(event, oom_late, "%u"); +DEBUGFS_FWSTATS_FILE(event, phy_transmit_error, "%u"); +DEBUGFS_FWSTATS_FILE(event, tx_stuck, "%u"); + +DEBUGFS_FWSTATS_FILE(ps, pspoll_timeouts, "%u"); +DEBUGFS_FWSTATS_FILE(ps, upsd_timeouts, "%u"); +DEBUGFS_FWSTATS_FILE(ps, upsd_max_sptime, "%u"); +DEBUGFS_FWSTATS_FILE(ps, upsd_max_apturn, "%u"); +DEBUGFS_FWSTATS_FILE(ps, pspoll_max_apturn, "%u"); +DEBUGFS_FWSTATS_FILE(ps, pspoll_utilization, "%u"); +DEBUGFS_FWSTATS_FILE(ps, upsd_utilization, "%u"); + +DEBUGFS_FWSTATS_FILE(rxpipe, rx_prep_beacon_drop, "%u"); +DEBUGFS_FWSTATS_FILE(rxpipe, descr_host_int_trig_rx_data, "%u"); +DEBUGFS_FWSTATS_FILE(rxpipe, beacon_buffer_thres_host_int_trig_rx_data, "%u"); +DEBUGFS_FWSTATS_FILE(rxpipe, missed_beacon_host_int_trig_rx_data, "%u"); +DEBUGFS_FWSTATS_FILE(rxpipe, tx_xfr_host_int_trig_rx_data, "%u"); DEBUGFS_READONLY_FILE(retry_count, "%u", wl->stats.retry_count); DEBUGFS_READONLY_FILE(excessive_retries, "%u", @@ -102,89 +241,6 @@ static const struct file_operations tx_queue_len_ops = { .llseek = default_llseek, }; -static void chip_op_handler(struct wl1271 *wl, unsigned long value, - void *arg) -{ - int ret; - int (*chip_op) (struct wl1271 *wl); - - if (!arg) { - wl1271_warning("debugfs chip_op_handler with no callback"); - return; - } - - ret = wl1271_ps_elp_wakeup(wl); - if (ret < 0) - return; - - chip_op = arg; - chip_op(wl); - - wl1271_ps_elp_sleep(wl); -} - - -static inline void no_write_handler(struct wl1271 *wl, - unsigned long value, - unsigned long param) -{ -} - -#define WL12XX_CONF_DEBUGFS(param, conf_sub_struct, \ - min_val, max_val, write_handler_locked, \ - write_handler_arg) \ - static ssize_t param##_read(struct file *file, \ - char __user *user_buf, \ - size_t count, loff_t *ppos) \ - { \ - struct wl1271 *wl = file->private_data; \ - return wl1271_format_buffer(user_buf, count, \ - ppos, "%d\n", \ - wl->conf.conf_sub_struct.param); \ - } \ - \ - static ssize_t param##_write(struct file *file, \ - const char __user *user_buf, \ - size_t count, loff_t *ppos) \ - { \ - struct wl1271 *wl = file->private_data; \ - unsigned long value; \ - int ret; \ - \ - ret = kstrtoul_from_user(user_buf, count, 10, &value); \ - if (ret < 0) { \ - wl1271_warning("illegal value for " #param); \ - return -EINVAL; \ - } \ - \ - if (value < min_val || value > max_val) { \ - wl1271_warning(#param " is not in valid range"); \ - return -ERANGE; \ - } \ - \ - mutex_lock(&wl->mutex); \ - wl->conf.conf_sub_struct.param = value; \ - \ - write_handler_locked(wl, value, write_handler_arg); \ - \ - mutex_unlock(&wl->mutex); \ - return count; \ - } \ - \ - static const struct file_operations param##_ops = { \ - .read = param##_read, \ - .write = param##_write, \ - .open = simple_open, \ - .llseek = default_llseek, \ - }; - -WL12XX_CONF_DEBUGFS(irq_pkt_threshold, rx, 0, 65535, - chip_op_handler, wl1271_acx_init_rx_interrupt) -WL12XX_CONF_DEBUGFS(irq_blk_threshold, rx, 0, 65535, - chip_op_handler, wl1271_acx_init_rx_interrupt) -WL12XX_CONF_DEBUGFS(irq_timeout, rx, 0, 100, - chip_op_handler, wl1271_acx_init_rx_interrupt) - static ssize_t gpio_power_read(struct file *file, char __user *user_buf, size_t count, loff_t *ppos) { @@ -479,7 +535,8 @@ static ssize_t driver_state_read(struct file *file, char __user *user_buf, DRIVER_STATE_PRINT_LHEX(ap_ps_map); DRIVER_STATE_PRINT_HEX(quirks); DRIVER_STATE_PRINT_HEX(irq); - /* TODO: ref_clock and tcxo_clock were moved to wl12xx priv */ + DRIVER_STATE_PRINT_HEX(ref_clock); + DRIVER_STATE_PRINT_HEX(tcxo_clock); DRIVER_STATE_PRINT_HEX(hw_pg_ver); DRIVER_STATE_PRINT_HEX(platform_quirks); DRIVER_STATE_PRINT_HEX(chip.id); @@ -590,6 +647,7 @@ static ssize_t vifs_state_read(struct file *file, char __user *user_buf, VIF_STATE_PRINT_INT(last_rssi_event); VIF_STATE_PRINT_INT(ba_support); VIF_STATE_PRINT_INT(ba_allowed); + VIF_STATE_PRINT_INT(is_gem); VIF_STATE_PRINT_LLHEX(tx_security_seq); VIF_STATE_PRINT_INT(tx_security_last_seq_lsb); } @@ -944,30 +1002,108 @@ static const struct file_operations beacon_filtering_ops = { .llseek = default_llseek, }; -static ssize_t fw_stats_raw_read(struct file *file, - char __user *userbuf, - size_t count, loff_t *ppos) -{ - struct wl1271 *wl = file->private_data; - - wl1271_debugfs_update_stats(wl); - - return simple_read_from_buffer(userbuf, count, ppos, - wl->stats.fw_stats, - wl->stats.fw_stats_len); -} - -static const struct file_operations fw_stats_raw_ops = { - .read = fw_stats_raw_read, - .open = simple_open, - .llseek = default_llseek, -}; - static int wl1271_debugfs_add_files(struct wl1271 *wl, - struct dentry *rootdir) + struct dentry *rootdir) { int ret = 0; - struct dentry *entry, *streaming; + struct dentry *entry, *stats, *streaming; + + stats = debugfs_create_dir("fw-statistics", rootdir); + if (!stats || IS_ERR(stats)) { + entry = stats; + goto err; + } + + DEBUGFS_FWSTATS_ADD(tx, internal_desc_overflow); + + DEBUGFS_FWSTATS_ADD(rx, out_of_mem); + DEBUGFS_FWSTATS_ADD(rx, hdr_overflow); + DEBUGFS_FWSTATS_ADD(rx, hw_stuck); + DEBUGFS_FWSTATS_ADD(rx, dropped); + DEBUGFS_FWSTATS_ADD(rx, fcs_err); + DEBUGFS_FWSTATS_ADD(rx, xfr_hint_trig); + DEBUGFS_FWSTATS_ADD(rx, path_reset); + DEBUGFS_FWSTATS_ADD(rx, reset_counter); + + DEBUGFS_FWSTATS_ADD(dma, rx_requested); + DEBUGFS_FWSTATS_ADD(dma, rx_errors); + DEBUGFS_FWSTATS_ADD(dma, tx_requested); + DEBUGFS_FWSTATS_ADD(dma, tx_errors); + + DEBUGFS_FWSTATS_ADD(isr, cmd_cmplt); + DEBUGFS_FWSTATS_ADD(isr, fiqs); + DEBUGFS_FWSTATS_ADD(isr, rx_headers); + DEBUGFS_FWSTATS_ADD(isr, rx_mem_overflow); + DEBUGFS_FWSTATS_ADD(isr, rx_rdys); + DEBUGFS_FWSTATS_ADD(isr, irqs); + DEBUGFS_FWSTATS_ADD(isr, tx_procs); + DEBUGFS_FWSTATS_ADD(isr, decrypt_done); + DEBUGFS_FWSTATS_ADD(isr, dma0_done); + DEBUGFS_FWSTATS_ADD(isr, dma1_done); + DEBUGFS_FWSTATS_ADD(isr, tx_exch_complete); + DEBUGFS_FWSTATS_ADD(isr, commands); + DEBUGFS_FWSTATS_ADD(isr, rx_procs); + DEBUGFS_FWSTATS_ADD(isr, hw_pm_mode_changes); + DEBUGFS_FWSTATS_ADD(isr, host_acknowledges); + DEBUGFS_FWSTATS_ADD(isr, pci_pm); + DEBUGFS_FWSTATS_ADD(isr, wakeups); + DEBUGFS_FWSTATS_ADD(isr, low_rssi); + + DEBUGFS_FWSTATS_ADD(wep, addr_key_count); + DEBUGFS_FWSTATS_ADD(wep, default_key_count); + /* skipping wep.reserved */ + DEBUGFS_FWSTATS_ADD(wep, key_not_found); + DEBUGFS_FWSTATS_ADD(wep, decrypt_fail); + DEBUGFS_FWSTATS_ADD(wep, packets); + DEBUGFS_FWSTATS_ADD(wep, interrupt); + + DEBUGFS_FWSTATS_ADD(pwr, ps_enter); + DEBUGFS_FWSTATS_ADD(pwr, elp_enter); + DEBUGFS_FWSTATS_ADD(pwr, missing_bcns); + DEBUGFS_FWSTATS_ADD(pwr, wake_on_host); + DEBUGFS_FWSTATS_ADD(pwr, wake_on_timer_exp); + DEBUGFS_FWSTATS_ADD(pwr, tx_with_ps); + DEBUGFS_FWSTATS_ADD(pwr, tx_without_ps); + DEBUGFS_FWSTATS_ADD(pwr, rcvd_beacons); + DEBUGFS_FWSTATS_ADD(pwr, power_save_off); + DEBUGFS_FWSTATS_ADD(pwr, enable_ps); + DEBUGFS_FWSTATS_ADD(pwr, disable_ps); + DEBUGFS_FWSTATS_ADD(pwr, fix_tsf_ps); + /* skipping cont_miss_bcns_spread for now */ + DEBUGFS_FWSTATS_ADD(pwr, rcvd_awake_beacons); + + DEBUGFS_FWSTATS_ADD(mic, rx_pkts); + DEBUGFS_FWSTATS_ADD(mic, calc_failure); + + DEBUGFS_FWSTATS_ADD(aes, encrypt_fail); + DEBUGFS_FWSTATS_ADD(aes, decrypt_fail); + DEBUGFS_FWSTATS_ADD(aes, encrypt_packets); + DEBUGFS_FWSTATS_ADD(aes, decrypt_packets); + DEBUGFS_FWSTATS_ADD(aes, encrypt_interrupt); + DEBUGFS_FWSTATS_ADD(aes, decrypt_interrupt); + + DEBUGFS_FWSTATS_ADD(event, heart_beat); + DEBUGFS_FWSTATS_ADD(event, calibration); + DEBUGFS_FWSTATS_ADD(event, rx_mismatch); + DEBUGFS_FWSTATS_ADD(event, rx_mem_empty); + DEBUGFS_FWSTATS_ADD(event, rx_pool); + DEBUGFS_FWSTATS_ADD(event, oom_late); + DEBUGFS_FWSTATS_ADD(event, phy_transmit_error); + DEBUGFS_FWSTATS_ADD(event, tx_stuck); + + DEBUGFS_FWSTATS_ADD(ps, pspoll_timeouts); + DEBUGFS_FWSTATS_ADD(ps, upsd_timeouts); + DEBUGFS_FWSTATS_ADD(ps, upsd_max_sptime); + DEBUGFS_FWSTATS_ADD(ps, upsd_max_apturn); + DEBUGFS_FWSTATS_ADD(ps, pspoll_max_apturn); + DEBUGFS_FWSTATS_ADD(ps, pspoll_utilization); + DEBUGFS_FWSTATS_ADD(ps, upsd_utilization); + + DEBUGFS_FWSTATS_ADD(rxpipe, rx_prep_beacon_drop); + DEBUGFS_FWSTATS_ADD(rxpipe, descr_host_int_trig_rx_data); + DEBUGFS_FWSTATS_ADD(rxpipe, beacon_buffer_thres_host_int_trig_rx_data); + DEBUGFS_FWSTATS_ADD(rxpipe, missed_beacon_host_int_trig_rx_data); + DEBUGFS_FWSTATS_ADD(rxpipe, tx_xfr_host_int_trig_rx_data); DEBUGFS_ADD(tx_queue_len, rootdir); DEBUGFS_ADD(retry_count, rootdir); @@ -984,10 +1120,6 @@ static int wl1271_debugfs_add_files(struct wl1271 *wl, DEBUGFS_ADD(dynamic_ps_timeout, rootdir); DEBUGFS_ADD(forced_ps, rootdir); DEBUGFS_ADD(split_scan_timeout, rootdir); - DEBUGFS_ADD(irq_pkt_threshold, rootdir); - DEBUGFS_ADD(irq_blk_threshold, rootdir); - DEBUGFS_ADD(irq_timeout, rootdir); - DEBUGFS_ADD(fw_stats_raw, rootdir); streaming = debugfs_create_dir("rx_streaming", rootdir); if (!streaming || IS_ERR(streaming)) @@ -1013,7 +1145,7 @@ void wl1271_debugfs_reset(struct wl1271 *wl) if (!wl->stats.fw_stats) return; - memset(wl->stats.fw_stats, 0, wl->stats.fw_stats_len); + memset(wl->stats.fw_stats, 0, sizeof(*wl->stats.fw_stats)); wl->stats.retry_count = 0; wl->stats.excessive_retries = 0; } @@ -1028,34 +1160,34 @@ int wl1271_debugfs_init(struct wl1271 *wl) if (IS_ERR(rootdir)) { ret = PTR_ERR(rootdir); - goto out; + goto err; } - wl->stats.fw_stats = kzalloc(wl->stats.fw_stats_len, GFP_KERNEL); + wl->stats.fw_stats = kzalloc(sizeof(*wl->stats.fw_stats), + GFP_KERNEL); + if (!wl->stats.fw_stats) { ret = -ENOMEM; - goto out_remove; + goto err_fw; } wl->stats.fw_stats_update = jiffies; ret = wl1271_debugfs_add_files(wl, rootdir); - if (ret < 0) - goto out_exit; - ret = wlcore_debugfs_init(wl, rootdir); if (ret < 0) - goto out_exit; + goto err_file; - goto out; + return 0; -out_exit: - wl1271_debugfs_exit(wl); +err_file: + kfree(wl->stats.fw_stats); + wl->stats.fw_stats = NULL; -out_remove: +err_fw: debugfs_remove_recursive(rootdir); -out: +err: return ret; } diff --git a/trunk/drivers/net/wireless/ti/wlcore/debugfs.h b/trunk/drivers/net/wireless/ti/wlcore/debugfs.h index f7381dd69009..a8d3aef011ff 100644 --- a/trunk/drivers/net/wireless/ti/wlcore/debugfs.h +++ b/trunk/drivers/net/wireless/ti/wlcore/debugfs.h @@ -26,95 +26,8 @@ #include "wlcore.h" -int wl1271_format_buffer(char __user *userbuf, size_t count, - loff_t *ppos, char *fmt, ...); - int wl1271_debugfs_init(struct wl1271 *wl); void wl1271_debugfs_exit(struct wl1271 *wl); void wl1271_debugfs_reset(struct wl1271 *wl); -void wl1271_debugfs_update_stats(struct wl1271 *wl); - -#define DEBUGFS_FORMAT_BUFFER_SIZE 256 - -#define DEBUGFS_READONLY_FILE(name, fmt, value...) \ -static ssize_t name## _read(struct file *file, char __user *userbuf, \ - size_t count, loff_t *ppos) \ -{ \ - struct wl1271 *wl = file->private_data; \ - return wl1271_format_buffer(userbuf, count, ppos, \ - fmt "\n", ##value); \ -} \ - \ -static const struct file_operations name## _ops = { \ - .read = name## _read, \ - .open = simple_open, \ - .llseek = generic_file_llseek, \ -}; - -#define DEBUGFS_ADD(name, parent) \ - do { \ - entry = debugfs_create_file(#name, 0400, parent, \ - wl, &name## _ops); \ - if (!entry || IS_ERR(entry)) \ - goto err; \ - } while (0); - - -#define DEBUGFS_ADD_PREFIX(prefix, name, parent) \ - do { \ - entry = debugfs_create_file(#name, 0400, parent, \ - wl, &prefix## _## name## _ops); \ - if (!entry || IS_ERR(entry)) \ - goto err; \ - } while (0); - -#define DEBUGFS_FWSTATS_FILE(sub, name, fmt, struct_type) \ -static ssize_t sub## _ ##name## _read(struct file *file, \ - char __user *userbuf, \ - size_t count, loff_t *ppos) \ -{ \ - struct wl1271 *wl = file->private_data; \ - struct struct_type *stats = wl->stats.fw_stats; \ - \ - wl1271_debugfs_update_stats(wl); \ - \ - return wl1271_format_buffer(userbuf, count, ppos, fmt "\n", \ - stats->sub.name); \ -} \ - \ -static const struct file_operations sub## _ ##name## _ops = { \ - .read = sub## _ ##name## _read, \ - .open = simple_open, \ - .llseek = generic_file_llseek, \ -}; - -#define DEBUGFS_FWSTATS_FILE_ARRAY(sub, name, len, struct_type) \ -static ssize_t sub## _ ##name## _read(struct file *file, \ - char __user *userbuf, \ - size_t count, loff_t *ppos) \ -{ \ - struct wl1271 *wl = file->private_data; \ - struct struct_type *stats = wl->stats.fw_stats; \ - char buf[DEBUGFS_FORMAT_BUFFER_SIZE] = ""; \ - int res, i; \ - \ - wl1271_debugfs_update_stats(wl); \ - \ - for (i = 0; i < len; i++) \ - res = snprintf(buf, sizeof(buf), "%s[%d] = %d\n", \ - buf, i, stats->sub.name[i]); \ - \ - return wl1271_format_buffer(userbuf, count, ppos, "%s", buf); \ -} \ - \ -static const struct file_operations sub## _ ##name## _ops = { \ - .read = sub## _ ##name## _read, \ - .open = simple_open, \ - .llseek = generic_file_llseek, \ -}; - -#define DEBUGFS_FWSTATS_ADD(sub, name) \ - DEBUGFS_ADD(sub## _ ##name, stats) - #endif /* WL1271_DEBUGFS_H */ diff --git a/trunk/drivers/net/wireless/ti/wlcore/event.c b/trunk/drivers/net/wireless/ti/wlcore/event.c index c976f0409865..28e2a633c3be 100644 --- a/trunk/drivers/net/wireless/ti/wlcore/event.c +++ b/trunk/drivers/net/wireless/ti/wlcore/event.c @@ -148,33 +148,15 @@ static int wl1271_event_process(struct wl1271 *wl) int delay = wl->conf.conn.synch_fail_thold * wl->conf.conn.bss_lose_timeout; wl1271_info("Beacon loss detected."); - - /* - * if the work is already queued, it should take place. We - * don't want to delay the connection loss indication - * any more. - */ + cancel_delayed_work_sync(&wl->connection_loss_work); ieee80211_queue_delayed_work(wl->hw, &wl->connection_loss_work, - msecs_to_jiffies(delay)); - - wl12xx_for_each_wlvif_sta(wl, wlvif) { - vif = wl12xx_wlvif_to_vif(wlvif); - - ieee80211_cqm_rssi_notify( - vif, - NL80211_CQM_RSSI_BEACON_LOSS_EVENT, - GFP_KERNEL); - } + msecs_to_jiffies(delay)); } if (vector & REGAINED_BSS_EVENT_ID) { /* TODO: check for multi-role */ wl1271_info("Beacon regained."); - cancel_delayed_work(&wl->connection_loss_work); - - /* sanity check - we can't lose and gain the beacon together */ - WARN(vector & BSS_LOSE_EVENT_ID, - "Concurrent beacon loss and gain from FW"); + cancel_delayed_work_sync(&wl->connection_loss_work); } if (vector & RSSI_SNR_TRIGGER_0_EVENT_ID) { diff --git a/trunk/drivers/net/wireless/ti/wlcore/hw_ops.h b/trunk/drivers/net/wireless/ti/wlcore/hw_ops.h index 9e7787ba9610..9384b4d56c24 100644 --- a/trunk/drivers/net/wireless/ti/wlcore/hw_ops.h +++ b/trunk/drivers/net/wireless/ti/wlcore/hw_ops.h @@ -119,82 +119,4 @@ static inline int wlcore_identify_fw(struct wl1271 *wl) return 0; } -static inline void -wlcore_hw_set_tx_desc_csum(struct wl1271 *wl, - struct wl1271_tx_hw_descr *desc, - struct sk_buff *skb) -{ - if (!wl->ops->set_tx_desc_csum) - BUG_ON(1); - - wl->ops->set_tx_desc_csum(wl, desc, skb); -} - -static inline void -wlcore_hw_set_rx_csum(struct wl1271 *wl, - struct wl1271_rx_descriptor *desc, - struct sk_buff *skb) -{ - if (wl->ops->set_rx_csum) - wl->ops->set_rx_csum(wl, desc, skb); -} - -static inline u32 -wlcore_hw_ap_get_mimo_wide_rate_mask(struct wl1271 *wl, - struct wl12xx_vif *wlvif) -{ - if (wl->ops->ap_get_mimo_wide_rate_mask) - return wl->ops->ap_get_mimo_wide_rate_mask(wl, wlvif); - - return 0; -} - -static inline int -wlcore_debugfs_init(struct wl1271 *wl, struct dentry *rootdir) -{ - if (wl->ops->debugfs_init) - return wl->ops->debugfs_init(wl, rootdir); - - return 0; -} - -static inline int -wlcore_handle_static_data(struct wl1271 *wl, void *static_data) -{ - if (wl->ops->handle_static_data) - return wl->ops->handle_static_data(wl, static_data); - - return 0; -} - -static inline int -wlcore_hw_get_spare_blocks(struct wl1271 *wl, bool is_gem) -{ - if (!wl->ops->get_spare_blocks) - BUG_ON(1); - - return wl->ops->get_spare_blocks(wl, is_gem); -} - -static inline int -wlcore_hw_set_key(struct wl1271 *wl, enum set_key_cmd cmd, - struct ieee80211_vif *vif, - struct ieee80211_sta *sta, - struct ieee80211_key_conf *key_conf) -{ - if (!wl->ops->set_key) - BUG_ON(1); - - return wl->ops->set_key(wl, cmd, vif, sta, key_conf); -} - -static inline u32 -wlcore_hw_pre_pkt_send(struct wl1271 *wl, u32 buf_offset, u32 last_len) -{ - if (wl->ops->pre_pkt_send) - return wl->ops->pre_pkt_send(wl, buf_offset, last_len); - - return buf_offset; -} - #endif diff --git a/trunk/drivers/net/wireless/ti/wlcore/init.c b/trunk/drivers/net/wireless/ti/wlcore/init.c index 645abd4b660d..9f89255eb6e6 100644 --- a/trunk/drivers/net/wireless/ti/wlcore/init.c +++ b/trunk/drivers/net/wireless/ti/wlcore/init.c @@ -460,9 +460,6 @@ int wl1271_init_ap_rates(struct wl1271 *wl, struct wl12xx_vif *wlvif) /* unconditionally enable HT rates */ supported_rates |= CONF_TX_MCS_RATES; - /* get extra MIMO or wide-chan rates where the HW supports it */ - supported_rates |= wlcore_hw_ap_get_mimo_wide_rate_mask(wl, wlvif); - /* configure unicast TX rate classes */ for (i = 0; i < wl->conf.tx.ac_conf_count; i++) { rc.enabled_rates = supported_rates; diff --git a/trunk/drivers/net/wireless/ti/wlcore/main.c b/trunk/drivers/net/wireless/ti/wlcore/main.c index 1156e3f578c1..acef93390d3d 100644 --- a/trunk/drivers/net/wireless/ti/wlcore/main.c +++ b/trunk/drivers/net/wireless/ti/wlcore/main.c @@ -320,6 +320,46 @@ static void wlcore_adjust_conf(struct wl1271 *wl) } } +static int wl1271_plt_init(struct wl1271 *wl) +{ + int ret; + + ret = wl->ops->hw_init(wl); + if (ret < 0) + return ret; + + ret = wl1271_acx_init_mem_config(wl); + if (ret < 0) + return ret; + + ret = wl12xx_acx_mem_cfg(wl); + if (ret < 0) + goto out_free_memmap; + + /* Enable data path */ + ret = wl1271_cmd_data_path(wl, 1); + if (ret < 0) + goto out_free_memmap; + + /* Configure for CAM power saving (ie. always active) */ + ret = wl1271_acx_sleep_auth(wl, WL1271_PSM_CAM); + if (ret < 0) + goto out_free_memmap; + + /* configure PM */ + ret = wl1271_acx_pm_config(wl); + if (ret < 0) + goto out_free_memmap; + + return 0; + + out_free_memmap: + kfree(wl->target_mem_map); + wl->target_mem_map = NULL; + + return ret; +} + static void wl12xx_irq_ps_regulate_link(struct wl1271 *wl, struct wl12xx_vif *wlvif, u8 hlid, u8 tx_pkts) @@ -347,7 +387,7 @@ static void wl12xx_irq_ps_regulate_link(struct wl1271 *wl, static void wl12xx_irq_update_links_status(struct wl1271 *wl, struct wl12xx_vif *wlvif, - struct wl_fw_status_2 *status) + struct wl_fw_status *status) { struct wl1271_link *lnk; u32 cur_fw_ps_map; @@ -379,8 +419,7 @@ static void wl12xx_irq_update_links_status(struct wl1271 *wl, } static void wl12xx_fw_status(struct wl1271 *wl, - struct wl_fw_status_1 *status_1, - struct wl_fw_status_2 *status_2) + struct wl_fw_status *status) { struct wl12xx_vif *wlvif; struct timespec ts; @@ -389,38 +428,37 @@ static void wl12xx_fw_status(struct wl1271 *wl, int i; size_t status_len; - status_len = WLCORE_FW_STATUS_1_LEN(wl->num_rx_desc) + - sizeof(*status_2) + wl->fw_status_priv_len; + status_len = sizeof(*status) + wl->fw_status_priv_len; - wlcore_raw_read_data(wl, REG_RAW_FW_STATUS_ADDR, status_1, + wlcore_raw_read_data(wl, REG_RAW_FW_STATUS_ADDR, status, status_len, false); wl1271_debug(DEBUG_IRQ, "intr: 0x%x (fw_rx_counter = %d, " "drv_rx_counter = %d, tx_results_counter = %d)", - status_1->intr, - status_1->fw_rx_counter, - status_1->drv_rx_counter, - status_1->tx_results_counter); + status->intr, + status->fw_rx_counter, + status->drv_rx_counter, + status->tx_results_counter); for (i = 0; i < NUM_TX_QUEUES; i++) { /* prevent wrap-around in freed-packets counter */ wl->tx_allocated_pkts[i] -= - (status_2->counters.tx_released_pkts[i] - + (status->counters.tx_released_pkts[i] - wl->tx_pkts_freed[i]) & 0xff; - wl->tx_pkts_freed[i] = status_2->counters.tx_released_pkts[i]; + wl->tx_pkts_freed[i] = status->counters.tx_released_pkts[i]; } /* prevent wrap-around in total blocks counter */ if (likely(wl->tx_blocks_freed <= - le32_to_cpu(status_2->total_released_blks))) - freed_blocks = le32_to_cpu(status_2->total_released_blks) - + le32_to_cpu(status->total_released_blks))) + freed_blocks = le32_to_cpu(status->total_released_blks) - wl->tx_blocks_freed; else freed_blocks = 0x100000000LL - wl->tx_blocks_freed + - le32_to_cpu(status_2->total_released_blks); + le32_to_cpu(status->total_released_blks); - wl->tx_blocks_freed = le32_to_cpu(status_2->total_released_blks); + wl->tx_blocks_freed = le32_to_cpu(status->total_released_blks); wl->tx_allocated_blocks -= freed_blocks; @@ -436,7 +474,7 @@ static void wl12xx_fw_status(struct wl1271 *wl, cancel_delayed_work(&wl->tx_watchdog_work); } - avail = le32_to_cpu(status_2->tx_total) - wl->tx_allocated_blocks; + avail = le32_to_cpu(status->tx_total) - wl->tx_allocated_blocks; /* * The FW might change the total number of TX memblocks before @@ -455,13 +493,13 @@ static void wl12xx_fw_status(struct wl1271 *wl, /* for AP update num of allocated TX blocks per link and ps status */ wl12xx_for_each_wlvif_ap(wl, wlvif) { - wl12xx_irq_update_links_status(wl, wlvif, status_2); + wl12xx_irq_update_links_status(wl, wlvif, status); } /* update the host-chipset time offset */ getnstimeofday(&ts); wl->time_offset = (timespec_to_ns(&ts) >> 10) - - (s64)le32_to_cpu(status_2->fw_localtime); + (s64)le32_to_cpu(status->fw_localtime); } static void wl1271_flush_deferred_work(struct wl1271 *wl) @@ -530,30 +568,20 @@ static irqreturn_t wl1271_irq(int irq, void *cookie) clear_bit(WL1271_FLAG_IRQ_RUNNING, &wl->flags); smp_mb__after_clear_bit(); - wl12xx_fw_status(wl, wl->fw_status_1, wl->fw_status_2); + wl12xx_fw_status(wl, wl->fw_status); wlcore_hw_tx_immediate_compl(wl); - intr = le32_to_cpu(wl->fw_status_1->intr); - intr &= WLCORE_ALL_INTR_MASK; + intr = le32_to_cpu(wl->fw_status->intr); + intr &= WL1271_INTR_MASK; if (!intr) { done = true; continue; } if (unlikely(intr & WL1271_ACX_INTR_WATCHDOG)) { - wl1271_error("HW watchdog interrupt received! starting recovery."); - wl->watchdog_recovery = true; - wl12xx_queue_recovery_work(wl); - - /* restarting the chip. ignore any other interrupt. */ - goto out; - } - - if (unlikely(intr & WL1271_ACX_SW_INTR_WATCHDOG)) { - wl1271_error("SW watchdog interrupt received! " + wl1271_error("watchdog interrupt received! " "starting recovery."); - wl->watchdog_recovery = true; wl12xx_queue_recovery_work(wl); /* restarting the chip. ignore any other interrupt. */ @@ -563,7 +591,7 @@ static irqreturn_t wl1271_irq(int irq, void *cookie) if (likely(intr & WL1271_ACX_INTR_DATA)) { wl1271_debug(DEBUG_IRQ, "WL1271_ACX_INTR_DATA"); - wl12xx_rx(wl, wl->fw_status_1); + wl12xx_rx(wl, wl->fw_status); /* Check if any tx blocks were freed */ spin_lock_irqsave(&wl->wl_lock, flags); @@ -715,7 +743,7 @@ static int wl12xx_fetch_firmware(struct wl1271 *wl, bool plt) return ret; } -static void wl1271_fetch_nvs(struct wl1271 *wl) +static int wl1271_fetch_nvs(struct wl1271 *wl) { const struct firmware *fw; int ret; @@ -723,15 +751,16 @@ static void wl1271_fetch_nvs(struct wl1271 *wl) ret = request_firmware(&fw, WL12XX_NVS_NAME, wl->dev); if (ret < 0) { - wl1271_debug(DEBUG_BOOT, "could not get nvs file %s: %d", - WL12XX_NVS_NAME, ret); - return; + wl1271_error("could not get nvs file %s: %d", WL12XX_NVS_NAME, + ret); + return ret; } wl->nvs = kmemdup(fw->data, fw->size, GFP_KERNEL); if (!wl->nvs) { wl1271_error("could not allocate memory for the nvs file"); + ret = -ENOMEM; goto out; } @@ -739,6 +768,8 @@ static void wl1271_fetch_nvs(struct wl1271 *wl) out: release_firmware(fw); + + return ret; } void wl12xx_queue_recovery_work(struct wl1271 *wl) @@ -789,16 +820,14 @@ static void wl12xx_read_fwlog_panic(struct wl1271 *wl) /* * Make sure the chip is awake and the logger isn't active. - * Do not send a stop fwlog command if the fw is hanged. + * This might fail if the firmware hanged. */ - if (!wl1271_ps_elp_wakeup(wl) && !wl->watchdog_recovery) + if (!wl1271_ps_elp_wakeup(wl)) wl12xx_cmd_stop_fwlog(wl); - else - goto out; /* Read the first memory block address */ - wl12xx_fw_status(wl, wl->fw_status_1, wl->fw_status_2); - first_addr = le32_to_cpu(wl->fw_status_2->log_start_addr); + wl12xx_fw_status(wl, wl->fw_status); + first_addr = le32_to_cpu(wl->fw_status->log_start_addr); if (!first_addr) goto out; @@ -843,14 +872,9 @@ static void wl1271_recovery_work(struct work_struct *work) wl12xx_read_fwlog_panic(wl); - /* change partitions momentarily so we can read the FW pc */ - wlcore_set_partition(wl, &wl->ptable[PART_BOOT]); - wl1271_info("Hardware recovery in progress. FW ver: %s pc: 0x%x " - "hint_sts: 0x%08x", + wl1271_info("Hardware recovery in progress. FW ver: %s pc: 0x%x", wl->chip.fw_ver_str, - wlcore_read_reg(wl, REG_PC_ON_RECOVERY), - wlcore_read_reg(wl, REG_INTERRUPT_NO_CLEAR)); - wlcore_set_partition(wl, &wl->ptable[PART_WORK]); + wlcore_read_reg(wl, REG_PC_ON_RECOVERY)); BUG_ON(bug_on_recovery && !test_bit(WL1271_FLAG_INTENDED_FW_RECOVERY, &wl->flags)); @@ -861,6 +885,8 @@ static void wl1271_recovery_work(struct work_struct *work) goto out_unlock; } + BUG_ON(bug_on_recovery); + /* * Advance security sequence number to overcome potential progress * in the firmware during recovery. This doens't hurt if the network is @@ -874,7 +900,7 @@ static void wl1271_recovery_work(struct work_struct *work) } /* Prevent spurious TX during FW restart */ - wlcore_stop_queues(wl, WLCORE_QUEUE_STOP_REASON_FW_RESTART); + ieee80211_stop_queues(wl->hw); if (wl->sched_scanning) { ieee80211_sched_scan_stopped(wl->hw); @@ -888,7 +914,6 @@ static void wl1271_recovery_work(struct work_struct *work) vif = wl12xx_wlvif_to_vif(wlvif); __wl1271_op_remove_interface(wl, vif, false); } - wl->watchdog_recovery = false; mutex_unlock(&wl->mutex); wl1271_op_stop(wl->hw); @@ -900,10 +925,9 @@ static void wl1271_recovery_work(struct work_struct *work) * Its safe to enable TX now - the queues are stopped after a request * to restart the HW. */ - wlcore_wake_queues(wl, WLCORE_QUEUE_STOP_REASON_FW_RESTART); + ieee80211_wake_queues(wl->hw); return; out_unlock: - wl->watchdog_recovery = false; mutex_unlock(&wl->mutex); } @@ -914,19 +938,13 @@ static void wl1271_fw_wakeup(struct wl1271 *wl) static int wl1271_setup(struct wl1271 *wl) { - wl->fw_status_1 = kmalloc(WLCORE_FW_STATUS_1_LEN(wl->num_rx_desc) + - sizeof(*wl->fw_status_2) + - wl->fw_status_priv_len, GFP_KERNEL); - if (!wl->fw_status_1) + wl->fw_status = kmalloc(sizeof(*wl->fw_status), GFP_KERNEL); + if (!wl->fw_status) return -ENOMEM; - wl->fw_status_2 = (struct wl_fw_status_2 *) - (((u8 *) wl->fw_status_1) + - WLCORE_FW_STATUS_1_LEN(wl->num_rx_desc)); - wl->tx_res_if = kmalloc(sizeof(*wl->tx_res_if), GFP_KERNEL); if (!wl->tx_res_if) { - kfree(wl->fw_status_1); + kfree(wl->fw_status); return -ENOMEM; } @@ -969,12 +987,13 @@ static int wl12xx_chip_wakeup(struct wl1271 *wl, bool plt) * simplify the code and since the performance impact is * negligible, we use the same block size for all different * chip types. - * - * Check if the bus supports blocksize alignment and, if it - * doesn't, make sure we don't have the quirk. */ - if (!wl1271_set_block_size(wl)) - wl->quirks &= ~WLCORE_QUIRK_TX_BLOCKSIZE_ALIGN; + if (wl1271_set_block_size(wl)) + wl->quirks |= WLCORE_QUIRK_TX_BLOCKSIZE_ALIGN; + + ret = wl->ops->identify_chip(wl); + if (ret < 0) + goto out; /* TODO: make sure the lower driver has set things up correctly */ @@ -986,6 +1005,13 @@ static int wl12xx_chip_wakeup(struct wl1271 *wl, bool plt) if (ret < 0) goto out; + /* No NVS from netlink, try to get it from the filesystem */ + if (wl->nvs == NULL) { + ret = wl1271_fetch_nvs(wl); + if (ret < 0) + goto out; + } + out: return ret; } @@ -1013,10 +1039,14 @@ int wl1271_plt_start(struct wl1271 *wl) if (ret < 0) goto power_off; - ret = wl->ops->plt_init(wl); + ret = wl->ops->boot(wl); if (ret < 0) goto power_off; + ret = wl1271_plt_init(wl); + if (ret < 0) + goto irq_disable; + wl->plt = true; wl->state = WL1271_STATE_ON; wl1271_notice("firmware booted in PLT mode (%s)", @@ -1029,6 +1059,19 @@ int wl1271_plt_start(struct wl1271 *wl) goto out; +irq_disable: + mutex_unlock(&wl->mutex); + /* Unlocking the mutex in the middle of handling is + inherently unsafe. In this case we deem it safe to do, + because we need to let any possibly pending IRQ out of + the system (and while we are WL1271_STATE_OFF the IRQ + work function will not do anything.) Also, any other + possible concurrent operations will fail due to the + current state, hence the wl1271 struct should be safe. */ + wlcore_disable_interrupts(wl); + wl1271_flush_deferred_work(wl); + cancel_work_sync(&wl->netstack_work); + mutex_lock(&wl->mutex); power_off: wl1271_power_off(wl); } @@ -1111,16 +1154,9 @@ static void wl1271_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb) spin_lock_irqsave(&wl->wl_lock, flags); - /* - * drop the packet if the link is invalid or the queue is stopped - * for any reason but watermark. Watermark is a "soft"-stop so we - * allow these packets through. - */ + /* queue the packet */ if (hlid == WL12XX_INVALID_LINK_ID || - (wlvif && !test_bit(hlid, wlvif->links_map)) || - (wlcore_is_queue_stopped(wl, q) && - !wlcore_is_queue_stopped_by_reason(wl, q, - WLCORE_QUEUE_STOP_REASON_WATERMARK))) { + (wlvif && !test_bit(hlid, wlvif->links_map))) { wl1271_debug(DEBUG_TX, "DROP skb hlid %d q %d", hlid, q); ieee80211_free_txskb(hw, skb); goto out; @@ -1138,8 +1174,8 @@ static void wl1271_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb) */ if (wl->tx_queue_count[q] >= WL1271_TX_QUEUE_HIGH_WATERMARK) { wl1271_debug(DEBUG_TX, "op_tx: stopping queues for q %d", q); - wlcore_stop_queue_locked(wl, q, - WLCORE_QUEUE_STOP_REASON_WATERMARK); + ieee80211_stop_queue(wl->hw, mapping); + set_bit(q, &wl->stopped_queues_map); } /* @@ -1722,7 +1758,7 @@ static void wl1271_op_stop(struct ieee80211_hw *hw) cancel_delayed_work_sync(&wl->connection_loss_work); /* let's notify MAC80211 about the remaining pending TX frames */ - wl12xx_tx_reset(wl); + wl12xx_tx_reset(wl, true); mutex_lock(&wl->mutex); wl1271_power_off(wl); @@ -1731,7 +1767,6 @@ static void wl1271_op_stop(struct ieee80211_hw *hw) wl->rx_counter = 0; wl->power_level = WL1271_DEFAULT_POWER_LEVEL; - wl->channel_type = NL80211_CHAN_NO_HT; wl->tx_blocks_available = 0; wl->tx_allocated_blocks = 0; wl->tx_results_count = 0; @@ -1764,9 +1799,8 @@ static void wl1271_op_stop(struct ieee80211_hw *hw) wl1271_debugfs_reset(wl); - kfree(wl->fw_status_1); - wl->fw_status_1 = NULL; - wl->fw_status_2 = NULL; + kfree(wl->fw_status); + wl->fw_status = NULL; kfree(wl->tx_res_if); wl->tx_res_if = NULL; kfree(wl->target_mem_map); @@ -1860,9 +1894,6 @@ static int wl12xx_init_vif_data(struct wl1271 *wl, struct ieee80211_vif *vif) wl12xx_allocate_rate_policy(wl, &wlvif->sta.basic_rate_idx); wl12xx_allocate_rate_policy(wl, &wlvif->sta.ap_rate_idx); wl12xx_allocate_rate_policy(wl, &wlvif->sta.p2p_rate_idx); - wlvif->basic_rate_set = CONF_TX_RATE_MASK_BASIC; - wlvif->basic_rate = CONF_TX_RATE_MASK_BASIC; - wlvif->rate_set = CONF_TX_RATE_MASK_BASIC; } else { /* init ap data */ wlvif->ap.bcast_hlid = WL12XX_INVALID_LINK_ID; @@ -1872,19 +1903,13 @@ static int wl12xx_init_vif_data(struct wl1271 *wl, struct ieee80211_vif *vif) for (i = 0; i < CONF_TX_MAX_AC_COUNT; i++) wl12xx_allocate_rate_policy(wl, &wlvif->ap.ucast_rate_idx[i]); - wlvif->basic_rate_set = CONF_TX_AP_ENABLED_RATES; - /* - * TODO: check if basic_rate shouldn't be - * wl1271_tx_min_rate_get(wl, wlvif->basic_rate_set); - * instead (the same thing for STA above). - */ - wlvif->basic_rate = CONF_TX_AP_ENABLED_RATES; - /* TODO: this seems to be used only for STA, check it */ - wlvif->rate_set = CONF_TX_AP_ENABLED_RATES; } wlvif->bitrate_masks[IEEE80211_BAND_2GHZ] = wl->conf.tx.basic_rate; wlvif->bitrate_masks[IEEE80211_BAND_5GHZ] = wl->conf.tx.basic_rate_5; + wlvif->basic_rate_set = CONF_TX_RATE_MASK_BASIC; + wlvif->basic_rate = CONF_TX_RATE_MASK_BASIC; + wlvif->rate_set = CONF_TX_RATE_MASK_BASIC; wlvif->beacon_int = WL1271_DEFAULT_BEACON_INT; /* @@ -1894,7 +1919,6 @@ static int wl12xx_init_vif_data(struct wl1271 *wl, struct ieee80211_vif *vif) wlvif->band = wl->band; wlvif->channel = wl->channel; wlvif->power_level = wl->power_level; - wlvif->channel_type = wl->channel_type; INIT_WORK(&wlvif->rx_streaming_enable_work, wl1271_rx_streaming_enable_work); @@ -2420,7 +2444,7 @@ static int wl1271_sta_handle_idle(struct wl1271 *wl, struct wl12xx_vif *wlvif, } else { /* The current firmware only supports sched_scan in idle */ if (wl->sched_scanning) { - wl1271_scan_sched_scan_stop(wl, wlvif); + wl1271_scan_sched_scan_stop(wl); ieee80211_sched_scan_stopped(wl->hw); } @@ -2445,20 +2469,13 @@ static int wl12xx_config_vif(struct wl1271 *wl, struct wl12xx_vif *wlvif, /* if the channel changes while joined, join again */ if (changed & IEEE80211_CONF_CHANGE_CHANNEL && ((wlvif->band != conf->channel->band) || - (wlvif->channel != channel) || - (wlvif->channel_type != conf->channel_type))) { + (wlvif->channel != channel))) { /* send all pending packets */ wl1271_tx_work_locked(wl); wlvif->band = conf->channel->band; wlvif->channel = channel; - wlvif->channel_type = conf->channel_type; - if (is_ap) { - ret = wl1271_init_ap_rates(wl, wlvif); - if (ret < 0) - wl1271_error("AP rate policy change failed %d", - ret); - } else { + if (!is_ap) { /* * FIXME: the mac80211 should really provide a fixed * rate to use here. for now, just use the smallest @@ -2566,9 +2583,8 @@ static int wl1271_op_config(struct ieee80211_hw *hw, u32 changed) * frames, such as the deauth. To make sure those frames reach the air, * wait here until the TX queue is fully flushed. */ - if ((changed & IEEE80211_CONF_CHANGE_CHANNEL) || - ((changed & IEEE80211_CONF_CHANGE_IDLE) && - (conf->flags & IEEE80211_CONF_IDLE))) + if ((changed & IEEE80211_CONF_CHANGE_IDLE) && + (conf->flags & IEEE80211_CONF_IDLE)) wl1271_tx_flush(wl); mutex_lock(&wl->mutex); @@ -2577,7 +2593,6 @@ static int wl1271_op_config(struct ieee80211_hw *hw, u32 changed) if (changed & IEEE80211_CONF_CHANGE_CHANNEL) { wl->band = conf->channel->band; wl->channel = channel; - wl->channel_type = conf->channel_type; } if (changed & IEEE80211_CONF_CHANGE_POWER) @@ -2810,6 +2825,17 @@ static int wl1271_set_key(struct wl1271 *wl, struct wl12xx_vif *wlvif, int ret; bool is_ap = (wlvif->bss_type == BSS_TYPE_AP_BSS); + /* + * A role set to GEM cipher requires different Tx settings (namely + * spare blocks). Note when we are in this mode so the HW can adjust. + */ + if (key_type == KEY_GEM) { + if (action == KEY_ADD_OR_REPLACE) + wlvif->is_gem = true; + else if (action == KEY_REMOVE) + wlvif->is_gem = false; + } + if (is_ap) { struct wl1271_station *wl_sta; u8 hlid; @@ -2887,21 +2913,12 @@ static int wl1271_set_key(struct wl1271 *wl, struct wl12xx_vif *wlvif, return 0; } -static int wlcore_op_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, +static int wl1271_op_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, struct ieee80211_vif *vif, struct ieee80211_sta *sta, struct ieee80211_key_conf *key_conf) { struct wl1271 *wl = hw->priv; - - return wlcore_hw_set_key(wl, cmd, vif, sta, key_conf); -} - -int wlcore_set_key(struct wl1271 *wl, enum set_key_cmd cmd, - struct ieee80211_vif *vif, - struct ieee80211_sta *sta, - struct ieee80211_key_conf *key_conf) -{ struct wl12xx_vif *wlvif = wl12xx_vif_to_data(vif); int ret; u32 tx_seq_32 = 0; @@ -3012,7 +3029,6 @@ int wlcore_set_key(struct wl1271 *wl, enum set_key_cmd cmd, return ret; } -EXPORT_SYMBOL_GPL(wlcore_set_key); static int wl1271_op_hw_scan(struct ieee80211_hw *hw, struct ieee80211_vif *vif, @@ -3151,7 +3167,6 @@ static void wl1271_op_sched_scan_stop(struct ieee80211_hw *hw, struct ieee80211_vif *vif) { struct wl1271 *wl = hw->priv; - struct wl12xx_vif *wlvif = wl12xx_vif_to_data(vif); int ret; wl1271_debug(DEBUG_MAC80211, "wl1271_op_sched_scan_stop"); @@ -3165,7 +3180,7 @@ static void wl1271_op_sched_scan_stop(struct ieee80211_hw *hw, if (ret < 0) goto out; - wl1271_scan_sched_scan_stop(wl, wlvif); + wl1271_scan_sched_scan_stop(wl); wl1271_ps_elp_sleep(wl); out: @@ -3301,15 +3316,8 @@ static int wl1271_ap_set_probe_resp_tmpl(struct wl1271 *wl, u32 rates, skb->data, skb->len, 0, rates); - dev_kfree_skb(skb); - - if (ret < 0) - goto out; - - wl1271_debug(DEBUG_AP, "probe response updated"); - set_bit(WLVIF_FLAG_AP_PROBE_RESP_SET, &wlvif->flags); -out: + dev_kfree_skb(skb); return ret; } @@ -3414,87 +3422,6 @@ static int wl1271_bss_erp_info_changed(struct wl1271 *wl, return ret; } -static int wlcore_set_beacon_template(struct wl1271 *wl, - struct ieee80211_vif *vif, - bool is_ap) -{ - struct wl12xx_vif *wlvif = wl12xx_vif_to_data(vif); - struct ieee80211_hdr *hdr; - u32 min_rate; - int ret; - int ieoffset = offsetof(struct ieee80211_mgmt, - u.beacon.variable); - struct sk_buff *beacon = ieee80211_beacon_get(wl->hw, vif); - u16 tmpl_id; - - if (!beacon) { - ret = -EINVAL; - goto out; - } - - wl1271_debug(DEBUG_MASTER, "beacon updated"); - - ret = wl1271_ssid_set(vif, beacon, ieoffset); - if (ret < 0) { - dev_kfree_skb(beacon); - goto out; - } - min_rate = wl1271_tx_min_rate_get(wl, wlvif->basic_rate_set); - tmpl_id = is_ap ? CMD_TEMPL_AP_BEACON : - CMD_TEMPL_BEACON; - ret = wl1271_cmd_template_set(wl, wlvif->role_id, tmpl_id, - beacon->data, - beacon->len, 0, - min_rate); - if (ret < 0) { - dev_kfree_skb(beacon); - goto out; - } - - /* - * In case we already have a probe-resp beacon set explicitly - * by usermode, don't use the beacon data. - */ - if (test_bit(WLVIF_FLAG_AP_PROBE_RESP_SET, &wlvif->flags)) - goto end_bcn; - - /* remove TIM ie from probe response */ - wl12xx_remove_ie(beacon, WLAN_EID_TIM, ieoffset); - - /* - * remove p2p ie from probe response. - * the fw reponds to probe requests that don't include - * the p2p ie. probe requests with p2p ie will be passed, - * and will be responded by the supplicant (the spec - * forbids including the p2p ie when responding to probe - * requests that didn't include it). - */ - wl12xx_remove_vendor_ie(beacon, WLAN_OUI_WFA, - WLAN_OUI_TYPE_WFA_P2P, ieoffset); - - hdr = (struct ieee80211_hdr *) beacon->data; - hdr->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | - IEEE80211_STYPE_PROBE_RESP); - if (is_ap) - ret = wl1271_ap_set_probe_resp_tmpl_legacy(wl, vif, - beacon->data, - beacon->len, - min_rate); - else - ret = wl1271_cmd_template_set(wl, wlvif->role_id, - CMD_TEMPL_PROBE_RESPONSE, - beacon->data, - beacon->len, 0, - min_rate); -end_bcn: - dev_kfree_skb(beacon); - if (ret < 0) - goto out; - -out: - return ret; -} - static int wl1271_bss_beacon_info_changed(struct wl1271 *wl, struct ieee80211_vif *vif, struct ieee80211_bss_conf *bss_conf, @@ -3513,12 +3440,81 @@ static int wl1271_bss_beacon_info_changed(struct wl1271 *wl, if ((changed & BSS_CHANGED_AP_PROBE_RESP) && is_ap) { u32 rate = wl1271_tx_min_rate_get(wl, wlvif->basic_rate_set); - - wl1271_ap_set_probe_resp_tmpl(wl, rate, vif); + if (!wl1271_ap_set_probe_resp_tmpl(wl, rate, vif)) { + wl1271_debug(DEBUG_AP, "probe response updated"); + set_bit(WLVIF_FLAG_AP_PROBE_RESP_SET, &wlvif->flags); + } } if ((changed & BSS_CHANGED_BEACON)) { - ret = wlcore_set_beacon_template(wl, vif, is_ap); + struct ieee80211_hdr *hdr; + u32 min_rate; + int ieoffset = offsetof(struct ieee80211_mgmt, + u.beacon.variable); + struct sk_buff *beacon = ieee80211_beacon_get(wl->hw, vif); + u16 tmpl_id; + + if (!beacon) { + ret = -EINVAL; + goto out; + } + + wl1271_debug(DEBUG_MASTER, "beacon updated"); + + ret = wl1271_ssid_set(vif, beacon, ieoffset); + if (ret < 0) { + dev_kfree_skb(beacon); + goto out; + } + min_rate = wl1271_tx_min_rate_get(wl, wlvif->basic_rate_set); + tmpl_id = is_ap ? CMD_TEMPL_AP_BEACON : + CMD_TEMPL_BEACON; + ret = wl1271_cmd_template_set(wl, wlvif->role_id, tmpl_id, + beacon->data, + beacon->len, 0, + min_rate); + if (ret < 0) { + dev_kfree_skb(beacon); + goto out; + } + + /* + * In case we already have a probe-resp beacon set explicitly + * by usermode, don't use the beacon data. + */ + if (test_bit(WLVIF_FLAG_AP_PROBE_RESP_SET, &wlvif->flags)) + goto end_bcn; + + /* remove TIM ie from probe response */ + wl12xx_remove_ie(beacon, WLAN_EID_TIM, ieoffset); + + /* + * remove p2p ie from probe response. + * the fw reponds to probe requests that don't include + * the p2p ie. probe requests with p2p ie will be passed, + * and will be responded by the supplicant (the spec + * forbids including the p2p ie when responding to probe + * requests that didn't include it). + */ + wl12xx_remove_vendor_ie(beacon, WLAN_OUI_WFA, + WLAN_OUI_TYPE_WFA_P2P, ieoffset); + + hdr = (struct ieee80211_hdr *) beacon->data; + hdr->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | + IEEE80211_STYPE_PROBE_RESP); + if (is_ap) + ret = wl1271_ap_set_probe_resp_tmpl_legacy(wl, vif, + beacon->data, + beacon->len, + min_rate); + else + ret = wl1271_cmd_template_set(wl, wlvif->role_id, + CMD_TEMPL_PROBE_RESPONSE, + beacon->data, + beacon->len, 0, + min_rate); +end_bcn: + dev_kfree_skb(beacon); if (ret < 0) goto out; } @@ -3555,14 +3551,6 @@ static void wl1271_bss_info_changed_ap(struct wl1271 *wl, ret = wl1271_ap_init_templates(wl, vif); if (ret < 0) goto out; - - ret = wl1271_ap_set_probe_resp_tmpl(wl, wlvif->basic_rate, vif); - if (ret < 0) - goto out; - - ret = wlcore_set_beacon_template(wl, vif, true); - if (ret < 0) - goto out; } ret = wl1271_bss_beacon_info_changed(wl, vif, bss_conf, changed); @@ -3703,8 +3691,7 @@ static void wl1271_bss_info_changed_sta(struct wl1271 *wl, sta_rate_set = sta->supp_rates[wl->hw->conf.channel->band]; if (sta->ht_cap.ht_supported) sta_rate_set |= - (sta->ht_cap.mcs.rx_mask[0] << HW_HT_RATES_OFFSET) | - (sta->ht_cap.mcs.rx_mask[1] << HW_MIMO_RATES_OFFSET); + (sta->ht_cap.mcs.rx_mask[0] << HW_HT_RATES_OFFSET); sta_ht_cap = sta->ht_cap; sta_exists = true; @@ -3717,11 +3704,13 @@ static void wl1271_bss_info_changed_sta(struct wl1271 *wl, u32 rates; int ieoffset; wlvif->aid = bss_conf->aid; - wlvif->channel_type = bss_conf->channel_type; wlvif->beacon_int = bss_conf->beacon_int; do_join = true; set_assoc = true; + /* Cancel connection_loss_work */ + cancel_delayed_work_sync(&wl->connection_loss_work); + /* * use basic rates from AP, and determine lowest rate * to use with control frames. @@ -3971,17 +3960,6 @@ static void wl1271_op_bss_info_changed(struct ieee80211_hw *hw, wl1271_debug(DEBUG_MAC80211, "mac80211 bss info changed 0x%x", (int)changed); - /* - * make sure to cancel pending disconnections if our association - * state changed - */ - if (!is_ap && (changed & BSS_CHANGED_ASSOC)) - cancel_delayed_work_sync(&wl->connection_loss_work); - - if (is_ap && (changed & BSS_CHANGED_BEACON_ENABLED) && - !bss_conf->enable_beacon) - wl1271_tx_flush(wl); - mutex_lock(&wl->mutex); if (unlikely(wl->state == WL1271_STATE_OFF)) @@ -4658,7 +4636,7 @@ static const struct ieee80211_ops wl1271_ops = { .prepare_multicast = wl1271_op_prepare_multicast, .configure_filter = wl1271_op_configure_filter, .tx = wl1271_op_tx, - .set_key = wlcore_op_set_key, + .set_key = wl1271_op_set_key, .hw_scan = wl1271_op_hw_scan, .cancel_hw_scan = wl1271_op_cancel_hw_scan, .sched_scan_start = wl1271_op_sched_scan_start, @@ -4927,8 +4905,14 @@ static int wl1271_register_hw(struct wl1271 *wl) if (wl->mac80211_registered) return 0; - wl1271_fetch_nvs(wl); - if (wl->nvs != NULL) { + ret = wl12xx_get_hw_info(wl); + if (ret < 0) { + wl1271_error("couldn't get hw info"); + goto out; + } + + ret = wl1271_fetch_nvs(wl); + if (ret == 0) { /* NOTE: The wl->nvs->nvs element must be first, in * order to simplify the casting, we assume it is at * the beginning of the wl->nvs structure. @@ -4986,11 +4970,9 @@ static int wl1271_init_ieee80211(struct wl1271 *wl) WL1271_CIPHER_SUITE_GEM, }; - /* The tx descriptor buffer */ - wl->hw->extra_tx_headroom = sizeof(struct wl1271_tx_hw_descr); - - if (wl->quirks & WLCORE_QUIRK_TKIP_HEADER_SPACE) - wl->hw->extra_tx_headroom += WL1271_EXTRA_SPACE_TKIP; + /* The tx descriptor buffer and the TKIP space. */ + wl->hw->extra_tx_headroom = WL1271_EXTRA_SPACE_TKIP + + sizeof(struct wl1271_tx_hw_descr); /* unit us */ /* FIXME: find a proper value */ @@ -5043,14 +5025,12 @@ static int wl1271_init_ieee80211(struct wl1271 *wl) */ memcpy(&wl->bands[IEEE80211_BAND_2GHZ], &wl1271_band_2ghz, sizeof(wl1271_band_2ghz)); - memcpy(&wl->bands[IEEE80211_BAND_2GHZ].ht_cap, - &wl->ht_cap[IEEE80211_BAND_2GHZ], - sizeof(*wl->ht_cap)); + memcpy(&wl->bands[IEEE80211_BAND_2GHZ].ht_cap, &wl->ht_cap, + sizeof(wl->ht_cap)); memcpy(&wl->bands[IEEE80211_BAND_5GHZ], &wl1271_band_5ghz, sizeof(wl1271_band_5ghz)); - memcpy(&wl->bands[IEEE80211_BAND_5GHZ].ht_cap, - &wl->ht_cap[IEEE80211_BAND_5GHZ], - sizeof(*wl->ht_cap)); + memcpy(&wl->bands[IEEE80211_BAND_5GHZ].ht_cap, &wl->ht_cap, + sizeof(wl->ht_cap)); wl->hw->wiphy->bands[IEEE80211_BAND_2GHZ] = &wl->bands[IEEE80211_BAND_2GHZ]; @@ -5137,7 +5117,6 @@ struct ieee80211_hw *wlcore_alloc_hw(size_t priv_size) wl->rx_counter = 0; wl->power_level = WL1271_DEFAULT_POWER_LEVEL; wl->band = IEEE80211_BAND_2GHZ; - wl->channel_type = NL80211_CHAN_NO_HT; wl->flags = 0; wl->sg_enabled = true; wl->hw_pg_ver = -1; @@ -5163,7 +5142,6 @@ struct ieee80211_hw *wlcore_alloc_hw(size_t priv_size) wl->state = WL1271_STATE_OFF; wl->fw_type = WL12XX_FW_TYPE_NONE; mutex_init(&wl->mutex); - mutex_init(&wl->flush_mutex); order = get_order(WL1271_AGGR_BUFFER_SIZE); wl->aggr_buf = (u8 *)__get_free_pages(GFP_KERNEL, order); @@ -5244,7 +5222,7 @@ int wlcore_free_hw(struct wl1271 *wl) kfree(wl->nvs); wl->nvs = NULL; - kfree(wl->fw_status_1); + kfree(wl->fw_status); kfree(wl->tx_res_if); destroy_workqueue(wl->freezable_wq); @@ -5301,6 +5279,8 @@ int __devinit wlcore_probe(struct wl1271 *wl, struct platform_device *pdev) wlcore_adjust_conf(wl); wl->irq = platform_get_irq(pdev, 0); + wl->ref_clock = pdata->board_ref_clock; + wl->tcxo_clock = pdata->board_tcxo_clock; wl->platform_quirks = pdata->platform_quirks; wl->set_power = pdata->set_power; wl->dev = &pdev->dev; @@ -5336,16 +5316,6 @@ int __devinit wlcore_probe(struct wl1271 *wl, struct platform_device *pdev) } disable_irq(wl->irq); - ret = wl12xx_get_hw_info(wl); - if (ret < 0) { - wl1271_error("couldn't get hw info"); - goto out; - } - - ret = wl->ops->identify_chip(wl); - if (ret < 0) - goto out; - ret = wl1271_init_ieee80211(wl); if (ret) goto out_irq; diff --git a/trunk/drivers/net/wireless/ti/wlcore/ps.c b/trunk/drivers/net/wireless/ti/wlcore/ps.c index 47e81b32f7da..756eee2257b4 100644 --- a/trunk/drivers/net/wireless/ti/wlcore/ps.c +++ b/trunk/drivers/net/wireless/ti/wlcore/ps.c @@ -28,8 +28,6 @@ #define WL1271_WAKEUP_TIMEOUT 500 -#define ELP_ENTRY_DELAY 5 - void wl1271_elp_work(struct work_struct *work) { struct delayed_work *dwork; @@ -74,7 +72,6 @@ void wl1271_elp_work(struct work_struct *work) void wl1271_ps_elp_sleep(struct wl1271 *wl) { struct wl12xx_vif *wlvif; - u32 timeout; if (wl->quirks & WLCORE_QUIRK_NO_ELP) return; @@ -92,13 +89,8 @@ void wl1271_ps_elp_sleep(struct wl1271 *wl) return; } - if (wl->conf.conn.forced_ps) - timeout = ELP_ENTRY_DELAY; - else - timeout = wl->conf.conn.dynamic_ps_timeout; - ieee80211_queue_delayed_work(wl->hw, &wl->elp_work, - msecs_to_jiffies(timeout)); + msecs_to_jiffies(wl->conf.conn.dynamic_ps_timeout)); } int wl1271_ps_elp_wakeup(struct wl1271 *wl) @@ -193,12 +185,8 @@ int wl1271_ps_set_mode(struct wl1271 *wl, struct wl12xx_vif *wlvif, set_bit(WLVIF_FLAG_IN_PS, &wlvif->flags); - /* - * enable beacon early termination. - * Not relevant for 5GHz and for high rates. - */ - if ((wlvif->band == IEEE80211_BAND_2GHZ) && - (wlvif->basic_rate < CONF_HW_BIT_RATE_9MBPS)) { + /* enable beacon early termination. Not relevant for 5GHz */ + if (wlvif->band == IEEE80211_BAND_2GHZ) { ret = wl1271_acx_bet_enable(wl, wlvif, true); if (ret < 0) return ret; @@ -208,8 +196,7 @@ int wl1271_ps_set_mode(struct wl1271 *wl, struct wl12xx_vif *wlvif, wl1271_debug(DEBUG_PSM, "leaving psm"); /* disable beacon early termination */ - if ((wlvif->band == IEEE80211_BAND_2GHZ) && - (wlvif->basic_rate < CONF_HW_BIT_RATE_9MBPS)) { + if (wlvif->band == IEEE80211_BAND_2GHZ) { ret = wl1271_acx_bet_enable(wl, wlvif, false); if (ret < 0) return ret; diff --git a/trunk/drivers/net/wireless/ti/wlcore/rx.c b/trunk/drivers/net/wireless/ti/wlcore/rx.c index 78200dcacfca..d6a3c6b07827 100644 --- a/trunk/drivers/net/wireless/ti/wlcore/rx.c +++ b/trunk/drivers/net/wireless/ti/wlcore/rx.c @@ -186,7 +186,6 @@ static int wl1271_rx_handle_data(struct wl1271 *wl, u8 *data, u32 length, is_data = 1; wl1271_rx_status(wl, desc, IEEE80211_SKB_RXCB(skb), beacon); - wlcore_hw_set_rx_csum(wl, desc, skb); seq_num = (le16_to_cpu(hdr->seq_ctrl) & IEEE80211_SCTL_SEQ) >> 4; wl1271_debug(DEBUG_RX, "rx skb 0x%p: %d B %s seq %d hlid %d", skb, @@ -200,12 +199,12 @@ static int wl1271_rx_handle_data(struct wl1271 *wl, u8 *data, u32 length, return is_data; } -void wl12xx_rx(struct wl1271 *wl, struct wl_fw_status_1 *status) +void wl12xx_rx(struct wl1271 *wl, struct wl_fw_status *status) { unsigned long active_hlids[BITS_TO_LONGS(WL12XX_MAX_LINKS)] = {0}; u32 buf_size; - u32 fw_rx_counter = status->fw_rx_counter % wl->num_rx_desc; - u32 drv_rx_counter = wl->rx_counter % wl->num_rx_desc; + u32 fw_rx_counter = status->fw_rx_counter & NUM_RX_PKT_DESC_MOD_MASK; + u32 drv_rx_counter = wl->rx_counter & NUM_RX_PKT_DESC_MOD_MASK; u32 rx_counter; u32 pkt_len, align_pkt_len; u32 pkt_offset, des; @@ -224,7 +223,7 @@ void wl12xx_rx(struct wl1271 *wl, struct wl_fw_status_1 *status) break; buf_size += align_pkt_len; rx_counter++; - rx_counter %= wl->num_rx_desc; + rx_counter &= NUM_RX_PKT_DESC_MOD_MASK; } if (buf_size == 0) { @@ -264,7 +263,7 @@ void wl12xx_rx(struct wl1271 *wl, struct wl_fw_status_1 *status) wl->rx_counter++; drv_rx_counter++; - drv_rx_counter %= wl->num_rx_desc; + drv_rx_counter &= NUM_RX_PKT_DESC_MOD_MASK; pkt_offset += wlcore_rx_get_align_buf_size(wl, pkt_len); } } diff --git a/trunk/drivers/net/wireless/ti/wlcore/rx.h b/trunk/drivers/net/wireless/ti/wlcore/rx.h index 9be780179456..e9a162a864ca 100644 --- a/trunk/drivers/net/wireless/ti/wlcore/rx.h +++ b/trunk/drivers/net/wireless/ti/wlcore/rx.h @@ -38,6 +38,8 @@ #define RX_DESC_PACKETID_SHIFT 11 #define RX_MAX_PACKET_ID 3 +#define NUM_RX_PKT_DESC_MOD_MASK 7 + #define RX_DESC_VALID_FCS 0x0001 #define RX_DESC_MATCH_RXADDR1 0x0002 #define RX_DESC_MCAST 0x0004 @@ -100,9 +102,6 @@ /* If set, the start of IP payload is not 4 bytes aligned */ #define RX_BUF_UNALIGNED_PAYLOAD BIT(20) -/* If set, the buffer was padded by the FW to be 4 bytes aligned */ -#define RX_BUF_PADDED_PAYLOAD BIT(30) - /* Describes the alignment state of a Rx buffer */ enum wl_rx_buf_align { WLCORE_RX_BUF_ALIGNED, @@ -137,7 +136,7 @@ struct wl1271_rx_descriptor { u8 reserved; } __packed; -void wl12xx_rx(struct wl1271 *wl, struct wl_fw_status_1 *status); +void wl12xx_rx(struct wl1271 *wl, struct wl_fw_status *status); u8 wl1271_rate_to_idx(int rate, enum ieee80211_band band); int wl1271_rx_filter_enable(struct wl1271 *wl, int index, bool enable, diff --git a/trunk/drivers/net/wireless/ti/wlcore/scan.c b/trunk/drivers/net/wireless/ti/wlcore/scan.c index d9daed53ceb7..ade21a011c45 100644 --- a/trunk/drivers/net/wireless/ti/wlcore/scan.c +++ b/trunk/drivers/net/wireless/ti/wlcore/scan.c @@ -411,8 +411,7 @@ wl1271_scan_get_sched_scan_channels(struct wl1271 *wl, struct cfg80211_sched_scan_request *req, struct conn_scan_ch_params *channels, u32 band, bool radar, bool passive, - int start, int max_channels, - u8 *n_pactive_ch) + int start, int max_channels) { struct conf_sched_scan_settings *c = &wl->conf.sched_scan; int i, j; @@ -480,23 +479,6 @@ wl1271_scan_get_sched_scan_channels(struct wl1271 *wl, channels[j].tx_power_att = req->channels[i]->max_power; channels[j].channel = req->channels[i]->hw_value; - if ((band == IEEE80211_BAND_2GHZ) && - (channels[j].channel >= 12) && - (channels[j].channel <= 14) && - (flags & IEEE80211_CHAN_PASSIVE_SCAN) && - !force_passive) { - /* pactive channels treated as DFS */ - channels[j].flags = SCAN_CHANNEL_FLAGS_DFS; - - /* - * n_pactive_ch is counted down from the end of - * the passive channel list - */ - (*n_pactive_ch)++; - wl1271_debug(DEBUG_SCAN, "n_pactive_ch = %d", - *n_pactive_ch); - } - j++; } } @@ -509,47 +491,38 @@ wl1271_scan_sched_scan_channels(struct wl1271 *wl, struct cfg80211_sched_scan_request *req, struct wl1271_cmd_sched_scan_config *cfg) { - u8 n_pactive_ch = 0; - cfg->passive[0] = wl1271_scan_get_sched_scan_channels(wl, req, cfg->channels_2, IEEE80211_BAND_2GHZ, false, true, 0, - MAX_CHANNELS_2GHZ, - &n_pactive_ch); + MAX_CHANNELS_2GHZ); cfg->active[0] = wl1271_scan_get_sched_scan_channels(wl, req, cfg->channels_2, IEEE80211_BAND_2GHZ, false, false, cfg->passive[0], - MAX_CHANNELS_2GHZ, - &n_pactive_ch); + MAX_CHANNELS_2GHZ); cfg->passive[1] = wl1271_scan_get_sched_scan_channels(wl, req, cfg->channels_5, IEEE80211_BAND_5GHZ, false, true, 0, - MAX_CHANNELS_5GHZ, - &n_pactive_ch); + MAX_CHANNELS_5GHZ); cfg->dfs = wl1271_scan_get_sched_scan_channels(wl, req, cfg->channels_5, IEEE80211_BAND_5GHZ, true, true, cfg->passive[1], - MAX_CHANNELS_5GHZ, - &n_pactive_ch); + MAX_CHANNELS_5GHZ); cfg->active[1] = wl1271_scan_get_sched_scan_channels(wl, req, cfg->channels_5, IEEE80211_BAND_5GHZ, false, false, cfg->passive[1] + cfg->dfs, - MAX_CHANNELS_5GHZ, - &n_pactive_ch); + MAX_CHANNELS_5GHZ); /* 802.11j channels are not supported yet */ cfg->passive[2] = 0; cfg->active[2] = 0; - cfg->n_pactive_ch = n_pactive_ch; - wl1271_debug(DEBUG_SCAN, " 2.4GHz: active %d passive %d", cfg->active[0], cfg->passive[0]); wl1271_debug(DEBUG_SCAN, " 5GHz: active %d passive %d", @@ -564,7 +537,6 @@ wl1271_scan_sched_scan_channels(struct wl1271 *wl, /* Returns the scan type to be used or a negative value on error */ static int wl12xx_scan_sched_scan_ssid_list(struct wl1271 *wl, - struct wl12xx_vif *wlvif, struct cfg80211_sched_scan_request *req) { struct wl1271_cmd_sched_scan_ssid_list *cmd = NULL; @@ -593,7 +565,6 @@ wl12xx_scan_sched_scan_ssid_list(struct wl1271 *wl, goto out; } - cmd->role_id = wlvif->dev_role_id; if (!n_match_ssids) { /* No filter, with ssids */ type = SCAN_SSID_FILTER_DISABLED; @@ -632,9 +603,7 @@ wl12xx_scan_sched_scan_ssid_list(struct wl1271 *wl, continue; for (j = 0; j < cmd->n_ssids; j++) - if ((req->ssids[i].ssid_len == - req->ssids[j].ssid_len) && - !memcmp(req->ssids[i].ssid, + if (!memcmp(req->ssids[i].ssid, cmd->ssids[j].ssid, req->ssids[i].ssid_len)) { cmd->ssids[j].type = @@ -683,7 +652,6 @@ int wl1271_scan_sched_scan_config(struct wl1271 *wl, if (!cfg) return -ENOMEM; - cfg->role_id = wlvif->dev_role_id; cfg->rssi_threshold = c->rssi_threshold; cfg->snr_threshold = c->snr_threshold; cfg->n_probe_reqs = c->num_probe_reqs; @@ -701,7 +669,7 @@ int wl1271_scan_sched_scan_config(struct wl1271 *wl, cfg->intervals[i] = cpu_to_le32(req->interval); cfg->ssid_len = 0; - ret = wl12xx_scan_sched_scan_ssid_list(wl, wlvif, req); + ret = wl12xx_scan_sched_scan_ssid_list(wl, req); if (ret < 0) goto out; @@ -773,7 +741,6 @@ int wl1271_scan_sched_scan_start(struct wl1271 *wl, struct wl12xx_vif *wlvif) if (!start) return -ENOMEM; - start->role_id = wlvif->dev_role_id; start->tag = WL1271_SCAN_DEFAULT_TAG; ret = wl1271_cmd_send(wl, CMD_START_PERIODIC_SCAN, start, @@ -795,7 +762,7 @@ void wl1271_scan_sched_scan_results(struct wl1271 *wl) ieee80211_sched_scan_results(wl->hw); } -void wl1271_scan_sched_scan_stop(struct wl1271 *wl, struct wl12xx_vif *wlvif) +void wl1271_scan_sched_scan_stop(struct wl1271 *wl) { struct wl1271_cmd_sched_scan_stop *stop; int ret = 0; @@ -809,7 +776,6 @@ void wl1271_scan_sched_scan_stop(struct wl1271 *wl, struct wl12xx_vif *wlvif) return; } - stop->role_id = wlvif->dev_role_id; stop->tag = WL1271_SCAN_DEFAULT_TAG; ret = wl1271_cmd_send(wl, CMD_STOP_PERIODIC_SCAN, stop, diff --git a/trunk/drivers/net/wireless/ti/wlcore/scan.h b/trunk/drivers/net/wireless/ti/wlcore/scan.h index 29f3c8d6b046..81ee36ac2078 100644 --- a/trunk/drivers/net/wireless/ti/wlcore/scan.h +++ b/trunk/drivers/net/wireless/ti/wlcore/scan.h @@ -40,7 +40,7 @@ int wl1271_scan_sched_scan_config(struct wl1271 *wl, struct cfg80211_sched_scan_request *req, struct ieee80211_sched_scan_ies *ies); int wl1271_scan_sched_scan_start(struct wl1271 *wl, struct wl12xx_vif *wlvif); -void wl1271_scan_sched_scan_stop(struct wl1271 *wl, struct wl12xx_vif *wlvif); +void wl1271_scan_sched_scan_stop(struct wl1271 *wl); void wl1271_scan_sched_scan_results(struct wl1271 *wl); #define WL1271_SCAN_MAX_CHANNELS 24 @@ -142,8 +142,7 @@ enum { SCAN_BSS_TYPE_ANY, }; -#define SCAN_CHANNEL_FLAGS_DFS BIT(0) /* channel is passive until an - activity is detected on it */ +#define SCAN_CHANNEL_FLAGS_DFS BIT(0) #define SCAN_CHANNEL_FLAGS_DFS_ENABLED BIT(1) struct conn_scan_ch_params { @@ -186,10 +185,7 @@ struct wl1271_cmd_sched_scan_config { u8 dfs; - u8 n_pactive_ch; /* number of pactive (passive until fw detects energy) - channels in BG band */ - u8 role_id; - u8 padding[1]; + u8 padding[3]; struct conn_scan_ch_params channels_2[MAX_CHANNELS_2GHZ]; struct conn_scan_ch_params channels_5[MAX_CHANNELS_5GHZ]; @@ -216,24 +212,21 @@ struct wl1271_cmd_sched_scan_ssid_list { u8 n_ssids; struct wl1271_ssid ssids[SCHED_SCAN_MAX_SSIDS]; - u8 role_id; - u8 padding[2]; + u8 padding[3]; } __packed; struct wl1271_cmd_sched_scan_start { struct wl1271_cmd_header header; u8 tag; - u8 role_id; - u8 padding[2]; + u8 padding[3]; } __packed; struct wl1271_cmd_sched_scan_stop { struct wl1271_cmd_header header; u8 tag; - u8 role_id; - u8 padding[2]; + u8 padding[3]; } __packed; diff --git a/trunk/drivers/net/wireless/ti/wlcore/sdio.c b/trunk/drivers/net/wireless/ti/wlcore/sdio.c index c67ec482e445..0a72347cfc4c 100644 --- a/trunk/drivers/net/wireless/ti/wlcore/sdio.c +++ b/trunk/drivers/net/wireless/ti/wlcore/sdio.c @@ -25,7 +25,6 @@ #include #include #include -#include #include #include #include @@ -33,7 +32,6 @@ #include #include #include -#include #include "wlcore.h" #include "wl12xx_80211.h" @@ -47,8 +45,6 @@ #define SDIO_DEVICE_ID_TI_WL1271 0x4076 #endif -static bool dump = false; - struct wl12xx_sdio_glue { struct device *dev; struct platform_device *core; @@ -80,13 +76,6 @@ static void wl12xx_sdio_raw_read(struct device *child, int addr, void *buf, sdio_claim_host(func); - if (unlikely(dump)) { - printk(KERN_DEBUG "wlcore_sdio: READ from 0x%04x\n", addr); - print_hex_dump(KERN_DEBUG, "wlcore_sdio: READ ", - DUMP_PREFIX_OFFSET, 16, 1, - buf, len, false); - } - if (unlikely(addr == HW_ACCESS_ELP_CTRL_REG)) { ((u8 *)buf)[0] = sdio_f0_readb(func, addr, &ret); dev_dbg(child->parent, "sdio read 52 addr 0x%x, byte 0x%02x\n", @@ -116,13 +105,6 @@ static void wl12xx_sdio_raw_write(struct device *child, int addr, void *buf, sdio_claim_host(func); - if (unlikely(dump)) { - printk(KERN_DEBUG "wlcore_sdio: WRITE to 0x%04x\n", addr); - print_hex_dump(KERN_DEBUG, "wlcore_sdio: WRITE ", - DUMP_PREFIX_OFFSET, 16, 1, - buf, len, false); - } - if (unlikely(addr == HW_ACCESS_ELP_CTRL_REG)) { sdio_f0_writeb(func, ((u8 *)buf)[0], addr, &ret); dev_dbg(child->parent, "sdio write 52 addr 0x%x, byte 0x%02x\n", @@ -214,7 +196,6 @@ static int __devinit wl1271_probe(struct sdio_func *func, struct resource res[1]; mmc_pm_flag_t mmcflags; int ret = -ENOMEM; - const char *chip_family; /* We are only able to handle the wlan function */ if (func->num != 0x02) @@ -255,18 +236,7 @@ static int __devinit wl1271_probe(struct sdio_func *func, /* Tell PM core that we don't need the card to be powered now */ pm_runtime_put_noidle(&func->dev); - /* - * Due to a hardware bug, we can't differentiate wl18xx from - * wl12xx, because both report the same device ID. The only - * way to differentiate is by checking the SDIO revision, - * which is 3.00 on the wl18xx chips. - */ - if (func->card->cccr.sdio_vsn == SDIO_SDIO_REV_3_00) - chip_family = "wl18xx"; - else - chip_family = "wl12xx"; - - glue->core = platform_device_alloc(chip_family, -1); + glue->core = platform_device_alloc("wl12xx", -1); if (!glue->core) { dev_err(glue->dev, "can't allocate platform_device"); ret = -ENOMEM; @@ -397,9 +367,6 @@ static void __exit wl1271_exit(void) module_init(wl1271_init); module_exit(wl1271_exit); -module_param(dump, bool, S_IRUSR | S_IWUSR); -MODULE_PARM_DESC(dump, "Enable sdio read/write dumps."); - MODULE_LICENSE("GPL"); MODULE_AUTHOR("Luciano Coelho "); MODULE_AUTHOR("Juuso Oikarinen "); diff --git a/trunk/drivers/net/wireless/ti/wlcore/tx.c b/trunk/drivers/net/wireless/ti/wlcore/tx.c index 6983e7a829d0..6893bc207994 100644 --- a/trunk/drivers/net/wireless/ti/wlcore/tx.c +++ b/trunk/drivers/net/wireless/ti/wlcore/tx.c @@ -72,7 +72,7 @@ static int wl1271_alloc_tx_id(struct wl1271 *wl, struct sk_buff *skb) return id; } -void wl1271_free_tx_id(struct wl1271 *wl, int id) +static void wl1271_free_tx_id(struct wl1271 *wl, int id) { if (__test_and_clear_bit(id, wl->tx_frames_map)) { if (unlikely(wl->tx_frames_cnt == wl->num_tx_desc)) @@ -82,7 +82,6 @@ void wl1271_free_tx_id(struct wl1271 *wl, int id) wl->tx_frames_cnt--; } } -EXPORT_SYMBOL(wl1271_free_tx_id); static void wl1271_tx_ap_update_inconnection_sta(struct wl1271 *wl, struct sk_buff *skb) @@ -128,7 +127,6 @@ bool wl12xx_is_dummy_packet(struct wl1271 *wl, struct sk_buff *skb) { return wl->dummy_packet == skb; } -EXPORT_SYMBOL(wl12xx_is_dummy_packet); u8 wl12xx_tx_get_hlid_ap(struct wl1271 *wl, struct wl12xx_vif *wlvif, struct sk_buff *skb) @@ -148,10 +146,10 @@ u8 wl12xx_tx_get_hlid_ap(struct wl1271 *wl, struct wl12xx_vif *wlvif, return wl->system_hlid; hdr = (struct ieee80211_hdr *)skb->data; - if (is_multicast_ether_addr(ieee80211_get_DA(hdr))) - return wlvif->ap.bcast_hlid; - else + if (ieee80211_is_mgmt(hdr->frame_control)) return wlvif->ap.global_hlid; + else + return wlvif->ap.bcast_hlid; } } @@ -178,34 +176,37 @@ u8 wl12xx_tx_get_hlid(struct wl1271 *wl, struct wl12xx_vif *wlvif, unsigned int wlcore_calc_packet_alignment(struct wl1271 *wl, unsigned int packet_length) { - if ((wl->quirks & WLCORE_QUIRK_TX_PAD_LAST_FRAME) || - !(wl->quirks & WLCORE_QUIRK_TX_BLOCKSIZE_ALIGN)) - return ALIGN(packet_length, WL1271_TX_ALIGN_TO); - else + if (wl->quirks & WLCORE_QUIRK_TX_BLOCKSIZE_ALIGN) return ALIGN(packet_length, WL12XX_BUS_BLOCK_SIZE); + else + return ALIGN(packet_length, WL1271_TX_ALIGN_TO); } EXPORT_SYMBOL(wlcore_calc_packet_alignment); static int wl1271_tx_allocate(struct wl1271 *wl, struct wl12xx_vif *wlvif, struct sk_buff *skb, u32 extra, u32 buf_offset, - u8 hlid, bool is_gem) + u8 hlid) { struct wl1271_tx_hw_descr *desc; u32 total_len = skb->len + sizeof(struct wl1271_tx_hw_descr) + extra; u32 total_blocks; int id, ret = -EBUSY, ac; - u32 spare_blocks; + u32 spare_blocks = wl->normal_tx_spare; + bool is_dummy = false; if (buf_offset + total_len > WL1271_AGGR_BUFFER_SIZE) return -EAGAIN; - spare_blocks = wlcore_hw_get_spare_blocks(wl, is_gem); - /* allocate free identifier for the packet */ id = wl1271_alloc_tx_id(wl, skb); if (id < 0) return id; + if (unlikely(wl12xx_is_dummy_packet(wl, skb))) + is_dummy = true; + else if (wlvif->is_gem) + spare_blocks = wl->gem_tx_spare; + total_blocks = wlcore_hw_calc_tx_blocks(wl, total_len, spare_blocks); if (total_blocks <= wl->tx_blocks_available) { @@ -227,7 +228,7 @@ static int wl1271_tx_allocate(struct wl1271 *wl, struct wl12xx_vif *wlvif, ac = wl1271_tx_get_queue(skb_get_queue_mapping(skb)); wl->tx_allocated_pkts[ac]++; - if (!wl12xx_is_dummy_packet(wl, skb) && wlvif && + if (!is_dummy && wlvif && wlvif->bss_type == BSS_TYPE_AP_BSS && test_bit(hlid, wlvif->ap.sta_hlid_map)) wl->links[hlid].allocated_pkts++; @@ -267,7 +268,6 @@ static void wl1271_tx_fill_hdr(struct wl1271 *wl, struct wl12xx_vif *wlvif, if (extra) { int hdrlen = ieee80211_hdrlen(frame_control); memmove(frame_start, hdr, hdrlen); - skb_set_network_header(skb, skb_network_offset(skb) + extra); } /* configure packet life time */ @@ -330,9 +330,9 @@ static void wl1271_tx_fill_hdr(struct wl1271 *wl, struct wl12xx_vif *wlvif, ieee80211_has_protected(frame_control)) tx_attr |= TX_HW_ATTR_HOST_ENCRYPT; + desc->reserved = 0; desc->tx_attr = cpu_to_le16(tx_attr); - wlcore_hw_set_tx_desc_csum(wl, desc, skb); wlcore_hw_set_tx_desc_data_len(wl, desc, skb); } @@ -346,7 +346,6 @@ static int wl1271_prepare_tx_frame(struct wl1271 *wl, struct wl12xx_vif *wlvif, u32 total_len; u8 hlid; bool is_dummy; - bool is_gem = false; if (!skb) return -EINVAL; @@ -356,8 +355,7 @@ static int wl1271_prepare_tx_frame(struct wl1271 *wl, struct wl12xx_vif *wlvif, /* TODO: handle dummy packets on multi-vifs */ is_dummy = wl12xx_is_dummy_packet(wl, skb); - if ((wl->quirks & WLCORE_QUIRK_TKIP_HEADER_SPACE) && - info->control.hw_key && + if (info->control.hw_key && info->control.hw_key->cipher == WLAN_CIPHER_SUITE_TKIP) extra = WL1271_EXTRA_SPACE_TKIP; @@ -375,8 +373,6 @@ static int wl1271_prepare_tx_frame(struct wl1271 *wl, struct wl12xx_vif *wlvif, return ret; wlvif->default_key = idx; } - - is_gem = (cipher == WL1271_CIPHER_SUITE_GEM); } hlid = wl12xx_tx_get_hlid(wl, wlvif, skb); if (hlid == WL12XX_INVALID_LINK_ID) { @@ -384,8 +380,7 @@ static int wl1271_prepare_tx_frame(struct wl1271 *wl, struct wl12xx_vif *wlvif, return -EINVAL; } - ret = wl1271_tx_allocate(wl, wlvif, skb, extra, buf_offset, hlid, - is_gem); + ret = wl1271_tx_allocate(wl, wlvif, skb, extra, buf_offset, hlid); if (ret < 0) return ret; @@ -430,10 +425,10 @@ u32 wl1271_tx_enabled_rates_get(struct wl1271 *wl, u32 rate_set, rate_set >>= 1; } - /* MCS rates indication are on bits 16 - 31 */ + /* MCS rates indication are on bits 16 - 23 */ rate_set >>= HW_HT_RATES_OFFSET - band->n_bitrates; - for (bit = 0; bit < 16; bit++) { + for (bit = 0; bit < 8; bit++) { if (rate_set & 0x1) enabled_rates |= (CONF_HW_BIT_RATE_MCS_0 << bit); rate_set >>= 1; @@ -444,15 +439,18 @@ u32 wl1271_tx_enabled_rates_get(struct wl1271 *wl, u32 rate_set, void wl1271_handle_tx_low_watermark(struct wl1271 *wl) { + unsigned long flags; int i; for (i = 0; i < NUM_TX_QUEUES; i++) { - if (wlcore_is_queue_stopped_by_reason(wl, i, - WLCORE_QUEUE_STOP_REASON_WATERMARK) && + if (test_bit(i, &wl->stopped_queues_map) && wl->tx_queue_count[i] <= WL1271_TX_QUEUE_LOW_WATERMARK) { /* firmware buffer has space, restart queues */ - wlcore_wake_queue(wl, i, - WLCORE_QUEUE_STOP_REASON_WATERMARK); + spin_lock_irqsave(&wl->wl_lock, flags); + ieee80211_wake_queue(wl->hw, + wl1271_tx_get_mac80211_queue(i)); + clear_bit(i, &wl->stopped_queues_map); + spin_unlock_irqrestore(&wl->wl_lock, flags); } } } @@ -663,7 +661,7 @@ void wl1271_tx_work_locked(struct wl1271 *wl) struct wl12xx_vif *wlvif; struct sk_buff *skb; struct wl1271_tx_hw_descr *desc; - u32 buf_offset = 0, last_len = 0; + u32 buf_offset = 0; bool sent_packets = false; unsigned long active_hlids[BITS_TO_LONGS(WL12XX_MAX_LINKS)] = {0}; int ret; @@ -687,9 +685,6 @@ void wl1271_tx_work_locked(struct wl1271 *wl) * Flush buffer and try again. */ wl1271_skb_queue_head(wl, wlvif, skb); - - buf_offset = wlcore_hw_pre_pkt_send(wl, buf_offset, - last_len); wlcore_write_data(wl, REG_SLV_MEM_DATA, wl->aggr_buf, buf_offset, true); sent_packets = true; @@ -715,8 +710,7 @@ void wl1271_tx_work_locked(struct wl1271 *wl) ieee80211_free_txskb(wl->hw, skb); goto out_ack; } - last_len = ret; - buf_offset += last_len; + buf_offset += ret; wl->tx_packets_count++; if (has_data) { desc = (struct wl1271_tx_hw_descr *) skb->data; @@ -726,7 +720,6 @@ void wl1271_tx_work_locked(struct wl1271 *wl) out_ack: if (buf_offset) { - buf_offset = wlcore_hw_pre_pkt_send(wl, buf_offset, last_len); wlcore_write_data(wl, REG_SLV_MEM_DATA, wl->aggr_buf, buf_offset, true); sent_packets = true; @@ -856,8 +849,7 @@ static void wl1271_tx_complete_packet(struct wl1271 *wl, skb_pull(skb, sizeof(struct wl1271_tx_hw_descr)); /* remove TKIP header space if present */ - if ((wl->quirks & WLCORE_QUIRK_TKIP_HEADER_SPACE) && - info->control.hw_key && + if (info->control.hw_key && info->control.hw_key->cipher == WLAN_CIPHER_SUITE_TKIP) { int hdrlen = ieee80211_get_hdrlen_from_skb(skb); memmove(skb->data + WL1271_EXTRA_SPACE_TKIP, skb->data, @@ -966,7 +958,7 @@ void wl12xx_tx_reset_wlvif(struct wl1271 *wl, struct wl12xx_vif *wlvif) } /* caller must hold wl->mutex and TX must be stopped */ -void wl12xx_tx_reset(struct wl1271 *wl) +void wl12xx_tx_reset(struct wl1271 *wl, bool reset_tx_queues) { int i; struct sk_buff *skb; @@ -981,12 +973,15 @@ void wl12xx_tx_reset(struct wl1271 *wl) wl->tx_queue_count[i] = 0; } + wl->stopped_queues_map = 0; + /* * Make sure the driver is at a consistent state, in case this * function is called from a context other than interface removal. * This call will always wake the TX queues. */ - wl1271_handle_tx_low_watermark(wl); + if (reset_tx_queues) + wl1271_handle_tx_low_watermark(wl); for (i = 0; i < wl->num_tx_desc; i++) { if (wl->tx_frames[i] == NULL) @@ -1003,8 +998,7 @@ void wl12xx_tx_reset(struct wl1271 *wl) */ info = IEEE80211_SKB_CB(skb); skb_pull(skb, sizeof(struct wl1271_tx_hw_descr)); - if ((wl->quirks & WLCORE_QUIRK_TKIP_HEADER_SPACE) && - info->control.hw_key && + if (info->control.hw_key && info->control.hw_key->cipher == WLAN_CIPHER_SUITE_TKIP) { int hdrlen = ieee80211_get_hdrlen_from_skb(skb); @@ -1030,11 +1024,6 @@ void wl1271_tx_flush(struct wl1271 *wl) int i; timeout = jiffies + usecs_to_jiffies(WL1271_TX_FLUSH_TIMEOUT); - /* only one flush should be in progress, for consistent queue state */ - mutex_lock(&wl->flush_mutex); - - wlcore_stop_queues(wl, WLCORE_QUEUE_STOP_REASON_FLUSH); - while (!time_after(jiffies, timeout)) { mutex_lock(&wl->mutex); wl1271_debug(DEBUG_TX, "flushing tx buffer: %d %d", @@ -1043,7 +1032,7 @@ void wl1271_tx_flush(struct wl1271 *wl) if ((wl->tx_frames_cnt == 0) && (wl1271_tx_total_queue_count(wl) == 0)) { mutex_unlock(&wl->mutex); - goto out; + return; } mutex_unlock(&wl->mutex); msleep(1); @@ -1056,12 +1045,7 @@ void wl1271_tx_flush(struct wl1271 *wl) for (i = 0; i < WL12XX_MAX_LINKS; i++) wl1271_tx_reset_link_queues(wl, i); mutex_unlock(&wl->mutex); - -out: - wlcore_wake_queues(wl, WLCORE_QUEUE_STOP_REASON_FLUSH); - mutex_unlock(&wl->flush_mutex); } -EXPORT_SYMBOL_GPL(wl1271_tx_flush); u32 wl1271_tx_min_rate_get(struct wl1271 *wl, u32 rate_set) { @@ -1070,96 +1054,3 @@ u32 wl1271_tx_min_rate_get(struct wl1271 *wl, u32 rate_set) return BIT(__ffs(rate_set)); } - -void wlcore_stop_queue_locked(struct wl1271 *wl, u8 queue, - enum wlcore_queue_stop_reason reason) -{ - bool stopped = !!wl->queue_stop_reasons[queue]; - - /* queue should not be stopped for this reason */ - WARN_ON(test_and_set_bit(reason, &wl->queue_stop_reasons[queue])); - - if (stopped) - return; - - ieee80211_stop_queue(wl->hw, wl1271_tx_get_mac80211_queue(queue)); -} - -void wlcore_stop_queue(struct wl1271 *wl, u8 queue, - enum wlcore_queue_stop_reason reason) -{ - unsigned long flags; - - spin_lock_irqsave(&wl->wl_lock, flags); - wlcore_stop_queue_locked(wl, queue, reason); - spin_unlock_irqrestore(&wl->wl_lock, flags); -} - -void wlcore_wake_queue(struct wl1271 *wl, u8 queue, - enum wlcore_queue_stop_reason reason) -{ - unsigned long flags; - - spin_lock_irqsave(&wl->wl_lock, flags); - - /* queue should not be clear for this reason */ - WARN_ON(!test_and_clear_bit(reason, &wl->queue_stop_reasons[queue])); - - if (wl->queue_stop_reasons[queue]) - goto out; - - ieee80211_wake_queue(wl->hw, wl1271_tx_get_mac80211_queue(queue)); - -out: - spin_unlock_irqrestore(&wl->wl_lock, flags); -} - -void wlcore_stop_queues(struct wl1271 *wl, - enum wlcore_queue_stop_reason reason) -{ - int i; - - for (i = 0; i < NUM_TX_QUEUES; i++) - wlcore_stop_queue(wl, i, reason); -} -EXPORT_SYMBOL_GPL(wlcore_stop_queues); - -void wlcore_wake_queues(struct wl1271 *wl, - enum wlcore_queue_stop_reason reason) -{ - int i; - - for (i = 0; i < NUM_TX_QUEUES; i++) - wlcore_wake_queue(wl, i, reason); -} -EXPORT_SYMBOL_GPL(wlcore_wake_queues); - -void wlcore_reset_stopped_queues(struct wl1271 *wl) -{ - int i; - unsigned long flags; - - spin_lock_irqsave(&wl->wl_lock, flags); - - for (i = 0; i < NUM_TX_QUEUES; i++) { - if (!wl->queue_stop_reasons[i]) - continue; - - wl->queue_stop_reasons[i] = 0; - ieee80211_wake_queue(wl->hw, - wl1271_tx_get_mac80211_queue(i)); - } - - spin_unlock_irqrestore(&wl->wl_lock, flags); -} - -bool wlcore_is_queue_stopped_by_reason(struct wl1271 *wl, u8 queue, - enum wlcore_queue_stop_reason reason) -{ - return test_bit(reason, &wl->queue_stop_reasons[queue]); -} - -bool wlcore_is_queue_stopped(struct wl1271 *wl, u8 queue) -{ - return !!wl->queue_stop_reasons[queue]; -} diff --git a/trunk/drivers/net/wireless/ti/wlcore/tx.h b/trunk/drivers/net/wireless/ti/wlcore/tx.h index fa4be1b91135..2fd6e5dc6f75 100644 --- a/trunk/drivers/net/wireless/ti/wlcore/tx.h +++ b/trunk/drivers/net/wireless/ti/wlcore/tx.h @@ -85,19 +85,6 @@ struct wl128x_tx_mem { u8 extra_bytes; } __packed; -struct wl18xx_tx_mem { - /* - * Total number of memory blocks allocated by the host for - * this packet. - */ - u8 total_mem_blocks; - - /* - * control bits - */ - u8 ctrl; -} __packed; - /* * On wl128x based devices, when TX packets are aggregated, each packet * size must be aligned to the SDIO block size. The maximum block size @@ -113,7 +100,6 @@ struct wl1271_tx_hw_descr { union { struct wl127x_tx_mem wl127x_mem; struct wl128x_tx_mem wl128x_mem; - struct wl18xx_tx_mem wl18xx_mem; } __packed; /* Device time (in us) when the packet arrived to the driver */ __le32 start_time; @@ -130,16 +116,7 @@ struct wl1271_tx_hw_descr { u8 tid; /* host link ID (HLID) */ u8 hlid; - - union { - u8 wl12xx_reserved; - - /* - * bit 0 -> 0 = udp, 1 = tcp - * bit 1:7 -> IP header offset - */ - u8 wl18xx_checksum_data; - } __packed; + u8 reserved; } __packed; enum wl1271_tx_hw_res_status { @@ -184,13 +161,6 @@ struct wl1271_tx_hw_res_if { struct wl1271_tx_hw_res_descr tx_results_queue[TX_HW_RESULT_QUEUE_LEN]; } __packed; -enum wlcore_queue_stop_reason { - WLCORE_QUEUE_STOP_REASON_WATERMARK, - WLCORE_QUEUE_STOP_REASON_FW_RESTART, - WLCORE_QUEUE_STOP_REASON_FLUSH, - WLCORE_QUEUE_STOP_REASON_SPARE_BLK, /* 18xx specific */ -}; - static inline int wl1271_tx_get_queue(int queue) { switch (queue) { @@ -237,7 +207,7 @@ void wl1271_tx_work(struct work_struct *work); void wl1271_tx_work_locked(struct wl1271 *wl); void wl1271_tx_complete(struct wl1271 *wl); void wl12xx_tx_reset_wlvif(struct wl1271 *wl, struct wl12xx_vif *wlvif); -void wl12xx_tx_reset(struct wl1271 *wl); +void wl12xx_tx_reset(struct wl1271 *wl, bool reset_tx_queues); void wl1271_tx_flush(struct wl1271 *wl); u8 wlcore_rate_to_idx(struct wl1271 *wl, u8 rate, enum ieee80211_band band); u32 wl1271_tx_enabled_rates_get(struct wl1271 *wl, u32 rate_set, @@ -253,21 +223,6 @@ bool wl12xx_is_dummy_packet(struct wl1271 *wl, struct sk_buff *skb); void wl12xx_rearm_rx_streaming(struct wl1271 *wl, unsigned long *active_hlids); unsigned int wlcore_calc_packet_alignment(struct wl1271 *wl, unsigned int packet_length); -void wl1271_free_tx_id(struct wl1271 *wl, int id); -void wlcore_stop_queue_locked(struct wl1271 *wl, u8 queue, - enum wlcore_queue_stop_reason reason); -void wlcore_stop_queue(struct wl1271 *wl, u8 queue, - enum wlcore_queue_stop_reason reason); -void wlcore_wake_queue(struct wl1271 *wl, u8 queue, - enum wlcore_queue_stop_reason reason); -void wlcore_stop_queues(struct wl1271 *wl, - enum wlcore_queue_stop_reason reason); -void wlcore_wake_queues(struct wl1271 *wl, - enum wlcore_queue_stop_reason reason); -void wlcore_reset_stopped_queues(struct wl1271 *wl); -bool wlcore_is_queue_stopped_by_reason(struct wl1271 *wl, u8 queue, - enum wlcore_queue_stop_reason reason); -bool wlcore_is_queue_stopped(struct wl1271 *wl, u8 queue); /* from main.c */ void wl1271_free_sta(struct wl1271 *wl, struct wl12xx_vif *wlvif, u8 hlid); diff --git a/trunk/drivers/net/wireless/ti/wlcore/wlcore_i.h b/trunk/drivers/net/wireless/ti/wlcore/wl12xx.h similarity index 95% rename from trunk/drivers/net/wireless/ti/wlcore/wlcore_i.h rename to trunk/drivers/net/wireless/ti/wlcore/wl12xx.h index 8260b1e9288a..f12bdf745180 100644 --- a/trunk/drivers/net/wireless/ti/wlcore/wlcore_i.h +++ b/trunk/drivers/net/wireless/ti/wlcore/wl12xx.h @@ -22,8 +22,8 @@ * */ -#ifndef __WLCORE_I_H__ -#define __WLCORE_I_H__ +#ifndef __WL12XX_H__ +#define __WL12XX_H__ #include #include @@ -89,7 +89,7 @@ #define WL1271_AP_BSS_INDEX 0 #define WL1271_AP_DEF_BEACON_EXP 20 -#define WL1271_AGGR_BUFFER_SIZE (5 * PAGE_SIZE) +#define WL1271_AGGR_BUFFER_SIZE (4 * PAGE_SIZE) enum wl1271_state { WL1271_STATE_OFF, @@ -132,7 +132,16 @@ struct wl1271_chip { unsigned int fw_ver[NUM_FW_VER]; }; +struct wl1271_stats { + struct acx_statistics *fw_stats; + unsigned long fw_stats_update; + + unsigned int retry_count; + unsigned int excessive_retries; +}; + #define NUM_TX_QUEUES 4 +#define NUM_RX_PKT_DESC 8 #define AP_MAX_STATIONS 8 @@ -150,26 +159,13 @@ struct wl_fw_packet_counters { } __packed; /* FW status registers */ -struct wl_fw_status_1 { +struct wl_fw_status { __le32 intr; u8 fw_rx_counter; u8 drv_rx_counter; u8 reserved; u8 tx_results_counter; - __le32 rx_pkt_descs[0]; -} __packed; - -/* - * Each HW arch has a different number of Rx descriptors. - * The length of the status depends on it, since it holds an array - * of descriptors. - */ -#define WLCORE_FW_STATUS_1_LEN(num_rx_desc) \ - (sizeof(struct wl_fw_status_1) + \ - (sizeof(((struct wl_fw_status_1 *)0)->rx_pkt_descs[0])) * \ - num_rx_desc) - -struct wl_fw_status_2 { + __le32 rx_pkt_descs[NUM_RX_PKT_DESC]; __le32 fw_localtime; /* @@ -198,6 +194,11 @@ struct wl_fw_status_2 { u8 priv[0]; } __packed; +struct wl1271_rx_mem_pool_addr { + u32 addr; + u32 addr_extra; +}; + #define WL1271_MAX_CHANNELS 64 struct wl1271_scan { struct cfg80211_scan_request *req; @@ -366,7 +367,6 @@ struct wl12xx_vif { /* The current band */ enum ieee80211_band band; int channel; - enum nl80211_channel_type channel_type; u32 bitrate_masks[IEEE80211_NUM_BANDS]; u32 basic_rate_set; @@ -417,6 +417,9 @@ struct wl12xx_vif { struct work_struct rx_streaming_disable_work; struct timer_list rx_streaming_timer; + /* does the current role use GEM for encryption (AP or STA) */ + bool is_gem; + /* * This struct must be last! * data that has to be saved acrossed reconfigs (e.g. recovery) @@ -498,8 +501,7 @@ void wl1271_rx_filter_flatten_fields(struct wl12xx_rx_filter *filter, /* Macros to handle wl1271.sta_rate_set */ #define HW_BG_RATES_MASK 0xffff #define HW_HT_RATES_OFFSET 16 -#define HW_MIMO_RATES_OFFSET 24 #define WL12XX_HW_BLOCK_SIZE 256 -#endif /* __WLCORE_I_H__ */ +#endif diff --git a/trunk/drivers/net/wireless/ti/wlcore/wlcore.h b/trunk/drivers/net/wireless/ti/wlcore/wlcore.h index 761a72f4b8d1..0b3f0b586f4b 100644 --- a/trunk/drivers/net/wireless/ti/wlcore/wlcore.h +++ b/trunk/drivers/net/wireless/ti/wlcore/wlcore.h @@ -24,9 +24,8 @@ #include -#include "wlcore_i.h" +#include "wl12xx.h" #include "event.h" -#include "boot.h" /* The maximum number of Tx descriptors in all chip families */ #define WLCORE_MAX_TX_DESCRIPTORS 32 @@ -34,13 +33,11 @@ /* forward declaration */ struct wl1271_tx_hw_descr; enum wl_rx_buf_align; -struct wl1271_rx_descriptor; struct wlcore_ops { int (*identify_chip)(struct wl1271 *wl); int (*identify_fw)(struct wl1271 *wl); int (*boot)(struct wl1271 *wl); - int (*plt_init)(struct wl1271 *wl); void (*trigger_cmd)(struct wl1271 *wl, int cmd_box_addr, void *buf, size_t len); void (*ack_event)(struct wl1271 *wl); @@ -64,23 +61,6 @@ struct wlcore_ops { struct wl12xx_vif *wlvif); s8 (*get_pg_ver)(struct wl1271 *wl); void (*get_mac)(struct wl1271 *wl); - void (*set_tx_desc_csum)(struct wl1271 *wl, - struct wl1271_tx_hw_descr *desc, - struct sk_buff *skb); - void (*set_rx_csum)(struct wl1271 *wl, - struct wl1271_rx_descriptor *desc, - struct sk_buff *skb); - u32 (*ap_get_mimo_wide_rate_mask)(struct wl1271 *wl, - struct wl12xx_vif *wlvif); - int (*debugfs_init)(struct wl1271 *wl, struct dentry *rootdir); - int (*handle_static_data)(struct wl1271 *wl, - struct wl1271_static_data *static_data); - int (*get_spare_blocks)(struct wl1271 *wl, bool is_gem); - int (*set_key)(struct wl1271 *wl, enum set_key_cmd cmd, - struct ieee80211_vif *vif, - struct ieee80211_sta *sta, - struct ieee80211_key_conf *key_conf); - u32 (*pre_pkt_send)(struct wl1271 *wl, u32 buf_offset, u32 last_len); }; enum wlcore_partitions { @@ -129,15 +109,6 @@ enum wlcore_registers { REG_TABLE_LEN, }; -struct wl1271_stats { - void *fw_stats; - unsigned long fw_stats_update; - size_t fw_stats_len; - - unsigned int retry_count; - unsigned int excessive_retries; -}; - struct wl1271 { struct ieee80211_hw *hw; bool mac80211_registered; @@ -150,6 +121,7 @@ struct wl1271 { void (*set_power)(bool enable); int irq; + int ref_clock; spinlock_t wl_lock; @@ -214,7 +186,7 @@ struct wl1271 { /* Frames scheduled for transmission, not handled yet */ int tx_queue_count[NUM_TX_QUEUES]; - unsigned long queue_stop_reasons[NUM_TX_QUEUES]; + long stopped_queues_map; /* Frames received, not handled yet by mac80211 */ struct sk_buff_head deferred_rx_queue; @@ -233,6 +205,9 @@ struct wl1271 { /* FW Rx counter */ u32 rx_counter; + /* Rx memory pool address */ + struct wl1271_rx_mem_pool_addr rx_mem_pool_addr; + /* Intermediate buffer, used for packet aggregation */ u8 *aggr_buf; @@ -253,7 +228,6 @@ struct wl1271 { /* Hardware recovery work */ struct work_struct recovery_work; - bool watchdog_recovery; /* Pointer that holds DMA-friendly block for the mailbox */ struct event_mailbox *mbox; @@ -289,8 +263,7 @@ struct wl1271 { u32 buffer_cmd; u32 buffer_busyword[WL1271_BUSY_WORD_CNT]; - struct wl_fw_status_1 *fw_status_1; - struct wl_fw_status_2 *fw_status_2; + struct wl_fw_status *fw_status; struct wl1271_tx_hw_res_if *tx_res_if; /* Current chipset configuration */ @@ -306,6 +279,8 @@ struct wl1271 { /* bands supported by this instance of wl12xx */ struct ieee80211_supported_band bands[IEEE80211_NUM_BANDS]; + int tcxo_clock; + /* * wowlan trigger was configured during suspend. * (currently, only "ANY" trigger is supported) @@ -358,8 +333,10 @@ struct wl1271 { /* number of TX descriptors the HW supports. */ u32 num_tx_desc; - /* number of RX descriptors the HW supports. */ - u32 num_rx_desc; + + /* spare Tx blocks for normal/GEM operating modes */ + u32 normal_tx_spare; + u32 gem_tx_spare; /* translate HW Tx rates to standard rate-indices */ const u8 **band_rate_to_idx; @@ -371,32 +348,19 @@ struct wl1271 { u8 hw_min_ht_rate; /* HW HT (11n) capabilities */ - struct ieee80211_sta_ht_cap ht_cap[IEEE80211_NUM_BANDS]; + struct ieee80211_sta_ht_cap ht_cap; /* size of the private FW status data */ size_t fw_status_priv_len; /* RX Data filter rule state - enabled/disabled */ bool rx_filter_enabled[WL1271_MAX_RX_FILTERS]; - - /* size of the private static data */ - size_t static_data_priv_len; - - /* the current channel type */ - enum nl80211_channel_type channel_type; - - /* mutex for protecting the tx_flush function */ - struct mutex flush_mutex; }; int __devinit wlcore_probe(struct wl1271 *wl, struct platform_device *pdev); int __devexit wlcore_remove(struct platform_device *pdev); struct ieee80211_hw *wlcore_alloc_hw(size_t priv_size); int wlcore_free_hw(struct wl1271 *wl); -int wlcore_set_key(struct wl1271 *wl, enum set_key_cmd cmd, - struct ieee80211_vif *vif, - struct ieee80211_sta *sta, - struct ieee80211_key_conf *key_conf); /* Firmware image load chunk size */ #define CHUNK_SIZE 16384 @@ -421,12 +385,6 @@ int wlcore_set_key(struct wl1271 *wl, enum set_key_cmd cmd, /* Some firmwares may not support ELP */ #define WLCORE_QUIRK_NO_ELP BIT(6) -/* pad only the last frame in the aggregate buffer */ -#define WLCORE_QUIRK_TX_PAD_LAST_FRAME BIT(7) - -/* extra header space is required for TKIP */ -#define WLCORE_QUIRK_TKIP_HEADER_SPACE BIT(8) - /* TODO: move to the lower drivers when all usages are abstracted */ #define CHIP_ID_1271_PG10 (0x4030101) #define CHIP_ID_1271_PG20 (0x4030111) diff --git a/trunk/drivers/nfc/pn533.c b/trunk/drivers/nfc/pn533.c index 9ac829e22e73..19110f0eb15f 100644 --- a/trunk/drivers/nfc/pn533.c +++ b/trunk/drivers/nfc/pn533.c @@ -45,9 +45,6 @@ static const struct usb_device_id pn533_table[] = { }; MODULE_DEVICE_TABLE(usb, pn533_table); -/* How much time we spend listening for initiators */ -#define PN533_LISTEN_TIME 2 - /* frame definitions */ #define PN533_FRAME_TAIL_SIZE 2 #define PN533_FRAME_SIZE(f) (sizeof(struct pn533_frame) + f->datalen + \ @@ -77,10 +74,6 @@ MODULE_DEVICE_TABLE(usb, pn533_table); #define PN533_CMD_IN_RELEASE 0x52 #define PN533_CMD_IN_JUMP_FOR_DEP 0x56 -#define PN533_CMD_TG_INIT_AS_TARGET 0x8c -#define PN533_CMD_TG_GET_DATA 0x86 -#define PN533_CMD_TG_SET_DATA 0x8e - #define PN533_CMD_RESPONSE(cmd) (cmd + 1) /* PN533 Return codes */ @@ -88,9 +81,6 @@ MODULE_DEVICE_TABLE(usb, pn533_table); #define PN533_CMD_MI_MASK 0x40 #define PN533_CMD_RET_SUCCESS 0x00 -/* PN533 status codes */ -#define PN533_STATUS_TARGET_RELEASED 0x29 - struct pn533; typedef int (*pn533_cmd_complete_t) (struct pn533 *dev, void *arg, @@ -107,14 +97,8 @@ struct pn533_fw_version { }; /* PN533_CMD_RF_CONFIGURATION */ -#define PN533_CFGITEM_TIMING 0x02 #define PN533_CFGITEM_MAX_RETRIES 0x05 -#define PN533_CONFIG_TIMING_102 0xb -#define PN533_CONFIG_TIMING_204 0xc -#define PN533_CONFIG_TIMING_409 0xd -#define PN533_CONFIG_TIMING_819 0xe - #define PN533_CONFIG_MAX_RETRIES_NO_RETRY 0x00 #define PN533_CONFIG_MAX_RETRIES_ENDLESS 0xFF @@ -124,12 +108,6 @@ struct pn533_config_max_retries { u8 mx_rty_passive_act; } __packed; -struct pn533_config_timing { - u8 rfu; - u8 atr_res_timeout; - u8 dep_timeout; -} __packed; - /* PN533_CMD_IN_LIST_PASSIVE_TARGET */ /* felica commands opcode */ @@ -166,7 +144,6 @@ enum { PN533_POLL_MOD_424KBPS_FELICA, PN533_POLL_MOD_106KBPS_JEWEL, PN533_POLL_MOD_847KBPS_B, - PN533_LISTEN_MOD, __PN533_POLL_MOD_AFTER_LAST, }; @@ -234,9 +211,6 @@ const struct pn533_poll_modulations poll_mod[] = { }, .len = 3, }, - [PN533_LISTEN_MOD] = { - .len = 0, - }, }; /* PN533_CMD_IN_ATR */ @@ -263,7 +237,7 @@ struct pn533_cmd_jump_dep { u8 active; u8 baud; u8 next; - u8 data[]; + u8 gt[]; } __packed; struct pn533_cmd_jump_dep_response { @@ -279,29 +253,6 @@ struct pn533_cmd_jump_dep_response { u8 gt[]; } __packed; - -/* PN533_TG_INIT_AS_TARGET */ -#define PN533_INIT_TARGET_PASSIVE 0x1 -#define PN533_INIT_TARGET_DEP 0x2 - -#define PN533_INIT_TARGET_RESP_FRAME_MASK 0x3 -#define PN533_INIT_TARGET_RESP_ACTIVE 0x1 -#define PN533_INIT_TARGET_RESP_DEP 0x4 - -struct pn533_cmd_init_target { - u8 mode; - u8 mifare[6]; - u8 felica[18]; - u8 nfcid3[10]; - u8 gb_len; - u8 gb[]; -} __packed; - -struct pn533_cmd_init_target_response { - u8 mode; - u8 cmd[]; -} __packed; - struct pn533 { struct usb_device *udev; struct usb_interface *interface; @@ -319,31 +270,22 @@ struct pn533 { struct workqueue_struct *wq; struct work_struct cmd_work; - struct work_struct poll_work; struct work_struct mi_work; - struct work_struct tg_work; - struct timer_list listen_timer; struct pn533_frame *wq_in_frame; int wq_in_error; - int cancel_listen; pn533_cmd_complete_t cmd_complete; void *cmd_complete_arg; - struct mutex cmd_lock; + struct semaphore cmd_lock; u8 cmd; struct pn533_poll_modulations *poll_mod_active[PN533_POLL_MOD_MAX + 1]; u8 poll_mod_count; u8 poll_mod_curr; u32 poll_protocols; - u32 listen_protocols; - - u8 *gb; - size_t gb_len; u8 tgt_available_prots; u8 tgt_active_prot; - u8 tgt_mode; }; struct pn533_frame { @@ -463,7 +405,7 @@ static void pn533_wq_cmd_complete(struct work_struct *work) PN533_FRAME_CMD_PARAMS_LEN(in_frame)); if (rc != -EINPROGRESS) - mutex_unlock(&dev->cmd_lock); + up(&dev->cmd_lock); } static void pn533_recv_response(struct urb *urb) @@ -641,7 +583,7 @@ static int pn533_send_cmd_frame_async(struct pn533 *dev, nfc_dev_dbg(&dev->interface->dev, "%s", __func__); - if (!mutex_trylock(&dev->cmd_lock)) + if (down_trylock(&dev->cmd_lock)) return -EBUSY; rc = __pn533_send_cmd_frame_async(dev, out_frame, in_frame, @@ -651,7 +593,7 @@ static int pn533_send_cmd_frame_async(struct pn533 *dev, return 0; error: - mutex_unlock(&dev->cmd_lock); + up(&dev->cmd_lock); return rc; } @@ -1021,11 +963,6 @@ static int pn533_target_found(struct pn533 *dev, return 0; } -static inline void pn533_poll_next_mod(struct pn533 *dev) -{ - dev->poll_mod_curr = (dev->poll_mod_curr + 1) % dev->poll_mod_count; -} - static void pn533_poll_reset_mod_list(struct pn533 *dev) { dev->poll_mod_count = 0; @@ -1038,283 +975,102 @@ static void pn533_poll_add_mod(struct pn533 *dev, u8 mod_index) dev->poll_mod_count++; } -static void pn533_poll_create_mod_list(struct pn533 *dev, - u32 im_protocols, u32 tm_protocols) +static void pn533_poll_create_mod_list(struct pn533 *dev, u32 protocols) { pn533_poll_reset_mod_list(dev); - if (im_protocols & NFC_PROTO_MIFARE_MASK - || im_protocols & NFC_PROTO_ISO14443_MASK - || im_protocols & NFC_PROTO_NFC_DEP_MASK) + if (protocols & NFC_PROTO_MIFARE_MASK + || protocols & NFC_PROTO_ISO14443_MASK + || protocols & NFC_PROTO_NFC_DEP_MASK) pn533_poll_add_mod(dev, PN533_POLL_MOD_106KBPS_A); - if (im_protocols & NFC_PROTO_FELICA_MASK - || im_protocols & NFC_PROTO_NFC_DEP_MASK) { + if (protocols & NFC_PROTO_FELICA_MASK + || protocols & NFC_PROTO_NFC_DEP_MASK) { pn533_poll_add_mod(dev, PN533_POLL_MOD_212KBPS_FELICA); pn533_poll_add_mod(dev, PN533_POLL_MOD_424KBPS_FELICA); } - if (im_protocols & NFC_PROTO_JEWEL_MASK) + if (protocols & NFC_PROTO_JEWEL_MASK) pn533_poll_add_mod(dev, PN533_POLL_MOD_106KBPS_JEWEL); - if (im_protocols & NFC_PROTO_ISO14443_MASK) + if (protocols & NFC_PROTO_ISO14443_MASK) pn533_poll_add_mod(dev, PN533_POLL_MOD_847KBPS_B); - - if (tm_protocols) - pn533_poll_add_mod(dev, PN533_LISTEN_MOD); -} - -static int pn533_start_poll_complete(struct pn533 *dev, void *arg, - u8 *params, int params_len) -{ - struct pn533_poll_response *resp; - int rc; - - nfc_dev_dbg(&dev->interface->dev, "%s", __func__); - - resp = (struct pn533_poll_response *) params; - if (resp->nbtg) { - rc = pn533_target_found(dev, resp, params_len); - - /* We must stop the poll after a valid target found */ - if (rc == 0) { - pn533_poll_reset_mod_list(dev); - return 0; - } - } - - return -EAGAIN; } -static int pn533_init_target_frame(struct pn533_frame *frame, - u8 *gb, size_t gb_len) +static void pn533_start_poll_frame(struct pn533_frame *frame, + struct pn533_poll_modulations *mod) { - struct pn533_cmd_init_target *cmd; - size_t cmd_len; - u8 felica_params[18] = {0x1, 0xfe, /* DEP */ - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, /* random */ - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0xff, 0xff}; /* System code */ - u8 mifare_params[6] = {0x1, 0x1, /* SENS_RES */ - 0x0, 0x0, 0x0, - 0x40}; /* SEL_RES for DEP */ - - cmd_len = sizeof(struct pn533_cmd_init_target) + gb_len + 1; - cmd = kzalloc(cmd_len, GFP_KERNEL); - if (cmd == NULL) - return -ENOMEM; - - pn533_tx_frame_init(frame, PN533_CMD_TG_INIT_AS_TARGET); - - /* DEP support only */ - cmd->mode |= PN533_INIT_TARGET_DEP; - - /* Felica params */ - memcpy(cmd->felica, felica_params, 18); - get_random_bytes(cmd->felica + 2, 6); - - /* NFCID3 */ - memset(cmd->nfcid3, 0, 10); - memcpy(cmd->nfcid3, cmd->felica, 8); - /* MIFARE params */ - memcpy(cmd->mifare, mifare_params, 6); + pn533_tx_frame_init(frame, PN533_CMD_IN_LIST_PASSIVE_TARGET); - /* General bytes */ - cmd->gb_len = gb_len; - memcpy(cmd->gb, gb, gb_len); - - /* Len Tk */ - cmd->gb[gb_len] = 0; - - memcpy(PN533_FRAME_CMD_PARAMS_PTR(frame), cmd, cmd_len); - - frame->datalen += cmd_len; + memcpy(PN533_FRAME_CMD_PARAMS_PTR(frame), &mod->data, mod->len); + frame->datalen += mod->len; pn533_tx_frame_finish(frame); - - kfree(cmd); - - return 0; } -#define PN533_CMD_DATAEXCH_HEAD_LEN (sizeof(struct pn533_frame) + 3) -#define PN533_CMD_DATAEXCH_DATA_MAXLEN 262 -static int pn533_tm_get_data_complete(struct pn533 *dev, void *arg, - u8 *params, int params_len) +static int pn533_start_poll_complete(struct pn533 *dev, void *arg, + u8 *params, int params_len) { - struct sk_buff *skb_resp = arg; - struct pn533_frame *in_frame = (struct pn533_frame *) skb_resp->data; + struct pn533_poll_response *resp; + struct pn533_poll_modulations *next_mod; + int rc; nfc_dev_dbg(&dev->interface->dev, "%s", __func__); - if (params_len < 0) { - nfc_dev_err(&dev->interface->dev, - "Error %d when starting as a target", - params_len); - - return params_len; - } - - if (params_len > 0 && params[0] != 0) { - nfc_tm_deactivated(dev->nfc_dev); - - dev->tgt_mode = 0; - - kfree_skb(skb_resp); - return 0; + if (params_len == -ENOENT) { + nfc_dev_dbg(&dev->interface->dev, "Polling operation has been" + " stopped"); + goto stop_poll; } - skb_put(skb_resp, PN533_FRAME_SIZE(in_frame)); - skb_pull(skb_resp, PN533_CMD_DATAEXCH_HEAD_LEN); - skb_trim(skb_resp, skb_resp->len - PN533_FRAME_TAIL_SIZE); - - return nfc_tm_data_received(dev->nfc_dev, skb_resp); -} - -static void pn533_wq_tg_get_data(struct work_struct *work) -{ - struct pn533 *dev = container_of(work, struct pn533, tg_work); - struct pn533_frame *in_frame; - struct sk_buff *skb_resp; - size_t skb_resp_len; - - nfc_dev_dbg(&dev->interface->dev, "%s", __func__); - - skb_resp_len = PN533_CMD_DATAEXCH_HEAD_LEN + - PN533_CMD_DATAEXCH_DATA_MAXLEN + - PN533_FRAME_TAIL_SIZE; - - skb_resp = nfc_alloc_recv_skb(skb_resp_len, GFP_KERNEL); - if (!skb_resp) - return; - - in_frame = (struct pn533_frame *)skb_resp->data; - - pn533_tx_frame_init(dev->out_frame, PN533_CMD_TG_GET_DATA); - pn533_tx_frame_finish(dev->out_frame); - - pn533_send_cmd_frame_async(dev, dev->out_frame, in_frame, - skb_resp_len, - pn533_tm_get_data_complete, - skb_resp, GFP_KERNEL); - - return; -} - -#define ATR_REQ_GB_OFFSET 17 -static int pn533_init_target_complete(struct pn533 *dev, void *arg, - u8 *params, int params_len) -{ - struct pn533_cmd_init_target_response *resp; - u8 frame, comm_mode = NFC_COMM_PASSIVE, *gb; - size_t gb_len; - int rc; - - nfc_dev_dbg(&dev->interface->dev, "%s", __func__); - if (params_len < 0) { - nfc_dev_err(&dev->interface->dev, - "Error %d when starting as a target", - params_len); - - return params_len; + nfc_dev_err(&dev->interface->dev, "Error %d when running poll", + params_len); + goto stop_poll; } - if (params_len < ATR_REQ_GB_OFFSET + 1) - return -EINVAL; - - resp = (struct pn533_cmd_init_target_response *) params; - - nfc_dev_dbg(&dev->interface->dev, "Target mode 0x%x param len %d\n", - resp->mode, params_len); - - frame = resp->mode & PN533_INIT_TARGET_RESP_FRAME_MASK; - if (frame == PN533_INIT_TARGET_RESP_ACTIVE) - comm_mode = NFC_COMM_ACTIVE; - - /* Again, only DEP */ - if ((resp->mode & PN533_INIT_TARGET_RESP_DEP) == 0) - return -EOPNOTSUPP; + resp = (struct pn533_poll_response *) params; + if (resp->nbtg) { + rc = pn533_target_found(dev, resp, params_len); - gb = resp->cmd + ATR_REQ_GB_OFFSET; - gb_len = params_len - (ATR_REQ_GB_OFFSET + 1); + /* We must stop the poll after a valid target found */ + if (rc == 0) + goto stop_poll; - rc = nfc_tm_activated(dev->nfc_dev, NFC_PROTO_NFC_DEP_MASK, - comm_mode, gb, gb_len); - if (rc < 0) { - nfc_dev_err(&dev->interface->dev, - "Error when signaling target activation"); - return rc; + if (rc != -EAGAIN) + nfc_dev_err(&dev->interface->dev, "The target found is" + " not valid - continuing to poll"); } - dev->tgt_mode = 1; - - queue_work(dev->wq, &dev->tg_work); - - return 0; -} - -static void pn533_listen_mode_timer(unsigned long data) -{ - struct pn533 *dev = (struct pn533 *) data; - - nfc_dev_dbg(&dev->interface->dev, "Listen mode timeout"); - - /* An ack will cancel the last issued command (poll) */ - pn533_send_ack(dev, GFP_ATOMIC); - - dev->cancel_listen = 1; - - mutex_unlock(&dev->cmd_lock); - - pn533_poll_next_mod(dev); - - queue_work(dev->wq, &dev->poll_work); -} + dev->poll_mod_curr = (dev->poll_mod_curr + 1) % dev->poll_mod_count; -static int pn533_poll_complete(struct pn533 *dev, void *arg, - u8 *params, int params_len) -{ - struct pn533_poll_modulations *cur_mod; - int rc; + next_mod = dev->poll_mod_active[dev->poll_mod_curr]; - nfc_dev_dbg(&dev->interface->dev, "%s", __func__); + nfc_dev_dbg(&dev->interface->dev, "Polling next modulation (0x%x)", + dev->poll_mod_curr); - if (params_len == -ENOENT) { - if (dev->poll_mod_count != 0) - return 0; + pn533_start_poll_frame(dev->out_frame, next_mod); - nfc_dev_err(&dev->interface->dev, - "Polling operation has been stopped"); + /* Don't need to down the semaphore again */ + rc = __pn533_send_cmd_frame_async(dev, dev->out_frame, dev->in_frame, + dev->in_maxlen, pn533_start_poll_complete, + NULL, GFP_ATOMIC); + if (rc == -EPERM) { + nfc_dev_dbg(&dev->interface->dev, "Cannot poll next modulation" + " because poll has been stopped"); goto stop_poll; } - if (params_len < 0) { - nfc_dev_err(&dev->interface->dev, - "Error %d when running poll", params_len); - + if (rc) { + nfc_dev_err(&dev->interface->dev, "Error %d when trying to poll" + " next modulation", rc); goto stop_poll; } - cur_mod = dev->poll_mod_active[dev->poll_mod_curr]; - - if (cur_mod->len == 0) { - del_timer(&dev->listen_timer); - - return pn533_init_target_complete(dev, arg, params, params_len); - } else { - rc = pn533_start_poll_complete(dev, arg, params, params_len); - if (!rc) - return rc; - } - - pn533_poll_next_mod(dev); - - queue_work(dev->wq, &dev->poll_work); - - return 0; + /* Inform caller function to do not up the semaphore */ + return -EINPROGRESS; stop_poll: pn533_poll_reset_mod_list(dev); @@ -1322,104 +1078,61 @@ static int pn533_poll_complete(struct pn533 *dev, void *arg, return 0; } -static void pn533_build_poll_frame(struct pn533 *dev, - struct pn533_frame *frame, - struct pn533_poll_modulations *mod) +static int pn533_start_poll(struct nfc_dev *nfc_dev, u32 protocols) { - nfc_dev_dbg(&dev->interface->dev, "mod len %d\n", mod->len); - - if (mod->len == 0) { - /* Listen mode */ - pn533_init_target_frame(frame, dev->gb, dev->gb_len); - } else { - /* Polling mode */ - pn533_tx_frame_init(frame, PN533_CMD_IN_LIST_PASSIVE_TARGET); - - memcpy(PN533_FRAME_CMD_PARAMS_PTR(frame), &mod->data, mod->len); - frame->datalen += mod->len; - - pn533_tx_frame_finish(frame); - } -} - -static int pn533_send_poll_frame(struct pn533 *dev) -{ - struct pn533_poll_modulations *cur_mod; - int rc; - - cur_mod = dev->poll_mod_active[dev->poll_mod_curr]; - - pn533_build_poll_frame(dev, dev->out_frame, cur_mod); - - rc = pn533_send_cmd_frame_async(dev, dev->out_frame, dev->in_frame, - dev->in_maxlen, pn533_poll_complete, - NULL, GFP_KERNEL); - if (rc) - nfc_dev_err(&dev->interface->dev, "Polling loop error %d", rc); - - return rc; -} - -static void pn533_wq_poll(struct work_struct *work) -{ - struct pn533 *dev = container_of(work, struct pn533, poll_work); - struct pn533_poll_modulations *cur_mod; + struct pn533 *dev = nfc_get_drvdata(nfc_dev); + struct pn533_poll_modulations *start_mod; int rc; - cur_mod = dev->poll_mod_active[dev->poll_mod_curr]; + nfc_dev_dbg(&dev->interface->dev, "%s - protocols=0x%x", __func__, + protocols); - nfc_dev_dbg(&dev->interface->dev, - "%s cancel_listen %d modulation len %d", - __func__, dev->cancel_listen, cur_mod->len); + if (dev->poll_mod_count) { + nfc_dev_err(&dev->interface->dev, "Polling operation already" + " active"); + return -EBUSY; + } - if (dev->cancel_listen == 1) { - dev->cancel_listen = 0; - usb_kill_urb(dev->in_urb); + if (dev->tgt_active_prot) { + nfc_dev_err(&dev->interface->dev, "Cannot poll with a target" + " already activated"); + return -EBUSY; } - rc = pn533_send_poll_frame(dev); - if (rc) - return; + pn533_poll_create_mod_list(dev, protocols); - if (cur_mod->len == 0 && dev->poll_mod_count > 1) - mod_timer(&dev->listen_timer, jiffies + PN533_LISTEN_TIME * HZ); + if (!dev->poll_mod_count) { + nfc_dev_err(&dev->interface->dev, "No valid protocols" + " specified"); + rc = -EINVAL; + goto error; + } - return; -} + nfc_dev_dbg(&dev->interface->dev, "It will poll %d modulations types", + dev->poll_mod_count); -static int pn533_start_poll(struct nfc_dev *nfc_dev, - u32 im_protocols, u32 tm_protocols) -{ - struct pn533 *dev = nfc_get_drvdata(nfc_dev); + dev->poll_mod_curr = 0; + start_mod = dev->poll_mod_active[dev->poll_mod_curr]; - nfc_dev_dbg(&dev->interface->dev, - "%s: im protocols 0x%x tm protocols 0x%x", - __func__, im_protocols, tm_protocols); + pn533_start_poll_frame(dev->out_frame, start_mod); - if (dev->tgt_active_prot) { - nfc_dev_err(&dev->interface->dev, - "Cannot poll with a target already activated"); - return -EBUSY; - } + rc = pn533_send_cmd_frame_async(dev, dev->out_frame, dev->in_frame, + dev->in_maxlen, pn533_start_poll_complete, + NULL, GFP_KERNEL); - if (dev->tgt_mode) { - nfc_dev_err(&dev->interface->dev, - "Cannot poll while already being activated"); - return -EBUSY; + if (rc) { + nfc_dev_err(&dev->interface->dev, "Error %d when trying to" + " start poll", rc); + goto error; } - if (tm_protocols) { - dev->gb = nfc_get_local_general_bytes(nfc_dev, &dev->gb_len); - if (dev->gb == NULL) - tm_protocols = 0; - } + dev->poll_protocols = protocols; - dev->poll_mod_curr = 0; - pn533_poll_create_mod_list(dev, im_protocols, tm_protocols); - dev->poll_protocols = im_protocols; - dev->listen_protocols = tm_protocols; + return 0; - return pn533_send_poll_frame(dev); +error: + pn533_poll_reset_mod_list(dev); + return rc; } static void pn533_stop_poll(struct nfc_dev *nfc_dev) @@ -1428,8 +1141,6 @@ static void pn533_stop_poll(struct nfc_dev *nfc_dev) nfc_dev_dbg(&dev->interface->dev, "%s", __func__); - del_timer(&dev->listen_timer); - if (!dev->poll_mod_count) { nfc_dev_dbg(&dev->interface->dev, "Polling operation was not" " running"); @@ -1441,8 +1152,6 @@ static void pn533_stop_poll(struct nfc_dev *nfc_dev) /* prevent pn533_start_poll_complete to issue a new poll meanwhile */ usb_kill_urb(dev->in_urb); - - pn533_poll_reset_mod_list(dev); } static int pn533_activate_target_nfcdep(struct pn533 *dev) @@ -1640,29 +1349,13 @@ static int pn533_in_dep_link_up_complete(struct pn533 *dev, void *arg, return 0; } -static int pn533_mod_to_baud(struct pn533 *dev) -{ - switch (dev->poll_mod_curr) { - case PN533_POLL_MOD_106KBPS_A: - return 0; - case PN533_POLL_MOD_212KBPS_FELICA: - return 1; - case PN533_POLL_MOD_424KBPS_FELICA: - return 2; - default: - return -EINVAL; - } -} - -#define PASSIVE_DATA_LEN 5 static int pn533_dep_link_up(struct nfc_dev *nfc_dev, struct nfc_target *target, u8 comm_mode, u8* gb, size_t gb_len) { struct pn533 *dev = nfc_get_drvdata(nfc_dev); struct pn533_cmd_jump_dep *cmd; - u8 cmd_len, *data_ptr; - u8 passive_data[PASSIVE_DATA_LEN] = {0x00, 0xff, 0xff, 0x00, 0x3}; - int rc, baud; + u8 cmd_len; + int rc; nfc_dev_dbg(&dev->interface->dev, "%s", __func__); @@ -1678,17 +1371,7 @@ static int pn533_dep_link_up(struct nfc_dev *nfc_dev, struct nfc_target *target, return -EBUSY; } - baud = pn533_mod_to_baud(dev); - if (baud < 0) { - nfc_dev_err(&dev->interface->dev, - "Invalid curr modulation %d", dev->poll_mod_curr); - return baud; - } - cmd_len = sizeof(struct pn533_cmd_jump_dep) + gb_len; - if (comm_mode == NFC_COMM_PASSIVE) - cmd_len += PASSIVE_DATA_LEN; - cmd = kzalloc(cmd_len, GFP_KERNEL); if (cmd == NULL) return -ENOMEM; @@ -1696,18 +1379,10 @@ static int pn533_dep_link_up(struct nfc_dev *nfc_dev, struct nfc_target *target, pn533_tx_frame_init(dev->out_frame, PN533_CMD_IN_JUMP_FOR_DEP); cmd->active = !comm_mode; - cmd->next = 0; - cmd->baud = baud; - data_ptr = cmd->data; - if (comm_mode == NFC_COMM_PASSIVE && cmd->baud > 0) { - memcpy(data_ptr, passive_data, PASSIVE_DATA_LEN); - cmd->next |= 1; - data_ptr += PASSIVE_DATA_LEN; - } - + cmd->baud = 0; if (gb != NULL && gb_len > 0) { - cmd->next |= 4; /* We have some Gi */ - memcpy(data_ptr, gb, gb_len); + cmd->next = 4; /* We have some Gi */ + memcpy(cmd->gt, gb, gb_len); } else { cmd->next = 0; } @@ -1732,25 +1407,15 @@ static int pn533_dep_link_up(struct nfc_dev *nfc_dev, struct nfc_target *target, static int pn533_dep_link_down(struct nfc_dev *nfc_dev) { - struct pn533 *dev = nfc_get_drvdata(nfc_dev); - - pn533_poll_reset_mod_list(dev); - - if (dev->tgt_mode || dev->tgt_active_prot) { - pn533_send_ack(dev, GFP_KERNEL); - usb_kill_urb(dev->in_urb); - } - - dev->tgt_active_prot = 0; - dev->tgt_mode = 0; - - skb_queue_purge(&dev->resp_q); + pn533_deactivate_target(nfc_dev, 0); return 0; } -static int pn533_build_tx_frame(struct pn533 *dev, struct sk_buff *skb, - bool target) +#define PN533_CMD_DATAEXCH_HEAD_LEN (sizeof(struct pn533_frame) + 3) +#define PN533_CMD_DATAEXCH_DATA_MAXLEN 262 + +static int pn533_data_exchange_tx_frame(struct pn533 *dev, struct sk_buff *skb) { int payload_len = skb->len; struct pn533_frame *out_frame; @@ -1767,20 +1432,14 @@ static int pn533_build_tx_frame(struct pn533 *dev, struct sk_buff *skb, return -ENOSYS; } - if (target == true) { - skb_push(skb, PN533_CMD_DATAEXCH_HEAD_LEN); - out_frame = (struct pn533_frame *) skb->data; + skb_push(skb, PN533_CMD_DATAEXCH_HEAD_LEN); + out_frame = (struct pn533_frame *) skb->data; - pn533_tx_frame_init(out_frame, PN533_CMD_IN_DATA_EXCHANGE); - tg = 1; - memcpy(PN533_FRAME_CMD_PARAMS_PTR(out_frame), &tg, sizeof(u8)); - out_frame->datalen += sizeof(u8); - } else { - skb_push(skb, PN533_CMD_DATAEXCH_HEAD_LEN - 1); - out_frame = (struct pn533_frame *) skb->data; - pn533_tx_frame_init(out_frame, PN533_CMD_TG_SET_DATA); - } + pn533_tx_frame_init(out_frame, PN533_CMD_IN_DATA_EXCHANGE); + tg = 1; + memcpy(PN533_FRAME_CMD_PARAMS_PTR(out_frame), &tg, sizeof(u8)); + out_frame->datalen += sizeof(u8); /* The data is already in the out_frame, just update the datalen */ out_frame->datalen += payload_len; @@ -1891,9 +1550,9 @@ static int pn533_data_exchange_complete(struct pn533 *dev, void *_arg, return 0; } -static int pn533_transceive(struct nfc_dev *nfc_dev, - struct nfc_target *target, struct sk_buff *skb, - data_exchange_cb_t cb, void *cb_context) +static int pn533_data_exchange(struct nfc_dev *nfc_dev, + struct nfc_target *target, struct sk_buff *skb, + data_exchange_cb_t cb, void *cb_context) { struct pn533 *dev = nfc_get_drvdata(nfc_dev); struct pn533_frame *out_frame, *in_frame; @@ -1911,7 +1570,7 @@ static int pn533_transceive(struct nfc_dev *nfc_dev, goto error; } - rc = pn533_build_tx_frame(dev, skb, true); + rc = pn533_data_exchange_tx_frame(dev, skb); if (rc) goto error; @@ -1959,63 +1618,6 @@ static int pn533_transceive(struct nfc_dev *nfc_dev, return rc; } -static int pn533_tm_send_complete(struct pn533 *dev, void *arg, - u8 *params, int params_len) -{ - nfc_dev_dbg(&dev->interface->dev, "%s", __func__); - - if (params_len < 0) { - nfc_dev_err(&dev->interface->dev, - "Error %d when sending data", - params_len); - - return params_len; - } - - if (params_len > 0 && params[0] != 0) { - nfc_tm_deactivated(dev->nfc_dev); - - dev->tgt_mode = 0; - - return 0; - } - - queue_work(dev->wq, &dev->tg_work); - - return 0; -} - -static int pn533_tm_send(struct nfc_dev *nfc_dev, struct sk_buff *skb) -{ - struct pn533 *dev = nfc_get_drvdata(nfc_dev); - struct pn533_frame *out_frame; - int rc; - - nfc_dev_dbg(&dev->interface->dev, "%s", __func__); - - rc = pn533_build_tx_frame(dev, skb, false); - if (rc) - goto error; - - out_frame = (struct pn533_frame *) skb->data; - - rc = pn533_send_cmd_frame_async(dev, out_frame, dev->in_frame, - dev->in_maxlen, pn533_tm_send_complete, - NULL, GFP_KERNEL); - if (rc) { - nfc_dev_err(&dev->interface->dev, - "Error %d when trying to send data", rc); - goto error; - } - - return 0; - -error: - kfree_skb(skb); - - return rc; -} - static void pn533_wq_mi_recv(struct work_struct *work) { struct pn533 *dev = container_of(work, struct pn533, mi_work); @@ -2036,7 +1638,7 @@ static void pn533_wq_mi_recv(struct work_struct *work) skb_reserve(skb_cmd, PN533_CMD_DATAEXCH_HEAD_LEN); - rc = pn533_build_tx_frame(dev, skb_cmd, true); + rc = pn533_data_exchange_tx_frame(dev, skb_cmd); if (rc) goto error_frame; @@ -2075,7 +1677,7 @@ static void pn533_wq_mi_recv(struct work_struct *work) kfree(arg); - mutex_unlock(&dev->cmd_lock); + up(&dev->cmd_lock); } static int pn533_set_configuration(struct pn533 *dev, u8 cfgitem, u8 *cfgdata, @@ -2110,8 +1712,7 @@ struct nfc_ops pn533_nfc_ops = { .stop_poll = pn533_stop_poll, .activate_target = pn533_activate_target, .deactivate_target = pn533_deactivate_target, - .im_transceive = pn533_transceive, - .tm_send = pn533_tm_send, + .data_exchange = pn533_data_exchange, }; static int pn533_probe(struct usb_interface *interface, @@ -2122,7 +1723,6 @@ static int pn533_probe(struct usb_interface *interface, struct usb_host_interface *iface_desc; struct usb_endpoint_descriptor *endpoint; struct pn533_config_max_retries max_retries; - struct pn533_config_timing timing; int in_endpoint = 0; int out_endpoint = 0; int rc = -ENOMEM; @@ -2135,7 +1735,7 @@ static int pn533_probe(struct usb_interface *interface, dev->udev = usb_get_dev(interface_to_usbdev(interface)); dev->interface = interface; - mutex_init(&dev->cmd_lock); + sema_init(&dev->cmd_lock, 1); iface_desc = interface->cur_altsetting; for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) { @@ -2179,18 +1779,12 @@ static int pn533_probe(struct usb_interface *interface, INIT_WORK(&dev->cmd_work, pn533_wq_cmd_complete); INIT_WORK(&dev->mi_work, pn533_wq_mi_recv); - INIT_WORK(&dev->tg_work, pn533_wq_tg_get_data); - INIT_WORK(&dev->poll_work, pn533_wq_poll); dev->wq = alloc_workqueue("pn533", WQ_NON_REENTRANT | WQ_UNBOUND | WQ_MEM_RECLAIM, 1); if (dev->wq == NULL) goto error; - init_timer(&dev->listen_timer); - dev->listen_timer.data = (unsigned long) dev; - dev->listen_timer.function = pn533_listen_mode_timer; - skb_queue_head_init(&dev->resp_q); usb_set_intfdata(interface, dev); @@ -2236,29 +1830,13 @@ static int pn533_probe(struct usb_interface *interface, if (rc) { nfc_dev_err(&dev->interface->dev, "Error on setting MAX_RETRIES" " config"); - goto unregister_nfc_dev; - } - - timing.rfu = PN533_CONFIG_TIMING_102; - timing.atr_res_timeout = PN533_CONFIG_TIMING_204; - timing.dep_timeout = PN533_CONFIG_TIMING_409; - - rc = pn533_set_configuration(dev, PN533_CFGITEM_TIMING, - (u8 *) &timing, sizeof(timing)); - if (rc) { - nfc_dev_err(&dev->interface->dev, - "Error on setting RF timings"); - goto unregister_nfc_dev; + goto free_nfc_dev; } return 0; -unregister_nfc_dev: - nfc_unregister_device(dev->nfc_dev); - free_nfc_dev: nfc_free_device(dev->nfc_dev); - destroy_wq: destroy_workqueue(dev->wq); error: @@ -2287,8 +1865,6 @@ static void pn533_disconnect(struct usb_interface *interface) skb_queue_purge(&dev->resp_q); - del_timer(&dev->listen_timer); - kfree(dev->in_frame); usb_free_urb(dev->in_urb); kfree(dev->out_frame); diff --git a/trunk/drivers/nfc/pn544_hci.c b/trunk/drivers/nfc/pn544_hci.c index 457eac35dc74..281f18c2fb82 100644 --- a/trunk/drivers/nfc/pn544_hci.c +++ b/trunk/drivers/nfc/pn544_hci.c @@ -576,8 +576,7 @@ static int pn544_hci_xmit(struct nfc_shdlc *shdlc, struct sk_buff *skb) return pn544_hci_i2c_write(client, skb->data, skb->len); } -static int pn544_hci_start_poll(struct nfc_shdlc *shdlc, - u32 im_protocols, u32 tm_protocols) +static int pn544_hci_start_poll(struct nfc_shdlc *shdlc, u32 protocols) { struct nfc_hci_dev *hdev = nfc_shdlc_get_hci_dev(shdlc); u8 phases = 0; @@ -585,8 +584,7 @@ static int pn544_hci_start_poll(struct nfc_shdlc *shdlc, u8 duration[2]; u8 activated; - pr_info(DRIVER_DESC ": %s protocols 0x%x 0x%x\n", - __func__, im_protocols, tm_protocols); + pr_info(DRIVER_DESC ": %s protocols = %d\n", __func__, protocols); r = nfc_hci_send_event(hdev, NFC_HCI_RF_READER_A_GATE, NFC_HCI_EVT_END_OPERATION, NULL, 0); @@ -606,10 +604,10 @@ static int pn544_hci_start_poll(struct nfc_shdlc *shdlc, if (r < 0) return r; - if (im_protocols & (NFC_PROTO_ISO14443_MASK | NFC_PROTO_MIFARE_MASK | + if (protocols & (NFC_PROTO_ISO14443_MASK | NFC_PROTO_MIFARE_MASK | NFC_PROTO_JEWEL_MASK)) phases |= 1; /* Type A */ - if (im_protocols & NFC_PROTO_FELICA_MASK) { + if (protocols & NFC_PROTO_FELICA_MASK) { phases |= (1 << 2); /* Type F 212 */ phases |= (1 << 3); /* Type F 424 */ } diff --git a/trunk/drivers/ssb/scan.c b/trunk/drivers/ssb/scan.c index ab4627cf1114..266c7c5c86dc 100644 --- a/trunk/drivers/ssb/scan.c +++ b/trunk/drivers/ssb/scan.c @@ -90,8 +90,6 @@ const char *ssb_core_name(u16 coreid) return "ARM 1176"; case SSB_DEV_ARM_7TDMI: return "ARM 7TDMI"; - case SSB_DEV_ARM_CM3: - return "ARM Cortex M3"; } return "UNKNOWN"; } diff --git a/trunk/include/linux/nfc.h b/trunk/include/linux/nfc.h index f4e6dd915b1c..0ae9b5857c83 100644 --- a/trunk/include/linux/nfc.h +++ b/trunk/include/linux/nfc.h @@ -56,10 +56,6 @@ * %NFC_ATTR_PROTOCOLS) * @NFC_EVENT_DEVICE_REMOVED: event emitted when a device is removed * (it sends %NFC_ATTR_DEVICE_INDEX) - * @NFC_EVENT_TM_ACTIVATED: event emitted when the adapter is activated in - * target mode. - * @NFC_EVENT_DEVICE_DEACTIVATED: event emitted when the adapter is deactivated - * from target mode. */ enum nfc_commands { NFC_CMD_UNSPEC, @@ -75,8 +71,6 @@ enum nfc_commands { NFC_EVENT_DEVICE_ADDED, NFC_EVENT_DEVICE_REMOVED, NFC_EVENT_TARGET_LOST, - NFC_EVENT_TM_ACTIVATED, - NFC_EVENT_TM_DEACTIVATED, /* private: internal use only */ __NFC_CMD_AFTER_LAST }; @@ -100,8 +94,6 @@ enum nfc_commands { * @NFC_ATTR_TARGET_SENSF_RES: NFC-F targets extra information, max 18 bytes * @NFC_ATTR_COMM_MODE: Passive or active mode * @NFC_ATTR_RF_MODE: Initiator or target - * @NFC_ATTR_IM_PROTOCOLS: Initiator mode protocols to poll for - * @NFC_ATTR_TM_PROTOCOLS: Target mode protocols to listen for */ enum nfc_attrs { NFC_ATTR_UNSPEC, @@ -117,8 +109,6 @@ enum nfc_attrs { NFC_ATTR_COMM_MODE, NFC_ATTR_RF_MODE, NFC_ATTR_DEVICE_POWERED, - NFC_ATTR_IM_PROTOCOLS, - NFC_ATTR_TM_PROTOCOLS, /* private: internal use only */ __NFC_ATTR_AFTER_LAST }; @@ -128,7 +118,6 @@ enum nfc_attrs { #define NFC_NFCID1_MAXSIZE 10 #define NFC_SENSB_RES_MAXSIZE 12 #define NFC_SENSF_RES_MAXSIZE 18 -#define NFC_GB_MAXSIZE 48 /* NFC protocols */ #define NFC_PROTO_JEWEL 1 @@ -146,7 +135,6 @@ enum nfc_attrs { /* NFC RF modes */ #define NFC_RF_INITIATOR 0 #define NFC_RF_TARGET 1 -#define NFC_RF_NONE 2 /* NFC protocols masks used in bitsets */ #define NFC_PROTO_JEWEL_MASK (1 << NFC_PROTO_JEWEL) diff --git a/trunk/include/linux/nl80211.h b/trunk/include/linux/nl80211.h index 970afdf5a605..85e5037a218d 100644 --- a/trunk/include/linux/nl80211.h +++ b/trunk/include/linux/nl80211.h @@ -1522,8 +1522,6 @@ enum nl80211_attrs { #define NL80211_MAX_NR_CIPHER_SUITES 5 #define NL80211_MAX_NR_AKM_SUITES 2 -#define NL80211_MIN_REMAIN_ON_CHANNEL_TIME 10 - /** * enum nl80211_iftype - (virtual) interface types * diff --git a/trunk/include/linux/ssb/ssb.h b/trunk/include/linux/ssb/ssb.h index bb674c02f306..bc14bd738ade 100644 --- a/trunk/include/linux/ssb/ssb.h +++ b/trunk/include/linux/ssb/ssb.h @@ -243,7 +243,6 @@ struct ssb_bus_ops { #define SSB_DEV_MINI_MACPHY 0x823 #define SSB_DEV_ARM_1176 0x824 #define SSB_DEV_ARM_7TDMI 0x825 -#define SSB_DEV_ARM_CM3 0x82A /* Vendor-ID values */ #define SSB_VENDOR_BROADCOM 0x4243 diff --git a/trunk/include/net/cfg80211.h b/trunk/include/net/cfg80211.h index 7319f25250b6..4c90c44b8b75 100644 --- a/trunk/include/net/cfg80211.h +++ b/trunk/include/net/cfg80211.h @@ -1420,14 +1420,11 @@ struct cfg80211_gtk_rekey_data { * * @set_txq_params: Set TX queue parameters * - * @libertas_set_mesh_channel: Only for backward compatibility for libertas, - * as it doesn't implement join_mesh and needs to set the channel to - * join the mesh instead. - * - * @set_monitor_channel: Set the monitor mode channel for the device. If other - * interfaces are active this callback should reject the configuration. - * If no interfaces are active or the device is down, the channel should - * be stored for when a monitor interface becomes active. + * @set_channel: Set channel for a given wireless interface. Some devices + * may support multi-channel operation (by channel hopping) so cfg80211 + * doesn't verify much. Note, however, that the passed netdev may be + * %NULL as well if the user requested changing the channel for the + * device itself, or for a monitor interface. * @get_channel: Get the current operating channel, should return %NULL if * there's no single defined operating channel if for example the * device implements channel hopping for multi-channel virtual interfaces. @@ -1617,13 +1614,9 @@ struct cfg80211_ops { int (*set_txq_params)(struct wiphy *wiphy, struct net_device *dev, struct ieee80211_txq_params *params); - int (*libertas_set_mesh_channel)(struct wiphy *wiphy, - struct net_device *dev, - struct ieee80211_channel *chan); - - int (*set_monitor_channel)(struct wiphy *wiphy, - struct ieee80211_channel *chan, - enum nl80211_channel_type channel_type); + int (*set_channel)(struct wiphy *wiphy, struct net_device *dev, + struct ieee80211_channel *chan, + enum nl80211_channel_type channel_type); int (*scan)(struct wiphy *wiphy, struct net_device *dev, struct cfg80211_scan_request *request); @@ -2332,6 +2325,7 @@ struct wireless_dev { spinlock_t event_lock; struct cfg80211_internal_bss *current_bss; /* associated / joined */ + struct ieee80211_channel *channel; struct ieee80211_channel *preset_chan; enum nl80211_channel_type preset_chantype; diff --git a/trunk/include/net/mac80211.h b/trunk/include/net/mac80211.h index d152f54064fd..d2ed86da8e4c 100644 --- a/trunk/include/net/mac80211.h +++ b/trunk/include/net/mac80211.h @@ -2183,10 +2183,7 @@ enum ieee80211_rate_control_changed { * offload. Frames to transmit on the off-channel channel are transmitted * normally except for the %IEEE80211_TX_CTL_TX_OFFCHAN flag. When the * duration (which will always be non-zero) expires, the driver must call - * ieee80211_remain_on_channel_expired(). - * Note that this callback may be called while the device is in IDLE and - * must be accepted in this case. - * This callback may sleep. + * ieee80211_remain_on_channel_expired(). This callback may sleep. * @cancel_remain_on_channel: Requests that an ongoing off-channel period is * aborted before it expires. This callback may sleep. * diff --git a/trunk/include/net/nfc/hci.h b/trunk/include/net/nfc/hci.h index e30e6a869714..4467c9460857 100644 --- a/trunk/include/net/nfc/hci.h +++ b/trunk/include/net/nfc/hci.h @@ -31,8 +31,7 @@ struct nfc_hci_ops { void (*close) (struct nfc_hci_dev *hdev); int (*hci_ready) (struct nfc_hci_dev *hdev); int (*xmit) (struct nfc_hci_dev *hdev, struct sk_buff *skb); - int (*start_poll) (struct nfc_hci_dev *hdev, - u32 im_protocols, u32 tm_protocols); + int (*start_poll) (struct nfc_hci_dev *hdev, u32 protocols); int (*target_from_gate) (struct nfc_hci_dev *hdev, u8 gate, struct nfc_target *target); int (*complete_target_discovered) (struct nfc_hci_dev *hdev, u8 gate, diff --git a/trunk/include/net/nfc/nfc.h b/trunk/include/net/nfc/nfc.h index 180964b954ab..b7ca4a2a1d72 100644 --- a/trunk/include/net/nfc/nfc.h +++ b/trunk/include/net/nfc/nfc.h @@ -53,8 +53,7 @@ struct nfc_target; struct nfc_ops { int (*dev_up)(struct nfc_dev *dev); int (*dev_down)(struct nfc_dev *dev); - int (*start_poll)(struct nfc_dev *dev, - u32 im_protocols, u32 tm_protocols); + int (*start_poll)(struct nfc_dev *dev, u32 protocols); void (*stop_poll)(struct nfc_dev *dev); int (*dep_link_up)(struct nfc_dev *dev, struct nfc_target *target, u8 comm_mode, u8 *gb, size_t gb_len); @@ -63,10 +62,9 @@ struct nfc_ops { u32 protocol); void (*deactivate_target)(struct nfc_dev *dev, struct nfc_target *target); - int (*im_transceive)(struct nfc_dev *dev, struct nfc_target *target, + int (*data_exchange)(struct nfc_dev *dev, struct nfc_target *target, struct sk_buff *skb, data_exchange_cb_t cb, void *cb_context); - int (*tm_send)(struct nfc_dev *dev, struct sk_buff *skb); int (*check_presence)(struct nfc_dev *dev, struct nfc_target *target); }; @@ -101,10 +99,10 @@ struct nfc_dev { int targets_generation; struct device dev; bool dev_up; - u8 rf_mode; bool polling; struct nfc_target *active_target; bool dep_link_up; + u32 dep_rf_mode; struct nfc_genl_data genl_data; u32 supported_protocols; @@ -190,7 +188,6 @@ struct sk_buff *nfc_alloc_recv_skb(unsigned int size, gfp_t gfp); int nfc_set_remote_general_bytes(struct nfc_dev *dev, u8 *gt, u8 gt_len); -u8 *nfc_get_local_general_bytes(struct nfc_dev *dev, size_t *gb_len); int nfc_targets_found(struct nfc_dev *dev, struct nfc_target *targets, int ntargets); @@ -199,9 +196,4 @@ int nfc_target_lost(struct nfc_dev *dev, u32 target_idx); int nfc_dep_link_is_up(struct nfc_dev *dev, u32 target_idx, u8 comm_mode, u8 rf_mode); -int nfc_tm_activated(struct nfc_dev *dev, u32 protocol, u8 comm_mode, - u8 *gb, size_t gb_len); -int nfc_tm_deactivated(struct nfc_dev *dev); -int nfc_tm_data_received(struct nfc_dev *dev, struct sk_buff *skb); - #endif /* __NET_NFC_H */ diff --git a/trunk/include/net/nfc/shdlc.h b/trunk/include/net/nfc/shdlc.h index 35e930d2f638..ab06afd462da 100644 --- a/trunk/include/net/nfc/shdlc.h +++ b/trunk/include/net/nfc/shdlc.h @@ -27,8 +27,7 @@ struct nfc_shdlc_ops { void (*close) (struct nfc_shdlc *shdlc); int (*hci_ready) (struct nfc_shdlc *shdlc); int (*xmit) (struct nfc_shdlc *shdlc, struct sk_buff *skb); - int (*start_poll) (struct nfc_shdlc *shdlc, - u32 im_protocols, u32 tm_protocols); + int (*start_poll) (struct nfc_shdlc *shdlc, u32 protocols); int (*target_from_gate) (struct nfc_shdlc *shdlc, u8 gate, struct nfc_target *target); int (*complete_target_discovered) (struct nfc_shdlc *shdlc, u8 gate, diff --git a/trunk/net/bluetooth/af_bluetooth.c b/trunk/net/bluetooth/af_bluetooth.c index 3e18af4dadc4..46e7f86acfc9 100644 --- a/trunk/net/bluetooth/af_bluetooth.c +++ b/trunk/net/bluetooth/af_bluetooth.c @@ -210,7 +210,7 @@ struct sock *bt_accept_dequeue(struct sock *parent, struct socket *newsock) } if (sk->sk_state == BT_CONNECTED || !newsock || - test_bit(BT_SK_DEFER_SETUP, &bt_sk(parent)->flags)) { + test_bit(BT_DEFER_SETUP, &bt_sk(parent)->flags)) { bt_accept_unlink(sk); if (newsock) sock_graft(sk, newsock); diff --git a/trunk/net/mac80211/Makefile b/trunk/net/mac80211/Makefile index 2b1470bac178..3e9d931bba35 100644 --- a/trunk/net/mac80211/Makefile +++ b/trunk/net/mac80211/Makefile @@ -9,6 +9,7 @@ mac80211-y := \ scan.o offchannel.o \ ht.o agg-tx.o agg-rx.o \ ibss.o \ + work.o \ iface.o \ rate.o \ michael.o \ diff --git a/trunk/net/mac80211/agg-rx.c b/trunk/net/mac80211/agg-rx.c index 32ef11d69798..a096b0dae37d 100644 --- a/trunk/net/mac80211/agg-rx.c +++ b/trunk/net/mac80211/agg-rx.c @@ -142,20 +142,15 @@ static void sta_rx_agg_session_timer_expired(unsigned long data) struct tid_ampdu_rx *tid_rx; unsigned long timeout; - rcu_read_lock(); tid_rx = rcu_dereference(sta->ampdu_mlme.tid_rx[*ptid]); - if (!tid_rx) { - rcu_read_unlock(); + if (!tid_rx) return; - } timeout = tid_rx->last_rx + TU_TO_JIFFIES(tid_rx->timeout); if (time_is_after_jiffies(timeout)) { mod_timer(&tid_rx->session_timer, timeout); - rcu_read_unlock(); return; } - rcu_read_unlock(); ht_vdbg("rx session timer expired on tid %d\n", (u16)*ptid); diff --git a/trunk/net/mac80211/cfg.c b/trunk/net/mac80211/cfg.c index 498c94e34427..f47af8b3185e 100644 --- a/trunk/net/mac80211/cfg.c +++ b/trunk/net/mac80211/cfg.c @@ -533,16 +533,16 @@ static void ieee80211_get_et_stats(struct wiphy *wiphy, sinfo.filled = 0; sta_set_sinfo(sta, &sinfo); - if (sinfo.filled & STATION_INFO_TX_BITRATE) + if (sinfo.filled | STATION_INFO_TX_BITRATE) data[i] = 100000 * cfg80211_calculate_bitrate(&sinfo.txrate); i++; - if (sinfo.filled & STATION_INFO_RX_BITRATE) + if (sinfo.filled | STATION_INFO_RX_BITRATE) data[i] = 100000 * cfg80211_calculate_bitrate(&sinfo.rxrate); i++; - if (sinfo.filled & STATION_INFO_SIGNAL_AVG) + if (sinfo.filled | STATION_INFO_SIGNAL_AVG) data[i] = (u8)sinfo.signal_avg; i++; } else { @@ -709,13 +709,6 @@ static int ieee80211_set_channel(struct wiphy *wiphy, return 0; } -static int ieee80211_set_monitor_channel(struct wiphy *wiphy, - struct ieee80211_channel *chan, - enum nl80211_channel_type channel_type) -{ - return ieee80211_set_channel(wiphy, NULL, chan, channel_type); -} - static int ieee80211_set_probe_resp(struct ieee80211_sub_if_data *sdata, const u8 *resp, size_t resp_len) { @@ -2112,171 +2105,35 @@ static int ieee80211_set_bitrate_mask(struct wiphy *wiphy, return 0; } -static int ieee80211_start_roc_work(struct ieee80211_local *local, - struct ieee80211_sub_if_data *sdata, - struct ieee80211_channel *channel, - enum nl80211_channel_type channel_type, - unsigned int duration, u64 *cookie, - struct sk_buff *txskb) +static int ieee80211_remain_on_channel_hw(struct ieee80211_local *local, + struct net_device *dev, + struct ieee80211_channel *chan, + enum nl80211_channel_type chantype, + unsigned int duration, u64 *cookie) { - struct ieee80211_roc_work *roc, *tmp; - bool queued = false; int ret; + u32 random_cookie; lockdep_assert_held(&local->mtx); - roc = kzalloc(sizeof(*roc), GFP_KERNEL); - if (!roc) - return -ENOMEM; - - roc->chan = channel; - roc->chan_type = channel_type; - roc->duration = duration; - roc->req_duration = duration; - roc->frame = txskb; - roc->mgmt_tx_cookie = (unsigned long)txskb; - roc->sdata = sdata; - INIT_DELAYED_WORK(&roc->work, ieee80211_sw_roc_work); - INIT_LIST_HEAD(&roc->dependents); - - /* if there's one pending or we're scanning, queue this one */ - if (!list_empty(&local->roc_list) || local->scanning) - goto out_check_combine; - - /* if not HW assist, just queue & schedule work */ - if (!local->ops->remain_on_channel) { - ieee80211_queue_delayed_work(&local->hw, &roc->work, 0); - goto out_queue; - } - - /* otherwise actually kick it off here (for error handling) */ - - /* - * If the duration is zero, then the driver - * wouldn't actually do anything. Set it to - * 10 for now. - * - * TODO: cancel the off-channel operation - * when we get the SKB's TX status and - * the wait time was zero before. - */ - if (!duration) - duration = 10; - - ret = drv_remain_on_channel(local, channel, channel_type, duration); + if (local->hw_roc_cookie) + return -EBUSY; + /* must be nonzero */ + random_cookie = random32() | 1; + + *cookie = random_cookie; + local->hw_roc_dev = dev; + local->hw_roc_cookie = random_cookie; + local->hw_roc_channel = chan; + local->hw_roc_channel_type = chantype; + local->hw_roc_duration = duration; + ret = drv_remain_on_channel(local, chan, chantype, duration); if (ret) { - kfree(roc); - return ret; - } - - roc->started = true; - goto out_queue; - - out_check_combine: - list_for_each_entry(tmp, &local->roc_list, list) { - if (tmp->chan != channel || tmp->chan_type != channel_type) - continue; - - /* - * Extend this ROC if possible: - * - * If it hasn't started yet, just increase the duration - * and add the new one to the list of dependents. - */ - if (!tmp->started) { - list_add_tail(&roc->list, &tmp->dependents); - tmp->duration = max(tmp->duration, roc->duration); - queued = true; - break; - } - - /* If it has already started, it's more difficult ... */ - if (local->ops->remain_on_channel) { - unsigned long j = jiffies; - - /* - * In the offloaded ROC case, if it hasn't begun, add - * this new one to the dependent list to be handled - * when the the master one begins. If it has begun, - * check that there's still a minimum time left and - * if so, start this one, transmitting the frame, but - * add it to the list directly after this one with a - * a reduced time so we'll ask the driver to execute - * it right after finishing the previous one, in the - * hope that it'll also be executed right afterwards, - * effectively extending the old one. - * If there's no minimum time left, just add it to the - * normal list. - */ - if (!tmp->hw_begun) { - list_add_tail(&roc->list, &tmp->dependents); - queued = true; - break; - } - - if (time_before(j + IEEE80211_ROC_MIN_LEFT, - tmp->hw_start_time + - msecs_to_jiffies(tmp->duration))) { - int new_dur; - - ieee80211_handle_roc_started(roc); - - new_dur = roc->duration - - jiffies_to_msecs(tmp->hw_start_time + - msecs_to_jiffies( - tmp->duration) - - j); - - if (new_dur > 0) { - /* add right after tmp */ - list_add(&roc->list, &tmp->list); - } else { - list_add_tail(&roc->list, - &tmp->dependents); - } - queued = true; - } - } else if (del_timer_sync(&tmp->work.timer)) { - unsigned long new_end; - - /* - * In the software ROC case, cancel the timer, if - * that fails then the finish work is already - * queued/pending and thus we queue the new ROC - * normally, if that succeeds then we can extend - * the timer duration and TX the frame (if any.) - */ - - list_add_tail(&roc->list, &tmp->dependents); - queued = true; - - new_end = jiffies + msecs_to_jiffies(roc->duration); - - /* ok, it was started & we canceled timer */ - if (time_after(new_end, tmp->work.timer.expires)) - mod_timer(&tmp->work.timer, new_end); - else - add_timer(&tmp->work.timer); - - ieee80211_handle_roc_started(roc); - } - break; + local->hw_roc_channel = NULL; + local->hw_roc_cookie = 0; } - out_queue: - if (!queued) - list_add_tail(&roc->list, &local->roc_list); - - /* - * cookie is either the roc (for normal roc) - * or the SKB (for mgmt TX) - */ - if (txskb) - *cookie = (unsigned long)txskb; - else - *cookie = (unsigned long)roc; - - return 0; + return ret; } static int ieee80211_remain_on_channel(struct wiphy *wiphy, @@ -2288,64 +2145,42 @@ static int ieee80211_remain_on_channel(struct wiphy *wiphy, { struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); struct ieee80211_local *local = sdata->local; - int ret; - mutex_lock(&local->mtx); - ret = ieee80211_start_roc_work(local, sdata, chan, channel_type, - duration, cookie, NULL); - mutex_unlock(&local->mtx); + if (local->ops->remain_on_channel) { + int ret; - return ret; + mutex_lock(&local->mtx); + ret = ieee80211_remain_on_channel_hw(local, dev, + chan, channel_type, + duration, cookie); + local->hw_roc_for_tx = false; + mutex_unlock(&local->mtx); + + return ret; + } + + return ieee80211_wk_remain_on_channel(sdata, chan, channel_type, + duration, cookie); } -static int ieee80211_cancel_roc(struct ieee80211_local *local, - u64 cookie, bool mgmt_tx) +static int ieee80211_cancel_remain_on_channel_hw(struct ieee80211_local *local, + u64 cookie) { - struct ieee80211_roc_work *roc, *tmp, *found = NULL; int ret; - mutex_lock(&local->mtx); - list_for_each_entry_safe(roc, tmp, &local->roc_list, list) { - if (!mgmt_tx && (unsigned long)roc != cookie) - continue; - else if (mgmt_tx && roc->mgmt_tx_cookie != cookie) - continue; - - found = roc; - break; - } + lockdep_assert_held(&local->mtx); - if (!found) { - mutex_unlock(&local->mtx); + if (local->hw_roc_cookie != cookie) return -ENOENT; - } - if (local->ops->remain_on_channel) { - if (found->started) { - ret = drv_cancel_remain_on_channel(local); - if (WARN_ON_ONCE(ret)) { - mutex_unlock(&local->mtx); - return ret; - } - } - - list_del(&found->list); - - ieee80211_run_deferred_scan(local); - ieee80211_start_next_roc(local); - mutex_unlock(&local->mtx); - - ieee80211_roc_notify_destroy(found); - } else { - /* work may be pending so use it all the time */ - found->abort = true; - ieee80211_queue_delayed_work(&local->hw, &found->work, 0); + ret = drv_cancel_remain_on_channel(local); + if (ret) + return ret; - mutex_unlock(&local->mtx); + local->hw_roc_cookie = 0; + local->hw_roc_channel = NULL; - /* work will clean up etc */ - flush_delayed_work(&found->work); - } + ieee80211_recalc_idle(local); return 0; } @@ -2357,7 +2192,39 @@ static int ieee80211_cancel_remain_on_channel(struct wiphy *wiphy, struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); struct ieee80211_local *local = sdata->local; - return ieee80211_cancel_roc(local, cookie, false); + if (local->ops->cancel_remain_on_channel) { + int ret; + + mutex_lock(&local->mtx); + ret = ieee80211_cancel_remain_on_channel_hw(local, cookie); + mutex_unlock(&local->mtx); + + return ret; + } + + return ieee80211_wk_cancel_remain_on_channel(sdata, cookie); +} + +static enum work_done_result +ieee80211_offchan_tx_done(struct ieee80211_work *wk, struct sk_buff *skb) +{ + /* + * Use the data embedded in the work struct for reporting + * here so if the driver mangled the SKB before dropping + * it (which is the only way we really should get here) + * then we don't report mangled data. + * + * If there was no wait time, then by the time we get here + * the driver will likely not have reported the status yet, + * so in that case userspace will have to deal with it. + */ + + if (wk->offchan_tx.wait && !wk->offchan_tx.status) + cfg80211_mgmt_tx_status(wk->sdata->dev, + (unsigned long) wk->offchan_tx.frame, + wk->data, wk->data_len, false, GFP_KERNEL); + + return WORK_DONE_DESTROY; } static int ieee80211_mgmt_tx(struct wiphy *wiphy, struct net_device *dev, @@ -2371,10 +2238,10 @@ static int ieee80211_mgmt_tx(struct wiphy *wiphy, struct net_device *dev, struct ieee80211_local *local = sdata->local; struct sk_buff *skb; struct sta_info *sta; + struct ieee80211_work *wk; const struct ieee80211_mgmt *mgmt = (void *)buf; - bool need_offchan = false; u32 flags; - int ret; + bool is_offchan = false; if (dont_wait_for_ack) flags = IEEE80211_TX_CTL_NO_ACK; @@ -2382,28 +2249,33 @@ static int ieee80211_mgmt_tx(struct wiphy *wiphy, struct net_device *dev, flags = IEEE80211_TX_INTFL_NL80211_FRAME_TX | IEEE80211_TX_CTL_REQ_TX_STATUS; + /* Check that we are on the requested channel for transmission */ + if (chan != local->tmp_channel && + chan != local->oper_channel) + is_offchan = true; + if (channel_type_valid && + (channel_type != local->tmp_channel_type && + channel_type != local->_oper_channel_type)) + is_offchan = true; + + if (chan == local->hw_roc_channel) { + /* TODO: check channel type? */ + is_offchan = false; + flags |= IEEE80211_TX_CTL_TX_OFFCHAN; + } + if (no_cck) flags |= IEEE80211_TX_CTL_NO_CCK_RATE; + if (is_offchan && !offchan) + return -EBUSY; + switch (sdata->vif.type) { case NL80211_IFTYPE_ADHOC: - if (!sdata->vif.bss_conf.ibss_joined) - need_offchan = true; - /* fall through */ -#ifdef CONFIG_MAC80211_MESH - case NL80211_IFTYPE_MESH_POINT: - if (ieee80211_vif_is_mesh(&sdata->vif) && - !sdata->u.mesh.mesh_id_len) - need_offchan = true; - /* fall through */ -#endif case NL80211_IFTYPE_AP: case NL80211_IFTYPE_AP_VLAN: case NL80211_IFTYPE_P2P_GO: - if (sdata->vif.type != NL80211_IFTYPE_ADHOC && - !ieee80211_vif_is_mesh(&sdata->vif) && - !rcu_access_pointer(sdata->bss->beacon)) - need_offchan = true; + case NL80211_IFTYPE_MESH_POINT: if (!ieee80211_is_action(mgmt->frame_control) || mgmt->u.action.category == WLAN_CATEGORY_PUBLIC) break; @@ -2415,60 +2287,105 @@ static int ieee80211_mgmt_tx(struct wiphy *wiphy, struct net_device *dev, break; case NL80211_IFTYPE_STATION: case NL80211_IFTYPE_P2P_CLIENT: - if (!sdata->u.mgd.associated) - need_offchan = true; break; default: return -EOPNOTSUPP; } - mutex_lock(&local->mtx); - - /* Check if the operating channel is the requested channel */ - if (!need_offchan) { - need_offchan = chan != local->oper_channel; - if (channel_type_valid && - channel_type != local->_oper_channel_type) - need_offchan = true; - } - - if (need_offchan && !offchan) { - ret = -EBUSY; - goto out_unlock; - } - skb = dev_alloc_skb(local->hw.extra_tx_headroom + len); - if (!skb) { - ret = -ENOMEM; - goto out_unlock; - } + if (!skb) + return -ENOMEM; skb_reserve(skb, local->hw.extra_tx_headroom); memcpy(skb_put(skb, len), buf, len); IEEE80211_SKB_CB(skb)->flags = flags; + if (local->hw.flags & IEEE80211_HW_QUEUE_CONTROL && + flags & IEEE80211_TX_CTL_TX_OFFCHAN) + IEEE80211_SKB_CB(skb)->hw_queue = + local->hw.offchannel_tx_hw_queue; + skb->dev = sdata->dev; - if (!need_offchan) { - ieee80211_tx_skb(sdata, skb); - ret = 0; - goto out_unlock; + *cookie = (unsigned long) skb; + + if (is_offchan && local->ops->remain_on_channel) { + unsigned int duration; + int ret; + + mutex_lock(&local->mtx); + /* + * If the duration is zero, then the driver + * wouldn't actually do anything. Set it to + * 100 for now. + * + * TODO: cancel the off-channel operation + * when we get the SKB's TX status and + * the wait time was zero before. + */ + duration = 100; + if (wait) + duration = wait; + ret = ieee80211_remain_on_channel_hw(local, dev, chan, + channel_type, + duration, cookie); + if (ret) { + kfree_skb(skb); + mutex_unlock(&local->mtx); + return ret; + } + + local->hw_roc_for_tx = true; + local->hw_roc_duration = wait; + + /* + * queue up frame for transmission after + * ieee80211_ready_on_channel call + */ + + /* modify cookie to prevent API mismatches */ + *cookie ^= 2; + IEEE80211_SKB_CB(skb)->flags |= IEEE80211_TX_CTL_TX_OFFCHAN; + if (local->hw.flags & IEEE80211_HW_QUEUE_CONTROL) + IEEE80211_SKB_CB(skb)->hw_queue = + local->hw.offchannel_tx_hw_queue; + local->hw_roc_skb = skb; + local->hw_roc_skb_for_status = skb; + mutex_unlock(&local->mtx); + + return 0; } - IEEE80211_SKB_CB(skb)->flags |= IEEE80211_TX_CTL_TX_OFFCHAN; - if (local->hw.flags & IEEE80211_HW_QUEUE_CONTROL) - IEEE80211_SKB_CB(skb)->hw_queue = - local->hw.offchannel_tx_hw_queue; + /* + * Can transmit right away if the channel was the + * right one and there's no wait involved... If a + * wait is involved, we might otherwise not be on + * the right channel for long enough! + */ + if (!is_offchan && !wait && !sdata->vif.bss_conf.idle) { + ieee80211_tx_skb(sdata, skb); + return 0; + } - /* This will handle all kinds of coalescing and immediate TX */ - ret = ieee80211_start_roc_work(local, sdata, chan, channel_type, - wait, cookie, skb); - if (ret) + wk = kzalloc(sizeof(*wk) + len, GFP_KERNEL); + if (!wk) { kfree_skb(skb); - out_unlock: - mutex_unlock(&local->mtx); - return ret; + return -ENOMEM; + } + + wk->type = IEEE80211_WORK_OFFCHANNEL_TX; + wk->chan = chan; + wk->chan_type = channel_type; + wk->sdata = sdata; + wk->done = ieee80211_offchan_tx_done; + wk->offchan_tx.frame = skb; + wk->offchan_tx.wait = wait; + wk->data_len = len; + memcpy(wk->data, buf, len); + + ieee80211_add_work(wk); + return 0; } static int ieee80211_mgmt_tx_cancel_wait(struct wiphy *wiphy, @@ -2477,8 +2394,45 @@ static int ieee80211_mgmt_tx_cancel_wait(struct wiphy *wiphy, { struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); struct ieee80211_local *local = sdata->local; + struct ieee80211_work *wk; + int ret = -ENOENT; - return ieee80211_cancel_roc(local, cookie, true); + mutex_lock(&local->mtx); + + if (local->ops->cancel_remain_on_channel) { + cookie ^= 2; + ret = ieee80211_cancel_remain_on_channel_hw(local, cookie); + + if (ret == 0) { + kfree_skb(local->hw_roc_skb); + local->hw_roc_skb = NULL; + local->hw_roc_skb_for_status = NULL; + } + + mutex_unlock(&local->mtx); + + return ret; + } + + list_for_each_entry(wk, &local->work_list, list) { + if (wk->sdata != sdata) + continue; + + if (wk->type != IEEE80211_WORK_OFFCHANNEL_TX) + continue; + + if (cookie != (unsigned long) wk->offchan_tx.frame) + continue; + + wk->timeout = jiffies; + + ieee80211_queue_work(&local->hw, &local->work_work); + ret = 0; + break; + } + mutex_unlock(&local->mtx); + + return ret; } static void ieee80211_mgmt_frame_register(struct wiphy *wiphy, @@ -2978,7 +2932,7 @@ struct cfg80211_ops mac80211_config_ops = { #endif .change_bss = ieee80211_change_bss, .set_txq_params = ieee80211_set_txq_params, - .set_monitor_channel = ieee80211_set_monitor_channel, + .set_channel = ieee80211_set_channel, .suspend = ieee80211_suspend, .resume = ieee80211_resume, .scan = ieee80211_scan, diff --git a/trunk/net/mac80211/debugfs_netdev.c b/trunk/net/mac80211/debugfs_netdev.c index d4272ff43f71..1a3b36154e73 100644 --- a/trunk/net/mac80211/debugfs_netdev.c +++ b/trunk/net/mac80211/debugfs_netdev.c @@ -607,7 +607,6 @@ static void add_mesh_config(struct ieee80211_sub_if_data *sdata) MESHPARAMS_ADD(min_discovery_timeout); MESHPARAMS_ADD(dot11MeshHWMPRootMode); MESHPARAMS_ADD(dot11MeshHWMPRannInterval); - MESHPARAMS_ADD(dot11MeshForwarding); MESHPARAMS_ADD(dot11MeshGateAnnouncementProtocol); MESHPARAMS_ADD(rssi_threshold); MESHPARAMS_ADD(ht_opmode); diff --git a/trunk/net/mac80211/ieee80211_i.h b/trunk/net/mac80211/ieee80211_i.h index e6cbf5b68c89..8c026abcb8d9 100644 --- a/trunk/net/mac80211/ieee80211_i.h +++ b/trunk/net/mac80211/ieee80211_i.h @@ -317,30 +317,55 @@ struct mesh_preq_queue { u8 flags; }; -#if HZ/100 == 0 -#define IEEE80211_ROC_MIN_LEFT 1 -#else -#define IEEE80211_ROC_MIN_LEFT (HZ/100) -#endif +enum ieee80211_work_type { + IEEE80211_WORK_ABORT, + IEEE80211_WORK_REMAIN_ON_CHANNEL, + IEEE80211_WORK_OFFCHANNEL_TX, +}; + +/** + * enum work_done_result - indicates what to do after work was done + * + * @WORK_DONE_DESTROY: This work item is no longer needed, destroy. + * @WORK_DONE_REQUEUE: This work item was reset to be reused, and + * should be requeued. + */ +enum work_done_result { + WORK_DONE_DESTROY, + WORK_DONE_REQUEUE, +}; -struct ieee80211_roc_work { +struct ieee80211_work { struct list_head list; - struct list_head dependents; - struct delayed_work work; + struct rcu_head rcu_head; struct ieee80211_sub_if_data *sdata; + enum work_done_result (*done)(struct ieee80211_work *wk, + struct sk_buff *skb); + struct ieee80211_channel *chan; enum nl80211_channel_type chan_type; - bool started, abort, hw_begun, notified; + unsigned long timeout; + enum ieee80211_work_type type; - unsigned long hw_start_time; + bool started; - u32 duration, req_duration; - struct sk_buff *frame; - u64 mgmt_tx_cookie; + union { + struct { + u32 duration; + } remain; + struct { + struct sk_buff *frame; + u32 wait; + bool status; + } offchan_tx; + }; + + size_t data_len; + u8 data[]; }; /* flags used in struct ieee80211_if_managed.flags */ @@ -822,6 +847,13 @@ struct ieee80211_local { const struct ieee80211_ops *ops; + /* + * work stuff, potentially off-channel (in the future) + */ + struct list_head work_list; + struct timer_list work_timer; + struct work_struct work_work; + /* * private workqueue to mac80211. mac80211 makes this accessible * via ieee80211_queue_work() @@ -1056,12 +1088,14 @@ struct ieee80211_local { } debugfs; #endif - /* - * Remain-on-channel support - */ - struct list_head roc_list; + struct ieee80211_channel *hw_roc_channel; + struct net_device *hw_roc_dev; + struct sk_buff *hw_roc_skb, *hw_roc_skb_for_status; struct work_struct hw_roc_start, hw_roc_done; - unsigned long hw_roc_start_time; + enum nl80211_channel_type hw_roc_channel_type; + unsigned int hw_roc_duration; + u32 hw_roc_cookie; + bool hw_roc_for_tx; struct idr ack_status_frames; spinlock_t ack_status_lock; @@ -1257,12 +1291,7 @@ void ieee80211_offchannel_stop_vifs(struct ieee80211_local *local, bool offchannel_ps_enable); void ieee80211_offchannel_return(struct ieee80211_local *local, bool offchannel_ps_disable); -void ieee80211_roc_setup(struct ieee80211_local *local); -void ieee80211_start_next_roc(struct ieee80211_local *local); -void ieee80211_roc_purge(struct ieee80211_sub_if_data *sdata); -void ieee80211_roc_notify_destroy(struct ieee80211_roc_work *roc); -void ieee80211_sw_roc_work(struct work_struct *work); -void ieee80211_handle_roc_started(struct ieee80211_roc_work *roc); +void ieee80211_hw_roc_setup(struct ieee80211_local *local); /* interface handling */ int ieee80211_iface_init(void); @@ -1472,6 +1501,18 @@ u8 *ieee80211_ie_build_ht_oper(u8 *pos, struct ieee80211_sta_ht_cap *ht_cap, enum nl80211_channel_type channel_type, u16 prot_mode); +/* internal work items */ +void ieee80211_work_init(struct ieee80211_local *local); +void ieee80211_add_work(struct ieee80211_work *wk); +void free_work(struct ieee80211_work *wk); +void ieee80211_work_purge(struct ieee80211_sub_if_data *sdata); +int ieee80211_wk_remain_on_channel(struct ieee80211_sub_if_data *sdata, + struct ieee80211_channel *chan, + enum nl80211_channel_type channel_type, + unsigned int duration, u64 *cookie); +int ieee80211_wk_cancel_remain_on_channel( + struct ieee80211_sub_if_data *sdata, u64 cookie); + /* channel management */ enum ieee80211_chan_mode { CHAN_MODE_UNDEFINED, diff --git a/trunk/net/mac80211/iface.c b/trunk/net/mac80211/iface.c index 87aeb4f21ffd..bebc45db9c7a 100644 --- a/trunk/net/mac80211/iface.c +++ b/trunk/net/mac80211/iface.c @@ -528,7 +528,10 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata, */ netif_tx_stop_all_queues(sdata->dev); - ieee80211_roc_purge(sdata); + /* + * Purge work for this interface. + */ + ieee80211_work_purge(sdata); /* * Remove all stations associated with this interface. @@ -1441,9 +1444,9 @@ u32 __ieee80211_recalc_idle(struct ieee80211_local *local) { struct ieee80211_sub_if_data *sdata; int count = 0; - bool working = false, scanning = false; + bool working = false, scanning = false, hw_roc = false; + struct ieee80211_work *wk; unsigned int led_trig_start = 0, led_trig_stop = 0; - struct ieee80211_roc_work *roc; #ifdef CONFIG_PROVE_LOCKING WARN_ON(debug_locks && !lockdep_rtnl_is_held() && @@ -1478,11 +1481,9 @@ u32 __ieee80211_recalc_idle(struct ieee80211_local *local) count++; } - if (!local->ops->remain_on_channel) { - list_for_each_entry(roc, &local->roc_list, list) { - working = true; - roc->sdata->vif.bss_conf.idle = false; - } + list_for_each_entry(wk, &local->work_list, list) { + working = true; + wk->sdata->vif.bss_conf.idle = false; } if (local->scan_sdata && @@ -1491,6 +1492,9 @@ u32 __ieee80211_recalc_idle(struct ieee80211_local *local) local->scan_sdata->vif.bss_conf.idle = false; } + if (local->hw_roc_channel) + hw_roc = true; + list_for_each_entry(sdata, &local->interfaces, list) { if (sdata->vif.type == NL80211_IFTYPE_MONITOR || sdata->vif.type == NL80211_IFTYPE_AP_VLAN) @@ -1502,7 +1506,7 @@ u32 __ieee80211_recalc_idle(struct ieee80211_local *local) ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_IDLE); } - if (working || scanning) + if (working || scanning || hw_roc) led_trig_start |= IEEE80211_TPT_LEDTRIG_FL_WORK; else led_trig_stop |= IEEE80211_TPT_LEDTRIG_FL_WORK; @@ -1514,6 +1518,8 @@ u32 __ieee80211_recalc_idle(struct ieee80211_local *local) ieee80211_mod_tpt_led_trig(local, led_trig_start, led_trig_stop); + if (hw_roc) + return ieee80211_idle_off(local, "hw remain-on-channel"); if (working) return ieee80211_idle_off(local, "working"); if (scanning) diff --git a/trunk/net/mac80211/main.c b/trunk/net/mac80211/main.c index d81c178c7712..779ac613ee57 100644 --- a/trunk/net/mac80211/main.c +++ b/trunk/net/mac80211/main.c @@ -625,6 +625,8 @@ struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len, INIT_DELAYED_WORK(&local->scan_work, ieee80211_scan_work); + ieee80211_work_init(local); + INIT_WORK(&local->restart_work, ieee80211_restart_work); INIT_WORK(&local->reconfig_filter, ieee80211_reconfig_filter); @@ -667,7 +669,7 @@ struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len, ieee80211_led_names(local); - ieee80211_roc_setup(local); + ieee80211_hw_roc_setup(local); return &local->hw; } @@ -1014,6 +1016,12 @@ void ieee80211_unregister_hw(struct ieee80211_hw *hw) rtnl_unlock(); + /* + * Now all work items will be gone, but the + * timer might still be armed, so delete it + */ + del_timer_sync(&local->work_timer); + cancel_work_sync(&local->restart_work); cancel_work_sync(&local->reconfig_filter); diff --git a/trunk/net/mac80211/mlme.c b/trunk/net/mac80211/mlme.c index 0f45d02e0ba7..7c077158eb88 100644 --- a/trunk/net/mac80211/mlme.c +++ b/trunk/net/mac80211/mlme.c @@ -930,6 +930,11 @@ void ieee80211_recalc_ps(struct ieee80211_local *local, s32 latency) return; } + if (!list_empty(&local->work_list)) { + local->ps_sdata = NULL; + goto change; + } + list_for_each_entry(sdata, &local->interfaces, list) { if (!ieee80211_sdata_running(sdata)) continue; @@ -1002,6 +1007,7 @@ void ieee80211_recalc_ps(struct ieee80211_local *local, s32 latency) local->ps_sdata = NULL; } + change: ieee80211_change_ps(local); } @@ -1205,22 +1211,6 @@ static void ieee80211_sta_wmm_params(struct ieee80211_local *local, sdata->vif.bss_conf.qos = true; } -static void __ieee80211_stop_poll(struct ieee80211_sub_if_data *sdata) -{ - lockdep_assert_held(&sdata->local->mtx); - - sdata->u.mgd.flags &= ~(IEEE80211_STA_CONNECTION_POLL | - IEEE80211_STA_BEACON_POLL); - ieee80211_run_deferred_scan(sdata->local); -} - -static void ieee80211_stop_poll(struct ieee80211_sub_if_data *sdata) -{ - mutex_lock(&sdata->local->mtx); - __ieee80211_stop_poll(sdata); - mutex_unlock(&sdata->local->mtx); -} - static u32 ieee80211_handle_bss_capability(struct ieee80211_sub_if_data *sdata, u16 capab, bool erp_valid, u8 erp) { @@ -1286,7 +1276,8 @@ static void ieee80211_set_associated(struct ieee80211_sub_if_data *sdata, sdata->u.mgd.flags |= IEEE80211_STA_RESET_SIGNAL_AVE; /* just to be sure */ - ieee80211_stop_poll(sdata); + sdata->u.mgd.flags &= ~(IEEE80211_STA_CONNECTION_POLL | + IEEE80211_STA_BEACON_POLL); ieee80211_led_assoc(local, 1); @@ -1456,7 +1447,8 @@ static void ieee80211_reset_ap_probe(struct ieee80211_sub_if_data *sdata) return; } - __ieee80211_stop_poll(sdata); + ifmgd->flags &= ~(IEEE80211_STA_CONNECTION_POLL | + IEEE80211_STA_BEACON_POLL); mutex_lock(&local->iflist_mtx); ieee80211_recalc_ps(local, -1); @@ -1476,6 +1468,7 @@ static void ieee80211_reset_ap_probe(struct ieee80211_sub_if_data *sdata) round_jiffies_up(jiffies + IEEE80211_CONNECTION_IDLE_TIME)); out: + ieee80211_run_deferred_scan(local); mutex_unlock(&local->mtx); } @@ -2401,11 +2394,7 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata, net_dbg_ratelimited("%s: cancelling probereq poll due to a received beacon\n", sdata->name); #endif - mutex_lock(&local->mtx); ifmgd->flags &= ~IEEE80211_STA_BEACON_POLL; - ieee80211_run_deferred_scan(local); - mutex_unlock(&local->mtx); - mutex_lock(&local->iflist_mtx); ieee80211_recalc_ps(local, -1); mutex_unlock(&local->iflist_mtx); @@ -2592,7 +2581,8 @@ static void ieee80211_sta_connection_lost(struct ieee80211_sub_if_data *sdata, struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; u8 frame_buf[DEAUTH_DISASSOC_LEN]; - ieee80211_stop_poll(sdata); + ifmgd->flags &= ~(IEEE80211_STA_CONNECTION_POLL | + IEEE80211_STA_BEACON_POLL); ieee80211_set_disassoc(sdata, IEEE80211_STYPE_DEAUTH, reason, false, frame_buf); @@ -2870,7 +2860,8 @@ static void ieee80211_restart_sta_timer(struct ieee80211_sub_if_data *sdata) u32 flags; if (sdata->vif.type == NL80211_IFTYPE_STATION) { - __ieee80211_stop_poll(sdata); + sdata->u.mgd.flags &= ~(IEEE80211_STA_BEACON_POLL | + IEEE80211_STA_CONNECTION_POLL); /* let's probe the connection once */ flags = sdata->local->hw.flags; @@ -2939,10 +2930,7 @@ void ieee80211_sta_restart(struct ieee80211_sub_if_data *sdata) if (test_and_clear_bit(TMR_RUNNING_CHANSW, &ifmgd->timers_running)) add_timer(&ifmgd->chswitch_timer); ieee80211_sta_reset_beacon_monitor(sdata); - - mutex_lock(&sdata->local->mtx); ieee80211_restart_sta_timer(sdata); - mutex_unlock(&sdata->local->mtx); } #endif @@ -3311,15 +3299,11 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata, * We can set this to true for non-11n hardware, that'll be checked * separately along with the peer capabilities. */ - for (i = 0; i < req->crypto.n_ciphers_pairwise; i++) { + for (i = 0; i < req->crypto.n_ciphers_pairwise; i++) if (req->crypto.ciphers_pairwise[i] == WLAN_CIPHER_SUITE_WEP40 || req->crypto.ciphers_pairwise[i] == WLAN_CIPHER_SUITE_TKIP || - req->crypto.ciphers_pairwise[i] == WLAN_CIPHER_SUITE_WEP104) { + req->crypto.ciphers_pairwise[i] == WLAN_CIPHER_SUITE_WEP104) ifmgd->flags |= IEEE80211_STA_DISABLE_11N; - netdev_info(sdata->dev, - "disabling HT due to WEP/TKIP use\n"); - } - } if (req->flags & ASSOC_REQ_DISABLE_HT) ifmgd->flags |= IEEE80211_STA_DISABLE_11N; @@ -3327,11 +3311,8 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata, /* Also disable HT if we don't support it or the AP doesn't use WMM */ sband = local->hw.wiphy->bands[req->bss->channel->band]; if (!sband->ht_cap.ht_supported || - local->hw.queues < IEEE80211_NUM_ACS || !bss->wmm_used) { + local->hw.queues < IEEE80211_NUM_ACS || !bss->wmm_used) ifmgd->flags |= IEEE80211_STA_DISABLE_11N; - netdev_info(sdata->dev, - "disabling HT as WMM/QoS is not supported\n"); - } memcpy(&ifmgd->ht_capa, &req->ht_capa, sizeof(ifmgd->ht_capa)); memcpy(&ifmgd->ht_capa_mask, &req->ht_capa_mask, diff --git a/trunk/net/mac80211/offchannel.c b/trunk/net/mac80211/offchannel.c index abb226dc4753..f054e94901a2 100644 --- a/trunk/net/mac80211/offchannel.c +++ b/trunk/net/mac80211/offchannel.c @@ -16,7 +16,6 @@ #include #include "ieee80211_i.h" #include "driver-trace.h" -#include "driver-ops.h" /* * Tell our hardware to disable PS. @@ -182,58 +181,34 @@ void ieee80211_offchannel_return(struct ieee80211_local *local, mutex_unlock(&local->iflist_mtx); } -void ieee80211_handle_roc_started(struct ieee80211_roc_work *roc) -{ - if (roc->notified) - return; - - if (roc->mgmt_tx_cookie) { - if (!WARN_ON(!roc->frame)) { - ieee80211_tx_skb(roc->sdata, roc->frame); - roc->frame = NULL; - } - } else { - cfg80211_ready_on_channel(roc->sdata->dev, (unsigned long)roc, - roc->chan, roc->chan_type, - roc->req_duration, GFP_KERNEL); - } - - roc->notified = true; -} - static void ieee80211_hw_roc_start(struct work_struct *work) { struct ieee80211_local *local = container_of(work, struct ieee80211_local, hw_roc_start); - struct ieee80211_roc_work *roc, *dep, *tmp; + struct ieee80211_sub_if_data *sdata; mutex_lock(&local->mtx); - if (list_empty(&local->roc_list)) - goto out_unlock; - - roc = list_first_entry(&local->roc_list, struct ieee80211_roc_work, - list); - - if (!roc->started) - goto out_unlock; + if (!local->hw_roc_channel) { + mutex_unlock(&local->mtx); + return; + } - roc->hw_begun = true; - roc->hw_start_time = local->hw_roc_start_time; + if (local->hw_roc_skb) { + sdata = IEEE80211_DEV_TO_SUB_IF(local->hw_roc_dev); + ieee80211_tx_skb(sdata, local->hw_roc_skb); + local->hw_roc_skb = NULL; + } else { + cfg80211_ready_on_channel(local->hw_roc_dev, + local->hw_roc_cookie, + local->hw_roc_channel, + local->hw_roc_channel_type, + local->hw_roc_duration, + GFP_KERNEL); + } - ieee80211_handle_roc_started(roc); - list_for_each_entry_safe(dep, tmp, &roc->dependents, list) { - ieee80211_handle_roc_started(dep); + ieee80211_recalc_idle(local); - if (dep->duration > roc->duration) { - u32 dur = dep->duration; - dep->duration = dur - roc->duration; - roc->duration = dur; - list_del(&dep->list); - list_add(&dep->list, &roc->list); - } - } - out_unlock: mutex_unlock(&local->mtx); } @@ -241,179 +216,36 @@ void ieee80211_ready_on_channel(struct ieee80211_hw *hw) { struct ieee80211_local *local = hw_to_local(hw); - local->hw_roc_start_time = jiffies; - trace_api_ready_on_channel(local); ieee80211_queue_work(hw, &local->hw_roc_start); } EXPORT_SYMBOL_GPL(ieee80211_ready_on_channel); -void ieee80211_start_next_roc(struct ieee80211_local *local) -{ - struct ieee80211_roc_work *roc; - - lockdep_assert_held(&local->mtx); - - if (list_empty(&local->roc_list)) { - ieee80211_run_deferred_scan(local); - return; - } - - roc = list_first_entry(&local->roc_list, struct ieee80211_roc_work, - list); - - if (local->ops->remain_on_channel) { - int ret, duration = roc->duration; - - /* XXX: duplicated, see ieee80211_start_roc_work() */ - if (!duration) - duration = 10; - - ret = drv_remain_on_channel(local, roc->chan, - roc->chan_type, - duration); - - roc->started = true; - - if (ret) { - wiphy_warn(local->hw.wiphy, - "failed to start next HW ROC (%d)\n", ret); - /* - * queue the work struct again to avoid recursion - * when multiple failures occur - */ - ieee80211_remain_on_channel_expired(&local->hw); - } - } else { - /* delay it a bit */ - ieee80211_queue_delayed_work(&local->hw, &roc->work, - round_jiffies_relative(HZ/2)); - } -} - -void ieee80211_roc_notify_destroy(struct ieee80211_roc_work *roc) -{ - struct ieee80211_roc_work *dep, *tmp; - - /* was never transmitted */ - if (roc->frame) { - cfg80211_mgmt_tx_status(roc->sdata->dev, - (unsigned long)roc->frame, - roc->frame->data, roc->frame->len, - false, GFP_KERNEL); - kfree_skb(roc->frame); - } - - if (!roc->mgmt_tx_cookie) - cfg80211_remain_on_channel_expired(roc->sdata->dev, - (unsigned long)roc, - roc->chan, roc->chan_type, - GFP_KERNEL); - - list_for_each_entry_safe(dep, tmp, &roc->dependents, list) - ieee80211_roc_notify_destroy(dep); - - kfree(roc); -} - -void ieee80211_sw_roc_work(struct work_struct *work) -{ - struct ieee80211_roc_work *roc = - container_of(work, struct ieee80211_roc_work, work.work); - struct ieee80211_sub_if_data *sdata = roc->sdata; - struct ieee80211_local *local = sdata->local; - - mutex_lock(&local->mtx); - - if (roc->abort) - goto finish; - - if (WARN_ON(list_empty(&local->roc_list))) - goto out_unlock; - - if (WARN_ON(roc != list_first_entry(&local->roc_list, - struct ieee80211_roc_work, - list))) - goto out_unlock; - - if (!roc->started) { - struct ieee80211_roc_work *dep; - - /* start this ROC */ - - /* switch channel etc */ - ieee80211_recalc_idle(local); - - local->tmp_channel = roc->chan; - local->tmp_channel_type = roc->chan_type; - ieee80211_hw_config(local, 0); - - /* tell userspace or send frame */ - ieee80211_handle_roc_started(roc); - list_for_each_entry(dep, &roc->dependents, list) - ieee80211_handle_roc_started(dep); - - /* if it was pure TX, just finish right away */ - if (!roc->duration) - goto finish; - - roc->started = true; - ieee80211_queue_delayed_work(&local->hw, &roc->work, - msecs_to_jiffies(roc->duration)); - } else { - /* finish this ROC */ - finish: - list_del(&roc->list); - ieee80211_roc_notify_destroy(roc); - - if (roc->started) { - drv_flush(local, false); - - local->tmp_channel = NULL; - ieee80211_hw_config(local, 0); - - ieee80211_offchannel_return(local, true); - } - - ieee80211_recalc_idle(local); - - ieee80211_start_next_roc(local); - ieee80211_run_deferred_scan(local); - } - - out_unlock: - mutex_unlock(&local->mtx); -} - static void ieee80211_hw_roc_done(struct work_struct *work) { struct ieee80211_local *local = container_of(work, struct ieee80211_local, hw_roc_done); - struct ieee80211_roc_work *roc; mutex_lock(&local->mtx); - if (list_empty(&local->roc_list)) - goto out_unlock; - - roc = list_first_entry(&local->roc_list, struct ieee80211_roc_work, - list); - - if (!roc->started) - goto out_unlock; - - list_del(&roc->list); + if (!local->hw_roc_channel) { + mutex_unlock(&local->mtx); + return; + } - ieee80211_roc_notify_destroy(roc); + if (!local->hw_roc_for_tx) + cfg80211_remain_on_channel_expired(local->hw_roc_dev, + local->hw_roc_cookie, + local->hw_roc_channel, + local->hw_roc_channel_type, + GFP_KERNEL); - /* if there's another roc, start it now */ - ieee80211_start_next_roc(local); + local->hw_roc_channel = NULL; + local->hw_roc_cookie = 0; - /* or scan maybe */ - ieee80211_run_deferred_scan(local); + ieee80211_recalc_idle(local); - out_unlock: mutex_unlock(&local->mtx); } @@ -427,48 +259,8 @@ void ieee80211_remain_on_channel_expired(struct ieee80211_hw *hw) } EXPORT_SYMBOL_GPL(ieee80211_remain_on_channel_expired); -void ieee80211_roc_setup(struct ieee80211_local *local) +void ieee80211_hw_roc_setup(struct ieee80211_local *local) { INIT_WORK(&local->hw_roc_start, ieee80211_hw_roc_start); INIT_WORK(&local->hw_roc_done, ieee80211_hw_roc_done); - INIT_LIST_HEAD(&local->roc_list); -} - -void ieee80211_roc_purge(struct ieee80211_sub_if_data *sdata) -{ - struct ieee80211_local *local = sdata->local; - struct ieee80211_roc_work *roc, *tmp; - LIST_HEAD(tmp_list); - - mutex_lock(&local->mtx); - list_for_each_entry_safe(roc, tmp, &local->roc_list, list) { - if (roc->sdata != sdata) - continue; - - if (roc->started && local->ops->remain_on_channel) { - /* can race, so ignore return value */ - drv_cancel_remain_on_channel(local); - } - - list_move_tail(&roc->list, &tmp_list); - roc->abort = true; - } - - ieee80211_start_next_roc(local); - ieee80211_run_deferred_scan(local); - mutex_unlock(&local->mtx); - - list_for_each_entry_safe(roc, tmp, &tmp_list, list) { - if (local->ops->remain_on_channel) { - list_del(&roc->list); - ieee80211_roc_notify_destroy(roc); - } else { - ieee80211_queue_delayed_work(&local->hw, &roc->work, 0); - - /* work will clean up etc */ - flush_delayed_work(&roc->work); - } - } - - WARN_ON_ONCE(!list_empty(&tmp_list)); } diff --git a/trunk/net/mac80211/pm.c b/trunk/net/mac80211/pm.c index 98c128be3827..af1c4e26e965 100644 --- a/trunk/net/mac80211/pm.c +++ b/trunk/net/mac80211/pm.c @@ -77,7 +77,6 @@ int __ieee80211_suspend(struct ieee80211_hw *hw, struct cfg80211_wowlan *wowlan) int err = drv_suspend(local, wowlan); if (err < 0) { local->quiescing = false; - local->wowlan = false; return err; } else if (err > 0) { WARN_ON(err != 1); diff --git a/trunk/net/mac80211/scan.c b/trunk/net/mac80211/scan.c index 379f178eab5f..169da0742c81 100644 --- a/trunk/net/mac80211/scan.c +++ b/trunk/net/mac80211/scan.c @@ -323,7 +323,7 @@ static void __ieee80211_scan_completed(struct ieee80211_hw *hw, bool aborted, ieee80211_mlme_notify_scan_completed(local); ieee80211_ibss_notify_scan_completed(local); ieee80211_mesh_notify_scan_completed(local); - ieee80211_start_next_roc(local); + ieee80211_queue_work(&local->hw, &local->work_work); } void ieee80211_scan_completed(struct ieee80211_hw *hw, bool aborted) @@ -376,7 +376,7 @@ static int ieee80211_start_sw_scan(struct ieee80211_local *local) static bool ieee80211_can_scan(struct ieee80211_local *local, struct ieee80211_sub_if_data *sdata) { - if (!list_empty(&local->roc_list)) + if (!list_empty(&local->work_list)) return false; if (sdata->vif.type == NL80211_IFTYPE_STATION && diff --git a/trunk/net/mac80211/sta_info.c b/trunk/net/mac80211/sta_info.c index 77dcf2f89d42..0a70f797dcf1 100644 --- a/trunk/net/mac80211/sta_info.c +++ b/trunk/net/mac80211/sta_info.c @@ -377,7 +377,7 @@ static int sta_info_insert_finish(struct sta_info *sta) __acquires(RCU) /* make the station visible */ sta_info_hash_add(local, sta); - list_add_rcu(&sta->list, &local->sta_list); + list_add(&sta->list, &local->sta_list); set_sta_flag(sta, WLAN_STA_INSERTED); @@ -686,7 +686,7 @@ int __must_check __sta_info_destroy(struct sta_info *sta) if (ret) return ret; - list_del_rcu(&sta->list); + list_del(&sta->list); mutex_lock(&local->key_mtx); for (i = 0; i < NUM_DEFAULT_KEYS; i++) diff --git a/trunk/net/mac80211/status.c b/trunk/net/mac80211/status.c index 6b4f42527887..63a769015068 100644 --- a/trunk/net/mac80211/status.c +++ b/trunk/net/mac80211/status.c @@ -520,16 +520,36 @@ void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb) if (info->flags & IEEE80211_TX_INTFL_NL80211_FRAME_TX) { u64 cookie = (unsigned long)skb; - acked = info->flags & IEEE80211_TX_STAT_ACK; if (ieee80211_is_nullfunc(hdr->frame_control) || - ieee80211_is_qos_nullfunc(hdr->frame_control)) + ieee80211_is_qos_nullfunc(hdr->frame_control)) { + acked = info->flags & IEEE80211_TX_STAT_ACK; + cfg80211_probe_status(skb->dev, hdr->addr1, cookie, acked, GFP_ATOMIC); - else + } else { + struct ieee80211_work *wk; + + rcu_read_lock(); + list_for_each_entry_rcu(wk, &local->work_list, list) { + if (wk->type != IEEE80211_WORK_OFFCHANNEL_TX) + continue; + if (wk->offchan_tx.frame != skb) + continue; + wk->offchan_tx.status = true; + break; + } + rcu_read_unlock(); + if (local->hw_roc_skb_for_status == skb) { + cookie = local->hw_roc_cookie ^ 2; + local->hw_roc_skb_for_status = NULL; + } + cfg80211_mgmt_tx_status( skb->dev, cookie, skb->data, skb->len, - acked, GFP_ATOMIC); + !!(info->flags & IEEE80211_TX_STAT_ACK), + GFP_ATOMIC); + } } if (unlikely(info->ack_frame_id)) { diff --git a/trunk/net/mac80211/tx.c b/trunk/net/mac80211/tx.c index af25c4e7ec5c..0c3476530339 100644 --- a/trunk/net/mac80211/tx.c +++ b/trunk/net/mac80211/tx.c @@ -1735,7 +1735,7 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb, __le16 fc; struct ieee80211_hdr hdr; struct ieee80211s_hdr mesh_hdr __maybe_unused; - struct mesh_path __maybe_unused *mppath = NULL, *mpath = NULL; + struct mesh_path __maybe_unused *mppath = NULL; const u8 *encaps_data; int encaps_len, skip_header_bytes; int nh_pos, h_pos; @@ -1801,11 +1801,8 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb, goto fail; } rcu_read_lock(); - if (!is_multicast_ether_addr(skb->data)) { - mpath = mesh_path_lookup(skb->data, sdata); - if (!mpath) - mppath = mpp_path_lookup(skb->data, sdata); - } + if (!is_multicast_ether_addr(skb->data)) + mppath = mpp_path_lookup(skb->data, sdata); /* * Use address extension if it is a packet from diff --git a/trunk/net/mac80211/util.c b/trunk/net/mac80211/util.c index 1df4019f294b..a44c6807df01 100644 --- a/trunk/net/mac80211/util.c +++ b/trunk/net/mac80211/util.c @@ -804,7 +804,7 @@ void ieee80211_set_wmm_default(struct ieee80211_sub_if_data *sdata, struct ieee80211_local *local = sdata->local; struct ieee80211_tx_queue_params qparam; int ac; - bool use_11b, enable_qos; + bool use_11b; int aCWmin, aCWmax; if (!local->ops->conf_tx) @@ -818,13 +818,6 @@ void ieee80211_set_wmm_default(struct ieee80211_sub_if_data *sdata, use_11b = (local->hw.conf.channel->band == IEEE80211_BAND_2GHZ) && !(sdata->flags & IEEE80211_SDATA_OPERATING_GMODE); - /* - * By default disable QoS in STA mode for old access points, which do - * not support 802.11e. New APs will provide proper queue parameters, - * that we will configure later. - */ - enable_qos = (sdata->vif.type != NL80211_IFTYPE_STATION); - for (ac = 0; ac < IEEE80211_NUM_ACS; ac++) { /* Set defaults according to 802.11-2007 Table 7-37 */ aCWmax = 1023; @@ -833,47 +826,38 @@ void ieee80211_set_wmm_default(struct ieee80211_sub_if_data *sdata, else aCWmin = 15; - if (enable_qos) { - switch (ac) { - case IEEE80211_AC_BK: - qparam.cw_max = aCWmax; - qparam.cw_min = aCWmin; - qparam.txop = 0; - qparam.aifs = 7; - break; - /* never happens but let's not leave undefined */ - default: - case IEEE80211_AC_BE: - qparam.cw_max = aCWmax; - qparam.cw_min = aCWmin; - qparam.txop = 0; - qparam.aifs = 3; - break; - case IEEE80211_AC_VI: - qparam.cw_max = aCWmin; - qparam.cw_min = (aCWmin + 1) / 2 - 1; - if (use_11b) - qparam.txop = 6016/32; - else - qparam.txop = 3008/32; - qparam.aifs = 2; - break; - case IEEE80211_AC_VO: - qparam.cw_max = (aCWmin + 1) / 2 - 1; - qparam.cw_min = (aCWmin + 1) / 4 - 1; - if (use_11b) - qparam.txop = 3264/32; - else - qparam.txop = 1504/32; - qparam.aifs = 2; - break; - } - } else { - /* Confiure old 802.11b/g medium access rules. */ + switch (ac) { + case IEEE80211_AC_BK: + qparam.cw_max = aCWmax; + qparam.cw_min = aCWmin; + qparam.txop = 0; + qparam.aifs = 7; + break; + default: /* never happens but let's not leave undefined */ + case IEEE80211_AC_BE: qparam.cw_max = aCWmax; qparam.cw_min = aCWmin; qparam.txop = 0; + qparam.aifs = 3; + break; + case IEEE80211_AC_VI: + qparam.cw_max = aCWmin; + qparam.cw_min = (aCWmin + 1) / 2 - 1; + if (use_11b) + qparam.txop = 6016/32; + else + qparam.txop = 3008/32; + qparam.aifs = 2; + break; + case IEEE80211_AC_VO: + qparam.cw_max = (aCWmin + 1) / 2 - 1; + qparam.cw_min = (aCWmin + 1) / 4 - 1; + if (use_11b) + qparam.txop = 3264/32; + else + qparam.txop = 1504/32; qparam.aifs = 2; + break; } qparam.uapsd = false; @@ -882,8 +866,12 @@ void ieee80211_set_wmm_default(struct ieee80211_sub_if_data *sdata, drv_conf_tx(local, sdata, ac, &qparam); } + /* after reinitialize QoS TX queues setting to default, + * disable QoS at all */ + if (sdata->vif.type != NL80211_IFTYPE_MONITOR) { - sdata->vif.bss_conf.qos = enable_qos; + sdata->vif.bss_conf.qos = + sdata->vif.type != NL80211_IFTYPE_STATION; if (bss_notify) ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_QOS); @@ -1279,19 +1267,14 @@ int ieee80211_reconfig(struct ieee80211_local *local) /* add STAs back */ mutex_lock(&local->sta_mtx); list_for_each_entry(sta, &local->sta_list, list) { - enum ieee80211_sta_state state; + if (sta->uploaded) { + enum ieee80211_sta_state state; - if (!sta->uploaded) - continue; - - /* AP-mode stations will be added later */ - if (sta->sdata->vif.type == NL80211_IFTYPE_AP) - continue; - - for (state = IEEE80211_STA_NOTEXIST; - state < sta->sta_state; state++) - WARN_ON(drv_sta_state(local, sta->sdata, sta, state, - state + 1)); + for (state = IEEE80211_STA_NOTEXIST; + state < sta->sta_state - 1; state++) + WARN_ON(drv_sta_state(local, sta->sdata, sta, + state, state + 1)); + } } mutex_unlock(&local->sta_mtx); @@ -1388,24 +1371,6 @@ int ieee80211_reconfig(struct ieee80211_local *local) } } - /* APs are now beaconing, add back stations */ - mutex_lock(&local->sta_mtx); - list_for_each_entry(sta, &local->sta_list, list) { - enum ieee80211_sta_state state; - - if (!sta->uploaded) - continue; - - if (sta->sdata->vif.type != NL80211_IFTYPE_AP) - continue; - - for (state = IEEE80211_STA_NOTEXIST; - state < sta->sta_state; state++) - WARN_ON(drv_sta_state(local, sta->sdata, sta, state, - state + 1)); - } - mutex_unlock(&local->sta_mtx); - /* add back keys */ list_for_each_entry(sdata, &local->interfaces, list) if (ieee80211_sdata_running(sdata)) diff --git a/trunk/net/mac80211/work.c b/trunk/net/mac80211/work.c new file mode 100644 index 000000000000..b2650a9d45ff --- /dev/null +++ b/trunk/net/mac80211/work.c @@ -0,0 +1,370 @@ +/* + * mac80211 work implementation + * + * Copyright 2003-2008, Jouni Malinen + * Copyright 2004, Instant802 Networks, Inc. + * Copyright 2005, Devicescape Software, Inc. + * Copyright 2006-2007 Jiri Benc + * Copyright 2007, Michael Wu + * Copyright 2009, Johannes Berg + * + * 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. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "ieee80211_i.h" +#include "rate.h" +#include "driver-ops.h" + +enum work_action { + WORK_ACT_NONE, + WORK_ACT_TIMEOUT, +}; + + +/* utils */ +static inline void ASSERT_WORK_MTX(struct ieee80211_local *local) +{ + lockdep_assert_held(&local->mtx); +} + +/* + * We can have multiple work items (and connection probing) + * scheduling this timer, but we need to take care to only + * reschedule it when it should fire _earlier_ than it was + * asked for before, or if it's not pending right now. This + * function ensures that. Note that it then is required to + * run this function for all timeouts after the first one + * has happened -- the work that runs from this timer will + * do that. + */ +static void run_again(struct ieee80211_local *local, + unsigned long timeout) +{ + ASSERT_WORK_MTX(local); + + if (!timer_pending(&local->work_timer) || + time_before(timeout, local->work_timer.expires)) + mod_timer(&local->work_timer, timeout); +} + +void free_work(struct ieee80211_work *wk) +{ + kfree_rcu(wk, rcu_head); +} + +static enum work_action __must_check +ieee80211_remain_on_channel_timeout(struct ieee80211_work *wk) +{ + /* + * First time we run, do nothing -- the generic code will + * have switched to the right channel etc. + */ + if (!wk->started) { + wk->timeout = jiffies + msecs_to_jiffies(wk->remain.duration); + + cfg80211_ready_on_channel(wk->sdata->dev, (unsigned long) wk, + wk->chan, wk->chan_type, + wk->remain.duration, GFP_KERNEL); + + return WORK_ACT_NONE; + } + + return WORK_ACT_TIMEOUT; +} + +static enum work_action __must_check +ieee80211_offchannel_tx(struct ieee80211_work *wk) +{ + if (!wk->started) { + wk->timeout = jiffies + msecs_to_jiffies(wk->offchan_tx.wait); + + /* + * After this, offchan_tx.frame remains but now is no + * longer a valid pointer -- we still need it as the + * cookie for canceling this work/status matching. + */ + ieee80211_tx_skb(wk->sdata, wk->offchan_tx.frame); + + return WORK_ACT_NONE; + } + + return WORK_ACT_TIMEOUT; +} + +static void ieee80211_work_timer(unsigned long data) +{ + struct ieee80211_local *local = (void *) data; + + if (local->quiescing) + return; + + ieee80211_queue_work(&local->hw, &local->work_work); +} + +static void ieee80211_work_work(struct work_struct *work) +{ + struct ieee80211_local *local = + container_of(work, struct ieee80211_local, work_work); + struct ieee80211_work *wk, *tmp; + LIST_HEAD(free_work); + enum work_action rma; + bool remain_off_channel = false; + + /* + * ieee80211_queue_work() should have picked up most cases, + * here we'll pick the rest. + */ + if (WARN(local->suspended, "work scheduled while going to suspend\n")) + return; + + mutex_lock(&local->mtx); + + if (local->scanning) { + mutex_unlock(&local->mtx); + return; + } + + ieee80211_recalc_idle(local); + + list_for_each_entry_safe(wk, tmp, &local->work_list, list) { + bool started = wk->started; + + /* mark work as started if it's on the current off-channel */ + if (!started && local->tmp_channel && + wk->chan == local->tmp_channel && + wk->chan_type == local->tmp_channel_type) { + started = true; + wk->timeout = jiffies; + } + + if (!started && !local->tmp_channel) { + ieee80211_offchannel_stop_vifs(local, true); + + local->tmp_channel = wk->chan; + local->tmp_channel_type = wk->chan_type; + + ieee80211_hw_config(local, 0); + + started = true; + wk->timeout = jiffies; + } + + /* don't try to work with items that aren't started */ + if (!started) + continue; + + if (time_is_after_jiffies(wk->timeout)) { + /* + * This work item isn't supposed to be worked on + * right now, but take care to adjust the timer + * properly. + */ + run_again(local, wk->timeout); + continue; + } + + switch (wk->type) { + default: + WARN_ON(1); + /* nothing */ + rma = WORK_ACT_NONE; + break; + case IEEE80211_WORK_ABORT: + rma = WORK_ACT_TIMEOUT; + break; + case IEEE80211_WORK_REMAIN_ON_CHANNEL: + rma = ieee80211_remain_on_channel_timeout(wk); + break; + case IEEE80211_WORK_OFFCHANNEL_TX: + rma = ieee80211_offchannel_tx(wk); + break; + } + + wk->started = started; + + switch (rma) { + case WORK_ACT_NONE: + /* might have changed the timeout */ + run_again(local, wk->timeout); + break; + case WORK_ACT_TIMEOUT: + list_del_rcu(&wk->list); + synchronize_rcu(); + list_add(&wk->list, &free_work); + break; + default: + WARN(1, "unexpected: %d", rma); + } + } + + list_for_each_entry(wk, &local->work_list, list) { + if (!wk->started) + continue; + if (wk->chan != local->tmp_channel || + wk->chan_type != local->tmp_channel_type) + continue; + remain_off_channel = true; + } + + if (!remain_off_channel && local->tmp_channel) { + local->tmp_channel = NULL; + ieee80211_hw_config(local, 0); + + ieee80211_offchannel_return(local, true); + + /* give connection some time to breathe */ + run_again(local, jiffies + HZ/2); + } + + ieee80211_recalc_idle(local); + ieee80211_run_deferred_scan(local); + + mutex_unlock(&local->mtx); + + list_for_each_entry_safe(wk, tmp, &free_work, list) { + wk->done(wk, NULL); + list_del(&wk->list); + kfree(wk); + } +} + +void ieee80211_add_work(struct ieee80211_work *wk) +{ + struct ieee80211_local *local; + + if (WARN_ON(!wk->chan)) + return; + + if (WARN_ON(!wk->sdata)) + return; + + if (WARN_ON(!wk->done)) + return; + + if (WARN_ON(!ieee80211_sdata_running(wk->sdata))) + return; + + wk->started = false; + + local = wk->sdata->local; + mutex_lock(&local->mtx); + list_add_tail(&wk->list, &local->work_list); + mutex_unlock(&local->mtx); + + ieee80211_queue_work(&local->hw, &local->work_work); +} + +void ieee80211_work_init(struct ieee80211_local *local) +{ + INIT_LIST_HEAD(&local->work_list); + setup_timer(&local->work_timer, ieee80211_work_timer, + (unsigned long)local); + INIT_WORK(&local->work_work, ieee80211_work_work); +} + +void ieee80211_work_purge(struct ieee80211_sub_if_data *sdata) +{ + struct ieee80211_local *local = sdata->local; + struct ieee80211_work *wk; + bool cleanup = false; + + mutex_lock(&local->mtx); + list_for_each_entry(wk, &local->work_list, list) { + if (wk->sdata != sdata) + continue; + cleanup = true; + wk->type = IEEE80211_WORK_ABORT; + wk->started = true; + wk->timeout = jiffies; + } + mutex_unlock(&local->mtx); + + /* run cleanups etc. */ + if (cleanup) + ieee80211_work_work(&local->work_work); + + mutex_lock(&local->mtx); + list_for_each_entry(wk, &local->work_list, list) { + if (wk->sdata != sdata) + continue; + WARN_ON(1); + break; + } + mutex_unlock(&local->mtx); +} + +static enum work_done_result ieee80211_remain_done(struct ieee80211_work *wk, + struct sk_buff *skb) +{ + /* + * We are done serving the remain-on-channel command. + */ + cfg80211_remain_on_channel_expired(wk->sdata->dev, (unsigned long) wk, + wk->chan, wk->chan_type, + GFP_KERNEL); + + return WORK_DONE_DESTROY; +} + +int ieee80211_wk_remain_on_channel(struct ieee80211_sub_if_data *sdata, + struct ieee80211_channel *chan, + enum nl80211_channel_type channel_type, + unsigned int duration, u64 *cookie) +{ + struct ieee80211_work *wk; + + wk = kzalloc(sizeof(*wk), GFP_KERNEL); + if (!wk) + return -ENOMEM; + + wk->type = IEEE80211_WORK_REMAIN_ON_CHANNEL; + wk->chan = chan; + wk->chan_type = channel_type; + wk->sdata = sdata; + wk->done = ieee80211_remain_done; + + wk->remain.duration = duration; + + *cookie = (unsigned long) wk; + + ieee80211_add_work(wk); + + return 0; +} + +int ieee80211_wk_cancel_remain_on_channel(struct ieee80211_sub_if_data *sdata, + u64 cookie) +{ + struct ieee80211_local *local = sdata->local; + struct ieee80211_work *wk, *tmp; + bool found = false; + + mutex_lock(&local->mtx); + list_for_each_entry_safe(wk, tmp, &local->work_list, list) { + if ((unsigned long) wk == cookie) { + wk->timeout = jiffies; + found = true; + break; + } + } + mutex_unlock(&local->mtx); + + if (!found) + return -ENOENT; + + ieee80211_queue_work(&local->hw, &local->work_work); + + return 0; +} diff --git a/trunk/net/nfc/core.c b/trunk/net/nfc/core.c index 4177bb5104b9..9f6ce011d35d 100644 --- a/trunk/net/nfc/core.c +++ b/trunk/net/nfc/core.c @@ -121,14 +121,14 @@ int nfc_dev_down(struct nfc_dev *dev) * The device remains polling for targets until a target is found or * the nfc_stop_poll function is called. */ -int nfc_start_poll(struct nfc_dev *dev, u32 im_protocols, u32 tm_protocols) +int nfc_start_poll(struct nfc_dev *dev, u32 protocols) { int rc; - pr_debug("dev_name %s initiator protocols 0x%x target protocols 0x%x\n", - dev_name(&dev->dev), im_protocols, tm_protocols); + pr_debug("dev_name=%s protocols=0x%x\n", + dev_name(&dev->dev), protocols); - if (!im_protocols && !tm_protocols) + if (!protocols) return -EINVAL; device_lock(&dev->dev); @@ -143,11 +143,9 @@ int nfc_start_poll(struct nfc_dev *dev, u32 im_protocols, u32 tm_protocols) goto error; } - rc = dev->ops->start_poll(dev, im_protocols, tm_protocols); - if (!rc) { + rc = dev->ops->start_poll(dev, protocols); + if (!rc) dev->polling = true; - dev->rf_mode = NFC_RF_NONE; - } error: device_unlock(&dev->dev); @@ -237,10 +235,8 @@ int nfc_dep_link_up(struct nfc_dev *dev, int target_index, u8 comm_mode) } rc = dev->ops->dep_link_up(dev, target, comm_mode, gb, gb_len); - if (!rc) { + if (!rc) dev->active_target = target; - dev->rf_mode = NFC_RF_INITIATOR; - } error: device_unlock(&dev->dev); @@ -268,6 +264,11 @@ int nfc_dep_link_down(struct nfc_dev *dev) goto error; } + if (dev->dep_rf_mode == NFC_RF_TARGET) { + rc = -EOPNOTSUPP; + goto error; + } + rc = dev->ops->dep_link_down(dev); if (!rc) { dev->dep_link_up = false; @@ -285,6 +286,7 @@ int nfc_dep_link_is_up(struct nfc_dev *dev, u32 target_idx, u8 comm_mode, u8 rf_mode) { dev->dep_link_up = true; + dev->dep_rf_mode = rf_mode; nfc_llcp_mac_is_up(dev, target_idx, comm_mode, rf_mode); @@ -328,7 +330,6 @@ int nfc_activate_target(struct nfc_dev *dev, u32 target_idx, u32 protocol) rc = dev->ops->activate_target(dev, target, protocol); if (!rc) { dev->active_target = target; - dev->rf_mode = NFC_RF_INITIATOR; if (dev->ops->check_presence) mod_timer(&dev->check_pres_timer, jiffies + @@ -408,30 +409,27 @@ int nfc_data_exchange(struct nfc_dev *dev, u32 target_idx, struct sk_buff *skb, goto error; } - if (dev->rf_mode == NFC_RF_INITIATOR && dev->active_target != NULL) { - if (dev->active_target->idx != target_idx) { - rc = -EADDRNOTAVAIL; - kfree_skb(skb); - goto error; - } - - if (dev->ops->check_presence) - del_timer_sync(&dev->check_pres_timer); - - rc = dev->ops->im_transceive(dev, dev->active_target, skb, cb, - cb_context); - - if (!rc && dev->ops->check_presence) - mod_timer(&dev->check_pres_timer, jiffies + - msecs_to_jiffies(NFC_CHECK_PRES_FREQ_MS)); - } else if (dev->rf_mode == NFC_RF_TARGET && dev->ops->tm_send != NULL) { - rc = dev->ops->tm_send(dev, skb); - } else { + if (dev->active_target == NULL) { rc = -ENOTCONN; kfree_skb(skb); goto error; } + if (dev->active_target->idx != target_idx) { + rc = -EADDRNOTAVAIL; + kfree_skb(skb); + goto error; + } + + if (dev->ops->check_presence) + del_timer_sync(&dev->check_pres_timer); + + rc = dev->ops->data_exchange(dev, dev->active_target, skb, cb, + cb_context); + + if (!rc && dev->ops->check_presence) + mod_timer(&dev->check_pres_timer, jiffies + + msecs_to_jiffies(NFC_CHECK_PRES_FREQ_MS)); error: device_unlock(&dev->dev); @@ -449,63 +447,6 @@ int nfc_set_remote_general_bytes(struct nfc_dev *dev, u8 *gb, u8 gb_len) } EXPORT_SYMBOL(nfc_set_remote_general_bytes); -u8 *nfc_get_local_general_bytes(struct nfc_dev *dev, size_t *gb_len) -{ - pr_debug("dev_name=%s\n", dev_name(&dev->dev)); - - return nfc_llcp_general_bytes(dev, gb_len); -} -EXPORT_SYMBOL(nfc_get_local_general_bytes); - -int nfc_tm_data_received(struct nfc_dev *dev, struct sk_buff *skb) -{ - /* Only LLCP target mode for now */ - if (dev->dep_link_up == false) { - kfree_skb(skb); - return -ENOLINK; - } - - return nfc_llcp_data_received(dev, skb); -} -EXPORT_SYMBOL(nfc_tm_data_received); - -int nfc_tm_activated(struct nfc_dev *dev, u32 protocol, u8 comm_mode, - u8 *gb, size_t gb_len) -{ - int rc; - - device_lock(&dev->dev); - - dev->polling = false; - - if (gb != NULL) { - rc = nfc_set_remote_general_bytes(dev, gb, gb_len); - if (rc < 0) - goto out; - } - - dev->rf_mode = NFC_RF_TARGET; - - if (protocol == NFC_PROTO_NFC_DEP_MASK) - nfc_dep_link_is_up(dev, 0, comm_mode, NFC_RF_TARGET); - - rc = nfc_genl_tm_activated(dev, protocol); - -out: - device_unlock(&dev->dev); - - return rc; -} -EXPORT_SYMBOL(nfc_tm_activated); - -int nfc_tm_deactivated(struct nfc_dev *dev) -{ - dev->dep_link_up = false; - - return nfc_genl_tm_deactivated(dev); -} -EXPORT_SYMBOL(nfc_tm_deactivated); - /** * nfc_alloc_send_skb - allocate a skb for data exchange responses * @@ -737,7 +678,7 @@ struct nfc_dev *nfc_allocate_device(struct nfc_ops *ops, struct nfc_dev *dev; if (!ops->start_poll || !ops->stop_poll || !ops->activate_target || - !ops->deactivate_target || !ops->im_transceive) + !ops->deactivate_target || !ops->data_exchange) return NULL; if (!supported_protocols) diff --git a/trunk/net/nfc/hci/core.c b/trunk/net/nfc/hci/core.c index a8b0b71e8f86..e1a640d2b588 100644 --- a/trunk/net/nfc/hci/core.c +++ b/trunk/net/nfc/hci/core.c @@ -481,13 +481,12 @@ static int hci_dev_down(struct nfc_dev *nfc_dev) return 0; } -static int hci_start_poll(struct nfc_dev *nfc_dev, - u32 im_protocols, u32 tm_protocols) +static int hci_start_poll(struct nfc_dev *nfc_dev, u32 protocols) { struct nfc_hci_dev *hdev = nfc_get_drvdata(nfc_dev); if (hdev->ops->start_poll) - return hdev->ops->start_poll(hdev, im_protocols, tm_protocols); + return hdev->ops->start_poll(hdev, protocols); else return nfc_hci_send_event(hdev, NFC_HCI_RF_READER_A_GATE, NFC_HCI_EVT_READER_REQUESTED, NULL, 0); @@ -512,9 +511,9 @@ static void hci_deactivate_target(struct nfc_dev *nfc_dev, { } -static int hci_transceive(struct nfc_dev *nfc_dev, struct nfc_target *target, - struct sk_buff *skb, data_exchange_cb_t cb, - void *cb_context) +static int hci_data_exchange(struct nfc_dev *nfc_dev, struct nfc_target *target, + struct sk_buff *skb, data_exchange_cb_t cb, + void *cb_context) { struct nfc_hci_dev *hdev = nfc_get_drvdata(nfc_dev); int r; @@ -580,7 +579,7 @@ static struct nfc_ops hci_nfc_ops = { .stop_poll = hci_stop_poll, .activate_target = hci_activate_target, .deactivate_target = hci_deactivate_target, - .im_transceive = hci_transceive, + .data_exchange = hci_data_exchange, .check_presence = hci_check_presence, }; diff --git a/trunk/net/nfc/hci/shdlc.c b/trunk/net/nfc/hci/shdlc.c index 6b836e6242b7..5665dc6d893a 100644 --- a/trunk/net/nfc/hci/shdlc.c +++ b/trunk/net/nfc/hci/shdlc.c @@ -765,16 +765,14 @@ static int nfc_shdlc_xmit(struct nfc_hci_dev *hdev, struct sk_buff *skb) return 0; } -static int nfc_shdlc_start_poll(struct nfc_hci_dev *hdev, - u32 im_protocols, u32 tm_protocols) +static int nfc_shdlc_start_poll(struct nfc_hci_dev *hdev, u32 protocols) { struct nfc_shdlc *shdlc = nfc_hci_get_clientdata(hdev); pr_debug("\n"); if (shdlc->ops->start_poll) - return shdlc->ops->start_poll(shdlc, - im_protocols, tm_protocols); + return shdlc->ops->start_poll(shdlc, protocols); return 0; } diff --git a/trunk/net/nfc/llcp/commands.c b/trunk/net/nfc/llcp/commands.c index b982b5b890d7..bf8ae4f0b90c 100644 --- a/trunk/net/nfc/llcp/commands.c +++ b/trunk/net/nfc/llcp/commands.c @@ -51,7 +51,7 @@ static u8 llcp_tlv8(u8 *tlv, u8 type) return tlv[2]; } -static u16 llcp_tlv16(u8 *tlv, u8 type) +static u8 llcp_tlv16(u8 *tlv, u8 type) { if (tlv[0] != type || tlv[1] != llcp_tlv_length[tlv[0]]) return 0; @@ -67,7 +67,7 @@ static u8 llcp_tlv_version(u8 *tlv) static u16 llcp_tlv_miux(u8 *tlv) { - return llcp_tlv16(tlv, LLCP_TLV_MIUX) & 0x7ff; + return llcp_tlv16(tlv, LLCP_TLV_MIUX) & 0x7f; } static u16 llcp_tlv_wks(u8 *tlv) @@ -117,8 +117,8 @@ u8 *nfc_llcp_build_tlv(u8 type, u8 *value, u8 value_length, u8 *tlv_length) return tlv; } -int nfc_llcp_parse_gb_tlv(struct nfc_llcp_local *local, - u8 *tlv_array, u16 tlv_array_len) +int nfc_llcp_parse_tlv(struct nfc_llcp_local *local, + u8 *tlv_array, u16 tlv_array_len) { u8 *tlv = tlv_array, type, length, offset = 0; @@ -149,45 +149,8 @@ int nfc_llcp_parse_gb_tlv(struct nfc_llcp_local *local, case LLCP_TLV_OPT: local->remote_opt = llcp_tlv_opt(tlv); break; - default: - pr_err("Invalid gt tlv value 0x%x\n", type); - break; - } - - offset += length + 2; - tlv += length + 2; - } - - pr_debug("version 0x%x miu %d lto %d opt 0x%x wks 0x%x\n", - local->remote_version, local->remote_miu, - local->remote_lto, local->remote_opt, - local->remote_wks); - - return 0; -} - -int nfc_llcp_parse_connection_tlv(struct nfc_llcp_sock *sock, - u8 *tlv_array, u16 tlv_array_len) -{ - u8 *tlv = tlv_array, type, length, offset = 0; - - pr_debug("TLV array length %d\n", tlv_array_len); - - if (sock == NULL) - return -ENOTCONN; - - while (offset < tlv_array_len) { - type = tlv[0]; - length = tlv[1]; - - pr_debug("type 0x%x length %d\n", type, length); - - switch (type) { - case LLCP_TLV_MIUX: - sock->miu = llcp_tlv_miux(tlv) + 128; - break; case LLCP_TLV_RW: - sock->rw = llcp_tlv_rw(tlv); + local->remote_rw = llcp_tlv_rw(tlv); break; case LLCP_TLV_SN: break; @@ -200,7 +163,10 @@ int nfc_llcp_parse_connection_tlv(struct nfc_llcp_sock *sock, tlv += length + 2; } - pr_debug("sock %p rw %d miu %d\n", sock, sock->rw, sock->miu); + pr_debug("version 0x%x miu %d lto %d opt 0x%x wks 0x%x rw %d\n", + local->remote_version, local->remote_miu, + local->remote_lto, local->remote_opt, + local->remote_wks, local->remote_rw); return 0; } @@ -508,7 +474,7 @@ int nfc_llcp_send_i_frame(struct nfc_llcp_sock *sock, while (remaining_len > 0) { - frag_len = min_t(size_t, sock->miu, remaining_len); + frag_len = min_t(size_t, local->remote_miu, remaining_len); pr_debug("Fragment %zd bytes remaining %zd", frag_len, remaining_len); diff --git a/trunk/net/nfc/llcp/llcp.c b/trunk/net/nfc/llcp/llcp.c index 5d503eeb15a1..42994fac26d6 100644 --- a/trunk/net/nfc/llcp/llcp.c +++ b/trunk/net/nfc/llcp/llcp.c @@ -31,41 +31,47 @@ static u8 llcp_magic[3] = {0x46, 0x66, 0x6d}; static struct list_head llcp_devices; -void nfc_llcp_sock_link(struct llcp_sock_list *l, struct sock *sk) +static void nfc_llcp_socket_release(struct nfc_llcp_local *local) { - write_lock(&l->lock); - sk_add_node(sk, &l->head); - write_unlock(&l->lock); -} + struct nfc_llcp_sock *parent, *s, *n; + struct sock *sk, *parent_sk; + int i; -void nfc_llcp_sock_unlink(struct llcp_sock_list *l, struct sock *sk) -{ - write_lock(&l->lock); - sk_del_node_init(sk); - write_unlock(&l->lock); -} + mutex_lock(&local->socket_lock); -static void nfc_llcp_socket_release(struct nfc_llcp_local *local) -{ - struct sock *sk; - struct hlist_node *node, *tmp; - struct nfc_llcp_sock *llcp_sock; + for (i = 0; i < LLCP_MAX_SAP; i++) { + parent = local->sockets[i]; + if (parent == NULL) + continue; - write_lock(&local->sockets.lock); + /* Release all child sockets */ + list_for_each_entry_safe(s, n, &parent->list, list) { + list_del_init(&s->list); + sk = &s->sk; - sk_for_each_safe(sk, node, tmp, &local->sockets.head) { - llcp_sock = nfc_llcp_sock(sk); + lock_sock(sk); - lock_sock(sk); + if (sk->sk_state == LLCP_CONNECTED) + nfc_put_device(s->dev); - if (sk->sk_state == LLCP_CONNECTED) - nfc_put_device(llcp_sock->dev); + sk->sk_state = LLCP_CLOSED; - if (sk->sk_state == LLCP_LISTEN) { + release_sock(sk); + + sock_orphan(sk); + + s->local = NULL; + } + + parent_sk = &parent->sk; + + lock_sock(parent_sk); + + if (parent_sk->sk_state == LLCP_LISTEN) { struct nfc_llcp_sock *lsk, *n; struct sock *accept_sk; - list_for_each_entry_safe(lsk, n, &llcp_sock->accept_queue, + list_for_each_entry_safe(lsk, n, &parent->accept_queue, accept_queue) { accept_sk = &lsk->sk; lock_sock(accept_sk); @@ -77,53 +83,24 @@ static void nfc_llcp_socket_release(struct nfc_llcp_local *local) release_sock(accept_sk); sock_orphan(accept_sk); + + lsk->local = NULL; } } - sk->sk_state = LLCP_CLOSED; - - release_sock(sk); - - sock_orphan(sk); - - sk_del_node_init(sk); - } - - write_unlock(&local->sockets.lock); -} - -struct nfc_llcp_local *nfc_llcp_local_get(struct nfc_llcp_local *local) -{ - kref_get(&local->ref); + if (parent_sk->sk_state == LLCP_CONNECTED) + nfc_put_device(parent->dev); - return local; -} + parent_sk->sk_state = LLCP_CLOSED; -static void local_release(struct kref *ref) -{ - struct nfc_llcp_local *local; + release_sock(parent_sk); - local = container_of(ref, struct nfc_llcp_local, ref); + sock_orphan(parent_sk); - list_del(&local->list); - nfc_llcp_socket_release(local); - del_timer_sync(&local->link_timer); - skb_queue_purge(&local->tx_queue); - destroy_workqueue(local->tx_wq); - destroy_workqueue(local->rx_wq); - destroy_workqueue(local->timeout_wq); - kfree_skb(local->rx_pending); - kfree(local); -} - -int nfc_llcp_local_put(struct nfc_llcp_local *local) -{ - WARN_ON(local == NULL); - - if (local == NULL) - return 0; + parent->local = NULL; + } - return kref_put(&local->ref, local_release); + mutex_unlock(&local->socket_lock); } static void nfc_llcp_clear_sdp(struct nfc_llcp_local *local) @@ -407,9 +384,31 @@ int nfc_llcp_set_remote_gb(struct nfc_dev *dev, u8 *gb, u8 gb_len) return -EINVAL; } - return nfc_llcp_parse_gb_tlv(local, - &local->remote_gb[3], - local->remote_gb_len - 3); + return nfc_llcp_parse_tlv(local, + &local->remote_gb[3], + local->remote_gb_len - 3); +} + +static void nfc_llcp_tx_work(struct work_struct *work) +{ + struct nfc_llcp_local *local = container_of(work, struct nfc_llcp_local, + tx_work); + struct sk_buff *skb; + + skb = skb_dequeue(&local->tx_queue); + if (skb != NULL) { + pr_debug("Sending pending skb\n"); + print_hex_dump(KERN_DEBUG, "LLCP Tx: ", DUMP_PREFIX_OFFSET, + 16, 1, skb->data, skb->len, true); + + nfc_data_exchange(local->dev, local->target_idx, + skb, nfc_llcp_recv, local); + } else { + nfc_llcp_send_symm(local->dev); + } + + mod_timer(&local->link_timer, + jiffies + msecs_to_jiffies(local->remote_lto)); } static u8 nfc_llcp_dsap(struct sk_buff *pdu) @@ -444,146 +443,46 @@ static void nfc_llcp_set_nrns(struct nfc_llcp_sock *sock, struct sk_buff *pdu) sock->recv_ack_n = (sock->recv_n - 1) % 16; } -static void nfc_llcp_tx_work(struct work_struct *work) -{ - struct nfc_llcp_local *local = container_of(work, struct nfc_llcp_local, - tx_work); - struct sk_buff *skb; - struct sock *sk; - struct nfc_llcp_sock *llcp_sock; - - skb = skb_dequeue(&local->tx_queue); - if (skb != NULL) { - sk = skb->sk; - llcp_sock = nfc_llcp_sock(sk); - if (llcp_sock != NULL) { - int ret; - - pr_debug("Sending pending skb\n"); - print_hex_dump(KERN_DEBUG, "LLCP Tx: ", - DUMP_PREFIX_OFFSET, 16, 1, - skb->data, skb->len, true); - - ret = nfc_data_exchange(local->dev, local->target_idx, - skb, nfc_llcp_recv, local); - - if (!ret && nfc_llcp_ptype(skb) == LLCP_PDU_I) { - skb = skb_get(skb); - skb_queue_tail(&llcp_sock->tx_pending_queue, - skb); - } - } else { - nfc_llcp_send_symm(local->dev); - } - } else { - nfc_llcp_send_symm(local->dev); - } - - mod_timer(&local->link_timer, - jiffies + msecs_to_jiffies(2 * local->remote_lto)); -} - -static struct nfc_llcp_sock *nfc_llcp_connecting_sock_get(struct nfc_llcp_local *local, - u8 ssap) -{ - struct sock *sk; - struct nfc_llcp_sock *llcp_sock; - struct hlist_node *node; - - read_lock(&local->connecting_sockets.lock); - - sk_for_each(sk, node, &local->connecting_sockets.head) { - llcp_sock = nfc_llcp_sock(sk); - - if (llcp_sock->ssap == ssap) { - sock_hold(&llcp_sock->sk); - goto out; - } - } - - llcp_sock = NULL; - -out: - read_unlock(&local->connecting_sockets.lock); - - return llcp_sock; -} - static struct nfc_llcp_sock *nfc_llcp_sock_get(struct nfc_llcp_local *local, u8 ssap, u8 dsap) { - struct sock *sk; - struct hlist_node *node; - struct nfc_llcp_sock *llcp_sock; + struct nfc_llcp_sock *sock, *llcp_sock, *n; pr_debug("ssap dsap %d %d\n", ssap, dsap); if (ssap == 0 && dsap == 0) return NULL; - read_lock(&local->sockets.lock); - - llcp_sock = NULL; - - sk_for_each(sk, node, &local->sockets.head) { - llcp_sock = nfc_llcp_sock(sk); - - if (llcp_sock->ssap == ssap && - llcp_sock->dsap == dsap) - break; - } - - read_unlock(&local->sockets.lock); - - if (llcp_sock == NULL) + mutex_lock(&local->socket_lock); + sock = local->sockets[ssap]; + if (sock == NULL) { + mutex_unlock(&local->socket_lock); return NULL; + } - sock_hold(&llcp_sock->sk); - - return llcp_sock; -} - -static struct nfc_llcp_sock *nfc_llcp_sock_get_sn(struct nfc_llcp_local *local, - u8 *sn, size_t sn_len) -{ - struct sock *sk; - struct hlist_node *node; - struct nfc_llcp_sock *llcp_sock; - - pr_debug("sn %zd\n", sn_len); - - if (sn == NULL || sn_len == 0) - return NULL; - - read_lock(&local->sockets.lock); - - llcp_sock = NULL; - - sk_for_each(sk, node, &local->sockets.head) { - llcp_sock = nfc_llcp_sock(sk); - - if (llcp_sock->sk.sk_state != LLCP_LISTEN) - continue; - - if (llcp_sock->service_name == NULL || - llcp_sock->service_name_len == 0) - continue; - - if (llcp_sock->service_name_len != sn_len) - continue; + pr_debug("root dsap %d (%d)\n", sock->dsap, dsap); - if (memcmp(sn, llcp_sock->service_name, sn_len) == 0) - break; + if (sock->dsap == dsap) { + sock_hold(&sock->sk); + mutex_unlock(&local->socket_lock); + return sock; } - read_unlock(&local->sockets.lock); + list_for_each_entry_safe(llcp_sock, n, &sock->list, list) { + pr_debug("llcp_sock %p sk %p dsap %d\n", llcp_sock, + &llcp_sock->sk, llcp_sock->dsap); + if (llcp_sock->dsap == dsap) { + sock_hold(&llcp_sock->sk); + mutex_unlock(&local->socket_lock); + return llcp_sock; + } + } - if (llcp_sock == NULL) - return NULL; + pr_err("Could not find socket for %d %d\n", ssap, dsap); - sock_hold(&llcp_sock->sk); + mutex_unlock(&local->socket_lock); - return llcp_sock; + return NULL; } static void nfc_llcp_sock_put(struct nfc_llcp_sock *sock) @@ -619,19 +518,35 @@ static void nfc_llcp_recv_connect(struct nfc_llcp_local *local, { struct sock *new_sk, *parent; struct nfc_llcp_sock *sock, *new_sock; - u8 dsap, ssap, reason; + u8 dsap, ssap, bound_sap, reason; dsap = nfc_llcp_dsap(skb); ssap = nfc_llcp_ssap(skb); pr_debug("%d %d\n", dsap, ssap); + nfc_llcp_parse_tlv(local, &skb->data[LLCP_HEADER_SIZE], + skb->len - LLCP_HEADER_SIZE); + if (dsap != LLCP_SAP_SDP) { - sock = nfc_llcp_sock_get(local, dsap, LLCP_SAP_SDP); - if (sock == NULL || sock->sk.sk_state != LLCP_LISTEN) { + bound_sap = dsap; + + mutex_lock(&local->socket_lock); + sock = local->sockets[dsap]; + if (sock == NULL) { + mutex_unlock(&local->socket_lock); reason = LLCP_DM_NOBOUND; goto fail; } + + sock_hold(&sock->sk); + mutex_unlock(&local->socket_lock); + + lock_sock(&sock->sk); + + if (sock->dsap == LLCP_SAP_SDP && + sock->sk.sk_state == LLCP_LISTEN) + goto enqueue; } else { u8 *sn; size_t sn_len; @@ -644,15 +559,40 @@ static void nfc_llcp_recv_connect(struct nfc_llcp_local *local, pr_debug("Service name length %zu\n", sn_len); - sock = nfc_llcp_sock_get_sn(local, sn, sn_len); - if (sock == NULL) { - reason = LLCP_DM_NOBOUND; - goto fail; + mutex_lock(&local->socket_lock); + for (bound_sap = 0; bound_sap < LLCP_LOCAL_SAP_OFFSET; + bound_sap++) { + sock = local->sockets[bound_sap]; + if (sock == NULL) + continue; + + if (sock->service_name == NULL || + sock->service_name_len == 0) + continue; + + if (sock->service_name_len != sn_len) + continue; + + if (sock->dsap == LLCP_SAP_SDP && + sock->sk.sk_state == LLCP_LISTEN && + !memcmp(sn, sock->service_name, sn_len)) { + pr_debug("Found service name at SAP %d\n", + bound_sap); + sock_hold(&sock->sk); + mutex_unlock(&local->socket_lock); + + lock_sock(&sock->sk); + + goto enqueue; + } } + mutex_unlock(&local->socket_lock); } - lock_sock(&sock->sk); + reason = LLCP_DM_NOBOUND; + goto fail; +enqueue: parent = &sock->sk; if (sk_acceptq_is_full(parent)) { @@ -672,19 +612,15 @@ static void nfc_llcp_recv_connect(struct nfc_llcp_local *local, new_sock = nfc_llcp_sock(new_sk); new_sock->dev = local->dev; - new_sock->local = nfc_llcp_local_get(local); - new_sock->miu = local->remote_miu; + new_sock->local = local; new_sock->nfc_protocol = sock->nfc_protocol; - new_sock->ssap = sock->ssap; + new_sock->ssap = bound_sap; new_sock->dsap = ssap; new_sock->parent = parent; - nfc_llcp_parse_connection_tlv(new_sock, &skb->data[LLCP_HEADER_SIZE], - skb->len - LLCP_HEADER_SIZE); - pr_debug("new sock %p sk %p\n", new_sock, &new_sock->sk); - nfc_llcp_sock_link(&local->sockets, new_sk); + list_add_tail(&new_sock->list, &sock->list); nfc_llcp_accept_enqueue(&sock->sk, new_sk); @@ -718,12 +654,12 @@ int nfc_llcp_queue_i_frames(struct nfc_llcp_sock *sock) pr_debug("Remote ready %d tx queue len %d remote rw %d", sock->remote_ready, skb_queue_len(&sock->tx_pending_queue), - sock->rw); + local->remote_rw); /* Try to queue some I frames for transmission */ while (sock->remote_ready && - skb_queue_len(&sock->tx_pending_queue) < sock->rw) { - struct sk_buff *pdu; + skb_queue_len(&sock->tx_pending_queue) < local->remote_rw) { + struct sk_buff *pdu, *pending_pdu; pdu = skb_dequeue(&sock->tx_queue); if (pdu == NULL) @@ -732,7 +668,10 @@ int nfc_llcp_queue_i_frames(struct nfc_llcp_sock *sock) /* Update N(S)/N(R) */ nfc_llcp_set_nrns(sock, pdu); + pending_pdu = skb_clone(pdu, GFP_KERNEL); + skb_queue_tail(&local->tx_queue, pdu); + skb_queue_tail(&sock->tx_pending_queue, pending_pdu); nr_frames++; } @@ -789,21 +728,11 @@ static void nfc_llcp_recv_hdlc(struct nfc_llcp_local *local, llcp_sock->send_ack_n = nr; - /* Remove and free all skbs until ns == nr */ - skb_queue_walk_safe(&llcp_sock->tx_pending_queue, s, tmp) { - skb_unlink(s, &llcp_sock->tx_pending_queue); - kfree_skb(s); - - if (nfc_llcp_ns(s) == nr) - break; - } - - /* Re-queue the remaining skbs for transmission */ - skb_queue_reverse_walk_safe(&llcp_sock->tx_pending_queue, - s, tmp) { - skb_unlink(s, &llcp_sock->tx_pending_queue); - skb_queue_head(&local->tx_queue, s); - } + skb_queue_walk_safe(&llcp_sock->tx_pending_queue, s, tmp) + if (nfc_llcp_ns(s) <= nr) { + skb_unlink(s, &llcp_sock->tx_pending_queue); + kfree_skb(s); + } } if (ptype == LLCP_PDU_RR) @@ -811,7 +740,7 @@ static void nfc_llcp_recv_hdlc(struct nfc_llcp_local *local, else if (ptype == LLCP_PDU_RNR) llcp_sock->remote_ready = false; - if (nfc_llcp_queue_i_frames(llcp_sock) == 0 && ptype == LLCP_PDU_I) + if (nfc_llcp_queue_i_frames(llcp_sock) == 0) nfc_llcp_send_rr(llcp_sock); release_sock(sk); @@ -862,7 +791,11 @@ static void nfc_llcp_recv_cc(struct nfc_llcp_local *local, struct sk_buff *skb) dsap = nfc_llcp_dsap(skb); ssap = nfc_llcp_ssap(skb); - llcp_sock = nfc_llcp_connecting_sock_get(local, dsap); + llcp_sock = nfc_llcp_sock_get(local, dsap, ssap); + + if (llcp_sock == NULL) + llcp_sock = nfc_llcp_sock_get(local, dsap, LLCP_SAP_SDP); + if (llcp_sock == NULL) { pr_err("Invalid CC\n"); nfc_llcp_send_dm(local, dsap, ssap, LLCP_DM_NOCONN); @@ -870,15 +803,11 @@ static void nfc_llcp_recv_cc(struct nfc_llcp_local *local, struct sk_buff *skb) return; } - sk = &llcp_sock->sk; - - /* Unlink from connecting and link to the client array */ - nfc_llcp_sock_unlink(&local->connecting_sockets, sk); - nfc_llcp_sock_link(&local->sockets, sk); llcp_sock->dsap = ssap; + sk = &llcp_sock->sk; - nfc_llcp_parse_connection_tlv(llcp_sock, &skb->data[LLCP_HEADER_SIZE], - skb->len - LLCP_HEADER_SIZE); + nfc_llcp_parse_tlv(local, &skb->data[LLCP_HEADER_SIZE], + skb->len - LLCP_HEADER_SIZE); sk->sk_state = LLCP_CONNECTED; sk->sk_state_change(sk); @@ -962,21 +891,6 @@ void nfc_llcp_recv(void *data, struct sk_buff *skb, int err) return; } -int nfc_llcp_data_received(struct nfc_dev *dev, struct sk_buff *skb) -{ - struct nfc_llcp_local *local; - - local = nfc_llcp_find_local(dev); - if (local == NULL) - return -ENODEV; - - local->rx_pending = skb_get(skb); - del_timer(&local->link_timer); - queue_work(local->rx_wq, &local->rx_work); - - return 0; -} - void nfc_llcp_mac_is_down(struct nfc_dev *dev) { struct nfc_llcp_local *local; @@ -1029,8 +943,8 @@ int nfc_llcp_register_device(struct nfc_dev *ndev) local->dev = ndev; INIT_LIST_HEAD(&local->list); - kref_init(&local->ref); mutex_init(&local->sdp_lock); + mutex_init(&local->socket_lock); init_timer(&local->link_timer); local->link_timer.data = (unsigned long) local; local->link_timer.function = nfc_llcp_symm_timer; @@ -1070,13 +984,11 @@ int nfc_llcp_register_device(struct nfc_dev *ndev) goto err_rx_wq; } - local->sockets.lock = __RW_LOCK_UNLOCKED(local->sockets.lock); - local->connecting_sockets.lock = __RW_LOCK_UNLOCKED(local->connecting_sockets.lock); - nfc_llcp_build_gb(local); local->remote_miu = LLCP_DEFAULT_MIU; local->remote_lto = LLCP_DEFAULT_LTO; + local->remote_rw = LLCP_DEFAULT_RW; list_add(&llcp_devices, &local->list); @@ -1103,7 +1015,14 @@ void nfc_llcp_unregister_device(struct nfc_dev *dev) return; } - nfc_llcp_local_put(local); + list_del(&local->list); + nfc_llcp_socket_release(local); + del_timer_sync(&local->link_timer); + skb_queue_purge(&local->tx_queue); + destroy_workqueue(local->tx_wq); + destroy_workqueue(local->rx_wq); + kfree_skb(local->rx_pending); + kfree(local); } int __init nfc_llcp_init(void) diff --git a/trunk/net/nfc/llcp/llcp.h b/trunk/net/nfc/llcp/llcp.h index 7286c86982ff..50680ce5ae43 100644 --- a/trunk/net/nfc/llcp/llcp.h +++ b/trunk/net/nfc/llcp/llcp.h @@ -40,18 +40,12 @@ enum llcp_state { struct nfc_llcp_sock; -struct llcp_sock_list { - struct hlist_head head; - rwlock_t lock; -}; - struct nfc_llcp_local { struct list_head list; struct nfc_dev *dev; - struct kref ref; - struct mutex sdp_lock; + struct mutex socket_lock; struct timer_list link_timer; struct sk_buff_head tx_queue; @@ -83,26 +77,24 @@ struct nfc_llcp_local { u16 remote_lto; u8 remote_opt; u16 remote_wks; + u8 remote_rw; /* sockets array */ - struct llcp_sock_list sockets; - struct llcp_sock_list connecting_sockets; + struct nfc_llcp_sock *sockets[LLCP_MAX_SAP]; }; struct nfc_llcp_sock { struct sock sk; + struct list_head list; struct nfc_dev *dev; struct nfc_llcp_local *local; u32 target_idx; u32 nfc_protocol; - /* Link parameters */ u8 ssap; u8 dsap; char *service_name; size_t service_name_len; - u8 rw; - u16 miu; /* Link variables */ u8 send_n; @@ -172,11 +164,7 @@ struct nfc_llcp_sock { #define LLCP_DM_REJ 0x03 -void nfc_llcp_sock_link(struct llcp_sock_list *l, struct sock *s); -void nfc_llcp_sock_unlink(struct llcp_sock_list *l, struct sock *s); struct nfc_llcp_local *nfc_llcp_find_local(struct nfc_dev *dev); -struct nfc_llcp_local *nfc_llcp_local_get(struct nfc_llcp_local *local); -int nfc_llcp_local_put(struct nfc_llcp_local *local); u8 nfc_llcp_get_sdp_ssap(struct nfc_llcp_local *local, struct nfc_llcp_sock *sock); u8 nfc_llcp_get_local_ssap(struct nfc_llcp_local *local); @@ -191,10 +179,8 @@ void nfc_llcp_accept_enqueue(struct sock *parent, struct sock *sk); struct sock *nfc_llcp_accept_dequeue(struct sock *sk, struct socket *newsock); /* TLV API */ -int nfc_llcp_parse_gb_tlv(struct nfc_llcp_local *local, - u8 *tlv_array, u16 tlv_array_len); -int nfc_llcp_parse_connection_tlv(struct nfc_llcp_sock *sock, - u8 *tlv_array, u16 tlv_array_len); +int nfc_llcp_parse_tlv(struct nfc_llcp_local *local, + u8 *tlv_array, u16 tlv_array_len); /* Commands API */ void nfc_llcp_recv(void *data, struct sk_buff *skb, int err); diff --git a/trunk/net/nfc/llcp/sock.c b/trunk/net/nfc/llcp/sock.c index 30e3cc71be7a..3f339b19d140 100644 --- a/trunk/net/nfc/llcp/sock.c +++ b/trunk/net/nfc/llcp/sock.c @@ -111,7 +111,7 @@ static int llcp_sock_bind(struct socket *sock, struct sockaddr *addr, int alen) } llcp_sock->dev = dev; - llcp_sock->local = nfc_llcp_local_get(local); + llcp_sock->local = local; llcp_sock->nfc_protocol = llcp_addr.nfc_protocol; llcp_sock->service_name_len = min_t(unsigned int, llcp_addr.service_name_len, @@ -124,7 +124,7 @@ static int llcp_sock_bind(struct socket *sock, struct sockaddr *addr, int alen) if (llcp_sock->ssap == LLCP_MAX_SAP) goto put_dev; - nfc_llcp_sock_link(&local->sockets, sk); + local->sockets[llcp_sock->ssap] = llcp_sock; pr_debug("Socket bound to SAP %d\n", llcp_sock->ssap); @@ -379,6 +379,15 @@ static int llcp_sock_release(struct socket *sock) goto out; } + mutex_lock(&local->socket_lock); + + if (llcp_sock == local->sockets[llcp_sock->ssap]) + local->sockets[llcp_sock->ssap] = NULL; + else + list_del_init(&llcp_sock->list); + + mutex_unlock(&local->socket_lock); + lock_sock(sk); /* Send a DISC */ @@ -403,12 +412,14 @@ static int llcp_sock_release(struct socket *sock) } } - nfc_llcp_put_ssap(llcp_sock->local, llcp_sock->ssap); + /* Freeing the SAP */ + if ((sk->sk_state == LLCP_CONNECTED + && llcp_sock->ssap > LLCP_LOCAL_SAP_OFFSET) || + sk->sk_state == LLCP_BOUND || sk->sk_state == LLCP_LISTEN) + nfc_llcp_put_ssap(llcp_sock->local, llcp_sock->ssap); release_sock(sk); - nfc_llcp_sock_unlink(&local->sockets, sk); - out: sock_orphan(sk); sock_put(sk); @@ -476,8 +487,7 @@ static int llcp_sock_connect(struct socket *sock, struct sockaddr *_addr, } llcp_sock->dev = dev; - llcp_sock->local = nfc_llcp_local_get(local); - llcp_sock->miu = llcp_sock->local->remote_miu; + llcp_sock->local = local; llcp_sock->ssap = nfc_llcp_get_local_ssap(local); if (llcp_sock->ssap == LLCP_SAP_MAX) { ret = -ENOMEM; @@ -495,26 +505,21 @@ static int llcp_sock_connect(struct socket *sock, struct sockaddr *_addr, llcp_sock->service_name_len, GFP_KERNEL); - nfc_llcp_sock_link(&local->connecting_sockets, sk); + local->sockets[llcp_sock->ssap] = llcp_sock; ret = nfc_llcp_send_connect(llcp_sock); if (ret) - goto sock_unlink; + goto put_dev; ret = sock_wait_state(sk, LLCP_CONNECTED, sock_sndtimeo(sk, flags & O_NONBLOCK)); if (ret) - goto sock_unlink; + goto put_dev; release_sock(sk); return 0; -sock_unlink: - nfc_llcp_put_ssap(local, llcp_sock->ssap); - - nfc_llcp_sock_unlink(&local->connecting_sockets, sk); - put_dev: nfc_put_device(dev); @@ -679,14 +684,13 @@ struct sock *nfc_llcp_sock_alloc(struct socket *sock, int type, gfp_t gfp) llcp_sock->ssap = 0; llcp_sock->dsap = LLCP_SAP_SDP; - llcp_sock->rw = LLCP_DEFAULT_RW; - llcp_sock->miu = LLCP_DEFAULT_MIU; llcp_sock->send_n = llcp_sock->send_ack_n = 0; llcp_sock->recv_n = llcp_sock->recv_ack_n = 0; llcp_sock->remote_ready = 1; skb_queue_head_init(&llcp_sock->tx_queue); skb_queue_head_init(&llcp_sock->tx_pending_queue); skb_queue_head_init(&llcp_sock->tx_backlog_queue); + INIT_LIST_HEAD(&llcp_sock->list); INIT_LIST_HEAD(&llcp_sock->accept_queue); if (sock != NULL) @@ -697,6 +701,8 @@ struct sock *nfc_llcp_sock_alloc(struct socket *sock, int type, gfp_t gfp) void nfc_llcp_sock_free(struct nfc_llcp_sock *sock) { + struct nfc_llcp_local *local = sock->local; + kfree(sock->service_name); skb_queue_purge(&sock->tx_queue); @@ -705,9 +711,12 @@ void nfc_llcp_sock_free(struct nfc_llcp_sock *sock) list_del_init(&sock->accept_queue); - sock->parent = NULL; + if (local != NULL && sock == local->sockets[sock->ssap]) + local->sockets[sock->ssap] = NULL; + else + list_del_init(&sock->list); - nfc_llcp_local_put(sock->local); + sock->parent = NULL; } static int llcp_sock_create(struct net *net, struct socket *sock, diff --git a/trunk/net/nfc/nci/core.c b/trunk/net/nfc/nci/core.c index 766a02b1dfa1..d560e6f13072 100644 --- a/trunk/net/nfc/nci/core.c +++ b/trunk/net/nfc/nci/core.c @@ -387,8 +387,7 @@ static int nci_dev_down(struct nfc_dev *nfc_dev) return nci_close_device(ndev); } -static int nci_start_poll(struct nfc_dev *nfc_dev, - __u32 im_protocols, __u32 tm_protocols) +static int nci_start_poll(struct nfc_dev *nfc_dev, __u32 protocols) { struct nci_dev *ndev = nfc_get_drvdata(nfc_dev); int rc; @@ -414,11 +413,11 @@ static int nci_start_poll(struct nfc_dev *nfc_dev, return -EBUSY; } - rc = nci_request(ndev, nci_rf_discover_req, im_protocols, + rc = nci_request(ndev, nci_rf_discover_req, protocols, msecs_to_jiffies(NCI_RF_DISC_TIMEOUT)); if (!rc) - ndev->poll_prots = im_protocols; + ndev->poll_prots = protocols; return rc; } @@ -522,9 +521,9 @@ static void nci_deactivate_target(struct nfc_dev *nfc_dev, } } -static int nci_transceive(struct nfc_dev *nfc_dev, struct nfc_target *target, - struct sk_buff *skb, - data_exchange_cb_t cb, void *cb_context) +static int nci_data_exchange(struct nfc_dev *nfc_dev, struct nfc_target *target, + struct sk_buff *skb, + data_exchange_cb_t cb, void *cb_context) { struct nci_dev *ndev = nfc_get_drvdata(nfc_dev); int rc; @@ -557,7 +556,7 @@ static struct nfc_ops nci_nfc_ops = { .stop_poll = nci_stop_poll, .activate_target = nci_activate_target, .deactivate_target = nci_deactivate_target, - .im_transceive = nci_transceive, + .data_exchange = nci_data_exchange, }; /* ---- Interface to NCI drivers ---- */ diff --git a/trunk/net/nfc/netlink.c b/trunk/net/nfc/netlink.c index 03c31db38f12..581d419083aa 100644 --- a/trunk/net/nfc/netlink.c +++ b/trunk/net/nfc/netlink.c @@ -49,8 +49,6 @@ static const struct nla_policy nfc_genl_policy[NFC_ATTR_MAX + 1] = { [NFC_ATTR_COMM_MODE] = { .type = NLA_U8 }, [NFC_ATTR_RF_MODE] = { .type = NLA_U8 }, [NFC_ATTR_DEVICE_POWERED] = { .type = NLA_U8 }, - [NFC_ATTR_IM_PROTOCOLS] = { .type = NLA_U32 }, - [NFC_ATTR_TM_PROTOCOLS] = { .type = NLA_U32 }, }; static int nfc_genl_send_target(struct sk_buff *msg, struct nfc_target *target, @@ -221,68 +219,6 @@ int nfc_genl_target_lost(struct nfc_dev *dev, u32 target_idx) return -EMSGSIZE; } -int nfc_genl_tm_activated(struct nfc_dev *dev, u32 protocol) -{ - struct sk_buff *msg; - void *hdr; - - msg = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL); - if (!msg) - return -ENOMEM; - - hdr = genlmsg_put(msg, 0, 0, &nfc_genl_family, 0, - NFC_EVENT_TM_ACTIVATED); - if (!hdr) - goto free_msg; - - if (nla_put_u32(msg, NFC_ATTR_DEVICE_INDEX, dev->idx)) - goto nla_put_failure; - if (nla_put_u32(msg, NFC_ATTR_TM_PROTOCOLS, protocol)) - goto nla_put_failure; - - genlmsg_end(msg, hdr); - - genlmsg_multicast(msg, 0, nfc_genl_event_mcgrp.id, GFP_KERNEL); - - return 0; - -nla_put_failure: - genlmsg_cancel(msg, hdr); -free_msg: - nlmsg_free(msg); - return -EMSGSIZE; -} - -int nfc_genl_tm_deactivated(struct nfc_dev *dev) -{ - struct sk_buff *msg; - void *hdr; - - msg = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL); - if (!msg) - return -ENOMEM; - - hdr = genlmsg_put(msg, 0, 0, &nfc_genl_family, 0, - NFC_EVENT_TM_DEACTIVATED); - if (!hdr) - goto free_msg; - - if (nla_put_u32(msg, NFC_ATTR_DEVICE_INDEX, dev->idx)) - goto nla_put_failure; - - genlmsg_end(msg, hdr); - - genlmsg_multicast(msg, 0, nfc_genl_event_mcgrp.id, GFP_KERNEL); - - return 0; - -nla_put_failure: - genlmsg_cancel(msg, hdr); -free_msg: - nlmsg_free(msg); - return -EMSGSIZE; -} - int nfc_genl_device_added(struct nfc_dev *dev) { struct sk_buff *msg; @@ -583,25 +519,16 @@ static int nfc_genl_start_poll(struct sk_buff *skb, struct genl_info *info) struct nfc_dev *dev; int rc; u32 idx; - u32 im_protocols = 0, tm_protocols = 0; + u32 protocols; pr_debug("Poll start\n"); if (!info->attrs[NFC_ATTR_DEVICE_INDEX] || - ((!info->attrs[NFC_ATTR_IM_PROTOCOLS] && - !info->attrs[NFC_ATTR_PROTOCOLS]) && - !info->attrs[NFC_ATTR_TM_PROTOCOLS])) + !info->attrs[NFC_ATTR_PROTOCOLS]) return -EINVAL; idx = nla_get_u32(info->attrs[NFC_ATTR_DEVICE_INDEX]); - - if (info->attrs[NFC_ATTR_TM_PROTOCOLS]) - tm_protocols = nla_get_u32(info->attrs[NFC_ATTR_TM_PROTOCOLS]); - - if (info->attrs[NFC_ATTR_IM_PROTOCOLS]) - im_protocols = nla_get_u32(info->attrs[NFC_ATTR_IM_PROTOCOLS]); - else if (info->attrs[NFC_ATTR_PROTOCOLS]) - im_protocols = nla_get_u32(info->attrs[NFC_ATTR_PROTOCOLS]); + protocols = nla_get_u32(info->attrs[NFC_ATTR_PROTOCOLS]); dev = nfc_get_device(idx); if (!dev) @@ -609,7 +536,7 @@ static int nfc_genl_start_poll(struct sk_buff *skb, struct genl_info *info) mutex_lock(&dev->genl_data.genl_data_mutex); - rc = nfc_start_poll(dev, im_protocols, tm_protocols); + rc = nfc_start_poll(dev, protocols); if (!rc) dev->genl_data.poll_req_pid = info->snd_pid; diff --git a/trunk/net/nfc/nfc.h b/trunk/net/nfc/nfc.h index c5e42b79a418..3dd4232ae664 100644 --- a/trunk/net/nfc/nfc.h +++ b/trunk/net/nfc/nfc.h @@ -55,7 +55,6 @@ int nfc_llcp_register_device(struct nfc_dev *dev); void nfc_llcp_unregister_device(struct nfc_dev *dev); int nfc_llcp_set_remote_gb(struct nfc_dev *dev, u8 *gb, u8 gb_len); u8 *nfc_llcp_general_bytes(struct nfc_dev *dev, size_t *general_bytes_len); -int nfc_llcp_data_received(struct nfc_dev *dev, struct sk_buff *skb); int __init nfc_llcp_init(void); void nfc_llcp_exit(void); @@ -91,12 +90,6 @@ static inline u8 *nfc_llcp_general_bytes(struct nfc_dev *dev, size_t *gb_len) return NULL; } -static inline int nfc_llcp_data_received(struct nfc_dev *dev, - struct sk_buff *skb) -{ - return 0; -} - static inline int nfc_llcp_init(void) { return 0; @@ -135,9 +128,6 @@ int nfc_genl_dep_link_up_event(struct nfc_dev *dev, u32 target_idx, u8 comm_mode, u8 rf_mode); int nfc_genl_dep_link_down_event(struct nfc_dev *dev); -int nfc_genl_tm_activated(struct nfc_dev *dev, u32 protocol); -int nfc_genl_tm_deactivated(struct nfc_dev *dev); - struct nfc_dev *nfc_get_device(unsigned int idx); static inline void nfc_put_device(struct nfc_dev *dev) @@ -168,7 +158,7 @@ int nfc_dev_up(struct nfc_dev *dev); int nfc_dev_down(struct nfc_dev *dev); -int nfc_start_poll(struct nfc_dev *dev, u32 im_protocols, u32 tm_protocols); +int nfc_start_poll(struct nfc_dev *dev, u32 protocols); int nfc_stop_poll(struct nfc_dev *dev); diff --git a/trunk/net/rfkill/core.c b/trunk/net/rfkill/core.c index 752b72360ebc..f974961754ca 100644 --- a/trunk/net/rfkill/core.c +++ b/trunk/net/rfkill/core.c @@ -325,7 +325,7 @@ static void __rfkill_switch_all(const enum rfkill_type type, bool blocked) rfkill_global_states[type].cur = blocked; list_for_each_entry(rfkill, &rfkill_list, node) { - if (rfkill->type != type && type != RFKILL_TYPE_ALL) + if (rfkill->type != type) continue; rfkill_set_block(rfkill, blocked); diff --git a/trunk/net/wireless/chan.c b/trunk/net/wireless/chan.c index c1999e45a07c..20b87d895722 100644 --- a/trunk/net/wireless/chan.c +++ b/trunk/net/wireless/chan.c @@ -78,17 +78,50 @@ bool cfg80211_can_beacon_sec_chan(struct wiphy *wiphy, } EXPORT_SYMBOL(cfg80211_can_beacon_sec_chan); -int cfg80211_set_monitor_channel(struct cfg80211_registered_device *rdev, - int freq, enum nl80211_channel_type chantype) +int cfg80211_set_freq(struct cfg80211_registered_device *rdev, + struct wireless_dev *wdev, int freq, + enum nl80211_channel_type channel_type) { struct ieee80211_channel *chan; + int result; - if (!rdev->ops->set_monitor_channel) + if (wdev && wdev->iftype == NL80211_IFTYPE_MONITOR) + wdev = NULL; + + if (wdev) { + ASSERT_WDEV_LOCK(wdev); + + if (!netif_running(wdev->netdev)) + return -ENETDOWN; + } + + if (!rdev->ops->set_channel) return -EOPNOTSUPP; - chan = rdev_freq_to_chan(rdev, freq, chantype); + chan = rdev_freq_to_chan(rdev, freq, channel_type); if (!chan) return -EINVAL; - return rdev->ops->set_monitor_channel(&rdev->wiphy, chan, chantype); + /* Both channels should be able to initiate communication */ + if (wdev && (wdev->iftype == NL80211_IFTYPE_ADHOC || + wdev->iftype == NL80211_IFTYPE_AP || + wdev->iftype == NL80211_IFTYPE_AP_VLAN || + wdev->iftype == NL80211_IFTYPE_MESH_POINT || + wdev->iftype == NL80211_IFTYPE_P2P_GO) && + !cfg80211_can_beacon_sec_chan(&rdev->wiphy, chan, channel_type)) { + printk(KERN_DEBUG + "cfg80211: Secondary channel not allowed to beacon\n"); + return -EINVAL; + } + + result = rdev->ops->set_channel(&rdev->wiphy, + wdev ? wdev->netdev : NULL, + chan, channel_type); + if (result) + return result; + + if (wdev) + wdev->channel = chan; + + return 0; } diff --git a/trunk/net/wireless/core.h b/trunk/net/wireless/core.h index 9348a47562a4..1d3d24126946 100644 --- a/trunk/net/wireless/core.h +++ b/trunk/net/wireless/core.h @@ -444,8 +444,9 @@ cfg80211_can_add_interface(struct cfg80211_registered_device *rdev, struct ieee80211_channel * rdev_freq_to_chan(struct cfg80211_registered_device *rdev, int freq, enum nl80211_channel_type channel_type); -int cfg80211_set_monitor_channel(struct cfg80211_registered_device *rdev, - int freq, enum nl80211_channel_type chantype); +int cfg80211_set_freq(struct cfg80211_registered_device *rdev, + struct wireless_dev *wdev, int freq, + enum nl80211_channel_type channel_type); int ieee80211_get_ratemask(struct ieee80211_supported_band *sband, const u8 *rates, unsigned int n_rates, diff --git a/trunk/net/wireless/ibss.c b/trunk/net/wireless/ibss.c index 89baa3328411..d2a19b0ff71f 100644 --- a/trunk/net/wireless/ibss.c +++ b/trunk/net/wireless/ibss.c @@ -42,7 +42,6 @@ void __cfg80211_ibss_joined(struct net_device *dev, const u8 *bssid) cfg80211_hold_bss(bss_from_pub(bss)); wdev->current_bss = bss_from_pub(bss); - wdev->sme_state = CFG80211_SME_CONNECTED; cfg80211_upload_connect_keys(wdev); nl80211_send_ibss_bssid(wiphy_to_dev(wdev->wiphy), dev, bssid, @@ -61,7 +60,7 @@ void cfg80211_ibss_joined(struct net_device *dev, const u8 *bssid, gfp_t gfp) struct cfg80211_event *ev; unsigned long flags; - CFG80211_DEV_WARN_ON(wdev->sme_state != CFG80211_SME_CONNECTING); + CFG80211_DEV_WARN_ON(!wdev->ssid_len); ev = kzalloc(sizeof(*ev), gfp); if (!ev) @@ -116,11 +115,9 @@ int __cfg80211_join_ibss(struct cfg80211_registered_device *rdev, #ifdef CONFIG_CFG80211_WEXT wdev->wext.ibss.channel = params->channel; #endif - wdev->sme_state = CFG80211_SME_CONNECTING; err = rdev->ops->join_ibss(&rdev->wiphy, dev, params); if (err) { wdev->connect_keys = NULL; - wdev->sme_state = CFG80211_SME_IDLE; return err; } @@ -172,7 +169,6 @@ static void __cfg80211_clear_ibss(struct net_device *dev, bool nowext) } wdev->current_bss = NULL; - wdev->sme_state = CFG80211_SME_IDLE; wdev->ssid_len = 0; #ifdef CONFIG_CFG80211_WEXT if (!nowext) diff --git a/trunk/net/wireless/mesh.c b/trunk/net/wireless/mesh.c index b44c736bf9cf..2e3b700eba32 100644 --- a/trunk/net/wireless/mesh.c +++ b/trunk/net/wireless/mesh.c @@ -179,13 +179,6 @@ int cfg80211_set_mesh_freq(struct cfg80211_registered_device *rdev, { struct ieee80211_channel *channel; - channel = rdev_freq_to_chan(rdev, freq, channel_type); - if (!channel || !cfg80211_can_beacon_sec_chan(&rdev->wiphy, - channel, - channel_type)) { - return -EINVAL; - } - /* * Workaround for libertas (only!), it puts the interface * into mesh mode but doesn't implement join_mesh. Instead, @@ -193,20 +186,27 @@ int cfg80211_set_mesh_freq(struct cfg80211_registered_device *rdev, * you set the channel. Note that the libertas mesh isn't * compatible with 802.11 mesh. */ - if (rdev->ops->libertas_set_mesh_channel) { - if (channel_type != NL80211_CHAN_NO_HT) - return -EINVAL; + if (!rdev->ops->join_mesh) { + int err; if (!netif_running(wdev->netdev)) return -ENETDOWN; - return rdev->ops->libertas_set_mesh_channel(&rdev->wiphy, - wdev->netdev, - channel); + wdev_lock(wdev); + err = cfg80211_set_freq(rdev, wdev, freq, channel_type); + wdev_unlock(wdev); + + return err; } if (wdev->mesh_id_len) return -EBUSY; + channel = rdev_freq_to_chan(rdev, freq, channel_type); + if (!channel || !cfg80211_can_beacon_sec_chan(&rdev->wiphy, + channel, + channel_type)) { + return -EINVAL; + } wdev->preset_chan = channel; wdev->preset_chantype = channel_type; return 0; diff --git a/trunk/net/wireless/mlme.c b/trunk/net/wireless/mlme.c index da4406f11929..eb90988bbd36 100644 --- a/trunk/net/wireless/mlme.c +++ b/trunk/net/wireless/mlme.c @@ -947,6 +947,8 @@ void cfg80211_ch_switch_notify(struct net_device *dev, int freq, if (WARN_ON(!chan)) goto out; + wdev->channel = chan; + nl80211_ch_switch_notify(rdev, dev, freq, type, GFP_KERNEL); out: wdev_unlock(wdev); diff --git a/trunk/net/wireless/nl80211.c b/trunk/net/wireless/nl80211.c index 7ae54b82291f..b22f1f876881 100644 --- a/trunk/net/wireless/nl80211.c +++ b/trunk/net/wireless/nl80211.c @@ -921,7 +921,7 @@ static int nl80211_send_wiphy(struct sk_buff *msg, u32 pid, u32 seq, int flags, if (nla_put_u32(msg, i, NL80211_CMD_SET_WIPHY_NETNS)) goto nla_put_failure; } - if (dev->ops->set_monitor_channel || dev->ops->start_ap || + if (dev->ops->set_channel || dev->ops->start_ap || dev->ops->join_mesh) { i++; if (nla_put_u32(msg, i, NL80211_CMD_SET_CHANNEL)) @@ -1178,8 +1178,8 @@ static bool nl80211_can_set_dev_channel(struct wireless_dev *wdev) * the channel in the start-ap or join-mesh commands instead. * * Monitors are special as they are normally slaved to - * whatever else is going on, so they have their own special - * operation to set the monitor channel if possible. + * whatever else is going on, so they behave as though + * you tried setting the wiphy channel itself. */ return !wdev || wdev->iftype == NL80211_IFTYPE_AP || @@ -1217,10 +1217,6 @@ static int __nl80211_set_channel(struct cfg80211_registered_device *rdev, enum nl80211_channel_type channel_type = NL80211_CHAN_NO_HT; u32 freq; int result; - enum nl80211_iftype iftype = NL80211_IFTYPE_MONITOR; - - if (wdev) - iftype = wdev->iftype; if (!info->attrs[NL80211_ATTR_WIPHY_FREQ]) return -EINVAL; @@ -1235,7 +1231,7 @@ static int __nl80211_set_channel(struct cfg80211_registered_device *rdev, freq = nla_get_u32(info->attrs[NL80211_ATTR_WIPHY_FREQ]); mutex_lock(&rdev->devlist_mtx); - switch (iftype) { + if (wdev) switch (wdev->iftype) { case NL80211_IFTYPE_AP: case NL80211_IFTYPE_P2P_GO: if (wdev->beacon_interval) { @@ -1256,11 +1252,12 @@ static int __nl80211_set_channel(struct cfg80211_registered_device *rdev, case NL80211_IFTYPE_MESH_POINT: result = cfg80211_set_mesh_freq(rdev, wdev, freq, channel_type); break; - case NL80211_IFTYPE_MONITOR: - result = cfg80211_set_monitor_channel(rdev, freq, channel_type); - break; default: - result = -EINVAL; + wdev_lock(wdev); + result = cfg80211_set_freq(rdev, wdev, freq, channel_type); + wdev_unlock(wdev); + } else { + result = cfg80211_set_freq(rdev, NULL, freq, channel_type); } mutex_unlock(&rdev->devlist_mtx); @@ -5545,18 +5542,18 @@ static int nl80211_remain_on_channel(struct sk_buff *skb, duration = nla_get_u32(info->attrs[NL80211_ATTR_DURATION]); - if (!rdev->ops->remain_on_channel || - !(rdev->wiphy.flags & WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL)) - return -EOPNOTSUPP; - /* - * We should be on that channel for at least a minimum amount of - * time (10ms) but no longer than the driver supports. + * We should be on that channel for at least one jiffie, + * and more than 5 seconds seems excessive. */ - if (duration < NL80211_MIN_REMAIN_ON_CHANNEL_TIME || + if (!duration || !msecs_to_jiffies(duration) || duration > rdev->wiphy.max_remain_on_channel_duration) return -EINVAL; + if (!rdev->ops->remain_on_channel || + !(rdev->wiphy.flags & WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL)) + return -EOPNOTSUPP; + if (info->attrs[NL80211_ATTR_WIPHY_CHANNEL_TYPE] && !nl80211_valid_channel_type(info, &channel_type)) return -EINVAL; @@ -5827,15 +5824,6 @@ static int nl80211_tx_mgmt(struct sk_buff *skb, struct genl_info *info) if (!(rdev->wiphy.flags & WIPHY_FLAG_OFFCHAN_TX)) return -EINVAL; wait = nla_get_u32(info->attrs[NL80211_ATTR_DURATION]); - - /* - * We should wait on the channel for at least a minimum amount - * of time (10ms) but no longer than the driver supports. - */ - if (wait < NL80211_MIN_REMAIN_ON_CHANNEL_TIME || - wait > rdev->wiphy.max_remain_on_channel_duration) - return -EINVAL; - } if (info->attrs[NL80211_ATTR_WIPHY_CHANNEL_TYPE]) { diff --git a/trunk/net/wireless/util.c b/trunk/net/wireless/util.c index 8f2d68fc3a44..55d99466babb 100644 --- a/trunk/net/wireless/util.c +++ b/trunk/net/wireless/util.c @@ -935,7 +935,6 @@ int cfg80211_can_change_interface(struct cfg80211_registered_device *rdev, enum nl80211_iftype iftype) { struct wireless_dev *wdev_iter; - u32 used_iftypes = BIT(iftype); int num[NUM_NL80211_IFTYPES]; int total = 1; int i, j; @@ -962,7 +961,6 @@ int cfg80211_can_change_interface(struct cfg80211_registered_device *rdev, num[wdev_iter->iftype]++; total++; - used_iftypes |= BIT(wdev_iter->iftype); } mutex_unlock(&rdev->devlist_mtx); @@ -972,7 +970,6 @@ int cfg80211_can_change_interface(struct cfg80211_registered_device *rdev, for (i = 0; i < rdev->wiphy.n_iface_combinations; i++) { const struct ieee80211_iface_combination *c; struct ieee80211_iface_limit *limits; - u32 all_iftypes = 0; c = &rdev->wiphy.iface_combinations[i]; @@ -987,7 +984,6 @@ int cfg80211_can_change_interface(struct cfg80211_registered_device *rdev, if (rdev->wiphy.software_iftypes & BIT(iftype)) continue; for (j = 0; j < c->n_limits; j++) { - all_iftypes |= limits[j].types; if (!(limits[j].types & BIT(iftype))) continue; if (limits[j].max < num[iftype]) @@ -995,20 +991,7 @@ int cfg80211_can_change_interface(struct cfg80211_registered_device *rdev, limits[j].max -= num[iftype]; } } - - /* - * Finally check that all iftypes that we're currently - * using are actually part of this combination. If they - * aren't then we can't use this combination and have - * to continue to the next. - */ - if ((all_iftypes & used_iftypes) != used_iftypes) - goto cont; - - /* - * This combination covered all interface types and - * supported the requested numbers, so we're good. - */ + /* yay, it fits */ kfree(limits); return 0; cont: diff --git a/trunk/net/wireless/wext-compat.c b/trunk/net/wireless/wext-compat.c index bc879833b21f..faeb03548aa4 100644 --- a/trunk/net/wireless/wext-compat.c +++ b/trunk/net/wireless/wext-compat.c @@ -802,7 +802,9 @@ static int cfg80211_wext_siwfreq(struct net_device *dev, if (freq == 0) return -EINVAL; mutex_lock(&rdev->devlist_mtx); - err = cfg80211_set_monitor_channel(rdev, freq, NL80211_CHAN_NO_HT); + wdev_lock(wdev); + err = cfg80211_set_freq(rdev, wdev, freq, NL80211_CHAN_NO_HT); + wdev_unlock(wdev); mutex_unlock(&rdev->devlist_mtx); return err; case NL80211_IFTYPE_MESH_POINT: @@ -846,7 +848,11 @@ static int cfg80211_wext_giwfreq(struct net_device *dev, freq->e = 6; return 0; default: - return -EINVAL; + if (!wdev->channel) + return -EINVAL; + freq->m = wdev->channel->center_freq; + freq->e = 6; + return 0; } } diff --git a/trunk/net/wireless/wext-sme.c b/trunk/net/wireless/wext-sme.c index 1f773f668d1a..7decbd357d51 100644 --- a/trunk/net/wireless/wext-sme.c +++ b/trunk/net/wireless/wext-sme.c @@ -111,15 +111,9 @@ int cfg80211_mgd_wext_siwfreq(struct net_device *dev, wdev->wext.connect.channel = chan; - /* - * SSID is not set, we just want to switch monitor channel, - * this is really just backward compatibility, if the SSID - * is set then we use the channel to select the BSS to use - * to connect to instead. If we were connected on another - * channel we disconnected above and reconnect below. - */ + /* SSID is not set, we just want to switch channel */ if (chan && !wdev->wext.connect.ssid_len) { - err = cfg80211_set_monitor_channel(rdev, freq, NL80211_CHAN_NO_HT); + err = cfg80211_set_freq(rdev, wdev, freq, NL80211_CHAN_NO_HT); goto out; }