]> git.kernelconcepts.de Git - karo-tx-linux.git/commitdiff
Merge ssh://master.kernel.org/pub/scm/linux/kernel/git/linville/wireless-next-2.6...
authorJohn W. Linville <linville@tuxdriver.com>
Tue, 24 May 2011 20:47:54 +0000 (16:47 -0400)
committerJohn W. Linville <linville@tuxdriver.com>
Tue, 24 May 2011 20:47:54 +0000 (16:47 -0400)
143 files changed:
drivers/bcma/host_pci.c
drivers/net/wireless/airo.c
drivers/net/wireless/ath/ath9k/ahb.c
drivers/net/wireless/ath/ath9k/ani.c
drivers/net/wireless/ath/ath9k/ani.h
drivers/net/wireless/ath/ath9k/ar5008_initvals.h
drivers/net/wireless/ath/ath9k/ar5008_phy.c
drivers/net/wireless/ath/ath9k/ar9001_initvals.h
drivers/net/wireless/ath/ath9k/ar9002_calib.c
drivers/net/wireless/ath/ath9k/ar9002_hw.c
drivers/net/wireless/ath/ath9k/ar9002_initvals.h
drivers/net/wireless/ath/ath9k/ar9002_mac.c
drivers/net/wireless/ath/ath9k/ar9002_phy.c
drivers/net/wireless/ath/ath9k/ar9002_phy.h
drivers/net/wireless/ath/ath9k/ar9003_2p2_initvals.h
drivers/net/wireless/ath/ath9k/ar9003_calib.c
drivers/net/wireless/ath/ath9k/ar9003_eeprom.c
drivers/net/wireless/ath/ath9k/ar9003_eeprom.h
drivers/net/wireless/ath/ath9k/ar9003_hw.c
drivers/net/wireless/ath/ath9k/ar9003_mac.c
drivers/net/wireless/ath/ath9k/ar9003_mac.h
drivers/net/wireless/ath/ath9k/ar9003_paprd.c
drivers/net/wireless/ath/ath9k/ar9003_phy.c
drivers/net/wireless/ath/ath9k/ar9003_phy.h
drivers/net/wireless/ath/ath9k/ar9485_initvals.h
drivers/net/wireless/ath/ath9k/ath9k.h
drivers/net/wireless/ath/ath9k/beacon.c
drivers/net/wireless/ath/ath9k/btcoex.c
drivers/net/wireless/ath/ath9k/btcoex.h
drivers/net/wireless/ath/ath9k/calib.c
drivers/net/wireless/ath/ath9k/calib.h
drivers/net/wireless/ath/ath9k/common.c
drivers/net/wireless/ath/ath9k/common.h
drivers/net/wireless/ath/ath9k/debug.c
drivers/net/wireless/ath/ath9k/debug.h
drivers/net/wireless/ath/ath9k/eeprom.c
drivers/net/wireless/ath/ath9k/eeprom.h
drivers/net/wireless/ath/ath9k/eeprom_4k.c
drivers/net/wireless/ath/ath9k/eeprom_9287.c
drivers/net/wireless/ath/ath9k/eeprom_def.c
drivers/net/wireless/ath/ath9k/gpio.c
drivers/net/wireless/ath/ath9k/hif_usb.c
drivers/net/wireless/ath/ath9k/hif_usb.h
drivers/net/wireless/ath/ath9k/htc.h
drivers/net/wireless/ath/ath9k/htc_drv_beacon.c
drivers/net/wireless/ath/ath9k/htc_drv_gpio.c
drivers/net/wireless/ath/ath9k/htc_drv_init.c
drivers/net/wireless/ath/ath9k/htc_drv_main.c
drivers/net/wireless/ath/ath9k/htc_drv_txrx.c
drivers/net/wireless/ath/ath9k/htc_hst.c
drivers/net/wireless/ath/ath9k/htc_hst.h
drivers/net/wireless/ath/ath9k/hw-ops.h
drivers/net/wireless/ath/ath9k/hw.c
drivers/net/wireless/ath/ath9k/hw.h
drivers/net/wireless/ath/ath9k/init.c
drivers/net/wireless/ath/ath9k/mac.c
drivers/net/wireless/ath/ath9k/mac.h
drivers/net/wireless/ath/ath9k/main.c
drivers/net/wireless/ath/ath9k/pci.c
drivers/net/wireless/ath/ath9k/phy.h
drivers/net/wireless/ath/ath9k/rc.c
drivers/net/wireless/ath/ath9k/rc.h
drivers/net/wireless/ath/ath9k/recv.c
drivers/net/wireless/ath/ath9k/reg.h
drivers/net/wireless/ath/ath9k/wmi.c
drivers/net/wireless/ath/ath9k/wmi.h
drivers/net/wireless/ath/ath9k/xmit.c
drivers/net/wireless/ath/carl9170/carl9170.h
drivers/net/wireless/ath/carl9170/fw.c
drivers/net/wireless/ath/carl9170/main.c
drivers/net/wireless/ath/hw.c
drivers/net/wireless/b43/b43.h
drivers/net/wireless/b43/dma.c
drivers/net/wireless/b43/leds.c
drivers/net/wireless/b43/lo.c
drivers/net/wireless/b43/main.c
drivers/net/wireless/b43/phy_a.c
drivers/net/wireless/b43/phy_common.c
drivers/net/wireless/b43/phy_g.c
drivers/net/wireless/b43/phy_lp.c
drivers/net/wireless/b43/phy_n.c
drivers/net/wireless/b43/pio.c
drivers/net/wireless/b43/rfkill.c
drivers/net/wireless/b43/sdio.c
drivers/net/wireless/b43/sysfs.c
drivers/net/wireless/b43/tables_lpphy.c
drivers/net/wireless/b43/wa.c
drivers/net/wireless/b43/xmit.c
drivers/net/wireless/iwlwifi/iwl-1000.c
drivers/net/wireless/iwlwifi/iwl-2000.c
drivers/net/wireless/iwlwifi/iwl-5000.c
drivers/net/wireless/iwlwifi/iwl-6000.c
drivers/net/wireless/iwlwifi/iwl-agn-calib.c
drivers/net/wireless/iwlwifi/iwl-agn-lib.c
drivers/net/wireless/iwlwifi/iwl-agn-rs.c
drivers/net/wireless/iwlwifi/iwl-agn-rxon.c
drivers/net/wireless/iwlwifi/iwl-agn-sta.c
drivers/net/wireless/iwlwifi/iwl-agn-tx.c
drivers/net/wireless/iwlwifi/iwl-agn-ucode.c
drivers/net/wireless/iwlwifi/iwl-agn.c
drivers/net/wireless/iwlwifi/iwl-agn.h
drivers/net/wireless/iwlwifi/iwl-commands.h
drivers/net/wireless/iwlwifi/iwl-core.h
drivers/net/wireless/iwlwifi/iwl-dev.h
drivers/net/wireless/iwlwifi/iwl-devtrace.h
drivers/net/wireless/iwlwifi/iwl-eeprom.c
drivers/net/wireless/iwlwifi/iwl-hcmd.c
drivers/net/wireless/iwlwifi/iwl-led.c
drivers/net/wireless/iwlwifi/iwl-sta.c
drivers/net/wireless/iwlwifi/iwl-sv-open.c
drivers/net/wireless/iwlwifi/iwl-testmode.h
drivers/net/wireless/iwlwifi/iwl-tx.c
drivers/net/wireless/iwmc3200wifi/rx.c
drivers/net/wireless/mwifiex/11n_aggr.c
drivers/net/wireless/mwifiex/main.h
drivers/net/wireless/mwifiex/txrx.c
drivers/net/wireless/mwifiex/wmm.c
drivers/net/wireless/p54/p54usb.c
drivers/net/wireless/rndis_wlan.c
drivers/net/wireless/rtlwifi/ps.c
drivers/net/wireless/rtlwifi/rtl8192c/phy_common.c
drivers/net/wireless/rtlwifi/rtl8192ce/phy.c
drivers/net/wireless/rtlwifi/rtl8192ce/phy.h
drivers/net/wireless/rtlwifi/rtl8192ce/sw.c
drivers/staging/ath6kl/os/linux/cfg80211.c
drivers/staging/brcm80211/brcmfmac/wl_cfg80211.c
drivers/staging/wlan-ng/cfg80211.c
fs/proc/generic.c
include/linux/rfkill-gpio.h [new file with mode: 0644]
include/net/cfg80211.h
include/net/mac80211.h
net/mac80211/iface.c
net/mac80211/main.c
net/mac80211/mesh.h
net/mac80211/mesh_pathtbl.c
net/mac80211/scan.c
net/rfkill/Kconfig
net/rfkill/Makefile
net/rfkill/rfkill-gpio.c [new file with mode: 0644]
net/wireless/core.h
net/wireless/nl80211.c
net/wireless/sme.c
net/wireless/util.c

index 99dd36e8500b8df8706885bcc2d9dc31694e73cb..ffd8797faf4f0d3a10bcd49dbef7264e399347dd 100644 (file)
@@ -171,6 +171,7 @@ static void bcma_host_pci_remove(struct pci_dev *dev)
 }
 
 static DEFINE_PCI_DEVICE_TABLE(bcma_pci_bridge_tbl) = {
+       { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x0576) },
        { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4331) },
        { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4353) },
        { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4727) },
index 4e5c7a11f04aa5c496dcf7872bb75705c34588a5..aa9ff130e2972d39027d9a5fa8c05813f7f97f98 100644 (file)
@@ -4500,17 +4500,15 @@ static int setup_proc_entry( struct net_device *dev,
        struct proc_dir_entry *entry;
        /* First setup the device directory */
        strcpy(apriv->proc_name,dev->name);
-       apriv->proc_entry = create_proc_entry(apriv->proc_name,
-                                             S_IFDIR|airo_perm,
-                                             airo_entry);
+       apriv->proc_entry = proc_mkdir_mode(apriv->proc_name, airo_perm,
+                                           airo_entry);
        if (!apriv->proc_entry)
                goto fail;
        apriv->proc_entry->uid = proc_uid;
        apriv->proc_entry->gid = proc_gid;
 
        /* Setup the StatsDelta */
-       entry = proc_create_data("StatsDelta",
-                                S_IFREG | (S_IRUGO&proc_perm),
+       entry = proc_create_data("StatsDelta", S_IRUGO & proc_perm,
                                 apriv->proc_entry, &proc_statsdelta_ops, dev);
        if (!entry)
                goto fail_stats_delta;
@@ -4518,8 +4516,7 @@ static int setup_proc_entry( struct net_device *dev,
        entry->gid = proc_gid;
 
        /* Setup the Stats */
-       entry = proc_create_data("Stats",
-                                S_IFREG | (S_IRUGO&proc_perm),
+       entry = proc_create_data("Stats", S_IRUGO & proc_perm,
                                 apriv->proc_entry, &proc_stats_ops, dev);
        if (!entry)
                goto fail_stats;
@@ -4527,8 +4524,7 @@ static int setup_proc_entry( struct net_device *dev,
        entry->gid = proc_gid;
 
        /* Setup the Status */
-       entry = proc_create_data("Status",
-                                S_IFREG | (S_IRUGO&proc_perm),
+       entry = proc_create_data("Status", S_IRUGO & proc_perm,
                                 apriv->proc_entry, &proc_status_ops, dev);
        if (!entry)
                goto fail_status;
@@ -4536,8 +4532,7 @@ static int setup_proc_entry( struct net_device *dev,
        entry->gid = proc_gid;
 
        /* Setup the Config */
-       entry = proc_create_data("Config",
-                                S_IFREG | proc_perm,
+       entry = proc_create_data("Config", proc_perm,
                                 apriv->proc_entry, &proc_config_ops, dev);
        if (!entry)
                goto fail_config;
@@ -4545,8 +4540,7 @@ static int setup_proc_entry( struct net_device *dev,
        entry->gid = proc_gid;
 
        /* Setup the SSID */
-       entry = proc_create_data("SSID",
-                                S_IFREG | proc_perm,
+       entry = proc_create_data("SSID", proc_perm,
                                 apriv->proc_entry, &proc_SSID_ops, dev);
        if (!entry)
                goto fail_ssid;
@@ -4554,8 +4548,7 @@ static int setup_proc_entry( struct net_device *dev,
        entry->gid = proc_gid;
 
        /* Setup the APList */
-       entry = proc_create_data("APList",
-                                S_IFREG | proc_perm,
+       entry = proc_create_data("APList", proc_perm,
                                 apriv->proc_entry, &proc_APList_ops, dev);
        if (!entry)
                goto fail_aplist;
@@ -4563,8 +4556,7 @@ static int setup_proc_entry( struct net_device *dev,
        entry->gid = proc_gid;
 
        /* Setup the BSSList */
-       entry = proc_create_data("BSSList",
-                                S_IFREG | proc_perm,
+       entry = proc_create_data("BSSList", proc_perm,
                                 apriv->proc_entry, &proc_BSSList_ops, dev);
        if (!entry)
                goto fail_bsslist;
@@ -4572,8 +4564,7 @@ static int setup_proc_entry( struct net_device *dev,
        entry->gid = proc_gid;
 
        /* Setup the WepKey */
-       entry = proc_create_data("WepKey",
-                                S_IFREG | proc_perm,
+       entry = proc_create_data("WepKey", proc_perm,
                                 apriv->proc_entry, &proc_wepkey_ops, dev);
        if (!entry)
                goto fail_wepkey;
@@ -5705,9 +5696,7 @@ static int __init airo_init_module( void )
 {
        int i;
 
-       airo_entry = create_proc_entry("driver/aironet",
-                                      S_IFDIR | airo_perm,
-                                      NULL);
+       airo_entry = proc_mkdir_mode("driver/aironet", airo_perm, NULL);
 
        if (airo_entry) {
                airo_entry->uid = proc_uid;
index 61956392f2da44c3b8dd86b0f84c5a6e6675c5ed..5b49cd03bfdfcaa09d130c07fed1d0bab0607afe 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008-2009 Atheros Communications Inc.
+ * Copyright (c) 2008-2011 Atheros Communications Inc.
  * Copyright (c) 2009 Gabor Juhos <juhosg@openwrt.org>
  * Copyright (c) 2009 Imre Kaloz <kaloz@openwrt.org>
  *
index 5a1f4f511bc152df2e033380e666c45a0bb9cc5b..bfb6481f01f9ba9d06aa92fecf9c6ccd4e9c0757 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008-2010 Atheros Communications Inc.
+ * Copyright (c) 2008-2011 Atheros Communications 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
index 0cd6783de883668d2f433bfb07f5ffe0c47863cb..dbab5b9ce4948a3174a4a6e1bb4c74b800f3eb90 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008-2009 Atheros Communications Inc.
+ * Copyright (c) 2008-2011 Atheros Communications 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
index 36f7d0639db333d51e904ab6a2871909d06937d1..234617c948a1d8589e4b1a56f30e758ffb597993 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010 Atheros Communications Inc.
+ * Copyright (c) 2010-2011 Atheros Communications 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
index 4bf9dab4f2b38b776d25d5226222be1f7bd36474..441bb33f17adb705af53f5a04f764a6cfa911f46 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008-2010 Atheros Communications Inc.
+ * Copyright (c) 2008-2011 Atheros Communications 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
index 69a94c7e45cb3df2b9b4ce79d5f89f0bdbe09b9d..6d2e2f3303f9125db9f4b7b3fcf47388b61223c7 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010 Atheros Communications Inc.
+ * Copyright (c) 2010-2011 Atheros Communications 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
index cb611b287b35a4459bdce1fa4c179b72b64aef94..015d97439935d05b0deb119471334929b7891f0f 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008-2010 Atheros Communications Inc.
+ * Copyright (c) 2008-2011 Atheros Communications 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
index f44c84ab5dceddae414dfdec5f877e98bc0013e6..f344cc2b3d5966827eb352cb5761d14b13833568 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008-2010 Atheros Communications Inc.
+ * Copyright (c) 2008-2011 Atheros Communications 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
index 6203eed860ddc1c31fd2ba0ed10d4151a7e843b5..7573257731b6d7e865f97f50b2f41adbf860dec5 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010 Atheros Communications Inc.
+ * Copyright (c) 2010-2011 Atheros Communications 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
index 7a332f16b79af9b83ad7764b45577342e64384e0..077e8a6983fab5637fb8bdc9a949f38a018d7d09 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008-2009 Atheros Communications Inc.
+ * Copyright (c) 2008-2011 Atheros Communications 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
index a57e963cf0dc19dd6b7ad51180657f63c65b6b9d..2fe0a34cbabcba3750446f5b33e57d80878c5fbf 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008-2010 Atheros Communications Inc.
+ * Copyright (c) 2008-2011 Atheros Communications 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
index 47780ef1c892e56317d48e4fdc500bf34fc7c17f..453af6dc514b5f700a16a615d1f2ea3104191026 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008-2010 Atheros Communications Inc.
+ * Copyright (c) 2008-2011 Atheros Communications 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
index f915a3dbfcad106737b4fc803c814a6ae63e067f..e8ac70da5ac70d2ec0fc585c556017ce51b6b90e 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010 Atheros Communications Inc.
+ * Copyright (c) 2010-2011 Atheros Communications 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
index f276cb922b4d5d96bf16703bd67b75ac40aecb55..f48051c50092f0d85a5babf97160621862c24b36 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010 Atheros Communications Inc.
+ * Copyright (c) 2010-2011 Atheros Communications 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
index 1e220354e4be2593c4f7869a636e3af0fd763ef3..729534c82e44bf7a21122435aefc91f4e088f9b4 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010 Atheros Communications Inc.
+ * Copyright (c) 2010-2011 Atheros Communications 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
index afb0b5ee1865c3c10481b5d6a8fac4c932f97af2..ab21a49159811c8ccaa587aef294e37dd95e84cd 100644 (file)
@@ -1,3 +1,19 @@
+/*
+ * Copyright (c) 2010-2011 Atheros Communications 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.
+ */
+
 #ifndef AR9003_EEPROM_H
 #define AR9003_EEPROM_H
 
index a55eddbb258923aaf85a35966fb35a3974fa15f0..392bf0f8ff1687678ff01816a0177a99c303e4c5 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008-2010 Atheros Communications Inc.
+ * Copyright (c) 2008-2011 Atheros Communications 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
index be6adec33ddbb0d9c9d655f8b1ca4b5a3f6fc852..10d71f7d3fc22b7ed71bb8f5ad7f9097d910e82e 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010 Atheros Communications Inc.
+ * Copyright (c) 2010-2011 Atheros Communications 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
index 45cc7e80436c067430e140dd5dfb36b671afe62f..c50449387bf163144a0ad8491296ca87cc08dfc8 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010 Atheros Communications Inc.
+ * Copyright (c) 2010-2011 Atheros Communications 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
index 356d2fd78822279245b0d4a2669a5d6aa6dd731d..e4d6a87ec53830bf70126f29090a2349dea5cfef 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010 Atheros Communications Inc.
+ * Copyright (c) 2010-2011 Atheros Communications 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
index 25f3c2fdf2bcf15010d550cfb167294acc45781f..eee23ecd118a292f35e959018414d6a548ed74d4 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010 Atheros Communications Inc.
+ * Copyright (c) 2010-2011 Atheros Communications 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
index c7505b48e5c0b3ede5ff22de98f0f2edd1afc7b5..443090d278e33234e432085fdb97657ce974afd9 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2002-2010 Atheros Communications, Inc.
+ * Copyright (c) 2010-2011 Atheros Communications, 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
index fbdde29f0ab8d4e9349d3320e923eeef262d4432..611ea6ce8508dfb760a1172ea46793e6716c48e3 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010 Atheros Communications Inc.
+ * Copyright (c) 2010-2011 Atheros Communications 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
index 03b37d7be1c3bac7cb5276d71fb55019869ac6fe..f75068b4b310e2383c2b30e79a2e88c59c0a0622 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008-2009 Atheros Communications Inc.
+ * Copyright (c) 2008-2011 Atheros Communications 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
@@ -397,6 +397,9 @@ struct ath_beacon {
        struct ath_descdma bdma;
        struct ath_txq *cabq;
        struct list_head bbuf;
+
+       bool tx_processed;
+       bool tx_last;
 };
 
 void ath_beacon_tasklet(unsigned long data);
index 637dbc5f7b67478e975e81a33a33ab5785fc5d84..d4d8ceced89b754c1babef1ba41d11cfe456efcc 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008-2009 Atheros Communications Inc.
+ * Copyright (c) 2008-2011 Atheros Communications 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
 
 #define FUDGE 2
 
+static void ath9k_reset_beacon_status(struct ath_softc *sc)
+{
+       sc->beacon.tx_processed = false;
+       sc->beacon.tx_last = false;
+}
+
 /*
  *  This function will modify certain transmit queue properties depending on
  *  the operating mode of the station (AP or AdHoc).  Parameters are AIFS
@@ -72,6 +78,8 @@ static void ath_beacon_setup(struct ath_softc *sc, struct ath_vif *avp,
        struct ieee80211_supported_band *sband;
        u8 rate = 0;
 
+       ath9k_reset_beacon_status(sc);
+
        ds = bf->bf_desc;
        flags = ATH9K_TXDESC_NOACK;
 
@@ -134,6 +142,8 @@ static struct ath_buf *ath_beacon_generate(struct ieee80211_hw *hw,
        struct ieee80211_tx_info *info;
        int cabq_depth;
 
+       ath9k_reset_beacon_status(sc);
+
        avp = (void *)vif->drv_priv;
        cabq = sc->beacon.cabq;
 
@@ -351,9 +361,7 @@ void ath_beacon_tasklet(unsigned long data)
        struct ath_buf *bf = NULL;
        struct ieee80211_vif *vif;
        int slot;
-       u32 bfaddr, bc = 0, tsftu;
-       u64 tsf;
-       u16 intval;
+       u32 bfaddr, bc = 0;
 
        /*
         * Check if the previous beacon has gone out.  If
@@ -388,17 +396,27 @@ void ath_beacon_tasklet(unsigned long data)
         * on the tsf to safeguard against missing an swba.
         */
 
-       intval = cur_conf->beacon_interval ? : ATH_DEFAULT_BINTVAL;
 
-       tsf = ath9k_hw_gettsf64(ah);
-       tsf += TU_TO_USEC(ah->config.sw_beacon_response_time);
-       tsftu = TSF_TO_TU((tsf * ATH_BCBUF) >>32, tsf * ATH_BCBUF);
-       slot = (tsftu % (intval * ATH_BCBUF)) / intval;
-       vif = sc->beacon.bslot[slot];
+       if (ah->opmode == NL80211_IFTYPE_AP) {
+               u16 intval;
+               u32 tsftu;
+               u64 tsf;
+
+               intval = cur_conf->beacon_interval ? : ATH_DEFAULT_BINTVAL;
+               tsf = ath9k_hw_gettsf64(ah);
+               tsf += TU_TO_USEC(ah->config.sw_beacon_response_time);
+               tsftu = TSF_TO_TU((tsf * ATH_BCBUF) >>32, tsf * ATH_BCBUF);
+               slot = (tsftu % (intval * ATH_BCBUF)) / intval;
+               vif = sc->beacon.bslot[slot];
+
+               ath_dbg(common, ATH_DBG_BEACON,
+                       "slot %d [tsf %llu tsftu %u intval %u] vif %p\n",
+                       slot, tsf, tsftu / ATH_BCBUF, intval, vif);
+       } else {
+               slot = 0;
+               vif = sc->beacon.bslot[slot];
+       }
 
-       ath_dbg(common, ATH_DBG_BEACON,
-               "slot %d [tsf %llu tsftu %u intval %u] vif %p\n",
-               slot, tsf, tsftu / ATH_BCBUF, intval, vif);
 
        bfaddr = 0;
        if (vif) {
@@ -636,6 +654,8 @@ static void ath_beacon_config_adhoc(struct ath_softc *sc,
        struct ath_common *common = ath9k_hw_common(ah);
        u32 tsf, delta, intval, nexttbtt;
 
+       ath9k_reset_beacon_status(sc);
+
        tsf = ath9k_hw_gettsf32(ah) + TU_TO_USEC(FUDGE);
        intval = TU_TO_USEC(conf->beacon_interval & ATH9K_BEACON_PERIOD);
 
@@ -646,7 +666,7 @@ static void ath_beacon_config_adhoc(struct ath_softc *sc,
                        delta = (tsf - sc->beacon.bc_tstamp);
                else
                        delta = (tsf + 1 + (~0U - sc->beacon.bc_tstamp));
-               nexttbtt = tsf + roundup(delta, intval);
+               nexttbtt = tsf + intval - (delta % intval);
        }
 
        ath_dbg(common, ATH_DBG_BEACON,
index 23f15a7ca7f128a364ddc32d4ed5cee3fa66834d..41ce0b1398868eeab8c954af9b493913d05c5772 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2009 Atheros Communications Inc.
+ * Copyright (c) 2009-2011 Atheros Communications 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
index a9efca83d676dc08de3ca884004a886e5ec9824b..234f77689b144715d51372d6da5e1f038b37e78a 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2009 Atheros Communications Inc.
+ * Copyright (c) 2009-2011 Atheros Communications 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
index 558b228a717fe06c35ac66a4e78962a23be97473..a1250c586e40884989a853845e1c68230434f6c2 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008-2009 Atheros Communications Inc.
+ * Copyright (c) 2008-2011 Atheros Communications 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
index 4420780fa3b86d2a7fbbfb173e0f2fefc7026e05..1bef41d1b1ffb250d38f490a395d6c79e033b019 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008-2009 Atheros Communications Inc.
+ * Copyright (c) 2008-2011 Atheros Communications 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
index 74535e6dfb82a024538caf059c6545f701ba3606..fa6bd2d189e573516e2ab7cac919ab3109dbe52f 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2009 Atheros Communications Inc.
+ * Copyright (c) 2009-2011 Atheros Communications 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
index 5124f1420b3ae404cbcc80dfdf7732c3c0a06d91..77ec288b5a70557efc233e53c03b31b95d822bb4 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2009 Atheros Communications Inc.
+ * Copyright (c) 2009-2011 Atheros Communications 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
index bad1a87249b6011898027cce7300cea8358dbc49..d55ffd7d4bd28565df7d93b5e1ed65c010b99ba5 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008-2009 Atheros Communications Inc.
+ * Copyright (c) 2008-2011 Atheros Communications 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
@@ -435,6 +435,7 @@ static ssize_t read_file_wiphy(struct file *file, char __user *user_buf,
                        conf->channel_type,
                        channel_type_str(conf->channel_type));
 
+       ath9k_ps_wakeup(sc);
        put_unaligned_le32(REG_READ_D(sc->sc_ah, AR_STA_ID0), addr);
        put_unaligned_le16(REG_READ_D(sc->sc_ah, AR_STA_ID1) & 0xffff, addr + 4);
        len += snprintf(buf + len, sizeof(buf) - len,
@@ -444,6 +445,7 @@ static ssize_t read_file_wiphy(struct file *file, char __user *user_buf,
        len += snprintf(buf + len, sizeof(buf) - len,
                        "addrmask: %pM\n", addr);
        tmp = ath9k_hw_getrxfilter(sc->sc_ah);
+       ath9k_ps_restore(sc);
        len += snprintf(buf + len, sizeof(buf) - len,
                        "rfilt: 0x%x", tmp);
        if (tmp & ATH9K_RX_FILTER_UCAST)
@@ -725,6 +727,7 @@ static ssize_t read_file_misc(struct file *file, char __user *user_buf,
                break;
        }
 
+       ath9k_ps_wakeup(sc);
        len += snprintf(buf + len, size - len,
                        "curbssid: %pM\n"
                        "OP-Mode: %s(%i)\n"
@@ -734,6 +737,7 @@ static ssize_t read_file_misc(struct file *file, char __user *user_buf,
                        REG_READ(ah, AR_BEACON_PERIOD));
 
        reg = REG_READ(ah, AR_TIMER_MODE);
+       ath9k_ps_restore(sc);
        len += snprintf(buf + len, size - len, "Timer-Mode-Register: 0x%x (",
                        reg);
        if (reg & AR_TBTT_TIMER_EN)
@@ -1050,7 +1054,9 @@ static ssize_t read_file_regval(struct file *file, char __user *user_buf,
        unsigned int len;
        u32 regval;
 
+       ath9k_ps_wakeup(sc);
        regval = REG_READ_D(ah, sc->debug.regidx);
+       ath9k_ps_restore(sc);
        len = sprintf(buf, "0x%08x\n", regval);
        return simple_read_from_buffer(user_buf, count, ppos, buf, len);
 }
@@ -1072,7 +1078,9 @@ static ssize_t write_file_regval(struct file *file, const char __user *user_buf,
        if (strict_strtoul(buf, 0, &regval))
                return -EINVAL;
 
+       ath9k_ps_wakeup(sc);
        REG_WRITE_D(ah, sc->debug.regidx, regval);
+       ath9k_ps_restore(sc);
        return count;
 }
 
index 5488a324cc100b142ed1871a9ce493f18b893543..8ce6ad80f4e208461469ecbb7b90172ae460a044 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008-2009 Atheros Communications Inc.
+ * Copyright (c) 2008-2011 Atheros Communications 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
index 8c18bed3a55890e3fbc9195bc37802aaab2a9015..e61404dda8c59b36be9766dada75b3c16ae3560e 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008-2009 Atheros Communications Inc.
+ * Copyright (c) 2008-2011 Atheros Communications 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
index 3e316133f114c9b6765b9002d168e157fbccdaba..de99c0da52e4e33c412086f346673d1d49211015 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008-2009 Atheros Communications Inc.
+ * Copyright (c) 2008-2011 Atheros Communications 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
index 6f714dd723653032c0622b8821852749b4254f38..5b1e894f3d679aa7d43fe52707d731e7aaec6032 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008-2009 Atheros Communications Inc.
+ * Copyright (c) 2008-2011 Atheros Communications 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
index b87db4763098bad950f78824102d2626b598aa38..7856f0d4512d6292a1a70ef3f4f98360666f1847 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008-2009 Atheros Communications Inc.
+ * Copyright (c) 2008-2011 Atheros Communications 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
index c031854b569fe0a5c3c145724ec3373c802b68e2..17f0a6806207bca7936c4bd6fdbe8271d04e54f3 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008-2009 Atheros Communications Inc.
+ * Copyright (c) 2008-2011 Atheros Communications 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
index 0349b3a1cc58c8dcb29729f0237f9d4137e8de46..bc713fc28191b2baf4e1992365902cfbce25fd07 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008-2009 Atheros Communications Inc.
+ * Copyright (c) 2008-2011 Atheros Communications 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
index 2e3a33a53406a85d08c4266d90e33462a1a8208b..260f1f37a60e486446394f71043c9ce5c0255dec 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010 Atheros Communications Inc.
+ * Copyright (c) 2010-2011 Atheros Communications 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
index 2bdcdbc14b1ea899c687170522e6c3ced11475e2..794f63094e5d66db28189cc248e106474358497e 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010 Atheros Communications Inc.
+ * Copyright (c) 2010-2011 Atheros Communications 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
@@ -18,7 +18,7 @@
 #define HTC_USB_H
 
 #define MAJOR_VERSION_REQ 1
-#define MINOR_VERSION_REQ 2
+#define MINOR_VERSION_REQ 3
 
 #define IS_AR7010_DEVICE(_v) (((_v) == AR9280_USB) || ((_v) == AR9287_USB))
 
index dfc7a982fc7eb265e263e524926603ba631574fc..5bc022087e651e8be0a8097ca17af1257c1b4f45 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010 Atheros Communications Inc.
+ * Copyright (c) 2010-2011 Atheros Communications 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
@@ -46,15 +46,8 @@ extern struct ieee80211_ops ath9k_htc_ops;
 extern int htc_modparam_nohwcrypt;
 
 enum htc_phymode {
-       HTC_MODE_AUTO           = 0,
-       HTC_MODE_11A            = 1,
-       HTC_MODE_11B            = 2,
-       HTC_MODE_11G            = 3,
-       HTC_MODE_FH             = 4,
-       HTC_MODE_TURBO_A        = 5,
-       HTC_MODE_TURBO_G        = 6,
-       HTC_MODE_11NA           = 7,
-       HTC_MODE_11NG           = 8
+       HTC_MODE_11NA           = 0,
+       HTC_MODE_11NG           = 1
 };
 
 enum htc_opmode {
@@ -123,18 +116,13 @@ struct ath9k_htc_target_vif {
        u8 pad;
 } __packed;
 
-#define ATH_HTC_STA_AUTH  0x0001
-#define ATH_HTC_STA_QOS   0x0002
-#define ATH_HTC_STA_ERP   0x0004
-#define ATH_HTC_STA_HT    0x0008
-
 struct ath9k_htc_target_sta {
        u8 macaddr[ETH_ALEN];
        u8 bssid[ETH_ALEN];
        u8 sta_index;
        u8 vif_index;
        u8 is_vif_sta;
-       __be16 flags; /* ATH_HTC_STA_* */
+       __be16 flags;
        __be16 htcap;
        __be16 maxampdu;
        u8 pad;
@@ -285,9 +273,9 @@ struct ath9k_htc_rx {
 };
 
 #define ATH9K_HTC_TX_CLEANUP_INTERVAL 50 /* ms */
-#define ATH9K_HTC_TX_TIMEOUT_INTERVAL 2500 /* ms */
+#define ATH9K_HTC_TX_TIMEOUT_INTERVAL 3000 /* ms */
 #define ATH9K_HTC_TX_RESERVE 10
-#define ATH9K_HTC_TX_TIMEOUT_COUNT 20
+#define ATH9K_HTC_TX_TIMEOUT_COUNT 40
 #define ATH9K_HTC_TX_THRESHOLD (MAX_TX_BUF_NUM - ATH9K_HTC_TX_RESERVE)
 
 #define ATH9K_HTC_OP_TX_QUEUES_STOP BIT(0)
@@ -450,6 +438,7 @@ struct ath9k_htc_priv {
        u8 vif_sta_pos[ATH9K_HTC_MAX_VIF];
        u8 num_ibss_vif;
        u8 num_sta_vif;
+       u8 num_sta_assoc_vif;
        u8 num_ap_vif;
 
        u16 op_flags;
index 0ded2c66d5ffdd13fe38607794cf65b291d90f32..aa6a73118706753d6d70ac608f8473f7c218c780 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010 Atheros Communications Inc.
+ * Copyright (c) 2010-2011 Atheros Communications 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
index af57fe5aab98848f52bcd129184181a84c773033..db2352e5cc0d5e660d005ac09204e7c0cc46e8c3 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010 Atheros Communications Inc.
+ * Copyright (c) 2010-2011 Atheros Communications 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
index bfdc8a8871830b5ccb63aa848d69d8121d3745b0..61e6d39507182feda2bc6d02351803f7c5a51e2a 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010 Atheros Communications Inc.
+ * Copyright (c) 2010-2011 Atheros Communications 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
@@ -258,7 +258,7 @@ static int ath9k_init_htc_services(struct ath9k_htc_priv *priv, u16 devid,
         */
 
        if (IS_AR7010_DEVICE(drv_info))
-               priv->htc->credits = 48;
+               priv->htc->credits = 45;
        else
                priv->htc->credits = 33;
 
@@ -769,11 +769,6 @@ static void ath9k_set_hw_capab(struct ath9k_htc_priv *priv,
        hw->channel_change_time = 5000;
        hw->max_listen_interval = 10;
 
-       if (AR_SREV_9271(priv->ah))
-               hw->max_tx_aggregation_subframes = MAX_TX_AMPDU_SUBFRAMES_9271;
-       else
-               hw->max_tx_aggregation_subframes = MAX_TX_AMPDU_SUBFRAMES_7010;
-
        hw->vif_data_size = sizeof(struct ath9k_htc_vif);
        hw->sta_data_size = sizeof(struct ath9k_htc_sta);
 
index 5aa104fe7eebf26e44d60eee2efcfc21d5129ed0..7b779689543223cb7c110b64cd9e1fc819a25bf6 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010 Atheros Communications Inc.
+ * Copyright (c) 2010-2011 Atheros Communications 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
@@ -26,7 +26,7 @@ static enum htc_phymode ath9k_htc_get_curmode(struct ath9k_htc_priv *priv,
 {
        enum htc_phymode mode;
 
-       mode = HTC_MODE_AUTO;
+       mode = -EINVAL;
 
        switch (ichan->chanmode) {
        case CHANNEL_G:
@@ -45,6 +45,8 @@ static enum htc_phymode ath9k_htc_get_curmode(struct ath9k_htc_priv *priv,
                break;
        }
 
+       WARN_ON(mode < 0);
+
        return mode;
 }
 
@@ -500,9 +502,6 @@ static int ath9k_htc_add_station(struct ath9k_htc_priv *priv,
                tsta.maxampdu = cpu_to_be16(maxampdu);
        }
 
-       if (sta && sta->ht_cap.ht_supported)
-               tsta.flags = cpu_to_be16(ATH_HTC_STA_HT);
-
        WMI_CMD_BUF(WMI_NODE_CREATE_CMDID, &tsta);
        if (ret) {
                if (sta)
@@ -582,7 +581,7 @@ int ath9k_htc_update_cap_target(struct ath9k_htc_priv *priv,
        memset(&tcap, 0, sizeof(struct ath9k_htc_cap_target));
 
        tcap.ampdu_limit = cpu_to_be32(0xffff);
-       tcap.ampdu_subframes = priv->hw->max_tx_aggregation_subframes;
+       tcap.ampdu_subframes = 0xff;
        tcap.enable_coex = enable_coex;
        tcap.tx_chainmask = priv->ah->caps.tx_chainmask;
 
@@ -1165,6 +1164,8 @@ static void ath9k_htc_remove_interface(struct ieee80211_hw *hw,
 
        ath9k_htc_set_opmode(priv);
 
+       ath9k_htc_set_bssid_mask(priv, vif);
+
        /*
         * Stop ANI only if there are no associated station interfaces.
         */
@@ -1435,6 +1436,37 @@ static int ath9k_htc_set_key(struct ieee80211_hw *hw,
        return ret;
 }
 
+static void ath9k_htc_set_bssid(struct ath9k_htc_priv *priv)
+{
+       struct ath_common *common = ath9k_hw_common(priv->ah);
+
+       ath9k_hw_write_associd(priv->ah);
+       ath_dbg(common, ATH_DBG_CONFIG,
+               "BSSID: %pM aid: 0x%x\n",
+               common->curbssid, common->curaid);
+}
+
+static void ath9k_htc_bss_iter(void *data, u8 *mac, struct ieee80211_vif *vif)
+{
+       struct ath9k_htc_priv *priv = (struct ath9k_htc_priv *)data;
+       struct ath_common *common = ath9k_hw_common(priv->ah);
+       struct ieee80211_bss_conf *bss_conf = &vif->bss_conf;
+
+       if ((vif->type == NL80211_IFTYPE_STATION) && bss_conf->assoc) {
+               common->curaid = bss_conf->aid;
+               memcpy(common->curbssid, bss_conf->bssid, ETH_ALEN);
+       }
+}
+
+static void ath9k_htc_choose_set_bssid(struct ath9k_htc_priv *priv)
+{
+       if (priv->num_sta_assoc_vif == 1) {
+               ieee80211_iterate_active_interfaces_atomic(priv->hw,
+                                                          ath9k_htc_bss_iter, priv);
+               ath9k_htc_set_bssid(priv);
+       }
+}
+
 static void ath9k_htc_bss_info_changed(struct ieee80211_hw *hw,
                                       struct ieee80211_vif *vif,
                                       struct ieee80211_bss_conf *bss_conf,
@@ -1443,43 +1475,32 @@ static void ath9k_htc_bss_info_changed(struct ieee80211_hw *hw,
        struct ath9k_htc_priv *priv = hw->priv;
        struct ath_hw *ah = priv->ah;
        struct ath_common *common = ath9k_hw_common(ah);
-       bool set_assoc;
 
        mutex_lock(&priv->mutex);
        ath9k_htc_ps_wakeup(priv);
 
-       /*
-        * Set the HW AID/BSSID only for the first station interface
-        * or in IBSS mode.
-        */
-       set_assoc = !!((priv->ah->opmode == NL80211_IFTYPE_ADHOC) ||
-                      ((priv->ah->opmode == NL80211_IFTYPE_STATION) &&
-                       (priv->num_sta_vif == 1)));
-
-
        if (changed & BSS_CHANGED_ASSOC) {
-               if (set_assoc) {
-                       ath_dbg(common, ATH_DBG_CONFIG, "BSS Changed ASSOC %d\n",
-                               bss_conf->assoc);
+               ath_dbg(common, ATH_DBG_CONFIG, "BSS Changed ASSOC %d\n",
+                       bss_conf->assoc);
 
-                       common->curaid = bss_conf->assoc ?
-                               bss_conf->aid : 0;
+               bss_conf->assoc ?
+                       priv->num_sta_assoc_vif++ : priv->num_sta_assoc_vif--;
 
-                       if (bss_conf->assoc)
+               if (priv->ah->opmode == NL80211_IFTYPE_STATION) {
+                       if (bss_conf->assoc && (priv->num_sta_assoc_vif == 1))
                                ath9k_htc_start_ani(priv);
-                       else
+                       else if (priv->num_sta_assoc_vif == 0)
                                ath9k_htc_stop_ani(priv);
                }
        }
 
        if (changed & BSS_CHANGED_BSSID) {
-               if (set_assoc) {
+               if (priv->ah->opmode == NL80211_IFTYPE_ADHOC) {
+                       common->curaid = bss_conf->aid;
                        memcpy(common->curbssid, bss_conf->bssid, ETH_ALEN);
-                       ath9k_hw_write_associd(ah);
-
-                       ath_dbg(common, ATH_DBG_CONFIG,
-                               "BSSID: %pM aid: 0x%x\n",
-                               common->curbssid, common->curaid);
+                       ath9k_htc_set_bssid(priv);
+               } else if (priv->ah->opmode == NL80211_IFTYPE_STATION) {
+                       ath9k_htc_choose_set_bssid(priv);
                }
        }
 
index a898dac22337e559cf46b7f53d2743f2a1341904..2d81c700e201cd4fa3b87cb1414a0b820785c7fc 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010 Atheros Communications Inc.
+ * Copyright (c) 2010-2011 Atheros Communications 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
@@ -875,6 +875,7 @@ u32 ath9k_htc_calcrxfilter(struct ath9k_htc_priv *priv)
                rfilt |= ATH9K_RX_FILTER_CONTROL;
 
        if ((ah->opmode == NL80211_IFTYPE_STATION) &&
+           (priv->nvifs <= 1) &&
            !(priv->rxfilter & FIF_BCN_PRBRESP_PROMISC))
                rfilt |= ATH9K_RX_FILTER_MYBEACON;
        else
@@ -888,6 +889,9 @@ u32 ath9k_htc_calcrxfilter(struct ath9k_htc_priv *priv)
        if (priv->rxfilter & FIF_PSPOLL)
                rfilt |= ATH9K_RX_FILTER_PSPOLL;
 
+       if (priv->nvifs > 1)
+               rfilt |= ATH9K_RX_FILTER_MCAST_BCAST_ALL;
+
        return rfilt;
 
 #undef RX_FILTER_PRESERVE
index cee970fdf65256c5124d358b674b977d9201c9b5..1b90ed8795c345a087d59a88a4715a873c3ebf90 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010 Atheros Communications Inc.
+ * Copyright (c) 2010-2011 Atheros Communications 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
index 91a5305db95a317eced836e417c9e601de8abdf8..e1ffbb6bd636049686b3181705b236862004d29f 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010 Atheros Communications Inc.
+ * Copyright (c) 2010-2011 Atheros Communications 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
index 8b8f0445aef817fc2395bdb5c33a90847cc3e415..2f3e07263fcbaae598b5be8b6c77760e3c566358 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010 Atheros Communications Inc.
+ * Copyright (c) 2010-2011 Atheros Communications 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
index b75b5dca4e2905dfc020846d1939a01ff47f3d57..72543ce8f616a23b84d2949117ea65d1bd29982c 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008-2010 Atheros Communications Inc.
+ * Copyright (c) 2008-2011 Atheros Communications 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
index 7af2773d2bfc38766ec77480aace1f205cb045d2..57435ce627928adaada552ce1aa5636f140ea8cd 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008-2010 Atheros Communications Inc.
+ * Copyright (c) 2008-2011 Atheros Communications 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
index b172d1509515e97881eb9a14945df7cb1830a207..45c585a337e9885b336f1ae50731170f6f63344c 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008-2009 Atheros Communications Inc.
+ * Copyright (c) 2008-2011 Atheros Communications 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
index bd6d2b9d736fbb7b2649bdc3311971f5c9f1a8e0..c2091f1f409616cf6a3d131a19b2f3c2dd341980 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008-2009 Atheros Communications Inc.
+ * Copyright (c) 2008-2011 Atheros Communications 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
index b60c130917f7e959a356381757c852934c2ada17..8e848c4d16baf536834231633795e3c1c9382abe 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008-2009 Atheros Communications Inc.
+ * Copyright (c) 2008-2011 Atheros Communications 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
index 17ebdf1e8b7bc567c20644eb150eec9058012a72..a198ee374b050b6d331107510be54b0618904ccd 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008-2009 Atheros Communications Inc.
+ * Copyright (c) 2008-2011 Atheros Communications 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
@@ -2332,6 +2332,45 @@ static bool ath9k_tx_frames_pending(struct ieee80211_hw *hw)
        return false;
 }
 
+int ath9k_tx_last_beacon(struct ieee80211_hw *hw)
+{
+       struct ath_softc *sc = hw->priv;
+       struct ath_hw *ah = sc->sc_ah;
+       struct ieee80211_vif *vif;
+       struct ath_vif *avp;
+       struct ath_buf *bf;
+       struct ath_tx_status ts;
+       int status;
+
+       vif = sc->beacon.bslot[0];
+       if (!vif)
+               return 0;
+
+       avp = (void *)vif->drv_priv;
+       if (!avp->is_bslot_active)
+               return 0;
+
+       if (!sc->beacon.tx_processed) {
+               tasklet_disable(&sc->bcon_tasklet);
+
+               bf = avp->av_bcbuf;
+               if (!bf || !bf->bf_mpdu)
+                       goto skip;
+
+               status = ath9k_hw_txprocdesc(ah, bf->bf_desc, &ts);
+               if (status == -EINPROGRESS)
+                       goto skip;
+
+               sc->beacon.tx_processed = true;
+               sc->beacon.tx_last = !(ts.ts_status & ATH9K_TXERR_MASK);
+
+skip:
+               tasklet_enable(&sc->bcon_tasklet);
+       }
+
+       return sc->beacon.tx_last;
+}
+
 struct ieee80211_ops ath9k_ops = {
        .tx                 = ath9k_tx,
        .start              = ath9k_start,
@@ -2356,4 +2395,5 @@ struct ieee80211_ops ath9k_ops = {
        .set_coverage_class = ath9k_set_coverage_class,
        .flush              = ath9k_flush,
        .tx_frames_pending  = ath9k_tx_frames_pending,
+       .tx_last_beacon = ath9k_tx_last_beacon,
 };
index 9c65459be100585e243bb3a3e65c23dab0c6d556..b8cbfc7072137064f443ad0f137b9ccba99c85f4 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008-2009 Atheros Communications Inc.
+ * Copyright (c) 2008-2011 Atheros Communications 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
index 9441bf8ca2fd6cf003331d04898e96551a184d6f..8b380305b0fc1acf8c2593acd474daa52f7eb6c9 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008-2009 Atheros Communications Inc.
+ * Copyright (c) 2008-2011 Atheros Communications 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
index 4ccbf2ddb5535c27c0699418f723b9314c5e7191..17542214c93f65bfb1727547258f20e11c8440be 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * Copyright (c) 2004 Video54 Technologies, Inc.
- * Copyright (c) 2004-2009 Atheros Communications, Inc.
+ * Copyright (c) 2004-2011 Atheros Communications, 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
index 5d984b8acdb12540fc531a74186d6b7021f2759c..c3d850207bee0375c9f806cc37fea898e1985bd1 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * Copyright (c) 2004 Sam Leffler, Errno Consulting
  * Copyright (c) 2004 Video54 Technologies, Inc.
- * Copyright (c) 2008-2009 Atheros Communications Inc.
+ * Copyright (c) 2008-2011 Atheros Communications 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
index 4f52e0429f996718ad1630a597541f803f256079..07e35e59c9e31fa8d9dbb1c6b086c4027e13e2c6 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008-2009 Atheros Communications Inc.
+ * Copyright (c) 2008-2011 Atheros Communications 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
index 456f3ec20fef94235ccb724c66419b6a7012d260..c18ee9921fb19ef9000122c21d1da887c5731094 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008-2009 Atheros Communications Inc.
+ * Copyright (c) 2008-2011 Atheros Communications 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
index f9b1eb4853c4a93a1f964e239a41349e5e7fa0cf..35422fc1f2ce1a566ce11cb0a0d740880531badd 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010 Atheros Communications Inc.
+ * Copyright (c) 2010-2011 Atheros Communications 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
index 6095eeb6e025fdd08f971da826e0a5680b3a2f98..fde6da619f30f96e146c00b017e5f37a9df0e80d 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010 Atheros Communications Inc.
+ * Copyright (c) 2010-2011 Atheros Communications 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
index 97dd1fac98b6390591a3baa89f0943e9e50eb92c..3779b8977d4709a9ce68d85a8b2458d472deaea4 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008-2009 Atheros Communications Inc.
+ * Copyright (c) 2008-2011 Atheros Communications 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
index bb578690935e7f88327bcedf94231219d27cc973..4da01a9f5680feef4726f9a9fbff56914b396045 100644 (file)
@@ -286,6 +286,10 @@ struct ar9170 {
                unsigned int tx_seq_table;
        } fw;
 
+       /* interface configuration combinations */
+       struct ieee80211_iface_limit if_comb_limits[1];
+       struct ieee80211_iface_combination if_combs[1];
+
        /* reset / stuck frames/queue detection */
        struct work_struct restart_work;
        struct work_struct ping_work;
index 9517ede9e2dfdbb104042c3f520e9cb36a18c778..221957c5d37370830eef6c74ae3aacddcbb62f89 100644 (file)
@@ -151,6 +151,7 @@ static int carl9170_fw(struct ar9170 *ar, const __u8 *data, size_t len)
        const struct carl9170fw_chk_desc *chk_desc;
        const struct carl9170fw_last_desc *last_desc;
        const struct carl9170fw_txsq_desc *txsq_desc;
+       u16 if_comb_types;
 
        last_desc = carl9170_fw_find_desc(ar, LAST_MAGIC,
                sizeof(*last_desc), CARL9170FW_LAST_DESC_CUR_VER);
@@ -268,6 +269,9 @@ static int carl9170_fw(struct ar9170 *ar, const __u8 *data, size_t len)
        if (SUPP(CARL9170FW_WOL))
                device_set_wakeup_enable(&ar->udev->dev, true);
 
+       if_comb_types = BIT(NL80211_IFTYPE_STATION) |
+                       BIT(NL80211_IFTYPE_P2P_CLIENT);
+
        ar->fw.vif_num = otus_desc->vif_num;
        ar->fw.cmd_bufs = otus_desc->cmd_bufs;
        ar->fw.address = le32_to_cpu(otus_desc->fw_address);
@@ -294,12 +298,25 @@ static int carl9170_fw(struct ar9170 *ar, const __u8 *data, size_t len)
                ar->hw->wiphy->interface_modes |= BIT(NL80211_IFTYPE_ADHOC);
 
                if (SUPP(CARL9170FW_WLANTX_CAB)) {
-                       ar->hw->wiphy->interface_modes |=
+                       if_comb_types |=
                                BIT(NL80211_IFTYPE_AP) |
                                BIT(NL80211_IFTYPE_P2P_GO);
                }
        }
 
+       ar->if_comb_limits[0].max = ar->fw.vif_num;
+       ar->if_comb_limits[0].types = if_comb_types;
+
+       ar->if_combs[0].num_different_channels = 1;
+       ar->if_combs[0].max_interfaces = ar->fw.vif_num;
+       ar->if_combs[0].limits = ar->if_comb_limits;
+       ar->if_combs[0].n_limits = ARRAY_SIZE(ar->if_comb_limits);
+
+       ar->hw->wiphy->iface_combinations = ar->if_combs;
+       ar->hw->wiphy->n_iface_combinations = ARRAY_SIZE(ar->if_combs);
+
+       ar->hw->wiphy->interface_modes |= if_comb_types;
+
        txsq_desc = carl9170_fw_find_desc(ar, TXSQ_MAGIC,
                sizeof(*txsq_desc), CARL9170FW_TXSQ_DESC_CUR_VER);
 
index 7d5c65ea94e6213723ecb7a98f8222d6fa727daf..54d093c2ab44f956b5988d73ae819ed9b398a58b 100644 (file)
@@ -1570,14 +1570,8 @@ void *carl9170_alloc(size_t priv_size)
        INIT_LIST_HEAD(&ar->vif_list);
        init_completion(&ar->tx_flush);
 
-       /*
-        * Note:
-        * IBSS/ADHOC and AP mode are only enabled, if the firmware
-        * supports these modes. The code which will add the
-        * additional interface_modes is in fw.c.
-        */
-       hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) |
-                                    BIT(NL80211_IFTYPE_P2P_CLIENT);
+       /* firmware decides which modes we support */
+       hw->wiphy->interface_modes = 0;
 
        hw->flags |= IEEE80211_HW_RX_INCLUDES_FCS |
                     IEEE80211_HW_REPORTS_TX_ACK_STATUS |
index cc11d66f15bcc69fd02110ae5eb87b02f5f3948d..3f508e59f146b412246f34becab5862117bfd765 100644 (file)
@@ -43,7 +43,7 @@
  * set of  ~ ( MAC XOR BSSID ) for all bssids we handle.
  *
  * When you do this you are essentially computing the common bits of all your
- * BSSes. Later it is assumed the harware will "and" (&) the BSSID mask with
+ * BSSes. Later it is assumed the hardware will "and" (&) the BSSID mask with
  * the MAC address to obtain the relevant bits and compare the result with
  * (frame's BSSID & mask) to see if they match.
  *
@@ -71,8 +71,8 @@
  *             On loop iteration for BSSID-02:
  *             bssid_mask &= ~(0001   ^   1001)
  *             bssid_mask =   (1010)  & ~(0001 ^ 1001)
- *             bssid_mask =   (1010)  & ~(1001)
- *             bssid_mask =   (1010)  &  (0110)
+ *             bssid_mask =   (1010)  & ~(1000)
+ *             bssid_mask =   (1010)  &  (0111)
  *             bssid_mask =   0010
  *
  * A bssid_mask of 0010 means "only pay attention to the second least
  *
  * IFRAME-02:  0001 (we should allow)
  *
- *     allow = (0001 & 1010) == 1010
- *
  *     allow = (IFRAME-02 & bssid_mask) == (bssid_mask & MAC) ? 1 : 0;
  *  --> allow = (0001 & 0010) ==  (0010 & 0001) ? 1 :0;
- *  --> allow = (0010) == (0010)
+ *  --> allow = (0000) == (0000)
  *  --> allow = 1
  *
  * Other examples:
index 229f4388f790895108cd5ba592657fdcf3780a1f..ee4d06f13e2356a095b8a07d433432214dbac984 100644 (file)
@@ -567,6 +567,8 @@ struct b43_dma {
        struct b43_dmaring *tx_ring_mcast; /* Multicast */
 
        struct b43_dmaring *rx_ring;
+
+       u32 translation; /* Routing bits */
 };
 
 struct b43_pio_txqueue;
@@ -705,7 +707,7 @@ enum {
 
 /* Data structure for one wireless device (802.11 core) */
 struct b43_wldev {
-       struct ssb_device *dev;
+       struct ssb_device *sdev;
        struct b43_wl *wl;
 
        /* The device initialization status.
@@ -879,22 +881,34 @@ static inline enum ieee80211_band b43_current_band(struct b43_wl *wl)
 
 static inline u16 b43_read16(struct b43_wldev *dev, u16 offset)
 {
-       return ssb_read16(dev->dev, offset);
+       return ssb_read16(dev->sdev, offset);
 }
 
 static inline void b43_write16(struct b43_wldev *dev, u16 offset, u16 value)
 {
-       ssb_write16(dev->dev, offset, value);
+       ssb_write16(dev->sdev, offset, value);
 }
 
 static inline u32 b43_read32(struct b43_wldev *dev, u16 offset)
 {
-       return ssb_read32(dev->dev, offset);
+       return ssb_read32(dev->sdev, offset);
 }
 
 static inline void b43_write32(struct b43_wldev *dev, u16 offset, u32 value)
 {
-       ssb_write32(dev->dev, offset, value);
+       ssb_write32(dev->sdev, offset, value);
+}
+
+static inline void b43_block_read(struct b43_wldev *dev, void *buffer,
+                                size_t count, u16 offset, u8 reg_width)
+{
+       ssb_block_read(dev->sdev, buffer, count, offset, reg_width);
+}
+
+static inline void b43_block_write(struct b43_wldev *dev, const void *buffer,
+                                  size_t count, u16 offset, u8 reg_width)
+{
+       ssb_block_write(dev->sdev, buffer, count, offset, reg_width);
 }
 
 static inline bool b43_using_pio_transfers(struct b43_wldev *dev)
index ff0f5ba14b2cfb60223a19455772fddca719951b..47d44bcff37dccb73705e4a2575470010650f83b 100644 (file)
@@ -80,7 +80,7 @@ static void op32_fill_descriptor(struct b43_dmaring *ring,
        addr = (u32) (dmaaddr & ~SSB_DMA_TRANSLATION_MASK);
        addrext = (u32) (dmaaddr & SSB_DMA_TRANSLATION_MASK)
            >> SSB_DMA_TRANSLATION_SHIFT;
-       addr |= ssb_dma_translation(ring->dev->dev);
+       addr |= ring->dev->dma.translation;
        ctl = bufsize & B43_DMA32_DCTL_BYTECNT;
        if (slot == ring->nr_slots - 1)
                ctl |= B43_DMA32_DCTL_DTABLEEND;
@@ -174,7 +174,7 @@ static void op64_fill_descriptor(struct b43_dmaring *ring,
        addrhi = (((u64) dmaaddr >> 32) & ~SSB_DMA_TRANSLATION_MASK);
        addrext = (((u64) dmaaddr >> 32) & SSB_DMA_TRANSLATION_MASK)
            >> SSB_DMA_TRANSLATION_SHIFT;
-       addrhi |= (ssb_dma_translation(ring->dev->dev) << 1);
+       addrhi |= (ring->dev->dma.translation << 1);
        if (slot == ring->nr_slots - 1)
                ctl0 |= B43_DMA64_DCTL0_DTABLEEND;
        if (start)
@@ -333,10 +333,10 @@ static inline
        dma_addr_t dmaaddr;
 
        if (tx) {
-               dmaaddr = dma_map_single(ring->dev->dev->dma_dev,
+               dmaaddr = dma_map_single(ring->dev->sdev->dma_dev,
                                         buf, len, DMA_TO_DEVICE);
        } else {
-               dmaaddr = dma_map_single(ring->dev->dev->dma_dev,
+               dmaaddr = dma_map_single(ring->dev->sdev->dma_dev,
                                         buf, len, DMA_FROM_DEVICE);
        }
 
@@ -348,10 +348,10 @@ static inline
                          dma_addr_t addr, size_t len, int tx)
 {
        if (tx) {
-               dma_unmap_single(ring->dev->dev->dma_dev,
+               dma_unmap_single(ring->dev->sdev->dma_dev,
                                 addr, len, DMA_TO_DEVICE);
        } else {
-               dma_unmap_single(ring->dev->dev->dma_dev,
+               dma_unmap_single(ring->dev->sdev->dma_dev,
                                 addr, len, DMA_FROM_DEVICE);
        }
 }
@@ -361,7 +361,7 @@ static inline
                                 dma_addr_t addr, size_t len)
 {
        B43_WARN_ON(ring->tx);
-       dma_sync_single_for_cpu(ring->dev->dev->dma_dev,
+       dma_sync_single_for_cpu(ring->dev->sdev->dma_dev,
                                    addr, len, DMA_FROM_DEVICE);
 }
 
@@ -370,7 +370,7 @@ static inline
                                    dma_addr_t addr, size_t len)
 {
        B43_WARN_ON(ring->tx);
-       dma_sync_single_for_device(ring->dev->dev->dma_dev,
+       dma_sync_single_for_device(ring->dev->sdev->dma_dev,
                                   addr, len, DMA_FROM_DEVICE);
 }
 
@@ -401,7 +401,7 @@ static int alloc_ringmemory(struct b43_dmaring *ring)
         */
        if (ring->type == B43_DMA_64BIT)
                flags |= GFP_DMA;
-       ring->descbase = dma_alloc_coherent(ring->dev->dev->dma_dev,
+       ring->descbase = dma_alloc_coherent(ring->dev->sdev->dma_dev,
                                            B43_DMA_RINGMEMSIZE,
                                            &(ring->dmabase), flags);
        if (!ring->descbase) {
@@ -415,7 +415,7 @@ static int alloc_ringmemory(struct b43_dmaring *ring)
 
 static void free_ringmemory(struct b43_dmaring *ring)
 {
-       dma_free_coherent(ring->dev->dev->dma_dev, B43_DMA_RINGMEMSIZE,
+       dma_free_coherent(ring->dev->sdev->dma_dev, B43_DMA_RINGMEMSIZE,
                          ring->descbase, ring->dmabase);
 }
 
@@ -523,7 +523,7 @@ static bool b43_dma_mapping_error(struct b43_dmaring *ring,
                                  dma_addr_t addr,
                                  size_t buffersize, bool dma_to_device)
 {
-       if (unlikely(dma_mapping_error(ring->dev->dev->dma_dev, addr)))
+       if (unlikely(dma_mapping_error(ring->dev->sdev->dma_dev, addr)))
                return 1;
 
        switch (ring->type) {
@@ -658,7 +658,7 @@ static int dmacontroller_setup(struct b43_dmaring *ring)
        int err = 0;
        u32 value;
        u32 addrext;
-       u32 trans = ssb_dma_translation(ring->dev->dev);
+       u32 trans = ring->dev->dma.translation;
 
        if (ring->tx) {
                if (ring->type == B43_DMA_64BIT) {
@@ -869,7 +869,7 @@ struct b43_dmaring *b43_setup_dmaring(struct b43_wldev *dev,
                        goto err_kfree_meta;
 
                /* test for ability to dma to txhdr_cache */
-               dma_test = dma_map_single(dev->dev->dma_dev,
+               dma_test = dma_map_single(dev->sdev->dma_dev,
                                          ring->txhdr_cache,
                                          b43_txhdr_size(dev),
                                          DMA_TO_DEVICE);
@@ -884,7 +884,7 @@ struct b43_dmaring *b43_setup_dmaring(struct b43_wldev *dev,
                        if (!ring->txhdr_cache)
                                goto err_kfree_meta;
 
-                       dma_test = dma_map_single(dev->dev->dma_dev,
+                       dma_test = dma_map_single(dev->sdev->dma_dev,
                                                  ring->txhdr_cache,
                                                  b43_txhdr_size(dev),
                                                  DMA_TO_DEVICE);
@@ -898,7 +898,7 @@ struct b43_dmaring *b43_setup_dmaring(struct b43_wldev *dev,
                        }
                }
 
-               dma_unmap_single(dev->dev->dma_dev,
+               dma_unmap_single(dev->sdev->dma_dev,
                                 dma_test, b43_txhdr_size(dev),
                                 DMA_TO_DEVICE);
        }
@@ -1013,9 +1013,9 @@ static int b43_dma_set_mask(struct b43_wldev *dev, u64 mask)
        /* Try to set the DMA mask. If it fails, try falling back to a
         * lower mask, as we can always also support a lower one. */
        while (1) {
-               err = dma_set_mask(dev->dev->dma_dev, mask);
+               err = dma_set_mask(dev->sdev->dma_dev, mask);
                if (!err) {
-                       err = dma_set_coherent_mask(dev->dev->dma_dev, mask);
+                       err = dma_set_coherent_mask(dev->sdev->dma_dev, mask);
                        if (!err)
                                break;
                }
@@ -1055,6 +1055,7 @@ int b43_dma_init(struct b43_wldev *dev)
        err = b43_dma_set_mask(dev, dmamask);
        if (err)
                return err;
+       dma->translation = ssb_dma_translation(dev->sdev);
 
        err = -ENOMEM;
        /* setup TX DMA channels. */
@@ -1084,7 +1085,7 @@ int b43_dma_init(struct b43_wldev *dev)
                goto err_destroy_mcast;
 
        /* No support for the TX status DMA ring. */
-       B43_WARN_ON(dev->dev->id.revision < 5);
+       B43_WARN_ON(dev->sdev->id.revision < 5);
 
        b43dbg(dev->wl, "%u-bit DMA initialized\n",
               (unsigned int)type);
index c587115dd2b9685175e7449ebb0cd118d870488a..0cafafe368af0467f16fd7eb4072010466ce0184 100644 (file)
@@ -138,7 +138,7 @@ static int b43_register_led(struct b43_wldev *dev, struct b43_led *led,
        led->led_dev.default_trigger = default_trigger;
        led->led_dev.brightness_set = b43_led_brightness_set;
 
-       err = led_classdev_register(dev->dev->dev, &led->led_dev);
+       err = led_classdev_register(dev->sdev->dev, &led->led_dev);
        if (err) {
                b43warn(dev->wl, "LEDs: Failed to register %s\n", name);
                led->wl = NULL;
@@ -215,7 +215,7 @@ static void b43_led_get_sprominfo(struct b43_wldev *dev,
                                  enum b43_led_behaviour *behaviour,
                                  bool *activelow)
 {
-       struct ssb_bus *bus = dev->dev->bus;
+       struct ssb_bus *bus = dev->sdev->bus;
        u8 sprom[4];
 
        sprom[0] = bus->sprom.gpio0;
index 94e4f1378fc3c5660bd42b008c3e6384768d798d..2ef7d4b3854021fbfcec018225c309efa3d39daa 100644 (file)
@@ -98,7 +98,7 @@ static u16 lo_measure_feedthrough(struct b43_wldev *dev,
                rfover |= pga;
                rfover |= lna;
                rfover |= trsw_rx;
-               if ((dev->dev->bus->sprom.boardflags_lo & B43_BFL_EXTLNA)
+               if ((dev->sdev->bus->sprom.boardflags_lo & B43_BFL_EXTLNA)
                    && phy->rev > 6)
                        rfover |= B43_PHY_RFOVERVAL_EXTLNA;
 
@@ -387,7 +387,7 @@ struct lo_g_saved_values {
 static void lo_measure_setup(struct b43_wldev *dev,
                             struct lo_g_saved_values *sav)
 {
-       struct ssb_sprom *sprom = &dev->dev->bus->sprom;
+       struct ssb_sprom *sprom = &dev->sdev->bus->sprom;
        struct b43_phy *phy = &dev->phy;
        struct b43_phy_g *gphy = phy->g;
        struct b43_txpower_lo_control *lo = gphy->lo_control;
index 5a43984bdcea8e2f63294d3dbdd5690cf83caa5e..eb415968698502c597d866ff5a6e3b4f8e36b761 100644 (file)
@@ -548,7 +548,7 @@ void b43_tsf_read(struct b43_wldev *dev, u64 *tsf)
 {
        u32 low, high;
 
-       B43_WARN_ON(dev->dev->id.revision < 3);
+       B43_WARN_ON(dev->sdev->id.revision < 3);
 
        /* The hardware guarantees us an atomic read, if we
         * read the low register first. */
@@ -586,7 +586,7 @@ static void b43_tsf_write_locked(struct b43_wldev *dev, u64 tsf)
 {
        u32 low, high;
 
-       B43_WARN_ON(dev->dev->id.revision < 3);
+       B43_WARN_ON(dev->sdev->id.revision < 3);
 
        low = tsf;
        high = (tsf >> 32);
@@ -714,7 +714,7 @@ void b43_dummy_transmission(struct b43_wldev *dev, bool ofdm, bool pa_on)
                b43_ram_write(dev, i * 4, buffer[i]);
 
        b43_write16(dev, 0x0568, 0x0000);
-       if (dev->dev->id.revision < 11)
+       if (dev->sdev->id.revision < 11)
                b43_write16(dev, 0x07C0, 0x0000);
        else
                b43_write16(dev, 0x07C0, 0x0100);
@@ -1132,7 +1132,7 @@ void b43_power_saving_ctl_bits(struct b43_wldev *dev, unsigned int ps_flags)
        b43_write32(dev, B43_MMIO_MACCTL, macctl);
        /* Commit write */
        b43_read32(dev, B43_MMIO_MACCTL);
-       if (awake && dev->dev->id.revision >= 5) {
+       if (awake && dev->sdev->id.revision >= 5) {
                /* Wait for the microcode to wake up. */
                for (i = 0; i < 100; i++) {
                        ucstat = b43_shm_read16(dev, B43_SHM_SHARED,
@@ -1144,29 +1144,35 @@ void b43_power_saving_ctl_bits(struct b43_wldev *dev, unsigned int ps_flags)
        }
 }
 
-void b43_wireless_core_reset(struct b43_wldev *dev, u32 flags)
+static void b43_ssb_wireless_core_reset(struct b43_wldev *dev, u32 flags)
 {
        u32 tmslow;
-       u32 macctl;
 
        flags |= B43_TMSLOW_PHYCLKEN;
        flags |= B43_TMSLOW_PHYRESET;
        if (dev->phy.type == B43_PHYTYPE_N)
                flags |= B43_TMSLOW_PHY_BANDWIDTH_20MHZ; /* Make 20 MHz def */
-       ssb_device_enable(dev->dev, flags);
+       ssb_device_enable(dev->sdev, flags);
        msleep(2);              /* Wait for the PLL to turn on. */
 
        /* Now take the PHY out of Reset again */
-       tmslow = ssb_read32(dev->dev, SSB_TMSLOW);
+       tmslow = ssb_read32(dev->sdev, SSB_TMSLOW);
        tmslow |= SSB_TMSLOW_FGC;
        tmslow &= ~B43_TMSLOW_PHYRESET;
-       ssb_write32(dev->dev, SSB_TMSLOW, tmslow);
-       ssb_read32(dev->dev, SSB_TMSLOW);       /* flush */
+       ssb_write32(dev->sdev, SSB_TMSLOW, tmslow);
+       ssb_read32(dev->sdev, SSB_TMSLOW);      /* flush */
        msleep(1);
        tmslow &= ~SSB_TMSLOW_FGC;
-       ssb_write32(dev->dev, SSB_TMSLOW, tmslow);
-       ssb_read32(dev->dev, SSB_TMSLOW);       /* flush */
+       ssb_write32(dev->sdev, SSB_TMSLOW, tmslow);
+       ssb_read32(dev->sdev, SSB_TMSLOW);      /* flush */
        msleep(1);
+}
+
+void b43_wireless_core_reset(struct b43_wldev *dev, u32 flags)
+{
+       u32 macctl;
+
+       b43_ssb_wireless_core_reset(dev, flags);
 
        /* Turn Analog ON, but only if we already know the PHY-type.
         * This protects against very early setup where we don't know the
@@ -1215,7 +1221,7 @@ static void drain_txstatus_queue(struct b43_wldev *dev)
 {
        u32 dummy;
 
-       if (dev->dev->id.revision < 5)
+       if (dev->sdev->id.revision < 5)
                return;
        /* Read all entries from the microcode TXstatus FIFO
         * and throw them away.
@@ -1421,9 +1427,9 @@ u8 b43_ieee80211_antenna_sanitize(struct b43_wldev *dev,
 
        /* Get the mask of available antennas. */
        if (dev->phy.gmode)
-               antenna_mask = dev->dev->bus->sprom.ant_available_bg;
+               antenna_mask = dev->sdev->bus->sprom.ant_available_bg;
        else
-               antenna_mask = dev->dev->bus->sprom.ant_available_a;
+               antenna_mask = dev->sdev->bus->sprom.ant_available_a;
 
        if (!(antenna_mask & (1 << (antenna_nr - 1)))) {
                /* This antenna is not available. Fall back to default. */
@@ -1638,7 +1644,7 @@ static void b43_beacon_update_trigger_work(struct work_struct *work)
        mutex_lock(&wl->mutex);
        dev = wl->current_dev;
        if (likely(dev && (b43_status(dev) >= B43_STAT_INITIALIZED))) {
-               if (dev->dev->bus->bustype == SSB_BUSTYPE_SDIO) {
+               if (dev->sdev->bus->bustype == SSB_BUSTYPE_SDIO) {
                        /* wl->mutex is enough. */
                        b43_do_beacon_update_trigger_work(dev);
                        mmiowb();
@@ -1683,7 +1689,7 @@ static void b43_update_templates(struct b43_wl *wl)
 static void b43_set_beacon_int(struct b43_wldev *dev, u16 beacon_int)
 {
        b43_time_lock(dev);
-       if (dev->dev->id.revision >= 3) {
+       if (dev->sdev->id.revision >= 3) {
                b43_write32(dev, B43_MMIO_TSF_CFP_REP, (beacon_int << 16));
                b43_write32(dev, B43_MMIO_TSF_CFP_START, (beacon_int << 10));
        } else {
@@ -2057,7 +2063,7 @@ int b43_do_request_fw(struct b43_request_fw_context *ctx,
                B43_WARN_ON(1);
                return -ENOSYS;
        }
-       err = request_firmware(&blob, ctx->fwname, ctx->dev->dev->dev);
+       err = request_firmware(&blob, ctx->fwname, ctx->dev->sdev->dev);
        if (err == -ENOENT) {
                snprintf(ctx->errors[ctx->req_type],
                         sizeof(ctx->errors[ctx->req_type]),
@@ -2107,13 +2113,12 @@ static int b43_try_request_fw(struct b43_request_fw_context *ctx)
 {
        struct b43_wldev *dev = ctx->dev;
        struct b43_firmware *fw = &ctx->dev->fw;
-       const u8 rev = ctx->dev->dev->id.revision;
+       const u8 rev = ctx->dev->sdev->id.revision;
        const char *filename;
        u32 tmshigh;
        int err;
 
        /* Get microcode */
-       tmshigh = ssb_read32(dev->dev, SSB_TMSHIGH);
        if ((rev >= 5) && (rev <= 10))
                filename = "ucode5";
        else if ((rev >= 11) && (rev <= 12))
@@ -2152,6 +2157,7 @@ static int b43_try_request_fw(struct b43_request_fw_context *ctx)
        switch (dev->phy.type) {
        case B43_PHYTYPE_A:
                if ((rev >= 5) && (rev <= 10)) {
+                       tmshigh = ssb_read32(dev->sdev, SSB_TMSHIGH);
                        if (tmshigh & B43_TMSHIGH_HAVE_2GHZ_PHY)
                                filename = "a0g1initvals5";
                        else
@@ -2196,6 +2202,7 @@ static int b43_try_request_fw(struct b43_request_fw_context *ctx)
        switch (dev->phy.type) {
        case B43_PHYTYPE_A:
                if ((rev >= 5) && (rev <= 10)) {
+                       tmshigh = ssb_read32(dev->sdev, SSB_TMSHIGH);
                        if (tmshigh & B43_TMSHIGH_HAVE_2GHZ_PHY)
                                filename = "a0g1bsinitvals5";
                        else
@@ -2441,7 +2448,7 @@ static int b43_upload_microcode(struct b43_wldev *dev)
 
        snprintf(wiphy->fw_version, sizeof(wiphy->fw_version), "%u.%u",
                        dev->fw.rev, dev->fw.patch);
-       wiphy->hw_version = dev->dev->id.coreid;
+       wiphy->hw_version = dev->sdev->id.coreid;
 
        if (b43_is_old_txhdr_format(dev)) {
                /* We're over the deadline, but we keep support for old fw
@@ -2557,10 +2564,20 @@ out:
 /* Initialize the GPIOs
  * http://bcm-specs.sipsolutions.net/GPIO
  */
+static struct ssb_device *b43_ssb_gpio_dev(struct b43_wldev *dev)
+{
+       struct ssb_bus *bus = dev->sdev->bus;
+
+#ifdef CONFIG_SSB_DRIVER_PCICORE
+       return (bus->chipco.dev ? bus->chipco.dev : bus->pcicore.dev);
+#else
+       return bus->chipco.dev;
+#endif
+}
+
 static int b43_gpio_init(struct b43_wldev *dev)
 {
-       struct ssb_bus *bus = dev->dev->bus;
-       struct ssb_device *gpiodev, *pcidev = NULL;
+       struct ssb_device *gpiodev;
        u32 mask, set;
 
        b43_write32(dev, B43_MMIO_MACCTL, b43_read32(dev, B43_MMIO_MACCTL)
@@ -2571,7 +2588,7 @@ static int b43_gpio_init(struct b43_wldev *dev)
 
        mask = 0x0000001F;
        set = 0x0000000F;
-       if (dev->dev->bus->chip_id == 0x4301) {
+       if (dev->sdev->bus->chip_id == 0x4301) {
                mask |= 0x0060;
                set |= 0x0060;
        }
@@ -2582,25 +2599,21 @@ static int b43_gpio_init(struct b43_wldev *dev)
                mask |= 0x0180;
                set |= 0x0180;
        }
-       if (dev->dev->bus->sprom.boardflags_lo & B43_BFL_PACTRL) {
+       if (dev->sdev->bus->sprom.boardflags_lo & B43_BFL_PACTRL) {
                b43_write16(dev, B43_MMIO_GPIO_MASK,
                            b43_read16(dev, B43_MMIO_GPIO_MASK)
                            | 0x0200);
                mask |= 0x0200;
                set |= 0x0200;
        }
-       if (dev->dev->id.revision >= 2)
+       if (dev->sdev->id.revision >= 2)
                mask |= 0x0010; /* FIXME: This is redundant. */
 
-#ifdef CONFIG_SSB_DRIVER_PCICORE
-       pcidev = bus->pcicore.dev;
-#endif
-       gpiodev = bus->chipco.dev ? : pcidev;
-       if (!gpiodev)
-               return 0;
-       ssb_write32(gpiodev, B43_GPIO_CONTROL,
-                   (ssb_read32(gpiodev, B43_GPIO_CONTROL)
-                    & mask) | set);
+       gpiodev = b43_ssb_gpio_dev(dev);
+       if (gpiodev)
+               ssb_write32(gpiodev, B43_GPIO_CONTROL,
+                           (ssb_read32(gpiodev, B43_GPIO_CONTROL)
+                            & mask) | set);
 
        return 0;
 }
@@ -2608,16 +2621,11 @@ static int b43_gpio_init(struct b43_wldev *dev)
 /* Turn off all GPIO stuff. Call this on module unload, for example. */
 static void b43_gpio_cleanup(struct b43_wldev *dev)
 {
-       struct ssb_bus *bus = dev->dev->bus;
-       struct ssb_device *gpiodev, *pcidev = NULL;
+       struct ssb_device *gpiodev;
 
-#ifdef CONFIG_SSB_DRIVER_PCICORE
-       pcidev = bus->pcicore.dev;
-#endif
-       gpiodev = bus->chipco.dev ? : pcidev;
-       if (!gpiodev)
-               return;
-       ssb_write32(gpiodev, B43_GPIO_CONTROL, 0);
+       gpiodev = b43_ssb_gpio_dev(dev);
+       if (gpiodev)
+               ssb_write32(gpiodev, B43_GPIO_CONTROL, 0);
 }
 
 /* http://bcm-specs.sipsolutions.net/EnableMac */
@@ -2689,12 +2697,12 @@ out:
 /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/MacPhyClkSet */
 void b43_mac_phy_clock_set(struct b43_wldev *dev, bool on)
 {
-       u32 tmslow = ssb_read32(dev->dev, SSB_TMSLOW);
+       u32 tmslow = ssb_read32(dev->sdev, SSB_TMSLOW);
        if (on)
                tmslow |= B43_TMSLOW_MACPHYCLKEN;
        else
                tmslow &= ~B43_TMSLOW_MACPHYCLKEN;
-       ssb_write32(dev->dev, SSB_TMSLOW, tmslow);
+       ssb_write32(dev->sdev, SSB_TMSLOW, tmslow);
 }
 
 static void b43_adjust_opmode(struct b43_wldev *dev)
@@ -2733,15 +2741,15 @@ static void b43_adjust_opmode(struct b43_wldev *dev)
        /* Workaround: On old hardware the HW-MAC-address-filter
         * doesn't work properly, so always run promisc in filter
         * it in software. */
-       if (dev->dev->id.revision <= 4)
+       if (dev->sdev->id.revision <= 4)
                ctl |= B43_MACCTL_PROMISC;
 
        b43_write32(dev, B43_MMIO_MACCTL, ctl);
 
        cfp_pretbtt = 2;
        if ((ctl & B43_MACCTL_INFRA) && !(ctl & B43_MACCTL_AP)) {
-               if (dev->dev->bus->chip_id == 0x4306 &&
-                   dev->dev->bus->chip_rev == 3)
+               if (dev->sdev->bus->chip_id == 0x4306 &&
+                   dev->sdev->bus->chip_rev == 3)
                        cfp_pretbtt = 100;
                else
                        cfp_pretbtt = 50;
@@ -2899,7 +2907,7 @@ static int b43_chip_init(struct b43_wldev *dev)
                b43_write16(dev, 0x005E, value16);
        }
        b43_write32(dev, 0x0100, 0x01000000);
-       if (dev->dev->id.revision < 5)
+       if (dev->sdev->id.revision < 5)
                b43_write32(dev, 0x010C, 0x01000000);
 
        b43_write32(dev, B43_MMIO_MACCTL, b43_read32(dev, B43_MMIO_MACCTL)
@@ -2914,7 +2922,7 @@ static int b43_chip_init(struct b43_wldev *dev)
        /* Initially set the wireless operation mode. */
        b43_adjust_opmode(dev);
 
-       if (dev->dev->id.revision < 3) {
+       if (dev->sdev->id.revision < 3) {
                b43_write16(dev, 0x060E, 0x0000);
                b43_write16(dev, 0x0610, 0x8000);
                b43_write16(dev, 0x0604, 0x0000);
@@ -2934,7 +2942,7 @@ static int b43_chip_init(struct b43_wldev *dev)
        b43_mac_phy_clock_set(dev, true);
 
        b43_write16(dev, B43_MMIO_POWERUP_DELAY,
-                   dev->dev->bus->chipco.fast_pwrup_delay);
+                   dev->sdev->bus->chipco.fast_pwrup_delay);
 
        err = 0;
        b43dbg(dev->wl, "Chip initialized\n");
@@ -3097,7 +3105,7 @@ static int b43_validate_chipaccess(struct b43_wldev *dev)
        b43_shm_write32(dev, B43_SHM_SHARED, 0, backup0);
        b43_shm_write32(dev, B43_SHM_SHARED, 4, backup4);
 
-       if ((dev->dev->id.revision >= 3) && (dev->dev->id.revision <= 10)) {
+       if ((dev->sdev->id.revision >= 3) && (dev->sdev->id.revision <= 10)) {
                /* The 32bit register shadows the two 16bit registers
                 * with update sideeffects. Validate this. */
                b43_write16(dev, B43_MMIO_TSF_CFP_START, 0xAAAA);
@@ -3450,7 +3458,7 @@ static void b43_op_set_tsf(struct ieee80211_hw *hw, u64 tsf)
 
 static void b43_put_phy_into_reset(struct b43_wldev *dev)
 {
-       struct ssb_device *sdev = dev->dev;
+       struct ssb_device *sdev = dev->sdev;
        u32 tmslow;
 
        tmslow = ssb_read32(sdev, SSB_TMSLOW);
@@ -3946,7 +3954,7 @@ redo:
 
        /* Disable interrupts on the device. */
        b43_set_status(dev, B43_STAT_INITIALIZED);
-       if (dev->dev->bus->bustype == SSB_BUSTYPE_SDIO) {
+       if (dev->sdev->bus->bustype == SSB_BUSTYPE_SDIO) {
                /* wl->mutex is locked. That is enough. */
                b43_write32(dev, B43_MMIO_GEN_IRQ_MASK, 0);
                b43_read32(dev, B43_MMIO_GEN_IRQ_MASK); /* Flush */
@@ -3959,11 +3967,11 @@ redo:
        /* Synchronize and free the interrupt handlers. Unlock to avoid deadlocks. */
        orig_dev = dev;
        mutex_unlock(&wl->mutex);
-       if (dev->dev->bus->bustype == SSB_BUSTYPE_SDIO) {
+       if (dev->sdev->bus->bustype == SSB_BUSTYPE_SDIO) {
                b43_sdio_free_irq(dev);
        } else {
-               synchronize_irq(dev->dev->irq);
-               free_irq(dev->dev->irq, dev);
+               synchronize_irq(dev->sdev->irq);
+               free_irq(dev->sdev->irq, dev);
        }
        mutex_lock(&wl->mutex);
        dev = wl->current_dev;
@@ -3996,18 +4004,19 @@ static int b43_wireless_core_start(struct b43_wldev *dev)
        B43_WARN_ON(b43_status(dev) != B43_STAT_INITIALIZED);
 
        drain_txstatus_queue(dev);
-       if (dev->dev->bus->bustype == SSB_BUSTYPE_SDIO) {
+       if (dev->sdev->bus->bustype == SSB_BUSTYPE_SDIO) {
                err = b43_sdio_request_irq(dev, b43_sdio_interrupt_handler);
                if (err) {
                        b43err(dev->wl, "Cannot request SDIO IRQ\n");
                        goto out;
                }
        } else {
-               err = request_threaded_irq(dev->dev->irq, b43_interrupt_handler,
+               err = request_threaded_irq(dev->sdev->irq, b43_interrupt_handler,
                                           b43_interrupt_thread_handler,
                                           IRQF_SHARED, KBUILD_MODNAME, dev);
                if (err) {
-                       b43err(dev->wl, "Cannot request IRQ-%d\n", dev->dev->irq);
+                       b43err(dev->wl, "Cannot request IRQ-%d\n",
+                              dev->sdev->irq);
                        goto out;
                }
        }
@@ -4087,10 +4096,10 @@ static int b43_phy_versioning(struct b43_wldev *dev)
               analog_type, phy_type, phy_rev);
 
        /* Get RADIO versioning */
-       if (dev->dev->bus->chip_id == 0x4317) {
-               if (dev->dev->bus->chip_rev == 0)
+       if (dev->sdev->bus->chip_id == 0x4317) {
+               if (dev->sdev->bus->chip_rev == 0)
                        tmp = 0x3205017F;
-               else if (dev->dev->bus->chip_rev == 1)
+               else if (dev->sdev->bus->chip_rev == 1)
                        tmp = 0x4205017F;
                else
                        tmp = 0x5205017F;
@@ -4195,7 +4204,7 @@ static void setup_struct_wldev_for_init(struct b43_wldev *dev)
 
 static void b43_bluetooth_coext_enable(struct b43_wldev *dev)
 {
-       struct ssb_sprom *sprom = &dev->dev->bus->sprom;
+       struct ssb_sprom *sprom = &dev->sdev->bus->sprom;
        u64 hf;
 
        if (!modparam_btcoex)
@@ -4222,16 +4231,16 @@ static void b43_bluetooth_coext_disable(struct b43_wldev *dev)
 
 static void b43_imcfglo_timeouts_workaround(struct b43_wldev *dev)
 {
-       struct ssb_bus *bus = dev->dev->bus;
+       struct ssb_bus *bus = dev->sdev->bus;
        u32 tmp;
 
        if ((bus->chip_id == 0x4311 && bus->chip_rev == 2) ||
            (bus->chip_id == 0x4312)) {
-               tmp = ssb_read32(dev->dev, SSB_IMCFGLO);
+               tmp = ssb_read32(dev->sdev, SSB_IMCFGLO);
                tmp &= ~SSB_IMCFGLO_REQTO;
                tmp &= ~SSB_IMCFGLO_SERTO;
                tmp |= 0x3;
-               ssb_write32(dev->dev, SSB_IMCFGLO, tmp);
+               ssb_write32(dev->sdev, SSB_IMCFGLO, tmp);
                ssb_commit_settings(bus);
        }
 }
@@ -4301,14 +4310,14 @@ static void b43_wireless_core_exit(struct b43_wldev *dev)
                dev->wl->current_beacon = NULL;
        }
 
-       ssb_device_disable(dev->dev, 0);
-       ssb_bus_may_powerdown(dev->dev->bus);
+       ssb_device_disable(dev->sdev, 0);
+       ssb_bus_may_powerdown(dev->sdev->bus);
 }
 
 /* Initialize a wireless core */
 static int b43_wireless_core_init(struct b43_wldev *dev)
 {
-       struct ssb_bus *bus = dev->dev->bus;
+       struct ssb_bus *bus = dev->sdev->bus;
        struct ssb_sprom *sprom = &bus->sprom;
        struct b43_phy *phy = &dev->phy;
        int err;
@@ -4320,7 +4329,7 @@ static int b43_wireless_core_init(struct b43_wldev *dev)
        err = ssb_bus_powerup(bus, 0);
        if (err)
                goto out;
-       if (!ssb_device_is_enabled(dev->dev)) {
+       if (!ssb_device_is_enabled(dev->sdev)) {
                tmp = phy->gmode ? B43_TMSLOW_GMODE : 0;
                b43_wireless_core_reset(dev, tmp);
        }
@@ -4330,7 +4339,7 @@ static int b43_wireless_core_init(struct b43_wldev *dev)
        phy->ops->prepare_structs(dev);
 
        /* Enable IRQ routing to this device. */
-       ssb_pcicore_dev_irqvecs_enable(&bus->pcicore, dev->dev);
+       ssb_pcicore_dev_irqvecs_enable(&bus->pcicore, dev->sdev);
 
        b43_imcfglo_timeouts_workaround(dev);
        b43_bluetooth_coext_disable(dev);
@@ -4343,7 +4352,7 @@ static int b43_wireless_core_init(struct b43_wldev *dev)
        if (err)
                goto err_busdown;
        b43_shm_write16(dev, B43_SHM_SHARED,
-                       B43_SHM_SH_WLCOREREV, dev->dev->id.revision);
+                       B43_SHM_SH_WLCOREREV, dev->sdev->id.revision);
        hf = b43_hf_read(dev);
        if (phy->type == B43_PHYTYPE_G) {
                hf |= B43_HF_SYMW;
@@ -4390,8 +4399,8 @@ static int b43_wireless_core_init(struct b43_wldev *dev)
        /* Maximum Contention Window */
        b43_shm_write16(dev, B43_SHM_SCRATCH, B43_SHM_SC_MAXCONT, 0x3FF);
 
-       if ((dev->dev->bus->bustype == SSB_BUSTYPE_PCMCIA) ||
-           (dev->dev->bus->bustype == SSB_BUSTYPE_SDIO) ||
+       if ((dev->sdev->bus->bustype == SSB_BUSTYPE_PCMCIA) ||
+           (dev->sdev->bus->bustype == SSB_BUSTYPE_SDIO) ||
            dev->use_pio) {
                dev->__using_pio_transfers = 1;
                err = b43_pio_init(dev);
@@ -4728,7 +4737,7 @@ static void b43_wireless_core_detach(struct b43_wldev *dev)
 static int b43_wireless_core_attach(struct b43_wldev *dev)
 {
        struct b43_wl *wl = dev->wl;
-       struct ssb_bus *bus = dev->dev->bus;
+       struct ssb_bus *bus = dev->sdev->bus;
        struct pci_dev *pdev = (bus->bustype == SSB_BUSTYPE_PCI) ? bus->host_pci : NULL;
        int err;
        bool have_2ghz_phy = 0, have_5ghz_phy = 0;
@@ -4747,10 +4756,10 @@ static int b43_wireless_core_attach(struct b43_wldev *dev)
                goto out;
        }
        /* Get the PHY type. */
-       if (dev->dev->id.revision >= 5) {
+       if (dev->sdev->id.revision >= 5) {
                u32 tmshigh;
 
-               tmshigh = ssb_read32(dev->dev, SSB_TMSHIGH);
+               tmshigh = ssb_read32(dev->sdev, SSB_TMSHIGH);
                have_2ghz_phy = !!(tmshigh & B43_TMSHIGH_HAVE_2GHZ_PHY);
                have_5ghz_phy = !!(tmshigh & B43_TMSHIGH_HAVE_5GHZ_PHY);
        } else
@@ -4823,7 +4832,7 @@ static int b43_wireless_core_attach(struct b43_wldev *dev)
        INIT_WORK(&dev->restart_work, b43_chip_reset);
 
        dev->phy.ops->switch_analog(dev, 0);
-       ssb_device_disable(dev->dev, 0);
+       ssb_device_disable(dev->sdev, 0);
        ssb_bus_may_powerdown(bus);
 
 out:
@@ -4864,7 +4873,7 @@ static int b43_one_core_attach(struct ssb_device *dev, struct b43_wl *wl)
                goto out;
 
        wldev->use_pio = b43_modparam_pio;
-       wldev->dev = dev;
+       wldev->sdev = dev;
        wldev->wl = wl;
        b43_set_status(wldev, B43_STAT_UNINIT);
        wldev->bad_frames_preempt = modparam_bad_frames_preempt;
@@ -4925,19 +4934,16 @@ static void b43_wireless_exit(struct ssb_device *dev, struct b43_wl *wl)
        ieee80211_free_hw(hw);
 }
 
-static int b43_wireless_init(struct ssb_device *dev)
+static struct b43_wl *b43_wireless_init(struct ssb_device *dev)
 {
        struct ssb_sprom *sprom = &dev->bus->sprom;
        struct ieee80211_hw *hw;
        struct b43_wl *wl;
-       int err = -ENOMEM;
-
-       b43_sprom_fixup(dev->bus);
 
        hw = ieee80211_alloc_hw(sizeof(*wl), &b43_hw_ops);
        if (!hw) {
                b43err(NULL, "Could not allocate ieee80211 device\n");
-               goto out;
+               return ERR_PTR(-ENOMEM);
        }
        wl = hw_to_b43_wl(hw);
 
@@ -4971,12 +4977,9 @@ static int b43_wireless_init(struct ssb_device *dev)
        INIT_WORK(&wl->tx_work, b43_tx_work);
        skb_queue_head_init(&wl->tx_queue);
 
-       ssb_set_devtypedata(dev, wl);
        b43info(wl, "Broadcom %04X WLAN found (core revision %u)\n",
                dev->bus->chip_id, dev->id.revision);
-       err = 0;
-out:
-       return err;
+       return wl;
 }
 
 static int b43_ssb_probe(struct ssb_device *dev, const struct ssb_device_id *id)
@@ -4989,11 +4992,14 @@ static int b43_ssb_probe(struct ssb_device *dev, const struct ssb_device_id *id)
        if (!wl) {
                /* Probing the first core. Must setup common struct b43_wl */
                first = 1;
-               err = b43_wireless_init(dev);
-               if (err)
+               b43_sprom_fixup(dev->bus);
+               wl = b43_wireless_init(dev);
+               if (IS_ERR(wl)) {
+                       err = PTR_ERR(wl);
                        goto out;
-               wl = ssb_get_devtypedata(dev);
-               B43_WARN_ON(!wl);
+               }
+               ssb_set_devtypedata(dev, wl);
+               B43_WARN_ON(ssb_get_devtypedata(dev) != wl);
        }
        err = b43_one_core_attach(dev, wl);
        if (err)
index b6428ec16dd638faf0fe167616ab2c9efb21d91a..b01c8ced57c3938099990b46220431108f521943 100644 (file)
@@ -265,7 +265,7 @@ static void hardware_pctl_init_aphy(struct b43_wldev *dev)
 
 void b43_phy_inita(struct b43_wldev *dev)
 {
-       struct ssb_bus *bus = dev->dev->bus;
+       struct ssb_bus *bus = dev->sdev->bus;
        struct b43_phy *phy = &dev->phy;
 
        /* This lowlevel A-PHY init is also called from G-PHY init.
@@ -311,7 +311,7 @@ void b43_phy_inita(struct b43_wldev *dev)
        }
 
        if ((phy->type == B43_PHYTYPE_G) &&
-           (dev->dev->bus->sprom.boardflags_lo & B43_BFL_PACTRL)) {
+           (dev->sdev->bus->sprom.boardflags_lo & B43_BFL_PACTRL)) {
                b43_phy_maskset(dev, B43_PHY_OFDM(0x6E), 0xE000, 0x3CF);
        }
 }
@@ -323,17 +323,17 @@ static int b43_aphy_init_tssi2dbm_table(struct b43_wldev *dev)
        struct b43_phy_a *aphy = phy->a;
        s16 pab0, pab1, pab2;
 
-       pab0 = (s16) (dev->dev->bus->sprom.pa1b0);
-       pab1 = (s16) (dev->dev->bus->sprom.pa1b1);
-       pab2 = (s16) (dev->dev->bus->sprom.pa1b2);
+       pab0 = (s16) (dev->sdev->bus->sprom.pa1b0);
+       pab1 = (s16) (dev->sdev->bus->sprom.pa1b1);
+       pab2 = (s16) (dev->sdev->bus->sprom.pa1b2);
 
        if (pab0 != 0 && pab1 != 0 && pab2 != 0 &&
            pab0 != -1 && pab1 != -1 && pab2 != -1) {
                /* The pabX values are set in SPROM. Use them. */
-               if ((s8) dev->dev->bus->sprom.itssi_a != 0 &&
-                   (s8) dev->dev->bus->sprom.itssi_a != -1)
+               if ((s8) dev->sdev->bus->sprom.itssi_a != 0 &&
+                   (s8) dev->sdev->bus->sprom.itssi_a != -1)
                        aphy->tgt_idle_tssi =
-                           (s8) (dev->dev->bus->sprom.itssi_a);
+                           (s8) (dev->sdev->bus->sprom.itssi_a);
                else
                        aphy->tgt_idle_tssi = 62;
                aphy->tssi2dbm = b43_generate_dyn_tssi2dbm_tab(dev, pab0,
index b5c5ce94d3fd8607c9d06b20d351cd8345a3c7b0..e46b2f4f0920d0ce202dc2b21678603148a5baa8 100644 (file)
@@ -168,7 +168,7 @@ void b43_phy_lock(struct b43_wldev *dev)
        B43_WARN_ON(dev->phy.phy_locked);
        dev->phy.phy_locked = 1;
 #endif
-       B43_WARN_ON(dev->dev->id.revision < 3);
+       B43_WARN_ON(dev->sdev->id.revision < 3);
 
        if (!b43_is_mode(dev->wl, NL80211_IFTYPE_AP))
                b43_power_saving_ctl_bits(dev, B43_PS_AWAKE);
@@ -180,7 +180,7 @@ void b43_phy_unlock(struct b43_wldev *dev)
        B43_WARN_ON(!dev->phy.phy_locked);
        dev->phy.phy_locked = 0;
 #endif
-       B43_WARN_ON(dev->dev->id.revision < 3);
+       B43_WARN_ON(dev->sdev->id.revision < 3);
 
        if (!b43_is_mode(dev->wl, NL80211_IFTYPE_AP))
                b43_power_saving_ctl_bits(dev, 0);
@@ -368,8 +368,8 @@ void b43_phy_txpower_check(struct b43_wldev *dev, unsigned int flags)
        /* The next check will be needed in two seconds, or later. */
        phy->next_txpwr_check_time = round_jiffies(now + (HZ * 2));
 
-       if ((dev->dev->bus->boardinfo.vendor == SSB_BOARDVENDOR_BCM) &&
-           (dev->dev->bus->boardinfo.type == SSB_BOARD_BU4306))
+       if ((dev->sdev->bus->boardinfo.vendor == SSB_BOARDVENDOR_BCM) &&
+           (dev->sdev->bus->boardinfo.type == SSB_BOARD_BU4306))
                return; /* No software txpower adjustment needed */
 
        result = phy->ops->recalc_txpower(dev, !!(flags & B43_TXPWR_IGNORE_TSSI));
index be4828167012d0703f7ebe60d501e9b0f6fd8b6c..1758a282f913548403ee0a6b55dacac832ac92f5 100644 (file)
@@ -718,7 +718,7 @@ static void b43_calc_nrssi_threshold(struct b43_wldev *dev)
        B43_WARN_ON(phy->type != B43_PHYTYPE_G);
 
        if (!phy->gmode ||
-           !(dev->dev->bus->sprom.boardflags_lo & B43_BFL_RSSI)) {
+           !(dev->sdev->bus->sprom.boardflags_lo & B43_BFL_RSSI)) {
                tmp16 = b43_nrssi_hw_read(dev, 0x20);
                if (tmp16 >= 0x20)
                        tmp16 -= 0x40;
@@ -1114,7 +1114,7 @@ static u16 radio2050_rfover_val(struct b43_wldev *dev,
 {
        struct b43_phy *phy = &dev->phy;
        struct b43_phy_g *gphy = phy->g;
-       struct ssb_sprom *sprom = &(dev->dev->bus->sprom);
+       struct ssb_sprom *sprom = &(dev->sdev->bus->sprom);
 
        if (!phy->gmode)
                return 0;
@@ -1491,7 +1491,7 @@ static u16 b43_radio_init2050(struct b43_wldev *dev)
 
 static void b43_phy_initb5(struct b43_wldev *dev)
 {
-       struct ssb_bus *bus = dev->dev->bus;
+       struct ssb_bus *bus = dev->sdev->bus;
        struct b43_phy *phy = &dev->phy;
        struct b43_phy_g *gphy = phy->g;
        u16 offset, value;
@@ -1620,7 +1620,7 @@ static void b43_phy_initb6(struct b43_wldev *dev)
                b43_radio_write16(dev, 0x5A, 0x88);
                b43_radio_write16(dev, 0x5B, 0x6B);
                b43_radio_write16(dev, 0x5C, 0x0F);
-               if (dev->dev->bus->sprom.boardflags_lo & B43_BFL_ALTIQ) {
+               if (dev->sdev->bus->sprom.boardflags_lo & B43_BFL_ALTIQ) {
                        b43_radio_write16(dev, 0x5D, 0xFA);
                        b43_radio_write16(dev, 0x5E, 0xD8);
                } else {
@@ -1787,7 +1787,7 @@ static void b43_calc_loopback_gain(struct b43_wldev *dev)
        b43_phy_set(dev, B43_PHY_RFOVER, 0x0100);
        b43_phy_mask(dev, B43_PHY_RFOVERVAL, 0xCFFF);
 
-       if (dev->dev->bus->sprom.boardflags_lo & B43_BFL_EXTLNA) {
+       if (dev->sdev->bus->sprom.boardflags_lo & B43_BFL_EXTLNA) {
                if (phy->rev >= 7) {
                        b43_phy_set(dev, B43_PHY_RFOVER, 0x0800);
                        b43_phy_set(dev, B43_PHY_RFOVERVAL, 0x8000);
@@ -1922,7 +1922,7 @@ static void b43_hardware_pctl_init_gphy(struct b43_wldev *dev)
 /* Initialize B/G PHY power control */
 static void b43_phy_init_pctl(struct b43_wldev *dev)
 {
-       struct ssb_bus *bus = dev->dev->bus;
+       struct ssb_bus *bus = dev->sdev->bus;
        struct b43_phy *phy = &dev->phy;
        struct b43_phy_g *gphy = phy->g;
        struct b43_rfatt old_rfatt;
@@ -2053,7 +2053,7 @@ static void b43_phy_initg(struct b43_wldev *dev)
        if (phy->rev >= 6) {
                b43_phy_maskset(dev, B43_PHY_CCK(0x36), 0x0FFF, (gphy->lo_control->tx_bias << 12));
        }
-       if (dev->dev->bus->sprom.boardflags_lo & B43_BFL_PACTRL)
+       if (dev->sdev->bus->sprom.boardflags_lo & B43_BFL_PACTRL)
                b43_phy_write(dev, B43_PHY_CCK(0x2E), 0x8075);
        else
                b43_phy_write(dev, B43_PHY_CCK(0x2E), 0x807F);
@@ -2066,7 +2066,7 @@ static void b43_phy_initg(struct b43_wldev *dev)
                b43_phy_write(dev, B43_PHY_LO_MASK, 0x8078);
        }
 
-       if (!(dev->dev->bus->sprom.boardflags_lo & B43_BFL_RSSI)) {
+       if (!(dev->sdev->bus->sprom.boardflags_lo & B43_BFL_RSSI)) {
                /* The specs state to update the NRSSI LT with
                 * the value 0x7FFFFFFF here. I think that is some weird
                 * compiler optimization in the original driver.
@@ -2088,8 +2088,8 @@ static void b43_phy_initg(struct b43_wldev *dev)
        /* FIXME: The spec says in the following if, the 0 should be replaced
           'if OFDM may not be used in the current locale'
           but OFDM is legal everywhere */
-       if ((dev->dev->bus->chip_id == 0x4306
-            && dev->dev->bus->chip_package == 2) || 0) {
+       if ((dev->sdev->bus->chip_id == 0x4306
+            && dev->sdev->bus->chip_package == 2) || 0) {
                b43_phy_mask(dev, B43_PHY_CRS0, 0xBFFF);
                b43_phy_mask(dev, B43_PHY_OFDM(0xC3), 0x7FFF);
        }
@@ -2105,7 +2105,7 @@ void b43_gphy_channel_switch(struct b43_wldev *dev,
        b43_write16(dev, B43_MMIO_CHANNEL, channel2freq_bg(channel));
 
        if (channel == 14) {
-               if (dev->dev->bus->sprom.country_code ==
+               if (dev->sdev->bus->sprom.country_code ==
                    SSB_SPROM1CCODE_JAPAN)
                        b43_hf_write(dev,
                                     b43_hf_read(dev) & ~B43_HF_ACPR);
@@ -2136,7 +2136,7 @@ static void default_baseband_attenuation(struct b43_wldev *dev,
 static void default_radio_attenuation(struct b43_wldev *dev,
                                      struct b43_rfatt *rf)
 {
-       struct ssb_bus *bus = dev->dev->bus;
+       struct ssb_bus *bus = dev->sdev->bus;
        struct b43_phy *phy = &dev->phy;
 
        rf->with_padmix = 0;
@@ -2384,11 +2384,11 @@ static int b43_gphy_init_tssi2dbm_table(struct b43_wldev *dev)
        struct b43_phy_g *gphy = phy->g;
        s16 pab0, pab1, pab2;
 
-       pab0 = (s16) (dev->dev->bus->sprom.pa0b0);
-       pab1 = (s16) (dev->dev->bus->sprom.pa0b1);
-       pab2 = (s16) (dev->dev->bus->sprom.pa0b2);
+       pab0 = (s16) (dev->sdev->bus->sprom.pa0b0);
+       pab1 = (s16) (dev->sdev->bus->sprom.pa0b1);
+       pab2 = (s16) (dev->sdev->bus->sprom.pa0b2);
 
-       B43_WARN_ON((dev->dev->bus->chip_id == 0x4301) &&
+       B43_WARN_ON((dev->sdev->bus->chip_id == 0x4301) &&
                    (phy->radio_ver != 0x2050)); /* Not supported anymore */
 
        gphy->dyn_tssi_tbl = 0;
@@ -2396,10 +2396,10 @@ static int b43_gphy_init_tssi2dbm_table(struct b43_wldev *dev)
        if (pab0 != 0 && pab1 != 0 && pab2 != 0 &&
            pab0 != -1 && pab1 != -1 && pab2 != -1) {
                /* The pabX values are set in SPROM. Use them. */
-               if ((s8) dev->dev->bus->sprom.itssi_bg != 0 &&
-                   (s8) dev->dev->bus->sprom.itssi_bg != -1) {
+               if ((s8) dev->sdev->bus->sprom.itssi_bg != 0 &&
+                   (s8) dev->sdev->bus->sprom.itssi_bg != -1) {
                        gphy->tgt_idle_tssi =
-                               (s8) (dev->dev->bus->sprom.itssi_bg);
+                               (s8) (dev->sdev->bus->sprom.itssi_bg);
                } else
                        gphy->tgt_idle_tssi = 62;
                gphy->tssi2dbm = b43_generate_dyn_tssi2dbm_tab(dev, pab0,
@@ -2840,7 +2840,7 @@ static void b43_gphy_op_adjust_txpower(struct b43_wldev *dev)
                                    B43_TXCTL_TXMIX;
                                rfatt += 2;
                                bbatt += 2;
-                       } else if (dev->dev->bus->sprom.
+                       } else if (dev->sdev->bus->sprom.
                                   boardflags_lo &
                                   B43_BFL_PACTRL) {
                                bbatt += 4 * (rfatt - 2);
@@ -2914,14 +2914,14 @@ static enum b43_txpwr_result b43_gphy_op_recalc_txpower(struct b43_wldev *dev,
        estimated_pwr = b43_gphy_estimate_power_out(dev, average_tssi);
 
        B43_WARN_ON(phy->type != B43_PHYTYPE_G);
-       max_pwr = dev->dev->bus->sprom.maxpwr_bg;
-       if (dev->dev->bus->sprom.boardflags_lo & B43_BFL_PACTRL)
+       max_pwr = dev->sdev->bus->sprom.maxpwr_bg;
+       if (dev->sdev->bus->sprom.boardflags_lo & B43_BFL_PACTRL)
                max_pwr -= 3; /* minus 0.75 */
        if (unlikely(max_pwr >= INT_TO_Q52(30/*dBm*/))) {
                b43warn(dev->wl,
                        "Invalid max-TX-power value in SPROM.\n");
                max_pwr = INT_TO_Q52(20); /* fake it */
-               dev->dev->bus->sprom.maxpwr_bg = max_pwr;
+               dev->sdev->bus->sprom.maxpwr_bg = max_pwr;
        }
 
        /* Get desired power (in Q5.2) */
@@ -3014,7 +3014,7 @@ static void b43_gphy_op_pwork_60sec(struct b43_wldev *dev)
 {
        struct b43_phy *phy = &dev->phy;
 
-       if (!(dev->dev->bus->sprom.boardflags_lo & B43_BFL_RSSI))
+       if (!(dev->sdev->bus->sprom.boardflags_lo & B43_BFL_RSSI))
                return;
 
        b43_mac_suspend(dev);
index fd50eb116243487f532bca9ac24623cdb1e81c93..012c8da2f9447eec120b5c3bd8d97021f4eb3c01 100644 (file)
@@ -86,7 +86,7 @@ static void b43_lpphy_op_free(struct b43_wldev *dev)
 static void lpphy_read_band_sprom(struct b43_wldev *dev)
 {
        struct b43_phy_lp *lpphy = dev->phy.lp;
-       struct ssb_bus *bus = dev->dev->bus;
+       struct ssb_bus *bus = dev->sdev->bus;
        u16 cckpo, maxpwr;
        u32 ofdmpo;
        int i;
@@ -214,7 +214,7 @@ static void lpphy_table_init(struct b43_wldev *dev)
 
 static void lpphy_baseband_rev0_1_init(struct b43_wldev *dev)
 {
-       struct ssb_bus *bus = dev->dev->bus;
+       struct ssb_bus *bus = dev->sdev->bus;
        struct b43_phy_lp *lpphy = dev->phy.lp;
        u16 tmp, tmp2;
 
@@ -412,7 +412,7 @@ static void lpphy_restore_dig_flt_state(struct b43_wldev *dev)
 
 static void lpphy_baseband_rev2plus_init(struct b43_wldev *dev)
 {
-       struct ssb_bus *bus = dev->dev->bus;
+       struct ssb_bus *bus = dev->sdev->bus;
        struct b43_phy_lp *lpphy = dev->phy.lp;
 
        b43_phy_write(dev, B43_LPPHY_AFE_DAC_CTL, 0x50);
@@ -519,7 +519,7 @@ struct b2062_freqdata {
 static void lpphy_2062_init(struct b43_wldev *dev)
 {
        struct b43_phy_lp *lpphy = dev->phy.lp;
-       struct ssb_bus *bus = dev->dev->bus;
+       struct ssb_bus *bus = dev->sdev->bus;
        u32 crystalfreq, tmp, ref;
        unsigned int i;
        const struct b2062_freqdata *fd = NULL;
@@ -697,7 +697,7 @@ static void lpphy_radio_init(struct b43_wldev *dev)
                lpphy_sync_stx(dev);
                b43_phy_write(dev, B43_PHY_OFDM(0xF0), 0x5F80);
                b43_phy_write(dev, B43_PHY_OFDM(0xF1), 0);
-               if (dev->dev->bus->chip_id == 0x4325) {
+               if (dev->sdev->bus->chip_id == 0x4325) {
                        // TODO SSB PMU recalibration
                }
        }
@@ -1289,7 +1289,7 @@ finish:
 
 static void lpphy_rev2plus_rc_calib(struct b43_wldev *dev)
 {
-       struct ssb_bus *bus = dev->dev->bus;
+       struct ssb_bus *bus = dev->sdev->bus;
        u32 crystal_freq = bus->chipco.pmu.crystalfreq * 1000;
        u8 tmp = b43_radio_read(dev, B2063_RX_BB_SP8) & 0xFF;
        int i;
@@ -1840,7 +1840,7 @@ static void lpphy_papd_cal(struct b43_wldev *dev, struct lpphy_tx_gains gains,
 static void lpphy_papd_cal_txpwr(struct b43_wldev *dev)
 {
        struct b43_phy_lp *lpphy = dev->phy.lp;
-       struct ssb_bus *bus = dev->dev->bus;
+       struct ssb_bus *bus = dev->sdev->bus;
        struct lpphy_tx_gains gains, oldgains;
        int old_txpctl, old_afe_ovr, old_rf, old_bbmult;
 
@@ -1870,7 +1870,7 @@ static int lpphy_rx_iq_cal(struct b43_wldev *dev, bool noise, bool tx,
                            bool rx, bool pa, struct lpphy_tx_gains *gains)
 {
        struct b43_phy_lp *lpphy = dev->phy.lp;
-       struct ssb_bus *bus = dev->dev->bus;
+       struct ssb_bus *bus = dev->sdev->bus;
        const struct lpphy_rx_iq_comp *iqcomp = NULL;
        struct lpphy_tx_gains nogains, oldgains;
        u16 tmp;
@@ -2408,7 +2408,7 @@ static const struct b206x_channel b2063_chantbl[] = {
 
 static void lpphy_b2062_reset_pll_bias(struct b43_wldev *dev)
 {
-       struct ssb_bus *bus = dev->dev->bus;
+       struct ssb_bus *bus = dev->sdev->bus;
 
        b43_radio_write(dev, B2062_S_RFPLL_CTL2, 0xFF);
        udelay(20);
@@ -2432,7 +2432,7 @@ static int lpphy_b2062_tune(struct b43_wldev *dev,
                            unsigned int channel)
 {
        struct b43_phy_lp *lpphy = dev->phy.lp;
-       struct ssb_bus *bus = dev->dev->bus;
+       struct ssb_bus *bus = dev->sdev->bus;
        const struct b206x_channel *chandata = NULL;
        u32 crystal_freq = bus->chipco.pmu.crystalfreq * 1000;
        u32 tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7, tmp8, tmp9;
@@ -2522,7 +2522,7 @@ static void lpphy_b2063_vco_calib(struct b43_wldev *dev)
 static int lpphy_b2063_tune(struct b43_wldev *dev,
                            unsigned int channel)
 {
-       struct ssb_bus *bus = dev->dev->bus;
+       struct ssb_bus *bus = dev->sdev->bus;
 
        static const struct b206x_channel *chandata = NULL;
        u32 crystal_freq = bus->chipco.pmu.crystalfreq * 1000;
index b075a3f82a43377e9c22a8f54bd4c43854e0c168..9ed65157bef554bcbcd1e857e3d80177a9af60bd 100644 (file)
@@ -299,7 +299,7 @@ static void b43_nphy_tx_power_ctrl(struct b43_wldev *dev, bool enable)
 static void b43_nphy_tx_power_fix(struct b43_wldev *dev)
 {
        struct b43_phy_n *nphy = dev->phy.n;
-       struct ssb_sprom *sprom = &(dev->dev->bus->sprom);
+       struct ssb_sprom *sprom = &(dev->sdev->bus->sprom);
 
        u8 txpi[2], bbmult, i;
        u16 tmp, radio_gain, dac_gain;
@@ -423,8 +423,8 @@ static void b43_radio_init2055_pre(struct b43_wldev *dev)
 static void b43_radio_init2055_post(struct b43_wldev *dev)
 {
        struct b43_phy_n *nphy = dev->phy.n;
-       struct ssb_sprom *sprom = &(dev->dev->bus->sprom);
-       struct ssb_boardinfo *binfo = &(dev->dev->bus->boardinfo);
+       struct ssb_sprom *sprom = &(dev->sdev->bus->sprom);
+       struct ssb_boardinfo *binfo = &(dev->sdev->bus->boardinfo);
        int i;
        u16 val;
        bool workaround = false;
@@ -609,12 +609,12 @@ static void b43_nphy_bmac_clock_fgc(struct b43_wldev *dev, bool force)
        if (dev->phy.type != B43_PHYTYPE_N)
                return;
 
-       tmslow = ssb_read32(dev->dev, SSB_TMSLOW);
+       tmslow = ssb_read32(dev->sdev, SSB_TMSLOW);
        if (force)
                tmslow |= SSB_TMSLOW_FGC;
        else
                tmslow &= ~SSB_TMSLOW_FGC;
-       ssb_write32(dev->dev, SSB_TMSLOW, tmslow);
+       ssb_write32(dev->sdev, SSB_TMSLOW, tmslow);
 }
 
 /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/CCA */
@@ -959,7 +959,7 @@ static void b43_nphy_superswitch_init(struct b43_wldev *dev, bool init)
                b43_phy_write(dev, B43_NPHY_GPIO_LOOEN, 0);
                b43_phy_write(dev, B43_NPHY_GPIO_HIOEN, 0);
 
-               ssb_chipco_gpio_control(&dev->dev->bus->chipco, 0xFC00,
+               ssb_chipco_gpio_control(&dev->sdev->bus->chipco, 0xFC00,
                                        0xFC00);
                b43_write32(dev, B43_MMIO_MACCTL,
                        b43_read32(dev, B43_MMIO_MACCTL) &
@@ -983,7 +983,7 @@ static u16 b43_nphy_classifier(struct b43_wldev *dev, u16 mask, u16 val)
 {
        u16 tmp;
 
-       if (dev->dev->id.revision == 16)
+       if (dev->sdev->id.revision == 16)
                b43_mac_suspend(dev);
 
        tmp = b43_phy_read(dev, B43_NPHY_CLASSCTL);
@@ -993,7 +993,7 @@ static u16 b43_nphy_classifier(struct b43_wldev *dev, u16 mask, u16 val)
        tmp |= (val & mask);
        b43_phy_maskset(dev, B43_NPHY_CLASSCTL, 0xFFF8, tmp);
 
-       if (dev->dev->id.revision == 16)
+       if (dev->sdev->id.revision == 16)
                b43_mac_enable(dev);
 
        return tmp;
@@ -1168,7 +1168,7 @@ static void b43_nphy_adjust_lna_gain_table(struct b43_wldev *dev)
 static void b43_nphy_gain_ctrl_workarounds(struct b43_wldev *dev)
 {
        struct b43_phy_n *nphy = dev->phy.n;
-       struct ssb_sprom *sprom = &(dev->dev->bus->sprom);
+       struct ssb_sprom *sprom = &(dev->sdev->bus->sprom);
 
        /* PHY rev 0, 1, 2 */
        u8 i, j;
@@ -1373,7 +1373,7 @@ static void b43_nphy_gain_ctrl_workarounds(struct b43_wldev *dev)
 /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/Workarounds */
 static void b43_nphy_workarounds(struct b43_wldev *dev)
 {
-       struct ssb_bus *bus = dev->dev->bus;
+       struct ssb_bus *bus = dev->sdev->bus;
        struct b43_phy *phy = &dev->phy;
        struct b43_phy_n *nphy = phy->n;
 
@@ -3586,7 +3586,7 @@ static void b43_nphy_set_rx_core_state(struct b43_wldev *dev, u8 mask)
  */
 int b43_phy_initn(struct b43_wldev *dev)
 {
-       struct ssb_bus *bus = dev->dev->bus;
+       struct ssb_bus *bus = dev->sdev->bus;
        struct b43_phy *phy = &dev->phy;
        struct b43_phy_n *nphy = phy->n;
        u8 tx_pwr_state;
@@ -3601,7 +3601,7 @@ int b43_phy_initn(struct b43_wldev *dev)
        if ((dev->phy.rev >= 3) &&
           (bus->sprom.boardflags_lo & B43_BFL_EXTLNA) &&
           (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ)) {
-               chipco_set32(&dev->dev->bus->chipco, SSB_CHIPCO_CHIPCTL, 0x40);
+               chipco_set32(&dev->sdev->bus->chipco, SSB_CHIPCO_CHIPCTL, 0x40);
        }
        nphy->deaf_count = 0;
        b43_nphy_tables_init(dev);
index aa12273ae716482544f71f0733beb8d70c45ff84..72ab94df7569e79696e475470a33978c3c49c834 100644 (file)
@@ -111,7 +111,7 @@ static u16 index_to_pioqueue_base(struct b43_wldev *dev,
                B43_MMIO_PIO11_BASE5,
        };
 
-       if (dev->dev->id.revision >= 11) {
+       if (dev->sdev->id.revision >= 11) {
                B43_WARN_ON(index >= ARRAY_SIZE(bases_rev11));
                return bases_rev11[index];
        }
@@ -121,14 +121,14 @@ static u16 index_to_pioqueue_base(struct b43_wldev *dev,
 
 static u16 pio_txqueue_offset(struct b43_wldev *dev)
 {
-       if (dev->dev->id.revision >= 11)
+       if (dev->sdev->id.revision >= 11)
                return 0x18;
        return 0;
 }
 
 static u16 pio_rxqueue_offset(struct b43_wldev *dev)
 {
-       if (dev->dev->id.revision >= 11)
+       if (dev->sdev->id.revision >= 11)
                return 0x38;
        return 8;
 }
@@ -144,7 +144,7 @@ static struct b43_pio_txqueue *b43_setup_pioqueue_tx(struct b43_wldev *dev,
        if (!q)
                return NULL;
        q->dev = dev;
-       q->rev = dev->dev->id.revision;
+       q->rev = dev->sdev->id.revision;
        q->mmio_base = index_to_pioqueue_base(dev, index) +
                       pio_txqueue_offset(dev);
        q->index = index;
@@ -178,7 +178,7 @@ static struct b43_pio_rxqueue *b43_setup_pioqueue_rx(struct b43_wldev *dev,
        if (!q)
                return NULL;
        q->dev = dev;
-       q->rev = dev->dev->id.revision;
+       q->rev = dev->sdev->id.revision;
        q->mmio_base = index_to_pioqueue_base(dev, index) +
                       pio_rxqueue_offset(dev);
 
@@ -339,7 +339,7 @@ static u16 tx_write_2byte_queue(struct b43_pio_txqueue *q,
        ctl |= B43_PIO_TXCTL_WRITELO | B43_PIO_TXCTL_WRITEHI;
        b43_piotx_write16(q, B43_PIO_TXCTL, ctl);
 
-       ssb_block_write(dev->dev, data, (data_len & ~1),
+       b43_block_write(dev, data, (data_len & ~1),
                        q->mmio_base + B43_PIO_TXDATA,
                        sizeof(u16));
        if (data_len & 1) {
@@ -351,7 +351,7 @@ static u16 tx_write_2byte_queue(struct b43_pio_txqueue *q,
                b43_piotx_write16(q, B43_PIO_TXCTL, ctl);
                tail[0] = data[data_len - 1];
                tail[1] = 0;
-               ssb_block_write(dev->dev, tail, 2,
+               b43_block_write(dev, tail, 2,
                                q->mmio_base + B43_PIO_TXDATA,
                                sizeof(u16));
        }
@@ -393,7 +393,7 @@ static u32 tx_write_4byte_queue(struct b43_pio_txqueue *q,
               B43_PIO8_TXCTL_16_23 | B43_PIO8_TXCTL_24_31;
        b43_piotx_write32(q, B43_PIO8_TXCTL, ctl);
 
-       ssb_block_write(dev->dev, data, (data_len & ~3),
+       b43_block_write(dev, data, (data_len & ~3),
                        q->mmio_base + B43_PIO8_TXDATA,
                        sizeof(u32));
        if (data_len & 3) {
@@ -421,7 +421,7 @@ static u32 tx_write_4byte_queue(struct b43_pio_txqueue *q,
                        break;
                }
                b43_piotx_write32(q, B43_PIO8_TXCTL, ctl);
-               ssb_block_write(dev->dev, tail, 4,
+               b43_block_write(dev, tail, 4,
                                q->mmio_base + B43_PIO8_TXDATA,
                                sizeof(u32));
        }
@@ -657,11 +657,11 @@ data_ready:
 
        /* Get the preamble (RX header) */
        if (q->rev >= 8) {
-               ssb_block_read(dev->dev, rxhdr, sizeof(*rxhdr),
+               b43_block_read(dev, rxhdr, sizeof(*rxhdr),
                               q->mmio_base + B43_PIO8_RXDATA,
                               sizeof(u32));
        } else {
-               ssb_block_read(dev->dev, rxhdr, sizeof(*rxhdr),
+               b43_block_read(dev, rxhdr, sizeof(*rxhdr),
                               q->mmio_base + B43_PIO_RXDATA,
                               sizeof(u16));
        }
@@ -697,7 +697,7 @@ data_ready:
        skb_reserve(skb, 2);
        skb_put(skb, len + padding);
        if (q->rev >= 8) {
-               ssb_block_read(dev->dev, skb->data + padding, (len & ~3),
+               b43_block_read(dev, skb->data + padding, (len & ~3),
                               q->mmio_base + B43_PIO8_RXDATA,
                               sizeof(u32));
                if (len & 3) {
@@ -705,7 +705,7 @@ data_ready:
                        BUILD_BUG_ON(sizeof(wl->pio_tailspace) < 4);
 
                        /* Read the last few bytes. */
-                       ssb_block_read(dev->dev, tail, 4,
+                       b43_block_read(dev, tail, 4,
                                       q->mmio_base + B43_PIO8_RXDATA,
                                       sizeof(u32));
                        switch (len & 3) {
@@ -724,7 +724,7 @@ data_ready:
                        }
                }
        } else {
-               ssb_block_read(dev->dev, skb->data + padding, (len & ~1),
+               b43_block_read(dev, skb->data + padding, (len & ~1),
                               q->mmio_base + B43_PIO_RXDATA,
                               sizeof(u16));
                if (len & 1) {
@@ -732,7 +732,7 @@ data_ready:
                        BUILD_BUG_ON(sizeof(wl->pio_tailspace) < 2);
 
                        /* Read the last byte. */
-                       ssb_block_read(dev->dev, tail, 2,
+                       b43_block_read(dev, tail, 2,
                                       q->mmio_base + B43_PIO_RXDATA,
                                       sizeof(u16));
                        skb->data[len + padding - 1] = tail[0];
index 86bc0a0f735cf63fd0218b3628af061a238b77bc..a617efe38289d1157ccccc78fca85dda73b52e5a 100644 (file)
@@ -37,7 +37,7 @@ void b43_rfkill_poll(struct ieee80211_hw *hw)
 {
        struct b43_wl *wl = hw_to_b43_wl(hw);
        struct b43_wldev *dev = wl->current_dev;
-       struct ssb_bus *bus = dev->dev->bus;
+       struct ssb_bus *bus = dev->sdev->bus;
        bool enabled;
        bool brought_up = false;
 
@@ -47,7 +47,7 @@ void b43_rfkill_poll(struct ieee80211_hw *hw)
                        mutex_unlock(&wl->mutex);
                        return;
                }
-               ssb_device_enable(dev->dev, 0);
+               ssb_device_enable(dev->sdev, 0);
                brought_up = true;
        }
 
@@ -63,7 +63,7 @@ void b43_rfkill_poll(struct ieee80211_hw *hw)
        }
 
        if (brought_up) {
-               ssb_device_disable(dev->dev, 0);
+               ssb_device_disable(dev->sdev, 0);
                ssb_bus_may_powerdown(bus);
        }
 
index 09e2dfd7b175a74534de12fe240761f7a3138302..808e25b79703a0151cab0bd46317523768ca160b 100644 (file)
@@ -66,7 +66,7 @@ static void b43_sdio_interrupt_dispatcher(struct sdio_func *func)
 int b43_sdio_request_irq(struct b43_wldev *dev,
                         void (*handler)(struct b43_wldev *dev))
 {
-       struct ssb_bus *bus = dev->dev->bus;
+       struct ssb_bus *bus = dev->sdev->bus;
        struct sdio_func *func = bus->host_sdio;
        struct b43_sdio *sdio = sdio_get_drvdata(func);
        int err;
@@ -82,7 +82,7 @@ int b43_sdio_request_irq(struct b43_wldev *dev,
 
 void b43_sdio_free_irq(struct b43_wldev *dev)
 {
-       struct ssb_bus *bus = dev->dev->bus;
+       struct ssb_bus *bus = dev->sdev->bus;
        struct sdio_func *func = bus->host_sdio;
        struct b43_sdio *sdio = sdio_get_drvdata(func);
 
index f1ae4e05a32cf3b77b356dbf2ea97b56b6e72c68..57af619725c3e12c3716cae0e0fd7369ae8bcd8a 100644 (file)
@@ -140,7 +140,7 @@ static DEVICE_ATTR(interference, 0644,
 
 int b43_sysfs_register(struct b43_wldev *wldev)
 {
-       struct device *dev = wldev->dev->dev;
+       struct device *dev = wldev->sdev->dev;
 
        B43_WARN_ON(b43_status(wldev) != B43_STAT_INITIALIZED);
 
@@ -149,7 +149,7 @@ int b43_sysfs_register(struct b43_wldev *wldev)
 
 void b43_sysfs_unregister(struct b43_wldev *wldev)
 {
-       struct device *dev = wldev->dev->dev;
+       struct device *dev = wldev->sdev->dev;
 
        device_remove_file(dev, &dev_attr_interference);
 }
index 61027ee84fb537dd2e0276ef518ac66d180907e1..59df3c64af6339e69684a3f048622abac960472f 100644 (file)
@@ -2304,7 +2304,7 @@ void lpphy_rev0_1_table_init(struct b43_wldev *dev)
 
 void lpphy_rev2plus_table_init(struct b43_wldev *dev)
 {
-       struct ssb_bus *bus = dev->dev->bus;
+       struct ssb_bus *bus = dev->sdev->bus;
        int i;
 
        B43_WARN_ON(dev->phy.rev < 2);
@@ -2416,7 +2416,7 @@ void lpphy_write_gain_table_bulk(struct b43_wldev *dev, int offset, int count,
 
 void lpphy_init_tx_gain_table(struct b43_wldev *dev)
 {
-       struct ssb_bus *bus = dev->dev->bus;
+       struct ssb_bus *bus = dev->sdev->bus;
 
        switch (dev->phy.rev) {
        case 0:
index 9a335da65b423129c54c8245dcdbf890fd531701..8f4db448ec3308a1e6f2ccad03a1277f59e6f610 100644 (file)
@@ -458,7 +458,7 @@ static void b43_wa_rssi_adc(struct b43_wldev *dev)
 
 static void b43_wa_boards_a(struct b43_wldev *dev)
 {
-       struct ssb_bus *bus = dev->dev->bus;
+       struct ssb_bus *bus = dev->sdev->bus;
 
        if (bus->boardinfo.vendor == SSB_BOARDVENDOR_BCM &&
            bus->boardinfo.type == SSB_BOARD_BU4306 &&
@@ -486,7 +486,7 @@ static void b43_wa_boards_a(struct b43_wldev *dev)
 
 static void b43_wa_boards_g(struct b43_wldev *dev)
 {
-       struct ssb_bus *bus = dev->dev->bus;
+       struct ssb_bus *bus = dev->sdev->bus;
        struct b43_phy *phy = &dev->phy;
 
        if (bus->boardinfo.vendor != SSB_BOARDVENDOR_BCM ||
index e5be381c17bce02ff4e43269f56c80feb787a8b4..c8f99aebe01f6565a798ef67952bb7cc9c4722c7 100644 (file)
@@ -547,7 +547,7 @@ static s8 b43_rssi_postprocess(struct b43_wldev *dev,
                        else
                                tmp -= 3;
                } else {
-                       if (dev->dev->bus->sprom.
+                       if (dev->sdev->bus->sprom.
                            boardflags_lo & B43_BFL_RSSI) {
                                if (in_rssi > 63)
                                        in_rssi = 63;
index b4c81931e136b376c8fa3ec5b1634c719591106e..61d4a11f566b4f9e9864f1109369eade4634c50a 100644 (file)
@@ -171,10 +171,6 @@ static int iwl1000_hw_set_hw_params(struct iwl_priv *priv)
 
 static struct iwl_lib_ops iwl1000_lib = {
        .set_hw_params = iwl1000_hw_set_hw_params,
-       .txq_set_sched = iwlagn_txq_set_sched,
-       .txq_attach_buf_to_tfd = iwl_hw_txq_attach_buf_to_tfd,
-       .txq_free_tfd = iwl_hw_txq_free_tfd,
-       .txq_init = iwl_hw_tx_queue_init,
        .rx_handler_setup = iwlagn_rx_handler_setup,
        .setup_deferred_work = iwlagn_setup_deferred_work,
        .is_valid_rtc_data_addr = iwlagn_hw_valid_rtc_data_addr,
index 89b8da7a6c8bc9ce2d5811a6dd075448ee1237e6..86feec86d13009c9b6266cd7bf102b8f3195af94 100644 (file)
@@ -195,9 +195,9 @@ static int iwl2030_hw_channel_switch(struct iwl_priv *priv,
        struct ieee80211_vif *vif = ctx->vif;
        struct iwl_host_cmd hcmd = {
                .id = REPLY_CHANNEL_SWITCH,
-               .len = sizeof(cmd),
+               .len = { sizeof(cmd), },
                .flags = CMD_SYNC,
-               .data = &cmd,
+               .data = { &cmd, },
        };
 
        cmd.band = priv->band == IEEE80211_BAND_2GHZ;
@@ -252,10 +252,6 @@ static int iwl2030_hw_channel_switch(struct iwl_priv *priv,
 
 static struct iwl_lib_ops iwl2000_lib = {
        .set_hw_params = iwl2000_hw_set_hw_params,
-       .txq_set_sched = iwlagn_txq_set_sched,
-       .txq_attach_buf_to_tfd = iwl_hw_txq_attach_buf_to_tfd,
-       .txq_free_tfd = iwl_hw_txq_free_tfd,
-       .txq_init = iwl_hw_tx_queue_init,
        .rx_handler_setup = iwlagn_rx_handler_setup,
        .setup_deferred_work = iwlagn_bt_setup_deferred_work,
        .cancel_deferred_work = iwlagn_bt_cancel_deferred_work,
index 98f81df166e399ecbf674d53e603c7f00db2fd47..a70b8cfafda195a3b92e1f46d2a7e617c3faba0f 100644 (file)
@@ -282,9 +282,9 @@ static int iwl5000_hw_channel_switch(struct iwl_priv *priv,
        struct ieee80211_vif *vif = ctx->vif;
        struct iwl_host_cmd hcmd = {
                .id = REPLY_CHANNEL_SWITCH,
-               .len = sizeof(cmd),
+               .len = { sizeof(cmd), },
                .flags = CMD_SYNC,
-               .data = &cmd,
+               .data = { &cmd, },
        };
 
        cmd.band = priv->band == IEEE80211_BAND_2GHZ;
@@ -339,10 +339,6 @@ static int iwl5000_hw_channel_switch(struct iwl_priv *priv,
 
 static struct iwl_lib_ops iwl5000_lib = {
        .set_hw_params = iwl5000_hw_set_hw_params,
-       .txq_set_sched = iwlagn_txq_set_sched,
-       .txq_attach_buf_to_tfd = iwl_hw_txq_attach_buf_to_tfd,
-       .txq_free_tfd = iwl_hw_txq_free_tfd,
-       .txq_init = iwl_hw_tx_queue_init,
        .rx_handler_setup = iwlagn_rx_handler_setup,
        .setup_deferred_work = iwlagn_setup_deferred_work,
        .is_valid_rtc_data_addr = iwlagn_hw_valid_rtc_data_addr,
@@ -374,10 +370,6 @@ static struct iwl_lib_ops iwl5000_lib = {
 
 static struct iwl_lib_ops iwl5150_lib = {
        .set_hw_params = iwl5150_hw_set_hw_params,
-       .txq_set_sched = iwlagn_txq_set_sched,
-       .txq_attach_buf_to_tfd = iwl_hw_txq_attach_buf_to_tfd,
-       .txq_free_tfd = iwl_hw_txq_free_tfd,
-       .txq_init = iwl_hw_tx_queue_init,
        .rx_handler_setup = iwlagn_rx_handler_setup,
        .setup_deferred_work = iwlagn_setup_deferred_work,
        .is_valid_rtc_data_addr = iwlagn_hw_valid_rtc_data_addr,
index a7921f9a03c62488475ee76234918ced431b01b6..f8c710db6e6f90345a8a1f42e7ce1b2d8a7d85aa 100644 (file)
@@ -221,9 +221,9 @@ static int iwl6000_hw_channel_switch(struct iwl_priv *priv,
        struct ieee80211_vif *vif = ctx->vif;
        struct iwl_host_cmd hcmd = {
                .id = REPLY_CHANNEL_SWITCH,
-               .len = sizeof(cmd),
+               .len = { sizeof(cmd), },
                .flags = CMD_SYNC,
-               .data = &cmd,
+               .data = { &cmd, },
        };
 
        cmd.band = priv->band == IEEE80211_BAND_2GHZ;
@@ -278,10 +278,6 @@ static int iwl6000_hw_channel_switch(struct iwl_priv *priv,
 
 static struct iwl_lib_ops iwl6000_lib = {
        .set_hw_params = iwl6000_hw_set_hw_params,
-       .txq_set_sched = iwlagn_txq_set_sched,
-       .txq_attach_buf_to_tfd = iwl_hw_txq_attach_buf_to_tfd,
-       .txq_free_tfd = iwl_hw_txq_free_tfd,
-       .txq_init = iwl_hw_tx_queue_init,
        .rx_handler_setup = iwlagn_rx_handler_setup,
        .setup_deferred_work = iwlagn_setup_deferred_work,
        .is_valid_rtc_data_addr = iwlagn_hw_valid_rtc_data_addr,
@@ -314,10 +310,6 @@ static struct iwl_lib_ops iwl6000_lib = {
 
 static struct iwl_lib_ops iwl6030_lib = {
        .set_hw_params = iwl6000_hw_set_hw_params,
-       .txq_set_sched = iwlagn_txq_set_sched,
-       .txq_attach_buf_to_tfd = iwl_hw_txq_attach_buf_to_tfd,
-       .txq_free_tfd = iwl_hw_txq_free_tfd,
-       .txq_init = iwl_hw_tx_queue_init,
        .rx_handler_setup = iwlagn_bt_rx_handler_setup,
        .setup_deferred_work = iwlagn_bt_setup_deferred_work,
        .cancel_deferred_work = iwlagn_bt_cancel_deferred_work,
index 0f6bb9b2e642610a56e260812be037d18b1bd34b..d39efcce8ba71afcf2bbcc0764d17ff7988518c9 100644 (file)
@@ -87,14 +87,14 @@ int iwl_send_calib_results(struct iwl_priv *priv)
 
        struct iwl_host_cmd hcmd = {
                .id = REPLY_PHY_CALIBRATION_CMD,
-               .flags = CMD_SIZE_HUGE,
        };
 
        for (i = 0; i < IWL_CALIB_MAX; i++) {
                if ((BIT(i) & priv->hw_params.calib_init_cfg) &&
                    priv->calib_results[i].buf) {
-                       hcmd.len = priv->calib_results[i].buf_len;
-                       hcmd.data = priv->calib_results[i].buf;
+                       hcmd.len[0] = priv->calib_results[i].buf_len;
+                       hcmd.data[0] = priv->calib_results[i].buf;
+                       hcmd.dataflags[0] = IWL_HCMD_DFL_NOCOPY;
                        ret = iwl_send_cmd_sync(priv, &hcmd);
                        if (ret) {
                                IWL_ERR(priv, "Error %d iteration %d\n",
@@ -456,9 +456,9 @@ static int iwl_sensitivity_write(struct iwl_priv *priv)
        struct iwl_sensitivity_data *data = NULL;
        struct iwl_host_cmd cmd_out = {
                .id = SENSITIVITY_CMD,
-               .len = sizeof(struct iwl_sensitivity_cmd),
+               .len = { sizeof(struct iwl_sensitivity_cmd), },
                .flags = CMD_ASYNC,
-               .data = &cmd,
+               .data = { &cmd, },
        };
 
        data = &(priv->sensitivity_data);
@@ -491,9 +491,9 @@ static int iwl_enhance_sensitivity_write(struct iwl_priv *priv)
        struct iwl_sensitivity_data *data = NULL;
        struct iwl_host_cmd cmd_out = {
                .id = SENSITIVITY_CMD,
-               .len = sizeof(struct iwl_enhance_sensitivity_cmd),
+               .len = { sizeof(struct iwl_enhance_sensitivity_cmd), },
                .flags = CMD_ASYNC,
-               .data = &cmd,
+               .data = { &cmd, },
        };
 
        data = &(priv->sensitivity_data);
index 8e79653aed9aa799eb169713d2cde2843e920ec7..f803fb62f8bc0abee7a41d3d09ec3bdd35895cbe 100644 (file)
@@ -1140,8 +1140,7 @@ int iwlagn_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif)
 {
        struct iwl_host_cmd cmd = {
                .id = REPLY_SCAN_CMD,
-               .len = sizeof(struct iwl_scan_cmd),
-               .flags = CMD_SIZE_HUGE,
+               .len = { sizeof(struct iwl_scan_cmd), },
        };
        struct iwl_scan_cmd *scan;
        struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS];
@@ -1425,10 +1424,11 @@ int iwlagn_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif)
                return -EIO;
        }
 
-       cmd.len += le16_to_cpu(scan->tx_cmd.len) +
+       cmd.len[0] += le16_to_cpu(scan->tx_cmd.len) +
            scan->channel_count * sizeof(struct iwl_scan_channel);
-       cmd.data = scan;
-       scan->len = cpu_to_le16(cmd.len);
+       cmd.data[0] = scan;
+       cmd.dataflags[0] = IWL_HCMD_DFL_NOCOPY;
+       scan->len = cpu_to_le16(cmd.len[0]);
 
        /* set scan bit here for PAN params */
        set_bit(STATUS_SCAN_HW, &priv->status);
@@ -1520,9 +1520,9 @@ int iwlagn_txfifo_flush(struct iwl_priv *priv, u16 flush_control)
        struct iwl_txfifo_flush_cmd flush_cmd;
        struct iwl_host_cmd cmd = {
                .id = REPLY_TXFIFO_FLUSH,
-               .len = sizeof(struct iwl_txfifo_flush_cmd),
+               .len = { sizeof(struct iwl_txfifo_flush_cmd), },
                .flags = CMD_SYNC,
-               .data = &flush_cmd,
+               .data = { &flush_cmd, },
        };
 
        might_sleep();
index 91f26556ac23880ca98461d5fa9b1975f1688d18..592b0cfcf717a7a9f76af9515ae77481dfda47bb 100644 (file)
@@ -335,6 +335,32 @@ static u8 rs_tl_add_packet(struct iwl_lq_sta *lq_data,
        return tid;
 }
 
+#ifdef CONFIG_MAC80211_DEBUGFS
+static void rs_program_fix_rate(struct iwl_priv *priv,
+                               struct iwl_lq_sta *lq_sta)
+{
+       struct iwl_station_priv *sta_priv =
+               container_of(lq_sta, struct iwl_station_priv, lq_sta);
+       struct iwl_rxon_context *ctx = sta_priv->common.ctx;
+
+       lq_sta->active_legacy_rate = 0x0FFF;    /* 1 - 54 MBits, includes CCK */
+       lq_sta->active_siso_rate   = 0x1FD0;    /* 6 - 60 MBits, no 9, no CCK */
+       lq_sta->active_mimo2_rate  = 0x1FD0;    /* 6 - 60 MBits, no 9, no CCK */
+       lq_sta->active_mimo3_rate  = 0x1FD0;    /* 6 - 60 MBits, no 9, no CCK */
+
+       lq_sta->dbg_fixed_rate = priv->dbg_fixed_rate;
+
+       IWL_DEBUG_RATE(priv, "sta_id %d rate 0x%X\n",
+               lq_sta->lq.sta_id, priv->dbg_fixed_rate);
+
+       if (priv->dbg_fixed_rate) {
+               rs_fill_link_cmd(NULL, lq_sta, priv->dbg_fixed_rate);
+               iwl_send_lq_cmd(lq_sta->drv, ctx, &lq_sta->lq, CMD_ASYNC,
+                               false);
+       }
+}
+#endif
+
 /*
        get the traffic load value for tid
 */
@@ -1046,7 +1072,10 @@ done:
        /* See if there's a better rate or modulation mode to try. */
        if (sta && sta->supp_rates[sband->band])
                rs_rate_scale_perform(priv, skb, sta, lq_sta);
-
+#ifdef CONFIG_MAC80211_DEBUGFS
+       if (priv->dbg_fixed_rate != lq_sta->dbg_fixed_rate)
+               rs_program_fix_rate(priv, lq_sta);
+#endif
        if (priv->cfg->bt_params && priv->cfg->bt_params->advanced_bt_coexist)
                rs_bt_update_lq(priv, ctx, lq_sta);
 }
@@ -2170,11 +2199,11 @@ static void rs_stay_in_table(struct iwl_lq_sta *lq_sta, bool force_search)
  * setup rate table in uCode
  * return rate_n_flags as used in the table
  */
-static u32 rs_update_rate_tbl(struct iwl_priv *priv,
-                             struct iwl_rxon_context *ctx,
-                               struct iwl_lq_sta *lq_sta,
-                               struct iwl_scale_tbl_info *tbl,
-                               int index, u8 is_green)
+static void rs_update_rate_tbl(struct iwl_priv *priv,
+                              struct iwl_rxon_context *ctx,
+                              struct iwl_lq_sta *lq_sta,
+                              struct iwl_scale_tbl_info *tbl,
+                              int index, u8 is_green)
 {
        u32 rate;
 
@@ -2182,8 +2211,6 @@ static u32 rs_update_rate_tbl(struct iwl_priv *priv,
        rate = rate_n_flags_from_tbl(priv, tbl, index, is_green);
        rs_fill_link_cmd(priv, lq_sta, rate);
        iwl_send_lq_cmd(priv, ctx, &lq_sta->lq, CMD_ASYNC, false);
-
-       return rate;
 }
 
 /*
@@ -2212,7 +2239,6 @@ static void rs_rate_scale_perform(struct iwl_priv *priv,
        u8 update_lq = 0;
        struct iwl_scale_tbl_info *tbl, *tbl1;
        u16 rate_scale_index_msk = 0;
-       u32 rate;
        u8 is_green = 0;
        u8 active_tbl = 0;
        u8 done_search = 0;
@@ -2299,8 +2325,8 @@ static void rs_rate_scale_perform(struct iwl_priv *priv,
                        tbl = &(lq_sta->lq_info[lq_sta->active_tbl]);
                        /* get "active" rate info */
                        index = iwl_hwrate_to_plcp_idx(tbl->current_rate);
-                       rate = rs_update_rate_tbl(priv, ctx, lq_sta,
-                                                 tbl, index, is_green);
+                       rs_update_rate_tbl(priv, ctx, lq_sta, tbl,
+                                          index, is_green);
                }
                return;
        }
@@ -2541,8 +2567,7 @@ static void rs_rate_scale_perform(struct iwl_priv *priv,
 lq_update:
        /* Replace uCode's rate table for the destination station. */
        if (update_lq)
-               rate = rs_update_rate_tbl(priv, ctx, lq_sta,
-                                         tbl, index, is_green);
+               rs_update_rate_tbl(priv, ctx, lq_sta, tbl, index, is_green);
 
        if (iwl_tx_ant_restriction(priv) == IWL_ANT_OK_MULTI) {
                /* Should we stay with this modulation mode,
@@ -2871,6 +2896,7 @@ void iwl_rs_rate_init(struct iwl_priv *priv, struct ieee80211_sta *sta, u8 sta_i
                lq_sta->last_txrate_idx += IWL_FIRST_OFDM_RATE;
        lq_sta->is_agg = 0;
 
+       priv->dbg_fixed_rate = 0;
 #ifdef CONFIG_MAC80211_DEBUGFS
        lq_sta->dbg_fixed_rate = 0;
 #endif
@@ -3045,7 +3071,6 @@ static void rs_free_sta(void *priv_r, struct ieee80211_sta *sta,
        IWL_DEBUG_RATE(priv, "leave\n");
 }
 
-
 #ifdef CONFIG_MAC80211_DEBUGFS
 static int open_file_generic(struct inode *inode, struct file *file)
 {
@@ -3070,6 +3095,7 @@ static void rs_dbgfs_set_mcs(struct iwl_lq_sta *lq_sta,
                        IWL_DEBUG_RATE(priv, "Fixed rate ON\n");
                } else {
                        lq_sta->dbg_fixed_rate = 0;
+                       priv->dbg_fixed_rate = 0;
                        IWL_ERR(priv,
                            "Invalid antenna selection 0x%X, Valid is 0x%X\n",
                            ant_sel_tx, valid_tx_ant);
@@ -3088,9 +3114,7 @@ static ssize_t rs_sta_dbgfs_scale_table_write(struct file *file,
        char buf[64];
        size_t buf_size;
        u32 parsed_rate;
-       struct iwl_station_priv *sta_priv =
-               container_of(lq_sta, struct iwl_station_priv, lq_sta);
-       struct iwl_rxon_context *ctx = sta_priv->common.ctx;
+
 
        priv = lq_sta->drv;
        memset(buf, 0, sizeof(buf));
@@ -3099,23 +3123,11 @@ static ssize_t rs_sta_dbgfs_scale_table_write(struct file *file,
                return -EFAULT;
 
        if (sscanf(buf, "%x", &parsed_rate) == 1)
-               lq_sta->dbg_fixed_rate = parsed_rate;
+               priv->dbg_fixed_rate = lq_sta->dbg_fixed_rate = parsed_rate;
        else
-               lq_sta->dbg_fixed_rate = 0;
+               priv->dbg_fixed_rate = lq_sta->dbg_fixed_rate = 0;
 
-       lq_sta->active_legacy_rate = 0x0FFF;    /* 1 - 54 MBits, includes CCK */
-       lq_sta->active_siso_rate   = 0x1FD0;    /* 6 - 60 MBits, no 9, no CCK */
-       lq_sta->active_mimo2_rate  = 0x1FD0;    /* 6 - 60 MBits, no 9, no CCK */
-       lq_sta->active_mimo3_rate  = 0x1FD0;    /* 6 - 60 MBits, no 9, no CCK */
-
-       IWL_DEBUG_RATE(priv, "sta_id %d rate 0x%X\n",
-               lq_sta->lq.sta_id, lq_sta->dbg_fixed_rate);
-
-       if (lq_sta->dbg_fixed_rate) {
-               rs_fill_link_cmd(NULL, lq_sta, lq_sta->dbg_fixed_rate);
-               iwl_send_lq_cmd(lq_sta->drv, ctx, &lq_sta->lq, CMD_ASYNC,
-                               false);
-       }
+       rs_program_fix_rate(priv, lq_sta);
 
        return count;
 }
@@ -3143,7 +3155,7 @@ static ssize_t rs_sta_dbgfs_scale_table_read(struct file *file,
                        lq_sta->total_failed, lq_sta->total_success,
                        lq_sta->active_legacy_rate);
        desc += sprintf(buff+desc, "fixed rate 0x%X\n",
-                       lq_sta->dbg_fixed_rate);
+                       priv->dbg_fixed_rate);
        desc += sprintf(buff+desc, "valid_tx_ant %s%s%s\n",
            (priv->hw_params.valid_tx_ant & ANT_A) ? "ANT_A," : "",
            (priv->hw_params.valid_tx_ant & ANT_B) ? "ANT_B," : "",
@@ -3254,14 +3266,10 @@ static const struct file_operations rs_sta_dbgfs_stats_table_ops = {
 static ssize_t rs_sta_dbgfs_rate_scale_data_read(struct file *file,
                        char __user *user_buf, size_t count, loff_t *ppos)
 {
-       char buff[120];
-       int desc = 0;
-
        struct iwl_lq_sta *lq_sta = file->private_data;
-       struct iwl_priv *priv;
        struct iwl_scale_tbl_info *tbl = &lq_sta->lq_info[lq_sta->active_tbl];
-
-       priv = lq_sta->drv;
+       char buff[120];
+       int desc = 0;
 
        if (is_Ht(tbl->lq_type))
                desc += sprintf(buff+desc,
index 02387430f7fe0dddae5006aa80e59301c19ecaec..a95ad84c537752c7c2c9491cc29eb8531c841b38 100644 (file)
@@ -289,7 +289,6 @@ int iwlagn_commit_rxon(struct iwl_priv *priv, struct iwl_rxon_context *ctx)
        /* cast away the const for active_rxon in this function */
        struct iwl_rxon_cmd *active = (void *)&ctx->active;
        bool new_assoc = !!(ctx->staging.filter_flags & RXON_FILTER_ASSOC_MSK);
-       bool old_assoc = !!(ctx->active.filter_flags & RXON_FILTER_ASSOC_MSK);
        int ret;
 
        lockdep_assert_held(&priv->mutex);
@@ -389,11 +388,9 @@ int iwlagn_commit_rxon(struct iwl_priv *priv, struct iwl_rxon_context *ctx)
         * AP station must be done after the BSSID is set to correctly
         * set up filters in the device.
         */
-       if ((old_assoc && new_assoc) || !new_assoc) {
-               ret = iwlagn_rxon_disconn(priv, ctx);
-               if (ret)
-                       return ret;
-       }
+       ret = iwlagn_rxon_disconn(priv, ctx);
+       if (ret)
+               return ret;
 
        if (new_assoc)
                return iwlagn_rxon_connect(priv, ctx);
index 079275f2c64d919102b40c97ad3900ba79899265..0bd722cee5ae0cf3a3f2c8429fa07aa118bfbacf 100644 (file)
@@ -144,7 +144,7 @@ static int iwl_send_static_wepkey_cmd(struct iwl_priv *priv,
        size_t cmd_size  = sizeof(struct iwl_wep_cmd);
        struct iwl_host_cmd cmd = {
                .id = ctx->wep_key_cmd,
-               .data = wep_cmd,
+               .data = { wep_cmd, },
                .flags = CMD_SYNC,
        };
 
@@ -172,7 +172,7 @@ static int iwl_send_static_wepkey_cmd(struct iwl_priv *priv,
 
        cmd_size += sizeof(struct iwl_wep_key) * WEP_KEYS_MAX;
 
-       cmd.len = cmd_size;
+       cmd.len[0] = cmd_size;
 
        if (not_empty || send_if_empty)
                return iwl_send_cmd(priv, &cmd);
index 342de780a3661dd08f8c41e79eaacfa0f3dbe356..4974cd7837cbecb92a40f6d757eaa42a75235024 100644 (file)
@@ -755,12 +755,10 @@ int iwlagn_tx_skb(struct iwl_priv *priv, struct sk_buff *skb)
        spin_unlock(&priv->sta_lock);
 
        /* Attach buffers to TFD */
-       priv->cfg->ops->lib->txq_attach_buf_to_tfd(priv, txq,
-                                                  txcmd_phys, firstlen, 1, 0);
+       iwlagn_txq_attach_buf_to_tfd(priv, txq, txcmd_phys, firstlen, 1);
        if (secondlen > 0)
-               priv->cfg->ops->lib->txq_attach_buf_to_tfd(priv, txq,
-                                                          phys_addr, secondlen,
-                                                          0, 0);
+               iwlagn_txq_attach_buf_to_tfd(priv, txq, phys_addr,
+                                            secondlen, 0);
 
        scratch_phys = txcmd_phys + sizeof(struct iwl_cmd_header) +
                                offsetof(struct iwl_tx_cmd, scratch);
@@ -916,7 +914,7 @@ int iwlagn_txq_ctx_alloc(struct iwl_priv *priv)
        spin_lock_irqsave(&priv->lock, flags);
 
        /* Turn off all Tx DMA fifos */
-       priv->cfg->ops->lib->txq_set_sched(priv, 0);
+       iwlagn_txq_set_sched(priv, 0);
 
        /* Tell NIC where to find the "keep warm" buffer */
        iwl_write_direct32(priv, FH_KW_MEM_ADDR_REG, priv->kw.dma >> 4);
@@ -954,7 +952,7 @@ void iwlagn_txq_ctx_reset(struct iwl_priv *priv)
        spin_lock_irqsave(&priv->lock, flags);
 
        /* Turn off all Tx DMA fifos */
-       priv->cfg->ops->lib->txq_set_sched(priv, 0);
+       iwlagn_txq_set_sched(priv, 0);
 
        /* Tell NIC where to find the "keep warm" buffer */
        iwl_write_direct32(priv, FH_KW_MEM_ADDR_REG, priv->kw.dma >> 4);
@@ -980,7 +978,7 @@ void iwlagn_txq_ctx_stop(struct iwl_priv *priv)
        /* Turn off all Tx DMA fifos */
        spin_lock_irqsave(&priv->lock, flags);
 
-       priv->cfg->ops->lib->txq_set_sched(priv, 0);
+       iwlagn_txq_set_sched(priv, 0);
 
        /* Stop each Tx DMA channel, and wait for it to be idle */
        for (ch = 0; ch < priv->hw_params.dma_chnl_num; ch++) {
@@ -1263,7 +1261,7 @@ int iwlagn_tx_queue_reclaim(struct iwl_priv *priv, int txq_id, int index)
 
                iwlagn_txq_inval_byte_cnt_tbl(priv, txq);
 
-               priv->cfg->ops->lib->txq_free_tfd(priv, txq);
+               iwlagn_txq_free_tfd(priv, txq);
        }
        return nfreed;
 }
index 8bda0e8d666184ab58322cabef88e8424ec47e12..97de5d9de67b5421582ee9c60f9f555f141f3684 100644 (file)
@@ -217,8 +217,8 @@ static int iwlagn_send_calib_cfg(struct iwl_priv *priv)
        struct iwl_calib_cfg_cmd calib_cfg_cmd;
        struct iwl_host_cmd cmd = {
                .id = CALIBRATION_CFG_CMD,
-               .len = sizeof(struct iwl_calib_cfg_cmd),
-               .data = &calib_cfg_cmd,
+               .len = { sizeof(struct iwl_calib_cfg_cmd), },
+               .data = { &calib_cfg_cmd, },
        };
 
        memset(&calib_cfg_cmd, 0, sizeof(calib_cfg_cmd));
@@ -440,7 +440,7 @@ static int iwlagn_alive_notify(struct iwl_priv *priv)
                        IWL_MASK(0, priv->hw_params.max_txq_num));
 
        /* Activate all Tx DMA/FIFO channels */
-       priv->cfg->ops->lib->txq_set_sched(priv, IWL_MASK(0, 7));
+       iwlagn_txq_set_sched(priv, IWL_MASK(0, 7));
 
        /* map queues to FIFOs */
        if (priv->valid_contexts != BIT(IWL_RXON_CTX_BSS))
index 3ecc3198d9bf9f089d567c5afbcaec6bc5068e57..e027f99f18a5a4e539b3740fec61ebda72f814e6 100644 (file)
@@ -134,12 +134,10 @@ int iwlagn_send_beacon_cmd(struct iwl_priv *priv)
        struct iwl_tx_beacon_cmd *tx_beacon_cmd;
        struct iwl_host_cmd cmd = {
                .id = REPLY_TX_BEACON,
-               .flags = CMD_SIZE_HUGE,
        };
        u32 frame_size;
        u32 rate_flags;
        u32 rate;
-       int err;
 
        /*
         * We have to set up the TX command, the TX Beacon command, and the
@@ -156,17 +154,15 @@ int iwlagn_send_beacon_cmd(struct iwl_priv *priv)
        if (WARN_ON(!priv->beacon_skb))
                return -EINVAL;
 
-       /* Allocate beacon memory */
-       tx_beacon_cmd = kzalloc(sizeof(*tx_beacon_cmd) + priv->beacon_skb->len,
-                               GFP_KERNEL);
+       /* Allocate beacon command */
+       if (!priv->beacon_cmd)
+               priv->beacon_cmd = kzalloc(sizeof(*tx_beacon_cmd), GFP_KERNEL);
+       tx_beacon_cmd = priv->beacon_cmd;
        if (!tx_beacon_cmd)
                return -ENOMEM;
 
        frame_size = priv->beacon_skb->len;
 
-       /* Set up TX beacon contents */
-       memcpy(tx_beacon_cmd->frame, priv->beacon_skb->data, frame_size);
-
        /* Set up TX command fields */
        tx_beacon_cmd->tx.len = cpu_to_le16((u16)frame_size);
        tx_beacon_cmd->tx.sta_id = priv->beacon_ctx->bcast_sta_id;
@@ -175,7 +171,7 @@ int iwlagn_send_beacon_cmd(struct iwl_priv *priv)
                TX_CMD_FLG_TSF_MSK | TX_CMD_FLG_STA_RATE_MSK;
 
        /* Set up TX beacon command fields */
-       iwl_set_beacon_tim(priv, tx_beacon_cmd, (u8 *)tx_beacon_cmd->frame,
+       iwl_set_beacon_tim(priv, tx_beacon_cmd, priv->beacon_skb->data,
                           frame_size);
 
        /* Set up packet rate and flags */
@@ -189,164 +185,14 @@ int iwlagn_send_beacon_cmd(struct iwl_priv *priv)
                        rate_flags);
 
        /* Submit command */
-       cmd.len = sizeof(*tx_beacon_cmd) + frame_size;
-       cmd.data = tx_beacon_cmd;
-
-       err = iwl_send_cmd_sync(priv, &cmd);
-
-       /* Free temporary storage */
-       kfree(tx_beacon_cmd);
-
-       return err;
-}
-
-static inline dma_addr_t iwl_tfd_tb_get_addr(struct iwl_tfd *tfd, u8 idx)
-{
-       struct iwl_tfd_tb *tb = &tfd->tbs[idx];
+       cmd.len[0] = sizeof(*tx_beacon_cmd);
+       cmd.data[0] = tx_beacon_cmd;
+       cmd.dataflags[0] = IWL_HCMD_DFL_NOCOPY;
+       cmd.len[1] = frame_size;
+       cmd.data[1] = priv->beacon_skb->data;
+       cmd.dataflags[1] = IWL_HCMD_DFL_NOCOPY;
 
-       dma_addr_t addr = get_unaligned_le32(&tb->lo);
-       if (sizeof(dma_addr_t) > sizeof(u32))
-               addr |=
-               ((dma_addr_t)(le16_to_cpu(tb->hi_n_len) & 0xF) << 16) << 16;
-
-       return addr;
-}
-
-static inline u16 iwl_tfd_tb_get_len(struct iwl_tfd *tfd, u8 idx)
-{
-       struct iwl_tfd_tb *tb = &tfd->tbs[idx];
-
-       return le16_to_cpu(tb->hi_n_len) >> 4;
-}
-
-static inline void iwl_tfd_set_tb(struct iwl_tfd *tfd, u8 idx,
-                                 dma_addr_t addr, u16 len)
-{
-       struct iwl_tfd_tb *tb = &tfd->tbs[idx];
-       u16 hi_n_len = len << 4;
-
-       put_unaligned_le32(addr, &tb->lo);
-       if (sizeof(dma_addr_t) > sizeof(u32))
-               hi_n_len |= ((addr >> 16) >> 16) & 0xF;
-
-       tb->hi_n_len = cpu_to_le16(hi_n_len);
-
-       tfd->num_tbs = idx + 1;
-}
-
-static inline u8 iwl_tfd_get_num_tbs(struct iwl_tfd *tfd)
-{
-       return tfd->num_tbs & 0x1f;
-}
-
-/**
- * iwl_hw_txq_free_tfd - Free all chunks referenced by TFD [txq->q.read_ptr]
- * @priv - driver private data
- * @txq - tx queue
- *
- * Does NOT advance any TFD circular buffer read/write indexes
- * Does NOT free the TFD itself (which is within circular buffer)
- */
-void iwl_hw_txq_free_tfd(struct iwl_priv *priv, struct iwl_tx_queue *txq)
-{
-       struct iwl_tfd *tfd_tmp = (struct iwl_tfd *)txq->tfds;
-       struct iwl_tfd *tfd;
-       struct pci_dev *dev = priv->pci_dev;
-       int index = txq->q.read_ptr;
-       int i;
-       int num_tbs;
-
-       tfd = &tfd_tmp[index];
-
-       /* Sanity check on number of chunks */
-       num_tbs = iwl_tfd_get_num_tbs(tfd);
-
-       if (num_tbs >= IWL_NUM_OF_TBS) {
-               IWL_ERR(priv, "Too many chunks: %i\n", num_tbs);
-               /* @todo issue fatal error, it is quite serious situation */
-               return;
-       }
-
-       /* Unmap tx_cmd */
-       if (num_tbs)
-               pci_unmap_single(dev,
-                               dma_unmap_addr(&txq->meta[index], mapping),
-                               dma_unmap_len(&txq->meta[index], len),
-                               PCI_DMA_BIDIRECTIONAL);
-
-       /* Unmap chunks, if any. */
-       for (i = 1; i < num_tbs; i++)
-               pci_unmap_single(dev, iwl_tfd_tb_get_addr(tfd, i),
-                               iwl_tfd_tb_get_len(tfd, i), PCI_DMA_TODEVICE);
-
-       /* free SKB */
-       if (txq->txb) {
-               struct sk_buff *skb;
-
-               skb = txq->txb[txq->q.read_ptr].skb;
-
-               /* can be called from irqs-disabled context */
-               if (skb) {
-                       dev_kfree_skb_any(skb);
-                       txq->txb[txq->q.read_ptr].skb = NULL;
-               }
-       }
-}
-
-int iwl_hw_txq_attach_buf_to_tfd(struct iwl_priv *priv,
-                                struct iwl_tx_queue *txq,
-                                dma_addr_t addr, u16 len,
-                                u8 reset, u8 pad)
-{
-       struct iwl_queue *q;
-       struct iwl_tfd *tfd, *tfd_tmp;
-       u32 num_tbs;
-
-       q = &txq->q;
-       tfd_tmp = (struct iwl_tfd *)txq->tfds;
-       tfd = &tfd_tmp[q->write_ptr];
-
-       if (reset)
-               memset(tfd, 0, sizeof(*tfd));
-
-       num_tbs = iwl_tfd_get_num_tbs(tfd);
-
-       /* Each TFD can point to a maximum 20 Tx buffers */
-       if (num_tbs >= IWL_NUM_OF_TBS) {
-               IWL_ERR(priv, "Error can not send more than %d chunks\n",
-                         IWL_NUM_OF_TBS);
-               return -EINVAL;
-       }
-
-       if (WARN_ON(addr & ~DMA_BIT_MASK(36)))
-               return -EINVAL;
-
-       if (unlikely(addr & ~IWL_TX_DMA_MASK))
-               IWL_ERR(priv, "Unaligned address = %llx\n",
-                         (unsigned long long)addr);
-
-       iwl_tfd_set_tb(tfd, num_tbs, addr, len);
-
-       return 0;
-}
-
-/*
- * Tell nic where to find circular buffer of Tx Frame Descriptors for
- * given Tx queue, and enable the DMA channel used for that queue.
- *
- * supports up to 16 Tx queues in DRAM, mapped to up to 8 Tx DMA
- * channels supported in hardware.
- */
-int iwl_hw_tx_queue_init(struct iwl_priv *priv,
-                        struct iwl_tx_queue *txq)
-{
-       int txq_id = txq->q.id;
-
-       /* Circular buffer (TFD queue in DRAM) physical base address */
-       iwl_write_direct32(priv, FH_MEM_CBBC_QUEUE(txq_id),
-                            txq->q.dma_addr >> 8);
-
-       return 0;
+       return iwl_send_cmd_sync(priv, &cmd);
 }
 
 static void iwl_bg_beacon_update(struct work_struct *work)
@@ -1776,10 +1622,7 @@ static const char *desc_lookup(u32 num)
 
 void iwl_dump_nic_error_log(struct iwl_priv *priv)
 {
-       u32 data2, line;
-       u32 desc, time, count, base, data1;
-       u32 blink1, blink2, ilink1, ilink2;
-       u32 pc, hcmd;
+       u32 base;
        struct iwl_error_event_table table;
 
        base = priv->device_pointers.error_event_table;
@@ -1802,37 +1645,40 @@ void iwl_dump_nic_error_log(struct iwl_priv *priv)
 
        iwl_read_targ_mem_words(priv, base, &table, sizeof(table));
 
-       count = table.valid;
-
-       if (ERROR_START_OFFSET <= count * ERROR_ELEM_SIZE) {
+       if (ERROR_START_OFFSET <= table.valid * ERROR_ELEM_SIZE) {
                IWL_ERR(priv, "Start IWL Error Log Dump:\n");
                IWL_ERR(priv, "Status: 0x%08lX, count: %d\n",
-                       priv->status, count);
-       }
-
-       desc = table.error_id;
-       priv->isr_stats.err_code = desc;
-       pc = table.pc;
-       blink1 = table.blink1;
-       blink2 = table.blink2;
-       ilink1 = table.ilink1;
-       ilink2 = table.ilink2;
-       data1 = table.data1;
-       data2 = table.data2;
-       line = table.line;
-       time = table.tsf_low;
-       hcmd = table.hcmd;
-
-       trace_iwlwifi_dev_ucode_error(priv, desc, time, data1, data2, line,
-                                     blink1, blink2, ilink1, ilink2);
-
-       IWL_ERR(priv, "Desc                                  Time       "
-               "data1      data2      line\n");
-       IWL_ERR(priv, "%-28s (0x%04X) %010u 0x%08X 0x%08X %u\n",
-               desc_lookup(desc), desc, time, data1, data2, line);
-       IWL_ERR(priv, "pc      blink1  blink2  ilink1  ilink2  hcmd\n");
-       IWL_ERR(priv, "0x%05X 0x%05X 0x%05X 0x%05X 0x%05X 0x%05X\n",
-               pc, blink1, blink2, ilink1, ilink2, hcmd);
+                       priv->status, table.valid);
+       }
+
+       priv->isr_stats.err_code = table.error_id;
+
+       trace_iwlwifi_dev_ucode_error(priv, table.error_id, table.tsf_low,
+                                     table.data1, table.data2, table.line,
+                                     table.blink1, table.blink2, table.ilink1,
+                                     table.ilink2, table.bcon_time, table.gp1,
+                                     table.gp2, table.gp3, table.ucode_ver,
+                                     table.hw_ver, table.brd_ver);
+       IWL_ERR(priv, "0x%08X | %-28s\n", table.error_id,
+               desc_lookup(table.error_id));
+       IWL_ERR(priv, "0x%08X | uPc\n", table.pc);
+       IWL_ERR(priv, "0x%08X | branchlink1\n", table.blink1);
+       IWL_ERR(priv, "0x%08X | branchlink2\n", table.blink2);
+       IWL_ERR(priv, "0x%08X | interruptlink1\n", table.ilink1);
+       IWL_ERR(priv, "0x%08X | interruptlink2\n", table.ilink2);
+       IWL_ERR(priv, "0x%08X | data1\n", table.data1);
+       IWL_ERR(priv, "0x%08X | data2\n", table.data2);
+       IWL_ERR(priv, "0x%08X | line\n", table.line);
+       IWL_ERR(priv, "0x%08X | beacon time\n", table.bcon_time);
+       IWL_ERR(priv, "0x%08X | tsf low\n", table.tsf_low);
+       IWL_ERR(priv, "0x%08X | tsf hi\n", table.tsf_hi);
+       IWL_ERR(priv, "0x%08X | time gp1\n", table.gp1);
+       IWL_ERR(priv, "0x%08X | time gp2\n", table.gp2);
+       IWL_ERR(priv, "0x%08X | time gp3\n", table.gp3);
+       IWL_ERR(priv, "0x%08X | uCode version\n", table.ucode_ver);
+       IWL_ERR(priv, "0x%08X | hw version\n", table.hw_ver);
+       IWL_ERR(priv, "0x%08X | board version\n", table.brd_ver);
+       IWL_ERR(priv, "0x%08X | hcmd\n", table.hcmd);
 }
 
 #define EVENT_START_OFFSET  (4 * sizeof(u32))
@@ -2114,8 +1960,8 @@ static int iwlagn_send_calib_cfg_rt(struct iwl_priv *priv, u32 cfg)
        struct iwl_calib_cfg_cmd calib_cfg_cmd;
        struct iwl_host_cmd cmd = {
                .id = CALIBRATION_CFG_CMD,
-               .len = sizeof(struct iwl_calib_cfg_cmd),
-               .data = &calib_cfg_cmd,
+               .len = { sizeof(struct iwl_calib_cfg_cmd), },
+               .data = { &calib_cfg_cmd, },
        };
 
        memset(&calib_cfg_cmd, 0, sizeof(calib_cfg_cmd));
@@ -3395,6 +3241,7 @@ static void iwl_uninit_drv(struct iwl_priv *priv)
        iwlcore_free_geos(priv);
        iwl_free_channel_map(priv);
        kfree(priv->scan_cmd);
+       kfree(priv->beacon_cmd);
 }
 
 struct ieee80211_ops iwlagn_hw_ops = {
@@ -3812,6 +3659,7 @@ static void __devexit iwl_pci_remove(struct pci_dev *pdev)
         */
        set_bit(STATUS_EXIT_PENDING, &priv->status);
 
+       iwl_testmode_cleanup(priv);
        iwl_leds_exit(priv);
 
        if (priv->mac80211_registered) {
index fe33fe8aa4185ed0a47bb668048745df7cd32e0b..2495fe7a58cbb5f7d61399c6dacb8ebf358ede73 100644 (file)
@@ -191,12 +191,10 @@ int iwlagn_hwrate_to_mac80211_idx(u32 rate_n_flags, enum ieee80211_band band);
 void iwl_setup_rx_handlers(struct iwl_priv *priv);
 
 /* tx */
-void iwl_hw_txq_free_tfd(struct iwl_priv *priv, struct iwl_tx_queue *txq);
-int iwl_hw_txq_attach_buf_to_tfd(struct iwl_priv *priv,
+void iwlagn_txq_free_tfd(struct iwl_priv *priv, struct iwl_tx_queue *txq);
+int iwlagn_txq_attach_buf_to_tfd(struct iwl_priv *priv,
                                 struct iwl_tx_queue *txq,
-                                dma_addr_t addr, u16 len, u8 reset, u8 pad);
-int iwl_hw_tx_queue_init(struct iwl_priv *priv,
-                        struct iwl_tx_queue *txq);
+                                dma_addr_t addr, u16 len, u8 reset);
 void iwlagn_hwrate_to_tx_control(struct iwl_priv *priv, u32 rate_n_flags,
                              struct ieee80211_tx_info *info);
 int iwlagn_tx_skb(struct iwl_priv *priv, struct sk_buff *skb);
@@ -345,6 +343,7 @@ extern int iwl_alive_start(struct iwl_priv *priv);
 #ifdef CONFIG_IWLWIFI_DEVICE_SVTOOL
 extern int iwl_testmode_cmd(struct ieee80211_hw *hw, void *data, int len);
 extern void iwl_testmode_init(struct iwl_priv *priv);
+extern void iwl_testmode_cleanup(struct iwl_priv *priv);
 #else
 static inline
 int iwl_testmode_cmd(struct ieee80211_hw *hw, void *data, int len)
@@ -355,6 +354,10 @@ static inline
 void iwl_testmode_init(struct iwl_priv *priv)
 {
 }
+static inline
+void iwl_testmode_cleanup(struct iwl_priv *priv)
+{
+}
 #endif
 
 #endif /* __iwl_agn_h__ */
index 5fdad6532118884aebdbf9854597cbf2e0928ad6..6ee5f1aa555ca76af578642459fc178189f62db3 100644 (file)
@@ -205,7 +205,6 @@ enum {
 #define QUEUE_TO_SEQ(q)        (((q) & 0x1f) << 8)
 #define SEQ_TO_INDEX(s)        ((s) & 0xff)
 #define INDEX_TO_SEQ(i)        ((i) & 0xff)
-#define SEQ_HUGE_FRAME cpu_to_le16(0x4000)
 #define SEQ_RX_FRAME   cpu_to_le16(0x8000)
 
 /**
@@ -234,9 +233,7 @@ struct iwl_cmd_header {
         *
         *  0:7         tfd index - position within TX queue
         *  8:12        TX queue id
-        *  13          reserved
-        *  14          huge - driver sets this to indicate command is in the
-        *              'huge' storage at the end of the command buffers
+        *  13:14       reserved
         *  15          unsolicited RX or uCode-originated notification
         */
        __le16 sequence;
index 5b5b0cce4a54e7c85d89fb5e45e4b9c7c2853b97..3bb76f6ea41017448c5cc5ce99851c967d66dafe 100644 (file)
@@ -127,16 +127,6 @@ struct iwl_temp_ops {
 struct iwl_lib_ops {
        /* set hw dependent parameters */
        int (*set_hw_params)(struct iwl_priv *priv);
-       /* Handling TX */
-       void (*txq_set_sched)(struct iwl_priv *priv, u32 mask);
-       int (*txq_attach_buf_to_tfd)(struct iwl_priv *priv,
-                                    struct iwl_tx_queue *txq,
-                                    dma_addr_t addr,
-                                    u16 len, u8 reset, u8 pad);
-       void (*txq_free_tfd)(struct iwl_priv *priv,
-                            struct iwl_tx_queue *txq);
-       int (*txq_init)(struct iwl_priv *priv,
-                       struct iwl_tx_queue *txq);
        /* setup Rx handler */
        void (*rx_handler_setup)(struct iwl_priv *priv);
        /* setup deferred work */
index 214e4658c4951ffaff35ddc379b2dec5ffcb0f3e..22a6e3ec7094e651b6afbe8245b778b25881bd77 100644 (file)
@@ -48,8 +48,6 @@
 #include "iwl-agn-rs.h"
 #include "iwl-agn-tt.h"
 
-#define U32_PAD(n)             ((4-(n))&0x3)
-
 struct iwl_tx_queue;
 
 /* CT-KILL constants */
@@ -83,7 +81,7 @@ struct iwl_tx_queue;
 #define MAX_RTS_THRESHOLD         2347U
 #define MAX_MSDU_SIZE            2304U
 #define MAX_MPDU_SIZE            2346U
-#define DEFAULT_BEACON_INTERVAL   100U
+#define DEFAULT_BEACON_INTERVAL   200U
 #define        DEFAULT_SHORT_RETRY_LIMIT 7U
 #define        DEFAULT_LONG_RETRY_LIMIT  4U
 
@@ -112,8 +110,6 @@ struct iwl_cmd_meta {
                         struct iwl_device_cmd *cmd,
                         struct iwl_rx_packet *pkt);
 
-       /* The CMD_SIZE_HUGE flag bit indicates that the command
-        * structure is stored at the end of the shared queue memory. */
        u32 flags;
 
        DEFINE_DMA_UNMAP_ADDR(mapping);
@@ -123,7 +119,23 @@ struct iwl_cmd_meta {
 /*
  * Generic queue structure
  *
- * Contains common data for Rx and Tx queues
+ * Contains common data for Rx and Tx queues.
+ *
+ * Note the difference between n_bd and n_window: the hardware
+ * always assumes 256 descriptors, so n_bd is always 256 (unless
+ * there might be HW changes in the future). For the normal TX
+ * queues, n_window, which is the size of the software queue data
+ * is also 256; however, for the command queue, n_window is only
+ * 32 since we don't need so many commands pending. Since the HW
+ * still uses 256 BDs for DMA though, n_bd stays 256. As a result,
+ * the software buffers (in the variables @meta, @txb in struct
+ * iwl_tx_queue) only have 32 entries, while the HW buffers (@tfds
+ * in the same struct) have 256.
+ * This means that we end up with the following:
+ *  HW entries: | 0 | ... | N * 32 | ... | N * 32 + 31 | ... | 255 |
+ *  SW entries:           | 0      | ... | 31          |
+ * where N is a number between 0 and 7. This means that the SW
+ * data is a window overlayed over the HW queue.
  */
 struct iwl_queue {
        int n_bd;              /* number of BDs in this queue */
@@ -165,7 +177,7 @@ struct iwl_tx_info {
 
 struct iwl_tx_queue {
        struct iwl_queue q;
-       void *tfds;
+       struct iwl_tfd *tfds;
        struct iwl_device_cmd **cmd;
        struct iwl_cmd_meta *meta;
        struct iwl_tx_info *txb;
@@ -247,7 +259,6 @@ enum {
        CMD_SYNC = 0,
        CMD_SIZE_NORMAL = 0,
        CMD_NO_SKB = 0,
-       CMD_SIZE_HUGE = (1 << 0),
        CMD_ASYNC = (1 << 1),
        CMD_WANT_SKB = (1 << 2),
        CMD_MAPPED = (1 << 3),
@@ -259,8 +270,8 @@ enum {
  * struct iwl_device_cmd
  *
  * For allocation of the command and tx queues, this establishes the overall
- * size of the largest command we send to uCode, except for a scan command
- * (which is relatively huge; space is allocated separately).
+ * size of the largest command we send to uCode, except for commands that
+ * aren't fully copied and use other TFD space.
  */
 struct iwl_device_cmd {
        struct iwl_cmd_header hdr;      /* uCode API */
@@ -277,15 +288,21 @@ struct iwl_device_cmd {
 
 #define TFD_MAX_PAYLOAD_SIZE (sizeof(struct iwl_device_cmd))
 
+#define IWL_MAX_CMD_TFDS       2
+
+enum iwl_hcmd_dataflag {
+       IWL_HCMD_DFL_NOCOPY     = BIT(0),
+};
 
 struct iwl_host_cmd {
-       const void *data;
+       const void *data[IWL_MAX_CMD_TFDS];
        unsigned long reply_page;
        void (*callback)(struct iwl_priv *priv,
                         struct iwl_device_cmd *cmd,
                         struct iwl_rx_packet *pkt);
        u32 flags;
-       u16 len;
+       u16 len[IWL_MAX_CMD_TFDS];
+       u8 dataflags[IWL_MAX_CMD_TFDS];
        u8 id;
 };
 
@@ -688,17 +705,8 @@ static inline int iwl_queue_used(const struct iwl_queue *q, int i)
 }
 
 
-static inline u8 get_cmd_index(struct iwl_queue *q, u32 index, int is_huge)
+static inline u8 get_cmd_index(struct iwl_queue *q, u32 index)
 {
-       /*
-        * This is for init calibration result and scan command which
-        * required buffer > TFD_MAX_PAYLOAD_SIZE,
-        * the big buffer at end of command array
-        */
-       if (is_huge)
-               return q->n_window;     /* must be power of 2 */
-
-       /* Otherwise, use normal size buffers */
        return index & (q->n_window - 1);
 }
 
@@ -1171,6 +1179,14 @@ enum iwl_scan_type {
        IWL_SCAN_OFFCH_TX,
 };
 
+#ifdef CONFIG_IWLWIFI_DEVICE_SVTOOL
+struct iwl_testmode_trace {
+       u8 *cpu_addr;
+       u8 *trace_addr;
+       dma_addr_t dma_addr;
+       bool trace_enabled;
+};
+#endif
 struct iwl_priv {
 
        /* ieee device used by generic ieee processing code */
@@ -1452,6 +1468,7 @@ struct iwl_priv {
        struct work_struct beacon_update;
        struct iwl_rxon_context *beacon_ctx;
        struct sk_buff *beacon_skb;
+       void *beacon_cmd;
 
        struct work_struct tt_work;
        struct work_struct ct_enter;
@@ -1501,6 +1518,11 @@ struct iwl_priv {
        struct led_classdev led;
        unsigned long blink_on, blink_off;
        bool led_registered;
+#ifdef CONFIG_IWLWIFI_DEVICE_SVTOOL
+       struct iwl_testmode_trace testmode_trace;
+#endif
+       u32 dbg_fixed_rate;
+
 }; /*iwl_priv */
 
 static inline void iwl_txq_ctx_activate(struct iwl_priv *priv, int txq_id)
index f00172cb8a6dda1bc8975dbb6838954bc3f923d4..2c84ba95afca77f70cbdc9171552dacfa7853fcc 100644 (file)
@@ -137,20 +137,27 @@ TRACE_EVENT(iwlwifi_dev_ucode_wrap_event,
 #define TRACE_SYSTEM iwlwifi
 
 TRACE_EVENT(iwlwifi_dev_hcmd,
-       TP_PROTO(struct iwl_priv *priv, void *hcmd, size_t len, u32 flags),
-       TP_ARGS(priv, hcmd, len, flags),
+       TP_PROTO(struct iwl_priv *priv, u32 flags,
+                const void *hcmd0, size_t len0,
+                const void *hcmd1, size_t len1,
+                const void *hcmd2, size_t len2),
+       TP_ARGS(priv, flags, hcmd0, len0, hcmd1, len1, hcmd2, len2),
        TP_STRUCT__entry(
                PRIV_ENTRY
-               __dynamic_array(u8, hcmd, len)
+               __dynamic_array(u8, hcmd0, len0)
+               __dynamic_array(u8, hcmd1, len1)
+               __dynamic_array(u8, hcmd2, len2)
                __field(u32, flags)
        ),
        TP_fast_assign(
                PRIV_ASSIGN;
-               memcpy(__get_dynamic_array(hcmd), hcmd, len);
+               memcpy(__get_dynamic_array(hcmd0), hcmd0, len0);
+               memcpy(__get_dynamic_array(hcmd1), hcmd1, len1);
+               memcpy(__get_dynamic_array(hcmd2), hcmd2, len2);
                __entry->flags = flags;
        ),
        TP_printk("[%p] hcmd %#.2x (%ssync)",
-                 __entry->priv, ((u8 *)__get_dynamic_array(hcmd))[0],
+                 __entry->priv, ((u8 *)__get_dynamic_array(hcmd0))[0],
                  __entry->flags & CMD_ASYNC ? "a" : "")
 );
 
@@ -202,15 +209,18 @@ TRACE_EVENT(iwlwifi_dev_tx,
 );
 
 TRACE_EVENT(iwlwifi_dev_ucode_error,
-       TP_PROTO(struct iwl_priv *priv, u32 desc, u32 time,
+       TP_PROTO(struct iwl_priv *priv, u32 desc, u32 tsf_low,
                 u32 data1, u32 data2, u32 line, u32 blink1,
-                u32 blink2, u32 ilink1, u32 ilink2),
-       TP_ARGS(priv, desc, time, data1, data2, line,
-               blink1, blink2, ilink1, ilink2),
+                u32 blink2, u32 ilink1, u32 ilink2, u32 bcon_time,
+                u32 gp1, u32 gp2, u32 gp3, u32 ucode_ver, u32 hw_ver,
+                u32 brd_ver),
+       TP_ARGS(priv, desc, tsf_low, data1, data2, line,
+               blink1, blink2, ilink1, ilink2, bcon_time, gp1, gp2,
+               gp3, ucode_ver, hw_ver, brd_ver),
        TP_STRUCT__entry(
                PRIV_ENTRY
                __field(u32, desc)
-               __field(u32, time)
+               __field(u32, tsf_low)
                __field(u32, data1)
                __field(u32, data2)
                __field(u32, line)
@@ -218,11 +228,18 @@ TRACE_EVENT(iwlwifi_dev_ucode_error,
                __field(u32, blink2)
                __field(u32, ilink1)
                __field(u32, ilink2)
+               __field(u32, bcon_time)
+               __field(u32, gp1)
+               __field(u32, gp2)
+               __field(u32, gp3)
+               __field(u32, ucode_ver)
+               __field(u32, hw_ver)
+               __field(u32, brd_ver)
        ),
        TP_fast_assign(
                PRIV_ASSIGN;
                __entry->desc = desc;
-               __entry->time = time;
+               __entry->tsf_low = tsf_low;
                __entry->data1 = data1;
                __entry->data2 = data2;
                __entry->line = line;
@@ -230,12 +247,25 @@ TRACE_EVENT(iwlwifi_dev_ucode_error,
                __entry->blink2 = blink2;
                __entry->ilink1 = ilink1;
                __entry->ilink2 = ilink2;
+               __entry->bcon_time = bcon_time;
+               __entry->gp1 = gp1;
+               __entry->gp2 = gp2;
+               __entry->gp3 = gp3;
+               __entry->ucode_ver = ucode_ver;
+               __entry->hw_ver = hw_ver;
+               __entry->brd_ver = brd_ver;
        ),
        TP_printk("[%p] #%02d %010u data 0x%08X 0x%08X line %u, "
-                 "blink 0x%05X 0x%05X ilink 0x%05X 0x%05X",
-                 __entry->priv, __entry->desc, __entry->time, __entry->data1,
+                 "blink 0x%05X 0x%05X ilink 0x%05X 0x%05X "
+                 "bcon_tm %010u gp 0x%08X 0x%08X 0x%08X uCode 0x%08X "
+                 "hw 0x%08X brd 0x%08X",
+                 __entry->priv, __entry->desc, __entry->tsf_low,
+                 __entry->data1,
                  __entry->data2, __entry->line, __entry->blink1,
-                 __entry->blink2, __entry->ilink1, __entry->ilink2)
+                 __entry->blink2, __entry->ilink1, __entry->ilink2,
+                 __entry->bcon_time, __entry->gp1, __entry->gp2,
+                 __entry->gp3, __entry->ucode_ver, __entry->hw_ver,
+                 __entry->brd_ver)
 );
 
 TRACE_EVENT(iwlwifi_dev_ucode_event,
index c8397962632c97f2a830205390a0c7350c54a48e..47a56bc1cd12e063bd556c1f19095cda9fabcfcb 100644 (file)
@@ -216,15 +216,14 @@ static int iwl_eeprom_verify_signature(struct iwl_priv *priv)
 
 static void iwl_set_otp_access(struct iwl_priv *priv, enum iwl_access_mode mode)
 {
-       u32 otpgp;
+       iwl_read32(priv, CSR_OTP_GP_REG);
 
-       otpgp = iwl_read32(priv, CSR_OTP_GP_REG);
        if (mode == IWL_OTP_ACCESS_ABSOLUTE)
                iwl_clear_bit(priv, CSR_OTP_GP_REG,
-                               CSR_OTP_GP_REG_OTP_ACCESS_MODE);
+                             CSR_OTP_GP_REG_OTP_ACCESS_MODE);
        else
                iwl_set_bit(priv, CSR_OTP_GP_REG,
-                               CSR_OTP_GP_REG_OTP_ACCESS_MODE);
+                           CSR_OTP_GP_REG_OTP_ACCESS_MODE);
 }
 
 static int iwlcore_get_nvm_type(struct iwl_priv *priv, u32 hw_rev)
index 8f0beb992ccfb3f0bcf11baa83d92f7cbcf0d431..76f9966231405bf50a97e89ece9381300e30c4d1 100644 (file)
@@ -188,6 +188,7 @@ int iwl_send_cmd_sync(struct iwl_priv *priv, struct iwl_host_cmd *cmd)
        cmd_idx = iwl_enqueue_hcmd(priv, cmd);
        if (cmd_idx < 0) {
                ret = cmd_idx;
+               clear_bit(STATUS_HCMD_ACTIVE, &priv->status);
                IWL_ERR(priv, "Error sending %s: enqueue_hcmd failed: %d\n",
                          get_cmd_string(cmd->id), ret);
                return ret;
@@ -264,8 +265,8 @@ int iwl_send_cmd_pdu(struct iwl_priv *priv, u8 id, u16 len, const void *data)
 {
        struct iwl_host_cmd cmd = {
                .id = id,
-               .len = len,
-               .data = data,
+               .len = { len, },
+               .data = { data, },
        };
 
        return iwl_send_cmd_sync(priv, &cmd);
@@ -279,8 +280,8 @@ int iwl_send_cmd_pdu_async(struct iwl_priv *priv,
 {
        struct iwl_host_cmd cmd = {
                .id = id,
-               .len = len,
-               .data = data,
+               .len = { len, },
+               .data = { data, },
        };
 
        cmd.flags |= CMD_ASYNC;
index 439187f903c9f10f46c0e9f75bc9083624df0e05..7c23beb49d7cd8ba66ef4e4d767c8e77386758df 100644 (file)
@@ -107,8 +107,8 @@ static int iwl_send_led_cmd(struct iwl_priv *priv, struct iwl_led_cmd *led_cmd)
 {
        struct iwl_host_cmd cmd = {
                .id = REPLY_LEDS_CMD,
-               .len = sizeof(struct iwl_led_cmd),
-               .data = led_cmd,
+               .len = { sizeof(struct iwl_led_cmd), },
+               .data = { led_cmd, },
                .flags = CMD_ASYNC,
                .callback = NULL,
        };
index 3c8cebde16cc6608facbf2d28dd0b97100b6b637..7df2814fd4f8cf6724e9282641784f5d46f97241 100644 (file)
@@ -141,7 +141,7 @@ int iwl_send_add_sta(struct iwl_priv *priv,
        struct iwl_host_cmd cmd = {
                .id = REPLY_ADD_STA,
                .flags = flags,
-               .data = data,
+               .data = { data, },
        };
        u8 sta_id __maybe_unused = sta->sta.sta_id;
 
@@ -155,7 +155,7 @@ int iwl_send_add_sta(struct iwl_priv *priv,
                might_sleep();
        }
 
-       cmd.len = priv->cfg->ops->utils->build_addsta_hcmd(sta, data);
+       cmd.len[0] = priv->cfg->ops->utils->build_addsta_hcmd(sta, data);
        ret = iwl_send_cmd(priv, &cmd);
 
        if (ret || (flags & CMD_ASYNC))
@@ -401,9 +401,9 @@ static int iwl_send_remove_station(struct iwl_priv *priv,
 
        struct iwl_host_cmd cmd = {
                .id = REPLY_REMOVE_STA,
-               .len = sizeof(struct iwl_rem_sta_cmd),
+               .len = { sizeof(struct iwl_rem_sta_cmd), },
                .flags = CMD_SYNC,
-               .data = &rm_sta_cmd,
+               .data = { &rm_sta_cmd, },
        };
 
        memset(&rm_sta_cmd, 0, sizeof(rm_sta_cmd));
@@ -760,9 +760,9 @@ int iwl_send_lq_cmd(struct iwl_priv *priv, struct iwl_rxon_context *ctx,
 
        struct iwl_host_cmd cmd = {
                .id = REPLY_TX_LINK_QUALITY_CMD,
-               .len = sizeof(struct iwl_link_quality_cmd),
+               .len = { sizeof(struct iwl_link_quality_cmd), },
                .flags = flags,
-               .data = lq,
+               .data = { lq, },
        };
 
        if (WARN_ON(lq->sta_id == IWL_INVALID_STATION))
index 89b6696622c1883ba12cbbbf70a9965aba59b173..69b7e6bf2d6f40adfd1a1a6ab98795730da338f2 100644 (file)
@@ -97,6 +97,13 @@ struct nla_policy iwl_testmode_gnl_msg_policy[IWL_TM_ATTR_MAX] = {
 
        [IWL_TM_ATTR_SYNC_RSP] = { .type = NLA_UNSPEC, },
        [IWL_TM_ATTR_UCODE_RX_PKT] = { .type = NLA_UNSPEC, },
+
+       [IWL_TM_ATTR_EEPROM] = { .type = NLA_UNSPEC, },
+
+       [IWL_TM_ATTR_TRACE_ADDR] = { .type = NLA_UNSPEC, },
+       [IWL_TM_ATTR_TRACE_DATA] = { .type = NLA_UNSPEC, },
+
+       [IWL_TM_ATTR_FIXRATE] = { .type = NLA_U32, },
 };
 
 /*
@@ -167,6 +174,31 @@ nla_put_failure:
 void iwl_testmode_init(struct iwl_priv *priv)
 {
        priv->pre_rx_handler = iwl_testmode_ucode_rx_pkt;
+       priv->testmode_trace.trace_enabled = false;
+}
+
+static void iwl_trace_cleanup(struct iwl_priv *priv)
+{
+       struct device *dev = &priv->pci_dev->dev;
+
+       if (priv->testmode_trace.trace_enabled) {
+               if (priv->testmode_trace.cpu_addr &&
+                   priv->testmode_trace.dma_addr)
+                       dma_free_coherent(dev,
+                                       TRACE_TOTAL_SIZE,
+                                       priv->testmode_trace.cpu_addr,
+                                       priv->testmode_trace.dma_addr);
+               priv->testmode_trace.trace_enabled = false;
+               priv->testmode_trace.cpu_addr = NULL;
+               priv->testmode_trace.trace_addr = NULL;
+               priv->testmode_trace.dma_addr = 0;
+       }
+}
+
+
+void iwl_testmode_cleanup(struct iwl_priv *priv)
+{
+       iwl_trace_cleanup(priv);
 }
 
 /*
@@ -198,10 +230,11 @@ static int iwl_testmode_ucode(struct ieee80211_hw *hw, struct nlattr **tb)
        }
 
        cmd.id = nla_get_u8(tb[IWL_TM_ATTR_UCODE_CMD_ID]);
-       cmd.data = nla_data(tb[IWL_TM_ATTR_UCODE_CMD_DATA]);
-       cmd.len = nla_len(tb[IWL_TM_ATTR_UCODE_CMD_DATA]);
+       cmd.data[0] = nla_data(tb[IWL_TM_ATTR_UCODE_CMD_DATA]);
+       cmd.len[0] = nla_len(tb[IWL_TM_ATTR_UCODE_CMD_DATA]);
+       cmd.dataflags[0] = IWL_HCMD_DFL_NOCOPY;
        IWL_INFO(priv, "testmode ucode command ID 0x%x, flags 0x%x,"
-                               " len %d\n", cmd.id, cmd.flags, cmd.len);
+                               " len %d\n", cmd.id, cmd.flags, cmd.len[0]);
        /* ok, let's submit the command to ucode */
        return iwl_send_cmd(priv, &cmd);
 }
@@ -388,6 +421,38 @@ static int iwl_testmode_driver(struct ieee80211_hw *hw, struct nlattr **tb)
                                "Error starting the device: %d\n", status);
                break;
 
+       case IWL_TM_CMD_APP2DEV_GET_EEPROM:
+               if (priv->eeprom) {
+                       skb = cfg80211_testmode_alloc_reply_skb(hw->wiphy,
+                               priv->cfg->base_params->eeprom_size + 20);
+                       if (!skb) {
+                               IWL_DEBUG_INFO(priv,
+                                      "Error allocating memory\n");
+                               return -ENOMEM;
+                       }
+                       NLA_PUT_U32(skb, IWL_TM_ATTR_COMMAND,
+                               IWL_TM_CMD_DEV2APP_EEPROM_RSP);
+                       NLA_PUT(skb, IWL_TM_ATTR_EEPROM,
+                               priv->cfg->base_params->eeprom_size,
+                               priv->eeprom);
+                       status = cfg80211_testmode_reply(skb);
+                       if (status < 0)
+                               IWL_DEBUG_INFO(priv,
+                                              "Error sending msg : %d\n",
+                                              status);
+               } else
+                       return -EFAULT;
+               break;
+
+       case IWL_TM_CMD_APP2DEV_FIXRATE_REQ:
+               if (!tb[IWL_TM_ATTR_FIXRATE]) {
+                       IWL_DEBUG_INFO(priv,
+                                      "Error finding fixrate setting\n");
+                       return -ENOMSG;
+               }
+               priv->dbg_fixed_rate = nla_get_u32(tb[IWL_TM_ATTR_FIXRATE]);
+               break;
+
        default:
                IWL_DEBUG_INFO(priv, "Unknown testmode driver command ID\n");
                return -ENOSYS;
@@ -399,6 +464,102 @@ nla_put_failure:
        return -EMSGSIZE;
 }
 
+
+/*
+ * This function handles the user application commands for uCode trace
+ *
+ * It retrieves command ID carried with IWL_TM_ATTR_COMMAND and calls to the
+ * handlers respectively.
+ *
+ * If it's an unknown commdn ID, -ENOSYS is replied; otherwise, the returned
+ * value of the actual command execution is replied to the user application.
+ *
+ * @hw: ieee80211_hw object that represents the device
+ * @tb: gnl message fields from the user space
+ */
+static int iwl_testmode_trace(struct ieee80211_hw *hw, struct nlattr **tb)
+{
+       struct iwl_priv *priv = hw->priv;
+       struct sk_buff *skb;
+       int status = 0;
+       struct device *dev = &priv->pci_dev->dev;
+
+       switch (nla_get_u32(tb[IWL_TM_ATTR_COMMAND])) {
+       case IWL_TM_CMD_APP2DEV_BEGIN_TRACE:
+               if (priv->testmode_trace.trace_enabled)
+                       return -EBUSY;
+
+               priv->testmode_trace.cpu_addr =
+                       dma_alloc_coherent(dev,
+                                          TRACE_TOTAL_SIZE,
+                                          &priv->testmode_trace.dma_addr,
+                                          GFP_KERNEL);
+               if (!priv->testmode_trace.cpu_addr)
+                       return -ENOMEM;
+               priv->testmode_trace.trace_enabled = true;
+               priv->testmode_trace.trace_addr = (u8 *)PTR_ALIGN(
+                       priv->testmode_trace.cpu_addr, 0x100);
+               memset(priv->testmode_trace.trace_addr, 0x03B,
+                       TRACE_BUFF_SIZE);
+               skb = cfg80211_testmode_alloc_reply_skb(hw->wiphy,
+                       sizeof(priv->testmode_trace.dma_addr) + 20);
+               if (!skb) {
+                       IWL_DEBUG_INFO(priv,
+                               "Error allocating memory\n");
+                       iwl_trace_cleanup(priv);
+                       return -ENOMEM;
+               }
+               NLA_PUT(skb, IWL_TM_ATTR_TRACE_ADDR,
+                       sizeof(priv->testmode_trace.dma_addr),
+                       (u64 *)&priv->testmode_trace.dma_addr);
+               status = cfg80211_testmode_reply(skb);
+               if (status < 0) {
+                       IWL_DEBUG_INFO(priv,
+                                      "Error sending msg : %d\n",
+                                      status);
+               }
+               break;
+
+       case IWL_TM_CMD_APP2DEV_END_TRACE:
+               iwl_trace_cleanup(priv);
+               break;
+
+       case IWL_TM_CMD_APP2DEV_READ_TRACE:
+               if (priv->testmode_trace.trace_enabled &&
+                   priv->testmode_trace.trace_addr) {
+                       skb = cfg80211_testmode_alloc_reply_skb(hw->wiphy,
+                               20 + TRACE_BUFF_SIZE);
+                       if (skb == NULL) {
+                               IWL_DEBUG_INFO(priv,
+                                       "Error allocating memory\n");
+                               return -ENOMEM;
+                       }
+                       NLA_PUT(skb, IWL_TM_ATTR_TRACE_DATA,
+                               TRACE_BUFF_SIZE,
+                               priv->testmode_trace.trace_addr);
+                       status = cfg80211_testmode_reply(skb);
+                       if (status < 0) {
+                               IWL_DEBUG_INFO(priv,
+                                      "Error sending msg : %d\n", status);
+                       }
+               } else
+                       return -EFAULT;
+               break;
+
+       default:
+               IWL_DEBUG_INFO(priv, "Unknown testmode mem command ID\n");
+               return -ENOSYS;
+       }
+       return status;
+
+nla_put_failure:
+       kfree_skb(skb);
+       if (nla_get_u32(tb[IWL_TM_ATTR_COMMAND]) ==
+           IWL_TM_CMD_APP2DEV_BEGIN_TRACE)
+               iwl_trace_cleanup(priv);
+       return -EMSGSIZE;
+}
+
 /* The testmode gnl message handler that takes the gnl message from the
  * user space and parses it per the policy iwl_testmode_gnl_msg_policy, then
  * invoke the corresponding handlers.
@@ -455,9 +616,19 @@ int iwl_testmode_cmd(struct ieee80211_hw *hw, void *data, int len)
        case IWL_TM_CMD_APP2DEV_LOAD_INIT_FW:
        case IWL_TM_CMD_APP2DEV_CFG_INIT_CALIB:
        case IWL_TM_CMD_APP2DEV_LOAD_RUNTIME_FW:
+       case IWL_TM_CMD_APP2DEV_GET_EEPROM:
+       case IWL_TM_CMD_APP2DEV_FIXRATE_REQ:
                IWL_DEBUG_INFO(priv, "testmode cmd to driver\n");
                result = iwl_testmode_driver(hw, tb);
                break;
+
+       case IWL_TM_CMD_APP2DEV_BEGIN_TRACE:
+       case IWL_TM_CMD_APP2DEV_END_TRACE:
+       case IWL_TM_CMD_APP2DEV_READ_TRACE:
+               IWL_DEBUG_INFO(priv, "testmode uCode trace cmd to driver\n");
+               result = iwl_testmode_trace(hw, tb);
+               break;
+
        default:
                IWL_DEBUG_INFO(priv, "Unknown testmode command\n");
                result = -ENOSYS;
index 31f8949f2801b701cf409f93ffd68d726deb4115..a88085e9b3615e9739cb021cdfc85adff5e4aed4 100644 (file)
@@ -88,9 +88,15 @@ enum iwl_tm_cmd_t {
        IWL_TM_CMD_APP2DEV_LOAD_INIT_FW,
        IWL_TM_CMD_APP2DEV_CFG_INIT_CALIB,
        IWL_TM_CMD_APP2DEV_LOAD_RUNTIME_FW,
+       IWL_TM_CMD_APP2DEV_GET_EEPROM,
+       IWL_TM_CMD_APP2DEV_FIXRATE_REQ,
        /* if there is other new command for the driver layer operation,
         * append them here */
 
+       /* commands fom user space for uCode trace operations */
+       IWL_TM_CMD_APP2DEV_BEGIN_TRACE,
+       IWL_TM_CMD_APP2DEV_END_TRACE,
+       IWL_TM_CMD_APP2DEV_READ_TRACE,
 
        /* commands from kernel space to carry the synchronous response
         * to user application */
@@ -99,6 +105,11 @@ enum iwl_tm_cmd_t {
        /* commands from kernel space to multicast the spontaneous messages
         * to user application */
        IWL_TM_CMD_DEV2APP_UCODE_RX_PKT,
+
+       /* commands from kernel space to carry the eeprom response
+        * to user application */
+       IWL_TM_CMD_DEV2APP_EEPROM_RSP,
+
        IWL_TM_CMD_MAX,
 };
 
@@ -144,8 +155,31 @@ enum iwl_tm_attr_t {
         * application */
        IWL_TM_ATTR_UCODE_RX_PKT,
 
+       /* When IWL_TM_ATTR_COMMAND is IWL_TM_CMD_DEV2APP_EEPROM,
+        * The mandatory fields are:
+        * IWL_TM_ATTR_EEPROM for the data content responging to the user
+        * application */
+       IWL_TM_ATTR_EEPROM,
+
+       /* When IWL_TM_ATTR_COMMAND is IWL_TM_CMD_APP2DEV_XXX_TRACE,
+        * The mandatory fields are:
+        * IWL_TM_ATTR_MEM_TRACE_ADDR for the trace address
+        */
+       IWL_TM_ATTR_TRACE_ADDR,
+       IWL_TM_ATTR_TRACE_DATA,
+
+       /* When IWL_TM_ATTR_COMMAND is IWL_TM_CMD_APP2DEV_FIXRATE_REQ,
+        * The mandatory fields are:
+        * IWL_TM_ATTR_FIXRATE for the fixed rate
+        */
+       IWL_TM_ATTR_FIXRATE,
+
        IWL_TM_ATTR_MAX,
 };
 
+/* uCode trace buffer */
+#define TRACE_BUFF_SIZE                0x20000
+#define TRACE_BUFF_PADD                0x2000
+#define TRACE_TOTAL_SIZE       (TRACE_BUFF_SIZE + TRACE_BUFF_PADD)
 
 #endif
index e69597ea43e28e1c6ebde79655557e77c23b92d8..686e176b5ebdeb80c992860b49e2e64150892ca0 100644 (file)
@@ -32,6 +32,7 @@
 #include <linux/slab.h>
 #include <net/mac80211.h>
 #include "iwl-eeprom.h"
+#include "iwl-agn.h"
 #include "iwl-dev.h"
 #include "iwl-core.h"
 #include "iwl-sta.h"
@@ -85,6 +86,158 @@ void iwl_txq_update_write_ptr(struct iwl_priv *priv, struct iwl_tx_queue *txq)
        txq->need_update = 0;
 }
 
+static inline dma_addr_t iwl_tfd_tb_get_addr(struct iwl_tfd *tfd, u8 idx)
+{
+       struct iwl_tfd_tb *tb = &tfd->tbs[idx];
+
+       dma_addr_t addr = get_unaligned_le32(&tb->lo);
+       if (sizeof(dma_addr_t) > sizeof(u32))
+               addr |=
+               ((dma_addr_t)(le16_to_cpu(tb->hi_n_len) & 0xF) << 16) << 16;
+
+       return addr;
+}
+
+static inline u16 iwl_tfd_tb_get_len(struct iwl_tfd *tfd, u8 idx)
+{
+       struct iwl_tfd_tb *tb = &tfd->tbs[idx];
+
+       return le16_to_cpu(tb->hi_n_len) >> 4;
+}
+
+static inline void iwl_tfd_set_tb(struct iwl_tfd *tfd, u8 idx,
+                                 dma_addr_t addr, u16 len)
+{
+       struct iwl_tfd_tb *tb = &tfd->tbs[idx];
+       u16 hi_n_len = len << 4;
+
+       put_unaligned_le32(addr, &tb->lo);
+       if (sizeof(dma_addr_t) > sizeof(u32))
+               hi_n_len |= ((addr >> 16) >> 16) & 0xF;
+
+       tb->hi_n_len = cpu_to_le16(hi_n_len);
+
+       tfd->num_tbs = idx + 1;
+}
+
+static inline u8 iwl_tfd_get_num_tbs(struct iwl_tfd *tfd)
+{
+       return tfd->num_tbs & 0x1f;
+}
+
+static void iwlagn_unmap_tfd(struct iwl_priv *priv, struct iwl_cmd_meta *meta,
+                            struct iwl_tfd *tfd)
+{
+       struct pci_dev *dev = priv->pci_dev;
+       int i;
+       int num_tbs;
+
+       /* Sanity check on number of chunks */
+       num_tbs = iwl_tfd_get_num_tbs(tfd);
+
+       if (num_tbs >= IWL_NUM_OF_TBS) {
+               IWL_ERR(priv, "Too many chunks: %i\n", num_tbs);
+               /* @todo issue fatal error, it is quite serious situation */
+               return;
+       }
+
+       /* Unmap tx_cmd */
+       if (num_tbs)
+               pci_unmap_single(dev,
+                               dma_unmap_addr(meta, mapping),
+                               dma_unmap_len(meta, len),
+                               PCI_DMA_BIDIRECTIONAL);
+
+       /* Unmap chunks, if any. */
+       for (i = 1; i < num_tbs; i++)
+               pci_unmap_single(dev, iwl_tfd_tb_get_addr(tfd, i),
+                               iwl_tfd_tb_get_len(tfd, i), PCI_DMA_TODEVICE);
+}
+
+/**
+ * iwlagn_txq_free_tfd - Free all chunks referenced by TFD [txq->q.read_ptr]
+ * @priv - driver private data
+ * @txq - tx queue
+ *
+ * Does NOT advance any TFD circular buffer read/write indexes
+ * Does NOT free the TFD itself (which is within circular buffer)
+ */
+void iwlagn_txq_free_tfd(struct iwl_priv *priv, struct iwl_tx_queue *txq)
+{
+       struct iwl_tfd *tfd_tmp = txq->tfds;
+       int index = txq->q.read_ptr;
+
+       iwlagn_unmap_tfd(priv, &txq->meta[index], &tfd_tmp[index]);
+
+       /* free SKB */
+       if (txq->txb) {
+               struct sk_buff *skb;
+
+               skb = txq->txb[txq->q.read_ptr].skb;
+
+               /* can be called from irqs-disabled context */
+               if (skb) {
+                       dev_kfree_skb_any(skb);
+                       txq->txb[txq->q.read_ptr].skb = NULL;
+               }
+       }
+}
+
+int iwlagn_txq_attach_buf_to_tfd(struct iwl_priv *priv,
+                                struct iwl_tx_queue *txq,
+                                dma_addr_t addr, u16 len,
+                                u8 reset)
+{
+       struct iwl_queue *q;
+       struct iwl_tfd *tfd, *tfd_tmp;
+       u32 num_tbs;
+
+       q = &txq->q;
+       tfd_tmp = txq->tfds;
+       tfd = &tfd_tmp[q->write_ptr];
+
+       if (reset)
+               memset(tfd, 0, sizeof(*tfd));
+
+       num_tbs = iwl_tfd_get_num_tbs(tfd);
+
+       /* Each TFD can point to a maximum 20 Tx buffers */
+       if (num_tbs >= IWL_NUM_OF_TBS) {
+               IWL_ERR(priv, "Error can not send more than %d chunks\n",
+                         IWL_NUM_OF_TBS);
+               return -EINVAL;
+       }
+
+       if (WARN_ON(addr & ~DMA_BIT_MASK(36)))
+               return -EINVAL;
+
+       if (unlikely(addr & ~IWL_TX_DMA_MASK))
+               IWL_ERR(priv, "Unaligned address = %llx\n",
+                         (unsigned long long)addr);
+
+       iwl_tfd_set_tb(tfd, num_tbs, addr, len);
+
+       return 0;
+}
+
+/*
+ * Tell nic where to find circular buffer of Tx Frame Descriptors for
+ * given Tx queue, and enable the DMA channel used for that queue.
+ *
+ * supports up to 16 Tx queues in DRAM, mapped to up to 8 Tx DMA
+ * channels supported in hardware.
+ */
+static int iwlagn_tx_queue_init(struct iwl_priv *priv, struct iwl_tx_queue *txq)
+{
+       int txq_id = txq->q.id;
+
+       /* Circular buffer (TFD queue in DRAM) physical base address */
+       iwl_write_direct32(priv, FH_MEM_CBBC_QUEUE(txq_id),
+                            txq->q.dma_addr >> 8);
+
+       return 0;
+}
+
 /**
  * iwl_tx_queue_unmap -  Unmap any remaining DMA mappings and free skb's
  */
@@ -97,7 +250,7 @@ void iwl_tx_queue_unmap(struct iwl_priv *priv, int txq_id)
                return;
 
         while (q->write_ptr != q->read_ptr) {
-               priv->cfg->ops->lib->txq_free_tfd(priv, txq);
+               iwlagn_txq_free_tfd(priv, txq);
                q->read_ptr = iwl_queue_inc_wrap(q->read_ptr, q->n_bd);
        }
 }
@@ -154,7 +307,7 @@ void iwl_cmd_queue_unmap(struct iwl_priv *priv)
                return;
 
        while (q->read_ptr != q->write_ptr) {
-               i = get_cmd_index(q, q->read_ptr, 0);
+               i = get_cmd_index(q, q->read_ptr);
 
                if (txq->meta[i].flags & CMD_MAPPED) {
                        pci_unmap_single(priv->pci_dev,
@@ -166,15 +319,6 @@ void iwl_cmd_queue_unmap(struct iwl_priv *priv)
 
                q->read_ptr = iwl_queue_inc_wrap(q->read_ptr, q->n_bd);
        }
-
-       i = q->n_window;
-       if (txq->meta[i].flags & CMD_MAPPED) {
-               pci_unmap_single(priv->pci_dev,
-                                dma_unmap_addr(&txq->meta[i], mapping),
-                                dma_unmap_len(&txq->meta[i], len),
-                                PCI_DMA_BIDIRECTIONAL);
-               txq->meta[i].flags = 0;
-       }
 }
 
 /**
@@ -194,7 +338,7 @@ void iwl_cmd_queue_free(struct iwl_priv *priv)
        iwl_cmd_queue_unmap(priv);
 
        /* De-alloc array of command/tx buffers */
-       for (i = 0; i <= TFD_CMD_SLOTS; i++)
+       for (i = 0; i < TFD_CMD_SLOTS; i++)
                kfree(txq->cmd[i]);
 
        /* De-alloc circular buffer of TFDs */
@@ -334,33 +478,17 @@ int iwl_tx_queue_init(struct iwl_priv *priv, struct iwl_tx_queue *txq,
 {
        int i, len;
        int ret;
-       int actual_slots = slots_num;
-
-       /*
-        * Alloc buffer array for commands (Tx or other types of commands).
-        * For the command queue (#4/#9), allocate command space + one big
-        * command for scan, since scan command is very huge; the system will
-        * not have two scans at the same time, so only one is needed.
-        * For normal Tx queues (all other queues), no super-size command
-        * space is needed.
-        */
-       if (txq_id == priv->cmd_queue)
-               actual_slots++;
 
-       txq->meta = kzalloc(sizeof(struct iwl_cmd_meta) * actual_slots,
+       txq->meta = kzalloc(sizeof(struct iwl_cmd_meta) * slots_num,
                            GFP_KERNEL);
-       txq->cmd = kzalloc(sizeof(struct iwl_device_cmd *) * actual_slots,
+       txq->cmd = kzalloc(sizeof(struct iwl_device_cmd *) * slots_num,
                           GFP_KERNEL);
 
        if (!txq->meta || !txq->cmd)
                goto out_free_arrays;
 
        len = sizeof(struct iwl_device_cmd);
-       for (i = 0; i < actual_slots; i++) {
-               /* only happens for cmd queue */
-               if (i == slots_num)
-                       len = IWL_MAX_CMD_SIZE;
-
+       for (i = 0; i < slots_num; i++) {
                txq->cmd[i] = kmalloc(len, GFP_KERNEL);
                if (!txq->cmd[i])
                        goto err;
@@ -391,11 +519,11 @@ int iwl_tx_queue_init(struct iwl_priv *priv, struct iwl_tx_queue *txq,
                return ret;
 
        /* Tell device where to find queue */
-       priv->cfg->ops->lib->txq_init(priv, txq);
+       iwlagn_tx_queue_init(priv, txq);
 
        return 0;
 err:
-       for (i = 0; i < actual_slots; i++)
+       for (i = 0; i < slots_num; i++)
                kfree(txq->cmd[i]);
 out_free_arrays:
        kfree(txq->meta);
@@ -420,7 +548,7 @@ void iwl_tx_queue_reset(struct iwl_priv *priv, struct iwl_tx_queue *txq,
        iwl_queue_init(priv, &txq->q, TFD_QUEUE_SIZE_MAX, slots_num, txq_id);
 
        /* Tell device where to find queue */
-       priv->cfg->ops->lib->txq_init(priv, txq);
+       iwlagn_tx_queue_init(priv, txq);
 }
 
 /*************** HOST COMMAND QUEUE FUNCTIONS   *****/
@@ -443,23 +571,49 @@ int iwl_enqueue_hcmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd)
        dma_addr_t phys_addr;
        unsigned long flags;
        u32 idx;
-       u16 fix_size;
+       u16 copy_size, cmd_size;
        bool is_ct_kill = false;
+       bool had_nocopy = false;
+       int i;
+       u8 *cmd_dest;
+#ifdef CONFIG_IWLWIFI_DEVICE_TRACING
+       const void *trace_bufs[IWL_MAX_CMD_TFDS + 1] = {};
+       int trace_lens[IWL_MAX_CMD_TFDS + 1] = {};
+       int trace_idx;
+#endif
+
+       if (test_bit(STATUS_FW_ERROR, &priv->status)) {
+               IWL_WARN(priv, "fw recovery, no hcmd send\n");
+               return -EIO;
+       }
 
-       fix_size = (u16)(cmd->len + sizeof(out_cmd->hdr));
+       copy_size = sizeof(out_cmd->hdr);
+       cmd_size = sizeof(out_cmd->hdr);
+
+       /* need one for the header if the first is NOCOPY */
+       BUILD_BUG_ON(IWL_MAX_CMD_TFDS > IWL_NUM_OF_TBS - 1);
+
+       for (i = 0; i < IWL_MAX_CMD_TFDS; i++) {
+               if (!cmd->len[i])
+                       continue;
+               if (cmd->dataflags[i] & IWL_HCMD_DFL_NOCOPY) {
+                       had_nocopy = true;
+               } else {
+                       /* NOCOPY must not be followed by normal! */
+                       if (WARN_ON(had_nocopy))
+                               return -EINVAL;
+                       copy_size += cmd->len[i];
+               }
+               cmd_size += cmd->len[i];
+       }
 
        /*
         * If any of the command structures end up being larger than
-        * the TFD_MAX_PAYLOAD_SIZE, and it sent as a 'small' command then
-        * we will need to increase the size of the TFD entries
-        * Also, check to see if command buffer should not exceed the size
-        * of device_cmd and max_cmd_size.
+        * the TFD_MAX_PAYLOAD_SIZE and they aren't dynamically
+        * allocated into separate TFDs, then we will need to
+        * increase the size of the buffers.
         */
-       if (WARN_ON((fix_size > TFD_MAX_PAYLOAD_SIZE) &&
-                   !(cmd->flags & CMD_SIZE_HUGE)))
-               return -EINVAL;
-
-       if (WARN_ON(fix_size > IWL_MAX_CMD_SIZE))
+       if (WARN_ON(copy_size > TFD_MAX_PAYLOAD_SIZE))
                return -EINVAL;
 
        if (iwl_is_rfkill(priv) || iwl_is_ctkill(priv)) {
@@ -468,14 +622,6 @@ int iwl_enqueue_hcmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd)
                return -EIO;
        }
 
-       /*
-        * As we only have a single huge buffer, check that the command
-        * is synchronous (otherwise buffers could end up being reused).
-        */
-
-       if (WARN_ON((cmd->flags & CMD_ASYNC) && (cmd->flags & CMD_SIZE_HUGE)))
-               return -EINVAL;
-
        spin_lock_irqsave(&priv->hcmd_lock, flags);
 
        if (iwl_queue_space(q) < ((cmd->flags & CMD_ASYNC) ? 2 : 1)) {
@@ -490,7 +636,7 @@ int iwl_enqueue_hcmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd)
                return -ENOSPC;
        }
 
-       idx = get_cmd_index(q, q->write_ptr, cmd->flags & CMD_SIZE_HUGE);
+       idx = get_cmd_index(q, q->write_ptr);
        out_cmd = txq->cmd[idx];
        out_meta = &txq->meta[idx];
 
@@ -505,57 +651,84 @@ int iwl_enqueue_hcmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd)
        if (cmd->flags & CMD_ASYNC)
                out_meta->callback = cmd->callback;
 
-       out_cmd->hdr.cmd = cmd->id;
-       memcpy(&out_cmd->cmd.payload, cmd->data, cmd->len);
-
-       /* At this point, the out_cmd now has all of the incoming cmd
-        * information */
+       /* set up the header */
 
+       out_cmd->hdr.cmd = cmd->id;
        out_cmd->hdr.flags = 0;
        out_cmd->hdr.sequence = cpu_to_le16(QUEUE_TO_SEQ(priv->cmd_queue) |
-                       INDEX_TO_SEQ(q->write_ptr));
-       if (cmd->flags & CMD_SIZE_HUGE)
-               out_cmd->hdr.sequence |= SEQ_HUGE_FRAME;
-
-#ifdef CONFIG_IWLWIFI_DEBUG
-       switch (out_cmd->hdr.cmd) {
-       case REPLY_TX_LINK_QUALITY_CMD:
-       case SENSITIVITY_CMD:
-               IWL_DEBUG_HC_DUMP(priv, "Sending command %s (#%x), seq: 0x%04X, "
-                               "%d bytes at %d[%d]:%d\n",
-                               get_cmd_string(out_cmd->hdr.cmd),
-                               out_cmd->hdr.cmd,
-                               le16_to_cpu(out_cmd->hdr.sequence), fix_size,
-                               q->write_ptr, idx, priv->cmd_queue);
-               break;
-       default:
-               IWL_DEBUG_HC(priv, "Sending command %s (#%x), seq: 0x%04X, "
-                               "%d bytes at %d[%d]:%d\n",
-                               get_cmd_string(out_cmd->hdr.cmd),
-                               out_cmd->hdr.cmd,
-                               le16_to_cpu(out_cmd->hdr.sequence), fix_size,
-                               q->write_ptr, idx, priv->cmd_queue);
+                                           INDEX_TO_SEQ(q->write_ptr));
+
+       /* and copy the data that needs to be copied */
+
+       cmd_dest = &out_cmd->cmd.payload[0];
+       for (i = 0; i < IWL_MAX_CMD_TFDS; i++) {
+               if (!cmd->len[i])
+                       continue;
+               if (cmd->dataflags[i] & IWL_HCMD_DFL_NOCOPY)
+                       break;
+               memcpy(cmd_dest, cmd->data[i], cmd->len[i]);
+               cmd_dest += cmd->len[i];
        }
-#endif
+
+       IWL_DEBUG_HC(priv, "Sending command %s (#%x), seq: 0x%04X, "
+                       "%d bytes at %d[%d]:%d\n",
+                       get_cmd_string(out_cmd->hdr.cmd),
+                       out_cmd->hdr.cmd,
+                       le16_to_cpu(out_cmd->hdr.sequence), cmd_size,
+                       q->write_ptr, idx, priv->cmd_queue);
+
        phys_addr = pci_map_single(priv->pci_dev, &out_cmd->hdr,
-                                  fix_size, PCI_DMA_BIDIRECTIONAL);
+                                  copy_size, PCI_DMA_BIDIRECTIONAL);
        if (unlikely(pci_dma_mapping_error(priv->pci_dev, phys_addr))) {
                idx = -ENOMEM;
                goto out;
        }
 
        dma_unmap_addr_set(out_meta, mapping, phys_addr);
-       dma_unmap_len_set(out_meta, len, fix_size);
+       dma_unmap_len_set(out_meta, len, copy_size);
+
+       iwlagn_txq_attach_buf_to_tfd(priv, txq, phys_addr, copy_size, 1);
+#ifdef CONFIG_IWLWIFI_DEVICE_TRACING
+       trace_bufs[0] = &out_cmd->hdr;
+       trace_lens[0] = copy_size;
+       trace_idx = 1;
+#endif
+
+       for (i = 0; i < IWL_MAX_CMD_TFDS; i++) {
+               if (!cmd->len[i])
+                       continue;
+               if (!(cmd->dataflags[i] & IWL_HCMD_DFL_NOCOPY))
+                       continue;
+               phys_addr = pci_map_single(priv->pci_dev, (void *)cmd->data[i],
+                                          cmd->len[i], PCI_DMA_TODEVICE);
+               if (pci_dma_mapping_error(priv->pci_dev, phys_addr)) {
+                       iwlagn_unmap_tfd(priv, out_meta,
+                                        &txq->tfds[q->write_ptr]);
+                       idx = -ENOMEM;
+                       goto out;
+               }
+
+               iwlagn_txq_attach_buf_to_tfd(priv, txq, phys_addr,
+                                            cmd->len[i], 0);
+#ifdef CONFIG_IWLWIFI_DEVICE_TRACING
+               trace_bufs[trace_idx] = cmd->data[i];
+               trace_lens[trace_idx] = cmd->len[i];
+               trace_idx++;
+#endif
+       }
 
        out_meta->flags = cmd->flags | CMD_MAPPED;
 
        txq->need_update = 1;
 
-       trace_iwlwifi_dev_hcmd(priv, &out_cmd->hdr, fix_size, cmd->flags);
-
-       priv->cfg->ops->lib->txq_attach_buf_to_tfd(priv, txq,
-                                                  phys_addr, fix_size, 1,
-                                                  U32_PAD(cmd->len));
+       /* check that tracing gets all possible blocks */
+       BUILD_BUG_ON(IWL_MAX_CMD_TFDS + 1 != 3);
+#ifdef CONFIG_IWLWIFI_DEVICE_TRACING
+       trace_iwlwifi_dev_hcmd(priv, cmd->flags,
+                              trace_bufs[0], trace_lens[0],
+                              trace_bufs[1], trace_lens[1],
+                              trace_bufs[2], trace_lens[2]);
+#endif
 
        /* Increment and update queue's write index */
        q->write_ptr = iwl_queue_inc_wrap(q->write_ptr, q->n_bd);
@@ -573,8 +746,7 @@ int iwl_enqueue_hcmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd)
  * need to be reclaimed. As result, some free space forms.  If there is
  * enough free space (> low mark), wake the stack that feeds us.
  */
-static void iwl_hcmd_queue_reclaim(struct iwl_priv *priv, int txq_id,
-                                  int idx, int cmd_idx)
+static void iwl_hcmd_queue_reclaim(struct iwl_priv *priv, int txq_id, int idx)
 {
        struct iwl_tx_queue *txq = &priv->txq[txq_id];
        struct iwl_queue *q = &txq->q;
@@ -614,7 +786,6 @@ void iwl_tx_cmd_complete(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb)
        int txq_id = SEQ_TO_QUEUE(sequence);
        int index = SEQ_TO_INDEX(sequence);
        int cmd_index;
-       bool huge = !!(pkt->hdr.sequence & SEQ_HUGE_FRAME);
        struct iwl_device_cmd *cmd;
        struct iwl_cmd_meta *meta;
        struct iwl_tx_queue *txq = &priv->txq[priv->cmd_queue];
@@ -632,14 +803,11 @@ void iwl_tx_cmd_complete(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb)
                return;
        }
 
-       cmd_index = get_cmd_index(&txq->q, index, huge);
+       cmd_index = get_cmd_index(&txq->q, index);
        cmd = txq->cmd[cmd_index];
        meta = &txq->meta[cmd_index];
 
-       pci_unmap_single(priv->pci_dev,
-                        dma_unmap_addr(meta, mapping),
-                        dma_unmap_len(meta, len),
-                        PCI_DMA_BIDIRECTIONAL);
+       iwlagn_unmap_tfd(priv, meta, &txq->tfds[index]);
 
        /* Input error checking is done when commands are added to queue. */
        if (meta->flags & CMD_WANT_SKB) {
@@ -650,7 +818,7 @@ void iwl_tx_cmd_complete(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb)
 
        spin_lock_irqsave(&priv->hcmd_lock, flags);
 
-       iwl_hcmd_queue_reclaim(priv, txq_id, index, cmd_index);
+       iwl_hcmd_queue_reclaim(priv, txq_id, index);
 
        if (!(meta->flags & CMD_ASYNC)) {
                clear_bit(STATUS_HCMD_ACTIVE, &priv->status);
index 5665a1a9b99ef0ac511e5bafe68d3f7d19f1333f..a414768f40f11e7e002beae44d292972547cfbde 100644 (file)
@@ -565,7 +565,7 @@ static int iwm_mlme_assoc_complete(struct iwm_priv *iwm, u8 *buf,
                if (!test_and_clear_bit(IWM_STATUS_SME_CONNECTING, &iwm->status)
                    && iwm->conf.mode == UMAC_MODE_BSS) {
                        cancel_delayed_work(&iwm->disconnect);
-                       cfg80211_roamed(iwm_to_ndev(iwm),
+                       cfg80211_roamed(iwm_to_ndev(iwm), NULL,
                                        complete->bssid,
                                        iwm->req_ie, iwm->req_ie_len,
                                        iwm->resp_ie, iwm->resp_ie_len,
@@ -586,7 +586,7 @@ static int iwm_mlme_assoc_complete(struct iwm_priv *iwm, u8 *buf,
                                                WLAN_STATUS_SUCCESS,
                                                GFP_KERNEL);
                else
-                       cfg80211_roamed(iwm_to_ndev(iwm),
+                       cfg80211_roamed(iwm_to_ndev(iwm), NULL,
                                        complete->bssid,
                                        iwm->req_ie, iwm->req_ie_len,
                                        iwm->resp_ie, iwm->resp_ie_len,
index d3d5e0853c45822b8b58fa131732d7aca55d7e7c..f807447e4d993cf1fae0befdd13e57b4aa25f764 100644 (file)
@@ -196,6 +196,8 @@ mwifiex_11n_aggregate_pkt(struct mwifiex_private *priv,
                if (skb_src)
                        pra_list->total_pkts_size -= skb_src->len;
 
+               atomic_dec(&priv->wmm.tx_pkts_queued);
+
                spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock,
                                       ra_list_flags);
                mwifiex_11n_form_amsdu_pkt(skb_aggr, skb_src, &pad);
@@ -257,6 +259,8 @@ mwifiex_11n_aggregate_pkt(struct mwifiex_private *priv,
 
                pra_list->total_pkts_size += skb_aggr->len;
 
+               atomic_inc(&priv->wmm.tx_pkts_queued);
+
                tx_info_aggr->flags |= MWIFIEX_BUF_FLAG_REQUEUED_PKT;
                spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock,
                                       ra_list_flags);
index 672701dc2721b56575dc6ba11e1964c494aebf9a..8316b3cd92cdf421975c96ffd9955cc62ae49483 100644 (file)
@@ -69,7 +69,8 @@ struct mwifiex_drv_mode {
 #define MWIFIEX_TIMER_10S                      10000
 #define MWIFIEX_TIMER_1S                       1000
 
-#define MAX_TX_PENDING      60
+#define MAX_TX_PENDING      100
+#define LOW_TX_PENDING      80
 
 #define MWIFIEX_UPLD_SIZE               (2312)
 
@@ -202,6 +203,7 @@ struct mwifiex_tid_tbl {
 #define WMM_HIGHEST_PRIORITY           7
 #define HIGH_PRIO_TID                          7
 #define LOW_PRIO_TID                           0
+#define NO_PKT_PRIO_TID                                (-1)
 
 struct mwifiex_wmm_desc {
        struct mwifiex_tid_tbl tid_tbl_ptr[MAX_NUM_TID];
@@ -213,7 +215,10 @@ struct mwifiex_wmm_desc {
        u32 drv_pkt_delay_max;
        u8 queue_priority[IEEE80211_MAX_QUEUES];
        u32 user_pri_pkt_tx_ctrl[WMM_HIGHEST_PRIORITY + 1];     /* UP: 0 to 7 */
-
+       /* Number of transmit packets queued */
+       atomic_t tx_pkts_queued;
+       /* Tracks highest priority with a packet queued */
+       atomic_t highest_queued_prio;
 };
 
 struct mwifiex_802_11_security {
index 210120889dfe446c86b000d8f66e5d6e528a6847..aaa50c0741965c4bd7f3f39748a6ba856b1afb07 100644 (file)
@@ -140,7 +140,9 @@ int mwifiex_write_data_complete(struct mwifiex_adapter *adapter,
        } else {
                priv->stats.tx_errors++;
        }
-       atomic_dec(&adapter->tx_pending);
+
+       if (atomic_dec_return(&adapter->tx_pending) >= LOW_TX_PENDING)
+               goto done;
 
        for (i = 0; i < adapter->priv_num; i++) {
 
index faa09e32902eb140344da184af90a2fdf4e54afe..91634daec306c093928a7718c176d734b7bf07aa 100644 (file)
@@ -177,14 +177,20 @@ static void mwifiex_wmm_default_queue_priorities(struct mwifiex_private *priv)
  * This function map ACs to TIDs.
  */
 static void
-mwifiex_wmm_queue_priorities_tid(u8 queue_priority[])
+mwifiex_wmm_queue_priorities_tid(struct mwifiex_wmm_desc *wmm)
 {
+       u8 *queue_priority = wmm->queue_priority;
        int i;
 
        for (i = 0; i < 4; ++i) {
                tos_to_tid[7 - (i * 2)] = ac_to_tid[queue_priority[i]][1];
                tos_to_tid[6 - (i * 2)] = ac_to_tid[queue_priority[i]][0];
        }
+
+       for (i = 0; i < MAX_NUM_TID; ++i)
+               tos_to_tid_inv[tos_to_tid[i]] = (u8)i;
+
+       atomic_set(&wmm->highest_queued_prio, HIGH_PRIO_TID);
 }
 
 /*
@@ -246,7 +252,7 @@ mwifiex_wmm_setup_queue_priorities(struct mwifiex_private *priv,
                }
        }
 
-       mwifiex_wmm_queue_priorities_tid(priv->wmm.queue_priority);
+       mwifiex_wmm_queue_priorities_tid(&priv->wmm);
 }
 
 /*
@@ -399,6 +405,9 @@ mwifiex_wmm_init(struct mwifiex_adapter *adapter)
                priv->add_ba_param.timeout = MWIFIEX_DEFAULT_BLOCK_ACK_TIMEOUT;
                priv->add_ba_param.tx_win_size = MWIFIEX_AMPDU_DEF_TXWINSIZE;
                priv->add_ba_param.rx_win_size = MWIFIEX_AMPDU_DEF_RXWINSIZE;
+
+               atomic_set(&priv->wmm.tx_pkts_queued, 0);
+               atomic_set(&priv->wmm.highest_queued_prio, HIGH_PRIO_TID);
        }
 }
 
@@ -408,17 +417,13 @@ mwifiex_wmm_init(struct mwifiex_adapter *adapter)
 int
 mwifiex_wmm_lists_empty(struct mwifiex_adapter *adapter)
 {
-       int i, j;
+       int i;
        struct mwifiex_private *priv;
 
-       for (j = 0; j < adapter->priv_num; ++j) {
-               priv = adapter->priv[j];
-               if (priv) {
-                       for (i = 0; i < MAX_NUM_TID; i++)
-                               if (!mwifiex_wmm_is_ra_list_empty(
-                                            &priv->wmm.tid_tbl_ptr[i].ra_list))
-                                       return false;
-               }
+       for (i = 0; i < adapter->priv_num; ++i) {
+               priv = adapter->priv[i];
+               if (priv && atomic_read(&priv->wmm.tx_pkts_queued))
+                               return false;
        }
 
        return true;
@@ -468,6 +473,9 @@ static void mwifiex_wmm_cleanup_queues(struct mwifiex_private *priv)
        for (i = 0; i < MAX_NUM_TID; i++)
                mwifiex_wmm_del_pkts_in_ralist(priv, &priv->wmm.tid_tbl_ptr[i].
                                                     ra_list);
+
+       atomic_set(&priv->wmm.tx_pkts_queued, 0);
+       atomic_set(&priv->wmm.highest_queued_prio, HIGH_PRIO_TID);
 }
 
 /*
@@ -638,6 +646,13 @@ mwifiex_wmm_add_buf_txqueue(struct mwifiex_adapter *adapter,
 
        ra_list->total_pkts_size += skb->len;
 
+       atomic_inc(&priv->wmm.tx_pkts_queued);
+
+       if (atomic_read(&priv->wmm.highest_queued_prio) <
+                                               tos_to_tid_inv[tid_down])
+               atomic_set(&priv->wmm.highest_queued_prio,
+                                               tos_to_tid_inv[tid_down]);
+
        spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock, flags);
 }
 
@@ -863,9 +878,14 @@ mwifiex_wmm_get_highest_priolist_ptr(struct mwifiex_adapter *adapter,
                }
 
                do {
+                       atomic_t *hqp;
+                       spinlock_t *lock;
+
                        priv_tmp = bssprio_node->priv;
+                       hqp = &priv_tmp->wmm.highest_queued_prio;
+                       lock = &priv_tmp->wmm.ra_list_spinlock;
 
-                       for (i = HIGH_PRIO_TID; i >= LOW_PRIO_TID; --i) {
+                       for (i = atomic_read(hqp); i >= LOW_PRIO_TID; --i) {
 
                                tid_ptr = &(priv_tmp)->wmm.
                                        tid_tbl_ptr[tos_to_tid[i]];
@@ -903,6 +923,11 @@ mwifiex_wmm_get_highest_priolist_ptr(struct mwifiex_adapter *adapter,
                                        is_list_empty =
                                                skb_queue_empty(&ptr->skb_head);
                                        if (!is_list_empty) {
+                                               spin_lock_irqsave(lock, flags);
+                                               if (atomic_read(hqp) > i)
+                                                       atomic_set(hqp, i);
+                                               spin_unlock_irqrestore(lock,
+                                                                       flags);
                                                *priv = priv_tmp;
                                                *tid = tos_to_tid[i];
                                                return ptr;
@@ -921,6 +946,12 @@ mwifiex_wmm_get_highest_priolist_ptr(struct mwifiex_adapter *adapter,
                                } while (ptr != head);
                        }
 
+                       /* No packet at any TID for this priv. Mark as such
+                        * to skip checking TIDs for this priv (until pkt is
+                        * added).
+                        */
+                       atomic_set(hqp, NO_PKT_PRIO_TID);
+
                        /* Get next bss priority node */
                        bssprio_node = list_first_entry(&bssprio_node->list,
                                                struct mwifiex_bss_prio_node,
@@ -1028,6 +1059,7 @@ mwifiex_send_single_packet(struct mwifiex_private *priv,
                                .bss_prio_cur->list,
                                struct mwifiex_bss_prio_node,
                                list);
+               atomic_dec(&priv->wmm.tx_pkts_queued);
                spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock,
                                       ra_list_flags);
        }
@@ -1134,6 +1166,7 @@ mwifiex_send_processed_packet(struct mwifiex_private *priv,
                                .bss_prio_cur->list,
                                struct mwifiex_bss_prio_node,
                                list);
+               atomic_dec(&priv->wmm.tx_pkts_queued);
                spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock,
                                       ra_list_flags);
        }
@@ -1227,5 +1260,5 @@ mwifiex_wmm_process_tx(struct mwifiex_adapter *adapter)
 
                if (mwifiex_dequeue_tx_packet(adapter))
                        break;
-       } while (true);
+       } while (!mwifiex_wmm_lists_empty(adapter));
 }
index e18358725b69813077de8d9e55f8a98d5fa7a021..a8f3bc740dfaf8354abff344f5ab7665bd8faf58 100644 (file)
@@ -82,6 +82,7 @@ static struct usb_device_id p54u_table[] __devinitdata = {
        {USB_DEVICE(0x06b9, 0x0121)},   /* Thomson SpeedTouch 121g */
        {USB_DEVICE(0x0707, 0xee13)},   /* SMC 2862W-G version 2 */
        {USB_DEVICE(0x083a, 0x4521)},   /* Siemens Gigaset USB Adapter 54 version 2 */
+       {USB_DEVICE(0x083a, 0xc501)},   /* Zoom Wireless-G 4410 */
        {USB_DEVICE(0x083a, 0xf503)},   /* Accton FD7050E ver 1010ec  */
        {USB_DEVICE(0x0846, 0x4240)},   /* Netgear WG111 (v2) */
        {USB_DEVICE(0x0915, 0x2000)},   /* Cohiba Proto board */
index 518542b4bf9e87a0571431d4374842b72ef62faa..29f938930667d3696efd82f5d45fc9c98c15ac39 100644 (file)
@@ -2830,7 +2830,8 @@ static void rndis_wlan_do_link_up_work(struct usbnet *usbdev)
                                                req_ie_len, resp_ie,
                                                resp_ie_len, 0, GFP_KERNEL);
                else
-                       cfg80211_roamed(usbdev->net, bssid, req_ie, req_ie_len,
+                       cfg80211_roamed(usbdev->net, NULL, bssid,
+                                       req_ie, req_ie_len,
                                        resp_ie, resp_ie_len, GFP_KERNEL);
        } else if (priv->infra_mode == NDIS_80211_INFRA_ADHOC)
                cfg80211_ibss_joined(usbdev->net, bssid, GFP_KERNEL);
index 2bb71195e97658c98a39494d6190e3ce745b6344..39b0297ce925d6625291c91873d2948f42432a4c 100644 (file)
@@ -190,7 +190,7 @@ static void _rtl_ps_inactive_ps(struct ieee80211_hw *hw)
 
        ppsc->swrf_processing = true;
 
-       if (ppsc->inactive_pwrstate == ERFOFF &&
+       if (ppsc->inactive_pwrstate == ERFON &&
            rtlhal->interface == INTF_PCI) {
                if ((ppsc->reg_rfps_level & RT_RF_OFF_LEVL_ASPM) &&
                    RT_IN_PS_LEVEL(ppsc, RT_PS_LEVEL_ASPM) &&
index c5424cad43cb578ea57d8d095dfba92a4b23c772..d2cc81586a6a9c95a4b1660b0a377a024ac7fee9 100644 (file)
@@ -728,7 +728,7 @@ void rtl92c_phy_set_bw_mode(struct ieee80211_hw *hw,
                return;
        rtlphy->set_bwmode_inprogress = true;
        if ((!is_hal_stop(rtlhal)) && !(RT_CANNOT_IO(hw))) {
-               rtlphy->set_bwmode_inprogress = false;
+               rtlpriv->cfg->ops->phy_set_bw_mode_callback(hw);
        } else {
                RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING,
                         ("FALSE driver sleep or unload\n"));
index 73ae8a431848693818e55fcd76cceb6717031284..abe0fcc753686fc9ac888bb3b64a176fcd530382 100644 (file)
@@ -366,6 +366,75 @@ bool rtl92c_phy_config_rf_with_headerfile(struct ieee80211_hw *hw,
        return true;
 }
 
+void rtl92ce_phy_set_bw_mode_callback(struct ieee80211_hw *hw)
+{
+       struct rtl_priv *rtlpriv = rtl_priv(hw);
+       struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
+       struct rtl_phy *rtlphy = &(rtlpriv->phy);
+       struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
+       u8 reg_bw_opmode;
+       u8 reg_prsr_rsc;
+
+       RT_TRACE(rtlpriv, COMP_SCAN, DBG_TRACE,
+                ("Switch to %s bandwidth\n",
+                 rtlphy->current_chan_bw == HT_CHANNEL_WIDTH_20 ?
+                 "20MHz" : "40MHz"))
+
+       if (is_hal_stop(rtlhal)) {
+               rtlphy->set_bwmode_inprogress = false;
+               return;
+       }
+
+       reg_bw_opmode = rtl_read_byte(rtlpriv, REG_BWOPMODE);
+       reg_prsr_rsc = rtl_read_byte(rtlpriv, REG_RRSR + 2);
+
+       switch (rtlphy->current_chan_bw) {
+       case HT_CHANNEL_WIDTH_20:
+               reg_bw_opmode |= BW_OPMODE_20MHZ;
+               rtl_write_byte(rtlpriv, REG_BWOPMODE, reg_bw_opmode);
+               break;
+       case HT_CHANNEL_WIDTH_20_40:
+               reg_bw_opmode &= ~BW_OPMODE_20MHZ;
+               rtl_write_byte(rtlpriv, REG_BWOPMODE, reg_bw_opmode);
+               reg_prsr_rsc =
+                   (reg_prsr_rsc & 0x90) | (mac->cur_40_prime_sc << 5);
+               rtl_write_byte(rtlpriv, REG_RRSR + 2, reg_prsr_rsc);
+               break;
+       default:
+               RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
+                        ("unknown bandwidth: %#X\n", rtlphy->current_chan_bw));
+               break;
+       }
+
+       switch (rtlphy->current_chan_bw) {
+       case HT_CHANNEL_WIDTH_20:
+               rtl_set_bbreg(hw, RFPGA0_RFMOD, BRFMOD, 0x0);
+               rtl_set_bbreg(hw, RFPGA1_RFMOD, BRFMOD, 0x0);
+               rtl_set_bbreg(hw, RFPGA0_ANALOGPARAMETER2, BIT(10), 1);
+               break;
+       case HT_CHANNEL_WIDTH_20_40:
+               rtl_set_bbreg(hw, RFPGA0_RFMOD, BRFMOD, 0x1);
+               rtl_set_bbreg(hw, RFPGA1_RFMOD, BRFMOD, 0x1);
+
+               rtl_set_bbreg(hw, RCCK0_SYSTEM, BCCK_SIDEBAND,
+                             (mac->cur_40_prime_sc >> 1));
+               rtl_set_bbreg(hw, ROFDM1_LSTF, 0xC00, mac->cur_40_prime_sc);
+               rtl_set_bbreg(hw, RFPGA0_ANALOGPARAMETER2, BIT(10), 0);
+
+               rtl_set_bbreg(hw, 0x818, (BIT(26) | BIT(27)),
+                             (mac->cur_40_prime_sc ==
+                              HAL_PRIME_CHNL_OFFSET_LOWER) ? 2 : 1);
+               break;
+       default:
+               RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
+                        ("unknown bandwidth: %#X\n", rtlphy->current_chan_bw));
+               break;
+       }
+       rtl92ce_phy_rf6052_set_bandwidth(hw, rtlphy->current_chan_bw);
+       rtlphy->set_bwmode_inprogress = false;
+       RT_TRACE(rtlpriv, COMP_SCAN, DBG_TRACE, ("<==\n"));
+}
+
 void _rtl92ce_phy_lc_calibrate(struct ieee80211_hw *hw, bool is2t)
 {
        u8 tmpreg;
index ad580852cc76284f28c64d7fbea52c344deaf9fe..be2c92adef33d293e1579a78f57c4eb56e8574de 100644 (file)
@@ -257,5 +257,6 @@ bool _rtl92ce_phy_config_bb_with_headerfile(struct ieee80211_hw *hw,
                                            u8 configtype);
 bool _rtl92ce_phy_config_bb_with_pgheaderfile(struct ieee80211_hw *hw,
                                              u8 configtype);
+void rtl92ce_phy_set_bw_mode_callback(struct ieee80211_hw *hw);
 
 #endif
index 390bbb5ee11d425a4da2672e4b0895288c9e2076..373dc78af1dcaef05f5511de4e509a87f06add03 100644 (file)
@@ -232,6 +232,7 @@ static struct rtl_hal_ops rtl8192ce_hal_ops = {
        .config_bb_with_headerfile = _rtl92ce_phy_config_bb_with_headerfile,
        .config_bb_with_pgheaderfile = _rtl92ce_phy_config_bb_with_pgheaderfile,
        .phy_lc_calibrate = _rtl92ce_phy_lc_calibrate,
+       .phy_set_bw_mode_callback = rtl92ce_phy_set_bw_mode_callback,
        .dm_dynamic_txpower = rtl92ce_dm_dynamic_txpower,
 };
 
index bcca39418f904f9bfe90c1dabcb9ae226e8e94ba..5bda24e26c0e7cacb77e9257063717e9c15e118b 100644 (file)
@@ -570,7 +570,7 @@ ar6k_cfg80211_connect_event(struct ar6_softc *ar, u16 channel,
                                 WLAN_STATUS_SUCCESS, GFP_KERNEL);
     } else {
         /* inform roam event to cfg80211 */
-        cfg80211_roamed(ar->arNetDev, bssid,
+       cfg80211_roamed(ar->arNetDev, ibss_channel, bssid,
                         assocReqIe, assocReqLen,
                         assocRespIe, assocRespLen,
                         GFP_KERNEL);
index 555b056b49b1db6f60b0b82245eb2338b6f39021..7aaf99cc3a7b0e84d635b053afe3c13911b71120 100644 (file)
@@ -2630,7 +2630,7 @@ wl_bss_roaming_done(struct wl_priv *wl, struct net_device *ndev,
        wl_get_assoc_ies(wl);
        memcpy(&wl->bssid, &e->addr, ETH_ALEN);
        wl_update_bss_info(wl);
-       cfg80211_roamed(ndev,
+       cfg80211_roamed(ndev, NULL,
                        (u8 *)&wl->bssid,
                        conn_info->req_ie, conn_info->req_ie_len,
                        conn_info->resp_ie, conn_info->resp_ie_len, GFP_KERNEL);
@@ -2663,7 +2663,7 @@ wl_bss_connect_done(struct wl_priv *wl, struct net_device *ndev,
                WL_DBG("Report connect result - connection %s\n",
                       completed ? "succeeded" : "failed");
        } else {
-               cfg80211_roamed(ndev,
+               cfg80211_roamed(ndev, NULL,
                                (u8 *)&wl->bssid,
                                conn_info->req_ie, conn_info->req_ie_len,
                                conn_info->resp_ie, conn_info->resp_ie_len,
index 76378397b763355c059ace7b5fe6bdd09abaf80c..fb466f4c92e00794085a6e628bb66a44b1ecf133 100644 (file)
@@ -695,7 +695,7 @@ void prism2_disconnected(wlandevice_t *wlandev)
 
 void prism2_roamed(wlandevice_t *wlandev)
 {
-       cfg80211_roamed(wlandev->netdev, wlandev->bssid,
+       cfg80211_roamed(wlandev->netdev, NULL, wlandev->bssid,
                NULL, 0, NULL, 0, GFP_KERNEL);
 }
 
index f1281339b6fadc27ab1237e2d0191f666b0ed5ce..f1637f17c37c8b39c353c455c040d63d6e3637ed 100644 (file)
@@ -674,6 +674,7 @@ struct proc_dir_entry *proc_mkdir_mode(const char *name, mode_t mode,
        }
        return ent;
 }
+EXPORT_SYMBOL(proc_mkdir_mode);
 
 struct proc_dir_entry *proc_net_mkdir(struct net *net, const char *name,
                struct proc_dir_entry *parent)
diff --git a/include/linux/rfkill-gpio.h b/include/linux/rfkill-gpio.h
new file mode 100644 (file)
index 0000000..a175d05
--- /dev/null
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2011, NVIDIA Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * 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 Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+
+
+#ifndef __RFKILL_GPIO_H
+#define __RFKILL_GPIO_H
+
+#include <linux/types.h>
+#include <linux/rfkill.h>
+
+/**
+ * struct rfkill_gpio_platform_data - platform data for rfkill gpio device.
+ * for unused gpio's, the expected value is -1.
+ * @name:              name for the gpio rf kill instance
+ * @reset_gpio:                GPIO which is used for reseting rfkill switch
+ * @shutdown_gpio:     GPIO which is used for shutdown of rfkill switch
+ * @power_clk_name:    [optional] name of clk to turn off while blocked
+ */
+
+struct rfkill_gpio_platform_data {
+       char                    *name;
+       int                     reset_gpio;
+       int                     shutdown_gpio;
+       const char              *power_clk_name;
+       enum rfkill_type        type;
+};
+
+#endif /* __RFKILL_GPIO_H */
index bfd6557946beca9f5cf2525cf7931be4a2c51cbe..0589f554788aea2dd5dc28c9a372ee10637e3eb6 100644 (file)
@@ -531,6 +531,7 @@ struct sta_bss_parameters {
  * @tx_retries: cumulative retry counts
  * @tx_failed: number of failed transmissions (retries exceeded, no ACK)
  * @rx_dropped_misc:  Dropped for un-specified reason.
+ * @bss_param: current BSS parameters
  * @generation: generation number for nl80211 dumps.
  *     This number should increase every time the list of stations
  *     changes, i.e. when a station is added or removed, so that
@@ -1537,7 +1538,7 @@ struct cfg80211_ops {
  * @WIPHY_FLAG_IBSS_RSN: The device supports IBSS RSN.
  * @WIPHY_FLAG_MESH_AUTH: The device supports mesh authentication by routing
  *     auth frames to userspace. See @NL80211_MESH_SETUP_USERSPACE_AUTH.
- * @WIPHY_FLAG_SCHED_SCAN: The device supports scheduled scans.
+ * @WIPHY_FLAG_SUPPORTS_SCHED_SCAN: The device supports scheduled scans.
  */
 enum wiphy_flags {
        WIPHY_FLAG_CUSTOM_REGULATORY            = BIT(0),
@@ -2878,6 +2879,7 @@ void cfg80211_connect_result(struct net_device *dev, const u8 *bssid,
  * cfg80211_roamed - notify cfg80211 of roaming
  *
  * @dev: network device
+ * @channel: the channel of the new AP
  * @bssid: the BSSID of the new AP
  * @req_ie: association request IEs (maybe be %NULL)
  * @req_ie_len: association request IEs length
@@ -2888,7 +2890,9 @@ void cfg80211_connect_result(struct net_device *dev, const u8 *bssid,
  * It should be called by the underlying driver whenever it roamed
  * from one AP to another while connected.
  */
-void cfg80211_roamed(struct net_device *dev, const u8 *bssid,
+void cfg80211_roamed(struct net_device *dev,
+                    struct ieee80211_channel *channel,
+                    const u8 *bssid,
                     const u8 *req_ie, size_t req_ie_len,
                     const u8 *resp_ie, size_t resp_ie_len, gfp_t gfp);
 
index 8c7189c3f6ed9b822eece55d1943e6691851307e..e6d6a66a8f715a48d741a2331576fef7ea614ec8 100644 (file)
@@ -538,7 +538,7 @@ struct ieee80211_tx_info {
 };
 
 /**
- * ieee80211_sched_scan_ies - scheduled scan IEs
+ * struct ieee80211_sched_scan_ies - scheduled scan IEs
  *
  * This structure is used to pass the appropriate IEs to be used in scheduled
  * scans for all bands.  It contains both the IEs passed from the userspace
@@ -2278,6 +2278,7 @@ static inline int ieee80211_sta_ps_transition_ni(struct ieee80211_sta *sta,
 
 /**
  * ieee80211_sta_set_tim - set the TIM bit for a sleeping station
+ * @sta: &struct ieee80211_sta pointer for the sleeping station
  *
  * If a driver buffers frames for a powersave station instead of passing
  * them back to mac80211 for retransmission, the station needs to be told
index 7dfbe71dc637334d410eea7e4eef04a6b114b7d8..49d4f869e0bc74cfcd397558b2283440da761c1d 100644 (file)
@@ -384,11 +384,11 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata,
        int i;
        enum nl80211_channel_type orig_ct;
 
+       clear_bit(SDATA_STATE_RUNNING, &sdata->state);
+
        if (local->scan_sdata == sdata)
                ieee80211_scan_cancel(local);
 
-       clear_bit(SDATA_STATE_RUNNING, &sdata->state);
-
        /*
         * Stop TX on this interface first.
         */
index 0d7b08db8e564e07e953b1a501bc97a0e41a6db6..866f269183cf9a1532f317e3b9f52bc437a98213 100644 (file)
@@ -752,11 +752,25 @@ int ieee80211_register_hw(struct ieee80211_hw *hw)
        hw->wiphy->interface_modes |= BIT(NL80211_IFTYPE_MONITOR);
        hw->wiphy->software_iftypes |= BIT(NL80211_IFTYPE_MONITOR);
 
-       /* mac80211 doesn't support more than 1 channel */
-       for (i = 0; i < hw->wiphy->n_iface_combinations; i++)
-               if (hw->wiphy->iface_combinations[i].num_different_channels > 1)
+       /*
+        * mac80211 doesn't support more than 1 channel, and also not more
+        * than one IBSS interface
+        */
+       for (i = 0; i < hw->wiphy->n_iface_combinations; i++) {
+               const struct ieee80211_iface_combination *c;
+               int j;
+
+               c = &hw->wiphy->iface_combinations[i];
+
+               if (c->num_different_channels > 1)
                        return -EINVAL;
 
+               for (j = 0; j < c->n_limits; j++)
+                       if ((c->limits[j].types & BIT(NL80211_IFTYPE_ADHOC)) &&
+                           c->limits[j].max > 1)
+                               return -EINVAL;
+       }
+
 #ifndef CONFIG_MAC80211_MESH
        /* mesh depends on Kconfig, but drivers should set it if they want */
        local->hw.wiphy->interface_modes &= ~BIT(NL80211_IFTYPE_MESH_POINT);
@@ -1076,6 +1090,8 @@ static void __exit ieee80211_exit(void)
                ieee80211s_stop();
 
        ieee80211_iface_exit();
+
+       rcu_barrier();
 }
 
 
index e7c5fddb480400a8d61c08b577d093ff32b3b22b..249e733362e7b9bf4d48714800ba7da48273832d 100644 (file)
@@ -120,6 +120,7 @@ struct mesh_path {
  *     buckets
  * @mean_chain_len: maximum average length for the hash buckets' list, if it is
  *     reached, the table will grow
+ * rcu_head: RCU head to free the table
  */
 struct mesh_table {
        /* Number of buckets will be 2^N */
@@ -132,6 +133,8 @@ struct mesh_table {
        int (*copy_node) (struct hlist_node *p, struct mesh_table *newtbl);
        int size_order;
        int mean_chain_len;
+
+       struct rcu_head rcu_head;
 };
 
 /* Recent multicast cache */
@@ -286,10 +289,6 @@ static inline bool mesh_path_sel_is_hwmp(struct ieee80211_sub_if_data *sdata)
        return sdata->u.mesh.mesh_pp_id == IEEE80211_PATH_PROTOCOL_HWMP;
 }
 
-#define for_each_mesh_entry(x, p, node, i) \
-       for (i = 0; i <= x->hash_mask; i++) \
-               hlist_for_each_entry_rcu(node, p, &x->hash_buckets[i], list)
-
 void ieee80211_mesh_notify_scan_completed(struct ieee80211_local *local);
 
 void ieee80211_mesh_quiesce(struct ieee80211_sub_if_data *sdata);
index 83ce48e3191344384939ce669a71b5e266f336bf..0d2faacc3e870c0feee42ad2d854cb1110f32ecc 100644 (file)
@@ -36,8 +36,8 @@ struct mpath_node {
        struct mesh_path *mpath;
 };
 
-static struct mesh_table *mesh_paths;
-static struct mesh_table *mpp_paths; /* Store paths for MPP&MAP */
+static struct mesh_table __rcu *mesh_paths;
+static struct mesh_table __rcu *mpp_paths; /* Store paths for MPP&MAP */
 
 int mesh_paths_generation;
 
@@ -48,17 +48,40 @@ int mesh_paths_generation;
 static DEFINE_RWLOCK(pathtbl_resize_lock);
 
 
+static inline struct mesh_table *resize_dereference_mesh_paths(void)
+{
+       return rcu_dereference_protected(mesh_paths,
+               lockdep_is_held(&pathtbl_resize_lock));
+}
+
+static inline struct mesh_table *resize_dereference_mpp_paths(void)
+{
+       return rcu_dereference_protected(mpp_paths,
+               lockdep_is_held(&pathtbl_resize_lock));
+}
+
+/*
+ * CAREFUL -- "tbl" must not be an expression,
+ * in particular not an rcu_dereference(), since
+ * it's used twice. So it is illegal to do
+ *     for_each_mesh_entry(rcu_dereference(...), ...)
+ */
+#define for_each_mesh_entry(tbl, p, node, i) \
+       for (i = 0; i <= tbl->hash_mask; i++) \
+               hlist_for_each_entry_rcu(node, p, &tbl->hash_buckets[i], list)
+
+
 static struct mesh_table *mesh_table_alloc(int size_order)
 {
        int i;
        struct mesh_table *newtbl;
 
-       newtbl = kmalloc(sizeof(struct mesh_table), GFP_KERNEL);
+       newtbl = kmalloc(sizeof(struct mesh_table), GFP_ATOMIC);
        if (!newtbl)
                return NULL;
 
        newtbl->hash_buckets = kzalloc(sizeof(struct hlist_head) *
-                       (1 << size_order), GFP_KERNEL);
+                       (1 << size_order), GFP_ATOMIC);
 
        if (!newtbl->hash_buckets) {
                kfree(newtbl);
@@ -66,7 +89,7 @@ static struct mesh_table *mesh_table_alloc(int size_order)
        }
 
        newtbl->hashwlock = kmalloc(sizeof(spinlock_t) *
-                       (1 << size_order), GFP_KERNEL);
+                       (1 << size_order), GFP_ATOMIC);
        if (!newtbl->hashwlock) {
                kfree(newtbl->hash_buckets);
                kfree(newtbl);
@@ -258,12 +281,13 @@ struct mesh_path *mpp_path_lookup(u8 *dst, struct ieee80211_sub_if_data *sdata)
  */
 struct mesh_path *mesh_path_lookup_by_idx(int idx, struct ieee80211_sub_if_data *sdata)
 {
+       struct mesh_table *tbl = rcu_dereference(mesh_paths);
        struct mpath_node *node;
        struct hlist_node *p;
        int i;
        int j = 0;
 
-       for_each_mesh_entry(mesh_paths, p, node, i) {
+       for_each_mesh_entry(tbl, p, node, i) {
                if (sdata && node->mpath->sdata != sdata)
                        continue;
                if (j++ == idx) {
@@ -293,6 +317,7 @@ int mesh_path_add(u8 *dst, struct ieee80211_sub_if_data *sdata)
 {
        struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
        struct ieee80211_local *local = sdata->local;
+       struct mesh_table *tbl;
        struct mesh_path *mpath, *new_mpath;
        struct mpath_node *node, *new_node;
        struct hlist_head *bucket;
@@ -332,10 +357,12 @@ int mesh_path_add(u8 *dst, struct ieee80211_sub_if_data *sdata)
        spin_lock_init(&new_mpath->state_lock);
        init_timer(&new_mpath->timer);
 
-       hash_idx = mesh_table_hash(dst, sdata, mesh_paths);
-       bucket = &mesh_paths->hash_buckets[hash_idx];
+       tbl = resize_dereference_mesh_paths();
+
+       hash_idx = mesh_table_hash(dst, sdata, tbl);
+       bucket = &tbl->hash_buckets[hash_idx];
 
-       spin_lock_bh(&mesh_paths->hashwlock[hash_idx]);
+       spin_lock_bh(&tbl->hashwlock[hash_idx]);
 
        err = -EEXIST;
        hlist_for_each_entry(node, n, bucket, list) {
@@ -345,13 +372,13 @@ int mesh_path_add(u8 *dst, struct ieee80211_sub_if_data *sdata)
        }
 
        hlist_add_head_rcu(&new_node->list, bucket);
-       if (atomic_inc_return(&mesh_paths->entries) >=
-               mesh_paths->mean_chain_len * (mesh_paths->hash_mask + 1))
+       if (atomic_inc_return(&tbl->entries) >=
+           tbl->mean_chain_len * (tbl->hash_mask + 1))
                grow = 1;
 
        mesh_paths_generation++;
 
-       spin_unlock_bh(&mesh_paths->hashwlock[hash_idx]);
+       spin_unlock_bh(&tbl->hashwlock[hash_idx]);
        read_unlock_bh(&pathtbl_resize_lock);
        if (grow) {
                set_bit(MESH_WORK_GROW_MPATH_TABLE,  &ifmsh->wrkq_flags);
@@ -360,7 +387,7 @@ int mesh_path_add(u8 *dst, struct ieee80211_sub_if_data *sdata)
        return 0;
 
 err_exists:
-       spin_unlock_bh(&mesh_paths->hashwlock[hash_idx]);
+       spin_unlock_bh(&tbl->hashwlock[hash_idx]);
        read_unlock_bh(&pathtbl_resize_lock);
        kfree(new_node);
 err_node_alloc:
@@ -370,58 +397,59 @@ err_path_alloc:
        return err;
 }
 
+static void mesh_table_free_rcu(struct rcu_head *rcu)
+{
+       struct mesh_table *tbl = container_of(rcu, struct mesh_table, rcu_head);
+
+       mesh_table_free(tbl, false);
+}
+
 void mesh_mpath_table_grow(void)
 {
        struct mesh_table *oldtbl, *newtbl;
 
-       rcu_read_lock();
-       newtbl = mesh_table_alloc(rcu_dereference(mesh_paths)->size_order + 1);
-       if (!newtbl)
-               return;
        write_lock_bh(&pathtbl_resize_lock);
-       oldtbl = mesh_paths;
-       if (mesh_table_grow(mesh_paths, newtbl) < 0) {
-               rcu_read_unlock();
+       oldtbl = resize_dereference_mesh_paths();
+       newtbl = mesh_table_alloc(oldtbl->size_order + 1);
+       if (!newtbl)
+               goto out;
+       if (mesh_table_grow(oldtbl, newtbl) < 0) {
                __mesh_table_free(newtbl);
-               write_unlock_bh(&pathtbl_resize_lock);
-               return;
+               goto out;
        }
-       rcu_read_unlock();
        rcu_assign_pointer(mesh_paths, newtbl);
-       write_unlock_bh(&pathtbl_resize_lock);
 
-       synchronize_rcu();
-       mesh_table_free(oldtbl, false);
+       call_rcu(&oldtbl->rcu_head, mesh_table_free_rcu);
+
+ out:
+       write_unlock_bh(&pathtbl_resize_lock);
 }
 
 void mesh_mpp_table_grow(void)
 {
        struct mesh_table *oldtbl, *newtbl;
 
-       rcu_read_lock();
-       newtbl = mesh_table_alloc(rcu_dereference(mpp_paths)->size_order + 1);
-       if (!newtbl)
-               return;
        write_lock_bh(&pathtbl_resize_lock);
-       oldtbl = mpp_paths;
-       if (mesh_table_grow(mpp_paths, newtbl) < 0) {
-               rcu_read_unlock();
+       oldtbl = resize_dereference_mpp_paths();
+       newtbl = mesh_table_alloc(oldtbl->size_order + 1);
+       if (!newtbl)
+               goto out;
+       if (mesh_table_grow(oldtbl, newtbl) < 0) {
                __mesh_table_free(newtbl);
-               write_unlock_bh(&pathtbl_resize_lock);
-               return;
+               goto out;
        }
-       rcu_read_unlock();
        rcu_assign_pointer(mpp_paths, newtbl);
-       write_unlock_bh(&pathtbl_resize_lock);
+       call_rcu(&oldtbl->rcu_head, mesh_table_free_rcu);
 
-       synchronize_rcu();
-       mesh_table_free(oldtbl, false);
+ out:
+       write_unlock_bh(&pathtbl_resize_lock);
 }
 
 int mpp_path_add(u8 *dst, u8 *mpp, struct ieee80211_sub_if_data *sdata)
 {
        struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
        struct ieee80211_local *local = sdata->local;
+       struct mesh_table *tbl;
        struct mesh_path *mpath, *new_mpath;
        struct mpath_node *node, *new_node;
        struct hlist_head *bucket;
@@ -456,10 +484,12 @@ int mpp_path_add(u8 *dst, u8 *mpp, struct ieee80211_sub_if_data *sdata)
        new_mpath->exp_time = jiffies;
        spin_lock_init(&new_mpath->state_lock);
 
-       hash_idx = mesh_table_hash(dst, sdata, mpp_paths);
-       bucket = &mpp_paths->hash_buckets[hash_idx];
+       tbl = resize_dereference_mpp_paths();
 
-       spin_lock_bh(&mpp_paths->hashwlock[hash_idx]);
+       hash_idx = mesh_table_hash(dst, sdata, tbl);
+       bucket = &tbl->hash_buckets[hash_idx];
+
+       spin_lock_bh(&tbl->hashwlock[hash_idx]);
 
        err = -EEXIST;
        hlist_for_each_entry(node, n, bucket, list) {
@@ -469,11 +499,11 @@ int mpp_path_add(u8 *dst, u8 *mpp, struct ieee80211_sub_if_data *sdata)
        }
 
        hlist_add_head_rcu(&new_node->list, bucket);
-       if (atomic_inc_return(&mpp_paths->entries) >=
-               mpp_paths->mean_chain_len * (mpp_paths->hash_mask + 1))
+       if (atomic_inc_return(&tbl->entries) >=
+           tbl->mean_chain_len * (tbl->hash_mask + 1))
                grow = 1;
 
-       spin_unlock_bh(&mpp_paths->hashwlock[hash_idx]);
+       spin_unlock_bh(&tbl->hashwlock[hash_idx]);
        read_unlock_bh(&pathtbl_resize_lock);
        if (grow) {
                set_bit(MESH_WORK_GROW_MPP_TABLE,  &ifmsh->wrkq_flags);
@@ -482,7 +512,7 @@ int mpp_path_add(u8 *dst, u8 *mpp, struct ieee80211_sub_if_data *sdata)
        return 0;
 
 err_exists:
-       spin_unlock_bh(&mpp_paths->hashwlock[hash_idx]);
+       spin_unlock_bh(&tbl->hashwlock[hash_idx]);
        read_unlock_bh(&pathtbl_resize_lock);
        kfree(new_node);
 err_node_alloc:
@@ -502,6 +532,7 @@ err_path_alloc:
  */
 void mesh_plink_broken(struct sta_info *sta)
 {
+       struct mesh_table *tbl;
        static const u8 bcast[ETH_ALEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
        struct mesh_path *mpath;
        struct mpath_node *node;
@@ -510,10 +541,11 @@ void mesh_plink_broken(struct sta_info *sta)
        int i;
 
        rcu_read_lock();
-       for_each_mesh_entry(mesh_paths, p, node, i) {
+       tbl = rcu_dereference(mesh_paths);
+       for_each_mesh_entry(tbl, p, node, i) {
                mpath = node->mpath;
                spin_lock_bh(&mpath->state_lock);
-               if (mpath->next_hop == sta &&
+               if (rcu_dereference(mpath->next_hop) == sta &&
                    mpath->flags & MESH_PATH_ACTIVE &&
                    !(mpath->flags & MESH_PATH_FIXED)) {
                        mpath->flags &= ~MESH_PATH_ACTIVE;
@@ -542,30 +574,38 @@ void mesh_plink_broken(struct sta_info *sta)
  */
 void mesh_path_flush_by_nexthop(struct sta_info *sta)
 {
+       struct mesh_table *tbl;
        struct mesh_path *mpath;
        struct mpath_node *node;
        struct hlist_node *p;
        int i;
 
-       for_each_mesh_entry(mesh_paths, p, node, i) {
+       rcu_read_lock();
+       tbl = rcu_dereference(mesh_paths);
+       for_each_mesh_entry(tbl, p, node, i) {
                mpath = node->mpath;
-               if (mpath->next_hop == sta)
+               if (rcu_dereference(mpath->next_hop) == sta)
                        mesh_path_del(mpath->dst, mpath->sdata);
        }
+       rcu_read_unlock();
 }
 
 void mesh_path_flush(struct ieee80211_sub_if_data *sdata)
 {
+       struct mesh_table *tbl;
        struct mesh_path *mpath;
        struct mpath_node *node;
        struct hlist_node *p;
        int i;
 
-       for_each_mesh_entry(mesh_paths, p, node, i) {
+       rcu_read_lock();
+       tbl = rcu_dereference(mesh_paths);
+       for_each_mesh_entry(tbl, p, node, i) {
                mpath = node->mpath;
                if (mpath->sdata == sdata)
                        mesh_path_del(mpath->dst, mpath->sdata);
        }
+       rcu_read_unlock();
 }
 
 static void mesh_path_node_reclaim(struct rcu_head *rp)
@@ -589,6 +629,7 @@ static void mesh_path_node_reclaim(struct rcu_head *rp)
  */
 int mesh_path_del(u8 *addr, struct ieee80211_sub_if_data *sdata)
 {
+       struct mesh_table *tbl;
        struct mesh_path *mpath;
        struct mpath_node *node;
        struct hlist_head *bucket;
@@ -597,19 +638,20 @@ int mesh_path_del(u8 *addr, struct ieee80211_sub_if_data *sdata)
        int err = 0;
 
        read_lock_bh(&pathtbl_resize_lock);
-       hash_idx = mesh_table_hash(addr, sdata, mesh_paths);
-       bucket = &mesh_paths->hash_buckets[hash_idx];
+       tbl = resize_dereference_mesh_paths();
+       hash_idx = mesh_table_hash(addr, sdata, tbl);
+       bucket = &tbl->hash_buckets[hash_idx];
 
-       spin_lock_bh(&mesh_paths->hashwlock[hash_idx]);
+       spin_lock_bh(&tbl->hashwlock[hash_idx]);
        hlist_for_each_entry(node, n, bucket, list) {
                mpath = node->mpath;
                if (mpath->sdata == sdata &&
-                               memcmp(addr, mpath->dst, ETH_ALEN) == 0) {
+                   memcmp(addr, mpath->dst, ETH_ALEN) == 0) {
                        spin_lock_bh(&mpath->state_lock);
                        mpath->flags |= MESH_PATH_RESOLVING;
                        hlist_del_rcu(&node->list);
                        call_rcu(&node->rcu, mesh_path_node_reclaim);
-                       atomic_dec(&mesh_paths->entries);
+                       atomic_dec(&tbl->entries);
                        spin_unlock_bh(&mpath->state_lock);
                        goto enddel;
                }
@@ -618,7 +660,7 @@ int mesh_path_del(u8 *addr, struct ieee80211_sub_if_data *sdata)
        err = -ENXIO;
 enddel:
        mesh_paths_generation++;
-       spin_unlock_bh(&mesh_paths->hashwlock[hash_idx]);
+       spin_unlock_bh(&tbl->hashwlock[hash_idx]);
        read_unlock_bh(&pathtbl_resize_lock);
        return err;
 }
@@ -719,8 +761,10 @@ static void mesh_path_node_free(struct hlist_node *p, bool free_leafs)
        struct mpath_node *node = hlist_entry(p, struct mpath_node, list);
        mpath = node->mpath;
        hlist_del_rcu(p);
-       if (free_leafs)
+       if (free_leafs) {
+               del_timer_sync(&mpath->timer);
                kfree(mpath);
+       }
        kfree(node);
 }
 
@@ -745,52 +789,60 @@ static int mesh_path_node_copy(struct hlist_node *p, struct mesh_table *newtbl)
 
 int mesh_pathtbl_init(void)
 {
-       mesh_paths = mesh_table_alloc(INIT_PATHS_SIZE_ORDER);
-       if (!mesh_paths)
+       struct mesh_table *tbl_path, *tbl_mpp;
+
+       tbl_path = mesh_table_alloc(INIT_PATHS_SIZE_ORDER);
+       if (!tbl_path)
                return -ENOMEM;
-       mesh_paths->free_node = &mesh_path_node_free;
-       mesh_paths->copy_node = &mesh_path_node_copy;
-       mesh_paths->mean_chain_len = MEAN_CHAIN_LEN;
+       tbl_path->free_node = &mesh_path_node_free;
+       tbl_path->copy_node = &mesh_path_node_copy;
+       tbl_path->mean_chain_len = MEAN_CHAIN_LEN;
 
-       mpp_paths = mesh_table_alloc(INIT_PATHS_SIZE_ORDER);
-       if (!mpp_paths) {
-               mesh_table_free(mesh_paths, true);
+       tbl_mpp = mesh_table_alloc(INIT_PATHS_SIZE_ORDER);
+       if (!tbl_mpp) {
+               mesh_table_free(tbl_path, true);
                return -ENOMEM;
        }
-       mpp_paths->free_node = &mesh_path_node_free;
-       mpp_paths->copy_node = &mesh_path_node_copy;
-       mpp_paths->mean_chain_len = MEAN_CHAIN_LEN;
+       tbl_mpp->free_node = &mesh_path_node_free;
+       tbl_mpp->copy_node = &mesh_path_node_copy;
+       tbl_mpp->mean_chain_len = MEAN_CHAIN_LEN;
+
+       /* Need no locking since this is during init */
+       RCU_INIT_POINTER(mesh_paths, tbl_path);
+       RCU_INIT_POINTER(mpp_paths, tbl_mpp);
 
        return 0;
 }
 
 void mesh_path_expire(struct ieee80211_sub_if_data *sdata)
 {
+       struct mesh_table *tbl;
        struct mesh_path *mpath;
        struct mpath_node *node;
        struct hlist_node *p;
        int i;
 
-       read_lock_bh(&pathtbl_resize_lock);
-       for_each_mesh_entry(mesh_paths, p, node, i) {
+       rcu_read_lock();
+       tbl = rcu_dereference(mesh_paths);
+       for_each_mesh_entry(tbl, p, node, i) {
                if (node->mpath->sdata != sdata)
                        continue;
                mpath = node->mpath;
                spin_lock_bh(&mpath->state_lock);
                if ((!(mpath->flags & MESH_PATH_RESOLVING)) &&
                    (!(mpath->flags & MESH_PATH_FIXED)) &&
-                       time_after(jiffies,
-                        mpath->exp_time + MESH_PATH_EXPIRE)) {
+                    time_after(jiffies, mpath->exp_time + MESH_PATH_EXPIRE)) {
                        spin_unlock_bh(&mpath->state_lock);
                        mesh_path_del(mpath->dst, mpath->sdata);
                } else
                        spin_unlock_bh(&mpath->state_lock);
        }
-       read_unlock_bh(&pathtbl_resize_lock);
+       rcu_read_unlock();
 }
 
 void mesh_pathtbl_unregister(void)
 {
-       mesh_table_free(mesh_paths, true);
-       mesh_table_free(mpp_paths, true);
+       /* no need for locking during exit path */
+       mesh_table_free(rcu_dereference_raw(mesh_paths), true);
+       mesh_table_free(rcu_dereference_raw(mpp_paths), true);
 }
index d20046b5d8f4953bb4ae4007e927ccee1505985a..27af6723cb5e5496efc606010bf04541806da43e 100644 (file)
@@ -719,6 +719,11 @@ void ieee80211_scan_work(struct work_struct *work)
         * without scheduling a new work
         */
        do {
+               if (!ieee80211_sdata_running(sdata)) {
+                       aborted = true;
+                       goto out_complete;
+               }
+
                switch (local->next_scan_state) {
                case SCAN_DECISION:
                        /* if no more bands/channels left, complete scan */
index 48464ca13b242c45a8825ed57e326affc5026455..78efe895b6636c4a57af6d72f156501e2c778992 100644 (file)
@@ -33,3 +33,12 @@ config RFKILL_REGULATOR
 
           To compile this driver as a module, choose M here: the module will
           be called rfkill-regulator.
+
+config RFKILL_GPIO
+       tristate "GPIO RFKILL driver"
+       depends on RFKILL && GPIOLIB && HAVE_CLK
+       default n
+       help
+         If you say yes here you get support of a generic gpio RFKILL
+         driver. The platform should fill in the appropriate fields in the
+         rfkill_gpio_platform_data structure and pass that to the driver.
index d9a5a58ffd8c8102553f18abdd7729d6d7e4c43c..311768783f4a116843349687c99a3cf65f6c6314 100644 (file)
@@ -6,3 +6,4 @@ rfkill-y                        += core.o
 rfkill-$(CONFIG_RFKILL_INPUT)  += input.o
 obj-$(CONFIG_RFKILL)           += rfkill.o
 obj-$(CONFIG_RFKILL_REGULATOR) += rfkill-regulator.o
+obj-$(CONFIG_RFKILL_GPIO)      += rfkill-gpio.o
diff --git a/net/rfkill/rfkill-gpio.c b/net/rfkill/rfkill-gpio.c
new file mode 100644 (file)
index 0000000..256c5dd
--- /dev/null
@@ -0,0 +1,227 @@
+/*
+ * Copyright (c) 2011, NVIDIA Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * 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 Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+
+#include <linux/gpio.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/rfkill.h>
+#include <linux/platform_device.h>
+#include <linux/clk.h>
+#include <linux/slab.h>
+
+#include <linux/rfkill-gpio.h>
+
+enum rfkill_gpio_clk_state {
+       UNSPECIFIED = 0,
+       PWR_ENABLED,
+       PWR_DISABLED
+};
+
+#define PWR_CLK_SET(_RF, _EN) \
+       ((_RF)->pwr_clk_enabled = (!(_EN) ? PWR_ENABLED : PWR_DISABLED))
+#define PWR_CLK_ENABLED(_RF) ((_RF)->pwr_clk_enabled == PWR_ENABLED)
+#define PWR_CLK_DISABLED(_RF) ((_RF)->pwr_clk_enabled != PWR_ENABLED)
+
+struct rfkill_gpio_data {
+       struct rfkill_gpio_platform_data        *pdata;
+       struct rfkill                           *rfkill_dev;
+       char                                    *reset_name;
+       char                                    *shutdown_name;
+       enum rfkill_gpio_clk_state              pwr_clk_enabled;
+       struct clk                              *pwr_clk;
+};
+
+static int rfkill_gpio_set_power(void *data, bool blocked)
+{
+       struct rfkill_gpio_data *rfkill = data;
+
+       if (blocked) {
+               if (gpio_is_valid(rfkill->pdata->shutdown_gpio))
+                       gpio_direction_output(rfkill->pdata->shutdown_gpio, 0);
+               if (gpio_is_valid(rfkill->pdata->reset_gpio))
+                       gpio_direction_output(rfkill->pdata->reset_gpio, 0);
+               if (rfkill->pwr_clk && PWR_CLK_ENABLED(rfkill))
+                       clk_disable(rfkill->pwr_clk);
+       } else {
+               if (rfkill->pwr_clk && PWR_CLK_DISABLED(rfkill))
+                       clk_enable(rfkill->pwr_clk);
+               if (gpio_is_valid(rfkill->pdata->reset_gpio))
+                       gpio_direction_output(rfkill->pdata->reset_gpio, 1);
+               if (gpio_is_valid(rfkill->pdata->shutdown_gpio))
+                       gpio_direction_output(rfkill->pdata->shutdown_gpio, 1);
+       }
+
+       if (rfkill->pwr_clk)
+               PWR_CLK_SET(rfkill, blocked);
+
+       return 0;
+}
+
+static const struct rfkill_ops rfkill_gpio_ops = {
+       .set_block = rfkill_gpio_set_power,
+};
+
+static int rfkill_gpio_probe(struct platform_device *pdev)
+{
+       struct rfkill_gpio_data *rfkill;
+       struct rfkill_gpio_platform_data *pdata = pdev->dev.platform_data;
+       int ret = 0;
+       int len = 0;
+
+       if (!pdata) {
+               pr_warn("%s: No platform data specified\n", __func__);
+               return -EINVAL;
+       }
+
+       /* make sure at-least one of the GPIO is defined and that
+        * a name is specified for this instance */
+       if (!pdata->name || (!gpio_is_valid(pdata->reset_gpio) &&
+               !gpio_is_valid(pdata->shutdown_gpio))) {
+               pr_warn("%s: invalid platform data\n", __func__);
+               return -EINVAL;
+       }
+
+       rfkill = kzalloc(sizeof(*rfkill), GFP_KERNEL);
+       if (!rfkill)
+               return -ENOMEM;
+
+       rfkill->pdata = pdata;
+
+       len = strlen(pdata->name);
+       rfkill->reset_name = kzalloc(len + 7, GFP_KERNEL);
+       if (!rfkill->reset_name) {
+               ret = -ENOMEM;
+               goto fail_alloc;
+       }
+
+       rfkill->shutdown_name = kzalloc(len + 10, GFP_KERNEL);
+       if (!rfkill->shutdown_name) {
+               ret = -ENOMEM;
+               goto fail_reset_name;
+       }
+
+       snprintf(rfkill->reset_name, len + 6 , "%s_reset", pdata->name);
+       snprintf(rfkill->shutdown_name, len + 9, "%s_shutdown", pdata->name);
+
+       if (pdata->power_clk_name) {
+               rfkill->pwr_clk = clk_get(&pdev->dev, pdata->power_clk_name);
+               if (IS_ERR(rfkill->pwr_clk)) {
+                       pr_warn("%s: can't find pwr_clk.\n", __func__);
+                       goto fail_shutdown_name;
+               }
+       }
+
+       if (gpio_is_valid(pdata->reset_gpio)) {
+               ret = gpio_request(pdata->reset_gpio, rfkill->reset_name);
+               if (ret) {
+                       pr_warn("%s: failed to get reset gpio.\n", __func__);
+                       goto fail_clock;
+               }
+       }
+
+       if (gpio_is_valid(pdata->shutdown_gpio)) {
+               ret = gpio_request(pdata->shutdown_gpio, rfkill->shutdown_name);
+               if (ret) {
+                       pr_warn("%s: failed to get shutdown gpio.\n", __func__);
+                       goto fail_reset;
+               }
+       }
+
+       rfkill->rfkill_dev = rfkill_alloc(pdata->name, &pdev->dev, pdata->type,
+                               &rfkill_gpio_ops, rfkill);
+       if (!rfkill->rfkill_dev)
+               goto fail_shutdown;
+
+       ret = rfkill_register(rfkill->rfkill_dev);
+       if (ret < 0)
+               goto fail_rfkill;
+
+       platform_set_drvdata(pdev, rfkill);
+
+       dev_info(&pdev->dev, "%s device registered.\n", pdata->name);
+
+       return 0;
+
+fail_rfkill:
+       rfkill_destroy(rfkill->rfkill_dev);
+fail_shutdown:
+       if (gpio_is_valid(pdata->shutdown_gpio))
+               gpio_free(pdata->shutdown_gpio);
+fail_reset:
+       if (gpio_is_valid(pdata->reset_gpio))
+               gpio_free(pdata->reset_gpio);
+fail_clock:
+       if (rfkill->pwr_clk)
+               clk_put(rfkill->pwr_clk);
+fail_shutdown_name:
+       kfree(rfkill->shutdown_name);
+fail_reset_name:
+       kfree(rfkill->reset_name);
+fail_alloc:
+       kfree(rfkill);
+
+       return ret;
+}
+
+static int rfkill_gpio_remove(struct platform_device *pdev)
+{
+       struct rfkill_gpio_data *rfkill = platform_get_drvdata(pdev);
+
+       rfkill_unregister(rfkill->rfkill_dev);
+       rfkill_destroy(rfkill->rfkill_dev);
+       if (gpio_is_valid(rfkill->pdata->shutdown_gpio))
+               gpio_free(rfkill->pdata->shutdown_gpio);
+       if (gpio_is_valid(rfkill->pdata->reset_gpio))
+               gpio_free(rfkill->pdata->reset_gpio);
+       if (rfkill->pwr_clk && PWR_CLK_ENABLED(rfkill))
+               clk_disable(rfkill->pwr_clk);
+       if (rfkill->pwr_clk)
+               clk_put(rfkill->pwr_clk);
+       kfree(rfkill->shutdown_name);
+       kfree(rfkill->reset_name);
+       kfree(rfkill);
+
+       return 0;
+}
+
+static struct platform_driver rfkill_gpio_driver = {
+       .probe = rfkill_gpio_probe,
+       .remove = __devexit_p(rfkill_gpio_remove),
+       .driver = {
+                  .name = "rfkill_gpio",
+                  .owner = THIS_MODULE,
+       },
+};
+
+static int __init rfkill_gpio_init(void)
+{
+       return platform_driver_register(&rfkill_gpio_driver);
+}
+
+static void __exit rfkill_gpio_exit(void)
+{
+       platform_driver_unregister(&rfkill_gpio_driver);
+}
+
+module_init(rfkill_gpio_init);
+module_exit(rfkill_gpio_exit);
+
+MODULE_DESCRIPTION("gpio rfkill");
+MODULE_AUTHOR("NVIDIA");
+MODULE_LICENSE("GPL");
index bf0fb40e3c8ba2eeac28292128e16e29fb4a7ff5..3dce1f167eba338a6a3c92d0c584636936600420 100644 (file)
@@ -245,6 +245,7 @@ struct cfg80211_event {
                        u16 status;
                } cr;
                struct {
+                       struct ieee80211_channel *channel;
                        u8 bssid[ETH_ALEN];
                        const u8 *req_ie;
                        const u8 *resp_ie;
@@ -392,7 +393,9 @@ int __cfg80211_disconnect(struct cfg80211_registered_device *rdev,
 int cfg80211_disconnect(struct cfg80211_registered_device *rdev,
                        struct net_device *dev, u16 reason,
                        bool wextev);
-void __cfg80211_roamed(struct wireless_dev *wdev, const u8 *bssid,
+void __cfg80211_roamed(struct wireless_dev *wdev,
+                      struct ieee80211_channel *channel,
+                      const u8 *bssid,
                       const u8 *req_ie, size_t req_ie_len,
                       const u8 *resp_ie, size_t resp_ie_len);
 int cfg80211_mgd_wext_connect(struct cfg80211_registered_device *rdev,
index 2222ce08ee91ea8d82e8c8222451c4af1bb4c5ef..ec83f413a7ed19d41b3a37a0a7e0b1d7b1ce9988 100644 (file)
@@ -3294,8 +3294,6 @@ static int nl80211_trigger_scan(struct sk_buff *skb, struct genl_info *info)
        struct cfg80211_registered_device *rdev = info->user_ptr[0];
        struct net_device *dev = info->user_ptr[1];
        struct cfg80211_scan_request *request;
-       struct cfg80211_ssid *ssid;
-       struct ieee80211_channel *channel;
        struct nlattr *attr;
        struct wiphy *wiphy;
        int err, tmp, n_ssids = 0, n_channels, i;
@@ -3342,8 +3340,8 @@ static int nl80211_trigger_scan(struct sk_buff *skb, struct genl_info *info)
                return -EINVAL;
 
        request = kzalloc(sizeof(*request)
-                       + sizeof(*ssid) * n_ssids
-                       + sizeof(channel) * n_channels
+                       + sizeof(*request->ssids) * n_ssids
+                       + sizeof(*request->channels) * n_channels
                        + ie_len, GFP_KERNEL);
        if (!request)
                return -ENOMEM;
@@ -3449,8 +3447,6 @@ static int nl80211_start_sched_scan(struct sk_buff *skb,
        struct cfg80211_sched_scan_request *request;
        struct cfg80211_registered_device *rdev = info->user_ptr[0];
        struct net_device *dev = info->user_ptr[1];
-       struct cfg80211_ssid *ssid;
-       struct ieee80211_channel *channel;
        struct nlattr *attr;
        struct wiphy *wiphy;
        int err, tmp, n_ssids = 0, n_channels, i;
@@ -3507,8 +3503,8 @@ static int nl80211_start_sched_scan(struct sk_buff *skb,
                return -EINVAL;
 
        request = kzalloc(sizeof(*request)
-                       + sizeof(*ssid) * n_ssids
-                       + sizeof(channel) * n_channels
+                       + sizeof(*request->ssids) * n_ssids
+                       + sizeof(*request->channels) * n_channels
                        + ie_len, GFP_KERNEL);
        if (!request)
                return -ENOMEM;
index e17b0bee6bdc7b8e0b6d74a401ea9df3bdf7e977..b7b6ff8be553a10f7a0191ac04f09eeaff06463c 100644 (file)
@@ -250,7 +250,8 @@ static struct cfg80211_bss *cfg80211_get_conn_bss(struct wireless_dev *wdev)
        if (wdev->conn->params.privacy)
                capa |= WLAN_CAPABILITY_PRIVACY;
 
-       bss = cfg80211_get_bss(wdev->wiphy, NULL, wdev->conn->params.bssid,
+       bss = cfg80211_get_bss(wdev->wiphy, wdev->conn->params.channel,
+                              wdev->conn->params.bssid,
                               wdev->conn->params.ssid,
                               wdev->conn->params.ssid_len,
                               WLAN_CAPABILITY_ESS | WLAN_CAPABILITY_PRIVACY,
@@ -470,7 +471,10 @@ void __cfg80211_connect_result(struct net_device *dev, const u8 *bssid,
        }
 
        if (!bss)
-               bss = cfg80211_get_bss(wdev->wiphy, NULL, bssid,
+               bss = cfg80211_get_bss(wdev->wiphy,
+                                      wdev->conn ? wdev->conn->params.channel :
+                                      NULL,
+                                      bssid,
                                       wdev->ssid, wdev->ssid_len,
                                       WLAN_CAPABILITY_ESS,
                                       WLAN_CAPABILITY_ESS);
@@ -538,7 +542,9 @@ void cfg80211_connect_result(struct net_device *dev, const u8 *bssid,
 }
 EXPORT_SYMBOL(cfg80211_connect_result);
 
-void __cfg80211_roamed(struct wireless_dev *wdev, const u8 *bssid,
+void __cfg80211_roamed(struct wireless_dev *wdev,
+                      struct ieee80211_channel *channel,
+                      const u8 *bssid,
                       const u8 *req_ie, size_t req_ie_len,
                       const u8 *resp_ie, size_t resp_ie_len)
 {
@@ -565,7 +571,7 @@ void __cfg80211_roamed(struct wireless_dev *wdev, const u8 *bssid,
        cfg80211_put_bss(&wdev->current_bss->pub);
        wdev->current_bss = NULL;
 
-       bss = cfg80211_get_bss(wdev->wiphy, NULL, bssid,
+       bss = cfg80211_get_bss(wdev->wiphy, channel, bssid,
                               wdev->ssid, wdev->ssid_len,
                               WLAN_CAPABILITY_ESS, WLAN_CAPABILITY_ESS);
 
@@ -603,7 +609,9 @@ void __cfg80211_roamed(struct wireless_dev *wdev, const u8 *bssid,
 #endif
 }
 
-void cfg80211_roamed(struct net_device *dev, const u8 *bssid,
+void cfg80211_roamed(struct net_device *dev,
+                    struct ieee80211_channel *channel,
+                    const u8 *bssid,
                     const u8 *req_ie, size_t req_ie_len,
                     const u8 *resp_ie, size_t resp_ie_len, gfp_t gfp)
 {
@@ -619,6 +627,7 @@ void cfg80211_roamed(struct net_device *dev, const u8 *bssid,
                return;
 
        ev->type = EVENT_ROAMED;
+       ev->rm.channel = channel;
        memcpy(ev->rm.bssid, bssid, ETH_ALEN);
        ev->rm.req_ie = ((u8 *)ev) + sizeof(*ev);
        ev->rm.req_ie_len = req_ie_len;
index f0536d44d43c18e11b54b8f060f8e1b5da42709d..4d7b83fbc32f0eb042e3a70e23d01d626a5add04 100644 (file)
@@ -746,7 +746,7 @@ static void cfg80211_process_wdev_events(struct wireless_dev *wdev)
                                NULL);
                        break;
                case EVENT_ROAMED:
-                       __cfg80211_roamed(wdev, ev->rm.bssid,
+                       __cfg80211_roamed(wdev, ev->rm.channel, ev->rm.bssid,
                                          ev->rm.req_ie, ev->rm.req_ie_len,
                                          ev->rm.resp_ie, ev->rm.resp_ie_len);
                        break;